diff --git a/.github/workflows/phpunit_on_pull_request.yml b/.github/workflows/phpunit_on_pull_request.yml index fcca5610..e2670d3a 100644 --- a/.github/workflows/phpunit_on_pull_request.yml +++ b/.github/workflows/phpunit_on_pull_request.yml @@ -48,9 +48,13 @@ jobs: if: steps.check_files.outputs.files_exists == 'true' run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + - name: Update composer packages + if: steps.check_files.outputs.files_exists == 'true' + run: composer update + - name: Run PHPUnit if: steps.check_files.outputs.files_exists == 'true' - run: composer update && composer tests:unit + run: vendor/bin/phpunit tests/php/Unit/ --verbose - name: Archive code coverage results uses: actions/upload-artifact@v2 diff --git a/.gitignore b/.gitignore index 19b7c6ec..0e617167 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ node_modules/ .DS_Store .phpunit.result.cache + +# Configs +/phpcs.xml diff --git a/composer.json b/composer.json index 720659d7..daa43523 100644 --- a/composer.json +++ b/composer.json @@ -1,67 +1,54 @@ { - "name": "rtcamp/login-with-google", - "description": "WordPress plugin to let users login with google.", - "license": "GPL 2.0", - "authors": [ - { - "name": "rtCamp", - "email": "contact@rtcamp.com", - "homepage": "https://rtcamp.com/", - "role": "Developer" - }, - { - "name": "Utkarsh Patel", - "email": "itismeutkarsh@gmail.com" - }, - { - "name": "Paul Clark", - "role": "Developer" - }, - { - "name": "Ankit Gade", - "email": "ankit.gade@rtcamp.com", - "homepage": "https://iamank.it/", - "role": "Developer" - } - ], - "minimum-stability": "dev", - "prefer-stable": true, - "require": { - "php": ">=7.1", - "pimple/pimple": "3.3.*" - }, - "require-dev": { - "squizlabs/php_codesniffer": "^3.7.1", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.2", - "wp-coding-standards/wpcs": "^2.3", - "sirbrillig/phpcs-variable-analysis": "^v2.11.3", - "automattic/vipwpcs": "^2.3.3", - "phpcompatibility/phpcompatibility-wp": "^2.1.3", - "phpunit/phpunit": "9.5", - "10up/wp_mock": "0.4.2" - }, - "config": { - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true - } - }, - "autoload": { - "psr-4": { - "RtCamp\\GoogleLogin\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "RtCamp\\GoogleLogin\\Tests\\": "tests/php" - } - }, - "scripts": { - "cs": "@php ./vendor/bin/phpcs", - "cs:fix": "@php ./vendor/bin/phpcbf", - "tests:unit": "@php ./vendor/bin/phpunit tests/php/Unit/", - "qa": [ - "@cs", - "@tests" - ] - } + "name": "rtcamp/login-with-google", + "description": "WordPress plugin to let users login with google.", + "license": "GPL-2.0-or-later", + "type": "wordpress-plugin", + "homepage": "https://github.com/rtCamp/login-with-google", + "require": { + "php": ">=7.1", + "pimple/pimple": "3.3.*" + }, + "require-dev": { + "10up/wp_mock": "^0.4.2", + "automattic/vipwpcs": "^2.3", + "civicrm/composer-downloads-plugin": "^3.0", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.2", + "php-stubs/wordpress-stubs": "^6.0", + "phpcompatibility/phpcompatibility-wp": "^2.1", + "phpunit/phpunit": "^9.5", + "roave/security-advisories": "dev-latest", + "sirbrillig/phpcs-variable-analysis": "^2.11", + "wp-coding-standards/wpcs": "^2.3" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "autoload": { + "psr-4": { + "RtCamp\\GoogleLogin\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "RtCamp\\GoogleLogin\\Tests\\": "tests/php" + } + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "civicrm/composer-downloads-plugin": true + }, + "sort-packages": true + }, + "extra": { + "downloads": { + "phpstan": { + "path": "vendor/bin/phpstan", + "type": "phar", + "url": "https://github.com/phpstan/phpstan/releases/latest/download/phpstan.phar" + } + } + }, + "scripts": { + "analyze": "if [ -z $TEST_SKIP_PHPSTAN ]; then phpstan --version; phpstan analyze --ansi --memory-limit=2G; fi" + } } diff --git a/composer.lock b/composer.lock index 26277ea8..46d54de2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d2829135489b5b1e667b36f82f5acec2", + "content-hash": "c02cee376d9004646594ecd17e2bb462", "packages": [ { "name": "pimple/pimple", @@ -54,6 +54,9 @@ "container", "dependency injection" ], + "support": { + "source": "https://github.com/silexphp/Pimple/tree/v3.3.1" + }, "time": "2020-11-24T20:35:42+00:00" }, { @@ -98,6 +101,10 @@ "container-interop", "psr" ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, "time": "2021-11-05T16:50:12+00:00" } ], @@ -141,6 +148,10 @@ "GPL-2.0-or-later" ], "description": "A mocking library to take the pain out of unit testing for WordPress", + "support": { + "issues": "https://github.com/10up/wp_mock/issues", + "source": "https://github.com/10up/wp_mock/tree/master" + }, "time": "2019-03-16T03:44:39+00:00" }, { @@ -185,6 +196,10 @@ "runkit", "testing" ], + "support": { + "issues": "https://github.com/antecedent/patchwork/issues", + "source": "https://github.com/antecedent/patchwork/tree/2.1.21" + }, "time": "2022-02-07T07:28:34+00:00" }, { @@ -232,8 +247,67 @@ "standards", "wordpress" ], + "support": { + "issues": "https://github.com/Automattic/VIP-Coding-Standards/issues", + "source": "https://github.com/Automattic/VIP-Coding-Standards", + "wiki": "https://github.com/Automattic/VIP-Coding-Standards/wiki" + }, "time": "2021-09-29T16:20:23+00:00" }, + { + "name": "civicrm/composer-downloads-plugin", + "version": "v3.0.1", + "source": { + "type": "git", + "url": "https://github.com/civicrm/composer-downloads-plugin.git", + "reference": "3aabb6d259a86158d01829fc2c62a2afb9618877" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/civicrm/composer-downloads-plugin/zipball/3aabb6d259a86158d01829fc2c62a2afb9618877", + "reference": "3aabb6d259a86158d01829fc2c62a2afb9618877", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1 || ^2.0", + "php": ">=5.6", + "togos/gitignore": "~1.1.1" + }, + "require-dev": { + "composer/composer": "~1.0 || ~2.0", + "friendsofphp/php-cs-fixer": "^2.3", + "phpunit/phpunit": "^5.7", + "totten/process-helper": "^1.0.1" + }, + "type": "composer-plugin", + "extra": { + "class": "LastCall\\DownloadsPlugin\\Plugin" + }, + "autoload": { + "psr-4": { + "LastCall\\DownloadsPlugin\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rob Bayliss", + "email": "rob@lastcallmedia.com" + }, + { + "name": "Tim Otten", + "email": "totten@civicrm.org" + } + ], + "description": "Composer plugin for downloading additional files within any composer package.", + "support": { + "source": "https://github.com/civicrm/composer-downloads-plugin/tree/v3.0.1" + }, + "time": "2020-11-02T05:26:23+00:00" + }, { "name": "dealerdirect/phpcodesniffer-composer-installer", "version": "v0.7.2", @@ -303,34 +377,38 @@ "stylecheck", "tests" ], + "support": { + "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", + "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" + }, "time": "2022-02-04T12:51:07+00:00" }, { "name": "doctrine/instantiator", - "version": "1.4.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9", + "doctrine/coding-standard": "^9 || ^11", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^0.16 || ^1", "phpstan/phpstan": "^1.4", "phpstan/phpstan-phpunit": "^1", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.22" + "vimeo/psalm": "^4.30 || ^5.4" }, "type": "library", "autoload": { @@ -355,6 +433,10 @@ "constructor", "instantiate" ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -369,7 +451,7 @@ "type": "tidelift" } ], - "time": "2022-03-03T08:28:38+00:00" + "time": "2022-12-30T00:15:36+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -416,20 +498,24 @@ "keywords": [ "test" ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + }, "time": "2020-07-09T08:09:16+00:00" }, { "name": "mockery/mockery", - "version": "1.5.0", + "version": "1.5.1", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "c10a5f6e06fc2470ab1822fa13fa2a7380f8fbac" + "reference": "e92dcc83d5a51851baf5f5591d32cb2b16e3684e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/c10a5f6e06fc2470ab1822fa13fa2a7380f8fbac", - "reference": "c10a5f6e06fc2470ab1822fa13fa2a7380f8fbac", + "url": "https://api.github.com/repos/mockery/mockery/zipball/e92dcc83d5a51851baf5f5591d32cb2b16e3684e", + "reference": "e92dcc83d5a51851baf5f5591d32cb2b16e3684e", "shasum": "" }, "require": { @@ -484,7 +570,11 @@ "test double", "testing" ], - "time": "2022-01-20T13:18:17+00:00" + "support": { + "issues": "https://github.com/mockery/mockery/issues", + "source": "https://github.com/mockery/mockery/tree/1.5.1" + }, + "time": "2022-09-07T15:32:08+00:00" }, { "name": "myclabs/deep-copy", @@ -533,6 +623,10 @@ "object", "object graph" ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + }, "funding": [ { "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", @@ -543,16 +637,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.14.0", + "version": "v4.15.3", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1" + "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/570e980a201d8ed0236b0a62ddf2c9cbb2034039", + "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039", "shasum": "" }, "require": { @@ -591,7 +685,11 @@ "parser", "php" ], - "time": "2022-05-31T20:59:12+00:00" + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.3" + }, + "time": "2023-01-16T22:05:37+00:00" }, { "name": "phar-io/manifest", @@ -647,6 +745,10 @@ } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, "time": "2021-07-20T11:28:43+00:00" }, { @@ -694,8 +796,56 @@ } ], "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "php-stubs/wordpress-stubs", + "version": "v6.1.1", + "source": { + "type": "git", + "url": "https://github.com/php-stubs/wordpress-stubs.git", + "reference": "601c429ba8d91ef50a2a1bec05a7cd38b88064ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/601c429ba8d91ef50a2a1bec05a7cd38b88064ff", + "reference": "601c429ba8d91ef50a2a1bec05a7cd38b88064ff", + "shasum": "" + }, + "require-dev": { + "nikic/php-parser": "< 4.12.0", + "php": "~7.3 || ~8.0", + "php-stubs/generator": "^0.8.3", + "phpdocumentor/reflection-docblock": "^5.3", + "phpstan/phpstan": "^1.2" + }, + "suggest": { + "paragonie/sodium_compat": "Pure PHP implementation of libsodium", + "symfony/polyfill-php73": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "WordPress function and class declaration stubs for static analysis.", + "homepage": "https://github.com/php-stubs/wordpress-stubs", + "keywords": [ + "PHPStan", + "static analysis", + "wordpress" + ], + "support": { + "issues": "https://github.com/php-stubs/wordpress-stubs/issues", + "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.1.1" + }, + "time": "2023-02-09T11:10:35+00:00" + }, { "name": "phpcompatibility/php-compatibility", "version": "9.3.5", @@ -752,20 +902,24 @@ "phpcs", "standards" ], + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", + "source": "https://github.com/PHPCompatibility/PHPCompatibility" + }, "time": "2019-12-27T09:44:58+00:00" }, { "name": "phpcompatibility/phpcompatibility-paragonie", - "version": "1.3.1", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", - "reference": "ddabec839cc003651f2ce695c938686d1086cf43" + "reference": "bba5a9dfec7fcfbd679cfaf611d86b4d3759da26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/ddabec839cc003651f2ce695c938686d1086cf43", - "reference": "ddabec839cc003651f2ce695c938686d1086cf43", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/bba5a9dfec7fcfbd679cfaf611d86b4d3759da26", + "reference": "bba5a9dfec7fcfbd679cfaf611d86b4d3759da26", "shasum": "" }, "require": { @@ -802,22 +956,27 @@ "paragonie", "phpcs", "polyfill", - "standards" + "standards", + "static analysis" ], - "time": "2021-02-15T10:24:51+00:00" + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" + }, + "time": "2022-10-25T01:46:02+00:00" }, { "name": "phpcompatibility/phpcompatibility-wp", - "version": "2.1.3", + "version": "2.1.4", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", - "reference": "d55de55f88697b9cdb94bccf04f14eb3b11cf308" + "reference": "b6c1e3ee1c35de6c41a511d5eb9bd03e447480a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/d55de55f88697b9cdb94bccf04f14eb3b11cf308", - "reference": "d55de55f88697b9cdb94bccf04f14eb3b11cf308", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/b6c1e3ee1c35de6c41a511d5eb9bd03e447480a5", + "reference": "b6c1e3ee1c35de6c41a511d5eb9bd03e447480a5", "shasum": "" }, "require": { @@ -852,240 +1011,34 @@ "compatibility", "phpcs", "standards", + "static analysis", "wordpress" ], - "time": "2021-12-30T16:37:40+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2021-10-19T17:43:47+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.6.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "77a32518733312af16a44300404e945338981de3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", - "reference": "77a32518733312af16a44300404e945338981de3", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2022-03-15T21:29:03+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "v1.15.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.2", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0 || ^7.0", - "phpunit/phpunit": "^8.0 || ^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2021-12-08T12:19:24+00:00" + "time": "2022-10-24T09:00:36+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.15", + "version": "9.2.24", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f" + "reference": "2cf940ebc6355a9d430462811b5aaa308b174bed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f", - "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2cf940ebc6355a9d430462811b5aaa308b174bed", + "reference": "2cf940ebc6355a9d430462811b5aaa308b174bed", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.13.0", + "nikic/php-parser": "^4.14", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -1132,13 +1085,17 @@ "testing", "xunit" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.24" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2022-03-07T09:28:20+00:00" + "time": "2023-01-26T08:26:55+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1188,6 +1145,10 @@ "filesystem", "iterator" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1247,6 +1208,10 @@ "keywords": [ "process" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1302,6 +1267,10 @@ "keywords": [ "template" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1357,6 +1326,10 @@ "keywords": [ "timer" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1367,20 +1340,20 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.0", + "version": "9.6.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "8e16c225d57c3d6808014df6b1dd7598d0a5bbbe" + "reference": "e7b1615e3e887d6c719121c6d4a44b0ab9645555" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e16c225d57c3d6808014df6b1dd7598d0a5bbbe", - "reference": "8e16c225d57c3d6808014df6b1dd7598d0a5bbbe", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e7b1615e3e887d6c719121c6d4a44b0ab9645555", + "reference": "e7b1615e3e887d6c719121c6d4a44b0ab9645555", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", + "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -1388,31 +1361,26 @@ "ext-xml": "*", "ext-xmlwriter": "*", "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.1", + "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2.3", + "phpunit/php-code-coverage": "^9.2.13", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", "phpunit/php-timer": "^5.0.2", "sebastian/cli-parser": "^1.0.1", "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", + "sebastian/comparator": "^4.0.8", "sebastian/diff": "^4.0.3", "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", + "sebastian/exporter": "^4.0.5", "sebastian/global-state": "^5.0.1", "sebastian/object-enumerator": "^4.0.3", "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^2.3", + "sebastian/type": "^3.2", "sebastian/version": "^3.0.2" }, - "require-dev": { - "ext-pdo": "*", - "phpspec/prophecy-phpunit": "^2.0.1" - }, "suggest": { "ext-soap": "*", "ext-xdebug": "*" @@ -1423,7 +1391,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.5-dev" + "dev-master": "9.6-dev" } }, "autoload": { @@ -1452,17 +1420,602 @@ "testing", "xunit" ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.3" + }, "funding": [ { - "url": "https://phpunit.de/donate.html", + "url": "https://phpunit.de/sponsors.html", "type": "custom" }, { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2023-02-04T13:37:15+00:00" + }, + { + "name": "roave/security-advisories", + "version": "dev-latest", + "source": { + "type": "git", + "url": "https://github.com/Roave/SecurityAdvisories.git", + "reference": "72ca3d8b529b6679ccbefcdc1433fa6aeb7564b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/72ca3d8b529b6679ccbefcdc1433fa6aeb7564b8", + "reference": "72ca3d8b529b6679ccbefcdc1433fa6aeb7564b8", + "shasum": "" + }, + "conflict": { + "3f/pygmentize": "<1.2", + "admidio/admidio": "<4.1.9", + "adodb/adodb-php": "<=5.20.20|>=5.21,<=5.21.3", + "aheinze/cockpit": "<=2.2.1", + "akaunting/akaunting": "<2.1.13", + "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", + "alextselegidis/easyappointments": "<=1.4.3", + "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", + "amazing/media2click": ">=1,<1.3.3", + "amphp/artax": "<1.0.6|>=2,<2.0.6", + "amphp/http": "<1.0.1", + "amphp/http-client": ">=4,<4.4", + "anchorcms/anchor-cms": "<=0.12.7", + "andreapollastri/cipi": "<=3.1.15", + "apereo/phpcas": "<1.6", + "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6", + "appwrite/server-ce": "<0.11.1|>=0.12,<0.12.2", + "arc/web": "<3", + "area17/twill": "<1.2.5|>=2,<2.5.3", + "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", + "automad/automad": "<1.8", + "awesome-support/awesome-support": "<=6.0.7", + "aws/aws-sdk-php": ">=3,<3.2.1", + "backdrop/backdrop": "<=1.23", + "badaso/core": "<2.7", + "bagisto/bagisto": "<0.1.5", + "barrelstrength/sprout-base-email": "<1.2.7", + "barrelstrength/sprout-forms": "<3.9", + "barryvdh/laravel-translation-manager": "<0.6.2", + "barzahlen/barzahlen-php": "<2.0.1", + "baserproject/basercms": "<4.7.2", + "bassjobsen/bootstrap-3-typeahead": ">4.0.2", + "billz/raspap-webgui": "<=2.6.6", + "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", + "bmarshall511/wordpress_zero_spam": "<5.2.13", + "bolt/bolt": "<3.7.2", + "bolt/core": "<=4.2", + "bottelet/flarepoint": "<2.2.1", + "brightlocal/phpwhois": "<=4.2.5", + "brotkrueml/codehighlight": "<2.7", + "brotkrueml/schema": "<1.13.1|>=2,<2.5.1", + "brotkrueml/typo3-matomo-integration": "<1.3.2", + "buddypress/buddypress": "<7.2.1", + "bugsnag/bugsnag-laravel": ">=2,<2.0.2", + "bytefury/crater": "<6.0.2", + "cachethq/cachet": "<2.5.1", + "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10|= 1.3.7|>=4.1,<4.1.4", + "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", + "cardgate/magento2": "<2.0.33", + "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", + "cartalyst/sentry": "<=2.1.6", + "catfan/medoo": "<1.7.5", + "centreon/centreon": "<22.10-beta.1", + "cesnet/simplesamlphp-module-proxystatistics": "<3.1", + "cockpit-hq/cockpit": "<2.3.9", + "codeception/codeception": "<3.1.3|>=4,<4.1.22", + "codeigniter/framework": "<=3.0.6", + "codeigniter4/framework": "<4.2.11", + "codeigniter4/shield": "= 1.0.0-beta", + "codiad/codiad": "<=2.8.4", + "composer/composer": "<1.10.26|>=2-alpha.1,<2.2.12|>=2.3,<2.3.5", + "concrete5/concrete5": "<=9.1.3|>= 9.0.0RC1, < 9.1.3", + "concrete5/core": "<8.5.8|>=9,<9.1", + "contao-components/mediaelement": ">=2.14.2,<2.21.1", + "contao/contao": ">=4,<4.4.56|>=4.5,<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3", + "contao/core": ">=2,<3.5.39", + "contao/core-bundle": "<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3|= 4.10.0", + "contao/listing-bundle": ">=4,<4.4.8", + "contao/managed-edition": "<=1.5", + "craftcms/cms": "<3.7.55.2|>= 4.0.0-RC1, < 4.2.1", + "croogo/croogo": "<3.0.7", + "cuyz/valinor": "<0.12", + "czproject/git-php": "<4.0.3", + "darylldoyle/safe-svg": "<1.9.10", + "datadog/dd-trace": ">=0.30,<0.30.2", + "david-garcia/phpwhois": "<=4.3.1", + "dbrisinajumi/d2files": "<1", + "derhansen/fe_change_pwd": "<2.0.5|>=3,<3.0.3", + "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1", + "directmailteam/direct-mail": "<5.2.4", + "doctrine/annotations": ">=1,<1.2.7", + "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", + "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1", + "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2|>=3,<3.1.4", + "doctrine/doctrine-bundle": "<1.5.2", + "doctrine/doctrine-module": "<=0.7.1", + "doctrine/mongodb-odm": ">=1,<1.0.2", + "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", + "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", + "dolibarr/dolibarr": "<16|>=16.0.1,<16.0.3|= 12.0.5|>= 3.3.beta1, < 13.0.2", + "dompdf/dompdf": "<2.0.2|= 2.0.2", + "drupal/core": ">=7,<7.91|>=8,<9.3.19|>=9.4,<9.4.3", + "drupal/drupal": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4", + "dweeves/magmi": "<=0.7.24", + "ecodev/newsletter": "<=4", + "ectouch/ectouch": "<=2.7.2", + "elefant/cms": "<1.3.13", + "elgg/elgg": "<3.3.24|>=4,<4.0.5", + "endroid/qr-code-bundle": "<3.4.2", + "enshrined/svg-sanitize": "<0.15", + "erusev/parsedown": "<1.7.2", + "ether/logs": "<3.0.4", + "exceedone/exment": "<4.4.3|>=5,<5.0.3", + "exceedone/laravel-admin": "= 3.0.0|<2.2.3", + "ezsystems/demobundle": ">=5.4,<5.4.6.1", + "ezsystems/ez-support-tools": ">=2.2,<2.2.3", + "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1", + "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1|>=5.4,<5.4.11.1|>=2017.12,<2017.12.0.1", + "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", + "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.29|>=2.3,<2.3.26", + "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1", + "ezsystems/ezplatform-graphql": ">=1-rc.1,<1.0.13|>=2-beta.1,<2.3.12", + "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<1.3.26", + "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", + "ezsystems/ezplatform-richtext": ">=2.3,<=2.3.7", + "ezsystems/ezplatform-user": ">=1,<1.0.1", + "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<7.5.30", + "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.3.5.1", + "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", + "ezsystems/repository-forms": ">=2.3,<2.3.2.1|>=2.5,<2.5.15", + "ezyang/htmlpurifier": "<4.1.1", + "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", + "facturascripts/facturascripts": "<=2022.8", + "feehi/cms": "<=2.1.1", + "feehi/feehicms": "<=2.1.1", + "fenom/fenom": "<=2.12.1", + "filegator/filegator": "<7.8", + "firebase/php-jwt": "<2", + "fixpunkt/fp-masterquiz": "<2.2.1|>=3,<3.5.2", + "fixpunkt/fp-newsletter": "<1.1.1|>=2,<2.1.2|>=2.2,<3.2.6", + "flarum/core": "<1.6.3", + "flarum/mentions": "<1.6.3", + "flarum/sticky": ">=0.1-beta.14,<=0.1-beta.15", + "flarum/tags": "<=0.1-beta.13", + "fluidtypo3/vhs": "<5.1.1", + "fof/byobu": ">=0.3-beta.2,<1.1.7", + "fof/upload": "<1.2.3", + "fooman/tcpdf": "<6.2.22", + "forkcms/forkcms": "<5.11.1", + "fossar/tcpdf-parser": "<6.2.22", + "francoisjacquet/rosariosis": "<10.1", + "friendsofsymfony/oauth2-php": "<1.3", + "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", + "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", + "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", + "froala/wysiwyg-editor": "<3.2.7", + "froxlor/froxlor": "<2.0.10", + "fuel/core": "<1.8.1", + "gaoming13/wechat-php-sdk": "<=1.10.2", + "genix/cms": "<=1.1.11", + "getgrav/grav": "<1.7.34", + "getkirby/cms": "= 3.8.0|<3.5.8.2|>=3.6,<3.6.6.2|>=3.7,<3.7.5.1", + "getkirby/panel": "<2.5.14", + "getkirby/starterkit": "<=3.7.0.2", + "gilacms/gila": "<=1.11.4", + "globalpayments/php-sdk": "<2", + "google/protobuf": "<3.15", + "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", + "gree/jose": "<=2.2", + "gregwar/rst": "<1.0.3", + "grumpydictator/firefly-iii": "<5.8", + "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", + "guzzlehttp/psr7": "<1.8.4|>=2,<2.1.1", + "harvesthq/chosen": "<1.8.7", + "helloxz/imgurl": "= 2.31|<=2.31", + "hillelcoren/invoice-ninja": "<5.3.35", + "himiklab/yii2-jqgrid-widget": "<1.0.8", + "hjue/justwriting": "<=1", + "hov/jobfair": "<1.0.13|>=2,<2.0.2", + "hyn/multi-tenant": ">=5.6,<5.7.2", + "ibexa/admin-ui": ">=4.2,<4.2.3", + "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4|>=4.2,<4.2.3", + "ibexa/graphql": ">=2.5,<2.5.31|>=3.3,<3.3.28|>=4.2,<4.2.3", + "ibexa/post-install": "<=1.0.4", + "icecoder/icecoder": "<=8.1", + "idno/known": "<=1.3.1", + "illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10", + "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.99999|>=4.2,<=4.2.99999|>=5,<=5.0.99999|>=5.1,<=5.1.99999|>=5.2,<=5.2.99999|>=5.3,<=5.3.99999|>=5.4,<=5.4.99999|>=5.5,<=5.5.49|>=5.6,<=5.6.99999|>=5.7,<=5.7.99999|>=5.8,<=5.8.99999|>=6,<6.18.31|>=7,<7.22.4", + "illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40", + "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", + "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", + "impresscms/impresscms": "<=1.4.3", + "in2code/femanager": "<5.5.3|>=6,<6.3.4|>=7,<7.1", + "in2code/lux": "<17.6.1|>=18,<24.0.2", + "innologi/typo3-appointments": "<2.0.6", + "intelliants/subrion": "<=4.2.1", + "islandora/islandora": ">=2,<2.4.1", + "ivankristianto/phpwhois": "<=4.3", + "jackalope/jackalope-doctrine-dbal": "<1.7.4", + "james-heinrich/getid3": "<1.9.21", + "jasig/phpcas": "<1.3.3", + "joomla/archive": "<1.1.12|>=2,<2.0.1", + "joomla/filesystem": "<1.6.2|>=2,<2.0.1", + "joomla/filter": "<1.4.4|>=2,<2.0.1", + "joomla/input": ">=2,<2.0.2", + "joomla/session": "<1.3.1", + "joyqi/hyper-down": "<=2.4.27", + "jsdecena/laracom": "<2.0.9", + "jsmitty12/phpwhois": "<5.1", + "kazist/phpwhois": "<=4.2.6", + "kelvinmo/simplexrd": "<3.1.1", + "kevinpapst/kimai2": "<1.16.7", + "kitodo/presentation": "<3.1.2", + "klaviyo/magento2-extension": ">=1,<3", + "krayin/laravel-crm": "<1.2.2", + "kreait/firebase-php": ">=3.2,<3.8.1", + "la-haute-societe/tcpdf": "<6.2.22", + "laminas/laminas-diactoros": "<2.11.1", + "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", + "laminas/laminas-http": "<2.14.2", + "laravel/fortify": "<1.11.1", + "laravel/framework": "<6.20.42|>=7,<7.30.6|>=8,<8.75", + "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", + "latte/latte": "<2.10.8", + "lavalite/cms": "<=5.8", + "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", + "league/commonmark": "<0.18.3", + "league/flysystem": "<1.1.4|>=2,<2.1.1", + "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", + "librenms/librenms": "<22.10", + "liftkit/database": "<2.13.2", + "limesurvey/limesurvey": "<3.27.19", + "livehelperchat/livehelperchat": "<=3.91", + "livewire/livewire": ">2.2.4,<2.2.6", + "lms/routes": "<2.1.1", + "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2", + "luyadev/yii-helpers": "<1.2.1", + "magento/community-edition": ">=2,<2.2.10|>=2.3,<2.3.3", + "magento/magento1ce": "<1.9.4.3", + "magento/magento1ee": ">=1,<1.14.4.3", + "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2", + "marcwillmann/turn": "<0.3.3", + "matyhtf/framework": "<3.0.6", + "mautic/core": "<4.3|= 2.13.1", + "mediawiki/core": ">=1.27,<1.27.6|>=1.29,<1.29.3|>=1.30,<1.30.2|>=1.31,<1.31.9|>=1.32,<1.32.6|>=1.32.99,<1.33.3|>=1.33.99,<1.34.3|>=1.34.99,<1.35", + "melisplatform/melis-asset-manager": "<5.0.1", + "melisplatform/melis-cms": "<5.0.1", + "melisplatform/melis-front": "<5.0.1", + "mezzio/mezzio-swoole": "<3.7|>=4,<4.3", + "mgallegos/laravel-jqgrid": "<=1.3", + "microweber/microweber": "<1.3.2", + "miniorange/miniorange-saml": "<1.4.3", + "mittwald/typo3_forum": "<1.2.1", + "modx/revolution": "<= 2.8.3-pl|<2.8", + "mojo42/jirafeau": "<4.4", + "monolog/monolog": ">=1.8,<1.12", + "moodle/moodle": "<4.0.5", + "mustache/mustache": ">=2,<2.14.1", + "namshi/jose": "<2.2", + "neoan3-apps/template": "<1.1.1", + "neorazorx/facturascripts": "<2022.4", + "neos/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "neos/form": ">=1.2,<4.3.3|>=5,<5.0.9|>=5.1,<5.1.3", + "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.9.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<5.3.10|>=7,<7.0.9|>=7.1,<7.1.7|>=7.2,<7.2.6|>=7.3,<7.3.4|>=8,<8.0.2", + "neos/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", + "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", + "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", + "nilsteampassnet/teampass": "<=2.1.27.36", + "notrinos/notrinos-erp": "<=0.7", + "noumo/easyii": "<=0.9", + "nukeviet/nukeviet": "<4.5.2", + "nystudio107/craft-seomatic": "<3.4.12", + "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", + "october/backend": "<1.1.2", + "october/cms": "= 1.1.1|= 1.0.471|= 1.0.469|>=1.0.319,<1.0.469", + "october/october": ">=1.0.319,<1.0.466|>=2.1,<2.1.12", + "october/rain": "<1.0.472|>=1.1,<1.1.2", + "october/system": "<1.0.476|>=1.1,<1.1.12|>=2,<2.2.34|>=3,<3.0.66", + "onelogin/php-saml": "<2.10.4", + "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5", + "open-web-analytics/open-web-analytics": "<1.7.4", + "opencart/opencart": "<=3.0.3.7", + "openid/php-openid": "<2.3", + "openmage/magento-lts": "<19.4.22|>=20,<20.0.19", + "orchid/platform": ">=9,<9.4.4", + "oro/commerce": ">=4.1,<5.0.6", + "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", + "oro/platform": ">=1.7,<1.7.4|>=3.1,<3.1.29|>=4.1,<4.1.17|>=4.2,<4.2.8", + "packbackbooks/lti-1-3-php-library": "<5", + "padraic/humbug_get_contents": "<1.1.2", + "pagarme/pagarme-php": ">=0,<3", + "pagekit/pagekit": "<=1.0.18", + "paragonie/random_compat": "<2", + "passbolt/passbolt_api": "<2.11", + "paypal/merchant-sdk-php": "<3.12", + "pear/archive_tar": "<1.4.14", + "pear/crypt_gpg": "<1.6.7", + "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", + "personnummer/personnummer": "<3.0.2", + "phanan/koel": "<5.1.4", + "php-mod/curl": "<2.3.2", + "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", + "phpmailer/phpmailer": "<6.5", + "phpmussel/phpmussel": ">=1,<1.6", + "phpmyadmin/phpmyadmin": "<5.2.1", + "phpmyfaq/phpmyfaq": "<=3.1.7", + "phpoffice/phpexcel": "<1.8", + "phpoffice/phpspreadsheet": "<1.16", + "phpseclib/phpseclib": "<2.0.31|>=3,<3.0.7", + "phpservermon/phpservermon": "<=3.5.2", + "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5,<5.6.3", + "phpwhois/phpwhois": "<=4.2.5", + "phpxmlrpc/extras": "<0.6.1", + "phpxmlrpc/phpxmlrpc": "<4.9.2", + "pimcore/data-hub": "<1.2.4", + "pimcore/pimcore": "<10.5.16", + "pocketmine/bedrock-protocol": "<8.0.2", + "pocketmine/pocketmine-mp": "<4.12.5|>= 4.0.0-BETA5, < 4.4.2", + "pressbooks/pressbooks": "<5.18", + "prestashop/autoupgrade": ">=4,<4.10.1", + "prestashop/blockwishlist": ">=2,<2.1.1", + "prestashop/contactform": ">=1.0.1,<4.3", + "prestashop/gamification": "<2.3.2", + "prestashop/prestashop": "<1.7.8.8", + "prestashop/productcomments": "<5.0.2", + "prestashop/ps_emailsubscription": "<2.6.1", + "prestashop/ps_facetedsearch": "<3.4.1", + "prestashop/ps_linklist": "<3.1", + "privatebin/privatebin": "<1.4", + "processwire/processwire": "<=3.0.200", + "propel/propel": ">=2-alpha.1,<=2-alpha.7", + "propel/propel1": ">=1,<=1.7.1", + "pterodactyl/panel": "<1.7", + "ptrofimov/beanstalk_console": "<1.7.14", + "pusher/pusher-php-server": "<2.2.1", + "pwweb/laravel-core": "<=0.3.6-beta", + "pyrocms/pyrocms": "<=3.9.1", + "rainlab/debugbar-plugin": "<3.1", + "rankmath/seo-by-rank-math": "<=1.0.95", + "react/http": ">=0.7,<1.7", + "remdex/livehelperchat": "<3.99", + "rmccue/requests": ">=1.6,<1.8", + "robrichards/xmlseclibs": "<3.0.4", + "roots/soil": "<4.1", + "rudloff/alltube": "<3.0.3", + "s-cart/core": "<6.9", + "s-cart/s-cart": "<6.9", + "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", + "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", + "scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11", + "sensiolabs/connect": "<4.2.3", + "serluck/phpwhois": "<=4.2.6", + "shopware/core": "<=6.4.18", + "shopware/platform": "<=6.4.18", + "shopware/production": "<=6.3.5.2", + "shopware/shopware": "<=5.7.14", + "shopware/storefront": "<=6.4.8.1", + "shopxo/shopxo": "<2.2.6", + "showdoc/showdoc": "<2.10.4", + "silverstripe/admin": ">=1,<1.11.3", + "silverstripe/assets": ">=1,<1.11.1", + "silverstripe/cms": "<4.11.3", + "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1", + "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", + "silverstripe/framework": "<4.11.14", + "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|= 4.0.0-alpha1", + "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", + "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", + "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4", + "silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1", + "silverstripe/subsites": ">=2,<2.6.1", + "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", + "silverstripe/userforms": "<3", + "silverstripe/versioned-admin": ">=1,<1.11.1", + "simple-updates/phpwhois": "<=1", + "simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4", + "simplesamlphp/simplesamlphp": "<1.18.6", + "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", + "simplesamlphp/simplesamlphp-module-openid": "<1", + "simplesamlphp/simplesamlphp-module-openidprovider": "<0.9", + "simplito/elliptic-php": "<1.0.6", + "slim/slim": "<2.6", + "smarty/smarty": "<3.1.47|>=4,<4.2.1", + "snipe/snipe-it": "<=6.0.14|>= 6.0.0-RC-1, <= 6.0.0-RC-5", + "socalnick/scn-social-auth": "<1.15.2", + "socialiteproviders/steam": "<1.1", + "spatie/browsershot": "<3.57.4", + "spipu/html2pdf": "<5.2.4", + "spoonity/tcpdf": "<6.2.22", + "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", + "ssddanbrown/bookstack": "<22.2.3", + "statamic/cms": "<3.2.39|>=3.3,<3.3.2", + "stormpath/sdk": ">=0,<9.9.99", + "studio-42/elfinder": "<2.1.59", + "subrion/cms": "<=4.2.1", + "sukohi/surpass": "<1", + "sulu/sulu": "= 2.4.0-RC1|<1.6.44|>=2,<2.2.18|>=2.3,<2.3.8", + "sumocoders/framework-user-bundle": "<1.4", + "swag/paypal": "<5.4.4", + "swiftmailer/swiftmailer": ">=4,<5.4.5", + "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", + "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", + "sylius/grid-bundle": "<1.10.1", + "sylius/paypal-plugin": ">=1,<1.2.4|>=1.3,<1.3.1", + "sylius/resource-bundle": "<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", + "sylius/sylius": "<1.9.10|>=1.10,<1.10.11|>=1.11,<1.11.2", + "symbiote/silverstripe-multivaluefield": ">=3,<3.0.99", + "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", + "symbiote/silverstripe-seed": "<6.0.3", + "symbiote/silverstripe-versionedfiles": "<=2.0.3", + "symfont/process": ">=0", + "symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8", + "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", + "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", + "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3|= 6.0.3|= 5.4.3|= 5.3.14", + "symfony/http-foundation": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7", + "symfony/http-kernel": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", + "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", + "symfony/mime": ">=4.3,<4.3.8", + "symfony/phpunit-bridge": ">=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/polyfill": ">=1,<1.10", + "symfony/polyfill-php55": ">=1,<1.10", + "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/routing": ">=2,<2.0.19", + "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8", + "symfony/security-bundle": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", + "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", + "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", + "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", + "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7|>=5.1,<5.2.8|>=5.3,<5.3.2", + "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", + "symfony/symfony": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", + "symfony/translation": ">=2,<2.0.17", + "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3", + "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", + "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", + "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", + "t3/dce": ">=2.2,<2.6.2", + "t3g/svg-sanitizer": "<1.0.3", + "tastyigniter/tastyigniter": "<3.3", + "tecnickcom/tcpdf": "<6.2.22", + "terminal42/contao-tablelookupwizard": "<3.3.5", + "thelia/backoffice-default-template": ">=2.1,<2.1.2", + "thelia/thelia": ">=2.1-beta.1,<2.1.3", + "theonedemon/phpwhois": "<=4.2.5", + "thinkcmf/thinkcmf": "<=5.1.7", + "thorsten/phpmyfaq": "<3.1.11", + "tinymce/tinymce": "<5.10.7|>=6,<6.3.1", + "titon/framework": ">=0,<9.9.99", + "tobiasbg/tablepress": "<= 2.0-RC1", + "topthink/framework": "<6.0.14", + "topthink/think": "<=6.0.9", + "topthink/thinkphp": "<=3.2.3", + "tribalsystems/zenario": "<=9.3.57595", + "truckersmp/phpwhois": "<=4.3.1", + "ttskch/pagination-service-provider": "<1", + "twig/twig": "<1.44.7|>=2,<2.15.3|>=3,<3.4.3", + "typo3/cms": "<2.0.5|>=3,<3.0.3|>=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.35|>=11,<11.5.23|>=12,<12.2", + "typo3/cms-backend": ">=7,<=7.6.50|>=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", + "typo3/cms-core": "<8.7.51|>=9,<9.5.40|>=10,<10.4.36|>=11,<11.5.23|>=12,<12.2", + "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", + "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "typo3/html-sanitizer": ">=1,<1.5|>=2,<2.1.1", + "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", + "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", + "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", + "ua-parser/uap-php": "<3.8", + "unisharp/laravel-filemanager": "<=2.5.1", + "userfrosting/userfrosting": ">=0.3.1,<4.6.3", + "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", + "vanilla/safecurl": "<0.9.2", + "verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4", + "vova07/yii2-fileapi-widget": "<0.1.9", + "vrana/adminer": "<4.8.1", + "wallabag/tcpdf": "<6.2.22", + "wallabag/wallabag": "<2.5.4", + "wanglelecc/laracms": "<=1.0.3", + "web-auth/webauthn-framework": ">=3.3,<3.3.4", + "webcoast/deferred-image-processing": "<1.0.2", + "webpa/webpa": "<3.1.2", + "wikimedia/parsoid": "<0.12.2", + "willdurand/js-translation-bundle": "<2.1.1", + "wintercms/winter": "<1.0.475|>=1.1,<1.1.10|>=1.2,<1.2.1", + "woocommerce/woocommerce": "<6.6", + "wp-cli/wp-cli": "<2.5", + "wp-graphql/wp-graphql": "<0.3.5", + "wpanel/wpanel4-cms": "<=4.3.1", + "wwbn/avideo": "<12.4", + "xataface/xataface": "<3", + "xpressengine/xpressengine": "<3.0.15", + "yeswiki/yeswiki": "<4.1", + "yetiforce/yetiforce-crm": "<=6.4", + "yidashi/yii2cmf": "<=2", + "yii2mod/yii2-cms": "<1.9.2", + "yiisoft/yii": "<1.1.27", + "yiisoft/yii2": "<2.0.38", + "yiisoft/yii2-bootstrap": "<2.0.4", + "yiisoft/yii2-dev": "<2.0.43", + "yiisoft/yii2-elasticsearch": "<2.0.5", + "yiisoft/yii2-gii": "<=2.2.4", + "yiisoft/yii2-jui": "<2.0.4", + "yiisoft/yii2-redis": "<2.0.8", + "yikesinc/yikes-inc-easy-mailchimp-extender": "<6.8.6", + "yoast-seo-for-typo3/yoast_seo": "<7.2.3", + "yourls/yourls": "<=1.8.2", + "zendesk/zendesk_api_client_php": "<2.2.11", + "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", + "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-db": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.10|>=2.3,<2.3.5", + "zendframework/zend-developer-tools": ">=1.2.2,<1.2.3", + "zendframework/zend-diactoros": "<1.8.4", + "zendframework/zend-feed": "<2.10.3", + "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-http": "<2.8.1", + "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", + "zendframework/zend-mail": ">=2,<2.4.11|>=2.5,<2.7.2", + "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-session": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.9|>=2.3,<2.3.4", + "zendframework/zend-validator": ">=2.3,<2.3.6", + "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zendframework": "<=3", + "zendframework/zendframework1": "<1.12.20", + "zendframework/zendopenid": ">=2,<2.0.2", + "zendframework/zendxml": ">=1,<1.0.1", + "zetacomponents/mail": "<1.8.2", + "zf-commons/zfc-user": "<1.2.2", + "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", + "zfr/zfr-oauth2-server-module": "<0.1.2", + "zoujingli/thinkadmin": "<6.0.22" + }, + "default-branch": true, + "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "role": "maintainer" + }, + { + "name": "Ilya Tribusean", + "email": "slash3b@gmail.com", + "role": "maintainer" + } + ], + "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", + "support": { + "issues": "https://github.com/Roave/SecurityAdvisories/issues", + "source": "https://github.com/Roave/SecurityAdvisories/tree/latest" + }, + "funding": [ + { + "url": "https://github.com/Ocramius", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/roave/security-advisories", + "type": "tidelift" } ], - "time": "2020-12-04T05:05:53+00:00" + "time": "2023-02-14T01:32:29+00:00" }, { "name": "sebastian/cli-parser", @@ -1508,6 +2061,10 @@ ], "description": "Library for parsing CLI options", "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1560,6 +2117,10 @@ ], "description": "Collection of value objects that represent the PHP code units", "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1611,6 +2172,10 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1621,16 +2186,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { @@ -1681,13 +2246,17 @@ "compare", "equality" ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2020-10-26T15:49:45+00:00" + "time": "2022-09-14T12:41:17+00:00" }, { "name": "sebastian/complexity", @@ -1734,6 +2303,10 @@ ], "description": "Library for calculating the complexity of PHP code units", "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1796,6 +2369,10 @@ "unidiff", "unified diff" ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1806,16 +2383,16 @@ }, { "name": "sebastian/environment", - "version": "5.1.4", + "version": "5.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { @@ -1855,26 +2432,30 @@ "environment", "hhvm" ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2022-04-03T09:37:03+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", "shasum": "" }, "require": { @@ -1928,13 +2509,17 @@ "export", "exporter" ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2021-11-11T14:18:36+00:00" + "time": "2022-09-14T06:03:37+00:00" }, { "name": "sebastian/global-state", @@ -1988,6 +2573,10 @@ "keywords": [ "global state" ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -2041,6 +2630,10 @@ ], "description": "Library for counting the lines of code in PHP source code", "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -2094,6 +2687,10 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -2145,6 +2742,10 @@ ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -2155,16 +2756,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { @@ -2203,14 +2804,18 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2020-10-26T13:17:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", @@ -2255,6 +2860,10 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -2265,28 +2874,28 @@ }, { "name": "sebastian/type", - "version": "2.3.4", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914", - "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -2307,13 +2916,17 @@ ], "description": "Collection of value objects that represent the types of the PHP type system", "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2021-06-15T12:49:02+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", @@ -2356,6 +2969,10 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -2366,28 +2983,29 @@ }, { "name": "sirbrillig/phpcs-variable-analysis", - "version": "v2.11.3", + "version": "v2.11.10", "source": { "type": "git", "url": "https://github.com/sirbrillig/phpcs-variable-analysis.git", - "reference": "c921498b474212fe4552928bbeb68d70250ce5e8" + "reference": "0f25a3766f26df91d6bdda0c8931303fc85499d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/c921498b474212fe4552928bbeb68d70250ce5e8", - "reference": "c921498b474212fe4552928bbeb68d70250ce5e8", + "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/0f25a3766f26df91d6bdda0c8931303fc85499d7", + "reference": "0f25a3766f26df91d6bdda0c8931303fc85499d7", "shasum": "" }, "require": { "php": ">=5.4.0", - "squizlabs/php_codesniffer": "^3.5" + "squizlabs/php_codesniffer": "^3.5.6" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", - "limedeck/phpunit-detailed-printer": "^3.1 || ^4.0 || ^5.0", - "phpstan/phpstan": "^0.11.8", - "phpunit/phpunit": "^5.0 || ^6.5 || ^7.0 || ^8.0", - "sirbrillig/phpcs-import-detection": "^1.1" + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.0", + "phpcsstandards/phpcsdevcs": "^1.1", + "phpstan/phpstan": "^1.7", + "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.5 || ^7.0 || ^8.0 || ^9.0", + "sirbrillig/phpcs-import-detection": "^1.1", + "vimeo/psalm": "^0.2 || ^0.3 || ^1.1 || ^4.24 || ^5.0@beta" }, "type": "phpcodesniffer-standard", "autoload": { @@ -2410,7 +3028,16 @@ } ], "description": "A PHPCS sniff to detect problems with variables.", - "time": "2022-02-21T17:01:13+00:00" + "keywords": [ + "phpcs", + "static analysis" + ], + "support": { + "issues": "https://github.com/sirbrillig/phpcs-variable-analysis/issues", + "source": "https://github.com/sirbrillig/phpcs-variable-analysis", + "wiki": "https://github.com/sirbrillig/phpcs-variable-analysis/wiki" + }, + "time": "2023-01-05T18:45:16+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -2461,6 +3088,11 @@ "phpcs", "standards" ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, "time": "2022-06-18T07:21:10+00:00" }, { @@ -2501,6 +3133,10 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + }, "funding": [ { "url": "https://github.com/theseer", @@ -2510,58 +3146,41 @@ "time": "2021-07-28T10:34:58+00:00" }, { - "name": "webmozart/assert", - "version": "1.11.0", + "name": "togos/gitignore", + "version": "1.1.1", "source": { "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + "url": "https://github.com/TOGoS/PHPGitIgnore.git", + "reference": "32bc0830e4123f670adcbf5ddda5bef362f4f4d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "url": "https://api.github.com/repos/TOGoS/PHPGitIgnore/zipball/32bc0830e4123f670adcbf5ddda5bef362f4f4d4", + "reference": "32bc0830e4123f670adcbf5ddda5bef362f4f4d4", "shasum": "" }, "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" + "php": ">=5.2" }, "require-dev": { - "phpunit/phpunit": "^8.5.13" + "togos/simpler-test": "1.1.1" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" + "psr-0": { + "TOGoS_GitIgnore_": "src/main/php/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "time": "2022-06-03T18:03:27+00:00" + "description": "Parser for .gitignore (and sparse-checkout, and anything else using the same format) files", + "support": { + "issues": "https://github.com/TOGoS/PHPGitIgnore/issues", + "source": "https://github.com/TOGoS/PHPGitIgnore/tree/master" + }, + "time": "2019-04-19T19:16:58+00:00" }, { "name": "wp-coding-standards/wpcs", @@ -2607,17 +3226,24 @@ "standards", "wordpress" ], + "support": { + "issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues", + "source": "https://github.com/WordPress/WordPress-Coding-Standards", + "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki" + }, "time": "2020-05-13T23:57:56+00:00" } ], "aliases": [], "minimum-stability": "dev", - "stability-flags": [], + "stability-flags": { + "roave/security-advisories": 20 + }, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": ">=7.1" }, "platform-dev": [], - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.2.0" } diff --git a/phpcs.xml b/phpcs.xml deleted file mode 100644 index 9fea8e34..00000000 --- a/phpcs.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - src - login-with-google.php - - - - - - - - - - - - - - - tests/* - - - - - - - - - - tests/* - - - - - - - - - - - - - - - - - - - - */vendor/* - */node_modules/* - /lib/* - */tests/* - */.github/* - */.scripts/* - diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 00000000..5e50ca69 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + tests/* + + + + + + + + + + + + + tests/* + + + + + + + + + + + + src/* + tests/* + + + + src/* + tests/* + + + + tests/* + + + + + + + + + + + + src/* + + + + + + + + + + + + + + + bin/* + tests/php/src/PhpStan/* + + + + templates/* + includes/templates/* + back-compat/* + + + + + + + + . + + + + + + + + */node_modules/* + */vendor/* + ^build/* + ^logs/* + /assets/js/*.asset.php + */.github/* + */assets/* + */languages/* + */wp-assets/* + diff --git a/src/Interfaces/Container.php b/src/Interfaces/Container.php index b83e9613..a5ff90ce 100644 --- a/src/Interfaces/Container.php +++ b/src/Interfaces/Container.php @@ -16,6 +16,7 @@ * @package WpGuruDev\OrderExport\Interfaces */ interface Container { + /** * Define services in container. * diff --git a/src/Modules/Block.php b/src/Modules/Block.php index e854a71a..5c8345c9 100644 --- a/src/Modules/Block.php +++ b/src/Modules/Block.php @@ -155,7 +155,7 @@ public function render_login_button( $attributes ): string { * @since 1.2.3 */ $force_display = $attributes['forceDisplay'] ?? false; - if ( $force_display || ! is_user_logged_in() || apply_filters( 'rtcamp.google_login_button_display', false ) ) { + if ( $force_display || ! is_user_logged_in() || apply_filters( 'rtcamp.google_login_button_display', false ) ) { $markup = $this->markup( [ 'login_url' => $this->client->authorization_url(), diff --git a/src/Modules/Shortcode.php b/src/Modules/Shortcode.php index 0d9c87a5..05f86bfc 100644 --- a/src/Modules/Shortcode.php +++ b/src/Modules/Shortcode.php @@ -134,7 +134,6 @@ public function scan_shortcode( string $output, string $tag, $attrs ): string { return $output; } - /** * Filter redirect URL as per shortcode param. * diff --git a/src/Utils/GoogleClient.php b/src/Utils/GoogleClient.php index ea78f887..b162f00e 100644 --- a/src/Utils/GoogleClient.php +++ b/src/Utils/GoogleClient.php @@ -244,11 +244,14 @@ public function user(): \stdClass { * @return string */ public function state(): string { - $state_data['nonce'] = wp_create_nonce( 'login_with_google' ); + + $state_data = [ + 'nonce' => wp_create_nonce( 'login_with_google' ), + ]; + $state_data = apply_filters( 'rtcamp.google_login_state', $state_data ); $state_data['provider'] = 'google'; return base64_encode( wp_json_encode( $state_data ) ); } - } diff --git a/templates/google-login-button.php b/templates/google-login-button.php index c010785f..93290387 100644 --- a/templates/google-login-button.php +++ b/templates/google-login-button.php @@ -20,7 +20,7 @@ if ( is_user_logged_in() ) { $button_text = __( 'Log out', 'login-with-google' ); - $button_url = wp_logout_url( get_permalink() ); + $button_url = wp_logout_url( get_permalink() ); } ?>
diff --git a/tests/php/TestCase.php b/tests/php/TestCase.php index 94c6e820..fb03ffff 100644 --- a/tests/php/TestCase.php +++ b/tests/php/TestCase.php @@ -19,14 +19,14 @@ * * @author Guido Scialfa */ -class TestCase extends WPMockTestCase -{ +class TestCase extends WPMockTestCase { + /** * Sets up the fixture, for example, open a network connection. * This method is called before a test is executed. */ - public function setUp(): void - { + public function setUp(): void { + parent::setUp(); \WP_Mock::setUp(); } @@ -35,8 +35,8 @@ public function setUp(): void * Tears down the fixture, for example, close a network connection. * This method is called after a test is executed. */ - public function tearDown(): void - { + public function tearDown(): void { + parent::tearDown(); \WP_Mock::tearDown(); } @@ -46,27 +46,28 @@ public function tearDown(): void * * Basic configuration available for all of the testee objects, call `getMock` to get the mock. * - * @param string $className - * @param array $constructorArguments - * @param array $methods - * @param string $sutMethod + * @param string $class_name + * @param array $constructor_arguments + * @param array $methods + * @param string $sut_method * * @return PHPUnit_Framework_MockObject_MockBuilder */ protected function buildTesteeMock( - string $className, - array $constructorArguments, + string $class_name, + array $constructor_arguments, array $methods, - string $sutMethod - ): object { + string $sut_method + ): object { // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations.objectFound -- Ignoring because assuming php application version greater than 7.1. + + $testee = $this->getMockBuilder( $class_name ); - $testee = $this->getMockBuilder($className); - $constructorArguments - ? $testee->setConstructorArgs($constructorArguments) + $constructor_arguments + ? $testee->setConstructorArgs( $constructor_arguments ) : $testee->disableOriginalConstructor(); - $methods and $testee->setMethods($methods); - $sutMethod and $testee->setMethodsExcept([$sutMethod]); + $methods && $testee->setMethods( $methods ); + $sut_method && $testee->setMethodsExcept( [ $sut_method ] ); return $testee; } @@ -75,31 +76,36 @@ protected function buildTesteeMock( * Retrieve a Testee Mock to Test Protected Methods * * return MockBuilder - * @param string $className - * @param array $constructorArguments + * + * @param string $class_name + * @param array $constructor_arguments * @param string $method - * @param array $methods + * @param array $methods + * * @return array + * * @throws ReflectionException */ protected function buildTesteeMethodMock( - string $className, - array $constructorArguments, + string $class_name, + array $constructor_arguments, string $method, array $methods ): array { $testee = $this->buildTesteeMock( - $className, - $constructorArguments, + $class_name, + $constructor_arguments, $methods, '' )->getMock(); - $reflectionMethod = new ReflectionMethod($className, $method); - $reflectionMethod->setAccessible(true); + + $reflection_method = new ReflectionMethod( $class_name, $method ); + $reflection_method->setAccessible( true ); + return [ $testee, - $reflectionMethod, + $reflection_method, ]; } @@ -112,13 +118,14 @@ protected function buildTesteeMethodMock( //phpcs:disable Inpsyde.CodeQuality.ReturnTypeDeclaration.NoReturnType protected function getTesteeProperty( string $property, - object $object + object $object // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewParamTypeDeclarations.objectFound -- Ignoring because assuming php application version greater than 7.1. ) { - $reflection = new \ReflectionClass($object); - $reflectionProperty = $reflection->getProperty($property); - $reflectionProperty->setAccessible(true); - return $reflectionProperty->getValue($object); + $reflection = new \ReflectionClass( $object ); + $reflection_property = $reflection->getProperty( $property ); + + $reflection_property->setAccessible( true ); + return $reflection_property->getValue( $object ); } /** @@ -131,12 +138,17 @@ protected function getTesteeProperty( * @throws ReflectionException */ // phpcs:disable Inpsyde.CodeQuality.ArgumentTypeDeclaration.NoArgumentType - protected function setTesteeProperty(object $object, string $property, $value): void - { - $reflection = new \ReflectionClass($object); - $reflectionProperty = $reflection->getProperty($property); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($object, $value); + protected function setTesteeProperty( + object $object, // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewParamTypeDeclarations.objectFound -- Ignoring because assuming php application version greater than 7.1. + string $property, + $value + ): void { + + $reflection = new \ReflectionClass( $object ); + $reflection_property = $reflection->getProperty( $property ); + + $reflection_property->setAccessible( true ); + $reflection_property->setValue( $object, $value ); } /** @@ -146,30 +158,32 @@ protected function setTesteeProperty(object $object, string $property, $value): * @param string $function_name * @param mixed $args * @param int $times + * * @param mixed $return */ protected function wpMockFunction( - string $functionName, + string $function_name, $args = [], int $times = 1, $return = null ) { - $funcArgs = [ + $func_args = [ 'times' => $times, ]; - if (!empty($args)) { - $funcArgs['args'] = $args; + if ( ! empty( $args ) ) { + $func_args['args'] = $args; } - if (!empty($return)) { - $funcArgs['return'] = $return; + if ( ! empty( $return ) ) { + $func_args['return'] = $return; } \WP_Mock::userFunction( - $functionName, - $funcArgs + $function_name, + $func_args ); + } } diff --git a/tests/php/Unit/ContainerTest.php b/tests/php/Unit/ContainerTest.php index be42f480..86aaf586 100644 --- a/tests/php/Unit/ContainerTest.php +++ b/tests/php/Unit/ContainerTest.php @@ -27,7 +27,7 @@ class ContainerTest extends TestCase { /** * @var PimpleContainer */ - private $pimpleMock; + private $pimple_mock; /** * Object under test. @@ -40,11 +40,14 @@ class ContainerTest extends TestCase { * @return void */ public function setUp(): void { - $this->pimpleMock = $this->createMock( PimpleContainer::class ); - $this->testee = new Testee( $this->pimpleMock ); + + $this->pimple_mock = $this->createMock( PimpleContainer::class ); + $this->testee = new Testee( $this->pimple_mock ); + } public function testContainerImplementsInterface() { + $this->assertInstanceOf( ContainerInterface::class, $this->testee ); } @@ -52,11 +55,13 @@ public function testContainerImplementsInterface() { * @covers ::get */ public function testGetThrowsExceptionForNonExistentService() { - $this->pimpleMock->expects( $this->once() ) - ->method( 'keys' ) - ->willReturn( [ 'example_service' ] ); + + $this->pimple_mock->expects( $this->once() ) + ->method( 'keys' ) + ->willReturn( [ 'example_service' ] ); $this->expectException( InvalidArgumentException::class ); + $this->testee->get( 'non_existent_service' ); } @@ -64,21 +69,22 @@ public function testGetThrowsExceptionForNonExistentService() { * @covers ::get */ public function testGetReturnsServiceObject() { - $dummyService = (object) [ + + $dummy_service = (object) [ 'some_key' => 'some_value', 'some_other_key' => 'some_other_value', ]; - $this->testee->container['test_service'] = $dummyService; + $this->testee->container['test_service'] = $dummy_service; - $this->pimpleMock->expects( $this->once() ) - ->method( 'keys' ) - ->willReturn( [ 'test_service' ] ); + $this->pimple_mock->expects( $this->once() ) + ->method( 'keys' ) + ->willReturn( [ 'test_service' ] ); - $this->pimpleMock->expects( $this->once() ) - ->method( 'offsetGet' ) - ->with( 'test_service' ) - ->willReturn( $dummyService ); + $this->pimple_mock->expects( $this->once() ) + ->method( 'offsetGet' ) + ->with( 'test_service' ) + ->willReturn( $dummy_service ); $this->testee->get( 'test_service' ); } diff --git a/tests/php/Unit/Modules/AssetsTest.php b/tests/php/Unit/Modules/AssetsTest.php index 4342eaca..008db153 100644 --- a/tests/php/Unit/Modules/AssetsTest.php +++ b/tests/php/Unit/Modules/AssetsTest.php @@ -45,7 +45,7 @@ public function testInit() { 'login_enqueue_scripts', [ $this->testee, - 'enqueue_login_styles' + 'enqueue_login_styles', ] ); @@ -111,7 +111,7 @@ function () { 'login-with-google', 'https://example.com/assets/js/login.js', [ - 'some-other-script' + 'some-other-script', ], false, true, @@ -124,7 +124,7 @@ function () { 'login-with-google', 'js/login.js', [ - 'some-other-script' + 'some-other-script', ] ); diff --git a/tests/php/Unit/Modules/BlockTest.php b/tests/php/Unit/Modules/BlockTest.php index e5edc9e8..096f8c6e 100644 --- a/tests/php/Unit/Modules/BlockTest.php +++ b/tests/php/Unit/Modules/BlockTest.php @@ -27,12 +27,12 @@ class BlockTest extends TestCase { /** * @var GoogleClient */ - private $ghClientMock; + private $gh_client_mock; /** * @var Assets */ - private $assetMock; + private $assert_mock; /** * @var Testee @@ -45,15 +45,15 @@ class BlockTest extends TestCase { * @return void */ public function setUp(): void { - $this->ghClientMock = $this->createMock( GoogleClient::class ); - $this->assetMock = $this->createMock( Assets::class ); - $this->testee = new Testee( $this->assetMock, $this->ghClientMock ); + $this->gh_client_mock = $this->createMock( GoogleClient::class ); + $this->assert_mock = $this->createMock( Assets::class ); + $this->testee = new Testee( $this->assert_mock, $this->gh_client_mock ); } public function tearDown(): void { parent::tearDown(); - $this->ghClientMock = null; - $this->assetMock = null; + $this->gh_client_mock = null; + $this->assert_mock = null; unset( $this->testee ); } @@ -114,20 +114,20 @@ function () use ( $path ) { true ); - $this->assetMock->expects( $this->once() )->method( 'register_login_styles' ); - $this->assetMock->expects( $this->once() )->method( 'register_script' ) - ->with( - 'google-login-block', - 'build/js/block-button.js', - [ - 'wp-blocks', - 'wp-element', - 'wp-editor', - 'wp-components', - ], - filemtime( $path . 'build/js/block-button.js' ), - false - ); + $this->assert_mock->expects( $this->once() )->method( 'register_login_styles' ); + $this->assert_mock->expects( $this->once() )->method( 'register_script' ) + ->with( + 'google-login-block', + 'build/js/block-button.js', + [ + 'wp-blocks', + 'wp-element', + 'wp-editor', + 'wp-components', + ], + filemtime( $path . 'build/js/block-button.js' ), + false + ); $this->testee->enqueue_block_editor_assets(); } @@ -164,12 +164,12 @@ public function testRegister() { $this->assertConditionsMet(); } - /** * @covers ::render_login_button, ::markup */ public function testRenderLoginButton() { - $mockAttributes = [ + + $mock_attributes = [ 'login_url' => '#', 'custom_btn_text' => 'test', 'force_display' => false, @@ -186,7 +186,7 @@ public function testRenderLoginButton() { 'wp_parse_args', [], 1, - $mockAttributes + $mock_attributes ); $this->wpMockFunction( @@ -219,11 +219,11 @@ function () use ( $path ) { ); - $helperMock = \Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'render_template' )->once()->withArgs( + $helper_mock = \Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'render_template' )->once()->withArgs( [ $path . 'google-login-button.php', - $mockAttributes, + $mock_attributes, false, ] )->andReturn( '' ); @@ -231,7 +231,7 @@ function () use ( $path ) { $markup = $this->testee->render_login_button( [ $path . '/google-login-button.php', - $mockAttributes, + $mock_attributes, false, ] ); @@ -243,7 +243,8 @@ function () use ( $path ) { * @covers ::render_login_button, ::markup */ public function testRenderLogoutButton() { - $mockAttributes = [ + + $mock_attributes = [ 'login_url' => '#', 'custom_btn_text' => 'test', 'force_display' => true, @@ -260,7 +261,7 @@ public function testRenderLogoutButton() { 'wp_parse_args', [], 1, - $mockAttributes + $mock_attributes ); $this->wpMockFunction( @@ -293,11 +294,11 @@ function () use ( $path ) { ); - $helperMock = \Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'render_template' )->once()->withArgs( + $helper_mock = \Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'render_template' )->once()->withArgs( [ $path . 'google-login-button.php', - $mockAttributes, + $mock_attributes, false, ] )->andReturn( '' ); @@ -305,7 +306,7 @@ function () use ( $path ) { $markup = $this->testee->render_login_button( [ $path . '/google-login-button.php', - $mockAttributes, + $mock_attributes, false, ] ); diff --git a/tests/php/Unit/Modules/LoginTest.php b/tests/php/Unit/Modules/LoginTest.php index 94c5b958..372f43f0 100644 --- a/tests/php/Unit/Modules/LoginTest.php +++ b/tests/php/Unit/Modules/LoginTest.php @@ -31,12 +31,12 @@ class LoginTest extends TestCase { /** * @var GoogleClient */ - private $ghClientMock; + private $gh_client_mock; /** * @var Settings */ - private $authenticatorMock; + private $authenticator_mock; /** * @var Testee @@ -49,16 +49,18 @@ class LoginTest extends TestCase { * @return void */ public function setUp(): void { - $this->ghClientMock = $this->createMock( GoogleClient::class ); - $this->authenticatorMock = $this->createMock( Authenticator::class ); - $this->testee = new Testee( $this->ghClientMock, $this->authenticatorMock ); + $this->gh_client_mock = $this->createMock( GoogleClient::class ); + $this->authenticator_mock = $this->createMock( Authenticator::class ); + + $this->testee = new Testee( $this->gh_client_mock, $this->authenticator_mock ); } /** * @covers ::name */ public function testName() { + $this->assertSame( 'login_flow', $this->testee->name() ); } @@ -66,6 +68,7 @@ public function testName() { * @covers ::__construct */ public function testImplementsModuleInterface() { + $this->assertTrue( $this->testee instanceof ModuleInterface ); } @@ -73,9 +76,10 @@ public function testImplementsModuleInterface() { * @covers ::init */ public function testInit() { + WP_Mock::expectActionAdded( 'login_form', [ $this->testee, 'login_button' ] ); WP_Mock::expectActionAdded( 'authenticate', [ $this->testee, 'authenticate' ], 20 ); - WP_Mock::expectActionAdded( 'rtcamp.google_register_user', [ $this->authenticatorMock, 'register' ] ); + WP_Mock::expectActionAdded( 'rtcamp.google_register_user', [ $this->authenticator_mock, 'register' ] ); WP_Mock::expectActionAdded( 'rtcamp.google_redirect_url', [ $this->testee, 'redirect_url' ] ); WP_Mock::expectActionAdded( 'rtcamp.google_user_created', [ $this->testee, 'user_meta' ] ); WP_Mock::expectFilterAdded( 'rtcamp.google_login_state', [ $this->testee, 'state_redirect' ] ); @@ -89,27 +93,28 @@ public function testInit() { * @covers ::login_button */ public function testLoginButton() { - $pluginMock = $this->createMock( Plugin::class ); - $pluginMock->template_dir = 'https://example.com/templates/'; - $containerMock = $this->createMock( Container::class ); - $containerMock->expects( $this->once() ) - ->method( 'get' ) - ->willReturn( $this->ghClientMock ); + $plugin_mock = $this->createMock( Plugin::class ); + $plugin_mock->template_dir = 'https://example.com/templates/'; + + $container_mock = $this->createMock( Container::class ); + $container_mock->expects( $this->once() ) + ->method( 'get' ) + ->willReturn( $this->gh_client_mock ); - $pluginMock->expects( $this->once() ) - ->method( 'container' ) - ->willReturn( $containerMock ); + $plugin_mock->expects( $this->once() ) + ->method( 'container' ) + ->willReturn( $container_mock ); - $this->ghClientMock->expects( $this->once() ) - ->method( 'authorization_url' ) - ->willReturn( 'https://google.com/auth/' ); + $this->gh_client_mock->expects( $this->once() ) + ->method( 'authorization_url' ) + ->willReturn( 'https://google.com/auth/' ); $this->wpMockFunction( 'RtCamp\GoogleLogin\plugin', [], 2, - $pluginMock + $plugin_mock ); WP_Mock::userFunction( @@ -117,19 +122,19 @@ public function testLoginButton() { [ 'times' => 1, 'args' => [ - 'https://example.com/templates/' + 'https://example.com/templates/', ], - 'return_arg' => 0 + 'return_arg' => 0, ] ); - $helperMock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'render_template' )->once()->withArgs( + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'render_template' )->once()->withArgs( [ 'https://example.com/templates/google-login-button.php', [ 'login_url' => 'https://google.com/auth/', - ] + ], ] ); @@ -141,12 +146,13 @@ public function testLoginButton() { * @covers ::authenticate */ public function testAuthenticationForNoCode() { - $helperMock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'filter_input' )->once()->withArgs( + + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'filter_input' )->once()->withArgs( [ INPUT_GET, 'code', - FILTER_SANITIZE_STRING + FILTER_SANITIZE_STRING, ] )->andReturn( null ); @@ -154,7 +160,7 @@ public function testAuthenticationForNoCode() { $wp_user_mock->login = 'test'; $wp_user_mock->email = 'test@unit.com'; - $returned = $this->testee->authenticate( $wp_user_mock ); + $returned = $this->testee->authenticate( $wp_user_mock ); $this->assertSame( $returned, $wp_user_mock ); } @@ -163,12 +169,13 @@ public function testAuthenticationForNoCode() { * @covers ::authenticate */ public function testAuthenticationForAlreadyAuthenticatedUser() { - $helperMock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'filter_input' )->never()->withArgs( + + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'filter_input' )->never()->withArgs( [ INPUT_GET, 'code', - FILTER_SANITIZE_STRING + FILTER_SANITIZE_STRING, ] )->andReturn( null ); @@ -182,27 +189,28 @@ public function testAuthenticationForAlreadyAuthenticatedUser() { * @covers ::authenticate */ public function testAuthenticationForDifferentProvider() { + $state = [ 'nonce' => '1234', 'provider' => 'some_other', ]; - $state = base64_encode( json_encode( $state ) ); + $state = base64_encode( wp_json_encode( $state ) ); - $helperMock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'filter_input' )->once()->withArgs( + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'filter_input' )->once()->withArgs( [ INPUT_GET, 'code', - FILTER_SANITIZE_STRING + FILTER_SANITIZE_STRING, ] )->andReturn( 'test_code' ); - $helperMock->expects( 'filter_input' )->once()->withArgs( + $helper_mock->expects( 'filter_input' )->once()->withArgs( [ INPUT_GET, 'state', - FILTER_SANITIZE_STRING + FILTER_SANITIZE_STRING, ] )->andReturn( $state ); @@ -210,7 +218,7 @@ public function testAuthenticationForDifferentProvider() { $wp_user_mock->login = 'test'; $wp_user_mock->email = 'test@unit.com'; - $returned = $this->testee->authenticate( $wp_user_mock ); + $returned = $this->testee->authenticate( $wp_user_mock ); $this->assertSame( $returned, $wp_user_mock ); } @@ -219,20 +227,21 @@ public function testAuthenticationForDifferentProvider() { * @covers ::authenticate */ public function testAuthenticationWithForgedState() { - $helperMock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'filter_input' )->once()->withArgs( + + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'filter_input' )->once()->withArgs( [ INPUT_GET, 'code', - FILTER_SANITIZE_STRING + FILTER_SANITIZE_STRING, ] )->andReturn( 'abc' ); - $helperMock->expects( 'filter_input' )->once()->withArgs( + $helper_mock->expects( 'filter_input' )->once()->withArgs( [ INPUT_GET, 'state', - FILTER_SANITIZE_STRING + FILTER_SANITIZE_STRING, ] )->andReturn( 'eyJwcm92aWRlciI6ImdpdGh1YiJ9' ); @@ -246,26 +255,27 @@ public function testAuthenticationWithForgedState() { * @covers ::authenticate */ public function testAuthenticationWhenUserExists() { - $helperMock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'filter_input' )->once()->withArgs( + + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'filter_input' )->once()->withArgs( [ INPUT_GET, 'code', - FILTER_SANITIZE_STRING + FILTER_SANITIZE_STRING, ] )->andReturn( 'abc' ); - $helperMock->expects( 'filter_input' )->once()->withArgs( + $helper_mock->expects( 'filter_input' )->once()->withArgs( [ INPUT_GET, 'state', - FILTER_SANITIZE_STRING + FILTER_SANITIZE_STRING, ] )->andReturn( 'eyJwcm92aWRlciI6Imdvb2dsZSIsIm5vbmNlIjoidGVzdG5vbmNlIn0=' ); - $this->ghClientMock->expects( $this->never() ) - ->method( 'state' ) - ->willReturn( 'eyJwcm92aWRlciI6Imdvb2dsZSIsIm5vbmNlIjoidGVzdG5vbmNlIn0=' ); + $this->gh_client_mock->expects( $this->never() ) + ->method( 'state' ) + ->willReturn( 'eyJwcm92aWRlciI6Imdvb2dsZSIsIm5vbmNlIjoidGVzdG5vbmNlIn0=' ); $this->wpMockFunction( 'wp_verify_nonce', @@ -277,26 +287,26 @@ public function testAuthenticationWhenUserExists() { true ); - $this->ghClientMock->expects( $this->once() ) - ->method( 'set_access_token' ) - ->with( 'abc' ); + $this->gh_client_mock->expects( $this->once() ) + ->method( 'set_access_token' ) + ->with( 'abc' ); $user = (object) [ 'email' => 'fakeemail@domain.com', ]; - $this->ghClientMock->expects( $this->once() ) - ->method( 'user' ) - ->willReturn( $user ); + $this->gh_client_mock->expects( $this->once() ) + ->method( 'user' ) + ->willReturn( $user ); - $userMock = Mockery::mock( 'WP_User' ); - $this->authenticatorMock->expects( $this->once() ) - ->method( 'authenticate' ) - ->willReturn( $userMock ); + $user_mock = Mockery::mock( 'WP_User' ); + $this->authenticator_mock->expects( $this->once() ) + ->method( 'authenticate' ) + ->willReturn( $user_mock ); $returned = $this->testee->authenticate(); - $this->assertSame( $returned, $userMock ); + $this->assertSame( $returned, $user_mock ); $this->assertConditionsMet(); } @@ -305,26 +315,27 @@ public function testAuthenticationWhenUserExists() { * @covers ::authenticate */ public function testAuthenticationCapturesExceptions() { - $helperMock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'filter_input' )->once()->withArgs( + + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'filter_input' )->once()->withArgs( [ INPUT_GET, 'code', - FILTER_SANITIZE_STRING + FILTER_SANITIZE_STRING, ] )->andReturn( 'abc' ); - $helperMock->expects( 'filter_input' )->once()->withArgs( + $helper_mock->expects( 'filter_input' )->once()->withArgs( [ INPUT_GET, 'state', - FILTER_SANITIZE_STRING + FILTER_SANITIZE_STRING, ] )->andReturn( 'eyJwcm92aWRlciI6Imdvb2dsZSIsIm5vbmNlIjoidGVzdG5vbmNlIn0=' ); - $this->ghClientMock->expects( $this->never() ) - ->method( 'state' ) - ->willReturn( 'eyJwcm92aWRlciI6Imdvb2dsZSIsIm5vbmNlIjoidGVzdG5vbmNlIn0=' ); + $this->gh_client_mock->expects( $this->never() ) + ->method( 'state' ) + ->willReturn( 'eyJwcm92aWRlciI6Imdvb2dsZSIsIm5vbmNlIjoidGVzdG5vbmNlIn0=' ); $this->wpMockFunction( 'wp_verify_nonce', @@ -336,10 +347,10 @@ public function testAuthenticationCapturesExceptions() { true ); - $this->ghClientMock->expects( $this->once() ) - ->method( 'set_access_token' ) - ->with( 'abc' ) - ->willThrowException( new Exception( 'Exception for test' ) ); + $this->gh_client_mock->expects( $this->once() ) + ->method( 'set_access_token' ) + ->with( 'abc' ) + ->willThrowException( new Exception( 'Exception for test' ) ); Mockery::mock( 'WP_Error' ); $returned = $this->testee->authenticate(); @@ -352,7 +363,8 @@ public function testAuthenticationCapturesExceptions() { * @covers ::user_meta */ public function testUserMeta() { - $user = new \stdClass(); + + $user = new \stdClass(); $user->login = 'login'; $this->wpMockFunction( @@ -387,6 +399,7 @@ public function testUserMeta() { * @covers ::redirect_url */ public function testRedirectURLRetuensWithQueryParam() { + $url = 'https://example.com/?redirect_to=https://example.com/wp-admin'; $this->wpMockFunction( @@ -407,12 +420,13 @@ public function testRedirectURLRetuensWithQueryParam() { * @covers ::state_redirect */ public function testStateRedirectWithRedirectTo() { - $helperMock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'filter_input' )->once()->withArgs( + + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'filter_input' )->once()->withArgs( [ INPUT_GET, 'redirect_to', - FILTER_SANITIZE_STRING + FILTER_SANITIZE_STRING, ] )->andReturn( 'https://example.com/state-page' ); @@ -426,12 +440,13 @@ public function testStateRedirectWithRedirectTo() { * @covers ::state_redirect */ public function testStateRedirectWithoutRedirectTo() { - $helperMock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'filter_input' )->once()->withArgs( + + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'filter_input' )->once()->withArgs( [ INPUT_GET, 'redirect_to', - FILTER_SANITIZE_STRING + FILTER_SANITIZE_STRING, ] )->andReturn( null ); @@ -452,12 +467,13 @@ public function testStateRedirectWithoutRedirectTo() { * @covers ::login_redirect */ public function testLoginRedirectWithNotStateAuthenticated() { - $helperMock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'filter_input' )->once()->withArgs( + + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'filter_input' )->once()->withArgs( [ INPUT_GET, 'state', - FILTER_SANITIZE_STRING + FILTER_SANITIZE_STRING, ] )->andReturn( [] ); diff --git a/tests/php/Unit/Modules/SettingsTest.php b/tests/php/Unit/Modules/SettingsTest.php index bc2616e1..d095a772 100644 --- a/tests/php/Unit/Modules/SettingsTest.php +++ b/tests/php/Unit/Modules/SettingsTest.php @@ -33,6 +33,7 @@ class SettingsTest extends TestCase { * @return void */ public function setUp(): void { + $this->testee = new Testee(); } @@ -40,10 +41,12 @@ public function setUp(): void { * @covers ::name */ public function testName() { + $this->assertSame( 'settings', $this->testee->name() ); } public function testImplementsModuleInterface() { + $this->assertTrue( $this->testee instanceof ModuleInterface ); } @@ -51,6 +54,7 @@ public function testImplementsModuleInterface() { * @covers ::__get */ public function testGetWithNull() { + $value = $this->testee->__get( 'some_test_property' ); $this->assertEquals( null, $value ); } @@ -59,15 +63,16 @@ public function testGetWithNull() { * @covers ::__get */ public function testGetWithProper() { + $this->wpMockFunction( 'get_option', [ 'wp_google_login_settings', - [] + [], ], 1, [ - 'client_id' => 'cid' + 'client_id' => 'cid', ] ); @@ -80,11 +85,12 @@ public function testGetWithProper() { * @covers ::init */ public function testInit() { + $this->wpMockFunction( 'get_option', [ 'wp_google_login_settings', - [] + [], ], 1, [] @@ -101,11 +107,12 @@ public function testInit() { * @covers ::register_settings */ public function testRegisterSettings() { + $this->wpMockFunction( 'register_setting', [ 'wp_google_login', - 'wp_google_login_settings' + 'wp_google_login_settings', ], 1, true @@ -117,7 +124,7 @@ public function testRegisterSettings() { 'wp_google_login_section', 'Log in with Google Settings', \Closure::class, - 'login-with-google' + 'login-with-google', ], 1 ); @@ -133,7 +140,7 @@ public function testRegisterSettings() { \WP_Mock\Functions::type( 'string' ), \WP_Mock\Functions::type( 'array' ), ], - 'times' => 6 + 'times' => 6, ] ); @@ -145,6 +152,7 @@ public function testRegisterSettings() { * @covers ::settings_page */ public function testSettingsPage() { + $this->wpMockFunction( 'add_options_page', [ @@ -154,7 +162,7 @@ public function testSettingsPage() { 'login-with-google', [ $this->testee, - 'output' + 'output', ], ] ); @@ -167,6 +175,7 @@ public function testSettingsPage() { * @covers ::output */ public function testOutput() { + $this->wpMockFunction( 'settings_fields', [ @@ -190,7 +199,7 @@ public function testOutput() { '' ); - $this->setOutputCallback(function() {}); + $this->setOutputCallback( function() {} ); $this->testee->output(); $this->assertConditionsMet(); } @@ -199,13 +208,14 @@ public function testOutput() { * @covers ::client_id_field */ public function testClientIdField() { + $this->wpMockFunction( 'esc_html__', [ 'Create oAuth Client ID and Client Secret at', - 'login-with-google' + 'login-with-google', ], - 2, + 2 ); $this->wpMockFunction( @@ -216,12 +226,12 @@ public function testClientIdField() { esc_html__( 'Create oAuth Client ID and Client Secret at', 'login-with-google' ), 'https://console.developers.google.com/apis/dashboard', 'console.developers.google.com' - ) + ), ], - 1, + 1 ); - $this->setOutputCallback(function() {}); + $this->setOutputCallback( function() {} ); $this->testee->client_id_field(); $this->assertConditionsMet(); } @@ -230,23 +240,24 @@ public function testClientIdField() { * @covers ::user_registration */ public function testUserRegistration() { + $this->testee->registration_enabled = 'yes'; $this->wpMockFunction( 'checked', [ - 'yes' + 'yes', ], - 1, + 1 ); $this->wpMockFunction( 'esc_html_e', [ 'Create a new user account if it does not exist already', - 'login-with-google' + 'login-with-google', ], - 1, + 1 ); $this->wpMockFunction( @@ -262,10 +273,10 @@ public function testUserRegistration() { /* translators: %1s will be replaced by page link */ __( 'If this setting is checked, a new user will be created even if membership setting is off.', 'login-with-google' ), ], - 1, + 1 ); - $this->setOutputCallback(function() {}); + $this->setOutputCallback( function() {} ); $this->testee->user_registration(); $this->assertConditionsMet(); } @@ -274,6 +285,7 @@ public function testUserRegistration() { * @covers ::whitelisted_domains */ public function testWhitelistedDomains() { + $this->testee->whitelisted_domains = 'https://example1.com,https://example2.com'; $this->wpMockFunction( @@ -281,18 +293,18 @@ public function testWhitelistedDomains() { [ 'https://example1.com,https://example2.com', ], - 1, + 1 ); $this->wpMockFunction( 'esc_html', [ - __( 'Add each domain comma separated', 'login-with-google' ) + __( 'Add each domain comma separated', 'login-with-google' ), ], - 1, + 1 ); - $this->setOutputCallback(function() {}); + $this->setOutputCallback( function() {} ); $this->testee->whitelisted_domains(); $this->assertConditionsMet(); } @@ -301,18 +313,18 @@ public function testWhitelistedDomains() { * @covers ::client_secret_field */ public function testClientSecretField() { + $this->testee->client_secret = 'cis'; $this->wpMockFunction( 'esc_attr', [ - 'cis' + 'cis', ], 1 ); - $this->setOutputCallback(function() {}); + $this->setOutputCallback( function() {} ); $this->testee->client_secret_field(); $this->assertConditionsMet(); } - } diff --git a/tests/php/Unit/Modules/ShortCodeTest.php b/tests/php/Unit/Modules/ShortCodeTest.php index 0d1f270a..2e526213 100644 --- a/tests/php/Unit/Modules/ShortCodeTest.php +++ b/tests/php/Unit/Modules/ShortCodeTest.php @@ -27,12 +27,12 @@ class ShortCodeTest extends TestCase { /** * @var GoogleClient */ - private $ghClientMock; + private $gh_client_mock; /** * @var Assets */ - private $assetMock; + private $asset_mock; /** * @var Testee @@ -45,10 +45,10 @@ class ShortCodeTest extends TestCase { * @return void */ public function setUp(): void { - $this->ghClientMock = $this->createMock( GoogleClient::class ); - $this->assetMock = $this->createMock( Assets::class ); + $this->gh_client_mock = $this->createMock( GoogleClient::class ); + $this->asset_mock = $this->createMock( Assets::class ); - $this->testee = new Testee( $this->ghClientMock, $this->assetMock ); + $this->testee = new Testee( $this->gh_client_mock, $this->asset_mock ); } /** @@ -76,7 +76,7 @@ public function testInit() { [ $this->testee, 'callback', - ] + ], ] ); @@ -91,6 +91,7 @@ public function testInit() { * @covers ::should_display */ public function testCallbackWhenUserIsLoggedIn() { + $this->wpMockFunction( 'get_permalink', [], @@ -111,7 +112,7 @@ public function testCallbackWhenUserIsLoggedIn() { 'google_login', ], 'times' => 1, - 'return_arg' => 0 + 'return_arg' => 0, ] ); @@ -132,6 +133,7 @@ public function testCallbackWhenUserIsLoggedIn() { * @covers ::should_display */ public function testCallbackWhenUserIsLoggedOut() { + WP_Mock::userFunction( 'shortcode_atts', [ @@ -145,7 +147,7 @@ public function testCallbackWhenUserIsLoggedOut() { 'google_login', ], 'times' => 1, - 'return_arg' => 0 + 'return_arg' => 0, ] ); @@ -174,13 +176,13 @@ public function testCallbackWhenUserIsLoggedOut() { '/some/path/templates/' ); - $this->ghClientMock->expects( $this->once() ) - ->method( 'authorization_url' ) - ->willReturn( 'https://google.com/auth/' ); + $this->gh_client_mock->expects( $this->once() ) + ->method( 'authorization_url' ) + ->willReturn( 'https://google.com/auth/' ); - $helperMock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'render_template' )->once()->withArgs( + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'render_template' )->once()->withArgs( [ '/some/path/templates/google-login-button.php', [ @@ -189,7 +191,7 @@ public function testCallbackWhenUserIsLoggedOut() { 'redirect_to' => null, 'login_url' => 'https://google.com/auth/', ], - false + false, ] )->andReturn( '' ); @@ -202,6 +204,7 @@ public function testCallbackWhenUserIsLoggedOut() { * @covers ::should_display */ public function testScanShortcodeForSinglePage() { + $this->wpMockFunction( 'is_single', [], @@ -223,7 +226,7 @@ public function testScanShortcodeForSinglePage() { false ); - $this->assetMock->expects( $this->once() )->method( 'enqueue_login_styles' ); + $this->asset_mock->expects( $this->once() )->method( 'enqueue_login_styles' ); $output = $this->testee->scan_shortcode( 'Hello', 'google_login', [] ); $this->assertSame( 'Hello', $output ); @@ -234,6 +237,7 @@ public function testScanShortcodeForSinglePage() { * @covers ::should_display */ public function testScanShortcodeForDifferentTag() { + $this->wpMockFunction( 'is_single', [], @@ -248,8 +252,7 @@ public function testScanShortcodeForDifferentTag() { false ); - - $this->assetMock->expects( $this->never() )->method( 'enqueue_login_styles' ); + $this->asset_mock->expects( $this->never() )->method( 'enqueue_login_styles' ); $output = $this->testee->scan_shortcode( 'Hello', 'other_tag', [] ); $this->assertSame( 'Hello', $output ); @@ -259,14 +262,15 @@ public function testScanShortcodeForDifferentTag() { * @covers ::redirect_url */ public function testRedirectURL() { - $url = 'https://example.com/?redirect_to=https://example.com/wp-admin'; + + $url = 'https://example.com/?redirect_to=https://example.com/wp-admin'; $this->testee->redirect_uri = 'https://example.com/some-page'; $this->wpMockFunction( 'remove_query_arg', [ 'redirect_to', - $url + $url, ], 1, 'https://example.com/' @@ -280,11 +284,12 @@ public function testRedirectURL() { * @covers ::state_redirect */ public function testStateRedirectWithRedirectUrl() { + $this->testee->redirect_uri = 'https://example.com'; $state = [ 'provider' => 'google', - 'redirect_to' => 'https://example.com' + 'redirect_to' => 'https://example.com', ]; $expected = $this->testee->state_redirect( $state ); @@ -295,10 +300,11 @@ public function testStateRedirectWithRedirectUrl() { * @covers ::state_redirect */ public function testStateRedirectWithoutRedirectUrl() { + $this->testee->redirect_uri = null; $state = [ - 'provider' => 'google' + 'provider' => 'google', ]; $expected = $this->testee->state_redirect( $state ); diff --git a/tests/php/Unit/PluginTest.php b/tests/php/Unit/PluginTest.php index d594aad0..967043bf 100644 --- a/tests/php/Unit/PluginTest.php +++ b/tests/php/Unit/PluginTest.php @@ -29,14 +29,14 @@ class PluginTest extends TestCase { * * @var ContainerInterface */ - private $containerMock; + private $container_mock; /** * Mock for module. * * @var ModuleInterface */ - private $moduleMock; + private $module_mock; /** * Object in test. @@ -49,9 +49,10 @@ class PluginTest extends TestCase { * Runs before any test in class is run. */ public function setUp(): void { - $this->moduleMock = $this->createMock( ModuleInterface::class ); - $this->containerMock = $this->createMock( Container::class ); - $this->testee = new Testee( $this->containerMock ); + + $this->module_mock = $this->createMock( ModuleInterface::class ); + $this->container_mock = $this->createMock( Container::class ); + $this->testee = new Testee( $this->container_mock ); } /** @@ -61,22 +62,23 @@ public function setUp(): void { * @covers ::activate_modules */ public function testRun() { - $this->moduleMock->expects( $this->exactly( 6 ) ) - ->method( 'init' ); - $this->containerMock->expects( $this->once() ) - ->method( 'define_services' ); + $this->module_mock->expects( $this->exactly( 6 ) ) + ->method( 'init' ); + + $this->container_mock->expects( $this->once() ) + ->method( 'define_services' ); - $this->containerMock->expects( $this->exactly( 6 ) ) - ->method( 'get' ) - ->withAnyParameters() - ->willReturn( $this->moduleMock ); + $this->container_mock->expects( $this->exactly( 6 ) ) + ->method( 'get' ) + ->withAnyParameters() + ->willReturn( $this->module_mock ); $this->wpMockFunction( 'trailingslashit', [ - WP_Mock\Functions::type( 'string' ) + WP_Mock\Functions::type( 'string' ), ], 3, 'slashedstring/' @@ -85,7 +87,7 @@ public function testRun() { $this->wpMockFunction( 'plugin_dir_url', [ - 'slashedstring/login-with-google.php' + 'slashedstring/login-with-google.php', ] ); @@ -100,21 +102,22 @@ public function testRun() { * @covers ::run */ public function testPath() { - $this->moduleMock->expects( $this->exactly( 6 ) ) - ->method( 'init' ); - $this->containerMock->expects( $this->once() ) - ->method( 'define_services' ); + $this->module_mock->expects( $this->exactly( 6 ) ) + ->method( 'init' ); + + $this->container_mock->expects( $this->once() ) + ->method( 'define_services' ); - $this->containerMock->expects( $this->exactly( 6 ) ) - ->method( 'get' ) - ->withAnyParameters() - ->willReturn( $this->moduleMock ); + $this->container_mock->expects( $this->exactly( 6 ) ) + ->method( 'get' ) + ->withAnyParameters() + ->willReturn( $this->module_mock ); $this->wpMockFunction( 'trailingslashit', [ - WP_Mock\Functions::type( 'string' ) + WP_Mock\Functions::type( 'string' ), ], 3, 'slashedstring/' @@ -123,7 +126,7 @@ public function testPath() { $this->wpMockFunction( 'plugin_dir_url', [ - 'slashedstring/login-with-google.php' + 'slashedstring/login-with-google.php', ] ); @@ -138,15 +141,16 @@ public function testPath() { * @covers ::run */ public function testTemplateDirPath() { - $this->containerMock->expects( $this->exactly( 6 ) ) - ->method( 'get' ) - ->withAnyParameters() - ->willReturn( $this->moduleMock ); + + $this->container_mock->expects( $this->exactly( 6 ) ) + ->method( 'get' ) + ->withAnyParameters() + ->willReturn( $this->module_mock ); $this->wpMockFunction( 'trailingslashit', [ - WP_Mock\Functions::type( 'string' ) + WP_Mock\Functions::type( 'string' ), ], 3, 'slashedstring/' @@ -155,7 +159,7 @@ public function testTemplateDirPath() { $this->wpMockFunction( 'plugin_dir_url', [ - 'slashedstring/login-with-google.php' + 'slashedstring/login-with-google.php', ] ); @@ -170,15 +174,15 @@ public function testTemplateDirPath() { * @covers ::run */ public function testPluginURL() { - $this->containerMock->expects( $this->exactly( 6 ) ) - ->method( 'get' ) - ->withAnyParameters() - ->willReturn( $this->moduleMock ); + $this->container_mock->expects( $this->exactly( 6 ) ) + ->method( 'get' ) + ->withAnyParameters() + ->willReturn( $this->module_mock ); $this->wpMockFunction( 'trailingslashit', [ - WP_Mock\Functions::type( 'string' ) + WP_Mock\Functions::type( 'string' ), ], 3, 'slashedstring/' @@ -188,9 +192,9 @@ public function testPluginURL() { 'plugin_dir_url', [ 'args' => [ - 'slashedstring/login-with-google.php' + 'slashedstring/login-with-google.php', ], - 'return_arg' => 0 + 'return_arg' => 0, ] ); @@ -205,15 +209,15 @@ public function testPluginURL() { * @covers ::run */ public function testAssetsDirPath() { - $this->containerMock->expects( $this->exactly( 6 ) ) - ->method( 'get' ) - ->withAnyParameters() - ->willReturn( $this->moduleMock ); + $this->container_mock->expects( $this->exactly( 6 ) ) + ->method( 'get' ) + ->withAnyParameters() + ->willReturn( $this->module_mock ); $this->wpMockFunction( 'trailingslashit', [ - WP_Mock\Functions::type( 'string' ) + WP_Mock\Functions::type( 'string' ), ], 3, 'slashedstring/' @@ -222,7 +226,7 @@ public function testAssetsDirPath() { $this->wpMockFunction( 'plugin_dir_url', [ - 'slashedstring/login-with-google.php' + 'slashedstring/login-with-google.php', ] ); @@ -237,15 +241,16 @@ public function testAssetsDirPath() { * @covers ::run */ public function testHooksAddedOnRun() { - $this->containerMock->expects( $this->exactly( 6 ) ) - ->method( 'get' ) - ->withAnyParameters() - ->willReturn( $this->moduleMock ); + + $this->container_mock->expects( $this->exactly( 6 ) ) + ->method( 'get' ) + ->withAnyParameters() + ->willReturn( $this->module_mock ); $this->wpMockFunction( 'trailingslashit', [ - WP_Mock\Functions::type( 'string' ) + WP_Mock\Functions::type( 'string' ), ], 3, 'slashedstring/' @@ -254,7 +259,7 @@ public function testHooksAddedOnRun() { $this->wpMockFunction( 'plugin_dir_url', [ - 'slashedstring/login-with-google.php' + 'slashedstring/login-with-google.php', ] ); @@ -272,11 +277,11 @@ public function testHooksAddedOnRun() { */ public function testLoadTranslation() { - $this->moduleMock->expects( $this->never() ) - ->method( 'init' ); + $this->module_mock->expects( $this->never() ) + ->method( 'init' ); - $this->containerMock->expects( $this->never() ) - ->method( 'define_services' ); + $this->container_mock->expects( $this->never() ) + ->method( 'define_services' ); $this->wpMockFunction( 'get_locale', @@ -301,7 +306,7 @@ function () { [ 'login-with-google', false, - 'path-to-test/languages/en_US' + 'path-to-test/languages/en_US', ] ); @@ -316,6 +321,6 @@ function () { public function testContainer() { $container = $this->testee->container(); - $this->assertSame( $container, $this->containerMock ); + $this->assertSame( $container, $this->container_mock ); } } diff --git a/tests/php/Unit/Utils/AuthenticatorTest.php b/tests/php/Unit/Utils/AuthenticatorTest.php index 0c56f6ca..8284031e 100644 --- a/tests/php/Unit/Utils/AuthenticatorTest.php +++ b/tests/php/Unit/Utils/AuthenticatorTest.php @@ -35,20 +35,22 @@ class AuthenticatorTest extends TestCase { /** * @var Settings */ - private $settingsMock; + private $settings_mock; /** * @return void */ public function setUp(): void { - $this->settingsMock = $this->createMock( Settings::class ); - $this->testee = new Testee( $this->settingsMock ); + + $this->settings_mock = $this->createMock( Settings::class ); + $this->testee = new Testee( $this->settings_mock ); } /** * @covers ::__construct */ public function testInstance() { + $this->assertInstanceOf( Testee::class, $this->testee ); } @@ -56,8 +58,9 @@ public function testInstance() { * @covers ::authenticate */ public function testAuthenticateException() { + $user = [ - 'name' => 'Test' + 'name' => 'Test', ]; $user = (object) $user; @@ -132,11 +135,11 @@ public function testAuthenticateFilterApplied() { 'test' ); - $helperMock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'unique_username' ) - ->once() - ->withArgs( ['test'] ); + $helper_mock->expects( 'unique_username' ) + ->once() + ->withArgs( [ 'test' ] ); WP_Mock::onFilter( 'rtcamp.google_register_user' )->with( $user )->reply( $wp_user ); @@ -148,7 +151,7 @@ public function testAuthenticateFilterApplied() { * @covers ::register */ public function testRegisterThrowsExceptionForRegistrationDisabled() { - $this->settingsMock->registration_enabled = false; + $this->settings_mock->registration_enabled = false; $this->wpMockFunction( 'get_option', @@ -169,12 +172,14 @@ public function testRegisterThrowsExceptionForRegistrationDisabled() { * @covers ::register */ public function testRegisterThrowsExceptionForInvalidEmailDomain() { - $user = (object) [ + + $user = (object) [ 'email' => 'test@example.com', 'login' => 'test', ]; - $this->settingsMock->registration_enabled = true; - $this->settingsMock->whitelisted_domains = 'somedomain.com'; + + $this->settings_mock->registration_enabled = true; + $this->settings_mock->whitelisted_domains = 'somedomain.com'; $this->expectException( \Exception::class ); $this->testee->register( $user ); @@ -185,19 +190,20 @@ public function testRegisterThrowsExceptionForInvalidEmailDomain() { * @covers ::can_register_with_email */ public function testRegisterReturnsUserObject() { + $user = (object) [ 'email' => 'test@example.com', 'login' => 'test', ]; - $this->settingsMock->registration_enabled = true; - $this->settingsMock->whitelisted_domains = 'example.com,somedomain.com'; + $this->settings_mock->registration_enabled = true; + $this->settings_mock->whitelisted_domains = 'example.com,somedomain.com'; - $helperMock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'unique_username' ) - ->once() - ->withArgs( ['test'] ) - ->andReturn( 'test' ); + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'unique_username' ) + ->once() + ->withArgs( [ 'test' ] ) + ->andReturn( 'test' ); $this->wpMockFunction( 'wp_generate_password', @@ -215,7 +221,7 @@ public function testRegisterReturnsUserObject() { 'user_email' => 'test@example.com', 'first_name' => '', 'last_name' => '', - ] + ], ], 1, 100 @@ -246,20 +252,21 @@ public function testRegisterReturnsUserObject() { * @covers ::can_register_with_email */ public function testRegisterReturnsUserObjectWithFirstNameOnly() { + $user = (object) [ 'email' => 'test@example.com', 'login' => 'test', 'given_name' => 'Test', ]; - $this->settingsMock->registration_enabled = true; - $this->settingsMock->whitelisted_domains = 'example.com,somedomain.com'; + $this->settings_mock->registration_enabled = true; + $this->settings_mock->whitelisted_domains = 'example.com,somedomain.com'; - $helperMock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'unique_username' ) - ->once() - ->withArgs( ['test'] ) - ->andReturn( 'test' ); + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'unique_username' ) + ->once() + ->withArgs( [ 'test' ] ) + ->andReturn( 'test' ); $this->wpMockFunction( 'wp_generate_password', @@ -277,7 +284,7 @@ public function testRegisterReturnsUserObjectWithFirstNameOnly() { 'user_email' => 'test@example.com', 'first_name' => 'Test', 'last_name' => '', - ] + ], ], 1, 100 @@ -308,6 +315,7 @@ public function testRegisterReturnsUserObjectWithFirstNameOnly() { * @covers ::can_register_with_email */ public function testRegisterReturnsUserObjectWithFirstLastName() { + $user = (object) [ 'email' => 'test@example.com', 'login' => 'test', @@ -315,14 +323,14 @@ public function testRegisterReturnsUserObjectWithFirstLastName() { 'family_name' => 'User', ]; - $this->settingsMock->registration_enabled = true; - $this->settingsMock->whitelisted_domains = 'example.com,somedomain.com'; + $this->settings_mock->registration_enabled = true; + $this->settings_mock->whitelisted_domains = 'example.com,somedomain.com'; - $helperMock = Mockery::mock( 'alias:' . Helper::class ); - $helperMock->expects( 'unique_username' ) - ->once() - ->withArgs( ['test'] ) - ->andReturn( 'test' ); + $helper_mock = Mockery::mock( 'alias:' . Helper::class ); + $helper_mock->expects( 'unique_username' ) + ->once() + ->withArgs( [ 'test' ] ) + ->andReturn( 'test' ); $this->wpMockFunction( 'wp_generate_password', @@ -340,7 +348,7 @@ public function testRegisterReturnsUserObjectWithFirstLastName() { 'user_email' => 'test@example.com', 'first_name' => 'Test', 'last_name' => 'User', - ] + ], ], 1, 100 @@ -370,6 +378,7 @@ public function testRegisterReturnsUserObjectWithFirstLastName() { * @covers ::set_auth_cookies */ public function testSetAuthCookies() { + $wp_user = Mockery::mock( \WP_User::class ); $wp_user->ID = 100; $wp_user->user_login = 'test'; @@ -392,7 +401,7 @@ public function testSetAuthCookies() { $this->wpMockFunction( 'wp_set_auth_cookie', [ - 100 + 100, ], 1 ); diff --git a/tests/php/Unit/Utils/GoogleClientTest.php b/tests/php/Unit/Utils/GoogleClientTest.php index 8a3b24bb..9e4a6d86 100644 --- a/tests/php/Unit/Utils/GoogleClientTest.php +++ b/tests/php/Unit/Utils/GoogleClientTest.php @@ -32,16 +32,20 @@ class GoogleClientTest extends TestCase { * @return void */ public function setUp(): void { - $this->testee = new Testee( [ - 'client_id' => 'cid', - 'client_secret' => 'csc', - ] ); + + $this->testee = new Testee( + [ + 'client_id' => 'cid', + 'client_secret' => 'csc', + ] + ); } /** * @covers ::__construct */ public function testConstruct() { + $this->assertSame( 'cid', $this->getTesteeProperty( 'client_id', $this->testee ) ); $this->assertSame( 'csc', $this->getTesteeProperty( 'client_secret', $this->testee ) ); $this->assertSame( '', $this->getTesteeProperty( 'redirect_uri', $this->testee ) ); @@ -51,6 +55,7 @@ public function testConstruct() { * @covers ::__call */ public function testCallWithUser() { + $this->expectException( Exception::class ); $this->testee->__call( 'user', null ); } @@ -59,6 +64,7 @@ public function testCallWithUser() { * @covers ::__call */ public function testCallWithEmails() { + $this->expectException( Exception::class ); $this->testee->__call( 'emails', null ); } @@ -68,6 +74,7 @@ public function testCallWithEmails() { * @covers ::gt_redirect_url */ public function testCallWithOtherMethods() { + WP_Mock::expectFilterNotAdded( 'rtcamp.github_redirect_url', '' ); $this->testee->__call( 'some_other_method', null ); @@ -81,6 +88,7 @@ public function testCallWithOtherMethods() { * @covers ::access_token */ public function testSetAccessToken() { + WP_Mock::expectFilter( 'rtcamp.google_redirect_url', '' ); $this->wpMockFunction( @@ -98,7 +106,7 @@ public function testSetAccessToken() { 'code' => 'abc', 'grant_type' => 'authorization_code', ], - ] + ], ], 1, 'response' @@ -107,7 +115,7 @@ public function testSetAccessToken() { $this->wpMockFunction( 'wp_remote_retrieve_response_code', [ - 'response' + 'response', ], 1, 200 @@ -121,13 +129,13 @@ public function testSetAccessToken() { 1, function() { $token = (object) [ - 'access_token' => 'AccessToken' + 'access_token' => 'AccessToken', ]; - return json_encode( $token ); + return wp_json_encode( $token ); } ); - $obj = $this->testee->set_access_token( 'abc' ); + $obj = $this->testee->set_access_token( 'abc' ); $token = $this->getTesteeProperty( 'access_token', $this->testee ); $this->assertSame( $this->testee, $obj ); @@ -139,6 +147,7 @@ function() { * @covers ::set_access_token */ public function testSetAccessTokenThrowsException() { + WP_Mock::expectFilter( 'rtcamp.google_redirect_url', '' ); $this->wpMockFunction( @@ -156,7 +165,7 @@ public function testSetAccessTokenThrowsException() { 'code' => 'abc', 'grant_type' => 'authorization_code', ], - ] + ], ], 1, 'response' @@ -165,7 +174,7 @@ public function testSetAccessTokenThrowsException() { $this->wpMockFunction( 'wp_remote_retrieve_response_code', [ - 'response' + 'response', ], 1, 400 @@ -179,11 +188,12 @@ public function testSetAccessTokenThrowsException() { * @covers ::access_token */ public function testAccessTokenThrowsExceptionForNon200Code() { - $ghClient = $this->createPartialMock( Testee::class, [ 'gt_redirect_url' ] ); - $ghClient->expects( $this->once() )->method( 'gt_redirect_url' )->willReturn( '' ); - $ghClient->client_id = 'cid'; - $ghClient->client_secret = 'csc'; + $gh_client = $this->createPartialMock( Testee::class, [ 'gt_redirect_url' ] ); + $gh_client->expects( $this->once() )->method( 'gt_redirect_url' )->willReturn( '' ); + + $gh_client->client_id = 'cid'; + $gh_client->client_secret = 'csc'; $this->wpMockFunction( 'wp_remote_post', @@ -200,7 +210,7 @@ public function testAccessTokenThrowsExceptionForNon200Code() { 'code' => 'abc', 'grant_type' => 'authorization_code', ], - ] + ], ], 1, 'response' @@ -209,26 +219,27 @@ public function testAccessTokenThrowsExceptionForNon200Code() { $this->wpMockFunction( 'wp_remote_retrieve_response_code', [ - 'response' + 'response', ], 1, 400 ); $this->expectException( Exception::class ); - $ghClient->access_token( 'abc' ); + $gh_client->access_token( 'abc' ); } /** * @covers ::user */ public function testUserReturnsObject() { + $this->setTesteeProperty( $this->testee, 'access_token', 'someToken' ); $this->wpMockFunction( 'trailingslashit', [ - 'https://www.googleapis.com' + 'https://www.googleapis.com', ], 1, 'https://www.googleapis.com/' @@ -242,7 +253,7 @@ public function testUserReturnsObject() { 'headers' => [ 'Accept' => 'application/json', ], - ] + ], ], 1, 'response' @@ -251,7 +262,7 @@ public function testUserReturnsObject() { $this->wpMockFunction( 'wp_remote_retrieve_response_code', [ - 'response' + 'response', ], 1, 200 @@ -268,11 +279,12 @@ function() { 'email' => 'user@domain.com', 'login' => 'login', ]; - return json_encode( $token ); + return wp_json_encode( $token ); } ); $user = $this->testee->user(); + $this->assertInstanceOf( \stdClass::class, $user ); $this->assertSame( $user->email, 'user@domain.com' ); $this->assertSame( $user->login, 'login' ); @@ -283,12 +295,13 @@ function() { * @covers ::user */ public function testUserThrowsException() { + $this->setTesteeProperty( $this->testee, 'access_token', 'someToken' ); $this->wpMockFunction( 'trailingslashit', [ - 'https://www.googleapis.com' + 'https://www.googleapis.com', ], 1, 'https://www.googleapis.com/' @@ -302,7 +315,7 @@ public function testUserThrowsException() { 'headers' => [ 'Accept' => 'application/json', ], - ] + ], ], 1, 'response' @@ -311,7 +324,7 @@ public function testUserThrowsException() { $this->wpMockFunction( 'wp_remote_retrieve_response_code', [ - 'response' + 'response', ], 1, 404 @@ -325,12 +338,16 @@ public function testUserThrowsException() { * @covers ::authorization_url */ public function testAuthorizationURL() { + $scope = [ 'email', 'profile', 'openid' ]; + WP_Mock::onFilter( 'rtcamp.google_scope' )->with( $scope )->reply( $scope ); - $ghClient = $this->createPartialMock( Testee::class, [ 'gt_redirect_url', 'state' ] ); - $ghClient->expects( $this->once() )->method( 'gt_redirect_url' )->willReturn( '' ); - $ghClient->expects( $this->once() )->method( 'state' )->willReturn( 'abcd' ); - $ghClient->client_id = 'cid'; + + $gh_client = $this->createPartialMock( Testee::class, [ 'gt_redirect_url', 'state' ] ); + $gh_client->expects( $this->once() )->method( 'gt_redirect_url' )->willReturn( '' ); + $gh_client->expects( $this->once() )->method( 'state' )->willReturn( 'abcd' ); + + $gh_client->client_id = 'cid'; $client_args = [ 'client_id' => 'cid', @@ -345,6 +362,6 @@ public function testAuthorizationURL() { $expected = 'https://accounts.google.com/o/oauth2/auth?client_id=cid&redirect_uri=&state=abcd&scope=email+profile+openid&access_type=online&response_type=code'; - $this->assertSame( $expected, $ghClient->authorization_url() ); + $this->assertSame( $expected, $gh_client->authorization_url() ); } } diff --git a/tests/php/Unit/Utils/TokenVerifierTest.php b/tests/php/Unit/Utils/TokenVerifierTest.php index 1ed359b8..9875798d 100644 --- a/tests/php/Unit/Utils/TokenVerifierTest.php +++ b/tests/php/Unit/Utils/TokenVerifierTest.php @@ -35,24 +35,27 @@ class TokenVerifierTest extends TestCase { /** * @var Settings */ - private $settingsMock; + private $settings_mock; /** * @return void */ public function setUp(): void { - $this->settingsMock = $this->createMock( Settings::class ); - $this->testee = new Testee( $this->settingsMock ); + + $this->settings_mock = $this->createMock( Settings::class ); + $this->testee = new Testee( $this->settings_mock ); } /** * @covers ::__construct */ public function testInstance() { + $this->assertInstanceOf( Testee::class, $this->testee ); } public function testCertsURL() { + $this->assertSame( 'https://www.googleapis.com/oauth2/v1/certs', $this->testee::CERTS_URL ); } @@ -60,9 +63,11 @@ public function testCertsURL() { * @covers ::get_supported_algorithm */ public function testGetSupportedAlgorithmDefault() { + \WP_Mock::expectFilter( 'rtcamp.default_algorithm', OPENSSL_ALGO_SHA256, '' ); + $expected = OPENSSL_ALGO_SHA256; - $algo = $this->testee::get_supported_algorithm(); + $algo = $this->testee::get_supported_algorithm(); $this->assertSame( $expected, $algo ); } @@ -71,8 +76,9 @@ public function testGetSupportedAlgorithmDefault() { * @covers ::get_supported_algorithm */ public function testGetSHA256Algo() { + $expected = OPENSSL_ALGO_SHA256; - $algo = $this->testee::get_supported_algorithm( 'RS256' ); + $algo = $this->testee::get_supported_algorithm( 'RS256' ); $this->assertSame( $expected, $algo ); } @@ -81,6 +87,7 @@ public function testGetSHA256Algo() { * @covers ::base64_encode_url */ public function testBase64EncodeURL() { + $str = 'some+random/string='; $result = $this->testee->base64_encode_url( $str ); @@ -91,6 +98,7 @@ public function testBase64EncodeURL() { * @covers ::base64_decode_url */ public function testBase64DecodeURL() { + $str = 'c29tZStyYW5kb20vc3RyaW5nPQ'; $result = $this->testee->base64_decode_url( $str ); @@ -101,9 +109,11 @@ public function testBase64DecodeURL() { * @covers ::current_user */ public function testCurrentUser() { + $wp_user = (object) [ 'name' => 'Test', ]; + $this->setTesteeProperty( $this->testee, 'current_user', $wp_user ); $result = $this->testee->current_user(); @@ -114,6 +124,7 @@ public function testCurrentUser() { * @covers ::get_public_key */ public function testPublicKeyIsNull() { + $pk = $this->testee->get_public_key( null ); $this->assertNull( $pk ); @@ -123,10 +134,11 @@ public function testPublicKeyIsNull() { * @covers ::get_public_key */ public function testPublicKeyCachedValue() { + $this->wpMockFunction( 'get_transient', [ - 'lwg_pk_my_public_key' + 'lwg_pk_my_public_key', ], 1, 'abcd' @@ -141,10 +153,11 @@ public function testPublicKeyCachedValue() { * @covers ::get_public_key */ public function testPublicKeyIsNullForNon200Response() { + $this->wpMockFunction( 'get_transient', [ - 'lwg_pk_my_public_key' + 'lwg_pk_my_public_key', ], 1, null @@ -153,7 +166,7 @@ public function testPublicKeyIsNullForNon200Response() { $this->wpMockFunction( 'wp_remote_get', [ - $this->testee::CERTS_URL + $this->testee::CERTS_URL, ], 1, 'certificate' @@ -178,10 +191,11 @@ public function testPublicKeyIsNullForNon200Response() { * @covers ::get_max_age */ public function testPublicKeyRetrievalFromResponse() { + $this->wpMockFunction( 'get_transient', [ - 'lwg_pk_my_public_key' + 'lwg_pk_my_public_key', ], 1, null @@ -190,7 +204,7 @@ public function testPublicKeyRetrievalFromResponse() { $this->wpMockFunction( 'wp_remote_get', [ - $this->testee::CERTS_URL + $this->testee::CERTS_URL, ], 1, 'certificate' @@ -206,6 +220,7 @@ public function testPublicKeyRetrievalFromResponse() { ); $headers = \Mockery::mock( \Requests_Utility_CaseInsensitiveDictionary::class ); + $headers->expects( 'offsetExists' )->withArgs( [ 'cache-control' ] )->andReturn( true ); $headers->expects( 'offsetGet' )->withArgs( [ 'cache-control' ] )->andReturn( 'public, max-age=600' ); @@ -213,7 +228,7 @@ public function testPublicKeyRetrievalFromResponse() { 'my_public_key' => 'thisissomerandomkey', ]; - $body = json_encode( $body ); + $body = wp_json_encode( $body ); $this->wpMockFunction( 'wp_remote_retrieve_headers', @@ -238,13 +253,14 @@ public function testPublicKeyRetrievalFromResponse() { [ 'lwg_pk_my_public_key', 'thisissomerandomkey', - 300 + 300, ], 1, true ); $pk = $this->testee->get_public_key( 'my_public_key' ); + $this->assertSame( 'thisissomerandomkey', $pk ); $this->assertConditionsMet(); } @@ -253,12 +269,13 @@ public function testPublicKeyRetrievalFromResponse() { * @covers ::set_transient */ public function testSetTransient() { + $this->wpMockFunction( 'set_transient', [ 'key', 'val', - 200 + 200, ] ); diff --git a/tests/php/bootstrap.php b/tests/php/bootstrap.php index 112893e5..ff838cfa 100644 --- a/tests/php/bootstrap.php +++ b/tests/php/bootstrap.php @@ -8,20 +8,22 @@ * file that was distributed with this source code. */ -declare(strict_types=1); +declare( strict_types=1 ); $vendor = dirname( __DIR__, 2 ) . '/vendor/'; -if (!file_exists($vendor . 'autoload.php')) { - die('Please install via Composer before running tests.'); +if ( ! file_exists( $vendor . 'autoload.php' ) ) { + die( 'Please install via Composer before running tests.' ); } require_once __DIR__ . '/stubs/hooks.php'; require_once $vendor . 'autoload.php'; require_once __DIR__ . '/TestCase.php'; -WP_Mock::setUsePatchwork(true); + +WP_Mock::setUsePatchwork( true ); WP_Mock::bootstrap(); -unset($vendor); + +unset( $vendor ); if ( ! defined( 'GH_PLUGIN_DIR' ) ) { define( 'GH_PLUGIN_DIR', dirname( __DIR__, 2 ) ); diff --git a/tests/php/stubs/hooks.php b/tests/php/stubs/hooks.php index c530401d..490ee0bc 100644 --- a/tests/php/stubs/hooks.php +++ b/tests/php/stubs/hooks.php @@ -9,6 +9,7 @@ function remove_filter( $tag, $callback, $priority = 10, $args = 0 ) { } } if ( ! function_exists( 'apply_filters_deprecated' ) ) { + function apply_filters_deprecated( string $tag, array $args, string $version, string $replacement = '', string $message = '' ) { return $args[0] ?? []; } diff --git a/vendor/10up/wp_mock/.github/ISSUE_TEMPLATE/bug_report.md b/vendor/10up/wp_mock/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..dd84ea78 --- /dev/null +++ b/vendor/10up/wp_mock/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/vendor/10up/wp_mock/.github/ISSUE_TEMPLATE/feature_request.md b/vendor/10up/wp_mock/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..bbcbbe7d --- /dev/null +++ b/vendor/10up/wp_mock/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/vendor/10up/wp_mock/.gitignore b/vendor/10up/wp_mock/.gitignore new file mode 100644 index 00000000..f0d9f56e --- /dev/null +++ b/vendor/10up/wp_mock/.gitignore @@ -0,0 +1,7 @@ +/.idea +composer.lock +vendor/ +docs/ +.editorconfig +.phpunit.result.cache +build/ \ No newline at end of file diff --git a/vendor/10up/wp_mock/.gitmodules b/vendor/10up/wp_mock/.gitmodules new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/vendor/10up/wp_mock/.gitmodules @@ -0,0 +1 @@ + diff --git a/vendor/10up/wp_mock/.travis.yml b/vendor/10up/wp_mock/.travis.yml new file mode 100644 index 00000000..2042d80b --- /dev/null +++ b/vendor/10up/wp_mock/.travis.yml @@ -0,0 +1,44 @@ +language: php + +matrix: + include: + - php: '7.1' + env: WP_MOCK_INSTALL_LOWEST=0 + - php: '7.2' + env: WP_MOCK_INSTALL_LOWEST=0 + - php: '7.3' + env: WP_MOCK_INSTALL_LOWEST=0 + - php: nightly + env: WP_MOCK_INSTALL_LOWEST=0 + - php: '7.1' + env: WP_MOCK_INSTALL_LOWEST=1 + - php: '7.2' + env: WP_MOCK_INSTALL_LOWEST=1 + - php: '7.3' + env: WP_MOCK_INSTALL_LOWEST=1 + - php: nightly + env: WP_MOCK_INSTALL_LOWEST=1 + allow_failures: + - php: nightly + env: WP_MOCK_INSTALL_LOWEST=0 + - php: nightly + env: WP_MOCK_INSTALL_LOWEST=1 + +before_script: + - if [ 1 -eq $WP_MOCK_INSTALL_LOWEST ]; then composer update --prefer-lowest; else composer update; fi + +script: + - mkdir -p build/logs + - composer run-script coverage + +cache: + directories: + - vendor + +branches: + only: + - dev + - master + +after_success: + - travis_retry php vendor/bin/php-coveralls diff --git a/vendor/10up/wp_mock/CONTRIBUTING.md b/vendor/10up/wp_mock/CONTRIBUTING.md new file mode 100644 index 00000000..43c81513 --- /dev/null +++ b/vendor/10up/wp_mock/CONTRIBUTING.md @@ -0,0 +1,26 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. + +We accept contributions via Pull Requests on [Github](https://github.com/10up/wp_mock) + +## Branches + +* We try to follow [SemVer](http://semver.org/) in WP Mock +* The current "stable" release version lives on the **master** branch. +* If there is a current development release, it will live on a **{version}-dev** branch. + +## Pull Requests + +* New features must be submitted against the the **master** branch +* Bug fixes should be submitted against the branch in which the bug exists, which is likely **master**. +* If you're not sure whether a feature idea would be something we'd be interested in, please open an issue before you start working on it. We'd be happy to discuss your idea with you. + +## Merging + +* As of 2019, all merges to the **master** branch will be squash merges of features. +* If there are multiple features pending in a release, we will create a **{version}-dev** branch to track development against that version. Once the version is ready, that branch will be squash-merged into **master** as well. + +## Thanks + +**You're awesome** - Thanks for being interested in contributing your time and code to this project! \ No newline at end of file diff --git a/vendor/10up/wp_mock/LICENSE.md b/vendor/10up/wp_mock/LICENSE.md new file mode 100644 index 00000000..94f2d395 --- /dev/null +++ b/vendor/10up/wp_mock/LICENSE.md @@ -0,0 +1,368 @@ +WP_Mock - WordPress API Mocking Framework + +Copyright 2013-2019 by the contributors + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +This program incorporates work covered by the following copyright and +permission notices: + + WordPress - Web publishing software + + Copyright 2003-2017 by the contributors + + WordPress is released under the GPL + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. \ No newline at end of file diff --git a/vendor/10up/wp_mock/README.md b/vendor/10up/wp_mock/README.md new file mode 100644 index 00000000..c91aacc2 --- /dev/null +++ b/vendor/10up/wp_mock/README.md @@ -0,0 +1,407 @@ +# WP_Mock ![PHP 7.1+][php-image] [![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Packagist][packagist-image]][packagist-url] + +WP_Mock is an API mocking framework, built and maintained by [10up](http://10up.com) for the purpose of making it possible to properly unit test within WordPress. + + + +## Installation + +First, add WP Mock as a dev-dependency with [Composer](http://getcomposer.org): + +```bash +composer require --dev 10up/wp_mock:0.4.2 +``` + +Then, make sure your bootstrap file is loading the composer autoloader: + +```php +require_once 'vendor/autoload.php'; +``` + +Finally, register calls inside your test class to instantiate and clean up the `WP_Mock` object: + +```php +class MyTestClass extends \WP_Mock\Tools\TestCase { + public function setUp() { + \WP_Mock::setUp(); + } + + public function tearDown() { + \WP_Mock::tearDown(); + } +} +``` + +## Bootstrapping WP_Mock + +Before you can start using WP_Mock to test your code, you'll need to bootstrap the library. The easiest way is to use a bootstrap file. See the PHPUnit documentation for how to define a bootstrap script either [from the command line](https://phpunit.de/manual/current/en/textui.html#textui.clioptions) or [from the xml config file](https://phpunit.de/manual/current/en/appendixes.configuration.html). Here is an example of a bootstrap you might use: + +```php + 42, + 'times' => 1, + 'return' => 'http://example.com/foo' + ) ); + + \WP_Mock::passthruFunction( 'absint', array( 'times' => 1 ) ); + + \WP_Mock::onFilter( 'special_filter' ) + ->with( 'http://example.com/foo' ) + ->reply( 'https://example.com/bar' ); + + \WP_Mock::expectAction( 'special_action', 'https://example.com/bar' ); + + $result = my_permalink_function( 42 ); + + $this->assertEquals( 'https://example.com/bar', $result ); + } +} +``` + +The function being described by our tests would look something like this: + +```php +/** + * Get a post's permalink, then run it through special filters and trigger + * the 'special_action' action hook. + * + * @param int $post_id The post ID being linked to. + * @return str|bool The permalink or a boolean false if $post_id does + * not exist. + */ +function my_permalink_function( $post_id ) { + $permalink = get_permalink( absint( $post_id ) ); + $permalink = apply_filters( 'special_filter', $permalink ); + + do_action( 'special_action', $permalink ); + + return $permalink; +} +``` + +### Mocking WordPress core functions + +Ideally, a unit test will not depend on WordPress being loaded in order to test our code. By constructing **mocks**, it's possible to simulate WordPress core functionality by defining their expected arguments, responses, the number of times they are called, and more. In WP_Mock, this is done via the `\WP_Mock::userFunction()` method: + +```php +public function test_uses_get_post() { + global $post; + + $post = new \stdClass; + $post->ID = 42; + $post->special_meta = '

I am on the end

'; + + \WP_Mock::userFunction( 'get_post', array( + 'times' => 1, + 'args' => array( $post->ID ), + 'return' => $post, + ) ); + + /* + * Let's say our function gets the post and appends a value stored in + * 'special_meta' to the content. + */ + $results = special_the_content( '

Some content

' ); + + /* + * In addition to failing if this assertion is false, the test will fail + * if get_post is not called with the arguments above. + */ + $this->assertEquals( '

Some content

I am on the end

', $results ); +} +``` + +In the example above, we're creating a simple `\stdClass` to represent a response from `get_post()`, setting the `ID` and `special_meta` properties. WP_Mock is expecting `get_post()` to be called exactly once, with a single argument of '42', and for the function to return our `$post` object. + +With our expectations set, we call `special_the_content()`, the function we're testing, then asserting that what we get back from it is equal to `

Some content

I am on the end

`, which proves that `special_the_content()` appended `$post->special_meta` to `

Some content

`. + +Calling `\WP_Mock::userFunction()` will dynamically define the function for you if necessary, which means changes the internal WP_Mock API shouldn't break your mocks. If you really want to define your own function mocks, they should always end with this line: + +```php +return \WP_Mock\Handler::handle_function( __FUNCTION__, func_get_args() ); +``` + +#### Setting expectations + +`\WP_Mock::userFunction()` accepts an associative array of arguments for its second parameter: + +##### args + +Sets expectations about what the arguments passed to the function should be. This value should always be an array with the arguments in order and, like with return, if you use a `\Closure`, its return value will be used to validate the argument expectations. You can also indicate that the argument can be any value of any type by using '`*`'. + +WP_Mock has several helper functions to make this feature more flexible. The are static methods on the `\WP_Mock\Functions` class. They are: + +* `Functions::type( $type )`: Expects an argument of a certain type. This can be any core PHP data type (`string`, `int`, `resource`, `callable`, etc.) or any class or interface name. +* `Functions::anyOf( $values )`: Expects the argument to be any value in the `$values` array. + +###### Examples + +In the following example, we're expecting `get_post_meta()` twice: once each for `some_meta_key` and `another_meta_key`, where an integer (in this case, a post ID) is the first argument, the meta key is the second, and a boolean TRUE is the third. + +```php +\WP_Mock::userFunction( 'get_post_meta', array( + 'times' => 1, + 'args' => array( \WP_Mock\Functions::type( 'int' ), 'some_meta_key', true ) +) ); + +\WP_Mock::userFunction( 'get_post_meta', array( + 'times' => 1, + 'args' => array( \WP_Mock\Functions::type( 'int' ), 'another_meta_key', true ) +) ); +``` + +##### times + +Declares how many times the given function should be called. For an exact number of calls, use a non-negative, numeric value (e.g. `3`). If the function should be called a minimum number of times, append a plus-sign (`+`, e.g. `7+` for seven or more calls). Conversely, if a mocked function should have a maximum number of invocations, append a minus-sign (`-`) to the argument (e.g. `7-` for seven or fewer times). + +You may also choose to specify a range, e.g. `3-6` would translate to "this function should be called between three and six times". + +The default value for `times` is `0+`, meaning the function should be called any number of times. + +##### return + +Defines the value (if any) that the function should return. If you pass a `\Closure` as the return value, the function will return whatever the Closure's return value is. + +##### return_in_order + +Set an array of values that should be returned with each subsequent call, useful if if your function will be called multiple times in the test but needs to return different values. + +**Note:** Setting this value overrides whatever may be set `return`. + +###### Example + +```php +\WP_Mock::userFunction( 'is_single', array( + 'return_in_order' => array( true, false ) +) ); + +$this->assertTrue( is_single() ); +$this->assertFalse( is_single() ); +$this->assertFalse( is_single() ); // All subsequent calls will use the last defined return value +``` +##### return_arg + +Use this to specify that the function should return one of its arguments. `return_arg` should be the position of the argument in the arguments array, so `0` for the first argument, `1` for the second, etc. You can also set this to `true`, which is equivalent to `0`. This will override both `return` and `return_in_order`. + +### Using Mockery expectations + +The return value of `\WP_Mock::userFunction` will be a complete `Mockery\Mock` object with any expectations added to match the arguments passed to the function. This enables using [Mockery methods](http://docs.mockery.io/en/latest/reference/expectations.html) to add expectations in addition to, or instead of using the arguments array passed to `userFunction`. + +For example, the following are synonymous: + +```php +\WP_Mock::userFunction( 'get_permalink', array( 'args' => 42, 'return' => 'http://example.com/foo' ) ); +``` + +```php +\WP_Mock::userFunction( 'get_permalink' )->with( 42 )->andReturn( 'http://example.com/foo' ); +``` + +### Passthru functions + +It's not uncommon for tests to need to declare "passthrough/passthru" functions: empty functions that just return whatever they're passed (remember: you're testing your code, not the framework). In these situations you can use `\WP_Mock::passthruFunction( 'function_name' )`, which is equivalent to the following: + +```php +\WP_Mock::userFunction( 'function_name', array( + 'return_arg' => 0 +) ); +``` + +You can still test things like invocation count by passing the `times` argument in the second parameter, just like `\WP_Mock::userFunction()`. + +### Deprecated methods + +Please note that `WP_Mock::wpFunction()` and `WP_Mock::wpPassthruFunction()` are both officially deprecated. Replace all uses of them with `WP_Mock::userFunction()` and `WP_Mock::passthruFunction()`. If you use either of the deprecated methods, WP_Mock will mark those tests as risky. Your tests will still count as passing, but PHPUnit will start telling you which tests are causing issues. + +### Mocking actions and filters + +The [hooks and filters of the WordPress Plugin API](http://codex.wordpress.org/Plugin_API) are common (and preferred) entry points for third-party scripts, and WP_Mock makes it easy to test that these are being registered and executed within your code. + +#### Ensuring actions and filters are registered + +Rather than attempting to mock `add_action()` or `add_filter()`, WP_Mock has built-in support for both of these functions: instead, use `\WP_Mock::expectActionAdded()` and `\WP_Mock::expectFilterAdded()` (respectively). In the following example, our `test_special_function()` test will fail if `special_function()` doesn't call `add_action( 'save_post', 'special_save_post', 10, 2 )` _and_ `add_filter( 'the_content', 'special_the_content' )`: + +```php +public function test_special_function() { + \WP_Mock::expectActionAdded( 'save_post', 'special_save_post', 10, 2 ); + \WP_Mock::expectFilterAdded( 'the_content', 'special_the_content' ); + + special_function(); +} +``` + +It's important to note that the `$priority` and `$parameter_count` arguments (parameters 3 and 4 for both `add_action()` and `add_filter()`) are significant. If `special_function()` were to call `add_action( 'save_post', 'special_save_post', 99, 3 )` instead of the expected `add_action( 'save_post', 'special_save_post', 10, 2 )`, our test would fail. + +#### Asserting that actions and filters are applied + +Now that we're testing whether or not we're adding actions and/or filters, the next step is to ensure our code is calling those hooks when expected. + +For actions, we'll want to listen for `do_action()` to be called for our action name, so we'll use `\WP_Mock::expectAction()`: + +```php +function test_action_calling_function () { + \WP_Mock::expectAction( 'my_action' ); + + action_calling_function(); +} +``` + +This test will fail if `action_calling_function()` doesn't call `do_action( 'my_action' )`. In situations where your code needs to trigger actions, this assertion makes sure the appropriate hooks are being triggered. + +For filters, we can inject our own response to `apply_filters()` using `\WP_Mock::onFilter()`: + +```php +public function filter_content() { + return apply_filters( 'custom_content_filter', 'This is unfiltered' ); +} + +public function test_filter_content() { + \WP_Mock::onFilter( 'custom_content_filter' ) + ->with( 'This is unfiltered' ) + ->reply( 'This is filtered' ); + + $response = $this->filter_content(); + + $this->assertEquals( 'This is filtered', $response ); +} +``` + +Alternatively, there is a method `\WP_Mock::expectFilter()` that will add a bare assertion that the filter will be applied without changing the value: + +```php +class SUT { + public function filter_content() { + $value = apply_filters( 'custom_content_filter', 'Default' ); + if ( $value === 'Default' ) { + do_action( 'default_value' ); + } + + return $value; + } +} + +class SUTTest { + public function test_filter_content() { + \WP_Mock::expectFilter( 'custom_content_filter', 'Default' ); + \WP_Mock::expectAction( 'default_value' ); + + $this->assertEquals( 'Default', (new SUT)->filter_content() ); + } +} +``` + +### Mocking WordPress objects + +Mocking calls to `wpdb`, `WP_Query`, etc. can be done using the [mockery](https://github.com/padraic/mockery) framework. While this isn't part of WP Mock itself, complex code will often need these objects and this framework will let you incorporate those into your tests. Since WP Mock requires Mockery, it should already be included as part of your install. + +#### $wpdb example + +Let's say we have a function that gets three post IDs from the database. +```php +function get_post_ids() { + global $wpdb; + return $wpdb->get_col( "select ID from {$wpdb->posts} LIMIT 3" ); +} +``` + +When we mock the `$wpdb` object, we're not performing an actual database call, only mocking the results. We need to call the `get_col` method with an SQL statement, and return three arbitrary post IDs. + +```php +use Mockery; + +function test_get_post_ids() { + global $wpdb; + + $wpdb = Mockery::mock( '\WPDB' ); + $wpdb->shouldReceive( 'get_col' ) + ->once() + ->with( "select ID from wp_posts LIMIT 3" ) + ->andReturn( array( 1, 2, 3 ) ); + $wpdb->posts = 'wp_posts'; + + $post_ids = get_post_ids(); + + $this->assertEquals( array( 1, 2, 3 ), $post_ids ); +} +``` + +## Credits + +* [Eric Mann](https://github.com/ericmann) +* [John Bloch](https://github.com/johnpbloch) +* [All Contributors](https://github.com/10up/wp_mock/graphs/contributors) + +## Contributing + +Thanks so much for being interested in contributing! Please read over our [guidelines](https://github.com/10up/wp_mock/blob/dev/CONTRIBUTING.md) before you get started. + +[php-image]: https://img.shields.io/badge/php-7.1%2B-green.svg +[packagist-image]: https://img.shields.io/packagist/dt/10up/wp_mock.svg +[packagist-url]: https://packagist.org/packages/10up/wp_mock +[travis-image]: https://travis-ci.org/10up/wp_mock.svg?branch=master +[travis-url]: https://travis-ci.org/10up/wp_mock +[coveralls-image]: https://coveralls.io/repos/github/10up/wp_mock/badge.svg?branch=master +[coveralls-url]: https://coveralls.io/github/10up/wp_mock?branch=master diff --git a/vendor/10up/wp_mock/behat.yml b/vendor/10up/wp_mock/behat.yml new file mode 100644 index 00000000..44bcae1e --- /dev/null +++ b/vendor/10up/wp_mock/behat.yml @@ -0,0 +1,9 @@ +default: + suites: + default: + contexts: + - FeatureContext + - HooksContext + - FunctionsContext + formatters: + progress: true diff --git a/vendor/10up/wp_mock/bootstrap.php.dist b/vendor/10up/wp_mock/bootstrap.php.dist new file mode 100644 index 00000000..7bb24406 --- /dev/null +++ b/vendor/10up/wp_mock/bootstrap.php.dist @@ -0,0 +1,5 @@ +=7.1", + "phpunit/phpunit" : ">=7.0", + "mockery/mockery" : "^1.0", + "antecedent/patchwork": "^2.1" + }, + "require-dev": { + "behat/behat" : "^3.0", + "sebastian/comparator": ">=1.2.3", + "php-coveralls/php-coveralls": "^2.1" + }, + "autoload" : { + "psr-4" : {"WP_Mock\\": "./php/WP_Mock"}, + "classmap": ["php/WP_Mock.php"] + }, + "scripts": { + "test:behat" : "behat", + "test:phpunit" : "phpunit", + "test:phpunitcov": "phpunit --coverage-clover build/logs/clover.xml", + "test" : [ + "@test:behat", + "@test:phpunit" + ], + "coverage" : [ + "@test:behat", + "@test:phpunitcov" + ] + } +} diff --git a/vendor/10up/wp_mock/features/bootstrap/FeatureContext.php b/vendor/10up/wp_mock/features/bootstrap/FeatureContext.php new file mode 100644 index 00000000..8d02f6e3 --- /dev/null +++ b/vendor/10up/wp_mock/features/bootstrap/FeatureContext.php @@ -0,0 +1,88 @@ +setAccessible( true ); + $property->setValue( true ); + } + + /** + * @AfterScenario @strictmode + */ + public function ensureStrictModeOff() { + self::forceStrictModeOff(); + } + + public static function forceStrictModeOff() { + $property = new ReflectionProperty( 'WP_Mock', '__strict_mode' ); + $property->setAccessible( true ); + $property->setValue( false ); + } + + /** + * @Then tearDown should not fail + */ + public function teardownShouldNotFail() { + WP_Mock::tearDown(); + } + + /** + * @When I do nothing + */ + public function iDoNothing() { + // Move along... + } + + /** + * @Then tearDown should fail + */ + public function teardownShouldFail() { + try { + $this->teardownShouldNotFail(); + throw new \PHPUnit\Framework\ExpectationFailedException( 'WP_Mock Teardown should have failed!' ); + } catch ( \Mockery\Exception\InvalidCountException $e ) { + // Move along + } + } +} diff --git a/vendor/10up/wp_mock/features/bootstrap/FunctionsContext.php b/vendor/10up/wp_mock/features/bootstrap/FunctionsContext.php new file mode 100644 index 00000000..8dd3bc8d --- /dev/null +++ b/vendor/10up/wp_mock/features/bootstrap/FunctionsContext.php @@ -0,0 +1,127 @@ + $args->getRow( 0 ), + ) ); + } + + /** + * @Given I mock function :function to return :value + */ + public function iMockFunctionToReturn( $function, $value ) { + WP_Mock::userFunction( $function, array( 'return' => $value ) ); + } + + /** + * @Given I alias :alias to :function + */ + public function iAliasTo( $alias, $function ) { + WP_Mock::alias( $alias, $function ); + } + + /** + * @Given I mock function :function to echo input + */ + public function iMockFunctionWpMockTestToEcho( $function ) { + WP_Mock::echoFunction( $function ); + } + + /** + * @Given strict mode is on + */ + public function strictModeIsOn() { + FeatureContext::forceStrictModeOn(); + \PHPUnit\Framework\Assert::assertTrue( WP_Mock::strictMode() ); + } + + /** + * @Given strict mode is off + */ + public function strictModeIsOff() { + FeatureContext::forceStrictModeOff(); + \PHPUnit\Framework\Assert::assertFalse( WP_Mock::strictMode() ); + } + + /** + * @When I mock function :function + */ + public function iMockFunction( $function ) { + WP_Mock::userFunction( $function ); + } + + /** + * @When I tear down the test + */ + public function iTearDownTheTest() { + WP_Mock::tearDown(); + } + + /** + * @Then function :function should exist + */ + public function functionShouldExist( $function ) { + \PHPUnit\Framework\Assert::assertTrue( function_exists( $function ) ); + } + + /** + * @Then I expect :return when I run :function with args: + */ + public function iExpectWhenIRunWithArgs( $return, $function, TableNode $args ) { + \PHPUnit\Framework\Assert::assertEquals( $return, call_user_func_array( $function, $args->getRow( 0 ) ) ); + } + + /** + * @Then I expect :return when I run :function + */ + public function iExcpectWhenIRun( $return, $function ) { + $this->iExpectWhenIRunWithArgs( $return, $function, new TableNode( array( array() ) ) ); + } + + /** + * @Then I expect an error when I run :function with args: + */ + public function iExpectAnErrorWhenIRunWithArgs( $function, TableNode $args ) { + try { + $this->iExpectWhenIRunWithArgs( null, $function, $args ); + } catch ( NoMatchingExpectationException $e ) { + // Move along... + } catch ( \PHPUnit\Framework\ExpectationFailedException $e ) { + // Move along... + } + } + + /** + * @Then I expect function :function to echo :input + */ + public function iExpectFunctionToEcho( $function, $input ) { + ob_start(); + $function( $input ); + $output = trim( ob_get_clean() ); + \PHPUnit\Framework\Assert::assertEquals( trim( $input ), $output ); + } + + /** + * @Then Nothing happens when I run function :function + */ + public function iRunFunction( $function ) { + $function(); + } + +} diff --git a/vendor/10up/wp_mock/features/bootstrap/HooksContext.php b/vendor/10up/wp_mock/features/bootstrap/HooksContext.php new file mode 100644 index 00000000..ac0d4be4 --- /dev/null +++ b/vendor/10up/wp_mock/features/bootstrap/HooksContext.php @@ -0,0 +1,235 @@ +filterResults = array(); + } + + /** + * @AfterScenario + */ + public function tearDownWpMock( AfterScenarioScope $scope ) { + $this->filterResults = array(); + } + + /** + * @Given I expect the following actions added: + */ + public function iExpectTheFollowingActionsAdded( TableNode $table ) { + foreach ( $this->getActionsWithDefaults( $table ) as $action ) { + WP_Mock::expectActionAdded( + $action['action'], + $action['callback'], + $action['priority'], + $action['arguments'] + ); + } + } + + /** + * @Given I expect the following actions not to be added: + */ + public function iExpectTheFollowingActionsNotToBeAdded( TableNode $table ) { + foreach ( $this->getActionsWithDefaults( $table ) as $action ) { + WP_Mock::expectActionNotAdded( $action['action'], $action['callback'] ); + } + } + + /** + * @Given I expect the :action action + */ + public function iExpectTheAction( $action ) { + $this->iExpectTheActionWith( $action, new TableNode( array() ) ); + } + + /** + * @When I expect the :action action with: + */ + public function iExpectTheActionWith( $action, TableNode $table ) { + $args = array( $action ); + $rows = $table->getRows(); + if ( isset( $rows[0] ) && is_array( $rows[0] ) ) { + $args = array_merge( $args, $rows[0] ); + } + call_user_func_array( array( 'WP_Mock', 'expectAction' ), $args ); + } + + /** + * @Given I expect the :filter filter with :value + */ + public function iExpectTheFilterWith( $filter, $value ) { + $this->iExpectTheFilterWithValues( $filter, new TableNode( array( array( $value ) ) ) ); + } + + /** + * @When I expect the :filter filter with: + */ + public function iExpectTheFilterWithValues( $filter, TableNode $table ) { + $args = array( $filter ); + $rows = $table->getRows(); + if ( isset( $rows[0] ) && is_array( $rows[0] ) ) { + $args = array_merge( $args, $rows[0] ); + } + call_user_func_array( array( 'WP_Mock', 'expectFilter' ), $args ); + } + + /** + * @When I add the following actions: + */ + public function iAddTheFollowingActions( TableNode $table ) { + foreach ( $this->getActionsWithDefaults( $table ) as $action ) { + add_action( + $action['action'], + $action['callback'], + $action['priority'], + $action['arguments'] + ); + } + } + + /** + * @When I do the :action action + */ + public function iDoTheAction( $action ) { + $this->iDoTheActionWith( $action, new TableNode( array() ) ); + } + + /** + * @When I do the :action action with: + */ + public function iDoTheActionWith( $action, TableNode $table ) { + $args = array( $action ); + $rows = $table->getRows(); + if ( isset( $rows[0] ) && is_array( $rows[0] ) ) { + $args = array_merge( $args, $rows[0] ); + } + call_user_func_array( 'do_action', $args ); + } + + /** + * @Given I expect the following filters added: + */ + public function iExpectTheFollowingFiltersAdded( TableNode $table ) { + $filters = $table->getHash(); + $defaults = array( + 'filter' => '', + 'callback' => '', + 'priority' => 10, + 'arguments' => 1, + ); + foreach ( $filters as $filter ) { + $filter += $defaults; + WP_Mock::expectFilterAdded( + $filter['filter'], + $filter['callback'], + $filter['priority'], + $filter['arguments'] + ); + } + } + + /** + * @Given I expect the following filters not to be added: + */ + public function iExpectTheFollowingFiltersNotToBeAdded( TableNode $table ) { + foreach ( $this->getFiltersWithDefaults( $table ) as $filter ) { + WP_Mock::expectFilterNotAdded( $filter['filter'], $filter['callback'] ); + } + } + + /** + * @When I add the following filters: + */ + public function iAddTheFollowingFilters( TableNode $table ) { + foreach ( $this->getFiltersWithDefaults( $table ) as $filter ) { + add_filter( + $filter['filter'], + $filter['callback'], + $filter['priority'], + $filter['arguments'] + ); + } + } + + /** + * @Given I expect filter :filter to respond to :thing with :response + */ + public function iExpectFilterToRespondToWith( $filter, $thing, $response ) { + WP_Mock::onFilter( $filter )->with( $thing )->reply( $response ); + } + + /** + * @Given I expect filter :filter to respond with :response + */ + public function iExpectFilterToRespondWith( $filter, $response ) { + $this->iExpectFilterToRespondToWith( $filter, null, $response ); + } + + /** + * @When I apply the filter :filter with :with + */ + public function iApplyFilterWith( $filter, $with ) { + $this->iApplyFilterWithData( $filter, new TableNode( array( array( $with ) ) ) ); + } + + /** + * @When I apply the filter :filter with: + */ + public function iApplyFilterWithData( $filter, TableNode $table ) { + $row = $table->getRow( 0 ); + array_unshift( $row, $filter ); + $this->filterResults[ $filter ] = call_user_func_array( 'apply_filters', $row ); + } + + /** + * @Then The filter :filter should return :value + */ + public function theFilterShouldReturn( $filter, $value ) { + \PHPUnit\Framework\Assert::assertArrayHasKey( $filter, $this->filterResults ); + \PHPUnit\Framework\Assert::assertEquals( $this->filterResults[ $filter ], $value ); + } + + private function getActionsWithDefaults( TableNode $table ) { + $actions = $table->getHash(); + $defaults = array( + 'action' => '', + 'callback' => '', + 'priority' => 10, + 'arguments' => 1, + ); + foreach ( $actions as &$action ) { + $action += $defaults; + } + unset( $action ); + + return $actions; + } + + private function getFiltersWithDefaults( TableNode $table ) { + $filters = $table->getHash(); + $defaults = array( + 'filter' => '', + 'callback' => '', + 'priority' => 10, + 'arguments' => 1, + ); + foreach ( $filters as &$filter ) { + $filter += $defaults; + } + unset( $filter ); + + return $filters; + } + +} diff --git a/vendor/10up/wp_mock/features/function-mocks.feature b/vendor/10up/wp_mock/features/function-mocks.feature new file mode 100644 index 00000000..9e773a5d --- /dev/null +++ b/vendor/10up/wp_mock/features/function-mocks.feature @@ -0,0 +1,48 @@ +Feature: Function mocking + In order to simulate the WordPress functional API + As a developer + I need to be able to mock WordPress core functions + + Scenario: userFunction creates functions that don't exist + Given function wpMockTest does not exist + When I mock function wpMockTest + Then function wpMockTest should exist + + Scenario: Passthru function returns first argument + Given I mock passthru function wpMockPassthruTest with args: + | foobar | bazbat | + Then I expect foobar when I run wpMockPassthruTest with args: + | foobar | bazbat | + + Scenario: return value works correctly + Given I mock function wpMockTest to return "test value" + Then I expect "test value" when I run wpMockTest + + Scenario: expectations cause error on unexpected use + Given I mock passthru function wpMockTest with args: + | bazbat | foobar | + Then I expect an error when I run wpMockTest with args: + | bimbam | bobeep | + + Scenario: alias uses the provided callback when called + Given I mock function wpMockTest to return "alias test" + And I alias wpAliasTest to wpMockTest + Then I expect "alias test" when I run wpAliasTest + + Scenario: echoFunction echoes the correct output + Given I mock function wpMockTest to echo input + Then I expect function wpMockTest to echo "echo test" + + Scenario: Previously defined functions do not cause failure when called without being expected + Given strict mode is off + And I mock function wpMockStrictTest + And I tear down the test + Then Nothing happens when I run function wpMockStrictTest + + @strictmode + Scenario: Strict mode causes unexpected but previously defined functions to fail + Given strict mode is on + And I mock function wpMockTest + When I tear down the test + Then I expect an error when I run wpMockTest with args: + | | diff --git a/vendor/10up/wp_mock/features/hooks.feature b/vendor/10up/wp_mock/features/hooks.feature new file mode 100644 index 00000000..45f169a8 --- /dev/null +++ b/vendor/10up/wp_mock/features/hooks.feature @@ -0,0 +1,228 @@ +Feature: Hook mocking + In order to test common WordPress functionality + As a developer + I need to be able to mock actions and filters + + Scenario: expectActionAdded sets up expectation + Given I expect the following actions added: + | action | callback | priority | arguments | + | foobar | bazbat | 10 | 2 | + When I add the following actions: + | action | callback | priority | arguments | + | foobar | bazbat | 10 | 2 | + Then tearDown should not fail + + Scenario: expectActionAdded fails when not met + Given I expect the following actions added: + | action | callback | + | foobar | bazbat | + When I do nothing + Then tearDown should fail + + Scenario: expectActionAdded fails when argument count is different + Given I expect the following actions added: + | action | callback | priority | arguments | + | foobar | bazbat | 10 | 2 | + When I add the following actions: + | action | callback | priority | arguments | + | foobar | bazbat | 10 | 3 | + Then tearDown should fail + + Scenario: expectActionAdded fails when priority is different + Given I expect the following actions added: + | action | callback | priority | + | foobar | bazbat | 10 | + When I add the following actions: + | action | callback | priority | + | foobar | bazbat | 11 | + Then tearDown should fail + + Scenario: expectActionNotAdded fails when action added + Given I expect the following actions not to be added: + | action | callback | + | foobar | bazbat | + When I add the following actions: + | action | callback | + | foobar | bazbat | + Then tearDown should fail + + Scenario: expectActionNotAdded passes when action not added + Given I expect the following actions not to be added: + | action | callback | + | foobar | bazbat | + When I do nothing + Then tearDown should not fail + + Scenario: expectFilterAdded sets up expectation + Given I expect the following filters added: + | filter | callback | priority | arguments | + | foobar | bazbat | 10 | 2 | + When I add the following filters: + | filter | callback | priority | arguments | + | foobar | bazbat | 10 | 2 | + Then tearDown should not fail + + Scenario: expectFilterAdded fails when not met + Given I expect the following filters added: + | filter | callback | + | foobar | bazbat | + When I do nothing + Then tearDown should fail + + Scenario: expectFilterAdded fails when argument count is different + Given I expect the following filters added: + | filter | callback | priority | arguments | + | foobar | bazbat | 10 | 2 | + When I add the following filters: + | filter | callback | priority | arguments | + | foobar | bazbat | 10 | 3 | + Then tearDown should fail + + Scenario: expectFilterAdded fails when priority is different + Given I expect the following filters added: + | filter | callback | priority | + | foobar | bazbat | 10 | + When I add the following filters: + | filter | callback | priority | + | foobar | bazbat | 11 | + Then tearDown should fail + + Scenario: expectAction sets up expectation + Given I expect the "foobar" action + When I do the "foobar" action + Then tearDown should not fail + + Scenario: expectAction fails when unmet + Given I expect the "foobar" action + When I do nothing + Then tearDown should fail + + Scenario: expectAction with extra arguments + Given I expect the "foobar" action with: + | some | extra | data | + When I do the "foobar" action with: + | some | extra | data | + Then tearDown should not fail + + Scenario: action with the wrong arguments fails + Given I expect the "bazbat" action with: + | the correct data | + When I do the "bazbat" action with: + | Invalid information | + Then tearDown should fail + + Scenario: action with extra arguments fails + Given I expect the "bazbat" action with: + | data | + When I do the "bazbat" action with: + | data | plus | + Then tearDown should fail + + Scenario: expectFilter sets up expectation + Given I expect the "foobar" filter with "bazbat" + When I apply the filter "foobar" with "bazbat" + Then tearDown should not fail + + Scenario: expectFilter fails when unmet + Given I expect the "foobar" filter with "bazbat" + When I do nothing + Then tearDown should fail + + Scenario: expectFilter with extra arguments + Given I expect the "foobar" filter with: + | some | extra | data | + When I apply the filter "foobar" with: + | some | extra | data | + Then tearDown should not fail + + Scenario: filter with the wrong arguments fails + Given I expect the "bazbat" filter with: + | the correct data | + When I apply the filter "bazbat" with: + | Invalid information | + Then tearDown should fail + + Scenario: expectFilter fails when called with wrong argument + Given I expect the "foobar" filter with "bazbat" + When I apply the filter "foobar" with "bimbam" + Then tearDown should fail + + Scenario: filter with extra arguments fails + Given I expect the "bazbat" filter with: + | data | + When I apply the filter "bazbat" with: + | data | plus | + Then tearDown should fail + + @strictmode + Scenario: Unexpected action fails in strict mode + Given strict mode is on + When I do nothing + Then I expect an error when I run do_action with args: + | bimbam | bazbat | + + Scenario: unexpected action does not fail tests + Given I do nothing + When I add the following actions: + | action | callback | + | foobar | bazbat | + Then tearDown should not fail + + @strictmode + Scenario: Unexpected filter fails in strict mode + Given strict mode is on + When I do nothing + Then I expect an error when I run apply_filters with args: + | foobar | bazbat | + + Scenario: unexpected filter does not fail tests + Given I do nothing + When I add the following filters: + | filter | callback | + | foobar | bazbat | + Then tearDown should not fail + + @strictmode + Scenario: unexpected action fails in strict mode + Given strict mode is on + When I do nothing + Then I expect an error when I run add_action with args: + | foobar | bazbat | + + @strictmode + Scenario: unexpected action fails in strict mode + Given strict mode is on + When I do nothing + Then I expect an error when I run add_filter with args: + | foobar | bazbat | + + Scenario: filter responder works + Given I expect filter "the_content" to respond to "Test content" with "Responder works" + When I apply the filter "the_content" with "Test content" + Then The filter "the_content" should return "Responder works" + + Scenario: filter returns default value when no filter defined + Given I do nothing + When I apply the filter "the_content" with "Apple" + Then The filter "the_content" should return "Apple" + + Scenario: filter returns default value when unexpected value used + Given I expect filter "the_content" to respond to "Windows" with "OS X" + When I apply the filter "the_content" with "Linux" + Then The filter "the_content" should return "Linux" + + Scenario: expectFilterNotAdded fails when filter added + Given I expect the following filters not to be added: + | filter | callback | + | foobar | bazbat | + When I add the following filters: + | filter | callback | + | foobar | bazbat | + Then tearDown should fail + + Scenario: expectFilterNotAdded passes when filter not added + Given I expect the following filters not to be added: + | filter | callback | + | foobar | bazbat | + When I do nothing + Then tearDown should not fail diff --git a/vendor/10up/wp_mock/php/WP_Mock.php b/vendor/10up/wp_mock/php/WP_Mock.php new file mode 100644 index 00000000..37db9373 --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock.php @@ -0,0 +1,557 @@ +flush(); + self::$function_manager->flush(); + + \Mockery::close(); + \WP_Mock\Handler::cleanup(); + } + + /** + * Fire a specific (mocked) callback when an apply_filters() call is used. + * + * @param string $filter + * + * @return \WP_Mock\Filter + */ + public static function onFilter( $filter ) { + self::$event_manager->called($filter,'filter'); + return self::$event_manager->filter( $filter ); + } + + /** + * Fire a specific (mocked) callback when a do_action() call is used. + * + * @param string $action + * + * @return \WP_Mock\Action + */ + public static function onAction( $action ) { + return self::$event_manager->action( $action ); + } + + /** + * Get a filter or action added callback object + * + * @param string $hook + * @param string $type + * + * @return \WP_Mock\HookedCallback + */ + public static function onHookAdded( $hook, $type = 'filter' ) { + return self::$event_manager->callback( $hook, $type ); + } + + /** + * Get a filter added callback object + * + * @param string $hook + * + * @return \WP_Mock\HookedCallback + */ + public static function onFilterAdded( $hook ) { + return self::onHookAdded( $hook, 'filter' ); + } + + /** + * Get an action added callback object + * + * @param string $hook + * + * @return \WP_Mock\HookedCallback + */ + public static function onActionAdded( $hook ) { + return self::onHookAdded( $hook, 'action' ); + } + + /** + * Alert the Event Manager that an action has been invoked. + * + * @param string $action + */ + public static function invokeAction( $action ) { + self::$event_manager->called( $action ); + } + + public static function addFilter( $hook ) { + self::addHook( $hook, 'filter' ); + } + + public static function addAction( $hook ) { + self::addHook( $hook, 'action' ); + } + + public static function addHook( $hook, $type = 'filter' ) { + $type_name = "$type::$hook"; + self::$event_manager->called( $type_name, 'callback' ); + } + + /** + * Set up the expectation that an action will be called during the test. + * + * Mock a WordPress action, regardless of the parameters used. This call merely + * verifies that the action is invoked by the tested method. + * + * @param string $action Action we expect the method to call + */ + public static function expectAction( $action ) { + $intercept = \Mockery::mock( 'intercept' ); + $intercept->shouldReceive( 'intercepted' )->atLeast()->once(); + $args = func_get_args(); + $args = count( $args ) > 1 ? array_slice( $args, 1 ) : array( null ); + + $mocked_action = self::onAction( $action ); + $responder = call_user_func_array( array( $mocked_action, 'with' ), $args ); + $responder->perform( array( $intercept, 'intercepted' ) ); + } + + /** + * Set up the expectation that a filter will be applied during the test. + * + * Mock a WordPress filter with specific arguments. You need all arguments that you expect + * in order to fulfill the expectation. + * + * @param string $filter + */ + public static function expectFilter( $filter ) { + $intercept = \Mockery::mock( 'intercept' ); + $intercept->shouldReceive( 'intercepted' )->atLeast()->once()->andReturnUsing( function( $value ) { + return $value; + } ); + $args = func_num_args() > 1 ? array_slice( func_get_args(), 1 ) : array( null ); + + $mocked_filter = self::onFilter( $filter ); + $responder = call_user_func_array( array( $mocked_filter, 'with' ), $args ); + $responder->reply( new \WP_Mock\InvokedFilterValue( array( $intercept, 'intercepted' ) ) ); + } + + /** + * Assert that all actions are called. + */ + public static function assertActionsCalled() { + $allActionsCalled = self::$event_manager->allActionsCalled(); + $failed = implode( ', ', self::$event_manager->expectedActions() ); + \PHPUnit\Framework\Assert::assertTrue( $allActionsCalled, 'Method failed to invoke actions: ' . $failed ); + } + + /** + * Assert that all filters are called. + */ + public static function assertFiltersCalled() { + $allFiltersCalled = self::$event_manager->allFiltersCalled(); + $failed = implode( ', ', self::$event_manager->expectedFilters() ); + \PHPUnit\Framework\Assert::assertTrue( $allFiltersCalled, 'Method failed to invoke filters: ' . $failed ); + } + + /** + * Add an expectation that an action should be added + * + * Really just a wrapper function for expectHookAdded() + * + * @param string $action The action name + * @param callable $callback The callback that should be registered + * @param int $priority The priority it should be registered at + * @param int $args The number of arguments that should be allowed + */ + public static function expectActionAdded( $action, $callback, $priority = 10, $args = 1 ) { + self::expectHookAdded( 'action', $action, $callback, $priority, $args ); + } + + /** + * Add an expection that an action should not be added. A wrapper + * around the expectHookNotAdded function. + * + * @param string $action The action hook name + * @param callable $callback The action callback + */ + public static function expectActionNotAdded( $action, $callback ) { + self::expectHookNotAdded( 'action', $action, $callback ); + } + + /** + * Add an expectation that a filter should be added + * + * Really just a wrapper function for expectHookAdded() + * + * @param string $filter The action name + * @param callable $callback The callback that should be registered + * @param int $priority The priority it should be registered at + * @param int $args The number of arguments that should be allowed + */ + public static function expectFilterAdded( $filter, $callback, $priority = 10, $args = 1 ) { + self::expectHookAdded( 'filter', $filter, $callback, $priority, $args ); + } + + /** + * Adds an expectation that a filter will not be added. A wrapper + * around the expectHookNotAdded function. + * + * @param string $filter The filter hook name + * @param callable $callback The filter callback + */ + public static function expectFilterNotAdded( $filter, $callback ) { + self::expectHookNotAdded( 'filter', $filter, $callback ); + } + + /** + * Add an expectation that a hook should be added + * + * @param string $type The type of hook being added + * @param string $action The action name + * @param callable $callback The callback that should be registered + * @param int $priority The priority it should be registered at + * @param int $args The number of arguments that should be allowed + */ + public static function expectHookAdded( $type, $action, $callback, $priority = 10, $args = 1 ) { + $intercept = \Mockery::mock( 'intercept' ); + $intercept->shouldReceive( 'intercepted' )->atLeast()->once(); + + /** @var WP_Mock\HookedCallbackResponder $responder */ + $responder = self::onHookAdded( $action, $type ) + ->with( $callback, $priority, $args ); + $responder->perform( array( $intercept, 'intercepted' ) ); + } + + /** + * Adds an expectation that a hook should not be added. Based on the + * shouldNotReceive API of Mocker. + * + * @param string $type The hook type, 'action' or 'filter' + * @param string $action The name of the hook + * @param callable $callback The hooks callback handler. + */ + public static function expectHookNotAdded( $type, $action, $callback ) { + $intercept = \Mockery::mock( 'intercept' ); + $intercept->shouldNotReceive( 'intercepted' ); + + /** @var WP_Mock\HookedCallbackResponder $responder */ + $responder = self::onHookAdded( $action, $type ) + ->with( $callback, 10, 1 ); + $responder->perform( array( $intercept, 'intercepted' ) ); + } + + /** + * Assert that all hooks are added. + */ + public static function assertHooksAdded() { + $allHooksAdded = self::$event_manager->allHooksAdded(); + $failed = implode( ', ', self::$event_manager->expectedHooks() ); + PHPUnit\Framework\Assert::assertTrue( $allHooksAdded, 'Method failed to add hooks: ' . $failed ); + } + + /** + * Mock a WordPress API function + * + * This function registers a mock object for a WordPress function and, if + * necessary, dynamically defines the function. Pass the function name as + * the first argument (e.g. wp_remote_get) and pass in details about the + * expectations in the $arguments array. The arguments array has a few + * options for defining expectations about how the WordPress function should + * be used during a test. Currently, it accepts the following settings: + * + * - times: Defines expectations for the number of times a function should + * be called. The default is 0 or more times. To expect the function to be + * called an exact amount of times, set times to a non-negative numeric + * value. To specify that the function should be called a minimum number + * of times, use a string with the minimum followed by '+' (e.g. '3+' + * means 3 or more times). Append a '-' to indicate a maximum number of + * times a function should be called (e.g. '3-' means no more than 3 times) + * To indicate a range, use '-' between two numbers (e.g. '2-5' means at + * least 2 times and no more than 5 times) + * - return: Defines the value (if any) that the function should return. If + * you pass a Closure as the return value, the function will return + * whatever the Closure's return value. + * - return_in_order: Use this if your function will be called multiple + * times in the test but needs to have different return values. Set this to + * an array of return values. Each time the function is called, it will + * return the next value in the sequence until it reaches the last value, + * which will become the return value for all subsequent calls. For + * example, if I am mocking is_single(), I can set return_in_order to + * array( false, true ). The first time is_single() is called it will + * return false. The second and all subsequent times it will return true. + * Setting this value overrides return, so if you set both, return will be + * ignored. + * - return_arg: Use this to specify that the function should return one of + * its arguments. return_arg should be the position of the argument in the + * arguments array, so 0 for the first argument, 1 for the second, etc. + * You can also set this to true, which is equivalent to 0. This will + * override both return and return_in_order. + * - args: Use this to set expectations about what the arguments passed to + * the function should be. This value should always be an array with the + * arguments in order. Like with return, if you use a Closure, its return + * value will be used to validate the argument expectations. WP_Mock has + * several helper functions to make this feature more flexible. The are + * static methods on the \WP_Mock\Functions class. They are: + * - Functions::type( $type ) Expects an argument of a certain type. This + * can be any core PHP data type (string, int, resource, callable, etc.) + * or any class or interface name. + * - Functions::anyOf( $values ) Expects the argument to be any value in + * the $values array + * In addition to these helper functions, you can indicate that the + * argument can be any value of any type by using '*'. So, for example, if + * I am expecting get_post_meta to be called, the args array might look + * something like this: + * array( $post->ID, 'some_meta_key', true ) + * + * Returns the Mockery\Expectation object with the function expectations + * added. It is possible to use Mockery methods to add expectations to the + * object returned, which will then be combined with any expectations that + * may have been passed as arguments. + * + * @param string $function_name + * @param array $arguments + * + * @return Mockery\Expectation + */ + public static function userFunction( $function_name, $arguments = array() ) { + return self::$function_manager->register( $function_name, $arguments ); + } + + /** + * Alias for userFunction + * + * @deprecated since 1.0 + * + * @param string $function_name + * @param array $arguments + * + * @return Mockery\Expectation + */ + public static function wpFunction( $function_name, $arguments = array() ) { + static::getDeprecatedListener()->logDeprecatedCall( __METHOD__, array( $function_name, $arguments ) ); + return self::userFunction( $function_name, $arguments ); + } + + /** + * A wrapper for userFunction that will simply set/override the return to be + * a function that echoes the value that its passed. For example, esc_attr_e + * may need to be mocked, and it must echo some value. echoFunction will set + * esc_attr_e to echo the value its passed. + * + * \WP_Mock::echoFunction( 'esc_attr_e' ); + * esc_attr_e( 'some_value' ); // echoes (translated) "some_value" + * + * @param string $function_name Function name. + * @param array $arguments Optional. Arguments. Defaults to array(). + * + * @return Mockery\Expectation + */ + public static function echoFunction( $function_name, $arguments = array() ) { + $arguments = (array) $arguments; + $arguments['return'] = function ( $param ) { + echo $param; + }; + return self::$function_manager->register( $function_name, $arguments ); + } + + /** + * A wrapper for userFunction that will simply set/override the return to be + * a function that returns the value that its passed. For example, esc_attr + * may need to be mocked, and it must return some value. passthruFunction + * will set esc_attr to return the value its passed. + * + * \WP_Mock::passthruFunction( 'esc_attr' ); + * echo esc_attr( 'some_value' ); // echoes "some_value" + * + * @param string $function_name + * @param array $arguments + * + * @return Mockery\Expectation + */ + public static function passthruFunction( $function_name, $arguments = array() ) { + $arguments = (array) $arguments; + $arguments['return'] = function ( $param ) { + return $param; + }; + return self::$function_manager->register( $function_name, $arguments ); + } + + /** + * Alias for passthruFunction + * + * @deprecated since 1.0 + * + * @param string $function_name + * @param array $arguments + * + * @return Mockery\Expectation + */ + public static function wpPassthruFunction( $function_name, $arguments = array() ) { + static::getDeprecatedListener()->logDeprecatedCall( __METHOD__, array( $function_name, $arguments ) ); + return self::passthruFunction( $function_name, $arguments ); + } + + /** + * Add a function mock that aliases another callable. + * + * e.g.: WP_Mock::alias( 'wp_hash', 'md5' ); + * + * @param string $function_name + * @param callable $alias + * @param array $arguments + * + * @return Mockery\Expectation + */ + public static function alias( $function_name, $alias, $arguments = array() ) { + $arguments = (array) $arguments; + if ( is_callable( $alias ) ) { + $arguments['return'] = function () use ( $alias ) { + return call_user_func_array( $alias, func_get_args() ); + }; + } + return self::$function_manager->register( $function_name, $arguments ); + } + + /** + * Generate a fuzzy object match expectation + * + * This will let you fuzzy match objects based on their properties without + * needing to use the identical (===) operator. This is helpful when the + * object being passed to a function is constructed inside the scope of the + * function being tested but where you want to make assertions on more than + * just the type of the object. + * + * @param $thing + * + * @return FuzzyObject + */ + public static function fuzzyObject( $thing ) { + return new FuzzyObject( $thing ); + } + + /** + * @return \WP_Mock\DeprecatedListener + */ + public static function getDeprecatedListener() { + return static::$deprecated_listener; + } +} diff --git a/vendor/10up/wp_mock/php/WP_Mock/API/constant-mocks.php b/vendor/10up/wp_mock/php/WP_Mock/API/constant-mocks.php new file mode 100644 index 00000000..aa8f92bf --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/API/constant-mocks.php @@ -0,0 +1,72 @@ +react( $function_to_add, (int) $priority, (int) $accepted_args ); + } +} + +if ( ! function_exists( 'do_action' ) ) { + /** + * Execute functions hooked on a specific action hook. + * + * @param string $tag The name of the action to be executed. + * @param mixed $arg,... Optional additional arguments which are passed on to the functions hooked to the action. + * + * @return null Will return null if $tag does not exist in $wp_filter array + */ + function do_action( $tag, $arg = '' ) { + $args = func_get_args(); + $args = array_slice( $args, 1 ); + + return \WP_Mock::onAction( $tag )->react( $args ); + } +} + +if ( ! function_exists( 'add_filter' ) ) { + /** + * Dummy method to prevent filter hooks in constructor from failing. + */ + function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) { + \WP_Mock::onFilterAdded( $tag )->react( $function_to_add, (int) $priority, (int) $accepted_args ); + } +} + +if ( ! function_exists( 'apply_filters' ) ) { + /** + * Call the functions added to a filter hook. + * + * @param string $tag The name of the filter hook. + * @param mixed $value The value on which the filters hooked to $tag are applied on. + * @param mixed $var,... Additional variables passed to the functions hooked to $tag. + * + * @return mixed The filtered value after all hooked functions are applied to it. + */ + function apply_filters( $tag, $value ) { + $args = func_get_args(); + $args = array_slice( $args, 1 ); + $args[0] = $value; + + return \WP_Mock::onFilter( $tag )->apply( $args ); + } +} + +if ( ! function_exists( 'esc_html' ) ) { + function esc_html() { + return \WP_Mock\Handler::predefined_return_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( 'esc_attr' ) ) { + function esc_attr() { + return \WP_Mock\Handler::predefined_return_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( 'esc_url' ) ) { + function esc_url() { + return \WP_Mock\Handler::predefined_return_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( 'esc_url_raw' ) ) { + function esc_url_raw() { + return \WP_Mock\Handler::predefined_return_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( 'esc_js' ) ) { + function esc_js() { + return \WP_Mock\Handler::predefined_return_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( 'esc_textarea' ) ) { + function esc_textarea() { + return \WP_Mock\Handler::predefined_return_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( '__' ) ) { + function __() { + return \WP_Mock\Handler::predefined_return_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( '_e' ) ) { + function _e() { + \WP_Mock\Handler::predefined_echo_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( '_x' ) ) { + function _x() { + return \WP_Mock\Handler::predefined_return_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( 'esc_html__' ) ) { + function esc_html__() { + return \WP_Mock\Handler::predefined_return_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( 'esc_html_e' ) ) { + function esc_html_e() { + \WP_Mock\Handler::predefined_echo_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( 'esc_html_x' ) ) { + function esc_html_x() { + return \WP_Mock\Handler::predefined_return_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( 'esc_attr__' ) ) { + function esc_attr__() { + return \WP_Mock\Handler::predefined_return_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( 'esc_attr_e' ) ) { + function esc_attr_e() { + \WP_Mock\Handler::predefined_echo_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( 'esc_attr_x' ) ) { + function esc_attr_x() { + return \WP_Mock\Handler::predefined_return_function_helper( __FUNCTION__, func_get_args() ); + } +} + +if ( ! function_exists( '_n' ) ) { + function _n() { + return \WP_Mock\Handler::predefined_return_function_helper( __FUNCTION__, func_get_args() ); + } +} diff --git a/vendor/10up/wp_mock/php/WP_Mock/Action.php b/vendor/10up/wp_mock/php/WP_Mock/Action.php new file mode 100644 index 00000000..b984b422 --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/Action.php @@ -0,0 +1,77 @@ +name ); + + $arg_num = count( $args ); + + if ( 0 === $arg_num ) { + if ( ! isset( $this->processors['argsnull'] ) ) { + $this->strict_check(); + + return; + } + + $this->processors['argsnull']->react(); + } else { + $processors = $this->processors; + for ( $i = 0; $i < $arg_num - 1; $i ++ ) { + $arg = $this->safe_offset( $args[ $i ] ); + + if ( ! isset( $processors[ $arg ] ) ) { + $this->strict_check(); + + return; + } + + $processors = $processors[ $arg ]; + } + + $arg = $this->safe_offset( $args[ $arg_num - 1 ] ); + if ( ! is_array( $processors ) || ! isset( $processors[ $arg ] ) ) { + $this->strict_check(); + + return; + } + + $processors[ $arg ]->react(); + } + } + + protected function new_responder() { + return new Action_Responder(); + } + + /** + * @return string + */ + protected function get_strict_mode_message() { + return sprintf( 'Unexpected use of do_action for action %s', $this->name ); + } +} + +class Action_Responder { + /** + * @var mixed + */ + protected $callable; + + public function perform( $callable ) { + $this->callable = $callable; + } + + public function react() { + call_user_func( $this->callable ); + } +} diff --git a/vendor/10up/wp_mock/php/WP_Mock/DeprecatedListener.php b/vendor/10up/wp_mock/php/WP_Mock/DeprecatedListener.php new file mode 100644 index 00000000..155a6403 --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/DeprecatedListener.php @@ -0,0 +1,119 @@ +calls[] = array( $method, $args ); + } + + public function reset() { + $this->calls = array(); + } + + public function checkCalls() { + if ( empty( $this->calls ) ) { + return; + } + $e = new \PHPUnit\Framework\RiskyTestError( $this->getMessage() ); + $this->testResult->addFailure( $this->testCase, $e, 0 ); + } + + /** + * @param \PHPUnit\Framework\TestResult $testResult + */ + public function setTestResult( $testResult ) { + $this->testResult = $testResult; + } + + /** + * @param mixed $testName + */ + public function setTestName( $testName ) { + $this->testName = $testName; + } + + public function setTestCase( \PHPUnit\Framework\TestCase $testCase ) { + $this->testCase = $testCase; + } + + protected function getMessage() { + $maxLength = array_reduce( $this->getDeprecatedMethods(), function ( $carry, $item ) { + return max( $carry, strlen( $item ) ); + }, 0 ) + 1; + $message = 'Deprecated WP Mock calls inside ' . $this->testName . ":"; + foreach ( $this->getDeprecatedMethodsWithArgs() as $method => $args ) { + $firstRun = true; + $extra = $maxLength - strlen( $method ); + foreach ( $args as $arg ) { + $message .= "\n "; + if ( $firstRun ) { + $message .= $method . str_repeat( ' ', $extra ); + $firstRun = false; + $extra = $maxLength; + } else { + $message .= str_repeat( ' ', $extra ); + } + $message .= $arg; + } + } + + return $message; + } + + protected function getDeprecatedMethods() { + $methods = array(); + foreach ( $this->calls as $call ) { + $methods[] = $call[0]; + } + + return array_unique( $methods ); + } + + protected function getDeprecatedMethodsWithArgs() { + $collection = array(); + foreach ( $this->calls as $call ) { + $method = $call[0]; + $args = json_encode( array_map( array( $this, 'scalarizeArg' ), $call[1] ) ); + if ( empty( $collection[ $method ] ) ) { + $collection[ $method ] = array(); + } + $collection[ $method ][] = $args; + } + + return array_map( 'array_unique', $collection ); + } + + protected function scalarizeArg( $value ) { + if ( is_scalar( $value ) ) { + return $value; + } elseif ( is_object( $value ) ) { + return '<' . get_class( $value ) . ':' . spl_object_hash( $value ) . '>'; + } elseif ( is_array( $value ) ) { + if ( is_callable( $value ) ) { + return '[' . implode( ',', array_map( array( $this, 'scalarizeArg' ), $value ) ) . ']'; + } else { + return 'Array([' . count( $value ) . '] ...)'; + } + } elseif ( is_resource( $value ) ) { + return 'Resource'; + } else { + return 'Unknown Value'; + } + } +} diff --git a/vendor/10up/wp_mock/php/WP_Mock/EventManager.php b/vendor/10up/wp_mock/php/WP_Mock/EventManager.php new file mode 100644 index 00000000..652daa81 --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/EventManager.php @@ -0,0 +1,156 @@ +flush(); + } + + /** + * Clear internal storage. + */ + public function flush() { + $this->filters = array(); + $this->actions = array(); + $this->expected = array(); + } + + /** + * @param string $name Action handler to retrieve + * + * @return Action + */ + public function action( $name ) { + if ( ! isset( $this->actions[ $name ] ) ) { + $this->actions[ $name ] = new Action( $name ); + $this->expected[] = 'action::' . $name; + } + + return $this->actions[ $name ]; + } + + /** + * @param string $name Filter handler to retrieve + * + * @return Filter + */ + public function filter( $name ) { + if ( ! isset( $this->filters[ $name ] ) ) { + $this->filters[ $name ] = new Filter( $name ); + $this->expected[] = 'filter::' . $name; + } + + return $this->filters[ $name ]; + } + + public function callback( $name, $type = 'filter' ) { + $type_name = "$type::$name"; + if ( ! isset( $this->callbacks[ $type_name ] ) ) { + $hookedCallback = new HookedCallback( $name ); + $hookedCallback->setType( $type ); + $this->callbacks[ $type_name ] = $hookedCallback; + $this->expected[] = "callback::$type_name"; + } + + return $this->callbacks[ $type_name ]; + } + + /** + * Remember that a particular hook has been invoked during operation. + * + * @param string $hook + * @param string $type + */ + public function called( $hook, $type = 'action' ) { + $position = array_search( $type . '::' . $hook, $this->expected ); + array_splice( $this->expected, $position, 1 ); + } + + /** + * Return a list of all the actions we're expecting a test to invoke. + * + * @return array + */ + public function expectedActions() { + return array_keys( $this->actions ); + } + + /** + * Return a list of all the filters we're expecting a test to invoke. + * @return array + */ + public function expectedFilters() { + return array_keys( $this->filters ); + } + + /** + * Return a list of all the hooks we're expecting a test to invoke. + * @return array + */ + public function expectedHooks() { + return array_keys( $this->callbacks ); + } + + /** + * Check whether or not all actions have been invoked at least once. + * + * @return bool + */ + public function allActionsCalled() { + foreach( $this->expected as $hook ) { + if ( 0 === strpos( $hook, 'action::' ) ) { + return false; + } + } + + return true; + } + + /** + * Check whether or not all filters have been invoked at least once. + * + * @return bool + */ + public function allFiltersCalled() { + foreach ( $this->expected as $hook ) { + if ( 0 === strpos( $hook, 'filter::' ) ) { + return false; + } + } + + return true; + } + + /** + * Check whether or not all hooks have been invoked at least once. + * + * @return bool + */ + public function allHooksAdded() { + foreach( $this->expected as $hook ) { + if ( 0 === strpos( $hook, 'callback::' ) ) { + return false; + } + } + + return true; + } +} diff --git a/vendor/10up/wp_mock/php/WP_Mock/Filter.php b/vendor/10up/wp_mock/php/WP_Mock/Filter.php new file mode 100644 index 00000000..d1503e98 --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/Filter.php @@ -0,0 +1,76 @@ +processors['argsnull'] ) ) { + return $this->processors['argsnull']->send(); + } + $this->strict_check(); + + return null; + } + + $processors = $this->processors; + foreach ( $args as $arg ) { + $key = $this->safe_offset( $arg ); + if ( ! is_array( $processors ) || ! isset( $processors[ $key ] ) ) { + $this->strict_check(); + + return $arg; + } + + $processors = $processors[ $key ]; + } + + return call_user_func_array( array($processors, 'send'), $args ); + } + + protected function new_responder() { + return new Filter_Responder(); + } + + /** + * @return string + */ + protected function get_strict_mode_message() { + return sprintf( 'Unexpected use of apply_filters for filter %s', $this->name ); + } +} + +class Filter_Responder { + /** + * @var mixed + */ + protected $value; + + public function reply( $value ) { + $this->value = $value; + } + + public function send() { + if ( $this->value instanceof InvokedFilterValue ) { + return call_user_func_array( $this->value, func_get_args() ); + } + + return $this->value; + } +} + diff --git a/vendor/10up/wp_mock/php/WP_Mock/Functions.php b/vendor/10up/wp_mock/php/WP_Mock/Functions.php new file mode 100644 index 00000000..8fdd3279 --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/Functions.php @@ -0,0 +1,295 @@ +flush(); + } + + /** + * Emptys the mocked_functions array + */ + public function flush() { + $this->mocked_functions = array(); + Handler::cleanup(); + $this->patchwork_functions = array(); + if ( function_exists( 'Patchwork\undoAll' ) ) { + \Patchwork\restoreAll(); + } + if ( empty( self::$wp_mocked_functions ) ) { + self::$wp_mocked_functions = array( + 'add_action', + 'do_action', + 'add_filter', + 'apply_filters', + 'esc_attr', + 'esc_html', + 'esc_js', + 'esc_textarea', + 'esc_url', + 'esc_url_raw', + '__', + '_e', + '_x', + 'esc_attr__', + 'esc_attr_e', + 'esc_attr_x', + 'esc_html__', + 'esc_html_e', + 'esc_html_x', + '_n', + ); + } + } + + /** + * Registers the function to be mocked and sets up its expectations + * + * @param string $function + * @param array $arguments + * + * @throws \Exception If the function name is invalid + * + * @return Mockery\Expectation + */ + public function register( $function, $arguments ) { + $expectation = null; + try { + $this->generate_function( $function ); + if ( empty( $this->mocked_functions[$function] ) ) { + $this->mocked_functions[$function] = Mockery::mock( 'wp_api' ); + } + $mock = $this->mocked_functions[$function]; + + $method = preg_replace( '/\\\\+/', '_', $function ); + $expectation = $this->set_up_mock( $mock, $method, $arguments ); + Handler::register_handler( $function, array( $mock, $method ) ); + } catch ( \Exception $e ) { + throw $e; + } + return $expectation; + } + + /** + * Sets up an argument placeholder that allows it to be any of an enumerated + * list of possibilities + * + * @return \Mockery\Matcher\anyOf + */ + public static function anyOf() { + return call_user_func_array( array( '\\Mockery', 'anyOf' ), func_get_args() ); + } + + /** + * Sets up an argument placeholder that requires the argument to be of a + * certain type + * + * This may be any type for which there is a "is_*" function, or any class or + * interface. + * + * @param string $expected + * + * @return Mockery\Matcher\Type + */ + public static function type( $expected ) { + return Mockery::type( $expected ); + } + + /** + * Set up the mock object with an expectation for this test. + * + * @param \Mockery\Mock $mock + * @param string $function + * @param array $arguments + * + * @return Mockery\Expectation + */ + protected function set_up_mock( $mock, $function, $arguments ) { + $expectation = $mock->shouldReceive( $function ); + + if ( isset( $arguments['times'] ) ) { + $times = $arguments['times']; + if ( is_int( $times ) || preg_match( '/^\d+$/', $times ) ) { + $expectation->times( (int) $times ); + } elseif ( preg_match( '/^(\d+)([\-+])$/', $times, $matches ) ) { + $method = '+' === $matches[2] ? 'atLeast' : 'atMost'; + $expectation->$method()->times( (int) $matches[1] ); + } elseif ( preg_match( '/^(\d+)-(\d+)$/', $times, $matches ) ) { + $num1 = (int) $matches[1]; + $num2 = (int) $matches[2]; + if ( $num1 === $num2 ) { + $expectation->times( $num1 ); + } else { + $expectation->between( min( $num1, $num2 ), max( $num1, $num2 ) ); + } + } + } + if ( isset( $arguments['args'] ) ) { + $arguments['args'] = array_map( function ( $argument ) { + if ( $argument instanceof \Closure ) { + return Mockery::on( $argument ); + } + if ( $argument === '*' ) { + return Mockery::any(); + } + return $argument; + }, (array) $arguments['args'] ); + call_user_func_array( array( $expectation, 'with' ), $arguments['args'] ); + } + if ( isset( $arguments['return_arg'] ) ) { + $argument_position = true === $arguments['return_arg'] ? 0 : (int) $arguments['return_arg']; + $arguments['return'] = function () use ( $argument_position ) { + if ( $argument_position >= func_num_args() ) { + return null; + } + return func_get_arg( $argument_position ); + }; + } elseif ( isset( $arguments['return_in_order'] ) ) { + $arguments['return'] = new ReturnSequence(); + $arguments['return']->setReturnValues( (array) $arguments['return_in_order'] ); + } + if ( isset( $arguments['return'] ) ) { + $return = $arguments['return']; + if ( $return instanceof ReturnSequence ) { + $expectation->andReturnValues( $return->getReturnValues() ); + } elseif ( $return instanceof \Closure ) { + $expectation->andReturnUsing( $return ); + } else { + $expectation->andReturn( $return ); + } + } + return $expectation; + } + + /** + * Dynamically declares a function if it doesn't already exist + * + * This function is namespace-aware. + * + * @param $function_name + */ + private function generate_function( $function_name ) { + $function_name = $this->sanitize_function_name( $function_name ); + + $this->validate_function_name( $function_name ); + + $this->create_function( $function_name ) OR $this->replace_function( $function_name ); + } + + /** + * Create a function with WP_Mock + * + * @param string $function_name + * + * @return bool True if this function created the mock, false otherwise + */ + private function create_function( $function_name ) { + if ( in_array( $function_name, self::$wp_mocked_functions ) ) { + return true; + } + if ( function_exists( $function_name ) ) { + return false; + } + + $parts = explode( '\\', $function_name ); + $name = array_pop( $parts ); + $namespace = empty( $parts ) ? '' : 'namespace ' . implode( '\\', $parts ) . ';' . PHP_EOL; + + $declaration = <<patchwork_functions ) ) { + return true; + } + if ( ! function_exists( 'Patchwork\\replace' ) ) { + return true; + } + $this->patchwork_functions[] = $function_name; + \Patchwork\redefine( $function_name, function () use ( $function_name ) { + return Handler::handle_function( $function_name, func_get_args() ); + } ); + return true; + } + + /** + * Clean the function name to be of a standard shape + * + * @param string $function_name + * + * @return string + */ + private function sanitize_function_name( $function_name ) { + $function_name = trim( $function_name, '\\' ); + return $function_name; + } + + /** + * Validate the function name for format and other considerations + * + * Validation will fail if the string doesn't match the regex, if it's an + * internal function, or if it is a reserved word in PHP. + * + * @param string $function_name + * + * @throws \InvalidArgumentException + */ + private function validate_function_name( $function_name ) { + if ( function_exists( $function_name ) ) { + if ( empty( $this->internal_functions ) ) { + $defined_functions = get_defined_functions(); + $this->internal_functions = $defined_functions['internal']; + } + if ( in_array( $function_name, $this->internal_functions ) ) { + throw new \InvalidArgumentException( 'Cannot override internal PHP functions!' ); + } + } + + $parts = explode( '\\', $function_name ); + $name = array_pop( $parts ); + + if ( ! preg_match( '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $function_name ) ) { + throw new \InvalidArgumentException( 'Function name not properly formatted!' ); + } + + $reserved_words = ' __halt_compiler abstract and array as break callable case catch class clone const continue declare default die do echo else elseif empty enddeclare endfor endforeach endif endswitch endwhile eval exit extends final for foreach function global goto if implements include include_once instanceof insteadof interface isset list namespace new or print private protected public require require_once return static switch throw trait try unset use var while xor __CLASS__ __DIR__ __FILE__ __FUNCTION__ __LINE__ __METHOD__ __NAMESPACE__ __TRAIT__ '; + if ( false !== strpos( $reserved_words, " $name " ) ) { + throw new \InvalidArgumentException( 'Function name can not be a reserved word!' ); + } + } + +} + diff --git a/vendor/10up/wp_mock/php/WP_Mock/Handler.php b/vendor/10up/wp_mock/php/WP_Mock/Handler.php new file mode 100644 index 00000000..9b701668 --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/Handler.php @@ -0,0 +1,110 @@ +name = $name; + } + + protected function safe_offset( $value ) { + if ( is_null( $value ) ) { + return 'null'; + } elseif ( is_scalar( $value ) ) { + return $value; + } elseif ( is_object( $value ) ) { + return spl_object_hash( $value ); + } elseif ( is_array( $value ) ) { + $return = ''; + foreach ( $value as $k => $v ) { + $k = is_numeric( $k ) ? '' : $k; + $return .= $k . $this->safe_offset( $v ); + } + + return $return; + } + + return ''; + } + + /** @return Action_Responder|Filter_Responder */ + public function with() { + $args = func_get_args(); + $responder = $this->new_responder(); + + if ( $args === array( null ) ) { + $this->processors['argsnull'] = $responder; + } else { + $num_args = count( $args ); + + $processors = &$this->processors; + for ( $i = 0; $i < $num_args - 1; $i ++ ) { + $arg = $this->safe_offset( $args[ $i ] ); + + if ( ! isset( $processors[ $arg ] ) ) { + $processors[ $arg ] = array(); + } + + $processors = &$processors[ $arg ]; + } + + $processors[ $this->safe_offset( $args[ $num_args - 1 ] ) ] = $responder; + } + + return $responder; + } + + protected abstract function new_responder(); + + /** + * Throw an exception if strict mode is on + * + * @throws \PHPUnit\Framework\ExpectationFailedException + */ + protected function strict_check() { + if ( \WP_Mock::strictMode() ) { + throw new \PHPUnit\Framework\ExpectationFailedException( $this->get_strict_mode_message() ); + } + } + + /** + * @return string + */ + abstract protected function get_strict_mode_message(); + +} diff --git a/vendor/10up/wp_mock/php/WP_Mock/HookedCallback.php b/vendor/10up/wp_mock/php/WP_Mock/HookedCallback.php new file mode 100644 index 00000000..e064788f --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/HookedCallback.php @@ -0,0 +1,107 @@ +type = $type; + } + + public function react( $callback, $priority, $argument_count ) { + \WP_Mock::addHook( $this->name ); + + $safe_callback = $this->safe_offset( $callback ); + if ( + empty( $this->processors[ $safe_callback ] ) || + empty( $this->processors[ $safe_callback ][ $priority ] ) || + empty( $this->processors[ $safe_callback ][ $priority ][ $argument_count ] ) + ) { + $this->callback = $callback; + $this->strict_check(); + + return null; + } + + return $this->processors[ $this->safe_offset( $callback ) ][ $priority ][ $argument_count ]->react(); + } + + protected function new_responder() { + return new HookedCallbackResponder(); + } + + protected function safe_offset( $value ) { + if ( $value instanceof \Closure ) { + $value = '__CLOSURE__'; + } + + return parent::safe_offset( $value ); + } + + /** + * Converts a callable to a string + * + * Closures get returned as 'Closure', objects (those with an __invoke() method get turned into ::__invoke, + * and arrays get turned into :: + * + * @param callable $callback + * + * @return string + */ + protected function callback_to_string( $callback ) { + if ( ! is_string( $callback ) ) { + if ( $callback instanceof \Closure ) { + $callback = 'Closure'; + } elseif ( is_object( $callback ) ) { + $callback = get_class( $callback ) . '::__invoke'; + } else { + $class = $callback[0]; + $method = $callback[1]; + if ( ! is_string( $class ) ) { + $class = get_class( $class ); + } + $callback = "{$class}::$method"; + } + } + + return $callback; + } + + /** + * @param $callback + * + * @return string + */ + protected function get_strict_mode_message() { + return sprintf( + 'Unexpected use of add_%s for action %s with callback %s', + $this->type, + $this->name, + $this->callback_to_string( $this->callback ) + ); + } + +} + +class HookedCallbackResponder { + + /** + * @var callable + */ + protected $callable; + + public function perform( $callable ) { + $this->callable = $callable; + } + + public function react() { + call_user_func( $this->callable ); + } + +} diff --git a/vendor/10up/wp_mock/php/WP_Mock/InvokedFilterValue.php b/vendor/10up/wp_mock/php/WP_Mock/InvokedFilterValue.php new file mode 100644 index 00000000..bf7a56a5 --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/InvokedFilterValue.php @@ -0,0 +1,25 @@ +callback = $callable; + } + + public function __invoke() { + return call_user_func_array( $this->callback, func_get_args() ); + } + +} diff --git a/vendor/10up/wp_mock/php/WP_Mock/Loader.php b/vendor/10up/wp_mock/php/WP_Mock/Loader.php new file mode 100644 index 00000000..91277cbc --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/Loader.php @@ -0,0 +1,149 @@ +register(); + * + * @author Jonathan H. Wage + * @author Roman S. Borschel + * @author Matthew Weier O'Phinney + * @author Kris Wallsmith + * @author Fabien Potencier + */ + +namespace WP_Mock; + + +class Loader { + private $_fileExtension = '.php'; + private $_namespace; + private $_includePath; + private $_namespaceSeparator = '\\'; + + /** + * Creates a new Loader that loads classes of the + * specified namespace. + * + * @param string $ns The namespace to use. + */ + public function __construct( $ns = 'WP_Mock', $includePath = null ) { + $this->_namespace = $ns; + $this->_includePath = $includePath; + } + + /** + * Sets the namespace separator used by classes in the namespace of this class loader. + * + * @param string $sep The separator to use. + */ + public function setNamespaceSeparator( $sep ) { + $this->_namespaceSeparator = $sep; + } + + /** + * Gets the namespace seperator used by classes in the namespace of this class loader. + * + * @return void + */ + public function getNamespaceSeparator() { + return $this->_namespaceSeparator; + } + + /** + * Sets the base include path for all class files in the namespace of this class loader. + * + * @param string $includePath + */ + public function setIncludePath( $includePath ) { + $this->_includePath = $includePath; + } + + /** + * Gets the base include path for all class files in the namespace of this class loader. + * + * @return string $includePath + */ + public function getIncludePath() { + return $this->_includePath; + } + + /** + * Sets the file extension of class files in the namespace of this class loader. + * + * @param string $fileExtension + */ + public function setFileExtension( $fileExtension ) { + $this->_fileExtension = $fileExtension; + } + + /** + * Gets the file extension of class files in the namespace of this class loader. + * + * @return string $fileExtension + */ + public function getFileExtension() { + return $this->_fileExtension; + } + + /** + * Installs this class loader on the SPL autoload stack. + * + * @param bool $prepend If true, prepend autoloader on the autoload stack + */ + public function register( $prepend = false ) { + //spl_autoload_register( array( $this, 'loadClass' ), true, $prepend ); + } + + /** + * Uninstalls this class loader from the SPL autoloader stack. + */ + public function unregister() { + //spl_autoload_unregister( array( $this, 'loadClass' ) ); + } + + /** + * Loads the given class or interface. + * + * @param string $className The name of the class to load. + * + * @return void + */ + public function loadClass( $className ) { + return; + if ( $className === 'WP_Mock' ) { + require $this->getFullPath( 'WP_Mock.php' ); + + return; + } + if ( null === $this->_namespace + || $this->_namespace . $this->_namespaceSeparator === substr( $className, 0, strlen( $this->_namespace . $this->_namespaceSeparator ) ) + ) { + $fileName = ''; + $namespace = ''; + if ( false !== ( $lastNsPos = strripos( $className, $this->_namespaceSeparator ) ) ) { + $namespace = substr( $className, 0, $lastNsPos ); + $className = substr( $className, $lastNsPos + 1 ); + $fileName = str_replace( $this->_namespaceSeparator, DIRECTORY_SEPARATOR, $namespace ) . DIRECTORY_SEPARATOR; + } + $fileName .= str_replace( '_', DIRECTORY_SEPARATOR, $className ) . $this->_fileExtension; + require $this->getFullPath( $fileName ); + } + } + + /** + * Returns full path for $fileName if _includePath is set, or leaves as-is for PHP's internal search in 'require'. + * + * @param string $fileName relative to include path. + * + * @return string + */ + private function getFullPath( $fileName ) { + return ($this->_includePath !== null ? $this->_includePath . DIRECTORY_SEPARATOR : '') . $fileName; + } +} diff --git a/vendor/10up/wp_mock/php/WP_Mock/Matcher/FuzzyObject.php b/vendor/10up/wp_mock/php/WP_Mock/Matcher/FuzzyObject.php new file mode 100644 index 00000000..a3ee3fd4 --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/Matcher/FuzzyObject.php @@ -0,0 +1,101 @@ +haveCommonAncestor( $actual, $this->_expected ) ) { + return false; + } + + $expected_properties = get_object_vars( $this->_expected ); + + foreach ( $expected_properties as $prop => $value ) { + if ( ! isset( $actual->$prop ) || $value !== $actual->$prop ) { + return false; + } + } + + $actual_keys = array_keys( get_object_vars( $actual ) ); + $extra_actual = array_diff( $actual_keys, array_keys( $expected_properties ) ); + if ( ! empty( $extra_actual ) ) { + return false; + } + + return true; + } + + /** + * Return a string representation of this Matcher + * + * @return string + */ + public function __toString() { + $values = array_values( get_object_vars( $this->_expected ) ); + $values = array_map( function ( $value ) { + if ( ! is_scalar( $value ) ) { + if ( is_array( $value ) ) { + $value = 'Array'; + } elseif ( is_object( $value ) ) { + $value = get_class( $value ); + } elseif ( is_resource( $value ) ) { + $value = get_resource_type( $value ); + } else { + $value = 'unknown'; + } + } + return $value; + }, $values ); + return ''; + } + + /** + * @param object $object1 + * @param object $object2 + * + * @return bool + */ + protected function haveCommonAncestor( $object1, $object2 ) { + $class1 = get_class( $object1 ); + $class2 = get_class( $object2 ); + if ( $class1 === $class2 ) { + return true; + } + $inheritance1 = class_parents( $class1 ); + $inheritance2 = class_parents( $class2 ); + return (bool) array_intersect_assoc( $inheritance1, $inheritance2 ); + } +} diff --git a/vendor/10up/wp_mock/php/WP_Mock/ReturnSequence.php b/vendor/10up/wp_mock/php/WP_Mock/ReturnSequence.php new file mode 100644 index 00000000..a7c55a32 --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/ReturnSequence.php @@ -0,0 +1,39 @@ +return_values = func_get_args(); + } + + /** + * Retrieve the $return_values array + * + * @return array + */ + public function getReturnValues() { + return $this->return_values; + } + + /** + * Set the return_values array + * + * Values should be passed in as one array. Keys will be discarded. + * + * @param array $return_values + */ + public function setReturnValues( $return_values ) { + $this->return_values = array_values( (array) $return_values ); + } + +} \ No newline at end of file diff --git a/vendor/10up/wp_mock/php/WP_Mock/Tools/Constraints/ExpectationsMet.php b/vendor/10up/wp_mock/php/WP_Mock/Tools/Constraints/ExpectationsMet.php new file mode 100644 index 00000000..6feba966 --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/Tools/Constraints/ExpectationsMet.php @@ -0,0 +1,40 @@ +mockery_verify(); + } catch ( Exception $e ) { + $this->_mockery_message = $e->getMessage(); + return false; + } + return true; + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString(): string { + return 'WP Mock expectations are met'; + } + + protected function additionalFailureDescription( $other ): string { + return str_replace( array( "\r", "\n" ), '', (string) $this->_mockery_message ); + } + + protected function failureDescription( $other ): string { + return $this->toString(); + } + +} diff --git a/vendor/10up/wp_mock/php/WP_Mock/Tools/Constraints/IsEqualHtml.php b/vendor/10up/wp_mock/php/WP_Mock/Tools/Constraints/IsEqualHtml.php new file mode 100644 index 00000000..38bed5a0 --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/Tools/Constraints/IsEqualHtml.php @@ -0,0 +1,57 @@ +value = $value; + $this->delta = $delta; + $this->maxDepth = $maxDepth; + $this->canonicalize = $canonicalize; + $this->ignoreCase = $ignoreCase; + } + + private function clean( $thing ) { + $thing = preg_replace( '/\n\s+/', '', $thing ); + $thing = preg_replace( '/\s\s+/', ' ', $thing ); + return str_replace( array( "\r", "\n", "\t" ), '', $thing ); + } + + public function evaluate( $other, $description = '', $returnResult = FALSE ) { + $other = $this->clean( $other ); + $this->value = $this->clean( $this->value ); + $isEqual = new IsEqual( $this->value, $this->delta, $this->maxDepth, $this->canonicalize, $this->ignoreCase ); + return $isEqual->evaluate( $other, $description, $returnResult ); + } +} diff --git a/vendor/10up/wp_mock/php/WP_Mock/Tools/TestCase.php b/vendor/10up/wp_mock/php/WP_Mock/Tools/TestCase.php new file mode 100644 index 00000000..995d7bfa --- /dev/null +++ b/vendor/10up/wp_mock/php/WP_Mock/Tools/TestCase.php @@ -0,0 +1,319 @@ +requireFileDependencies(); + + WP_Mock::setUp(); + + $_GET = (array) $this->__default_get; + $_POST = (array) $this->__default_post; + $_REQUEST = (array) $this->__default_request; + + $this->setUpContentFiltering(); + + $this->cleanGlobals(); + } + + public function tearDown() : void { + WP_Mock::tearDown(); + + $this->cleanGlobals(); + + $this->mockedStaticMethods = array(); + + $_GET = array(); + $_POST = array(); + $_REQUEST = array(); + } + + public function assertActionsCalled() { + $actions_not_added = $expected_actions = 0; + try { + WP_Mock::assertActionsCalled(); + } catch ( Exception $e ) { + $actions_not_added = 1; + $expected_actions = $e->getMessage(); + } + $this->assertEmpty( $actions_not_added, $expected_actions ); + } + + public function assertHooksAdded() { + $hooks_not_added = $expected_hooks = 0; + try { + WP_Mock::assertHooksAdded(); + } catch ( Exception $e ) { + $hooks_not_added = 1; + $expected_hooks = $e->getMessage(); + } + $this->assertEmpty( $hooks_not_added, $expected_hooks ); + } + + public function ns( $function ) { + if ( ! is_string( $function ) || false !== strpos( $function, '\\' ) ) { + return $function; + } + + $thisClassName = trim( get_class( $this ), '\\' ); + + if ( ! strpos( $thisClassName, '\\' ) ) { + return $function; + } + + // $thisNamespace is constructed by exploding the current class name on + // namespace separators, running array_slice on that array starting at 0 + // and ending one element from the end (chops the class name off) and + // imploding that using namespace separators as the glue. + $thisNamespace = implode( '\\', array_slice( explode( '\\', $thisClassName ), 0, - 1 ) ); + + return "$thisNamespace\\$function"; + } + + public function stripTabsAndNewlines( $content ) { + return str_replace( array( "\t", "\r", "\n" ), '', $content ); + } + + public function expectOutputString( string $expectedString ): void { + if ( is_callable( $this->__contentFilterCallback ) ) { + $expectedString = call_user_func( $this->__contentFilterCallback, $expectedString ); + } + parent::expectOutputString( $expectedString ); + } + + public function assertCurrentConditionsMet( $message = '' ) { + $this->assertThat( null, new ExpectationsMet, $message ); + } + + public function assertConditionsMet( $message = '' ) { + $this->assertCurrentConditionsMet( $message ); + } + + public function assertEqualsHTML( $expected, $actual, $message = '' ) { + $constraint = new IsEqualHtml( $expected ); + $this->assertThat( $actual, $constraint, $message ); + } + + /** + * Nuke the globals from orbit for process isolation + * + * See http://kpayne.me/2012/07/02/phpunit-process-isolation-and-constant-already-defined/ + * for more details + * + * {@inheritdoc} + */ + protected function prepareTemplate( Text_Template $template ) { + $template->setVar( array( + 'globals' => '$GLOBALS[\'__PHPUNIT_BOOTSTRAP\'] = \'' . $GLOBALS['__PHPUNIT_BOOTSTRAP'] . '\';', + ) ); + parent::prepareTemplate( $template ); + } + + + /** + * Mock a static method of a class + * + * @param string $class The classname or class::method name + * @param null|string $method The method name. Optional if class::method used for $class + * + * @return \Mockery\Expectation + * @throws Exception + */ + protected function mockStaticMethod( $class, $method = null ) { + if ( ! $method ) { + list( $class, $method ) = ( explode( '::', $class ) + array( null, null ) ); + } + if ( ! $method ) { + throw new Exception( sprintf( 'Could not mock %s::%s', $class, $method ) ); + } + if ( ! WP_Mock::usingPatchwork() || ! function_exists( 'Patchwork\Interceptor\patch' ) ) { + throw new Exception( 'Patchwork is not loaded! Please load patchwork before mocking static methods!' ); + } + + $safe_method = "wp_mock_safe_$method"; + $signature = md5( "$class::$method" ); + if ( ! empty( $this->mockedStaticMethods[ $signature ] ) ) { + $mock = $this->mockedStaticMethods[ $signature ]; + } else { + + $rMethod = false; + if ( class_exists( $class ) ) { + $rMethod = new ReflectionMethod( $class, $method ); + } + if ( + $rMethod && + ( + ! $rMethod->isUserDefined() || + ! $rMethod->isStatic() || + $rMethod->isPrivate() + ) + ) { + throw new Exception( sprintf( '%s::%s is not a user-defined non-private static method!', $class, $method ) ); + } + + /** @var \Mockery\Mock $mock */ + $mock = Mockery::mock( $class ); + $mock->shouldAllowMockingProtectedMethods(); + $this->mockedStaticMethods[ $signature ] = $mock; + + \Patchwork\redefine( "$class::$method", function () use ( $mock, $safe_method ) { + return call_user_func_array( array( $mock, $safe_method ), func_get_args() ); + }, ! ( $rMethod ) ); + } + $expectation = $mock->shouldReceive( $safe_method ); + + return $expectation; + } + + /** + * @param array|object $data The post data to add to the post + * + * @return \WP_Post + */ + protected function mockPost( $data ) { + /** @var \WP_Post $post */ + $post = \Mockery::mock( 'WP_Post' ); + $data = array_merge( array( + 'ID' => 0, + 'post_author' => 0, + 'post_type' => '', + 'post_title' => '', + 'post_date' => '', + 'post_date_gmt' => '', + 'post_content' => '', + 'post_excerpt' => '', + 'post_status' => '', + 'comment_status' => '', + 'ping_status' => '', + 'post_password' => '', + 'post_parent' => 0, + 'post_modified' => '', + 'post_modified_gmt' => '', + 'comment_count' => 0, + 'menu_order' => 0, + ), (array) $data ); + array_walk( $data, function ( $value, $prop ) use ( $post ) { + $post->$prop = $value; + } ); + + return $post; + } + + /** + * @param array $query_vars + * + * @return \WP + */ + protected function mockWp( array $query_vars = array() ) { + /** @var \WP $wp */ + $wp = \Mockery::mock( 'WP' ); + $wp->query_vars = $query_vars; + + return $wp; + } + + protected function cleanGlobals() { + $common_globals = array( + 'post', + 'wp_query', + ); + foreach ( $common_globals as $var ) { + if ( isset( $GLOBALS[ $var ] ) ) { + unset( $GLOBALS[ $var ] ); + } + } + + } + + /** + * Require any testFiles that are defined in a subclass + * + * This will only work if the WP_MOCK_INCLUDE_DIR is defined to point to the root directory you want to include + * files from. + */ + protected function requireFileDependencies() { + if ( ! empty( $this->testFiles ) && defined( 'WP_MOCK_INCLUDE_DIR' ) ) { + foreach ( $this->testFiles as $file ) { + if ( file_exists( WP_MOCK_INCLUDE_DIR . $file ) ) { + require_once( WP_MOCK_INCLUDE_DIR . $file ); + } + } + } + } + + protected function setUpContentFiltering() { + $this->__contentFilterCallback = false; + + $annotations = $this->getAnnotations(); + if ( + ! isset( $annotations['stripTabsAndNewlinesFromOutput'] ) || + $annotations['stripTabsAndNewlinesFromOutput'][0] !== 'disabled' || + ( + is_numeric( $annotations['stripTabsAndNewlinesFromOutput'][0] ) && + (int) $annotations['stripTabsAndNewlinesFromOutput'][0] !== 0 + ) + ) { + $this->__contentFilterCallback = array( $this, 'stripTabsAndNewlines' ); + $this->setOutputCallback( $this->__contentFilterCallback ); + } + } + + public function run( TestResult $result = null ): TestResult { + if ( $result === null ) { + $result = $this->createResult(); + } + + WP_Mock::getDeprecatedListener()->setTestResult( $result ); + WP_Mock::getDeprecatedListener()->setTestCase($this); + + return parent::run( $result ); + } + + /** + * @after + */ + public function checkDeprecatedCalls() { + WP_Mock::getDeprecatedListener()->checkCalls(); + WP_Mock::getDeprecatedListener()->reset(); + } + +} + diff --git a/vendor/10up/wp_mock/phpdoc.xml b/vendor/10up/wp_mock/phpdoc.xml new file mode 100644 index 00000000..d954812d --- /dev/null +++ b/vendor/10up/wp_mock/phpdoc.xml @@ -0,0 +1,16 @@ + + + + WP_Mock + docs + utf-8 + + + docs + + + WP_Mock + tests/* + vendor/* + + \ No newline at end of file diff --git a/vendor/10up/wp_mock/phpunit.xml.dist b/vendor/10up/wp_mock/phpunit.xml.dist new file mode 100644 index 00000000..3c6875f0 --- /dev/null +++ b/vendor/10up/wp_mock/phpunit.xml.dist @@ -0,0 +1,22 @@ + + + + ./tests/ + + + + + + php + + + diff --git a/vendor/10up/wp_mock/tests/DeprecatedMethodsTest.php b/vendor/10up/wp_mock/tests/DeprecatedMethodsTest.php new file mode 100644 index 00000000..b953ab73 --- /dev/null +++ b/vendor/10up/wp_mock/tests/DeprecatedMethodsTest.php @@ -0,0 +1,43 @@ +reset(); + } + + protected function tearDown() : void { + WP_Mock::getDeprecatedListener()->reset(); + WP_Mock::tearDown(); + } + + public function testWpFunctionLogsDeprecationNotice() { + $listener = WP_Mock::getDeprecatedListener(); + $testResult = new \PHPUnit\Framework\TestResult(); + $result = Mockery::mock( $testResult ); + $case = Mockery::mock( '\PHPUnit\Framework\TestCase' ); + $listener->setTestCase( $case ); + $listener->setTestResult( $result ); + $result->shouldReceive( 'addFailure' ) + ->once() + ->with( $case, Mockery::type( '\PHPUnit\Framework\RiskyTestError' ), 0 ); + WP_Mock::wpFunction( 'foobar' ); + $this->assertNull($listener->checkCalls()); + } + + public function testWpPassthruFunctionLogsDeprecationNotice() { + $listener = WP_Mock::getDeprecatedListener(); + $testResult = new \PHPUnit\Framework\TestResult(); + $result = Mockery::mock( $testResult ); + $case = Mockery::mock( '\PHPUnit\Framework\TestCase' ); + $listener->setTestCase( $case ); + $listener->setTestResult( $result ); + $result->shouldReceive( 'addFailure' ) + ->once() + ->with( $case, Mockery::type( '\PHPUnit\Framework\RiskyTestError' ), 0 ); + WP_Mock::wpPassthruFunction( 'foobar' ); + $this->assertNull( $listener->checkCalls() ); + } + +} diff --git a/vendor/10up/wp_mock/tests/FunctionMocksTest.php b/vendor/10up/wp_mock/tests/FunctionMocksTest.php new file mode 100644 index 00000000..e832d9c2 --- /dev/null +++ b/vendor/10up/wp_mock/tests/FunctionMocksTest.php @@ -0,0 +1,85 @@ +isInIsolation() ) { + WP_Mock::setUp(); + } + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testCommonFunctionsAreDefined() { + // First we assert that all common functions get removed from the returned array. If any one of these functions + // doesn't get removed, that means it already exists. + $this->assertEmpty( array_filter( $this->common_functions, 'function_exists' ) ); + WP_Mock::bootstrap(); + // Now we assert that the array doesn't lose any items after bootstrap, meaning all expected functions got + // defined correctly. + $this->assertEquals( $this->common_functions, array_filter( $this->common_functions, 'function_exists' ) ); + } + + /** + * @dataProvider dataCommonFunctionsDefaultFunctionality + */ + public function testCommonFunctionsDefaultFunctionality( $function, $action ) { + $input = $expected = 'Something Random ' . rand( 0, 99 ); + if ( 'echo' === $action ) { + $this->expectOutputString( $input ); + $expected = null; + } + $this->assertEquals( $expected, call_user_func( $function, $input ) ); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testDefaultFailsInStrictMode() { + $this->expectExceptionMessageRegExp('/No handler found for \w+/'); + $this->expectException('\PHPUnit\Framework\ExpectationFailedException'); + WP_Mock::activateStrictMode(); + WP_Mock::bootstrap(); + _e('Test'); + } + + public function dataCommonFunctionsDefaultFunctionality() { + return array_map( function ( $function ) { + return array( $function, '_e' === substr( $function, - 2 ) ? 'echo' : 'return' ); + }, $this->common_functions ); + } + + public function testMockingOverridesDefaults() { + $this->assertEquals( 'Input', __( 'Input' ) ); + WP_Mock::userFunction( '__' )->andReturn( 'Output' ); + $this->assertEquals( 'Output', __( 'Input' ) ); + } + + public function testBotchedMocksStillOverrideDefault() { + WP_Mock::userFunction( 'esc_html' ); + $this->assertEmpty( esc_html( 'Input' ) ); + } + +} diff --git a/vendor/10up/wp_mock/tests/WP_Mock/DeprecatedListenerTest.php b/vendor/10up/wp_mock/tests/WP_Mock/DeprecatedListenerTest.php new file mode 100644 index 00000000..67cfd659 --- /dev/null +++ b/vendor/10up/wp_mock/tests/WP_Mock/DeprecatedListenerTest.php @@ -0,0 +1,131 @@ +object = new DeprecatedListener(); + } + + public function tearDown() : void { + $this->object->reset(); + } + + public function testLogDeprecatedCall() { + $method = 'Foobar::asdf' . rand( 0, 9 ); + $args = array( rand( 10, 99 ) ); + $this->object->logDeprecatedCall( $method, $args ); + + $this->assertEquals( array( array( $method, $args ) ), $this->getCalls( $this->object ) ); + } + + public function testReset() { + $this->object->logDeprecatedCall( 'Asdf', array( 'foobar' ) ); + $this->object->reset(); + + $this->assertEquals( array(), $this->getCalls( $this->object ) ); + } + + public function testCheckCallsNoCalls() { + $testResult = new \PHPUnit\Framework\TestResult(); + $result = Mockery::mock( $testResult ); + $result->shouldReceive( 'addFailure' )->never(); + /** @var \\PHPUnit\Framework\TestResult $result */ + $this->object->setTestResult( $result ); + + /** @noinspection PhpVoidFunctionResultUsedInspection */ + $this->assertNull($this->object->checkCalls()); + } + + public function testCheckCalls_scalar_only() { + $this->object->logDeprecatedCall( 'FooBar::bazBat', array( 'string', true, 42 ) ); + $this->object->setTestName( 'TestName' ); + $testCase = Mockery::mock( '\PHPUnit\Framework\TestCase' ); + /** @var \PHPUnit\Framework\TestCase $testCase */ + $this->object->setTestCase( $testCase ); + $testResult = new \PHPUnit\Framework\TestResult(); + $result = Mockery::mock( $testResult ); + $result->shouldReceive( 'addFailure' ) + ->once() + ->andReturnUsing( function ( $case, $exception, $int ) use ( $testCase ) { + $int = (int) $int; // It's coming as 0.0 + \PHPUnit\Framework\Assert::assertSame( $testCase, $case ); + \PHPUnit\Framework\Assert::assertTrue( $exception instanceof \PHPUnit\Framework\RiskyTest ); + $message = <<getMessage() ); + \PHPUnit\Framework\Assert::assertTrue( 0 === $int ); + } ); + /** @var \\PHPUnit\Framework\TestResult $result */ + $this->object->setTestResult( $result ); + + $this->object->checkCalls(); + } + + public function testCheckCalls_non_scalars() { + $callback1 = function () { + }; + $object1 = Mockery::mock( 'WP_Query' ); + $range = rand( 5, 10 ); + $resource = fopen( 'php://temp', 'r' ); + $this->object->logDeprecatedCall( 'BazBat::fooBar', array( $callback1 ) ); + $this->object->logDeprecatedCall( 'BazBat::fooBar', array( $object1 ) ); + $this->object->logDeprecatedCall( 'LongerClassName::callback', array( array( $object1, 'shouldReceive' ) ) ); + $this->object->logDeprecatedCall( 'BazBat::fooBar', array( range( 1, $range ), $resource ) ); + $this->object->setTestName( 'OtherTest' ); + $testCase = Mockery::mock( '\PHPUnit\Framework\TestCase' ); + /** @var \PHPUnit\Framework\TestCase $testCase */ + $this->object->setTestCase( $testCase ); + $testResult = new \PHPUnit\Framework\TestResult(); + $result = Mockery::mock( $testResult );; + $testClosure = function ( $case, $exception, $int ) use ( $testCase, $callback1, $object1, $range ) { + $int = (int) $int; // It's coming as 0.0 + $callback1 = get_class( $callback1 ) . ':' . spl_object_hash( $callback1 ); + $object1 = get_class( $object1 ) . ':' . spl_object_hash( $object1 ); + \PHPUnit\Framework\Assert::assertSame( $testCase, $case ); + \PHPUnit\Framework\Assert::assertTrue( $exception instanceof \PHPUnit\Framework\RiskyTest ); + $message = <<"] + ["<$object1>"] + ["Array([$range] ...)","Resource"] + LongerClassName::callback ["[<$object1>,shouldReceive]"] +EOT; + \PHPUnit\Framework\Assert::assertEquals( $message, $exception->getMessage() ); + \PHPUnit\Framework\Assert::assertTrue( 0 === $int ); + }; + $result->shouldReceive( 'addFailure' ) + ->once() + ->andReturnUsing( $testClosure ); + /** @var \\PHPUnit\Framework\TestResult $result */ + $this->object->setTestResult( $result ); + + try { + $this->object->checkCalls(); + } catch ( \Exception $e ) { + fclose( $resource ); + throw $e; + } + fclose( $resource ); + } + + protected function getCalls( $listener ) { + $prop = new ReflectionProperty( $listener, 'calls' ); + $prop->setAccessible( true ); + + return $prop->getValue( $listener ); + } + +} diff --git a/vendor/10up/wp_mock/tests/WP_MockTest.php b/vendor/10up/wp_mock/tests/WP_MockTest.php new file mode 100644 index 00000000..d82d1a1c --- /dev/null +++ b/vendor/10up/wp_mock/tests/WP_MockTest.php @@ -0,0 +1,110 @@ +assertFalse( WP_Mock::strictMode() ); + } + + /** + * @runInSeparateProcess + */ + public function test_activateStrictMode_turns_strict_mode_on() { + WP_Mock::activateStrictMode(); + $this->assertTrue( WP_Mock::strictMode() ); + } + + /** + * @runInSeparateProcess + */ + public function test_activateStrictMode_does_not_work_after_bootstrap() { + WP_Mock::bootstrap(); + WP_Mock::activateStrictMode(); + $this->assertFalse( WP_Mock::strictMode() ); + } + + /** + * @runInSeparateProcess + */ + public function test_userFunction_returns_expectation() { + WP_Mock::bootstrap(); + $this->assertInstanceOf( + '\Mockery\ExpectationInterface', + WP_Mock::userFunction( 'testWpMockFunction' ) + ); + } + + /** + * @runInSeparateProcess + */ + public function test_assertHooksAdded_for_filters_and_actions() { + WP_Mock::bootstrap(); + WP_Mock::expectFilterAdded( 'testFilter', 'testCallback' ,10, 1); + WP_Mock::expectActionAdded( 'testAction', 'testCallback', 10, 1 ); + add_action( 'testAction', 'testCallback',10, 1 ); + add_filter('testFilter','testCallback', 10, 1); + WP_Mock::assertHooksAdded(); + \Mockery::close(); + } + + /** + * @runInSeparateProcess + */ + public function test_assertHooksAdded_for_filters_and_actions_fails() { + WP_Mock::bootstrap(); + WP_Mock::expectFilterAdded( 'testFilter', 'testCallback', 10, 1 ); + WP_Mock::expectActionAdded( 'testAction', 'testCallback', 10, 1 ); + $this->expectException('PHPUnit\Framework\ExpectationFailedException'); + WP_Mock::assertHooksAdded(); + \Mockery::close(); + } + + /** + * @runInSeparateProcess + */ + public function test_assertActionsCalled_actions() { + WP_Mock::bootstrap(); + WP_Mock::expectAction( 'testAction' ); + do_action('testAction'); + WP_Mock::assertActionsCalled(); + \Mockery::close(); + } + + /** + * @runInSeparateProcess + */ + public function test_assertActionsCalled_actions_fails() { + WP_Mock::bootstrap(); + WP_Mock::expectAction( 'testAction' ); + $this->expectException( 'PHPUnit\Framework\ExpectationFailedException' ); + WP_Mock::assertActionsCalled(); + \Mockery::close(); + } + + /** + * @runInSeparateProcess + */ + public function test_assertActionsCalled_filters() { + + WP_Mock::bootstrap(); + WP_Mock::expectFilter( 'testFilter','testVal' ); + apply_filters( 'testFilter','testVal' ); + WP_Mock::assertFiltersCalled(); + \Mockery::close(); + } + + /** + * @runInSeparateProcess + */ + public function test_assertActionsCalled_filters_fails() { + + WP_Mock::bootstrap(); + WP_Mock::expectFilter( 'testFilter2', 'testVal' ); + + $this->expectException( 'Mockery\Exception\InvalidCountException' ); + \Mockery::close(); + } +} \ No newline at end of file diff --git a/vendor/antecedent/patchwork/LICENSE b/vendor/antecedent/patchwork/LICENSE new file mode 100644 index 00000000..d1ccb7a5 --- /dev/null +++ b/vendor/antecedent/patchwork/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2010-2018 Ignas Rudaitis + +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/antecedent/patchwork/Patchwork.php b/vendor/antecedent/patchwork/Patchwork.php new file mode 100644 index 00000000..bf25f65f --- /dev/null +++ b/vendor/antecedent/patchwork/Patchwork.php @@ -0,0 +1,149 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork; + +if (function_exists('Patchwork\replace')) { + return; +} + +require_once __DIR__ . '/src/Exceptions.php'; +require_once __DIR__ . '/src/CallRerouting.php'; +require_once __DIR__ . '/src/CodeManipulation.php'; +require_once __DIR__ . '/src/Utils.php'; +require_once __DIR__ . '/src/Stack.php'; +require_once __DIR__ . '/src/Config.php'; + +function redefine($subject, callable $content) +{ + $handle = null; + foreach (array_slice(func_get_args(), 1) as $content) { + $handle = CallRerouting\connect($subject, $content, $handle); + } + $handle->silence(); + return $handle; +} + +function relay(array $args = null) +{ + return CallRerouting\relay($args); +} + +function fallBack() +{ + throw new Exceptions\NoResult; +} + +function restore(CallRerouting\Handle $handle) +{ + $handle->expire(); +} + +function restoreAll() +{ + CallRerouting\disconnectAll(); +} + +function silence(CallRerouting\Handle $handle) +{ + $handle->silence(); +} + +function assertEventuallyDefined(CallRerouting\Handle $handle) +{ + $handle->unsilence(); +} + +function getClass() +{ + return Stack\top('class'); +} + +function getCalledClass() +{ + return Stack\topCalledClass(); +} + +function getFunction() +{ + return Stack\top('function'); +} + +function getMethod() +{ + return getClass() . '::' . getFunction(); +} + +function configure() +{ + Config\locate(); +} + +function hasMissed($callable) +{ + return Utils\callableWasMissed($callable); +} + +function always($value) +{ + return function() use ($value) { + return $value; + }; +} + +Utils\alias('Patchwork', [ + 'redefine' => ['replace', 'replaceLater'], + 'relay' => 'callOriginal', + 'fallBack' => 'pass', + 'restore' => 'undo', + 'restoreAll' => 'undoAll', +]); + +configure(); + +Utils\markMissedCallables(); + +if (Utils\runningOnHHVM()) { + # no preprocessor needed on HHVM; + # just let Patchwork become a wrapper for fb_intercept() + spl_autoload_register('Patchwork\CallRerouting\deployQueue'); + return; +} + +CodeManipulation\Stream::wrap(); + +CodeManipulation\register([ + CodeManipulation\Actions\CodeManipulation\propagateThroughEval(), + CodeManipulation\Actions\CallRerouting\injectCallInterceptionCode(), + CodeManipulation\Actions\RedefinitionOfInternals\spliceNamedFunctionCalls(), + CodeManipulation\Actions\RedefinitionOfInternals\spliceDynamicCalls(), + CodeManipulation\Actions\RedefinitionOfNew\spliceAllInstantiations, + CodeManipulation\Actions\RedefinitionOfNew\publicizeConstructors, + CodeManipulation\Actions\ConflictPrevention\preventImportingOtherCopiesOfPatchwork(), +]); + +CodeManipulation\onImport([ + CodeManipulation\Actions\CallRerouting\markPreprocessedFiles(), +]); + +Utils\clearOpcodeCaches(); + +register_shutdown_function('Patchwork\Utils\clearOpcodeCaches'); + +CallRerouting\createStubsForInternals(); +CallRerouting\connectDefaultInternals(); + +require __DIR__ . '/src/Redefinitions/LanguageConstructs.php'; + +CodeManipulation\register([ + CodeManipulation\Actions\RedefinitionOfLanguageConstructs\spliceAllConfiguredLanguageConstructs(), + CodeManipulation\Actions\CallRerouting\injectQueueDeploymentCode(), +]); + +if (Utils\wasRunAsConsoleApp()) { + require __DIR__ . '/src/Console.php'; +} diff --git a/vendor/antecedent/patchwork/box.json b/vendor/antecedent/patchwork/box.json new file mode 100644 index 00000000..9dc3317b --- /dev/null +++ b/vendor/antecedent/patchwork/box.json @@ -0,0 +1,17 @@ +{ + "base-path": null, + "output": "patchwork.phar", + "check-requirements": false, + "compactors": [ + "KevinGH\\Box\\Compactor\\Php" + ], + "main": "Patchwork.php", + "directories": [ + "src" + ], + "files": [ + "Patchwork.php", + "LICENSE" + ], + "dump-autoload": false +} diff --git a/vendor/antecedent/patchwork/composer.json b/vendor/antecedent/patchwork/composer.json new file mode 100644 index 00000000..2868b883 --- /dev/null +++ b/vendor/antecedent/patchwork/composer.json @@ -0,0 +1,20 @@ +{ + "name": "antecedent/patchwork", + "homepage": "http://patchwork2.org/", + "description": "Method redefinition (monkey-patching) functionality for PHP.", + "keywords": ["testing", "redefinition", "runkit", "monkeypatching", "interception", "aop", "aspect"], + "license": "MIT", + "authors": [ + { + "name": "Ignas Rudaitis", + "email": "ignas.rudaitis@gmail.com" + } + ], + "minimum-stability": "stable", + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": ">=4" + } +} diff --git a/vendor/antecedent/patchwork/src/CallRerouting.php b/vendor/antecedent/patchwork/src/CallRerouting.php new file mode 100644 index 00000000..6980cc25 --- /dev/null +++ b/vendor/antecedent/patchwork/src/CallRerouting.php @@ -0,0 +1,619 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CallRerouting; + +require __DIR__ . '/CallRerouting/Handle.php'; +require __DIR__ . '/CallRerouting/Decorator.php'; + +use Patchwork\Utils; +use Patchwork\Stack; +use Patchwork\Config; +use Patchwork\Exceptions; +use Patchwork\CodeManipulation; +use Patchwork\CodeManipulation\Actions\RedefinitionOfLanguageConstructs; +use Patchwork\CodeManipulation\Actions\RedefinitionOfNew; + +const INTERNAL_REDEFINITION_NAMESPACE = 'Patchwork\Redefinitions'; +const EVALUATED_CODE_FILE_NAME_SUFFIX = '/\(\d+\) : eval\(\)\'d code$/'; +const INSTANTIATOR_NAMESPACE = 'Patchwork\Instantiators'; +const INSTANTIATOR_DEFAULT_ARGUMENT = 'Patchwork\CallRerouting\INSTANTIATOR_DEFAULT_ARGUMENT'; + +const INTERNAL_STUB_CODE = ' + namespace @ns_for_redefinitions; + function @name(@signature) { + $__pwArgs = \array_slice(\debug_backtrace()[0]["args"], 1); + if (!empty($__pwNamespace) && \function_exists($__pwNamespace . "\\\\@name")) { + return \call_user_func_array($__pwNamespace . "\\\\@name", $__pwArgs); + } + @interceptor; + return \call_user_func_array("@name", $__pwArgs); + } +'; + +const INSTANTIATOR_CODE = ' + namespace @namespace; + class @instantiator { + function instantiate(@parameters) { + $__pwArgs = \debug_backtrace()[0]["args"]; + foreach ($__pwArgs as $__pwOffset => $__pwValue) { + if ($__pwValue === \Patchwork\CallRerouting\INSTANTIATOR_DEFAULT_ARGUMENT) { + unset($__pwArgs[$__pwOffset]); + } + } + switch (count($__pwArgs)) { + case 0: + return new \@class; + case 1: + return new \@class($__pwArgs[0]); + case 2: + return new \@class($__pwArgs[0], $__pwArgs[1]); + case 3: + return new \@class($__pwArgs[0], $__pwArgs[1], $__pwArgs[2]); + case 4: + return new \@class($__pwArgs[0], $__pwArgs[1], $__pwArgs[2], $__pwArgs[3]); + case 5: + return new \@class($__pwArgs[0], $__pwArgs[1], $__pwArgs[2], $__pwArgs[3], $__pwArgs[4]); + default: + $__pwReflector = new \ReflectionClass(\'@class\'); + return $__pwReflector->newInstanceArgs($__pwArgs); + } + } + } +'; + +function connect($source, callable $target, Handle $handle = null, $partOfWildcard = false) +{ + $source = translateIfLanguageConstruct($source); + $handle = $handle ?: new Handle; + list($class, $method) = Utils\interpretCallable($source); + if (constitutesWildcard($source)) { + return applyWildcard($source, $target, $handle); + } + if (Utils\isOwnName($class) || Utils\isOwnName($method)) { + return $handle; + } + validate($source, $partOfWildcard); + if (empty($class)) { + if (Utils\callableDefined($source) && (new \ReflectionFunction($method))->isInternal()) { + $stub = INTERNAL_REDEFINITION_NAMESPACE . '\\' . $source; + return connect($stub, $target, $handle, $partOfWildcard); + } + $handle = connectFunction($method, $target, $handle); + } else { + if (Utils\callableDefined($source)) { + if ($method === 'new') { + $handle = connectInstantiation($class, $target, $handle); + } elseif ((new \ReflectionMethod($class, $method))->isUserDefined()) { + $handle = connectMethod($source, $target, $handle); + } else { + throw new InternalMethodsNotSupported($source); + } + } else { + $handle = queueConnection($source, $target, $handle); + if (Utils\runningOnHHVM()) { + connectOnHHVM("$class::$method", $handle); + } + } + } + attachExistenceAssertion($handle, $source); + return $handle; +} + +function constitutesWildcard($source) +{ + $source = Utils\interpretCallable($source); + $source = Utils\callableToString($source); + return strcspn($source, '*{,}') != strlen($source); +} + +function applyWildcard($wildcard, callable $target, Handle $handle = null) +{ + $handle = $handle ?: new Handle; + list($class, $method, $instance) = Utils\interpretCallable($wildcard); + if (!empty($instance)) { + foreach (Utils\matchWildcard($method, get_class_methods($instance)) as $item) { + if (!$handle->hasTag($item)) { + connect([$instance, $item], $target, $handle); + $handle->tag($item); + } + } + return $handle; + } + + $callables = Utils\matchWildcard($wildcard, Utils\getRedefinableCallables()); + foreach ($callables as $callable) { + if (!inPreprocessedFile($callable) || $handle->hasTag($callable)) { + continue; + } + if (function_exists($callable)) { + # Restore lower/upper case distinction + $callable = (new \ReflectionFunction($callable))->getName(); + } + connect($callable, $target, $handle, true); + $handle->tag($callable); + } + if (!isset($class) || !class_exists($class, false)) { + queueConnection($wildcard, $target, $handle); + } + return $handle; +} + +function attachExistenceAssertion(Handle $handle, $function) +{ + $handle->addExpirationHandler(function() use ($function) { + if (!Utils\callableDefined($function)) { + # Not using exceptions because this might happen during PHP shutdown + $message = '%s() was never defined during the lifetime of its redefinition'; + trigger_error(sprintf($message, Utils\callableToString($function)), E_USER_WARNING); + } + }); +} + +function validate($function, $partOfWildcard = false) +{ + list($class, $method) = Utils\interpretCallable($function); + if (!Utils\callableDefined($function) || $method === 'new') { + return; + } + $reflection = Utils\reflectCallable($function); + $name = Utils\callableToString($function); + if ($reflection->isInternal() && !in_array($name, Config\getRedefinableInternals())) { + throw new Exceptions\NotUserDefined($function); + } + if (Utils\runningOnHHVM()) { + if ($reflection->isInternal()) { + throw new Exceptions\InternalsNotSupportedOnHHVM($function); + } + return; + } + if (!$reflection->isInternal() && !inPreprocessedFile($function) && !$partOfWildcard) { + throw new Exceptions\DefinedTooEarly($function); + } +} + +function inPreprocessedFile($callable) +{ + if (Utils\runningOnHHVM()) { + return true; + } + if (Utils\isOwnName(Utils\callableToString($callable))) { + return false; + } + $file = Utils\reflectCallable($callable)->getFileName(); + $evaluated = preg_match(EVALUATED_CODE_FILE_NAME_SUFFIX, $file); + return $evaluated || !empty(State::$preprocessedFiles[$file]); +} + +function connectFunction($function, callable $target, Handle $handle = null) +{ + $handle = $handle ?: new Handle; + $routes = &State::$routes[null][$function]; + $offset = Utils\append($routes, [$target, $handle]); + $handle->addReference($routes[$offset]); + if (Utils\runningOnHHVM()) { + connectOnHHVM($function, $handle); + } + return $handle; +} + +function queueConnection($source, callable $target, Handle $handle = null) +{ + $handle = $handle ?: new Handle; + $offset = Utils\append(State::$queue, [$source, $target, $handle]); + $handle->addReference(State::$queue[$offset]); + return $handle; +} + +function deployQueue() +{ + foreach (State::$queue as $offset => $item) { + if (empty($item)) { + unset(State::$queue[$offset]); + continue; + } + list($source, $target, $handle) = $item; + if (Utils\callableDefined($source) || constitutesWildcard($source)) { + connect($source, $target, $handle); + unset(State::$queue[$offset]); + } + } +} + +function connectMethod($function, callable $target, Handle $handle = null) +{ + $handle = $handle ?: new Handle; + list($class, $method, $instance) = Utils\interpretCallable($function); + $target = new Decorator($target); + $target->superclass = $class; + $target->method = $method; + $target->instance = $instance; + $reflection = Utils\reflectCallable($function); + $declaringClass = $reflection->getDeclaringClass(); + $class = $declaringClass->getName(); + if (!Utils\runningOnHHVM()) { + $aliases = $declaringClass->getTraitAliases(); + if (isset($aliases[$method])) { + list($trait, $method) = explode('::', $aliases[$method]); + } + } + $routes = &State::$routes[$class][$method]; + $offset = Utils\append($routes, [$target, $handle]); + $handle->addReference($routes[$offset]); + if (Utils\runningOnHHVM()) { + connectOnHHVM("$class::$method", $handle); + } + return $handle; +} + +function connectInstantiation($class, callable $target, Handle $handle = null) +{ + if (!Config\isNewKeywordRedefinable()) { + throw new Exceptions\NewKeywordNotRedefinable; + } + $handle = $handle ?: new Handle; + $class = strtr($class, ['\\' => '__']); + $routes = &State::$routes["Patchwork\\Instantiators\\$class"]['instantiate']; + $offset = Utils\append($routes, [$target, $handle]); + $handle->addReference($routes[$offset]); + return $handle; +} + +function disconnectAll() +{ + foreach (State::$routes as $class => $routesByClass) { + foreach ($routesByClass as $method => $routes) { + foreach ($routes as $route) { + list($callback, $handle) = $route; + if ($handle !== null) { + $handle->expire(); + } + } + } + } + State::$routes = []; + connectDefaultInternals(); +} + +function dispatchTo(callable $target) +{ + return call_user_func_array($target, Stack\top('args')); +} + +function dispatch($class, $calledClass, $method, $frame, &$result, array $args = null) +{ + $isInternalStub = strpos($method, INTERNAL_REDEFINITION_NAMESPACE) === 0; + $isLanguageConstructStub = strpos($method, RedefinitionOfLanguageConstructs\LANGUAGE_CONSTRUCT_PREFIX) === 0; + $isInstantiator = strpos($method, INSTANTIATOR_NAMESPACE) === 0; + if ($isInternalStub && !$isLanguageConstructStub && $args === null) { + # Mind the namespace-of-origin argument + $trace = debug_backtrace(); + $args = array_reverse($trace)[$frame - 1]['args']; + array_shift($args); + } + if ($isInstantiator) { + $trace = debug_backtrace(); + $args = $args ?: array_reverse($trace)[$frame - 1]['args']; + foreach ($args as $offset => $value) { + if ($value === INSTANTIATOR_DEFAULT_ARGUMENT) { + unset($args[$offset]); + } + } + } + $success = false; + Stack\pushFor($frame, $calledClass, function() use ($class, $method, &$result, &$success) { + foreach (getRoutesFor($class, $method) as $offset => $route) { + if (empty($route)) { + unset(State::$routes[$class][$method][$offset]); + continue; + } + State::$routeStack[] = [$class, $method, $offset]; + try { + $result = dispatchTo(reset($route)); + $success = true; + } catch (Exceptions\NoResult $e) { + array_pop(State::$routeStack); + continue; + } + array_pop(State::$routeStack); + if ($success) { + break; + } + } + }, $args); + return $success; +} + +function relay(array $args = null) +{ + list($class, $method, $offset) = end(State::$routeStack); + $route = &State::$routes[$class][$method][$offset]; + $backup = $route; + $route = ['Patchwork\fallBack', new Handle]; + $top = Stack\top(); + if ($args === null) { + $args = $top['args']; + } + $isInternalStub = strpos($method, INTERNAL_REDEFINITION_NAMESPACE) === 0; + $isLanguageConstructStub = strpos($method, RedefinitionOfLanguageConstructs\LANGUAGE_CONSTRUCT_PREFIX) === 0; + if ($isInternalStub && !$isLanguageConstructStub) { + array_unshift($args, ''); + } + try { + if (isset($top['class'])) { + $reflection = new \ReflectionMethod(Stack\topCalledClass(), $top['function']); + $reflection->setAccessible(true); + $result = $reflection->invokeArgs(Stack\top('object'), $args); + } else { + $result = call_user_func_array($top['function'], $args); + } + } catch (\Exception $e) { + $exception = $e; + } + $route = $backup; + if (isset($exception)) { + throw $exception; + } + return $result; +} + +function connectOnHHVM($function, Handle $handle) +{ + fb_intercept($function, function($name, $obj, $args, $data, &$done) { + deployQueue(); + list($class, $method) = Utils\interpretCallable($name); + $calledClass = null; + if (is_string($obj)) { + $calledClass = $obj; + } elseif (is_object($obj)) { + $calledClass = get_class($obj); + } + $frame = count(debug_backtrace(0)) - 1; + $result = null; + $done = dispatch($class, $calledClass, $method, $frame, $result, $args); + return $result; + }); + $handle->addExpirationHandler(getHHVMExpirationHandler($function)); +} + +function getHHVMExpirationHandler($function) +{ + return function() use ($function) { + list($class, $method) = Utils\interpretCallable($function); + $empty = true; + foreach (getRoutesFor($class, $method) as $offset => $route) { + if (!empty($route)) { + $empty = false; + break; + } else { + unset(State::$routes[$class][$method][$offset]); + } + } + if ($empty) { + fb_intercept($function, null); + } + }; +} + +function getRoutesFor($class, $method) +{ + if (!isset(State::$routes[$class][$method])) { + return []; + } + return array_reverse(State::$routes[$class][$method], true); +} + +function dispatchDynamic($callable, array $arguments) +{ + list($class, $method) = Utils\interpretCallable($callable); + $translation = INTERNAL_REDEFINITION_NAMESPACE . '\\' . $method; + if ($class === null && function_exists($translation)) { + $callable = $translation; + # Mind the namespace-of-origin argument + array_unshift($arguments, ''); + } + return call_user_func_array($callable, $arguments); +} + +function createStubsForInternals() +{ + $namespace = INTERNAL_REDEFINITION_NAMESPACE; + foreach (Config\getRedefinableInternals() as $name) { + if (function_exists($namespace . '\\' . $name)) { + continue; + } + $signature = ['$__pwNamespace']; + foreach ((new \ReflectionFunction($name))->getParameters() as $offset => $argument) { + $formal = ''; + if ($argument->isPassedByReference()) { + $formal .= '&'; + } + $formal .= '$' . $argument->getName(); + $isVariadic = is_callable([$argument, 'isVariadic']) ? $argument->isVariadic() : false; + if ($argument->isOptional() || $isVariadic || ($name === 'define' && $offset === 2)) { + continue; + } + $signature[] = $formal; + } + $refs = sprintf('[%s]', join(', ', $signature)); + $interceptor = sprintf( + str_replace( + '$__pwRefOffset = 0;', + '$__pwRefOffset = 1;', + \Patchwork\CodeManipulation\Actions\CallRerouting\CALL_INTERCEPTION_CODE + ), + $refs + ); + eval(strtr(INTERNAL_STUB_CODE, [ + '@name' => $name, + '@signature' => join(', ', $signature), + '@interceptor' => $interceptor, + '@ns_for_redefinitions' => INTERNAL_REDEFINITION_NAMESPACE, + ])); + } +} + +/** + * This is needed, for instance, to intercept the time() call in call_user_func('time'). + * + * For that to happen, we require that if at least one internal function is redefinable, then + * call_user_func, preg_replace_callback and other callback-taking internal functions also be + * redefinable: see Patchwork\Config. + * + * Here, we go through the callback-taking internals and add argument-inspecting patches + * (redefinitions) to them. + * + * The patches are then expected to find the "nested" internal calls, such as the 'time' argument + * in call_user_func('time'), and invoke their respective redefinitions, if any. + */ +function connectDefaultInternals() +{ + # call_user_func() etc. are not a problem if no other internal functions are redefined + if (Config\getRedefinableInternals() === []) { + return; + } + foreach (Config\getDefaultRedefinableInternals() as $function) { + # Which arguments are callbacks? Store their offsets in the following array. + $offsets = []; + foreach ((new \ReflectionFunction($function))->getParameters() as $offset => $argument) { + $name = $argument->getName(); + if (strpos($name, 'call') !== false || strpos($name, 'func') !== false) { + $offsets[] = $offset; + } + } + connect($function, function() use ($function, $offsets) { + # This is the argument-inspecting patch. + $args = Stack\top('args'); + $caller = Stack\all()[1]; + foreach ($offsets as $offset) { + # Callback absent + if (!isset($args[$offset])) { + continue; + } + $callable = $args[$offset]; + # Callback is a closure => definitely not internal + if ($callable instanceof \Closure) { + continue; + } + list($class, $method, $instance) = Utils\interpretCallable($callable); + if (empty($class)) { + # Callback is global function, which might be internal too. + $args[$offset] = function() use ($callable) { + return dispatchDynamic($callable, func_get_args()); + }; + } + # Callback involves a class => not internal either, since the only internals that + # Patchwork can handle as of 2.0 are global functions. + # However, we must handle all kinds of opaque access here too, such as self:: and + # private methods, because we're actually patching a stub (see INTERNAL_STUB_CODE) + # and not directly call_user_func itself (or usort, or any other of those). + # We must compensate for scope that is lost, and that callback-taking functions + # can make use of. + if (!empty($class)) { + if ($class === 'self' || $class === 'static' || $class === 'parent') { + # We do not discriminate between early and late static binding here: FIXME. + $actualClass = $caller['class']; + if ($class === 'parent') { + $actualClass = get_parent_class($actualClass); + } + $class = $actualClass; + } + + # When calling a parent constructor, the reference to the object being + # constructed needs to be extracted from the stack info. + # Also turned out to be necessary to solve this, without any parent + # constructors involved: https://github.com/antecedent/patchwork/issues/99 + if (is_null($instance) && isset($caller['object'])) { + $instance = $caller['object']; + } + try { + $reflection = new \ReflectionMethod($class, $method); + $reflection->setAccessible(true); + $args[$offset] = function() use ($reflection, $instance) { + return $reflection->invokeArgs($instance, func_get_args()); + }; + } catch (\ReflectionException $e) { + # If it's an invalid callable, then just prevent the unexpected propagation + # of ReflectionExceptions. + } + } + } + # Give the inspected arguments back to the *original* definition of the + # callback-taking function, e.g. \array_map(). This works given that the + # present patch is the innermost. + return call_user_func_array($function, $args); + }); + } +} + +/** + * @since 2.0.5 + * + * As of version 2.0.5, this is used to accommodate language constructs + * (echo, eval, exit and others) within the concept of callable. + */ +function translateIfLanguageConstruct($callable) +{ + if (!is_string($callable)) { + return $callable; + } + if (in_array($callable, Config\getRedefinableLanguageConstructs())) { + return RedefinitionOfLanguageConstructs\LANGUAGE_CONSTRUCT_PREFIX . $callable; + } elseif (in_array($callable, Config\getSupportedLanguageConstructs())) { + throw new Exceptions\NotUserDefined($callable); + } else { + return $callable; + } +} + +function resolveClassToInstantiate($class, $calledClass) +{ + $pieces = explode('\\', $class); + $last = array_pop($pieces); + if (in_array($last, ['self', 'static', 'parent'])) { + $frame = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]; + if ($last == 'self') { + $class = $frame['class']; + } elseif ($last == 'parent') { + $class = get_parent_class($frame['class']); + } elseif ($last == 'static') { + $class = $calledClass; + } + } + return ltrim($class, '\\'); +} + +function getInstantiator($class, $calledClass) +{ + $namespace = INSTANTIATOR_NAMESPACE; + $class = resolveClassToInstantiate($class, $calledClass); + $adaptedName = strtr($class, ['\\' => '__']); + if (!class_exists("$namespace\\$adaptedName")) { + $constructor = (new \ReflectionClass($class))->getConstructor(); + list($parameters, $arguments) = Utils\getParameterAndArgumentLists($constructor); + $code = strtr(INSTANTIATOR_CODE, [ + '@namespace' => INSTANTIATOR_NAMESPACE, + '@instantiator' => $adaptedName, + '@class' => $class, + '@parameters' => $parameters, + ]); + RedefinitionOfNew\suspendFor(function() use ($code) { + eval(CodeManipulation\transformForEval($code)); + }); + } + $instantiator = "$namespace\\$adaptedName"; + return new $instantiator; +} + +class State +{ + static $routes = []; + static $queue = []; + static $preprocessedFiles = []; + static $routeStack = []; +} diff --git a/vendor/antecedent/patchwork/src/CallRerouting/Decorator.php b/vendor/antecedent/patchwork/src/CallRerouting/Decorator.php new file mode 100644 index 00000000..1a641df0 --- /dev/null +++ b/vendor/antecedent/patchwork/src/CallRerouting/Decorator.php @@ -0,0 +1,62 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CallRerouting; + +use Patchwork; +use Patchwork\Stack; + +class Decorator +{ + public $superclass; + public $instance; + public $method; + + private $patch; + + public function __construct($patch) + { + $this->patch = $patch; + } + + public function __invoke() + { + $top = Stack\top(); + $superclassMatches = $this->superclassMatches(); + $instanceMatches = $this->instanceMatches($top); + $methodMatches = $this->methodMatches($top); + if ($superclassMatches && $instanceMatches && $methodMatches) { + $patch = $this->patch; + if (isset($top["object"]) && $patch instanceof \Closure) { + $patch = $patch->bindTo($top["object"], $this->superclass); + } + return dispatchTo($patch); + } + Patchwork\fallBack(); + } + + private function superclassMatches() + { + return $this->superclass === null || + Stack\topCalledClass() === $this->superclass || + is_subclass_of(Stack\topCalledClass(), $this->superclass); + } + + private function instanceMatches(array $top) + { + return $this->instance === null || + (isset($top["object"]) && $top["object"] === $this->instance); + } + + private function methodMatches(array $top) + { + return $this->method === null || + $this->method === 'new' || + $top["function"] === $this->method; + } +} diff --git a/vendor/antecedent/patchwork/src/CallRerouting/Handle.php b/vendor/antecedent/patchwork/src/CallRerouting/Handle.php new file mode 100644 index 00000000..2c0d96d3 --- /dev/null +++ b/vendor/antecedent/patchwork/src/CallRerouting/Handle.php @@ -0,0 +1,65 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CallRerouting; + +class Handle +{ + private $references = []; + private $expirationHandlers = []; + private $silenced = false; + private $tags = []; + + public function __destruct() + { + $this->expire(); + } + + public function tag($tag) + { + $this->tags[] = $tag; + } + + public function hasTag($tag) + { + return in_array($tag, $this->tags); + } + + public function addReference(&$reference) + { + $this->references[] = &$reference; + } + + public function expire() + { + foreach ($this->references as &$reference) { + $reference = null; + } + if (!$this->silenced) { + foreach ($this->expirationHandlers as $expirationHandler) { + $expirationHandler(); + } + } + $this->expirationHandlers = []; + } + + public function addExpirationHandler(callable $expirationHandler) + { + $this->expirationHandlers[] = $expirationHandler; + } + + public function silence() + { + $this->silenced = true; + } + + public function unsilence() + { + $this->silenced = false; + } +} diff --git a/vendor/antecedent/patchwork/src/CodeManipulation.php b/vendor/antecedent/patchwork/src/CodeManipulation.php new file mode 100644 index 00000000..44c992b0 --- /dev/null +++ b/vendor/antecedent/patchwork/src/CodeManipulation.php @@ -0,0 +1,161 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CodeManipulation; + +require __DIR__ . '/CodeManipulation/Source.php'; +require __DIR__ . '/CodeManipulation/Stream.php'; +require __DIR__ . '/CodeManipulation/Actions/Generic.php'; +require __DIR__ . '/CodeManipulation/Actions/CallRerouting.php'; +require __DIR__ . '/CodeManipulation/Actions/CodeManipulation.php'; +require __DIR__ . '/CodeManipulation/Actions/Namespaces.php'; +require __DIR__ . '/CodeManipulation/Actions/RedefinitionOfInternals.php'; +require __DIR__ . '/CodeManipulation/Actions/RedefinitionOfLanguageConstructs.php'; +require __DIR__ . '/CodeManipulation/Actions/ConflictPrevention.php'; +require __DIR__ . '/CodeManipulation/Actions/RedefinitionOfNew.php'; +require __DIR__ . '/CodeManipulation/Actions/Arguments.php'; + +use Patchwork\Exceptions; +use Patchwork\Utils; +use Patchwork\Config; + +const OUTPUT_DESTINATION = 'php://memory'; +const OUTPUT_ACCESS_MODE = 'rb+'; + +function transform(Source $s) +{ + foreach (State::$actions as $action) { + $action($s); + } +} + +function transformString($code) +{ + $source = new Source($code); + transform($source); + return (string) $source; +} + +function transformForEval($code) +{ + $prefix = "file), $source); +} + +function availableCached($file) +{ + if (!cacheEnabled()) { + return false; + } + $cached = getCachedPath($file); + return file_exists($cached) && + filemtime($file) <= filemtime($cached) && + Config\getTimestamp() <= filemtime($cached); +} + +function internalToCache($file) +{ + if (!cacheEnabled()) { + return false; + } + return strpos($file, Config\getCachePath() . '/') === 0 + || strpos($file, Config\getCachePath() . DIRECTORY_SEPARATOR) === 0; +} + +function transformAndOpen($file) +{ + foreach (State::$importListeners as $listener) { + $listener($file); + } + if (!internalToCache($file) && availableCached($file)) { + return fopen(getCachedPath($file), 'r'); + } + $resource = fopen(OUTPUT_DESTINATION, OUTPUT_ACCESS_MODE); + $code = file_get_contents($file, true); + $source = new Source($code); + $source->file = $file; + transform($source); + if (!internalToCache($file) && cacheEnabled()) { + storeInCache($source); + return transformAndOpen($file); + } + fwrite($resource, $source); + rewind($resource); + return $resource; +} + +function prime($file) +{ + fclose(transformAndOpen($file)); +} + +function shouldTransform($file) +{ + return !Config\isBlacklisted($file) || Config\isWhitelisted($file); +} + +function register($actions) +{ + State::$actions = array_merge(State::$actions, (array) $actions); +} + +function onImport($listeners) +{ + State::$importListeners = array_merge(State::$importListeners, (array) $listeners); +} + +class State +{ + static $actions = []; + static $importListeners = []; + static $cacheIndex = []; + static $cacheIndexFile; +} diff --git a/vendor/antecedent/patchwork/src/CodeManipulation/Actions/Arguments.php b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/Arguments.php new file mode 100644 index 00000000..d0c9e77e --- /dev/null +++ b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/Arguments.php @@ -0,0 +1,49 @@ + + * @copyright 2010-2021 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CodeManipulation\Actions\Arguments; + +use Patchwork\CodeManipulation\Source; +use Patchwork\CodeManipulation\Actions\Generic; + +/** + * @since 2.1.13 + */ +function readNames(Source $s, $pos) +{ + $result = []; + $pos++; + while (!$s->is(Generic\RIGHT_ROUND, $pos)) { + if ($s->is([Generic\LEFT_ROUND, Generic\LEFT_SQUARE, Generic\LEFT_CURLY], $pos)) { + $pos = $s->match($pos); + } else { + if ($s->is(T_VARIABLE, $pos)) { + $result[] = $s->read($pos); + } elseif ($s->is(Generic\ELLIPSIS, $pos)) { + $pos = $s->skip(Source::junk(), $pos); + $result[] = '...' . $s->read($pos); + } + $pos++; + } + } + return $result; +} + +/** + * @since 2.1.13 + */ +function constructReferenceArray(array $names) +{ + $names = array_map(function($name) { + if ($name[0] === '.') { + return '], ' . substr($name, 3) . ', ['; + } + return '&' . $name; + }, $names); + return 'array_merge([' . join(', ', $names) . '])'; +} \ No newline at end of file diff --git a/vendor/antecedent/patchwork/src/CodeManipulation/Actions/CallRerouting.php b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/CallRerouting.php new file mode 100644 index 00000000..a0488ef6 --- /dev/null +++ b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/CallRerouting.php @@ -0,0 +1,70 @@ + + * @link http://patchwork2.org/ + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CodeManipulation\Actions\CallRerouting; + +use Patchwork\CodeManipulation\Actions\Generic; +use Patchwork\CallRerouting; +use Patchwork\Utils; + +const CALL_INTERCEPTION_CODE = ' + $__pwClosureName = __NAMESPACE__ ? __NAMESPACE__ . "\\\\{closure}" : "\\\\{closure}"; + $__pwClass = (__CLASS__ && __FUNCTION__ !== $__pwClosureName) ? __CLASS__ : null; + if (!empty(\Patchwork\CallRerouting\State::$routes[$__pwClass][__FUNCTION__])) { + $__pwCalledClass = $__pwClass ? \get_called_class() : null; + $__pwFrame = \count(\debug_backtrace(0)); + $__pwRefs = %s; + $__pwRefOffset = 0; + if (\Patchwork\CallRerouting\dispatch($__pwClass, $__pwCalledClass, __FUNCTION__, $__pwFrame, $__pwResult, \array_merge(\array_slice($__pwRefs, $__pwRefOffset, \func_num_args()), \array_slice(\func_get_args(), \count($__pwRefs))))) { + return $__pwResult; + } + } + unset($__pwClass, $__pwCalledClass, $__pwResult, $__pwClosureName, $__pwFrame, $__pwRefs, $__pwRefOffset); +'; + +const CALL_INTERCEPTION_CODE_VOID_TYPED = ' + $__pwClosureName = __NAMESPACE__ ? __NAMESPACE__ . "\\\\{closure}" : "\\\\{closure}"; + $__pwClass = (__CLASS__ && __FUNCTION__ !== $__pwClosureName) ? __CLASS__ : null; + if (!empty(\Patchwork\CallRerouting\State::$routes[$__pwClass][__FUNCTION__])) { + $__pwCalledClass = $__pwClass ? \get_called_class() : null; + $__pwFrame = \count(\debug_backtrace(0)); + $__pwRefs = %s; + $__pwRefOffset = 0; + if (\Patchwork\CallRerouting\dispatch($__pwClass, $__pwCalledClass, __FUNCTION__, $__pwFrame, $__pwResult, \array_merge(\array_slice($__pwRefs, $__pwRefOffset, \func_num_args()), \array_slice(\func_get_args(), \count($__pwRefs))))) { + if ($__pwResult !== null) { + throw new \Patchwork\Exceptions\NonNullToVoid; + } + return; + } + } + unset($__pwClass, $__pwCalledClass, $__pwResult, $__pwClosureName, $__pwFrame, $__pwRefOffset); +'; + +const QUEUE_DEPLOYMENT_CODE = '\Patchwork\CallRerouting\deployQueue()'; + +function markPreprocessedFiles() +{ + return Generic\markPreprocessedFiles(CallRerouting\State::$preprocessedFiles); +} + +function injectCallInterceptionCode() +{ + return Generic\prependCodeToFunctions( + Utils\condense(CALL_INTERCEPTION_CODE), + Utils\condense(CALL_INTERCEPTION_CODE_VOID_TYPED), + true + ); +} + +function injectQueueDeploymentCode() +{ + return Generic\chain(array( + Generic\injectFalseExpressionAtBeginnings(QUEUE_DEPLOYMENT_CODE), + Generic\injectCodeAfterClassDefinitions(QUEUE_DEPLOYMENT_CODE . ';'), + )); +} diff --git a/vendor/antecedent/patchwork/src/CodeManipulation/Actions/CodeManipulation.php b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/CodeManipulation.php new file mode 100644 index 00000000..cbf96973 --- /dev/null +++ b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/CodeManipulation.php @@ -0,0 +1,26 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CodeManipulation\Actions\CodeManipulation; + +use Patchwork\CodeManipulation\Actions\Generic; +use Patchwork\CodeManipulation\Source; + +const EVAL_ARGUMENT_WRAPPER = '\Patchwork\CodeManipulation\transformForEval'; + +function propagateThroughEval() +{ + return Generic\wrapUnaryConstructArguments(T_EVAL, EVAL_ARGUMENT_WRAPPER); +} + +function flush() +{ + return function(Source $s) { + $s->flush(); + }; +} diff --git a/vendor/antecedent/patchwork/src/CodeManipulation/Actions/ConflictPrevention.php b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/ConflictPrevention.php new file mode 100644 index 00000000..634296b7 --- /dev/null +++ b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/ConflictPrevention.php @@ -0,0 +1,33 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CodeManipulation\Actions\ConflictPrevention; + +use Patchwork\CodeManipulation\Source; + +/** + * @since 2.0.1 + * + * Serves to avoid "Cannot redeclare Patchwork\redefine()" errors. + */ +function preventImportingOtherCopiesOfPatchwork() +{ + return function(Source $s) { + $namespaceKeyword = $s->next(T_NAMESPACE, -1); + if ($namespaceKeyword === INF || $namespaceKeyword < 2) { + return; + } + if ($s->read($namespaceKeyword, 4) == 'namespace Patchwork;') { + $pattern = '/@copyright\s+2010(-\d+)? Ignas Rudaitis/'; + if (preg_match($pattern, $s->read($namespaceKeyword - 2))) { + # Clear the file completely (in memory) + $s->splice('', 0, count($s->tokens)); + } + } + }; +} diff --git a/vendor/antecedent/patchwork/src/CodeManipulation/Actions/Generic.php b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/Generic.php new file mode 100644 index 00000000..e4550cd0 --- /dev/null +++ b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/Generic.php @@ -0,0 +1,162 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CodeManipulation\Actions\Generic; + +use Patchwork\CodeManipulation\Actions\Arguments; +use Patchwork\CodeManipulation\Source; +use Patchwork\Utils; + +const LEFT_ROUND = '('; +const RIGHT_ROUND = ')'; +const LEFT_CURLY = '{'; +const RIGHT_CURLY = '}'; +const LEFT_SQUARE = '['; +const RIGHT_SQUARE = ']'; +const SEMICOLON = ';'; + +foreach (['NAME_FULLY_QUALIFIED', 'NAME_QUALIFIED', 'NAME_RELATIVE', 'ELLIPSIS', 'ATTRIBUTE'] as $constant) { + if (defined('T_' . $constant)) { + define(__NAMESPACE__ . '\\' . $constant, constant('T_' . $constant)); + } else { + define(__NAMESPACE__ . '\\' . $constant, -1); + } +} + +function markPreprocessedFiles(&$target) +{ + return function($file) use (&$target) { + $target[$file] = true; + }; +} + +function prependCodeToFunctions($code, $voidTypedVariant = null, $fillArgRefs = false) +{ + if ($voidTypedVariant === null) { + $voidTypedVariant = $code; + } + return function(Source $s) use ($code, $voidTypedVariant, $fillArgRefs) { + foreach ($s->all(T_FUNCTION) as $function) { + # Skip "use function" + $previous = $s->skipBack(Source::junk(), $function); + if ($s->is(T_USE, $previous)) { + continue; + } + $voidTyped = isVoidTyped($s, $function); + $argRefs = null; + if ($fillArgRefs) { + $parenthesis = $s->next(LEFT_ROUND, $function); + $args = Arguments\readNames($s, $parenthesis); + $argRefs = Arguments\constructReferenceArray($args); + } + $bracket = $s->next(LEFT_CURLY, $function); + if (Utils\generatorsSupported()) { + # Skip generators + $yield = $s->next(T_YIELD, $bracket); + if ($yield < $s->match($bracket)) { + continue; + } + } + $semicolon = $s->next(SEMICOLON, $function); + if ($bracket < $semicolon) { + $variant = $voidTyped ? $voidTypedVariant : $code; + if ($fillArgRefs) { + $variant = sprintf($variant, $argRefs); + } + $s->splice($variant, $bracket + 1); + } + } + }; +} + +function isVoidTyped(Source $s, $function) +{ + $parenthesis = $s->next(LEFT_ROUND, $function); + $next = $s->skip(Source::junk(), $s->match($parenthesis)); + if ($s->is(T_USE, $next)) { + $next = $s->skip(Source::junk(), $s->match($s->next(LEFT_ROUND, $next))); + } + if ($s->is(':', $next)) { + return $s->read($s->skip(Source::junk(), $next), 1) === 'void'; + } + return false; +} + +function wrapUnaryConstructArguments($construct, $wrapper) +{ + return function(Source $s) use ($construct, $wrapper) { + foreach ($s->all($construct) as $match) { + $pos = $s->next(LEFT_ROUND, $match); + $s->splice($wrapper . LEFT_ROUND, $pos + 1); + $s->splice(RIGHT_ROUND, $s->match($pos)); + } + }; +} + +function injectFalseExpressionAtBeginnings($expression) +{ + return function(Source $s) use ($expression) { + $openingTags = $s->all(T_OPEN_TAG); + $openingTagsWithEcho = $s->all(T_OPEN_TAG_WITH_ECHO); + if (empty($openingTags) && empty($openingTagsWithEcho)) { + return; + } + if (!empty($openingTags) && + (empty($openingTagsWithEcho) || reset($openingTags) < reset($openingTagsWithEcho))) { + $pos = reset($openingTags); + # Skip initial declare() statements + while ($s->read($s->skip(Source::junk(), $pos)) === 'declare') { + $pos = $s->next(SEMICOLON, $pos); + } + # Enter first namespace + $namespaceKeyword = $s->next(T_NAMESPACE, $pos); + if ($namespaceKeyword !== INF) { + $semicolon = $s->next(SEMICOLON, $namespaceKeyword); + $leftBracket = $s->next(LEFT_CURLY, $namespaceKeyword); + $pos = min($semicolon, $leftBracket); + } + $s->splice(' ' . $expression . ';', $pos + 1); + } else { + $openingTag = reset($openingTagsWithEcho); + $closingTag = $s->next(T_CLOSE_TAG, $openingTag); + $semicolon = $s->next(SEMICOLON, $openingTag); + $s->splice(' (' . $expression . ') ?: (', $openingTag + 1); + $s->splice(') ', min($closingTag, $semicolon)); + } + }; +} + +function injectCodeAfterClassDefinitions($code) +{ + return function(Source $s) use ($code) { + foreach ($s->all(T_CLASS) as $match) { + if ($s->is([T_DOUBLE_COLON, T_NEW], $s->skipBack(Source::junk(), $match))) { + # Not a proper class definition: either ::class syntax or anonymous class + continue; + } + $leftBracket = $s->next(LEFT_CURLY, $match); + if ($leftBracket === INF) { + continue; + } + $rightBracket = $s->match($leftBracket); + if ($rightBracket === INF) { + continue; + } + $s->splice($code, $rightBracket + 1); + } + }; +} + +function chain(array $callbacks) +{ + return function(Source $s) use ($callbacks) { + foreach ($callbacks as $callback) { + $callback($s); + } + }; +} diff --git a/vendor/antecedent/patchwork/src/CodeManipulation/Actions/Namespaces.php b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/Namespaces.php new file mode 100644 index 00000000..f2545336 --- /dev/null +++ b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/Namespaces.php @@ -0,0 +1,185 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CodeManipulation\Actions\Namespaces; + +use Patchwork\CodeManipulation\Source; +use Patchwork\CodeManipulation\Actions\Generic; + +/** + * @since 2.1.0 + */ +function resolveName(Source $s, $pos, $type = 'class') +{ + $name = scanQualifiedName($s, $pos); + $pieces = explode('\\', $name); + if ($pieces[0] === '') { + return $name; + } + $uses = collectUseDeclarations($s, $pos); + if (isset($uses[$type][$name])) { + return '\\' . ltrim($uses[$type][$name], ' \\'); + } + if (isset($uses['class'][$pieces[0]])) { + $name = '\\' . ltrim($uses['class'][$pieces[0]] . '\\' . join('\\', array_slice($pieces, 1)), '\\'); + } else { + $name = '\\' . ltrim(getNamespaceAt($s, $pos) . '\\' . $name, '\\'); + } + return $name; +} + +/** + * @since 2.1.0 + */ +function getNamespaceAt(Source $s, $pos) +{ + foreach (collectNamespaceBoundaries($s) as $namespace => $boundaryPairs) { + foreach ($boundaryPairs as $boundaries) { + list($begin, $end) = $boundaries; + if ($begin <= $pos && $pos <= $end) { + return $namespace; + } + } + } + return ''; +} + +function collectNamespaceBoundaries(Source $s) +{ + return $s->cache([], function() { + if (!$this->has(T_NAMESPACE)) { + return ['' => [[0, INF]]]; + } + $result = []; + foreach ($this->all(T_NAMESPACE) as $keyword) { + if ($this->next(';', $keyword) < $this->next(Generic\LEFT_CURLY, $keyword)) { + return [scanQualifiedName($this, $keyword + 1) => [[0, INF]]]; + } + $begin = $this->next(Generic\LEFT_CURLY, $keyword) + 1; + $end = $this->match($begin - 1) - 1; + $name = scanQualifiedName($this, $keyword + 1); + if (!isset($result[$name])) { + $result[$name] = []; + } + $result[$name][] = [$begin, $end]; + } + return $result; + }); +} + +function collectUseDeclarations(Source $s, $begin) +{ + foreach (collectNamespaceBoundaries($s) as $boundaryPairs) { + foreach ($boundaryPairs as $boundaries) { + list($leftBoundary, $rightBoundary) = $boundaries; + if ($leftBoundary <= $begin && $begin <= $rightBoundary) { + $begin = $leftBoundary; + break; + } + } + } + return $s->cache([$begin], function($begin) { + $result = ['class' => [], 'function' => [], 'const' => []]; + # only tokens that are siblings bracket-wise are considered, + # so trait-use instances are not an issue + foreach ($this->siblings(T_USE, $begin) as $keyword) { + # skip if closure-use + $next = $this->skip(Source::junk(), $keyword); + if ($this->is(Generic\LEFT_ROUND, $next)) { + continue; + } + parseUseDeclaration($this, $next, $result); + } + return $result; + }); +} + +function parseUseDeclaration(Source $s, $pos, array &$aliases, $prefix = '', $type = 'class') +{ + $lastPart = null; + $whole = $prefix; + while (true) { + switch ($s->tokens[$pos][Source::TYPE_OFFSET]) { + case T_FUNCTION: + $type = 'function'; + break; + case T_CONST: + $type = 'const'; + break; + case T_NS_SEPARATOR: + if (!empty($whole)) { + $whole .= '\\'; + } + break; + case T_STRING: + case Generic\NAME_FULLY_QUALIFIED: + case Generic\NAME_QUALIFIED: + case Generic\NAME_RELATIVE: + $update = $s->tokens[$pos][Source::STRING_OFFSET]; + $parts = explode('\\', $update); + $whole .= $update; + $lastPart = end($parts); + break; + case T_AS: + $pos = $s->skip(Source::junk(), $pos); + $aliases[$type][$s->tokens[$pos][Source::STRING_OFFSET]] = $whole; + $lastPart = null; + $whole = $prefix; + break; + case ',': + if ($lastPart !== null) { + $aliases[$type][$lastPart] = $whole; + } + $lastPart = null; + $whole = $prefix; + $type = 'class'; + break; + case Generic\LEFT_CURLY: + parseUseDeclaration($s, $pos + 1, $aliases, $prefix . '\\', $type); + break; + case T_WHITESPACE: + case T_COMMENT: + case T_DOC_COMMENT: + break; + default: + if ($lastPart !== null) { + $aliases[$type][$lastPart] = $whole; + } + return; + } + $pos++; + } +} + +function scanQualifiedName(Source $s, $begin) +{ + $result = ''; + while (true) { + switch ($s->tokens[$begin][Source::TYPE_OFFSET]) { + case T_NS_SEPARATOR: + if (!empty($result)) { + $result .= '\\'; + } + # fall through + case T_STRING: + case Generic\NAME_FULLY_QUALIFIED: + case Generic\NAME_QUALIFIED: + case Generic\NAME_RELATIVE: + case T_STATIC: + $result .= $s->tokens[$begin][Source::STRING_OFFSET]; + break; + case T_WHITESPACE: + case T_COMMENT: + case T_DOC_COMMENT: + break; + default: + return str_replace('\\\\', '\\', $result); + } + $begin++; + } +} diff --git a/vendor/antecedent/patchwork/src/CodeManipulation/Actions/RedefinitionOfInternals.php b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/RedefinitionOfInternals.php new file mode 100644 index 00000000..3a4f834d --- /dev/null +++ b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/RedefinitionOfInternals.php @@ -0,0 +1,142 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CodeManipulation\Actions\RedefinitionOfInternals; + +use Patchwork\Config; +use Patchwork\CallRerouting; +use Patchwork\CodeManipulation\Source; +use Patchwork\CodeManipulation\Actions\Generic; +use Patchwork\CodeManipulation\Actions\Namespaces; + +const DYNAMIC_CALL_REPLACEMENT = '\Patchwork\CallRerouting\dispatchDynamic(%s, \Patchwork\Utils\args(%s))'; + +function spliceNamedFunctionCalls() +{ + if (Config\getRedefinableInternals() === []) { + return function() {}; + } + $names = []; + foreach (Config\getRedefinableInternals() as $name) { + $names[strtolower($name)] = true; + } + return function(Source $s) use ($names) { + foreach (Namespaces\collectNamespaceBoundaries($s) as $namespace => $boundaryList) { + foreach ($boundaryList as $boundaries) { + list($begin, $end) = $boundaries; + $aliases = Namespaces\collectUseDeclarations($s, $begin)['function']; + # Receive all aliases, leave only those for redefinable internals + foreach ($aliases as $alias => $qualified) { + if (!isset($names[$qualified])) { + unset($aliases[$alias]); + } else { + $aliases[strtolower($alias)] = strtolower($qualified); + } + } + spliceNamedCallsWithin($s, $begin, $end, $names, $aliases); + } + } + }; +} + +function spliceNamedCallsWithin(Source $s, $begin, $end, array $names, array $aliases) +{ + foreach ($s->within([T_STRING, Generic\NAME_FULLY_QUALIFIED, Generic\NAME_QUALIFIED, Generic\NAME_RELATIVE], $begin, $end) as $string) { + $original = strtolower($s->read($string)); + if ($original[0] == '\\') { + $original = substr($original, 1); + } + if (isset($names[$original]) || isset($aliases[$original])) { + $previous = $s->skipBack(Source::junk(), $string); + $hadBackslash = false; + if ($s->is(T_NS_SEPARATOR, $previous) || $s->is(Generic\NAME_FULLY_QUALIFIED, $string)) { + if (!isset($names[$original])) { + # use-aliased name cannot have a leading backslash + continue; + } + if ($s->is(T_NS_SEPARATOR, $previous)) { + $s->splice('', $previous, 1); + $previous = $s->skipBack(Source::junk(), $previous); + } + $hadBackslash = true; + } + if ($s->is([T_FUNCTION, T_OBJECT_OPERATOR, T_DOUBLE_COLON, T_STRING, T_NEW, Generic\NAME_FULLY_QUALIFIED, Generic\NAME_QUALIFIED, Generic\NAME_RELATIVE], $previous)) { + continue; + } + $next = $s->skip(Source::junk(), $string); + if (!$s->is(Generic\LEFT_ROUND, $next)) { + continue; + } + if (isset($aliases[$original])) { + $original = $aliases[$original]; + } + $secondNext = $s->skip(Source::junk(), $next); + $splice = '\\' . CallRerouting\INTERNAL_REDEFINITION_NAMESPACE . '\\'; + $splice .= $original . Generic\LEFT_ROUND; + # prepend a namespace-of-origin argument to handle cases like Acme\time() vs time() + $splice .= !$hadBackslash ? '__NAMESPACE__' : '""'; + if (!$s->is(Generic\RIGHT_ROUND, $secondNext)) { + # right parenthesis doesn't follow immediately => there are arguments + $splice .= ', '; + } + $s->splice($splice, $string, $secondNext - $string); + } + } +} + +function spliceDynamicCalls() +{ + if (Config\getRedefinableInternals() === []) { + return function() {}; + } + return function(Source $s) { + spliceDynamicCallsWithin($s, 0, count($s->tokens) - 1); + }; +} + +function spliceDynamicCallsWithin(Source $s, $first, $last) +{ + $pos = $first; + $anchor = INF; + $suppress = false; + while ($pos <= $last) { + switch ($s->tokens[$pos][Source::TYPE_OFFSET]) { + case '$': + case T_VARIABLE: + $anchor = min($pos, $anchor); + break; + case Generic\LEFT_ROUND: + if ($anchor !== INF && !$suppress) { + $callable = $s->read($anchor, $pos - $anchor); + $arguments = $s->read($pos + 1, $s->match($pos) - $pos - 1); + $pos = $s->match($pos); + $replacement = sprintf(DYNAMIC_CALL_REPLACEMENT, $callable, $arguments); + $s->splice($replacement, $anchor, $pos - $anchor + 1); + } + break; + case Generic\LEFT_SQUARE: + case Generic\LEFT_CURLY: + spliceDynamicCallsWithin($s, $pos + 1, $s->match($pos) - 1); + $pos = $s->match($pos); + break; + case T_WHITESPACE: + case T_COMMENT: + case T_DOC_COMMENT: + break; + case T_OBJECT_OPERATOR: + case T_DOUBLE_COLON: + case T_NEW: + $suppress = true; + break; + default: + $suppress = false; + $anchor = INF; + } + $pos++; + } +} diff --git a/vendor/antecedent/patchwork/src/CodeManipulation/Actions/RedefinitionOfLanguageConstructs.php b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/RedefinitionOfLanguageConstructs.php new file mode 100644 index 00000000..371ec6da --- /dev/null +++ b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/RedefinitionOfLanguageConstructs.php @@ -0,0 +1,128 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CodeManipulation\Actions\RedefinitionOfLanguageConstructs; + +use Patchwork\CodeManipulation\Source; +use Patchwork\CodeManipulation\Actions\Generic; +use Patchwork\Exceptions; +use Patchwork\Config; + +const LANGUAGE_CONSTRUCT_PREFIX = 'Patchwork\Redefinitions\LanguageConstructs\_'; + +/** + * @since 2.0.5 + */ +function spliceAllConfiguredLanguageConstructs() +{ + $mapping = getMappingOfConstructs(); + $used = []; + $actions = []; + foreach (Config\getRedefinableLanguageConstructs() as $construct) { + if (isset($used[$mapping[$construct]])) { + continue; + } + $used[$mapping[$construct]] = true; + $actions[] = spliceLanguageConstruct($mapping[$construct]); + } + return Generic\chain($actions); +} + +function getMappingOfConstructs() +{ + return [ + 'echo' => T_ECHO, + 'print' => T_PRINT, + 'eval' => T_EVAL, + 'die' => T_EXIT, + 'exit' => T_EXIT, + 'isset' => T_ISSET, + 'unset' => T_UNSET, + 'empty' => T_EMPTY, + 'require' => T_REQUIRE, + 'require_once' => T_REQUIRE_ONCE, + 'include' => T_INCLUDE, + 'include_once' => T_INCLUDE_ONCE, + 'clone' => T_CLONE, + ]; +} + +function getInnerTokens() +{ + return [ + '$', + ',', + T_OBJECT_OPERATOR, + T_DOUBLE_COLON, + T_NS_SEPARATOR, + T_STRING, + T_LNUMBER, + T_DNUMBER, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_COMMENT, + T_DOC_COMMENT, + T_VARIABLE, + T_ENCAPSED_AND_WHITESPACE, + Generic\NAME_FULLY_QUALIFIED, + Generic\NAME_QUALIFIED, + Generic\NAME_RELATIVE, + ]; +} + +function getBracketTokens() +{ + return [ + Generic\LEFT_ROUND, + Generic\LEFT_SQUARE, + Generic\LEFT_CURLY, + T_CURLY_OPEN, + T_DOLLAR_OPEN_CURLY_BRACES, + Generic\ATTRIBUTE, + ]; +} + +function spliceLanguageConstruct($token) +{ + return function(Source $s) use ($token) { + foreach ($s->all($token) as $pos) { + $s->splice('\\' . LANGUAGE_CONSTRUCT_PREFIX, $pos, 0, Source::PREPEND); + if (lacksParentheses($s, $pos)) { + addParentheses($s, $pos); + } + } + }; +} + +function lacksParentheses(Source $s, $pos) +{ + if ($s->is(T_ECHO, $pos)) { + return true; + } + $next = $s->skip(Source::junk(), $pos); + return !$s->is(Generic\LEFT_ROUND, $next); +} + +function addParentheses(Source $s, $pos) +{ + $pos = $s->skip(Source::junk(), $pos); + $s->splice(Generic\LEFT_ROUND, $pos, 0, Source::PREPEND); + while ($pos < count($s->tokens)) { + if ($s->is(getInnerTokens(), $pos)) { + $pos++; + } elseif ($s->is(getBracketTokens(), $pos)) { + $pos = $s->match($pos) + 1; + } else { + break; + } + } + if ($s->is(Source::junk(), $pos)) { + $pos = $s->skipBack(Source::junk(), $pos); + } + $s->splice(Generic\RIGHT_ROUND, $pos, 0, Source::APPEND); +} diff --git a/vendor/antecedent/patchwork/src/CodeManipulation/Actions/RedefinitionOfNew.php b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/RedefinitionOfNew.php new file mode 100644 index 00000000..02344d87 --- /dev/null +++ b/vendor/antecedent/patchwork/src/CodeManipulation/Actions/RedefinitionOfNew.php @@ -0,0 +1,199 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CodeManipulation\Actions\RedefinitionOfNew; + +use Patchwork\CodeManipulation\Source; +use Patchwork\CodeManipulation\Actions\Generic; +use Patchwork\CodeManipulation\Actions\Namespaces; +use Patchwork\Config; + +const STATIC_INSTANTIATION_REPLACEMENT = '\Patchwork\CallRerouting\getInstantiator(\'%s\', %s)->instantiate(%s)'; +const DYNAMIC_INSTANTIATION_REPLACEMENT = '\Patchwork\CallRerouting\getInstantiator(%s, %s)->instantiate(%s)'; +const CALLED_CLASS = '((__CLASS__ && __FUNCTION__ !== (__NAMESPACE__ ? __NAMESPACE__ . "\\\\{closure}" : "\\\\{closure}")) ? \get_called_class() : null)'; + +const spliceAllInstantiations = 'Patchwork\CodeManipulation\Actions\RedefinitionOfNew\spliceAllInstantiations'; +const publicizeConstructors = 'Patchwork\CodeManipulation\Actions\RedefinitionOfNew\publicizeConstructors'; + +/** + * @since 2.1.0 + */ +function spliceAllInstantiations(Source $s) +{ + if (!State::$enabled || !Config\isNewKeywordRedefinable()) { + return; + } + foreach ($s->all(T_NEW) as $new) { + $begin = $s->skip(Source::junk(), $new); + if ($s->is(T_CLASS, $begin)) { + # Anonymous class + continue; + } + $end = scanInnerTokens($s, $begin, $dynamic); + $afterEnd = $s->skip(Source::junk(), $end); + list($argsOpen, $argsClose) = [null, null]; + if ($s->is(Generic\LEFT_ROUND, $afterEnd)) { + list($argsOpen, $argsClose) = [$afterEnd, $s->match($afterEnd)]; + } + spliceInstantiation($s, $new, $begin, $end, $argsOpen, $argsClose, $dynamic); + if (hasExtraParentheses($s, $new)) { + removeExtraParentheses($s, $new); + } + } +} + +function publicizeConstructors(Source $s) +{ + if (!Config\isNewKeywordRedefinable()) { + return; + } + foreach ($s->all([T_PRIVATE, T_PROTECTED]) as $first) { + $second = $s->skip(Source::junk(), $first); + $third = $s->skip(Source::junk(), $second); + if ($s->is(T_FUNCTION, $second) && $s->read($third, 1) === '__construct') { + $s->splice('public', $first, 1); + } + } +} + +function spliceInstantiation(Source $s, $new, $begin, $end, $argsOpen, $argsClose, $dynamic) +{ + $class = $s->read($begin, $end - $begin + 1); + $args = ''; + $length = $end - $new + 1; + if ($argsOpen !== null) { + $args = $s->read($argsOpen + 1, $argsClose - $argsOpen - 1); + $length = $argsClose - $new + 1; + } + $replacement = DYNAMIC_INSTANTIATION_REPLACEMENT; + if (!$dynamic) { + $class = Namespaces\resolveName($s, $begin); + $replacement = STATIC_INSTANTIATION_REPLACEMENT; + } + $s->splice(sprintf($replacement, $class, CALLED_CLASS, $args), $new, $length); +} + +function getInnerTokens() +{ + return [ + '$', + T_OBJECT_OPERATOR, + T_DOUBLE_COLON, + T_NS_SEPARATOR, + T_STRING, + T_LNUMBER, + T_DNUMBER, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_COMMENT, + T_DOC_COMMENT, + T_VARIABLE, + T_ENCAPSED_AND_WHITESPACE, + T_STATIC, + Generic\NAME_FULLY_QUALIFIED, + Generic\NAME_QUALIFIED, + Generic\NAME_RELATIVE, + ]; +} + +function getBracketTokens() +{ + return [ + Generic\LEFT_SQUARE, + Generic\LEFT_CURLY, + T_CURLY_OPEN, + T_DOLLAR_OPEN_CURLY_BRACES, + Generic\ATTRIBUTE, + ]; +} + +function getDynamicTokens() +{ + return [ + '$', + T_OBJECT_OPERATOR, + T_DOUBLE_COLON, + T_LNUMBER, + T_DNUMBER, + T_CONSTANT_ENCAPSED_STRING, + T_VARIABLE, + T_ENCAPSED_AND_WHITESPACE, + ]; +} + +function scanInnerTokens(Source $s, $begin, &$dynamic = null) +{ + $dynamic = false; + $pos = $begin; + while ($s->is(getInnerTokens(), $pos) || $s->is(getBracketTokens(), $pos)) { + if ($s->is(getBracketTokens(), $pos)) { + $dynamic = true; + $pos = $s->match($pos) + 1; + } else { + if ($s->is(getDynamicTokens(), $pos)) { + $dynamic = true; + } + $pos++; + } + } + return $pos - 1; +} + +function hasExtraParentheses(Source $s, $new) +{ + $doNotRemoveAfter = [ + T_STRING, + T_STATIC, + T_VARIABLE, + T_FOREACH, + T_FOR, + T_IF, + T_ELSEIF, + T_WHILE, + T_ARRAY, + T_PRINT, + T_ECHO, + T_CLASS, + Generic\NAME_FULLY_QUALIFIED, + Generic\NAME_QUALIFIED, + Generic\NAME_RELATIVE, + ]; + $left = $s->skipBack(Source::junk(), $new); + if (!$s->is(Generic\LEFT_ROUND, $left)) { + return false; + } + $beforeLeft = $s->skipBack(Source::junk(), $left); + return !$s->is($doNotRemoveAfter, $beforeLeft); +} + +function removeExtraParentheses(Source $s, $new) +{ + $left = $s->skipBack(Source::junk(), $new); + $s->splice('', $left, 1); + $s->splice('', $s->match($left), 1); +} + +function suspendFor(callable $function) +{ + State::$enabled = false; + $exception = null; + try { + $function(); + } catch (\Exception $e) { + $exception = $e; + } + State::$enabled = true; + if ($exception) { + throw $exception; + } +} + +class State +{ + static $enabled = true; +} diff --git a/vendor/antecedent/patchwork/src/CodeManipulation/Source.php b/vendor/antecedent/patchwork/src/CodeManipulation/Source.php new file mode 100644 index 00000000..f16bc120 --- /dev/null +++ b/vendor/antecedent/patchwork/src/CodeManipulation/Source.php @@ -0,0 +1,318 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CodeManipulation; + +use Patchwork\CodeManipulation\Actions\Generic; +use Patchwork\Utils; + +class Source +{ + const TYPE_OFFSET = 0; + const STRING_OFFSET = 1; + + const PREPEND = 'PREPEND'; + const APPEND = 'APPEND'; + const OVERWRITE = 'OVERWRITE'; + + const ANY = null; + + public $tokens; + public $tokensByType; + public $splices; + public $spliceLengths; + public $code; + public $file; + public $matchingBrackets; + public $levels; + public $levelBeginnings; + public $levelEndings; + public $tokensByLevel; + public $tokensByLevelAndType; + public $cache; + + function __construct($string) + { + $this->code = $string; + $this->initialize(); + } + + function initialize() + { + $this->tokens = Utils\tokenize($this->code); + $this->tokens[] = [T_WHITESPACE, ""]; + $this->indexTokensByType(); + $this->collectBracketMatchings(); + $this->collectLevelInfo(); + $this->splices = []; + $this->spliceLengths = []; + $this->cache = []; + } + + function indexTokensByType() + { + $this->tokensByType = []; + foreach ($this->tokens as $offset => $token) { + $this->tokensByType[$token[self::TYPE_OFFSET]][] = $offset; + } + } + + function collectBracketMatchings() + { + $this->matchingBrackets = []; + $stack = []; + foreach ($this->tokens as $offset => $token) { + $type = $token[self::TYPE_OFFSET]; + switch ($type) { + case '(': + case '[': + case '{': + case T_CURLY_OPEN: + case T_DOLLAR_OPEN_CURLY_BRACES: + case Generic\ATTRIBUTE: + $stack[] = $offset; + break; + case ')': + case ']': + case '}': + $top = array_pop($stack); + $this->matchingBrackets[$top] = $offset; + $this->matchingBrackets[$offset] = $top; + break; + } + } + } + + function collectLevelInfo() + { + $level = 0; + $this->levels = []; + $this->tokensByLevel = []; + $this->levelBeginnings = []; + $this->levelEndings = []; + $this->tokensByLevelAndType = []; + foreach ($this->tokens as $offset => $token) { + $type = $token[self::TYPE_OFFSET]; + switch ($type) { + case '(': + case '[': + case '{': + case T_CURLY_OPEN: + case T_DOLLAR_OPEN_CURLY_BRACES: + case Generic\ATTRIBUTE: + $level++; + Utils\appendUnder($this->levelBeginnings, $level, $offset); + break; + case ')': + case ']': + case '}': + Utils\appendUnder($this->levelEndings, $level, $offset); + $level--; + } + $this->levels[$offset] = $level; + Utils\appendUnder($this->tokensByLevel, $level, $offset); + Utils\appendUnder($this->tokensByLevelAndType, [$level, $type], $offset); + } + Utils\appendUnder($this->levelBeginnings, 0, 0); + Utils\appendUnder($this->levelEndings, 0, count($this->tokens) - 1); + } + + function has($types) + { + foreach ((array) $types as $type) { + if ($this->all($type) !== []) { + return true; + } + } + return false; + } + + function is($types, $offset) + { + foreach ((array) $types as $type) { + if ($this->tokens[$offset][self::TYPE_OFFSET] === $type) { + return true; + } + } + return false; + } + + function skip($types, $offset, $direction = 1) + { + $offset += $direction; + $types = (array) $types; + while ($offset < count($this->tokens) && $offset >= 0) { + if (!in_array($this->tokens[$offset][self::TYPE_OFFSET], $types)) { + return $offset; + } + $offset += $direction; + } + return ($direction > 0) ? INF : -1; + } + + function skipBack($types, $offset) + { + return $this->skip($types, $offset, -1); + } + + function within($types, $low, $high) + { + $result = []; + foreach ((array) $types as $type) { + $candidates = isset($this->tokensByType[$type]) ? $this->tokensByType[$type] : []; + $result = array_merge(Utils\allWithinRange($candidates, $low, $high), $result); + } + return $result; + } + + function read($offset, $count = 1) + { + $result = ''; + $pos = $offset; + while ($pos < $offset + $count) { + if (isset($this->tokens[$pos][self::STRING_OFFSET])) { + $result .= $this->tokens[$pos][self::STRING_OFFSET]; + } else { + $result .= $this->tokens[$pos]; + } + $pos++; + } + return $result; + } + + function siblings($types, $offset) + { + $level = $this->levels[$offset]; + $begin = Utils\lastNotGreaterThan(Utils\access($this->levelBeginnings, $level, []), $offset); + $end = Utils\firstGreaterThan(Utils\access($this->levelEndings, $level, []), $offset); + if ($types === self::ANY) { + return Utils\allWithinRange($this->tokensByLevel[$level], $begin, $end); + } else { + $result = []; + foreach ((array) $types as $type) { + $candidates = Utils\access($this->tokensByLevelAndType, [$level, $type], []); + $result = array_merge(Utils\allWithinRange($candidates, $begin, $end), $result); + } + return $result; + } + } + + function next($types, $offset) + { + if (!is_array($types)) { + $candidates = Utils\access($this->tokensByType, $types, []); + return Utils\firstGreaterThan($candidates, $offset); + } + $result = INF; + foreach ($types as $type) { + $result = min($this->next($type, $offset), $result); + } + return $result; + } + + function all($types) + { + if (!is_array($types)) { + return Utils\access($this->tokensByType, $types, []); + } + $result = []; + foreach ($types as $type) { + $result = array_merge($result, $this->all($type)); + } + sort($result); + return $result; + } + + function match($offset) + { + $offset = (string) $offset; + return isset($this->matchingBrackets[$offset]) ? $this->matchingBrackets[$offset] : INF; + } + + function splice($splice, $offset, $length = 0, $policy = self::OVERWRITE) + { + if ($policy === self::OVERWRITE) { + $this->splices[$offset] = $splice; + } elseif ($policy === self::PREPEND || $policy === self::APPEND) { + if (!isset($this->splices[$offset])) { + $this->splices[$offset] = ''; + } + if ($policy === self::PREPEND) { + $this->splices[$offset] = $splice . $this->splices[$offset]; + } elseif ($policy === self::APPEND) { + $this->splices[$offset] .= $splice; + } + } + if (!isset($this->spliceLengths[$offset])) { + $this->spliceLengths[$offset] = 0; + } + $this->spliceLengths[$offset] = max($length, $this->spliceLengths[$offset]); + $this->code = null; + } + + function createCodeFromTokens() + { + $splices = $this->splices; + $code = ""; + $count = count($this->tokens); + for ($offset = 0; $offset < $count; $offset++) { + if (isset($splices[$offset])) { + $code .= $splices[$offset]; + unset($splices[$offset]); + $offset += $this->spliceLengths[$offset] - 1; + } else { + $t = $this->tokens[$offset]; + $code .= isset($t[self::STRING_OFFSET]) ? $t[self::STRING_OFFSET] : $t; + } + } + $this->code = $code; + } + + static function junk() + { + return [T_WHITESPACE, T_COMMENT, T_DOC_COMMENT]; + } + + function __toString() + { + if ($this->code === null) { + $this->createCodeFromTokens(); + } + return (string) $this->code; + } + + function flush() + { + $this->initialize(Utils\tokenize($this)); + } + + /** + * @since 2.1.0 + */ + function cache(array $args, \Closure $function) + { + $found = true; + $trace = debug_backtrace()[1]; + $location = $trace['file'] . ':' . $trace['line']; + $result = &$this->cache; + foreach (array_merge([$location], $args) as $step) { + if (!is_scalar($step)) { + throw new \LogicException; + } + if (!isset($result[$step])) { + $result[$step] = []; + $found = false; + } + $result = &$result[$step]; + } + if (!$found) { + $result = call_user_func_array($function->bindTo($this), $args); + } + return $result; + } +} diff --git a/vendor/antecedent/patchwork/src/CodeManipulation/Stream.php b/vendor/antecedent/patchwork/src/CodeManipulation/Stream.php new file mode 100644 index 00000000..0a1c50e9 --- /dev/null +++ b/vendor/antecedent/patchwork/src/CodeManipulation/Stream.php @@ -0,0 +1,273 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\CodeManipulation; + +use Patchwork\Utils; + +class Stream +{ + const STREAM_OPEN_FOR_INCLUDE = 128; + const STAT_MTIME_NUMERIC_OFFSET = 9; + const STAT_MTIME_ASSOC_OFFSET = 'mtime'; + + protected static $protocols = ['file', 'phar']; + + public $context; + public $resource; + + public static function wrap() + { + foreach (static::$protocols as $protocol) { + stream_wrapper_unregister($protocol); + stream_wrapper_register($protocol, get_called_class()); + } + } + + public static function unwrap() + { + foreach (static::$protocols as $protocol) { + set_error_handler(function() {}); + stream_wrapper_restore($protocol); + restore_error_handler(); + } + } + + public function stream_open($path, $mode, $options, &$openedPath) + { + $this->unwrap(); + $including = (bool) ($options & self::STREAM_OPEN_FOR_INCLUDE); + + // In PHP 7 and 8, `parse_ini_file()` also sets STREAM_OPEN_FOR_INCLUDE. + if ($including) { + $frame = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]; + if (empty($frame['class']) && $frame['function'] === 'parse_ini_file') { + $including = false; + } + } + + if ($including && shouldTransform($path)) { + $this->resource = transformAndOpen($path); + $this->wrap(); + return true; + } + if (isset($this->context)) { + $this->resource = fopen($path, $mode, $options, $this->context); + } else { + $this->resource = fopen($path, $mode, $options); + } + $this->wrap(); + return $this->resource !== false; + } + + public function stream_close() + { + return fclose($this->resource); + } + + public function stream_eof() + { + return feof($this->resource); + } + + public function stream_flush() + { + return fflush($this->resource); + } + + public function stream_read($count) + { + return fread($this->resource, $count); + } + + public function stream_seek($offset, $whence = SEEK_SET) + { + return fseek($this->resource, $offset, $whence) === 0; + } + + public function stream_stat() + { + $result = fstat($this->resource); + if ($result) { + $result[self::STAT_MTIME_ASSOC_OFFSET]++; + $result[self::STAT_MTIME_NUMERIC_OFFSET]++; + } + return $result; + } + + public function stream_tell() + { + return ftell($this->resource); + } + + public function url_stat($path, $flags) + { + $func = ($flags & STREAM_URL_STAT_LINK) ? 'lstat' : 'stat'; + $this->unwrap(); + clearstatcache(); + if ($flags & STREAM_URL_STAT_QUIET) { + set_error_handler(function() {}); + try { + $result = call_user_func($func, $path); + } catch (\Exception $e) { + $result = null; + } + restore_error_handler(); + } else { + $result = call_user_func($func, $path); + } + clearstatcache(); + $this->wrap(); + if ($result) { + $result[self::STAT_MTIME_ASSOC_OFFSET]++; + $result[self::STAT_MTIME_NUMERIC_OFFSET]++; + } + return $result; + } + + public function dir_closedir() + { + closedir($this->resource); + return true; + } + + public function dir_opendir($path, $options) + { + $this->unwrap(); + if (isset($this->context)) { + $this->resource = opendir($path, $this->context); + } else { + $this->resource = opendir($path); + } + $this->wrap(); + return $this->resource !== false; + } + + public function dir_readdir() + { + return readdir($this->resource); + } + + public function dir_rewinddir() + { + rewinddir($this->resource); + return true; + } + + public function mkdir($path, $mode, $options) + { + $this->unwrap(); + if (isset($this->context)) { + $result = mkdir($path, $mode, $options, $this->context); + } else { + $result = mkdir($path, $mode, $options); + } + $this->wrap(); + return $result; + } + + public function rename($path_from, $path_to) + { + $this->unwrap(); + if (isset($this->context)) { + $result = rename($path_from, $path_to, $this->context); + } else { + $result = rename($path_from, $path_to); + } + $this->wrap(); + return $result; + } + + public function rmdir($path, $options) + { + $this->unwrap(); + if (isset($this->context)) { + $result = rmdir($path, $this->context); + } else { + $result = rmdir($path); + } + $this->wrap(); + return $result; + } + + public function stream_cast($cast_as) + { + return $this->resource; + } + + public function stream_lock($operation) + { + if ($operation === '0' || $operation === 0) { + $operation = LOCK_EX; + } + return flock($this->resource, $operation); + } + + public function stream_set_option($option, $arg1, $arg2) + { + switch ($option) { + case STREAM_OPTION_BLOCKING: + return stream_set_blocking($this->resource, $arg1); + case STREAM_OPTION_READ_TIMEOUT: + return stream_set_timeout($this->resource, $arg1, $arg2); + case STREAM_OPTION_WRITE_BUFFER: + return stream_set_write_buffer($this->resource, $arg1); + case STREAM_OPTION_READ_BUFFER: + return stream_set_read_buffer($this->resource, $arg1); + } + } + + public function stream_write($data) + { + return fwrite($this->resource, $data); + } + + public function unlink($path) + { + $this->unwrap(); + if (isset($this->context)) { + $result = unlink($path, $this->context); + } else { + $result = unlink($path); + } + $this->wrap(); + return $result; + } + + public function stream_metadata($path, $option, $value) + { + $this->unwrap(); + switch ($option) { + case STREAM_META_TOUCH: + if (empty($value)) { + $result = touch($path); + } else { + $result = touch($path, $value[0], $value[1]); + } + break; + case STREAM_META_OWNER_NAME: + case STREAM_META_OWNER: + $result = chown($path, $value); + break; + case STREAM_META_GROUP_NAME: + case STREAM_META_GROUP: + $result = chgrp($path, $value); + break; + case STREAM_META_ACCESS: + $result = chmod($path, $value); + break; + } + $this->wrap(); + return $result; + } + + public function stream_truncate($new_size) + { + return ftruncate($this->resource, $new_size); + } +} diff --git a/vendor/antecedent/patchwork/src/Config.php b/vendor/antecedent/patchwork/src/Config.php new file mode 100644 index 00000000..9da67a86 --- /dev/null +++ b/vendor/antecedent/patchwork/src/Config.php @@ -0,0 +1,233 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Config; + +use Patchwork\Utils; +use Patchwork\Exceptions; +use Patchwork\CodeManipulation\Actions\RedefinitionOfLanguageConstructs; + +const FILE_NAME = 'patchwork.json'; + +function locate() +{ + $alreadyRead = []; + $paths = array_map('dirname', get_included_files()); + $paths[] = dirname($_SERVER['PHP_SELF']); + $paths[] = getcwd(); + foreach ($paths as $path) { + while (dirname($path) !== $path) { + $file = $path . DIRECTORY_SEPARATOR . FILE_NAME; + if (is_file($file) && !isset($alreadyRead[$file])) { + read($file); + State::$timestamp = max(filemtime($file), State::$timestamp); + $alreadyRead[$file] = true; + } + $path = dirname($path); + } + } +} + +function read($file) +{ + $data = json_decode(file_get_contents($file), true); + if (json_last_error() !== JSON_ERROR_NONE) { + $message = json_last_error_msg(); + throw new Exceptions\ConfigMalformed($file, $message); + } + set($data, $file); +} + +function set(array $data, $file) +{ + $keys = array_keys($data); + $list = ['blacklist', 'whitelist', 'cache-path', 'redefinable-internals', 'new-keyword-redefinable']; + $unknown = array_diff($keys, $list); + if ($unknown != []) { + throw new Exceptions\ConfigKeyNotRecognized(reset($unknown), $list, $file); + } + $root = dirname($file); + setBlacklist(get($data, 'blacklist'), $root); + setWhitelist(get($data, 'whitelist'), $root); + setCachePath(get($data, 'cache-path'), $root); + setRedefinableInternals(get($data, 'redefinable-internals'), $root); + setNewKeywordRedefinability(get($data, 'new-keyword-redefinable'), $root); +} + +function get(array $data, $key) +{ + return isset($data[$key]) ? $data[$key] : null; +} + +function setBlacklist($data, $root) +{ + merge(State::$blacklist, resolvePaths($data, $root)); +} + +function isListed($path, array $list) +{ + $path = rtrim($path, '\\/'); + foreach ($list as $item) { + if (!is_string($item)) { + $item = chr($item); + } + if (strpos($path, $item) === 0) { + return true; + } + } + return false; +} + +function isBlacklisted($path) +{ + return isListed($path, State::$blacklist); +} + +function setWhitelist($data, $root) +{ + merge(State::$whitelist, resolvePaths($data, $root)); +} + +function isWhitelisted($path) +{ + return isListed($path, State::$whitelist); +} + +function setCachePath($data, $root) +{ + if ($data === null) { + return; + } + $path = resolvePath($data, $root); + if (State::$cachePath !== null && State::$cachePath !== $path) { + throw new Exceptions\CachePathConflict(State::$cachePath, $path); + } + State::$cachePath = $path; +} + +function getDefaultRedefinableInternals() +{ + return [ + 'preg_replace_callback', + 'spl_autoload_register', + 'iterator_apply', + 'header_register_callback', + 'call_user_func', + 'call_user_func_array', + 'forward_static_call', + 'forward_static_call_array', + 'register_shutdown_function', + 'register_tick_function', + 'unregister_tick_function', + 'ob_start', + 'usort', + 'uasort', + 'uksort', + 'array_reduce', + 'array_intersect_ukey', + 'array_uintersect', + 'array_uintersect_assoc', + 'array_intersect_uassoc', + 'array_uintersect_uassoc', + 'array_uintersect_uassoc', + 'array_diff_ukey', + 'array_udiff', + 'array_udiff_assoc', + 'array_diff_uassoc', + 'array_udiff_uassoc', + 'array_udiff_uassoc', + 'array_filter', + 'array_map', + 'libxml_set_external_entity_loader', + ]; +} + +function getRedefinableInternals() +{ + if (!empty(State::$redefinableInternals)) { + return array_merge(State::$redefinableInternals, getDefaultRedefinableInternals()); + } + return []; +} + +function setRedefinableInternals($names) +{ + merge(State::$redefinableInternals, $names); + $constructs = array_intersect(State::$redefinableInternals, getSupportedLanguageConstructs()); + State::$redefinableLanguageConstructs = array_merge(State::$redefinableLanguageConstructs, $constructs); + State::$redefinableInternals = array_diff(State::$redefinableInternals, $constructs); +} + +function setNewKeywordRedefinability($value) +{ + State::$newKeywordRedefinable = State::$newKeywordRedefinable || $value; +} + +function getRedefinableLanguageConstructs() +{ + return State::$redefinableLanguageConstructs; +} + +function getSupportedLanguageConstructs() +{ + return array_keys(RedefinitionOfLanguageConstructs\getMappingOfConstructs()); +} + +function isNewKeywordRedefinable() +{ + return State::$newKeywordRedefinable; +} + +function getCachePath() +{ + return State::$cachePath; +} + +function resolvePath($path, $root) +{ + if ($path === null) { + return null; + } + if (file_exists($path) && realpath($path) === $path) { + return $path; + } + return realpath($root . '/' . $path); +} + +function resolvePaths($paths, $root) +{ + if ($paths === null) { + return []; + } + $result = []; + foreach ((array) $paths as $path) { + $result[] = resolvePath($path, $root); + } + return $result; +} + +function merge(array &$target, $source) +{ + $target = array_merge($target, (array) $source); +} + +function getTimestamp() +{ + return State::$timestamp; +} + +class State +{ + static $blacklist = []; + static $whitelist = []; + static $cachePath; + static $redefinableInternals = []; + static $redefinableLanguageConstructs = []; + static $newKeywordRedefinable = false; + static $timestamp = 0; +} diff --git a/vendor/antecedent/patchwork/src/Console.php b/vendor/antecedent/patchwork/src/Console.php new file mode 100644 index 00000000..466130d1 --- /dev/null +++ b/vendor/antecedent/patchwork/src/Console.php @@ -0,0 +1,57 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Console; + +use Patchwork\CodeManipulation as CM; + +error_reporting(E_ALL | E_STRICT); + +$argc > 2 && $argv[1] == 'prime' + or exit("\nUsage: php patchwork.phar prime DIR1 DIR2 ... DIRn\n" . + " (to recursively prime all PHP files under given directories)\n\n"); + +try { + CM\cacheEnabled() + or exit("\nError: no cache location set.\n\n"); +} catch (Patchwork\Exceptions\CachePathUnavailable $e) { + exit("\nError: " . $e->getMessage() . "\n\n"); +} + +echo "\nCounting files...\n"; + +$files = []; + +foreach (array_slice($argv, 2) as $path) { + $path = realpath($path); + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path)) as $file) { + if (substr($file, -4) == '.php' && !CM\internalToCache($file) && !CM\availableCached($file)) { + $files[] = $file; + } + } +} + +$count = count($files); + +$count > 0 or exit("\nNothing to do.\n\n"); + +echo "\nPriming ($count files total):\n"; + +const CONSOLE_WIDTH = 80; + +$progress = 0; + +for ($i = 0; $i < $count; $i++) { + CM\prime($files[$i]->getRealPath()); + while ((int) (($i + 1) / $count * CONSOLE_WIDTH) > $progress) { + echo '.'; + $progress++; + } +} + +echo "\n\n"; diff --git a/vendor/antecedent/patchwork/src/Exceptions.php b/vendor/antecedent/patchwork/src/Exceptions.php new file mode 100644 index 00000000..c02c7df3 --- /dev/null +++ b/vendor/antecedent/patchwork/src/Exceptions.php @@ -0,0 +1,121 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Exceptions; + +use Patchwork\Utils; + +abstract class Exception extends \Exception +{ +} + +class NoResult extends Exception +{ +} + +class StackEmpty extends Exception +{ + protected $message = "There are no calls in the dispatch stack"; +} + +abstract class CallbackException extends Exception +{ + function __construct($callback) + { + parent::__construct(sprintf($this->message, Utils\callableToString($callback))); + } +} + +class NotUserDefined extends CallbackException +{ + protected $message = 'Please include {"redefinable-internals": ["%s"]} in your patchwork.json.'; +} + +class DefinedTooEarly extends CallbackException +{ + + function __construct($callback) + { + $this->message = "The file that defines %s() was included earlier than Patchwork. " . + "This is likely a result of an improper setup; see readme for details."; + parent::__construct($callback); + } +} + +class InternalMethodsNotSupported extends CallbackException +{ + protected $message = "Methods of internal classes (such as %s) are not yet redefinable in Patchwork 2.1."; +} + +class InternalsNotSupportedOnHHVM extends CallbackException +{ + protected $message = "As of version 2.1, Patchwork cannot redefine internal functions and methods (such as %s) on HHVM."; +} + +class CachePathUnavailable extends Exception +{ + function __construct($location) + { + parent::__construct(sprintf( + "The specified cache path is inexistent or read-only: %s", + $location + )); + } +} + +class ConfigException extends Exception +{ +} + +class ConfigMalformed extends ConfigException +{ + function __construct($file, $message) + { + parent::__construct(sprintf( + 'The configuration file %s is malformed: %s', + $file, + $message + )); + } +} + +class ConfigKeyNotRecognized extends ConfigException +{ + function __construct($key, $list, $file) + { + parent::__construct(sprintf( + "The key '%s' in the configuration file %s was not recognized. " . + "You might have meant one of these: %s", + $key, + $file, + join(', ', $list) + )); + } +} + +class CachePathConflict extends ConfigException +{ + function __construct($first, $second) + { + parent::__construct(sprintf( + "Detected configuration files provide conflicting cache paths: %s and %s", + $first, + $second + )); + } +} + +class NewKeywordNotRedefinable extends ConfigException +{ + protected $message = 'Please set {"new-keyword-redefinable": true} to redefine instantiations'; +} + +class NonNullToVoid extends Exception +{ + protected $message = 'A redefinition of a void-typed callable attempted to return a non-null result'; +} diff --git a/vendor/antecedent/patchwork/src/Redefinitions/LanguageConstructs.php b/vendor/antecedent/patchwork/src/Redefinitions/LanguageConstructs.php new file mode 100644 index 00000000..66172661 --- /dev/null +++ b/vendor/antecedent/patchwork/src/Redefinitions/LanguageConstructs.php @@ -0,0 +1,76 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Redefinitions\LanguageConstructs; + +function _echo($string) +{ + foreach (func_get_args() as $argument) { + echo $argument; + } +} + +function _print($string) +{ + return print($string); +} + +function _eval($code) +{ + return eval($code); +} + +function _die($message = null) +{ + die($message); +} + +function _exit($message = null) +{ + exit($message); +} + +function _isset(&$lvalue) +{ + return isset($lvalue); +} + +function _unset(&$lvalue) +{ + unset($lvalue); +} + +function _empty(&$lvalue) +{ + return empty($lvalue); +} + +function _require($path) +{ + return require($path); +} + +function _require_once($path) +{ + return require_once($path); +} + +function _include($path) +{ + return include($path); +} + +function _include_once($path) +{ + return include_once($path); +} + +function _clone($object) +{ + return clone $object; +} diff --git a/vendor/antecedent/patchwork/src/Stack.php b/vendor/antecedent/patchwork/src/Stack.php new file mode 100644 index 00000000..aab8f040 --- /dev/null +++ b/vendor/antecedent/patchwork/src/Stack.php @@ -0,0 +1,95 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Stack; + +use Patchwork\Exceptions; + +function push($offset, $calledClass, array $argsOverride = null) +{ + State::$items[] = [$offset, $calledClass, $argsOverride]; +} + +function pop() +{ + array_pop(State::$items); +} + +function pushFor($offset, $calledClass, $callback, array $argsOverride = null) +{ + push($offset, $calledClass, $argsOverride); + try { + $callback(); + } catch (\Exception $e) { + $exception = $e; + } + pop(); + if (isset($exception)) { + throw $exception; + } +} + +function top($property = null) +{ + $all = all(); + $frame = reset($all); + $argsOverride = topArgsOverride(); + if ($argsOverride !== null) { + $frame["args"] = $argsOverride; + } + if ($property) { + return isset($frame[$property]) ? $frame[$property] : null; + } + return $frame; +} + +function topOffset() +{ + if (empty(State::$items)) { + throw new Exceptions\StackEmpty; + } + list($offset, $calledClass) = end(State::$items); + return $offset; +} + +function topCalledClass() +{ + if (empty(State::$items)) { + throw new Exceptions\StackEmpty; + } + list($offset, $calledClass) = end(State::$items); + return $calledClass; +} + +function topArgsOverride() +{ + if (empty(State::$items)) { + throw new Exceptions\StackEmpty; + } + list($offset, $calledClass, $argsOverride) = end(State::$items); + return $argsOverride; +} + +function all() +{ + $backtrace = debug_backtrace(); + return array_slice($backtrace, count($backtrace) - topOffset()); +} + +function allCalledClasses() +{ + return array_map(function($item) { + list($offset, $calledClass) = $item; + return $calledClass; + }, State::$items); +} + +class State +{ + static $items = []; +} diff --git a/vendor/antecedent/patchwork/src/Utils.php b/vendor/antecedent/patchwork/src/Utils.php new file mode 100644 index 00000000..c6f9261c --- /dev/null +++ b/vendor/antecedent/patchwork/src/Utils.php @@ -0,0 +1,392 @@ + + * @copyright 2010-2018 Ignas Rudaitis + * @license http://www.opensource.org/licenses/mit-license.html + */ +namespace Patchwork\Utils; + +use Patchwork\Config; +use Patchwork\CallRerouting; +use Patchwork\CodeManipulation; + +const ALIASING_CODE = ' + namespace %s; + function %s() { + return call_user_func_array("%s", func_get_args()); + } +'; + +function clearOpcodeCaches() +{ + if (function_exists('opcache_reset')) { + opcache_reset(); + } + if (ini_get('wincache.ocenabled')) { + wincache_refresh_if_changed(); + } + if (ini_get('apc.enabled') && function_exists('apc_clear_cache')) { + apc_clear_cache(); + } +} + +function generatorsSupported() +{ + return version_compare(PHP_VERSION, "5.5", ">="); +} + +function runningOnHHVM() +{ + return defined("HHVM_VERSION"); +} + +function condense($string) +{ + return preg_replace('/\s*/', '', $string); +} + +function indexOfFirstGreaterThan(array $array, $value) +{ + $low = 0; + $high = count($array) - 1; + if (empty($array) || $array[$high] <= $value) { + return -1; + } + while ($low < $high) { + $mid = (int)(($low + $high) / 2); + if ($array[$mid] <= $value) { + $low = $mid + 1; + } else { + $high = $mid; + } + } + return $low; +} + +function indexOfLastNotGreaterThan(array $array, $value) +{ + if (empty($array)) { + return -1; + } + $result = indexOfFirstGreaterThan($array, $value); + if ($result === -1) { + $result = count($array) - 1; + } + while ($array[$result] > $value) { + $result--; + } + return $result; +} + +function firstGreaterThan(array $array, $value, $default = INF) +{ + $index = indexOfFirstGreaterThan($array, $value); + return ($index !== -1) ? $array[$index] : $default; +} + +function lastNotGreaterThan(array $array, $value, $default = INF) +{ + $index = indexOfLastNotGreaterThan($array, $value); + return ($index !== -1) ? $array[$index] : $default; +} + +function allWithinRange(array $array, $low, $high) +{ + $low--; + $high++; + $index = indexOfFirstGreaterThan($array, $low); + if ($index === -1) { + return []; + } + $result = []; + while ($index < count($array) && $array[$index] < $high) { + $result[] = $array[$index]; + $index++; + } + return $result; +} + +function interpretCallable($callback) +{ + if (is_object($callback)) { + return interpretCallable([$callback, "__invoke"]); + } + if (is_array($callback)) { + list($class, $method) = $callback; + $instance = null; + if (is_object($class)) { + $instance = $class; + $class = get_class($class); + } + $class = isset($class) ? ltrim($class, "\\") : ''; + return [$class, $method, $instance]; + } + if (substr($callback, 0, 4) === 'new ') { + return [ltrim(substr($callback, 4)), 'new', null]; + } + $callback = ltrim($callback, "\\"); + if (strpos($callback, "::")) { + list($class, $method) = explode("::", $callback); + return [$class, $method, null]; + } + return [null, $callback, null]; +} + +function callableDefined($callable, $shouldAutoload = false) +{ + list($class, $method, $instance) = interpretCallable($callable); + if ($instance !== null) { + return true; + } + if (isset($class)) { + return classOrTraitExists($class, $shouldAutoload) && + (method_exists($class, $method) || $method === 'new'); + } + return function_exists($method); +} + +function classOrTraitExists($classOrTrait, $shouldAutoload = true) +{ + return class_exists($classOrTrait, $shouldAutoload) + || trait_exists($classOrTrait, $shouldAutoload); +} + +function append(&$array, $value) +{ + $array[] = $value; + end($array); + return key($array); +} + +function appendUnder(&$array, $path, $value) +{ + foreach ((array) $path as $key) { + if (!isset($array[$key])) { + $array[$key] = []; + } + $array = &$array[$key]; + } + return append($array, $value); +} + +function access($array, $path, $default = null) +{ + foreach ((array) $path as $key) { + if (!isset($array[$key])) { + return $default; + } + $array = $array[$key]; + } + return $array; +} + +function normalizePath($path) +{ + return rtrim(strtr($path, "\\", "/"), "/"); +} + +function reflectCallable($callback) +{ + if ($callback instanceof \Closure) { + return new \ReflectionFunction($callback); + } + list($class, $method) = interpretCallable($callback); + if (isset($class)) { + return new \ReflectionMethod($class, $method); + } + return new \ReflectionFunction($method); +} + +function callableToString($callback) +{ + list($class, $method) = interpretCallable($callback); + if (isset($class)) { + return $class . "::" . $method; + } + return $method; +} + +function alias($namespace, array $mapping) +{ + foreach ($mapping as $original => $aliases) { + $original = ltrim(str_replace('\\', '\\\\', $namespace) . '\\\\' . $original, '\\'); + foreach ((array) $aliases as $alias) { + eval(sprintf(ALIASING_CODE, $namespace, $alias, $original)); + } + } +} + +function getUserDefinedCallables() +{ + return array_merge(get_defined_functions()['user'], getUserDefinedMethods()); +} + +function getRedefinableCallables() +{ + return array_merge(getUserDefinedCallables(), Config\getRedefinableInternals()); +} + +function getUserDefinedMethods() +{ + static $result = []; + static $classCount = 0; + static $traitCount = 0; + $classes = getUserDefinedClasses(); + $traits = getUserDefinedTraits(); + if (runningOnHHVM()) { + # cannot rely on the order of get_declared_classes() + static $previousClasses = []; + static $previousTraits = []; + $newClasses = array_diff($classes, $previousClasses); + $newTraits = array_diff($traits, $previousTraits); + $previousClasses = $classes; + $previousTraits = $traits; + } else { + $newClasses = array_slice($classes, $classCount); + $newTraits = array_slice($traits, $traitCount); + } + foreach (array_merge($newClasses, $newTraits) as $newClass) { + foreach (get_class_methods($newClass) as $method) { + $result[] = $newClass . '::' . $method; + } + } + $classCount = count($classes); + $traitCount = count($traits); + return $result; +} + +function getUserDefinedClasses() +{ + static $classCutoff; + $classes = get_declared_classes(); + if (!isset($classCutoff)) { + $classCutoff = count($classes); + for ($i = 0; $i < count($classes); $i++) { + if ((new \ReflectionClass($classes[$i]))->isUserDefined()) { + $classCutoff = $i; + break; + } + } + } + return array_slice($classes, $classCutoff); +} + +function getUserDefinedTraits() +{ + static $traitCutoff; + $traits = get_declared_traits(); + if (!isset($traitCutoff)) { + $traitCutoff = count($traits); + for ($i = 0; $i < count($traits); $i++) { + $methods = get_class_methods($traits[$i]); + if (empty($methods)) { + continue; + } + list($first) = $methods; + if ((new \ReflectionMethod($traits[$i], $first))->isUserDefined()) { + $traitCutoff = $i; + break; + } + } + } + return array_slice($traits, $traitCutoff); +} + +function matchWildcard($wildcard, array $subjects) +{ + $table = ['*' => '.*', '{' => '(', '}' => ')', ' ' => '', '\\' => '\\\\']; + $pattern = '/' . strtr($wildcard, $table) . '/i'; + return preg_grep($pattern, $subjects); +} + +function wildcardMatches($wildcard, $subject) +{ + return matchWildcard($wildcard, [$subject]) == [$subject]; +} + +function isOwnName($name) +{ + return stripos((string) $name, 'Patchwork\\') === 0 + && stripos((string) $name, CallRerouting\INTERNAL_REDEFINITION_NAMESPACE . '\\') !== 0; +} + +function isForeignName($name) +{ + return !isOwnName($name); +} + +function markMissedCallables() +{ + State::$missedCallables = array_map('strtolower', getUserDefinedCallables()); +} + +function getMissedCallables() +{ + return State::$missedCallables; +} + +function callableWasMissed($name) +{ + return in_array(strtolower($name), getMissedCallables()); +} + +function endsWith($haystack, $needle) +{ + if (strlen($haystack) === strlen($needle)) { + return $haystack === $needle; + } + if (strlen($haystack) < strlen($needle)) { + return false; + } + return substr($haystack, -strlen($needle)) === $needle; +} + +function wasRunAsConsoleApp() +{ + global $argv; + return isset($argv) && ( + endsWith($argv[0], 'patchwork.phar') || endsWith($argv[0], 'Patchwork.php') + ); +} + +function getParameterAndArgumentLists(\ReflectionMethod $reflection = null) +{ + $parameters = []; + $arguments = []; + if ($reflection) { + foreach ($reflection->getParameters() as $p) { + $parameter = '$' . $p->name; + if ($p->isOptional()) { + try { + $value = var_export($p->getDefaultValue(), true); + } catch (\ReflectionException $e) { + $value = var_export(CallRerouting\INSTANTIATOR_DEFAULT_ARGUMENT, true); + } + $parameter .= ' = ' . $value; + } + $parameters[] = $parameter; + $arguments[] = '$' . $p->name; + } + } + return [join(', ' , $parameters), join(', ', $arguments)]; +} + +function args() +{ + return func_get_args(); +} + +function tokenize($string) +{ + if (defined('TOKEN_PARSE')) { + return token_get_all($string, TOKEN_PARSE); + } + return token_get_all($string); +} + +class State +{ + static $missedCallables = []; +} diff --git a/vendor/automattic/vipwpcs/CHANGELOG.md b/vendor/automattic/vipwpcs/CHANGELOG.md new file mode 100644 index 00000000..b3a805c8 --- /dev/null +++ b/vendor/automattic/vipwpcs/CHANGELOG.md @@ -0,0 +1,589 @@ +# Change Log for VIP Coding Standards + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [2.3.3] - 2021-09-29 + +Props: gudmdharalds, jrfnl, BrookeDot, rebeccahum + +## Changed +- [#690](https://github.com/Automattic/VIP-Coding-Standards/pull/690): Ruleset: do not flag undefined variables in file scope or unused variables before require statement. +- [#691](https://github.com/Automattic/VIP-Coding-Standards/pull/691): Composer: use VariableAnalysis 2.11.1. +- [#694](https://github.com/Automattic/VIP-Coding-Standards/pull/694): PHPCS: enable caching for quicker scanning. +- [#697](https://github.com/Automattic/VIP-Coding-Standards/pull/697): ProperEscapingFunction: upgrade htmlAttrNotByEscHTML to default severity level. + +## Removed +- [#692](https://github.com/Automattic/VIP-Coding-Standards/pull/692): RestrictedFunctions: remove dbDelta group. + +## [2.3.2] - 2021-04-28 + +Props: jrfnl + +### Fixed +- [#681](https://github.com/Automattic/VIP-Coding-Standards/pull/681): ProperEscapingFunction: improve attribute matching accuracy for notAttrEscAttr. + +## [2.3.1] - 2021-04-23 + +Props: jrfnl + +### Fixed +- [#668](https://github.com/Automattic/VIP-Coding-Standards/pull/668): ProperEscapingFunction: fix overreach of comma usage in non-echo expressions for notAttrEscAttr. +- [#670](https://github.com/Automattic/VIP-Coding-Standards/pull/670): ProperEscapingFunction: improve "action" match precision for hrefSrcEscUrl. + +### Deprecated +- [#670](https://github.com/Automattic/VIP-Coding-Standards/pull/670): ProperEscapingFunction: private properties `$url_attrs` and `$attr_endings` are deprecated along with the public methods `is_html_attr()` and `attr_expects_url()`. + +## [2.3.0] - 2021-04-19 + +Props: jrfnl, rebeccahum, kevinfodness, GaryJones. + +** There is a minor breaking change in the ProperEscapingFunction sniff from PR [#624](https://github.com/Automattic/VIP-Coding-Standards/pull/624). The `escaping_function` property can no longer be overruled via custom rulesets. Please remove any usages of the property in custom rulesets. + +** Composer now requires the [phpcodesniffer-composer-installer](https://github.com/Dealerdirect/phpcodesniffer-composer-installer) plugin per [#583](https://github.com/Automattic/VIP-Coding-Standards/pull/583). Note: If you either include it in the "require-dev" of your `composer.json`, use another Composer PHPCS plugin, or run bash commands to register PHPCS standards, please remove it from those sources to prevent interferences or version constraint conflicts. + +### Added +- [#581](https://github.com/Automattic/VIP-Coding-Standards/pull/581): AlwaysReturnInFilter: flag abstract methods for manual inspection. +- [#583](https://github.com/Automattic/VIP-Coding-Standards/pull/583): Composer: require phpcs-composer-installer plugin. +- [#586](https://github.com/Automattic/VIP-Coding-Standards/pull/586): IncludingNonPHPFile: recognition of .phar file extensions. +- [#589](https://github.com/Automattic/VIP-Coding-Standards/pull/589): WPQueryParams: flags 'exclude' array key. +- [#595](https://github.com/Automattic/VIP-Coding-Standards/pull/595): Underscorejs: checks for additional print syntaxes and now throws an additional error for each occurrence of unescaped notation. +- [#624](https://github.com/Automattic/VIP-Coding-Standards/pull/624): ProperEscapingFunction: account for additional escaping functions and check for `esc_attr()` usage in non-HTML attributes. +- [#638](https://github.com/Automattic/VIP-Coding-Standards/pull/638): IncludingFile: new public property `$allowedKeywords` for allowing custom partial keywords in constants to reduce false positives. + +### Changed +- [#586](https://github.com/Automattic/VIP-Coding-Standards/pull/586): IncludingNonPHPFile: various performance improvements. +- [#587](https://github.com/Automattic/VIP-Coding-Standards/pull/587): LowExpiryCacheTime: new warning added for manual inspection along with various improvements. +- [#592](https://github.com/Automattic/VIP-Coding-Standards/pull/592): DynamicCalls: various improvements. +- [#595](https://github.com/Automattic/VIP-Coding-Standards/pull/595): Underscorejs: various improvements. +- [#618](https://github.com/Automattic/VIP-Coding-Standards/pull/618): RestrictedFunctions: upgrade setcookie() to error at sniff level and remove Batcache references from messaging. +- [#620](https://github.com/Automattic/VIP-Coding-Standards/pull/620): Ruleset: silence UnusedVariable from VariableAnalysis to reduce noise. +- [#630](https://github.com/Automattic/VIP-Coding-Standards/pull/630): VariableAnalysis: fix incompatibility for VariableAnalysis standard with previously deprecated native VIPCS sniff. +- [#639](https://github.com/Automattic/VIP-Coding-Standards/pull/639): RestrictedFunctions: remove site_option group. +- [#644](https://github.com/Automattic/VIP-Coding-Standards/pull/644): RestrictedFunctions: remove wp_cache_get_multi group. +- [#645](https://github.com/Automattic/VIP-Coding-Standards/pull/645): Ruleset: silence WordPress.WP.AlternativeFunctions.file_system_read_readfile. +- [#646](https://github.com/Automattic/VIP-Coding-Standards/pull/646): Ruleset: silence WordPress.WP.AlternativeFunctions.file_system_read_fclose. +- [#647](https://github.com/Automattic/VIP-Coding-Standards/pull/647): RestrictedFunctions: remove get_super_admins group. +- [#649](https://github.com/Automattic/VIP-Coding-Standards/pull/649): RestrictedFunctions: downgrade switch_to_blog() to warning and change messaging. +- [#652](https://github.com/Automattic/VIP-Coding-Standards/pull/652): RestrictedFunctions/RestrictedVariables: remove usermeta related errors. + +### Fixed +- [#444](https://github.com/Automattic/VIP-Coding-Standards/pull/444): ConstantString: only error when a plain constant is passed as constant name parameter. +- [#581](https://github.com/Automattic/VIP-Coding-Standards/pull/581): AlwaysReturnInFilter: fix runtime failure on abstract methods. +- [#584](https://github.com/Automattic/VIP-Coding-Standards/pull/584): Performance: more selective sniffing for efficiency. +- [#586](https://github.com/Automattic/VIP-Coding-Standards/pull/586): IncludingNonPHPFile: various bug fixes such as recognition of interpolated strings and case insensitivity in file extensions. +- [#587](https://github.com/Automattic/VIP-Coding-Standards/pull/587): LowExpiryCacheTime: allow arithmetic operators, simple floats, numerical strings, zeroes and parentheses in calculations, and FQN time constants. +- [#592](https://github.com/Automattic/VIP-Coding-Standards/pull/592): DynamicCalls: ignore comments, allow double quotes and remove potential memory leak. +- [#595](https://github.com/Automattic/VIP-Coding-Standards/pull/595): Underscorejs: fixed false positive for when a variable is `_.escape()`-ed. +- [#624](https://github.com/Automattic/VIP-Coding-Standards/pull/624): ProperEscapingFunction: slash escaped quotes and non-quoted strings in HTML attributes are now parsed as expected. + +### Removed +- [#624](https://github.com/Automattic/VIP-Coding-Standards/pull/624): ProperEscapingFunction: remove `$escaping_functions` public property. + +### Maintenance +- [#582](https://github.com/Automattic/VIP-Coding-Standards/pull/582): CI: re-try composer install on failure. +- [#599](https://github.com/Automattic/VIP-Coding-Standards/pull/599): CI: add build against PHP 8. +- [#606](https://github.com/Automattic/VIP-Coding-Standards/pull/606): Ruleset: remove redundant rule ref. +- [#607](https://github.com/Automattic/VIP-Coding-Standards/pull/607): Ruleset: remove redundant rule ref. +- [#608](https://github.com/Automattic/VIP-Coding-Standards/pull/608): Ruleset: remove duplicate rule ref. +- [#611](https://github.com/Automattic/VIP-Coding-Standards/pull/611): Ruleset: remove redundant notice type declaration. +- [#617](https://github.com/Automattic/VIP-Coding-Standards/pull/617): Ruleset: remove redundant notice type declaration. +- [#619](https://github.com/Automattic/VIP-Coding-Standards/pull/619): Docs: Update links to wpvip.com. +- [#631](https://github.com/Automattic/VIP-Coding-Standards/pull/631): QA: remove unused use statements. +- [#632](https://github.com/Automattic/VIP-Coding-Standards/pull/632): Docs: various minor improvements (typos, alignment and code examples). +- [#633](https://github.com/Automattic/VIP-Coding-Standards/pull/633): CI: switch to GitHub Actions. +- [#635](https://github.com/Automattic/VIP-Coding-Standards/pull/635): Ruleset: remove redundant rule ref. +- [#653](https://github.com/Automattic/VIP-Coding-Standards/pull/653): CI: use parallel linting of PHP files. +- [#655](https://github.com/Automattic/VIP-Coding-Standards/pull/655): QA: remove redundant ignore annotations. +- [#656](https://github.com/Automattic/VIP-Coding-Standards/pull/656): CI: always check that sniffs are feature complete. +- [#657](https://github.com/Automattic/VIP-Coding-Standards/pull/657): CI: add "quicktest" stage for non-PR/merge builds. +- [#658](https://github.com/Automattic/VIP-Coding-Standards/pull/658): Release template: add checkbox for dependency check. + +## [2.2.0] - 2020-09-09 + +Props: GaryJones, jrfnl, rebeccahum. + +Technically, there's a breaking change due to the use of the VariableAnalysis package over the previous sniff. If you have `WordPressVIPMinimum.Variables.Variables` references in your PHPCS config file or in inline ignore comments, then these will need to be updated to `VariableAnalysis.CodeAnalysis.VariableAnalysis`. + +### Added +- [#494](https://github.com/Automattic/VIP-Coding-Standards/pull/494): `.gitattributes` file. +- [#495](https://github.com/Automattic/VIP-Coding-Standards/pull/495): `CODEOWNERS` file. +- [#450](https://github.com/Automattic/VIP-Coding-Standards/pull/450): [VariableAnalysis](https://github.com/sirbrillig/phpcs-variable-analysis/) package. +- [#560](https://github.com/Automattic/VIP-Coding-Standards/pull/560): Allow checking test code coverage. +- [#579](https://github.com/Automattic/VIP-Coding-Standards/pull/560): Docs: Add comparisons and props to change log for old versions. + +### Changed +- [#500](https://github.com/Automattic/VIP-Coding-Standards/pull/500): Travis: change from "trusty" to "xenial". +- [#501](https://github.com/Automattic/VIP-Coding-Standards/pull/501): Move and improve `CONTRIBUTING.md`. +- [#502](https://github.com/Automattic/VIP-Coding-Standards/pull/502): CS Ruleset: minor tweaks. +- [#508](https://github.com/Automattic/VIP-Coding-Standards/pull/508): RulesetTest: don't use the system default version of PHP. +- [#558](https://github.com/Automattic/VIP-Coding-Standards/pull/558): Test bootstrap: various minor tweaks. +- [#571](https://github.com/Automattic/VIP-Coding-Standards/pull/571): CS: change yoda conditions to non-yoda. +- [#573](https://github.com/Automattic/VIP-Coding-Standards/pull/573): Composer: Change minimum stability to stable. + +### Fixed +- [#503](https://github.com/Automattic/VIP-Coding-Standards/pull/503): RulesetTest, fix compatibility with Windows. +- [#504](https://github.com/Automattic/VIP-Coding-Standards/pull/504): RulesetTest: fail the build on failing ruleset tests, fix the failing ruleset test, and fix the test script to handle 0 values. +- [#505](https://github.com/Automattic/VIP-Coding-Standards/pull/505): DeclarationCompatibility: fix incorrect signature check for `Walker::walk()`. +- [#509](https://github.com/Automattic/VIP-Coding-Standards/pull/509): RulesetTest: Revert #485 and fix one of the three causes properly. +- [#559](https://github.com/Automattic/VIP-Coding-Standards/pull/559): Variables/RestrictedVariables: fix namespace of unit test file, fix the test. +- [#561](https://github.com/Automattic/VIP-Coding-Standards/pull/561): Functions/RestrictedFunctions: fix false positive on class instantiation. +- [#563](https://github.com/Automattic/VIP-Coding-Standards/pull/563): Hooks/AlwaysReturnInFilter: add support for hook-ins using short arrays. +- [#564](https://github.com/Automattic/VIP-Coding-Standards/pull/564): Hooks/PreGetPosts: add support for hook-ins using short arrays. +- [#565](https://github.com/Automattic/VIP-Coding-Standards/pull/565): PreGetPosts: improve the `isEarlyMainQueryCheck()` method. +- [#566](https://github.com/Automattic/VIP-Coding-Standards/pull/566): RestrictedFunctions: fix false negative - functions in `config_settings` would never match. +- [#569](https://github.com/Automattic/VIP-Coding-Standards/pull/569): RestrictedVariables: don't report on "use" in `isset()`. +- [#575](https://github.com/Automattic/VIP-Coding-Standards/pull/575): ProperEscaping: Fix message for action attribute. +- [#576](https://github.com/Automattic/VIP-Coding-Standards/pull/576): Docs: Update notes for releasing. + +### Deprecated +- [#450](https://github.com/Automattic/VIP-Coding-Standards/pull/450): Deprecate Variables/VariableAnalysisSniff. Will be removed in the next major release. + +## [2.1.0] - 2020-07-07 + +Bumps requirements to PHPCS 3.5.5+ and WPCS 2.3.0+. + +Props: GaryJones, jenkoian, kevinfodness, rebeccahum. + +### Added +- `get_page_by_path()` restricted function warning, to suggest `wpcom_vip_get_page_by_path()` function. +- `stats_get_csv()` restricted function error, since this is a Jetpack-only function. +- Expanded list of HTMLExecutingFunctions to include `after`, `appendTo`, `before`, `insertAfter`, `insertBefore`, `prepend`, `prependTo`, `replaceAll` and `replaceWith`. +- Support PHP 5.4+ (down from 5.6+). +- PHP 8 nightly testing. + +### Changed +- Expand message for `wp_remote_get()` usage. +- Downgrade `append()` usage violation from Error to Warning for VIP Go, to be consistent with the other HTMLExecutingFunctions. +- Downgrade AdminBarRemoval sniff from Error to Warning for VIP Go. +- Add `get_parent_theme_file_path()` to safelist of path functions for `WordPressVIPMinimum.Files.IncludingFile` sniff. +- Allow short array syntax and fix tests within the VIPCS own coding standards. +- Update issue templates. + +### Fixed +- Use new `WordPress.DateTime.RestrictedFunctions` sniff instead of deprecated `WordPress.WP.TimezoneChange`. +- Fixed warnings and information items in Travis. + +### Removed +- `get_super_admins()` restricted function rule for VIP Go. +- `WordPressVIPMinimum.VersionControl.MergeConflict` sniff in favour of `Generic.VersionControl.GitMergeConflict`. + +## [2.0.0] - 2019-07-12 + +This release switches from having WPCS `1.*` as a dependency, to WPCS `2.*`. It is not compatible with WPCS `1.*`. + +The sniffs in WPCS `2.*` are more accurate, so you may see new violations there weren't being reported before, and a reduction in violations for false positives. + +Props: GaryJones, hanifn, paulscreiber, rebeccahum, tomjn. + +### Added +- Switch to using WPCS `2.*`. + - Remove reference to WPCS's `PHPAliases.php`. + - Remove WPCS `1.*`'s `WordPress.VIP` references from rulesets. + - Bump PHPCS minimum required version to 3.3.1. + - Update the WPCS namespace. + - Update ruleset and ruleset test to account for WPCS 2's switch to `WordPress.PHP.IniSet` sniff. + - Update ruleset test for WPCS security sniffs. + - Update `DiscouragedPHPFunctions` group exclusion in `WordPressVIPMinimum` ruleset. + +### Changed +- Downgrade use of file operation functions from Error to Warning: + - `delete` + - `file_put_contents` + - `flock` + - `fputcsv` + - `fputs` + - `fwrite` + - `ftruncate` + - `is_writable` + - `is_writeable` + - `link` + - `rename` + - `symlink` + - `tempnam` + - `touch` + - `unlink` + - `fclose` + - `fopen` + - `file_get_contents` +- Simplify Travis config. +- Switch references from `vip.wordpress.com` to `wpvip.com`. +- Documentation updates. +- Switch development to a `git-flow` workflow. + +## Fixed +- Fixed CS violations in VIPCS code. + +## [1.0.0] - 2019-04-24 + +This release contains many breaking changes. + +It requires PHP `>= 5.6`, PHPCS `3.2.3+`, and WPCS `1.*`. It does not work with WPCS `2.*`. + +Props: GaryJones, rebeccahum, whyisjake, WPprodigy. + +### Reorganisation and Renaming +The sniffs in VIPCS have been reorganised into different categories, with new sniff names and new violation codes. The changes are detailed in the table below. If you reference any of the old violations in your custom ruleset (to change severity, type, or message), or with `// phpcs:ignore` or `// phpcs:disable`, you will need to updates these references to the new violation codes. + +| Original Violation | New Violation | +|--------------------|---------------| +| `WordPressVIPMinimum.Actions.PreGetPostSniff.PreGetPosts` | `WordPressVIPMinimum.Hooks.PreGetPosts.PreGetPosts` | +| `WordPressVIPMinimum.Cache.BatcacheWhitelistedParams.strippedGetParam` | `WordPressVIPMinimum.Performance.BatcacheWhitelistedParams.StrippedGetParam` | +| `WordPressVIPMinimum.Cache.CacheValueOverride.CacheValueOverride` | `WordPressVIPMinimum.Performance.CacheValueOverride.CacheValueOverride` | +| `WordPressVIPMinimum.Cache.LowExpiryCacheTime.LowCacheTime` | `WordPressVIPMinimum.Performance.LowExpiryCacheTime.LowCacheTime` | +| `WordPressVIPMinimum.Classes.DeclarationCompatibility.DeclarationCompatibility` | No change | +| `WordPressVIPMinimum.Classes.RestrictedExtendClasses.wp_cli_wp_cli_command` | `WordPressVIPMinimum.Classes.RestrictedExtendClasses.wp_cli` | +| `WordPressVIPMinimum.Constants.ConstantsRestrictions.ConstantRestrictions` | `WordPressVIPMinimum.Constants.RestrictedConstants.DefiningRestrictedConstant`
`WordPressVIPMinimum.Constants.RestrictedConstants.UsingRestrictedConstant` | +| `WordPressVIPMinimum.Constants.ConstantString.NotCheckingConstantName` | No change | +| `WordPressVIPMinimum.Files.IncludingFile.IncludingFile` | `WordPressVIPMinimum.Files.IncludingFile.UsingVariable`
`WordPressVIPMinimum.Files.IncludingFile.UsingCustomConstant`
`WordPressVIPMinimum.Files.IncludingFile.UsingCustomFunction`
`WordPressVIPMinimum.Files.IncludingFile.NotAbsolutePath`
`WordPressVIPMinimum.Files.IncludingFile.ExternalURL`
`WordPressVIPMinimum.Files.IncludingFile.RestrictedConstant` | +| `WordPressVIPMinimum.Files.IncludingNonPHPFile.IncludingSVGCSSFile` | `WordPressVIPMinimum.Files.IncludingNonPHPFile.IncludingSVGCSSFile` | +| `WordPressVIPMinimum.Files.IncludingNonPHPFile.IncludingNonPHPFile` | `WordPressVIPMinimum.Files.IncludingNonPHPFile.IncludingNonPHPFile` | +| `WordPressVIPMinimum.Filters.AlwaysReturn.voidReturn` | `WordPressVIPMinimum.Hooks.AlwaysReturnInFilter.VoidReturn` | +| `WordPressVIPMinimum.Filters.AlwaysReturn.missingReturnStatement` | `WordPressVIPMinimum.Hooks.AlwaysReturnInFilter.MissingReturnStatement` | +| `WordPressVIPMinimum.Filters.RestrictedHook.UploadMimes` | `WordPressVIPMinimum.Hooks.RestrictedHooks.upload_mimes_upload_mimes` | +| `WordPressVIPMinimum.Filters.RestrictedHook.HighTimeout` | `WordPressVIPMinimum.Hooks.RestrictedHooks.http_request_http_request_args`
`WordPressVIPMinimum.Hooks.RestrictedHooks.http_request_http_request_timeout` | +| `WordPressVIPMinimum.Functions.CheckReturnValue.CheckReturnValue` | `WordPressVIPMinimum.Functions.CheckReturnValue.DirectFunctionCall`
`WordPressVIPMinimum.Functions.CheckReturnValue.NonCheckedVariable` | +| `WordPressVIPMinimum.Functions.CreateFunction.CreateFunction` | `WordPressVIPMinimum.Functions.RestrictedFunctions.create_function_create_function` | +| `WordPressVIPMinimum.Functions.DynamicCalls.DynamicCalls` | No change | +| `WordPressVIPMinimum.Functions.StripTags.StripTagsOneParameter` | No change | +| `WordPressVIPMinimum.Functions.StripTags.StripTagsTwoParameters` | No change | +| `WordPressVIPMinimum.JS.DangerouslySetInnerHTML.dangerouslySetInnerHTML` | `WordPressVIPMinimum.JS.DangerouslySetInnerHTML.Found` | +| `WordPressVIPMinimum.JS.HTMLExecutingFunctions.html` | No change | +| `WordPressVIPMinimum.JS.HTMLExecutingFunctions.append` | No change | +| `WordPressVIPMinimum.JS.HTMLExecutingFunctions.write` | No change | +| `WordPressVIPMinimum.JS.HTMLExecutingFunctions.writeln` | No change | +| `WordPressVIPMinimum.JS.InnerHTML.innerHTML` | `WordPressVIPMinimum.JS.InnerHTML.Found` | +| `WordPressVIPMinimum.JS.StringConcat.StringConcatNext` | `WordPressVIPMinimum.JS.StringConcat.Found` | +| `WordPressVIPMinimum.JS.StrippingTags.VulnerableTagStripping` | No change | +| `WordPressVIPMinimum.JS.Window.VarAssignment` | No change | +| `WordPressVIPMinimum.JS.Window.location` | No change | +| `WordPressVIPMinimum.JS.Window.name` | No change | +| `WordPressVIPMinimum.JS.Window.status` | No change | +| `WordPressVIPMinimum.Plugins.Zoninator.Zoninator` | `WordPressVIPMinimum.Compatibility.Zoninator.RequiresRESTAPI` | +| `WordPressVIPMinimum.TemplatingEngines.UnescapedOutputMustache.{{{` | `WordPressVIPMinimum.Security.Mustache.OutputNotation` | +| `WordPressVIPMinimum.TemplatingEngines.UnescapedOutputMustache.{{&` | `WordPressVIPMinimum.Security.Mustache.VariableNotation` | +| `WordPressVIPMinimum.TemplatingEngines.UnescapedOutputMustache.delimeterChange` | `WordPressVIPMinimum.Security.Mustache.DelimiterChange` | +| `WordPressVIPMinimum.TemplatingEngines.UnescapedOutputMustache.SafeString` | `WordPressVIPMinimum.Security.Mustache.SafeString` | +| `WordPressVIPMinimum.TemplatingEngines.UnescapedOutputTwig.autoescape false` | `WordPressVIPMinimum.Security.Twig.AutoescapeFalse` | +| `WordPressVIPMinimum.TemplatingEngines.UnescapedOutputTwig.raw` | `WordPressVIPMinimum.Security.Twig.RawFound` | +| `WordPressVIPMinimum.TemplatingEngines.UnescapedOutputUnderscorejs.<%=` | `WordPressVIPMinimum.Security.Underscorejs.OutputNotation` | +| `WordPressVIPMinimum.TemplatingEngines.UnescapedOutputUnderscorejs.interpolate` | `WordPressVIPMinimum.Security.Underscorejs.InterpolateFound` | +| `WordPressVIPMinimum.TemplatingEngines.UnescapedOutputVuejs.v-html` | `WordPressVIPMinimum.Security.Vuejs.Found` | +| `WordPressVIPMinimum.Variables.ServerVariables.BasicAuthentication` | No change | +| `WordPressVIPMinimum.Variables.ServerVariables.UserControlledHeaders` | No change | +| `WordPressVIPMinimum.Variables.VariableAnalysis.VariableRedeclaration` | No change | +| `WordPressVIPMinimum.Variables.VariableAnalysis.UndefinedVariables` | `WordPressVIPMinimum.Variables.VariableAnalysis.UndefinedVariable` | +| `WordPressVIPMinimum.Variables.VariableAnalysis.$...` | `WordPressVIPMinimum.Variables.VariableAnalysis.SelfInsideClosure`
`WordPressVIPMinimum.Variables.VariableAnalysis.SelfOutsideClass`
`WordPressVIPMinimum.Variables.VariableAnalysis.StaticInsideClosure`
`WordPressVIPMinimum.Variables.VariableAnalysis.StaticOutsideClass` | +| `WordPressVIPMinimum.Variables.VariableAnalysis.UnusedVariable` | No change | +| `WordPressVIPMinimum.VIP.ErrorControl.ErrorControl` | Replaced with `Generic.PHP.NoSilencedErrors` | +| `WordPressVIPMinimum.VIP.EscapingVoidReturnFunctions.escapingVoidReturningFunction` | `WordPressVIPMinimum.Security.EscapingVoidReturnFunctions.Found` | +| `WordPressVIPMinimum.VIP.ExitAfterRedirect.NoExitInConditional` | `WordPressVIPMinimum.Security.ExitAfterRedirect.NoExitInConditional` | +| `WordPressVIPMinimum.VIP.ExitAfterRedirect.NoExit` | `WordPressVIPMinimum.Security.ExitAfterRedirect.NoExit` | +| `WordPressVIPMinimum.VIP.FetchingRemoteData.fileGetContentsUknown` | `WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown` | +| `WordPressVIPMinimum.VIP.FetchingRemoteData.fileGetContentsRemoteFile` | `WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsRemoteFile` | +| `WordPressVIPMinimum.VIP.FlushRewriteRules.FlushRewriteRules` | Replaced with `WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules` and `WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules` | +| `WordPressVIPMinimum.VIP.MergeConflict.HEAD` | `WordPressVIPMinimum.MergeConflict.MergeConflict.Start` | +| `WordPressVIPMinimum.VIP.MergeConflict.DELIMITER` | `WordPressVIPMinimum.MergeConflict.MergeConflict.End`
`WordPressVIPMinimum.MergeConflict.MergeConflict.Separator` | +| `WordPressVIPMinimum.VIP.PHPFilterFunctions.MissingThirdParameter` | `WordPressVIPMinimum.Security.PHPFilterFunctions.MissingThirdParameter` | +| `WordPressVIPMinimum.VIP.PHPFilterFunctions.RestrictedFilter` | `WordPressVIPMinimum.Security.PHPFilterFunctions.RestrictedFilter` | +| `WordPressVIPMinimum.VIP.PHPFilterFunctions.MissingSecondParameter` | `WordPressVIPMinimum.Security.PHPFilterFunctions.MissingSecondParameter` | +| `WordPressVIPMinimum.VIP.ProperEscapingFunction.hrefSrcEscUrl` | `WordPressVIPMinimum.Security.ProperEscapingFunction.hrefSrcEscUrl` | +| `WordPressVIPMinimum.VIP.ProperEscapingFunction.htmlAttrNotByEscHTML` | `WordPressVIPMinimum.Security.ProperEscapingFunction.htmlAttrNotByEscHTML` | +| `WordPressVIPMinimum.VIP.RegexpCompare.compare_compare` | `WordPressVIPMinimum.Performance.RegexCompare.compare_compare` | +| `WordPressVIPMinimum.VIP.RegexpCompare.compare_meta_compare` | `WordPressVIPMinimum.Performance.RegexCompare.compare_meta_compare` | +| `WordPressVIPMinimum.VIP.RemoteRequestTimeout.timeout_timeout` | `WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.wp_cache_get_multi.wp_cache_get_multi` | `WordPressVIPMinimum.Functions.RestrictedFunctions.wp_cache_get_multi_wp_cache_get_multi` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.opcache_opcache_reset` | `WordPressVIPMinimum.Functions.RestrictedFunctions.opcache_opcache_reset` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.opcache_opcache_invalidate` | `WordPressVIPMinimum.Functions.RestrictedFunctions.opcache_opcache_invalidate` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.opcache_opcache_compile_file` | `WordPressVIPMinimum.Functions.RestrictedFunctions.opcache_opcache_compile_file` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.config_settings_opcache_is_script_cached` | `WordPressVIPMinimum.Functions.RestrictedFunctions.config_settings_opcache_is_script_cached` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.config_settings_opcache_get_status` | `WordPressVIPMinimum.Functions.RestrictedFunctions.config_settings_opcache_get_status` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.config_settings_opcache_get_configuration` | `WordPressVIPMinimum.Functions.RestrictedFunctions.config_settings_opcache_get_configuration` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.get_super_admins_get_super_admins` | `WordPressVIPMinimum.Functions.RestrictedFunctions.get_super_admins_get_super_admins` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.internal_wpcom_vip_irc` | `WordPressVIPMinimum.Functions.RestrictedFunctions.internal_wpcom_vip_irc` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.rewrite_rules_flush_rewrite_rules` | `WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.attachment_url_to_postid_attachment_url_to_postid` | `WordPressVIPMinimum.Functions.RestrictedFunctions.attachment_url_to_postid_attachment_url_to_postid` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.dbDelta_dbDelta` | `WordPressVIPMinimum.Functions.RestrictedFunctions.dbDelta_dbDelta` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.switch_to_blog_switch_to_blog` | `WordPressVIPMinimum.Functions.RestrictedFunctions.switch_to_blog_switch_to_blog` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.get_page_by_title_get_page_by_title` | `WordPressVIPMinimum.Functions.RestrictedFunctions.get_page_by_title_get_page_by_title` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.url_to_postid_url_to_postid` | `WordPressVIPMinimum.Functions.RestrictedFunctions.url_to_postid_url_to_postid` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.url_to_postid_url_to_post_id` | Removed | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.custom_role_add_role` | `WordPressVIPMinimum.Functions.RestrictedFunctions.custom_role_add_role` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.user_meta_get_user_meta` | `WordPressVIPMinimum.Functions.RestrictedFunctions.user_meta_get_user_meta` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.user_meta_update_user_meta` | `WordPressVIPMinimum.Functions.RestrictedFunctions.user_meta_update_user_meta` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.user_meta_delete_user_meta` | `WordPressVIPMinimum.Functions.RestrictedFunctions.user_meta_delete_user_meta` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.user_meta_add_user_meta` | `WordPressVIPMinimum.Functions.RestrictedFunctions.user_meta_add_user_meta` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.term_exists_term_exists` | `WordPressVIPMinimum.Functions.RestrictedFunctions.term_exists_term_exists` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.count_user_posts_count_user_posts` | `WordPressVIPMinimum.Functions.RestrictedFunctions.count_user_posts_count_user_posts` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.wp_old_slug_redirect_wp_old_slug_redirect` | `WordPressVIPMinimum.Functions.RestrictedFunctions.wp_old_slug_redirect_wp_old_slug_redirect` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.get_adjacent_post_get_adjacent_post` | `WordPressVIPMinimum.Functions.RestrictedFunctions.get_adjacent_post_get_adjacent_post` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.get_adjacent_post_get_previous_post` | `WordPressVIPMinimum.Functions.RestrictedFunctions.get_adjacent_post_get_previous_post` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.get_adjacent_post_get_previous_post_link` | `WordPressVIPMinimum.Functions.RestrictedFunctions.get_adjacent_post_get_previous_post_link` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.get_adjacent_post_get_next_post` | `WordPressVIPMinimum.Functions.RestrictedFunctions.get_adjacent_post_get_next_post` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.get_adjacent_post_get_next_post_link` | `WordPressVIPMinimum.Functions.RestrictedFunctions.get_adjacent_post_get_next_post_link` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.get_intermediate_image_sizes_get_intermediate_image_sizes` | `WordPressVIPMinimum.Functions.RestrictedFunctions.get_intermediate_image_sizes_get_intermediate_image_sizes` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.wp_is_mobile_wp_is_mobile` | `WordPressVIPMinimum.Functions.RestrictedFunctions.wp_is_mobile_wp_is_mobile` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.wp_mail_wp_mail` | `WordPressVIPMinimum.Functions.RestrictedFunctions.wp_mail_wp_mail` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.wp_mail_mail` | `WordPressVIPMinimum.Functions.RestrictedFunctions.wp_mail_mail` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.is_multi_author_is_multi_author` | `WordPressVIPMinimum.Functions.RestrictedFunctions.is_multi_author_is_multi_author` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.advanced_custom_fields_the_sub_field` | `WordPressVIPMinimum.Functions.RestrictedFunctions.advanced_custom_fields_the_sub_field` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.advanced_custom_fields_the_field` | `WordPressVIPMinimum.Functions.RestrictedFunctions.advanced_custom_fields_the_field` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.wp_remote_get_wp_remote_get` | `WordPressVIPMinimum.Functions.RestrictedFunctions.wp_remote_get_wp_remote_get` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.cookies_setcookie` | `WordPressVIPMinimum.Functions.RestrictedFunctions.cookies_setcookie` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.get_posts_get_posts` | `WordPressVIPMinimum.Functions.RestrictedFunctions.get_posts_get_posts` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.get_posts_wp_get_recent_posts` | `WordPressVIPMinimum.Functions.RestrictedFunctions.get_posts_wp_get_recent_posts` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.get_posts_get_children` | `WordPressVIPMinimum.Functions.RestrictedFunctions.get_posts_get_children` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.wpcom_vip_get_term_link_wpcom_vip_get_term_link` | `WordPressVIPMinimum.Functions.RestrictedFunctions.wpcom_vip_get_term_link_wpcom_vip_get_term_link` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.wpcom_vip_get_term_by_wpcom_vip_get_term_by` | `WordPressVIPMinimum.Functions.RestrictedFunctions.wpcom_vip_get_term_by_wpcom_vip_get_term_by` | +| `WordPressVIPMinimum.VIP.RestrictedFunctions.wpcom_vip_get_category_by_slug_wpcom_vip_get_category_by_slug` | `WordPressVIPMinimum.Functions.RestrictedFunctions.wpcom_vip_get_category_by_slug_wpcom_vip_get_category_by_slug` | +| `WordPressVIPMinimum.VIP.Robotstxt.RobotstxtSniff` | `WordPressVIPMinimum.Hooks.RestrictedHooks.robotstxt_do_robotstxt`
`WordPressVIPMinimum.Hooks.RestrictedHooks.robotstxt_robots_txt` | +| `WordPressVIPMinimum.VIP.StaticStrreplace.StaticStrreplace` | `WordPressVIPMinimum.Security.StaticStrreplace.StaticStrreplace` | +| `WordPressVIPMinimum.VIP.TaxonomyMetaInOptions.PossibleTermMetaInOptions` | `WordPressVIPMinimum.Performance.TaxonomyMetaInOptions.PossibleTermMetaInOptions` | +| `WordPressVIPMinimum.VIP.WPQueryParams.suppressFiltersTrue` | `WordPressVIPMinimum.Performance.WPQueryParams.SuppressFiltersTrue` | +| `WordPressVIPMinimum.VIP.WPQueryParams.post__not_in` | `WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn` | + +### Added +- New violations: + - `WordPressVIPMinimum.Functions.RestrictedFunctions.chmod_chgrp` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.chmod_chown` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.chmod_chmod` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.chmod_lchgrp` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.chmod_lchown` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.directory_mkdir` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.directory_rmdir` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_delete` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_file_put_contents` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_flock` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_fputcsv` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_fputs` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_ftruncate` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_fwrite` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_is_writable` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_is_writeable` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_link` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_rename` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_symlink` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_tempnam` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_touch` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_unlink` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_abort` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_cache_expire` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_cache_limiter` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_commit` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_create_id` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_decode` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_destroy` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_encode` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_gc` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_get_cookie_params` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_id` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_is_registered` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_module_name` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_name` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_regenerate_id` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_register_shutdown` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_register` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_reset` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_save_path` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_set_cookie_params` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_set_save_handler` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_start` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_status` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_unregister` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_unset` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.session_session_write_close` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.site_option_add_site_option` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.site_option_delete_site_option` + - `WordPressVIPMinimum.Functions.RestrictedFunctions.site_option_update_site_option` + - `WordPressVIPMinimum.Performance.NoPaging.nopaging_nopaging` + - `WordPressVIPMinimum.Performance.OrderByRand.orderby_orderby` + - `WordPressVIPMinimum.UserExperience.AdminBarRemoval.HidingDetected` + - `WordPressVIPMinimum.UserExperience.AdminBarRemoval.RemovalDetected` + - `WordPressVIPMinimum.Variables.RestrictedVariables.user_meta__wpdb__users` + - `WordPressVIPMinimum.Variables.RestrictedVariables.user_meta__wpdb__usermeta` + - `WordPressVIPMinimum.Variables.RestrictedVariables.cache_constraints___COOKIE` + - `WordPressVIPMinimum.Variables.RestrictedVariables.cache_constraints___SERVER__HTTP_USER_AGENT__` + - `WordPressVIPMinimum.Variables.RestrictedVariables.cache_constraints___SERVER__REMOTE_ADDR__` + - `WordPressVIPMinimum.Variables.RestrictedVariables.session___session` +- `WordPress-VIP-Go` ruleset test. +- docs about ruleset tests. +- XSD reference and ruleset validation. +- `phpcodesniffer-composer-installer` plugin. +- Copy `has_html_open_tag()` from WPCS. +- Copy `AbstractVariableRestrictionsSniff` from WPCS. + +### Changed +- Switch from PHPCS 2.* class names to PHPCS 3.* namespaced classes. +- Refactor all sniffs to extend `VIPCS\Sniff`, which is an extension of `WordPress\Sniff`. +- Tidied up: + - unused imports + - unused local variables + - unused parameters + - unused private field + - duplicate array keys + - redundant self-assignment + - assignment in conditions + - not returning void function calls + - undefined class fields + - strict comparisons + - missing scope keywords + - parentheses to clarify one specific conditional + - consolidate multiple `isset()` calls + - consolidate positive nested `if()`’s + - difference in case for function calls + - simplified return statements + - switched to `__DIR__` + - switched FQCN to import statements + - use static property + - use more performant `strpos()` instead of `substr()` + - split or remove `else` / `elseif` workflows for lower complexity and more comprehension + - misuse of `array_push()` + - misuse of `array_values()` + - misuse of `in_array()` + - useless `return` + - redundant `continue` + - comments that were naming parameters + - default assignments of `null` to class properties + - function parameters that match default arg values + - redundant parentheses +- Ruleset Test improvements: + - Move mostly duplicate `PHPCS_Ruleset_Test` classes into new `RulesetTest` class. + - Refactor new class: + - Accept a ruleset name in the constructor + - Change public method from `run()` to `passes()`. + - Break out logic into smaller private methods to make the logic more self-documenting. + - Refactor variable names in some methods. + - Decode JSON into objects, not arrays + - Fix incorrect reference to local `$expected` to `$this->expected`. Somehow, this was still working regardless. + - Fix bug where it doesn't catch proper number of errors/warnings on a line basis due to order of operations of incrementating after assignment. + - Add further documentation. + - Change ruleset test class usage, including adding the name to the "tests passed!" message. + - Replaced WPCS whitelisting `// XSS OK` comments in this files with `// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped` comments. + - Change naming of tests from "integration test" to "ruleset tests", to make it more intuitive exactly what these are (composer script, Travis, bin filename). +- Improve `addError()` and `addWarning()` calls +- Remove `Generic.NamingConventions.ConstructorName.OldStyle` from `WordPress-VIP-Go` ruleset +- Travis: Restrict PHPUnit versions to match PHPCS +- Travis: Use `7.4snapshot` instead of nightly, switch from Trusty to Xenial, remove `sudo: false`. +- `EscapingVoidReturnFunctions`: Fix docs and improve logic +- `AlwaysReturnSniff`: trigger errors instead of warnings, don't give violation for when callback args is passed by reference +- Change `exec()` and `shell_exec()` to be flagged as Error. +- Disallow long array syntax in VIPCS sniff code. +- Remove a `WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition` exclusion in the PHPCS config for VIPCS itself. +- Update docs. + +### Fixed +- Bumped PHPCompatibility `testVersion` to match PHP requirement. +- Silence `Generic.PHP.DisallowShortOpenTag.EchoFound` for `WordPress-VIP-Go` ruleset: ` + +
  • This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
  • +
  • You may copy and distribute verbatim copies of the Program’s source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
  • +
  • You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: +
      +
    1. You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
    2. +
    3. You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
    4. +
    5. If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
    6. +
    + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
  • +
  • You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: +
      +
    1. Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
    2. +
    3. Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
    4. +
    5. Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
    6. +
    +
  • +
  • You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
  • +
  • You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
  • +
  • Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
  • +
  • If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
  • +
  • If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
  • +
  • The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
  • +
  • If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
  • +
  • BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  • +
  • IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  • + + + +Included Files +========================== + +This project includes: + +- [WordPress-Coding-Standards](https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards), which is Copyright © 2009 John Godley and contributors. Released under the MIT license https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/blob/develop/LICENSE +- [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer), Copyright © 2012, Squiz Pty Ltd (ABN 77 084 670 600). Released under the following license: https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt diff --git a/vendor/automattic/vipwpcs/README.md b/vendor/automattic/vipwpcs/README.md new file mode 100644 index 00000000..8a7c31ae --- /dev/null +++ b/vendor/automattic/vipwpcs/README.md @@ -0,0 +1,39 @@ +# VIP Coding Standards + +This project contains [PHP_CodeSniffer (PHPCS) sniffs and rulesets](https://github.com/squizlabs/PHP_CodeSniffer) to validate code developed for [WordPress VIP](https://wpvip.com/). + +This project contains two rulesets: + + - `WordPressVIPMinimum` - for use with projects on the (older) WordPress.com VIP platform. + - `WordPress-VIP-Go` - for use with projects on the (newer) VIP Go platform. + +These rulesets contain only the rules which are considered to be ["errors"](https://docs.wpvip.com/technical-references/code-review/vip-errors/) and ["warnings"](https://docs.wpvip.com/technical-references/code-review/vip-warnings/) according to the WordPress VIP Go documentation. + +The rulesets use rules from the [WordPress Coding Standards](https://github.com/WordPress/WordPress-Coding-Standards) (WPCS) project, as well as the [VariableAnalysis](https://github.com/sirbrillig/phpcs-variable-analysis) standard. + +Go to https://docs.wpvip.com/technical-references/code-review/phpcs-report/ to learn about why violations are flagged as errors vs warnings and what the levels mean. + +## Minimal requirements + +* PHP 5.4+ +* [PHPCS 3.5.5+](https://github.com/squizlabs/PHP_CodeSniffer/releases) +* [WPCS 2.3.0+](https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/releases) +* [VariableAnalysis 2.8.3+](https://github.com/sirbrillig/phpcs-variable-analysis/releases) + +## Installation + +`composer require automattic/vipwpcs`, or `composer g require automattic/vipwpcs` if installing globally. + +This will install the latest compatible versions of PHPCS, WPCS and VariableAnalysis and register the external standards with PHP_CodeSniffer. + +Please refer to the [installation instructions for installing PHP_CodeSniffer for WordPress.com VIP](https://docs.wpvip.com/how-tos/code-review/php_codesniffer/) for more details. + +As of VIPCS version 2.3.0, there is no need to `require` the [PHP_CodeSniffer Standards Composer Installer Plugin](https://github.com/Dealerdirect/phpcodesniffer-composer-installer) anymore as it is now a requirement of VIPCS itself. + +## Contribution + +Please see [CONTRIBUTION.md](.github/CONTRIBUTING.md). + +## License + +Licensed under [GPL-2.0-or-later](LICENSE.md). diff --git a/vendor/automattic/vipwpcs/WordPress-VIP-Go/ruleset-test.inc b/vendor/automattic/vipwpcs/WordPress-VIP-Go/ruleset-test.inc new file mode 100644 index 00000000..61e56955 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPress-VIP-Go/ruleset-test.inc @@ -0,0 +1,574 @@ + 999, // Warning + Message. + 'posts_per_page' => 1, // OK. + 'posts_per_page' => '1', // OK. +); +_query_posts( 'posts_per_page=999' ); // Warning + Message. +$query_args['posts_per_page'] = 999; // Warning + Message. +$query_args['posts_per_page'] = 1; // OK. + +// WordPressVIPMinimum.Hooks.RestrictedHooks.upload_mimes +add_filter( 'upload_mimes', 'foo' ); // Warning. + +// WordPressVIPMinimum.Security.PHPFilterFunctions +filter_var( $url ); // Warning. +filter_var_array( $array ); // Warning. +filter_input_array( $array ); // Warning. +filter_var( $url, FILTER_SANITIZE_URL ); // Ok. +filter_input( INPUT_GET, 'foo' ); // Warning. +filter_input( INPUT_GET, 'foo', FILTER_SANITIZE_STRING ); // Ok. +filter_var( $url, FILTER_DEFAULT ); // Warning. +filter_var_array( $array, FILTER_UNSAFE_RAW ); // Warning. +filter_var_array( $array, FILTER_SANITIZE_STRING ); // Ok. +filter_input_array( $array,FILTER_SANITIZE_STRING ); // Ok. +filter_input( INPUT_GET, 'foo', FILTER_DEFAULT ); // Warning. + + + + +// WordPressVIPMinimum.Functions.RestrictedFunctions.wp_mail_wp_mail +wp_mail(); // Warning. +mail(); // Warning. + +// WordPressVIPMinimum.Functions.RestrictedFunctions.attachment_url_to_postid_attachment_url_to_postid +wpcom_vip_attachment_url_to_postid( $url ); // Ok. +attachment_url_to_postid( $url ); // Warning + Message. + +// WordPressVIPMinimum.Functions.RestrictedFunctions.get_adjacent_post_get_adjacent_post +wpcom_vip_get_adjacent_post(); // Ok. +get_adjacent_post(); // Warning. +get_previous_post(); // Warning. +get_next_post(); // Warning. +get_previous_post_link(); // Warning. +get_next_post_link(); // Warning. + +// WordPressVIPMinimum.Functions.RestrictedFunctions.get_page_by_title_get_page_by_title +wpcom_vip_get_page_by_title(); // Ok. +get_page_by_title( $page_title ); // Warning + Message. + +// WordPressVIPMinimum.Functions.RestrictedFunctions.get_posts_get_children +get_child(); // Ok. +get_children(); // Warning + Message. + +// WordPressVIPMinimum.Functions.RestrictedFunctions.get_posts_get_posts +get_posts(); // Warning. +get_post( 123 ); // Ok. + +// WordPressVIPMinimum.Functions.RestrictedFunctions.get_posts_wp_get_recent_posts +wp_get_recent_posts(); // Warning. + +// WordPressVIPMinimum.Functions.RestrictedFunctions.url_to_postid_url_to_postid +wpcom_vip_url_to_postid( $url ); // Ok. +url_to_postid( $url ); // Warning + Message. + +// WordPressVIPMinimum.Functions.RestrictedFunctions.wp_old_slug_redirect_wp_old_slug_redirect +wpcom_vip_old_slug_redirect(); // Ok. +wp_old_slug_redirect(); // Warning. + +// WordPress.CodeAnalysis.AssignmentInCondition.Found +if ($a = 123) { // Warning. +} + +// WordPress.PHP.DiscouragedPHPFunctions.urlencode_urlencode +urlencode(); // Warning. +rawurlencode(); // Ok. + +// WordPress.PHP.DontExtract +extract( array( 'a' => 1 ) ); // Error. +$obj->extract(); // Ok. + +// WordPress.PHP.StrictComparisons.LooseComparison +true == $true; // Warning. +false === $true; // Ok. + +// WordPress.PHP.StrictInArray.MissingTrueStrict +in_array( 1, array( '1', 1, true ), true ); // Ok. +in_array( 1, array( '1', 1, true ) ); // Warning. +in_array( 1, array( '1', 1, true ), false ); // Warning. +array_search( 1, $array, false ); // Warning. +array_keys( array( '1', 1, true ), 'my_key' ); // Warning. + +// WordPress.Security.EscapeOutput.UnsafePrintingFunction +_e( $some_nasty_var ); // Error. +_ex( $some_nasty_var, 'context' ); // Error. +echo esc_html_x( 'Something', 'context' ); // Ok. +echo esc_html_x( $some_nasty_var, 'context' ); // Ok. + +// WordPress.WP.GlobalVariablesOverride.OverrideProhibited +global $wpdb; +$wpdb = 'test'; // Error. +$GLOBALS['domain']['subkey'] = 'something else'; // Error. + +// WordPress.WP.EnqueuedResources.NonEnqueuedScript +echo wp_kses( ' + + + +'; // Warning + Message. + +// WordPressVIPMinimum.Performance.LowExpiryCacheTime.LowCacheTime +wp_cache_set( 'test', $data, $group, 100 ); // Warning. +wp_cache_add( 'test', $data, $group, 2*MINUTE_IN_SECONDS ); // Warning. +wp_cache_replace( $testing, $data, '', 1.5 * MINUTE_IN_SECONDS ); // Warning. + +// WordPressVIPMinimum.Files.IncludingFile +include_once ( MY_CONSTANT . "my_file.php" ); // Warning. +require_once( custom_function( 'test_file.php' ) ); // Warning. +require_once "my_file.php"; // Warning. +require '../../my_file.php'; // Warning. +include("http://www.google.com/bad_file.php"); // Warning. + +// VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable +function foo_bar_bar() { + $b . 'test'; // Warning. +} + +// VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable +function foo_bar_foo() { + $a = 'Hello'; // OK. Unused variables warning silenced. +} + +// WordPressVIPMinimum.UserExperience.AdminBarRemoval +add_filter( 'show_admin_bar', '__return_false' ); // Warning. +add_filter( 'show_admin_bar', '__return_true' ); // Ok. +show_admin_bar( false ); // Warning. +show_admin_bar( true ); // Ok. +add_filter( 'show_admin_bar', 'my_own_return_false' ); // Warning. +echo ''; +?> '; // Error. +echo ''; // Error. +echo ''; // OK. +?>Hello +Hey + + array( 1, 2, 3 ), // Warning. +] ); + +/* Rules that are being silenced and should NOT be flagged. */ + +// WordPress.DB.SlowDBQuery.slow_db_query_meta_key +$query = new WP_Query( ['meta_key' => 'foo' ] ); // Ok. +$args = 'foo=bar&meta_key=foo'; // Ok. + +// WordPressVIPMinimum.Performance.BatcacheWhitelistedParams +if ( isset( $_GET['migSource'] ) && wp_verify_nonce( sanitize_text_field( $_GET['migSource'] ) ) ) { + $test = sanitize_text_field( $_GET['migSource'] ); // Ok. +} + + + + + + + + + + + + + + + + +// WordPressVIPMinimum.Functions.RestrictedFunctions.site_option_delete_site_option +delete_site_option( $foo ); // Ok. + +// WordPressVIPMinimum.Functions.RestrictedFunctions.site_option_update_site_option +update_site_option( $bar, $foo, true ); // Ok. + +// WordPressVIPMinimum.Functions.RestrictedFunctions.site_option_add_site_option +add_site_option( 'foo', $bar ); // Ok. + +// Generic.PHP.DisallowShortOpenTag.EchoFound +?> My term link'; // Error. + +// WordPressVIPMinimum.Functions.DynamicCalls +$my_notokay_func = 'extract'; +$my_notokay_func(); // Error. + +// WordPressVIPMinimum.Functions.RestrictedFunctions + +opcache_reset(); // Error. +opcache_invalidate( 'test_script.php' ); // Error. +opcache_compile_file( $var ); // Error. +opcache_is_script_cached( 'test_script.php' ); // Error. +opcache_get_status(); // Error. +opcache_get_configuration(); // Error. +get_super_admins(); // OK. +wpcom_vip_irc(); // Error. +flush_rewrite_rules(); // Error. +$wp_rewrite->flush_rules(); // Error. +\add_role(); // Error. +term_exists(); // Error. +count_user_posts(); // Error. +get_intermediate_image_sizes(); // Error. +wp_is_mobile(); // Error. +session_abort(); // Error. +session_cache_expire(); // Error. +session_cache_limiter(); // Error. +session_commit(); // Error. +session_create_id(); // Error. +session_decode(); // Error. +session_destroy(); // Error. +session_encode(); // Error. +session_gc(); // Error. +session_get_cookie_params(); // Error. +session_id(); // Error. +session_is_registered(); // Error. +session_module_name(); // Error. +session_name(); // Error. +session_regenerate_id(); // Error. +session_register_shutdown(); // Error. +session_register(); // Error. +session_reset(); // Error. +session_save_path(); // Error. +session_set_cookie_params(); // Error. +session_set_save_handler(); // Error. +session_start(); // Error. +session_status(); // Error. +session_unregister(); // Error. +session_unset(); // Error. +session_write_close(); // Error. +delete(); // Warning. +file_put_contents( $file, $text, FILE_APPEND ); // Warning. +while ( $count > $loop ) { + if ( flock( $fp, LOCK_EX ) ) { // Warning. + fwrite( $fp, $text ); // Warning. + } +} +fputcsv(); // Warning. +fputs(); // Warning. +ftruncate(); // Warning. +is_writable(); // Warning. +is_writeable(); // Warning. +link(); // Warning. +rename(); // Warning. +symlink(); // Warning. +tempnam(); // Warning. +touch(); // Warning. +unlink(); // Warning. +mkdir(); // Error. +rmdir(); // Error. +chgrp(); // Error. +chown(); // Error. +chmod(); // Error. +lchgrp(); // Error. +lchown(); // Error. +the_sub_field( 'field' ); // Warning. +the_field( 'field' ); // Warning. +wp_remote_get( $url ); // Warning. +get_posts(); // Warning. +function test_function( $a, $b ) { // OK. Unused variables warning silenced. + return create_function( '$a, $b', 'return ( $b / $a ); '); // Warning. +} +wpcom_vip_get_term_link(); // Warning. +wpcom_vip_get_term_by(); // Warning. +wpcom_vip_get_category_by_slug(); // Warning. + +// WordPressVIPMinimum.Functions.StripTagsSniff +strip_tags( 'Test', $text ); // Warning. + +// WordPressVIPMinimum.Hooks.AlwaysReturnInFilter +function bad_example_function_thing() { // Error. + if ( 1 === 0 ) { + if ( 1 === 1 ) { + return 'ahoj'; + } else { + return 'hello'; + } + } +} +add_filter( 'bad_example_function_filter', 'bad_example_function_thing' ); +add_filter( 'another_bad_example_closure', function() { // Error. + return; +} ); + +// WordPressVIPMinimum.Hooks.PreGetPosts +add_action( 'pre_get_posts', function( $wp_query ) { + if ( ! $wp_query->is_search() ) { + $wp_query->set( 'cat', '-5' ); // Warning. + } +} ); + +// WordPressVIPMinimum.Hooks.RestrictedHooks +add_action( 'http_request_timeout', 'bad_example_function' ); // Warning. +add_filter('http_request_args', 'bad_example_function' ); // Warning. +add_action( 'do_robotstxt', 'my_do_robotstxt'); // Warning. +add_filter( 'robots_txt', function() { // Warning. + return 'test'; +} ); + +// WordPressVIPMinimum.Performance.CacheValueOverride +$bad_wp_users = wp_cache_get( md5( self::CACHE_KEY . '_wp_users'), self::CACHE_GROUP ); +$bad_wp_users = false; // Error. + +// WordPressVIPMinimum.Performance.NoPaging +$args = array( + 'nopaging' => true, // Error. +); +_query_posts( 'nopaging=true' ); // Error. + +// WordPressVIPMinimum.Performance.OrderByRand +$args = array( + "orderby" => "RAND", // Error. +); +$query_args['orderby'] = 'rand'; // Error. + +// WordPressVIPMinimum.Performance.RegexpCompare +$query_args = array( + 'posts_per_page' => 1, + 'post_status' => 'draft', + 'meta_compare' => 'REGEXP', // Error. +); +$query_args = [ + 'post_status' => 'publish', + 'meta_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query + [ + 'compare' => 'REGEXP', // Error. + ] + ] +]; + +// WordPressVIPMinimum.Performance.RemoteRequestTimeout +wp_remote_post( $obj->endpoint, array( + 'method' => 'POST', + 'timeout' => 45, // Error. + 'httpversion' => '1.1', + 'blocking' => false, + 'body' => wp_json_encode( $obj->logs, JSON_UNESCAPED_SLASHES ), + ) +); + +// WordPressVIPMinimum.Performance.TaxonomyMetaInOptions +get_option( "taxonomy_rating_$obj->term_id" ); // Warning. +update_option( 'taxonomy_rating_' . $category_id ); // Warning. + +// WordPressVIPMinimum.Performance.WPQueryParams +$query_args = array( + 'suppress_filters' => true, // Error. +); + +// WordPressVIPMinimum.Security.EscapingVoidReturnFunctions.Found +esc_js( _deprecated_argument() ); // Error. +esc_js( _deprecated_constructor() ); // Error. +esc_js( _deprecated_file( 'filename' ) ); // Error. +esc_js( _deprecated_function() ); // Error. +esc_js( _deprecated_hook() ); // Error. +esc_js( _doing_it_wrong() ); // Error. +esc_html( printf( 'foo', [] ) ); // Error. +esc_attr( user_error( 'foo', '' ) ); // Error. +esc_attr( vprintf( 'foo', [] ) ); // Error. +esc_attr( wp_die( 'foo' ) ); // Error. +esc_attr( wp_dropdown_pages() ); // Error. + +// WordPressVIPMinimum.Security.ExitAfterRedirect +function redirect_test() { + wp_safe_redirect( 'https.//vip.wordpress.com' ); // Error. +} +wp_redirect( 'https://vip.wordpress.com' ); // Error. + +// WordPressVIPMinimum.Security.Mustache +echo '{{{data}}}
    '; // Warning. +?> + + + _.templateSettings = { + interpolate: /\{\{(.+?)\}\}/g" . // Warning. +"}; + "; + +// WordPressVIPMinimum.Security.Vuejs +?>
    +

    +
    +<<<<<<< HEAD // Error. + +>>>>>>> // Error. diff --git a/vendor/automattic/vipwpcs/WordPress-VIP-Go/ruleset-test.php b/vendor/automattic/vipwpcs/WordPress-VIP-Go/ruleset-test.php new file mode 100644 index 00000000..af455144 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPress-VIP-Go/ruleset-test.php @@ -0,0 +1,345 @@ + [ + 50 => 1, + 53 => 1, + 56 => 1, + 72 => 1, + 83 => 1, + 165 => 1, + 180 => 1, + 181 => 1, + 187 => 1, + 188 => 1, + 252 => 1, + 255 => 1, + 256 => 1, + 258 => 1, + 259 => 1, + 318 => 1, + 329 => 1, + 334 => 1, + 337 => 1, + 341 => 1, + 342 => 1, + 346 => 1, + 350 => 1, + 351 => 1, + 352 => 1, + 353 => 1, + 354 => 1, + 355 => 1, + 357 => 1, + 358 => 1, + 359 => 1, + 360 => 1, + 361 => 1, + 362 => 1, + 363 => 1, + 364 => 1, + 365 => 1, + 366 => 1, + 367 => 1, + 368 => 1, + 369 => 1, + 370 => 1, + 371 => 1, + 372 => 1, + 373 => 1, + 374 => 1, + 375 => 1, + 376 => 1, + 377 => 1, + 378 => 1, + 379 => 1, + 380 => 1, + 381 => 1, + 382 => 1, + 383 => 1, + 384 => 1, + 385 => 1, + 386 => 1, + 387 => 1, + 388 => 1, + 389 => 1, + 390 => 1, + 409 => 1, + 410 => 1, + 411 => 1, + 412 => 1, + 413 => 1, + 414 => 1, + 415 => 1, + 431 => 1, + 441 => 1, + 462 => 1, + 466 => 1, + 468 => 1, + 472 => 1, + 474 => 1, + 480 => 1, + 486 => 1, + 494 => 1, + 507 => 1, + 511 => 1, + 512 => 1, + 513 => 1, + 514 => 1, + 515 => 1, + 516 => 1, + 517 => 1, + 518 => 1, + 519 => 1, + 520 => 1, + 521 => 1, + 525 => 1, + 527 => 1, + 545 => 1, + 560 => 1, + 564 => 1, + 565 => 1, + 566 => 1, + 567 => 1, + 572 => 1, + 574 => 1, + ], + 'warnings' => [ + 4 => 1, + 7 => 1, + 10 => 1, + 14 => 1, + 17 => 1, + 20 => 1, + 23 => 1, + 26 => 1, + 29 => 1, + 32 => 1, + 35 => 1, + 38 => 1, + 41 => 1, + 44 => 1, + 47 => 1, + 63 => 1, + 66 => 1, + 85 => 1, + 90 => 1, + 94 => 1, + 95 => 1, + 99 => 1, + 102 => 1, + 103 => 1, + 104 => 1, + 106 => 1, + 108 => 1, + 109 => 1, + 112 => 1, + 118 => 1, + 119 => 1, + 123 => 1, + 127 => 1, + 128 => 1, + 129 => 1, + 130 => 1, + 131 => 1, + 135 => 1, + 139 => 1, + 142 => 1, + 146 => 1, + 150 => 1, + 154 => 1, + 157 => 1, + 161 => 1, + 169 => 1, + 174 => 1, + 175 => 1, + 176 => 1, + 177 => 1, + 191 => 1, + 192 => 1, + 195 => 1, + 196 => 1, + 199 => 1, + 200 => 1, + 201 => 1, + 204 => 1, + 205 => 1, + 206 => 1, + 207 => 1, + 208 => 1, + 212 => 1, + 221 => 1, + 223 => 1, + 225 => 1, + 228 => 1, + 229 => 1, + 230 => 1, + 235 => 1, + 236 => 1, + 237 => 1, + 245 => 1, + 246 => 1, + 247 => 1, + 265 => 1, + 269 => 1, + 273 => 1, + 322 => 1, + 326 => 1, + 332 => 1, + 391 => 1, + 392 => 1, + 394 => 1, + 395 => 1, + 398 => 1, + 399 => 1, + 400 => 1, + 401 => 1, + 402 => 1, + 403 => 1, + 404 => 1, + 405 => 1, + 406 => 1, + 407 => 1, + 408 => 1, + 416 => 1, + 417 => 1, + 418 => 1, + 419 => 1, + 421 => 1, + 423 => 1, + 424 => 1, + 425 => 1, + 428 => 1, + 448 => 1, + 453 => 1, + 454 => 1, + 455 => 1, + 456 => 1, + 502 => 1, + 503 => 1, + 530 => 1, + 533 => 1, + 540 => 1, + 550 => 1, + 556 => 1, + ], + 'messages' => [ + 4 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as delete(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 7 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as file_put_contents(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 10 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as flock(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 14 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as fputcsv(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 17 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as fputs(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 20 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as fwrite(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 23 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as ftruncate(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 26 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as is_writable(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 29 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as is_writeable(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 32 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as link(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 35 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as rename(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 38 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as symlink(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 41 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as tempnam(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 44 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as touch(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 47 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as unlink(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 50 => [ + 'Due to server-side caching, server-side based client related logic might not work. We recommend implementing client side logic in JavaScript instead.', + ], + 53 => [ + 'Due to server-side caching, server-side based client related logic might not work. We recommend implementing client side logic in JavaScript instead.', + ], + 56 => [ + 'Due to server-side caching, server-side based client related logic might not work. We recommend implementing client side logic in JavaScript instead.', + ], + 63 => [ + 'File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as fopen(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/', + ], + 66 => [ + 'file_get_contents() is uncached. If the function is being used to fetch a remote file (e.g. a URL starting with https://), please use wpcom_vip_file_get_contents() to ensure the results are cached. For more details, please see: https://docs.wpvip.com/technical-references/code-quality-and-best-practices/retrieving-remote-data/', + ], + 90 => [ + 'Having more than 100 posts returned per page may lead to severe performance problems.', + ], + 94 => [ + 'Having more than 100 posts returned per page may lead to severe performance problems.', + ], + 95 => [ + 'Having more than 100 posts returned per page may lead to severe performance problems.', + ], + 123 => [ + 'attachment_url_to_postid() is uncached, please use wpcom_vip_attachment_url_to_postid() instead.', + ], + 135 => [ + 'get_page_by_title() is uncached, please use wpcom_vip_get_page_by_title() instead.', + ], + 139 => [ + 'get_children() is uncached and performs a no limit query. Please use get_posts or WP_Query instead. Please see: https://docs.wpvip.com/technical-references/caching/uncached-functions/', + ], + 150 => [ + 'url_to_postid() is uncached, please use wpcom_vip_url_to_postid() instead.', + ], + 191 => [ + 'Scripts should be registered/enqueued via `wp_enqueue_script`. This can improve the site\'s performance due to script concatenation.', + ], + 192 => [ + 'Scripts should be registered/enqueued via `wp_enqueue_script`. This can improve the site\'s performance due to script concatenation.', + ], + 195 => [ + 'Stylesheets should be registered/enqueued via `wp_enqueue_style`. This can improve the site\'s performance due to styles concatenation.', + ], + 196 => [ + 'Stylesheets should be registered/enqueued via `wp_enqueue_style`. This can improve the site\'s performance due to styles concatenation.', + ], + ], +]; + +require __DIR__ . '/../tests/RulesetTest.php'; + +// Run the tests! +$test = new RulesetTest( 'WordPress-VIP-Go', $expected ); +if ( $test->passes() ) { + printf( 'All WordPress-VIP-Go tests passed!' . PHP_EOL ); + exit( 0 ); +} + +exit( 1 ); diff --git a/vendor/automattic/vipwpcs/WordPress-VIP-Go/ruleset.xml b/vendor/automattic/vipwpcs/WordPress-VIP-Go/ruleset.xml new file mode 100644 index 00000000..58386a58 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPress-VIP-Go/ruleset.xml @@ -0,0 +1,273 @@ + + + WordPress VIP Go Coding Standards + + + + + + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + warning + 6 + Removal of admin bar is highly discouraged for user roles of "administrator" and "vip_support" -- if these roles are already excluded, this warning can be ignored. + + + warning + 6 + Hiding of admin bar is highly discouraged for user roles of "administrator" and "vip_support" -- if these roles are already excluded, this warning can be ignored. + + + 6 + + + error + 6 + + + error + 6 + + + + + + + File system operations only work on the `/tmp/` and `wp-content/uploads/` directories. To avoid unexpected results, please use helper functions like `get_temp_dir()` or `wp_get_upload_dir()` to get the proper directory path when using functions such as %s(). For more details, please see: https://docs.wpvip.com/technical-references/vip-go-files-system/local-file-operations/ + + + %s() is uncached. If the function is being used to fetch a remote file (e.g. a URL starting with https://), please use wpcom_vip_file_get_contents() to ensure the results are cached. For more details, please see: https://docs.wpvip.com/technical-references/code-quality-and-best-practices/retrieving-remote-data/ + + + + + + + warning + 10 + + + Having more than 100 posts returned per page may lead to severe performance problems. + + + 10 + + + 10 + + + 7 + + + + + + warning + %s() is uncached, please use wpcom_vip_attachment_url_to_postid() instead. + + + warning + + + warning + + + warning + + + warning + + + warning + + + warning + %s() is uncached, please use wpcom_vip_get_page_by_title() instead. + + + warning + 3 + %s() is uncached and performs a no limit query. Please use get_posts or WP_Query instead. Please see: https://docs.wpvip.com/technical-references/caching/uncached-functions/ + + + 3 + + + 3 + + + warning + %s() is uncached, please use wpcom_vip_url_to_postid() instead. + + + warning + + + + + 1 + + + 1 + + + 3 + + + 3 + + + 3 + + + 3 + + + + 1 + + + warning + 3 + Scripts should be registered/enqueued via `wp_enqueue_script`. This can improve the site's performance due to script concatenation. + + + warning + 3 + Stylesheets should be registered/enqueued via `wp_enqueue_style`. This can improve the site's performance due to styles concatenation. + + + 3 + + + warning + 3 + + + 3 + + + 3 + + + 1 + + + 1 + + + 3 + + + 3 + + + + + 0 + + + + + + + + + + + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/AbstractVariableRestrictionsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/AbstractVariableRestrictionsSniff.php new file mode 100644 index 00000000..e46373a3 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/AbstractVariableRestrictionsSniff.php @@ -0,0 +1,231 @@ +setup_groups() === false ) { + return []; + } + + return [ + \T_VARIABLE, + \T_OBJECT_OPERATOR, + \T_DOUBLE_COLON, + \T_OPEN_SQUARE_BRACKET, + \T_DOUBLE_QUOTED_STRING, + \T_HEREDOC, + ]; + } + + /** + * Groups of variables to restrict. + * + * This method should be overridden in extending classes. + * + * Example: groups => array( + * 'wpdb' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Dont use this one please!', + * 'variables' => array( '$val', '$var' ), + * 'object_vars' => array( '$foo->bar', .. ), + * 'array_members' => array( '$foo['bar']', .. ), + * ) + * ) + * + * @return array + */ + abstract public function getGroups(); + + /** + * Cache the groups. + * + * @return bool True if the groups were setup. False if not. + */ + protected function setup_groups() { + $this->groups_cache = $this->getGroups(); + + if ( empty( $this->groups_cache ) && empty( self::$groups ) ) { + return false; + } + + // Allow for adding extra unit tests. + if ( ! empty( self::$groups ) ) { + $this->groups_cache = array_merge( $this->groups_cache, self::$groups ); + } + + return true; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + * + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException Exception. + */ + public function process_token( $stackPtr ) { + + $token = $this->tokens[ $stackPtr ]; + + $this->excluded_groups = static::merge_custom_array( $this->exclude ); + if ( array_diff_key( $this->groups_cache, $this->excluded_groups ) === [] ) { + // All groups have been excluded. + // Don't remove the listener as the exclude property can be changed inline. + return; + } + + // Check if it is a function not a variable. + if ( \in_array( $token['code'], [ \T_OBJECT_OPERATOR, \T_DOUBLE_COLON ], true ) ) { // This only works for object vars and array members. + $method = $this->phpcsFile->findNext( \T_WHITESPACE, $stackPtr + 1, null, true ); + $possible_parenthesis = $this->phpcsFile->findNext( \T_WHITESPACE, $method + 1, null, true ); + if ( $this->tokens[ $possible_parenthesis ]['code'] === \T_OPEN_PARENTHESIS ) { + return; // So .. it is a function after all ! + } + } + + if ( $this->is_in_isset_or_empty( $stackPtr ) === true ) { + // Checking whether a variable exists is not the same as using it. + return; + } + + foreach ( $this->groups_cache as $groupName => $group ) { + + if ( isset( $this->excluded_groups[ $groupName ] ) ) { + continue; + } + + $patterns = []; + + // Simple variable. + if ( \in_array( $token['code'], [ \T_VARIABLE, \T_DOUBLE_QUOTED_STRING, \T_HEREDOC ], true ) && ! empty( $group['variables'] ) ) { + $patterns = array_merge( $patterns, $group['variables'] ); + $var = $token['content']; + + } + + if ( \in_array( $token['code'], [ \T_OBJECT_OPERATOR, \T_DOUBLE_COLON, \T_DOUBLE_QUOTED_STRING, \T_HEREDOC ], true ) && ! empty( $group['object_vars'] ) ) { + // Object var, ex: $foo->bar / $foo::bar / Foo::bar / Foo::$bar . + $patterns = array_merge( $patterns, $group['object_vars'] ); + + $owner = $this->phpcsFile->findPrevious( [ \T_VARIABLE, \T_STRING ], $stackPtr ); + $child = $this->phpcsFile->findNext( [ \T_STRING, \T_VARIABLE ], $stackPtr ); + $var = implode( '', [ $this->tokens[ $owner ]['content'], $token['content'], $this->tokens[ $child ]['content'] ] ); + + } + + if ( \in_array( $token['code'], [ \T_OPEN_SQUARE_BRACKET, \T_DOUBLE_QUOTED_STRING, \T_HEREDOC ], true ) && ! empty( $group['array_members'] ) ) { + // Array members. + $patterns = array_merge( $patterns, $group['array_members'] ); + + if ( isset( $token['bracket_closer'] ) ) { + $owner = $this->phpcsFile->findPrevious( \T_VARIABLE, $stackPtr ); + $inside = $this->phpcsFile->getTokensAsString( $stackPtr, $token['bracket_closer'] - $stackPtr + 1 ); + $var = implode( '', [ $this->tokens[ $owner ]['content'], $inside ] ); + } + } + + if ( empty( $patterns ) ) { + continue; + } + + $patterns = array_map( [ $this, 'test_patterns' ], $patterns ); + $pattern = implode( '|', $patterns ); + $delim = ( $token['code'] !== \T_OPEN_SQUARE_BRACKET && $token['code'] !== \T_HEREDOC ) ? '\b' : ''; + + if ( $token['code'] === \T_DOUBLE_QUOTED_STRING || $token['code'] === \T_HEREDOC ) { + $var = $token['content']; + } + + if ( empty( $var ) || preg_match( '#(' . $pattern . ')' . $delim . '#', $var, $match ) !== 1 ) { + continue; + } + + $this->addMessage( + $group['message'], + $stackPtr, + $group['type'] === 'error', + $this->string_to_errorcode( $groupName . '_' . $match[1] ), + [ $var ] + ); + + return; // Show one error only. + } + } + + /** + * Transform a wildcard pattern to a usable regex pattern. + * + * @param string $pattern Pattern. + * @return string + */ + private function test_patterns( $pattern ) { + $pattern = preg_quote( $pattern, '#' ); + $pattern = preg_replace( + [ '#\\\\\*#', '[\'"]' ], + [ '.*', '\'' ], + $pattern + ); + return $pattern; + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Classes/DeclarationCompatibilitySniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Classes/DeclarationCompatibilitySniff.php new file mode 100644 index 00000000..6b294807 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Classes/DeclarationCompatibilitySniff.php @@ -0,0 +1,390 @@ + [ + 'widget' => [ 'args', 'instance' ], + 'update' => [ 'new_instance', 'old_instance' ], + 'form' => [ 'instance' ], + 'WP_Widget' => [ + 'id_base', + 'name', + 'widget_options' => [ + 'default' => 'array()', + ], + 'constol_options' => [ + 'default' => 'array()', + ], + ], + 'get_field_name' => [ 'field_name' ], + 'get_field_id' => [ 'field_name' ], + '_register' => [], + '_set' => [ 'number' ], + '_get_display_callback' => [], + '_get_update_callback' => [], + '_get_form_callback' => [], + 'is_preview' => [], + 'display_callback' => [ + 'args', + 'widget_args' => [ + 'default' => '1', + ], + ], + 'update_callback' => [ + 'deprecated' => [ + 'default' => '1', + ], + ], + 'form_callback' => [ + 'widget_args' => [ + 'default' => '1', + ], + ], + 'register_one' => [ + 'number' => [ + 'default' => '-1', + ], + ], + 'save_settings' => [ 'settings' ], + 'get_settings' => [], + ], + 'Walker' => [ + 'start_lvl' => [ + 'output' => [ + 'pass_by_reference' => true, + ], + 'depth' => [ + 'default' => '0', + ], + 'args' => [ + 'default' => 'array()', + ], + ], + 'end_lvl' => [ + 'output' => [ + 'pass_by_reference' => true, + ], + 'depth' => [ + 'default' => '0', + ], + 'args' => [ + 'default' => 'array()', + ], + ], + 'start_el' => [ + 'output' => [ + 'pass_by_reference' => true, + ], + 'object', + 'depth' => [ + 'default' => '0', + ], + 'args' => [ + 'default' => 'array()', + ], + 'current_object_id' => [ + 'default' => '0', + ], + ], + 'end_el' => [ + 'output' => [ + 'pass_by_reference' => true, + ], + 'object', + 'depth' => [ + 'default' => '0', + ], + 'args' => [ + 'default' => 'array()', + ], + ], + 'display_element' => [ + 'element', + 'children_elements' => [ + 'pass_by_reference' => true, + ], + 'max_depth', + 'depth', + 'args', + 'output' => [ + 'pass_by_reference' => true, + ], + ], + 'walk' => [ + 'elements', + 'max_depth', + 'args' => [ + 'variable_length' => true, + ], + ], + 'paged_walk' => [ + 'elements', + 'max_depth', + 'page_num', + 'per_page', + 'args' => [ + 'variable_length' => true, + ], + ], + 'get_number_of_root_elements' => [ + 'elements', + ], + 'unset_children' => [ + 'el', + 'children_elements' => [ + 'pass_by_reference' => true, + ], + ], + ], + ]; + + /** + * List of grouped classes with same methods (as they extend the same parent class) + * + * @var string[] + */ + public $checkClassesGroups = [ + 'Walker' => [ + 'Walker_Category_Checklist', + 'Walker_Category', + 'Walker_CategoryDropdown', + 'Walker_PageDropdown', + 'Walker_Nav_Menu', + 'Walker_Page', + 'Walker_Comment', + ], + ]; + + /** + * Constructs the test with the tokens it wishes to listen for. + */ + public function __construct() { + parent::__construct( [ T_CLASS ], [ T_FUNCTION ], true ); + } + + /** + * Processes this test when one of its tokens is encountered. + * + * @param File $phpcsFile The PHP_CodeSniffer file where the token was found. + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * @param int $currScope A pointer to the start of the scope. + * + * @return void + */ + protected function processTokenWithinScope( File $phpcsFile, $stackPtr, $currScope ) { + + $className = $phpcsFile->getDeclarationName( $currScope ); + + if ( $className !== $this->currentClass ) { + $this->loadFunctionNamesInScope( $phpcsFile, $currScope ); + $this->currentClass = $className; + } + + $methodName = $phpcsFile->getDeclarationName( $stackPtr ); + + $parentClassName = $phpcsFile->findExtendedClassName( $currScope ); + if ( $parentClassName === false ) { + // This class does not extend any other class. + return; + } + + // Meed to define the originalParentClassName since we might override the parentClassName due to signature notations grouping. + $originalParentClassName = $parentClassName; + + if ( array_key_exists( $parentClassName, $this->checkClasses ) === false ) { + // This class does not extend a class we are interested in. + foreach ( $this->checkClassesGroups as $parent => $children ) { + // But it might be one of the grouped classes. + foreach ( $children as $child ) { + if ( $child === $parentClassName ) { + $parentClassName = $parent; + break 2; + } + } + } + if ( array_key_exists( $parentClassName, $this->checkClasses ) === false ) { + // This class really does not extend a class we are interested in. + return; + } + } + + if ( array_key_exists( $methodName, $this->checkClasses[ $parentClassName ] ) === false && + in_array( $methodName, $this->checkClasses[ $parentClassName ], true ) === false + ) { + // This method is not a one we are interested in. + return; + } + + $signatureParams = $phpcsFile->getMethodParameters( $stackPtr ); + + $parentSignature = $this->checkClasses[ $parentClassName ][ $methodName ]; + + if ( count( $signatureParams ) > count( $parentSignature ) ) { + $extra_params = array_slice( $signatureParams, count( $parentSignature ) - count( $signatureParams ) ); + $all_extra_params_have_default = true; + foreach ( $extra_params as $extra_param ) { + if ( array_key_exists( 'default', $extra_param ) === false || $extra_param['default'] !== 'true' ) { + $all_extra_params_have_default = false; + } + } + if ( $all_extra_params_have_default === true ) { + return; // We're good. + } + } + + if ( count( $signatureParams ) !== count( $parentSignature ) ) { + $this->addError( $originalParentClassName, $methodName, $signatureParams, $parentSignature, $phpcsFile, $stackPtr ); + return; + } + + $i = 0; + foreach ( $parentSignature as $key => $param ) { + if ( is_array( $param ) === true ) { + if ( + ( + array_key_exists( 'default', $param ) === true && + array_key_exists( 'default', $signatureParams[ $i ] ) === false + ) || ( + array_key_exists( 'pass_by_reference', $param ) === true && + $param['pass_by_reference'] !== $signatureParams[ $i ]['pass_by_reference'] + ) || ( + array_key_exists( 'variable_length', $param ) === true && + $param['variable_length'] !== $signatureParams[ $i ]['variable_length'] + ) + ) { + $this->addError( $originalParentClassName, $methodName, $signatureParams, $parentSignature, $phpcsFile, $stackPtr ); + return; + } + } + $i++; + } + } + + /** + * Generates an error with nice current and parent class method notations + * + * @param string $parentClassName The name of the extended (parent) class. + * @param string $methodName The name of the method currently being examined. + * @param array $currentMethodSignature The list of params and their options of the method which is being examined. + * @param array $parentMethodSignature The list of params and their options of the parent class method. + * @param File $phpcsFile The PHP_CodeSniffer file where the token was found. + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + private function addError( $parentClassName, $methodName, $currentMethodSignature, $parentMethodSignature, $phpcsFile, $stackPtr ) { + + $currentSignature = sprintf( '%s::%s(%s)', $this->currentClass, $methodName, implode( ', ', $this->generateParamList( $currentMethodSignature ) ) ); + + $parentSignature = sprintf( '%s::%s(%s)', $parentClassName, $methodName, implode( ', ', $this->generateParamList( $parentMethodSignature ) ) ); + + $message = 'Declaration of `%s` should be compatible with `%s`.'; + $data = [ $currentSignature, $parentSignature ]; + $phpcsFile->addError( $message, $stackPtr, 'DeclarationCompatibility', $data ); + } + + /** + * Generates an array of params as they appear in the signature. + * + * @param array $methodSignature Signature of a method. + * + * @return array + */ + private function generateParamList( $methodSignature ) { + $paramList = []; + foreach ( $methodSignature as $param => $options ) { + $paramName = '$'; + if ( is_array( $options ) === false ) { + $paramList[] = '$' . $options; + continue; + } + + if ( array_key_exists( 'name', $options ) === true ) { + $paramName = $options['name']; + } else { + $paramName .= $param; + } + + if ( array_key_exists( 'variable_length', $options ) === true && $options['variable_length'] === true ) { + $paramName = '...' . $paramName; + } + + if ( array_key_exists( 'pass_by_reference', $options ) === true && $options['pass_by_reference'] === true ) { + $paramName = '&' . $paramName; + } + + if ( array_key_exists( 'default', $options ) === true && empty( $options['default'] ) === false ) { + $paramName .= ' = ' . trim( $options['default'] ); + } + + $paramList[] = $paramName; + } + + return $paramList; + } + + /** + * Extracts all the function names found in the given scope. + * + * @param File $phpcsFile The current file being scanned. + * @param int $currScope A pointer to the start of the scope. + * + * @return void + */ + protected function loadFunctionNamesInScope( File $phpcsFile, $currScope ) { + $this->functionList = []; + $tokens = $phpcsFile->getTokens(); + + for ( $i = ( $tokens[ $currScope ]['scope_opener'] + 1 ); $i < $tokens[ $currScope ]['scope_closer']; $i++ ) { + if ( $tokens[ $i ]['code'] !== T_FUNCTION ) { + continue; + } + + $next = $phpcsFile->findNext( T_STRING, $i ); + $this->functionList[] = trim( $tokens[ $next ]['content'] ); + } + } + + /** + * Do nothing outside the scope. Has to be implemented accordingly to parent abstract class. + * + * @param File $phpcsFile PHPCS File. + * @param int $stackPtr Stack position. + */ + public function processTokenOutsideScope( File $phpcsFile, $stackPtr ) {} +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Classes/RestrictedExtendClassesSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Classes/RestrictedExtendClassesSniff.php new file mode 100644 index 00000000..b92ffbd8 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Classes/RestrictedExtendClassesSniff.php @@ -0,0 +1,59 @@ + [ + 'type' => 'warning', + 'message' => 'We recommend extending `WPCOM_VIP_CLI_Command` instead of `WP_CLI_Command` and using the helper functions available in it (such as `stop_the_insanity()`), see https://vip.wordpress.com/documentation/writing-bin-scripts/ for more information.', + 'classes' => [ + 'WP_CLI_Command', + ], + ], + ]; + } + + /** + * Process a matched token. + * + * @param int $stackPtr The position of the current token in the stack. + * @param array $group_name The name of the group which was matched. + * @param string $matched_content The token content (class name) which was matched. + * + * @return void + */ + public function process_matched_token( $stackPtr, $group_name, $matched_content ) { + $tokens = $this->phpcsFile->getTokens(); + + if ( $tokens[ $stackPtr ]['code'] !== T_EXTENDS ) { + // If not extending, bail. + return; + } + + foreach ( $this->getGroups() as $group => $group_args ) { + $this->phpcsFile->{ 'add' . $group_args['type'] }( $group_args['message'], $stackPtr, $group ); + } + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Compatibility/ZoninatorSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Compatibility/ZoninatorSniff.php new file mode 100644 index 00000000..1dae2b96 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Compatibility/ZoninatorSniff.php @@ -0,0 +1,90 @@ +tokens[ $stackPtr ]['content'] !== 'wpcom_vip_load_plugin' ) { + return; + } + + $openBracket = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true ); + + if ( $this->tokens[ $openBracket ]['code'] !== T_OPEN_PARENTHESIS ) { + // Not a function call. + return; + } + + $plugin_name = $this->phpcsFile->findNext( Tokens::$emptyTokens, $openBracket + 1, null, true ); + + if ( $this->remove_wrapping_quotation_marks( $this->tokens[ $plugin_name ]['content'] ) !== 'zoninator' ) { + return; + } + + $comma = $this->phpcsFile->findNext( Tokens::$emptyTokens, $plugin_name + 1, null, true ); + + if ( ! $comma || $this->tokens[ $comma ]['code'] !== 'PHPCS_T_COMMA' ) { + // We are loading the default version. + return; + } + + $folder = $this->phpcsFile->findNext( Tokens::$emptyTokens, $comma + 1, null, true ); + + $comma = $this->phpcsFile->findNext( Tokens::$emptyTokens, $folder + 1, null, true ); + + if ( ! $comma || $this->tokens[ $comma ]['code'] !== 'PHPCS_T_COMMA' ) { + // We are loading the default version. + return; + } + + $version = $this->phpcsFile->findNext( Tokens::$emptyTokens, $comma + 1, null, true ); + $version = $this->remove_wrapping_quotation_marks( $this->tokens[ $version ]['content'] ); + + if ( version_compare( $version, '0.8', '>=' ) === true ) { + $message = 'Zoninator of version >= v0.8 requires WordPress core REST API. Please, make sure the `wpcom_vip_load_wp_rest_api()` is being called on all sites loading this file.'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'RequiresRESTAPI' ); + } + } + + /** + * Removes the quotation marks around T_CONSTANT_ENCAPSED_STRING. + * + * @param string $string T_CONSTANT_ENCAPSED_STRING containing wrapping quotation marks. + * + * @return string String w/o wrapping quotation marks. + */ + public function remove_wrapping_quotation_marks( $string ) { + return trim( str_replace( '"', "'", $string ), "'" ); + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Constants/ConstantStringSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Constants/ConstantStringSniff.php new file mode 100644 index 00000000..d6506c8f --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Constants/ConstantStringSniff.php @@ -0,0 +1,80 @@ +tokens[ $stackPtr ]['content'], [ 'define', 'defined' ], true ) === false ) { + return; + } + + // Find the next non-empty token. + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true ); + + if ( $this->tokens[ $nextToken ]['code'] !== T_OPEN_PARENTHESIS ) { + // Not a function call. + return; + } + + if ( isset( $this->tokens[ $nextToken ]['parenthesis_closer'] ) === false ) { + // Not a function call. + return; + } + + $param = $this->get_function_call_parameter( $stackPtr, 1 ); + if ( $param === false ) { + // Target parameter not found. + return; + } + + $search = Tokens::$emptyTokens; + $search[ T_STRING ] = T_STRING; + + $has_only_tstring = $this->phpcsFile->findNext( $search, $param['start'], $param['end'] + 1, true ); + if ( $has_only_tstring !== false ) { + // Came across something other than a T_STRING token. Ignore. + return; + } + + $tstring_token = $this->phpcsFile->findNext( T_STRING, $param['start'], $param['end'] + 1 ); + + $message = 'Constant name, as a string, should be used along with `%s()`.'; + $data = [ $this->tokens[ $stackPtr ]['content'] ]; + $this->phpcsFile->addError( $message, $tstring_token, 'NotCheckingConstantName', $data ); + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Constants/RestrictedConstantsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Constants/RestrictedConstantsSniff.php new file mode 100644 index 00000000..92d1f7dc --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Constants/RestrictedConstantsSniff.php @@ -0,0 +1,112 @@ +tokens[ $stackPtr ]['code'] === T_STRING ) { + $constantName = $this->tokens[ $stackPtr ]['content']; + } else { + $constantName = trim( $this->tokens[ $stackPtr ]['content'], "\"'" ); + } + + if ( in_array( $constantName, $this->restrictedConstantNames, true ) === false && in_array( $constantName, $this->restrictedConstantDeclaration, true ) === false ) { + // Not the constant we are looking for. + return; + } + + if ( $this->tokens[ $stackPtr ]['code'] === T_STRING && in_array( $constantName, $this->restrictedConstantNames, true ) === true ) { + $message = 'Code is touching the `%s` constant. Make sure it\'s used appropriately.'; + $data = [ $constantName ]; + $this->phpcsFile->addWarning( $message, $stackPtr, 'UsingRestrictedConstant', $data ); + return; + } + + // Find the previous non-empty token. + $openBracket = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $stackPtr - 1, null, true, null, true ); + + if ( $this->tokens[ $openBracket ]['code'] !== T_OPEN_PARENTHESIS ) { + // Not a function call. + return; + } + + if ( isset( $this->tokens[ $openBracket ]['parenthesis_closer'] ) === false ) { + // Not a function call. + return; + } + + // Find the previous non-empty token. + $search = Tokens::$emptyTokens; + $search[] = T_BITWISE_AND; + $previous = $this->phpcsFile->findPrevious( $search, $openBracket - 1, null, true ); + if ( $this->tokens[ $previous ]['code'] === T_FUNCTION ) { + // It's a function definition, not a function call. + return; + } + + if ( in_array( $this->tokens[ $previous ]['code'], Tokens::$functionNameTokens, true ) === true ) { + $data = [ $constantName ]; + if ( $this->tokens[ $previous ]['content'] === 'define' ) { + $message = 'The definition of `%s` constant is prohibited. Please use a different name.'; + $this->phpcsFile->addError( $message, $previous, 'DefiningRestrictedConstant', $data ); + } elseif ( in_array( $constantName, $this->restrictedConstantNames, true ) === true ) { + $message = 'Code is touching the `%s` constant. Make sure it\'s used appropriately.'; + $this->phpcsFile->addWarning( $message, $previous, 'UsingRestrictedConstant', $data ); + } + } + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Files/IncludingFileSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Files/IncludingFileSniff.php new file mode 100644 index 00000000..4cbbfb12 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Files/IncludingFileSniff.php @@ -0,0 +1,207 @@ + 'get_template_directory', + 'STYLESHEETPATH' => 'get_stylesheet_directory', + ]; + + /** + * List of allowed constants. + * + * @var array + */ + public $allowedConstants = [ + 'ABSPATH', + 'WP_CONTENT_DIR', + 'WP_PLUGIN_DIR', + ]; + + /** + * List of keywords allowed for use in custom constants. + * Note: Customizing this property will overwrite current default values. + * + * @var array + */ + public $allowedKeywords = [ + 'PATH', + 'DIR', + ]; + + /** + * Functions used for modify slashes. + * + * @var array + */ + public $slashingFunctions = [ + 'trailingslashit', + 'user_trailingslashit', + 'untrailingslashit', + ]; + + /** + * Groups of functions to restrict. + * + * @return array + */ + public function getGroups() { + return []; + } + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return Tokens::$includeTokens; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true ); + + if ( $this->tokens[ $nextToken ]['code'] === T_OPEN_PARENTHESIS ) { + // The construct is using parenthesis, grab the next non empty token. + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $nextToken + 1, null, true, null, true ); + } + + if ( $this->tokens[ $nextToken ]['code'] === T_DIR || $this->tokens[ $nextToken ]['content'] === '__DIR__' ) { + // The construct is using __DIR__ which is fine. + return; + } + + if ( $this->tokens[ $nextToken ]['code'] === T_VARIABLE ) { + $message = 'File inclusion using variable (`%s`). Probably needs manual inspection.'; + $data = [ $this->tokens[ $nextToken ]['content'] ]; + $this->phpcsFile->addWarning( $message, $nextToken, 'UsingVariable', $data ); + return; + } + + if ( $this->tokens[ $nextToken ]['code'] === T_STRING ) { + if ( in_array( $this->tokens[ $nextToken ]['content'], $this->getPathFunctions, true ) === true ) { + // The construct is using one of the function for getting correct path which is fine. + return; + } + + if ( in_array( $this->tokens[ $nextToken ]['content'], $this->allowedConstants, true ) === true ) { + // The construct is using one of the allowed constants which is fine. + return; + } + + if ( $this->has_custom_path( $this->tokens[ $nextToken ]['content'] ) === true ) { + // The construct is using a constant with an allowed keyword. + return; + } + + if ( array_key_exists( $this->tokens[ $nextToken ]['content'], $this->restrictedConstants ) === true ) { + // The construct is using one of the restricted constants. + $message = '`%s` constant might not be defined or available. Use `%s()` instead.'; + $data = [ $this->tokens[ $nextToken ]['content'], $this->restrictedConstants[ $this->tokens[ $nextToken ]['content'] ] ]; + $this->phpcsFile->addError( $message, $nextToken, 'RestrictedConstant', $data ); + return; + } + + $nextNextToken = $this->phpcsFile->findNext( array_merge( Tokens::$emptyTokens, [ T_COMMENT ] ), $nextToken + 1, null, true, null, true ); + if ( preg_match( '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $this->tokens[ $nextToken ]['content'] ) === 1 && $this->tokens[ $nextNextToken ]['code'] !== T_OPEN_PARENTHESIS ) { + // The construct is using custom constant, which needs manual inspection. + $message = 'File inclusion using custom constant (`%s`). Probably needs manual inspection.'; + $data = [ $this->tokens[ $nextToken ]['content'] ]; + $this->phpcsFile->addWarning( $message, $nextToken, 'UsingCustomConstant', $data ); + return; + } + + if ( strpos( $this->tokens[ $nextToken ]['content'], '$' ) === 0 ) { + $message = 'File inclusion using variable (`%s`). Probably needs manual inspection.'; + $data = [ $this->tokens[ $nextToken ]['content'] ]; + $this->phpcsFile->addWarning( $message, $nextToken, 'UsingVariable', $data ); + return; + } + + if ( in_array( $this->tokens[ $nextToken ]['content'], $this->slashingFunctions, true ) === true ) { + // The construct is using one of the slashing functions, it's probably correct. + return; + } + + if ( $this->is_targetted_token( $nextToken ) ) { + $message = 'File inclusion using custom function ( `%s()` ). Must return local file source, as external URLs are prohibited on WordPress VIP. Probably needs manual inspection.'; + $data = [ $this->tokens[ $nextToken ]['content'] ]; + $this->phpcsFile->addWarning( $message, $nextToken, 'UsingCustomFunction', $data ); + return; + } + + $message = 'Absolute include path must be used. Use `get_template_directory()`, `get_stylesheet_directory()` or `plugin_dir_path()`.'; + $this->phpcsFile->addError( $message, $nextToken, 'NotAbsolutePath' ); + return; + } + + if ( $this->tokens[ $nextToken ]['code'] === T_CONSTANT_ENCAPSED_STRING && filter_var( str_replace( [ '"', "'" ], '', $this->tokens[ $nextToken ]['content'] ), FILTER_VALIDATE_URL ) ) { + $message = 'Include path must be local file source, external URLs are prohibited on WordPress VIP.'; + $this->phpcsFile->addError( $message, $nextToken, 'ExternalURL' ); + return; + } + + $message = 'Absolute include path must be used. Use `get_template_directory()`, `get_stylesheet_directory()` or `plugin_dir_path()`.'; + $this->phpcsFile->addError( $message, $nextToken, 'NotAbsolutePath' ); + } + + /** + * Check if a content string contains a keyword in custom paths. + * + * @param string $content Content string. + * + * @return bool True if the string partially matches a keyword in $allowedCustomKeywords, false otherwise. + */ + private function has_custom_path( $content ) { + foreach ( $this->allowedKeywords as $keyword ) { + if ( strpos( $content, $keyword ) !== false ) { + return true; + } + } + + return false; + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Files/IncludingNonPHPFileSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Files/IncludingNonPHPFileSniff.php new file mode 100644 index 00000000..de30c6e5 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Files/IncludingNonPHPFileSniff.php @@ -0,0 +1,105 @@ + true, + 'inc' => true, + 'phar' => true, + ]; + + /** + * File extensions used for SVG and CSS files. + * + * @var array Key is the extension, value is irrelevant. + */ + private $svg_css_extensions = [ + 'css' => true, + 'svg' => true, + ]; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return Tokens::$includeTokens; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * + * @return void + */ + public function process_token( $stackPtr ) { + $end_of_statement = $this->phpcsFile->findEndOfStatement( $stackPtr ); + $curStackPtr = ( $end_of_statement + 1 ); + + do { + $curStackPtr = $this->phpcsFile->findPrevious( Tokens::$stringTokens, $curStackPtr - 1, $stackPtr ); + if ( $curStackPtr === false ) { + return; + } + + $stringWithoutEnclosingQuotationMarks = trim( $this->tokens[ $curStackPtr ]['content'], "\"'" ); + + $isFileName = preg_match( '`\.([a-z]{2,})$`i', $stringWithoutEnclosingQuotationMarks, $regexMatches ); + + if ( $isFileName !== 1 ) { + continue; + } + + $extension = strtolower( $regexMatches[1] ); + if ( isset( $this->php_extensions[ $extension ] ) === true ) { + return; + } + + $message = 'Local non-PHP file should be loaded via `file_get_contents` rather than via `%s`. Found: %s'; + $data = [ + strtolower( $this->tokens[ $stackPtr ]['content'] ), + $this->tokens[ $curStackPtr ]['content'], + ]; + $code = 'IncludingNonPHPFile'; + + if ( isset( $this->svg_css_extensions[ $extension ] ) === true ) { + // Be more specific for SVG and CSS files. + $message = 'Local SVG and CSS files should be loaded via `file_get_contents` rather than via `%s`. Found: %s'; + $code = 'IncludingSVGCSSFile'; + } + + $this->phpcsFile->addError( $message, $curStackPtr, $code, $data ); + + // Don't throw more than one error for any one statement. + return; + + } while ( $curStackPtr > $stackPtr ); + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Functions/CheckReturnValueSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Functions/CheckReturnValueSniff.php new file mode 100644 index 00000000..86a7348e --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Functions/CheckReturnValueSniff.php @@ -0,0 +1,315 @@ + + * echo esc_url( wpcom_vip_get_term_link( $term ) ); + * + */ +class CheckReturnValueSniff extends Sniff { + + /** + * Pairs we are about to check. + * + * @var array + */ + public $catch = [ + 'esc_url' => [ + 'get_term_link', + ], + 'wp_list_pluck' => [ + 'get_the_tags', + 'get_the_terms', + ], + 'foreach' => [ + 'get_post_meta', + 'get_term_meta', + 'get_the_terms', + 'get_the_tags', + ], + 'array_key_exists' => [ + 'get_option', + ], + ]; + + /** + * Tokens we are about to examine, which are not functions. + * + * @var array + */ + public $notFunctions = [ + 'foreach' => T_FOREACH, + ]; + + /** + * Returns the token types that this sniff is interested in. + * + * @return array(int) + */ + public function register() { + return [ T_STRING ]; + } + + /** + * Processes the tokens that this sniff is interested in. + * + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process_token( $stackPtr ) { + + $this->findDirectFunctionCalls( $stackPtr ); + $this->findNonCheckedVariables( $stackPtr ); + } + + /** + * Check whether the currently examined code is a function call. + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * + * @return bool + */ + private function isFunctionCall( $stackPtr ) { + + if ( $this->tokens[ $stackPtr ]['code'] !== T_STRING ) { + return false; + } + + // Find the next non-empty token. + $openBracket = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true ); + + if ( $this->tokens[ $openBracket ]['code'] !== T_OPEN_PARENTHESIS ) { + // Not a function call. + return false; + } + + // Find the previous non-empty token. + $search = Tokens::$emptyTokens; + $search[] = T_BITWISE_AND; + $previous = $this->phpcsFile->findPrevious( $search, $stackPtr - 1, null, true ); + + // It's a function definition, not a function call, so return false. + return ! ( $this->tokens[ $previous ]['code'] === T_FUNCTION ); + } + + /** + * Check whether the examined code is a variable assignment. + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * + * @return bool + */ + private function isVariableAssignment( $stackPtr ) { + + // Find the previous non-empty token. + $search = Tokens::$emptyTokens; + $search[] = T_BITWISE_AND; + $previous = $this->phpcsFile->findPrevious( $search, $stackPtr - 1, null, true ); + + if ( $this->tokens[ $previous ]['code'] !== T_EQUAL ) { + // It's not a variable assignment. + return false; + } + + $previous = $this->phpcsFile->findPrevious( $search, $previous - 1, null, true ); + + if ( $this->tokens[ $previous ]['code'] !== T_VARIABLE ) { + // It's not a variable assignment. + return false; + } + + return $previous; + } + + /** + * Find instances in which a function call is directly passed to another one w/o checking the return type + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + */ + public function findDirectFunctionCalls( $stackPtr ) { + + $functionName = $this->tokens[ $stackPtr ]['content']; + + if ( array_key_exists( $functionName, $this->catch ) === false ) { + // Not a function we are looking for. + return; + } + + if ( $this->isFunctionCall( $stackPtr ) === false ) { + // Not a function call. + return; + } + + // Find the next non-empty token. + $openBracket = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true ); + + // Find the closing bracket. + $closeBracket = $this->tokens[ $openBracket ]['parenthesis_closer']; + + $startNext = $openBracket + 1; + $next = $this->phpcsFile->findNext( T_STRING, $startNext, $closeBracket, false, null, true ); + while ( $next ) { + if ( in_array( $this->tokens[ $next ]['content'], $this->catch[ $functionName ], true ) === true ) { + $message = "`%s`'s return type must be checked before calling `%s` using that value."; + $data = [ $this->tokens[ $next ]['content'], $functionName ]; + $this->phpcsFile->addError( $message, $next, 'DirectFunctionCall', $data ); + } + $next = $this->phpcsFile->findNext( T_STRING, $next + 1, $closeBracket, false, null, true ); + } + } + + /** + * Deals with situations in which the variable is being used later in the code along with a function which is known for causing issues. + * + * This only catches situations in which the variable is not being used with some other function before it's interacting with function we look for. + * That's currently necessary in order to prevent false positives. + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * + * @return void + */ + public function findNonCheckedVariables( $stackPtr ) { + + $functionName = $this->tokens[ $stackPtr ]['content']; + + $isFunctionWeLookFor = false; + + $callees = []; + + foreach ( $this->catch as $callee => $checkReturnArray ) { + if ( in_array( $functionName, $checkReturnArray, true ) === true ) { + $isFunctionWeLookFor = true; + $callees[] = $callee; + } + } + + if ( $isFunctionWeLookFor === false ) { + // Not a function we are looking for. + return; + } + + if ( $this->isFunctionCall( $stackPtr ) === false ) { + // Not a function call. + return; + } + + $variablePos = $this->isVariableAssignment( $stackPtr ); + + if ( $variablePos === false ) { + // Not a variable assignment. + return; + } + + $variableToken = $this->tokens[ $variablePos ]; + $variableName = $variableToken['content']; + + // Find the next non-empty token. + $openBracket = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true ); + + // Find the closing bracket. + $closeBracket = $this->tokens[ $openBracket ]['parenthesis_closer']; + + if ( in_array( $functionName, [ 'get_post_meta', 'get_term_meta' ], true ) === true ) { + // Since the get_post_meta and get_term_meta always returns an array if $single is set to `true` we need to check for the value of it's third param before proceeding. + $params = []; + $paramNo = 1; + $prevCommaPos = $openBracket + 1; + + for ( $i = $openBracket + 1; $i <= $closeBracket; $i++ ) { + + if ( $this->tokens[ $i ]['code'] === T_OPEN_PARENTHESIS ) { + $i = $this->tokens[ $i ]['parenthesis_closer']; + } + + if ( $this->tokens[ $i ]['code'] === T_COMMA ) { + $params[ $paramNo++ ] = trim( array_reduce( array_slice( $this->tokens, $prevCommaPos, $i - $prevCommaPos ), [ $this, 'reduce_array' ] ) ); + $prevCommaPos = $i + 1; + } + + if ( $i === $closeBracket ) { + $params[ $paramNo ] = trim( array_reduce( array_slice( $this->tokens, $prevCommaPos, $i - $prevCommaPos ), [ $this, 'reduce_array' ] ) ); + break; + } + } + + if ( array_key_exists( 3, $params ) === false || $params[3] === 'false' ) { + // Third param of get_post_meta is not set (default to false) or is set to false. + // Means the function returns an array. We are good then. + return; + } + } + + $nextVariableOccurrence = $this->phpcsFile->findNext( T_VARIABLE, $closeBracket + 1, null, false, $variableName ); + + // Find previous non-empty token, which is not an open parenthesis, comma nor variable. + $search = Tokens::$emptyTokens; + $search[] = T_OPEN_PARENTHESIS; + // This allows us to check for variables which are passed as second parameter of a function e.g.: array_key_exists. + $search[] = T_COMMA; + $search[] = T_VARIABLE; + $search[] = T_CONSTANT_ENCAPSED_STRING; + + $nextFunctionCallWithVariable = $this->phpcsFile->findPrevious( $search, $nextVariableOccurrence - 1, null, true ); + + foreach ( $callees as $callee ) { + $notFunctionsCallee = array_key_exists( $callee, $this->notFunctions ) ? (array) $this->notFunctions[ $callee ] : []; + // Check whether the found token is one of the function calls (or foreach call) we are interested in. + if ( in_array( $this->tokens[ $nextFunctionCallWithVariable ]['code'], array_merge( [ T_STRING ], $notFunctionsCallee ), true ) === true + && $this->tokens[ $nextFunctionCallWithVariable ]['content'] === $callee + ) { + $this->addNonCheckedVariableError( $nextFunctionCallWithVariable, $variableName, $callee ); + return; + } + + $search = array_merge( Tokens::$emptyTokens, [ T_EQUAL ] ); + $next = $this->phpcsFile->findNext( $search, $nextVariableOccurrence + 1, null, true ); + if ( $this->tokens[ $next ]['code'] === T_STRING + && $this->tokens[ $next ]['content'] === $callee + ) { + $this->addNonCheckedVariableError( $next, $variableName, $callee ); + return; + } + } + } + + /** + * Function used as as callback for the array_reduce call. + * + * @param string $carry The final string. + * @param array $item Processed item. + * + * @return string + */ + public function reduce_array( $carry, $item ) { + return $carry . $item['content']; + } + + /** + * Consolidated violation. + * + * @param int $stackPtr The position in the stack where the token was found. + * @param string $variableName Variable name. + * @param string $callee Function name. + */ + private function addNonCheckedVariableError( $stackPtr, $variableName, $callee ) { + $message = 'Type of `%s` must be checked before calling `%s()` using that variable.'; + $data = [ $variableName, $callee ]; + $this->phpcsFile->addError( $message, $stackPtr, 'NonCheckedVariable', $data ); + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Functions/DynamicCallsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Functions/DynamicCallsSniff.php new file mode 100644 index 00000000..c069696f --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Functions/DynamicCallsSniff.php @@ -0,0 +1,188 @@ + true, + 'compact' => true, + 'extract' => true, + 'func_get_args' => true, + 'func_get_arg' => true, + 'func_num_args' => true, + 'get_defined_vars' => true, + 'mb_parse_str' => true, + 'parse_str' => true, + ]; + + /** + * Array of variable assignments encountered, along with their values. + * + * Populated at run-time. + * + * @var array The key is the name of the variable, the value, its assigned value. + */ + private $variables_arr = []; + + /** + * The position in the stack where the token was found. + * + * @var int + */ + private $stackPtr; + + /** + * Returns the token types that this sniff is interested in. + * + * @return array(int) + */ + public function register() { + return [ T_VARIABLE => T_VARIABLE ]; + } + + /** + * Processes the tokens that this sniff is interested in. + * + * @param int $stackPtr The position in the stack where the token was found. + * + * @return void + */ + public function process_token( $stackPtr ) { + $this->stackPtr = $stackPtr; + + // First collect all variables encountered and their values. + $this->collect_variables(); + + // Then find all dynamic calls, and report them. + $this->find_dynamic_calls(); + } + + /** + * Finds any variable-definitions in the file being processed and stores them + * internally in a private array. + * + * @return void + */ + private function collect_variables() { + + $current_var_name = $this->tokens[ $this->stackPtr ]['content']; + + /* + * Find assignments ( $foo = "bar"; ) by finding all non-whitespaces, + * and checking if the first one is T_EQUAL. + */ + $t_item_key = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $this->stackPtr + 1, + null, + true, + null, + true + ); + + if ( $t_item_key === false || $this->tokens[ $t_item_key ]['code'] !== T_EQUAL ) { + return; + } + + /* + * Find assignments which only assign a plain text string. + */ + $end_of_statement = $this->phpcsFile->findNext( [ T_SEMICOLON, T_CLOSE_TAG ], ( $t_item_key + 1 ) ); + $value_ptr = null; + + for ( $i = $t_item_key + 1; $i < $end_of_statement; $i++ ) { + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) === true ) { + continue; + } + + if ( $this->tokens[ $i ]['code'] !== T_CONSTANT_ENCAPSED_STRING ) { + // Not a plain text string value. Value cannot be determined reliably. + return; + } + + $value_ptr = $i; + } + + if ( isset( $value_ptr ) === false ) { + // Parse error. Bow out. + return; + } + + /* + * If we reached the end of the loop and the $value_ptr was set, we know for sure + * this was a plain text string variable assignment. + */ + $current_var_value = $this->strip_quotes( $this->tokens[ $value_ptr ]['content'] ); + + if ( isset( $this->disallowed_functions[ $current_var_value ] ) === false ) { + // Text string is not one of the ones we're looking for. + return; + } + + /* + * Register the variable name and value in the internal array for later usage. + */ + $this->variables_arr[ $current_var_name ] = $current_var_value; + } + + /** + * Find any dynamic calls being made using variables. + * + * Report on this when found, using the name of the function in the message. + * + * @return void + */ + private function find_dynamic_calls() { + // No variables detected; no basis for doing anything. + if ( empty( $this->variables_arr ) ) { + return; + } + + /* + * If variable is not found in our registry of variables, do nothing, as we cannot be + * sure that the function being called is one of the disallowed ones. + */ + if ( ! isset( $this->variables_arr[ $this->tokens[ $this->stackPtr ]['content'] ] ) ) { + return; + } + + /* + * Check if we have an '(' next. + */ + $next = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $this->stackPtr + 1 ), null, true ); + if ( $next === false || $this->tokens[ $next ]['code'] !== T_OPEN_PARENTHESIS ) { + return; + } + + $message = 'Dynamic calling is not recommended in the case of %s().'; + $data = [ $this->variables_arr[ $this->tokens[ $this->stackPtr ]['content'] ] ]; + $this->phpcsFile->addError( $message, $this->stackPtr, 'DynamicCalls', $data ); + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Functions/RestrictedFunctionsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Functions/RestrictedFunctionsSniff.php new file mode 100644 index 00000000..8f3bba86 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Functions/RestrictedFunctionsSniff.php @@ -0,0 +1,371 @@ + [ + 'type' => 'error', + 'message' => '`%s` is prohibited on the WordPress VIP platform due to memory corruption.', + 'functions' => [ + 'opcache_reset', + 'opcache_invalidate', + 'opcache_compile_file', + ], + ], + 'config_settings' => [ + 'type' => 'error', + 'message' => '`%s` is not recommended for use on the WordPress VIP platform due to potential setting changes.', + 'functions' => [ + 'opcache_is_script_cached', + 'opcache_get_status', + 'opcache_get_configuration', + ], + ], + 'internal' => [ + 'type' => 'error', + 'message' => '`%1$s()` is for internal use only.', + 'functions' => [ + 'wpcom_vip_irc', + ], + ], + 'flush_rewrite_rules' => [ + 'type' => 'error', + 'message' => '`%s` should not be used in any normal circumstances in the theme code.', + 'functions' => [ + 'flush_rewrite_rules', + ], + ], + 'flush_rules' => [ + 'type' => 'error', + 'message' => '`%s` should not be used in any normal circumstances in the theme code.', + 'functions' => [ + 'flush_rules', + ], + 'object_var' => [ + '$wp_rewrite' => true, + ], + ], + 'attachment_url_to_postid' => [ + 'type' => 'error', + 'message' => '`%s()` is prohibited, please use `wpcom_vip_attachment_url_to_postid()` instead.', + 'functions' => [ + 'attachment_url_to_postid', + ], + ], + // @link https://docs.wpvip.com/technical-references/code-review/vip-notices/#h-switch_to_blog + 'switch_to_blog' => [ + 'type' => 'warning', + 'message' => '%s() may not work as expected since it only changes the database context for the blog and does not load the plugins or theme of that site. Filters or hooks on the blog you are switching to will not run.', + 'functions' => [ + 'switch_to_blog', + ], + ], + 'get_page_by_title' => [ + 'type' => 'error', + 'message' => '%s() is prohibited, please use wpcom_vip_get_page_by_title() instead.', + 'functions' => [ + 'get_page_by_title', + ], + ], + 'url_to_postid' => [ + 'type' => 'error', + 'message' => '%s() is prohibited, please use wpcom_vip_url_to_postid() instead.', + 'functions' => [ + 'url_to_postid', + ], + ], + // @link https://docs.wpvip.com/how-tos/customize-user-roles/ + 'custom_role' => [ + 'type' => 'error', + 'message' => 'Use wpcom_vip_add_role() instead of %s().', + 'functions' => [ + 'add_role', + ], + ], + 'term_exists' => [ + 'type' => 'error', + 'message' => '%s() is highly discouraged due to not being cached; please use wpcom_vip_term_exists() instead.', + 'functions' => [ + 'term_exists', + ], + ], + 'count_user_posts' => [ + 'type' => 'error', + 'message' => '%s() is highly discouraged due to not being cached; please use wpcom_vip_count_user_posts() instead.', + 'functions' => [ + 'count_user_posts', + ], + ], + 'wp_old_slug_redirect' => [ + 'type' => 'error', + 'message' => '%s() is highly discouraged due to not being cached; please use wpcom_vip_old_slug_redirect() instead.', + 'functions' => [ + 'wp_old_slug_redirect', + ], + ], + 'get_adjacent_post' => [ + 'type' => 'error', + 'message' => '%s() is highly discouraged due to not being cached; please use wpcom_vip_get_adjacent_post() instead.', + 'functions' => [ + 'get_adjacent_post', + 'get_previous_post', + 'get_previous_post_link', + 'get_next_post', + 'get_next_post_link', + ], + ], + 'get_intermediate_image_sizes' => [ + 'type' => 'error', + 'message' => 'Intermediate images do not exist on the VIP platform, and thus get_intermediate_image_sizes() returns an empty array() on the platform. This behavior is intentional to prevent WordPress from generating multiple thumbnails when images are uploaded.', + 'functions' => [ + 'get_intermediate_image_sizes', + ], + ], + // @link https://docs.wpvip.com/technical-references/code-review/vip-warnings/#h-mobile-detection + 'wp_is_mobile' => [ + 'type' => 'error', + 'message' => '%s() found. When targeting mobile visitors, jetpack_is_mobile() should be used instead of wp_is_mobile. It is more robust and works better with full page caching.', + 'functions' => [ + 'wp_is_mobile', + ], + ], + 'session' => [ + 'type' => 'error', + 'message' => 'The use of PHP session function %s() is prohibited.', + 'functions' => [ + 'session_abort', + 'session_cache_expire', + 'session_cache_limiter', + 'session_commit', + 'session_create_id', + 'session_decode', + 'session_destroy', + 'session_encode', + 'session_gc', + 'session_get_cookie_params', + 'session_id', + 'session_is_registered', + 'session_module_name', + 'session_name', + 'session_regenerate_id', + 'session_register_shutdown', + 'session_register', + 'session_reset', + 'session_save_path', + 'session_set_cookie_params', + 'session_set_save_handler', + 'session_start', + 'session_status', + 'session_unregister', + 'session_unset', + 'session_write_close', + ], + ], + 'file_ops' => [ + 'type' => 'error', + 'message' => 'Filesystem writes are forbidden, please do not use %s().', + 'functions' => [ + 'delete', + 'file_put_contents', + 'flock', + 'fputcsv', + 'fputs', + 'fwrite', + 'ftruncate', + 'is_writable', + 'is_writeable', + 'link', + 'rename', + 'symlink', + 'tempnam', + 'touch', + 'unlink', + ], + ], + 'directory' => [ + 'type' => 'error', + 'message' => 'Filesystem writes are forbidden, please do not use %s().', + 'functions' => [ + 'mkdir', + 'rmdir', + ], + ], + 'chmod' => [ + 'type' => 'error', + 'message' => 'Filesystem writes are forbidden, please do not use %s().', + 'functions' => [ + 'chgrp', + 'chown', + 'chmod', + 'lchgrp', + 'lchown', + ], + ], + 'stats_get_csv' => [ + 'type' => 'error', + 'message' => 'Using `%s` outside of Jetpack context pollutes the stats_cache entry in the wp_options table. We recommend building a custom function instead.', + 'functions' => [ + 'stats_get_csv', + ], + ], + 'wp_mail' => [ + 'type' => 'warning', + 'message' => '`%s` should be used sparingly. For any bulk emailing should be handled by a 3rd party service, in order to prevent domain or IP addresses being flagged as spam.', + 'functions' => [ + 'wp_mail', + 'mail', + ], + ], + 'is_multi_author' => [ + 'type' => 'warning', + 'message' => '`%s` can be very slow on large sites and likely not needed on many VIP sites since they tend to have more than one author.', + 'functions' => [ + 'is_multi_author', + ], + ], + 'advanced_custom_fields' => [ + 'type' => 'warning', + 'message' => '`%1$s` does not escape output by default, please echo and escape with the `get_*()` variant function instead (i.e. `get_field()`).', + 'functions' => [ + 'the_sub_field', + 'the_field', + ], + ], + // @link https://docs.wpvip.com/technical-references/code-review/vip-warnings/#h-remote-calls + 'wp_remote_get' => [ + 'type' => 'warning', + 'message' => '%s() is highly discouraged. Please use vip_safe_wp_remote_get() instead which is designed to more gracefully handle failure than wp_remote_get() does.', + 'functions' => [ + 'wp_remote_get', + ], + ], + // @link https://docs.wpvip.com/technical-references/code-review/vip-errors/#h-cache-constraints + 'cookies' => [ + 'type' => 'error', + 'message' => 'Due to server-side caching, server-side based client related logic might not work. We recommend implementing client side logic in JavaScript instead.', + 'functions' => [ + 'setcookie', + ], + ], + // @todo Introduce a sniff specific to get_posts() that checks for suppress_filters=>false being supplied. + 'get_posts' => [ + 'type' => 'warning', + 'message' => '%s() is uncached unless the "suppress_filters" parameter is set to false. If the suppress_filter parameter is set to false this can be safely ignored. More Info: https://docs.wpvip.com/technical-references/caching/uncached-functions/.', + 'functions' => [ + 'get_posts', + 'wp_get_recent_posts', + 'get_children', + ], + ], + 'create_function' => [ + 'type' => 'warning', + 'message' => '%s() is highly discouraged, as it can execute arbritary code (additionally, it\'s deprecated as of PHP 7.2): https://docs.wpvip.com/technical-references/code-review/vip-warnings/#h-eval-and-create_function. )', + 'functions' => [ + 'create_function', + ], + ], + 'get_page_by_path' => [ + 'type' => 'warning', + 'message' => '%s() is highly discouraged due to not being cached; please use wpcom_vip_get_page_by_path() instead.', + 'functions' => [ + 'get_page_by_path', + ], + ], + ]; + + $deprecated_vip_helpers = [ + 'get_term_link' => 'wpcom_vip_get_term_link', + 'get_term_by' => 'wpcom_vip_get_term_by', + 'get_category_by_slug' => 'wpcom_vip_get_category_by_slug', + ]; + foreach ( $deprecated_vip_helpers as $restricted => $helper ) { + $groups[ $helper ] = [ + 'type' => 'warning', + 'message' => "`%s()` is deprecated, please use `{$restricted}()` instead.", + 'functions' => [ + $helper, + ], + ]; + } + + return $groups; + } + + /** + * Verify the current token is a function call or a method call on a specific object variable. + * + * This differs to the parent class method that it overrides, by also checking to see if the + * function call is actually a method call on a specific object variable. This works best with global objects, + * such as the `flush_rules()` method on the `$wp_rewrite` object. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return bool + */ + public function is_targetted_token( $stackPtr ) { + // Exclude function definitions, class methods, and namespaced calls. + if ( $this->tokens[ $stackPtr ]['code'] === \T_STRING && isset( $this->tokens[ $stackPtr - 1 ] ) ) { + // Check if this is really a function. + $next = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true ); + if ( $next !== false && $this->tokens[ $next ]['code'] !== T_OPEN_PARENTHESIS ) { + return false; + } + + $prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $stackPtr - 1, null, true ); + if ( $prev !== false ) { + + // Start difference to parent class method. + // Check to see if function is a method on a specific object variable. + if ( ! empty( $this->groups[ $this->tokens[ $stackPtr ]['content'] ]['object_var'] ) ) { + $prevPrev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $stackPtr - 2, null, true ); + + return $this->tokens[ $prev ]['code'] === \T_OBJECT_OPERATOR && isset( $this->groups[ $this->tokens[ $stackPtr ]['content'] ]['object_var'][ $this->tokens[ $prevPrev ]['content'] ] ); + } // End difference to parent class method. + + // Skip sniffing if calling a same-named method, or on function definitions. + $skipped = [ + \T_FUNCTION => \T_FUNCTION, + \T_CLASS => \T_CLASS, + \T_AS => \T_AS, // Use declaration alias. + \T_DOUBLE_COLON => \T_DOUBLE_COLON, + \T_OBJECT_OPERATOR => \T_OBJECT_OPERATOR, + \T_NEW => \T_NEW, + ]; + if ( isset( $skipped[ $this->tokens[ $prev ]['code'] ] ) ) { + return false; + } + // Skip namespaced functions, ie: `\foo\bar()` not `\bar()`. + if ( $this->tokens[ $prev ]['code'] === \T_NS_SEPARATOR ) { + $pprev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $prev - 1, null, true ); + if ( $pprev !== false && $this->tokens[ $pprev ]['code'] === \T_STRING ) { + return false; + } + } + } + return true; + } + return false; + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Functions/StripTagsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Functions/StripTagsSniff.php new file mode 100644 index 00000000..5434427d --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Functions/StripTagsSniff.php @@ -0,0 +1,59 @@ + true, + ]; + + /** + * Process the parameters of a matched function. + * + * @param int $stackPtr The position of the current token in the stack. + * @param array $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + if ( count( $parameters ) === 1 ) { + $message = '`strip_tags()` does not strip CSS and JS in between the script and style tags. Use `wp_strip_all_tags()` to strip all tags.'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'StripTagsOneParameter' ); + } elseif ( isset( $parameters[2] ) ) { + $message = '`strip_tags()` does not strip CSS and JS in between the script and style tags. Use `wp_kses()` instead to allow only the HTML you need.'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'StripTagsTwoParameters' ); + } + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Hooks/AlwaysReturnInFilterSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Hooks/AlwaysReturnInFilterSniff.php new file mode 100644 index 00000000..8029e732 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Hooks/AlwaysReturnInFilterSniff.php @@ -0,0 +1,299 @@ +tokens[ $stackPtr ]['content']; + + if ( $functionName !== 'add_filter' ) { + return; + } + + $this->filterNamePtr = $this->phpcsFile->findNext( + array_merge( Tokens::$emptyTokens, [ T_OPEN_PARENTHESIS ] ), + $stackPtr + 1, + null, + true, + null, + true + ); + + if ( ! $this->filterNamePtr ) { + // Something is wrong. + return; + } + + $callbackPtr = $this->phpcsFile->findNext( + array_merge( Tokens::$emptyTokens, [ T_COMMA ] ), + $this->filterNamePtr + 1, + null, + true, + null, + true + ); + + if ( ! $callbackPtr ) { + // Something is wrong. + return; + } + + if ( $this->tokens[ $callbackPtr ]['code'] === 'PHPCS_T_CLOSURE' ) { + $this->processFunctionBody( $callbackPtr ); + } elseif ( $this->tokens[ $callbackPtr ]['code'] === T_ARRAY + || $this->tokens[ $callbackPtr ]['code'] === T_OPEN_SHORT_ARRAY + ) { + $this->processArray( $callbackPtr ); + } elseif ( in_array( $this->tokens[ $callbackPtr ]['code'], Tokens::$stringTokens, true ) === true ) { + $this->processString( $callbackPtr ); + } + } + + /** + * Process array. + * + * @param int $stackPtr The position in the stack where the token was found. + */ + private function processArray( $stackPtr ) { + + $open_close = $this->find_array_open_close( $stackPtr ); + if ( $open_close === false ) { + return; + } + + $previous = $this->phpcsFile->findPrevious( + Tokens::$emptyTokens, + $open_close['closer'] - 1, + null, + true + ); + + if ( in_array( T_CLASS, $this->tokens[ $stackPtr ]['conditions'], true ) === true ) { + $classPtr = array_search( T_CLASS, $this->tokens[ $stackPtr ]['conditions'], true ); + if ( $classPtr ) { + $classToken = $this->tokens[ $classPtr ]; + $this->processString( $previous, $classToken['scope_opener'], $classToken['scope_closer'] ); + return; + } + } + + $this->processString( $previous ); + } + + /** + * Process string. + * + * @param int $stackPtr The position in the stack where the token was found. + * @param int $start The start of the token. + * @param int $end The end of the token. + */ + private function processString( $stackPtr, $start = 0, $end = null ) { + + $callbackFunctionName = substr( $this->tokens[ $stackPtr ]['content'], 1, -1 ); + + $callbackFunctionPtr = $this->phpcsFile->findNext( + T_STRING, + $start, + $end, + false, + $callbackFunctionName + ); + + if ( ! $callbackFunctionPtr ) { + // We were not able to find the function callback in the file. + return; + } + + $this->processFunction( $callbackFunctionPtr, $start, $end ); + } + + /** + * Process function. + * + * @param int $stackPtr The position in the stack where the token was found. + * @param int $start The start of the token. + * @param int $end The end of the token. + */ + private function processFunction( $stackPtr, $start = 0, $end = null ) { + + $functionName = $this->tokens[ $stackPtr ]['content']; + + $offset = $start; + while ( $this->phpcsFile->findNext( [ T_FUNCTION ], $offset, $end ) !== false ) { + $functionStackPtr = $this->phpcsFile->findNext( [ T_FUNCTION ], $offset, $end ); + $functionNamePtr = $this->phpcsFile->findNext( Tokens::$emptyTokens, $functionStackPtr + 1, null, true, null, true ); + if ( $this->tokens[ $functionNamePtr ]['code'] === T_STRING && $this->tokens[ $functionNamePtr ]['content'] === $functionName ) { + $this->processFunctionBody( $functionStackPtr ); + return; + } + $offset = $functionStackPtr + 1; + } + } + + /** + * Process function's body + * + * @param int $stackPtr The position in the stack where the token was found. + */ + private function processFunctionBody( $stackPtr ) { + + $filterName = $this->tokens[ $this->filterNamePtr ]['content']; + + $methodProps = $this->phpcsFile->getMethodProperties( $stackPtr ); + if ( $methodProps['is_abstract'] === true ) { + $message = 'The callback for the `%s` filter hook-in points to an abstract method. Please ensure that child class implementations of this method always return a value.'; + $data = [ $filterName ]; + $this->phpcsFile->addWarning( $message, $stackPtr, 'AbstractMethod', $data ); + return; + } + + if ( isset( $this->tokens[ $stackPtr ]['scope_opener'], $this->tokens[ $stackPtr ]['scope_closer'] ) === false ) { + // Live coding, parse or tokenizer error. + return; + } + + $argPtr = $this->phpcsFile->findNext( + array_merge( Tokens::$emptyTokens, [ T_STRING, T_OPEN_PARENTHESIS ] ), + $stackPtr + 1, + null, + true, + null, + true + ); + + // If arg is being passed by reference, we can skip. + if ( $this->tokens[ $argPtr ]['code'] === T_BITWISE_AND ) { + return; + } + + $functionBodyScopeStart = $this->tokens[ $stackPtr ]['scope_opener']; + $functionBodyScopeEnd = $this->tokens[ $stackPtr ]['scope_closer']; + + $returnTokenPtr = $this->phpcsFile->findNext( + [ T_RETURN ], + $functionBodyScopeStart + 1, + $functionBodyScopeEnd + ); + + $insideIfConditionalReturn = 0; + $outsideConditionalReturn = 0; + + while ( $returnTokenPtr ) { + if ( $this->isInsideIfConditonal( $returnTokenPtr ) ) { + $insideIfConditionalReturn++; + } else { + $outsideConditionalReturn++; + } + if ( $this->isReturningVoid( $returnTokenPtr ) ) { + $message = 'Please, make sure that a callback to `%s` filter is returning void intentionally.'; + $data = [ $filterName ]; + $this->phpcsFile->addError( $message, $functionBodyScopeStart, 'VoidReturn', $data ); + } + $returnTokenPtr = $this->phpcsFile->findNext( + [ T_RETURN ], + $returnTokenPtr + 1, + $functionBodyScopeEnd + ); + } + + if ( $insideIfConditionalReturn >= 0 && $outsideConditionalReturn === 0 ) { + $message = 'Please, make sure that a callback to `%s` filter is always returning some value.'; + $data = [ $filterName ]; + $this->phpcsFile->addError( $message, $functionBodyScopeStart, 'MissingReturnStatement', $data ); + + } + } + + /** + * Is the current token inside a conditional? + * + * @param int $stackPtr The position in the stack where the token was found. + * + * @return bool + */ + private function isInsideIfConditonal( $stackPtr ) { + + // This check helps us in situations a class or a function is wrapped + // inside a conditional as a whole. Eg.: inside `class_exists`. + if ( end( $this->tokens[ $stackPtr ]['conditions'] ) === T_FUNCTION ) { + return false; + } + + // Similar case may be a conditional closure. + if ( end( $this->tokens[ $stackPtr ]['conditions'] ) === 'PHPCS_T_CLOSURE' ) { + return false; + } + + // Loop over the array of conditions and look for an IF. + reset( $this->tokens[ $stackPtr ]['conditions'] ); + + if ( array_key_exists( 'conditions', $this->tokens[ $stackPtr ] ) === true + && is_array( $this->tokens[ $stackPtr ]['conditions'] ) === true + && empty( $this->tokens[ $stackPtr ]['conditions'] ) === false + ) { + foreach ( $this->tokens[ $stackPtr ]['conditions'] as $tokenPtr => $tokenCode ) { + if ( $this->tokens[ $stackPtr ]['conditions'][ $tokenPtr ] === T_IF ) { + return true; + } + } + } + return false; + } + + /** + * Is the token returning void + * + * @param int $stackPtr The position in the stack where the token was found. + * + * @return bool + **/ + private function isReturningVoid( $stackPtr ) { + + $nextToReturnTokenPtr = $this->phpcsFile->findNext( + [ Tokens::$emptyTokens ], + $stackPtr + 1, + null, + true + ); + + return $this->tokens[ $nextToReturnTokenPtr ]['code'] === T_SEMICOLON; + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Hooks/PreGetPostsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Hooks/PreGetPostsSniff.php new file mode 100644 index 00000000..75b54729 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Hooks/PreGetPostsSniff.php @@ -0,0 +1,450 @@ +tokens[ $stackPtr ]['content']; + + if ( $functionName !== 'add_action' ) { + // We are interested in add_action calls only. + return; + } + + $actionNamePtr = $this->phpcsFile->findNext( + array_merge( Tokens::$emptyTokens, [ T_OPEN_PARENTHESIS ] ), + $stackPtr + 1, + null, + true, + null, + true + ); + + if ( ! $actionNamePtr ) { + // Something is wrong. + return; + } + + if ( substr( $this->tokens[ $actionNamePtr ]['content'], 1, -1 ) !== 'pre_get_posts' ) { + // This is not setting a callback for pre_get_posts action. + return; + } + + $callbackPtr = $this->phpcsFile->findNext( + array_merge( Tokens::$emptyTokens, [ T_COMMA ] ), + $actionNamePtr + 1, + null, + true, + null, + true + ); + + if ( ! $callbackPtr ) { + // Something is wrong. + return; + } + + if ( $this->tokens[ $callbackPtr ]['code'] === 'PHPCS_T_CLOSURE' ) { + $this->processClosure( $callbackPtr ); + } elseif ( $this->tokens[ $callbackPtr ]['code'] === T_ARRAY + || $this->tokens[ $callbackPtr ]['code'] === T_OPEN_SHORT_ARRAY + ) { + $this->processArray( $callbackPtr ); + } elseif ( in_array( $this->tokens[ $callbackPtr ]['code'], Tokens::$stringTokens, true ) === true ) { + $this->processString( $callbackPtr ); + } + } + + /** + * Process array. + * + * @param int $stackPtr The position in the stack where the token was found. + */ + private function processArray( $stackPtr ) { + + $open_close = $this->find_array_open_close( $stackPtr ); + if ( $open_close === false ) { + return; + } + + $previous = $this->phpcsFile->findPrevious( + Tokens::$emptyTokens, + $open_close['closer'] - 1, + null, + true + ); + + $this->processString( $previous ); + } + + /** + * Process string. + * + * @param int $stackPtr The position in the stack where the token was found. + */ + private function processString( $stackPtr ) { + + $callbackFunctionName = substr( $this->tokens[ $stackPtr ]['content'], 1, -1 ); + + $callbackFunctionPtr = $this->phpcsFile->findNext( + T_STRING, + 0, + null, + false, + $callbackFunctionName + ); + + if ( ! $callbackFunctionPtr ) { + // We were not able to find the function callback in the file. + return; + } + + $this->processFunction( $callbackFunctionPtr ); + } + + /** + * Process function. + * + * @param int $stackPtr The position in the stack where the token was found. + */ + private function processFunction( $stackPtr ) { + + $wpQueryObjectNamePtr = $this->phpcsFile->findNext( + [ T_VARIABLE ], + $stackPtr + 1, + null, + false, + null, + true + ); + + if ( ! $wpQueryObjectNamePtr ) { + // Something is wrong. + return; + } + + $wpQueryObjectVariableName = $this->tokens[ $wpQueryObjectNamePtr ]['content']; + + $functionDefinitionPtr = $this->phpcsFile->findPrevious( [ T_FUNCTION ], $wpQueryObjectNamePtr - 1 ); + + if ( ! $functionDefinitionPtr ) { + // Something is wrong. + return; + } + + $this->processFunctionBody( $functionDefinitionPtr, $wpQueryObjectVariableName ); + } + + /** + * Process closure. + * + * @param int $stackPtr The position in the stack where the token was found. + */ + private function processClosure( $stackPtr ) { + + $wpQueryObjectNamePtr = $this->phpcsFile->findNext( + [ T_VARIABLE ], + $stackPtr + 1, + null, + false, + null, + true + ); + + if ( ! $wpQueryObjectNamePtr ) { + // Something is wrong. + return; + } + + $this->processFunctionBody( $stackPtr, $this->tokens[ $wpQueryObjectNamePtr ]['content'] ); + } + + /** + * Process function's body + * + * @param int $stackPtr The position in the stack where the token was found. + * @param string $variableName Variable name. + */ + private function processFunctionBody( $stackPtr, $variableName ) { + + $functionBodyScopeStart = $this->tokens[ $stackPtr ]['scope_opener']; + $functionBodyScopeEnd = $this->tokens[ $stackPtr ]['scope_closer']; + + $wpQueryVarUsed = $this->phpcsFile->findNext( + [ T_VARIABLE ], + $functionBodyScopeStart + 1, + $functionBodyScopeEnd, + false, + $variableName + ); + while ( $wpQueryVarUsed ) { + if ( $this->isPartOfIfConditional( $wpQueryVarUsed ) ) { + if ( $this->isEarlyMainQueryCheck( $wpQueryVarUsed ) ) { + return; + } + } elseif ( $this->isInsideIfConditonal( $wpQueryVarUsed ) ) { + if ( ! $this->isParentConditionalCheckingMainQuery( $wpQueryVarUsed ) ) { + $this->addPreGetPostsWarning( $wpQueryVarUsed ); + } + } elseif ( $this->isWPQueryMethodCall( $wpQueryVarUsed, 'set' ) ) { + $this->addPreGetPostsWarning( $wpQueryVarUsed ); + } + $wpQueryVarUsed = $this->phpcsFile->findNext( + [ T_VARIABLE ], + $wpQueryVarUsed + 1, + $functionBodyScopeEnd, + false, + $variableName + ); + } + } + + /** + * Consolidated violation. + * + * @param int $stackPtr The position in the stack where the token was found. + */ + private function addPreGetPostsWarning( $stackPtr ) { + $message = 'Main WP_Query is being modified without `$query->is_main_query()` check. Needs manual inspection.'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'PreGetPosts' ); + } + + /** + * Is parent conditional checking is_main_query? + * + * @param int $stackPtr The position in the stack where the token was found. + * + * @return bool + */ + private function isParentConditionalCheckingMainQuery( $stackPtr ) { + + if ( array_key_exists( 'conditions', $this->tokens[ $stackPtr ] ) === false + || is_array( $this->tokens[ $stackPtr ]['conditions'] ) === false + || empty( $this->tokens[ $stackPtr ]['conditions'] ) === true + ) { + return false; + } + + $conditionStackPtrs = array_keys( $this->tokens[ $stackPtr ]['conditions'] ); + $lastConditionStackPtr = array_pop( $conditionStackPtrs ); + + while ( $this->tokens[ $stackPtr ]['conditions'][ $lastConditionStackPtr ] === T_IF ) { + + $next = $this->phpcsFile->findNext( + [ T_VARIABLE ], + $lastConditionStackPtr + 1, + null, + false, + $this->tokens[ $stackPtr ]['content'], + true + ); + while ( $next ) { + if ( $this->isWPQueryMethodCall( $next, 'is_main_query' ) === true ) { + return true; + } + $next = $this->phpcsFile->findNext( + [ T_VARIABLE ], + $next + 1, + null, + false, + $this->tokens[ $stackPtr ]['content'], + true + ); + } + + $lastConditionStackPtr = array_pop( $conditionStackPtrs ); + } + + return false; + } + + + /** + * Is the current code an early main query check? + * + * @param int $stackPtr The position in the stack where the token was found. + * + * @return bool + */ + private function isEarlyMainQueryCheck( $stackPtr ) { + + if ( ! $this->isWPQueryMethodCall( $stackPtr, 'is_main_query' ) ) { + return false; + } + + if ( array_key_exists( 'nested_parenthesis', $this->tokens[ $stackPtr ] ) === false + || empty( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) === true + ) { + return false; + } + + $parentheses = $this->tokens[ $stackPtr ]['nested_parenthesis']; + do { + $nestedParenthesisEnd = array_shift( $parentheses ); + if ( $nestedParenthesisEnd === null ) { + // Nothing left in the array. No parenthesis found with a non-closure owner. + return false; + } + + if ( isset( $this->tokens[ $nestedParenthesisEnd ]['parenthesis_owner'] ) + && $this->tokens[ $this->tokens[ $nestedParenthesisEnd ]['parenthesis_owner'] ]['code'] !== T_CLOSURE + ) { + break; + } + } while ( true ); + + $owner = $this->tokens[ $nestedParenthesisEnd ]['parenthesis_owner']; + if ( isset( $this->tokens[ $owner ]['scope_opener'], $this->tokens[ $owner ]['scope_closer'] ) === false ) { + // This may be an inline control structure (no braces). + $next = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $nestedParenthesisEnd + 1 ), + null, + true + ); + + if ( $next !== false && $this->tokens[ $next ]['code'] === T_RETURN ) { + return true; + } + + return false; + } + + $next = $this->phpcsFile->findNext( + [ T_RETURN ], + $this->tokens[ $this->tokens[ $nestedParenthesisEnd ]['parenthesis_owner'] ]['scope_opener'], + $this->tokens[ $this->tokens[ $nestedParenthesisEnd ]['parenthesis_owner'] ]['scope_closer'], + false, + 'return', + true + ); + + if ( $next ) { + return true; + } + + return false; + } + + /** + * Is the current code a WP_Query call? + * + * @param int $stackPtr The position in the stack where the token was found. + * @param null $method Method. + * + * @return bool + */ + private function isWPQueryMethodCall( $stackPtr, $method = null ) { + $next = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $stackPtr + 1, + null, + true, + null, + true + ); + + if ( ! $next || $this->tokens[ $next ]['type'] !== 'T_OBJECT_OPERATOR' ) { + return false; + } + + if ( $method === null ) { + return true; + } + + $next = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $next + 1, + null, + true, + null, + true + ); + + return $next && $this->tokens[ $next ]['code'] === T_STRING && $method === $this->tokens[ $next ]['content']; + } + + /** + * Is the current token a part of a conditional? + * + * @param int $stackPtr The position in the stack where the token was found. + * + * @return bool + */ + private function isPartOfIfConditional( $stackPtr ) { + + if ( array_key_exists( 'nested_parenthesis', $this->tokens[ $stackPtr ] ) === true + && is_array( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) === true + && empty( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) === false + ) { + $previousLocalIf = $this->phpcsFile->findPrevious( + [ T_IF ], + $stackPtr - 1, + null, + false, + null, + true + ); + if ( $previousLocalIf !== false + && $this->tokens[ $previousLocalIf ]['parenthesis_opener'] < $stackPtr + && $this->tokens[ $previousLocalIf ]['parenthesis_closer'] > $stackPtr + ) { + return true; + } + } + return false; + } + + /** + * Is the current token inside a conditional? + * + * @param int $stackPtr The position in the stack where the token was found. + * + * @return bool + */ + private function isInsideIfConditonal( $stackPtr ) { + + if ( array_key_exists( 'conditions', $this->tokens[ $stackPtr ] ) === true + && is_array( $this->tokens[ $stackPtr ]['conditions'] ) === true + && empty( $this->tokens[ $stackPtr ]['conditions'] ) === false + ) { + $conditionStackPtrs = array_keys( $this->tokens[ $stackPtr ]['conditions'] ); + $lastConditionStackPtr = array_pop( $conditionStackPtrs ); + return $this->tokens[ $stackPtr ]['conditions'][ $lastConditionStackPtr ] === T_IF; + } + return false; + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Hooks/RestrictedHooksSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Hooks/RestrictedHooksSniff.php new file mode 100644 index 00000000..43054c2b --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Hooks/RestrictedHooksSniff.php @@ -0,0 +1,127 @@ + true, + 'add_action' => true, + ]; + + /** + * List of restricted filters by groups. + * + * @var array + */ + private $restricted_hook_groups = [ + 'upload_mimes' => [ + // TODO: This error message needs a link to the VIP Documentation, see https://github.com/Automattic/VIP-Coding-Standards/issues/235. + 'type' => 'Warning', + 'msg' => 'Please ensure that the mimes being filtered do not include insecure types (i.e. SVG, SWF, etc.). Manual inspection required.', + 'hooks' => [ + 'upload_mimes', + ], + ], + 'http_request' => [ + // https://docs.wpvip.com/technical-references/code-quality-and-best-practices/retrieving-remote-data/. + 'type' => 'Warning', + 'msg' => 'Please ensure that the timeout being filtered is not greater than 3s since remote requests require the user to wait for completion before the rest of the page will load. Manual inspection required.', + 'hooks' => [ + 'http_request_timeout', + 'http_request_args', + ], + ], + 'robotstxt' => [ + // https://docs.wpvip.com/how-tos/modify-the-robots-txt-file/. + 'type' => 'Warning', + 'msg' => 'Don\'t forget to flush the robots.txt cache by going to Settings > Reading and toggling the privacy settings.', + 'hooks' => [ + 'do_robotstxt', + 'robots_txt', + ], + ], + ]; + + /** + * Process the parameters of a matched function. + * + * @param int $stackPtr The position of the current token in the stack. + * @param array $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + foreach ( $this->restricted_hook_groups as $group => $group_args ) { + foreach ( $group_args['hooks'] as $hook ) { + if ( $this->normalize_hook_name_from_parameter( $parameters[1] ) === $hook ) { + $addMethod = 'add' . $group_args['type']; + $this->phpcsFile->{$addMethod}( $group_args['msg'], $stackPtr, $hook ); + } + } + } + } + + /** + * Normalize hook name parameter. + * + * @param array $parameter Array with information about a parameter. + * @return string Normalized hook name. + */ + private function normalize_hook_name_from_parameter( $parameter ) { + // If concatenation is found, build hook name. + $concat_ptr = $this->phpcsFile->findNext( + T_STRING_CONCAT, + $parameter['start'], + $parameter['end'], + false, + null, + true + ); + + if ( $concat_ptr ) { + $hook_name = ''; + for ( $i = $parameter['start'] + 1; $i < $parameter['end']; $i++ ) { + if ( $this->tokens[ $i ]['code'] === T_CONSTANT_ENCAPSED_STRING ) { + $hook_name .= str_replace( [ "'", '"' ], '', $this->tokens[ $i ]['content'] ); + } + } + } else { + $hook_name = $parameter['raw']; + } + + // Remove quotes (double and single), and use lowercase. + return strtolower( str_replace( [ "'", '"' ], '', $hook_name ) ); + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/DangerouslySetInnerHTMLSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/DangerouslySetInnerHTMLSniff.php new file mode 100644 index 00000000..9355756e --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/DangerouslySetInnerHTMLSniff.php @@ -0,0 +1,73 @@ +tokens[ $stackPtr ]['content'] !== 'dangerouslySetInnerHTML' ) { + // Looking for dangerouslySetInnerHTML only. + return; + } + + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true ); + + if ( $this->tokens[ $nextToken ]['code'] !== T_EQUAL ) { + // Not an assignment. + return; + } + + $nextNextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $nextToken + 1, null, true, null, true ); + + if ( $this->tokens[ $nextNextToken ]['code'] !== T_OBJECT ) { + // Not react syntax. + return; + } + + $message = "Any HTML passed to `%s` gets executed. Please make sure it's properly escaped."; + $data = [ $this->tokens[ $stackPtr ]['content'] ]; + $this->phpcsFile->addError( $message, $stackPtr, 'Found', $data ); + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/HTMLExecutingFunctionsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/HTMLExecutingFunctionsSniff.php new file mode 100644 index 00000000..66126d28 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/HTMLExecutingFunctionsSniff.php @@ -0,0 +1,134 @@ + content or target. + * Value indicates whether the function's arg is the content to be inserted, or the target where the inserted + * content is to be inserted before/after/replaced. For the latter, the content is in the preceding method's arg. + * + * @var array + */ + public $HTMLExecutingFunctions = [ + 'after' => 'content', // jQuery. + 'append' => 'content', // jQuery. + 'appendTo' => 'target', // jQuery. + 'before' => 'content', // jQuery. + 'html' => 'content', // jQuery. + 'insertAfter' => 'target', // jQuery. + 'insertBefore' => 'target', // jQuery. + 'prepend' => 'content', // jQuery. + 'prependTo' => 'target', // jQuery. + 'replaceAll' => 'target', // jQuery. + 'replaceWith' => 'content', // jQuery. + 'write' => 'content', + 'writeln' => 'content', + ]; + + /** + * A list of tokenizers this sniff supports. + * + * @var string[] + */ + public $supportedTokenizers = [ 'JS' ]; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return [ + T_STRING, + ]; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * + * @return void + */ + public function process_token( $stackPtr ) { + + if ( ! isset( $this->HTMLExecutingFunctions[ $this->tokens[ $stackPtr ]['content'] ] ) ) { + // Looking for specific functions only. + return; + } + + if ( $this->HTMLExecutingFunctions[ $this->tokens[ $stackPtr ]['content'] ] === 'content' ) { + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true ); + + if ( $this->tokens[ $nextToken ]['code'] !== T_OPEN_PARENTHESIS ) { + // Not a function. + return; + } + + $parenthesis_closer = $this->tokens[ $nextToken ]['parenthesis_closer']; + + while ( $nextToken < $parenthesis_closer ) { + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $nextToken + 1, null, true, null, true ); + if ( $this->tokens[ $nextToken ]['code'] === T_STRING ) { // Contains a variable, function call or something else dynamic. + $message = 'Any HTML passed to `%s` gets executed. Make sure it\'s properly escaped.'; + $data = [ $this->tokens[ $stackPtr ]['content'] ]; + $this->phpcsFile->addWarning( $message, $stackPtr, $this->tokens[ $stackPtr ]['content'], $data ); + + return; + } + } + } elseif ( $this->HTMLExecutingFunctions[ $this->tokens[ $stackPtr ]['content'] ] === 'target' ) { + $prevToken = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $stackPtr - 1, null, true, null, true ); + + if ( $this->tokens[ $prevToken ]['code'] !== T_OBJECT_OPERATOR ) { + return; + } + + $prevPrevToken = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $prevToken - 1, null, true, null, true ); + + if ( $this->tokens[ $prevPrevToken ]['code'] !== T_CLOSE_PARENTHESIS ) { + // Not a function call, but may be a variable containing an element reference, so just + // flag all remaining instances of these target HTML executing functions. + $message = 'Any HTML used with `%s` gets executed. Make sure it\'s properly escaped.'; + $data = [ $this->tokens[ $stackPtr ]['content'] ]; + $this->phpcsFile->addWarning( $message, $stackPtr, $this->tokens[ $stackPtr ]['content'], $data ); + + return; + } + + // Check if it's a function call (typically $() ) that contains a dynamic part. + $parenthesis_opener = $this->tokens[ $prevPrevToken ]['parenthesis_opener']; + + while ( $prevPrevToken > $parenthesis_opener ) { + $prevPrevToken = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $prevPrevToken - 1, null, true, null, true ); + if ( $this->tokens[ $prevPrevToken ]['code'] === T_STRING ) { // Contains a variable, function call or something else dynamic. + $message = 'Any HTML used with `%s` gets executed. Make sure it\'s properly escaped.'; + $data = [ $this->tokens[ $stackPtr ]['content'] ]; + $this->phpcsFile->addWarning( $message, $stackPtr, $this->tokens[ $stackPtr ]['content'], $data ); + + return; + } + } + } + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/InnerHTMLSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/InnerHTMLSniff.php new file mode 100644 index 00000000..aac49116 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/InnerHTMLSniff.php @@ -0,0 +1,87 @@ +tokens[ $stackPtr ]['content'] !== 'innerHTML' ) { + // Looking for .innerHTML only. + return; + } + + $prevToken = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $stackPtr - 1, null, true, null, true ); + + if ( $this->tokens[ $prevToken ]['code'] !== T_OBJECT_OPERATOR ) { + return; + } + + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true ); + + if ( $this->tokens[ $nextToken ]['code'] !== T_EQUAL ) { + // Not an assignment. + return; + } + + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $nextToken + 1, null, true, null, true ); + $foundVariable = false; + + while ( $nextToken !== false && $this->tokens[ $nextToken ]['code'] !== T_SEMICOLON ) { + + if ( $this->tokens[ $nextToken ]['code'] === T_STRING ) { + $foundVariable = true; + break; + } + + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $nextToken + 1, null, true, null, true ); + } + + if ( $foundVariable === true ) { + $message = 'Any HTML passed to `%s` gets executed. Consider using `.textContent` or make sure that used variables are properly escaped.'; + $data = [ $this->tokens[ $stackPtr ]['content'] ]; + $this->phpcsFile->addWarning( $message, $stackPtr, 'Found', $data ); + } + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/StringConcatSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/StringConcatSniff.php new file mode 100644 index 00000000..74fab5fc --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/StringConcatSniff.php @@ -0,0 +1,76 @@ +phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true ); + + if ( $this->tokens[ $nextToken ]['code'] === T_CONSTANT_ENCAPSED_STRING && strpos( $this->tokens[ $nextToken ]['content'], '<' ) !== false && preg_match( '/\<\/[a-zA-Z]+/', $this->tokens[ $nextToken ]['content'] ) === 1 ) { + $data = [ '+' . $this->tokens[ $nextToken ]['content'] ]; + $this->addFoundError( $stackPtr, $data ); + } + + $prevToken = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $stackPtr - 1, null, true, null, true ); + + if ( $this->tokens[ $prevToken ]['code'] === T_CONSTANT_ENCAPSED_STRING && strpos( $this->tokens[ $prevToken ]['content'], '<' ) !== false && preg_match( '/\<[a-zA-Z]+/', $this->tokens[ $prevToken ]['content'] ) === 1 ) { + $data = [ $this->tokens[ $nextToken ]['content'] . '+' ]; + $this->addFoundError( $stackPtr, $data ); + } + } + + /** + * Consolidated violation. + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * @param array $data Replacements for the error message. + */ + private function addFoundError( $stackPtr, array $data ) { + $message = 'HTML string concatenation detected, this is a security risk, use DOM node construction or a templating language instead: %s.'; + $this->phpcsFile->addError( $message, $stackPtr, 'Found', $data ); + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/StrippingTagsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/StrippingTagsSniff.php new file mode 100644 index 00000000..8017fe58 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/StrippingTagsSniff.php @@ -0,0 +1,76 @@ +tokens[ $stackPtr ]['content'] !== 'html' ) { + // Looking for html() only. + return; + } + + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true ); + + if ( $this->tokens[ $nextToken ]['code'] !== T_OPEN_PARENTHESIS ) { + // Not a function. + return; + } + + $afterFunctionCall = $this->phpcsFile->findNext( Tokens::$emptyTokens, $this->tokens[ $nextToken ]['parenthesis_closer'] + 1, null, true, null, true ); + + if ( $this->tokens[ $afterFunctionCall ]['code'] !== T_OBJECT_OPERATOR ) { + return; + } + + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $afterFunctionCall + 1, null, true, null, true ); + + if ( $this->tokens[ $nextToken ]['code'] === T_STRING && $this->tokens[ $nextToken ]['content'] === 'text' ) { + $message = 'Vulnerable tag stripping approach detected.'; + $this->phpcsFile->addError( $message, $stackPtr, 'VulnerableTagStripping' ); + } + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/WindowSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/WindowSniff.php new file mode 100644 index 00000000..e233e479 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/JS/WindowSniff.php @@ -0,0 +1,131 @@ + [ + 'href' => true, + 'protocol' => true, + 'host' => true, + 'hostname' => true, + 'pathname' => true, + 'search' => true, + 'hash' => true, + 'username' => true, + 'port' => true, + 'password' => true, + ], + 'name' => true, + 'status' => true, + ]; + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * + * @return void + */ + public function process_token( $stackPtr ) { + + if ( $this->tokens[ $stackPtr ]['content'] !== 'window' ) { + // Doesn't begin with 'window', bail. + return; + } + + $nextTokenPtr = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true ); + $nextToken = $this->tokens[ $nextTokenPtr ]['code']; + if ( $nextToken !== T_OBJECT_OPERATOR && $nextToken !== T_OPEN_SQUARE_BRACKET ) { + // No . or [' next, bail. + return; + } + + $nextNextTokenPtr = $this->phpcsFile->findNext( Tokens::$emptyTokens, $nextTokenPtr + 1, null, true, null, true ); + if ( $nextNextTokenPtr === false ) { + // Something went wrong, bail. + return; + } + + $nextNextToken = str_replace( [ '"', "'" ], '', $this->tokens[ $nextNextTokenPtr ]['content'] ); + if ( ! isset( $this->windowProperties[ $nextNextToken ] ) ) { + // Not in $windowProperties, bail. + return; + } + + $nextNextNextTokenPtr = $this->phpcsFile->findNext( array_merge( [ T_CLOSE_SQUARE_BRACKET ], Tokens::$emptyTokens ), $nextNextTokenPtr + 1, null, true, null, true ); + $nextNextNextToken = $this->tokens[ $nextNextNextTokenPtr ]['code']; + + $nextNextNextNextToken = false; + if ( $nextNextNextToken === T_OBJECT_OPERATOR || $nextNextNextToken === T_OPEN_SQUARE_BRACKET ) { + $nextNextNextNextTokenPtr = $this->phpcsFile->findNext( Tokens::$emptyTokens, $nextNextNextTokenPtr + 1, null, true, null, true ); + if ( $nextNextNextNextTokenPtr === false ) { + // Something went wrong, bail. + return; + } + + $nextNextNextNextToken = str_replace( [ '"', "'" ], '', $this->tokens[ $nextNextNextNextTokenPtr ]['content'] ); + if ( ! isset( $this->windowProperties[ $nextNextToken ][ $nextNextNextNextToken ] ) ) { + // Not in $windowProperties, bail. + return; + } + } + + $windowProperty = 'window.'; + $windowProperty .= $nextNextNextNextToken ? $nextNextToken . '.' . $nextNextNextNextToken : $nextNextToken; + $data = [ $windowProperty ]; + + $prevTokenPtr = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, $stackPtr - 1, null, true, null, true ); + + if ( $this->tokens[ $prevTokenPtr ]['code'] === T_EQUAL ) { + // Variable assignment. + $message = 'Data from JS global "%s" may contain user-supplied values and should be checked.'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'VarAssignment', $data ); + + return; + } + + $message = 'Data from JS global "%s" may contain user-supplied values and should be sanitized before output to prevent XSS.'; + $this->phpcsFile->addError( $message, $stackPtr, $nextNextToken, $data ); + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/BatcacheWhitelistedParamsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/BatcacheWhitelistedParamsSniff.php new file mode 100644 index 00000000..1b42498b --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/BatcacheWhitelistedParamsSniff.php @@ -0,0 +1,113 @@ +tokens[ $stackPtr ]['content'] !== '$_GET' ) { + return; + } + + $key = $this->phpcsFile->findNext( array_merge( Tokens::$emptyTokens, [ T_OPEN_SQUARE_BRACKET ] ), $stackPtr + 1, null, true ); + + if ( $this->tokens[ $key ]['code'] !== T_CONSTANT_ENCAPSED_STRING ) { + return; + } + + $variable_name = $this->tokens[ $key ]['content']; + + $variable_name = substr( $variable_name, 1, -1 ); + + if ( in_array( $variable_name, $this->whitelistes_batcache_params, true ) === true ) { + $message = 'Batcache whitelisted GET param, `%s`, found. Batcache whitelisted parameters get stripped and are not available in PHP.'; + $data = [ $variable_name ]; + $this->phpcsFile->addWarning( $message, $stackPtr, 'StrippedGetParam', $data ); + + return; + } + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/CacheValueOverrideSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/CacheValueOverrideSniff.php new file mode 100644 index 00000000..806bebef --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/CacheValueOverrideSniff.php @@ -0,0 +1,146 @@ + + * echo esc_url( wpcom_vip_get_term_link( $term ) ); + * + * + * @package VIPCS\WordPressVIPMinimum + */ +class CacheValueOverrideSniff extends Sniff { + + /** + * Returns the token types that this sniff is interested in. + * + * @return array(int) + */ + public function register() { + return [ T_STRING ]; + } + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param int $stackPtr The position in the stack where the token was found. + * + * @return void + */ + public function process_token( $stackPtr ) { + + $functionName = $this->tokens[ $stackPtr ]['content']; + + if ( $functionName !== 'wp_cache_get' ) { + // Not a function we are looking for. + return; + } + + if ( $this->isFunctionCall( $stackPtr ) === false ) { + // Not a function call. + return; + } + + $variablePos = $this->isVariableAssignment( $stackPtr ); + + if ( $variablePos === false ) { + // Not a variable assignment. + return; + } + + $variableToken = $this->tokens[ $variablePos ]; + $variableName = $variableToken['content']; + + // Find the next non-empty token. + $openBracket = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true ); + + // Find the closing bracket. + $closeBracket = $this->tokens[ $openBracket ]['parenthesis_closer']; + + $nextVariableOccurrence = $this->phpcsFile->findNext( T_VARIABLE, $closeBracket + 1, null, false, $variableName ); + + $rightAfterNextVariableOccurence = $this->phpcsFile->findNext( Tokens::$emptyTokens, $nextVariableOccurrence + 1, null, true, null, true ); + + if ( $this->tokens[ $rightAfterNextVariableOccurence ]['code'] !== T_EQUAL ) { + // Not a value override. + return; + } + + $valueAfterEqualSign = $this->phpcsFile->findNext( Tokens::$emptyTokens, $rightAfterNextVariableOccurence + 1, null, true, null, true ); + + if ( $this->tokens[ $valueAfterEqualSign ]['code'] === T_FALSE ) { + $message = 'Obtained cached value in `%s` is being overridden. Disabling caching?'; + $data = [ $variableName ]; + $this->phpcsFile->addError( $message, $nextVariableOccurrence, 'CacheValueOverride', $data ); + } + } + + /** + * Check whether the examined code is a function call. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return bool + */ + private function isFunctionCall( $stackPtr ) { + + // Find the next non-empty token. + $openBracket = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true ); + + if ( $this->tokens[ $openBracket ]['code'] !== T_OPEN_PARENTHESIS ) { + // Not a function call. + return false; + } + + // Find the previous non-empty token. + $search = Tokens::$emptyTokens; + $search[] = T_BITWISE_AND; + $previous = $this->phpcsFile->findPrevious( $search, $stackPtr - 1, null, true ); + + // It's a function definition, not a function call, so return false. + return ! ( $this->tokens[ $previous ]['code'] === T_FUNCTION ); + } + + /** + * Check whether the examined code is a variable assignment. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return bool + */ + private function isVariableAssignment( $stackPtr ) { + + // Find the previous non-empty token. + $search = Tokens::$emptyTokens; + $search[] = T_BITWISE_AND; + $previous = $this->phpcsFile->findPrevious( $search, $stackPtr - 1, null, true ); + + if ( $this->tokens[ $previous ]['code'] !== T_EQUAL ) { + // It's not a variable assignment. + return false; + } + + $previous = $this->phpcsFile->findPrevious( $search, $previous - 1, null, true ); + + if ( $this->tokens[ $previous ]['code'] !== T_VARIABLE ) { + // It's not a variable assignment. + return false; + } + + return $previous; + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/FetchingRemoteDataSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/FetchingRemoteDataSniff.php new file mode 100644 index 00000000..e3fc4330 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/FetchingRemoteDataSniff.php @@ -0,0 +1,61 @@ +tokens[ $stackPtr ]['content']; + if ( $functionName !== 'file_get_contents' ) { + return; + } + + $data = [ $this->tokens[ $stackPtr ]['content'] ]; + + $fileNameStackPtr = $this->phpcsFile->findNext( Tokens::$stringTokens, $stackPtr + 1, null, false, null, true ); + if ( $fileNameStackPtr === false ) { + $message = '`%s()` is highly discouraged for remote requests, please use `wpcom_vip_file_get_contents()` or `vip_safe_wp_remote_get()` instead. If it\'s for a local file please use WP_Filesystem instead.'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'FileGetContentsUnknown', $data ); + } + + $fileName = $this->tokens[ $fileNameStackPtr ]['content']; + + $isRemoteFile = ( strpos( $fileName, '://' ) !== false ); + if ( $isRemoteFile === true ) { + $message = '`%s()` is highly discouraged for remote requests, please use `wpcom_vip_file_get_contents()` or `vip_safe_wp_remote_get()` instead.'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'FileGetContentsRemoteFile', $data ); + } + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/LowExpiryCacheTimeSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/LowExpiryCacheTimeSniff.php new file mode 100644 index 00000000..23639560 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/LowExpiryCacheTimeSniff.php @@ -0,0 +1,206 @@ + true, + 'wp_cache_add' => true, + 'wp_cache_replace' => true, + ]; + + /** + * List of WP time constants, see https://codex.wordpress.org/Easier_Expression_of_Time_Constants. + * + * @var array + */ + protected $wp_time_constants = [ + 'MINUTE_IN_SECONDS' => 60, + 'HOUR_IN_SECONDS' => 3600, + 'DAY_IN_SECONDS' => 86400, + 'WEEK_IN_SECONDS' => 604800, + 'MONTH_IN_SECONDS' => 2592000, + 'YEAR_IN_SECONDS' => 31536000, + ]; + + /** + * Process the parameters of a matched function. + * + * @param int $stackPtr The position of the current token in the stack. + * @param array $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + if ( isset( $parameters[4] ) === false ) { + // If no cache expiry time, bail (i.e. we don't want to flag for something like feeds where it is cached indefinitely until a hook runs). + return; + } + + $param = $parameters[4]; + $tokensAsString = ''; + $reportPtr = null; + $openParens = 0; + + $message = 'Cache expiry time could not be determined. Please inspect that the fourth parameter passed to %s() evaluates to 300 seconds or more. Found: "%s"'; + $error_code = 'CacheTimeUndetermined'; + $data = [ $matched_content, $parameters[4]['raw'] ]; + + for ( $i = $param['start']; $i <= $param['end']; $i++ ) { + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) === true ) { + $tokensAsString .= ' '; + continue; + } + + if ( $this->tokens[ $i ]['code'] === T_NS_SEPARATOR ) { + /* + * Ignore namespace separators. If it's part of a global WP time constant, it will be + * handled correctly. If it's used in any other context, another token *will* trigger the + * "undetermined" warning anyway. + */ + continue; + } + + if ( isset( $reportPtr ) === false ) { + // Set the report pointer to the first non-empty token we encounter. + $reportPtr = $i; + } + + if ( $this->tokens[ $i ]['code'] === T_LNUMBER + || $this->tokens[ $i ]['code'] === T_DNUMBER + ) { + // Integer or float. + $tokensAsString .= $this->tokens[ $i ]['content']; + continue; + } + + if ( $this->tokens[ $i ]['code'] === T_FALSE + || $this->tokens[ $i ]['code'] === T_NULL + ) { + $tokensAsString .= 0; + continue; + } + + if ( $this->tokens[ $i ]['code'] === T_TRUE ) { + $tokensAsString .= 1; + continue; + } + + if ( isset( Tokens::$arithmeticTokens[ $this->tokens[ $i ]['code'] ] ) === true ) { + $tokensAsString .= $this->tokens[ $i ]['content']; + continue; + } + + // If using time constants, we need to convert to a number. + if ( $this->tokens[ $i ]['code'] === T_STRING + && isset( $this->wp_time_constants[ $this->tokens[ $i ]['content'] ] ) === true + ) { + $tokensAsString .= $this->wp_time_constants[ $this->tokens[ $i ]['content'] ]; + continue; + } + + if ( $this->tokens[ $i ]['code'] === T_OPEN_PARENTHESIS ) { + $tokensAsString .= $this->tokens[ $i ]['content']; + ++$openParens; + continue; + } + + if ( $this->tokens[ $i ]['code'] === T_CLOSE_PARENTHESIS ) { + $tokensAsString .= $this->tokens[ $i ]['content']; + --$openParens; + continue; + } + + if ( $this->tokens[ $i ]['code'] === T_CONSTANT_ENCAPSED_STRING ) { + $content = $this->strip_quotes( $this->tokens[ $i ]['content'] ); + if ( is_numeric( $content ) === true ) { + $tokensAsString .= $content; + continue; + } + } + + // Encountered an unexpected token. Manual inspection needed. + $this->phpcsFile->addWarning( $message, $reportPtr, $error_code, $data ); + + return; + } + + if ( $tokensAsString === '' ) { + // Nothing found to evaluate. + return; + } + + $tokensAsString = trim( $tokensAsString ); + + if ( $openParens !== 0 ) { + /* + * Shouldn't be possible as that would indicate a parse error in the original code, + * but let's prevent getting parse errors in the `eval`-ed code. + */ + if ( $openParens > 0 ) { + $tokensAsString .= str_repeat( ')', $openParens ); + } else { + $tokensAsString = str_repeat( '(', abs( $openParens ) ) . $tokensAsString; + } + } + + $time = @eval( "return $tokensAsString;" ); // phpcs:ignore Squiz.PHP.Eval,WordPress.PHP.NoSilencedErrors -- No harm here. + + if ( $time === false ) { + /* + * The eval resulted in a parse error. This will only happen for backfilled + * arithmetic operator tokens, like T_POW, on PHP versions in which the token + * did not exist. In that case, flag for manual inspection. + */ + $this->phpcsFile->addWarning( $message, $reportPtr, $error_code, $data ); + return; + } + + if ( $time < 300 && (int) $time !== 0 ) { + $message = 'Low cache expiry time of %s seconds detected. It is recommended to have 300 seconds or more.'; + $data = [ $time ]; + + if ( (string) $time !== $tokensAsString ) { + $message .= ' Found: "%s"'; + $data[] = $tokensAsString; + } + + $this->phpcsFile->addWarning( $message, $reportPtr, 'LowCacheTime', $data ); + } + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/NoPagingSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/NoPagingSniff.php new file mode 100644 index 00000000..9e23fc4f --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/NoPagingSniff.php @@ -0,0 +1,61 @@ + [ + 'type' => 'error', + 'keys' => [ + 'nopaging', + ], + ], + ]; + } + + /** + * Callback to process each confirmed key, to check value. + * + * @param string $key Array index / key. + * @param mixed $val Assigned value. + * @param int $line Token line. + * @param array $group Group definition. + * @return mixed FALSE if no match, TRUE if matches, STRING if matches + * with custom error message passed to ->process(). + */ + public function callback( $key, $val, $line, $group ) { + $key = strtolower( $key ); + + if ( $key === 'nopaging' && ( $val === 'true' || $val === 1 ) ) { + return 'Disabling pagination is prohibited in VIP context, do not set `%s` to `%s` ever.'; + } + + return false; + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/OrderByRandSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/OrderByRandSniff.php new file mode 100644 index 00000000..e6e64c6f --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/OrderByRandSniff.php @@ -0,0 +1,59 @@ + rand. + * + * @link https://docs.wpvip.com/technical-references/code-review/#order-by-rand + * + * @package VIPCS\WordPressVIPMinimum + * + * @since 0.5.0 + */ +class OrderByRandSniff extends AbstractArrayAssignmentRestrictionsSniff { + + /** + * Groups of variables to restrict. + * + * @return array + */ + public function getGroups() { + return [ + 'orderby' => [ + 'type' => 'error', + 'keys' => [ + 'orderby', + ], + ], + ]; + } + + /** + * Callback to process each confirmed key, to check value + * This must be extended to add the logic to check assignment value + * + * @param string $key Array index / key. + * @param mixed $val Assigned value. + * @param int $line Token line. + * @param array $group Group definition. + * @return mixed FALSE if no match, TRUE if matches, STRING if matches with custom error message passed to ->process(). + */ + public function callback( $key, $val, $line, $group ) { + if ( strtolower( $val ) === 'rand' ) { + return 'Detected forbidden query_var "%s" of "%s". Use vip_get_random_posts() instead.'; + } + + return false; + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/RegexpCompareSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/RegexpCompareSniff.php new file mode 100644 index 00000000..dea5fd5f --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/RegexpCompareSniff.php @@ -0,0 +1,65 @@ + array( + * 'groupname' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Dont use this one please!', + * 'keys' => array( 'key1', 'another_key' ), + * 'callback' => array( 'class', 'method' ), // Optional. + * ) + * ) + * + * @return array + */ + public function getGroups() { + return [ + 'compare' => [ + 'type' => 'error', + 'keys' => [ + 'compare', + 'meta_compare', + ], + ], + ]; + } + + /** + * Callback to process each confirmed key, to check value. + * This must be extended to add the logic to check assignment value. + * + * @param string $key Array index / key. + * @param mixed $val Assigned value. + * @param int $line Token line. + * @param array $group Group definition. + * @return mixed FALSE if no match, TRUE if matches, STRING if matches + * with custom error message passed to ->process(). + */ + public function callback( $key, $val, $line, $group ) { + if ( strpos( $val, 'NOT REGEXP' ) === 0 + || strpos( $val, 'REGEXP' ) === 0 + || in_array( $val, [ 'REGEXP', 'NOT REGEXP' ], true ) === true + ) { + return 'Detected regular expression comparison. `%s` is set to `%s`.'; + } + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/RemoteRequestTimeoutSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/RemoteRequestTimeoutSniff.php new file mode 100644 index 00000000..974532f4 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/RemoteRequestTimeoutSniff.php @@ -0,0 +1,61 @@ + array( + * 'groupname' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Dont use this one please!', + * 'keys' => array( 'key1', 'another_key' ), + * 'callback' => array( 'class', 'method' ), // Optional. + * ) + * ) + * + * @return array + */ + public function getGroups() { + return [ + 'timeout' => [ + 'type' => 'error', + 'keys' => [ + 'timeout', + ], + ], + ]; + } + + /** + * Callback to process each confirmed key, to check value. + * This must be extended to add the logic to check assignment value. + * + * @param string $key Array index / key. + * @param mixed $val Assigned value. + * @param int $line Token line. + * @param array $group Group definition. + * @return mixed FALSE if no match, TRUE if matches, STRING if matches + * with custom error message passed to ->process(). + */ + public function callback( $key, $val, $line, $group ) { + if ( (int) $val > 3 ) { + return 'Detected high remote request timeout. `%s` is set to `%d`.'; + } + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/TaxonomyMetaInOptionsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/TaxonomyMetaInOptionsSniff.php new file mode 100644 index 00000000..c9c815be --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/TaxonomyMetaInOptionsSniff.php @@ -0,0 +1,134 @@ +tokens[ $stackPtr ]['content'], $this->option_functions, true ) === false ) { + return; + } + + $openBracket = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true ); + + if ( $this->tokens[ $openBracket ]['code'] !== T_OPEN_PARENTHESIS ) { + return; + } + + $param_ptr = $this->phpcsFile->findNext( Tokens::$emptyTokens, $openBracket + 1, null, true ); + + if ( $this->tokens[ $param_ptr ]['code'] === T_DOUBLE_QUOTED_STRING ) { + foreach ( $this->taxonomy_term_patterns as $taxonomy_term_pattern ) { + if ( strpos( $this->tokens[ $param_ptr ]['content'], $taxonomy_term_pattern ) !== false ) { + $this->addPossibleTermMetaInOptionsWarning( $stackPtr ); + return; + } + } + } elseif ( $this->tokens[ $param_ptr ]['code'] === T_CONSTANT_ENCAPSED_STRING ) { + + $string_concat = $this->phpcsFile->findNext( Tokens::$emptyTokens, $param_ptr + 1, null, true ); + if ( $this->tokens[ $string_concat ]['code'] !== T_STRING_CONCAT ) { + return; + } + + $variable_name = $this->phpcsFile->findNext( Tokens::$emptyTokens, $string_concat + 1, null, true ); + if ( $this->tokens[ $variable_name ]['code'] !== T_VARIABLE ) { + return; + } + + foreach ( $this->taxonomy_term_patterns as $taxonomy_term_pattern ) { + if ( strpos( $this->tokens[ $variable_name ]['content'], $taxonomy_term_pattern ) !== false ) { + $this->addPossibleTermMetaInOptionsWarning( $stackPtr ); + return; + } + } + + $object_operator = $this->phpcsFile->findNext( Tokens::$emptyTokens, $variable_name + 1, null, true ); + if ( $this->tokens[ $object_operator ]['code'] !== T_OBJECT_OPERATOR ) { + return; + } + + $object_property = $this->phpcsFile->findNext( Tokens::$emptyTokens, $object_operator + 1, null, true ); + if ( $this->tokens[ $object_property ]['code'] !== T_STRING ) { + return; + } + + foreach ( $this->taxonomy_term_patterns as $taxonomy_term_pattern ) { + if ( strpos( $this->tokens[ $object_property ]['content'], $taxonomy_term_pattern ) !== false ) { + $this->addPossibleTermMetaInOptionsWarning( $stackPtr ); + return; + } + } + } + } + + /** + * Helper method for composing the Warning for all possible cases. + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * + * @return void + */ + public function addPossibleTermMetaInOptionsWarning( $stackPtr ) { + $message = 'Possible detection of storing taxonomy term meta in options table. Needs manual inspection. All such data should be stored in term_meta.'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'PossibleTermMetaInOptions' ); + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/WPQueryParamsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/WPQueryParamsSniff.php new file mode 100644 index 00000000..9b15ef63 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Performance/WPQueryParamsSniff.php @@ -0,0 +1,104 @@ + array( + * 'groupname' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Dont use this one please!', + * 'keys' => array( 'key1', 'another_key' ), + * 'callback' => array( 'class', 'method' ), // Optional. + * ) + * ) + * + * @return array + */ + public function getGroups() { + return [ + 'PostNotIn' => [ + 'type' => 'warning', + 'message' => 'Using `exclude`, which is subsequently used by `post__not_in`, should be done with caution, see https://docs.wpvip.com/how-tos/improve-performance-by-removing-usage-of-post__not_in/ for more information.', + 'keys' => [ + 'exclude', + ], + ], + ]; + } + + /** + * Process this test when one of its tokens is encountered + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * + * @return void + */ + public function process_token( $stackPtr ) { + + if ( trim( $this->tokens[ $stackPtr ]['content'], '\'' ) === 'suppress_filters' ) { + + $next_token = $this->phpcsFile->findNext( array_merge( Tokens::$emptyTokens, [ T_EQUAL, T_CLOSE_SQUARE_BRACKET, T_DOUBLE_ARROW ] ), $stackPtr + 1, null, true ); + + if ( $this->tokens[ $next_token ]['code'] === T_TRUE ) { + // https://docs.wpvip.com/technical-references/caching/uncached-functions/. + $message = 'Setting `suppress_filters` to `true` is prohibited.'; + $this->phpcsFile->addError( $message, $stackPtr, 'SuppressFiltersTrue' ); + } + } + + if ( trim( $this->tokens[ $stackPtr ]['content'], '\'' ) === 'post__not_in' ) { + $message = 'Using `post__not_in` should be done with caution, see https://docs.wpvip.com/how-tos/improve-performance-by-removing-usage-of-post__not_in/ for more information.'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'PostNotIn' ); + } + + parent::process_token( $stackPtr ); + } + + /** + * Callback to process a confirmed key which doesn't need custom logic, but should always error. + * + * @param string $key Array index / key. + * @param mixed $val Assigned value. + * @param int $line Token line. + * @param array $group Group definition. + * @return mixed FALSE if no match, TRUE if matches, STRING if matches + * with custom error message passed to ->process(). + */ + public function callback( $key, $val, $line, $group ) { + return true; + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/EscapingVoidReturnFunctionsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/EscapingVoidReturnFunctionsSniff.php new file mode 100644 index 00000000..5c7f4e72 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/EscapingVoidReturnFunctionsSniff.php @@ -0,0 +1,70 @@ +tokens[ $stackPtr ]['content'], 'esc_' ) !== 0 && strpos( $this->tokens[ $stackPtr ]['content'], 'wp_kses' ) !== 0 ) { + // Not what we are looking for. + return; + } + + $next_token = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true ); + + if ( $this->tokens[ $next_token ]['code'] !== T_OPEN_PARENTHESIS ) { + // Not a function call. + return; + } + + $next_token = $this->phpcsFile->findNext( Tokens::$emptyTokens, $next_token + 1, null, true ); + + if ( $this->tokens[ $next_token ]['code'] !== T_STRING ) { + // Not what we are looking for. + return; + } + + if ( isset( $this->printingFunctions[ $this->tokens[ $next_token ]['content'] ] ) ) { + $message = 'Attempting to escape `%s()` which is printing its output.'; + $data = [ $this->tokens[ $next_token ]['content'] ]; + $this->phpcsFile->addError( $message, $stackPtr, 'Found', $data ); + return; + } + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/ExitAfterRedirectSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/ExitAfterRedirectSniff.php new file mode 100644 index 00000000..dfacc425 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/ExitAfterRedirectSniff.php @@ -0,0 +1,68 @@ +tokens[ $stackPtr ]['content'] !== 'wp_redirect' && $this->tokens[ $stackPtr ]['content'] !== 'wp_safe_redirect' ) { + return; + } + + $openBracket = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true ); + + if ( $this->tokens[ $openBracket ]['code'] !== T_OPEN_PARENTHESIS ) { + return; + } + + $next_token = $this->phpcsFile->findNext( array_merge( Tokens::$emptyTokens, [ T_SEMICOLON, T_CLOSE_PARENTHESIS ] ), $this->tokens[ $openBracket ]['parenthesis_closer'] + 1, null, true ); + + $message = '`%s()` should almost always be followed by a call to `exit;`.'; + $data = [ $this->tokens[ $stackPtr ]['content'] ]; + + if ( $this->tokens[ $next_token ]['code'] === T_OPEN_CURLY_BRACKET ) { + $is_exit_in_scope = false; + for ( $i = $this->tokens[ $next_token ]['scope_opener']; $i <= $this->tokens[ $next_token ]['scope_closer']; $i++ ) { + if ( $this->tokens[ $i ]['code'] === T_EXIT ) { + $is_exit_in_scope = true; + } + } + if ( $is_exit_in_scope === false ) { + $this->phpcsFile->addError( $message, $stackPtr, 'NoExitInConditional', $data ); + } + } elseif ( $this->tokens[ $next_token ]['code'] !== T_EXIT ) { + $this->phpcsFile->addError( $message, $stackPtr, 'NoExit', $data ); + } + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/MustacheSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/MustacheSniff.php new file mode 100644 index 00000000..c6465c2d --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/MustacheSniff.php @@ -0,0 +1,77 @@ +tokens[ $stackPtr ]['content'], '{{{' ) !== false || strpos( $this->tokens[ $stackPtr ]['content'], '}}}' ) !== false ) { + // Mustache unescaped output notation. + $message = 'Found Mustache unescaped output notation: "{{{}}}".'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'OutputNotation' ); + } + + if ( strpos( $this->tokens[ $stackPtr ]['content'], '{{&' ) !== false ) { + // Mustache unescaped variable notation. + $message = 'Found Mustache unescape variable notation: "{{&".'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'VariableNotation' ); + } + + if ( strpos( $this->tokens[ $stackPtr ]['content'], '{{=' ) !== false ) { + // Mustache delimiter change. + $new_delimiter = trim( str_replace( [ '{{=', '=}}' ], '', substr( $this->tokens[ $stackPtr ]['content'], 0, strpos( $this->tokens[ $stackPtr ]['content'], '=}}' ) + 3 ) ) ); + $message = 'Found Mustache delimiter change notation. New delimiter is: %s.'; + $data = [ $new_delimiter ]; + $this->phpcsFile->addWarning( $message, $stackPtr, 'DelimiterChange', $data ); + } + + if ( strpos( $this->tokens[ $stackPtr ]['content'], 'SafeString' ) !== false ) { + // Handlebars.js Handlebars.SafeString does not get escaped. + $message = 'Found Handlebars.SafeString call which does not get escaped.'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'SafeString' ); + } + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/PHPFilterFunctionsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/PHPFilterFunctionsSniff.php new file mode 100644 index 00000000..84278541 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/PHPFilterFunctionsSniff.php @@ -0,0 +1,90 @@ + true, + 'filter_input' => true, + 'filter_var_array' => true, + 'filter_input_array' => true, + ]; + + /** + * List of restricted filter names. + * + * @var array + */ + private $restricted_filters = [ + 'FILTER_DEFAULT' => true, + 'FILTER_UNSAFE_RAW' => true, + ]; + + /** + * Process the parameters of a matched function. + * + * @param int $stackPtr The position of the current token in the stack. + * @param array $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + if ( $matched_content === 'filter_input' ) { + if ( count( $parameters ) === 2 ) { + $message = 'Missing third parameter for "%s".'; + $data = [ $matched_content ]; + $this->phpcsFile->addWarning( $message, $stackPtr, 'MissingThirdParameter', $data ); + } + + if ( isset( $parameters[3], $this->restricted_filters[ $parameters[3]['raw'] ] ) ) { + $message = 'Please use an appropriate filter to sanitize, as "%s" does no filtering, see: http://php.net/manual/en/filter.filters.sanitize.php.'; + $data = [ strtoupper( $parameters[3]['raw'] ) ]; + $this->phpcsFile->addWarning( $message, $stackPtr, 'RestrictedFilter', $data ); + } + } else { + if ( count( $parameters ) === 1 ) { + $message = 'Missing second parameter for "%s".'; + $data = [ $matched_content ]; + $this->phpcsFile->addWarning( $message, $stackPtr, 'MissingSecondParameter', $data ); + } + + if ( isset( $parameters[2], $this->restricted_filters[ $parameters[2]['raw'] ] ) ) { + $message = 'Please use an appropriate filter to sanitize, as "%s" does no filtering, see http://php.net/manual/en/filter.filters.sanitize.php.'; + $data = [ strtoupper( $parameters[2]['raw'] ) ]; + $this->phpcsFile->addWarning( $message, $stackPtr, 'RestrictedFilter', $data ); + } + } + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php new file mode 100644 index 00000000..9b9513f0 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/ProperEscapingFunctionSniff.php @@ -0,0 +1,277 @@ +href|src|url|(^|\s+)action)?(?<=[a-z0-9_-])=(?:\\\\)?["\']*$`i'; + + /** + * List of escaping functions which are being tested. + * + * @var array + */ + protected $escaping_functions = [ + 'esc_url' => 'url', + 'esc_attr' => 'attr', + 'esc_attr__' => 'attr', + 'esc_attr_x' => 'attr', + 'esc_attr_e' => 'attr', + 'esc_html' => 'html', + 'esc_html__' => 'html', + 'esc_html_x' => 'html', + 'esc_html_e' => 'html', + ]; + + /** + * List of tokens we can skip. + * + * @var array + */ + private $echo_or_concat_tokens = + [ + T_ECHO => T_ECHO, + T_OPEN_TAG => T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO => T_OPEN_TAG_WITH_ECHO, + T_STRING_CONCAT => T_STRING_CONCAT, + T_NS_SEPARATOR => T_NS_SEPARATOR, + ]; + + /** + * List of attributes associated with url outputs. + * + * @deprecated 2.3.1 Currently unused by the sniff, but needed for + * for public methods which extending sniffs may be + * relying on. + * + * @var array + */ + private $url_attrs = [ + 'href', + 'src', + 'url', + 'action', + ]; + + /** + * List of syntaxes for inside attribute detection. + * + * @deprecated 2.3.1 Currently unused by the sniff, but needed for + * for public methods which extending sniffs may be + * relying on. + * + * @var array + */ + private $attr_endings = [ + '=', + '="', + "='", + "=\\'", + '=\\"', + ]; + + /** + * Keep track of whether or not we're currently in the first statement of a short open echo tag. + * + * @var int|false Integer stack pointer to the end of the first statement in the current + * short open echo tag or false when not in a short open echo tag. + */ + private $in_short_echo = false; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + $this->echo_or_concat_tokens += Tokens::$emptyTokens; + + return [ + T_STRING, + T_OPEN_TAG_WITH_ECHO, + ]; + } + + /** + * Process this test when one of its tokens is encountered + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * + * @return void + */ + public function process_token( $stackPtr ) { + /* + * Short open echo tags will act as an echo for the first expression and + * allow for passing multiple comma-separated parameters. + * However, short open echo tags also allow for additional statements after, but + * those have to be full PHP statements, not expressions. + * + * This snippet of code will keep track of whether or not we're in the first + * expression in a short open echo tag. + * $phpcsFile->findStartOfStatement() unfortunately is useless, as it will return + * the first token in the statement, which can be anything - variable, text string - + * without any indication of whether this is the start of a normal statement or + * a short open echo expression. + * So, if we used that, we'd need to walk back from every start of statement to + * the previous non-empty to see if it is the short open echo tag. + */ + if ( $this->tokens[ $stackPtr ]['code'] === T_OPEN_TAG_WITH_ECHO ) { + $end_of_echo = $this->phpcsFile->findNext( [ T_SEMICOLON, T_CLOSE_TAG ], ( $stackPtr + 1 ) ); + if ( $end_of_echo === false ) { + $this->in_short_echo = $this->phpcsFile->numTokens; + } else { + $this->in_short_echo = $end_of_echo; + } + + return; + } + + if ( $this->in_short_echo !== false && $this->in_short_echo < $stackPtr ) { + $this->in_short_echo = false; + } + + $function_name = strtolower( $this->tokens[ $stackPtr ]['content'] ); + + if ( isset( $this->escaping_functions[ $function_name ] ) === false ) { + return; + } + + $next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + if ( $next_non_empty === false || $this->tokens[ $next_non_empty ]['code'] !== T_OPEN_PARENTHESIS ) { + // Not a function call. + return; + } + + $ignore = $this->echo_or_concat_tokens; + if ( $this->in_short_echo !== false ) { + $ignore[ T_COMMA ] = T_COMMA; + } else { + $start_of_statement = $this->phpcsFile->findStartOfStatement( $stackPtr, T_COMMA ); + if ( $this->tokens[ $start_of_statement ]['code'] === T_ECHO ) { + $ignore[ T_COMMA ] = T_COMMA; + } + } + + $html = $this->phpcsFile->findPrevious( $ignore, $stackPtr - 1, null, true ); + + // Use $textStringTokens b/c heredoc and nowdoc tokens will never be encountered in this context anyways.. + if ( $html === false || isset( Tokens::$textStringTokens[ $this->tokens[ $html ]['code'] ] ) === false ) { + return; + } + + $data = [ $function_name ]; + + $content = $this->tokens[ $html ]['content']; + if ( isset( Tokens::$stringTokens[ $this->tokens[ $html ]['code'] ] ) === true ) { + $content = Sniff::strip_quotes( $content ); + } + + $escaping_type = $this->escaping_functions[ $function_name ]; + + if ( $escaping_type === 'attr' && $this->is_outside_html_attr_context( $content ) ) { + $message = 'Wrong escaping function, using `%s()` in a context outside of HTML attributes may not escape properly.'; + $this->phpcsFile->addError( $message, $html, 'notAttrEscAttr', $data ); + return; + } + + if ( preg_match( self::ATTR_END_REGEX, $content, $matches ) !== 1 ) { + return; + } + + if ( $escaping_type !== 'url' && empty( $matches['attrname'] ) === false ) { + $message = 'Wrong escaping function. href, src, and action attributes should be escaped by `esc_url()`, not by `%s()`.'; + $this->phpcsFile->addError( $message, $stackPtr, 'hrefSrcEscUrl', $data ); + return; + } + + if ( $escaping_type === 'html' ) { + $message = 'Wrong escaping function. HTML attributes should be escaped by `esc_attr()`, not by `%s()`.'; + $this->phpcsFile->addError( $message, $stackPtr, 'htmlAttrNotByEscHTML', $data ); + return; + } + } + + /** + * Tests whether provided string ends with open attribute which expects a URL value. + * + * @deprecated 2.3.1 + * + * @param string $content Haystack in which we look for an open attribute which exects a URL value. + * + * @return bool True if string ends with open attribute which expects a URL value. + */ + public function attr_expects_url( $content ) { + $attr_expects_url = false; + foreach ( $this->url_attrs as $attr ) { + foreach ( $this->attr_endings as $ending ) { + if ( $this->endswith( $content, $attr . $ending ) === true ) { + $attr_expects_url = true; + break; + } + } + } + return $attr_expects_url; + } + + /** + * Tests whether provided string ends with open HMTL attribute. + * + * @deprecated 2.3.1 + * + * @param string $content Haystack in which we look for open HTML attribute. + * + * @return bool True if string ends with open HTML attribute. + */ + public function is_html_attr( $content ) { + $is_html_attr = false; + foreach ( $this->attr_endings as $ending ) { + if ( $this->endswith( $content, $ending ) === true ) { + $is_html_attr = true; + break; + } + } + return $is_html_attr; + } + + /** + * Tests whether an attribute escaping function is being used outside of an HTML tag. + * + * @param string $content Haystack where we look for the end of a HTML tag. + * + * @return bool True if the passed string ends a HTML tag. + */ + public function is_outside_html_attr_context( $content ) { + return $this->endswith( trim( $content ), '>' ); + } + + /** + * A helper function which tests whether string ends with some other. + * + * @param string $haystack String which is being tested. + * @param string $needle The substring, which we try to locate on the end of the $haystack. + * + * @return bool True if haystack ends with needle. + */ + public function endswith( $haystack, $needle ) { + return substr( $haystack, -strlen( $needle ) ) === $needle; + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/StaticStrreplaceSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/StaticStrreplaceSniff.php new file mode 100644 index 00000000..3d57edcc --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/StaticStrreplaceSniff.php @@ -0,0 +1,87 @@ +tokens[ $stackPtr ]['content'] !== 'str_replace' ) { + return; + } + + $openBracket = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true ); + + if ( $this->tokens[ $openBracket ]['code'] !== T_OPEN_PARENTHESIS ) { + return; + } + + $next_start_ptr = $openBracket + 1; + for ( $i = 0; $i < 3; $i++ ) { + $param_ptr = $this->phpcsFile->findNext( array_merge( Tokens::$emptyTokens, [ T_COMMA ] ), $next_start_ptr, null, true ); + + if ( $this->tokens[ $param_ptr ]['code'] === T_ARRAY ) { + $openBracket = $this->phpcsFile->findNext( Tokens::$emptyTokens, $param_ptr + 1, null, true ); + if ( $this->tokens[ $openBracket ]['code'] !== T_OPEN_PARENTHESIS ) { + return; + } + + // Find the closing bracket. + $closeBracket = $this->tokens[ $openBracket ]['parenthesis_closer']; + + $array_item_ptr = $this->phpcsFile->findNext( array_merge( Tokens::$emptyTokens, [ T_COMMA ] ), $openBracket + 1, $closeBracket, true ); + while ( $array_item_ptr !== false ) { + + if ( $this->tokens[ $array_item_ptr ]['code'] !== T_CONSTANT_ENCAPSED_STRING ) { + return; + } + $array_item_ptr = $this->phpcsFile->findNext( array_merge( Tokens::$emptyTokens, [ T_COMMA ] ), $array_item_ptr + 1, $closeBracket, true ); + } + + $next_start_ptr = $closeBracket + 1; + continue; + + } + + if ( $this->tokens[ $param_ptr ]['code'] !== T_CONSTANT_ENCAPSED_STRING ) { + return; + } + + $next_start_ptr = $param_ptr + 1; + + } + + $message = 'This code pattern is often used to run a very dangerous shell programs on your server. The code in these files needs to be reviewed, and possibly cleaned.'; + $this->phpcsFile->addError( $message, $stackPtr, 'StaticStrreplace' ); + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/TwigSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/TwigSniff.php new file mode 100644 index 00000000..9c87efa7 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/TwigSniff.php @@ -0,0 +1,62 @@ +tokens[ $stackPtr ]['content'] ) === 1 ) { + // Twig autoescape disabled. + $message = 'Found Twig autoescape disabling notation.'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'AutoescapeFalse' ); + } + + if ( preg_match( '/\|\s*raw/', $this->tokens[ $stackPtr ]['content'] ) === 1 ) { + // Twig default unescape filter. + $message = 'Found Twig default unescape filter: "|raw".'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'RawFound' ); + } + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/UnderscorejsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/UnderscorejsSniff.php new file mode 100644 index 00000000..6ea36135 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/UnderscorejsSniff.php @@ -0,0 +1,162 @@ +|$)`'; + + /** + * Regex to match execute notations containing a print command + * and retrieve a code snippet. + * + * @var string + */ + const UNESCAPED_PRINT_REGEX = '`<%\s*(?:print\s*\(.+?\)\s*;|__p\s*\+=.+?)\s*%>`'; + + /** + * Regex to match the "interpolate" keyword when used to overrule the ERB-style delimiters. + * + * @var string + */ + const INTERPOLATE_KEYWORD_REGEX = '`(?:templateSettings\.interpolate|\.interpolate\s*=\s*/|interpolate\s*:\s*/)`'; + + /** + * A list of tokenizers this sniff supports. + * + * @var string[] + */ + public $supportedTokenizers = [ 'JS', 'PHP' ]; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + $targets = Tokens::$textStringTokens; + $targets[] = T_PROPERTY; + $targets[] = T_STRING; + + return $targets; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * + * @return void + */ + public function process_token( $stackPtr ) { + /* + * Ignore Gruntfile.js files as they are configuration, not code. + */ + $file_name = $this->strip_quotes( $this->phpcsFile->getFileName() ); + $file_name = strtolower( basename( $file_name ) ); + + if ( $file_name === 'gruntfile.js' ) { + return; + } + + /* + * Check for delimiter change in JS files. + */ + if ( $this->tokens[ $stackPtr ]['code'] === T_STRING + || $this->tokens[ $stackPtr ]['code'] === T_PROPERTY + ) { + if ( $this->phpcsFile->tokenizerType !== 'JS' ) { + // These tokens are only relevant for JS files. + return; + } + + if ( $this->tokens[ $stackPtr ]['content'] !== 'interpolate' ) { + return; + } + + // Check the context to prevent false positives. + if ( $this->tokens[ $stackPtr ]['code'] === T_STRING ) { + $prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true ); + if ( $prev === false || $this->tokens[ $prev ]['code'] !== T_OBJECT_OPERATOR ) { + return; + } + + $prevPrev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true ); + $next = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + if ( ( $prevPrev === false + || $this->tokens[ $prevPrev ]['code'] !== T_STRING + || $this->tokens[ $prevPrev ]['content'] !== 'templateSettings' ) + && ( $next === false + || $this->tokens[ $next ]['code'] !== T_EQUAL ) + ) { + return; + } + } + + // Underscore.js delimiter change. + $message = 'Found Underscore.js delimiter change notation.'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'InterpolateFound' ); + + return; + } + + $content = $this->strip_quotes( $this->tokens[ $stackPtr ]['content'] ); + + $match_count = preg_match_all( self::UNESCAPED_INTERPOLATE_REGEX, $content, $matches ); + if ( $match_count > 0 ) { + foreach ( $matches[0] as $match ) { + if ( strpos( $match, '_.escape(' ) !== false ) { + continue; + } + + // Underscore.js unescaped output. + $message = 'Found Underscore.js unescaped output notation: "%s".'; + $data = [ $match ]; + $this->phpcsFile->addWarning( $message, $stackPtr, 'OutputNotation', $data ); + } + } + + $match_count = preg_match_all( self::UNESCAPED_PRINT_REGEX, $content, $matches ); + if ( $match_count > 0 ) { + foreach ( $matches[0] as $match ) { + if ( strpos( $match, '_.escape(' ) !== false ) { + continue; + } + + // Underscore.js unescaped output. + $message = 'Found Underscore.js unescaped print execution: "%s".'; + $data = [ $match ]; + $this->phpcsFile->addWarning( $message, $stackPtr, 'PrintExecution', $data ); + } + } + + if ( $this->phpcsFile->tokenizerType !== 'JS' + && preg_match( self::INTERPOLATE_KEYWORD_REGEX, $content ) > 0 + ) { + // Underscore.js delimiter change. + $message = 'Found Underscore.js delimiter change notation.'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'InterpolateFound' ); + } + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/VuejsSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/VuejsSniff.php new file mode 100644 index 00000000..df9ac30d --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Security/VuejsSniff.php @@ -0,0 +1,55 @@ +tokens[ $stackPtr ]['content'], 'v-html' ) !== false ) { + // Vue autoescape disabled. + $message = 'Found Vue.js non-escaped (raw) HTML directive.'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'RawHTMLDirectiveFound' ); + } + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Sniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Sniff.php new file mode 100644 index 00000000..dfad0381 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Sniff.php @@ -0,0 +1,20 @@ + true, + 'add_filter' => true, + ]; + + /** + * CSS properties this sniff is looking for. + * + * @var array + */ + protected $target_css_properties = [ + 'visibility' => [ + 'type' => '!=', + 'value' => 'hidden', + ], + 'display' => [ + 'type' => '!=', + 'value' => 'none', + ], + 'opacity' => [ + 'type' => '>', + 'value' => 0.3, + ], + ]; + + /** + * CSS selectors this sniff is looking for. + * + * @var array + */ + protected $target_css_selectors = [ + '.show-admin-bar', + '#wpadminbar', + ]; + + /** + * String tokens within PHP files we want to deal with. + * + * Set from the register() method. + * + * @var array + */ + private $string_tokens = []; + + /** + * Regex template for use with the CSS selectors in combination with PHP text strings. + * + * @var string + */ + private $target_css_selectors_regex = '`(?:%s).*?\{(.*)$`'; + + /** + * Property to keep track of whether a ' ) !== false ) { + // Make sure we check any content on this line before the closing style tag. + $this->in_style[ $file_name ] = false; + $content = trim( substr( $content, 0, strpos( $content, '' ) ) ); + } + } elseif ( $this->has_html_open_tag( 'style', $stackPtr, $content ) === true ) { + // Ok, found a ' ) === false ) { + // Make sure we check any content on this line after the opening style tag. + $this->in_style[ $file_name ] = true; + $content = trim( substr( $content, strpos( $content, '' ); + $content = trim( substr( $content, $start, $end - $start ) ); + unset( $start, $end ); + } + } else { + return; + } + + // Are we in one of the target selectors ? + if ( $this->in_target_selector[ $file_name ] === true ) { + if ( strpos( $content, '}' ) !== false ) { + // Make sure we check any content on this line before the selector closing brace. + $this->in_target_selector[ $file_name ] = false; + $content = trim( substr( $content, 0, strpos( $content, '}' ) ) ); + } + } elseif ( preg_match( $this->target_css_selectors_regex, $content, $matches ) > 0 ) { + // Ok, found a new target selector. + $content = ''; + + if ( isset( $matches[1] ) && $matches[1] !== '' ) { + if ( strpos( $matches[1], '}' ) === false ) { + // Make sure we check any content on this line before the closing brace. + $this->in_target_selector[ $file_name ] = true; + $content = trim( $matches[1] ); + } else { + // Ok, we have the selector open and close brace on the same line. + $content = trim( substr( $matches[1], 0, strpos( $matches[1], '}' ) ) ); + } + } else { + $this->in_target_selector[ $file_name ] = true; + } + } else { + return; + } + unset( $matches ); + + // Now let's do the check for the CSS properties. + if ( ! empty( $content ) ) { + foreach ( $this->target_css_properties as $property => $requirements ) { + if ( strpos( $content, $property ) !== false ) { + $error = true; + + // Check the value of the CSS property. + if ( $this->remove_only === true && preg_match( '`' . preg_quote( $property, '`' ) . '\s*:\s*(.+?)\s*(?:!important)?;`', $content, $matches ) > 0 ) { + $value = trim( $matches[1] ); + $valid = $this->validate_css_property_value( $value, $requirements['type'], $requirements['value'] ); + if ( $valid === true ) { + $error = false; + } + } + + if ( $error === true ) { + $this->addHidingDetectedError( $stackPtr ); + } + } + } + } + } + + /** + * Processes this test for T_STYLE tokens in CSS files. + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * + * @return void + */ + protected function process_css_style( $stackPtr ) { + if ( ! isset( $this->target_css_properties[ $this->tokens[ $stackPtr ]['content'] ] ) ) { + // Not one of the CSS properties we're interested in. + return; + } + + $css_property = $this->target_css_properties[ $this->tokens[ $stackPtr ]['content'] ]; + + // Check if the CSS selector matches. + $opener = $this->phpcsFile->findPrevious( \T_OPEN_CURLY_BRACKET, $stackPtr ); + if ( $opener !== false ) { + for ( $i = ( $opener - 1 ); $i >= 0; $i-- ) { + if ( isset( Tokens::$commentTokens[ $this->tokens[ $i ]['code'] ] ) + || $this->tokens[ $i ]['code'] === \T_CLOSE_CURLY_BRACKET + ) { + break; + } + } + $start = ( $i + 1 ); + $selector = trim( $this->phpcsFile->getTokensAsString( $start, $opener - $start ) ); + unset( $i ); + + foreach ( $this->target_css_selectors as $target_selector ) { + if ( strpos( $selector, $target_selector ) !== false ) { + $error = true; + + if ( $this->remove_only === true ) { + // Check the value of the CSS property. + $valuePtr = $this->phpcsFile->findNext( [ \T_COLON, \T_WHITESPACE ], $stackPtr + 1, null, true ); + $value = $this->tokens[ $valuePtr ]['content']; + $valid = $this->validate_css_property_value( $value, $css_property['type'], $css_property['value'] ); + if ( $valid === true ) { + $error = false; + } + } + + if ( $error === true ) { + $this->addHidingDetectedError( $stackPtr ); + } + } + } + } + } + + /** + * Consolidated violation. + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + */ + private function addHidingDetectedError( $stackPtr ) { + $message = 'Hiding of the admin bar is not allowed.'; + $this->phpcsFile->addError( $message, $stackPtr, 'HidingDetected' ); + } + + /** + * Verify if a CSS property value complies with an expected value. + * + * {@internal This is a method stub, doing only what is needed for this sniff. + * If at some point in the future other sniff would need similar functionality, + * this method should be moved to the WordPress_Sniff class and expanded to cover + * all types of comparisons.}} + * + * @param mixed $value The value of CSS property. + * @param string $compare_type The type of comparison to use for the validation. + * @param string $compare_value The value to compare against. + * + * @return bool True if the property value complies, false otherwise. + */ + protected function validate_css_property_value( $value, $compare_type, $compare_value ) { + switch ( $compare_type ) { + case '!=': + return $value !== $compare_value; + + case '>': + return $value > $compare_value; + } + return false; + } + + /** + * Check if a content string contains a specific HTML open tag. + * + * @param string $tag_name The name of the HTML tag without brackets. So if + * searching for ' open tag, false otherwise. + */ + public function has_html_open_tag( $tag_name, $stackPtr = null, $content = null ) { + if ( $content === null && isset( $stackPtr ) ) { + $content = $this->tokens[ $stackPtr ]['content']; + } + + return $content !== null && strpos( $content, '<' . $tag_name ) !== false; + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Variables/RestrictedVariablesSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Variables/RestrictedVariablesSniff.php new file mode 100644 index 00000000..fe19452d --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Variables/RestrictedVariablesSniff.php @@ -0,0 +1,70 @@ + array( + * 'wpdb' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Dont use this one please!', + * 'variables' => array( '$val', '$var' ), + * 'object_vars' => array( '$foo->bar', .. ), + * 'array_members' => array( '$foo['bar']', .. ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return [ + 'user_meta' => [ + 'type' => 'error', + 'message' => 'Usage of users tables is highly discouraged in VIP context', + 'object_vars' => [ + '$wpdb->users', + ], + ], + 'session' => [ + 'type' => 'error', + 'message' => 'Usage of $_SESSION variable is prohibited.', + 'variables' => [ + '$_SESSION', + ], + ], + + // @link https://docs.wpvip.com/technical-references/code-review/vip-errors/#h-cache-constraints + 'cache_constraints' => [ + 'type' => 'warning', + 'message' => 'Due to server-side caching, server-side based client related logic might not work. We recommend implementing client side logic in JavaScript instead.', + 'variables' => [ + '$_COOKIE', + ], + 'array_members' => [ + '$_SERVER[\'HTTP_USER_AGENT\']', + '$_SERVER[\'REMOTE_ADDR\']', + ], + ], + ]; + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Variables/ServerVariablesSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Variables/ServerVariablesSniff.php new file mode 100644 index 00000000..03e52e55 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Variables/ServerVariablesSniff.php @@ -0,0 +1,75 @@ + [ + 'PHP_AUTH_USER' => true, + 'PHP_AUTH_PW' => true, + ], + 'userControlledVariables' => [ + 'HTTP_X_IP_TRAIL' => true, + 'HTTP_X_FORWARDED_FOR' => true, + 'REMOTE_ADDR' => true, + ], + ]; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return [ + T_VARIABLE, + ]; + } + + /** + * Process this test when one of its tokens is encountered + * + * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * + * @return void + */ + public function process_token( $stackPtr ) { + + if ( $this->tokens[ $stackPtr ]['content'] !== '$_SERVER' ) { + // Not the variable we are looking for. + return; + } + + $variableNamePtr = $this->phpcsFile->findNext( [ T_CONSTANT_ENCAPSED_STRING ], $stackPtr + 1, null, false, null, true ); + $variableName = str_replace( [ "'", '"' ], '', $this->tokens[ $variableNamePtr ]['content'] ); + + if ( isset( $this->restrictedVariables['authVariables'][ $variableName ] ) ) { + $message = 'Basic authentication should not be handled via PHP code.'; + $this->phpcsFile->addError( $message, $stackPtr, 'BasicAuthentication' ); + } elseif ( isset( $this->restrictedVariables['userControlledVariables'][ $variableName ] ) ) { + $message = 'Header "%s" is user-controlled and should be properly validated before use.'; + $data = [ $variableName ]; + $this->phpcsFile->addError( $message, $stackPtr, 'UserControlledHeaders', $data ); + } + } + +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Variables/VariableAnalysisSniff.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Variables/VariableAnalysisSniff.php new file mode 100644 index 00000000..18e1ed27 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/Sniffs/Variables/VariableAnalysisSniff.php @@ -0,0 +1,81 @@ + + * @copyright 2011-2012 Sam Graham + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @link http://pear.php.net/package/PHP_CodeSniffer + */ + +namespace WordPressVIPMinimum\Sniffs\Variables; + +use PHP_CodeSniffer\Files\File; + +/** + * Checks for undefined function variables. + * + * This sniff checks that all function variables + * are defined in the function body. + * + * @category PHP + * @package PHP_CodeSniffer + * @author Sam Graham + * @copyright 2011 Sam Graham + * @link http://pear.php.net/package/PHP_CodeSniffer + * + * @deprecated 2.2.0 Use the `VariableAnalysis.CodeAnalysis.VariableAnalysis` sniff instead. + * This `WordPressVIPMinimum.Variables.VariableAnalysis sniff will be removed in VIPCS 3.0.0. + */ +class VariableAnalysisSniff extends \VariableAnalysis\Sniffs\CodeAnalysis\VariableAnalysisSniff { + + /** + * Keep track of whether the warnings have been thrown to prevent + * the messages being thrown for every token triggering the sniff. + * + * @since 2.2.0 + * + * @var array + */ + private $thrown = [ + 'DeprecatedSniff' => false, + 'FoundPropertyForDeprecatedSniff' => false, + ]; + + /** + * Don't use. + * + * @since 2.2.0 Added to allow for throwing the deprecation notices. + * @deprecated 2.2.0 + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process( File $phpcsFile, $stackPtr ) { + + if ( $this->thrown['DeprecatedSniff'] === false ) { + $this->thrown['DeprecatedSniff'] = $phpcsFile->addWarning( + 'The "WordPressVIPMinimum.Variables.VariableAnalysis" sniff has been deprecated. Use the "VariableAnalysis.CodeAnalysis.VariableAnalysis" sniff instead. Please update your custom ruleset.', + 0, + 'DeprecatedSniff' + ); + } + if ( ! empty( $this->exclude ) && $this->thrown['FoundPropertyForDeprecatedSniff'] === false ) { + $this->thrown['FoundPropertyForDeprecatedSniff'] = $phpcsFile->addWarning( + 'The "WordPressVIPMinimum.Variables.VariableAnalysis" sniff has been deprecated. Use the "CodeAnalysis.VariableAnalysis" sniff instead. "exclude" property setting found. Please update your custom ruleset.', + 0, + 'FoundPropertyForDeprecatedSniff' + ); + } + + parent::process( $phpcsFile, $stackPtr ); + } +} diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/ruleset-test.inc b/vendor/automattic/vipwpcs/WordPressVIPMinimum/ruleset-test.inc new file mode 100644 index 00000000..803e890f --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/ruleset-test.inc @@ -0,0 +1,622 @@ + + + + 999, // Warning. +); +_query_posts( 'posts_per_page=999' ); // Warning. +$query_args['posts_per_page'] = 999; // Warning. + +// WordPress.DateTime.RestrictedFunctions +date_default_timezone_set( 'FooBar' ); // Error. + +// WordPress.DB.PreparedSQL +$b = function () { + global $wpdb; + $listofthings = wp_cache_get( 'foo' ); + if ( ! $listofthings ) { + $foo = "column = 'test'"; + + $listofthings = $wpdb->query( 'SELECT something FROM somewhere WHERE ' . $foo ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Error. + wp_cache_set( 'foo', $listofthings ); + } +}; + +// WordPress.DB.DirectDatabaseQuery +$baz = $wpdb->get_results( $wpdb->prepare( 'SELECT X FROM Y ' ) ); // Warning x 2. + +// WordPress.DB.SlowDBQuery +$test = [ + 'tax_query' => [], // Warning. +]; +new WP_Query( array( + 'meta_query' => [], // Warning. + 'meta_key' => 'foo', // Warning. + 'meta_value' => 'bar', // Warning. +) ); + +// WordPress.WP.GlobalVariablesOverride +$GLOBALS['wpdb'] = 'test'; // Error. + +// WordPress.PHP.StrictComparisons +if ( true == $true ) { // Warning. +} + +// WordPress.CodeAnalysis.AssignmentInCondition +if ( $test = get_post( $post ) ) { // Warning. +} + +// WordPress.PHP.StrictInArray +if ( true === in_array( $foo, $bar ) ) { // Warning. +} + +// WordPress.Functions.DontExtract +extract( $foobar ); // Error. + +// WordPress.WP.CronInterval +function my_add_weekly( $schedules ) { + $schedules['every_6_mins'] = array( + 'interval' => 360, + 'display' => __( 'Once every 6 minutes' ) + ); + return $schedules; +} +add_filter( 'cron_schedules', 'my_add_weekly'); // Warning. + +// Generic.NamingConventions.ConstructorName +class TestClass extends MyClass +{ + function __construct() { + parent::MYCLASS(); // Error. + parent::__construct(); + } +} +class OldClass +{ + function OldClass() // Error. + { + } +} + +// Generic.NamingConventions.ConstructorName +class TestClass extends MyClass { + function TestClass() { // Error. + parent::MyClass(); // Error. + parent::__construct(); + } +} + +// Generic.PHP.DisallowShortOpenTag +?> +// if (empty($this)) {echo 'This is will not work';} + +// Squiz.PHP.Eval +eval('$var = 4;'); // Error + Message. + +// WordPress.PHP.DiscouragedPHPFunctions +base64_decode( 'VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw=='); // Ok - exclude obfuscation group. +base64_encode( 'This is an encoded string' ); // Ok - exclude obfuscation group. +convert_uudecode( "+22!L;W9E(%!(4\"$`\n`" ); // Ok - exclude obfuscation group. +convert_uuencode( "test\ntext text\r\n" ); // Ok - exclude obfuscation group. +str_rot13( 'The quick brown fox jumps over the lazy dog.' ); // Ok - exclude obfuscation group. +serialize(); // Warning. +unserialize(); // Warning. +urlencode(); // Warning. +passthru( 'cat myfile.zip', $err ); // Warning. +$process = proc_open( 'php', $descriptorspec, $pipes, $cwd, $env ); // Warning. +$last_line = system( 'ls', $retval ); // Warning. +$handle = popen( '/bin/ls', 'r' ); // Warning. + +// WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_error_reporting +error_reporting(); // Error. + +// WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_ini_restore +ini_restore(); // Error. + +// WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_apache_setenv +apache_setenv(); // Error. + +// WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_putenv +putenv(); // Error. + +// WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_set_include_path +set_include_path(); // Error. + +// WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_restore_include_path +restore_include_path(); // Error. + +// WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_magic_quotes_runtime +magic_quotes_runtime(); // Error. + +// WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_set_magic_quotes_runtime +set_magic_quotes_runtime(); // Error. + +// WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_dl +dl(); // Error. + +// WordPress.PHP.DiscouragedPHPFunctions.system_calls_exec +exec( 'whoami' ); // Error. + +// WordPress.PHP.DiscouragedPHPFunctions.system_calls_shell_exec +$output = shell_exec( 'ls -lart' ); // Error. + +// WordPress.PHP.DevelopmentFunctions +var_dump(); // Warning. +var_export(); // Warning. +print_r(); // Warning. +trigger_error( 'message' ); // Warning. +set_error_handler(); // Warning. +debug_backtrace(); // Warning. +debug_print_backtrace(); // Warning. +wp_debug_backtrace_summary(); // Warning. + +// WordPress.PHP.DevelopmentFunctions.prevent_path_disclosure_phpinfo +phpinfo(); // Error. + +// WordPress.PHP.DevelopmentFunctions.error_log_error_log +error_log(); // Error. + +// WordPress.PHP.IniSet +ini_set( 'auto_detect_line_endings', true ); // Ok. +ini_set( 'highlight.bg', '#000000' ); // Ok. +ini_set( 'highlight.comment', '#000000' ); // Ok. +ini_set( 'highlight.default', '#000000' ); // Ok. +ini_set( 'highlight.html', '#000000' ); // Ok. +ini_set( 'highlight.keyword', '#000000' ); // Ok. +ini_set( 'highlight.string', '#000000' ); // Ok. +ini_set( 'short_open_tag', 1 ); // Ok. +ini_set( 'bcmath.scale', 1 ); // Error. +ini_set( 'display_errors', 1 ); // Error. +ini_set( 'error_reporting', 1 ); // Error. +ini_set( 'filter.default', 1 ); // Error. +ini_set( 'filter.default_flags', 1 ); // Error. +ini_set( 'iconv.input_encoding', 1 ); // Error. +ini_set( 'iconv.internal_encoding', 1 ); // Error. +ini_set( 'iconv.output_encoding', 1 ); // Error. +ini_set( 'ignore_user_abort', 1 ); // Error. +ini_set( 'log_errors', 1 ); // Error. +ini_set( 'max_execution_time', 1 ); // Error. +ini_set( 'memory_limit', 1 ); // Error. +ini_set( 'short_open_tag', 'off' ); // Error. +ini_set( 'foo', true ); // Warning. +ini_alter( 'auto_detect_line_endings', true ); // Ok. +ini_alter( 'highlight.bg', '#000000' ); // Ok. +ini_alter( 'highlight.comment', '#000000' ); // Ok. +ini_alter( 'highlight.default', '#000000' ); // Ok. +ini_alter( 'highlight.html', '#000000' ); // Ok. +ini_alter( 'highlight.keyword', '#000000' ); // Ok. +ini_alter( 'highlight.string', '#000000' ); // Ok. +ini_alter( 'short_open_tag', 1 ); // Ok. +ini_alter( 'bcmath.scale', 1 ); // Error. +ini_alter( 'display_errors', 1 ); // Error. +ini_alter( 'error_reporting', 1 ); // Error. +ini_alter( 'filter.default', 1 ); // Error. +ini_alter( 'filter.default_flags', 1 ); // Error. +ini_alter( 'iconv.input_encoding', 1 ); // Error. +ini_alter( 'iconv.internal_encoding', 1 ); // Error. +ini_alter( 'iconv.output_encoding', 1 ); // Error. +ini_alter( 'ignore_user_abort', 1 ); // Error. +ini_alter( 'log_errors', 1 ); // Error. +ini_alter( 'max_execution_time', 1 ); // Error. +ini_alter( 'memory_limit', 1 ); // Error. +ini_alter( 'short_open_tag', 'off' ); // Error. +ini_alter( 'foo', true ); // Warning. + +// WordPress.WP.AlternativeFunctions +curl_init(); // Warning + Message. +curl_close( $ch ); // Warning + Message. +CURL_getinfo(); // Warning + Message. +parse_url( 'http://example.com/' ); // Warning. +$json = json_encode( $thing ); // Warning. +readfile(); // Warning. +fclose(); // Warning. +fopen(); // Warning. +fread(); // Warning. +fsockopen(); // Warning. +pfsockopen(); // Warning. +srand(); // Warning. +mt_srand(); // Warning. +rand(); // Warning. +mt_rand(); // Warning. + +// WordPressVIPMinimum.Functions.RestrictedFunctions.get_posts_get_children +get_children(); // Error + Message. + +// VariableAnalysis.CodeAnalysis.VariableAnalysis +function foo() { + $a = 'Hello'; + $c = compact( $a, $b ); // Warning x 2. + try { + do_something_silly(); + } catch ( Exception $e ) {} // Ok. +} + +/* The below rules are implicitly included via WordPressVIPMinimum */ + +// WordPressVIPMinimum.Classes.DeclarationCompatibility +class MyWidget extends WP_Widget { + function widget() { // Error. + } +} + +// WordPressVIPMinimum.Classes.RestrictedExtendClasses +class BadTestClass extends WP_CLI_Command { } // Warning. + +// WordPressVIPMinimum.Compatibility.ZoninatorSniff +wpcom_vip_load_plugin( 'zoninator', 'plugins', '0.8' ); // Warning. + +// WordPressVIPMinimum.Constants.ConstantString +define( WPCOM_VIP ); // Error. + +// WordPressVIPMinimum.Constants.RestrictedConstants +if ( A8C_PROXIED_REQUEST === true ) { // Warning. +} +define( 'JETPACK_DEV_DEBUG', true ); // Error. + +// WordPressVIPMinimum.Files.IncludingFile +include ( MY_CONSTANT . "my_file.php" ); // Warning. +require_once( custom_function( 'test_file.php' ) ); // Warning. +require '../my_file.php'; // Error. +include_once("http://www.google.com/bad_file.php"); // Error. + +// WordPressVIPMinimum.Files.IncludingNonPHPFile +require_once __DIR__ . "/my_file.svg"; // Error. + +// WordPressVIPMinimum.Functions.CheckReturnValue +$my_theme_options = get_option( 'my_theme', false ); +if ( array_key_exists( 'key', $my_theme_options ) ) { } // Error. +echo 'My term link'; // Error. + +// WordPressVIPMinimum.Functions.DynamicCalls +$my_notokay_func = 'extract'; +$my_notokay_func(); // Error. + +// WordPressVIPMinimum.Functions.RestrictedFunctions + +opcache_reset(); // Error. +opcache_invalidate( 'test_script.php' ); // Error. +opcache_compile_file( $var ); // Error. +opcache_is_script_cached( 'test_script.php' ); // Error. +opcache_get_status(); // Error. +opcache_get_configuration(); // Error. + +wpcom_vip_irc(); // Error. +flush_rewrite_rules(); // Error. +$wp_rewrite->flush_rules(); // Error. +attachment_url_to_postid( $url ); // Error. + +switch_to_blog( $blogid ); // Warning. +get_page_by_title( $page_title ); // Error. +url_to_postid( $url ); // Error. +\add_role(); // Error. + + + + +term_exists(); // Error. +count_user_posts(); // Error. +wp_old_slug_redirect(); // Error. +get_adjacent_post(); // Error. +get_previous_post(); // Error. +get_previous_post_link(); // Error. +get_next_post(); // Error. +get_next_post_link(); // Error. +get_intermediate_image_sizes(); // Error. +wp_is_mobile(); // Error. +session_abort(); // Error. +session_cache_expire(); // Error. +session_cache_limiter(); // Error. +session_commit(); // Error. +session_create_id(); // Error. +session_decode(); // Error. +session_destroy(); // Error. +session_encode(); // Error. +session_gc(); // Error. +session_get_cookie_params(); // Error. +session_id(); // Error. +session_is_registered(); // Error. +session_module_name(); // Error. +session_name(); // Error. +session_regenerate_id(); // Error. +session_register_shutdown(); // Error. +session_register(); // Error. +session_reset(); // Error. +session_save_path(); // Error. +session_set_cookie_params(); // Error. +session_set_save_handler(); // Error. +session_start(); // Error. +session_status(); // Error. +session_unregister(); // Error. +session_unset(); // Error. +session_write_close(); // Error. +delete(); // Error. +file_put_contents( $file, $text, FILE_APPEND ); // Error. +while ( $count > $loop ) { + if ( flock( $fp, LOCK_EX ) ) { // Error. + fwrite( $fp, $text ); // Error. + } +} +fputcsv(); // Error. +fputs(); // Error. +ftruncate(); // Error. +is_writable(); // Error. +is_writeable(); // Error. +link(); // Error. +rename(); // Error. +symlink(); // Error. +tempnam(); // Error. +touch(); // Error. +unlink(); // Error. +mkdir(); // Error. +rmdir(); // Error. +chgrp(); // Error. +chown(); // Error. +chmod(); // Error. +lchgrp(); // Error. +lchown(); // Error. + + + +wp_mail(); // Warning. +mail(); // Warning. +is_multi_author(); // Warning. +the_sub_field( 'field' ); // Warning. +the_field( 'field' ); // Warning. +wp_remote_get( $url ); // Warning. +setcookie( 'cookie[three]', 'cookiethree' ); // Error. +get_posts(); // Warning. +wp_get_recent_posts(); // Warning. +$wp_random_testing = create_function( '$a, $b', 'return ( $b / $a ); '); // Warning. +wpcom_vip_get_term_link(); // Warning. +wpcom_vip_get_term_by(); // Warning. +wpcom_vip_get_category_by_slug(); // Warning. + +// WordPressVIPMinimum.Functions.StripTagsSniff +strip_tags( 'Testing' ); // Warning. +strip_tags( 'Test', $text ); // Warning. + +// WordPressVIPMinimum.Hooks.AlwaysReturnInFilter +function bad_example_function_thing() { // Error. + if ( 1 === 0 ) { + if ( 1 === 1 ) { + return 'ahoj'; + } else { + return 'hello'; + } + } +} +add_filter( 'bad_example_function_filter', 'bad_example_function_thing' ); +add_filter( 'another_bad_example_closure', function() { // Error. + return; +} ); + +// WordPressVIPMinimum.Hooks.PreGetPosts +add_action( 'pre_get_posts', function( $wp_query ) { + if ( ! $wp_query->is_search() ) { + $wp_query->set( 'cat', '-5' ); // Warning. + } +} ); + +// WordPressVIPMinimum.Hooks.RestrictedHooks +add_filter( 'upload_mimes', 'bad_example_function' ); // Warning. +add_action( 'http_request_timeout', 'bad_example_function' ); // Warning. +add_filter('http_request_args', 'bad_example_function' ); // Warning. +add_action( 'do_robotstxt', 'my_do_robotstxt'); // Warning. +add_filter( 'robots_txt', function() { // Warning. + return 'test'; +} ); + +// WordPressVIPMinimum.Performance.BatcacheWhitelistedParams +// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated +$test = sanitize_text_field( $_GET["utm_medium"] ); // Warning. + +// WordPressVIPMinimum.Performance.CacheValueOverride +$bad_wp_users = wp_cache_get( md5( self::CACHE_KEY . '_wp_users'), self::CACHE_GROUP ); +$bad_wp_users = false; // Error. + +// WordPressVIPMinimum.Performance.FetchingRemoteData +$external_resource = file_get_contents( 'https://example.com' ); // Warning. + +// WordPressVIPMinimum.Performance.LowExpiryCacheTime +wp_cache_set( 'test', $data, $group, 100 ); // Warning. +wp_cache_add( 123, $data, null, 1.5 * MINUTE_IN_SECONDS ); // Warning. +wp_cache_replace( 'test', $data, $group, 2*MINUTE_IN_SECONDS ); // Warning. + +// WordPressVIPMinimum.Performance.NoPaging +$args = array( + 'nopaging' => true, // Error. +); +_query_posts( 'nopaging=true' ); // Error. + +// WordPressVIPMinimum.Performance.OrderByRand +$args = array( + "orderby" => "RAND", // Error. +); +$query_args['orderby'] = 'rand'; // Error. + +// WordPressVIPMinimum.Performance.RegexpCompare +$query_args = array( + 'posts_per_page' => 1, + 'post_status' => 'draft', + 'meta_compare' => 'REGEXP', // Error. +); +$query_args = [ + 'post_status' => 'publish', + 'meta_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query + [ + 'compare' => 'REGEXP', // Error. + ] + ] +]; + +// WordPressVIPMinimum.Performance.RemoteRequestTimeout +wp_remote_post( $stdClass->endpoint, array( + 'method' => 'POST', + 'timeout' => 45, // Error. + 'httpversion' => '1.1', + 'blocking' => false, + 'body' => wp_json_encode( $stdClass->logs, JSON_UNESCAPED_SLASHES ), + ) +); + +// WordPressVIPMinimum.Performance.TaxonomyMetaInOptions +get_option( "taxonomy_rating_$obj->term_id" ); // Warning. +update_option( 'taxonomy_rating_' . $category_id ); // Warning. + +// WordPressVIPMinimum.Performance.WPQueryParams +$query_args = array( + 'post__not_in' => $posts_not_in, // Warning. + 'suppress_filters' => true, // Error. +); + +// WordPressVIPMinimum.Security.EscapingVoidReturnFunctions.Found +esc_js( _deprecated_argument() ); // Error. +esc_js( _deprecated_constructor() ); // Error. +esc_js( _deprecated_file( 'filename' ) ); // Error. +esc_js( _deprecated_function() ); // Error. +esc_js( _deprecated_hook() ); // Error. +esc_js( _doing_it_wrong() ); // Error. +esc_html( printf( 'foo', [] ) ); // Error. +esc_attr( user_error( 'foo', '' ) ); // Error. +esc_attr( vprintf( 'foo', [] ) ); // Error. +esc_attr( wp_die( 'foo' ) ); // Error. +esc_attr( wp_dropdown_pages() ); // Error. + +// WordPressVIPMinimum.Security.ExitAfterRedirect +function redirect_test() { + wp_safe_redirect( 'https.//vip.wordpress.com' ); // Error. +} +wp_redirect( 'https://vip.wordpress.com' ); // Error. + +// WordPressVIPMinimum.Security.PHPFilterFunctions +filter_input( INPUT_GET, 'foo' ); // Warning. +filter_input( INPUT_GET, "foo", FILTER_UNSAFE_RAW ); // Warning. +filter_var( $url, FILTER_DEFAULT ); // Warning. +filter_var_array( $array ); // Warning. +filter_input_array( $array ); // Warning. + +// WordPressVIPMinimum.Security.Mustache +echo '{{{data}}}'; // Warning. +?> + + '; // Error. +echo ''; // Error. + +// WordPressVIPMinimum.Security.StaticStrreplace +str_replace( 'foo', array( 'bar', 'foo' ), 'foobar' ); // Error. + +// WordPressVIPMinimum.Security.Underscorejs +echo ""; + +// WordPressVIPMinimum.Security.Vuejs +?>
    +

    +
    +#wpadminbar { + visibility: hidden; /* Error. */ + display: none; /* Error. */ + opacity: 0; /* Error. */ +} +'; +echo ''; // Error. +?> users"; // Error. +$x = foo( sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- Warning. +foo( $_SESSION['bar'] ); // Error. + +// WordPressVIPMinimum.Variables.ServerVariables +// phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotValidated,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized +$test = $_SERVER['PHP_AUTH_PW']; // Error. +bar( $_SERVER['HTTP_X_IP_TRAIL'] ); // Error. +$_SERVER['HTTP_X_FORWARDED_FOR']; // Error. +$_SERVER["REMOTE_ADDR"]; // Error. +// phpcs:enable WordPress.Security.ValidatedSanitizedInput.InputNotValidated,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + +class MyClass { + function my_function() { + return function() { + $this->my_callback(); // OK - new VariableAnalysis doesn't flag $this as undefined in closure. + }; + } + + function my_callback() {} +} + +// Generic.VersionControl.GitMergeConflict +?> +<<<<<<< HEAD // Error. + +>>>>>>> // Error. + + + + + diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/ruleset-test.php b/vendor/automattic/vipwpcs/WordPressVIPMinimum/ruleset-test.php new file mode 100644 index 00000000..19d74bf1 --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/ruleset-test.php @@ -0,0 +1,325 @@ + [ + 4 => 1, + 7 => 1, + 11 => 1, + 16 => 1, + 17 => 1, + 21 => 1, + 27 => 2, + 35 => 1, + 45 => 1, + 54 => 1, + 73 => 1, + 88 => 1, + 104 => 1, + 110 => 1, + 117 => 1, + 118 => 1, + 124 => 1, + 130 => 1, + 147 => 1, + 150 => 1, + 153 => 1, + 156 => 1, + 159 => 1, + 162 => 1, + 165 => 1, + 168 => 1, + 171 => 1, + 174 => 1, + 177 => 1, + 190 => 1, + 193 => 1, + 204 => 1, + 205 => 1, + 206 => 1, + 207 => 1, + 208 => 1, + 209 => 1, + 210 => 1, + 211 => 1, + 212 => 1, + 213 => 1, + 214 => 1, + 215 => 1, + 216 => 1, + 226 => 1, + 227 => 1, + 228 => 1, + 229 => 1, + 230 => 1, + 231 => 1, + 232 => 1, + 233 => 1, + 234 => 1, + 235 => 1, + 236 => 1, + 237 => 1, + 238 => 1, + 259 => 1, + 274 => 1, + 285 => 1, + 290 => 1, + 295 => 1, + 296 => 1, + 299 => 1, + 303 => 1, + 304 => 1, + 308 => 1, + 312 => 1, + 313 => 1, + 314 => 1, + 315 => 1, + 316 => 1, + 317 => 1, + 319 => 1, + 320 => 1, + 321 => 1, + 322 => 1, + 325 => 1, + 326 => 1, + 327 => 1, + 332 => 1, + 333 => 1, + 334 => 1, + 335 => 1, + 336 => 1, + 337 => 1, + 338 => 1, + 339 => 1, + 340 => 1, + 341 => 1, + 342 => 1, + 343 => 1, + 344 => 1, + 345 => 1, + 346 => 1, + 347 => 1, + 348 => 1, + 349 => 1, + 350 => 1, + 351 => 1, + 352 => 1, + 353 => 1, + 354 => 1, + 355 => 1, + 356 => 1, + 357 => 1, + 358 => 1, + 359 => 1, + 360 => 1, + 361 => 1, + 362 => 1, + 363 => 1, + 364 => 1, + 365 => 1, + 366 => 1, + 367 => 1, + 368 => 1, + 369 => 1, + 371 => 1, + 372 => 1, + 375 => 1, + 376 => 1, + 377 => 1, + 378 => 1, + 379 => 1, + 380 => 1, + 381 => 1, + 382 => 1, + 383 => 1, + 384 => 1, + 385 => 1, + 386 => 1, + 387 => 1, + 388 => 1, + 389 => 1, + 390 => 1, + 391 => 1, + 392 => 1, + 402 => 1, + 415 => 1, + 425 => 1, + 451 => 1, + 463 => 1, + 465 => 1, + 469 => 1, + 471 => 1, + 477 => 1, + 483 => 1, + 491 => 1, + 505 => 1, + 509 => 1, + 510 => 1, + 511 => 1, + 512 => 1, + 513 => 1, + 514 => 1, + 515 => 1, + 516 => 1, + 517 => 1, + 518 => 1, + 519 => 1, + 523 => 1, + 525 => 1, + 550 => 1, + 551 => 1, + 554 => 1, + 569 => 1, + 570 => 1, + 573 => 1, + 574 => 1, + 575 => 1, + 578 => 1, + 581 => 1, + 582 => 1, + 583 => 1, + 588 => 1, + 590 => 1, + 594 => 1, + 595 => 1, + 596 => 1, + 597 => 1, + 612 => 1, + 614 => 1, + 618 => 1, + ], + 'warnings' => [ + 32 => 1, + 39 => 1, + 41 => 1, + 42 => 1, + 60 => 2, + 64 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 76 => 1, + 80 => 1, + 84 => 1, + 98 => 1, + 126 => 1, + 138 => 1, + 139 => 1, + 140 => 1, + 141 => 1, + 142 => 1, + 143 => 1, + 144 => 1, + 180 => 1, + 181 => 1, + 182 => 1, + 183 => 1, + 184 => 1, + 185 => 1, + 186 => 1, + 187 => 1, + 217 => 1, + 239 => 1, + 242 => 1, + 243 => 1, + 244 => 1, + 245 => 1, + 246 => 1, + 247 => 1, + 248 => 1, + 249 => 1, + 250 => 1, + 251 => 1, + 252 => 1, + 253 => 1, + 254 => 1, + 255 => 1, + 256 => 1, + 264 => 2, + 279 => 1, + 282 => 1, + 288 => 1, + 293 => 1, + 294 => 1, + 324 => 1, + 396 => 1, + 397 => 1, + 398 => 1, + 399 => 1, + 400 => 1, + 401 => 1, + 403 => 1, + 404 => 1, + 405 => 1, + 406 => 1, + 407 => 1, + 408 => 1, + 411 => 1, + 412 => 1, + 432 => 1, + 437 => 1, + 438 => 1, + 439 => 1, + 440 => 1, + 441 => 1, + 447 => 1, + 454 => 1, + 457 => 1, + 458 => 1, + 459 => 1, + 499 => 1, + 500 => 1, + 504 => 1, + 528 => 1, + 529 => 1, + 530 => 1, + 531 => 1, + 532 => 1, + 535 => 1, + 538 => 1, + 545 => 1, + 559 => 1, + 565 => 1, + 589 => 1, + ], + 'messages' => [ + 130 => [ + '`eval()` is a security risk, please refrain from using it.', + ], + 242 => [ + 'Using cURL functions is highly discouraged within VIP context. Please see: https://docs.wpvip.com/technical-references/code-quality-and-best-practices/retrieving-remote-data/.', + ], + 243 => [ + 'Using cURL functions is highly discouraged within VIP context. Please see: https://docs.wpvip.com/technical-references/code-quality-and-best-practices/retrieving-remote-data/.', + ], + 244 => [ + 'Using cURL functions is highly discouraged within VIP context. Please see: https://docs.wpvip.com/technical-references/code-quality-and-best-practices/retrieving-remote-data/.', + ], + 259 => [ + '`get_children()` performs a no-LIMIT query by default, make sure to set a reasonable `posts_per_page`. `get_children()` will do a -1 query by default, a maximum of 100 should be used.', + ], + ], +]; + +require __DIR__ . '/../tests/RulesetTest.php'; + +// Run the tests! +$test = new RulesetTest( 'WordPressVIPMinimum', $expected ); +if ( $test->passes() ) { + printf( 'All WordPressVIPMinimum tests passed!' . PHP_EOL ); + exit( 0 ); +} + +exit( 1 ); diff --git a/vendor/automattic/vipwpcs/WordPressVIPMinimum/ruleset.xml b/vendor/automattic/vipwpcs/WordPressVIPMinimum/ruleset.xml new file mode 100644 index 00000000..2ce2511c --- /dev/null +++ b/vendor/automattic/vipwpcs/WordPressVIPMinimum/ruleset.xml @@ -0,0 +1,177 @@ + + + WordPress VIP Minimum Coding Standards + + + + + + + + + *.twig + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *.php + *.inc + *.js + *.css + + + + + + error + `eval()` is a security risk, please refrain from using it. + + + + + + + + + + + + + error + + + error + + + error + + + error + + + error + + + error + + + error + + + error + + + error + + + error + + + error + + + + + + + + + + error + + + error + + + + + + + + + + + + + + + + + + Using cURL functions is highly discouraged within VIP context. Please see: https://docs.wpvip.com/technical-references/code-quality-and-best-practices/retrieving-remote-data/. + + + Using cURL functions is highly discouraged within VIP context. Please see: https://docs.wpvip.com/technical-references/code-quality-and-best-practices/retrieving-remote-data/. + + + Using cURL functions is highly discouraged within VIP context. Please see: https://docs.wpvip.com/technical-references/code-quality-and-best-practices/retrieving-remote-data/. + + + + error + `%1$s()` performs a no-LIMIT query by default, make sure to set a reasonable `posts_per_page`. `%1$s()` will do a -1 query by default, a maximum of 100 should be used. + + + + + + + + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + diff --git a/vendor/automattic/vipwpcs/composer.json b/vendor/automattic/vipwpcs/composer.json new file mode 100644 index 00000000..5a7ee54b --- /dev/null +++ b/vendor/automattic/vipwpcs/composer.json @@ -0,0 +1,57 @@ +{ + "name": "automattic/vipwpcs", + "type": "phpcodesniffer-standard", + "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress VIP minimum coding conventions", + "keywords": [ + "phpcs", + "standards", + "WordPress" + ], + "license": "MIT", + "authors": [ + { + "name": "Contributors", + "homepage": "https://github.com/Automattic/VIP-Coding-Standards/graphs/contributors" + } + ], + "require": { + "php": ">=5.4", + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7", + "sirbrillig/phpcs-variable-analysis": "^2.11.1", + "squizlabs/php_codesniffer": "^3.5.5", + "wp-coding-standards/wpcs": "^2.3" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.0", + "php-parallel-lint/php-console-highlighter": "^0.5", + "phpcompatibility/php-compatibility": "^9", + "phpcsstandards/phpcsdevtools": "^1.0", + "phpunit/phpunit": "^4 || ^5 || ^6 || ^7" + }, + "scripts": { + "install-codestandards": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run", + "ruleset": "bin/ruleset-tests", + "lint": [ + "bin/php-lint", + "bin/xml-lint" + ], + "phpcs": "bin/phpcs", + "phpunit": "bin/unit-tests", + "coverage": "bin/unit-tests-coverage", + "check-complete": [ + "@php ./vendor/phpcsstandards/phpcsdevtools/bin/phpcs-check-feature-completeness -q ./WordPressVIPMinimum" + ], + "test": [ + "@lint", + "@ruleset", + "@phpunit", + "@phpcs", + "@check-complete" + ] + }, + "support": { + "issues": "https://github.com/Automattic/VIP-Coding-Standards/issues", + "wiki": "https://github.com/Automattic/VIP-Coding-Standards/wiki", + "source": "https://github.com/Automattic/VIP-Coding-Standards" + } +} diff --git a/vendor/bin/.composer-downloads/phpstan-c8e8da3840ca188cc0c7896c1cd21b1f.json b/vendor/bin/.composer-downloads/phpstan-c8e8da3840ca188cc0c7896c1cd21b1f.json new file mode 100644 index 00000000..ff06c010 --- /dev/null +++ b/vendor/bin/.composer-downloads/phpstan-c8e8da3840ca188cc0c7896c1cd21b1f.json @@ -0,0 +1,5 @@ +{ + "name": "rtcamp/login-with-google:phpstan", + "url": "https://github.com/phpstan/phpstan/releases/latest/download/phpstan.phar", + "checksum": "29b3aafd3e3bff7f68a8e6f9b462eb8945952e3f5408e913007eddc69a4dae4b" +} \ No newline at end of file diff --git a/vendor/bin/php-parse b/vendor/bin/php-parse new file mode 100755 index 00000000..80f0e486 --- /dev/null +++ b/vendor/bin/php-parse @@ -0,0 +1,117 @@ +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) { + include("phpvfscomposer://" . __DIR__ . '/..'.'/nikic/php-parser/bin/php-parse'); + exit(0); + } +} + +include __DIR__ . '/..'.'/nikic/php-parser/bin/php-parse'; diff --git a/vendor/bin/phpcbf b/vendor/bin/phpcbf new file mode 100755 index 00000000..dd5f763d --- /dev/null +++ b/vendor/bin/phpcbf @@ -0,0 +1,117 @@ +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) { + include("phpvfscomposer://" . __DIR__ . '/..'.'/squizlabs/php_codesniffer/bin/phpcbf'); + exit(0); + } +} + +include __DIR__ . '/..'.'/squizlabs/php_codesniffer/bin/phpcbf'; diff --git a/vendor/bin/phpcs b/vendor/bin/phpcs new file mode 100755 index 00000000..5123b7d6 --- /dev/null +++ b/vendor/bin/phpcs @@ -0,0 +1,117 @@ +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) { + include("phpvfscomposer://" . __DIR__ . '/..'.'/squizlabs/php_codesniffer/bin/phpcs'); + exit(0); + } +} + +include __DIR__ . '/..'.'/squizlabs/php_codesniffer/bin/phpcs'; diff --git a/vendor/bin/phpstan b/vendor/bin/phpstan new file mode 100755 index 00000000..7546edab Binary files /dev/null and b/vendor/bin/phpstan differ diff --git a/vendor/bin/phpunit b/vendor/bin/phpunit new file mode 100755 index 00000000..c52ed8c3 --- /dev/null +++ b/vendor/bin/phpunit @@ -0,0 +1,120 @@ +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = 'phpvfscomposer://'.$this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + $data = str_replace('__DIR__', var_export(dirname($this->realpath), true), $data); + $data = str_replace('__FILE__', var_export($this->realpath, true), $data); + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) { + include("phpvfscomposer://" . __DIR__ . '/..'.'/phpunit/phpunit/phpunit'); + exit(0); + } +} + +include __DIR__ . '/..'.'/phpunit/phpunit/phpunit'; diff --git a/vendor/civicrm/composer-downloads-plugin/.github/workflows/main.yml b/vendor/civicrm/composer-downloads-plugin/.github/workflows/main.yml new file mode 100644 index 00000000..026f0d72 --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/.github/workflows/main.yml @@ -0,0 +1,36 @@ +name: PHP Composer + +on: + push: + pull_request: + branches: [ master ] + +jobs: + phpunit: + runs-on: ${{ matrix.os }} + strategy: + matrix: + php: [7.4, 7.3] + os: [ubuntu-latest] + composer: [v1, v2] + name: ${{ matrix.php }} - PHPUnit - Composer ${{ matrix.composer }} + steps: + - uses: actions/checkout@v2 + - uses: actions/cache@v2 + with: + path: | + ~/.composer/cache/files + ~/.composer/cache/repo + key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: dom, curl, libxml, mbstring, zip, pdo, mysql, pdo_mysql, bcmath, soap, intl, gd, exif, iconv + coverage: none + tools: composer:${{ matrix.composer }} + - name: Validate composer.json + run: composer validate + - name: Install dependencies + run: composer install --prefer-dist --no-progress --no-suggest + - name: Run tests + run: ./vendor/bin/phpunit diff --git a/vendor/civicrm/composer-downloads-plugin/.gitignore b/vendor/civicrm/composer-downloads-plugin/.gitignore new file mode 100644 index 00000000..4a45ef5f --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/.gitignore @@ -0,0 +1,3 @@ +vendor +composer.lock +.php_cs.cache diff --git a/vendor/civicrm/composer-downloads-plugin/.php_cs.dist b/vendor/civicrm/composer-downloads-plugin/.php_cs.dist new file mode 100644 index 00000000..b2de1a8c --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/.php_cs.dist @@ -0,0 +1,22 @@ + + +This source file is subject to the MIT license that is bundled +with this source code in the file LICENSE. +EOF; + +return PhpCsFixer\Config::create() + ->setRiskyAllowed(true) + ->setRules([ + '@Symfony' => true, + '@Symfony:risky' => true, + 'header_comment' => ['header' => $header], + ]) + ->setFinder( + PhpCsFixer\Finder::create() + ->in([__DIR__.'/src', __DIR__.'/tests']) + ); diff --git a/vendor/civicrm/composer-downloads-plugin/LICENSE b/vendor/civicrm/composer-downloads-plugin/LICENSE new file mode 100644 index 00000000..eda17bec --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/LICENSE @@ -0,0 +1,20 @@ +(c) 2017 Last Call Media, Rob Bayliss +(c) 2019 CiviCRM LLC, Tim Otten + +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/civicrm/composer-downloads-plugin/README.md b/vendor/civicrm/composer-downloads-plugin/README.md new file mode 100644 index 00000000..7ca12bfa --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/README.md @@ -0,0 +1,160 @@ +Composer Downloads Plugin +=========================== + +The "Downloads" plugin allows you to download extra files (`*.zip` or `*.tar.gz`) and extract them within your package. + +This is an updated version of [lastcall/composer-extra-files](https://github.com/LastCallMedia/ComposerExtraFiles/). +It adds integration tests, fixes some bugs, and makes a few other improvements. Some of the +configuration options have changed, so it has been renamed to prevent it from conflicting in real-world usage. + +## Example + +Suppose you publish a PHP package `foo/bar` which relies on an external artifact `examplelib-0.1.zip`. Place this configuration in the `composer.json` for `foo/bar`: + +```json +{ + "name": "foo/bar", + "require": { + "civicrm/composer-downloads-plugin": "~2.1" + }, + "extra": { + "downloads": { + "examplelib": { + "url": "https://example.com/examplelib-0.1.zip", + "path": "extern/examplelib", + "ignore": ["test", "doc", ".*"] + } + } + } +} +``` + +When a downstream user of `foo/bar` runs `composer install`, it will fetch and extract the zip file, creating `vendor/foo/bar/extern/examplelib`. + +## Evaluation + +The primary strengths of `composer-downloads-plugin` are: + +* __Simple__: It downloads a URL (ZIP/TAR file) and extracts it. It only needs to know two things: *what to download* (`url`) and *where to put it* (`path`). It runs as pure-PHP without any external dependencies. +* __Fast__: The logic does not require scanning, indexing, or mapping any large registries. The download system uses `composer`'s built-in cache. +* __Isolated__: As the author of a package `foo/bar`, you define the content under the `vendor/foo/bar` folder. When others use `foo/bar`, there is no need for special instructions, no root-level configuration, no interaction with other packages. + +The "Downloads" plugin is only a download mechanism. Use it to *assimilate* an external resource as part of a `composer` package. + +The "Downloads" plugin is __not__ a *dependency management system*. There is no logic to scan registries, resolve transitive dependencies, identify version-conflicts, etc among diverse external resources. If you need that functionality, then you may want a *bridge* to integrate `composer` with an external dependency management tool. A few good bridges to consider: + +* [Asset Packagist](https://asset-packagist.org/) +* [Composer Asset Plugin](https://github.com/fxpio/composer-asset-plugin) +* [Composer Bower Plugin](https://github.com/php-kit/composer-bower-plugin) +* [Foxy](https://github.com/fxpio/foxy) + +## Configuration: Properties + +The `extra.downloads` section contains a list of files to download. Each extra-file has a symbolic ID (e.g. `examplelib` above) and some mix of properties: + +* `url`: The URL to fetch the content from. + +* `path`: The releative path where content will be extracted. + +* `type`: (*Optional*) Determines how the download is handled + * `archive`: The `url` references a zip or tarball which should be extracted at the given `path`. (Default for URLs involving `*.zip`, `*.tar.gz`, or `*.tgz`.) + * `file`: The `url` should be downloaded to the given `path`. (Default for all other URLs.) + * `phar`: The `url` references a PHP executable which should be installed at the given `path`. + +* `ignore`: (*Optional*) A list of a files that should be omited from the extracted folder. (This supports a subset of `.gitignore` notation.) + +* `version`: (*Optional*) A version number for the downloaded artifact. This has no functional impact on the lifecycle of the artifact, but + it can affect the console output, and it can be optionally used as a variable when setting `url` or `path`. + +Values in `url` and `path` support the following variables: + +* `{$id}`: The symbolic identifier of the download. (In the introductory example, it would be `examplelib`.) +* `{$version}`: The displayed/simulated/pretty version number of the package. + +## Configuration: Defaults + +You may set default properties for all downloads. Place them under `*`, as in: + +```json +{ + "extra": { + "downloads": { + "*": { + "path": "bower_components/{$id}", + "ignore": ["test", "tests", "doc", "docs"] + }, + "jquery": { + "url": "https://github.com/jquery/jquery-dist/archive/1.12.4.zip" + }, + "jquery-ui": { + "url": "https://github.com/components/jqueryui/archive/1.12.1.zip" + } + } + } +} +``` + +This example will: + +* Create `bower_components/jquery` (based on jQuery 1.12.4), minus any test/doc folders. +* Create `bower_components/jquery-ui` (based on jQueryUI 1.12.1), minus any test/doc folders. + +## Tips + +* In each downloaded folder, this plugin will create a small metadata folder (`.composer-downloads`) to track the origin of the current code. If you modify the `composer.json` to use a different URL, then it will re-download the file. + +* Download each extra file to a distinct `path`. Don't try to download into overlapping paths. (*This has not been tested, but I expect downloads are not well-ordered, and you may find that updates require re-downloading.*) + +* What should you do if you *normally* download the extra-file as `*.tar.gz` but sometimes (for local dev) need to grab bleeding edge content from somewhere else? Simply delete the autodownloaded folder and replace it with your own. `composer-downloads-plugin` will detect that conflict (by virtue of the absent `.composer-downloads`) and leave your code in place (until you choose to get rid of it). To switch back, you can simply delete the code and run `composer install` again. + +## Known Limitations + +If you use `downloads` in a root-project (or in symlinked dev repo), it will create+update downloads, but it will not remove orphaned items automatically. This could be addressed by doing a file-scan for `.composer-downloads` (and deleting any orphan folders). Since the edge-case is not particularly common right now, and since a file-scan could be time-consuming, it might make sense as a separate subcommand. + +I believe the limitation does *not* affect downstream consumers of a dependency. In that case, the regular `composer` install/update/removal mechanics should take care of any nested downloads. + +## Automated Tests + +The `tests/` folder includes unit-tests and integration-tests written with +PHPUnit. Each integration-test generates a new folder/project with a +plausible, representative `composer.json` file and executes `composer +install`. It checks the output has the expected files. + +To run the tests, you will need `composer` and `phpunit` in the `PATH`. + +``` +[~/src/composer-downloads-plugin] which composer +/Users/myuser/bin/composer + +[~/src/composer-downloads-plugin] which phpunit +/Users/myuser/bin/phpunit + +[~/src/composer-downloads-plugin] phpunit +PHPUnit 5.7.27 by Sebastian Bergmann and contributors. + +..... 5 / 5 (100%) + +Time: 40.35 seconds, Memory: 10.00MB + +OK (5 tests, 7 assertions) +``` + +The integration tests can be a bit large/slow. To monitor the tests more +closesly, set the `DEBUG` variable, as in: + +``` +[~/src/composer-downloads-plugin] env DEBUG=2 phpunit +``` + +## Local Dev Harness + +What if you want to produce an environment which uses the current plugin +code - one where you can quickly re-run `composer` commands while +iterating on code? + +You may use any of the integration-tests to initialize a baseline +environment: + +``` +env USE_TEST_PROJECT=$HOME/src/myprj DEBUG=2 phpunit tests/SniffTest.php +``` diff --git a/vendor/civicrm/composer-downloads-plugin/circle.yml b/vendor/civicrm/composer-downloads-plugin/circle.yml new file mode 100644 index 00000000..54042d67 --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/circle.yml @@ -0,0 +1,24 @@ +version: 2 +jobs: + build: + working_directory: /srv + docker: + - image: lastcallmedia/php:7.0-dev + steps: + - checkout + - restore_cache: + key: composer-v1-{{ checksum "composer.json" }} + - run: composer install + - save_cache: + key: composer-v1-{{ checksum "composer.json" }} + paths: [vendor, composer.lock] + - run: | + COMMIT_RANGE=`echo $CIRCLE_COMPARE_URL | cut -d/ -f7` + IFS=$'\n'; COMMIT_SCA_FILES=($(git diff --name-only --diff-filter=ACMRTUXB "${COMMIT_RANGE}")); unset IFS + vendor/bin/php-cs-fixer fix --config=.php_cs.dist -v --dry-run --stop-on-violation --using-cache=no --path-mode=intersection -- "${COMMIT_SCA_FILES[@]}" + - run: | + composer validate + - run: mkdir -p /phpunit + - run: vendor/bin/phpunit --log-junit=/phpunit/junit.xml + - store_test_results: + path: /phpunit \ No newline at end of file diff --git a/vendor/civicrm/composer-downloads-plugin/composer.json b/vendor/civicrm/composer-downloads-plugin/composer.json new file mode 100644 index 00000000..6e51f4d5 --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/composer.json @@ -0,0 +1,40 @@ +{ + "name": "civicrm/composer-downloads-plugin", + "description": "Composer plugin for downloading additional files within any composer package.", + "type": "composer-plugin", + "license": "MIT", + "authors": [ + { + "name": "Rob Bayliss", + "email": "rob@lastcallmedia.com" + }, + { + "name": "Tim Otten", + "email": "totten@civicrm.org" + } + ], + "require": { + "composer-plugin-api": "^1.1 || ^2.0", + "php": ">=5.6", + "togos/gitignore": "~1.1.1" + }, + "require-dev": { + "composer/composer": "~1.0 || ~2.0", + "phpunit/phpunit": "^5.7", + "friendsofphp/php-cs-fixer": "^2.3", + "totten/process-helper": "^1.0.1" + }, + "autoload": { + "psr-4": { + "LastCall\\DownloadsPlugin\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "LastCall\\DownloadsPlugin\\Tests\\": "tests/" + } + }, + "extra": { + "class": "LastCall\\DownloadsPlugin\\Plugin" + } +} diff --git a/vendor/civicrm/composer-downloads-plugin/phpunit.xml b/vendor/civicrm/composer-downloads-plugin/phpunit.xml new file mode 100644 index 00000000..c9f9021f --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/phpunit.xml @@ -0,0 +1,16 @@ + + + + + + tests + + + + + + ./src/*/ + + + + \ No newline at end of file diff --git a/vendor/civicrm/composer-downloads-plugin/src/DownloadsParser.php b/vendor/civicrm/composer-downloads-plugin/src/DownloadsParser.php new file mode 100644 index 00000000..614882e9 --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/src/DownloadsParser.php @@ -0,0 +1,78 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace LastCall\DownloadsPlugin; + +use Composer\Package\PackageInterface; +use LastCall\DownloadsPlugin\Handler\ArchiveHandler; +use LastCall\DownloadsPlugin\Handler\BaseHandler; +use LastCall\DownloadsPlugin\Handler\FileHandler; +use LastCall\DownloadsPlugin\Handler\PharHandler; + +class DownloadsParser +{ + + /** + * @param \Composer\Package\PackageInterface $package + * + * @return BaseHandler[] + * Each item is a specification of an extra file, with defaults and variables evaluated. + */ + public function parse(PackageInterface $package, $basePath) + { + $extraFiles = []; + $extra = $package->getExtra(); + + $defaults = isset($extra['downloads']['*']) ? $extra['downloads']['*'] : []; + + if (!empty($extra['downloads'])) { + foreach ((array) $extra['downloads'] as $id => $extraFile) { + if ($id === '*') continue; + + $extraFile = array_merge($defaults, $extraFile); + $extraFile['id'] = $id; + foreach (['url', 'path'] as $prop) { + if (isset($extraFile[$prop])) { + $extraFile[$prop] = strtr($extraFile[$prop], [ + '{$id}' => $extraFile['id'], + '{$version}' => isset($extraFile['version']) ? $extraFile['version'] : '', + ]); + } + } + + $class = $this->pickClass($extraFile); + $extraFiles[] = new $class($package, $basePath, $extraFile); + } + } + + return $extraFiles; + } + + public function pickClass($extraFile) + { + $types = [ + 'archive' => ArchiveHandler::CLASS, + 'file' => FileHandler::CLASS, + 'phar' => PharHandler::CLASS, + ]; + if (isset($extraFile['type'], $types[$extraFile['type']])) { + return $types[$extraFile['type']]; + } + + $parts = parse_url($extraFile['url']); + $filename = pathinfo($parts['path'], PATHINFO_BASENAME); + if (preg_match('/\.(zip|tar\.gz|tgz)$/', $filename)) { + return $types['archive']; + } + + return $types['file']; + } +} diff --git a/vendor/civicrm/composer-downloads-plugin/src/GlobCleaner.php b/vendor/civicrm/composer-downloads-plugin/src/GlobCleaner.php new file mode 100644 index 00000000..0e7aaad6 --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/src/GlobCleaner.php @@ -0,0 +1,57 @@ + \TOGoS_GitIgnore_Ruleset::loadFromStrings($ignores), + 'invertRulesetResult' => false, + 'defaultResult' => false, + 'includeDirectories' => false, + 'callback' => function($file, $match) use ($baseDir, &$dirs) { + if ($match) { + unlink("$baseDir/$file"); + $dir = dirname($file); + if ($dir !== '.') { + $dirs[dirname($file)] = 1; + } + } + } + )); + $finder->findFiles($baseDir); + + // Cleanup any empy directories + $dirNames = array_keys($dirs); + $byLength = function ($a, $b) { + return strlen($b) - strlen($a); + }; + usort($dirNames, $byLength); + + while ($dirName = array_shift($dirNames)) { + if (!glob("$baseDir/$dirName/*")) { + @rmdir("$baseDir/$dirName"); + $dirNames[] = dirname($dirName); + usort($dirNames, $byLength); + } + } + } + + +} \ No newline at end of file diff --git a/vendor/civicrm/composer-downloads-plugin/src/Handler/ArchiveHandler.php b/vendor/civicrm/composer-downloads-plugin/src/Handler/ArchiveHandler.php new file mode 100644 index 00000000..f9a8f52a --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/src/Handler/ArchiveHandler.php @@ -0,0 +1,89 @@ +setDistType($this->parseDistType($this->extraFile['url'])); + return $pkg; + } + + protected function parseDistType($url) + { + $parts = parse_url($url); + $filename = pathinfo($parts['path'], PATHINFO_BASENAME); + if (preg_match('/\.zip$/', $filename)) { + return 'zip'; + } elseif (preg_match('/\.(tar\.gz|tgz)$/', $filename)) { + return 'tar'; + } else { + throw new \RuntimeException("Failed to determine archive type for $filename"); + } + } + + public function getTrackingFile() + { + $file = basename($this->extraFile['id']) . '-' . md5($this->extraFile['id']) . '.json'; + return + $this->getTargetPath() . + DIRECTORY_SEPARATOR . self::DOT_DIR . + DIRECTORY_SEPARATOR . $file; + } + + public function createTrackingData() + { + $meta = parent::createTrackingData(); + $meta['ignore'] = $this->findIgnores(); + return $meta; + } + + + public function getChecksum() { + $ignore = empty($this->extraFile['ignore']) ? [] : array_values($this->extraFile['ignore']); + sort($ignore); + return hash('sha256', parent::getChecksum() . serialize($ignore)); + } + + /** + * @return string[]|NULL + * List of files to exclude. Use '**' to match subdirectories. + * Ex: ['.gitignore', '*.md'] + */ + public function findIgnores() + { + return isset($this->extraFile['ignore']) + ? $this->extraFile['ignore'] + : NULL; + } + + /** + * @param Composer $composer + * @param IOInterface $io + */ + public function download(Composer $composer, IOInterface $io) + { + $targetPath = $this->getTargetPath(); + $downloadManager = $composer->getDownloadManager(); + + // In composer:v2, download and extract were separated. + $version = method_exists(Composer::class, 'getVersion') ? Composer::getVersion() : Composer::VERSION; + if (version_compare($version, '2.0.0') >= 0) { + $promise = $downloadManager->download($this->getSubpackage(), $targetPath); + $composer->getLoop()->wait([$promise]); + $promise = $downloadManager->install($this->getSubpackage(), $targetPath); + $composer->getLoop()->wait([$promise]); + } else { + $downloadManager->download($this->getSubpackage(), $targetPath); + } + GlobCleaner::clean($io, $targetPath, $this->findIgnores()); + } + +} diff --git a/vendor/civicrm/composer-downloads-plugin/src/Handler/BaseHandler.php b/vendor/civicrm/composer-downloads-plugin/src/Handler/BaseHandler.php new file mode 100644 index 00000000..032cc99e --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/src/Handler/BaseHandler.php @@ -0,0 +1,145 @@ +parent = $parent; + $this->parentPath = $parentPath; + $this->extraFile = $extraFile; + } + + public function getSubpackage() { + if ($this->subpackage === NULL) { + $this->subpackage = $this->createSubpackage(); + } + return $this->subpackage; + } + + /** + * @return Subpackage + */ + public function createSubpackage() + { + $versionParser = new VersionParser(); + $extraFile = $this->extraFile; + $parent = $this->parent; + + if (isset($extraFile['version'])) { + // $version = $versionParser->normalize($extraFile['version']); + $version = $versionParser->normalize(self::FAKE_VERSION); + $prettyVersion = $extraFile['version']; + } + elseif ($parent instanceof RootPackageInterface) { + $version = $versionParser->normalize(self::FAKE_VERSION); + $prettyVersion = self::FAKE_VERSION; + } + else { + $version = $parent->getVersion(); + $prettyVersion = $parent->getPrettyVersion(); + } + + $package = new Subpackage( + $parent, + $extraFile['id'], + $extraFile['url'], + NULL, + $extraFile['path'], + $version, + $prettyVersion + ); + + return $package; + } + + public function createTrackingData() { + return [ + 'name' => $this->getSubpackage()->getName(), + 'url' => $this->getSubpackage()->getDistUrl(), + 'checksum' => $this->getChecksum(), + ]; + } + + /** + * @return string + * A unique identifier for this configuration of this asset. + * If the identifier changes, that implies that the asset should be + * replaced/redownloaded. + */ + public function getChecksum() { + $extraFile = $this->extraFile; + return hash('sha256', serialize([ + get_class($this), + $extraFile['id'], + $extraFile['url'], + $extraFile['path'], + ])); + } + + /** + * @return string + */ + public function getTargetPath() + { + return $this->parentPath . '/' . $this->extraFile['path']; + } + + /** + * @param Composer $composer + * @param IOInterface $io + */ + abstract public function download(Composer $composer, IOInterface $io); + + /** + * @return string + */ + abstract public function getTrackingFile(); + +} \ No newline at end of file diff --git a/vendor/civicrm/composer-downloads-plugin/src/Handler/FileHandler.php b/vendor/civicrm/composer-downloads-plugin/src/Handler/FileHandler.php new file mode 100644 index 00000000..299a0178 --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/src/Handler/FileHandler.php @@ -0,0 +1,77 @@ +setDistType('file'); + return $pkg; + } + + public function getTrackingFile() + { + $file = basename($this->extraFile['id']) . '-' . md5($this->extraFile['id']) . '.json'; + return + dirname($this->getTargetPath()) . + DIRECTORY_SEPARATOR . self::DOT_DIR . + DIRECTORY_SEPARATOR . $file; + } + + /** + * @param Composer $composer + * @param IOInterface $io + */ + public function download(Composer $composer, IOInterface $io) { + // We want to take advantage of the cache in composer's downloader, but it + // doesn't put the file the spot we want, so we shuffle a bit. + + $cfs = new Filesystem(); + $target = $this->getTargetPath(); + $tmpDir = dirname($target) . DIRECTORY_SEPARATOR . self::TMP_PREFIX . basename($target); + + if (file_exists($tmpDir)) { + $cfs->remove($tmpDir); + } + if (file_exists($target)) { + $cfs->remove($target); + } + + $pkg = clone $this->getSubpackage(); + $pkg->setTargetDir($tmpDir); + $downloadManager = $composer->getDownloadManager(); + // composer:v2 + $version = method_exists(Composer::class, 'getVersion') ? Composer::getVersion() : Composer::VERSION; + if (version_compare($version, '2.0.0') >= 0) { + $file = ''; + $promise = $downloadManager->download($pkg, $tmpDir); + $promise->then(static function($res) use (&$file) { + $file = $res; + }); + $composer->getLoop()->wait([$promise]); + $cfs->rename($file, $target); + $cfs->remove($tmpDir); + } + // composer:v1 + else { + $downloadManager->download($pkg, $tmpDir); + foreach ((array)glob("$tmpDir/*") as $file) { + if (is_file($file)) { + $cfs->rename($file, $target); + $cfs->remove($tmpDir); + break; + } + } + } + } + +} diff --git a/vendor/civicrm/composer-downloads-plugin/src/Handler/PharHandler.php b/vendor/civicrm/composer-downloads-plugin/src/Handler/PharHandler.php new file mode 100644 index 00000000..450fbe32 --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/src/Handler/PharHandler.php @@ -0,0 +1,28 @@ +getTargetPath(), 0777 ^ umask()); + } + } + + +} diff --git a/vendor/civicrm/composer-downloads-plugin/src/Plugin.php b/vendor/civicrm/composer-downloads-plugin/src/Plugin.php new file mode 100644 index 00000000..23def5b0 --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/src/Plugin.php @@ -0,0 +1,141 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace LastCall\DownloadsPlugin; + +use Composer\Composer; +use Composer\EventDispatcher\EventSubscriberInterface; +use Composer\Installer\PackageEvent; +use Composer\Installer\PackageEvents; +use Composer\IO\IOInterface; +use Composer\Package\Package; +use Composer\Package\PackageInterface; +use Composer\Plugin\PluginInterface; +use Composer\Script\Event; +use Composer\Script\ScriptEvents; +use LastCall\DownloadsPlugin\Handler\BaseHandler; + +class Plugin implements PluginInterface, EventSubscriberInterface +{ + + /** @var Composer */ + private $composer; + /** @var IOInterface */ + private $io; + + private $parser; + + public function __construct() + { + $this->parser = new DownloadsParser(); + } + + public static function getSubscribedEvents() + { + return [ + PackageEvents::POST_PACKAGE_INSTALL => ['installDownloads', 10], + PackageEvents::POST_PACKAGE_UPDATE => ['updateDownloads', 10], + ScriptEvents::POST_INSTALL_CMD => ['installDownloadsRoot', 10], + ScriptEvents::POST_UPDATE_CMD => ['installDownloadsRoot', 10], + ]; + } + + public function installDownloadsRoot(Event $event) { + $rootPackage = $this->composer->getPackage(); + $this->installUpdateDownloads(getcwd(), $rootPackage); + + // Ensure that any other packages are properly reconciled. + $localRepo = $this->composer->getRepositoryManager()->getLocalRepository(); + $installationManager = $this->composer->getInstallationManager(); + foreach ($localRepo->getCanonicalPackages() as $package) { + /** @var \Composer\Package\PackageInterface $package */ + if (!empty($package->getExtra()['downloads'])) { + $this->installUpdateDownloads($installationManager->getInstallPath($package), $package); + } + } + } + public function installDownloads(PackageEvent $event) + { + /** @var \Composer\Package\PackageInterface $package */ + $package = $event->getOperation()->getPackage(); + $installationManager = $event->getComposer()->getInstallationManager(); + $this->installUpdateDownloads($installationManager->getInstallPath($package), $package); + } + + public function updateDownloads(PackageEvent $event) + { + /** @var \Composer\Package\PackageInterface $package */ + $package = $event->getOperation()->getTargetPackage(); + $installationManager = $event->getComposer()->getInstallationManager(); + $this->installUpdateDownloads($installationManager->getInstallPath($package), $package); + } + + public function activate(Composer $composer, IOInterface $io) + { + $this->composer = $composer; + $this->io = $io; + } + + public function deactivate(Composer $composer, IOInterface $io) + { + // @todo determine if any operation required. + } + + public function uninstall(Composer $composer, IOInterface $io) + { + // @todo determine if any operation required. + } + + /** + * @param string $basePath + * @param PackageInterface $package + */ + protected function installUpdateDownloads($basePath, $package) + { + $first = TRUE; + foreach ($this->parser->parse($package, $basePath) as $extraFileHandler) { + /** @var BaseHandler $extraFileHandler */ + $extraFilePkg = $extraFileHandler->getSubpackage(); + $targetPath = $extraFileHandler->getTargetPath(); + $trackingFile = $extraFileHandler->getTrackingFile(); + + if (file_exists($targetPath) && !file_exists($trackingFile)) { + $this->io->write(sprintf("Extra file %s has been locally overriden in %s. To reset it, delete and reinstall.", $extraFilePkg->getName(), $extraFilePkg->getTargetDir()), TRUE); + continue; + } + + if (file_exists($targetPath) && file_exists($trackingFile)) { + $meta = @json_decode(file_get_contents($trackingFile), 1); + if (isset($meta['checksum']) && $meta['checksum'] === $extraFileHandler->getChecksum()) { + $this->io->write(sprintf("Skip extra file %s", $extraFilePkg->getName()), TRUE, IOInterface::VERY_VERBOSE); + continue; + } + } + + if ($first) { + $this->io->write(sprintf("Download extra files for %s", $package->getName())); + $first = FALSE; + } + + $this->io->write(sprintf("Download extra file %s", $extraFilePkg->getName()), TRUE, IOInterface::VERBOSE); + $extraFileHandler->download($this->composer, $this->io); + + if (!file_exists(dirname($trackingFile))) { + mkdir(dirname($trackingFile), 0777, TRUE); + } + file_put_contents($trackingFile, json_encode( + $extraFileHandler->createTrackingData(), + JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES + )); + } + } + +} diff --git a/vendor/civicrm/composer-downloads-plugin/src/Subpackage.php b/vendor/civicrm/composer-downloads-plugin/src/Subpackage.php new file mode 100644 index 00000000..62d4b754 --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/src/Subpackage.php @@ -0,0 +1,48 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace LastCall\DownloadsPlugin; + +use Composer\IO\IOInterface; +use Composer\Package\Package; +use Composer\Package\PackageInterface; +use Composer\Package\RootPackageInterface; + +/** + * Class Subpackage + * @package LastCall\DownloadsPlugin + * + * A subpackage is simulated package which lives beneath some parent package. + */ +class Subpackage extends Package +{ + + /** + * @var PackageInterface + */ + private $parent; + + public function __construct(PackageInterface $parent, $id, $url, $type, $path, $version = NULL, $prettyVersion = NULL) + { + parent::__construct( + sprintf('%s:%s', $parent->getName(), $id), + $version ? $version : $parent->getVersion(), + $prettyVersion ? $prettyVersion : $parent->getPrettyVersion() + ); + $this->parent = $parent; + $this->id = $id; + $this->setDistUrl($url); + $this->setDistType($type); + $this->setTargetDir($path); + $this->setInstallationSource('dist'); + } + +} diff --git a/vendor/civicrm/composer-downloads-plugin/tests/DownloadsParserTest.php b/vendor/civicrm/composer-downloads-plugin/tests/DownloadsParserTest.php new file mode 100644 index 00000000..039d38ee --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/tests/DownloadsParserTest.php @@ -0,0 +1,72 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace LastCall\DownloadsPlugin\Tests; + +use Composer\Package\Package; +use LastCall\DownloadsPlugin\Subpackage; +use LastCall\DownloadsPlugin\DownloadsParser; +use PHPUnit\Framework\TestCase; + +class DownloadsParserTest extends TestCase +{ + private function getPackage(array $extra = []) + { + $package = new Package('foo', '1.0.0', '1.0.0'); + $package->setExtra([ + 'downloads' => $extra, + ]); + + return $package; + } + + public function testIgnoresPackagesWithoutDownloads() + { + $package = new Package('foo', '1.0.0', '1.0.0'); + $parser = new DownloadsParser(); + $this->assertEquals([], $parser->parse($package, "/EXAMPLE")); + } + + public function testAddsFiles() + { + $package = $this->getPackage([ + 'bar' => ['url' => 'foo', 'path' => 'bar'], + ]); + $expectSubpackage = new Subpackage($package, 'bar', 'foo', 'file', 'bar'); + $actualSubpackage = (new DownloadsParser())->parse($package, "/EXAMPLE")[0]->getSubpackage(); + $this->assertEquals([$expectSubpackage], [$actualSubpackage]); + } + + public function getDownloadTypeTests() + { + return [ + ['zip', 'foo.zip'], + ['zip', 'foo.zip?foo'], + ['zip', 'http://example.com/foo.zip?abc#def'], + ['tar', 'foo.tar.gz'], + ['tar', 'http://example.com/foo.tar.gz?abc#def'], + ['tar', 'foo.tgz'], + ['file', 'foo'], + ]; + } + + /** + * @dataProvider getDownloadTypeTests + */ + public function testSetsDownloadType($expectedType, $url) + { + $package = $this->getPackage([ + 'bar' => ['url' => $url, 'path' => 'bar'], + ]); + $parsed = (new DownloadsParser())->parse($package, "/EXAMPLE"); + $this->assertEquals($expectedType, $parsed[0]->getSubpackage()->getDistType()); + } +} diff --git a/vendor/civicrm/composer-downloads-plugin/tests/IntegrationTestCase.php b/vendor/civicrm/composer-downloads-plugin/tests/IntegrationTestCase.php new file mode 100644 index 00000000..8a56103d --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/tests/IntegrationTestCase.php @@ -0,0 +1,140 @@ + [ + [ + 'name' => 'Tester McFakus', + 'email' => 'tester@example.org', + ], + ], + + 'repositories' => [ + 'composer-downloads-plugin' => [ + 'type' => 'path', + 'url' => self::getPluginSourceDir(), + ], + ], + ]; + } + + /** + * @return string + * The root folder of the composer-downloads-plugin. + */ + public static function getPluginSourceDir() + { + return dirname(__DIR__); + } + + /** + * @return string + * The path of the autogenerated composer project. + */ + public static function getTestDir() + { + return self::$testDir; + } + + private static $origDir; + private static $testDir; + + /** + * Create a temp folder with a "composer.json" file and chdir() into it. + * + * @param array $composerJson + * @return string + */ + public static function initTestProject($composerJson) + { + self::$origDir = getcwd(); + if (getenv('USE_TEST_PROJECT')) { + self::$testDir = getenv('USE_TEST_PROJECT'); + @unlink(self::$testDir . DIRECTORY_SEPARATOR . 'composer.lock'); + } else { + self::$testDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'assetplg-' . md5(__DIR__ . time() . rand(0, 10000)); + self::cleanDir(self::$testDir); + } + + if (!is_dir(self::$testDir)) { + mkdir(self::$testDir); + } + file_put_contents(self::$testDir . DIRECTORY_SEPARATOR . 'composer.json', json_encode($composerJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); + chdir(self::$testDir); + return self::$testDir; + } + + public static function tearDownAfterClass() + { + parent::tearDownAfterClass(); + + if (self::$testDir) { + chdir(self::$origDir); + self::$origDir = NULL; + + if (getenv('USE_TEST_PROJECT')) { + fwrite(STDERR, sprintf("\n\nTest project location (%s): %s\n", __CLASS__, self::$testDir)); + } else { + self::cleanDir(self::$testDir); + } + self::$testDir = NULL; + } + } + + /** + * If a directory exists, remove it. + * + * @param string $dir + */ + protected static function cleanDir($dir) + { + PH::runOk(['if [ -d @DIR ]; then rm -rf @DIR ; fi', 'DIR' => $dir]); + } + + public function assertSameFileContent($expected, $actual) + { + $this->assertEquals(file_get_contents($expected), file_get_contents($actual)); + } + + public function assertFileIsSymlink($path) + { + $this->assertTrue(file_exists($path), "Path ($path) should exist (symlink file)"); + $this->assertTrue(is_link($path), "Path ($path) should be a symlink"); + + $linkTgt = readlink($path); + $this->assertTrue(is_string($linkTgt)); + $this->assertTrue(is_file(dirname($path) . '/' . $linkTgt), "Path ($path) should be symlinking pointing to a file. Found tgt ($linkTgt)"); + } + + public function assertFileIsNormal($path) + { + $this->assertTrue(file_exists($path), "Path ($path) should exist (normal file)"); + $this->assertTrue(is_file($path), "Path ($path) should be a normal file"); + $this->assertTrue(!is_link($path), "Path ($path) should not be a symlink"); + } + + public function assertDirIsSymlink($path) + { + $this->assertTrue(file_exists($path), "Path ($path) should exist (symlink dir)"); + $this->assertTrue(is_link($path), "Path ($path) should be a symlink"); + + $linkTgt = readlink($path); + $this->assertTrue(is_string($linkTgt)); + $this->assertTrue(is_dir(dirname($path) . '/' . $linkTgt), "Path ($path) should be symlinking pointing to a dir. Found tgt ($linkTgt"); + } + + public function assertDirIsNormal($path) + { + $this->assertTrue(file_exists($path), "Path ($path) should exist (normal dir)"); + $this->assertTrue(!is_link($path), "Path ($path) should not be a symlink"); + $this->assertTrue(is_dir($path), "Path ($path) should be a dir"); + } + +} diff --git a/vendor/civicrm/composer-downloads-plugin/tests/SniffTest.php b/vendor/civicrm/composer-downloads-plugin/tests/SniffTest.php new file mode 100644 index 00000000..49eaf17c --- /dev/null +++ b/vendor/civicrm/composer-downloads-plugin/tests/SniffTest.php @@ -0,0 +1,112 @@ + 'test/sniff-test', + 'require' => [ + 'civicrm/composer-downloads-plugin' => '@dev', + ], + 'minimum-stability' => 'dev', + 'extra' => [ + 'downloads' => [ + '*' => [ + 'path' => 'extern/{$id}', + ], + 'README' => [ + 'url' => 'https://github.com/composer/composer/raw/1.9.0/README.md', + 'path' => 'docs/README.md' + ], + 'jquery-full' => [ + 'url' => 'https://github.com/civicrm/jquery/archive/1.12.4-civicrm-1.2.zip', + ], + 'jquery-lesser' => [ + 'version' => '1.12.4-civicrm-1.2', + 'url' => 'https://github.com/civicrm/jquery/archive/{$version}.zip', + 'path' => 'extern/jquery-lesser', + 'ignore' => ['Gruntfile.js'] + ], + 'cv' => [ + 'type' => 'phar', + 'url' => 'https://download.civicrm.org/cv/cv.phar-2019-08-20-14fe9da8', + 'path' => 'bin/cv', + ], + ], + ], + ]; + } + + public static function setUpBeforeClass() { + parent::setUpBeforeClass(); + self::initTestProject(static::getComposerJson()); + $composer_path = self::getComposerPath(); + PH::runOk("$composer_path install -v"); + } + + public function getExampleChecksums() { + return [ + ['docs/README.md', 'docs/README.md', '1d0577cc52d55f0680b431184e898f0cbcb927e52e843a319d7122db9be72813'], + ['extern/jquery-full', 'extern/jquery-full/dist/jquery.js', '5f2caf09052782caf67e1772c0abce31747ffbc7a1c50690e331b99c7d9ea8dc'], + ['extern/jquery-full', 'extern/jquery-full/Gruntfile.js', '3508ff74f8ef106a80f25f28f44a20c47a2b67d84396bb141928ff978ba4012e'], + ['extern/jquery-lesser', 'extern/jquery-lesser/dist/jquery.js', '5f2caf09052782caf67e1772c0abce31747ffbc7a1c50690e331b99c7d9ea8dc'], + ['extern/jquery-lesser', 'extern/jquery-lesser/Gruntfile.js', NULL], + ['bin/cv', 'bin/cv', 'bf162d5d7dd0bef087d7dd07f474039b2e25c4bcca328a2b2097958ac6294476'] + ]; + } + + /** + * Ensure that the file checksums match expectations with both (a) original download and (b) re-download. + * + * @param string $file + * @param string|NULL $sha256 + * The expected content of the file, or NULL if the file should not exist. + * @dataProvider getExampleChecksums + */ + public function testDownloadAndRedownload($path, $file, $sha256) { + // Initial download + $this->assertFileChecksum($file, $sha256, 'Initial'); + + // Force re-download + if (is_dir($path)) { + self::cleanDir($path); + } + else { + unlink($path); + } + $this->assertFileNotExists($file); + $composer_path = self::getComposerPath(); + PH::runOk("$composer_path install -v"); + + // And make sure it all worked out... + $this->assertFileChecksum($file, $sha256, 'Redownload'); + } + + public function assertFileChecksum($file, $sha256, $message = NULL) { + if ($sha256 === NULL) { + $this->assertFileNotExists($file, "($message) File should not exist"); + } + else { + $this->assertFileExists($file, "($message) File should exist"); + $this->assertEquals($sha256, hash('sha256', file_get_contents($file)), "($message) File should given checksum"); + } + } + + private static function getComposerPath() { + return realpath(__DIR__ . '/../vendor/bin/composer'); + } + +} diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index fce8549f..afef3fa2 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -37,57 +37,130 @@ * * @author Fabien Potencier * @author Jordi Boggiano - * @see http://www.php-fig.org/psr/psr-0/ - * @see http://www.php-fig.org/psr/psr-4/ + * @see https://www.php-fig.org/psr/psr-0/ + * @see https://www.php-fig.org/psr/psr-4/ */ class ClassLoader { + /** @var ?string */ + private $vendorDir; + // PSR-4 + /** + * @var array[] + * @psalm-var array> + */ private $prefixLengthsPsr4 = array(); + /** + * @var array[] + * @psalm-var array> + */ private $prefixDirsPsr4 = array(); + /** + * @var array[] + * @psalm-var array + */ private $fallbackDirsPsr4 = array(); // PSR-0 + /** + * @var array[] + * @psalm-var array> + */ private $prefixesPsr0 = array(); + /** + * @var array[] + * @psalm-var array + */ private $fallbackDirsPsr0 = array(); + /** @var bool */ private $useIncludePath = false; + + /** + * @var string[] + * @psalm-var array + */ private $classMap = array(); + + /** @var bool */ private $classMapAuthoritative = false; + + /** + * @var bool[] + * @psalm-var array + */ private $missingClasses = array(); + + /** @var ?string */ private $apcuPrefix; + /** + * @var self[] + */ + private static $registeredLoaders = array(); + + /** + * @param ?string $vendorDir + */ + public function __construct($vendorDir = null) + { + $this->vendorDir = $vendorDir; + } + + /** + * @return string[] + */ public function getPrefixes() { if (!empty($this->prefixesPsr0)) { - return call_user_func_array('array_merge', $this->prefixesPsr0); + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); } return array(); } + /** + * @return array[] + * @psalm-return array> + */ public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } + /** + * @return array[] + * @psalm-return array + */ public function getFallbackDirs() { return $this->fallbackDirsPsr0; } + /** + * @return array[] + * @psalm-return array + */ public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } + /** + * @return string[] Array of classname => path + * @psalm-return array + */ public function getClassMap() { return $this->classMap; } /** - * @param array $classMap Class to filename map + * @param string[] $classMap Class to filename map + * @psalm-param array $classMap + * + * @return void */ public function addClassMap(array $classMap) { @@ -102,9 +175,11 @@ public function addClassMap(array $classMap) * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void */ public function add($prefix, $paths, $prepend = false) { @@ -147,11 +222,13 @@ public function add($prefix, $paths, $prepend = false) * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException + * + * @return void */ public function addPsr4($prefix, $paths, $prepend = false) { @@ -195,8 +272,10 @@ public function addPsr4($prefix, $paths, $prepend = false) * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 base directories + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 base directories + * + * @return void */ public function set($prefix, $paths) { @@ -211,10 +290,12 @@ public function set($prefix, $paths) * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException + * + * @return void */ public function setPsr4($prefix, $paths) { @@ -234,6 +315,8 @@ public function setPsr4($prefix, $paths) * Turns on searching the include path for class files. * * @param bool $useIncludePath + * + * @return void */ public function setUseIncludePath($useIncludePath) { @@ -256,6 +339,8 @@ public function getUseIncludePath() * that have not been registered with the class map. * * @param bool $classMapAuthoritative + * + * @return void */ public function setClassMapAuthoritative($classMapAuthoritative) { @@ -276,6 +361,8 @@ public function isClassMapAuthoritative() * APCu prefix to use to cache found/not-found classes, if the extension is enabled. * * @param string|null $apcuPrefix + * + * @return void */ public function setApcuPrefix($apcuPrefix) { @@ -296,25 +383,44 @@ public function getApcuPrefix() * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); + + if (null === $this->vendorDir) { + return; + } + + if ($prepend) { + self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; + } else { + unset(self::$registeredLoaders[$this->vendorDir]); + self::$registeredLoaders[$this->vendorDir] = $this; + } } /** * Unregisters this instance as an autoloader. + * + * @return void */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); + + if (null !== $this->vendorDir) { + unset(self::$registeredLoaders[$this->vendorDir]); + } } /** * Loads the given class or interface. * * @param string $class The name of the class - * @return bool|null True if loaded, null otherwise + * @return true|null True if loaded, null otherwise */ public function loadClass($class) { @@ -323,6 +429,8 @@ public function loadClass($class) return true; } + + return null; } /** @@ -367,6 +475,21 @@ public function findFile($class) return $file; } + /** + * Returns the currently registered loaders indexed by their corresponding vendor directories. + * + * @return self[] + */ + public static function getRegisteredLoaders() + { + return self::$registeredLoaders; + } + + /** + * @param string $class + * @param string $ext + * @return string|false + */ private function findFileWithExtension($class, $ext) { // PSR-4 lookup @@ -438,6 +561,10 @@ private function findFileWithExtension($class, $ext) * Scope isolated include. * * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + * @private */ function includeFile($file) { diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php new file mode 100644 index 00000000..d50e0c9f --- /dev/null +++ b/vendor/composer/InstalledVersions.php @@ -0,0 +1,350 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer; + +use Composer\Autoload\ClassLoader; +use Composer\Semver\VersionParser; + +/** + * This class is copied in every Composer installed project and available to all + * + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions + * + * To require its presence, you can require `composer-runtime-api ^2.0` + */ +class InstalledVersions +{ + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + private static $installedByVendor = array(); + + /** + * Returns a list of all package names which are present, either by being installed, replaced or provided + * + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackages() + { + $packages = array(); + foreach (self::getInstalled() as $installed) { + $packages[] = array_keys($installed['versions']); + } + + if (1 === \count($packages)) { + return $packages[0]; + } + + return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); + } + + /** + * Returns a list of all package names with a specific type e.g. 'library' + * + * @param string $type + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackagesByType($type) + { + $packagesByType = array(); + + foreach (self::getInstalled() as $installed) { + foreach ($installed['versions'] as $name => $package) { + if (isset($package['type']) && $package['type'] === $type) { + $packagesByType[] = $name; + } + } + } + + return $packagesByType; + } + + /** + * Checks whether the given package is installed + * + * This also returns true if the package name is provided or replaced by another package + * + * @param string $packageName + * @param bool $includeDevRequirements + * @return bool + */ + public static function isInstalled($packageName, $includeDevRequirements = true) + { + foreach (self::getInstalled() as $installed) { + if (isset($installed['versions'][$packageName])) { + return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); + } + } + + return false; + } + + /** + * Checks whether the given package satisfies a version constraint + * + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: + * + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') + * + * @param VersionParser $parser Install composer/semver to have access to this class and functionality + * @param string $packageName + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package + * @return bool + */ + public static function satisfies(VersionParser $parser, $packageName, $constraint) + { + $constraint = $parser->parseConstraints($constraint); + $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + + return $provided->matches($constraint); + } + + /** + * Returns a version constraint representing all the range(s) which are installed for a given package + * + * It is easier to use this via isInstalled() with the $constraint argument if you need to check + * whether a given version of a package is installed, and not just whether it exists + * + * @param string $packageName + * @return string Version constraint usable with composer/semver + */ + public static function getVersionRanges($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + $ranges = array(); + if (isset($installed['versions'][$packageName]['pretty_version'])) { + $ranges[] = $installed['versions'][$packageName]['pretty_version']; + } + if (array_key_exists('aliases', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); + } + if (array_key_exists('replaced', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); + } + if (array_key_exists('provided', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); + } + + return implode(' || ', $ranges); + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['version'])) { + return null; + } + + return $installed['versions'][$packageName]['version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getPrettyVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['pretty_version'])) { + return null; + } + + return $installed['versions'][$packageName]['pretty_version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference + */ + public static function getReference($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['reference'])) { + return null; + } + + return $installed['versions'][$packageName]['reference']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. + */ + public static function getInstallPath($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @return array + * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string} + */ + public static function getRootPackage() + { + $installed = self::getInstalled(); + + return $installed[0]['root']; + } + + /** + * Returns the raw installed.php data for custom implementations + * + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. + * @return array[] + * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} + */ + public static function getRawData() + { + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = include __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + + return self::$installed; + } + + /** + * Returns the raw data of all installed.php which are currently loaded for custom implementations + * + * @return array[] + * @psalm-return list}> + */ + public static function getAllRawData() + { + return self::getInstalled(); + } + + /** + * Lets you reload the static array from another file + * + * This is only useful for complex integrations in which a project needs to use + * this class but then also needs to execute another project's autoloader in process, + * and wants to ensure both projects have access to their version of installed.php. + * + * A typical case would be PHPUnit, where it would need to make sure it reads all + * the data it needs from this class, then call reload() with + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure + * the project in which it runs can then also use this class safely, without + * interference between PHPUnit's dependencies and the project's dependencies. + * + * @param array[] $data A vendor/composer/installed.php data set + * @return void + * + * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + private static function getInstalled() + { + if (null === self::$canGetVendors) { + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); + } + + $installed = array(); + + if (self::$canGetVendors) { + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + if (isset(self::$installedByVendor[$vendorDir])) { + $installed[] = self::$installedByVendor[$vendorDir]; + } elseif (is_file($vendorDir.'/composer/installed.php')) { + $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; + if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + self::$installed = $installed[count($installed) - 1]; + } + } + } + } + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = require __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + $installed[] = self::$installed; + + return $installed; + } +} diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 7a91153b..8e840613 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -6,4 +6,701 @@ $baseDir = dirname($vendorDir); return array( + 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', + 'Hamcrest\\Arrays\\IsArray' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArray.php', + 'Hamcrest\\Arrays\\IsArrayContaining' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContaining.php', + 'Hamcrest\\Arrays\\IsArrayContainingInAnyOrder' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingInAnyOrder.php', + 'Hamcrest\\Arrays\\IsArrayContainingInOrder' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingInOrder.php', + 'Hamcrest\\Arrays\\IsArrayContainingKey' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingKey.php', + 'Hamcrest\\Arrays\\IsArrayContainingKeyValuePair' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingKeyValuePair.php', + 'Hamcrest\\Arrays\\IsArrayWithSize' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayWithSize.php', + 'Hamcrest\\Arrays\\MatchingOnce' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/MatchingOnce.php', + 'Hamcrest\\Arrays\\SeriesMatchingOnce' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/SeriesMatchingOnce.php', + 'Hamcrest\\AssertionError' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/AssertionError.php', + 'Hamcrest\\BaseDescription' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/BaseDescription.php', + 'Hamcrest\\BaseMatcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/BaseMatcher.php', + 'Hamcrest\\Collection\\IsEmptyTraversable' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Collection/IsEmptyTraversable.php', + 'Hamcrest\\Collection\\IsTraversableWithSize' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Collection/IsTraversableWithSize.php', + 'Hamcrest\\Core\\AllOf' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/AllOf.php', + 'Hamcrest\\Core\\AnyOf' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/AnyOf.php', + 'Hamcrest\\Core\\CombinableMatcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/CombinableMatcher.php', + 'Hamcrest\\Core\\DescribedAs' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/DescribedAs.php', + 'Hamcrest\\Core\\Every' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Every.php', + 'Hamcrest\\Core\\HasToString' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/HasToString.php', + 'Hamcrest\\Core\\Is' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Is.php', + 'Hamcrest\\Core\\IsAnything' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsAnything.php', + 'Hamcrest\\Core\\IsCollectionContaining' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsCollectionContaining.php', + 'Hamcrest\\Core\\IsEqual' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsEqual.php', + 'Hamcrest\\Core\\IsIdentical' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsIdentical.php', + 'Hamcrest\\Core\\IsInstanceOf' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsInstanceOf.php', + 'Hamcrest\\Core\\IsNot' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsNot.php', + 'Hamcrest\\Core\\IsNull' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsNull.php', + 'Hamcrest\\Core\\IsSame' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsSame.php', + 'Hamcrest\\Core\\IsTypeOf' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsTypeOf.php', + 'Hamcrest\\Core\\Set' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Set.php', + 'Hamcrest\\Core\\ShortcutCombination' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/ShortcutCombination.php', + 'Hamcrest\\Description' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Description.php', + 'Hamcrest\\DiagnosingMatcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/DiagnosingMatcher.php', + 'Hamcrest\\FeatureMatcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/FeatureMatcher.php', + 'Hamcrest\\Internal\\SelfDescribingValue' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Internal/SelfDescribingValue.php', + 'Hamcrest\\Matcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Matcher.php', + 'Hamcrest\\MatcherAssert' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/MatcherAssert.php', + 'Hamcrest\\Matchers' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Matchers.php', + 'Hamcrest\\NullDescription' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/NullDescription.php', + 'Hamcrest\\Number\\IsCloseTo' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Number/IsCloseTo.php', + 'Hamcrest\\Number\\OrderingComparison' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Number/OrderingComparison.php', + 'Hamcrest\\SelfDescribing' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/SelfDescribing.php', + 'Hamcrest\\StringDescription' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/StringDescription.php', + 'Hamcrest\\Text\\IsEmptyString' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEmptyString.php', + 'Hamcrest\\Text\\IsEqualIgnoringCase' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEqualIgnoringCase.php', + 'Hamcrest\\Text\\IsEqualIgnoringWhiteSpace' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEqualIgnoringWhiteSpace.php', + 'Hamcrest\\Text\\MatchesPattern' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/MatchesPattern.php', + 'Hamcrest\\Text\\StringContains' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContains.php', + 'Hamcrest\\Text\\StringContainsIgnoringCase' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContainsIgnoringCase.php', + 'Hamcrest\\Text\\StringContainsInOrder' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContainsInOrder.php', + 'Hamcrest\\Text\\StringEndsWith' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringEndsWith.php', + 'Hamcrest\\Text\\StringStartsWith' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringStartsWith.php', + 'Hamcrest\\Text\\SubstringMatcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/SubstringMatcher.php', + 'Hamcrest\\TypeSafeDiagnosingMatcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/TypeSafeDiagnosingMatcher.php', + 'Hamcrest\\TypeSafeMatcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/TypeSafeMatcher.php', + 'Hamcrest\\Type\\IsArray' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsArray.php', + 'Hamcrest\\Type\\IsBoolean' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsBoolean.php', + 'Hamcrest\\Type\\IsCallable' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsCallable.php', + 'Hamcrest\\Type\\IsDouble' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsDouble.php', + 'Hamcrest\\Type\\IsInteger' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsInteger.php', + 'Hamcrest\\Type\\IsNumeric' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsNumeric.php', + 'Hamcrest\\Type\\IsObject' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsObject.php', + 'Hamcrest\\Type\\IsResource' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsResource.php', + 'Hamcrest\\Type\\IsScalar' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsScalar.php', + 'Hamcrest\\Type\\IsString' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsString.php', + 'Hamcrest\\Util' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Util.php', + 'Hamcrest\\Xml\\HasXPath' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Xml/HasXPath.php', + 'PHPUnit\\Exception' => $vendorDir . '/phpunit/phpunit/src/Exception.php', + 'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php', + 'PHPUnit\\Framework\\Assert' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert.php', + 'PHPUnit\\Framework\\AssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php', + 'PHPUnit\\Framework\\CodeCoverageException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotAcceptParameterTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotAcceptParameterTypeException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareBoolReturnTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareExactlyOneParameterException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareParameterTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareParameterTypeException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotExistException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotExistException.php', + 'PHPUnit\\Framework\\Constraint\\ArrayHasKey' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php', + 'PHPUnit\\Framework\\Constraint\\BinaryOperator' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php', + 'PHPUnit\\Framework\\Constraint\\Callback' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Callback.php', + 'PHPUnit\\Framework\\Constraint\\ClassHasAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasAttribute.php', + 'PHPUnit\\Framework\\Constraint\\ClassHasStaticAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasStaticAttribute.php', + 'PHPUnit\\Framework\\Constraint\\Constraint' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Constraint.php', + 'PHPUnit\\Framework\\Constraint\\Count' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php', + 'PHPUnit\\Framework\\Constraint\\DirectoryExists' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php', + 'PHPUnit\\Framework\\Constraint\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php', + 'PHPUnit\\Framework\\Constraint\\ExceptionCode' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php', + 'PHPUnit\\Framework\\Constraint\\ExceptionMessage' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessage.php', + 'PHPUnit\\Framework\\Constraint\\ExceptionMessageRegularExpression' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageRegularExpression.php', + 'PHPUnit\\Framework\\Constraint\\FileExists' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php', + 'PHPUnit\\Framework\\Constraint\\GreaterThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php', + 'PHPUnit\\Framework\\Constraint\\IsAnything' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php', + 'PHPUnit\\Framework\\Constraint\\IsEmpty' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php', + 'PHPUnit\\Framework\\Constraint\\IsEqual' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php', + 'PHPUnit\\Framework\\Constraint\\IsEqualCanonicalizing' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php', + 'PHPUnit\\Framework\\Constraint\\IsEqualIgnoringCase' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php', + 'PHPUnit\\Framework\\Constraint\\IsEqualWithDelta' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php', + 'PHPUnit\\Framework\\Constraint\\IsFalse' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php', + 'PHPUnit\\Framework\\Constraint\\IsFinite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php', + 'PHPUnit\\Framework\\Constraint\\IsIdentical' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php', + 'PHPUnit\\Framework\\Constraint\\IsInfinite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php', + 'PHPUnit\\Framework\\Constraint\\IsInstanceOf' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php', + 'PHPUnit\\Framework\\Constraint\\IsJson' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php', + 'PHPUnit\\Framework\\Constraint\\IsNan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php', + 'PHPUnit\\Framework\\Constraint\\IsNull' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php', + 'PHPUnit\\Framework\\Constraint\\IsReadable' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php', + 'PHPUnit\\Framework\\Constraint\\IsTrue' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php', + 'PHPUnit\\Framework\\Constraint\\IsType' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php', + 'PHPUnit\\Framework\\Constraint\\IsWritable' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php', + 'PHPUnit\\Framework\\Constraint\\JsonMatches' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php', + 'PHPUnit\\Framework\\Constraint\\JsonMatchesErrorMessageProvider' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php', + 'PHPUnit\\Framework\\Constraint\\LessThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php', + 'PHPUnit\\Framework\\Constraint\\LogicalAnd' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php', + 'PHPUnit\\Framework\\Constraint\\LogicalNot' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php', + 'PHPUnit\\Framework\\Constraint\\LogicalOr' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php', + 'PHPUnit\\Framework\\Constraint\\LogicalXor' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php', + 'PHPUnit\\Framework\\Constraint\\ObjectEquals' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php', + 'PHPUnit\\Framework\\Constraint\\ObjectHasAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasAttribute.php', + 'PHPUnit\\Framework\\Constraint\\Operator' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php', + 'PHPUnit\\Framework\\Constraint\\RegularExpression' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php', + 'PHPUnit\\Framework\\Constraint\\SameSize' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php', + 'PHPUnit\\Framework\\Constraint\\StringContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php', + 'PHPUnit\\Framework\\Constraint\\StringEndsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php', + 'PHPUnit\\Framework\\Constraint\\StringMatchesFormatDescription' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php', + 'PHPUnit\\Framework\\Constraint\\StringStartsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContainsEqual' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContainsIdentical' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContainsOnly' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php', + 'PHPUnit\\Framework\\Constraint\\UnaryOperator' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php', + 'PHPUnit\\Framework\\CoveredCodeNotExecutedException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/CoveredCodeNotExecutedException.php', + 'PHPUnit\\Framework\\DataProviderTestSuite' => $vendorDir . '/phpunit/phpunit/src/Framework/DataProviderTestSuite.php', + 'PHPUnit\\Framework\\Error' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Error.php', + 'PHPUnit\\Framework\\ErrorTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/ErrorTestCase.php', + 'PHPUnit\\Framework\\Error\\Deprecated' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Deprecated.php', + 'PHPUnit\\Framework\\Error\\Error' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Error.php', + 'PHPUnit\\Framework\\Error\\Notice' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Notice.php', + 'PHPUnit\\Framework\\Error\\Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Warning.php', + 'PHPUnit\\Framework\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Exception.php', + 'PHPUnit\\Framework\\ExceptionWrapper' => $vendorDir . '/phpunit/phpunit/src/Framework/ExceptionWrapper.php', + 'PHPUnit\\Framework\\ExecutionOrderDependency' => $vendorDir . '/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php', + 'PHPUnit\\Framework\\ExpectationFailedException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php', + 'PHPUnit\\Framework\\IncompleteTest' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTest.php', + 'PHPUnit\\Framework\\IncompleteTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTestCase.php', + 'PHPUnit\\Framework\\IncompleteTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/IncompleteTestError.php', + 'PHPUnit\\Framework\\InvalidArgumentException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php', + 'PHPUnit\\Framework\\InvalidCoversTargetException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php', + 'PHPUnit\\Framework\\InvalidDataProviderException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php', + 'PHPUnit\\Framework\\InvalidParameterGroupException' => $vendorDir . '/phpunit/phpunit/src/Framework/InvalidParameterGroupException.php', + 'PHPUnit\\Framework\\MissingCoversAnnotationException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/MissingCoversAnnotationException.php', + 'PHPUnit\\Framework\\MockObject\\Api' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Api/Api.php', + 'PHPUnit\\Framework\\MockObject\\BadMethodCallException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\Identity' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/Identity.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationMocker' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationMocker.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationStubber' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationStubber.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\MethodNameMatch' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/MethodNameMatch.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\ParametersMatch' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/ParametersMatch.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Builder/Stub.php', + 'PHPUnit\\Framework\\MockObject\\CannotUseAddMethodsException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseAddMethodsException.php', + 'PHPUnit\\Framework\\MockObject\\CannotUseOnlyMethodsException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php', + 'PHPUnit\\Framework\\MockObject\\ClassAlreadyExistsException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/ClassAlreadyExistsException.php', + 'PHPUnit\\Framework\\MockObject\\ClassIsFinalException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsFinalException.php', + 'PHPUnit\\Framework\\MockObject\\ClassIsReadonlyException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsReadonlyException.php', + 'PHPUnit\\Framework\\MockObject\\ConfigurableMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php', + 'PHPUnit\\Framework\\MockObject\\ConfigurableMethodsAlreadyInitializedException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/ConfigurableMethodsAlreadyInitializedException.php', + 'PHPUnit\\Framework\\MockObject\\DuplicateMethodException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/DuplicateMethodException.php', + 'PHPUnit\\Framework\\MockObject\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php', + 'PHPUnit\\Framework\\MockObject\\Generator' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator.php', + 'PHPUnit\\Framework\\MockObject\\IncompatibleReturnValueException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php', + 'PHPUnit\\Framework\\MockObject\\InvalidMethodNameException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/InvalidMethodNameException.php', + 'PHPUnit\\Framework\\MockObject\\Invocation' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Invocation.php', + 'PHPUnit\\Framework\\MockObject\\InvocationHandler' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/InvocationHandler.php', + 'PHPUnit\\Framework\\MockObject\\MatchBuilderNotFoundException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php', + 'PHPUnit\\Framework\\MockObject\\Matcher' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Matcher.php', + 'PHPUnit\\Framework\\MockObject\\MatcherAlreadyRegisteredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php', + 'PHPUnit\\Framework\\MockObject\\Method' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Api/Method.php', + 'PHPUnit\\Framework\\MockObject\\MethodCannotBeConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MethodNameAlreadyConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MethodNameConstraint' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MethodNameConstraint.php', + 'PHPUnit\\Framework\\MockObject\\MethodNameNotConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MethodParametersAlreadyConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MockBuilder' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php', + 'PHPUnit\\Framework\\MockObject\\MockClass' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockClass.php', + 'PHPUnit\\Framework\\MockObject\\MockMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockMethod.php', + 'PHPUnit\\Framework\\MockObject\\MockMethodSet' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockMethodSet.php', + 'PHPUnit\\Framework\\MockObject\\MockObject' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockObject.php', + 'PHPUnit\\Framework\\MockObject\\MockTrait' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockTrait.php', + 'PHPUnit\\Framework\\MockObject\\MockType' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockType.php', + 'PHPUnit\\Framework\\MockObject\\OriginalConstructorInvocationRequiredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/OriginalConstructorInvocationRequiredException.php', + 'PHPUnit\\Framework\\MockObject\\ReflectionException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/ReflectionException.php', + 'PHPUnit\\Framework\\MockObject\\ReturnValueNotConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\AnyInvokedCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/AnyInvokedCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\AnyParameters' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/AnyParameters.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\ConsecutiveParameters' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/ConsecutiveParameters.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvocationOrder' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvocationOrder.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtIndex' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtIndex.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastOnce' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastOnce.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtMostCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtMostCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\MethodName' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/MethodName.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\Parameters' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/Parameters.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\ParametersRule' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Rule/ParametersRule.php', + 'PHPUnit\\Framework\\MockObject\\RuntimeException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php', + 'PHPUnit\\Framework\\MockObject\\SoapExtensionNotAvailableException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/SoapExtensionNotAvailableException.php', + 'PHPUnit\\Framework\\MockObject\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ConsecutiveCalls' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ConsecutiveCalls.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/Exception.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnArgument' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnArgument.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnCallback' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnCallback.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnReference' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnReference.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnSelf' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnSelf.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnStub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnStub.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnValueMap' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnValueMap.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Stub/Stub.php', + 'PHPUnit\\Framework\\MockObject\\UnknownClassException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownClassException.php', + 'PHPUnit\\Framework\\MockObject\\UnknownTraitException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTraitException.php', + 'PHPUnit\\Framework\\MockObject\\UnknownTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTypeException.php', + 'PHPUnit\\Framework\\MockObject\\Verifiable' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Verifiable.php', + 'PHPUnit\\Framework\\NoChildTestSuiteException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php', + 'PHPUnit\\Framework\\OutputError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/OutputError.php', + 'PHPUnit\\Framework\\PHPTAssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/PHPTAssertionFailedError.php', + 'PHPUnit\\Framework\\Reorderable' => $vendorDir . '/phpunit/phpunit/src/Framework/Reorderable.php', + 'PHPUnit\\Framework\\RiskyTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/RiskyTestError.php', + 'PHPUnit\\Framework\\SelfDescribing' => $vendorDir . '/phpunit/phpunit/src/Framework/SelfDescribing.php', + 'PHPUnit\\Framework\\SkippedTest' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTest.php', + 'PHPUnit\\Framework\\SkippedTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestCase.php', + 'PHPUnit\\Framework\\SkippedTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/SkippedTestError.php', + 'PHPUnit\\Framework\\SkippedTestSuiteError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/SkippedTestSuiteError.php', + 'PHPUnit\\Framework\\SyntheticError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/SyntheticError.php', + 'PHPUnit\\Framework\\SyntheticSkippedError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/SyntheticSkippedError.php', + 'PHPUnit\\Framework\\Test' => $vendorDir . '/phpunit/phpunit/src/Framework/Test.php', + 'PHPUnit\\Framework\\TestBuilder' => $vendorDir . '/phpunit/phpunit/src/Framework/TestBuilder.php', + 'PHPUnit\\Framework\\TestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/TestCase.php', + 'PHPUnit\\Framework\\TestFailure' => $vendorDir . '/phpunit/phpunit/src/Framework/TestFailure.php', + 'PHPUnit\\Framework\\TestListener' => $vendorDir . '/phpunit/phpunit/src/Framework/TestListener.php', + 'PHPUnit\\Framework\\TestListenerDefaultImplementation' => $vendorDir . '/phpunit/phpunit/src/Framework/TestListenerDefaultImplementation.php', + 'PHPUnit\\Framework\\TestResult' => $vendorDir . '/phpunit/phpunit/src/Framework/TestResult.php', + 'PHPUnit\\Framework\\TestSuite' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuite.php', + 'PHPUnit\\Framework\\TestSuiteIterator' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuiteIterator.php', + 'PHPUnit\\Framework\\UnintentionallyCoveredCodeError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/UnintentionallyCoveredCodeError.php', + 'PHPUnit\\Framework\\Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Warning.php', + 'PHPUnit\\Framework\\WarningTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/WarningTestCase.php', + 'PHPUnit\\Runner\\AfterIncompleteTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterIncompleteTestHook.php', + 'PHPUnit\\Runner\\AfterLastTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterLastTestHook.php', + 'PHPUnit\\Runner\\AfterRiskyTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterRiskyTestHook.php', + 'PHPUnit\\Runner\\AfterSkippedTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterSkippedTestHook.php', + 'PHPUnit\\Runner\\AfterSuccessfulTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterSuccessfulTestHook.php', + 'PHPUnit\\Runner\\AfterTestErrorHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterTestErrorHook.php', + 'PHPUnit\\Runner\\AfterTestFailureHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterTestFailureHook.php', + 'PHPUnit\\Runner\\AfterTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterTestHook.php', + 'PHPUnit\\Runner\\AfterTestWarningHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/AfterTestWarningHook.php', + 'PHPUnit\\Runner\\BaseTestRunner' => $vendorDir . '/phpunit/phpunit/src/Runner/BaseTestRunner.php', + 'PHPUnit\\Runner\\BeforeFirstTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/BeforeFirstTestHook.php', + 'PHPUnit\\Runner\\BeforeTestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/BeforeTestHook.php', + 'PHPUnit\\Runner\\DefaultTestResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/DefaultTestResultCache.php', + 'PHPUnit\\Runner\\Exception' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception.php', + 'PHPUnit\\Runner\\Extension\\ExtensionHandler' => $vendorDir . '/phpunit/phpunit/src/Runner/Extension/ExtensionHandler.php', + 'PHPUnit\\Runner\\Extension\\PharLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/Extension/PharLoader.php', + 'PHPUnit\\Runner\\Filter\\ExcludeGroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php', + 'PHPUnit\\Runner\\Filter\\Factory' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Factory.php', + 'PHPUnit\\Runner\\Filter\\GroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php', + 'PHPUnit\\Runner\\Filter\\IncludeGroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php', + 'PHPUnit\\Runner\\Filter\\NameFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php', + 'PHPUnit\\Runner\\Hook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/Hook.php', + 'PHPUnit\\Runner\\NullTestResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/NullTestResultCache.php', + 'PHPUnit\\Runner\\PhptTestCase' => $vendorDir . '/phpunit/phpunit/src/Runner/PhptTestCase.php', + 'PHPUnit\\Runner\\ResultCacheExtension' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCacheExtension.php', + 'PHPUnit\\Runner\\StandardTestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php', + 'PHPUnit\\Runner\\TestHook' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/TestHook.php', + 'PHPUnit\\Runner\\TestListenerAdapter' => $vendorDir . '/phpunit/phpunit/src/Runner/Hook/TestListenerAdapter.php', + 'PHPUnit\\Runner\\TestResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResultCache.php', + 'PHPUnit\\Runner\\TestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php', + 'PHPUnit\\Runner\\TestSuiteSorter' => $vendorDir . '/phpunit/phpunit/src/Runner/TestSuiteSorter.php', + 'PHPUnit\\Runner\\Version' => $vendorDir . '/phpunit/phpunit/src/Runner/Version.php', + 'PHPUnit\\TextUI\\CliArguments\\Builder' => $vendorDir . '/phpunit/phpunit/src/TextUI/CliArguments/Builder.php', + 'PHPUnit\\TextUI\\CliArguments\\Configuration' => $vendorDir . '/phpunit/phpunit/src/TextUI/CliArguments/Configuration.php', + 'PHPUnit\\TextUI\\CliArguments\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/CliArguments/Exception.php', + 'PHPUnit\\TextUI\\CliArguments\\Mapper' => $vendorDir . '/phpunit/phpunit/src/TextUI/CliArguments/Mapper.php', + 'PHPUnit\\TextUI\\Command' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command.php', + 'PHPUnit\\TextUI\\DefaultResultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/DefaultResultPrinter.php', + 'PHPUnit\\TextUI\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/Exception.php', + 'PHPUnit\\TextUI\\Help' => $vendorDir . '/phpunit/phpunit/src/TextUI/Help.php', + 'PHPUnit\\TextUI\\ReflectionException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/ReflectionException.php', + 'PHPUnit\\TextUI\\ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/ResultPrinter.php', + 'PHPUnit\\TextUI\\RuntimeException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php', + 'PHPUnit\\TextUI\\TestDirectoryNotFoundException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php', + 'PHPUnit\\TextUI\\TestFileNotFoundException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php', + 'PHPUnit\\TextUI\\TestRunner' => $vendorDir . '/phpunit/phpunit/src/TextUI/TestRunner.php', + 'PHPUnit\\TextUI\\TestSuiteMapper' => $vendorDir . '/phpunit/phpunit/src/TextUI/TestSuiteMapper.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\CodeCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/CodeCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\FilterMapper' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/FilterMapper.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Filter\\Directory' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/Directory.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Filter\\DirectoryCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Filter\\DirectoryCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Clover' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Clover.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Cobertura' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Cobertura.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Crap4j' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Crap4j.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Html' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Html.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Php' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Php.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Text' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Text.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Xml' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Xml.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Configuration' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Configuration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Constant' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Constant.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\ConstantCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\ConstantCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\ConvertLogTypes' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/ConvertLogTypes.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCloverToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCloverToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCrap4jToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCrap4jToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageHtmlToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageHtmlToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoveragePhpToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoveragePhpToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageTextToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageTextToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageXmlToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageXmlToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Directory' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/Directory.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\DirectoryCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\DirectoryCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Exception.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Extension' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/Extension.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\ExtensionCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\ExtensionCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\File' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/File.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\FileCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\FileCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Generator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Generator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Group' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Group.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\GroupCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\GroupCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Groups' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Groups.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\IniSetting' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSetting.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\IniSettingCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\IniSettingCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\IntroduceCoverageElement' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/IntroduceCoverageElement.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Loader' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Loader.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\LogToReportMigration' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/LogToReportMigration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Junit' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Junit.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Logging' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Logging.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TeamCity' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TeamCity.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Html' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Html.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Text' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Text.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Xml' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Xml.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Text' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Text.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Migration' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/Migration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MigrationBuilder' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilder.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MigrationBuilderException' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilderException.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MigrationException' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationException.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Migrator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromFilterWhitelistToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromRootToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromRootToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistDirectoriesToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistDirectoriesToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistExcludesToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistExcludesToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\PHPUnit' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/PHPUnit.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Php' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Php.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\PhpHandler' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/PhpHandler.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCacheTokensAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveCacheTokensAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveEmptyFilter' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveEmptyFilter.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveLogTypes' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveLogTypes.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestDirectory' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectory.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestDirectoryCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestDirectoryCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestFile' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFile.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestFileCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestFileCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestSuite' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuite.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestSuiteCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestSuiteCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\UpdateSchemaLocationTo93' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/UpdateSchemaLocationTo93.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Variable' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Variable.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\VariableCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\VariableCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollectionIterator.php', + 'PHPUnit\\Util\\Annotation\\DocBlock' => $vendorDir . '/phpunit/phpunit/src/Util/Annotation/DocBlock.php', + 'PHPUnit\\Util\\Annotation\\Registry' => $vendorDir . '/phpunit/phpunit/src/Util/Annotation/Registry.php', + 'PHPUnit\\Util\\Blacklist' => $vendorDir . '/phpunit/phpunit/src/Util/Blacklist.php', + 'PHPUnit\\Util\\Cloner' => $vendorDir . '/phpunit/phpunit/src/Util/Cloner.php', + 'PHPUnit\\Util\\Color' => $vendorDir . '/phpunit/phpunit/src/Util/Color.php', + 'PHPUnit\\Util\\ErrorHandler' => $vendorDir . '/phpunit/phpunit/src/Util/ErrorHandler.php', + 'PHPUnit\\Util\\Exception' => $vendorDir . '/phpunit/phpunit/src/Util/Exception.php', + 'PHPUnit\\Util\\ExcludeList' => $vendorDir . '/phpunit/phpunit/src/Util/ExcludeList.php', + 'PHPUnit\\Util\\FileLoader' => $vendorDir . '/phpunit/phpunit/src/Util/FileLoader.php', + 'PHPUnit\\Util\\Filesystem' => $vendorDir . '/phpunit/phpunit/src/Util/Filesystem.php', + 'PHPUnit\\Util\\Filter' => $vendorDir . '/phpunit/phpunit/src/Util/Filter.php', + 'PHPUnit\\Util\\GlobalState' => $vendorDir . '/phpunit/phpunit/src/Util/GlobalState.php', + 'PHPUnit\\Util\\InvalidDataSetException' => $vendorDir . '/phpunit/phpunit/src/Util/InvalidDataSetException.php', + 'PHPUnit\\Util\\Json' => $vendorDir . '/phpunit/phpunit/src/Util/Json.php', + 'PHPUnit\\Util\\Log\\JUnit' => $vendorDir . '/phpunit/phpunit/src/Util/Log/JUnit.php', + 'PHPUnit\\Util\\Log\\TeamCity' => $vendorDir . '/phpunit/phpunit/src/Util/Log/TeamCity.php', + 'PHPUnit\\Util\\PHP\\AbstractPhpProcess' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php', + 'PHPUnit\\Util\\PHP\\DefaultPhpProcess' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php', + 'PHPUnit\\Util\\PHP\\WindowsPhpProcess' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/WindowsPhpProcess.php', + 'PHPUnit\\Util\\Printer' => $vendorDir . '/phpunit/phpunit/src/Util/Printer.php', + 'PHPUnit\\Util\\Reflection' => $vendorDir . '/phpunit/phpunit/src/Util/Reflection.php', + 'PHPUnit\\Util\\RegularExpression' => $vendorDir . '/phpunit/phpunit/src/Util/RegularExpression.php', + 'PHPUnit\\Util\\Test' => $vendorDir . '/phpunit/phpunit/src/Util/Test.php', + 'PHPUnit\\Util\\TestDox\\CliTestDoxPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/CliTestDoxPrinter.php', + 'PHPUnit\\Util\\TestDox\\HtmlResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/HtmlResultPrinter.php', + 'PHPUnit\\Util\\TestDox\\NamePrettifier' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php', + 'PHPUnit\\Util\\TestDox\\ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php', + 'PHPUnit\\Util\\TestDox\\TestDoxPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/TestDoxPrinter.php', + 'PHPUnit\\Util\\TestDox\\TextResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/TextResultPrinter.php', + 'PHPUnit\\Util\\TestDox\\XmlResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/XmlResultPrinter.php', + 'PHPUnit\\Util\\TextTestListRenderer' => $vendorDir . '/phpunit/phpunit/src/Util/TextTestListRenderer.php', + 'PHPUnit\\Util\\Type' => $vendorDir . '/phpunit/phpunit/src/Util/Type.php', + 'PHPUnit\\Util\\VersionComparisonOperator' => $vendorDir . '/phpunit/phpunit/src/Util/VersionComparisonOperator.php', + 'PHPUnit\\Util\\XdebugFilterScriptGenerator' => $vendorDir . '/phpunit/phpunit/src/Util/XdebugFilterScriptGenerator.php', + 'PHPUnit\\Util\\Xml' => $vendorDir . '/phpunit/phpunit/src/Util/Xml.php', + 'PHPUnit\\Util\\XmlTestListRenderer' => $vendorDir . '/phpunit/phpunit/src/Util/XmlTestListRenderer.php', + 'PHPUnit\\Util\\Xml\\Exception' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/Exception.php', + 'PHPUnit\\Util\\Xml\\FailedSchemaDetectionResult' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/FailedSchemaDetectionResult.php', + 'PHPUnit\\Util\\Xml\\Loader' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/Loader.php', + 'PHPUnit\\Util\\Xml\\SchemaDetectionResult' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/SchemaDetectionResult.php', + 'PHPUnit\\Util\\Xml\\SchemaDetector' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/SchemaDetector.php', + 'PHPUnit\\Util\\Xml\\SchemaFinder' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/SchemaFinder.php', + 'PHPUnit\\Util\\Xml\\SnapshotNodeList' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/SnapshotNodeList.php', + 'PHPUnit\\Util\\Xml\\SuccessfulSchemaDetectionResult' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/SuccessfulSchemaDetectionResult.php', + 'PHPUnit\\Util\\Xml\\ValidationResult' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/ValidationResult.php', + 'PHPUnit\\Util\\Xml\\Validator' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/Validator.php', + 'PharIo\\Manifest\\Application' => $vendorDir . '/phar-io/manifest/src/values/Application.php', + 'PharIo\\Manifest\\ApplicationName' => $vendorDir . '/phar-io/manifest/src/values/ApplicationName.php', + 'PharIo\\Manifest\\Author' => $vendorDir . '/phar-io/manifest/src/values/Author.php', + 'PharIo\\Manifest\\AuthorCollection' => $vendorDir . '/phar-io/manifest/src/values/AuthorCollection.php', + 'PharIo\\Manifest\\AuthorCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/AuthorCollectionIterator.php', + 'PharIo\\Manifest\\AuthorElement' => $vendorDir . '/phar-io/manifest/src/xml/AuthorElement.php', + 'PharIo\\Manifest\\AuthorElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/AuthorElementCollection.php', + 'PharIo\\Manifest\\BundledComponent' => $vendorDir . '/phar-io/manifest/src/values/BundledComponent.php', + 'PharIo\\Manifest\\BundledComponentCollection' => $vendorDir . '/phar-io/manifest/src/values/BundledComponentCollection.php', + 'PharIo\\Manifest\\BundledComponentCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/BundledComponentCollectionIterator.php', + 'PharIo\\Manifest\\BundlesElement' => $vendorDir . '/phar-io/manifest/src/xml/BundlesElement.php', + 'PharIo\\Manifest\\ComponentElement' => $vendorDir . '/phar-io/manifest/src/xml/ComponentElement.php', + 'PharIo\\Manifest\\ComponentElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ComponentElementCollection.php', + 'PharIo\\Manifest\\ContainsElement' => $vendorDir . '/phar-io/manifest/src/xml/ContainsElement.php', + 'PharIo\\Manifest\\CopyrightElement' => $vendorDir . '/phar-io/manifest/src/xml/CopyrightElement.php', + 'PharIo\\Manifest\\CopyrightInformation' => $vendorDir . '/phar-io/manifest/src/values/CopyrightInformation.php', + 'PharIo\\Manifest\\ElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ElementCollection.php', + 'PharIo\\Manifest\\ElementCollectionException' => $vendorDir . '/phar-io/manifest/src/exceptions/ElementCollectionException.php', + 'PharIo\\Manifest\\Email' => $vendorDir . '/phar-io/manifest/src/values/Email.php', + 'PharIo\\Manifest\\Exception' => $vendorDir . '/phar-io/manifest/src/exceptions/Exception.php', + 'PharIo\\Manifest\\ExtElement' => $vendorDir . '/phar-io/manifest/src/xml/ExtElement.php', + 'PharIo\\Manifest\\ExtElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ExtElementCollection.php', + 'PharIo\\Manifest\\Extension' => $vendorDir . '/phar-io/manifest/src/values/Extension.php', + 'PharIo\\Manifest\\ExtensionElement' => $vendorDir . '/phar-io/manifest/src/xml/ExtensionElement.php', + 'PharIo\\Manifest\\InvalidApplicationNameException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php', + 'PharIo\\Manifest\\InvalidEmailException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidEmailException.php', + 'PharIo\\Manifest\\InvalidUrlException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidUrlException.php', + 'PharIo\\Manifest\\Library' => $vendorDir . '/phar-io/manifest/src/values/Library.php', + 'PharIo\\Manifest\\License' => $vendorDir . '/phar-io/manifest/src/values/License.php', + 'PharIo\\Manifest\\LicenseElement' => $vendorDir . '/phar-io/manifest/src/xml/LicenseElement.php', + 'PharIo\\Manifest\\Manifest' => $vendorDir . '/phar-io/manifest/src/values/Manifest.php', + 'PharIo\\Manifest\\ManifestDocument' => $vendorDir . '/phar-io/manifest/src/xml/ManifestDocument.php', + 'PharIo\\Manifest\\ManifestDocumentException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentException.php', + 'PharIo\\Manifest\\ManifestDocumentLoadingException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php', + 'PharIo\\Manifest\\ManifestDocumentMapper' => $vendorDir . '/phar-io/manifest/src/ManifestDocumentMapper.php', + 'PharIo\\Manifest\\ManifestDocumentMapperException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php', + 'PharIo\\Manifest\\ManifestElement' => $vendorDir . '/phar-io/manifest/src/xml/ManifestElement.php', + 'PharIo\\Manifest\\ManifestElementException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestElementException.php', + 'PharIo\\Manifest\\ManifestLoader' => $vendorDir . '/phar-io/manifest/src/ManifestLoader.php', + 'PharIo\\Manifest\\ManifestLoaderException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestLoaderException.php', + 'PharIo\\Manifest\\ManifestSerializer' => $vendorDir . '/phar-io/manifest/src/ManifestSerializer.php', + 'PharIo\\Manifest\\PhpElement' => $vendorDir . '/phar-io/manifest/src/xml/PhpElement.php', + 'PharIo\\Manifest\\PhpExtensionRequirement' => $vendorDir . '/phar-io/manifest/src/values/PhpExtensionRequirement.php', + 'PharIo\\Manifest\\PhpVersionRequirement' => $vendorDir . '/phar-io/manifest/src/values/PhpVersionRequirement.php', + 'PharIo\\Manifest\\Requirement' => $vendorDir . '/phar-io/manifest/src/values/Requirement.php', + 'PharIo\\Manifest\\RequirementCollection' => $vendorDir . '/phar-io/manifest/src/values/RequirementCollection.php', + 'PharIo\\Manifest\\RequirementCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/RequirementCollectionIterator.php', + 'PharIo\\Manifest\\RequiresElement' => $vendorDir . '/phar-io/manifest/src/xml/RequiresElement.php', + 'PharIo\\Manifest\\Type' => $vendorDir . '/phar-io/manifest/src/values/Type.php', + 'PharIo\\Manifest\\Url' => $vendorDir . '/phar-io/manifest/src/values/Url.php', + 'PharIo\\Version\\AbstractVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/AbstractVersionConstraint.php', + 'PharIo\\Version\\AndVersionConstraintGroup' => $vendorDir . '/phar-io/version/src/constraints/AndVersionConstraintGroup.php', + 'PharIo\\Version\\AnyVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/AnyVersionConstraint.php', + 'PharIo\\Version\\BuildMetaData' => $vendorDir . '/phar-io/version/src/BuildMetaData.php', + 'PharIo\\Version\\ExactVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/ExactVersionConstraint.php', + 'PharIo\\Version\\Exception' => $vendorDir . '/phar-io/version/src/exceptions/Exception.php', + 'PharIo\\Version\\GreaterThanOrEqualToVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php', + 'PharIo\\Version\\InvalidPreReleaseSuffixException' => $vendorDir . '/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php', + 'PharIo\\Version\\InvalidVersionException' => $vendorDir . '/phar-io/version/src/exceptions/InvalidVersionException.php', + 'PharIo\\Version\\NoBuildMetaDataException' => $vendorDir . '/phar-io/version/src/exceptions/NoBuildMetaDataException.php', + 'PharIo\\Version\\NoPreReleaseSuffixException' => $vendorDir . '/phar-io/version/src/exceptions/NoPreReleaseSuffixException.php', + 'PharIo\\Version\\OrVersionConstraintGroup' => $vendorDir . '/phar-io/version/src/constraints/OrVersionConstraintGroup.php', + 'PharIo\\Version\\PreReleaseSuffix' => $vendorDir . '/phar-io/version/src/PreReleaseSuffix.php', + 'PharIo\\Version\\SpecificMajorAndMinorVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php', + 'PharIo\\Version\\SpecificMajorVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php', + 'PharIo\\Version\\UnsupportedVersionConstraintException' => $vendorDir . '/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.php', + 'PharIo\\Version\\Version' => $vendorDir . '/phar-io/version/src/Version.php', + 'PharIo\\Version\\VersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/VersionConstraint.php', + 'PharIo\\Version\\VersionConstraintParser' => $vendorDir . '/phar-io/version/src/VersionConstraintParser.php', + 'PharIo\\Version\\VersionConstraintValue' => $vendorDir . '/phar-io/version/src/VersionConstraintValue.php', + 'PharIo\\Version\\VersionNumber' => $vendorDir . '/phar-io/version/src/VersionNumber.php', + 'SebastianBergmann\\CliParser\\AmbiguousOptionException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php', + 'SebastianBergmann\\CliParser\\Exception' => $vendorDir . '/sebastian/cli-parser/src/exceptions/Exception.php', + 'SebastianBergmann\\CliParser\\OptionDoesNotAllowArgumentException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php', + 'SebastianBergmann\\CliParser\\Parser' => $vendorDir . '/sebastian/cli-parser/src/Parser.php', + 'SebastianBergmann\\CliParser\\RequiredOptionArgumentMissingException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php', + 'SebastianBergmann\\CliParser\\UnknownOptionException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/UnknownOptionException.php', + 'SebastianBergmann\\CodeCoverage\\BranchAndPathCoverageNotSupportedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php', + 'SebastianBergmann\\CodeCoverage\\CodeCoverage' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage.php', + 'SebastianBergmann\\CodeCoverage\\DeadCodeDetectionNotSupportedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Driver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Driver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PathExistsButIsNotDirectoryException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PcovDriver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/PcovDriver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PcovNotAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PhpdbgDriver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/PhpdbgDriver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PhpdbgNotAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/PhpdbgNotAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Selector' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Selector.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\WriteOperationFailedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\WrongXdebugVersionException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/WrongXdebugVersionException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug2Driver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Xdebug2Driver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug2NotEnabledException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/Xdebug2NotEnabledException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug3Driver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Xdebug3Driver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug3NotEnabledException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/Xdebug3NotEnabledException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\Exception' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/Exception.php', + 'SebastianBergmann\\CodeCoverage\\Filter' => $vendorDir . '/phpunit/php-code-coverage/src/Filter.php', + 'SebastianBergmann\\CodeCoverage\\InvalidArgumentException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php', + 'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverWithPathCoverageSupportAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\Node\\AbstractNode' => $vendorDir . '/phpunit/php-code-coverage/src/Node/AbstractNode.php', + 'SebastianBergmann\\CodeCoverage\\Node\\Builder' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Builder.php', + 'SebastianBergmann\\CodeCoverage\\Node\\CrapIndex' => $vendorDir . '/phpunit/php-code-coverage/src/Node/CrapIndex.php', + 'SebastianBergmann\\CodeCoverage\\Node\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Directory.php', + 'SebastianBergmann\\CodeCoverage\\Node\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Node/File.php', + 'SebastianBergmann\\CodeCoverage\\Node\\Iterator' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Iterator.php', + 'SebastianBergmann\\CodeCoverage\\ParserException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ParserException.php', + 'SebastianBergmann\\CodeCoverage\\ProcessedCodeCoverageData' => $vendorDir . '/phpunit/php-code-coverage/src/ProcessedCodeCoverageData.php', + 'SebastianBergmann\\CodeCoverage\\RawCodeCoverageData' => $vendorDir . '/phpunit/php-code-coverage/src/RawCodeCoverageData.php', + 'SebastianBergmann\\CodeCoverage\\ReflectionException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ReflectionException.php', + 'SebastianBergmann\\CodeCoverage\\ReportAlreadyFinalizedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Clover' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Clover.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Cobertura' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Cobertura.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Crap4j' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Crap4j.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Dashboard' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Facade' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Facade.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Renderer' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer.php', + 'SebastianBergmann\\CodeCoverage\\Report\\PHP' => $vendorDir . '/phpunit/php-code-coverage/src/Report/PHP.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Text' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Text.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\BuildInformation' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Coverage' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Coverage.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Directory.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Facade' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Facade.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/File.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Method' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Method.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Node' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Node.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Project' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Project.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Report' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Report.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Source' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Source.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Tests' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Tests.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Totals' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Totals.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Unit' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Unit.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysisCacheNotConfiguredException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CacheWarmer' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CachingFileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CodeUnitFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ExecutableLinesFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\FileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\IgnoredLinesFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ParsingFileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php', + 'SebastianBergmann\\CodeCoverage\\TestIdMissingException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php', + 'SebastianBergmann\\CodeCoverage\\UnintentionallyCoveredCodeException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php', + 'SebastianBergmann\\CodeCoverage\\Util\\DirectoryCouldNotBeCreatedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php', + 'SebastianBergmann\\CodeCoverage\\Util\\Filesystem' => $vendorDir . '/phpunit/php-code-coverage/src/Util/Filesystem.php', + 'SebastianBergmann\\CodeCoverage\\Util\\Percentage' => $vendorDir . '/phpunit/php-code-coverage/src/Util/Percentage.php', + 'SebastianBergmann\\CodeCoverage\\Version' => $vendorDir . '/phpunit/php-code-coverage/src/Version.php', + 'SebastianBergmann\\CodeCoverage\\XmlException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/XmlException.php', + 'SebastianBergmann\\CodeUnitReverseLookup\\Wizard' => $vendorDir . '/sebastian/code-unit-reverse-lookup/src/Wizard.php', + 'SebastianBergmann\\CodeUnit\\ClassMethodUnit' => $vendorDir . '/sebastian/code-unit/src/ClassMethodUnit.php', + 'SebastianBergmann\\CodeUnit\\ClassUnit' => $vendorDir . '/sebastian/code-unit/src/ClassUnit.php', + 'SebastianBergmann\\CodeUnit\\CodeUnit' => $vendorDir . '/sebastian/code-unit/src/CodeUnit.php', + 'SebastianBergmann\\CodeUnit\\CodeUnitCollection' => $vendorDir . '/sebastian/code-unit/src/CodeUnitCollection.php', + 'SebastianBergmann\\CodeUnit\\CodeUnitCollectionIterator' => $vendorDir . '/sebastian/code-unit/src/CodeUnitCollectionIterator.php', + 'SebastianBergmann\\CodeUnit\\Exception' => $vendorDir . '/sebastian/code-unit/src/exceptions/Exception.php', + 'SebastianBergmann\\CodeUnit\\FunctionUnit' => $vendorDir . '/sebastian/code-unit/src/FunctionUnit.php', + 'SebastianBergmann\\CodeUnit\\InterfaceMethodUnit' => $vendorDir . '/sebastian/code-unit/src/InterfaceMethodUnit.php', + 'SebastianBergmann\\CodeUnit\\InterfaceUnit' => $vendorDir . '/sebastian/code-unit/src/InterfaceUnit.php', + 'SebastianBergmann\\CodeUnit\\InvalidCodeUnitException' => $vendorDir . '/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php', + 'SebastianBergmann\\CodeUnit\\Mapper' => $vendorDir . '/sebastian/code-unit/src/Mapper.php', + 'SebastianBergmann\\CodeUnit\\NoTraitException' => $vendorDir . '/sebastian/code-unit/src/exceptions/NoTraitException.php', + 'SebastianBergmann\\CodeUnit\\ReflectionException' => $vendorDir . '/sebastian/code-unit/src/exceptions/ReflectionException.php', + 'SebastianBergmann\\CodeUnit\\TraitMethodUnit' => $vendorDir . '/sebastian/code-unit/src/TraitMethodUnit.php', + 'SebastianBergmann\\CodeUnit\\TraitUnit' => $vendorDir . '/sebastian/code-unit/src/TraitUnit.php', + 'SebastianBergmann\\Comparator\\ArrayComparator' => $vendorDir . '/sebastian/comparator/src/ArrayComparator.php', + 'SebastianBergmann\\Comparator\\Comparator' => $vendorDir . '/sebastian/comparator/src/Comparator.php', + 'SebastianBergmann\\Comparator\\ComparisonFailure' => $vendorDir . '/sebastian/comparator/src/ComparisonFailure.php', + 'SebastianBergmann\\Comparator\\DOMNodeComparator' => $vendorDir . '/sebastian/comparator/src/DOMNodeComparator.php', + 'SebastianBergmann\\Comparator\\DateTimeComparator' => $vendorDir . '/sebastian/comparator/src/DateTimeComparator.php', + 'SebastianBergmann\\Comparator\\DoubleComparator' => $vendorDir . '/sebastian/comparator/src/DoubleComparator.php', + 'SebastianBergmann\\Comparator\\Exception' => $vendorDir . '/sebastian/comparator/src/exceptions/Exception.php', + 'SebastianBergmann\\Comparator\\ExceptionComparator' => $vendorDir . '/sebastian/comparator/src/ExceptionComparator.php', + 'SebastianBergmann\\Comparator\\Factory' => $vendorDir . '/sebastian/comparator/src/Factory.php', + 'SebastianBergmann\\Comparator\\MockObjectComparator' => $vendorDir . '/sebastian/comparator/src/MockObjectComparator.php', + 'SebastianBergmann\\Comparator\\NumericComparator' => $vendorDir . '/sebastian/comparator/src/NumericComparator.php', + 'SebastianBergmann\\Comparator\\ObjectComparator' => $vendorDir . '/sebastian/comparator/src/ObjectComparator.php', + 'SebastianBergmann\\Comparator\\ResourceComparator' => $vendorDir . '/sebastian/comparator/src/ResourceComparator.php', + 'SebastianBergmann\\Comparator\\RuntimeException' => $vendorDir . '/sebastian/comparator/src/exceptions/RuntimeException.php', + 'SebastianBergmann\\Comparator\\ScalarComparator' => $vendorDir . '/sebastian/comparator/src/ScalarComparator.php', + 'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => $vendorDir . '/sebastian/comparator/src/SplObjectStorageComparator.php', + 'SebastianBergmann\\Comparator\\TypeComparator' => $vendorDir . '/sebastian/comparator/src/TypeComparator.php', + 'SebastianBergmann\\Complexity\\Calculator' => $vendorDir . '/sebastian/complexity/src/Calculator.php', + 'SebastianBergmann\\Complexity\\Complexity' => $vendorDir . '/sebastian/complexity/src/Complexity/Complexity.php', + 'SebastianBergmann\\Complexity\\ComplexityCalculatingVisitor' => $vendorDir . '/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php', + 'SebastianBergmann\\Complexity\\ComplexityCollection' => $vendorDir . '/sebastian/complexity/src/Complexity/ComplexityCollection.php', + 'SebastianBergmann\\Complexity\\ComplexityCollectionIterator' => $vendorDir . '/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php', + 'SebastianBergmann\\Complexity\\CyclomaticComplexityCalculatingVisitor' => $vendorDir . '/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php', + 'SebastianBergmann\\Complexity\\Exception' => $vendorDir . '/sebastian/complexity/src/Exception/Exception.php', + 'SebastianBergmann\\Complexity\\RuntimeException' => $vendorDir . '/sebastian/complexity/src/Exception/RuntimeException.php', + 'SebastianBergmann\\Diff\\Chunk' => $vendorDir . '/sebastian/diff/src/Chunk.php', + 'SebastianBergmann\\Diff\\ConfigurationException' => $vendorDir . '/sebastian/diff/src/Exception/ConfigurationException.php', + 'SebastianBergmann\\Diff\\Diff' => $vendorDir . '/sebastian/diff/src/Diff.php', + 'SebastianBergmann\\Diff\\Differ' => $vendorDir . '/sebastian/diff/src/Differ.php', + 'SebastianBergmann\\Diff\\Exception' => $vendorDir . '/sebastian/diff/src/Exception/Exception.php', + 'SebastianBergmann\\Diff\\InvalidArgumentException' => $vendorDir . '/sebastian/diff/src/Exception/InvalidArgumentException.php', + 'SebastianBergmann\\Diff\\Line' => $vendorDir . '/sebastian/diff/src/Line.php', + 'SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php', + 'SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php', + 'SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php', + 'SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php', + 'SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => $vendorDir . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php', + 'SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php', + 'SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php', + 'SebastianBergmann\\Diff\\Parser' => $vendorDir . '/sebastian/diff/src/Parser.php', + 'SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php', + 'SebastianBergmann\\Environment\\Console' => $vendorDir . '/sebastian/environment/src/Console.php', + 'SebastianBergmann\\Environment\\OperatingSystem' => $vendorDir . '/sebastian/environment/src/OperatingSystem.php', + 'SebastianBergmann\\Environment\\Runtime' => $vendorDir . '/sebastian/environment/src/Runtime.php', + 'SebastianBergmann\\Exporter\\Exporter' => $vendorDir . '/sebastian/exporter/src/Exporter.php', + 'SebastianBergmann\\FileIterator\\Facade' => $vendorDir . '/phpunit/php-file-iterator/src/Facade.php', + 'SebastianBergmann\\FileIterator\\Factory' => $vendorDir . '/phpunit/php-file-iterator/src/Factory.php', + 'SebastianBergmann\\FileIterator\\Iterator' => $vendorDir . '/phpunit/php-file-iterator/src/Iterator.php', + 'SebastianBergmann\\GlobalState\\CodeExporter' => $vendorDir . '/sebastian/global-state/src/CodeExporter.php', + 'SebastianBergmann\\GlobalState\\Exception' => $vendorDir . '/sebastian/global-state/src/exceptions/Exception.php', + 'SebastianBergmann\\GlobalState\\ExcludeList' => $vendorDir . '/sebastian/global-state/src/ExcludeList.php', + 'SebastianBergmann\\GlobalState\\Restorer' => $vendorDir . '/sebastian/global-state/src/Restorer.php', + 'SebastianBergmann\\GlobalState\\RuntimeException' => $vendorDir . '/sebastian/global-state/src/exceptions/RuntimeException.php', + 'SebastianBergmann\\GlobalState\\Snapshot' => $vendorDir . '/sebastian/global-state/src/Snapshot.php', + 'SebastianBergmann\\Invoker\\Exception' => $vendorDir . '/phpunit/php-invoker/src/exceptions/Exception.php', + 'SebastianBergmann\\Invoker\\Invoker' => $vendorDir . '/phpunit/php-invoker/src/Invoker.php', + 'SebastianBergmann\\Invoker\\ProcessControlExtensionNotLoadedException' => $vendorDir . '/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php', + 'SebastianBergmann\\Invoker\\TimeoutException' => $vendorDir . '/phpunit/php-invoker/src/exceptions/TimeoutException.php', + 'SebastianBergmann\\LinesOfCode\\Counter' => $vendorDir . '/sebastian/lines-of-code/src/Counter.php', + 'SebastianBergmann\\LinesOfCode\\Exception' => $vendorDir . '/sebastian/lines-of-code/src/Exception/Exception.php', + 'SebastianBergmann\\LinesOfCode\\IllogicalValuesException' => $vendorDir . '/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php', + 'SebastianBergmann\\LinesOfCode\\LineCountingVisitor' => $vendorDir . '/sebastian/lines-of-code/src/LineCountingVisitor.php', + 'SebastianBergmann\\LinesOfCode\\LinesOfCode' => $vendorDir . '/sebastian/lines-of-code/src/LinesOfCode.php', + 'SebastianBergmann\\LinesOfCode\\NegativeValueException' => $vendorDir . '/sebastian/lines-of-code/src/Exception/NegativeValueException.php', + 'SebastianBergmann\\LinesOfCode\\RuntimeException' => $vendorDir . '/sebastian/lines-of-code/src/Exception/RuntimeException.php', + 'SebastianBergmann\\ObjectEnumerator\\Enumerator' => $vendorDir . '/sebastian/object-enumerator/src/Enumerator.php', + 'SebastianBergmann\\ObjectEnumerator\\Exception' => $vendorDir . '/sebastian/object-enumerator/src/Exception.php', + 'SebastianBergmann\\ObjectEnumerator\\InvalidArgumentException' => $vendorDir . '/sebastian/object-enumerator/src/InvalidArgumentException.php', + 'SebastianBergmann\\ObjectReflector\\Exception' => $vendorDir . '/sebastian/object-reflector/src/Exception.php', + 'SebastianBergmann\\ObjectReflector\\InvalidArgumentException' => $vendorDir . '/sebastian/object-reflector/src/InvalidArgumentException.php', + 'SebastianBergmann\\ObjectReflector\\ObjectReflector' => $vendorDir . '/sebastian/object-reflector/src/ObjectReflector.php', + 'SebastianBergmann\\RecursionContext\\Context' => $vendorDir . '/sebastian/recursion-context/src/Context.php', + 'SebastianBergmann\\RecursionContext\\Exception' => $vendorDir . '/sebastian/recursion-context/src/Exception.php', + 'SebastianBergmann\\RecursionContext\\InvalidArgumentException' => $vendorDir . '/sebastian/recursion-context/src/InvalidArgumentException.php', + 'SebastianBergmann\\ResourceOperations\\ResourceOperations' => $vendorDir . '/sebastian/resource-operations/src/ResourceOperations.php', + 'SebastianBergmann\\Template\\Exception' => $vendorDir . '/phpunit/php-text-template/src/exceptions/Exception.php', + 'SebastianBergmann\\Template\\InvalidArgumentException' => $vendorDir . '/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php', + 'SebastianBergmann\\Template\\RuntimeException' => $vendorDir . '/phpunit/php-text-template/src/exceptions/RuntimeException.php', + 'SebastianBergmann\\Template\\Template' => $vendorDir . '/phpunit/php-text-template/src/Template.php', + 'SebastianBergmann\\Timer\\Duration' => $vendorDir . '/phpunit/php-timer/src/Duration.php', + 'SebastianBergmann\\Timer\\Exception' => $vendorDir . '/phpunit/php-timer/src/exceptions/Exception.php', + 'SebastianBergmann\\Timer\\NoActiveTimerException' => $vendorDir . '/phpunit/php-timer/src/exceptions/NoActiveTimerException.php', + 'SebastianBergmann\\Timer\\ResourceUsageFormatter' => $vendorDir . '/phpunit/php-timer/src/ResourceUsageFormatter.php', + 'SebastianBergmann\\Timer\\TimeSinceStartOfRequestNotAvailableException' => $vendorDir . '/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php', + 'SebastianBergmann\\Timer\\Timer' => $vendorDir . '/phpunit/php-timer/src/Timer.php', + 'SebastianBergmann\\Type\\CallableType' => $vendorDir . '/sebastian/type/src/type/CallableType.php', + 'SebastianBergmann\\Type\\Exception' => $vendorDir . '/sebastian/type/src/exception/Exception.php', + 'SebastianBergmann\\Type\\FalseType' => $vendorDir . '/sebastian/type/src/type/FalseType.php', + 'SebastianBergmann\\Type\\GenericObjectType' => $vendorDir . '/sebastian/type/src/type/GenericObjectType.php', + 'SebastianBergmann\\Type\\IntersectionType' => $vendorDir . '/sebastian/type/src/type/IntersectionType.php', + 'SebastianBergmann\\Type\\IterableType' => $vendorDir . '/sebastian/type/src/type/IterableType.php', + 'SebastianBergmann\\Type\\MixedType' => $vendorDir . '/sebastian/type/src/type/MixedType.php', + 'SebastianBergmann\\Type\\NeverType' => $vendorDir . '/sebastian/type/src/type/NeverType.php', + 'SebastianBergmann\\Type\\NullType' => $vendorDir . '/sebastian/type/src/type/NullType.php', + 'SebastianBergmann\\Type\\ObjectType' => $vendorDir . '/sebastian/type/src/type/ObjectType.php', + 'SebastianBergmann\\Type\\Parameter' => $vendorDir . '/sebastian/type/src/Parameter.php', + 'SebastianBergmann\\Type\\ReflectionMapper' => $vendorDir . '/sebastian/type/src/ReflectionMapper.php', + 'SebastianBergmann\\Type\\RuntimeException' => $vendorDir . '/sebastian/type/src/exception/RuntimeException.php', + 'SebastianBergmann\\Type\\SimpleType' => $vendorDir . '/sebastian/type/src/type/SimpleType.php', + 'SebastianBergmann\\Type\\StaticType' => $vendorDir . '/sebastian/type/src/type/StaticType.php', + 'SebastianBergmann\\Type\\TrueType' => $vendorDir . '/sebastian/type/src/type/TrueType.php', + 'SebastianBergmann\\Type\\Type' => $vendorDir . '/sebastian/type/src/type/Type.php', + 'SebastianBergmann\\Type\\TypeName' => $vendorDir . '/sebastian/type/src/TypeName.php', + 'SebastianBergmann\\Type\\UnionType' => $vendorDir . '/sebastian/type/src/type/UnionType.php', + 'SebastianBergmann\\Type\\UnknownType' => $vendorDir . '/sebastian/type/src/type/UnknownType.php', + 'SebastianBergmann\\Type\\VoidType' => $vendorDir . '/sebastian/type/src/type/VoidType.php', + 'SebastianBergmann\\Version' => $vendorDir . '/sebastian/version/src/Version.php', + 'TheSeer\\Tokenizer\\Exception' => $vendorDir . '/theseer/tokenizer/src/Exception.php', + 'TheSeer\\Tokenizer\\NamespaceUri' => $vendorDir . '/theseer/tokenizer/src/NamespaceUri.php', + 'TheSeer\\Tokenizer\\NamespaceUriException' => $vendorDir . '/theseer/tokenizer/src/NamespaceUriException.php', + 'TheSeer\\Tokenizer\\Token' => $vendorDir . '/theseer/tokenizer/src/Token.php', + 'TheSeer\\Tokenizer\\TokenCollection' => $vendorDir . '/theseer/tokenizer/src/TokenCollection.php', + 'TheSeer\\Tokenizer\\TokenCollectionException' => $vendorDir . '/theseer/tokenizer/src/TokenCollectionException.php', + 'TheSeer\\Tokenizer\\Tokenizer' => $vendorDir . '/theseer/tokenizer/src/Tokenizer.php', + 'TheSeer\\Tokenizer\\XMLSerializer' => $vendorDir . '/theseer/tokenizer/src/XMLSerializer.php', + 'WP_Mock' => $vendorDir . '/10up/wp_mock/php/WP_Mock.php', ); diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php new file mode 100644 index 00000000..00440ee1 --- /dev/null +++ b/vendor/composer/autoload_files.php @@ -0,0 +1,11 @@ + $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php', + 'ec07570ca5a812141189b1fa81503674' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert/Functions.php', +); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index c3cd0229..24d49857 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -6,5 +6,7 @@ $baseDir = dirname($vendorDir); return array( + 'TOGoS_GitIgnore_' => array($vendorDir . '/togos/gitignore/src/main/php'), 'Pimple' => array($vendorDir . '/pimple/pimple/src'), + 'Mockery' => array($vendorDir . '/mockery/mockery/library'), ); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 8cc4e05a..df0056d3 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -6,6 +6,14 @@ $baseDir = dirname($vendorDir); return array( + 'WP_Mock\\' => array($vendorDir . '/10up/wp_mock/php/WP_Mock'), + 'VariableAnalysis\\' => array($vendorDir . '/sirbrillig/phpcs-variable-analysis/VariableAnalysis'), + 'RtCamp\\GoogleLogin\\Tests\\' => array($baseDir . '/tests/php'), 'RtCamp\\GoogleLogin\\' => array($baseDir . '/src'), 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), + 'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'), + 'LastCall\\DownloadsPlugin\\' => array($vendorDir . '/civicrm/composer-downloads-plugin/src'), + 'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'), + 'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'), + 'Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => array($vendorDir . '/dealerdirect/phpcodesniffer-composer-installer/src'), ); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index d90c45be..c8dfb816 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -22,13 +22,15 @@ public static function getLoader() return self::$loader; } + require __DIR__ . '/platform_check.php'; + spl_autoload_register(array('ComposerAutoloaderInit414112f68a04b4d078687d18b2bb675e', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__))); spl_autoload_unregister(array('ComposerAutoloaderInit414112f68a04b4d078687d18b2bb675e', 'loadClassLoader')); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); if ($useStaticLoader) { - require_once __DIR__ . '/autoload_static.php'; + require __DIR__ . '/autoload_static.php'; call_user_func(\Composer\Autoload\ComposerStaticInit414112f68a04b4d078687d18b2bb675e::getInitializer($loader)); } else { @@ -50,6 +52,29 @@ public static function getLoader() $loader->register(true); + if ($useStaticLoader) { + $includeFiles = Composer\Autoload\ComposerStaticInit414112f68a04b4d078687d18b2bb675e::$files; + } else { + $includeFiles = require __DIR__ . '/autoload_files.php'; + } + foreach ($includeFiles as $fileIdentifier => $file) { + composerRequire414112f68a04b4d078687d18b2bb675e($fileIdentifier, $file); + } + return $loader; } } + +/** + * @param string $fileIdentifier + * @param string $file + * @return void + */ +function composerRequire414112f68a04b4d078687d18b2bb675e($fileIdentifier, $file) +{ + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + + require $file; + } +} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 5f324ac3..70fbac35 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -6,18 +6,55 @@ class ComposerStaticInit414112f68a04b4d078687d18b2bb675e { + public static $files = array ( + '6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php', + 'ec07570ca5a812141189b1fa81503674' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert/Functions.php', + ); + public static $prefixLengthsPsr4 = array ( + 'W' => + array ( + 'WP_Mock\\' => 8, + ), + 'V' => + array ( + 'VariableAnalysis\\' => 17, + ), 'R' => array ( + 'RtCamp\\GoogleLogin\\Tests\\' => 25, 'RtCamp\\GoogleLogin\\' => 19, ), 'P' => array ( 'Psr\\Container\\' => 14, + 'PhpParser\\' => 10, + ), + 'L' => + array ( + 'LastCall\\DownloadsPlugin\\' => 25, + ), + 'D' => + array ( + 'Doctrine\\Instantiator\\' => 22, + 'DeepCopy\\' => 9, + 'Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => 55, ), ); public static $prefixDirsPsr4 = array ( + 'WP_Mock\\' => + array ( + 0 => __DIR__ . '/..' . '/10up/wp_mock/php/WP_Mock', + ), + 'VariableAnalysis\\' => + array ( + 0 => __DIR__ . '/..' . '/sirbrillig/phpcs-variable-analysis/VariableAnalysis', + ), + 'RtCamp\\GoogleLogin\\Tests\\' => + array ( + 0 => __DIR__ . '/../..' . '/tests/php', + ), 'RtCamp\\GoogleLogin\\' => array ( 0 => __DIR__ . '/../..' . '/src', @@ -26,9 +63,36 @@ class ComposerStaticInit414112f68a04b4d078687d18b2bb675e array ( 0 => __DIR__ . '/..' . '/psr/container/src', ), + 'PhpParser\\' => + array ( + 0 => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser', + ), + 'LastCall\\DownloadsPlugin\\' => + array ( + 0 => __DIR__ . '/..' . '/civicrm/composer-downloads-plugin/src', + ), + 'Doctrine\\Instantiator\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/instantiator/src/Doctrine/Instantiator', + ), + 'DeepCopy\\' => + array ( + 0 => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy', + ), + 'Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => + array ( + 0 => __DIR__ . '/..' . '/dealerdirect/phpcodesniffer-composer-installer/src', + ), ); public static $prefixesPsr0 = array ( + 'T' => + array ( + 'TOGoS_GitIgnore_' => + array ( + 0 => __DIR__ . '/..' . '/togos/gitignore/src/main/php', + ), + ), 'P' => array ( 'Pimple' => @@ -36,6 +100,713 @@ class ComposerStaticInit414112f68a04b4d078687d18b2bb675e 0 => __DIR__ . '/..' . '/pimple/pimple/src', ), ), + 'M' => + array ( + 'Mockery' => + array ( + 0 => __DIR__ . '/..' . '/mockery/mockery/library', + ), + ), + ); + + public static $classMap = array ( + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + 'Hamcrest\\Arrays\\IsArray' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArray.php', + 'Hamcrest\\Arrays\\IsArrayContaining' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContaining.php', + 'Hamcrest\\Arrays\\IsArrayContainingInAnyOrder' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingInAnyOrder.php', + 'Hamcrest\\Arrays\\IsArrayContainingInOrder' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingInOrder.php', + 'Hamcrest\\Arrays\\IsArrayContainingKey' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingKey.php', + 'Hamcrest\\Arrays\\IsArrayContainingKeyValuePair' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingKeyValuePair.php', + 'Hamcrest\\Arrays\\IsArrayWithSize' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayWithSize.php', + 'Hamcrest\\Arrays\\MatchingOnce' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/MatchingOnce.php', + 'Hamcrest\\Arrays\\SeriesMatchingOnce' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/SeriesMatchingOnce.php', + 'Hamcrest\\AssertionError' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/AssertionError.php', + 'Hamcrest\\BaseDescription' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/BaseDescription.php', + 'Hamcrest\\BaseMatcher' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/BaseMatcher.php', + 'Hamcrest\\Collection\\IsEmptyTraversable' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Collection/IsEmptyTraversable.php', + 'Hamcrest\\Collection\\IsTraversableWithSize' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Collection/IsTraversableWithSize.php', + 'Hamcrest\\Core\\AllOf' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/AllOf.php', + 'Hamcrest\\Core\\AnyOf' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/AnyOf.php', + 'Hamcrest\\Core\\CombinableMatcher' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/CombinableMatcher.php', + 'Hamcrest\\Core\\DescribedAs' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/DescribedAs.php', + 'Hamcrest\\Core\\Every' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Every.php', + 'Hamcrest\\Core\\HasToString' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/HasToString.php', + 'Hamcrest\\Core\\Is' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Is.php', + 'Hamcrest\\Core\\IsAnything' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsAnything.php', + 'Hamcrest\\Core\\IsCollectionContaining' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsCollectionContaining.php', + 'Hamcrest\\Core\\IsEqual' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsEqual.php', + 'Hamcrest\\Core\\IsIdentical' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsIdentical.php', + 'Hamcrest\\Core\\IsInstanceOf' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsInstanceOf.php', + 'Hamcrest\\Core\\IsNot' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsNot.php', + 'Hamcrest\\Core\\IsNull' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsNull.php', + 'Hamcrest\\Core\\IsSame' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsSame.php', + 'Hamcrest\\Core\\IsTypeOf' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsTypeOf.php', + 'Hamcrest\\Core\\Set' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Set.php', + 'Hamcrest\\Core\\ShortcutCombination' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/ShortcutCombination.php', + 'Hamcrest\\Description' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Description.php', + 'Hamcrest\\DiagnosingMatcher' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/DiagnosingMatcher.php', + 'Hamcrest\\FeatureMatcher' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/FeatureMatcher.php', + 'Hamcrest\\Internal\\SelfDescribingValue' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Internal/SelfDescribingValue.php', + 'Hamcrest\\Matcher' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Matcher.php', + 'Hamcrest\\MatcherAssert' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/MatcherAssert.php', + 'Hamcrest\\Matchers' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Matchers.php', + 'Hamcrest\\NullDescription' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/NullDescription.php', + 'Hamcrest\\Number\\IsCloseTo' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Number/IsCloseTo.php', + 'Hamcrest\\Number\\OrderingComparison' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Number/OrderingComparison.php', + 'Hamcrest\\SelfDescribing' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/SelfDescribing.php', + 'Hamcrest\\StringDescription' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/StringDescription.php', + 'Hamcrest\\Text\\IsEmptyString' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEmptyString.php', + 'Hamcrest\\Text\\IsEqualIgnoringCase' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEqualIgnoringCase.php', + 'Hamcrest\\Text\\IsEqualIgnoringWhiteSpace' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEqualIgnoringWhiteSpace.php', + 'Hamcrest\\Text\\MatchesPattern' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/MatchesPattern.php', + 'Hamcrest\\Text\\StringContains' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContains.php', + 'Hamcrest\\Text\\StringContainsIgnoringCase' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContainsIgnoringCase.php', + 'Hamcrest\\Text\\StringContainsInOrder' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContainsInOrder.php', + 'Hamcrest\\Text\\StringEndsWith' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringEndsWith.php', + 'Hamcrest\\Text\\StringStartsWith' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringStartsWith.php', + 'Hamcrest\\Text\\SubstringMatcher' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/SubstringMatcher.php', + 'Hamcrest\\TypeSafeDiagnosingMatcher' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/TypeSafeDiagnosingMatcher.php', + 'Hamcrest\\TypeSafeMatcher' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/TypeSafeMatcher.php', + 'Hamcrest\\Type\\IsArray' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsArray.php', + 'Hamcrest\\Type\\IsBoolean' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsBoolean.php', + 'Hamcrest\\Type\\IsCallable' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsCallable.php', + 'Hamcrest\\Type\\IsDouble' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsDouble.php', + 'Hamcrest\\Type\\IsInteger' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsInteger.php', + 'Hamcrest\\Type\\IsNumeric' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsNumeric.php', + 'Hamcrest\\Type\\IsObject' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsObject.php', + 'Hamcrest\\Type\\IsResource' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsResource.php', + 'Hamcrest\\Type\\IsScalar' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsScalar.php', + 'Hamcrest\\Type\\IsString' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsString.php', + 'Hamcrest\\Util' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Util.php', + 'Hamcrest\\Xml\\HasXPath' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Xml/HasXPath.php', + 'PHPUnit\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Exception.php', + 'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php', + 'PHPUnit\\Framework\\Assert' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert.php', + 'PHPUnit\\Framework\\AssertionFailedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php', + 'PHPUnit\\Framework\\CodeCoverageException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotAcceptParameterTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotAcceptParameterTypeException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareBoolReturnTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareExactlyOneParameterException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareParameterTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareParameterTypeException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotExistException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotExistException.php', + 'PHPUnit\\Framework\\Constraint\\ArrayHasKey' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php', + 'PHPUnit\\Framework\\Constraint\\BinaryOperator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php', + 'PHPUnit\\Framework\\Constraint\\Callback' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Callback.php', + 'PHPUnit\\Framework\\Constraint\\ClassHasAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasAttribute.php', + 'PHPUnit\\Framework\\Constraint\\ClassHasStaticAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasStaticAttribute.php', + 'PHPUnit\\Framework\\Constraint\\Constraint' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Constraint.php', + 'PHPUnit\\Framework\\Constraint\\Count' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php', + 'PHPUnit\\Framework\\Constraint\\DirectoryExists' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php', + 'PHPUnit\\Framework\\Constraint\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php', + 'PHPUnit\\Framework\\Constraint\\ExceptionCode' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php', + 'PHPUnit\\Framework\\Constraint\\ExceptionMessage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessage.php', + 'PHPUnit\\Framework\\Constraint\\ExceptionMessageRegularExpression' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageRegularExpression.php', + 'PHPUnit\\Framework\\Constraint\\FileExists' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php', + 'PHPUnit\\Framework\\Constraint\\GreaterThan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php', + 'PHPUnit\\Framework\\Constraint\\IsAnything' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php', + 'PHPUnit\\Framework\\Constraint\\IsEmpty' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php', + 'PHPUnit\\Framework\\Constraint\\IsEqual' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php', + 'PHPUnit\\Framework\\Constraint\\IsEqualCanonicalizing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php', + 'PHPUnit\\Framework\\Constraint\\IsEqualIgnoringCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php', + 'PHPUnit\\Framework\\Constraint\\IsEqualWithDelta' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php', + 'PHPUnit\\Framework\\Constraint\\IsFalse' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php', + 'PHPUnit\\Framework\\Constraint\\IsFinite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php', + 'PHPUnit\\Framework\\Constraint\\IsIdentical' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php', + 'PHPUnit\\Framework\\Constraint\\IsInfinite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php', + 'PHPUnit\\Framework\\Constraint\\IsInstanceOf' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php', + 'PHPUnit\\Framework\\Constraint\\IsJson' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php', + 'PHPUnit\\Framework\\Constraint\\IsNan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php', + 'PHPUnit\\Framework\\Constraint\\IsNull' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php', + 'PHPUnit\\Framework\\Constraint\\IsReadable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php', + 'PHPUnit\\Framework\\Constraint\\IsTrue' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php', + 'PHPUnit\\Framework\\Constraint\\IsType' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php', + 'PHPUnit\\Framework\\Constraint\\IsWritable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php', + 'PHPUnit\\Framework\\Constraint\\JsonMatches' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php', + 'PHPUnit\\Framework\\Constraint\\JsonMatchesErrorMessageProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php', + 'PHPUnit\\Framework\\Constraint\\LessThan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php', + 'PHPUnit\\Framework\\Constraint\\LogicalAnd' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php', + 'PHPUnit\\Framework\\Constraint\\LogicalNot' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php', + 'PHPUnit\\Framework\\Constraint\\LogicalOr' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php', + 'PHPUnit\\Framework\\Constraint\\LogicalXor' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php', + 'PHPUnit\\Framework\\Constraint\\ObjectEquals' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php', + 'PHPUnit\\Framework\\Constraint\\ObjectHasAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasAttribute.php', + 'PHPUnit\\Framework\\Constraint\\Operator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php', + 'PHPUnit\\Framework\\Constraint\\RegularExpression' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php', + 'PHPUnit\\Framework\\Constraint\\SameSize' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php', + 'PHPUnit\\Framework\\Constraint\\StringContains' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php', + 'PHPUnit\\Framework\\Constraint\\StringEndsWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php', + 'PHPUnit\\Framework\\Constraint\\StringMatchesFormatDescription' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php', + 'PHPUnit\\Framework\\Constraint\\StringStartsWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContains' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContainsEqual' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContainsIdentical' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContainsOnly' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php', + 'PHPUnit\\Framework\\Constraint\\UnaryOperator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php', + 'PHPUnit\\Framework\\CoveredCodeNotExecutedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/CoveredCodeNotExecutedException.php', + 'PHPUnit\\Framework\\DataProviderTestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/DataProviderTestSuite.php', + 'PHPUnit\\Framework\\Error' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Error.php', + 'PHPUnit\\Framework\\ErrorTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/ErrorTestCase.php', + 'PHPUnit\\Framework\\Error\\Deprecated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Deprecated.php', + 'PHPUnit\\Framework\\Error\\Error' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Error.php', + 'PHPUnit\\Framework\\Error\\Notice' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Notice.php', + 'PHPUnit\\Framework\\Error\\Warning' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Warning.php', + 'PHPUnit\\Framework\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Exception.php', + 'PHPUnit\\Framework\\ExceptionWrapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/ExceptionWrapper.php', + 'PHPUnit\\Framework\\ExecutionOrderDependency' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php', + 'PHPUnit\\Framework\\ExpectationFailedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php', + 'PHPUnit\\Framework\\IncompleteTest' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/IncompleteTest.php', + 'PHPUnit\\Framework\\IncompleteTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/IncompleteTestCase.php', + 'PHPUnit\\Framework\\IncompleteTestError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/IncompleteTestError.php', + 'PHPUnit\\Framework\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php', + 'PHPUnit\\Framework\\InvalidCoversTargetException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php', + 'PHPUnit\\Framework\\InvalidDataProviderException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php', + 'PHPUnit\\Framework\\InvalidParameterGroupException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/InvalidParameterGroupException.php', + 'PHPUnit\\Framework\\MissingCoversAnnotationException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/MissingCoversAnnotationException.php', + 'PHPUnit\\Framework\\MockObject\\Api' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Api/Api.php', + 'PHPUnit\\Framework\\MockObject\\BadMethodCallException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\Identity' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/Identity.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationMocker' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationMocker.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationStubber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationStubber.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\MethodNameMatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/MethodNameMatch.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\ParametersMatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/ParametersMatch.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Builder/Stub.php', + 'PHPUnit\\Framework\\MockObject\\CannotUseAddMethodsException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseAddMethodsException.php', + 'PHPUnit\\Framework\\MockObject\\CannotUseOnlyMethodsException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php', + 'PHPUnit\\Framework\\MockObject\\ClassAlreadyExistsException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/ClassAlreadyExistsException.php', + 'PHPUnit\\Framework\\MockObject\\ClassIsFinalException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsFinalException.php', + 'PHPUnit\\Framework\\MockObject\\ClassIsReadonlyException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsReadonlyException.php', + 'PHPUnit\\Framework\\MockObject\\ConfigurableMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php', + 'PHPUnit\\Framework\\MockObject\\ConfigurableMethodsAlreadyInitializedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/ConfigurableMethodsAlreadyInitializedException.php', + 'PHPUnit\\Framework\\MockObject\\DuplicateMethodException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/DuplicateMethodException.php', + 'PHPUnit\\Framework\\MockObject\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php', + 'PHPUnit\\Framework\\MockObject\\Generator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator.php', + 'PHPUnit\\Framework\\MockObject\\IncompatibleReturnValueException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php', + 'PHPUnit\\Framework\\MockObject\\InvalidMethodNameException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/InvalidMethodNameException.php', + 'PHPUnit\\Framework\\MockObject\\Invocation' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Invocation.php', + 'PHPUnit\\Framework\\MockObject\\InvocationHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/InvocationHandler.php', + 'PHPUnit\\Framework\\MockObject\\MatchBuilderNotFoundException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php', + 'PHPUnit\\Framework\\MockObject\\Matcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Matcher.php', + 'PHPUnit\\Framework\\MockObject\\MatcherAlreadyRegisteredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php', + 'PHPUnit\\Framework\\MockObject\\Method' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Api/Method.php', + 'PHPUnit\\Framework\\MockObject\\MethodCannotBeConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MethodNameAlreadyConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MethodNameConstraint' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MethodNameConstraint.php', + 'PHPUnit\\Framework\\MockObject\\MethodNameNotConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MethodParametersAlreadyConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MockBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php', + 'PHPUnit\\Framework\\MockObject\\MockClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockClass.php', + 'PHPUnit\\Framework\\MockObject\\MockMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockMethod.php', + 'PHPUnit\\Framework\\MockObject\\MockMethodSet' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockMethodSet.php', + 'PHPUnit\\Framework\\MockObject\\MockObject' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockObject.php', + 'PHPUnit\\Framework\\MockObject\\MockTrait' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockTrait.php', + 'PHPUnit\\Framework\\MockObject\\MockType' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockType.php', + 'PHPUnit\\Framework\\MockObject\\OriginalConstructorInvocationRequiredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/OriginalConstructorInvocationRequiredException.php', + 'PHPUnit\\Framework\\MockObject\\ReflectionException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/ReflectionException.php', + 'PHPUnit\\Framework\\MockObject\\ReturnValueNotConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\AnyInvokedCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/AnyInvokedCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\AnyParameters' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/AnyParameters.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\ConsecutiveParameters' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/ConsecutiveParameters.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvocationOrder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvocationOrder.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtIndex' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtIndex.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastOnce' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastOnce.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtMostCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtMostCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\MethodName' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/MethodName.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\Parameters' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/Parameters.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\ParametersRule' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Rule/ParametersRule.php', + 'PHPUnit\\Framework\\MockObject\\RuntimeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php', + 'PHPUnit\\Framework\\MockObject\\SoapExtensionNotAvailableException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/SoapExtensionNotAvailableException.php', + 'PHPUnit\\Framework\\MockObject\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ConsecutiveCalls' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ConsecutiveCalls.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/Exception.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnArgument' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnArgument.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnCallback' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnCallback.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnReference' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnReference.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnSelf' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnSelf.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnStub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnStub.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnValueMap' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnValueMap.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Stub/Stub.php', + 'PHPUnit\\Framework\\MockObject\\UnknownClassException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownClassException.php', + 'PHPUnit\\Framework\\MockObject\\UnknownTraitException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTraitException.php', + 'PHPUnit\\Framework\\MockObject\\UnknownTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTypeException.php', + 'PHPUnit\\Framework\\MockObject\\Verifiable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Verifiable.php', + 'PHPUnit\\Framework\\NoChildTestSuiteException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php', + 'PHPUnit\\Framework\\OutputError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/OutputError.php', + 'PHPUnit\\Framework\\PHPTAssertionFailedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/PHPTAssertionFailedError.php', + 'PHPUnit\\Framework\\Reorderable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Reorderable.php', + 'PHPUnit\\Framework\\RiskyTestError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/RiskyTestError.php', + 'PHPUnit\\Framework\\SelfDescribing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SelfDescribing.php', + 'PHPUnit\\Framework\\SkippedTest' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SkippedTest.php', + 'PHPUnit\\Framework\\SkippedTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SkippedTestCase.php', + 'PHPUnit\\Framework\\SkippedTestError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/SkippedTestError.php', + 'PHPUnit\\Framework\\SkippedTestSuiteError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/SkippedTestSuiteError.php', + 'PHPUnit\\Framework\\SyntheticError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/SyntheticError.php', + 'PHPUnit\\Framework\\SyntheticSkippedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/SyntheticSkippedError.php', + 'PHPUnit\\Framework\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Test.php', + 'PHPUnit\\Framework\\TestBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestBuilder.php', + 'PHPUnit\\Framework\\TestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestCase.php', + 'PHPUnit\\Framework\\TestFailure' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestFailure.php', + 'PHPUnit\\Framework\\TestListener' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestListener.php', + 'PHPUnit\\Framework\\TestListenerDefaultImplementation' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestListenerDefaultImplementation.php', + 'PHPUnit\\Framework\\TestResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestResult.php', + 'PHPUnit\\Framework\\TestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSuite.php', + 'PHPUnit\\Framework\\TestSuiteIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSuiteIterator.php', + 'PHPUnit\\Framework\\UnintentionallyCoveredCodeError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/UnintentionallyCoveredCodeError.php', + 'PHPUnit\\Framework\\Warning' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Warning.php', + 'PHPUnit\\Framework\\WarningTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/WarningTestCase.php', + 'PHPUnit\\Runner\\AfterIncompleteTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterIncompleteTestHook.php', + 'PHPUnit\\Runner\\AfterLastTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterLastTestHook.php', + 'PHPUnit\\Runner\\AfterRiskyTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterRiskyTestHook.php', + 'PHPUnit\\Runner\\AfterSkippedTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterSkippedTestHook.php', + 'PHPUnit\\Runner\\AfterSuccessfulTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterSuccessfulTestHook.php', + 'PHPUnit\\Runner\\AfterTestErrorHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterTestErrorHook.php', + 'PHPUnit\\Runner\\AfterTestFailureHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterTestFailureHook.php', + 'PHPUnit\\Runner\\AfterTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterTestHook.php', + 'PHPUnit\\Runner\\AfterTestWarningHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/AfterTestWarningHook.php', + 'PHPUnit\\Runner\\BaseTestRunner' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/BaseTestRunner.php', + 'PHPUnit\\Runner\\BeforeFirstTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/BeforeFirstTestHook.php', + 'PHPUnit\\Runner\\BeforeTestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/BeforeTestHook.php', + 'PHPUnit\\Runner\\DefaultTestResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/DefaultTestResultCache.php', + 'PHPUnit\\Runner\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception.php', + 'PHPUnit\\Runner\\Extension\\ExtensionHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Extension/ExtensionHandler.php', + 'PHPUnit\\Runner\\Extension\\PharLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Extension/PharLoader.php', + 'PHPUnit\\Runner\\Filter\\ExcludeGroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php', + 'PHPUnit\\Runner\\Filter\\Factory' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/Factory.php', + 'PHPUnit\\Runner\\Filter\\GroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php', + 'PHPUnit\\Runner\\Filter\\IncludeGroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php', + 'PHPUnit\\Runner\\Filter\\NameFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php', + 'PHPUnit\\Runner\\Hook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/Hook.php', + 'PHPUnit\\Runner\\NullTestResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/NullTestResultCache.php', + 'PHPUnit\\Runner\\PhptTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/PhptTestCase.php', + 'PHPUnit\\Runner\\ResultCacheExtension' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCacheExtension.php', + 'PHPUnit\\Runner\\StandardTestSuiteLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php', + 'PHPUnit\\Runner\\TestHook' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/TestHook.php', + 'PHPUnit\\Runner\\TestListenerAdapter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Hook/TestListenerAdapter.php', + 'PHPUnit\\Runner\\TestResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResultCache.php', + 'PHPUnit\\Runner\\TestSuiteLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php', + 'PHPUnit\\Runner\\TestSuiteSorter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestSuiteSorter.php', + 'PHPUnit\\Runner\\Version' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Version.php', + 'PHPUnit\\TextUI\\CliArguments\\Builder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/CliArguments/Builder.php', + 'PHPUnit\\TextUI\\CliArguments\\Configuration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/CliArguments/Configuration.php', + 'PHPUnit\\TextUI\\CliArguments\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/CliArguments/Exception.php', + 'PHPUnit\\TextUI\\CliArguments\\Mapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/CliArguments/Mapper.php', + 'PHPUnit\\TextUI\\Command' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command.php', + 'PHPUnit\\TextUI\\DefaultResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/DefaultResultPrinter.php', + 'PHPUnit\\TextUI\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/Exception.php', + 'PHPUnit\\TextUI\\Help' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Help.php', + 'PHPUnit\\TextUI\\ReflectionException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/ReflectionException.php', + 'PHPUnit\\TextUI\\ResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/ResultPrinter.php', + 'PHPUnit\\TextUI\\RuntimeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php', + 'PHPUnit\\TextUI\\TestDirectoryNotFoundException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php', + 'PHPUnit\\TextUI\\TestFileNotFoundException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php', + 'PHPUnit\\TextUI\\TestRunner' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/TestRunner.php', + 'PHPUnit\\TextUI\\TestSuiteMapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/TestSuiteMapper.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\CodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/CodeCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\FilterMapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/FilterMapper.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Filter\\Directory' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/Directory.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Filter\\DirectoryCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Filter\\DirectoryCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Clover' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Clover.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Cobertura' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Cobertura.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Crap4j' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Crap4j.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Html' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Html.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Php' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Php.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Text' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Text.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Xml' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Xml.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Configuration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Configuration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Constant' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Constant.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\ConstantCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\ConstantCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\ConvertLogTypes' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/ConvertLogTypes.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCloverToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCloverToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCrap4jToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCrap4jToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageHtmlToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageHtmlToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoveragePhpToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoveragePhpToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageTextToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageTextToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageXmlToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageXmlToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Directory' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/Directory.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\DirectoryCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\DirectoryCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Exception.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Extension' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/Extension.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\ExtensionCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\ExtensionCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\File' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/File.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\FileCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\FileCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Generator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Generator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Group' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Group.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\GroupCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\GroupCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Groups' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Groups.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\IniSetting' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSetting.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\IniSettingCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\IniSettingCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\IntroduceCoverageElement' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/IntroduceCoverageElement.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Loader' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Loader.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\LogToReportMigration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/LogToReportMigration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Junit' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Junit.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Logging' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Logging.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TeamCity' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TeamCity.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Html' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Html.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Text' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Text.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Xml' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Xml.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Text' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Text.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Migration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/Migration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MigrationBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilder.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MigrationBuilderException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilderException.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MigrationException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationException.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Migrator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromFilterWhitelistToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromRootToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromRootToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistDirectoriesToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistDirectoriesToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistExcludesToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistExcludesToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\PHPUnit' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/PHPUnit.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Php' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Php.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\PhpHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/PhpHandler.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCacheTokensAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveCacheTokensAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveEmptyFilter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveEmptyFilter.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveLogTypes' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveLogTypes.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestDirectory' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectory.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestDirectoryCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestDirectoryCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestFile' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFile.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestFileCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestFileCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuite.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestSuiteCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestSuiteCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollectionIterator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\UpdateSchemaLocationTo93' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/UpdateSchemaLocationTo93.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Variable' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Variable.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\VariableCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollection.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\VariableCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollectionIterator.php', + 'PHPUnit\\Util\\Annotation\\DocBlock' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Annotation/DocBlock.php', + 'PHPUnit\\Util\\Annotation\\Registry' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Annotation/Registry.php', + 'PHPUnit\\Util\\Blacklist' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Blacklist.php', + 'PHPUnit\\Util\\Cloner' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Cloner.php', + 'PHPUnit\\Util\\Color' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Color.php', + 'PHPUnit\\Util\\ErrorHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/ErrorHandler.php', + 'PHPUnit\\Util\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception.php', + 'PHPUnit\\Util\\ExcludeList' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/ExcludeList.php', + 'PHPUnit\\Util\\FileLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/FileLoader.php', + 'PHPUnit\\Util\\Filesystem' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Filesystem.php', + 'PHPUnit\\Util\\Filter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Filter.php', + 'PHPUnit\\Util\\GlobalState' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/GlobalState.php', + 'PHPUnit\\Util\\InvalidDataSetException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/InvalidDataSetException.php', + 'PHPUnit\\Util\\Json' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Json.php', + 'PHPUnit\\Util\\Log\\JUnit' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Log/JUnit.php', + 'PHPUnit\\Util\\Log\\TeamCity' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Log/TeamCity.php', + 'PHPUnit\\Util\\PHP\\AbstractPhpProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php', + 'PHPUnit\\Util\\PHP\\DefaultPhpProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php', + 'PHPUnit\\Util\\PHP\\WindowsPhpProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/WindowsPhpProcess.php', + 'PHPUnit\\Util\\Printer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Printer.php', + 'PHPUnit\\Util\\Reflection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Reflection.php', + 'PHPUnit\\Util\\RegularExpression' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/RegularExpression.php', + 'PHPUnit\\Util\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Test.php', + 'PHPUnit\\Util\\TestDox\\CliTestDoxPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/CliTestDoxPrinter.php', + 'PHPUnit\\Util\\TestDox\\HtmlResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/HtmlResultPrinter.php', + 'PHPUnit\\Util\\TestDox\\NamePrettifier' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php', + 'PHPUnit\\Util\\TestDox\\ResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php', + 'PHPUnit\\Util\\TestDox\\TestDoxPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/TestDoxPrinter.php', + 'PHPUnit\\Util\\TestDox\\TextResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/TextResultPrinter.php', + 'PHPUnit\\Util\\TestDox\\XmlResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/XmlResultPrinter.php', + 'PHPUnit\\Util\\TextTestListRenderer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TextTestListRenderer.php', + 'PHPUnit\\Util\\Type' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Type.php', + 'PHPUnit\\Util\\VersionComparisonOperator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/VersionComparisonOperator.php', + 'PHPUnit\\Util\\XdebugFilterScriptGenerator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/XdebugFilterScriptGenerator.php', + 'PHPUnit\\Util\\Xml' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml.php', + 'PHPUnit\\Util\\XmlTestListRenderer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/XmlTestListRenderer.php', + 'PHPUnit\\Util\\Xml\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/Exception.php', + 'PHPUnit\\Util\\Xml\\FailedSchemaDetectionResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/FailedSchemaDetectionResult.php', + 'PHPUnit\\Util\\Xml\\Loader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/Loader.php', + 'PHPUnit\\Util\\Xml\\SchemaDetectionResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/SchemaDetectionResult.php', + 'PHPUnit\\Util\\Xml\\SchemaDetector' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/SchemaDetector.php', + 'PHPUnit\\Util\\Xml\\SchemaFinder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/SchemaFinder.php', + 'PHPUnit\\Util\\Xml\\SnapshotNodeList' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/SnapshotNodeList.php', + 'PHPUnit\\Util\\Xml\\SuccessfulSchemaDetectionResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/SuccessfulSchemaDetectionResult.php', + 'PHPUnit\\Util\\Xml\\ValidationResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/ValidationResult.php', + 'PHPUnit\\Util\\Xml\\Validator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/Validator.php', + 'PharIo\\Manifest\\Application' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Application.php', + 'PharIo\\Manifest\\ApplicationName' => __DIR__ . '/..' . '/phar-io/manifest/src/values/ApplicationName.php', + 'PharIo\\Manifest\\Author' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Author.php', + 'PharIo\\Manifest\\AuthorCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/AuthorCollection.php', + 'PharIo\\Manifest\\AuthorCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/AuthorCollectionIterator.php', + 'PharIo\\Manifest\\AuthorElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/AuthorElement.php', + 'PharIo\\Manifest\\AuthorElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/AuthorElementCollection.php', + 'PharIo\\Manifest\\BundledComponent' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponent.php', + 'PharIo\\Manifest\\BundledComponentCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponentCollection.php', + 'PharIo\\Manifest\\BundledComponentCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponentCollectionIterator.php', + 'PharIo\\Manifest\\BundlesElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/BundlesElement.php', + 'PharIo\\Manifest\\ComponentElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ComponentElement.php', + 'PharIo\\Manifest\\ComponentElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ComponentElementCollection.php', + 'PharIo\\Manifest\\ContainsElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ContainsElement.php', + 'PharIo\\Manifest\\CopyrightElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/CopyrightElement.php', + 'PharIo\\Manifest\\CopyrightInformation' => __DIR__ . '/..' . '/phar-io/manifest/src/values/CopyrightInformation.php', + 'PharIo\\Manifest\\ElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ElementCollection.php', + 'PharIo\\Manifest\\ElementCollectionException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ElementCollectionException.php', + 'PharIo\\Manifest\\Email' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Email.php', + 'PharIo\\Manifest\\Exception' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/Exception.php', + 'PharIo\\Manifest\\ExtElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtElement.php', + 'PharIo\\Manifest\\ExtElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtElementCollection.php', + 'PharIo\\Manifest\\Extension' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Extension.php', + 'PharIo\\Manifest\\ExtensionElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtensionElement.php', + 'PharIo\\Manifest\\InvalidApplicationNameException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php', + 'PharIo\\Manifest\\InvalidEmailException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidEmailException.php', + 'PharIo\\Manifest\\InvalidUrlException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidUrlException.php', + 'PharIo\\Manifest\\Library' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Library.php', + 'PharIo\\Manifest\\License' => __DIR__ . '/..' . '/phar-io/manifest/src/values/License.php', + 'PharIo\\Manifest\\LicenseElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/LicenseElement.php', + 'PharIo\\Manifest\\Manifest' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Manifest.php', + 'PharIo\\Manifest\\ManifestDocument' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ManifestDocument.php', + 'PharIo\\Manifest\\ManifestDocumentException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentException.php', + 'PharIo\\Manifest\\ManifestDocumentLoadingException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php', + 'PharIo\\Manifest\\ManifestDocumentMapper' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestDocumentMapper.php', + 'PharIo\\Manifest\\ManifestDocumentMapperException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php', + 'PharIo\\Manifest\\ManifestElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ManifestElement.php', + 'PharIo\\Manifest\\ManifestElementException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestElementException.php', + 'PharIo\\Manifest\\ManifestLoader' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestLoader.php', + 'PharIo\\Manifest\\ManifestLoaderException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestLoaderException.php', + 'PharIo\\Manifest\\ManifestSerializer' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestSerializer.php', + 'PharIo\\Manifest\\PhpElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/PhpElement.php', + 'PharIo\\Manifest\\PhpExtensionRequirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/PhpExtensionRequirement.php', + 'PharIo\\Manifest\\PhpVersionRequirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/PhpVersionRequirement.php', + 'PharIo\\Manifest\\Requirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Requirement.php', + 'PharIo\\Manifest\\RequirementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/RequirementCollection.php', + 'PharIo\\Manifest\\RequirementCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/RequirementCollectionIterator.php', + 'PharIo\\Manifest\\RequiresElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/RequiresElement.php', + 'PharIo\\Manifest\\Type' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Type.php', + 'PharIo\\Manifest\\Url' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Url.php', + 'PharIo\\Version\\AbstractVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AbstractVersionConstraint.php', + 'PharIo\\Version\\AndVersionConstraintGroup' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AndVersionConstraintGroup.php', + 'PharIo\\Version\\AnyVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AnyVersionConstraint.php', + 'PharIo\\Version\\BuildMetaData' => __DIR__ . '/..' . '/phar-io/version/src/BuildMetaData.php', + 'PharIo\\Version\\ExactVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/ExactVersionConstraint.php', + 'PharIo\\Version\\Exception' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/Exception.php', + 'PharIo\\Version\\GreaterThanOrEqualToVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php', + 'PharIo\\Version\\InvalidPreReleaseSuffixException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php', + 'PharIo\\Version\\InvalidVersionException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/InvalidVersionException.php', + 'PharIo\\Version\\NoBuildMetaDataException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/NoBuildMetaDataException.php', + 'PharIo\\Version\\NoPreReleaseSuffixException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/NoPreReleaseSuffixException.php', + 'PharIo\\Version\\OrVersionConstraintGroup' => __DIR__ . '/..' . '/phar-io/version/src/constraints/OrVersionConstraintGroup.php', + 'PharIo\\Version\\PreReleaseSuffix' => __DIR__ . '/..' . '/phar-io/version/src/PreReleaseSuffix.php', + 'PharIo\\Version\\SpecificMajorAndMinorVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php', + 'PharIo\\Version\\SpecificMajorVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php', + 'PharIo\\Version\\UnsupportedVersionConstraintException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.php', + 'PharIo\\Version\\Version' => __DIR__ . '/..' . '/phar-io/version/src/Version.php', + 'PharIo\\Version\\VersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/VersionConstraint.php', + 'PharIo\\Version\\VersionConstraintParser' => __DIR__ . '/..' . '/phar-io/version/src/VersionConstraintParser.php', + 'PharIo\\Version\\VersionConstraintValue' => __DIR__ . '/..' . '/phar-io/version/src/VersionConstraintValue.php', + 'PharIo\\Version\\VersionNumber' => __DIR__ . '/..' . '/phar-io/version/src/VersionNumber.php', + 'SebastianBergmann\\CliParser\\AmbiguousOptionException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php', + 'SebastianBergmann\\CliParser\\Exception' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/Exception.php', + 'SebastianBergmann\\CliParser\\OptionDoesNotAllowArgumentException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php', + 'SebastianBergmann\\CliParser\\Parser' => __DIR__ . '/..' . '/sebastian/cli-parser/src/Parser.php', + 'SebastianBergmann\\CliParser\\RequiredOptionArgumentMissingException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php', + 'SebastianBergmann\\CliParser\\UnknownOptionException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/UnknownOptionException.php', + 'SebastianBergmann\\CodeCoverage\\BranchAndPathCoverageNotSupportedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php', + 'SebastianBergmann\\CodeCoverage\\CodeCoverage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage.php', + 'SebastianBergmann\\CodeCoverage\\DeadCodeDetectionNotSupportedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Driver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Driver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PathExistsButIsNotDirectoryException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PcovDriver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/PcovDriver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PcovNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PhpdbgDriver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/PhpdbgDriver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PhpdbgNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/PhpdbgNotAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Selector' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Selector.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\WriteOperationFailedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\WrongXdebugVersionException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/WrongXdebugVersionException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug2Driver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Xdebug2Driver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug2NotEnabledException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/Xdebug2NotEnabledException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug3Driver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Xdebug3Driver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Xdebug3NotEnabledException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/Xdebug3NotEnabledException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\Exception' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/Exception.php', + 'SebastianBergmann\\CodeCoverage\\Filter' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Filter.php', + 'SebastianBergmann\\CodeCoverage\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php', + 'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverWithPathCoverageSupportAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\Node\\AbstractNode' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/AbstractNode.php', + 'SebastianBergmann\\CodeCoverage\\Node\\Builder' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Builder.php', + 'SebastianBergmann\\CodeCoverage\\Node\\CrapIndex' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/CrapIndex.php', + 'SebastianBergmann\\CodeCoverage\\Node\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Directory.php', + 'SebastianBergmann\\CodeCoverage\\Node\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/File.php', + 'SebastianBergmann\\CodeCoverage\\Node\\Iterator' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Iterator.php', + 'SebastianBergmann\\CodeCoverage\\ParserException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ParserException.php', + 'SebastianBergmann\\CodeCoverage\\ProcessedCodeCoverageData' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/ProcessedCodeCoverageData.php', + 'SebastianBergmann\\CodeCoverage\\RawCodeCoverageData' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/RawCodeCoverageData.php', + 'SebastianBergmann\\CodeCoverage\\ReflectionException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ReflectionException.php', + 'SebastianBergmann\\CodeCoverage\\ReportAlreadyFinalizedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Clover' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Clover.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Cobertura' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Cobertura.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Crap4j' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Crap4j.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Dashboard' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Facade' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Facade.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Renderer' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer.php', + 'SebastianBergmann\\CodeCoverage\\Report\\PHP' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/PHP.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Text' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Text.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\BuildInformation' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Coverage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Coverage.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Directory.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Facade' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Facade.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/File.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Method' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Method.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Node' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Node.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Project' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Project.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Report' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Report.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Source' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Source.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Tests' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Tests.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Totals' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Totals.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Unit' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Unit.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysisCacheNotConfiguredException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CacheWarmer' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CachingFileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CodeUnitFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ExecutableLinesFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\FileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\IgnoredLinesFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ParsingFileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php', + 'SebastianBergmann\\CodeCoverage\\TestIdMissingException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php', + 'SebastianBergmann\\CodeCoverage\\UnintentionallyCoveredCodeException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php', + 'SebastianBergmann\\CodeCoverage\\Util\\DirectoryCouldNotBeCreatedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php', + 'SebastianBergmann\\CodeCoverage\\Util\\Filesystem' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Util/Filesystem.php', + 'SebastianBergmann\\CodeCoverage\\Util\\Percentage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Util/Percentage.php', + 'SebastianBergmann\\CodeCoverage\\Version' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Version.php', + 'SebastianBergmann\\CodeCoverage\\XmlException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/XmlException.php', + 'SebastianBergmann\\CodeUnitReverseLookup\\Wizard' => __DIR__ . '/..' . '/sebastian/code-unit-reverse-lookup/src/Wizard.php', + 'SebastianBergmann\\CodeUnit\\ClassMethodUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/ClassMethodUnit.php', + 'SebastianBergmann\\CodeUnit\\ClassUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/ClassUnit.php', + 'SebastianBergmann\\CodeUnit\\CodeUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/CodeUnit.php', + 'SebastianBergmann\\CodeUnit\\CodeUnitCollection' => __DIR__ . '/..' . '/sebastian/code-unit/src/CodeUnitCollection.php', + 'SebastianBergmann\\CodeUnit\\CodeUnitCollectionIterator' => __DIR__ . '/..' . '/sebastian/code-unit/src/CodeUnitCollectionIterator.php', + 'SebastianBergmann\\CodeUnit\\Exception' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/Exception.php', + 'SebastianBergmann\\CodeUnit\\FunctionUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/FunctionUnit.php', + 'SebastianBergmann\\CodeUnit\\InterfaceMethodUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/InterfaceMethodUnit.php', + 'SebastianBergmann\\CodeUnit\\InterfaceUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/InterfaceUnit.php', + 'SebastianBergmann\\CodeUnit\\InvalidCodeUnitException' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php', + 'SebastianBergmann\\CodeUnit\\Mapper' => __DIR__ . '/..' . '/sebastian/code-unit/src/Mapper.php', + 'SebastianBergmann\\CodeUnit\\NoTraitException' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/NoTraitException.php', + 'SebastianBergmann\\CodeUnit\\ReflectionException' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/ReflectionException.php', + 'SebastianBergmann\\CodeUnit\\TraitMethodUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/TraitMethodUnit.php', + 'SebastianBergmann\\CodeUnit\\TraitUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/TraitUnit.php', + 'SebastianBergmann\\Comparator\\ArrayComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ArrayComparator.php', + 'SebastianBergmann\\Comparator\\Comparator' => __DIR__ . '/..' . '/sebastian/comparator/src/Comparator.php', + 'SebastianBergmann\\Comparator\\ComparisonFailure' => __DIR__ . '/..' . '/sebastian/comparator/src/ComparisonFailure.php', + 'SebastianBergmann\\Comparator\\DOMNodeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DOMNodeComparator.php', + 'SebastianBergmann\\Comparator\\DateTimeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DateTimeComparator.php', + 'SebastianBergmann\\Comparator\\DoubleComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DoubleComparator.php', + 'SebastianBergmann\\Comparator\\Exception' => __DIR__ . '/..' . '/sebastian/comparator/src/exceptions/Exception.php', + 'SebastianBergmann\\Comparator\\ExceptionComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ExceptionComparator.php', + 'SebastianBergmann\\Comparator\\Factory' => __DIR__ . '/..' . '/sebastian/comparator/src/Factory.php', + 'SebastianBergmann\\Comparator\\MockObjectComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/MockObjectComparator.php', + 'SebastianBergmann\\Comparator\\NumericComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/NumericComparator.php', + 'SebastianBergmann\\Comparator\\ObjectComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ObjectComparator.php', + 'SebastianBergmann\\Comparator\\ResourceComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ResourceComparator.php', + 'SebastianBergmann\\Comparator\\RuntimeException' => __DIR__ . '/..' . '/sebastian/comparator/src/exceptions/RuntimeException.php', + 'SebastianBergmann\\Comparator\\ScalarComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ScalarComparator.php', + 'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/SplObjectStorageComparator.php', + 'SebastianBergmann\\Comparator\\TypeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/TypeComparator.php', + 'SebastianBergmann\\Complexity\\Calculator' => __DIR__ . '/..' . '/sebastian/complexity/src/Calculator.php', + 'SebastianBergmann\\Complexity\\Complexity' => __DIR__ . '/..' . '/sebastian/complexity/src/Complexity/Complexity.php', + 'SebastianBergmann\\Complexity\\ComplexityCalculatingVisitor' => __DIR__ . '/..' . '/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php', + 'SebastianBergmann\\Complexity\\ComplexityCollection' => __DIR__ . '/..' . '/sebastian/complexity/src/Complexity/ComplexityCollection.php', + 'SebastianBergmann\\Complexity\\ComplexityCollectionIterator' => __DIR__ . '/..' . '/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php', + 'SebastianBergmann\\Complexity\\CyclomaticComplexityCalculatingVisitor' => __DIR__ . '/..' . '/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php', + 'SebastianBergmann\\Complexity\\Exception' => __DIR__ . '/..' . '/sebastian/complexity/src/Exception/Exception.php', + 'SebastianBergmann\\Complexity\\RuntimeException' => __DIR__ . '/..' . '/sebastian/complexity/src/Exception/RuntimeException.php', + 'SebastianBergmann\\Diff\\Chunk' => __DIR__ . '/..' . '/sebastian/diff/src/Chunk.php', + 'SebastianBergmann\\Diff\\ConfigurationException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/ConfigurationException.php', + 'SebastianBergmann\\Diff\\Diff' => __DIR__ . '/..' . '/sebastian/diff/src/Diff.php', + 'SebastianBergmann\\Diff\\Differ' => __DIR__ . '/..' . '/sebastian/diff/src/Differ.php', + 'SebastianBergmann\\Diff\\Exception' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/Exception.php', + 'SebastianBergmann\\Diff\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/InvalidArgumentException.php', + 'SebastianBergmann\\Diff\\Line' => __DIR__ . '/..' . '/sebastian/diff/src/Line.php', + 'SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php', + 'SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php', + 'SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php', + 'SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php', + 'SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php', + 'SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php', + 'SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php', + 'SebastianBergmann\\Diff\\Parser' => __DIR__ . '/..' . '/sebastian/diff/src/Parser.php', + 'SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php', + 'SebastianBergmann\\Environment\\Console' => __DIR__ . '/..' . '/sebastian/environment/src/Console.php', + 'SebastianBergmann\\Environment\\OperatingSystem' => __DIR__ . '/..' . '/sebastian/environment/src/OperatingSystem.php', + 'SebastianBergmann\\Environment\\Runtime' => __DIR__ . '/..' . '/sebastian/environment/src/Runtime.php', + 'SebastianBergmann\\Exporter\\Exporter' => __DIR__ . '/..' . '/sebastian/exporter/src/Exporter.php', + 'SebastianBergmann\\FileIterator\\Facade' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Facade.php', + 'SebastianBergmann\\FileIterator\\Factory' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Factory.php', + 'SebastianBergmann\\FileIterator\\Iterator' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Iterator.php', + 'SebastianBergmann\\GlobalState\\CodeExporter' => __DIR__ . '/..' . '/sebastian/global-state/src/CodeExporter.php', + 'SebastianBergmann\\GlobalState\\Exception' => __DIR__ . '/..' . '/sebastian/global-state/src/exceptions/Exception.php', + 'SebastianBergmann\\GlobalState\\ExcludeList' => __DIR__ . '/..' . '/sebastian/global-state/src/ExcludeList.php', + 'SebastianBergmann\\GlobalState\\Restorer' => __DIR__ . '/..' . '/sebastian/global-state/src/Restorer.php', + 'SebastianBergmann\\GlobalState\\RuntimeException' => __DIR__ . '/..' . '/sebastian/global-state/src/exceptions/RuntimeException.php', + 'SebastianBergmann\\GlobalState\\Snapshot' => __DIR__ . '/..' . '/sebastian/global-state/src/Snapshot.php', + 'SebastianBergmann\\Invoker\\Exception' => __DIR__ . '/..' . '/phpunit/php-invoker/src/exceptions/Exception.php', + 'SebastianBergmann\\Invoker\\Invoker' => __DIR__ . '/..' . '/phpunit/php-invoker/src/Invoker.php', + 'SebastianBergmann\\Invoker\\ProcessControlExtensionNotLoadedException' => __DIR__ . '/..' . '/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php', + 'SebastianBergmann\\Invoker\\TimeoutException' => __DIR__ . '/..' . '/phpunit/php-invoker/src/exceptions/TimeoutException.php', + 'SebastianBergmann\\LinesOfCode\\Counter' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Counter.php', + 'SebastianBergmann\\LinesOfCode\\Exception' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/Exception.php', + 'SebastianBergmann\\LinesOfCode\\IllogicalValuesException' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php', + 'SebastianBergmann\\LinesOfCode\\LineCountingVisitor' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/LineCountingVisitor.php', + 'SebastianBergmann\\LinesOfCode\\LinesOfCode' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/LinesOfCode.php', + 'SebastianBergmann\\LinesOfCode\\NegativeValueException' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/NegativeValueException.php', + 'SebastianBergmann\\LinesOfCode\\RuntimeException' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/RuntimeException.php', + 'SebastianBergmann\\ObjectEnumerator\\Enumerator' => __DIR__ . '/..' . '/sebastian/object-enumerator/src/Enumerator.php', + 'SebastianBergmann\\ObjectEnumerator\\Exception' => __DIR__ . '/..' . '/sebastian/object-enumerator/src/Exception.php', + 'SebastianBergmann\\ObjectEnumerator\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/object-enumerator/src/InvalidArgumentException.php', + 'SebastianBergmann\\ObjectReflector\\Exception' => __DIR__ . '/..' . '/sebastian/object-reflector/src/Exception.php', + 'SebastianBergmann\\ObjectReflector\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/object-reflector/src/InvalidArgumentException.php', + 'SebastianBergmann\\ObjectReflector\\ObjectReflector' => __DIR__ . '/..' . '/sebastian/object-reflector/src/ObjectReflector.php', + 'SebastianBergmann\\RecursionContext\\Context' => __DIR__ . '/..' . '/sebastian/recursion-context/src/Context.php', + 'SebastianBergmann\\RecursionContext\\Exception' => __DIR__ . '/..' . '/sebastian/recursion-context/src/Exception.php', + 'SebastianBergmann\\RecursionContext\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/recursion-context/src/InvalidArgumentException.php', + 'SebastianBergmann\\ResourceOperations\\ResourceOperations' => __DIR__ . '/..' . '/sebastian/resource-operations/src/ResourceOperations.php', + 'SebastianBergmann\\Template\\Exception' => __DIR__ . '/..' . '/phpunit/php-text-template/src/exceptions/Exception.php', + 'SebastianBergmann\\Template\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php', + 'SebastianBergmann\\Template\\RuntimeException' => __DIR__ . '/..' . '/phpunit/php-text-template/src/exceptions/RuntimeException.php', + 'SebastianBergmann\\Template\\Template' => __DIR__ . '/..' . '/phpunit/php-text-template/src/Template.php', + 'SebastianBergmann\\Timer\\Duration' => __DIR__ . '/..' . '/phpunit/php-timer/src/Duration.php', + 'SebastianBergmann\\Timer\\Exception' => __DIR__ . '/..' . '/phpunit/php-timer/src/exceptions/Exception.php', + 'SebastianBergmann\\Timer\\NoActiveTimerException' => __DIR__ . '/..' . '/phpunit/php-timer/src/exceptions/NoActiveTimerException.php', + 'SebastianBergmann\\Timer\\ResourceUsageFormatter' => __DIR__ . '/..' . '/phpunit/php-timer/src/ResourceUsageFormatter.php', + 'SebastianBergmann\\Timer\\TimeSinceStartOfRequestNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php', + 'SebastianBergmann\\Timer\\Timer' => __DIR__ . '/..' . '/phpunit/php-timer/src/Timer.php', + 'SebastianBergmann\\Type\\CallableType' => __DIR__ . '/..' . '/sebastian/type/src/type/CallableType.php', + 'SebastianBergmann\\Type\\Exception' => __DIR__ . '/..' . '/sebastian/type/src/exception/Exception.php', + 'SebastianBergmann\\Type\\FalseType' => __DIR__ . '/..' . '/sebastian/type/src/type/FalseType.php', + 'SebastianBergmann\\Type\\GenericObjectType' => __DIR__ . '/..' . '/sebastian/type/src/type/GenericObjectType.php', + 'SebastianBergmann\\Type\\IntersectionType' => __DIR__ . '/..' . '/sebastian/type/src/type/IntersectionType.php', + 'SebastianBergmann\\Type\\IterableType' => __DIR__ . '/..' . '/sebastian/type/src/type/IterableType.php', + 'SebastianBergmann\\Type\\MixedType' => __DIR__ . '/..' . '/sebastian/type/src/type/MixedType.php', + 'SebastianBergmann\\Type\\NeverType' => __DIR__ . '/..' . '/sebastian/type/src/type/NeverType.php', + 'SebastianBergmann\\Type\\NullType' => __DIR__ . '/..' . '/sebastian/type/src/type/NullType.php', + 'SebastianBergmann\\Type\\ObjectType' => __DIR__ . '/..' . '/sebastian/type/src/type/ObjectType.php', + 'SebastianBergmann\\Type\\Parameter' => __DIR__ . '/..' . '/sebastian/type/src/Parameter.php', + 'SebastianBergmann\\Type\\ReflectionMapper' => __DIR__ . '/..' . '/sebastian/type/src/ReflectionMapper.php', + 'SebastianBergmann\\Type\\RuntimeException' => __DIR__ . '/..' . '/sebastian/type/src/exception/RuntimeException.php', + 'SebastianBergmann\\Type\\SimpleType' => __DIR__ . '/..' . '/sebastian/type/src/type/SimpleType.php', + 'SebastianBergmann\\Type\\StaticType' => __DIR__ . '/..' . '/sebastian/type/src/type/StaticType.php', + 'SebastianBergmann\\Type\\TrueType' => __DIR__ . '/..' . '/sebastian/type/src/type/TrueType.php', + 'SebastianBergmann\\Type\\Type' => __DIR__ . '/..' . '/sebastian/type/src/type/Type.php', + 'SebastianBergmann\\Type\\TypeName' => __DIR__ . '/..' . '/sebastian/type/src/TypeName.php', + 'SebastianBergmann\\Type\\UnionType' => __DIR__ . '/..' . '/sebastian/type/src/type/UnionType.php', + 'SebastianBergmann\\Type\\UnknownType' => __DIR__ . '/..' . '/sebastian/type/src/type/UnknownType.php', + 'SebastianBergmann\\Type\\VoidType' => __DIR__ . '/..' . '/sebastian/type/src/type/VoidType.php', + 'SebastianBergmann\\Version' => __DIR__ . '/..' . '/sebastian/version/src/Version.php', + 'TheSeer\\Tokenizer\\Exception' => __DIR__ . '/..' . '/theseer/tokenizer/src/Exception.php', + 'TheSeer\\Tokenizer\\NamespaceUri' => __DIR__ . '/..' . '/theseer/tokenizer/src/NamespaceUri.php', + 'TheSeer\\Tokenizer\\NamespaceUriException' => __DIR__ . '/..' . '/theseer/tokenizer/src/NamespaceUriException.php', + 'TheSeer\\Tokenizer\\Token' => __DIR__ . '/..' . '/theseer/tokenizer/src/Token.php', + 'TheSeer\\Tokenizer\\TokenCollection' => __DIR__ . '/..' . '/theseer/tokenizer/src/TokenCollection.php', + 'TheSeer\\Tokenizer\\TokenCollectionException' => __DIR__ . '/..' . '/theseer/tokenizer/src/TokenCollectionException.php', + 'TheSeer\\Tokenizer\\Tokenizer' => __DIR__ . '/..' . '/theseer/tokenizer/src/Tokenizer.php', + 'TheSeer\\Tokenizer\\XMLSerializer' => __DIR__ . '/..' . '/theseer/tokenizer/src/XMLSerializer.php', + 'WP_Mock' => __DIR__ . '/..' . '/10up/wp_mock/php/WP_Mock.php', ); public static function getInitializer(ClassLoader $loader) @@ -44,6 +815,7 @@ public static function getInitializer(ClassLoader $loader) $loader->prefixLengthsPsr4 = ComposerStaticInit414112f68a04b4d078687d18b2bb675e::$prefixLengthsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInit414112f68a04b4d078687d18b2bb675e::$prefixDirsPsr4; $loader->prefixesPsr0 = ComposerStaticInit414112f68a04b4d078687d18b2bb675e::$prefixesPsr0; + $loader->classMap = ComposerStaticInit414112f68a04b4d078687d18b2bb675e::$classMap; }, null, ClassLoader::class); } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 09972ca9..fba80b6a 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,100 +1,3295 @@ -[ - { - "name": "pimple/pimple", - "version": "v3.3.1", - "version_normalized": "3.3.1.0", - "source": { - "type": "git", - "url": "https://github.com/silexphp/Pimple.git", - "reference": "21e45061c3429b1e06233475cc0e1f6fc774d5b0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/silexphp/Pimple/zipball/21e45061c3429b1e06233475cc0e1f6fc774d5b0", - "reference": "21e45061c3429b1e06233475cc0e1f6fc774d5b0", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^5.0" - }, - "time": "2020-11-24T20:35:42+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.3.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "Pimple": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Pimple, a simple Dependency Injection Container", - "homepage": "https://pimple.symfony.com", - "keywords": [ - "container", - "dependency injection" - ] - }, - { - "name": "psr/container", - "version": "1.1.2", - "version_normalized": "1.1.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "time": "2021-11-05T16:50:12+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ] - } -] +{ + "packages": [ + { + "name": "10up/wp_mock", + "version": "0.4.2", + "version_normalized": "0.4.2.0", + "source": { + "type": "git", + "url": "https://github.com/10up/wp_mock.git", + "reference": "9019226eb50df275aa86bb15bfc98a619601ee49" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/10up/wp_mock/zipball/9019226eb50df275aa86bb15bfc98a619601ee49", + "reference": "9019226eb50df275aa86bb15bfc98a619601ee49", + "shasum": "" + }, + "require": { + "antecedent/patchwork": "^2.1", + "mockery/mockery": "^1.0", + "php": ">=7.1", + "phpunit/phpunit": ">=7.0" + }, + "require-dev": { + "behat/behat": "^3.0", + "php-coveralls/php-coveralls": "^2.1", + "sebastian/comparator": ">=1.2.3" + }, + "time": "2019-03-16T03:44:39+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "WP_Mock\\": "./php/WP_Mock" + }, + "classmap": [ + "php/WP_Mock.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "A mocking library to take the pain out of unit testing for WordPress", + "install-path": "../10up/wp_mock" + }, + { + "name": "antecedent/patchwork", + "version": "2.1.21", + "version_normalized": "2.1.21.0", + "source": { + "type": "git", + "url": "https://github.com/antecedent/patchwork.git", + "reference": "25c1fa0cd9a6e6d0d13863d8df8f050b6733f16d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/antecedent/patchwork/zipball/25c1fa0cd9a6e6d0d13863d8df8f050b6733f16d", + "reference": "25c1fa0cd9a6e6d0d13863d8df8f050b6733f16d", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": ">=4" + }, + "time": "2022-02-07T07:28:34+00:00", + "type": "library", + "installation-source": "dist", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignas Rudaitis", + "email": "ignas.rudaitis@gmail.com" + } + ], + "description": "Method redefinition (monkey-patching) functionality for PHP.", + "homepage": "http://patchwork2.org/", + "keywords": [ + "aop", + "aspect", + "interception", + "monkeypatching", + "redefinition", + "runkit", + "testing" + ], + "install-path": "../antecedent/patchwork" + }, + { + "name": "automattic/vipwpcs", + "version": "2.3.3", + "version_normalized": "2.3.3.0", + "source": { + "type": "git", + "url": "https://github.com/Automattic/VIP-Coding-Standards.git", + "reference": "6cd0a6a82bc0ac988dbf9d6a7c2e293dc8ac640b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Automattic/VIP-Coding-Standards/zipball/6cd0a6a82bc0ac988dbf9d6a7c2e293dc8ac640b", + "reference": "6cd0a6a82bc0ac988dbf9d6a7c2e293dc8ac640b", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7", + "php": ">=5.4", + "sirbrillig/phpcs-variable-analysis": "^2.11.1", + "squizlabs/php_codesniffer": "^3.5.5", + "wp-coding-standards/wpcs": "^2.3" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^0.5", + "php-parallel-lint/php-parallel-lint": "^1.0", + "phpcompatibility/php-compatibility": "^9", + "phpcsstandards/phpcsdevtools": "^1.0", + "phpunit/phpunit": "^4 || ^5 || ^6 || ^7" + }, + "time": "2021-09-29T16:20:23+00:00", + "type": "phpcodesniffer-standard", + "installation-source": "dist", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Contributors", + "homepage": "https://github.com/Automattic/VIP-Coding-Standards/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress VIP minimum coding conventions", + "keywords": [ + "phpcs", + "standards", + "wordpress" + ], + "install-path": "../automattic/vipwpcs" + }, + { + "name": "civicrm/composer-downloads-plugin", + "version": "v3.0.1", + "version_normalized": "3.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/civicrm/composer-downloads-plugin.git", + "reference": "3aabb6d259a86158d01829fc2c62a2afb9618877" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/civicrm/composer-downloads-plugin/zipball/3aabb6d259a86158d01829fc2c62a2afb9618877", + "reference": "3aabb6d259a86158d01829fc2c62a2afb9618877", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1 || ^2.0", + "php": ">=5.6", + "togos/gitignore": "~1.1.1" + }, + "require-dev": { + "composer/composer": "~1.0 || ~2.0", + "friendsofphp/php-cs-fixer": "^2.3", + "phpunit/phpunit": "^5.7", + "totten/process-helper": "^1.0.1" + }, + "time": "2020-11-02T05:26:23+00:00", + "type": "composer-plugin", + "extra": { + "class": "LastCall\\DownloadsPlugin\\Plugin" + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "LastCall\\DownloadsPlugin\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rob Bayliss", + "email": "rob@lastcallmedia.com" + }, + { + "name": "Tim Otten", + "email": "totten@civicrm.org" + } + ], + "description": "Composer plugin for downloading additional files within any composer package.", + "support": { + "source": "https://github.com/civicrm/composer-downloads-plugin/tree/v3.0.1" + }, + "install-path": "../civicrm/composer-downloads-plugin" + }, + { + "name": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v0.7.2", + "version_normalized": "0.7.2.0", + "source": { + "type": "git", + "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", + "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", + "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.3", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + }, + "require-dev": { + "composer/composer": "*", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "phpcompatibility/php-compatibility": "^9.0" + }, + "time": "2022-02-04T12:51:07+00:00", + "type": "composer-plugin", + "extra": { + "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" + }, + { + "name": "Contributors", + "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "homepage": "http://www.dealerdirect.com", + "keywords": [ + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcbf", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" + ], + "install-path": "../dealerdirect/phpcodesniffer-composer-installer" + }, + { + "name": "doctrine/instantiator", + "version": "1.5.0", + "version_normalized": "1.5.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" + }, + "time": "2022-12-30T00:15:36+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "install-path": "../doctrine/instantiator" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.0.1", + "version_normalized": "2.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "shasum": "" + }, + "require": { + "php": "^5.3|^7.0|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" + }, + "time": "2020-07-09T08:09:16+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "install-path": "../hamcrest/hamcrest-php" + }, + { + "name": "mockery/mockery", + "version": "1.5.1", + "version_normalized": "1.5.1.0", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "e92dcc83d5a51851baf5f5591d32cb2b16e3684e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/e92dcc83d5a51851baf5f5591d32cb2b16e3684e", + "reference": "e92dcc83d5a51851baf5f5591d32cb2b16e3684e", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": "^7.3 || ^8.0" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.3" + }, + "time": "2022-09-07T15:32:08+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Mockery": "library/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "http://blog.astrumfutura.com" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "http://davedevelopment.co.uk" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "issues": "https://github.com/mockery/mockery/issues", + "source": "https://github.com/mockery/mockery/tree/1.5.1" + }, + "install-path": "../mockery/mockery" + }, + { + "name": "myclabs/deep-copy", + "version": "1.11.0", + "version_normalized": "1.11.0.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "time": "2022-03-03T13:19:32+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "install-path": "../myclabs/deep-copy" + }, + { + "name": "nikic/php-parser", + "version": "v4.15.3", + "version_normalized": "4.15.3.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/570e980a201d8ed0236b0a62ddf2c9cbb2034039", + "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "time": "2023-01-16T22:05:37+00:00", + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.3" + }, + "install-path": "../nikic/php-parser" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "version_normalized": "2.0.3.0", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "time": "2021-07-20T11:28:43+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "install-path": "../phar-io/manifest" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "version_normalized": "3.2.1.0", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "time": "2022-02-21T01:04:05+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "install-path": "../phar-io/version" + }, + { + "name": "php-stubs/wordpress-stubs", + "version": "v6.1.1", + "version_normalized": "6.1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-stubs/wordpress-stubs.git", + "reference": "601c429ba8d91ef50a2a1bec05a7cd38b88064ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/601c429ba8d91ef50a2a1bec05a7cd38b88064ff", + "reference": "601c429ba8d91ef50a2a1bec05a7cd38b88064ff", + "shasum": "" + }, + "require-dev": { + "nikic/php-parser": "< 4.12.0", + "php": "~7.3 || ~8.0", + "php-stubs/generator": "^0.8.3", + "phpdocumentor/reflection-docblock": "^5.3", + "phpstan/phpstan": "^1.2" + }, + "suggest": { + "paragonie/sodium_compat": "Pure PHP implementation of libsodium", + "symfony/polyfill-php73": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan" + }, + "time": "2023-02-09T11:10:35+00:00", + "type": "library", + "installation-source": "dist", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "WordPress function and class declaration stubs for static analysis.", + "homepage": "https://github.com/php-stubs/wordpress-stubs", + "keywords": [ + "PHPStan", + "static analysis", + "wordpress" + ], + "support": { + "issues": "https://github.com/php-stubs/wordpress-stubs/issues", + "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.1.1" + }, + "install-path": "../php-stubs/wordpress-stubs" + }, + { + "name": "phpcompatibility/php-compatibility", + "version": "9.3.5", + "version_normalized": "9.3.5.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", + "reference": "9fb324479acf6f39452e0655d2429cc0d3914243" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243", + "reference": "9fb324479acf6f39452e0655d2429cc0d3914243", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" + }, + "conflict": { + "squizlabs/php_codesniffer": "2.6.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "time": "2019-12-27T09:44:58+00:00", + "type": "phpcodesniffer-standard", + "installation-source": "dist", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "homepage": "https://github.com/wimg", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" + } + ], + "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", + "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", + "keywords": [ + "compatibility", + "phpcs", + "standards" + ], + "install-path": "../phpcompatibility/php-compatibility" + }, + { + "name": "phpcompatibility/phpcompatibility-paragonie", + "version": "1.3.2", + "version_normalized": "1.3.2.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", + "reference": "bba5a9dfec7fcfbd679cfaf611d86b4d3759da26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/bba5a9dfec7fcfbd679cfaf611d86b4d3759da26", + "reference": "bba5a9dfec7fcfbd679cfaf611d86b4d3759da26", + "shasum": "" + }, + "require": { + "phpcompatibility/php-compatibility": "^9.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7", + "paragonie/random_compat": "dev-master", + "paragonie/sodium_compat": "dev-master" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "time": "2022-10-25T01:46:02+00:00", + "type": "phpcodesniffer-standard", + "installation-source": "dist", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "lead" + } + ], + "description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.", + "homepage": "http://phpcompatibility.com/", + "keywords": [ + "compatibility", + "paragonie", + "phpcs", + "polyfill", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" + }, + "install-path": "../phpcompatibility/phpcompatibility-paragonie" + }, + { + "name": "phpcompatibility/phpcompatibility-wp", + "version": "2.1.4", + "version_normalized": "2.1.4.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", + "reference": "b6c1e3ee1c35de6c41a511d5eb9bd03e447480a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/b6c1e3ee1c35de6c41a511d5eb9bd03e447480a5", + "reference": "b6c1e3ee1c35de6c41a511d5eb9bd03e447480a5", + "shasum": "" + }, + "require": { + "phpcompatibility/php-compatibility": "^9.0", + "phpcompatibility/phpcompatibility-paragonie": "^1.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "time": "2022-10-24T09:00:36+00:00", + "type": "phpcodesniffer-standard", + "installation-source": "dist", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "lead" + } + ], + "description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.", + "homepage": "http://phpcompatibility.com/", + "keywords": [ + "compatibility", + "phpcs", + "standards", + "static analysis", + "wordpress" + ], + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP" + }, + "install-path": "../phpcompatibility/phpcompatibility-wp" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.24", + "version_normalized": "9.2.24.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "2cf940ebc6355a9d430462811b5aaa308b174bed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2cf940ebc6355a9d430462811b5aaa308b174bed", + "reference": "2cf940ebc6355a9d430462811b5aaa308b174bed", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.14", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcov": "*", + "ext-xdebug": "*" + }, + "time": "2023-01-26T08:26:55+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.2-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.24" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../phpunit/php-code-coverage" + }, + { + "name": "phpunit/php-file-iterator", + "version": "3.0.6", + "version_normalized": "3.0.6.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "time": "2021-12-02T12:48:52+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../phpunit/php-file-iterator" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "version_normalized": "3.1.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "time": "2020-09-28T05:58:55+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../phpunit/php-invoker" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "version_normalized": "2.0.4.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "time": "2020-10-26T05:33:50+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../phpunit/php-text-template" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "version_normalized": "5.0.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "time": "2020-10-26T13:16:10+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../phpunit/php-timer" + }, + { + "name": "phpunit/phpunit", + "version": "9.6.3", + "version_normalized": "9.6.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "e7b1615e3e887d6c719121c6d4a44b0ab9645555" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e7b1615e3e887d6c719121c6d4a44b0ab9645555", + "reference": "e7b1615e3e887d6c719121c6d4a44b0ab9645555", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*" + }, + "time": "2023-02-04T13:37:15+00:00", + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.6-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.3" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "install-path": "../phpunit/phpunit" + }, + { + "name": "pimple/pimple", + "version": "v3.3.1", + "version_normalized": "3.3.1.0", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Pimple.git", + "reference": "21e45061c3429b1e06233475cc0e1f6fc774d5b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/21e45061c3429b1e06233475cc0e1f6fc774d5b0", + "reference": "21e45061c3429b1e06233475cc0e1f6fc774d5b0", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^5.0" + }, + "time": "2020-11-24T20:35:42+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple, a simple Dependency Injection Container", + "homepage": "https://pimple.symfony.com", + "keywords": [ + "container", + "dependency injection" + ], + "install-path": "../pimple/pimple" + }, + { + "name": "psr/container", + "version": "1.1.2", + "version_normalized": "1.1.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "time": "2021-11-05T16:50:12+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "install-path": "../psr/container" + }, + { + "name": "roave/security-advisories", + "version": "dev-latest", + "version_normalized": "dev-latest", + "source": { + "type": "git", + "url": "https://github.com/Roave/SecurityAdvisories.git", + "reference": "72ca3d8b529b6679ccbefcdc1433fa6aeb7564b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/72ca3d8b529b6679ccbefcdc1433fa6aeb7564b8", + "reference": "72ca3d8b529b6679ccbefcdc1433fa6aeb7564b8", + "shasum": "" + }, + "conflict": { + "3f/pygmentize": "<1.2", + "admidio/admidio": "<4.1.9", + "adodb/adodb-php": "<=5.20.20|>=5.21,<=5.21.3", + "aheinze/cockpit": "<=2.2.1", + "akaunting/akaunting": "<2.1.13", + "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", + "alextselegidis/easyappointments": "<=1.4.3", + "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", + "amazing/media2click": ">=1,<1.3.3", + "amphp/artax": "<1.0.6|>=2,<2.0.6", + "amphp/http": "<1.0.1", + "amphp/http-client": ">=4,<4.4", + "anchorcms/anchor-cms": "<=0.12.7", + "andreapollastri/cipi": "<=3.1.15", + "apereo/phpcas": "<1.6", + "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6", + "appwrite/server-ce": "<0.11.1|>=0.12,<0.12.2", + "arc/web": "<3", + "area17/twill": "<1.2.5|>=2,<2.5.3", + "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", + "automad/automad": "<1.8", + "awesome-support/awesome-support": "<=6.0.7", + "aws/aws-sdk-php": ">=3,<3.2.1", + "backdrop/backdrop": "<=1.23", + "badaso/core": "<2.7", + "bagisto/bagisto": "<0.1.5", + "barrelstrength/sprout-base-email": "<1.2.7", + "barrelstrength/sprout-forms": "<3.9", + "barryvdh/laravel-translation-manager": "<0.6.2", + "barzahlen/barzahlen-php": "<2.0.1", + "baserproject/basercms": "<4.7.2", + "bassjobsen/bootstrap-3-typeahead": ">4.0.2", + "billz/raspap-webgui": "<=2.6.6", + "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", + "bmarshall511/wordpress_zero_spam": "<5.2.13", + "bolt/bolt": "<3.7.2", + "bolt/core": "<=4.2", + "bottelet/flarepoint": "<2.2.1", + "brightlocal/phpwhois": "<=4.2.5", + "brotkrueml/codehighlight": "<2.7", + "brotkrueml/schema": "<1.13.1|>=2,<2.5.1", + "brotkrueml/typo3-matomo-integration": "<1.3.2", + "buddypress/buddypress": "<7.2.1", + "bugsnag/bugsnag-laravel": ">=2,<2.0.2", + "bytefury/crater": "<6.0.2", + "cachethq/cachet": "<2.5.1", + "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10|= 1.3.7|>=4.1,<4.1.4", + "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", + "cardgate/magento2": "<2.0.33", + "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", + "cartalyst/sentry": "<=2.1.6", + "catfan/medoo": "<1.7.5", + "centreon/centreon": "<22.10-beta.1", + "cesnet/simplesamlphp-module-proxystatistics": "<3.1", + "cockpit-hq/cockpit": "<2.3.9", + "codeception/codeception": "<3.1.3|>=4,<4.1.22", + "codeigniter/framework": "<=3.0.6", + "codeigniter4/framework": "<4.2.11", + "codeigniter4/shield": "= 1.0.0-beta", + "codiad/codiad": "<=2.8.4", + "composer/composer": "<1.10.26|>=2-alpha.1,<2.2.12|>=2.3,<2.3.5", + "concrete5/concrete5": "<=9.1.3|>= 9.0.0RC1, < 9.1.3", + "concrete5/core": "<8.5.8|>=9,<9.1", + "contao-components/mediaelement": ">=2.14.2,<2.21.1", + "contao/contao": ">=4,<4.4.56|>=4.5,<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3", + "contao/core": ">=2,<3.5.39", + "contao/core-bundle": "<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3|= 4.10.0", + "contao/listing-bundle": ">=4,<4.4.8", + "contao/managed-edition": "<=1.5", + "craftcms/cms": "<3.7.55.2|>= 4.0.0-RC1, < 4.2.1", + "croogo/croogo": "<3.0.7", + "cuyz/valinor": "<0.12", + "czproject/git-php": "<4.0.3", + "darylldoyle/safe-svg": "<1.9.10", + "datadog/dd-trace": ">=0.30,<0.30.2", + "david-garcia/phpwhois": "<=4.3.1", + "dbrisinajumi/d2files": "<1", + "derhansen/fe_change_pwd": "<2.0.5|>=3,<3.0.3", + "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1", + "directmailteam/direct-mail": "<5.2.4", + "doctrine/annotations": ">=1,<1.2.7", + "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", + "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1", + "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2|>=3,<3.1.4", + "doctrine/doctrine-bundle": "<1.5.2", + "doctrine/doctrine-module": "<=0.7.1", + "doctrine/mongodb-odm": ">=1,<1.0.2", + "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", + "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", + "dolibarr/dolibarr": "<16|>=16.0.1,<16.0.3|= 12.0.5|>= 3.3.beta1, < 13.0.2", + "dompdf/dompdf": "<2.0.2|= 2.0.2", + "drupal/core": ">=7,<7.91|>=8,<9.3.19|>=9.4,<9.4.3", + "drupal/drupal": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4", + "dweeves/magmi": "<=0.7.24", + "ecodev/newsletter": "<=4", + "ectouch/ectouch": "<=2.7.2", + "elefant/cms": "<1.3.13", + "elgg/elgg": "<3.3.24|>=4,<4.0.5", + "endroid/qr-code-bundle": "<3.4.2", + "enshrined/svg-sanitize": "<0.15", + "erusev/parsedown": "<1.7.2", + "ether/logs": "<3.0.4", + "exceedone/exment": "<4.4.3|>=5,<5.0.3", + "exceedone/laravel-admin": "= 3.0.0|<2.2.3", + "ezsystems/demobundle": ">=5.4,<5.4.6.1", + "ezsystems/ez-support-tools": ">=2.2,<2.2.3", + "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1", + "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1|>=5.4,<5.4.11.1|>=2017.12,<2017.12.0.1", + "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", + "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.29|>=2.3,<2.3.26", + "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1", + "ezsystems/ezplatform-graphql": ">=1-rc.1,<1.0.13|>=2-beta.1,<2.3.12", + "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<1.3.26", + "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", + "ezsystems/ezplatform-richtext": ">=2.3,<=2.3.7", + "ezsystems/ezplatform-user": ">=1,<1.0.1", + "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<7.5.30", + "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.3.5.1", + "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", + "ezsystems/repository-forms": ">=2.3,<2.3.2.1|>=2.5,<2.5.15", + "ezyang/htmlpurifier": "<4.1.1", + "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", + "facturascripts/facturascripts": "<=2022.8", + "feehi/cms": "<=2.1.1", + "feehi/feehicms": "<=2.1.1", + "fenom/fenom": "<=2.12.1", + "filegator/filegator": "<7.8", + "firebase/php-jwt": "<2", + "fixpunkt/fp-masterquiz": "<2.2.1|>=3,<3.5.2", + "fixpunkt/fp-newsletter": "<1.1.1|>=2,<2.1.2|>=2.2,<3.2.6", + "flarum/core": "<1.6.3", + "flarum/mentions": "<1.6.3", + "flarum/sticky": ">=0.1-beta.14,<=0.1-beta.15", + "flarum/tags": "<=0.1-beta.13", + "fluidtypo3/vhs": "<5.1.1", + "fof/byobu": ">=0.3-beta.2,<1.1.7", + "fof/upload": "<1.2.3", + "fooman/tcpdf": "<6.2.22", + "forkcms/forkcms": "<5.11.1", + "fossar/tcpdf-parser": "<6.2.22", + "francoisjacquet/rosariosis": "<10.1", + "friendsofsymfony/oauth2-php": "<1.3", + "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", + "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", + "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", + "froala/wysiwyg-editor": "<3.2.7", + "froxlor/froxlor": "<2.0.10", + "fuel/core": "<1.8.1", + "gaoming13/wechat-php-sdk": "<=1.10.2", + "genix/cms": "<=1.1.11", + "getgrav/grav": "<1.7.34", + "getkirby/cms": "= 3.8.0|<3.5.8.2|>=3.6,<3.6.6.2|>=3.7,<3.7.5.1", + "getkirby/panel": "<2.5.14", + "getkirby/starterkit": "<=3.7.0.2", + "gilacms/gila": "<=1.11.4", + "globalpayments/php-sdk": "<2", + "google/protobuf": "<3.15", + "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", + "gree/jose": "<=2.2", + "gregwar/rst": "<1.0.3", + "grumpydictator/firefly-iii": "<5.8", + "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", + "guzzlehttp/psr7": "<1.8.4|>=2,<2.1.1", + "harvesthq/chosen": "<1.8.7", + "helloxz/imgurl": "= 2.31|<=2.31", + "hillelcoren/invoice-ninja": "<5.3.35", + "himiklab/yii2-jqgrid-widget": "<1.0.8", + "hjue/justwriting": "<=1", + "hov/jobfair": "<1.0.13|>=2,<2.0.2", + "hyn/multi-tenant": ">=5.6,<5.7.2", + "ibexa/admin-ui": ">=4.2,<4.2.3", + "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4|>=4.2,<4.2.3", + "ibexa/graphql": ">=2.5,<2.5.31|>=3.3,<3.3.28|>=4.2,<4.2.3", + "ibexa/post-install": "<=1.0.4", + "icecoder/icecoder": "<=8.1", + "idno/known": "<=1.3.1", + "illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10", + "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.99999|>=4.2,<=4.2.99999|>=5,<=5.0.99999|>=5.1,<=5.1.99999|>=5.2,<=5.2.99999|>=5.3,<=5.3.99999|>=5.4,<=5.4.99999|>=5.5,<=5.5.49|>=5.6,<=5.6.99999|>=5.7,<=5.7.99999|>=5.8,<=5.8.99999|>=6,<6.18.31|>=7,<7.22.4", + "illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40", + "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", + "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", + "impresscms/impresscms": "<=1.4.3", + "in2code/femanager": "<5.5.3|>=6,<6.3.4|>=7,<7.1", + "in2code/lux": "<17.6.1|>=18,<24.0.2", + "innologi/typo3-appointments": "<2.0.6", + "intelliants/subrion": "<=4.2.1", + "islandora/islandora": ">=2,<2.4.1", + "ivankristianto/phpwhois": "<=4.3", + "jackalope/jackalope-doctrine-dbal": "<1.7.4", + "james-heinrich/getid3": "<1.9.21", + "jasig/phpcas": "<1.3.3", + "joomla/archive": "<1.1.12|>=2,<2.0.1", + "joomla/filesystem": "<1.6.2|>=2,<2.0.1", + "joomla/filter": "<1.4.4|>=2,<2.0.1", + "joomla/input": ">=2,<2.0.2", + "joomla/session": "<1.3.1", + "joyqi/hyper-down": "<=2.4.27", + "jsdecena/laracom": "<2.0.9", + "jsmitty12/phpwhois": "<5.1", + "kazist/phpwhois": "<=4.2.6", + "kelvinmo/simplexrd": "<3.1.1", + "kevinpapst/kimai2": "<1.16.7", + "kitodo/presentation": "<3.1.2", + "klaviyo/magento2-extension": ">=1,<3", + "krayin/laravel-crm": "<1.2.2", + "kreait/firebase-php": ">=3.2,<3.8.1", + "la-haute-societe/tcpdf": "<6.2.22", + "laminas/laminas-diactoros": "<2.11.1", + "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", + "laminas/laminas-http": "<2.14.2", + "laravel/fortify": "<1.11.1", + "laravel/framework": "<6.20.42|>=7,<7.30.6|>=8,<8.75", + "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", + "latte/latte": "<2.10.8", + "lavalite/cms": "<=5.8", + "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", + "league/commonmark": "<0.18.3", + "league/flysystem": "<1.1.4|>=2,<2.1.1", + "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", + "librenms/librenms": "<22.10", + "liftkit/database": "<2.13.2", + "limesurvey/limesurvey": "<3.27.19", + "livehelperchat/livehelperchat": "<=3.91", + "livewire/livewire": ">2.2.4,<2.2.6", + "lms/routes": "<2.1.1", + "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2", + "luyadev/yii-helpers": "<1.2.1", + "magento/community-edition": ">=2,<2.2.10|>=2.3,<2.3.3", + "magento/magento1ce": "<1.9.4.3", + "magento/magento1ee": ">=1,<1.14.4.3", + "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2", + "marcwillmann/turn": "<0.3.3", + "matyhtf/framework": "<3.0.6", + "mautic/core": "<4.3|= 2.13.1", + "mediawiki/core": ">=1.27,<1.27.6|>=1.29,<1.29.3|>=1.30,<1.30.2|>=1.31,<1.31.9|>=1.32,<1.32.6|>=1.32.99,<1.33.3|>=1.33.99,<1.34.3|>=1.34.99,<1.35", + "melisplatform/melis-asset-manager": "<5.0.1", + "melisplatform/melis-cms": "<5.0.1", + "melisplatform/melis-front": "<5.0.1", + "mezzio/mezzio-swoole": "<3.7|>=4,<4.3", + "mgallegos/laravel-jqgrid": "<=1.3", + "microweber/microweber": "<1.3.2", + "miniorange/miniorange-saml": "<1.4.3", + "mittwald/typo3_forum": "<1.2.1", + "modx/revolution": "<= 2.8.3-pl|<2.8", + "mojo42/jirafeau": "<4.4", + "monolog/monolog": ">=1.8,<1.12", + "moodle/moodle": "<4.0.5", + "mustache/mustache": ">=2,<2.14.1", + "namshi/jose": "<2.2", + "neoan3-apps/template": "<1.1.1", + "neorazorx/facturascripts": "<2022.4", + "neos/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "neos/form": ">=1.2,<4.3.3|>=5,<5.0.9|>=5.1,<5.1.3", + "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.9.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<5.3.10|>=7,<7.0.9|>=7.1,<7.1.7|>=7.2,<7.2.6|>=7.3,<7.3.4|>=8,<8.0.2", + "neos/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", + "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", + "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", + "nilsteampassnet/teampass": "<=2.1.27.36", + "notrinos/notrinos-erp": "<=0.7", + "noumo/easyii": "<=0.9", + "nukeviet/nukeviet": "<4.5.2", + "nystudio107/craft-seomatic": "<3.4.12", + "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", + "october/backend": "<1.1.2", + "october/cms": "= 1.1.1|= 1.0.471|= 1.0.469|>=1.0.319,<1.0.469", + "october/october": ">=1.0.319,<1.0.466|>=2.1,<2.1.12", + "october/rain": "<1.0.472|>=1.1,<1.1.2", + "october/system": "<1.0.476|>=1.1,<1.1.12|>=2,<2.2.34|>=3,<3.0.66", + "onelogin/php-saml": "<2.10.4", + "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5", + "open-web-analytics/open-web-analytics": "<1.7.4", + "opencart/opencart": "<=3.0.3.7", + "openid/php-openid": "<2.3", + "openmage/magento-lts": "<19.4.22|>=20,<20.0.19", + "orchid/platform": ">=9,<9.4.4", + "oro/commerce": ">=4.1,<5.0.6", + "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", + "oro/platform": ">=1.7,<1.7.4|>=3.1,<3.1.29|>=4.1,<4.1.17|>=4.2,<4.2.8", + "packbackbooks/lti-1-3-php-library": "<5", + "padraic/humbug_get_contents": "<1.1.2", + "pagarme/pagarme-php": ">=0,<3", + "pagekit/pagekit": "<=1.0.18", + "paragonie/random_compat": "<2", + "passbolt/passbolt_api": "<2.11", + "paypal/merchant-sdk-php": "<3.12", + "pear/archive_tar": "<1.4.14", + "pear/crypt_gpg": "<1.6.7", + "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", + "personnummer/personnummer": "<3.0.2", + "phanan/koel": "<5.1.4", + "php-mod/curl": "<2.3.2", + "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", + "phpmailer/phpmailer": "<6.5", + "phpmussel/phpmussel": ">=1,<1.6", + "phpmyadmin/phpmyadmin": "<5.2.1", + "phpmyfaq/phpmyfaq": "<=3.1.7", + "phpoffice/phpexcel": "<1.8", + "phpoffice/phpspreadsheet": "<1.16", + "phpseclib/phpseclib": "<2.0.31|>=3,<3.0.7", + "phpservermon/phpservermon": "<=3.5.2", + "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5,<5.6.3", + "phpwhois/phpwhois": "<=4.2.5", + "phpxmlrpc/extras": "<0.6.1", + "phpxmlrpc/phpxmlrpc": "<4.9.2", + "pimcore/data-hub": "<1.2.4", + "pimcore/pimcore": "<10.5.16", + "pocketmine/bedrock-protocol": "<8.0.2", + "pocketmine/pocketmine-mp": "<4.12.5|>= 4.0.0-BETA5, < 4.4.2", + "pressbooks/pressbooks": "<5.18", + "prestashop/autoupgrade": ">=4,<4.10.1", + "prestashop/blockwishlist": ">=2,<2.1.1", + "prestashop/contactform": ">=1.0.1,<4.3", + "prestashop/gamification": "<2.3.2", + "prestashop/prestashop": "<1.7.8.8", + "prestashop/productcomments": "<5.0.2", + "prestashop/ps_emailsubscription": "<2.6.1", + "prestashop/ps_facetedsearch": "<3.4.1", + "prestashop/ps_linklist": "<3.1", + "privatebin/privatebin": "<1.4", + "processwire/processwire": "<=3.0.200", + "propel/propel": ">=2-alpha.1,<=2-alpha.7", + "propel/propel1": ">=1,<=1.7.1", + "pterodactyl/panel": "<1.7", + "ptrofimov/beanstalk_console": "<1.7.14", + "pusher/pusher-php-server": "<2.2.1", + "pwweb/laravel-core": "<=0.3.6-beta", + "pyrocms/pyrocms": "<=3.9.1", + "rainlab/debugbar-plugin": "<3.1", + "rankmath/seo-by-rank-math": "<=1.0.95", + "react/http": ">=0.7,<1.7", + "remdex/livehelperchat": "<3.99", + "rmccue/requests": ">=1.6,<1.8", + "robrichards/xmlseclibs": "<3.0.4", + "roots/soil": "<4.1", + "rudloff/alltube": "<3.0.3", + "s-cart/core": "<6.9", + "s-cart/s-cart": "<6.9", + "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", + "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", + "scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11", + "sensiolabs/connect": "<4.2.3", + "serluck/phpwhois": "<=4.2.6", + "shopware/core": "<=6.4.18", + "shopware/platform": "<=6.4.18", + "shopware/production": "<=6.3.5.2", + "shopware/shopware": "<=5.7.14", + "shopware/storefront": "<=6.4.8.1", + "shopxo/shopxo": "<2.2.6", + "showdoc/showdoc": "<2.10.4", + "silverstripe/admin": ">=1,<1.11.3", + "silverstripe/assets": ">=1,<1.11.1", + "silverstripe/cms": "<4.11.3", + "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1", + "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", + "silverstripe/framework": "<4.11.14", + "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|= 4.0.0-alpha1", + "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", + "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", + "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4", + "silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1", + "silverstripe/subsites": ">=2,<2.6.1", + "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", + "silverstripe/userforms": "<3", + "silverstripe/versioned-admin": ">=1,<1.11.1", + "simple-updates/phpwhois": "<=1", + "simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4", + "simplesamlphp/simplesamlphp": "<1.18.6", + "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", + "simplesamlphp/simplesamlphp-module-openid": "<1", + "simplesamlphp/simplesamlphp-module-openidprovider": "<0.9", + "simplito/elliptic-php": "<1.0.6", + "slim/slim": "<2.6", + "smarty/smarty": "<3.1.47|>=4,<4.2.1", + "snipe/snipe-it": "<=6.0.14|>= 6.0.0-RC-1, <= 6.0.0-RC-5", + "socalnick/scn-social-auth": "<1.15.2", + "socialiteproviders/steam": "<1.1", + "spatie/browsershot": "<3.57.4", + "spipu/html2pdf": "<5.2.4", + "spoonity/tcpdf": "<6.2.22", + "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", + "ssddanbrown/bookstack": "<22.2.3", + "statamic/cms": "<3.2.39|>=3.3,<3.3.2", + "stormpath/sdk": ">=0,<9.9.99", + "studio-42/elfinder": "<2.1.59", + "subrion/cms": "<=4.2.1", + "sukohi/surpass": "<1", + "sulu/sulu": "= 2.4.0-RC1|<1.6.44|>=2,<2.2.18|>=2.3,<2.3.8", + "sumocoders/framework-user-bundle": "<1.4", + "swag/paypal": "<5.4.4", + "swiftmailer/swiftmailer": ">=4,<5.4.5", + "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", + "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", + "sylius/grid-bundle": "<1.10.1", + "sylius/paypal-plugin": ">=1,<1.2.4|>=1.3,<1.3.1", + "sylius/resource-bundle": "<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", + "sylius/sylius": "<1.9.10|>=1.10,<1.10.11|>=1.11,<1.11.2", + "symbiote/silverstripe-multivaluefield": ">=3,<3.0.99", + "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", + "symbiote/silverstripe-seed": "<6.0.3", + "symbiote/silverstripe-versionedfiles": "<=2.0.3", + "symfont/process": ">=0", + "symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8", + "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", + "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", + "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3|= 6.0.3|= 5.4.3|= 5.3.14", + "symfony/http-foundation": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7", + "symfony/http-kernel": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", + "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", + "symfony/mime": ">=4.3,<4.3.8", + "symfony/phpunit-bridge": ">=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/polyfill": ">=1,<1.10", + "symfony/polyfill-php55": ">=1,<1.10", + "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/routing": ">=2,<2.0.19", + "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8", + "symfony/security-bundle": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", + "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", + "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", + "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", + "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7|>=5.1,<5.2.8|>=5.3,<5.3.2", + "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", + "symfony/symfony": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", + "symfony/translation": ">=2,<2.0.17", + "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3", + "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", + "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", + "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", + "t3/dce": ">=2.2,<2.6.2", + "t3g/svg-sanitizer": "<1.0.3", + "tastyigniter/tastyigniter": "<3.3", + "tecnickcom/tcpdf": "<6.2.22", + "terminal42/contao-tablelookupwizard": "<3.3.5", + "thelia/backoffice-default-template": ">=2.1,<2.1.2", + "thelia/thelia": ">=2.1-beta.1,<2.1.3", + "theonedemon/phpwhois": "<=4.2.5", + "thinkcmf/thinkcmf": "<=5.1.7", + "thorsten/phpmyfaq": "<3.1.11", + "tinymce/tinymce": "<5.10.7|>=6,<6.3.1", + "titon/framework": ">=0,<9.9.99", + "tobiasbg/tablepress": "<= 2.0-RC1", + "topthink/framework": "<6.0.14", + "topthink/think": "<=6.0.9", + "topthink/thinkphp": "<=3.2.3", + "tribalsystems/zenario": "<=9.3.57595", + "truckersmp/phpwhois": "<=4.3.1", + "ttskch/pagination-service-provider": "<1", + "twig/twig": "<1.44.7|>=2,<2.15.3|>=3,<3.4.3", + "typo3/cms": "<2.0.5|>=3,<3.0.3|>=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.35|>=11,<11.5.23|>=12,<12.2", + "typo3/cms-backend": ">=7,<=7.6.50|>=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", + "typo3/cms-core": "<8.7.51|>=9,<9.5.40|>=10,<10.4.36|>=11,<11.5.23|>=12,<12.2", + "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", + "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "typo3/html-sanitizer": ">=1,<1.5|>=2,<2.1.1", + "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", + "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", + "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", + "ua-parser/uap-php": "<3.8", + "unisharp/laravel-filemanager": "<=2.5.1", + "userfrosting/userfrosting": ">=0.3.1,<4.6.3", + "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", + "vanilla/safecurl": "<0.9.2", + "verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4", + "vova07/yii2-fileapi-widget": "<0.1.9", + "vrana/adminer": "<4.8.1", + "wallabag/tcpdf": "<6.2.22", + "wallabag/wallabag": "<2.5.4", + "wanglelecc/laracms": "<=1.0.3", + "web-auth/webauthn-framework": ">=3.3,<3.3.4", + "webcoast/deferred-image-processing": "<1.0.2", + "webpa/webpa": "<3.1.2", + "wikimedia/parsoid": "<0.12.2", + "willdurand/js-translation-bundle": "<2.1.1", + "wintercms/winter": "<1.0.475|>=1.1,<1.1.10|>=1.2,<1.2.1", + "woocommerce/woocommerce": "<6.6", + "wp-cli/wp-cli": "<2.5", + "wp-graphql/wp-graphql": "<0.3.5", + "wpanel/wpanel4-cms": "<=4.3.1", + "wwbn/avideo": "<12.4", + "xataface/xataface": "<3", + "xpressengine/xpressengine": "<3.0.15", + "yeswiki/yeswiki": "<4.1", + "yetiforce/yetiforce-crm": "<=6.4", + "yidashi/yii2cmf": "<=2", + "yii2mod/yii2-cms": "<1.9.2", + "yiisoft/yii": "<1.1.27", + "yiisoft/yii2": "<2.0.38", + "yiisoft/yii2-bootstrap": "<2.0.4", + "yiisoft/yii2-dev": "<2.0.43", + "yiisoft/yii2-elasticsearch": "<2.0.5", + "yiisoft/yii2-gii": "<=2.2.4", + "yiisoft/yii2-jui": "<2.0.4", + "yiisoft/yii2-redis": "<2.0.8", + "yikesinc/yikes-inc-easy-mailchimp-extender": "<6.8.6", + "yoast-seo-for-typo3/yoast_seo": "<7.2.3", + "yourls/yourls": "<=1.8.2", + "zendesk/zendesk_api_client_php": "<2.2.11", + "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", + "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-db": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.10|>=2.3,<2.3.5", + "zendframework/zend-developer-tools": ">=1.2.2,<1.2.3", + "zendframework/zend-diactoros": "<1.8.4", + "zendframework/zend-feed": "<2.10.3", + "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-http": "<2.8.1", + "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", + "zendframework/zend-mail": ">=2,<2.4.11|>=2.5,<2.7.2", + "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-session": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.9|>=2.3,<2.3.4", + "zendframework/zend-validator": ">=2.3,<2.3.6", + "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zendframework": "<=3", + "zendframework/zendframework1": "<1.12.20", + "zendframework/zendopenid": ">=2,<2.0.2", + "zendframework/zendxml": ">=1,<1.0.1", + "zetacomponents/mail": "<1.8.2", + "zf-commons/zfc-user": "<1.2.2", + "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", + "zfr/zfr-oauth2-server-module": "<0.1.2", + "zoujingli/thinkadmin": "<6.0.22" + }, + "time": "2023-02-14T01:32:29+00:00", + "default-branch": true, + "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "role": "maintainer" + }, + { + "name": "Ilya Tribusean", + "email": "slash3b@gmail.com", + "role": "maintainer" + } + ], + "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", + "support": { + "issues": "https://github.com/Roave/SecurityAdvisories/issues", + "source": "https://github.com/Roave/SecurityAdvisories/tree/latest" + }, + "funding": [ + { + "url": "https://github.com/Ocramius", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/roave/security-advisories", + "type": "tidelift" + } + ], + "install-path": null + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "time": "2020-09-28T06:08:49+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/cli-parser" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "version_normalized": "1.0.8.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "time": "2020-10-26T13:08:54+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/code-unit" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "version_normalized": "2.0.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "time": "2020-09-28T05:30:19+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/code-unit-reverse-lookup" + }, + { + "name": "sebastian/comparator", + "version": "4.0.8", + "version_normalized": "4.0.8.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "time": "2022-09-14T12:41:17+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/comparator" + }, + { + "name": "sebastian/complexity", + "version": "2.0.2", + "version_normalized": "2.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.7", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "time": "2020-10-26T15:52:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/complexity" + }, + { + "name": "sebastian/diff", + "version": "4.0.4", + "version_normalized": "4.0.4.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "time": "2020-10-26T13:10:38+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/diff" + }, + { + "name": "sebastian/environment", + "version": "5.1.5", + "version_normalized": "5.1.5.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "time": "2023-02-03T06:03:51+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/environment" + }, + { + "name": "sebastian/exporter", + "version": "4.0.5", + "version_normalized": "4.0.5.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "time": "2022-09-14T06:03:37+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/exporter" + }, + { + "name": "sebastian/global-state", + "version": "5.0.5", + "version_normalized": "5.0.5.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "time": "2022-02-14T08:28:10+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/global-state" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.3", + "version_normalized": "1.0.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.6", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "time": "2020-11-28T06:42:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/lines-of-code" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "version_normalized": "4.0.4.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "time": "2020-10-26T13:12:34+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/object-enumerator" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "version_normalized": "2.0.4.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "time": "2020-10-26T13:14:26+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/object-reflector" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.5", + "version_normalized": "4.0.5.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "time": "2023-02-03T06:07:39+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/recursion-context" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.3", + "version_normalized": "3.0.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "time": "2020-09-28T06:45:17+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/resource-operations" + }, + { + "name": "sebastian/type", + "version": "3.2.1", + "version_normalized": "3.2.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "time": "2023-02-03T06:13:03+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/type" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "version_normalized": "3.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "time": "2020-09-28T06:39:44+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/version" + }, + { + "name": "sirbrillig/phpcs-variable-analysis", + "version": "v2.11.10", + "version_normalized": "2.11.10.0", + "source": { + "type": "git", + "url": "https://github.com/sirbrillig/phpcs-variable-analysis.git", + "reference": "0f25a3766f26df91d6bdda0c8931303fc85499d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/0f25a3766f26df91d6bdda0c8931303fc85499d7", + "reference": "0f25a3766f26df91d6bdda0c8931303fc85499d7", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "squizlabs/php_codesniffer": "^3.5.6" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.0", + "phpcsstandards/phpcsdevcs": "^1.1", + "phpstan/phpstan": "^1.7", + "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.5 || ^7.0 || ^8.0 || ^9.0", + "sirbrillig/phpcs-import-detection": "^1.1", + "vimeo/psalm": "^0.2 || ^0.3 || ^1.1 || ^4.24 || ^5.0@beta" + }, + "time": "2023-01-05T18:45:16+00:00", + "type": "phpcodesniffer-standard", + "installation-source": "dist", + "autoload": { + "psr-4": { + "VariableAnalysis\\": "VariableAnalysis/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Sam Graham", + "email": "php-codesniffer-variableanalysis@illusori.co.uk" + }, + { + "name": "Payton Swick", + "email": "payton@foolord.com" + } + ], + "description": "A PHPCS sniff to detect problems with variables.", + "keywords": [ + "phpcs", + "static analysis" + ], + "support": { + "issues": "https://github.com/sirbrillig/phpcs-variable-analysis/issues", + "source": "https://github.com/sirbrillig/phpcs-variable-analysis", + "wiki": "https://github.com/sirbrillig/phpcs-variable-analysis/wiki" + }, + "install-path": "../sirbrillig/phpcs-variable-analysis" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.7.1", + "version_normalized": "3.7.1.0", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", + "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "time": "2022-06-18T07:21:10+00:00", + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "installation-source": "dist", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards" + ], + "install-path": "../squizlabs/php_codesniffer" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.1", + "version_normalized": "1.2.1.0", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "time": "2021-07-28T10:34:58+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "install-path": "../theseer/tokenizer" + }, + { + "name": "togos/gitignore", + "version": "1.1.1", + "version_normalized": "1.1.1.0", + "source": { + "type": "git", + "url": "https://github.com/TOGoS/PHPGitIgnore.git", + "reference": "32bc0830e4123f670adcbf5ddda5bef362f4f4d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/TOGoS/PHPGitIgnore/zipball/32bc0830e4123f670adcbf5ddda5bef362f4f4d4", + "reference": "32bc0830e4123f670adcbf5ddda5bef362f4f4d4", + "shasum": "" + }, + "require": { + "php": ">=5.2" + }, + "require-dev": { + "togos/simpler-test": "1.1.1" + }, + "time": "2019-04-19T19:16:58+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "TOGoS_GitIgnore_": "src/main/php/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Parser for .gitignore (and sparse-checkout, and anything else using the same format) files", + "support": { + "issues": "https://github.com/TOGoS/PHPGitIgnore/issues", + "source": "https://github.com/TOGoS/PHPGitIgnore/tree/master" + }, + "install-path": "../togos/gitignore" + }, + { + "name": "wp-coding-standards/wpcs", + "version": "2.3.0", + "version_normalized": "2.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/WordPress/WordPress-Coding-Standards.git", + "reference": "7da1894633f168fe244afc6de00d141f27517b62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7da1894633f168fe244afc6de00d141f27517b62", + "reference": "7da1894633f168fe244afc6de00d141f27517b62", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "squizlabs/php_codesniffer": "^3.3.1" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || ^0.6", + "phpcompatibility/php-compatibility": "^9.0", + "phpcsstandards/phpcsdevtools": "^1.0", + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.6 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically." + }, + "time": "2020-05-13T23:57:56+00:00", + "type": "phpcodesniffer-standard", + "installation-source": "dist", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Contributors", + "homepage": "https://github.com/WordPress/WordPress-Coding-Standards/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions", + "keywords": [ + "phpcs", + "standards", + "wordpress" + ], + "install-path": "../wp-coding-standards/wpcs" + } + ], + "dev": true, + "dev-package-names": [ + "10up/wp_mock", + "antecedent/patchwork", + "automattic/vipwpcs", + "civicrm/composer-downloads-plugin", + "dealerdirect/phpcodesniffer-composer-installer", + "doctrine/instantiator", + "hamcrest/hamcrest-php", + "mockery/mockery", + "myclabs/deep-copy", + "nikic/php-parser", + "phar-io/manifest", + "phar-io/version", + "php-stubs/wordpress-stubs", + "phpcompatibility/php-compatibility", + "phpcompatibility/phpcompatibility-paragonie", + "phpcompatibility/phpcompatibility-wp", + "phpunit/php-code-coverage", + "phpunit/php-file-iterator", + "phpunit/php-invoker", + "phpunit/php-text-template", + "phpunit/php-timer", + "phpunit/phpunit", + "roave/security-advisories", + "sebastian/cli-parser", + "sebastian/code-unit", + "sebastian/code-unit-reverse-lookup", + "sebastian/comparator", + "sebastian/complexity", + "sebastian/diff", + "sebastian/environment", + "sebastian/exporter", + "sebastian/global-state", + "sebastian/lines-of-code", + "sebastian/object-enumerator", + "sebastian/object-reflector", + "sebastian/recursion-context", + "sebastian/resource-operations", + "sebastian/type", + "sebastian/version", + "sirbrillig/phpcs-variable-analysis", + "squizlabs/php_codesniffer", + "theseer/tokenizer", + "togos/gitignore", + "wp-coding-standards/wpcs" + ] +} diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php new file mode 100644 index 00000000..c0aae560 --- /dev/null +++ b/vendor/composer/installed.php @@ -0,0 +1,457 @@ + array( + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'type' => 'wordpress-plugin', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'reference' => '38c98fe46f42966d52b298d405d20a527d6f7789', + 'name' => 'rtcamp/login-with-google', + 'dev' => true, + ), + 'versions' => array( + '10up/wp_mock' => array( + 'pretty_version' => '0.4.2', + 'version' => '0.4.2.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../10up/wp_mock', + 'aliases' => array(), + 'reference' => '9019226eb50df275aa86bb15bfc98a619601ee49', + 'dev_requirement' => true, + ), + 'antecedent/patchwork' => array( + 'pretty_version' => '2.1.21', + 'version' => '2.1.21.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../antecedent/patchwork', + 'aliases' => array(), + 'reference' => '25c1fa0cd9a6e6d0d13863d8df8f050b6733f16d', + 'dev_requirement' => true, + ), + 'automattic/vipwpcs' => array( + 'pretty_version' => '2.3.3', + 'version' => '2.3.3.0', + 'type' => 'phpcodesniffer-standard', + 'install_path' => __DIR__ . '/../automattic/vipwpcs', + 'aliases' => array(), + 'reference' => '6cd0a6a82bc0ac988dbf9d6a7c2e293dc8ac640b', + 'dev_requirement' => true, + ), + 'civicrm/composer-downloads-plugin' => array( + 'pretty_version' => 'v3.0.1', + 'version' => '3.0.1.0', + 'type' => 'composer-plugin', + 'install_path' => __DIR__ . '/../civicrm/composer-downloads-plugin', + 'aliases' => array(), + 'reference' => '3aabb6d259a86158d01829fc2c62a2afb9618877', + 'dev_requirement' => true, + ), + 'cordoval/hamcrest-php' => array( + 'dev_requirement' => true, + 'replaced' => array( + 0 => '*', + ), + ), + 'davedevelopment/hamcrest-php' => array( + 'dev_requirement' => true, + 'replaced' => array( + 0 => '*', + ), + ), + 'dealerdirect/phpcodesniffer-composer-installer' => array( + 'pretty_version' => 'v0.7.2', + 'version' => '0.7.2.0', + 'type' => 'composer-plugin', + 'install_path' => __DIR__ . '/../dealerdirect/phpcodesniffer-composer-installer', + 'aliases' => array(), + 'reference' => '1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db', + 'dev_requirement' => true, + ), + 'doctrine/instantiator' => array( + 'pretty_version' => '1.5.0', + 'version' => '1.5.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../doctrine/instantiator', + 'aliases' => array(), + 'reference' => '0a0fa9780f5d4e507415a065172d26a98d02047b', + 'dev_requirement' => true, + ), + 'hamcrest/hamcrest-php' => array( + 'pretty_version' => 'v2.0.1', + 'version' => '2.0.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../hamcrest/hamcrest-php', + 'aliases' => array(), + 'reference' => '8c3d0a3f6af734494ad8f6fbbee0ba92422859f3', + 'dev_requirement' => true, + ), + 'kodova/hamcrest-php' => array( + 'dev_requirement' => true, + 'replaced' => array( + 0 => '*', + ), + ), + 'mockery/mockery' => array( + 'pretty_version' => '1.5.1', + 'version' => '1.5.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../mockery/mockery', + 'aliases' => array(), + 'reference' => 'e92dcc83d5a51851baf5f5591d32cb2b16e3684e', + 'dev_requirement' => true, + ), + 'myclabs/deep-copy' => array( + 'pretty_version' => '1.11.0', + 'version' => '1.11.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../myclabs/deep-copy', + 'aliases' => array(), + 'reference' => '14daed4296fae74d9e3201d2c4925d1acb7aa614', + 'dev_requirement' => true, + ), + 'nikic/php-parser' => array( + 'pretty_version' => 'v4.15.3', + 'version' => '4.15.3.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nikic/php-parser', + 'aliases' => array(), + 'reference' => '570e980a201d8ed0236b0a62ddf2c9cbb2034039', + 'dev_requirement' => true, + ), + 'phar-io/manifest' => array( + 'pretty_version' => '2.0.3', + 'version' => '2.0.3.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phar-io/manifest', + 'aliases' => array(), + 'reference' => '97803eca37d319dfa7826cc2437fc020857acb53', + 'dev_requirement' => true, + ), + 'phar-io/version' => array( + 'pretty_version' => '3.2.1', + 'version' => '3.2.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phar-io/version', + 'aliases' => array(), + 'reference' => '4f7fd7836c6f332bb2933569e566a0d6c4cbed74', + 'dev_requirement' => true, + ), + 'php-stubs/wordpress-stubs' => array( + 'pretty_version' => 'v6.1.1', + 'version' => '6.1.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../php-stubs/wordpress-stubs', + 'aliases' => array(), + 'reference' => '601c429ba8d91ef50a2a1bec05a7cd38b88064ff', + 'dev_requirement' => true, + ), + 'phpcompatibility/php-compatibility' => array( + 'pretty_version' => '9.3.5', + 'version' => '9.3.5.0', + 'type' => 'phpcodesniffer-standard', + 'install_path' => __DIR__ . '/../phpcompatibility/php-compatibility', + 'aliases' => array(), + 'reference' => '9fb324479acf6f39452e0655d2429cc0d3914243', + 'dev_requirement' => true, + ), + 'phpcompatibility/phpcompatibility-paragonie' => array( + 'pretty_version' => '1.3.2', + 'version' => '1.3.2.0', + 'type' => 'phpcodesniffer-standard', + 'install_path' => __DIR__ . '/../phpcompatibility/phpcompatibility-paragonie', + 'aliases' => array(), + 'reference' => 'bba5a9dfec7fcfbd679cfaf611d86b4d3759da26', + 'dev_requirement' => true, + ), + 'phpcompatibility/phpcompatibility-wp' => array( + 'pretty_version' => '2.1.4', + 'version' => '2.1.4.0', + 'type' => 'phpcodesniffer-standard', + 'install_path' => __DIR__ . '/../phpcompatibility/phpcompatibility-wp', + 'aliases' => array(), + 'reference' => 'b6c1e3ee1c35de6c41a511d5eb9bd03e447480a5', + 'dev_requirement' => true, + ), + 'phpunit/php-code-coverage' => array( + 'pretty_version' => '9.2.24', + 'version' => '9.2.24.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-code-coverage', + 'aliases' => array(), + 'reference' => '2cf940ebc6355a9d430462811b5aaa308b174bed', + 'dev_requirement' => true, + ), + 'phpunit/php-file-iterator' => array( + 'pretty_version' => '3.0.6', + 'version' => '3.0.6.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-file-iterator', + 'aliases' => array(), + 'reference' => 'cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf', + 'dev_requirement' => true, + ), + 'phpunit/php-invoker' => array( + 'pretty_version' => '3.1.1', + 'version' => '3.1.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-invoker', + 'aliases' => array(), + 'reference' => '5a10147d0aaf65b58940a0b72f71c9ac0423cc67', + 'dev_requirement' => true, + ), + 'phpunit/php-text-template' => array( + 'pretty_version' => '2.0.4', + 'version' => '2.0.4.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-text-template', + 'aliases' => array(), + 'reference' => '5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28', + 'dev_requirement' => true, + ), + 'phpunit/php-timer' => array( + 'pretty_version' => '5.0.3', + 'version' => '5.0.3.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-timer', + 'aliases' => array(), + 'reference' => '5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2', + 'dev_requirement' => true, + ), + 'phpunit/phpunit' => array( + 'pretty_version' => '9.6.3', + 'version' => '9.6.3.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/phpunit', + 'aliases' => array(), + 'reference' => 'e7b1615e3e887d6c719121c6d4a44b0ab9645555', + 'dev_requirement' => true, + ), + 'pimple/pimple' => array( + 'pretty_version' => 'v3.3.1', + 'version' => '3.3.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../pimple/pimple', + 'aliases' => array(), + 'reference' => '21e45061c3429b1e06233475cc0e1f6fc774d5b0', + 'dev_requirement' => false, + ), + 'psr/container' => array( + 'pretty_version' => '1.1.2', + 'version' => '1.1.2.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/container', + 'aliases' => array(), + 'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea', + 'dev_requirement' => false, + ), + 'roave/security-advisories' => array( + 'pretty_version' => 'dev-latest', + 'version' => 'dev-latest', + 'type' => 'metapackage', + 'install_path' => NULL, + 'aliases' => array( + 0 => '9999999-dev', + ), + 'reference' => '72ca3d8b529b6679ccbefcdc1433fa6aeb7564b8', + 'dev_requirement' => true, + ), + 'rtcamp/login-with-google' => array( + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'type' => 'wordpress-plugin', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'reference' => '38c98fe46f42966d52b298d405d20a527d6f7789', + 'dev_requirement' => false, + ), + 'sebastian/cli-parser' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/cli-parser', + 'aliases' => array(), + 'reference' => '442e7c7e687e42adc03470c7b668bc4b2402c0b2', + 'dev_requirement' => true, + ), + 'sebastian/code-unit' => array( + 'pretty_version' => '1.0.8', + 'version' => '1.0.8.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/code-unit', + 'aliases' => array(), + 'reference' => '1fc9f64c0927627ef78ba436c9b17d967e68e120', + 'dev_requirement' => true, + ), + 'sebastian/code-unit-reverse-lookup' => array( + 'pretty_version' => '2.0.3', + 'version' => '2.0.3.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/code-unit-reverse-lookup', + 'aliases' => array(), + 'reference' => 'ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5', + 'dev_requirement' => true, + ), + 'sebastian/comparator' => array( + 'pretty_version' => '4.0.8', + 'version' => '4.0.8.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/comparator', + 'aliases' => array(), + 'reference' => 'fa0f136dd2334583309d32b62544682ee972b51a', + 'dev_requirement' => true, + ), + 'sebastian/complexity' => array( + 'pretty_version' => '2.0.2', + 'version' => '2.0.2.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/complexity', + 'aliases' => array(), + 'reference' => '739b35e53379900cc9ac327b2147867b8b6efd88', + 'dev_requirement' => true, + ), + 'sebastian/diff' => array( + 'pretty_version' => '4.0.4', + 'version' => '4.0.4.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/diff', + 'aliases' => array(), + 'reference' => '3461e3fccc7cfdfc2720be910d3bd73c69be590d', + 'dev_requirement' => true, + ), + 'sebastian/environment' => array( + 'pretty_version' => '5.1.5', + 'version' => '5.1.5.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/environment', + 'aliases' => array(), + 'reference' => '830c43a844f1f8d5b7a1f6d6076b784454d8b7ed', + 'dev_requirement' => true, + ), + 'sebastian/exporter' => array( + 'pretty_version' => '4.0.5', + 'version' => '4.0.5.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/exporter', + 'aliases' => array(), + 'reference' => 'ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d', + 'dev_requirement' => true, + ), + 'sebastian/global-state' => array( + 'pretty_version' => '5.0.5', + 'version' => '5.0.5.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/global-state', + 'aliases' => array(), + 'reference' => '0ca8db5a5fc9c8646244e629625ac486fa286bf2', + 'dev_requirement' => true, + ), + 'sebastian/lines-of-code' => array( + 'pretty_version' => '1.0.3', + 'version' => '1.0.3.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/lines-of-code', + 'aliases' => array(), + 'reference' => 'c1c2e997aa3146983ed888ad08b15470a2e22ecc', + 'dev_requirement' => true, + ), + 'sebastian/object-enumerator' => array( + 'pretty_version' => '4.0.4', + 'version' => '4.0.4.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/object-enumerator', + 'aliases' => array(), + 'reference' => '5c9eeac41b290a3712d88851518825ad78f45c71', + 'dev_requirement' => true, + ), + 'sebastian/object-reflector' => array( + 'pretty_version' => '2.0.4', + 'version' => '2.0.4.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/object-reflector', + 'aliases' => array(), + 'reference' => 'b4f479ebdbf63ac605d183ece17d8d7fe49c15c7', + 'dev_requirement' => true, + ), + 'sebastian/recursion-context' => array( + 'pretty_version' => '4.0.5', + 'version' => '4.0.5.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/recursion-context', + 'aliases' => array(), + 'reference' => 'e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1', + 'dev_requirement' => true, + ), + 'sebastian/resource-operations' => array( + 'pretty_version' => '3.0.3', + 'version' => '3.0.3.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/resource-operations', + 'aliases' => array(), + 'reference' => '0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8', + 'dev_requirement' => true, + ), + 'sebastian/type' => array( + 'pretty_version' => '3.2.1', + 'version' => '3.2.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/type', + 'aliases' => array(), + 'reference' => '75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7', + 'dev_requirement' => true, + ), + 'sebastian/version' => array( + 'pretty_version' => '3.0.2', + 'version' => '3.0.2.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/version', + 'aliases' => array(), + 'reference' => 'c6c1022351a901512170118436c764e473f6de8c', + 'dev_requirement' => true, + ), + 'sirbrillig/phpcs-variable-analysis' => array( + 'pretty_version' => 'v2.11.10', + 'version' => '2.11.10.0', + 'type' => 'phpcodesniffer-standard', + 'install_path' => __DIR__ . '/../sirbrillig/phpcs-variable-analysis', + 'aliases' => array(), + 'reference' => '0f25a3766f26df91d6bdda0c8931303fc85499d7', + 'dev_requirement' => true, + ), + 'squizlabs/php_codesniffer' => array( + 'pretty_version' => '3.7.1', + 'version' => '3.7.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../squizlabs/php_codesniffer', + 'aliases' => array(), + 'reference' => '1359e176e9307e906dc3d890bcc9603ff6d90619', + 'dev_requirement' => true, + ), + 'theseer/tokenizer' => array( + 'pretty_version' => '1.2.1', + 'version' => '1.2.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../theseer/tokenizer', + 'aliases' => array(), + 'reference' => '34a41e998c2183e22995f158c581e7b5e755ab9e', + 'dev_requirement' => true, + ), + 'togos/gitignore' => array( + 'pretty_version' => '1.1.1', + 'version' => '1.1.1.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../togos/gitignore', + 'aliases' => array(), + 'reference' => '32bc0830e4123f670adcbf5ddda5bef362f4f4d4', + 'dev_requirement' => true, + ), + 'wp-coding-standards/wpcs' => array( + 'pretty_version' => '2.3.0', + 'version' => '2.3.0.0', + 'type' => 'phpcodesniffer-standard', + 'install_path' => __DIR__ . '/../wp-coding-standards/wpcs', + 'aliases' => array(), + 'reference' => '7da1894633f168fe244afc6de00d141f27517b62', + 'dev_requirement' => true, + ), + ), +); diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php new file mode 100644 index 00000000..580fa960 --- /dev/null +++ b/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 70400)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.0". You are running ' . PHP_VERSION . '.'; +} + +if ($issues) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); + } elseif (!headers_sent()) { + echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; + } + } + trigger_error( + 'Composer detected issues in your platform: ' . implode(' ', $issues), + E_USER_ERROR + ); +} diff --git a/vendor/dealerdirect/phpcodesniffer-composer-installer/.github_changelog_generator b/vendor/dealerdirect/phpcodesniffer-composer-installer/.github_changelog_generator new file mode 100644 index 00000000..a56afb45 --- /dev/null +++ b/vendor/dealerdirect/phpcodesniffer-composer-installer/.github_changelog_generator @@ -0,0 +1,34 @@ +add-issues-wo-labels=true +add-pr-wo-labels=true +author=true +breaking-labels=backwards-incompatible,Backwards incompatible,breaking +breaking-prefix=### Breaking changes +bug-labels=bug - confirmed +bug-prefix=### Fixes +compare-link=true +date-format=%Y-%m-%d +deprecated-labels=deprecated,Deprecated,Type: Deprecated +deprecated-prefix=### Deprecates +enhancement-labels=improvement,documentation,builds / deploys / releases,feature request +enhancement-prefix=### Changes +exclude-labels=bug - unconfirmed,can't reproduce / won't fix,invalid,triage +filter-issues-by-milestone=true +header= +http-cache=true +issues=true +issue-prefix=### Closes +merge-prefix=### Pull request(s) without label +output= +project=phpcodesniffer-composer-installer +pulls=true +removed-labels=removed,Removed,Type: Removed +removed-prefix=### Removes +security-labels=security,Security,Type: Security +security-prefix=### Security +summary-labels=Release summary,release-summary,Summary,summary +unreleased=true +unreleased-label=Unreleased +unreleased-only=true +user=Dealerdirect +usernames-as-github-logins=true +verbose=false diff --git a/vendor/dealerdirect/phpcodesniffer-composer-installer/.remarkrc b/vendor/dealerdirect/phpcodesniffer-composer-installer/.remarkrc new file mode 100644 index 00000000..bfa065da --- /dev/null +++ b/vendor/dealerdirect/phpcodesniffer-composer-installer/.remarkrc @@ -0,0 +1,6 @@ +{ + "plugins": [ + "remark-preset-lint-recommended", + ["remark-lint-list-item-indent", "space"] + ] +} diff --git a/vendor/dealerdirect/phpcodesniffer-composer-installer/.yamllint b/vendor/dealerdirect/phpcodesniffer-composer-installer/.yamllint new file mode 100644 index 00000000..ef433bd4 --- /dev/null +++ b/vendor/dealerdirect/phpcodesniffer-composer-installer/.yamllint @@ -0,0 +1,8 @@ +--- +extends: default + +rules: + line-length: + level: warning + max: 120 + truthy: {allowed-values: ["true", "false", "on"]} diff --git a/vendor/dealerdirect/phpcodesniffer-composer-installer/CODE_OF_CONDUCT.md b/vendor/dealerdirect/phpcodesniffer-composer-installer/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..a408703d --- /dev/null +++ b/vendor/dealerdirect/phpcodesniffer-composer-installer/CODE_OF_CONDUCT.md @@ -0,0 +1,129 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/vendor/dealerdirect/phpcodesniffer-composer-installer/LICENSE.md b/vendor/dealerdirect/phpcodesniffer-composer-installer/LICENSE.md new file mode 100644 index 00000000..893aafb7 --- /dev/null +++ b/vendor/dealerdirect/phpcodesniffer-composer-installer/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016-2022 Dealerdirect B.V. + +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/dealerdirect/phpcodesniffer-composer-installer/README.md b/vendor/dealerdirect/phpcodesniffer-composer-installer/README.md new file mode 100644 index 00000000..b8ae2201 --- /dev/null +++ b/vendor/dealerdirect/phpcodesniffer-composer-installer/README.md @@ -0,0 +1,285 @@ +# PHP_CodeSniffer Standards Composer Installer Plugin + +![Project Stage][project-stage-shield] +![Last Commit][last-updated-shield] +![Awesome][awesome-shield] +[![License][license-shield]](LICENSE.md) + +[![Tests][ghactionstest-shield]][ghactions] +[![Scrutinizer][scrutinizer-shield]][scrutinizer] +[![Latest Version on Packagist][packagist-version-shield]][packagist-version] +[![Packagist][packagist-shield]][packagist] + +[![Contributor Covenant][code-of-conduct-shield]][code-of-conduct] + +This composer installer plugin allows for easy installation of [PHP_CodeSniffer][codesniffer] coding standards (rulesets). + +No more symbolic linking of directories, checking out repositories on specific locations or changing +the `phpcs` configuration. + +## Usage + +Installation can be done with [Composer][composer], by requiring this package as a development dependency: + +```bash +composer require --dev dealerdirect/phpcodesniffer-composer-installer +``` + +When using Composer 2.2 or higher, Composer will [ask for your permission](https://blog.packagist.com/composer-2-2/#more-secure-plugin-execution) to allow this plugin to execute code. For this plugin to be functional, permission needs to be granted. + +When permission has been granted, the following snippet will automatically be added to your `composer.json` file by Composer: +```json +{ + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + } +} +``` + +When using Composer < 2.2, you can add the permission flag ahead of the upgrade to Composer 2.2, by running: +```bash +composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true +``` + +That's it. + +### Compatibility + +This plugin is compatible with: + +- PHP **5.x**, **7.x**, and **8.x** (Support for PHP v8 is available since [`v0.7.0`][v0.7]) +- [Composer][composer] **1.x** and **2.x** (Support for Composer v2 is available since [`v0.7.0`][v0.7]) +- [PHP_CodeSniffer][codesniffer] **2.x** and **3.x** (Support for PHP_CodeSniffer v3 is available since [`v0.4.0`][v0.4]) + + +> **ℹ️ Please Note:** [Composer treats _minor_ releases below 1.0.0 as _major_ releases][composer-manual-caret]. So version `0.7.x` (or higher) of this plugin must be _explicitly_ set as version constraint when using Composer 2.x or PHP 8.0. In other words: using `^0.6` will **not** work with Composer 2.x or PHP 8.0. + +### How it works + +Basically, this plugin executes the following steps: + +- This plugin searches for [`phpcodesniffer-standard` packages][] in all of your currently installed Composer packages. +- Matching packages and the project itself are scanned for PHP_CodeSniffer rulesets. +- The plugin will call PHP_CodeSniffer and configure the `installed_paths` option. + +### Example project + +The following is an example Composer project and has included +multiple `phpcodesniffer-standard` packages. + +```json +{ + "name": "dealerdirect/example-project", + "description": "Just an example project", + "type": "project", + "require": {}, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "*", + "object-calisthenics/phpcs-calisthenics-rules": "*", + "phpcompatibility/php-compatibility": "*", + "wp-coding-standards/wpcs": "*" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + } +} +``` + +After running `composer install` PHP_CodeSniffer just works: + +```bash +$ ./vendor/bin/phpcs -i +The installed coding standards are MySource, PEAR, PSR1, PSR2, PSR12, Squiz, Zend, ObjectCalisthenics, +PHPCompatibility, WordPress, WordPress-Core, WordPress-Docs and WordPress-Extra +``` + +### Calling the plugin directly + +In some circumstances, it is desirable to call this plugin's functionality +directly. For instance, during development or in [CI][definition-ci] environments. + +As the plugin requires Composer to work, direct calls need to be wired through a +project's `composer.json`. + +This is done by adding a call to the `Plugin::run` function in the `script` +section of the `composer.json`: + +```json +{ + "scripts": { + "install-codestandards": [ + "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run" + ] + } +} +``` + +The command can then be called using `composer run-script install-codestandards` or +referenced from other script configurations, as follows: + +```json +{ + "scripts": { + "install-codestandards": [ + "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run" + ], + "post-install-cmd": [ + "@install-codestandards" + ] + } +} +``` + +For more details about Composer scripts, please refer to [the section on scripts +in the Composer manual][composer-manual-scripts]. + +### Changing the Coding Standards search depth + +By default, this plugin searches up for Coding Standards up to three directories +deep. In most cases, this should be sufficient. However, this plugin allows +you to customize the search depth setting if needed. + +```json +{ + "extra": { + "phpcodesniffer-search-depth": 5 + } +} +``` + +### Caveats + +When this plugin is installed globally, composer will load the _global_ plugin rather +than the one from the local repository. Despite [this behavior being documented +in the composer manual][using-composer-plugins], it could potentially confuse +as another version of the plugin could be run and not the one specified by the project. + +## Developing Coding Standards + +Coding standard can be developed normally, as documented by [PHP_CodeSniffer][codesniffer], in the [Coding Standard Tutorial][tutorial]. + +Create a composer package of your coding standard by adding a `composer.json` file. + +```json +{ + "name" : "acme/phpcodesniffer-our-standards", + "description" : "Package contains all coding standards of the Acme company", + "require" : { + "php" : ">=5.4.0", + "squizlabs/php_codesniffer" : "^3.6" + }, + "type" : "phpcodesniffer-standard" +} +``` + +Requirements: +* The repository may contain one or more standards. +* Each standard can have a separate directory no deeper than 3 levels from the repository root. +* The package `type` must be `phpcodesniffer-standard`. Without this, the plugin will not trigger. + +### Requiring the plugin from within your coding standard + +If your coding standard itself depends on additional external PHPCS standards, this plugin can +make life easier on your end-users by taking care of the installation of all standards - yours +and your dependencies - for them. + +This can help reduce the number of support questions about setting the `installed_paths`, as well +as simplify your standard's installation instructions. + +For this to work, make sure your external standard adds this plugin to the `composer.json` config +via `require`, **not** `require-dev`. + +> :warning: Your end-user may already `require-dev` this plugin and/or other external standards used +> by your end-users may require this plugin as well. +> +> To prevent your end-users getting into "_dependency hell_", make sure to make the version requirement +> for this plugin flexible. +> +> As, for now, this plugin is still regarded as "unstable" (version < 1.0), remember that Composer +> treats unstable minors as majors and will not be able to resolve one config requiring this plugin +> at version `^0.5`, while another requires it at version `^0.6`. +> Either allow multiple minors or use `*` as the version requirement. +> +> Some examples of flexible requirements which can be used: +> ```bash +> composer require dealerdirect/phpcodesniffer-composer-installer:"*" +> composer require dealerdirect/phpcodesniffer-composer-installer:"0.*" +> composer require dealerdirect/phpcodesniffer-composer-installer:"^0.4.1 || ^0.5 || ^0.6 || ^0.7" +> ``` + +## Changelog + +This repository does not contain a `CHANGELOG.md` file, however, we do publish a changelog on each release +using the [GitHub releases][changelog] functionality. + +## Contributing + +This is an active open-source project. We are always open to people who want to +use the code or contribute to it. + +We've set up a separate document for our [contribution guidelines][contributing-guidelines]. + +Thank you for being involved! :heart_eyes: + +## Authors & contributors + +The original idea and setup of this repository is by [Franck Nijhof][frenck], employee @ Dealerdirect. + +For a full list of all author and/or contributors, check [the contributors page][contributors]. + +## License + +The MIT License (MIT) + +Copyright (c) 2016-2022 Dealerdirect B.V. + +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. + +[awesome-shield]: https://img.shields.io/badge/awesome%3F-yes-brightgreen.svg +[changelog]: https://github.com/Dealerdirect/phpcodesniffer-composer-installer/releases +[code-of-conduct-shield]: https://img.shields.io/badge/Contributor%20Covenant-v2.0-ff69b4.svg +[code-of-conduct]: CODE_OF_CONDUCT.md +[codesniffer]: https://github.com/squizlabs/PHP_CodeSniffer +[composer-manual-scripts]: https://getcomposer.org/doc/articles/scripts.md +[composer-manual-caret]: https://getcomposer.org/doc/articles/versions.md#caret-version-range- +[composer]: https://getcomposer.org/ +[contributing-guidelines]: CONTRIBUTING.md +[contributors]: https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors +[definition-ci]: https://en.wikipedia.org/wiki/Continuous_integration +[frenck]: https://github.com/frenck +[last-updated-shield]: https://img.shields.io/github/last-commit/Dealerdirect/phpcodesniffer-composer-installer.svg +[license-shield]: https://img.shields.io/github/license/dealerdirect/phpcodesniffer-composer-installer.svg +[packagist-shield]: https://img.shields.io/packagist/dt/dealerdirect/phpcodesniffer-composer-installer.svg +[packagist-version-shield]: https://img.shields.io/packagist/v/dealerdirect/phpcodesniffer-composer-installer.svg +[packagist-version]: https://packagist.org/packages/dealerdirect/phpcodesniffer-composer-installer +[packagist]: https://packagist.org/packages/dealerdirect/phpcodesniffer-composer-installer +[`phpcodesniffer-standard` packages]: https://packagist.org/explore/?type=phpcodesniffer-standard +[project-stage-shield]: https://img.shields.io/badge/Project%20Stage-Development-yellowgreen.svg +[scrutinizer-shield]: https://img.shields.io/scrutinizer/g/dealerdirect/phpcodesniffer-composer-installer.svg +[scrutinizer]: https://scrutinizer-ci.com/g/dealerdirect/phpcodesniffer-composer-installer/ +[ghactionstest-shield]: https://github.com/Dealerdirect/phpcodesniffer-composer-installer/actions/workflows/integrationtest.yml/badge.svg +[ghactions]: https://github.com/Dealerdirect/phpcodesniffer-composer-installer/actions/workflows/integrationtest.yml +[tutorial]: https://github.com/squizlabs/PHP_CodeSniffer/wiki/Coding-Standard-Tutorial +[using-composer-plugins]: https://getcomposer.org/doc/articles/plugins.md#using-plugins +[v0.4]: https://github.com/Dealerdirect/phpcodesniffer-composer-installer/releases/tag/v0.4.0 +[v0.7]: https://github.com/Dealerdirect/phpcodesniffer-composer-installer/releases/tag/v0.7.0 diff --git a/vendor/dealerdirect/phpcodesniffer-composer-installer/bin/generate-changelog.sh b/vendor/dealerdirect/phpcodesniffer-composer-installer/bin/generate-changelog.sh new file mode 100644 index 00000000..42dd8d8f --- /dev/null +++ b/vendor/dealerdirect/phpcodesniffer-composer-installer/bin/generate-changelog.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +set -o errexit -o errtrace -o nounset -o pipefail + +: ${GITHUB_CHANGELOG_GENERATOR:=github_changelog_generator} +: ${GEM:=gem} + +generate_changelog() { + local -r sVersion="${1?One parameter required: }" + + if ! command -v "${GITHUB_CHANGELOG_GENERATOR}" >/dev/null 2>&1;then + echo "This script requires the '${GITHUB_CHANGELOG_GENERATOR}' Ruby Gem" + + if ! command -v "${GEM}" >/dev/null 2>&1;then + echo "Could not find the '${GEM}' command needed to install 'github_changelog_generator'!" >&2 + echo 'Aborting.' + exit 67 + else + echo "Installing '${GITHUB_CHANGELOG_GENERATOR}'..." + gem install github_changelog_generator + fi + fi + + local -r sChangelog="$( + "${GITHUB_CHANGELOG_GENERATOR}" \ + --user Dealerdirect \ + --project phpcodesniffer-composer-installer \ + --token "$(cat ~/.github-token)" \ + --future-release "${sVersion}" \ + --enhancement-label '### Changes' \ + --bugs-label '### Fixes' \ + --issues-label '### Closes' \ + --usernames-as-github-logins \ + --bug-labels 'bug - confirmed' \ + --enhancement-labels 'improvement','documentation','builds / deploys / releases','feature request' \ + --exclude-labels 'bug - unconfirmed',"can't reproduce / won't fix",'invalid','triage' \ + --unreleased-only \ + --output '' 2>/dev/null + )" || echo "There was a problem running '${GITHUB_CHANGELOG_GENERATOR}'" + + echo "${sChangelog}" | sed -E 's/\[\\(#[0-9]+)\]\([^)]+\)/\1/' | head -n -3 +} + +if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then + export -f generate_changelog +else + generate_changelog "${@}" + exit $? +fi diff --git a/vendor/dealerdirect/phpcodesniffer-composer-installer/composer.json b/vendor/dealerdirect/phpcodesniffer-composer-installer/composer.json new file mode 100644 index 00000000..e5b72c9e --- /dev/null +++ b/vendor/dealerdirect/phpcodesniffer-composer-installer/composer.json @@ -0,0 +1,57 @@ +{ + "name": "dealerdirect/phpcodesniffer-composer-installer", + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "type": "composer-plugin", + "keywords": [ + "composer", "installer", "plugin", + "phpcs", "phpcbf", "codesniffer", "phpcodesniffer", "php_codesniffer", + "standard", "standards", "style guide", "stylecheck", + "qa", "quality", "code quality", "tests" + ], + "homepage": "http://www.dealerdirect.com", + "license": "MIT", + "authors": [ + { + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" + }, + { + "name" : "Contributors", + "homepage" : "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" + } + ], + "support": { + "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", + "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" + }, + "require": { + "php": ">=5.3", + "composer-plugin-api": "^1.0 || ^2.0", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + }, + "require-dev": { + "composer/composer": "*", + "phpcompatibility/php-compatibility": "^9.0", + "php-parallel-lint/php-parallel-lint": "^1.3.1" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "autoload": { + "psr-4": { + "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "extra": { + "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "scripts": { + "install-codestandards": [ + "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run" + ], + "lint": [ + "@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --exclude vendor --exclude .git" + ] + } +} diff --git a/vendor/dealerdirect/phpcodesniffer-composer-installer/src/Plugin.php b/vendor/dealerdirect/phpcodesniffer-composer-installer/src/Plugin.php new file mode 100644 index 00000000..75653e49 --- /dev/null +++ b/vendor/dealerdirect/phpcodesniffer-composer-installer/src/Plugin.php @@ -0,0 +1,621 @@ + + */ +class Plugin implements PluginInterface, EventSubscriberInterface +{ + const KEY_MAX_DEPTH = 'phpcodesniffer-search-depth'; + + const MESSAGE_ERROR_WRONG_MAX_DEPTH = + 'The value of "%s" (in the composer.json "extra".section) must be an integer larger then %d, %s given.'; + + const MESSAGE_NOT_INSTALLED = 'PHPCodeSniffer is not installed'; + const MESSAGE_NOTHING_TO_INSTALL = 'Nothing to install or update'; + const MESSAGE_PLUGIN_UNINSTALLED = 'PHPCodeSniffer Composer Installer is uninstalled'; + const MESSAGE_RUNNING_INSTALLER = 'Running PHPCodeSniffer Composer Installer'; + + const PACKAGE_NAME = 'squizlabs/php_codesniffer'; + const PACKAGE_TYPE = 'phpcodesniffer-standard'; + + const PHPCS_CONFIG_REGEX = '`%s:[^\r\n]+`'; + const PHPCS_CONFIG_KEY = 'installed_paths'; + + const PLUGIN_NAME = 'dealerdirect/phpcodesniffer-composer-installer'; + + /** + * @var Composer + */ + private $composer; + + /** + * @var string + */ + private $cwd; + + /** + * @var Filesystem + */ + private $filesystem; + + /** + * @var array + */ + private $installedPaths; + + /** + * @var IOInterface + */ + private $io; + + /** + * @var ProcessExecutor + */ + private $processExecutor; + + /** + * Triggers the plugin's main functionality. + * + * Makes it possible to run the plugin as a custom command. + * + * @param Event $event + * + * @throws \InvalidArgumentException + * @throws \RuntimeException + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + public static function run(Event $event) + { + $io = $event->getIO(); + $composer = $event->getComposer(); + + $instance = new static(); + + $instance->io = $io; + $instance->composer = $composer; + $instance->init(); + $instance->onDependenciesChangedEvent(); + } + + /** + * {@inheritDoc} + * + * @throws \RuntimeException + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + public function activate(Composer $composer, IOInterface $io) + { + $this->composer = $composer; + $this->io = $io; + + $this->init(); + } + + /** + * {@inheritDoc} + */ + public function deactivate(Composer $composer, IOInterface $io) + { + } + + /** + * {@inheritDoc} + */ + public function uninstall(Composer $composer, IOInterface $io) + { + } + + /** + * Prepares the plugin so it's main functionality can be run. + * + * @throws \RuntimeException + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + private function init() + { + $this->cwd = getcwd(); + $this->installedPaths = array(); + + $this->processExecutor = new ProcessExecutor($this->io); + $this->filesystem = new Filesystem($this->processExecutor); + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + ScriptEvents::POST_INSTALL_CMD => array( + array('onDependenciesChangedEvent', 0), + ), + ScriptEvents::POST_UPDATE_CMD => array( + array('onDependenciesChangedEvent', 0), + ), + ); + } + + /** + * Entry point for post install and post update events. + * + * @throws \InvalidArgumentException + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + public function onDependenciesChangedEvent() + { + $io = $this->io; + $isVerbose = $io->isVerbose(); + $exitCode = 0; + + if ($isVerbose) { + $io->write(sprintf('%s', self::MESSAGE_RUNNING_INSTALLER)); + } + + if ($this->isPHPCodeSnifferInstalled() === true) { + $this->loadInstalledPaths(); + $installPathCleaned = $this->cleanInstalledPaths(); + $installPathUpdated = $this->updateInstalledPaths(); + + if ($installPathCleaned === true || $installPathUpdated === true) { + $exitCode = $this->saveInstalledPaths(); + } elseif ($isVerbose) { + $io->write(sprintf('%s', self::MESSAGE_NOTHING_TO_INSTALL)); + } + } else { + $pluginPackage = $this + ->composer + ->getRepositoryManager() + ->getLocalRepository() + ->findPackages(self::PLUGIN_NAME) + ; + + $isPluginUninstalled = count($pluginPackage) === 0; + + if ($isPluginUninstalled) { + if ($isVerbose) { + $io->write(sprintf('%s', self::MESSAGE_PLUGIN_UNINSTALLED)); + } + } else { + $exitCode = 1; + if ($isVerbose) { + $io->write(sprintf('%s', self::MESSAGE_NOT_INSTALLED)); + } + } + } + + return $exitCode; + } + + /** + * Load all paths from PHP_CodeSniffer into an array. + * + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + private function loadInstalledPaths() + { + if ($this->isPHPCodeSnifferInstalled() === true) { + $this->processExecutor->execute( + 'phpcs --config-show', + $output, + $this->composer->getConfig()->get('bin-dir') + ); + + $regex = sprintf(self::PHPCS_CONFIG_REGEX, self::PHPCS_CONFIG_KEY); + if (preg_match($regex, $output, $match) === 1) { + $phpcsInstalledPaths = str_replace(self::PHPCS_CONFIG_KEY . ': ', '', $match[0]); + $phpcsInstalledPaths = trim($phpcsInstalledPaths); + + if ($phpcsInstalledPaths !== '') { + $this->installedPaths = explode(',', $phpcsInstalledPaths); + } + } + } + } + + /** + * Save all coding standard paths back into PHP_CodeSniffer + * + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + * + * @return int Exit code. 0 for success, 1 or higher for failure. + */ + private function saveInstalledPaths() + { + // Check if we found installed paths to set. + if (count($this->installedPaths) !== 0) { + sort($this->installedPaths); + $paths = implode(',', $this->installedPaths); + $arguments = array('--config-set', self::PHPCS_CONFIG_KEY, $paths); + $configMessage = sprintf( + 'PHP CodeSniffer Config %s set to %s', + self::PHPCS_CONFIG_KEY, + $paths + ); + } else { + // Delete the installed paths if none were found. + $arguments = array('--config-delete', self::PHPCS_CONFIG_KEY); + $configMessage = sprintf( + 'PHP CodeSniffer Config %s delete', + self::PHPCS_CONFIG_KEY + ); + } + + // Prepare message in case of failure + $failMessage = sprintf( + 'Failed to set PHP CodeSniffer %s Config', + self::PHPCS_CONFIG_KEY + ); + + // Determine the path to the main PHPCS file. + $phpcsPath = $this->getPHPCodeSnifferInstallPath(); + if (file_exists($phpcsPath . '/bin/phpcs') === true) { + // PHPCS 3.x. + $phpcsExecutable = './bin/phpcs'; + } else { + // PHPCS 2.x. + $phpcsExecutable = './scripts/phpcs'; + } + + // Okay, lets rock! + $command = vsprintf( + '%s %s %s', + array( + 'php executable' => $this->getPhpExecCommand(), + 'phpcs executable' => $phpcsExecutable, + 'arguments' => implode(' ', $arguments), + ) + ); + + $exitCode = $this->processExecutor->execute($command, $configResult, $phpcsPath); + if ($exitCode === 0) { + $exitCode = $this->verifySaveSuccess(); + } + + if ($exitCode === 0) { + $this->io->write($configMessage); + } else { + $this->io->write($failMessage); + } + + if ($this->io->isVerbose() && !empty($configResult)) { + $this->io->write(sprintf('%s', $configResult)); + } + + return $exitCode; + } + + /** + * Verify that the paths which were expected to be saved, have been. + * + * @return int Exit code. 0 for success, 1 for failure. + */ + private function verifySaveSuccess() + { + $exitCode = 1; + $expectedPaths = $this->installedPaths; + + // Request the currently set installed paths after the save. + $this->loadInstalledPaths(); + + $registeredPaths = array_intersect($this->installedPaths, $expectedPaths); + $registeredCount = count($registeredPaths); + $expectedCount = count($expectedPaths); + + if ($expectedCount === $registeredCount) { + $exitCode = 0; + } + + if ($exitCode === 1 && $this->io->isVerbose()) { + $verificationMessage = sprintf( + "Paths to external standards found by the plugin: %s\n" + . 'Actual paths registered with PHPCS: %s', + implode(', ', $expectedPaths), + implode(', ', $this->installedPaths) + ); + $this->io->write($verificationMessage); + } + + return $exitCode; + } + + /** + * Get the path to the current PHP version being used. + * + * Duplicate of the same in the EventDispatcher class in Composer itself. + */ + protected function getPhpExecCommand() + { + $finder = new PhpExecutableFinder(); + + $phpPath = $finder->find(false); + + if ($phpPath === false) { + throw new \RuntimeException('Failed to locate PHP binary to execute ' . $phpPath); + } + + $phpArgs = $finder->findArguments(); + $phpArgs = $phpArgs + ? ' ' . implode(' ', $phpArgs) + : '' + ; + + $command = ProcessExecutor::escape($phpPath) . + $phpArgs . + ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen')) . + ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions')) . + ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit')) + ; + + return $command; + } + + /** + * Iterate trough all known paths and check if they are still valid. + * + * If path does not exists, is not an directory or isn't readable, the path + * is removed from the list. + * + * @return bool True if changes where made, false otherwise + */ + private function cleanInstalledPaths() + { + $changes = false; + foreach ($this->installedPaths as $key => $path) { + // This might be a relative path as well + $alternativePath = realpath($this->getPHPCodeSnifferInstallPath() . \DIRECTORY_SEPARATOR . $path); + + if ( + (is_dir($path) === false || is_readable($path) === false) && + ( + $alternativePath === false || + is_dir($alternativePath) === false || + is_readable($alternativePath) === false + ) + ) { + unset($this->installedPaths[$key]); + $changes = true; + } + } + return $changes; + } + + /** + * Check all installed packages (including the root package) against + * the installed paths from PHP_CodeSniffer and add the missing ones. + * + * @return bool True if changes where made, false otherwise + * + * @throws \InvalidArgumentException + * @throws \RuntimeException + */ + private function updateInstalledPaths() + { + $changes = false; + + $searchPaths = array($this->cwd); + $codingStandardPackages = $this->getPHPCodingStandardPackages(); + foreach ($codingStandardPackages as $package) { + $installPath = $this->composer->getInstallationManager()->getInstallPath($package); + if ($this->filesystem->isAbsolutePath($installPath) === false) { + $installPath = $this->filesystem->normalizePath( + $this->cwd . \DIRECTORY_SEPARATOR . $installPath + ); + } + $searchPaths[] = $installPath; + } + + $finder = new Finder(); + $finder->files() + ->depth('<= ' . $this->getMaxDepth()) + ->depth('>= ' . $this->getMinDepth()) + ->ignoreUnreadableDirs() + ->ignoreVCS(true) + ->in($searchPaths) + ->name('ruleset.xml'); + + // Process each found possible ruleset. + foreach ($finder as $ruleset) { + $standardsPath = $ruleset->getPath(); + + // Pick the directory above the directory containing the standard, unless this is the project root. + if ($standardsPath !== $this->cwd) { + $standardsPath = dirname($standardsPath); + } + + // Use relative paths for local project repositories. + if ($this->isRunningGlobally() === false) { + $standardsPath = $this->filesystem->findShortestPath( + $this->getPHPCodeSnifferInstallPath(), + $standardsPath, + true + ); + } + + // De-duplicate and add when directory is not configured. + if (in_array($standardsPath, $this->installedPaths, true) === false) { + $this->installedPaths[] = $standardsPath; + $changes = true; + } + } + + return $changes; + } + + /** + * Iterates through Composers' local repository looking for valid Coding + * Standard packages. + * + * If the package is the RootPackage (the one the plugin is installed into), + * the package is ignored for now since it needs a different install path logic. + * + * @return array Composer packages containing coding standard(s) + */ + private function getPHPCodingStandardPackages() + { + $codingStandardPackages = array_filter( + $this->composer->getRepositoryManager()->getLocalRepository()->getPackages(), + function (PackageInterface $package) { + if ($package instanceof AliasPackage) { + return false; + } + return $package->getType() === Plugin::PACKAGE_TYPE; + } + ); + + if ( + ! $this->composer->getPackage() instanceof RootPackageInterface + && $this->composer->getPackage()->getType() === self::PACKAGE_TYPE + ) { + $codingStandardPackages[] = $this->composer->getPackage(); + } + + return $codingStandardPackages; + } + + /** + * Searches for the installed PHP_CodeSniffer Composer package + * + * @param null|string|\Composer\Semver\Constraint\ConstraintInterface $versionConstraint to match against + * + * @return PackageInterface|null + */ + private function getPHPCodeSnifferPackage($versionConstraint = null) + { + $packages = $this + ->composer + ->getRepositoryManager() + ->getLocalRepository() + ->findPackages(self::PACKAGE_NAME, $versionConstraint); + + return array_shift($packages); + } + + /** + * Returns the path to the PHP_CodeSniffer package installation location + * + * @return string + */ + private function getPHPCodeSnifferInstallPath() + { + return $this->composer->getInstallationManager()->getInstallPath($this->getPHPCodeSnifferPackage()); + } + + /** + * Simple check if PHP_CodeSniffer is installed. + * + * @param null|string|\Composer\Semver\Constraint\ConstraintInterface $versionConstraint to match against + * + * @return bool Whether PHP_CodeSniffer is installed + */ + private function isPHPCodeSnifferInstalled($versionConstraint = null) + { + return ($this->getPHPCodeSnifferPackage($versionConstraint) !== null); + } + + /** + * Test if composer is running "global" + * This check kinda dirty, but it is the "Composer Way" + * + * @return bool Whether Composer is running "globally" + * + * @throws \RuntimeException + */ + private function isRunningGlobally() + { + return ($this->composer->getConfig()->get('home') === $this->cwd); + } + + /** + * Determines the maximum search depth when searching for Coding Standards. + * + * @return int + * + * @throws \InvalidArgumentException + */ + private function getMaxDepth() + { + $maxDepth = 3; + + $extra = $this->composer->getPackage()->getExtra(); + + if (array_key_exists(self::KEY_MAX_DEPTH, $extra)) { + $maxDepth = $extra[self::KEY_MAX_DEPTH]; + $minDepth = $this->getMinDepth(); + + if ( + (string) (int) $maxDepth !== (string) $maxDepth /* Must be an integer or cleanly castable to one */ + || $maxDepth <= $minDepth /* Larger than the minimum */ + || is_float($maxDepth) === true /* Within the boundaries of integer */ + ) { + $message = vsprintf( + self::MESSAGE_ERROR_WRONG_MAX_DEPTH, + array( + 'key' => self::KEY_MAX_DEPTH, + 'min' => $minDepth, + 'given' => var_export($maxDepth, true), + ) + ); + + throw new \InvalidArgumentException($message); + } + } + + return (int) $maxDepth; + } + + /** + * Returns the minimal search depth for Coding Standard packages. + * + * Usually this is 0, unless PHP_CodeSniffer >= 3 is used. + * + * @return int + */ + private function getMinDepth() + { + if ($this->isPHPCodeSnifferInstalled('>= 3.0.0') !== true) { + return 1; + } + return 0; + } +} diff --git a/vendor/doctrine/instantiator/.doctrine-project.json b/vendor/doctrine/instantiator/.doctrine-project.json new file mode 100644 index 00000000..24ae36e0 --- /dev/null +++ b/vendor/doctrine/instantiator/.doctrine-project.json @@ -0,0 +1,47 @@ +{ + "active": true, + "name": "Instantiator", + "slug": "instantiator", + "docsSlug": "doctrine-instantiator", + "codePath": "/src", + "versions": [ + { + "name": "1.5", + "branchName": "1.5.x", + "slug": "latest", + "upcoming": true + }, + { + "name": "1.4", + "branchName": "1.4.x", + "slug": "1.4", + "aliases": [ + "current", + "stable" + ], + "maintained": true, + "current": true + }, + { + "name": "1.3", + "branchName": "1.3.x", + "slug": "1.3", + "maintained": false + }, + { + "name": "1.2", + "branchName": "1.2.x", + "slug": "1.2" + }, + { + "name": "1.1", + "branchName": "1.1.x", + "slug": "1.1" + }, + { + "name": "1.0", + "branchName": "1.0.x", + "slug": "1.0" + } + ] +} diff --git a/vendor/doctrine/instantiator/CONTRIBUTING.md b/vendor/doctrine/instantiator/CONTRIBUTING.md new file mode 100644 index 00000000..c1a2c42e --- /dev/null +++ b/vendor/doctrine/instantiator/CONTRIBUTING.md @@ -0,0 +1,35 @@ +# Contributing + + * Follow the [Doctrine Coding Standard](https://github.com/doctrine/coding-standard) + * The project will follow strict [object calisthenics](http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php) + * Any contribution must provide tests for additional introduced conditions + * Any un-confirmed issue needs a failing test case before being accepted + * Pull requests must be sent from a new hotfix/feature branch, not from `master`. + +## Installation + +To install the project and run the tests, you need to clone it first: + +```sh +$ git clone git://github.com/doctrine/instantiator.git +``` + +You will then need to run a composer installation: + +```sh +$ cd Instantiator +$ curl -s https://getcomposer.org/installer | php +$ php composer.phar update +``` + +## Testing + +The PHPUnit version to be used is the one installed as a dev- dependency via composer: + +```sh +$ ./vendor/bin/phpunit +``` + +Accepted coverage for new contributions is 80%. Any contribution not satisfying this requirement +won't be merged. + diff --git a/vendor/doctrine/instantiator/LICENSE b/vendor/doctrine/instantiator/LICENSE new file mode 100644 index 00000000..4d983d1a --- /dev/null +++ b/vendor/doctrine/instantiator/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 Doctrine Project + +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/doctrine/instantiator/README.md b/vendor/doctrine/instantiator/README.md new file mode 100644 index 00000000..1fa95679 --- /dev/null +++ b/vendor/doctrine/instantiator/README.md @@ -0,0 +1,38 @@ +# Instantiator + +This library provides a way of avoiding usage of constructors when instantiating PHP classes. + +[![Build Status](https://travis-ci.org/doctrine/instantiator.svg?branch=master)](https://travis-ci.org/doctrine/instantiator) +[![Code Coverage](https://codecov.io/gh/doctrine/instantiator/branch/master/graph/badge.svg)](https://codecov.io/gh/doctrine/instantiator/branch/master) +[![Dependency Status](https://www.versioneye.com/package/php--doctrine--instantiator/badge.svg)](https://www.versioneye.com/package/php--doctrine--instantiator) + +[![Latest Stable Version](https://poser.pugx.org/doctrine/instantiator/v/stable.png)](https://packagist.org/packages/doctrine/instantiator) +[![Latest Unstable Version](https://poser.pugx.org/doctrine/instantiator/v/unstable.png)](https://packagist.org/packages/doctrine/instantiator) + +## Installation + +The suggested installation method is via [composer](https://getcomposer.org/): + +```sh +composer require doctrine/instantiator +``` + +## Usage + +The instantiator is able to create new instances of any class without using the constructor or any API of the class +itself: + +```php +$instantiator = new \Doctrine\Instantiator\Instantiator(); + +$instance = $instantiator->instantiate(\My\ClassName\Here::class); +``` + +## Contributing + +Please read the [CONTRIBUTING.md](CONTRIBUTING.md) contents if you wish to help out! + +## Credits + +This library was migrated from [ocramius/instantiator](https://github.com/Ocramius/Instantiator), which +has been donated to the doctrine organization, and which is now deprecated in favour of this package. diff --git a/vendor/doctrine/instantiator/composer.json b/vendor/doctrine/instantiator/composer.json new file mode 100644 index 00000000..fab81720 --- /dev/null +++ b/vendor/doctrine/instantiator/composer.json @@ -0,0 +1,48 @@ +{ + "name": "doctrine/instantiator", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "type": "library", + "license": "MIT", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "instantiate", + "constructor" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "ext-phar": "*", + "ext-pdo": "*", + "doctrine/coding-standard": "^9 || ^11", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "autoload-dev": { + "psr-0": { + "DoctrineTest\\InstantiatorPerformance\\": "tests", + "DoctrineTest\\InstantiatorTest\\": "tests", + "DoctrineTest\\InstantiatorTestAsset\\": "tests" + } + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + } +} diff --git a/vendor/doctrine/instantiator/docs/en/index.rst b/vendor/doctrine/instantiator/docs/en/index.rst new file mode 100644 index 00000000..0c85da0b --- /dev/null +++ b/vendor/doctrine/instantiator/docs/en/index.rst @@ -0,0 +1,68 @@ +Introduction +============ + +This library provides a way of avoiding usage of constructors when instantiating PHP classes. + +Installation +============ + +The suggested installation method is via `composer`_: + +.. code-block:: console + + $ composer require doctrine/instantiator + +Usage +===== + +The instantiator is able to create new instances of any class without +using the constructor or any API of the class itself: + +.. code-block:: php + + instantiate(User::class); + +Contributing +============ + +- Follow the `Doctrine Coding Standard`_ +- The project will follow strict `object calisthenics`_ +- Any contribution must provide tests for additional introduced + conditions +- Any un-confirmed issue needs a failing test case before being + accepted +- Pull requests must be sent from a new hotfix/feature branch, not from + ``master``. + +Testing +======= + +The PHPUnit version to be used is the one installed as a dev- dependency +via composer: + +.. code-block:: console + + $ ./vendor/bin/phpunit + +Accepted coverage for new contributions is 80%. Any contribution not +satisfying this requirement won’t be merged. + +Credits +======= + +This library was migrated from `ocramius/instantiator`_, which has been +donated to the doctrine organization, and which is now deprecated in +favour of this package. + +.. _composer: https://getcomposer.org/ +.. _CONTRIBUTING.md: CONTRIBUTING.md +.. _ocramius/instantiator: https://github.com/Ocramius/Instantiator +.. _Doctrine Coding Standard: https://github.com/doctrine/coding-standard +.. _object calisthenics: http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php diff --git a/vendor/doctrine/instantiator/docs/en/sidebar.rst b/vendor/doctrine/instantiator/docs/en/sidebar.rst new file mode 100644 index 00000000..0c364791 --- /dev/null +++ b/vendor/doctrine/instantiator/docs/en/sidebar.rst @@ -0,0 +1,4 @@ +.. toctree:: + :depth: 3 + + index diff --git a/vendor/doctrine/instantiator/psalm.xml b/vendor/doctrine/instantiator/psalm.xml new file mode 100644 index 00000000..e9b622b3 --- /dev/null +++ b/vendor/doctrine/instantiator/psalm.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php new file mode 100644 index 00000000..e6a5195f --- /dev/null +++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php @@ -0,0 +1,12 @@ + $reflectionClass + * + * @template T of object + */ + public static function fromAbstractClass(ReflectionClass $reflectionClass): self + { + return new self(sprintf( + 'The provided class "%s" is abstract, and cannot be instantiated', + $reflectionClass->getName() + )); + } + + public static function fromEnum(string $className): self + { + return new self(sprintf( + 'The provided class "%s" is an enum, and cannot be instantiated', + $className + )); + } +} diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php new file mode 100644 index 00000000..4e55ac52 --- /dev/null +++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php @@ -0,0 +1,59 @@ + $reflectionClass + * + * @template T of object + */ + public static function fromSerializationTriggeredException( + ReflectionClass $reflectionClass, + Exception $exception + ): self { + return new self( + sprintf( + 'An exception was raised while trying to instantiate an instance of "%s" via un-serialization', + $reflectionClass->getName() + ), + 0, + $exception + ); + } + + /** + * @phpstan-param ReflectionClass $reflectionClass + * + * @template T of object + */ + public static function fromUncleanUnSerialization( + ReflectionClass $reflectionClass, + string $errorString, + int $errorCode, + string $errorFile, + int $errorLine + ): self { + return new self( + sprintf( + 'Could not produce an instance of "%s" via un-serialization, since an error was triggered ' + . 'in file "%s" at line "%d"', + $reflectionClass->getName(), + $errorFile, + $errorLine + ), + 0, + new Exception($errorString, $errorCode) + ); + } +} diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php new file mode 100644 index 00000000..10067a0f --- /dev/null +++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php @@ -0,0 +1,262 @@ + $className + * + * @return object + * @phpstan-return T + * + * @throws ExceptionInterface + * + * @template T of object + */ + public function instantiate($className) + { + if (isset(self::$cachedCloneables[$className])) { + /** @phpstan-var T */ + $cachedCloneable = self::$cachedCloneables[$className]; + + return clone $cachedCloneable; + } + + if (isset(self::$cachedInstantiators[$className])) { + $factory = self::$cachedInstantiators[$className]; + + return $factory(); + } + + return $this->buildAndCacheFromFactory($className); + } + + /** + * Builds the requested object and caches it in static properties for performance + * + * @phpstan-param class-string $className + * + * @return object + * @phpstan-return T + * + * @template T of object + */ + private function buildAndCacheFromFactory(string $className) + { + $factory = self::$cachedInstantiators[$className] = $this->buildFactory($className); + $instance = $factory(); + + if ($this->isSafeToClone(new ReflectionClass($instance))) { + self::$cachedCloneables[$className] = clone $instance; + } + + return $instance; + } + + /** + * Builds a callable capable of instantiating the given $className without + * invoking its constructor. + * + * @phpstan-param class-string $className + * + * @phpstan-return callable(): T + * + * @throws InvalidArgumentException + * @throws UnexpectedValueException + * @throws ReflectionException + * + * @template T of object + */ + private function buildFactory(string $className): callable + { + $reflectionClass = $this->getReflectionClass($className); + + if ($this->isInstantiableViaReflection($reflectionClass)) { + return [$reflectionClass, 'newInstanceWithoutConstructor']; + } + + $serializedString = sprintf( + '%s:%d:"%s":0:{}', + is_subclass_of($className, Serializable::class) ? self::SERIALIZATION_FORMAT_USE_UNSERIALIZER : self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER, + strlen($className), + $className + ); + + $this->checkIfUnSerializationIsSupported($reflectionClass, $serializedString); + + return static function () use ($serializedString) { + return unserialize($serializedString); + }; + } + + /** + * @phpstan-param class-string $className + * + * @phpstan-return ReflectionClass + * + * @throws InvalidArgumentException + * @throws ReflectionException + * + * @template T of object + */ + private function getReflectionClass(string $className): ReflectionClass + { + if (! class_exists($className)) { + throw InvalidArgumentException::fromNonExistingClass($className); + } + + if (PHP_VERSION_ID >= 80100 && enum_exists($className, false)) { + throw InvalidArgumentException::fromEnum($className); + } + + $reflection = new ReflectionClass($className); + + if ($reflection->isAbstract()) { + throw InvalidArgumentException::fromAbstractClass($reflection); + } + + return $reflection; + } + + /** + * @phpstan-param ReflectionClass $reflectionClass + * + * @throws UnexpectedValueException + * + * @template T of object + */ + private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, string $serializedString): void + { + set_error_handler(static function (int $code, string $message, string $file, int $line) use ($reflectionClass, &$error): bool { + $error = UnexpectedValueException::fromUncleanUnSerialization( + $reflectionClass, + $message, + $code, + $file, + $line + ); + + return true; + }); + + try { + $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString); + } finally { + restore_error_handler(); + } + + if ($error) { + throw $error; + } + } + + /** + * @phpstan-param ReflectionClass $reflectionClass + * + * @throws UnexpectedValueException + * + * @template T of object + */ + private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, string $serializedString): void + { + try { + unserialize($serializedString); + } catch (Exception $exception) { + throw UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $exception); + } + } + + /** + * @phpstan-param ReflectionClass $reflectionClass + * + * @template T of object + */ + private function isInstantiableViaReflection(ReflectionClass $reflectionClass): bool + { + return ! ($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal()); + } + + /** + * Verifies whether the given class is to be considered internal + * + * @phpstan-param ReflectionClass $reflectionClass + * + * @template T of object + */ + private function hasInternalAncestors(ReflectionClass $reflectionClass): bool + { + do { + if ($reflectionClass->isInternal()) { + return true; + } + + $reflectionClass = $reflectionClass->getParentClass(); + } while ($reflectionClass); + + return false; + } + + /** + * Checks if a class is cloneable + * + * Classes implementing `__clone` cannot be safely cloned, as that may cause side-effects. + * + * @phpstan-param ReflectionClass $reflectionClass + * + * @template T of object + */ + private function isSafeToClone(ReflectionClass $reflectionClass): bool + { + return $reflectionClass->isCloneable() + && ! $reflectionClass->hasMethod('__clone') + && ! $reflectionClass->isSubclassOf(ArrayIterator::class); + } +} diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php new file mode 100644 index 00000000..10508b56 --- /dev/null +++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php @@ -0,0 +1,24 @@ + $className + * + * @return object + * @phpstan-return T + * + * @throws ExceptionInterface + * + * @template T of object + */ + public function instantiate($className); +} diff --git a/vendor/hamcrest/hamcrest-php/.coveralls.yml b/vendor/hamcrest/hamcrest-php/.coveralls.yml new file mode 100644 index 00000000..f2f9ed58 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/.coveralls.yml @@ -0,0 +1 @@ +src_dir: hamcrest diff --git a/vendor/hamcrest/hamcrest-php/.github/workflows/tests.yml b/vendor/hamcrest/hamcrest-php/.github/workflows/tests.yml new file mode 100644 index 00000000..06255a1b --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/.github/workflows/tests.yml @@ -0,0 +1,38 @@ +name: tests + +on: + push: + pull_request: + +jobs: + tests: + + runs-on: ubuntu-latest + strategy: + matrix: + php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] + + name: PHP ${{ matrix.php }} + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: curl + tools: composer:v2 + coverage: none + + - name: Install PHP 7 dependencies + run: composer update --prefer-dist --no-interaction --no-progress + if: "matrix.php != '8.0'" + + - name: Install PHP 8 dependencies + run: composer update --prefer-dist --no-interaction --no-progress --ignore-platform-reqs + if: "matrix.php == '8.0'" + + - name: Execute tests + run: vendor/bin/phpunit -c tests/phpunit.xml.dist diff --git a/vendor/hamcrest/hamcrest-php/.gitignore b/vendor/hamcrest/hamcrest-php/.gitignore new file mode 100644 index 00000000..987e2a25 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/.gitignore @@ -0,0 +1,2 @@ +composer.lock +vendor diff --git a/vendor/hamcrest/hamcrest-php/.gush.yml b/vendor/hamcrest/hamcrest-php/.gush.yml new file mode 100644 index 00000000..b7c226d5 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/.gush.yml @@ -0,0 +1,7 @@ +adapter: github +issue_tracker: github +meta-header: "Copyright (c) 2009-2015 hamcrest.org" +table-pr: + fixed_tickets: ['Fixed Tickets', ''] + license: ['License', MIT] +base: master diff --git a/vendor/hamcrest/hamcrest-php/.travis.yml b/vendor/hamcrest/hamcrest-php/.travis.yml new file mode 100644 index 00000000..3b5651fa --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/.travis.yml @@ -0,0 +1,23 @@ +language: php + +dist: trusty + +matrix: + include: + - name: PHP 5.3 + php: 5.3 + dist: precise + - name: PHP 5.4 + php: 5.4 + - name: PHP 5.5 + php: 5.5 + - name: PHP 5.6 + php: 5.6 + - name: HHVM 3.18 + php: hhvm-3.18 + +install: + - travis_retry composer update --prefer-dist --no-progress + +script: + - vendor/bin/phpunit -c tests/phpunit.xml.dist diff --git a/vendor/hamcrest/hamcrest-php/CHANGES.txt b/vendor/hamcrest/hamcrest-php/CHANGES.txt new file mode 100644 index 00000000..bad8bcfe --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/CHANGES.txt @@ -0,0 +1,173 @@ +== Version 2.0.1: Released Jul 09 2020 == + +* Added support for PHP 8 + + +== Version 2.0: Released Feb 26 2016 == + +* Removed automatic loading of global functions + + +== Version 1.1.0: Released Feb 2 2012 == + +Issues Fixed: 121, 138, 147 + +* Added non-empty matchers to complement the emptiness-matching forms. + + - nonEmptyString() + - nonEmptyArray() + - nonEmptyTraversable() + +* Added ability to pass variable arguments to several array-based matcher + factory methods so they work like allOf() et al. + + - anArray() + - arrayContainingInAnyOrder(), containsInAnyOrder() + - arrayContaining(), contains() + - stringContainsInOrder() + +* Matchers that accept an array of matchers now also accept variable arguments. + Any non-matcher arguments are wrapped by IsEqual. + +* Added noneOf() as a shortcut for not(anyOf()). + + +== Version 1.0.0: Released Jan 20 2012 == + +Issues Fixed: 119, 136, 139, 141, 148, 149, 172 + +* Moved hamcrest.php into Hamcrest folder and renamed to Hamcrest.php. + This is more in line with PEAR packaging standards. + +* Renamed callable() to callableValue() for compatibility with PHP 5.4. + +* Added Hamcrest_Text_StringContainsIgnoringCase to assert using stripos(). + + assertThat('fOObAr', containsStringIgnoringCase('oba')); + assertThat('fOObAr', containsString('oba')->ignoringCase()); + +* Fixed Hamcrest_Core_IsInstanceOf to return false for native types. + +* Moved string-based matchers to Hamcrest_Text package. + StringContains, StringEndsWith, StringStartsWith, and SubstringMatcher + +* Hamcrest.php and Hamcrest_Matchers.php are now built from @factory doctags. + Added @factory doctag to every static factory method. + +* Hamcrest_Matchers and Hamcrest.php now import each matcher as-needed + and Hamcrest.php calls the matchers directly instead of Hamcrest_Matchers. + + +== Version 0.3.0: Released Jul 26 2010 == + +* Added running count to Hamcrest_MatcherAssert with methods to get and reset it. + This can be used by unit testing frameworks for reporting. + +* Added Hamcrest_Core_HasToString to assert return value of toString() or __toString(). + + assertThat($anObject, hasToString('foo')); + +* Added Hamcrest_Type_IsScalar to assert is_scalar(). + Matches values of type bool, int, float, double, and string. + + assertThat($count, scalarValue()); + assertThat('foo', scalarValue()); + +* Added Hamcrest_Collection package. + + - IsEmptyTraversable + - IsTraversableWithSize + + assertThat($iterator, emptyTraversable()); + assertThat($iterator, traversableWithSize(5)); + +* Added Hamcrest_Xml_HasXPath to assert XPath expressions or the content of nodes in an XML/HTML DOM. + + assertThat($dom, hasXPath('books/book/title')); + assertThat($dom, hasXPath('books/book[contains(title, "Alice")]', 3)); + assertThat($dom, hasXPath('books/book/title', 'Alice in Wonderland')); + assertThat($dom, hasXPath('count(books/book)', greaterThan(10))); + +* Added aliases to match the Java API. + + hasEntry() -> hasKeyValuePair() + hasValue() -> hasItemInArray() + contains() -> arrayContaining() + containsInAnyOrder() -> arrayContainingInAnyOrder() + +* Added optional subtype to Hamcrest_TypeSafeMatcher to enforce object class or resource type. + +* Hamcrest_TypeSafeDiagnosingMatcher now extends Hamcrest_TypeSafeMatcher. + + +== Version 0.2.0: Released Jul 14 2010 == + +Issues Fixed: 109, 111, 114, 115 + +* Description::appendValues() and appendValueList() accept Iterator and IteratorAggregate. [111] + BaseDescription::appendValue() handles IteratorAggregate. + +* assertThat() accepts a single boolean parameter and + wraps any non-Matcher third parameter with equalTo(). + +* Removed null return value from assertThat(). [114] + +* Fixed wrong variable name in contains(). [109] + +* Added Hamcrest_Core_IsSet to assert isset(). + + assertThat(array('foo' => 'bar'), set('foo')); + assertThat(array('foo' => 'bar'), notSet('bar')); + +* Added Hamcrest_Core_IsTypeOf to assert built-in types with gettype(). [115] + Types: array, boolean, double, integer, null, object, resource, and string. + Note that gettype() returns "double" for float values. + + assertThat($count, typeOf('integer')); + assertThat(3.14159, typeOf('double')); + assertThat(array('foo', 'bar'), typeOf('array')); + assertThat(new stdClass(), typeOf('object')); + +* Added type-specific matchers in new Hamcrest_Type package. + + - IsArray + - IsBoolean + - IsDouble (includes float values) + - IsInteger + - IsObject + - IsResource + - IsString + + assertThat($count, integerValue()); + assertThat(3.14159, floatValue()); + assertThat('foo', stringValue()); + +* Added Hamcrest_Type_IsNumeric to assert is_numeric(). + Matches values of type int and float/double or strings that are formatted as numbers. + + assertThat(5, numericValue()); + assertThat('-5e+3', numericValue()); + +* Added Hamcrest_Type_IsCallable to assert is_callable(). + + assertThat('preg_match', callable()); + assertThat(array('SomeClass', 'SomeMethod'), callable()); + assertThat(array($object, 'SomeMethod'), callable()); + assertThat($object, callable()); + assertThat(function ($x, $y) { return $x + $y; }, callable()); + +* Added Hamcrest_Text_MatchesPattern for regex matching with preg_match(). + + assertThat('foobar', matchesPattern('/o+b/')); + +* Added aliases: + - atLeast() for greaterThanOrEqualTo() + - atMost() for lessThanOrEqualTo() + + +== Version 0.1.0: Released Jul 7 2010 == + +* Created PEAR package + +* Core matchers + diff --git a/vendor/hamcrest/hamcrest-php/LICENSE.txt b/vendor/hamcrest/hamcrest-php/LICENSE.txt new file mode 100644 index 00000000..91cd329a --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/LICENSE.txt @@ -0,0 +1,27 @@ +BSD License + +Copyright (c) 2000-2014, www.hamcrest.org +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +Neither the name of Hamcrest nor the names of its contributors may be used to endorse +or promote products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY +WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. diff --git a/vendor/hamcrest/hamcrest-php/README.md b/vendor/hamcrest/hamcrest-php/README.md new file mode 100644 index 00000000..52e20413 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/README.md @@ -0,0 +1,488 @@ +This is the PHP port of Hamcrest Matchers +========================================= + +[![Build Status](https://travis-ci.org/hamcrest/hamcrest-php.png?branch=master)](https://travis-ci.org/hamcrest/hamcrest-php) + +Hamcrest is a matching library originally written for Java, but +subsequently ported to many other languages. hamcrest-php is the +official PHP port of Hamcrest and essentially follows a literal +translation of the original Java API for Hamcrest, with a few +Exceptions, mostly down to PHP language barriers: + + 1. `instanceOf($theClass)` is actually `anInstanceOf($theClass)` + + 2. `both(containsString('a'))->and(containsString('b'))` + is actually `both(containsString('a'))->andAlso(containsString('b'))` + + 3. `either(containsString('a'))->or(containsString('b'))` + is actually `either(containsString('a'))->orElse(containsString('b'))` + + 4. Unless it would be non-semantic for a matcher to do so, hamcrest-php + allows dynamic typing for it's input, in "the PHP way". Exception are + where semantics surrounding the type itself would suggest otherwise, + such as stringContains() and greaterThan(). + + 5. Several official matchers have not been ported because they don't + make sense or don't apply in PHP: + + - `typeCompatibleWith($theClass)` + - `eventFrom($source)` + - `hasProperty($name)` ** + - `samePropertyValuesAs($obj)` ** + + 6. When most of the collections matchers are finally ported, PHP-specific + aliases will probably be created due to a difference in naming + conventions between Java's Arrays, Collections, Sets and Maps compared + with PHP's Arrays. + +--- +** [Unless we consider POPO's (Plain Old PHP Objects) akin to JavaBeans] + - The POPO thing is a joke. Java devs coin the term POJO's (Plain Old + Java Objects). + + +Usage +----- + +Hamcrest matchers are easy to use as: + +```php +Hamcrest_MatcherAssert::assertThat('a', Hamcrest_Matchers::equalToIgnoringCase('A')); +``` + +Alternatively, you can use the global proxy-functions: + +```php +$result = true; +// with an identifier +assertThat("result should be true", $result, equalTo(true)); + +// without an identifier +assertThat($result, equalTo(true)); + +// evaluate a boolean expression +assertThat($result === true); + +// with syntactic sugar is() +assertThat(true, is(true)); +``` + +:warning: **NOTE:** the global proxy-functions aren't autoloaded by default, so you will need to load them first: + +```php +\Hamcrest\Util::registerGlobalFunctions(); +``` + +For brevity, all of the examples below use the proxy-functions. + + +Documentation +------------- +A tutorial can be found on the [Hamcrest site](https://code.google.com/archive/p/hamcrest/wikis/TutorialPHP.wiki). + + +Available Matchers +------------------ +* [Array](../master/README.md#array) +* [Collection](../master/README.md#collection) +* [Object](../master/README.md#object) +* [Numbers](../master/README.md#numbers) +* [Type checking](../master/README.md#type-checking) +* [XML](../master/README.md#xml) + + +### Array + +* `anArray` - evaluates an array +```php +assertThat([], anArray()); +``` + +* `hasItemInArray` - check if item exists in array +```php +$list = range(2, 7, 2); +$item = 4; +assertThat($list, hasItemInArray($item)); +``` + +* `hasValue` - alias of hasItemInArray + +* `arrayContainingInAnyOrder` - check if array contains elements in any order +```php +assertThat([2, 4, 6], arrayContainingInAnyOrder([6, 4, 2])); +assertThat([2, 4, 6], arrayContainingInAnyOrder([4, 2, 6])); +``` + +* `containsInAnyOrder` - alias of arrayContainingInAnyOrder + +* `arrayContaining` - An array with elements that match the given matchers in the same order. +```php +assertThat([2, 4, 6], arrayContaining([2, 4, 6])); +assertthat([2, 4, 6], not(arrayContaining([6, 4, 2]))); +``` + +* `contains` - check array in same order +```php +assertThat([2, 4, 6], contains([2, 4, 6])); +``` + +* `hasKeyInArray` - check if array has given key +```php +assertThat(['name'=> 'foobar'], hasKeyInArray('name')); +``` + +* `hasKey` - alias of hasKeyInArray + +* `hasKeyValuePair` - check if arary has given key, value pair +```php +assertThat(['name'=> 'foobar'], hasKeyValuePair('name', 'foobar')); +``` +* `hasEntry` - same as hasKeyValuePair + +* `arrayWithSize` - check array has given size +```php +assertthat([2, 4, 6], arrayWithSize(3)); +``` +* `emptyArray` - check if array is emtpy +```php +assertThat([], emptyArray()); +``` + +* `nonEmptyArray` +```php +assertThat([1], nonEmptyArray()); +``` + +### Collection + +* `emptyTraversable` - check if traversable is empty +```php +$empty_it = new EmptyIterator; +assertThat($empty_it, emptyTraversable()); +``` + +* `nonEmptyTraversable` - check if traversable isn't empty +```php +$non_empty_it = new ArrayIterator(range(1, 10)); +assertThat($non_empty_it, nonEmptyTraversable()); +a +``` + +* `traversableWithSize` +```php +$non_empty_it = new ArrayIterator(range(1, 10)); +assertThat($non_empty_it, traversableWithSize(count(range(1, 10)))); +` +``` + +### Core + +* `allOf` - Evaluates to true only if ALL of the passed in matchers evaluate to true. +```php +assertThat([2,4,6], allOf(hasValue(2), arrayWithSize(3))); +``` + +* `anyOf` - Evaluates to true if ANY of the passed in matchers evaluate to true. +```php +assertThat([2, 4, 6], anyOf(hasValue(8), hasValue(2))); +``` + +* `noneOf` - Evaluates to false if ANY of the passed in matchers evaluate to true. +```php +assertThat([2, 4, 6], noneOf(hasValue(1), hasValue(3))); +``` + +* `both` + `andAlso` - This is useful for fluently combining matchers that must both pass. +```php +assertThat([2, 4, 6], both(hasValue(2))->andAlso(hasValue(4))); +``` + +* `either` + `orElse` - This is useful for fluently combining matchers where either may pass, +```php +assertThat([2, 4, 6], either(hasValue(2))->orElse(hasValue(4))); +``` + +* `describedAs` - Wraps an existing matcher and overrides the description when it fails. +```php +$expected = "Dog"; +$found = null; +// this assertion would result error message as Expected: is not null but: was null +//assertThat("Expected {$expected}, got {$found}", $found, is(notNullValue())); +// and this assertion would result error message as Expected: Dog but: was null +//assertThat($found, describedAs($expected, notNullValue())); +``` + +* `everyItem` - A matcher to apply to every element in an array. +```php +assertThat([2, 4, 6], everyItem(notNullValue())); +``` + +* `hasItem` - check array has given item, it can take a matcher argument +```php +assertThat([2, 4, 6], hasItem(equalTo(2))); +``` + +* `hasItems` - check array has givem items, it can take multiple matcher as arguments +```php +assertThat([1, 3, 5], hasItems(equalTo(1), equalTo(3))); +``` + +### Object + +* `hasToString` - check `__toString` or `toString` method +```php +class Foo { + public $name = null; + + public function __toString() { + return "[Foo]Instance"; + } +} +$foo = new Foo; +assertThat($foo, hasToString(equalTo("[Foo]Instance"))); +``` + +* `equalTo` - compares two instances using comparison operator '==' +```php +$foo = new Foo; +$foo2 = new Foo; +assertThat($foo, equalTo($foo2)); +``` + +* `identicalTo` - compares two instances using identity operator '===' +```php +assertThat($foo, is(not(identicalTo($foo2)))); +``` + +* `anInstanceOf` - check instance is an instance|sub-class of given class +```php +assertThat($foo, anInstanceOf(Foo::class)); +``` + +* `any` - alias of `anInstanceOf` + +* `nullValue` check null +```php +assertThat(null, is(nullValue())); +``` + +* `notNullValue` check not null +```php +assertThat("", notNullValue()); +``` + +* `sameInstance` - check for same instance +```php +assertThat($foo, is(not(sameInstance($foo2)))); +assertThat($foo, is(sameInstance($foo))); +``` + +* `typeOf`- check type +```php +assertThat(1, typeOf("integer")); +``` + +* `notSet` - check if instance property is not set +```php +assertThat($foo, notSet("name")); +``` + +* `set` - check if instance property is set +```php +$foo->name = "bar"; +assertThat($foo, set("name")); +``` + +### Numbers + +* `closeTo` - check value close to a range +```php +assertThat(3, closeTo(3, 0.5)); +``` + +* `comparesEqualTo` - check with '==' +```php +assertThat(2, comparesEqualTo(2)); +``` + +* `greaterThan` - check '>' +``` +assertThat(2, greaterThan(1)); +``` + +* `greaterThanOrEqualTo` +```php +assertThat(2, greaterThanOrEqualTo(2)); +``` + +* `atLeast` - The value is >= given value +```php +assertThat(3, atLeast(2)); +``` +* `lessThan` +```php +assertThat(2, lessThan(3)); +``` + +* `lessThanOrEqualTo` +```php +assertThat(2, lessThanOrEqualTo(3)); +``` + +* `atMost` - The value is <= given value +```php +assertThat(2, atMost(3)); +``` + +### String + +* `emptyString` - check for empty string +```php +assertThat("", emptyString()); +``` + +* `isEmptyOrNullString` +```php +assertThat(null, isEmptyOrNullString()); +``` + +* `nullOrEmptyString` +```php +assertThat("", nullOrEmptyString()); +``` + +* `isNonEmptyString` +```php +assertThat("foo", isNonEmptyString()); +``` + +* `nonEmptyString` +```php +assertThat("foo", nonEmptyString()); +``` + +* `equalToIgnoringCase` +```php +assertThat("Foo", equalToIgnoringCase("foo")); +``` +* `equalToIgnoringWhiteSpace` +```php +assertThat(" Foo ", equalToIgnoringWhiteSpace("Foo")); +``` + +* `matchesPattern` - matches with regex pattern +```php +assertThat("foobarbaz", matchesPattern('/(foo)(bar)(baz)/')); +``` + +* `containsString` - check for substring +```php +assertThat("foobar", containsString("foo")); +``` + +* `containsStringIgnoringCase` +```php +assertThat("fooBar", containsStringIgnoringCase("bar")); +``` + +* `stringContainsInOrder` +```php +assertThat("foo", stringContainsInOrder("foo")); +``` + +* `endsWith` - check string that ends with given value +```php +assertThat("foo", endsWith("oo")); +``` + +* `startsWith` - check string that starts with given value +```php +assertThat("bar", startsWith("ba")); +``` + +### Type-checking + +* `arrayValue` - check array type +```php +assertThat([], arrayValue()); +``` + +* `booleanValue` +```php +assertThat(true, booleanValue()); +``` +* `boolValue` - alias of booleanValue + +* `callableValue` - check if value is callable +```php +$func = function () {}; +assertThat($func, callableValue()); +``` +* `doubleValue` +```php +assertThat(3.14, doubleValue()); +``` + +* `floatValue` +```php +assertThat(3.14, floatValue()); +``` + +* `integerValue` +```php +assertThat(1, integerValue()); +``` + +* `intValue` - alias of `integerValue` + +* `numericValue` - check if value is numeric +```php +assertThat("123", numericValue()); +``` + +* `objectValue` - check for object +```php +$obj = new stdClass; +assertThat($obj, objectValue()); +``` +* `anObject` +```php +assertThat($obj, anObject()); +``` + +* `resourceValue` - check resource type +```php +$fp = fopen("/tmp/foo", "w+"); +assertThat($fp, resourceValue()); +``` + +* `scalarValue` - check for scaler value +```php +assertThat(1, scalarValue()); +``` + +* `stringValue` +```php +assertThat("", stringValue()); +``` + +### XML + +* `hasXPath` - check xml with a xpath +```php +$xml = << + + 1 + + + 2 + + +XML; + +$doc = new DOMDocument; +$doc->loadXML($xml); +assertThat($doc, hasXPath("book", 2)); +``` + diff --git a/vendor/hamcrest/hamcrest-php/composer.json b/vendor/hamcrest/hamcrest-php/composer.json new file mode 100644 index 00000000..712ad965 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/composer.json @@ -0,0 +1,37 @@ +{ + "name": "hamcrest/hamcrest-php", + "type": "library", + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": ["test"], + "license": "BSD-3-Clause", + "authors": [ + ], + + "autoload": { + "classmap": ["hamcrest"] + }, + "autoload-dev": { + "classmap": ["tests", "generator"] + }, + + "require": { + "php": "^5.3|^7.0|^8.0" + }, + + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" + }, + + "replace": { + "kodova/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "cordoval/hamcrest-php": "*" + }, + + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + } +} diff --git a/vendor/hamcrest/hamcrest-php/generator/FactoryCall.php b/vendor/hamcrest/hamcrest-php/generator/FactoryCall.php new file mode 100644 index 00000000..83965b2a --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/generator/FactoryCall.php @@ -0,0 +1,41 @@ +method = $method; + $this->name = $name; + } + + public function getMethod() + { + return $this->method; + } + + public function getName() + { + return $this->name; + } +} diff --git a/vendor/hamcrest/hamcrest-php/generator/FactoryClass.php b/vendor/hamcrest/hamcrest-php/generator/FactoryClass.php new file mode 100644 index 00000000..a09cb73c --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/generator/FactoryClass.php @@ -0,0 +1,71 @@ +file = $file; + $this->reflector = $class; + $this->extractFactoryMethods(); + } + + public function extractFactoryMethods() + { + $this->methods = array(); + foreach ($this->getPublicStaticMethods() as $method) { + if ($method->isFactory()) { + $this->methods[] = $method; + } + } + } + + public function getPublicStaticMethods() + { + $methods = array(); + foreach ($this->reflector->getMethods(ReflectionMethod::IS_STATIC) as $method) { + if ($method->isPublic() && $method->getDeclaringClass() == $this->reflector) { + $methods[] = new FactoryMethod($this, $method); + } + } + return $methods; + } + + public function getFile() + { + return $this->file; + } + + public function getName() + { + return $this->reflector->name; + } + + public function isFactory() + { + return !empty($this->methods); + } + + public function getMethods() + { + return $this->methods; + } +} diff --git a/vendor/hamcrest/hamcrest-php/generator/FactoryFile.php b/vendor/hamcrest/hamcrest-php/generator/FactoryFile.php new file mode 100644 index 00000000..dd6109b1 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/generator/FactoryFile.php @@ -0,0 +1,121 @@ +file = $file; + $this->indent = $indent; + } + + abstract public function addCall(FactoryCall $call); + + abstract public function build(); + + public function addFileHeader() + { + $this->code = ''; + $this->addPart('file_header'); + } + + public function addPart($name) + { + $this->addCode($this->readPart($name)); + } + + public function addCode($code) + { + $this->code .= $code; + } + + public function readPart($name) + { + return file_get_contents(__DIR__ . "/parts/$name.txt"); + } + + public function generateFactoryCall(FactoryCall $call) + { + $method = $call->getMethod(); + $code = $method->getComment($this->indent) . "\n"; + $code .= $this->generateDeclaration($call->getName(), $method); + $code .= $this->generateCall($method); + $code .= $this->generateClosing(); + return $code; + } + + public function generateDeclaration($name, FactoryMethod $method) + { + $code = $this->indent . $this->getDeclarationModifiers() + . 'function ' . $name . '(' + . $this->generateDeclarationArguments($method) + . ')' . "\n" . $this->indent . '{' . "\n"; + return $code; + } + + public function getDeclarationModifiers() + { + return ''; + } + + public function generateDeclarationArguments(FactoryMethod $method) + { + if ($method->acceptsVariableArguments()) { + return '/* args... */'; + } else { + return $method->getParameterDeclarations(); + } + } + + public function generateImport(FactoryMethod $method) + { + return $this->indent . self::INDENT . "require_once '" . $method->getClass()->getFile() . "';" . "\n"; + } + + public function generateCall(FactoryMethod $method) + { + $code = ''; + if ($method->acceptsVariableArguments()) { + $code .= $this->indent . self::INDENT . '$args = func_get_args();' . "\n"; + } + + $code .= $this->indent . self::INDENT . 'return '; + if ($method->acceptsVariableArguments()) { + $code .= 'call_user_func_array(array(\'' + . '\\' . $method->getClassName() . '\', \'' + . $method->getName() . '\'), $args);' . "\n"; + } else { + $code .= '\\' . $method->getClassName() . '::' + . $method->getName() . '(' + . $method->getParameterInvocations() . ');' . "\n"; + } + + return $code; + } + + public function generateClosing() + { + return $this->indent . '}' . "\n"; + } + + public function write() + { + file_put_contents($this->file, $this->code); + } +} diff --git a/vendor/hamcrest/hamcrest-php/generator/FactoryGenerator.php b/vendor/hamcrest/hamcrest-php/generator/FactoryGenerator.php new file mode 100644 index 00000000..242875a0 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/generator/FactoryGenerator.php @@ -0,0 +1,124 @@ +path = $path; + $this->factoryFiles = array(); + } + + public function addFactoryFile(FactoryFile $factoryFile) + { + $this->factoryFiles[] = $factoryFile; + } + + public function generate() + { + $classes = $this->getClassesWithFactoryMethods(); + foreach ($classes as $class) { + foreach ($class->getMethods() as $method) { + foreach ($method->getCalls() as $call) { + foreach ($this->factoryFiles as $file) { + $file->addCall($call); + } + } + } + } + } + + public function write() + { + foreach ($this->factoryFiles as $file) { + $file->build(); + $file->write(); + } + } + + public function getClassesWithFactoryMethods() + { + $classes = array(); + $files = $this->getSortedFiles(); + foreach ($files as $file) { + $class = $this->getFactoryClass($file); + if ($class !== null) { + $classes[] = $class; + } + } + + return $classes; + } + + public function getSortedFiles() + { + $iter = $this->getFileIterator(); + $files = array(); + foreach ($iter as $file) { + $files[] = $file; + } + sort($files, SORT_STRING); + + return $files; + } + + private function getFileIterator() + { + $factoryClass = class_exists('File_Iterator_Factory') ? 'File_Iterator_Factory' : 'SebastianBergmann\FileIterator\Factory'; + + $factory = new $factoryClass(); + + return $factory->getFileIterator($this->path, '.php'); + } + + public function getFactoryClass($file) + { + $name = $this->getFactoryClassName($file); + if ($name !== null) { + require_once $file; + + if (class_exists($name)) { + $class = new FactoryClass(substr($file, strpos($file, 'Hamcrest/')), new ReflectionClass($name)); + if ($class->isFactory()) { + return $class; + } + } + } + + return null; + } + + public function getFactoryClassName($file) + { + $content = file_get_contents($file); + if (preg_match('/namespace\s+(.+);/', $content, $namespace) + && preg_match('/\n\s*class\s+(\w+)\s+extends\b/', $content, $className) + && preg_match('/@factory\b/', $content) + ) { + return $namespace[1] . '\\' . $className[1]; + } + + return null; + } +} diff --git a/vendor/hamcrest/hamcrest-php/generator/FactoryMethod.php b/vendor/hamcrest/hamcrest-php/generator/FactoryMethod.php new file mode 100644 index 00000000..8a05371b --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/generator/FactoryMethod.php @@ -0,0 +1,231 @@ +class = $class; + $this->reflector = $reflector; + $this->extractCommentWithoutLeadingShashesAndStars(); + $this->extractFactoryNamesFromComment(); + $this->extractParameters(); + } + + public function extractCommentWithoutLeadingShashesAndStars() + { + $this->comment = explode("\n", $this->reflector->getDocComment()); + foreach ($this->comment as &$line) { + $line = preg_replace('#^\s*(/\\*+|\\*+/|\\*)\s?#', '', $line); + } + $this->trimLeadingBlankLinesFromComment(); + $this->trimTrailingBlankLinesFromComment(); + } + + public function trimLeadingBlankLinesFromComment() + { + while (count($this->comment) > 0) { + $line = array_shift($this->comment); + if (trim($line) != '') { + array_unshift($this->comment, $line); + break; + } + } + } + + public function trimTrailingBlankLinesFromComment() + { + while (count($this->comment) > 0) { + $line = array_pop($this->comment); + if (trim($line) != '') { + array_push($this->comment, $line); + break; + } + } + } + + public function extractFactoryNamesFromComment() + { + $this->calls = array(); + for ($i = 0; $i < count($this->comment); $i++) { + if ($this->extractFactoryNamesFromLine($this->comment[$i])) { + unset($this->comment[$i]); + } + } + $this->trimTrailingBlankLinesFromComment(); + } + + public function extractFactoryNamesFromLine($line) + { + if (preg_match('/^\s*@factory(\s+(.+))?$/', $line, $match)) { + $this->createCalls( + $this->extractFactoryNamesFromAnnotation( + isset($match[2]) ? trim($match[2]) : null + ) + ); + return true; + } + return false; + } + + public function extractFactoryNamesFromAnnotation($value) + { + $primaryName = $this->reflector->getName(); + if (empty($value)) { + return array($primaryName); + } + preg_match_all('/(\.{3}|-|[a-zA-Z_][a-zA-Z_0-9]*)/', $value, $match); + $names = $match[0]; + if (in_array('...', $names)) { + $this->isVarArgs = true; + } + if (!in_array('-', $names) && !in_array($primaryName, $names)) { + array_unshift($names, $primaryName); + } + return $names; + } + + public function createCalls(array $names) + { + $names = array_unique($names); + foreach ($names as $name) { + if ($name != '-' && $name != '...') { + $this->calls[] = new FactoryCall($this, $name); + } + } + } + + public function extractParameters() + { + $this->parameters = array(); + if (!$this->isVarArgs) { + foreach ($this->reflector->getParameters() as $parameter) { + $this->parameters[] = new FactoryParameter($this, $parameter); + } + } + } + + public function getParameterDeclarations() + { + if ($this->isVarArgs || !$this->hasParameters()) { + return ''; + } + $params = array(); + foreach ($this->parameters as /** @var $parameter FactoryParameter */ + $parameter) { + $params[] = $parameter->getDeclaration(); + } + return implode(', ', $params); + } + + public function getParameterInvocations() + { + if ($this->isVarArgs) { + return ''; + } + $params = array(); + foreach ($this->parameters as $parameter) { + $params[] = $parameter->getInvocation(); + } + return implode(', ', $params); + } + + + public function getClass() + { + return $this->class; + } + + public function getClassName() + { + return $this->class->getName(); + } + + public function getName() + { + return $this->reflector->name; + } + + public function isFactory() + { + return count($this->calls) > 0; + } + + public function getCalls() + { + return $this->calls; + } + + public function acceptsVariableArguments() + { + return $this->isVarArgs; + } + + public function hasParameters() + { + return !empty($this->parameters); + } + + public function getParameters() + { + return $this->parameters; + } + + public function getFullName() + { + return $this->getClassName() . '::' . $this->getName(); + } + + public function getCommentText() + { + return implode("\n", $this->comment); + } + + public function getComment($indent = '') + { + $comment = $indent . '/**'; + foreach ($this->comment as $line) { + $comment .= "\n" . rtrim($indent . ' * ' . $line); + } + $comment .= "\n" . $indent . ' */'; + return $comment; + } +} diff --git a/vendor/hamcrest/hamcrest-php/generator/FactoryParameter.php b/vendor/hamcrest/hamcrest-php/generator/FactoryParameter.php new file mode 100644 index 00000000..82b707ac --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/generator/FactoryParameter.php @@ -0,0 +1,131 @@ +method = $method; + $this->reflector = $reflector; + } + + /** + * Compute the declaration code. + * + * @return string + */ + public function getDeclaration() + { + $code = $this->getTypeCode() . $this->getInvocation(); + + if ($this->reflector->isOptional()) { + $default = $this->reflector->getDefaultValue(); + if (is_null($default)) { + $default = 'null'; + } elseif (is_bool($default)) { + $default = $default ? 'true' : 'false'; + } elseif (is_string($default)) { + $default = "'" . $default . "'"; + } elseif (is_numeric($default)) { + $default = strval($default); + } elseif (is_array($default)) { + $default = 'array()'; + } else { + echo 'Warning: unknown default type for ' . $this->getMethod()->getFullName() . "\n"; + var_dump($default); + $default = 'null'; + } + $code .= ' = ' . $default; + } + return $code; + } + + /** + * Compute the type code for the paramater. + * + * @return string + */ + private function getTypeCode() + { + // Handle PHP 5 separately + if (PHP_VERSION_ID < 70000) { + if ($this->reflector->isArray()) { + return 'array'; + } + + $class = $this->reflector->getClass(); + + return $class ? sprintf('\\%s ', $class->getName()) : ''; + } + + if (!$this->reflector->hasType()) { + return ''; + } + + $type = $this->reflector->getType(); + $name = self::getQualifiedName($type); + + // PHP 7.1+ supports nullable types via a leading question mark + return (PHP_VERSION_ID >= 70100 && $type->allowsNull()) ? sprintf('?%s ', $name) : sprintf('%s ', $name); + } + + /** + * Compute qualified name for the given type. + * + * This function knows how to prefix class names with a leading slash and + * also how to handle PHP 8's union types. + * + * @param ReflectionType $type + * + * @return string + */ + private static function getQualifiedName(ReflectionType $type) + { + // PHP 8 union types can be recursively processed + if ($type instanceof ReflectionUnionType) { + return implode('|', array_map(function (ReflectionType $type) { + // The "self::" call within a Closure is fine here because this + // code will only ever be executed on PHP 7.0+ + return self::getQualifiedName($type); + }, $type->getTypes())); + } + + // PHP 7.0 doesn't have named types, but 7.1+ does + $name = $type instanceof ReflectionNamedType ? $type->getName() : (string) $type; + + return $type->isBuiltin() ? $name : sprintf('\\%s', $name); + } + + /** + * Compute the invocation code. + * + * @return string + */ + public function getInvocation() + { + return sprintf('$%s', $this->reflector->getName()); + } + + /** + * Compute the method name. + * + * @return string + */ + public function getMethod() + { + return $this->method; + } +} diff --git a/vendor/hamcrest/hamcrest-php/generator/GlobalFunctionFile.php b/vendor/hamcrest/hamcrest-php/generator/GlobalFunctionFile.php new file mode 100644 index 00000000..ec8b1b39 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/generator/GlobalFunctionFile.php @@ -0,0 +1,42 @@ +functions = ''; + } + + public function addCall(FactoryCall $call) + { + $this->functions .= "\n" . $this->generateFactoryCall($call); + } + + public function build() + { + $this->addFileHeader(); + $this->addPart('functions_imports'); + $this->addPart('functions_header'); + $this->addCode($this->functions); + $this->addPart('functions_footer'); + } + + public function generateFactoryCall(FactoryCall $call) + { + $code = "if (!function_exists('{$call->getName()}')) {\n"; + $code.= parent::generateFactoryCall($call); + $code.= "}\n"; + + return $code; + } +} diff --git a/vendor/hamcrest/hamcrest-php/generator/StaticMethodFile.php b/vendor/hamcrest/hamcrest-php/generator/StaticMethodFile.php new file mode 100644 index 00000000..44cec02f --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/generator/StaticMethodFile.php @@ -0,0 +1,38 @@ +methods = ''; + } + + public function addCall(FactoryCall $call) + { + $this->methods .= PHP_EOL . $this->generateFactoryCall($call); + } + + public function getDeclarationModifiers() + { + return 'public static '; + } + + public function build() + { + $this->addFileHeader(); + $this->addPart('matchers_imports'); + $this->addPart('matchers_header'); + $this->addCode($this->methods); + $this->addPart('matchers_footer'); + } +} diff --git a/vendor/hamcrest/hamcrest-php/generator/parts/file_header.txt b/vendor/hamcrest/hamcrest-php/generator/parts/file_header.txt new file mode 100644 index 00000000..7b352e44 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/generator/parts/file_header.txt @@ -0,0 +1,7 @@ + + * //With an identifier + * assertThat("assertion identifier", $apple->flavour(), equalTo("tasty")); + * //Without an identifier + * assertThat($apple->flavour(), equalTo("tasty")); + * //Evaluating a boolean expression + * assertThat("some error", $a > $b); + * + */ + function assertThat() + { + $args = func_get_args(); + call_user_func_array( + array('Hamcrest\MatcherAssert', 'assertThat'), + $args + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/generator/parts/functions_imports.txt b/vendor/hamcrest/hamcrest-php/generator/parts/functions_imports.txt new file mode 100644 index 00000000..e69de29b diff --git a/vendor/hamcrest/hamcrest-php/generator/parts/matchers_footer.txt b/vendor/hamcrest/hamcrest-php/generator/parts/matchers_footer.txt new file mode 100644 index 00000000..5c34318c --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/generator/parts/matchers_footer.txt @@ -0,0 +1 @@ +} diff --git a/vendor/hamcrest/hamcrest-php/generator/parts/matchers_header.txt b/vendor/hamcrest/hamcrest-php/generator/parts/matchers_header.txt new file mode 100644 index 00000000..4f8bb2b7 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/generator/parts/matchers_header.txt @@ -0,0 +1,7 @@ + + +/** + * A series of static factories for all hamcrest matchers. + */ +class Matchers +{ diff --git a/vendor/hamcrest/hamcrest-php/generator/parts/matchers_imports.txt b/vendor/hamcrest/hamcrest-php/generator/parts/matchers_imports.txt new file mode 100644 index 00000000..7dd68495 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/generator/parts/matchers_imports.txt @@ -0,0 +1,2 @@ + +namespace Hamcrest; \ No newline at end of file diff --git a/vendor/hamcrest/hamcrest-php/generator/run.php b/vendor/hamcrest/hamcrest-php/generator/run.php new file mode 100644 index 00000000..924d752f --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/generator/run.php @@ -0,0 +1,37 @@ +addFactoryFile(new StaticMethodFile(STATIC_MATCHERS_FILE)); +$generator->addFactoryFile(new GlobalFunctionFile(GLOBAL_FUNCTIONS_FILE)); +$generator->generate(); +$generator->write(); diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest.php new file mode 100644 index 00000000..55a2dd8c --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest.php @@ -0,0 +1,882 @@ + + * //With an identifier + * assertThat("assertion identifier", $apple->flavour(), equalTo("tasty")); + * //Without an identifier + * assertThat($apple->flavour(), equalTo("tasty")); + * //Evaluating a boolean expression + * assertThat("some error", $a > $b); + * + */ + function assertThat() + { + $args = func_get_args(); + call_user_func_array( + array('Hamcrest\MatcherAssert', 'assertThat'), + $args + ); + } +} + +if (!function_exists('anArray')) { + /** + * Evaluates to true only if each $matcher[$i] is satisfied by $array[$i]. + */ + function anArray(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Arrays\IsArray', 'anArray'), $args); + } +} + +if (!function_exists('hasItemInArray')) { + /** + * Evaluates to true if any item in an array satisfies the given matcher. + * + * @param mixed $item as a {@link Hamcrest\Matcher} or a value. + * + * @return \Hamcrest\Arrays\IsArrayContaining + */ + function hasItemInArray($item) + { + return \Hamcrest\Arrays\IsArrayContaining::hasItemInArray($item); + } +} + +if (!function_exists('hasValue')) { + /** + * Evaluates to true if any item in an array satisfies the given matcher. + * + * @param mixed $item as a {@link Hamcrest\Matcher} or a value. + * + * @return \Hamcrest\Arrays\IsArrayContaining + */ + function hasValue($item) + { + return \Hamcrest\Arrays\IsArrayContaining::hasItemInArray($item); + } +} + +if (!function_exists('arrayContainingInAnyOrder')) { + /** + * An array with elements that match the given matchers. + */ + function arrayContainingInAnyOrder(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Arrays\IsArrayContainingInAnyOrder', 'arrayContainingInAnyOrder'), $args); + } +} + +if (!function_exists('containsInAnyOrder')) { + /** + * An array with elements that match the given matchers. + */ + function containsInAnyOrder(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Arrays\IsArrayContainingInAnyOrder', 'arrayContainingInAnyOrder'), $args); + } +} + +if (!function_exists('arrayContaining')) { + /** + * An array with elements that match the given matchers in the same order. + */ + function arrayContaining(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Arrays\IsArrayContainingInOrder', 'arrayContaining'), $args); + } +} + +if (!function_exists('contains')) { + /** + * An array with elements that match the given matchers in the same order. + */ + function contains(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Arrays\IsArrayContainingInOrder', 'arrayContaining'), $args); + } +} + +if (!function_exists('hasKeyInArray')) { + /** + * Evaluates to true if any key in an array matches the given matcher. + * + * @param mixed $key as a {@link Hamcrest\Matcher} or a value. + * + * @return \Hamcrest\Arrays\IsArrayContainingKey + */ + function hasKeyInArray($key) + { + return \Hamcrest\Arrays\IsArrayContainingKey::hasKeyInArray($key); + } +} + +if (!function_exists('hasKey')) { + /** + * Evaluates to true if any key in an array matches the given matcher. + * + * @param mixed $key as a {@link Hamcrest\Matcher} or a value. + * + * @return \Hamcrest\Arrays\IsArrayContainingKey + */ + function hasKey($key) + { + return \Hamcrest\Arrays\IsArrayContainingKey::hasKeyInArray($key); + } +} + +if (!function_exists('hasKeyValuePair')) { + /** + * Test if an array has both an key and value in parity with each other. + */ + function hasKeyValuePair($key, $value) + { + return \Hamcrest\Arrays\IsArrayContainingKeyValuePair::hasKeyValuePair($key, $value); + } +} + +if (!function_exists('hasEntry')) { + /** + * Test if an array has both an key and value in parity with each other. + */ + function hasEntry($key, $value) + { + return \Hamcrest\Arrays\IsArrayContainingKeyValuePair::hasKeyValuePair($key, $value); + } +} + +if (!function_exists('arrayWithSize')) { + /** + * Does array size satisfy a given matcher? + * + * @param \Hamcrest\Matcher|int $size as a {@link Hamcrest\Matcher} or a value. + * + * @return \Hamcrest\Arrays\IsArrayWithSize + */ + function arrayWithSize($size) + { + return \Hamcrest\Arrays\IsArrayWithSize::arrayWithSize($size); + } +} + +if (!function_exists('emptyArray')) { + /** + * Matches an empty array. + */ + function emptyArray() + { + return \Hamcrest\Arrays\IsArrayWithSize::emptyArray(); + } +} + +if (!function_exists('nonEmptyArray')) { + /** + * Matches an empty array. + */ + function nonEmptyArray() + { + return \Hamcrest\Arrays\IsArrayWithSize::nonEmptyArray(); + } +} + +if (!function_exists('emptyTraversable')) { + /** + * Returns true if traversable is empty. + */ + function emptyTraversable() + { + return \Hamcrest\Collection\IsEmptyTraversable::emptyTraversable(); + } +} + +if (!function_exists('nonEmptyTraversable')) { + /** + * Returns true if traversable is not empty. + */ + function nonEmptyTraversable() + { + return \Hamcrest\Collection\IsEmptyTraversable::nonEmptyTraversable(); + } +} + +if (!function_exists('traversableWithSize')) { + /** + * Does traversable size satisfy a given matcher? + */ + function traversableWithSize($size) + { + return \Hamcrest\Collection\IsTraversableWithSize::traversableWithSize($size); + } +} + +if (!function_exists('allOf')) { + /** + * Evaluates to true only if ALL of the passed in matchers evaluate to true. + */ + function allOf(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Core\AllOf', 'allOf'), $args); + } +} + +if (!function_exists('anyOf')) { + /** + * Evaluates to true if ANY of the passed in matchers evaluate to true. + */ + function anyOf(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Core\AnyOf', 'anyOf'), $args); + } +} + +if (!function_exists('noneOf')) { + /** + * Evaluates to false if ANY of the passed in matchers evaluate to true. + */ + function noneOf(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Core\AnyOf', 'noneOf'), $args); + } +} + +if (!function_exists('both')) { + /** + * This is useful for fluently combining matchers that must both pass. + * For example: + *
    +     *   assertThat($string, both(containsString("a"))->andAlso(containsString("b")));
    +     * 
    + */ + function both(\Hamcrest\Matcher $matcher) + { + return \Hamcrest\Core\CombinableMatcher::both($matcher); + } +} + +if (!function_exists('either')) { + /** + * This is useful for fluently combining matchers where either may pass, + * for example: + *
    +     *   assertThat($string, either(containsString("a"))->orElse(containsString("b")));
    +     * 
    + */ + function either(\Hamcrest\Matcher $matcher) + { + return \Hamcrest\Core\CombinableMatcher::either($matcher); + } +} + +if (!function_exists('describedAs')) { + /** + * Wraps an existing matcher and overrides the description when it fails. + */ + function describedAs(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Core\DescribedAs', 'describedAs'), $args); + } +} + +if (!function_exists('everyItem')) { + /** + * @param Matcher $itemMatcher + * A matcher to apply to every element in an array. + * + * @return \Hamcrest\Core\Every + * Evaluates to TRUE for a collection in which every item matches $itemMatcher + */ + function everyItem(\Hamcrest\Matcher $itemMatcher) + { + return \Hamcrest\Core\Every::everyItem($itemMatcher); + } +} + +if (!function_exists('hasToString')) { + /** + * Does array size satisfy a given matcher? + */ + function hasToString($matcher) + { + return \Hamcrest\Core\HasToString::hasToString($matcher); + } +} + +if (!function_exists('is')) { + /** + * Decorates another Matcher, retaining the behavior but allowing tests + * to be slightly more expressive. + * + * For example: assertThat($cheese, equalTo($smelly)) + * vs. assertThat($cheese, is(equalTo($smelly))) + */ + function is($value) + { + return \Hamcrest\Core\Is::is($value); + } +} + +if (!function_exists('anything')) { + /** + * This matcher always evaluates to true. + * + * @param string $description A meaningful string used when describing itself. + * + * @return \Hamcrest\Core\IsAnything + */ + function anything($description = 'ANYTHING') + { + return \Hamcrest\Core\IsAnything::anything($description); + } +} + +if (!function_exists('hasItem')) { + /** + * Test if the value is an array containing this matcher. + * + * Example: + *
    +     * assertThat(array('a', 'b'), hasItem(equalTo('b')));
    +     * //Convenience defaults to equalTo()
    +     * assertThat(array('a', 'b'), hasItem('b'));
    +     * 
    + */ + function hasItem(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Core\IsCollectionContaining', 'hasItem'), $args); + } +} + +if (!function_exists('hasItems')) { + /** + * Test if the value is an array containing elements that match all of these + * matchers. + * + * Example: + *
    +     * assertThat(array('a', 'b', 'c'), hasItems(equalTo('a'), equalTo('b')));
    +     * 
    + */ + function hasItems(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Core\IsCollectionContaining', 'hasItems'), $args); + } +} + +if (!function_exists('equalTo')) { + /** + * Is the value equal to another value, as tested by the use of the "==" + * comparison operator? + */ + function equalTo($item) + { + return \Hamcrest\Core\IsEqual::equalTo($item); + } +} + +if (!function_exists('identicalTo')) { + /** + * Tests of the value is identical to $value as tested by the "===" operator. + */ + function identicalTo($value) + { + return \Hamcrest\Core\IsIdentical::identicalTo($value); + } +} + +if (!function_exists('anInstanceOf')) { + /** + * Is the value an instance of a particular type? + * This version assumes no relationship between the required type and + * the signature of the method that sets it up, for example in + * assertThat($anObject, anInstanceOf('Thing')); + */ + function anInstanceOf($theClass) + { + return \Hamcrest\Core\IsInstanceOf::anInstanceOf($theClass); + } +} + +if (!function_exists('any')) { + /** + * Is the value an instance of a particular type? + * This version assumes no relationship between the required type and + * the signature of the method that sets it up, for example in + * assertThat($anObject, anInstanceOf('Thing')); + */ + function any($theClass) + { + return \Hamcrest\Core\IsInstanceOf::anInstanceOf($theClass); + } +} + +if (!function_exists('not')) { + /** + * Matches if value does not match $value. + */ + function not($value) + { + return \Hamcrest\Core\IsNot::not($value); + } +} + +if (!function_exists('nullValue')) { + /** + * Matches if value is null. + */ + function nullValue() + { + return \Hamcrest\Core\IsNull::nullValue(); + } +} + +if (!function_exists('notNullValue')) { + /** + * Matches if value is not null. + */ + function notNullValue() + { + return \Hamcrest\Core\IsNull::notNullValue(); + } +} + +if (!function_exists('sameInstance')) { + /** + * Creates a new instance of IsSame. + * + * @param mixed $object + * The predicate evaluates to true only when the argument is + * this object. + * + * @return \Hamcrest\Core\IsSame + */ + function sameInstance($object) + { + return \Hamcrest\Core\IsSame::sameInstance($object); + } +} + +if (!function_exists('typeOf')) { + /** + * Is the value a particular built-in type? + */ + function typeOf($theType) + { + return \Hamcrest\Core\IsTypeOf::typeOf($theType); + } +} + +if (!function_exists('set')) { + /** + * Matches if value (class, object, or array) has named $property. + */ + function set($property) + { + return \Hamcrest\Core\Set::set($property); + } +} + +if (!function_exists('notSet')) { + /** + * Matches if value (class, object, or array) does not have named $property. + */ + function notSet($property) + { + return \Hamcrest\Core\Set::notSet($property); + } +} + +if (!function_exists('closeTo')) { + /** + * Matches if value is a number equal to $value within some range of + * acceptable error $delta. + */ + function closeTo($value, $delta) + { + return \Hamcrest\Number\IsCloseTo::closeTo($value, $delta); + } +} + +if (!function_exists('comparesEqualTo')) { + /** + * The value is not > $value, nor < $value. + */ + function comparesEqualTo($value) + { + return \Hamcrest\Number\OrderingComparison::comparesEqualTo($value); + } +} + +if (!function_exists('greaterThan')) { + /** + * The value is > $value. + */ + function greaterThan($value) + { + return \Hamcrest\Number\OrderingComparison::greaterThan($value); + } +} + +if (!function_exists('greaterThanOrEqualTo')) { + /** + * The value is >= $value. + */ + function greaterThanOrEqualTo($value) + { + return \Hamcrest\Number\OrderingComparison::greaterThanOrEqualTo($value); + } +} + +if (!function_exists('atLeast')) { + /** + * The value is >= $value. + */ + function atLeast($value) + { + return \Hamcrest\Number\OrderingComparison::greaterThanOrEqualTo($value); + } +} + +if (!function_exists('lessThan')) { + /** + * The value is < $value. + */ + function lessThan($value) + { + return \Hamcrest\Number\OrderingComparison::lessThan($value); + } +} + +if (!function_exists('lessThanOrEqualTo')) { + /** + * The value is <= $value. + */ + function lessThanOrEqualTo($value) + { + return \Hamcrest\Number\OrderingComparison::lessThanOrEqualTo($value); + } +} + +if (!function_exists('atMost')) { + /** + * The value is <= $value. + */ + function atMost($value) + { + return \Hamcrest\Number\OrderingComparison::lessThanOrEqualTo($value); + } +} + +if (!function_exists('isEmptyString')) { + /** + * Matches if value is a zero-length string. + */ + function isEmptyString() + { + return \Hamcrest\Text\IsEmptyString::isEmptyString(); + } +} + +if (!function_exists('emptyString')) { + /** + * Matches if value is a zero-length string. + */ + function emptyString() + { + return \Hamcrest\Text\IsEmptyString::isEmptyString(); + } +} + +if (!function_exists('isEmptyOrNullString')) { + /** + * Matches if value is null or a zero-length string. + */ + function isEmptyOrNullString() + { + return \Hamcrest\Text\IsEmptyString::isEmptyOrNullString(); + } +} + +if (!function_exists('nullOrEmptyString')) { + /** + * Matches if value is null or a zero-length string. + */ + function nullOrEmptyString() + { + return \Hamcrest\Text\IsEmptyString::isEmptyOrNullString(); + } +} + +if (!function_exists('isNonEmptyString')) { + /** + * Matches if value is a non-zero-length string. + */ + function isNonEmptyString() + { + return \Hamcrest\Text\IsEmptyString::isNonEmptyString(); + } +} + +if (!function_exists('nonEmptyString')) { + /** + * Matches if value is a non-zero-length string. + */ + function nonEmptyString() + { + return \Hamcrest\Text\IsEmptyString::isNonEmptyString(); + } +} + +if (!function_exists('equalToIgnoringCase')) { + /** + * Matches if value is a string equal to $string, regardless of the case. + */ + function equalToIgnoringCase($string) + { + return \Hamcrest\Text\IsEqualIgnoringCase::equalToIgnoringCase($string); + } +} + +if (!function_exists('equalToIgnoringWhiteSpace')) { + /** + * Matches if value is a string equal to $string, regardless of whitespace. + */ + function equalToIgnoringWhiteSpace($string) + { + return \Hamcrest\Text\IsEqualIgnoringWhiteSpace::equalToIgnoringWhiteSpace($string); + } +} + +if (!function_exists('matchesPattern')) { + /** + * Matches if value is a string that matches regular expression $pattern. + */ + function matchesPattern($pattern) + { + return \Hamcrest\Text\MatchesPattern::matchesPattern($pattern); + } +} + +if (!function_exists('containsString')) { + /** + * Matches if value is a string that contains $substring. + */ + function containsString($substring) + { + return \Hamcrest\Text\StringContains::containsString($substring); + } +} + +if (!function_exists('containsStringIgnoringCase')) { + /** + * Matches if value is a string that contains $substring regardless of the case. + */ + function containsStringIgnoringCase($substring) + { + return \Hamcrest\Text\StringContainsIgnoringCase::containsStringIgnoringCase($substring); + } +} + +if (!function_exists('stringContainsInOrder')) { + /** + * Matches if value contains $substrings in a constrained order. + */ + function stringContainsInOrder(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Text\StringContainsInOrder', 'stringContainsInOrder'), $args); + } +} + +if (!function_exists('endsWith')) { + /** + * Matches if value is a string that ends with $substring. + */ + function endsWith($substring) + { + return \Hamcrest\Text\StringEndsWith::endsWith($substring); + } +} + +if (!function_exists('startsWith')) { + /** + * Matches if value is a string that starts with $substring. + */ + function startsWith($substring) + { + return \Hamcrest\Text\StringStartsWith::startsWith($substring); + } +} + +if (!function_exists('arrayValue')) { + /** + * Is the value an array? + */ + function arrayValue() + { + return \Hamcrest\Type\IsArray::arrayValue(); + } +} + +if (!function_exists('booleanValue')) { + /** + * Is the value a boolean? + */ + function booleanValue() + { + return \Hamcrest\Type\IsBoolean::booleanValue(); + } +} + +if (!function_exists('boolValue')) { + /** + * Is the value a boolean? + */ + function boolValue() + { + return \Hamcrest\Type\IsBoolean::booleanValue(); + } +} + +if (!function_exists('callableValue')) { + /** + * Is the value callable? + */ + function callableValue() + { + return \Hamcrest\Type\IsCallable::callableValue(); + } +} + +if (!function_exists('doubleValue')) { + /** + * Is the value a float/double? + */ + function doubleValue() + { + return \Hamcrest\Type\IsDouble::doubleValue(); + } +} + +if (!function_exists('floatValue')) { + /** + * Is the value a float/double? + */ + function floatValue() + { + return \Hamcrest\Type\IsDouble::doubleValue(); + } +} + +if (!function_exists('integerValue')) { + /** + * Is the value an integer? + */ + function integerValue() + { + return \Hamcrest\Type\IsInteger::integerValue(); + } +} + +if (!function_exists('intValue')) { + /** + * Is the value an integer? + */ + function intValue() + { + return \Hamcrest\Type\IsInteger::integerValue(); + } +} + +if (!function_exists('numericValue')) { + /** + * Is the value a numeric? + */ + function numericValue() + { + return \Hamcrest\Type\IsNumeric::numericValue(); + } +} + +if (!function_exists('objectValue')) { + /** + * Is the value an object? + */ + function objectValue() + { + return \Hamcrest\Type\IsObject::objectValue(); + } +} + +if (!function_exists('anObject')) { + /** + * Is the value an object? + */ + function anObject() + { + return \Hamcrest\Type\IsObject::objectValue(); + } +} + +if (!function_exists('resourceValue')) { + /** + * Is the value a resource? + */ + function resourceValue() + { + return \Hamcrest\Type\IsResource::resourceValue(); + } +} + +if (!function_exists('scalarValue')) { + /** + * Is the value a scalar (boolean, integer, double, or string)? + */ + function scalarValue() + { + return \Hamcrest\Type\IsScalar::scalarValue(); + } +} + +if (!function_exists('stringValue')) { + /** + * Is the value a string? + */ + function stringValue() + { + return \Hamcrest\Type\IsString::stringValue(); + } +} + +if (!function_exists('hasXPath')) { + /** + * Wraps $matcher with {@link Hamcrest\Core\IsEqual) + * if it's not a matcher and the XPath in count() + * if it's an integer. + */ + function hasXPath($xpath, $matcher = null) + { + return \Hamcrest\Xml\HasXPath::hasXPath($xpath, $matcher); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArray.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArray.php new file mode 100644 index 00000000..9ea56970 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArray.php @@ -0,0 +1,118 @@ +_elementMatchers = $elementMatchers; + } + + protected function matchesSafely($array) + { + if (array_keys($array) != array_keys($this->_elementMatchers)) { + return false; + } + + /** @var $matcher \Hamcrest\Matcher */ + foreach ($this->_elementMatchers as $k => $matcher) { + if (!$matcher->matches($array[$k])) { + return false; + } + } + + return true; + } + + protected function describeMismatchSafely($actual, Description $mismatchDescription) + { + if (count($actual) != count($this->_elementMatchers)) { + $mismatchDescription->appendText('array length was ' . count($actual)); + + return; + } elseif (array_keys($actual) != array_keys($this->_elementMatchers)) { + $mismatchDescription->appendText('array keys were ') + ->appendValueList( + $this->descriptionStart(), + $this->descriptionSeparator(), + $this->descriptionEnd(), + array_keys($actual) + ) + ; + + return; + } + + /** @var $matcher \Hamcrest\Matcher */ + foreach ($this->_elementMatchers as $k => $matcher) { + if (!$matcher->matches($actual[$k])) { + $mismatchDescription->appendText('element ')->appendValue($k) + ->appendText(' was ')->appendValue($actual[$k]); + + return; + } + } + } + + public function describeTo(Description $description) + { + $description->appendList( + $this->descriptionStart(), + $this->descriptionSeparator(), + $this->descriptionEnd(), + $this->_elementMatchers + ); + } + + /** + * Evaluates to true only if each $matcher[$i] is satisfied by $array[$i]. + * + * @factory ... + */ + public static function anArray(/* args... */) + { + $args = func_get_args(); + + return new self(Util::createMatcherArray($args)); + } + + // -- Protected Methods + + protected function descriptionStart() + { + return '['; + } + + protected function descriptionSeparator() + { + return ', '; + } + + protected function descriptionEnd() + { + return ']'; + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContaining.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContaining.php new file mode 100644 index 00000000..0e4a1eda --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContaining.php @@ -0,0 +1,63 @@ +_elementMatcher = $elementMatcher; + } + + protected function matchesSafely($array) + { + foreach ($array as $element) { + if ($this->_elementMatcher->matches($element)) { + return true; + } + } + + return false; + } + + protected function describeMismatchSafely($array, Description $mismatchDescription) + { + $mismatchDescription->appendText('was ')->appendValue($array); + } + + public function describeTo(Description $description) + { + $description + ->appendText('an array containing ') + ->appendDescriptionOf($this->_elementMatcher) + ; + } + + /** + * Evaluates to true if any item in an array satisfies the given matcher. + * + * @param mixed $item as a {@link Hamcrest\Matcher} or a value. + * + * @return \Hamcrest\Arrays\IsArrayContaining + * @factory hasValue + */ + public static function hasItemInArray($item) + { + return new self(Util::wrapValueWithIsEqual($item)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingInAnyOrder.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingInAnyOrder.php new file mode 100644 index 00000000..9009026b --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingInAnyOrder.php @@ -0,0 +1,59 @@ +_elementMatchers = $elementMatchers; + } + + protected function matchesSafelyWithDiagnosticDescription($array, Description $mismatchDescription) + { + $matching = new MatchingOnce($this->_elementMatchers, $mismatchDescription); + + foreach ($array as $element) { + if (!$matching->matches($element)) { + return false; + } + } + + return $matching->isFinished($array); + } + + public function describeTo(Description $description) + { + $description->appendList('[', ', ', ']', $this->_elementMatchers) + ->appendText(' in any order') + ; + } + + /** + * An array with elements that match the given matchers. + * + * @factory containsInAnyOrder ... + */ + public static function arrayContainingInAnyOrder(/* args... */) + { + $args = func_get_args(); + + return new self(Util::createMatcherArray($args)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingInOrder.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingInOrder.php new file mode 100644 index 00000000..61157404 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingInOrder.php @@ -0,0 +1,57 @@ +_elementMatchers = $elementMatchers; + } + + protected function matchesSafelyWithDiagnosticDescription($array, Description $mismatchDescription) + { + $series = new SeriesMatchingOnce($this->_elementMatchers, $mismatchDescription); + + foreach ($array as $element) { + if (!$series->matches($element)) { + return false; + } + } + + return $series->isFinished(); + } + + public function describeTo(Description $description) + { + $description->appendList('[', ', ', ']', $this->_elementMatchers); + } + + /** + * An array with elements that match the given matchers in the same order. + * + * @factory contains ... + */ + public static function arrayContaining(/* args... */) + { + $args = func_get_args(); + + return new self(Util::createMatcherArray($args)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingKey.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingKey.php new file mode 100644 index 00000000..523477e7 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingKey.php @@ -0,0 +1,75 @@ +_keyMatcher = $keyMatcher; + } + + protected function matchesSafely($array) + { + foreach ($array as $key => $element) { + if ($this->_keyMatcher->matches($key)) { + return true; + } + } + + return false; + } + + protected function describeMismatchSafely($array, Description $mismatchDescription) + { + //Not using appendValueList() so that keys can be shown + $mismatchDescription->appendText('array was ') + ->appendText('[') + ; + $loop = false; + foreach ($array as $key => $value) { + if ($loop) { + $mismatchDescription->appendText(', '); + } + $mismatchDescription->appendValue($key)->appendText(' => ')->appendValue($value); + $loop = true; + } + $mismatchDescription->appendText(']'); + } + + public function describeTo(Description $description) + { + $description + ->appendText('array with key ') + ->appendDescriptionOf($this->_keyMatcher) + ; + } + + /** + * Evaluates to true if any key in an array matches the given matcher. + * + * @param mixed $key as a {@link Hamcrest\Matcher} or a value. + * + * @return \Hamcrest\Arrays\IsArrayContainingKey + * @factory hasKey + */ + public static function hasKeyInArray($key) + { + return new self(Util::wrapValueWithIsEqual($key)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingKeyValuePair.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingKeyValuePair.php new file mode 100644 index 00000000..9ac3eba8 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingKeyValuePair.php @@ -0,0 +1,80 @@ +_keyMatcher = $keyMatcher; + $this->_valueMatcher = $valueMatcher; + } + + protected function matchesSafely($array) + { + foreach ($array as $key => $value) { + if ($this->_keyMatcher->matches($key) && $this->_valueMatcher->matches($value)) { + return true; + } + } + + return false; + } + + protected function describeMismatchSafely($array, Description $mismatchDescription) + { + //Not using appendValueList() so that keys can be shown + $mismatchDescription->appendText('array was ') + ->appendText('[') + ; + $loop = false; + foreach ($array as $key => $value) { + if ($loop) { + $mismatchDescription->appendText(', '); + } + $mismatchDescription->appendValue($key)->appendText(' => ')->appendValue($value); + $loop = true; + } + $mismatchDescription->appendText(']'); + } + + public function describeTo(Description $description) + { + $description->appendText('array containing [') + ->appendDescriptionOf($this->_keyMatcher) + ->appendText(' => ') + ->appendDescriptionOf($this->_valueMatcher) + ->appendText(']') + ; + } + + /** + * Test if an array has both an key and value in parity with each other. + * + * @factory hasEntry + */ + public static function hasKeyValuePair($key, $value) + { + return new self( + Util::wrapValueWithIsEqual($key), + Util::wrapValueWithIsEqual($value) + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayWithSize.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayWithSize.php new file mode 100644 index 00000000..074375ce --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayWithSize.php @@ -0,0 +1,73 @@ +_elementMatchers = $elementMatchers; + $this->_mismatchDescription = $mismatchDescription; + } + + public function matches($item) + { + return $this->_isNotSurplus($item) && $this->_isMatched($item); + } + + public function isFinished($items) + { + if (empty($this->_elementMatchers)) { + return true; + } + + $this->_mismatchDescription + ->appendText('No item matches: ')->appendList('', ', ', '', $this->_elementMatchers) + ->appendText(' in ')->appendValueList('[', ', ', ']', $items) + ; + + return false; + } + + // -- Private Methods + + private function _isNotSurplus($item) + { + if (empty($this->_elementMatchers)) { + $this->_mismatchDescription->appendText('Not matched: ')->appendValue($item); + + return false; + } + + return true; + } + + private function _isMatched($item) + { + /** @var $matcher \Hamcrest\Matcher */ + foreach ($this->_elementMatchers as $i => $matcher) { + if ($matcher->matches($item)) { + unset($this->_elementMatchers[$i]); + + return true; + } + } + + $this->_mismatchDescription->appendText('Not matched: ')->appendValue($item); + + return false; + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/SeriesMatchingOnce.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/SeriesMatchingOnce.php new file mode 100644 index 00000000..12a912d8 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/SeriesMatchingOnce.php @@ -0,0 +1,75 @@ +_elementMatchers = $elementMatchers; + $this->_keys = array_keys($elementMatchers); + $this->_mismatchDescription = $mismatchDescription; + } + + public function matches($item) + { + return $this->_isNotSurplus($item) && $this->_isMatched($item); + } + + public function isFinished() + { + if (!empty($this->_elementMatchers)) { + $nextMatcher = current($this->_elementMatchers); + $this->_mismatchDescription->appendText('No item matched: ')->appendDescriptionOf($nextMatcher); + + return false; + } + + return true; + } + + // -- Private Methods + + private function _isNotSurplus($item) + { + if (empty($this->_elementMatchers)) { + $this->_mismatchDescription->appendText('Not matched: ')->appendValue($item); + + return false; + } + + return true; + } + + private function _isMatched($item) + { + $this->_nextMatchKey = array_shift($this->_keys); + $nextMatcher = array_shift($this->_elementMatchers); + + if (!$nextMatcher->matches($item)) { + $this->_describeMismatch($nextMatcher, $item); + + return false; + } + + return true; + } + + private function _describeMismatch(Matcher $matcher, $item) + { + $this->_mismatchDescription->appendText('item with key ' . $this->_nextMatchKey . ': '); + $matcher->describeMismatch($item, $this->_mismatchDescription); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/AssertionError.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/AssertionError.php new file mode 100644 index 00000000..3a2a0e7c --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/AssertionError.php @@ -0,0 +1,10 @@ +append($text); + + return $this; + } + + public function appendDescriptionOf(SelfDescribing $value) + { + $value->describeTo($this); + + return $this; + } + + public function appendValue($value) + { + if (is_null($value)) { + $this->append('null'); + } elseif (is_string($value)) { + $this->_toPhpSyntax($value); + } elseif (is_float($value)) { + $this->append('<'); + $this->append($value); + $this->append('F>'); + } elseif (is_bool($value)) { + $this->append('<'); + $this->append($value ? 'true' : 'false'); + $this->append('>'); + } elseif (is_array($value) || $value instanceof \Iterator || $value instanceof \IteratorAggregate) { + $this->appendValueList('[', ', ', ']', $value); + } elseif (is_object($value) && !method_exists($value, '__toString')) { + $this->append('<'); + $this->append(get_class($value)); + $this->append('>'); + } else { + $this->append('<'); + $this->append($value); + $this->append('>'); + } + + return $this; + } + + public function appendValueList($start, $separator, $end, $values) + { + $list = array(); + foreach ($values as $v) { + $list[] = new SelfDescribingValue($v); + } + + $this->appendList($start, $separator, $end, $list); + + return $this; + } + + public function appendList($start, $separator, $end, $values) + { + $this->append($start); + + $separate = false; + + foreach ($values as $value) { + /*if (!($value instanceof Hamcrest\SelfDescribing)) { + $value = new Hamcrest\Internal\SelfDescribingValue($value); + }*/ + + if ($separate) { + $this->append($separator); + } + + $this->appendDescriptionOf($value); + + $separate = true; + } + + $this->append($end); + + return $this; + } + + // -- Protected Methods + + /** + * Append the String $str to the description. + */ + abstract protected function append($str); + + // -- Private Methods + + private function _toPhpSyntax($value) + { + $str = '"'; + for ($i = 0, $len = strlen($value); $i < $len; ++$i) { + switch ($value[$i]) { + case '"': + $str .= '\\"'; + break; + + case "\t": + $str .= '\\t'; + break; + + case "\r": + $str .= '\\r'; + break; + + case "\n": + $str .= '\\n'; + break; + + default: + $str .= $value[$i]; + } + } + $str .= '"'; + $this->append($str); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/BaseMatcher.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/BaseMatcher.php new file mode 100644 index 00000000..06055698 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/BaseMatcher.php @@ -0,0 +1,30 @@ +appendText('was ')->appendValue($item); + } + + public function __toString() + { + return StringDescription::toString($this); + } + + public function __invoke() + { + return call_user_func_array(array($this, 'matches'), func_get_args()); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Collection/IsEmptyTraversable.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Collection/IsEmptyTraversable.php new file mode 100644 index 00000000..8ab58ea5 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Collection/IsEmptyTraversable.php @@ -0,0 +1,71 @@ +_empty = $empty; + } + + public function matches($item) + { + if (!$item instanceof \Traversable) { + return false; + } + + foreach ($item as $value) { + return !$this->_empty; + } + + return $this->_empty; + } + + public function describeTo(Description $description) + { + $description->appendText($this->_empty ? 'an empty traversable' : 'a non-empty traversable'); + } + + /** + * Returns true if traversable is empty. + * + * @factory + */ + public static function emptyTraversable() + { + if (!self::$_INSTANCE) { + self::$_INSTANCE = new self; + } + + return self::$_INSTANCE; + } + + /** + * Returns true if traversable is not empty. + * + * @factory + */ + public static function nonEmptyTraversable() + { + if (!self::$_NOT_INSTANCE) { + self::$_NOT_INSTANCE = new self(false); + } + + return self::$_NOT_INSTANCE; + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Collection/IsTraversableWithSize.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Collection/IsTraversableWithSize.php new file mode 100644 index 00000000..c95edc5c --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Collection/IsTraversableWithSize.php @@ -0,0 +1,47 @@ +false. + */ +class AllOf extends DiagnosingMatcher +{ + + private $_matchers; + + public function __construct(array $matchers) + { + Util::checkAllAreMatchers($matchers); + + $this->_matchers = $matchers; + } + + public function matchesWithDiagnosticDescription($item, Description $mismatchDescription) + { + /** @var $matcher \Hamcrest\Matcher */ + foreach ($this->_matchers as $matcher) { + if (!$matcher->matches($item)) { + $mismatchDescription->appendDescriptionOf($matcher)->appendText(' '); + $matcher->describeMismatch($item, $mismatchDescription); + + return false; + } + } + + return true; + } + + public function describeTo(Description $description) + { + $description->appendList('(', ' and ', ')', $this->_matchers); + } + + /** + * Evaluates to true only if ALL of the passed in matchers evaluate to true. + * + * @factory ... + */ + public static function allOf(/* args... */) + { + $args = func_get_args(); + + return new self(Util::createMatcherArray($args)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/AnyOf.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/AnyOf.php new file mode 100644 index 00000000..4504279f --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/AnyOf.php @@ -0,0 +1,58 @@ +true. + */ +class AnyOf extends ShortcutCombination +{ + + public function __construct(array $matchers) + { + parent::__construct($matchers); + } + + public function matches($item) + { + return $this->matchesWithShortcut($item, true); + } + + public function describeTo(Description $description) + { + $this->describeToWithOperator($description, 'or'); + } + + /** + * Evaluates to true if ANY of the passed in matchers evaluate to true. + * + * @factory ... + */ + public static function anyOf(/* args... */) + { + $args = func_get_args(); + + return new self(Util::createMatcherArray($args)); + } + + /** + * Evaluates to false if ANY of the passed in matchers evaluate to true. + * + * @factory ... + */ + public static function noneOf(/* args... */) + { + $args = func_get_args(); + + return IsNot::not( + new self(Util::createMatcherArray($args)) + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/CombinableMatcher.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/CombinableMatcher.php new file mode 100644 index 00000000..e3b4aa78 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/CombinableMatcher.php @@ -0,0 +1,78 @@ +_matcher = $matcher; + } + + public function matches($item) + { + return $this->_matcher->matches($item); + } + + public function describeTo(Description $description) + { + $description->appendDescriptionOf($this->_matcher); + } + + /** Diversion from Hamcrest-Java... Logical "and" not permitted */ + public function andAlso(Matcher $other) + { + return new self(new AllOf($this->_templatedListWith($other))); + } + + /** Diversion from Hamcrest-Java... Logical "or" not permitted */ + public function orElse(Matcher $other) + { + return new self(new AnyOf($this->_templatedListWith($other))); + } + + /** + * This is useful for fluently combining matchers that must both pass. + * For example: + *
    +     *   assertThat($string, both(containsString("a"))->andAlso(containsString("b")));
    +     * 
    + * + * @factory + */ + public static function both(Matcher $matcher) + { + return new self($matcher); + } + + /** + * This is useful for fluently combining matchers where either may pass, + * for example: + *
    +     *   assertThat($string, either(containsString("a"))->orElse(containsString("b")));
    +     * 
    + * + * @factory + */ + public static function either(Matcher $matcher) + { + return new self($matcher); + } + + // -- Private Methods + + private function _templatedListWith(Matcher $other) + { + return array($this->_matcher, $other); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/DescribedAs.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/DescribedAs.php new file mode 100644 index 00000000..5b2583fa --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/DescribedAs.php @@ -0,0 +1,68 @@ +_descriptionTemplate = $descriptionTemplate; + $this->_matcher = $matcher; + $this->_values = $values; + } + + public function matches($item) + { + return $this->_matcher->matches($item); + } + + public function describeTo(Description $description) + { + $textStart = 0; + while (preg_match(self::ARG_PATTERN, $this->_descriptionTemplate, $matches, PREG_OFFSET_CAPTURE, $textStart)) { + $text = $matches[0][0]; + $index = $matches[1][0]; + $offset = $matches[0][1]; + + $description->appendText(substr($this->_descriptionTemplate, $textStart, $offset - $textStart)); + $description->appendValue($this->_values[$index]); + + $textStart = $offset + strlen($text); + } + + if ($textStart < strlen($this->_descriptionTemplate)) { + $description->appendText(substr($this->_descriptionTemplate, $textStart)); + } + } + + /** + * Wraps an existing matcher and overrides the description when it fails. + * + * @factory ... + */ + public static function describedAs(/* $description, Hamcrest\Matcher $matcher, $values... */) + { + $args = func_get_args(); + $description = array_shift($args); + $matcher = array_shift($args); + $values = $args; + + return new self($description, $matcher, $values); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Every.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Every.php new file mode 100644 index 00000000..d686f8da --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Every.php @@ -0,0 +1,56 @@ +_matcher = $matcher; + } + + protected function matchesSafelyWithDiagnosticDescription($items, Description $mismatchDescription) + { + foreach ($items as $item) { + if (!$this->_matcher->matches($item)) { + $mismatchDescription->appendText('an item '); + $this->_matcher->describeMismatch($item, $mismatchDescription); + + return false; + } + } + + return true; + } + + public function describeTo(Description $description) + { + $description->appendText('every item is ')->appendDescriptionOf($this->_matcher); + } + + /** + * @param Matcher $itemMatcher + * A matcher to apply to every element in an array. + * + * @return \Hamcrest\Core\Every + * Evaluates to TRUE for a collection in which every item matches $itemMatcher + * + * @factory + */ + public static function everyItem(Matcher $itemMatcher) + { + return new self($itemMatcher); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/HasToString.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/HasToString.php new file mode 100644 index 00000000..45bd9102 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/HasToString.php @@ -0,0 +1,56 @@ +toString(); + } + + return (string) $actual; + } + + /** + * Does array size satisfy a given matcher? + * + * @factory + */ + public static function hasToString($matcher) + { + return new self(Util::wrapValueWithIsEqual($matcher)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Is.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Is.php new file mode 100644 index 00000000..41266dc1 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Is.php @@ -0,0 +1,57 @@ +_matcher = $matcher; + } + + public function matches($arg) + { + return $this->_matcher->matches($arg); + } + + public function describeTo(Description $description) + { + $description->appendText('is ')->appendDescriptionOf($this->_matcher); + } + + public function describeMismatch($item, Description $mismatchDescription) + { + $this->_matcher->describeMismatch($item, $mismatchDescription); + } + + /** + * Decorates another Matcher, retaining the behavior but allowing tests + * to be slightly more expressive. + * + * For example: assertThat($cheese, equalTo($smelly)) + * vs. assertThat($cheese, is(equalTo($smelly))) + * + * @factory + */ + public static function is($value) + { + return new self(Util::wrapValueWithIsEqual($value)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsAnything.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsAnything.php new file mode 100644 index 00000000..f20e6c0d --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsAnything.php @@ -0,0 +1,45 @@ +true. + */ +class IsAnything extends BaseMatcher +{ + + private $_message; + + public function __construct($message = 'ANYTHING') + { + $this->_message = $message; + } + + public function matches($item) + { + return true; + } + + public function describeTo(Description $description) + { + $description->appendText($this->_message); + } + + /** + * This matcher always evaluates to true. + * + * @param string $description A meaningful string used when describing itself. + * + * @return \Hamcrest\Core\IsAnything + * @factory + */ + public static function anything($description = 'ANYTHING') + { + return new self($description); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsCollectionContaining.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsCollectionContaining.php new file mode 100644 index 00000000..5e60426d --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsCollectionContaining.php @@ -0,0 +1,93 @@ +_elementMatcher = $elementMatcher; + } + + protected function matchesSafely($items) + { + foreach ($items as $item) { + if ($this->_elementMatcher->matches($item)) { + return true; + } + } + + return false; + } + + protected function describeMismatchSafely($items, Description $mismatchDescription) + { + $mismatchDescription->appendText('was ')->appendValue($items); + } + + public function describeTo(Description $description) + { + $description + ->appendText('a collection containing ') + ->appendDescriptionOf($this->_elementMatcher) + ; + } + + /** + * Test if the value is an array containing this matcher. + * + * Example: + *
    +     * assertThat(array('a', 'b'), hasItem(equalTo('b')));
    +     * //Convenience defaults to equalTo()
    +     * assertThat(array('a', 'b'), hasItem('b'));
    +     * 
    + * + * @factory ... + */ + public static function hasItem() + { + $args = func_get_args(); + $firstArg = array_shift($args); + + return new self(Util::wrapValueWithIsEqual($firstArg)); + } + + /** + * Test if the value is an array containing elements that match all of these + * matchers. + * + * Example: + *
    +     * assertThat(array('a', 'b', 'c'), hasItems(equalTo('a'), equalTo('b')));
    +     * 
    + * + * @factory ... + */ + public static function hasItems(/* args... */) + { + $args = func_get_args(); + $matchers = array(); + + foreach ($args as $arg) { + $matchers[] = self::hasItem($arg); + } + + return AllOf::allOf($matchers); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsEqual.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsEqual.php new file mode 100644 index 00000000..523fba0b --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsEqual.php @@ -0,0 +1,44 @@ +_item = $item; + } + + public function matches($arg) + { + return (($arg == $this->_item) && ($this->_item == $arg)); + } + + public function describeTo(Description $description) + { + $description->appendValue($this->_item); + } + + /** + * Is the value equal to another value, as tested by the use of the "==" + * comparison operator? + * + * @factory + */ + public static function equalTo($item) + { + return new self($item); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsIdentical.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsIdentical.php new file mode 100644 index 00000000..28f7b36e --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsIdentical.php @@ -0,0 +1,38 @@ +_value = $value; + } + + public function describeTo(Description $description) + { + $description->appendValue($this->_value); + } + + /** + * Tests of the value is identical to $value as tested by the "===" operator. + * + * @factory + */ + public static function identicalTo($value) + { + return new self($value); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsInstanceOf.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsInstanceOf.php new file mode 100644 index 00000000..7a5c92a6 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsInstanceOf.php @@ -0,0 +1,67 @@ +_theClass = $theClass; + } + + protected function matchesWithDiagnosticDescription($item, Description $mismatchDescription) + { + if (!is_object($item)) { + $mismatchDescription->appendText('was ')->appendValue($item); + + return false; + } + + if (!($item instanceof $this->_theClass)) { + $mismatchDescription->appendText('[' . get_class($item) . '] ') + ->appendValue($item); + + return false; + } + + return true; + } + + public function describeTo(Description $description) + { + $description->appendText('an instance of ') + ->appendText($this->_theClass) + ; + } + + /** + * Is the value an instance of a particular type? + * This version assumes no relationship between the required type and + * the signature of the method that sets it up, for example in + * assertThat($anObject, anInstanceOf('Thing')); + * + * @factory any + */ + public static function anInstanceOf($theClass) + { + return new self($theClass); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsNot.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsNot.php new file mode 100644 index 00000000..167f0d06 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsNot.php @@ -0,0 +1,44 @@ +_matcher = $matcher; + } + + public function matches($arg) + { + return !$this->_matcher->matches($arg); + } + + public function describeTo(Description $description) + { + $description->appendText('not ')->appendDescriptionOf($this->_matcher); + } + + /** + * Matches if value does not match $value. + * + * @factory + */ + public static function not($value) + { + return new self(Util::wrapValueWithIsEqual($value)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsNull.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsNull.php new file mode 100644 index 00000000..91a454c1 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsNull.php @@ -0,0 +1,56 @@ +appendText('null'); + } + + /** + * Matches if value is null. + * + * @factory + */ + public static function nullValue() + { + if (!self::$_INSTANCE) { + self::$_INSTANCE = new self(); + } + + return self::$_INSTANCE; + } + + /** + * Matches if value is not null. + * + * @factory + */ + public static function notNullValue() + { + if (!self::$_NOT_INSTANCE) { + self::$_NOT_INSTANCE = IsNot::not(self::nullValue()); + } + + return self::$_NOT_INSTANCE; + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsSame.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsSame.php new file mode 100644 index 00000000..81078705 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsSame.php @@ -0,0 +1,51 @@ +_object = $object; + } + + public function matches($object) + { + return ($object === $this->_object) && ($this->_object === $object); + } + + public function describeTo(Description $description) + { + $description->appendText('sameInstance(') + ->appendValue($this->_object) + ->appendText(')') + ; + } + + /** + * Creates a new instance of IsSame. + * + * @param mixed $object + * The predicate evaluates to true only when the argument is + * this object. + * + * @return \Hamcrest\Core\IsSame + * @factory + */ + public static function sameInstance($object) + { + return new self($object); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsTypeOf.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsTypeOf.php new file mode 100644 index 00000000..d24f0f94 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsTypeOf.php @@ -0,0 +1,71 @@ +_theType = strtolower($theType); + } + + public function matches($item) + { + return strtolower(gettype($item)) == $this->_theType; + } + + public function describeTo(Description $description) + { + $description->appendText(self::getTypeDescription($this->_theType)); + } + + public function describeMismatch($item, Description $description) + { + if ($item === null) { + $description->appendText('was null'); + } else { + $description->appendText('was ') + ->appendText(self::getTypeDescription(strtolower(gettype($item)))) + ->appendText(' ') + ->appendValue($item) + ; + } + } + + public static function getTypeDescription($type) + { + if ($type == 'null') { + return 'null'; + } + + return (strpos('aeiou', substr($type, 0, 1)) === false ? 'a ' : 'an ') + . $type; + } + + /** + * Is the value a particular built-in type? + * + * @factory + */ + public static function typeOf($theType) + { + return new self($theType); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Set.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Set.php new file mode 100644 index 00000000..cdc45d53 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Set.php @@ -0,0 +1,95 @@ + + * assertThat(array('a', 'b'), set('b')); + * assertThat($foo, set('bar')); + * assertThat('Server', notSet('defaultPort')); + * + * + * @todo Replace $property with a matcher and iterate all property names. + */ +class Set extends BaseMatcher +{ + + private $_property; + private $_not; + + public function __construct($property, $not = false) + { + $this->_property = $property; + $this->_not = $not; + } + + public function matches($item) + { + if ($item === null) { + return false; + } + $property = $this->_property; + if (is_array($item)) { + $result = isset($item[$property]); + } elseif (is_object($item)) { + $result = isset($item->$property); + } elseif (is_string($item)) { + $result = isset($item::$$property); + } else { + throw new \InvalidArgumentException('Must pass an object, array, or class name'); + } + + return $this->_not ? !$result : $result; + } + + public function describeTo(Description $description) + { + $description->appendText($this->_not ? 'unset property ' : 'set property ')->appendText($this->_property); + } + + public function describeMismatch($item, Description $description) + { + $value = ''; + if (!$this->_not) { + $description->appendText('was not set'); + } else { + $property = $this->_property; + if (is_array($item)) { + $value = $item[$property]; + } elseif (is_object($item)) { + $value = $item->$property; + } elseif (is_string($item)) { + $value = $item::$$property; + } + parent::describeMismatch($value, $description); + } + } + + /** + * Matches if value (class, object, or array) has named $property. + * + * @factory + */ + public static function set($property) + { + return new self($property); + } + + /** + * Matches if value (class, object, or array) does not have named $property. + * + * @factory + */ + public static function notSet($property) + { + return new self($property, true); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/ShortcutCombination.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/ShortcutCombination.php new file mode 100644 index 00000000..d93db74f --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/ShortcutCombination.php @@ -0,0 +1,43 @@ + + */ + private $_matchers; + + public function __construct(array $matchers) + { + Util::checkAllAreMatchers($matchers); + + $this->_matchers = $matchers; + } + + protected function matchesWithShortcut($item, $shortcut) + { + /** @var $matcher \Hamcrest\Matcher */ + foreach ($this->_matchers as $matcher) { + if ($matcher->matches($item) == $shortcut) { + return $shortcut; + } + } + + return !$shortcut; + } + + public function describeToWithOperator(Description $description, $operator) + { + $description->appendList('(', ' ' . $operator . ' ', ')', $this->_matchers); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Description.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Description.php new file mode 100644 index 00000000..9a482dbf --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Description.php @@ -0,0 +1,70 @@ +matchesWithDiagnosticDescription($item, new NullDescription()); + } + + public function describeMismatch($item, Description $mismatchDescription) + { + $this->matchesWithDiagnosticDescription($item, $mismatchDescription); + } + + abstract protected function matchesWithDiagnosticDescription($item, Description $mismatchDescription); +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/FeatureMatcher.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/FeatureMatcher.php new file mode 100644 index 00000000..59f6cc73 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/FeatureMatcher.php @@ -0,0 +1,67 @@ +featureValueOf() in a subclass to pull out the feature to be + * matched against. + */ +abstract class FeatureMatcher extends TypeSafeDiagnosingMatcher +{ + + private $_subMatcher; + private $_featureDescription; + private $_featureName; + + /** + * Constructor. + * + * @param string $type + * @param string $subtype + * @param \Hamcrest\Matcher $subMatcher The matcher to apply to the feature + * @param string $featureDescription Descriptive text to use in describeTo + * @param string $featureName Identifying text for mismatch message + */ + public function __construct($type, $subtype, Matcher $subMatcher, $featureDescription, $featureName) + { + parent::__construct($type, $subtype); + + $this->_subMatcher = $subMatcher; + $this->_featureDescription = $featureDescription; + $this->_featureName = $featureName; + } + + /** + * Implement this to extract the interesting feature. + * + * @param mixed $actual the target object + * + * @return mixed the feature to be matched + */ + abstract protected function featureValueOf($actual); + + public function matchesSafelyWithDiagnosticDescription($actual, Description $mismatchDescription) + { + $featureValue = $this->featureValueOf($actual); + + if (!$this->_subMatcher->matches($featureValue)) { + $mismatchDescription->appendText($this->_featureName) + ->appendText(' was ')->appendValue($featureValue); + + return false; + } + + return true; + } + + final public function describeTo(Description $description) + { + $description->appendText($this->_featureDescription)->appendText(' ') + ->appendDescriptionOf($this->_subMatcher) + ; + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Internal/SelfDescribingValue.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Internal/SelfDescribingValue.php new file mode 100644 index 00000000..995da71d --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Internal/SelfDescribingValue.php @@ -0,0 +1,27 @@ +_value = $value; + } + + public function describeTo(Description $description) + { + $description->appendValue($this->_value); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Matcher.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Matcher.php new file mode 100644 index 00000000..e5dcf093 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Matcher.php @@ -0,0 +1,50 @@ + + * Matcher implementations should NOT directly implement this interface. + * Instead, extend the {@link Hamcrest\BaseMatcher} abstract class, + * which will ensure that the Matcher API can grow to support + * new features and remain compatible with all Matcher implementations. + *

    + * For easy access to common Matcher implementations, use the static factory + * methods in {@link Hamcrest\CoreMatchers}. + * + * @see Hamcrest\CoreMatchers + * @see Hamcrest\BaseMatcher + */ +interface Matcher extends SelfDescribing +{ + + /** + * Evaluates the matcher for argument $item. + * + * @param mixed $item the object against which the matcher is evaluated. + * + * @return boolean true if $item matches, + * otherwise false. + * + * @see Hamcrest\BaseMatcher + */ + public function matches($item); + + /** + * Generate a description of why the matcher has not accepted the item. + * The description will be part of a larger description of why a matching + * failed, so it should be concise. + * This method assumes that matches($item) is false, but + * will not check this. + * + * @param mixed $item The item that the Matcher has rejected. + * @param Description $description + * @return + */ + public function describeMismatch($item, Description $description); +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/MatcherAssert.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/MatcherAssert.php new file mode 100644 index 00000000..d546dbee --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/MatcherAssert.php @@ -0,0 +1,118 @@ + + * // With an identifier + * assertThat("apple flavour", $apple->flavour(), equalTo("tasty")); + * // Without an identifier + * assertThat($apple->flavour(), equalTo("tasty")); + * // Evaluating a boolean expression + * assertThat("some error", $a > $b); + * assertThat($a > $b); + * + */ + public static function assertThat(/* $args ... */) + { + $args = func_get_args(); + switch (count($args)) { + case 1: + self::$_count++; + if (!$args[0]) { + throw new AssertionError(); + } + break; + + case 2: + self::$_count++; + if ($args[1] instanceof Matcher) { + self::doAssert('', $args[0], $args[1]); + } elseif (!$args[1]) { + throw new AssertionError($args[0]); + } + break; + + case 3: + self::$_count++; + self::doAssert( + $args[0], + $args[1], + Util::wrapValueWithIsEqual($args[2]) + ); + break; + + default: + throw new \InvalidArgumentException('assertThat() requires one to three arguments'); + } + } + + /** + * Returns the number of assertions performed. + * + * @return int + */ + public static function getCount() + { + return self::$_count; + } + + /** + * Resets the number of assertions performed to zero. + */ + public static function resetCount() + { + self::$_count = 0; + } + + /** + * Performs the actual assertion logic. + * + * If $matcher doesn't match $actual, + * throws a {@link Hamcrest\AssertionError} with a description + * of the failure along with the optional $identifier. + * + * @param string $identifier added to the message upon failure + * @param mixed $actual value to compare against $matcher + * @param \Hamcrest\Matcher $matcher applied to $actual + * @throws AssertionError + */ + private static function doAssert($identifier, $actual, Matcher $matcher) + { + if (!$matcher->matches($actual)) { + $description = new StringDescription(); + if (!empty($identifier)) { + $description->appendText($identifier . PHP_EOL); + } + $description->appendText('Expected: ') + ->appendDescriptionOf($matcher) + ->appendText(PHP_EOL . ' but: '); + + $matcher->describeMismatch($actual, $description); + + throw new AssertionError((string) $description); + } + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Matchers.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Matchers.php new file mode 100644 index 00000000..23232e45 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Matchers.php @@ -0,0 +1,713 @@ + + * assertThat($string, both(containsString("a"))->andAlso(containsString("b"))); + * + */ + public static function both(\Hamcrest\Matcher $matcher) + { + return \Hamcrest\Core\CombinableMatcher::both($matcher); + } + + /** + * This is useful for fluently combining matchers where either may pass, + * for example: + *

    +     *   assertThat($string, either(containsString("a"))->orElse(containsString("b")));
    +     * 
    + */ + public static function either(\Hamcrest\Matcher $matcher) + { + return \Hamcrest\Core\CombinableMatcher::either($matcher); + } + + /** + * Wraps an existing matcher and overrides the description when it fails. + */ + public static function describedAs(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Core\DescribedAs', 'describedAs'), $args); + } + + /** + * @param Matcher $itemMatcher + * A matcher to apply to every element in an array. + * + * @return \Hamcrest\Core\Every + * Evaluates to TRUE for a collection in which every item matches $itemMatcher + */ + public static function everyItem(\Hamcrest\Matcher $itemMatcher) + { + return \Hamcrest\Core\Every::everyItem($itemMatcher); + } + + /** + * Does array size satisfy a given matcher? + */ + public static function hasToString($matcher) + { + return \Hamcrest\Core\HasToString::hasToString($matcher); + } + + /** + * Decorates another Matcher, retaining the behavior but allowing tests + * to be slightly more expressive. + * + * For example: assertThat($cheese, equalTo($smelly)) + * vs. assertThat($cheese, is(equalTo($smelly))) + */ + public static function is($value) + { + return \Hamcrest\Core\Is::is($value); + } + + /** + * This matcher always evaluates to true. + * + * @param string $description A meaningful string used when describing itself. + * + * @return \Hamcrest\Core\IsAnything + */ + public static function anything($description = 'ANYTHING') + { + return \Hamcrest\Core\IsAnything::anything($description); + } + + /** + * Test if the value is an array containing this matcher. + * + * Example: + *
    +     * assertThat(array('a', 'b'), hasItem(equalTo('b')));
    +     * //Convenience defaults to equalTo()
    +     * assertThat(array('a', 'b'), hasItem('b'));
    +     * 
    + */ + public static function hasItem(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Core\IsCollectionContaining', 'hasItem'), $args); + } + + /** + * Test if the value is an array containing elements that match all of these + * matchers. + * + * Example: + *
    +     * assertThat(array('a', 'b', 'c'), hasItems(equalTo('a'), equalTo('b')));
    +     * 
    + */ + public static function hasItems(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Core\IsCollectionContaining', 'hasItems'), $args); + } + + /** + * Is the value equal to another value, as tested by the use of the "==" + * comparison operator? + */ + public static function equalTo($item) + { + return \Hamcrest\Core\IsEqual::equalTo($item); + } + + /** + * Tests of the value is identical to $value as tested by the "===" operator. + */ + public static function identicalTo($value) + { + return \Hamcrest\Core\IsIdentical::identicalTo($value); + } + + /** + * Is the value an instance of a particular type? + * This version assumes no relationship between the required type and + * the signature of the method that sets it up, for example in + * assertThat($anObject, anInstanceOf('Thing')); + */ + public static function anInstanceOf($theClass) + { + return \Hamcrest\Core\IsInstanceOf::anInstanceOf($theClass); + } + + /** + * Is the value an instance of a particular type? + * This version assumes no relationship between the required type and + * the signature of the method that sets it up, for example in + * assertThat($anObject, anInstanceOf('Thing')); + */ + public static function any($theClass) + { + return \Hamcrest\Core\IsInstanceOf::anInstanceOf($theClass); + } + + /** + * Matches if value does not match $value. + */ + public static function not($value) + { + return \Hamcrest\Core\IsNot::not($value); + } + + /** + * Matches if value is null. + */ + public static function nullValue() + { + return \Hamcrest\Core\IsNull::nullValue(); + } + + /** + * Matches if value is not null. + */ + public static function notNullValue() + { + return \Hamcrest\Core\IsNull::notNullValue(); + } + + /** + * Creates a new instance of IsSame. + * + * @param mixed $object + * The predicate evaluates to true only when the argument is + * this object. + * + * @return \Hamcrest\Core\IsSame + */ + public static function sameInstance($object) + { + return \Hamcrest\Core\IsSame::sameInstance($object); + } + + /** + * Is the value a particular built-in type? + */ + public static function typeOf($theType) + { + return \Hamcrest\Core\IsTypeOf::typeOf($theType); + } + + /** + * Matches if value (class, object, or array) has named $property. + */ + public static function set($property) + { + return \Hamcrest\Core\Set::set($property); + } + + /** + * Matches if value (class, object, or array) does not have named $property. + */ + public static function notSet($property) + { + return \Hamcrest\Core\Set::notSet($property); + } + + /** + * Matches if value is a number equal to $value within some range of + * acceptable error $delta. + */ + public static function closeTo($value, $delta) + { + return \Hamcrest\Number\IsCloseTo::closeTo($value, $delta); + } + + /** + * The value is not > $value, nor < $value. + */ + public static function comparesEqualTo($value) + { + return \Hamcrest\Number\OrderingComparison::comparesEqualTo($value); + } + + /** + * The value is > $value. + */ + public static function greaterThan($value) + { + return \Hamcrest\Number\OrderingComparison::greaterThan($value); + } + + /** + * The value is >= $value. + */ + public static function greaterThanOrEqualTo($value) + { + return \Hamcrest\Number\OrderingComparison::greaterThanOrEqualTo($value); + } + + /** + * The value is >= $value. + */ + public static function atLeast($value) + { + return \Hamcrest\Number\OrderingComparison::greaterThanOrEqualTo($value); + } + + /** + * The value is < $value. + */ + public static function lessThan($value) + { + return \Hamcrest\Number\OrderingComparison::lessThan($value); + } + + /** + * The value is <= $value. + */ + public static function lessThanOrEqualTo($value) + { + return \Hamcrest\Number\OrderingComparison::lessThanOrEqualTo($value); + } + + /** + * The value is <= $value. + */ + public static function atMost($value) + { + return \Hamcrest\Number\OrderingComparison::lessThanOrEqualTo($value); + } + + /** + * Matches if value is a zero-length string. + */ + public static function isEmptyString() + { + return \Hamcrest\Text\IsEmptyString::isEmptyString(); + } + + /** + * Matches if value is a zero-length string. + */ + public static function emptyString() + { + return \Hamcrest\Text\IsEmptyString::isEmptyString(); + } + + /** + * Matches if value is null or a zero-length string. + */ + public static function isEmptyOrNullString() + { + return \Hamcrest\Text\IsEmptyString::isEmptyOrNullString(); + } + + /** + * Matches if value is null or a zero-length string. + */ + public static function nullOrEmptyString() + { + return \Hamcrest\Text\IsEmptyString::isEmptyOrNullString(); + } + + /** + * Matches if value is a non-zero-length string. + */ + public static function isNonEmptyString() + { + return \Hamcrest\Text\IsEmptyString::isNonEmptyString(); + } + + /** + * Matches if value is a non-zero-length string. + */ + public static function nonEmptyString() + { + return \Hamcrest\Text\IsEmptyString::isNonEmptyString(); + } + + /** + * Matches if value is a string equal to $string, regardless of the case. + */ + public static function equalToIgnoringCase($string) + { + return \Hamcrest\Text\IsEqualIgnoringCase::equalToIgnoringCase($string); + } + + /** + * Matches if value is a string equal to $string, regardless of whitespace. + */ + public static function equalToIgnoringWhiteSpace($string) + { + return \Hamcrest\Text\IsEqualIgnoringWhiteSpace::equalToIgnoringWhiteSpace($string); + } + + /** + * Matches if value is a string that matches regular expression $pattern. + */ + public static function matchesPattern($pattern) + { + return \Hamcrest\Text\MatchesPattern::matchesPattern($pattern); + } + + /** + * Matches if value is a string that contains $substring. + */ + public static function containsString($substring) + { + return \Hamcrest\Text\StringContains::containsString($substring); + } + + /** + * Matches if value is a string that contains $substring regardless of the case. + */ + public static function containsStringIgnoringCase($substring) + { + return \Hamcrest\Text\StringContainsIgnoringCase::containsStringIgnoringCase($substring); + } + + /** + * Matches if value contains $substrings in a constrained order. + */ + public static function stringContainsInOrder(/* args... */) + { + $args = func_get_args(); + return call_user_func_array(array('\Hamcrest\Text\StringContainsInOrder', 'stringContainsInOrder'), $args); + } + + /** + * Matches if value is a string that ends with $substring. + */ + public static function endsWith($substring) + { + return \Hamcrest\Text\StringEndsWith::endsWith($substring); + } + + /** + * Matches if value is a string that starts with $substring. + */ + public static function startsWith($substring) + { + return \Hamcrest\Text\StringStartsWith::startsWith($substring); + } + + /** + * Is the value an array? + */ + public static function arrayValue() + { + return \Hamcrest\Type\IsArray::arrayValue(); + } + + /** + * Is the value a boolean? + */ + public static function booleanValue() + { + return \Hamcrest\Type\IsBoolean::booleanValue(); + } + + /** + * Is the value a boolean? + */ + public static function boolValue() + { + return \Hamcrest\Type\IsBoolean::booleanValue(); + } + + /** + * Is the value callable? + */ + public static function callableValue() + { + return \Hamcrest\Type\IsCallable::callableValue(); + } + + /** + * Is the value a float/double? + */ + public static function doubleValue() + { + return \Hamcrest\Type\IsDouble::doubleValue(); + } + + /** + * Is the value a float/double? + */ + public static function floatValue() + { + return \Hamcrest\Type\IsDouble::doubleValue(); + } + + /** + * Is the value an integer? + */ + public static function integerValue() + { + return \Hamcrest\Type\IsInteger::integerValue(); + } + + /** + * Is the value an integer? + */ + public static function intValue() + { + return \Hamcrest\Type\IsInteger::integerValue(); + } + + /** + * Is the value a numeric? + */ + public static function numericValue() + { + return \Hamcrest\Type\IsNumeric::numericValue(); + } + + /** + * Is the value an object? + */ + public static function objectValue() + { + return \Hamcrest\Type\IsObject::objectValue(); + } + + /** + * Is the value an object? + */ + public static function anObject() + { + return \Hamcrest\Type\IsObject::objectValue(); + } + + /** + * Is the value a resource? + */ + public static function resourceValue() + { + return \Hamcrest\Type\IsResource::resourceValue(); + } + + /** + * Is the value a scalar (boolean, integer, double, or string)? + */ + public static function scalarValue() + { + return \Hamcrest\Type\IsScalar::scalarValue(); + } + + /** + * Is the value a string? + */ + public static function stringValue() + { + return \Hamcrest\Type\IsString::stringValue(); + } + + /** + * Wraps $matcher with {@link Hamcrest\Core\IsEqual) + * if it's not a matcher and the XPath in count() + * if it's an integer. + */ + public static function hasXPath($xpath, $matcher = null) + { + return \Hamcrest\Xml\HasXPath::hasXPath($xpath, $matcher); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/NullDescription.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/NullDescription.php new file mode 100644 index 00000000..aae8e461 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/NullDescription.php @@ -0,0 +1,43 @@ +_value = $value; + $this->_delta = $delta; + } + + protected function matchesSafely($item) + { + return $this->_actualDelta($item) <= 0.0; + } + + protected function describeMismatchSafely($item, Description $mismatchDescription) + { + $mismatchDescription->appendValue($item) + ->appendText(' differed by ') + ->appendValue($this->_actualDelta($item)) + ; + } + + public function describeTo(Description $description) + { + $description->appendText('a numeric value within ') + ->appendValue($this->_delta) + ->appendText(' of ') + ->appendValue($this->_value) + ; + } + + /** + * Matches if value is a number equal to $value within some range of + * acceptable error $delta. + * + * @factory + */ + public static function closeTo($value, $delta) + { + return new self($value, $delta); + } + + // -- Private Methods + + private function _actualDelta($item) + { + return (abs(($item - $this->_value)) - $this->_delta); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Number/OrderingComparison.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Number/OrderingComparison.php new file mode 100644 index 00000000..369d0cfa --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Number/OrderingComparison.php @@ -0,0 +1,132 @@ +_value = $value; + $this->_minCompare = $minCompare; + $this->_maxCompare = $maxCompare; + } + + protected function matchesSafely($other) + { + $compare = $this->_compare($this->_value, $other); + + return ($this->_minCompare <= $compare) && ($compare <= $this->_maxCompare); + } + + protected function describeMismatchSafely($item, Description $mismatchDescription) + { + $mismatchDescription + ->appendValue($item)->appendText(' was ') + ->appendText($this->_comparison($this->_compare($this->_value, $item))) + ->appendText(' ')->appendValue($this->_value) + ; + } + + public function describeTo(Description $description) + { + $description->appendText('a value ') + ->appendText($this->_comparison($this->_minCompare)) + ; + if ($this->_minCompare != $this->_maxCompare) { + $description->appendText(' or ') + ->appendText($this->_comparison($this->_maxCompare)) + ; + } + $description->appendText(' ')->appendValue($this->_value); + } + + /** + * The value is not > $value, nor < $value. + * + * @factory + */ + public static function comparesEqualTo($value) + { + return new self($value, 0, 0); + } + + /** + * The value is > $value. + * + * @factory + */ + public static function greaterThan($value) + { + return new self($value, -1, -1); + } + + /** + * The value is >= $value. + * + * @factory atLeast + */ + public static function greaterThanOrEqualTo($value) + { + return new self($value, -1, 0); + } + + /** + * The value is < $value. + * + * @factory + */ + public static function lessThan($value) + { + return new self($value, 1, 1); + } + + /** + * The value is <= $value. + * + * @factory atMost + */ + public static function lessThanOrEqualTo($value) + { + return new self($value, 0, 1); + } + + // -- Private Methods + + private function _compare($left, $right) + { + $a = $left; + $b = $right; + + if ($a < $b) { + return -1; + } elseif ($a == $b) { + return 0; + } else { + return 1; + } + } + + private function _comparison($compare) + { + if ($compare > 0) { + return 'less than'; + } elseif ($compare == 0) { + return 'equal to'; + } else { + return 'greater than'; + } + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/SelfDescribing.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/SelfDescribing.php new file mode 100644 index 00000000..872fdf9c --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/SelfDescribing.php @@ -0,0 +1,23 @@ +_out = (string) $out; + } + + public function __toString() + { + return $this->_out; + } + + /** + * Return the description of a {@link Hamcrest\SelfDescribing} object as a + * String. + * + * @param \Hamcrest\SelfDescribing $selfDescribing + * The object to be described. + * + * @return string + * The description of the object. + */ + public static function toString(SelfDescribing $selfDescribing) + { + $self = new self(); + + return (string) $self->appendDescriptionOf($selfDescribing); + } + + /** + * Alias for {@link toString()}. + */ + public static function asString(SelfDescribing $selfDescribing) + { + return self::toString($selfDescribing); + } + + // -- Protected Methods + + protected function append($str) + { + $this->_out .= $str; + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEmptyString.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEmptyString.php new file mode 100644 index 00000000..2ae61b96 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEmptyString.php @@ -0,0 +1,85 @@ +_empty = $empty; + } + + public function matches($item) + { + return $this->_empty + ? ($item === '') + : is_string($item) && $item !== ''; + } + + public function describeTo(Description $description) + { + $description->appendText($this->_empty ? 'an empty string' : 'a non-empty string'); + } + + /** + * Matches if value is a zero-length string. + * + * @factory emptyString + */ + public static function isEmptyString() + { + if (!self::$_INSTANCE) { + self::$_INSTANCE = new self(true); + } + + return self::$_INSTANCE; + } + + /** + * Matches if value is null or a zero-length string. + * + * @factory nullOrEmptyString + */ + public static function isEmptyOrNullString() + { + if (!self::$_NULL_OR_EMPTY_INSTANCE) { + self::$_NULL_OR_EMPTY_INSTANCE = AnyOf::anyOf( + IsNull::nullvalue(), + self::isEmptyString() + ); + } + + return self::$_NULL_OR_EMPTY_INSTANCE; + } + + /** + * Matches if value is a non-zero-length string. + * + * @factory nonEmptyString + */ + public static function isNonEmptyString() + { + if (!self::$_NOT_INSTANCE) { + self::$_NOT_INSTANCE = new self(false); + } + + return self::$_NOT_INSTANCE; + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEqualIgnoringCase.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEqualIgnoringCase.php new file mode 100644 index 00000000..3836a8c3 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEqualIgnoringCase.php @@ -0,0 +1,52 @@ +_string = $string; + } + + protected function matchesSafely($item) + { + return strtolower($this->_string) === strtolower($item); + } + + protected function describeMismatchSafely($item, Description $mismatchDescription) + { + $mismatchDescription->appendText('was ')->appendText($item); + } + + public function describeTo(Description $description) + { + $description->appendText('equalToIgnoringCase(') + ->appendValue($this->_string) + ->appendText(')') + ; + } + + /** + * Matches if value is a string equal to $string, regardless of the case. + * + * @factory + */ + public static function equalToIgnoringCase($string) + { + return new self($string); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEqualIgnoringWhiteSpace.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEqualIgnoringWhiteSpace.php new file mode 100644 index 00000000..853692b0 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEqualIgnoringWhiteSpace.php @@ -0,0 +1,66 @@ +_string = $string; + } + + protected function matchesSafely($item) + { + return (strtolower($this->_stripSpace($item)) + === strtolower($this->_stripSpace($this->_string))); + } + + protected function describeMismatchSafely($item, Description $mismatchDescription) + { + $mismatchDescription->appendText('was ')->appendText($item); + } + + public function describeTo(Description $description) + { + $description->appendText('equalToIgnoringWhiteSpace(') + ->appendValue($this->_string) + ->appendText(')') + ; + } + + /** + * Matches if value is a string equal to $string, regardless of whitespace. + * + * @factory + */ + public static function equalToIgnoringWhiteSpace($string) + { + return new self($string); + } + + // -- Private Methods + + private function _stripSpace($string) + { + $parts = preg_split("/[\r\n\t ]+/", $string); + foreach ($parts as $i => $part) { + $parts[$i] = trim($part, " \r\n\t"); + } + + return trim(implode(' ', $parts), " \r\n\t"); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/MatchesPattern.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/MatchesPattern.php new file mode 100644 index 00000000..fa0d68ee --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/MatchesPattern.php @@ -0,0 +1,40 @@ +_substring, (string) $item) >= 1; + } + + protected function relationship() + { + return 'matching'; + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContains.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContains.php new file mode 100644 index 00000000..b92786b6 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContains.php @@ -0,0 +1,45 @@ +_substring); + } + + /** + * Matches if value is a string that contains $substring. + * + * @factory + */ + public static function containsString($substring) + { + return new self($substring); + } + + // -- Protected Methods + + protected function evalSubstringOf($item) + { + return (false !== strpos((string) $item, $this->_substring)); + } + + protected function relationship() + { + return 'containing'; + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContainsIgnoringCase.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContainsIgnoringCase.php new file mode 100644 index 00000000..69f37c25 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContainsIgnoringCase.php @@ -0,0 +1,40 @@ +_substring)); + } + + protected function relationship() + { + return 'containing in any case'; + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContainsInOrder.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContainsInOrder.php new file mode 100644 index 00000000..e75de65d --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContainsInOrder.php @@ -0,0 +1,66 @@ +_substrings = $substrings; + } + + protected function matchesSafely($item) + { + $fromIndex = 0; + + foreach ($this->_substrings as $substring) { + if (false === $fromIndex = strpos($item, $substring, $fromIndex)) { + return false; + } + } + + return true; + } + + protected function describeMismatchSafely($item, Description $mismatchDescription) + { + $mismatchDescription->appendText('was ')->appendText($item); + } + + public function describeTo(Description $description) + { + $description->appendText('a string containing ') + ->appendValueList('', ', ', '', $this->_substrings) + ->appendText(' in order') + ; + } + + /** + * Matches if value contains $substrings in a constrained order. + * + * @factory ... + */ + public static function stringContainsInOrder(/* args... */) + { + $args = func_get_args(); + + if (isset($args[0]) && is_array($args[0])) { + $args = $args[0]; + } + + return new self($args); + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringEndsWith.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringEndsWith.php new file mode 100644 index 00000000..f802ee4d --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringEndsWith.php @@ -0,0 +1,40 @@ +_substring))) === $this->_substring); + } + + protected function relationship() + { + return 'ending with'; + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringStartsWith.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringStartsWith.php new file mode 100644 index 00000000..79c95656 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringStartsWith.php @@ -0,0 +1,40 @@ +_substring)) === $this->_substring); + } + + protected function relationship() + { + return 'starting with'; + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/SubstringMatcher.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/SubstringMatcher.php new file mode 100644 index 00000000..e560ad62 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/SubstringMatcher.php @@ -0,0 +1,45 @@ +_substring = $substring; + } + + protected function matchesSafely($item) + { + return $this->evalSubstringOf($item); + } + + protected function describeMismatchSafely($item, Description $mismatchDescription) + { + $mismatchDescription->appendText('was "')->appendText($item)->appendText('"'); + } + + public function describeTo(Description $description) + { + $description->appendText('a string ') + ->appendText($this->relationship()) + ->appendText(' ') + ->appendValue($this->_substring) + ; + } + + abstract protected function evalSubstringOf($string); + + abstract protected function relationship(); +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsArray.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsArray.php new file mode 100644 index 00000000..9179102f --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsArray.php @@ -0,0 +1,32 @@ +isHexadecimal($item)) { + return true; + } + + return is_numeric($item); + } + + /** + * Return if the string passed is a valid hexadecimal number. + * This check is necessary because PHP 7 doesn't recognize hexadecimal string as numeric anymore. + * + * @param mixed $item + * @return boolean + */ + private function isHexadecimal($item) + { + if (is_string($item) && preg_match('/^0x(.*)$/', $item, $matches)) { + return ctype_xdigit($matches[1]); + } + + return false; + } + + /** + * Is the value a numeric? + * + * @factory + */ + public static function numericValue() + { + return new self; + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsObject.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsObject.php new file mode 100644 index 00000000..65918fcf --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsObject.php @@ -0,0 +1,32 @@ +matchesSafelyWithDiagnosticDescription($item, new NullDescription()); + } + + final public function describeMismatchSafely($item, Description $mismatchDescription) + { + $this->matchesSafelyWithDiagnosticDescription($item, $mismatchDescription); + } + + // -- Protected Methods + + /** + * Subclasses should implement these. The item will already have been checked for + * the specific type. + */ + abstract protected function matchesSafelyWithDiagnosticDescription($item, Description $mismatchDescription); +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/TypeSafeMatcher.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/TypeSafeMatcher.php new file mode 100644 index 00000000..56e299a9 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/TypeSafeMatcher.php @@ -0,0 +1,107 @@ +_expectedType = $expectedType; + $this->_expectedSubtype = $expectedSubtype; + } + + final public function matches($item) + { + return $this->_isSafeType($item) && $this->matchesSafely($item); + } + + final public function describeMismatch($item, Description $mismatchDescription) + { + if (!$this->_isSafeType($item)) { + parent::describeMismatch($item, $mismatchDescription); + } else { + $this->describeMismatchSafely($item, $mismatchDescription); + } + } + + // -- Protected Methods + + /** + * The item will already have been checked for the specific type and subtype. + */ + abstract protected function matchesSafely($item); + + /** + * The item will already have been checked for the specific type and subtype. + */ + abstract protected function describeMismatchSafely($item, Description $mismatchDescription); + + // -- Private Methods + + private function _isSafeType($value) + { + switch ($this->_expectedType) { + + case self::TYPE_ANY: + return true; + + case self::TYPE_STRING: + return is_string($value) || is_numeric($value); + + case self::TYPE_NUMERIC: + return is_numeric($value) || is_string($value); + + case self::TYPE_ARRAY: + return is_array($value); + + case self::TYPE_OBJECT: + return is_object($value) + && ($this->_expectedSubtype === null + || $value instanceof $this->_expectedSubtype); + + case self::TYPE_RESOURCE: + return is_resource($value) + && ($this->_expectedSubtype === null + || get_resource_type($value) == $this->_expectedSubtype); + + case self::TYPE_BOOLEAN: + return true; + + default: + return true; + + } + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Util.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Util.php new file mode 100644 index 00000000..169b0366 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Util.php @@ -0,0 +1,76 @@ + all items are + */ + public static function createMatcherArray(array $items) + { + //Extract single array item + if (count($items) == 1 && is_array($items[0])) { + $items = $items[0]; + } + + //Replace non-matchers + foreach ($items as &$item) { + if (!($item instanceof Matcher)) { + $item = Core\IsEqual::equalTo($item); + } + } + + return $items; + } +} diff --git a/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Xml/HasXPath.php b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Xml/HasXPath.php new file mode 100644 index 00000000..d9764e45 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Xml/HasXPath.php @@ -0,0 +1,195 @@ +_xpath = $xpath; + $this->_matcher = $matcher; + } + + /** + * Matches if the XPath matches against the DOM node and the matcher. + * + * @param string|\DOMNode $actual + * @param Description $mismatchDescription + * @return bool + */ + protected function matchesWithDiagnosticDescription($actual, Description $mismatchDescription) + { + if (is_string($actual)) { + $actual = $this->createDocument($actual); + } elseif (!$actual instanceof \DOMNode) { + $mismatchDescription->appendText('was ')->appendValue($actual); + + return false; + } + $result = $this->evaluate($actual); + if ($result instanceof \DOMNodeList) { + return $this->matchesContent($result, $mismatchDescription); + } else { + return $this->matchesExpression($result, $mismatchDescription); + } + } + + /** + * Creates and returns a DOMDocument from the given + * XML or HTML string. + * + * @param string $text + * @return \DOMDocument built from $text + * @throws \InvalidArgumentException if the document is not valid + */ + protected function createDocument($text) + { + $document = new \DOMDocument(); + if (preg_match('/^\s*<\?xml/', $text)) { + if (!@$document->loadXML($text)) { + throw new \InvalidArgumentException('Must pass a valid XML document'); + } + } else { + if (!@$document->loadHTML($text)) { + throw new \InvalidArgumentException('Must pass a valid HTML or XHTML document'); + } + } + + return $document; + } + + /** + * Applies the configured XPath to the DOM node and returns either + * the result if it's an expression or the node list if it's a query. + * + * @param \DOMNode $node context from which to issue query + * @return mixed result of expression or DOMNodeList from query + */ + protected function evaluate(\DOMNode $node) + { + if ($node instanceof \DOMDocument) { + $xpathDocument = new \DOMXPath($node); + + return $xpathDocument->evaluate($this->_xpath); + } else { + $xpathDocument = new \DOMXPath($node->ownerDocument); + + return $xpathDocument->evaluate($this->_xpath, $node); + } + } + + /** + * Matches if the list of nodes is not empty and the content of at least + * one node matches the configured matcher, if supplied. + * + * @param \DOMNodeList $nodes selected by the XPath query + * @param Description $mismatchDescription + * @return bool + */ + protected function matchesContent(\DOMNodeList $nodes, Description $mismatchDescription) + { + if ($nodes->length == 0) { + $mismatchDescription->appendText('XPath returned no results'); + } elseif ($this->_matcher === null) { + return true; + } else { + foreach ($nodes as $node) { + if ($this->_matcher->matches($node->textContent)) { + return true; + } + } + $content = array(); + foreach ($nodes as $node) { + $content[] = $node->textContent; + } + $mismatchDescription->appendText('XPath returned ') + ->appendValue($content); + } + + return false; + } + + /** + * Matches if the result of the XPath expression matches the configured + * matcher or evaluates to true if there is none. + * + * @param mixed $result result of the XPath expression + * @param Description $mismatchDescription + * @return bool + */ + protected function matchesExpression($result, Description $mismatchDescription) + { + if ($this->_matcher === null) { + if ($result) { + return true; + } + $mismatchDescription->appendText('XPath expression result was ') + ->appendValue($result); + } else { + if ($this->_matcher->matches($result)) { + return true; + } + $mismatchDescription->appendText('XPath expression result '); + $this->_matcher->describeMismatch($result, $mismatchDescription); + } + + return false; + } + + public function describeTo(Description $description) + { + $description->appendText('XML or HTML document with XPath "') + ->appendText($this->_xpath) + ->appendText('"'); + if ($this->_matcher !== null) { + $description->appendText(' '); + $this->_matcher->describeTo($description); + } + } + + /** + * Wraps $matcher with {@link Hamcrest\Core\IsEqual) + * if it's not a matcher and the XPath in count() + * if it's an integer. + * + * @factory + */ + public static function hasXPath($xpath, $matcher = null) + { + if ($matcher === null || $matcher instanceof Matcher) { + return new self($xpath, $matcher); + } elseif (is_int($matcher) && strpos($xpath, 'count(') !== 0) { + $xpath = 'count(' . $xpath . ')'; + } + + return new self($xpath, IsEqual::equalTo($matcher)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/AbstractMatcherTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/AbstractMatcherTest.php new file mode 100644 index 00000000..8a1fb2a9 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/AbstractMatcherTest.php @@ -0,0 +1,68 @@ +assertTrue($matcher->matches($arg), $message); + } + + public function assertDoesNotMatch(\Hamcrest\Matcher $matcher, $arg, $message) + { + $this->assertFalse($matcher->matches($arg), $message); + } + + public function assertDescription($expected, \Hamcrest\Matcher $matcher) + { + $description = new \Hamcrest\StringDescription(); + $description->appendDescriptionOf($matcher); + $this->assertEquals($expected, (string) $description, 'Expected description'); + } + + public function assertMismatchDescription($expected, \Hamcrest\Matcher $matcher, $arg) + { + $description = new \Hamcrest\StringDescription(); + $this->assertFalse( + $matcher->matches($arg), + 'Precondtion: Matcher should not match item' + ); + $matcher->describeMismatch($arg, $description); + $this->assertEquals( + $expected, + (string) $description, + 'Expected mismatch description' + ); + } + + public function testIsNullSafe() + { + //Should not generate any notices + $this->createMatcher()->matches(null); + $this->createMatcher()->describeMismatch( + null, + new \Hamcrest\NullDescription() + ); + } + + public function testCopesWithUnknownTypes() + { + //Should not generate any notices + $this->createMatcher()->matches(new UnknownType()); + $this->createMatcher()->describeMismatch( + new UnknownType(), + new NullDescription() + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingInAnyOrderTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingInAnyOrderTest.php new file mode 100644 index 00000000..45d9f138 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingInAnyOrderTest.php @@ -0,0 +1,54 @@ +assertDescription('[<1>, <2>] in any order', containsInAnyOrder(array(1, 2))); + } + + public function testMatchesItemsInAnyOrder() + { + $this->assertMatches(containsInAnyOrder(array(1, 2, 3)), array(1, 2, 3), 'in order'); + $this->assertMatches(containsInAnyOrder(array(1, 2, 3)), array(3, 2, 1), 'out of order'); + $this->assertMatches(containsInAnyOrder(array(1)), array(1), 'single'); + } + + public function testAppliesMatchersInAnyOrder() + { + $this->assertMatches( + containsInAnyOrder(array(1, 2, 3)), + array(1, 2, 3), + 'in order' + ); + $this->assertMatches( + containsInAnyOrder(array(1, 2, 3)), + array(3, 2, 1), + 'out of order' + ); + $this->assertMatches( + containsInAnyOrder(array(1)), + array(1), + 'single' + ); + } + + public function testMismatchesItemsInAnyOrder() + { + $matcher = containsInAnyOrder(array(1, 2, 3)); + + $this->assertMismatchDescription('was null', $matcher, null); + $this->assertMismatchDescription('No item matches: <1>, <2>, <3> in []', $matcher, array()); + $this->assertMismatchDescription('No item matches: <2>, <3> in [<1>]', $matcher, array(1)); + $this->assertMismatchDescription('Not matched: <4>', $matcher, array(4, 3, 2, 1)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingInOrderTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingInOrderTest.php new file mode 100644 index 00000000..a9e4e5b0 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingInOrderTest.php @@ -0,0 +1,48 @@ +assertDescription('[<1>, <2>]', arrayContaining(array(1, 2))); + } + + public function testMatchesItemsInOrder() + { + $this->assertMatches(arrayContaining(array(1, 2, 3)), array(1, 2, 3), 'in order'); + $this->assertMatches(arrayContaining(array(1)), array(1), 'single'); + } + + public function testAppliesMatchersInOrder() + { + $this->assertMatches( + arrayContaining(array(1, 2, 3)), + array(1, 2, 3), + 'in order' + ); + $this->assertMatches(arrayContaining(array(1)), array(1), 'single'); + } + + public function testMismatchesItemsInAnyOrder() + { + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('Broken on HHVM.'); + } + + $matcher = arrayContaining(array(1, 2, 3)); + $this->assertMismatchDescription('was null', $matcher, null); + $this->assertMismatchDescription('No item matched: <1>', $matcher, array()); + $this->assertMismatchDescription('No item matched: <2>', $matcher, array(1)); + $this->assertMismatchDescription('item with key 0: was <4>', $matcher, array(4, 3, 2, 1)); + $this->assertMismatchDescription('item with key 2: was <4>', $matcher, array(1, 2, 4)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingKeyTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingKeyTest.php new file mode 100644 index 00000000..31770d8d --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingKeyTest.php @@ -0,0 +1,62 @@ +1); + + $this->assertMatches(hasKey('a'), $array, 'Matches single key'); + } + + public function testMatchesArrayContainingKey() + { + $array = array('a'=>1, 'b'=>2, 'c'=>3); + + $this->assertMatches(hasKey('a'), $array, 'Matches a'); + $this->assertMatches(hasKey('c'), $array, 'Matches c'); + } + + public function testMatchesArrayContainingKeyWithIntegerKeys() + { + $array = array(1=>'A', 2=>'B'); + + assertThat($array, hasKey(1)); + } + + public function testMatchesArrayContainingKeyWithNumberKeys() + { + $array = array(1=>'A', 2=>'B'); + + assertThat($array, hasKey(1)); + + // very ugly version! + assertThat($array, IsArrayContainingKey::hasKeyInArray(2)); + } + + public function testHasReadableDescription() + { + $this->assertDescription('array with key "a"', hasKey('a')); + } + + public function testDoesNotMatchEmptyArray() + { + $this->assertMismatchDescription('array was []', hasKey('Foo'), array()); + } + + public function testDoesNotMatchArrayMissingKey() + { + $array = array('a'=>1, 'b'=>2, 'c'=>3); + + $this->assertMismatchDescription('array was ["a" => <1>, "b" => <2>, "c" => <3>]', hasKey('d'), $array); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingKeyValuePairTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingKeyValuePairTest.php new file mode 100644 index 00000000..a415f9f7 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingKeyValuePairTest.php @@ -0,0 +1,36 @@ +1, 'b'=>2); + + $this->assertMatches(hasKeyValuePair(equalTo('a'), equalTo(1)), $array, 'matcherA'); + $this->assertMatches(hasKeyValuePair(equalTo('b'), equalTo(2)), $array, 'matcherB'); + $this->assertMismatchDescription( + 'array was ["a" => <1>, "b" => <2>]', + hasKeyValuePair(equalTo('c'), equalTo(3)), + $array + ); + } + + public function testDoesNotMatchNull() + { + $this->assertMismatchDescription('was null', hasKeyValuePair(anything(), anything()), null); + } + + public function testHasReadableDescription() + { + $this->assertDescription('array containing ["a" => <2>]', hasKeyValuePair(equalTo('a'), equalTo(2))); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingTest.php new file mode 100644 index 00000000..8d5bd810 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayContainingTest.php @@ -0,0 +1,50 @@ +assertMatches( + hasItemInArray('a'), + array('a', 'b', 'c'), + "should matches array that contains 'a'" + ); + } + + public function testDoesNotMatchAnArrayThatDoesntContainAnElementMatchingTheGivenMatcher() + { + $this->assertDoesNotMatch( + hasItemInArray('a'), + array('b', 'c'), + "should not matches array that doesn't contain 'a'" + ); + $this->assertDoesNotMatch( + hasItemInArray('a'), + array(), + 'should not match empty array' + ); + } + + public function testDoesNotMatchNull() + { + $this->assertDoesNotMatch( + hasItemInArray('a'), + null, + 'should not match null' + ); + } + + public function testHasAReadableDescription() + { + $this->assertDescription('an array containing "a"', hasItemInArray('a')); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayTest.php new file mode 100644 index 00000000..e4db53e7 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayTest.php @@ -0,0 +1,89 @@ +assertMatches( + anArray(array(equalTo('a'), equalTo('b'), equalTo('c'))), + array('a', 'b', 'c'), + 'should match array with matching elements' + ); + } + + public function testDoesNotMatchAnArrayWhenElementsDoNotMatch() + { + $this->assertDoesNotMatch( + anArray(array(equalTo('a'), equalTo('b'))), + array('b', 'c'), + 'should not match array with different elements' + ); + } + + public function testDoesNotMatchAnArrayOfDifferentSize() + { + $this->assertDoesNotMatch( + anArray(array(equalTo('a'), equalTo('b'))), + array('a', 'b', 'c'), + 'should not match larger array' + ); + $this->assertDoesNotMatch( + anArray(array(equalTo('a'), equalTo('b'))), + array('a'), + 'should not match smaller array' + ); + } + + public function testDoesNotMatchNull() + { + $this->assertDoesNotMatch( + anArray(array(equalTo('a'))), + null, + 'should not match null' + ); + } + + public function testHasAReadableDescription() + { + $this->assertDescription( + '["a", "b"]', + anArray(array(equalTo('a'), equalTo('b'))) + ); + } + + public function testHasAReadableMismatchDescriptionWhenKeysDontMatch() + { + $this->assertMismatchDescription( + 'array keys were [<1>, <2>]', + anArray(array(equalTo('a'), equalTo('b'))), + array(1 => 'a', 2 => 'b') + ); + } + + public function testSupportsMatchesAssociativeArrays() + { + $this->assertMatches( + anArray(array('x'=>equalTo('a'), 'y'=>equalTo('b'), 'z'=>equalTo('c'))), + array('x'=>'a', 'y'=>'b', 'z'=>'c'), + 'should match associative array with matching elements' + ); + } + + public function testDoesNotMatchAnAssociativeArrayWhenKeysDoNotMatch() + { + $this->assertDoesNotMatch( + anArray(array('x'=>equalTo('a'), 'y'=>equalTo('b'))), + array('x'=>'b', 'z'=>'c'), + 'should not match array with different keys' + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayWithSizeTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayWithSizeTest.php new file mode 100644 index 00000000..8413c896 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Array/IsArrayWithSizeTest.php @@ -0,0 +1,37 @@ +assertMatches(arrayWithSize(equalTo(3)), array(1, 2, 3), 'correct size'); + $this->assertDoesNotMatch(arrayWithSize(equalTo(2)), array(1, 2, 3), 'incorrect size'); + } + + public function testProvidesConvenientShortcutForArrayWithSizeEqualTo() + { + $this->assertMatches(arrayWithSize(3), array(1, 2, 3), 'correct size'); + $this->assertDoesNotMatch(arrayWithSize(2), array(1, 2, 3), 'incorrect size'); + } + + public function testEmptyArray() + { + $this->assertMatches(emptyArray(), array(), 'correct size'); + $this->assertDoesNotMatch(emptyArray(), array(1), 'incorrect size'); + } + + public function testHasAReadableDescription() + { + $this->assertDescription('an array with size <3>', arrayWithSize(equalTo(3))); + $this->assertDescription('an empty array', emptyArray()); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/BaseMatcherTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/BaseMatcherTest.php new file mode 100644 index 00000000..833e2c3e --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/BaseMatcherTest.php @@ -0,0 +1,23 @@ +appendText('SOME DESCRIPTION'); + } + + public function testDescribesItselfWithToStringMethod() + { + $someMatcher = new \Hamcrest\SomeMatcher(); + $this->assertEquals('SOME DESCRIPTION', (string) $someMatcher); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Collection/IsEmptyTraversableTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Collection/IsEmptyTraversableTest.php new file mode 100644 index 00000000..2f15fb49 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Collection/IsEmptyTraversableTest.php @@ -0,0 +1,77 @@ +assertMatches( + emptyTraversable(), + new \ArrayObject(array()), + 'an empty traversable' + ); + } + + public function testEmptyMatcherDoesNotMatchWhenNotEmpty() + { + $this->assertDoesNotMatch( + emptyTraversable(), + new \ArrayObject(array(1, 2, 3)), + 'a non-empty traversable' + ); + } + + public function testEmptyMatcherDoesNotMatchNull() + { + $this->assertDoesNotMatch( + emptyTraversable(), + null, + 'should not match null' + ); + } + + public function testEmptyMatcherHasAReadableDescription() + { + $this->assertDescription('an empty traversable', emptyTraversable()); + } + + public function testNonEmptyDoesNotMatchNull() + { + $this->assertDoesNotMatch( + nonEmptyTraversable(), + null, + 'should not match null' + ); + } + + public function testNonEmptyDoesNotMatchWhenEmpty() + { + $this->assertDoesNotMatch( + nonEmptyTraversable(), + new \ArrayObject(array()), + 'an empty traversable' + ); + } + + public function testNonEmptyMatchesWhenNotEmpty() + { + $this->assertMatches( + nonEmptyTraversable(), + new \ArrayObject(array(1, 2, 3)), + 'a non-empty traversable' + ); + } + + public function testNonEmptyNonEmptyMatcherHasAReadableDescription() + { + $this->assertDescription('a non-empty traversable', nonEmptyTraversable()); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Collection/IsTraversableWithSizeTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Collection/IsTraversableWithSizeTest.php new file mode 100644 index 00000000..c1c67a7a --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Collection/IsTraversableWithSizeTest.php @@ -0,0 +1,57 @@ +assertMatches( + traversableWithSize(equalTo(3)), + new \ArrayObject(array(1, 2, 3)), + 'correct size' + ); + } + + public function testDoesNotMatchWhenSizeIsIncorrect() + { + $this->assertDoesNotMatch( + traversableWithSize(equalTo(2)), + new \ArrayObject(array(1, 2, 3)), + 'incorrect size' + ); + } + + public function testDoesNotMatchNull() + { + $this->assertDoesNotMatch( + traversableWithSize(3), + null, + 'should not match null' + ); + } + + public function testProvidesConvenientShortcutForTraversableWithSizeEqualTo() + { + $this->assertMatches( + traversableWithSize(3), + new \ArrayObject(array(1, 2, 3)), + 'correct size' + ); + } + + public function testHasAReadableDescription() + { + $this->assertDescription( + 'a traversable with size <3>', + traversableWithSize(equalTo(3)) + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/AllOfTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/AllOfTest.php new file mode 100644 index 00000000..86b8c277 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/AllOfTest.php @@ -0,0 +1,56 @@ +assertDescription( + '("good" and "bad" and "ugly")', + allOf('good', 'bad', 'ugly') + ); + } + + public function testMismatchDescriptionDescribesFirstFailingMatch() + { + $this->assertMismatchDescription( + '"good" was "bad"', + allOf('bad', 'good'), + 'bad' + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/AnyOfTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/AnyOfTest.php new file mode 100644 index 00000000..3d62b935 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/AnyOfTest.php @@ -0,0 +1,79 @@ +assertDescription( + '("good" or "bad" or "ugly")', + anyOf('good', 'bad', 'ugly') + ); + } + + public function testNoneOfEvaluatesToTheLogicalDisjunctionOfTwoOtherMatchers() + { + assertThat('good', not(noneOf('bad', 'good'))); + assertThat('good', not(noneOf('good', 'good'))); + assertThat('good', not(noneOf('good', 'bad'))); + + assertThat('good', noneOf('bad', startsWith('b'))); + } + + public function testNoneOfEvaluatesToTheLogicalDisjunctionOfManyOtherMatchers() + { + assertThat('good', not(noneOf('bad', 'good', 'bad', 'bad', 'bad'))); + assertThat('good', noneOf('bad', 'bad', 'bad', 'bad', 'bad')); + } + + public function testNoneOfSupportsMixedTypes() + { + $combined = noneOf( + equalTo(new \Hamcrest\Core\SampleBaseClass('good')), + equalTo(new \Hamcrest\Core\SampleBaseClass('ugly')), + equalTo(new \Hamcrest\Core\SampleSubClass('good')) + ); + + assertThat(new \Hamcrest\Core\SampleSubClass('bad'), $combined); + } + + public function testNoneOfHasAReadableDescription() + { + $this->assertDescription( + 'not ("good" or "bad" or "ugly")', + noneOf('good', 'bad', 'ugly') + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/CombinableMatcherTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/CombinableMatcherTest.php new file mode 100644 index 00000000..463c7543 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/CombinableMatcherTest.php @@ -0,0 +1,59 @@ +_either_3_or_4 = \Hamcrest\Core\CombinableMatcher::either(equalTo(3))->orElse(equalTo(4)); + $this->_not_3_and_not_4 = \Hamcrest\Core\CombinableMatcher::both(not(equalTo(3)))->andAlso(not(equalTo(4))); + } + + protected function createMatcher() + { + return \Hamcrest\Core\CombinableMatcher::either(equalTo('irrelevant'))->orElse(equalTo('ignored')); + } + + public function testBothAcceptsAndRejects() + { + assertThat(2, $this->_not_3_and_not_4); + assertThat(3, not($this->_not_3_and_not_4)); + } + + public function testAcceptsAndRejectsThreeAnds() + { + $tripleAnd = $this->_not_3_and_not_4->andAlso(equalTo(2)); + assertThat(2, $tripleAnd); + assertThat(3, not($tripleAnd)); + } + + public function testBothDescribesItself() + { + $this->assertEquals('(not <3> and not <4>)', (string) $this->_not_3_and_not_4); + $this->assertMismatchDescription('was <3>', $this->_not_3_and_not_4, 3); + } + + public function testEitherAcceptsAndRejects() + { + assertThat(3, $this->_either_3_or_4); + assertThat(6, not($this->_either_3_or_4)); + } + + public function testAcceptsAndRejectsThreeOrs() + { + $orTriple = $this->_either_3_or_4->orElse(greaterThan(10)); + + assertThat(11, $orTriple); + assertThat(9, not($orTriple)); + } + + public function testEitherDescribesItself() + { + $this->assertEquals('(<3> or <4>)', (string) $this->_either_3_or_4); + $this->assertMismatchDescription('was <6>', $this->_either_3_or_4, 6); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/DescribedAsTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/DescribedAsTest.php new file mode 100644 index 00000000..673ab41e --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/DescribedAsTest.php @@ -0,0 +1,36 @@ +assertDescription('m1 description', $m1); + $this->assertDescription('m2 description', $m2); + } + + public function testAppendsValuesToDescription() + { + $m = describedAs('value 1 = %0, value 2 = %1', anything(), 33, 97); + + $this->assertDescription('value 1 = <33>, value 2 = <97>', $m); + } + + public function testDelegatesMatchingToAnotherMatcher() + { + $m1 = describedAs('irrelevant', anything()); + $m2 = describedAs('irrelevant', not(anything())); + + $this->assertTrue($m1->matches(new \stdClass())); + $this->assertFalse($m2->matches('hi')); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/EveryTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/EveryTest.php new file mode 100644 index 00000000..5eb153c5 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/EveryTest.php @@ -0,0 +1,30 @@ +assertEquals('every item is a string containing "a"', (string) $each); + + $this->assertMismatchDescription('an item was "BbB"', $each, array('BbB')); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/HasToStringTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/HasToStringTest.php new file mode 100644 index 00000000..e2e136dc --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/HasToStringTest.php @@ -0,0 +1,108 @@ +assertMatches( + hasToString(equalTo('php')), + new \Hamcrest\Core\PhpForm(), + 'correct __toString' + ); + $this->assertMatches( + hasToString(equalTo('java')), + new \Hamcrest\Core\JavaForm(), + 'correct toString' + ); + } + + public function testPicksJavaOverPhpToString() + { + $this->assertMatches( + hasToString(equalTo('java')), + new \Hamcrest\Core\BothForms(), + 'correct toString' + ); + } + + public function testDoesNotMatchWhenToStringDoesNotMatch() + { + $this->assertDoesNotMatch( + hasToString(equalTo('mismatch')), + new \Hamcrest\Core\PhpForm(), + 'incorrect __toString' + ); + $this->assertDoesNotMatch( + hasToString(equalTo('mismatch')), + new \Hamcrest\Core\JavaForm(), + 'incorrect toString' + ); + $this->assertDoesNotMatch( + hasToString(equalTo('mismatch')), + new \Hamcrest\Core\BothForms(), + 'incorrect __toString' + ); + } + + public function testDoesNotMatchNull() + { + $this->assertDoesNotMatch( + hasToString(equalTo('a')), + null, + 'should not match null' + ); + } + + public function testProvidesConvenientShortcutForTraversableWithSizeEqualTo() + { + $this->assertMatches( + hasToString(equalTo('php')), + new \Hamcrest\Core\PhpForm(), + 'correct __toString' + ); + } + + public function testHasAReadableDescription() + { + $this->assertDescription( + 'an object with toString() "php"', + hasToString(equalTo('php')) + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsAnythingTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsAnythingTest.php new file mode 100644 index 00000000..f68032e5 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsAnythingTest.php @@ -0,0 +1,29 @@ +assertDescription('ANYTHING', anything()); + } + + public function testCanOverrideDescription() + { + $description = 'description'; + $this->assertDescription($description, anything($description)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsCollectionContainingTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsCollectionContainingTest.php new file mode 100644 index 00000000..a3929b54 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsCollectionContainingTest.php @@ -0,0 +1,91 @@ +assertMatches( + $itemMatcher, + array('a', 'b', 'c'), + "should match list that contains 'a'" + ); + } + + public function testDoesNotMatchCollectionThatDoesntContainAnElementMatchingTheGivenMatcher() + { + $matcher1 = hasItem(equalTo('a')); + $this->assertDoesNotMatch( + $matcher1, + array('b', 'c'), + "should not match list that doesn't contain 'a'" + ); + + $matcher2 = hasItem(equalTo('a')); + $this->assertDoesNotMatch( + $matcher2, + array(), + 'should not match the empty list' + ); + } + + public function testDoesNotMatchNull() + { + $this->assertDoesNotMatch( + hasItem(equalTo('a')), + null, + 'should not match null' + ); + } + + public function testHasAReadableDescription() + { + $this->assertDescription('a collection containing "a"', hasItem(equalTo('a'))); + } + + public function testMatchesAllItemsInCollection() + { + $matcher1 = hasItems(equalTo('a'), equalTo('b'), equalTo('c')); + $this->assertMatches( + $matcher1, + array('a', 'b', 'c'), + 'should match list containing all items' + ); + + $matcher2 = hasItems('a', 'b', 'c'); + $this->assertMatches( + $matcher2, + array('a', 'b', 'c'), + 'should match list containing all items (without matchers)' + ); + + $matcher3 = hasItems(equalTo('a'), equalTo('b'), equalTo('c')); + $this->assertMatches( + $matcher3, + array('c', 'b', 'a'), + 'should match list containing all items in any order' + ); + + $matcher4 = hasItems(equalTo('a'), equalTo('b'), equalTo('c')); + $this->assertMatches( + $matcher4, + array('e', 'c', 'b', 'a', 'd'), + 'should match list containing all items plus others' + ); + + $matcher5 = hasItems(equalTo('a'), equalTo('b'), equalTo('c')); + $this->assertDoesNotMatch( + $matcher5, + array('e', 'c', 'b', 'd'), // 'a' missing + 'should not match list unless it contains all items' + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsEqualTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsEqualTest.php new file mode 100644 index 00000000..73e3ff07 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsEqualTest.php @@ -0,0 +1,102 @@ +_arg = $arg; + } + + public function __toString() + { + return $this->_arg; + } +} + +class IsEqualTest extends \Hamcrest\AbstractMatcherTest +{ + + protected function createMatcher() + { + return \Hamcrest\Core\IsEqual::equalTo('irrelevant'); + } + + public function testComparesObjectsUsingEqualityOperator() + { + assertThat("hi", equalTo("hi")); + assertThat("bye", not(equalTo("hi"))); + + assertThat(1, equalTo(1)); + assertThat(1, not(equalTo(2))); + + assertThat("2", equalTo(2)); + } + + public function testCanCompareNullValues() + { + assertThat(null, equalTo(null)); + + assertThat(null, not(equalTo('hi'))); + assertThat('hi', not(equalTo(null))); + } + + public function testComparesTheElementsOfAnArray() + { + $s1 = array('a', 'b'); + $s2 = array('a', 'b'); + $s3 = array('c', 'd'); + $s4 = array('a', 'b', 'c', 'd'); + + assertThat($s1, equalTo($s1)); + assertThat($s2, equalTo($s1)); + assertThat($s3, not(equalTo($s1))); + assertThat($s4, not(equalTo($s1))); + } + + public function testComparesTheElementsOfAnArrayOfPrimitiveTypes() + { + $i1 = array(1, 2); + $i2 = array(1, 2); + $i3 = array(3, 4); + $i4 = array(1, 2, 3, 4); + + assertThat($i1, equalTo($i1)); + assertThat($i2, equalTo($i1)); + assertThat($i3, not(equalTo($i1))); + assertThat($i4, not(equalTo($i1))); + } + + public function testRecursivelyTestsElementsOfArrays() + { + $i1 = array(array(1, 2), array(3, 4)); + $i2 = array(array(1, 2), array(3, 4)); + $i3 = array(array(5, 6), array(7, 8)); + $i4 = array(array(1, 2, 3, 4), array(3, 4)); + + assertThat($i1, equalTo($i1)); + assertThat($i2, equalTo($i1)); + assertThat($i3, not(equalTo($i1))); + assertThat($i4, not(equalTo($i1))); + } + + public function testIncludesTheResultOfCallingToStringOnItsArgumentInTheDescription() + { + $argumentDescription = 'ARGUMENT DESCRIPTION'; + $argument = new \Hamcrest\Core\DummyToStringClass($argumentDescription); + $this->assertDescription('<' . $argumentDescription . '>', equalTo($argument)); + } + + public function testReturnsAnObviousDescriptionIfCreatedWithANestedMatcherByMistake() + { + $innerMatcher = equalTo('NestedMatcher'); + $this->assertDescription('<' . (string) $innerMatcher . '>', equalTo($innerMatcher)); + } + + public function testReturnsGoodDescriptionIfCreatedWithNullReference() + { + $this->assertDescription('null', equalTo(null)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsIdenticalTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsIdenticalTest.php new file mode 100644 index 00000000..9cc27946 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsIdenticalTest.php @@ -0,0 +1,30 @@ +assertDescription('"ARG"', identicalTo('ARG')); + } + + public function testReturnsReadableDescriptionFromToStringWhenInitialisedWithNull() + { + $this->assertDescription('null', identicalTo(null)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsInstanceOfTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsInstanceOfTest.php new file mode 100644 index 00000000..f74cfdb5 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsInstanceOfTest.php @@ -0,0 +1,51 @@ +_baseClassInstance = new \Hamcrest\Core\SampleBaseClass('good'); + $this->_subClassInstance = new \Hamcrest\Core\SampleSubClass('good'); + } + + protected function createMatcher() + { + return \Hamcrest\Core\IsInstanceOf::anInstanceOf('stdClass'); + } + + public function testEvaluatesToTrueIfArgumentIsInstanceOfASpecificClass() + { + assertThat($this->_baseClassInstance, anInstanceOf('Hamcrest\Core\SampleBaseClass')); + assertThat($this->_subClassInstance, anInstanceOf('Hamcrest\Core\SampleSubClass')); + assertThat(null, not(anInstanceOf('Hamcrest\Core\SampleBaseClass'))); + assertThat(new \stdClass(), not(anInstanceOf('Hamcrest\Core\SampleBaseClass'))); + } + + public function testEvaluatesToFalseIfArgumentIsNotAnObject() + { + assertThat(null, not(anInstanceOf('Hamcrest\Core\SampleBaseClass'))); + assertThat(false, not(anInstanceOf('Hamcrest\Core\SampleBaseClass'))); + assertThat(5, not(anInstanceOf('Hamcrest\Core\SampleBaseClass'))); + assertThat('foo', not(anInstanceOf('Hamcrest\Core\SampleBaseClass'))); + assertThat(array(1, 2, 3), not(anInstanceOf('Hamcrest\Core\SampleBaseClass'))); + } + + public function testHasAReadableDescription() + { + $this->assertDescription('an instance of stdClass', anInstanceOf('stdClass')); + } + + public function testDecribesActualClassInMismatchMessage() + { + $this->assertMismatchDescription( + '[Hamcrest\Core\SampleBaseClass] ', + anInstanceOf('Hamcrest\Core\SampleSubClass'), + $this->_baseClassInstance + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsNotTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsNotTest.php new file mode 100644 index 00000000..09d4a652 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsNotTest.php @@ -0,0 +1,31 @@ +assertMatches(not(equalTo('A')), 'B', 'should match'); + $this->assertDoesNotMatch(not(equalTo('B')), 'B', 'should not match'); + } + + public function testProvidesConvenientShortcutForNotEqualTo() + { + $this->assertMatches(not('A'), 'B', 'should match'); + $this->assertMatches(not('B'), 'A', 'should match'); + $this->assertDoesNotMatch(not('A'), 'A', 'should not match'); + $this->assertDoesNotMatch(not('B'), 'B', 'should not match'); + } + + public function testUsesDescriptionOfNegatedMatcherWithPrefix() + { + $this->assertDescription('not a value greater than <2>', not(greaterThan(2))); + $this->assertDescription('not "A"', not('A')); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsNullTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsNullTest.php new file mode 100644 index 00000000..bfa42554 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsNullTest.php @@ -0,0 +1,20 @@ +assertDescription('sameInstance("ARG")', sameInstance('ARG')); + } + + public function testReturnsReadableDescriptionFromToStringWhenInitialisedWithNull() + { + $this->assertDescription('sameInstance(null)', sameInstance(null)); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsTest.php new file mode 100644 index 00000000..bbd848b9 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsTest.php @@ -0,0 +1,33 @@ +assertMatches(is(equalTo(true)), true, 'should match'); + $this->assertMatches(is(equalTo(false)), false, 'should match'); + $this->assertDoesNotMatch(is(equalTo(true)), false, 'should not match'); + $this->assertDoesNotMatch(is(equalTo(false)), true, 'should not match'); + } + + public function testGeneratesIsPrefixInDescription() + { + $this->assertDescription('is ', is(equalTo(true))); + } + + public function testProvidesConvenientShortcutForIsEqualTo() + { + $this->assertMatches(is('A'), 'A', 'should match'); + $this->assertMatches(is('B'), 'B', 'should match'); + $this->assertDoesNotMatch(is('A'), 'B', 'should not match'); + $this->assertDoesNotMatch(is('B'), 'A', 'should not match'); + $this->assertDescription('is "A"', is('A')); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsTypeOfTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsTypeOfTest.php new file mode 100644 index 00000000..3f48dea7 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/IsTypeOfTest.php @@ -0,0 +1,45 @@ +assertDescription('a double', typeOf('double')); + $this->assertDescription('an integer', typeOf('integer')); + } + + public function testDecribesActualTypeInMismatchMessage() + { + $this->assertMismatchDescription('was null', typeOf('boolean'), null); + $this->assertMismatchDescription('was an integer <5>', typeOf('float'), 5); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/SampleBaseClass.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/SampleBaseClass.php new file mode 100644 index 00000000..c953e7cd --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/SampleBaseClass.php @@ -0,0 +1,18 @@ +_arg = $arg; + } + + public function __toString() + { + return $this->_arg; + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/SampleSubClass.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/SampleSubClass.php new file mode 100644 index 00000000..822f1b64 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Core/SampleSubClass.php @@ -0,0 +1,6 @@ +_instanceProperty); + } + + protected function createMatcher() + { + return \Hamcrest\Core\Set::set('property_name'); + } + + public function testEvaluatesToTrueIfArrayPropertyIsSet() + { + assertThat(array('foo' => 'bar'), set('foo')); + } + + public function testNegatedEvaluatesToFalseIfArrayPropertyIsSet() + { + assertThat(array('foo' => 'bar'), not(notSet('foo'))); + } + + public function testEvaluatesToTrueIfClassPropertyIsSet() + { + self::$_classProperty = 'bar'; + assertThat('Hamcrest\Core\SetTest', set('_classProperty')); + } + + public function testNegatedEvaluatesToFalseIfClassPropertyIsSet() + { + self::$_classProperty = 'bar'; + assertThat('Hamcrest\Core\SetTest', not(notSet('_classProperty'))); + } + + public function testEvaluatesToTrueIfObjectPropertyIsSet() + { + $this->_instanceProperty = 'bar'; + assertThat($this, set('_instanceProperty')); + } + + public function testNegatedEvaluatesToFalseIfObjectPropertyIsSet() + { + $this->_instanceProperty = 'bar'; + assertThat($this, not(notSet('_instanceProperty'))); + } + + public function testEvaluatesToFalseIfArrayPropertyIsNotSet() + { + assertThat(array('foo' => 'bar'), not(set('baz'))); + } + + public function testNegatedEvaluatesToTrueIfArrayPropertyIsNotSet() + { + assertThat(array('foo' => 'bar'), notSet('baz')); + } + + public function testEvaluatesToFalseIfClassPropertyIsNotSet() + { + assertThat('Hamcrest\Core\SetTest', not(set('_classProperty'))); + } + + public function testNegatedEvaluatesToTrueIfClassPropertyIsNotSet() + { + assertThat('Hamcrest\Core\SetTest', notSet('_classProperty')); + } + + public function testEvaluatesToFalseIfObjectPropertyIsNotSet() + { + assertThat($this, not(set('_instanceProperty'))); + } + + public function testNegatedEvaluatesToTrueIfObjectPropertyIsNotSet() + { + assertThat($this, notSet('_instanceProperty')); + } + + public function testHasAReadableDescription() + { + $this->assertDescription('set property foo', set('foo')); + $this->assertDescription('unset property bar', notSet('bar')); + } + + public function testDecribesPropertySettingInMismatchMessage() + { + $this->assertMismatchDescription( + 'was not set', + set('bar'), + array('foo' => 'bar') + ); + $this->assertMismatchDescription( + 'was "bar"', + notSet('foo'), + array('foo' => 'bar') + ); + self::$_classProperty = 'bar'; + $this->assertMismatchDescription( + 'was "bar"', + notSet('_classProperty'), + 'Hamcrest\Core\SetTest' + ); + $this->_instanceProperty = 'bar'; + $this->assertMismatchDescription( + 'was "bar"', + notSet('_instanceProperty'), + $this + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/FeatureMatcherTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/FeatureMatcherTest.php new file mode 100644 index 00000000..1b023049 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/FeatureMatcherTest.php @@ -0,0 +1,73 @@ +_result = $result; + } + public function getResult() + { + return $this->_result; + } +} + +/* Test-specific subclass only */ +class ResultMatcher extends \Hamcrest\FeatureMatcher +{ + public function __construct() + { + parent::__construct(self::TYPE_ANY, null, equalTo('bar'), 'Thingy with result', 'result'); + } + public function featureValueOf($actual) + { + if ($actual instanceof \Hamcrest\Thingy) { + return $actual->getResult(); + } + } +} + +class FeatureMatcherTest extends \Hamcrest\AbstractMatcherTest +{ + + private $_resultMatcher; + + protected function setUp() + { + $this->_resultMatcher = $this->_resultMatcher(); + } + + protected function createMatcher() + { + return $this->_resultMatcher(); + } + + public function testMatchesPartOfAnObject() + { + $this->assertMatches($this->_resultMatcher, new \Hamcrest\Thingy('bar'), 'feature'); + $this->assertDescription('Thingy with result "bar"', $this->_resultMatcher); + } + + public function testMismatchesPartOfAnObject() + { + $this->assertMismatchDescription( + 'result was "foo"', + $this->_resultMatcher, + new \Hamcrest\Thingy('foo') + ); + } + + public function testDoesNotGenerateNoticesForNull() + { + $this->assertMismatchDescription('result was null', $this->_resultMatcher, null); + } + + // -- Creation Methods + + private function _resultMatcher() + { + return new \Hamcrest\ResultMatcher(); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/InvokedMatcherTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/InvokedMatcherTest.php new file mode 100644 index 00000000..dfa77006 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/InvokedMatcherTest.php @@ -0,0 +1,31 @@ +matchAgainst = $matchAgainst; + } + + public function matches($item) + { + return $item == $this->matchAgainst; + } + +} + +class InvokedMatcherTest extends TestCase +{ + public function testInvokedMatchersCallMatches() + { + $sampleMatcher = new SampleInvokeMatcher('foo'); + + $this->assertTrue($sampleMatcher('foo')); + $this->assertFalse($sampleMatcher('bar')); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/MatcherAssertTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/MatcherAssertTest.php new file mode 100644 index 00000000..dc12fba5 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/MatcherAssertTest.php @@ -0,0 +1,192 @@ +getMessage()); + } + try { + \Hamcrest\MatcherAssert::assertThat(null); + self::fail('expected assertion failure'); + } catch (\Hamcrest\AssertionError $ex) { + self::assertEquals('', $ex->getMessage()); + } + try { + \Hamcrest\MatcherAssert::assertThat(''); + self::fail('expected assertion failure'); + } catch (\Hamcrest\AssertionError $ex) { + self::assertEquals('', $ex->getMessage()); + } + try { + \Hamcrest\MatcherAssert::assertThat(0); + self::fail('expected assertion failure'); + } catch (\Hamcrest\AssertionError $ex) { + self::assertEquals('', $ex->getMessage()); + } + try { + \Hamcrest\MatcherAssert::assertThat(0.0); + self::fail('expected assertion failure'); + } catch (\Hamcrest\AssertionError $ex) { + self::assertEquals('', $ex->getMessage()); + } + try { + \Hamcrest\MatcherAssert::assertThat(array()); + self::fail('expected assertion failure'); + } catch (\Hamcrest\AssertionError $ex) { + self::assertEquals('', $ex->getMessage()); + } + self::assertEquals(6, \Hamcrest\MatcherAssert::getCount(), 'assertion count'); + } + + public function testAssertThatWithIdentifierAndTrueArgPasses() + { + \Hamcrest\MatcherAssert::assertThat('identifier', true); + \Hamcrest\MatcherAssert::assertThat('identifier', 'non-empty'); + \Hamcrest\MatcherAssert::assertThat('identifier', 1); + \Hamcrest\MatcherAssert::assertThat('identifier', 3.14159); + \Hamcrest\MatcherAssert::assertThat('identifier', array(true)); + self::assertEquals(5, \Hamcrest\MatcherAssert::getCount(), 'assertion count'); + } + + public function testAssertThatWithIdentifierAndFalseArgFails() + { + try { + \Hamcrest\MatcherAssert::assertThat('identifier', false); + self::fail('expected assertion failure'); + } catch (\Hamcrest\AssertionError $ex) { + self::assertEquals('identifier', $ex->getMessage()); + } + try { + \Hamcrest\MatcherAssert::assertThat('identifier', null); + self::fail('expected assertion failure'); + } catch (\Hamcrest\AssertionError $ex) { + self::assertEquals('identifier', $ex->getMessage()); + } + try { + \Hamcrest\MatcherAssert::assertThat('identifier', ''); + self::fail('expected assertion failure'); + } catch (\Hamcrest\AssertionError $ex) { + self::assertEquals('identifier', $ex->getMessage()); + } + try { + \Hamcrest\MatcherAssert::assertThat('identifier', 0); + self::fail('expected assertion failure'); + } catch (\Hamcrest\AssertionError $ex) { + self::assertEquals('identifier', $ex->getMessage()); + } + try { + \Hamcrest\MatcherAssert::assertThat('identifier', 0.0); + self::fail('expected assertion failure'); + } catch (\Hamcrest\AssertionError $ex) { + self::assertEquals('identifier', $ex->getMessage()); + } + try { + \Hamcrest\MatcherAssert::assertThat('identifier', array()); + self::fail('expected assertion failure'); + } catch (\Hamcrest\AssertionError $ex) { + self::assertEquals('identifier', $ex->getMessage()); + } + self::assertEquals(6, \Hamcrest\MatcherAssert::getCount(), 'assertion count'); + } + + public function testAssertThatWithActualValueAndMatcherArgsThatMatchPasses() + { + \Hamcrest\MatcherAssert::assertThat(true, is(true)); + self::assertEquals(1, \Hamcrest\MatcherAssert::getCount(), 'assertion count'); + } + + public function testAssertThatWithActualValueAndMatcherArgsThatDontMatchFails() + { + $expected = 'expected'; + $actual = 'actual'; + + $expectedMessage = + 'Expected: "expected"' . PHP_EOL . + ' but: was "actual"'; + + try { + \Hamcrest\MatcherAssert::assertThat($actual, equalTo($expected)); + self::fail('expected assertion failure'); + } catch (\Hamcrest\AssertionError $ex) { + self::assertEquals($expectedMessage, $ex->getMessage()); + self::assertEquals(1, \Hamcrest\MatcherAssert::getCount(), 'assertion count'); + } + } + + public function testAssertThatWithIdentifierAndActualValueAndMatcherArgsThatMatchPasses() + { + \Hamcrest\MatcherAssert::assertThat('identifier', true, is(true)); + self::assertEquals(1, \Hamcrest\MatcherAssert::getCount(), 'assertion count'); + } + + public function testAssertThatWithIdentifierAndActualValueAndMatcherArgsThatDontMatchFails() + { + $expected = 'expected'; + $actual = 'actual'; + + $expectedMessage = + 'identifier' . PHP_EOL . + 'Expected: "expected"' . PHP_EOL . + ' but: was "actual"'; + + try { + \Hamcrest\MatcherAssert::assertThat('identifier', $actual, equalTo($expected)); + self::fail('expected assertion failure'); + } catch (\Hamcrest\AssertionError $ex) { + self::assertEquals($expectedMessage, $ex->getMessage()); + self::assertEquals(1, \Hamcrest\MatcherAssert::getCount(), 'assertion count'); + } + } + + public function testAssertThatWithNoArgsThrowsErrorAndDoesntIncrementCount() + { + try { + \Hamcrest\MatcherAssert::assertThat(); + self::fail('expected invalid argument exception'); + } catch (\InvalidArgumentException $ex) { + self::assertEquals(0, \Hamcrest\MatcherAssert::getCount(), 'assertion count'); + } + } + + public function testAssertThatWithFourArgsThrowsErrorAndDoesntIncrementCount() + { + try { + \Hamcrest\MatcherAssert::assertThat(1, 2, 3, 4); + self::fail('expected invalid argument exception'); + } catch (\InvalidArgumentException $ex) { + self::assertEquals(0, \Hamcrest\MatcherAssert::getCount(), 'assertion count'); + } + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Number/IsCloseToTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Number/IsCloseToTest.php new file mode 100644 index 00000000..987d5526 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Number/IsCloseToTest.php @@ -0,0 +1,27 @@ +assertTrue($p->matches(1.0)); + $this->assertTrue($p->matches(0.5)); + $this->assertTrue($p->matches(1.5)); + + $this->assertDoesNotMatch($p, 2.0, 'too large'); + $this->assertMismatchDescription('<2F> differed by <0.5F>', $p, 2.0); + $this->assertDoesNotMatch($p, 0.0, 'number too small'); + $this->assertMismatchDescription('<0F> differed by <0.5F>', $p, 0.0); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Number/OrderingComparisonTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Number/OrderingComparisonTest.php new file mode 100644 index 00000000..a4c94d37 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Number/OrderingComparisonTest.php @@ -0,0 +1,41 @@ +_text = $text; + } + + public function describeTo(\Hamcrest\Description $description) + { + $description->appendText($this->_text); + } +} + +class StringDescriptionTest extends TestCase +{ + + private $_description; + + protected function setUp() + { + $this->_description = new \Hamcrest\StringDescription(); + } + + public function testAppendTextAppendsTextInformation() + { + $this->_description->appendText('foo')->appendText('bar'); + $this->assertEquals('foobar', (string) $this->_description); + } + + public function testAppendValueCanAppendTextTypes() + { + $this->_description->appendValue('foo'); + $this->assertEquals('"foo"', (string) $this->_description); + } + + public function testSpecialCharactersAreEscapedForStringTypes() + { + $this->_description->appendValue("foo\\bar\"zip\r\n"); + $this->assertEquals('"foo\\bar\\"zip\r\n"', (string) $this->_description); + } + + public function testIntegerValuesCanBeAppended() + { + $this->_description->appendValue(42); + $this->assertEquals('<42>', (string) $this->_description); + } + + public function testFloatValuesCanBeAppended() + { + $this->_description->appendValue(42.78); + $this->assertEquals('<42.78F>', (string) $this->_description); + } + + public function testNullValuesCanBeAppended() + { + $this->_description->appendValue(null); + $this->assertEquals('null', (string) $this->_description); + } + + public function testArraysCanBeAppended() + { + $this->_description->appendValue(array('foo', 42.78)); + $this->assertEquals('["foo", <42.78F>]', (string) $this->_description); + } + + public function testObjectsCanBeAppended() + { + $this->_description->appendValue(new \stdClass()); + $this->assertEquals('', (string) $this->_description); + } + + public function testBooleanValuesCanBeAppended() + { + $this->_description->appendValue(false); + $this->assertEquals('', (string) $this->_description); + } + + public function testListsOfvaluesCanBeAppended() + { + $this->_description->appendValue(array('foo', 42.78)); + $this->assertEquals('["foo", <42.78F>]', (string) $this->_description); + } + + public function testIterableOfvaluesCanBeAppended() + { + $items = new \ArrayObject(array('foo', 42.78)); + $this->_description->appendValue($items); + $this->assertEquals('["foo", <42.78F>]', (string) $this->_description); + } + + public function testIteratorOfvaluesCanBeAppended() + { + $items = new \ArrayObject(array('foo', 42.78)); + $this->_description->appendValue($items->getIterator()); + $this->assertEquals('["foo", <42.78F>]', (string) $this->_description); + } + + public function testListsOfvaluesCanBeAppendedManually() + { + $this->_description->appendValueList('@start@', '@sep@ ', '@end@', array('foo', 42.78)); + $this->assertEquals('@start@"foo"@sep@ <42.78F>@end@', (string) $this->_description); + } + + public function testIterableOfvaluesCanBeAppendedManually() + { + $items = new \ArrayObject(array('foo', 42.78)); + $this->_description->appendValueList('@start@', '@sep@ ', '@end@', $items); + $this->assertEquals('@start@"foo"@sep@ <42.78F>@end@', (string) $this->_description); + } + + public function testIteratorOfvaluesCanBeAppendedManually() + { + $items = new \ArrayObject(array('foo', 42.78)); + $this->_description->appendValueList('@start@', '@sep@ ', '@end@', $items->getIterator()); + $this->assertEquals('@start@"foo"@sep@ <42.78F>@end@', (string) $this->_description); + } + + public function testSelfDescribingObjectsCanBeAppended() + { + $this->_description + ->appendDescriptionOf(new \Hamcrest\SampleSelfDescriber('foo')) + ->appendDescriptionOf(new \Hamcrest\SampleSelfDescriber('bar')) + ; + $this->assertEquals('foobar', (string) $this->_description); + } + + public function testSelfDescribingObjectsCanBeAppendedAsLists() + { + $this->_description->appendList('@start@', '@sep@ ', '@end@', array( + new \Hamcrest\SampleSelfDescriber('foo'), + new \Hamcrest\SampleSelfDescriber('bar') + )); + $this->assertEquals('@start@foo@sep@ bar@end@', (string) $this->_description); + } + + public function testSelfDescribingObjectsCanBeAppendedAsIteratedLists() + { + $items = new \ArrayObject(array( + new \Hamcrest\SampleSelfDescriber('foo'), + new \Hamcrest\SampleSelfDescriber('bar') + )); + $this->_description->appendList('@start@', '@sep@ ', '@end@', $items); + $this->assertEquals('@start@foo@sep@ bar@end@', (string) $this->_description); + } + + public function testSelfDescribingObjectsCanBeAppendedAsIterators() + { + $items = new \ArrayObject(array( + new \Hamcrest\SampleSelfDescriber('foo'), + new \Hamcrest\SampleSelfDescriber('bar') + )); + $this->_description->appendList('@start@', '@sep@ ', '@end@', $items->getIterator()); + $this->assertEquals('@start@foo@sep@ bar@end@', (string) $this->_description); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/IsEmptyStringTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/IsEmptyStringTest.php new file mode 100644 index 00000000..8d5c56be --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/IsEmptyStringTest.php @@ -0,0 +1,86 @@ +assertDoesNotMatch(emptyString(), null, 'null'); + } + + public function testEmptyDoesNotMatchZero() + { + $this->assertDoesNotMatch(emptyString(), 0, 'zero'); + } + + public function testEmptyDoesNotMatchFalse() + { + $this->assertDoesNotMatch(emptyString(), false, 'false'); + } + + public function testEmptyDoesNotMatchEmptyArray() + { + $this->assertDoesNotMatch(emptyString(), array(), 'empty array'); + } + + public function testEmptyMatchesEmptyString() + { + $this->assertMatches(emptyString(), '', 'empty string'); + } + + public function testEmptyDoesNotMatchNonEmptyString() + { + $this->assertDoesNotMatch(emptyString(), 'foo', 'non-empty string'); + } + + public function testEmptyHasAReadableDescription() + { + $this->assertDescription('an empty string', emptyString()); + } + + public function testEmptyOrNullMatchesNull() + { + $this->assertMatches(nullOrEmptyString(), null, 'null'); + } + + public function testEmptyOrNullMatchesEmptyString() + { + $this->assertMatches(nullOrEmptyString(), '', 'empty string'); + } + + public function testEmptyOrNullDoesNotMatchNonEmptyString() + { + $this->assertDoesNotMatch(nullOrEmptyString(), 'foo', 'non-empty string'); + } + + public function testEmptyOrNullHasAReadableDescription() + { + $this->assertDescription('(null or an empty string)', nullOrEmptyString()); + } + + public function testNonEmptyDoesNotMatchNull() + { + $this->assertDoesNotMatch(nonEmptyString(), null, 'null'); + } + + public function testNonEmptyDoesNotMatchEmptyString() + { + $this->assertDoesNotMatch(nonEmptyString(), '', 'empty string'); + } + + public function testNonEmptyMatchesNonEmptyString() + { + $this->assertMatches(nonEmptyString(), 'foo', 'non-empty string'); + } + + public function testNonEmptyHasAReadableDescription() + { + $this->assertDescription('a non-empty string', nonEmptyString()); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/IsEqualIgnoringCaseTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/IsEqualIgnoringCaseTest.php new file mode 100644 index 00000000..0539fd5c --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/IsEqualIgnoringCaseTest.php @@ -0,0 +1,40 @@ +assertDescription( + 'equalToIgnoringCase("heLLo")', + equalToIgnoringCase('heLLo') + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/IsEqualIgnoringWhiteSpaceTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/IsEqualIgnoringWhiteSpaceTest.php new file mode 100644 index 00000000..27ad338b --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/IsEqualIgnoringWhiteSpaceTest.php @@ -0,0 +1,51 @@ +_matcher = \Hamcrest\Text\IsEqualIgnoringWhiteSpace::equalToIgnoringWhiteSpace( + "Hello World how\n are we? " + ); + } + + protected function createMatcher() + { + return $this->_matcher; + } + + public function testPassesIfWordsAreSameButWhitespaceDiffers() + { + assertThat('Hello World how are we?', $this->_matcher); + assertThat(" Hello \rWorld \t how are\nwe?", $this->_matcher); + } + + public function testFailsIfTextOtherThanWhitespaceDiffers() + { + assertThat('Hello PLANET how are we?', not($this->_matcher)); + assertThat('Hello World how are we', not($this->_matcher)); + } + + public function testFailsIfWhitespaceIsAddedOrRemovedInMidWord() + { + assertThat('HelloWorld how are we?', not($this->_matcher)); + assertThat('Hello Wo rld how are we?', not($this->_matcher)); + } + + public function testFailsIfMatchingAgainstNull() + { + assertThat(null, not($this->_matcher)); + } + + public function testHasAReadableDescription() + { + $this->assertDescription( + "equalToIgnoringWhiteSpace(\"Hello World how\\n are we? \")", + $this->_matcher + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/MatchesPatternTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/MatchesPatternTest.php new file mode 100644 index 00000000..4891598f --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/MatchesPatternTest.php @@ -0,0 +1,30 @@ +assertDescription('a string matching "pattern"', matchesPattern('pattern')); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringContainsIgnoringCaseTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringContainsIgnoringCaseTest.php new file mode 100644 index 00000000..73023007 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringContainsIgnoringCaseTest.php @@ -0,0 +1,80 @@ +_stringContains = \Hamcrest\Text\StringContainsIgnoringCase::containsStringIgnoringCase( + strtolower(self::EXCERPT) + ); + } + + protected function createMatcher() + { + return $this->_stringContains; + } + + public function testEvaluatesToTrueIfArgumentContainsSpecifiedSubstring() + { + $this->assertTrue( + $this->_stringContains->matches(self::EXCERPT . 'END'), + 'should be true if excerpt at beginning' + ); + $this->assertTrue( + $this->_stringContains->matches('START' . self::EXCERPT), + 'should be true if excerpt at end' + ); + $this->assertTrue( + $this->_stringContains->matches('START' . self::EXCERPT . 'END'), + 'should be true if excerpt in middle' + ); + $this->assertTrue( + $this->_stringContains->matches(self::EXCERPT . self::EXCERPT), + 'should be true if excerpt is repeated' + ); + + $this->assertFalse( + $this->_stringContains->matches('Something else'), + 'should not be true if excerpt is not in string' + ); + $this->assertFalse( + $this->_stringContains->matches(substr(self::EXCERPT, 1)), + 'should not be true if part of excerpt is in string' + ); + } + + public function testEvaluatesToTrueIfArgumentIsEqualToSubstring() + { + $this->assertTrue( + $this->_stringContains->matches(self::EXCERPT), + 'should be true if excerpt is entire string' + ); + } + + public function testEvaluatesToTrueIfArgumentContainsExactSubstring() + { + $this->assertTrue( + $this->_stringContains->matches(strtolower(self::EXCERPT)), + 'should be false if excerpt is entire string ignoring case' + ); + $this->assertTrue( + $this->_stringContains->matches('START' . strtolower(self::EXCERPT) . 'END'), + 'should be false if excerpt is contained in string ignoring case' + ); + } + + public function testHasAReadableDescription() + { + $this->assertDescription( + 'a string containing in any case "' + . strtolower(self::EXCERPT) . '"', + $this->_stringContains + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringContainsInOrderTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringContainsInOrderTest.php new file mode 100644 index 00000000..4c465b29 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringContainsInOrderTest.php @@ -0,0 +1,42 @@ +_m = \Hamcrest\Text\StringContainsInOrder::stringContainsInOrder(array('a', 'b', 'c')); + } + + protected function createMatcher() + { + return $this->_m; + } + + public function testMatchesOnlyIfStringContainsGivenSubstringsInTheSameOrder() + { + $this->assertMatches($this->_m, 'abc', 'substrings in order'); + $this->assertMatches($this->_m, '1a2b3c4', 'substrings separated'); + + $this->assertDoesNotMatch($this->_m, 'cab', 'substrings out of order'); + $this->assertDoesNotMatch($this->_m, 'xyz', 'no substrings in string'); + $this->assertDoesNotMatch($this->_m, 'ac', 'substring missing'); + $this->assertDoesNotMatch($this->_m, '', 'empty string'); + } + + public function testAcceptsVariableArguments() + { + $this->assertMatches(stringContainsInOrder('a', 'b', 'c'), 'abc', 'substrings as variable arguments'); + } + + public function testHasAReadableDescription() + { + $this->assertDescription( + 'a string containing "a", "b", "c" in order', + $this->_m + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringContainsTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringContainsTest.php new file mode 100644 index 00000000..bf4afa3c --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringContainsTest.php @@ -0,0 +1,86 @@ +_stringContains = \Hamcrest\Text\StringContains::containsString(self::EXCERPT); + } + + protected function createMatcher() + { + return $this->_stringContains; + } + + public function testEvaluatesToTrueIfArgumentContainsSubstring() + { + $this->assertTrue( + $this->_stringContains->matches(self::EXCERPT . 'END'), + 'should be true if excerpt at beginning' + ); + $this->assertTrue( + $this->_stringContains->matches('START' . self::EXCERPT), + 'should be true if excerpt at end' + ); + $this->assertTrue( + $this->_stringContains->matches('START' . self::EXCERPT . 'END'), + 'should be true if excerpt in middle' + ); + $this->assertTrue( + $this->_stringContains->matches(self::EXCERPT . self::EXCERPT), + 'should be true if excerpt is repeated' + ); + + $this->assertFalse( + $this->_stringContains->matches('Something else'), + 'should not be true if excerpt is not in string' + ); + $this->assertFalse( + $this->_stringContains->matches(substr(self::EXCERPT, 1)), + 'should not be true if part of excerpt is in string' + ); + } + + public function testEvaluatesToTrueIfArgumentIsEqualToSubstring() + { + $this->assertTrue( + $this->_stringContains->matches(self::EXCERPT), + 'should be true if excerpt is entire string' + ); + } + + public function testEvaluatesToFalseIfArgumentContainsSubstringIgnoringCase() + { + $this->assertFalse( + $this->_stringContains->matches(strtolower(self::EXCERPT)), + 'should be false if excerpt is entire string ignoring case' + ); + $this->assertFalse( + $this->_stringContains->matches('START' . strtolower(self::EXCERPT) . 'END'), + 'should be false if excerpt is contained in string ignoring case' + ); + } + + public function testIgnoringCaseReturnsCorrectMatcher() + { + $this->assertTrue( + $this->_stringContains->ignoringCase()->matches('EXceRpT'), + 'should be true if excerpt is entire string ignoring case' + ); + } + + public function testHasAReadableDescription() + { + $this->assertDescription( + 'a string containing "' + . self::EXCERPT . '"', + $this->_stringContains + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringEndsWithTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringEndsWithTest.php new file mode 100644 index 00000000..9a30f952 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringEndsWithTest.php @@ -0,0 +1,62 @@ +_stringEndsWith = \Hamcrest\Text\StringEndsWith::endsWith(self::EXCERPT); + } + + protected function createMatcher() + { + return $this->_stringEndsWith; + } + + public function testEvaluatesToTrueIfArgumentContainsSpecifiedSubstring() + { + $this->assertFalse( + $this->_stringEndsWith->matches(self::EXCERPT . 'END'), + 'should be false if excerpt at beginning' + ); + $this->assertTrue( + $this->_stringEndsWith->matches('START' . self::EXCERPT), + 'should be true if excerpt at end' + ); + $this->assertFalse( + $this->_stringEndsWith->matches('START' . self::EXCERPT . 'END'), + 'should be false if excerpt in middle' + ); + $this->assertTrue( + $this->_stringEndsWith->matches(self::EXCERPT . self::EXCERPT), + 'should be true if excerpt is at end and repeated' + ); + + $this->assertFalse( + $this->_stringEndsWith->matches('Something else'), + 'should be false if excerpt is not in string' + ); + $this->assertFalse( + $this->_stringEndsWith->matches(substr(self::EXCERPT, 0, strlen(self::EXCERPT) - 2)), + 'should be false if part of excerpt is at end of string' + ); + } + + public function testEvaluatesToTrueIfArgumentIsEqualToSubstring() + { + $this->assertTrue( + $this->_stringEndsWith->matches(self::EXCERPT), + 'should be true if excerpt is entire string' + ); + } + + public function testHasAReadableDescription() + { + $this->assertDescription('a string ending with "EXCERPT"', $this->_stringEndsWith); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringStartsWithTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringStartsWithTest.php new file mode 100644 index 00000000..3be201f1 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Text/StringStartsWithTest.php @@ -0,0 +1,62 @@ +_stringStartsWith = \Hamcrest\Text\StringStartsWith::startsWith(self::EXCERPT); + } + + protected function createMatcher() + { + return $this->_stringStartsWith; + } + + public function testEvaluatesToTrueIfArgumentContainsSpecifiedSubstring() + { + $this->assertTrue( + $this->_stringStartsWith->matches(self::EXCERPT . 'END'), + 'should be true if excerpt at beginning' + ); + $this->assertFalse( + $this->_stringStartsWith->matches('START' . self::EXCERPT), + 'should be false if excerpt at end' + ); + $this->assertFalse( + $this->_stringStartsWith->matches('START' . self::EXCERPT . 'END'), + 'should be false if excerpt in middle' + ); + $this->assertTrue( + $this->_stringStartsWith->matches(self::EXCERPT . self::EXCERPT), + 'should be true if excerpt is at beginning and repeated' + ); + + $this->assertFalse( + $this->_stringStartsWith->matches('Something else'), + 'should be false if excerpt is not in string' + ); + $this->assertFalse( + $this->_stringStartsWith->matches(substr(self::EXCERPT, 1)), + 'should be false if part of excerpt is at start of string' + ); + } + + public function testEvaluatesToTrueIfArgumentIsEqualToSubstring() + { + $this->assertTrue( + $this->_stringStartsWith->matches(self::EXCERPT), + 'should be true if excerpt is entire string' + ); + } + + public function testHasAReadableDescription() + { + $this->assertDescription('a string starting with "EXCERPT"', $this->_stringStartsWith); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsArrayTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsArrayTest.php new file mode 100644 index 00000000..d13c24d2 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsArrayTest.php @@ -0,0 +1,35 @@ +assertDescription('an array', arrayValue()); + } + + public function testDecribesActualTypeInMismatchMessage() + { + $this->assertMismatchDescription('was null', arrayValue(), null); + $this->assertMismatchDescription('was a string "foo"', arrayValue(), 'foo'); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsBooleanTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsBooleanTest.php new file mode 100644 index 00000000..24309fc0 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsBooleanTest.php @@ -0,0 +1,35 @@ +assertDescription('a boolean', booleanValue()); + } + + public function testDecribesActualTypeInMismatchMessage() + { + $this->assertMismatchDescription('was null', booleanValue(), null); + $this->assertMismatchDescription('was a string "foo"', booleanValue(), 'foo'); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsCallableTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsCallableTest.php new file mode 100644 index 00000000..5098e21b --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsCallableTest.php @@ -0,0 +1,103 @@ +=')) { + $this->markTestSkipped('Closures require php 5.3'); + } + eval('assertThat(function () {}, callableValue());'); + } + + public function testEvaluatesToTrueIfArgumentImplementsInvoke() + { + if (!version_compare(PHP_VERSION, '5.3', '>=')) { + $this->markTestSkipped('Magic method __invoke() requires php 5.3'); + } + assertThat($this, callableValue()); + } + + public function testEvaluatesToFalseIfArgumentIsInvalidFunctionName() + { + if (function_exists('not_a_Hamcrest_function')) { + $this->markTestSkipped('Function "not_a_Hamcrest_function" must not exist'); + } + + assertThat('not_a_Hamcrest_function', not(callableValue())); + } + + public function testEvaluatesToFalseIfArgumentIsInvalidStaticMethodCallback() + { + assertThat( + array('Hamcrest\Type\IsCallableTest', 'noMethod'), + not(callableValue()) + ); + } + + public function testEvaluatesToFalseIfArgumentIsInvalidInstanceMethodCallback() + { + assertThat(array($this, 'noMethod'), not(callableValue())); + } + + public function testEvaluatesToFalseIfArgumentDoesntImplementInvoke() + { + assertThat(new \stdClass(), not(callableValue())); + } + + public function testEvaluatesToFalseIfArgumentDoesntMatchType() + { + assertThat(false, not(callableValue())); + assertThat(5.2, not(callableValue())); + } + + public function testHasAReadableDescription() + { + $this->assertDescription('a callable', callableValue()); + } + + public function testDecribesActualTypeInMismatchMessage() + { + $this->assertMismatchDescription( + 'was a string "invalid-function"', + callableValue(), + 'invalid-function' + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsDoubleTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsDoubleTest.php new file mode 100644 index 00000000..85c2a963 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsDoubleTest.php @@ -0,0 +1,35 @@ +assertDescription('a double', doubleValue()); + } + + public function testDecribesActualTypeInMismatchMessage() + { + $this->assertMismatchDescription('was null', doubleValue(), null); + $this->assertMismatchDescription('was a string "foo"', doubleValue(), 'foo'); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsIntegerTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsIntegerTest.php new file mode 100644 index 00000000..ce5a51a9 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsIntegerTest.php @@ -0,0 +1,36 @@ +assertDescription('an integer', integerValue()); + } + + public function testDecribesActualTypeInMismatchMessage() + { + $this->assertMismatchDescription('was null', integerValue(), null); + $this->assertMismatchDescription('was a string "foo"', integerValue(), 'foo'); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsNumericTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsNumericTest.php new file mode 100644 index 00000000..1fd83efe --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsNumericTest.php @@ -0,0 +1,53 @@ +assertDescription('a number', numericValue()); + } + + public function testDecribesActualTypeInMismatchMessage() + { + $this->assertMismatchDescription('was null', numericValue(), null); + $this->assertMismatchDescription('was a string "foo"', numericValue(), 'foo'); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsObjectTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsObjectTest.php new file mode 100644 index 00000000..a3b617c2 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsObjectTest.php @@ -0,0 +1,34 @@ +assertDescription('an object', objectValue()); + } + + public function testDecribesActualTypeInMismatchMessage() + { + $this->assertMismatchDescription('was null', objectValue(), null); + $this->assertMismatchDescription('was a string "foo"', objectValue(), 'foo'); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsResourceTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsResourceTest.php new file mode 100644 index 00000000..d6ea5348 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsResourceTest.php @@ -0,0 +1,34 @@ +assertDescription('a resource', resourceValue()); + } + + public function testDecribesActualTypeInMismatchMessage() + { + $this->assertMismatchDescription('was null', resourceValue(), null); + $this->assertMismatchDescription('was a string "foo"', resourceValue(), 'foo'); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsScalarTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsScalarTest.php new file mode 100644 index 00000000..72a188d6 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsScalarTest.php @@ -0,0 +1,39 @@ +assertDescription('a scalar', scalarValue()); + } + + public function testDecribesActualTypeInMismatchMessage() + { + $this->assertMismatchDescription('was null', scalarValue(), null); + $this->assertMismatchDescription('was an array ["foo"]', scalarValue(), array('foo')); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsStringTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsStringTest.php new file mode 100644 index 00000000..557d5913 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Type/IsStringTest.php @@ -0,0 +1,35 @@ +assertDescription('a string', stringValue()); + } + + public function testDecribesActualTypeInMismatchMessage() + { + $this->assertMismatchDescription('was null', stringValue(), null); + $this->assertMismatchDescription('was a double <5.2F>', stringValue(), 5.2); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/UtilTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/UtilTest.php new file mode 100644 index 00000000..7248978c --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/UtilTest.php @@ -0,0 +1,82 @@ +assertSame($matcher, $newMatcher); + } + + public function testWrapValueWithIsEqualWrapsPrimitive() + { + $matcher = \Hamcrest\Util::wrapValueWithIsEqual('foo'); + $this->assertInstanceOf('Hamcrest\Core\IsEqual', $matcher); + $this->assertTrue($matcher->matches('foo')); + } + + public function testCheckAllAreMatchersAcceptsMatchers() + { + \Hamcrest\Util::checkAllAreMatchers(array( + new \Hamcrest\Text\MatchesPattern('/fo+/'), + new \Hamcrest\Core\IsEqual('foo'), + )); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testCheckAllAreMatchersFailsForPrimitive() + { + \Hamcrest\Util::checkAllAreMatchers(array( + new \Hamcrest\Text\MatchesPattern('/fo+/'), + 'foo', + )); + } + + private function callAndAssertCreateMatcherArray($items) + { + $matchers = \Hamcrest\Util::createMatcherArray($items); + $this->assertInternalType('array', $matchers); + $this->assertSameSize($items, $matchers); + foreach ($matchers as $matcher) { + $this->assertInstanceOf('\Hamcrest\Matcher', $matcher); + } + + return $matchers; + } + + public function testCreateMatcherArrayLeavesMatchersUntouched() + { + $matcher = new \Hamcrest\Text\MatchesPattern('/fo+/'); + $items = array($matcher); + $matchers = $this->callAndAssertCreateMatcherArray($items); + $this->assertSame($matcher, $matchers[0]); + } + + public function testCreateMatcherArrayWrapsPrimitiveWithIsEqualMatcher() + { + $matchers = $this->callAndAssertCreateMatcherArray(array('foo')); + $this->assertInstanceOf('Hamcrest\Core\IsEqual', $matchers[0]); + $this->assertTrue($matchers[0]->matches('foo')); + } + + public function testCreateMatcherArrayDoesntModifyOriginalArray() + { + $items = array('foo'); + $this->callAndAssertCreateMatcherArray($items); + $this->assertSame('foo', $items[0]); + } + + public function testCreateMatcherArrayUnwrapsSingleArrayElement() + { + $matchers = $this->callAndAssertCreateMatcherArray(array(array('foo'))); + $this->assertInstanceOf('Hamcrest\Core\IsEqual', $matchers[0]); + $this->assertTrue($matchers[0]->matches('foo')); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Xml/HasXPathTest.php b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Xml/HasXPathTest.php new file mode 100644 index 00000000..67748871 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/Hamcrest/Xml/HasXPathTest.php @@ -0,0 +1,198 @@ + + + + alice + Alice Frankel + admin + + + bob + Bob Frankel + user + + + charlie + Charlie Chan + user + + +XML; + self::$doc = new \DOMDocument(); + self::$doc->loadXML(self::$xml); + + self::$html = << + + Home Page + + +

    Heading

    +

    Some text

    + + +HTML; + } + + protected function createMatcher() + { + return \Hamcrest\Xml\HasXPath::hasXPath('/users/user'); + } + + public function testMatchesWhenXPathIsFound() + { + assertThat('one match', self::$doc, hasXPath('user[id = "bob"]')); + assertThat('two matches', self::$doc, hasXPath('user[role = "user"]')); + } + + public function testDoesNotMatchWhenXPathIsNotFound() + { + assertThat( + 'no match', + self::$doc, + not(hasXPath('user[contains(id, "frank")]')) + ); + } + + public function testMatchesWhenExpressionWithoutMatcherEvaluatesToTrue() + { + assertThat( + 'one match', + self::$doc, + hasXPath('count(user[id = "bob"])') + ); + } + + public function testDoesNotMatchWhenExpressionWithoutMatcherEvaluatesToFalse() + { + assertThat( + 'no matches', + self::$doc, + not(hasXPath('count(user[id = "frank"])')) + ); + } + + public function testMatchesWhenExpressionIsEqual() + { + assertThat( + 'one match', + self::$doc, + hasXPath('count(user[id = "bob"])', 1) + ); + assertThat( + 'two matches', + self::$doc, + hasXPath('count(user[role = "user"])', 2) + ); + } + + public function testDoesNotMatchWhenExpressionIsNotEqual() + { + assertThat( + 'no match', + self::$doc, + not(hasXPath('count(user[id = "frank"])', 2)) + ); + assertThat( + 'one match', + self::$doc, + not(hasXPath('count(user[role = "admin"])', 2)) + ); + } + + public function testMatchesWhenContentMatches() + { + assertThat( + 'one match', + self::$doc, + hasXPath('user/name', containsString('ice')) + ); + assertThat( + 'two matches', + self::$doc, + hasXPath('user/role', equalTo('user')) + ); + } + + public function testDoesNotMatchWhenContentDoesNotMatch() + { + assertThat( + 'no match', + self::$doc, + not(hasXPath('user/name', containsString('Bobby'))) + ); + assertThat( + 'no matches', + self::$doc, + not(hasXPath('user/role', equalTo('owner'))) + ); + } + + public function testProvidesConvenientShortcutForHasXPathEqualTo() + { + assertThat('matches', self::$doc, hasXPath('count(user)', 3)); + assertThat('matches', self::$doc, hasXPath('user[2]/id', 'bob')); + } + + public function testProvidesConvenientShortcutForHasXPathCountEqualTo() + { + assertThat('matches', self::$doc, hasXPath('user[id = "charlie"]', 1)); + } + + public function testMatchesAcceptsXmlString() + { + assertThat('accepts XML string', self::$xml, hasXPath('user')); + } + + public function testMatchesAcceptsHtmlString() + { + assertThat('accepts HTML string', self::$html, hasXPath('body/h1', 'Heading')); + } + + public function testHasAReadableDescription() + { + $this->assertDescription( + 'XML or HTML document with XPath "/users/user"', + hasXPath('/users/user') + ); + $this->assertDescription( + 'XML or HTML document with XPath "count(/users/user)" <2>', + hasXPath('/users/user', 2) + ); + $this->assertDescription( + 'XML or HTML document with XPath "/users/user/name"' + . ' a string starting with "Alice"', + hasXPath('/users/user/name', startsWith('Alice')) + ); + } + + public function testHasAReadableMismatchDescription() + { + $this->assertMismatchDescription( + 'XPath returned no results', + hasXPath('/users/name'), + self::$doc + ); + $this->assertMismatchDescription( + 'XPath expression result was <3F>', + hasXPath('/users/user', 2), + self::$doc + ); + $this->assertMismatchDescription( + 'XPath returned ["alice", "bob", "charlie"]', + hasXPath('/users/user/id', 'Frank'), + self::$doc + ); + } +} diff --git a/vendor/hamcrest/hamcrest-php/tests/bootstrap.php b/vendor/hamcrest/hamcrest-php/tests/bootstrap.php new file mode 100644 index 00000000..bc4958d1 --- /dev/null +++ b/vendor/hamcrest/hamcrest-php/tests/bootstrap.php @@ -0,0 +1,11 @@ + + + + . + + + + + + ../hamcrest + + + diff --git a/vendor/mockery/mockery/.phpstorm.meta.php b/vendor/mockery/mockery/.phpstorm.meta.php new file mode 100644 index 00000000..bb7acee5 --- /dev/null +++ b/vendor/mockery/mockery/.phpstorm.meta.php @@ -0,0 +1,11 @@ + "@"])); +override(\Mockery::spy(0), map(["" => "@"])); +override(\Mockery::namedMock(0), map(["" => "@"])); +override(\Mockery::instanceMock(0), map(["" => "@"])); +override(\mock(0), map(["" => "@"])); +override(\spy(0), map(["" => "@"])); +override(\namedMock(0), map(["" => "@"])); \ No newline at end of file diff --git a/vendor/mockery/mockery/CHANGELOG.md b/vendor/mockery/mockery/CHANGELOG.md new file mode 100644 index 00000000..937460e9 --- /dev/null +++ b/vendor/mockery/mockery/CHANGELOG.md @@ -0,0 +1,217 @@ +# Change Log + +## 1.3.6 (2022-09-07) +* PHP 8.2 | Fix "Use of "parent" in callables is deprecated" notice #1169 + +## 1.5.1 (2022-09-07) + +* [PHP 8.2] Various tests: explicitly declare properties #1170 +* [PHP 8.2] Fix "Use of "parent" in callables is deprecated" notice #1169 +* [PHP 8.1] Support intersection types #1164 +* Handle final `__toString` methods #1162 + +## 1.5.0 (2022-01-20) + +* Override default call count expectations via expects() #1146 +* Mock methods with static return types #1157 +* Mock methods with mixed return type #1156 +* Mock classes with new in initializers on PHP 8.1 #1160 +* Removes redundant PHPUnitConstraint #1158 + +## 1.4.4 (2021-09-13) + +* Fixes auto-generated return values #1144 +* Adds support for tentative types #1130 +* Fixes for PHP 8.1 Support (#1130 and #1140) +* Add method that allows defining a set of arguments the mock should yield #1133 +* Added option to configure default matchers for objects `\Mockery::getConfiguration()->setDefaultMatcher($class, $matcherClass)` #1120 + +## 1.3.5 (2021-09-13) +* Fix auto-generated return values with union types #1143 +* Adds support for tentative types #1130 +* Fixes for PHP 8.1 Support (#1130 and #1140) +* Add method that allows defining a set of arguments the mock should yield #1133 +* Added option to configure default matchers for objects `\Mockery::getConfiguration()->setDefaultMatcher($class, $matcherClass)` #1120 + +## 1.4.3 (2021-02-24) + +* Fixes calls to fetchMock before initialisation #1113 +* Allow shouldIgnoreMissing() to behave in a recursive fashion #1097 +* Custom object formatters #766 (Needs Docs) +* Fix crash on a union type including null #1106 + +## 1.3.4 (2021-02-24) + +* Fixes calls to fetchMock before initialisation #1113 +* Fix crash on a union type including null #1106 + +## 1.4.2 (2020-08-11) + +* Fix array to string conversion in ConstantsPass (#1086) +* Fixed nullable PHP 8.0 union types (#1088, #1089) +* Fixed support for PHP 8.0 parent type (#1088, #1089) +* Fixed PHP 8.0 mixed type support (#1088, #1089) +* Fixed PHP 8.0 union return types (#1088, #1089) + +## 1.4.1 (2020-07-09) + +* Allow quick definitions to use 'at least once' expectation + `\Mockery::getConfiguration()->getQuickDefinitions()->shouldBeCalledAtLeastOnce(true)` (#1056) +* Added provisional support for PHP 8.0 (#1068, #1072,#1079) +* Fix mocking methods with iterable return type without specifying a return value (#1075) + +## 1.3.3 (2020-08-11) + +* Fix array to string conversion in ConstantsPass (#1086) +* Fixed nullable PHP 8.0 union types (#1088) +* Fixed support for PHP 8.0 parent type (#1088) +* Fixed PHP 8.0 mixed type support (#1088) +* Fixed PHP 8.0 union return types (#1088) + +## 1.3.2 (2020-07-09) + +* Fix mocking with anonymous classes (#1039) +* Fix andAnyOthers() to properly match earlier expectations (#1051) +* Added provisional support for PHP 8.0 (#1068, #1072,#1079) +* Fix mocking methods with iterable return type without specifying a return value (#1075) + +## 1.4.0 (2020-05-19) + +* Fix mocking with anonymous classes (#1039) +* Fix andAnyOthers() to properly match earlier expectations (#1051) +* Drops support for PHP < 7.3 and PHPUnit < 8 (#1059) + +## 1.3.1 (2019-12-26) + +* Revert improved exception debugging due to BC breaks (#1032) + +## 1.3.0 (2019-11-24) + +* Added capture `Mockery::capture` convenience matcher (#1020) +* Added `andReturnArg` to echo back an argument passed to a an expectation (#992) +* Improved exception debugging (#1000) +* Fixed `andSet` to not reuse properties between mock objects (#1012) + +## 1.2.4 (2019-09-30) + +* Fix a bug introduced with previous release, for empty method definition lists (#1009) + +## 1.2.3 (2019-08-07) + +* Allow mocking classes that have allows and expects methods (#868) +* Allow passing thru __call method in all mock types (experimental) (#969) +* Add support for `!` to blacklist methods (#959) +* Added `withSomeOfArgs` to partial match a list of args (#967) +* Fix chained demeter calls with type hint (#956) + +## 1.2.2 (2019-02-13) + +* Fix a BC breaking change for PHP 5.6/PHPUnit 5.7.27 (#947) + +## 1.2.1 (2019-02-07) + +* Support for PHPUnit 8 (#942) +* Allow mocking static methods called on instance (#938) + +## 1.2.0 (2018-10-02) + +* Starts counting default expectations towards count (#910) +* Adds workaround for some HHVM return types (#909) +* Adds PhpStorm metadata support for autocomplete etc (#904) +* Further attempts to support multiple PHPUnit versions (#903) +* Allows setting constructor expectations on instance mocks (#900) +* Adds workaround for HHVM memoization decorator (#893) +* Adds experimental support for callable spys (#712) + +## 1.1.0 (2018-05-08) + +* Allows use of string method names in allows and expects (#794) +* Finalises allows and expects syntax in API (#799) +* Search for handlers in a case instensitive way (#801) +* Deprecate allowMockingMethodsUnnecessarily (#808) +* Fix risky tests (#769) +* Fix namespace in TestListener (#812) +* Fixed conflicting mock names (#813) +* Clean elses (#819) +* Updated protected method mocking exception message (#826) +* Map of constants to mock (#829) +* Simplify foreach with `in_array` function (#830) +* Typehinted return value on Expectation#verify. (#832) +* Fix shouldNotHaveReceived with HigherOrderMessage (#842) +* Deprecates shouldDeferMissing (#839) +* Adds support for return type hints in Demeter chains (#848) +* Adds shouldNotReceive to composite expectation (#847) +* Fix internal error when using --static-backup (#845) +* Adds `andAnyOtherArgs` as an optional argument matcher (#860) +* Fixes namespace qualifying with namespaced named mocks (#872) +* Added possibility to add Constructor-Expections on hard dependencies, read: Mockery::mock('overload:...') (#781) + +## 1.0.0 (2017-09-06) + +* Destructors (`__destruct`) are stubbed out where it makes sense +* Allow passing a closure argument to `withArgs()` to validate multiple arguments at once. +* `Mockery\Adapter\Phpunit\TestListener` has been rewritten because it + incorrectly marked some tests as risky. It will no longer verify mock + expectations but instead check that tests do that themselves. PHPUnit 6 is + required if you want to use this fail safe. +* Removes SPL Class Loader +* Removed object recorder feature +* Bumped minimum PHP version to 5.6 +* `andThrow` will now throw anything `\Throwable` +* Adds `allows` and `expects` syntax +* Adds optional global helpers for `mock`, `namedMock` and `spy` +* Adds ability to create objects using traits +* `Mockery\Matcher\MustBe` was deprecated +* Marked `Mockery\MockInterface` as internal +* Subset matcher matches recursively +* BC BREAK - Spies return `null` by default from ignored (non-mocked) methods with nullable return type +* Removed extracting getter methods of object instances +* BC BREAK - Remove implicit regex matching when trying to match string arguments, introduce `\Mockery::pattern()` when regex matching is needed +* Fix Mockery not getting closed in cases of failing test cases +* Fix Mockery not setting properties on overloaded instance mocks +* BC BREAK - Fix Mockery not trying default expectations if there is any concrete expectation +* BC BREAK - Mockery's PHPUnit integration will mark a test as risky if it + thinks one it's exceptions has been swallowed in PHPUnit > 5.7.6. Use `$e->dismiss()` to dismiss. + +## 0.9.4 (XXXX-XX-XX) + +* `shouldIgnoreMissing` will respect global `allowMockingNonExistentMethods` + config +* Some support for variadic parameters +* Hamcrest is now a required dependency +* Instance mocks now respect `shouldIgnoreMissing` call on control instance +* This will be the *last version to support PHP 5.3* +* Added `Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration` trait +* Added `makePartial` to `Mockery\MockInterface` as it was missing + +## 0.9.3 (2014-12-22) + +* Added a basic spy implementation +* Added `Mockery\Adapter\Phpunit\MockeryTestCase` for more reliable PHPUnit + integration + +## 0.9.2 (2014-09-03) + +* Some workarounds for the serialisation problems created by changes to PHP in 5.5.13, 5.4.29, + 5.6. +* Demeter chains attempt to reuse doubles as they see fit, so for foo->bar and + foo->baz, we'll attempt to use the same foo + +## 0.9.1 (2014-05-02) + +* Allow specifying consecutive exceptions to be thrown with `andThrowExceptions` +* Allow specifying methods which can be mocked when using + `Mockery\Configuration::allowMockingNonExistentMethods(false)` with + `Mockery\MockInterface::shouldAllowMockingMethod($methodName)` +* Added andReturnSelf method: `$mock->shouldReceive("foo")->andReturnSelf()` +* `shouldIgnoreMissing` now takes an optional value that will be return instead + of null, e.g. `$mock->shouldIgnoreMissing($mock)` + +## 0.9.0 (2014-02-05) + +* Allow mocking classes with final __wakeup() method +* Quick definitions are now always `byDefault` +* Allow mocking of protected methods with `shouldAllowMockingProtectedMethods` +* Support official Hamcrest package +* Generator completely rewritten +* Easily create named mocks with namedMock diff --git a/vendor/mockery/mockery/CONTRIBUTING.md b/vendor/mockery/mockery/CONTRIBUTING.md new file mode 100644 index 00000000..b714f3f4 --- /dev/null +++ b/vendor/mockery/mockery/CONTRIBUTING.md @@ -0,0 +1,88 @@ +# Contributing + + +We'd love you to help out with mockery and no contribution is too small. + + +## Reporting Bugs + +Issues can be reported on the [issue +tracker](https://github.com/padraic/mockery/issues). Please try and report any +bugs with a minimal reproducible example, it will make things easier for other +contributors and your problems will hopefully be resolved quickly. + + +## Requesting Features + +We're always interested to hear about your ideas and you can request features by +creating a ticket in the [issue +tracker](https://github.com/padraic/mockery/issues). We can't always guarantee +someone will jump on it straight away, but putting it out there to see if anyone +else is interested is a good idea. + +Likewise, if a feature you would like is already listed in +the issue tracker, add a :+1: so that other contributors know it's a feature +that would help others. + + +## Contributing code and documentation + +We loosely follow the +[PSR-1](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md) +and +[PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) coding standards, +but we'll probably merge any code that looks close enough. + +* Fork the [repository](https://github.com/padraic/mockery) on GitHub +* Add the code for your feature or bug +* Add some tests for your feature or bug +* Optionally, but preferably, write some documentation +* Optionally, update the CHANGELOG.md file with your feature or + [BC](http://en.wikipedia.org/wiki/Backward_compatibility) break +* Send a [Pull + Request](https://help.github.com/articles/creating-a-pull-request) to the + correct target branch (see below) + +If you have a big change or would like to discuss something, create an issue in +the [issue tracker](https://github.com/padraic/mockery/issues) or jump in to +\#mockery on freenode + + +Any code you contribute must be licensed under the [BSD 3-Clause +License](http://opensource.org/licenses/BSD-3-Clause). + + +## Target Branch + +Mockery may have several active branches at any one time and roughly follows a +[Git Branching Model](https://igor.io/2013/10/21/git-branching-model.html). +Generally, if you're developing a new feature, you want to be targeting the +master branch, if it's a bug fix, you want to be targeting a release branch, +e.g. 0.8. + + +## Testing Mockery + +To run the unit tests for Mockery, clone the git repository, download Composer using +the instructions at [http://getcomposer.org/download/](http://getcomposer.org/download/), +then install the dependencies with `php /path/to/composer.phar install`. + +This will install the required PHPUnit and Hamcrest dev dependencies and create the +autoload files required by the unit tests. You may run the `vendor/bin/phpunit` command +to run the unit tests. If everything goes to plan, there will be no failed tests! + + +## Debugging Mockery + +Mockery and its code generation can be difficult to debug. A good start is to +use the `RequireLoader`, which will dump the code generated by mockery to a file +before requiring it, rather than using eval. This will help with stack traces, +and you will be able to open the mock class in your editor. + +``` php + +// tests/bootstrap.php + +Mockery::setLoader(new Mockery\Loader\RequireLoader(sys_get_temp_dir())); + +``` diff --git a/vendor/mockery/mockery/LICENSE b/vendor/mockery/mockery/LICENSE new file mode 100644 index 00000000..2e127a65 --- /dev/null +++ b/vendor/mockery/mockery/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2010, Pádraic Brady +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * The name of Pádraic Brady may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/mockery/mockery/README.md b/vendor/mockery/mockery/README.md new file mode 100644 index 00000000..55771dfb --- /dev/null +++ b/vendor/mockery/mockery/README.md @@ -0,0 +1,291 @@ +Mockery +======= + +[![Build Status](https://github.com/mockery/mockery/actions/workflows/tests.yml/badge.svg)](https://github.com/mockery/mockery/actions) +[![Latest Stable Version](https://poser.pugx.org/mockery/mockery/v/stable.svg)](https://packagist.org/packages/mockery/mockery) +[![Total Downloads](https://poser.pugx.org/mockery/mockery/downloads.svg)](https://packagist.org/packages/mockery/mockery) + +Mockery is a simple yet flexible PHP mock object framework for use in unit testing +with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a +test double framework with a succinct API capable of clearly defining all possible +object operations and interactions using a human readable Domain Specific Language +(DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, +Mockery is easy to integrate with PHPUnit and can operate alongside +phpunit-mock-objects without the World ending. + +Mockery is released under a New BSD License. + +## Installation + +To install Mockery, run the command below and you will get the latest +version + +```sh +composer require --dev mockery/mockery +``` + +## Documentation + +In older versions, this README file was the documentation for Mockery. Over time +we have improved this, and have created an extensive documentation for you. Please +use this README file as a starting point for Mockery, but do read the documentation +to learn how to use Mockery. + +The current version can be seen at [docs.mockery.io](http://docs.mockery.io). + +## PHPUnit Integration + +Mockery ships with some helpers if you are using PHPUnit. You can extend the +[`Mockery\Adapter\Phpunit\MockeryTestCase`](library/Mockery/Adapter/Phpunit/MockeryTestCase.php) +class instead of `PHPUnit\Framework\TestCase`, or if you are already using a +custom base class for your tests, take a look at the traits available in the +[`Mockery\Adapter\Phpunit`](library/Mockery/Adapter/Phpunit) namespace. + +## Test Doubles + +Test doubles (often called mocks) simulate the behaviour of real objects. They are +commonly utilised to offer test isolation, to stand in for objects which do not +yet exist, or to allow for the exploratory design of class APIs without +requiring actual implementation up front. + +The benefits of a test double framework are to allow for the flexible generation +and configuration of test doubles. They allow the setting of expected method calls +and/or return values using a flexible API which is capable of capturing every +possible real object behaviour in way that is stated as close as possible to a +natural language description. Use the `Mockery::mock` method to create a test +double. + +``` php +$double = Mockery::mock(); +``` + +If you need Mockery to create a test double to satisfy a particular type hint, +you can pass the type to the `mock` method. + +``` php +class Book {} + +interface BookRepository { + function find($id): Book; + function findAll(): array; + function add(Book $book): void; +} + +$double = Mockery::mock(BookRepository::class); +``` + +A detailed explanation of creating and working with test doubles is given in the +documentation, [Creating test doubles](http://docs.mockery.io/en/latest/reference/creating_test_doubles.html) +section. + +## Method Stubs 🎫 + +A method stub is a mechanism for having your test double return canned responses +to certain method calls. With stubs, you don't care how many times, if at all, +the method is called. Stubs are used to provide indirect input to the system +under test. + +``` php +$double->allows()->find(123)->andReturns(new Book()); + +$book = $double->find(123); +``` + +If you have used Mockery before, you might see something new in the example +above — we created a method stub using `allows`, instead of the "old" +`shouldReceive` syntax. This is a new feature of Mockery v1, but fear not, +the trusty ol' `shouldReceive` is still here. + +For new users of Mockery, the above example can also be written as: + +``` php +$double->shouldReceive('find')->with(123)->andReturn(new Book()); +$book = $double->find(123); +``` + +If your stub doesn't require specific arguments, you can also use this shortcut +for setting up multiple calls at once: + +``` php +$double->allows([ + "findAll" => [new Book(), new Book()], +]); +``` + +or + +``` php +$double->shouldReceive('findAll') + ->andReturn([new Book(), new Book()]); +``` + +You can also use this shortcut, which creates a double and sets up some stubs in +one call: + +``` php +$double = Mockery::mock(BookRepository::class, [ + "findAll" => [new Book(), new Book()], +]); +``` + +## Method Call Expectations 📲 + +A Method call expectation is a mechanism to allow you to verify that a +particular method has been called. You can specify the parameters and you can +also specify how many times you expect it to be called. Method call expectations +are used to verify indirect output of the system under test. + +``` php +$book = new Book(); + +$double = Mockery::mock(BookRepository::class); +$double->expects()->add($book); +``` + +During the test, Mockery accept calls to the `add` method as prescribed. +After you have finished exercising the system under test, you need to +tell Mockery to check that the method was called as expected, using the +`Mockery::close` method. One way to do that is to add it to your `tearDown` +method in PHPUnit. + +``` php + +public function tearDown() +{ + Mockery::close(); +} +``` + +The `expects()` method automatically sets up an expectation that the method call +(and matching parameters) is called **once and once only**. You can choose to change +this if you are expecting more calls. + +``` php +$double->expects()->add($book)->twice(); +``` + +If you have used Mockery before, you might see something new in the example +above — we created a method expectation using `expects`, instead of the "old" +`shouldReceive` syntax. This is a new feature of Mockery v1, but same as with +`accepts` in the previous section, it can be written in the "old" style. + +For new users of Mockery, the above example can also be written as: + +``` php +$double->shouldReceive('find') + ->with(123) + ->once() + ->andReturn(new Book()); +$book = $double->find(123); +``` + +A detailed explanation of declaring expectations on method calls, please +read the documentation, the [Expectation declarations](http://docs.mockery.io/en/latest/reference/expectations.html) +section. After that, you can also learn about the new `allows` and `expects` methods +in the [Alternative shouldReceive syntax](http://docs.mockery.io/en/latest/reference/alternative_should_receive_syntax.html) +section. + +It is worth mentioning that one way of setting up expectations is no better or worse +than the other. Under the hood, `allows` and `expects` are doing the same thing as +`shouldReceive`, at times in "less words", and as such it comes to a personal preference +of the programmer which way to use. + +## Test Spies 🕵️ + +By default, all test doubles created with the `Mockery::mock` method will only +accept calls that they have been configured to `allow` or `expect` (or in other words, +calls that they `shouldReceive`). Sometimes we don't necessarily care about all of the +calls that are going to be made to an object. To facilitate this, we can tell Mockery +to ignore any calls it has not been told to expect or allow. To do so, we can tell a +test double `shouldIgnoreMissing`, or we can create the double using the `Mocker::spy` +shortcut. + +``` php +// $double = Mockery::mock()->shouldIgnoreMissing(); +$double = Mockery::spy(); + +$double->foo(); // null +$double->bar(); // null +``` + +Further to this, sometimes we want to have the object accept any call during the test execution +and then verify the calls afterwards. For these purposes, we need our test +double to act as a Spy. All mockery test doubles record the calls that are made +to them for verification afterwards by default: + +``` php +$double->baz(123); + +$double->shouldHaveReceived()->baz(123); // null +$double->shouldHaveReceived()->baz(12345); // Uncaught Exception Mockery\Exception\InvalidCountException... +``` + +Please refer to the [Spies](http://docs.mockery.io/en/latest/reference/spies.html) section +of the documentation to learn more about the spies. + +## Utilities 🔌 + +### Global Helpers + +Mockery ships with a handful of global helper methods, you just need to ask +Mockery to declare them. + +``` php +Mockery::globalHelpers(); + +$mock = mock(Some::class); +$spy = spy(Some::class); + +$spy->shouldHaveReceived() + ->foo(anyArgs()); +``` + +All of the global helpers are wrapped in a `!function_exists` call to avoid +conflicts. So if you already have a global function called `spy`, Mockery will +silently skip the declaring its own `spy` function. + +### Testing Traits + +As Mockery ships with code generation capabilities, it was trivial to add +functionality allowing users to create objects on the fly that use particular +traits. Any abstract methods defined by the trait will be created and can have +expectations or stubs configured like normal Test Doubles. + +``` php +trait Foo { + function foo() { + return $this->doFoo(); + } + + abstract function doFoo(); +} + +$double = Mockery::mock(Foo::class); +$double->allows()->doFoo()->andReturns(123); +$double->foo(); // int(123) +``` + +## Versioning + +The Mockery team attempts to adhere to [Semantic Versioning](http://semver.org), +however, some of Mockery's internals are considered private and will be open to +change at any time. Just because a class isn't final, or a method isn't marked +private, does not mean it constitutes part of the API we guarantee under the +versioning scheme. + +### Alternative Runtimes + +Mockery 1.3 was the last version to support HHVM 3 and PHP 5. There is no support for HHVM 4+. + +## A new home for Mockery + +⚠️️ Update your remotes! Mockery has transferred to a new location. While it was once +at `padraic/mockery`, it is now at `mockery/mockery`. While your +existing repositories will redirect transparently for any operations, take some +time to transition to the new URL. +```sh +$ git remote set-url upstream https://github.com/mockery/mockery.git +``` +Replace `upstream` with the name of the remote you use locally; `upstream` is commonly +used but you may be using something else. Run `git remote -v` to see what you're actually +using. diff --git a/vendor/mockery/mockery/composer.json b/vendor/mockery/mockery/composer.json new file mode 100644 index 00000000..43caba8c --- /dev/null +++ b/vendor/mockery/mockery/composer.json @@ -0,0 +1,62 @@ +{ + "name": "mockery/mockery", + "description": "Mockery is a simple yet flexible PHP mock object framework", + "scripts": { + "docs": "phpdoc -d library -t docs/api" + }, + "keywords": [ + "bdd", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "tdd", + "test", + "test double", + "testing" + ], + "homepage": "https://github.com/mockery/mockery", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "http://blog.astrumfutura.com" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "http://davedevelopment.co.uk" + } + ], + "require": { + "php": "^7.3 || ^8.0", + "lib-pcre": ">=7.0", + "hamcrest/hamcrest-php": "^2.0.1" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "autoload": { + "psr-0": { + "Mockery": "library/" + } + }, + "autoload-dev": { + "psr-4": { + "test\\": "tests/" + } + }, + "config": { + "preferred-install": "dist" + }, + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + } +} diff --git a/vendor/mockery/mockery/docs/README.md b/vendor/mockery/mockery/docs/README.md new file mode 100644 index 00000000..63ca69db --- /dev/null +++ b/vendor/mockery/mockery/docs/README.md @@ -0,0 +1,4 @@ +mockery-docs +============ + +Document for the PHP Mockery framework on readthedocs.org \ No newline at end of file diff --git a/vendor/mockery/mockery/docs/conf.py b/vendor/mockery/mockery/docs/conf.py new file mode 100644 index 00000000..901f0405 --- /dev/null +++ b/vendor/mockery/mockery/docs/conf.py @@ -0,0 +1,267 @@ +# -*- coding: utf-8 -*- +# +# Mockery Docs documentation build configuration file, created by +# sphinx-quickstart on Mon Mar 3 14:04:26 2014. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.todo', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Mockery Docs' +copyright = u'Pádraic Brady, Dave Marshall and contributors' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0-alpha' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'MockeryDocsdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'MockeryDocs.tex', u'Mockery Docs Documentation', + u'Pádraic Brady, Dave Marshall, Wouter, Graham Campbell', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'mockerydocs', u'Mockery Docs Documentation', + [u'Pádraic Brady, Dave Marshall, Wouter, Graham Campbell'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'MockeryDocs', u'Mockery Docs Documentation', + u'Pádraic Brady, Dave Marshall, Wouter, Graham Campbell', 'MockeryDocs', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + + +#on_rtd is whether we are on readthedocs.org, this line of code grabbed from docs.readthedocs.org +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' + +if not on_rtd: # only import and set the theme if we're building docs locally + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + print sphinx_rtd_theme.get_html_theme_path() + +# load PhpLexer +from sphinx.highlighting import lexers +from pygments.lexers.web import PhpLexer + +# enable highlighting for PHP code not between by default +lexers['php'] = PhpLexer(startinline=True) +lexers['php-annotations'] = PhpLexer(startinline=True) diff --git a/vendor/mockery/mockery/docs/cookbook/big_parent_class.rst b/vendor/mockery/mockery/docs/cookbook/big_parent_class.rst new file mode 100644 index 00000000..a27d5327 --- /dev/null +++ b/vendor/mockery/mockery/docs/cookbook/big_parent_class.rst @@ -0,0 +1,52 @@ +.. index:: + single: Cookbook; Big Parent Class + +Big Parent Class +================ + +In some application code, especially older legacy code, we can come across some +classes that extend a "big parent class" - a parent class that knows and does +too much: + +.. code-block:: php + + class BigParentClass + { + public function doesEverything() + { + // sets up database connections + // writes to log files + } + } + + class ChildClass extends BigParentClass + { + public function doesOneThing() + { + // but calls on BigParentClass methods + $result = $this->doesEverything(); + // does something with $result + return $result; + } + } + +We want to test our ``ChildClass`` and its ``doesOneThing`` method, but the +problem is that it calls on ``BigParentClass::doesEverything()``. One way to +handle this would be to mock out **all** of the dependencies ``BigParentClass`` +has and needs, and then finally actually test our ``doesOneThing`` method. It's +an awful lot of work to do that. + +What we can do, is to do something... unconventional. We can create a runtime +partial test double of the ``ChildClass`` itself and mock only the parent's +``doesEverything()`` method: + +.. code-block:: php + + $childClass = \Mockery::mock('ChildClass')->makePartial(); + $childClass->shouldReceive('doesEverything') + ->andReturn('some result from parent'); + + $childClass->doesOneThing(); // string("some result from parent"); + +With this approach we mock out only the ``doesEverything()`` method, and all the +unmocked methods are called on the actual ``ChildClass`` instance. diff --git a/vendor/mockery/mockery/docs/cookbook/class_constants.rst b/vendor/mockery/mockery/docs/cookbook/class_constants.rst new file mode 100644 index 00000000..0b925692 --- /dev/null +++ b/vendor/mockery/mockery/docs/cookbook/class_constants.rst @@ -0,0 +1,183 @@ +.. index:: + single: Cookbook; Class Constants + +Class Constants +=============== + +When creating a test double for a class, Mockery does not create stubs out of +any class constants defined in the class we are mocking. Sometimes though, the +non-existence of these class constants, setup of the test, and the application +code itself, it can lead to undesired behavior, and even a PHP error: +``PHP Fatal error: Uncaught Error: Undefined class constant 'FOO' in ...`` + +While supporting class constants in Mockery would be possible, it does require +an awful lot of work, for a small number of use cases. + +Named Mocks +----------- + +We can, however, deal with these constants in a way supported by Mockery - by +using :ref:`creating-test-doubles-named-mocks`. + +A named mock is a test double that has a name of the class we want to mock, but +under it is a stubbed out class that mimics the real class with canned responses. + +Lets look at the following made up, but not impossible scenario: + +.. code-block:: php + + class Fetcher + { + const SUCCESS = 0; + const FAILURE = 1; + + public static function fetch() + { + // Fetcher gets something for us from somewhere... + return self::SUCCESS; + } + } + + class MyClass + { + public function doFetching() + { + $response = Fetcher::fetch(); + + if ($response == Fetcher::SUCCESS) { + echo "Thanks!" . PHP_EOL; + } else { + echo "Try again!" . PHP_EOL; + } + } + } + +Our ``MyClass`` calls a ``Fetcher`` that fetches some resource from somewhere - +maybe it downloads a file from a remote web service. Our ``MyClass`` prints out +a response message depending on the response from the ``Fetcher::fetch()`` call. + +When testing ``MyClass`` we don't really want ``Fetcher`` to go and download +random stuff from the internet every time we run our test suite. So we mock it +out: + +.. code-block:: php + + // Using alias: because fetch is called statically! + \Mockery::mock('alias:Fetcher') + ->shouldReceive('fetch') + ->andReturn(0); + + $myClass = new MyClass(); + $myClass->doFetching(); + +If we run this, our test will error out with a nasty +``PHP Fatal error: Uncaught Error: Undefined class constant 'SUCCESS' in ..``. + +Here's how a ``namedMock()`` can help us in a situation like this. + +We create a stub for the ``Fetcher`` class, stubbing out the class constants, +and then use ``namedMock()`` to create a mock named ``Fetcher`` based on our +stub: + +.. code-block:: php + + class FetcherStub + { + const SUCCESS = 0; + const FAILURE = 1; + } + + \Mockery::namedMock('Fetcher', 'FetcherStub') + ->shouldReceive('fetch') + ->andReturn(0); + + $myClass = new MyClass(); + $myClass->doFetching(); + +This works because under the hood, Mockery creates a class called ``Fetcher`` +that extends ``FetcherStub``. + +The same approach will work even if ``Fetcher::fetch()`` is not a static +dependency: + +.. code-block:: php + + class Fetcher + { + const SUCCESS = 0; + const FAILURE = 1; + + public function fetch() + { + // Fetcher gets something for us from somewhere... + return self::SUCCESS; + } + } + + class MyClass + { + public function doFetching($fetcher) + { + $response = $fetcher->fetch(); + + if ($response == Fetcher::SUCCESS) { + echo "Thanks!" . PHP_EOL; + } else { + echo "Try again!" . PHP_EOL; + } + } + } + +And the test will have something like this: + +.. code-block:: php + + class FetcherStub + { + const SUCCESS = 0; + const FAILURE = 1; + } + + $mock = \Mockery::mock('Fetcher', 'FetcherStub') + $mock->shouldReceive('fetch') + ->andReturn(0); + + $myClass = new MyClass(); + $myClass->doFetching($mock); + + +Constants Map +------------- + +Another way of mocking class constants can be with the use of the constants map configuration. + +Given a class with constants: + +.. code-block:: php + + class Fetcher + { + const SUCCESS = 0; + const FAILURE = 1; + + public function fetch() + { + // Fetcher gets something for us from somewhere... + return self::SUCCESS; + } + } + +It can be mocked with: + +.. code-block:: php + + \Mockery::getConfiguration()->setConstantsMap([ + 'Fetcher' => [ + 'SUCCESS' => 'success', + 'FAILURE' => 'fail', + ] + ]); + + $mock = \Mockery::mock('Fetcher'); + var_dump($mock::SUCCESS); // (string) 'success' + var_dump($mock::FAILURE); // (string) 'fail' diff --git a/vendor/mockery/mockery/docs/cookbook/default_expectations.rst b/vendor/mockery/mockery/docs/cookbook/default_expectations.rst new file mode 100644 index 00000000..2c6fcae2 --- /dev/null +++ b/vendor/mockery/mockery/docs/cookbook/default_expectations.rst @@ -0,0 +1,17 @@ +.. index:: + single: Cookbook; Default Mock Expectations + +Default Mock Expectations +========================= + +Often in unit testing, we end up with sets of tests which use the same object +dependency over and over again. Rather than mocking this class/object within +every single unit test (requiring a mountain of duplicate code), we can +instead define reusable default mocks within the test case's ``setup()`` +method. This even works where unit tests use varying expectations on the same +or similar mock object. + +How this works, is that you can define mocks with default expectations. Then, +in a later unit test, you can add or fine-tune expectations for that specific +test. Any expectation can be set as a default using the ``byDefault()`` +declaration. diff --git a/vendor/mockery/mockery/docs/cookbook/detecting_mock_objects.rst b/vendor/mockery/mockery/docs/cookbook/detecting_mock_objects.rst new file mode 100644 index 00000000..0210c692 --- /dev/null +++ b/vendor/mockery/mockery/docs/cookbook/detecting_mock_objects.rst @@ -0,0 +1,13 @@ +.. index:: + single: Cookbook; Detecting Mock Objects + +Detecting Mock Objects +====================== + +Users may find it useful to check whether a given object is a real object or a +simulated Mock Object. All Mockery mocks implement the +``\Mockery\MockInterface`` interface which can be used in a type check. + +.. code-block:: php + + assert($mightBeMocked instanceof \Mockery\MockInterface); diff --git a/vendor/mockery/mockery/docs/cookbook/index.rst b/vendor/mockery/mockery/docs/cookbook/index.rst new file mode 100644 index 00000000..034e39de --- /dev/null +++ b/vendor/mockery/mockery/docs/cookbook/index.rst @@ -0,0 +1,16 @@ +Cookbook +======== + +.. toctree:: + :hidden: + + default_expectations + detecting_mock_objects + not_calling_the_constructor + mocking_hard_dependencies + class_constants + big_parent_class + mockery_on + mocking_class_within_class + +.. include:: map.rst.inc diff --git a/vendor/mockery/mockery/docs/cookbook/map.rst.inc b/vendor/mockery/mockery/docs/cookbook/map.rst.inc new file mode 100644 index 00000000..c9dd99ef --- /dev/null +++ b/vendor/mockery/mockery/docs/cookbook/map.rst.inc @@ -0,0 +1,7 @@ +* :doc:`/cookbook/default_expectations` +* :doc:`/cookbook/detecting_mock_objects` +* :doc:`/cookbook/not_calling_the_constructor` +* :doc:`/cookbook/mocking_hard_dependencies` +* :doc:`/cookbook/class_constants` +* :doc:`/cookbook/big_parent_class` +* :doc:`/cookbook/mockery_on` diff --git a/vendor/mockery/mockery/docs/cookbook/mockery_on.rst b/vendor/mockery/mockery/docs/cookbook/mockery_on.rst new file mode 100644 index 00000000..631f1241 --- /dev/null +++ b/vendor/mockery/mockery/docs/cookbook/mockery_on.rst @@ -0,0 +1,85 @@ +.. index:: + single: Cookbook; Complex Argument Matching With Mockery::on + +Complex Argument Matching With Mockery::on +========================================== + +When we need to do a more complex argument matching for an expected method call, +the ``\Mockery::on()`` matcher comes in really handy. It accepts a closure as an +argument and that closure in turn receives the argument passed in to the method, +when called. If the closure returns ``true``, Mockery will consider that the +argument has passed the expectation. If the closure returns ``false``, or a +"falsey" value, the expectation will not pass. + +The ``\Mockery::on()`` matcher can be used in various scenarios — validating +an array argument based on multiple keys and values, complex string matching... + +Say, for example, we have the following code. It doesn't do much; publishes a +post by setting the ``published`` flag in the database to ``1`` and sets the +``published_at`` to the current date and time: + +.. code-block:: php + + model = $model; + } + + public function publishPost($id) + { + $saveData = [ + 'post_id' => $id, + 'published' => 1, + 'published_at' => gmdate('Y-m-d H:i:s'), + ]; + $this->model->save($saveData); + } + } + +In a test we would mock the model and set some expectations on the call of the +``save()`` method: + +.. code-block:: php + + shouldReceive('save') + ->once() + ->with(\Mockery::on(function ($argument) use ($postId) { + $postIdIsSet = isset($argument['post_id']) && $argument['post_id'] === $postId; + $publishedFlagIsSet = isset($argument['published']) && $argument['published'] === 1; + $publishedAtIsSet = isset($argument['published_at']); + + return $postIdIsSet && $publishedFlagIsSet && $publishedAtIsSet; + })); + + $service = new \Service\Post($modelMock); + $service->publishPost($postId); + + \Mockery::close(); + +The important part of the example is inside the closure we pass to the +``\Mockery::on()`` matcher. The ``$argument`` is actually the ``$saveData`` argument +the ``save()`` method gets when it is called. We check for a couple of things in +this argument: + +* the post ID is set, and is same as the post ID we passed in to the + ``publishPost()`` method, +* the ``published`` flag is set, and is ``1``, and +* the ``published_at`` key is present. + +If any of these requirements is not satisfied, the closure will return ``false``, +the method call expectation will not be met, and Mockery will throw a +``NoMatchingExpectationException``. + +.. note:: + + This cookbook entry is an adaption of the blog post titled + `"Complex argument matching in Mockery" `_, + published by Robert Basic on his blog. diff --git a/vendor/mockery/mockery/docs/cookbook/mocking_class_within_class.rst b/vendor/mockery/mockery/docs/cookbook/mocking_class_within_class.rst new file mode 100644 index 00000000..51f030b9 --- /dev/null +++ b/vendor/mockery/mockery/docs/cookbook/mocking_class_within_class.rst @@ -0,0 +1,146 @@ +.. index:: + single: Cookbook; Mocking class within class + +.. _mocking-class-within-class: + +Mocking class within class +========================== + +Imagine a case where you need to create an instance of a class and use it +within the same method: + +.. code-block:: php + + // Point.php + setPoint($x1, $y1); + + $b = new Point(); + $b->setPoint($x2, $y1); + + $c = new Point(); + $c->setPoint($x2, $y2); + + $d = new Point(); + $d->setPoint($x1, $y2); + + $this->draw([$a, $b, $c, $d]); + } + + public function draw($points) { + echo "Do something with the points"; + } + } + +And that you want to test that a logic in ``Rectangle->create()`` calls +properly each used thing - in this case calls ``Point->setPoint()``, but +``Rectangle->draw()`` does some graphical stuff that you want to avoid calling. + +You set the mocks for ``App\Point`` and ``App\Rectangle``: + +.. code-block:: php + + shouldReceive("setPoint")->andThrow(Exception::class); + + $rect = Mockery::mock("App\Rectangle")->makePartial(); + $rect->shouldReceive("draw"); + + $rect->create(0, 0, 100, 100); // does not throw exception + Mockery::close(); + } + } + +and the test does not work. Why? The mocking relies on the class not being +present yet, but the class is autoloaded therefore the mock alone for +``App\Point`` is useless which you can see with ``echo`` being executed. + +Mocks however work for the first class in the order of loading i.e. +``App\Rectangle``, which loads the ``App\Point`` class. In more complex example +that would be a single point that initiates the whole loading (``use Class``) +such as:: + + A // main loading initiator + |- B // another loading initiator + | |-E + | +-G + | + |- C // another loading initiator + | +-F + | + +- D + +That basically means that the loading prevents mocking and for each such +a loading initiator there needs to be implemented a workaround. +Overloading is one approach, however it pollutes the global state. In this case +we try to completely avoid the global state pollution with custom +``new Class()`` behavior per loading initiator and that can be mocked easily +in few critical places. + +That being said, although we can't stop loading, we can return mocks. Let's +look at ``Rectangle->create()`` method: + +.. code-block:: php + + class Rectangle { + public function newPoint() { + return new Point(); + } + + public function create($x1, $y1, $x2, $y2) { + $a = $this->newPoint(); + $a->setPoint($x1, $y1); + ... + } + ... + } + +We create a custom function to encapsulate ``new`` keyword that would otherwise +just use the autoloaded class ``App\Point`` and in our test we mock that function +so that it returns our mock: + +.. code-block:: php + + shouldReceive("setPoint")->andThrow(Exception::class); + + $rect = Mockery::mock("App\Rectangle")->makePartial(); + $rect->shouldReceive("draw"); + + // pass the App\Point mock into App\Rectangle as an alternative + // to using new App\Point() in-place. + $rect->shouldReceive("newPoint")->andReturn($point); + + $this->expectException(Exception::class); + $rect->create(0, 0, 100, 100); + Mockery::close(); + } + } + +If we run this test now, it should pass. For more complex cases we'd find +the next loader in the program flow and proceed with wrapping and passing +mock instances with predefined behavior into already existing classes. diff --git a/vendor/mockery/mockery/docs/cookbook/mocking_hard_dependencies.rst b/vendor/mockery/mockery/docs/cookbook/mocking_hard_dependencies.rst new file mode 100644 index 00000000..3391d7b3 --- /dev/null +++ b/vendor/mockery/mockery/docs/cookbook/mocking_hard_dependencies.rst @@ -0,0 +1,137 @@ +.. index:: + single: Cookbook; Mocking Hard Dependencies + +Mocking Hard Dependencies (new Keyword) +======================================= + +One prerequisite to mock hard dependencies is that the code we are trying to test uses autoloading. + +Let's take the following code for an example: + +.. code-block:: php + + sendSomething($param); + return $externalService->getSomething(); + } + } + +The way we can test this without doing any changes to the code itself is by creating :doc:`instance mocks ` by using the ``overload`` prefix. + +.. code-block:: php + + shouldReceive('sendSomething') + ->once() + ->with($param); + $externalMock->shouldReceive('getSomething') + ->once() + ->andReturn('Tested!'); + + $service = new \App\Service(); + + $result = $service->callExternalService($param); + + $this->assertSame('Tested!', $result); + } + } + +If we run this test now, it should pass. Mockery does its job and our ``App\Service`` will use the mocked external service instead of the real one. + +The problem with this is when we want to, for example, test the ``App\Service\External`` itself, or if we use that class somewhere else in our tests. + +When Mockery overloads a class, because of how PHP works with files, that overloaded class file must not be included otherwise Mockery will throw a "class already exists" exception. This is where autoloading kicks in and makes our job a lot easier. + +To make this possible, we'll tell PHPUnit to run the tests that have overloaded classes in separate processes and to not preserve global state. That way we'll avoid having the overloaded class included more than once. Of course this has its downsides as these tests will run slower. + +Our test example from above now becomes: + +.. code-block:: php + + shouldReceive('sendSomething') + ->once() + ->with($param); + $externalMock->shouldReceive('getSomething') + ->once() + ->andReturn('Tested!'); + + $service = new \App\Service(); + + $result = $service->callExternalService($param); + + $this->assertSame('Tested!', $result); + } + } + + + +Testing the constructor arguments of hard Dependencies +------------------------------------------------------ + +Sometimes we might want to ensure that the hard dependency is instantiated with +particular arguments. With overloaded mocks, we can set up expectations on the +constructor. + +.. code-block:: php + + allows('sendSomething'); + $externalMock->shouldReceive('__construct') + ->once() + ->with(5); + + $service = new \App\Service(); + $result = $service->callExternalService($param); + } + } + + +.. note:: + For more straightforward and single-process tests oriented way check + :ref:`mocking-class-within-class`. + +.. note:: + + This cookbook entry is an adaption of the blog post titled + `"Mocking hard dependencies with Mockery" `_, + published by Robert Basic on his blog. diff --git a/vendor/mockery/mockery/docs/cookbook/not_calling_the_constructor.rst b/vendor/mockery/mockery/docs/cookbook/not_calling_the_constructor.rst new file mode 100644 index 00000000..b8157ae3 --- /dev/null +++ b/vendor/mockery/mockery/docs/cookbook/not_calling_the_constructor.rst @@ -0,0 +1,63 @@ +.. index:: + single: Cookbook; Not Calling the Original Constructor + +Not Calling the Original Constructor +==================================== + +When creating generated partial test doubles, Mockery mocks out only the method +which we specifically told it to. This means that the original constructor of +the class we are mocking will be called. + +In some cases this is not a desired behavior, as the constructor might issue +calls to other methods, or other object collaborators, and as such, can create +undesired side-effects in the application's environment when running the tests. + +If this happens, we need to use runtime partial test doubles, as they don't +call the original constructor. + +.. code-block:: php + + class MyClass + { + public function __construct() + { + echo "Original constructor called." . PHP_EOL; + // Other side-effects can happen... + } + } + + // This will print "Original constructor called." + $mock = \Mockery::mock('MyClass[foo]'); + +A better approach is to use runtime partial doubles: + +.. code-block:: php + + class MyClass + { + public function __construct() + { + echo "Original constructor called." . PHP_EOL; + // Other side-effects can happen... + } + } + + // This will not print anything + $mock = \Mockery::mock('MyClass')->makePartial(); + $mock->shouldReceive('foo'); + +This is one of the reason why we don't recommend using generated partial test +doubles, but if possible, always use the runtime partials. + +Read more about :ref:`creating-test-doubles-partial-test-doubles`. + +.. note:: + + The way generated partial test doubles work, is a BC break. If you use a + really old version of Mockery, it might behave in a way that the constructor + is not being called for these generated partials. In the case if you upgrade + to a more recent version of Mockery, you'll probably have to change your + tests to use runtime partials, instead of generated ones. + + This change was introduced in early 2013, so it is highly unlikely that you + are using a Mockery from before that, so this should not be an issue. diff --git a/vendor/mockery/mockery/docs/getting_started/index.rst b/vendor/mockery/mockery/docs/getting_started/index.rst new file mode 100644 index 00000000..434755c8 --- /dev/null +++ b/vendor/mockery/mockery/docs/getting_started/index.rst @@ -0,0 +1,12 @@ +Getting Started +=============== + +.. toctree:: + :hidden: + + installation + upgrading + simple_example + quick_reference + +.. include:: map.rst.inc diff --git a/vendor/mockery/mockery/docs/getting_started/installation.rst b/vendor/mockery/mockery/docs/getting_started/installation.rst new file mode 100644 index 00000000..f578adc9 --- /dev/null +++ b/vendor/mockery/mockery/docs/getting_started/installation.rst @@ -0,0 +1,49 @@ +.. index:: + single: Installation + +Installation +============ + +Mockery can be installed using Composer or by cloning it from its GitHub +repository. These two options are outlined below. + +Composer +-------- + +You can read more about Composer on `getcomposer.org `_. +To install Mockery using Composer, first install Composer for your project +using the instructions on the `Composer download page `_. +You can then define your development dependency on Mockery using the suggested +parameters below. While every effort is made to keep the master branch stable, +you may prefer to use the current stable version tag instead (use the +``@stable`` tag). + +.. code-block:: json + + { + "require-dev": { + "mockery/mockery": "dev-master" + } + } + +To install, you then may call: + +.. code-block:: bash + + php composer.phar update + +This will install Mockery as a development dependency, meaning it won't be +installed when using ``php composer.phar update --no-dev`` in production. + +Other way to install is directly from composer command line, as below. + +.. code-block:: bash + + php composer.phar require --dev mockery/mockery + +Git +--- + +The Git repository hosts the development version in its master branch. You can +install this using Composer by referencing ``dev-master`` as your preferred +version in your project's ``composer.json`` file as the earlier example shows. diff --git a/vendor/mockery/mockery/docs/getting_started/map.rst.inc b/vendor/mockery/mockery/docs/getting_started/map.rst.inc new file mode 100644 index 00000000..1055945b --- /dev/null +++ b/vendor/mockery/mockery/docs/getting_started/map.rst.inc @@ -0,0 +1,4 @@ +* :doc:`/getting_started/installation` +* :doc:`/getting_started/upgrading` +* :doc:`/getting_started/simple_example` +* :doc:`/getting_started/quick_reference` diff --git a/vendor/mockery/mockery/docs/getting_started/quick_reference.rst b/vendor/mockery/mockery/docs/getting_started/quick_reference.rst new file mode 100644 index 00000000..e729a850 --- /dev/null +++ b/vendor/mockery/mockery/docs/getting_started/quick_reference.rst @@ -0,0 +1,200 @@ +.. index:: + single: Quick Reference + +Quick Reference +=============== + +The purpose of this page is to give a quick and short overview of some of the +most common Mockery features. + +Do read the :doc:`../reference/index` to learn about all the Mockery features. + +Integrate Mockery with PHPUnit, either by extending the ``MockeryTestCase``: + +.. code-block:: php + + use \Mockery\Adapter\Phpunit\MockeryTestCase; + + class MyTest extends MockeryTestCase + { + } + +or by using the ``MockeryPHPUnitIntegration`` trait: + +.. code-block:: php + + use \PHPUnit\Framework\TestCase; + use \Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; + + class MyTest extends TestCase + { + use MockeryPHPUnitIntegration; + } + +Creating a test double: + +.. code-block:: php + + $testDouble = \Mockery::mock('MyClass'); + +Creating a test double that implements a certain interface: + +.. code-block:: php + + $testDouble = \Mockery::mock('MyClass, MyInterface'); + +Expecting a method to be called on a test double: + +.. code-block:: php + + $testDouble = \Mockery::mock('MyClass'); + $testDouble->shouldReceive('foo'); + +Expecting a method to **not** be called on a test double: + +.. code-block:: php + + $testDouble = \Mockery::mock('MyClass'); + $testDouble->shouldNotReceive('foo'); + +Expecting a method to be called on a test double, once, with a certain argument, +and to return a value: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('foo') + ->once() + ->with($arg) + ->andReturn($returnValue); + +Expecting a method to be called on a test double and to return a different value +for each successive call: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('foo') + ->andReturn(1, 2, 3); + + $mock->foo(); // int(1); + $mock->foo(); // int(2); + $mock->foo(); // int(3); + $mock->foo(); // int(3); + +Creating a runtime partial test double: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass')->makePartial(); + +Creating a spy: + +.. code-block:: php + + $spy = \Mockery::spy('MyClass'); + +Expecting that a spy should have received a method call: + +.. code-block:: php + + $spy = \Mockery::spy('MyClass'); + + $spy->foo(); + + $spy->shouldHaveReceived()->foo(); + +Not so simple examples +^^^^^^^^^^^^^^^^^^^^^^ + +Creating a mock object to return a sequence of values from a set of method +calls: + +.. code-block:: php + + use \Mockery\Adapter\Phpunit\MockeryTestCase; + + class SimpleTest extends MockeryTestCase + { + public function testSimpleMock() + { + $mock = \Mockery::mock(array('pi' => 3.1416, 'e' => 2.71)); + $this->assertEquals(3.1416, $mock->pi()); + $this->assertEquals(2.71, $mock->e()); + } + } + +Creating a mock object which returns a self-chaining Undefined object for a +method call: + +.. code-block:: php + + use \Mockery\Adapter\Phpunit\MockeryTestCase; + + class UndefinedTest extends MockeryTestCase + { + public function testUndefinedValues() + { + $mock = \Mockery::mock('mymock'); + $mock->shouldReceive('divideBy')->with(0)->andReturnUndefined(); + $this->assertTrue($mock->divideBy(0) instanceof \Mockery\Undefined); + } + } + +Creating a mock object with multiple query calls and a single update call: + +.. code-block:: php + + use \Mockery\Adapter\Phpunit\MockeryTestCase; + + class DbTest extends MockeryTestCase + { + public function testDbAdapter() + { + $mock = \Mockery::mock('db'); + $mock->shouldReceive('query')->andReturn(1, 2, 3); + $mock->shouldReceive('update')->with(5)->andReturn(NULL)->once(); + + // ... test code here using the mock + } + } + +Expecting all queries to be executed before any updates: + +.. code-block:: php + + use \Mockery\Adapter\Phpunit\MockeryTestCase; + + class DbTest extends MockeryTestCase + { + public function testQueryAndUpdateOrder() + { + $mock = \Mockery::mock('db'); + $mock->shouldReceive('query')->andReturn(1, 2, 3)->ordered(); + $mock->shouldReceive('update')->andReturn(NULL)->once()->ordered(); + + // ... test code here using the mock + } + } + +Creating a mock object where all queries occur after startup, but before finish, +and where queries are expected with several different params: + +.. code-block:: php + + use \Mockery\Adapter\Phpunit\MockeryTestCase; + + class DbTest extends MockeryTestCase + { + public function testOrderedQueries() + { + $db = \Mockery::mock('db'); + $db->shouldReceive('startup')->once()->ordered(); + $db->shouldReceive('query')->with('CPWR')->andReturn(12.3)->once()->ordered('queries'); + $db->shouldReceive('query')->with('MSFT')->andReturn(10.0)->once()->ordered('queries'); + $db->shouldReceive('query')->with(\Mockery::pattern("/^....$/"))->andReturn(3.3)->atLeast()->once()->ordered('queries'); + $db->shouldReceive('finish')->once()->ordered(); + + // ... test code here using the mock + } + } diff --git a/vendor/mockery/mockery/docs/getting_started/simple_example.rst b/vendor/mockery/mockery/docs/getting_started/simple_example.rst new file mode 100644 index 00000000..32ee2691 --- /dev/null +++ b/vendor/mockery/mockery/docs/getting_started/simple_example.rst @@ -0,0 +1,70 @@ +.. index:: + single: Getting Started; Simple Example + +Simple Example +============== + +Imagine we have a ``Temperature`` class which samples the temperature of a +locale before reporting an average temperature. The data could come from a web +service or any other data source, but we do not have such a class at present. +We can, however, assume some basic interactions with such a class based on its +interaction with the ``Temperature`` class: + +.. code-block:: php + + class Temperature + { + private $service; + + public function __construct($service) + { + $this->service = $service; + } + + public function average() + { + $total = 0; + for ($i=0; $i<3; $i++) { + $total += $this->service->readTemp(); + } + return $total/3; + } + } + +Even without an actual service class, we can see how we expect it to operate. +When writing a test for the ``Temperature`` class, we can now substitute a +mock object for the real service which allows us to test the behaviour of the +``Temperature`` class without actually needing a concrete service instance. + +.. code-block:: php + + use \Mockery; + + class TemperatureTest extends \PHPUnit\Framework\TestCase + { + public function tearDown() + { + Mockery::close(); + } + + public function testGetsAverageTemperatureFromThreeServiceReadings() + { + $service = Mockery::mock('service'); + $service->shouldReceive('readTemp') + ->times(3) + ->andReturn(10, 12, 14); + + $temperature = new Temperature($service); + + $this->assertEquals(12, $temperature->average()); + } + } + +We create a mock object which our ``Temperature`` class will use and set some +expectations for that mock — that it should receive three calls to the ``readTemp`` +method, and these calls will return 10, 12, and 14 as results. + +.. note:: + + PHPUnit integration can remove the need for a ``tearDown()`` method. See + ":doc:`/reference/phpunit_integration`" for more information. diff --git a/vendor/mockery/mockery/docs/getting_started/upgrading.rst b/vendor/mockery/mockery/docs/getting_started/upgrading.rst new file mode 100644 index 00000000..7201e597 --- /dev/null +++ b/vendor/mockery/mockery/docs/getting_started/upgrading.rst @@ -0,0 +1,82 @@ +.. index:: + single: Upgrading + +Upgrading +========= + +Upgrading to 1.0.0 +------------------ + +Minimum PHP version ++++++++++++++++++++ + +As of Mockery 1.0.0 the minimum PHP version required is 5.6. + +Using Mockery with PHPUnit +++++++++++++++++++++++++++ + +In the "old days", 0.9.x and older, the way Mockery was integrated with PHPUnit was +through a PHPUnit listener. That listener would in turn call the ``\Mockery::close()`` +method for us. + +As of 1.0.0, PHPUnit test cases where we want to use Mockery, should either use the +``\Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration`` trait, or extend the +``\Mockery\Adapter\Phpunit\MockeryTestCase`` test case. This will in turn call the +``\Mockery::close()`` method for us. + +Read the documentation for a detailed overview of ":doc:`/reference/phpunit_integration`". + +``\Mockery\Matcher\MustBe`` is deprecated ++++++++++++++++++++++++++++++++++++++++++ + +As of 1.0.0 the ``\Mockery\Matcher\MustBe`` matcher is deprecated and will be removed in +Mockery 2.0.0. We recommend instead to use the PHPUnit or Hamcrest equivalents of the +MustBe matcher. + +``allows`` and ``expects`` +++++++++++++++++++++++++++ + +As of 1.0.0, Mockery has two new methods to set up expectations: ``allows`` and ``expects``. +This means that these methods names are now "reserved" for Mockery, or in other words +classes you want to mock with Mockery, can't have methods called ``allows`` or ``expects``. + +Read more in the documentation about this ":doc:`/reference/alternative_should_receive_syntax`". + +No more implicit regex matching for string arguments +++++++++++++++++++++++++++++++++++++++++++++++++++++ + +When setting up string arguments in method expectations, Mockery 0.9.x and older, would try +to match arguments using a regular expression in a "last attempt" scenario. + +As of 1.0.0, Mockery will no longer attempt to do this regex matching, but will only try +first the identical operator ``===``, and failing that, the equals operator ``==``. + +If you want to match an argument using regular expressions, please use the new +``\Mockery\Matcher\Pattern`` matcher. Read more in the documentation about this +pattern matcher in the ":doc:`/reference/argument_validation`" section. + +``andThrow`` ``\Throwable`` ++++++++++++++++++++++++++++ + +As of 1.0.0, the ``andThrow`` can now throw any ``\Throwable``. + +Upgrading to 0.9 +---------------- + +The generator was completely rewritten, so any code with a deep integration to +mockery will need evaluating. + +Upgrading to 0.8 +---------------- + +Since the release of 0.8.0 the following behaviours were altered: + +1. The ``shouldIgnoreMissing()`` behaviour optionally applied to mock objects + returned an instance of ``\Mockery\Undefined`` when methods called did not + match a known expectation. Since 0.8.0, this behaviour was switched to + returning ``null`` instead. You can restore the 0.7.2 behaviour by using the + following: + + .. code-block:: php + + $mock = \Mockery::mock('stdClass')->shouldIgnoreMissing()->asUndefined(); diff --git a/vendor/mockery/mockery/docs/index.rst b/vendor/mockery/mockery/docs/index.rst new file mode 100644 index 00000000..f8cbbd32 --- /dev/null +++ b/vendor/mockery/mockery/docs/index.rst @@ -0,0 +1,76 @@ +Mockery +======= + +Mockery is a simple yet flexible PHP mock object framework for use in unit +testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is +to offer a test double framework with a succinct API capable of clearly +defining all possible object operations and interactions using a human +readable Domain Specific Language (DSL). Designed as a drop in alternative to +PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with +PHPUnit and can operate alongside phpunit-mock-objects without the World +ending. + +Mock Objects +------------ + +In unit tests, mock objects simulate the behaviour of real objects. They are +commonly utilised to offer test isolation, to stand in for objects which do +not yet exist, or to allow for the exploratory design of class APIs without +requiring actual implementation up front. + +The benefits of a mock object framework are to allow for the flexible +generation of such mock objects (and stubs). They allow the setting of +expected method calls and return values using a flexible API which is capable +of capturing every possible real object behaviour in way that is stated as +close as possible to a natural language description. + +Getting Started +--------------- + +Ready to dive into the Mockery framework? Then you can get started by reading +the "Getting Started" section! + +.. toctree:: + :hidden: + + getting_started/index + +.. include:: getting_started/map.rst.inc + +Reference +--------- + +The reference contains a complete overview of all features of the Mockery +framework. + +.. toctree:: + :hidden: + + reference/index + +.. include:: reference/map.rst.inc + +Mockery +------- + +Learn about Mockery's configuration, reserved method names, exceptions... + +.. toctree:: + :hidden: + + mockery/index + +.. include:: mockery/map.rst.inc + +Cookbook +-------- + +Want to learn some easy tips and tricks? Take a look at the cookbook articles! + +.. toctree:: + :hidden: + + cookbook/index + +.. include:: cookbook/map.rst.inc + diff --git a/vendor/mockery/mockery/docs/mockery/configuration.rst b/vendor/mockery/mockery/docs/mockery/configuration.rst new file mode 100644 index 00000000..00713367 --- /dev/null +++ b/vendor/mockery/mockery/docs/mockery/configuration.rst @@ -0,0 +1,94 @@ +.. index:: + single: Mockery; Configuration + +Mockery Global Configuration +============================ + +To allow for a degree of fine-tuning, Mockery utilises a singleton +configuration object to store a small subset of core behaviours. The three +currently present include: + +* Option to allow/disallow the mocking of methods which do not actually exist + fulfilled (i.e. unused) +* Setter/Getter for added a parameter map for internal PHP class methods + (``Reflection`` cannot detect these automatically) +* Option to drive if quick definitions should define a stub or a mock with + an 'at least once' expectation. + +By default, the first behaviour is enabled. Of course, there are +situations where this can lead to unintended consequences. The mocking of +non-existent methods may allow mocks based on real classes/objects to fall out +of sync with the actual implementations, especially when some degree of +integration testing (testing of object wiring) is not being performed. + +You may allow or disallow this behaviour (whether for whole test suites or +just select tests) by using the following call: + +.. code-block:: php + + \Mockery::getConfiguration()->allowMockingNonExistentMethods(bool); + +Passing a true allows the behaviour, false disallows it. It takes effect +immediately until switched back. If the behaviour is detected when not allowed, +it will result in an Exception being thrown at that point. Note that disallowing +this behaviour should be carefully considered since it necessarily removes at +least some of Mockery's flexibility. + +The other two methods are: + +.. code-block:: php + + \Mockery::getConfiguration()->setInternalClassMethodParamMap($class, $method, array $paramMap) + \Mockery::getConfiguration()->getInternalClassMethodParamMap($class, $method) + +These are used to define parameters (i.e. the signature string of each) for the +methods of internal PHP classes (e.g. SPL, or PECL extension classes like +ext/mongo's MongoCollection. Reflection cannot analyse the parameters of internal +classes. Most of the time, you never need to do this. It's mainly needed where an +internal class method uses pass-by-reference for a parameter - you MUST in such +cases ensure the parameter signature includes the ``&`` symbol correctly as Mockery +won't correctly add it automatically for internal classes. Note that internal class +parameter overriding is not available in PHP 8. This is because incompatible +signatures have been reclassified as fatal errors. + +Finally there is the possibility to change what a quick definition produces. +By default quick definitions create stubs but you can change this behaviour +by asking Mockery to use 'at least once' expectations. + +.. code-block:: php + + \Mockery::getConfiguration()->getQuickDefinitions()->shouldBeCalledAtLeastOnce(bool) + +Passing a true allows the behaviour, false disallows it. It takes effect +immediately until switched back. By doing so you can avoid the proliferating of +quick definitions that accumulate overtime in your code since the test would +fail in case the 'at least once' expectation is not fulfilled. + +Disabling reflection caching +---------------------------- + +Mockery heavily uses `"reflection" `_ +to do it's job. To speed up things, Mockery caches internally the information it +gathers via reflection. In some cases, this caching can cause problems. + +The **only** known situation when this occurs is when PHPUnit's ``--static-backup`` option +is used. If you use ``--static-backup`` and you get an error that looks like the +following: + +.. code-block:: php + + Error: Internal error: Failed to retrieve the reflection object + +We suggest turning off the reflection cache as so: + +.. code-block:: php + + \Mockery::getConfiguration()->disableReflectionCache(); + +Turning it back on can be done like so: + +.. code-block:: php + + \Mockery::getConfiguration()->enableReflectionCache(); + +In no other situation should you be required turn this reflection cache off. diff --git a/vendor/mockery/mockery/docs/mockery/exceptions.rst b/vendor/mockery/mockery/docs/mockery/exceptions.rst new file mode 100644 index 00000000..623b158e --- /dev/null +++ b/vendor/mockery/mockery/docs/mockery/exceptions.rst @@ -0,0 +1,65 @@ +.. index:: + single: Mockery; Exceptions + +Mockery Exceptions +================== + +Mockery throws three types of exceptions when it cannot verify a mock object. + +#. ``\Mockery\Exception\InvalidCountException`` +#. ``\Mockery\Exception\InvalidOrderException`` +#. ``\Mockery\Exception\NoMatchingExpectationException`` + +You can capture any of these exceptions in a try...catch block to query them +for specific information which is also passed along in the exception message +but is provided separately from getters should they be useful when logging or +reformatting output. + +\Mockery\Exception\InvalidCountException +---------------------------------------- + +The exception class is used when a method is called too many (or too few) +times and offers the following methods: + +* ``getMock()`` - return actual mock object +* ``getMockName()`` - return the name of the mock object +* ``getMethodName()`` - return the name of the method the failing expectation + is attached to +* ``getExpectedCount()`` - return expected calls +* ``getExpectedCountComparative()`` - returns a string, e.g. ``<=`` used to + compare to actual count +* ``getActualCount()`` - return actual calls made with given argument + constraints + +\Mockery\Exception\InvalidOrderException +---------------------------------------- + +The exception class is used when a method is called outside the expected order +set using the ``ordered()`` and ``globally()`` expectation modifiers. It +offers the following methods: + +* ``getMock()`` - return actual mock object +* ``getMockName()`` - return the name of the mock object +* ``getMethodName()`` - return the name of the method the failing expectation + is attached to +* ``getExpectedOrder()`` - returns an integer represented the expected index + for which this call was expected +* ``getActualOrder()`` - return the actual index at which this method call + occurred. + +\Mockery\Exception\NoMatchingExpectationException +------------------------------------------------- + +The exception class is used when a method call does not match any known +expectation. All expectations are uniquely identified in a mock object by the +method name and the list of expected arguments. You can disable this exception +and opt for returning NULL from all unexpected method calls by using the +earlier mentioned shouldIgnoreMissing() behaviour modifier. This exception +class offers the following methods: + +* ``getMock()`` - return actual mock object +* ``getMockName()`` - return the name of the mock object +* ``getMethodName()`` - return the name of the method the failing expectation + is attached to +* ``getActualArguments()`` - return actual arguments used to search for a + matching expectation diff --git a/vendor/mockery/mockery/docs/mockery/gotchas.rst b/vendor/mockery/mockery/docs/mockery/gotchas.rst new file mode 100644 index 00000000..92c566dd --- /dev/null +++ b/vendor/mockery/mockery/docs/mockery/gotchas.rst @@ -0,0 +1,44 @@ +.. index:: + single: Mockery; Gotchas + +Gotchas! +======== + +Mocking objects in PHP has its limitations and gotchas. Some functionality +can't be mocked or can't be mocked YET! If you locate such a circumstance, +please please (pretty please with sugar on top) create a new issue on GitHub +so it can be documented and resolved where possible. Here is a list to note: + +1. Classes containing public ``__wakeup()`` methods can be mocked but the + mocked ``__wakeup()`` method will perform no actions and cannot have + expectations set for it. This is necessary since Mockery must serialize and + unserialize objects to avoid some ``__construct()`` insanity and attempting + to mock a ``__wakeup()`` method as normal leads to a + ``BadMethodCallException`` being thrown. + +2. Mockery has two scenarios where real classes are replaced: Instance mocks + and alias mocks. Both will generate PHP fatal errors if the real class is + loaded, usually via a require or include statement. Only use these two mock + types where autoloading is in place and where classes are not explicitly + loaded on a per-file basis using ``require()``, ``require_once()``, etc. + +3. Internal PHP classes are not entirely capable of being fully analysed using + ``Reflection``. For example, ``Reflection`` cannot reveal details of + expected parameters to the methods of such internal classes. As a result, + there will be problems where a method parameter is defined to accept a + value by reference (Mockery cannot detect this condition and will assume a + pass by value on scalars and arrays). If references as internal class + method parameters are needed, you should use the + ``\Mockery\Configuration::setInternalClassMethodParamMap()`` method. + Note, however that internal class parameter overriding is not available in + PHP 8 since incompatible signatures have been reclassified as fatal errors. + +4. Creating a mock implementing a certain interface with incorrect case in the + interface name, and then creating a second mock implementing the same + interface, but this time with the correct case, will have undefined behavior + due to PHP's ``class_exists`` and related functions being case insensitive. + Using the ``::class`` keyword in PHP can help you avoid these mistakes. + +The gotchas noted above are largely down to PHP's architecture and are assumed +to be unavoidable. But - if you figure out a solution (or a better one than +what may exist), let us know! diff --git a/vendor/mockery/mockery/docs/mockery/index.rst b/vendor/mockery/mockery/docs/mockery/index.rst new file mode 100644 index 00000000..b698d6cb --- /dev/null +++ b/vendor/mockery/mockery/docs/mockery/index.rst @@ -0,0 +1,12 @@ +Mockery +======= + +.. toctree:: + :hidden: + + configuration + exceptions + reserved_method_names + gotchas + +.. include:: map.rst.inc diff --git a/vendor/mockery/mockery/docs/mockery/map.rst.inc b/vendor/mockery/mockery/docs/mockery/map.rst.inc new file mode 100644 index 00000000..46ffa975 --- /dev/null +++ b/vendor/mockery/mockery/docs/mockery/map.rst.inc @@ -0,0 +1,4 @@ +* :doc:`/mockery/configuration` +* :doc:`/mockery/exceptions` +* :doc:`/mockery/reserved_method_names` +* :doc:`/mockery/gotchas` diff --git a/vendor/mockery/mockery/docs/mockery/reserved_method_names.rst b/vendor/mockery/mockery/docs/mockery/reserved_method_names.rst new file mode 100644 index 00000000..5ad58d40 --- /dev/null +++ b/vendor/mockery/mockery/docs/mockery/reserved_method_names.rst @@ -0,0 +1,33 @@ +.. index:: + single: Reserved Method Names + +Reserved Method Names +===================== + +As you may have noticed, Mockery uses a number of methods called directly on +all mock objects, for example ``shouldReceive()``. Such methods are necessary +in order to setup expectations on the given mock, and so they cannot be +implemented on the classes or objects being mocked without creating a method +name collision (reported as a PHP fatal error). The methods reserved by +Mockery are: + +* ``shouldReceive()`` +* ``shouldNotReceive()`` +* ``allows()`` +* ``expects()`` +* ``shouldAllowMockingMethod()`` +* ``shouldIgnoreMissing()`` +* ``asUndefined()`` +* ``shouldAllowMockingProtectedMethods()`` +* ``makePartial()`` +* ``byDefault()`` +* ``shouldHaveReceived()`` +* ``shouldHaveBeenCalled()`` +* ``shouldNotHaveReceived()`` +* ``shouldNotHaveBeenCalled()`` + + +In addition, all mocks utilise a set of added methods and protected properties +which cannot exist on the class or object being mocked. These are far less +likely to cause collisions. All properties are prefixed with ``_mockery`` and +all method names with ``mockery_``. diff --git a/vendor/mockery/mockery/docs/reference/alternative_should_receive_syntax.rst b/vendor/mockery/mockery/docs/reference/alternative_should_receive_syntax.rst new file mode 100644 index 00000000..78c1e83c --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/alternative_should_receive_syntax.rst @@ -0,0 +1,91 @@ +.. index:: + single: Alternative shouldReceive Syntax + +Alternative shouldReceive Syntax +================================ + +As of Mockery 1.0.0, we support calling methods as we would call any PHP method, +and not as string arguments to Mockery ``should*`` methods. + +The two Mockery methods that enable this are ``allows()`` and ``expects()``. + +Allows +------ + +We use ``allows()`` when we create stubs for methods that return a predefined +return value, but for these method stubs we don't care how many times, or if at +all, were they called. + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->allows([ + 'name_of_method_1' => 'return value', + 'name_of_method_2' => 'return value', + ]); + +This is equivalent with the following ``shouldReceive`` syntax: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive([ + 'name_of_method_1' => 'return value', + 'name_of_method_2' => 'return value', + ]); + +Note that with this format, we also tell Mockery that we don't care about the +arguments to the stubbed methods. + +If we do care about the arguments, we would do it like so: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->allows() + ->name_of_method_1($arg1) + ->andReturn('return value'); + +This is equivalent with the following ``shouldReceive`` syntax: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method_1') + ->with($arg1) + ->andReturn('return value'); + +Expects +------- + +We use ``expects()`` when we want to verify that a particular method was called: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->expects() + ->name_of_method_1($arg1) + ->andReturn('return value'); + +This is equivalent with the following ``shouldReceive`` syntax: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method_1') + ->once() + ->with($arg1) + ->andReturn('return value'); + +By default ``expects()`` sets up an expectation that the method should be called +once and once only. If we expect more than one call to the method, we can change +that expectation: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->expects() + ->name_of_method_1($arg1) + ->twice() + ->andReturn('return value'); + diff --git a/vendor/mockery/mockery/docs/reference/argument_validation.rst b/vendor/mockery/mockery/docs/reference/argument_validation.rst new file mode 100644 index 00000000..9351ce40 --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/argument_validation.rst @@ -0,0 +1,338 @@ +.. index:: + single: Argument Validation + +Argument Validation +=================== + +The arguments passed to the ``with()`` declaration when setting up an +expectation determine the criteria for matching method calls to expectations. +Thus, we can setup up many expectations for a single method, each +differentiated by the expected arguments. Such argument matching is done on a +"best fit" basis. This ensures explicit matches take precedence over +generalised matches. + +An explicit match is merely where the expected argument and the actual +argument are easily equated (i.e. using ``===`` or ``==``). More generalised +matches are possible using regular expressions, class hinting and the +available generic matchers. The purpose of generalised matchers is to allow +arguments be defined in non-explicit terms, e.g. ``Mockery::any()`` passed to +``with()`` will match **any** argument in that position. + +Mockery's generic matchers do not cover all possibilities but offers optional +support for the Hamcrest library of matchers. Hamcrest is a PHP port of the +similarly named Java library (which has been ported also to Python, Erlang, +etc). By using Hamcrest, Mockery does not need to duplicate Hamcrest's already +impressive utility which itself promotes a natural English DSL. + +The examples below show Mockery matchers and their Hamcrest equivalent, if there +is one. Hamcrest uses functions (no namespacing). + +.. note:: + + If you don't wish to use the global Hamcrest functions, they are all exposed + through the ``\Hamcrest\Matchers`` class as well, as static methods. Thus, + ``identicalTo($arg)`` is the same as ``\Hamcrest\Matchers::identicalTo($arg)`` + +The most common matcher is the ``with()`` matcher: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('foo') + ->with(1): + +It tells mockery that it should receive a call to the ``foo`` method with the +integer ``1`` as an argument. In cases like this, Mockery first tries to match +the arguments using ``===`` (identical) comparison operator. If the argument is +a primitive, and if it fails the identical comparison, Mockery does a fallback +to the ``==`` (equals) comparison operator. + +When matching objects as arguments, Mockery only does the strict ``===`` +comparison, which means only the same ``$object`` will match: + +.. code-block:: php + + $object = new stdClass(); + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive("foo") + ->with($object); + + // Hamcrest equivalent + $mock->shouldReceive("foo") + ->with(identicalTo($object)); + +A different instance of ``stdClass`` will **not** match. + +.. note:: + + The ``Mockery\Matcher\MustBe`` matcher has been deprecated. + +If we need a loose comparison of objects, we can do that using Hamcrest's +``equalTo`` matcher: + +.. code-block:: php + + $mock->shouldReceive("foo") + ->with(equalTo(new stdClass)); + +In cases when we don't care about the type, or the value of an argument, just +that any argument is present, we use ``any()``: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive("foo") + ->with(\Mockery::any()); + + // Hamcrest equivalent + $mock->shouldReceive("foo") + ->with(anything()) + +Anything and everything passed in this argument slot is passed unconstrained. + +Validating Types and Resources +------------------------------ + +The ``type()`` matcher accepts any string which can be attached to ``is_`` to +form a valid type check. + +To match any PHP resource, we could do the following: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive("foo") + ->with(\Mockery::type('resource')); + + // Hamcrest equivalents + $mock->shouldReceive("foo") + ->with(resourceValue()); + $mock->shouldReceive("foo") + ->with(typeOf('resource')); + +It will return a ``true`` from an ``is_resource()`` call, if the provided +argument to the method is a PHP resource. For example, ``\Mockery::type('float')`` +or Hamcrest's ``floatValue()`` and ``typeOf('float')`` checks use ``is_float()``, +and ``\Mockery::type('callable')`` or Hamcrest's ``callable()`` uses +``is_callable()``. + +The ``type()`` matcher also accepts a class or interface name to be used in an +``instanceof`` evaluation of the actual argument. Hamcrest uses ``anInstanceOf()``. + +A full list of the type checkers is available at +`php.net `_ or browse Hamcrest's function +list in +`the Hamcrest code `_. + +.. _argument-validation-complex-argument-validation: + +Complex Argument Validation +--------------------------- + +If we want to perform a complex argument validation, the ``on()`` matcher is +invaluable. It accepts a closure (anonymous function) to which the actual +argument will be passed. + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive("foo") + ->with(\Mockery::on(closure)); + +If the closure evaluates to (i.e. returns) boolean ``true`` then the argument is +assumed to have matched the expectation. + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + + $mock->shouldReceive('foo') + ->with(\Mockery::on(function ($argument) { + if ($argument % 2 == 0) { + return true; + } + return false; + })); + + $mock->foo(4); // matches the expectation + $mock->foo(3); // throws a NoMatchingExpectationException + +.. note:: + + There is no Hamcrest version of the ``on()`` matcher. + +We can also perform argument validation by passing a closure to ``withArgs()`` +method. The closure will receive all arguments passed in the call to the expected +method and if it evaluates (i.e. returns) to boolean ``true``, then the list of +arguments is assumed to have matched the expectation: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive("foo") + ->withArgs(closure); + +The closure can also handle optional parameters, so if an optional parameter is +missing in the call to the expected method, it doesn't necessary means that the +list of arguments doesn't match the expectation. + +.. code-block:: php + + $closure = function ($odd, $even, $sum = null) { + $result = ($odd % 2 != 0) && ($even % 2 == 0); + if (!is_null($sum)) { + return $result && ($odd + $even == $sum); + } + return $result; + }; + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('foo')->withArgs($closure); + + $mock->foo(1, 2); // It matches the expectation: the optional argument is not needed + $mock->foo(1, 2, 3); // It also matches the expectation: the optional argument pass the validation + $mock->foo(1, 2, 4); // It doesn't match the expectation: the optional doesn't pass the validation + +.. note:: + + In previous versions, Mockery's ``with()`` would attempt to do a pattern + matching against the arguments, attempting to use the argument as a + regular expression. Over time this proved to be not such a great idea, so + we removed this functionality, and have introduced ``Mockery::pattern()`` + instead. + +If we would like to match an argument against a regular expression, we can use +the ``\Mockery::pattern()``: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('foo') + ->with(\Mockery::pattern('/^foo/')); + + // Hamcrest equivalent + $mock->shouldReceive('foo') + ->with(matchesPattern('/^foo/')); + +The ``ducktype()`` matcher is an alternative to matching by class type: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('foo') + ->with(\Mockery::ducktype('foo', 'bar')); + +It matches any argument which is an object containing the provided list of +methods to call. + +.. note:: + + There is no Hamcrest version of the ``ducktype()`` matcher. + +Capturing Arguments +------------------- + +If we want to perform multiple validations on a single argument, the ``capture`` +matcher provides a streamlined alternative to using the ``on()`` matcher. +It accepts a variable which the actual argument will be assigned. + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive("foo") + ->with(\Mockery::capture($bar)); + +This will assign *any* argument passed to ``foo`` to the local ``$bar`` variable to +then perform additional validation using assertions. + +.. note:: + + The ``capture`` matcher always evaluates to ``true``. As such, we should always + perform additional argument validation. + +Additional Argument Matchers +---------------------------- + +The ``not()`` matcher matches any argument which is not equal or identical to +the matcher's parameter: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('foo') + ->with(\Mockery::not(2)); + + // Hamcrest equivalent + $mock->shouldReceive('foo') + ->with(not(2)); + +``anyOf()`` matches any argument which equals any one of the given parameters: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('foo') + ->with(\Mockery::anyOf(1, 2)); + + // Hamcrest equivalent + $mock->shouldReceive('foo') + ->with(anyOf(1,2)); + +``notAnyOf()`` matches any argument which is not equal or identical to any of +the given parameters: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('foo') + ->with(\Mockery::notAnyOf(1, 2)); + +.. note:: + + There is no Hamcrest version of the ``notAnyOf()`` matcher. + +``subset()`` matches any argument which is any array containing the given array +subset: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('foo') + ->with(\Mockery::subset(array(0 => 'foo'))); + +This enforces both key naming and values, i.e. both the key and value of each +actual element is compared. + +.. note:: + + There is no Hamcrest version of this functionality, though Hamcrest can check + a single entry using ``hasEntry()`` or ``hasKeyValuePair()``. + +``contains()`` matches any argument which is an array containing the listed +values: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('foo') + ->with(\Mockery::contains(value1, value2)); + +The naming of keys is ignored. + +``hasKey()`` matches any argument which is an array containing the given key +name: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('foo') + ->with(\Mockery::hasKey(key)); + +``hasValue()`` matches any argument which is an array containing the given +value: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('foo') + ->with(\Mockery::hasValue(value)); diff --git a/vendor/mockery/mockery/docs/reference/creating_test_doubles.rst b/vendor/mockery/mockery/docs/reference/creating_test_doubles.rst new file mode 100644 index 00000000..6f8f8c3f --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/creating_test_doubles.rst @@ -0,0 +1,435 @@ +.. index:: + single: Reference; Creating Test Doubles + +Creating Test Doubles +===================== + +Mockery's main goal is to help us create test doubles. It can create stubs, +mocks, and spies. + +Stubs and mocks are created the same. The difference between the two is that a +stub only returns a preset result when called, while a mock needs to have +expectations set on the method calls it expects to receive. + +Spies are a type of test doubles that keep track of the calls they received, and +allow us to inspect these calls after the fact. + +When creating a test double object, we can pass in an identifier as a name for +our test double. If we pass it no identifier, the test double name will be +unknown. Furthermore, the identifier does not have to be a class name. It is a +good practice, and our recommendation, to always name the test doubles with the +same name as the underlying class we are creating test doubles for. + +If the identifier we use for our test double is a name of an existing class, +the test double will inherit the type of the class (via inheritance), i.e. the +mock object will pass type hints or ``instanceof`` evaluations for the existing +class. This is useful when a test double must be of a specific type, to satisfy +the expectations our code has. + +Stubs and mocks +--------------- + +Stubs and mocks are created by calling the ``\Mockery::mock()`` method. The +following example shows how to create a stub, or a mock, object named "foo": + +.. code-block:: php + + $mock = \Mockery::mock('foo'); + +The mock object created like this is the loosest form of mocks possible, and is +an instance of ``\Mockery\MockInterface``. + +.. note:: + + All test doubles created with Mockery are an instance of + ``\Mockery\MockInterface``, regardless are they a stub, mock or a spy. + +To create a stub or a mock object with no name, we can call the ``mock()`` +method with no parameters: + +.. code-block:: php + + $mock = \Mockery::mock(); + +As we stated earlier, we don't recommend creating stub or mock objects without +a name. + +Classes, abstracts, interfaces +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The recommended way to create a stub or a mock object is by using a name of +an existing class we want to create a test double of: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + +This stub or mock object will have the type of ``MyClass``, through inheritance. + +Stub or mock objects can be based on any concrete class, abstract class or even +an interface. The primary purpose is to ensure the mock object inherits a +specific type for type hinting. + +.. code-block:: php + + $mock = \Mockery::mock('MyInterface'); + +This stub or mock object will implement the ``MyInterface`` interface. + +.. note:: + + Classes marked final, or classes that have methods marked final cannot be + mocked fully. Mockery supports creating partial mocks for these cases. + Partial mocks will be explained later in the documentation. + +Mockery also supports creating stub or mock objects based on a single existing +class, which must implement one or more interfaces. We can do this by providing +a comma-separated list of the class and interfaces as the first argument to the +``\Mockery::mock()`` method: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass, MyInterface, OtherInterface'); + +This stub or mock object will now be of type ``MyClass`` and implement the +``MyInterface`` and ``OtherInterface`` interfaces. + +.. note:: + + The class name doesn't need to be the first member of the list but it's a + friendly convention to use for readability. + +We can tell a mock to implement the desired interfaces by passing the list of +interfaces as the second argument: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass', 'MyInterface, OtherInterface'); + +For all intents and purposes, this is the same as the previous example. + +Spies +----- + +The third type of test doubles Mockery supports are spies. The main difference +between spies and mock objects is that with spies we verify the calls made +against our test double after the calls were made. We would use a spy when we +don't necessarily care about all of the calls that are going to be made to an +object. + +A spy will return ``null`` for all method calls it receives. It is not possible +to tell a spy what will be the return value of a method call. If we do that, then +we would deal with a mock object, and not with a spy. + +We create a spy by calling the ``\Mockery::spy()`` method: + +.. code-block:: php + + $spy = \Mockery::spy('MyClass'); + +Just as with stubs or mocks, we can tell Mockery to base a spy on any concrete +or abstract class, or to implement any number of interfaces: + +.. code-block:: php + + $spy = \Mockery::spy('MyClass, MyInterface, OtherInterface'); + +This spy will now be of type ``MyClass`` and implement the ``MyInterface`` and +``OtherInterface`` interfaces. + +.. note:: + + The ``\Mockery::spy()`` method call is actually a shorthand for calling + ``\Mockery::mock()->shouldIgnoreMissing()``. The ``shouldIgnoreMissing`` + method is a "behaviour modifier". We'll discuss them a bit later. + +Mocks vs. Spies +--------------- + +Let's try and illustrate the difference between mocks and spies with the +following example: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $spy = \Mockery::spy('MyClass'); + + $mock->shouldReceive('foo')->andReturn(42); + + $mockResult = $mock->foo(); + $spyResult = $spy->foo(); + + $spy->shouldHaveReceived()->foo(); + + var_dump($mockResult); // int(42) + var_dump($spyResult); // null + +As we can see from this example, with a mock object we set the call expectations +before the call itself, and we get the return result we expect it to return. +With a spy object on the other hand, we verify the call has happened after the +fact. The return result of a method call against a spy is always ``null``. + +We also have a dedicated chapter to :doc:`spies` only. + +.. _creating-test-doubles-partial-test-doubles: + +Partial Test Doubles +-------------------- + +Partial doubles are useful when we want to stub out, set expectations for, or +spy on *some* methods of a class, but run the actual code for other methods. + +We differentiate between three types of partial test doubles: + + * runtime partial test doubles, + * generated partial test doubles, and + * proxied partial test doubles. + +Runtime partial test doubles +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +What we call a runtime partial, involves creating a test double and then telling +it to make itself partial. Any method calls that the double hasn't been told to +allow or expect, will act as they would on a normal instance of the object. + +.. code-block:: php + + class Foo { + function foo() { return 123; } + function bar() { return $this->foo(); } + } + + $foo = mock(Foo::class)->makePartial(); + $foo->foo(); // int(123); + +We can then tell the test double to allow or expect calls as with any other +Mockery double. + +.. code-block:: php + + $foo->shouldReceive('foo')->andReturn(456); + $foo->bar(); // int(456) + +See the cookbook entry on :doc:`../cookbook/big_parent_class` for an example +usage of runtime partial test doubles. + +Generated partial test doubles +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The second type of partial double we can create is what we call a generated +partial. With generated partials, we specifically tell Mockery which methods +we want to be able to allow or expect calls to. All other methods will run the +actual code *directly*, so stubs and expectations on these methods will not +work. + +.. code-block:: php + + class Foo { + function foo() { return 123; } + function bar() { return $this->foo(); } + } + + $foo = mock("Foo[foo]"); + + $foo->foo(); // error, no expectation set + + $foo->shouldReceive('foo')->andReturn(456); + $foo->foo(); // int(456) + + // setting an expectation for this has no effect + $foo->shouldReceive('bar')->andReturn(999); + $foo->bar(); // int(456) + +It's also possible to specify explicitly which methods to run directly using +the `!method` syntax: + +.. code-block:: php + + class Foo { + function foo() { return 123; } + function bar() { return $this->foo(); } + } + + $foo = mock("Foo[!foo]"); + + $foo->foo(); // int(123) + + $foo->bar(); // error, no expectation set + +.. note:: + + Even though we support generated partial test doubles, we do not recommend + using them. + + One of the reasons why is because a generated partial will call the original + constructor of the mocked class. This can have unwanted side-effects during + testing application code. + + See :doc:`../cookbook/not_calling_the_constructor` for more details. + +Proxied partial test doubles +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A proxied partial mock is a partial of last resort. We may encounter a class +which is simply not capable of being mocked because it has been marked as +final. Similarly, we may find a class with methods marked as final. In such a +scenario, we cannot simply extend the class and override methods to mock - we +need to get creative. + +.. code-block:: php + + $mock = \Mockery::mock(new MyClass); + +Yes, the new mock is a Proxy. It intercepts calls and reroutes them to the +proxied object (which we construct and pass in) for methods which are not +subject to any expectations. Indirectly, this allows us to mock methods +marked final since the Proxy is not subject to those limitations. The tradeoff +should be obvious - a proxied partial will fail any typehint checks for the +class being mocked since it cannot extend that class. + +.. _creating-test-doubles-aliasing: + +Aliasing +-------- + +Prefixing the valid name of a class (which is NOT currently loaded) with +"alias:" will generate an "alias mock". Alias mocks create a class alias with +the given classname to stdClass and are generally used to enable the mocking +of public static methods. Expectations set on the new mock object which refer +to static methods will be used by all static calls to this class. + +.. code-block:: php + + $mock = \Mockery::mock('alias:MyClass'); + + +.. note:: + + Even though aliasing classes is supported, we do not recommend it. + +Overloading +----------- + +Prefixing the valid name of a class (which is NOT currently loaded) with +"overload:" will generate an alias mock (as with "alias:") except that created +new instances of that class will import any expectations set on the origin +mock (``$mock``). The origin mock is never verified since it's used an +expectation store for new instances. For this purpose we use the term "instance +mock" to differentiate it from the simpler "alias mock". + +In other words, an instance mock will "intercept" when a new instance of the +mocked class is created, then the mock will be used instead. This is useful +especially when mocking hard dependencies which will be discussed later. + +.. code-block:: php + + $mock = \Mockery::mock('overload:MyClass'); + +.. note:: + + Using alias/instance mocks across more than one test will generate a fatal + error since we can't have two classes of the same name. To avoid this, + run each test of this kind in a separate PHP process (which is supported + out of the box by both PHPUnit and PHPT). + + +.. _creating-test-doubles-named-mocks: + +Named Mocks +----------- + +The ``namedMock()`` method will generate a class called by the first argument, +so in this example ``MyClassName``. The rest of the arguments are treated in the +same way as the ``mock`` method: + +.. code-block:: php + + $mock = \Mockery::namedMock('MyClassName', 'DateTime'); + +This example would create a class called ``MyClassName`` that extends +``DateTime``. + +Named mocks are quite an edge case, but they can be useful when code depends +on the ``__CLASS__`` magic constant, or when we need two derivatives of an +abstract type, that are actually different classes. + +See the cookbook entry on :doc:`../cookbook/class_constants` for an example +usage of named mocks. + +.. note:: + + We can only create a named mock once, any subsequent calls to + ``namedMock``, with different arguments are likely to cause exceptions. + +.. _creating-test-doubles-constructor-arguments: + +Constructor Arguments +--------------------- + +Sometimes the mocked class has required constructor arguments. We can pass these +to Mockery as an indexed array, as the 2nd argument: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass', [$constructorArg1, $constructorArg2]); + +or if we need the ``MyClass`` to implement an interface as well, as the 3rd +argument: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass', 'MyInterface', [$constructorArg1, $constructorArg2]); + +Mockery now knows to pass in ``$constructorArg1`` and ``$constructorArg2`` as +arguments to the constructor. + +.. _creating-test-doubles-behavior-modifiers: + +Behavior Modifiers +------------------ + +When creating a mock object, we may wish to use some commonly preferred +behaviours that are not the default in Mockery. + +The use of the ``shouldIgnoreMissing()`` behaviour modifier will label this +mock object as a Passive Mock: + +.. code-block:: php + + \Mockery::mock('MyClass')->shouldIgnoreMissing(); + +In such a mock object, calls to methods which are not covered by expectations +will return ``null`` instead of the usual error about there being no expectation +matching the call. + +On PHP >= 7.0.0, methods with missing expectations that have a return type +will return either a mock of the object (if return type is a class) or a +"falsy" primitive value, e.g. empty string, empty array, zero for ints and +floats, false for bools, or empty closures. + +On PHP >= 7.1.0, methods with missing expectations and nullable return type +will return null. + +We can optionally prefer to return an object of type ``\Mockery\Undefined`` +(i.e. a ``null`` object) (which was the 0.7.2 behaviour) by using an +additional modifier: + +.. code-block:: php + + \Mockery::mock('MyClass')->shouldIgnoreMissing()->asUndefined(); + +The returned object is nothing more than a placeholder so if, by some act of +fate, it's erroneously used somewhere it shouldn't it will likely not pass a +logic check. + +We have encountered the ``makePartial()`` method before, as it is the method we +use to create runtime partial test doubles: + +.. code-block:: php + + \Mockery::mock('MyClass')->makePartial(); + +This form of mock object will defer all methods not subject to an expectation to +the parent class of the mock, i.e. ``MyClass``. Whereas the previous +``shouldIgnoreMissing()`` returned ``null``, this behaviour simply calls the +parent's matching method. diff --git a/vendor/mockery/mockery/docs/reference/demeter_chains.rst b/vendor/mockery/mockery/docs/reference/demeter_chains.rst new file mode 100644 index 00000000..1dad5eff --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/demeter_chains.rst @@ -0,0 +1,38 @@ +.. index:: + single: Mocking; Demeter Chains + +Mocking Demeter Chains And Fluent Interfaces +============================================ + +Both of these terms refer to the growing practice of invoking statements +similar to: + +.. code-block:: php + + $object->foo()->bar()->zebra()->alpha()->selfDestruct(); + +The long chain of method calls isn't necessarily a bad thing, assuming they +each link back to a local object the calling class knows. As a fun example, +Mockery's long chains (after the first ``shouldReceive()`` method) all call to +the same instance of ``\Mockery\Expectation``. However, sometimes this is not +the case and the chain is constantly crossing object boundaries. + +In either case, mocking such a chain can be a horrible task. To make it easier +Mockery supports demeter chain mocking. Essentially, we shortcut through the +chain and return a defined value from the final call. For example, let's +assume ``selfDestruct()`` returns the string "Ten!" to $object (an instance of +``CaptainsConsole``). Here's how we could mock it. + +.. code-block:: php + + $mock = \Mockery::mock('CaptainsConsole'); + $mock->shouldReceive('foo->bar->zebra->alpha->selfDestruct')->andReturn('Ten!'); + +The above expectation can follow any previously seen format or expectation, +except that the method name is simply the string of all expected chain calls +separated by ``->``. Mockery will automatically setup the chain of expected +calls with its final return values, regardless of whatever intermediary object +might be used in the real implementation. + +Arguments to all members of the chain (except the final call) are ignored in +this process. diff --git a/vendor/mockery/mockery/docs/reference/expectations.rst b/vendor/mockery/mockery/docs/reference/expectations.rst new file mode 100644 index 00000000..608aaef1 --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/expectations.rst @@ -0,0 +1,533 @@ +.. index:: + single: Expectations + +Expectation Declarations +======================== + +.. note:: + + In order for our expectations to work we MUST call ``Mockery::close()``, + preferably in a callback method such as ``tearDown`` or ``_after`` + (depending on whether or not we're integrating Mockery with another + framework). This static call cleans up the Mockery container used by the + current test, and run any verification tasks needed for our expectations. + +Once we have created a mock object, we'll often want to start defining how +exactly it should behave (and how it should be called). This is where the +Mockery expectation declarations take over. + +Declaring Method Call Expectations +---------------------------------- + +To tell our test double to expect a call for a method with a given name, we use +the ``shouldReceive`` method: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method'); + +This is the starting expectation upon which all other expectations and +constraints are appended. + +We can declare more than one method call to be expected: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method_1', 'name_of_method_2'); + +All of these will adopt any chained expectations or constraints. + +It is possible to declare the expectations for the method calls, along with +their return values: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive([ + 'name_of_method_1' => 'return value 1', + 'name_of_method_2' => 'return value 2', + ]); + +There's also a shorthand way of setting up method call expectations and their +return values: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass', ['name_of_method_1' => 'return value 1', 'name_of_method_2' => 'return value 2']); + +All of these will adopt any additional chained expectations or constraints. + +We can declare that a test double should not expect a call to the given method +name: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldNotReceive('name_of_method'); + +This method is a convenience method for calling ``shouldReceive()->never()``. + +Declaring Method Argument Expectations +-------------------------------------- + +For every method we declare expectation for, we can add constraints that the +defined expectations apply only to the method calls that match the expected +argument list: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->with($arg1, $arg2, ...); + // or + $mock->shouldReceive('name_of_method') + ->withArgs([$arg1, $arg2, ...]); + +We can add a lot more flexibility to argument matching using the built in +matcher classes (see later). For example, ``\Mockery::any()`` matches any +argument passed to that position in the ``with()`` parameter list. Mockery also +allows Hamcrest library matchers - for example, the Hamcrest function +``anything()`` is equivalent to ``\Mockery::any()``. + +It's important to note that this means all expectations attached only apply to +the given method when it is called with these exact arguments: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + + $mock->shouldReceive('foo')->with('Hello'); + + $mock->foo('Goodbye'); // throws a NoMatchingExpectationException + +This allows for setting up differing expectations based on the arguments +provided to expected calls. + +Argument matching with closures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Instead of providing a built-in matcher for each argument, we can provide a +closure that matches all passed arguments at once: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->withArgs(closure); + +The given closure receives all the arguments passed in the call to the expected +method. In this way, this expectation only applies to method calls where passed +arguments make the closure evaluate to true: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + + $mock->shouldReceive('foo')->withArgs(function ($arg) { + if ($arg % 2 == 0) { + return true; + } + return false; + }); + + $mock->foo(4); // matches the expectation + $mock->foo(3); // throws a NoMatchingExpectationException + +Argument matching with some of given values +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +We can provide expected arguments that match passed arguments when mocked method +is called. + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->withSomeOfArgs(arg1, arg2, arg3, ...); + +The given expected arguments order doesn't matter. +Check if expected values are included or not, but type should be matched: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('foo') + ->withSomeOfArgs(1, 2); + + $mock->foo(1, 2, 3); // matches the expectation + $mock->foo(3, 2, 1); // matches the expectation (passed order doesn't matter) + $mock->foo('1', '2'); // throws a NoMatchingExpectationException (type should be matched) + $mock->foo(3); // throws a NoMatchingExpectationException + +Any, or no arguments +^^^^^^^^^^^^^^^^^^^^ + +We can declare that the expectation matches a method call regardless of what +arguments are passed: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->withAnyArgs(); + +This is set by default unless otherwise specified. + +We can declare that the expectation matches method calls with zero arguments: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->withNoArgs(); + +Declaring Return Value Expectations +----------------------------------- + +For mock objects, we can tell Mockery what return values to return from the +expected method calls. + +For that we can use the ``andReturn()`` method: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->andReturn($value); + +This sets a value to be returned from the expected method call. + +It is possible to set up expectation for multiple return values. By providing +a sequence of return values, we tell Mockery what value to return on every +subsequent call to the method: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->andReturn($value1, $value2, ...) + +The first call will return ``$value1`` and the second call will return ``$value2``. + +If we call the method more times than the number of return values we declared, +Mockery will return the final value for any subsequent method call: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + + $mock->shouldReceive('foo')->andReturn(1, 2, 3); + + $mock->foo(); // int(1) + $mock->foo(); // int(2) + $mock->foo(); // int(3) + $mock->foo(); // int(3) + +The same can be achieved using the alternative syntax: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->andReturnValues([$value1, $value2, ...]) + +It accepts a simple array instead of a list of parameters. The order of return +is determined by the numerical index of the given array with the last array +member being returned on all calls once previous return values are exhausted. + +The following two options are primarily for communication with test readers: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->andReturnNull(); + // or + $mock->shouldReceive('name_of_method') + ->andReturn([null]); + +They mark the mock object method call as returning ``null`` or nothing. + +Sometimes we want to calculate the return results of the method calls, based on +the arguments passed to the method. We can do that with the ``andReturnUsing()`` +method which accepts one or more closure: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->andReturnUsing(closure, ...); + +Closures can be queued by passing them as extra parameters as for ``andReturn()``. + +Occasionally, it can be useful to echo back one of the arguments that a method +is called with. In this case we can use the ``andReturnArg()`` method; the +argument to be returned is specified by its index in the arguments list: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->andReturnArg(1); + +This returns the second argument (index #1) from the list of arguments when the +method is called. + +.. note:: + + We cannot currently mix ``andReturnUsing()`` or ``andReturnArg`` with + ``andReturn()``. + +If we are mocking fluid interfaces, the following method will be helpful: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->andReturnSelf(); + +It sets the return value to the mocked class name. + +Throwing Exceptions +------------------- + +We can tell the method of mock objects to throw exceptions: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->andThrow(new Exception); + +It will throw the given ``Exception`` object when called. + +Rather than an object, we can pass in the ``Exception`` class, message and/or code to +use when throwing an ``Exception`` from the mocked method: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->andThrow('exception_name', 'message', 123456789); + +.. _expectations-setting-public-properties: + +Setting Public Properties +------------------------- + +Used with an expectation so that when a matching method is called, we can cause +a mock object's public property to be set to a specified value, by using +``andSet()`` or ``set()``: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->andSet($property, $value); + // or + $mock->shouldReceive('name_of_method') + ->set($property, $value); + +In cases where we want to call the real method of the class that was mocked and +return its result, the ``passthru()`` method tells the expectation to bypass +a return queue: + +.. code-block:: php + + passthru() + +It allows expectation matching and call count validation to be applied against +real methods while still calling the real class method with the expected +arguments. + +Declaring Call Count Expectations +--------------------------------- + +Besides setting expectations on the arguments of the method calls, and the +return values of those same calls, we can set expectations on how many times +should any method be called. + +When a call count expectation is not met, a +``\Mockery\Expectation\InvalidCountException`` will be thrown. + +.. note:: + + It is absolutely required to call ``\Mockery::close()`` at the end of our + tests, for example in the ``tearDown()`` method of PHPUnit. Otherwise + Mockery will not verify the calls made against our mock objects. + +We can declare that the expected method may be called zero or more times: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->zeroOrMoreTimes(); + +This is the default for all methods unless otherwise set. + +To tell Mockery to expect an exact number of calls to a method, we can use the +following: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->times($n); + +where ``$n`` is the number of times the method should be called. + +A couple of most common cases got their shorthand methods. + +To declare that the expected method must be called one time only: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->once(); + +To declare that the expected method must be called two times: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->twice(); + +To declare that the expected method must never be called: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->never(); + +Call count modifiers +^^^^^^^^^^^^^^^^^^^^ + +The call count expectations can have modifiers set. + +If we want to tell Mockery the minimum number of times a method should be called, +we use ``atLeast()``: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->atLeast() + ->times(3); + +``atLeast()->times(3)`` means the call must be called at least three times +(given matching method args) but never less than three times. + +Similarly, we can tell Mockery the maximum number of times a method should be +called, using ``atMost()``: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->atMost() + ->times(3); + +``atMost()->times(3)`` means the call must be called no more than three times. +If the method gets no calls at all, the expectation will still be met. + +We can also set a range of call counts, using ``between()``: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + $mock->shouldReceive('name_of_method') + ->between($min, $max); + +This is actually identical to using ``atLeast()->times($min)->atMost()->times($max)`` +but is provided as a shorthand. It may be followed by a ``times()`` call with no +parameter to preserve the APIs natural language readability. + +Multiple Calls with Different Expectations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If a method is expected to get called multiple times with different arguments +and/or return values we can simply repeat the expectations. The same of course +also works if we expect multiple calls to different methods. + +.. code-block:: php + + $mock = \Mockery::mock('MyClass'); + // Expectations for the 1st call + $mock->shouldReceive('name_of_method'); + ->once() + ->with('arg1') + ->andReturn($value1) + + // 2nd call to same method + ->shouldReceive('name_of_method') + ->once() + ->with('arg2') + ->andReturn($value2) + + // final call to another method + ->shouldReceive('other_method') + ->once() + ->with('other') + ->andReturn($value_other); + +Expectation Declaration Utilities +--------------------------------- + +Declares that this method is expected to be called in a specific order in +relation to similarly marked methods. + +.. code-block:: php + + ordered() + +The order is dictated by the order in which this modifier is actually used when +setting up mocks. + +Declares the method as belonging to an order group (which can be named or +numbered). Methods within a group can be called in any order, but the ordered +calls from outside the group are ordered in relation to the group: + +.. code-block:: php + + ordered(group) + +We can set up so that method1 is called before group1 which is in turn called +before method2. + +When called prior to ``ordered()`` or ``ordered(group)``, it declares this +ordering to apply across all mock objects (not just the current mock): + +.. code-block:: php + + globally() + +This allows for dictating order expectations across multiple mocks. + +The ``byDefault()`` marks an expectation as a default. Default expectations are +applied unless a non-default expectation is created: + +.. code-block:: php + + byDefault() + +These later expectations immediately replace the previously defined default. +This is useful so we can setup default mocks in our unit test ``setup()`` and +later tweak them in specific tests as needed. + +Returns the current mock object from an expectation chain: + +.. code-block:: php + + getMock() + +Useful where we prefer to keep mock setups as a single statement, e.g.: + +.. code-block:: php + + $mock = \Mockery::mock('foo')->shouldReceive('foo')->andReturn(1)->getMock(); diff --git a/vendor/mockery/mockery/docs/reference/final_methods_classes.rst b/vendor/mockery/mockery/docs/reference/final_methods_classes.rst new file mode 100644 index 00000000..dd0fa5ba --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/final_methods_classes.rst @@ -0,0 +1,29 @@ +.. index:: + single: Mocking; Final Classes/Methods + +Dealing with Final Classes/Methods +================================== + +One of the primary restrictions of mock objects in PHP, is that mocking +classes or methods marked final is hard. The final keyword prevents methods so +marked from being replaced in subclasses (subclassing is how mock objects can +inherit the type of the class or object being mocked). + +The simplest solution is to implement an interface in your final class and +typehint against / mock this. + +However this may not be possible in some third party libraries. +Mockery does allow creating "proxy mocks" from classes marked final, or from +classes with methods marked final. This offers all the usual mock object +goodness but the resulting mock will not inherit the class type of the object +being mocked, i.e. it will not pass any instanceof comparison. Methods marked +as final will be proxied to the original method, i.e., final methods can't be +mocked. + +We can create a proxy mock by passing the instantiated object we wish to +mock into ``\Mockery::mock()``, i.e. Mockery will then generate a Proxy to the +real object and selectively intercept method calls for the purposes of setting +and meeting expectations. + +See the :ref:`creating-test-doubles-partial-test-doubles` chapter, the subsection +about proxied partial test doubles. diff --git a/vendor/mockery/mockery/docs/reference/index.rst b/vendor/mockery/mockery/docs/reference/index.rst new file mode 100644 index 00000000..1e5bf048 --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/index.rst @@ -0,0 +1,22 @@ +Reference +========= + +.. toctree:: + :hidden: + + creating_test_doubles + expectations + argument_validation + alternative_should_receive_syntax + spies + partial_mocks + protected_methods + public_properties + public_static_properties + pass_by_reference_behaviours + demeter_chains + final_methods_classes + magic_methods + phpunit_integration + +.. include:: map.rst.inc diff --git a/vendor/mockery/mockery/docs/reference/instance_mocking.rst b/vendor/mockery/mockery/docs/reference/instance_mocking.rst new file mode 100644 index 00000000..9d1aa283 --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/instance_mocking.rst @@ -0,0 +1,22 @@ +.. index:: + single: Mocking; Instance + +Instance Mocking +================ + +Instance mocking means that a statement like: + +.. code-block:: php + + $obj = new \MyNamespace\Foo; + +...will actually generate a mock object. This is done by replacing the real +class with an instance mock (similar to an alias mock), as with mocking public +methods. The alias will import its expectations from the original mock of +that type (note that the original is never verified and should be ignored +after its expectations are setup). This lets you intercept instantiation where +you can't simply inject a replacement object. + +As before, this does not prevent a require statement from including the real +class and triggering a fatal PHP error. It's intended for use where +autoloading is the primary class loading mechanism. diff --git a/vendor/mockery/mockery/docs/reference/magic_methods.rst b/vendor/mockery/mockery/docs/reference/magic_methods.rst new file mode 100644 index 00000000..39591cff --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/magic_methods.rst @@ -0,0 +1,16 @@ +.. index:: + single: Mocking; Magic Methods + +PHP Magic Methods +================= + +PHP magic methods which are prefixed with a double underscore, e.g. +``__set()``, pose a particular problem in mocking and unit testing in general. +It is strongly recommended that unit tests and mock objects do not directly +refer to magic methods. Instead, refer only to the virtual methods and +properties these magic methods simulate. + +Following this piece of advice will ensure we are testing the real API of +classes and also ensures there is no conflict should Mockery override these +magic methods, which it will inevitably do in order to support its role in +intercepting method calls and properties. diff --git a/vendor/mockery/mockery/docs/reference/map.rst.inc b/vendor/mockery/mockery/docs/reference/map.rst.inc new file mode 100644 index 00000000..883bc3ca --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/map.rst.inc @@ -0,0 +1,14 @@ +* :doc:`/reference/creating_test_doubles` +* :doc:`/reference/expectations` +* :doc:`/reference/argument_validation` +* :doc:`/reference/alternative_should_receive_syntax` +* :doc:`/reference/spies` +* :doc:`/reference/partial_mocks` +* :doc:`/reference/protected_methods` +* :doc:`/reference/public_properties` +* :doc:`/reference/public_static_properties` +* :doc:`/reference/pass_by_reference_behaviours` +* :doc:`/reference/demeter_chains` +* :doc:`/reference/final_methods_classes` +* :doc:`/reference/magic_methods` +* :doc:`/reference/phpunit_integration` diff --git a/vendor/mockery/mockery/docs/reference/partial_mocks.rst b/vendor/mockery/mockery/docs/reference/partial_mocks.rst new file mode 100644 index 00000000..457eb8de --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/partial_mocks.rst @@ -0,0 +1,108 @@ +.. index:: + single: Mocking; Partial Mocks + +Creating Partial Mocks +====================== + +Partial mocks are useful when we only need to mock several methods of an +object leaving the remainder free to respond to calls normally (i.e. as +implemented). Mockery implements three distinct strategies for creating +partials. Each has specific advantages and disadvantages so which strategy we +use will depend on our own preferences and the source code in need of +mocking. + +We have previously talked a bit about :ref:`creating-test-doubles-partial-test-doubles`, +but we'd like to expand on the subject a bit here. + +#. Runtime partial test doubles +#. Generated partial test doubles +#. Proxied Partial Mock + +Runtime partial test doubles +---------------------------- + +A runtime partial test double, also known as a passive partial mock, is a kind +of a default state of being for a mocked object. + +.. code-block:: php + + $mock = \Mockery::mock('MyClass')->makePartial(); + +With a runtime partial, we assume that all methods will simply defer to the +parent class (``MyClass``) original methods unless a method call matches a +known expectation. If we have no matching expectation for a specific method +call, that call is deferred to the class being mocked. Since the division +between mocked and unmocked calls depends entirely on the expectations we +define, there is no need to define which methods to mock in advance. + +See the cookbook entry on :doc:`../cookbook/big_parent_class` for an example +usage of runtime partial test doubles. + +Generated Partial Test Doubles +------------------------------ + +A generated partial test double, also known as a traditional partial mock, +defines ahead of time which methods of a class are to be mocked and which are +to be left unmocked (i.e. callable as normal). The syntax for creating +traditional mocks is: + +.. code-block:: php + + $mock = \Mockery::mock('MyClass[foo,bar]'); + +In the above example, the ``foo()`` and ``bar()`` methods of MyClass will be +mocked but no other MyClass methods are touched. We will need to define +expectations for the ``foo()`` and ``bar()`` methods to dictate their mocked +behaviour. + +Don't forget that we can pass in constructor arguments since unmocked methods +may rely on those! + +.. code-block:: php + + $mock = \Mockery::mock('MyNamespace\MyClass[foo]', array($arg1, $arg2)); + +See the :ref:`creating-test-doubles-constructor-arguments` section to read up +on them. + +.. note:: + + Even though we support generated partial test doubles, we do not recommend + using them. + +Proxied Partial Mock +-------------------- + +A proxied partial mock is a partial of last resort. We may encounter a class +which is simply not capable of being mocked because it has been marked as +final. Similarly, we may find a class with methods marked as final. In such a +scenario, we cannot simply extend the class and override methods to mock - we +need to get creative. + +.. code-block:: php + + $mock = \Mockery::mock(new MyClass); + +Yes, the new mock is a Proxy. It intercepts calls and reroutes them to the +proxied object (which we construct and pass in) for methods which are not +subject to any expectations. Indirectly, this allows us to mock methods +marked final since the Proxy is not subject to those limitations. The tradeoff +should be obvious - a proxied partial will fail any typehint checks for the +class being mocked since it cannot extend that class. + +Special Internal Cases +---------------------- + +All mock objects, with the exception of Proxied Partials, allows us to make +any expectation call to the underlying real class method using the ``passthru()`` +expectation call. This will return values from the real call and bypass any +mocked return queue (which can simply be omitted obviously). + +There is a fourth kind of partial mock reserved for internal use. This is +automatically generated when we attempt to mock a class containing methods +marked final. Since we cannot override such methods, they are simply left +unmocked. Typically, we don't need to worry about this but if we really +really must mock a final method, the only possible means is through a Proxied +Partial Mock. SplFileInfo, for example, is a common class subject to this form +of automatic internal partial since it contains public final methods used +internally. diff --git a/vendor/mockery/mockery/docs/reference/pass_by_reference_behaviours.rst b/vendor/mockery/mockery/docs/reference/pass_by_reference_behaviours.rst new file mode 100644 index 00000000..5e2e457f --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/pass_by_reference_behaviours.rst @@ -0,0 +1,130 @@ +.. index:: + single: Pass-By-Reference Method Parameter Behaviour + +Preserving Pass-By-Reference Method Parameter Behaviour +======================================================= + +PHP Class method may accept parameters by reference. In this case, changes +made to the parameter (a reference to the original variable passed to the +method) are reflected in the original variable. An example: + +.. code-block:: php + + class Foo + { + + public function bar(&$a) + { + $a++; + } + + } + + $baz = 1; + $foo = new Foo; + $foo->bar($baz); + + echo $baz; // will echo the integer 2 + +In the example above, the variable ``$baz`` is passed by reference to +``Foo::bar()`` (notice the ``&`` symbol in front of the parameter?). Any +change ``bar()`` makes to the parameter reference is reflected in the original +variable, ``$baz``. + +Mockery handles references correctly for all methods where it can analyse +the parameter (using ``Reflection``) to see if it is passed by reference. To +mock how a reference is manipulated by the class method, we can use a closure +argument matcher to manipulate it, i.e. ``\Mockery::on()`` - see the +:ref:`argument-validation-complex-argument-validation` chapter. + +There is an exception for internal PHP classes where Mockery cannot analyse +method parameters using ``Reflection`` (a limitation in PHP). To work around +this, we can explicitly declare method parameters for an internal class using +``\Mockery\Configuration::setInternalClassMethodParamMap()``. + +Here's an example using ``MongoCollection::insert()``. ``MongoCollection`` is +an internal class offered by the mongo extension from PECL. Its ``insert()`` +method accepts an array of data as the first parameter, and an optional +options array as the second parameter. The original data array is updated +(i.e. when a ``insert()`` pass-by-reference parameter) to include a new +``_id`` field. We can mock this behaviour using a configured parameter map (to +tell Mockery to expect a pass by reference parameter) and a ``Closure`` +attached to the expected method parameter to be updated. + +Here's a PHPUnit unit test verifying that this pass-by-reference behaviour is +preserved: + +.. code-block:: php + + public function testCanOverrideExpectedParametersOfInternalPHPClassesToPreserveRefs() + { + \Mockery::getConfiguration()->setInternalClassMethodParamMap( + 'MongoCollection', + 'insert', + array('&$data', '$options = array()') + ); + $m = \Mockery::mock('MongoCollection'); + $m->shouldReceive('insert')->with( + \Mockery::on(function(&$data) { + if (!is_array($data)) return false; + $data['_id'] = 123; + return true; + }), + \Mockery::any() + ); + + $data = array('a'=>1,'b'=>2); + $m->insert($data); + + $this->assertTrue(isset($data['_id'])); + $this->assertEquals(123, $data['_id']); + + \Mockery::resetContainer(); + } + +Protected Methods +----------------- + +When dealing with protected methods, and trying to preserve pass by reference +behavior for them, a different approach is required. + +.. code-block:: php + + class Model + { + public function test(&$data) + { + return $this->doTest($data); + } + + protected function doTest(&$data) + { + $data['something'] = 'wrong'; + return $this; + } + } + + class Test extends \PHPUnit\Framework\TestCase + { + public function testModel() + { + $mock = \Mockery::mock('Model[test]')->shouldAllowMockingProtectedMethods(); + + $mock->shouldReceive('test') + ->with(\Mockery::on(function(&$data) { + $data['something'] = 'wrong'; + return true; + })); + + $data = array('foo' => 'bar'); + + $mock->test($data); + $this->assertTrue(isset($data['something'])); + $this->assertEquals('wrong', $data['something']); + } + } + +This is quite an edge case, so we need to change the original code a little bit, +by creating a public method that will call our protected method, and then mock +that, instead of the protected method. This new public method will act as a +proxy to our protected method. diff --git a/vendor/mockery/mockery/docs/reference/phpunit_integration.rst b/vendor/mockery/mockery/docs/reference/phpunit_integration.rst new file mode 100644 index 00000000..669a8ca9 --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/phpunit_integration.rst @@ -0,0 +1,145 @@ +.. index:: + single: PHPUnit Integration + +PHPUnit Integration +=================== + +Mockery was designed as a simple-to-use *standalone* mock object framework, so +its need for integration with any testing framework is entirely optional. To +integrate Mockery, we need to define a ``tearDown()`` method for our tests +containing the following (we may use a shorter ``\Mockery`` namespace +alias): + +.. code-block:: php + + public function tearDown() { + \Mockery::close(); + } + +This static call cleans up the Mockery container used by the current test, and +run any verification tasks needed for our expectations. + +For some added brevity when it comes to using Mockery, we can also explicitly +use the Mockery namespace with a shorter alias. For example: + +.. code-block:: php + + use \Mockery as m; + + class SimpleTest extends \PHPUnit\Framework\TestCase + { + public function testSimpleMock() { + $mock = m::mock('simplemock'); + $mock->shouldReceive('foo')->with(5, m::any())->once()->andReturn(10); + + $this->assertEquals(10, $mock->foo(5)); + } + + public function tearDown() { + m::close(); + } + } + +Mockery ships with an autoloader so we don't need to litter our tests with +``require_once()`` calls. To use it, ensure Mockery is on our +``include_path`` and add the following to our test suite's ``Bootstrap.php`` +or ``TestHelper.php`` file: + +.. code-block:: php + + require_once 'Mockery/Loader.php'; + require_once 'Hamcrest/Hamcrest.php'; + + $loader = new \Mockery\Loader; + $loader->register(); + +If we are using Composer, we can simplify this to including the Composer +generated autoloader file: + +.. code-block:: php + + require __DIR__ . '/../vendor/autoload.php'; // assuming vendor is one directory up + +.. caution:: + + Prior to Hamcrest 1.0.0, the ``Hamcrest.php`` file name had a small "h" + (i.e. ``hamcrest.php``). If upgrading Hamcrest to 1.0.0 remember to check + the file name is updated for all your projects.) + +To integrate Mockery into PHPUnit and avoid having to call the close method +and have Mockery remove itself from code coverage reports, have your test case +extends the ``\Mockery\Adapter\Phpunit\MockeryTestCase``: + +.. code-block:: php + + class MyTest extends \Mockery\Adapter\Phpunit\MockeryTestCase + { + + } + +An alternative is to use the supplied trait: + +.. code-block:: php + + class MyTest extends \PHPUnit\Framework\TestCase + { + use \Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; + } + +Extending ``MockeryTestCase`` or using the ``MockeryPHPUnitIntegration`` +trait is **the recommended way** of integrating Mockery with PHPUnit, +since Mockery 1.0.0. + +PHPUnit listener +---------------- + +Before the 1.0.0 release, Mockery provided a PHPUnit listener that would +call ``Mockery::close()`` for us at the end of a test. This has changed +significantly since the 1.0.0 version. + +Now, Mockery provides a PHPUnit listener that makes tests fail if +``Mockery::close()`` has not been called. It can help identify tests where +we've forgotten to include the trait or extend the ``MockeryTestCase``. + +If we are using PHPUnit's XML configuration approach, we can include the +following to load the ``TestListener``: + +.. code-block:: xml + + + + + +Make sure Composer's or Mockery's autoloader is present in the bootstrap file +or we will need to also define a "file" attribute pointing to the file of the +``TestListener`` class. + +If we are creating the test suite programmatically we may add the listener +like this: + +.. code-block:: php + + // Create the suite. + $suite = new PHPUnit\Framework\TestSuite(); + + // Create the listener and add it to the suite. + $result = new PHPUnit\Framework\TestResult(); + $result->addListener(new \Mockery\Adapter\Phpunit\TestListener()); + + // Run the tests. + $suite->run($result); + +.. caution:: + + PHPUnit provides a functionality that allows + `tests to run in a separated process `_, + to ensure better isolation. Mockery verifies the mocks expectations using the + ``Mockery::close()`` method, and provides a PHPUnit listener, that automatically + calls this method for us after every test. + + However, this listener is not called in the right process when using + PHPUnit's process isolation, resulting in expectations that might not be + respected, but without raising any ``Mockery\Exception``. To avoid this, + we cannot rely on the supplied Mockery PHPUnit ``TestListener``, and we need + to explicitly call ``Mockery::close``. The easiest solution to include this + call in the ``tearDown()`` method, as explained previously. diff --git a/vendor/mockery/mockery/docs/reference/protected_methods.rst b/vendor/mockery/mockery/docs/reference/protected_methods.rst new file mode 100644 index 00000000..ec4a5bad --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/protected_methods.rst @@ -0,0 +1,26 @@ +.. index:: + single: Mocking; Protected Methods + +Mocking Protected Methods +========================= + +By default, Mockery does not allow mocking protected methods. We do not recommend +mocking protected methods, but there are cases when there is no other solution. + +For those cases we have the ``shouldAllowMockingProtectedMethods()`` method. It +instructs Mockery to specifically allow mocking of protected methods, for that +one class only: + +.. code-block:: php + + class MyClass + { + protected function foo() + { + } + } + + $mock = \Mockery::mock('MyClass') + ->shouldAllowMockingProtectedMethods(); + $mock->shouldReceive('foo'); + diff --git a/vendor/mockery/mockery/docs/reference/public_properties.rst b/vendor/mockery/mockery/docs/reference/public_properties.rst new file mode 100644 index 00000000..31656683 --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/public_properties.rst @@ -0,0 +1,20 @@ +.. index:: + single: Mocking; Public Properties + +Mocking Public Properties +========================= + +Mockery allows us to mock properties in several ways. One way is that we can set +a public property and its value on any mock object. The second is that we can +use the expectation methods ``set()`` and ``andSet()`` to set property values if +that expectation is ever met. + +You can read more about :ref:`expectations-setting-public-properties`. + +.. note:: + + In general, Mockery does not support mocking any magic methods since these + are generally not considered a public API (and besides it is a bit difficult + to differentiate them when you badly need them for mocking!). So please mock + virtual properties (those relying on ``__get()`` and ``__set()``) as if they + were actually declared on the class. diff --git a/vendor/mockery/mockery/docs/reference/public_static_properties.rst b/vendor/mockery/mockery/docs/reference/public_static_properties.rst new file mode 100644 index 00000000..2396efc7 --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/public_static_properties.rst @@ -0,0 +1,15 @@ +.. index:: + single: Mocking; Public Static Methods + +Mocking Public Static Methods +============================= + +Static methods are not called on real objects, so normal mock objects can't +mock them. Mockery supports class aliased mocks, mocks representing a class +name which would normally be loaded (via autoloading or a require statement) +in the system under test. These aliases block that loading (unless via a +require statement - so please use autoloading!) and allow Mockery to intercept +static method calls and add expectations for them. + +See the :ref:`creating-test-doubles-aliasing` section for more information on +creating aliased mocks, for the purpose of mocking public static methods. diff --git a/vendor/mockery/mockery/docs/reference/spies.rst b/vendor/mockery/mockery/docs/reference/spies.rst new file mode 100644 index 00000000..9a699cbf --- /dev/null +++ b/vendor/mockery/mockery/docs/reference/spies.rst @@ -0,0 +1,154 @@ +.. index:: + single: Reference; Spies + +Spies +===== + +Spies are a type of test doubles, but they differ from stubs or mocks in that, +that the spies record any interaction between the spy and the System Under Test +(SUT), and allow us to make assertions against those interactions after the fact. + +Creating a spy means we don't have to set up expectations for every method call +the double might receive during the test, some of which may not be relevant to +the current test. A spy allows us to make assertions about the calls we care +about for this test only, reducing the chances of over-specification and making +our tests more clear. + +Spies also allow us to follow the more familiar Arrange-Act-Assert or +Given-When-Then style within our tests. With mocks, we have to follow a less +familiar style, something along the lines of Arrange-Expect-Act-Assert, where +we have to tell our mocks what to expect before we act on the SUT, then assert +that those expectations where met: + +.. code-block:: php + + // arrange + $mock = \Mockery::mock('MyDependency'); + $sut = new MyClass($mock); + + // expect + $mock->shouldReceive('foo') + ->once() + ->with('bar'); + + // act + $sut->callFoo(); + + // assert + \Mockery::close(); + +Spies allow us to skip the expect part and move the assertion to after we have +acted on the SUT, usually making our tests more readable: + +.. code-block:: php + + // arrange + $spy = \Mockery::spy('MyDependency'); + $sut = new MyClass($spy); + + // act + $sut->callFoo(); + + // assert + $spy->shouldHaveReceived() + ->foo() + ->with('bar'); + +On the other hand, spies are far less restrictive than mocks, meaning tests are +usually less precise, as they let us get away with more. This is usually a +good thing, they should only be as precise as they need to be, but while spies +make our tests more intent-revealing, they do tend to reveal less about the +design of the SUT. If we're having to setup lots of expectations for a mock, +in lots of different tests, our tests are trying to tell us something - the SUT +is doing too much and probably should be refactored. We don't get this with +spies, they simply ignore the calls that aren't relevant to them. + +Another downside to using spies is debugging. When a mock receives a call that +it wasn't expecting, it immediately throws an exception (failing fast), giving +us a nice stack trace or possibly even invoking our debugger. With spies, we're +simply asserting calls were made after the fact, so if the wrong calls were made, +we don't have quite the same just in time context we have with the mocks. + +Finally, if we need to define a return value for our test double, we can't do +that with a spy, only with a mock object. + +.. note:: + + This documentation page is an adaption of the blog post titled + `"Mockery Spies" `_, + published by Dave Marshall on his blog. Dave is the original author of spies + in Mockery. + +Spies Reference +--------------- + +To verify that a method was called on a spy, we use the ``shouldHaveReceived()`` +method: + +.. code-block:: php + + $spy->shouldHaveReceived('foo'); + +To verify that a method was **not** called on a spy, we use the +``shouldNotHaveReceived()`` method: + +.. code-block:: php + + $spy->shouldNotHaveReceived('foo'); + +We can also do argument matching with spies: + +.. code-block:: php + + $spy->shouldHaveReceived('foo') + ->with('bar'); + +Argument matching is also possible by passing in an array of arguments to +match: + +.. code-block:: php + + $spy->shouldHaveReceived('foo', ['bar']); + +Although when verifying a method was not called, the argument matching can only +be done by supplying the array of arguments as the 2nd argument to the +``shouldNotHaveReceived()`` method: + +.. code-block:: php + + $spy->shouldNotHaveReceived('foo', ['bar']); + +This is due to Mockery's internals. + +Finally, when expecting calls that should have been received, we can also verify +the number of calls: + +.. code-block:: php + + $spy->shouldHaveReceived('foo') + ->with('bar') + ->twice(); + +Alternative shouldReceive syntax +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +As of Mockery 1.0.0, we support calling methods as we would call any PHP method, +and not as string arguments to Mockery ``should*`` methods. + +In cases of spies, this only applies to the ``shouldHaveReceived()`` method: + +.. code-block:: php + + $spy->shouldHaveReceived() + ->foo('bar'); + +We can set expectation on number of calls as well: + +.. code-block:: php + + $spy->shouldHaveReceived() + ->foo('bar') + ->twice(); + +Unfortunately, due to limitations we can't support the same syntax for the +``shouldNotHaveReceived()`` method. diff --git a/vendor/mockery/mockery/library/Mockery.php b/vendor/mockery/mockery/library/Mockery.php new file mode 100644 index 00000000..95abd1b9 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery.php @@ -0,0 +1,983 @@ +shouldIgnoreMissing(); + } + + /** + * Static and Semantic shortcut to \Mockery\Container::mock(). + * + * @param mixed ...$args + * + * @return \Mockery\MockInterface|\Mockery\LegacyMockInterface + */ + public static function instanceMock(...$args) + { + return call_user_func_array(array(self::getContainer(), 'mock'), $args); + } + + /** + * Static shortcut to \Mockery\Container::mock(), first argument names the mock. + * + * @param mixed ...$args + * + * @return \Mockery\MockInterface|\Mockery\LegacyMockInterface + */ + public static function namedMock(...$args) + { + $name = array_shift($args); + + $builder = new MockConfigurationBuilder(); + $builder->setName($name); + + array_unshift($args, $builder); + + return call_user_func_array(array(self::getContainer(), 'mock'), $args); + } + + /** + * Static shortcut to \Mockery\Container::self(). + * + * @throws LogicException + * + * @return \Mockery\MockInterface|\Mockery\LegacyMockInterface + */ + public static function self() + { + if (is_null(self::$_container)) { + throw new \LogicException('You have not declared any mocks yet'); + } + + return self::$_container->self(); + } + + /** + * Static shortcut to closing up and verifying all mocks in the global + * container, and resetting the container static variable to null. + * + * @return void + */ + public static function close() + { + foreach (self::$_filesToCleanUp as $fileName) { + @unlink($fileName); + } + self::$_filesToCleanUp = []; + + if (is_null(self::$_container)) { + return; + } + + $container = self::$_container; + self::$_container = null; + + $container->mockery_teardown(); + $container->mockery_close(); + } + + /** + * Static fetching of a mock associated with a name or explicit class poser. + * + * @param string $name + * + * @return \Mockery\Mock + */ + public static function fetchMock($name) + { + return self::getContainer()->fetchMock($name); + } + + /** + * Lazy loader and getter for + * the container property. + * + * @return Mockery\Container + */ + public static function getContainer() + { + if (is_null(self::$_container)) { + self::$_container = new Mockery\Container(self::getGenerator(), self::getLoader()); + } + + return self::$_container; + } + + /** + * Setter for the $_generator static property. + * + * @param \Mockery\Generator\Generator $generator + */ + public static function setGenerator(Generator $generator) + { + self::$_generator = $generator; + } + + /** + * Lazy loader method and getter for + * the generator property. + * + * @return Generator + */ + public static function getGenerator() + { + if (is_null(self::$_generator)) { + self::$_generator = self::getDefaultGenerator(); + } + + return self::$_generator; + } + + /** + * Creates and returns a default generator + * used inside this class. + * + * @return CachingGenerator + */ + public static function getDefaultGenerator() + { + return new CachingGenerator(StringManipulationGenerator::withDefaultPasses()); + } + + /** + * Setter for the $_loader static property. + * + * @param Loader $loader + */ + public static function setLoader(Loader $loader) + { + self::$_loader = $loader; + } + + /** + * Lazy loader method and getter for + * the $_loader property. + * + * @return Loader + */ + public static function getLoader() + { + if (is_null(self::$_loader)) { + self::$_loader = self::getDefaultLoader(); + } + + return self::$_loader; + } + + /** + * Gets an EvalLoader to be used as default. + * + * @return EvalLoader + */ + public static function getDefaultLoader() + { + return new EvalLoader(); + } + + /** + * Set the container. + * + * @param \Mockery\Container $container + * + * @return \Mockery\Container + */ + public static function setContainer(Mockery\Container $container) + { + return self::$_container = $container; + } + + /** + * Reset the container to null. + * + * @return void + */ + public static function resetContainer() + { + self::$_container = null; + } + + /** + * Return instance of ANY matcher. + * + * @return \Mockery\Matcher\Any + */ + public static function any() + { + return new \Mockery\Matcher\Any(); + } + + /** + * Return instance of AndAnyOtherArgs matcher. + * + * An alternative name to `andAnyOtherArgs` so + * the API stays closer to `any` as well. + * + * @return \Mockery\Matcher\AndAnyOtherArgs + */ + public static function andAnyOthers() + { + return new \Mockery\Matcher\AndAnyOtherArgs(); + } + + /** + * Return instance of AndAnyOtherArgs matcher. + * + * @return \Mockery\Matcher\AndAnyOtherArgs + */ + public static function andAnyOtherArgs() + { + return new \Mockery\Matcher\AndAnyOtherArgs(); + } + + /** + * Return instance of TYPE matcher. + * + * @param mixed $expected + * + * @return \Mockery\Matcher\Type + */ + public static function type($expected) + { + return new \Mockery\Matcher\Type($expected); + } + + /** + * Return instance of DUCKTYPE matcher. + * + * @param array ...$args + * + * @return \Mockery\Matcher\Ducktype + */ + public static function ducktype(...$args) + { + return new \Mockery\Matcher\Ducktype($args); + } + + /** + * Return instance of SUBSET matcher. + * + * @param array $part + * @param bool $strict - (Optional) True for strict comparison, false for loose + * + * @return \Mockery\Matcher\Subset + */ + public static function subset(array $part, $strict = true) + { + return new \Mockery\Matcher\Subset($part, $strict); + } + + /** + * Return instance of CONTAINS matcher. + * + * @param mixed $args + * + * @return \Mockery\Matcher\Contains + */ + public static function contains(...$args) + { + return new \Mockery\Matcher\Contains($args); + } + + /** + * Return instance of HASKEY matcher. + * + * @param mixed $key + * + * @return \Mockery\Matcher\HasKey + */ + public static function hasKey($key) + { + return new \Mockery\Matcher\HasKey($key); + } + + /** + * Return instance of HASVALUE matcher. + * + * @param mixed $val + * + * @return \Mockery\Matcher\HasValue + */ + public static function hasValue($val) + { + return new \Mockery\Matcher\HasValue($val); + } + + /** + * Return instance of CLOSURE matcher. + * + * @param $reference + * + * @return \Mockery\Matcher\Closure + */ + public static function capture(&$reference) + { + $closure = function ($argument) use (&$reference) { + $reference = $argument; + return true; + }; + + return new \Mockery\Matcher\Closure($closure); + } + + /** + * Return instance of CLOSURE matcher. + * + * @param mixed $closure + * + * @return \Mockery\Matcher\Closure + */ + public static function on($closure) + { + return new \Mockery\Matcher\Closure($closure); + } + + /** + * Return instance of MUSTBE matcher. + * + * @param mixed $expected + * + * @return \Mockery\Matcher\MustBe + */ + public static function mustBe($expected) + { + return new \Mockery\Matcher\MustBe($expected); + } + + /** + * Return instance of NOT matcher. + * + * @param mixed $expected + * + * @return \Mockery\Matcher\Not + */ + public static function not($expected) + { + return new \Mockery\Matcher\Not($expected); + } + + /** + * Return instance of ANYOF matcher. + * + * @param array ...$args + * + * @return \Mockery\Matcher\AnyOf + */ + public static function anyOf(...$args) + { + return new \Mockery\Matcher\AnyOf($args); + } + + /** + * Return instance of NOTANYOF matcher. + * + * @param array ...$args + * + * @return \Mockery\Matcher\NotAnyOf + */ + public static function notAnyOf(...$args) + { + return new \Mockery\Matcher\NotAnyOf($args); + } + + /** + * Return instance of PATTERN matcher. + * + * @param mixed $expected + * + * @return \Mockery\Matcher\Pattern + */ + public static function pattern($expected) + { + return new \Mockery\Matcher\Pattern($expected); + } + + /** + * Lazy loader and Getter for the global + * configuration container. + * + * @return \Mockery\Configuration + */ + public static function getConfiguration() + { + if (is_null(self::$_config)) { + self::$_config = new \Mockery\Configuration(); + } + + return self::$_config; + } + + /** + * Utility method to format method name and arguments into a string. + * + * @param string $method + * @param array $arguments + * + * @return string + */ + public static function formatArgs($method, array $arguments = null) + { + if (is_null($arguments)) { + return $method . '()'; + } + + $formattedArguments = array(); + foreach ($arguments as $argument) { + $formattedArguments[] = self::formatArgument($argument); + } + + return $method . '(' . implode(', ', $formattedArguments) . ')'; + } + + /** + * Gets the string representation + * of any passed argument. + * + * @param mixed $argument + * @param int $depth + * + * @return mixed + */ + private static function formatArgument($argument, $depth = 0) + { + if ($argument instanceof MatcherAbstract) { + return (string) $argument; + } + + if (is_object($argument)) { + return 'object(' . get_class($argument) . ')'; + } + + if (is_int($argument) || is_float($argument)) { + return $argument; + } + + if (is_array($argument)) { + if ($depth === 1) { + $argument = '[...]'; + } else { + $sample = array(); + foreach ($argument as $key => $value) { + $key = is_int($key) ? $key : "'$key'"; + $value = self::formatArgument($value, $depth + 1); + $sample[] = "$key => $value"; + } + + $argument = "[" . implode(", ", $sample) . "]"; + } + + return ((strlen($argument) > 1000) ? substr($argument, 0, 1000) . '...]' : $argument); + } + + if (is_bool($argument)) { + return $argument ? 'true' : 'false'; + } + + if (is_resource($argument)) { + return 'resource(...)'; + } + + if (is_null($argument)) { + return 'NULL'; + } + + return "'" . (string) $argument . "'"; + } + + /** + * Utility function to format objects to printable arrays. + * + * @param array $objects + * + * @return string + */ + public static function formatObjects(array $objects = null) + { + static $formatting; + + if ($formatting) { + return '[Recursion]'; + } + + if (is_null($objects)) { + return ''; + } + + $objects = array_filter($objects, 'is_object'); + if (empty($objects)) { + return ''; + } + + $formatting = true; + $parts = array(); + + foreach ($objects as $object) { + $parts[get_class($object)] = self::objectToArray($object); + } + + $formatting = false; + + return 'Objects: ( ' . var_export($parts, true) . ')'; + } + + /** + * Utility function to turn public properties and public get* and is* method values into an array. + * + * @param object $object + * @param int $nesting + * + * @return array + */ + private static function objectToArray($object, $nesting = 3) + { + if ($nesting == 0) { + return array('...'); + } + + $defaultFormatter = function ($object, $nesting) { + return array('properties' => self::extractInstancePublicProperties($object, $nesting)); + }; + + $class = get_class($object); + + $formatter = self::getConfiguration()->getObjectFormatter($class, $defaultFormatter); + + $array = array( + 'class' => $class, + 'identity' => '#' . md5(spl_object_hash($object)) + ); + + $array = array_merge($array, $formatter($object, $nesting)); + + return $array; + } + + /** + * Returns all public instance properties. + * + * @param mixed $object + * @param int $nesting + * + * @return array + */ + private static function extractInstancePublicProperties($object, $nesting) + { + $reflection = new \ReflectionClass(get_class($object)); + $properties = $reflection->getProperties(\ReflectionProperty::IS_PUBLIC); + $cleanedProperties = array(); + + foreach ($properties as $publicProperty) { + if (!$publicProperty->isStatic()) { + $name = $publicProperty->getName(); + try { + $cleanedProperties[$name] = self::cleanupNesting($object->$name, $nesting); + } catch (\Exception $exception) { + $cleanedProperties[$name] = $exception->getMessage(); + } + } + } + + return $cleanedProperties; + } + + /** + * Utility method used for recursively generating + * an object or array representation. + * + * @param mixed $argument + * @param int $nesting + * + * @return mixed + */ + private static function cleanupNesting($argument, $nesting) + { + if (is_object($argument)) { + $object = self::objectToArray($argument, $nesting - 1); + $object['class'] = get_class($argument); + + return $object; + } + + if (is_array($argument)) { + return self::cleanupArray($argument, $nesting - 1); + } + + return $argument; + } + + /** + * Utility method for recursively + * gerating a representation + * of the given array. + * + * @param array $argument + * @param int $nesting + * + * @return mixed + */ + private static function cleanupArray($argument, $nesting = 3) + { + if ($nesting == 0) { + return '...'; + } + + foreach ($argument as $key => $value) { + if (is_array($value)) { + $argument[$key] = self::cleanupArray($value, $nesting - 1); + } elseif (is_object($value)) { + $argument[$key] = self::objectToArray($value, $nesting - 1); + } + } + + return $argument; + } + + /** + * Utility function to parse shouldReceive() arguments and generate + * expectations from such as needed. + * + * @param Mockery\LegacyMockInterface $mock + * @param array ...$args + * @param callable $add + * @return \Mockery\CompositeExpectation + */ + public static function parseShouldReturnArgs(\Mockery\LegacyMockInterface $mock, $args, $add) + { + $composite = new \Mockery\CompositeExpectation(); + + foreach ($args as $arg) { + if (is_array($arg)) { + foreach ($arg as $k => $v) { + $expectation = self::buildDemeterChain($mock, $k, $add)->andReturn($v); + $composite->add($expectation); + } + } elseif (is_string($arg)) { + $expectation = self::buildDemeterChain($mock, $arg, $add); + $composite->add($expectation); + } + } + + return $composite; + } + + /** + * Sets up expectations on the members of the CompositeExpectation and + * builds up any demeter chain that was passed to shouldReceive. + * + * @param \Mockery\LegacyMockInterface $mock + * @param string $arg + * @param callable $add + * @throws Mockery\Exception + * @return \Mockery\ExpectationInterface + */ + protected static function buildDemeterChain(\Mockery\LegacyMockInterface $mock, $arg, $add) + { + /** @var Mockery\Container $container */ + $container = $mock->mockery_getContainer(); + $methodNames = explode('->', $arg); + reset($methodNames); + + if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() + && !$mock->mockery_isAnonymous() + && !in_array(current($methodNames), $mock->mockery_getMockableMethods()) + ) { + throw new \Mockery\Exception( + 'Mockery\'s configuration currently forbids mocking the method ' + . current($methodNames) . ' as it does not exist on the class or object ' + . 'being mocked' + ); + } + + /** @var ExpectationInterface|null $expectations */ + $expectations = null; + + /** @var Callable $nextExp */ + $nextExp = function ($method) use ($add) { + return $add($method); + }; + + $parent = get_class($mock); + + while (true) { + $method = array_shift($methodNames); + $expectations = $mock->mockery_getExpectationsFor($method); + + if (is_null($expectations) || self::noMoreElementsInChain($methodNames)) { + $expectations = $nextExp($method); + if (self::noMoreElementsInChain($methodNames)) { + break; + } + + $mock = self::getNewDemeterMock($container, $parent, $method, $expectations); + } else { + $demeterMockKey = $container->getKeyOfDemeterMockFor($method, $parent); + if ($demeterMockKey) { + $mock = self::getExistingDemeterMock($container, $demeterMockKey); + } + } + + $parent .= '->' . $method; + + $nextExp = function ($n) use ($mock) { + return $mock->shouldReceive($n); + }; + } + + return $expectations; + } + + /** + * Gets a new demeter configured + * mock from the container. + * + * @param \Mockery\Container $container + * @param string $parent + * @param string $method + * @param Mockery\ExpectationInterface $exp + * + * @return \Mockery\Mock + */ + private static function getNewDemeterMock( + Mockery\Container $container, + $parent, + $method, + Mockery\ExpectationInterface $exp + ) { + $newMockName = 'demeter_' . md5($parent) . '_' . $method; + + $parRef = null; + $parRefMethod = null; + $parRefMethodRetType = null; + + $parentMock = $exp->getMock(); + if ($parentMock !== null) { + $parRef = new ReflectionObject($parentMock); + } + + if ($parRef !== null && $parRef->hasMethod($method)) { + $parRefMethod = $parRef->getMethod($method); + $parRefMethodRetType = Reflector::getReturnType($parRefMethod, true); + + if ($parRefMethodRetType !== null && $parRefMethodRetType !== 'mixed') { + $nameBuilder = new MockNameBuilder(); + $nameBuilder->addPart('\\' . $newMockName); + $mock = self::namedMock($nameBuilder->build(), $parRefMethodRetType); + $exp->andReturn($mock); + + return $mock; + } + } + + $mock = $container->mock($newMockName); + $exp->andReturn($mock); + + return $mock; + } + + /** + * Gets an specific demeter mock from + * the ones kept by the container. + * + * @param \Mockery\Container $container + * @param string $demeterMockKey + * + * @return mixed + */ + private static function getExistingDemeterMock( + Mockery\Container $container, + $demeterMockKey + ) { + $mocks = $container->getMocks(); + $mock = $mocks[$demeterMockKey]; + + return $mock; + } + + /** + * Checks if the passed array representing a demeter + * chain with the method names is empty. + * + * @param array $methodNames + * + * @return bool + */ + private static function noMoreElementsInChain(array $methodNames) + { + return empty($methodNames); + } + + public static function declareClass($fqn) + { + return static::declareType($fqn, "class"); + } + + public static function declareInterface($fqn) + { + return static::declareType($fqn, "interface"); + } + + private static function declareType($fqn, $type) + { + $targetCode = "addMockeryExpectationsToAssertionCount(); + $this->checkMockeryExceptions(); + $this->closeMockery(); + + parent::assertPostConditions(); + } + + protected function addMockeryExpectationsToAssertionCount() + { + $this->addToAssertionCount(Mockery::getContainer()->mockery_getExpectationCount()); + } + + protected function checkMockeryExceptions() + { + if (!method_exists($this, "markAsRisky")) { + return; + } + + foreach (Mockery::getContainer()->mockery_thrownExceptions() as $e) { + if (!$e->dismissed()) { + $this->markAsRisky(); + } + } + } + + protected function closeMockery() + { + Mockery::close(); + $this->mockeryOpen = false; + } + + /** + * @before + */ + protected function startMockery() + { + $this->mockeryOpen = true; + } + + /** + * @after + */ + protected function purgeMockeryContainer() + { + if ($this->mockeryOpen) { + // post conditions wasn't called, so test probably failed + Mockery::close(); + } + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/MockeryPHPUnitIntegrationAssertPostConditions.php b/vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/MockeryPHPUnitIntegrationAssertPostConditions.php new file mode 100644 index 00000000..68fc89ef --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/MockeryPHPUnitIntegrationAssertPostConditions.php @@ -0,0 +1,31 @@ +mockeryAssertPostConditions(); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/MockeryTestCase.php b/vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/MockeryTestCase.php new file mode 100644 index 00000000..f18ce2cf --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/MockeryTestCase.php @@ -0,0 +1,35 @@ +mockeryTestSetUp(); + } + + protected function tearDown(): void + { + $this->mockeryTestTearDown(); + parent::tearDown(); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListener.php b/vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListener.php new file mode 100644 index 00000000..effb8e48 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListener.php @@ -0,0 +1,48 @@ +trait = new TestListenerTrait(); + } + + public function endTest(Test $test, float $time): void + { + $this->trait->endTest($test, $time); + } + + public function startTestSuite(TestSuite $suite): void + { + $this->trait->startTestSuite(); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListenerTrait.php b/vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListenerTrait.php new file mode 100644 index 00000000..7b5bfe92 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListenerTrait.php @@ -0,0 +1,87 @@ +getStatus() !== BaseTestRunner::STATUS_PASSED) { + // If the test didn't pass there is no guarantee that + // verifyMockObjects and assertPostConditions have been called. + // And even if it did, the point here is to prevent false + // negatives, not to make failing tests fail for more reasons. + return; + } + + try { + // The self() call is used as a sentinel. Anything that throws if + // the container is closed already will do. + \Mockery::self(); + } catch (\LogicException $_) { + return; + } + + $e = new ExpectationFailedException( + \sprintf( + "Mockery's expectations have not been verified. Make sure that \Mockery::close() is called at the end of the test. Consider using %s\MockeryPHPUnitIntegration or extending %s\MockeryTestCase.", + __NAMESPACE__, + __NAMESPACE__ + ) + ); + + /** @var \PHPUnit\Framework\TestResult $result */ + $result = $test->getTestResultObject(); + + if ($result !== null) { + $result->addFailure($test, $e, $time); + } + } + + public function startTestSuite() + { + if (method_exists(Blacklist::class, 'addDirectory')) { + (new BlackList())->getBlacklistedDirectories(); + Blacklist::addDirectory(\dirname((new \ReflectionClass(\Mockery::class))->getFileName())); + } else { + Blacklist::$blacklistedClassNames[\Mockery::class] = 1; + } + } +} diff --git a/vendor/mockery/mockery/library/Mockery/ClosureWrapper.php b/vendor/mockery/mockery/library/Mockery/ClosureWrapper.php new file mode 100644 index 00000000..35ca16db --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/ClosureWrapper.php @@ -0,0 +1,42 @@ +closure = $closure; + } + + public function __invoke() + { + return call_user_func_array($this->closure, func_get_args()); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/CompositeExpectation.php b/vendor/mockery/mockery/library/Mockery/CompositeExpectation.php new file mode 100644 index 00000000..52314322 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/CompositeExpectation.php @@ -0,0 +1,154 @@ +_expectations[] = $expectation; + } + + /** + * @param mixed ...$args + */ + public function andReturn(...$args) + { + return $this->__call(__FUNCTION__, $args); + } + + /** + * Set a return value, or sequential queue of return values + * + * @param mixed ...$args + * @return self + */ + public function andReturns(...$args) + { + return call_user_func_array([$this, 'andReturn'], $args); + } + + /** + * Intercept any expectation calls and direct against all expectations + * + * @param string $method + * @param array $args + * @return self + */ + public function __call($method, array $args) + { + foreach ($this->_expectations as $expectation) { + call_user_func_array(array($expectation, $method), $args); + } + return $this; + } + + /** + * Return order number of the first expectation + * + * @return int + */ + public function getOrderNumber() + { + reset($this->_expectations); + $first = current($this->_expectations); + return $first->getOrderNumber(); + } + + /** + * Return the parent mock of the first expectation + * + * @return \Mockery\MockInterface|\Mockery\LegacyMockInterface + */ + public function getMock() + { + reset($this->_expectations); + $first = current($this->_expectations); + return $first->getMock(); + } + + /** + * Mockery API alias to getMock + * + * @return \Mockery\LegacyMockInterface|\Mockery\MockInterface + */ + public function mock() + { + return $this->getMock(); + } + + /** + * Starts a new expectation addition on the first mock which is the primary + * target outside of a demeter chain + * + * @param mixed ...$args + * @return \Mockery\Expectation + */ + public function shouldReceive(...$args) + { + reset($this->_expectations); + $first = current($this->_expectations); + return call_user_func_array(array($first->getMock(), 'shouldReceive'), $args); + } + + /** + * Starts a new expectation addition on the first mock which is the primary + * target outside of a demeter chain + * + * @param mixed ...$args + * @return \Mockery\Expectation + */ + public function shouldNotReceive(...$args) + { + reset($this->_expectations); + $first = current($this->_expectations); + return call_user_func_array(array($first->getMock(), 'shouldNotReceive'), $args); + } + + /** + * Return the string summary of this composite expectation + * + * @return string + */ + public function __toString() + { + $return = '['; + $parts = array(); + foreach ($this->_expectations as $exp) { + $parts[] = (string) $exp; + } + $return .= implode(', ', $parts) . ']'; + return $return; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Configuration.php b/vendor/mockery/mockery/library/Mockery/Configuration.php new file mode 100644 index 00000000..bce05f3c --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Configuration.php @@ -0,0 +1,283 @@ +_quickDefinitionsConfiguration = new QuickDefinitionsConfiguration(); + } + + /** + * Custom object formatters + * + * @var array + */ + protected $_objectFormatters = array(); + + /** + * Default argument matchers + * + * @var array + */ + protected $_defaultMatchers = array(); + + /** + * Set boolean to allow/prevent mocking of non-existent methods + * + * @param bool $flag + */ + public function allowMockingNonExistentMethods($flag = true) + { + $this->_allowMockingNonExistentMethod = (bool) $flag; + } + + /** + * Return flag indicating whether mocking non-existent methods allowed + * + * @return bool + */ + public function mockingNonExistentMethodsAllowed() + { + return $this->_allowMockingNonExistentMethod; + } + + /** + * Set boolean to allow/prevent unnecessary mocking of methods + * + * @param bool $flag + * + * @deprecated since 1.4.0 + */ + public function allowMockingMethodsUnnecessarily($flag = true) + { + @trigger_error(sprintf("The %s method is deprecated and will be removed in a future version of Mockery", __METHOD__), E_USER_DEPRECATED); + + $this->_allowMockingMethodsUnnecessarily = (bool) $flag; + } + + /** + * Return flag indicating whether mocking non-existent methods allowed + * + * @return bool + * + * @deprecated since 1.4.0 + */ + public function mockingMethodsUnnecessarilyAllowed() + { + @trigger_error(sprintf("The %s method is deprecated and will be removed in a future version of Mockery", __METHOD__), E_USER_DEPRECATED); + + return $this->_allowMockingMethodsUnnecessarily; + } + + /** + * Set a parameter map (array of param signature strings) for the method + * of an internal PHP class. + * + * @param string $class + * @param string $method + * @param array $map + */ + public function setInternalClassMethodParamMap($class, $method, array $map) + { + if (\PHP_MAJOR_VERSION > 7) { + throw new \LogicException('Internal class parameter overriding is not available in PHP 8. Incompatible signatures have been reclassified as fatal errors.'); + } + + if (!isset($this->_internalClassParamMap[strtolower($class)])) { + $this->_internalClassParamMap[strtolower($class)] = array(); + } + $this->_internalClassParamMap[strtolower($class)][strtolower($method)] = $map; + } + + /** + * Remove all overridden parameter maps from internal PHP classes. + */ + public function resetInternalClassMethodParamMaps() + { + $this->_internalClassParamMap = array(); + } + + /** + * Get the parameter map of an internal PHP class method + * + * @return array|null + */ + public function getInternalClassMethodParamMap($class, $method) + { + if (isset($this->_internalClassParamMap[strtolower($class)][strtolower($method)])) { + return $this->_internalClassParamMap[strtolower($class)][strtolower($method)]; + } + } + + public function getInternalClassMethodParamMaps() + { + return $this->_internalClassParamMap; + } + + public function setConstantsMap(array $map) + { + $this->_constantsMap = $map; + } + + public function getConstantsMap() + { + return $this->_constantsMap; + } + + /** + * Returns the quick definitions configuration + */ + public function getQuickDefinitions(): QuickDefinitionsConfiguration + { + return $this->_quickDefinitionsConfiguration; + } + + /** + * Disable reflection caching + * + * It should be always enabled, except when using + * PHPUnit's --static-backup option. + * + * @see https://github.com/mockery/mockery/issues/268 + */ + public function disableReflectionCache() + { + $this->_reflectionCacheEnabled = false; + } + + /** + * Enable reflection caching + * + * It should be always enabled, except when using + * PHPUnit's --static-backup option. + * + * @see https://github.com/mockery/mockery/issues/268 + */ + public function enableReflectionCache() + { + $this->_reflectionCacheEnabled = true; + } + + /** + * Is reflection cache enabled? + */ + public function reflectionCacheEnabled() + { + return $this->_reflectionCacheEnabled; + } + + public function setObjectFormatter($class, $formatterCallback) + { + $this->_objectFormatters[$class] = $formatterCallback; + } + + public function getObjectFormatter($class, $defaultFormatter) + { + $parentClass = $class; + do { + $classes[] = $parentClass; + $parentClass = get_parent_class($parentClass); + } while ($parentClass); + $classesAndInterfaces = array_merge($classes, class_implements($class)); + foreach ($classesAndInterfaces as $type) { + if (isset($this->_objectFormatters[$type])) { + return $this->_objectFormatters[$type]; + } + } + return $defaultFormatter; + } + + /** + * @param string $class + * @param string $matcherClass + */ + public function setDefaultMatcher($class, $matcherClass) + { + if (!is_a($matcherClass, \Mockery\Matcher\MatcherAbstract::class, true) && + !is_a($matcherClass, \Hamcrest\Matcher::class, true) && + !is_a($matcherClass, \Hamcrest_Matcher::class, true) + ) { + throw new \InvalidArgumentException( + "Matcher class must be either Hamcrest matcher or extend \Mockery\Matcher\MatcherAbstract, " . + "'$matcherClass' given." + ); + } + $this->_defaultMatchers[$class] = $matcherClass; + } + + public function getDefaultMatcher($class) + { + $parentClass = $class; + do { + $classes[] = $parentClass; + $parentClass = get_parent_class($parentClass); + } while ($parentClass); + $classesAndInterfaces = array_merge($classes, class_implements($class)); + foreach ($classesAndInterfaces as $type) { + if (isset($this->_defaultMatchers[$type])) { + return $this->_defaultMatchers[$type]; + } + } + return null; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Container.php b/vendor/mockery/mockery/library/Mockery/Container.php new file mode 100644 index 00000000..196dc996 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Container.php @@ -0,0 +1,535 @@ +_generator = $generator ?: \Mockery::getDefaultGenerator(); + $this->_loader = $loader ?: \Mockery::getDefaultLoader(); + } + + /** + * Generates a new mock object for this container + * + * I apologies in advance for this. A God Method just fits the API which + * doesn't require differentiating between classes, interfaces, abstracts, + * names or partials - just so long as it's something that can be mocked. + * I'll refactor it one day so it's easier to follow. + * + * @param array ...$args + * + * @return Mock + * @throws Exception\RuntimeException + */ + public function mock(...$args) + { + $expectationClosure = null; + $quickdefs = array(); + $constructorArgs = null; + $blocks = array(); + $class = null; + + if (count($args) > 1) { + $finalArg = end($args); + reset($args); + if (is_callable($finalArg) && is_object($finalArg)) { + $expectationClosure = array_pop($args); + } + } + + $builder = new MockConfigurationBuilder(); + + foreach ($args as $k => $arg) { + if ($arg instanceof MockConfigurationBuilder) { + $builder = $arg; + unset($args[$k]); + } + } + reset($args); + + $builder->setParameterOverrides(\Mockery::getConfiguration()->getInternalClassMethodParamMaps()); + $builder->setConstantsMap(\Mockery::getConfiguration()->getConstantsMap()); + + while (count($args) > 0) { + $arg = array_shift($args); + // check for multiple interfaces + if (is_string($arg)) { + foreach (explode('|', $arg) as $type) { + if ($arg === 'null') { + // skip PHP 8 'null's + } elseif (strpos($type, ',') && !strpos($type, ']')) { + $interfaces = explode(',', str_replace(' ', '', $type)); + $builder->addTargets($interfaces); + } elseif (substr($type, 0, 6) == 'alias:') { + $type = str_replace('alias:', '', $type); + $builder->addTarget('stdClass'); + $builder->setName($type); + } elseif (substr($type, 0, 9) == 'overload:') { + $type = str_replace('overload:', '', $type); + $builder->setInstanceMock(true); + $builder->addTarget('stdClass'); + $builder->setName($type); + } elseif (substr($type, strlen($type)-1, 1) == ']') { + $parts = explode('[', $type); + if (!class_exists($parts[0], true) && !interface_exists($parts[0], true)) { + throw new \Mockery\Exception('Can only create a partial mock from' + . ' an existing class or interface'); + } + $class = $parts[0]; + $parts[1] = str_replace(' ', '', $parts[1]); + $partialMethods = array_filter(explode(',', strtolower(rtrim($parts[1], ']')))); + $builder->addTarget($class); + foreach ($partialMethods as $partialMethod) { + if ($partialMethod[0] === '!') { + $builder->addBlackListedMethod(substr($partialMethod, 1)); + continue; + } + $builder->addWhiteListedMethod($partialMethod); + } + } elseif (class_exists($type, true) || interface_exists($type, true) || trait_exists($type, true)) { + $builder->addTarget($type); + } elseif (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() && (!class_exists($type, true) && !interface_exists($type, true))) { + throw new \Mockery\Exception("Mockery can't find '$type' so can't mock it"); + } else { + if (!$this->isValidClassName($type)) { + throw new \Mockery\Exception('Class name contains invalid characters'); + } + $builder->addTarget($type); + } + break; // unions are "sum" types and not "intersections", and so we must only process the first part + } + } elseif (is_object($arg)) { + $builder->addTarget($arg); + } elseif (is_array($arg)) { + if (!empty($arg) && array_keys($arg) !== range(0, count($arg) - 1)) { + // if associative array + if (array_key_exists(self::BLOCKS, $arg)) { + $blocks = $arg[self::BLOCKS]; + } + unset($arg[self::BLOCKS]); + $quickdefs = $arg; + } else { + $constructorArgs = $arg; + } + } else { + throw new \Mockery\Exception( + 'Unable to parse arguments sent to ' + . get_class($this) . '::mock()' + ); + } + } + + $builder->addBlackListedMethods($blocks); + + if (!is_null($constructorArgs)) { + $builder->addBlackListedMethod("__construct"); // we need to pass through + } else { + $builder->setMockOriginalDestructor(true); + } + + if (!empty($partialMethods) && $constructorArgs === null) { + $constructorArgs = array(); + } + + $config = $builder->getMockConfiguration(); + + $this->checkForNamedMockClashes($config); + + $def = $this->getGenerator()->generate($config); + + if (class_exists($def->getClassName(), $attemptAutoload = false)) { + $rfc = new \ReflectionClass($def->getClassName()); + if (!$rfc->implementsInterface("Mockery\LegacyMockInterface")) { + throw new \Mockery\Exception\RuntimeException("Could not load mock {$def->getClassName()}, class already exists"); + } + } + + $this->getLoader()->load($def); + + $mock = $this->_getInstance($def->getClassName(), $constructorArgs); + $mock->mockery_init($this, $config->getTargetObject(), $config->isInstanceMock()); + + if (!empty($quickdefs)) { + if (\Mockery::getConfiguration()->getQuickDefinitions()->shouldBeCalledAtLeastOnce()) { + $mock->shouldReceive($quickdefs)->atLeast()->once(); + } else { + $mock->shouldReceive($quickdefs)->byDefault(); + } + } + if (!empty($expectationClosure)) { + $expectationClosure($mock); + } + $this->rememberMock($mock); + return $mock; + } + + public function instanceMock() + { + } + + public function getLoader() + { + return $this->_loader; + } + + public function getGenerator() + { + return $this->_generator; + } + + /** + * @param string $method + * @param string $parent + * @return string|null + */ + public function getKeyOfDemeterMockFor($method, $parent) + { + $keys = array_keys($this->_mocks); + $match = preg_grep("/__demeter_" . md5($parent) . "_{$method}$/", $keys); + if (count($match) == 1) { + $res = array_values($match); + if (count($res) > 0) { + return $res[0]; + } + } + return null; + } + + /** + * @return array + */ + public function getMocks() + { + return $this->_mocks; + } + + /** + * Tear down tasks for this container + * + * @throws \Exception + * @return void + */ + public function mockery_teardown() + { + try { + $this->mockery_verify(); + } catch (\Exception $e) { + $this->mockery_close(); + throw $e; + } + } + + /** + * Verify the container mocks + * + * @return void + */ + public function mockery_verify() + { + foreach ($this->_mocks as $mock) { + $mock->mockery_verify(); + } + } + + /** + * Retrieves all exceptions thrown by mocks + * + * @return array + */ + public function mockery_thrownExceptions() + { + $e = []; + + foreach ($this->_mocks as $mock) { + $e = array_merge($e, $mock->mockery_thrownExceptions()); + } + + return $e; + } + + /** + * Reset the container to its original state + * + * @return void + */ + public function mockery_close() + { + foreach ($this->_mocks as $mock) { + $mock->mockery_teardown(); + } + $this->_mocks = array(); + } + + /** + * Fetch the next available allocation order number + * + * @return int + */ + public function mockery_allocateOrder() + { + $this->_allocatedOrder += 1; + return $this->_allocatedOrder; + } + + /** + * Set ordering for a group + * + * @param mixed $group + * @param int $order + */ + public function mockery_setGroup($group, $order) + { + $this->_groups[$group] = $order; + } + + /** + * Fetch array of ordered groups + * + * @return array + */ + public function mockery_getGroups() + { + return $this->_groups; + } + + /** + * Set current ordered number + * + * @param int $order + * @return int The current order number that was set + */ + public function mockery_setCurrentOrder($order) + { + $this->_currentOrder = $order; + return $this->_currentOrder; + } + + /** + * Get current ordered number + * + * @return int + */ + public function mockery_getCurrentOrder() + { + return $this->_currentOrder; + } + + /** + * Validate the current mock's ordering + * + * @param string $method + * @param int $order + * @throws \Mockery\Exception + * @return void + */ + public function mockery_validateOrder($method, $order, \Mockery\LegacyMockInterface $mock) + { + if ($order < $this->_currentOrder) { + $exception = new \Mockery\Exception\InvalidOrderException( + 'Method ' . $method . ' called out of order: expected order ' + . $order . ', was ' . $this->_currentOrder + ); + $exception->setMock($mock) + ->setMethodName($method) + ->setExpectedOrder($order) + ->setActualOrder($this->_currentOrder); + throw $exception; + } + $this->mockery_setCurrentOrder($order); + } + + /** + * Gets the count of expectations on the mocks + * + * @return int + */ + public function mockery_getExpectationCount() + { + $count = 0; + foreach ($this->_mocks as $mock) { + $count += $mock->mockery_getExpectationCount(); + } + return $count; + } + + /** + * Store a mock and set its container reference + * + * @param \Mockery\Mock $mock + * @return \Mockery\LegacyMockInterface|\Mockery\MockInterface + */ + public function rememberMock(\Mockery\LegacyMockInterface $mock) + { + if (!isset($this->_mocks[get_class($mock)])) { + $this->_mocks[get_class($mock)] = $mock; + } else { + /** + * This condition triggers for an instance mock where origin mock + * is already remembered + */ + $this->_mocks[] = $mock; + } + return $mock; + } + + /** + * Retrieve the last remembered mock object, which is the same as saying + * retrieve the current mock being programmed where you have yet to call + * mock() to change it - thus why the method name is "self" since it will be + * be used during the programming of the same mock. + * + * @return \Mockery\Mock + */ + public function self() + { + $mocks = array_values($this->_mocks); + $index = count($mocks) - 1; + return $mocks[$index]; + } + + /** + * Return a specific remembered mock according to the array index it + * was stored to in this container instance + * + * @return \Mockery\Mock + */ + public function fetchMock($reference) + { + if (isset($this->_mocks[$reference])) { + return $this->_mocks[$reference]; + } + } + + protected function _getInstance($mockName, $constructorArgs = null) + { + if ($constructorArgs !== null) { + $r = new \ReflectionClass($mockName); + return $r->newInstanceArgs($constructorArgs); + } + + try { + $instantiator = new Instantiator(); + $instance = $instantiator->instantiate($mockName); + } catch (\Exception $ex) { + $internalMockName = $mockName . '_Internal'; + + if (!class_exists($internalMockName)) { + eval("class $internalMockName extends $mockName {" . + 'public function __construct() {}' . + '}'); + } + + $instance = new $internalMockName(); + } + + return $instance; + } + + protected function checkForNamedMockClashes($config) + { + $name = $config->getName(); + + if (!$name) { + return; + } + + $hash = $config->getHash(); + + if (isset($this->_namedMocks[$name])) { + if ($hash !== $this->_namedMocks[$name]) { + throw new \Mockery\Exception( + "The mock named '$name' has been already defined with a different mock configuration" + ); + } + } + + $this->_namedMocks[$name] = $hash; + } + + /** + * see http://php.net/manual/en/language.oop5.basic.php + * @param string $className + * @return bool + */ + public function isValidClassName($className) + { + $pos = strpos($className, '\\'); + if ($pos === 0) { + $className = substr($className, 1); // remove the first backslash + } + // all the namespaces and class name should match the regex + $invalidNames = array_filter(explode('\\', $className), function ($name) { + return !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $name); + }); + return empty($invalidNames); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/CountValidator/AtLeast.php b/vendor/mockery/mockery/library/Mockery/CountValidator/AtLeast.php new file mode 100644 index 00000000..f6ac130e --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/CountValidator/AtLeast.php @@ -0,0 +1,62 @@ +_limit > $n) { + $exception = new Mockery\Exception\InvalidCountException( + 'Method ' . (string) $this->_expectation + . ' from ' . $this->_expectation->getMock()->mockery_getName() + . ' should be called' . PHP_EOL + . ' at least ' . $this->_limit . ' times but called ' . $n + . ' times.' + ); + $exception->setMock($this->_expectation->getMock()) + ->setMethodName((string) $this->_expectation) + ->setExpectedCountComparative('>=') + ->setExpectedCount($this->_limit) + ->setActualCount($n); + throw $exception; + } + } +} diff --git a/vendor/mockery/mockery/library/Mockery/CountValidator/AtMost.php b/vendor/mockery/mockery/library/Mockery/CountValidator/AtMost.php new file mode 100644 index 00000000..4d23e28d --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/CountValidator/AtMost.php @@ -0,0 +1,51 @@ +_limit < $n) { + $exception = new Mockery\Exception\InvalidCountException( + 'Method ' . (string) $this->_expectation + . ' from ' . $this->_expectation->getMock()->mockery_getName() + . ' should be called' . PHP_EOL + . ' at most ' . $this->_limit . ' times but called ' . $n + . ' times.' + ); + $exception->setMock($this->_expectation->getMock()) + ->setMethodName((string) $this->_expectation) + ->setExpectedCountComparative('<=') + ->setExpectedCount($this->_limit) + ->setActualCount($n); + throw $exception; + } + } +} diff --git a/vendor/mockery/mockery/library/Mockery/CountValidator/CountValidatorAbstract.php b/vendor/mockery/mockery/library/Mockery/CountValidator/CountValidatorAbstract.php new file mode 100644 index 00000000..ae3b0bfe --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/CountValidator/CountValidatorAbstract.php @@ -0,0 +1,69 @@ +_expectation = $expectation; + $this->_limit = $limit; + } + + /** + * Checks if the validator can accept an additional nth call + * + * @param int $n + * @return bool + */ + public function isEligible($n) + { + return ($n < $this->_limit); + } + + /** + * Validate the call count against this validator + * + * @param int $n + * @return bool + */ + abstract public function validate($n); +} diff --git a/vendor/mockery/mockery/library/Mockery/CountValidator/Exact.php b/vendor/mockery/mockery/library/Mockery/CountValidator/Exact.php new file mode 100644 index 00000000..504f080d --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/CountValidator/Exact.php @@ -0,0 +1,54 @@ +_limit !== $n) { + $because = $this->_expectation->getExceptionMessage(); + + $exception = new Mockery\Exception\InvalidCountException( + 'Method ' . (string) $this->_expectation + . ' from ' . $this->_expectation->getMock()->mockery_getName() + . ' should be called' . PHP_EOL + . ' exactly ' . $this->_limit . ' times but called ' . $n + . ' times.' + . ($because ? ' Because ' . $this->_expectation->getExceptionMessage() : '') + ); + $exception->setMock($this->_expectation->getMock()) + ->setMethodName((string) $this->_expectation) + ->setExpectedCountComparative('=') + ->setExpectedCount($this->_limit) + ->setActualCount($n); + throw $exception; + } + } +} diff --git a/vendor/mockery/mockery/library/Mockery/CountValidator/Exception.php b/vendor/mockery/mockery/library/Mockery/CountValidator/Exception.php new file mode 100644 index 00000000..b43aad3e --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/CountValidator/Exception.php @@ -0,0 +1,25 @@ +dismissed = true; + + // we sometimes stack them + if ($this->getPrevious() && $this->getPrevious() instanceof BadMethodCallException) { + $this->getPrevious()->dismiss(); + } + } + + public function dismissed() + { + return $this->dismissed; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Exception/InvalidArgumentException.php b/vendor/mockery/mockery/library/Mockery/Exception/InvalidArgumentException.php new file mode 100644 index 00000000..ccf5c76f --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Exception/InvalidArgumentException.php @@ -0,0 +1,25 @@ +mockObject = $mock; + return $this; + } + + public function setMethodName($name) + { + $this->method = $name; + return $this; + } + + public function setActualCount($count) + { + $this->actual = $count; + return $this; + } + + public function setExpectedCount($count) + { + $this->expected = $count; + return $this; + } + + public function setExpectedCountComparative($comp) + { + if (!in_array($comp, array('=', '>', '<', '>=', '<='))) { + throw new RuntimeException( + 'Illegal comparative for expected call counts set: ' . $comp + ); + } + $this->expectedComparative = $comp; + return $this; + } + + public function getMock() + { + return $this->mockObject; + } + + public function getMethodName() + { + return $this->method; + } + + public function getActualCount() + { + return $this->actual; + } + + public function getExpectedCount() + { + return $this->expected; + } + + public function getMockName() + { + return $this->getMock()->mockery_getName(); + } + + public function getExpectedCountComparative() + { + return $this->expectedComparative; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Exception/InvalidOrderException.php b/vendor/mockery/mockery/library/Mockery/Exception/InvalidOrderException.php new file mode 100644 index 00000000..50b8049e --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Exception/InvalidOrderException.php @@ -0,0 +1,83 @@ +mockObject = $mock; + return $this; + } + + public function setMethodName($name) + { + $this->method = $name; + return $this; + } + + public function setActualOrder($count) + { + $this->actual = $count; + return $this; + } + + public function setExpectedOrder($count) + { + $this->expected = $count; + return $this; + } + + public function getMock() + { + return $this->mockObject; + } + + public function getMethodName() + { + return $this->method; + } + + public function getActualOrder() + { + return $this->actual; + } + + public function getExpectedOrder() + { + return $this->expected; + } + + public function getMockName() + { + return $this->getMock()->mockery_getName(); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Exception/NoMatchingExpectationException.php b/vendor/mockery/mockery/library/Mockery/Exception/NoMatchingExpectationException.php new file mode 100644 index 00000000..fe5f3515 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Exception/NoMatchingExpectationException.php @@ -0,0 +1,70 @@ +mockObject = $mock; + return $this; + } + + public function setMethodName($name) + { + $this->method = $name; + return $this; + } + + public function setActualArguments($count) + { + $this->actual = $count; + return $this; + } + + public function getMock() + { + return $this->mockObject; + } + + public function getMethodName() + { + return $this->method; + } + + public function getActualArguments() + { + return $this->actual; + } + + public function getMockName() + { + return $this->getMock()->mockery_getName(); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Exception/RuntimeException.php b/vendor/mockery/mockery/library/Mockery/Exception/RuntimeException.php new file mode 100644 index 00000000..4b2f53c2 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Exception/RuntimeException.php @@ -0,0 +1,25 @@ +_mock = $mock; + $this->_name = $name; + $this->withAnyArgs(); + } + + /** + * Return a string with the method name and arguments formatted + * + * @param string $name Name of the expected method + * @param array $args List of arguments to the method + * @return string + */ + public function __toString() + { + return \Mockery::formatArgs($this->_name, $this->_expectedArgs); + } + + /** + * Verify the current call, i.e. that the given arguments match those + * of this expectation + * + * @param array $args + * @return mixed + */ + public function verifyCall(array $args) + { + $this->validateOrder(); + $this->_actualCount++; + if (true === $this->_passthru) { + return $this->_mock->mockery_callSubjectMethod($this->_name, $args); + } + + $return = $this->_getReturnValue($args); + $this->throwAsNecessary($return); + $this->_setValues(); + + return $return; + } + + /** + * Throws an exception if the expectation has been configured to do so + * + * @throws \Throwable + * @return void + */ + private function throwAsNecessary($return) + { + if (!$this->_throw) { + return; + } + + if ($return instanceof \Throwable) { + throw $return; + } + + return; + } + + /** + * Sets public properties with queued values to the mock object + * + * @param array $args + * @return mixed + */ + protected function _setValues() + { + $mockClass = get_class($this->_mock); + $container = $this->_mock->mockery_getContainer(); + /** @var Mock[] $mocks */ + $mocks = $container->getMocks(); + foreach ($this->_setQueue as $name => &$values) { + if (count($values) > 0) { + $value = array_shift($values); + $this->_mock->{$name} = $value; + foreach ($mocks as $mock) { + if (is_a($mock, $mockClass) && $mock->mockery_isInstance()) { + $mock->{$name} = $value; + } + } + } + } + } + + /** + * Fetch the return value for the matching args + * + * @param array $args + * @return mixed + */ + protected function _getReturnValue(array $args) + { + if (count($this->_closureQueue) > 1) { + return call_user_func_array(array_shift($this->_closureQueue), $args); + } elseif (count($this->_closureQueue) > 0) { + return call_user_func_array(current($this->_closureQueue), $args); + } elseif (count($this->_returnQueue) > 1) { + return array_shift($this->_returnQueue); + } elseif (count($this->_returnQueue) > 0) { + return current($this->_returnQueue); + } + + return $this->_mock->mockery_returnValueForMethod($this->_name); + } + + /** + * Checks if this expectation is eligible for additional calls + * + * @return bool + */ + public function isEligible() + { + foreach ($this->_countValidators as $validator) { + if (!$validator->isEligible($this->_actualCount)) { + return false; + } + } + return true; + } + + /** + * Check if there is a constraint on call count + * + * @return bool + */ + public function isCallCountConstrained() + { + return (count($this->_countValidators) > 0); + } + + /** + * Verify call order + * + * @return void + */ + public function validateOrder() + { + if ($this->_orderNumber) { + $this->_mock->mockery_validateOrder((string) $this, $this->_orderNumber, $this->_mock); + } + if ($this->_globalOrderNumber) { + $this->_mock->mockery_getContainer() + ->mockery_validateOrder((string) $this, $this->_globalOrderNumber, $this->_mock); + } + } + + /** + * Verify this expectation + * + * @return void + */ + public function verify() + { + foreach ($this->_countValidators as $validator) { + $validator->validate($this->_actualCount); + } + } + + /** + * Check if the registered expectation is an ArgumentListMatcher + * @return bool + */ + private function isArgumentListMatcher() + { + return (count($this->_expectedArgs) === 1 && ($this->_expectedArgs[0] instanceof ArgumentListMatcher)); + } + + private function isAndAnyOtherArgumentsMatcher($expectedArg) + { + return $expectedArg instanceof AndAnyOtherArgs; + } + + /** + * Check if passed arguments match an argument expectation + * + * @param array $args + * @return bool + */ + public function matchArgs(array $args) + { + if ($this->isArgumentListMatcher()) { + return $this->_matchArg($this->_expectedArgs[0], $args); + } + $argCount = count($args); + if ($argCount !== count((array) $this->_expectedArgs)) { + $lastExpectedArgument = end($this->_expectedArgs); + reset($this->_expectedArgs); + + if ($this->isAndAnyOtherArgumentsMatcher($lastExpectedArgument)) { + $args = array_slice($args, 0, array_search($lastExpectedArgument, $this->_expectedArgs, true)); + return $this->_matchArgs($args); + } + + return false; + } + + return $this->_matchArgs($args); + } + + /** + * Check if the passed arguments match the expectations, one by one. + * + * @param array $args + * @return bool + */ + protected function _matchArgs($args) + { + $argCount = count($args); + for ($i=0; $i<$argCount; $i++) { + $param =& $args[$i]; + if (!$this->_matchArg($this->_expectedArgs[$i], $param)) { + return false; + } + } + return true; + } + + /** + * Check if passed argument matches an argument expectation + * + * @param mixed $expected + * @param mixed $actual + * @return bool + */ + protected function _matchArg($expected, &$actual) + { + if ($expected === $actual) { + return true; + } + if (!is_object($expected) && !is_object($actual) && $expected == $actual) { + return true; + } + if (is_string($expected) && is_object($actual)) { + $result = $actual instanceof $expected; + if ($result) { + return true; + } + } + if (is_object($expected)) { + $matcher = \Mockery::getConfiguration()->getDefaultMatcher(get_class($expected)); + if ($matcher !== null) { + $expected = new $matcher($expected); + } + } + if ($expected instanceof \Mockery\Matcher\MatcherAbstract) { + return $expected->match($actual); + } + if ($expected instanceof \Hamcrest\Matcher || $expected instanceof \Hamcrest_Matcher) { + return $expected->matches($actual); + } + return false; + } + + /** + * Expected argument setter for the expectation + * + * @param mixed ...$args + * + * @return self + */ + public function with(...$args) + { + return $this->withArgs($args); + } + + /** + * Expected arguments for the expectation passed as an array + * + * @param array $arguments + * @return self + */ + private function withArgsInArray(array $arguments) + { + if (empty($arguments)) { + return $this->withNoArgs(); + } + $this->_expectedArgs = $arguments; + return $this; + } + + /** + * Expected arguments have to be matched by the given closure. + * + * @param Closure $closure + * @return self + */ + private function withArgsMatchedByClosure(Closure $closure) + { + $this->_expectedArgs = [new MultiArgumentClosure($closure)]; + return $this; + } + + /** + * Expected arguments for the expectation passed as an array or a closure that matches each passed argument on + * each function call. + * + * @param array|Closure $argsOrClosure + * @return self + */ + public function withArgs($argsOrClosure) + { + if (is_array($argsOrClosure)) { + $this->withArgsInArray($argsOrClosure); + } elseif ($argsOrClosure instanceof Closure) { + $this->withArgsMatchedByClosure($argsOrClosure); + } else { + throw new \InvalidArgumentException(sprintf('Call to %s with an invalid argument (%s), only array and ' . + 'closure are allowed', __METHOD__, $argsOrClosure)); + } + return $this; + } + + /** + * Set with() as no arguments expected + * + * @return self + */ + public function withNoArgs() + { + $this->_expectedArgs = [new NoArgs()]; + return $this; + } + + /** + * Set expectation that any arguments are acceptable + * + * @return self + */ + public function withAnyArgs() + { + $this->_expectedArgs = [new AnyArgs()]; + return $this; + } + + /** + * Expected arguments should partially match the real arguments + * + * @param mixed ...$expectedArgs + * @return self + */ + public function withSomeOfArgs(...$expectedArgs) + { + return $this->withArgs(function (...$args) use ($expectedArgs) { + foreach ($expectedArgs as $expectedArg) { + if (!in_array($expectedArg, $args, true)) { + return false; + } + } + return true; + }); + } + + /** + * Set a return value, or sequential queue of return values + * + * @param mixed ...$args + * @return self + */ + public function andReturn(...$args) + { + $this->_returnQueue = $args; + return $this; + } + + /** + * Set a return value, or sequential queue of return values + * + * @param mixed ...$args + * @return self + */ + public function andReturns(...$args) + { + return call_user_func_array([$this, 'andReturn'], $args); + } + + /** + * Return this mock, like a fluent interface + * + * @return self + */ + public function andReturnSelf() + { + return $this->andReturn($this->_mock); + } + + /** + * Set a sequential queue of return values with an array + * + * @param array $values + * @return self + */ + public function andReturnValues(array $values) + { + call_user_func_array(array($this, 'andReturn'), $values); + return $this; + } + + /** + * Set a closure or sequence of closures with which to generate return + * values. The arguments passed to the expected method are passed to the + * closures as parameters. + * + * @param callable ...$args + * @return self + */ + public function andReturnUsing(...$args) + { + $this->_closureQueue = $args; + return $this; + } + + /** + * Sets up a closure to return the nth argument from the expected method call + * + * @param int $index + * @return self + */ + public function andReturnArg($index) + { + if (!is_int($index) || $index < 0) { + throw new \InvalidArgumentException("Invalid argument index supplied. Index must be a non-negative integer."); + } + $closure = function (...$args) use ($index) { + if (array_key_exists($index, $args)) { + return $args[$index]; + } + throw new \OutOfBoundsException("Cannot return an argument value. No argument exists for the index $index"); + }; + + $this->_closureQueue = [$closure]; + return $this; + } + + /** + * Return a self-returning black hole object. + * + * @return self + */ + public function andReturnUndefined() + { + $this->andReturn(new \Mockery\Undefined()); + return $this; + } + + /** + * Return null. This is merely a language construct for Mock describing. + * + * @return self + */ + public function andReturnNull() + { + return $this->andReturn(null); + } + + public function andReturnFalse() + { + return $this->andReturn(false); + } + + public function andReturnTrue() + { + return $this->andReturn(true); + } + + /** + * Set Exception class and arguments to that class to be thrown + * + * @param string|\Exception $exception + * @param string $message + * @param int $code + * @param \Exception $previous + * @return self + */ + public function andThrow($exception, $message = '', $code = 0, \Exception $previous = null) + { + $this->_throw = true; + if (is_object($exception)) { + $this->andReturn($exception); + } else { + $this->andReturn(new $exception($message, $code, $previous)); + } + return $this; + } + + public function andThrows($exception, $message = '', $code = 0, \Exception $previous = null) + { + return $this->andThrow($exception, $message, $code, $previous); + } + + /** + * Set Exception classes to be thrown + * + * @param array $exceptions + * @return self + */ + public function andThrowExceptions(array $exceptions) + { + $this->_throw = true; + foreach ($exceptions as $exception) { + if (!is_object($exception)) { + throw new Exception('You must pass an array of exception objects to andThrowExceptions'); + } + } + return $this->andReturnValues($exceptions); + } + + /** + * Register values to be set to a public property each time this expectation occurs + * + * @param string $name + * @param array ...$values + * @return self + */ + public function andSet($name, ...$values) + { + $this->_setQueue[$name] = $values; + return $this; + } + + /** + * Sets up a closure that will yield each of the provided args + * + * @param mixed ...$args + * @return self + */ + public function andYield(...$args) + { + $this->_closureQueue = [ + static function () use ($args) { + foreach ($args as $arg) { + yield $arg; + } + }, + ]; + + return $this; + } + + /** + * Alias to andSet(). Allows the natural English construct + * - set('foo', 'bar')->andReturn('bar') + * + * @param string $name + * @param mixed $value + * @return self + */ + public function set($name, $value) + { + return call_user_func_array(array($this, 'andSet'), func_get_args()); + } + + /** + * Indicates this expectation should occur zero or more times + * + * @return self + */ + public function zeroOrMoreTimes() + { + $this->atLeast()->never(); + } + + /** + * Indicates the number of times this expectation should occur + * + * @param int $limit + * @throws \InvalidArgumentException + * @return self + */ + public function times($limit = null) + { + if (is_null($limit)) { + return $this; + } + if (!is_int($limit)) { + throw new \InvalidArgumentException('The passed Times limit should be an integer value'); + } + $this->_countValidators[$this->_countValidatorClass] = new $this->_countValidatorClass($this, $limit); + + if ('Mockery\CountValidator\Exact' !== $this->_countValidatorClass) { + $this->_countValidatorClass = 'Mockery\CountValidator\Exact'; + unset($this->_countValidators[$this->_countValidatorClass]); + } + + return $this; + } + + /** + * Indicates that this expectation is never expected to be called + * + * @return self + */ + public function never() + { + return $this->times(0); + } + + /** + * Indicates that this expectation is expected exactly once + * + * @return self + */ + public function once() + { + return $this->times(1); + } + + /** + * Indicates that this expectation is expected exactly twice + * + * @return self + */ + public function twice() + { + return $this->times(2); + } + + /** + * Sets next count validator to the AtLeast instance + * + * @return self + */ + public function atLeast() + { + $this->_countValidatorClass = 'Mockery\CountValidator\AtLeast'; + return $this; + } + + /** + * Sets next count validator to the AtMost instance + * + * @return self + */ + public function atMost() + { + $this->_countValidatorClass = 'Mockery\CountValidator\AtMost'; + return $this; + } + + /** + * Shorthand for setting minimum and maximum constraints on call counts + * + * @param int $minimum + * @param int $maximum + */ + public function between($minimum, $maximum) + { + return $this->atLeast()->times($minimum)->atMost()->times($maximum); + } + + + /** + * Set the exception message + * + * @param string $message + * @return $this + */ + public function because($message) + { + $this->_because = $message; + return $this; + } + + /** + * Indicates that this expectation must be called in a specific given order + * + * @param string $group Name of the ordered group + * @return self + */ + public function ordered($group = null) + { + if ($this->_globally) { + $this->_globalOrderNumber = $this->_defineOrdered($group, $this->_mock->mockery_getContainer()); + } else { + $this->_orderNumber = $this->_defineOrdered($group, $this->_mock); + } + $this->_globally = false; + return $this; + } + + /** + * Indicates call order should apply globally + * + * @return self + */ + public function globally() + { + $this->_globally = true; + return $this; + } + + /** + * Setup the ordering tracking on the mock or mock container + * + * @param string $group + * @param object $ordering + * @return int + */ + protected function _defineOrdered($group, $ordering) + { + $groups = $ordering->mockery_getGroups(); + if (is_null($group)) { + $result = $ordering->mockery_allocateOrder(); + } elseif (isset($groups[$group])) { + $result = $groups[$group]; + } else { + $result = $ordering->mockery_allocateOrder(); + $ordering->mockery_setGroup($group, $result); + } + return $result; + } + + /** + * Return order number + * + * @return int + */ + public function getOrderNumber() + { + return $this->_orderNumber; + } + + /** + * Mark this expectation as being a default + * + * @return self + */ + public function byDefault() + { + $director = $this->_mock->mockery_getExpectationsFor($this->_name); + if (!empty($director)) { + $director->makeExpectationDefault($this); + } + return $this; + } + + /** + * Return the parent mock of the expectation + * + * @return \Mockery\LegacyMockInterface|\Mockery\MockInterface + */ + public function getMock() + { + return $this->_mock; + } + + /** + * Flag this expectation as calling the original class method with the + * any provided arguments instead of using a return value queue. + * + * @return self + */ + public function passthru() + { + if ($this->_mock instanceof Mock) { + throw new Exception( + 'Mock Objects not created from a loaded/existing class are ' + . 'incapable of passing method calls through to a parent class' + ); + } + $this->_passthru = true; + return $this; + } + + /** + * Cloning logic + * + */ + public function __clone() + { + $newValidators = array(); + $countValidators = $this->_countValidators; + foreach ($countValidators as $validator) { + $newValidators[] = clone $validator; + } + $this->_countValidators = $newValidators; + } + + public function getName() + { + return $this->_name; + } + + public function getExceptionMessage() + { + return $this->_because; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/ExpectationDirector.php b/vendor/mockery/mockery/library/Mockery/ExpectationDirector.php new file mode 100644 index 00000000..efb0b70b --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/ExpectationDirector.php @@ -0,0 +1,226 @@ +_name = $name; + $this->_mock = $mock; + } + + /** + * Add a new expectation to the director + * + * @param \Mockery\Expectation $expectation + */ + public function addExpectation(\Mockery\Expectation $expectation) + { + $this->_expectations[] = $expectation; + } + + /** + * Handle a method call being directed by this instance + * + * @param array $args + * @return mixed + */ + public function call(array $args) + { + $expectation = $this->findExpectation($args); + if (is_null($expectation)) { + $exception = new \Mockery\Exception\NoMatchingExpectationException( + 'No matching handler found for ' + . $this->_mock->mockery_getName() . '::' + . \Mockery::formatArgs($this->_name, $args) + . '. Either the method was unexpected or its arguments matched' + . ' no expected argument list for this method' + . PHP_EOL . PHP_EOL + . \Mockery::formatObjects($args) + ); + $exception->setMock($this->_mock) + ->setMethodName($this->_name) + ->setActualArguments($args); + throw $exception; + } + return $expectation->verifyCall($args); + } + + /** + * Verify all expectations of the director + * + * @throws \Mockery\CountValidator\Exception + * @return void + */ + public function verify() + { + if (!empty($this->_expectations)) { + foreach ($this->_expectations as $exp) { + $exp->verify(); + } + } else { + foreach ($this->_defaults as $exp) { + $exp->verify(); + } + } + } + + /** + * Attempt to locate an expectation matching the provided args + * + * @param array $args + * @return mixed + */ + public function findExpectation(array $args) + { + $expectation = null; + + if (!empty($this->_expectations)) { + $expectation = $this->_findExpectationIn($this->_expectations, $args); + } + + if ($expectation === null && !empty($this->_defaults)) { + $expectation = $this->_findExpectationIn($this->_defaults, $args); + } + + return $expectation; + } + + /** + * Make the given expectation a default for all others assuming it was + * correctly created last + * + * @param \Mockery\Expectation $expectation + */ + public function makeExpectationDefault(\Mockery\Expectation $expectation) + { + $last = end($this->_expectations); + if ($last === $expectation) { + array_pop($this->_expectations); + array_unshift($this->_defaults, $expectation); + } else { + throw new \Mockery\Exception( + 'Cannot turn a previously defined expectation into a default' + ); + } + } + + /** + * Search current array of expectations for a match + * + * @param array $expectations + * @param array $args + * @return mixed + */ + protected function _findExpectationIn(array $expectations, array $args) + { + foreach ($expectations as $exp) { + if ($exp->isEligible() && $exp->matchArgs($args)) { + return $exp; + } + } + foreach ($expectations as $exp) { + if ($exp->matchArgs($args)) { + return $exp; + } + } + } + + /** + * Return all expectations assigned to this director + * + * @return array + */ + public function getExpectations() + { + return $this->_expectations; + } + + /** + * Return all expectations assigned to this director + * + * @return array + */ + public function getDefaultExpectations() + { + return $this->_defaults; + } + + /** + * Return the number of expectations assigned to this director. + * + * @return int + */ + public function getExpectationCount() + { + $count = 0; + /** @var Expectation $expectations */ + $expectations = $this->getExpectations() ?: $this->getDefaultExpectations(); + foreach ($expectations as $expectation) { + if ($expectation->isCallCountConstrained()) { + $count++; + } + } + return $count; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/ExpectationInterface.php b/vendor/mockery/mockery/library/Mockery/ExpectationInterface.php new file mode 100644 index 00000000..f1295ad3 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/ExpectationInterface.php @@ -0,0 +1,46 @@ +once(); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/CachingGenerator.php b/vendor/mockery/mockery/library/Mockery/Generator/CachingGenerator.php new file mode 100644 index 00000000..6497e885 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/CachingGenerator.php @@ -0,0 +1,45 @@ +generator = $generator; + } + + public function generate(MockConfiguration $config) + { + $hash = $config->getHash(); + if (isset($this->cache[$hash])) { + return $this->cache[$hash]; + } + + $definition = $this->generator->generate($config); + $this->cache[$hash] = $definition; + + return $definition; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/DefinedTargetClass.php b/vendor/mockery/mockery/library/Mockery/Generator/DefinedTargetClass.php new file mode 100644 index 00000000..7463f1d1 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/DefinedTargetClass.php @@ -0,0 +1,110 @@ +rfc = $rfc; + $this->name = $alias === null ? $rfc->getName() : $alias; + } + + public static function factory($name, $alias = null) + { + return new self(new \ReflectionClass($name), $alias); + } + + public function getName() + { + return $this->name; + } + + public function isAbstract() + { + return $this->rfc->isAbstract(); + } + + public function isFinal() + { + return $this->rfc->isFinal(); + } + + public function getMethods() + { + return array_map(function ($method) { + return new Method($method); + }, $this->rfc->getMethods()); + } + + public function getInterfaces() + { + $class = __CLASS__; + return array_map(function ($interface) use ($class) { + return new $class($interface); + }, $this->rfc->getInterfaces()); + } + + public function __toString() + { + return $this->getName(); + } + + public function getNamespaceName() + { + return $this->rfc->getNamespaceName(); + } + + public function inNamespace() + { + return $this->rfc->inNamespace(); + } + + public function getShortName() + { + return $this->rfc->getShortName(); + } + + public function implementsInterface($interface) + { + return $this->rfc->implementsInterface($interface); + } + + public function hasInternalAncestor() + { + if ($this->rfc->isInternal()) { + return true; + } + + $child = $this->rfc; + while ($parent = $child->getParentClass()) { + if ($parent->isInternal()) { + return true; + } + $child = $parent; + } + + return false; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/Generator.php b/vendor/mockery/mockery/library/Mockery/Generator/Generator.php new file mode 100644 index 00000000..459a93cc --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/Generator.php @@ -0,0 +1,27 @@ +method = $method; + } + + public function __call($method, $args) + { + return call_user_func_array(array($this->method, $method), $args); + } + + /** + * @return Parameter[] + */ + public function getParameters() + { + return array_map(function (\ReflectionParameter $parameter) { + return new Parameter($parameter); + }, $this->method->getParameters()); + } + + /** + * @return string|null + */ + public function getReturnType() + { + return Reflector::getReturnType($this->method); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/MockConfiguration.php b/vendor/mockery/mockery/library/Mockery/Generator/MockConfiguration.php new file mode 100644 index 00000000..05903e5b --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/MockConfiguration.php @@ -0,0 +1,556 @@ +addTargets($targets); + $this->blackListedMethods = $blackListedMethods; + $this->whiteListedMethods = $whiteListedMethods; + $this->name = $name; + $this->instanceMock = $instanceMock; + $this->parameterOverrides = $parameterOverrides; + $this->mockOriginalDestructor = $mockOriginalDestructor; + $this->constantsMap = $constantsMap; + } + + /** + * Attempt to create a hash of the configuration, in order to allow caching + * + * @TODO workout if this will work + * + * @return string + */ + public function getHash() + { + $vars = array( + 'targetClassName' => $this->targetClassName, + 'targetInterfaceNames' => $this->targetInterfaceNames, + 'targetTraitNames' => $this->targetTraitNames, + 'name' => $this->name, + 'blackListedMethods' => $this->blackListedMethods, + 'whiteListedMethod' => $this->whiteListedMethods, + 'instanceMock' => $this->instanceMock, + 'parameterOverrides' => $this->parameterOverrides, + 'mockOriginalDestructor' => $this->mockOriginalDestructor + ); + + return md5(serialize($vars)); + } + + /** + * Gets a list of methods from the classes, interfaces and objects and + * filters them appropriately. Lot's of filtering going on, perhaps we could + * have filter classes to iterate through + */ + public function getMethodsToMock() + { + $methods = $this->getAllMethods(); + + foreach ($methods as $key => $method) { + if ($method->isFinal()) { + unset($methods[$key]); + } + } + + /** + * Whitelist trumps everything else + */ + if (count($this->getWhiteListedMethods())) { + $whitelist = array_map('strtolower', $this->getWhiteListedMethods()); + $methods = array_filter($methods, function ($method) use ($whitelist) { + return $method->isAbstract() || in_array(strtolower($method->getName()), $whitelist); + }); + + return $methods; + } + + /** + * Remove blacklisted methods + */ + if (count($this->getBlackListedMethods())) { + $blacklist = array_map('strtolower', $this->getBlackListedMethods()); + $methods = array_filter($methods, function ($method) use ($blacklist) { + return !in_array(strtolower($method->getName()), $blacklist); + }); + } + + /** + * Internal objects can not be instantiated with newInstanceArgs and if + * they implement Serializable, unserialize will have to be called. As + * such, we can't mock it and will need a pass to add a dummy + * implementation + */ + if ($this->getTargetClass() + && $this->getTargetClass()->implementsInterface("Serializable") + && $this->getTargetClass()->hasInternalAncestor()) { + $methods = array_filter($methods, function ($method) { + return $method->getName() !== "unserialize"; + }); + } + + return array_values($methods); + } + + /** + * We declare the __call method to handle undefined stuff, if the class + * we're mocking has also defined it, we need to comply with their interface + */ + public function requiresCallTypeHintRemoval() + { + foreach ($this->getAllMethods() as $method) { + if ("__call" === $method->getName()) { + $params = $method->getParameters(); + return !$params[1]->isArray(); + } + } + + return false; + } + + /** + * We declare the __callStatic method to handle undefined stuff, if the class + * we're mocking has also defined it, we need to comply with their interface + */ + public function requiresCallStaticTypeHintRemoval() + { + foreach ($this->getAllMethods() as $method) { + if ("__callStatic" === $method->getName()) { + $params = $method->getParameters(); + return !$params[1]->isArray(); + } + } + + return false; + } + + public function rename($className) + { + $targets = array(); + + if ($this->targetClassName) { + $targets[] = $this->targetClassName; + } + + if ($this->targetInterfaceNames) { + $targets = array_merge($targets, $this->targetInterfaceNames); + } + + if ($this->targetTraitNames) { + $targets = array_merge($targets, $this->targetTraitNames); + } + + if ($this->targetObject) { + $targets[] = $this->targetObject; + } + + return new self( + $targets, + $this->blackListedMethods, + $this->whiteListedMethods, + $className, + $this->instanceMock, + $this->parameterOverrides, + $this->mockOriginalDestructor, + $this->constantsMap + ); + } + + protected function addTarget($target) + { + if (is_object($target)) { + $this->setTargetObject($target); + $this->setTargetClassName(get_class($target)); + return $this; + } + + if ($target[0] !== "\\") { + $target = "\\" . $target; + } + + if (class_exists($target)) { + $this->setTargetClassName($target); + return $this; + } + + if (interface_exists($target)) { + $this->addTargetInterfaceName($target); + return $this; + } + + if (trait_exists($target)) { + $this->addTargetTraitName($target); + return $this; + } + + /** + * Default is to set as class, or interface if class already set + * + * Don't like this condition, can't remember what the default + * targetClass is for + */ + if ($this->getTargetClassName()) { + $this->addTargetInterfaceName($target); + return $this; + } + + $this->setTargetClassName($target); + } + + protected function addTargets($interfaces) + { + foreach ($interfaces as $interface) { + $this->addTarget($interface); + } + } + + public function getTargetClassName() + { + return $this->targetClassName; + } + + public function getTargetClass() + { + if ($this->targetClass) { + return $this->targetClass; + } + + if (!$this->targetClassName) { + return null; + } + + if (class_exists($this->targetClassName)) { + $alias = null; + if (strpos($this->targetClassName, '@') !== false) { + $alias = (new MockNameBuilder()) + ->addPart('anonymous_class') + ->addPart(md5($this->targetClassName)) + ->build(); + class_alias($this->targetClassName, $alias); + } + $dtc = DefinedTargetClass::factory($this->targetClassName, $alias); + + if ($this->getTargetObject() == false && $dtc->isFinal()) { + throw new \Mockery\Exception( + 'The class ' . $this->targetClassName . ' is marked final and its methods' + . ' cannot be replaced. Classes marked final can be passed in' + . ' to \Mockery::mock() as instantiated objects to create a' + . ' partial mock, but only if the mock is not subject to type' + . ' hinting checks.' + ); + } + + $this->targetClass = $dtc; + } else { + $this->targetClass = UndefinedTargetClass::factory($this->targetClassName); + } + + return $this->targetClass; + } + + public function getTargetTraits() + { + if (!empty($this->targetTraits)) { + return $this->targetTraits; + } + + foreach ($this->targetTraitNames as $targetTrait) { + $this->targetTraits[] = DefinedTargetClass::factory($targetTrait); + } + + $this->targetTraits = array_unique($this->targetTraits); // just in case + return $this->targetTraits; + } + + public function getTargetInterfaces() + { + if (!empty($this->targetInterfaces)) { + return $this->targetInterfaces; + } + + foreach ($this->targetInterfaceNames as $targetInterface) { + if (!interface_exists($targetInterface)) { + $this->targetInterfaces[] = UndefinedTargetClass::factory($targetInterface); + continue; + } + + $dtc = DefinedTargetClass::factory($targetInterface); + $extendedInterfaces = array_keys($dtc->getInterfaces()); + $extendedInterfaces[] = $targetInterface; + + $traversableFound = false; + $iteratorShiftedToFront = false; + foreach ($extendedInterfaces as $interface) { + if (!$traversableFound && preg_match("/^\\?Iterator(|Aggregate)$/i", $interface)) { + break; + } + + if (preg_match("/^\\\\?IteratorAggregate$/i", $interface)) { + $this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate"); + $iteratorShiftedToFront = true; + } elseif (preg_match("/^\\\\?Iterator$/i", $interface)) { + $this->targetInterfaces[] = DefinedTargetClass::factory("\\Iterator"); + $iteratorShiftedToFront = true; + } elseif (preg_match("/^\\\\?Traversable$/i", $interface)) { + $traversableFound = true; + } + } + + if ($traversableFound && !$iteratorShiftedToFront) { + $this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate"); + } + + /** + * We never straight up implement Traversable + */ + if (!preg_match("/^\\\\?Traversable$/i", $targetInterface)) { + $this->targetInterfaces[] = $dtc; + } + } + $this->targetInterfaces = array_unique($this->targetInterfaces); // just in case + return $this->targetInterfaces; + } + + public function getTargetObject() + { + return $this->targetObject; + } + + public function getName() + { + return $this->name; + } + + /** + * Generate a suitable name based on the config + */ + public function generateName() + { + $nameBuilder = new MockNameBuilder(); + + if ($this->getTargetObject()) { + $className = get_class($this->getTargetObject()); + $nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className); + } + + if ($this->getTargetClass()) { + $className = $this->getTargetClass()->getName(); + $nameBuilder->addPart(strpos($className, '@') !== false ? md5($className) : $className); + } + + foreach ($this->getTargetInterfaces() as $targetInterface) { + $nameBuilder->addPart($targetInterface->getName()); + } + + return $nameBuilder->build(); + } + + public function getShortName() + { + $parts = explode("\\", $this->getName()); + return array_pop($parts); + } + + public function getNamespaceName() + { + $parts = explode("\\", $this->getName()); + array_pop($parts); + + if (count($parts)) { + return implode("\\", $parts); + } + + return ""; + } + + public function getBlackListedMethods() + { + return $this->blackListedMethods; + } + + public function getWhiteListedMethods() + { + return $this->whiteListedMethods; + } + + public function isInstanceMock() + { + return $this->instanceMock; + } + + public function getParameterOverrides() + { + return $this->parameterOverrides; + } + + public function isMockOriginalDestructor() + { + return $this->mockOriginalDestructor; + } + + protected function setTargetClassName($targetClassName) + { + $this->targetClassName = $targetClassName; + } + + protected function getAllMethods() + { + if ($this->allMethods) { + return $this->allMethods; + } + + $classes = $this->getTargetInterfaces(); + + if ($this->getTargetClass()) { + $classes[] = $this->getTargetClass(); + } + + $methods = array(); + foreach ($classes as $class) { + $methods = array_merge($methods, $class->getMethods()); + } + + foreach ($this->getTargetTraits() as $trait) { + foreach ($trait->getMethods() as $method) { + if ($method->isAbstract()) { + $methods[] = $method; + } + } + } + + $names = array(); + $methods = array_filter($methods, function ($method) use (&$names) { + if (in_array($method->getName(), $names)) { + return false; + } + + $names[] = $method->getName(); + return true; + }); + + return $this->allMethods = $methods; + } + + /** + * If we attempt to implement Traversable, we must ensure we are also + * implementing either Iterator or IteratorAggregate, and that whichever one + * it is comes before Traversable in the list of implements. + */ + protected function addTargetInterfaceName($targetInterface) + { + $this->targetInterfaceNames[] = $targetInterface; + } + + protected function addTargetTraitName($targetTraitName) + { + $this->targetTraitNames[] = $targetTraitName; + } + + protected function setTargetObject($object) + { + $this->targetObject = $object; + } + + public function getConstantsMap() + { + return $this->constantsMap; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/MockConfigurationBuilder.php b/vendor/mockery/mockery/library/Mockery/Generator/MockConfigurationBuilder.php new file mode 100644 index 00000000..273b1d8b --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/MockConfigurationBuilder.php @@ -0,0 +1,174 @@ +blackListedMethods = array_diff($this->blackListedMethods, $this->php7SemiReservedKeywords); + } + + public function addTarget($target) + { + $this->targets[] = $target; + + return $this; + } + + public function addTargets($targets) + { + foreach ($targets as $target) { + $this->addTarget($target); + } + + return $this; + } + + public function setName($name) + { + $this->name = $name; + return $this; + } + + public function addBlackListedMethod($blackListedMethod) + { + $this->blackListedMethods[] = $blackListedMethod; + return $this; + } + + public function addBlackListedMethods(array $blackListedMethods) + { + foreach ($blackListedMethods as $method) { + $this->addBlackListedMethod($method); + } + return $this; + } + + public function setBlackListedMethods(array $blackListedMethods) + { + $this->blackListedMethods = $blackListedMethods; + return $this; + } + + public function addWhiteListedMethod($whiteListedMethod) + { + $this->whiteListedMethods[] = $whiteListedMethod; + return $this; + } + + public function addWhiteListedMethods(array $whiteListedMethods) + { + foreach ($whiteListedMethods as $method) { + $this->addWhiteListedMethod($method); + } + return $this; + } + + public function setWhiteListedMethods(array $whiteListedMethods) + { + $this->whiteListedMethods = $whiteListedMethods; + return $this; + } + + public function setInstanceMock($instanceMock) + { + $this->instanceMock = (bool) $instanceMock; + } + + public function setParameterOverrides(array $overrides) + { + $this->parameterOverrides = $overrides; + } + + public function setMockOriginalDestructor($mockDestructor) + { + $this->mockOriginalDestructor = $mockDestructor; + return $this; + } + + public function setConstantsMap(array $map) + { + $this->constantsMap = $map; + } + + public function getMockConfiguration() + { + return new MockConfiguration( + $this->targets, + $this->blackListedMethods, + $this->whiteListedMethods, + $this->name, + $this->instanceMock, + $this->parameterOverrides, + $this->mockOriginalDestructor, + $this->constantsMap + ); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/MockDefinition.php b/vendor/mockery/mockery/library/Mockery/Generator/MockDefinition.php new file mode 100644 index 00000000..fd6a9fa2 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/MockDefinition.php @@ -0,0 +1,51 @@ +getName()) { + throw new \InvalidArgumentException("MockConfiguration must contain a name"); + } + $this->config = $config; + $this->code = $code; + } + + public function getConfig() + { + return $this->config; + } + + public function getClassName() + { + return $this->config->getName(); + } + + public function getCode() + { + return $this->code; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/MockNameBuilder.php b/vendor/mockery/mockery/library/Mockery/Generator/MockNameBuilder.php new file mode 100644 index 00000000..204308ab --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/MockNameBuilder.php @@ -0,0 +1,46 @@ +parts[] = $part; + + return $this; + } + + public function build() + { + $parts = ['Mockery', static::$mockCounter++]; + + foreach ($this->parts as $part) { + $parts[] = str_replace("\\", "_", $part); + } + + return implode('_', $parts); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/Parameter.php b/vendor/mockery/mockery/library/Mockery/Generator/Parameter.php new file mode 100644 index 00000000..70095336 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/Parameter.php @@ -0,0 +1,117 @@ +rfp = $rfp; + } + + public function __call($method, array $args) + { + return call_user_func_array(array($this->rfp, $method), $args); + } + + /** + * Get the reflection class for the parameter type, if it exists. + * + * This will be null if there was no type, or it was a scalar or a union. + * + * @return \ReflectionClass|null + * + * @deprecated since 1.3.3 and will be removed in 2.0. + */ + public function getClass() + { + $typeHint = Reflector::getTypeHint($this->rfp, true); + + return \class_exists($typeHint) ? DefinedTargetClass::factory($typeHint, false) : null; + } + + /** + * Get the string representation for the paramater type. + * + * @return string|null + */ + public function getTypeHint() + { + return Reflector::getTypeHint($this->rfp); + } + + /** + * Get the string representation for the paramater type. + * + * @return string + * + * @deprecated since 1.3.2 and will be removed in 2.0. Use getTypeHint() instead. + */ + public function getTypeHintAsString() + { + return (string) Reflector::getTypeHint($this->rfp, true); + } + + /** + * Get the name of the parameter. + * + * Some internal classes have funny looking definitions! + * + * @return string + */ + public function getName() + { + $name = $this->rfp->getName(); + if (!$name || $name == '...') { + $name = 'arg' . self::$parameterCounter++; + } + + return $name; + } + + /** + * Determine if the parameter is an array. + * + * @return bool + */ + public function isArray() + { + return Reflector::isArray($this->rfp); + } + + /** + * Determine if the parameter is variadic. + * + * @return bool + */ + public function isVariadic() + { + return $this->rfp->isVariadic(); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/AvoidMethodClashPass.php b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/AvoidMethodClashPass.php new file mode 100644 index 00000000..45312573 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/AvoidMethodClashPass.php @@ -0,0 +1,49 @@ +getName(); + }, $config->getMethodsToMock()); + + foreach (["allows", "expects"] as $method) { + if (in_array($method, $names)) { + $code = preg_replace( + "#// start method {$method}.*// end method {$method}#ms", + "", + $code + ); + + $code = str_replace(" implements MockInterface", " implements LegacyMockInterface", $code); + } + } + + return $code; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/CallTypeHintPass.php b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/CallTypeHintPass.php new file mode 100644 index 00000000..fd00264c --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/CallTypeHintPass.php @@ -0,0 +1,47 @@ +requiresCallTypeHintRemoval()) { + $code = str_replace( + 'public function __call($method, array $args)', + 'public function __call($method, $args)', + $code + ); + } + + if ($config->requiresCallStaticTypeHintRemoval()) { + $code = str_replace( + 'public static function __callStatic($method, array $args)', + 'public static function __callStatic($method, $args)', + $code + ); + } + + return $code; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/ClassNamePass.php b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/ClassNamePass.php new file mode 100644 index 00000000..b5a31098 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/ClassNamePass.php @@ -0,0 +1,49 @@ +getNamespaceName(); + + $namespace = ltrim($namespace, "\\"); + + $className = $config->getShortName(); + + $code = str_replace( + 'namespace Mockery;', + $namespace ? 'namespace ' . $namespace . ';' : '', + $code + ); + + $code = str_replace( + 'class Mock', + 'class ' . $className, + $code + ); + + return $code; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/ClassPass.php b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/ClassPass.php new file mode 100644 index 00000000..1debcbb1 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/ClassPass.php @@ -0,0 +1,53 @@ +getTargetClass(); + + if (!$target) { + return $code; + } + + if ($target->isFinal()) { + return $code; + } + + $className = ltrim($target->getName(), "\\"); + + if (!class_exists($className)) { + \Mockery::declareClass($className); + } + + $code = str_replace( + "implements MockInterface", + "extends \\" . $className . " implements MockInterface", + $code + ); + + return $code; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/ConstantsPass.php b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/ConstantsPass.php new file mode 100644 index 00000000..df5dd8ce --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/ConstantsPass.php @@ -0,0 +1,33 @@ +getConstantsMap(); + if (empty($cm)) { + return $code; + } + + if (!isset($cm[$config->getName()])) { + return $code; + } + + $cm = $cm[$config->getName()]; + + $constantsCode = ''; + foreach ($cm as $constant => $value) { + $constantsCode .= sprintf("\n const %s = %s;\n", $constant, var_export($value, true)); + } + + $i = strrpos($code, '}'); + $code = substr_replace($code, $constantsCode, $i); + $code .= "}\n"; + + return $code; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/InstanceMockPass.php b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/InstanceMockPass.php new file mode 100644 index 00000000..62791475 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/InstanceMockPass.php @@ -0,0 +1,83 @@ +_mockery_ignoreVerification = false; + \$associatedRealObject = \Mockery::fetchMock(__CLASS__); + + foreach (get_object_vars(\$this) as \$attr => \$val) { + if (\$attr !== "_mockery_ignoreVerification" && \$attr !== "_mockery_expectations") { + \$this->\$attr = \$associatedRealObject->\$attr; + } + } + + \$directors = \$associatedRealObject->mockery_getExpectations(); + foreach (\$directors as \$method=>\$director) { + // get the director method needed + \$existingDirector = \$this->mockery_getExpectationsFor(\$method); + if (!\$existingDirector) { + \$existingDirector = new \Mockery\ExpectationDirector(\$method, \$this); + \$this->mockery_setExpectationsFor(\$method, \$existingDirector); + } + \$expectations = \$director->getExpectations(); + foreach (\$expectations as \$expectation) { + \$clonedExpectation = clone \$expectation; + \$existingDirector->addExpectation(\$clonedExpectation); + } + \$defaultExpectations = \$director->getDefaultExpectations(); + foreach (array_reverse(\$defaultExpectations) as \$expectation) { + \$clonedExpectation = clone \$expectation; + \$existingDirector->addExpectation(\$clonedExpectation); + \$existingDirector->makeExpectationDefault(\$clonedExpectation); + } + } + \Mockery::getContainer()->rememberMock(\$this); + + \$this->_mockery_constructorCalled(func_get_args()); + } +MOCK; + + public function apply($code, MockConfiguration $config) + { + if ($config->isInstanceMock()) { + $code = $this->appendToClass($code, static::INSTANCE_MOCK_CODE); + } + + return $code; + } + + protected function appendToClass($class, $code) + { + $lastBrace = strrpos($class, "}"); + $class = substr($class, 0, $lastBrace) . $code . "\n }\n"; + return $class; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/InterfacePass.php b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/InterfacePass.php new file mode 100644 index 00000000..982956e5 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/InterfacePass.php @@ -0,0 +1,48 @@ +getTargetInterfaces() as $i) { + $name = ltrim($i->getName(), "\\"); + if (!interface_exists($name)) { + \Mockery::declareInterface($name); + } + } + + $interfaces = array_reduce((array) $config->getTargetInterfaces(), function ($code, $i) { + return $code . ", \\" . ltrim($i->getName(), "\\"); + }, ""); + + $code = str_replace( + "implements MockInterface", + "implements MockInterface" . $interfaces, + $code + ); + + return $code; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/MagicMethodTypeHintsPass.php b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/MagicMethodTypeHintsPass.php new file mode 100644 index 00000000..ddcdb0b7 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/MagicMethodTypeHintsPass.php @@ -0,0 +1,212 @@ +getMagicMethods($config->getTargetClass()); + foreach ($config->getTargetInterfaces() as $interface) { + $magicMethods = array_merge($magicMethods, $this->getMagicMethods($interface)); + } + + foreach ($magicMethods as $method) { + $code = $this->applyMagicTypeHints($code, $method); + } + + return $code; + } + + /** + * Returns the magic methods within the + * passed DefinedTargetClass. + * + * @param TargetClassInterface $class + * @return array + */ + public function getMagicMethods( + TargetClassInterface $class = null + ) { + if (is_null($class)) { + return array(); + } + return array_filter($class->getMethods(), function (Method $method) { + return in_array($method->getName(), $this->mockMagicMethods); + }); + } + + /** + * Applies type hints of magic methods from + * class to the passed code. + * + * @param int $code + * @param Method $method + * @return string + */ + private function applyMagicTypeHints($code, Method $method) + { + if ($this->isMethodWithinCode($code, $method)) { + $namedParameters = $this->getOriginalParameters( + $code, + $method + ); + $code = preg_replace( + $this->getDeclarationRegex($method->getName()), + $this->getMethodDeclaration($method, $namedParameters), + $code + ); + } + return $code; + } + + /** + * Checks if the method is declared within code. + * + * @param int $code + * @param Method $method + * @return boolean + */ + private function isMethodWithinCode($code, Method $method) + { + return preg_match( + $this->getDeclarationRegex($method->getName()), + $code + ) == 1; + } + + /** + * Returns the method original parameters, as they're + * described in the $code string. + * + * @param int $code + * @param Method $method + * @return array + */ + private function getOriginalParameters($code, Method $method) + { + $matches = []; + $parameterMatches = []; + + preg_match( + $this->getDeclarationRegex($method->getName()), + $code, + $matches + ); + + if (count($matches) > 0) { + preg_match_all( + '/(?<=\$)(\w+)+/i', + $matches[0], + $parameterMatches + ); + } + + $groupMatches = end($parameterMatches); + $parameterNames = is_array($groupMatches) ? $groupMatches : [$groupMatches]; + + return $parameterNames; + } + + /** + * Gets the declaration code, as a string, for the passed method. + * + * @param Method $method + * @param array $namedParameters + * @return string + */ + private function getMethodDeclaration( + Method $method, + array $namedParameters + ) { + $declaration = 'public'; + $declaration .= $method->isStatic() ? ' static' : ''; + $declaration .= ' function ' . $method->getName() . '('; + + foreach ($method->getParameters() as $index => $parameter) { + $declaration .= $this->renderTypeHint($parameter); + $name = isset($namedParameters[$index]) ? $namedParameters[$index] : $parameter->getName(); + $declaration .= '$' . $name; + $declaration .= ','; + } + $declaration = rtrim($declaration, ','); + $declaration .= ') '; + + $returnType = $method->getReturnType(); + if ($returnType !== null) { + $declaration .= sprintf(': %s', $returnType); + } + + return $declaration; + } + + protected function renderTypeHint(Parameter $param) + { + $typeHint = $param->getTypeHint(); + + return $typeHint === null ? '' : sprintf('%s ', $typeHint); + } + + /** + * Returns a regex string used to match the + * declaration of some method. + * + * @param string $methodName + * @return string + */ + private function getDeclarationRegex($methodName) + { + return "/public\s+(?:static\s+)?function\s+$methodName\s*\(.*\)\s*(?=\{)/i"; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/MethodDefinitionPass.php b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/MethodDefinitionPass.php new file mode 100644 index 00000000..b0b743df --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/MethodDefinitionPass.php @@ -0,0 +1,167 @@ +getMethodsToMock() as $method) { + if ($method->isPublic()) { + $methodDef = 'public'; + } elseif ($method->isProtected()) { + $methodDef = 'protected'; + } else { + $methodDef = 'private'; + } + + if ($method->isStatic()) { + $methodDef .= ' static'; + } + + $methodDef .= ' function '; + $methodDef .= $method->returnsReference() ? ' & ' : ''; + $methodDef .= $method->getName(); + $methodDef .= $this->renderParams($method, $config); + $methodDef .= $this->renderReturnType($method); + $methodDef .= $this->renderMethodBody($method, $config); + + $code = $this->appendToClass($code, $methodDef); + } + + return $code; + } + + protected function renderParams(Method $method, $config) + { + $class = $method->getDeclaringClass(); + if ($class->isInternal()) { + $overrides = $config->getParameterOverrides(); + + if (isset($overrides[strtolower($class->getName())][$method->getName()])) { + return '(' . implode(',', $overrides[strtolower($class->getName())][$method->getName()]) . ')'; + } + } + + $methodParams = array(); + $params = $method->getParameters(); + foreach ($params as $param) { + $paramDef = $this->renderTypeHint($param); + $paramDef .= $param->isPassedByReference() ? '&' : ''; + $paramDef .= $param->isVariadic() ? '...' : ''; + $paramDef .= '$' . $param->getName(); + + if (!$param->isVariadic()) { + if (false !== $param->isDefaultValueAvailable()) { + $defaultValue = $param->getDefaultValue(); + $paramDef .= ' = ' . (is_object($defaultValue) ? get_class($defaultValue) : var_export($defaultValue, true)); + } elseif ($param->isOptional()) { + $paramDef .= ' = null'; + } + } + + $methodParams[] = $paramDef; + } + return '(' . implode(', ', $methodParams) . ')'; + } + + protected function renderReturnType(Method $method) + { + $type = $method->getReturnType(); + + return $type ? sprintf(': %s', $type) : ''; + } + + protected function appendToClass($class, $code) + { + $lastBrace = strrpos($class, "}"); + $class = substr($class, 0, $lastBrace) . $code . "\n }\n"; + return $class; + } + + protected function renderTypeHint(Parameter $param) + { + $typeHint = $param->getTypeHint(); + + return $typeHint === null ? '' : sprintf('%s ', $typeHint); + } + + private function renderMethodBody($method, $config) + { + $invoke = $method->isStatic() ? 'static::_mockery_handleStaticMethodCall' : '$this->_mockery_handleMethodCall'; + $body = <<getDeclaringClass(); + $class_name = strtolower($class->getName()); + $overrides = $config->getParameterOverrides(); + if (isset($overrides[$class_name][$method->getName()])) { + $params = array_values($overrides[$class_name][$method->getName()]); + $paramCount = count($params); + for ($i = 0; $i < $paramCount; ++$i) { + $param = $params[$i]; + if (strpos($param, '&') !== false) { + $body .= << $i) { + \$argv[$i] = {$param}; +} + +BODY; + } + } + } else { + $params = array_values($method->getParameters()); + $paramCount = count($params); + for ($i = 0; $i < $paramCount; ++$i) { + $param = $params[$i]; + if (!$param->isPassedByReference()) { + continue; + } + $body .= << $i) { + \$argv[$i] =& \${$param->getName()}; +} + +BODY; + } + } + + $body .= "\$ret = {$invoke}(__FUNCTION__, \$argv);\n"; + + if (! in_array($method->getReturnType(), ['never','void'], true)) { + $body .= "return \$ret;\n"; + } + + $body .= "}\n"; + return $body; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/Pass.php b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/Pass.php new file mode 100644 index 00000000..f7b72c9f --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/Pass.php @@ -0,0 +1,28 @@ + '/public function __wakeup\(\)\s+\{.*?\}/sm', + '__toString' => '/public function __toString\(\)\s+(:\s+string)?\s*\{.*?\}/sm', + ); + + public function apply($code, MockConfiguration $config) + { + $target = $config->getTargetClass(); + + if (!$target) { + return $code; + } + + foreach ($target->getMethods() as $method) { + if ($method->isFinal() && isset($this->methods[$method->getName()])) { + $code = preg_replace($this->methods[$method->getName()], '', $code); + } + } + + return $code; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/RemoveDestructorPass.php b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/RemoveDestructorPass.php new file mode 100644 index 00000000..ed5a4206 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/RemoveDestructorPass.php @@ -0,0 +1,45 @@ + + */ + +namespace Mockery\Generator\StringManipulation\Pass; + +use Mockery\Generator\MockConfiguration; + +/** + * Remove mock's empty destructor if we tend to use original class destructor + */ +class RemoveDestructorPass +{ + public function apply($code, MockConfiguration $config) + { + $target = $config->getTargetClass(); + + if (!$target) { + return $code; + } + + if (!$config->isMockOriginalDestructor()) { + $code = preg_replace('/public function __destruct\(\)\s+\{.*?\}/sm', '', $code); + } + + return $code; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/RemoveUnserializeForInternalSerializableClassesPass.php b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/RemoveUnserializeForInternalSerializableClassesPass.php new file mode 100644 index 00000000..0abefe26 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/RemoveUnserializeForInternalSerializableClassesPass.php @@ -0,0 +1,59 @@ +getTargetClass(); + + if (!$target) { + return $code; + } + + if (!$target->hasInternalAncestor() || !$target->implementsInterface("Serializable")) { + return $code; + } + + $code = $this->appendToClass($code, \PHP_VERSION_ID < 80100 ? self::DUMMY_METHOD_DEFINITION_LEGACY : self::DUMMY_METHOD_DEFINITION); + + return $code; + } + + protected function appendToClass($class, $code) + { + $lastBrace = strrpos($class, "}"); + $class = substr($class, 0, $lastBrace) . $code . "\n }\n"; + return $class; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/TraitPass.php b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/TraitPass.php new file mode 100644 index 00000000..f6db5d74 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/TraitPass.php @@ -0,0 +1,47 @@ +getTargetTraits(); + + if (empty($traits)) { + return $code; + } + + $useStatements = array_map(function ($trait) { + return "use \\\\" . ltrim($trait->getName(), "\\") . ";"; + }, $traits); + + $code = preg_replace( + '/^{$/m', + "{\n " . implode("\n ", $useStatements) . "\n", + $code + ); + + return $code; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/StringManipulationGenerator.php b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulationGenerator.php new file mode 100644 index 00000000..4bc415f6 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/StringManipulationGenerator.php @@ -0,0 +1,89 @@ +passes = $passes; + } + + public function generate(MockConfiguration $config) + { + $code = file_get_contents(__DIR__ . '/../Mock.php'); + $className = $config->getName() ?: $config->generateName(); + + $namedConfig = $config->rename($className); + + foreach ($this->passes as $pass) { + $code = $pass->apply($code, $namedConfig); + } + + return new MockDefinition($namedConfig, $code); + } + + public function addPass(Pass $pass) + { + $this->passes[] = $pass; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Generator/TargetClassInterface.php b/vendor/mockery/mockery/library/Mockery/Generator/TargetClassInterface.php new file mode 100644 index 00000000..77244124 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Generator/TargetClassInterface.php @@ -0,0 +1,107 @@ +name = $name; + } + + public static function factory($name) + { + return new self($name); + } + + public function getName() + { + return $this->name; + } + + public function isAbstract() + { + return false; + } + + public function isFinal() + { + return false; + } + + public function getMethods() + { + return array(); + } + + public function getInterfaces() + { + return array(); + } + + public function getNamespaceName() + { + $parts = explode("\\", ltrim($this->getName(), "\\")); + array_pop($parts); + return implode("\\", $parts); + } + + public function inNamespace() + { + return $this->getNamespaceName() !== ''; + } + + public function getShortName() + { + $parts = explode("\\", $this->getName()); + return array_pop($parts); + } + + public function implementsInterface($interface) + { + return false; + } + + public function hasInternalAncestor() + { + return false; + } + + public function __toString() + { + return $this->name; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/HigherOrderMessage.php b/vendor/mockery/mockery/library/Mockery/HigherOrderMessage.php new file mode 100644 index 00000000..1c13c898 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/HigherOrderMessage.php @@ -0,0 +1,49 @@ +mock = $mock; + $this->method = $method; + } + + /** + * @return \Mockery\Expectation + */ + public function __call($method, $args) + { + if ($this->method === 'shouldNotHaveReceived') { + return $this->mock->{$this->method}($method, $args); + } + + $expectation = $this->mock->{$this->method}($method); + return $expectation->withArgs($args); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Instantiator.php b/vendor/mockery/mockery/library/Mockery/Instantiator.php new file mode 100644 index 00000000..0eafff7f --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Instantiator.php @@ -0,0 +1,162 @@ +. + */ + +namespace Mockery; + +use Closure; +use ReflectionClass; +use UnexpectedValueException; +use InvalidArgumentException; + +/** + * This is a trimmed down version of https://github.com/doctrine/instantiator, + * basically without the caching + * + * @author Marco Pivetta + */ +final class Instantiator +{ + /** + * {@inheritDoc} + */ + public function instantiate($className) + { + $factory = $this->buildFactory($className); + $instance = $factory(); + + return $instance; + } + + /** + * Builds a {@see \Closure} capable of instantiating the given $className without + * invoking its constructor. + * + * @param string $className + * + * @return Closure + */ + private function buildFactory($className) + { + $reflectionClass = $this->getReflectionClass($className); + + if ($this->isInstantiableViaReflection($reflectionClass)) { + return function () use ($reflectionClass) { + return $reflectionClass->newInstanceWithoutConstructor(); + }; + } + + $serializedString = sprintf( + 'O:%d:"%s":0:{}', + strlen($className), + $className + ); + + $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString); + + return function () use ($serializedString) { + return unserialize($serializedString); + }; + } + + /** + * @param string $className + * + * @return ReflectionClass + * + * @throws InvalidArgumentException + */ + private function getReflectionClass($className) + { + if (! class_exists($className)) { + throw new InvalidArgumentException("Class:$className does not exist"); + } + + $reflection = new ReflectionClass($className); + + if ($reflection->isAbstract()) { + throw new InvalidArgumentException("Class:$className is an abstract class"); + } + + return $reflection; + } + + /** + * @param ReflectionClass $reflectionClass + * @param string $serializedString + * + * @throws UnexpectedValueException + * + * @return void + */ + private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, $serializedString) + { + set_error_handler(function ($code, $message, $file, $line) use ($reflectionClass, & $error) { + $msg = sprintf( + 'Could not produce an instance of "%s" via un-serialization, since an error was triggered in file "%s" at line "%d"', + $reflectionClass->getName(), + $file, + $line + ); + + $error = new UnexpectedValueException($msg, 0, new \Exception($message, $code)); + }); + + try { + unserialize($serializedString); + } catch (\Exception $exception) { + restore_error_handler(); + + throw new UnexpectedValueException("An exception was raised while trying to instantiate an instance of \"{$reflectionClass->getName()}\" via un-serialization", 0, $exception); + } + + restore_error_handler(); + + if ($error) { + throw $error; + } + } + + /** + * @param ReflectionClass $reflectionClass + * + * @return bool + */ + private function isInstantiableViaReflection(ReflectionClass $reflectionClass) + { + return ! ($reflectionClass->isInternal() && $reflectionClass->isFinal()); + } + + /** + * Verifies whether the given class is to be considered internal + * + * @param ReflectionClass $reflectionClass + * + * @return bool + */ + private function hasInternalAncestors(ReflectionClass $reflectionClass) + { + do { + if ($reflectionClass->isInternal()) { + return true; + } + } while ($reflectionClass = $reflectionClass->getParentClass()); + + return false; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/LegacyMockInterface.php b/vendor/mockery/mockery/library/Mockery/LegacyMockInterface.php new file mode 100644 index 00000000..ae0cc2a7 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/LegacyMockInterface.php @@ -0,0 +1,240 @@ +getClassName(), false)) { + return; + } + + eval("?>" . $definition->getCode()); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Loader/Loader.php b/vendor/mockery/mockery/library/Mockery/Loader/Loader.php new file mode 100644 index 00000000..170ffb6e --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Loader/Loader.php @@ -0,0 +1,28 @@ +path = realpath($path) ?: sys_get_temp_dir(); + } + + public function load(MockDefinition $definition) + { + if (class_exists($definition->getClassName(), false)) { + return; + } + + $tmpfname = $this->path . DIRECTORY_SEPARATOR . "Mockery_" . uniqid() . ".php"; + file_put_contents($tmpfname, $definition->getCode()); + + require $tmpfname; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/AndAnyOtherArgs.php b/vendor/mockery/mockery/library/Mockery/Matcher/AndAnyOtherArgs.php new file mode 100644 index 00000000..e3c3b943 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/AndAnyOtherArgs.php @@ -0,0 +1,45 @@ +'; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/Any.php b/vendor/mockery/mockery/library/Mockery/Matcher/Any.php new file mode 100644 index 00000000..1ff440b1 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/Any.php @@ -0,0 +1,45 @@ +'; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/AnyArgs.php b/vendor/mockery/mockery/library/Mockery/Matcher/AnyArgs.php new file mode 100644 index 00000000..9663a76d --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/AnyArgs.php @@ -0,0 +1,40 @@ +'; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/AnyOf.php b/vendor/mockery/mockery/library/Mockery/Matcher/AnyOf.php new file mode 100644 index 00000000..bcce4b74 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/AnyOf.php @@ -0,0 +1,46 @@ +_expected, true); + } + + /** + * Return a string representation of this Matcher + * + * @return string + */ + public function __toString() + { + return ''; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/ArgumentListMatcher.php b/vendor/mockery/mockery/library/Mockery/Matcher/ArgumentListMatcher.php new file mode 100644 index 00000000..04408f56 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/ArgumentListMatcher.php @@ -0,0 +1,25 @@ +_expected; + $result = $closure($actual); + return $result === true; + } + + /** + * Return a string representation of this Matcher + * + * @return string + */ + public function __toString() + { + return ''; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/Contains.php b/vendor/mockery/mockery/library/Mockery/Matcher/Contains.php new file mode 100644 index 00000000..79afb73a --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/Contains.php @@ -0,0 +1,64 @@ +_expected as $exp) { + $match = false; + foreach ($values as $val) { + if ($exp === $val || $exp == $val) { + $match = true; + break; + } + } + if ($match === false) { + return false; + } + } + return true; + } + + /** + * Return a string representation of this Matcher + * + * @return string + */ + public function __toString() + { + $return = '_expected as $v) { + $elements[] = (string) $v; + } + $return .= implode(', ', $elements) . ']>'; + return $return; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/Ducktype.php b/vendor/mockery/mockery/library/Mockery/Matcher/Ducktype.php new file mode 100644 index 00000000..291f4220 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/Ducktype.php @@ -0,0 +1,53 @@ +_expected as $method) { + if (!method_exists($actual, $method)) { + return false; + } + } + return true; + } + + /** + * Return a string representation of this Matcher + * + * @return string + */ + public function __toString() + { + return '_expected) . ']>'; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/HasKey.php b/vendor/mockery/mockery/library/Mockery/Matcher/HasKey.php new file mode 100644 index 00000000..fa983eaf --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/HasKey.php @@ -0,0 +1,45 @@ +_expected, $actual); + } + + /** + * Return a string representation of this Matcher + * + * @return string + */ + public function __toString() + { + return "_expected]>"; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/HasValue.php b/vendor/mockery/mockery/library/Mockery/Matcher/HasValue.php new file mode 100644 index 00000000..8ca6afd1 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/HasValue.php @@ -0,0 +1,46 @@ +_expected, $actual); + } + + /** + * Return a string representation of this Matcher + * + * @return string + */ + public function __toString() + { + $return = '_expected . ']>'; + return $return; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/MatcherAbstract.php b/vendor/mockery/mockery/library/Mockery/Matcher/MatcherAbstract.php new file mode 100644 index 00000000..3233079e --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/MatcherAbstract.php @@ -0,0 +1,58 @@ +_expected = $expected; + } + + /** + * Check if the actual value matches the expected. + * Actual passed by reference to preserve reference trail (where applicable) + * back to the original method parameter. + * + * @param mixed $actual + * @return bool + */ + abstract public function match(&$actual); + + /** + * Return a string representation of this Matcher + * + * @return string + */ + abstract public function __toString(); +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/MultiArgumentClosure.php b/vendor/mockery/mockery/library/Mockery/Matcher/MultiArgumentClosure.php new file mode 100644 index 00000000..63dbff0e --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/MultiArgumentClosure.php @@ -0,0 +1,48 @@ +_expected; + return true === call_user_func_array($closure, $actual); + } + + /** + * Return a string representation of this Matcher + * + * @return string + */ + public function __toString() + { + return ''; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/MustBe.php b/vendor/mockery/mockery/library/Mockery/Matcher/MustBe.php new file mode 100644 index 00000000..27b5ec56 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/MustBe.php @@ -0,0 +1,52 @@ +_expected === $actual; + } + + return $this->_expected == $actual; + } + + /** + * Return a string representation of this Matcher + * + * @return string + */ + public function __toString() + { + return ''; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/NoArgs.php b/vendor/mockery/mockery/library/Mockery/Matcher/NoArgs.php new file mode 100644 index 00000000..5e9e4189 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/NoArgs.php @@ -0,0 +1,40 @@ +'; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/Not.php b/vendor/mockery/mockery/library/Mockery/Matcher/Not.php new file mode 100644 index 00000000..756ccaa5 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/Not.php @@ -0,0 +1,46 @@ +_expected; + } + + /** + * Return a string representation of this Matcher + * + * @return string + */ + public function __toString() + { + return ''; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/NotAnyOf.php b/vendor/mockery/mockery/library/Mockery/Matcher/NotAnyOf.php new file mode 100644 index 00000000..cd827015 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/NotAnyOf.php @@ -0,0 +1,51 @@ +_expected as $exp) { + if ($actual === $exp || $actual == $exp) { + return false; + } + } + return true; + } + + /** + * Return a string representation of this Matcher + * + * @return string + */ + public function __toString() + { + return ''; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/Pattern.php b/vendor/mockery/mockery/library/Mockery/Matcher/Pattern.php new file mode 100644 index 00000000..362c366f --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/Pattern.php @@ -0,0 +1,45 @@ +_expected, (string) $actual) >= 1; + } + + /** + * Return a string representation of this Matcher + * + * @return string + */ + public function __toString() + { + return ''; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/Subset.php b/vendor/mockery/mockery/library/Mockery/Matcher/Subset.php new file mode 100644 index 00000000..5e706c81 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/Subset.php @@ -0,0 +1,92 @@ +expected = $expected; + $this->strict = $strict; + } + + /** + * @param array $expected Expected subset of data + * + * @return Subset + */ + public static function strict(array $expected) + { + return new static($expected, true); + } + + /** + * @param array $expected Expected subset of data + * + * @return Subset + */ + public static function loose(array $expected) + { + return new static($expected, false); + } + + /** + * Check if the actual value matches the expected. + * + * @param mixed $actual + * @return bool + */ + public function match(&$actual) + { + if (!is_array($actual)) { + return false; + } + + if ($this->strict) { + return $actual === array_replace_recursive($actual, $this->expected); + } + + return $actual == array_replace_recursive($actual, $this->expected); + } + + /** + * Return a string representation of this Matcher + * + * @return string + */ + public function __toString() + { + $return = 'expected as $k=>$v) { + $elements[] = $k . '=' . (string) $v; + } + $return .= implode(', ', $elements) . ']>'; + return $return; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Matcher/Type.php b/vendor/mockery/mockery/library/Mockery/Matcher/Type.php new file mode 100644 index 00000000..d81ce834 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Matcher/Type.php @@ -0,0 +1,56 @@ +_expected == 'real') { + $function = 'is_float'; + } else { + $function = 'is_' . strtolower($this->_expected); + } + if (function_exists($function)) { + return $function($actual); + } elseif (is_string($this->_expected) + && (class_exists($this->_expected) || interface_exists($this->_expected))) { + return $actual instanceof $this->_expected; + } + return false; + } + + /** + * Return a string representation of this Matcher + * + * @return string + */ + public function __toString() + { + return '<' . ucfirst($this->_expected) . '>'; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/MethodCall.php b/vendor/mockery/mockery/library/Mockery/MethodCall.php new file mode 100644 index 00000000..db68fd81 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/MethodCall.php @@ -0,0 +1,43 @@ +method = $method; + $this->args = $args; + } + + public function getMethod() + { + return $this->method; + } + + public function getArgs() + { + return $this->args; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Mock.php b/vendor/mockery/mockery/library/Mockery/Mock.php new file mode 100644 index 00000000..c9000838 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Mock.php @@ -0,0 +1,977 @@ +_mockery_container = $container; + if (!is_null($partialObject)) { + $this->_mockery_partial = $partialObject; + } + + if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()) { + foreach ($this->mockery_getMethods() as $method) { + if ($method->isPublic()) { + $this->_mockery_mockableMethods[] = $method->getName(); + } + } + } + + $this->_mockery_instanceMock = $instanceMock; + } + + /** + * Set expected method calls + * + * @param string ...$methodNames one or many methods that are expected to be called in this mock + * + * @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage + */ + public function shouldReceive(...$methodNames) + { + if (count($methodNames) === 0) { + return new HigherOrderMessage($this, "shouldReceive"); + } + + foreach ($methodNames as $method) { + if ("" == $method) { + throw new \InvalidArgumentException("Received empty method name"); + } + } + + $self = $this; + $allowMockingProtectedMethods = $this->_mockery_allowMockingProtectedMethods; + + $lastExpectation = \Mockery::parseShouldReturnArgs( + $this, + $methodNames, + function ($method) use ($self, $allowMockingProtectedMethods) { + $rm = $self->mockery_getMethod($method); + if ($rm) { + if ($rm->isPrivate()) { + throw new \InvalidArgumentException("$method() cannot be mocked as it is a private method"); + } + if (!$allowMockingProtectedMethods && $rm->isProtected()) { + throw new \InvalidArgumentException("$method() cannot be mocked as it is a protected method and mocking protected methods is not enabled for the currently used mock object. Use shouldAllowMockingProtectedMethods() to enable mocking of protected methods."); + } + } + + $director = $self->mockery_getExpectationsFor($method); + if (!$director) { + $director = new \Mockery\ExpectationDirector($method, $self); + $self->mockery_setExpectationsFor($method, $director); + } + $expectation = new \Mockery\Expectation($self, $method); + $director->addExpectation($expectation); + return $expectation; + } + ); + return $lastExpectation; + } + + // start method allows + /** + * @param mixed $something String method name or map of method => return + * @return self|\Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage + */ + public function allows($something = []) + { + if (is_string($something)) { + return $this->shouldReceive($something); + } + + if (empty($something)) { + return $this->shouldReceive(); + } + + foreach ($something as $method => $returnValue) { + $this->shouldReceive($method)->andReturn($returnValue); + } + + return $this; + } + // end method allows + + // start method expects + /** + /** + * @param mixed $something String method name (optional) + * @return \Mockery\ExpectationInterface|\Mockery\Expectation|ExpectsHigherOrderMessage + */ + public function expects($something = null) + { + if (is_string($something)) { + return $this->shouldReceive($something)->once(); + } + + return new ExpectsHigherOrderMessage($this); + } + // end method expects + + /** + * Shortcut method for setting an expectation that a method should not be called. + * + * @param string ...$methodNames one or many methods that are expected not to be called in this mock + * @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage + */ + public function shouldNotReceive(...$methodNames) + { + if (count($methodNames) === 0) { + return new HigherOrderMessage($this, "shouldNotReceive"); + } + + $expectation = call_user_func_array(array($this, 'shouldReceive'), $methodNames); + $expectation->never(); + return $expectation; + } + + /** + * Allows additional methods to be mocked that do not explicitly exist on mocked class + * @param String $method name of the method to be mocked + * @return Mock + */ + public function shouldAllowMockingMethod($method) + { + $this->_mockery_mockableMethods[] = $method; + return $this; + } + + /** + * Set mock to ignore unexpected methods and return Undefined class + * @param mixed $returnValue the default return value for calls to missing functions on this mock + * @param bool $recursive Specify if returned mocks should also have shouldIgnoreMissing set + * @return Mock + */ + public function shouldIgnoreMissing($returnValue = null, $recursive = false) + { + $this->_mockery_ignoreMissing = true; + $this->_mockery_ignoreMissingRecursive = $recursive; + $this->_mockery_defaultReturnValue = $returnValue; + return $this; + } + + public function asUndefined() + { + $this->_mockery_ignoreMissing = true; + $this->_mockery_defaultReturnValue = new \Mockery\Undefined(); + return $this; + } + + /** + * @return Mock + */ + public function shouldAllowMockingProtectedMethods() + { + if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()) { + foreach ($this->mockery_getMethods() as $method) { + if ($method->isProtected()) { + $this->_mockery_mockableMethods[] = $method->getName(); + } + } + } + + $this->_mockery_allowMockingProtectedMethods = true; + return $this; + } + + + /** + * Set mock to defer unexpected methods to it's parent + * + * This is particularly useless for this class, as it doesn't have a parent, + * but included for completeness + * + * @deprecated 2.0.0 Please use makePartial() instead + * + * @return Mock + */ + public function shouldDeferMissing() + { + return $this->makePartial(); + } + + /** + * Set mock to defer unexpected methods to it's parent + * + * It was an alias for shouldDeferMissing(), which will be removed + * in 2.0.0. + * + * @return Mock + */ + public function makePartial() + { + $this->_mockery_deferMissing = true; + return $this; + } + + /** + * In the event shouldReceive() accepting one or more methods/returns, + * this method will switch them from normal expectations to default + * expectations + * + * @return self + */ + public function byDefault() + { + foreach ($this->_mockery_expectations as $director) { + $exps = $director->getExpectations(); + foreach ($exps as $exp) { + $exp->byDefault(); + } + } + return $this; + } + + /** + * Capture calls to this mock + */ + public function __call($method, array $args) + { + return $this->_mockery_handleMethodCall($method, $args); + } + + public static function __callStatic($method, array $args) + { + return self::_mockery_handleStaticMethodCall($method, $args); + } + + /** + * Forward calls to this magic method to the __call method + */ + public function __toString() + { + return $this->__call('__toString', array()); + } + + /** + * Iterate across all expectation directors and validate each + * + * @throws \Mockery\CountValidator\Exception + * @return void + */ + public function mockery_verify() + { + if ($this->_mockery_verified) { + return; + } + if (isset($this->_mockery_ignoreVerification) + && $this->_mockery_ignoreVerification == true) { + return; + } + $this->_mockery_verified = true; + foreach ($this->_mockery_expectations as $director) { + $director->verify(); + } + } + + /** + * Gets a list of exceptions thrown by this mock + * + * @return array + */ + public function mockery_thrownExceptions() + { + return $this->_mockery_thrownExceptions; + } + + /** + * Tear down tasks for this mock + * + * @return void + */ + public function mockery_teardown() + { + } + + /** + * Fetch the next available allocation order number + * + * @return int + */ + public function mockery_allocateOrder() + { + $this->_mockery_allocatedOrder += 1; + return $this->_mockery_allocatedOrder; + } + + /** + * Set ordering for a group + * + * @param mixed $group + * @param int $order + */ + public function mockery_setGroup($group, $order) + { + $this->_mockery_groups[$group] = $order; + } + + /** + * Fetch array of ordered groups + * + * @return array + */ + public function mockery_getGroups() + { + return $this->_mockery_groups; + } + + /** + * Set current ordered number + * + * @param int $order + */ + public function mockery_setCurrentOrder($order) + { + $this->_mockery_currentOrder = $order; + return $this->_mockery_currentOrder; + } + + /** + * Get current ordered number + * + * @return int + */ + public function mockery_getCurrentOrder() + { + return $this->_mockery_currentOrder; + } + + /** + * Validate the current mock's ordering + * + * @param string $method + * @param int $order + * @throws \Mockery\Exception + * @return void + */ + public function mockery_validateOrder($method, $order) + { + if ($order < $this->_mockery_currentOrder) { + $exception = new \Mockery\Exception\InvalidOrderException( + 'Method ' . __CLASS__ . '::' . $method . '()' + . ' called out of order: expected order ' + . $order . ', was ' . $this->_mockery_currentOrder + ); + $exception->setMock($this) + ->setMethodName($method) + ->setExpectedOrder($order) + ->setActualOrder($this->_mockery_currentOrder); + throw $exception; + } + $this->mockery_setCurrentOrder($order); + } + + /** + * Gets the count of expectations for this mock + * + * @return int + */ + public function mockery_getExpectationCount() + { + $count = $this->_mockery_expectations_count; + foreach ($this->_mockery_expectations as $director) { + $count += $director->getExpectationCount(); + } + return $count; + } + + /** + * Return the expectations director for the given method + * + * @var string $method + * @return \Mockery\ExpectationDirector|null + */ + public function mockery_setExpectationsFor($method, \Mockery\ExpectationDirector $director) + { + $this->_mockery_expectations[$method] = $director; + } + + /** + * Return the expectations director for the given method + * + * @var string $method + * @return \Mockery\ExpectationDirector|null + */ + public function mockery_getExpectationsFor($method) + { + if (isset($this->_mockery_expectations[$method])) { + return $this->_mockery_expectations[$method]; + } + } + + /** + * Find an expectation matching the given method and arguments + * + * @var string $method + * @var array $args + * @return \Mockery\Expectation|null + */ + public function mockery_findExpectation($method, array $args) + { + if (!isset($this->_mockery_expectations[$method])) { + return null; + } + $director = $this->_mockery_expectations[$method]; + + return $director->findExpectation($args); + } + + /** + * Return the container for this mock + * + * @return \Mockery\Container + */ + public function mockery_getContainer() + { + return $this->_mockery_container; + } + + /** + * Return the name for this mock + * + * @return string + */ + public function mockery_getName() + { + return __CLASS__; + } + + /** + * @return array + */ + public function mockery_getMockableProperties() + { + return $this->_mockery_mockableProperties; + } + + public function __isset($name) + { + if (false === stripos($name, '_mockery_') && get_parent_class($this) && method_exists(get_parent_class($this), '__isset')) { + return call_user_func(get_parent_class($this) . '::__isset', $name); + } + + return false; + } + + public function mockery_getExpectations() + { + return $this->_mockery_expectations; + } + + /** + * Calls a parent class method and returns the result. Used in a passthru + * expectation where a real return value is required while still taking + * advantage of expectation matching and call count verification. + * + * @param string $name + * @param array $args + * @return mixed + */ + public function mockery_callSubjectMethod($name, array $args) + { + if (!method_exists($this, $name) && get_parent_class($this) && method_exists(get_parent_class($this), '__call')) { + return call_user_func(get_parent_class($this) . '::__call', $name, $args); + } + return call_user_func_array(get_parent_class($this) . '::' . $name, $args); + } + + /** + * @return string[] + */ + public function mockery_getMockableMethods() + { + return $this->_mockery_mockableMethods; + } + + /** + * @return bool + */ + public function mockery_isAnonymous() + { + $rfc = new \ReflectionClass($this); + + // PHP 8 has Stringable interface + $interfaces = array_filter($rfc->getInterfaces(), function ($i) { + return $i->getName() !== 'Stringable'; + }); + + return false === $rfc->getParentClass() && 2 === count($interfaces); + } + + public function mockery_isInstance() + { + return $this->_mockery_instanceMock; + } + + public function __wakeup() + { + /** + * This does not add __wakeup method support. It's a blind method and any + * expected __wakeup work will NOT be performed. It merely cuts off + * annoying errors where a __wakeup exists but is not essential when + * mocking + */ + } + + public function __destruct() + { + /** + * Overrides real class destructor in case if class was created without original constructor + */ + } + + public function mockery_getMethod($name) + { + foreach ($this->mockery_getMethods() as $method) { + if ($method->getName() == $name) { + return $method; + } + } + + return null; + } + + /** + * @param string $name Method name. + * + * @return mixed Generated return value based on the declared return value of the named method. + */ + public function mockery_returnValueForMethod($name) + { + $rm = $this->mockery_getMethod($name); + + if ($rm === null) { + return null; + } + + $returnType = Reflector::getSimplestReturnType($rm); + + switch ($returnType) { + case null: return null; + case 'string': return ''; + case 'int': return 0; + case 'float': return 0.0; + case 'bool': return false; + + case 'array': + case 'iterable': + return []; + + case 'callable': + case '\Closure': + return function () { + }; + + case '\Traversable': + case '\Generator': + $generator = function () { yield; }; + return $generator(); + + case 'void': + return null; + + case 'static': + return $this; + + case 'object': + $mock = \Mockery::mock(); + if ($this->_mockery_ignoreMissingRecursive) { + $mock->shouldIgnoreMissing($this->_mockery_defaultReturnValue, true); + } + return $mock; + + default: + $mock = \Mockery::mock($returnType); + if ($this->_mockery_ignoreMissingRecursive) { + $mock->shouldIgnoreMissing($this->_mockery_defaultReturnValue, true); + } + return $mock; + } + } + + public function shouldHaveReceived($method = null, $args = null) + { + if ($method === null) { + return new HigherOrderMessage($this, "shouldHaveReceived"); + } + + $expectation = new \Mockery\VerificationExpectation($this, $method); + if (null !== $args) { + $expectation->withArgs($args); + } + $expectation->atLeast()->once(); + $director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation); + $this->_mockery_expectations_count++; + $director->verify(); + return $director; + } + + public function shouldHaveBeenCalled() + { + return $this->shouldHaveReceived("__invoke"); + } + + public function shouldNotHaveReceived($method = null, $args = null) + { + if ($method === null) { + return new HigherOrderMessage($this, "shouldNotHaveReceived"); + } + + $expectation = new \Mockery\VerificationExpectation($this, $method); + if (null !== $args) { + $expectation->withArgs($args); + } + $expectation->never(); + $director = new \Mockery\VerificationDirector($this->_mockery_getReceivedMethodCalls(), $expectation); + $this->_mockery_expectations_count++; + $director->verify(); + return null; + } + + public function shouldNotHaveBeenCalled(array $args = null) + { + return $this->shouldNotHaveReceived("__invoke", $args); + } + + protected static function _mockery_handleStaticMethodCall($method, array $args) + { + $associatedRealObject = \Mockery::fetchMock(__CLASS__); + try { + return $associatedRealObject->__call($method, $args); + } catch (BadMethodCallException $e) { + throw new BadMethodCallException( + 'Static method ' . $associatedRealObject->mockery_getName() . '::' . $method + . '() does not exist on this mock object', + 0, + $e + ); + } + } + + protected function _mockery_getReceivedMethodCalls() + { + return $this->_mockery_receivedMethodCalls ?: $this->_mockery_receivedMethodCalls = new \Mockery\ReceivedMethodCalls(); + } + + /** + * Called when an instance Mock was created and its constructor is getting called + * + * @see \Mockery\Generator\StringManipulation\Pass\InstanceMockPass + * @param array $args + */ + protected function _mockery_constructorCalled(array $args) + { + if (!isset($this->_mockery_expectations['__construct']) /* _mockery_handleMethodCall runs the other checks */) { + return; + } + $this->_mockery_handleMethodCall('__construct', $args); + } + + protected function _mockery_findExpectedMethodHandler($method) + { + if (isset($this->_mockery_expectations[$method])) { + return $this->_mockery_expectations[$method]; + } + + $lowerCasedMockeryExpectations = array_change_key_case($this->_mockery_expectations, CASE_LOWER); + $lowerCasedMethod = strtolower($method); + + if (isset($lowerCasedMockeryExpectations[$lowerCasedMethod])) { + return $lowerCasedMockeryExpectations[$lowerCasedMethod]; + } + + return null; + } + + protected function _mockery_handleMethodCall($method, array $args) + { + $this->_mockery_getReceivedMethodCalls()->push(new \Mockery\MethodCall($method, $args)); + + $rm = $this->mockery_getMethod($method); + if ($rm && $rm->isProtected() && !$this->_mockery_allowMockingProtectedMethods) { + if ($rm->isAbstract()) { + return; + } + + try { + $prototype = $rm->getPrototype(); + if ($prototype->isAbstract()) { + return; + } + } catch (\ReflectionException $re) { + // noop - there is no hasPrototype method + } + + return call_user_func_array(get_parent_class($this) . '::' . $method, $args); + } + + $handler = $this->_mockery_findExpectedMethodHandler($method); + + if ($handler !== null && !$this->_mockery_disableExpectationMatching) { + try { + return $handler->call($args); + } catch (\Mockery\Exception\NoMatchingExpectationException $e) { + if (!$this->_mockery_ignoreMissing && !$this->_mockery_deferMissing) { + throw $e; + } + } + } + + if (!is_null($this->_mockery_partial) && + (method_exists($this->_mockery_partial, $method) || method_exists($this->_mockery_partial, '__call')) + ) { + return call_user_func_array(array($this->_mockery_partial, $method), $args); + } elseif ($this->_mockery_deferMissing && is_callable(get_parent_class($this) . '::' . $method) + && (!$this->hasMethodOverloadingInParentClass() || (get_parent_class($this) && method_exists(get_parent_class($this), $method)))) { + return call_user_func_array(get_parent_class($this) . '::' . $method, $args); + } elseif ($this->_mockery_deferMissing && get_parent_class($this) && method_exists(get_parent_class($this), '__call')) { + return call_user_func(get_parent_class($this) . '::__call', $method, $args); + } elseif ($method == '__toString') { + // __toString is special because we force its addition to the class API regardless of the + // original implementation. Thus, we should always return a string rather than honor + // _mockery_ignoreMissing and break the API with an error. + return sprintf("%s#%s", __CLASS__, spl_object_hash($this)); + } elseif ($this->_mockery_ignoreMissing) { + if (\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() || (!is_null($this->_mockery_partial) && method_exists($this->_mockery_partial, $method)) || is_callable(get_parent_class($this) . '::' . $method)) { + if ($this->_mockery_defaultReturnValue instanceof \Mockery\Undefined) { + return call_user_func_array(array($this->_mockery_defaultReturnValue, $method), $args); + } elseif (null === $this->_mockery_defaultReturnValue) { + return $this->mockery_returnValueForMethod($method); + } + + return $this->_mockery_defaultReturnValue; + } + } + + $message = 'Method ' . __CLASS__ . '::' . $method . + '() does not exist on this mock object'; + + if (!is_null($rm)) { + $message = 'Received ' . __CLASS__ . + '::' . $method . '(), but no expectations were specified'; + } + + $bmce = new BadMethodCallException($message); + $this->_mockery_thrownExceptions[] = $bmce; + throw $bmce; + } + + /** + * Uses reflection to get the list of all + * methods within the current mock object + * + * @return array + */ + protected function mockery_getMethods() + { + if (static::$_mockery_methods && \Mockery::getConfiguration()->reflectionCacheEnabled()) { + return static::$_mockery_methods; + } + + if (isset($this->_mockery_partial)) { + $reflected = new \ReflectionObject($this->_mockery_partial); + } else { + $reflected = new \ReflectionClass($this); + } + + return static::$_mockery_methods = $reflected->getMethods(); + } + + private function hasMethodOverloadingInParentClass() + { + // if there's __call any name would be callable + return is_callable(get_parent_class($this) . '::aFunctionNameThatNoOneWouldEverUseInRealLife12345'); + } + + /** + * @return array + */ + private function getNonPublicMethods() + { + return array_map( + function ($method) { + return $method->getName(); + }, + array_filter($this->mockery_getMethods(), function ($method) { + return !$method->isPublic(); + }) + ); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/MockInterface.php b/vendor/mockery/mockery/library/Mockery/MockInterface.php new file mode 100644 index 00000000..7c1774b4 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/MockInterface.php @@ -0,0 +1,38 @@ + return + * @return self|\Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\HigherOrderMessage + */ + public function allows($something = []); + + /** + * @param mixed $something String method name (optional) + * @return \Mockery\ExpectationInterface|\Mockery\Expectation|\Mockery\ExpectsHigherOrderMessage + */ + public function expects($something = null); +} diff --git a/vendor/mockery/mockery/library/Mockery/QuickDefinitionsConfiguration.php b/vendor/mockery/mockery/library/Mockery/QuickDefinitionsConfiguration.php new file mode 100644 index 00000000..b0eea662 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/QuickDefinitionsConfiguration.php @@ -0,0 +1,56 @@ +_quickDefinitionsApplicationMode = $newValue + ? self::QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE + : self::QUICK_DEFINITIONS_MODE_DEFAULT_EXPECTATION; + } + + return $this->_quickDefinitionsApplicationMode === self::QUICK_DEFINITIONS_MODE_MOCK_AT_LEAST_ONCE; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/ReceivedMethodCalls.php b/vendor/mockery/mockery/library/Mockery/ReceivedMethodCalls.php new file mode 100644 index 00000000..8ed81f10 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/ReceivedMethodCalls.php @@ -0,0 +1,48 @@ +methodCalls[] = $methodCall; + } + + public function verify(Expectation $expectation) + { + foreach ($this->methodCalls as $methodCall) { + if ($methodCall->getMethod() !== $expectation->getName()) { + continue; + } + + if (!$expectation->matchArgs($methodCall->getArgs())) { + continue; + } + + $expectation->verifyCall($methodCall->getArgs()); + } + + $expectation->verify(); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Reflector.php b/vendor/mockery/mockery/library/Mockery/Reflector.php new file mode 100644 index 00000000..4e8c6e1f --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Reflector.php @@ -0,0 +1,224 @@ +getType(); + + return $type instanceof \ReflectionNamedType && $type->getName(); + } + + /** + * Compute the string representation for the paramater type. + * + * @param \ReflectionParameter $param + * @param bool $withoutNullable + * + * @return string|null + */ + public static function getTypeHint(\ReflectionParameter $param, $withoutNullable = false) + { + if (!$param->hasType()) { + return null; + } + + $type = $param->getType(); + $declaringClass = $param->getDeclaringClass(); + $typeHint = self::typeToString($type, $declaringClass); + + return (!$withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint; + } + + /** + * Compute the string representation for the return type. + * + * @param \ReflectionParameter $param + * @param bool $withoutNullable + * + * @return string|null + */ + public static function getReturnType(\ReflectionMethod $method, $withoutNullable = false) + { + $type = $method->getReturnType(); + + if (is_null($type) && method_exists($method, 'getTentativeReturnType')) { + $type = $method->getTentativeReturnType(); + } + + if (is_null($type)) { + return null; + } + + $typeHint = self::typeToString($type, $method->getDeclaringClass()); + + return (!$withoutNullable && $type->allowsNull()) ? self::formatNullableType($typeHint) : $typeHint; + } + + /** + * Compute the string representation for the simplest return type. + * + * @param \ReflectionParameter $param + * + * @return string|null + */ + public static function getSimplestReturnType(\ReflectionMethod $method) + { + $type = $method->getReturnType(); + + if (is_null($type) && method_exists($method, 'getTentativeReturnType')) { + $type = $method->getTentativeReturnType(); + } + + if (is_null($type) || $type->allowsNull()) { + return null; + } + + $typeInformation = self::getTypeInformation($type, $method->getDeclaringClass()); + + // return the first primitive type hint + foreach ($typeInformation as $info) { + if ($info['isPrimitive']) { + return $info['typeHint']; + } + } + + // if no primitive type, return the first type + foreach ($typeInformation as $info) { + return $info['typeHint']; + } + + return null; + } + + /** + * Get the string representation of the given type. + * + * @param \ReflectionType $type + * @param string $declaringClass + * + * @return string|null + */ + private static function typeToString(\ReflectionType $type, \ReflectionClass $declaringClass) + { + return \implode('|', \array_map(function (array $typeInformation) { + return $typeInformation['typeHint']; + }, self::getTypeInformation($type, $declaringClass))); + } + + /** + * Get the string representation of the given type. + * + * @param \ReflectionType $type + * @param \ReflectionClass $declaringClass + * + * @return list + */ + private static function getTypeInformation(\ReflectionType $type, \ReflectionClass $declaringClass) + { + // PHP 8 union types and PHP 8.1 intersection types can be recursively processed + if ($type instanceof \ReflectionUnionType || $type instanceof \ReflectionIntersectionType) { + $types = []; + + foreach ($type->getTypes() as $innterType) { + foreach (self::getTypeInformation($innterType, $declaringClass) as $info) { + if ($info['typeHint'] === 'null' && $info['isPrimitive']) { + continue; + } + + $types[] = $info; + } + } + + return $types; + } + + // $type must be an instance of \ReflectionNamedType + $typeHint = $type->getName(); + + // builtins can be returned as is + if ($type->isBuiltin()) { + return [ + [ + 'typeHint' => $typeHint, + 'isPrimitive' => in_array($typeHint, ['array', 'bool', 'int', 'float', 'null', 'object', 'string']), + ], + ]; + } + + // 'static' can be returned as is + if ($typeHint === 'static') { + return [ + [ + 'typeHint' => $typeHint, + 'isPrimitive' => false, + ], + ]; + } + + // 'self' needs to be resolved to the name of the declaring class + if ($typeHint === 'self') { + $typeHint = $declaringClass->getName(); + } + + // 'parent' needs to be resolved to the name of the parent class + if ($typeHint === 'parent') { + $typeHint = $declaringClass->getParentClass()->getName(); + } + + // class names need prefixing with a slash + return [ + [ + 'typeHint' => sprintf('\\%s', $typeHint), + 'isPrimitive' => false, + ], + ]; + } + + /** + * Format the given type as a nullable type. + * + * @param string $typeHint + * + * @return string + */ + private static function formatNullableType($typeHint) + { + if (\PHP_VERSION_ID < 80000) { + return sprintf('?%s', $typeHint); + } + + return $typeHint === 'mixed' ? 'mixed' : sprintf('%s|null', $typeHint); + } +} diff --git a/vendor/mockery/mockery/library/Mockery/Undefined.php b/vendor/mockery/mockery/library/Mockery/Undefined.php new file mode 100644 index 00000000..53b05e9c --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/Undefined.php @@ -0,0 +1,46 @@ +receivedMethodCalls = $receivedMethodCalls; + $this->expectation = $expectation; + } + + public function verify() + { + return $this->receivedMethodCalls->verify($this->expectation); + } + + public function with(...$args) + { + return $this->cloneApplyAndVerify("with", $args); + } + + public function withArgs($args) + { + return $this->cloneApplyAndVerify("withArgs", array($args)); + } + + public function withNoArgs() + { + return $this->cloneApplyAndVerify("withNoArgs", array()); + } + + public function withAnyArgs() + { + return $this->cloneApplyAndVerify("withAnyArgs", array()); + } + + public function times($limit = null) + { + return $this->cloneWithoutCountValidatorsApplyAndVerify("times", array($limit)); + } + + public function once() + { + return $this->cloneWithoutCountValidatorsApplyAndVerify("once", array()); + } + + public function twice() + { + return $this->cloneWithoutCountValidatorsApplyAndVerify("twice", array()); + } + + public function atLeast() + { + return $this->cloneWithoutCountValidatorsApplyAndVerify("atLeast", array()); + } + + public function atMost() + { + return $this->cloneWithoutCountValidatorsApplyAndVerify("atMost", array()); + } + + public function between($minimum, $maximum) + { + return $this->cloneWithoutCountValidatorsApplyAndVerify("between", array($minimum, $maximum)); + } + + protected function cloneWithoutCountValidatorsApplyAndVerify($method, $args) + { + $expectation = clone $this->expectation; + $expectation->clearCountValidators(); + call_user_func_array(array($expectation, $method), $args); + $director = new VerificationDirector($this->receivedMethodCalls, $expectation); + $director->verify(); + return $director; + } + + protected function cloneApplyAndVerify($method, $args) + { + $expectation = clone $this->expectation; + call_user_func_array(array($expectation, $method), $args); + $director = new VerificationDirector($this->receivedMethodCalls, $expectation); + $director->verify(); + return $director; + } +} diff --git a/vendor/mockery/mockery/library/Mockery/VerificationExpectation.php b/vendor/mockery/mockery/library/Mockery/VerificationExpectation.php new file mode 100644 index 00000000..3844a090 --- /dev/null +++ b/vendor/mockery/mockery/library/Mockery/VerificationExpectation.php @@ -0,0 +1,35 @@ +_countValidators = array(); + } + + public function __clone() + { + parent::__clone(); + $this->_actualCount = 0; + } +} diff --git a/vendor/mockery/mockery/library/helpers.php b/vendor/mockery/mockery/library/helpers.php new file mode 100644 index 00000000..0756a328 --- /dev/null +++ b/vendor/mockery/mockery/library/helpers.php @@ -0,0 +1,65 @@ +copy($myObject); +``` + + +## Why? + +- How do you create copies of your objects? + +```php +$myCopy = clone $myObject; +``` + +- How do you create **deep** copies of your objects (i.e. copying also all the objects referenced in the properties)? + +You use [`__clone()`](http://www.php.net/manual/en/language.oop5.cloning.php#object.clone) and implement the behavior +yourself. + +- But how do you handle **cycles** in the association graph? + +Now you're in for a big mess :( + +![association graph](doc/graph.png) + + +### Using simply `clone` + +![Using clone](doc/clone.png) + + +### Overriding `__clone()` + +![Overriding __clone](doc/deep-clone.png) + + +### With `DeepCopy` + +![With DeepCopy](doc/deep-copy.png) + + +## How it works + +DeepCopy recursively traverses all the object's properties and clones them. To avoid cloning the same object twice it +keeps a hash map of all instances and thus preserves the object graph. + +To use it: + +```php +use function DeepCopy\deep_copy; + +$copy = deep_copy($var); +``` + +Alternatively, you can create your own `DeepCopy` instance to configure it differently for example: + +```php +use DeepCopy\DeepCopy; + +$copier = new DeepCopy(true); + +$copy = $copier->copy($var); +``` + +You may want to roll your own deep copy function: + +```php +namespace Acme; + +use DeepCopy\DeepCopy; + +function deep_copy($var) +{ + static $copier = null; + + if (null === $copier) { + $copier = new DeepCopy(true); + } + + return $copier->copy($var); +} +``` + + +## Going further + +You can add filters to customize the copy process. + +The method to add a filter is `DeepCopy\DeepCopy::addFilter($filter, $matcher)`, +with `$filter` implementing `DeepCopy\Filter\Filter` +and `$matcher` implementing `DeepCopy\Matcher\Matcher`. + +We provide some generic filters and matchers. + + +### Matchers + + - `DeepCopy\Matcher` applies on a object attribute. + - `DeepCopy\TypeMatcher` applies on any element found in graph, including array elements. + + +#### Property name + +The `PropertyNameMatcher` will match a property by its name: + +```php +use DeepCopy\Matcher\PropertyNameMatcher; + +// Will apply a filter to any property of any objects named "id" +$matcher = new PropertyNameMatcher('id'); +``` + + +#### Specific property + +The `PropertyMatcher` will match a specific property of a specific class: + +```php +use DeepCopy\Matcher\PropertyMatcher; + +// Will apply a filter to the property "id" of any objects of the class "MyClass" +$matcher = new PropertyMatcher('MyClass', 'id'); +``` + + +#### Type + +The `TypeMatcher` will match any element by its type (instance of a class or any value that could be parameter of +[gettype()](http://php.net/manual/en/function.gettype.php) function): + +```php +use DeepCopy\TypeMatcher\TypeMatcher; + +// Will apply a filter to any object that is an instance of Doctrine\Common\Collections\Collection +$matcher = new TypeMatcher('Doctrine\Common\Collections\Collection'); +``` + + +### Filters + +- `DeepCopy\Filter` applies a transformation to the object attribute matched by `DeepCopy\Matcher` +- `DeepCopy\TypeFilter` applies a transformation to any element matched by `DeepCopy\TypeMatcher` + + +#### `SetNullFilter` (filter) + +Let's say for example that you are copying a database record (or a Doctrine entity), so you want the copy not to have +any ID: + +```php +use DeepCopy\DeepCopy; +use DeepCopy\Filter\SetNullFilter; +use DeepCopy\Matcher\PropertyNameMatcher; + +$object = MyClass::load(123); +echo $object->id; // 123 + +$copier = new DeepCopy(); +$copier->addFilter(new SetNullFilter(), new PropertyNameMatcher('id')); + +$copy = $copier->copy($object); + +echo $copy->id; // null +``` + + +#### `KeepFilter` (filter) + +If you want a property to remain untouched (for example, an association to an object): + +```php +use DeepCopy\DeepCopy; +use DeepCopy\Filter\KeepFilter; +use DeepCopy\Matcher\PropertyMatcher; + +$copier = new DeepCopy(); +$copier->addFilter(new KeepFilter(), new PropertyMatcher('MyClass', 'category')); + +$copy = $copier->copy($object); +// $copy->category has not been touched +``` + + +#### `DoctrineCollectionFilter` (filter) + +If you use Doctrine and want to copy an entity, you will need to use the `DoctrineCollectionFilter`: + +```php +use DeepCopy\DeepCopy; +use DeepCopy\Filter\Doctrine\DoctrineCollectionFilter; +use DeepCopy\Matcher\PropertyTypeMatcher; + +$copier = new DeepCopy(); +$copier->addFilter(new DoctrineCollectionFilter(), new PropertyTypeMatcher('Doctrine\Common\Collections\Collection')); + +$copy = $copier->copy($object); +``` + + +#### `DoctrineEmptyCollectionFilter` (filter) + +If you use Doctrine and want to copy an entity who contains a `Collection` that you want to be reset, you can use the +`DoctrineEmptyCollectionFilter` + +```php +use DeepCopy\DeepCopy; +use DeepCopy\Filter\Doctrine\DoctrineEmptyCollectionFilter; +use DeepCopy\Matcher\PropertyMatcher; + +$copier = new DeepCopy(); +$copier->addFilter(new DoctrineEmptyCollectionFilter(), new PropertyMatcher('MyClass', 'myProperty')); + +$copy = $copier->copy($object); + +// $copy->myProperty will return an empty collection +``` + + +#### `DoctrineProxyFilter` (filter) + +If you use Doctrine and use cloning on lazy loaded entities, you might encounter errors mentioning missing fields on a +Doctrine proxy class (...\\\_\_CG\_\_\Proxy). +You can use the `DoctrineProxyFilter` to load the actual entity behind the Doctrine proxy class. +**Make sure, though, to put this as one of your very first filters in the filter chain so that the entity is loaded +before other filters are applied!** + +```php +use DeepCopy\DeepCopy; +use DeepCopy\Filter\Doctrine\DoctrineProxyFilter; +use DeepCopy\Matcher\Doctrine\DoctrineProxyMatcher; + +$copier = new DeepCopy(); +$copier->addFilter(new DoctrineProxyFilter(), new DoctrineProxyMatcher()); + +$copy = $copier->copy($object); + +// $copy should now contain a clone of all entities, including those that were not yet fully loaded. +``` + + +#### `ReplaceFilter` (type filter) + +1. If you want to replace the value of a property: + +```php +use DeepCopy\DeepCopy; +use DeepCopy\Filter\ReplaceFilter; +use DeepCopy\Matcher\PropertyMatcher; + +$copier = new DeepCopy(); +$callback = function ($currentValue) { + return $currentValue . ' (copy)' +}; +$copier->addFilter(new ReplaceFilter($callback), new PropertyMatcher('MyClass', 'title')); + +$copy = $copier->copy($object); + +// $copy->title will contain the data returned by the callback, e.g. 'The title (copy)' +``` + +2. If you want to replace whole element: + +```php +use DeepCopy\DeepCopy; +use DeepCopy\TypeFilter\ReplaceFilter; +use DeepCopy\TypeMatcher\TypeMatcher; + +$copier = new DeepCopy(); +$callback = function (MyClass $myClass) { + return get_class($myClass); +}; +$copier->addTypeFilter(new ReplaceFilter($callback), new TypeMatcher('MyClass')); + +$copy = $copier->copy([new MyClass, 'some string', new MyClass]); + +// $copy will contain ['MyClass', 'some string', 'MyClass'] +``` + + +The `$callback` parameter of the `ReplaceFilter` constructor accepts any PHP callable. + + +#### `ShallowCopyFilter` (type filter) + +Stop *DeepCopy* from recursively copying element, using standard `clone` instead: + +```php +use DeepCopy\DeepCopy; +use DeepCopy\TypeFilter\ShallowCopyFilter; +use DeepCopy\TypeMatcher\TypeMatcher; +use Mockery as m; + +$this->deepCopy = new DeepCopy(); +$this->deepCopy->addTypeFilter( + new ShallowCopyFilter, + new TypeMatcher(m\MockInterface::class) +); + +$myServiceWithMocks = new MyService(m::mock(MyDependency1::class), m::mock(MyDependency2::class)); +// All mocks will be just cloned, not deep copied +``` + + +## Edge cases + +The following structures cannot be deep-copied with PHP Reflection. As a result they are shallow cloned and filters are +not applied. There is two ways for you to handle them: + +- Implement your own `__clone()` method +- Use a filter with a type matcher + + +## Contributing + +DeepCopy is distributed under the MIT license. + + +### Tests + +Running the tests is simple: + +```php +vendor/bin/phpunit +``` + +### Support + +Get professional support via [the Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-myclabs-deep-copy?utm_source=packagist-myclabs-deep-copy&utm_medium=referral&utm_campaign=readme). diff --git a/vendor/myclabs/deep-copy/composer.json b/vendor/myclabs/deep-copy/composer.json new file mode 100644 index 00000000..66fb34a5 --- /dev/null +++ b/vendor/myclabs/deep-copy/composer.json @@ -0,0 +1,42 @@ +{ + "name": "myclabs/deep-copy", + "description": "Create deep copies (clones) of your objects", + "license": "MIT", + "type": "library", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "autoload-dev": { + "psr-4": { + "DeepCopy\\": "fixtures/", + "DeepCopyTest\\": "tests/DeepCopyTest/" + } + }, + "config": { + "sort-packages": true + } +} diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php b/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php new file mode 100644 index 00000000..5e68c64e --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php @@ -0,0 +1,303 @@ + Filter, 'matcher' => Matcher] pairs. + */ + private $filters = []; + + /** + * Type Filters to apply. + * + * @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs. + */ + private $typeFilters = []; + + /** + * @var bool + */ + private $skipUncloneable = false; + + /** + * @var bool + */ + private $useCloneMethod; + + /** + * @param bool $useCloneMethod If set to true, when an object implements the __clone() function, it will be used + * instead of the regular deep cloning. + */ + public function __construct($useCloneMethod = false) + { + $this->useCloneMethod = $useCloneMethod; + + $this->addTypeFilter(new ArrayObjectFilter($this), new TypeMatcher(ArrayObject::class)); + $this->addTypeFilter(new DateIntervalFilter(), new TypeMatcher(DateInterval::class)); + $this->addTypeFilter(new SplDoublyLinkedListFilter($this), new TypeMatcher(SplDoublyLinkedList::class)); + } + + /** + * If enabled, will not throw an exception when coming across an uncloneable property. + * + * @param $skipUncloneable + * + * @return $this + */ + public function skipUncloneable($skipUncloneable = true) + { + $this->skipUncloneable = $skipUncloneable; + + return $this; + } + + /** + * Deep copies the given object. + * + * @param mixed $object + * + * @return mixed + */ + public function copy($object) + { + $this->hashMap = []; + + return $this->recursiveCopy($object); + } + + public function addFilter(Filter $filter, Matcher $matcher) + { + $this->filters[] = [ + 'matcher' => $matcher, + 'filter' => $filter, + ]; + } + + public function prependFilter(Filter $filter, Matcher $matcher) + { + array_unshift($this->filters, [ + 'matcher' => $matcher, + 'filter' => $filter, + ]); + } + + public function addTypeFilter(TypeFilter $filter, TypeMatcher $matcher) + { + $this->typeFilters[] = [ + 'matcher' => $matcher, + 'filter' => $filter, + ]; + } + + private function recursiveCopy($var) + { + // Matches Type Filter + if ($filter = $this->getFirstMatchedTypeFilter($this->typeFilters, $var)) { + return $filter->apply($var); + } + + // Resource + if (is_resource($var)) { + return $var; + } + + // Array + if (is_array($var)) { + return $this->copyArray($var); + } + + // Scalar + if (! is_object($var)) { + return $var; + } + + // Enum + if (PHP_VERSION_ID >= 80100 && enum_exists(get_class($var))) { + return $var; + } + + // Object + return $this->copyObject($var); + } + + /** + * Copy an array + * @param array $array + * @return array + */ + private function copyArray(array $array) + { + foreach ($array as $key => $value) { + $array[$key] = $this->recursiveCopy($value); + } + + return $array; + } + + /** + * Copies an object. + * + * @param object $object + * + * @throws CloneException + * + * @return object + */ + private function copyObject($object) + { + $objectHash = spl_object_hash($object); + + if (isset($this->hashMap[$objectHash])) { + return $this->hashMap[$objectHash]; + } + + $reflectedObject = new ReflectionObject($object); + $isCloneable = $reflectedObject->isCloneable(); + + if (false === $isCloneable) { + if ($this->skipUncloneable) { + $this->hashMap[$objectHash] = $object; + + return $object; + } + + throw new CloneException( + sprintf( + 'The class "%s" is not cloneable.', + $reflectedObject->getName() + ) + ); + } + + $newObject = clone $object; + $this->hashMap[$objectHash] = $newObject; + + if ($this->useCloneMethod && $reflectedObject->hasMethod('__clone')) { + return $newObject; + } + + if ($newObject instanceof DateTimeInterface || $newObject instanceof DateTimeZone) { + return $newObject; + } + + foreach (ReflectionHelper::getProperties($reflectedObject) as $property) { + $this->copyObjectProperty($newObject, $property); + } + + return $newObject; + } + + private function copyObjectProperty($object, ReflectionProperty $property) + { + // Ignore static properties + if ($property->isStatic()) { + return; + } + + // Apply the filters + foreach ($this->filters as $item) { + /** @var Matcher $matcher */ + $matcher = $item['matcher']; + /** @var Filter $filter */ + $filter = $item['filter']; + + if ($matcher->matches($object, $property->getName())) { + $filter->apply( + $object, + $property->getName(), + function ($object) { + return $this->recursiveCopy($object); + } + ); + + // If a filter matches, we stop processing this property + return; + } + } + + $property->setAccessible(true); + + // Ignore uninitialized properties (for PHP >7.4) + if (method_exists($property, 'isInitialized') && !$property->isInitialized($object)) { + return; + } + + $propertyValue = $property->getValue($object); + + // Copy the property + $property->setValue($object, $this->recursiveCopy($propertyValue)); + } + + /** + * Returns first filter that matches variable, `null` if no such filter found. + * + * @param array $filterRecords Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and + * 'matcher' with value of type {@see TypeMatcher} + * @param mixed $var + * + * @return TypeFilter|null + */ + private function getFirstMatchedTypeFilter(array $filterRecords, $var) + { + $matched = $this->first( + $filterRecords, + function (array $record) use ($var) { + /* @var TypeMatcher $matcher */ + $matcher = $record['matcher']; + + return $matcher->matches($var); + } + ); + + return isset($matched) ? $matched['filter'] : null; + } + + /** + * Returns first element that matches predicate, `null` if no such element found. + * + * @param array $elements Array of ['filter' => Filter, 'matcher' => Matcher] pairs. + * @param callable $predicate Predicate arguments are: element. + * + * @return array|null Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and 'matcher' + * with value of type {@see TypeMatcher} or `null`. + */ + private function first(array $elements, callable $predicate) + { + foreach ($elements as $element) { + if (call_user_func($predicate, $element)) { + return $element; + } + } + + return null; + } +} diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php b/vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php new file mode 100644 index 00000000..c046706a --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php @@ -0,0 +1,9 @@ +setAccessible(true); + $oldCollection = $reflectionProperty->getValue($object); + + $newCollection = $oldCollection->map( + function ($item) use ($objectCopier) { + return $objectCopier($item); + } + ); + + $reflectionProperty->setValue($object, $newCollection); + } +} diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php new file mode 100644 index 00000000..7b33fd54 --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php @@ -0,0 +1,28 @@ +setAccessible(true); + + $reflectionProperty->setValue($object, new ArrayCollection()); + } +} \ No newline at end of file diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php new file mode 100644 index 00000000..8bee8f76 --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php @@ -0,0 +1,22 @@ +__load(); + } +} diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php new file mode 100644 index 00000000..85ba18ce --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php @@ -0,0 +1,18 @@ +callback = $callable; + } + + /** + * Replaces the object property by the result of the callback called with the object property. + * + * {@inheritdoc} + */ + public function apply($object, $property, $objectCopier) + { + $reflectionProperty = ReflectionHelper::getProperty($object, $property); + $reflectionProperty->setAccessible(true); + + $value = call_user_func($this->callback, $reflectionProperty->getValue($object)); + + $reflectionProperty->setValue($object, $value); + } +} diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php new file mode 100644 index 00000000..bea86b88 --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php @@ -0,0 +1,24 @@ +setAccessible(true); + $reflectionProperty->setValue($object, null); + } +} diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php new file mode 100644 index 00000000..c5887b19 --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php @@ -0,0 +1,22 @@ +class = $class; + $this->property = $property; + } + + /** + * Matches a specific property of a specific class. + * + * {@inheritdoc} + */ + public function matches($object, $property) + { + return ($object instanceof $this->class) && $property == $this->property; + } +} diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php new file mode 100644 index 00000000..c8ec0d2b --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php @@ -0,0 +1,32 @@ +property = $property; + } + + /** + * Matches a property by its name. + * + * {@inheritdoc} + */ + public function matches($object, $property) + { + return $property == $this->property; + } +} diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php new file mode 100644 index 00000000..c7f46908 --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php @@ -0,0 +1,52 @@ +propertyType = $propertyType; + } + + /** + * {@inheritdoc} + */ + public function matches($object, $property) + { + try { + $reflectionProperty = ReflectionHelper::getProperty($object, $property); + } catch (ReflectionException $exception) { + return false; + } + + $reflectionProperty->setAccessible(true); + + // Uninitialized properties (for PHP >7.4) + if (method_exists($reflectionProperty, 'isInitialized') && !$reflectionProperty->isInitialized($object)) { + // null instanceof $this->propertyType + return false; + } + + return $reflectionProperty->getValue($object) instanceof $this->propertyType; + } +} diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php b/vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php new file mode 100644 index 00000000..742410cb --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php @@ -0,0 +1,78 @@ +getProperties() does not return private properties from ancestor classes. + * + * @author muratyaman@gmail.com + * @see http://php.net/manual/en/reflectionclass.getproperties.php + * + * @param ReflectionClass $ref + * + * @return ReflectionProperty[] + */ + public static function getProperties(ReflectionClass $ref) + { + $props = $ref->getProperties(); + $propsArr = array(); + + foreach ($props as $prop) { + $propertyName = $prop->getName(); + $propsArr[$propertyName] = $prop; + } + + if ($parentClass = $ref->getParentClass()) { + $parentPropsArr = self::getProperties($parentClass); + foreach ($propsArr as $key => $property) { + $parentPropsArr[$key] = $property; + } + + return $parentPropsArr; + } + + return $propsArr; + } + + /** + * Retrieves property by name from object and all its ancestors. + * + * @param object|string $object + * @param string $name + * + * @throws PropertyException + * @throws ReflectionException + * + * @return ReflectionProperty + */ + public static function getProperty($object, $name) + { + $reflection = is_object($object) ? new ReflectionObject($object) : new ReflectionClass($object); + + if ($reflection->hasProperty($name)) { + return $reflection->getProperty($name); + } + + if ($parentClass = $reflection->getParentClass()) { + return self::getProperty($parentClass->getName(), $name); + } + + throw new PropertyException( + sprintf( + 'The class "%s" doesn\'t have a property with the given name: "%s".', + is_object($object) ? get_class($object) : $object, + $name + ) + ); + } +} diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php new file mode 100644 index 00000000..becd1cff --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php @@ -0,0 +1,33 @@ + $propertyValue) { + $copy->{$propertyName} = $propertyValue; + } + + return $copy; + } +} diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php new file mode 100644 index 00000000..164f8b8e --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php @@ -0,0 +1,30 @@ +callback = $callable; + } + + /** + * {@inheritdoc} + */ + public function apply($element) + { + return call_user_func($this->callback, $element); + } +} diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php new file mode 100644 index 00000000..a5fbd7a2 --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php @@ -0,0 +1,17 @@ +copier = $copier; + } + + /** + * {@inheritdoc} + */ + public function apply($arrayObject) + { + $clone = clone $arrayObject; + foreach ($arrayObject->getArrayCopy() as $k => $v) { + $clone->offsetSet($k, $this->copier->copy($v)); + } + + return $clone; + } +} + diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.php new file mode 100644 index 00000000..c5644cff --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.php @@ -0,0 +1,10 @@ +copier = $copier; + } + + /** + * {@inheritdoc} + */ + public function apply($element) + { + $newElement = clone $element; + + $copy = $this->createCopyClosure(); + + return $copy($newElement); + } + + private function createCopyClosure() + { + $copier = $this->copier; + + $copy = function (SplDoublyLinkedList $list) use ($copier) { + // Replace each element in the list with a deep copy of itself + for ($i = 1; $i <= $list->count(); $i++) { + $copy = $copier->recursiveCopy($list->shift()); + + $list->push($copy); + } + + return $list; + }; + + return Closure::bind($copy, null, DeepCopy::class); + } +} diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php new file mode 100644 index 00000000..5785a7da --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php @@ -0,0 +1,13 @@ +type = $type; + } + + /** + * @param mixed $element + * + * @return boolean + */ + public function matches($element) + { + return is_object($element) ? is_a($element, $this->type) : gettype($element) === $this->type; + } +} diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php b/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php new file mode 100644 index 00000000..55dcc926 --- /dev/null +++ b/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php @@ -0,0 +1,20 @@ +copy($value); + } +} diff --git a/vendor/nikic/php-parser/LICENSE b/vendor/nikic/php-parser/LICENSE new file mode 100644 index 00000000..2e567183 --- /dev/null +++ b/vendor/nikic/php-parser/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2011, Nikita Popov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/nikic/php-parser/README.md b/vendor/nikic/php-parser/README.md new file mode 100644 index 00000000..36de23cd --- /dev/null +++ b/vendor/nikic/php-parser/README.md @@ -0,0 +1,225 @@ +PHP Parser +========== + +[![Coverage Status](https://coveralls.io/repos/github/nikic/PHP-Parser/badge.svg?branch=master)](https://coveralls.io/github/nikic/PHP-Parser?branch=master) + +This is a PHP 5.2 to PHP 8.2 parser written in PHP. Its purpose is to simplify static code analysis and +manipulation. + +[**Documentation for version 4.x**][doc_4_x] (stable; for running on PHP >= 7.0; for parsing PHP 5.2 to PHP 8.2). + +[Documentation for version 3.x][doc_3_x] (unsupported; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.2). + +Features +-------- + +The main features provided by this library are: + + * Parsing PHP 5, PHP 7, and PHP 8 code into an abstract syntax tree (AST). + * Invalid code can be parsed into a partial AST. + * The AST contains accurate location information. + * Dumping the AST in human-readable form. + * Converting an AST back to PHP code. + * Experimental: Formatting can be preserved for partially changed ASTs. + * Infrastructure to traverse and modify ASTs. + * Resolution of namespaced names. + * Evaluation of constant expressions. + * Builders to simplify AST construction for code generation. + * Converting an AST into JSON and back. + +Quick Start +----------- + +Install the library using [composer](https://getcomposer.org): + + php composer.phar require nikic/php-parser + +Parse some PHP code into an AST and dump the result in human-readable form: + +```php +create(ParserFactory::PREFER_PHP7); +try { + $ast = $parser->parse($code); +} catch (Error $error) { + echo "Parse error: {$error->getMessage()}\n"; + return; +} + +$dumper = new NodeDumper; +echo $dumper->dump($ast) . "\n"; +``` + +This dumps an AST looking something like this: + +``` +array( + 0: Stmt_Function( + byRef: false + name: Identifier( + name: test + ) + params: array( + 0: Param( + type: null + byRef: false + variadic: false + var: Expr_Variable( + name: foo + ) + default: null + ) + ) + returnType: null + stmts: array( + 0: Stmt_Expression( + expr: Expr_FuncCall( + name: Name( + parts: array( + 0: var_dump + ) + ) + args: array( + 0: Arg( + value: Expr_Variable( + name: foo + ) + byRef: false + unpack: false + ) + ) + ) + ) + ) + ) +) +``` + +Let's traverse the AST and perform some kind of modification. For example, drop all function bodies: + +```php +use PhpParser\Node; +use PhpParser\Node\Stmt\Function_; +use PhpParser\NodeTraverser; +use PhpParser\NodeVisitorAbstract; + +$traverser = new NodeTraverser(); +$traverser->addVisitor(new class extends NodeVisitorAbstract { + public function enterNode(Node $node) { + if ($node instanceof Function_) { + // Clean out the function body + $node->stmts = []; + } + } +}); + +$ast = $traverser->traverse($ast); +echo $dumper->dump($ast) . "\n"; +``` + +This gives us an AST where the `Function_::$stmts` are empty: + +``` +array( + 0: Stmt_Function( + byRef: false + name: Identifier( + name: test + ) + params: array( + 0: Param( + type: null + byRef: false + variadic: false + var: Expr_Variable( + name: foo + ) + default: null + ) + ) + returnType: null + stmts: array( + ) + ) +) +``` + +Finally, we can convert the new AST back to PHP code: + +```php +use PhpParser\PrettyPrinter; + +$prettyPrinter = new PrettyPrinter\Standard; +echo $prettyPrinter->prettyPrintFile($ast); +``` + +This gives us our original code, minus the `var_dump()` call inside the function: + +```php + [ + 'startLine', 'endLine', 'startFilePos', 'endFilePos', 'comments' +]]); +$parser = (new PhpParser\ParserFactory)->create( + PhpParser\ParserFactory::PREFER_PHP7, + $lexer +); +$dumper = new PhpParser\NodeDumper([ + 'dumpComments' => true, + 'dumpPositions' => $attributes['with-positions'], +]); +$prettyPrinter = new PhpParser\PrettyPrinter\Standard; + +$traverser = new PhpParser\NodeTraverser(); +$traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver); + +foreach ($files as $file) { + if (strpos($file, ' Code $code\n"); + } else { + if (!file_exists($file)) { + fwrite(STDERR, "File $file does not exist.\n"); + exit(1); + } + + $code = file_get_contents($file); + fwrite(STDERR, "====> File $file:\n"); + } + + if ($attributes['with-recovery']) { + $errorHandler = new PhpParser\ErrorHandler\Collecting; + $stmts = $parser->parse($code, $errorHandler); + foreach ($errorHandler->getErrors() as $error) { + $message = formatErrorMessage($error, $code, $attributes['with-column-info']); + fwrite(STDERR, $message . "\n"); + } + if (null === $stmts) { + continue; + } + } else { + try { + $stmts = $parser->parse($code); + } catch (PhpParser\Error $error) { + $message = formatErrorMessage($error, $code, $attributes['with-column-info']); + fwrite(STDERR, $message . "\n"); + exit(1); + } + } + + foreach ($operations as $operation) { + if ('dump' === $operation) { + fwrite(STDERR, "==> Node dump:\n"); + echo $dumper->dump($stmts, $code), "\n"; + } elseif ('pretty-print' === $operation) { + fwrite(STDERR, "==> Pretty print:\n"); + echo $prettyPrinter->prettyPrintFile($stmts), "\n"; + } elseif ('json-dump' === $operation) { + fwrite(STDERR, "==> JSON dump:\n"); + echo json_encode($stmts, JSON_PRETTY_PRINT), "\n"; + } elseif ('var-dump' === $operation) { + fwrite(STDERR, "==> var_dump():\n"); + var_dump($stmts); + } elseif ('resolve-names' === $operation) { + fwrite(STDERR, "==> Resolved names.\n"); + $stmts = $traverser->traverse($stmts); + } + } +} + +function formatErrorMessage(PhpParser\Error $e, $code, $withColumnInfo) { + if ($withColumnInfo && $e->hasColumnInfo()) { + return $e->getMessageWithColumnInfo($code); + } else { + return $e->getMessage(); + } +} + +function showHelp($error = '') { + if ($error) { + fwrite(STDERR, $error . "\n\n"); + } + fwrite($error ? STDERR : STDOUT, << false, + 'with-positions' => false, + 'with-recovery' => false, + ]; + + array_shift($args); + $parseOptions = true; + foreach ($args as $arg) { + if (!$parseOptions) { + $files[] = $arg; + continue; + } + + switch ($arg) { + case '--dump': + case '-d': + $operations[] = 'dump'; + break; + case '--pretty-print': + case '-p': + $operations[] = 'pretty-print'; + break; + case '--json-dump': + case '-j': + $operations[] = 'json-dump'; + break; + case '--var-dump': + $operations[] = 'var-dump'; + break; + case '--resolve-names': + case '-N'; + $operations[] = 'resolve-names'; + break; + case '--with-column-info': + case '-c'; + $attributes['with-column-info'] = true; + break; + case '--with-positions': + case '-P': + $attributes['with-positions'] = true; + break; + case '--with-recovery': + case '-r': + $attributes['with-recovery'] = true; + break; + case '--help': + case '-h'; + showHelp(); + break; + case '--': + $parseOptions = false; + break; + default: + if ($arg[0] === '-') { + showHelp("Invalid operation $arg."); + } else { + $files[] = $arg; + } + } + } + + return [$operations, $files, $attributes]; +} diff --git a/vendor/nikic/php-parser/composer.json b/vendor/nikic/php-parser/composer.json new file mode 100644 index 00000000..2fd064a2 --- /dev/null +++ b/vendor/nikic/php-parser/composer.json @@ -0,0 +1,41 @@ +{ + "name": "nikic/php-parser", + "type": "library", + "description": "A PHP parser written in PHP", + "keywords": [ + "php", + "parser" + ], + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Nikita Popov" + } + ], + "require": { + "php": ">=7.0", + "ext-tokenizer": "*" + }, + "require-dev": { + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0", + "ircmaxell/php-yacc": "^0.0.7" + }, + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "autoload-dev": { + "psr-4": { + "PhpParser\\": "test/PhpParser/" + } + }, + "bin": [ + "bin/php-parse" + ] +} diff --git a/vendor/nikic/php-parser/grammar/README.md b/vendor/nikic/php-parser/grammar/README.md new file mode 100644 index 00000000..4bae11d8 --- /dev/null +++ b/vendor/nikic/php-parser/grammar/README.md @@ -0,0 +1,30 @@ +What do all those files mean? +============================= + + * `php5.y`: PHP 5 grammar written in a pseudo language + * `php7.y`: PHP 7 grammar written in a pseudo language + * `tokens.y`: Tokens definition shared between PHP 5 and PHP 7 grammars + * `parser.template`: A `kmyacc` parser prototype file for PHP + * `tokens.template`: A `kmyacc` prototype file for the `Tokens` class + * `rebuildParsers.php`: Preprocesses the grammar and builds the parser using `kmyacc` + +.phpy pseudo language +===================== + +The `.y` file is a normal grammar in `kmyacc` (`yacc`) style, with some transformations +applied to it: + + * Nodes are created using the syntax `Name[..., ...]`. This is transformed into + `new Name(..., ..., attributes())` + * Some function-like constructs are resolved (see `rebuildParsers.php` for a list) + +Building the parser +=================== + +Run `php grammar/rebuildParsers.php` to rebuild the parsers. Additional options: + + * The `KMYACC` environment variable can be used to specify an alternative `kmyacc` binary. + By default the `phpyacc` dev dependency will be used. To use the original `kmyacc`, you + need to compile [moriyoshi's fork](https://github.com/moriyoshi/kmyacc-forked). + * The `--debug` option enables emission of debug symbols and creates the `y.output` file. + * The `--keep-tmp-grammar` option preserves the preprocessed grammar file. diff --git a/vendor/nikic/php-parser/grammar/parser.template b/vendor/nikic/php-parser/grammar/parser.template new file mode 100644 index 00000000..6166607c --- /dev/null +++ b/vendor/nikic/php-parser/grammar/parser.template @@ -0,0 +1,106 @@ +semValue +#semval($,%t) $this->semValue +#semval(%n) $stackPos-(%l-%n) +#semval(%n,%t) $stackPos-(%l-%n) + +namespace PhpParser\Parser; + +use PhpParser\Error; +use PhpParser\Node; +use PhpParser\Node\Expr; +use PhpParser\Node\Name; +use PhpParser\Node\Scalar; +use PhpParser\Node\Stmt; +#include; + +/* This is an automatically GENERATED file, which should not be manually edited. + * Instead edit one of the following: + * * the grammar files grammar/php5.y or grammar/php7.y + * * the skeleton file grammar/parser.template + * * the preprocessing script grammar/rebuildParsers.php + */ +class #(-p) extends \PhpParser\ParserAbstract +{ + protected $tokenToSymbolMapSize = #(YYMAXLEX); + protected $actionTableSize = #(YYLAST); + protected $gotoTableSize = #(YYGLAST); + + protected $invalidSymbol = #(YYBADCH); + protected $errorSymbol = #(YYINTERRTOK); + protected $defaultAction = #(YYDEFAULT); + protected $unexpectedTokenRule = #(YYUNEXPECTED); + + protected $YY2TBLSTATE = #(YY2TBLSTATE); + protected $numNonLeafStates = #(YYNLSTATES); + + protected $symbolToName = array( + #listvar terminals + ); + + protected $tokenToSymbol = array( + #listvar yytranslate + ); + + protected $action = array( + #listvar yyaction + ); + + protected $actionCheck = array( + #listvar yycheck + ); + + protected $actionBase = array( + #listvar yybase + ); + + protected $actionDefault = array( + #listvar yydefault + ); + + protected $goto = array( + #listvar yygoto + ); + + protected $gotoCheck = array( + #listvar yygcheck + ); + + protected $gotoBase = array( + #listvar yygbase + ); + + protected $gotoDefault = array( + #listvar yygdefault + ); + + protected $ruleToNonTerminal = array( + #listvar yylhs + ); + + protected $ruleToLength = array( + #listvar yylen + ); +#if -t + + protected $productions = array( + #production-strings; + ); +#endif + + protected function initReduceCallbacks() { + $this->reduceCallbacks = [ +#reduce + %n => function ($stackPos) { + %b + }, +#noact + %n => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, +#endreduce + ]; + } +} +#tailcode; diff --git a/vendor/nikic/php-parser/grammar/php5.y b/vendor/nikic/php-parser/grammar/php5.y new file mode 100644 index 00000000..2920dead --- /dev/null +++ b/vendor/nikic/php-parser/grammar/php5.y @@ -0,0 +1,1046 @@ +%pure_parser +%expect 6 + +%tokens + +%% + +start: + top_statement_list { $$ = $this->handleNamespaces($1); } +; + +top_statement_list_ex: + top_statement_list_ex top_statement { pushNormalizing($1, $2); } + | /* empty */ { init(); } +; + +top_statement_list: + top_statement_list_ex + { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); + if ($nop !== null) { $1[] = $nop; } $$ = $1; } +; + +ampersand: + T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG + | T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG +; + +reserved_non_modifiers: + T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND + | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE + | T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH + | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO + | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT + | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS + | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN + | T_MATCH +; + +semi_reserved: + reserved_non_modifiers + | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC +; + +identifier_ex: + T_STRING { $$ = Node\Identifier[$1]; } + | semi_reserved { $$ = Node\Identifier[$1]; } +; + +identifier: + T_STRING { $$ = Node\Identifier[$1]; } +; + +reserved_non_modifiers_identifier: + reserved_non_modifiers { $$ = Node\Identifier[$1]; } +; + +namespace_name: + T_STRING { $$ = Name[$1]; } + | T_NAME_QUALIFIED { $$ = Name[$1]; } +; + +legacy_namespace_name: + namespace_name { $$ = $1; } + | T_NAME_FULLY_QUALIFIED { $$ = Name[substr($1, 1)]; } +; + +plain_variable: + T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } +; + +top_statement: + statement { $$ = $1; } + | function_declaration_statement { $$ = $1; } + | class_declaration_statement { $$ = $1; } + | T_HALT_COMPILER + { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; } + | T_NAMESPACE namespace_name ';' + { $$ = Stmt\Namespace_[$2, null]; + $$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); + $this->checkNamespace($$); } + | T_NAMESPACE namespace_name '{' top_statement_list '}' + { $$ = Stmt\Namespace_[$2, $4]; + $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($$); } + | T_NAMESPACE '{' top_statement_list '}' + { $$ = Stmt\Namespace_[null, $3]; + $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($$); } + | T_USE use_declarations ';' { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; } + | T_USE use_type use_declarations ';' { $$ = Stmt\Use_[$3, $2]; } + | group_use_declaration ';' { $$ = $1; } + | T_CONST constant_declaration_list ';' { $$ = Stmt\Const_[$2]; } +; + +use_type: + T_FUNCTION { $$ = Stmt\Use_::TYPE_FUNCTION; } + | T_CONST { $$ = Stmt\Use_::TYPE_CONSTANT; } +; + +group_use_declaration: + T_USE use_type legacy_namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations '}' + { $$ = Stmt\GroupUse[$3, $6, $2]; } + | T_USE legacy_namespace_name T_NS_SEPARATOR '{' inline_use_declarations '}' + { $$ = Stmt\GroupUse[$2, $5, Stmt\Use_::TYPE_UNKNOWN]; } +; + +unprefixed_use_declarations: + unprefixed_use_declarations ',' unprefixed_use_declaration + { push($1, $3); } + | unprefixed_use_declaration { init($1); } +; + +use_declarations: + use_declarations ',' use_declaration { push($1, $3); } + | use_declaration { init($1); } +; + +inline_use_declarations: + inline_use_declarations ',' inline_use_declaration { push($1, $3); } + | inline_use_declaration { init($1); } +; + +unprefixed_use_declaration: + namespace_name + { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } + | namespace_name T_AS identifier + { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } +; + +use_declaration: + legacy_namespace_name + { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } + | legacy_namespace_name T_AS identifier + { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } +; + +inline_use_declaration: + unprefixed_use_declaration { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; } + | use_type unprefixed_use_declaration { $$ = $2; $$->type = $1; } +; + +constant_declaration_list: + constant_declaration_list ',' constant_declaration { push($1, $3); } + | constant_declaration { init($1); } +; + +constant_declaration: + identifier '=' static_scalar { $$ = Node\Const_[$1, $3]; } +; + +class_const_list: + class_const_list ',' class_const { push($1, $3); } + | class_const { init($1); } +; + +class_const: + identifier_ex '=' static_scalar { $$ = Node\Const_[$1, $3]; } +; + +inner_statement_list_ex: + inner_statement_list_ex inner_statement { pushNormalizing($1, $2); } + | /* empty */ { init(); } +; + +inner_statement_list: + inner_statement_list_ex + { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); + if ($nop !== null) { $1[] = $nop; } $$ = $1; } +; + +inner_statement: + statement { $$ = $1; } + | function_declaration_statement { $$ = $1; } + | class_declaration_statement { $$ = $1; } + | T_HALT_COMPILER + { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); } +; + +non_empty_statement: + '{' inner_statement_list '}' + { + if ($2) { + $$ = $2; prependLeadingComments($$); + } else { + makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); + if (null === $$) { $$ = array(); } + } + } + | T_IF parentheses_expr statement elseif_list else_single + { $$ = Stmt\If_[$2, ['stmts' => toArray($3), 'elseifs' => $4, 'else' => $5]]; } + | T_IF parentheses_expr ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' + { $$ = Stmt\If_[$2, ['stmts' => $4, 'elseifs' => $5, 'else' => $6]]; } + | T_WHILE parentheses_expr while_statement { $$ = Stmt\While_[$2, $3]; } + | T_DO statement T_WHILE parentheses_expr ';' { $$ = Stmt\Do_ [$4, toArray($2)]; } + | T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement + { $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; } + | T_SWITCH parentheses_expr switch_case_list { $$ = Stmt\Switch_[$2, $3]; } + | T_BREAK ';' { $$ = Stmt\Break_[null]; } + | T_BREAK expr ';' { $$ = Stmt\Break_[$2]; } + | T_CONTINUE ';' { $$ = Stmt\Continue_[null]; } + | T_CONTINUE expr ';' { $$ = Stmt\Continue_[$2]; } + | T_RETURN ';' { $$ = Stmt\Return_[null]; } + | T_RETURN expr ';' { $$ = Stmt\Return_[$2]; } + | T_GLOBAL global_var_list ';' { $$ = Stmt\Global_[$2]; } + | T_STATIC static_var_list ';' { $$ = Stmt\Static_[$2]; } + | T_ECHO expr_list ';' { $$ = Stmt\Echo_[$2]; } + | T_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; } + | yield_expr ';' { $$ = Stmt\Expression[$1]; } + | expr ';' { $$ = Stmt\Expression[$1]; } + | T_UNSET '(' variables_list ')' ';' { $$ = Stmt\Unset_[$3]; } + | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement + { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; } + | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement + { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; } + | T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; } + | T_TRY '{' inner_statement_list '}' catches optional_finally + { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); } + | T_THROW expr ';' { $$ = Stmt\Throw_[$2]; } + | T_GOTO identifier ';' { $$ = Stmt\Goto_[$2]; } + | identifier ':' { $$ = Stmt\Label[$1]; } + | expr error { $$ = Stmt\Expression[$1]; } + | error { $$ = array(); /* means: no statement */ } +; + +statement: + non_empty_statement { $$ = $1; } + | ';' + { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); + if ($$ === null) $$ = array(); /* means: no statement */ } +; + +catches: + /* empty */ { init(); } + | catches catch { push($1, $2); } +; + +catch: + T_CATCH '(' name plain_variable ')' '{' inner_statement_list '}' + { $$ = Stmt\Catch_[array($3), $4, $7]; } +; + +optional_finally: + /* empty */ { $$ = null; } + | T_FINALLY '{' inner_statement_list '}' { $$ = Stmt\Finally_[$3]; } +; + +variables_list: + variable { init($1); } + | variables_list ',' variable { push($1, $3); } +; + +optional_ref: + /* empty */ { $$ = false; } + | ampersand { $$ = true; } +; + +optional_arg_ref: + /* empty */ { $$ = false; } + | T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG { $$ = true; } +; + +optional_ellipsis: + /* empty */ { $$ = false; } + | T_ELLIPSIS { $$ = true; } +; + +identifier_maybe_readonly: + identifier { $$ = $1; } + | T_READONLY { $$ = Node\Identifier[$1]; } +; + +function_declaration_statement: + T_FUNCTION optional_ref identifier_maybe_readonly '(' parameter_list ')' optional_return_type '{' inner_statement_list '}' + { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $9]]; } +; + +class_declaration_statement: + class_entry_type identifier extends_from implements_list '{' class_statement_list '}' + { $$ = Stmt\Class_[$2, ['type' => $1, 'extends' => $3, 'implements' => $4, 'stmts' => $6]]; + $this->checkClass($$, #2); } + | T_INTERFACE identifier interface_extends_list '{' class_statement_list '}' + { $$ = Stmt\Interface_[$2, ['extends' => $3, 'stmts' => $5]]; + $this->checkInterface($$, #2); } + | T_TRAIT identifier '{' class_statement_list '}' + { $$ = Stmt\Trait_[$2, ['stmts' => $4]]; } +; + +class_entry_type: + T_CLASS { $$ = 0; } + | T_ABSTRACT T_CLASS { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } + | T_FINAL T_CLASS { $$ = Stmt\Class_::MODIFIER_FINAL; } +; + +extends_from: + /* empty */ { $$ = null; } + | T_EXTENDS class_name { $$ = $2; } +; + +interface_extends_list: + /* empty */ { $$ = array(); } + | T_EXTENDS class_name_list { $$ = $2; } +; + +implements_list: + /* empty */ { $$ = array(); } + | T_IMPLEMENTS class_name_list { $$ = $2; } +; + +class_name_list: + class_name { init($1); } + | class_name_list ',' class_name { push($1, $3); } +; + +for_statement: + statement { $$ = toArray($1); } + | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } +; + +foreach_statement: + statement { $$ = toArray($1); } + | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } +; + +declare_statement: + non_empty_statement { $$ = toArray($1); } + | ';' { $$ = null; } + | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } +; + +declare_list: + declare_list_element { init($1); } + | declare_list ',' declare_list_element { push($1, $3); } +; + +declare_list_element: + identifier '=' static_scalar { $$ = Stmt\DeclareDeclare[$1, $3]; } +; + +switch_case_list: + '{' case_list '}' { $$ = $2; } + | '{' ';' case_list '}' { $$ = $3; } + | ':' case_list T_ENDSWITCH ';' { $$ = $2; } + | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } +; + +case_list: + /* empty */ { init(); } + | case_list case { push($1, $2); } +; + +case: + T_CASE expr case_separator inner_statement_list_ex { $$ = Stmt\Case_[$2, $4]; } + | T_DEFAULT case_separator inner_statement_list_ex { $$ = Stmt\Case_[null, $3]; } +; + +case_separator: + ':' + | ';' +; + +while_statement: + statement { $$ = toArray($1); } + | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } +; + +elseif_list: + /* empty */ { init(); } + | elseif_list elseif { push($1, $2); } +; + +elseif: + T_ELSEIF parentheses_expr statement { $$ = Stmt\ElseIf_[$2, toArray($3)]; } +; + +new_elseif_list: + /* empty */ { init(); } + | new_elseif_list new_elseif { push($1, $2); } +; + +new_elseif: + T_ELSEIF parentheses_expr ':' inner_statement_list { $$ = Stmt\ElseIf_[$2, $4]; } +; + +else_single: + /* empty */ { $$ = null; } + | T_ELSE statement { $$ = Stmt\Else_[toArray($2)]; } +; + +new_else_single: + /* empty */ { $$ = null; } + | T_ELSE ':' inner_statement_list { $$ = Stmt\Else_[$3]; } +; + +foreach_variable: + variable { $$ = array($1, false); } + | ampersand variable { $$ = array($2, true); } + | list_expr { $$ = array($1, false); } +; + +parameter_list: + non_empty_parameter_list { $$ = $1; } + | /* empty */ { $$ = array(); } +; + +non_empty_parameter_list: + parameter { init($1); } + | non_empty_parameter_list ',' parameter { push($1, $3); } +; + +parameter: + optional_param_type optional_arg_ref optional_ellipsis plain_variable + { $$ = Node\Param[$4, null, $1, $2, $3]; $this->checkParam($$); } + | optional_param_type optional_arg_ref optional_ellipsis plain_variable '=' static_scalar + { $$ = Node\Param[$4, $6, $1, $2, $3]; $this->checkParam($$); } +; + +type: + name { $$ = $1; } + | T_ARRAY { $$ = Node\Identifier['array']; } + | T_CALLABLE { $$ = Node\Identifier['callable']; } +; + +optional_param_type: + /* empty */ { $$ = null; } + | type { $$ = $1; } +; + +optional_return_type: + /* empty */ { $$ = null; } + | ':' type { $$ = $2; } +; + +argument_list: + '(' ')' { $$ = array(); } + | '(' non_empty_argument_list ')' { $$ = $2; } + | '(' yield_expr ')' { $$ = array(Node\Arg[$2, false, false]); } +; + +non_empty_argument_list: + argument { init($1); } + | non_empty_argument_list ',' argument { push($1, $3); } +; + +argument: + expr { $$ = Node\Arg[$1, false, false]; } + | ampersand variable { $$ = Node\Arg[$2, true, false]; } + | T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; } +; + +global_var_list: + global_var_list ',' global_var { push($1, $3); } + | global_var { init($1); } +; + +global_var: + plain_variable { $$ = $1; } + | '$' variable { $$ = Expr\Variable[$2]; } + | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } +; + +static_var_list: + static_var_list ',' static_var { push($1, $3); } + | static_var { init($1); } +; + +static_var: + plain_variable { $$ = Stmt\StaticVar[$1, null]; } + | plain_variable '=' static_scalar { $$ = Stmt\StaticVar[$1, $3]; } +; + +class_statement_list_ex: + class_statement_list_ex class_statement { if ($2 !== null) { push($1, $2); } } + | /* empty */ { init(); } +; + +class_statement_list: + class_statement_list_ex + { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); + if ($nop !== null) { $1[] = $nop; } $$ = $1; } +; + +class_statement: + variable_modifiers property_declaration_list ';' + { $$ = Stmt\Property[$1, $2]; $this->checkProperty($$, #1); } + | T_CONST class_const_list ';' { $$ = Stmt\ClassConst[$2, 0]; } + | method_modifiers T_FUNCTION optional_ref identifier_ex '(' parameter_list ')' optional_return_type method_body + { $$ = Stmt\ClassMethod[$4, ['type' => $1, 'byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9]]; + $this->checkClassMethod($$, #1); } + | T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; } +; + +trait_adaptations: + ';' { $$ = array(); } + | '{' trait_adaptation_list '}' { $$ = $2; } +; + +trait_adaptation_list: + /* empty */ { init(); } + | trait_adaptation_list trait_adaptation { push($1, $2); } +; + +trait_adaptation: + trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';' + { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; } + | trait_method_reference T_AS member_modifier identifier_ex ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; } + | trait_method_reference T_AS member_modifier ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; } + | trait_method_reference T_AS identifier ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } + | trait_method_reference T_AS reserved_non_modifiers_identifier ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } +; + +trait_method_reference_fully_qualified: + name T_PAAMAYIM_NEKUDOTAYIM identifier_ex { $$ = array($1, $3); } +; +trait_method_reference: + trait_method_reference_fully_qualified { $$ = $1; } + | identifier_ex { $$ = array(null, $1); } +; + +method_body: + ';' /* abstract method */ { $$ = null; } + | '{' inner_statement_list '}' { $$ = $2; } +; + +variable_modifiers: + non_empty_member_modifiers { $$ = $1; } + | T_VAR { $$ = 0; } +; + +method_modifiers: + /* empty */ { $$ = 0; } + | non_empty_member_modifiers { $$ = $1; } +; + +non_empty_member_modifiers: + member_modifier { $$ = $1; } + | non_empty_member_modifiers member_modifier { $this->checkModifier($1, $2, #2); $$ = $1 | $2; } +; + +member_modifier: + T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } + | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } + | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } + | T_STATIC { $$ = Stmt\Class_::MODIFIER_STATIC; } + | T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } + | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } +; + +property_declaration_list: + property_declaration { init($1); } + | property_declaration_list ',' property_declaration { push($1, $3); } +; + +property_decl_name: + T_VARIABLE { $$ = Node\VarLikeIdentifier[parseVar($1)]; } +; + +property_declaration: + property_decl_name { $$ = Stmt\PropertyProperty[$1, null]; } + | property_decl_name '=' static_scalar { $$ = Stmt\PropertyProperty[$1, $3]; } +; + +expr_list: + expr_list ',' expr { push($1, $3); } + | expr { init($1); } +; + +for_expr: + /* empty */ { $$ = array(); } + | expr_list { $$ = $1; } +; + +expr: + variable { $$ = $1; } + | list_expr '=' expr { $$ = Expr\Assign[$1, $3]; } + | variable '=' expr { $$ = Expr\Assign[$1, $3]; } + | variable '=' ampersand variable { $$ = Expr\AssignRef[$1, $4]; } + | variable '=' ampersand new_expr { $$ = Expr\AssignRef[$1, $4]; } + | new_expr { $$ = $1; } + | T_CLONE expr { $$ = Expr\Clone_[$2]; } + | variable T_PLUS_EQUAL expr { $$ = Expr\AssignOp\Plus [$1, $3]; } + | variable T_MINUS_EQUAL expr { $$ = Expr\AssignOp\Minus [$1, $3]; } + | variable T_MUL_EQUAL expr { $$ = Expr\AssignOp\Mul [$1, $3]; } + | variable T_DIV_EQUAL expr { $$ = Expr\AssignOp\Div [$1, $3]; } + | variable T_CONCAT_EQUAL expr { $$ = Expr\AssignOp\Concat [$1, $3]; } + | variable T_MOD_EQUAL expr { $$ = Expr\AssignOp\Mod [$1, $3]; } + | variable T_AND_EQUAL expr { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; } + | variable T_OR_EQUAL expr { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; } + | variable T_XOR_EQUAL expr { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; } + | variable T_SL_EQUAL expr { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; } + | variable T_SR_EQUAL expr { $$ = Expr\AssignOp\ShiftRight[$1, $3]; } + | variable T_POW_EQUAL expr { $$ = Expr\AssignOp\Pow [$1, $3]; } + | variable T_COALESCE_EQUAL expr { $$ = Expr\AssignOp\Coalesce [$1, $3]; } + | variable T_INC { $$ = Expr\PostInc[$1]; } + | T_INC variable { $$ = Expr\PreInc [$2]; } + | variable T_DEC { $$ = Expr\PostDec[$1]; } + | T_DEC variable { $$ = Expr\PreDec [$2]; } + | expr T_BOOLEAN_OR expr { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } + | expr T_BOOLEAN_AND expr { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } + | expr T_LOGICAL_OR expr { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } + | expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } + | expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } + | expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } + | expr T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } + | expr T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } + | expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } + | expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; } + | expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; } + | expr '-' expr { $$ = Expr\BinaryOp\Minus [$1, $3]; } + | expr '*' expr { $$ = Expr\BinaryOp\Mul [$1, $3]; } + | expr '/' expr { $$ = Expr\BinaryOp\Div [$1, $3]; } + | expr '%' expr { $$ = Expr\BinaryOp\Mod [$1, $3]; } + | expr T_SL expr { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } + | expr T_SR expr { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } + | expr T_POW expr { $$ = Expr\BinaryOp\Pow [$1, $3]; } + | '+' expr %prec T_INC { $$ = Expr\UnaryPlus [$2]; } + | '-' expr %prec T_INC { $$ = Expr\UnaryMinus[$2]; } + | '!' expr { $$ = Expr\BooleanNot[$2]; } + | '~' expr { $$ = Expr\BitwiseNot[$2]; } + | expr T_IS_IDENTICAL expr { $$ = Expr\BinaryOp\Identical [$1, $3]; } + | expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } + | expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; } + | expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } + | expr T_SPACESHIP expr { $$ = Expr\BinaryOp\Spaceship [$1, $3]; } + | expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; } + | expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } + | expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; } + | expr T_IS_GREATER_OR_EQUAL expr { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } + | expr T_INSTANCEOF class_name_reference { $$ = Expr\Instanceof_[$1, $3]; } + | parentheses_expr { $$ = $1; } + /* we need a separate '(' new_expr ')' rule to avoid problems caused by a s/r conflict */ + | '(' new_expr ')' { $$ = $2; } + | expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; } + | expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; } + | expr T_COALESCE expr { $$ = Expr\BinaryOp\Coalesce[$1, $3]; } + | T_ISSET '(' variables_list ')' { $$ = Expr\Isset_[$3]; } + | T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; } + | T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; } + | T_INCLUDE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; } + | T_EVAL parentheses_expr { $$ = Expr\Eval_[$2]; } + | T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; } + | T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; } + | T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; } + | T_DOUBLE_CAST expr + { $attrs = attributes(); + $attrs['kind'] = $this->getFloatCastKind($1); + $$ = new Expr\Cast\Double($2, $attrs); } + | T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; } + | T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; } + | T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; } + | T_BOOL_CAST expr { $$ = Expr\Cast\Bool_ [$2]; } + | T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; } + | T_EXIT exit_expr + { $attrs = attributes(); + $attrs['kind'] = strtolower($1) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; + $$ = new Expr\Exit_($2, $attrs); } + | '@' expr { $$ = Expr\ErrorSuppress[$2]; } + | scalar { $$ = $1; } + | array_expr { $$ = $1; } + | scalar_dereference { $$ = $1; } + | '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; } + | T_PRINT expr { $$ = Expr\Print_[$2]; } + | T_YIELD { $$ = Expr\Yield_[null, null]; } + | T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; } + | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type + '{' inner_statement_list '}' + { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $9]]; } + | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type + '{' inner_statement_list '}' + { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $10]]; } +; + +parentheses_expr: + '(' expr ')' { $$ = $2; } + | '(' yield_expr ')' { $$ = $2; } +; + +yield_expr: + T_YIELD expr { $$ = Expr\Yield_[$2, null]; } + | T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; } +; + +array_expr: + T_ARRAY '(' array_pair_list ')' + { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG; + $$ = new Expr\Array_($3, $attrs); } + | '[' array_pair_list ']' + { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_SHORT; + $$ = new Expr\Array_($2, $attrs); } +; + +scalar_dereference: + array_expr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[Scalar\String_::fromString($1, attributes()), $3]; } + | constant '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | scalar_dereference '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + /* alternative array syntax missing intentionally */ +; + +anonymous_class: + T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}' + { $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $3, 'implements' => $4, 'stmts' => $6]], $2); + $this->checkClass($$[0], -1); } +; + +new_expr: + T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; } + | T_NEW anonymous_class + { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; } +; + +lexical_vars: + /* empty */ { $$ = array(); } + | T_USE '(' lexical_var_list ')' { $$ = $3; } +; + +lexical_var_list: + lexical_var { init($1); } + | lexical_var_list ',' lexical_var { push($1, $3); } +; + +lexical_var: + optional_ref plain_variable { $$ = Expr\ClosureUse[$2, $1]; } +; + +name_readonly: + T_READONLY { $$ = Name[$1]; } +; + +function_call: + name argument_list { $$ = Expr\FuncCall[$1, $2]; } + | name_readonly argument_list { $$ = Expr\FuncCall[$1, $2]; } + | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex argument_list + { $$ = Expr\StaticCall[$1, $3, $4]; } + | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' argument_list + { $$ = Expr\StaticCall[$1, $4, $6]; } + | static_property argument_list + { $$ = $this->fixupPhp5StaticPropCall($1, $2, attributes()); } + | variable_without_objects argument_list + { $$ = Expr\FuncCall[$1, $2]; } + | function_call '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + /* alternative array syntax missing intentionally */ +; + +class_name: + T_STATIC { $$ = Name[$1]; } + | name { $$ = $1; } +; + +name: + T_STRING { $$ = Name[$1]; } + | T_NAME_QUALIFIED { $$ = Name[$1]; } + | T_NAME_FULLY_QUALIFIED { $$ = Name\FullyQualified[substr($1, 1)]; } + | T_NAME_RELATIVE { $$ = Name\Relative[substr($1, 10)]; } +; + +class_name_reference: + class_name { $$ = $1; } + | dynamic_class_name_reference { $$ = $1; } +; + +dynamic_class_name_reference: + object_access_for_dcnr { $$ = $1; } + | base_variable { $$ = $1; } +; + +class_name_or_var: + class_name { $$ = $1; } + | reference_variable { $$ = $1; } +; + +object_access_for_dcnr: + base_variable T_OBJECT_OPERATOR object_property + { $$ = Expr\PropertyFetch[$1, $3]; } + | object_access_for_dcnr T_OBJECT_OPERATOR object_property + { $$ = Expr\PropertyFetch[$1, $3]; } + | object_access_for_dcnr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | object_access_for_dcnr '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } +; + +exit_expr: + /* empty */ { $$ = null; } + | '(' ')' { $$ = null; } + | parentheses_expr { $$ = $1; } +; + +backticks_expr: + /* empty */ { $$ = array(); } + | T_ENCAPSED_AND_WHITESPACE + { $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`', false)]); } + | encaps_list { parseEncapsed($1, '`', false); $$ = $1; } +; + +ctor_arguments: + /* empty */ { $$ = array(); } + | argument_list { $$ = $1; } +; + +common_scalar: + T_LNUMBER { $$ = $this->parseLNumber($1, attributes(), true); } + | T_DNUMBER { $$ = Scalar\DNumber::fromString($1, attributes()); } + | T_CONSTANT_ENCAPSED_STRING { $$ = Scalar\String_::fromString($1, attributes(), false); } + | T_LINE { $$ = Scalar\MagicConst\Line[]; } + | T_FILE { $$ = Scalar\MagicConst\File[]; } + | T_DIR { $$ = Scalar\MagicConst\Dir[]; } + | T_CLASS_C { $$ = Scalar\MagicConst\Class_[]; } + | T_TRAIT_C { $$ = Scalar\MagicConst\Trait_[]; } + | T_METHOD_C { $$ = Scalar\MagicConst\Method[]; } + | T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; } + | T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; } + | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC + { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), false); } + | T_START_HEREDOC T_END_HEREDOC + { $$ = $this->parseDocString($1, '', $2, attributes(), stackAttributes(#2), false); } +; + +static_scalar: + common_scalar { $$ = $1; } + | class_name T_PAAMAYIM_NEKUDOTAYIM identifier_ex { $$ = Expr\ClassConstFetch[$1, $3]; } + | name { $$ = Expr\ConstFetch[$1]; } + | T_ARRAY '(' static_array_pair_list ')' { $$ = Expr\Array_[$3]; } + | '[' static_array_pair_list ']' { $$ = Expr\Array_[$2]; } + | static_operation { $$ = $1; } +; + +static_operation: + static_scalar T_BOOLEAN_OR static_scalar { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } + | static_scalar T_BOOLEAN_AND static_scalar { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } + | static_scalar T_LOGICAL_OR static_scalar { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } + | static_scalar T_LOGICAL_AND static_scalar { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } + | static_scalar T_LOGICAL_XOR static_scalar { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } + | static_scalar '|' static_scalar { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } + | static_scalar T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG static_scalar + { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } + | static_scalar T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG static_scalar + { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } + | static_scalar '^' static_scalar { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } + | static_scalar '.' static_scalar { $$ = Expr\BinaryOp\Concat [$1, $3]; } + | static_scalar '+' static_scalar { $$ = Expr\BinaryOp\Plus [$1, $3]; } + | static_scalar '-' static_scalar { $$ = Expr\BinaryOp\Minus [$1, $3]; } + | static_scalar '*' static_scalar { $$ = Expr\BinaryOp\Mul [$1, $3]; } + | static_scalar '/' static_scalar { $$ = Expr\BinaryOp\Div [$1, $3]; } + | static_scalar '%' static_scalar { $$ = Expr\BinaryOp\Mod [$1, $3]; } + | static_scalar T_SL static_scalar { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } + | static_scalar T_SR static_scalar { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } + | static_scalar T_POW static_scalar { $$ = Expr\BinaryOp\Pow [$1, $3]; } + | '+' static_scalar %prec T_INC { $$ = Expr\UnaryPlus [$2]; } + | '-' static_scalar %prec T_INC { $$ = Expr\UnaryMinus[$2]; } + | '!' static_scalar { $$ = Expr\BooleanNot[$2]; } + | '~' static_scalar { $$ = Expr\BitwiseNot[$2]; } + | static_scalar T_IS_IDENTICAL static_scalar { $$ = Expr\BinaryOp\Identical [$1, $3]; } + | static_scalar T_IS_NOT_IDENTICAL static_scalar { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } + | static_scalar T_IS_EQUAL static_scalar { $$ = Expr\BinaryOp\Equal [$1, $3]; } + | static_scalar T_IS_NOT_EQUAL static_scalar { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } + | static_scalar '<' static_scalar { $$ = Expr\BinaryOp\Smaller [$1, $3]; } + | static_scalar T_IS_SMALLER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } + | static_scalar '>' static_scalar { $$ = Expr\BinaryOp\Greater [$1, $3]; } + | static_scalar T_IS_GREATER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } + | static_scalar '?' static_scalar ':' static_scalar { $$ = Expr\Ternary[$1, $3, $5]; } + | static_scalar '?' ':' static_scalar { $$ = Expr\Ternary[$1, null, $4]; } + | static_scalar '[' static_scalar ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | '(' static_scalar ')' { $$ = $2; } +; + +constant: + name { $$ = Expr\ConstFetch[$1]; } + | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex + { $$ = Expr\ClassConstFetch[$1, $3]; } +; + +scalar: + common_scalar { $$ = $1; } + | constant { $$ = $1; } + | '"' encaps_list '"' + { $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; + parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); } + | T_START_HEREDOC encaps_list T_END_HEREDOC + { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); } +; + +static_array_pair_list: + /* empty */ { $$ = array(); } + | non_empty_static_array_pair_list optional_comma { $$ = $1; } +; + +optional_comma: + /* empty */ + | ',' +; + +non_empty_static_array_pair_list: + non_empty_static_array_pair_list ',' static_array_pair { push($1, $3); } + | static_array_pair { init($1); } +; + +static_array_pair: + static_scalar T_DOUBLE_ARROW static_scalar { $$ = Expr\ArrayItem[$3, $1, false]; } + | static_scalar { $$ = Expr\ArrayItem[$1, null, false]; } +; + +variable: + object_access { $$ = $1; } + | base_variable { $$ = $1; } + | function_call { $$ = $1; } + | new_expr_array_deref { $$ = $1; } +; + +new_expr_array_deref: + '(' new_expr ')' '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$2, $5]; } + | new_expr_array_deref '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + /* alternative array syntax missing intentionally */ +; + +object_access: + variable_or_new_expr T_OBJECT_OPERATOR object_property + { $$ = Expr\PropertyFetch[$1, $3]; } + | variable_or_new_expr T_OBJECT_OPERATOR object_property argument_list + { $$ = Expr\MethodCall[$1, $3, $4]; } + | object_access argument_list { $$ = Expr\FuncCall[$1, $2]; } + | object_access '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | object_access '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } +; + +variable_or_new_expr: + variable { $$ = $1; } + | '(' new_expr ')' { $$ = $2; } +; + +variable_without_objects: + reference_variable { $$ = $1; } + | '$' variable_without_objects { $$ = Expr\Variable[$2]; } +; + +base_variable: + variable_without_objects { $$ = $1; } + | static_property { $$ = $1; } +; + +static_property: + class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' reference_variable + { $$ = Expr\StaticPropertyFetch[$1, $4]; } + | static_property_with_arrays { $$ = $1; } +; + +static_property_simple_name: + T_VARIABLE + { $var = parseVar($1); $$ = \is_string($var) ? Node\VarLikeIdentifier[$var] : $var; } +; + +static_property_with_arrays: + class_name_or_var T_PAAMAYIM_NEKUDOTAYIM static_property_simple_name + { $$ = Expr\StaticPropertyFetch[$1, $3]; } + | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' '{' expr '}' + { $$ = Expr\StaticPropertyFetch[$1, $5]; } + | static_property_with_arrays '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | static_property_with_arrays '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } +; + +reference_variable: + reference_variable '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | reference_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | plain_variable { $$ = $1; } + | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } +; + +dim_offset: + /* empty */ { $$ = null; } + | expr { $$ = $1; } +; + +object_property: + identifier { $$ = $1; } + | '{' expr '}' { $$ = $2; } + | variable_without_objects { $$ = $1; } + | error { $$ = Expr\Error[]; $this->errorState = 2; } +; + +list_expr: + T_LIST '(' list_expr_elements ')' { $$ = Expr\List_[$3]; } +; + +list_expr_elements: + list_expr_elements ',' list_expr_element { push($1, $3); } + | list_expr_element { init($1); } +; + +list_expr_element: + variable { $$ = Expr\ArrayItem[$1, null, false]; } + | list_expr { $$ = Expr\ArrayItem[$1, null, false]; } + | /* empty */ { $$ = null; } +; + +array_pair_list: + /* empty */ { $$ = array(); } + | non_empty_array_pair_list optional_comma { $$ = $1; } +; + +non_empty_array_pair_list: + non_empty_array_pair_list ',' array_pair { push($1, $3); } + | array_pair { init($1); } +; + +array_pair: + expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; } + | expr { $$ = Expr\ArrayItem[$1, null, false]; } + | expr T_DOUBLE_ARROW ampersand variable { $$ = Expr\ArrayItem[$4, $1, true]; } + | ampersand variable { $$ = Expr\ArrayItem[$2, null, true]; } + | T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; } +; + +encaps_list: + encaps_list encaps_var { push($1, $2); } + | encaps_list encaps_string_part { push($1, $2); } + | encaps_var { init($1); } + | encaps_string_part encaps_var { init($1, $2); } +; + +encaps_string_part: + T_ENCAPSED_AND_WHITESPACE { $$ = Scalar\EncapsedStringPart[$1]; } +; + +encaps_str_varname: + T_STRING_VARNAME { $$ = Expr\Variable[$1]; } +; + +encaps_var: + plain_variable { $$ = $1; } + | plain_variable '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | plain_variable T_OBJECT_OPERATOR identifier { $$ = Expr\PropertyFetch[$1, $3]; } + | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = Expr\Variable[$2]; } + | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' { $$ = Expr\Variable[$2]; } + | T_DOLLAR_OPEN_CURLY_BRACES encaps_str_varname '[' expr ']' '}' + { $$ = Expr\ArrayDimFetch[$2, $4]; } + | T_CURLY_OPEN variable '}' { $$ = $2; } +; + +encaps_var_offset: + T_STRING { $$ = Scalar\String_[$1]; } + | T_NUM_STRING { $$ = $this->parseNumString($1, attributes()); } + | plain_variable { $$ = $1; } +; + +%% diff --git a/vendor/nikic/php-parser/grammar/php7.y b/vendor/nikic/php-parser/grammar/php7.y new file mode 100644 index 00000000..1f9b4bdd --- /dev/null +++ b/vendor/nikic/php-parser/grammar/php7.y @@ -0,0 +1,1235 @@ +%pure_parser +%expect 2 + +%tokens + +%% + +start: + top_statement_list { $$ = $this->handleNamespaces($1); } +; + +top_statement_list_ex: + top_statement_list_ex top_statement { pushNormalizing($1, $2); } + | /* empty */ { init(); } +; + +top_statement_list: + top_statement_list_ex + { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); + if ($nop !== null) { $1[] = $nop; } $$ = $1; } +; + +ampersand: + T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG + | T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG +; + +reserved_non_modifiers: + T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND + | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE + | T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH + | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO + | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT + | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS + | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN + | T_MATCH | T_ENUM +; + +semi_reserved: + reserved_non_modifiers + | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC | T_READONLY +; + +identifier_maybe_reserved: + T_STRING { $$ = Node\Identifier[$1]; } + | semi_reserved { $$ = Node\Identifier[$1]; } +; + +identifier_not_reserved: + T_STRING { $$ = Node\Identifier[$1]; } +; + +reserved_non_modifiers_identifier: + reserved_non_modifiers { $$ = Node\Identifier[$1]; } +; + +namespace_declaration_name: + T_STRING { $$ = Name[$1]; } + | semi_reserved { $$ = Name[$1]; } + | T_NAME_QUALIFIED { $$ = Name[$1]; } +; + +namespace_name: + T_STRING { $$ = Name[$1]; } + | T_NAME_QUALIFIED { $$ = Name[$1]; } +; + +legacy_namespace_name: + namespace_name { $$ = $1; } + | T_NAME_FULLY_QUALIFIED { $$ = Name[substr($1, 1)]; } +; + +plain_variable: + T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } +; + +semi: + ';' { /* nothing */ } + | error { /* nothing */ } +; + +no_comma: + /* empty */ { /* nothing */ } + | ',' { $this->emitError(new Error('A trailing comma is not allowed here', attributes())); } +; + +optional_comma: + /* empty */ + | ',' +; + +attribute_decl: + class_name { $$ = Node\Attribute[$1, []]; } + | class_name argument_list { $$ = Node\Attribute[$1, $2]; } +; + +attribute_group: + attribute_decl { init($1); } + | attribute_group ',' attribute_decl { push($1, $3); } +; + +attribute: + T_ATTRIBUTE attribute_group optional_comma ']' { $$ = Node\AttributeGroup[$2]; } +; + +attributes: + attribute { init($1); } + | attributes attribute { push($1, $2); } +; + +optional_attributes: + /* empty */ { $$ = []; } + | attributes { $$ = $1; } +; + +top_statement: + statement { $$ = $1; } + | function_declaration_statement { $$ = $1; } + | class_declaration_statement { $$ = $1; } + | T_HALT_COMPILER + { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; } + | T_NAMESPACE namespace_declaration_name semi + { $$ = Stmt\Namespace_[$2, null]; + $$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); + $this->checkNamespace($$); } + | T_NAMESPACE namespace_declaration_name '{' top_statement_list '}' + { $$ = Stmt\Namespace_[$2, $4]; + $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($$); } + | T_NAMESPACE '{' top_statement_list '}' + { $$ = Stmt\Namespace_[null, $3]; + $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($$); } + | T_USE use_declarations semi { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; } + | T_USE use_type use_declarations semi { $$ = Stmt\Use_[$3, $2]; } + | group_use_declaration semi { $$ = $1; } + | T_CONST constant_declaration_list semi { $$ = Stmt\Const_[$2]; } +; + +use_type: + T_FUNCTION { $$ = Stmt\Use_::TYPE_FUNCTION; } + | T_CONST { $$ = Stmt\Use_::TYPE_CONSTANT; } +; + +group_use_declaration: + T_USE use_type legacy_namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations '}' + { $$ = Stmt\GroupUse[$3, $6, $2]; } + | T_USE legacy_namespace_name T_NS_SEPARATOR '{' inline_use_declarations '}' + { $$ = Stmt\GroupUse[$2, $5, Stmt\Use_::TYPE_UNKNOWN]; } +; + +unprefixed_use_declarations: + non_empty_unprefixed_use_declarations optional_comma { $$ = $1; } +; + +non_empty_unprefixed_use_declarations: + non_empty_unprefixed_use_declarations ',' unprefixed_use_declaration + { push($1, $3); } + | unprefixed_use_declaration { init($1); } +; + +use_declarations: + non_empty_use_declarations no_comma { $$ = $1; } +; + +non_empty_use_declarations: + non_empty_use_declarations ',' use_declaration { push($1, $3); } + | use_declaration { init($1); } +; + +inline_use_declarations: + non_empty_inline_use_declarations optional_comma { $$ = $1; } +; + +non_empty_inline_use_declarations: + non_empty_inline_use_declarations ',' inline_use_declaration + { push($1, $3); } + | inline_use_declaration { init($1); } +; + +unprefixed_use_declaration: + namespace_name + { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } + | namespace_name T_AS identifier_not_reserved + { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } +; + +use_declaration: + legacy_namespace_name + { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } + | legacy_namespace_name T_AS identifier_not_reserved + { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } +; + +inline_use_declaration: + unprefixed_use_declaration { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; } + | use_type unprefixed_use_declaration { $$ = $2; $$->type = $1; } +; + +constant_declaration_list: + non_empty_constant_declaration_list no_comma { $$ = $1; } +; + +non_empty_constant_declaration_list: + non_empty_constant_declaration_list ',' constant_declaration + { push($1, $3); } + | constant_declaration { init($1); } +; + +constant_declaration: + identifier_not_reserved '=' expr { $$ = Node\Const_[$1, $3]; } +; + +class_const_list: + non_empty_class_const_list no_comma { $$ = $1; } +; + +non_empty_class_const_list: + non_empty_class_const_list ',' class_const { push($1, $3); } + | class_const { init($1); } +; + +class_const: + identifier_maybe_reserved '=' expr { $$ = Node\Const_[$1, $3]; } +; + +inner_statement_list_ex: + inner_statement_list_ex inner_statement { pushNormalizing($1, $2); } + | /* empty */ { init(); } +; + +inner_statement_list: + inner_statement_list_ex + { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); + if ($nop !== null) { $1[] = $nop; } $$ = $1; } +; + +inner_statement: + statement { $$ = $1; } + | function_declaration_statement { $$ = $1; } + | class_declaration_statement { $$ = $1; } + | T_HALT_COMPILER + { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); } +; + +non_empty_statement: + '{' inner_statement_list '}' + { + if ($2) { + $$ = $2; prependLeadingComments($$); + } else { + makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); + if (null === $$) { $$ = array(); } + } + } + | T_IF '(' expr ')' statement elseif_list else_single + { $$ = Stmt\If_[$3, ['stmts' => toArray($5), 'elseifs' => $6, 'else' => $7]]; } + | T_IF '(' expr ')' ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' + { $$ = Stmt\If_[$3, ['stmts' => $6, 'elseifs' => $7, 'else' => $8]]; } + | T_WHILE '(' expr ')' while_statement { $$ = Stmt\While_[$3, $5]; } + | T_DO statement T_WHILE '(' expr ')' ';' { $$ = Stmt\Do_ [$5, toArray($2)]; } + | T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement + { $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; } + | T_SWITCH '(' expr ')' switch_case_list { $$ = Stmt\Switch_[$3, $5]; } + | T_BREAK optional_expr semi { $$ = Stmt\Break_[$2]; } + | T_CONTINUE optional_expr semi { $$ = Stmt\Continue_[$2]; } + | T_RETURN optional_expr semi { $$ = Stmt\Return_[$2]; } + | T_GLOBAL global_var_list semi { $$ = Stmt\Global_[$2]; } + | T_STATIC static_var_list semi { $$ = Stmt\Static_[$2]; } + | T_ECHO expr_list_forbid_comma semi { $$ = Stmt\Echo_[$2]; } + | T_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; } + | expr semi { + $e = $1; + if ($e instanceof Expr\Throw_) { + // For backwards-compatibility reasons, convert throw in statement position into + // Stmt\Throw_ rather than Stmt\Expression(Expr\Throw_). + $$ = Stmt\Throw_[$e->expr]; + } else { + $$ = Stmt\Expression[$e]; + } + } + | T_UNSET '(' variables_list ')' semi { $$ = Stmt\Unset_[$3]; } + | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement + { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; } + | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement + { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; } + | T_FOREACH '(' expr error ')' foreach_statement + { $$ = Stmt\Foreach_[$3, new Expr\Error(stackAttributes(#4)), ['stmts' => $6]]; } + | T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; } + | T_TRY '{' inner_statement_list '}' catches optional_finally + { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); } + | T_GOTO identifier_not_reserved semi { $$ = Stmt\Goto_[$2]; } + | identifier_not_reserved ':' { $$ = Stmt\Label[$1]; } + | error { $$ = array(); /* means: no statement */ } +; + +statement: + non_empty_statement { $$ = $1; } + | ';' + { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); + if ($$ === null) $$ = array(); /* means: no statement */ } +; + +catches: + /* empty */ { init(); } + | catches catch { push($1, $2); } +; + +name_union: + name { init($1); } + | name_union '|' name { push($1, $3); } +; + +catch: + T_CATCH '(' name_union optional_plain_variable ')' '{' inner_statement_list '}' + { $$ = Stmt\Catch_[$3, $4, $7]; } +; + +optional_finally: + /* empty */ { $$ = null; } + | T_FINALLY '{' inner_statement_list '}' { $$ = Stmt\Finally_[$3]; } +; + +variables_list: + non_empty_variables_list optional_comma { $$ = $1; } +; + +non_empty_variables_list: + variable { init($1); } + | non_empty_variables_list ',' variable { push($1, $3); } +; + +optional_ref: + /* empty */ { $$ = false; } + | ampersand { $$ = true; } +; + +optional_arg_ref: + /* empty */ { $$ = false; } + | T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG { $$ = true; } +; + +optional_ellipsis: + /* empty */ { $$ = false; } + | T_ELLIPSIS { $$ = true; } +; + +block_or_error: + '{' inner_statement_list '}' { $$ = $2; } + | error { $$ = []; } +; + +identifier_maybe_readonly: + identifier_not_reserved { $$ = $1; } + | T_READONLY { $$ = Node\Identifier[$1]; } +; + +function_declaration_statement: + T_FUNCTION optional_ref identifier_maybe_readonly '(' parameter_list ')' optional_return_type block_or_error + { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $8, 'attrGroups' => []]]; } + | attributes T_FUNCTION optional_ref identifier_maybe_readonly '(' parameter_list ')' optional_return_type block_or_error + { $$ = Stmt\Function_[$4, ['byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => $1]]; } +; + +class_declaration_statement: + class_entry_type identifier_not_reserved extends_from implements_list '{' class_statement_list '}' + { $$ = Stmt\Class_[$2, ['type' => $1, 'extends' => $3, 'implements' => $4, 'stmts' => $6, 'attrGroups' => []]]; + $this->checkClass($$, #2); } + | attributes class_entry_type identifier_not_reserved extends_from implements_list '{' class_statement_list '}' + { $$ = Stmt\Class_[$3, ['type' => $2, 'extends' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]]; + $this->checkClass($$, #3); } + | optional_attributes T_INTERFACE identifier_not_reserved interface_extends_list '{' class_statement_list '}' + { $$ = Stmt\Interface_[$3, ['extends' => $4, 'stmts' => $6, 'attrGroups' => $1]]; + $this->checkInterface($$, #3); } + | optional_attributes T_TRAIT identifier_not_reserved '{' class_statement_list '}' + { $$ = Stmt\Trait_[$3, ['stmts' => $5, 'attrGroups' => $1]]; } + | optional_attributes T_ENUM identifier_not_reserved enum_scalar_type implements_list '{' class_statement_list '}' + { $$ = Stmt\Enum_[$3, ['scalarType' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]]; + $this->checkEnum($$, #3); } +; + +enum_scalar_type: + /* empty */ { $$ = null; } + | ':' type { $$ = $2; } + +enum_case_expr: + /* empty */ { $$ = null; } + | '=' expr { $$ = $2; } +; + +class_entry_type: + T_CLASS { $$ = 0; } + | class_modifiers T_CLASS { $$ = $1; } +; + +class_modifiers: + class_modifier { $$ = $1; } + | class_modifiers class_modifier { $this->checkClassModifier($1, $2, #2); $$ = $1 | $2; } +; + +class_modifier: + T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } + | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } + | T_READONLY { $$ = Stmt\Class_::MODIFIER_READONLY; } +; + +extends_from: + /* empty */ { $$ = null; } + | T_EXTENDS class_name { $$ = $2; } +; + +interface_extends_list: + /* empty */ { $$ = array(); } + | T_EXTENDS class_name_list { $$ = $2; } +; + +implements_list: + /* empty */ { $$ = array(); } + | T_IMPLEMENTS class_name_list { $$ = $2; } +; + +class_name_list: + non_empty_class_name_list no_comma { $$ = $1; } +; + +non_empty_class_name_list: + class_name { init($1); } + | non_empty_class_name_list ',' class_name { push($1, $3); } +; + +for_statement: + statement { $$ = toArray($1); } + | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } +; + +foreach_statement: + statement { $$ = toArray($1); } + | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } +; + +declare_statement: + non_empty_statement { $$ = toArray($1); } + | ';' { $$ = null; } + | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } +; + +declare_list: + non_empty_declare_list no_comma { $$ = $1; } +; + +non_empty_declare_list: + declare_list_element { init($1); } + | non_empty_declare_list ',' declare_list_element { push($1, $3); } +; + +declare_list_element: + identifier_not_reserved '=' expr { $$ = Stmt\DeclareDeclare[$1, $3]; } +; + +switch_case_list: + '{' case_list '}' { $$ = $2; } + | '{' ';' case_list '}' { $$ = $3; } + | ':' case_list T_ENDSWITCH ';' { $$ = $2; } + | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } +; + +case_list: + /* empty */ { init(); } + | case_list case { push($1, $2); } +; + +case: + T_CASE expr case_separator inner_statement_list_ex { $$ = Stmt\Case_[$2, $4]; } + | T_DEFAULT case_separator inner_statement_list_ex { $$ = Stmt\Case_[null, $3]; } +; + +case_separator: + ':' + | ';' +; + +match: + T_MATCH '(' expr ')' '{' match_arm_list '}' { $$ = Expr\Match_[$3, $6]; } +; + +match_arm_list: + /* empty */ { $$ = []; } + | non_empty_match_arm_list optional_comma { $$ = $1; } +; + +non_empty_match_arm_list: + match_arm { init($1); } + | non_empty_match_arm_list ',' match_arm { push($1, $3); } +; + +match_arm: + expr_list_allow_comma T_DOUBLE_ARROW expr { $$ = Node\MatchArm[$1, $3]; } + | T_DEFAULT optional_comma T_DOUBLE_ARROW expr { $$ = Node\MatchArm[null, $4]; } +; + +while_statement: + statement { $$ = toArray($1); } + | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } +; + +elseif_list: + /* empty */ { init(); } + | elseif_list elseif { push($1, $2); } +; + +elseif: + T_ELSEIF '(' expr ')' statement { $$ = Stmt\ElseIf_[$3, toArray($5)]; } +; + +new_elseif_list: + /* empty */ { init(); } + | new_elseif_list new_elseif { push($1, $2); } +; + +new_elseif: + T_ELSEIF '(' expr ')' ':' inner_statement_list { $$ = Stmt\ElseIf_[$3, $6]; } +; + +else_single: + /* empty */ { $$ = null; } + | T_ELSE statement { $$ = Stmt\Else_[toArray($2)]; } +; + +new_else_single: + /* empty */ { $$ = null; } + | T_ELSE ':' inner_statement_list { $$ = Stmt\Else_[$3]; } +; + +foreach_variable: + variable { $$ = array($1, false); } + | ampersand variable { $$ = array($2, true); } + | list_expr { $$ = array($1, false); } + | array_short_syntax { $$ = array($1, false); } +; + +parameter_list: + non_empty_parameter_list optional_comma { $$ = $1; } + | /* empty */ { $$ = array(); } +; + +non_empty_parameter_list: + parameter { init($1); } + | non_empty_parameter_list ',' parameter { push($1, $3); } +; + +optional_property_modifiers: + /* empty */ { $$ = 0; } + | optional_property_modifiers property_modifier + { $this->checkModifier($1, $2, #2); $$ = $1 | $2; } +; + +property_modifier: + T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } + | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } + | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } + | T_READONLY { $$ = Stmt\Class_::MODIFIER_READONLY; } +; + +parameter: + optional_attributes optional_property_modifiers optional_type_without_static + optional_arg_ref optional_ellipsis plain_variable + { $$ = new Node\Param($6, null, $3, $4, $5, attributes(), $2, $1); + $this->checkParam($$); } + | optional_attributes optional_property_modifiers optional_type_without_static + optional_arg_ref optional_ellipsis plain_variable '=' expr + { $$ = new Node\Param($6, $8, $3, $4, $5, attributes(), $2, $1); + $this->checkParam($$); } + | optional_attributes optional_property_modifiers optional_type_without_static + optional_arg_ref optional_ellipsis error + { $$ = new Node\Param(Expr\Error[], null, $3, $4, $5, attributes(), $2, $1); } +; + +type_expr: + type { $$ = $1; } + | '?' type { $$ = Node\NullableType[$2]; } + | union_type { $$ = Node\UnionType[$1]; } + | intersection_type { $$ = $1; } +; + +type: + type_without_static { $$ = $1; } + | T_STATIC { $$ = Node\Name['static']; } +; + +type_without_static: + name { $$ = $this->handleBuiltinTypes($1); } + | T_ARRAY { $$ = Node\Identifier['array']; } + | T_CALLABLE { $$ = Node\Identifier['callable']; } +; + +union_type_element: + type { $$ = $1; } + | '(' intersection_type ')' { $$ = $2; } +; + +union_type: + union_type_element '|' union_type_element { init($1, $3); } + | union_type '|' union_type_element { push($1, $3); } +; + +union_type_without_static_element: + type_without_static { $$ = $1; } + | '(' intersection_type_without_static ')' { $$ = $2; } +; + +union_type_without_static: + union_type_without_static_element '|' union_type_without_static_element { init($1, $3); } + | union_type_without_static '|' union_type_without_static_element { push($1, $3); } +; + +intersection_type_list: + type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type { init($1, $3); } + | intersection_type_list T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type + { push($1, $3); } +; + +intersection_type: + intersection_type_list { $$ = Node\IntersectionType[$1]; } +; + +intersection_type_without_static_list: + type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static + { init($1, $3); } + | intersection_type_without_static_list T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static + { push($1, $3); } +; + +intersection_type_without_static: + intersection_type_without_static_list { $$ = Node\IntersectionType[$1]; } +; + +type_expr_without_static: + type_without_static { $$ = $1; } + | '?' type_without_static { $$ = Node\NullableType[$2]; } + | union_type_without_static { $$ = Node\UnionType[$1]; } + | intersection_type_without_static { $$ = $1; } +; + +optional_type_without_static: + /* empty */ { $$ = null; } + | type_expr_without_static { $$ = $1; } +; + +optional_return_type: + /* empty */ { $$ = null; } + | ':' type_expr { $$ = $2; } + | ':' error { $$ = null; } +; + +argument_list: + '(' ')' { $$ = array(); } + | '(' non_empty_argument_list optional_comma ')' { $$ = $2; } + | '(' variadic_placeholder ')' { init($2); } +; + +variadic_placeholder: + T_ELLIPSIS { $$ = Node\VariadicPlaceholder[]; } +; + +non_empty_argument_list: + argument { init($1); } + | non_empty_argument_list ',' argument { push($1, $3); } +; + +argument: + expr { $$ = Node\Arg[$1, false, false]; } + | ampersand variable { $$ = Node\Arg[$2, true, false]; } + | T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; } + | identifier_maybe_reserved ':' expr + { $$ = new Node\Arg($3, false, false, attributes(), $1); } +; + +global_var_list: + non_empty_global_var_list no_comma { $$ = $1; } +; + +non_empty_global_var_list: + non_empty_global_var_list ',' global_var { push($1, $3); } + | global_var { init($1); } +; + +global_var: + simple_variable { $$ = $1; } +; + +static_var_list: + non_empty_static_var_list no_comma { $$ = $1; } +; + +non_empty_static_var_list: + non_empty_static_var_list ',' static_var { push($1, $3); } + | static_var { init($1); } +; + +static_var: + plain_variable { $$ = Stmt\StaticVar[$1, null]; } + | plain_variable '=' expr { $$ = Stmt\StaticVar[$1, $3]; } +; + +class_statement_list_ex: + class_statement_list_ex class_statement { if ($2 !== null) { push($1, $2); } } + | /* empty */ { init(); } +; + +class_statement_list: + class_statement_list_ex + { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); + if ($nop !== null) { $1[] = $nop; } $$ = $1; } +; + +class_statement: + optional_attributes variable_modifiers optional_type_without_static property_declaration_list semi + { $$ = new Stmt\Property($2, $4, attributes(), $3, $1); + $this->checkProperty($$, #2); } + | optional_attributes method_modifiers T_CONST class_const_list semi + { $$ = new Stmt\ClassConst($4, $2, attributes(), $1); + $this->checkClassConst($$, #2); } + | optional_attributes method_modifiers T_FUNCTION optional_ref identifier_maybe_reserved '(' parameter_list ')' + optional_return_type method_body + { $$ = Stmt\ClassMethod[$5, ['type' => $2, 'byRef' => $4, 'params' => $7, 'returnType' => $9, 'stmts' => $10, 'attrGroups' => $1]]; + $this->checkClassMethod($$, #2); } + | T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; } + | optional_attributes T_CASE identifier_maybe_reserved enum_case_expr semi + { $$ = Stmt\EnumCase[$3, $4, $1]; } + | error { $$ = null; /* will be skipped */ } +; + +trait_adaptations: + ';' { $$ = array(); } + | '{' trait_adaptation_list '}' { $$ = $2; } +; + +trait_adaptation_list: + /* empty */ { init(); } + | trait_adaptation_list trait_adaptation { push($1, $2); } +; + +trait_adaptation: + trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';' + { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; } + | trait_method_reference T_AS member_modifier identifier_maybe_reserved ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; } + | trait_method_reference T_AS member_modifier ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; } + | trait_method_reference T_AS identifier_not_reserved ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } + | trait_method_reference T_AS reserved_non_modifiers_identifier ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } +; + +trait_method_reference_fully_qualified: + name T_PAAMAYIM_NEKUDOTAYIM identifier_maybe_reserved { $$ = array($1, $3); } +; +trait_method_reference: + trait_method_reference_fully_qualified { $$ = $1; } + | identifier_maybe_reserved { $$ = array(null, $1); } +; + +method_body: + ';' /* abstract method */ { $$ = null; } + | block_or_error { $$ = $1; } +; + +variable_modifiers: + non_empty_member_modifiers { $$ = $1; } + | T_VAR { $$ = 0; } +; + +method_modifiers: + /* empty */ { $$ = 0; } + | non_empty_member_modifiers { $$ = $1; } +; + +non_empty_member_modifiers: + member_modifier { $$ = $1; } + | non_empty_member_modifiers member_modifier { $this->checkModifier($1, $2, #2); $$ = $1 | $2; } +; + +member_modifier: + T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } + | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } + | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } + | T_STATIC { $$ = Stmt\Class_::MODIFIER_STATIC; } + | T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } + | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } + | T_READONLY { $$ = Stmt\Class_::MODIFIER_READONLY; } +; + +property_declaration_list: + non_empty_property_declaration_list no_comma { $$ = $1; } +; + +non_empty_property_declaration_list: + property_declaration { init($1); } + | non_empty_property_declaration_list ',' property_declaration + { push($1, $3); } +; + +property_decl_name: + T_VARIABLE { $$ = Node\VarLikeIdentifier[parseVar($1)]; } +; + +property_declaration: + property_decl_name { $$ = Stmt\PropertyProperty[$1, null]; } + | property_decl_name '=' expr { $$ = Stmt\PropertyProperty[$1, $3]; } +; + +expr_list_forbid_comma: + non_empty_expr_list no_comma { $$ = $1; } +; + +expr_list_allow_comma: + non_empty_expr_list optional_comma { $$ = $1; } +; + +non_empty_expr_list: + non_empty_expr_list ',' expr { push($1, $3); } + | expr { init($1); } +; + +for_expr: + /* empty */ { $$ = array(); } + | expr_list_forbid_comma { $$ = $1; } +; + +expr: + variable { $$ = $1; } + | list_expr '=' expr { $$ = Expr\Assign[$1, $3]; } + | array_short_syntax '=' expr { $$ = Expr\Assign[$1, $3]; } + | variable '=' expr { $$ = Expr\Assign[$1, $3]; } + | variable '=' ampersand variable { $$ = Expr\AssignRef[$1, $4]; } + | new_expr { $$ = $1; } + | match { $$ = $1; } + | T_CLONE expr { $$ = Expr\Clone_[$2]; } + | variable T_PLUS_EQUAL expr { $$ = Expr\AssignOp\Plus [$1, $3]; } + | variable T_MINUS_EQUAL expr { $$ = Expr\AssignOp\Minus [$1, $3]; } + | variable T_MUL_EQUAL expr { $$ = Expr\AssignOp\Mul [$1, $3]; } + | variable T_DIV_EQUAL expr { $$ = Expr\AssignOp\Div [$1, $3]; } + | variable T_CONCAT_EQUAL expr { $$ = Expr\AssignOp\Concat [$1, $3]; } + | variable T_MOD_EQUAL expr { $$ = Expr\AssignOp\Mod [$1, $3]; } + | variable T_AND_EQUAL expr { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; } + | variable T_OR_EQUAL expr { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; } + | variable T_XOR_EQUAL expr { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; } + | variable T_SL_EQUAL expr { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; } + | variable T_SR_EQUAL expr { $$ = Expr\AssignOp\ShiftRight[$1, $3]; } + | variable T_POW_EQUAL expr { $$ = Expr\AssignOp\Pow [$1, $3]; } + | variable T_COALESCE_EQUAL expr { $$ = Expr\AssignOp\Coalesce [$1, $3]; } + | variable T_INC { $$ = Expr\PostInc[$1]; } + | T_INC variable { $$ = Expr\PreInc [$2]; } + | variable T_DEC { $$ = Expr\PostDec[$1]; } + | T_DEC variable { $$ = Expr\PreDec [$2]; } + | expr T_BOOLEAN_OR expr { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } + | expr T_BOOLEAN_AND expr { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } + | expr T_LOGICAL_OR expr { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } + | expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } + | expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } + | expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } + | expr T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } + | expr T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } + | expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } + | expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; } + | expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; } + | expr '-' expr { $$ = Expr\BinaryOp\Minus [$1, $3]; } + | expr '*' expr { $$ = Expr\BinaryOp\Mul [$1, $3]; } + | expr '/' expr { $$ = Expr\BinaryOp\Div [$1, $3]; } + | expr '%' expr { $$ = Expr\BinaryOp\Mod [$1, $3]; } + | expr T_SL expr { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } + | expr T_SR expr { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } + | expr T_POW expr { $$ = Expr\BinaryOp\Pow [$1, $3]; } + | '+' expr %prec T_INC { $$ = Expr\UnaryPlus [$2]; } + | '-' expr %prec T_INC { $$ = Expr\UnaryMinus[$2]; } + | '!' expr { $$ = Expr\BooleanNot[$2]; } + | '~' expr { $$ = Expr\BitwiseNot[$2]; } + | expr T_IS_IDENTICAL expr { $$ = Expr\BinaryOp\Identical [$1, $3]; } + | expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } + | expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; } + | expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } + | expr T_SPACESHIP expr { $$ = Expr\BinaryOp\Spaceship [$1, $3]; } + | expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; } + | expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } + | expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; } + | expr T_IS_GREATER_OR_EQUAL expr { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } + | expr T_INSTANCEOF class_name_reference { $$ = Expr\Instanceof_[$1, $3]; } + | '(' expr ')' { $$ = $2; } + | expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; } + | expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; } + | expr T_COALESCE expr { $$ = Expr\BinaryOp\Coalesce[$1, $3]; } + | T_ISSET '(' expr_list_allow_comma ')' { $$ = Expr\Isset_[$3]; } + | T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; } + | T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; } + | T_INCLUDE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; } + | T_EVAL '(' expr ')' { $$ = Expr\Eval_[$3]; } + | T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; } + | T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; } + | T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; } + | T_DOUBLE_CAST expr + { $attrs = attributes(); + $attrs['kind'] = $this->getFloatCastKind($1); + $$ = new Expr\Cast\Double($2, $attrs); } + | T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; } + | T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; } + | T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; } + | T_BOOL_CAST expr { $$ = Expr\Cast\Bool_ [$2]; } + | T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; } + | T_EXIT exit_expr + { $attrs = attributes(); + $attrs['kind'] = strtolower($1) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; + $$ = new Expr\Exit_($2, $attrs); } + | '@' expr { $$ = Expr\ErrorSuppress[$2]; } + | scalar { $$ = $1; } + | '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; } + | T_PRINT expr { $$ = Expr\Print_[$2]; } + | T_YIELD { $$ = Expr\Yield_[null, null]; } + | T_YIELD expr { $$ = Expr\Yield_[$2, null]; } + | T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; } + | T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; } + | T_THROW expr { $$ = Expr\Throw_[$2]; } + + | T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW + { $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $2, 'params' => $4, 'returnType' => $6, 'expr' => $8, 'attrGroups' => []]]; } + | T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW + { $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9, 'attrGroups' => []]]; } + | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error + { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $8, 'attrGroups' => []]]; } + | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error + { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => []]]; } + + | attributes T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW + { $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9, 'attrGroups' => $1]]; } + | attributes T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW + { $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $4, 'params' => $6, 'returnType' => $8, 'expr' => $10, 'attrGroups' => $1]]; } + | attributes T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error + { $$ = Expr\Closure[['static' => false, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => $1]]; } + | attributes T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error + { $$ = Expr\Closure[['static' => true, 'byRef' => $4, 'params' => $6, 'uses' => $8, 'returnType' => $9, 'stmts' => $10, 'attrGroups' => $1]]; } +; + +anonymous_class: + optional_attributes T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}' + { $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]], $3); + $this->checkClass($$[0], -1); } +; + +new_expr: + T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; } + | T_NEW anonymous_class + { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; } +; + +lexical_vars: + /* empty */ { $$ = array(); } + | T_USE '(' lexical_var_list ')' { $$ = $3; } +; + +lexical_var_list: + non_empty_lexical_var_list optional_comma { $$ = $1; } +; + +non_empty_lexical_var_list: + lexical_var { init($1); } + | non_empty_lexical_var_list ',' lexical_var { push($1, $3); } +; + +lexical_var: + optional_ref plain_variable { $$ = Expr\ClosureUse[$2, $1]; } +; + +name_readonly: + T_READONLY { $$ = Name[$1]; } +; + +function_call: + name argument_list { $$ = Expr\FuncCall[$1, $2]; } + | name_readonly argument_list { $$ = Expr\FuncCall[$1, $2]; } + | callable_expr argument_list { $$ = Expr\FuncCall[$1, $2]; } + | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM member_name argument_list + { $$ = Expr\StaticCall[$1, $3, $4]; } +; + +class_name: + T_STATIC { $$ = Name[$1]; } + | name { $$ = $1; } +; + +name: + T_STRING { $$ = Name[$1]; } + | T_NAME_QUALIFIED { $$ = Name[$1]; } + | T_NAME_FULLY_QUALIFIED { $$ = Name\FullyQualified[substr($1, 1)]; } + | T_NAME_RELATIVE { $$ = Name\Relative[substr($1, 10)]; } +; + +class_name_reference: + class_name { $$ = $1; } + | new_variable { $$ = $1; } + | '(' expr ')' { $$ = $2; } + | error { $$ = Expr\Error[]; $this->errorState = 2; } +; + +class_name_or_var: + class_name { $$ = $1; } + | fully_dereferencable { $$ = $1; } +; + +exit_expr: + /* empty */ { $$ = null; } + | '(' optional_expr ')' { $$ = $2; } +; + +backticks_expr: + /* empty */ { $$ = array(); } + | T_ENCAPSED_AND_WHITESPACE + { $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`')]); } + | encaps_list { parseEncapsed($1, '`', true); $$ = $1; } +; + +ctor_arguments: + /* empty */ { $$ = array(); } + | argument_list { $$ = $1; } +; + +constant: + name { $$ = Expr\ConstFetch[$1]; } + | T_LINE { $$ = Scalar\MagicConst\Line[]; } + | T_FILE { $$ = Scalar\MagicConst\File[]; } + | T_DIR { $$ = Scalar\MagicConst\Dir[]; } + | T_CLASS_C { $$ = Scalar\MagicConst\Class_[]; } + | T_TRAIT_C { $$ = Scalar\MagicConst\Trait_[]; } + | T_METHOD_C { $$ = Scalar\MagicConst\Method[]; } + | T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; } + | T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; } +; + +class_constant: + class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_maybe_reserved + { $$ = Expr\ClassConstFetch[$1, $3]; } + /* We interpret an isolated FOO:: as an unfinished class constant fetch. It could also be + an unfinished static property fetch or unfinished scoped call. */ + | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM error + { $$ = Expr\ClassConstFetch[$1, new Expr\Error(stackAttributes(#3))]; $this->errorState = 2; } +; + +array_short_syntax: + '[' array_pair_list ']' + { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_SHORT; + $$ = new Expr\Array_($2, $attrs); } +; + +dereferencable_scalar: + T_ARRAY '(' array_pair_list ')' + { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG; + $$ = new Expr\Array_($3, $attrs); } + | array_short_syntax { $$ = $1; } + | T_CONSTANT_ENCAPSED_STRING { $$ = Scalar\String_::fromString($1, attributes()); } + | '"' encaps_list '"' + { $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; + parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); } +; + +scalar: + T_LNUMBER { $$ = $this->parseLNumber($1, attributes()); } + | T_DNUMBER { $$ = Scalar\DNumber::fromString($1, attributes()); } + | dereferencable_scalar { $$ = $1; } + | constant { $$ = $1; } + | class_constant { $$ = $1; } + | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC + { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); } + | T_START_HEREDOC T_END_HEREDOC + { $$ = $this->parseDocString($1, '', $2, attributes(), stackAttributes(#2), true); } + | T_START_HEREDOC encaps_list T_END_HEREDOC + { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); } +; + +optional_expr: + /* empty */ { $$ = null; } + | expr { $$ = $1; } +; + +fully_dereferencable: + variable { $$ = $1; } + | '(' expr ')' { $$ = $2; } + | dereferencable_scalar { $$ = $1; } + | class_constant { $$ = $1; } +; + +array_object_dereferencable: + fully_dereferencable { $$ = $1; } + | constant { $$ = $1; } +; + +callable_expr: + callable_variable { $$ = $1; } + | '(' expr ')' { $$ = $2; } + | dereferencable_scalar { $$ = $1; } +; + +callable_variable: + simple_variable { $$ = $1; } + | array_object_dereferencable '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | array_object_dereferencable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | function_call { $$ = $1; } + | array_object_dereferencable T_OBJECT_OPERATOR property_name argument_list + { $$ = Expr\MethodCall[$1, $3, $4]; } + | array_object_dereferencable T_NULLSAFE_OBJECT_OPERATOR property_name argument_list + { $$ = Expr\NullsafeMethodCall[$1, $3, $4]; } +; + +optional_plain_variable: + /* empty */ { $$ = null; } + | plain_variable { $$ = $1; } +; + +variable: + callable_variable { $$ = $1; } + | static_member { $$ = $1; } + | array_object_dereferencable T_OBJECT_OPERATOR property_name + { $$ = Expr\PropertyFetch[$1, $3]; } + | array_object_dereferencable T_NULLSAFE_OBJECT_OPERATOR property_name + { $$ = Expr\NullsafePropertyFetch[$1, $3]; } +; + +simple_variable: + plain_variable { $$ = $1; } + | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } + | '$' simple_variable { $$ = Expr\Variable[$2]; } + | '$' error { $$ = Expr\Variable[Expr\Error[]]; $this->errorState = 2; } +; + +static_member_prop_name: + simple_variable + { $var = $1->name; $$ = \is_string($var) ? Node\VarLikeIdentifier[$var] : $var; } +; + +static_member: + class_name_or_var T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name + { $$ = Expr\StaticPropertyFetch[$1, $3]; } +; + +new_variable: + simple_variable { $$ = $1; } + | new_variable '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | new_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | new_variable T_OBJECT_OPERATOR property_name { $$ = Expr\PropertyFetch[$1, $3]; } + | new_variable T_NULLSAFE_OBJECT_OPERATOR property_name { $$ = Expr\NullsafePropertyFetch[$1, $3]; } + | class_name T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name + { $$ = Expr\StaticPropertyFetch[$1, $3]; } + | new_variable T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name + { $$ = Expr\StaticPropertyFetch[$1, $3]; } +; + +member_name: + identifier_maybe_reserved { $$ = $1; } + | '{' expr '}' { $$ = $2; } + | simple_variable { $$ = $1; } +; + +property_name: + identifier_not_reserved { $$ = $1; } + | '{' expr '}' { $$ = $2; } + | simple_variable { $$ = $1; } + | error { $$ = Expr\Error[]; $this->errorState = 2; } +; + +list_expr: + T_LIST '(' inner_array_pair_list ')' { $$ = Expr\List_[$3]; } +; + +array_pair_list: + inner_array_pair_list + { $$ = $1; $end = count($$)-1; if ($$[$end] === null) array_pop($$); } +; + +comma_or_error: + ',' + | error + { /* do nothing -- prevent default action of $$=$1. See #551. */ } +; + +inner_array_pair_list: + inner_array_pair_list comma_or_error array_pair { push($1, $3); } + | array_pair { init($1); } +; + +array_pair: + expr { $$ = Expr\ArrayItem[$1, null, false]; } + | ampersand variable { $$ = Expr\ArrayItem[$2, null, true]; } + | list_expr { $$ = Expr\ArrayItem[$1, null, false]; } + | expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; } + | expr T_DOUBLE_ARROW ampersand variable { $$ = Expr\ArrayItem[$4, $1, true]; } + | expr T_DOUBLE_ARROW list_expr { $$ = Expr\ArrayItem[$3, $1, false]; } + | T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; } + | /* empty */ { $$ = null; } +; + +encaps_list: + encaps_list encaps_var { push($1, $2); } + | encaps_list encaps_string_part { push($1, $2); } + | encaps_var { init($1); } + | encaps_string_part encaps_var { init($1, $2); } +; + +encaps_string_part: + T_ENCAPSED_AND_WHITESPACE { $$ = Scalar\EncapsedStringPart[$1]; } +; + +encaps_str_varname: + T_STRING_VARNAME { $$ = Expr\Variable[$1]; } +; + +encaps_var: + plain_variable { $$ = $1; } + | plain_variable '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | plain_variable T_OBJECT_OPERATOR identifier_not_reserved + { $$ = Expr\PropertyFetch[$1, $3]; } + | plain_variable T_NULLSAFE_OBJECT_OPERATOR identifier_not_reserved + { $$ = Expr\NullsafePropertyFetch[$1, $3]; } + | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = Expr\Variable[$2]; } + | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' { $$ = Expr\Variable[$2]; } + | T_DOLLAR_OPEN_CURLY_BRACES encaps_str_varname '[' expr ']' '}' + { $$ = Expr\ArrayDimFetch[$2, $4]; } + | T_CURLY_OPEN variable '}' { $$ = $2; } +; + +encaps_var_offset: + T_STRING { $$ = Scalar\String_[$1]; } + | T_NUM_STRING { $$ = $this->parseNumString($1, attributes()); } + | '-' T_NUM_STRING { $$ = $this->parseNumString('-' . $2, attributes()); } + | plain_variable { $$ = $1; } +; + +%% diff --git a/vendor/nikic/php-parser/grammar/phpyLang.php b/vendor/nikic/php-parser/grammar/phpyLang.php new file mode 100644 index 00000000..663c2a14 --- /dev/null +++ b/vendor/nikic/php-parser/grammar/phpyLang.php @@ -0,0 +1,184 @@ +\'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\') + (?"[^\\\\"]*+(?:\\\\.[^\\\\"]*+)*+") + (?(?&singleQuotedString)|(?&doubleQuotedString)) + (?/\*[^*]*+(?:\*(?!/)[^*]*+)*+\*/) + (?\{[^\'"/{}]*+(?:(?:(?&string)|(?&comment)|(?&code)|/)[^\'"/{}]*+)*+}) +)'; + +const PARAMS = '\[(?[^[\]]*+(?:\[(?¶ms)\][^[\]]*+)*+)\]'; +const ARGS = '\((?[^()]*+(?:\((?&args)\)[^()]*+)*+)\)'; + +/////////////////////////////// +/// Preprocessing functions /// +/////////////////////////////// + +function preprocessGrammar($code) { + $code = resolveNodes($code); + $code = resolveMacros($code); + $code = resolveStackAccess($code); + + return $code; +} + +function resolveNodes($code) { + return preg_replace_callback( + '~\b(?[A-Z][a-zA-Z_\\\\]++)\s*' . PARAMS . '~', + function($matches) { + // recurse + $matches['params'] = resolveNodes($matches['params']); + + $params = magicSplit( + '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,', + $matches['params'] + ); + + $paramCode = ''; + foreach ($params as $param) { + $paramCode .= $param . ', '; + } + + return 'new ' . $matches['name'] . '(' . $paramCode . 'attributes())'; + }, + $code + ); +} + +function resolveMacros($code) { + return preg_replace_callback( + '~\b(?)(?!array\()(?[a-z][A-Za-z]++)' . ARGS . '~', + function($matches) { + // recurse + $matches['args'] = resolveMacros($matches['args']); + + $name = $matches['name']; + $args = magicSplit( + '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,', + $matches['args'] + ); + + if ('attributes' === $name) { + assertArgs(0, $args, $name); + return '$this->startAttributeStack[#1] + $this->endAttributes'; + } + + if ('stackAttributes' === $name) { + assertArgs(1, $args, $name); + return '$this->startAttributeStack[' . $args[0] . ']' + . ' + $this->endAttributeStack[' . $args[0] . ']'; + } + + if ('init' === $name) { + return '$$ = array(' . implode(', ', $args) . ')'; + } + + if ('push' === $name) { + assertArgs(2, $args, $name); + + return $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0]; + } + + if ('pushNormalizing' === $name) { + assertArgs(2, $args, $name); + + return 'if (is_array(' . $args[1] . ')) { $$ = array_merge(' . $args[0] . ', ' . $args[1] . '); }' + . ' else { ' . $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0] . '; }'; + } + + if ('toArray' == $name) { + assertArgs(1, $args, $name); + + return 'is_array(' . $args[0] . ') ? ' . $args[0] . ' : array(' . $args[0] . ')'; + } + + if ('parseVar' === $name) { + assertArgs(1, $args, $name); + + return 'substr(' . $args[0] . ', 1)'; + } + + if ('parseEncapsed' === $name) { + assertArgs(3, $args, $name); + + return 'foreach (' . $args[0] . ' as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) {' + . ' $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, ' . $args[1] . ', ' . $args[2] . '); } }'; + } + + if ('makeNop' === $name) { + assertArgs(3, $args, $name); + + return '$startAttributes = ' . $args[1] . ';' + . ' if (isset($startAttributes[\'comments\']))' + . ' { ' . $args[0] . ' = new Stmt\Nop($startAttributes + ' . $args[2] . '); }' + . ' else { ' . $args[0] . ' = null; }'; + } + + if ('makeZeroLengthNop' == $name) { + assertArgs(2, $args, $name); + + return '$startAttributes = ' . $args[1] . ';' + . ' if (isset($startAttributes[\'comments\']))' + . ' { ' . $args[0] . ' = new Stmt\Nop($this->createCommentNopAttributes($startAttributes[\'comments\'])); }' + . ' else { ' . $args[0] . ' = null; }'; + } + + if ('prependLeadingComments' === $name) { + assertArgs(1, $args, $name); + + return '$attrs = $this->startAttributeStack[#1]; $stmts = ' . $args[0] . '; ' + . 'if (!empty($attrs[\'comments\'])) {' + . '$stmts[0]->setAttribute(\'comments\', ' + . 'array_merge($attrs[\'comments\'], $stmts[0]->getAttribute(\'comments\', []))); }'; + } + + return $matches[0]; + }, + $code + ); +} + +function assertArgs($num, $args, $name) { + if ($num != count($args)) { + die('Wrong argument count for ' . $name . '().'); + } +} + +function resolveStackAccess($code) { + $code = preg_replace('/\$\d+/', '$this->semStack[$0]', $code); + $code = preg_replace('/#(\d+)/', '$$1', $code); + return $code; +} + +function removeTrailingWhitespace($code) { + $lines = explode("\n", $code); + $lines = array_map('rtrim', $lines); + return implode("\n", $lines); +} + +////////////////////////////// +/// Regex helper functions /// +////////////////////////////// + +function regex($regex) { + return '~' . LIB . '(?:' . str_replace('~', '\~', $regex) . ')~'; +} + +function magicSplit($regex, $string) { + $pieces = preg_split(regex('(?:(?&string)|(?&comment)|(?&code))(*SKIP)(*FAIL)|' . $regex), $string); + + foreach ($pieces as &$piece) { + $piece = trim($piece); + } + + if ($pieces === ['']) { + return []; + } + + return $pieces; +} diff --git a/vendor/nikic/php-parser/grammar/rebuildParsers.php b/vendor/nikic/php-parser/grammar/rebuildParsers.php new file mode 100644 index 00000000..2d0c6b14 --- /dev/null +++ b/vendor/nikic/php-parser/grammar/rebuildParsers.php @@ -0,0 +1,81 @@ + 'Php5', + __DIR__ . '/php7.y' => 'Php7', +]; + +$tokensFile = __DIR__ . '/tokens.y'; +$tokensTemplate = __DIR__ . '/tokens.template'; +$skeletonFile = __DIR__ . '/parser.template'; +$tmpGrammarFile = __DIR__ . '/tmp_parser.phpy'; +$tmpResultFile = __DIR__ . '/tmp_parser.php'; +$resultDir = __DIR__ . '/../lib/PhpParser/Parser'; +$tokensResultsFile = $resultDir . '/Tokens.php'; + +$kmyacc = getenv('KMYACC'); +if (!$kmyacc) { + // Use phpyacc from dev dependencies by default. + $kmyacc = __DIR__ . '/../vendor/bin/phpyacc'; +} + +$options = array_flip($argv); +$optionDebug = isset($options['--debug']); +$optionKeepTmpGrammar = isset($options['--keep-tmp-grammar']); + +/////////////////// +/// Main script /// +/////////////////// + +$tokens = file_get_contents($tokensFile); + +foreach ($grammarFileToName as $grammarFile => $name) { + echo "Building temporary $name grammar file.\n"; + + $grammarCode = file_get_contents($grammarFile); + $grammarCode = str_replace('%tokens', $tokens, $grammarCode); + $grammarCode = preprocessGrammar($grammarCode); + + file_put_contents($tmpGrammarFile, $grammarCode); + + $additionalArgs = $optionDebug ? '-t -v' : ''; + + echo "Building $name parser.\n"; + $output = execCmd("$kmyacc $additionalArgs -m $skeletonFile -p $name $tmpGrammarFile"); + + $resultCode = file_get_contents($tmpResultFile); + $resultCode = removeTrailingWhitespace($resultCode); + + ensureDirExists($resultDir); + file_put_contents("$resultDir/$name.php", $resultCode); + unlink($tmpResultFile); + + echo "Building token definition.\n"; + $output = execCmd("$kmyacc -m $tokensTemplate $tmpGrammarFile"); + rename($tmpResultFile, $tokensResultsFile); + + if (!$optionKeepTmpGrammar) { + unlink($tmpGrammarFile); + } +} + +//////////////////////////////// +/// Utility helper functions /// +//////////////////////////////// + +function ensureDirExists($dir) { + if (!is_dir($dir)) { + mkdir($dir, 0777, true); + } +} + +function execCmd($cmd) { + $output = trim(shell_exec("$cmd 2>&1")); + if ($output !== "") { + echo "> " . $cmd . "\n"; + echo $output; + } + return $output; +} diff --git a/vendor/nikic/php-parser/grammar/tokens.template b/vendor/nikic/php-parser/grammar/tokens.template new file mode 100644 index 00000000..ba4e4901 --- /dev/null +++ b/vendor/nikic/php-parser/grammar/tokens.template @@ -0,0 +1,17 @@ +semValue +#semval($,%t) $this->semValue +#semval(%n) $this->stackPos-(%l-%n) +#semval(%n,%t) $this->stackPos-(%l-%n) + +namespace PhpParser\Parser; +#include; + +/* GENERATED file based on grammar/tokens.y */ +final class Tokens +{ +#tokenval + const %s = %n; +#endtokenval +} diff --git a/vendor/nikic/php-parser/grammar/tokens.y b/vendor/nikic/php-parser/grammar/tokens.y new file mode 100644 index 00000000..8f0b2172 --- /dev/null +++ b/vendor/nikic/php-parser/grammar/tokens.y @@ -0,0 +1,115 @@ +/* We currently rely on the token ID mapping to be the same between PHP 5 and PHP 7 - so the same lexer can be used for + * both. This is enforced by sharing this token file. */ + +%right T_THROW +%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE +%left ',' +%left T_LOGICAL_OR +%left T_LOGICAL_XOR +%left T_LOGICAL_AND +%right T_PRINT +%right T_YIELD +%right T_DOUBLE_ARROW +%right T_YIELD_FROM +%left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL T_COALESCE_EQUAL +%left '?' ':' +%right T_COALESCE +%left T_BOOLEAN_OR +%left T_BOOLEAN_AND +%left '|' +%left '^' +%left T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG +%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP +%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL +%left T_SL T_SR +%left '+' '-' '.' +%left '*' '/' '%' +%right '!' +%nonassoc T_INSTANCEOF +%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@' +%right T_POW +%right '[' +%nonassoc T_NEW T_CLONE +%token T_EXIT +%token T_IF +%left T_ELSEIF +%left T_ELSE +%left T_ENDIF +%token T_LNUMBER +%token T_DNUMBER +%token T_STRING +%token T_STRING_VARNAME +%token T_VARIABLE +%token T_NUM_STRING +%token T_INLINE_HTML +%token T_ENCAPSED_AND_WHITESPACE +%token T_CONSTANT_ENCAPSED_STRING +%token T_ECHO +%token T_DO +%token T_WHILE +%token T_ENDWHILE +%token T_FOR +%token T_ENDFOR +%token T_FOREACH +%token T_ENDFOREACH +%token T_DECLARE +%token T_ENDDECLARE +%token T_AS +%token T_SWITCH +%token T_MATCH +%token T_ENDSWITCH +%token T_CASE +%token T_DEFAULT +%token T_BREAK +%token T_CONTINUE +%token T_GOTO +%token T_FUNCTION +%token T_FN +%token T_CONST +%token T_RETURN +%token T_TRY +%token T_CATCH +%token T_FINALLY +%token T_THROW +%token T_USE +%token T_INSTEADOF +%token T_GLOBAL +%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC T_READONLY +%token T_VAR +%token T_UNSET +%token T_ISSET +%token T_EMPTY +%token T_HALT_COMPILER +%token T_CLASS +%token T_TRAIT +%token T_INTERFACE +%token T_ENUM +%token T_EXTENDS +%token T_IMPLEMENTS +%token T_OBJECT_OPERATOR +%token T_NULLSAFE_OBJECT_OPERATOR +%token T_DOUBLE_ARROW +%token T_LIST +%token T_ARRAY +%token T_CALLABLE +%token T_CLASS_C +%token T_TRAIT_C +%token T_METHOD_C +%token T_FUNC_C +%token T_LINE +%token T_FILE +%token T_START_HEREDOC +%token T_END_HEREDOC +%token T_DOLLAR_OPEN_CURLY_BRACES +%token T_CURLY_OPEN +%token T_PAAMAYIM_NEKUDOTAYIM +%token T_NAMESPACE +%token T_NS_C +%token T_DIR +%token T_NS_SEPARATOR +%token T_ELLIPSIS +%token T_NAME_FULLY_QUALIFIED +%token T_NAME_QUALIFIED +%token T_NAME_RELATIVE +%token T_ATTRIBUTE +%token T_ENUM diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder.php b/vendor/nikic/php-parser/lib/PhpParser/Builder.php new file mode 100644 index 00000000..26d8921e --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder.php @@ -0,0 +1,13 @@ +constants = [new Const_($name, BuilderHelpers::normalizeValue($value))]; + } + + /** + * Add another constant to const group + * + * @param string|Identifier $name Name + * @param Node\Expr|bool|null|int|float|string|array $value Value + * + * @return $this The builder instance (for fluid interface) + */ + public function addConst($name, $value) { + $this->constants[] = new Const_($name, BuilderHelpers::normalizeValue($value)); + + return $this; + } + + /** + * Makes the constant public. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePublic() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC); + + return $this; + } + + /** + * Makes the constant protected. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeProtected() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED); + + return $this; + } + + /** + * Makes the constant private. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePrivate() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE); + + return $this; + } + + /** + * Makes the constant final. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeFinal() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL); + + return $this; + } + + /** + * Sets doc comment for the constant. + * + * @param PhpParser\Comment\Doc|string $docComment Doc comment to set + * + * @return $this The builder instance (for fluid interface) + */ + public function setDocComment($docComment) { + $this->attributes = [ + 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] + ]; + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built class node. + * + * @return Stmt\ClassConst The built constant node + */ + public function getNode(): PhpParser\Node { + return new Stmt\ClassConst( + $this->constants, + $this->flags, + $this->attributes, + $this->attributeGroups + ); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.php new file mode 100644 index 00000000..35b54d04 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.php @@ -0,0 +1,146 @@ +name = $name; + } + + /** + * Extends a class. + * + * @param Name|string $class Name of class to extend + * + * @return $this The builder instance (for fluid interface) + */ + public function extend($class) { + $this->extends = BuilderHelpers::normalizeName($class); + + return $this; + } + + /** + * Implements one or more interfaces. + * + * @param Name|string ...$interfaces Names of interfaces to implement + * + * @return $this The builder instance (for fluid interface) + */ + public function implement(...$interfaces) { + foreach ($interfaces as $interface) { + $this->implements[] = BuilderHelpers::normalizeName($interface); + } + + return $this; + } + + /** + * Makes the class abstract. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeAbstract() { + $this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT); + + return $this; + } + + /** + * Makes the class final. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeFinal() { + $this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_FINAL); + + return $this; + } + + public function makeReadonly() { + $this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_READONLY); + + return $this; + } + + /** + * Adds a statement. + * + * @param Stmt|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $stmt = BuilderHelpers::normalizeNode($stmt); + + $targets = [ + Stmt\TraitUse::class => &$this->uses, + Stmt\ClassConst::class => &$this->constants, + Stmt\Property::class => &$this->properties, + Stmt\ClassMethod::class => &$this->methods, + ]; + + $class = \get_class($stmt); + if (!isset($targets[$class])) { + throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); + } + + $targets[$class][] = $stmt; + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built class node. + * + * @return Stmt\Class_ The built class node + */ + public function getNode() : PhpParser\Node { + return new Stmt\Class_($this->name, [ + 'flags' => $this->flags, + 'extends' => $this->extends, + 'implements' => $this->implements, + 'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods), + 'attrGroups' => $this->attributeGroups, + ], $this->attributes); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php new file mode 100644 index 00000000..83094992 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php @@ -0,0 +1,43 @@ +addStmt($stmt); + } + + return $this; + } + + /** + * Sets doc comment for the declaration. + * + * @param PhpParser\Comment\Doc|string $docComment Doc comment to set + * + * @return $this The builder instance (for fluid interface) + */ + public function setDocComment($docComment) { + $this->attributes['comments'] = [ + BuilderHelpers::normalizeDocComment($docComment) + ]; + + return $this; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php new file mode 100644 index 00000000..accc5166 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php @@ -0,0 +1,85 @@ +name = $name; + } + + /** + * Sets the value. + * + * @param Node\Expr|string|int $value + * + * @return $this + */ + public function setValue($value) { + $this->value = BuilderHelpers::normalizeValue($value); + + return $this; + } + + /** + * Sets doc comment for the constant. + * + * @param PhpParser\Comment\Doc|string $docComment Doc comment to set + * + * @return $this The builder instance (for fluid interface) + */ + public function setDocComment($docComment) { + $this->attributes = [ + 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] + ]; + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built enum case node. + * + * @return Stmt\EnumCase The built constant node + */ + public function getNode(): PhpParser\Node { + return new Stmt\EnumCase( + $this->name, + $this->value, + $this->attributeGroups, + $this->attributes + ); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Enum_.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Enum_.php new file mode 100644 index 00000000..be7eef95 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Enum_.php @@ -0,0 +1,117 @@ +name = $name; + } + + /** + * Sets the scalar type. + * + * @param string|Identifier $type + * + * @return $this + */ + public function setScalarType($scalarType) { + $this->scalarType = BuilderHelpers::normalizeType($scalarType); + + return $this; + } + + /** + * Implements one or more interfaces. + * + * @param Name|string ...$interfaces Names of interfaces to implement + * + * @return $this The builder instance (for fluid interface) + */ + public function implement(...$interfaces) { + foreach ($interfaces as $interface) { + $this->implements[] = BuilderHelpers::normalizeName($interface); + } + + return $this; + } + + /** + * Adds a statement. + * + * @param Stmt|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $stmt = BuilderHelpers::normalizeNode($stmt); + + $targets = [ + Stmt\TraitUse::class => &$this->uses, + Stmt\EnumCase::class => &$this->enumCases, + Stmt\ClassConst::class => &$this->constants, + Stmt\ClassMethod::class => &$this->methods, + ]; + + $class = \get_class($stmt); + if (!isset($targets[$class])) { + throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); + } + + $targets[$class][] = $stmt; + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built class node. + * + * @return Stmt\Enum_ The built enum node + */ + public function getNode() : PhpParser\Node { + return new Stmt\Enum_($this->name, [ + 'scalarType' => $this->scalarType, + 'implements' => $this->implements, + 'stmts' => array_merge($this->uses, $this->enumCases, $this->constants, $this->methods), + 'attrGroups' => $this->attributeGroups, + ], $this->attributes); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php new file mode 100644 index 00000000..98ea9d33 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php @@ -0,0 +1,73 @@ +returnByRef = true; + + return $this; + } + + /** + * Adds a parameter. + * + * @param Node\Param|Param $param The parameter to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addParam($param) { + $param = BuilderHelpers::normalizeNode($param); + + if (!$param instanceof Node\Param) { + throw new \LogicException(sprintf('Expected parameter node, got "%s"', $param->getType())); + } + + $this->params[] = $param; + + return $this; + } + + /** + * Adds multiple parameters. + * + * @param array $params The parameters to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addParams(array $params) { + foreach ($params as $param) { + $this->addParam($param); + } + + return $this; + } + + /** + * Sets the return type for PHP 7. + * + * @param string|Node\Name|Node\Identifier|Node\ComplexType $type + * + * @return $this The builder instance (for fluid interface) + */ + public function setReturnType($type) { + $this->returnType = BuilderHelpers::normalizeType($type); + + return $this; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php new file mode 100644 index 00000000..1cd73c0d --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php @@ -0,0 +1,67 @@ +name = $name; + } + + /** + * Adds a statement. + * + * @param Node|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built function node. + * + * @return Stmt\Function_ The built function node + */ + public function getNode() : Node { + return new Stmt\Function_($this->name, [ + 'byRef' => $this->returnByRef, + 'params' => $this->params, + 'returnType' => $this->returnType, + 'stmts' => $this->stmts, + 'attrGroups' => $this->attributeGroups, + ], $this->attributes); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php new file mode 100644 index 00000000..7806e85f --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php @@ -0,0 +1,93 @@ +name = $name; + } + + /** + * Extends one or more interfaces. + * + * @param Name|string ...$interfaces Names of interfaces to extend + * + * @return $this The builder instance (for fluid interface) + */ + public function extend(...$interfaces) { + foreach ($interfaces as $interface) { + $this->extends[] = BuilderHelpers::normalizeName($interface); + } + + return $this; + } + + /** + * Adds a statement. + * + * @param Stmt|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $stmt = BuilderHelpers::normalizeNode($stmt); + + if ($stmt instanceof Stmt\ClassConst) { + $this->constants[] = $stmt; + } elseif ($stmt instanceof Stmt\ClassMethod) { + // we erase all statements in the body of an interface method + $stmt->stmts = null; + $this->methods[] = $stmt; + } else { + throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); + } + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built interface node. + * + * @return Stmt\Interface_ The built interface node + */ + public function getNode() : PhpParser\Node { + return new Stmt\Interface_($this->name, [ + 'extends' => $this->extends, + 'stmts' => array_merge($this->constants, $this->methods), + 'attrGroups' => $this->attributeGroups, + ], $this->attributes); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php new file mode 100644 index 00000000..232d7cb8 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php @@ -0,0 +1,146 @@ +name = $name; + } + + /** + * Makes the method public. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePublic() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC); + + return $this; + } + + /** + * Makes the method protected. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeProtected() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED); + + return $this; + } + + /** + * Makes the method private. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePrivate() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE); + + return $this; + } + + /** + * Makes the method static. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeStatic() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_STATIC); + + return $this; + } + + /** + * Makes the method abstract. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeAbstract() { + if (!empty($this->stmts)) { + throw new \LogicException('Cannot make method with statements abstract'); + } + + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT); + $this->stmts = null; // abstract methods don't have statements + + return $this; + } + + /** + * Makes the method final. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeFinal() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL); + + return $this; + } + + /** + * Adds a statement. + * + * @param Node|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + if (null === $this->stmts) { + throw new \LogicException('Cannot add statements to an abstract method'); + } + + $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built method node. + * + * @return Stmt\ClassMethod The built method node + */ + public function getNode() : Node { + return new Stmt\ClassMethod($this->name, [ + 'flags' => $this->flags, + 'byRef' => $this->returnByRef, + 'params' => $this->params, + 'returnType' => $this->returnType, + 'stmts' => $this->stmts, + 'attrGroups' => $this->attributeGroups, + ], $this->attributes); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php new file mode 100644 index 00000000..1c751e16 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php @@ -0,0 +1,45 @@ +name = null !== $name ? BuilderHelpers::normalizeName($name) : null; + } + + /** + * Adds a statement. + * + * @param Node|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); + + return $this; + } + + /** + * Returns the built node. + * + * @return Stmt\Namespace_ The built node + */ + public function getNode() : Node { + return new Stmt\Namespace_($this->name, $this->stmts, $this->attributes); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php new file mode 100644 index 00000000..de9aae7e --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php @@ -0,0 +1,122 @@ +name = $name; + } + + /** + * Sets default value for the parameter. + * + * @param mixed $value Default value to use + * + * @return $this The builder instance (for fluid interface) + */ + public function setDefault($value) { + $this->default = BuilderHelpers::normalizeValue($value); + + return $this; + } + + /** + * Sets type for the parameter. + * + * @param string|Node\Name|Node\Identifier|Node\ComplexType $type Parameter type + * + * @return $this The builder instance (for fluid interface) + */ + public function setType($type) { + $this->type = BuilderHelpers::normalizeType($type); + if ($this->type == 'void') { + throw new \LogicException('Parameter type cannot be void'); + } + + return $this; + } + + /** + * Sets type for the parameter. + * + * @param string|Node\Name|Node\Identifier|Node\ComplexType $type Parameter type + * + * @return $this The builder instance (for fluid interface) + * + * @deprecated Use setType() instead + */ + public function setTypeHint($type) { + return $this->setType($type); + } + + /** + * Make the parameter accept the value by reference. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeByRef() { + $this->byRef = true; + + return $this; + } + + /** + * Make the parameter variadic + * + * @return $this The builder instance (for fluid interface) + */ + public function makeVariadic() { + $this->variadic = true; + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built parameter node. + * + * @return Node\Param The built parameter node + */ + public function getNode() : Node { + return new Node\Param( + new Node\Expr\Variable($this->name), + $this->default, $this->type, $this->byRef, $this->variadic, [], 0, $this->attributeGroups + ); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php new file mode 100644 index 00000000..68e31856 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php @@ -0,0 +1,161 @@ +name = $name; + } + + /** + * Makes the property public. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePublic() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC); + + return $this; + } + + /** + * Makes the property protected. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeProtected() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED); + + return $this; + } + + /** + * Makes the property private. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePrivate() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE); + + return $this; + } + + /** + * Makes the property static. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeStatic() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_STATIC); + + return $this; + } + + /** + * Makes the property readonly. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeReadonly() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_READONLY); + + return $this; + } + + /** + * Sets default value for the property. + * + * @param mixed $value Default value to use + * + * @return $this The builder instance (for fluid interface) + */ + public function setDefault($value) { + $this->default = BuilderHelpers::normalizeValue($value); + + return $this; + } + + /** + * Sets doc comment for the property. + * + * @param PhpParser\Comment\Doc|string $docComment Doc comment to set + * + * @return $this The builder instance (for fluid interface) + */ + public function setDocComment($docComment) { + $this->attributes = [ + 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] + ]; + + return $this; + } + + /** + * Sets the property type for PHP 7.4+. + * + * @param string|Name|Identifier|ComplexType $type + * + * @return $this + */ + public function setType($type) { + $this->type = BuilderHelpers::normalizeType($type); + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built class node. + * + * @return Stmt\Property The built property node + */ + public function getNode() : PhpParser\Node { + return new Stmt\Property( + $this->flags !== 0 ? $this->flags : Stmt\Class_::MODIFIER_PUBLIC, + [ + new Stmt\PropertyProperty($this->name, $this->default) + ], + $this->attributes, + $this->type, + $this->attributeGroups + ); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php new file mode 100644 index 00000000..311e8cd7 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php @@ -0,0 +1,64 @@ +and($trait); + } + } + + /** + * Adds used trait. + * + * @param Node\Name|string $trait Trait name + * + * @return $this The builder instance (for fluid interface) + */ + public function and($trait) { + $this->traits[] = BuilderHelpers::normalizeName($trait); + return $this; + } + + /** + * Adds trait adaptation. + * + * @param Stmt\TraitUseAdaptation|Builder\TraitUseAdaptation $adaptation Trait adaptation + * + * @return $this The builder instance (for fluid interface) + */ + public function with($adaptation) { + $adaptation = BuilderHelpers::normalizeNode($adaptation); + + if (!$adaptation instanceof Stmt\TraitUseAdaptation) { + throw new \LogicException('Adaptation must have type TraitUseAdaptation'); + } + + $this->adaptations[] = $adaptation; + return $this; + } + + /** + * Returns the built node. + * + * @return Node The built node + */ + public function getNode() : Node { + return new Stmt\TraitUse($this->traits, $this->adaptations); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php new file mode 100644 index 00000000..eb6c0b62 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php @@ -0,0 +1,148 @@ +type = self::TYPE_UNDEFINED; + + $this->trait = is_null($trait)? null: BuilderHelpers::normalizeName($trait); + $this->method = BuilderHelpers::normalizeIdentifier($method); + } + + /** + * Sets alias of method. + * + * @param Node\Identifier|string $alias Alias for adaptated method + * + * @return $this The builder instance (for fluid interface) + */ + public function as($alias) { + if ($this->type === self::TYPE_UNDEFINED) { + $this->type = self::TYPE_ALIAS; + } + + if ($this->type !== self::TYPE_ALIAS) { + throw new \LogicException('Cannot set alias for not alias adaptation buider'); + } + + $this->alias = $alias; + return $this; + } + + /** + * Sets adaptated method public. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePublic() { + $this->setModifier(Stmt\Class_::MODIFIER_PUBLIC); + return $this; + } + + /** + * Sets adaptated method protected. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeProtected() { + $this->setModifier(Stmt\Class_::MODIFIER_PROTECTED); + return $this; + } + + /** + * Sets adaptated method private. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePrivate() { + $this->setModifier(Stmt\Class_::MODIFIER_PRIVATE); + return $this; + } + + /** + * Adds overwritten traits. + * + * @param Node\Name|string ...$traits Traits for overwrite + * + * @return $this The builder instance (for fluid interface) + */ + public function insteadof(...$traits) { + if ($this->type === self::TYPE_UNDEFINED) { + if (is_null($this->trait)) { + throw new \LogicException('Precedence adaptation must have trait'); + } + + $this->type = self::TYPE_PRECEDENCE; + } + + if ($this->type !== self::TYPE_PRECEDENCE) { + throw new \LogicException('Cannot add overwritten traits for not precedence adaptation buider'); + } + + foreach ($traits as $trait) { + $this->insteadof[] = BuilderHelpers::normalizeName($trait); + } + + return $this; + } + + protected function setModifier(int $modifier) { + if ($this->type === self::TYPE_UNDEFINED) { + $this->type = self::TYPE_ALIAS; + } + + if ($this->type !== self::TYPE_ALIAS) { + throw new \LogicException('Cannot set access modifier for not alias adaptation buider'); + } + + if (is_null($this->modifier)) { + $this->modifier = $modifier; + } else { + throw new \LogicException('Multiple access type modifiers are not allowed'); + } + } + + /** + * Returns the built node. + * + * @return Node The built node + */ + public function getNode() : Node { + switch ($this->type) { + case self::TYPE_ALIAS: + return new Stmt\TraitUseAdaptation\Alias($this->trait, $this->method, $this->modifier, $this->alias); + case self::TYPE_PRECEDENCE: + return new Stmt\TraitUseAdaptation\Precedence($this->trait, $this->method, $this->insteadof); + default: + throw new \LogicException('Type of adaptation is not defined'); + } + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php new file mode 100644 index 00000000..97f32f98 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php @@ -0,0 +1,78 @@ +name = $name; + } + + /** + * Adds a statement. + * + * @param Stmt|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $stmt = BuilderHelpers::normalizeNode($stmt); + + if ($stmt instanceof Stmt\Property) { + $this->properties[] = $stmt; + } elseif ($stmt instanceof Stmt\ClassMethod) { + $this->methods[] = $stmt; + } elseif ($stmt instanceof Stmt\TraitUse) { + $this->uses[] = $stmt; + } else { + throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); + } + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built trait node. + * + * @return Stmt\Trait_ The built interface node + */ + public function getNode() : PhpParser\Node { + return new Stmt\Trait_( + $this->name, [ + 'stmts' => array_merge($this->uses, $this->properties, $this->methods), + 'attrGroups' => $this->attributeGroups, + ], $this->attributes + ); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php b/vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php new file mode 100644 index 00000000..4bd3d12d --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php @@ -0,0 +1,49 @@ +name = BuilderHelpers::normalizeName($name); + $this->type = $type; + } + + /** + * Sets alias for used name. + * + * @param string $alias Alias to use (last component of full name by default) + * + * @return $this The builder instance (for fluid interface) + */ + public function as(string $alias) { + $this->alias = $alias; + return $this; + } + + /** + * Returns the built node. + * + * @return Stmt\Use_ The built node + */ + public function getNode() : Node { + return new Stmt\Use_([ + new Stmt\UseUse($this->name, $this->alias) + ], $this->type); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php b/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php new file mode 100644 index 00000000..fef2579b --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php @@ -0,0 +1,399 @@ +args($args) + ); + } + + /** + * Creates a namespace builder. + * + * @param null|string|Node\Name $name Name of the namespace + * + * @return Builder\Namespace_ The created namespace builder + */ + public function namespace($name) : Builder\Namespace_ { + return new Builder\Namespace_($name); + } + + /** + * Creates a class builder. + * + * @param string $name Name of the class + * + * @return Builder\Class_ The created class builder + */ + public function class(string $name) : Builder\Class_ { + return new Builder\Class_($name); + } + + /** + * Creates an interface builder. + * + * @param string $name Name of the interface + * + * @return Builder\Interface_ The created interface builder + */ + public function interface(string $name) : Builder\Interface_ { + return new Builder\Interface_($name); + } + + /** + * Creates a trait builder. + * + * @param string $name Name of the trait + * + * @return Builder\Trait_ The created trait builder + */ + public function trait(string $name) : Builder\Trait_ { + return new Builder\Trait_($name); + } + + /** + * Creates an enum builder. + * + * @param string $name Name of the enum + * + * @return Builder\Enum_ The created enum builder + */ + public function enum(string $name) : Builder\Enum_ { + return new Builder\Enum_($name); + } + + /** + * Creates a trait use builder. + * + * @param Node\Name|string ...$traits Trait names + * + * @return Builder\TraitUse The create trait use builder + */ + public function useTrait(...$traits) : Builder\TraitUse { + return new Builder\TraitUse(...$traits); + } + + /** + * Creates a trait use adaptation builder. + * + * @param Node\Name|string|null $trait Trait name + * @param Node\Identifier|string $method Method name + * + * @return Builder\TraitUseAdaptation The create trait use adaptation builder + */ + public function traitUseAdaptation($trait, $method = null) : Builder\TraitUseAdaptation { + if ($method === null) { + $method = $trait; + $trait = null; + } + + return new Builder\TraitUseAdaptation($trait, $method); + } + + /** + * Creates a method builder. + * + * @param string $name Name of the method + * + * @return Builder\Method The created method builder + */ + public function method(string $name) : Builder\Method { + return new Builder\Method($name); + } + + /** + * Creates a parameter builder. + * + * @param string $name Name of the parameter + * + * @return Builder\Param The created parameter builder + */ + public function param(string $name) : Builder\Param { + return new Builder\Param($name); + } + + /** + * Creates a property builder. + * + * @param string $name Name of the property + * + * @return Builder\Property The created property builder + */ + public function property(string $name) : Builder\Property { + return new Builder\Property($name); + } + + /** + * Creates a function builder. + * + * @param string $name Name of the function + * + * @return Builder\Function_ The created function builder + */ + public function function(string $name) : Builder\Function_ { + return new Builder\Function_($name); + } + + /** + * Creates a namespace/class use builder. + * + * @param Node\Name|string $name Name of the entity (namespace or class) to alias + * + * @return Builder\Use_ The created use builder + */ + public function use($name) : Builder\Use_ { + return new Builder\Use_($name, Use_::TYPE_NORMAL); + } + + /** + * Creates a function use builder. + * + * @param Node\Name|string $name Name of the function to alias + * + * @return Builder\Use_ The created use function builder + */ + public function useFunction($name) : Builder\Use_ { + return new Builder\Use_($name, Use_::TYPE_FUNCTION); + } + + /** + * Creates a constant use builder. + * + * @param Node\Name|string $name Name of the const to alias + * + * @return Builder\Use_ The created use const builder + */ + public function useConst($name) : Builder\Use_ { + return new Builder\Use_($name, Use_::TYPE_CONSTANT); + } + + /** + * Creates a class constant builder. + * + * @param string|Identifier $name Name + * @param Node\Expr|bool|null|int|float|string|array $value Value + * + * @return Builder\ClassConst The created use const builder + */ + public function classConst($name, $value) : Builder\ClassConst { + return new Builder\ClassConst($name, $value); + } + + /** + * Creates an enum case builder. + * + * @param string|Identifier $name Name + * + * @return Builder\EnumCase The created use const builder + */ + public function enumCase($name) : Builder\EnumCase { + return new Builder\EnumCase($name); + } + + /** + * Creates node a for a literal value. + * + * @param Expr|bool|null|int|float|string|array $value $value + * + * @return Expr + */ + public function val($value) : Expr { + return BuilderHelpers::normalizeValue($value); + } + + /** + * Creates variable node. + * + * @param string|Expr $name Name + * + * @return Expr\Variable + */ + public function var($name) : Expr\Variable { + if (!\is_string($name) && !$name instanceof Expr) { + throw new \LogicException('Variable name must be string or Expr'); + } + + return new Expr\Variable($name); + } + + /** + * Normalizes an argument list. + * + * Creates Arg nodes for all arguments and converts literal values to expressions. + * + * @param array $args List of arguments to normalize + * + * @return Arg[] + */ + public function args(array $args) : array { + $normalizedArgs = []; + foreach ($args as $key => $arg) { + if (!($arg instanceof Arg)) { + $arg = new Arg(BuilderHelpers::normalizeValue($arg)); + } + if (\is_string($key)) { + $arg->name = BuilderHelpers::normalizeIdentifier($key); + } + $normalizedArgs[] = $arg; + } + return $normalizedArgs; + } + + /** + * Creates a function call node. + * + * @param string|Name|Expr $name Function name + * @param array $args Function arguments + * + * @return Expr\FuncCall + */ + public function funcCall($name, array $args = []) : Expr\FuncCall { + return new Expr\FuncCall( + BuilderHelpers::normalizeNameOrExpr($name), + $this->args($args) + ); + } + + /** + * Creates a method call node. + * + * @param Expr $var Variable the method is called on + * @param string|Identifier|Expr $name Method name + * @param array $args Method arguments + * + * @return Expr\MethodCall + */ + public function methodCall(Expr $var, $name, array $args = []) : Expr\MethodCall { + return new Expr\MethodCall( + $var, + BuilderHelpers::normalizeIdentifierOrExpr($name), + $this->args($args) + ); + } + + /** + * Creates a static method call node. + * + * @param string|Name|Expr $class Class name + * @param string|Identifier|Expr $name Method name + * @param array $args Method arguments + * + * @return Expr\StaticCall + */ + public function staticCall($class, $name, array $args = []) : Expr\StaticCall { + return new Expr\StaticCall( + BuilderHelpers::normalizeNameOrExpr($class), + BuilderHelpers::normalizeIdentifierOrExpr($name), + $this->args($args) + ); + } + + /** + * Creates an object creation node. + * + * @param string|Name|Expr $class Class name + * @param array $args Constructor arguments + * + * @return Expr\New_ + */ + public function new($class, array $args = []) : Expr\New_ { + return new Expr\New_( + BuilderHelpers::normalizeNameOrExpr($class), + $this->args($args) + ); + } + + /** + * Creates a constant fetch node. + * + * @param string|Name $name Constant name + * + * @return Expr\ConstFetch + */ + public function constFetch($name) : Expr\ConstFetch { + return new Expr\ConstFetch(BuilderHelpers::normalizeName($name)); + } + + /** + * Creates a property fetch node. + * + * @param Expr $var Variable holding object + * @param string|Identifier|Expr $name Property name + * + * @return Expr\PropertyFetch + */ + public function propertyFetch(Expr $var, $name) : Expr\PropertyFetch { + return new Expr\PropertyFetch($var, BuilderHelpers::normalizeIdentifierOrExpr($name)); + } + + /** + * Creates a class constant fetch node. + * + * @param string|Name|Expr $class Class name + * @param string|Identifier $name Constant name + * + * @return Expr\ClassConstFetch + */ + public function classConstFetch($class, $name): Expr\ClassConstFetch { + return new Expr\ClassConstFetch( + BuilderHelpers::normalizeNameOrExpr($class), + BuilderHelpers::normalizeIdentifier($name) + ); + } + + /** + * Creates nested Concat nodes from a list of expressions. + * + * @param Expr|string ...$exprs Expressions or literal strings + * + * @return Concat + */ + public function concat(...$exprs) : Concat { + $numExprs = count($exprs); + if ($numExprs < 2) { + throw new \LogicException('Expected at least two expressions'); + } + + $lastConcat = $this->normalizeStringExpr($exprs[0]); + for ($i = 1; $i < $numExprs; $i++) { + $lastConcat = new Concat($lastConcat, $this->normalizeStringExpr($exprs[$i])); + } + return $lastConcat; + } + + /** + * @param string|Expr $expr + * @return Expr + */ + private function normalizeStringExpr($expr) : Expr { + if ($expr instanceof Expr) { + return $expr; + } + + if (\is_string($expr)) { + return new String_($expr); + } + + throw new \LogicException('Expected string or Expr'); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php b/vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php new file mode 100644 index 00000000..af6ceb99 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php @@ -0,0 +1,335 @@ +getNode(); + } + + if ($node instanceof Node) { + return $node; + } + + throw new \LogicException('Expected node or builder object'); + } + + /** + * Normalizes a node to a statement. + * + * Expressions are wrapped in a Stmt\Expression node. + * + * @param Node|Builder $node The node to normalize + * + * @return Stmt The normalized statement node + */ + public static function normalizeStmt($node) : Stmt { + $node = self::normalizeNode($node); + if ($node instanceof Stmt) { + return $node; + } + + if ($node instanceof Expr) { + return new Stmt\Expression($node); + } + + throw new \LogicException('Expected statement or expression node'); + } + + /** + * Normalizes strings to Identifier. + * + * @param string|Identifier $name The identifier to normalize + * + * @return Identifier The normalized identifier + */ + public static function normalizeIdentifier($name) : Identifier { + if ($name instanceof Identifier) { + return $name; + } + + if (\is_string($name)) { + return new Identifier($name); + } + + throw new \LogicException('Expected string or instance of Node\Identifier'); + } + + /** + * Normalizes strings to Identifier, also allowing expressions. + * + * @param string|Identifier|Expr $name The identifier to normalize + * + * @return Identifier|Expr The normalized identifier or expression + */ + public static function normalizeIdentifierOrExpr($name) { + if ($name instanceof Identifier || $name instanceof Expr) { + return $name; + } + + if (\is_string($name)) { + return new Identifier($name); + } + + throw new \LogicException('Expected string or instance of Node\Identifier or Node\Expr'); + } + + /** + * Normalizes a name: Converts string names to Name nodes. + * + * @param Name|string $name The name to normalize + * + * @return Name The normalized name + */ + public static function normalizeName($name) : Name { + if ($name instanceof Name) { + return $name; + } + + if (is_string($name)) { + if (!$name) { + throw new \LogicException('Name cannot be empty'); + } + + if ($name[0] === '\\') { + return new Name\FullyQualified(substr($name, 1)); + } + + if (0 === strpos($name, 'namespace\\')) { + return new Name\Relative(substr($name, strlen('namespace\\'))); + } + + return new Name($name); + } + + throw new \LogicException('Name must be a string or an instance of Node\Name'); + } + + /** + * Normalizes a name: Converts string names to Name nodes, while also allowing expressions. + * + * @param Expr|Name|string $name The name to normalize + * + * @return Name|Expr The normalized name or expression + */ + public static function normalizeNameOrExpr($name) { + if ($name instanceof Expr) { + return $name; + } + + if (!is_string($name) && !($name instanceof Name)) { + throw new \LogicException( + 'Name must be a string or an instance of Node\Name or Node\Expr' + ); + } + + return self::normalizeName($name); + } + + /** + * Normalizes a type: Converts plain-text type names into proper AST representation. + * + * In particular, builtin types become Identifiers, custom types become Names and nullables + * are wrapped in NullableType nodes. + * + * @param string|Name|Identifier|ComplexType $type The type to normalize + * + * @return Name|Identifier|ComplexType The normalized type + */ + public static function normalizeType($type) { + if (!is_string($type)) { + if ( + !$type instanceof Name && !$type instanceof Identifier && + !$type instanceof ComplexType + ) { + throw new \LogicException( + 'Type must be a string, or an instance of Name, Identifier or ComplexType' + ); + } + return $type; + } + + $nullable = false; + if (strlen($type) > 0 && $type[0] === '?') { + $nullable = true; + $type = substr($type, 1); + } + + $builtinTypes = [ + 'array', + 'callable', + 'bool', + 'int', + 'float', + 'string', + 'iterable', + 'void', + 'object', + 'null', + 'false', + 'mixed', + 'never', + 'true', + ]; + + $lowerType = strtolower($type); + if (in_array($lowerType, $builtinTypes)) { + $type = new Identifier($lowerType); + } else { + $type = self::normalizeName($type); + } + + $notNullableTypes = [ + 'void', 'mixed', 'never', + ]; + if ($nullable && in_array((string) $type, $notNullableTypes)) { + throw new \LogicException(sprintf('%s type cannot be nullable', $type)); + } + + return $nullable ? new NullableType($type) : $type; + } + + /** + * Normalizes a value: Converts nulls, booleans, integers, + * floats, strings and arrays into their respective nodes + * + * @param Node\Expr|bool|null|int|float|string|array $value The value to normalize + * + * @return Expr The normalized value + */ + public static function normalizeValue($value) : Expr { + if ($value instanceof Node\Expr) { + return $value; + } + + if (is_null($value)) { + return new Expr\ConstFetch( + new Name('null') + ); + } + + if (is_bool($value)) { + return new Expr\ConstFetch( + new Name($value ? 'true' : 'false') + ); + } + + if (is_int($value)) { + return new Scalar\LNumber($value); + } + + if (is_float($value)) { + return new Scalar\DNumber($value); + } + + if (is_string($value)) { + return new Scalar\String_($value); + } + + if (is_array($value)) { + $items = []; + $lastKey = -1; + foreach ($value as $itemKey => $itemValue) { + // for consecutive, numeric keys don't generate keys + if (null !== $lastKey && ++$lastKey === $itemKey) { + $items[] = new Expr\ArrayItem( + self::normalizeValue($itemValue) + ); + } else { + $lastKey = null; + $items[] = new Expr\ArrayItem( + self::normalizeValue($itemValue), + self::normalizeValue($itemKey) + ); + } + } + + return new Expr\Array_($items); + } + + throw new \LogicException('Invalid value'); + } + + /** + * Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc. + * + * @param Comment\Doc|string $docComment The doc comment to normalize + * + * @return Comment\Doc The normalized doc comment + */ + public static function normalizeDocComment($docComment) : Comment\Doc { + if ($docComment instanceof Comment\Doc) { + return $docComment; + } + + if (is_string($docComment)) { + return new Comment\Doc($docComment); + } + + throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc'); + } + + /** + * Normalizes a attribute: Converts attribute to the Attribute Group if needed. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return Node\AttributeGroup The Attribute Group + */ + public static function normalizeAttribute($attribute) : Node\AttributeGroup + { + if ($attribute instanceof Node\AttributeGroup) { + return $attribute; + } + + if (!($attribute instanceof Node\Attribute)) { + throw new \LogicException('Attribute must be an instance of PhpParser\Node\Attribute or PhpParser\Node\AttributeGroup'); + } + + return new Node\AttributeGroup([$attribute]); + } + + /** + * Adds a modifier and returns new modifier bitmask. + * + * @param int $modifiers Existing modifiers + * @param int $modifier Modifier to set + * + * @return int New modifiers + */ + public static function addModifier(int $modifiers, int $modifier) : int { + Stmt\Class_::verifyModifier($modifiers, $modifier); + return $modifiers | $modifier; + } + + /** + * Adds a modifier and returns new modifier bitmask. + * @return int New modifiers + */ + public static function addClassModifier(int $existingModifiers, int $modifierToSet) : int { + Stmt\Class_::verifyClassModifier($existingModifiers, $modifierToSet); + return $existingModifiers | $modifierToSet; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Comment.php b/vendor/nikic/php-parser/lib/PhpParser/Comment.php new file mode 100644 index 00000000..61e98d3d --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Comment.php @@ -0,0 +1,239 @@ +text = $text; + $this->startLine = $startLine; + $this->startFilePos = $startFilePos; + $this->startTokenPos = $startTokenPos; + $this->endLine = $endLine; + $this->endFilePos = $endFilePos; + $this->endTokenPos = $endTokenPos; + } + + /** + * Gets the comment text. + * + * @return string The comment text (including comment delimiters like /*) + */ + public function getText() : string { + return $this->text; + } + + /** + * Gets the line number the comment started on. + * + * @return int Line number (or -1 if not available) + */ + public function getStartLine() : int { + return $this->startLine; + } + + /** + * Gets the file offset the comment started on. + * + * @return int File offset (or -1 if not available) + */ + public function getStartFilePos() : int { + return $this->startFilePos; + } + + /** + * Gets the token offset the comment started on. + * + * @return int Token offset (or -1 if not available) + */ + public function getStartTokenPos() : int { + return $this->startTokenPos; + } + + /** + * Gets the line number the comment ends on. + * + * @return int Line number (or -1 if not available) + */ + public function getEndLine() : int { + return $this->endLine; + } + + /** + * Gets the file offset the comment ends on. + * + * @return int File offset (or -1 if not available) + */ + public function getEndFilePos() : int { + return $this->endFilePos; + } + + /** + * Gets the token offset the comment ends on. + * + * @return int Token offset (or -1 if not available) + */ + public function getEndTokenPos() : int { + return $this->endTokenPos; + } + + /** + * Gets the line number the comment started on. + * + * @deprecated Use getStartLine() instead + * + * @return int Line number + */ + public function getLine() : int { + return $this->startLine; + } + + /** + * Gets the file offset the comment started on. + * + * @deprecated Use getStartFilePos() instead + * + * @return int File offset + */ + public function getFilePos() : int { + return $this->startFilePos; + } + + /** + * Gets the token offset the comment started on. + * + * @deprecated Use getStartTokenPos() instead + * + * @return int Token offset + */ + public function getTokenPos() : int { + return $this->startTokenPos; + } + + /** + * Gets the comment text. + * + * @return string The comment text (including comment delimiters like /*) + */ + public function __toString() : string { + return $this->text; + } + + /** + * Gets the reformatted comment text. + * + * "Reformatted" here means that we try to clean up the whitespace at the + * starts of the lines. This is necessary because we receive the comments + * without trailing whitespace on the first line, but with trailing whitespace + * on all subsequent lines. + * + * @return mixed|string + */ + public function getReformattedText() { + $text = trim($this->text); + $newlinePos = strpos($text, "\n"); + if (false === $newlinePos) { + // Single line comments don't need further processing + return $text; + } elseif (preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\R\s+\*.*)+$)', $text)) { + // Multi line comment of the type + // + // /* + // * Some text. + // * Some more text. + // */ + // + // is handled by replacing the whitespace sequences before the * by a single space + return preg_replace('(^\s+\*)m', ' *', $this->text); + } elseif (preg_match('(^/\*\*?\s*[\r\n])', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) { + // Multi line comment of the type + // + // /* + // Some text. + // Some more text. + // */ + // + // is handled by removing the whitespace sequence on the line before the closing + // */ on all lines. So if the last line is " */", then " " is removed at the + // start of all lines. + return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text); + } elseif (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) { + // Multi line comment of the type + // + // /* Some text. + // Some more text. + // Indented text. + // Even more text. */ + // + // is handled by removing the difference between the shortest whitespace prefix on all + // lines and the length of the "/* " opening sequence. + $prefixLen = $this->getShortestWhitespacePrefixLen(substr($text, $newlinePos + 1)); + $removeLen = $prefixLen - strlen($matches[0]); + return preg_replace('(^\s{' . $removeLen . '})m', '', $text); + } + + // No idea how to format this comment, so simply return as is + return $text; + } + + /** + * Get length of shortest whitespace prefix (at the start of a line). + * + * If there is a line with no prefix whitespace, 0 is a valid return value. + * + * @param string $str String to check + * @return int Length in characters. Tabs count as single characters. + */ + private function getShortestWhitespacePrefixLen(string $str) : int { + $lines = explode("\n", $str); + $shortestPrefixLen = \INF; + foreach ($lines as $line) { + preg_match('(^\s*)', $line, $matches); + $prefixLen = strlen($matches[0]); + if ($prefixLen < $shortestPrefixLen) { + $shortestPrefixLen = $prefixLen; + } + } + return $shortestPrefixLen; + } + + /** + * @return array + * @psalm-return array{nodeType:string, text:mixed, line:mixed, filePos:mixed} + */ + public function jsonSerialize() : array { + // Technically not a node, but we make it look like one anyway + $type = $this instanceof Comment\Doc ? 'Comment_Doc' : 'Comment'; + return [ + 'nodeType' => $type, + 'text' => $this->text, + // TODO: Rename these to include "start". + 'line' => $this->startLine, + 'filePos' => $this->startFilePos, + 'tokenPos' => $this->startTokenPos, + 'endLine' => $this->endLine, + 'endFilePos' => $this->endFilePos, + 'endTokenPos' => $this->endTokenPos, + ]; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php b/vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php new file mode 100644 index 00000000..a9db6128 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php @@ -0,0 +1,7 @@ +fallbackEvaluator = $fallbackEvaluator ?? function(Expr $expr) { + throw new ConstExprEvaluationException( + "Expression of type {$expr->getType()} cannot be evaluated" + ); + }; + } + + /** + * Silently evaluates a constant expression into a PHP value. + * + * Thrown Errors, warnings or notices will be converted into a ConstExprEvaluationException. + * The original source of the exception is available through getPrevious(). + * + * If some part of the expression cannot be evaluated, the fallback evaluator passed to the + * constructor will be invoked. By default, if no fallback is provided, an exception of type + * ConstExprEvaluationException is thrown. + * + * See class doc comment for caveats and limitations. + * + * @param Expr $expr Constant expression to evaluate + * @return mixed Result of evaluation + * + * @throws ConstExprEvaluationException if the expression cannot be evaluated or an error occurred + */ + public function evaluateSilently(Expr $expr) { + set_error_handler(function($num, $str, $file, $line) { + throw new \ErrorException($str, 0, $num, $file, $line); + }); + + try { + return $this->evaluate($expr); + } catch (\Throwable $e) { + if (!$e instanceof ConstExprEvaluationException) { + $e = new ConstExprEvaluationException( + "An error occurred during constant expression evaluation", 0, $e); + } + throw $e; + } finally { + restore_error_handler(); + } + } + + /** + * Directly evaluates a constant expression into a PHP value. + * + * May generate Error exceptions, warnings or notices. Use evaluateSilently() to convert these + * into a ConstExprEvaluationException. + * + * If some part of the expression cannot be evaluated, the fallback evaluator passed to the + * constructor will be invoked. By default, if no fallback is provided, an exception of type + * ConstExprEvaluationException is thrown. + * + * See class doc comment for caveats and limitations. + * + * @param Expr $expr Constant expression to evaluate + * @return mixed Result of evaluation + * + * @throws ConstExprEvaluationException if the expression cannot be evaluated + */ + public function evaluateDirectly(Expr $expr) { + return $this->evaluate($expr); + } + + private function evaluate(Expr $expr) { + if ($expr instanceof Scalar\LNumber + || $expr instanceof Scalar\DNumber + || $expr instanceof Scalar\String_ + ) { + return $expr->value; + } + + if ($expr instanceof Expr\Array_) { + return $this->evaluateArray($expr); + } + + // Unary operators + if ($expr instanceof Expr\UnaryPlus) { + return +$this->evaluate($expr->expr); + } + if ($expr instanceof Expr\UnaryMinus) { + return -$this->evaluate($expr->expr); + } + if ($expr instanceof Expr\BooleanNot) { + return !$this->evaluate($expr->expr); + } + if ($expr instanceof Expr\BitwiseNot) { + return ~$this->evaluate($expr->expr); + } + + if ($expr instanceof Expr\BinaryOp) { + return $this->evaluateBinaryOp($expr); + } + + if ($expr instanceof Expr\Ternary) { + return $this->evaluateTernary($expr); + } + + if ($expr instanceof Expr\ArrayDimFetch && null !== $expr->dim) { + return $this->evaluate($expr->var)[$this->evaluate($expr->dim)]; + } + + if ($expr instanceof Expr\ConstFetch) { + return $this->evaluateConstFetch($expr); + } + + return ($this->fallbackEvaluator)($expr); + } + + private function evaluateArray(Expr\Array_ $expr) { + $array = []; + foreach ($expr->items as $item) { + if (null !== $item->key) { + $array[$this->evaluate($item->key)] = $this->evaluate($item->value); + } elseif ($item->unpack) { + $array = array_merge($array, $this->evaluate($item->value)); + } else { + $array[] = $this->evaluate($item->value); + } + } + return $array; + } + + private function evaluateTernary(Expr\Ternary $expr) { + if (null === $expr->if) { + return $this->evaluate($expr->cond) ?: $this->evaluate($expr->else); + } + + return $this->evaluate($expr->cond) + ? $this->evaluate($expr->if) + : $this->evaluate($expr->else); + } + + private function evaluateBinaryOp(Expr\BinaryOp $expr) { + if ($expr instanceof Expr\BinaryOp\Coalesce + && $expr->left instanceof Expr\ArrayDimFetch + ) { + // This needs to be special cased to respect BP_VAR_IS fetch semantics + return $this->evaluate($expr->left->var)[$this->evaluate($expr->left->dim)] + ?? $this->evaluate($expr->right); + } + + // The evaluate() calls are repeated in each branch, because some of the operators are + // short-circuiting and evaluating the RHS in advance may be illegal in that case + $l = $expr->left; + $r = $expr->right; + switch ($expr->getOperatorSigil()) { + case '&': return $this->evaluate($l) & $this->evaluate($r); + case '|': return $this->evaluate($l) | $this->evaluate($r); + case '^': return $this->evaluate($l) ^ $this->evaluate($r); + case '&&': return $this->evaluate($l) && $this->evaluate($r); + case '||': return $this->evaluate($l) || $this->evaluate($r); + case '??': return $this->evaluate($l) ?? $this->evaluate($r); + case '.': return $this->evaluate($l) . $this->evaluate($r); + case '/': return $this->evaluate($l) / $this->evaluate($r); + case '==': return $this->evaluate($l) == $this->evaluate($r); + case '>': return $this->evaluate($l) > $this->evaluate($r); + case '>=': return $this->evaluate($l) >= $this->evaluate($r); + case '===': return $this->evaluate($l) === $this->evaluate($r); + case 'and': return $this->evaluate($l) and $this->evaluate($r); + case 'or': return $this->evaluate($l) or $this->evaluate($r); + case 'xor': return $this->evaluate($l) xor $this->evaluate($r); + case '-': return $this->evaluate($l) - $this->evaluate($r); + case '%': return $this->evaluate($l) % $this->evaluate($r); + case '*': return $this->evaluate($l) * $this->evaluate($r); + case '!=': return $this->evaluate($l) != $this->evaluate($r); + case '!==': return $this->evaluate($l) !== $this->evaluate($r); + case '+': return $this->evaluate($l) + $this->evaluate($r); + case '**': return $this->evaluate($l) ** $this->evaluate($r); + case '<<': return $this->evaluate($l) << $this->evaluate($r); + case '>>': return $this->evaluate($l) >> $this->evaluate($r); + case '<': return $this->evaluate($l) < $this->evaluate($r); + case '<=': return $this->evaluate($l) <= $this->evaluate($r); + case '<=>': return $this->evaluate($l) <=> $this->evaluate($r); + } + + throw new \Exception('Should not happen'); + } + + private function evaluateConstFetch(Expr\ConstFetch $expr) { + $name = $expr->name->toLowerString(); + switch ($name) { + case 'null': return null; + case 'false': return false; + case 'true': return true; + } + + return ($this->fallbackEvaluator)($expr); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Error.php b/vendor/nikic/php-parser/lib/PhpParser/Error.php new file mode 100644 index 00000000..d1fb959d --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Error.php @@ -0,0 +1,180 @@ +rawMessage = $message; + if (is_array($attributes)) { + $this->attributes = $attributes; + } else { + $this->attributes = ['startLine' => $attributes]; + } + $this->updateMessage(); + } + + /** + * Gets the error message + * + * @return string Error message + */ + public function getRawMessage() : string { + return $this->rawMessage; + } + + /** + * Gets the line the error starts in. + * + * @return int Error start line + */ + public function getStartLine() : int { + return $this->attributes['startLine'] ?? -1; + } + + /** + * Gets the line the error ends in. + * + * @return int Error end line + */ + public function getEndLine() : int { + return $this->attributes['endLine'] ?? -1; + } + + /** + * Gets the attributes of the node/token the error occurred at. + * + * @return array + */ + public function getAttributes() : array { + return $this->attributes; + } + + /** + * Sets the attributes of the node/token the error occurred at. + * + * @param array $attributes + */ + public function setAttributes(array $attributes) { + $this->attributes = $attributes; + $this->updateMessage(); + } + + /** + * Sets the line of the PHP file the error occurred in. + * + * @param string $message Error message + */ + public function setRawMessage(string $message) { + $this->rawMessage = $message; + $this->updateMessage(); + } + + /** + * Sets the line the error starts in. + * + * @param int $line Error start line + */ + public function setStartLine(int $line) { + $this->attributes['startLine'] = $line; + $this->updateMessage(); + } + + /** + * Returns whether the error has start and end column information. + * + * For column information enable the startFilePos and endFilePos in the lexer options. + * + * @return bool + */ + public function hasColumnInfo() : bool { + return isset($this->attributes['startFilePos'], $this->attributes['endFilePos']); + } + + /** + * Gets the start column (1-based) into the line where the error started. + * + * @param string $code Source code of the file + * @return int + */ + public function getStartColumn(string $code) : int { + if (!$this->hasColumnInfo()) { + throw new \RuntimeException('Error does not have column information'); + } + + return $this->toColumn($code, $this->attributes['startFilePos']); + } + + /** + * Gets the end column (1-based) into the line where the error ended. + * + * @param string $code Source code of the file + * @return int + */ + public function getEndColumn(string $code) : int { + if (!$this->hasColumnInfo()) { + throw new \RuntimeException('Error does not have column information'); + } + + return $this->toColumn($code, $this->attributes['endFilePos']); + } + + /** + * Formats message including line and column information. + * + * @param string $code Source code associated with the error, for calculation of the columns + * + * @return string Formatted message + */ + public function getMessageWithColumnInfo(string $code) : string { + return sprintf( + '%s from %d:%d to %d:%d', $this->getRawMessage(), + $this->getStartLine(), $this->getStartColumn($code), + $this->getEndLine(), $this->getEndColumn($code) + ); + } + + /** + * Converts a file offset into a column. + * + * @param string $code Source code that $pos indexes into + * @param int $pos 0-based position in $code + * + * @return int 1-based column (relative to start of line) + */ + private function toColumn(string $code, int $pos) : int { + if ($pos > strlen($code)) { + throw new \RuntimeException('Invalid position information'); + } + + $lineStartPos = strrpos($code, "\n", $pos - strlen($code)); + if (false === $lineStartPos) { + $lineStartPos = -1; + } + + return $pos - $lineStartPos; + } + + /** + * Updates the exception message after a change to rawMessage or rawLine. + */ + protected function updateMessage() { + $this->message = $this->rawMessage; + + if (-1 === $this->getStartLine()) { + $this->message .= ' on unknown line'; + } else { + $this->message .= ' on line ' . $this->getStartLine(); + } + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php b/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php new file mode 100644 index 00000000..d620e745 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php @@ -0,0 +1,13 @@ +errors[] = $error; + } + + /** + * Get collected errors. + * + * @return Error[] + */ + public function getErrors() : array { + return $this->errors; + } + + /** + * Check whether there are any errors. + * + * @return bool + */ + public function hasErrors() : bool { + return !empty($this->errors); + } + + /** + * Reset/clear collected errors. + */ + public function clearErrors() { + $this->errors = []; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php b/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php new file mode 100644 index 00000000..aeee989b --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php @@ -0,0 +1,18 @@ +type = $type; + $this->old = $old; + $this->new = $new; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.php b/vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.php new file mode 100644 index 00000000..7f218c74 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.php @@ -0,0 +1,164 @@ +isEqual = $isEqual; + } + + /** + * Calculate diff (edit script) from $old to $new. + * + * @param array $old Original array + * @param array $new New array + * + * @return DiffElem[] Diff (edit script) + */ + public function diff(array $old, array $new) { + list($trace, $x, $y) = $this->calculateTrace($old, $new); + return $this->extractDiff($trace, $x, $y, $old, $new); + } + + /** + * Calculate diff, including "replace" operations. + * + * If a sequence of remove operations is followed by the same number of add operations, these + * will be coalesced into replace operations. + * + * @param array $old Original array + * @param array $new New array + * + * @return DiffElem[] Diff (edit script), including replace operations + */ + public function diffWithReplacements(array $old, array $new) { + return $this->coalesceReplacements($this->diff($old, $new)); + } + + private function calculateTrace(array $a, array $b) { + $n = \count($a); + $m = \count($b); + $max = $n + $m; + $v = [1 => 0]; + $trace = []; + for ($d = 0; $d <= $max; $d++) { + $trace[] = $v; + for ($k = -$d; $k <= $d; $k += 2) { + if ($k === -$d || ($k !== $d && $v[$k-1] < $v[$k+1])) { + $x = $v[$k+1]; + } else { + $x = $v[$k-1] + 1; + } + + $y = $x - $k; + while ($x < $n && $y < $m && ($this->isEqual)($a[$x], $b[$y])) { + $x++; + $y++; + } + + $v[$k] = $x; + if ($x >= $n && $y >= $m) { + return [$trace, $x, $y]; + } + } + } + throw new \Exception('Should not happen'); + } + + private function extractDiff(array $trace, int $x, int $y, array $a, array $b) { + $result = []; + for ($d = \count($trace) - 1; $d >= 0; $d--) { + $v = $trace[$d]; + $k = $x - $y; + + if ($k === -$d || ($k !== $d && $v[$k-1] < $v[$k+1])) { + $prevK = $k + 1; + } else { + $prevK = $k - 1; + } + + $prevX = $v[$prevK]; + $prevY = $prevX - $prevK; + + while ($x > $prevX && $y > $prevY) { + $result[] = new DiffElem(DiffElem::TYPE_KEEP, $a[$x-1], $b[$y-1]); + $x--; + $y--; + } + + if ($d === 0) { + break; + } + + while ($x > $prevX) { + $result[] = new DiffElem(DiffElem::TYPE_REMOVE, $a[$x-1], null); + $x--; + } + + while ($y > $prevY) { + $result[] = new DiffElem(DiffElem::TYPE_ADD, null, $b[$y-1]); + $y--; + } + } + return array_reverse($result); + } + + /** + * Coalesce equal-length sequences of remove+add into a replace operation. + * + * @param DiffElem[] $diff + * @return DiffElem[] + */ + private function coalesceReplacements(array $diff) { + $newDiff = []; + $c = \count($diff); + for ($i = 0; $i < $c; $i++) { + $diffType = $diff[$i]->type; + if ($diffType !== DiffElem::TYPE_REMOVE) { + $newDiff[] = $diff[$i]; + continue; + } + + $j = $i; + while ($j < $c && $diff[$j]->type === DiffElem::TYPE_REMOVE) { + $j++; + } + + $k = $j; + while ($k < $c && $diff[$k]->type === DiffElem::TYPE_ADD) { + $k++; + } + + if ($j - $i === $k - $j) { + $len = $j - $i; + for ($n = 0; $n < $len; $n++) { + $newDiff[] = new DiffElem( + DiffElem::TYPE_REPLACE, $diff[$i + $n]->old, $diff[$j + $n]->new + ); + } + } else { + for (; $i < $k; $i++) { + $newDiff[] = $diff[$i]; + } + } + $i = $k - 1; + } + return $newDiff; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php b/vendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php new file mode 100644 index 00000000..3eeac04a --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php @@ -0,0 +1,61 @@ +attrGroups = $attrGroups; + $this->args = $args; + $this->extends = $extends; + $this->implements = $implements; + $this->stmts = $stmts; + } + + public static function fromNewNode(Expr\New_ $newNode) { + $class = $newNode->class; + assert($class instanceof Node\Stmt\Class_); + // We don't assert that $class->name is null here, to allow consumers to assign unique names + // to anonymous classes for their own purposes. We simplify ignore the name here. + return new self( + $class->attrGroups, $newNode->args, $class->extends, $class->implements, + $class->stmts, $newNode->getAttributes() + ); + } + + public function getType() : string { + return 'Expr_PrintableNewAnonClass'; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'args', 'extends', 'implements', 'stmts']; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php b/vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php new file mode 100644 index 00000000..7e0a5de0 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php @@ -0,0 +1,286 @@ +tokens = $tokens; + $this->indentMap = $this->calcIndentMap(); + } + + /** + * Whether the given position is immediately surrounded by parenthesis. + * + * @param int $startPos Start position + * @param int $endPos End position + * + * @return bool + */ + public function haveParens(int $startPos, int $endPos) : bool { + return $this->haveTokenImmediatelyBefore($startPos, '(') + && $this->haveTokenImmediatelyAfter($endPos, ')'); + } + + /** + * Whether the given position is immediately surrounded by braces. + * + * @param int $startPos Start position + * @param int $endPos End position + * + * @return bool + */ + public function haveBraces(int $startPos, int $endPos) : bool { + return ($this->haveTokenImmediatelyBefore($startPos, '{') + || $this->haveTokenImmediatelyBefore($startPos, T_CURLY_OPEN)) + && $this->haveTokenImmediatelyAfter($endPos, '}'); + } + + /** + * Check whether the position is directly preceded by a certain token type. + * + * During this check whitespace and comments are skipped. + * + * @param int $pos Position before which the token should occur + * @param int|string $expectedTokenType Token to check for + * + * @return bool Whether the expected token was found + */ + public function haveTokenImmediatelyBefore(int $pos, $expectedTokenType) : bool { + $tokens = $this->tokens; + $pos--; + for (; $pos >= 0; $pos--) { + $tokenType = $tokens[$pos][0]; + if ($tokenType === $expectedTokenType) { + return true; + } + if ($tokenType !== \T_WHITESPACE + && $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) { + break; + } + } + return false; + } + + /** + * Check whether the position is directly followed by a certain token type. + * + * During this check whitespace and comments are skipped. + * + * @param int $pos Position after which the token should occur + * @param int|string $expectedTokenType Token to check for + * + * @return bool Whether the expected token was found + */ + public function haveTokenImmediatelyAfter(int $pos, $expectedTokenType) : bool { + $tokens = $this->tokens; + $pos++; + for (; $pos < \count($tokens); $pos++) { + $tokenType = $tokens[$pos][0]; + if ($tokenType === $expectedTokenType) { + return true; + } + if ($tokenType !== \T_WHITESPACE + && $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) { + break; + } + } + return false; + } + + public function skipLeft(int $pos, $skipTokenType) { + $tokens = $this->tokens; + + $pos = $this->skipLeftWhitespace($pos); + if ($skipTokenType === \T_WHITESPACE) { + return $pos; + } + + if ($tokens[$pos][0] !== $skipTokenType) { + // Shouldn't happen. The skip token MUST be there + throw new \Exception('Encountered unexpected token'); + } + $pos--; + + return $this->skipLeftWhitespace($pos); + } + + public function skipRight(int $pos, $skipTokenType) { + $tokens = $this->tokens; + + $pos = $this->skipRightWhitespace($pos); + if ($skipTokenType === \T_WHITESPACE) { + return $pos; + } + + if ($tokens[$pos][0] !== $skipTokenType) { + // Shouldn't happen. The skip token MUST be there + throw new \Exception('Encountered unexpected token'); + } + $pos++; + + return $this->skipRightWhitespace($pos); + } + + /** + * Return first non-whitespace token position smaller or equal to passed position. + * + * @param int $pos Token position + * @return int Non-whitespace token position + */ + public function skipLeftWhitespace(int $pos) { + $tokens = $this->tokens; + for (; $pos >= 0; $pos--) { + $type = $tokens[$pos][0]; + if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) { + break; + } + } + return $pos; + } + + /** + * Return first non-whitespace position greater or equal to passed position. + * + * @param int $pos Token position + * @return int Non-whitespace token position + */ + public function skipRightWhitespace(int $pos) { + $tokens = $this->tokens; + for ($count = \count($tokens); $pos < $count; $pos++) { + $type = $tokens[$pos][0]; + if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) { + break; + } + } + return $pos; + } + + public function findRight(int $pos, $findTokenType) { + $tokens = $this->tokens; + for ($count = \count($tokens); $pos < $count; $pos++) { + $type = $tokens[$pos][0]; + if ($type === $findTokenType) { + return $pos; + } + } + return -1; + } + + /** + * Whether the given position range contains a certain token type. + * + * @param int $startPos Starting position (inclusive) + * @param int $endPos Ending position (exclusive) + * @param int|string $tokenType Token type to look for + * @return bool Whether the token occurs in the given range + */ + public function haveTokenInRange(int $startPos, int $endPos, $tokenType) { + $tokens = $this->tokens; + for ($pos = $startPos; $pos < $endPos; $pos++) { + if ($tokens[$pos][0] === $tokenType) { + return true; + } + } + return false; + } + + public function haveBracesInRange(int $startPos, int $endPos) { + return $this->haveTokenInRange($startPos, $endPos, '{') + || $this->haveTokenInRange($startPos, $endPos, T_CURLY_OPEN) + || $this->haveTokenInRange($startPos, $endPos, '}'); + } + + public function haveTagInRange(int $startPos, int $endPos): bool { + return $this->haveTokenInRange($startPos, $endPos, \T_OPEN_TAG) + || $this->haveTokenInRange($startPos, $endPos, \T_CLOSE_TAG); + } + + /** + * Get indentation before token position. + * + * @param int $pos Token position + * + * @return int Indentation depth (in spaces) + */ + public function getIndentationBefore(int $pos) : int { + return $this->indentMap[$pos]; + } + + /** + * Get the code corresponding to a token offset range, optionally adjusted for indentation. + * + * @param int $from Token start position (inclusive) + * @param int $to Token end position (exclusive) + * @param int $indent By how much the code should be indented (can be negative as well) + * + * @return string Code corresponding to token range, adjusted for indentation + */ + public function getTokenCode(int $from, int $to, int $indent) : string { + $tokens = $this->tokens; + $result = ''; + for ($pos = $from; $pos < $to; $pos++) { + $token = $tokens[$pos]; + if (\is_array($token)) { + $type = $token[0]; + $content = $token[1]; + if ($type === \T_CONSTANT_ENCAPSED_STRING || $type === \T_ENCAPSED_AND_WHITESPACE) { + $result .= $content; + } else { + // TODO Handle non-space indentation + if ($indent < 0) { + $result .= str_replace("\n" . str_repeat(" ", -$indent), "\n", $content); + } elseif ($indent > 0) { + $result .= str_replace("\n", "\n" . str_repeat(" ", $indent), $content); + } else { + $result .= $content; + } + } + } else { + $result .= $token; + } + } + return $result; + } + + /** + * Precalculate the indentation at every token position. + * + * @return int[] Token position to indentation map + */ + private function calcIndentMap() { + $indentMap = []; + $indent = 0; + foreach ($this->tokens as $token) { + $indentMap[] = $indent; + + if ($token[0] === \T_WHITESPACE) { + $content = $token[1]; + $newlinePos = \strrpos($content, "\n"); + if (false !== $newlinePos) { + $indent = \strlen($content) - $newlinePos - 1; + } + } + } + + // Add a sentinel for one past end of the file + $indentMap[] = $indent; + + return $indentMap; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php b/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php new file mode 100644 index 00000000..47d2003d --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php @@ -0,0 +1,103 @@ +decodeRecursive($value); + } + + private function decodeRecursive($value) { + if (\is_array($value)) { + if (isset($value['nodeType'])) { + if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc') { + return $this->decodeComment($value); + } + return $this->decodeNode($value); + } + return $this->decodeArray($value); + } + return $value; + } + + private function decodeArray(array $array) : array { + $decodedArray = []; + foreach ($array as $key => $value) { + $decodedArray[$key] = $this->decodeRecursive($value); + } + return $decodedArray; + } + + private function decodeNode(array $value) : Node { + $nodeType = $value['nodeType']; + if (!\is_string($nodeType)) { + throw new \RuntimeException('Node type must be a string'); + } + + $reflectionClass = $this->reflectionClassFromNodeType($nodeType); + /** @var Node $node */ + $node = $reflectionClass->newInstanceWithoutConstructor(); + + if (isset($value['attributes'])) { + if (!\is_array($value['attributes'])) { + throw new \RuntimeException('Attributes must be an array'); + } + + $node->setAttributes($this->decodeArray($value['attributes'])); + } + + foreach ($value as $name => $subNode) { + if ($name === 'nodeType' || $name === 'attributes') { + continue; + } + + $node->$name = $this->decodeRecursive($subNode); + } + + return $node; + } + + private function decodeComment(array $value) : Comment { + $className = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class; + if (!isset($value['text'])) { + throw new \RuntimeException('Comment must have text'); + } + + return new $className( + $value['text'], + $value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1, + $value['endLine'] ?? -1, $value['endFilePos'] ?? -1, $value['endTokenPos'] ?? -1 + ); + } + + private function reflectionClassFromNodeType(string $nodeType) : \ReflectionClass { + if (!isset($this->reflectionClassCache[$nodeType])) { + $className = $this->classNameFromNodeType($nodeType); + $this->reflectionClassCache[$nodeType] = new \ReflectionClass($className); + } + return $this->reflectionClassCache[$nodeType]; + } + + private function classNameFromNodeType(string $nodeType) : string { + $className = 'PhpParser\\Node\\' . strtr($nodeType, '_', '\\'); + if (class_exists($className)) { + return $className; + } + + $className .= '_'; + if (class_exists($className)) { + return $className; + } + + throw new \RuntimeException("Unknown node type \"$nodeType\""); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer.php new file mode 100644 index 00000000..e15dd0a5 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer.php @@ -0,0 +1,560 @@ +defineCompatibilityTokens(); + $this->tokenMap = $this->createTokenMap(); + $this->identifierTokens = $this->createIdentifierTokenMap(); + + // map of tokens to drop while lexing (the map is only used for isset lookup, + // that's why the value is simply set to 1; the value is never actually used.) + $this->dropTokens = array_fill_keys( + [\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT, \T_BAD_CHARACTER], 1 + ); + + $defaultAttributes = ['comments', 'startLine', 'endLine']; + $usedAttributes = array_fill_keys($options['usedAttributes'] ?? $defaultAttributes, true); + + // Create individual boolean properties to make these checks faster. + $this->attributeStartLineUsed = isset($usedAttributes['startLine']); + $this->attributeEndLineUsed = isset($usedAttributes['endLine']); + $this->attributeStartTokenPosUsed = isset($usedAttributes['startTokenPos']); + $this->attributeEndTokenPosUsed = isset($usedAttributes['endTokenPos']); + $this->attributeStartFilePosUsed = isset($usedAttributes['startFilePos']); + $this->attributeEndFilePosUsed = isset($usedAttributes['endFilePos']); + $this->attributeCommentsUsed = isset($usedAttributes['comments']); + } + + /** + * Initializes the lexer for lexing the provided source code. + * + * This function does not throw if lexing errors occur. Instead, errors may be retrieved using + * the getErrors() method. + * + * @param string $code The source code to lex + * @param ErrorHandler|null $errorHandler Error handler to use for lexing errors. Defaults to + * ErrorHandler\Throwing + */ + public function startLexing(string $code, ErrorHandler $errorHandler = null) { + if (null === $errorHandler) { + $errorHandler = new ErrorHandler\Throwing(); + } + + $this->code = $code; // keep the code around for __halt_compiler() handling + $this->pos = -1; + $this->line = 1; + $this->filePos = 0; + + // If inline HTML occurs without preceding code, treat it as if it had a leading newline. + // This ensures proper composability, because having a newline is the "safe" assumption. + $this->prevCloseTagHasNewline = true; + + $scream = ini_set('xdebug.scream', '0'); + + $this->tokens = @token_get_all($code); + $this->postprocessTokens($errorHandler); + + if (false !== $scream) { + ini_set('xdebug.scream', $scream); + } + } + + private function handleInvalidCharacterRange($start, $end, $line, ErrorHandler $errorHandler) { + $tokens = []; + for ($i = $start; $i < $end; $i++) { + $chr = $this->code[$i]; + if ($chr === "\0") { + // PHP cuts error message after null byte, so need special case + $errorMsg = 'Unexpected null byte'; + } else { + $errorMsg = sprintf( + 'Unexpected character "%s" (ASCII %d)', $chr, ord($chr) + ); + } + + $tokens[] = [\T_BAD_CHARACTER, $chr, $line]; + $errorHandler->handleError(new Error($errorMsg, [ + 'startLine' => $line, + 'endLine' => $line, + 'startFilePos' => $i, + 'endFilePos' => $i, + ])); + } + return $tokens; + } + + /** + * Check whether comment token is unterminated. + * + * @return bool + */ + private function isUnterminatedComment($token) : bool { + return ($token[0] === \T_COMMENT || $token[0] === \T_DOC_COMMENT) + && substr($token[1], 0, 2) === '/*' + && substr($token[1], -2) !== '*/'; + } + + protected function postprocessTokens(ErrorHandler $errorHandler) { + // PHP's error handling for token_get_all() is rather bad, so if we want detailed + // error information we need to compute it ourselves. Invalid character errors are + // detected by finding "gaps" in the token array. Unterminated comments are detected + // by checking if a trailing comment has a "*/" at the end. + // + // Additionally, we perform a number of canonicalizations here: + // * Use the PHP 8.0 comment format, which does not include trailing whitespace anymore. + // * Use PHP 8.0 T_NAME_* tokens. + // * Use PHP 8.1 T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG and + // T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG tokens used to disambiguate intersection types. + + $filePos = 0; + $line = 1; + $numTokens = \count($this->tokens); + for ($i = 0; $i < $numTokens; $i++) { + $token = $this->tokens[$i]; + + // Since PHP 7.4 invalid characters are represented by a T_BAD_CHARACTER token. + // In this case we only need to emit an error. + if ($token[0] === \T_BAD_CHARACTER) { + $this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler); + } + + if ($token[0] === \T_COMMENT && substr($token[1], 0, 2) !== '/*' + && preg_match('/(\r\n|\n|\r)$/D', $token[1], $matches)) { + $trailingNewline = $matches[0]; + $token[1] = substr($token[1], 0, -strlen($trailingNewline)); + $this->tokens[$i] = $token; + if (isset($this->tokens[$i + 1]) && $this->tokens[$i + 1][0] === \T_WHITESPACE) { + // Move trailing newline into following T_WHITESPACE token, if it already exists. + $this->tokens[$i + 1][1] = $trailingNewline . $this->tokens[$i + 1][1]; + $this->tokens[$i + 1][2]--; + } else { + // Otherwise, we need to create a new T_WHITESPACE token. + array_splice($this->tokens, $i + 1, 0, [ + [\T_WHITESPACE, $trailingNewline, $line], + ]); + $numTokens++; + } + } + + // Emulate PHP 8 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and T_STRING + // into a single token. + if (\is_array($token) + && ($token[0] === \T_NS_SEPARATOR || isset($this->identifierTokens[$token[0]]))) { + $lastWasSeparator = $token[0] === \T_NS_SEPARATOR; + $text = $token[1]; + for ($j = $i + 1; isset($this->tokens[$j]); $j++) { + if ($lastWasSeparator) { + if (!isset($this->identifierTokens[$this->tokens[$j][0]])) { + break; + } + $lastWasSeparator = false; + } else { + if ($this->tokens[$j][0] !== \T_NS_SEPARATOR) { + break; + } + $lastWasSeparator = true; + } + $text .= $this->tokens[$j][1]; + } + if ($lastWasSeparator) { + // Trailing separator is not part of the name. + $j--; + $text = substr($text, 0, -1); + } + if ($j > $i + 1) { + if ($token[0] === \T_NS_SEPARATOR) { + $type = \T_NAME_FULLY_QUALIFIED; + } else if ($token[0] === \T_NAMESPACE) { + $type = \T_NAME_RELATIVE; + } else { + $type = \T_NAME_QUALIFIED; + } + $token = [$type, $text, $line]; + array_splice($this->tokens, $i, $j - $i, [$token]); + $numTokens -= $j - $i - 1; + } + } + + if ($token === '&') { + $next = $i + 1; + while (isset($this->tokens[$next]) && $this->tokens[$next][0] === \T_WHITESPACE) { + $next++; + } + $followedByVarOrVarArg = isset($this->tokens[$next]) && + ($this->tokens[$next][0] === \T_VARIABLE || $this->tokens[$next][0] === \T_ELLIPSIS); + $this->tokens[$i] = $token = [ + $followedByVarOrVarArg + ? \T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG + : \T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG, + '&', + $line, + ]; + } + + $tokenValue = \is_string($token) ? $token : $token[1]; + $tokenLen = \strlen($tokenValue); + + if (substr($this->code, $filePos, $tokenLen) !== $tokenValue) { + // Something is missing, must be an invalid character + $nextFilePos = strpos($this->code, $tokenValue, $filePos); + $badCharTokens = $this->handleInvalidCharacterRange( + $filePos, $nextFilePos, $line, $errorHandler); + $filePos = (int) $nextFilePos; + + array_splice($this->tokens, $i, 0, $badCharTokens); + $numTokens += \count($badCharTokens); + $i += \count($badCharTokens); + } + + $filePos += $tokenLen; + $line += substr_count($tokenValue, "\n"); + } + + if ($filePos !== \strlen($this->code)) { + if (substr($this->code, $filePos, 2) === '/*') { + // Unlike PHP, HHVM will drop unterminated comments entirely + $comment = substr($this->code, $filePos); + $errorHandler->handleError(new Error('Unterminated comment', [ + 'startLine' => $line, + 'endLine' => $line + substr_count($comment, "\n"), + 'startFilePos' => $filePos, + 'endFilePos' => $filePos + \strlen($comment), + ])); + + // Emulate the PHP behavior + $isDocComment = isset($comment[3]) && $comment[3] === '*'; + $this->tokens[] = [$isDocComment ? \T_DOC_COMMENT : \T_COMMENT, $comment, $line]; + } else { + // Invalid characters at the end of the input + $badCharTokens = $this->handleInvalidCharacterRange( + $filePos, \strlen($this->code), $line, $errorHandler); + $this->tokens = array_merge($this->tokens, $badCharTokens); + } + return; + } + + if (count($this->tokens) > 0) { + // Check for unterminated comment + $lastToken = $this->tokens[count($this->tokens) - 1]; + if ($this->isUnterminatedComment($lastToken)) { + $errorHandler->handleError(new Error('Unterminated comment', [ + 'startLine' => $line - substr_count($lastToken[1], "\n"), + 'endLine' => $line, + 'startFilePos' => $filePos - \strlen($lastToken[1]), + 'endFilePos' => $filePos, + ])); + } + } + } + + /** + * Fetches the next token. + * + * The available attributes are determined by the 'usedAttributes' option, which can + * be specified in the constructor. The following attributes are supported: + * + * * 'comments' => Array of PhpParser\Comment or PhpParser\Comment\Doc instances, + * representing all comments that occurred between the previous + * non-discarded token and the current one. + * * 'startLine' => Line in which the node starts. + * * 'endLine' => Line in which the node ends. + * * 'startTokenPos' => Offset into the token array of the first token in the node. + * * 'endTokenPos' => Offset into the token array of the last token in the node. + * * 'startFilePos' => Offset into the code string of the first character that is part of the node. + * * 'endFilePos' => Offset into the code string of the last character that is part of the node. + * + * @param mixed $value Variable to store token content in + * @param mixed $startAttributes Variable to store start attributes in + * @param mixed $endAttributes Variable to store end attributes in + * + * @return int Token id + */ + public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) : int { + $startAttributes = []; + $endAttributes = []; + + while (1) { + if (isset($this->tokens[++$this->pos])) { + $token = $this->tokens[$this->pos]; + } else { + // EOF token with ID 0 + $token = "\0"; + } + + if ($this->attributeStartLineUsed) { + $startAttributes['startLine'] = $this->line; + } + if ($this->attributeStartTokenPosUsed) { + $startAttributes['startTokenPos'] = $this->pos; + } + if ($this->attributeStartFilePosUsed) { + $startAttributes['startFilePos'] = $this->filePos; + } + + if (\is_string($token)) { + $value = $token; + if (isset($token[1])) { + // bug in token_get_all + $this->filePos += 2; + $id = ord('"'); + } else { + $this->filePos += 1; + $id = ord($token); + } + } elseif (!isset($this->dropTokens[$token[0]])) { + $value = $token[1]; + $id = $this->tokenMap[$token[0]]; + if (\T_CLOSE_TAG === $token[0]) { + $this->prevCloseTagHasNewline = false !== strpos($token[1], "\n") + || false !== strpos($token[1], "\r"); + } elseif (\T_INLINE_HTML === $token[0]) { + $startAttributes['hasLeadingNewline'] = $this->prevCloseTagHasNewline; + } + + $this->line += substr_count($value, "\n"); + $this->filePos += \strlen($value); + } else { + $origLine = $this->line; + $origFilePos = $this->filePos; + $this->line += substr_count($token[1], "\n"); + $this->filePos += \strlen($token[1]); + + if (\T_COMMENT === $token[0] || \T_DOC_COMMENT === $token[0]) { + if ($this->attributeCommentsUsed) { + $comment = \T_DOC_COMMENT === $token[0] + ? new Comment\Doc($token[1], + $origLine, $origFilePos, $this->pos, + $this->line, $this->filePos - 1, $this->pos) + : new Comment($token[1], + $origLine, $origFilePos, $this->pos, + $this->line, $this->filePos - 1, $this->pos); + $startAttributes['comments'][] = $comment; + } + } + continue; + } + + if ($this->attributeEndLineUsed) { + $endAttributes['endLine'] = $this->line; + } + if ($this->attributeEndTokenPosUsed) { + $endAttributes['endTokenPos'] = $this->pos; + } + if ($this->attributeEndFilePosUsed) { + $endAttributes['endFilePos'] = $this->filePos - 1; + } + + return $id; + } + + throw new \RuntimeException('Reached end of lexer loop'); + } + + /** + * Returns the token array for current code. + * + * The token array is in the same format as provided by the + * token_get_all() function and does not discard tokens (i.e. + * whitespace and comments are included). The token position + * attributes are against this token array. + * + * @return array Array of tokens in token_get_all() format + */ + public function getTokens() : array { + return $this->tokens; + } + + /** + * Handles __halt_compiler() by returning the text after it. + * + * @return string Remaining text + */ + public function handleHaltCompiler() : string { + // text after T_HALT_COMPILER, still including (); + $textAfter = substr($this->code, $this->filePos); + + // ensure that it is followed by (); + // this simplifies the situation, by not allowing any comments + // in between of the tokens. + if (!preg_match('~^\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) { + throw new Error('__HALT_COMPILER must be followed by "();"'); + } + + // prevent the lexer from returning any further tokens + $this->pos = count($this->tokens); + + // return with (); removed + return substr($textAfter, strlen($matches[0])); + } + + private function defineCompatibilityTokens() { + static $compatTokensDefined = false; + if ($compatTokensDefined) { + return; + } + + $compatTokens = [ + // PHP 7.4 + 'T_BAD_CHARACTER', + 'T_FN', + 'T_COALESCE_EQUAL', + // PHP 8.0 + 'T_NAME_QUALIFIED', + 'T_NAME_FULLY_QUALIFIED', + 'T_NAME_RELATIVE', + 'T_MATCH', + 'T_NULLSAFE_OBJECT_OPERATOR', + 'T_ATTRIBUTE', + // PHP 8.1 + 'T_ENUM', + 'T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG', + 'T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG', + 'T_READONLY', + ]; + + // PHP-Parser might be used together with another library that also emulates some or all + // of these tokens. Perform a sanity-check that all already defined tokens have been + // assigned a unique ID. + $usedTokenIds = []; + foreach ($compatTokens as $token) { + if (\defined($token)) { + $tokenId = \constant($token); + $clashingToken = $usedTokenIds[$tokenId] ?? null; + if ($clashingToken !== null) { + throw new \Error(sprintf( + 'Token %s has same ID as token %s, ' . + 'you may be using a library with broken token emulation', + $token, $clashingToken + )); + } + $usedTokenIds[$tokenId] = $token; + } + } + + // Now define any tokens that have not yet been emulated. Try to assign IDs from -1 + // downwards, but skip any IDs that may already be in use. + $newTokenId = -1; + foreach ($compatTokens as $token) { + if (!\defined($token)) { + while (isset($usedTokenIds[$newTokenId])) { + $newTokenId--; + } + \define($token, $newTokenId); + $newTokenId--; + } + } + + $compatTokensDefined = true; + } + + /** + * Creates the token map. + * + * The token map maps the PHP internal token identifiers + * to the identifiers used by the Parser. Additionally it + * maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'. + * + * @return array The token map + */ + protected function createTokenMap() : array { + $tokenMap = []; + + // 256 is the minimum possible token number, as everything below + // it is an ASCII value + for ($i = 256; $i < 1000; ++$i) { + if (\T_DOUBLE_COLON === $i) { + // T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM + $tokenMap[$i] = Tokens::T_PAAMAYIM_NEKUDOTAYIM; + } elseif(\T_OPEN_TAG_WITH_ECHO === $i) { + // T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO + $tokenMap[$i] = Tokens::T_ECHO; + } elseif(\T_CLOSE_TAG === $i) { + // T_CLOSE_TAG is equivalent to ';' + $tokenMap[$i] = ord(';'); + } elseif ('UNKNOWN' !== $name = token_name($i)) { + if ('T_HASHBANG' === $name) { + // HHVM uses a special token for #! hashbang lines + $tokenMap[$i] = Tokens::T_INLINE_HTML; + } elseif (defined($name = Tokens::class . '::' . $name)) { + // Other tokens can be mapped directly + $tokenMap[$i] = constant($name); + } + } + } + + // HHVM uses a special token for numbers that overflow to double + if (defined('T_ONUMBER')) { + $tokenMap[\T_ONUMBER] = Tokens::T_DNUMBER; + } + // HHVM also has a separate token for the __COMPILER_HALT_OFFSET__ constant + if (defined('T_COMPILER_HALT_OFFSET')) { + $tokenMap[\T_COMPILER_HALT_OFFSET] = Tokens::T_STRING; + } + + // Assign tokens for which we define compatibility constants, as token_name() does not know them. + $tokenMap[\T_FN] = Tokens::T_FN; + $tokenMap[\T_COALESCE_EQUAL] = Tokens::T_COALESCE_EQUAL; + $tokenMap[\T_NAME_QUALIFIED] = Tokens::T_NAME_QUALIFIED; + $tokenMap[\T_NAME_FULLY_QUALIFIED] = Tokens::T_NAME_FULLY_QUALIFIED; + $tokenMap[\T_NAME_RELATIVE] = Tokens::T_NAME_RELATIVE; + $tokenMap[\T_MATCH] = Tokens::T_MATCH; + $tokenMap[\T_NULLSAFE_OBJECT_OPERATOR] = Tokens::T_NULLSAFE_OBJECT_OPERATOR; + $tokenMap[\T_ATTRIBUTE] = Tokens::T_ATTRIBUTE; + $tokenMap[\T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG; + $tokenMap[\T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG; + $tokenMap[\T_ENUM] = Tokens::T_ENUM; + $tokenMap[\T_READONLY] = Tokens::T_READONLY; + + return $tokenMap; + } + + private function createIdentifierTokenMap(): array { + // Based on semi_reserved production. + return array_fill_keys([ + \T_STRING, + \T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC, \T_READONLY, + \T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND, + \T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE, + \T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH, + \T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO, + \T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT, + \T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS, + \T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN, + \T_MATCH, + ], true); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php new file mode 100644 index 00000000..b0929f3c --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php @@ -0,0 +1,251 @@ +targetPhpVersion = $options['phpVersion'] ?? Emulative::PHP_8_2; + unset($options['phpVersion']); + + parent::__construct($options); + + $emulators = [ + new FlexibleDocStringEmulator(), + new FnTokenEmulator(), + new MatchTokenEmulator(), + new CoaleseEqualTokenEmulator(), + new NumericLiteralSeparatorEmulator(), + new NullsafeTokenEmulator(), + new AttributeEmulator(), + new EnumTokenEmulator(), + new ReadonlyTokenEmulator(), + new ExplicitOctalEmulator(), + new ReadonlyFunctionTokenEmulator(), + ]; + + // Collect emulators that are relevant for the PHP version we're running + // and the PHP version we're targeting for emulation. + foreach ($emulators as $emulator) { + $emulatorPhpVersion = $emulator->getPhpVersion(); + if ($this->isForwardEmulationNeeded($emulatorPhpVersion)) { + $this->emulators[] = $emulator; + } else if ($this->isReverseEmulationNeeded($emulatorPhpVersion)) { + $this->emulators[] = new ReverseEmulator($emulator); + } + } + } + + public function startLexing(string $code, ErrorHandler $errorHandler = null) { + $emulators = array_filter($this->emulators, function($emulator) use($code) { + return $emulator->isEmulationNeeded($code); + }); + + if (empty($emulators)) { + // Nothing to emulate, yay + parent::startLexing($code, $errorHandler); + return; + } + + $this->patches = []; + foreach ($emulators as $emulator) { + $code = $emulator->preprocessCode($code, $this->patches); + } + + $collector = new ErrorHandler\Collecting(); + parent::startLexing($code, $collector); + $this->sortPatches(); + $this->fixupTokens(); + + $errors = $collector->getErrors(); + if (!empty($errors)) { + $this->fixupErrors($errors); + foreach ($errors as $error) { + $errorHandler->handleError($error); + } + } + + foreach ($emulators as $emulator) { + $this->tokens = $emulator->emulate($code, $this->tokens); + } + } + + private function isForwardEmulationNeeded(string $emulatorPhpVersion): bool { + return version_compare(\PHP_VERSION, $emulatorPhpVersion, '<') + && version_compare($this->targetPhpVersion, $emulatorPhpVersion, '>='); + } + + private function isReverseEmulationNeeded(string $emulatorPhpVersion): bool { + return version_compare(\PHP_VERSION, $emulatorPhpVersion, '>=') + && version_compare($this->targetPhpVersion, $emulatorPhpVersion, '<'); + } + + private function sortPatches() + { + // Patches may be contributed by different emulators. + // Make sure they are sorted by increasing patch position. + usort($this->patches, function($p1, $p2) { + return $p1[0] <=> $p2[0]; + }); + } + + private function fixupTokens() + { + if (\count($this->patches) === 0) { + return; + } + + // Load first patch + $patchIdx = 0; + + list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; + + // We use a manual loop over the tokens, because we modify the array on the fly + $pos = 0; + for ($i = 0, $c = \count($this->tokens); $i < $c; $i++) { + $token = $this->tokens[$i]; + if (\is_string($token)) { + if ($patchPos === $pos) { + // Only support replacement for string tokens. + assert($patchType === 'replace'); + $this->tokens[$i] = $patchText; + + // Fetch the next patch + $patchIdx++; + if ($patchIdx >= \count($this->patches)) { + // No more patches, we're done + return; + } + list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; + } + + $pos += \strlen($token); + continue; + } + + $len = \strlen($token[1]); + $posDelta = 0; + while ($patchPos >= $pos && $patchPos < $pos + $len) { + $patchTextLen = \strlen($patchText); + if ($patchType === 'remove') { + if ($patchPos === $pos && $patchTextLen === $len) { + // Remove token entirely + array_splice($this->tokens, $i, 1, []); + $i--; + $c--; + } else { + // Remove from token string + $this->tokens[$i][1] = substr_replace( + $token[1], '', $patchPos - $pos + $posDelta, $patchTextLen + ); + $posDelta -= $patchTextLen; + } + } elseif ($patchType === 'add') { + // Insert into the token string + $this->tokens[$i][1] = substr_replace( + $token[1], $patchText, $patchPos - $pos + $posDelta, 0 + ); + $posDelta += $patchTextLen; + } else if ($patchType === 'replace') { + // Replace inside the token string + $this->tokens[$i][1] = substr_replace( + $token[1], $patchText, $patchPos - $pos + $posDelta, $patchTextLen + ); + } else { + assert(false); + } + + // Fetch the next patch + $patchIdx++; + if ($patchIdx >= \count($this->patches)) { + // No more patches, we're done + return; + } + + list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; + + // Multiple patches may apply to the same token. Reload the current one to check + // If the new patch applies + $token = $this->tokens[$i]; + } + + $pos += $len; + } + + // A patch did not apply + assert(false); + } + + /** + * Fixup line and position information in errors. + * + * @param Error[] $errors + */ + private function fixupErrors(array $errors) { + foreach ($errors as $error) { + $attrs = $error->getAttributes(); + + $posDelta = 0; + $lineDelta = 0; + foreach ($this->patches as $patch) { + list($patchPos, $patchType, $patchText) = $patch; + if ($patchPos >= $attrs['startFilePos']) { + // No longer relevant + break; + } + + if ($patchType === 'add') { + $posDelta += strlen($patchText); + $lineDelta += substr_count($patchText, "\n"); + } else if ($patchType === 'remove') { + $posDelta -= strlen($patchText); + $lineDelta -= substr_count($patchText, "\n"); + } + } + + $attrs['startFilePos'] += $posDelta; + $attrs['endFilePos'] += $posDelta; + $attrs['startLine'] += $lineDelta; + $attrs['endLine'] += $lineDelta; + $error->setAttributes($attrs); + } + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php new file mode 100644 index 00000000..6776a519 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php @@ -0,0 +1,56 @@ +resolveIntegerOrFloatToken($tokens[$i + 1][1]); + array_splice($tokens, $i, 2, [ + [$tokenKind, '0' . $tokens[$i + 1][1], $tokens[$i][2]], + ]); + $c--; + } + } + return $tokens; + } + + private function resolveIntegerOrFloatToken(string $str): int + { + $str = substr($str, 1); + $str = str_replace('_', '', $str); + $num = octdec($str); + return is_float($num) ? \T_DNUMBER : \T_LNUMBER; + } + + public function reverseEmulate(string $code, array $tokens): array { + // Explicit octals were not legal code previously, don't bother. + return $tokens; + } +} \ No newline at end of file diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php new file mode 100644 index 00000000..c15d6271 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php @@ -0,0 +1,76 @@ +\h*)\2(?![a-zA-Z0-9_\x80-\xff])(?(?:;?[\r\n])?)/x +REGEX; + + public function getPhpVersion(): string + { + return Emulative::PHP_7_3; + } + + public function isEmulationNeeded(string $code) : bool + { + return strpos($code, '<<<') !== false; + } + + public function emulate(string $code, array $tokens): array + { + // Handled by preprocessing + fixup. + return $tokens; + } + + public function reverseEmulate(string $code, array $tokens): array + { + // Not supported. + return $tokens; + } + + public function preprocessCode(string $code, array &$patches): string { + if (!preg_match_all(self::FLEXIBLE_DOC_STRING_REGEX, $code, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE)) { + // No heredoc/nowdoc found + return $code; + } + + // Keep track of how much we need to adjust string offsets due to the modifications we + // already made + $posDelta = 0; + foreach ($matches as $match) { + $indentation = $match['indentation'][0]; + $indentationStart = $match['indentation'][1]; + + $separator = $match['separator'][0]; + $separatorStart = $match['separator'][1]; + + if ($indentation === '' && $separator !== '') { + // Ordinary heredoc/nowdoc + continue; + } + + if ($indentation !== '') { + // Remove indentation + $indentationLen = strlen($indentation); + $code = substr_replace($code, '', $indentationStart + $posDelta, $indentationLen); + $patches[] = [$indentationStart + $posDelta, 'add', $indentation]; + $posDelta -= $indentationLen; + } + + if ($separator === '') { + // Insert newline as separator + $code = substr_replace($code, "\n", $separatorStart + $posDelta, 0); + $patches[] = [$separatorStart + $posDelta, 'remove', "\n"]; + $posDelta += 1; + } + } + + return $code; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php new file mode 100644 index 00000000..eb7e4963 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php @@ -0,0 +1,23 @@ +getKeywordString()) !== false; + } + + protected function isKeywordContext(array $tokens, int $pos): bool + { + $previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $pos); + return $previousNonSpaceToken === null || $previousNonSpaceToken[0] !== \T_OBJECT_OPERATOR; + } + + public function emulate(string $code, array $tokens): array + { + $keywordString = $this->getKeywordString(); + foreach ($tokens as $i => $token) { + if ($token[0] === T_STRING && strtolower($token[1]) === $keywordString + && $this->isKeywordContext($tokens, $i)) { + $tokens[$i][0] = $this->getKeywordToken(); + } + } + + return $tokens; + } + + /** + * @param mixed[] $tokens + * @return array|string|null + */ + private function getPreviousNonSpaceToken(array $tokens, int $start) + { + for ($i = $start - 1; $i >= 0; --$i) { + if ($tokens[$i][0] === T_WHITESPACE) { + continue; + } + + return $tokens[$i]; + } + + return null; + } + + public function reverseEmulate(string $code, array $tokens): array + { + $keywordToken = $this->getKeywordToken(); + foreach ($tokens as $i => $token) { + if ($token[0] === $keywordToken) { + $tokens[$i][0] = \T_STRING; + } + } + + return $tokens; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php new file mode 100644 index 00000000..902a46df --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php @@ -0,0 +1,23 @@ +') !== false; + } + + public function emulate(string $code, array $tokens): array + { + // We need to manually iterate and manage a count because we'll change + // the tokens array on the way + $line = 1; + for ($i = 0, $c = count($tokens); $i < $c; ++$i) { + if ($tokens[$i] === '?' && isset($tokens[$i + 1]) && $tokens[$i + 1][0] === \T_OBJECT_OPERATOR) { + array_splice($tokens, $i, 2, [ + [\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line] + ]); + $c--; + continue; + } + + // Handle ?-> inside encapsed string. + if ($tokens[$i][0] === \T_ENCAPSED_AND_WHITESPACE && isset($tokens[$i - 1]) + && $tokens[$i - 1][0] === \T_VARIABLE + && preg_match('/^\?->([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/', $tokens[$i][1], $matches) + ) { + $replacement = [ + [\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line], + [\T_STRING, $matches[1], $line], + ]; + if (\strlen($matches[0]) !== \strlen($tokens[$i][1])) { + $replacement[] = [ + \T_ENCAPSED_AND_WHITESPACE, + \substr($tokens[$i][1], \strlen($matches[0])), + $line + ]; + } + array_splice($tokens, $i, 1, $replacement); + $c += \count($replacement) - 1; + continue; + } + + if (\is_array($tokens[$i])) { + $line += substr_count($tokens[$i][1], "\n"); + } + } + + return $tokens; + } + + public function reverseEmulate(string $code, array $tokens): array + { + // ?-> was not valid code previously, don't bother. + return $tokens; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php new file mode 100644 index 00000000..cdf793e4 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php @@ -0,0 +1,105 @@ +resolveIntegerOrFloatToken($match); + $newTokens = [[$tokenKind, $match, $token[2]]]; + + $numTokens = 1; + $len = $tokenLen; + while ($matchLen > $len) { + $nextToken = $tokens[$i + $numTokens]; + $nextTokenText = \is_array($nextToken) ? $nextToken[1] : $nextToken; + $nextTokenLen = \strlen($nextTokenText); + + $numTokens++; + if ($matchLen < $len + $nextTokenLen) { + // Split trailing characters into a partial token. + assert(is_array($nextToken), "Partial token should be an array token"); + $partialText = substr($nextTokenText, $matchLen - $len); + $newTokens[] = [$nextToken[0], $partialText, $nextToken[2]]; + break; + } + + $len += $nextTokenLen; + } + + array_splice($tokens, $i, $numTokens, $newTokens); + $c -= $numTokens - \count($newTokens); + $codeOffset += $matchLen; + } + + return $tokens; + } + + private function resolveIntegerOrFloatToken(string $str): int + { + $str = str_replace('_', '', $str); + + if (stripos($str, '0b') === 0) { + $num = bindec($str); + } elseif (stripos($str, '0x') === 0) { + $num = hexdec($str); + } elseif (stripos($str, '0') === 0 && ctype_digit($str)) { + $num = octdec($str); + } else { + $num = +$str; + } + + return is_float($num) ? T_DNUMBER : T_LNUMBER; + } + + public function reverseEmulate(string $code, array $tokens): array + { + // Numeric separators were not legal code previously, don't bother. + return $tokens; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyFunctionTokenEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyFunctionTokenEmulator.php new file mode 100644 index 00000000..e671458c --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyFunctionTokenEmulator.php @@ -0,0 +1,31 @@ +emulator = $emulator; + } + + public function getPhpVersion(): string { + return $this->emulator->getPhpVersion(); + } + + public function isEmulationNeeded(string $code): bool { + return $this->emulator->isEmulationNeeded($code); + } + + public function emulate(string $code, array $tokens): array { + return $this->emulator->reverseEmulate($code, $tokens); + } + + public function reverseEmulate(string $code, array $tokens): array { + return $this->emulator->emulate($code, $tokens); + } + + public function preprocessCode(string $code, array &$patches): string { + return $code; + } +} \ No newline at end of file diff --git a/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php new file mode 100644 index 00000000..a020bc0f --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php @@ -0,0 +1,25 @@ + [aliasName => originalName]] */ + protected $aliases = []; + + /** @var Name[][] Same as $aliases but preserving original case */ + protected $origAliases = []; + + /** @var ErrorHandler Error handler */ + protected $errorHandler; + + /** + * Create a name context. + * + * @param ErrorHandler $errorHandler Error handling used to report errors + */ + public function __construct(ErrorHandler $errorHandler) { + $this->errorHandler = $errorHandler; + } + + /** + * Start a new namespace. + * + * This also resets the alias table. + * + * @param Name|null $namespace Null is the global namespace + */ + public function startNamespace(Name $namespace = null) { + $this->namespace = $namespace; + $this->origAliases = $this->aliases = [ + Stmt\Use_::TYPE_NORMAL => [], + Stmt\Use_::TYPE_FUNCTION => [], + Stmt\Use_::TYPE_CONSTANT => [], + ]; + } + + /** + * Add an alias / import. + * + * @param Name $name Original name + * @param string $aliasName Aliased name + * @param int $type One of Stmt\Use_::TYPE_* + * @param array $errorAttrs Attributes to use to report an error + */ + public function addAlias(Name $name, string $aliasName, int $type, array $errorAttrs = []) { + // Constant names are case sensitive, everything else case insensitive + if ($type === Stmt\Use_::TYPE_CONSTANT) { + $aliasLookupName = $aliasName; + } else { + $aliasLookupName = strtolower($aliasName); + } + + if (isset($this->aliases[$type][$aliasLookupName])) { + $typeStringMap = [ + Stmt\Use_::TYPE_NORMAL => '', + Stmt\Use_::TYPE_FUNCTION => 'function ', + Stmt\Use_::TYPE_CONSTANT => 'const ', + ]; + + $this->errorHandler->handleError(new Error( + sprintf( + 'Cannot use %s%s as %s because the name is already in use', + $typeStringMap[$type], $name, $aliasName + ), + $errorAttrs + )); + return; + } + + $this->aliases[$type][$aliasLookupName] = $name; + $this->origAliases[$type][$aliasName] = $name; + } + + /** + * Get current namespace. + * + * @return null|Name Namespace (or null if global namespace) + */ + public function getNamespace() { + return $this->namespace; + } + + /** + * Get resolved name. + * + * @param Name $name Name to resolve + * @param int $type One of Stmt\Use_::TYPE_{FUNCTION|CONSTANT} + * + * @return null|Name Resolved name, or null if static resolution is not possible + */ + public function getResolvedName(Name $name, int $type) { + // don't resolve special class names + if ($type === Stmt\Use_::TYPE_NORMAL && $name->isSpecialClassName()) { + if (!$name->isUnqualified()) { + $this->errorHandler->handleError(new Error( + sprintf("'\\%s' is an invalid class name", $name->toString()), + $name->getAttributes() + )); + } + return $name; + } + + // fully qualified names are already resolved + if ($name->isFullyQualified()) { + return $name; + } + + // Try to resolve aliases + if (null !== $resolvedName = $this->resolveAlias($name, $type)) { + return $resolvedName; + } + + if ($type !== Stmt\Use_::TYPE_NORMAL && $name->isUnqualified()) { + if (null === $this->namespace) { + // outside of a namespace unaliased unqualified is same as fully qualified + return new FullyQualified($name, $name->getAttributes()); + } + + // Cannot resolve statically + return null; + } + + // if no alias exists prepend current namespace + return FullyQualified::concat($this->namespace, $name, $name->getAttributes()); + } + + /** + * Get resolved class name. + * + * @param Name $name Class ame to resolve + * + * @return Name Resolved name + */ + public function getResolvedClassName(Name $name) : Name { + return $this->getResolvedName($name, Stmt\Use_::TYPE_NORMAL); + } + + /** + * Get possible ways of writing a fully qualified name (e.g., by making use of aliases). + * + * @param string $name Fully-qualified name (without leading namespace separator) + * @param int $type One of Stmt\Use_::TYPE_* + * + * @return Name[] Possible representations of the name + */ + public function getPossibleNames(string $name, int $type) : array { + $lcName = strtolower($name); + + if ($type === Stmt\Use_::TYPE_NORMAL) { + // self, parent and static must always be unqualified + if ($lcName === "self" || $lcName === "parent" || $lcName === "static") { + return [new Name($name)]; + } + } + + // Collect possible ways to write this name, starting with the fully-qualified name + $possibleNames = [new FullyQualified($name)]; + + if (null !== $nsRelativeName = $this->getNamespaceRelativeName($name, $lcName, $type)) { + // Make sure there is no alias that makes the normally namespace-relative name + // into something else + if (null === $this->resolveAlias($nsRelativeName, $type)) { + $possibleNames[] = $nsRelativeName; + } + } + + // Check for relevant namespace use statements + foreach ($this->origAliases[Stmt\Use_::TYPE_NORMAL] as $alias => $orig) { + $lcOrig = $orig->toLowerString(); + if (0 === strpos($lcName, $lcOrig . '\\')) { + $possibleNames[] = new Name($alias . substr($name, strlen($lcOrig))); + } + } + + // Check for relevant type-specific use statements + foreach ($this->origAliases[$type] as $alias => $orig) { + if ($type === Stmt\Use_::TYPE_CONSTANT) { + // Constants are are complicated-sensitive + $normalizedOrig = $this->normalizeConstName($orig->toString()); + if ($normalizedOrig === $this->normalizeConstName($name)) { + $possibleNames[] = new Name($alias); + } + } else { + // Everything else is case-insensitive + if ($orig->toLowerString() === $lcName) { + $possibleNames[] = new Name($alias); + } + } + } + + return $possibleNames; + } + + /** + * Get shortest representation of this fully-qualified name. + * + * @param string $name Fully-qualified name (without leading namespace separator) + * @param int $type One of Stmt\Use_::TYPE_* + * + * @return Name Shortest representation + */ + public function getShortName(string $name, int $type) : Name { + $possibleNames = $this->getPossibleNames($name, $type); + + // Find shortest name + $shortestName = null; + $shortestLength = \INF; + foreach ($possibleNames as $possibleName) { + $length = strlen($possibleName->toCodeString()); + if ($length < $shortestLength) { + $shortestName = $possibleName; + $shortestLength = $length; + } + } + + return $shortestName; + } + + private function resolveAlias(Name $name, $type) { + $firstPart = $name->getFirst(); + + if ($name->isQualified()) { + // resolve aliases for qualified names, always against class alias table + $checkName = strtolower($firstPart); + if (isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$checkName])) { + $alias = $this->aliases[Stmt\Use_::TYPE_NORMAL][$checkName]; + return FullyQualified::concat($alias, $name->slice(1), $name->getAttributes()); + } + } elseif ($name->isUnqualified()) { + // constant aliases are case-sensitive, function aliases case-insensitive + $checkName = $type === Stmt\Use_::TYPE_CONSTANT ? $firstPart : strtolower($firstPart); + if (isset($this->aliases[$type][$checkName])) { + // resolve unqualified aliases + return new FullyQualified($this->aliases[$type][$checkName], $name->getAttributes()); + } + } + + // No applicable aliases + return null; + } + + private function getNamespaceRelativeName(string $name, string $lcName, int $type) { + if (null === $this->namespace) { + return new Name($name); + } + + if ($type === Stmt\Use_::TYPE_CONSTANT) { + // The constants true/false/null always resolve to the global symbols, even inside a + // namespace, so they may be used without qualification + if ($lcName === "true" || $lcName === "false" || $lcName === "null") { + return new Name($name); + } + } + + $namespacePrefix = strtolower($this->namespace . '\\'); + if (0 === strpos($lcName, $namespacePrefix)) { + return new Name(substr($name, strlen($namespacePrefix))); + } + + return null; + } + + private function normalizeConstName(string $name) { + $nsSep = strrpos($name, '\\'); + if (false === $nsSep) { + return $name; + } + + // Constants have case-insensitive namespace and case-sensitive short-name + $ns = substr($name, 0, $nsSep); + $shortName = substr($name, $nsSep + 1); + return strtolower($ns) . '\\' . $shortName; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node.php b/vendor/nikic/php-parser/lib/PhpParser/Node.php new file mode 100644 index 00000000..befb2565 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node.php @@ -0,0 +1,151 @@ +attributes = $attributes; + $this->name = $name; + $this->value = $value; + $this->byRef = $byRef; + $this->unpack = $unpack; + } + + public function getSubNodeNames() : array { + return ['name', 'value', 'byRef', 'unpack']; + } + + public function getType() : string { + return 'Arg'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php new file mode 100644 index 00000000..c96f66e5 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->name = $name; + $this->args = $args; + } + + public function getSubNodeNames() : array { + return ['name', 'args']; + } + + public function getType() : string { + return 'Attribute'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php b/vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php new file mode 100644 index 00000000..613bfc41 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php @@ -0,0 +1,29 @@ +attributes = $attributes; + $this->attrs = $attrs; + } + + public function getSubNodeNames() : array { + return ['attrs']; + } + + public function getType() : string { + return 'AttributeGroup'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/ComplexType.php b/vendor/nikic/php-parser/lib/PhpParser/Node/ComplexType.php new file mode 100644 index 00000000..9505532a --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/ComplexType.php @@ -0,0 +1,14 @@ +attributes = $attributes; + $this->name = \is_string($name) ? new Identifier($name) : $name; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['name', 'value']; + } + + public function getType() : string { + return 'Const'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php new file mode 100644 index 00000000..6cf4df22 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php @@ -0,0 +1,9 @@ +attributes = $attributes; + $this->var = $var; + $this->dim = $dim; + } + + public function getSubNodeNames() : array { + return ['var', 'dim']; + } + + public function getType() : string { + return 'Expr_ArrayDimFetch'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php new file mode 100644 index 00000000..1b078f82 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php @@ -0,0 +1,41 @@ +attributes = $attributes; + $this->key = $key; + $this->value = $value; + $this->byRef = $byRef; + $this->unpack = $unpack; + } + + public function getSubNodeNames() : array { + return ['key', 'value', 'byRef', 'unpack']; + } + + public function getType() : string { + return 'Expr_ArrayItem'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php new file mode 100644 index 00000000..e6eaa283 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->items = $items; + } + + public function getSubNodeNames() : array { + return ['items']; + } + + public function getType() : string { + return 'Expr_Array'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php new file mode 100644 index 00000000..c273fb7e --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php @@ -0,0 +1,79 @@ + false : Whether the closure is static + * 'byRef' => false : Whether to return by reference + * 'params' => array() : Parameters + * 'returnType' => null : Return type + * 'expr' => Expr : Expression body + * 'attrGroups' => array() : PHP attribute groups + * @param array $attributes Additional attributes + */ + public function __construct(array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->static = $subNodes['static'] ?? false; + $this->byRef = $subNodes['byRef'] ?? false; + $this->params = $subNodes['params'] ?? []; + $returnType = $subNodes['returnType'] ?? null; + $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; + $this->expr = $subNodes['expr']; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'static', 'byRef', 'params', 'returnType', 'expr']; + } + + public function returnsByRef() : bool { + return $this->byRef; + } + + public function getParams() : array { + return $this->params; + } + + public function getReturnType() { + return $this->returnType; + } + + public function getAttrGroups() : array { + return $this->attrGroups; + } + + /** + * @return Node\Stmt\Return_[] + */ + public function getStmts() : array { + return [new Node\Stmt\Return_($this->expr)]; + } + + public function getType() : string { + return 'Expr_ArrowFunction'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php new file mode 100644 index 00000000..cf9e6e82 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->var = $var; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['var', 'expr']; + } + + public function getType() : string { + return 'Expr_Assign'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php new file mode 100644 index 00000000..bce8604f --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->var = $var; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['var', 'expr']; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php new file mode 100644 index 00000000..420284cd --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php @@ -0,0 +1,12 @@ +attributes = $attributes; + $this->var = $var; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['var', 'expr']; + } + + public function getType() : string { + return 'Expr_AssignRef'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php new file mode 100644 index 00000000..d9c582b0 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php @@ -0,0 +1,40 @@ +attributes = $attributes; + $this->left = $left; + $this->right = $right; + } + + public function getSubNodeNames() : array { + return ['left', 'right']; + } + + /** + * Get the operator sigil for this binary operation. + * + * In the case there are multiple possible sigils for an operator, this method does not + * necessarily return the one used in the parsed code. + * + * @return string + */ + abstract public function getOperatorSigil() : string; +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php new file mode 100644 index 00000000..d907393b --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php @@ -0,0 +1,16 @@ +'; + } + + public function getType() : string { + return 'Expr_BinaryOp_Greater'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php new file mode 100644 index 00000000..d677502c --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php @@ -0,0 +1,16 @@ +='; + } + + public function getType() : string { + return 'Expr_BinaryOp_GreaterOrEqual'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php new file mode 100644 index 00000000..3d96285c --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php @@ -0,0 +1,16 @@ +>'; + } + + public function getType() : string { + return 'Expr_BinaryOp_ShiftRight'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php new file mode 100644 index 00000000..3cb8e7e0 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php @@ -0,0 +1,16 @@ +'; + } + + public function getType() : string { + return 'Expr_BinaryOp_Spaceship'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php new file mode 100644 index 00000000..ed44984b --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_BitwiseNot'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php new file mode 100644 index 00000000..bf27e9f6 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_BooleanNot'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php new file mode 100644 index 00000000..78e1cf34 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php @@ -0,0 +1,39 @@ + + */ + abstract public function getRawArgs(): array; + + /** + * Returns whether this call expression is actually a first class callable. + */ + public function isFirstClassCallable(): bool { + foreach ($this->getRawArgs() as $arg) { + if ($arg instanceof VariadicPlaceholder) { + return true; + } + } + return false; + } + + /** + * Assert that this is not a first-class callable and return only ordinary Args. + * + * @return Arg[] + */ + public function getArgs(): array { + assert(!$this->isFirstClassCallable()); + return $this->getRawArgs(); + } +} \ No newline at end of file diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php new file mode 100644 index 00000000..36769d4f --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php @@ -0,0 +1,26 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php new file mode 100644 index 00000000..57cc473b --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php @@ -0,0 +1,12 @@ +attributes = $attributes; + $this->class = $class; + $this->name = \is_string($name) ? new Identifier($name) : $name; + } + + public function getSubNodeNames() : array { + return ['class', 'name']; + } + + public function getType() : string { + return 'Expr_ClassConstFetch'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php new file mode 100644 index 00000000..db216b8f --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_Clone'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php new file mode 100644 index 00000000..56ddea6a --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php @@ -0,0 +1,79 @@ + false : Whether the closure is static + * 'byRef' => false : Whether to return by reference + * 'params' => array(): Parameters + * 'uses' => array(): use()s + * 'returnType' => null : Return type + * 'stmts' => array(): Statements + * 'attrGroups' => array(): PHP attributes groups + * @param array $attributes Additional attributes + */ + public function __construct(array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->static = $subNodes['static'] ?? false; + $this->byRef = $subNodes['byRef'] ?? false; + $this->params = $subNodes['params'] ?? []; + $this->uses = $subNodes['uses'] ?? []; + $returnType = $subNodes['returnType'] ?? null; + $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; + $this->stmts = $subNodes['stmts'] ?? []; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'static', 'byRef', 'params', 'uses', 'returnType', 'stmts']; + } + + public function returnsByRef() : bool { + return $this->byRef; + } + + public function getParams() : array { + return $this->params; + } + + public function getReturnType() { + return $this->returnType; + } + + /** @return Node\Stmt[] */ + public function getStmts() : array { + return $this->stmts; + } + + public function getAttrGroups() : array { + return $this->attrGroups; + } + + public function getType() : string { + return 'Expr_Closure'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php new file mode 100644 index 00000000..2b8a0966 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->var = $var; + $this->byRef = $byRef; + } + + public function getSubNodeNames() : array { + return ['var', 'byRef']; + } + + public function getType() : string { + return 'Expr_ClosureUse'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php new file mode 100644 index 00000000..14ebd16b --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php @@ -0,0 +1,31 @@ +attributes = $attributes; + $this->name = $name; + } + + public function getSubNodeNames() : array { + return ['name']; + } + + public function getType() : string { + return 'Expr_ConstFetch'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php new file mode 100644 index 00000000..4042ec93 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_Empty'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php new file mode 100644 index 00000000..1637f3ae --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php @@ -0,0 +1,31 @@ +attributes = $attributes; + } + + public function getSubNodeNames() : array { + return []; + } + + public function getType() : string { + return 'Expr_Error'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php new file mode 100644 index 00000000..c44ff6f9 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_ErrorSuppress'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php new file mode 100644 index 00000000..85685474 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_Eval'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php new file mode 100644 index 00000000..b88a8f7e --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_Exit'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php new file mode 100644 index 00000000..2de4d0dd --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php @@ -0,0 +1,39 @@ + Arguments */ + public $args; + + /** + * Constructs a function call node. + * + * @param Node\Name|Expr $name Function name + * @param array $args Arguments + * @param array $attributes Additional attributes + */ + public function __construct($name, array $args = [], array $attributes = []) { + $this->attributes = $attributes; + $this->name = $name; + $this->args = $args; + } + + public function getSubNodeNames() : array { + return ['name', 'args']; + } + + public function getType() : string { + return 'Expr_FuncCall'; + } + + public function getRawArgs(): array { + return $this->args; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php new file mode 100644 index 00000000..07ce5968 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php @@ -0,0 +1,39 @@ +attributes = $attributes; + $this->expr = $expr; + $this->type = $type; + } + + public function getSubNodeNames() : array { + return ['expr', 'type']; + } + + public function getType() : string { + return 'Expr_Include'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php new file mode 100644 index 00000000..9000d47b --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php @@ -0,0 +1,35 @@ +attributes = $attributes; + $this->expr = $expr; + $this->class = $class; + } + + public function getSubNodeNames() : array { + return ['expr', 'class']; + } + + public function getType() : string { + return 'Expr_Instanceof'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php new file mode 100644 index 00000000..76b73875 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->vars = $vars; + } + + public function getSubNodeNames() : array { + return ['vars']; + } + + public function getType() : string { + return 'Expr_Isset'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php new file mode 100644 index 00000000..c27a27b9 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->items = $items; + } + + public function getSubNodeNames() : array { + return ['items']; + } + + public function getType() : string { + return 'Expr_List'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php new file mode 100644 index 00000000..2455a302 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php @@ -0,0 +1,31 @@ +attributes = $attributes; + $this->cond = $cond; + $this->arms = $arms; + } + + public function getSubNodeNames() : array { + return ['cond', 'arms']; + } + + public function getType() : string { + return 'Expr_Match'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php new file mode 100644 index 00000000..49ca4835 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php @@ -0,0 +1,45 @@ + Arguments */ + public $args; + + /** + * Constructs a function call node. + * + * @param Expr $var Variable holding object + * @param string|Identifier|Expr $name Method name + * @param array $args Arguments + * @param array $attributes Additional attributes + */ + public function __construct(Expr $var, $name, array $args = [], array $attributes = []) { + $this->attributes = $attributes; + $this->var = $var; + $this->name = \is_string($name) ? new Identifier($name) : $name; + $this->args = $args; + } + + public function getSubNodeNames() : array { + return ['var', 'name', 'args']; + } + + public function getType() : string { + return 'Expr_MethodCall'; + } + + public function getRawArgs(): array { + return $this->args; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php new file mode 100644 index 00000000..e2bb6492 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php @@ -0,0 +1,41 @@ + Arguments */ + public $args; + + /** + * Constructs a function call node. + * + * @param Node\Name|Expr|Node\Stmt\Class_ $class Class name (or class node for anonymous classes) + * @param array $args Arguments + * @param array $attributes Additional attributes + */ + public function __construct($class, array $args = [], array $attributes = []) { + $this->attributes = $attributes; + $this->class = $class; + $this->args = $args; + } + + public function getSubNodeNames() : array { + return ['class', 'args']; + } + + public function getType() : string { + return 'Expr_New'; + } + + public function getRawArgs(): array { + return $this->args; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php new file mode 100644 index 00000000..07a571fd --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php @@ -0,0 +1,45 @@ + Arguments */ + public $args; + + /** + * Constructs a nullsafe method call node. + * + * @param Expr $var Variable holding object + * @param string|Identifier|Expr $name Method name + * @param array $args Arguments + * @param array $attributes Additional attributes + */ + public function __construct(Expr $var, $name, array $args = [], array $attributes = []) { + $this->attributes = $attributes; + $this->var = $var; + $this->name = \is_string($name) ? new Identifier($name) : $name; + $this->args = $args; + } + + public function getSubNodeNames() : array { + return ['var', 'name', 'args']; + } + + public function getType() : string { + return 'Expr_NullsafeMethodCall'; + } + + public function getRawArgs(): array { + return $this->args; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php new file mode 100644 index 00000000..9317eb3b --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php @@ -0,0 +1,35 @@ +attributes = $attributes; + $this->var = $var; + $this->name = \is_string($name) ? new Identifier($name) : $name; + } + + public function getSubNodeNames() : array { + return ['var', 'name']; + } + + public function getType() : string { + return 'Expr_NullsafePropertyFetch'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php new file mode 100644 index 00000000..94d6c296 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->var = $var; + } + + public function getSubNodeNames() : array { + return ['var']; + } + + public function getType() : string { + return 'Expr_PostDec'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php new file mode 100644 index 00000000..005c443a --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->var = $var; + } + + public function getSubNodeNames() : array { + return ['var']; + } + + public function getType() : string { + return 'Expr_PostInc'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php new file mode 100644 index 00000000..a5ca685a --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->var = $var; + } + + public function getSubNodeNames() : array { + return ['var']; + } + + public function getType() : string { + return 'Expr_PreDec'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php new file mode 100644 index 00000000..0986c447 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->var = $var; + } + + public function getSubNodeNames() : array { + return ['var']; + } + + public function getType() : string { + return 'Expr_PreInc'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php new file mode 100644 index 00000000..2d43c2ac --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_Print'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php new file mode 100644 index 00000000..4281f31c --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php @@ -0,0 +1,35 @@ +attributes = $attributes; + $this->var = $var; + $this->name = \is_string($name) ? new Identifier($name) : $name; + } + + public function getSubNodeNames() : array { + return ['var', 'name']; + } + + public function getType() : string { + return 'Expr_PropertyFetch'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php new file mode 100644 index 00000000..537a7cc8 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->parts = $parts; + } + + public function getSubNodeNames() : array { + return ['parts']; + } + + public function getType() : string { + return 'Expr_ShellExec'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php new file mode 100644 index 00000000..d0d099c4 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php @@ -0,0 +1,46 @@ + Arguments */ + public $args; + + /** + * Constructs a static method call node. + * + * @param Node\Name|Expr $class Class name + * @param string|Identifier|Expr $name Method name + * @param array $args Arguments + * @param array $attributes Additional attributes + */ + public function __construct($class, $name, array $args = [], array $attributes = []) { + $this->attributes = $attributes; + $this->class = $class; + $this->name = \is_string($name) ? new Identifier($name) : $name; + $this->args = $args; + } + + public function getSubNodeNames() : array { + return ['class', 'name', 'args']; + } + + public function getType() : string { + return 'Expr_StaticCall'; + } + + public function getRawArgs(): array { + return $this->args; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php new file mode 100644 index 00000000..1ee1a25e --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php @@ -0,0 +1,36 @@ +attributes = $attributes; + $this->class = $class; + $this->name = \is_string($name) ? new VarLikeIdentifier($name) : $name; + } + + public function getSubNodeNames() : array { + return ['class', 'name']; + } + + public function getType() : string { + return 'Expr_StaticPropertyFetch'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php new file mode 100644 index 00000000..9316f47d --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php @@ -0,0 +1,38 @@ +attributes = $attributes; + $this->cond = $cond; + $this->if = $if; + $this->else = $else; + } + + public function getSubNodeNames() : array { + return ['cond', 'if', 'else']; + } + + public function getType() : string { + return 'Expr_Ternary'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php new file mode 100644 index 00000000..5c97f0e2 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_Throw'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php new file mode 100644 index 00000000..ce8808bc --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_UnaryMinus'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php new file mode 100644 index 00000000..d23047e5 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_UnaryPlus'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php new file mode 100644 index 00000000..b47d38e9 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->name = $name; + } + + public function getSubNodeNames() : array { + return ['name']; + } + + public function getType() : string { + return 'Expr_Variable'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php new file mode 100644 index 00000000..a3efce61 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_YieldFrom'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php new file mode 100644 index 00000000..aef8fc33 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->key = $key; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['key', 'value']; + } + + public function getType() : string { + return 'Expr_Yield'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php b/vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php new file mode 100644 index 00000000..5a825e73 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php @@ -0,0 +1,43 @@ + true, + 'parent' => true, + 'static' => true, + ]; + + /** + * Constructs an identifier node. + * + * @param string $name Identifier as string + * @param array $attributes Additional attributes + */ + public function __construct(string $name, array $attributes = []) { + $this->attributes = $attributes; + $this->name = $name; + } + + public function getSubNodeNames() : array { + return ['name']; + } + + /** + * Get identifier as string. + * + * @return string Identifier as string. + */ + public function toString() : string { + return $this->name; + } + + /** + * Get lowercased identifier as string. + * + * @return string Lowercased identifier as string + */ + public function toLowerString() : string { + return strtolower($this->name); + } + + /** + * Checks whether the identifier is a special class name (self, parent or static). + * + * @return bool Whether identifier is a special class name + */ + public function isSpecialClassName() : bool { + return isset(self::$specialClassNames[strtolower($this->name)]); + } + + /** + * Get identifier as string. + * + * @return string Identifier as string + */ + public function __toString() : string { + return $this->name; + } + + public function getType() : string { + return 'Identifier'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php b/vendor/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php new file mode 100644 index 00000000..9208e139 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->types = $types; + } + + public function getSubNodeNames() : array { + return ['types']; + } + + public function getType() : string { + return 'IntersectionType'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.php b/vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.php new file mode 100644 index 00000000..2ae1c86b --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.php @@ -0,0 +1,31 @@ +conds = $conds; + $this->body = $body; + $this->attributes = $attributes; + } + + public function getSubNodeNames() : array { + return ['conds', 'body']; + } + + public function getType() : string { + return 'MatchArm'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php new file mode 100644 index 00000000..17bd1c0f --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php @@ -0,0 +1,242 @@ + true, + 'parent' => true, + 'static' => true, + ]; + + /** + * Constructs a name node. + * + * @param string|string[]|self $name Name as string, part array or Name instance (copy ctor) + * @param array $attributes Additional attributes + */ + public function __construct($name, array $attributes = []) { + $this->attributes = $attributes; + $this->parts = self::prepareName($name); + } + + public function getSubNodeNames() : array { + return ['parts']; + } + + /** + * Gets the first part of the name, i.e. everything before the first namespace separator. + * + * @return string First part of the name + */ + public function getFirst() : string { + return $this->parts[0]; + } + + /** + * Gets the last part of the name, i.e. everything after the last namespace separator. + * + * @return string Last part of the name + */ + public function getLast() : string { + return $this->parts[count($this->parts) - 1]; + } + + /** + * Checks whether the name is unqualified. (E.g. Name) + * + * @return bool Whether the name is unqualified + */ + public function isUnqualified() : bool { + return 1 === count($this->parts); + } + + /** + * Checks whether the name is qualified. (E.g. Name\Name) + * + * @return bool Whether the name is qualified + */ + public function isQualified() : bool { + return 1 < count($this->parts); + } + + /** + * Checks whether the name is fully qualified. (E.g. \Name) + * + * @return bool Whether the name is fully qualified + */ + public function isFullyQualified() : bool { + return false; + } + + /** + * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name) + * + * @return bool Whether the name is relative + */ + public function isRelative() : bool { + return false; + } + + /** + * Returns a string representation of the name itself, without taking the name type into + * account (e.g., not including a leading backslash for fully qualified names). + * + * @return string String representation + */ + public function toString() : string { + return implode('\\', $this->parts); + } + + /** + * Returns a string representation of the name as it would occur in code (e.g., including + * leading backslash for fully qualified names. + * + * @return string String representation + */ + public function toCodeString() : string { + return $this->toString(); + } + + /** + * Returns lowercased string representation of the name, without taking the name type into + * account (e.g., no leading backslash for fully qualified names). + * + * @return string Lowercased string representation + */ + public function toLowerString() : string { + return strtolower(implode('\\', $this->parts)); + } + + /** + * Checks whether the identifier is a special class name (self, parent or static). + * + * @return bool Whether identifier is a special class name + */ + public function isSpecialClassName() : bool { + return count($this->parts) === 1 + && isset(self::$specialClassNames[strtolower($this->parts[0])]); + } + + /** + * Returns a string representation of the name by imploding the namespace parts with the + * namespace separator. + * + * @return string String representation + */ + public function __toString() : string { + return implode('\\', $this->parts); + } + + /** + * Gets a slice of a name (similar to array_slice). + * + * This method returns a new instance of the same type as the original and with the same + * attributes. + * + * If the slice is empty, null is returned. The null value will be correctly handled in + * concatenations using concat(). + * + * Offset and length have the same meaning as in array_slice(). + * + * @param int $offset Offset to start the slice at (may be negative) + * @param int|null $length Length of the slice (may be negative) + * + * @return static|null Sliced name + */ + public function slice(int $offset, int $length = null) { + $numParts = count($this->parts); + + $realOffset = $offset < 0 ? $offset + $numParts : $offset; + if ($realOffset < 0 || $realOffset > $numParts) { + throw new \OutOfBoundsException(sprintf('Offset %d is out of bounds', $offset)); + } + + if (null === $length) { + $realLength = $numParts - $realOffset; + } else { + $realLength = $length < 0 ? $length + $numParts - $realOffset : $length; + if ($realLength < 0 || $realLength > $numParts - $realOffset) { + throw new \OutOfBoundsException(sprintf('Length %d is out of bounds', $length)); + } + } + + if ($realLength === 0) { + // Empty slice is represented as null + return null; + } + + return new static(array_slice($this->parts, $realOffset, $realLength), $this->attributes); + } + + /** + * Concatenate two names, yielding a new Name instance. + * + * The type of the generated instance depends on which class this method is called on, for + * example Name\FullyQualified::concat() will yield a Name\FullyQualified instance. + * + * If one of the arguments is null, a new instance of the other name will be returned. If both + * arguments are null, null will be returned. As such, writing + * Name::concat($namespace, $shortName) + * where $namespace is a Name node or null will work as expected. + * + * @param string|string[]|self|null $name1 The first name + * @param string|string[]|self|null $name2 The second name + * @param array $attributes Attributes to assign to concatenated name + * + * @return static|null Concatenated name + */ + public static function concat($name1, $name2, array $attributes = []) { + if (null === $name1 && null === $name2) { + return null; + } elseif (null === $name1) { + return new static(self::prepareName($name2), $attributes); + } elseif (null === $name2) { + return new static(self::prepareName($name1), $attributes); + } else { + return new static( + array_merge(self::prepareName($name1), self::prepareName($name2)), $attributes + ); + } + } + + /** + * Prepares a (string, array or Name node) name for use in name changing methods by converting + * it to an array. + * + * @param string|string[]|self $name Name to prepare + * + * @return string[] Prepared name + */ + private static function prepareName($name) : array { + if (\is_string($name)) { + if ('' === $name) { + throw new \InvalidArgumentException('Name cannot be empty'); + } + + return explode('\\', $name); + } elseif (\is_array($name)) { + if (empty($name)) { + throw new \InvalidArgumentException('Name cannot be empty'); + } + + return $name; + } elseif ($name instanceof self) { + return $name->parts; + } + + throw new \InvalidArgumentException( + 'Expected string, array of parts or Name instance' + ); + } + + public function getType() : string { + return 'Name'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php new file mode 100644 index 00000000..1df93a56 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php @@ -0,0 +1,50 @@ +toString(); + } + + public function getType() : string { + return 'Name_FullyQualified'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php new file mode 100644 index 00000000..57bf7af2 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php @@ -0,0 +1,50 @@ +toString(); + } + + public function getType() : string { + return 'Name_Relative'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.php b/vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.php new file mode 100644 index 00000000..d68e26a3 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.php @@ -0,0 +1,28 @@ +attributes = $attributes; + $this->type = \is_string($type) ? new Identifier($type) : $type; + } + + public function getSubNodeNames() : array { + return ['type']; + } + + public function getType() : string { + return 'NullableType'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php new file mode 100644 index 00000000..1e90b794 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php @@ -0,0 +1,60 @@ +attributes = $attributes; + $this->type = \is_string($type) ? new Identifier($type) : $type; + $this->byRef = $byRef; + $this->variadic = $variadic; + $this->var = $var; + $this->default = $default; + $this->flags = $flags; + $this->attrGroups = $attrGroups; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; + } + + public function getType() : string { + return 'Param'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php new file mode 100644 index 00000000..8117909b --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php @@ -0,0 +1,7 @@ +attributes = $attributes; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['value']; + } + + /** + * @param mixed[] $attributes + */ + public static function fromString(string $str, array $attributes = []): DNumber + { + $attributes['rawValue'] = $str; + $float = self::parse($str); + + return new DNumber($float, $attributes); + } + + /** + * @internal + * + * Parses a DNUMBER token like PHP would. + * + * @param string $str A string number + * + * @return float The parsed number + */ + public static function parse(string $str) : float { + $str = str_replace('_', '', $str); + + // Check whether this is one of the special integer notations. + if ('0' === $str[0]) { + // hex + if ('x' === $str[1] || 'X' === $str[1]) { + return hexdec($str); + } + + // bin + if ('b' === $str[1] || 'B' === $str[1]) { + return bindec($str); + } + + // oct, but only if the string does not contain any of '.eE'. + if (false === strpbrk($str, '.eE')) { + // substr($str, 0, strcspn($str, '89')) cuts the string at the first invalid digit + // (8 or 9) so that only the digits before that are used. + return octdec(substr($str, 0, strcspn($str, '89'))); + } + } + + // dec + return (float) $str; + } + + public function getType() : string { + return 'Scalar_DNumber'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php new file mode 100644 index 00000000..fa5d2e26 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php @@ -0,0 +1,31 @@ +attributes = $attributes; + $this->parts = $parts; + } + + public function getSubNodeNames() : array { + return ['parts']; + } + + public function getType() : string { + return 'Scalar_Encapsed'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php new file mode 100644 index 00000000..bb3194c1 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['value']; + } + + public function getType() : string { + return 'Scalar_EncapsedStringPart'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php new file mode 100644 index 00000000..2cc2b22c --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php @@ -0,0 +1,80 @@ +attributes = $attributes; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['value']; + } + + /** + * Constructs an LNumber node from a string number literal. + * + * @param string $str String number literal (decimal, octal, hex or binary) + * @param array $attributes Additional attributes + * @param bool $allowInvalidOctal Whether to allow invalid octal numbers (PHP 5) + * + * @return LNumber The constructed LNumber, including kind attribute + */ + public static function fromString(string $str, array $attributes = [], bool $allowInvalidOctal = false) : LNumber { + $attributes['rawValue'] = $str; + + $str = str_replace('_', '', $str); + + if ('0' !== $str[0] || '0' === $str) { + $attributes['kind'] = LNumber::KIND_DEC; + return new LNumber((int) $str, $attributes); + } + + if ('x' === $str[1] || 'X' === $str[1]) { + $attributes['kind'] = LNumber::KIND_HEX; + return new LNumber(hexdec($str), $attributes); + } + + if ('b' === $str[1] || 'B' === $str[1]) { + $attributes['kind'] = LNumber::KIND_BIN; + return new LNumber(bindec($str), $attributes); + } + + if (!$allowInvalidOctal && strpbrk($str, '89')) { + throw new Error('Invalid numeric literal', $attributes); + } + + // Strip optional explicit octal prefix. + if ('o' === $str[1] || 'O' === $str[1]) { + $str = substr($str, 2); + } + + // use intval instead of octdec to get proper cutting behavior with malformed numbers + $attributes['kind'] = LNumber::KIND_OCT; + return new LNumber(intval($str, 8), $attributes); + } + + public function getType() : string { + return 'Scalar_LNumber'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php new file mode 100644 index 00000000..941f0c76 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php @@ -0,0 +1,28 @@ +attributes = $attributes; + } + + public function getSubNodeNames() : array { + return []; + } + + /** + * Get name of magic constant. + * + * @return string Name of magic constant + */ + abstract public function getName() : string; +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php new file mode 100644 index 00000000..24432847 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php @@ -0,0 +1,16 @@ + '\\', + '$' => '$', + 'n' => "\n", + 'r' => "\r", + 't' => "\t", + 'f' => "\f", + 'v' => "\v", + 'e' => "\x1B", + ]; + + /** + * Constructs a string scalar node. + * + * @param string $value Value of the string + * @param array $attributes Additional attributes + */ + public function __construct(string $value, array $attributes = []) { + $this->attributes = $attributes; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['value']; + } + + /** + * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes + */ + public static function fromString(string $str, array $attributes = [], bool $parseUnicodeEscape = true): self + { + $attributes['kind'] = ($str[0] === "'" || ($str[1] === "'" && ($str[0] === 'b' || $str[0] === 'B'))) + ? Scalar\String_::KIND_SINGLE_QUOTED + : Scalar\String_::KIND_DOUBLE_QUOTED; + + $attributes['rawValue'] = $str; + + $string = self::parse($str, $parseUnicodeEscape); + + return new self($string, $attributes); + } + + /** + * @internal + * + * Parses a string token. + * + * @param string $str String token content + * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes + * + * @return string The parsed string + */ + public static function parse(string $str, bool $parseUnicodeEscape = true) : string { + $bLength = 0; + if ('b' === $str[0] || 'B' === $str[0]) { + $bLength = 1; + } + + if ('\'' === $str[$bLength]) { + return str_replace( + ['\\\\', '\\\''], + ['\\', '\''], + substr($str, $bLength + 1, -1) + ); + } else { + return self::parseEscapeSequences( + substr($str, $bLength + 1, -1), '"', $parseUnicodeEscape + ); + } + } + + /** + * @internal + * + * Parses escape sequences in strings (all string types apart from single quoted). + * + * @param string $str String without quotes + * @param null|string $quote Quote type + * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes + * + * @return string String with escape sequences parsed + */ + public static function parseEscapeSequences(string $str, $quote, bool $parseUnicodeEscape = true) : string { + if (null !== $quote) { + $str = str_replace('\\' . $quote, $quote, $str); + } + + $extra = ''; + if ($parseUnicodeEscape) { + $extra = '|u\{([0-9a-fA-F]+)\}'; + } + + return preg_replace_callback( + '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}' . $extra . ')~', + function($matches) { + $str = $matches[1]; + + if (isset(self::$replacements[$str])) { + return self::$replacements[$str]; + } elseif ('x' === $str[0] || 'X' === $str[0]) { + return chr(hexdec(substr($str, 1))); + } elseif ('u' === $str[0]) { + return self::codePointToUtf8(hexdec($matches[2])); + } else { + return chr(octdec($str)); + } + }, + $str + ); + } + + /** + * Converts a Unicode code point to its UTF-8 encoded representation. + * + * @param int $num Code point + * + * @return string UTF-8 representation of code point + */ + private static function codePointToUtf8(int $num) : string { + if ($num <= 0x7F) { + return chr($num); + } + if ($num <= 0x7FF) { + return chr(($num>>6) + 0xC0) . chr(($num&0x3F) + 0x80); + } + if ($num <= 0xFFFF) { + return chr(($num>>12) + 0xE0) . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80); + } + if ($num <= 0x1FFFFF) { + return chr(($num>>18) + 0xF0) . chr((($num>>12)&0x3F) + 0x80) + . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80); + } + throw new Error('Invalid UTF-8 codepoint escape sequence: Codepoint too large'); + } + + public function getType() : string { + return 'Scalar_String'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.php new file mode 100644 index 00000000..69d33e57 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.php @@ -0,0 +1,9 @@ +attributes = $attributes; + $this->num = $num; + } + + public function getSubNodeNames() : array { + return ['num']; + } + + public function getType() : string { + return 'Stmt_Break'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php new file mode 100644 index 00000000..2bf044c9 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->cond = $cond; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['cond', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Case'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php new file mode 100644 index 00000000..9b9c0947 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php @@ -0,0 +1,41 @@ +attributes = $attributes; + $this->types = $types; + $this->var = $var; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['types', 'var', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Catch'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php new file mode 100644 index 00000000..1fc7f336 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php @@ -0,0 +1,80 @@ +attributes = $attributes; + $this->flags = $flags; + $this->consts = $consts; + $this->attrGroups = $attrGroups; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'flags', 'consts']; + } + + /** + * Whether constant is explicitly or implicitly public. + * + * @return bool + */ + public function isPublic() : bool { + return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 + || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; + } + + /** + * Whether constant is protected. + * + * @return bool + */ + public function isProtected() : bool { + return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); + } + + /** + * Whether constant is private. + * + * @return bool + */ + public function isPrivate() : bool { + return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); + } + + /** + * Whether constant is final. + * + * @return bool + */ + public function isFinal() : bool { + return (bool) ($this->flags & Class_::MODIFIER_FINAL); + } + + public function getType() : string { + return 'Stmt_ClassConst'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php new file mode 100644 index 00000000..2fa4e861 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php @@ -0,0 +1,109 @@ +stmts as $stmt) { + if ($stmt instanceof TraitUse) { + $traitUses[] = $stmt; + } + } + return $traitUses; + } + + /** + * @return ClassConst[] + */ + public function getConstants() : array { + $constants = []; + foreach ($this->stmts as $stmt) { + if ($stmt instanceof ClassConst) { + $constants[] = $stmt; + } + } + return $constants; + } + + /** + * @return Property[] + */ + public function getProperties() : array { + $properties = []; + foreach ($this->stmts as $stmt) { + if ($stmt instanceof Property) { + $properties[] = $stmt; + } + } + return $properties; + } + + /** + * Gets property with the given name defined directly in this class/interface/trait. + * + * @param string $name Name of the property + * + * @return Property|null Property node or null if the property does not exist + */ + public function getProperty(string $name) { + foreach ($this->stmts as $stmt) { + if ($stmt instanceof Property) { + foreach ($stmt->props as $prop) { + if ($prop instanceof PropertyProperty && $name === $prop->name->toString()) { + return $stmt; + } + } + } + } + return null; + } + + /** + * Gets all methods defined directly in this class/interface/trait + * + * @return ClassMethod[] + */ + public function getMethods() : array { + $methods = []; + foreach ($this->stmts as $stmt) { + if ($stmt instanceof ClassMethod) { + $methods[] = $stmt; + } + } + return $methods; + } + + /** + * Gets method with the given name defined directly in this class/interface/trait. + * + * @param string $name Name of the method (compared case-insensitively) + * + * @return ClassMethod|null Method node or null if the method does not exist + */ + public function getMethod(string $name) { + $lowerName = strtolower($name); + foreach ($this->stmts as $stmt) { + if ($stmt instanceof ClassMethod && $lowerName === $stmt->name->toLowerString()) { + return $stmt; + } + } + return null; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php new file mode 100644 index 00000000..6e85161e --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php @@ -0,0 +1,161 @@ + true, + '__destruct' => true, + '__call' => true, + '__callstatic' => true, + '__get' => true, + '__set' => true, + '__isset' => true, + '__unset' => true, + '__sleep' => true, + '__wakeup' => true, + '__tostring' => true, + '__set_state' => true, + '__clone' => true, + '__invoke' => true, + '__debuginfo' => true, + '__serialize' => true, + '__unserialize' => true, + ]; + + /** + * Constructs a class method node. + * + * @param string|Node\Identifier $name Name + * @param array $subNodes Array of the following optional subnodes: + * 'flags => MODIFIER_PUBLIC: Flags + * 'byRef' => false : Whether to return by reference + * 'params' => array() : Parameters + * 'returnType' => null : Return type + * 'stmts' => array() : Statements + * 'attrGroups' => array() : PHP attribute groups + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0; + $this->byRef = $subNodes['byRef'] ?? false; + $this->name = \is_string($name) ? new Node\Identifier($name) : $name; + $this->params = $subNodes['params'] ?? []; + $returnType = $subNodes['returnType'] ?? null; + $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; + $this->stmts = array_key_exists('stmts', $subNodes) ? $subNodes['stmts'] : []; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'flags', 'byRef', 'name', 'params', 'returnType', 'stmts']; + } + + public function returnsByRef() : bool { + return $this->byRef; + } + + public function getParams() : array { + return $this->params; + } + + public function getReturnType() { + return $this->returnType; + } + + public function getStmts() { + return $this->stmts; + } + + public function getAttrGroups() : array { + return $this->attrGroups; + } + + /** + * Whether the method is explicitly or implicitly public. + * + * @return bool + */ + public function isPublic() : bool { + return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 + || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; + } + + /** + * Whether the method is protected. + * + * @return bool + */ + public function isProtected() : bool { + return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); + } + + /** + * Whether the method is private. + * + * @return bool + */ + public function isPrivate() : bool { + return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); + } + + /** + * Whether the method is abstract. + * + * @return bool + */ + public function isAbstract() : bool { + return (bool) ($this->flags & Class_::MODIFIER_ABSTRACT); + } + + /** + * Whether the method is final. + * + * @return bool + */ + public function isFinal() : bool { + return (bool) ($this->flags & Class_::MODIFIER_FINAL); + } + + /** + * Whether the method is static. + * + * @return bool + */ + public function isStatic() : bool { + return (bool) ($this->flags & Class_::MODIFIER_STATIC); + } + + /** + * Whether the method is magic. + * + * @return bool + */ + public function isMagic() : bool { + return isset(self::$magicNames[$this->name->toLowerString()]); + } + + public function getType() : string { + return 'Stmt_ClassMethod'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php new file mode 100644 index 00000000..52ed6c6c --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php @@ -0,0 +1,137 @@ + 0 : Flags + * 'extends' => null : Name of extended class + * 'implements' => array(): Names of implemented interfaces + * 'stmts' => array(): Statements + * 'attrGroups' => array(): PHP attribute groups + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0; + $this->name = \is_string($name) ? new Node\Identifier($name) : $name; + $this->extends = $subNodes['extends'] ?? null; + $this->implements = $subNodes['implements'] ?? []; + $this->stmts = $subNodes['stmts'] ?? []; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'flags', 'name', 'extends', 'implements', 'stmts']; + } + + /** + * Whether the class is explicitly abstract. + * + * @return bool + */ + public function isAbstract() : bool { + return (bool) ($this->flags & self::MODIFIER_ABSTRACT); + } + + /** + * Whether the class is final. + * + * @return bool + */ + public function isFinal() : bool { + return (bool) ($this->flags & self::MODIFIER_FINAL); + } + + public function isReadonly() : bool { + return (bool) ($this->flags & self::MODIFIER_READONLY); + } + + /** + * Whether the class is anonymous. + * + * @return bool + */ + public function isAnonymous() : bool { + return null === $this->name; + } + + /** + * @internal + */ + public static function verifyClassModifier($a, $b) { + if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) { + throw new Error('Multiple abstract modifiers are not allowed'); + } + + if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) { + throw new Error('Multiple final modifiers are not allowed'); + } + + if ($a & self::MODIFIER_READONLY && $b & self::MODIFIER_READONLY) { + throw new Error('Multiple readonly modifiers are not allowed'); + } + + if ($a & 48 && $b & 48) { + throw new Error('Cannot use the final modifier on an abstract class'); + } + } + + /** + * @internal + */ + public static function verifyModifier($a, $b) { + if ($a & self::VISIBILITY_MODIFIER_MASK && $b & self::VISIBILITY_MODIFIER_MASK) { + throw new Error('Multiple access type modifiers are not allowed'); + } + + if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) { + throw new Error('Multiple abstract modifiers are not allowed'); + } + + if ($a & self::MODIFIER_STATIC && $b & self::MODIFIER_STATIC) { + throw new Error('Multiple static modifiers are not allowed'); + } + + if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) { + throw new Error('Multiple final modifiers are not allowed'); + } + + if ($a & self::MODIFIER_READONLY && $b & self::MODIFIER_READONLY) { + throw new Error('Multiple readonly modifiers are not allowed'); + } + + if ($a & 48 && $b & 48) { + throw new Error('Cannot use the final modifier on an abstract class member'); + } + } + + public function getType() : string { + return 'Stmt_Class'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php new file mode 100644 index 00000000..e6316345 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->consts = $consts; + } + + public function getSubNodeNames() : array { + return ['consts']; + } + + public function getType() : string { + return 'Stmt_Const'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php new file mode 100644 index 00000000..24882683 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->num = $num; + } + + public function getSubNodeNames() : array { + return ['num']; + } + + public function getType() : string { + return 'Stmt_Continue'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php new file mode 100644 index 00000000..ac07f30c --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php @@ -0,0 +1,34 @@ +value pair node. + * + * @param string|Node\Identifier $key Key + * @param Node\Expr $value Value + * @param array $attributes Additional attributes + */ + public function __construct($key, Node\Expr $value, array $attributes = []) { + $this->attributes = $attributes; + $this->key = \is_string($key) ? new Node\Identifier($key) : $key; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['key', 'value']; + } + + public function getType() : string { + return 'Stmt_DeclareDeclare'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php new file mode 100644 index 00000000..f46ff0ba --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->declares = $declares; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['declares', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Declare'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php new file mode 100644 index 00000000..78e90da0 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->cond = $cond; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['stmts', 'cond']; + } + + public function getType() : string { + return 'Stmt_Do'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php new file mode 100644 index 00000000..7cc50d5d --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->exprs = $exprs; + } + + public function getSubNodeNames() : array { + return ['exprs']; + } + + public function getType() : string { + return 'Stmt_Echo'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php new file mode 100644 index 00000000..eef1ece3 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->cond = $cond; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['cond', 'stmts']; + } + + public function getType() : string { + return 'Stmt_ElseIf'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php new file mode 100644 index 00000000..0e61778e --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['stmts']; + } + + public function getType() : string { + return 'Stmt_Else'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php new file mode 100644 index 00000000..5beff8b3 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php @@ -0,0 +1,37 @@ +name = \is_string($name) ? new Node\Identifier($name) : $name; + $this->expr = $expr; + $this->attrGroups = $attrGroups; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'name', 'expr']; + } + + public function getType() : string { + return 'Stmt_EnumCase'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php new file mode 100644 index 00000000..3a50c225 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php @@ -0,0 +1,40 @@ + null : Scalar type + * 'implements' => array() : Names of implemented interfaces + * 'stmts' => array() : Statements + * 'attrGroups' => array() : PHP attribute groups + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = [], array $attributes = []) { + $this->name = \is_string($name) ? new Node\Identifier($name) : $name; + $this->scalarType = $subNodes['scalarType'] ?? null; + $this->implements = $subNodes['implements'] ?? []; + $this->stmts = $subNodes['stmts'] ?? []; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + + parent::__construct($attributes); + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'name', 'scalarType', 'implements', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Enum'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php new file mode 100644 index 00000000..99d1687d --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php @@ -0,0 +1,33 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Stmt_Expression'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php new file mode 100644 index 00000000..d55b8b68 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['stmts']; + } + + public function getType() : string { + return 'Stmt_Finally'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php new file mode 100644 index 00000000..1323d37c --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php @@ -0,0 +1,43 @@ + array(): Init expressions + * 'cond' => array(): Loop conditions + * 'loop' => array(): Loop expressions + * 'stmts' => array(): Statements + * @param array $attributes Additional attributes + */ + public function __construct(array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->init = $subNodes['init'] ?? []; + $this->cond = $subNodes['cond'] ?? []; + $this->loop = $subNodes['loop'] ?? []; + $this->stmts = $subNodes['stmts'] ?? []; + } + + public function getSubNodeNames() : array { + return ['init', 'cond', 'loop', 'stmts']; + } + + public function getType() : string { + return 'Stmt_For'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php new file mode 100644 index 00000000..0556a7ce --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php @@ -0,0 +1,47 @@ + null : Variable to assign key to + * 'byRef' => false : Whether to assign value by reference + * 'stmts' => array(): Statements + * @param array $attributes Additional attributes + */ + public function __construct(Node\Expr $expr, Node\Expr $valueVar, array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->expr = $expr; + $this->keyVar = $subNodes['keyVar'] ?? null; + $this->byRef = $subNodes['byRef'] ?? false; + $this->valueVar = $valueVar; + $this->stmts = $subNodes['stmts'] ?? []; + } + + public function getSubNodeNames() : array { + return ['expr', 'keyVar', 'byRef', 'valueVar', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Foreach'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php new file mode 100644 index 00000000..c2ccae24 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php @@ -0,0 +1,77 @@ + false : Whether to return by reference + * 'params' => array(): Parameters + * 'returnType' => null : Return type + * 'stmts' => array(): Statements + * 'attrGroups' => array(): PHP attribute groups + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->byRef = $subNodes['byRef'] ?? false; + $this->name = \is_string($name) ? new Node\Identifier($name) : $name; + $this->params = $subNodes['params'] ?? []; + $returnType = $subNodes['returnType'] ?? null; + $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; + $this->stmts = $subNodes['stmts'] ?? []; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts']; + } + + public function returnsByRef() : bool { + return $this->byRef; + } + + public function getParams() : array { + return $this->params; + } + + public function getReturnType() { + return $this->returnType; + } + + public function getAttrGroups() : array { + return $this->attrGroups; + } + + /** @return Node\Stmt[] */ + public function getStmts() : array { + return $this->stmts; + } + + public function getType() : string { + return 'Stmt_Function'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php new file mode 100644 index 00000000..a0022ad9 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->vars = $vars; + } + + public function getSubNodeNames() : array { + return ['vars']; + } + + public function getType() : string { + return 'Stmt_Global'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php new file mode 100644 index 00000000..24a57f78 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php @@ -0,0 +1,31 @@ +attributes = $attributes; + $this->name = \is_string($name) ? new Identifier($name) : $name; + } + + public function getSubNodeNames() : array { + return ['name']; + } + + public function getType() : string { + return 'Stmt_Goto'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php new file mode 100644 index 00000000..24520d22 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php @@ -0,0 +1,39 @@ +attributes = $attributes; + $this->type = $type; + $this->prefix = $prefix; + $this->uses = $uses; + } + + public function getSubNodeNames() : array { + return ['type', 'prefix', 'uses']; + } + + public function getType() : string { + return 'Stmt_GroupUse'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php new file mode 100644 index 00000000..8e624e0f --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->remaining = $remaining; + } + + public function getSubNodeNames() : array { + return ['remaining']; + } + + public function getType() : string { + return 'Stmt_HaltCompiler'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php new file mode 100644 index 00000000..a1bae4bf --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php @@ -0,0 +1,43 @@ + array(): Statements + * 'elseifs' => array(): Elseif clauses + * 'else' => null : Else clause + * @param array $attributes Additional attributes + */ + public function __construct(Node\Expr $cond, array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->cond = $cond; + $this->stmts = $subNodes['stmts'] ?? []; + $this->elseifs = $subNodes['elseifs'] ?? []; + $this->else = $subNodes['else'] ?? null; + } + + public function getSubNodeNames() : array { + return ['cond', 'stmts', 'elseifs', 'else']; + } + + public function getType() : string { + return 'Stmt_If'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php new file mode 100644 index 00000000..0711d284 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['value']; + } + + public function getType() : string { + return 'Stmt_InlineHTML'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php new file mode 100644 index 00000000..4d587dd4 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php @@ -0,0 +1,37 @@ + array(): Name of extended interfaces + * 'stmts' => array(): Statements + * 'attrGroups' => array(): PHP attribute groups + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->name = \is_string($name) ? new Node\Identifier($name) : $name; + $this->extends = $subNodes['extends'] ?? []; + $this->stmts = $subNodes['stmts'] ?? []; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'name', 'extends', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Interface'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php new file mode 100644 index 00000000..3edcb3be --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php @@ -0,0 +1,31 @@ +attributes = $attributes; + $this->name = \is_string($name) ? new Identifier($name) : $name; + } + + public function getSubNodeNames() : array { + return ['name']; + } + + public function getType() : string { + return 'Stmt_Label'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php new file mode 100644 index 00000000..c6320457 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php @@ -0,0 +1,38 @@ +attributes = $attributes; + $this->name = $name; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['name', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Namespace'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php new file mode 100644 index 00000000..f86f8df7 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php @@ -0,0 +1,17 @@ +attributes = $attributes; + $this->flags = $flags; + $this->props = $props; + $this->type = \is_string($type) ? new Identifier($type) : $type; + $this->attrGroups = $attrGroups; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'flags', 'type', 'props']; + } + + /** + * Whether the property is explicitly or implicitly public. + * + * @return bool + */ + public function isPublic() : bool { + return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 + || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; + } + + /** + * Whether the property is protected. + * + * @return bool + */ + public function isProtected() : bool { + return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); + } + + /** + * Whether the property is private. + * + * @return bool + */ + public function isPrivate() : bool { + return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); + } + + /** + * Whether the property is static. + * + * @return bool + */ + public function isStatic() : bool { + return (bool) ($this->flags & Class_::MODIFIER_STATIC); + } + + /** + * Whether the property is readonly. + * + * @return bool + */ + public function isReadonly() : bool { + return (bool) ($this->flags & Class_::MODIFIER_READONLY); + } + + public function getType() : string { + return 'Stmt_Property'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php new file mode 100644 index 00000000..205731e2 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->name = \is_string($name) ? new Node\VarLikeIdentifier($name) : $name; + $this->default = $default; + } + + public function getSubNodeNames() : array { + return ['name', 'default']; + } + + public function getType() : string { + return 'Stmt_PropertyProperty'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php new file mode 100644 index 00000000..efc578c5 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Stmt_Return'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php new file mode 100644 index 00000000..29584560 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php @@ -0,0 +1,37 @@ +attributes = $attributes; + $this->var = $var; + $this->default = $default; + } + + public function getSubNodeNames() : array { + return ['var', 'default']; + } + + public function getType() : string { + return 'Stmt_StaticVar'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php new file mode 100644 index 00000000..464898ff --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->vars = $vars; + } + + public function getSubNodeNames() : array { + return ['vars']; + } + + public function getType() : string { + return 'Stmt_Static'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php new file mode 100644 index 00000000..2c8dae02 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->cond = $cond; + $this->cases = $cases; + } + + public function getSubNodeNames() : array { + return ['cond', 'cases']; + } + + public function getType() : string { + return 'Stmt_Switch'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php new file mode 100644 index 00000000..a34e2b36 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Stmt_Throw'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php new file mode 100644 index 00000000..9e97053b --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->traits = $traits; + $this->adaptations = $adaptations; + } + + public function getSubNodeNames() : array { + return ['traits', 'adaptations']; + } + + public function getType() : string { + return 'Stmt_TraitUse'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php new file mode 100644 index 00000000..8bdd2c04 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php @@ -0,0 +1,13 @@ +attributes = $attributes; + $this->trait = $trait; + $this->method = \is_string($method) ? new Node\Identifier($method) : $method; + $this->newModifier = $newModifier; + $this->newName = \is_string($newName) ? new Node\Identifier($newName) : $newName; + } + + public function getSubNodeNames() : array { + return ['trait', 'method', 'newModifier', 'newName']; + } + + public function getType() : string { + return 'Stmt_TraitUseAdaptation_Alias'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php new file mode 100644 index 00000000..80385f64 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->trait = $trait; + $this->method = \is_string($method) ? new Node\Identifier($method) : $method; + $this->insteadof = $insteadof; + } + + public function getSubNodeNames() : array { + return ['trait', 'method', 'insteadof']; + } + + public function getType() : string { + return 'Stmt_TraitUseAdaptation_Precedence'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php new file mode 100644 index 00000000..0cec203a --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php @@ -0,0 +1,32 @@ + array(): Statements + * 'attrGroups' => array(): PHP attribute groups + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->name = \is_string($name) ? new Node\Identifier($name) : $name; + $this->stmts = $subNodes['stmts'] ?? []; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'name', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Trait'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php new file mode 100644 index 00000000..7fc158c5 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php @@ -0,0 +1,38 @@ +attributes = $attributes; + $this->stmts = $stmts; + $this->catches = $catches; + $this->finally = $finally; + } + + public function getSubNodeNames() : array { + return ['stmts', 'catches', 'finally']; + } + + public function getType() : string { + return 'Stmt_TryCatch'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php new file mode 100644 index 00000000..310e427a --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->vars = $vars; + } + + public function getSubNodeNames() : array { + return ['vars']; + } + + public function getType() : string { + return 'Stmt_Unset'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php new file mode 100644 index 00000000..32bd7847 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php @@ -0,0 +1,52 @@ +attributes = $attributes; + $this->type = $type; + $this->name = $name; + $this->alias = \is_string($alias) ? new Identifier($alias) : $alias; + } + + public function getSubNodeNames() : array { + return ['type', 'name', 'alias']; + } + + /** + * Get alias. If not explicitly given this is the last component of the used name. + * + * @return Identifier + */ + public function getAlias() : Identifier { + if (null !== $this->alias) { + return $this->alias; + } + + return new Identifier($this->name->getLast()); + } + + public function getType() : string { + return 'Stmt_UseUse'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php new file mode 100644 index 00000000..8753da31 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php @@ -0,0 +1,47 @@ +attributes = $attributes; + $this->type = $type; + $this->uses = $uses; + } + + public function getSubNodeNames() : array { + return ['type', 'uses']; + } + + public function getType() : string { + return 'Stmt_Use'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php new file mode 100644 index 00000000..f41034f8 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->cond = $cond; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['cond', 'stmts']; + } + + public function getType() : string { + return 'Stmt_While'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.php b/vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.php new file mode 100644 index 00000000..93cecd23 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.php @@ -0,0 +1,28 @@ +attributes = $attributes; + $this->types = $types; + } + + public function getSubNodeNames() : array { + return ['types']; + } + + public function getType() : string { + return 'UnionType'; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php b/vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php new file mode 100644 index 00000000..a30807a6 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php @@ -0,0 +1,17 @@ +attributes = $attributes; + } + + public function getType(): string { + return 'VariadicPlaceholder'; + } + + public function getSubNodeNames(): array { + return []; + } +} \ No newline at end of file diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php b/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php new file mode 100644 index 00000000..04514da1 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php @@ -0,0 +1,178 @@ +attributes = $attributes; + } + + /** + * Gets line the node started in (alias of getStartLine). + * + * @return int Start line (or -1 if not available) + */ + public function getLine() : int { + return $this->attributes['startLine'] ?? -1; + } + + /** + * Gets line the node started in. + * + * Requires the 'startLine' attribute to be enabled in the lexer (enabled by default). + * + * @return int Start line (or -1 if not available) + */ + public function getStartLine() : int { + return $this->attributes['startLine'] ?? -1; + } + + /** + * Gets the line the node ended in. + * + * Requires the 'endLine' attribute to be enabled in the lexer (enabled by default). + * + * @return int End line (or -1 if not available) + */ + public function getEndLine() : int { + return $this->attributes['endLine'] ?? -1; + } + + /** + * Gets the token offset of the first token that is part of this node. + * + * The offset is an index into the array returned by Lexer::getTokens(). + * + * Requires the 'startTokenPos' attribute to be enabled in the lexer (DISABLED by default). + * + * @return int Token start position (or -1 if not available) + */ + public function getStartTokenPos() : int { + return $this->attributes['startTokenPos'] ?? -1; + } + + /** + * Gets the token offset of the last token that is part of this node. + * + * The offset is an index into the array returned by Lexer::getTokens(). + * + * Requires the 'endTokenPos' attribute to be enabled in the lexer (DISABLED by default). + * + * @return int Token end position (or -1 if not available) + */ + public function getEndTokenPos() : int { + return $this->attributes['endTokenPos'] ?? -1; + } + + /** + * Gets the file offset of the first character that is part of this node. + * + * Requires the 'startFilePos' attribute to be enabled in the lexer (DISABLED by default). + * + * @return int File start position (or -1 if not available) + */ + public function getStartFilePos() : int { + return $this->attributes['startFilePos'] ?? -1; + } + + /** + * Gets the file offset of the last character that is part of this node. + * + * Requires the 'endFilePos' attribute to be enabled in the lexer (DISABLED by default). + * + * @return int File end position (or -1 if not available) + */ + public function getEndFilePos() : int { + return $this->attributes['endFilePos'] ?? -1; + } + + /** + * Gets all comments directly preceding this node. + * + * The comments are also available through the "comments" attribute. + * + * @return Comment[] + */ + public function getComments() : array { + return $this->attributes['comments'] ?? []; + } + + /** + * Gets the doc comment of the node. + * + * @return null|Comment\Doc Doc comment object or null + */ + public function getDocComment() { + $comments = $this->getComments(); + for ($i = count($comments) - 1; $i >= 0; $i--) { + $comment = $comments[$i]; + if ($comment instanceof Comment\Doc) { + return $comment; + } + } + + return null; + } + + /** + * Sets the doc comment of the node. + * + * This will either replace an existing doc comment or add it to the comments array. + * + * @param Comment\Doc $docComment Doc comment to set + */ + public function setDocComment(Comment\Doc $docComment) { + $comments = $this->getComments(); + for ($i = count($comments) - 1; $i >= 0; $i--) { + if ($comments[$i] instanceof Comment\Doc) { + // Replace existing doc comment. + $comments[$i] = $docComment; + $this->setAttribute('comments', $comments); + return; + } + } + + // Append new doc comment. + $comments[] = $docComment; + $this->setAttribute('comments', $comments); + } + + public function setAttribute(string $key, $value) { + $this->attributes[$key] = $value; + } + + public function hasAttribute(string $key) : bool { + return array_key_exists($key, $this->attributes); + } + + public function getAttribute(string $key, $default = null) { + if (array_key_exists($key, $this->attributes)) { + return $this->attributes[$key]; + } + + return $default; + } + + public function getAttributes() : array { + return $this->attributes; + } + + public function setAttributes(array $attributes) { + $this->attributes = $attributes; + } + + /** + * @return array + */ + public function jsonSerialize() : array { + return ['nodeType' => $this->getType()] + get_object_vars($this); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php b/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php new file mode 100644 index 00000000..ba622efd --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php @@ -0,0 +1,206 @@ +dumpComments = !empty($options['dumpComments']); + $this->dumpPositions = !empty($options['dumpPositions']); + } + + /** + * Dumps a node or array. + * + * @param array|Node $node Node or array to dump + * @param string|null $code Code corresponding to dumped AST. This only needs to be passed if + * the dumpPositions option is enabled and the dumping of node offsets + * is desired. + * + * @return string Dumped value + */ + public function dump($node, string $code = null) : string { + $this->code = $code; + return $this->dumpRecursive($node); + } + + protected function dumpRecursive($node) { + if ($node instanceof Node) { + $r = $node->getType(); + if ($this->dumpPositions && null !== $p = $this->dumpPosition($node)) { + $r .= $p; + } + $r .= '('; + + foreach ($node->getSubNodeNames() as $key) { + $r .= "\n " . $key . ': '; + + $value = $node->$key; + if (null === $value) { + $r .= 'null'; + } elseif (false === $value) { + $r .= 'false'; + } elseif (true === $value) { + $r .= 'true'; + } elseif (is_scalar($value)) { + if ('flags' === $key || 'newModifier' === $key) { + $r .= $this->dumpFlags($value); + } elseif ('type' === $key && $node instanceof Include_) { + $r .= $this->dumpIncludeType($value); + } elseif ('type' === $key + && ($node instanceof Use_ || $node instanceof UseUse || $node instanceof GroupUse)) { + $r .= $this->dumpUseType($value); + } else { + $r .= $value; + } + } else { + $r .= str_replace("\n", "\n ", $this->dumpRecursive($value)); + } + } + + if ($this->dumpComments && $comments = $node->getComments()) { + $r .= "\n comments: " . str_replace("\n", "\n ", $this->dumpRecursive($comments)); + } + } elseif (is_array($node)) { + $r = 'array('; + + foreach ($node as $key => $value) { + $r .= "\n " . $key . ': '; + + if (null === $value) { + $r .= 'null'; + } elseif (false === $value) { + $r .= 'false'; + } elseif (true === $value) { + $r .= 'true'; + } elseif (is_scalar($value)) { + $r .= $value; + } else { + $r .= str_replace("\n", "\n ", $this->dumpRecursive($value)); + } + } + } elseif ($node instanceof Comment) { + return $node->getReformattedText(); + } else { + throw new \InvalidArgumentException('Can only dump nodes and arrays.'); + } + + return $r . "\n)"; + } + + protected function dumpFlags($flags) { + $strs = []; + if ($flags & Class_::MODIFIER_PUBLIC) { + $strs[] = 'MODIFIER_PUBLIC'; + } + if ($flags & Class_::MODIFIER_PROTECTED) { + $strs[] = 'MODIFIER_PROTECTED'; + } + if ($flags & Class_::MODIFIER_PRIVATE) { + $strs[] = 'MODIFIER_PRIVATE'; + } + if ($flags & Class_::MODIFIER_ABSTRACT) { + $strs[] = 'MODIFIER_ABSTRACT'; + } + if ($flags & Class_::MODIFIER_STATIC) { + $strs[] = 'MODIFIER_STATIC'; + } + if ($flags & Class_::MODIFIER_FINAL) { + $strs[] = 'MODIFIER_FINAL'; + } + if ($flags & Class_::MODIFIER_READONLY) { + $strs[] = 'MODIFIER_READONLY'; + } + + if ($strs) { + return implode(' | ', $strs) . ' (' . $flags . ')'; + } else { + return $flags; + } + } + + protected function dumpIncludeType($type) { + $map = [ + Include_::TYPE_INCLUDE => 'TYPE_INCLUDE', + Include_::TYPE_INCLUDE_ONCE => 'TYPE_INCLUDE_ONCE', + Include_::TYPE_REQUIRE => 'TYPE_REQUIRE', + Include_::TYPE_REQUIRE_ONCE => 'TYPE_REQUIRE_ONCE', + ]; + + if (!isset($map[$type])) { + return $type; + } + return $map[$type] . ' (' . $type . ')'; + } + + protected function dumpUseType($type) { + $map = [ + Use_::TYPE_UNKNOWN => 'TYPE_UNKNOWN', + Use_::TYPE_NORMAL => 'TYPE_NORMAL', + Use_::TYPE_FUNCTION => 'TYPE_FUNCTION', + Use_::TYPE_CONSTANT => 'TYPE_CONSTANT', + ]; + + if (!isset($map[$type])) { + return $type; + } + return $map[$type] . ' (' . $type . ')'; + } + + /** + * Dump node position, if possible. + * + * @param Node $node Node for which to dump position + * + * @return string|null Dump of position, or null if position information not available + */ + protected function dumpPosition(Node $node) { + if (!$node->hasAttribute('startLine') || !$node->hasAttribute('endLine')) { + return null; + } + + $start = $node->getStartLine(); + $end = $node->getEndLine(); + if ($node->hasAttribute('startFilePos') && $node->hasAttribute('endFilePos') + && null !== $this->code + ) { + $start .= ':' . $this->toColumn($this->code, $node->getStartFilePos()); + $end .= ':' . $this->toColumn($this->code, $node->getEndFilePos()); + } + return "[$start - $end]"; + } + + // Copied from Error class + private function toColumn($code, $pos) { + if ($pos > strlen($code)) { + throw new \RuntimeException('Invalid position information'); + } + + $lineStartPos = strrpos($code, "\n", $pos - strlen($code)); + if (false === $lineStartPos) { + $lineStartPos = -1; + } + + return $pos - $lineStartPos; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php b/vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php new file mode 100644 index 00000000..2e7cfdad --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php @@ -0,0 +1,81 @@ +addVisitor($visitor); + $traverser->traverse($nodes); + + return $visitor->getFoundNodes(); + } + + /** + * Find all nodes that are instances of a certain class. + * + * @param Node|Node[] $nodes Single node or array of nodes to search in + * @param string $class Class name + * + * @return Node[] Found nodes (all instances of $class) + */ + public function findInstanceOf($nodes, string $class) : array { + return $this->find($nodes, function ($node) use ($class) { + return $node instanceof $class; + }); + } + + /** + * Find first node satisfying a filter callback. + * + * @param Node|Node[] $nodes Single node or array of nodes to search in + * @param callable $filter Filter callback: function(Node $node) : bool + * + * @return null|Node Found node (or null if none found) + */ + public function findFirst($nodes, callable $filter) { + if (!is_array($nodes)) { + $nodes = [$nodes]; + } + + $visitor = new FirstFindingVisitor($filter); + + $traverser = new NodeTraverser; + $traverser->addVisitor($visitor); + $traverser->traverse($nodes); + + return $visitor->getFoundNode(); + } + + /** + * Find first node that is an instance of a certain class. + * + * @param Node|Node[] $nodes Single node or array of nodes to search in + * @param string $class Class name + * + * @return null|Node Found node, which is an instance of $class (or null if none found) + */ + public function findFirstInstanceOf($nodes, string $class) { + return $this->findFirst($nodes, function ($node) use ($class) { + return $node instanceof $class; + }); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php b/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php new file mode 100644 index 00000000..97d45bda --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php @@ -0,0 +1,291 @@ +visitors[] = $visitor; + } + + /** + * Removes an added visitor. + * + * @param NodeVisitor $visitor + */ + public function removeVisitor(NodeVisitor $visitor) { + foreach ($this->visitors as $index => $storedVisitor) { + if ($storedVisitor === $visitor) { + unset($this->visitors[$index]); + break; + } + } + } + + /** + * Traverses an array of nodes using the registered visitors. + * + * @param Node[] $nodes Array of nodes + * + * @return Node[] Traversed array of nodes + */ + public function traverse(array $nodes) : array { + $this->stopTraversal = false; + + foreach ($this->visitors as $visitor) { + if (null !== $return = $visitor->beforeTraverse($nodes)) { + $nodes = $return; + } + } + + $nodes = $this->traverseArray($nodes); + + foreach ($this->visitors as $visitor) { + if (null !== $return = $visitor->afterTraverse($nodes)) { + $nodes = $return; + } + } + + return $nodes; + } + + /** + * Recursively traverse a node. + * + * @param Node $node Node to traverse. + * + * @return Node Result of traversal (may be original node or new one) + */ + protected function traverseNode(Node $node) : Node { + foreach ($node->getSubNodeNames() as $name) { + $subNode =& $node->$name; + + if (\is_array($subNode)) { + $subNode = $this->traverseArray($subNode); + if ($this->stopTraversal) { + break; + } + } elseif ($subNode instanceof Node) { + $traverseChildren = true; + $breakVisitorIndex = null; + + foreach ($this->visitors as $visitorIndex => $visitor) { + $return = $visitor->enterNode($subNode); + if (null !== $return) { + if ($return instanceof Node) { + $this->ensureReplacementReasonable($subNode, $return); + $subNode = $return; + } elseif (self::DONT_TRAVERSE_CHILDREN === $return) { + $traverseChildren = false; + } elseif (self::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) { + $traverseChildren = false; + $breakVisitorIndex = $visitorIndex; + break; + } elseif (self::STOP_TRAVERSAL === $return) { + $this->stopTraversal = true; + break 2; + } else { + throw new \LogicException( + 'enterNode() returned invalid value of type ' . gettype($return) + ); + } + } + } + + if ($traverseChildren) { + $subNode = $this->traverseNode($subNode); + if ($this->stopTraversal) { + break; + } + } + + foreach ($this->visitors as $visitorIndex => $visitor) { + $return = $visitor->leaveNode($subNode); + + if (null !== $return) { + if ($return instanceof Node) { + $this->ensureReplacementReasonable($subNode, $return); + $subNode = $return; + } elseif (self::STOP_TRAVERSAL === $return) { + $this->stopTraversal = true; + break 2; + } elseif (\is_array($return)) { + throw new \LogicException( + 'leaveNode() may only return an array ' . + 'if the parent structure is an array' + ); + } else { + throw new \LogicException( + 'leaveNode() returned invalid value of type ' . gettype($return) + ); + } + } + + if ($breakVisitorIndex === $visitorIndex) { + break; + } + } + } + } + + return $node; + } + + /** + * Recursively traverse array (usually of nodes). + * + * @param array $nodes Array to traverse + * + * @return array Result of traversal (may be original array or changed one) + */ + protected function traverseArray(array $nodes) : array { + $doNodes = []; + + foreach ($nodes as $i => &$node) { + if ($node instanceof Node) { + $traverseChildren = true; + $breakVisitorIndex = null; + + foreach ($this->visitors as $visitorIndex => $visitor) { + $return = $visitor->enterNode($node); + if (null !== $return) { + if ($return instanceof Node) { + $this->ensureReplacementReasonable($node, $return); + $node = $return; + } elseif (self::DONT_TRAVERSE_CHILDREN === $return) { + $traverseChildren = false; + } elseif (self::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) { + $traverseChildren = false; + $breakVisitorIndex = $visitorIndex; + break; + } elseif (self::STOP_TRAVERSAL === $return) { + $this->stopTraversal = true; + break 2; + } else { + throw new \LogicException( + 'enterNode() returned invalid value of type ' . gettype($return) + ); + } + } + } + + if ($traverseChildren) { + $node = $this->traverseNode($node); + if ($this->stopTraversal) { + break; + } + } + + foreach ($this->visitors as $visitorIndex => $visitor) { + $return = $visitor->leaveNode($node); + + if (null !== $return) { + if ($return instanceof Node) { + $this->ensureReplacementReasonable($node, $return); + $node = $return; + } elseif (\is_array($return)) { + $doNodes[] = [$i, $return]; + break; + } elseif (self::REMOVE_NODE === $return) { + $doNodes[] = [$i, []]; + break; + } elseif (self::STOP_TRAVERSAL === $return) { + $this->stopTraversal = true; + break 2; + } elseif (false === $return) { + throw new \LogicException( + 'bool(false) return from leaveNode() no longer supported. ' . + 'Return NodeTraverser::REMOVE_NODE instead' + ); + } else { + throw new \LogicException( + 'leaveNode() returned invalid value of type ' . gettype($return) + ); + } + } + + if ($breakVisitorIndex === $visitorIndex) { + break; + } + } + } elseif (\is_array($node)) { + throw new \LogicException('Invalid node structure: Contains nested arrays'); + } + } + + if (!empty($doNodes)) { + while (list($i, $replace) = array_pop($doNodes)) { + array_splice($nodes, $i, 1, $replace); + } + } + + return $nodes; + } + + private function ensureReplacementReasonable($old, $new) { + if ($old instanceof Node\Stmt && $new instanceof Node\Expr) { + throw new \LogicException( + "Trying to replace statement ({$old->getType()}) " . + "with expression ({$new->getType()}). Are you missing a " . + "Stmt_Expression wrapper?" + ); + } + + if ($old instanceof Node\Expr && $new instanceof Node\Stmt) { + throw new \LogicException( + "Trying to replace expression ({$old->getType()}) " . + "with statement ({$new->getType()})" + ); + } + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php b/vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php new file mode 100644 index 00000000..77ff3d27 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php @@ -0,0 +1,29 @@ + $node stays as-is + * * NodeTraverser::DONT_TRAVERSE_CHILDREN + * => Children of $node are not traversed. $node stays as-is + * * NodeTraverser::STOP_TRAVERSAL + * => Traversal is aborted. $node stays as-is + * * otherwise + * => $node is set to the return value + * + * @param Node $node Node + * + * @return null|int|Node Replacement node (or special return value) + */ + public function enterNode(Node $node); + + /** + * Called when leaving a node. + * + * Return value semantics: + * * null + * => $node stays as-is + * * NodeTraverser::REMOVE_NODE + * => $node is removed from the parent array + * * NodeTraverser::STOP_TRAVERSAL + * => Traversal is aborted. $node stays as-is + * * array (of Nodes) + * => The return value is merged into the parent array (at the position of the $node) + * * otherwise + * => $node is set to the return value + * + * @param Node $node Node + * + * @return null|int|Node|Node[] Replacement node (or special return value) + */ + public function leaveNode(Node $node); + + /** + * Called once after traversal. + * + * Return value semantics: + * * null: $nodes stays as-is + * * otherwise: $nodes is set to the return value + * + * @param Node[] $nodes Array of nodes + * + * @return null|Node[] Array of nodes + */ + public function afterTraverse(array $nodes); +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php new file mode 100644 index 00000000..a85fa493 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php @@ -0,0 +1,20 @@ +setAttribute('origNode', $origNode); + return $node; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php new file mode 100644 index 00000000..9531edbc --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php @@ -0,0 +1,48 @@ +filterCallback = $filterCallback; + } + + /** + * Get found nodes satisfying the filter callback. + * + * Nodes are returned in pre-order. + * + * @return Node[] Found nodes + */ + public function getFoundNodes() : array { + return $this->foundNodes; + } + + public function beforeTraverse(array $nodes) { + $this->foundNodes = []; + + return null; + } + + public function enterNode(Node $node) { + $filterCallback = $this->filterCallback; + if ($filterCallback($node)) { + $this->foundNodes[] = $node; + } + + return null; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php new file mode 100644 index 00000000..596a7d7f --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php @@ -0,0 +1,50 @@ +filterCallback = $filterCallback; + } + + /** + * Get found node satisfying the filter callback. + * + * Returns null if no node satisfies the filter callback. + * + * @return null|Node Found node (or null if not found) + */ + public function getFoundNode() { + return $this->foundNode; + } + + public function beforeTraverse(array $nodes) { + $this->foundNode = null; + + return null; + } + + public function enterNode(Node $node) { + $filterCallback = $this->filterCallback; + if ($filterCallback($node)) { + $this->foundNode = $node; + return NodeTraverser::STOP_TRAVERSAL; + } + + return null; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php new file mode 100644 index 00000000..d0e7de02 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php @@ -0,0 +1,257 @@ +nameContext = new NameContext($errorHandler ?? new ErrorHandler\Throwing); + $this->preserveOriginalNames = $options['preserveOriginalNames'] ?? false; + $this->replaceNodes = $options['replaceNodes'] ?? true; + } + + /** + * Get name resolution context. + * + * @return NameContext + */ + public function getNameContext() : NameContext { + return $this->nameContext; + } + + public function beforeTraverse(array $nodes) { + $this->nameContext->startNamespace(); + return null; + } + + public function enterNode(Node $node) { + if ($node instanceof Stmt\Namespace_) { + $this->nameContext->startNamespace($node->name); + } elseif ($node instanceof Stmt\Use_) { + foreach ($node->uses as $use) { + $this->addAlias($use, $node->type, null); + } + } elseif ($node instanceof Stmt\GroupUse) { + foreach ($node->uses as $use) { + $this->addAlias($use, $node->type, $node->prefix); + } + } elseif ($node instanceof Stmt\Class_) { + if (null !== $node->extends) { + $node->extends = $this->resolveClassName($node->extends); + } + + foreach ($node->implements as &$interface) { + $interface = $this->resolveClassName($interface); + } + + $this->resolveAttrGroups($node); + if (null !== $node->name) { + $this->addNamespacedName($node); + } + } elseif ($node instanceof Stmt\Interface_) { + foreach ($node->extends as &$interface) { + $interface = $this->resolveClassName($interface); + } + + $this->resolveAttrGroups($node); + $this->addNamespacedName($node); + } elseif ($node instanceof Stmt\Enum_) { + foreach ($node->implements as &$interface) { + $interface = $this->resolveClassName($interface); + } + + $this->resolveAttrGroups($node); + if (null !== $node->name) { + $this->addNamespacedName($node); + } + } elseif ($node instanceof Stmt\Trait_) { + $this->resolveAttrGroups($node); + $this->addNamespacedName($node); + } elseif ($node instanceof Stmt\Function_) { + $this->resolveSignature($node); + $this->resolveAttrGroups($node); + $this->addNamespacedName($node); + } elseif ($node instanceof Stmt\ClassMethod + || $node instanceof Expr\Closure + || $node instanceof Expr\ArrowFunction + ) { + $this->resolveSignature($node); + $this->resolveAttrGroups($node); + } elseif ($node instanceof Stmt\Property) { + if (null !== $node->type) { + $node->type = $this->resolveType($node->type); + } + $this->resolveAttrGroups($node); + } elseif ($node instanceof Stmt\Const_) { + foreach ($node->consts as $const) { + $this->addNamespacedName($const); + } + } else if ($node instanceof Stmt\ClassConst) { + $this->resolveAttrGroups($node); + } else if ($node instanceof Stmt\EnumCase) { + $this->resolveAttrGroups($node); + } elseif ($node instanceof Expr\StaticCall + || $node instanceof Expr\StaticPropertyFetch + || $node instanceof Expr\ClassConstFetch + || $node instanceof Expr\New_ + || $node instanceof Expr\Instanceof_ + ) { + if ($node->class instanceof Name) { + $node->class = $this->resolveClassName($node->class); + } + } elseif ($node instanceof Stmt\Catch_) { + foreach ($node->types as &$type) { + $type = $this->resolveClassName($type); + } + } elseif ($node instanceof Expr\FuncCall) { + if ($node->name instanceof Name) { + $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_FUNCTION); + } + } elseif ($node instanceof Expr\ConstFetch) { + $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_CONSTANT); + } elseif ($node instanceof Stmt\TraitUse) { + foreach ($node->traits as &$trait) { + $trait = $this->resolveClassName($trait); + } + + foreach ($node->adaptations as $adaptation) { + if (null !== $adaptation->trait) { + $adaptation->trait = $this->resolveClassName($adaptation->trait); + } + + if ($adaptation instanceof Stmt\TraitUseAdaptation\Precedence) { + foreach ($adaptation->insteadof as &$insteadof) { + $insteadof = $this->resolveClassName($insteadof); + } + } + } + } + + return null; + } + + private function addAlias(Stmt\UseUse $use, int $type, Name $prefix = null) { + // Add prefix for group uses + $name = $prefix ? Name::concat($prefix, $use->name) : $use->name; + // Type is determined either by individual element or whole use declaration + $type |= $use->type; + + $this->nameContext->addAlias( + $name, (string) $use->getAlias(), $type, $use->getAttributes() + ); + } + + /** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */ + private function resolveSignature($node) { + foreach ($node->params as $param) { + $param->type = $this->resolveType($param->type); + $this->resolveAttrGroups($param); + } + $node->returnType = $this->resolveType($node->returnType); + } + + private function resolveType($node) { + if ($node instanceof Name) { + return $this->resolveClassName($node); + } + if ($node instanceof Node\NullableType) { + $node->type = $this->resolveType($node->type); + return $node; + } + if ($node instanceof Node\UnionType || $node instanceof Node\IntersectionType) { + foreach ($node->types as &$type) { + $type = $this->resolveType($type); + } + return $node; + } + return $node; + } + + /** + * Resolve name, according to name resolver options. + * + * @param Name $name Function or constant name to resolve + * @param int $type One of Stmt\Use_::TYPE_* + * + * @return Name Resolved name, or original name with attribute + */ + protected function resolveName(Name $name, int $type) : Name { + if (!$this->replaceNodes) { + $resolvedName = $this->nameContext->getResolvedName($name, $type); + if (null !== $resolvedName) { + $name->setAttribute('resolvedName', $resolvedName); + } else { + $name->setAttribute('namespacedName', FullyQualified::concat( + $this->nameContext->getNamespace(), $name, $name->getAttributes())); + } + return $name; + } + + if ($this->preserveOriginalNames) { + // Save the original name + $originalName = $name; + $name = clone $originalName; + $name->setAttribute('originalName', $originalName); + } + + $resolvedName = $this->nameContext->getResolvedName($name, $type); + if (null !== $resolvedName) { + return $resolvedName; + } + + // unqualified names inside a namespace cannot be resolved at compile-time + // add the namespaced version of the name as an attribute + $name->setAttribute('namespacedName', FullyQualified::concat( + $this->nameContext->getNamespace(), $name, $name->getAttributes())); + return $name; + } + + protected function resolveClassName(Name $name) { + return $this->resolveName($name, Stmt\Use_::TYPE_NORMAL); + } + + protected function addNamespacedName(Node $node) { + $node->namespacedName = Name::concat( + $this->nameContext->getNamespace(), (string) $node->name); + } + + protected function resolveAttrGroups(Node $node) + { + foreach ($node->attrGroups as $attrGroup) { + foreach ($attrGroup->attrs as $attr) { + $attr->name = $this->resolveClassName($attr->name); + } + } + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php new file mode 100644 index 00000000..ea372e5b --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php @@ -0,0 +1,52 @@ +$node->getAttribute('parent'), the previous + * node can be accessed through $node->getAttribute('previous'), + * and the next node can be accessed through $node->getAttribute('next'). + */ +final class NodeConnectingVisitor extends NodeVisitorAbstract +{ + /** + * @var Node[] + */ + private $stack = []; + + /** + * @var ?Node + */ + private $previous; + + public function beforeTraverse(array $nodes) { + $this->stack = []; + $this->previous = null; + } + + public function enterNode(Node $node) { + if (!empty($this->stack)) { + $node->setAttribute('parent', $this->stack[count($this->stack) - 1]); + } + + if ($this->previous !== null && $this->previous->getAttribute('parent') === $node->getAttribute('parent')) { + $node->setAttribute('previous', $this->previous); + $this->previous->setAttribute('next', $node); + } + + $this->stack[] = $node; + } + + public function leaveNode(Node $node) { + $this->previous = $node; + + array_pop($this->stack); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php new file mode 100644 index 00000000..b98d2bfa --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php @@ -0,0 +1,41 @@ +$node->getAttribute('parent'). + */ +final class ParentConnectingVisitor extends NodeVisitorAbstract +{ + /** + * @var Node[] + */ + private $stack = []; + + public function beforeTraverse(array $nodes) + { + $this->stack = []; + } + + public function enterNode(Node $node) + { + if (!empty($this->stack)) { + $node->setAttribute('parent', $this->stack[count($this->stack) - 1]); + } + + $this->stack[] = $node; + } + + public function leaveNode(Node $node) + { + array_pop($this->stack); + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php new file mode 100644 index 00000000..d378d670 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php @@ -0,0 +1,25 @@ +parsers = $parsers; + } + + public function parse(string $code, ErrorHandler $errorHandler = null) { + if (null === $errorHandler) { + $errorHandler = new ErrorHandler\Throwing; + } + + list($firstStmts, $firstError) = $this->tryParse($this->parsers[0], $errorHandler, $code); + if ($firstError === null) { + return $firstStmts; + } + + for ($i = 1, $c = count($this->parsers); $i < $c; ++$i) { + list($stmts, $error) = $this->tryParse($this->parsers[$i], $errorHandler, $code); + if ($error === null) { + return $stmts; + } + } + + throw $firstError; + } + + private function tryParse(Parser $parser, ErrorHandler $errorHandler, $code) { + $stmts = null; + $error = null; + try { + $stmts = $parser->parse($code, $errorHandler); + } catch (Error $error) {} + return [$stmts, $error]; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php b/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php new file mode 100644 index 00000000..351db9ed --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php @@ -0,0 +1,2682 @@ +'", + "T_IS_GREATER_OR_EQUAL", + "T_SL", + "T_SR", + "'+'", + "'-'", + "'.'", + "'*'", + "'/'", + "'%'", + "'!'", + "T_INSTANCEOF", + "'~'", + "T_INC", + "T_DEC", + "T_INT_CAST", + "T_DOUBLE_CAST", + "T_STRING_CAST", + "T_ARRAY_CAST", + "T_OBJECT_CAST", + "T_BOOL_CAST", + "T_UNSET_CAST", + "'@'", + "T_POW", + "'['", + "T_NEW", + "T_CLONE", + "T_EXIT", + "T_IF", + "T_ELSEIF", + "T_ELSE", + "T_ENDIF", + "T_LNUMBER", + "T_DNUMBER", + "T_STRING", + "T_STRING_VARNAME", + "T_VARIABLE", + "T_NUM_STRING", + "T_INLINE_HTML", + "T_ENCAPSED_AND_WHITESPACE", + "T_CONSTANT_ENCAPSED_STRING", + "T_ECHO", + "T_DO", + "T_WHILE", + "T_ENDWHILE", + "T_FOR", + "T_ENDFOR", + "T_FOREACH", + "T_ENDFOREACH", + "T_DECLARE", + "T_ENDDECLARE", + "T_AS", + "T_SWITCH", + "T_MATCH", + "T_ENDSWITCH", + "T_CASE", + "T_DEFAULT", + "T_BREAK", + "T_CONTINUE", + "T_GOTO", + "T_FUNCTION", + "T_FN", + "T_CONST", + "T_RETURN", + "T_TRY", + "T_CATCH", + "T_FINALLY", + "T_USE", + "T_INSTEADOF", + "T_GLOBAL", + "T_STATIC", + "T_ABSTRACT", + "T_FINAL", + "T_PRIVATE", + "T_PROTECTED", + "T_PUBLIC", + "T_READONLY", + "T_VAR", + "T_UNSET", + "T_ISSET", + "T_EMPTY", + "T_HALT_COMPILER", + "T_CLASS", + "T_TRAIT", + "T_INTERFACE", + "T_EXTENDS", + "T_IMPLEMENTS", + "T_OBJECT_OPERATOR", + "T_LIST", + "T_ARRAY", + "T_CALLABLE", + "T_CLASS_C", + "T_TRAIT_C", + "T_METHOD_C", + "T_FUNC_C", + "T_LINE", + "T_FILE", + "T_START_HEREDOC", + "T_END_HEREDOC", + "T_DOLLAR_OPEN_CURLY_BRACES", + "T_CURLY_OPEN", + "T_PAAMAYIM_NEKUDOTAYIM", + "T_NAMESPACE", + "T_NS_C", + "T_DIR", + "T_NS_SEPARATOR", + "T_ELLIPSIS", + "T_NAME_FULLY_QUALIFIED", + "T_NAME_QUALIFIED", + "T_NAME_RELATIVE", + "';'", + "'{'", + "'}'", + "'('", + "')'", + "'$'", + "'`'", + "']'", + "'\"'", + "T_ENUM", + "T_NULLSAFE_OBJECT_OPERATOR", + "T_ATTRIBUTE" + ); + + protected $tokenToSymbol = array( + 0, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 56, 164, 168, 161, 55, 168, 168, + 159, 160, 53, 50, 8, 51, 52, 54, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 31, 156, + 44, 16, 46, 30, 68, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 70, 168, 163, 36, 168, 162, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 157, 35, 158, 58, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 1, 2, 3, 4, + 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 32, 33, 34, 37, 38, 39, 40, + 41, 42, 43, 45, 47, 48, 49, 57, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 69, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 165, 131, + 132, 133, 166, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 154, 155, 167 + ); + + protected $action = array( + 700, 670, 671, 672, 673, 674, 286, 675, 676, 677, + 713, 714, 223, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 0, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244,-32766,-32766,-32766,-32766,-32766, + -32766,-32766,-32766,-32766,-32767,-32767,-32767,-32767, 245, 246, + 242, 243, 244,-32766,-32766, 678,-32766,-32766,-32766,-32766, + -32766,-32766,-32766,-32766,-32766, 1229, 245, 246, 1230, 679, + 680, 681, 682, 683, 684, 685, 899, 900, 747,-32766, + -32766,-32766,-32766,-32766,-32766, 686, 687, 688, 689, 690, + 691, 692, 693, 694, 695, 696, 716, 739, 717, 718, + 719, 720, 708, 709, 710, 738, 711, 712, 697, 698, + 699, 701, 702, 703, 741, 742, 743, 744, 745, 746, + 875, 704, 705, 706, 707, 737, 728, 726, 727, 723, + 724, 1046, 715, 721, 722, 729, 730, 732, 731, 733, + 734, 55, 56, 425, 57, 58, 725, 736, 735, 755, + 59, 60, -226, 61,-32766,-32766,-32766,-32766,-32766,-32766, + -32766,-32766,-32766,-32766, 337,-32767,-32767,-32767,-32767, 29, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 620,-32766,-32766,-32766,-32766, 62, 63, + 1046,-32766,-32766,-32766, 64, 419, 65, 294, 295, 66, + 67, 68, 69, 70, 71, 72, 73, 823, 25, 302, + 74, 418, 984, 986, 669, 668, 1100, 1101, 1078, 755, + 755, 767, 1220, 768, 470,-32766,-32766,-32766, 341, 749, + 824, 54,-32767,-32767,-32767,-32767, 98, 99, 100, 101, + 102, 220, 221, 222, 362, 876,-32766, 27,-32766,-32766, + -32766,-32766,-32766, 1046, 493, 126, 1080, 1079, 1081, 370, + 1068, 930, 207, 478, 479, 952, 953, 954, 951, 950, + 949, 128, 480, 481, 803, 1106, 1107, 1108, 1109, 1103, + 1104, 319, 32, 297, 10, 211, -515, 1110, 1105, 669, + 668, 1080, 1079, 1081, 220, 221, 222, 41, 364, 341, + 334, 421, 336, 426, -128, -128, -128, 313, 1046, 469, + -4, 824, 54, 812, 770, 207, 40, 21, 427, -128, + 471, -128, 472, -128, 473, -128, 1046, 428, 220, 221, + 222,-32766, 33, 34, 429, 361, 327, 52, 35, 474, + -32766,-32766,-32766, 342, 357, 358, 475, 476, 48, 207, + 249, 669, 668, 477, 443, 300, 795, 846, 430, 431, + 28,-32766, 814,-32766,-32766,-32766,-32766,-32766,-32766,-32766, + -32767,-32767,-32767,-32767,-32767, 952, 953, 954, 951, 950, + 949, 422, 755, 424, 426, 826, 634, -128,-32766,-32766, + 469, 824, 54, 288, 812, 1151, 755, 40, 21, 427, + 317, 471, 345, 472, 129, 473, 9, 1186, 428, 769, + 360, 324, 905, 33, 34, 429, 361, 1046, 415, 35, + 474, 944, 1068, 315, 125, 357, 358, 475, 476,-32766, + -32766,-32766, 926, 302, 477, 121, 1068, 759, 846, 430, + 431, 669, 668, 423, 755, 1152, 809, 1046, 480, 766, + -32766, 805,-32766,-32766,-32766,-32766, -261, 127, 347, 436, + 841, 341, 1078, 1200, 426, 446, 826, 634, -4, 807, + 469, 824, 54, 436, 812, 341, 755, 40, 21, 427, + 444, 471, 130, 472, 1068, 473, 346, 767, 428, 768, + -211, -211, -211, 33, 34, 429, 361, 308, 1076, 35, + 474,-32766,-32766,-32766, 1046, 357, 358, 475, 476,-32766, + -32766,-32766, 906, 120, 477, 539, 1068, 795, 846, 430, + 431, 436,-32766, 341,-32766,-32766,-32766, 1046, 480, 810, + -32766, 925,-32766,-32766, 754, 1080, 1079, 1081, 49,-32766, + -32766,-32766, 749, 751, 426, 1201, 826, 634, -211, 30, + 469, 669, 668, 436, 812, 341, 75, 40, 21, 427, + -32766, 471, 1064, 472, 124, 473, 669, 668, 428, 212, + -210, -210, -210, 33, 34, 429, 361, 51, 1186, 35, + 474, 755,-32766,-32766,-32766, 357, 358, 475, 476, 213, + 824, 54, 221, 222, 477, 20, 581, 795, 846, 430, + 431, 220, 221, 222, 755, 222, 247, 78, 79, 80, + 81, 341, 207, 517, 103, 104, 105, 752, 307, 131, + 637, 1068, 207, 341, 207, 122, 826, 634, -210, 36, + 106, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 1112, 307, 346, 436, 214, + 341, 824, 54, 426, 123, 250, 129, 134, 106, 469, + -32766, 572, 1112, 812, 245, 246, 40, 21, 427, 251, + 471, 252, 472, 341, 473, 453, 22, 428, 207, 899, + 900, 638, 33, 34, 429, 824, 54, -86, 35, 474, + 220, 221, 222, 314, 357, 358, 100, 101, 102, 239, + 240, 241, 645, 477, -230, 458, 589, 135, 374, 596, + 597, 207, 760, 640, 648, 642, 941, 654, 929, 662, + 822, 133, 307, 837, 426,-32766, 106, 749, 43, 44, + 469, 45, 442, 46, 812, 826, 634, 40, 21, 427, + 47, 471, 50, 472, 53, 473, 132, 608, 428, 302, + 604, -280,-32766, 33, 34, 429, 824, 54, 426, 35, + 474, 755, 957, -84, 469, 357, 358, 521, 812, 628, + 363, 40, 21, 427, 477, 471, 575, 472, -515, 473, + 847, 616, 428, -423,-32766, 11, 646, 33, 34, 429, + 824, 54, 445, 35, 474, 462, 285, 578, 1111, 357, + 358, 593, 369, 848, 594, 290, 826, 634, 477, 0, + 0, 532, 0, 0, 325, 0, 0, 0, 0, 0, + 651, 0, 0, 0, 322, 326, 0, 0, 0, 426, + 0, 0, 0, 0, 323, 469, 316, 318, -516, 812, + 862, 634, 40, 21, 427, 0, 471, 0, 472, 0, + 473, 1158, 0, 428, 0, -414, 6, 7, 33, 34, + 429, 824, 54, 426, 35, 474, 12, 14, 373, 469, + 357, 358, -424, 812, 563, 754, 40, 21, 427, 477, + 471, 248, 472, 839, 473, 38, 39, 428, 657, 658, + 765, 813, 33, 34, 429, 821, 800, 815, 35, 474, + 215, 216, 878, 869, 357, 358, 217, 870, 218, 798, + 863, 826, 634, 477, 860, 858, 936, 937, 934, 820, + 209, 804, 806, 808, 811, 933, 763, 764, 1100, 1101, + 935, 659, 78, 335, 426, 359, 1102, 635, 639, 641, + 469, 643, 644, 647, 812, 826, 634, 40, 21, 427, + 649, 471, 650, 472, 652, 473, 653, 636, 428, 796, + 1226, 1228, 762, 33, 34, 429, 215, 216, 845, 35, + 474, 761, 217, 844, 218, 357, 358, 1227, 843, 1060, + 831, 1048, 842, 1049, 477, 559, 209, 1106, 1107, 1108, + 1109, 1103, 1104, 398, 1100, 1101, 829, 942, 867, 1110, + 1105, 868, 1102, 457, 1225, 1194, 1192, 1177, 1157, 219, + 1190, 1091, 917, 1198, 1188, 0, 826, 634, 24, -433, + 26, 31, 37, 42, 76, 77, 210, 287, 292, 293, + 308, 309, 310, 311, 339, 356, 416, 0, -227, -226, + 16, 17, 18, 393, 454, 461, 463, 467, 553, 625, + 1051, 559, 1054, 1106, 1107, 1108, 1109, 1103, 1104, 398, + 907, 1116, 1050, 1026, 564, 1110, 1105, 1025, 1093, 1055, + 0, 1044, 0, 1057, 1056, 219, 1059, 1058, 1075, 0, + 1191, 1176, 1172, 1189, 1090, 1223, 1117, 1171, 600 + ); + + protected $actionCheck = array( + 2, 3, 4, 5, 6, 7, 14, 9, 10, 11, + 12, 13, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 0, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 9, 10, 11, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 69, 70, + 53, 54, 55, 9, 10, 57, 30, 116, 32, 33, + 34, 35, 36, 37, 38, 80, 69, 70, 83, 71, + 72, 73, 74, 75, 76, 77, 135, 136, 80, 33, + 34, 35, 36, 37, 38, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 31, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 13, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 3, 4, 5, 6, 7, 148, 149, 150, 82, + 12, 13, 160, 15, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 8, 44, 45, 46, 47, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 80, 33, 34, 35, 36, 50, 51, + 13, 9, 10, 11, 56, 128, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 1, 70, 71, + 72, 73, 59, 60, 37, 38, 78, 79, 80, 82, + 82, 106, 85, 108, 86, 9, 10, 11, 161, 80, + 1, 2, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 9, 10, 11, 106, 156, 30, 8, 32, 33, + 34, 35, 36, 13, 116, 8, 153, 154, 155, 8, + 122, 158, 30, 125, 126, 116, 117, 118, 119, 120, + 121, 31, 134, 135, 156, 137, 138, 139, 140, 141, + 142, 143, 145, 146, 8, 8, 133, 149, 150, 37, + 38, 153, 154, 155, 9, 10, 11, 159, 8, 161, + 162, 8, 164, 74, 75, 76, 77, 8, 13, 80, + 0, 1, 2, 84, 158, 30, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 13, 98, 9, 10, + 11, 9, 103, 104, 105, 106, 8, 70, 109, 110, + 9, 10, 11, 8, 115, 116, 117, 118, 70, 30, + 31, 37, 38, 124, 31, 8, 127, 128, 129, 130, + 8, 30, 156, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 116, 117, 118, 119, 120, + 121, 8, 82, 8, 74, 156, 157, 158, 33, 34, + 80, 1, 2, 8, 84, 163, 82, 87, 88, 89, + 133, 91, 70, 93, 152, 95, 108, 82, 98, 158, + 8, 113, 160, 103, 104, 105, 106, 13, 108, 109, + 110, 123, 122, 113, 157, 115, 116, 117, 118, 9, + 10, 11, 156, 71, 124, 157, 122, 127, 128, 129, + 130, 37, 38, 8, 82, 160, 156, 13, 134, 156, + 30, 156, 32, 33, 34, 35, 158, 157, 148, 159, + 122, 161, 80, 1, 74, 133, 156, 157, 158, 156, + 80, 1, 2, 159, 84, 161, 82, 87, 88, 89, + 157, 91, 157, 93, 122, 95, 161, 106, 98, 108, + 100, 101, 102, 103, 104, 105, 106, 159, 116, 109, + 110, 9, 10, 11, 13, 115, 116, 117, 118, 9, + 10, 11, 160, 16, 124, 81, 122, 127, 128, 129, + 130, 159, 30, 161, 32, 33, 34, 13, 134, 156, + 30, 156, 32, 33, 153, 153, 154, 155, 70, 9, + 10, 11, 80, 80, 74, 160, 156, 157, 158, 14, + 80, 37, 38, 159, 84, 161, 152, 87, 88, 89, + 30, 91, 160, 93, 14, 95, 37, 38, 98, 16, + 100, 101, 102, 103, 104, 105, 106, 70, 82, 109, + 110, 82, 33, 34, 35, 115, 116, 117, 118, 16, + 1, 2, 10, 11, 124, 160, 85, 127, 128, 129, + 130, 9, 10, 11, 82, 11, 14, 157, 9, 10, + 11, 161, 30, 85, 53, 54, 55, 154, 57, 157, + 31, 122, 30, 161, 30, 157, 156, 157, 158, 30, + 69, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 144, 57, 161, 159, 16, + 161, 1, 2, 74, 157, 16, 152, 157, 69, 80, + 116, 161, 144, 84, 69, 70, 87, 88, 89, 16, + 91, 16, 93, 161, 95, 75, 76, 98, 30, 135, + 136, 31, 103, 104, 105, 1, 2, 31, 109, 110, + 9, 10, 11, 31, 115, 116, 50, 51, 52, 50, + 51, 52, 31, 124, 160, 75, 76, 101, 102, 111, + 112, 30, 156, 157, 31, 31, 156, 157, 156, 157, + 31, 31, 57, 38, 74, 33, 69, 80, 70, 70, + 80, 70, 89, 70, 84, 156, 157, 87, 88, 89, + 70, 91, 70, 93, 70, 95, 70, 96, 98, 71, + 77, 82, 85, 103, 104, 105, 1, 2, 74, 109, + 110, 82, 82, 97, 80, 115, 116, 85, 84, 92, + 106, 87, 88, 89, 124, 91, 90, 93, 133, 95, + 128, 94, 98, 147, 116, 97, 31, 103, 104, 105, + 1, 2, 97, 109, 110, 97, 97, 100, 144, 115, + 116, 100, 106, 128, 113, 161, 156, 157, 124, -1, + -1, 151, -1, -1, 114, -1, -1, -1, -1, -1, + 31, -1, -1, -1, 131, 131, -1, -1, -1, 74, + -1, -1, -1, -1, 132, 80, 133, 133, 133, 84, + 156, 157, 87, 88, 89, -1, 91, -1, 93, -1, + 95, 144, -1, 98, -1, 147, 147, 147, 103, 104, + 105, 1, 2, 74, 109, 110, 147, 147, 147, 80, + 115, 116, 147, 84, 151, 153, 87, 88, 89, 124, + 91, 31, 93, 152, 95, 156, 156, 98, 156, 156, + 156, 156, 103, 104, 105, 156, 156, 156, 109, 110, + 50, 51, 156, 156, 115, 116, 56, 156, 58, 156, + 156, 156, 157, 124, 156, 156, 156, 156, 156, 156, + 70, 156, 156, 156, 156, 156, 156, 156, 78, 79, + 156, 158, 157, 157, 74, 157, 86, 157, 157, 157, + 80, 157, 157, 157, 84, 156, 157, 87, 88, 89, + 157, 91, 157, 93, 157, 95, 157, 157, 98, 158, + 158, 158, 158, 103, 104, 105, 50, 51, 158, 109, + 110, 158, 56, 158, 58, 115, 116, 158, 158, 158, + 158, 158, 158, 158, 124, 135, 70, 137, 138, 139, + 140, 141, 142, 143, 78, 79, 158, 158, 158, 149, + 150, 158, 86, 158, 158, 158, 158, 158, 164, 159, + 158, 158, 158, 158, 158, -1, 156, 157, 159, 162, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, -1, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 135, 160, 137, 138, 139, 140, 141, 142, 143, + 160, 160, 160, 160, 160, 149, 150, 160, 160, 163, + -1, 162, -1, 163, 163, 159, 163, 163, 163, -1, + 163, 163, 163, 163, 163, 163, 163, 163, 163 + ); + + protected $actionBase = array( + 0, 229, 310, 390, 470, 103, 325, 325, 784, -2, + -2, 149, -2, -2, -2, 660, 765, 799, 765, 589, + 694, 870, 870, 870, 252, 404, 404, 404, 514, 177, + 177, 918, 434, 118, 295, 313, 240, 491, 491, 491, + 491, 138, 138, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 89, 206, 773, 550, + 535, 775, 776, 777, 912, 709, 913, 856, 857, 700, + 858, 859, 862, 863, 864, 855, 865, 935, 866, 599, + 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, + 599, 322, 592, 285, 319, 232, 44, 691, 691, 691, + 691, 691, 691, 691, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 582, 530, 530, 530, 594, 860, 658, 926, + 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, + 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, + 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, + 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, + 926, 926, 926, 500, -21, -21, 492, 702, 420, 355, + 216, 549, 151, 26, 26, 331, 331, 331, 331, 331, + 46, 46, 5, 5, 5, 5, 153, 188, 188, 188, + 188, 121, 121, 121, 121, 314, 314, 394, 394, 362, + 300, 298, 499, 499, 499, 499, 499, 499, 499, 499, + 499, 499, 67, 656, 656, 659, 659, 522, 554, 554, + 554, 554, 679, -59, -59, 381, 462, 462, 462, 528, + 717, 854, 382, 382, 382, 382, 382, 382, 561, 561, + 561, -3, -3, -3, 692, 115, 137, 115, 137, 678, + 732, 450, 732, 338, 677, -15, 510, 810, 468, 707, + 850, 711, 853, 572, 735, 267, 529, 654, 674, 463, + 529, 529, 529, 529, 654, 610, 640, 608, 463, 529, + 463, 718, 323, 496, 89, 570, 507, 675, 778, 293, + 670, 780, 290, 373, 332, 566, 278, 435, 733, 781, + 914, 917, 385, 715, 675, 675, 675, 352, 511, 278, + -8, 605, 605, 605, 605, 156, 605, 605, 605, 605, + 251, 276, 375, 402, 779, 657, 657, 690, 872, 869, + 869, 657, 689, 657, 690, 874, 874, 874, 874, 657, + 657, 657, 657, 869, 869, 869, 688, 869, 239, 703, + 704, 704, 874, 742, 743, 657, 657, 712, 869, 869, + 869, 712, 695, 874, 701, 741, 277, 869, 874, 672, + 689, 672, 657, 701, 672, 689, 689, 672, 22, 666, + 668, 873, 875, 887, 790, 662, 685, 879, 880, 876, + 878, 871, 699, 744, 745, 497, 669, 671, 673, 680, + 719, 682, 713, 674, 667, 667, 667, 655, 720, 655, + 667, 667, 667, 667, 667, 667, 667, 667, 916, 646, + 731, 714, 653, 749, 553, 573, 791, 664, 811, 900, + 893, 867, 919, 881, 898, 655, 920, 739, 247, 643, + 882, 783, 786, 655, 883, 655, 792, 655, 902, 812, + 686, 813, 814, 667, 910, 921, 923, 924, 925, 927, + 928, 929, 930, 684, 931, 750, 696, 894, 299, 877, + 718, 729, 705, 788, 751, 820, 328, 932, 823, 655, + 655, 794, 785, 655, 795, 756, 740, 890, 757, 895, + 933, 664, 708, 896, 655, 706, 825, 934, 328, 681, + 683, 888, 661, 761, 886, 911, 885, 796, 649, 663, + 829, 830, 831, 693, 763, 891, 892, 889, 764, 803, + 665, 805, 697, 832, 807, 884, 768, 833, 834, 899, + 676, 730, 710, 698, 687, 809, 835, 897, 769, 770, + 771, 848, 772, 849, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 138, 138, 138, 138, -2, -2, + -2, -2, 0, 0, -2, 0, 0, 0, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 0, 0, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 599, + 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, + 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, + 599, 599, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 599, -21, -21, -21, -21, 599, + -21, -21, -21, -21, -21, -21, -21, 599, 599, 599, + 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, + 599, 599, 599, 599, 599, -21, 599, 599, 599, -21, + 382, -21, 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 599, 0, 0, 599, + -21, 599, -21, 599, -21, -21, 599, 599, 599, 599, + 599, 599, 599, -21, -21, -21, -21, -21, -21, 0, + 561, 561, 561, 561, -21, -21, -21, -21, 382, 382, + 382, 382, 382, 382, 259, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 561, 561, -3, -3, + 382, 382, 382, 382, 382, 259, 382, 382, 463, 689, + 689, 689, 137, 137, 137, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 137, 463, 0, + 463, 0, 382, 463, 689, 463, 657, 137, 689, 689, + 463, 869, 616, 616, 616, 616, 328, 278, 0, 0, + 689, 689, 0, 0, 0, 0, 0, 689, 0, 0, + 0, 0, 0, 0, 869, 0, 0, 0, 0, 0, + 667, 247, 0, 705, 335, 0, 0, 0, 0, 0, + 0, 705, 335, 347, 347, 0, 684, 667, 667, 667, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 328 + ); + + protected $actionDefault = array( + 3,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767, 544, 544, 499,32767,32767, + 32767,32767,32767,32767,32767,32767,32767, 299, 299, 299, + 32767,32767,32767, 532, 532, 532, 532, 532, 532, 532, + 532, 532, 532, 532,32767,32767,32767,32767,32767,32767, + 383,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 389, + 549,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 364, + 365, 367, 368, 298, 552, 533, 247, 390, 548, 297, + 249, 327, 503,32767,32767,32767, 329, 122, 258, 203, + 502, 125, 296, 234, 382, 384, 328, 303, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 302, 458, 361, 360, 359, 460,32767, 459, 496, + 496, 499,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767, 325, 487, 486, 326, 456, 330, 457, + 333, 461, 464, 331, 332, 349, 350, 347, 348, 351, + 462, 463, 480, 481, 478, 479, 301, 352, 353, 354, + 355, 482, 483, 484, 485,32767,32767, 543, 543,32767, + 32767, 282,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767, 340, 341, 471, 472,32767, 238, 238, + 238, 238, 283, 238,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767, 335, 336, + 334, 466, 467, 465, 432,32767,32767,32767, 434,32767, + 32767,32767,32767,32767,32767,32767,32767,32767, 504,32767, + 32767,32767,32767,32767, 517, 421, 171,32767, 413,32767, + 171, 171, 171, 171,32767, 222, 224, 167,32767, 171, + 32767, 490,32767,32767,32767,32767, 522, 345,32767,32767, + 116,32767,32767,32767, 559,32767, 517,32767, 116,32767, + 32767,32767,32767, 358, 337, 338, 339,32767,32767, 521, + 515, 474, 475, 476, 477,32767, 468, 469, 470, 473, + 32767,32767,32767,32767,32767,32767,32767,32767, 429, 435, + 435,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767, 520, 519,32767, 414, 498, 188, + 186, 186,32767, 208, 208,32767,32767, 190, 491, 510, + 32767, 190, 173,32767, 400, 175, 498,32767,32767, 240, + 32767, 240,32767, 400, 240,32767,32767, 240,32767, 415, + 439,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767, 379, 380, 493, 506, + 32767, 507,32767, 413, 343, 344, 346, 322,32767, 324, + 369, 370, 371, 372, 373, 374, 375, 377,32767, 419, + 32767, 422,32767,32767,32767, 257,32767, 557,32767,32767, + 306, 557,32767,32767,32767, 551,32767,32767, 300,32767, + 32767,32767,32767, 253,32767, 169,32767, 541,32767, 558, + 32767, 515,32767, 342,32767,32767,32767,32767,32767,32767, + 32767,32767,32767, 516,32767,32767,32767,32767, 229,32767, + 452,32767, 116,32767,32767,32767, 189,32767,32767, 304, + 248,32767,32767, 550,32767,32767,32767,32767,32767,32767, + 32767,32767, 114,32767, 170,32767,32767,32767, 191,32767, + 32767, 515,32767,32767,32767,32767,32767,32767,32767, 295, + 32767,32767,32767,32767,32767,32767,32767, 515,32767,32767, + 233,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 415,32767, 276,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767, 127, 127, 3, 127, 127, 260, + 3, 260, 127, 260, 260, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 216, 219, 208, 208, 164, + 127, 127, 268 + ); + + protected $goto = array( + 166, 140, 140, 140, 166, 187, 168, 144, 147, 141, + 142, 143, 149, 163, 163, 163, 163, 144, 144, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 138, 159, 160, 161, 162, 184, 139, 185, 494, 495, + 377, 496, 500, 501, 502, 503, 504, 505, 506, 507, + 970, 164, 145, 146, 148, 171, 176, 186, 203, 253, + 256, 258, 260, 263, 264, 265, 266, 267, 268, 269, + 277, 278, 279, 280, 303, 304, 328, 329, 330, 394, + 395, 396, 543, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 150, 151, 152, + 167, 153, 169, 154, 204, 170, 155, 156, 157, 205, + 158, 136, 621, 561, 757, 561, 561, 561, 561, 561, + 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, + 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, + 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, + 561, 561, 561, 561, 561, 561, 561, 561, 561, 1113, + 629, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, + 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, + 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, + 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, + 1113, 1113, 1113, 1113, 1113, 758, 520, 531, 509, 656, + 556, 1183, 750, 509, 592, 786, 1183, 888, 612, 613, + 884, 617, 618, 624, 626, 631, 633, 817, 855, 855, + 855, 855, 850, 856, 174, 891, 891, 1205, 1205, 177, + 178, 179, 401, 402, 403, 404, 173, 202, 206, 208, + 257, 259, 261, 262, 270, 271, 272, 273, 274, 275, + 281, 282, 283, 284, 305, 306, 331, 332, 333, 406, + 407, 408, 409, 175, 180, 254, 255, 181, 182, 183, + 498, 498, 498, 498, 498, 498, 861, 498, 498, 498, + 498, 498, 498, 498, 498, 498, 498, 510, 586, 538, + 601, 602, 510, 545, 546, 547, 548, 549, 550, 551, + 552, 554, 587, 1209, 560, 350, 560, 560, 560, 560, + 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, + 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, + 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, + 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, + 400, 607, 537, 537, 569, 533, 909, 535, 535, 497, + 499, 525, 541, 570, 573, 584, 591, 298, 296, 296, + 296, 298, 289, 299, 611, 378, 511, 614, 595, 947, + 375, 511, 437, 437, 437, 437, 437, 437, 1163, 437, + 437, 437, 437, 437, 437, 437, 437, 437, 437, 1077, + 948, 338, 1175, 321, 1077, 898, 898, 898, 898, 606, + 898, 898, 1217, 1217, 1202, 753, 576, 605, 756, 1077, + 1077, 1077, 1077, 1077, 1077, 1069, 384, 384, 384, 391, + 1217, 877, 859, 857, 859, 655, 466, 512, 886, 881, + 753, 384, 753, 384, 968, 384, 895, 385, 588, 353, + 414, 384, 1231, 1019, 542, 1197, 1197, 1197, 568, 1094, + 386, 386, 386, 904, 915, 515, 1029, 19, 15, 372, + 389, 915, 940, 448, 450, 632, 340, 1216, 1216, 1114, + 615, 938, 840, 555, 775, 386, 913, 1070, 1073, 1074, + 399, 1069, 1182, 660, 23, 1216, 773, 1182, 544, 603, + 1066, 1219, 1071, 1174, 1071, 519, 1199, 1199, 1199, 1089, + 1088, 1072, 343, 523, 534, 519, 519, 772, 351, 352, + 13, 579, 583, 627, 1061, 388, 782, 562, 771, 515, + 783, 1181, 3, 4, 918, 956, 865, 451, 574, 1160, + 464, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 514, 529, 0, 0, 0, 0, + 514, 0, 529, 0, 0, 0, 0, 610, 513, 516, + 439, 440, 1067, 619, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 780, 1224, 0, 0, 0, 0, + 0, 524, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 778, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 301, 301 + ); + + protected $gotoCheck = array( + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 57, 69, 15, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 128, + 9, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 16, 102, 32, 69, 32, + 32, 120, 6, 69, 32, 29, 120, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 50, 69, 69, + 69, 69, 69, 69, 27, 77, 77, 77, 77, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 119, 119, 119, 119, 119, 119, 33, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 67, 110, + 67, 67, 119, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111, 142, 57, 72, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 51, 51, 51, 51, 51, 51, 84, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 5, 5, 5, + 5, 5, 5, 5, 63, 46, 124, 63, 129, 98, + 63, 124, 57, 57, 57, 57, 57, 57, 133, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 98, 127, 82, 127, 57, 57, 57, 57, 57, 49, + 57, 57, 144, 144, 140, 11, 40, 40, 14, 57, + 57, 57, 57, 57, 57, 82, 13, 13, 13, 48, + 144, 14, 14, 14, 14, 14, 57, 14, 14, 14, + 11, 13, 11, 13, 102, 13, 79, 11, 70, 70, + 70, 13, 13, 103, 2, 9, 9, 9, 2, 34, + 125, 125, 125, 81, 13, 13, 34, 34, 34, 34, + 17, 13, 8, 8, 8, 8, 18, 143, 143, 8, + 8, 8, 9, 34, 25, 125, 85, 82, 82, 82, + 125, 82, 121, 74, 34, 143, 24, 121, 47, 34, + 116, 143, 82, 82, 82, 47, 121, 121, 121, 126, + 126, 82, 58, 58, 58, 47, 47, 23, 72, 72, + 58, 62, 62, 62, 114, 12, 23, 12, 23, 13, + 26, 121, 30, 30, 86, 100, 71, 65, 66, 132, + 109, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 9, 9, -1, -1, -1, -1, + 9, -1, 9, -1, -1, -1, -1, 13, 9, 9, + 9, 9, 13, 13, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 9, 9, -1, -1, -1, -1, + -1, 102, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 5, 5 + ); + + protected $gotoBase = array( + 0, 0, -172, 0, 0, 353, 201, 0, 477, 149, + 0, 110, 195, 117, 426, 112, 203, 140, 171, 0, + 0, 0, 0, 168, 164, 157, 119, 27, 0, 205, + -118, 0, -428, 266, 51, 0, 0, 0, 0, 0, + 388, 0, 0, -24, 0, 0, 345, 484, 146, 133, + 209, 75, 0, 0, 0, 0, 0, 107, 161, 0, + 0, 0, 222, -77, 0, 106, 97, -343, 0, -94, + 135, 123, -129, 0, 129, 0, 0, -50, 0, 143, + 0, 159, 64, 0, 338, 132, 122, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, + 121, 0, 165, 156, 0, 0, 0, 0, 0, 87, + 273, 259, 0, 0, 114, 0, 150, 0, 0, -5, + -91, 200, 0, 0, 84, 154, 202, 77, -48, 178, + 0, 0, 93, 187, 0, 0, 0, 0, 0, 0, + 136, 0, 286, 167, 102, 0, 0 + ); + + protected $gotoDefault = array( + -32768, 468, 664, 2, 665, 835, 740, 748, 598, 482, + 630, 582, 380, 1193, 792, 793, 794, 381, 368, 483, + 379, 410, 405, 781, 774, 776, 784, 172, 411, 787, + 1, 789, 518, 825, 1020, 365, 797, 366, 590, 799, + 527, 801, 802, 137, 382, 383, 528, 484, 390, 577, + 816, 276, 387, 818, 367, 819, 828, 371, 465, 455, + 460, 530, 557, 609, 432, 447, 571, 565, 536, 1086, + 566, 864, 349, 872, 661, 880, 883, 485, 558, 894, + 452, 902, 1099, 397, 908, 914, 919, 291, 922, 417, + 412, 585, 927, 928, 5, 932, 622, 623, 8, 312, + 955, 599, 969, 420, 1039, 1041, 486, 487, 522, 459, + 508, 526, 488, 1062, 441, 413, 1065, 433, 489, 490, + 434, 435, 1083, 355, 1168, 354, 449, 320, 1155, 580, + 1118, 456, 1208, 1164, 348, 491, 492, 376, 1187, 392, + 1203, 438, 1210, 1218, 344, 540, 567 + ); + + protected $ruleToNonTerminal = array( + 0, 1, 3, 3, 2, 5, 5, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 7, 7, 8, 8, 9, 10, 11, 11, + 12, 12, 13, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 18, 18, 19, 19, 21, 21, + 17, 17, 22, 22, 23, 23, 24, 24, 25, 25, + 20, 20, 26, 28, 28, 29, 30, 30, 32, 31, + 31, 31, 31, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 14, 14, 54, 54, 56, 55, 55, 48, + 48, 58, 58, 59, 59, 60, 60, 61, 61, 15, + 16, 16, 16, 64, 64, 64, 65, 65, 68, 68, + 66, 66, 70, 70, 41, 41, 50, 50, 53, 53, + 53, 52, 52, 71, 42, 42, 42, 42, 72, 72, + 73, 73, 74, 74, 39, 39, 35, 35, 75, 37, + 37, 76, 36, 36, 38, 38, 49, 49, 49, 62, + 62, 78, 78, 79, 79, 81, 81, 81, 80, 80, + 63, 63, 82, 82, 82, 83, 83, 84, 84, 84, + 44, 44, 85, 85, 85, 45, 45, 86, 86, 87, + 87, 67, 88, 88, 88, 88, 93, 93, 94, 94, + 95, 95, 95, 95, 95, 96, 97, 97, 92, 92, + 89, 89, 91, 91, 99, 99, 98, 98, 98, 98, + 98, 98, 90, 90, 101, 100, 100, 46, 46, 40, + 40, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 34, 34, 47, + 47, 106, 106, 107, 107, 107, 107, 113, 102, 102, + 109, 109, 115, 115, 116, 117, 118, 118, 118, 118, + 118, 118, 118, 69, 69, 57, 57, 57, 57, 103, + 103, 122, 122, 119, 119, 123, 123, 123, 123, 104, + 104, 104, 108, 108, 108, 114, 114, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 27, 27, 27, 27, 27, 27, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 112, 112, 105, 105, 105, 105, 129, 129, 132, 132, + 131, 131, 133, 133, 51, 51, 51, 51, 135, 135, + 134, 134, 134, 134, 134, 136, 136, 121, 121, 124, + 124, 120, 120, 138, 137, 137, 137, 137, 125, 125, + 125, 125, 111, 111, 126, 126, 126, 126, 77, 139, + 139, 140, 140, 140, 110, 110, 141, 141, 142, 142, + 142, 142, 142, 127, 127, 127, 127, 144, 145, 143, + 143, 143, 143, 143, 143, 143, 146, 146, 146 + ); + + protected $ruleToLength = array( + 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 5, 4, + 3, 4, 2, 3, 1, 1, 7, 6, 3, 1, + 3, 1, 3, 1, 1, 3, 1, 3, 1, 2, + 3, 1, 3, 3, 1, 3, 2, 0, 1, 1, + 1, 1, 1, 3, 5, 8, 3, 5, 9, 3, + 2, 3, 2, 3, 2, 3, 3, 3, 3, 1, + 2, 2, 5, 7, 9, 5, 6, 3, 3, 2, + 2, 1, 1, 1, 0, 2, 8, 0, 4, 1, + 3, 0, 1, 0, 1, 0, 1, 1, 1, 10, + 7, 6, 5, 1, 2, 2, 0, 2, 0, 2, + 0, 2, 1, 3, 1, 4, 1, 4, 1, 1, + 4, 1, 3, 3, 3, 4, 4, 5, 0, 2, + 4, 3, 1, 1, 1, 4, 0, 2, 3, 0, + 2, 4, 0, 2, 0, 3, 1, 2, 1, 1, + 0, 1, 3, 4, 6, 1, 1, 1, 0, 1, + 0, 2, 2, 3, 3, 1, 3, 1, 2, 2, + 3, 1, 1, 2, 4, 3, 1, 1, 3, 2, + 0, 1, 3, 3, 9, 3, 1, 3, 0, 2, + 4, 5, 4, 4, 4, 3, 1, 1, 1, 3, + 1, 1, 0, 1, 1, 2, 1, 1, 1, 1, + 1, 1, 1, 3, 1, 1, 3, 3, 1, 0, + 1, 1, 3, 3, 4, 4, 1, 2, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 1, 3, 5, + 4, 3, 4, 4, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 3, 2, 1, 2, 10, 11, 3, 3, 2, + 4, 4, 3, 4, 4, 4, 4, 7, 3, 2, + 0, 4, 1, 3, 2, 1, 2, 2, 4, 6, + 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 3, 4, 4, 0, + 2, 1, 0, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, + 1, 3, 1, 4, 3, 1, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, + 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, + 1, 3, 1, 1, 3, 3, 0, 2, 0, 1, + 3, 1, 3, 1, 1, 1, 1, 1, 6, 4, + 3, 4, 2, 4, 4, 1, 3, 1, 2, 1, + 1, 4, 1, 1, 3, 6, 4, 4, 4, 4, + 1, 4, 0, 1, 1, 3, 1, 1, 4, 3, + 1, 1, 1, 0, 0, 2, 3, 1, 3, 1, + 4, 2, 2, 2, 2, 1, 2, 1, 1, 1, + 4, 3, 3, 3, 6, 3, 1, 1, 1 + ); + + protected function initReduceCallbacks() { + $this->reduceCallbacks = [ + 0 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 1 => function ($stackPos) { + $this->semValue = $this->handleNamespaces($this->semStack[$stackPos-(1-1)]); + }, + 2 => function ($stackPos) { + if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; + }, + 3 => function ($stackPos) { + $this->semValue = array(); + }, + 4 => function ($stackPos) { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 5 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 6 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 7 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 8 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 9 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 10 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 11 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 12 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 13 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 14 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 15 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 16 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 17 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 18 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 19 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 20 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 21 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 22 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 23 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 24 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 25 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 26 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 27 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 28 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 29 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 30 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 31 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 32 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 33 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 34 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 35 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 36 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 37 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 38 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 39 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 40 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 41 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 42 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 43 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 44 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 45 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 46 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 47 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 48 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 49 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 50 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 51 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 52 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 53 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 54 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 55 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 56 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 57 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 58 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 59 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 60 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 61 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 62 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 63 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 64 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 65 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 66 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 67 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 68 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 69 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 70 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 71 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 72 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 73 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 74 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 75 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 76 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 77 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 78 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 79 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 80 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 81 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 82 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 83 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 84 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 85 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 86 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 87 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 88 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 89 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 90 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 91 => function ($stackPos) { + $this->semValue = new Name(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 92 => function ($stackPos) { + $this->semValue = new Expr\Variable(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 93 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 94 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 95 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 96 => function ($stackPos) { + $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 97 => function ($stackPos) { + $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(3-2)], null, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); + $this->checkNamespace($this->semValue); + }, + 98 => function ($stackPos) { + $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($this->semValue); + }, + 99 => function ($stackPos) { + $this->semValue = new Stmt\Namespace_(null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($this->semValue); + }, + 100 => function ($stackPos) { + $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 101 => function ($stackPos) { + $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 102 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 103 => function ($stackPos) { + $this->semValue = new Stmt\Const_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 104 => function ($stackPos) { + $this->semValue = Stmt\Use_::TYPE_FUNCTION; + }, + 105 => function ($stackPos) { + $this->semValue = Stmt\Use_::TYPE_CONSTANT; + }, + 106 => function ($stackPos) { + $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-6)], $this->semStack[$stackPos-(7-2)], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + }, + 107 => function ($stackPos) { + $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 108 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 109 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 110 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 111 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 112 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 113 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 114 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); + }, + 115 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); + }, + 116 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); + }, + 117 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); + }, + 118 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; $this->semValue->type = Stmt\Use_::TYPE_NORMAL; + }, + 119 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; $this->semValue->type = $this->semStack[$stackPos-(2-1)]; + }, + 120 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 121 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 122 => function ($stackPos) { + $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 123 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 124 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 125 => function ($stackPos) { + $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 126 => function ($stackPos) { + if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; + }, + 127 => function ($stackPos) { + $this->semValue = array(); + }, + 128 => function ($stackPos) { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 129 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 130 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 131 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 132 => function ($stackPos) { + throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 133 => function ($stackPos) { + + if ($this->semStack[$stackPos-(3-2)]) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; $attrs = $this->startAttributeStack[$stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); }; + } else { + $startAttributes = $this->startAttributeStack[$stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; + if (null === $this->semValue) { $this->semValue = array(); } + } + + }, + 134 => function ($stackPos) { + $this->semValue = new Stmt\If_($this->semStack[$stackPos-(5-2)], ['stmts' => is_array($this->semStack[$stackPos-(5-3)]) ? $this->semStack[$stackPos-(5-3)] : array($this->semStack[$stackPos-(5-3)]), 'elseifs' => $this->semStack[$stackPos-(5-4)], 'else' => $this->semStack[$stackPos-(5-5)]], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 135 => function ($stackPos) { + $this->semValue = new Stmt\If_($this->semStack[$stackPos-(8-2)], ['stmts' => $this->semStack[$stackPos-(8-4)], 'elseifs' => $this->semStack[$stackPos-(8-5)], 'else' => $this->semStack[$stackPos-(8-6)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 136 => function ($stackPos) { + $this->semValue = new Stmt\While_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 137 => function ($stackPos) { + $this->semValue = new Stmt\Do_($this->semStack[$stackPos-(5-4)], is_array($this->semStack[$stackPos-(5-2)]) ? $this->semStack[$stackPos-(5-2)] : array($this->semStack[$stackPos-(5-2)]), $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 138 => function ($stackPos) { + $this->semValue = new Stmt\For_(['init' => $this->semStack[$stackPos-(9-3)], 'cond' => $this->semStack[$stackPos-(9-5)], 'loop' => $this->semStack[$stackPos-(9-7)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 139 => function ($stackPos) { + $this->semValue = new Stmt\Switch_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 140 => function ($stackPos) { + $this->semValue = new Stmt\Break_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 141 => function ($stackPos) { + $this->semValue = new Stmt\Break_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 142 => function ($stackPos) { + $this->semValue = new Stmt\Continue_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 143 => function ($stackPos) { + $this->semValue = new Stmt\Continue_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 144 => function ($stackPos) { + $this->semValue = new Stmt\Return_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 145 => function ($stackPos) { + $this->semValue = new Stmt\Return_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 146 => function ($stackPos) { + $this->semValue = new Stmt\Global_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 147 => function ($stackPos) { + $this->semValue = new Stmt\Static_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 148 => function ($stackPos) { + $this->semValue = new Stmt\Echo_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 149 => function ($stackPos) { + $this->semValue = new Stmt\InlineHTML($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 150 => function ($stackPos) { + $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 151 => function ($stackPos) { + $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 152 => function ($stackPos) { + $this->semValue = new Stmt\Unset_($this->semStack[$stackPos-(5-3)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 153 => function ($stackPos) { + $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$stackPos-(7-5)][1], 'stmts' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + }, + 154 => function ($stackPos) { + $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(9-3)], $this->semStack[$stackPos-(9-7)][0], ['keyVar' => $this->semStack[$stackPos-(9-5)], 'byRef' => $this->semStack[$stackPos-(9-7)][1], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 155 => function ($stackPos) { + $this->semValue = new Stmt\Declare_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 156 => function ($stackPos) { + $this->semValue = new Stmt\TryCatch($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-5)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue); + }, + 157 => function ($stackPos) { + $this->semValue = new Stmt\Throw_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 158 => function ($stackPos) { + $this->semValue = new Stmt\Goto_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 159 => function ($stackPos) { + $this->semValue = new Stmt\Label($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 160 => function ($stackPos) { + $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 161 => function ($stackPos) { + $this->semValue = array(); /* means: no statement */ + }, + 162 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 163 => function ($stackPos) { + $startAttributes = $this->startAttributeStack[$stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; + if ($this->semValue === null) $this->semValue = array(); /* means: no statement */ + }, + 164 => function ($stackPos) { + $this->semValue = array(); + }, + 165 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 166 => function ($stackPos) { + $this->semValue = new Stmt\Catch_(array($this->semStack[$stackPos-(8-3)]), $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-7)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 167 => function ($stackPos) { + $this->semValue = null; + }, + 168 => function ($stackPos) { + $this->semValue = new Stmt\Finally_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 169 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 170 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 171 => function ($stackPos) { + $this->semValue = false; + }, + 172 => function ($stackPos) { + $this->semValue = true; + }, + 173 => function ($stackPos) { + $this->semValue = false; + }, + 174 => function ($stackPos) { + $this->semValue = true; + }, + 175 => function ($stackPos) { + $this->semValue = false; + }, + 176 => function ($stackPos) { + $this->semValue = true; + }, + 177 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 178 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 179 => function ($stackPos) { + $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(10-3)], ['byRef' => $this->semStack[$stackPos-(10-2)], 'params' => $this->semStack[$stackPos-(10-5)], 'returnType' => $this->semStack[$stackPos-(10-7)], 'stmts' => $this->semStack[$stackPos-(10-9)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); + }, + 180 => function ($stackPos) { + $this->semValue = new Stmt\Class_($this->semStack[$stackPos-(7-2)], ['type' => $this->semStack[$stackPos-(7-1)], 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + $this->checkClass($this->semValue, $stackPos-(7-2)); + }, + 181 => function ($stackPos) { + $this->semValue = new Stmt\Interface_($this->semStack[$stackPos-(6-2)], ['extends' => $this->semStack[$stackPos-(6-3)], 'stmts' => $this->semStack[$stackPos-(6-5)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + $this->checkInterface($this->semValue, $stackPos-(6-2)); + }, + 182 => function ($stackPos) { + $this->semValue = new Stmt\Trait_($this->semStack[$stackPos-(5-2)], ['stmts' => $this->semStack[$stackPos-(5-4)]], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 183 => function ($stackPos) { + $this->semValue = 0; + }, + 184 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; + }, + 185 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_FINAL; + }, + 186 => function ($stackPos) { + $this->semValue = null; + }, + 187 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 188 => function ($stackPos) { + $this->semValue = array(); + }, + 189 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 190 => function ($stackPos) { + $this->semValue = array(); + }, + 191 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 192 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 193 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 194 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 195 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 196 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 197 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 198 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 199 => function ($stackPos) { + $this->semValue = null; + }, + 200 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 201 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 202 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 203 => function ($stackPos) { + $this->semValue = new Stmt\DeclareDeclare($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 204 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 205 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-3)]; + }, + 206 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 207 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(5-3)]; + }, + 208 => function ($stackPos) { + $this->semValue = array(); + }, + 209 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 210 => function ($stackPos) { + $this->semValue = new Stmt\Case_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 211 => function ($stackPos) { + $this->semValue = new Stmt\Case_(null, $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 212 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 213 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 214 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 215 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 216 => function ($stackPos) { + $this->semValue = array(); + }, + 217 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 218 => function ($stackPos) { + $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(3-2)], is_array($this->semStack[$stackPos-(3-3)]) ? $this->semStack[$stackPos-(3-3)] : array($this->semStack[$stackPos-(3-3)]), $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 219 => function ($stackPos) { + $this->semValue = array(); + }, + 220 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 221 => function ($stackPos) { + $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 222 => function ($stackPos) { + $this->semValue = null; + }, + 223 => function ($stackPos) { + $this->semValue = new Stmt\Else_(is_array($this->semStack[$stackPos-(2-2)]) ? $this->semStack[$stackPos-(2-2)] : array($this->semStack[$stackPos-(2-2)]), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 224 => function ($stackPos) { + $this->semValue = null; + }, + 225 => function ($stackPos) { + $this->semValue = new Stmt\Else_($this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 226 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)], false); + }, + 227 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(2-2)], true); + }, + 228 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)], false); + }, + 229 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 230 => function ($stackPos) { + $this->semValue = array(); + }, + 231 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 232 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 233 => function ($stackPos) { + $this->semValue = new Node\Param($this->semStack[$stackPos-(4-4)], null, $this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); $this->checkParam($this->semValue); + }, + 234 => function ($stackPos) { + $this->semValue = new Node\Param($this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-6)], $this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-3)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkParam($this->semValue); + }, + 235 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 236 => function ($stackPos) { + $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 237 => function ($stackPos) { + $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 238 => function ($stackPos) { + $this->semValue = null; + }, + 239 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 240 => function ($stackPos) { + $this->semValue = null; + }, + 241 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 242 => function ($stackPos) { + $this->semValue = array(); + }, + 243 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 244 => function ($stackPos) { + $this->semValue = array(new Node\Arg($this->semStack[$stackPos-(3-2)], false, false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes)); + }, + 245 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 246 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 247 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(1-1)], false, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 248 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], true, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 249 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], false, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 250 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 251 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 252 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 253 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 254 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 255 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 256 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 257 => function ($stackPos) { + $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 258 => function ($stackPos) { + $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 259 => function ($stackPos) { + if ($this->semStack[$stackPos-(2-2)] !== null) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; } + }, + 260 => function ($stackPos) { + $this->semValue = array(); + }, + 261 => function ($stackPos) { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 262 => function ($stackPos) { + $this->semValue = new Stmt\Property($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkProperty($this->semValue, $stackPos-(3-1)); + }, + 263 => function ($stackPos) { + $this->semValue = new Stmt\ClassConst($this->semStack[$stackPos-(3-2)], 0, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 264 => function ($stackPos) { + $this->semValue = new Stmt\ClassMethod($this->semStack[$stackPos-(9-4)], ['type' => $this->semStack[$stackPos-(9-1)], 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-6)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + $this->checkClassMethod($this->semValue, $stackPos-(9-1)); + }, + 265 => function ($stackPos) { + $this->semValue = new Stmt\TraitUse($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 266 => function ($stackPos) { + $this->semValue = array(); + }, + 267 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 268 => function ($stackPos) { + $this->semValue = array(); + }, + 269 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 270 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 271 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(5-1)][0], $this->semStack[$stackPos-(5-1)][1], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 272 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], null, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 273 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 274 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 275 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + }, + 276 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 277 => function ($stackPos) { + $this->semValue = array(null, $this->semStack[$stackPos-(1-1)]); + }, + 278 => function ($stackPos) { + $this->semValue = null; + }, + 279 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 280 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 281 => function ($stackPos) { + $this->semValue = 0; + }, + 282 => function ($stackPos) { + $this->semValue = 0; + }, + 283 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 284 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 285 => function ($stackPos) { + $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; + }, + 286 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; + }, + 287 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; + }, + 288 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; + }, + 289 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_STATIC; + }, + 290 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; + }, + 291 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_FINAL; + }, + 292 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 293 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 294 => function ($stackPos) { + $this->semValue = new Node\VarLikeIdentifier(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 295 => function ($stackPos) { + $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 296 => function ($stackPos) { + $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 297 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 298 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 299 => function ($stackPos) { + $this->semValue = array(); + }, + 300 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 301 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 302 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 303 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 304 => function ($stackPos) { + $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 305 => function ($stackPos) { + $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 306 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 307 => function ($stackPos) { + $this->semValue = new Expr\Clone_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 308 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 309 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 310 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 311 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 312 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 313 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 314 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 315 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 316 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 317 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 318 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 319 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 320 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 321 => function ($stackPos) { + $this->semValue = new Expr\PostInc($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 322 => function ($stackPos) { + $this->semValue = new Expr\PreInc($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 323 => function ($stackPos) { + $this->semValue = new Expr\PostDec($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 324 => function ($stackPos) { + $this->semValue = new Expr\PreDec($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 325 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 326 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 327 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 328 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 329 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 330 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 331 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 332 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 333 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 334 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 335 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 336 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 337 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 338 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 339 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 340 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 341 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 342 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 343 => function ($stackPos) { + $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 344 => function ($stackPos) { + $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 345 => function ($stackPos) { + $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 346 => function ($stackPos) { + $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 347 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 348 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 349 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 350 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 351 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 352 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 353 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 354 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 355 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 356 => function ($stackPos) { + $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 357 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 358 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 359 => function ($stackPos) { + $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 360 => function ($stackPos) { + $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 361 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 362 => function ($stackPos) { + $this->semValue = new Expr\Isset_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 363 => function ($stackPos) { + $this->semValue = new Expr\Empty_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 364 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 365 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 366 => function ($stackPos) { + $this->semValue = new Expr\Eval_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 367 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 368 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 369 => function ($stackPos) { + $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 370 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; + $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos-(2-1)]); + $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $attrs); + }, + 371 => function ($stackPos) { + $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 372 => function ($stackPos) { + $this->semValue = new Expr\Cast\Array_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 373 => function ($stackPos) { + $this->semValue = new Expr\Cast\Object_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 374 => function ($stackPos) { + $this->semValue = new Expr\Cast\Bool_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 375 => function ($stackPos) { + $this->semValue = new Expr\Cast\Unset_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 376 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; + $attrs['kind'] = strtolower($this->semStack[$stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; + $this->semValue = new Expr\Exit_($this->semStack[$stackPos-(2-2)], $attrs); + }, + 377 => function ($stackPos) { + $this->semValue = new Expr\ErrorSuppress($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 378 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 379 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 380 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 381 => function ($stackPos) { + $this->semValue = new Expr\ShellExec($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 382 => function ($stackPos) { + $this->semValue = new Expr\Print_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 383 => function ($stackPos) { + $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 384 => function ($stackPos) { + $this->semValue = new Expr\YieldFrom($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 385 => function ($stackPos) { + $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(10-2)], 'params' => $this->semStack[$stackPos-(10-4)], 'uses' => $this->semStack[$stackPos-(10-6)], 'returnType' => $this->semStack[$stackPos-(10-7)], 'stmts' => $this->semStack[$stackPos-(10-9)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); + }, + 386 => function ($stackPos) { + $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(11-3)], 'params' => $this->semStack[$stackPos-(11-5)], 'uses' => $this->semStack[$stackPos-(11-7)], 'returnType' => $this->semStack[$stackPos-(11-8)], 'stmts' => $this->semStack[$stackPos-(11-10)]], $this->startAttributeStack[$stackPos-(11-1)] + $this->endAttributes); + }, + 387 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 388 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 389 => function ($stackPos) { + $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(2-2)], null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 390 => function ($stackPos) { + $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 391 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG; + $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $attrs); + }, + 392 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT; + $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $attrs); + }, + 393 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 394 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch(Scalar\String_::fromString($this->semStack[$stackPos-(4-1)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes), $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 395 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 396 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 397 => function ($stackPos) { + $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes), $this->semStack[$stackPos-(7-2)]); + $this->checkClass($this->semValue[0], -1); + }, + 398 => function ($stackPos) { + $this->semValue = new Expr\New_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 399 => function ($stackPos) { + list($class, $ctorArgs) = $this->semStack[$stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 400 => function ($stackPos) { + $this->semValue = array(); + }, + 401 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-3)]; + }, + 402 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 403 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 404 => function ($stackPos) { + $this->semValue = new Expr\ClosureUse($this->semStack[$stackPos-(2-2)], $this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 405 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 406 => function ($stackPos) { + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 407 => function ($stackPos) { + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 408 => function ($stackPos) { + $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 409 => function ($stackPos) { + $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 410 => function ($stackPos) { + $this->semValue = $this->fixupPhp5StaticPropCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 411 => function ($stackPos) { + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 412 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 413 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 414 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 415 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 416 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 417 => function ($stackPos) { + $this->semValue = new Name\FullyQualified(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 418 => function ($stackPos) { + $this->semValue = new Name\Relative(substr($this->semStack[$stackPos-(1-1)], 10), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 419 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 420 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 421 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 422 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 423 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 424 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 425 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 426 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 427 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 428 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 429 => function ($stackPos) { + $this->semValue = null; + }, + 430 => function ($stackPos) { + $this->semValue = null; + }, + 431 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 432 => function ($stackPos) { + $this->semValue = array(); + }, + 433 => function ($stackPos) { + $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos-(1-1)], '`', false), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); + }, + 434 => function ($stackPos) { + foreach ($this->semStack[$stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', false); } }; $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 435 => function ($stackPos) { + $this->semValue = array(); + }, + 436 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 437 => function ($stackPos) { + $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, true); + }, + 438 => function ($stackPos) { + $this->semValue = Scalar\DNumber::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 439 => function ($stackPos) { + $this->semValue = Scalar\String_::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, false); + }, + 440 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 441 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 442 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 443 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 444 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 445 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 446 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 447 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 448 => function ($stackPos) { + $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], false); + }, + 449 => function ($stackPos) { + $this->semValue = $this->parseDocString($this->semStack[$stackPos-(2-1)], '', $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(2-2)] + $this->endAttributeStack[$stackPos-(2-2)], false); + }, + 450 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 451 => function ($stackPos) { + $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 452 => function ($stackPos) { + $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 453 => function ($stackPos) { + $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 454 => function ($stackPos) { + $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 455 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 456 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 457 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 458 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 459 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 460 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 461 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 462 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 463 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 464 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 465 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 466 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 467 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 468 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 469 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 470 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 471 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 472 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 473 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 474 => function ($stackPos) { + $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 475 => function ($stackPos) { + $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 476 => function ($stackPos) { + $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 477 => function ($stackPos) { + $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 478 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 479 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 480 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 481 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 482 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 483 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 484 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 485 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 486 => function ($stackPos) { + $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 487 => function ($stackPos) { + $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 488 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 489 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 490 => function ($stackPos) { + $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 491 => function ($stackPos) { + $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 492 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 493 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 494 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; + foreach ($this->semStack[$stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$stackPos-(3-2)], $attrs); + }, + 495 => function ($stackPos) { + $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true); + }, + 496 => function ($stackPos) { + $this->semValue = array(); + }, + 497 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 498 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 499 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 500 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 501 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 502 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 503 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 504 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 505 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 506 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 507 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 508 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 509 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 510 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 511 => function ($stackPos) { + $this->semValue = new Expr\MethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 512 => function ($stackPos) { + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 513 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 514 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 515 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 516 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 517 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 518 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 519 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 520 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 521 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 522 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 523 => function ($stackPos) { + $var = substr($this->semStack[$stackPos-(1-1)], 1); $this->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes) : $var; + }, + 524 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 525 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 526 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 527 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 528 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 529 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 530 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 531 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 532 => function ($stackPos) { + $this->semValue = null; + }, + 533 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 534 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 535 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 536 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 537 => function ($stackPos) { + $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; + }, + 538 => function ($stackPos) { + $this->semValue = new Expr\List_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 539 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 540 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 541 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 542 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 543 => function ($stackPos) { + $this->semValue = null; + }, + 544 => function ($stackPos) { + $this->semValue = array(); + }, + 545 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 546 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 547 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 548 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 549 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 550 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-1)], true, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 551 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 552 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 553 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 554 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 555 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 556 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); + }, + 557 => function ($stackPos) { + $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 558 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 559 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 560 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 561 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 562 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 563 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 564 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-4)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 565 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 566 => function ($stackPos) { + $this->semValue = new Scalar\String_($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 567 => function ($stackPos) { + $this->semValue = $this->parseNumString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 568 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + ]; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php b/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php new file mode 100644 index 00000000..48deff23 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php @@ -0,0 +1,2882 @@ +'", + "T_IS_GREATER_OR_EQUAL", + "T_SL", + "T_SR", + "'+'", + "'-'", + "'.'", + "'*'", + "'/'", + "'%'", + "'!'", + "T_INSTANCEOF", + "'~'", + "T_INC", + "T_DEC", + "T_INT_CAST", + "T_DOUBLE_CAST", + "T_STRING_CAST", + "T_ARRAY_CAST", + "T_OBJECT_CAST", + "T_BOOL_CAST", + "T_UNSET_CAST", + "'@'", + "T_POW", + "'['", + "T_NEW", + "T_CLONE", + "T_EXIT", + "T_IF", + "T_ELSEIF", + "T_ELSE", + "T_ENDIF", + "T_LNUMBER", + "T_DNUMBER", + "T_STRING", + "T_STRING_VARNAME", + "T_VARIABLE", + "T_NUM_STRING", + "T_INLINE_HTML", + "T_ENCAPSED_AND_WHITESPACE", + "T_CONSTANT_ENCAPSED_STRING", + "T_ECHO", + "T_DO", + "T_WHILE", + "T_ENDWHILE", + "T_FOR", + "T_ENDFOR", + "T_FOREACH", + "T_ENDFOREACH", + "T_DECLARE", + "T_ENDDECLARE", + "T_AS", + "T_SWITCH", + "T_MATCH", + "T_ENDSWITCH", + "T_CASE", + "T_DEFAULT", + "T_BREAK", + "T_CONTINUE", + "T_GOTO", + "T_FUNCTION", + "T_FN", + "T_CONST", + "T_RETURN", + "T_TRY", + "T_CATCH", + "T_FINALLY", + "T_USE", + "T_INSTEADOF", + "T_GLOBAL", + "T_STATIC", + "T_ABSTRACT", + "T_FINAL", + "T_PRIVATE", + "T_PROTECTED", + "T_PUBLIC", + "T_READONLY", + "T_VAR", + "T_UNSET", + "T_ISSET", + "T_EMPTY", + "T_HALT_COMPILER", + "T_CLASS", + "T_TRAIT", + "T_INTERFACE", + "T_ENUM", + "T_EXTENDS", + "T_IMPLEMENTS", + "T_OBJECT_OPERATOR", + "T_NULLSAFE_OBJECT_OPERATOR", + "T_LIST", + "T_ARRAY", + "T_CALLABLE", + "T_CLASS_C", + "T_TRAIT_C", + "T_METHOD_C", + "T_FUNC_C", + "T_LINE", + "T_FILE", + "T_START_HEREDOC", + "T_END_HEREDOC", + "T_DOLLAR_OPEN_CURLY_BRACES", + "T_CURLY_OPEN", + "T_PAAMAYIM_NEKUDOTAYIM", + "T_NAMESPACE", + "T_NS_C", + "T_DIR", + "T_NS_SEPARATOR", + "T_ELLIPSIS", + "T_NAME_FULLY_QUALIFIED", + "T_NAME_QUALIFIED", + "T_NAME_RELATIVE", + "T_ATTRIBUTE", + "';'", + "']'", + "'{'", + "'}'", + "'('", + "')'", + "'`'", + "'\"'", + "'$'" + ); + + protected $tokenToSymbol = array( + 0, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 56, 166, 168, 167, 55, 168, 168, + 163, 164, 53, 50, 8, 51, 52, 54, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 31, 159, + 44, 16, 46, 30, 68, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 70, 168, 160, 36, 168, 165, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 161, 35, 162, 58, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 1, 2, 3, 4, + 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 32, 33, 34, 37, 38, 39, 40, + 41, 42, 43, 45, 47, 48, 49, 57, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 69, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158 + ); + + protected $action = array( + 132, 133, 134, 575, 135, 136, 0, 738, 739, 740, + 137, 37, 850, 825, 851, 476,-32766,-32766,-32766,-32767, + -32767,-32767,-32767, 101, 102, 103, 104, 105, 1097, 1098, + 1099, 1096, 1095, 1094, 1100, 732, 731,-32766, 1289,-32766, + -32766,-32766,-32766,-32766,-32766,-32766,-32767,-32767,-32767,-32767, + -32767, 1022, 377, 376, 2, 741,-32766,-32766,-32766,-32766, + -32766, 822, 417,-32766,-32766,-32766,-32766,-32766,-32766, 267, + 138, 399, 745, 746, 747, 748, 287,-32766, 423,-32766, + -32766,-32766,-32766,-32766,-32766, 749, 750, 751, 752, 753, + 754, 755, 756, 757, 758, 759, 779, 576, 780, 781, + 782, 783, 771, 772, 340, 341, 774, 775, 760, 761, + 762, 764, 765, 766, 351, 806, 807, 808, 809, 810, + 577, 767, 768, 578, 579, 800, 791, 789, 790, 803, + 786, 787, -327, 423, 580, 581, 785, 582, 583, 584, + 585, 586, 587, 605, -590, 477, -86, 814, 788, 588, + 589, -590, 139,-32766,-32766,-32766, 132, 133, 134, 575, + 135, 136, 1046, 738, 739, 740, 137, 37, 323, 1013, + 823, 824, 1334, 1324,-32766, 1335,-32766,-32766,-32766,-32766, + -32766,-32766,-32766, 1097, 1098, 1099, 1096, 1095, 1094, 1100, + -587, 732, 731,-32766,-32766,-32766, 12, -587, 81,-32766, + -32766,-32766, 945, 946, 322, 927, 34, 947, 1224, 1223, + 1225, 741, -86, 942,-32766, 1075,-32766,-32766,-32766,-32766, + -32766, 239,-32766,-32766,-32766, 267, 138, 399, 745, 746, + 747, 748, 461, 462, 423, 35, 247, 103, 104, 105, + 128, 749, 750, 751, 752, 753, 754, 755, 756, 757, + 758, 759, 779, 576, 780, 781, 782, 783, 771, 772, + 340, 341, 774, 775, 760, 761, 762, 764, 765, 766, + 351, 806, 807, 808, 809, 810, 577, 767, 768, 578, + 579, 800, 791, 789, 790, 803, 786, 787, -327, 144, + 580, 581, 785, 582, 583, 584, 585, 586, 587, 1222, + 82, 83, 84, -590, 788, 588, 589, -590, 148, 763, + 733, 734, 735, 736, 737, 1309, 738, 739, 740, 776, + 777, 36, 1308, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 288, 271, -587, + -193, 375, 376, -587, 976,-32766, 1021, 453, 454, 455, + 109, 417, 945, 946, 741, 712, 819, 947,-32766,-32766, + -32766, -271, 1073, 941, 1224, 1223, 1225, 288, 742, 743, + 744, 745, 746, 747, 748, -192, -365, 812, -365,-32766, + 599,-32766,-32766, 549, 749, 750, 751, 752, 753, 754, + 755, 756, 757, 758, 759, 779, 802, 780, 781, 782, + 783, 771, 772, 773, 801, 774, 775, 760, 761, 762, + 764, 765, 766, 805, 806, 807, 808, 809, 810, 811, + 767, 768, 769, 770, 800, 791, 789, 790, 803, 786, + 787, 251, 820, 778, 784, 785, 792, 793, 795, 794, + 796, 797, 732, 731, 1261, 1022, 1019, 788, 799, 798, + 49, 50, 51, 507, 52, 53, 1009, 1008, 1007, 1010, + 54, 55, -111, 56, 816, 1045, 14, -111, 1022, -111, + 287, 1305, 977, 306, 302, 1022, 238, -111, -111, -111, + -111, -111, -111, -111, -111, 106, 107, 108, 1089, 271, + -32766,-32766,-32766, 280, 284, 126, -193, 929, 57, 58, + 287, 109, 1019, -541, 59, 308, 60, 244, 245, 61, + 62, 63, 64, 65, 66, 67, 68, 1229, 27, 269, + 69, 439, 508, -341, 1022, 929, 1255, 1256, 509, 907, + 823, -192, 150, 907, 1253, 41, 24, 510, 352, 511, + 818, 512, 386, 513, 11, 699, 514, 515, 648, 25, + 814, 43, 44, 440, 372, 371, 907, 45, 516, 702, + 1220, 667, 668, 363, 334, -540, 357, -541, -541, 320, + 1215, 1249, 518, 519, 520, -581, 1074, 335, 724, -581, + 1019,-32766, -541, 336, 521, 522, 703, 1243, 1244, 1245, + 1246, 1240, 1241, 294, -541, 850, -547, 851, 823, 1247, + 1242, 365, 1022, 1224, 1223, 1225, 295, -153, -153, -153, + 369, 70, 897, 318, 319, 322, 897, 384, 149, 402, + 373, 374, -153, 435, -153, 436, -153, 280, -153, -540, + -540, 141, 1220, 378, 379, 639, 640, 322, 370, 897, + 907, 437, 438, 829, -540, -88, 151, 732, 731, 945, + 946, 153, 823,-32766, 517, -51, -540, 154, -546, 883, + 941, -111, -111, -111, 31, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 155, 74, + 27, 157, 32, 322, -85, 123, 124, 909, 129, 697, + 130, 909, 823, 697, -153, 143, 1253, 158,-32766, -544, + 1229, -542, 159, 160, 1222, 161, -79, 1134, 1136, -75, + 285,-32766,-32766,-32766, 909,-32766, 697,-32766, -539,-32766, + -301, -73,-32766, 897, -72, -71, 1220,-32766,-32766,-32766, + -16, 140, 1215,-32766,-32766, 732, 731, 322, -70,-32766, + 414, -69, -4, 907, -68, -67, 521, 522,-32766, 1243, + 1244, 1245, 1246, 1240, 1241, -66, -47, -18, 147, 270, + 281, 1247, 1242, -544, -544, -542, -542, 732, 731, 713, + 716, 906,-32766, 72, 146, 907, 319, 322, 1222, -297, + -542, 823, -539, -539, 276,-32766,-32766,-32766, 277,-32766, + -544,-32766, -542,-32766, 282, 283,-32766, -539, 909, 328, + 697,-32766,-32766,-32766,-32766, 704, 286,-32766,-32766, -539, + 1222, 923, 289,-32766, 414, 1220, 290,-32766,-32766,-32766, + 271,-32766,-32766,-32766, 47,-32766, 897, -111,-32766, 677, + 109, 814, 145,-32766,-32766,-32766,-32766, 823, 131,-32766, + -32766, 1336,-32766, 654, 670,-32766, 414, 1104, 370, 637, + 430, 551, 73, 13,-32766, 293, 555, 295, 897, 945, + 946, 649, 74, 434, 517, 458, 322, 487, 690, 842, + 941, -111, -111, -111, 301, 1022, 561, 655, 671, 1260, + 300,-32766, -539,-32766, 907, 603, 303, 1222, 296, 297, + 39, 1262, 9, 40,-32766,-32766,-32766, 0,-32766, 907, + -32766, 909,-32766, 697, -4,-32766, 0, 1229, 907, 0, + -32766,-32766,-32766,-32766, 307, 125,-32766,-32766, 0, 1222, + 907, 0,-32766, 414, 0, 0,-32766,-32766,-32766, 707, + -32766,-32766,-32766, 962,-32766, 697, -505,-32766, 714, -495, + 7, 482,-32766,-32766,-32766,-32766, -539, -539,-32766,-32766, + 16, 1222, 567, 367,-32766, 414, 925, 295,-32766,-32766, + -32766, -539,-32766,-32766,-32766, 822,-32766, 897, 721,-32766, + 722, -575, 888, -539,-32766,-32766,-32766, 986, 963, 970, + -32766,-32766, 897, -249, -249, -249,-32766, 414, 823, 370, + 960, 897, 971, 886, 958,-32766, 1078, 1081, 718, 1082, + 945, 946, 1079, 897, 1080, 517, 1086, 33, 1250, 834, + 883, 941, -111, -111, -111, 27, 1275, 1293, 1327, -248, + -248, -248, 1220, 642, 884, 370, 317, 823, 366, 698, + 701, 1253, 1331, 705, -111, 706, 945, 946, 708, 709, + 710, 517, 909,-32766, 697, -249, 883, 941, -111, -111, + -111, 711, 715, 700, -509, 1333, 845, 909, 48, 697, + -573, 1220, 844, 853, 295, 935, 909, 1215, 697, 74, + 978, 852, 1332, 322, 934, 932, 933, 936, 909, 1206, + 697, -248, 522, 916, 1243, 1244, 1245, 1246, 1240, 1241, + 926, 914, 968, 969, 1330, 1287, 1247, 1242, 1276, 1294, + -32766, 1300, 1303, 1191, -547, -546, 1222, -545, 72, -489, + 1, 319, 322,-32766,-32766,-32766, 28,-32766, 29,-32766, + 38,-32766, 298, 299,-32766, 42, 46, 71, 75,-32766, + -32766,-32766, 76, 77, 78,-32766,-32766, 368, 79, 80, + 142,-32766, 414, 152, 156, 243, 324, 352, 353, 127, + -32766, -274, 354, 355, 356, 357, 358, 359, 360, 361, + 362, 364, 431, 0, -272, -271, 18, 19, 20, 21, + 23, 401, 478, 479, 486, 489, 490, 491, 492, 496, + 497, 498, 505, 684, 1233, 1174, 1251, 1048, 1047, 1028, + 0, 1210, 1024, -276, -103, 17, 22, 26, 292, 400, + 596, 600, 628, 689, 1178, 1228, 1175, 1306, 0, 0, + 1254, 0, 322 + ); + + protected $actionCheck = array( + 2, 3, 4, 5, 6, 7, 0, 9, 10, 11, + 12, 13, 106, 1, 108, 31, 9, 10, 11, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 116, 117, + 118, 119, 120, 121, 122, 37, 38, 30, 1, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 138, 106, 107, 8, 57, 9, 10, 11, 9, + 10, 155, 116, 9, 10, 11, 9, 10, 11, 71, + 72, 73, 74, 75, 76, 77, 163, 30, 80, 32, + 33, 34, 35, 36, 30, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 8, 80, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 51, 1, 161, 31, 80, 150, 151, + 152, 8, 154, 9, 10, 11, 2, 3, 4, 5, + 6, 7, 164, 9, 10, 11, 12, 13, 70, 1, + 82, 159, 80, 85, 30, 83, 32, 33, 34, 35, + 36, 37, 38, 116, 117, 118, 119, 120, 121, 122, + 1, 37, 38, 9, 10, 11, 8, 8, 161, 9, + 10, 11, 117, 118, 167, 1, 8, 122, 155, 156, + 157, 57, 97, 128, 30, 162, 32, 33, 34, 35, + 30, 14, 32, 33, 34, 71, 72, 73, 74, 75, + 76, 77, 134, 135, 80, 147, 148, 50, 51, 52, + 8, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, 164, 8, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 80, + 9, 10, 11, 160, 150, 151, 152, 164, 154, 2, + 3, 4, 5, 6, 7, 1, 9, 10, 11, 12, + 13, 30, 8, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 30, 57, 160, + 8, 106, 107, 164, 31, 9, 137, 129, 130, 131, + 69, 116, 117, 118, 57, 161, 80, 122, 9, 10, + 11, 164, 1, 128, 155, 156, 157, 30, 71, 72, + 73, 74, 75, 76, 77, 8, 106, 80, 108, 30, + 1, 32, 33, 85, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 8, 156, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 37, 38, 146, 138, 116, 150, 151, 152, + 2, 3, 4, 5, 6, 7, 119, 120, 121, 122, + 12, 13, 101, 15, 80, 1, 101, 106, 138, 108, + 163, 1, 159, 8, 113, 138, 97, 116, 117, 118, + 119, 120, 121, 122, 123, 53, 54, 55, 123, 57, + 9, 10, 11, 163, 30, 14, 164, 122, 50, 51, + 163, 69, 116, 70, 56, 8, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 1, 70, 71, + 72, 73, 74, 162, 138, 122, 78, 79, 80, 1, + 82, 164, 14, 1, 86, 87, 88, 89, 163, 91, + 156, 93, 106, 95, 108, 161, 98, 99, 75, 76, + 80, 103, 104, 105, 106, 107, 1, 109, 110, 31, + 116, 75, 76, 115, 116, 70, 163, 134, 135, 8, + 122, 1, 124, 125, 126, 160, 159, 8, 161, 164, + 116, 137, 149, 8, 136, 137, 31, 139, 140, 141, + 142, 143, 144, 145, 161, 106, 163, 108, 82, 151, + 152, 8, 138, 155, 156, 157, 158, 75, 76, 77, + 8, 163, 84, 165, 166, 167, 84, 8, 101, 102, + 106, 107, 90, 8, 92, 8, 94, 163, 96, 134, + 135, 161, 116, 106, 107, 111, 112, 167, 106, 84, + 1, 8, 8, 8, 149, 31, 14, 37, 38, 117, + 118, 14, 82, 137, 122, 31, 161, 14, 163, 127, + 128, 129, 130, 131, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 14, 163, + 70, 14, 14, 167, 31, 16, 16, 159, 16, 161, + 16, 159, 82, 161, 162, 16, 86, 16, 74, 70, + 1, 70, 16, 16, 80, 16, 31, 59, 60, 31, + 37, 87, 88, 89, 159, 91, 161, 93, 70, 95, + 35, 31, 98, 84, 31, 31, 116, 103, 104, 105, + 31, 161, 122, 109, 110, 37, 38, 167, 31, 115, + 116, 31, 0, 1, 31, 31, 136, 137, 124, 139, + 140, 141, 142, 143, 144, 31, 31, 31, 31, 31, + 31, 151, 152, 134, 135, 134, 135, 37, 38, 31, + 31, 31, 74, 163, 31, 1, 166, 167, 80, 35, + 149, 82, 134, 135, 35, 87, 88, 89, 35, 91, + 161, 93, 161, 95, 35, 35, 98, 149, 159, 35, + 161, 103, 104, 105, 74, 31, 37, 109, 110, 161, + 80, 38, 37, 115, 116, 116, 37, 87, 88, 89, + 57, 91, 124, 93, 70, 95, 84, 128, 98, 77, + 69, 80, 70, 103, 104, 105, 137, 82, 31, 109, + 110, 83, 85, 96, 94, 115, 116, 82, 106, 113, + 108, 85, 154, 97, 124, 113, 89, 158, 84, 117, + 118, 90, 163, 128, 122, 97, 167, 97, 92, 127, + 128, 129, 130, 131, 133, 138, 153, 100, 100, 146, + 132, 74, 70, 137, 1, 153, 114, 80, 134, 135, + 159, 146, 150, 159, 87, 88, 89, -1, 91, 1, + 93, 159, 95, 161, 162, 98, -1, 1, 1, -1, + 103, 104, 105, 74, 132, 161, 109, 110, -1, 80, + 1, -1, 115, 116, -1, -1, 87, 88, 89, 31, + 91, 124, 93, 159, 95, 161, 149, 98, 31, 149, + 149, 102, 103, 104, 105, 74, 134, 135, 109, 110, + 149, 80, 81, 149, 115, 116, 154, 158, 87, 88, + 89, 149, 91, 124, 93, 155, 95, 84, 159, 98, + 159, 163, 159, 161, 103, 104, 105, 159, 159, 159, + 109, 110, 84, 100, 101, 102, 115, 116, 82, 106, + 159, 84, 159, 159, 159, 124, 159, 159, 162, 159, + 117, 118, 159, 84, 159, 122, 159, 161, 160, 160, + 127, 128, 129, 130, 131, 70, 160, 160, 160, 100, + 101, 102, 116, 160, 162, 106, 161, 82, 161, 161, + 161, 86, 162, 161, 128, 161, 117, 118, 161, 161, + 161, 122, 159, 137, 161, 162, 127, 128, 129, 130, + 131, 161, 161, 161, 165, 162, 162, 159, 70, 161, + 163, 116, 162, 162, 158, 162, 159, 122, 161, 163, + 162, 162, 162, 167, 162, 162, 162, 162, 159, 162, + 161, 162, 137, 162, 139, 140, 141, 142, 143, 144, + 162, 162, 162, 162, 162, 162, 151, 152, 162, 162, + 74, 162, 162, 165, 163, 163, 80, 163, 163, 163, + 163, 166, 167, 87, 88, 89, 163, 91, 163, 93, + 163, 95, 134, 135, 98, 163, 163, 163, 163, 103, + 104, 105, 163, 163, 163, 109, 110, 149, 163, 163, + 163, 115, 116, 163, 163, 163, 163, 163, 163, 161, + 124, 164, 163, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, -1, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + -1, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, -1, -1, + 166, -1, 167 + ); + + protected $actionBase = array( + 0, -2, 154, 542, 752, 893, 929, 580, 53, 394, + 855, 307, 307, 67, 307, 307, 307, 565, 908, 908, + 917, 908, 538, 784, 649, 649, 649, 708, 708, 708, + 708, 740, 740, 849, 849, 881, 817, 634, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 12, 323, 389, 678, 1044, 1050, 1046, 1051, + 1042, 1041, 1045, 1047, 1052, 942, 943, 753, 946, 947, + 949, 950, 1048, 873, 1043, 1049, 291, 291, 291, 291, + 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, + 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, + 291, 291, 346, 491, 50, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 54, 54, 54, 620, 620, + 359, 190, 184, 955, 955, 955, 955, 955, 955, 955, + 955, 955, 955, 658, 47, 144, 144, 7, 7, 7, + 7, 7, 371, -25, -25, -25, -25, 709, 347, 916, + 474, 526, 375, 280, 317, 245, 340, 340, 187, 187, + 396, 396, -87, -87, 396, 396, 396, 747, 747, 747, + 747, 443, 505, -94, 308, 454, 480, 480, 480, 480, + 454, 454, 454, 454, 755, 1054, 454, 454, 454, 641, + 822, 822, 998, 442, 442, 442, 822, 499, 776, 88, + 499, 88, 37, 92, 756, 85, -54, 425, 756, 639, + 764, 189, 143, 820, 524, 820, 1040, 385, 767, 413, + 735, 688, 857, 902, 1053, 787, 940, 788, 941, 228, + 98, 685, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, + 1039, 1039, 1039, 1055, 415, 1040, 286, 1055, 1055, 1055, + 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, + 534, 286, 483, 496, 286, 774, 415, 12, 800, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 736, + -16, 12, 323, 204, 204, 427, 168, 204, 204, 204, + 204, 12, 12, 12, 524, 773, 733, 537, 742, 377, + 773, 773, 773, 115, 124, 207, 342, 695, 754, 446, + 761, 761, 775, 957, 957, 761, 765, 761, 775, 973, + 761, 761, 957, 957, 809, 232, 625, 579, 612, 627, + 957, 475, 761, 761, 761, 761, 792, 643, 761, 433, + 281, 761, 761, 792, 758, 739, 46, 751, 957, 957, + 957, 792, 603, 751, 751, 751, 819, 821, 746, 738, + 571, 507, 645, 198, 783, 738, 738, 761, 619, 746, + 738, 746, 738, 812, 738, 738, 738, 746, 738, 765, + 585, 738, 691, 644, 188, 738, 6, 974, 975, 624, + 979, 967, 980, 1009, 981, 985, 878, 956, 992, 972, + 986, 965, 963, 750, 679, 680, 801, 797, 954, 771, + 771, 771, 951, 771, 771, 771, 771, 771, 771, 771, + 771, 679, 858, 814, 745, 777, 995, 682, 684, 743, + 872, 899, 948, 994, 1030, 987, 741, 689, 1016, 999, + 846, 875, 1000, 1001, 1017, 1031, 1032, 880, 772, 903, + 904, 859, 1003, 879, 771, 974, 985, 663, 972, 986, + 965, 963, 734, 724, 720, 723, 717, 704, 700, 703, + 737, 1033, 907, 818, 866, 1002, 952, 679, 867, 1012, + 856, 1018, 1019, 877, 778, 768, 868, 910, 1004, 1005, + 1006, 882, 1034, 884, 744, 1013, 997, 1020, 780, 911, + 1021, 1022, 1023, 1024, 887, 913, 888, 889, 823, 781, + 1010, 757, 918, 528, 769, 770, 789, 1008, 642, 993, + 900, 919, 920, 1025, 1026, 1027, 922, 923, 990, 828, + 1014, 760, 1015, 1011, 829, 830, 647, 785, 1035, 759, + 763, 779, 653, 674, 924, 925, 927, 991, 748, 762, + 841, 843, 1037, 683, 1038, 931, 677, 844, 696, 938, + 1029, 697, 699, 786, 901, 811, 782, 766, 1007, 749, + 845, 939, 847, 848, 850, 1028, 853, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 458, 458, 458, + 458, 458, 458, 307, 307, 307, 307, 0, 0, 307, + 0, 0, 0, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 291, 291, + 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, + 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, + 291, 291, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 291, 291, + 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, + 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, + 291, 291, 291, 291, 219, 219, 291, 291, 291, 219, + 219, 219, 219, 219, 219, 219, 219, 219, 219, 0, + 291, 291, 291, 291, 291, 291, 291, 291, 809, 442, + 442, 442, 442, 219, 219, 219, 219, 219, -88, -88, + 219, 809, 219, 219, 442, 442, 219, 219, 219, 219, + 219, 219, 219, 219, 219, 219, 219, 0, 0, 286, + 88, 219, 765, 765, 765, 765, 219, 219, 219, 219, + 88, 88, 219, 219, 219, 0, 0, 0, 0, 0, + 0, 0, 0, 286, 88, 0, 286, 0, 765, 765, + 219, 0, 809, 314, 219, 0, 0, 0, 0, 286, + 765, 286, 415, 761, 88, 761, 415, 415, 204, 12, + 314, 527, 527, 527, 527, 0, 0, 524, 809, 809, + 809, 809, 809, 809, 809, 809, 809, 809, 809, 765, + 0, 809, 0, 765, 765, 765, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 765, 0, 0, 957, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 973, 0, 0, 0, 0, + 0, 0, 765, 0, 0, 0, 0, 0, 0, 0, + 0, 771, 778, 0, 778, 0, 771, 771, 771, 0, + 0, 0, 0, 785, 683 + ); + + protected $actionDefault = array( + 3,32767, 103,32767,32767,32767,32767,32767,32767,32767, + 32767,32767, 101,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767, 593, 593, 593, + 593,32767,32767, 253, 103,32767,32767, 467, 385, 385, + 385,32767,32767, 537, 537, 537, 537, 537, 537,32767, + 32767,32767,32767,32767,32767, 467,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767, 101,32767, + 32767,32767, 37, 7, 8, 10, 11, 50, 17, 323, + 32767,32767,32767,32767, 103,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767, 586,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767, 471, 450, 451, 453, + 454, 384, 538, 592, 326, 589, 383, 146, 338, 328, + 241, 329, 257, 472, 258, 473, 476, 477, 214, 286, + 380, 150, 414, 468, 416, 466, 470, 415, 390, 395, + 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, + 406, 407, 388, 389, 469, 447, 446, 445,32767,32767, + 412, 413, 417,32767,32767,32767,32767,32767,32767,32767, + 32767, 103,32767, 387, 420, 418, 419, 436, 437, 434, + 435, 438,32767, 439, 440, 441, 442,32767, 315,32767, + 32767,32767, 364, 362, 315, 112,32767,32767, 427, 428, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767, 531, 444,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767, 103,32767, 101, 533, + 409, 411, 501, 422, 423, 421, 391,32767, 508,32767, + 103, 510,32767,32767,32767,32767,32767,32767,32767, 532, + 32767, 539, 539,32767, 494, 101, 194,32767,32767,32767, + 194, 194,32767,32767,32767,32767,32767,32767,32767,32767, + 600, 494, 111, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111,32767, 194, 111,32767,32767,32767, 101, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 189,32767, 267, 269, 103, 554, 194,32767, 513,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 506, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767, 494, 432, 139,32767, 139, 539, + 424, 425, 426, 496, 539, 539, 539, 311, 288,32767, + 32767,32767,32767, 511, 511, 101, 101, 101, 101, 506, + 32767,32767,32767,32767, 112, 100, 100, 100, 100, 100, + 104, 102,32767,32767,32767,32767, 222, 100,32767, 102, + 102,32767,32767, 222, 224, 211, 102, 226,32767, 558, + 559, 222, 102, 226, 226, 226, 246, 246, 483, 317, + 102, 100, 102, 102, 196, 317, 317,32767, 102, 483, + 317, 483, 317, 198, 317, 317, 317, 483, 317,32767, + 102, 317, 213, 100, 100, 317,32767,32767,32767, 496, + 32767,32767,32767,32767,32767,32767,32767, 221,32767,32767, + 32767,32767,32767,32767,32767, 526,32767, 543, 556, 430, + 431, 433, 541, 455, 456, 457, 458, 459, 460, 461, + 463, 588,32767, 500,32767,32767,32767,32767, 337, 598, + 32767, 598,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767, 599,32767, 539, + 32767,32767,32767,32767, 429, 9, 76, 489, 43, 44, + 52, 58, 517, 518, 519, 520, 514, 515, 521, 516, + 32767,32767, 522, 564,32767,32767, 540, 591,32767,32767, + 32767,32767,32767,32767, 139,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767, 526,32767, 137,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 539,32767,32767,32767,32767, 313, 310,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767, 539,32767,32767,32767,32767,32767, 290, + 32767, 307,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767, 285,32767, + 32767, 379,32767,32767,32767,32767, 358,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767, 152, 152, 3, + 3, 340, 152, 152, 152, 340, 340, 152, 340, 340, + 340, 152, 152, 152, 152, 152, 152, 279, 184, 261, + 264, 246, 246, 152, 350, 152 + ); + + protected $goto = array( + 194, 194, 685, 425, 653, 346, 614, 650, 419, 310, + 311, 331, 569, 316, 424, 332, 426, 630, 1200, 930, + 693, 1051, 1201, 1204, 931, 1205, 165, 165, 165, 165, + 218, 195, 191, 191, 175, 177, 213, 191, 191, 191, + 191, 191, 192, 192, 192, 192, 192, 192, 186, 187, + 188, 189, 190, 215, 213, 216, 529, 530, 415, 531, + 533, 534, 535, 536, 537, 538, 539, 540, 1120, 166, + 167, 168, 193, 169, 170, 171, 164, 172, 173, 174, + 176, 212, 214, 217, 235, 240, 241, 242, 254, 255, + 256, 257, 258, 259, 260, 261, 263, 264, 265, 266, + 278, 279, 313, 314, 315, 420, 421, 422, 574, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 178, 234, 179, 196, 197, 198, + 236, 186, 187, 188, 189, 190, 215, 1120, 199, 180, + 181, 182, 200, 196, 183, 237, 201, 199, 163, 202, + 203, 184, 204, 205, 206, 185, 207, 208, 209, 210, + 211, 275, 275, 275, 275, 843, 593, 646, 647, 560, + 664, 665, 666, 720, 629, 631, 840, 418, 651, 604, + 841, 350, 675, 679, 996, 683, 691, 992, 616, 616, + 817, 350, 350, 1252, 1252, 1252, 1252, 1252, 1252, 1252, + 1252, 1252, 1252, 1092, 1093, 350, 350, 874, 350, 848, + 1337, 896, 891, 892, 905, 849, 893, 846, 894, 895, + 847, 548, 900, 899, 901, 350, 391, 394, 554, 594, + 598, 1270, 1270, 1072, 1068, 1069, 1270, 1270, 1270, 1270, + 1270, 1270, 1270, 1270, 1270, 1270, 1268, 1268, 815, 347, + 348, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, + 1268, 1221, 1020, 1221, 1020, 1221, 836, 5, 1020, 6, + 1020, 1020, 1281, 961, 1020, 1020, 1020, 1020, 1020, 1020, + 1020, 1020, 1020, 1020, 1020, 349, 349, 349, 349, 1221, + 460, 460, 566, 678, 1221, 1221, 1221, 1221, 344, 460, + 1221, 1221, 1221, 1302, 1302, 1302, 1302, 602, 617, 620, + 621, 622, 623, 643, 644, 645, 695, 836, 912, 553, + 546, 1310, 913, 548, 532, 532, 821, 856, 982, 532, + 532, 532, 532, 532, 532, 532, 532, 532, 532, 543, + 473, 543, 868, 543, 928, 855, 928, 389, 475, 337, + 546, 553, 562, 563, 339, 572, 595, 609, 610, 1320, + 1320, 249, 249, 1026, 1025, 15, 821, 450, 821, 494, + 565, 495, 955, 955, 955, 955, 1320, 501, 450, 949, + 956, 839, 652, 1321, 1321, 1169, 1214, 246, 246, 246, + 246, 248, 250, 1323, 985, 959, 959, 957, 959, 719, + 1321, 545, 994, 989, 470, 1295, 1296, 953, 405, 692, + 917, 1108, 432, 541, 541, 541, 541, 612, 597, 452, + 444, 1029, 1030, 1001, 658, 444, 1292, 444, 1292, 674, + 1292, 860, 833, 656, 980, 836, 861, 547, 557, 854, + 321, 305, 547, 333, 557, 1297, 1298, 392, 456, 570, + 607, 1211, 944, 398, 858, 1304, 1304, 1304, 1304, 463, + 573, 464, 465, 608, 1004, 866, 403, 404, 1328, 1329, + 1057, 662, 1212, 663, 471, 407, 408, 409, 723, 676, + 870, 1288, 410, 624, 626, 627, 342, 427, 1216, 869, + 857, 1056, 1060, 427, 864, 1061, 1103, 966, 0, 0, + 964, 1027, 1027, 0, 0, 0, 657, 1038, 1034, 1035, + 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, + 444, 0, 1059, 444, 954, 0, 1290, 1290, 1059, 592, + 1085, 0, 696, 682, 682, 0, 502, 688, 1083, 0, + 0, 0, 1217, 1218, 272, 428, 1101, 873, 0, 544, + 831, 544, 0, 0, 0, 673, 938, 0, 0, 1015, + 1031, 1032, 0, 0, 0, 0, 0, 0, 1219, 1278, + 1279, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 252, 252, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 999, 999 + ); + + protected $gotoCheck = array( + 42, 42, 72, 65, 65, 96, 55, 55, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 78, 78, + 9, 126, 78, 78, 78, 78, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 23, 23, 23, 23, 15, 129, 85, 85, 48, + 85, 85, 85, 48, 48, 48, 26, 13, 48, 13, + 27, 14, 48, 48, 48, 48, 48, 48, 107, 107, + 7, 14, 14, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 143, 143, 14, 14, 45, 14, 15, + 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 14, 64, 15, 64, 14, 58, 58, 58, 58, + 58, 168, 168, 15, 15, 15, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 169, 169, 6, 96, + 96, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 72, 72, 72, 72, 72, 22, 46, 72, 46, + 72, 72, 14, 49, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 24, 24, 24, 24, 72, + 148, 148, 170, 14, 72, 72, 72, 72, 177, 148, + 72, 72, 72, 9, 9, 9, 9, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 22, 72, 75, + 75, 179, 72, 14, 171, 171, 12, 35, 102, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 19, + 83, 19, 35, 19, 9, 35, 9, 61, 83, 75, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 180, + 180, 5, 5, 117, 117, 75, 12, 19, 12, 154, + 103, 154, 19, 19, 19, 19, 180, 154, 19, 19, + 19, 25, 63, 181, 181, 150, 14, 5, 5, 5, + 5, 5, 5, 180, 25, 25, 25, 25, 25, 25, + 181, 25, 25, 25, 174, 174, 174, 92, 92, 92, + 17, 17, 112, 106, 106, 106, 106, 17, 106, 82, + 23, 118, 118, 17, 119, 23, 129, 23, 129, 115, + 129, 17, 18, 17, 17, 22, 39, 9, 9, 17, + 167, 167, 9, 29, 9, 176, 176, 9, 9, 2, + 2, 17, 91, 28, 37, 129, 129, 129, 129, 9, + 9, 9, 9, 79, 109, 9, 81, 81, 9, 9, + 128, 81, 159, 81, 156, 81, 81, 81, 98, 81, + 41, 129, 81, 84, 84, 84, 81, 116, 20, 16, + 16, 16, 16, 116, 9, 131, 146, 95, -1, -1, + 16, 116, 116, -1, -1, -1, 116, 116, 116, 116, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, -1, 129, 23, 16, -1, 129, 129, 129, 8, + 8, -1, 8, 8, 8, -1, 8, 8, 8, -1, + -1, -1, 20, 20, 24, 88, 16, 16, -1, 24, + 20, 24, -1, -1, -1, 88, 88, -1, -1, 88, + 88, 88, -1, -1, -1, -1, -1, -1, 20, 20, + 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 5, 5, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 106, 106 + ); + + protected $gotoBase = array( + 0, 0, -250, 0, 0, 360, 235, 181, 522, 7, + 0, 0, 33, -156, -113, -178, 43, -49, 126, 72, + 100, 0, -9, 158, 282, 377, 172, 176, 120, 150, + 0, 0, 0, 0, 0, -39, 0, 119, 0, 116, + 0, 45, -1, 0, 0, 195, -456, 0, -529, 250, + 0, 0, 0, 0, 0, -33, 0, 0, 182, 0, + 0, 306, 0, 143, 203, -235, 0, 0, 0, 0, + 0, 0, -6, 0, 0, -21, 0, 0, -385, 124, + -46, -19, 144, -123, 10, -538, 0, 0, 275, 0, + 0, 127, 106, 0, 0, 60, -472, 0, 76, 0, + 0, 0, 294, 328, 0, 0, 386, -50, 0, 99, + 0, 0, 138, 0, 0, 149, 219, 87, 139, 137, + 0, 0, 0, 0, 0, 0, 19, 0, 101, 159, + 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -69, 0, 0, 58, 0, 257, 0, + 114, 0, 0, 0, -120, 0, 40, 0, 0, 108, + 0, 0, 0, 0, 0, 0, 0, 122, -7, 8, + 264, 86, 0, 0, 107, 0, 78, 269, 0, 291, + 55, 79, 0, 0 + ); + + protected $gotoDefault = array( + -32768, 506, 727, 4, 728, 921, 804, 813, 590, 523, + 694, 343, 618, 416, 1286, 898, 1107, 571, 832, 1230, + 1238, 451, 835, 326, 717, 880, 881, 882, 395, 381, + 387, 393, 641, 619, 488, 867, 447, 859, 480, 862, + 446, 871, 162, 413, 504, 875, 3, 877, 550, 908, + 382, 885, 383, 669, 887, 556, 889, 890, 390, 396, + 397, 1112, 564, 615, 902, 253, 558, 903, 380, 904, + 911, 385, 388, 680, 459, 499, 493, 406, 1087, 559, + 601, 638, 441, 467, 613, 625, 611, 474, 1023, 411, + 325, 943, 951, 481, 457, 965, 345, 973, 725, 1119, + 632, 483, 981, 633, 988, 991, 524, 525, 472, 1003, + 268, 1006, 484, 1044, 659, 1017, 1018, 660, 634, 1040, + 635, 661, 636, 1042, 466, 591, 1050, 448, 1058, 1274, + 449, 1062, 262, 1065, 274, 412, 429, 1070, 1071, 8, + 1077, 686, 687, 10, 273, 503, 1102, 681, 445, 1118, + 433, 1188, 1190, 552, 485, 1208, 1207, 672, 500, 1213, + 442, 1277, 443, 526, 468, 312, 527, 304, 329, 309, + 542, 291, 330, 528, 469, 1283, 1291, 327, 30, 1311, + 1322, 338, 568, 606 + ); + + protected $ruleToNonTerminal = array( + 0, 1, 3, 3, 2, 5, 5, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 8, 8, 9, 10, + 11, 11, 11, 12, 12, 13, 13, 14, 15, 15, + 16, 16, 17, 17, 18, 18, 21, 21, 22, 23, + 23, 24, 24, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 29, 29, 30, 30, 32, 34, + 34, 28, 36, 36, 33, 38, 38, 35, 35, 37, + 37, 39, 39, 31, 40, 40, 41, 43, 44, 44, + 45, 46, 46, 48, 47, 47, 47, 47, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 25, 25, 68, 68, 71, 71, 70, 69, + 69, 62, 74, 74, 75, 75, 76, 76, 77, 77, + 78, 78, 79, 79, 26, 26, 27, 27, 27, 27, + 27, 87, 87, 89, 89, 82, 82, 90, 90, 91, + 91, 91, 83, 83, 86, 86, 84, 84, 92, 93, + 93, 56, 56, 64, 64, 67, 67, 67, 66, 94, + 94, 95, 57, 57, 57, 57, 96, 96, 97, 97, + 98, 98, 99, 100, 100, 101, 101, 102, 102, 54, + 54, 50, 50, 104, 52, 52, 105, 51, 51, 53, + 53, 63, 63, 63, 63, 80, 80, 108, 108, 110, + 110, 111, 111, 111, 111, 109, 109, 109, 113, 113, + 113, 113, 88, 88, 116, 116, 116, 117, 117, 114, + 114, 118, 118, 120, 120, 121, 121, 115, 122, 122, + 119, 123, 123, 123, 123, 112, 112, 81, 81, 81, + 20, 20, 20, 125, 124, 124, 126, 126, 126, 126, + 59, 127, 127, 128, 60, 130, 130, 131, 131, 132, + 132, 85, 133, 133, 133, 133, 133, 133, 138, 138, + 139, 139, 140, 140, 140, 140, 140, 141, 142, 142, + 137, 137, 134, 134, 136, 136, 144, 144, 143, 143, + 143, 143, 143, 143, 143, 135, 145, 145, 147, 146, + 146, 61, 103, 148, 148, 55, 55, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 155, 149, 149, 154, 154, 157, 158, 158, 159, 160, + 161, 161, 161, 161, 19, 19, 72, 72, 72, 72, + 150, 150, 150, 150, 163, 163, 151, 151, 153, 153, + 153, 156, 156, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 169, 169, 107, 171, 171, 171, 171, 152, + 152, 152, 152, 152, 152, 152, 152, 58, 58, 166, + 166, 166, 166, 172, 172, 162, 162, 162, 173, 173, + 173, 173, 173, 173, 73, 73, 65, 65, 65, 65, + 129, 129, 129, 129, 176, 175, 165, 165, 165, 165, + 165, 165, 165, 164, 164, 164, 174, 174, 174, 174, + 106, 170, 178, 178, 177, 177, 179, 179, 179, 179, + 179, 179, 179, 179, 167, 167, 167, 167, 181, 182, + 180, 180, 180, 180, 180, 180, 180, 180, 183, 183, + 183, 183 + ); + + protected $ruleToLength = array( + 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 0, 1, 1, 2, 1, 3, 4, 1, + 2, 0, 1, 1, 1, 1, 1, 3, 5, 4, + 3, 4, 2, 3, 1, 1, 7, 6, 2, 3, + 1, 2, 3, 1, 2, 3, 1, 1, 3, 1, + 3, 1, 2, 2, 3, 1, 3, 2, 3, 1, + 3, 2, 0, 1, 1, 1, 1, 1, 3, 7, + 10, 5, 7, 9, 5, 3, 3, 3, 3, 3, + 3, 1, 2, 5, 7, 9, 6, 5, 6, 3, + 2, 1, 1, 1, 0, 2, 1, 3, 8, 0, + 4, 2, 1, 3, 0, 1, 0, 1, 0, 1, + 3, 1, 1, 1, 8, 9, 7, 8, 7, 6, + 8, 0, 2, 0, 2, 1, 2, 1, 2, 1, + 1, 1, 0, 2, 0, 2, 0, 2, 2, 1, + 3, 1, 4, 1, 4, 1, 1, 4, 2, 1, + 3, 3, 3, 4, 4, 5, 0, 2, 4, 3, + 1, 1, 7, 0, 2, 1, 3, 3, 4, 1, + 4, 0, 2, 5, 0, 2, 6, 0, 2, 0, + 3, 1, 2, 1, 1, 2, 0, 1, 3, 0, + 2, 1, 1, 1, 1, 6, 8, 6, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, + 3, 1, 3, 3, 3, 3, 3, 1, 3, 3, + 1, 1, 2, 1, 1, 0, 1, 0, 2, 2, + 2, 4, 3, 1, 1, 3, 1, 2, 2, 3, + 2, 3, 1, 1, 2, 3, 1, 1, 3, 2, + 0, 1, 5, 5, 10, 3, 5, 1, 1, 3, + 0, 2, 4, 5, 4, 4, 4, 3, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 3, 1, 1, + 3, 2, 2, 3, 1, 0, 1, 1, 3, 3, + 3, 4, 1, 1, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 5, 4, 3, 4, 4, + 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 1, 3, 2, 1, 2, 4, + 2, 2, 8, 9, 8, 9, 9, 10, 9, 10, + 8, 3, 2, 0, 4, 2, 1, 3, 2, 1, + 2, 2, 2, 4, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 1, 1, 1, 0, 3, 0, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 3, 3, 4, 1, 1, 3, 1, + 1, 1, 1, 1, 3, 2, 3, 0, 1, 1, + 3, 1, 1, 1, 1, 1, 3, 1, 1, 4, + 4, 1, 4, 4, 0, 1, 1, 1, 3, 3, + 1, 4, 2, 2, 1, 3, 1, 4, 4, 3, + 3, 3, 3, 1, 3, 1, 1, 3, 1, 1, + 4, 1, 1, 1, 3, 1, 1, 2, 1, 3, + 4, 3, 2, 0, 2, 2, 1, 2, 1, 1, + 1, 4, 3, 3, 3, 3, 6, 3, 1, 1, + 2, 1 + ); + + protected function initReduceCallbacks() { + $this->reduceCallbacks = [ + 0 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 1 => function ($stackPos) { + $this->semValue = $this->handleNamespaces($this->semStack[$stackPos-(1-1)]); + }, + 2 => function ($stackPos) { + if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; + }, + 3 => function ($stackPos) { + $this->semValue = array(); + }, + 4 => function ($stackPos) { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 5 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 6 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 7 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 8 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 9 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 10 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 11 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 12 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 13 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 14 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 15 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 16 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 17 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 18 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 19 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 20 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 21 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 22 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 23 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 24 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 25 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 26 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 27 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 28 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 29 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 30 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 31 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 32 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 33 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 34 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 35 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 36 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 37 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 38 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 39 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 40 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 41 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 42 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 43 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 44 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 45 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 46 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 47 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 48 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 49 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 50 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 51 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 52 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 53 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 54 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 55 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 56 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 57 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 58 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 59 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 60 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 61 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 62 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 63 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 64 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 65 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 66 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 67 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 68 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 69 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 70 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 71 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 72 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 73 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 74 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 75 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 76 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 77 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 78 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 79 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 80 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 81 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 82 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 83 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 84 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 85 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 86 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 87 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 88 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 89 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 90 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 91 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 92 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 93 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 94 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 95 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 96 => function ($stackPos) { + $this->semValue = new Name(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 97 => function ($stackPos) { + $this->semValue = new Expr\Variable(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 98 => function ($stackPos) { + /* nothing */ + }, + 99 => function ($stackPos) { + /* nothing */ + }, + 100 => function ($stackPos) { + /* nothing */ + }, + 101 => function ($stackPos) { + $this->emitError(new Error('A trailing comma is not allowed here', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); + }, + 102 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 103 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 104 => function ($stackPos) { + $this->semValue = new Node\Attribute($this->semStack[$stackPos-(1-1)], [], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 105 => function ($stackPos) { + $this->semValue = new Node\Attribute($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 106 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 107 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 108 => function ($stackPos) { + $this->semValue = new Node\AttributeGroup($this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 109 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 110 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 111 => function ($stackPos) { + $this->semValue = []; + }, + 112 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 113 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 114 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 115 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 116 => function ($stackPos) { + $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 117 => function ($stackPos) { + $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(3-2)], null, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); + $this->checkNamespace($this->semValue); + }, + 118 => function ($stackPos) { + $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($this->semValue); + }, + 119 => function ($stackPos) { + $this->semValue = new Stmt\Namespace_(null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($this->semValue); + }, + 120 => function ($stackPos) { + $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 121 => function ($stackPos) { + $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 122 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 123 => function ($stackPos) { + $this->semValue = new Stmt\Const_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 124 => function ($stackPos) { + $this->semValue = Stmt\Use_::TYPE_FUNCTION; + }, + 125 => function ($stackPos) { + $this->semValue = Stmt\Use_::TYPE_CONSTANT; + }, + 126 => function ($stackPos) { + $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-6)], $this->semStack[$stackPos-(7-2)], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + }, + 127 => function ($stackPos) { + $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 128 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 129 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 130 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 131 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 132 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 133 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 134 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 135 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 136 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 137 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); + }, + 138 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); + }, + 139 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); + }, + 140 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); + }, + 141 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; $this->semValue->type = Stmt\Use_::TYPE_NORMAL; + }, + 142 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; $this->semValue->type = $this->semStack[$stackPos-(2-1)]; + }, + 143 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 144 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 145 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 146 => function ($stackPos) { + $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 147 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 148 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 149 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 150 => function ($stackPos) { + $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 151 => function ($stackPos) { + if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; + }, + 152 => function ($stackPos) { + $this->semValue = array(); + }, + 153 => function ($stackPos) { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 154 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 155 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 156 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 157 => function ($stackPos) { + throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 158 => function ($stackPos) { + + if ($this->semStack[$stackPos-(3-2)]) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; $attrs = $this->startAttributeStack[$stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); }; + } else { + $startAttributes = $this->startAttributeStack[$stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; + if (null === $this->semValue) { $this->semValue = array(); } + } + + }, + 159 => function ($stackPos) { + $this->semValue = new Stmt\If_($this->semStack[$stackPos-(7-3)], ['stmts' => is_array($this->semStack[$stackPos-(7-5)]) ? $this->semStack[$stackPos-(7-5)] : array($this->semStack[$stackPos-(7-5)]), 'elseifs' => $this->semStack[$stackPos-(7-6)], 'else' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + }, + 160 => function ($stackPos) { + $this->semValue = new Stmt\If_($this->semStack[$stackPos-(10-3)], ['stmts' => $this->semStack[$stackPos-(10-6)], 'elseifs' => $this->semStack[$stackPos-(10-7)], 'else' => $this->semStack[$stackPos-(10-8)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); + }, + 161 => function ($stackPos) { + $this->semValue = new Stmt\While_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 162 => function ($stackPos) { + $this->semValue = new Stmt\Do_($this->semStack[$stackPos-(7-5)], is_array($this->semStack[$stackPos-(7-2)]) ? $this->semStack[$stackPos-(7-2)] : array($this->semStack[$stackPos-(7-2)]), $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + }, + 163 => function ($stackPos) { + $this->semValue = new Stmt\For_(['init' => $this->semStack[$stackPos-(9-3)], 'cond' => $this->semStack[$stackPos-(9-5)], 'loop' => $this->semStack[$stackPos-(9-7)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 164 => function ($stackPos) { + $this->semValue = new Stmt\Switch_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 165 => function ($stackPos) { + $this->semValue = new Stmt\Break_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 166 => function ($stackPos) { + $this->semValue = new Stmt\Continue_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 167 => function ($stackPos) { + $this->semValue = new Stmt\Return_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 168 => function ($stackPos) { + $this->semValue = new Stmt\Global_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 169 => function ($stackPos) { + $this->semValue = new Stmt\Static_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 170 => function ($stackPos) { + $this->semValue = new Stmt\Echo_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 171 => function ($stackPos) { + $this->semValue = new Stmt\InlineHTML($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 172 => function ($stackPos) { + + $e = $this->semStack[$stackPos-(2-1)]; + if ($e instanceof Expr\Throw_) { + // For backwards-compatibility reasons, convert throw in statement position into + // Stmt\Throw_ rather than Stmt\Expression(Expr\Throw_). + $this->semValue = new Stmt\Throw_($e->expr, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + } else { + $this->semValue = new Stmt\Expression($e, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + } + + }, + 173 => function ($stackPos) { + $this->semValue = new Stmt\Unset_($this->semStack[$stackPos-(5-3)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 174 => function ($stackPos) { + $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$stackPos-(7-5)][1], 'stmts' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + }, + 175 => function ($stackPos) { + $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(9-3)], $this->semStack[$stackPos-(9-7)][0], ['keyVar' => $this->semStack[$stackPos-(9-5)], 'byRef' => $this->semStack[$stackPos-(9-7)][1], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 176 => function ($stackPos) { + $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(6-3)], new Expr\Error($this->startAttributeStack[$stackPos-(6-4)] + $this->endAttributeStack[$stackPos-(6-4)]), ['stmts' => $this->semStack[$stackPos-(6-6)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 177 => function ($stackPos) { + $this->semValue = new Stmt\Declare_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 178 => function ($stackPos) { + $this->semValue = new Stmt\TryCatch($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-5)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue); + }, + 179 => function ($stackPos) { + $this->semValue = new Stmt\Goto_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 180 => function ($stackPos) { + $this->semValue = new Stmt\Label($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 181 => function ($stackPos) { + $this->semValue = array(); /* means: no statement */ + }, + 182 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 183 => function ($stackPos) { + $startAttributes = $this->startAttributeStack[$stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; + if ($this->semValue === null) $this->semValue = array(); /* means: no statement */ + }, + 184 => function ($stackPos) { + $this->semValue = array(); + }, + 185 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 186 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 187 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 188 => function ($stackPos) { + $this->semValue = new Stmt\Catch_($this->semStack[$stackPos-(8-3)], $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-7)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 189 => function ($stackPos) { + $this->semValue = null; + }, + 190 => function ($stackPos) { + $this->semValue = new Stmt\Finally_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 191 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 192 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 193 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 194 => function ($stackPos) { + $this->semValue = false; + }, + 195 => function ($stackPos) { + $this->semValue = true; + }, + 196 => function ($stackPos) { + $this->semValue = false; + }, + 197 => function ($stackPos) { + $this->semValue = true; + }, + 198 => function ($stackPos) { + $this->semValue = false; + }, + 199 => function ($stackPos) { + $this->semValue = true; + }, + 200 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 201 => function ($stackPos) { + $this->semValue = []; + }, + 202 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 203 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 204 => function ($stackPos) { + $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(8-3)], ['byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-5)], 'returnType' => $this->semStack[$stackPos-(8-7)], 'stmts' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 205 => function ($stackPos) { + $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(9-4)], ['byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-6)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 206 => function ($stackPos) { + $this->semValue = new Stmt\Class_($this->semStack[$stackPos-(7-2)], ['type' => $this->semStack[$stackPos-(7-1)], 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + $this->checkClass($this->semValue, $stackPos-(7-2)); + }, + 207 => function ($stackPos) { + $this->semValue = new Stmt\Class_($this->semStack[$stackPos-(8-3)], ['type' => $this->semStack[$stackPos-(8-2)], 'extends' => $this->semStack[$stackPos-(8-4)], 'implements' => $this->semStack[$stackPos-(8-5)], 'stmts' => $this->semStack[$stackPos-(8-7)], 'attrGroups' => $this->semStack[$stackPos-(8-1)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + $this->checkClass($this->semValue, $stackPos-(8-3)); + }, + 208 => function ($stackPos) { + $this->semValue = new Stmt\Interface_($this->semStack[$stackPos-(7-3)], ['extends' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)], 'attrGroups' => $this->semStack[$stackPos-(7-1)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + $this->checkInterface($this->semValue, $stackPos-(7-3)); + }, + 209 => function ($stackPos) { + $this->semValue = new Stmt\Trait_($this->semStack[$stackPos-(6-3)], ['stmts' => $this->semStack[$stackPos-(6-5)], 'attrGroups' => $this->semStack[$stackPos-(6-1)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 210 => function ($stackPos) { + $this->semValue = new Stmt\Enum_($this->semStack[$stackPos-(8-3)], ['scalarType' => $this->semStack[$stackPos-(8-4)], 'implements' => $this->semStack[$stackPos-(8-5)], 'stmts' => $this->semStack[$stackPos-(8-7)], 'attrGroups' => $this->semStack[$stackPos-(8-1)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + $this->checkEnum($this->semValue, $stackPos-(8-3)); + }, + 211 => function ($stackPos) { + $this->semValue = null; + }, + 212 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 213 => function ($stackPos) { + $this->semValue = null; + }, + 214 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 215 => function ($stackPos) { + $this->semValue = 0; + }, + 216 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 217 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 218 => function ($stackPos) { + $this->checkClassModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; + }, + 219 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; + }, + 220 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_FINAL; + }, + 221 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_READONLY; + }, + 222 => function ($stackPos) { + $this->semValue = null; + }, + 223 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 224 => function ($stackPos) { + $this->semValue = array(); + }, + 225 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 226 => function ($stackPos) { + $this->semValue = array(); + }, + 227 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 228 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 229 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 230 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 231 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 232 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 233 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 234 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 235 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 236 => function ($stackPos) { + $this->semValue = null; + }, + 237 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 238 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 239 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 240 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 241 => function ($stackPos) { + $this->semValue = new Stmt\DeclareDeclare($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 242 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 243 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-3)]; + }, + 244 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 245 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(5-3)]; + }, + 246 => function ($stackPos) { + $this->semValue = array(); + }, + 247 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 248 => function ($stackPos) { + $this->semValue = new Stmt\Case_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 249 => function ($stackPos) { + $this->semValue = new Stmt\Case_(null, $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 250 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 251 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 252 => function ($stackPos) { + $this->semValue = new Expr\Match_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-6)], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + }, + 253 => function ($stackPos) { + $this->semValue = []; + }, + 254 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 255 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 256 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 257 => function ($stackPos) { + $this->semValue = new Node\MatchArm($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 258 => function ($stackPos) { + $this->semValue = new Node\MatchArm(null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 259 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 260 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 261 => function ($stackPos) { + $this->semValue = array(); + }, + 262 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 263 => function ($stackPos) { + $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(5-3)], is_array($this->semStack[$stackPos-(5-5)]) ? $this->semStack[$stackPos-(5-5)] : array($this->semStack[$stackPos-(5-5)]), $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 264 => function ($stackPos) { + $this->semValue = array(); + }, + 265 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 266 => function ($stackPos) { + $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 267 => function ($stackPos) { + $this->semValue = null; + }, + 268 => function ($stackPos) { + $this->semValue = new Stmt\Else_(is_array($this->semStack[$stackPos-(2-2)]) ? $this->semStack[$stackPos-(2-2)] : array($this->semStack[$stackPos-(2-2)]), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 269 => function ($stackPos) { + $this->semValue = null; + }, + 270 => function ($stackPos) { + $this->semValue = new Stmt\Else_($this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 271 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)], false); + }, + 272 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(2-2)], true); + }, + 273 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)], false); + }, + 274 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)], false); + }, + 275 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 276 => function ($stackPos) { + $this->semValue = array(); + }, + 277 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 278 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 279 => function ($stackPos) { + $this->semValue = 0; + }, + 280 => function ($stackPos) { + $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; + }, + 281 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; + }, + 282 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; + }, + 283 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; + }, + 284 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_READONLY; + }, + 285 => function ($stackPos) { + $this->semValue = new Node\Param($this->semStack[$stackPos-(6-6)], null, $this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes, $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-1)]); + $this->checkParam($this->semValue); + }, + 286 => function ($stackPos) { + $this->semValue = new Node\Param($this->semStack[$stackPos-(8-6)], $this->semStack[$stackPos-(8-8)], $this->semStack[$stackPos-(8-3)], $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-5)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes, $this->semStack[$stackPos-(8-2)], $this->semStack[$stackPos-(8-1)]); + $this->checkParam($this->semValue); + }, + 287 => function ($stackPos) { + $this->semValue = new Node\Param(new Expr\Error($this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes), null, $this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes, $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-1)]); + }, + 288 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 289 => function ($stackPos) { + $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 290 => function ($stackPos) { + $this->semValue = new Node\UnionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 291 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 292 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 293 => function ($stackPos) { + $this->semValue = new Node\Name('static', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 294 => function ($stackPos) { + $this->semValue = $this->handleBuiltinTypes($this->semStack[$stackPos-(1-1)]); + }, + 295 => function ($stackPos) { + $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 296 => function ($stackPos) { + $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 297 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 298 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 299 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + }, + 300 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 301 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 302 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 303 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + }, + 304 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 305 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + }, + 306 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 307 => function ($stackPos) { + $this->semValue = new Node\IntersectionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 308 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + }, + 309 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 310 => function ($stackPos) { + $this->semValue = new Node\IntersectionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 311 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 312 => function ($stackPos) { + $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 313 => function ($stackPos) { + $this->semValue = new Node\UnionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 314 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 315 => function ($stackPos) { + $this->semValue = null; + }, + 316 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 317 => function ($stackPos) { + $this->semValue = null; + }, + 318 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 319 => function ($stackPos) { + $this->semValue = null; + }, + 320 => function ($stackPos) { + $this->semValue = array(); + }, + 321 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 322 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-2)]); + }, + 323 => function ($stackPos) { + $this->semValue = new Node\VariadicPlaceholder($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 324 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 325 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 326 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(1-1)], false, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 327 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], true, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 328 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], false, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 329 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(3-3)], false, false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->semStack[$stackPos-(3-1)]); + }, + 330 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 331 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 332 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 333 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 334 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 335 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 336 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 337 => function ($stackPos) { + $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 338 => function ($stackPos) { + $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 339 => function ($stackPos) { + if ($this->semStack[$stackPos-(2-2)] !== null) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; } + }, + 340 => function ($stackPos) { + $this->semValue = array(); + }, + 341 => function ($stackPos) { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 342 => function ($stackPos) { + $this->semValue = new Stmt\Property($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes, $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-1)]); + $this->checkProperty($this->semValue, $stackPos-(5-2)); + }, + 343 => function ($stackPos) { + $this->semValue = new Stmt\ClassConst($this->semStack[$stackPos-(5-4)], $this->semStack[$stackPos-(5-2)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes, $this->semStack[$stackPos-(5-1)]); + $this->checkClassConst($this->semValue, $stackPos-(5-2)); + }, + 344 => function ($stackPos) { + $this->semValue = new Stmt\ClassMethod($this->semStack[$stackPos-(10-5)], ['type' => $this->semStack[$stackPos-(10-2)], 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-7)], 'returnType' => $this->semStack[$stackPos-(10-9)], 'stmts' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); + $this->checkClassMethod($this->semValue, $stackPos-(10-2)); + }, + 345 => function ($stackPos) { + $this->semValue = new Stmt\TraitUse($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 346 => function ($stackPos) { + $this->semValue = new Stmt\EnumCase($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->semStack[$stackPos-(5-1)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 347 => function ($stackPos) { + $this->semValue = null; /* will be skipped */ + }, + 348 => function ($stackPos) { + $this->semValue = array(); + }, + 349 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 350 => function ($stackPos) { + $this->semValue = array(); + }, + 351 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 352 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 353 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(5-1)][0], $this->semStack[$stackPos-(5-1)][1], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 354 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], null, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 355 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 356 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 357 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + }, + 358 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 359 => function ($stackPos) { + $this->semValue = array(null, $this->semStack[$stackPos-(1-1)]); + }, + 360 => function ($stackPos) { + $this->semValue = null; + }, + 361 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 362 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 363 => function ($stackPos) { + $this->semValue = 0; + }, + 364 => function ($stackPos) { + $this->semValue = 0; + }, + 365 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 366 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 367 => function ($stackPos) { + $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; + }, + 368 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; + }, + 369 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; + }, + 370 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; + }, + 371 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_STATIC; + }, + 372 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; + }, + 373 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_FINAL; + }, + 374 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_READONLY; + }, + 375 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 376 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 377 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 378 => function ($stackPos) { + $this->semValue = new Node\VarLikeIdentifier(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 379 => function ($stackPos) { + $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 380 => function ($stackPos) { + $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 381 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 382 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 383 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 384 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 385 => function ($stackPos) { + $this->semValue = array(); + }, + 386 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 387 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 388 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 389 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 390 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 391 => function ($stackPos) { + $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 392 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 393 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 394 => function ($stackPos) { + $this->semValue = new Expr\Clone_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 395 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 396 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 397 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 398 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 399 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 400 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 401 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 402 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 403 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 404 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 405 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 406 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 407 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 408 => function ($stackPos) { + $this->semValue = new Expr\PostInc($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 409 => function ($stackPos) { + $this->semValue = new Expr\PreInc($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 410 => function ($stackPos) { + $this->semValue = new Expr\PostDec($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 411 => function ($stackPos) { + $this->semValue = new Expr\PreDec($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 412 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 413 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 414 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 415 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 416 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 417 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 418 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 419 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 420 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 421 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 422 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 423 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 424 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 425 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 426 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 427 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 428 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 429 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 430 => function ($stackPos) { + $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 431 => function ($stackPos) { + $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 432 => function ($stackPos) { + $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 433 => function ($stackPos) { + $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 434 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 435 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 436 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 437 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 438 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 439 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 440 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 441 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 442 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 443 => function ($stackPos) { + $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 444 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 445 => function ($stackPos) { + $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 446 => function ($stackPos) { + $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 447 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 448 => function ($stackPos) { + $this->semValue = new Expr\Isset_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 449 => function ($stackPos) { + $this->semValue = new Expr\Empty_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 450 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 451 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 452 => function ($stackPos) { + $this->semValue = new Expr\Eval_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 453 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 454 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 455 => function ($stackPos) { + $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 456 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; + $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos-(2-1)]); + $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $attrs); + }, + 457 => function ($stackPos) { + $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 458 => function ($stackPos) { + $this->semValue = new Expr\Cast\Array_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 459 => function ($stackPos) { + $this->semValue = new Expr\Cast\Object_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 460 => function ($stackPos) { + $this->semValue = new Expr\Cast\Bool_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 461 => function ($stackPos) { + $this->semValue = new Expr\Cast\Unset_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 462 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; + $attrs['kind'] = strtolower($this->semStack[$stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; + $this->semValue = new Expr\Exit_($this->semStack[$stackPos-(2-2)], $attrs); + }, + 463 => function ($stackPos) { + $this->semValue = new Expr\ErrorSuppress($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 464 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 465 => function ($stackPos) { + $this->semValue = new Expr\ShellExec($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 466 => function ($stackPos) { + $this->semValue = new Expr\Print_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 467 => function ($stackPos) { + $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 468 => function ($stackPos) { + $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(2-2)], null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 469 => function ($stackPos) { + $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 470 => function ($stackPos) { + $this->semValue = new Expr\YieldFrom($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 471 => function ($stackPos) { + $this->semValue = new Expr\Throw_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 472 => function ($stackPos) { + $this->semValue = new Expr\ArrowFunction(['static' => false, 'byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-4)], 'returnType' => $this->semStack[$stackPos-(8-6)], 'expr' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 473 => function ($stackPos) { + $this->semValue = new Expr\ArrowFunction(['static' => true, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'returnType' => $this->semStack[$stackPos-(9-7)], 'expr' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 474 => function ($stackPos) { + $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-4)], 'uses' => $this->semStack[$stackPos-(8-6)], 'returnType' => $this->semStack[$stackPos-(8-7)], 'stmts' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 475 => function ($stackPos) { + $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'uses' => $this->semStack[$stackPos-(9-7)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 476 => function ($stackPos) { + $this->semValue = new Expr\ArrowFunction(['static' => false, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'returnType' => $this->semStack[$stackPos-(9-7)], 'expr' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 477 => function ($stackPos) { + $this->semValue = new Expr\ArrowFunction(['static' => true, 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-6)], 'returnType' => $this->semStack[$stackPos-(10-8)], 'expr' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); + }, + 478 => function ($stackPos) { + $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'uses' => $this->semStack[$stackPos-(9-7)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 479 => function ($stackPos) { + $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-6)], 'uses' => $this->semStack[$stackPos-(10-8)], 'returnType' => $this->semStack[$stackPos-(10-9)], 'stmts' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); + }, + 480 => function ($stackPos) { + $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$stackPos-(8-4)], 'implements' => $this->semStack[$stackPos-(8-5)], 'stmts' => $this->semStack[$stackPos-(8-7)], 'attrGroups' => $this->semStack[$stackPos-(8-1)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes), $this->semStack[$stackPos-(8-3)]); + $this->checkClass($this->semValue[0], -1); + }, + 481 => function ($stackPos) { + $this->semValue = new Expr\New_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 482 => function ($stackPos) { + list($class, $ctorArgs) = $this->semStack[$stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 483 => function ($stackPos) { + $this->semValue = array(); + }, + 484 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-3)]; + }, + 485 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 486 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 487 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 488 => function ($stackPos) { + $this->semValue = new Expr\ClosureUse($this->semStack[$stackPos-(2-2)], $this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 489 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 490 => function ($stackPos) { + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 491 => function ($stackPos) { + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 492 => function ($stackPos) { + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 493 => function ($stackPos) { + $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 494 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 495 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 496 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 497 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 498 => function ($stackPos) { + $this->semValue = new Name\FullyQualified(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 499 => function ($stackPos) { + $this->semValue = new Name\Relative(substr($this->semStack[$stackPos-(1-1)], 10), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 500 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 501 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 502 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 503 => function ($stackPos) { + $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; + }, + 504 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 505 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 506 => function ($stackPos) { + $this->semValue = null; + }, + 507 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 508 => function ($stackPos) { + $this->semValue = array(); + }, + 509 => function ($stackPos) { + $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos-(1-1)], '`'), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); + }, + 510 => function ($stackPos) { + foreach ($this->semStack[$stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', true); } }; $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 511 => function ($stackPos) { + $this->semValue = array(); + }, + 512 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 513 => function ($stackPos) { + $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 514 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 515 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 516 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 517 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 518 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 519 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 520 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 521 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 522 => function ($stackPos) { + $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 523 => function ($stackPos) { + $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], new Expr\Error($this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)]), $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->errorState = 2; + }, + 524 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT; + $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $attrs); + }, + 525 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG; + $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $attrs); + }, + 526 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 527 => function ($stackPos) { + $this->semValue = Scalar\String_::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 528 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; + foreach ($this->semStack[$stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$stackPos-(3-2)], $attrs); + }, + 529 => function ($stackPos) { + $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 530 => function ($stackPos) { + $this->semValue = Scalar\DNumber::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 531 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 532 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 533 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 534 => function ($stackPos) { + $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true); + }, + 535 => function ($stackPos) { + $this->semValue = $this->parseDocString($this->semStack[$stackPos-(2-1)], '', $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(2-2)] + $this->endAttributeStack[$stackPos-(2-2)], true); + }, + 536 => function ($stackPos) { + $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true); + }, + 537 => function ($stackPos) { + $this->semValue = null; + }, + 538 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 539 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 540 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 541 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 542 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 543 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 544 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 545 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 546 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 547 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 548 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 549 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 550 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 551 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 552 => function ($stackPos) { + $this->semValue = new Expr\MethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 553 => function ($stackPos) { + $this->semValue = new Expr\NullsafeMethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 554 => function ($stackPos) { + $this->semValue = null; + }, + 555 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 556 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 557 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 558 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 559 => function ($stackPos) { + $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 560 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 561 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 562 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 563 => function ($stackPos) { + $this->semValue = new Expr\Variable(new Expr\Error($this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); $this->errorState = 2; + }, + 564 => function ($stackPos) { + $var = $this->semStack[$stackPos-(1-1)]->name; $this->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes) : $var; + }, + 565 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 566 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 567 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 568 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 569 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 570 => function ($stackPos) { + $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 571 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 572 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 573 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 574 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 575 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 576 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 577 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 578 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 579 => function ($stackPos) { + $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; + }, + 580 => function ($stackPos) { + $this->semValue = new Expr\List_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 581 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; $end = count($this->semValue)-1; if ($this->semValue[$end] === null) array_pop($this->semValue); + }, + 582 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 583 => function ($stackPos) { + /* do nothing -- prevent default action of $$=$this->semStack[$1]. See $551. */ + }, + 584 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 585 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 586 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 587 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 588 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 589 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 590 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-1)], true, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 591 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 592 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 593 => function ($stackPos) { + $this->semValue = null; + }, + 594 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 595 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 596 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 597 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); + }, + 598 => function ($stackPos) { + $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 599 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 600 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 601 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 602 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 603 => function ($stackPos) { + $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 604 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 605 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 606 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-4)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 607 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 608 => function ($stackPos) { + $this->semValue = new Scalar\String_($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 609 => function ($stackPos) { + $this->semValue = $this->parseNumString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 610 => function ($stackPos) { + $this->semValue = $this->parseNumString('-' . $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 611 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + ]; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.php b/vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.php new file mode 100644 index 00000000..b76a5d94 --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.php @@ -0,0 +1,148 @@ +lexer = $lexer; + + if (isset($options['throwOnError'])) { + throw new \LogicException( + '"throwOnError" is no longer supported, use "errorHandler" instead'); + } + + $this->initReduceCallbacks(); + } + + /** + * Parses PHP code into a node tree. + * + * If a non-throwing error handler is used, the parser will continue parsing after an error + * occurred and attempt to build a partial AST. + * + * @param string $code The source code to parse + * @param ErrorHandler|null $errorHandler Error handler to use for lexer/parser errors, defaults + * to ErrorHandler\Throwing. + * + * @return Node\Stmt[]|null Array of statements (or null non-throwing error handler is used and + * the parser was unable to recover from an error). + */ + public function parse(string $code, ErrorHandler $errorHandler = null) { + $this->errorHandler = $errorHandler ?: new ErrorHandler\Throwing; + + $this->lexer->startLexing($code, $this->errorHandler); + $result = $this->doParse(); + + // Clear out some of the interior state, so we don't hold onto unnecessary + // memory between uses of the parser + $this->startAttributeStack = []; + $this->endAttributeStack = []; + $this->semStack = []; + $this->semValue = null; + + return $result; + } + + protected function doParse() { + // We start off with no lookahead-token + $symbol = self::SYMBOL_NONE; + + // The attributes for a node are taken from the first and last token of the node. + // From the first token only the startAttributes are taken and from the last only + // the endAttributes. Both are merged using the array union operator (+). + $startAttributes = []; + $endAttributes = []; + $this->endAttributes = $endAttributes; + + // Keep stack of start and end attributes + $this->startAttributeStack = []; + $this->endAttributeStack = [$endAttributes]; + + // Start off in the initial state and keep a stack of previous states + $state = 0; + $stateStack = [$state]; + + // Semantic value stack (contains values of tokens and semantic action results) + $this->semStack = []; + + // Current position in the stack(s) + $stackPos = 0; + + $this->errorState = 0; + + for (;;) { + //$this->traceNewState($state, $symbol); + + if ($this->actionBase[$state] === 0) { + $rule = $this->actionDefault[$state]; + } else { + if ($symbol === self::SYMBOL_NONE) { + // Fetch the next token id from the lexer and fetch additional info by-ref. + // The end attributes are fetched into a temporary variable and only set once the token is really + // shifted (not during read). Otherwise you would sometimes get off-by-one errors, when a rule is + // reduced after a token was read but not yet shifted. + $tokenId = $this->lexer->getNextToken($tokenValue, $startAttributes, $endAttributes); + + // map the lexer token id to the internally used symbols + $symbol = $tokenId >= 0 && $tokenId < $this->tokenToSymbolMapSize + ? $this->tokenToSymbol[$tokenId] + : $this->invalidSymbol; + + if ($symbol === $this->invalidSymbol) { + throw new \RangeException(sprintf( + 'The lexer returned an invalid token (id=%d, value=%s)', + $tokenId, $tokenValue + )); + } + + // Allow productions to access the start attributes of the lookahead token. + $this->lookaheadStartAttributes = $startAttributes; + + //$this->traceRead($symbol); + } + + $idx = $this->actionBase[$state] + $symbol; + if ((($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol) + || ($state < $this->YY2TBLSTATE + && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 + && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol)) + && ($action = $this->action[$idx]) !== $this->defaultAction) { + /* + * >= numNonLeafStates: shift and reduce + * > 0: shift + * = 0: accept + * < 0: reduce + * = -YYUNEXPECTED: error + */ + if ($action > 0) { + /* shift */ + //$this->traceShift($symbol); + + ++$stackPos; + $stateStack[$stackPos] = $state = $action; + $this->semStack[$stackPos] = $tokenValue; + $this->startAttributeStack[$stackPos] = $startAttributes; + $this->endAttributeStack[$stackPos] = $endAttributes; + $this->endAttributes = $endAttributes; + $symbol = self::SYMBOL_NONE; + + if ($this->errorState) { + --$this->errorState; + } + + if ($action < $this->numNonLeafStates) { + continue; + } + + /* $yyn >= numNonLeafStates means shift-and-reduce */ + $rule = $action - $this->numNonLeafStates; + } else { + $rule = -$action; + } + } else { + $rule = $this->actionDefault[$state]; + } + } + + for (;;) { + if ($rule === 0) { + /* accept */ + //$this->traceAccept(); + return $this->semValue; + } elseif ($rule !== $this->unexpectedTokenRule) { + /* reduce */ + //$this->traceReduce($rule); + + try { + $this->reduceCallbacks[$rule]($stackPos); + } catch (Error $e) { + if (-1 === $e->getStartLine() && isset($startAttributes['startLine'])) { + $e->setStartLine($startAttributes['startLine']); + } + + $this->emitError($e); + // Can't recover from this type of error + return null; + } + + /* Goto - shift nonterminal */ + $lastEndAttributes = $this->endAttributeStack[$stackPos]; + $ruleLength = $this->ruleToLength[$rule]; + $stackPos -= $ruleLength; + $nonTerminal = $this->ruleToNonTerminal[$rule]; + $idx = $this->gotoBase[$nonTerminal] + $stateStack[$stackPos]; + if ($idx >= 0 && $idx < $this->gotoTableSize && $this->gotoCheck[$idx] === $nonTerminal) { + $state = $this->goto[$idx]; + } else { + $state = $this->gotoDefault[$nonTerminal]; + } + + ++$stackPos; + $stateStack[$stackPos] = $state; + $this->semStack[$stackPos] = $this->semValue; + $this->endAttributeStack[$stackPos] = $lastEndAttributes; + if ($ruleLength === 0) { + // Empty productions use the start attributes of the lookahead token. + $this->startAttributeStack[$stackPos] = $this->lookaheadStartAttributes; + } + } else { + /* error */ + switch ($this->errorState) { + case 0: + $msg = $this->getErrorMessage($symbol, $state); + $this->emitError(new Error($msg, $startAttributes + $endAttributes)); + // Break missing intentionally + case 1: + case 2: + $this->errorState = 3; + + // Pop until error-expecting state uncovered + while (!( + (($idx = $this->actionBase[$state] + $this->errorSymbol) >= 0 + && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol) + || ($state < $this->YY2TBLSTATE + && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $this->errorSymbol) >= 0 + && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol) + ) || ($action = $this->action[$idx]) === $this->defaultAction) { // Not totally sure about this + if ($stackPos <= 0) { + // Could not recover from error + return null; + } + $state = $stateStack[--$stackPos]; + //$this->tracePop($state); + } + + //$this->traceShift($this->errorSymbol); + ++$stackPos; + $stateStack[$stackPos] = $state = $action; + + // We treat the error symbol as being empty, so we reset the end attributes + // to the end attributes of the last non-error symbol + $this->startAttributeStack[$stackPos] = $this->lookaheadStartAttributes; + $this->endAttributeStack[$stackPos] = $this->endAttributeStack[$stackPos - 1]; + $this->endAttributes = $this->endAttributeStack[$stackPos - 1]; + break; + + case 3: + if ($symbol === 0) { + // Reached EOF without recovering from error + return null; + } + + //$this->traceDiscard($symbol); + $symbol = self::SYMBOL_NONE; + break 2; + } + } + + if ($state < $this->numNonLeafStates) { + break; + } + + /* >= numNonLeafStates means shift-and-reduce */ + $rule = $state - $this->numNonLeafStates; + } + } + + throw new \RuntimeException('Reached end of parser loop'); + } + + protected function emitError(Error $error) { + $this->errorHandler->handleError($error); + } + + /** + * Format error message including expected tokens. + * + * @param int $symbol Unexpected symbol + * @param int $state State at time of error + * + * @return string Formatted error message + */ + protected function getErrorMessage(int $symbol, int $state) : string { + $expectedString = ''; + if ($expected = $this->getExpectedTokens($state)) { + $expectedString = ', expecting ' . implode(' or ', $expected); + } + + return 'Syntax error, unexpected ' . $this->symbolToName[$symbol] . $expectedString; + } + + /** + * Get limited number of expected tokens in given state. + * + * @param int $state State + * + * @return string[] Expected tokens. If too many, an empty array is returned. + */ + protected function getExpectedTokens(int $state) : array { + $expected = []; + + $base = $this->actionBase[$state]; + foreach ($this->symbolToName as $symbol => $name) { + $idx = $base + $symbol; + if ($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol + || $state < $this->YY2TBLSTATE + && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 + && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol + ) { + if ($this->action[$idx] !== $this->unexpectedTokenRule + && $this->action[$idx] !== $this->defaultAction + && $symbol !== $this->errorSymbol + ) { + if (count($expected) === 4) { + /* Too many expected tokens */ + return []; + } + + $expected[] = $name; + } + } + } + + return $expected; + } + + /* + * Tracing functions used for debugging the parser. + */ + + /* + protected function traceNewState($state, $symbol) { + echo '% State ' . $state + . ', Lookahead ' . ($symbol == self::SYMBOL_NONE ? '--none--' : $this->symbolToName[$symbol]) . "\n"; + } + + protected function traceRead($symbol) { + echo '% Reading ' . $this->symbolToName[$symbol] . "\n"; + } + + protected function traceShift($symbol) { + echo '% Shift ' . $this->symbolToName[$symbol] . "\n"; + } + + protected function traceAccept() { + echo "% Accepted.\n"; + } + + protected function traceReduce($n) { + echo '% Reduce by (' . $n . ') ' . $this->productions[$n] . "\n"; + } + + protected function tracePop($state) { + echo '% Recovering, uncovered state ' . $state . "\n"; + } + + protected function traceDiscard($symbol) { + echo '% Discard ' . $this->symbolToName[$symbol] . "\n"; + } + */ + + /* + * Helper functions invoked by semantic actions + */ + + /** + * Moves statements of semicolon-style namespaces into $ns->stmts and checks various error conditions. + * + * @param Node\Stmt[] $stmts + * @return Node\Stmt[] + */ + protected function handleNamespaces(array $stmts) : array { + $hasErrored = false; + $style = $this->getNamespacingStyle($stmts); + if (null === $style) { + // not namespaced, nothing to do + return $stmts; + } elseif ('brace' === $style) { + // For braced namespaces we only have to check that there are no invalid statements between the namespaces + $afterFirstNamespace = false; + foreach ($stmts as $stmt) { + if ($stmt instanceof Node\Stmt\Namespace_) { + $afterFirstNamespace = true; + } elseif (!$stmt instanceof Node\Stmt\HaltCompiler + && !$stmt instanceof Node\Stmt\Nop + && $afterFirstNamespace && !$hasErrored) { + $this->emitError(new Error( + 'No code may exist outside of namespace {}', $stmt->getAttributes())); + $hasErrored = true; // Avoid one error for every statement + } + } + return $stmts; + } else { + // For semicolon namespaces we have to move the statements after a namespace declaration into ->stmts + $resultStmts = []; + $targetStmts =& $resultStmts; + $lastNs = null; + foreach ($stmts as $stmt) { + if ($stmt instanceof Node\Stmt\Namespace_) { + if ($lastNs !== null) { + $this->fixupNamespaceAttributes($lastNs); + } + if ($stmt->stmts === null) { + $stmt->stmts = []; + $targetStmts =& $stmt->stmts; + $resultStmts[] = $stmt; + } else { + // This handles the invalid case of mixed style namespaces + $resultStmts[] = $stmt; + $targetStmts =& $resultStmts; + } + $lastNs = $stmt; + } elseif ($stmt instanceof Node\Stmt\HaltCompiler) { + // __halt_compiler() is not moved into the namespace + $resultStmts[] = $stmt; + } else { + $targetStmts[] = $stmt; + } + } + if ($lastNs !== null) { + $this->fixupNamespaceAttributes($lastNs); + } + return $resultStmts; + } + } + + private function fixupNamespaceAttributes(Node\Stmt\Namespace_ $stmt) { + // We moved the statements into the namespace node, as such the end of the namespace node + // needs to be extended to the end of the statements. + if (empty($stmt->stmts)) { + return; + } + + // We only move the builtin end attributes here. This is the best we can do with the + // knowledge we have. + $endAttributes = ['endLine', 'endFilePos', 'endTokenPos']; + $lastStmt = $stmt->stmts[count($stmt->stmts) - 1]; + foreach ($endAttributes as $endAttribute) { + if ($lastStmt->hasAttribute($endAttribute)) { + $stmt->setAttribute($endAttribute, $lastStmt->getAttribute($endAttribute)); + } + } + } + + /** + * Determine namespacing style (semicolon or brace) + * + * @param Node[] $stmts Top-level statements. + * + * @return null|string One of "semicolon", "brace" or null (no namespaces) + */ + private function getNamespacingStyle(array $stmts) { + $style = null; + $hasNotAllowedStmts = false; + foreach ($stmts as $i => $stmt) { + if ($stmt instanceof Node\Stmt\Namespace_) { + $currentStyle = null === $stmt->stmts ? 'semicolon' : 'brace'; + if (null === $style) { + $style = $currentStyle; + if ($hasNotAllowedStmts) { + $this->emitError(new Error( + 'Namespace declaration statement has to be the very first statement in the script', + $stmt->getLine() // Avoid marking the entire namespace as an error + )); + } + } elseif ($style !== $currentStyle) { + $this->emitError(new Error( + 'Cannot mix bracketed namespace declarations with unbracketed namespace declarations', + $stmt->getLine() // Avoid marking the entire namespace as an error + )); + // Treat like semicolon style for namespace normalization + return 'semicolon'; + } + continue; + } + + /* declare(), __halt_compiler() and nops can be used before a namespace declaration */ + if ($stmt instanceof Node\Stmt\Declare_ + || $stmt instanceof Node\Stmt\HaltCompiler + || $stmt instanceof Node\Stmt\Nop) { + continue; + } + + /* There may be a hashbang line at the very start of the file */ + if ($i === 0 && $stmt instanceof Node\Stmt\InlineHTML && preg_match('/\A#!.*\r?\n\z/', $stmt->value)) { + continue; + } + + /* Everything else if forbidden before namespace declarations */ + $hasNotAllowedStmts = true; + } + return $style; + } + + /** + * Fix up parsing of static property calls in PHP 5. + * + * In PHP 5 A::$b[c][d] and A::$b[c][d]() have very different interpretation. The former is + * interpreted as (A::$b)[c][d], while the latter is the same as A::{$b[c][d]}(). We parse the + * latter as the former initially and this method fixes the AST into the correct form when we + * encounter the "()". + * + * @param Node\Expr\StaticPropertyFetch|Node\Expr\ArrayDimFetch $prop + * @param Node\Arg[] $args + * @param array $attributes + * + * @return Expr\StaticCall + */ + protected function fixupPhp5StaticPropCall($prop, array $args, array $attributes) : Expr\StaticCall { + if ($prop instanceof Node\Expr\StaticPropertyFetch) { + $name = $prop->name instanceof VarLikeIdentifier + ? $prop->name->toString() : $prop->name; + $var = new Expr\Variable($name, $prop->name->getAttributes()); + return new Expr\StaticCall($prop->class, $var, $args, $attributes); + } elseif ($prop instanceof Node\Expr\ArrayDimFetch) { + $tmp = $prop; + while ($tmp->var instanceof Node\Expr\ArrayDimFetch) { + $tmp = $tmp->var; + } + + /** @var Expr\StaticPropertyFetch $staticProp */ + $staticProp = $tmp->var; + + // Set start attributes to attributes of innermost node + $tmp = $prop; + $this->fixupStartAttributes($tmp, $staticProp->name); + while ($tmp->var instanceof Node\Expr\ArrayDimFetch) { + $tmp = $tmp->var; + $this->fixupStartAttributes($tmp, $staticProp->name); + } + + $name = $staticProp->name instanceof VarLikeIdentifier + ? $staticProp->name->toString() : $staticProp->name; + $tmp->var = new Expr\Variable($name, $staticProp->name->getAttributes()); + return new Expr\StaticCall($staticProp->class, $prop, $args, $attributes); + } else { + throw new \Exception; + } + } + + protected function fixupStartAttributes(Node $to, Node $from) { + $startAttributes = ['startLine', 'startFilePos', 'startTokenPos']; + foreach ($startAttributes as $startAttribute) { + if ($from->hasAttribute($startAttribute)) { + $to->setAttribute($startAttribute, $from->getAttribute($startAttribute)); + } + } + } + + protected function handleBuiltinTypes(Name $name) { + $builtinTypes = [ + 'bool' => true, + 'int' => true, + 'float' => true, + 'string' => true, + 'iterable' => true, + 'void' => true, + 'object' => true, + 'null' => true, + 'false' => true, + 'mixed' => true, + 'never' => true, + 'true' => true, + ]; + + if (!$name->isUnqualified()) { + return $name; + } + + $lowerName = $name->toLowerString(); + if (!isset($builtinTypes[$lowerName])) { + return $name; + } + + return new Node\Identifier($lowerName, $name->getAttributes()); + } + + /** + * Get combined start and end attributes at a stack location + * + * @param int $pos Stack location + * + * @return array Combined start and end attributes + */ + protected function getAttributesAt(int $pos) : array { + return $this->startAttributeStack[$pos] + $this->endAttributeStack[$pos]; + } + + protected function getFloatCastKind(string $cast): int + { + $cast = strtolower($cast); + if (strpos($cast, 'float') !== false) { + return Double::KIND_FLOAT; + } + + if (strpos($cast, 'real') !== false) { + return Double::KIND_REAL; + } + + return Double::KIND_DOUBLE; + } + + protected function parseLNumber($str, $attributes, $allowInvalidOctal = false) { + try { + return LNumber::fromString($str, $attributes, $allowInvalidOctal); + } catch (Error $error) { + $this->emitError($error); + // Use dummy value + return new LNumber(0, $attributes); + } + } + + /** + * Parse a T_NUM_STRING token into either an integer or string node. + * + * @param string $str Number string + * @param array $attributes Attributes + * + * @return LNumber|String_ Integer or string node. + */ + protected function parseNumString(string $str, array $attributes) { + if (!preg_match('/^(?:0|-?[1-9][0-9]*)$/', $str)) { + return new String_($str, $attributes); + } + + $num = +$str; + if (!is_int($num)) { + return new String_($str, $attributes); + } + + return new LNumber($num, $attributes); + } + + protected function stripIndentation( + string $string, int $indentLen, string $indentChar, + bool $newlineAtStart, bool $newlineAtEnd, array $attributes + ) { + if ($indentLen === 0) { + return $string; + } + + $start = $newlineAtStart ? '(?:(?<=\n)|\A)' : '(?<=\n)'; + $end = $newlineAtEnd ? '(?:(?=[\r\n])|\z)' : '(?=[\r\n])'; + $regex = '/' . $start . '([ \t]*)(' . $end . ')?/'; + return preg_replace_callback( + $regex, + function ($matches) use ($indentLen, $indentChar, $attributes) { + $prefix = substr($matches[1], 0, $indentLen); + if (false !== strpos($prefix, $indentChar === " " ? "\t" : " ")) { + $this->emitError(new Error( + 'Invalid indentation - tabs and spaces cannot be mixed', $attributes + )); + } elseif (strlen($prefix) < $indentLen && !isset($matches[2])) { + $this->emitError(new Error( + 'Invalid body indentation level ' . + '(expecting an indentation level of at least ' . $indentLen . ')', + $attributes + )); + } + return substr($matches[0], strlen($prefix)); + }, + $string + ); + } + + protected function parseDocString( + string $startToken, $contents, string $endToken, + array $attributes, array $endTokenAttributes, bool $parseUnicodeEscape + ) { + $kind = strpos($startToken, "'") === false + ? String_::KIND_HEREDOC : String_::KIND_NOWDOC; + + $regex = '/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/'; + $result = preg_match($regex, $startToken, $matches); + assert($result === 1); + $label = $matches[1]; + + $result = preg_match('/\A[ \t]*/', $endToken, $matches); + assert($result === 1); + $indentation = $matches[0]; + + $attributes['kind'] = $kind; + $attributes['docLabel'] = $label; + $attributes['docIndentation'] = $indentation; + + $indentHasSpaces = false !== strpos($indentation, " "); + $indentHasTabs = false !== strpos($indentation, "\t"); + if ($indentHasSpaces && $indentHasTabs) { + $this->emitError(new Error( + 'Invalid indentation - tabs and spaces cannot be mixed', + $endTokenAttributes + )); + + // Proceed processing as if this doc string is not indented + $indentation = ''; + } + + $indentLen = \strlen($indentation); + $indentChar = $indentHasSpaces ? " " : "\t"; + + if (\is_string($contents)) { + if ($contents === '') { + return new String_('', $attributes); + } + + $contents = $this->stripIndentation( + $contents, $indentLen, $indentChar, true, true, $attributes + ); + $contents = preg_replace('~(\r\n|\n|\r)\z~', '', $contents); + + if ($kind === String_::KIND_HEREDOC) { + $contents = String_::parseEscapeSequences($contents, null, $parseUnicodeEscape); + } + + return new String_($contents, $attributes); + } else { + assert(count($contents) > 0); + if (!$contents[0] instanceof Node\Scalar\EncapsedStringPart) { + // If there is no leading encapsed string part, pretend there is an empty one + $this->stripIndentation( + '', $indentLen, $indentChar, true, false, $contents[0]->getAttributes() + ); + } + + $newContents = []; + foreach ($contents as $i => $part) { + if ($part instanceof Node\Scalar\EncapsedStringPart) { + $isLast = $i === \count($contents) - 1; + $part->value = $this->stripIndentation( + $part->value, $indentLen, $indentChar, + $i === 0, $isLast, $part->getAttributes() + ); + $part->value = String_::parseEscapeSequences($part->value, null, $parseUnicodeEscape); + if ($isLast) { + $part->value = preg_replace('~(\r\n|\n|\r)\z~', '', $part->value); + } + if ('' === $part->value) { + continue; + } + } + $newContents[] = $part; + } + return new Encapsed($newContents, $attributes); + } + } + + /** + * Create attributes for a zero-length common-capturing nop. + * + * @param Comment[] $comments + * @return array + */ + protected function createCommentNopAttributes(array $comments) { + $comment = $comments[count($comments) - 1]; + $commentEndLine = $comment->getEndLine(); + $commentEndFilePos = $comment->getEndFilePos(); + $commentEndTokenPos = $comment->getEndTokenPos(); + + $attributes = ['comments' => $comments]; + if (-1 !== $commentEndLine) { + $attributes['startLine'] = $commentEndLine; + $attributes['endLine'] = $commentEndLine; + } + if (-1 !== $commentEndFilePos) { + $attributes['startFilePos'] = $commentEndFilePos + 1; + $attributes['endFilePos'] = $commentEndFilePos; + } + if (-1 !== $commentEndTokenPos) { + $attributes['startTokenPos'] = $commentEndTokenPos + 1; + $attributes['endTokenPos'] = $commentEndTokenPos; + } + return $attributes; + } + + protected function checkClassModifier($a, $b, $modifierPos) { + try { + Class_::verifyClassModifier($a, $b); + } catch (Error $error) { + $error->setAttributes($this->getAttributesAt($modifierPos)); + $this->emitError($error); + } + } + + protected function checkModifier($a, $b, $modifierPos) { + // Jumping through some hoops here because verifyModifier() is also used elsewhere + try { + Class_::verifyModifier($a, $b); + } catch (Error $error) { + $error->setAttributes($this->getAttributesAt($modifierPos)); + $this->emitError($error); + } + } + + protected function checkParam(Param $node) { + if ($node->variadic && null !== $node->default) { + $this->emitError(new Error( + 'Variadic parameter cannot have a default value', + $node->default->getAttributes() + )); + } + } + + protected function checkTryCatch(TryCatch $node) { + if (empty($node->catches) && null === $node->finally) { + $this->emitError(new Error( + 'Cannot use try without catch or finally', $node->getAttributes() + )); + } + } + + protected function checkNamespace(Namespace_ $node) { + if (null !== $node->stmts) { + foreach ($node->stmts as $stmt) { + if ($stmt instanceof Namespace_) { + $this->emitError(new Error( + 'Namespace declarations cannot be nested', $stmt->getAttributes() + )); + } + } + } + } + + private function checkClassName($name, $namePos) { + if (null !== $name && $name->isSpecialClassName()) { + $this->emitError(new Error( + sprintf('Cannot use \'%s\' as class name as it is reserved', $name), + $this->getAttributesAt($namePos) + )); + } + } + + private function checkImplementedInterfaces(array $interfaces) { + foreach ($interfaces as $interface) { + if ($interface->isSpecialClassName()) { + $this->emitError(new Error( + sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface), + $interface->getAttributes() + )); + } + } + } + + protected function checkClass(Class_ $node, $namePos) { + $this->checkClassName($node->name, $namePos); + + if ($node->extends && $node->extends->isSpecialClassName()) { + $this->emitError(new Error( + sprintf('Cannot use \'%s\' as class name as it is reserved', $node->extends), + $node->extends->getAttributes() + )); + } + + $this->checkImplementedInterfaces($node->implements); + } + + protected function checkInterface(Interface_ $node, $namePos) { + $this->checkClassName($node->name, $namePos); + $this->checkImplementedInterfaces($node->extends); + } + + protected function checkEnum(Enum_ $node, $namePos) { + $this->checkClassName($node->name, $namePos); + $this->checkImplementedInterfaces($node->implements); + } + + protected function checkClassMethod(ClassMethod $node, $modifierPos) { + if ($node->flags & Class_::MODIFIER_STATIC) { + switch ($node->name->toLowerString()) { + case '__construct': + $this->emitError(new Error( + sprintf('Constructor %s() cannot be static', $node->name), + $this->getAttributesAt($modifierPos))); + break; + case '__destruct': + $this->emitError(new Error( + sprintf('Destructor %s() cannot be static', $node->name), + $this->getAttributesAt($modifierPos))); + break; + case '__clone': + $this->emitError(new Error( + sprintf('Clone method %s() cannot be static', $node->name), + $this->getAttributesAt($modifierPos))); + break; + } + } + + if ($node->flags & Class_::MODIFIER_READONLY) { + $this->emitError(new Error( + sprintf('Method %s() cannot be readonly', $node->name), + $this->getAttributesAt($modifierPos))); + } + } + + protected function checkClassConst(ClassConst $node, $modifierPos) { + if ($node->flags & Class_::MODIFIER_STATIC) { + $this->emitError(new Error( + "Cannot use 'static' as constant modifier", + $this->getAttributesAt($modifierPos))); + } + if ($node->flags & Class_::MODIFIER_ABSTRACT) { + $this->emitError(new Error( + "Cannot use 'abstract' as constant modifier", + $this->getAttributesAt($modifierPos))); + } + if ($node->flags & Class_::MODIFIER_READONLY) { + $this->emitError(new Error( + "Cannot use 'readonly' as constant modifier", + $this->getAttributesAt($modifierPos))); + } + } + + protected function checkProperty(Property $node, $modifierPos) { + if ($node->flags & Class_::MODIFIER_ABSTRACT) { + $this->emitError(new Error('Properties cannot be declared abstract', + $this->getAttributesAt($modifierPos))); + } + + if ($node->flags & Class_::MODIFIER_FINAL) { + $this->emitError(new Error('Properties cannot be declared final', + $this->getAttributesAt($modifierPos))); + } + } + + protected function checkUseUse(UseUse $node, $namePos) { + if ($node->alias && $node->alias->isSpecialClassName()) { + $this->emitError(new Error( + sprintf( + 'Cannot use %s as %s because \'%2$s\' is a special class name', + $node->name, $node->alias + ), + $this->getAttributesAt($namePos) + )); + } + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php b/vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php new file mode 100644 index 00000000..f041e7ff --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php @@ -0,0 +1,44 @@ +pAttrGroups($node->attrGroups, true) + . $this->pModifiers($node->flags) + . ($node->type ? $this->p($node->type) . ' ' : '') + . ($node->byRef ? '&' : '') + . ($node->variadic ? '...' : '') + . $this->p($node->var) + . ($node->default ? ' = ' . $this->p($node->default) : ''); + } + + protected function pArg(Node\Arg $node) { + return ($node->name ? $node->name->toString() . ': ' : '') + . ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') + . $this->p($node->value); + } + + protected function pVariadicPlaceholder(Node\VariadicPlaceholder $node) { + return '...'; + } + + protected function pConst(Node\Const_ $node) { + return $node->name . ' = ' . $this->p($node->value); + } + + protected function pNullableType(Node\NullableType $node) { + return '?' . $this->p($node->type); + } + + protected function pUnionType(Node\UnionType $node) { + $types = []; + foreach ($node->types as $typeNode) { + if ($typeNode instanceof Node\IntersectionType) { + $types[] = '('. $this->p($typeNode) . ')'; + continue; + } + $types[] = $this->p($typeNode); + } + return implode('|', $types); + } + + protected function pIntersectionType(Node\IntersectionType $node) { + return $this->pImplode($node->types, '&'); + } + + protected function pIdentifier(Node\Identifier $node) { + return $node->name; + } + + protected function pVarLikeIdentifier(Node\VarLikeIdentifier $node) { + return '$' . $node->name; + } + + protected function pAttribute(Node\Attribute $node) { + return $this->p($node->name) + . ($node->args ? '(' . $this->pCommaSeparated($node->args) . ')' : ''); + } + + protected function pAttributeGroup(Node\AttributeGroup $node) { + return '#[' . $this->pCommaSeparated($node->attrs) . ']'; + } + + // Names + + protected function pName(Name $node) { + return implode('\\', $node->parts); + } + + protected function pName_FullyQualified(Name\FullyQualified $node) { + return '\\' . implode('\\', $node->parts); + } + + protected function pName_Relative(Name\Relative $node) { + return 'namespace\\' . implode('\\', $node->parts); + } + + // Magic Constants + + protected function pScalar_MagicConst_Class(MagicConst\Class_ $node) { + return '__CLASS__'; + } + + protected function pScalar_MagicConst_Dir(MagicConst\Dir $node) { + return '__DIR__'; + } + + protected function pScalar_MagicConst_File(MagicConst\File $node) { + return '__FILE__'; + } + + protected function pScalar_MagicConst_Function(MagicConst\Function_ $node) { + return '__FUNCTION__'; + } + + protected function pScalar_MagicConst_Line(MagicConst\Line $node) { + return '__LINE__'; + } + + protected function pScalar_MagicConst_Method(MagicConst\Method $node) { + return '__METHOD__'; + } + + protected function pScalar_MagicConst_Namespace(MagicConst\Namespace_ $node) { + return '__NAMESPACE__'; + } + + protected function pScalar_MagicConst_Trait(MagicConst\Trait_ $node) { + return '__TRAIT__'; + } + + // Scalars + + protected function pScalar_String(Scalar\String_ $node) { + $kind = $node->getAttribute('kind', Scalar\String_::KIND_SINGLE_QUOTED); + switch ($kind) { + case Scalar\String_::KIND_NOWDOC: + $label = $node->getAttribute('docLabel'); + if ($label && !$this->containsEndLabel($node->value, $label)) { + if ($node->value === '') { + return "<<<'$label'\n$label" . $this->docStringEndToken; + } + + return "<<<'$label'\n$node->value\n$label" + . $this->docStringEndToken; + } + /* break missing intentionally */ + case Scalar\String_::KIND_SINGLE_QUOTED: + return $this->pSingleQuotedString($node->value); + case Scalar\String_::KIND_HEREDOC: + $label = $node->getAttribute('docLabel'); + if ($label && !$this->containsEndLabel($node->value, $label)) { + if ($node->value === '') { + return "<<<$label\n$label" . $this->docStringEndToken; + } + + $escaped = $this->escapeString($node->value, null); + return "<<<$label\n" . $escaped . "\n$label" + . $this->docStringEndToken; + } + /* break missing intentionally */ + case Scalar\String_::KIND_DOUBLE_QUOTED: + return '"' . $this->escapeString($node->value, '"') . '"'; + } + throw new \Exception('Invalid string kind'); + } + + protected function pScalar_Encapsed(Scalar\Encapsed $node) { + if ($node->getAttribute('kind') === Scalar\String_::KIND_HEREDOC) { + $label = $node->getAttribute('docLabel'); + if ($label && !$this->encapsedContainsEndLabel($node->parts, $label)) { + if (count($node->parts) === 1 + && $node->parts[0] instanceof Scalar\EncapsedStringPart + && $node->parts[0]->value === '' + ) { + return "<<<$label\n$label" . $this->docStringEndToken; + } + + return "<<<$label\n" . $this->pEncapsList($node->parts, null) . "\n$label" + . $this->docStringEndToken; + } + } + return '"' . $this->pEncapsList($node->parts, '"') . '"'; + } + + protected function pScalar_LNumber(Scalar\LNumber $node) { + if ($node->value === -\PHP_INT_MAX-1) { + // PHP_INT_MIN cannot be represented as a literal, + // because the sign is not part of the literal + return '(-' . \PHP_INT_MAX . '-1)'; + } + + $kind = $node->getAttribute('kind', Scalar\LNumber::KIND_DEC); + if (Scalar\LNumber::KIND_DEC === $kind) { + return (string) $node->value; + } + + if ($node->value < 0) { + $sign = '-'; + $str = (string) -$node->value; + } else { + $sign = ''; + $str = (string) $node->value; + } + switch ($kind) { + case Scalar\LNumber::KIND_BIN: + return $sign . '0b' . base_convert($str, 10, 2); + case Scalar\LNumber::KIND_OCT: + return $sign . '0' . base_convert($str, 10, 8); + case Scalar\LNumber::KIND_HEX: + return $sign . '0x' . base_convert($str, 10, 16); + } + throw new \Exception('Invalid number kind'); + } + + protected function pScalar_DNumber(Scalar\DNumber $node) { + if (!is_finite($node->value)) { + if ($node->value === \INF) { + return '\INF'; + } elseif ($node->value === -\INF) { + return '-\INF'; + } else { + return '\NAN'; + } + } + + // Try to find a short full-precision representation + $stringValue = sprintf('%.16G', $node->value); + if ($node->value !== (double) $stringValue) { + $stringValue = sprintf('%.17G', $node->value); + } + + // %G is locale dependent and there exists no locale-independent alternative. We don't want + // mess with switching locales here, so let's assume that a comma is the only non-standard + // decimal separator we may encounter... + $stringValue = str_replace(',', '.', $stringValue); + + // ensure that number is really printed as float + return preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue; + } + + protected function pScalar_EncapsedStringPart(Scalar\EncapsedStringPart $node) { + throw new \LogicException('Cannot directly print EncapsedStringPart'); + } + + // Assignments + + protected function pExpr_Assign(Expr\Assign $node) { + return $this->pInfixOp(Expr\Assign::class, $node->var, ' = ', $node->expr); + } + + protected function pExpr_AssignRef(Expr\AssignRef $node) { + return $this->pInfixOp(Expr\AssignRef::class, $node->var, ' =& ', $node->expr); + } + + protected function pExpr_AssignOp_Plus(AssignOp\Plus $node) { + return $this->pInfixOp(AssignOp\Plus::class, $node->var, ' += ', $node->expr); + } + + protected function pExpr_AssignOp_Minus(AssignOp\Minus $node) { + return $this->pInfixOp(AssignOp\Minus::class, $node->var, ' -= ', $node->expr); + } + + protected function pExpr_AssignOp_Mul(AssignOp\Mul $node) { + return $this->pInfixOp(AssignOp\Mul::class, $node->var, ' *= ', $node->expr); + } + + protected function pExpr_AssignOp_Div(AssignOp\Div $node) { + return $this->pInfixOp(AssignOp\Div::class, $node->var, ' /= ', $node->expr); + } + + protected function pExpr_AssignOp_Concat(AssignOp\Concat $node) { + return $this->pInfixOp(AssignOp\Concat::class, $node->var, ' .= ', $node->expr); + } + + protected function pExpr_AssignOp_Mod(AssignOp\Mod $node) { + return $this->pInfixOp(AssignOp\Mod::class, $node->var, ' %= ', $node->expr); + } + + protected function pExpr_AssignOp_BitwiseAnd(AssignOp\BitwiseAnd $node) { + return $this->pInfixOp(AssignOp\BitwiseAnd::class, $node->var, ' &= ', $node->expr); + } + + protected function pExpr_AssignOp_BitwiseOr(AssignOp\BitwiseOr $node) { + return $this->pInfixOp(AssignOp\BitwiseOr::class, $node->var, ' |= ', $node->expr); + } + + protected function pExpr_AssignOp_BitwiseXor(AssignOp\BitwiseXor $node) { + return $this->pInfixOp(AssignOp\BitwiseXor::class, $node->var, ' ^= ', $node->expr); + } + + protected function pExpr_AssignOp_ShiftLeft(AssignOp\ShiftLeft $node) { + return $this->pInfixOp(AssignOp\ShiftLeft::class, $node->var, ' <<= ', $node->expr); + } + + protected function pExpr_AssignOp_ShiftRight(AssignOp\ShiftRight $node) { + return $this->pInfixOp(AssignOp\ShiftRight::class, $node->var, ' >>= ', $node->expr); + } + + protected function pExpr_AssignOp_Pow(AssignOp\Pow $node) { + return $this->pInfixOp(AssignOp\Pow::class, $node->var, ' **= ', $node->expr); + } + + protected function pExpr_AssignOp_Coalesce(AssignOp\Coalesce $node) { + return $this->pInfixOp(AssignOp\Coalesce::class, $node->var, ' ??= ', $node->expr); + } + + // Binary expressions + + protected function pExpr_BinaryOp_Plus(BinaryOp\Plus $node) { + return $this->pInfixOp(BinaryOp\Plus::class, $node->left, ' + ', $node->right); + } + + protected function pExpr_BinaryOp_Minus(BinaryOp\Minus $node) { + return $this->pInfixOp(BinaryOp\Minus::class, $node->left, ' - ', $node->right); + } + + protected function pExpr_BinaryOp_Mul(BinaryOp\Mul $node) { + return $this->pInfixOp(BinaryOp\Mul::class, $node->left, ' * ', $node->right); + } + + protected function pExpr_BinaryOp_Div(BinaryOp\Div $node) { + return $this->pInfixOp(BinaryOp\Div::class, $node->left, ' / ', $node->right); + } + + protected function pExpr_BinaryOp_Concat(BinaryOp\Concat $node) { + return $this->pInfixOp(BinaryOp\Concat::class, $node->left, ' . ', $node->right); + } + + protected function pExpr_BinaryOp_Mod(BinaryOp\Mod $node) { + return $this->pInfixOp(BinaryOp\Mod::class, $node->left, ' % ', $node->right); + } + + protected function pExpr_BinaryOp_BooleanAnd(BinaryOp\BooleanAnd $node) { + return $this->pInfixOp(BinaryOp\BooleanAnd::class, $node->left, ' && ', $node->right); + } + + protected function pExpr_BinaryOp_BooleanOr(BinaryOp\BooleanOr $node) { + return $this->pInfixOp(BinaryOp\BooleanOr::class, $node->left, ' || ', $node->right); + } + + protected function pExpr_BinaryOp_BitwiseAnd(BinaryOp\BitwiseAnd $node) { + return $this->pInfixOp(BinaryOp\BitwiseAnd::class, $node->left, ' & ', $node->right); + } + + protected function pExpr_BinaryOp_BitwiseOr(BinaryOp\BitwiseOr $node) { + return $this->pInfixOp(BinaryOp\BitwiseOr::class, $node->left, ' | ', $node->right); + } + + protected function pExpr_BinaryOp_BitwiseXor(BinaryOp\BitwiseXor $node) { + return $this->pInfixOp(BinaryOp\BitwiseXor::class, $node->left, ' ^ ', $node->right); + } + + protected function pExpr_BinaryOp_ShiftLeft(BinaryOp\ShiftLeft $node) { + return $this->pInfixOp(BinaryOp\ShiftLeft::class, $node->left, ' << ', $node->right); + } + + protected function pExpr_BinaryOp_ShiftRight(BinaryOp\ShiftRight $node) { + return $this->pInfixOp(BinaryOp\ShiftRight::class, $node->left, ' >> ', $node->right); + } + + protected function pExpr_BinaryOp_Pow(BinaryOp\Pow $node) { + return $this->pInfixOp(BinaryOp\Pow::class, $node->left, ' ** ', $node->right); + } + + protected function pExpr_BinaryOp_LogicalAnd(BinaryOp\LogicalAnd $node) { + return $this->pInfixOp(BinaryOp\LogicalAnd::class, $node->left, ' and ', $node->right); + } + + protected function pExpr_BinaryOp_LogicalOr(BinaryOp\LogicalOr $node) { + return $this->pInfixOp(BinaryOp\LogicalOr::class, $node->left, ' or ', $node->right); + } + + protected function pExpr_BinaryOp_LogicalXor(BinaryOp\LogicalXor $node) { + return $this->pInfixOp(BinaryOp\LogicalXor::class, $node->left, ' xor ', $node->right); + } + + protected function pExpr_BinaryOp_Equal(BinaryOp\Equal $node) { + return $this->pInfixOp(BinaryOp\Equal::class, $node->left, ' == ', $node->right); + } + + protected function pExpr_BinaryOp_NotEqual(BinaryOp\NotEqual $node) { + return $this->pInfixOp(BinaryOp\NotEqual::class, $node->left, ' != ', $node->right); + } + + protected function pExpr_BinaryOp_Identical(BinaryOp\Identical $node) { + return $this->pInfixOp(BinaryOp\Identical::class, $node->left, ' === ', $node->right); + } + + protected function pExpr_BinaryOp_NotIdentical(BinaryOp\NotIdentical $node) { + return $this->pInfixOp(BinaryOp\NotIdentical::class, $node->left, ' !== ', $node->right); + } + + protected function pExpr_BinaryOp_Spaceship(BinaryOp\Spaceship $node) { + return $this->pInfixOp(BinaryOp\Spaceship::class, $node->left, ' <=> ', $node->right); + } + + protected function pExpr_BinaryOp_Greater(BinaryOp\Greater $node) { + return $this->pInfixOp(BinaryOp\Greater::class, $node->left, ' > ', $node->right); + } + + protected function pExpr_BinaryOp_GreaterOrEqual(BinaryOp\GreaterOrEqual $node) { + return $this->pInfixOp(BinaryOp\GreaterOrEqual::class, $node->left, ' >= ', $node->right); + } + + protected function pExpr_BinaryOp_Smaller(BinaryOp\Smaller $node) { + return $this->pInfixOp(BinaryOp\Smaller::class, $node->left, ' < ', $node->right); + } + + protected function pExpr_BinaryOp_SmallerOrEqual(BinaryOp\SmallerOrEqual $node) { + return $this->pInfixOp(BinaryOp\SmallerOrEqual::class, $node->left, ' <= ', $node->right); + } + + protected function pExpr_BinaryOp_Coalesce(BinaryOp\Coalesce $node) { + return $this->pInfixOp(BinaryOp\Coalesce::class, $node->left, ' ?? ', $node->right); + } + + protected function pExpr_Instanceof(Expr\Instanceof_ $node) { + list($precedence, $associativity) = $this->precedenceMap[Expr\Instanceof_::class]; + return $this->pPrec($node->expr, $precedence, $associativity, -1) + . ' instanceof ' + . $this->pNewVariable($node->class); + } + + // Unary expressions + + protected function pExpr_BooleanNot(Expr\BooleanNot $node) { + return $this->pPrefixOp(Expr\BooleanNot::class, '!', $node->expr); + } + + protected function pExpr_BitwiseNot(Expr\BitwiseNot $node) { + return $this->pPrefixOp(Expr\BitwiseNot::class, '~', $node->expr); + } + + protected function pExpr_UnaryMinus(Expr\UnaryMinus $node) { + if ($node->expr instanceof Expr\UnaryMinus || $node->expr instanceof Expr\PreDec) { + // Enforce -(-$expr) instead of --$expr + return '-(' . $this->p($node->expr) . ')'; + } + return $this->pPrefixOp(Expr\UnaryMinus::class, '-', $node->expr); + } + + protected function pExpr_UnaryPlus(Expr\UnaryPlus $node) { + if ($node->expr instanceof Expr\UnaryPlus || $node->expr instanceof Expr\PreInc) { + // Enforce +(+$expr) instead of ++$expr + return '+(' . $this->p($node->expr) . ')'; + } + return $this->pPrefixOp(Expr\UnaryPlus::class, '+', $node->expr); + } + + protected function pExpr_PreInc(Expr\PreInc $node) { + return $this->pPrefixOp(Expr\PreInc::class, '++', $node->var); + } + + protected function pExpr_PreDec(Expr\PreDec $node) { + return $this->pPrefixOp(Expr\PreDec::class, '--', $node->var); + } + + protected function pExpr_PostInc(Expr\PostInc $node) { + return $this->pPostfixOp(Expr\PostInc::class, $node->var, '++'); + } + + protected function pExpr_PostDec(Expr\PostDec $node) { + return $this->pPostfixOp(Expr\PostDec::class, $node->var, '--'); + } + + protected function pExpr_ErrorSuppress(Expr\ErrorSuppress $node) { + return $this->pPrefixOp(Expr\ErrorSuppress::class, '@', $node->expr); + } + + protected function pExpr_YieldFrom(Expr\YieldFrom $node) { + return $this->pPrefixOp(Expr\YieldFrom::class, 'yield from ', $node->expr); + } + + protected function pExpr_Print(Expr\Print_ $node) { + return $this->pPrefixOp(Expr\Print_::class, 'print ', $node->expr); + } + + // Casts + + protected function pExpr_Cast_Int(Cast\Int_ $node) { + return $this->pPrefixOp(Cast\Int_::class, '(int) ', $node->expr); + } + + protected function pExpr_Cast_Double(Cast\Double $node) { + $kind = $node->getAttribute('kind', Cast\Double::KIND_DOUBLE); + if ($kind === Cast\Double::KIND_DOUBLE) { + $cast = '(double)'; + } elseif ($kind === Cast\Double::KIND_FLOAT) { + $cast = '(float)'; + } elseif ($kind === Cast\Double::KIND_REAL) { + $cast = '(real)'; + } + return $this->pPrefixOp(Cast\Double::class, $cast . ' ', $node->expr); + } + + protected function pExpr_Cast_String(Cast\String_ $node) { + return $this->pPrefixOp(Cast\String_::class, '(string) ', $node->expr); + } + + protected function pExpr_Cast_Array(Cast\Array_ $node) { + return $this->pPrefixOp(Cast\Array_::class, '(array) ', $node->expr); + } + + protected function pExpr_Cast_Object(Cast\Object_ $node) { + return $this->pPrefixOp(Cast\Object_::class, '(object) ', $node->expr); + } + + protected function pExpr_Cast_Bool(Cast\Bool_ $node) { + return $this->pPrefixOp(Cast\Bool_::class, '(bool) ', $node->expr); + } + + protected function pExpr_Cast_Unset(Cast\Unset_ $node) { + return $this->pPrefixOp(Cast\Unset_::class, '(unset) ', $node->expr); + } + + // Function calls and similar constructs + + protected function pExpr_FuncCall(Expr\FuncCall $node) { + return $this->pCallLhs($node->name) + . '(' . $this->pMaybeMultiline($node->args) . ')'; + } + + protected function pExpr_MethodCall(Expr\MethodCall $node) { + return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name) + . '(' . $this->pMaybeMultiline($node->args) . ')'; + } + + protected function pExpr_NullsafeMethodCall(Expr\NullsafeMethodCall $node) { + return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name) + . '(' . $this->pMaybeMultiline($node->args) . ')'; + } + + protected function pExpr_StaticCall(Expr\StaticCall $node) { + return $this->pDereferenceLhs($node->class) . '::' + . ($node->name instanceof Expr + ? ($node->name instanceof Expr\Variable + ? $this->p($node->name) + : '{' . $this->p($node->name) . '}') + : $node->name) + . '(' . $this->pMaybeMultiline($node->args) . ')'; + } + + protected function pExpr_Empty(Expr\Empty_ $node) { + return 'empty(' . $this->p($node->expr) . ')'; + } + + protected function pExpr_Isset(Expr\Isset_ $node) { + return 'isset(' . $this->pCommaSeparated($node->vars) . ')'; + } + + protected function pExpr_Eval(Expr\Eval_ $node) { + return 'eval(' . $this->p($node->expr) . ')'; + } + + protected function pExpr_Include(Expr\Include_ $node) { + static $map = [ + Expr\Include_::TYPE_INCLUDE => 'include', + Expr\Include_::TYPE_INCLUDE_ONCE => 'include_once', + Expr\Include_::TYPE_REQUIRE => 'require', + Expr\Include_::TYPE_REQUIRE_ONCE => 'require_once', + ]; + + return $map[$node->type] . ' ' . $this->p($node->expr); + } + + protected function pExpr_List(Expr\List_ $node) { + return 'list(' . $this->pCommaSeparated($node->items) . ')'; + } + + // Other + + protected function pExpr_Error(Expr\Error $node) { + throw new \LogicException('Cannot pretty-print AST with Error nodes'); + } + + protected function pExpr_Variable(Expr\Variable $node) { + if ($node->name instanceof Expr) { + return '${' . $this->p($node->name) . '}'; + } else { + return '$' . $node->name; + } + } + + protected function pExpr_Array(Expr\Array_ $node) { + $syntax = $node->getAttribute('kind', + $this->options['shortArraySyntax'] ? Expr\Array_::KIND_SHORT : Expr\Array_::KIND_LONG); + if ($syntax === Expr\Array_::KIND_SHORT) { + return '[' . $this->pMaybeMultiline($node->items, true) . ']'; + } else { + return 'array(' . $this->pMaybeMultiline($node->items, true) . ')'; + } + } + + protected function pExpr_ArrayItem(Expr\ArrayItem $node) { + return (null !== $node->key ? $this->p($node->key) . ' => ' : '') + . ($node->byRef ? '&' : '') + . ($node->unpack ? '...' : '') + . $this->p($node->value); + } + + protected function pExpr_ArrayDimFetch(Expr\ArrayDimFetch $node) { + return $this->pDereferenceLhs($node->var) + . '[' . (null !== $node->dim ? $this->p($node->dim) : '') . ']'; + } + + protected function pExpr_ConstFetch(Expr\ConstFetch $node) { + return $this->p($node->name); + } + + protected function pExpr_ClassConstFetch(Expr\ClassConstFetch $node) { + return $this->pDereferenceLhs($node->class) . '::' . $this->p($node->name); + } + + protected function pExpr_PropertyFetch(Expr\PropertyFetch $node) { + return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name); + } + + protected function pExpr_NullsafePropertyFetch(Expr\NullsafePropertyFetch $node) { + return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name); + } + + protected function pExpr_StaticPropertyFetch(Expr\StaticPropertyFetch $node) { + return $this->pDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name); + } + + protected function pExpr_ShellExec(Expr\ShellExec $node) { + return '`' . $this->pEncapsList($node->parts, '`') . '`'; + } + + protected function pExpr_Closure(Expr\Closure $node) { + return $this->pAttrGroups($node->attrGroups, true) + . ($node->static ? 'static ' : '') + . 'function ' . ($node->byRef ? '&' : '') + . '(' . $this->pCommaSeparated($node->params) . ')' + . (!empty($node->uses) ? ' use(' . $this->pCommaSeparated($node->uses) . ')' : '') + . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') + . ' {' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pExpr_Match(Expr\Match_ $node) { + return 'match (' . $this->p($node->cond) . ') {' + . $this->pCommaSeparatedMultiline($node->arms, true) + . $this->nl + . '}'; + } + + protected function pMatchArm(Node\MatchArm $node) { + return ($node->conds ? $this->pCommaSeparated($node->conds) : 'default') + . ' => ' . $this->p($node->body); + } + + protected function pExpr_ArrowFunction(Expr\ArrowFunction $node) { + return $this->pAttrGroups($node->attrGroups, true) + . ($node->static ? 'static ' : '') + . 'fn' . ($node->byRef ? '&' : '') + . '(' . $this->pCommaSeparated($node->params) . ')' + . (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '') + . ' => ' + . $this->p($node->expr); + } + + protected function pExpr_ClosureUse(Expr\ClosureUse $node) { + return ($node->byRef ? '&' : '') . $this->p($node->var); + } + + protected function pExpr_New(Expr\New_ $node) { + if ($node->class instanceof Stmt\Class_) { + $args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : ''; + return 'new ' . $this->pClassCommon($node->class, $args); + } + return 'new ' . $this->pNewVariable($node->class) + . '(' . $this->pMaybeMultiline($node->args) . ')'; + } + + protected function pExpr_Clone(Expr\Clone_ $node) { + return 'clone ' . $this->p($node->expr); + } + + protected function pExpr_Ternary(Expr\Ternary $node) { + // a bit of cheating: we treat the ternary as a binary op where the ?...: part is the operator. + // this is okay because the part between ? and : never needs parentheses. + return $this->pInfixOp(Expr\Ternary::class, + $node->cond, ' ?' . (null !== $node->if ? ' ' . $this->p($node->if) . ' ' : '') . ': ', $node->else + ); + } + + protected function pExpr_Exit(Expr\Exit_ $node) { + $kind = $node->getAttribute('kind', Expr\Exit_::KIND_DIE); + return ($kind === Expr\Exit_::KIND_EXIT ? 'exit' : 'die') + . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : ''); + } + + protected function pExpr_Throw(Expr\Throw_ $node) { + return 'throw ' . $this->p($node->expr); + } + + protected function pExpr_Yield(Expr\Yield_ $node) { + if ($node->value === null) { + return 'yield'; + } else { + // this is a bit ugly, but currently there is no way to detect whether the parentheses are necessary + return '(yield ' + . ($node->key !== null ? $this->p($node->key) . ' => ' : '') + . $this->p($node->value) + . ')'; + } + } + + // Declarations + + protected function pStmt_Namespace(Stmt\Namespace_ $node) { + if ($this->canUseSemicolonNamespaces) { + return 'namespace ' . $this->p($node->name) . ';' + . $this->nl . $this->pStmts($node->stmts, false); + } else { + return 'namespace' . (null !== $node->name ? ' ' . $this->p($node->name) : '') + . ' {' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + } + + protected function pStmt_Use(Stmt\Use_ $node) { + return 'use ' . $this->pUseType($node->type) + . $this->pCommaSeparated($node->uses) . ';'; + } + + protected function pStmt_GroupUse(Stmt\GroupUse $node) { + return 'use ' . $this->pUseType($node->type) . $this->pName($node->prefix) + . '\{' . $this->pCommaSeparated($node->uses) . '};'; + } + + protected function pStmt_UseUse(Stmt\UseUse $node) { + return $this->pUseType($node->type) . $this->p($node->name) + . (null !== $node->alias ? ' as ' . $node->alias : ''); + } + + protected function pUseType($type) { + return $type === Stmt\Use_::TYPE_FUNCTION ? 'function ' + : ($type === Stmt\Use_::TYPE_CONSTANT ? 'const ' : ''); + } + + protected function pStmt_Interface(Stmt\Interface_ $node) { + return $this->pAttrGroups($node->attrGroups) + . 'interface ' . $node->name + . (!empty($node->extends) ? ' extends ' . $this->pCommaSeparated($node->extends) : '') + . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Enum(Stmt\Enum_ $node) { + return $this->pAttrGroups($node->attrGroups) + . 'enum ' . $node->name + . ($node->scalarType ? " : $node->scalarType" : '') + . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') + . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Class(Stmt\Class_ $node) { + return $this->pClassCommon($node, ' ' . $node->name); + } + + protected function pStmt_Trait(Stmt\Trait_ $node) { + return $this->pAttrGroups($node->attrGroups) + . 'trait ' . $node->name + . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_EnumCase(Stmt\EnumCase $node) { + return $this->pAttrGroups($node->attrGroups) + . 'case ' . $node->name + . ($node->expr ? ' = ' . $this->p($node->expr) : '') + . ';'; + } + + protected function pStmt_TraitUse(Stmt\TraitUse $node) { + return 'use ' . $this->pCommaSeparated($node->traits) + . (empty($node->adaptations) + ? ';' + : ' {' . $this->pStmts($node->adaptations) . $this->nl . '}'); + } + + protected function pStmt_TraitUseAdaptation_Precedence(Stmt\TraitUseAdaptation\Precedence $node) { + return $this->p($node->trait) . '::' . $node->method + . ' insteadof ' . $this->pCommaSeparated($node->insteadof) . ';'; + } + + protected function pStmt_TraitUseAdaptation_Alias(Stmt\TraitUseAdaptation\Alias $node) { + return (null !== $node->trait ? $this->p($node->trait) . '::' : '') + . $node->method . ' as' + . (null !== $node->newModifier ? ' ' . rtrim($this->pModifiers($node->newModifier), ' ') : '') + . (null !== $node->newName ? ' ' . $node->newName : '') + . ';'; + } + + protected function pStmt_Property(Stmt\Property $node) { + return $this->pAttrGroups($node->attrGroups) + . (0 === $node->flags ? 'var ' : $this->pModifiers($node->flags)) + . ($node->type ? $this->p($node->type) . ' ' : '') + . $this->pCommaSeparated($node->props) . ';'; + } + + protected function pStmt_PropertyProperty(Stmt\PropertyProperty $node) { + return '$' . $node->name + . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); + } + + protected function pStmt_ClassMethod(Stmt\ClassMethod $node) { + return $this->pAttrGroups($node->attrGroups) + . $this->pModifiers($node->flags) + . 'function ' . ($node->byRef ? '&' : '') . $node->name + . '(' . $this->pMaybeMultiline($node->params) . ')' + . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') + . (null !== $node->stmts + ? $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}' + : ';'); + } + + protected function pStmt_ClassConst(Stmt\ClassConst $node) { + return $this->pAttrGroups($node->attrGroups) + . $this->pModifiers($node->flags) + . 'const ' . $this->pCommaSeparated($node->consts) . ';'; + } + + protected function pStmt_Function(Stmt\Function_ $node) { + return $this->pAttrGroups($node->attrGroups) + . 'function ' . ($node->byRef ? '&' : '') . $node->name + . '(' . $this->pCommaSeparated($node->params) . ')' + . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') + . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Const(Stmt\Const_ $node) { + return 'const ' . $this->pCommaSeparated($node->consts) . ';'; + } + + protected function pStmt_Declare(Stmt\Declare_ $node) { + return 'declare (' . $this->pCommaSeparated($node->declares) . ')' + . (null !== $node->stmts ? ' {' . $this->pStmts($node->stmts) . $this->nl . '}' : ';'); + } + + protected function pStmt_DeclareDeclare(Stmt\DeclareDeclare $node) { + return $node->key . '=' . $this->p($node->value); + } + + // Control flow + + protected function pStmt_If(Stmt\If_ $node) { + return 'if (' . $this->p($node->cond) . ') {' + . $this->pStmts($node->stmts) . $this->nl . '}' + . ($node->elseifs ? ' ' . $this->pImplode($node->elseifs, ' ') : '') + . (null !== $node->else ? ' ' . $this->p($node->else) : ''); + } + + protected function pStmt_ElseIf(Stmt\ElseIf_ $node) { + return 'elseif (' . $this->p($node->cond) . ') {' + . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Else(Stmt\Else_ $node) { + return 'else {' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_For(Stmt\For_ $node) { + return 'for (' + . $this->pCommaSeparated($node->init) . ';' . (!empty($node->cond) ? ' ' : '') + . $this->pCommaSeparated($node->cond) . ';' . (!empty($node->loop) ? ' ' : '') + . $this->pCommaSeparated($node->loop) + . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Foreach(Stmt\Foreach_ $node) { + return 'foreach (' . $this->p($node->expr) . ' as ' + . (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : '') + . ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {' + . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_While(Stmt\While_ $node) { + return 'while (' . $this->p($node->cond) . ') {' + . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Do(Stmt\Do_ $node) { + return 'do {' . $this->pStmts($node->stmts) . $this->nl + . '} while (' . $this->p($node->cond) . ');'; + } + + protected function pStmt_Switch(Stmt\Switch_ $node) { + return 'switch (' . $this->p($node->cond) . ') {' + . $this->pStmts($node->cases) . $this->nl . '}'; + } + + protected function pStmt_Case(Stmt\Case_ $node) { + return (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default') . ':' + . $this->pStmts($node->stmts); + } + + protected function pStmt_TryCatch(Stmt\TryCatch $node) { + return 'try {' . $this->pStmts($node->stmts) . $this->nl . '}' + . ($node->catches ? ' ' . $this->pImplode($node->catches, ' ') : '') + . ($node->finally !== null ? ' ' . $this->p($node->finally) : ''); + } + + protected function pStmt_Catch(Stmt\Catch_ $node) { + return 'catch (' . $this->pImplode($node->types, '|') + . ($node->var !== null ? ' ' . $this->p($node->var) : '') + . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Finally(Stmt\Finally_ $node) { + return 'finally {' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Break(Stmt\Break_ $node) { + return 'break' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; + } + + protected function pStmt_Continue(Stmt\Continue_ $node) { + return 'continue' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; + } + + protected function pStmt_Return(Stmt\Return_ $node) { + return 'return' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '') . ';'; + } + + protected function pStmt_Throw(Stmt\Throw_ $node) { + return 'throw ' . $this->p($node->expr) . ';'; + } + + protected function pStmt_Label(Stmt\Label $node) { + return $node->name . ':'; + } + + protected function pStmt_Goto(Stmt\Goto_ $node) { + return 'goto ' . $node->name . ';'; + } + + // Other + + protected function pStmt_Expression(Stmt\Expression $node) { + return $this->p($node->expr) . ';'; + } + + protected function pStmt_Echo(Stmt\Echo_ $node) { + return 'echo ' . $this->pCommaSeparated($node->exprs) . ';'; + } + + protected function pStmt_Static(Stmt\Static_ $node) { + return 'static ' . $this->pCommaSeparated($node->vars) . ';'; + } + + protected function pStmt_Global(Stmt\Global_ $node) { + return 'global ' . $this->pCommaSeparated($node->vars) . ';'; + } + + protected function pStmt_StaticVar(Stmt\StaticVar $node) { + return $this->p($node->var) + . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); + } + + protected function pStmt_Unset(Stmt\Unset_ $node) { + return 'unset(' . $this->pCommaSeparated($node->vars) . ');'; + } + + protected function pStmt_InlineHTML(Stmt\InlineHTML $node) { + $newline = $node->getAttribute('hasLeadingNewline', true) ? "\n" : ''; + return '?>' . $newline . $node->value . 'remaining; + } + + protected function pStmt_Nop(Stmt\Nop $node) { + return ''; + } + + // Helpers + + protected function pClassCommon(Stmt\Class_ $node, $afterClassToken) { + return $this->pAttrGroups($node->attrGroups, $node->name === null) + . $this->pModifiers($node->flags) + . 'class' . $afterClassToken + . (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '') + . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') + . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pObjectProperty($node) { + if ($node instanceof Expr) { + return '{' . $this->p($node) . '}'; + } else { + return $node; + } + } + + protected function pEncapsList(array $encapsList, $quote) { + $return = ''; + foreach ($encapsList as $element) { + if ($element instanceof Scalar\EncapsedStringPart) { + $return .= $this->escapeString($element->value, $quote); + } else { + $return .= '{' . $this->p($element) . '}'; + } + } + + return $return; + } + + protected function pSingleQuotedString(string $string) { + return '\'' . addcslashes($string, '\'\\') . '\''; + } + + protected function escapeString($string, $quote) { + if (null === $quote) { + // For doc strings, don't escape newlines + $escaped = addcslashes($string, "\t\f\v$\\"); + } else { + $escaped = addcslashes($string, "\n\r\t\f\v$" . $quote . "\\"); + } + + // Escape control characters and non-UTF-8 characters. + // Regex based on https://stackoverflow.com/a/11709412/385378. + $regex = '/( + [\x00-\x08\x0E-\x1F] # Control characters + | [\xC0-\xC1] # Invalid UTF-8 Bytes + | [\xF5-\xFF] # Invalid UTF-8 Bytes + | \xE0(?=[\x80-\x9F]) # Overlong encoding of prior code point + | \xF0(?=[\x80-\x8F]) # Overlong encoding of prior code point + | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start + | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start + | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start + | (?<=[\x00-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle + | (? $part) { + $atStart = $i === 0; + $atEnd = $i === count($parts) - 1; + if ($part instanceof Scalar\EncapsedStringPart + && $this->containsEndLabel($part->value, $label, $atStart, $atEnd) + ) { + return true; + } + } + return false; + } + + protected function pDereferenceLhs(Node $node) { + if (!$this->dereferenceLhsRequiresParens($node)) { + return $this->p($node); + } else { + return '(' . $this->p($node) . ')'; + } + } + + protected function pCallLhs(Node $node) { + if (!$this->callLhsRequiresParens($node)) { + return $this->p($node); + } else { + return '(' . $this->p($node) . ')'; + } + } + + protected function pNewVariable(Node $node) { + // TODO: This is not fully accurate. + return $this->pDereferenceLhs($node); + } + + /** + * @param Node[] $nodes + * @return bool + */ + protected function hasNodeWithComments(array $nodes) { + foreach ($nodes as $node) { + if ($node && $node->getComments()) { + return true; + } + } + return false; + } + + protected function pMaybeMultiline(array $nodes, bool $trailingComma = false) { + if (!$this->hasNodeWithComments($nodes)) { + return $this->pCommaSeparated($nodes); + } else { + return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . $this->nl; + } + } + + protected function pAttrGroups(array $nodes, bool $inline = false): string { + $result = ''; + $sep = $inline ? ' ' : $this->nl; + foreach ($nodes as $node) { + $result .= $this->p($node) . $sep; + } + + return $result; + } +} diff --git a/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php b/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php new file mode 100644 index 00000000..6ed936fe --- /dev/null +++ b/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php @@ -0,0 +1,1521 @@ + [ 0, 1], + Expr\BitwiseNot::class => [ 10, 1], + Expr\PreInc::class => [ 10, 1], + Expr\PreDec::class => [ 10, 1], + Expr\PostInc::class => [ 10, -1], + Expr\PostDec::class => [ 10, -1], + Expr\UnaryPlus::class => [ 10, 1], + Expr\UnaryMinus::class => [ 10, 1], + Cast\Int_::class => [ 10, 1], + Cast\Double::class => [ 10, 1], + Cast\String_::class => [ 10, 1], + Cast\Array_::class => [ 10, 1], + Cast\Object_::class => [ 10, 1], + Cast\Bool_::class => [ 10, 1], + Cast\Unset_::class => [ 10, 1], + Expr\ErrorSuppress::class => [ 10, 1], + Expr\Instanceof_::class => [ 20, 0], + Expr\BooleanNot::class => [ 30, 1], + BinaryOp\Mul::class => [ 40, -1], + BinaryOp\Div::class => [ 40, -1], + BinaryOp\Mod::class => [ 40, -1], + BinaryOp\Plus::class => [ 50, -1], + BinaryOp\Minus::class => [ 50, -1], + BinaryOp\Concat::class => [ 50, -1], + BinaryOp\ShiftLeft::class => [ 60, -1], + BinaryOp\ShiftRight::class => [ 60, -1], + BinaryOp\Smaller::class => [ 70, 0], + BinaryOp\SmallerOrEqual::class => [ 70, 0], + BinaryOp\Greater::class => [ 70, 0], + BinaryOp\GreaterOrEqual::class => [ 70, 0], + BinaryOp\Equal::class => [ 80, 0], + BinaryOp\NotEqual::class => [ 80, 0], + BinaryOp\Identical::class => [ 80, 0], + BinaryOp\NotIdentical::class => [ 80, 0], + BinaryOp\Spaceship::class => [ 80, 0], + BinaryOp\BitwiseAnd::class => [ 90, -1], + BinaryOp\BitwiseXor::class => [100, -1], + BinaryOp\BitwiseOr::class => [110, -1], + BinaryOp\BooleanAnd::class => [120, -1], + BinaryOp\BooleanOr::class => [130, -1], + BinaryOp\Coalesce::class => [140, 1], + Expr\Ternary::class => [150, 0], + // parser uses %left for assignments, but they really behave as %right + Expr\Assign::class => [160, 1], + Expr\AssignRef::class => [160, 1], + AssignOp\Plus::class => [160, 1], + AssignOp\Minus::class => [160, 1], + AssignOp\Mul::class => [160, 1], + AssignOp\Div::class => [160, 1], + AssignOp\Concat::class => [160, 1], + AssignOp\Mod::class => [160, 1], + AssignOp\BitwiseAnd::class => [160, 1], + AssignOp\BitwiseOr::class => [160, 1], + AssignOp\BitwiseXor::class => [160, 1], + AssignOp\ShiftLeft::class => [160, 1], + AssignOp\ShiftRight::class => [160, 1], + AssignOp\Pow::class => [160, 1], + AssignOp\Coalesce::class => [160, 1], + Expr\YieldFrom::class => [165, 1], + Expr\Print_::class => [168, 1], + BinaryOp\LogicalAnd::class => [170, -1], + BinaryOp\LogicalXor::class => [180, -1], + BinaryOp\LogicalOr::class => [190, -1], + Expr\Include_::class => [200, -1], + ]; + + /** @var int Current indentation level. */ + protected $indentLevel; + /** @var string Newline including current indentation. */ + protected $nl; + /** @var string Token placed at end of doc string to ensure it is followed by a newline. */ + protected $docStringEndToken; + /** @var bool Whether semicolon namespaces can be used (i.e. no global namespace is used) */ + protected $canUseSemicolonNamespaces; + /** @var array Pretty printer options */ + protected $options; + + /** @var TokenStream Original tokens for use in format-preserving pretty print */ + protected $origTokens; + /** @var Internal\Differ Differ for node lists */ + protected $nodeListDiffer; + /** @var bool[] Map determining whether a certain character is a label character */ + protected $labelCharMap; + /** + * @var int[][] Map from token classes and subnode names to FIXUP_* constants. This is used + * during format-preserving prints to place additional parens/braces if necessary. + */ + protected $fixupMap; + /** + * @var int[][] Map from "{$node->getType()}->{$subNode}" to ['left' => $l, 'right' => $r], + * where $l and $r specify the token type that needs to be stripped when removing + * this node. + */ + protected $removalMap; + /** + * @var mixed[] Map from "{$node->getType()}->{$subNode}" to [$find, $beforeToken, $extraLeft, $extraRight]. + * $find is an optional token after which the insertion occurs. $extraLeft/Right + * are optionally added before/after the main insertions. + */ + protected $insertionMap; + /** + * @var string[] Map From "{$node->getType()}->{$subNode}" to string that should be inserted + * between elements of this list subnode. + */ + protected $listInsertionMap; + protected $emptyListInsertionMap; + /** @var int[] Map from "{$node->getType()}->{$subNode}" to token before which the modifiers + * should be reprinted. */ + protected $modifierChangeMap; + + /** + * Creates a pretty printer instance using the given options. + * + * Supported options: + * * bool $shortArraySyntax = false: Whether to use [] instead of array() as the default array + * syntax, if the node does not specify a format. + * + * @param array $options Dictionary of formatting options + */ + public function __construct(array $options = []) { + $this->docStringEndToken = '_DOC_STRING_END_' . mt_rand(); + + $defaultOptions = ['shortArraySyntax' => false]; + $this->options = $options + $defaultOptions; + } + + /** + * Reset pretty printing state. + */ + protected function resetState() { + $this->indentLevel = 0; + $this->nl = "\n"; + $this->origTokens = null; + } + + /** + * Set indentation level + * + * @param int $level Level in number of spaces + */ + protected function setIndentLevel(int $level) { + $this->indentLevel = $level; + $this->nl = "\n" . \str_repeat(' ', $level); + } + + /** + * Increase indentation level. + */ + protected function indent() { + $this->indentLevel += 4; + $this->nl .= ' '; + } + + /** + * Decrease indentation level. + */ + protected function outdent() { + assert($this->indentLevel >= 4); + $this->indentLevel -= 4; + $this->nl = "\n" . str_repeat(' ', $this->indentLevel); + } + + /** + * Pretty prints an array of statements. + * + * @param Node[] $stmts Array of statements + * + * @return string Pretty printed statements + */ + public function prettyPrint(array $stmts) : string { + $this->resetState(); + $this->preprocessNodes($stmts); + + return ltrim($this->handleMagicTokens($this->pStmts($stmts, false))); + } + + /** + * Pretty prints an expression. + * + * @param Expr $node Expression node + * + * @return string Pretty printed node + */ + public function prettyPrintExpr(Expr $node) : string { + $this->resetState(); + return $this->handleMagicTokens($this->p($node)); + } + + /** + * Pretty prints a file of statements (includes the opening prettyPrint($stmts); + + if ($stmts[0] instanceof Stmt\InlineHTML) { + $p = preg_replace('/^<\?php\s+\?>\n?/', '', $p); + } + if ($stmts[count($stmts) - 1] instanceof Stmt\InlineHTML) { + $p = preg_replace('/<\?php$/', '', rtrim($p)); + } + + return $p; + } + + /** + * Preprocesses the top-level nodes to initialize pretty printer state. + * + * @param Node[] $nodes Array of nodes + */ + protected function preprocessNodes(array $nodes) { + /* We can use semicolon-namespaces unless there is a global namespace declaration */ + $this->canUseSemicolonNamespaces = true; + foreach ($nodes as $node) { + if ($node instanceof Stmt\Namespace_ && null === $node->name) { + $this->canUseSemicolonNamespaces = false; + break; + } + } + } + + /** + * Handles (and removes) no-indent and doc-string-end tokens. + * + * @param string $str + * @return string + */ + protected function handleMagicTokens(string $str) : string { + // Replace doc-string-end tokens with nothing or a newline + $str = str_replace($this->docStringEndToken . ";\n", ";\n", $str); + $str = str_replace($this->docStringEndToken, "\n", $str); + + return $str; + } + + /** + * Pretty prints an array of nodes (statements) and indents them optionally. + * + * @param Node[] $nodes Array of nodes + * @param bool $indent Whether to indent the printed nodes + * + * @return string Pretty printed statements + */ + protected function pStmts(array $nodes, bool $indent = true) : string { + if ($indent) { + $this->indent(); + } + + $result = ''; + foreach ($nodes as $node) { + $comments = $node->getComments(); + if ($comments) { + $result .= $this->nl . $this->pComments($comments); + if ($node instanceof Stmt\Nop) { + continue; + } + } + + $result .= $this->nl . $this->p($node); + } + + if ($indent) { + $this->outdent(); + } + + return $result; + } + + /** + * Pretty-print an infix operation while taking precedence into account. + * + * @param string $class Node class of operator + * @param Node $leftNode Left-hand side node + * @param string $operatorString String representation of the operator + * @param Node $rightNode Right-hand side node + * + * @return string Pretty printed infix operation + */ + protected function pInfixOp(string $class, Node $leftNode, string $operatorString, Node $rightNode) : string { + list($precedence, $associativity) = $this->precedenceMap[$class]; + + return $this->pPrec($leftNode, $precedence, $associativity, -1) + . $operatorString + . $this->pPrec($rightNode, $precedence, $associativity, 1); + } + + /** + * Pretty-print a prefix operation while taking precedence into account. + * + * @param string $class Node class of operator + * @param string $operatorString String representation of the operator + * @param Node $node Node + * + * @return string Pretty printed prefix operation + */ + protected function pPrefixOp(string $class, string $operatorString, Node $node) : string { + list($precedence, $associativity) = $this->precedenceMap[$class]; + return $operatorString . $this->pPrec($node, $precedence, $associativity, 1); + } + + /** + * Pretty-print a postfix operation while taking precedence into account. + * + * @param string $class Node class of operator + * @param string $operatorString String representation of the operator + * @param Node $node Node + * + * @return string Pretty printed postfix operation + */ + protected function pPostfixOp(string $class, Node $node, string $operatorString) : string { + list($precedence, $associativity) = $this->precedenceMap[$class]; + return $this->pPrec($node, $precedence, $associativity, -1) . $operatorString; + } + + /** + * Prints an expression node with the least amount of parentheses necessary to preserve the meaning. + * + * @param Node $node Node to pretty print + * @param int $parentPrecedence Precedence of the parent operator + * @param int $parentAssociativity Associativity of parent operator + * (-1 is left, 0 is nonassoc, 1 is right) + * @param int $childPosition Position of the node relative to the operator + * (-1 is left, 1 is right) + * + * @return string The pretty printed node + */ + protected function pPrec(Node $node, int $parentPrecedence, int $parentAssociativity, int $childPosition) : string { + $class = \get_class($node); + if (isset($this->precedenceMap[$class])) { + $childPrecedence = $this->precedenceMap[$class][0]; + if ($childPrecedence > $parentPrecedence + || ($parentPrecedence === $childPrecedence && $parentAssociativity !== $childPosition) + ) { + return '(' . $this->p($node) . ')'; + } + } + + return $this->p($node); + } + + /** + * Pretty prints an array of nodes and implodes the printed values. + * + * @param Node[] $nodes Array of Nodes to be printed + * @param string $glue Character to implode with + * + * @return string Imploded pretty printed nodes + */ + protected function pImplode(array $nodes, string $glue = '') : string { + $pNodes = []; + foreach ($nodes as $node) { + if (null === $node) { + $pNodes[] = ''; + } else { + $pNodes[] = $this->p($node); + } + } + + return implode($glue, $pNodes); + } + + /** + * Pretty prints an array of nodes and implodes the printed values with commas. + * + * @param Node[] $nodes Array of Nodes to be printed + * + * @return string Comma separated pretty printed nodes + */ + protected function pCommaSeparated(array $nodes) : string { + return $this->pImplode($nodes, ', '); + } + + /** + * Pretty prints a comma-separated list of nodes in multiline style, including comments. + * + * The result includes a leading newline and one level of indentation (same as pStmts). + * + * @param Node[] $nodes Array of Nodes to be printed + * @param bool $trailingComma Whether to use a trailing comma + * + * @return string Comma separated pretty printed nodes in multiline style + */ + protected function pCommaSeparatedMultiline(array $nodes, bool $trailingComma) : string { + $this->indent(); + + $result = ''; + $lastIdx = count($nodes) - 1; + foreach ($nodes as $idx => $node) { + if ($node !== null) { + $comments = $node->getComments(); + if ($comments) { + $result .= $this->nl . $this->pComments($comments); + } + + $result .= $this->nl . $this->p($node); + } else { + $result .= $this->nl; + } + if ($trailingComma || $idx !== $lastIdx) { + $result .= ','; + } + } + + $this->outdent(); + return $result; + } + + /** + * Prints reformatted text of the passed comments. + * + * @param Comment[] $comments List of comments + * + * @return string Reformatted text of comments + */ + protected function pComments(array $comments) : string { + $formattedComments = []; + + foreach ($comments as $comment) { + $formattedComments[] = str_replace("\n", $this->nl, $comment->getReformattedText()); + } + + return implode($this->nl, $formattedComments); + } + + /** + * Perform a format-preserving pretty print of an AST. + * + * The format preservation is best effort. For some changes to the AST the formatting will not + * be preserved (at least not locally). + * + * In order to use this method a number of prerequisites must be satisfied: + * * The startTokenPos and endTokenPos attributes in the lexer must be enabled. + * * The CloningVisitor must be run on the AST prior to modification. + * * The original tokens must be provided, using the getTokens() method on the lexer. + * + * @param Node[] $stmts Modified AST with links to original AST + * @param Node[] $origStmts Original AST with token offset information + * @param array $origTokens Tokens of the original code + * + * @return string + */ + public function printFormatPreserving(array $stmts, array $origStmts, array $origTokens) : string { + $this->initializeNodeListDiffer(); + $this->initializeLabelCharMap(); + $this->initializeFixupMap(); + $this->initializeRemovalMap(); + $this->initializeInsertionMap(); + $this->initializeListInsertionMap(); + $this->initializeEmptyListInsertionMap(); + $this->initializeModifierChangeMap(); + + $this->resetState(); + $this->origTokens = new TokenStream($origTokens); + + $this->preprocessNodes($stmts); + + $pos = 0; + $result = $this->pArray($stmts, $origStmts, $pos, 0, 'File', 'stmts', null); + if (null !== $result) { + $result .= $this->origTokens->getTokenCode($pos, count($origTokens), 0); + } else { + // Fallback + // TODO Add pStmts($stmts, false); + } + + return ltrim($this->handleMagicTokens($result)); + } + + protected function pFallback(Node $node) { + return $this->{'p' . $node->getType()}($node); + } + + /** + * Pretty prints a node. + * + * This method also handles formatting preservation for nodes. + * + * @param Node $node Node to be pretty printed + * @param bool $parentFormatPreserved Whether parent node has preserved formatting + * + * @return string Pretty printed node + */ + protected function p(Node $node, $parentFormatPreserved = false) : string { + // No orig tokens means this is a normal pretty print without preservation of formatting + if (!$this->origTokens) { + return $this->{'p' . $node->getType()}($node); + } + + /** @var Node $origNode */ + $origNode = $node->getAttribute('origNode'); + if (null === $origNode) { + return $this->pFallback($node); + } + + $class = \get_class($node); + \assert($class === \get_class($origNode)); + + $startPos = $origNode->getStartTokenPos(); + $endPos = $origNode->getEndTokenPos(); + \assert($startPos >= 0 && $endPos >= 0); + + $fallbackNode = $node; + if ($node instanceof Expr\New_ && $node->class instanceof Stmt\Class_) { + // Normalize node structure of anonymous classes + $node = PrintableNewAnonClassNode::fromNewNode($node); + $origNode = PrintableNewAnonClassNode::fromNewNode($origNode); + } + + // InlineHTML node does not contain closing and opening PHP tags. If the parent formatting + // is not preserved, then we need to use the fallback code to make sure the tags are + // printed. + if ($node instanceof Stmt\InlineHTML && !$parentFormatPreserved) { + return $this->pFallback($fallbackNode); + } + + $indentAdjustment = $this->indentLevel - $this->origTokens->getIndentationBefore($startPos); + + $type = $node->getType(); + $fixupInfo = $this->fixupMap[$class] ?? null; + + $result = ''; + $pos = $startPos; + foreach ($node->getSubNodeNames() as $subNodeName) { + $subNode = $node->$subNodeName; + $origSubNode = $origNode->$subNodeName; + + if ((!$subNode instanceof Node && $subNode !== null) + || (!$origSubNode instanceof Node && $origSubNode !== null) + ) { + if ($subNode === $origSubNode) { + // Unchanged, can reuse old code + continue; + } + + if (is_array($subNode) && is_array($origSubNode)) { + // Array subnode changed, we might be able to reconstruct it + $listResult = $this->pArray( + $subNode, $origSubNode, $pos, $indentAdjustment, $type, $subNodeName, + $fixupInfo[$subNodeName] ?? null + ); + if (null === $listResult) { + return $this->pFallback($fallbackNode); + } + + $result .= $listResult; + continue; + } + + if (is_int($subNode) && is_int($origSubNode)) { + // Check if this is a modifier change + $key = $type . '->' . $subNodeName; + if (!isset($this->modifierChangeMap[$key])) { + return $this->pFallback($fallbackNode); + } + + $findToken = $this->modifierChangeMap[$key]; + $result .= $this->pModifiers($subNode); + $pos = $this->origTokens->findRight($pos, $findToken); + continue; + } + + // If a non-node, non-array subnode changed, we don't be able to do a partial + // reconstructions, as we don't have enough offset information. Pretty print the + // whole node instead. + return $this->pFallback($fallbackNode); + } + + $extraLeft = ''; + $extraRight = ''; + if ($origSubNode !== null) { + $subStartPos = $origSubNode->getStartTokenPos(); + $subEndPos = $origSubNode->getEndTokenPos(); + \assert($subStartPos >= 0 && $subEndPos >= 0); + } else { + if ($subNode === null) { + // Both null, nothing to do + continue; + } + + // A node has been inserted, check if we have insertion information for it + $key = $type . '->' . $subNodeName; + if (!isset($this->insertionMap[$key])) { + return $this->pFallback($fallbackNode); + } + + list($findToken, $beforeToken, $extraLeft, $extraRight) = $this->insertionMap[$key]; + if (null !== $findToken) { + $subStartPos = $this->origTokens->findRight($pos, $findToken) + + (int) !$beforeToken; + } else { + $subStartPos = $pos; + } + + if (null === $extraLeft && null !== $extraRight) { + // If inserting on the right only, skipping whitespace looks better + $subStartPos = $this->origTokens->skipRightWhitespace($subStartPos); + } + $subEndPos = $subStartPos - 1; + } + + if (null === $subNode) { + // A node has been removed, check if we have removal information for it + $key = $type . '->' . $subNodeName; + if (!isset($this->removalMap[$key])) { + return $this->pFallback($fallbackNode); + } + + // Adjust positions to account for additional tokens that must be skipped + $removalInfo = $this->removalMap[$key]; + if (isset($removalInfo['left'])) { + $subStartPos = $this->origTokens->skipLeft($subStartPos - 1, $removalInfo['left']) + 1; + } + if (isset($removalInfo['right'])) { + $subEndPos = $this->origTokens->skipRight($subEndPos + 1, $removalInfo['right']) - 1; + } + } + + $result .= $this->origTokens->getTokenCode($pos, $subStartPos, $indentAdjustment); + + if (null !== $subNode) { + $result .= $extraLeft; + + $origIndentLevel = $this->indentLevel; + $this->setIndentLevel($this->origTokens->getIndentationBefore($subStartPos) + $indentAdjustment); + + // If it's the same node that was previously in this position, it certainly doesn't + // need fixup. It's important to check this here, because our fixup checks are more + // conservative than strictly necessary. + if (isset($fixupInfo[$subNodeName]) + && $subNode->getAttribute('origNode') !== $origSubNode + ) { + $fixup = $fixupInfo[$subNodeName]; + $res = $this->pFixup($fixup, $subNode, $class, $subStartPos, $subEndPos); + } else { + $res = $this->p($subNode, true); + } + + $this->safeAppend($result, $res); + $this->setIndentLevel($origIndentLevel); + + $result .= $extraRight; + } + + $pos = $subEndPos + 1; + } + + $result .= $this->origTokens->getTokenCode($pos, $endPos + 1, $indentAdjustment); + return $result; + } + + /** + * Perform a format-preserving pretty print of an array. + * + * @param array $nodes New nodes + * @param array $origNodes Original nodes + * @param int $pos Current token position (updated by reference) + * @param int $indentAdjustment Adjustment for indentation + * @param string $parentNodeType Type of the containing node. + * @param string $subNodeName Name of array subnode. + * @param null|int $fixup Fixup information for array item nodes + * + * @return null|string Result of pretty print or null if cannot preserve formatting + */ + protected function pArray( + array $nodes, array $origNodes, int &$pos, int $indentAdjustment, + string $parentNodeType, string $subNodeName, $fixup + ) { + $diff = $this->nodeListDiffer->diffWithReplacements($origNodes, $nodes); + + $mapKey = $parentNodeType . '->' . $subNodeName; + $insertStr = $this->listInsertionMap[$mapKey] ?? null; + $isStmtList = $subNodeName === 'stmts'; + + $beforeFirstKeepOrReplace = true; + $skipRemovedNode = false; + $delayedAdd = []; + $lastElemIndentLevel = $this->indentLevel; + + $insertNewline = false; + if ($insertStr === "\n") { + $insertStr = ''; + $insertNewline = true; + } + + if ($isStmtList && \count($origNodes) === 1 && \count($nodes) !== 1) { + $startPos = $origNodes[0]->getStartTokenPos(); + $endPos = $origNodes[0]->getEndTokenPos(); + \assert($startPos >= 0 && $endPos >= 0); + if (!$this->origTokens->haveBraces($startPos, $endPos)) { + // This was a single statement without braces, but either additional statements + // have been added, or the single statement has been removed. This requires the + // addition of braces. For now fall back. + // TODO: Try to preserve formatting + return null; + } + } + + $result = ''; + foreach ($diff as $i => $diffElem) { + $diffType = $diffElem->type; + /** @var Node|null $arrItem */ + $arrItem = $diffElem->new; + /** @var Node|null $origArrItem */ + $origArrItem = $diffElem->old; + + if ($diffType === DiffElem::TYPE_KEEP || $diffType === DiffElem::TYPE_REPLACE) { + $beforeFirstKeepOrReplace = false; + + if ($origArrItem === null || $arrItem === null) { + // We can only handle the case where both are null + if ($origArrItem === $arrItem) { + continue; + } + return null; + } + + if (!$arrItem instanceof Node || !$origArrItem instanceof Node) { + // We can only deal with nodes. This can occur for Names, which use string arrays. + return null; + } + + $itemStartPos = $origArrItem->getStartTokenPos(); + $itemEndPos = $origArrItem->getEndTokenPos(); + \assert($itemStartPos >= 0 && $itemEndPos >= 0 && $itemStartPos >= $pos); + + $origIndentLevel = $this->indentLevel; + $lastElemIndentLevel = $this->origTokens->getIndentationBefore($itemStartPos) + $indentAdjustment; + $this->setIndentLevel($lastElemIndentLevel); + + $comments = $arrItem->getComments(); + $origComments = $origArrItem->getComments(); + $commentStartPos = $origComments ? $origComments[0]->getStartTokenPos() : $itemStartPos; + \assert($commentStartPos >= 0); + + if ($commentStartPos < $pos) { + // Comments may be assigned to multiple nodes if they start at the same position. + // Make sure we don't try to print them multiple times. + $commentStartPos = $itemStartPos; + } + + if ($skipRemovedNode) { + if ($isStmtList && ($this->origTokens->haveBracesInRange($pos, $itemStartPos) || + $this->origTokens->haveTagInRange($pos, $itemStartPos))) { + // We'd remove the brace of a code block. + // TODO: Preserve formatting. + $this->setIndentLevel($origIndentLevel); + return null; + } + } else { + $result .= $this->origTokens->getTokenCode( + $pos, $commentStartPos, $indentAdjustment); + } + + if (!empty($delayedAdd)) { + /** @var Node $delayedAddNode */ + foreach ($delayedAdd as $delayedAddNode) { + if ($insertNewline) { + $delayedAddComments = $delayedAddNode->getComments(); + if ($delayedAddComments) { + $result .= $this->pComments($delayedAddComments) . $this->nl; + } + } + + $this->safeAppend($result, $this->p($delayedAddNode, true)); + + if ($insertNewline) { + $result .= $insertStr . $this->nl; + } else { + $result .= $insertStr; + } + } + + $delayedAdd = []; + } + + if ($comments !== $origComments) { + if ($comments) { + $result .= $this->pComments($comments) . $this->nl; + } + } else { + $result .= $this->origTokens->getTokenCode( + $commentStartPos, $itemStartPos, $indentAdjustment); + } + + // If we had to remove anything, we have done so now. + $skipRemovedNode = false; + } elseif ($diffType === DiffElem::TYPE_ADD) { + if (null === $insertStr) { + // We don't have insertion information for this list type + return null; + } + + // We go multiline if the original code was multiline, + // or if it's an array item with a comment above it. + if ($insertStr === ', ' && + ($this->isMultiline($origNodes) || $arrItem->getComments()) + ) { + $insertStr = ','; + $insertNewline = true; + } + + if ($beforeFirstKeepOrReplace) { + // Will be inserted at the next "replace" or "keep" element + $delayedAdd[] = $arrItem; + continue; + } + + $itemStartPos = $pos; + $itemEndPos = $pos - 1; + + $origIndentLevel = $this->indentLevel; + $this->setIndentLevel($lastElemIndentLevel); + + if ($insertNewline) { + $result .= $insertStr . $this->nl; + $comments = $arrItem->getComments(); + if ($comments) { + $result .= $this->pComments($comments) . $this->nl; + } + } else { + $result .= $insertStr; + } + } elseif ($diffType === DiffElem::TYPE_REMOVE) { + if (!$origArrItem instanceof Node) { + // We only support removal for nodes + return null; + } + + $itemStartPos = $origArrItem->getStartTokenPos(); + $itemEndPos = $origArrItem->getEndTokenPos(); + \assert($itemStartPos >= 0 && $itemEndPos >= 0); + + // Consider comments part of the node. + $origComments = $origArrItem->getComments(); + if ($origComments) { + $itemStartPos = $origComments[0]->getStartTokenPos(); + } + + if ($i === 0) { + // If we're removing from the start, keep the tokens before the node and drop those after it, + // instead of the other way around. + $result .= $this->origTokens->getTokenCode( + $pos, $itemStartPos, $indentAdjustment); + $skipRemovedNode = true; + } else { + if ($isStmtList && ($this->origTokens->haveBracesInRange($pos, $itemStartPos) || + $this->origTokens->haveTagInRange($pos, $itemStartPos))) { + // We'd remove the brace of a code block. + // TODO: Preserve formatting. + return null; + } + } + + $pos = $itemEndPos + 1; + continue; + } else { + throw new \Exception("Shouldn't happen"); + } + + if (null !== $fixup && $arrItem->getAttribute('origNode') !== $origArrItem) { + $res = $this->pFixup($fixup, $arrItem, null, $itemStartPos, $itemEndPos); + } else { + $res = $this->p($arrItem, true); + } + $this->safeAppend($result, $res); + + $this->setIndentLevel($origIndentLevel); + $pos = $itemEndPos + 1; + } + + if ($skipRemovedNode) { + // TODO: Support removing single node. + return null; + } + + if (!empty($delayedAdd)) { + if (!isset($this->emptyListInsertionMap[$mapKey])) { + return null; + } + + list($findToken, $extraLeft, $extraRight) = $this->emptyListInsertionMap[$mapKey]; + if (null !== $findToken) { + $insertPos = $this->origTokens->findRight($pos, $findToken) + 1; + $result .= $this->origTokens->getTokenCode($pos, $insertPos, $indentAdjustment); + $pos = $insertPos; + } + + $first = true; + $result .= $extraLeft; + foreach ($delayedAdd as $delayedAddNode) { + if (!$first) { + $result .= $insertStr; + if ($insertNewline) { + $result .= $this->nl; + } + } + $result .= $this->p($delayedAddNode, true); + $first = false; + } + $result .= $extraRight === "\n" ? $this->nl : $extraRight; + } + + return $result; + } + + /** + * Print node with fixups. + * + * Fixups here refer to the addition of extra parentheses, braces or other characters, that + * are required to preserve program semantics in a certain context (e.g. to maintain precedence + * or because only certain expressions are allowed in certain places). + * + * @param int $fixup Fixup type + * @param Node $subNode Subnode to print + * @param string|null $parentClass Class of parent node + * @param int $subStartPos Original start pos of subnode + * @param int $subEndPos Original end pos of subnode + * + * @return string Result of fixed-up print of subnode + */ + protected function pFixup(int $fixup, Node $subNode, $parentClass, int $subStartPos, int $subEndPos) : string { + switch ($fixup) { + case self::FIXUP_PREC_LEFT: + case self::FIXUP_PREC_RIGHT: + if (!$this->origTokens->haveParens($subStartPos, $subEndPos)) { + list($precedence, $associativity) = $this->precedenceMap[$parentClass]; + return $this->pPrec($subNode, $precedence, $associativity, + $fixup === self::FIXUP_PREC_LEFT ? -1 : 1); + } + break; + case self::FIXUP_CALL_LHS: + if ($this->callLhsRequiresParens($subNode) + && !$this->origTokens->haveParens($subStartPos, $subEndPos) + ) { + return '(' . $this->p($subNode) . ')'; + } + break; + case self::FIXUP_DEREF_LHS: + if ($this->dereferenceLhsRequiresParens($subNode) + && !$this->origTokens->haveParens($subStartPos, $subEndPos) + ) { + return '(' . $this->p($subNode) . ')'; + } + break; + case self::FIXUP_BRACED_NAME: + case self::FIXUP_VAR_BRACED_NAME: + if ($subNode instanceof Expr + && !$this->origTokens->haveBraces($subStartPos, $subEndPos) + ) { + return ($fixup === self::FIXUP_VAR_BRACED_NAME ? '$' : '') + . '{' . $this->p($subNode) . '}'; + } + break; + case self::FIXUP_ENCAPSED: + if (!$subNode instanceof Scalar\EncapsedStringPart + && !$this->origTokens->haveBraces($subStartPos, $subEndPos) + ) { + return '{' . $this->p($subNode) . '}'; + } + break; + default: + throw new \Exception('Cannot happen'); + } + + // Nothing special to do + return $this->p($subNode); + } + + /** + * Appends to a string, ensuring whitespace between label characters. + * + * Example: "echo" and "$x" result in "echo$x", but "echo" and "x" result in "echo x". + * Without safeAppend the result would be "echox", which does not preserve semantics. + * + * @param string $str + * @param string $append + */ + protected function safeAppend(string &$str, string $append) { + if ($str === "") { + $str = $append; + return; + } + + if ($append === "") { + return; + } + + if (!$this->labelCharMap[$append[0]] + || !$this->labelCharMap[$str[\strlen($str) - 1]]) { + $str .= $append; + } else { + $str .= " " . $append; + } + } + + /** + * Determines whether the LHS of a call must be wrapped in parenthesis. + * + * @param Node $node LHS of a call + * + * @return bool Whether parentheses are required + */ + protected function callLhsRequiresParens(Node $node) : bool { + return !($node instanceof Node\Name + || $node instanceof Expr\Variable + || $node instanceof Expr\ArrayDimFetch + || $node instanceof Expr\FuncCall + || $node instanceof Expr\MethodCall + || $node instanceof Expr\NullsafeMethodCall + || $node instanceof Expr\StaticCall + || $node instanceof Expr\Array_); + } + + /** + * Determines whether the LHS of a dereferencing operation must be wrapped in parenthesis. + * + * @param Node $node LHS of dereferencing operation + * + * @return bool Whether parentheses are required + */ + protected function dereferenceLhsRequiresParens(Node $node) : bool { + return !($node instanceof Expr\Variable + || $node instanceof Node\Name + || $node instanceof Expr\ArrayDimFetch + || $node instanceof Expr\PropertyFetch + || $node instanceof Expr\NullsafePropertyFetch + || $node instanceof Expr\StaticPropertyFetch + || $node instanceof Expr\FuncCall + || $node instanceof Expr\MethodCall + || $node instanceof Expr\NullsafeMethodCall + || $node instanceof Expr\StaticCall + || $node instanceof Expr\Array_ + || $node instanceof Scalar\String_ + || $node instanceof Expr\ConstFetch + || $node instanceof Expr\ClassConstFetch); + } + + /** + * Print modifiers, including trailing whitespace. + * + * @param int $modifiers Modifier mask to print + * + * @return string Printed modifiers + */ + protected function pModifiers(int $modifiers) { + return ($modifiers & Stmt\Class_::MODIFIER_PUBLIC ? 'public ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_PROTECTED ? 'protected ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_PRIVATE ? 'private ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_STATIC ? 'static ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_ABSTRACT ? 'abstract ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_FINAL ? 'final ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_READONLY ? 'readonly ' : ''); + } + + /** + * Determine whether a list of nodes uses multiline formatting. + * + * @param (Node|null)[] $nodes Node list + * + * @return bool Whether multiline formatting is used + */ + protected function isMultiline(array $nodes) : bool { + if (\count($nodes) < 2) { + return false; + } + + $pos = -1; + foreach ($nodes as $node) { + if (null === $node) { + continue; + } + + $endPos = $node->getEndTokenPos() + 1; + if ($pos >= 0) { + $text = $this->origTokens->getTokenCode($pos, $endPos, 0); + if (false === strpos($text, "\n")) { + // We require that a newline is present between *every* item. If the formatting + // is inconsistent, with only some items having newlines, we don't consider it + // as multiline + return false; + } + } + $pos = $endPos; + } + + return true; + } + + /** + * Lazily initializes label char map. + * + * The label char map determines whether a certain character may occur in a label. + */ + protected function initializeLabelCharMap() { + if ($this->labelCharMap) return; + + $this->labelCharMap = []; + for ($i = 0; $i < 256; $i++) { + // Since PHP 7.1 The lower range is 0x80. However, we also want to support code for + // older versions. + $chr = chr($i); + $this->labelCharMap[$chr] = $i >= 0x7f || ctype_alnum($chr); + } + } + + /** + * Lazily initializes node list differ. + * + * The node list differ is used to determine differences between two array subnodes. + */ + protected function initializeNodeListDiffer() { + if ($this->nodeListDiffer) return; + + $this->nodeListDiffer = new Internal\Differ(function ($a, $b) { + if ($a instanceof Node && $b instanceof Node) { + return $a === $b->getAttribute('origNode'); + } + // Can happen for array destructuring + return $a === null && $b === null; + }); + } + + /** + * Lazily initializes fixup map. + * + * The fixup map is used to determine whether a certain subnode of a certain node may require + * some kind of "fixup" operation, e.g. the addition of parenthesis or braces. + */ + protected function initializeFixupMap() { + if ($this->fixupMap) return; + + $this->fixupMap = [ + Expr\PreInc::class => ['var' => self::FIXUP_PREC_RIGHT], + Expr\PreDec::class => ['var' => self::FIXUP_PREC_RIGHT], + Expr\PostInc::class => ['var' => self::FIXUP_PREC_LEFT], + Expr\PostDec::class => ['var' => self::FIXUP_PREC_LEFT], + Expr\Instanceof_::class => [ + 'expr' => self::FIXUP_PREC_LEFT, + 'class' => self::FIXUP_PREC_RIGHT, // TODO: FIXUP_NEW_VARIABLE + ], + Expr\Ternary::class => [ + 'cond' => self::FIXUP_PREC_LEFT, + 'else' => self::FIXUP_PREC_RIGHT, + ], + + Expr\FuncCall::class => ['name' => self::FIXUP_CALL_LHS], + Expr\StaticCall::class => ['class' => self::FIXUP_DEREF_LHS], + Expr\ArrayDimFetch::class => ['var' => self::FIXUP_DEREF_LHS], + Expr\ClassConstFetch::class => ['var' => self::FIXUP_DEREF_LHS], + Expr\New_::class => ['class' => self::FIXUP_DEREF_LHS], // TODO: FIXUP_NEW_VARIABLE + Expr\MethodCall::class => [ + 'var' => self::FIXUP_DEREF_LHS, + 'name' => self::FIXUP_BRACED_NAME, + ], + Expr\NullsafeMethodCall::class => [ + 'var' => self::FIXUP_DEREF_LHS, + 'name' => self::FIXUP_BRACED_NAME, + ], + Expr\StaticPropertyFetch::class => [ + 'class' => self::FIXUP_DEREF_LHS, + 'name' => self::FIXUP_VAR_BRACED_NAME, + ], + Expr\PropertyFetch::class => [ + 'var' => self::FIXUP_DEREF_LHS, + 'name' => self::FIXUP_BRACED_NAME, + ], + Expr\NullsafePropertyFetch::class => [ + 'var' => self::FIXUP_DEREF_LHS, + 'name' => self::FIXUP_BRACED_NAME, + ], + Scalar\Encapsed::class => [ + 'parts' => self::FIXUP_ENCAPSED, + ], + ]; + + $binaryOps = [ + BinaryOp\Pow::class, BinaryOp\Mul::class, BinaryOp\Div::class, BinaryOp\Mod::class, + BinaryOp\Plus::class, BinaryOp\Minus::class, BinaryOp\Concat::class, + BinaryOp\ShiftLeft::class, BinaryOp\ShiftRight::class, BinaryOp\Smaller::class, + BinaryOp\SmallerOrEqual::class, BinaryOp\Greater::class, BinaryOp\GreaterOrEqual::class, + BinaryOp\Equal::class, BinaryOp\NotEqual::class, BinaryOp\Identical::class, + BinaryOp\NotIdentical::class, BinaryOp\Spaceship::class, BinaryOp\BitwiseAnd::class, + BinaryOp\BitwiseXor::class, BinaryOp\BitwiseOr::class, BinaryOp\BooleanAnd::class, + BinaryOp\BooleanOr::class, BinaryOp\Coalesce::class, BinaryOp\LogicalAnd::class, + BinaryOp\LogicalXor::class, BinaryOp\LogicalOr::class, + ]; + foreach ($binaryOps as $binaryOp) { + $this->fixupMap[$binaryOp] = [ + 'left' => self::FIXUP_PREC_LEFT, + 'right' => self::FIXUP_PREC_RIGHT + ]; + } + + $assignOps = [ + Expr\Assign::class, Expr\AssignRef::class, AssignOp\Plus::class, AssignOp\Minus::class, + AssignOp\Mul::class, AssignOp\Div::class, AssignOp\Concat::class, AssignOp\Mod::class, + AssignOp\BitwiseAnd::class, AssignOp\BitwiseOr::class, AssignOp\BitwiseXor::class, + AssignOp\ShiftLeft::class, AssignOp\ShiftRight::class, AssignOp\Pow::class, AssignOp\Coalesce::class + ]; + foreach ($assignOps as $assignOp) { + $this->fixupMap[$assignOp] = [ + 'var' => self::FIXUP_PREC_LEFT, + 'expr' => self::FIXUP_PREC_RIGHT, + ]; + } + + $prefixOps = [ + Expr\BitwiseNot::class, Expr\BooleanNot::class, Expr\UnaryPlus::class, Expr\UnaryMinus::class, + Cast\Int_::class, Cast\Double::class, Cast\String_::class, Cast\Array_::class, + Cast\Object_::class, Cast\Bool_::class, Cast\Unset_::class, Expr\ErrorSuppress::class, + Expr\YieldFrom::class, Expr\Print_::class, Expr\Include_::class, + ]; + foreach ($prefixOps as $prefixOp) { + $this->fixupMap[$prefixOp] = ['expr' => self::FIXUP_PREC_RIGHT]; + } + } + + /** + * Lazily initializes the removal map. + * + * The removal map is used to determine which additional tokens should be removed when a + * certain node is replaced by null. + */ + protected function initializeRemovalMap() { + if ($this->removalMap) return; + + $stripBoth = ['left' => \T_WHITESPACE, 'right' => \T_WHITESPACE]; + $stripLeft = ['left' => \T_WHITESPACE]; + $stripRight = ['right' => \T_WHITESPACE]; + $stripDoubleArrow = ['right' => \T_DOUBLE_ARROW]; + $stripColon = ['left' => ':']; + $stripEquals = ['left' => '=']; + $this->removalMap = [ + 'Expr_ArrayDimFetch->dim' => $stripBoth, + 'Expr_ArrayItem->key' => $stripDoubleArrow, + 'Expr_ArrowFunction->returnType' => $stripColon, + 'Expr_Closure->returnType' => $stripColon, + 'Expr_Exit->expr' => $stripBoth, + 'Expr_Ternary->if' => $stripBoth, + 'Expr_Yield->key' => $stripDoubleArrow, + 'Expr_Yield->value' => $stripBoth, + 'Param->type' => $stripRight, + 'Param->default' => $stripEquals, + 'Stmt_Break->num' => $stripBoth, + 'Stmt_Catch->var' => $stripLeft, + 'Stmt_ClassMethod->returnType' => $stripColon, + 'Stmt_Class->extends' => ['left' => \T_EXTENDS], + 'Stmt_Enum->scalarType' => $stripColon, + 'Stmt_EnumCase->expr' => $stripEquals, + 'Expr_PrintableNewAnonClass->extends' => ['left' => \T_EXTENDS], + 'Stmt_Continue->num' => $stripBoth, + 'Stmt_Foreach->keyVar' => $stripDoubleArrow, + 'Stmt_Function->returnType' => $stripColon, + 'Stmt_If->else' => $stripLeft, + 'Stmt_Namespace->name' => $stripLeft, + 'Stmt_Property->type' => $stripRight, + 'Stmt_PropertyProperty->default' => $stripEquals, + 'Stmt_Return->expr' => $stripBoth, + 'Stmt_StaticVar->default' => $stripEquals, + 'Stmt_TraitUseAdaptation_Alias->newName' => $stripLeft, + 'Stmt_TryCatch->finally' => $stripLeft, + // 'Stmt_Case->cond': Replace with "default" + // 'Stmt_Class->name': Unclear what to do + // 'Stmt_Declare->stmts': Not a plain node + // 'Stmt_TraitUseAdaptation_Alias->newModifier': Not a plain node + ]; + } + + protected function initializeInsertionMap() { + if ($this->insertionMap) return; + + // TODO: "yield" where both key and value are inserted doesn't work + // [$find, $beforeToken, $extraLeft, $extraRight] + $this->insertionMap = [ + 'Expr_ArrayDimFetch->dim' => ['[', false, null, null], + 'Expr_ArrayItem->key' => [null, false, null, ' => '], + 'Expr_ArrowFunction->returnType' => [')', false, ' : ', null], + 'Expr_Closure->returnType' => [')', false, ' : ', null], + 'Expr_Ternary->if' => ['?', false, ' ', ' '], + 'Expr_Yield->key' => [\T_YIELD, false, null, ' => '], + 'Expr_Yield->value' => [\T_YIELD, false, ' ', null], + 'Param->type' => [null, false, null, ' '], + 'Param->default' => [null, false, ' = ', null], + 'Stmt_Break->num' => [\T_BREAK, false, ' ', null], + 'Stmt_Catch->var' => [null, false, ' ', null], + 'Stmt_ClassMethod->returnType' => [')', false, ' : ', null], + 'Stmt_Class->extends' => [null, false, ' extends ', null], + 'Stmt_Enum->scalarType' => [null, false, ' : ', null], + 'Stmt_EnumCase->expr' => [null, false, ' = ', null], + 'Expr_PrintableNewAnonClass->extends' => [null, ' extends ', null], + 'Stmt_Continue->num' => [\T_CONTINUE, false, ' ', null], + 'Stmt_Foreach->keyVar' => [\T_AS, false, null, ' => '], + 'Stmt_Function->returnType' => [')', false, ' : ', null], + 'Stmt_If->else' => [null, false, ' ', null], + 'Stmt_Namespace->name' => [\T_NAMESPACE, false, ' ', null], + 'Stmt_Property->type' => [\T_VARIABLE, true, null, ' '], + 'Stmt_PropertyProperty->default' => [null, false, ' = ', null], + 'Stmt_Return->expr' => [\T_RETURN, false, ' ', null], + 'Stmt_StaticVar->default' => [null, false, ' = ', null], + //'Stmt_TraitUseAdaptation_Alias->newName' => [T_AS, false, ' ', null], // TODO + 'Stmt_TryCatch->finally' => [null, false, ' ', null], + + // 'Expr_Exit->expr': Complicated due to optional () + // 'Stmt_Case->cond': Conversion from default to case + // 'Stmt_Class->name': Unclear + // 'Stmt_Declare->stmts': Not a proper node + // 'Stmt_TraitUseAdaptation_Alias->newModifier': Not a proper node + ]; + } + + protected function initializeListInsertionMap() { + if ($this->listInsertionMap) return; + + $this->listInsertionMap = [ + // special + //'Expr_ShellExec->parts' => '', // TODO These need to be treated more carefully + //'Scalar_Encapsed->parts' => '', + 'Stmt_Catch->types' => '|', + 'UnionType->types' => '|', + 'IntersectionType->types' => '&', + 'Stmt_If->elseifs' => ' ', + 'Stmt_TryCatch->catches' => ' ', + + // comma-separated lists + 'Expr_Array->items' => ', ', + 'Expr_ArrowFunction->params' => ', ', + 'Expr_Closure->params' => ', ', + 'Expr_Closure->uses' => ', ', + 'Expr_FuncCall->args' => ', ', + 'Expr_Isset->vars' => ', ', + 'Expr_List->items' => ', ', + 'Expr_MethodCall->args' => ', ', + 'Expr_NullsafeMethodCall->args' => ', ', + 'Expr_New->args' => ', ', + 'Expr_PrintableNewAnonClass->args' => ', ', + 'Expr_StaticCall->args' => ', ', + 'Stmt_ClassConst->consts' => ', ', + 'Stmt_ClassMethod->params' => ', ', + 'Stmt_Class->implements' => ', ', + 'Stmt_Enum->implements' => ', ', + 'Expr_PrintableNewAnonClass->implements' => ', ', + 'Stmt_Const->consts' => ', ', + 'Stmt_Declare->declares' => ', ', + 'Stmt_Echo->exprs' => ', ', + 'Stmt_For->init' => ', ', + 'Stmt_For->cond' => ', ', + 'Stmt_For->loop' => ', ', + 'Stmt_Function->params' => ', ', + 'Stmt_Global->vars' => ', ', + 'Stmt_GroupUse->uses' => ', ', + 'Stmt_Interface->extends' => ', ', + 'Stmt_Match->arms' => ', ', + 'Stmt_Property->props' => ', ', + 'Stmt_StaticVar->vars' => ', ', + 'Stmt_TraitUse->traits' => ', ', + 'Stmt_TraitUseAdaptation_Precedence->insteadof' => ', ', + 'Stmt_Unset->vars' => ', ', + 'Stmt_Use->uses' => ', ', + 'MatchArm->conds' => ', ', + 'AttributeGroup->attrs' => ', ', + + // statement lists + 'Expr_Closure->stmts' => "\n", + 'Stmt_Case->stmts' => "\n", + 'Stmt_Catch->stmts' => "\n", + 'Stmt_Class->stmts' => "\n", + 'Stmt_Enum->stmts' => "\n", + 'Expr_PrintableNewAnonClass->stmts' => "\n", + 'Stmt_Interface->stmts' => "\n", + 'Stmt_Trait->stmts' => "\n", + 'Stmt_ClassMethod->stmts' => "\n", + 'Stmt_Declare->stmts' => "\n", + 'Stmt_Do->stmts' => "\n", + 'Stmt_ElseIf->stmts' => "\n", + 'Stmt_Else->stmts' => "\n", + 'Stmt_Finally->stmts' => "\n", + 'Stmt_Foreach->stmts' => "\n", + 'Stmt_For->stmts' => "\n", + 'Stmt_Function->stmts' => "\n", + 'Stmt_If->stmts' => "\n", + 'Stmt_Namespace->stmts' => "\n", + 'Stmt_Class->attrGroups' => "\n", + 'Stmt_Enum->attrGroups' => "\n", + 'Stmt_EnumCase->attrGroups' => "\n", + 'Stmt_Interface->attrGroups' => "\n", + 'Stmt_Trait->attrGroups' => "\n", + 'Stmt_Function->attrGroups' => "\n", + 'Stmt_ClassMethod->attrGroups' => "\n", + 'Stmt_ClassConst->attrGroups' => "\n", + 'Stmt_Property->attrGroups' => "\n", + 'Expr_PrintableNewAnonClass->attrGroups' => ' ', + 'Expr_Closure->attrGroups' => ' ', + 'Expr_ArrowFunction->attrGroups' => ' ', + 'Param->attrGroups' => ' ', + 'Stmt_Switch->cases' => "\n", + 'Stmt_TraitUse->adaptations' => "\n", + 'Stmt_TryCatch->stmts' => "\n", + 'Stmt_While->stmts' => "\n", + + // dummy for top-level context + 'File->stmts' => "\n", + ]; + } + + protected function initializeEmptyListInsertionMap() { + if ($this->emptyListInsertionMap) return; + + // TODO Insertion into empty statement lists. + + // [$find, $extraLeft, $extraRight] + $this->emptyListInsertionMap = [ + 'Expr_ArrowFunction->params' => ['(', '', ''], + 'Expr_Closure->uses' => [')', ' use(', ')'], + 'Expr_Closure->params' => ['(', '', ''], + 'Expr_FuncCall->args' => ['(', '', ''], + 'Expr_MethodCall->args' => ['(', '', ''], + 'Expr_NullsafeMethodCall->args' => ['(', '', ''], + 'Expr_New->args' => ['(', '', ''], + 'Expr_PrintableNewAnonClass->args' => ['(', '', ''], + 'Expr_PrintableNewAnonClass->implements' => [null, ' implements ', ''], + 'Expr_StaticCall->args' => ['(', '', ''], + 'Stmt_Class->implements' => [null, ' implements ', ''], + 'Stmt_Enum->implements' => [null, ' implements ', ''], + 'Stmt_ClassMethod->params' => ['(', '', ''], + 'Stmt_Interface->extends' => [null, ' extends ', ''], + 'Stmt_Function->params' => ['(', '', ''], + 'Stmt_Interface->attrGroups' => [null, '', "\n"], + 'Stmt_Class->attrGroups' => [null, '', "\n"], + 'Stmt_ClassConst->attrGroups' => [null, '', "\n"], + 'Stmt_ClassMethod->attrGroups' => [null, '', "\n"], + 'Stmt_Function->attrGroups' => [null, '', "\n"], + 'Stmt_Property->attrGroups' => [null, '', "\n"], + 'Stmt_Trait->attrGroups' => [null, '', "\n"], + 'Expr_ArrowFunction->attrGroups' => [null, '', ' '], + 'Expr_Closure->attrGroups' => [null, '', ' '], + 'Expr_PrintableNewAnonClass->attrGroups' => [\T_NEW, ' ', ''], + + /* These cannot be empty to start with: + * Expr_Isset->vars + * Stmt_Catch->types + * Stmt_Const->consts + * Stmt_ClassConst->consts + * Stmt_Declare->declares + * Stmt_Echo->exprs + * Stmt_Global->vars + * Stmt_GroupUse->uses + * Stmt_Property->props + * Stmt_StaticVar->vars + * Stmt_TraitUse->traits + * Stmt_TraitUseAdaptation_Precedence->insteadof + * Stmt_Unset->vars + * Stmt_Use->uses + * UnionType->types + */ + + /* TODO + * Stmt_If->elseifs + * Stmt_TryCatch->catches + * Expr_Array->items + * Expr_List->items + * Stmt_For->init + * Stmt_For->cond + * Stmt_For->loop + */ + ]; + } + + protected function initializeModifierChangeMap() { + if ($this->modifierChangeMap) return; + + $this->modifierChangeMap = [ + 'Stmt_ClassConst->flags' => \T_CONST, + 'Stmt_ClassMethod->flags' => \T_FUNCTION, + 'Stmt_Class->flags' => \T_CLASS, + 'Stmt_Property->flags' => \T_VARIABLE, + 'Param->flags' => \T_VARIABLE, + //'Stmt_TraitUseAdaptation_Alias->newModifier' => 0, // TODO + ]; + + // List of integer subnodes that are not modifiers: + // Expr_Include->type + // Stmt_GroupUse->type + // Stmt_Use->type + // Stmt_UseUse->type + } +} diff --git a/vendor/phar-io/manifest/CHANGELOG.md b/vendor/phar-io/manifest/CHANGELOG.md new file mode 100644 index 00000000..a403e093 --- /dev/null +++ b/vendor/phar-io/manifest/CHANGELOG.md @@ -0,0 +1,36 @@ +# Changelog + +All notable changes to phar-io/manifest are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [2.0.3] - 20.07.2021 + +- Fixed PHP 7.2 / PHP 7.3 incompatibility introduced in previous release + +## [2.0.2] - 20.07.2021 + +- Fixed PHP 8.1 deprecation notice + +## [2.0.1] - 27.06.2020 + +This release now supports the use of PHP 7.2+ and ^8.0 + +## [2.0.0] - 10.05.2020 + +This release now requires PHP 7.2+ + +### Changed + +- Upgraded to phar-io/version 3.0 + - Version strings `v1.2.3` will now be converted to valid semantic version strings `1.2.3` + - Abreviated strings like `1.0` will get expaneded to `1.0.0` + +### Unreleased + +[Unreleased]: https://github.com/phar-io/manifest/compare/2.0.3...HEAD +[2.0.3]: https://github.com/phar-io/manifest/compare/2.0.2...2.0.3 +[2.0.2]: https://github.com/phar-io/manifest/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/phar-io/manifest/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/phar-io/manifest/compare/1.0.1...2.0.0 +[1.0.3]: https://github.com/phar-io/manifest/compare/1.0.2...1.0.3 +[1.0.2]: https://github.com/phar-io/manifest/compare/1.0.1...1.0.2 +[1.0.1]: https://github.com/phar-io/manifest/compare/1.0.0...1.0.1 diff --git a/vendor/phar-io/manifest/LICENSE b/vendor/phar-io/manifest/LICENSE new file mode 100644 index 00000000..64690cf2 --- /dev/null +++ b/vendor/phar-io/manifest/LICENSE @@ -0,0 +1,31 @@ +Phar.io - Manifest + +Copyright (c) 2016-2019 Arne Blankerts , Sebastian Heuer , Sebastian Bergmann , and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of Arne Blankerts nor the names of contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + diff --git a/vendor/phar-io/manifest/README.md b/vendor/phar-io/manifest/README.md new file mode 100644 index 00000000..e6d0b055 --- /dev/null +++ b/vendor/phar-io/manifest/README.md @@ -0,0 +1,30 @@ +# Manifest + +Component for reading [phar.io](https://phar.io/) manifest information from a [PHP Archive (PHAR)](http://php.net/phar). + +[![Build Status](https://travis-ci.org/phar-io/manifest.svg?branch=master)](https://travis-ci.org/phar-io/manifest) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/phar-io/manifest/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/phar-io/manifest/?branch=master) +[![SensioLabsInsight](https://insight.sensiolabs.com/projects/d8cc6035-69ad-477d-bd1a-ccc605480fd7/mini.png)](https://insight.sensiolabs.com/projects/d8cc6035-69ad-477d-bd1a-ccc605480fd7) + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + + composer require phar-io/manifest + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + + composer require --dev phar-io/manifest + +## Usage + +```php +use PharIo\Manifest\ManifestLoader; +use PharIo\Manifest\ManifestSerializer; + +$manifest = ManifestLoader::fromFile('manifest.xml'); + +var_dump($manifest); + +echo (new ManifestSerializer)->serializeToString($manifest); +``` diff --git a/vendor/phar-io/manifest/composer.json b/vendor/phar-io/manifest/composer.json new file mode 100644 index 00000000..a2521193 --- /dev/null +++ b/vendor/phar-io/manifest/composer.json @@ -0,0 +1,42 @@ +{ + "name": "phar-io/manifest", + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "support": { + "issues": "https://github.com/phar-io/manifest/issues" + }, + "require": { + "php": "^7.2 || ^8.0", + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + } +} diff --git a/vendor/phar-io/manifest/composer.lock b/vendor/phar-io/manifest/composer.lock new file mode 100644 index 00000000..e0e6db76 --- /dev/null +++ b/vendor/phar-io/manifest/composer.lock @@ -0,0 +1,70 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "f2ac4614ce4f7273fd54a64b65fd047a", + "packages": [ + { + "name": "phar-io/version", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "d06a5000ac1a258a7d035295f0bd4ae7c859bc4f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/d06a5000ac1a258a7d035295f0bd4ae7c859bc4f", + "reference": "d06a5000ac1a258a7d035295f0bd4ae7c859bc4f", + "shasum": "" + }, + "require": { + "php": "^7.2" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2020-05-09T21:27:55+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.2", + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*" + }, + "platform-dev": [] +} diff --git a/vendor/phar-io/manifest/src/ManifestDocumentMapper.php b/vendor/phar-io/manifest/src/ManifestDocumentMapper.php new file mode 100644 index 00000000..8e539d5f --- /dev/null +++ b/vendor/phar-io/manifest/src/ManifestDocumentMapper.php @@ -0,0 +1,150 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +use PharIo\Version\Exception as VersionException; +use PharIo\Version\Version; +use PharIo\Version\VersionConstraintParser; + +class ManifestDocumentMapper { + public function map(ManifestDocument $document): Manifest { + try { + $contains = $document->getContainsElement(); + $type = $this->mapType($contains); + $copyright = $this->mapCopyright($document->getCopyrightElement()); + $requirements = $this->mapRequirements($document->getRequiresElement()); + $bundledComponents = $this->mapBundledComponents($document); + + return new Manifest( + new ApplicationName($contains->getName()), + new Version($contains->getVersion()), + $type, + $copyright, + $requirements, + $bundledComponents + ); + } catch (VersionException $e) { + throw new ManifestDocumentMapperException($e->getMessage(), (int)$e->getCode(), $e); + } catch (Exception $e) { + throw new ManifestDocumentMapperException($e->getMessage(), (int)$e->getCode(), $e); + } + } + + private function mapType(ContainsElement $contains): Type { + switch ($contains->getType()) { + case 'application': + return Type::application(); + case 'library': + return Type::library(); + case 'extension': + return $this->mapExtension($contains->getExtensionElement()); + } + + throw new ManifestDocumentMapperException( + \sprintf('Unsupported type %s', $contains->getType()) + ); + } + + private function mapCopyright(CopyrightElement $copyright): CopyrightInformation { + $authors = new AuthorCollection(); + + foreach ($copyright->getAuthorElements() as $authorElement) { + $authors->add( + new Author( + $authorElement->getName(), + new Email($authorElement->getEmail()) + ) + ); + } + + $licenseElement = $copyright->getLicenseElement(); + $license = new License( + $licenseElement->getType(), + new Url($licenseElement->getUrl()) + ); + + return new CopyrightInformation( + $authors, + $license + ); + } + + private function mapRequirements(RequiresElement $requires): RequirementCollection { + $collection = new RequirementCollection(); + $phpElement = $requires->getPHPElement(); + $parser = new VersionConstraintParser; + + try { + $versionConstraint = $parser->parse($phpElement->getVersion()); + } catch (VersionException $e) { + throw new ManifestDocumentMapperException( + \sprintf('Unsupported version constraint - %s', $e->getMessage()), + (int)$e->getCode(), + $e + ); + } + + $collection->add( + new PhpVersionRequirement( + $versionConstraint + ) + ); + + if (!$phpElement->hasExtElements()) { + return $collection; + } + + foreach ($phpElement->getExtElements() as $extElement) { + $collection->add( + new PhpExtensionRequirement($extElement->getName()) + ); + } + + return $collection; + } + + private function mapBundledComponents(ManifestDocument $document): BundledComponentCollection { + $collection = new BundledComponentCollection(); + + if (!$document->hasBundlesElement()) { + return $collection; + } + + foreach ($document->getBundlesElement()->getComponentElements() as $componentElement) { + $collection->add( + new BundledComponent( + $componentElement->getName(), + new Version( + $componentElement->getVersion() + ) + ) + ); + } + + return $collection; + } + + private function mapExtension(ExtensionElement $extension): Extension { + try { + $versionConstraint = (new VersionConstraintParser)->parse($extension->getCompatible()); + + return Type::extension( + new ApplicationName($extension->getFor()), + $versionConstraint + ); + } catch (VersionException $e) { + throw new ManifestDocumentMapperException( + \sprintf('Unsupported version constraint - %s', $e->getMessage()), + (int)$e->getCode(), + $e + ); + } + } +} diff --git a/vendor/phar-io/manifest/src/ManifestLoader.php b/vendor/phar-io/manifest/src/ManifestLoader.php new file mode 100644 index 00000000..ae884e49 --- /dev/null +++ b/vendor/phar-io/manifest/src/ManifestLoader.php @@ -0,0 +1,44 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class ManifestLoader { + public static function fromFile(string $filename): Manifest { + try { + return (new ManifestDocumentMapper())->map( + ManifestDocument::fromFile($filename) + ); + } catch (Exception $e) { + throw new ManifestLoaderException( + \sprintf('Loading %s failed.', $filename), + (int)$e->getCode(), + $e + ); + } + } + + public static function fromPhar(string $filename): Manifest { + return self::fromFile('phar://' . $filename . '/manifest.xml'); + } + + public static function fromString(string $manifest): Manifest { + try { + return (new ManifestDocumentMapper())->map( + ManifestDocument::fromString($manifest) + ); + } catch (Exception $e) { + throw new ManifestLoaderException( + 'Processing string failed', + (int)$e->getCode(), + $e + ); + } + } +} diff --git a/vendor/phar-io/manifest/src/ManifestSerializer.php b/vendor/phar-io/manifest/src/ManifestSerializer.php new file mode 100644 index 00000000..e236b598 --- /dev/null +++ b/vendor/phar-io/manifest/src/ManifestSerializer.php @@ -0,0 +1,168 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +use PharIo\Version\AnyVersionConstraint; +use PharIo\Version\Version; +use PharIo\Version\VersionConstraint; +use XMLWriter; + +/** @psalm-suppress MissingConstructor */ +class ManifestSerializer { + /** @var XMLWriter */ + private $xmlWriter; + + public function serializeToFile(Manifest $manifest, string $filename): void { + \file_put_contents( + $filename, + $this->serializeToString($manifest) + ); + } + + public function serializeToString(Manifest $manifest): string { + $this->startDocument(); + + $this->addContains($manifest->getName(), $manifest->getVersion(), $manifest->getType()); + $this->addCopyright($manifest->getCopyrightInformation()); + $this->addRequirements($manifest->getRequirements()); + $this->addBundles($manifest->getBundledComponents()); + + return $this->finishDocument(); + } + + private function startDocument(): void { + $xmlWriter = new XMLWriter(); + $xmlWriter->openMemory(); + $xmlWriter->setIndent(true); + $xmlWriter->setIndentString(\str_repeat(' ', 4)); + $xmlWriter->startDocument('1.0', 'UTF-8'); + $xmlWriter->startElement('phar'); + $xmlWriter->writeAttribute('xmlns', 'https://phar.io/xml/manifest/1.0'); + + $this->xmlWriter = $xmlWriter; + } + + private function finishDocument(): string { + $this->xmlWriter->endElement(); + $this->xmlWriter->endDocument(); + + return $this->xmlWriter->outputMemory(); + } + + private function addContains(ApplicationName $name, Version $version, Type $type): void { + $this->xmlWriter->startElement('contains'); + $this->xmlWriter->writeAttribute('name', $name->asString()); + $this->xmlWriter->writeAttribute('version', $version->getVersionString()); + + switch (true) { + case $type->isApplication(): { + $this->xmlWriter->writeAttribute('type', 'application'); + + break; + } + + case $type->isLibrary(): { + $this->xmlWriter->writeAttribute('type', 'library'); + + break; + } + + case $type->isExtension(): { + $this->xmlWriter->writeAttribute('type', 'extension'); + /* @var $type Extension */ + $this->addExtension( + $type->getApplicationName(), + $type->getVersionConstraint() + ); + + break; + } + + default: { + $this->xmlWriter->writeAttribute('type', 'custom'); + } + } + + $this->xmlWriter->endElement(); + } + + private function addCopyright(CopyrightInformation $copyrightInformation): void { + $this->xmlWriter->startElement('copyright'); + + foreach ($copyrightInformation->getAuthors() as $author) { + $this->xmlWriter->startElement('author'); + $this->xmlWriter->writeAttribute('name', $author->getName()); + $this->xmlWriter->writeAttribute('email', $author->getEmail()->asString()); + $this->xmlWriter->endElement(); + } + + $license = $copyrightInformation->getLicense(); + + $this->xmlWriter->startElement('license'); + $this->xmlWriter->writeAttribute('type', $license->getName()); + $this->xmlWriter->writeAttribute('url', $license->getUrl()->asString()); + $this->xmlWriter->endElement(); + + $this->xmlWriter->endElement(); + } + + private function addRequirements(RequirementCollection $requirementCollection): void { + $phpRequirement = new AnyVersionConstraint(); + $extensions = []; + + foreach ($requirementCollection as $requirement) { + if ($requirement instanceof PhpVersionRequirement) { + $phpRequirement = $requirement->getVersionConstraint(); + + continue; + } + + if ($requirement instanceof PhpExtensionRequirement) { + $extensions[] = $requirement->asString(); + } + } + + $this->xmlWriter->startElement('requires'); + $this->xmlWriter->startElement('php'); + $this->xmlWriter->writeAttribute('version', $phpRequirement->asString()); + + foreach ($extensions as $extension) { + $this->xmlWriter->startElement('ext'); + $this->xmlWriter->writeAttribute('name', $extension); + $this->xmlWriter->endElement(); + } + + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + } + + private function addBundles(BundledComponentCollection $bundledComponentCollection): void { + if (\count($bundledComponentCollection) === 0) { + return; + } + $this->xmlWriter->startElement('bundles'); + + foreach ($bundledComponentCollection as $bundledComponent) { + $this->xmlWriter->startElement('component'); + $this->xmlWriter->writeAttribute('name', $bundledComponent->getName()); + $this->xmlWriter->writeAttribute('version', $bundledComponent->getVersion()->getVersionString()); + $this->xmlWriter->endElement(); + } + + $this->xmlWriter->endElement(); + } + + private function addExtension(ApplicationName $applicationName, VersionConstraint $versionConstraint): void { + $this->xmlWriter->startElement('extension'); + $this->xmlWriter->writeAttribute('for', $applicationName->asString()); + $this->xmlWriter->writeAttribute('compatible', $versionConstraint->asString()); + $this->xmlWriter->endElement(); + } +} diff --git a/vendor/phar-io/manifest/src/exceptions/ElementCollectionException.php b/vendor/phar-io/manifest/src/exceptions/ElementCollectionException.php new file mode 100644 index 00000000..766fc0e6 --- /dev/null +++ b/vendor/phar-io/manifest/src/exceptions/ElementCollectionException.php @@ -0,0 +1,13 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class ElementCollectionException extends \InvalidArgumentException implements Exception { +} diff --git a/vendor/phar-io/manifest/src/exceptions/Exception.php b/vendor/phar-io/manifest/src/exceptions/Exception.php new file mode 100644 index 00000000..e7f12209 --- /dev/null +++ b/vendor/phar-io/manifest/src/exceptions/Exception.php @@ -0,0 +1,13 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +interface Exception extends \Throwable { +} diff --git a/vendor/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php b/vendor/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php new file mode 100644 index 00000000..952901eb --- /dev/null +++ b/vendor/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php @@ -0,0 +1,14 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class InvalidApplicationNameException extends \InvalidArgumentException implements Exception { + public const InvalidFormat = 2; +} diff --git a/vendor/phar-io/manifest/src/exceptions/InvalidEmailException.php b/vendor/phar-io/manifest/src/exceptions/InvalidEmailException.php new file mode 100644 index 00000000..3cbe0822 --- /dev/null +++ b/vendor/phar-io/manifest/src/exceptions/InvalidEmailException.php @@ -0,0 +1,13 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class InvalidEmailException extends \InvalidArgumentException implements Exception { +} diff --git a/vendor/phar-io/manifest/src/exceptions/InvalidUrlException.php b/vendor/phar-io/manifest/src/exceptions/InvalidUrlException.php new file mode 100644 index 00000000..8f77e294 --- /dev/null +++ b/vendor/phar-io/manifest/src/exceptions/InvalidUrlException.php @@ -0,0 +1,13 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class InvalidUrlException extends \InvalidArgumentException implements Exception { +} diff --git a/vendor/phar-io/manifest/src/exceptions/ManifestDocumentException.php b/vendor/phar-io/manifest/src/exceptions/ManifestDocumentException.php new file mode 100644 index 00000000..cf1c314c --- /dev/null +++ b/vendor/phar-io/manifest/src/exceptions/ManifestDocumentException.php @@ -0,0 +1,5 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +use LibXMLError; + +class ManifestDocumentLoadingException extends \Exception implements Exception { + /** @var LibXMLError[] */ + private $libxmlErrors; + + /** + * ManifestDocumentLoadingException constructor. + * + * @param LibXMLError[] $libxmlErrors + */ + public function __construct(array $libxmlErrors) { + $this->libxmlErrors = $libxmlErrors; + $first = $this->libxmlErrors[0]; + + parent::__construct( + \sprintf( + '%s (Line: %d / Column: %d / File: %s)', + $first->message, + $first->line, + $first->column, + $first->file + ), + $first->code + ); + } + + /** + * @return LibXMLError[] + */ + public function getLibxmlErrors(): array { + return $this->libxmlErrors; + } +} diff --git a/vendor/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php b/vendor/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php new file mode 100644 index 00000000..43373bd3 --- /dev/null +++ b/vendor/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php @@ -0,0 +1,5 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class Application extends Type { + public function isApplication(): bool { + return true; + } +} diff --git a/vendor/phar-io/manifest/src/values/ApplicationName.php b/vendor/phar-io/manifest/src/values/ApplicationName.php new file mode 100644 index 00000000..d71744ab --- /dev/null +++ b/vendor/phar-io/manifest/src/values/ApplicationName.php @@ -0,0 +1,37 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class ApplicationName { + /** @var string */ + private $name; + + public function __construct(string $name) { + $this->ensureValidFormat($name); + $this->name = $name; + } + + public function asString(): string { + return $this->name; + } + + public function isEqual(ApplicationName $name): bool { + return $this->name === $name->name; + } + + private function ensureValidFormat(string $name): void { + if (!\preg_match('#\w/\w#', $name)) { + throw new InvalidApplicationNameException( + \sprintf('Format of name "%s" is not valid - expected: vendor/packagename', $name), + InvalidApplicationNameException::InvalidFormat + ); + } + } +} diff --git a/vendor/phar-io/manifest/src/values/Author.php b/vendor/phar-io/manifest/src/values/Author.php new file mode 100644 index 00000000..82b666e7 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/Author.php @@ -0,0 +1,39 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class Author { + /** @var string */ + private $name; + + /** @var Email */ + private $email; + + public function __construct(string $name, Email $email) { + $this->name = $name; + $this->email = $email; + } + + public function asString(): string { + return \sprintf( + '%s <%s>', + $this->name, + $this->email->asString() + ); + } + + public function getName(): string { + return $this->name; + } + + public function getEmail(): Email { + return $this->email; + } +} diff --git a/vendor/phar-io/manifest/src/values/AuthorCollection.php b/vendor/phar-io/manifest/src/values/AuthorCollection.php new file mode 100644 index 00000000..27e50ad8 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/AuthorCollection.php @@ -0,0 +1,34 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class AuthorCollection implements \Countable, \IteratorAggregate { + /** @var Author[] */ + private $authors = []; + + public function add(Author $author): void { + $this->authors[] = $author; + } + + /** + * @return Author[] + */ + public function getAuthors(): array { + return $this->authors; + } + + public function count(): int { + return \count($this->authors); + } + + public function getIterator(): AuthorCollectionIterator { + return new AuthorCollectionIterator($this); + } +} diff --git a/vendor/phar-io/manifest/src/values/AuthorCollectionIterator.php b/vendor/phar-io/manifest/src/values/AuthorCollectionIterator.php new file mode 100644 index 00000000..4ff3c394 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/AuthorCollectionIterator.php @@ -0,0 +1,42 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class AuthorCollectionIterator implements \Iterator { + /** @var Author[] */ + private $authors; + + /** @var int */ + private $position = 0; + + public function __construct(AuthorCollection $authors) { + $this->authors = $authors->getAuthors(); + } + + public function rewind(): void { + $this->position = 0; + } + + public function valid(): bool { + return $this->position < \count($this->authors); + } + + public function key(): int { + return $this->position; + } + + public function current(): Author { + return $this->authors[$this->position]; + } + + public function next(): void { + $this->position++; + } +} diff --git a/vendor/phar-io/manifest/src/values/BundledComponent.php b/vendor/phar-io/manifest/src/values/BundledComponent.php new file mode 100644 index 00000000..ea77b440 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/BundledComponent.php @@ -0,0 +1,33 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +use PharIo\Version\Version; + +class BundledComponent { + /** @var string */ + private $name; + + /** @var Version */ + private $version; + + public function __construct(string $name, Version $version) { + $this->name = $name; + $this->version = $version; + } + + public function getName(): string { + return $this->name; + } + + public function getVersion(): Version { + return $this->version; + } +} diff --git a/vendor/phar-io/manifest/src/values/BundledComponentCollection.php b/vendor/phar-io/manifest/src/values/BundledComponentCollection.php new file mode 100644 index 00000000..b628eaa3 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/BundledComponentCollection.php @@ -0,0 +1,34 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class BundledComponentCollection implements \Countable, \IteratorAggregate { + /** @var BundledComponent[] */ + private $bundledComponents = []; + + public function add(BundledComponent $bundledComponent): void { + $this->bundledComponents[] = $bundledComponent; + } + + /** + * @return BundledComponent[] + */ + public function getBundledComponents(): array { + return $this->bundledComponents; + } + + public function count(): int { + return \count($this->bundledComponents); + } + + public function getIterator(): BundledComponentCollectionIterator { + return new BundledComponentCollectionIterator($this); + } +} diff --git a/vendor/phar-io/manifest/src/values/BundledComponentCollectionIterator.php b/vendor/phar-io/manifest/src/values/BundledComponentCollectionIterator.php new file mode 100644 index 00000000..462db45a --- /dev/null +++ b/vendor/phar-io/manifest/src/values/BundledComponentCollectionIterator.php @@ -0,0 +1,42 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class BundledComponentCollectionIterator implements \Iterator { + /** @var BundledComponent[] */ + private $bundledComponents; + + /** @var int */ + private $position = 0; + + public function __construct(BundledComponentCollection $bundledComponents) { + $this->bundledComponents = $bundledComponents->getBundledComponents(); + } + + public function rewind(): void { + $this->position = 0; + } + + public function valid(): bool { + return $this->position < \count($this->bundledComponents); + } + + public function key(): int { + return $this->position; + } + + public function current(): BundledComponent { + return $this->bundledComponents[$this->position]; + } + + public function next(): void { + $this->position++; + } +} diff --git a/vendor/phar-io/manifest/src/values/CopyrightInformation.php b/vendor/phar-io/manifest/src/values/CopyrightInformation.php new file mode 100644 index 00000000..d26f9472 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/CopyrightInformation.php @@ -0,0 +1,31 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class CopyrightInformation { + /** @var AuthorCollection */ + private $authors; + + /** @var License */ + private $license; + + public function __construct(AuthorCollection $authors, License $license) { + $this->authors = $authors; + $this->license = $license; + } + + public function getAuthors(): AuthorCollection { + return $this->authors; + } + + public function getLicense(): License { + return $this->license; + } +} diff --git a/vendor/phar-io/manifest/src/values/Email.php b/vendor/phar-io/manifest/src/values/Email.php new file mode 100644 index 00000000..588348d8 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/Email.php @@ -0,0 +1,31 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class Email { + /** @var string */ + private $email; + + public function __construct(string $email) { + $this->ensureEmailIsValid($email); + + $this->email = $email; + } + + public function asString(): string { + return $this->email; + } + + private function ensureEmailIsValid(string $url): void { + if (\filter_var($url, \FILTER_VALIDATE_EMAIL) === false) { + throw new InvalidEmailException; + } + } +} diff --git a/vendor/phar-io/manifest/src/values/Extension.php b/vendor/phar-io/manifest/src/values/Extension.php new file mode 100644 index 00000000..4c5726f8 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/Extension.php @@ -0,0 +1,46 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +use PharIo\Version\Version; +use PharIo\Version\VersionConstraint; + +class Extension extends Type { + /** @var ApplicationName */ + private $application; + + /** @var VersionConstraint */ + private $versionConstraint; + + public function __construct(ApplicationName $application, VersionConstraint $versionConstraint) { + $this->application = $application; + $this->versionConstraint = $versionConstraint; + } + + public function getApplicationName(): ApplicationName { + return $this->application; + } + + public function getVersionConstraint(): VersionConstraint { + return $this->versionConstraint; + } + + public function isExtension(): bool { + return true; + } + + public function isExtensionFor(ApplicationName $name): bool { + return $this->application->isEqual($name); + } + + public function isCompatibleWith(ApplicationName $name, Version $version): bool { + return $this->isExtensionFor($name) && $this->versionConstraint->complies($version); + } +} diff --git a/vendor/phar-io/manifest/src/values/Library.php b/vendor/phar-io/manifest/src/values/Library.php new file mode 100644 index 00000000..21849e13 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/Library.php @@ -0,0 +1,16 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class Library extends Type { + public function isLibrary(): bool { + return true; + } +} diff --git a/vendor/phar-io/manifest/src/values/License.php b/vendor/phar-io/manifest/src/values/License.php new file mode 100644 index 00000000..39542fe8 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/License.php @@ -0,0 +1,31 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class License { + /** @var string */ + private $name; + + /** @var Url */ + private $url; + + public function __construct(string $name, Url $url) { + $this->name = $name; + $this->url = $url; + } + + public function getName(): string { + return $this->name; + } + + public function getUrl(): Url { + return $this->url; + } +} diff --git a/vendor/phar-io/manifest/src/values/Manifest.php b/vendor/phar-io/manifest/src/values/Manifest.php new file mode 100644 index 00000000..0140b842 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/Manifest.php @@ -0,0 +1,92 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +use PharIo\Version\Version; + +class Manifest { + /** @var ApplicationName */ + private $name; + + /** @var Version */ + private $version; + + /** @var Type */ + private $type; + + /** @var CopyrightInformation */ + private $copyrightInformation; + + /** @var RequirementCollection */ + private $requirements; + + /** @var BundledComponentCollection */ + private $bundledComponents; + + public function __construct(ApplicationName $name, Version $version, Type $type, CopyrightInformation $copyrightInformation, RequirementCollection $requirements, BundledComponentCollection $bundledComponents) { + $this->name = $name; + $this->version = $version; + $this->type = $type; + $this->copyrightInformation = $copyrightInformation; + $this->requirements = $requirements; + $this->bundledComponents = $bundledComponents; + } + + public function getName(): ApplicationName { + return $this->name; + } + + public function getVersion(): Version { + return $this->version; + } + + public function getType(): Type { + return $this->type; + } + + public function getCopyrightInformation(): CopyrightInformation { + return $this->copyrightInformation; + } + + public function getRequirements(): RequirementCollection { + return $this->requirements; + } + + public function getBundledComponents(): BundledComponentCollection { + return $this->bundledComponents; + } + + public function isApplication(): bool { + return $this->type->isApplication(); + } + + public function isLibrary(): bool { + return $this->type->isLibrary(); + } + + public function isExtension(): bool { + return $this->type->isExtension(); + } + + public function isExtensionFor(ApplicationName $application, Version $version = null): bool { + if (!$this->isExtension()) { + return false; + } + + /** @var Extension $type */ + $type = $this->type; + + if ($version !== null) { + return $type->isCompatibleWith($application, $version); + } + + return $type->isExtensionFor($application); + } +} diff --git a/vendor/phar-io/manifest/src/values/PhpExtensionRequirement.php b/vendor/phar-io/manifest/src/values/PhpExtensionRequirement.php new file mode 100644 index 00000000..088f3858 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/PhpExtensionRequirement.php @@ -0,0 +1,23 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class PhpExtensionRequirement implements Requirement { + /** @var string */ + private $extension; + + public function __construct(string $extension) { + $this->extension = $extension; + } + + public function asString(): string { + return $this->extension; + } +} diff --git a/vendor/phar-io/manifest/src/values/PhpVersionRequirement.php b/vendor/phar-io/manifest/src/values/PhpVersionRequirement.php new file mode 100644 index 00000000..f8d6f6d1 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/PhpVersionRequirement.php @@ -0,0 +1,25 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +use PharIo\Version\VersionConstraint; + +class PhpVersionRequirement implements Requirement { + /** @var VersionConstraint */ + private $versionConstraint; + + public function __construct(VersionConstraint $versionConstraint) { + $this->versionConstraint = $versionConstraint; + } + + public function getVersionConstraint(): VersionConstraint { + return $this->versionConstraint; + } +} diff --git a/vendor/phar-io/manifest/src/values/Requirement.php b/vendor/phar-io/manifest/src/values/Requirement.php new file mode 100644 index 00000000..8b845d6a --- /dev/null +++ b/vendor/phar-io/manifest/src/values/Requirement.php @@ -0,0 +1,13 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +interface Requirement { +} diff --git a/vendor/phar-io/manifest/src/values/RequirementCollection.php b/vendor/phar-io/manifest/src/values/RequirementCollection.php new file mode 100644 index 00000000..b82cd955 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/RequirementCollection.php @@ -0,0 +1,34 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class RequirementCollection implements \Countable, \IteratorAggregate { + /** @var Requirement[] */ + private $requirements = []; + + public function add(Requirement $requirement): void { + $this->requirements[] = $requirement; + } + + /** + * @return Requirement[] + */ + public function getRequirements(): array { + return $this->requirements; + } + + public function count(): int { + return \count($this->requirements); + } + + public function getIterator(): RequirementCollectionIterator { + return new RequirementCollectionIterator($this); + } +} diff --git a/vendor/phar-io/manifest/src/values/RequirementCollectionIterator.php b/vendor/phar-io/manifest/src/values/RequirementCollectionIterator.php new file mode 100644 index 00000000..5614eaf7 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/RequirementCollectionIterator.php @@ -0,0 +1,42 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class RequirementCollectionIterator implements \Iterator { + /** @var Requirement[] */ + private $requirements; + + /** @var int */ + private $position = 0; + + public function __construct(RequirementCollection $requirements) { + $this->requirements = $requirements->getRequirements(); + } + + public function rewind(): void { + $this->position = 0; + } + + public function valid(): bool { + return $this->position < \count($this->requirements); + } + + public function key(): int { + return $this->position; + } + + public function current(): Requirement { + return $this->requirements[$this->position]; + } + + public function next(): void { + $this->position++; + } +} diff --git a/vendor/phar-io/manifest/src/values/Type.php b/vendor/phar-io/manifest/src/values/Type.php new file mode 100644 index 00000000..23b28980 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/Type.php @@ -0,0 +1,41 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +use PharIo\Version\VersionConstraint; + +abstract class Type { + public static function application(): Application { + return new Application; + } + + public static function library(): Library { + return new Library; + } + + public static function extension(ApplicationName $application, VersionConstraint $versionConstraint): Extension { + return new Extension($application, $versionConstraint); + } + + /** @psalm-assert-if-true Application $this */ + public function isApplication(): bool { + return false; + } + + /** @psalm-assert-if-true Library $this */ + public function isLibrary(): bool { + return false; + } + + /** @psalm-assert-if-true Extension $this */ + public function isExtension(): bool { + return false; + } +} diff --git a/vendor/phar-io/manifest/src/values/Url.php b/vendor/phar-io/manifest/src/values/Url.php new file mode 100644 index 00000000..63952533 --- /dev/null +++ b/vendor/phar-io/manifest/src/values/Url.php @@ -0,0 +1,36 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class Url { + /** @var string */ + private $url; + + public function __construct(string $url) { + $this->ensureUrlIsValid($url); + + $this->url = $url; + } + + public function asString(): string { + return $this->url; + } + + /** + * @param string $url + * + * @throws InvalidUrlException + */ + private function ensureUrlIsValid($url): void { + if (\filter_var($url, \FILTER_VALIDATE_URL) === false) { + throw new InvalidUrlException; + } + } +} diff --git a/vendor/phar-io/manifest/src/xml/AuthorElement.php b/vendor/phar-io/manifest/src/xml/AuthorElement.php new file mode 100644 index 00000000..c454b271 --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/AuthorElement.php @@ -0,0 +1,20 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class AuthorElement extends ManifestElement { + public function getName(): string { + return $this->getAttributeValue('name'); + } + + public function getEmail(): string { + return $this->getAttributeValue('email'); + } +} diff --git a/vendor/phar-io/manifest/src/xml/AuthorElementCollection.php b/vendor/phar-io/manifest/src/xml/AuthorElementCollection.php new file mode 100644 index 00000000..a54147eb --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/AuthorElementCollection.php @@ -0,0 +1,18 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class AuthorElementCollection extends ElementCollection { + public function current(): AuthorElement { + return new AuthorElement( + $this->getCurrentElement() + ); + } +} diff --git a/vendor/phar-io/manifest/src/xml/BundlesElement.php b/vendor/phar-io/manifest/src/xml/BundlesElement.php new file mode 100644 index 00000000..eb2105ac --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/BundlesElement.php @@ -0,0 +1,18 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class BundlesElement extends ManifestElement { + public function getComponentElements(): ComponentElementCollection { + return new ComponentElementCollection( + $this->getChildrenByName('component') + ); + } +} diff --git a/vendor/phar-io/manifest/src/xml/ComponentElement.php b/vendor/phar-io/manifest/src/xml/ComponentElement.php new file mode 100644 index 00000000..7f6a5ec9 --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/ComponentElement.php @@ -0,0 +1,20 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class ComponentElement extends ManifestElement { + public function getName(): string { + return $this->getAttributeValue('name'); + } + + public function getVersion(): string { + return $this->getAttributeValue('version'); + } +} diff --git a/vendor/phar-io/manifest/src/xml/ComponentElementCollection.php b/vendor/phar-io/manifest/src/xml/ComponentElementCollection.php new file mode 100644 index 00000000..23bcbd2f --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/ComponentElementCollection.php @@ -0,0 +1,18 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class ComponentElementCollection extends ElementCollection { + public function current(): ComponentElement { + return new ComponentElement( + $this->getCurrentElement() + ); + } +} diff --git a/vendor/phar-io/manifest/src/xml/ContainsElement.php b/vendor/phar-io/manifest/src/xml/ContainsElement.php new file mode 100644 index 00000000..ebef49d9 --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/ContainsElement.php @@ -0,0 +1,30 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class ContainsElement extends ManifestElement { + public function getName(): string { + return $this->getAttributeValue('name'); + } + + public function getVersion(): string { + return $this->getAttributeValue('version'); + } + + public function getType(): string { + return $this->getAttributeValue('type'); + } + + public function getExtensionElement(): ExtensionElement { + return new ExtensionElement( + $this->getChildByName('extension') + ); + } +} diff --git a/vendor/phar-io/manifest/src/xml/CopyrightElement.php b/vendor/phar-io/manifest/src/xml/CopyrightElement.php new file mode 100644 index 00000000..3debe7dc --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/CopyrightElement.php @@ -0,0 +1,24 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class CopyrightElement extends ManifestElement { + public function getAuthorElements(): AuthorElementCollection { + return new AuthorElementCollection( + $this->getChildrenByName('author') + ); + } + + public function getLicenseElement(): LicenseElement { + return new LicenseElement( + $this->getChildByName('license') + ); + } +} diff --git a/vendor/phar-io/manifest/src/xml/ElementCollection.php b/vendor/phar-io/manifest/src/xml/ElementCollection.php new file mode 100644 index 00000000..26d9250f --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/ElementCollection.php @@ -0,0 +1,61 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +use DOMElement; +use DOMNodeList; + +abstract class ElementCollection implements \Iterator { + /** @var DOMElement[] */ + private $nodes = []; + + /** @var int */ + private $position; + + public function __construct(DOMNodeList $nodeList) { + $this->position = 0; + $this->importNodes($nodeList); + } + + #[\ReturnTypeWillChange] + abstract public function current(); + + public function next(): void { + $this->position++; + } + + public function key(): int { + return $this->position; + } + + public function valid(): bool { + return $this->position < \count($this->nodes); + } + + public function rewind(): void { + $this->position = 0; + } + + protected function getCurrentElement(): DOMElement { + return $this->nodes[$this->position]; + } + + private function importNodes(DOMNodeList $nodeList): void { + foreach ($nodeList as $node) { + if (!$node instanceof DOMElement) { + throw new ElementCollectionException( + \sprintf('\DOMElement expected, got \%s', \get_class($node)) + ); + } + + $this->nodes[] = $node; + } + } +} diff --git a/vendor/phar-io/manifest/src/xml/ExtElement.php b/vendor/phar-io/manifest/src/xml/ExtElement.php new file mode 100644 index 00000000..257853c4 --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/ExtElement.php @@ -0,0 +1,16 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class ExtElement extends ManifestElement { + public function getName(): string { + return $this->getAttributeValue('name'); + } +} diff --git a/vendor/phar-io/manifest/src/xml/ExtElementCollection.php b/vendor/phar-io/manifest/src/xml/ExtElementCollection.php new file mode 100644 index 00000000..05977349 --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/ExtElementCollection.php @@ -0,0 +1,18 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class ExtElementCollection extends ElementCollection { + public function current(): ExtElement { + return new ExtElement( + $this->getCurrentElement() + ); + } +} diff --git a/vendor/phar-io/manifest/src/xml/ExtensionElement.php b/vendor/phar-io/manifest/src/xml/ExtensionElement.php new file mode 100644 index 00000000..db067f99 --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/ExtensionElement.php @@ -0,0 +1,20 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class ExtensionElement extends ManifestElement { + public function getFor(): string { + return $this->getAttributeValue('for'); + } + + public function getCompatible(): string { + return $this->getAttributeValue('compatible'); + } +} diff --git a/vendor/phar-io/manifest/src/xml/LicenseElement.php b/vendor/phar-io/manifest/src/xml/LicenseElement.php new file mode 100644 index 00000000..658c3d1c --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/LicenseElement.php @@ -0,0 +1,20 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class LicenseElement extends ManifestElement { + public function getType(): string { + return $this->getAttributeValue('type'); + } + + public function getUrl(): string { + return $this->getAttributeValue('url'); + } +} diff --git a/vendor/phar-io/manifest/src/xml/ManifestDocument.php b/vendor/phar-io/manifest/src/xml/ManifestDocument.php new file mode 100644 index 00000000..f88b2829 --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/ManifestDocument.php @@ -0,0 +1,103 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +use DOMDocument; +use DOMElement; + +class ManifestDocument { + public const XMLNS = 'https://phar.io/xml/manifest/1.0'; + + /** @var DOMDocument */ + private $dom; + + public static function fromFile(string $filename): ManifestDocument { + if (!\file_exists($filename)) { + throw new ManifestDocumentException( + \sprintf('File "%s" not found', $filename) + ); + } + + return self::fromString( + \file_get_contents($filename) + ); + } + + public static function fromString(string $xmlString): ManifestDocument { + $prev = \libxml_use_internal_errors(true); + \libxml_clear_errors(); + + $dom = new DOMDocument(); + $dom->loadXML($xmlString); + + $errors = \libxml_get_errors(); + \libxml_use_internal_errors($prev); + + if (\count($errors) !== 0) { + throw new ManifestDocumentLoadingException($errors); + } + + return new self($dom); + } + + private function __construct(DOMDocument $dom) { + $this->ensureCorrectDocumentType($dom); + + $this->dom = $dom; + } + + public function getContainsElement(): ContainsElement { + return new ContainsElement( + $this->fetchElementByName('contains') + ); + } + + public function getCopyrightElement(): CopyrightElement { + return new CopyrightElement( + $this->fetchElementByName('copyright') + ); + } + + public function getRequiresElement(): RequiresElement { + return new RequiresElement( + $this->fetchElementByName('requires') + ); + } + + public function hasBundlesElement(): bool { + return $this->dom->getElementsByTagNameNS(self::XMLNS, 'bundles')->length === 1; + } + + public function getBundlesElement(): BundlesElement { + return new BundlesElement( + $this->fetchElementByName('bundles') + ); + } + + private function ensureCorrectDocumentType(DOMDocument $dom): void { + $root = $dom->documentElement; + + if ($root->localName !== 'phar' || $root->namespaceURI !== self::XMLNS) { + throw new ManifestDocumentException('Not a phar.io manifest document'); + } + } + + private function fetchElementByName(string $elementName): DOMElement { + $element = $this->dom->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0); + + if (!$element instanceof DOMElement) { + throw new ManifestDocumentException( + \sprintf('Element %s missing', $elementName) + ); + } + + return $element; + } +} diff --git a/vendor/phar-io/manifest/src/xml/ManifestElement.php b/vendor/phar-io/manifest/src/xml/ManifestElement.php new file mode 100644 index 00000000..1f57f547 --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/ManifestElement.php @@ -0,0 +1,66 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +use DOMElement; +use DOMNodeList; + +class ManifestElement { + public const XMLNS = 'https://phar.io/xml/manifest/1.0'; + + /** @var DOMElement */ + private $element; + + public function __construct(DOMElement $element) { + $this->element = $element; + } + + protected function getAttributeValue(string $name): string { + if (!$this->element->hasAttribute($name)) { + throw new ManifestElementException( + \sprintf( + 'Attribute %s not set on element %s', + $name, + $this->element->localName + ) + ); + } + + return $this->element->getAttribute($name); + } + + protected function getChildByName(string $elementName): DOMElement { + $element = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0); + + if (!$element instanceof DOMElement) { + throw new ManifestElementException( + \sprintf('Element %s missing', $elementName) + ); + } + + return $element; + } + + protected function getChildrenByName(string $elementName): DOMNodeList { + $elementList = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName); + + if ($elementList->length === 0) { + throw new ManifestElementException( + \sprintf('Element(s) %s missing', $elementName) + ); + } + + return $elementList; + } + + protected function hasChild(string $elementName): bool { + return $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->length !== 0; + } +} diff --git a/vendor/phar-io/manifest/src/xml/PhpElement.php b/vendor/phar-io/manifest/src/xml/PhpElement.php new file mode 100644 index 00000000..c5c906c9 --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/PhpElement.php @@ -0,0 +1,26 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class PhpElement extends ManifestElement { + public function getVersion(): string { + return $this->getAttributeValue('version'); + } + + public function hasExtElements(): bool { + return $this->hasChild('ext'); + } + + public function getExtElements(): ExtElementCollection { + return new ExtElementCollection( + $this->getChildrenByName('ext') + ); + } +} diff --git a/vendor/phar-io/manifest/src/xml/RequiresElement.php b/vendor/phar-io/manifest/src/xml/RequiresElement.php new file mode 100644 index 00000000..b7cd41ef --- /dev/null +++ b/vendor/phar-io/manifest/src/xml/RequiresElement.php @@ -0,0 +1,18 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Manifest; + +class RequiresElement extends ManifestElement { + public function getPHPElement(): PhpElement { + return new PhpElement( + $this->getChildByName('php') + ); + } +} diff --git a/vendor/phar-io/version/CHANGELOG.md b/vendor/phar-io/version/CHANGELOG.md new file mode 100644 index 00000000..4c0edfa7 --- /dev/null +++ b/vendor/phar-io/version/CHANGELOG.md @@ -0,0 +1,142 @@ +# Changelog + +All notable changes to phar-io/version are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [3.2.1] - 2022-02-21 + +### Fixed + +- Have ExactVersionConstraint honor build metadata (added in 3.2.0) + + +## [3.2.0] - 2022-02-21 + +### Added + +- Build metadata is now supported and considered for equality checks only + + +## [3.1.1] - 2022-02-07 + +### Fixed + +- [#28](https://github.com/phar-io/version/issues/28): `VersionConstraintParser` does not support logical OR represented by single pipe (|) (Thanks @llaville) + + +## [3.1.0] - 2021-02-23 + +### Changed + +- Internal Refactoring +- More scalar types + +### Added + +- [#24](https://github.com/phar-io/version/issues/24): `Version::getOriginalString()` added (Thanks @addshore) +- Version constraints using the caret operator (`^`) now honor pre-1.0 releases, e.g. `^0.3` translates to `0.3.*`) +- Various integration tests for version constraint processing + +### Fixed + +- [#23](https://github.com/phar-io/version/pull/23): Tilde operator without patch level + + + +## [3.0.4] - 14.12.2020 + +### Fixed + +- [#22](https://github.com/phar-io/version/pull/22): make dev suffix rank works for uppercase too + +## [3.0.3] - 30.11.2020 + +### Added + +- Comparator method `Version::equals()` added + + +## [3.0.2] - 27.06.2020 + +This release now supports PHP 7.2+ and PHP ^8.0. No other changes included. + + +## [3.0.1] - 09.05.2020 + +__Potential BC Break Notice:__ +`Version::getVersionString()` no longer returns `v` prefixes in case the "input" +string contained one. These are not part of the semver specs +(see https://semver.org/#is-v123-a-semantic-version) and get stripped out. +As of Version 3.1.0 `Version::getOriginalString()` can be used to still +retrieve it as given. + +### Changed + +- Internal Refactoring +- More scalar types + +### Fixed + +- Fixed Constraint processing Regression for ^1.2 and ~1.2 + + +## [3.0.0] - 05.05.2020 + +### Changed + +- Require PHP 7.2+ +- All code now uses strict mode +- Scalar types have been added as needed + +### Added + +- The technically invalid format using 'v' prefix ("v1.2.3") is now properly supported + + +## [2.0.1] - 08.07.2018 + +### Fixed + +- Versions without a pre-release suffix are now always considered greater +than versions with a pre-release suffix. Example: `3.0.0 > 3.0.0-alpha.1` + + +## [2.0.0] - 23.06.2018 + +Changes to public API: + +- `PreReleaseSuffix::construct()`: optional parameter `$number` removed +- `PreReleaseSuffix::isGreaterThan()`: introduced +- `Version::hasPreReleaseSuffix()`: introduced + +### Added + +- [#11](https://github.com/phar-io/version/issues/11): Added support for pre-release version suffixes. Supported values are: + - `dev` + - `beta` (also abbreviated form `b`) + - `rc` + - `alpha` (also abbreviated form `a`) + - `patch` (also abbreviated form `p`) + + All values can be followed by a number, e.g. `beta3`. + + When comparing versions, the pre-release suffix is taken into account. Example: +`1.5.0 > 1.5.0-beta1 > 1.5.0-alpha3 > 1.5.0-alpha2 > 1.5.0-dev11` + +### Changed + +- reorganized the source directories + +### Fixed + +- [#10](https://github.com/phar-io/version/issues/10): Version numbers containing +a numeric suffix as seen in Debian packages are now supported. + + +[3.1.0]: https://github.com/phar-io/version/compare/3.0.4...3.1.0 +[3.0.4]: https://github.com/phar-io/version/compare/3.0.3...3.0.4 +[3.0.3]: https://github.com/phar-io/version/compare/3.0.2...3.0.3 +[3.0.2]: https://github.com/phar-io/version/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/phar-io/version/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/phar-io/version/compare/2.0.1...3.0.0 +[2.0.1]: https://github.com/phar-io/version/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/phar-io/version/compare/1.0.1...2.0.0 diff --git a/vendor/phar-io/version/LICENSE b/vendor/phar-io/version/LICENSE new file mode 100644 index 00000000..ce32758a --- /dev/null +++ b/vendor/phar-io/version/LICENSE @@ -0,0 +1,29 @@ +Copyright (c) 2016-2017 Arne Blankerts , Sebastian Heuer and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + diff --git a/vendor/phar-io/version/README.md b/vendor/phar-io/version/README.md new file mode 100644 index 00000000..76e6e985 --- /dev/null +++ b/vendor/phar-io/version/README.md @@ -0,0 +1,61 @@ +# Version + +Library for handling version information and constraints + +[![Build Status](https://travis-ci.org/phar-io/version.svg?branch=master)](https://travis-ci.org/phar-io/version) + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + + composer require phar-io/version + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + + composer require --dev phar-io/version + +## Version constraints + +A Version constraint describes a range of versions or a discrete version number. The format of version numbers follows the schema of [semantic versioning](http://semver.org): `..`. A constraint might contain an operator that describes the range. + +Beside the typical mathematical operators like `<=`, `>=`, there are two special operators: + +*Caret operator*: `^1.0` +can be written as `>=1.0.0 <2.0.0` and read as »every Version within major version `1`«. + +*Tilde operator*: `~1.0.0` +can be written as `>=1.0.0 <1.1.0` and read as »every version within minor version `1.1`. The behavior of tilde operator depends on whether a patch level version is provided or not. If no patch level is provided, tilde operator behaves like the caret operator: `~1.0` is identical to `^1.0`. + +## Usage examples + +Parsing version constraints and check discrete versions for compliance: + +```php + +use PharIo\Version\Version; +use PharIo\Version\VersionConstraintParser; + +$parser = new VersionConstraintParser(); +$caret_constraint = $parser->parse( '^7.0' ); + +$caret_constraint->complies( new Version( '7.0.17' ) ); // true +$caret_constraint->complies( new Version( '7.1.0' ) ); // true +$caret_constraint->complies( new Version( '6.4.34' ) ); // false + +$tilde_constraint = $parser->parse( '~1.1.0' ); + +$tilde_constraint->complies( new Version( '1.1.4' ) ); // true +$tilde_constraint->complies( new Version( '1.2.0' ) ); // false +``` + +As of version 2.0.0, pre-release labels are supported and taken into account when comparing versions: + +```php + +$leftVersion = new PharIo\Version\Version('3.0.0-alpha.1'); +$rightVersion = new PharIo\Version\Version('3.0.0-alpha.2'); + +$leftVersion->isGreaterThan($rightVersion); // false +$rightVersion->isGreaterThan($leftVersion); // true + +``` diff --git a/vendor/phar-io/version/composer.json b/vendor/phar-io/version/composer.json new file mode 100644 index 00000000..22687dcd --- /dev/null +++ b/vendor/phar-io/version/composer.json @@ -0,0 +1,34 @@ +{ + "name": "phar-io/version", + "description": "Library for handling version information and constraints", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "support": { + "issues": "https://github.com/phar-io/version/issues" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + } +} + diff --git a/vendor/phar-io/version/src/BuildMetaData.php b/vendor/phar-io/version/src/BuildMetaData.php new file mode 100644 index 00000000..d42f0363 --- /dev/null +++ b/vendor/phar-io/version/src/BuildMetaData.php @@ -0,0 +1,28 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class BuildMetaData { + + /** @var string */ + private $value; + + public function __construct(string $value) { + $this->value = $value; + } + + public function asString(): string { + return $this->value; + } + + public function equals(BuildMetaData $other): bool { + return $this->asString() === $other->asString(); + } +} diff --git a/vendor/phar-io/version/src/PreReleaseSuffix.php b/vendor/phar-io/version/src/PreReleaseSuffix.php new file mode 100644 index 00000000..00563008 --- /dev/null +++ b/vendor/phar-io/version/src/PreReleaseSuffix.php @@ -0,0 +1,82 @@ + 0, + 'a' => 1, + 'alpha' => 1, + 'b' => 2, + 'beta' => 2, + 'rc' => 3, + 'p' => 4, + 'pl' => 4, + 'patch' => 4, + ]; + + /** @var string */ + private $value; + + /** @var int */ + private $valueScore; + + /** @var int */ + private $number = 0; + + /** @var string */ + private $full; + + /** + * @throws InvalidPreReleaseSuffixException + */ + public function __construct(string $value) { + $this->parseValue($value); + } + + public function asString(): string { + return $this->full; + } + + public function getValue(): string { + return $this->value; + } + + public function getNumber(): ?int { + return $this->number; + } + + public function isGreaterThan(PreReleaseSuffix $suffix): bool { + if ($this->valueScore > $suffix->valueScore) { + return true; + } + + if ($this->valueScore < $suffix->valueScore) { + return false; + } + + return $this->getNumber() > $suffix->getNumber(); + } + + private function mapValueToScore(string $value): int { + $value = \strtolower($value); + + return self::valueScoreMap[$value]; + } + + private function parseValue(string $value): void { + $regex = '/-?((dev|beta|b|rc|alpha|a|patch|p|pl)\.?(\d*)).*$/i'; + + if (\preg_match($regex, $value, $matches) !== 1) { + throw new InvalidPreReleaseSuffixException(\sprintf('Invalid label %s', $value)); + } + + $this->full = $matches[1]; + $this->value = $matches[2]; + + if ($matches[3] !== '') { + $this->number = (int)$matches[3]; + } + + $this->valueScore = $this->mapValueToScore($matches[2]); + } +} diff --git a/vendor/phar-io/version/src/Version.php b/vendor/phar-io/version/src/Version.php new file mode 100644 index 00000000..644af5ca --- /dev/null +++ b/vendor/phar-io/version/src/Version.php @@ -0,0 +1,208 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class Version { + /** @var string */ + private $originalVersionString; + + /** @var VersionNumber */ + private $major; + + /** @var VersionNumber */ + private $minor; + + /** @var VersionNumber */ + private $patch; + + /** @var null|PreReleaseSuffix */ + private $preReleaseSuffix; + + /** @var null|BuildMetaData */ + private $buildMetadata; + + public function __construct(string $versionString) { + $this->ensureVersionStringIsValid($versionString); + $this->originalVersionString = $versionString; + } + + /** + * @throws NoPreReleaseSuffixException + */ + public function getPreReleaseSuffix(): PreReleaseSuffix { + if ($this->preReleaseSuffix === null) { + throw new NoPreReleaseSuffixException('No pre-release suffix set'); + } + + return $this->preReleaseSuffix; + } + + public function getOriginalString(): string { + return $this->originalVersionString; + } + + public function getVersionString(): string { + $str = \sprintf( + '%d.%d.%d', + $this->getMajor()->getValue() ?? 0, + $this->getMinor()->getValue() ?? 0, + $this->getPatch()->getValue() ?? 0 + ); + + if (!$this->hasPreReleaseSuffix()) { + return $str; + } + + return $str . '-' . $this->getPreReleaseSuffix()->asString(); + } + + public function hasPreReleaseSuffix(): bool { + return $this->preReleaseSuffix !== null; + } + + public function equals(Version $other): bool { + if ($this->getVersionString() !== $other->getVersionString()) { + return false; + } + + if ($this->hasBuildMetaData() !== $other->hasBuildMetaData()) { + return false; + } + + if ($this->hasBuildMetaData() && $other->hasBuildMetaData() && + !$this->getBuildMetaData()->equals($other->getBuildMetaData())) { + return false; + } + + return true; + } + + public function isGreaterThan(Version $version): bool { + if ($version->getMajor()->getValue() > $this->getMajor()->getValue()) { + return false; + } + + if ($version->getMajor()->getValue() < $this->getMajor()->getValue()) { + return true; + } + + if ($version->getMinor()->getValue() > $this->getMinor()->getValue()) { + return false; + } + + if ($version->getMinor()->getValue() < $this->getMinor()->getValue()) { + return true; + } + + if ($version->getPatch()->getValue() > $this->getPatch()->getValue()) { + return false; + } + + if ($version->getPatch()->getValue() < $this->getPatch()->getValue()) { + return true; + } + + if (!$version->hasPreReleaseSuffix() && !$this->hasPreReleaseSuffix()) { + return false; + } + + if ($version->hasPreReleaseSuffix() && !$this->hasPreReleaseSuffix()) { + return true; + } + + if (!$version->hasPreReleaseSuffix() && $this->hasPreReleaseSuffix()) { + return false; + } + + return $this->getPreReleaseSuffix()->isGreaterThan($version->getPreReleaseSuffix()); + } + + public function getMajor(): VersionNumber { + return $this->major; + } + + public function getMinor(): VersionNumber { + return $this->minor; + } + + public function getPatch(): VersionNumber { + return $this->patch; + } + + /** + * @psalm-assert-if-true BuildMetaData $this->buildMetadata + * @psalm-assert-if-true BuildMetaData $this->getBuildMetaData() + */ + public function hasBuildMetaData(): bool { + return $this->buildMetadata !== null; + } + + /** + * @throws NoBuildMetaDataException + */ + public function getBuildMetaData(): BuildMetaData { + if (!$this->hasBuildMetaData()) { + throw new NoBuildMetaDataException('No build metadata set'); + } + + return $this->buildMetadata; + } + + /** + * @param string[] $matches + * + * @throws InvalidPreReleaseSuffixException + */ + private function parseVersion(array $matches): void { + $this->major = new VersionNumber((int)$matches['Major']); + $this->minor = new VersionNumber((int)$matches['Minor']); + $this->patch = isset($matches['Patch']) ? new VersionNumber((int)$matches['Patch']) : new VersionNumber(0); + + if (isset($matches['PreReleaseSuffix']) && $matches['PreReleaseSuffix'] !== '') { + $this->preReleaseSuffix = new PreReleaseSuffix($matches['PreReleaseSuffix']); + } + + if (isset($matches['BuildMetadata'])) { + $this->buildMetadata = new BuildMetaData($matches['BuildMetadata']); + } + } + + /** + * @param string $version + * + * @throws InvalidVersionException + */ + private function ensureVersionStringIsValid($version): void { + $regex = '/^v? + (?P0|[1-9]\d*) + \\. + (?P0|[1-9]\d*) + (\\. + (?P0|[1-9]\d*) + )? + (?: + - + (?(?:(dev|beta|b|rc|alpha|a|patch|p|pl)\.?\d*)) + )? + (?: + \\+ + (?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-@]+)*) + )? + $/xi'; + + if (\preg_match($regex, $version, $matches) !== 1) { + throw new InvalidVersionException( + \sprintf("Version string '%s' does not follow SemVer semantics", $version) + ); + } + + $this->parseVersion($matches); + } +} diff --git a/vendor/phar-io/version/src/VersionConstraintParser.php b/vendor/phar-io/version/src/VersionConstraintParser.php new file mode 100644 index 00000000..03d6a095 --- /dev/null +++ b/vendor/phar-io/version/src/VersionConstraintParser.php @@ -0,0 +1,115 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class VersionConstraintParser { + /** + * @throws UnsupportedVersionConstraintException + */ + public function parse(string $value): VersionConstraint { + if (\strpos($value, '|') !== false) { + return $this->handleOrGroup($value); + } + + if (!\preg_match('/^[\^~*]?v?[\d.*]+(?:-.*)?$/i', $value)) { + throw new UnsupportedVersionConstraintException( + \sprintf('Version constraint %s is not supported.', $value) + ); + } + + switch ($value[0]) { + case '~': + return $this->handleTildeOperator($value); + case '^': + return $this->handleCaretOperator($value); + } + + $constraint = new VersionConstraintValue($value); + + if ($constraint->getMajor()->isAny()) { + return new AnyVersionConstraint(); + } + + if ($constraint->getMinor()->isAny()) { + return new SpecificMajorVersionConstraint( + $constraint->getVersionString(), + $constraint->getMajor()->getValue() ?? 0 + ); + } + + if ($constraint->getPatch()->isAny()) { + return new SpecificMajorAndMinorVersionConstraint( + $constraint->getVersionString(), + $constraint->getMajor()->getValue() ?? 0, + $constraint->getMinor()->getValue() ?? 0 + ); + } + + return new ExactVersionConstraint($constraint->getVersionString()); + } + + private function handleOrGroup(string $value): OrVersionConstraintGroup { + $constraints = []; + + foreach (\preg_split('{\s*\|\|?\s*}', \trim($value)) as $groupSegment) { + $constraints[] = $this->parse(\trim($groupSegment)); + } + + return new OrVersionConstraintGroup($value, $constraints); + } + + private function handleTildeOperator(string $value): AndVersionConstraintGroup { + $constraintValue = new VersionConstraintValue(\substr($value, 1)); + + if ($constraintValue->getPatch()->isAny()) { + return $this->handleCaretOperator($value); + } + + $constraints = [ + new GreaterThanOrEqualToVersionConstraint( + $value, + new Version(\substr($value, 1)) + ), + new SpecificMajorAndMinorVersionConstraint( + $value, + $constraintValue->getMajor()->getValue() ?? 0, + $constraintValue->getMinor()->getValue() ?? 0 + ) + ]; + + return new AndVersionConstraintGroup($value, $constraints); + } + + private function handleCaretOperator(string $value): AndVersionConstraintGroup { + $constraintValue = new VersionConstraintValue(\substr($value, 1)); + + $constraints = [ + new GreaterThanOrEqualToVersionConstraint($value, new Version(\substr($value, 1))) + ]; + + if ($constraintValue->getMajor()->getValue() === 0) { + $constraints[] = new SpecificMajorAndMinorVersionConstraint( + $value, + $constraintValue->getMajor()->getValue() ?? 0, + $constraintValue->getMinor()->getValue() ?? 0 + ); + } else { + $constraints[] = new SpecificMajorVersionConstraint( + $value, + $constraintValue->getMajor()->getValue() ?? 0 + ); + } + + return new AndVersionConstraintGroup( + $value, + $constraints + ); + } +} diff --git a/vendor/phar-io/version/src/VersionConstraintValue.php b/vendor/phar-io/version/src/VersionConstraintValue.php new file mode 100644 index 00000000..0762e7c0 --- /dev/null +++ b/vendor/phar-io/version/src/VersionConstraintValue.php @@ -0,0 +1,88 @@ +versionString = $versionString; + + $this->parseVersion($versionString); + } + + public function getLabel(): string { + return $this->label; + } + + public function getBuildMetaData(): string { + return $this->buildMetaData; + } + + public function getVersionString(): string { + return $this->versionString; + } + + public function getMajor(): VersionNumber { + return $this->major; + } + + public function getMinor(): VersionNumber { + return $this->minor; + } + + public function getPatch(): VersionNumber { + return $this->patch; + } + + private function parseVersion(string $versionString): void { + $this->extractBuildMetaData($versionString); + $this->extractLabel($versionString); + $this->stripPotentialVPrefix($versionString); + + $versionSegments = \explode('.', $versionString); + $this->major = new VersionNumber(\is_numeric($versionSegments[0]) ? (int)$versionSegments[0] : null); + + $minorValue = isset($versionSegments[1]) && \is_numeric($versionSegments[1]) ? (int)$versionSegments[1] : null; + $patchValue = isset($versionSegments[2]) && \is_numeric($versionSegments[2]) ? (int)$versionSegments[2] : null; + + $this->minor = new VersionNumber($minorValue); + $this->patch = new VersionNumber($patchValue); + } + + private function extractBuildMetaData(string &$versionString): void { + if (\preg_match('/\+(.*)/', $versionString, $matches) === 1) { + $this->buildMetaData = $matches[1]; + $versionString = \str_replace($matches[0], '', $versionString); + } + } + + private function extractLabel(string &$versionString): void { + if (\preg_match('/-(.*)/', $versionString, $matches) === 1) { + $this->label = $matches[1]; + $versionString = \str_replace($matches[0], '', $versionString); + } + } + + private function stripPotentialVPrefix(string &$versionString): void { + if ($versionString[0] !== 'v') { + return; + } + $versionString = \substr($versionString, 1); + } +} diff --git a/vendor/phar-io/version/src/VersionNumber.php b/vendor/phar-io/version/src/VersionNumber.php new file mode 100644 index 00000000..4833a9b0 --- /dev/null +++ b/vendor/phar-io/version/src/VersionNumber.php @@ -0,0 +1,28 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class VersionNumber { + + /** @var ?int */ + private $value; + + public function __construct(?int $value) { + $this->value = $value; + } + + public function isAny(): bool { + return $this->value === null; + } + + public function getValue(): ?int { + return $this->value; + } +} diff --git a/vendor/phar-io/version/src/constraints/AbstractVersionConstraint.php b/vendor/phar-io/version/src/constraints/AbstractVersionConstraint.php new file mode 100644 index 00000000..66201a14 --- /dev/null +++ b/vendor/phar-io/version/src/constraints/AbstractVersionConstraint.php @@ -0,0 +1,23 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +abstract class AbstractVersionConstraint implements VersionConstraint { + /** @var string */ + private $originalValue; + + public function __construct(string $originalValue) { + $this->originalValue = $originalValue; + } + + public function asString(): string { + return $this->originalValue; + } +} diff --git a/vendor/phar-io/version/src/constraints/AndVersionConstraintGroup.php b/vendor/phar-io/version/src/constraints/AndVersionConstraintGroup.php new file mode 100644 index 00000000..5096f2fb --- /dev/null +++ b/vendor/phar-io/version/src/constraints/AndVersionConstraintGroup.php @@ -0,0 +1,34 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class AndVersionConstraintGroup extends AbstractVersionConstraint { + /** @var VersionConstraint[] */ + private $constraints = []; + + /** + * @param VersionConstraint[] $constraints + */ + public function __construct(string $originalValue, array $constraints) { + parent::__construct($originalValue); + + $this->constraints = $constraints; + } + + public function complies(Version $version): bool { + foreach ($this->constraints as $constraint) { + if (!$constraint->complies($version)) { + return false; + } + } + + return true; + } +} diff --git a/vendor/phar-io/version/src/constraints/AnyVersionConstraint.php b/vendor/phar-io/version/src/constraints/AnyVersionConstraint.php new file mode 100644 index 00000000..1499f071 --- /dev/null +++ b/vendor/phar-io/version/src/constraints/AnyVersionConstraint.php @@ -0,0 +1,20 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class AnyVersionConstraint implements VersionConstraint { + public function complies(Version $version): bool { + return true; + } + + public function asString(): string { + return '*'; + } +} diff --git a/vendor/phar-io/version/src/constraints/ExactVersionConstraint.php b/vendor/phar-io/version/src/constraints/ExactVersionConstraint.php new file mode 100644 index 00000000..1d675c9c --- /dev/null +++ b/vendor/phar-io/version/src/constraints/ExactVersionConstraint.php @@ -0,0 +1,22 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class ExactVersionConstraint extends AbstractVersionConstraint { + public function complies(Version $version): bool { + $other = $version->getVersionString(); + + if ($version->hasBuildMetaData()) { + $other .= '+' . $version->getBuildMetaData()->asString(); + } + + return $this->asString() === $other; + } +} diff --git a/vendor/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php b/vendor/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php new file mode 100644 index 00000000..ec371723 --- /dev/null +++ b/vendor/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php @@ -0,0 +1,26 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class GreaterThanOrEqualToVersionConstraint extends AbstractVersionConstraint { + /** @var Version */ + private $minimalVersion; + + public function __construct(string $originalValue, Version $minimalVersion) { + parent::__construct($originalValue); + + $this->minimalVersion = $minimalVersion; + } + + public function complies(Version $version): bool { + return $version->getVersionString() === $this->minimalVersion->getVersionString() + || $version->isGreaterThan($this->minimalVersion); + } +} diff --git a/vendor/phar-io/version/src/constraints/OrVersionConstraintGroup.php b/vendor/phar-io/version/src/constraints/OrVersionConstraintGroup.php new file mode 100644 index 00000000..59fd382f --- /dev/null +++ b/vendor/phar-io/version/src/constraints/OrVersionConstraintGroup.php @@ -0,0 +1,35 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class OrVersionConstraintGroup extends AbstractVersionConstraint { + /** @var VersionConstraint[] */ + private $constraints = []; + + /** + * @param string $originalValue + * @param VersionConstraint[] $constraints + */ + public function __construct($originalValue, array $constraints) { + parent::__construct($originalValue); + + $this->constraints = $constraints; + } + + public function complies(Version $version): bool { + foreach ($this->constraints as $constraint) { + if ($constraint->complies($version)) { + return true; + } + } + + return false; + } +} diff --git a/vendor/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php b/vendor/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php new file mode 100644 index 00000000..302aa311 --- /dev/null +++ b/vendor/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php @@ -0,0 +1,33 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class SpecificMajorAndMinorVersionConstraint extends AbstractVersionConstraint { + /** @var int */ + private $major; + + /** @var int */ + private $minor; + + public function __construct(string $originalValue, int $major, int $minor) { + parent::__construct($originalValue); + + $this->major = $major; + $this->minor = $minor; + } + + public function complies(Version $version): bool { + if ($version->getMajor()->getValue() !== $this->major) { + return false; + } + + return $version->getMinor()->getValue() === $this->minor; + } +} diff --git a/vendor/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php b/vendor/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php new file mode 100644 index 00000000..968b809c --- /dev/null +++ b/vendor/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php @@ -0,0 +1,25 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class SpecificMajorVersionConstraint extends AbstractVersionConstraint { + /** @var int */ + private $major; + + public function __construct(string $originalValue, int $major) { + parent::__construct($originalValue); + + $this->major = $major; + } + + public function complies(Version $version): bool { + return $version->getMajor()->getValue() === $this->major; + } +} diff --git a/vendor/phar-io/version/src/constraints/VersionConstraint.php b/vendor/phar-io/version/src/constraints/VersionConstraint.php new file mode 100644 index 00000000..e94f9e00 --- /dev/null +++ b/vendor/phar-io/version/src/constraints/VersionConstraint.php @@ -0,0 +1,16 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +interface VersionConstraint { + public function complies(Version $version): bool; + + public function asString(): string; +} diff --git a/vendor/phar-io/version/src/exceptions/Exception.php b/vendor/phar-io/version/src/exceptions/Exception.php new file mode 100644 index 00000000..3ea458f3 --- /dev/null +++ b/vendor/phar-io/version/src/exceptions/Exception.php @@ -0,0 +1,15 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +use Throwable; + +interface Exception extends Throwable { +} diff --git a/vendor/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php b/vendor/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php new file mode 100644 index 00000000..bc0b0c3e --- /dev/null +++ b/vendor/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php @@ -0,0 +1,5 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +final class UnsupportedVersionConstraintException extends \RuntimeException implements Exception { +} diff --git a/vendor/php-stubs/wordpress-stubs/LICENSE b/vendor/php-stubs/wordpress-stubs/LICENSE new file mode 100644 index 00000000..84b563a5 --- /dev/null +++ b/vendor/php-stubs/wordpress-stubs/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Viktor Szépe + +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/php-stubs/wordpress-stubs/composer.json b/vendor/php-stubs/wordpress-stubs/composer.json new file mode 100644 index 00000000..c71c1e58 --- /dev/null +++ b/vendor/php-stubs/wordpress-stubs/composer.json @@ -0,0 +1,37 @@ +{ + "name": "php-stubs/wordpress-stubs", + "description": "WordPress function and class declaration stubs for static analysis.", + "license": "MIT", + "keywords": [ + "wordpress", + "static analysis", + "phpstan" + ], + "homepage": "https://github.com/php-stubs/wordpress-stubs", + "require-dev": { + "php": "~7.3 || ~8.0", + "nikic/php-parser": "< 4.12.0", + "php-stubs/generator": "^0.8.3", + "phpdocumentor/reflection-docblock": "^5.3", + "phpstan/phpstan": "^1.2" + }, + "suggest": { + "paragonie/sodium_compat": "Pure PHP implementation of libsodium", + "symfony/polyfill-php73": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan" + }, + "minimum-stability": "stable", + "config": { + "allow-plugins": { + "php-stubs/generator": true + } + }, + "scripts": { + "post-install-cmd": "@composer --working-dir=source/ update --no-interaction", + "post-update-cmd": "@composer --working-dir=source/ update --no-interaction", + "cleanup": "git status --short --ignored | sed -n -e 's#^!! ##p' | xargs -r rm -vrf" + }, + "scripts-descriptions": { + "cleanup": "Remove all ignored files." + } +} diff --git a/vendor/php-stubs/wordpress-stubs/functionMap.php b/vendor/php-stubs/wordpress-stubs/functionMap.php new file mode 100644 index 00000000..4e4dcec4 --- /dev/null +++ b/vendor/php-stubs/wordpress-stubs/functionMap.php @@ -0,0 +1,49 @@ +, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error'; +$cronArgsType = 'list'; + +/** + * This array is in the same format as the function map array in PHPStan: + * + * '' => ['', ''=>''] + * + * @link https://github.com/phpstan/phpstan-src/blob/1.5.x/resources/functionMap.php + */ +return [ + 'add_meta_box' => ['void', 'context'=>'"normal"|"side"|"advanced"', 'priority'=>'"high"|"core"|"default"|"low"'], + 'addslashes_gpc' => ['T', '@phpstan-template'=>'T', 'gpc'=>'T'], + 'rawurlencode_deep' => ['T', '@phpstan-template'=>'T', 'value'=>'T'], + 'remove_meta_box' => ['void', 'context'=>'"normal"|"side"|"advanced"'], + 'sanitize_category' => ['T', '@phpstan-template'=>'T of array|object', 'category'=>'T'], + 'sanitize_post' => ['T', '@phpstan-template'=>'T of array|object', 'post'=>'T'], + 'sanitize_term' => ['T', '@phpstan-template'=>'T of array|object', 'term'=>'T'], + 'stripslashes_deep' => ['T', '@phpstan-template'=>'T', 'value'=>'T'], + 'urldecode_deep' => ['T', '@phpstan-template'=>'T', 'value'=>'T'], + 'urlencode_deep' => ['T', '@phpstan-template'=>'T', 'value'=>'T'], + 'wp_clear_scheduled_hook' => ['int|false|WP_Error', 'args'=>$cronArgsType], + 'wp_get_schedule' => ['string|false', 'args'=>$cronArgsType], + 'wp_get_scheduled_event' => ['object|false', 'args'=>$cronArgsType], + 'WP_Http::get' => [$httpReturnType], + 'WP_Http::head' => [$httpReturnType], + 'WP_Http::post' => [$httpReturnType], + 'WP_Http::request' => [$httpReturnType], + 'WP_List_Table::bulk_actions' => ['void', 'which'=>'"top"|"bottom"'], + 'WP_List_Table::display_tablenav' => ['void', 'which'=>'"top"|"bottom"'], + 'WP_List_Table::pagination' => ['void', 'which'=>'"top"|"bottom"'], + 'wp_next_scheduled' => ['int|false', 'args'=>$cronArgsType], + 'wp_remote_get' => [$httpReturnType], + 'wp_remote_head' => [$httpReturnType], + 'wp_remote_post' => [$httpReturnType], + 'wp_remote_request' => [$httpReturnType], + 'wp_reschedule_event' => ['bool|WP_Error', 'args'=>$cronArgsType], + 'wp_safe_remote_get' => [$httpReturnType], + 'wp_safe_remote_head' => [$httpReturnType], + 'wp_safe_remote_post' => [$httpReturnType], + 'wp_safe_remote_request' => [$httpReturnType], + 'wp_schedule_event' => ['bool|WP_Error', 'args'=>$cronArgsType], + 'wp_schedule_single_event' => ['bool|WP_Error', 'args'=>$cronArgsType], + 'wp_slash' => ['T', '@phpstan-template'=>'T', 'value'=>'T'], + 'wp_unschedule_event' => ['bool|WP_Error', 'args'=>$cronArgsType], + 'wp_unslash' => ['T', '@phpstan-template'=>'T', 'value'=>'T'], +]; diff --git a/vendor/php-stubs/wordpress-stubs/phpstan.neon b/vendor/php-stubs/wordpress-stubs/phpstan.neon new file mode 100644 index 00000000..f83f2f0b --- /dev/null +++ b/vendor/php-stubs/wordpress-stubs/phpstan.neon @@ -0,0 +1,5 @@ +parameters: + level: 8 + paths: + - finder.php + - visitor.php diff --git a/vendor/php-stubs/wordpress-stubs/source/.gitignore b/vendor/php-stubs/wordpress-stubs/source/.gitignore new file mode 100644 index 00000000..2ea50ef7 --- /dev/null +++ b/vendor/php-stubs/wordpress-stubs/source/.gitignore @@ -0,0 +1,3 @@ +* +!/.gitignore +!/composer.json diff --git a/vendor/php-stubs/wordpress-stubs/source/composer.json b/vendor/php-stubs/wordpress-stubs/source/composer.json new file mode 100644 index 00000000..77e932a1 --- /dev/null +++ b/vendor/php-stubs/wordpress-stubs/source/composer.json @@ -0,0 +1,18 @@ +{ + "require": { + "php": "~7.3 || ~8.0", + "ext-gettext": "*", + "ext-hash": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-sodium": "*", + "johnpbloch/wordpress": "6.1.1" + }, + "minimum-stability": "stable", + "config": { + "allow-plugins": { + "johnpbloch/wordpress-core-installer": true + } + } +} diff --git a/vendor/php-stubs/wordpress-stubs/visitor.php b/vendor/php-stubs/wordpress-stubs/visitor.php new file mode 100644 index 00000000..5b536ae0 --- /dev/null +++ b/vendor/php-stubs/wordpress-stubs/visitor.php @@ -0,0 +1,887 @@ +children as $child) { + if ($child->name === null) { + return false; + } + } + + return true; + } + + public function isMixedShape(): bool + { + $hasStaticKey = false; + + foreach ($this->children as $child) { + if ($child->name !== null) { + $hasStaticKey = true; + } elseif ($hasStaticKey) { + return true; + } + } + + return false; + } +} + +final class WordPressTag extends WithChildren +{ + /** + * @var string + */ + public $tag; + + /** + * @var string + */ + public $type; + + /** + * @var ?string + */ + public $name = null; + + /** + * @var ?string + */ + public $description = null; + + /** + * @return string[] + */ + public function format(): array + { + if ($this->isMixedShape()) { + return []; + } + + $strings = []; + $childStrings = []; + $level = 1; + + if (! $this->isArrayShape()) { + $level = 0; + } + + foreach ($this->children as $child) { + $childStrings = array_merge($childStrings, $child->format($level)); + } + + if (count($childStrings) === 0) { + return []; + } + + $name = ($this->name !== null) ? (' $' . $this->name) : ''; + + if ($this->isArrayShape()) { + $strings[] = sprintf( + '%s %s{', + $this->tag, + $this->type + ); + } else { + if (count($this->children) > 0 && count($this->children[0]->children) > 0) { + $strings[] = sprintf( + '%s %stag, + $this->type + ); + } else { + $strings[] = sprintf( + '%s array%s', + $this->tag, + $this->type, + $name + ); + + return $strings; + } + } + + $strings = array_merge($strings, $childStrings); + $description = ''; + + if ($this->description !== null) { + $description = ' ' . $this->description; + } + + if ($this->isArrayShape()) { + $strings[] = sprintf( + '}%s%s', + $name, + $description + ); + } else { + $strings[] = sprintf( + '}>%s%s', + $name, + $description + ); + } + + return $strings; + } +} + +final class WordPressArg extends WithChildren +{ + /** + * @var string + */ + public $type; + + /** + * @var bool + */ + public $optional = false; + + /** + * @var ?string + */ + public $name = null; + + /** + * @return string[] + */ + public function format(int $level = 1): array + { + $strings = []; + $padding = str_repeat(' ', ($level * 2)); + + if ($this->isMixedShape()) { + return []; + } + + if (count($this->children) > 0) { + $childStrings = []; + + foreach ($this->children as $child) { + $childStrings = array_merge($childStrings, $child->format($level + 1)); + } + + if (count($childStrings) === 0) { + return []; + } + + if ($this->isArrayShape()) { + if ($this->name !== null) { + $strings[] = sprintf( + '%s%s%s: %s{', + $padding, + $this->name, + ($this->optional) ? '?' : '', + $this->type + ); + } + } else { + $strings[] = sprintf( + '%s%s%s: arrayname, + ($this->optional) ? '?' : '', + $this->type + ); + } + + $strings = array_merge($strings, $childStrings); + + if ($this->isArrayShape()) { + if ($this->name !== null) { + $strings[] = $padding . '},'; + } + } else { + $strings[] = $padding . '}>,'; + } + } else { + $strings[] = sprintf( + '%s%s%s: %s,', + $padding, + $this->name, + ($this->optional) ? '?' : '', + $this->type + ); + } + + return $strings; + } +} + +return new class extends NodeVisitor { + + /** + * @var \phpDocumentor\Reflection\DocBlockFactory + */ + private $docBlockFactory; + + /** + * @var ?array> + */ + private $functionMap = null; + + /** + * @var array> + */ + private $additionalTags = []; + + /** + * @var array> + */ + private $additionalTagStrings = []; + + public function __construct() + { + $this->docBlockFactory = \phpDocumentor\Reflection\DocBlockFactory::createInstance(); + } + + public function enterNode(Node $node) + { + parent::enterNode($node); + + if (!($node instanceof Function_) && !($node instanceof ClassMethod) && !($node instanceof Property)) { + return null; + } + + $docComment = $node->getDocComment(); + + if (!($docComment instanceof Doc)) { + return null; + } + + $symbolName = self::getNodeName($node); + + if ($node instanceof ClassMethod) { + /** @var \PhpParser\Node\Stmt\Class_ $parent */ + $parent = $this->stack[count($this->stack) - 2]; + + if (isset($parent->name)) { + $symbolName = sprintf( + '%1$s::%2$s', + $parent->name->name, + $node->name->name + ); + } + } + + $additions = $this->generateAdditionalTagsFromDoc($docComment); + $node->setAttribute('fullSymbolName', $symbolName); + + if (count($additions) > 0) { + $this->additionalTags[ $symbolName ] = $additions; + } + + $additions = $this->getAdditionalTagsFromMap($symbolName); + + if (count($additions) > 0) { + $this->additionalTagStrings[ $symbolName ] = $additions; + } + + return null; + } + + private static function getNodeName(Node $node): string + { + if (($node instanceof Function_) || ($node instanceof ClassMethod)) { + return $node->name->name; + } + + if ($node instanceof Property) { + return sprintf( + 'property_%s', + uniqid() + ); + } + + return ''; + } + + /** + * @return Node[] + */ + public function getStubStmts(): array + { + $stmts = parent::getStubStmts(); + + foreach ($stmts as $stmt) { + $this->postProcessNode($stmt); + } + + return $stmts; + } + + private function postProcessNode(Node $node): void + { + if (isset($node->stmts) && is_array($node->stmts)) { + foreach ($node->stmts as $stmt) { + $this->postProcessNode($stmt); + } + } + + if (! ($node instanceof Function_) && ! ($node instanceof ClassMethod) && ! ($node instanceof Property)) { + return; + } + + $name = $node->getAttribute('fullSymbolName'); + + if ($name === null) { + return; + } + + $docComment = $node->getDocComment(); + + if (!($docComment instanceof Doc)) { + return; + } + + $newDocComment = $this->addTags($name, $docComment); + + if ($newDocComment !== null) { + $node->setDocComment($newDocComment); + } + + if (! isset($this->additionalTagStrings[ $name ])) { + return; + } + + $docComment = $node->getDocComment(); + + if (!($docComment instanceof Doc)) { + return; + } + + $newDocComment = $this->addStringTags($name, $docComment); + + if ($newDocComment !== null) { + $node->setDocComment($newDocComment); + } + } + + /** + * @return array + */ + private function generateAdditionalTagsFromDoc(Doc $docComment): array + { + $docCommentText = $docComment->getText(); + + try { + $docblock = $this->docBlockFactory->create($docCommentText); + } catch ( \RuntimeException $e ) { + return []; + } catch ( \InvalidArgumentException $e ) { + return []; + } + + /** @var \phpDocumentor\Reflection\DocBlock\Tags\Param[] */ + $params = $docblock->getTagsByName('param'); + + /** @var \phpDocumentor\Reflection\DocBlock\Tags\Return_[] */ + $returns = $docblock->getTagsByName('return'); + + /** @var \phpDocumentor\Reflection\DocBlock\Tags\Var_[] */ + $vars = $docblock->getTagsByName('var'); + + /** @var WordPressTag[] $additions */ + $additions = []; + + foreach ($params as $param) { + if (! $param instanceof Param) { + continue; + } + + $addition = self::getAdditionFromParam($param); + + if ($addition !== null) { + $additions[] = $addition; + } + } + + foreach ($returns as $return) { + if (! $return instanceof Return_) { + continue; + } + + $addition = self::getAdditionFromReturn($return); + + if ($addition !== null) { + $additions[] = $addition; + } + } + + foreach ($vars as $var) { + if (! $var instanceof Var_) { + continue; + } + + $addition = self::getAdditionFromVar($var); + + if ($addition !== null) { + $additions[] = $addition; + } + } + + return $additions; + } + + private function addTags(string $name, Doc $docComment): ?Doc + { + if (isset($this->additionalTags[ $name ])) { + $additions = $this->additionalTags[ $name ]; + } else { + $additions = []; + } + + $docCommentText = $docComment->getText(); + + try { + $docblock = $this->docBlockFactory->create($docCommentText); + } catch ( \RuntimeException $e ) { + return null; + } catch ( \InvalidArgumentException $e ) { + return null; + } + + $additions = $this->discoverInheritedArgs($docblock, $additions); + + /** @var string[] $additionStrings */ + $additionStrings = array_map( function(WordPressTag $tag): string { + $lines = $tag->format(); + + if (count($lines) === 0) { + return ''; + } + + return " * " . implode("\n * ", $lines); + }, $additions); + + $additionStrings = array_filter($additionStrings); + + if (count($additionStrings) === 0) { + return null; + } + + $newDocComment = sprintf( + "%s\n%s\n */", + substr($docCommentText, 0, -4), + implode("\n", $additionStrings) + ); + + return new Doc($newDocComment, $docComment->getStartLine(), $docComment->getStartFilePos()); + } + + /** + * @param array $additions + * @return array + */ + private function discoverInheritedArgs(DocBlock $docblock, array $additions): array + { + /** @var Param[] $params */ + $params = $docblock->getTagsByName('param'); + + $phpStanParams = array_filter($additions, function(WordPressTag $addition): bool { + return $addition->tag === '@phpstan-param'; + }); + + foreach ($params as $param) { + $inherited = $this->getInheritedTagsForParam($param); + + if (count($inherited) === 0) { + continue; + } + + foreach ($phpStanParams as $addition) { + foreach ($inherited as $inherit) { + if ($addition->name !== $inherit->name) { + continue; + } + + $addition->children = array_merge($addition->children, $inherit->children); + continue 3; + } + } + + $additions = array_merge($additions, $inherited); + } + + return $additions; + } + + /** + * @return array + */ + private function getInheritedTagsForParam(Param $param): array + { + $type = $param->getType(); + + if ($type === null) { + return []; + } + + $typeName = self::getTypeNameFromType($type); + + if ($typeName === null) { + return []; + } + + $paramDescription = $param->getDescription(); + + if ($paramDescription === null) { + return []; + } + + list($description) = explode("\n\n", $paramDescription->__toString()); + + if (strpos($description, '()') === false) { + return []; + } + + $description = str_replace("\n", ' ', $description); + $additions = []; + + foreach ($this->additionalTags as $symbolName => $tags) { + $search = sprintf( + 'see %s()', + $symbolName + ); + + if (stripos($description, $search) === false) { + continue; + } + + $match = self::getMatchingInheritedTag($param, $tags, $symbolName); + + if ($match !== null) { + $additions[] = $match; + } + } + + return $additions; + } + + /** + * @param array $tags + */ + private static function getMatchingInheritedTag(Param $param, array $tags, string $symbolName): ?WordPressTag + { + $paramName = $param->getVariableName(); + $matchNames = [ + $paramName, + 'args', + 'options', + 'query', + ]; + $matchingTags = array_filter($tags, static function(WordPressTag $tag) use ($matchNames): bool { + return in_array($tag->name, $matchNames, true); + }); + + foreach ($matchingTags as $tag) { + $addTag = clone $tag; + $addTag->name = $paramName; + $addTag->description = sprintf( + 'See %s()', + $symbolName + ); + + return $addTag; + } + + return null; + } + + /** + * @return string[] + */ + private function getAdditionalTagsFromMap(string $symbolName): array + { + if (! isset($this->functionMap)) { + $this->functionMap = require __DIR__ . '/functionMap.php'; + } + + if (! isset($this->functionMap[$symbolName])) { + return []; + } + + $parameters = $this->functionMap[$symbolName]; + $returnType = array_shift($parameters); + $additions = []; + + foreach ($parameters as $paramName => $paramType) { + if (strpos($paramName, '@') === 0) { + $additions[] = sprintf( + '%s %s', + $paramName, + $paramType + ); + continue; + } + + $additions[] = sprintf( + '@phpstan-param %s $%s', + $paramType, + $paramName + ); + } + + $additions[] = sprintf( + '@phpstan-return %s', + $returnType + ); + + return $additions; + } + + private function addStringTags(string $name, Doc $docComment): ?Doc + { + if ( !isset($this->additionalTagStrings[ $name ])) { + return null; + } + + $additions = $this->additionalTagStrings[ $name ]; + + $docCommentText = $docComment->getText(); + $newDocComment = sprintf( + "%s\n * %s\n */", + substr($docCommentText, 0, -4), + implode("\n * ", $additions) + ); + + return new Doc($newDocComment, $docComment->getStartLine(), $docComment->getStartFilePos()); + } + + private function getAdditionFromParam(Param $tag): ?WordPressTag + { + $tagDescription = $tag->getDescription(); + $tagVariableName = $tag->getVariableName(); + $tagVariableType = $tag->getType(); + + // Skip if information we need is missing. + if (!$tagDescription || !$tagVariableName || !$tagVariableType) { + return null; + } + + $elements = self::getElementsFromDescription($tagDescription, true); + + if (count($elements) === 0) { + return null; + } + + $tagVariableType = self::getTypeNameFromType($tagVariableType); + + if ($tagVariableType === null) { + return null; + } + + // It's common for an args parameter to accept a query var string or array with `string|array`. + // Remove the accepted string type for these so we get the strongest typing we can manage. + $tagVariableType = str_replace(['|string', 'string|'], '', $tagVariableType); + + $tag = new WordPressTag(); + $tag->tag = '@phpstan-param'; + $tag->type = $tagVariableType; + $tag->name = $tagVariableName; + $tag->children = $elements; + + return $tag; + } + + private function getAdditionFromReturn(Return_ $tag): ?WordPressTag + { + $tagDescription = $tag->getDescription(); + $tagVariableType = $tag->getType(); + + // Skip if information we need is missing. + if (!$tagDescription || !$tagVariableType) { + return null; + } + + $elements = self::getElementsFromDescription($tagDescription, false); + + if (count($elements) === 0) { + return null; + } + + $tagVariableType = self::getTypeNameFromType($tagVariableType); + + if ($tagVariableType === null) { + return null; + } + + $tag = new WordPressTag(); + $tag->tag = '@phpstan-return'; + $tag->type = $tagVariableType; + $tag->children = $elements; + + return $tag; + } + + private static function getAdditionFromVar(Var_ $tag): ?WordPressTag + { + $tagDescription = $tag->getDescription(); + $tagVariableType = $tag->getType(); + + // Skip if information we need is missing. + if (!$tagDescription || !$tagVariableType) { + return null; + } + + $elements = self::getElementsFromDescription($tagDescription, false); + + if (count($elements) === 0) { + return null; + } + + $tagVariableType = self::getTypeNameFromType($tagVariableType); + + if ($tagVariableType === null) { + return null; + } + + $tag = new WordPressTag(); + $tag->tag = '@phpstan-var'; + $tag->type = $tagVariableType; + $tag->children = $elements; + + return $tag; + } + + private static function getTypeNameFromType(Type $tagVariableType): ?string + { + return self::getTypeNameFromString($tagVariableType->__toString()); + } + + private static function getTypeNameFromString(string $tagVariable): ?string + { + // PHPStan doesn't support typed array shapes (`int[]{...}`) so replace + // typed arrays such as `int[]` with `array`. + $tagVariableType = preg_replace('#[a-zA-Z0-9_]+\[\]#', 'array', $tagVariable); + + if ($tagVariableType === null) { + return null; + } + + if (strpos($tagVariableType, 'array') === false) { + // Skip if we have hash notation that's not for an array (ie. for `object`). + return null; + } + + if (strpos($tagVariableType, 'array|') !== false) { + // Move `array` to the end of union types so the appended array shape works. + $tagVariableType = str_replace('array|', '', $tagVariableType) . '|array'; + } + + return $tagVariableType; + } + + /** + * @return WordPressArg[] + */ + private static function getElementsFromDescription(Description $tagDescription, bool $optional): array + { + $text = $tagDescription->__toString(); + + // Skip if the description doesn't contain at least one correctly + // formatted `@type`, which indicates an array hash. + if (strpos($text, ' @type ') === false) { + return []; + } + + return self::getTypesAtLevel($text, $optional, 1); + } + + /** + * @return WordPressArg[] + */ + private static function getTypesAtLevel(string $text, bool $optional, int $level): array + { + // Populate `$types` with the value of each top level `@type`. + $spaces = str_repeat(' ', ($level * 4)); + $types = preg_split("/\R+{$spaces}@type /", $text); + + if ($types === false) { + return []; + } + + unset($types[0]); + $elements = []; + + foreach ($types as $typeTag) { + $parts = preg_split('#\s+#', trim($typeTag), 3); + + if ($parts === false || count($parts) < 2) { + return []; + } + + list($type, $name) = $parts; + + $optionalArg = $optional; + $nameTrimmed = ltrim($name, '$'); + + if (is_numeric($nameTrimmed)) { + $optionalArg = false; + } elseif ($optional && ($level > 1)) { + $optionalArg = isset($parts[2]) && self::isOptional($parts[2]); + } + + if (strpos($name, '...$') !== false) { + $name = null; + } elseif (strpos($name, '$') !== 0) { + return []; + } else { + $name = $nameTrimmed; + } + + $arg = new WordPressArg(); + $arg->type = $type; + $arg->optional = $optionalArg; + $arg->name = $name; + + $nextLevel = $level + 1; + $subTypes = self::getTypesAtLevel($typeTag, $optional, $nextLevel); + + if (count($subTypes) > 0) { + $type = self::getTypeNameFromString($type); + + if ($type !== null) { + $arg->type = $type; + } + $arg->children = $subTypes; + } + + $elements[] = $arg; + } + + return $elements; + } + + private static function isOptional(string $description): bool + { + return (stripos($description, 'Optional') !== false) + || (stripos($description, 'Default ') !== false) + || (stripos($description, 'Default: ') !== false) + || (stripos($description, 'Defaults to ') !== false) + ; + } +}; diff --git a/vendor/php-stubs/wordpress-stubs/wordpress-stubs.php b/vendor/php-stubs/wordpress-stubs/wordpress-stubs.php new file mode 100644 index 00000000..d0c3a90b --- /dev/null +++ b/vendor/php-stubs/wordpress-stubs/wordpress-stubs.php @@ -0,0 +1,131524 @@ + + // + // + function parselisting($line) + { + } + function SendMSG($message = "", $crlf = \true) + { + } + function SetType($mode = \FTP_AUTOASCII) + { + } + function _settype($mode = \FTP_ASCII) + { + } + function Passive($pasv = \NULL) + { + } + function SetServer($host, $port = 21, $reconnect = \true) + { + } + function SetUmask($umask = 022) + { + } + function SetTimeout($timeout = 30) + { + } + function connect($server = \NULL) + { + } + function quit($force = \false) + { + } + function login($user = \NULL, $pass = \NULL) + { + } + function pwd() + { + } + function cdup() + { + } + function chdir($pathname) + { + } + function rmdir($pathname) + { + } + function mkdir($pathname) + { + } + function rename($from, $to) + { + } + function filesize($pathname) + { + } + function abort() + { + } + function mdtm($pathname) + { + } + function systype() + { + } + function delete($pathname) + { + } + function site($command, $fnction = "site") + { + } + function chmod($pathname, $mode) + { + } + function restore($from) + { + } + function features() + { + } + function rawlist($pathname = "", $arg = "") + { + } + function nlist($pathname = "", $arg = "") + { + } + function is_exists($pathname) + { + } + function file_exists($pathname) + { + } + function fget($fp, $remotefile, $rest = 0) + { + } + function get($remotefile, $localfile = \NULL, $rest = 0) + { + } + function fput($remotefile, $fp, $rest = 0) + { + } + function put($localfile, $remotefile = \NULL, $rest = 0) + { + } + function mput($local = ".", $remote = \NULL, $continious = \false) + { + } + function mget($remote, $local = ".", $continious = \false) + { + } + function mdel($remote, $continious = \false) + { + } + function mmkdir($dir, $mode = 0777) + { + } + function glob($pattern, $handle = \NULL) + { + } + function glob_pattern_match($pattern, $subject) + { + } + function glob_regexp($pattern, $subject) + { + } + function dirlist($remote) + { + } + // + // + // + function _checkCode() + { + } + function _list($arg = "", $cmd = "LIST", $fnction = "_list") + { + } + // + // + // + // Gnre une erreur pour traitement externe la classe + function PushError($fctname, $msg, $desc = \false) + { + } + // Rcupre une erreur externe + function PopError() + { + } + } + /** + * PemFTP - An Ftp implementation in pure PHP + * + * @package PemFTP + * @since 2.5.0 + * + * @version 1.0 + * @copyright Alexey Dotsenko + * @author Alexey Dotsenko + * @link https://www.phpclasses.org/package/1743-PHP-FTP-client-in-pure-PHP.html + * @license LGPL https://opensource.org/licenses/lgpl-license.html + */ + /** + * FTP implementation using fsockopen to connect. + * + * @package PemFTP + * @subpackage Pure + * @since 2.5.0 + * + * @version 1.0 + * @copyright Alexey Dotsenko + * @author Alexey Dotsenko + * @link https://www.phpclasses.org/package/1743-PHP-FTP-client-in-pure-PHP.html + * @license LGPL https://opensource.org/licenses/lgpl-license.html + */ + class ftp_pure extends \ftp_base + { + function __construct($verb = \FALSE, $le = \FALSE) + { + } + // + // + // + function _settimeout($sock) + { + } + function _connect($host, $port) + { + } + function _readmsg($fnction = "_readmsg") + { + } + function _exec($cmd, $fnction = "_exec") + { + } + function _data_prepare($mode = \FTP_ASCII) + { + } + function _data_read($mode = \FTP_ASCII, $fp = \NULL) + { + } + function _data_write($mode = \FTP_ASCII, $fp = \NULL) + { + } + function _data_write_block($mode, $block) + { + } + function _data_close() + { + } + function _quit($force = \FALSE) + { + } + } + /** + * PemFTP - An Ftp implementation in pure PHP + * + * @package PemFTP + * @since 2.5.0 + * + * @version 1.0 + * @copyright Alexey Dotsenko + * @author Alexey Dotsenko + * @link https://www.phpclasses.org/package/1743-PHP-FTP-client-in-pure-PHP.html + * @license LGPL https://opensource.org/licenses/lgpl-license.html + */ + /** + * Socket Based FTP implementation + * + * @package PemFTP + * @subpackage Socket + * @since 2.5.0 + * + * @version 1.0 + * @copyright Alexey Dotsenko + * @author Alexey Dotsenko + * @link https://www.phpclasses.org/package/1743-PHP-FTP-client-in-pure-PHP.html + * @license LGPL https://opensource.org/licenses/lgpl-license.html + */ + class ftp_sockets extends \ftp_base + { + function __construct($verb = \FALSE, $le = \FALSE) + { + } + // + // + // + function _settimeout($sock) + { + } + function _connect($host, $port) + { + } + function _readmsg($fnction = "_readmsg") + { + } + function _exec($cmd, $fnction = "_exec") + { + } + function _data_prepare($mode = \FTP_ASCII) + { + } + function _data_read($mode = \FTP_ASCII, $fp = \NULL) + { + } + function _data_write($mode = \FTP_ASCII, $fp = \NULL) + { + } + function _data_write_block($mode, $block) + { + } + function _data_close() + { + } + function _quit() + { + } + } + class ftp extends \ftp_sockets + { + } + /** + * Upgrader API: Language_Pack_Upgrader_Skin class + * + * @package WordPress + * @subpackage Upgrader + * @since 4.6.0 + */ + /** + * Translation Upgrader Skin for WordPress Translation Upgrades. + * + * @since 3.7.0 + * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php. + * + * @see WP_Upgrader_Skin + */ + class Language_Pack_Upgrader_Skin extends \WP_Upgrader_Skin + { + public $language_update = \null; + public $done_header = \false; + public $done_footer = \false; + public $display_footer_actions = \true; + /** + * @param array $args + */ + public function __construct($args = array()) + { + } + /** + */ + public function before() + { + } + /** + * @since 5.9.0 Renamed `$error` to `$errors` for PHP 8 named parameter support. + * + * @param string|WP_Error $errors Errors. + */ + public function error($errors) + { + } + /** + */ + public function after() + { + } + /** + */ + public function bulk_footer() + { + } + } + /** + * Upgrade API: Language_Pack_Upgrader class + * + * @package WordPress + * @subpackage Upgrader + * @since 4.6.0 + */ + /** + * Core class used for updating/installing language packs (translations) + * for plugins, themes, and core. + * + * @since 3.7.0 + * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader.php. + * + * @see WP_Upgrader + */ + class Language_Pack_Upgrader extends \WP_Upgrader + { + /** + * Result of the language pack upgrade. + * + * @since 3.7.0 + * @var array|WP_Error $result + * @see WP_Upgrader::$result + */ + public $result; + /** + * Whether a bulk upgrade/installation is being performed. + * + * @since 3.7.0 + * @var bool $bulk + */ + public $bulk = \true; + /** + * Asynchronously upgrades language packs after other upgrades have been made. + * + * Hooked to the {@see 'upgrader_process_complete'} action by default. + * + * @since 3.7.0 + * + * @param false|WP_Upgrader $upgrader Optional. WP_Upgrader instance or false. If `$upgrader` is + * a Language_Pack_Upgrader instance, the method will bail to + * avoid recursion. Otherwise unused. Default false. + */ + public static function async_upgrade($upgrader = \false) + { + } + /** + * Initialize the upgrade strings. + * + * @since 3.7.0 + */ + public function upgrade_strings() + { + } + /** + * Upgrade a language pack. + * + * @since 3.7.0 + * + * @param string|false $update Optional. Whether an update offer is available. Default false. + * @param array $args Optional. Other optional arguments, see + * Language_Pack_Upgrader::bulk_upgrade(). Default empty array. + * @return array|bool|WP_Error The result of the upgrade, or a WP_Error object instead. + * @phpstan-param array{ + * clear_update_cache?: bool, + * } $args See Language_Pack_Upgrader::bulk_upgrade() + */ + public function upgrade($update = \false, $args = array()) + { + } + /** + * Bulk upgrade language packs. + * + * @since 3.7.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param object[] $language_updates Optional. Array of language packs to update. @see wp_get_translation_updates(). + * Default empty array. + * @param array $args { + * Other arguments for upgrading multiple language packs. Default empty array. + * + * @type bool $clear_update_cache Whether to clear the update cache when done. + * Default true. + * } + * @return array|bool|WP_Error Will return an array of results, or true if there are no updates, + * false or WP_Error for initial errors. + * @phpstan-param array{ + * clear_update_cache?: bool, + * } $args + */ + public function bulk_upgrade($language_updates = array(), $args = array()) + { + } + /** + * Checks that the package source contains .mo and .po files. + * + * Hooked to the {@see 'upgrader_source_selection'} filter by + * Language_Pack_Upgrader::bulk_upgrade(). + * + * @since 3.7.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param string|WP_Error $source The path to the downloaded package source. + * @param string $remote_source Remote file source location. + * @return string|WP_Error The source as passed, or a WP_Error object on failure. + */ + public function check_package($source, $remote_source) + { + } + /** + * Get the name of an item being updated. + * + * @since 3.7.0 + * + * @param object $update The data for an update. + * @return string The name of the item being updated. + */ + public function get_name_for_update($update) + { + } + /** + * Clears existing translations where this item is going to be installed into. + * + * @since 5.1.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param string $remote_destination The location on the remote filesystem to be cleared. + * @return bool|WP_Error True upon success, WP_Error on failure. + */ + public function clear_destination($remote_destination) + { + } + } + /* For futur use + define( 'PCLZIP_CB_PRE_LIST', 78005 ); + define( 'PCLZIP_CB_POST_LIST', 78006 ); + define( 'PCLZIP_CB_PRE_DELETE', 78007 ); + define( 'PCLZIP_CB_POST_DELETE', 78008 ); + */ + // -------------------------------------------------------------------------------- + // Class : PclZip + // Description : + // PclZip is the class that represent a Zip archive. + // The public methods allow the manipulation of the archive. + // Attributes : + // Attributes must not be accessed directly. + // Methods : + // PclZip() : Object creator + // create() : Creates the Zip archive + // listContent() : List the content of the Zip archive + // extract() : Extract the content of the archive + // properties() : List the properties of the archive + // -------------------------------------------------------------------------------- + class PclZip + { + // ----- Filename of the zip file + var $zipname = ''; + // ----- File descriptor of the zip file + var $zip_fd = 0; + // ----- Internal error handling + var $error_code = 1; + var $error_string = ''; + // ----- Current status of the magic_quotes_runtime + // This value store the php configuration for magic_quotes + // The class can then disable the magic_quotes and reset it after + var $magic_quotes_status; + // -------------------------------------------------------------------------------- + // Function : PclZip() + // Description : + // Creates a PclZip object and set the name of the associated Zip archive + // filename. + // Note that no real action is taken, if the archive does not exist it is not + // created. Use create() for that. + // -------------------------------------------------------------------------------- + function __construct($p_zipname) + { + } + public function PclZip($p_zipname) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : + // create($p_filelist, $p_add_dir="", $p_remove_dir="") + // create($p_filelist, $p_option, $p_option_value, ...) + // Description : + // This method supports two different synopsis. The first one is historical. + // This method creates a Zip Archive. The Zip file is created in the + // filesystem. The files and directories indicated in $p_filelist + // are added in the archive. See the parameters description for the + // supported format of $p_filelist. + // When a directory is in the list, the directory and its content is added + // in the archive. + // In this synopsis, the function takes an optional variable list of + // options. See below the supported options. + // Parameters : + // $p_filelist : An array containing file or directory names, or + // a string containing one filename or one directory name, or + // a string containing a list of filenames and/or directory + // names separated by spaces. + // $p_add_dir : A path to add before the real path of the archived file, + // in order to have it memorized in the archive. + // $p_remove_dir : A path to remove from the real path of the file to archive, + // in order to have a shorter path memorized in the archive. + // When $p_add_dir and $p_remove_dir are set, $p_remove_dir + // is removed first, before $p_add_dir is added. + // Options : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_COMMENT : + // PCLZIP_CB_PRE_ADD : + // PCLZIP_CB_POST_ADD : + // Return Values : + // 0 on failure, + // The list of the added files, with a status of the add action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function create($p_filelist) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : + // add($p_filelist, $p_add_dir="", $p_remove_dir="") + // add($p_filelist, $p_option, $p_option_value, ...) + // Description : + // This method supports two synopsis. The first one is historical. + // This methods add the list of files in an existing archive. + // If a file with the same name already exists, it is added at the end of the + // archive, the first one is still present. + // If the archive does not exist, it is created. + // Parameters : + // $p_filelist : An array containing file or directory names, or + // a string containing one filename or one directory name, or + // a string containing a list of filenames and/or directory + // names separated by spaces. + // $p_add_dir : A path to add before the real path of the archived file, + // in order to have it memorized in the archive. + // $p_remove_dir : A path to remove from the real path of the file to archive, + // in order to have a shorter path memorized in the archive. + // When $p_add_dir and $p_remove_dir are set, $p_remove_dir + // is removed first, before $p_add_dir is added. + // Options : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_COMMENT : + // PCLZIP_OPT_ADD_COMMENT : + // PCLZIP_OPT_PREPEND_COMMENT : + // PCLZIP_CB_PRE_ADD : + // PCLZIP_CB_POST_ADD : + // Return Values : + // 0 on failure, + // The list of the added files, with a status of the add action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function add($p_filelist) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : listContent() + // Description : + // This public method, gives the list of the files and directories, with their + // properties. + // The properties of each entries in the list are (used also in other functions) : + // filename : Name of the file. For a create or add action it is the filename + // given by the user. For an extract function it is the filename + // of the extracted file. + // stored_filename : Name of the file / directory stored in the archive. + // size : Size of the stored file. + // compressed_size : Size of the file's data compressed in the archive + // (without the headers overhead) + // mtime : Last known modification date of the file (UNIX timestamp) + // comment : Comment associated with the file + // folder : true | false + // index : index of the file in the archive + // status : status of the action (depending of the action) : + // Values are : + // ok : OK ! + // filtered : the file / dir is not extracted (filtered by user) + // already_a_directory : the file can not be extracted because a + // directory with the same name already exists + // write_protected : the file can not be extracted because a file + // with the same name already exists and is + // write protected + // newer_exist : the file was not extracted because a newer file exists + // path_creation_fail : the file is not extracted because the folder + // does not exist and can not be created + // write_error : the file was not extracted because there was a + // error while writing the file + // read_error : the file was not extracted because there was a error + // while reading the file + // invalid_header : the file was not extracted because of an archive + // format error (bad file header) + // Note that each time a method can continue operating when there + // is an action error on a file, the error is only logged in the file status. + // Return Values : + // 0 on an unrecoverable failure, + // The list of the files in the archive. + // -------------------------------------------------------------------------------- + function listContent() + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : + // extract($p_path="./", $p_remove_path="") + // extract([$p_option, $p_option_value, ...]) + // Description : + // This method supports two synopsis. The first one is historical. + // This method extract all the files / directories from the archive to the + // folder indicated in $p_path. + // If you want to ignore the 'root' part of path of the memorized files + // you can indicate this in the optional $p_remove_path parameter. + // By default, if a newer file with the same name already exists, the + // file is not extracted. + // + // If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH options + // are used, the path indicated in PCLZIP_OPT_ADD_PATH is append + // at the end of the path value of PCLZIP_OPT_PATH. + // Parameters : + // $p_path : Path where the files and directories are to be extracted + // $p_remove_path : First part ('root' part) of the memorized path + // (if any similar) to remove while extracting. + // Options : + // PCLZIP_OPT_PATH : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_CB_PRE_EXTRACT : + // PCLZIP_CB_POST_EXTRACT : + // Return Values : + // 0 or a negative value on failure, + // The list of the extracted files, with a status of the action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function extract() + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : + // extractByIndex($p_index, $p_path="./", $p_remove_path="") + // extractByIndex($p_index, [$p_option, $p_option_value, ...]) + // Description : + // This method supports two synopsis. The first one is historical. + // This method is doing a partial extract of the archive. + // The extracted files or folders are identified by their index in the + // archive (from 0 to n). + // Note that if the index identify a folder, only the folder entry is + // extracted, not all the files included in the archive. + // Parameters : + // $p_index : A single index (integer) or a string of indexes of files to + // extract. The form of the string is "0,4-6,8-12" with only numbers + // and '-' for range or ',' to separate ranges. No spaces or ';' + // are allowed. + // $p_path : Path where the files and directories are to be extracted + // $p_remove_path : First part ('root' part) of the memorized path + // (if any similar) to remove while extracting. + // Options : + // PCLZIP_OPT_PATH : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and + // not as files. + // The resulting content is in a new field 'content' in the file + // structure. + // This option must be used alone (any other options are ignored). + // PCLZIP_CB_PRE_EXTRACT : + // PCLZIP_CB_POST_EXTRACT : + // Return Values : + // 0 on failure, + // The list of the extracted files, with a status of the action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + //function extractByIndex($p_index, options...) + function extractByIndex($p_index) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : + // delete([$p_option, $p_option_value, ...]) + // Description : + // This method removes files from the archive. + // If no parameters are given, then all the archive is emptied. + // Parameters : + // None or optional arguments. + // Options : + // PCLZIP_OPT_BY_INDEX : + // PCLZIP_OPT_BY_NAME : + // PCLZIP_OPT_BY_EREG : + // PCLZIP_OPT_BY_PREG : + // Return Values : + // 0 on failure, + // The list of the files which are still present in the archive. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function delete() + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : deleteByIndex() + // Description : + // ***** Deprecated ***** + // delete(PCLZIP_OPT_BY_INDEX, $p_index) should be preferred. + // -------------------------------------------------------------------------------- + function deleteByIndex($p_index) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : properties() + // Description : + // This method gives the properties of the archive. + // The properties are : + // nb : Number of files in the archive + // comment : Comment associated with the archive file + // status : not_exist, ok + // Parameters : + // None + // Return Values : + // 0 on failure, + // An array with the archive properties. + // -------------------------------------------------------------------------------- + function properties() + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : duplicate() + // Description : + // This method creates an archive by copying the content of an other one. If + // the archive already exist, it is replaced by the new one without any warning. + // Parameters : + // $p_archive : The filename of a valid archive, or + // a valid PclZip object. + // Return Values : + // 1 on success. + // 0 or a negative value on error (error code). + // -------------------------------------------------------------------------------- + function duplicate($p_archive) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : merge() + // Description : + // This method merge the $p_archive_to_add archive at the end of the current + // one ($this). + // If the archive ($this) does not exist, the merge becomes a duplicate. + // If the $p_archive_to_add archive does not exist, the merge is a success. + // Parameters : + // $p_archive_to_add : It can be directly the filename of a valid zip archive, + // or a PclZip object archive. + // Return Values : + // 1 on success, + // 0 or negative values on error (see below). + // -------------------------------------------------------------------------------- + function merge($p_archive_to_add) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : errorCode() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorCode() + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : errorName() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorName($p_with_code = \false) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : errorInfo() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorInfo($p_full = \false) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS ***** + // ***** ***** + // ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY ***** + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privCheckFormat() + // Description : + // This method check that the archive exists and is a valid zip archive. + // Several level of check exists. (futur) + // Parameters : + // $p_level : Level of check. Default 0. + // 0 : Check the first bytes (magic codes) (default value)) + // 1 : 0 + Check the central directory (futur) + // 2 : 1 + Check each file header (futur) + // Return Values : + // true on success, + // false on error, the error code is set. + // -------------------------------------------------------------------------------- + function privCheckFormat($p_level = 0) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privParseOptions() + // Description : + // This internal methods reads the variable list of arguments ($p_options_list, + // $p_size) and generate an array with the options and values ($v_result_list). + // $v_requested_options contains the options that can be present and those that + // must be present. + // $v_requested_options is an array, with the option value as key, and 'optional', + // or 'mandatory' as value. + // Parameters : + // See above. + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options = \false) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privOptionDefaultThreshold() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privOptionDefaultThreshold(&$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privFileDescrParseAtt() + // Description : + // Parameters : + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options = \false) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privFileDescrExpand() + // Description : + // This method look for each item of the list to see if its a file, a folder + // or a string to be added as file. For any other type of files (link, other) + // just ignore the item. + // Then prepare the information that will be stored for that file. + // When its a folder, expand the folder with all the files that are in that + // folder (recursively). + // Parameters : + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privFileDescrExpand(&$p_filedescr_list, &$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privCreate() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privCreate($p_filedescr_list, &$p_result_list, &$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privAdd() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAdd($p_filedescr_list, &$p_result_list, &$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privOpenFd() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privOpenFd($p_mode) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privCloseFd() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privCloseFd() + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privAddList() + // Description : + // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is + // different from the real path of the file. This is useful if you want to have PclTar + // running in any directory, and memorize relative path from an other directory. + // Parameters : + // $p_list : An array containing the file or directory names to add in the tar + // $p_result_list : list of added files with their properties (specially the status field) + // $p_add_dir : Path to add in the filename path archived + // $p_remove_dir : Path to remove in the filename path archived + // Return Values : + // -------------------------------------------------------------------------------- + // function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options) + function privAddList($p_filedescr_list, &$p_result_list, &$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privAddFileList() + // Description : + // Parameters : + // $p_filedescr_list : An array containing the file description + // or directory names to add in the zip + // $p_result_list : list of added files with their properties (specially the status field) + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privAddFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFile($p_filedescr, &$p_header, &$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privAddFileUsingTempFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privCalculateStoredFilename() + // Description : + // Based on file descriptor properties and global options, this method + // calculate the filename that will be stored in the archive. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privCalculateStoredFilename(&$p_filedescr, &$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privWriteFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteFileHeader(&$p_header) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privWriteCentralFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteCentralFileHeader(&$p_header) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privWriteCentralHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privList() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privList(&$p_list) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privConvertHeader2FileInfo() + // Description : + // This function takes the file information from the central directory + // entries and extract the interesting parameters that will be given back. + // The resulting file infos are set in the array $p_info + // $p_info['filename'] : Filename with full path. Given by user (add), + // extracted in the filesystem (extract). + // $p_info['stored_filename'] : Stored filename in the archive. + // $p_info['size'] = Size of the file. + // $p_info['compressed_size'] = Compressed size of the file. + // $p_info['mtime'] = Last modification date of the file. + // $p_info['comment'] = Comment associated with the file. + // $p_info['folder'] = true/false : indicates if the entry is a folder or not. + // $p_info['status'] = status of the action on the file. + // $p_info['crc'] = CRC of the file content. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privConvertHeader2FileInfo($p_header, &$p_info) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privExtractByRule() + // Description : + // Extract a file or directory depending of rules (by index, by name, ...) + // Parameters : + // $p_file_list : An array where will be placed the properties of each + // extracted file + // $p_path : Path to add while writing the extracted files + // $p_remove_path : Path to remove (from the file memorized path) while writing the + // extracted files. If the path does not match the file path, + // the file is extracted with its memorized path. + // $p_remove_path does not apply to 'list' mode. + // $p_path and $p_remove_path are commulative. + // Return Values : + // 1 on success,0 or less on error (see error code list) + // -------------------------------------------------------------------------------- + function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privExtractFile() + // Description : + // Parameters : + // Return Values : + // + // 1 : ... ? + // PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback + // -------------------------------------------------------------------------------- + function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privExtractFileUsingTempFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileUsingTempFile(&$p_entry, &$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privExtractFileInOutput() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileInOutput(&$p_entry, &$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privExtractFileAsString() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileAsString(&$p_entry, &$p_string, &$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privReadFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadFileHeader(&$p_header) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privReadCentralFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadCentralFileHeader(&$p_header) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privCheckFileHeaders() + // Description : + // Parameters : + // Return Values : + // 1 on success, + // 0 on error; + // -------------------------------------------------------------------------------- + function privCheckFileHeaders(&$p_local_header, &$p_central_header) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privReadEndCentralDir() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadEndCentralDir(&$p_central_dir) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privDeleteByRule() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDeleteByRule(&$p_result_list, &$p_options) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privDirCheck() + // Description : + // Check if a directory exists, if not it creates it and all the parents directory + // which may be useful. + // Parameters : + // $p_dir : Directory path to check. + // Return Values : + // 1 : OK + // -1 : Unable to create directory + // -------------------------------------------------------------------------------- + function privDirCheck($p_dir, $p_is_dir = \false) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privMerge() + // Description : + // If $p_archive_to_add does not exist, the function exit with a success result. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privMerge(&$p_archive_to_add) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privDuplicate() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDuplicate($p_archive_filename) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privErrorLog() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privErrorLog($p_error_code = 0, $p_error_string = '') + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privErrorReset() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privErrorReset() + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privDisableMagicQuotes() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDisableMagicQuotes() + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : privSwapBackMagicQuotes() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privSwapBackMagicQuotes() + { + } + // -------------------------------------------------------------------------------- + } + /** + * Upgrader API: Plugin_Installer_Skin class + * + * @package WordPress + * @subpackage Upgrader + * @since 4.6.0 + */ + /** + * Plugin Installer Skin for WordPress Plugin Installer. + * + * @since 2.8.0 + * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php. + * + * @see WP_Upgrader_Skin + */ + class Plugin_Installer_Skin extends \WP_Upgrader_Skin + { + public $api; + public $type; + public $url; + public $overwrite; + /** + * @param array $args + */ + public function __construct($args = array()) + { + } + /** + * Action to perform before installing a plugin. + * + * @since 2.8.0 + */ + public function before() + { + } + /** + * Hides the `process_failed` error when updating a plugin by uploading a zip file. + * + * @since 5.5.0 + * + * @param WP_Error $wp_error WP_Error object. + * @return bool + */ + public function hide_process_failed($wp_error) + { + } + /** + * Action to perform following a plugin install. + * + * @since 2.8.0 + */ + public function after() + { + } + } + /** + * Upgrader API: Plugin_Upgrader_Skin class + * + * @package WordPress + * @subpackage Upgrader + * @since 4.6.0 + */ + /** + * Plugin Upgrader Skin for WordPress Plugin Upgrades. + * + * @since 2.8.0 + * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php. + * + * @see WP_Upgrader_Skin + */ + class Plugin_Upgrader_Skin extends \WP_Upgrader_Skin + { + /** + * Holds the plugin slug in the Plugin Directory. + * + * @since 2.8.0 + * + * @var string + */ + public $plugin = ''; + /** + * Whether the plugin is active. + * + * @since 2.8.0 + * + * @var bool + */ + public $plugin_active = \false; + /** + * Whether the plugin is active for the entire network. + * + * @since 2.8.0 + * + * @var bool + */ + public $plugin_network_active = \false; + /** + * Constructor. + * + * Sets up the plugin upgrader skin. + * + * @since 2.8.0 + * + * @param array $args Optional. The plugin upgrader skin arguments to + * override default options. Default empty array. + */ + public function __construct($args = array()) + { + } + /** + * Action to perform following a single plugin update. + * + * @since 2.8.0 + */ + public function after() + { + } + } + /** + * Upgrade API: Plugin_Upgrader class + * + * @package WordPress + * @subpackage Upgrader + * @since 4.6.0 + */ + /** + * Core class used for upgrading/installing plugins. + * + * It is designed to upgrade/install plugins from a local zip, remote zip URL, + * or uploaded zip file. + * + * @since 2.8.0 + * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader.php. + * + * @see WP_Upgrader + */ + class Plugin_Upgrader extends \WP_Upgrader + { + /** + * Plugin upgrade result. + * + * @since 2.8.0 + * @var array|WP_Error $result + * + * @see WP_Upgrader::$result + */ + public $result; + /** + * Whether a bulk upgrade/installation is being performed. + * + * @since 2.9.0 + * @var bool $bulk + */ + public $bulk = \false; + /** + * New plugin info. + * + * @since 5.5.0 + * @var array $new_plugin_data + * + * @see check_package() + */ + public $new_plugin_data = array(); + /** + * Initialize the upgrade strings. + * + * @since 2.8.0 + */ + public function upgrade_strings() + { + } + /** + * Initialize the installation strings. + * + * @since 2.8.0 + */ + public function install_strings() + { + } + /** + * Install a plugin package. + * + * @since 2.8.0 + * @since 3.7.0 The `$args` parameter was added, making clearing the plugin update cache optional. + * + * @param string $package The full local path or URI of the package. + * @param array $args { + * Optional. Other arguments for installing a plugin package. Default empty array. + * + * @type bool $clear_update_cache Whether to clear the plugin updates cache if successful. + * Default true. + * } + * @return bool|WP_Error True if the installation was successful, false or a WP_Error otherwise. + * @phpstan-param array{ + * clear_update_cache?: bool, + * } $args + */ + public function install($package, $args = array()) + { + } + /** + * Upgrade a plugin. + * + * @since 2.8.0 + * @since 3.7.0 The `$args` parameter was added, making clearing the plugin update cache optional. + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @param array $args { + * Optional. Other arguments for upgrading a plugin package. Default empty array. + * + * @type bool $clear_update_cache Whether to clear the plugin updates cache if successful. + * Default true. + * } + * @return bool|WP_Error True if the upgrade was successful, false or a WP_Error object otherwise. + * @phpstan-param array{ + * clear_update_cache?: bool, + * } $args + */ + public function upgrade($plugin, $args = array()) + { + } + /** + * Bulk upgrade several plugins at once. + * + * @since 2.8.0 + * @since 3.7.0 The `$args` parameter was added, making clearing the plugin update cache optional. + * + * @param string[] $plugins Array of paths to plugin files relative to the plugins directory. + * @param array $args { + * Optional. Other arguments for upgrading several plugins at once. + * + * @type bool $clear_update_cache Whether to clear the plugin updates cache if successful. Default true. + * } + * @return array|false An array of results indexed by plugin file, or false if unable to connect to the filesystem. + * @phpstan-param array{ + * clear_update_cache?: bool, + * } $args + */ + public function bulk_upgrade($plugins, $args = array()) + { + } + /** + * Checks that the source package contains a valid plugin. + * + * Hooked to the {@see 'upgrader_source_selection'} filter by Plugin_Upgrader::install(). + * + * @since 3.3.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * @global string $wp_version The WordPress version string. + * + * @param string $source The path to the downloaded package source. + * @return string|WP_Error The source as passed, or a WP_Error object on failure. + */ + public function check_package($source) + { + } + /** + * Retrieve the path to the file that contains the plugin info. + * + * This isn't used internally in the class, but is called by the skins. + * + * @since 2.8.0 + * + * @return string|false The full path to the main plugin file, or false. + */ + public function plugin_info() + { + } + /** + * Deactivates a plugin before it is upgraded. + * + * Hooked to the {@see 'upgrader_pre_install'} filter by Plugin_Upgrader::upgrade(). + * + * @since 2.8.0 + * @since 4.1.0 Added a return value. + * + * @param bool|WP_Error $response The installation response before the installation has started. + * @param array $plugin Plugin package arguments. + * @return bool|WP_Error The original `$response` parameter or WP_Error. + */ + public function deactivate_plugin_before_upgrade($response, $plugin) + { + } + /** + * Turns on maintenance mode before attempting to background update an active plugin. + * + * Hooked to the {@see 'upgrader_pre_install'} filter by Plugin_Upgrader::upgrade(). + * + * @since 5.4.0 + * + * @param bool|WP_Error $response The installation response before the installation has started. + * @param array $plugin Plugin package arguments. + * @return bool|WP_Error The original `$response` parameter or WP_Error. + */ + public function active_before($response, $plugin) + { + } + /** + * Turns off maintenance mode after upgrading an active plugin. + * + * Hooked to the {@see 'upgrader_post_install'} filter by Plugin_Upgrader::upgrade(). + * + * @since 5.4.0 + * + * @param bool|WP_Error $response The installation response after the installation has finished. + * @param array $plugin Plugin package arguments. + * @return bool|WP_Error The original `$response` parameter or WP_Error. + */ + public function active_after($response, $plugin) + { + } + /** + * Deletes the old plugin during an upgrade. + * + * Hooked to the {@see 'upgrader_clear_destination'} filter by + * Plugin_Upgrader::upgrade() and Plugin_Upgrader::bulk_upgrade(). + * + * @since 2.8.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param bool|WP_Error $removed Whether the destination was cleared. + * True on success, WP_Error on failure. + * @param string $local_destination The local package destination. + * @param string $remote_destination The remote package destination. + * @param array $plugin Extra arguments passed to hooked filters. + * @return bool|WP_Error + */ + public function delete_old_plugin($removed, $local_destination, $remote_destination, $plugin) + { + } + } + /** + * Upgrader API: Theme_Installer_Skin class + * + * @package WordPress + * @subpackage Upgrader + * @since 4.6.0 + */ + /** + * Theme Installer Skin for the WordPress Theme Installer. + * + * @since 2.8.0 + * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php. + * + * @see WP_Upgrader_Skin + */ + class Theme_Installer_Skin extends \WP_Upgrader_Skin + { + public $api; + public $type; + public $url; + public $overwrite; + /** + * @param array $args + */ + public function __construct($args = array()) + { + } + /** + * Action to perform before installing a theme. + * + * @since 2.8.0 + */ + public function before() + { + } + /** + * Hides the `process_failed` error when updating a theme by uploading a zip file. + * + * @since 5.5.0 + * + * @param WP_Error $wp_error WP_Error object. + * @return bool + */ + public function hide_process_failed($wp_error) + { + } + /** + * Action to perform following a single theme install. + * + * @since 2.8.0 + */ + public function after() + { + } + } + /** + * Upgrader API: Theme_Upgrader_Skin class + * + * @package WordPress + * @subpackage Upgrader + * @since 4.6.0 + */ + /** + * Theme Upgrader Skin for WordPress Theme Upgrades. + * + * @since 2.8.0 + * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php. + * + * @see WP_Upgrader_Skin + */ + class Theme_Upgrader_Skin extends \WP_Upgrader_Skin + { + /** + * Holds the theme slug in the Theme Directory. + * + * @since 2.8.0 + * + * @var string + */ + public $theme = ''; + /** + * Constructor. + * + * Sets up the theme upgrader skin. + * + * @since 2.8.0 + * + * @param array $args Optional. The theme upgrader skin arguments to + * override default options. Default empty array. + */ + public function __construct($args = array()) + { + } + /** + * Action to perform following a single theme update. + * + * @since 2.8.0 + */ + public function after() + { + } + } + /** + * Upgrade API: Theme_Upgrader class + * + * @package WordPress + * @subpackage Upgrader + * @since 4.6.0 + */ + /** + * Core class used for upgrading/installing themes. + * + * It is designed to upgrade/install themes from a local zip, remote zip URL, + * or uploaded zip file. + * + * @since 2.8.0 + * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader.php. + * + * @see WP_Upgrader + */ + class Theme_Upgrader extends \WP_Upgrader + { + /** + * Result of the theme upgrade offer. + * + * @since 2.8.0 + * @var array|WP_Error $result + * @see WP_Upgrader::$result + */ + public $result; + /** + * Whether multiple themes are being upgraded/installed in bulk. + * + * @since 2.9.0 + * @var bool $bulk + */ + public $bulk = \false; + /** + * New theme info. + * + * @since 5.5.0 + * @var array $new_theme_data + * + * @see check_package() + */ + public $new_theme_data = array(); + /** + * Initialize the upgrade strings. + * + * @since 2.8.0 + */ + public function upgrade_strings() + { + } + /** + * Initialize the installation strings. + * + * @since 2.8.0 + */ + public function install_strings() + { + } + /** + * Check if a child theme is being installed and we need to install its parent. + * + * Hooked to the {@see 'upgrader_post_install'} filter by Theme_Upgrader::install(). + * + * @since 3.4.0 + * + * @param bool $install_result + * @param array $hook_extra + * @param array $child_result + * @return bool + */ + public function check_parent_theme_filter($install_result, $hook_extra, $child_result) + { + } + /** + * Don't display the activate and preview actions to the user. + * + * Hooked to the {@see 'install_theme_complete_actions'} filter by + * Theme_Upgrader::check_parent_theme_filter() when installing + * a child theme and installing the parent theme fails. + * + * @since 3.4.0 + * + * @param array $actions Preview actions. + * @return array + */ + public function hide_activate_preview_actions($actions) + { + } + /** + * Install a theme package. + * + * @since 2.8.0 + * @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional. + * + * @param string $package The full local path or URI of the package. + * @param array $args { + * Optional. Other arguments for installing a theme package. Default empty array. + * + * @type bool $clear_update_cache Whether to clear the updates cache if successful. + * Default true. + * } + * + * @return bool|WP_Error True if the installation was successful, false or a WP_Error object otherwise. + * @phpstan-param array{ + * clear_update_cache?: bool, + * } $args + */ + public function install($package, $args = array()) + { + } + /** + * Upgrade a theme. + * + * @since 2.8.0 + * @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional. + * + * @param string $theme The theme slug. + * @param array $args { + * Optional. Other arguments for upgrading a theme. Default empty array. + * + * @type bool $clear_update_cache Whether to clear the update cache if successful. + * Default true. + * } + * @return bool|WP_Error True if the upgrade was successful, false or a WP_Error object otherwise. + * @phpstan-param array{ + * clear_update_cache?: bool, + * } $args + */ + public function upgrade($theme, $args = array()) + { + } + /** + * Upgrade several themes at once. + * + * @since 3.0.0 + * @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional. + * + * @param string[] $themes Array of the theme slugs. + * @param array $args { + * Optional. Other arguments for upgrading several themes at once. Default empty array. + * + * @type bool $clear_update_cache Whether to clear the update cache if successful. + * Default true. + * } + * @return array[]|false An array of results, or false if unable to connect to the filesystem. + * @phpstan-param array{ + * clear_update_cache?: bool, + * } $args + */ + public function bulk_upgrade($themes, $args = array()) + { + } + /** + * Checks that the package source contains a valid theme. + * + * Hooked to the {@see 'upgrader_source_selection'} filter by Theme_Upgrader::install(). + * + * @since 3.3.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * @global string $wp_version The WordPress version string. + * + * @param string $source The path to the downloaded package source. + * @return string|WP_Error The source as passed, or a WP_Error object on failure. + */ + public function check_package($source) + { + } + /** + * Turn on maintenance mode before attempting to upgrade the active theme. + * + * Hooked to the {@see 'upgrader_pre_install'} filter by Theme_Upgrader::upgrade() and + * Theme_Upgrader::bulk_upgrade(). + * + * @since 2.8.0 + * + * @param bool|WP_Error $response The installation response before the installation has started. + * @param array $theme Theme arguments. + * @return bool|WP_Error The original `$response` parameter or WP_Error. + */ + public function current_before($response, $theme) + { + } + /** + * Turn off maintenance mode after upgrading the active theme. + * + * Hooked to the {@see 'upgrader_post_install'} filter by Theme_Upgrader::upgrade() + * and Theme_Upgrader::bulk_upgrade(). + * + * @since 2.8.0 + * + * @param bool|WP_Error $response The installation response after the installation has finished. + * @param array $theme Theme arguments. + * @return bool|WP_Error The original `$response` parameter or WP_Error. + */ + public function current_after($response, $theme) + { + } + /** + * Delete the old theme during an upgrade. + * + * Hooked to the {@see 'upgrader_clear_destination'} filter by Theme_Upgrader::upgrade() + * and Theme_Upgrader::bulk_upgrade(). + * + * @since 2.8.0 + * + * @global WP_Filesystem_Base $wp_filesystem Subclass + * + * @param bool $removed + * @param string $local_destination + * @param string $remote_destination + * @param array $theme + * @return bool + */ + public function delete_old_theme($removed, $local_destination, $remote_destination, $theme) + { + } + /** + * Get the WP_Theme object for a theme. + * + * @since 2.8.0 + * @since 3.0.0 The `$theme` argument was added. + * + * @param string $theme The directory name of the theme. This is optional, and if not supplied, + * the directory name from the last result will be used. + * @return WP_Theme|false The theme's info object, or false `$theme` is not supplied + * and the last result isn't set. + */ + public function theme_info($theme = \null) + { + } + } + /** + * A class for displaying various tree-like structures. + * + * Extend the Walker class to use it, see examples below. Child classes + * do not need to implement all of the abstract methods in the class. The child + * only needs to implement the methods that are needed. + * + * @since 2.1.0 + * + * @package WordPress + * @abstract + */ + #[\AllowDynamicProperties] + class Walker + { + /** + * What the class handles. + * + * @since 2.1.0 + * @var string + */ + public $tree_type; + /** + * DB fields to use. + * + * @since 2.1.0 + * @var string[] + */ + public $db_fields; + /** + * Max number of pages walked by the paged walker. + * + * @since 2.7.0 + * @var int + */ + public $max_pages = 1; + /** + * Whether the current element has children or not. + * + * To be used in start_el(). + * + * @since 4.0.0 + * @var bool + */ + public $has_children; + /** + * Starts the list before the elements are added. + * + * The $args parameter holds additional values that may be used with the child + * class methods. This method is called at the start of the output list. + * + * @since 2.1.0 + * @abstract + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Depth of the item. + * @param array $args An array of additional arguments. + */ + public function start_lvl(&$output, $depth = 0, $args = array()) + { + } + /** + * Ends the list of after the elements are added. + * + * The $args parameter holds additional values that may be used with the child + * class methods. This method finishes the list at the end of output of the elements. + * + * @since 2.1.0 + * @abstract + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Depth of the item. + * @param array $args An array of additional arguments. + */ + public function end_lvl(&$output, $depth = 0, $args = array()) + { + } + /** + * Starts the element output. + * + * The $args parameter holds additional values that may be used with the child + * class methods. Also includes the element output. + * + * @since 2.1.0 + * @since 5.9.0 Renamed `$object` (a PHP reserved keyword) to `$data_object` for PHP 8 named parameter support. + * @abstract + * + * @param string $output Used to append additional content (passed by reference). + * @param object $data_object The data object. + * @param int $depth Depth of the item. + * @param array $args An array of additional arguments. + * @param int $current_object_id Optional. ID of the current item. Default 0. + */ + public function start_el(&$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0) + { + } + /** + * Ends the element output, if needed. + * + * The $args parameter holds additional values that may be used with the child class methods. + * + * @since 2.1.0 + * @since 5.9.0 Renamed `$object` (a PHP reserved keyword) to `$data_object` for PHP 8 named parameter support. + * @abstract + * + * @param string $output Used to append additional content (passed by reference). + * @param object $data_object The data object. + * @param int $depth Depth of the item. + * @param array $args An array of additional arguments. + */ + public function end_el(&$output, $data_object, $depth = 0, $args = array()) + { + } + /** + * Traverses elements to create list from elements. + * + * Display one element if the element doesn't have any children otherwise, + * display the element and its children. Will only traverse up to the max + * depth and no ignore elements under that depth. It is possible to set the + * max depth to include all depths, see walk() method. + * + * This method should not be called directly, use the walk() method instead. + * + * @since 2.5.0 + * + * @param object $element Data object. + * @param array $children_elements List of elements to continue traversing (passed by reference). + * @param int $max_depth Max depth to traverse. + * @param int $depth Depth of current element. + * @param array $args An array of arguments. + * @param string $output Used to append additional content (passed by reference). + */ + public function display_element($element, &$children_elements, $max_depth, $depth, $args, &$output) + { + } + /** + * Displays array of elements hierarchically. + * + * Does not assume any existing order of elements. + * + * $max_depth = -1 means flatly display every element. + * $max_depth = 0 means display all levels. + * $max_depth > 0 specifies the number of display levels. + * + * @since 2.1.0 + * @since 5.3.0 Formalized the existing `...$args` parameter by adding it + * to the function signature. + * + * @param array $elements An array of elements. + * @param int $max_depth The maximum hierarchical depth. + * @param mixed ...$args Optional additional arguments. + * @return string The hierarchical item output. + */ + public function walk($elements, $max_depth, ...$args) + { + } + /** + * Produces a page of nested elements. + * + * Given an array of hierarchical elements, the maximum depth, a specific page number, + * and number of elements per page, this function first determines all top level root elements + * belonging to that page, then lists them and all of their children in hierarchical order. + * + * $max_depth = 0 means display all levels. + * $max_depth > 0 specifies the number of display levels. + * + * @since 2.7.0 + * @since 5.3.0 Formalized the existing `...$args` parameter by adding it + * to the function signature. + * + * @param array $elements An array of elements. + * @param int $max_depth The maximum hierarchical depth. + * @param int $page_num The specific page number, beginning with 1. + * @param int $per_page Number of elements per page. + * @param mixed ...$args Optional additional arguments. + * @return string XHTML of the specified page of elements. + */ + public function paged_walk($elements, $max_depth, $page_num, $per_page, ...$args) + { + } + /** + * Calculates the total number of root elements. + * + * @since 2.7.0 + * + * @param array $elements Elements to list. + * @return int Number of root elements. + */ + public function get_number_of_root_elements($elements) + { + } + /** + * Unsets all the children for a given top level element. + * + * @since 2.7.0 + * + * @param object $element The top level element. + * @param array $children_elements The children elements. + */ + public function unset_children($element, &$children_elements) + { + } + } + /** + * Taxonomy API: Walker_Category_Checklist class + * + * @package WordPress + * @subpackage Administration + * @since 4.4.0 + */ + /** + * Core walker class to output an unordered list of category checkbox input elements. + * + * @since 2.5.1 + * + * @see Walker + * @see wp_category_checklist() + * @see wp_terms_checklist() + */ + class Walker_Category_Checklist extends \Walker + { + public $tree_type = 'category'; + public $db_fields = array('parent' => 'parent', 'id' => 'term_id'); + // TODO: Decouple this. + /** + * Starts the list before the elements are added. + * + * @see Walker:start_lvl() + * + * @since 2.5.1 + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Depth of category. Used for tab indentation. + * @param array $args An array of arguments. @see wp_terms_checklist() + * @phpstan-param array{ + * descendants_and_self?: int, + * selected_cats?: int[], + * popular_cats?: int[], + * walker?: Walker, + * taxonomy?: string, + * checked_ontop?: bool, + * echo?: bool, + * } $args See wp_terms_checklist() + */ + public function start_lvl(&$output, $depth = 0, $args = array()) + { + } + /** + * Ends the list of after the elements are added. + * + * @see Walker::end_lvl() + * + * @since 2.5.1 + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Depth of category. Used for tab indentation. + * @param array $args An array of arguments. @see wp_terms_checklist() + * @phpstan-param array{ + * descendants_and_self?: int, + * selected_cats?: int[], + * popular_cats?: int[], + * walker?: Walker, + * taxonomy?: string, + * checked_ontop?: bool, + * echo?: bool, + * } $args See wp_terms_checklist() + */ + public function end_lvl(&$output, $depth = 0, $args = array()) + { + } + /** + * Start the element output. + * + * @see Walker::start_el() + * + * @since 2.5.1 + * @since 5.9.0 Renamed `$category` to `$data_object` and `$id` to `$current_object_id` + * to match parent class for PHP 8 named parameter support. + * + * @param string $output Used to append additional content (passed by reference). + * @param WP_Term $data_object The current term object. + * @param int $depth Depth of the term in reference to parents. Default 0. + * @param array $args An array of arguments. @see wp_terms_checklist() + * @param int $current_object_id Optional. ID of the current term. Default 0. + * @phpstan-param array{ + * descendants_and_self?: int, + * selected_cats?: int[], + * popular_cats?: int[], + * walker?: Walker, + * taxonomy?: string, + * checked_ontop?: bool, + * echo?: bool, + * } $args See wp_terms_checklist() + */ + public function start_el(&$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0) + { + } + /** + * Ends the element output, if needed. + * + * @see Walker::end_el() + * + * @since 2.5.1 + * @since 5.9.0 Renamed `$category` to `$data_object` to match parent class for PHP 8 named parameter support. + * + * @param string $output Used to append additional content (passed by reference). + * @param WP_Term $data_object The current term object. + * @param int $depth Depth of the term in reference to parents. Default 0. + * @param array $args An array of arguments. @see wp_terms_checklist() + * @phpstan-param array{ + * descendants_and_self?: int, + * selected_cats?: int[], + * popular_cats?: int[], + * walker?: Walker, + * taxonomy?: string, + * checked_ontop?: bool, + * echo?: bool, + * } $args See wp_terms_checklist() + */ + public function end_el(&$output, $data_object, $depth = 0, $args = array()) + { + } + } + /** + * Nav Menu API: Walker_Nav_Menu class + * + * @package WordPress + * @subpackage Nav_Menus + * @since 4.6.0 + */ + /** + * Core class used to implement an HTML list of nav menu items. + * + * @since 3.0.0 + * + * @see Walker + */ + class Walker_Nav_Menu extends \Walker + { + /** + * What the class handles. + * + * @since 3.0.0 + * @var string + * + * @see Walker::$tree_type + */ + public $tree_type = array('post_type', 'taxonomy', 'custom'); + /** + * Database fields to use. + * + * @since 3.0.0 + * @todo Decouple this. + * @var string[] + * + * @see Walker::$db_fields + */ + public $db_fields = array('parent' => 'menu_item_parent', 'id' => 'db_id'); + /** + * Starts the list before the elements are added. + * + * @since 3.0.0 + * + * @see Walker::start_lvl() + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Depth of menu item. Used for padding. + * @param stdClass $args An object of wp_nav_menu() arguments. + */ + public function start_lvl(&$output, $depth = 0, $args = \null) + { + } + /** + * Ends the list of after the elements are added. + * + * @since 3.0.0 + * + * @see Walker::end_lvl() + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Depth of menu item. Used for padding. + * @param stdClass $args An object of wp_nav_menu() arguments. + */ + public function end_lvl(&$output, $depth = 0, $args = \null) + { + } + /** + * Starts the element output. + * + * @since 3.0.0 + * @since 4.4.0 The {@see 'nav_menu_item_args'} filter was added. + * @since 5.9.0 Renamed `$item` to `$data_object` and `$id` to `$current_object_id` + * to match parent class for PHP 8 named parameter support. + * + * @see Walker::start_el() + * + * @param string $output Used to append additional content (passed by reference). + * @param WP_Post $data_object Menu item data object. + * @param int $depth Depth of menu item. Used for padding. + * @param stdClass $args An object of wp_nav_menu() arguments. + * @param int $current_object_id Optional. ID of the current menu item. Default 0. + */ + public function start_el(&$output, $data_object, $depth = 0, $args = \null, $current_object_id = 0) + { + } + /** + * Ends the element output, if needed. + * + * @since 3.0.0 + * @since 5.9.0 Renamed `$item` to `$data_object` to match parent class for PHP 8 named parameter support. + * + * @see Walker::end_el() + * + * @param string $output Used to append additional content (passed by reference). + * @param WP_Post $data_object Menu item data object. Not used. + * @param int $depth Depth of page. Not Used. + * @param stdClass $args An object of wp_nav_menu() arguments. + */ + public function end_el(&$output, $data_object, $depth = 0, $args = \null) + { + } + } + /** + * Navigation Menu API: Walker_Nav_Menu_Checklist class + * + * @package WordPress + * @subpackage Administration + * @since 4.4.0 + */ + /** + * Create HTML list of nav menu input items. + * + * @since 3.0.0 + * @uses Walker_Nav_Menu + */ + class Walker_Nav_Menu_Checklist extends \Walker_Nav_Menu + { + /** + * @param array|false $fields Database fields to use. + */ + public function __construct($fields = \false) + { + } + /** + * Starts the list before the elements are added. + * + * @see Walker_Nav_Menu::start_lvl() + * + * @since 3.0.0 + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Depth of page. Used for padding. + * @param stdClass $args Not used. + */ + public function start_lvl(&$output, $depth = 0, $args = \null) + { + } + /** + * Ends the list of after the elements are added. + * + * @see Walker_Nav_Menu::end_lvl() + * + * @since 3.0.0 + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Depth of page. Used for padding. + * @param stdClass $args Not used. + */ + public function end_lvl(&$output, $depth = 0, $args = \null) + { + } + /** + * Start the element output. + * + * @see Walker_Nav_Menu::start_el() + * + * @since 3.0.0 + * @since 5.9.0 Renamed `$item` to `$data_object` and `$id` to `$current_object_id` + * to match parent class for PHP 8 named parameter support. + * + * @global int $_nav_menu_placeholder + * @global int|string $nav_menu_selected_id + * + * @param string $output Used to append additional content (passed by reference). + * @param WP_Post $data_object Menu item data object. + * @param int $depth Depth of menu item. Used for padding. + * @param stdClass $args Not used. + * @param int $current_object_id Optional. ID of the current menu item. Default 0. + */ + public function start_el(&$output, $data_object, $depth = 0, $args = \null, $current_object_id = 0) + { + } + } + /** + * Navigation Menu API: Walker_Nav_Menu_Edit class + * + * @package WordPress + * @subpackage Administration + * @since 4.4.0 + */ + /** + * Create HTML list of nav menu input items. + * + * @since 3.0.0 + * + * @see Walker_Nav_Menu + */ + class Walker_Nav_Menu_Edit extends \Walker_Nav_Menu + { + /** + * Starts the list before the elements are added. + * + * @see Walker_Nav_Menu::start_lvl() + * + * @since 3.0.0 + * + * @param string $output Passed by reference. + * @param int $depth Depth of menu item. Used for padding. + * @param stdClass $args Not used. + */ + public function start_lvl(&$output, $depth = 0, $args = \null) + { + } + /** + * Ends the list of after the elements are added. + * + * @see Walker_Nav_Menu::end_lvl() + * + * @since 3.0.0 + * + * @param string $output Passed by reference. + * @param int $depth Depth of menu item. Used for padding. + * @param stdClass $args Not used. + */ + public function end_lvl(&$output, $depth = 0, $args = \null) + { + } + /** + * Start the element output. + * + * @see Walker_Nav_Menu::start_el() + * @since 3.0.0 + * @since 5.9.0 Renamed `$item` to `$data_object` and `$id` to `$current_object_id` + * to match parent class for PHP 8 named parameter support. + * + * @global int $_wp_nav_menu_max_depth + * + * @param string $output Used to append additional content (passed by reference). + * @param WP_Post $data_object Menu item data object. + * @param int $depth Depth of menu item. Used for padding. + * @param stdClass $args Not used. + * @param int $current_object_id Optional. ID of the current menu item. Default 0. + */ + public function start_el(&$output, $data_object, $depth = 0, $args = \null, $current_object_id = 0) + { + } + } + /** + * Upgrader API: WP_Ajax_Upgrader_Skin class + * + * @package WordPress + * @subpackage Upgrader + * @since 4.6.0 + */ + /** + * Upgrader Skin for Ajax WordPress upgrades. + * + * This skin is designed to be used for Ajax updates. + * + * @since 4.6.0 + * + * @see Automatic_Upgrader_Skin + */ + class WP_Ajax_Upgrader_Skin extends \Automatic_Upgrader_Skin + { + /** + * Plugin info. + * + * The Plugin_Upgrader::bulk_upgrade() method will fill this in + * with info retrieved from the get_plugin_data() function. + * + * @var array Plugin data. Values will be empty if not supplied by the plugin. + */ + public $plugin_info = array(); + /** + * Theme info. + * + * The Theme_Upgrader::bulk_upgrade() method will fill this in + * with info retrieved from the Theme_Upgrader::theme_info() method, + * which in turn calls the wp_get_theme() function. + * + * @var WP_Theme|false The theme's info object, or false. + */ + public $theme_info = \false; + /** + * Holds the WP_Error object. + * + * @since 4.6.0 + * + * @var null|WP_Error + */ + protected $errors = \null; + /** + * Constructor. + * + * Sets up the WordPress Ajax upgrader skin. + * + * @since 4.6.0 + * + * @see WP_Upgrader_Skin::__construct() + * + * @param array $args Optional. The WordPress Ajax upgrader skin arguments to + * override default options. See WP_Upgrader_Skin::__construct(). + * Default empty array. + */ + public function __construct($args = array()) + { + } + /** + * Retrieves the list of errors. + * + * @since 4.6.0 + * + * @return WP_Error Errors during an upgrade. + */ + public function get_errors() + { + } + /** + * Retrieves a string for error messages. + * + * @since 4.6.0 + * + * @return string Error messages during an upgrade. + */ + public function get_error_messages() + { + } + /** + * Stores an error message about the upgrade. + * + * @since 4.6.0 + * @since 5.3.0 Formalized the existing `...$args` parameter by adding it + * to the function signature. + * + * @param string|WP_Error $errors Errors. + * @param mixed ...$args Optional text replacements. + */ + public function error($errors, ...$args) + { + } + /** + * Stores a message about the upgrade. + * + * @since 4.6.0 + * @since 5.3.0 Formalized the existing `...$args` parameter by adding it + * to the function signature. + * @since 5.9.0 Renamed `$data` to `$feedback` for PHP 8 named parameter support. + * + * @param string|array|WP_Error $feedback Message data. + * @param mixed ...$args Optional text replacements. + */ + public function feedback($feedback, ...$args) + { + } + } + /** + * Administration API: WP_List_Table class + * + * @package WordPress + * @subpackage List_Table + * @since 3.1.0 + */ + /** + * Base class for displaying a list of items in an ajaxified HTML table. + * + * @since 3.1.0 + */ + #[\AllowDynamicProperties] + class WP_List_Table + { + /** + * The current list of items. + * + * @since 3.1.0 + * @var array + */ + public $items; + /** + * Various information about the current table. + * + * @since 3.1.0 + * @var array + */ + protected $_args; + /** + * Various information needed for displaying the pagination. + * + * @since 3.1.0 + * @var array + */ + protected $_pagination_args = array(); + /** + * The current screen. + * + * @since 3.1.0 + * @var WP_Screen + */ + protected $screen; + /** + * The view switcher modes. + * + * @since 4.1.0 + * @var array + */ + protected $modes = array(); + /** + * Stores the value returned by ->get_column_info(). + * + * @since 4.1.0 + * @var array + */ + protected $_column_headers; + /** + * {@internal Missing Summary} + * + * @var array + */ + protected $compat_fields = array('_args', '_pagination_args', 'screen', '_actions', '_pagination'); + /** + * {@internal Missing Summary} + * + * @var array + */ + protected $compat_methods = array('set_pagination_args', 'get_views', 'get_bulk_actions', 'bulk_actions', 'row_actions', 'months_dropdown', 'view_switcher', 'comments_bubble', 'get_items_per_page', 'pagination', 'get_sortable_columns', 'get_column_info', 'get_table_classes', 'display_tablenav', 'extra_tablenav', 'single_row_columns'); + /** + * Constructor. + * + * The child class should call this constructor from its own constructor to override + * the default $args. + * + * @since 3.1.0 + * + * @param array|string $args { + * Array or string of arguments. + * + * @type string $plural Plural value used for labels and the objects being listed. + * This affects things such as CSS class-names and nonces used + * in the list table, e.g. 'posts'. Default empty. + * @type string $singular Singular label for an object being listed, e.g. 'post'. + * Default empty + * @type bool $ajax Whether the list table supports Ajax. This includes loading + * and sorting data, for example. If true, the class will call + * the _js_vars() method in the footer to provide variables + * to any scripts handling Ajax events. Default false. + * @type string $screen String containing the hook name used to determine the current + * screen. If left null, the current screen will be automatically set. + * Default null. + * } + * @phpstan-param array{ + * plural?: string, + * singular?: string, + * ajax?: bool, + * screen?: string, + * } $args + */ + public function __construct($args = array()) + { + } + /** + * Make private properties readable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to get. + * @return mixed Property. + */ + public function __get($name) + { + } + /** + * Make private properties settable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to check if set. + * @param mixed $value Property value. + * @return mixed Newly-set property. + */ + public function __set($name, $value) + { + } + /** + * Make private properties checkable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to check if set. + * @return bool Whether the property is a back-compat property and it is set. + */ + public function __isset($name) + { + } + /** + * Make private properties un-settable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to unset. + */ + public function __unset($name) + { + } + /** + * Make private/protected methods readable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Method to call. + * @param array $arguments Arguments to pass when calling. + * @return mixed|bool Return value of the callback, false otherwise. + */ + public function __call($name, $arguments) + { + } + /** + * Checks the current user's permissions + * + * @since 3.1.0 + * @abstract + */ + public function ajax_user_can() + { + } + /** + * Prepares the list of items for displaying. + * + * @uses WP_List_Table::set_pagination_args() + * + * @since 3.1.0 + * @abstract + */ + public function prepare_items() + { + } + /** + * An internal method that sets all the necessary pagination arguments + * + * @since 3.1.0 + * + * @param array|string $args Array or string of arguments with information about the pagination. + */ + protected function set_pagination_args($args) + { + } + /** + * Access the pagination args. + * + * @since 3.1.0 + * + * @param string $key Pagination argument to retrieve. Common values include 'total_items', + * 'total_pages', 'per_page', or 'infinite_scroll'. + * @return int Number of items that correspond to the given pagination argument. + */ + public function get_pagination_arg($key) + { + } + /** + * Whether the table has items to display or not + * + * @since 3.1.0 + * + * @return bool + */ + public function has_items() + { + } + /** + * Message to be displayed when there are no items + * + * @since 3.1.0 + */ + public function no_items() + { + } + /** + * Displays the search box. + * + * @since 3.1.0 + * + * @param string $text The 'submit' button label. + * @param string $input_id ID attribute value for the search input field. + */ + public function search_box($text, $input_id) + { + } + /** + * Generates views links. + * + * @since 6.1.0 + * + * @param array $link_data { + * An array of link data. + * + * @type string $url The link URL. + * @type string $label The link label. + * @type bool $current Optional. Whether this is the currently selected view. + * } + * @return array An array of link markup. Keys match the `$link_data` input array. + * @phpstan-param array{ + * url?: string, + * label?: string, + * current?: bool, + * } $link_data + */ + protected function get_views_links($link_data = array()) + { + } + /** + * Gets the list of views available on this table. + * + * The format is an associative array: + * - `'id' => 'link'` + * + * @since 3.1.0 + * + * @return array + */ + protected function get_views() + { + } + /** + * Displays the list of views available on this table. + * + * @since 3.1.0 + */ + public function views() + { + } + /** + * Retrieves the list of bulk actions available for this table. + * + * The format is an associative array where each element represents either a top level option value and label, or + * an array representing an optgroup and its options. + * + * For a standard option, the array element key is the field value and the array element value is the field label. + * + * For an optgroup, the array element key is the label and the array element value is an associative array of + * options as above. + * + * Example: + * + * [ + * 'edit' => 'Edit', + * 'delete' => 'Delete', + * 'Change State' => [ + * 'feature' => 'Featured', + * 'sale' => 'On Sale', + * ] + * ] + * + * @since 3.1.0 + * @since 5.6.0 A bulk action can now contain an array of options in order to create an optgroup. + * + * @return array + */ + protected function get_bulk_actions() + { + } + /** + * Displays the bulk actions dropdown. + * + * @since 3.1.0 + * + * @param string $which The location of the bulk actions: 'top' or 'bottom'. + * This is designated as optional for backward compatibility. + * @phpstan-param "top"|"bottom" $which + * @phpstan-return void + */ + protected function bulk_actions($which = '') + { + } + /** + * Gets the current action selected from the bulk actions dropdown. + * + * @since 3.1.0 + * + * @return string|false The action name. False if no action was selected. + */ + public function current_action() + { + } + /** + * Generates the required HTML for a list of row action links. + * + * @since 3.1.0 + * + * @param string[] $actions An array of action links. + * @param bool $always_visible Whether the actions should be always visible. + * @return string The HTML for the row actions. + */ + protected function row_actions($actions, $always_visible = \false) + { + } + /** + * Displays a dropdown for filtering items in the list table by month. + * + * @since 3.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @param string $post_type The post type. + */ + protected function months_dropdown($post_type) + { + } + /** + * Displays a view switcher. + * + * @since 3.1.0 + * + * @param string $current_mode + */ + protected function view_switcher($current_mode) + { + } + /** + * Displays a comment count bubble. + * + * @since 3.1.0 + * + * @param int $post_id The post ID. + * @param int $pending_comments Number of pending comments. + */ + protected function comments_bubble($post_id, $pending_comments) + { + } + /** + * Gets the current page number. + * + * @since 3.1.0 + * + * @return int + */ + public function get_pagenum() + { + } + /** + * Gets the number of items to display on a single page. + * + * @since 3.1.0 + * + * @param string $option User option name. + * @param int $default_value Optional. The number of items to display. Default 20. + * @return int + */ + protected function get_items_per_page($option, $default_value = 20) + { + } + /** + * Displays the pagination. + * + * @since 3.1.0 + * + * @param string $which + * @phpstan-param "top"|"bottom" $which + * @phpstan-return void + */ + protected function pagination($which) + { + } + /** + * Gets a list of columns. + * + * The format is: + * - `'internal-name' => 'Title'` + * + * @since 3.1.0 + * @abstract + * + * @return array + */ + public function get_columns() + { + } + /** + * Gets a list of sortable columns. + * + * The format is: + * - `'internal-name' => 'orderby'` + * - `'internal-name' => array( 'orderby', 'asc' )` - The second element sets the initial sorting order. + * - `'internal-name' => array( 'orderby', true )` - The second element makes the initial order descending. + * + * @since 3.1.0 + * + * @return array + */ + protected function get_sortable_columns() + { + } + /** + * Gets the name of the default primary column. + * + * @since 4.3.0 + * + * @return string Name of the default primary column, in this case, an empty string. + */ + protected function get_default_primary_column_name() + { + } + /** + * Public wrapper for WP_List_Table::get_default_primary_column_name(). + * + * @since 4.4.0 + * + * @return string Name of the default primary column. + */ + public function get_primary_column() + { + } + /** + * Gets the name of the primary column. + * + * @since 4.3.0 + * + * @return string The name of the primary column. + */ + protected function get_primary_column_name() + { + } + /** + * Gets a list of all, hidden, and sortable columns, with filter applied. + * + * @since 3.1.0 + * + * @return array + */ + protected function get_column_info() + { + } + /** + * Returns the number of visible columns. + * + * @since 3.1.0 + * + * @return int + */ + public function get_column_count() + { + } + /** + * Prints column headers, accounting for hidden and sortable columns. + * + * @since 3.1.0 + * + * @param bool $with_id Whether to set the ID attribute or not + */ + public function print_column_headers($with_id = \true) + { + } + /** + * Displays the table. + * + * @since 3.1.0 + */ + public function display() + { + } + /** + * Gets a list of CSS classes for the WP_List_Table table tag. + * + * @since 3.1.0 + * + * @return string[] Array of CSS classes for the table tag. + */ + protected function get_table_classes() + { + } + /** + * Generates the table navigation above or below the table + * + * @since 3.1.0 + * @param string $which + * @phpstan-param "top"|"bottom" $which + * @phpstan-return void + */ + protected function display_tablenav($which) + { + } + /** + * Extra controls to be displayed between bulk actions and pagination. + * + * @since 3.1.0 + * + * @param string $which + */ + protected function extra_tablenav($which) + { + } + /** + * Generates the tbody element for the list table. + * + * @since 3.1.0 + */ + public function display_rows_or_placeholder() + { + } + /** + * Generates the table rows. + * + * @since 3.1.0 + */ + public function display_rows() + { + } + /** + * Generates content for a single row of the table. + * + * @since 3.1.0 + * + * @param object|array $item The current item + */ + public function single_row($item) + { + } + /** + * @param object|array $item + * @param string $column_name + */ + protected function column_default($item, $column_name) + { + } + /** + * @param object|array $item + */ + protected function column_cb($item) + { + } + /** + * Generates the columns for a single row of the table. + * + * @since 3.1.0 + * + * @param object|array $item The current item. + */ + protected function single_row_columns($item) + { + } + /** + * Generates and display row actions links for the list table. + * + * @since 4.3.0 + * + * @param object|array $item The item being acted upon. + * @param string $column_name Current column name. + * @param string $primary Primary column name. + * @return string The row actions HTML, or an empty string + * if the current column is not the primary column. + */ + protected function handle_row_actions($item, $column_name, $primary) + { + } + /** + * Handles an incoming ajax request (called from admin-ajax.php) + * + * @since 3.1.0 + */ + public function ajax_response() + { + } + /** + * Sends required variables to JavaScript land. + * + * @since 3.1.0 + */ + public function _js_vars() + { + } + } + /** + * List Table API: WP_Application_Passwords_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 5.6.0 + */ + /** + * Class for displaying the list of application password items. + * + * @since 5.6.0 + * + * @see WP_List_Table + */ + class WP_Application_Passwords_List_Table extends \WP_List_Table + { + /** + * Gets the list of columns. + * + * @since 5.6.0 + * + * @return array + */ + public function get_columns() + { + } + /** + * Prepares the list of items for displaying. + * + * @since 5.6.0 + * + * @global int $user_id User ID. + */ + public function prepare_items() + { + } + /** + * Handles the name column output. + * + * @since 5.6.0 + * + * @param array $item The current application password item. + */ + public function column_name($item) + { + } + /** + * Handles the created column output. + * + * @since 5.6.0 + * + * @param array $item The current application password item. + */ + public function column_created($item) + { + } + /** + * Handles the last used column output. + * + * @since 5.6.0 + * + * @param array $item The current application password item. + */ + public function column_last_used($item) + { + } + /** + * Handles the last ip column output. + * + * @since 5.6.0 + * + * @param array $item The current application password item. + */ + public function column_last_ip($item) + { + } + /** + * Handles the revoke column output. + * + * @since 5.6.0 + * + * @param array $item The current application password item. + */ + public function column_revoke($item) + { + } + /** + * Generates content for a single row of the table + * + * @since 5.6.0 + * + * @param array $item The current item. + * @param string $column_name The current column name. + */ + protected function column_default($item, $column_name) + { + } + /** + * Generates custom table navigation to prevent conflicting nonces. + * + * @since 5.6.0 + * + * @param string $which The location of the bulk actions: 'top' or 'bottom'. + */ + protected function display_tablenav($which) + { + } + /** + * Generates content for a single row of the table. + * + * @since 5.6.0 + * + * @param array $item The current item. + */ + public function single_row($item) + { + } + /** + * Gets the name of the default primary column. + * + * @since 5.6.0 + * + * @return string Name of the default primary column, in this case, 'name'. + */ + protected function get_default_primary_column_name() + { + } + /** + * Prints the JavaScript template for the new row item. + * + * @since 5.6.0 + */ + public function print_js_template_row() + { + } + } + /** + * Upgrade API: WP_Automatic_Updater class + * + * @package WordPress + * @subpackage Upgrader + * @since 4.6.0 + */ + /** + * Core class used for handling automatic background updates. + * + * @since 3.7.0 + * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader.php. + */ + #[\AllowDynamicProperties] + class WP_Automatic_Updater + { + /** + * Tracks update results during processing. + * + * @var array + */ + protected $update_results = array(); + /** + * Determines whether the entire automatic updater is disabled. + * + * @since 3.7.0 + */ + public function is_disabled() + { + } + /** + * Checks for version control checkouts. + * + * Checks for Subversion, Git, Mercurial, and Bazaar. It recursively looks up the + * filesystem to the top of the drive, erring on the side of detecting a VCS + * checkout somewhere. + * + * ABSPATH is always checked in addition to whatever `$context` is (which may be the + * wp-content directory, for example). The underlying assumption is that if you are + * using version control *anywhere*, then you should be making decisions for + * how things get updated. + * + * @since 3.7.0 + * + * @param string $context The filesystem path to check, in addition to ABSPATH. + * @return bool True if a VCS checkout was discovered at `$context` or ABSPATH, + * or anywhere higher. False otherwise. + */ + public function is_vcs_checkout($context) + { + } + /** + * Tests to see if we can and should update a specific item. + * + * @since 3.7.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $type The type of update being checked: 'core', 'theme', + * 'plugin', 'translation'. + * @param object $item The update offer. + * @param string $context The filesystem context (a path) against which filesystem + * access and status should be checked. + * @return bool True if the item should be updated, false otherwise. + */ + public function should_update($type, $item, $context) + { + } + /** + * Notifies an administrator of a core update. + * + * @since 3.7.0 + * + * @param object $item The update offer. + * @return bool True if the site administrator is notified of a core update, + * false otherwise. + */ + protected function send_core_update_notification_email($item) + { + } + /** + * Updates an item, if appropriate. + * + * @since 3.7.0 + * + * @param string $type The type of update being checked: 'core', 'theme', 'plugin', 'translation'. + * @param object $item The update offer. + * @return null|WP_Error + */ + public function update($type, $item) + { + } + /** + * Kicks off the background update process, looping through all pending updates. + * + * @since 3.7.0 + */ + public function run() + { + } + /** + * If we tried to perform a core update, check if we should send an email, + * and if we need to avoid processing future updates. + * + * @since 3.7.0 + * + * @param object $update_result The result of the core update. Includes the update offer and result. + */ + protected function after_core_update($update_result) + { + } + /** + * Sends an email upon the completion or failure of a background core update. + * + * @since 3.7.0 + * + * @param string $type The type of email to send. Can be one of 'success', 'fail', 'manual', 'critical'. + * @param object $core_update The update offer that was attempted. + * @param mixed $result Optional. The result for the core update. Can be WP_Error. + */ + protected function send_email($type, $core_update, $result = \null) + { + } + /** + * If we tried to perform plugin or theme updates, check if we should send an email. + * + * @since 5.5.0 + * + * @param array $update_results The results of update tasks. + */ + protected function after_plugin_theme_update($update_results) + { + } + /** + * Sends an email upon the completion or failure of a plugin or theme background update. + * + * @since 5.5.0 + * + * @param string $type The type of email to send. Can be one of 'success', 'fail', 'mixed'. + * @param array $successful_updates A list of updates that succeeded. + * @param array $failed_updates A list of updates that failed. + */ + protected function send_plugin_theme_email($type, $successful_updates, $failed_updates) + { + } + /** + * Prepares and sends an email of a full log of background update results, useful for debugging and geekery. + * + * @since 3.7.0 + */ + protected function send_debug_email() + { + } + } + /** + * List Table API: WP_Comments_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 3.1.0 + */ + /** + * Core class used to implement displaying comments in a list table. + * + * @since 3.1.0 + * + * @see WP_List_Table + */ + class WP_Comments_List_Table extends \WP_List_Table + { + public $checkbox = \true; + public $pending_count = array(); + public $extra_items; + /** + * Constructor. + * + * @since 3.1.0 + * + * @see WP_List_Table::__construct() for more information on default arguments. + * + * @global int $post_id + * + * @param array $args An associative array of arguments. + */ + public function __construct($args = array()) + { + } + /** + * Adds avatars to comment author names. + * + * @since 3.1.0 + * + * @param string $name Comment author name. + * @param int $comment_id Comment ID. + * @return string Avatar with the user name. + */ + public function floated_admin_avatar($name, $comment_id) + { + } + /** + * @return bool + */ + public function ajax_user_can() + { + } + /** + * @global string $mode List table view mode. + * @global int $post_id + * @global string $comment_status + * @global string $comment_type + * @global string $search + */ + public function prepare_items() + { + } + /** + * @param string $comment_status + * @return int + */ + public function get_per_page($comment_status = 'all') + { + } + /** + * @global string $comment_status + */ + public function no_items() + { + } + /** + * @global int $post_id + * @global string $comment_status + * @global string $comment_type + */ + protected function get_views() + { + } + /** + * @global string $comment_status + * + * @return array + */ + protected function get_bulk_actions() + { + } + /** + * @global string $comment_status + * @global string $comment_type + * + * @param string $which + */ + protected function extra_tablenav($which) + { + } + /** + * @return string|false + */ + public function current_action() + { + } + /** + * @global int $post_id + * + * @return array + */ + public function get_columns() + { + } + /** + * Displays a comment type drop-down for filtering on the Comments list table. + * + * @since 5.5.0 + * @since 5.6.0 Renamed from `comment_status_dropdown()` to `comment_type_dropdown()`. + * + * @param string $comment_type The current comment type slug. + */ + protected function comment_type_dropdown($comment_type) + { + } + /** + * @return array + */ + protected function get_sortable_columns() + { + } + /** + * Gets the name of the default primary column. + * + * @since 4.3.0 + * + * @return string Name of the default primary column, in this case, 'comment'. + */ + protected function get_default_primary_column_name() + { + } + /** + * Displays the comments table. + * + * Overrides the parent display() method to render extra comments. + * + * @since 3.1.0 + */ + public function display() + { + } + /** + * @global WP_Post $post Global post object. + * @global WP_Comment $comment Global comment object. + * + * @param WP_Comment $item + */ + public function single_row($item) + { + } + /** + * Generates and displays row actions links. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$comment` to `$item` to match parent class for PHP 8 named parameter support. + * + * @global string $comment_status Status for the current listed comments. + * + * @param WP_Comment $item The comment object. + * @param string $column_name Current column name. + * @param string $primary Primary column name. + * @return string Row actions output for comments. An empty string + * if the current column is not the primary column, + * or if the current user cannot edit the comment. + */ + protected function handle_row_actions($item, $column_name, $primary) + { + } + /** + * @since 5.9.0 Renamed `$comment` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Comment $item The comment object. + */ + public function column_cb($item) + { + } + /** + * @param WP_Comment $comment The comment object. + */ + public function column_comment($comment) + { + } + /** + * @global string $comment_status + * + * @param WP_Comment $comment The comment object. + */ + public function column_author($comment) + { + } + /** + * @param WP_Comment $comment The comment object. + */ + public function column_date($comment) + { + } + /** + * @param WP_Comment $comment The comment object. + */ + public function column_response($comment) + { + } + /** + * @since 5.9.0 Renamed `$comment` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Comment $item The comment object. + * @param string $column_name The custom column's name. + */ + public function column_default($item, $column_name) + { + } + } + /** + * Administration: Community Events class. + * + * @package WordPress + * @subpackage Administration + * @since 4.8.0 + */ + /** + * Class WP_Community_Events. + * + * A client for api.wordpress.org/events. + * + * @since 4.8.0 + */ + #[\AllowDynamicProperties] + class WP_Community_Events + { + /** + * ID for a WordPress user account. + * + * @since 4.8.0 + * + * @var int + */ + protected $user_id = 0; + /** + * Stores location data for the user. + * + * @since 4.8.0 + * + * @var false|array + */ + protected $user_location = \false; + /** + * Constructor for WP_Community_Events. + * + * @since 4.8.0 + * + * @param int $user_id WP user ID. + * @param false|array $user_location { + * Stored location data for the user. false to pass no location. + * + * @type string $description The name of the location + * @type string $latitude The latitude in decimal degrees notation, without the degree + * symbol. e.g.: 47.615200. + * @type string $longitude The longitude in decimal degrees notation, without the degree + * symbol. e.g.: -122.341100. + * @type string $country The ISO 3166-1 alpha-2 country code. e.g.: BR + * } + * @phpstan-param false|array{ + * description?: string, + * latitude?: string, + * longitude?: string, + * country?: string, + * } $user_location + */ + public function __construct($user_id, $user_location = \false) + { + } + /** + * Gets data about events near a particular location. + * + * Cached events will be immediately returned if the `user_location` property + * is set for the current user, and cached events exist for that location. + * + * Otherwise, this method sends a request to the w.org Events API with location + * data. The API will send back a recognized location based on the data, along + * with nearby events. + * + * The browser's request for events is proxied with this method, rather + * than having the browser make the request directly to api.wordpress.org, + * because it allows results to be cached server-side and shared with other + * users and sites in the network. This makes the process more efficient, + * since increasing the number of visits that get cached data means users + * don't have to wait as often; if the user's browser made the request + * directly, it would also need to make a second request to WP in order to + * pass the data for caching. Having WP make the request also introduces + * the opportunity to anonymize the IP before sending it to w.org, which + * mitigates possible privacy concerns. + * + * @since 4.8.0 + * @since 5.5.2 Response no longer contains formatted date field. They're added + * in `wp.communityEvents.populateDynamicEventFields()` now. + * + * @param string $location_search Optional. City name to help determine the location. + * e.g., "Seattle". Default empty string. + * @param string $timezone Optional. Timezone to help determine the location. + * Default empty string. + * @return array|WP_Error A WP_Error on failure; an array with location and events on + * success. + */ + public function get_events($location_search = '', $timezone = '') + { + } + /** + * Builds an array of args to use in an HTTP request to the w.org Events API. + * + * @since 4.8.0 + * + * @param string $search Optional. City search string. Default empty string. + * @param string $timezone Optional. Timezone string. Default empty string. + * @return array The request args. + */ + protected function get_request_args($search = '', $timezone = '') + { + } + /** + * Determines the user's actual IP address and attempts to partially + * anonymize an IP address by converting it to a network ID. + * + * Geolocating the network ID usually returns a similar location as the + * actual IP, but provides some privacy for the user. + * + * $_SERVER['REMOTE_ADDR'] cannot be used in all cases, such as when the user + * is making their request through a proxy, or when the web server is behind + * a proxy. In those cases, $_SERVER['REMOTE_ADDR'] is set to the proxy address rather + * than the user's actual address. + * + * Modified from https://stackoverflow.com/a/2031935/450127, MIT license. + * Modified from https://github.com/geertw/php-ip-anonymizer, MIT license. + * + * SECURITY WARNING: This function is _NOT_ intended to be used in + * circumstances where the authenticity of the IP address matters. This does + * _NOT_ guarantee that the returned address is valid or accurate, and it can + * be easily spoofed. + * + * @since 4.8.0 + * + * @return string|false The anonymized address on success; the given address + * or false on failure. + */ + public static function get_unsafe_client_ip() + { + } + /** + * Test if two pairs of latitude/longitude coordinates match each other. + * + * @since 4.8.0 + * + * @param array $a The first pair, with indexes 'latitude' and 'longitude'. + * @param array $b The second pair, with indexes 'latitude' and 'longitude'. + * @return bool True if they match, false if they don't. + */ + protected function coordinates_match($a, $b) + { + } + /** + * Generates a transient key based on user location. + * + * This could be reduced to a one-liner in the calling functions, but it's + * intentionally a separate function because it's called from multiple + * functions, and having it abstracted keeps the logic consistent and DRY, + * which is less prone to errors. + * + * @since 4.8.0 + * + * @param array $location Should contain 'latitude' and 'longitude' indexes. + * @return string|false Transient key on success, false on failure. + */ + protected function get_events_transient_key($location) + { + } + /** + * Caches an array of events data from the Events API. + * + * @since 4.8.0 + * + * @param array $events Response body from the API request. + * @param int|false $expiration Optional. Amount of time to cache the events. Defaults to false. + * @return bool true if events were cached; false if not. + */ + protected function cache_events($events, $expiration = \false) + { + } + /** + * Gets cached events. + * + * @since 4.8.0 + * @since 5.5.2 Response no longer contains formatted date field. They're added + * in `wp.communityEvents.populateDynamicEventFields()` now. + * + * @return array|false An array containing `location` and `events` items + * on success, false on failure. + */ + public function get_cached_events() + { + } + /** + * Adds formatted date and time items for each event in an API response. + * + * This has to be called after the data is pulled from the cache, because + * the cached events are shared by all users. If it was called before storing + * the cache, then all users would see the events in the localized data/time + * of the user who triggered the cache refresh, rather than their own. + * + * @since 4.8.0 + * @deprecated 5.6.0 No longer used in core. + * + * @param array $response_body The response which contains the events. + * @return array The response with dates and times formatted. + */ + protected function format_event_data_time($response_body) + { + } + /** + * Prepares the event list for presentation. + * + * Discards expired events, and makes WordCamps "sticky." Attendees need more + * advanced notice about WordCamps than they do for meetups, so camps should + * appear in the list sooner. If a WordCamp is coming up, the API will "stick" + * it in the response, even if it wouldn't otherwise appear. When that happens, + * the event will be at the end of the list, and will need to be moved into a + * higher position, so that it doesn't get trimmed off. + * + * @since 4.8.0 + * @since 4.9.7 Stick a WordCamp to the final list. + * @since 5.5.2 Accepts and returns only the events, rather than an entire HTTP response. + * @since 6.0.0 Decode HTML entities from the event title. + * + * @param array $events The events that will be prepared. + * @return array The response body with events trimmed. + */ + protected function trim_events(array $events) + { + } + /** + * Logs responses to Events API requests. + * + * @since 4.8.0 + * @deprecated 4.9.0 Use a plugin instead. See #41217 for an example. + * + * @param string $message A description of what occurred. + * @param array $details Details that provide more context for the + * log entry. + */ + protected function maybe_log_events_response($message, $details) + { + } + } + /** + * Class for providing debug data based on a users WordPress environment. + * + * @package WordPress + * @subpackage Site_Health + * @since 5.2.0 + */ + #[\AllowDynamicProperties] + class WP_Debug_Data + { + /** + * Calls all core functions to check for updates. + * + * @since 5.2.0 + */ + public static function check_for_updates() + { + } + /** + * Static function for generating site debug data when required. + * + * @since 5.2.0 + * @since 5.3.0 Added database charset, database collation, + * and timezone information. + * @since 5.5.0 Added pretty permalinks support information. + * + * @throws ImagickException + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return array The debug data for the site. + */ + public static function debug_data() + { + } + /** + * Returns the value of a MySQL system variable. + * + * @since 5.9.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $mysql_var Name of the MySQL system variable. + * @return string|null The variable value on success. Null if the variable does not exist. + */ + public static function get_mysql_var($mysql_var) + { + } + /** + * Formats the information gathered for debugging, in a manner suitable for copying to a forum or support ticket. + * + * @since 5.2.0 + * + * @param array $info_array Information gathered from the `WP_Debug_Data::debug_data()` function. + * @param string $data_type The data type to return, either 'info' or 'debug'. + * @return string The formatted data. + */ + public static function format($info_array, $data_type) + { + } + /** + * Fetches the total size of all the database tables for the active database user. + * + * @since 5.2.0 + * + * @return int The size of the database, in bytes. + */ + public static function get_database_size() + { + } + /** + * Fetches the sizes of the WordPress directories: `wordpress` (ABSPATH), `plugins`, `themes`, and `uploads`. + * Intended to supplement the array returned by `WP_Debug_Data::debug_data()`. + * + * @since 5.2.0 + * + * @return array The sizes of the directories, also the database size and total installation size. + */ + public static function get_sizes() + { + } + } + /** + * Base WordPress Filesystem + * + * @package WordPress + * @subpackage Filesystem + */ + /** + * Base WordPress Filesystem class which Filesystem implementations extend. + * + * @since 2.5.0 + */ + #[\AllowDynamicProperties] + class WP_Filesystem_Base + { + /** + * Whether to display debug data for the connection. + * + * @since 2.5.0 + * @var bool + */ + public $verbose = \false; + /** + * Cached list of local filepaths to mapped remote filepaths. + * + * @since 2.7.0 + * @var array + */ + public $cache = array(); + /** + * The Access method of the current connection, Set automatically. + * + * @since 2.5.0 + * @var string + */ + public $method = ''; + /** + * @var WP_Error + */ + public $errors = \null; + /** + */ + public $options = array(); + /** + * Returns the path on the remote filesystem of ABSPATH. + * + * @since 2.7.0 + * + * @return string The location of the remote path. + */ + public function abspath() + { + } + /** + * Returns the path on the remote filesystem of WP_CONTENT_DIR. + * + * @since 2.7.0 + * + * @return string The location of the remote path. + */ + public function wp_content_dir() + { + } + /** + * Returns the path on the remote filesystem of WP_PLUGIN_DIR. + * + * @since 2.7.0 + * + * @return string The location of the remote path. + */ + public function wp_plugins_dir() + { + } + /** + * Returns the path on the remote filesystem of the Themes Directory. + * + * @since 2.7.0 + * + * @param string|false $theme Optional. The theme stylesheet or template for the directory. + * Default false. + * @return string The location of the remote path. + */ + public function wp_themes_dir($theme = \false) + { + } + /** + * Returns the path on the remote filesystem of WP_LANG_DIR. + * + * @since 3.2.0 + * + * @return string The location of the remote path. + */ + public function wp_lang_dir() + { + } + /** + * Locates a folder on the remote filesystem. + * + * @since 2.5.0 + * @deprecated 2.7.0 use WP_Filesystem_Base::abspath() or WP_Filesystem_Base::wp_*_dir() instead. + * @see WP_Filesystem_Base::abspath() + * @see WP_Filesystem_Base::wp_content_dir() + * @see WP_Filesystem_Base::wp_plugins_dir() + * @see WP_Filesystem_Base::wp_themes_dir() + * @see WP_Filesystem_Base::wp_lang_dir() + * + * @param string $base Optional. The folder to start searching from. Default '.'. + * @param bool $verbose Optional. True to display debug information. Default false. + * @return string The location of the remote path. + */ + public function find_base_dir($base = '.', $verbose = \false) + { + } + /** + * Locates a folder on the remote filesystem. + * + * @since 2.5.0 + * @deprecated 2.7.0 use WP_Filesystem_Base::abspath() or WP_Filesystem_Base::wp_*_dir() methods instead. + * @see WP_Filesystem_Base::abspath() + * @see WP_Filesystem_Base::wp_content_dir() + * @see WP_Filesystem_Base::wp_plugins_dir() + * @see WP_Filesystem_Base::wp_themes_dir() + * @see WP_Filesystem_Base::wp_lang_dir() + * + * @param string $base Optional. The folder to start searching from. Default '.'. + * @param bool $verbose Optional. True to display debug information. Default false. + * @return string The location of the remote path. + */ + public function get_base_dir($base = '.', $verbose = \false) + { + } + /** + * Locates a folder on the remote filesystem. + * + * Assumes that on Windows systems, Stripping off the Drive + * letter is OK Sanitizes \\ to / in Windows filepaths. + * + * @since 2.7.0 + * + * @param string $folder the folder to locate. + * @return string|false The location of the remote path, false on failure. + */ + public function find_folder($folder) + { + } + /** + * Locates a folder on the remote filesystem. + * + * Expects Windows sanitized path. + * + * @since 2.7.0 + * + * @param string $folder The folder to locate. + * @param string $base The folder to start searching from. + * @param bool $loop If the function has recursed. Internal use only. + * @return string|false The location of the remote path, false to cease looping. + */ + public function search_for_folder($folder, $base = '.', $loop = \false) + { + } + /** + * Returns the *nix-style file permissions for a file. + * + * From the PHP documentation page for fileperms(). + * + * @link https://www.php.net/manual/en/function.fileperms.php + * + * @since 2.5.0 + * + * @param string $file String filename. + * @return string The *nix-style representation of permissions. + */ + public function gethchmod($file) + { + } + /** + * Gets the permissions of the specified file or filepath in their octal format. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return string Mode of the file (the last 3 digits). + */ + public function getchmod($file) + { + } + /** + * Converts *nix-style file permissions to a octal number. + * + * Converts '-rw-r--r--' to 0644 + * From "info at rvgate dot nl"'s comment on the PHP documentation for chmod() + * + * @link https://www.php.net/manual/en/function.chmod.php#49614 + * + * @since 2.5.0 + * + * @param string $mode string The *nix-style file permissions. + * @return string Octal representation of permissions. + */ + public function getnumchmodfromh($mode) + { + } + /** + * Determines if the string provided contains binary characters. + * + * @since 2.7.0 + * + * @param string $text String to test against. + * @return bool True if string is binary, false otherwise. + */ + public function is_binary($text) + { + } + /** + * Changes the owner of a file or directory. + * + * Default behavior is to do nothing, override this in your subclass, if desired. + * + * @since 2.5.0 + * + * @param string $file Path to the file or directory. + * @param string|int $owner A user name or number. + * @param bool $recursive Optional. If set to true, changes file owner recursively. + * Default false. + * @return bool True on success, false on failure. + */ + public function chown($file, $owner, $recursive = \false) + { + } + /** + * Connects filesystem. + * + * @since 2.5.0 + * @abstract + * + * @return bool True on success, false on failure (always true for WP_Filesystem_Direct). + */ + public function connect() + { + } + /** + * Reads entire file into a string. + * + * @since 2.5.0 + * @abstract + * + * @param string $file Name of the file to read. + * @return string|false Read data on success, false on failure. + */ + public function get_contents($file) + { + } + /** + * Reads entire file into an array. + * + * @since 2.5.0 + * @abstract + * + * @param string $file Path to the file. + * @return array|false File contents in an array on success, false on failure. + */ + public function get_contents_array($file) + { + } + /** + * Writes a string to a file. + * + * @since 2.5.0 + * @abstract + * + * @param string $file Remote path to the file where to write the data. + * @param string $contents The data to write. + * @param int|false $mode Optional. The file permissions as octal number, usually 0644. + * Default false. + * @return bool True on success, false on failure. + */ + public function put_contents($file, $contents, $mode = \false) + { + } + /** + * Gets the current working directory. + * + * @since 2.5.0 + * @abstract + * + * @return string|false The current working directory on success, false on failure. + */ + public function cwd() + { + } + /** + * Changes current directory. + * + * @since 2.5.0 + * @abstract + * + * @param string $dir The new current directory. + * @return bool True on success, false on failure. + */ + public function chdir($dir) + { + } + /** + * Changes the file group. + * + * @since 2.5.0 + * @abstract + * + * @param string $file Path to the file. + * @param string|int $group A group name or number. + * @param bool $recursive Optional. If set to true, changes file group recursively. + * Default false. + * @return bool True on success, false on failure. + */ + public function chgrp($file, $group, $recursive = \false) + { + } + /** + * Changes filesystem permissions. + * + * @since 2.5.0 + * @abstract + * + * @param string $file Path to the file. + * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, + * 0755 for directories. Default false. + * @param bool $recursive Optional. If set to true, changes file permissions recursively. + * Default false. + * @return bool True on success, false on failure. + */ + public function chmod($file, $mode = \false, $recursive = \false) + { + } + /** + * Gets the file owner. + * + * @since 2.5.0 + * @abstract + * + * @param string $file Path to the file. + * @return string|false Username of the owner on success, false on failure. + */ + public function owner($file) + { + } + /** + * Gets the file's group. + * + * @since 2.5.0 + * @abstract + * + * @param string $file Path to the file. + * @return string|false The group on success, false on failure. + */ + public function group($file) + { + } + /** + * Copies a file. + * + * @since 2.5.0 + * @abstract + * + * @param string $source Path to the source file. + * @param string $destination Path to the destination file. + * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. + * Default false. + * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, + * 0755 for dirs. Default false. + * @return bool True on success, false on failure. + */ + public function copy($source, $destination, $overwrite = \false, $mode = \false) + { + } + /** + * Moves a file. + * + * @since 2.5.0 + * @abstract + * + * @param string $source Path to the source file. + * @param string $destination Path to the destination file. + * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. + * Default false. + * @return bool True on success, false on failure. + */ + public function move($source, $destination, $overwrite = \false) + { + } + /** + * Deletes a file or directory. + * + * @since 2.5.0 + * @abstract + * + * @param string $file Path to the file or directory. + * @param bool $recursive Optional. If set to true, deletes files and folders recursively. + * Default false. + * @param string|false $type Type of resource. 'f' for file, 'd' for directory. + * Default false. + * @return bool True on success, false on failure. + */ + public function delete($file, $recursive = \false, $type = \false) + { + } + /** + * Checks if a file or directory exists. + * + * @since 2.5.0 + * @abstract + * + * @param string $path Path to file or directory. + * @return bool Whether $path exists or not. + */ + public function exists($path) + { + } + /** + * Checks if resource is a file. + * + * @since 2.5.0 + * @abstract + * + * @param string $file File path. + * @return bool Whether $file is a file. + */ + public function is_file($file) + { + } + /** + * Checks if resource is a directory. + * + * @since 2.5.0 + * @abstract + * + * @param string $path Directory path. + * @return bool Whether $path is a directory. + */ + public function is_dir($path) + { + } + /** + * Checks if a file is readable. + * + * @since 2.5.0 + * @abstract + * + * @param string $file Path to file. + * @return bool Whether $file is readable. + */ + public function is_readable($file) + { + } + /** + * Checks if a file or directory is writable. + * + * @since 2.5.0 + * @abstract + * + * @param string $path Path to file or directory. + * @return bool Whether $path is writable. + */ + public function is_writable($path) + { + } + /** + * Gets the file's last access time. + * + * @since 2.5.0 + * @abstract + * + * @param string $file Path to file. + * @return int|false Unix timestamp representing last access time, false on failure. + */ + public function atime($file) + { + } + /** + * Gets the file modification time. + * + * @since 2.5.0 + * @abstract + * + * @param string $file Path to file. + * @return int|false Unix timestamp representing modification time, false on failure. + */ + public function mtime($file) + { + } + /** + * Gets the file size (in bytes). + * + * @since 2.5.0 + * @abstract + * + * @param string $file Path to file. + * @return int|false Size of the file in bytes on success, false on failure. + */ + public function size($file) + { + } + /** + * Sets the access and modification times of a file. + * + * Note: If $file doesn't exist, it will be created. + * + * @since 2.5.0 + * @abstract + * + * @param string $file Path to file. + * @param int $time Optional. Modified time to set for file. + * Default 0. + * @param int $atime Optional. Access time to set for file. + * Default 0. + * @return bool True on success, false on failure. + */ + public function touch($file, $time = 0, $atime = 0) + { + } + /** + * Creates a directory. + * + * @since 2.5.0 + * @abstract + * + * @param string $path Path for new directory. + * @param int|false $chmod Optional. The permissions as octal number (or false to skip chmod). + * Default false. + * @param string|int|false $chown Optional. A user name or number (or false to skip chown). + * Default false. + * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp). + * Default false. + * @return bool True on success, false on failure. + */ + public function mkdir($path, $chmod = \false, $chown = \false, $chgrp = \false) + { + } + /** + * Deletes a directory. + * + * @since 2.5.0 + * @abstract + * + * @param string $path Path to directory. + * @param bool $recursive Optional. Whether to recursively remove files/directories. + * Default false. + * @return bool True on success, false on failure. + */ + public function rmdir($path, $recursive = \false) + { + } + /** + * Gets details for files in a directory or a specific file. + * + * @since 2.5.0 + * @abstract + * + * @param string $path Path to directory or file. + * @param bool $include_hidden Optional. Whether to include details of hidden ("." prefixed) files. + * Default true. + * @param bool $recursive Optional. Whether to recursively include file details in nested directories. + * Default false. + * @return array|false { + * Array of files. False if unable to list directory contents. + * + * @type string $name Name of the file or directory. + * @type string $perms *nix representation of permissions. + * @type string $permsn Octal representation of permissions. + * @type string $owner Owner name or ID. + * @type int $size Size of file in bytes. + * @type int $lastmodunix Last modified unix timestamp. + * @type mixed $lastmod Last modified month (3 letter) and day (without leading 0). + * @type int $time Last modified time. + * @type string $type Type of resource. 'f' for file, 'd' for directory. + * @type mixed $files If a directory and `$recursive` is true, contains another array of files. + * } + * @phpstan-return false|array{ + * name: string, + * perms: string, + * permsn: string, + * owner: string, + * size: int, + * lastmodunix: int, + * lastmod: mixed, + * time: int, + * type: string, + * files: mixed, + * } + */ + public function dirlist($path, $include_hidden = \true, $recursive = \false) + { + } + } + /** + * WordPress Direct Filesystem. + * + * @package WordPress + * @subpackage Filesystem + */ + /** + * WordPress Filesystem Class for direct PHP file and folder manipulation. + * + * @since 2.5.0 + * + * @see WP_Filesystem_Base + */ + class WP_Filesystem_Direct extends \WP_Filesystem_Base + { + /** + * Constructor. + * + * @since 2.5.0 + * + * @param mixed $arg Not used. + */ + public function __construct($arg) + { + } + /** + * Reads entire file into a string. + * + * @since 2.5.0 + * + * @param string $file Name of the file to read. + * @return string|false Read data on success, false on failure. + */ + public function get_contents($file) + { + } + /** + * Reads entire file into an array. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return array|false File contents in an array on success, false on failure. + */ + public function get_contents_array($file) + { + } + /** + * Writes a string to a file. + * + * @since 2.5.0 + * + * @param string $file Remote path to the file where to write the data. + * @param string $contents The data to write. + * @param int|false $mode Optional. The file permissions as octal number, usually 0644. + * Default false. + * @return bool True on success, false on failure. + */ + public function put_contents($file, $contents, $mode = \false) + { + } + /** + * Gets the current working directory. + * + * @since 2.5.0 + * + * @return string|false The current working directory on success, false on failure. + */ + public function cwd() + { + } + /** + * Changes current directory. + * + * @since 2.5.0 + * + * @param string $dir The new current directory. + * @return bool True on success, false on failure. + */ + public function chdir($dir) + { + } + /** + * Changes the file group. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @param string|int $group A group name or number. + * @param bool $recursive Optional. If set to true, changes file group recursively. + * Default false. + * @return bool True on success, false on failure. + */ + public function chgrp($file, $group, $recursive = \false) + { + } + /** + * Changes filesystem permissions. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, + * 0755 for directories. Default false. + * @param bool $recursive Optional. If set to true, changes file permissions recursively. + * Default false. + * @return bool True on success, false on failure. + */ + public function chmod($file, $mode = \false, $recursive = \false) + { + } + /** + * Changes the owner of a file or directory. + * + * @since 2.5.0 + * + * @param string $file Path to the file or directory. + * @param string|int $owner A user name or number. + * @param bool $recursive Optional. If set to true, changes file owner recursively. + * Default false. + * @return bool True on success, false on failure. + */ + public function chown($file, $owner, $recursive = \false) + { + } + /** + * Gets the file owner. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return string|false Username of the owner on success, false on failure. + */ + public function owner($file) + { + } + /** + * Gets the permissions of the specified file or filepath in their octal format. + * + * FIXME does not handle errors in fileperms() + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return string Mode of the file (the last 3 digits). + */ + public function getchmod($file) + { + } + /** + * Gets the file's group. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return string|false The group on success, false on failure. + */ + public function group($file) + { + } + /** + * Copies a file. + * + * @since 2.5.0 + * + * @param string $source Path to the source file. + * @param string $destination Path to the destination file. + * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. + * Default false. + * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, + * 0755 for dirs. Default false. + * @return bool True on success, false on failure. + */ + public function copy($source, $destination, $overwrite = \false, $mode = \false) + { + } + /** + * Moves a file. + * + * @since 2.5.0 + * + * @param string $source Path to the source file. + * @param string $destination Path to the destination file. + * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. + * Default false. + * @return bool True on success, false on failure. + */ + public function move($source, $destination, $overwrite = \false) + { + } + /** + * Deletes a file or directory. + * + * @since 2.5.0 + * + * @param string $file Path to the file or directory. + * @param bool $recursive Optional. If set to true, deletes files and folders recursively. + * Default false. + * @param string|false $type Type of resource. 'f' for file, 'd' for directory. + * Default false. + * @return bool True on success, false on failure. + */ + public function delete($file, $recursive = \false, $type = \false) + { + } + /** + * Checks if a file or directory exists. + * + * @since 2.5.0 + * + * @param string $path Path to file or directory. + * @return bool Whether $path exists or not. + */ + public function exists($path) + { + } + /** + * Checks if resource is a file. + * + * @since 2.5.0 + * + * @param string $file File path. + * @return bool Whether $file is a file. + */ + public function is_file($file) + { + } + /** + * Checks if resource is a directory. + * + * @since 2.5.0 + * + * @param string $path Directory path. + * @return bool Whether $path is a directory. + */ + public function is_dir($path) + { + } + /** + * Checks if a file is readable. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return bool Whether $file is readable. + */ + public function is_readable($file) + { + } + /** + * Checks if a file or directory is writable. + * + * @since 2.5.0 + * + * @param string $path Path to file or directory. + * @return bool Whether $path is writable. + */ + public function is_writable($path) + { + } + /** + * Gets the file's last access time. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return int|false Unix timestamp representing last access time, false on failure. + */ + public function atime($file) + { + } + /** + * Gets the file modification time. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return int|false Unix timestamp representing modification time, false on failure. + */ + public function mtime($file) + { + } + /** + * Gets the file size (in bytes). + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return int|false Size of the file in bytes on success, false on failure. + */ + public function size($file) + { + } + /** + * Sets the access and modification times of a file. + * + * Note: If $file doesn't exist, it will be created. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @param int $time Optional. Modified time to set for file. + * Default 0. + * @param int $atime Optional. Access time to set for file. + * Default 0. + * @return bool True on success, false on failure. + */ + public function touch($file, $time = 0, $atime = 0) + { + } + /** + * Creates a directory. + * + * @since 2.5.0 + * + * @param string $path Path for new directory. + * @param int|false $chmod Optional. The permissions as octal number (or false to skip chmod). + * Default false. + * @param string|int|false $chown Optional. A user name or number (or false to skip chown). + * Default false. + * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp). + * Default false. + * @return bool True on success, false on failure. + */ + public function mkdir($path, $chmod = \false, $chown = \false, $chgrp = \false) + { + } + /** + * Deletes a directory. + * + * @since 2.5.0 + * + * @param string $path Path to directory. + * @param bool $recursive Optional. Whether to recursively remove files/directories. + * Default false. + * @return bool True on success, false on failure. + */ + public function rmdir($path, $recursive = \false) + { + } + /** + * Gets details for files in a directory or a specific file. + * + * @since 2.5.0 + * + * @param string $path Path to directory or file. + * @param bool $include_hidden Optional. Whether to include details of hidden ("." prefixed) files. + * Default true. + * @param bool $recursive Optional. Whether to recursively include file details in nested directories. + * Default false. + * @return array|false { + * Array of files. False if unable to list directory contents. + * + * @type string $name Name of the file or directory. + * @type string $perms *nix representation of permissions. + * @type string $permsn Octal representation of permissions. + * @type string $owner Owner name or ID. + * @type int $size Size of file in bytes. + * @type int $lastmodunix Last modified unix timestamp. + * @type mixed $lastmod Last modified month (3 letter) and day (without leading 0). + * @type int $time Last modified time. + * @type string $type Type of resource. 'f' for file, 'd' for directory. + * @type mixed $files If a directory and `$recursive` is true, contains another array of files. + * } + * @phpstan-return false|array{ + * name: string, + * perms: string, + * permsn: string, + * owner: string, + * size: int, + * lastmodunix: int, + * lastmod: mixed, + * time: int, + * type: string, + * files: mixed, + * } + */ + public function dirlist($path, $include_hidden = \true, $recursive = \false) + { + } + } + /** + * WordPress FTP Filesystem. + * + * @package WordPress + * @subpackage Filesystem + */ + /** + * WordPress Filesystem Class for implementing FTP. + * + * @since 2.5.0 + * + * @see WP_Filesystem_Base + */ + class WP_Filesystem_FTPext extends \WP_Filesystem_Base + { + /** + * @since 2.5.0 + * @var resource + */ + public $link; + /** + * Constructor. + * + * @since 2.5.0 + * + * @param array $opt + */ + public function __construct($opt = '') + { + } + /** + * Connects filesystem. + * + * @since 2.5.0 + * + * @return bool True on success, false on failure. + */ + public function connect() + { + } + /** + * Reads entire file into a string. + * + * @since 2.5.0 + * + * @param string $file Name of the file to read. + * @return string|false Read data on success, false if no temporary file could be opened, + * or if the file couldn't be retrieved. + */ + public function get_contents($file) + { + } + /** + * Reads entire file into an array. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return array|false File contents in an array on success, false on failure. + */ + public function get_contents_array($file) + { + } + /** + * Writes a string to a file. + * + * @since 2.5.0 + * + * @param string $file Remote path to the file where to write the data. + * @param string $contents The data to write. + * @param int|false $mode Optional. The file permissions as octal number, usually 0644. + * Default false. + * @return bool True on success, false on failure. + */ + public function put_contents($file, $contents, $mode = \false) + { + } + /** + * Gets the current working directory. + * + * @since 2.5.0 + * + * @return string|false The current working directory on success, false on failure. + */ + public function cwd() + { + } + /** + * Changes current directory. + * + * @since 2.5.0 + * + * @param string $dir The new current directory. + * @return bool True on success, false on failure. + */ + public function chdir($dir) + { + } + /** + * Changes filesystem permissions. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, + * 0755 for directories. Default false. + * @param bool $recursive Optional. If set to true, changes file permissions recursively. + * Default false. + * @return bool True on success, false on failure. + */ + public function chmod($file, $mode = \false, $recursive = \false) + { + } + /** + * Gets the file owner. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return string|false Username of the owner on success, false on failure. + */ + public function owner($file) + { + } + /** + * Gets the permissions of the specified file or filepath in their octal format. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return string Mode of the file (the last 3 digits). + */ + public function getchmod($file) + { + } + /** + * Gets the file's group. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return string|false The group on success, false on failure. + */ + public function group($file) + { + } + /** + * Copies a file. + * + * @since 2.5.0 + * + * @param string $source Path to the source file. + * @param string $destination Path to the destination file. + * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. + * Default false. + * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, + * 0755 for dirs. Default false. + * @return bool True on success, false on failure. + */ + public function copy($source, $destination, $overwrite = \false, $mode = \false) + { + } + /** + * Moves a file. + * + * @since 2.5.0 + * + * @param string $source Path to the source file. + * @param string $destination Path to the destination file. + * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. + * Default false. + * @return bool True on success, false on failure. + */ + public function move($source, $destination, $overwrite = \false) + { + } + /** + * Deletes a file or directory. + * + * @since 2.5.0 + * + * @param string $file Path to the file or directory. + * @param bool $recursive Optional. If set to true, deletes files and folders recursively. + * Default false. + * @param string|false $type Type of resource. 'f' for file, 'd' for directory. + * Default false. + * @return bool True on success, false on failure. + */ + public function delete($file, $recursive = \false, $type = \false) + { + } + /** + * Checks if a file or directory exists. + * + * @since 2.5.0 + * + * @param string $path Path to file or directory. + * @return bool Whether $path exists or not. + */ + public function exists($path) + { + } + /** + * Checks if resource is a file. + * + * @since 2.5.0 + * + * @param string $file File path. + * @return bool Whether $file is a file. + */ + public function is_file($file) + { + } + /** + * Checks if resource is a directory. + * + * @since 2.5.0 + * + * @param string $path Directory path. + * @return bool Whether $path is a directory. + */ + public function is_dir($path) + { + } + /** + * Checks if a file is readable. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return bool Whether $file is readable. + */ + public function is_readable($file) + { + } + /** + * Checks if a file or directory is writable. + * + * @since 2.5.0 + * + * @param string $path Path to file or directory. + * @return bool Whether $path is writable. + */ + public function is_writable($path) + { + } + /** + * Gets the file's last access time. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return int|false Unix timestamp representing last access time, false on failure. + */ + public function atime($file) + { + } + /** + * Gets the file modification time. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return int|false Unix timestamp representing modification time, false on failure. + */ + public function mtime($file) + { + } + /** + * Gets the file size (in bytes). + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return int|false Size of the file in bytes on success, false on failure. + */ + public function size($file) + { + } + /** + * Sets the access and modification times of a file. + * + * Note: If $file doesn't exist, it will be created. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @param int $time Optional. Modified time to set for file. + * Default 0. + * @param int $atime Optional. Access time to set for file. + * Default 0. + * @return bool True on success, false on failure. + */ + public function touch($file, $time = 0, $atime = 0) + { + } + /** + * Creates a directory. + * + * @since 2.5.0 + * + * @param string $path Path for new directory. + * @param int|false $chmod Optional. The permissions as octal number (or false to skip chmod). + * Default false. + * @param string|int|false $chown Optional. A user name or number (or false to skip chown). + * Default false. + * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp). + * Default false. + * @return bool True on success, false on failure. + */ + public function mkdir($path, $chmod = \false, $chown = \false, $chgrp = \false) + { + } + /** + * Deletes a directory. + * + * @since 2.5.0 + * + * @param string $path Path to directory. + * @param bool $recursive Optional. Whether to recursively remove files/directories. + * Default false. + * @return bool True on success, false on failure. + */ + public function rmdir($path, $recursive = \false) + { + } + /** + * @param string $line + * @return array + */ + public function parselisting($line) + { + } + /** + * Gets details for files in a directory or a specific file. + * + * @since 2.5.0 + * + * @param string $path Path to directory or file. + * @param bool $include_hidden Optional. Whether to include details of hidden ("." prefixed) files. + * Default true. + * @param bool $recursive Optional. Whether to recursively include file details in nested directories. + * Default false. + * @return array|false { + * Array of files. False if unable to list directory contents. + * + * @type string $name Name of the file or directory. + * @type string $perms *nix representation of permissions. + * @type string $permsn Octal representation of permissions. + * @type string $owner Owner name or ID. + * @type int $size Size of file in bytes. + * @type int $lastmodunix Last modified unix timestamp. + * @type mixed $lastmod Last modified month (3 letter) and day (without leading 0). + * @type int $time Last modified time. + * @type string $type Type of resource. 'f' for file, 'd' for directory. + * @type mixed $files If a directory and `$recursive` is true, contains another array of files. + * } + * @phpstan-return false|array{ + * name: string, + * perms: string, + * permsn: string, + * owner: string, + * size: int, + * lastmodunix: int, + * lastmod: mixed, + * time: int, + * type: string, + * files: mixed, + * } + */ + public function dirlist($path = '.', $include_hidden = \true, $recursive = \false) + { + } + /** + * Destructor. + * + * @since 2.5.0 + */ + public function __destruct() + { + } + } + /** + * WordPress FTP Sockets Filesystem. + * + * @package WordPress + * @subpackage Filesystem + */ + /** + * WordPress Filesystem Class for implementing FTP Sockets. + * + * @since 2.5.0 + * + * @see WP_Filesystem_Base + */ + class WP_Filesystem_ftpsockets extends \WP_Filesystem_Base + { + /** + * @since 2.5.0 + * @var ftp + */ + public $ftp; + /** + * Constructor. + * + * @since 2.5.0 + * + * @param array $opt + */ + public function __construct($opt = '') + { + } + /** + * Connects filesystem. + * + * @since 2.5.0 + * + * @return bool True on success, false on failure. + */ + public function connect() + { + } + /** + * Reads entire file into a string. + * + * @since 2.5.0 + * + * @param string $file Name of the file to read. + * @return string|false Read data on success, false if no temporary file could be opened, + * or if the file couldn't be retrieved. + */ + public function get_contents($file) + { + } + /** + * Reads entire file into an array. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return array|false File contents in an array on success, false on failure. + */ + public function get_contents_array($file) + { + } + /** + * Writes a string to a file. + * + * @since 2.5.0 + * + * @param string $file Remote path to the file where to write the data. + * @param string $contents The data to write. + * @param int|false $mode Optional. The file permissions as octal number, usually 0644. + * Default false. + * @return bool True on success, false on failure. + */ + public function put_contents($file, $contents, $mode = \false) + { + } + /** + * Gets the current working directory. + * + * @since 2.5.0 + * + * @return string|false The current working directory on success, false on failure. + */ + public function cwd() + { + } + /** + * Changes current directory. + * + * @since 2.5.0 + * + * @param string $dir The new current directory. + * @return bool True on success, false on failure. + */ + public function chdir($dir) + { + } + /** + * Changes filesystem permissions. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, + * 0755 for directories. Default false. + * @param bool $recursive Optional. If set to true, changes file permissions recursively. + * Default false. + * @return bool True on success, false on failure. + */ + public function chmod($file, $mode = \false, $recursive = \false) + { + } + /** + * Gets the file owner. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return string|false Username of the owner on success, false on failure. + */ + public function owner($file) + { + } + /** + * Gets the permissions of the specified file or filepath in their octal format. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return string Mode of the file (the last 3 digits). + */ + public function getchmod($file) + { + } + /** + * Gets the file's group. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return string|false The group on success, false on failure. + */ + public function group($file) + { + } + /** + * Copies a file. + * + * @since 2.5.0 + * + * @param string $source Path to the source file. + * @param string $destination Path to the destination file. + * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. + * Default false. + * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, + * 0755 for dirs. Default false. + * @return bool True on success, false on failure. + */ + public function copy($source, $destination, $overwrite = \false, $mode = \false) + { + } + /** + * Moves a file. + * + * @since 2.5.0 + * + * @param string $source Path to the source file. + * @param string $destination Path to the destination file. + * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. + * Default false. + * @return bool True on success, false on failure. + */ + public function move($source, $destination, $overwrite = \false) + { + } + /** + * Deletes a file or directory. + * + * @since 2.5.0 + * + * @param string $file Path to the file or directory. + * @param bool $recursive Optional. If set to true, deletes files and folders recursively. + * Default false. + * @param string|false $type Type of resource. 'f' for file, 'd' for directory. + * Default false. + * @return bool True on success, false on failure. + */ + public function delete($file, $recursive = \false, $type = \false) + { + } + /** + * Checks if a file or directory exists. + * + * @since 2.5.0 + * + * @param string $path Path to file or directory. + * @return bool Whether $path exists or not. + */ + public function exists($path) + { + } + /** + * Checks if resource is a file. + * + * @since 2.5.0 + * + * @param string $file File path. + * @return bool Whether $file is a file. + */ + public function is_file($file) + { + } + /** + * Checks if resource is a directory. + * + * @since 2.5.0 + * + * @param string $path Directory path. + * @return bool Whether $path is a directory. + */ + public function is_dir($path) + { + } + /** + * Checks if a file is readable. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return bool Whether $file is readable. + */ + public function is_readable($file) + { + } + /** + * Checks if a file or directory is writable. + * + * @since 2.5.0 + * + * @param string $path Path to file or directory. + * @return bool Whether $path is writable. + */ + public function is_writable($path) + { + } + /** + * Gets the file's last access time. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return int|false Unix timestamp representing last access time, false on failure. + */ + public function atime($file) + { + } + /** + * Gets the file modification time. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return int|false Unix timestamp representing modification time, false on failure. + */ + public function mtime($file) + { + } + /** + * Gets the file size (in bytes). + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return int|false Size of the file in bytes on success, false on failure. + */ + public function size($file) + { + } + /** + * Sets the access and modification times of a file. + * + * Note: If $file doesn't exist, it will be created. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @param int $time Optional. Modified time to set for file. + * Default 0. + * @param int $atime Optional. Access time to set for file. + * Default 0. + * @return bool True on success, false on failure. + */ + public function touch($file, $time = 0, $atime = 0) + { + } + /** + * Creates a directory. + * + * @since 2.5.0 + * + * @param string $path Path for new directory. + * @param int|false $chmod Optional. The permissions as octal number (or false to skip chmod). + * Default false. + * @param string|int|false $chown Optional. A user name or number (or false to skip chown). + * Default false. + * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp). + * Default false. + * @return bool True on success, false on failure. + */ + public function mkdir($path, $chmod = \false, $chown = \false, $chgrp = \false) + { + } + /** + * Deletes a directory. + * + * @since 2.5.0 + * + * @param string $path Path to directory. + * @param bool $recursive Optional. Whether to recursively remove files/directories. + * Default false. + * @return bool True on success, false on failure. + */ + public function rmdir($path, $recursive = \false) + { + } + /** + * Gets details for files in a directory or a specific file. + * + * @since 2.5.0 + * + * @param string $path Path to directory or file. + * @param bool $include_hidden Optional. Whether to include details of hidden ("." prefixed) files. + * Default true. + * @param bool $recursive Optional. Whether to recursively include file details in nested directories. + * Default false. + * @return array|false { + * Array of files. False if unable to list directory contents. + * + * @type string $name Name of the file or directory. + * @type string $perms *nix representation of permissions. + * @type string $permsn Octal representation of permissions. + * @type string $owner Owner name or ID. + * @type int $size Size of file in bytes. + * @type int $lastmodunix Last modified unix timestamp. + * @type mixed $lastmod Last modified month (3 letter) and day (without leading 0). + * @type int $time Last modified time. + * @type string $type Type of resource. 'f' for file, 'd' for directory. + * @type mixed $files If a directory and `$recursive` is true, contains another array of files. + * } + * @phpstan-return false|array{ + * name: string, + * perms: string, + * permsn: string, + * owner: string, + * size: int, + * lastmodunix: int, + * lastmod: mixed, + * time: int, + * type: string, + * files: mixed, + * } + */ + public function dirlist($path = '.', $include_hidden = \true, $recursive = \false) + { + } + /** + * Destructor. + * + * @since 2.5.0 + */ + public function __destruct() + { + } + } + /** + * WordPress Filesystem Class for implementing SSH2 + * + * To use this class you must follow these steps for PHP 5.2.6+ + * + * @contrib http://kevin.vanzonneveld.net/techblog/article/make_ssh_connections_with_php/ - Installation Notes + * + * Compile libssh2 (Note: Only 0.14 is officaly working with PHP 5.2.6+ right now, But many users have found the latest versions work) + * + * cd /usr/src + * wget https://www.libssh2.org/download/libssh2-0.14.tar.gz + * tar -zxvf libssh2-0.14.tar.gz + * cd libssh2-0.14/ + * ./configure + * make all install + * + * Note: Do not leave the directory yet! + * + * Enter: pecl install -f ssh2 + * + * Copy the ssh.so file it creates to your PHP Module Directory. + * Open up your PHP.INI file and look for where extensions are placed. + * Add in your PHP.ini file: extension=ssh2.so + * + * Restart Apache! + * Check phpinfo() streams to confirm that: ssh2.shell, ssh2.exec, ssh2.tunnel, ssh2.scp, ssh2.sftp exist. + * + * Note: As of WordPress 2.8, this utilizes the PHP5+ function `stream_get_contents()`. + * + * @since 2.7.0 + * + * @package WordPress + * @subpackage Filesystem + */ + class WP_Filesystem_SSH2 extends \WP_Filesystem_Base + { + /** + * @since 2.7.0 + * @var resource + */ + public $link = \false; + /** + * @since 2.7.0 + * @var resource + */ + public $sftp_link; + /** + * @since 2.7.0 + * @var bool + */ + public $keys = \false; + /** + * Constructor. + * + * @since 2.7.0 + * + * @param array $opt + */ + public function __construct($opt = '') + { + } + /** + * Connects filesystem. + * + * @since 2.7.0 + * + * @return bool True on success, false on failure. + */ + public function connect() + { + } + /** + * Gets the ssh2.sftp PHP stream wrapper path to open for the given file. + * + * This method also works around a PHP bug where the root directory (/) cannot + * be opened by PHP functions, causing a false failure. In order to work around + * this, the path is converted to /./ which is semantically the same as / + * See https://bugs.php.net/bug.php?id=64169 for more details. + * + * @since 4.4.0 + * + * @param string $path The File/Directory path on the remote server to return + * @return string The ssh2.sftp:// wrapped path to use. + */ + public function sftp_path($path) + { + } + /** + * @since 2.7.0 + * + * @param string $command + * @param bool $returnbool + * @return bool|string True on success, false on failure. String if the command was executed, `$returnbool` + * is false (default), and data from the resulting stream was retrieved. + */ + public function run_command($command, $returnbool = \false) + { + } + /** + * Reads entire file into a string. + * + * @since 2.7.0 + * + * @param string $file Name of the file to read. + * @return string|false Read data on success, false if no temporary file could be opened, + * or if the file couldn't be retrieved. + */ + public function get_contents($file) + { + } + /** + * Reads entire file into an array. + * + * @since 2.7.0 + * + * @param string $file Path to the file. + * @return array|false File contents in an array on success, false on failure. + */ + public function get_contents_array($file) + { + } + /** + * Writes a string to a file. + * + * @since 2.7.0 + * + * @param string $file Remote path to the file where to write the data. + * @param string $contents The data to write. + * @param int|false $mode Optional. The file permissions as octal number, usually 0644. + * Default false. + * @return bool True on success, false on failure. + */ + public function put_contents($file, $contents, $mode = \false) + { + } + /** + * Gets the current working directory. + * + * @since 2.7.0 + * + * @return string|false The current working directory on success, false on failure. + */ + public function cwd() + { + } + /** + * Changes current directory. + * + * @since 2.7.0 + * + * @param string $dir The new current directory. + * @return bool True on success, false on failure. + */ + public function chdir($dir) + { + } + /** + * Changes the file group. + * + * @since 2.7.0 + * + * @param string $file Path to the file. + * @param string|int $group A group name or number. + * @param bool $recursive Optional. If set to true, changes file group recursively. + * Default false. + * @return bool True on success, false on failure. + */ + public function chgrp($file, $group, $recursive = \false) + { + } + /** + * Changes filesystem permissions. + * + * @since 2.7.0 + * + * @param string $file Path to the file. + * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, + * 0755 for directories. Default false. + * @param bool $recursive Optional. If set to true, changes file permissions recursively. + * Default false. + * @return bool True on success, false on failure. + */ + public function chmod($file, $mode = \false, $recursive = \false) + { + } + /** + * Changes the owner of a file or directory. + * + * @since 2.7.0 + * + * @param string $file Path to the file or directory. + * @param string|int $owner A user name or number. + * @param bool $recursive Optional. If set to true, changes file owner recursively. + * Default false. + * @return bool True on success, false on failure. + */ + public function chown($file, $owner, $recursive = \false) + { + } + /** + * Gets the file owner. + * + * @since 2.7.0 + * + * @param string $file Path to the file. + * @return string|false Username of the owner on success, false on failure. + */ + public function owner($file) + { + } + /** + * Gets the permissions of the specified file or filepath in their octal format. + * + * @since 2.7.0 + * + * @param string $file Path to the file. + * @return string Mode of the file (the last 3 digits). + */ + public function getchmod($file) + { + } + /** + * Gets the file's group. + * + * @since 2.7.0 + * + * @param string $file Path to the file. + * @return string|false The group on success, false on failure. + */ + public function group($file) + { + } + /** + * Copies a file. + * + * @since 2.7.0 + * + * @param string $source Path to the source file. + * @param string $destination Path to the destination file. + * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. + * Default false. + * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, + * 0755 for dirs. Default false. + * @return bool True on success, false on failure. + */ + public function copy($source, $destination, $overwrite = \false, $mode = \false) + { + } + /** + * Moves a file. + * + * @since 2.7.0 + * + * @param string $source Path to the source file. + * @param string $destination Path to the destination file. + * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. + * Default false. + * @return bool True on success, false on failure. + */ + public function move($source, $destination, $overwrite = \false) + { + } + /** + * Deletes a file or directory. + * + * @since 2.7.0 + * + * @param string $file Path to the file or directory. + * @param bool $recursive Optional. If set to true, deletes files and folders recursively. + * Default false. + * @param string|false $type Type of resource. 'f' for file, 'd' for directory. + * Default false. + * @return bool True on success, false on failure. + */ + public function delete($file, $recursive = \false, $type = \false) + { + } + /** + * Checks if a file or directory exists. + * + * @since 2.7.0 + * + * @param string $path Path to file or directory. + * @return bool Whether $path exists or not. + */ + public function exists($path) + { + } + /** + * Checks if resource is a file. + * + * @since 2.7.0 + * + * @param string $file File path. + * @return bool Whether $file is a file. + */ + public function is_file($file) + { + } + /** + * Checks if resource is a directory. + * + * @since 2.7.0 + * + * @param string $path Directory path. + * @return bool Whether $path is a directory. + */ + public function is_dir($path) + { + } + /** + * Checks if a file is readable. + * + * @since 2.7.0 + * + * @param string $file Path to file. + * @return bool Whether $file is readable. + */ + public function is_readable($file) + { + } + /** + * Checks if a file or directory is writable. + * + * @since 2.7.0 + * + * @param string $path Path to file or directory. + * @return bool Whether $path is writable. + */ + public function is_writable($path) + { + } + /** + * Gets the file's last access time. + * + * @since 2.7.0 + * + * @param string $file Path to file. + * @return int|false Unix timestamp representing last access time, false on failure. + */ + public function atime($file) + { + } + /** + * Gets the file modification time. + * + * @since 2.7.0 + * + * @param string $file Path to file. + * @return int|false Unix timestamp representing modification time, false on failure. + */ + public function mtime($file) + { + } + /** + * Gets the file size (in bytes). + * + * @since 2.7.0 + * + * @param string $file Path to file. + * @return int|false Size of the file in bytes on success, false on failure. + */ + public function size($file) + { + } + /** + * Sets the access and modification times of a file. + * + * Note: Not implemented. + * + * @since 2.7.0 + * + * @param string $file Path to file. + * @param int $time Optional. Modified time to set for file. + * Default 0. + * @param int $atime Optional. Access time to set for file. + * Default 0. + */ + public function touch($file, $time = 0, $atime = 0) + { + } + /** + * Creates a directory. + * + * @since 2.7.0 + * + * @param string $path Path for new directory. + * @param int|false $chmod Optional. The permissions as octal number (or false to skip chmod). + * Default false. + * @param string|int|false $chown Optional. A user name or number (or false to skip chown). + * Default false. + * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp). + * Default false. + * @return bool True on success, false on failure. + */ + public function mkdir($path, $chmod = \false, $chown = \false, $chgrp = \false) + { + } + /** + * Deletes a directory. + * + * @since 2.7.0 + * + * @param string $path Path to directory. + * @param bool $recursive Optional. Whether to recursively remove files/directories. + * Default false. + * @return bool True on success, false on failure. + */ + public function rmdir($path, $recursive = \false) + { + } + /** + * Gets details for files in a directory or a specific file. + * + * @since 2.7.0 + * + * @param string $path Path to directory or file. + * @param bool $include_hidden Optional. Whether to include details of hidden ("." prefixed) files. + * Default true. + * @param bool $recursive Optional. Whether to recursively include file details in nested directories. + * Default false. + * @return array|false { + * Array of files. False if unable to list directory contents. + * + * @type string $name Name of the file or directory. + * @type string $perms *nix representation of permissions. + * @type string $permsn Octal representation of permissions. + * @type string $owner Owner name or ID. + * @type int $size Size of file in bytes. + * @type int $lastmodunix Last modified unix timestamp. + * @type mixed $lastmod Last modified month (3 letter) and day (without leading 0). + * @type int $time Last modified time. + * @type string $type Type of resource. 'f' for file, 'd' for directory. + * @type mixed $files If a directory and `$recursive` is true, contains another array of files. + * } + * @phpstan-return false|array{ + * name: string, + * perms: string, + * permsn: string, + * owner: string, + * size: int, + * lastmodunix: int, + * lastmod: mixed, + * time: int, + * type: string, + * files: mixed, + * } + */ + public function dirlist($path, $include_hidden = \true, $recursive = \false) + { + } + } + /** + * WP_Importer base class + */ + #[\AllowDynamicProperties] + class WP_Importer + { + /** + * Class Constructor + */ + public function __construct() + { + } + /** + * Returns array with imported permalinks from WordPress database + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $importer_name + * @param string $blog_id + * @return array + */ + public function get_imported_posts($importer_name, $blog_id) + { + } + /** + * Return count of imported permalinks from WordPress database + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $importer_name + * @param string $blog_id + * @return int + */ + public function count_imported_posts($importer_name, $blog_id) + { + } + /** + * Set array with imported comments from WordPress database + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $blog_id + * @return array + */ + public function get_imported_comments($blog_id) + { + } + /** + * @param int $blog_id + * @return int|void + */ + public function set_blog($blog_id) + { + } + /** + * @param int $user_id + * @return int|void + */ + public function set_user($user_id) + { + } + /** + * Sort by strlen, longest string first + * + * @param string $a + * @param string $b + * @return int + */ + public function cmpr_strlen($a, $b) + { + } + /** + * GET URL + * + * @param string $url + * @param string $username + * @param string $password + * @param bool $head + * @return array + */ + public function get_page($url, $username = '', $password = '', $head = \false) + { + } + /** + * Bump up the request timeout for http requests + * + * @param int $val + * @return int + */ + public function bump_request_timeout($val) + { + } + /** + * Check if user has exceeded disk quota + * + * @return bool + */ + public function is_user_over_quota() + { + } + /** + * Replace newlines, tabs, and multiple spaces with a single space. + * + * @param string $text + * @return string + */ + public function min_whitespace($text) + { + } + /** + * Resets global variables that grow out of control during imports. + * + * @since 3.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global int[] $wp_actions + */ + public function stop_the_insanity() + { + } + } + /** + * Administration API: WP_Internal_Pointers class + * + * @package WordPress + * @subpackage Administration + * @since 4.4.0 + */ + /** + * Core class used to implement an internal admin pointers API. + * + * @since 3.3.0 + */ + #[\AllowDynamicProperties] + final class WP_Internal_Pointers + { + /** + * Initializes the new feature pointers. + * + * @since 3.3.0 + * + * All pointers can be disabled using the following: + * remove_action( 'admin_enqueue_scripts', array( 'WP_Internal_Pointers', 'enqueue_scripts' ) ); + * + * Individual pointers (e.g. wp390_widgets) can be disabled using the following: + * + * function yourprefix_remove_pointers() { + * remove_action( + * 'admin_print_footer_scripts', + * array( 'WP_Internal_Pointers', 'pointer_wp390_widgets' ) + * ); + * } + * add_action( 'admin_enqueue_scripts', 'yourprefix_remove_pointers', 11 ); + * + * @param string $hook_suffix The current admin page. + */ + public static function enqueue_scripts($hook_suffix) + { + } + public static function pointer_wp330_toolbar() + { + } + public static function pointer_wp330_media_uploader() + { + } + public static function pointer_wp330_saving_widgets() + { + } + public static function pointer_wp340_customize_current_theme_link() + { + } + public static function pointer_wp340_choose_image_from_library() + { + } + public static function pointer_wp350_media() + { + } + public static function pointer_wp360_revisions() + { + } + public static function pointer_wp360_locks() + { + } + public static function pointer_wp390_widgets() + { + } + public static function pointer_wp410_dfw() + { + } + public static function pointer_wp496_privacy() + { + } + /** + * Prevents new users from seeing existing 'new feature' pointers. + * + * @since 3.3.0 + * + * @param int $user_id User ID. + */ + public static function dismiss_pointers_for_new_users($user_id) + { + } + } + /** + * List Table API: WP_Links_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 3.1.0 + */ + /** + * Core class used to implement displaying links in a list table. + * + * @since 3.1.0 + * + * @see WP_List_Table + */ + class WP_Links_List_Table extends \WP_List_Table + { + /** + * Constructor. + * + * @since 3.1.0 + * + * @see WP_List_Table::__construct() for more information on default arguments. + * + * @param array $args An associative array of arguments. + */ + public function __construct($args = array()) + { + } + /** + * @return bool + */ + public function ajax_user_can() + { + } + /** + * @global int $cat_id + * @global string $s + * @global string $orderby + * @global string $order + */ + public function prepare_items() + { + } + /** + */ + public function no_items() + { + } + /** + * @return array + */ + protected function get_bulk_actions() + { + } + /** + * @global int $cat_id + * @param string $which + */ + protected function extra_tablenav($which) + { + } + /** + * @return array + */ + public function get_columns() + { + } + /** + * @return array + */ + protected function get_sortable_columns() + { + } + /** + * Get the name of the default primary column. + * + * @since 4.3.0 + * + * @return string Name of the default primary column, in this case, 'name'. + */ + protected function get_default_primary_column_name() + { + } + /** + * Handles the checkbox column output. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$link` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param object $item The current link object. + */ + public function column_cb($item) + { + } + /** + * Handles the link name column output. + * + * @since 4.3.0 + * + * @param object $link The current link object. + */ + public function column_name($link) + { + } + /** + * Handles the link URL column output. + * + * @since 4.3.0 + * + * @param object $link The current link object. + */ + public function column_url($link) + { + } + /** + * Handles the link categories column output. + * + * @since 4.3.0 + * + * @global int $cat_id + * + * @param object $link The current link object. + */ + public function column_categories($link) + { + } + /** + * Handles the link relation column output. + * + * @since 4.3.0 + * + * @param object $link The current link object. + */ + public function column_rel($link) + { + } + /** + * Handles the link visibility column output. + * + * @since 4.3.0 + * + * @param object $link The current link object. + */ + public function column_visible($link) + { + } + /** + * Handles the link rating column output. + * + * @since 4.3.0 + * + * @param object $link The current link object. + */ + public function column_rating($link) + { + } + /** + * Handles the default column output. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$link` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param object $item Link object. + * @param string $column_name Current column name. + */ + public function column_default($item, $column_name) + { + } + public function display_rows() + { + } + /** + * Generates and displays row action links. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$link` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param object $item Link being acted upon. + * @param string $column_name Current column name. + * @param string $primary Primary column name. + * @return string Row actions output for links, or an empty string + * if the current column is not the primary column. + */ + protected function handle_row_actions($item, $column_name, $primary) + { + } + } + /** + * Helper functions for displaying a list of items in an ajaxified HTML table. + * + * @package WordPress + * @subpackage List_Table + * @since 4.7.0 + */ + /** + * Helper class to be used only by back compat functions. + * + * @since 3.1.0 + */ + class _WP_List_Table_Compat extends \WP_List_Table + { + public $_screen; + public $_columns; + /** + * Constructor. + * + * @since 3.1.0 + * + * @param string|WP_Screen $screen The screen hook name or screen object. + * @param string[] $columns An array of columns with column IDs as the keys + * and translated column names as the values. + */ + public function __construct($screen, $columns = array()) + { + } + /** + * Gets a list of all, hidden, and sortable columns. + * + * @since 3.1.0 + * + * @return array + */ + protected function get_column_info() + { + } + /** + * Gets a list of columns. + * + * @since 3.1.0 + * + * @return array + */ + public function get_columns() + { + } + } + /** + * List Table API: WP_Media_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 3.1.0 + */ + /** + * Core class used to implement displaying media items in a list table. + * + * @since 3.1.0 + * + * @see WP_List_Table + */ + class WP_Media_List_Table extends \WP_List_Table + { + /** + * Holds the number of pending comments for each post. + * + * @since 4.4.0 + * @var array + */ + protected $comment_pending_count = array(); + /** + * Constructor. + * + * @since 3.1.0 + * + * @see WP_List_Table::__construct() for more information on default arguments. + * + * @param array $args An associative array of arguments. + */ + public function __construct($args = array()) + { + } + /** + * @return bool + */ + public function ajax_user_can() + { + } + /** + * @global string $mode List table view mode. + * @global WP_Query $wp_query WordPress Query object. + * @global array $post_mime_types + * @global array $avail_post_mime_types + */ + public function prepare_items() + { + } + /** + * @global array $post_mime_types + * @global array $avail_post_mime_types + * @return array + */ + protected function get_views() + { + } + /** + * @return array + */ + protected function get_bulk_actions() + { + } + /** + * @param string $which + */ + protected function extra_tablenav($which) + { + } + /** + * @return string + */ + public function current_action() + { + } + /** + * @return bool + */ + public function has_items() + { + } + /** + */ + public function no_items() + { + } + /** + * Override parent views so we can use the filter bar display. + * + * @global string $mode List table view mode. + */ + public function views() + { + } + /** + * @return array + */ + public function get_columns() + { + } + /** + * @return array + */ + protected function get_sortable_columns() + { + } + /** + * Handles the checkbox column output. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Post $item The current WP_Post object. + */ + public function column_cb($item) + { + } + /** + * Handles the title column output. + * + * @since 4.3.0 + * + * @param WP_Post $post The current WP_Post object. + */ + public function column_title($post) + { + } + /** + * Handles the author column output. + * + * @since 4.3.0 + * + * @param WP_Post $post The current WP_Post object. + */ + public function column_author($post) + { + } + /** + * Handles the description column output. + * + * @since 4.3.0 + * + * @param WP_Post $post The current WP_Post object. + */ + public function column_desc($post) + { + } + /** + * Handles the date column output. + * + * @since 4.3.0 + * + * @param WP_Post $post The current WP_Post object. + */ + public function column_date($post) + { + } + /** + * Handles the parent column output. + * + * @since 4.3.0 + * + * @param WP_Post $post The current WP_Post object. + */ + public function column_parent($post) + { + } + /** + * Handles the comments column output. + * + * @since 4.3.0 + * + * @param WP_Post $post The current WP_Post object. + */ + public function column_comments($post) + { + } + /** + * Handles output for the default column. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Post $item The current WP_Post object. + * @param string $column_name Current column name. + */ + public function column_default($item, $column_name) + { + } + /** + * @global WP_Post $post Global post object. + */ + public function display_rows() + { + } + /** + * Gets the name of the default primary column. + * + * @since 4.3.0 + * + * @return string Name of the default primary column, in this case, 'title'. + */ + protected function get_default_primary_column_name() + { + } + /** + * Generates and displays row action links. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Post $item Attachment being acted upon. + * @param string $column_name Current column name. + * @param string $primary Primary column name. + * @return string Row actions output for media attachments, or an empty string + * if the current column is not the primary column. + */ + protected function handle_row_actions($item, $column_name, $primary) + { + } + } + /** + * List Table API: WP_MS_Sites_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 3.1.0 + */ + /** + * Core class used to implement displaying sites in a list table for the network admin. + * + * @since 3.1.0 + * + * @see WP_List_Table + */ + class WP_MS_Sites_List_Table extends \WP_List_Table + { + /** + * Site status list. + * + * @since 4.3.0 + * @var array + */ + public $status_list; + /** + * Constructor. + * + * @since 3.1.0 + * + * @see WP_List_Table::__construct() for more information on default arguments. + * + * @param array $args An associative array of arguments. + */ + public function __construct($args = array()) + { + } + /** + * @return bool + */ + public function ajax_user_can() + { + } + /** + * Prepares the list of sites for display. + * + * @since 3.1.0 + * + * @global string $mode List table view mode. + * @global string $s + * @global wpdb $wpdb WordPress database abstraction object. + */ + public function prepare_items() + { + } + /** + */ + public function no_items() + { + } + /** + * Gets links to filter sites by status. + * + * @since 5.3.0 + * + * @return array + */ + protected function get_views() + { + } + /** + * @return array + */ + protected function get_bulk_actions() + { + } + /** + * @global string $mode List table view mode. + * + * @param string $which The location of the pagination nav markup: 'top' or 'bottom'. + */ + protected function pagination($which) + { + } + /** + * Extra controls to be displayed between bulk actions and pagination. + * + * @since 5.3.0 + * + * @param string $which The location of the extra table nav markup: 'top' or 'bottom'. + */ + protected function extra_tablenav($which) + { + } + /** + * @return array + */ + public function get_columns() + { + } + /** + * @return array + */ + protected function get_sortable_columns() + { + } + /** + * Handles the checkbox column output. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$blog` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param array $item Current site. + */ + public function column_cb($item) + { + } + /** + * Handles the ID column output. + * + * @since 4.4.0 + * + * @param array $blog Current site. + */ + public function column_id($blog) + { + } + /** + * Handles the site name column output. + * + * @since 4.3.0 + * + * @global string $mode List table view mode. + * + * @param array $blog Current site. + */ + public function column_blogname($blog) + { + } + /** + * Handles the lastupdated column output. + * + * @since 4.3.0 + * + * @global string $mode List table view mode. + * + * @param array $blog Current site. + */ + public function column_lastupdated($blog) + { + } + /** + * Handles the registered column output. + * + * @since 4.3.0 + * + * @global string $mode List table view mode. + * + * @param array $blog Current site. + */ + public function column_registered($blog) + { + } + /** + * Handles the users column output. + * + * @since 4.3.0 + * + * @param array $blog Current site. + */ + public function column_users($blog) + { + } + /** + * Handles the plugins column output. + * + * @since 4.3.0 + * + * @param array $blog Current site. + */ + public function column_plugins($blog) + { + } + /** + * Handles output for the default column. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$blog` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param array $item Current site. + * @param string $column_name Current column name. + */ + public function column_default($item, $column_name) + { + } + /** + * @global string $mode List table view mode. + */ + public function display_rows() + { + } + /** + * Maybe output comma-separated site states. + * + * @since 5.3.0 + * + * @param array $site + */ + protected function site_states($site) + { + } + /** + * Gets the name of the default primary column. + * + * @since 4.3.0 + * + * @return string Name of the default primary column, in this case, 'blogname'. + */ + protected function get_default_primary_column_name() + { + } + /** + * Generates and displays row action links. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$blog` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param array $item Site being acted upon. + * @param string $column_name Current column name. + * @param string $primary Primary column name. + * @return string Row actions output for sites in Multisite, or an empty string + * if the current column is not the primary column. + */ + protected function handle_row_actions($item, $column_name, $primary) + { + } + } + /** + * List Table API: WP_MS_Themes_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 3.1.0 + */ + /** + * Core class used to implement displaying themes in a list table for the network admin. + * + * @since 3.1.0 + * + * @see WP_List_Table + */ + class WP_MS_Themes_List_Table extends \WP_List_Table + { + public $site_id; + public $is_site_themes; + /** + * Whether to show the auto-updates UI. + * + * @since 5.5.0 + * + * @var bool True if auto-updates UI is to be shown, false otherwise. + */ + protected $show_autoupdates = \true; + /** + * Constructor. + * + * @since 3.1.0 + * + * @see WP_List_Table::__construct() for more information on default arguments. + * + * @global string $status + * @global int $page + * + * @param array $args An associative array of arguments. + */ + public function __construct($args = array()) + { + } + /** + * @return array + */ + protected function get_table_classes() + { + } + /** + * @return bool + */ + public function ajax_user_can() + { + } + /** + * @global string $status + * @global array $totals + * @global int $page + * @global string $orderby + * @global string $order + * @global string $s + */ + public function prepare_items() + { + } + /** + * @param WP_Theme $theme + * @return bool + */ + public function _search_callback($theme) + { + } + // Not used by any core columns. + /** + * @global string $orderby + * @global string $order + * @param array $theme_a + * @param array $theme_b + * @return int + */ + public function _order_callback($theme_a, $theme_b) + { + } + /** + */ + public function no_items() + { + } + /** + * @return array + */ + public function get_columns() + { + } + /** + * @return array + */ + protected function get_sortable_columns() + { + } + /** + * Gets the name of the primary column. + * + * @since 4.3.0 + * + * @return string Unalterable name of the primary column name, in this case, 'name'. + */ + protected function get_primary_column_name() + { + } + /** + * @global array $totals + * @global string $status + * @return array + */ + protected function get_views() + { + } + /** + * @global string $status + * + * @return array + */ + protected function get_bulk_actions() + { + } + /** + */ + public function display_rows() + { + } + /** + * Handles the checkbox column output. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$theme` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Theme $item The current WP_Theme object. + */ + public function column_cb($item) + { + } + /** + * Handles the name column output. + * + * @since 4.3.0 + * + * @global string $status + * @global int $page + * @global string $s + * + * @param WP_Theme $theme The current WP_Theme object. + */ + public function column_name($theme) + { + } + /** + * Handles the description column output. + * + * @since 4.3.0 + * + * @global string $status + * @global array $totals + * + * @param WP_Theme $theme The current WP_Theme object. + */ + public function column_description($theme) + { + } + /** + * Handles the auto-updates column output. + * + * @since 5.5.0 + * + * @global string $status + * @global int $page + * + * @param WP_Theme $theme The current WP_Theme object. + */ + public function column_autoupdates($theme) + { + } + /** + * Handles default column output. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$theme` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Theme $item The current WP_Theme object. + * @param string $column_name The current column name. + */ + public function column_default($item, $column_name) + { + } + /** + * Handles the output for a single table row. + * + * @since 4.3.0 + * + * @param WP_Theme $item The current WP_Theme object. + */ + public function single_row_columns($item) + { + } + /** + * @global string $status + * @global array $totals + * + * @param WP_Theme $theme + */ + public function single_row($theme) + { + } + } + /** + * List Table API: WP_MS_Users_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 3.1.0 + */ + /** + * Core class used to implement displaying users in a list table for the network admin. + * + * @since 3.1.0 + * + * @see WP_List_Table + */ + class WP_MS_Users_List_Table extends \WP_List_Table + { + /** + * @return bool + */ + public function ajax_user_can() + { + } + /** + * @global string $mode List table view mode. + * @global string $usersearch + * @global string $role + */ + public function prepare_items() + { + } + /** + * @return array + */ + protected function get_bulk_actions() + { + } + /** + */ + public function no_items() + { + } + /** + * @global string $role + * @return array + */ + protected function get_views() + { + } + /** + * @global string $mode List table view mode. + * + * @param string $which + */ + protected function pagination($which) + { + } + /** + * @return array + */ + public function get_columns() + { + } + /** + * @return array + */ + protected function get_sortable_columns() + { + } + /** + * Handles the checkbox column output. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$user` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_User $item The current WP_User object. + */ + public function column_cb($item) + { + } + /** + * Handles the ID column output. + * + * @since 4.4.0 + * + * @param WP_User $user The current WP_User object. + */ + public function column_id($user) + { + } + /** + * Handles the username column output. + * + * @since 4.3.0 + * + * @param WP_User $user The current WP_User object. + */ + public function column_username($user) + { + } + /** + * Handles the name column output. + * + * @since 4.3.0 + * + * @param WP_User $user The current WP_User object. + */ + public function column_name($user) + { + } + /** + * Handles the email column output. + * + * @since 4.3.0 + * + * @param WP_User $user The current WP_User object. + */ + public function column_email($user) + { + } + /** + * Handles the registered date column output. + * + * @since 4.3.0 + * + * @global string $mode List table view mode. + * + * @param WP_User $user The current WP_User object. + */ + public function column_registered($user) + { + } + /** + * @since 4.3.0 + * + * @param WP_User $user + * @param string $classes + * @param string $data + * @param string $primary + */ + protected function _column_blogs($user, $classes, $data, $primary) + { + } + /** + * Handles the sites column output. + * + * @since 4.3.0 + * + * @param WP_User $user The current WP_User object. + */ + public function column_blogs($user) + { + } + /** + * Handles the default column output. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$user` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_User $item The current WP_User object. + * @param string $column_name The current column name. + */ + public function column_default($item, $column_name) + { + } + public function display_rows() + { + } + /** + * Gets the name of the default primary column. + * + * @since 4.3.0 + * + * @return string Name of the default primary column, in this case, 'username'. + */ + protected function get_default_primary_column_name() + { + } + /** + * Generates and displays row action links. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$user` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_User $item User being acted upon. + * @param string $column_name Current column name. + * @param string $primary Primary column name. + * @return string Row actions output for users in Multisite, or an empty string + * if the current column is not the primary column. + */ + protected function handle_row_actions($item, $column_name, $primary) + { + } + } + /** + * List Table API: WP_Plugin_Install_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 3.1.0 + */ + /** + * Core class used to implement displaying plugins to install in a list table. + * + * @since 3.1.0 + * + * @see WP_List_Table + */ + class WP_Plugin_Install_List_Table extends \WP_List_Table + { + public $order = 'ASC'; + public $orderby = \null; + public $groups = array(); + /** + * @return bool + */ + public function ajax_user_can() + { + } + /** + * Return the list of known plugins. + * + * Uses the transient data from the updates API to determine the known + * installed plugins. + * + * @since 4.9.0 + * @access protected + * + * @return array + */ + protected function get_installed_plugins() + { + } + /** + * Returns a list of slugs of installed plugins, if known. + * + * Uses the transient data from the updates API to determine the slugs of + * known installed plugins. This might be better elsewhere, perhaps even + * within get_plugins(). + * + * @since 4.0.0 + * + * @return array + */ + protected function get_installed_plugin_slugs() + { + } + /** + * @global array $tabs + * @global string $tab + * @global int $paged + * @global string $type + * @global string $term + */ + public function prepare_items() + { + } + /** + */ + public function no_items() + { + } + /** + * @global array $tabs + * @global string $tab + * + * @return array + */ + protected function get_views() + { + } + /** + * Overrides parent views so we can use the filter bar display. + */ + public function views() + { + } + /** + * Displays the plugin install table. + * + * Overrides the parent display() method to provide a different container. + * + * @since 4.0.0 + */ + public function display() + { + } + /** + * @global string $tab + * + * @param string $which + */ + protected function display_tablenav($which) + { + } + /** + * @return array + */ + protected function get_table_classes() + { + } + /** + * @return array + */ + public function get_columns() + { + } + public function display_rows() + { + } + } + /** + * List Table API: WP_Plugins_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 3.1.0 + */ + /** + * Core class used to implement displaying installed plugins in a list table. + * + * @since 3.1.0 + * + * @see WP_List_Table + */ + class WP_Plugins_List_Table extends \WP_List_Table + { + /** + * Whether to show the auto-updates UI. + * + * @since 5.5.0 + * + * @var bool True if auto-updates UI is to be shown, false otherwise. + */ + protected $show_autoupdates = \true; + /** + * Constructor. + * + * @since 3.1.0 + * + * @see WP_List_Table::__construct() for more information on default arguments. + * + * @global string $status + * @global int $page + * + * @param array $args An associative array of arguments. + */ + public function __construct($args = array()) + { + } + /** + * @return array + */ + protected function get_table_classes() + { + } + /** + * @return bool + */ + public function ajax_user_can() + { + } + /** + * @global string $status + * @global array $plugins + * @global array $totals + * @global int $page + * @global string $orderby + * @global string $order + * @global string $s + */ + public function prepare_items() + { + } + /** + * @global string $s URL encoded search term. + * + * @param array $plugin + * @return bool + */ + public function _search_callback($plugin) + { + } + /** + * @global string $orderby + * @global string $order + * @param array $plugin_a + * @param array $plugin_b + * @return int + */ + public function _order_callback($plugin_a, $plugin_b) + { + } + /** + * @global array $plugins + */ + public function no_items() + { + } + /** + * Displays the search box. + * + * @since 4.6.0 + * + * @param string $text The 'submit' button label. + * @param string $input_id ID attribute value for the search input field. + */ + public function search_box($text, $input_id) + { + } + /** + * @global string $status + * @return array + */ + public function get_columns() + { + } + /** + * @return array + */ + protected function get_sortable_columns() + { + } + /** + * @global array $totals + * @global string $status + * @return array + */ + protected function get_views() + { + } + /** + * @global string $status + * @return array + */ + protected function get_bulk_actions() + { + } + /** + * @global string $status + * @param string $which + */ + public function bulk_actions($which = '') + { + } + /** + * @global string $status + * @param string $which + */ + protected function extra_tablenav($which) + { + } + /** + * @return string + */ + public function current_action() + { + } + /** + * @global string $status + */ + public function display_rows() + { + } + /** + * @global string $status + * @global int $page + * @global string $s + * @global array $totals + * + * @param array $item + */ + public function single_row($item) + { + } + /** + * Gets the name of the primary column for this specific list table. + * + * @since 4.3.0 + * + * @return string Unalterable name for the primary column, in this case, 'name'. + */ + protected function get_primary_column_name() + { + } + } + /** + * List Table API: WP_Post_Comments_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 4.4.0 + */ + /** + * Core class used to implement displaying post comments in a list table. + * + * @since 3.1.0 + * + * @see WP_Comments_List_Table + */ + class WP_Post_Comments_List_Table extends \WP_Comments_List_Table + { + /** + * @return array + */ + protected function get_column_info() + { + } + /** + * @return array + */ + protected function get_table_classes() + { + } + /** + * @param bool $output_empty + */ + public function display($output_empty = \false) + { + } + /** + * @param bool $comment_status + * @return int + */ + public function get_per_page($comment_status = \false) + { + } + } + /** + * List Table API: WP_Posts_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 3.1.0 + */ + /** + * Core class used to implement displaying posts in a list table. + * + * @since 3.1.0 + * + * @see WP_List_Table + */ + class WP_Posts_List_Table extends \WP_List_Table + { + /** + * Whether the items should be displayed hierarchically or linearly. + * + * @since 3.1.0 + * @var bool + */ + protected $hierarchical_display; + /** + * Holds the number of pending comments for each post. + * + * @since 3.1.0 + * @var array + */ + protected $comment_pending_count; + /** + * Current level for output. + * + * @since 4.3.0 + * @var int + */ + protected $current_level = 0; + /** + * Constructor. + * + * @since 3.1.0 + * + * @see WP_List_Table::__construct() for more information on default arguments. + * + * @global WP_Post_Type $post_type_object + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $args An associative array of arguments. + */ + public function __construct($args = array()) + { + } + /** + * Sets whether the table layout should be hierarchical or not. + * + * @since 4.2.0 + * + * @param bool $display Whether the table layout should be hierarchical. + */ + public function set_hierarchical_display($display) + { + } + /** + * @return bool + */ + public function ajax_user_can() + { + } + /** + * @global string $mode List table view mode. + * @global array $avail_post_stati + * @global WP_Query $wp_query WordPress Query object. + * @global int $per_page + */ + public function prepare_items() + { + } + /** + * @return bool + */ + public function has_items() + { + } + /** + */ + public function no_items() + { + } + /** + * Determine if the current view is the "All" view. + * + * @since 4.2.0 + * + * @return bool Whether the current view is the "All" view. + */ + protected function is_base_request() + { + } + /** + * Helper to create links to edit.php with params. + * + * @since 4.4.0 + * + * @param string[] $args Associative array of URL parameters for the link. + * @param string $link_text Link text. + * @param string $css_class Optional. Class attribute. Default empty string. + * @return string The formatted link string. + */ + protected function get_edit_link($args, $link_text, $css_class = '') + { + } + /** + * @global array $locked_post_status This seems to be deprecated. + * @global array $avail_post_stati + * @return array + */ + protected function get_views() + { + } + /** + * @return array + */ + protected function get_bulk_actions() + { + } + /** + * Displays a categories drop-down for filtering on the Posts list table. + * + * @since 4.6.0 + * + * @global int $cat Currently selected category. + * + * @param string $post_type Post type slug. + */ + protected function categories_dropdown($post_type) + { + } + /** + * Displays a formats drop-down for filtering items. + * + * @since 5.2.0 + * @access protected + * + * @param string $post_type Post type slug. + */ + protected function formats_dropdown($post_type) + { + } + /** + * @param string $which + */ + protected function extra_tablenav($which) + { + } + /** + * @return string + */ + public function current_action() + { + } + /** + * @global string $mode List table view mode. + * + * @return array + */ + protected function get_table_classes() + { + } + /** + * @return array + */ + public function get_columns() + { + } + /** + * @return array + */ + protected function get_sortable_columns() + { + } + /** + * @global WP_Query $wp_query WordPress Query object. + * @global int $per_page + * @param array $posts + * @param int $level + */ + public function display_rows($posts = array(), $level = 0) + { + } + /** + * Handles the checkbox column output. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Post $item The current WP_Post object. + */ + public function column_cb($item) + { + } + /** + * @since 4.3.0 + * + * @param WP_Post $post + * @param string $classes + * @param string $data + * @param string $primary + */ + protected function _column_title($post, $classes, $data, $primary) + { + } + /** + * Handles the title column output. + * + * @since 4.3.0 + * + * @global string $mode List table view mode. + * + * @param WP_Post $post The current WP_Post object. + */ + public function column_title($post) + { + } + /** + * Handles the post date column output. + * + * @since 4.3.0 + * + * @global string $mode List table view mode. + * + * @param WP_Post $post The current WP_Post object. + */ + public function column_date($post) + { + } + /** + * Handles the comments column output. + * + * @since 4.3.0 + * + * @param WP_Post $post The current WP_Post object. + */ + public function column_comments($post) + { + } + /** + * Handles the post author column output. + * + * @since 4.3.0 + * + * @param WP_Post $post The current WP_Post object. + */ + public function column_author($post) + { + } + /** + * Handles the default column output. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Post $item The current WP_Post object. + * @param string $column_name The current column name. + */ + public function column_default($item, $column_name) + { + } + /** + * @global WP_Post $post Global post object. + * + * @param int|WP_Post $post + * @param int $level + */ + public function single_row($post, $level = 0) + { + } + /** + * Gets the name of the default primary column. + * + * @since 4.3.0 + * + * @return string Name of the default primary column, in this case, 'title'. + */ + protected function get_default_primary_column_name() + { + } + /** + * Generates and displays row action links. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Post $item Post being acted upon. + * @param string $column_name Current column name. + * @param string $primary Primary column name. + * @return string Row actions output for posts, or an empty string + * if the current column is not the primary column. + */ + protected function handle_row_actions($item, $column_name, $primary) + { + } + /** + * Outputs the hidden row displayed when inline editing + * + * @since 3.1.0 + * + * @global string $mode List table view mode. + */ + public function inline_edit() + { + } + } + /** + * List Table API: WP_Privacy_Requests_Table class + * + * @package WordPress + * @subpackage Administration + * @since 4.9.6 + */ + abstract class WP_Privacy_Requests_Table extends \WP_List_Table + { + /** + * Action name for the requests this table will work with. Classes + * which inherit from WP_Privacy_Requests_Table should define this. + * + * Example: 'export_personal_data'. + * + * @since 4.9.6 + * + * @var string $request_type Name of action. + */ + protected $request_type = 'INVALID'; + /** + * Post type to be used. + * + * @since 4.9.6 + * + * @var string $post_type The post type. + */ + protected $post_type = 'INVALID'; + /** + * Get columns to show in the list table. + * + * @since 4.9.6 + * + * @return string[] Array of column titles keyed by their column name. + */ + public function get_columns() + { + } + /** + * Normalize the admin URL to the current page (by request_type). + * + * @since 5.3.0 + * + * @return string URL to the current admin page. + */ + protected function get_admin_url() + { + } + /** + * Get a list of sortable columns. + * + * @since 4.9.6 + * + * @return array Default sortable columns. + */ + protected function get_sortable_columns() + { + } + /** + * Default primary column. + * + * @since 4.9.6 + * + * @return string Default primary column name. + */ + protected function get_default_primary_column_name() + { + } + /** + * Count number of requests for each status. + * + * @since 4.9.6 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return object Number of posts for each status. + */ + protected function get_request_counts() + { + } + /** + * Get an associative array ( id => link ) with the list of views available on this table. + * + * @since 4.9.6 + * + * @return string[] An array of HTML links keyed by their view. + */ + protected function get_views() + { + } + /** + * Get bulk actions. + * + * @since 4.9.6 + * + * @return array Array of bulk action labels keyed by their action. + */ + protected function get_bulk_actions() + { + } + /** + * Process bulk actions. + * + * @since 4.9.6 + * @since 5.6.0 Added support for the `complete` action. + */ + public function process_bulk_action() + { + } + /** + * Prepare items to output. + * + * @since 4.9.6 + * @since 5.1.0 Added support for column sorting. + */ + public function prepare_items() + { + } + /** + * Checkbox column. + * + * @since 4.9.6 + * + * @param WP_User_Request $item Item being shown. + * @return string Checkbox column markup. + */ + public function column_cb($item) + { + } + /** + * Status column. + * + * @since 4.9.6 + * + * @param WP_User_Request $item Item being shown. + * @return string Status column markup. + */ + public function column_status($item) + { + } + /** + * Convert timestamp for display. + * + * @since 4.9.6 + * + * @param int $timestamp Event timestamp. + * @return string Human readable date. + */ + protected function get_timestamp_as_date($timestamp) + { + } + /** + * Default column handler. + * + * @since 4.9.6 + * @since 5.7.0 Added `manage_{$this->screen->id}_custom_column` action. + * + * @param WP_User_Request $item Item being shown. + * @param string $column_name Name of column being shown. + */ + public function column_default($item, $column_name) + { + } + /** + * Created timestamp column. Overridden by children. + * + * @since 5.7.0 + * + * @param WP_User_Request $item Item being shown. + * @return string Human readable date. + */ + public function column_created_timestamp($item) + { + } + /** + * Actions column. Overridden by children. + * + * @since 4.9.6 + * + * @param WP_User_Request $item Item being shown. + * @return string Email column markup. + */ + public function column_email($item) + { + } + /** + * Next steps column. Overridden by children. + * + * @since 4.9.6 + * + * @param WP_User_Request $item Item being shown. + */ + public function column_next_steps($item) + { + } + /** + * Generates content for a single row of the table, + * + * @since 4.9.6 + * + * @param WP_User_Request $item The current item. + */ + public function single_row($item) + { + } + /** + * Embed scripts used to perform actions. Overridden by children. + * + * @since 4.9.6 + */ + public function embed_scripts() + { + } + } + /** + * WP_Privacy_Data_Export_Requests_Table class. + * + * @since 4.9.6 + */ + class WP_Privacy_Data_Export_Requests_List_Table extends \WP_Privacy_Requests_Table + { + /** + * Action name for the requests this table will work with. + * + * @since 4.9.6 + * + * @var string $request_type Name of action. + */ + protected $request_type = 'export_personal_data'; + /** + * Post type for the requests. + * + * @since 4.9.6 + * + * @var string $post_type The post type. + */ + protected $post_type = 'user_request'; + /** + * Actions column. + * + * @since 4.9.6 + * + * @param WP_User_Request $item Item being shown. + * @return string Email column markup. + */ + public function column_email($item) + { + } + /** + * Displays the next steps column. + * + * @since 4.9.6 + * + * @param WP_User_Request $item Item being shown. + */ + public function column_next_steps($item) + { + } + } + /** + * WP_Privacy_Data_Removal_Requests_List_Table class. + * + * @since 4.9.6 + */ + class WP_Privacy_Data_Removal_Requests_List_Table extends \WP_Privacy_Requests_Table + { + /** + * Action name for the requests this table will work with. + * + * @since 4.9.6 + * + * @var string $request_type Name of action. + */ + protected $request_type = 'remove_personal_data'; + /** + * Post type for the requests. + * + * @since 4.9.6 + * + * @var string $post_type The post type. + */ + protected $post_type = 'user_request'; + /** + * Actions column. + * + * @since 4.9.6 + * + * @param WP_User_Request $item Item being shown. + * @return string Email column markup. + */ + public function column_email($item) + { + } + /** + * Next steps column. + * + * @since 4.9.6 + * + * @param WP_User_Request $item Item being shown. + */ + public function column_next_steps($item) + { + } + } + /** + * WP_Privacy_Policy_Content class. + * + * @package WordPress + * @subpackage Administration + * @since 4.9.6 + */ + #[\AllowDynamicProperties] + final class WP_Privacy_Policy_Content + { + /** + * Add content to the postbox shown when editing the privacy policy. + * + * Plugins and themes should suggest text for inclusion in the site's privacy policy. + * The suggested text should contain information about any functionality that affects user privacy, + * and will be shown in the Suggested Privacy Policy Content postbox. + * + * Intended for use from `wp_add_privacy_policy_content()`. + * + * @since 4.9.6 + * + * @param string $plugin_name The name of the plugin or theme that is suggesting content for the site's privacy policy. + * @param string $policy_text The suggested content for inclusion in the policy. + */ + public static function add($plugin_name, $policy_text) + { + } + /** + * Quick check if any privacy info has changed. + * + * @since 4.9.6 + */ + public static function text_change_check() + { + } + /** + * Output a warning when some privacy info has changed. + * + * @since 4.9.6 + * + * @global WP_Post $post Global post object. + */ + public static function policy_text_changed_notice() + { + } + /** + * Update the cached policy info when the policy page is updated. + * + * @since 4.9.6 + * @access private + * + * @param int $post_id The ID of the updated post. + */ + public static function _policy_page_updated($post_id) + { + } + /** + * Check for updated, added or removed privacy policy information from plugins. + * + * Caches the current info in post_meta of the policy page. + * + * @since 4.9.6 + * + * @return array The privacy policy text/information added by core and plugins. + */ + public static function get_suggested_policy_text() + { + } + /** + * Add a notice with a link to the guide when editing the privacy policy page. + * + * @since 4.9.6 + * @since 5.0.0 The `$post` parameter was made optional. + * + * @global WP_Post $post Global post object. + * + * @param WP_Post|null $post The currently edited post. Default null. + */ + public static function notice($post = \null) + { + } + /** + * Output the privacy policy guide together with content from the theme and plugins. + * + * @since 4.9.6 + */ + public static function privacy_policy_guide() + { + } + /** + * Return the default suggested privacy policy content. + * + * @since 4.9.6 + * @since 5.0.0 Added the `$blocks` parameter. + * + * @param bool $description Whether to include the descriptions under the section headings. Default false. + * @param bool $blocks Whether to format the content for the block editor. Default true. + * @return string The default policy content. + */ + public static function get_default_content($description = \false, $blocks = \true) + { + } + /** + * Add the suggested privacy policy text to the policy postbox. + * + * @since 4.9.6 + */ + public static function add_suggested_content() + { + } + } + /** + * Screen API: WP_Screen class + * + * @package WordPress + * @subpackage Administration + * @since 4.4.0 + */ + /** + * Core class used to implement an admin screen API. + * + * @since 3.3.0 + */ + #[\AllowDynamicProperties] + final class WP_Screen + { + /** + * Any action associated with the screen. + * + * 'add' for *-add.php and *-new.php screens. Empty otherwise. + * + * @since 3.3.0 + * @var string + */ + public $action; + /** + * The base type of the screen. + * + * This is typically the same as `$id` but with any post types and taxonomies stripped. + * For example, for an `$id` of 'edit-post' the base is 'edit'. + * + * @since 3.3.0 + * @var string + */ + public $base; + /** + * The unique ID of the screen. + * + * @since 3.3.0 + * @var string + */ + public $id; + /** + * Whether the screen is in the network admin. + * + * Deprecated. Use in_admin() instead. + * + * @since 3.3.0 + * @deprecated 3.5.0 + * @var bool + */ + public $is_network; + /** + * Whether the screen is in the user admin. + * + * Deprecated. Use in_admin() instead. + * + * @since 3.3.0 + * @deprecated 3.5.0 + * @var bool + */ + public $is_user; + /** + * The base menu parent. + * + * This is derived from `$parent_file` by removing the query string and any .php extension. + * `$parent_file` values of 'edit.php?post_type=page' and 'edit.php?post_type=post' + * have a `$parent_base` of 'edit'. + * + * @since 3.3.0 + * @var string + */ + public $parent_base; + /** + * The parent_file for the screen per the admin menu system. + * + * Some `$parent_file` values are 'edit.php?post_type=page', 'edit.php', and 'options-general.php'. + * + * @since 3.3.0 + * @var string + */ + public $parent_file; + /** + * The post type associated with the screen, if any. + * + * The 'edit.php?post_type=page' screen has a post type of 'page'. + * The 'edit-tags.php?taxonomy=$taxonomy&post_type=page' screen has a post type of 'page'. + * + * @since 3.3.0 + * @var string + */ + public $post_type; + /** + * The taxonomy associated with the screen, if any. + * + * The 'edit-tags.php?taxonomy=category' screen has a taxonomy of 'category'. + * + * @since 3.3.0 + * @var string + */ + public $taxonomy; + /** + * Whether the screen is using the block editor. + * + * @since 5.0.0 + * @var bool + */ + public $is_block_editor = \false; + /** + * Fetches a screen object. + * + * @since 3.3.0 + * + * @global string $hook_suffix + * + * @param string|WP_Screen $hook_name Optional. The hook name (also known as the hook suffix) used to determine the screen. + * Defaults to the current $hook_suffix global. + * @return WP_Screen Screen object. + */ + public static function get($hook_name = '') + { + } + /** + * Makes the screen object the current screen. + * + * @see set_current_screen() + * @since 3.3.0 + * + * @global WP_Screen $current_screen WordPress current screen object. + * @global string $typenow The post type of the current screen. + * @global string $taxnow The taxonomy of the current screen. + */ + public function set_current_screen() + { + } + /** + * Indicates whether the screen is in a particular admin. + * + * @since 3.5.0 + * + * @param string $admin The admin to check against (network | user | site). + * If empty any of the three admins will result in true. + * @return bool True if the screen is in the indicated admin, false otherwise. + */ + public function in_admin($admin = \null) + { + } + /** + * Sets or returns whether the block editor is loading on the current screen. + * + * @since 5.0.0 + * + * @param bool $set Optional. Sets whether the block editor is loading on the current screen or not. + * @return bool True if the block editor is being loaded, false otherwise. + */ + public function is_block_editor($set = \null) + { + } + /** + * Sets the old string-based contextual help for the screen for backward compatibility. + * + * @since 3.3.0 + * + * @param WP_Screen $screen A screen object. + * @param string $help Help text. + */ + public static function add_old_compat_help($screen, $help) + { + } + /** + * Sets the parent information for the screen. + * + * This is called in admin-header.php after the menu parent for the screen has been determined. + * + * @since 3.3.0 + * + * @param string $parent_file The parent file of the screen. Typically the $parent_file global. + */ + public function set_parentage($parent_file) + { + } + /** + * Adds an option for the screen. + * + * Call this in template files after admin.php is loaded and before admin-header.php is loaded + * to add screen options. + * + * @since 3.3.0 + * + * @param string $option Option ID. + * @param mixed $args Option-dependent arguments. + */ + public function add_option($option, $args = array()) + { + } + /** + * Removes an option from the screen. + * + * @since 3.8.0 + * + * @param string $option Option ID. + */ + public function remove_option($option) + { + } + /** + * Removes all options from the screen. + * + * @since 3.8.0 + */ + public function remove_options() + { + } + /** + * Gets the options registered for the screen. + * + * @since 3.8.0 + * + * @return array Options with arguments. + */ + public function get_options() + { + } + /** + * Gets the arguments for an option for the screen. + * + * @since 3.3.0 + * + * @param string $option Option name. + * @param string|false $key Optional. Specific array key for when the option is an array. + * Default false. + * @return string The option value if set, null otherwise. + */ + public function get_option($option, $key = \false) + { + } + /** + * Gets the help tabs registered for the screen. + * + * @since 3.4.0 + * @since 4.4.0 Help tabs are ordered by their priority. + * + * @return array Help tabs with arguments. + */ + public function get_help_tabs() + { + } + /** + * Gets the arguments for a help tab. + * + * @since 3.4.0 + * + * @param string $id Help Tab ID. + * @return array Help tab arguments. + */ + public function get_help_tab($id) + { + } + /** + * Adds a help tab to the contextual help for the screen. + * + * Call this on the `load-$pagenow` hook for the relevant screen, + * or fetch the `$current_screen` object, or use get_current_screen() + * and then call the method from the object. + * + * You may need to filter `$current_screen` using an if or switch statement + * to prevent new help tabs from being added to ALL admin screens. + * + * @since 3.3.0 + * @since 4.4.0 The `$priority` argument was added. + * + * @param array $args { + * Array of arguments used to display the help tab. + * + * @type string $title Title for the tab. Default false. + * @type string $id Tab ID. Must be HTML-safe and should be unique for this menu. + * It is NOT allowed to contain any empty spaces. Default false. + * @type string $content Optional. Help tab content in plain text or HTML. Default empty string. + * @type callable $callback Optional. A callback to generate the tab content. Default false. + * @type int $priority Optional. The priority of the tab, used for ordering. Default 10. + * } + * @phpstan-param array{ + * title?: string, + * id?: string, + * content?: string, + * callback?: callable, + * priority?: int, + * } $args + */ + public function add_help_tab($args) + { + } + /** + * Removes a help tab from the contextual help for the screen. + * + * @since 3.3.0 + * + * @param string $id The help tab ID. + */ + public function remove_help_tab($id) + { + } + /** + * Removes all help tabs from the contextual help for the screen. + * + * @since 3.3.0 + */ + public function remove_help_tabs() + { + } + /** + * Gets the content from a contextual help sidebar. + * + * @since 3.4.0 + * + * @return string Contents of the help sidebar. + */ + public function get_help_sidebar() + { + } + /** + * Adds a sidebar to the contextual help for the screen. + * + * Call this in template files after admin.php is loaded and before admin-header.php is loaded + * to add a sidebar to the contextual help. + * + * @since 3.3.0 + * + * @param string $content Sidebar content in plain text or HTML. + */ + public function set_help_sidebar($content) + { + } + /** + * Gets the number of layout columns the user has selected. + * + * The layout_columns option controls the max number and default number of + * columns. This method returns the number of columns within that range selected + * by the user via Screen Options. If no selection has been made, the default + * provisioned in layout_columns is returned. If the screen does not support + * selecting the number of layout columns, 0 is returned. + * + * @since 3.4.0 + * + * @return int Number of columns to display. + */ + public function get_columns() + { + } + /** + * Gets the accessible hidden headings and text used in the screen. + * + * @since 4.4.0 + * + * @see set_screen_reader_content() For more information on the array format. + * + * @return array An associative array of screen reader text strings. + */ + public function get_screen_reader_content() + { + } + /** + * Gets a screen reader text string. + * + * @since 4.4.0 + * + * @param string $key Screen reader text array named key. + * @return string Screen reader text string. + */ + public function get_screen_reader_text($key) + { + } + /** + * Adds accessible hidden headings and text for the screen. + * + * @since 4.4.0 + * + * @param array $content { + * An associative array of screen reader text strings. + * + * @type string $heading_views Screen reader text for the filter links heading. + * Default 'Filter items list'. + * @type string $heading_pagination Screen reader text for the pagination heading. + * Default 'Items list navigation'. + * @type string $heading_list Screen reader text for the items list heading. + * Default 'Items list'. + * } + * @phpstan-param array{ + * heading_views?: string, + * heading_pagination?: string, + * heading_list?: string, + * } $content + */ + public function set_screen_reader_content($content = array()) + { + } + /** + * Removes all the accessible hidden headings and text for the screen. + * + * @since 4.4.0 + */ + public function remove_screen_reader_content() + { + } + /** + * Renders the screen's help section. + * + * This will trigger the deprecated filters for backward compatibility. + * + * @since 3.3.0 + * + * @global string $screen_layout_columns + */ + public function render_screen_meta() + { + } + /** + * @global array $wp_meta_boxes + * + * @return bool + */ + public function show_screen_options() + { + } + /** + * Renders the screen options tab. + * + * @since 3.3.0 + * + * @param array $options { + * Options for the tab. + * + * @type bool $wrap Whether the screen-options-wrap div will be included. Defaults to true. + * } + * @phpstan-param array{ + * wrap?: bool, + * } $options + */ + public function render_screen_options($options = array()) + { + } + /** + * Renders the meta boxes preferences. + * + * @since 4.4.0 + * + * @global array $wp_meta_boxes + */ + public function render_meta_boxes_preferences() + { + } + /** + * Renders the list table columns preferences. + * + * @since 4.4.0 + */ + public function render_list_table_columns_preferences() + { + } + /** + * Renders the option for number of columns on the page. + * + * @since 3.3.0 + */ + public function render_screen_layout() + { + } + /** + * Renders the items per page option. + * + * @since 3.3.0 + */ + public function render_per_page_options() + { + } + /** + * Renders the list table view mode preferences. + * + * @since 4.4.0 + * + * @global string $mode List table view mode. + */ + public function render_view_mode() + { + } + /** + * Renders screen reader text. + * + * @since 4.4.0 + * + * @param string $key The screen reader text array named key. + * @param string $tag Optional. The HTML tag to wrap the screen reader text. Default h2. + */ + public function render_screen_reader_content($key = '', $tag = 'h2') + { + } + } + /** + * Class for testing automatic updates in the WordPress code. + * + * @package WordPress + * @subpackage Site_Health + * @since 5.2.0 + */ + #[\AllowDynamicProperties] + class WP_Site_Health_Auto_Updates + { + /** + * WP_Site_Health_Auto_Updates constructor. + * + * @since 5.2.0 + */ + public function __construct() + { + } + /** + * Runs tests to determine if auto-updates can run. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function run_tests() + { + } + /** + * Tests if auto-updates related constants are set correctly. + * + * @since 5.2.0 + * @since 5.5.1 The `$value` parameter can accept an array. + * + * @param string $constant The name of the constant to check. + * @param bool|string|array $value The value that the constant should be, if set, + * or an array of acceptable values. + * @return array The test results. + */ + public function test_constants($constant, $value) + { + } + /** + * Checks if updates are intercepted by a filter. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function test_wp_version_check_attached() + { + } + /** + * Checks if automatic updates are disabled by a filter. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function test_filters_automatic_updater_disabled() + { + } + /** + * Checks if automatic updates are disabled. + * + * @since 5.3.0 + * + * @return array|false The test results. False if auto-updates are enabled. + */ + public function test_wp_automatic_updates_disabled() + { + } + /** + * Checks if automatic updates have tried to run, but failed, previously. + * + * @since 5.2.0 + * + * @return array|false The test results. False if the auto-updates failed. + */ + public function test_if_failed_update() + { + } + /** + * Checks if WordPress is controlled by a VCS (Git, Subversion etc). + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function test_vcs_abspath() + { + } + /** + * Checks if we can access files without providing credentials. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function test_check_wp_filesystem_method() + { + } + /** + * Checks if core files are writable by the web user/group. + * + * @since 5.2.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @return array|false The test results. False if they're not writeable. + */ + public function test_all_files_writable() + { + } + /** + * Checks if the install is using a development branch and can use nightly packages. + * + * @since 5.2.0 + * + * @return array|false The test results. False if it isn't a development version. + */ + public function test_accepts_dev_updates() + { + } + /** + * Checks if the site supports automatic minor updates. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function test_accepts_minor_updates() + { + } + } + /** + * Class for looking up a site's health based on a user's WordPress environment. + * + * @package WordPress + * @subpackage Site_Health + * @since 5.2.0 + */ + #[\AllowDynamicProperties] + class WP_Site_Health + { + public $is_mariadb = \false; + public $php_memory_limit; + public $schedules; + public $crons; + public $last_missed_cron = \null; + public $last_late_cron = \null; + /** + * WP_Site_Health constructor. + * + * @since 5.2.0 + */ + public function __construct() + { + } + /** + * Outputs the content of a tab in the Site Health screen. + * + * @since 5.8.0 + * + * @param string $tab Slug of the current tab being displayed. + */ + public function show_site_health_tab($tab) + { + } + /** + * Returns an instance of the WP_Site_Health class, or create one if none exist yet. + * + * @since 5.4.0 + * + * @return WP_Site_Health|null + */ + public static function get_instance() + { + } + /** + * Enqueues the site health scripts. + * + * @since 5.2.0 + */ + public function enqueue_scripts() + { + } + /** + * Tests whether `wp_version_check` is blocked. + * + * It's possible to block updates with the `wp_version_check` filter, but this can't be checked + * during an Ajax call, as the filter is never introduced then. + * + * This filter overrides a standard page request if it's made by an admin through the Ajax call + * with the right query argument to check for this. + * + * @since 5.2.0 + */ + public function check_wp_version_check_exists() + { + } + /** + * Tests for WordPress version and outputs it. + * + * Gives various results depending on what kind of updates are available, if any, to encourage + * the user to install security updates as a priority. + * + * @since 5.2.0 + * + * @return array The test result. + */ + public function get_test_wordpress_version() + { + } + /** + * Tests if plugins are outdated, or unnecessary. + * + * The test checks if your plugins are up to date, and encourages you to remove any + * that are not in use. + * + * @since 5.2.0 + * + * @return array The test result. + */ + public function get_test_plugin_version() + { + } + /** + * Tests if themes are outdated, or unnecessary. + * + * Checks if your site has a default theme (to fall back on if there is a need), + * if your themes are up to date and, finally, encourages you to remove any themes + * that are not needed. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function get_test_theme_version() + { + } + /** + * Tests if the supplied PHP version is supported. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function get_test_php_version() + { + } + /** + * Tests if required PHP modules are installed on the host. + * + * This test builds on the recommendations made by the WordPress Hosting Team + * as seen at https://make.wordpress.org/hosting/handbook/handbook/server-environment/#php-extensions + * + * @since 5.2.0 + * + * @return array + */ + public function get_test_php_extensions() + { + } + /** + * Tests if the PHP default timezone is set to UTC. + * + * @since 5.3.1 + * + * @return array The test results. + */ + public function get_test_php_default_timezone() + { + } + /** + * Tests if there's an active PHP session that can affect loopback requests. + * + * @since 5.5.0 + * + * @return array The test results. + */ + public function get_test_php_sessions() + { + } + /** + * Tests if the SQL server is up to date. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function get_test_sql_server() + { + } + /** + * Tests if the database server is capable of using utf8mb4. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function get_test_utf8mb4_support() + { + } + /** + * Tests if the site can communicate with WordPress.org. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function get_test_dotorg_communication() + { + } + /** + * Tests if debug information is enabled. + * + * When WP_DEBUG is enabled, errors and information may be disclosed to site visitors, + * or logged to a publicly accessible file. + * + * Debugging is also frequently left enabled after looking for errors on a site, + * as site owners do not understand the implications of this. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function get_test_is_in_debug_mode() + { + } + /** + * Tests if the site is serving content over HTTPS. + * + * Many sites have varying degrees of HTTPS support, the most common of which is sites that have it + * enabled, but only if you visit the right site address. + * + * @since 5.2.0 + * @since 5.7.0 Updated to rely on {@see wp_is_using_https()} and {@see wp_is_https_supported()}. + * + * @return array The test results. + */ + public function get_test_https_status() + { + } + /** + * Checks if the HTTP API can handle SSL/TLS requests. + * + * @since 5.2.0 + * + * @return array The test result. + */ + public function get_test_ssl_support() + { + } + /** + * Tests if scheduled events run as intended. + * + * If scheduled events are not running, this may indicate something with WP_Cron is not working + * as intended, or that there are orphaned events hanging around from older code. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function get_test_scheduled_events() + { + } + /** + * Tests if WordPress can run automated background updates. + * + * Background updates in WordPress are primarily used for minor releases and security updates. + * It's important to either have these working, or be aware that they are intentionally disabled + * for whatever reason. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function get_test_background_updates() + { + } + /** + * Tests if plugin and theme auto-updates appear to be configured correctly. + * + * @since 5.5.0 + * + * @return array The test results. + */ + public function get_test_plugin_theme_auto_updates() + { + } + /** + * Tests if loopbacks work as expected. + * + * A loopback is when WordPress queries itself, for example to start a new WP_Cron instance, + * or when editing a plugin or theme. This has shown itself to be a recurring issue, + * as code can very easily break this interaction. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function get_test_loopback_requests() + { + } + /** + * Tests if HTTP requests are blocked. + * + * It's possible to block all outgoing communication (with the possibility of allowing certain + * hosts) via the HTTP API. This may create problems for users as many features are running as + * services these days. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function get_test_http_requests() + { + } + /** + * Tests if the REST API is accessible. + * + * Various security measures may block the REST API from working, or it may have been disabled in general. + * This is required for the new block editor to work, so we explicitly test for this. + * + * @since 5.2.0 + * + * @return array The test results. + */ + public function get_test_rest_availability() + { + } + /** + * Tests if 'file_uploads' directive in PHP.ini is turned off. + * + * @since 5.5.0 + * + * @return array The test results. + */ + public function get_test_file_uploads() + { + } + /** + * Tests if the Authorization header has the expected values. + * + * @since 5.6.0 + * + * @return array + */ + public function get_test_authorization_header() + { + } + /** + * Tests if a full page cache is available. + * + * @since 6.1.0 + * + * @return array The test result. + */ + public function get_test_page_cache() + { + } + /** + * Tests if the site uses persistent object cache and recommends to use it if not. + * + * @since 6.1.0 + * + * @return array The test result. + */ + public function get_test_persistent_object_cache() + { + } + /** + * Returns a set of tests that belong to the site status page. + * + * Each site status test is defined here, they may be `direct` tests, that run on page load, or `async` tests + * which will run later down the line via JavaScript calls to improve page performance and hopefully also user + * experiences. + * + * @since 5.2.0 + * @since 5.6.0 Added support for `has_rest` and `permissions`. + * + * @return array The list of tests to run. + */ + public static function get_tests() + { + } + /** + * Adds a class to the body HTML tag. + * + * Filters the body class string for admin pages and adds our own class for easier styling. + * + * @since 5.2.0 + * + * @param string $body_class The body class string. + * @return string The modified body class string. + */ + public function admin_body_class($body_class) + { + } + /** + * Checks if any scheduled tasks have been missed. + * + * Returns a boolean value of `true` if a scheduled task has been missed and ends processing. + * + * If the list of crons is an instance of WP_Error, returns the instance instead of a boolean value. + * + * @since 5.2.0 + * + * @return bool|WP_Error True if a cron was missed, false if not. WP_Error if the cron is set to that. + */ + public function has_missed_cron() + { + } + /** + * Checks if any scheduled tasks are late. + * + * Returns a boolean value of `true` if a scheduled task is late and ends processing. + * + * If the list of crons is an instance of WP_Error, returns the instance instead of a boolean value. + * + * @since 5.3.0 + * + * @return bool|WP_Error True if a cron is late, false if not. WP_Error if the cron is set to that. + */ + public function has_late_cron() + { + } + /** + * Checks for potential issues with plugin and theme auto-updates. + * + * Though there is no way to 100% determine if plugin and theme auto-updates are configured + * correctly, a few educated guesses could be made to flag any conditions that would + * potentially cause unexpected behaviors. + * + * @since 5.5.0 + * + * @return object The test results. + */ + public function detect_plugin_theme_auto_update_issues() + { + } + /** + * Runs a loopback test on the site. + * + * Loopbacks are what WordPress uses to communicate with itself to start up WP_Cron, scheduled posts, + * make sure plugin or theme edits don't cause site failures and similar. + * + * @since 5.2.0 + * + * @return object The test results. + */ + public function can_perform_loopback() + { + } + /** + * Creates a weekly cron event, if one does not already exist. + * + * @since 5.4.0 + */ + public function maybe_create_scheduled_event() + { + } + /** + * Runs the scheduled event to check and update the latest site health status for the website. + * + * @since 5.4.0 + */ + public function wp_cron_scheduled_check() + { + } + /** + * Checks if the current environment type is set to 'development' or 'local'. + * + * @since 5.6.0 + * + * @return bool True if it is a development environment, false if not. + */ + public function is_development_environment() + { + } + /** + * Returns a list of headers and its verification callback to verify if page cache is enabled or not. + * + * Note: key is header name and value could be callable function to verify header value. + * Empty value mean existence of header detect page cache is enabled. + * + * @since 6.1.0 + * + * @return array List of client caching headers and their (optional) verification callbacks. + */ + public function get_page_cache_headers() + { + } + /** + * Determines whether to suggest using a persistent object cache. + * + * @since 6.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return bool Whether to suggest using a persistent object cache. + */ + public function should_suggest_persistent_object_cache() + { + } + } + /** + * Administration API: WP_Site_Icon class + * + * @package WordPress + * @subpackage Administration + * @since 4.3.0 + */ + /** + * Core class used to implement site icon functionality. + * + * @since 4.3.0 + */ + #[\AllowDynamicProperties] + class WP_Site_Icon + { + /** + * The minimum size of the site icon. + * + * @since 4.3.0 + * @var int + */ + public $min_size = 512; + /** + * The size to which to crop the image so that we can display it in the UI nicely. + * + * @since 4.3.0 + * @var int + */ + public $page_crop = 512; + /** + * List of site icon sizes. + * + * @since 4.3.0 + * @var int[] + */ + public $site_icon_sizes = array( + /* + * Square, medium sized tiles for IE11+. + * + * See https://msdn.microsoft.com/library/dn455106(v=vs.85).aspx + */ + 270, + /* + * App icon for Android/Chrome. + * + * @link https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android + * @link https://developer.chrome.com/multidevice/android/installtohomescreen + */ + 192, + /* + * App icons up to iPhone 6 Plus. + * + * See https://developer.apple.com/library/prerelease/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html + */ + 180, + // Our regular Favicon. + 32, + ); + /** + * Registers actions and filters. + * + * @since 4.3.0 + */ + public function __construct() + { + } + /** + * Creates an attachment 'object'. + * + * @since 4.3.0 + * + * @param string $cropped Cropped image URL. + * @param int $parent_attachment_id Attachment ID of parent image. + * @return array An array with attachment object data. + */ + public function create_attachment_object($cropped, $parent_attachment_id) + { + } + /** + * Inserts an attachment. + * + * @since 4.3.0 + * + * @param array $attachment An array with attachment object data. + * @param string $file File path of the attached image. + * @return int Attachment ID. + */ + public function insert_attachment($attachment, $file) + { + } + /** + * Adds additional sizes to be made when creating the site icon images. + * + * @since 4.3.0 + * + * @param array[] $sizes Array of arrays containing information for additional sizes. + * @return array[] Array of arrays containing additional image sizes. + */ + public function additional_sizes($sizes = array()) + { + } + /** + * Adds Site Icon sizes to the array of image sizes on demand. + * + * @since 4.3.0 + * + * @param string[] $sizes Array of image size names. + * @return string[] Array of image size names. + */ + public function intermediate_image_sizes($sizes = array()) + { + } + /** + * Deletes the Site Icon when the image file is deleted. + * + * @since 4.3.0 + * + * @param int $post_id Attachment ID. + */ + public function delete_attachment_data($post_id) + { + } + /** + * Adds custom image sizes when meta data for an image is requested, that happens to be used as Site Icon. + * + * @since 4.3.0 + * + * @param null|array|string $value The value get_metadata() should return a single metadata value, or an + * array of values. + * @param int $post_id Post ID. + * @param string $meta_key Meta key. + * @param bool $single Whether to return only the first value of the specified `$meta_key`. + * @return array|null|string The attachment metadata value, array of values, or null. + */ + public function get_post_metadata($value, $post_id, $meta_key, $single) + { + } + } + /** + * List Table API: WP_Terms_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 3.1.0 + */ + /** + * Core class used to implement displaying terms in a list table. + * + * @since 3.1.0 + * + * @see WP_List_Table + */ + class WP_Terms_List_Table extends \WP_List_Table + { + public $callback_args; + /** + * Constructor. + * + * @since 3.1.0 + * + * @see WP_List_Table::__construct() for more information on default arguments. + * + * @global string $post_type + * @global string $taxonomy + * @global string $action + * @global object $tax + * + * @param array $args An associative array of arguments. + */ + public function __construct($args = array()) + { + } + /** + * @return bool + */ + public function ajax_user_can() + { + } + /** + */ + public function prepare_items() + { + } + /** + */ + public function no_items() + { + } + /** + * @return array + */ + protected function get_bulk_actions() + { + } + /** + * @return string + */ + public function current_action() + { + } + /** + * @return array + */ + public function get_columns() + { + } + /** + * @return array + */ + protected function get_sortable_columns() + { + } + /** + */ + public function display_rows_or_placeholder() + { + } + /** + * @global string $taxonomy + * @param WP_Term $tag Term object. + * @param int $level + */ + public function single_row($tag, $level = 0) + { + } + /** + * @since 5.9.0 Renamed `$tag` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Term $item Term object. + * @return string + */ + public function column_cb($item) + { + } + /** + * @param WP_Term $tag Term object. + * @return string + */ + public function column_name($tag) + { + } + /** + * Gets the name of the default primary column. + * + * @since 4.3.0 + * + * @return string Name of the default primary column, in this case, 'name'. + */ + protected function get_default_primary_column_name() + { + } + /** + * Generates and displays row action links. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$tag` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Term $item Tag being acted upon. + * @param string $column_name Current column name. + * @param string $primary Primary column name. + * @return string Row actions output for terms, or an empty string + * if the current column is not the primary column. + */ + protected function handle_row_actions($item, $column_name, $primary) + { + } + /** + * @param WP_Term $tag Term object. + * @return string + */ + public function column_description($tag) + { + } + /** + * @param WP_Term $tag Term object. + * @return string + */ + public function column_slug($tag) + { + } + /** + * @param WP_Term $tag Term object. + * @return string + */ + public function column_posts($tag) + { + } + /** + * @param WP_Term $tag Term object. + * @return string + */ + public function column_links($tag) + { + } + /** + * @since 5.9.0 Renamed `$tag` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Term $item Term object. + * @param string $column_name Name of the column. + * @return string + */ + public function column_default($item, $column_name) + { + } + /** + * Outputs the hidden row displayed when inline editing + * + * @since 3.1.0 + */ + public function inline_edit() + { + } + } + /** + * List Table API: WP_Themes_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 3.1.0 + */ + /** + * Core class used to implement displaying installed themes in a list table. + * + * @since 3.1.0 + * + * @see WP_List_Table + */ + class WP_Themes_List_Table extends \WP_List_Table + { + protected $search_terms = array(); + public $features = array(); + /** + * Constructor. + * + * @since 3.1.0 + * + * @see WP_List_Table::__construct() for more information on default arguments. + * + * @param array $args An associative array of arguments. + */ + public function __construct($args = array()) + { + } + /** + * @return bool + */ + public function ajax_user_can() + { + } + /** + */ + public function prepare_items() + { + } + /** + */ + public function no_items() + { + } + /** + * @param string $which + */ + public function tablenav($which = 'top') + { + } + /** + * Displays the themes table. + * + * Overrides the parent display() method to provide a different container. + * + * @since 3.1.0 + */ + public function display() + { + } + /** + * @return array + */ + public function get_columns() + { + } + /** + */ + public function display_rows_or_placeholder() + { + } + /** + */ + public function display_rows() + { + } + /** + * @param WP_Theme $theme + * @return bool + */ + public function search_theme($theme) + { + } + /** + * Send required variables to JavaScript land + * + * @since 3.4.0 + * + * @param array $extra_args + */ + public function _js_vars($extra_args = array()) + { + } + } + /** + * List Table API: WP_Theme_Install_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 3.1.0 + */ + /** + * Core class used to implement displaying themes to install in a list table. + * + * @since 3.1.0 + * + * @see WP_Themes_List_Table + */ + class WP_Theme_Install_List_Table extends \WP_Themes_List_Table + { + public $features = array(); + /** + * @return bool + */ + public function ajax_user_can() + { + } + /** + * @global array $tabs + * @global string $tab + * @global int $paged + * @global string $type + * @global array $theme_field_defaults + */ + public function prepare_items() + { + } + /** + */ + public function no_items() + { + } + /** + * @global array $tabs + * @global string $tab + * @return array + */ + protected function get_views() + { + } + /** + * Displays the theme install table. + * + * Overrides the parent display() method to provide a different container. + * + * @since 3.1.0 + */ + public function display() + { + } + /** + */ + public function display_rows() + { + } + /** + * Prints a theme from the WordPress.org API. + * + * @since 3.1.0 + * + * @global array $themes_allowedtags + * + * @param stdClass $theme { + * An object that contains theme data returned by the WordPress.org API. + * + * @type string $name Theme name, e.g. 'Twenty Twenty-One'. + * @type string $slug Theme slug, e.g. 'twentytwentyone'. + * @type string $version Theme version, e.g. '1.1'. + * @type string $author Theme author username, e.g. 'melchoyce'. + * @type string $preview_url Preview URL, e.g. 'https://2021.wordpress.net/'. + * @type string $screenshot_url Screenshot URL, e.g. 'https://wordpress.org/themes/twentytwentyone/'. + * @type float $rating Rating score. + * @type int $num_ratings The number of ratings. + * @type string $homepage Theme homepage, e.g. 'https://wordpress.org/themes/twentytwentyone/'. + * @type string $description Theme description. + * @type string $download_link Theme ZIP download URL. + * } + */ + public function single_row($theme) + { + } + /** + * Prints the wrapper for the theme installer. + */ + public function theme_installer() + { + } + /** + * Prints the wrapper for the theme installer with a provided theme's data. + * Used to make the theme installer work for no-js. + * + * @param stdClass $theme A WordPress.org Theme API object. + */ + public function theme_installer_single($theme) + { + } + /** + * Prints the info for a theme (to be used in the theme installer modal). + * + * @global array $themes_allowedtags + * + * @param stdClass $theme A WordPress.org Theme API object. + */ + public function install_theme_info($theme) + { + } + /** + * Send required variables to JavaScript land + * + * @since 3.4.0 + * + * @global string $tab Current tab within Themes->Install screen + * @global string $type Type of search. + * + * @param array $extra_args Unused. + */ + public function _js_vars($extra_args = array()) + { + } + } + /** + * List Table API: WP_Users_List_Table class + * + * @package WordPress + * @subpackage Administration + * @since 3.1.0 + */ + /** + * Core class used to implement displaying users in a list table. + * + * @since 3.1.0 + * + * @see WP_List_Table + */ + class WP_Users_List_Table extends \WP_List_Table + { + /** + * Site ID to generate the Users list table for. + * + * @since 3.1.0 + * @var int + */ + public $site_id; + /** + * Whether or not the current Users list table is for Multisite. + * + * @since 3.1.0 + * @var bool + */ + public $is_site_users; + /** + * Constructor. + * + * @since 3.1.0 + * + * @see WP_List_Table::__construct() for more information on default arguments. + * + * @param array $args An associative array of arguments. + */ + public function __construct($args = array()) + { + } + /** + * Check the current user's permissions. + * + * @since 3.1.0 + * + * @return bool + */ + public function ajax_user_can() + { + } + /** + * Prepare the users list for display. + * + * @since 3.1.0 + * + * @global string $role + * @global string $usersearch + */ + public function prepare_items() + { + } + /** + * Output 'no users' message. + * + * @since 3.1.0 + */ + public function no_items() + { + } + /** + * Return an associative array listing all the views that can be used + * with this table. + * + * Provides a list of roles and user count for that role for easy + * Filtersing of the user table. + * + * @since 3.1.0 + * + * @global string $role + * + * @return string[] An array of HTML links keyed by their view. + */ + protected function get_views() + { + } + /** + * Retrieve an associative array of bulk actions available on this table. + * + * @since 3.1.0 + * + * @return array Array of bulk action labels keyed by their action. + */ + protected function get_bulk_actions() + { + } + /** + * Output the controls to allow user roles to be changed in bulk. + * + * @since 3.1.0 + * + * @param string $which Whether this is being invoked above ("top") + * or below the table ("bottom"). + */ + protected function extra_tablenav($which) + { + } + /** + * Capture the bulk action required, and return it. + * + * Overridden from the base class implementation to capture + * the role change drop-down. + * + * @since 3.1.0 + * + * @return string The bulk action required. + */ + public function current_action() + { + } + /** + * Get a list of columns for the list table. + * + * @since 3.1.0 + * + * @return string[] Array of column titles keyed by their column name. + */ + public function get_columns() + { + } + /** + * Get a list of sortable columns for the list table. + * + * @since 3.1.0 + * + * @return array Array of sortable columns. + */ + protected function get_sortable_columns() + { + } + /** + * Generate the list table rows. + * + * @since 3.1.0 + */ + public function display_rows() + { + } + /** + * Generate HTML for a single row on the users.php admin panel. + * + * @since 3.1.0 + * @since 4.2.0 The `$style` parameter was deprecated. + * @since 4.4.0 The `$role` parameter was deprecated. + * + * @param WP_User $user_object The current user object. + * @param string $style Deprecated. Not used. + * @param string $role Deprecated. Not used. + * @param int $numposts Optional. Post count to display for this user. Defaults + * to zero, as in, a new user has made zero posts. + * @return string Output for a single row. + */ + public function single_row($user_object, $style = '', $role = '', $numposts = 0) + { + } + /** + * Gets the name of the default primary column. + * + * @since 4.3.0 + * + * @return string Name of the default primary column, in this case, 'username'. + */ + protected function get_default_primary_column_name() + { + } + /** + * Returns an array of translated user role names for a given user object. + * + * @since 4.4.0 + * + * @param WP_User $user_object The WP_User object. + * @return string[] An array of user role names keyed by role. + */ + protected function get_role_list($user_object) + { + } + } + /** + * WordPress User Search class. + * + * @since 2.1.0 + * @deprecated 3.1.0 Use WP_User_Query + */ + class WP_User_Search + { + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var mixed + */ + var $results; + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var string + */ + var $search_term; + /** + * Page number. + * + * @since 2.1.0 + * @access private + * @var int + */ + var $page; + /** + * Role name that users have. + * + * @since 2.5.0 + * @access private + * @var string + */ + var $role; + /** + * Raw page number. + * + * @since 2.1.0 + * @access private + * @var int|bool + */ + var $raw_page; + /** + * Amount of users to display per page. + * + * @since 2.1.0 + * @access public + * @var int + */ + var $users_per_page = 50; + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var int + */ + var $first_user; + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var int + */ + var $last_user; + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var string + */ + var $query_limit; + /** + * {@internal Missing Description}} + * + * @since 3.0.0 + * @access private + * @var string + */ + var $query_orderby; + /** + * {@internal Missing Description}} + * + * @since 3.0.0 + * @access private + * @var string + */ + var $query_from; + /** + * {@internal Missing Description}} + * + * @since 3.0.0 + * @access private + * @var string + */ + var $query_where; + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var int + */ + var $total_users_for_query = 0; + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var bool + */ + var $too_many_total_users = \false; + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var WP_Error + */ + var $search_errors; + /** + * {@internal Missing Description}} + * + * @since 2.7.0 + * @access private + * @var string + */ + var $paging_text; + /** + * PHP5 Constructor - Sets up the object properties. + * + * @since 2.1.0 + * + * @param string $search_term Search terms string. + * @param int $page Optional. Page ID. + * @param string $role Role name. + * @return WP_User_Search + */ + function __construct($search_term = '', $page = '', $role = '') + { + } + /** + * PHP4 Constructor - Sets up the object properties. + * + * @since 2.1.0 + * + * @param string $search_term Search terms string. + * @param int $page Optional. Page ID. + * @param string $role Role name. + * @return WP_User_Search + */ + public function WP_User_Search($search_term = '', $page = '', $role = '') + { + } + /** + * Prepares the user search query (legacy). + * + * @since 2.1.0 + * @access public + */ + public function prepare_query() + { + } + /** + * Executes the user search query. + * + * @since 2.1.0 + * @access public + */ + public function query() + { + } + /** + * Prepares variables for use in templates. + * + * @since 2.1.0 + * @access public + */ + function prepare_vars_for_template_usage() + { + } + /** + * Handles paging for the user search query. + * + * @since 2.1.0 + * @access public + */ + public function do_paging() + { + } + /** + * Retrieves the user search query results. + * + * @since 2.1.0 + * @access public + * + * @return array + */ + public function get_results() + { + } + /** + * Displaying paging text. + * + * @see do_paging() Builds paging text. + * + * @since 2.1.0 + * @access public + */ + function page_links() + { + } + /** + * Whether paging is enabled. + * + * @see do_paging() Builds paging text. + * + * @since 2.1.0 + * @access public + * + * @return bool + */ + function results_are_paged() + { + } + /** + * Whether there are search terms. + * + * @since 2.1.0 + * @access public + * + * @return bool + */ + function is_search() + { + } + } + /** + * Previous class for list table for privacy data export requests. + * + * @since 4.9.6 + * @deprecated 5.3.0 + */ + class WP_Privacy_Data_Export_Requests_Table extends \WP_Privacy_Data_Export_Requests_List_Table + { + function __construct($args) + { + } + } + /** + * Previous class for list table for privacy data erasure requests. + * + * @since 4.9.6 + * @deprecated 5.3.0 + */ + class WP_Privacy_Data_Removal_Requests_Table extends \WP_Privacy_Data_Removal_Requests_List_Table + { + function __construct($args) + { + } + } + class getid3_lib + { + /** + * @param string $string + * @param bool $hex + * @param bool $spaces + * @param string|bool $htmlencoding + * + * @return string + */ + public static function PrintHexBytes($string, $hex = \true, $spaces = \true, $htmlencoding = 'UTF-8') + { + } + /** + * Truncates a floating-point number at the decimal point. + * + * @param float $floatnumber + * + * @return float|int returns int (if possible, otherwise float) + */ + public static function trunc($floatnumber) + { + } + /** + * @param int|null $variable + * @param int $increment + * + * @return bool + */ + public static function safe_inc(&$variable, $increment = 1) + { + } + /** + * @param int|float $floatnum + * + * @return int|float + */ + public static function CastAsInt($floatnum) + { + } + /** + * @param int $num + * + * @return bool + */ + public static function intValueSupported($num) + { + } + /** + * @param string $fraction + * + * @return float + */ + public static function DecimalizeFraction($fraction) + { + } + /** + * @param string $binarynumerator + * + * @return float + */ + public static function DecimalBinary2Float($binarynumerator) + { + } + /** + * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html + * + * @param string $binarypointnumber + * @param int $maxbits + * + * @return array + */ + public static function NormalizeBinaryPoint($binarypointnumber, $maxbits = 52) + { + } + /** + * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html + * + * @param float $floatvalue + * + * @return string + */ + public static function Float2BinaryDecimal($floatvalue) + { + } + /** + * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html + * + * @param float $floatvalue + * @param int $bits + * + * @return string|false + */ + public static function Float2String($floatvalue, $bits) + { + } + /** + * @param string $byteword + * + * @return float|false + */ + public static function LittleEndian2Float($byteword) + { + } + /** + * ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic + * + * @link https://web.archive.org/web/20120325162206/http://www.psc.edu/general/software/packages/ieee/ieee.php + * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html + * + * @param string $byteword + * + * @return float|false + */ + public static function BigEndian2Float($byteword) + { + } + /** + * @param string $byteword + * @param bool $synchsafe + * @param bool $signed + * + * @return int|float|false + * @throws Exception + */ + public static function BigEndian2Int($byteword, $synchsafe = \false, $signed = \false) + { + } + /** + * @param string $byteword + * @param bool $signed + * + * @return int|float|false + */ + public static function LittleEndian2Int($byteword, $signed = \false) + { + } + /** + * @param string $byteword + * + * @return string + */ + public static function LittleEndian2Bin($byteword) + { + } + /** + * @param string $byteword + * + * @return string + */ + public static function BigEndian2Bin($byteword) + { + } + /** + * @param int $number + * @param int $minbytes + * @param bool $synchsafe + * @param bool $signed + * + * @return string + * @throws Exception + */ + public static function BigEndian2String($number, $minbytes = 1, $synchsafe = \false, $signed = \false) + { + } + /** + * @param int $number + * + * @return string + */ + public static function Dec2Bin($number) + { + } + /** + * @param string $binstring + * @param bool $signed + * + * @return int|float + */ + public static function Bin2Dec($binstring, $signed = \false) + { + } + /** + * @param string $binstring + * + * @return string + */ + public static function Bin2String($binstring) + { + } + /** + * @param int $number + * @param int $minbytes + * @param bool $synchsafe + * + * @return string + */ + public static function LittleEndian2String($number, $minbytes = 1, $synchsafe = \false) + { + } + /** + * @param mixed $array1 + * @param mixed $array2 + * + * @return array|false + */ + public static function array_merge_clobber($array1, $array2) + { + } + /** + * @param mixed $array1 + * @param mixed $array2 + * + * @return array|false + */ + public static function array_merge_noclobber($array1, $array2) + { + } + /** + * @param mixed $array1 + * @param mixed $array2 + * + * @return array|false|null + */ + public static function flipped_array_merge_noclobber($array1, $array2) + { + } + /** + * @param array $theArray + * + * @return bool + */ + public static function ksort_recursive(&$theArray) + { + } + /** + * @param string $filename + * @param int $numextensions + * + * @return string + */ + public static function fileextension($filename, $numextensions = 1) + { + } + /** + * @param int $seconds + * + * @return string + */ + public static function PlaytimeString($seconds) + { + } + /** + * @param int $macdate + * + * @return int|float + */ + public static function DateMac2Unix($macdate) + { + } + /** + * @param string $rawdata + * + * @return float + */ + public static function FixedPoint8_8($rawdata) + { + } + /** + * @param string $rawdata + * + * @return float + */ + public static function FixedPoint16_16($rawdata) + { + } + /** + * @param string $rawdata + * + * @return float + */ + public static function FixedPoint2_30($rawdata) + { + } + /** + * @param string $ArrayPath + * @param string $Separator + * @param mixed $Value + * + * @return array + */ + public static function CreateDeepArray($ArrayPath, $Separator, $Value) + { + } + /** + * @param array $arraydata + * @param bool $returnkey + * + * @return int|false + */ + public static function array_max($arraydata, $returnkey = \false) + { + } + /** + * @param array $arraydata + * @param bool $returnkey + * + * @return int|false + */ + public static function array_min($arraydata, $returnkey = \false) + { + } + /** + * @param string $XMLstring + * + * @return array|false + */ + public static function XML2array($XMLstring) + { + } + /** + * @param SimpleXMLElement|array|mixed $XMLobject + * + * @return mixed + */ + public static function SimpleXMLelement2array($XMLobject) + { + } + /** + * Returns checksum for a file from starting position to absolute end position. + * + * @param string $file + * @param int $offset + * @param int $end + * @param string $algorithm + * + * @return string|false + * @throws getid3_exception + */ + public static function hash_data($file, $offset, $end, $algorithm) + { + } + /** + * @param string $filename_source + * @param string $filename_dest + * @param int $offset + * @param int $length + * + * @return bool + * @throws Exception + * + * @deprecated Unused, may be removed in future versions of getID3 + */ + public static function CopyFileParts($filename_source, $filename_dest, $offset, $length) + { + } + /** + * @param int $charval + * + * @return string + */ + public static function iconv_fallback_int_utf8($charval) + { + } + /** + * ISO-8859-1 => UTF-8 + * + * @param string $string + * @param bool $bom + * + * @return string + */ + public static function iconv_fallback_iso88591_utf8($string, $bom = \false) + { + } + /** + * ISO-8859-1 => UTF-16BE + * + * @param string $string + * @param bool $bom + * + * @return string + */ + public static function iconv_fallback_iso88591_utf16be($string, $bom = \false) + { + } + /** + * ISO-8859-1 => UTF-16LE + * + * @param string $string + * @param bool $bom + * + * @return string + */ + public static function iconv_fallback_iso88591_utf16le($string, $bom = \false) + { + } + /** + * ISO-8859-1 => UTF-16LE (BOM) + * + * @param string $string + * + * @return string + */ + public static function iconv_fallback_iso88591_utf16($string) + { + } + /** + * UTF-8 => ISO-8859-1 + * + * @param string $string + * + * @return string + */ + public static function iconv_fallback_utf8_iso88591($string) + { + } + /** + * UTF-8 => UTF-16BE + * + * @param string $string + * @param bool $bom + * + * @return string + */ + public static function iconv_fallback_utf8_utf16be($string, $bom = \false) + { + } + /** + * UTF-8 => UTF-16LE + * + * @param string $string + * @param bool $bom + * + * @return string + */ + public static function iconv_fallback_utf8_utf16le($string, $bom = \false) + { + } + /** + * UTF-8 => UTF-16LE (BOM) + * + * @param string $string + * + * @return string + */ + public static function iconv_fallback_utf8_utf16($string) + { + } + /** + * UTF-16BE => UTF-8 + * + * @param string $string + * + * @return string + */ + public static function iconv_fallback_utf16be_utf8($string) + { + } + /** + * UTF-16LE => UTF-8 + * + * @param string $string + * + * @return string + */ + public static function iconv_fallback_utf16le_utf8($string) + { + } + /** + * UTF-16BE => ISO-8859-1 + * + * @param string $string + * + * @return string + */ + public static function iconv_fallback_utf16be_iso88591($string) + { + } + /** + * UTF-16LE => ISO-8859-1 + * + * @param string $string + * + * @return string + */ + public static function iconv_fallback_utf16le_iso88591($string) + { + } + /** + * UTF-16 (BOM) => ISO-8859-1 + * + * @param string $string + * + * @return string + */ + public static function iconv_fallback_utf16_iso88591($string) + { + } + /** + * UTF-16 (BOM) => UTF-8 + * + * @param string $string + * + * @return string + */ + public static function iconv_fallback_utf16_utf8($string) + { + } + /** + * @param string $in_charset + * @param string $out_charset + * @param string $string + * + * @return string + * @throws Exception + */ + public static function iconv_fallback($in_charset, $out_charset, $string) + { + } + /** + * @param mixed $data + * @param string $charset + * + * @return mixed + */ + public static function recursiveMultiByteCharString2HTML($data, $charset = 'ISO-8859-1') + { + } + /** + * @param string|int|float $string + * @param string $charset + * + * @return string + */ + public static function MultiByteCharString2HTML($string, $charset = 'ISO-8859-1') + { + } + /** + * @param int $namecode + * + * @return string + */ + public static function RGADnameLookup($namecode) + { + } + /** + * @param int $originatorcode + * + * @return string + */ + public static function RGADoriginatorLookup($originatorcode) + { + } + /** + * @param int $rawadjustment + * @param int $signbit + * + * @return float + */ + public static function RGADadjustmentLookup($rawadjustment, $signbit) + { + } + /** + * @param int $namecode + * @param int $originatorcode + * @param int $replaygain + * + * @return string + */ + public static function RGADgainString($namecode, $originatorcode, $replaygain) + { + } + /** + * @param float $amplitude + * + * @return float + */ + public static function RGADamplitude2dB($amplitude) + { + } + /** + * @param string $imgData + * @param array $imageinfo + * + * @return array|false + */ + public static function GetDataImageSize($imgData, &$imageinfo = array()) + { + } + /** + * @param string $mime_type + * + * @return string + */ + public static function ImageExtFromMime($mime_type) + { + } + /** + * @param array $ThisFileInfo + * @param bool $option_tags_html default true (just as in the main getID3 class) + * + * @return bool + */ + public static function CopyTagsToComments(&$ThisFileInfo, $option_tags_html = \true) + { + } + /** + * @param string $key + * @param int $begin + * @param int $end + * @param string $file + * @param string $name + * + * @return string + */ + public static function EmbeddedLookup($key, $begin, $end, $file, $name) + { + } + /** + * @param string $filename + * @param string $sourcefile + * @param bool $DieOnFailure + * + * @return bool + * @throws Exception + */ + public static function IncludeDependency($filename, $sourcefile, $DieOnFailure = \false) + { + } + /** + * @param string $string + * + * @return string + */ + public static function trimNullByte($string) + { + } + /** + * @param string $path + * + * @return float|bool + */ + public static function getFileSizeSyscall($path) + { + } + /** + * @param string $filename + * + * @return string|false + */ + public static function truepath($filename) + { + } + /** + * Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268) + * + * @param string $path A path. + * @param string $suffix If the name component ends in suffix this will also be cut off. + * + * @return string + */ + public static function mb_basename($path, $suffix = '') + { + } + } + // End: Defines + class getID3 + { + /* + * Settings + */ + /** + * CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE + * + * @var string + */ + public $encoding = 'UTF-8'; + /** + * Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252' + * + * @var string + */ + public $encoding_id3v1 = 'ISO-8859-1'; + /** + * ID3v1 should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'Windows-1251' or 'KOI8-R'. If true attempt to detect these encodings, but may return incorrect values for some tags actually in ISO-8859-1 encoding + * + * @var bool + */ + public $encoding_id3v1_autodetect = \false; + /* + * Optional tag checks - disable for speed. + */ + /** + * Read and process ID3v1 tags + * + * @var bool + */ + public $option_tag_id3v1 = \true; + /** + * Read and process ID3v2 tags + * + * @var bool + */ + public $option_tag_id3v2 = \true; + /** + * Read and process Lyrics3 tags + * + * @var bool + */ + public $option_tag_lyrics3 = \true; + /** + * Read and process APE tags + * + * @var bool + */ + public $option_tag_apetag = \true; + /** + * Copy tags to root key 'tags' and encode to $this->encoding + * + * @var bool + */ + public $option_tags_process = \true; + /** + * Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities + * + * @var bool + */ + public $option_tags_html = \true; + /* + * Optional tag/comment calculations + */ + /** + * Calculate additional info such as bitrate, channelmode etc + * + * @var bool + */ + public $option_extra_info = \true; + /* + * Optional handling of embedded attachments (e.g. images) + */ + /** + * Defaults to true (ATTACHMENTS_INLINE) for backward compatibility + * + * @var bool|string + */ + public $option_save_attachments = \true; + /* + * Optional calculations + */ + /** + * Get MD5 sum of data part - slow + * + * @var bool + */ + public $option_md5_data = \false; + /** + * Use MD5 of source file if available - only FLAC and OptimFROG + * + * @var bool + */ + public $option_md5_data_source = \false; + /** + * Get SHA1 sum of data part - slow + * + * @var bool + */ + public $option_sha1_data = \false; + /** + * Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on + * PHP_INT_MAX) + * + * @var bool|null + */ + public $option_max_2gb_check; + /** + * Read buffer size in bytes + * + * @var int + */ + public $option_fread_buffer_size = 32768; + // module-specific options + /** archive.rar + * if true use PHP RarArchive extension, if false (non-extension parsing not yet written in getID3) + * + * @var bool + */ + public $options_archive_rar_use_php_rar_extension = \true; + /** archive.gzip + * Optional file list - disable for speed. + * Decode gzipped files, if possible, and parse recursively (.tar.gz for example). + * + * @var bool + */ + public $options_archive_gzip_parse_contents = \false; + /** audio.midi + * if false only parse most basic information, much faster for some files but may be inaccurate + * + * @var bool + */ + public $options_audio_midi_scanwholefile = \true; + /** audio.mp3 + * Forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow, + * unrecommended, but may provide data from otherwise-unusable files. + * + * @var bool + */ + public $options_audio_mp3_allow_bruteforce = \false; + /** audio.mp3 + * number of frames to scan to determine if MPEG-audio sequence is valid + * Lower this number to 5-20 for faster scanning + * Increase this number to 50+ for most accurate detection of valid VBR/CBR mpeg-audio streams + * + * @var int + */ + public $options_audio_mp3_mp3_valid_check_frames = 50; + /** audio.wavpack + * Avoid scanning all frames (break after finding ID_RIFF_HEADER and ID_CONFIG_BLOCK, + * significantly faster for very large files but other data may be missed + * + * @var bool + */ + public $options_audio_wavpack_quick_parsing = \false; + /** audio-video.flv + * Break out of the loop if too many frames have been scanned; only scan this + * many if meta frame does not contain useful duration. + * + * @var int + */ + public $options_audiovideo_flv_max_frames = 100000; + /** audio-video.matroska + * If true, do not return information about CLUSTER chunks, since there's a lot of them + * and they're not usually useful [default: TRUE]. + * + * @var bool + */ + public $options_audiovideo_matroska_hide_clusters = \true; + /** audio-video.matroska + * True to parse the whole file, not only header [default: FALSE]. + * + * @var bool + */ + public $options_audiovideo_matroska_parse_whole_file = \false; + /** audio-video.quicktime + * return all parsed data from all atoms if true, otherwise just returned parsed metadata + * + * @var bool + */ + public $options_audiovideo_quicktime_ReturnAtomData = \false; + /** audio-video.quicktime + * return all parsed data from all atoms if true, otherwise just returned parsed metadata + * + * @var bool + */ + public $options_audiovideo_quicktime_ParseAllPossibleAtoms = \false; + /** audio-video.swf + * return all parsed tags if true, otherwise do not return tags not parsed by getID3 + * + * @var bool + */ + public $options_audiovideo_swf_ReturnAllTagData = \false; + /** graphic.bmp + * return BMP palette + * + * @var bool + */ + public $options_graphic_bmp_ExtractPalette = \false; + /** graphic.bmp + * return image data + * + * @var bool + */ + public $options_graphic_bmp_ExtractData = \false; + /** graphic.png + * If data chunk is larger than this do not read it completely (getID3 only needs the first + * few dozen bytes for parsing). + * + * @var int + */ + public $options_graphic_png_max_data_bytes = 10000000; + /** misc.pdf + * return full details of PDF Cross-Reference Table (XREF) + * + * @var bool + */ + public $options_misc_pdf_returnXREF = \false; + /** misc.torrent + * Assume all .torrent files are less than 1MB and just read entire thing into memory for easy processing. + * Override this value if you need to process files larger than 1MB + * + * @var int + */ + public $options_misc_torrent_max_torrent_filesize = 1048576; + // Public variables + /** + * Filename of file being analysed. + * + * @var string + */ + public $filename; + /** + * Filepointer to file being analysed. + * + * @var resource + */ + public $fp; + /** + * Result array. + * + * @var array + */ + public $info; + /** + * @var string + */ + public $tempdir = \GETID3_TEMP_DIR; + /** + * @var int + */ + public $memory_limit = 0; + /** + * @var string + */ + protected $startup_error = ''; + /** + * @var string + */ + protected $startup_warning = ''; + const VERSION = '1.9.22-202207161647'; + const FREAD_BUFFER_SIZE = 32768; + const ATTACHMENTS_NONE = \false; + const ATTACHMENTS_INLINE = \true; + /** + * @throws getid3_exception + */ + public function __construct() + { + } + /** + * @return string + */ + public function version() + { + } + /** + * @return int + */ + public function fread_buffer_size() + { + } + /** + * @param array $optArray + * + * @return bool + */ + public function setOption($optArray) + { + } + /** + * @param string $filename + * @param int $filesize + * @param resource $fp + * + * @return bool + * + * @throws getid3_exception + */ + public function openfile($filename, $filesize = \null, $fp = \null) + { + } + /** + * analyze file + * + * @param string $filename + * @param int $filesize + * @param string $original_filename + * @param resource $fp + * + * @return array + */ + public function analyze($filename, $filesize = \null, $original_filename = '', $fp = \null) + { + } + /** + * Error handling. + * + * @param string $message + * + * @return array + */ + public function error($message) + { + } + /** + * Warning handling. + * + * @param string $message + * + * @return bool + */ + public function warning($message) + { + } + /** + * Return array containing information about all supported formats. + * + * @return array + */ + public function GetFileFormatArray() + { + } + /** + * @param string $filedata + * @param string $filename + * + * @return mixed|false + */ + public function GetFileFormat(&$filedata, $filename = '') + { + } + /** + * Converts array to $encoding charset from $this->encoding. + * + * @param array $array + * @param string $encoding + */ + public function CharConvert(&$array, $encoding) + { + } + /** + * @return bool + */ + public function HandleAllTags() + { + } + /** + * Calls getid3_lib::CopyTagsToComments() but passes in the option_tags_html setting from this instance of getID3 + * + * @param array $ThisFileInfo + * + * @return bool + */ + public function CopyTagsToComments(&$ThisFileInfo) + { + } + /** + * @param string $algorithm + * + * @return array|bool + */ + public function getHashdata($algorithm) + { + } + public function ChannelsBitratePlaytimeCalculations() + { + } + /** + * @return bool + */ + public function CalculateCompressionRatioVideo() + { + } + /** + * @return bool + */ + public function CalculateCompressionRatioAudio() + { + } + /** + * @return bool + */ + public function CalculateReplayGain() + { + } + /** + * @return bool + */ + public function ProcessAudioStreams() + { + } + /** + * @return string|bool + */ + public function getid3_tempnam() + { + } + /** + * @param string $name + * + * @return bool + * + * @throws getid3_exception + */ + public function include_module($name) + { + } + /** + * @param string $filename + * + * @return bool + */ + public static function is_writable($filename) + { + } + } + abstract class getid3_handler + { + /** + * @var getID3 + */ + protected $getid3; + // pointer + /** + * Analyzing filepointer or string. + * + * @var bool + */ + protected $data_string_flag = \false; + /** + * String to analyze. + * + * @var string + */ + protected $data_string = ''; + /** + * Seek position in string. + * + * @var int + */ + protected $data_string_position = 0; + /** + * String length. + * + * @var int + */ + protected $data_string_length = 0; + /** + * getid3_handler constructor. + * + * @param getID3 $getid3 + * @param string $call_module + */ + public function __construct(\getID3 $getid3, $call_module = \null) + { + } + /** + * Analyze from file pointer. + * + * @return bool + */ + public abstract function Analyze(); + /** + * Analyze from string instead. + * + * @param string $string + */ + public function AnalyzeString($string) + { + } + /** + * @param string $string + */ + public function setStringMode($string) + { + } + /** + * @return int|bool + */ + protected function ftell() + { + } + /** + * @param int $bytes + * + * @return string|false + * + * @throws getid3_exception + */ + protected function fread($bytes) + { + } + /** + * @param int $bytes + * @param int $whence + * + * @return int + * + * @throws getid3_exception + */ + protected function fseek($bytes, $whence = \SEEK_SET) + { + } + /** + * @return string|false + * + * @throws getid3_exception + */ + protected function fgets() + { + } + /** + * @return bool + */ + protected function feof() + { + } + /** + * @param string $module + * + * @return bool + */ + protected final function isDependencyFor($module) + { + } + /** + * @param string $text + * + * @return bool + */ + protected function error($text) + { + } + /** + * @param string $text + * + * @return bool + */ + protected function warning($text) + { + } + /** + * @param string $text + */ + protected function notice($text) + { + } + /** + * @param string $name + * @param int $offset + * @param int $length + * @param string $image_mime + * + * @return string|null + * + * @throws Exception + * @throws getid3_exception + */ + public function saveAttachment($name, $offset, $length, $image_mime = \null) + { + } + } + class getid3_exception extends \Exception + { + public $message; + } + class getid3_asf extends \getid3_handler + { + protected static $ASFIndexParametersObjectIndexSpecifiersIndexTypes = array(1 => 'Nearest Past Data Packet', 2 => 'Nearest Past Media Object', 3 => 'Nearest Past Cleanpoint'); + protected static $ASFMediaObjectIndexParametersObjectIndexSpecifiersIndexTypes = array(1 => 'Nearest Past Data Packet', 2 => 'Nearest Past Media Object', 3 => 'Nearest Past Cleanpoint', 0xff => 'Frame Number Offset'); + protected static $ASFTimecodeIndexParametersObjectIndexSpecifiersIndexTypes = array(2 => 'Nearest Past Media Object', 3 => 'Nearest Past Cleanpoint'); + /** + * @param getID3 $getid3 + */ + public function __construct(\getID3 $getid3) + { + } + /** + * @return bool + */ + public function Analyze() + { + } + /** + * @param int $CodecListType + * + * @return string + */ + public static function codecListObjectTypeLookup($CodecListType) + { + } + /** + * @return array + */ + public static function KnownGUIDs() + { + } + /** + * @param string $GUIDstring + * + * @return string|false + */ + public static function GUIDname($GUIDstring) + { + } + /** + * @param int $id + * + * @return string + */ + public static function ASFIndexObjectIndexTypeLookup($id) + { + } + /** + * @param string $GUIDstring + * + * @return string + */ + public static function GUIDtoBytestring($GUIDstring) + { + } + /** + * @param string $Bytestring + * + * @return string + */ + public static function BytestringToGUID($Bytestring) + { + } + /** + * @param int $FILETIME + * @param bool $round + * + * @return float|int + */ + public static function FILETIMEtoUNIXtime($FILETIME, $round = \true) + { + } + /** + * @param int $WMpictureType + * + * @return string + */ + public static function WMpictureTypeLookup($WMpictureType) + { + } + /** + * @param string $asf_header_extension_object_data + * @param int $unhandled_sections + * + * @return array + */ + public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) + { + } + /** + * @param int $id + * + * @return string + */ + public static function metadataLibraryObjectDataTypeLookup($id) + { + } + /** + * @param string $data + * + * @return array + */ + public function ASF_WMpicture(&$data) + { + } + /** + * Remove terminator 00 00 and convert UTF-16LE to Latin-1. + * + * @param string $string + * + * @return string + */ + public static function TrimConvert($string) + { + } + /** + * Remove terminator 00 00. + * + * @param string $string + * + * @return string + */ + public static function TrimTerm($string) + { + } + } + class getid3_flv extends \getid3_handler + { + const magic = 'FLV'; + /** + * Break out of the loop if too many frames have been scanned; only scan this + * many if meta frame does not contain useful duration. + * + * @var int + */ + public $max_frames = 100000; + /** + * @return bool + */ + public function Analyze() + { + } + /** + * @param int $id + * + * @return string|false + */ + public static function audioFormatLookup($id) + { + } + /** + * @param int $id + * + * @return int|false + */ + public static function audioRateLookup($id) + { + } + /** + * @param int $id + * + * @return int|false + */ + public static function audioBitDepthLookup($id) + { + } + /** + * @param int $id + * + * @return string|false + */ + public static function videoCodecLookup($id) + { + } + } + class AMFStream + { + /** + * @var string + */ + public $bytes; + /** + * @var int + */ + public $pos; + /** + * @param string $bytes + */ + public function __construct(&$bytes) + { + } + /** + * @return int + */ + public function readByte() + { + } + /** + * @return int + */ + public function readInt() + { + } + /** + * @return int + */ + public function readLong() + { + } + /** + * @return float|false + */ + public function readDouble() + { + } + /** + * @return string + */ + public function readUTF() + { + } + /** + * @return string + */ + public function readLongUTF() + { + } + /** + * @param int $length + * + * @return string + */ + public function read($length) + { + } + /** + * @return int + */ + public function peekByte() + { + } + /** + * @return int + */ + public function peekInt() + { + } + /** + * @return int + */ + public function peekLong() + { + } + /** + * @return float|false + */ + public function peekDouble() + { + } + /** + * @return string + */ + public function peekUTF() + { + } + /** + * @return string + */ + public function peekLongUTF() + { + } + } + class AMFReader + { + /** + * @var AMFStream + */ + public $stream; + /** + * @param AMFStream $stream + */ + public function __construct(\AMFStream $stream) + { + } + /** + * @return mixed + */ + public function readData() + { + } + /** + * @return float|false + */ + public function readDouble() + { + } + /** + * @return bool + */ + public function readBoolean() + { + } + /** + * @return string + */ + public function readString() + { + } + /** + * @return array + */ + public function readObject() + { + } + /** + * @return array + */ + public function readMixedArray() + { + } + /** + * @return array + */ + public function readArray() + { + } + /** + * @return float|false + */ + public function readDate() + { + } + /** + * @return string + */ + public function readLongString() + { + } + /** + * @return string + */ + public function readXML() + { + } + /** + * @return array + */ + public function readTypedObject() + { + } + } + class AVCSequenceParameterSetReader + { + /** + * @var string + */ + public $sps; + public $start = 0; + public $currentBytes = 0; + public $currentBits = 0; + /** + * @var int + */ + public $width; + /** + * @var int + */ + public $height; + /** + * @param string $sps + */ + public function __construct($sps) + { + } + public function readData() + { + } + /** + * @param int $bits + */ + public function skipBits($bits) + { + } + /** + * @return int + */ + public function getBit() + { + } + /** + * @param int $bits + * + * @return int + */ + public function getBits($bits) + { + } + /** + * @return int + */ + public function expGolombUe() + { + } + /** + * @return int + */ + public function expGolombSe() + { + } + /** + * @return int + */ + public function getWidth() + { + } + /** + * @return int + */ + public function getHeight() + { + } + } + // [FD] -- Relative position of the data that should be in position of the virtual block. + /** + * @tutorial http://www.matroska.org/technical/specs/index.html + * + * @todo Rewrite EBML parser to reduce it's size and honor default element values + * @todo After rewrite implement stream size calculation, that will provide additional useful info and enable AAC/FLAC audio bitrate detection + */ + class getid3_matroska extends \getid3_handler + { + /** + * If true, do not return information about CLUSTER chunks, since there's a lot of them + * and they're not usually useful [default: TRUE]. + * + * @var bool + */ + public $hide_clusters = \true; + /** + * True to parse the whole file, not only header [default: FALSE]. + * + * @var bool + */ + public $parse_whole_file = \false; + /** + * @return bool + */ + public function Analyze() + { + } + /** + * @param int $target_type + * + * @return string|int + */ + public static function TargetTypeValue($target_type) + { + } + /** + * @param int $lacingtype + * + * @return string|int + */ + public static function BlockLacingType($lacingtype) + { + } + /** + * @param string $codecid + * + * @return string + */ + public static function CodecIDtoCommonName($codecid) + { + } + /** + * @param int $value + * + * @return string + */ + public static function displayUnit($value) + { + } + } + // needed for ISO 639-2 language code lookup + class getid3_quicktime extends \getid3_handler + { + /** audio-video.quicktime + * return all parsed data from all atoms if true, otherwise just returned parsed metadata + * + * @var bool + */ + public $ReturnAtomData = \false; + /** audio-video.quicktime + * return all parsed data from all atoms if true, otherwise just returned parsed metadata + * + * @var bool + */ + public $ParseAllPossibleAtoms = \false; + /** + * @return bool + */ + public function Analyze() + { + } + /** + * @param string $atomname + * @param int $atomsize + * @param string $atom_data + * @param int $baseoffset + * @param array $atomHierarchy + * @param bool $ParseAllPossibleAtoms + * + * @return array|false + */ + public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) + { + } + /** + * @param string $atom_data + * @param int $baseoffset + * @param array $atomHierarchy + * @param bool $ParseAllPossibleAtoms + * + * @return array|false + */ + public function QuicktimeParseContainerAtom($atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) + { + } + /** + * @param string $data + * @param int $offset + * + * @return int + */ + public function quicktime_read_mp4_descr_length($data, &$offset) + { + } + /** + * @param int $languageid + * + * @return string + */ + public function QuicktimeLanguageLookup($languageid) + { + } + /** + * @param string $codecid + * + * @return string + */ + public function QuicktimeVideoCodecLookup($codecid) + { + } + /** + * @param string $codecid + * + * @return mixed|string + */ + public function QuicktimeAudioCodecLookup($codecid) + { + } + /** + * @param string $compressionid + * + * @return string + */ + public function QuicktimeDCOMLookup($compressionid) + { + } + /** + * @param int $colordepthid + * + * @return string + */ + public function QuicktimeColorNameLookup($colordepthid) + { + } + /** + * @param int $stik + * + * @return string + */ + public function QuicktimeSTIKLookup($stik) + { + } + /** + * @param int $audio_profile_id + * + * @return string + */ + public function QuicktimeIODSaudioProfileName($audio_profile_id) + { + } + /** + * @param int $video_profile_id + * + * @return string + */ + public function QuicktimeIODSvideoProfileName($video_profile_id) + { + } + /** + * @param int $rtng + * + * @return string + */ + public function QuicktimeContentRatingLookup($rtng) + { + } + /** + * @param int $akid + * + * @return string + */ + public function QuicktimeStoreAccountTypeLookup($akid) + { + } + /** + * @param int $sfid + * + * @return string + */ + public function QuicktimeStoreFrontCodeLookup($sfid) + { + } + /** + * @param string $keyname + * @param string|array $data + * @param string $boxname + * + * @return bool + */ + public function CopyToAppropriateCommentsSection($keyname, $data, $boxname = '') + { + } + /** + * @param string $lstring + * @param int $count + * + * @return string + */ + public function LociString($lstring, &$count) + { + } + /** + * @param string $nullterminatedstring + * + * @return string + */ + public function NoNullString($nullterminatedstring) + { + } + /** + * @param string $pascalstring + * + * @return string + */ + public function Pascal2String($pascalstring) + { + } + /** + * @param string $pascalstring + * + * @return string + */ + public function MaybePascal2String($pascalstring) + { + } + /** + * Helper functions for m4b audiobook chapters + * code by Steffen Hartmann 2015-Nov-08. + * + * @param array $info + * @param string $tag + * @param string $history + * @param array $result + */ + public function search_tag_by_key($info, $tag, $history, &$result) + { + } + /** + * @param array $info + * @param string $k + * @param string $v + * @param string $history + * @param array $result + */ + public function search_tag_by_pair($info, $k, $v, $history, &$result) + { + } + /** + * @param array $info + * + * @return array + */ + public function quicktime_time_to_sample_table($info) + { + } + /** + * @param array $info + * + * @return int + */ + public function quicktime_bookmark_time_scale($info) + { + } + /* + // END helper functions for m4b audiobook chapters + */ + } + class getid3_riff extends \getid3_handler + { + protected $container = 'riff'; + // default + /** + * @return bool + * + * @throws getid3_exception + */ + public function Analyze() + { + } + /** + * @param int $startoffset + * @param int $maxoffset + * + * @return array|false + * + * @throws Exception + * @throws getid3_exception + */ + public function ParseRIFFAMV($startoffset, $maxoffset) + { + } + /** + * @param int $startoffset + * @param int $maxoffset + * + * @return array|false + * @throws getid3_exception + */ + public function ParseRIFF($startoffset, $maxoffset) + { + } + /** + * @param string $RIFFdata + * + * @return bool + */ + public function ParseRIFFdata(&$RIFFdata) + { + } + /** + * @param array $RIFFinfoArray + * @param array $CommentsTargetArray + * + * @return bool + */ + public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) + { + } + /** + * @param string $WaveFormatExData + * + * @return array + */ + public static function parseWAVEFORMATex($WaveFormatExData) + { + } + /** + * @param string $WavPackChunkData + * + * @return bool + */ + public function parseWavPackHeader($WavPackChunkData) + { + } + /** + * @param string $BITMAPINFOHEADER + * @param bool $littleEndian + * + * @return array + */ + public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian = \true) + { + } + /** + * @param string $DIVXTAG + * @param bool $raw + * + * @return array + */ + public static function ParseDIVXTAG($DIVXTAG, $raw = \false) + { + } + /** + * @param string $tagshortname + * + * @return string + */ + public static function waveSNDMtagLookup($tagshortname) + { + } + /** + * @param int $wFormatTag + * + * @return string + */ + public static function wFormatTagLookup($wFormatTag) + { + } + /** + * @param string $fourcc + * + * @return string + */ + public static function fourccLookup($fourcc) + { + } + } + class getid3_ac3 extends \getid3_handler + { + const syncword = 0xb77; + /** + * @return bool + */ + public function Analyze() + { + } + /** + * @param int $fscod + * + * @return int|string|false + */ + public static function sampleRateCodeLookup($fscod) + { + } + /** + * @param int $fscod2 + * + * @return int|string|false + */ + public static function sampleRateCodeLookup2($fscod2) + { + } + /** + * @param int $bsmod + * @param int $acmod + * + * @return string|false + */ + public static function serviceTypeLookup($bsmod, $acmod) + { + } + /** + * @param int $acmod + * + * @return array|false + */ + public static function audioCodingModeLookup($acmod) + { + } + /** + * @param int $cmixlev + * + * @return int|float|string|false + */ + public static function centerMixLevelLookup($cmixlev) + { + } + /** + * @param int $surmixlev + * + * @return int|float|string|false + */ + public static function surroundMixLevelLookup($surmixlev) + { + } + /** + * @param int $dsurmod + * + * @return string|false + */ + public static function dolbySurroundModeLookup($dsurmod) + { + } + /** + * @param int $acmod + * @param bool $lfeon + * + * @return array + */ + public static function channelsEnabledLookup($acmod, $lfeon) + { + } + /** + * @param int $compre + * + * @return float|int + */ + public static function heavyCompression($compre) + { + } + /** + * @param int $roomtyp + * + * @return string|false + */ + public static function roomTypeLookup($roomtyp) + { + } + /** + * @param int $frmsizecod + * @param int $fscod + * + * @return int|false + */ + public static function frameSizeLookup($frmsizecod, $fscod) + { + } + /** + * @param int $frmsizecod + * + * @return int|false + */ + public static function bitrateLookup($frmsizecod) + { + } + /** + * @param int $numblkscod + * + * @return int|false + */ + public static function blocksPerSyncFrame($numblkscod) + { + } + } + /** + * @tutorial http://wiki.multimedia.cx/index.php?title=DTS + */ + class getid3_dts extends \getid3_handler + { + /** + * Default DTS syncword used in native .cpt or .dts formats. + */ + const syncword = "\xfe\x80\x01"; + /** + * Possible syncwords indicating bitstream encoding. + */ + public static $syncwords = array( + 0 => "\xfe\x80\x01", + // raw big-endian + 1 => "\xfe\x01\x80", + // raw little-endian + 2 => "\x1f\xff\xe8\x00", + // 14-bit big-endian + 3 => "\xff\x1f\x00\xe8", + ); + // 14-bit little-endian + /** + * @return bool + */ + public function Analyze() + { + } + /** + * @param int $index + * + * @return int|string|false + */ + public static function bitrateLookup($index) + { + } + /** + * @param int $index + * + * @return int|string|false + */ + public static function sampleRateLookup($index) + { + } + /** + * @param int $index + * + * @return int|false + */ + public static function bitPerSampleLookup($index) + { + } + /** + * @param int $index + * + * @return int|false + */ + public static function numChannelsLookup($index) + { + } + /** + * @param int $index + * + * @return string + */ + public static function channelArrangementLookup($index) + { + } + /** + * @param int $index + * @param int $version + * + * @return int|false + */ + public static function dialogNormalization($index, $version) + { + } + } + /** + * @tutorial http://flac.sourceforge.net/format.html + */ + class getid3_flac extends \getid3_handler + { + const syncword = 'fLaC'; + /** + * @return bool + */ + public function Analyze() + { + } + /** + * @return bool + */ + public function parseMETAdata() + { + } + /** + * @param string $BlockData + * + * @return array + */ + public static function parseSTREAMINFOdata($BlockData) + { + } + /** + * Parse METADATA_BLOCK_PICTURE flac structure and extract attachment + * External usage: audio.ogg + * + * @return bool + */ + public function parsePICTURE() + { + } + /** + * @param int $blocktype + * + * @return string + */ + public static function metaBlockTypeLookup($blocktype) + { + } + /** + * @param int $applicationid + * + * @return string + */ + public static function applicationIDLookup($applicationid) + { + } + /** + * @param int $type_id + * + * @return string + */ + public static function pictureTypeLookup($type_id) + { + } + } + class getid3_mp3 extends \getid3_handler + { + /** + * Forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow, + * unrecommended, but may provide data from otherwise-unusable files. + * + * @var bool + */ + public $allow_bruteforce = \false; + /** + * number of frames to scan to determine if MPEG-audio sequence is valid + * Lower this number to 5-20 for faster scanning + * Increase this number to 50+ for most accurate detection of valid VBR/CBR mpeg-audio streams + * + * @var int + */ + public $mp3_valid_check_frames = 50; + /** + * @return bool + */ + public function Analyze() + { + } + /** + * @return string + */ + public function GuessEncoderOptions() + { + } + /** + * @param int $offset + * @param array $info + * @param bool $recursivesearch + * @param bool $ScanAsCBR + * @param bool $FastMPEGheaderScan + * + * @return bool + */ + public function decodeMPEGaudioHeader($offset, &$info, $recursivesearch = \true, $ScanAsCBR = \false, $FastMPEGheaderScan = \false) + { + } + /** + * @param int $offset + * @param int $nextframetestoffset + * @param bool $ScanAsCBR + * + * @return bool + */ + public function RecursiveFrameScanning(&$offset, &$nextframetestoffset, $ScanAsCBR) + { + } + /** + * @param int $offset + * @param bool $deepscan + * + * @return int|false + */ + public function FreeFormatFrameLength($offset, $deepscan = \false) + { + } + /** + * @return bool + */ + public function getOnlyMPEGaudioInfoBruteForce() + { + } + /** + * @param int $avdataoffset + * @param bool $BitrateHistogram + * + * @return bool + */ + public function getOnlyMPEGaudioInfo($avdataoffset, $BitrateHistogram = \false) + { + } + /** + * @return array + */ + public static function MPEGaudioVersionArray() + { + } + /** + * @return array + */ + public static function MPEGaudioLayerArray() + { + } + /** + * @return array + */ + public static function MPEGaudioBitrateArray() + { + } + /** + * @return array + */ + public static function MPEGaudioFrequencyArray() + { + } + /** + * @return array + */ + public static function MPEGaudioChannelModeArray() + { + } + /** + * @return array + */ + public static function MPEGaudioModeExtensionArray() + { + } + /** + * @return array + */ + public static function MPEGaudioEmphasisArray() + { + } + /** + * @param string $head4 + * @param bool $allowBitrate15 + * + * @return bool + */ + public static function MPEGaudioHeaderBytesValid($head4, $allowBitrate15 = \false) + { + } + /** + * @param array $rawarray + * @param bool $echoerrors + * @param bool $allowBitrate15 + * + * @return bool + */ + public static function MPEGaudioHeaderValid($rawarray, $echoerrors = \false, $allowBitrate15 = \false) + { + } + /** + * @param string $Header4Bytes + * + * @return array|false + */ + public static function MPEGaudioHeaderDecode($Header4Bytes) + { + } + /** + * @param int|string $bitrate + * @param string $version + * @param string $layer + * @param bool $padding + * @param int $samplerate + * + * @return int|false + */ + public static function MPEGaudioFrameLength(&$bitrate, &$version, &$layer, $padding, &$samplerate) + { + } + /** + * @param float|int $bit_rate + * + * @return int|float|string + */ + public static function ClosestStandardMP3Bitrate($bit_rate) + { + } + /** + * @param string $version + * @param string $channelmode + * + * @return int + */ + public static function XingVBRidOffset($version, $channelmode) + { + } + /** + * @param int $VBRmethodID + * + * @return string + */ + public static function LAMEvbrMethodLookup($VBRmethodID) + { + } + /** + * @param int $StereoModeID + * + * @return string + */ + public static function LAMEmiscStereoModeLookup($StereoModeID) + { + } + /** + * @param int $SourceSampleFrequencyID + * + * @return string + */ + public static function LAMEmiscSourceSampleFrequencyLookup($SourceSampleFrequencyID) + { + } + /** + * @param int $SurroundInfoID + * + * @return string + */ + public static function LAMEsurroundInfoLookup($SurroundInfoID) + { + } + /** + * @param array $LAMEtag + * + * @return string + */ + public static function LAMEpresetUsedLookup($LAMEtag) + { + } + } + class getid3_ogg extends \getid3_handler + { + /** + * @link http://xiph.org/vorbis/doc/Vorbis_I_spec.html + * + * @return bool + */ + public function Analyze() + { + } + /** + * @param string $filedata + * @param int $filedataoffset + * @param array $oggpageinfo + * + * @return bool + */ + public function ParseVorbisPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) + { + } + /** + * @link http://tools.ietf.org/html/draft-ietf-codec-oggopus-03 + * + * @param string $filedata + * @param int $filedataoffset + * @param array $oggpageinfo + * + * @return bool + */ + public function ParseOpusPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) + { + } + /** + * @return array|false + */ + public function ParseOggPageHeader() + { + } + /** + * @link http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810005 + * + * @return bool + */ + public function ParseVorbisComments() + { + } + /** + * @param int $mode + * + * @return string|null + */ + public static function SpeexBandModeLookup($mode) + { + } + /** + * @param array $OggInfoArray + * @param int $SegmentNumber + * + * @return int + */ + public static function OggPageSegmentLength($OggInfoArray, $SegmentNumber = 1) + { + } + /** + * @param int $nominal_bitrate + * + * @return float + */ + public static function get_quality_from_nominal_bitrate($nominal_bitrate) + { + } + /** + * @param int $colorspace_id + * + * @return string|null + */ + public static function TheoraColorSpace($colorspace_id) + { + } + /** + * @param int $pixelformat_id + * + * @return string|null + */ + public static function TheoraPixelFormat($pixelformat_id) + { + } + } + class getid3_apetag extends \getid3_handler + { + /** + * true: return full data for all attachments; + * false: return no data for all attachments; + * integer: return data for attachments <= than this; + * string: save as file to this directory. + * + * @var int|bool|string + */ + public $inline_attachments = \true; + public $overrideendoffset = 0; + /** + * @return bool + */ + public function Analyze() + { + } + /** + * @param string $APEheaderFooterData + * + * @return array|false + */ + public function parseAPEheaderFooter($APEheaderFooterData) + { + } + /** + * @param int $rawflagint + * + * @return array + */ + public function parseAPEtagFlags($rawflagint) + { + } + /** + * @param int $contenttypeid + * + * @return string + */ + public function APEcontentTypeFlagLookup($contenttypeid) + { + } + /** + * @param string $itemkey + * + * @return bool + */ + public function APEtagItemIsUTF8Lookup($itemkey) + { + } + } + class getid3_id3v1 extends \getid3_handler + { + /** + * @return bool + */ + public function Analyze() + { + } + /** + * @param string $str + * + * @return string + */ + public static function cutfield($str) + { + } + /** + * @param bool $allowSCMPXextended + * + * @return string[] + */ + public static function ArrayOfGenres($allowSCMPXextended = \false) + { + } + /** + * @param string $genreid + * @param bool $allowSCMPXextended + * + * @return string|false + */ + public static function LookupGenreName($genreid, $allowSCMPXextended = \true) + { + } + /** + * @param string $genre + * @param bool $allowSCMPXextended + * + * @return string|false + */ + public static function LookupGenreID($genre, $allowSCMPXextended = \false) + { + } + /** + * @param string $OriginalGenre + * + * @return string|false + */ + public static function StandardiseID3v1GenreName($OriginalGenre) + { + } + /** + * @param string $title + * @param string $artist + * @param string $album + * @param string $year + * @param int $genreid + * @param string $comment + * @param int|string $track + * + * @return string + */ + public static function GenerateID3v1Tag($title, $artist, $album, $year, $genreid, $comment, $track = '') + { + } + } + class getid3_id3v2 extends \getid3_handler + { + public $StartingOffset = 0; + /** + * @return bool + */ + public function Analyze() + { + } + /** + * @param string $genrestring + * + * @return array + */ + public function ParseID3v2GenreString($genrestring) + { + } + /** + * @param array $parsedFrame + * + * @return bool + */ + public function ParseID3v2Frame(&$parsedFrame) + { + } + /** + * @param string $data + * + * @return string + */ + public function DeUnsynchronise($data) + { + } + /** + * @param int $index + * + * @return string + */ + public function LookupExtendedHeaderRestrictionsTagSizeLimits($index) + { + } + /** + * @param int $index + * + * @return string + */ + public function LookupExtendedHeaderRestrictionsTextEncodings($index) + { + } + /** + * @param int $index + * + * @return string + */ + public function LookupExtendedHeaderRestrictionsTextFieldSize($index) + { + } + /** + * @param int $index + * + * @return string + */ + public function LookupExtendedHeaderRestrictionsImageEncoding($index) + { + } + /** + * @param int $index + * + * @return string + */ + public function LookupExtendedHeaderRestrictionsImageSizeSize($index) + { + } + /** + * @param string $currencyid + * + * @return string + */ + public function LookupCurrencyUnits($currencyid) + { + } + /** + * @param string $currencyid + * + * @return string + */ + public function LookupCurrencyCountry($currencyid) + { + } + /** + * @param string $languagecode + * @param bool $casesensitive + * + * @return string + */ + public static function LanguageLookup($languagecode, $casesensitive = \false) + { + } + /** + * @param int $index + * + * @return string + */ + public static function ETCOEventLookup($index) + { + } + /** + * @param int $index + * + * @return string + */ + public static function SYTLContentTypeLookup($index) + { + } + /** + * @param int $index + * @param bool $returnarray + * + * @return array|string + */ + public static function APICPictureTypeLookup($index, $returnarray = \false) + { + } + /** + * @param int $index + * + * @return string + */ + public static function COMRReceivedAsLookup($index) + { + } + /** + * @param int $index + * + * @return string + */ + public static function RVA2ChannelTypeLookup($index) + { + } + /** + * @param string $framename + * + * @return string + */ + public static function FrameNameLongLookup($framename) + { + } + /** + * @param string $framename + * + * @return string + */ + public static function FrameNameShortLookup($framename) + { + } + /** + * @param string $encoding + * + * @return string + */ + public static function TextEncodingTerminatorLookup($encoding) + { + } + /** + * @param int $encoding + * + * @return string + */ + public static function TextEncodingNameLookup($encoding) + { + } + /** + * @param string $string + * @param string $terminator + * + * @return string + */ + public static function RemoveStringTerminator($string, $terminator) + { + } + /** + * @param string $string + * + * @return string + */ + public static function MakeUTF16emptyStringEmpty($string) + { + } + /** + * @param string $framename + * @param int $id3v2majorversion + * + * @return bool|int + */ + public static function IsValidID3v2FrameName($framename, $id3v2majorversion) + { + } + /** + * @param string $numberstring + * @param bool $allowdecimal + * @param bool $allownegative + * + * @return bool + */ + public static function IsANumber($numberstring, $allowdecimal = \false, $allownegative = \false) + { + } + /** + * @param string $datestamp + * + * @return bool + */ + public static function IsValidDateStampString($datestamp) + { + } + /** + * @param int $majorversion + * + * @return int + */ + public static function ID3v2HeaderLength($majorversion) + { + } + /** + * @param string $frame_name + * + * @return string|false + */ + public static function ID3v22iTunesBrokenFrameName($frame_name) + { + } + } + class getid3_lyrics3 extends \getid3_handler + { + /** + * @return bool + */ + public function Analyze() + { + } + /** + * @param int $endoffset + * @param int $version + * @param int $length + * + * @return bool + */ + public function getLyrics3Data($endoffset, $version, $length) + { + } + /** + * @param string $rawtimestamp + * + * @return int|false + */ + public function Lyrics3Timestamp2Seconds($rawtimestamp) + { + } + /** + * @param array $Lyrics3data + * + * @return bool + */ + public function Lyrics3LyricsTimestampParse(&$Lyrics3data) + { + } + /** + * @param string $char + * + * @return bool|null + */ + public function IntString2Bool($char) + { + } + } + /** + * IXR_Base64 + * + * @package IXR + * @since 1.5.0 + */ + class IXR_Base64 + { + var $data; + /** + * PHP5 constructor. + */ + function __construct($data) + { + } + /** + * PHP4 constructor. + */ + public function IXR_Base64($data) + { + } + function getXml() + { + } + } + /** + * IXR_Client + * + * @package IXR + * @since 1.5.0 + * + */ + class IXR_Client + { + var $server; + var $port; + var $path; + var $useragent; + var $response; + var $message = \false; + var $debug = \false; + var $timeout; + var $headers = array(); + // Storage place for an error message + var $error = \false; + /** + * PHP5 constructor. + */ + function __construct($server, $path = \false, $port = 80, $timeout = 15) + { + } + /** + * PHP4 constructor. + */ + public function IXR_Client($server, $path = \false, $port = 80, $timeout = 15) + { + } + /** + * @since 1.5.0 + * @since 5.5.0 Formalized the existing `...$args` parameter by adding it + * to the function signature. + * + * @return bool + */ + function query(...$args) + { + } + function getResponse() + { + } + function isError() + { + } + function getErrorCode() + { + } + function getErrorMessage() + { + } + } + /** + * IXR_ClientMulticall + * + * @package IXR + * @since 1.5.0 + */ + class IXR_ClientMulticall extends \IXR_Client + { + var $calls = array(); + /** + * PHP5 constructor. + */ + function __construct($server, $path = \false, $port = 80) + { + } + /** + * PHP4 constructor. + */ + public function IXR_ClientMulticall($server, $path = \false, $port = 80) + { + } + /** + * @since 1.5.0 + * @since 5.5.0 Formalized the existing `...$args` parameter by adding it + * to the function signature. + */ + function addCall(...$args) + { + } + /** + * @since 1.5.0 + * @since 5.5.0 Formalized the existing `...$args` parameter by adding it + * to the function signature. + * + * @return bool + */ + function query(...$args) + { + } + } + /** + * IXR_Date + * + * @package IXR + * @since 1.5.0 + */ + class IXR_Date + { + var $year; + var $month; + var $day; + var $hour; + var $minute; + var $second; + var $timezone; + /** + * PHP5 constructor. + */ + function __construct($time) + { + } + /** + * PHP4 constructor. + */ + public function IXR_Date($time) + { + } + function parseTimestamp($timestamp) + { + } + function parseIso($iso) + { + } + function getIso() + { + } + function getXml() + { + } + function getTimestamp() + { + } + } + /** + * IXR_Error + * + * @package IXR + * @since 1.5.0 + */ + class IXR_Error + { + var $code; + var $message; + /** + * PHP5 constructor. + */ + function __construct($code, $message) + { + } + /** + * PHP4 constructor. + */ + public function IXR_Error($code, $message) + { + } + function getXml() + { + } + } + /** + * IXR_Server + * + * @package IXR + * @since 1.5.0 + */ + class IXR_Server + { + var $data; + var $callbacks = array(); + var $message; + var $capabilities; + /** + * PHP5 constructor. + */ + function __construct($callbacks = \false, $data = \false, $wait = \false) + { + } + /** + * PHP4 constructor. + */ + public function IXR_Server($callbacks = \false, $data = \false, $wait = \false) + { + } + function serve($data = \false) + { + } + function call($methodname, $args) + { + } + function error($error, $message = \false) + { + } + function output($xml) + { + } + function hasMethod($method) + { + } + function setCapabilities() + { + } + function getCapabilities($args) + { + } + function setCallbacks() + { + } + function listMethods($args) + { + } + function multiCall($methodcalls) + { + } + } + /** + * IXR_IntrospectionServer + * + * @package IXR + * @since 1.5.0 + */ + class IXR_IntrospectionServer extends \IXR_Server + { + var $signatures; + var $help; + /** + * PHP5 constructor. + */ + function __construct() + { + } + /** + * PHP4 constructor. + */ + public function IXR_IntrospectionServer() + { + } + function addCallback($method, $callback, $args, $help) + { + } + function call($methodname, $args) + { + } + function methodSignature($method) + { + } + function methodHelp($method) + { + } + } + /** + * IXR_MESSAGE + * + * @package IXR + * @since 1.5.0 + * + */ + class IXR_Message + { + var $message = \false; + var $messageType = \false; + // methodCall / methodResponse / fault + var $faultCode = \false; + var $faultString = \false; + var $methodName = ''; + var $params = array(); + // Current variable stacks + var $_arraystructs = array(); + // The stack used to keep track of the current array/struct + var $_arraystructstypes = array(); + // Stack keeping track of if things are structs or array + var $_currentStructName = array(); + // A stack as well + var $_param; + var $_value; + var $_currentTag; + var $_currentTagContents; + // The XML parser + var $_parser; + /** + * PHP5 constructor. + */ + function __construct($message) + { + } + /** + * PHP4 constructor. + */ + public function IXR_Message($message) + { + } + function parse() + { + } + function tag_open($parser, $tag, $attr) + { + } + function cdata($parser, $cdata) + { + } + function tag_close($parser, $tag) + { + } + } + /** + * IXR_Request + * + * @package IXR + * @since 1.5.0 + */ + class IXR_Request + { + var $method; + var $args; + var $xml; + /** + * PHP5 constructor. + */ + function __construct($method, $args) + { + } + /** + * PHP4 constructor. + */ + public function IXR_Request($method, $args) + { + } + function getLength() + { + } + function getXml() + { + } + } + /** + * IXR_Value + * + * @package IXR + * @since 1.5.0 + */ + class IXR_Value + { + var $data; + var $type; + /** + * PHP5 constructor. + */ + function __construct($data, $type = \false) + { + } + /** + * PHP4 constructor. + */ + public function IXR_Value($data, $type = \false) + { + } + function calculateType() + { + } + function getXml() + { + } + /** + * Checks whether or not the supplied array is a struct or not + * + * @param array $array + * @return bool + */ + function isStruct($array) + { + } + } +} +namespace PHPMailer\PHPMailer { + /** + * PHPMailer exception handler. + * + * @author Marcus Bointon + */ + class Exception extends \Exception + { + /** + * Prettify error message output. + * + * @return string + */ + public function errorMessage() + { + } + } + /** + * PHPMailer - PHP email creation and transport class. + * + * @author Marcus Bointon (Synchro/coolbru) + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + */ + class PHPMailer + { + const CHARSET_ASCII = 'us-ascii'; + const CHARSET_ISO88591 = 'iso-8859-1'; + const CHARSET_UTF8 = 'utf-8'; + const CONTENT_TYPE_PLAINTEXT = 'text/plain'; + const CONTENT_TYPE_TEXT_CALENDAR = 'text/calendar'; + const CONTENT_TYPE_TEXT_HTML = 'text/html'; + const CONTENT_TYPE_MULTIPART_ALTERNATIVE = 'multipart/alternative'; + const CONTENT_TYPE_MULTIPART_MIXED = 'multipart/mixed'; + const CONTENT_TYPE_MULTIPART_RELATED = 'multipart/related'; + const ENCODING_7BIT = '7bit'; + const ENCODING_8BIT = '8bit'; + const ENCODING_BASE64 = 'base64'; + const ENCODING_BINARY = 'binary'; + const ENCODING_QUOTED_PRINTABLE = 'quoted-printable'; + const ENCRYPTION_STARTTLS = 'tls'; + const ENCRYPTION_SMTPS = 'ssl'; + const ICAL_METHOD_REQUEST = 'REQUEST'; + const ICAL_METHOD_PUBLISH = 'PUBLISH'; + const ICAL_METHOD_REPLY = 'REPLY'; + const ICAL_METHOD_ADD = 'ADD'; + const ICAL_METHOD_CANCEL = 'CANCEL'; + const ICAL_METHOD_REFRESH = 'REFRESH'; + const ICAL_METHOD_COUNTER = 'COUNTER'; + const ICAL_METHOD_DECLINECOUNTER = 'DECLINECOUNTER'; + /** + * Email priority. + * Options: null (default), 1 = High, 3 = Normal, 5 = low. + * When null, the header is not set at all. + * + * @var int|null + */ + public $Priority; + /** + * The character set of the message. + * + * @var string + */ + public $CharSet = self::CHARSET_ISO88591; + /** + * The MIME Content-type of the message. + * + * @var string + */ + public $ContentType = self::CONTENT_TYPE_PLAINTEXT; + /** + * The message encoding. + * Options: "8bit", "7bit", "binary", "base64", and "quoted-printable". + * + * @var string + */ + public $Encoding = self::ENCODING_8BIT; + /** + * Holds the most recent mailer error message. + * + * @var string + */ + public $ErrorInfo = ''; + /** + * The From email address for the message. + * + * @var string + */ + public $From = ''; + /** + * The From name of the message. + * + * @var string + */ + public $FromName = ''; + /** + * The envelope sender of the message. + * This will usually be turned into a Return-Path header by the receiver, + * and is the address that bounces will be sent to. + * If not empty, will be passed via `-f` to sendmail or as the 'MAIL FROM' value over SMTP. + * + * @var string + */ + public $Sender = ''; + /** + * The Subject of the message. + * + * @var string + */ + public $Subject = ''; + /** + * An HTML or plain text message body. + * If HTML then call isHTML(true). + * + * @var string + */ + public $Body = ''; + /** + * The plain-text message body. + * This body can be read by mail clients that do not have HTML email + * capability such as mutt & Eudora. + * Clients that can read HTML will view the normal Body. + * + * @var string + */ + public $AltBody = ''; + /** + * An iCal message part body. + * Only supported in simple alt or alt_inline message types + * To generate iCal event structures, use classes like EasyPeasyICS or iCalcreator. + * + * @see http://sprain.ch/blog/downloads/php-class-easypeasyics-create-ical-files-with-php/ + * @see http://kigkonsult.se/iCalcreator/ + * + * @var string + */ + public $Ical = ''; + /** + * Value-array of "method" in Contenttype header "text/calendar" + * + * @var string[] + */ + protected static $IcalMethods = [self::ICAL_METHOD_REQUEST, self::ICAL_METHOD_PUBLISH, self::ICAL_METHOD_REPLY, self::ICAL_METHOD_ADD, self::ICAL_METHOD_CANCEL, self::ICAL_METHOD_REFRESH, self::ICAL_METHOD_COUNTER, self::ICAL_METHOD_DECLINECOUNTER]; + /** + * The complete compiled MIME message body. + * + * @var string + */ + protected $MIMEBody = ''; + /** + * The complete compiled MIME message headers. + * + * @var string + */ + protected $MIMEHeader = ''; + /** + * Extra headers that createHeader() doesn't fold in. + * + * @var string + */ + protected $mailHeader = ''; + /** + * Word-wrap the message body to this number of chars. + * Set to 0 to not wrap. A useful value here is 78, for RFC2822 section 2.1.1 compliance. + * + * @see static::STD_LINE_LENGTH + * + * @var int + */ + public $WordWrap = 0; + /** + * Which method to use to send mail. + * Options: "mail", "sendmail", or "smtp". + * + * @var string + */ + public $Mailer = 'mail'; + /** + * The path to the sendmail program. + * + * @var string + */ + public $Sendmail = '/usr/sbin/sendmail'; + /** + * Whether mail() uses a fully sendmail-compatible MTA. + * One which supports sendmail's "-oi -f" options. + * + * @var bool + */ + public $UseSendmailOptions = true; + /** + * The email address that a reading confirmation should be sent to, also known as read receipt. + * + * @var string + */ + public $ConfirmReadingTo = ''; + /** + * The hostname to use in the Message-ID header and as default HELO string. + * If empty, PHPMailer attempts to find one with, in order, + * $_SERVER['SERVER_NAME'], gethostname(), php_uname('n'), or the value + * 'localhost.localdomain'. + * + * @see PHPMailer::$Helo + * + * @var string + */ + public $Hostname = ''; + /** + * An ID to be used in the Message-ID header. + * If empty, a unique id will be generated. + * You can set your own, but it must be in the format "", + * as defined in RFC5322 section 3.6.4 or it will be ignored. + * + * @see https://tools.ietf.org/html/rfc5322#section-3.6.4 + * + * @var string + */ + public $MessageID = ''; + /** + * The message Date to be used in the Date header. + * If empty, the current date will be added. + * + * @var string + */ + public $MessageDate = ''; + /** + * SMTP hosts. + * Either a single hostname or multiple semicolon-delimited hostnames. + * You can also specify a different port + * for each host by using this format: [hostname:port] + * (e.g. "smtp1.example.com:25;smtp2.example.com"). + * You can also specify encryption type, for example: + * (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465"). + * Hosts will be tried in order. + * + * @var string + */ + public $Host = 'localhost'; + /** + * The default SMTP server port. + * + * @var int + */ + public $Port = 25; + /** + * The SMTP HELO/EHLO name used for the SMTP connection. + * Default is $Hostname. If $Hostname is empty, PHPMailer attempts to find + * one with the same method described above for $Hostname. + * + * @see PHPMailer::$Hostname + * + * @var string + */ + public $Helo = ''; + /** + * What kind of encryption to use on the SMTP connection. + * Options: '', static::ENCRYPTION_STARTTLS, or static::ENCRYPTION_SMTPS. + * + * @var string + */ + public $SMTPSecure = ''; + /** + * Whether to enable TLS encryption automatically if a server supports it, + * even if `SMTPSecure` is not set to 'tls'. + * Be aware that in PHP >= 5.6 this requires that the server's certificates are valid. + * + * @var bool + */ + public $SMTPAutoTLS = true; + /** + * Whether to use SMTP authentication. + * Uses the Username and Password properties. + * + * @see PHPMailer::$Username + * @see PHPMailer::$Password + * + * @var bool + */ + public $SMTPAuth = false; + /** + * Options array passed to stream_context_create when connecting via SMTP. + * + * @var array + */ + public $SMTPOptions = []; + /** + * SMTP username. + * + * @var string + */ + public $Username = ''; + /** + * SMTP password. + * + * @var string + */ + public $Password = ''; + /** + * SMTP authentication type. Options are CRAM-MD5, LOGIN, PLAIN, XOAUTH2. + * If not specified, the first one from that list that the server supports will be selected. + * + * @var string + */ + public $AuthType = ''; + /** + * An implementation of the PHPMailer OAuthTokenProvider interface. + * + * @var OAuthTokenProvider + */ + protected $oauth; + /** + * The SMTP server timeout in seconds. + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2. + * + * @var int + */ + public $Timeout = 300; + /** + * Comma separated list of DSN notifications + * 'NEVER' under no circumstances a DSN must be returned to the sender. + * If you use NEVER all other notifications will be ignored. + * 'SUCCESS' will notify you when your mail has arrived at its destination. + * 'FAILURE' will arrive if an error occurred during delivery. + * 'DELAY' will notify you if there is an unusual delay in delivery, but the actual + * delivery's outcome (success or failure) is not yet decided. + * + * @see https://tools.ietf.org/html/rfc3461 See section 4.1 for more information about NOTIFY + */ + public $dsn = ''; + /** + * SMTP class debug output mode. + * Debug output level. + * Options: + * @see SMTP::DEBUG_OFF: No output + * @see SMTP::DEBUG_CLIENT: Client messages + * @see SMTP::DEBUG_SERVER: Client and server messages + * @see SMTP::DEBUG_CONNECTION: As SERVER plus connection status + * @see SMTP::DEBUG_LOWLEVEL: Noisy, low-level data output, rarely needed + * + * @see SMTP::$do_debug + * + * @var int + */ + public $SMTPDebug = 0; + /** + * How to handle debug output. + * Options: + * * `echo` Output plain-text as-is, appropriate for CLI + * * `html` Output escaped, line breaks converted to `
    `, appropriate for browser output + * * `error_log` Output to error log as configured in php.ini + * By default PHPMailer will use `echo` if run from a `cli` or `cli-server` SAPI, `html` otherwise. + * Alternatively, you can provide a callable expecting two params: a message string and the debug level: + * + * ```php + * $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";}; + * ``` + * + * Alternatively, you can pass in an instance of a PSR-3 compatible logger, though only `debug` + * level output is used: + * + * ```php + * $mail->Debugoutput = new myPsr3Logger; + * ``` + * + * @see SMTP::$Debugoutput + * + * @var string|callable|\Psr\Log\LoggerInterface + */ + public $Debugoutput = 'echo'; + /** + * Whether to keep the SMTP connection open after each message. + * If this is set to true then the connection will remain open after a send, + * and closing the connection will require an explicit call to smtpClose(). + * It's a good idea to use this if you are sending multiple messages as it reduces overhead. + * See the mailing list example for how to use it. + * + * @var bool + */ + public $SMTPKeepAlive = false; + /** + * Whether to split multiple to addresses into multiple messages + * or send them all in one message. + * Only supported in `mail` and `sendmail` transports, not in SMTP. + * + * @var bool + * + * @deprecated 6.0.0 PHPMailer isn't a mailing list manager! + */ + public $SingleTo = false; + /** + * Storage for addresses when SingleTo is enabled. + * + * @var array + */ + protected $SingleToArray = []; + /** + * Whether to generate VERP addresses on send. + * Only applicable when sending via SMTP. + * + * @see https://en.wikipedia.org/wiki/Variable_envelope_return_path + * @see http://www.postfix.org/VERP_README.html Postfix VERP info + * + * @var bool + */ + public $do_verp = false; + /** + * Whether to allow sending messages with an empty body. + * + * @var bool + */ + public $AllowEmpty = false; + /** + * DKIM selector. + * + * @var string + */ + public $DKIM_selector = ''; + /** + * DKIM Identity. + * Usually the email address used as the source of the email. + * + * @var string + */ + public $DKIM_identity = ''; + /** + * DKIM passphrase. + * Used if your key is encrypted. + * + * @var string + */ + public $DKIM_passphrase = ''; + /** + * DKIM signing domain name. + * + * @example 'example.com' + * + * @var string + */ + public $DKIM_domain = ''; + /** + * DKIM Copy header field values for diagnostic use. + * + * @var bool + */ + public $DKIM_copyHeaderFields = true; + /** + * DKIM Extra signing headers. + * + * @example ['List-Unsubscribe', 'List-Help'] + * + * @var array + */ + public $DKIM_extraHeaders = []; + /** + * DKIM private key file path. + * + * @var string + */ + public $DKIM_private = ''; + /** + * DKIM private key string. + * + * If set, takes precedence over `$DKIM_private`. + * + * @var string + */ + public $DKIM_private_string = ''; + /** + * Callback Action function name. + * + * The function that handles the result of the send email action. + * It is called out by send() for each email sent. + * + * Value can be any php callable: http://www.php.net/is_callable + * + * Parameters: + * bool $result result of the send action + * array $to email addresses of the recipients + * array $cc cc email addresses + * array $bcc bcc email addresses + * string $subject the subject + * string $body the email body + * string $from email address of sender + * string $extra extra information of possible use + * "smtp_transaction_id' => last smtp transaction id + * + * @var string + */ + public $action_function = ''; + /** + * What to put in the X-Mailer header. + * Options: An empty string for PHPMailer default, whitespace/null for none, or a string to use. + * + * @var string|null + */ + public $XMailer = ''; + /** + * Which validator to use by default when validating email addresses. + * May be a callable to inject your own validator, but there are several built-in validators. + * The default validator uses PHP's FILTER_VALIDATE_EMAIL filter_var option. + * + * @see PHPMailer::validateAddress() + * + * @var string|callable + */ + public static $validator = 'php'; + /** + * An instance of the SMTP sender class. + * + * @var SMTP + */ + protected $smtp; + /** + * The array of 'to' names and addresses. + * + * @var array + */ + protected $to = []; + /** + * The array of 'cc' names and addresses. + * + * @var array + */ + protected $cc = []; + /** + * The array of 'bcc' names and addresses. + * + * @var array + */ + protected $bcc = []; + /** + * The array of reply-to names and addresses. + * + * @var array + */ + protected $ReplyTo = []; + /** + * An array of all kinds of addresses. + * Includes all of $to, $cc, $bcc. + * + * @see PHPMailer::$to + * @see PHPMailer::$cc + * @see PHPMailer::$bcc + * + * @var array + */ + protected $all_recipients = []; + /** + * An array of names and addresses queued for validation. + * In send(), valid and non duplicate entries are moved to $all_recipients + * and one of $to, $cc, or $bcc. + * This array is used only for addresses with IDN. + * + * @see PHPMailer::$to + * @see PHPMailer::$cc + * @see PHPMailer::$bcc + * @see PHPMailer::$all_recipients + * + * @var array + */ + protected $RecipientsQueue = []; + /** + * An array of reply-to names and addresses queued for validation. + * In send(), valid and non duplicate entries are moved to $ReplyTo. + * This array is used only for addresses with IDN. + * + * @see PHPMailer::$ReplyTo + * + * @var array + */ + protected $ReplyToQueue = []; + /** + * The array of attachments. + * + * @var array + */ + protected $attachment = []; + /** + * The array of custom headers. + * + * @var array + */ + protected $CustomHeader = []; + /** + * The most recent Message-ID (including angular brackets). + * + * @var string + */ + protected $lastMessageID = ''; + /** + * The message's MIME type. + * + * @var string + */ + protected $message_type = ''; + /** + * The array of MIME boundary strings. + * + * @var array + */ + protected $boundary = []; + /** + * The array of available text strings for the current language. + * + * @var array + */ + protected $language = []; + /** + * The number of errors encountered. + * + * @var int + */ + protected $error_count = 0; + /** + * The S/MIME certificate file path. + * + * @var string + */ + protected $sign_cert_file = ''; + /** + * The S/MIME key file path. + * + * @var string + */ + protected $sign_key_file = ''; + /** + * The optional S/MIME extra certificates ("CA Chain") file path. + * + * @var string + */ + protected $sign_extracerts_file = ''; + /** + * The S/MIME password for the key. + * Used only if the key is encrypted. + * + * @var string + */ + protected $sign_key_pass = ''; + /** + * Whether to throw exceptions for errors. + * + * @var bool + */ + protected $exceptions = false; + /** + * Unique ID used for message ID and boundaries. + * + * @var string + */ + protected $uniqueid = ''; + /** + * The PHPMailer Version number. + * + * @var string + */ + const VERSION = '6.6.5'; + /** + * Error severity: message only, continue processing. + * + * @var int + */ + const STOP_MESSAGE = 0; + /** + * Error severity: message, likely ok to continue processing. + * + * @var int + */ + const STOP_CONTINUE = 1; + /** + * Error severity: message, plus full stop, critical error reached. + * + * @var int + */ + const STOP_CRITICAL = 2; + /** + * The SMTP standard CRLF line break. + * If you want to change line break format, change static::$LE, not this. + */ + const CRLF = "\r\n"; + /** + * "Folding White Space" a white space string used for line folding. + */ + const FWS = ' '; + /** + * SMTP RFC standard line ending; Carriage Return, Line Feed. + * + * @var string + */ + protected static $LE = self::CRLF; + /** + * The maximum line length supported by mail(). + * + * Background: mail() will sometimes corrupt messages + * with headers headers longer than 65 chars, see #818. + * + * @var int + */ + const MAIL_MAX_LINE_LENGTH = 63; + /** + * The maximum line length allowed by RFC 2822 section 2.1.1. + * + * @var int + */ + const MAX_LINE_LENGTH = 998; + /** + * The lower maximum line length allowed by RFC 2822 section 2.1.1. + * This length does NOT include the line break + * 76 means that lines will be 77 or 78 chars depending on whether + * the line break format is LF or CRLF; both are valid. + * + * @var int + */ + const STD_LINE_LENGTH = 76; + /** + * Constructor. + * + * @param bool $exceptions Should we throw external exceptions? + */ + public function __construct($exceptions = null) + { + } + /** + * Destructor. + */ + public function __destruct() + { + } + /** + * Output debugging info via a user-defined method. + * Only generates output if debug output is enabled. + * + * @see PHPMailer::$Debugoutput + * @see PHPMailer::$SMTPDebug + * + * @param string $str + */ + protected function edebug($str) + { + } + /** + * Sets message type to HTML or plain. + * + * @param bool $isHtml True for HTML mode + */ + public function isHTML($isHtml = true) + { + } + /** + * Send messages using SMTP. + */ + public function isSMTP() + { + } + /** + * Send messages using PHP's mail() function. + */ + public function isMail() + { + } + /** + * Send messages using $Sendmail. + */ + public function isSendmail() + { + } + /** + * Send messages using qmail. + */ + public function isQmail() + { + } + /** + * Add a "To" address. + * + * @param string $address The email address to send to + * @param string $name + * + * @throws Exception + * + * @return bool true on success, false if address already used or invalid in some way + */ + public function addAddress($address, $name = '') + { + } + /** + * Add a "CC" address. + * + * @param string $address The email address to send to + * @param string $name + * + * @throws Exception + * + * @return bool true on success, false if address already used or invalid in some way + */ + public function addCC($address, $name = '') + { + } + /** + * Add a "BCC" address. + * + * @param string $address The email address to send to + * @param string $name + * + * @throws Exception + * + * @return bool true on success, false if address already used or invalid in some way + */ + public function addBCC($address, $name = '') + { + } + /** + * Add a "Reply-To" address. + * + * @param string $address The email address to reply to + * @param string $name + * + * @throws Exception + * + * @return bool true on success, false if address already used or invalid in some way + */ + public function addReplyTo($address, $name = '') + { + } + /** + * Add an address to one of the recipient arrays or to the ReplyTo array. Because PHPMailer + * can't validate addresses with an IDN without knowing the PHPMailer::$CharSet (that can still + * be modified after calling this function), addition of such addresses is delayed until send(). + * Addresses that have been added already return false, but do not throw exceptions. + * + * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo' + * @param string $address The email address + * @param string $name An optional username associated with the address + * + * @throws Exception + * + * @return bool true on success, false if address already used or invalid in some way + */ + protected function addOrEnqueueAnAddress($kind, $address, $name) + { + } + /** + * Add an address to one of the recipient arrays or to the ReplyTo array. + * Addresses that have been added already return false, but do not throw exceptions. + * + * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo' + * @param string $address The email address to send, resp. to reply to + * @param string $name + * + * @throws Exception + * + * @return bool true on success, false if address already used or invalid in some way + */ + protected function addAnAddress($kind, $address, $name = '') + { + } + /** + * Parse and validate a string containing one or more RFC822-style comma-separated email addresses + * of the form "display name
    " into an array of name/address pairs. + * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available. + * Note that quotes in the name part are removed. + * + * @see http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation + * + * @param string $addrstr The address list string + * @param bool $useimap Whether to use the IMAP extension to parse the list + * @param string $charset The charset to use when decoding the address list string. + * + * @return array + */ + public static function parseAddresses($addrstr, $useimap = true, $charset = self::CHARSET_ISO88591) + { + } + /** + * Set the From and FromName properties. + * + * @param string $address + * @param string $name + * @param bool $auto Whether to also set the Sender address, defaults to true + * + * @throws Exception + * + * @return bool + */ + public function setFrom($address, $name = '', $auto = true) + { + } + /** + * Return the Message-ID header of the last email. + * Technically this is the value from the last time the headers were created, + * but it's also the message ID of the last sent message except in + * pathological cases. + * + * @return string + */ + public function getLastMessageID() + { + } + /** + * Check that a string looks like an email address. + * Validation patterns supported: + * * `auto` Pick best pattern automatically; + * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0; + * * `pcre` Use old PCRE implementation; + * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL; + * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements. + * * `noregex` Don't use a regex: super fast, really dumb. + * Alternatively you may pass in a callable to inject your own validator, for example: + * + * ```php + * PHPMailer::validateAddress('user@example.com', function($address) { + * return (strpos($address, '@') !== false); + * }); + * ``` + * + * You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator. + * + * @param string $address The email address to check + * @param string|callable $patternselect Which pattern to use + * + * @return bool + */ + public static function validateAddress($address, $patternselect = null) + { + } + /** + * Tells whether IDNs (Internationalized Domain Names) are supported or not. This requires the + * `intl` and `mbstring` PHP extensions. + * + * @return bool `true` if required functions for IDN support are present + */ + public static function idnSupported() + { + } + /** + * Converts IDN in given email address to its ASCII form, also known as punycode, if possible. + * Important: Address must be passed in same encoding as currently set in PHPMailer::$CharSet. + * This function silently returns unmodified address if: + * - No conversion is necessary (i.e. domain name is not an IDN, or is already in ASCII form) + * - Conversion to punycode is impossible (e.g. required PHP functions are not available) + * or fails for any reason (e.g. domain contains characters not allowed in an IDN). + * + * @see PHPMailer::$CharSet + * + * @param string $address The email address to convert + * + * @return string The encoded address in ASCII form + */ + public function punyencodeAddress($address) + { + } + /** + * Create a message and send it. + * Uses the sending method specified by $Mailer. + * + * @throws Exception + * + * @return bool false on error - See the ErrorInfo property for details of the error + */ + public function send() + { + } + /** + * Prepare a message for sending. + * + * @throws Exception + * + * @return bool + */ + public function preSend() + { + } + /** + * Actually send a message via the selected mechanism. + * + * @throws Exception + * + * @return bool + */ + public function postSend() + { + } + /** + * Send mail using the $Sendmail program. + * + * @see PHPMailer::$Sendmail + * + * @param string $header The message headers + * @param string $body The message body + * + * @throws Exception + * + * @return bool + */ + protected function sendmailSend($header, $body) + { + } + /** + * Fix CVE-2016-10033 and CVE-2016-10045 by disallowing potentially unsafe shell characters. + * Note that escapeshellarg and escapeshellcmd are inadequate for our purposes, especially on Windows. + * + * @see https://github.com/PHPMailer/PHPMailer/issues/924 CVE-2016-10045 bug report + * + * @param string $string The string to be validated + * + * @return bool + */ + protected static function isShellSafe($string) + { + } + /** + * Check whether a file path is of a permitted type. + * Used to reject URLs and phar files from functions that access local file paths, + * such as addAttachment. + * + * @param string $path A relative or absolute path to a file + * + * @return bool + */ + protected static function isPermittedPath($path) + { + } + /** + * Check whether a file path is safe, accessible, and readable. + * + * @param string $path A relative or absolute path to a file + * + * @return bool + */ + protected static function fileIsAccessible($path) + { + } + /** + * Send mail using the PHP mail() function. + * + * @see http://www.php.net/manual/en/book.mail.php + * + * @param string $header The message headers + * @param string $body The message body + * + * @throws Exception + * + * @return bool + */ + protected function mailSend($header, $body) + { + } + /** + * Get an instance to use for SMTP operations. + * Override this function to load your own SMTP implementation, + * or set one with setSMTPInstance. + * + * @return SMTP + */ + public function getSMTPInstance() + { + } + /** + * Provide an instance to use for SMTP operations. + * + * @return SMTP + */ + public function setSMTPInstance(\PHPMailer\PHPMailer\SMTP $smtp) + { + } + /** + * Send mail via SMTP. + * Returns false if there is a bad MAIL FROM, RCPT, or DATA input. + * + * @see PHPMailer::setSMTPInstance() to use a different class. + * + * @uses \PHPMailer\PHPMailer\SMTP + * + * @param string $header The message headers + * @param string $body The message body + * + * @throws Exception + * + * @return bool + */ + protected function smtpSend($header, $body) + { + } + /** + * Initiate a connection to an SMTP server. + * Returns false if the operation failed. + * + * @param array $options An array of options compatible with stream_context_create() + * + * @throws Exception + * + * @uses \PHPMailer\PHPMailer\SMTP + * + * @return bool + */ + public function smtpConnect($options = null) + { + } + /** + * Close the active SMTP session if one exists. + */ + public function smtpClose() + { + } + /** + * Set the language for error messages. + * The default language is English. + * + * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr") + * Optionally, the language code can be enhanced with a 4-character + * script annotation and/or a 2-character country annotation. + * @param string $lang_path Path to the language file directory, with trailing separator (slash) + * Do not set this from user input! + * + * @return bool Returns true if the requested language was loaded, false otherwise. + */ + public function setLanguage($langcode = 'en', $lang_path = '') + { + } + /** + * Get the array of strings for the current language. + * + * @return array + */ + public function getTranslations() + { + } + /** + * Create recipient headers. + * + * @param string $type + * @param array $addr An array of recipients, + * where each recipient is a 2-element indexed array with element 0 containing an address + * and element 1 containing a name, like: + * [['joe@example.com', 'Joe User'], ['zoe@example.com', 'Zoe User']] + * + * @return string + */ + public function addrAppend($type, $addr) + { + } + /** + * Format an address for use in a message header. + * + * @param array $addr A 2-element indexed array, element 0 containing an address, element 1 containing a name like + * ['joe@example.com', 'Joe User'] + * + * @return string + */ + public function addrFormat($addr) + { + } + /** + * Word-wrap message. + * For use with mailers that do not automatically perform wrapping + * and for quoted-printable encoded messages. + * Original written by philippe. + * + * @param string $message The message to wrap + * @param int $length The line length to wrap to + * @param bool $qp_mode Whether to run in Quoted-Printable mode + * + * @return string + */ + public function wrapText($message, $length, $qp_mode = false) + { + } + /** + * Find the last character boundary prior to $maxLength in a utf-8 + * quoted-printable encoded string. + * Original written by Colin Brown. + * + * @param string $encodedText utf-8 QP text + * @param int $maxLength Find the last character boundary prior to this length + * + * @return int + */ + public function utf8CharBoundary($encodedText, $maxLength) + { + } + /** + * Apply word wrapping to the message body. + * Wraps the message body to the number of chars set in the WordWrap property. + * You should only do this to plain-text bodies as wrapping HTML tags may break them. + * This is called automatically by createBody(), so you don't need to call it yourself. + */ + public function setWordWrap() + { + } + /** + * Assemble message headers. + * + * @return string The assembled headers + */ + public function createHeader() + { + } + /** + * Get the message MIME type headers. + * + * @return string + */ + public function getMailMIME() + { + } + /** + * Returns the whole MIME message. + * Includes complete headers and body. + * Only valid post preSend(). + * + * @see PHPMailer::preSend() + * + * @return string + */ + public function getSentMIMEMessage() + { + } + /** + * Create a unique ID to use for boundaries. + * + * @return string + */ + protected function generateId() + { + } + /** + * Assemble the message body. + * Returns an empty string on failure. + * + * @throws Exception + * + * @return string The assembled message body + */ + public function createBody() + { + } + /** + * Return the start of a message boundary. + * + * @param string $boundary + * @param string $charSet + * @param string $contentType + * @param string $encoding + * + * @return string + */ + protected function getBoundary($boundary, $charSet, $contentType, $encoding) + { + } + /** + * Return the end of a message boundary. + * + * @param string $boundary + * + * @return string + */ + protected function endBoundary($boundary) + { + } + /** + * Set the message type. + * PHPMailer only supports some preset message types, not arbitrary MIME structures. + */ + protected function setMessageType() + { + } + /** + * Format a header line. + * + * @param string $name + * @param string|int $value + * + * @return string + */ + public function headerLine($name, $value) + { + } + /** + * Return a formatted mail line. + * + * @param string $value + * + * @return string + */ + public function textLine($value) + { + } + /** + * Add an attachment from a path on the filesystem. + * Never use a user-supplied path to a file! + * Returns false if the file could not be found or read. + * Explicitly *does not* support passing URLs; PHPMailer is not an HTTP client. + * If you need to do that, fetch the resource yourself and pass it in via a local file or string. + * + * @param string $path Path to the attachment + * @param string $name Overrides the attachment name + * @param string $encoding File encoding (see $Encoding) + * @param string $type MIME type, e.g. `image/jpeg`; determined automatically from $path if not specified + * @param string $disposition Disposition to use + * + * @throws Exception + * + * @return bool + */ + public function addAttachment($path, $name = '', $encoding = self::ENCODING_BASE64, $type = '', $disposition = 'attachment') + { + } + /** + * Return the array of attachments. + * + * @return array + */ + public function getAttachments() + { + } + /** + * Attach all file, string, and binary attachments to the message. + * Returns an empty string on failure. + * + * @param string $disposition_type + * @param string $boundary + * + * @throws Exception + * + * @return string + */ + protected function attachAll($disposition_type, $boundary) + { + } + /** + * Encode a file attachment in requested format. + * Returns an empty string on failure. + * + * @param string $path The full path to the file + * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' + * + * @return string + */ + protected function encodeFile($path, $encoding = self::ENCODING_BASE64) + { + } + /** + * Encode a string in requested format. + * Returns an empty string on failure. + * + * @param string $str The text to encode + * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' + * + * @throws Exception + * + * @return string + */ + public function encodeString($str, $encoding = self::ENCODING_BASE64) + { + } + /** + * Encode a header value (not including its label) optimally. + * Picks shortest of Q, B, or none. Result includes folding if needed. + * See RFC822 definitions for phrase, comment and text positions. + * + * @param string $str The header value to encode + * @param string $position What context the string will be used in + * + * @return string + */ + public function encodeHeader($str, $position = 'text') + { + } + /** + * Check if a string contains multi-byte characters. + * + * @param string $str multi-byte text to wrap encode + * + * @return bool + */ + public function hasMultiBytes($str) + { + } + /** + * Does a string contain any 8-bit chars (in any charset)? + * + * @param string $text + * + * @return bool + */ + public function has8bitChars($text) + { + } + /** + * Encode and wrap long multibyte strings for mail headers + * without breaking lines within a character. + * Adapted from a function by paravoid. + * + * @see http://www.php.net/manual/en/function.mb-encode-mimeheader.php#60283 + * + * @param string $str multi-byte text to wrap encode + * @param string $linebreak string to use as linefeed/end-of-line + * + * @return string + */ + public function base64EncodeWrapMB($str, $linebreak = null) + { + } + /** + * Encode a string in quoted-printable format. + * According to RFC2045 section 6.7. + * + * @param string $string The text to encode + * + * @return string + */ + public function encodeQP($string) + { + } + /** + * Encode a string using Q encoding. + * + * @see http://tools.ietf.org/html/rfc2047#section-4.2 + * + * @param string $str the text to encode + * @param string $position Where the text is going to be used, see the RFC for what that means + * + * @return string + */ + public function encodeQ($str, $position = 'text') + { + } + /** + * Add a string or binary attachment (non-filesystem). + * This method can be used to attach ascii or binary data, + * such as a BLOB record from a database. + * + * @param string $string String attachment data + * @param string $filename Name of the attachment + * @param string $encoding File encoding (see $Encoding) + * @param string $type File extension (MIME) type + * @param string $disposition Disposition to use + * + * @throws Exception + * + * @return bool True on successfully adding an attachment + */ + public function addStringAttachment($string, $filename, $encoding = self::ENCODING_BASE64, $type = '', $disposition = 'attachment') + { + } + /** + * Add an embedded (inline) attachment from a file. + * This can include images, sounds, and just about any other document type. + * These differ from 'regular' attachments in that they are intended to be + * displayed inline with the message, not just attached for download. + * This is used in HTML messages that embed the images + * the HTML refers to using the `$cid` value in `img` tags, for example ``. + * Never use a user-supplied path to a file! + * + * @param string $path Path to the attachment + * @param string $cid Content ID of the attachment; Use this to reference + * the content when using an embedded image in HTML + * @param string $name Overrides the attachment filename + * @param string $encoding File encoding (see $Encoding) defaults to `base64` + * @param string $type File MIME type (by default mapped from the `$path` filename's extension) + * @param string $disposition Disposition to use: `inline` (default) or `attachment` + * (unlikely you want this – {@see `addAttachment()`} instead) + * + * @return bool True on successfully adding an attachment + * @throws Exception + * + */ + public function addEmbeddedImage($path, $cid, $name = '', $encoding = self::ENCODING_BASE64, $type = '', $disposition = 'inline') + { + } + /** + * Add an embedded stringified attachment. + * This can include images, sounds, and just about any other document type. + * If your filename doesn't contain an extension, be sure to set the $type to an appropriate MIME type. + * + * @param string $string The attachment binary data + * @param string $cid Content ID of the attachment; Use this to reference + * the content when using an embedded image in HTML + * @param string $name A filename for the attachment. If this contains an extension, + * PHPMailer will attempt to set a MIME type for the attachment. + * For example 'file.jpg' would get an 'image/jpeg' MIME type. + * @param string $encoding File encoding (see $Encoding), defaults to 'base64' + * @param string $type MIME type - will be used in preference to any automatically derived type + * @param string $disposition Disposition to use + * + * @throws Exception + * + * @return bool True on successfully adding an attachment + */ + public function addStringEmbeddedImage($string, $cid, $name = '', $encoding = self::ENCODING_BASE64, $type = '', $disposition = 'inline') + { + } + /** + * Validate encodings. + * + * @param string $encoding + * + * @return bool + */ + protected function validateEncoding($encoding) + { + } + /** + * Check if an embedded attachment is present with this cid. + * + * @param string $cid + * + * @return bool + */ + protected function cidExists($cid) + { + } + /** + * Check if an inline attachment is present. + * + * @return bool + */ + public function inlineImageExists() + { + } + /** + * Check if an attachment (non-inline) is present. + * + * @return bool + */ + public function attachmentExists() + { + } + /** + * Check if this message has an alternative body set. + * + * @return bool + */ + public function alternativeExists() + { + } + /** + * Clear queued addresses of given kind. + * + * @param string $kind 'to', 'cc', or 'bcc' + */ + public function clearQueuedAddresses($kind) + { + } + /** + * Clear all To recipients. + */ + public function clearAddresses() + { + } + /** + * Clear all CC recipients. + */ + public function clearCCs() + { + } + /** + * Clear all BCC recipients. + */ + public function clearBCCs() + { + } + /** + * Clear all ReplyTo recipients. + */ + public function clearReplyTos() + { + } + /** + * Clear all recipient types. + */ + public function clearAllRecipients() + { + } + /** + * Clear all filesystem, string, and binary attachments. + */ + public function clearAttachments() + { + } + /** + * Clear all custom headers. + */ + public function clearCustomHeaders() + { + } + /** + * Add an error message to the error container. + * + * @param string $msg + */ + protected function setError($msg) + { + } + /** + * Return an RFC 822 formatted date. + * + * @return string + */ + public static function rfcDate() + { + } + /** + * Get the server hostname. + * Returns 'localhost.localdomain' if unknown. + * + * @return string + */ + protected function serverHostname() + { + } + /** + * Validate whether a string contains a valid value to use as a hostname or IP address. + * IPv6 addresses must include [], e.g. `[::1]`, not just `::1`. + * + * @param string $host The host name or IP address to check + * + * @return bool + */ + public static function isValidHost($host) + { + } + /** + * Get an error message in the current language. + * + * @param string $key + * + * @return string + */ + protected function lang($key) + { + } + /** + * Check if an error occurred. + * + * @return bool True if an error did occur + */ + public function isError() + { + } + /** + * Add a custom header. + * $name value can be overloaded to contain + * both header name and value (name:value). + * + * @param string $name Custom header name + * @param string|null $value Header value + * + * @throws Exception + */ + public function addCustomHeader($name, $value = null) + { + } + /** + * Returns all custom headers. + * + * @return array + */ + public function getCustomHeaders() + { + } + /** + * Create a message body from an HTML string. + * Automatically inlines images and creates a plain-text version by converting the HTML, + * overwriting any existing values in Body and AltBody. + * Do not source $message content from user input! + * $basedir is prepended when handling relative URLs, e.g. and must not be empty + * will look for an image file in $basedir/images/a.png and convert it to inline. + * If you don't provide a $basedir, relative paths will be left untouched (and thus probably break in email) + * Converts data-uri images into embedded attachments. + * If you don't want to apply these transformations to your HTML, just set Body and AltBody directly. + * + * @param string $message HTML message string + * @param string $basedir Absolute path to a base directory to prepend to relative paths to images + * @param bool|callable $advanced Whether to use the internal HTML to text converter + * or your own custom converter + * @return string The transformed message body + * + * @throws Exception + * + * @see PHPMailer::html2text() + */ + public function msgHTML($message, $basedir = '', $advanced = false) + { + } + /** + * Convert an HTML string into plain text. + * This is used by msgHTML(). + * Note - older versions of this function used a bundled advanced converter + * which was removed for license reasons in #232. + * Example usage: + * + * ```php + * //Use default conversion + * $plain = $mail->html2text($html); + * //Use your own custom converter + * $plain = $mail->html2text($html, function($html) { + * $converter = new MyHtml2text($html); + * return $converter->get_text(); + * }); + * ``` + * + * @param string $html The HTML text to convert + * @param bool|callable $advanced Any boolean value to use the internal converter, + * or provide your own callable for custom conversion. + * *Never* pass user-supplied data into this parameter + * + * @return string + */ + public function html2text($html, $advanced = false) + { + } + /** + * Get the MIME type for a file extension. + * + * @param string $ext File extension + * + * @return string MIME type of file + */ + public static function _mime_types($ext = '') + { + } + /** + * Map a file name to a MIME type. + * Defaults to 'application/octet-stream', i.e.. arbitrary binary data. + * + * @param string $filename A file name or full path, does not need to exist as a file + * + * @return string + */ + public static function filenameToType($filename) + { + } + /** + * Multi-byte-safe pathinfo replacement. + * Drop-in replacement for pathinfo(), but multibyte- and cross-platform-safe. + * + * @see http://www.php.net/manual/en/function.pathinfo.php#107461 + * + * @param string $path A filename or path, does not need to exist as a file + * @param int|string $options Either a PATHINFO_* constant, + * or a string name to return only the specified piece + * + * @return string|array + */ + public static function mb_pathinfo($path, $options = null) + { + } + /** + * Set or reset instance properties. + * You should avoid this function - it's more verbose, less efficient, more error-prone and + * harder to debug than setting properties directly. + * Usage Example: + * `$mail->set('SMTPSecure', static::ENCRYPTION_STARTTLS);` + * is the same as: + * `$mail->SMTPSecure = static::ENCRYPTION_STARTTLS;`. + * + * @param string $name The property name to set + * @param mixed $value The value to set the property to + * + * @return bool + */ + public function set($name, $value = '') + { + } + /** + * Strip newlines to prevent header injection. + * + * @param string $str + * + * @return string + */ + public function secureHeader($str) + { + } + /** + * Normalize line breaks in a string. + * Converts UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format. + * Defaults to CRLF (for message bodies) and preserves consecutive breaks. + * + * @param string $text + * @param string $breaktype What kind of line break to use; defaults to static::$LE + * + * @return string + */ + public static function normalizeBreaks($text, $breaktype = null) + { + } + /** + * Remove trailing breaks from a string. + * + * @param string $text + * + * @return string The text to remove breaks from + */ + public static function stripTrailingWSP($text) + { + } + /** + * Return the current line break format string. + * + * @return string + */ + public static function getLE() + { + } + /** + * Set the line break format string, e.g. "\r\n". + * + * @param string $le + */ + protected static function setLE($le) + { + } + /** + * Set the public and private key files and password for S/MIME signing. + * + * @param string $cert_filename + * @param string $key_filename + * @param string $key_pass Password for private key + * @param string $extracerts_filename Optional path to chain certificate + */ + public function sign($cert_filename, $key_filename, $key_pass, $extracerts_filename = '') + { + } + /** + * Quoted-Printable-encode a DKIM header. + * + * @param string $txt + * + * @return string + */ + public function DKIM_QP($txt) + { + } + /** + * Generate a DKIM signature. + * + * @param string $signHeader + * + * @throws Exception + * + * @return string The DKIM signature value + */ + public function DKIM_Sign($signHeader) + { + } + /** + * Generate a DKIM canonicalization header. + * Uses the 'relaxed' algorithm from RFC6376 section 3.4.2. + * Canonicalized headers should *always* use CRLF, regardless of mailer setting. + * + * @see https://tools.ietf.org/html/rfc6376#section-3.4.2 + * + * @param string $signHeader Header + * + * @return string + */ + public function DKIM_HeaderC($signHeader) + { + } + /** + * Generate a DKIM canonicalization body. + * Uses the 'simple' algorithm from RFC6376 section 3.4.3. + * Canonicalized bodies should *always* use CRLF, regardless of mailer setting. + * + * @see https://tools.ietf.org/html/rfc6376#section-3.4.3 + * + * @param string $body Message Body + * + * @return string + */ + public function DKIM_BodyC($body) + { + } + /** + * Create the DKIM header and body in a new message header. + * + * @param string $headers_line Header lines + * @param string $subject Subject + * @param string $body Body + * + * @throws Exception + * + * @return string + */ + public function DKIM_Add($headers_line, $subject, $body) + { + } + /** + * Detect if a string contains a line longer than the maximum line length + * allowed by RFC 2822 section 2.1.1. + * + * @param string $str + * + * @return bool + */ + public static function hasLineLongerThanMax($str) + { + } + /** + * If a string contains any "special" characters, double-quote the name, + * and escape any double quotes with a backslash. + * + * @param string $str + * + * @return string + * + * @see RFC822 3.4.1 + */ + public static function quotedString($str) + { + } + /** + * Allows for public read access to 'to' property. + * Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * + * @return array + */ + public function getToAddresses() + { + } + /** + * Allows for public read access to 'cc' property. + * Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * + * @return array + */ + public function getCcAddresses() + { + } + /** + * Allows for public read access to 'bcc' property. + * Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * + * @return array + */ + public function getBccAddresses() + { + } + /** + * Allows for public read access to 'ReplyTo' property. + * Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * + * @return array + */ + public function getReplyToAddresses() + { + } + /** + * Allows for public read access to 'all_recipients' property. + * Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * + * @return array + */ + public function getAllRecipientAddresses() + { + } + /** + * Perform a callback. + * + * @param bool $isSent + * @param array $to + * @param array $cc + * @param array $bcc + * @param string $subject + * @param string $body + * @param string $from + * @param array $extra + */ + protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from, $extra) + { + } + /** + * Get the OAuthTokenProvider instance. + * + * @return OAuthTokenProvider + */ + public function getOAuth() + { + } + /** + * Set an OAuthTokenProvider instance. + */ + public function setOAuth(\PHPMailer\PHPMailer\OAuthTokenProvider $oauth) + { + } + } + /** + * PHPMailer RFC821 SMTP email transport class. + * Implements RFC 821 SMTP commands and provides some utility methods for sending mail to an SMTP server. + * + * @author Chris Ryan + * @author Marcus Bointon + */ + class SMTP + { + /** + * The PHPMailer SMTP version number. + * + * @var string + */ + const VERSION = '6.6.5'; + /** + * SMTP line break constant. + * + * @var string + */ + const LE = "\r\n"; + /** + * The SMTP port to use if one is not specified. + * + * @var int + */ + const DEFAULT_PORT = 25; + /** + * The maximum line length allowed by RFC 5321 section 4.5.3.1.6, + * *excluding* a trailing CRLF break. + * + * @see https://tools.ietf.org/html/rfc5321#section-4.5.3.1.6 + * + * @var int + */ + const MAX_LINE_LENGTH = 998; + /** + * The maximum line length allowed for replies in RFC 5321 section 4.5.3.1.5, + * *including* a trailing CRLF line break. + * + * @see https://tools.ietf.org/html/rfc5321#section-4.5.3.1.5 + * + * @var int + */ + const MAX_REPLY_LENGTH = 512; + /** + * Debug level for no output. + * + * @var int + */ + const DEBUG_OFF = 0; + /** + * Debug level to show client -> server messages. + * + * @var int + */ + const DEBUG_CLIENT = 1; + /** + * Debug level to show client -> server and server -> client messages. + * + * @var int + */ + const DEBUG_SERVER = 2; + /** + * Debug level to show connection status, client -> server and server -> client messages. + * + * @var int + */ + const DEBUG_CONNECTION = 3; + /** + * Debug level to show all messages. + * + * @var int + */ + const DEBUG_LOWLEVEL = 4; + /** + * Debug output level. + * Options: + * * self::DEBUG_OFF (`0`) No debug output, default + * * self::DEBUG_CLIENT (`1`) Client commands + * * self::DEBUG_SERVER (`2`) Client commands and server responses + * * self::DEBUG_CONNECTION (`3`) As DEBUG_SERVER plus connection status + * * self::DEBUG_LOWLEVEL (`4`) Low-level data output, all messages. + * + * @var int + */ + public $do_debug = self::DEBUG_OFF; + /** + * How to handle debug output. + * Options: + * * `echo` Output plain-text as-is, appropriate for CLI + * * `html` Output escaped, line breaks converted to `
    `, appropriate for browser output + * * `error_log` Output to error log as configured in php.ini + * Alternatively, you can provide a callable expecting two params: a message string and the debug level: + * + * ```php + * $smtp->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";}; + * ``` + * + * Alternatively, you can pass in an instance of a PSR-3 compatible logger, though only `debug` + * level output is used: + * + * ```php + * $mail->Debugoutput = new myPsr3Logger; + * ``` + * + * @var string|callable|\Psr\Log\LoggerInterface + */ + public $Debugoutput = 'echo'; + /** + * Whether to use VERP. + * + * @see http://en.wikipedia.org/wiki/Variable_envelope_return_path + * @see http://www.postfix.org/VERP_README.html Info on VERP + * + * @var bool + */ + public $do_verp = false; + /** + * The timeout value for connection, in seconds. + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2. + * This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure. + * + * @see http://tools.ietf.org/html/rfc2821#section-4.5.3.2 + * + * @var int + */ + public $Timeout = 300; + /** + * How long to wait for commands to complete, in seconds. + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2. + * + * @var int + */ + public $Timelimit = 300; + /** + * Patterns to extract an SMTP transaction id from reply to a DATA command. + * The first capture group in each regex will be used as the ID. + * MS ESMTP returns the message ID, which may not be correct for internal tracking. + * + * @var string[] + */ + protected $smtp_transaction_id_patterns = ['exim' => '/[\\d]{3} OK id=(.*)/', 'sendmail' => '/[\\d]{3} 2.0.0 (.*) Message/', 'postfix' => '/[\\d]{3} 2.0.0 Ok: queued as (.*)/', 'Microsoft_ESMTP' => '/[0-9]{3} 2.[\\d].0 (.*)@(?:.*) Queued mail for delivery/', 'Amazon_SES' => '/[\\d]{3} Ok (.*)/', 'SendGrid' => '/[\\d]{3} Ok: queued as (.*)/', 'CampaignMonitor' => '/[\\d]{3} 2.0.0 OK:([a-zA-Z\\d]{48})/', 'Haraka' => '/[\\d]{3} Message Queued \\((.*)\\)/', 'Mailjet' => '/[\\d]{3} OK queued as (.*)/']; + /** + * The last transaction ID issued in response to a DATA command, + * if one was detected. + * + * @var string|bool|null + */ + protected $last_smtp_transaction_id; + /** + * The socket for the server connection. + * + * @var ?resource + */ + protected $smtp_conn; + /** + * Error information, if any, for the last SMTP command. + * + * @var array + */ + protected $error = ['error' => '', 'detail' => '', 'smtp_code' => '', 'smtp_code_ex' => '']; + /** + * The reply the server sent to us for HELO. + * If null, no HELO string has yet been received. + * + * @var string|null + */ + protected $helo_rply; + /** + * The set of SMTP extensions sent in reply to EHLO command. + * Indexes of the array are extension names. + * Value at index 'HELO' or 'EHLO' (according to command that was sent) + * represents the server name. In case of HELO it is the only element of the array. + * Other values can be boolean TRUE or an array containing extension options. + * If null, no HELO/EHLO string has yet been received. + * + * @var array|null + */ + protected $server_caps; + /** + * The most recent reply received from the server. + * + * @var string + */ + protected $last_reply = ''; + /** + * Output debugging info via a user-selected method. + * + * @param string $str Debug string to output + * @param int $level The debug level of this message; see DEBUG_* constants + * + * @see SMTP::$Debugoutput + * @see SMTP::$do_debug + */ + protected function edebug($str, $level = 0) + { + } + /** + * Connect to an SMTP server. + * + * @param string $host SMTP server IP or host name + * @param int $port The port number to connect to + * @param int $timeout How long to wait for the connection to open + * @param array $options An array of options for stream_context_create() + * + * @return bool + */ + public function connect($host, $port = null, $timeout = 30, $options = []) + { + } + /** + * Create connection to the SMTP server. + * + * @param string $host SMTP server IP or host name + * @param int $port The port number to connect to + * @param int $timeout How long to wait for the connection to open + * @param array $options An array of options for stream_context_create() + * + * @return false|resource + */ + protected function getSMTPConnection($host, $port = null, $timeout = 30, $options = []) + { + } + /** + * Initiate a TLS (encrypted) session. + * + * @return bool + */ + public function startTLS() + { + } + /** + * Perform SMTP authentication. + * Must be run after hello(). + * + * @see hello() + * + * @param string $username The user name + * @param string $password The password + * @param string $authtype The auth type (CRAM-MD5, PLAIN, LOGIN, XOAUTH2) + * @param OAuthTokenProvider $OAuth An optional OAuthTokenProvider instance for XOAUTH2 authentication + * + * @return bool True if successfully authenticated + */ + public function authenticate($username, $password, $authtype = null, $OAuth = null) + { + } + /** + * Calculate an MD5 HMAC hash. + * Works like hash_hmac('md5', $data, $key) + * in case that function is not available. + * + * @param string $data The data to hash + * @param string $key The key to hash with + * + * @return string + */ + protected function hmac($data, $key) + { + } + /** + * Check connection state. + * + * @return bool True if connected + */ + public function connected() + { + } + /** + * Close the socket and clean up the state of the class. + * Don't use this function without first trying to use QUIT. + * + * @see quit() + */ + public function close() + { + } + /** + * Send an SMTP DATA command. + * Issues a data command and sends the msg_data to the server, + * finalizing the mail transaction. $msg_data is the message + * that is to be send with the headers. Each header needs to be + * on a single line followed by a with the message headers + * and the message body being separated by an additional . + * Implements RFC 821: DATA . + * + * @param string $msg_data Message data to send + * + * @return bool + */ + public function data($msg_data) + { + } + /** + * Send an SMTP HELO or EHLO command. + * Used to identify the sending server to the receiving server. + * This makes sure that client and server are in a known state. + * Implements RFC 821: HELO + * and RFC 2821 EHLO. + * + * @param string $host The host name or IP to connect to + * + * @return bool + */ + public function hello($host = '') + { + } + /** + * Send an SMTP HELO or EHLO command. + * Low-level implementation used by hello(). + * + * @param string $hello The HELO string + * @param string $host The hostname to say we are + * + * @return bool + * + * @see hello() + */ + protected function sendHello($hello, $host) + { + } + /** + * Parse a reply to HELO/EHLO command to discover server extensions. + * In case of HELO, the only parameter that can be discovered is a server name. + * + * @param string $type `HELO` or `EHLO` + */ + protected function parseHelloFields($type) + { + } + /** + * Send an SMTP MAIL command. + * Starts a mail transaction from the email address specified in + * $from. Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more recipient + * commands may be called followed by a data command. + * Implements RFC 821: MAIL FROM: . + * + * @param string $from Source address of this message + * + * @return bool + */ + public function mail($from) + { + } + /** + * Send an SMTP QUIT command. + * Closes the socket if there is no error or the $close_on_error argument is true. + * Implements from RFC 821: QUIT . + * + * @param bool $close_on_error Should the connection close if an error occurs? + * + * @return bool + */ + public function quit($close_on_error = true) + { + } + /** + * Send an SMTP RCPT command. + * Sets the TO argument to $toaddr. + * Returns true if the recipient was accepted false if it was rejected. + * Implements from RFC 821: RCPT TO: . + * + * @param string $address The address the message is being sent to + * @param string $dsn Comma separated list of DSN notifications. NEVER, SUCCESS, FAILURE + * or DELAY. If you specify NEVER all other notifications are ignored. + * + * @return bool + */ + public function recipient($address, $dsn = '') + { + } + /** + * Send an SMTP RSET command. + * Abort any transaction that is currently in progress. + * Implements RFC 821: RSET . + * + * @return bool True on success + */ + public function reset() + { + } + /** + * Send a command to an SMTP server and check its return code. + * + * @param string $command The command name - not sent to the server + * @param string $commandstring The actual command to send + * @param int|array $expect One or more expected integer success codes + * + * @return bool True on success + */ + protected function sendCommand($command, $commandstring, $expect) + { + } + /** + * Send an SMTP SAML command. + * Starts a mail transaction from the email address specified in $from. + * Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more recipient + * commands may be called followed by a data command. This command + * will send the message to the users terminal if they are logged + * in and send them an email. + * Implements RFC 821: SAML FROM: . + * + * @param string $from The address the message is from + * + * @return bool + */ + public function sendAndMail($from) + { + } + /** + * Send an SMTP VRFY command. + * + * @param string $name The name to verify + * + * @return bool + */ + public function verify($name) + { + } + /** + * Send an SMTP NOOP command. + * Used to keep keep-alives alive, doesn't actually do anything. + * + * @return bool + */ + public function noop() + { + } + /** + * Send an SMTP TURN command. + * This is an optional command for SMTP that this class does not support. + * This method is here to make the RFC821 Definition complete for this class + * and _may_ be implemented in future. + * Implements from RFC 821: TURN . + * + * @return bool + */ + public function turn() + { + } + /** + * Send raw data to the server. + * + * @param string $data The data to send + * @param string $command Optionally, the command this is part of, used only for controlling debug output + * + * @return int|bool The number of bytes sent to the server or false on error + */ + public function client_send($data, $command = '') + { + } + /** + * Get the latest error. + * + * @return array + */ + public function getError() + { + } + /** + * Get SMTP extensions available on the server. + * + * @return array|null + */ + public function getServerExtList() + { + } + /** + * Get metadata about the SMTP server from its HELO/EHLO response. + * The method works in three ways, dependent on argument value and current state: + * 1. HELO/EHLO has not been sent - returns null and populates $this->error. + * 2. HELO has been sent - + * $name == 'HELO': returns server name + * $name == 'EHLO': returns boolean false + * $name == any other string: returns null and populates $this->error + * 3. EHLO has been sent - + * $name == 'HELO'|'EHLO': returns the server name + * $name == any other string: if extension $name exists, returns True + * or its options (e.g. AUTH mechanisms supported). Otherwise returns False. + * + * @param string $name Name of SMTP extension or 'HELO'|'EHLO' + * + * @return string|bool|null + */ + public function getServerExt($name) + { + } + /** + * Get the last reply from the server. + * + * @return string + */ + public function getLastReply() + { + } + /** + * Read the SMTP server's response. + * Either before eof or socket timeout occurs on the operation. + * With SMTP we can tell if we have more lines to read if the + * 4th character is '-' symbol. If it is a space then we don't + * need to read anything else. + * + * @return string + */ + protected function get_lines() + { + } + /** + * Enable or disable VERP address generation. + * + * @param bool $enabled + */ + public function setVerp($enabled = false) + { + } + /** + * Get VERP address generation mode. + * + * @return bool + */ + public function getVerp() + { + } + /** + * Set error messages and codes. + * + * @param string $message The error message + * @param string $detail Further detail on the error + * @param string $smtp_code An associated SMTP error code + * @param string $smtp_code_ex Extended SMTP code + */ + protected function setError($message, $detail = '', $smtp_code = '', $smtp_code_ex = '') + { + } + /** + * Set debug output method. + * + * @param string|callable $method The name of the mechanism to use for debugging output, or a callable to handle it + */ + public function setDebugOutput($method = 'echo') + { + } + /** + * Get debug output method. + * + * @return string + */ + public function getDebugOutput() + { + } + /** + * Set debug output level. + * + * @param int $level + */ + public function setDebugLevel($level = 0) + { + } + /** + * Get debug output level. + * + * @return int + */ + public function getDebugLevel() + { + } + /** + * Set SMTP timeout. + * + * @param int $timeout The timeout duration in seconds + */ + public function setTimeout($timeout = 0) + { + } + /** + * Get SMTP timeout. + * + * @return int + */ + public function getTimeout() + { + } + /** + * Reports an error number and string. + * + * @param int $errno The error number returned by PHP + * @param string $errmsg The error message returned by PHP + * @param string $errfile The file the error occurred in + * @param int $errline The line number the error occurred on + */ + protected function errorHandler($errno, $errmsg, $errfile = '', $errline = 0) + { + } + /** + * Extract and return the ID of the last SMTP transaction based on + * a list of patterns provided in SMTP::$smtp_transaction_id_patterns. + * Relies on the host providing the ID in response to a DATA command. + * If no reply has been received yet, it will return null. + * If no pattern was matched, it will return false. + * + * @return bool|string|null + */ + protected function recordLastTransactionID() + { + } + /** + * Get the queue/transaction ID of the last SMTP transaction + * If no reply has been received yet, it will return null. + * If no pattern was matched, it will return false. + * + * @return bool|string|null + * + * @see recordLastTransactionID() + */ + public function getLastTransactionID() + { + } + } +} +namespace { + /** + * Authentication provider interface + * + * @package Requests + * @subpackage Authentication + */ + /** + * Authentication provider interface + * + * Implement this interface to act as an authentication provider. + * + * Parameters should be passed via the constructor where possible, as this + * makes it much easier for users to use your provider. + * + * @see Requests_Hooks + * @package Requests + * @subpackage Authentication + */ + interface Requests_Auth + { + /** + * Register hooks as needed + * + * This method is called in {@see Requests::request} when the user has set + * an instance as the 'auth' option. Use this callback to register all the + * hooks you'll need. + * + * @see Requests_Hooks::register + * @param Requests_Hooks $hooks Hook system + */ + public function register(\Requests_Hooks $hooks); + } + /** + * Basic Authentication provider + * + * @package Requests + * @subpackage Authentication + */ + /** + * Basic Authentication provider + * + * Provides a handler for Basic HTTP authentication via the Authorization + * header. + * + * @package Requests + * @subpackage Authentication + */ + class Requests_Auth_Basic implements \Requests_Auth + { + /** + * Username + * + * @var string + */ + public $user; + /** + * Password + * + * @var string + */ + public $pass; + /** + * Constructor + * + * @throws Requests_Exception On incorrect number of arguments (`authbasicbadargs`) + * @param array|null $args Array of user and password. Must have exactly two elements + */ + public function __construct($args = \null) + { + } + /** + * Register the necessary callbacks + * + * @see curl_before_send + * @see fsockopen_header + * @param Requests_Hooks $hooks Hook system + */ + public function register(\Requests_Hooks $hooks) + { + } + /** + * Set cURL parameters before the data is sent + * + * @param resource $handle cURL resource + */ + public function curl_before_send(&$handle) + { + } + /** + * Add extra headers to the request before sending + * + * @param string $out HTTP header string + */ + public function fsockopen_header(&$out) + { + } + /** + * Get the authentication string (user:pass) + * + * @return string + */ + public function getAuthString() + { + } + } + /** + * Cookie storage object + * + * @package Requests + * @subpackage Cookies + */ + /** + * Cookie storage object + * + * @package Requests + * @subpackage Cookies + */ + class Requests_Cookie + { + /** + * Cookie name. + * + * @var string + */ + public $name; + /** + * Cookie value. + * + * @var string + */ + public $value; + /** + * Cookie attributes + * + * Valid keys are (currently) path, domain, expires, max-age, secure and + * httponly. + * + * @var Requests_Utility_CaseInsensitiveDictionary|array Array-like object + */ + public $attributes = array(); + /** + * Cookie flags + * + * Valid keys are (currently) creation, last-access, persistent and + * host-only. + * + * @var array + */ + public $flags = array(); + /** + * Reference time for relative calculations + * + * This is used in place of `time()` when calculating Max-Age expiration and + * checking time validity. + * + * @var int + */ + public $reference_time = 0; + /** + * Create a new cookie object + * + * @param string $name + * @param string $value + * @param array|Requests_Utility_CaseInsensitiveDictionary $attributes Associative array of attribute data + */ + public function __construct($name, $value, $attributes = array(), $flags = array(), $reference_time = \null) + { + } + /** + * Check if a cookie is expired. + * + * Checks the age against $this->reference_time to determine if the cookie + * is expired. + * + * @return boolean True if expired, false if time is valid. + */ + public function is_expired() + { + } + /** + * Check if a cookie is valid for a given URI + * + * @param Requests_IRI $uri URI to check + * @return boolean Whether the cookie is valid for the given URI + */ + public function uri_matches(\Requests_IRI $uri) + { + } + /** + * Check if a cookie is valid for a given domain + * + * @param string $string Domain to check + * @return boolean Whether the cookie is valid for the given domain + */ + public function domain_matches($string) + { + } + /** + * Check if a cookie is valid for a given path + * + * From the path-match check in RFC 6265 section 5.1.4 + * + * @param string $request_path Path to check + * @return boolean Whether the cookie is valid for the given path + */ + public function path_matches($request_path) + { + } + /** + * Normalize cookie and attributes + * + * @return boolean Whether the cookie was successfully normalized + */ + public function normalize() + { + } + /** + * Parse an individual cookie attribute + * + * Handles parsing individual attributes from the cookie values. + * + * @param string $name Attribute name + * @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) + { + } + /** + * Format a cookie for a Cookie header + * + * This is used when sending cookies to a server. + * + * @return string Cookie formatted for Cookie header + */ + public function format_for_header() + { + } + /** + * Format a cookie for a Cookie header + * + * @codeCoverageIgnore + * @deprecated Use {@see Requests_Cookie::format_for_header} + * @return string + */ + public function formatForHeader() + { + } + /** + * Format a cookie for a Set-Cookie header + * + * This is used when sending cookies to clients. This isn't really + * applicable to client-side usage, but might be handy for debugging. + * + * @return string Cookie formatted for Set-Cookie header + */ + public function format_for_set_cookie() + { + } + /** + * Format a cookie for a Set-Cookie header + * + * @codeCoverageIgnore + * @deprecated Use {@see Requests_Cookie::format_for_set_cookie} + * @return string + */ + public function formatForSetCookie() + { + } + /** + * Get the cookie value + * + * Attributes and other data can be accessed via methods. + */ + public function __toString() + { + } + /** + * Parse a cookie string into a cookie object + * + * Based on Mozilla's parsing code in Firefox and related projects, which + * is an intentional deviation from RFC 2109 and RFC 2616. RFC 6265 + * specifies some of this handling, but not in a thorough manner. + * + * @param string Cookie header value (from a Set-Cookie header) + * @return Requests_Cookie Parsed cookie object + */ + public static function parse($string, $name = '', $reference_time = \null) + { + } + /** + * Parse all Set-Cookie headers from request headers + * + * @param Requests_Response_Headers $headers Headers to parse from + * @param Requests_IRI|null $origin URI for comparing cookie origins + * @param int|null $time Reference time for expiration calculation + * @return array + */ + public static function parse_from_headers(\Requests_Response_Headers $headers, \Requests_IRI $origin = \null, $time = \null) + { + } + /** + * Parse all Set-Cookie headers from request headers + * + * @codeCoverageIgnore + * @deprecated Use {@see Requests_Cookie::parse_from_headers} + * @return array + */ + public static function parseFromHeaders(\Requests_Response_Headers $headers) + { + } + } + /** + * Cookie holder object + * + * @package Requests + * @subpackage Cookies + */ + /** + * Cookie holder object + * + * @package Requests + * @subpackage Cookies + */ + class Requests_Cookie_Jar implements \ArrayAccess, \IteratorAggregate + { + /** + * Actual item data + * + * @var array + */ + protected $cookies = array(); + /** + * Create a new jar + * + * @param array $cookies Existing cookie values + */ + public function __construct($cookies = array()) + { + } + /** + * Normalise cookie data into a Requests_Cookie + * + * @param string|Requests_Cookie $cookie + * @return Requests_Cookie + */ + public function normalize_cookie($cookie, $key = \null) + { + } + /** + * Normalise cookie data into a Requests_Cookie + * + * @codeCoverageIgnore + * @deprecated Use {@see Requests_Cookie_Jar::normalize_cookie} + * @return Requests_Cookie + */ + public function normalizeCookie($cookie, $key = \null) + { + } + /** + * Check if the given item exists + * + * @param string $key Item key + * @return boolean Does the item exist? + */ + #[ReturnTypeWillChange] + public function offsetExists($key) + { + } + /** + * Get the value for the item + * + * @param string $key Item key + * @return string|null Item value (null if offsetExists is false) + */ + #[ReturnTypeWillChange] + public function offsetGet($key) + { + } + /** + * Set the given item + * + * @throws Requests_Exception On attempting to use dictionary as list (`invalidset`) + * + * @param string $key Item name + * @param string $value Item value + */ + #[ReturnTypeWillChange] + public function offsetSet($key, $value) + { + } + /** + * Unset the given header + * + * @param string $key + */ + #[ReturnTypeWillChange] + public function offsetUnset($key) + { + } + /** + * Get an iterator for the data + * + * @return ArrayIterator + */ + #[ReturnTypeWillChange] + public function getIterator() + { + } + /** + * Register the cookie handler with the request's hooking system + * + * @param Requests_Hooker $hooks Hooking system + */ + public function register(\Requests_Hooker $hooks) + { + } + /** + * Add Cookie header to a request if we have any + * + * As per RFC 6265, cookies are separated by '; ' + * + * @param string $url + * @param array $headers + * @param array $data + * @param string $type + * @param array $options + */ + public function before_request($url, &$headers, &$data, &$type, &$options) + { + } + /** + * Parse all cookies from a response and attach them to the response + * + * @var Requests_Response $response + */ + public function before_redirect_check(\Requests_Response $return) + { + } + } + /** + * Exception for HTTP requests + * + * @package Requests + */ + /** + * Exception for HTTP requests + * + * @package Requests + */ + class Requests_Exception extends \Exception + { + /** + * Type of exception + * + * @var string + */ + protected $type; + /** + * Data associated with the exception + * + * @var mixed + */ + protected $data; + /** + * Create a new exception + * + * @param string $message Exception message + * @param string $type Exception type + * @param mixed $data Associated data + * @param integer $code Exception numerical code, if applicable + */ + public function __construct($message, $type, $data = \null, $code = 0) + { + } + /** + * Like {@see getCode()}, but a string code. + * + * @codeCoverageIgnore + * @return string + */ + public function getType() + { + } + /** + * Gives any relevant data + * + * @codeCoverageIgnore + * @return mixed + */ + public function getData() + { + } + } + /** + * Exception based on HTTP response + * + * @package Requests + */ + /** + * Exception based on HTTP response + * + * @package Requests + */ + class Requests_Exception_HTTP extends \Requests_Exception + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 0; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Unknown'; + /** + * Create a new exception + * + * There is no mechanism to pass in the status code, as this is set by the + * subclass used. Reason phrases can vary, however. + * + * @param string|null $reason Reason phrase + * @param mixed $data Associated data + */ + public function __construct($reason = \null, $data = \null) + { + } + /** + * Get the status message + */ + public function getReason() + { + } + /** + * Get the correct exception class for a given error code + * + * @param int|bool $code HTTP status code, or false if unavailable + * @return string Exception class name to use + */ + public static function get_class($code) + { + } + } + /** + * Exception for 304 Not Modified responses + * + * @package Requests + */ + /** + * Exception for 304 Not Modified responses + * + * @package Requests + */ + class Requests_Exception_HTTP_304 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 304; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Not Modified'; + } + /** + * Exception for 305 Use Proxy responses + * + * @package Requests + */ + /** + * Exception for 305 Use Proxy responses + * + * @package Requests + */ + class Requests_Exception_HTTP_305 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 305; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Use Proxy'; + } + /** + * Exception for 306 Switch Proxy responses + * + * @package Requests + */ + /** + * Exception for 306 Switch Proxy responses + * + * @package Requests + */ + class Requests_Exception_HTTP_306 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 306; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Switch Proxy'; + } + /** + * Exception for 400 Bad Request responses + * + * @package Requests + */ + /** + * Exception for 400 Bad Request responses + * + * @package Requests + */ + class Requests_Exception_HTTP_400 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 400; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Bad Request'; + } + /** + * Exception for 401 Unauthorized responses + * + * @package Requests + */ + /** + * Exception for 401 Unauthorized responses + * + * @package Requests + */ + class Requests_Exception_HTTP_401 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 401; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Unauthorized'; + } + /** + * Exception for 402 Payment Required responses + * + * @package Requests + */ + /** + * Exception for 402 Payment Required responses + * + * @package Requests + */ + class Requests_Exception_HTTP_402 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 402; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Payment Required'; + } + /** + * Exception for 403 Forbidden responses + * + * @package Requests + */ + /** + * Exception for 403 Forbidden responses + * + * @package Requests + */ + class Requests_Exception_HTTP_403 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 403; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Forbidden'; + } + /** + * Exception for 404 Not Found responses + * + * @package Requests + */ + /** + * Exception for 404 Not Found responses + * + * @package Requests + */ + class Requests_Exception_HTTP_404 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 404; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Not Found'; + } + /** + * Exception for 405 Method Not Allowed responses + * + * @package Requests + */ + /** + * Exception for 405 Method Not Allowed responses + * + * @package Requests + */ + class Requests_Exception_HTTP_405 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 405; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Method Not Allowed'; + } + /** + * Exception for 406 Not Acceptable responses + * + * @package Requests + */ + /** + * Exception for 406 Not Acceptable responses + * + * @package Requests + */ + class Requests_Exception_HTTP_406 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 406; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Not Acceptable'; + } + /** + * Exception for 407 Proxy Authentication Required responses + * + * @package Requests + */ + /** + * Exception for 407 Proxy Authentication Required responses + * + * @package Requests + */ + class Requests_Exception_HTTP_407 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 407; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Proxy Authentication Required'; + } + /** + * Exception for 408 Request Timeout responses + * + * @package Requests + */ + /** + * Exception for 408 Request Timeout responses + * + * @package Requests + */ + class Requests_Exception_HTTP_408 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 408; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Request Timeout'; + } + /** + * Exception for 409 Conflict responses + * + * @package Requests + */ + /** + * Exception for 409 Conflict responses + * + * @package Requests + */ + class Requests_Exception_HTTP_409 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 409; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Conflict'; + } + /** + * Exception for 410 Gone responses + * + * @package Requests + */ + /** + * Exception for 410 Gone responses + * + * @package Requests + */ + class Requests_Exception_HTTP_410 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 410; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Gone'; + } + /** + * Exception for 411 Length Required responses + * + * @package Requests + */ + /** + * Exception for 411 Length Required responses + * + * @package Requests + */ + class Requests_Exception_HTTP_411 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 411; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Length Required'; + } + /** + * Exception for 412 Precondition Failed responses + * + * @package Requests + */ + /** + * Exception for 412 Precondition Failed responses + * + * @package Requests + */ + class Requests_Exception_HTTP_412 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 412; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Precondition Failed'; + } + /** + * Exception for 413 Request Entity Too Large responses + * + * @package Requests + */ + /** + * Exception for 413 Request Entity Too Large responses + * + * @package Requests + */ + class Requests_Exception_HTTP_413 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 413; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Request Entity Too Large'; + } + /** + * Exception for 414 Request-URI Too Large responses + * + * @package Requests + */ + /** + * Exception for 414 Request-URI Too Large responses + * + * @package Requests + */ + class Requests_Exception_HTTP_414 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 414; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Request-URI Too Large'; + } + /** + * Exception for 415 Unsupported Media Type responses + * + * @package Requests + */ + /** + * Exception for 415 Unsupported Media Type responses + * + * @package Requests + */ + class Requests_Exception_HTTP_415 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 415; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Unsupported Media Type'; + } + /** + * Exception for 416 Requested Range Not Satisfiable responses + * + * @package Requests + */ + /** + * Exception for 416 Requested Range Not Satisfiable responses + * + * @package Requests + */ + class Requests_Exception_HTTP_416 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 416; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Requested Range Not Satisfiable'; + } + /** + * Exception for 417 Expectation Failed responses + * + * @package Requests + */ + /** + * Exception for 417 Expectation Failed responses + * + * @package Requests + */ + class Requests_Exception_HTTP_417 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 417; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Expectation Failed'; + } + /** + * Exception for 418 I'm A Teapot responses + * + * @see https://tools.ietf.org/html/rfc2324 + * @package Requests + */ + /** + * Exception for 418 I'm A Teapot responses + * + * @see https://tools.ietf.org/html/rfc2324 + * @package Requests + */ + class Requests_Exception_HTTP_418 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 418; + /** + * Reason phrase + * + * @var string + */ + protected $reason = "I'm A Teapot"; + } + /** + * Exception for 428 Precondition Required responses + * + * @see https://tools.ietf.org/html/rfc6585 + * @package Requests + */ + /** + * Exception for 428 Precondition Required responses + * + * @see https://tools.ietf.org/html/rfc6585 + * @package Requests + */ + class Requests_Exception_HTTP_428 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 428; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Precondition Required'; + } + /** + * Exception for 429 Too Many Requests responses + * + * @see https://tools.ietf.org/html/draft-nottingham-http-new-status-04 + * @package Requests + */ + /** + * Exception for 429 Too Many Requests responses + * + * @see https://tools.ietf.org/html/draft-nottingham-http-new-status-04 + * @package Requests + */ + class Requests_Exception_HTTP_429 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 429; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Too Many Requests'; + } + /** + * Exception for 431 Request Header Fields Too Large responses + * + * @see https://tools.ietf.org/html/rfc6585 + * @package Requests + */ + /** + * Exception for 431 Request Header Fields Too Large responses + * + * @see https://tools.ietf.org/html/rfc6585 + * @package Requests + */ + class Requests_Exception_HTTP_431 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 431; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Request Header Fields Too Large'; + } + /** + * Exception for 500 Internal Server Error responses + * + * @package Requests + */ + /** + * Exception for 500 Internal Server Error responses + * + * @package Requests + */ + class Requests_Exception_HTTP_500 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 500; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Internal Server Error'; + } + /** + * Exception for 501 Not Implemented responses + * + * @package Requests + */ + /** + * Exception for 501 Not Implemented responses + * + * @package Requests + */ + class Requests_Exception_HTTP_501 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 501; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Not Implemented'; + } + /** + * Exception for 502 Bad Gateway responses + * + * @package Requests + */ + /** + * Exception for 502 Bad Gateway responses + * + * @package Requests + */ + class Requests_Exception_HTTP_502 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 502; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Bad Gateway'; + } + /** + * Exception for 503 Service Unavailable responses + * + * @package Requests + */ + /** + * Exception for 503 Service Unavailable responses + * + * @package Requests + */ + class Requests_Exception_HTTP_503 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 503; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Service Unavailable'; + } + /** + * Exception for 504 Gateway Timeout responses + * + * @package Requests + */ + /** + * Exception for 504 Gateway Timeout responses + * + * @package Requests + */ + class Requests_Exception_HTTP_504 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 504; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Gateway Timeout'; + } + /** + * Exception for 505 HTTP Version Not Supported responses + * + * @package Requests + */ + /** + * Exception for 505 HTTP Version Not Supported responses + * + * @package Requests + */ + class Requests_Exception_HTTP_505 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 505; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'HTTP Version Not Supported'; + } + /** + * Exception for 511 Network Authentication Required responses + * + * @see https://tools.ietf.org/html/rfc6585 + * @package Requests + */ + /** + * Exception for 511 Network Authentication Required responses + * + * @see https://tools.ietf.org/html/rfc6585 + * @package Requests + */ + class Requests_Exception_HTTP_511 extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer + */ + protected $code = 511; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Network Authentication Required'; + } + /** + * Exception for unknown status responses + * + * @package Requests + */ + /** + * Exception for unknown status responses + * + * @package Requests + */ + class Requests_Exception_HTTP_Unknown extends \Requests_Exception_HTTP + { + /** + * HTTP status code + * + * @var integer|bool Code if available, false if an error occurred + */ + protected $code = 0; + /** + * Reason phrase + * + * @var string + */ + protected $reason = 'Unknown'; + /** + * Create a new exception + * + * If `$data` is an instance of {@see Requests_Response}, uses the status + * code from it. Otherwise, sets as 0 + * + * @param string|null $reason Reason phrase + * @param mixed $data Associated data + */ + public function __construct($reason = \null, $data = \null) + { + } + } + class Requests_Exception_Transport extends \Requests_Exception + { + } + class Requests_Exception_Transport_cURL extends \Requests_Exception_Transport + { + const EASY = 'cURLEasy'; + const MULTI = 'cURLMulti'; + const SHARE = 'cURLShare'; + /** + * cURL error code + * + * @var integer + */ + protected $code = -1; + /** + * Which type of cURL error + * + * EASY|MULTI|SHARE + * + * @var string + */ + protected $type = 'Unknown'; + /** + * Clear text error message + * + * @var string + */ + protected $reason = 'Unknown'; + public function __construct($message, $type, $data = \null, $code = 0) + { + } + /** + * Get the error message + */ + public function getReason() + { + } + } + /** + * Event dispatcher + * + * @package Requests + * @subpackage Utilities + */ + /** + * Event dispatcher + * + * @package Requests + * @subpackage Utilities + */ + interface Requests_Hooker + { + /** + * Register a callback for a hook + * + * @param string $hook Hook name + * @param callback $callback Function/method to call on event + * @param int $priority Priority number. <0 is executed earlier, >0 is executed later + */ + public function register($hook, $callback, $priority = 0); + /** + * Dispatch a message + * + * @param string $hook Hook name + * @param array $parameters Parameters to pass to callbacks + * @return boolean Successfulness + */ + public function dispatch($hook, $parameters = array()); + } + /** + * Handles adding and dispatching events + * + * @package Requests + * @subpackage Utilities + */ + /** + * Handles adding and dispatching events + * + * @package Requests + * @subpackage Utilities + */ + class Requests_Hooks implements \Requests_Hooker + { + /** + * Registered callbacks for each hook + * + * @var array + */ + protected $hooks = array(); + /** + * Constructor + */ + public function __construct() + { + } + /** + * Register a callback for a hook + * + * @param string $hook Hook name + * @param callback $callback Function/method to call on event + * @param int $priority Priority number. <0 is executed earlier, >0 is executed later + */ + public function register($hook, $callback, $priority = 0) + { + } + /** + * Dispatch a message + * + * @param string $hook Hook name + * @param array $parameters Parameters to pass to callbacks + * @return boolean Successfulness + */ + public function dispatch($hook, $parameters = array()) + { + } + } + /** + * IDNA URL encoder + * + * Note: Not fully compliant, as nameprep does nothing yet. + * + * @package Requests + * @subpackage Utilities + * @see https://tools.ietf.org/html/rfc3490 IDNA specification + * @see https://tools.ietf.org/html/rfc3492 Punycode/Bootstrap specification + */ + class Requests_IDNAEncoder + { + /** + * ACE prefix used for IDNA + * + * @see https://tools.ietf.org/html/rfc3490#section-5 + * @var string + */ + const ACE_PREFIX = 'xn--'; + /**#@+ + * Bootstrap constant for Punycode + * + * @see https://tools.ietf.org/html/rfc3492#section-5 + * @var int + */ + const BOOTSTRAP_BASE = 36; + const BOOTSTRAP_TMIN = 1; + const BOOTSTRAP_TMAX = 26; + const BOOTSTRAP_SKEW = 38; + const BOOTSTRAP_DAMP = 700; + const BOOTSTRAP_INITIAL_BIAS = 72; + const BOOTSTRAP_INITIAL_N = 128; + /**#@-*/ + /** + * Encode a hostname using Punycode + * + * @param string $string Hostname + * @return string Punycode-encoded hostname + */ + public static function encode($string) + { + } + /** + * Convert a UTF-8 string to an ASCII string using Punycode + * + * @throws Requests_Exception Provided string longer than 64 ASCII characters (`idna.provided_too_long`) + * @throws Requests_Exception Prepared string longer than 64 ASCII characters (`idna.prepared_too_long`) + * @throws Requests_Exception Provided string already begins with xn-- (`idna.provided_is_prefixed`) + * @throws Requests_Exception Encoded string longer than 64 ASCII characters (`idna.encoded_too_long`) + * + * @param string $string ASCII or UTF-8 string (max length 64 characters) + * @return string ASCII string + */ + public static function to_ascii($string) + { + } + /** + * Check whether a given string contains only ASCII characters + * + * @internal (Testing found regex was the fastest implementation) + * + * @param string $string + * @return bool Is the string ASCII-only? + */ + protected static function is_ascii($string) + { + } + /** + * Prepare a string for use as an IDNA name + * + * @todo Implement this based on RFC 3491 and the newer 5891 + * @param string $string + * @return string Prepared string + */ + protected static function nameprep($string) + { + } + /** + * Convert a UTF-8 string to a UCS-4 codepoint array + * + * Based on Requests_IRI::replace_invalid_with_pct_encoding() + * + * @throws Requests_Exception Invalid UTF-8 codepoint (`idna.invalidcodepoint`) + * @param string $input + * @return array Unicode code points + */ + protected static function utf8_to_codepoints($input) + { + } + /** + * RFC3492-compliant encoder + * + * @internal Pseudo-code from Section 6.3 is commented with "#" next to relevant code + * @throws Requests_Exception On character outside of the domain (never happens with Punycode) (`idna.character_outside_domain`) + * + * @param string $input UTF-8 encoded string to encode + * @return string Punycode-encoded string + */ + public static function punycode_encode($input) + { + } + /** + * Convert a digit to its respective character + * + * @see https://tools.ietf.org/html/rfc3492#section-5 + * @throws Requests_Exception On invalid digit (`idna.invalid_digit`) + * + * @param int $digit Digit in the range 0-35 + * @return string Single character corresponding to digit + */ + protected static function digit_to_char($digit) + { + } + /** + * Adapt the bias + * + * @see https://tools.ietf.org/html/rfc3492#section-6.1 + * @param int $delta + * @param int $numpoints + * @param bool $firsttime + * @return int New bias + * + * function adapt(delta,numpoints,firsttime): + */ + protected static function adapt($delta, $numpoints, $firsttime) + { + } + } + /** + * Class to validate and to work with IPv6 addresses + * + * @package Requests + * @subpackage Utilities + */ + /** + * Class to validate and to work with IPv6 addresses + * + * This was originally based on the PEAR class of the same name, but has been + * entirely rewritten. + * + * @package Requests + * @subpackage Utilities + */ + class Requests_IPv6 + { + /** + * Uncompresses an IPv6 address + * + * RFC 4291 allows you to compress consecutive zero pieces in an address to + * '::'. This method expects a valid IPv6 address and expands the '::' to + * the required number of zero pieces. + * + * Example: FF01::101 -> FF01:0:0:0:0:0:0:101 + * ::1 -> 0:0:0:0:0:0:0:1 + * + * @author Alexander Merz + * @author elfrink at introweb dot nl + * @author Josh Peck + * @copyright 2003-2005 The PHP Group + * @license http://www.opensource.org/licenses/bsd-license.php + * @param string $ip An IPv6 address + * @return string The uncompressed IPv6 address + */ + public static function uncompress($ip) + { + } + /** + * Compresses an IPv6 address + * + * RFC 4291 allows you to compress consecutive zero pieces in an address to + * '::'. This method expects a valid IPv6 address and compresses consecutive + * zero pieces to '::'. + * + * Example: FF01:0:0:0:0:0:0:101 -> FF01::101 + * 0:0:0:0:0:0:0:1 -> ::1 + * + * @see uncompress() + * @param string $ip An IPv6 address + * @return string The compressed IPv6 address + */ + public static function compress($ip) + { + } + /** + * Splits an IPv6 address into the IPv6 and IPv4 representation parts + * + * RFC 4291 allows you to represent the last two parts of an IPv6 address + * using the standard IPv4 representation + * + * Example: 0:0:0:0:0:0:13.1.68.3 + * 0:0:0:0:0:FFFF:129.144.52.38 + * + * @param string $ip An IPv6 address + * @return string[] [0] contains the IPv6 represented part, and [1] the IPv4 represented part + */ + protected static function split_v6_v4($ip) + { + } + /** + * Checks an IPv6 address + * + * Checks if the given IP is a valid IPv6 address + * + * @param string $ip An IPv6 address + * @return bool true if $ip is a valid IPv6 address + */ + public static function check_ipv6($ip) + { + } + } + /** + * IRI parser/serialiser/normaliser + * + * @package Requests + * @subpackage Utilities + */ + /** + * IRI parser/serialiser/normaliser + * + * Copyright (c) 2007-2010, Geoffrey Sneddon and Steve Minutillo. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package Requests + * @subpackage Utilities + * @author Geoffrey Sneddon + * @author Steve Minutillo + * @copyright 2007-2009 Geoffrey Sneddon and Steve Minutillo + * @license http://www.opensource.org/licenses/bsd-license.php + * @link http://hg.gsnedders.com/iri/ + * + * @property string $iri IRI we're working with + * @property-read string $uri IRI in URI form, {@see to_uri} + * @property string $scheme Scheme part of the IRI + * @property string $authority Authority part, formatted for a URI (userinfo + host + port) + * @property string $iauthority Authority part of the IRI (userinfo + host + port) + * @property string $userinfo Userinfo part, formatted for a URI (after '://' and before '@') + * @property string $iuserinfo Userinfo part of the IRI (after '://' and before '@') + * @property string $host Host part, formatted for a URI + * @property string $ihost Host part of the IRI + * @property string $port Port part of the IRI (after ':') + * @property string $path Path part, formatted for a URI (after first '/') + * @property string $ipath Path part of the IRI (after first '/') + * @property string $query Query part, formatted for a URI (after '?') + * @property string $iquery Query part of the IRI (after '?') + * @property string $fragment Fragment, formatted for a URI (after '#') + * @property string $ifragment Fragment part of the IRI (after '#') + */ + class Requests_IRI + { + /** + * Scheme + * + * @var string|null + */ + protected $scheme = \null; + /** + * User Information + * + * @var string|null + */ + protected $iuserinfo = \null; + /** + * ihost + * + * @var string|null + */ + protected $ihost = \null; + /** + * Port + * + * @var string|null + */ + protected $port = \null; + /** + * ipath + * + * @var string + */ + protected $ipath = ''; + /** + * iquery + * + * @var string|null + */ + protected $iquery = \null; + /** + * ifragment|null + * + * @var string + */ + protected $ifragment = \null; + /** + * Normalization database + * + * Each key is the scheme, each value is an array with each key as the IRI + * part and value as the default value for that part. + * + * @var array + */ + protected $normalization = array('acap' => array('port' => 674), 'dict' => array('port' => 2628), 'file' => array('ihost' => 'localhost'), 'http' => array('port' => 80), 'https' => array('port' => 443)); + /** + * Return the entire IRI when you try and read the object as a string + * + * @return string + */ + public function __toString() + { + } + /** + * Overload __set() to provide access via properties + * + * @param string $name Property name + * @param mixed $value Property value + */ + public function __set($name, $value) + { + } + /** + * Overload __get() to provide access via properties + * + * @param string $name Property name + * @return mixed + */ + public function __get($name) + { + } + /** + * Overload __isset() to provide access via properties + * + * @param string $name Property name + * @return bool + */ + public function __isset($name) + { + } + /** + * Overload __unset() to provide access via properties + * + * @param string $name Property name + */ + public function __unset($name) + { + } + /** + * Create a new IRI object, from a specified string + * + * @param string|null $iri + */ + public function __construct($iri = \null) + { + } + /** + * Create a new IRI object by resolving a relative IRI + * + * Returns false if $base is not absolute, otherwise an IRI. + * + * @param Requests_IRI|string $base (Absolute) Base IRI + * @param Requests_IRI|string $relative Relative IRI + * @return Requests_IRI|false + */ + public static function absolutize($base, $relative) + { + } + /** + * Parse an IRI into scheme/authority/path/query/fragment segments + * + * @param string $iri + * @return array + */ + protected function parse_iri($iri) + { + } + /** + * Remove dot segments from a path + * + * @param string $input + * @return string + */ + protected function remove_dot_segments($input) + { + } + /** + * Replace invalid character with percent encoding + * + * @param string $string Input string + * @param string $extra_chars Valid characters not in iunreserved or + * iprivate (this is ASCII-only) + * @param bool $iprivate Allow iprivate + * @return string + */ + protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = \false) + { + } + /** + * Callback function for preg_replace_callback. + * + * Removes sequences of percent encoded bytes that represent UTF-8 + * encoded characters in iunreserved + * + * @param array $match PCRE match + * @return string Replacement + */ + protected function remove_iunreserved_percent_encoded($match) + { + } + protected function scheme_normalization() + { + } + /** + * Check if the object represents a valid IRI. This needs to be done on each + * call as some things change depending on another part of the IRI. + * + * @return bool + */ + public function is_valid() + { + } + /** + * Set the entire IRI. Returns true on success, false on failure (if there + * are any invalid characters). + * + * @param string $iri + * @return bool + */ + protected function set_iri($iri) + { + } + /** + * Set the scheme. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $scheme + * @return bool + */ + protected function set_scheme($scheme) + { + } + /** + * Set the authority. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $authority + * @return bool + */ + protected function set_authority($authority) + { + } + /** + * Set the iuserinfo. + * + * @param string $iuserinfo + * @return bool + */ + protected function set_userinfo($iuserinfo) + { + } + /** + * Set the ihost. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $ihost + * @return bool + */ + protected function set_host($ihost) + { + } + /** + * Set the port. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $port + * @return bool + */ + protected function set_port($port) + { + } + /** + * Set the ipath. + * + * @param string $ipath + * @return bool + */ + protected function set_path($ipath) + { + } + /** + * Set the iquery. + * + * @param string $iquery + * @return bool + */ + protected function set_query($iquery) + { + } + /** + * Set the ifragment. + * + * @param string $ifragment + * @return bool + */ + protected function set_fragment($ifragment) + { + } + /** + * Convert an IRI to a URI (or parts thereof) + * + * @param string|bool IRI to convert (or false from {@see get_iri}) + * @return string|false URI if IRI is valid, false otherwise. + */ + protected function to_uri($string) + { + } + /** + * Get the complete IRI + * + * @return string|false + */ + protected function get_iri() + { + } + /** + * Get the complete URI + * + * @return string + */ + protected function get_uri() + { + } + /** + * Get the complete iauthority + * + * @return string|null + */ + protected function get_iauthority() + { + } + /** + * Get the complete authority + * + * @return string + */ + protected function get_authority() + { + } + } + /** + * Proxy connection interface + * + * @package Requests + * @subpackage Proxy + * @since 1.6 + */ + /** + * Proxy connection interface + * + * Implement this interface to handle proxy settings and authentication + * + * Parameters should be passed via the constructor where possible, as this + * makes it much easier for users to use your provider. + * + * @see Requests_Hooks + * @package Requests + * @subpackage Proxy + * @since 1.6 + */ + interface Requests_Proxy + { + /** + * Register hooks as needed + * + * This method is called in {@see Requests::request} when the user has set + * an instance as the 'auth' option. Use this callback to register all the + * hooks you'll need. + * + * @see Requests_Hooks::register + * @param Requests_Hooks $hooks Hook system + */ + public function register(\Requests_Hooks $hooks); + } + /** + * HTTP Proxy connection interface + * + * @package Requests + * @subpackage Proxy + * @since 1.6 + */ + /** + * HTTP Proxy connection interface + * + * Provides a handler for connection via an HTTP proxy + * + * @package Requests + * @subpackage Proxy + * @since 1.6 + */ + class Requests_Proxy_HTTP implements \Requests_Proxy + { + /** + * Proxy host and port + * + * Notation: "host:port" (eg 127.0.0.1:8080 or someproxy.com:3128) + * + * @var string + */ + public $proxy; + /** + * Username + * + * @var string + */ + public $user; + /** + * Password + * + * @var string + */ + public $pass; + /** + * Do we need to authenticate? (ie username & password have been provided) + * + * @var boolean + */ + public $use_authentication; + /** + * Constructor + * + * @since 1.6 + * @throws Requests_Exception On incorrect number of arguments (`authbasicbadargs`) + * @param array|null $args Array of user and password. Must have exactly two elements + */ + public function __construct($args = \null) + { + } + /** + * Register the necessary callbacks + * + * @since 1.6 + * @see curl_before_send + * @see fsockopen_remote_socket + * @see fsockopen_remote_host_path + * @see fsockopen_header + * @param Requests_Hooks $hooks Hook system + */ + public function register(\Requests_Hooks $hooks) + { + } + /** + * Set cURL parameters before the data is sent + * + * @since 1.6 + * @param resource $handle cURL resource + */ + public function curl_before_send(&$handle) + { + } + /** + * Alter remote socket information before opening socket connection + * + * @since 1.6 + * @param string $remote_socket Socket connection string + */ + public function fsockopen_remote_socket(&$remote_socket) + { + } + /** + * Alter remote path before getting stream data + * + * @since 1.6 + * @param string $path Path to send in HTTP request string ("GET ...") + * @param string $url Full URL we're requesting + */ + public function fsockopen_remote_host_path(&$path, $url) + { + } + /** + * Add extra headers to the request before sending + * + * @since 1.6 + * @param string $out HTTP header string + */ + public function fsockopen_header(&$out) + { + } + /** + * Get the authentication string (user:pass) + * + * @since 1.6 + * @return string + */ + public function get_auth_string() + { + } + } + /** + * HTTP response class + * + * Contains a response from Requests::request() + * @package Requests + */ + /** + * HTTP response class + * + * Contains a response from Requests::request() + * @package Requests + */ + class Requests_Response + { + /** + * Constructor + */ + public function __construct() + { + } + /** + * Response body + * + * @var string + */ + public $body = ''; + /** + * Raw HTTP data from the transport + * + * @var string + */ + public $raw = ''; + /** + * Headers, as an associative array + * + * @var Requests_Response_Headers Array-like object representing headers + */ + public $headers = array(); + /** + * Status code, false if non-blocking + * + * @var integer|boolean + */ + public $status_code = \false; + /** + * Protocol version, false if non-blocking + * + * @var float|boolean + */ + public $protocol_version = \false; + /** + * Whether the request succeeded or not + * + * @var boolean + */ + public $success = \false; + /** + * Number of redirects the request used + * + * @var integer + */ + public $redirects = 0; + /** + * URL requested + * + * @var string + */ + public $url = ''; + /** + * Previous requests (from redirects) + * + * @var array Array of Requests_Response objects + */ + public $history = array(); + /** + * Cookies from the request + * + * @var Requests_Cookie_Jar Array-like object representing a cookie jar + */ + public $cookies = array(); + /** + * Is the response a redirect? + * + * @return boolean True if redirect (3xx status), false if not. + */ + public function is_redirect() + { + } + /** + * Throws an exception if the request was not successful + * + * @throws Requests_Exception If `$allow_redirects` is false, and code is 3xx (`response.no_redirects`) + * @throws Requests_Exception_HTTP On non-successful status code. Exception class corresponds to code (e.g. {@see Requests_Exception_HTTP_404}) + * @param boolean $allow_redirects Set to false to throw on a 3xx as well + */ + public function throw_for_status($allow_redirects = \true) + { + } + } + /** + * Case-insensitive dictionary, suitable for HTTP headers + * + * @package Requests + * @subpackage Utilities + */ + /** + * Case-insensitive dictionary, suitable for HTTP headers + * + * @package Requests + * @subpackage Utilities + */ + class Requests_Utility_CaseInsensitiveDictionary implements \ArrayAccess, \IteratorAggregate + { + /** + * Actual item data + * + * @var array + */ + protected $data = array(); + /** + * Creates a case insensitive dictionary. + * + * @param array $data Dictionary/map to convert to case-insensitive + */ + public function __construct(array $data = array()) + { + } + /** + * Check if the given item exists + * + * @param string $key Item key + * @return boolean Does the item exist? + */ + #[ReturnTypeWillChange] + public function offsetExists($key) + { + } + /** + * Get the value for the item + * + * @param string $key Item key + * @return string|null Item value (null if offsetExists is false) + */ + #[ReturnTypeWillChange] + public function offsetGet($key) + { + } + /** + * Set the given item + * + * @throws Requests_Exception On attempting to use dictionary as list (`invalidset`) + * + * @param string $key Item name + * @param string $value Item value + */ + #[ReturnTypeWillChange] + public function offsetSet($key, $value) + { + } + /** + * Unset the given header + * + * @param string $key + */ + #[ReturnTypeWillChange] + public function offsetUnset($key) + { + } + /** + * Get an iterator for the data + * + * @return ArrayIterator + */ + #[ReturnTypeWillChange] + public function getIterator() + { + } + /** + * Get the headers as an array + * + * @return array Header data + */ + public function getAll() + { + } + } + /** + * Case-insensitive dictionary, suitable for HTTP headers + * + * @package Requests + */ + /** + * Case-insensitive dictionary, suitable for HTTP headers + * + * @package Requests + */ + class Requests_Response_Headers extends \Requests_Utility_CaseInsensitiveDictionary + { + /** + * Get the given header + * + * Unlike {@see self::getValues()}, this returns a string. If there are + * multiple values, it concatenates them with a comma as per RFC2616. + * + * Avoid using this where commas may be used unquoted in values, such as + * Set-Cookie headers. + * + * @param string $key + * @return string|null Header value + */ + public function offsetGet($key) + { + } + /** + * Set the given item + * + * @throws Requests_Exception On attempting to use dictionary as list (`invalidset`) + * + * @param string $key Item name + * @param string $value Item value + */ + public function offsetSet($key, $value) + { + } + /** + * Get all values for a given header + * + * @param string $key + * @return array|null Header values + */ + public function getValues($key) + { + } + /** + * Flattens a value into a string + * + * Converts an array into a string by imploding values with a comma, as per + * RFC2616's rules for folding headers. + * + * @param string|array $value Value to flatten + * @return string Flattened value + */ + public function flatten($value) + { + } + /** + * Get an iterator for the data + * + * Converts the internal + * @return ArrayIterator + */ + public function getIterator() + { + } + } + /** + * SSL utilities for Requests + * + * @package Requests + * @subpackage Utilities + */ + /** + * SSL utilities for Requests + * + * Collection of utilities for working with and verifying SSL certificates. + * + * @package Requests + * @subpackage Utilities + */ + class Requests_SSL + { + /** + * Verify the certificate against common name and subject alternative names + * + * Unfortunately, PHP doesn't check the certificate against the alternative + * names, leading things like 'https://www.github.com/' to be invalid. + * + * @see https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1 + * + * @throws Requests_Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`) + * @param string $host Host name to verify against + * @param array $cert Certificate data from openssl_x509_parse() + * @return bool + */ + public static function verify_certificate($host, $cert) + { + } + /** + * Verify that a reference name is valid + * + * Verifies a dNSName for HTTPS usage, (almost) as per Firefox's rules: + * - Wildcards can only occur in a name with more than 3 components + * - Wildcards can only occur as the last character in the first + * component + * - Wildcards may be preceded by additional characters + * + * We modify these rules to be a bit stricter and only allow the wildcard + * character to be the full first component; that is, with the exclusion of + * the third rule. + * + * @param string $reference Reference dNSName + * @return boolean Is the name valid? + */ + public static function verify_reference_name($reference) + { + } + /** + * Match a hostname against a dNSName reference + * + * @param string $host Requested host + * @param string $reference dNSName to match against + * @return boolean Does the domain match? + */ + public static function match_domain($host, $reference) + { + } + } + /** + * Session handler for persistent requests and default parameters + * + * @package Requests + * @subpackage Session Handler + */ + /** + * Session handler for persistent requests and default parameters + * + * Allows various options to be set as default values, and merges both the + * options and URL properties together. A base URL can be set for all requests, + * with all subrequests resolved from this. Base options can be set (including + * a shared cookie jar), then overridden for individual requests. + * + * @package Requests + * @subpackage Session Handler + */ + class Requests_Session + { + /** + * Base URL for requests + * + * URLs will be made absolute using this as the base + * + * @var string|null + */ + public $url = \null; + /** + * Base headers for requests + * + * @var array + */ + public $headers = array(); + /** + * Base data for requests + * + * If both the base data and the per-request data are arrays, the data will + * be merged before sending the request. + * + * @var array + */ + public $data = array(); + /** + * Base options for requests + * + * The base options are merged with the per-request data for each request. + * The only default option is a shared cookie jar between requests. + * + * Values here can also be set directly via properties on the Session + * object, e.g. `$session->useragent = 'X';` + * + * @var array + */ + public $options = array(); + /** + * Create a new session + * + * @param string|null $url Base URL for requests + * @param array $headers Default headers for requests + * @param array $data Default data for requests + * @param array $options Default options for requests + */ + public function __construct($url = \null, $headers = array(), $data = array(), $options = array()) + { + } + /** + * Get a property's value + * + * @param string $key Property key + * @return mixed|null Property value, null if none found + */ + public function __get($key) + { + } + /** + * Set a property's value + * + * @param string $key Property key + * @param mixed $value Property value + */ + public function __set($key, $value) + { + } + /** + * Remove a property's value + * + * @param string $key Property key + */ + public function __isset($key) + { + } + /** + * Remove a property's value + * + * @param string $key Property key + */ + public function __unset($key) + { + } + /**#@+ + * @see request() + * @param string $url + * @param array $headers + * @param array $options + * @return Requests_Response + */ + /** + * Send a GET request + */ + public function get($url, $headers = array(), $options = array()) + { + } + /** + * Send a HEAD request + */ + public function head($url, $headers = array(), $options = array()) + { + } + /** + * Send a DELETE request + */ + public function delete($url, $headers = array(), $options = array()) + { + } + /**#@-*/ + /**#@+ + * @see request() + * @param string $url + * @param array $headers + * @param array $data + * @param array $options + * @return Requests_Response + */ + /** + * Send a POST request + */ + public function post($url, $headers = array(), $data = array(), $options = array()) + { + } + /** + * Send a PUT request + */ + public function put($url, $headers = array(), $data = array(), $options = array()) + { + } + /** + * Send a PATCH request + * + * Note: Unlike {@see post} and {@see put}, `$headers` is required, as the + * specification recommends that should send an ETag + * + * @link https://tools.ietf.org/html/rfc5789 + */ + public function patch($url, $headers, $data = array(), $options = array()) + { + } + /**#@-*/ + /** + * Main interface for HTTP requests + * + * This method initiates a request and sends it via a transport before + * parsing. + * + * @see Requests::request() + * + * @throws Requests_Exception On invalid URLs (`nonhttp`) + * + * @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 (use Requests constants) + * @param array $options Options for the request (see {@see Requests::request}) + * @return Requests_Response + */ + public function request($url, $headers = array(), $data = array(), $type = \Requests::GET, $options = array()) + { + } + /** + * Send multiple HTTP requests simultaneously + * + * @see Requests::request_multiple() + * + * @param array $requests Requests data (see {@see Requests::request_multiple}) + * @param array $options Global and default options (see {@see Requests::request}) + * @return array Responses (either Requests_Response or a Requests_Exception object) + */ + public function request_multiple($requests, $options = array()) + { + } + /** + * Merge a request's data with the default data + * + * @param array $request Request data (same form as {@see request_multiple}) + * @param boolean $merge_options Should we merge options as well? + * @return array Request data + */ + protected function merge_request($request, $merge_options = \true) + { + } + } + /** + * Base HTTP transport + * + * @package Requests + * @subpackage Transport + */ + /** + * Base HTTP transport + * + * @package Requests + * @subpackage Transport + */ + interface Requests_Transport + { + /** + * Perform a request + * + * @param string $url URL to request + * @param array $headers Associative array of request headers + * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD + * @param array $options Request options, see {@see Requests::response()} for documentation + * @return string Raw HTTP result + */ + public function request($url, $headers = array(), $data = array(), $options = array()); + /** + * Send multiple requests simultaneously + * + * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see Requests_Transport::request} + * @param array $options Global options, see {@see Requests::response()} for documentation + * @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well) + */ + public function request_multiple($requests, $options); + /** + * Self-test whether the transport can be used + * @return bool + */ + public static function test(); + } + /** + * cURL HTTP transport + * + * @package Requests + * @subpackage Transport + */ + /** + * cURL HTTP transport + * + * @package Requests + * @subpackage Transport + */ + class Requests_Transport_cURL implements \Requests_Transport + { + const CURL_7_10_5 = 0x70a05; + const CURL_7_16_2 = 0x71002; + /** + * Raw HTTP data + * + * @var string + */ + public $headers = ''; + /** + * Raw body data + * + * @var string + */ + public $response_data = ''; + /** + * Information on the current request + * + * @var array cURL information array, see {@see https://secure.php.net/curl_getinfo} + */ + public $info; + /** + * cURL version number + * + * @var int + */ + public $version; + /** + * cURL handle + * + * @var resource + */ + protected $handle; + /** + * Hook dispatcher instance + * + * @var Requests_Hooks + */ + protected $hooks; + /** + * Have we finished the headers yet? + * + * @var boolean + */ + protected $done_headers = \false; + /** + * If streaming to a file, keep the file pointer + * + * @var resource + */ + protected $stream_handle; + /** + * How many bytes are in the response body? + * + * @var int + */ + protected $response_bytes; + /** + * What's the maximum number of bytes we should keep? + * + * @var int|bool Byte count, or false if no limit. + */ + protected $response_byte_limit; + /** + * Constructor + */ + public function __construct() + { + } + /** + * Destructor + */ + public function __destruct() + { + } + /** + * Perform a request + * + * @throws Requests_Exception On a cURL error (`curlerror`) + * + * @param string $url URL to request + * @param array $headers Associative array of request headers + * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD + * @param array $options Request options, see {@see Requests::response()} for documentation + * @return string Raw HTTP result + */ + public function request($url, $headers = array(), $data = array(), $options = array()) + { + } + /** + * Send multiple requests simultaneously + * + * @param array $requests Request data + * @param array $options Global options + * @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well) + */ + public function request_multiple($requests, $options) + { + } + /** + * Get the cURL handle for use in a multi-request + * + * @param string $url URL to request + * @param array $headers Associative array of request headers + * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD + * @param array $options Request options, see {@see Requests::response()} for documentation + * @return resource Subrequest's cURL handle + */ + public function &get_subrequest_handle($url, $headers, $data, $options) + { + } + /** + * Setup the cURL handle for the given data + * + * @param string $url URL to request + * @param array $headers Associative array of request headers + * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD + * @param array $options Request options, see {@see Requests::response()} for documentation + */ + protected function setup_handle($url, $headers, $data, $options) + { + } + /** + * Process a response + * + * @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 Requests_Exception + */ + public function process_response($response, $options) + { + } + /** + * Collect the headers as they are received + * + * @param resource $handle cURL resource + * @param string $headers Header string + * @return integer Length of provided header + */ + public function stream_headers($handle, $headers) + { + } + /** + * Collect data as it's received + * + * @since 1.6.1 + * + * @param resource $handle cURL resource + * @param string $data Body data + * @return integer Length of provided data + */ + public function stream_body($handle, $data) + { + } + /** + * Format a URL given GET data + * + * @param string $url + * @param array|object $data Data to build query using, see {@see https://secure.php.net/http_build_query} + * @return string URL with data + */ + protected static function format_get($url, $data) + { + } + /** + * Whether this transport is valid + * + * @codeCoverageIgnore + * @return boolean True if the transport is valid, false otherwise. + */ + public static function test($capabilities = array()) + { + } + /** + * Get the correct "Expect" header for the given request data. + * + * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD. + * @return string The "Expect" header. + */ + protected function get_expect_header($data) + { + } + } + /** + * fsockopen HTTP transport + * + * @package Requests + * @subpackage Transport + */ + /** + * fsockopen HTTP transport + * + * @package Requests + * @subpackage Transport + */ + class Requests_Transport_fsockopen implements \Requests_Transport + { + /** + * Second to microsecond conversion + * + * @var integer + */ + const SECOND_IN_MICROSECONDS = 1000000; + /** + * Raw HTTP data + * + * @var string + */ + public $headers = ''; + /** + * Stream metadata + * + * @var array Associative array of properties, see {@see https://secure.php.net/stream_get_meta_data} + */ + public $info; + /** + * What's the maximum number of bytes we should keep? + * + * @var int|bool Byte count, or false if no limit. + */ + protected $max_bytes = \false; + protected $connect_error = ''; + /** + * Perform a request + * + * @throws Requests_Exception On failure to connect to socket (`fsockopenerror`) + * @throws Requests_Exception On socket timeout (`timeout`) + * + * @param string $url URL to request + * @param array $headers Associative array of request headers + * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD + * @param array $options Request options, see {@see Requests::response()} for documentation + * @return string Raw HTTP result + */ + public function request($url, $headers = array(), $data = array(), $options = array()) + { + } + /** + * Send multiple requests simultaneously + * + * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see Requests_Transport::request} + * @param array $options Global options, see {@see Requests::response()} for documentation + * @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well) + */ + public function request_multiple($requests, $options) + { + } + /** + * Retrieve the encodings we can accept + * + * @return string Accept-Encoding header value + */ + protected static function accept_encoding() + { + } + /** + * Format a URL given GET data + * + * @param array $url_parts + * @param array|object $data Data to build query using, see {@see https://secure.php.net/http_build_query} + * @return string URL with data + */ + protected static function format_get($url_parts, $data) + { + } + /** + * Error handler for stream_socket_client() + * + * @param int $errno Error number (e.g. E_WARNING) + * @param string $errstr Error message + */ + public function connect_error_handler($errno, $errstr) + { + } + /** + * Verify the certificate against common name and subject alternative names + * + * Unfortunately, PHP doesn't check the certificate against the alternative + * names, leading things like 'https://www.github.com/' to be invalid. + * Instead + * + * @see https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1 + * + * @throws Requests_Exception On failure to connect via TLS (`fsockopen.ssl.connect_error`) + * @throws Requests_Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`) + * @param string $host Host name to verify against + * @param resource $context Stream context + * @return bool + */ + public function verify_certificate_from_context($host, $context) + { + } + /** + * Whether this transport is valid + * + * @codeCoverageIgnore + * @return boolean True if the transport is valid, false otherwise. + */ + public static function test($capabilities = array()) + { + } + } + /** + * Iterator for arrays requiring filtered values + * + * @package Requests + * @subpackage Utilities + */ + /** + * Iterator for arrays requiring filtered values + * + * @package Requests + * @subpackage Utilities + */ + class Requests_Utility_FilteredIterator extends \ArrayIterator + { + /** + * Callback to run as a filter + * + * @var callable + */ + protected $callback; + /** + * Create a new iterator + * + * @param array $data + * @param callable $callback Callback to be called on each value + */ + public function __construct($data, $callback) + { + } + /** + * Get the current item's value after filtering + * + * @return string + */ + #[ReturnTypeWillChange] + public function current() + { + } + /** + * @inheritdoc + */ + #[ReturnTypeWillChange] + public function unserialize($serialized) + { + } + /** + * @inheritdoc + * + * @phpcs:disable PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.MethodDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.NewMagicMethods.__unserializeFound + */ + #[ReturnTypeWillChange] + public function __unserialize($serialized) + { + } + public function __wakeup() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Manages all author-related data + * + * Used by {@see SimplePie_Item::get_author()} and {@see SimplePie::get_authors()} + * + * This class can be overloaded with {@see SimplePie::set_author_class()} + * + * @package SimplePie + * @subpackage API + */ + class SimplePie_Author + { + /** + * Author's name + * + * @var string + * @see get_name() + */ + var $name; + /** + * Author's link + * + * @var string + * @see get_link() + */ + var $link; + /** + * Author's email address + * + * @var string + * @see get_email() + */ + var $email; + /** + * Constructor, used to input the data + * + * @param string $name + * @param string $link + * @param string $email + */ + public function __construct($name = \null, $link = \null, $email = \null) + { + } + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + } + /** + * Author's name + * + * @return string|null + */ + public function get_name() + { + } + /** + * Author's link + * + * @return string|null + */ + public function get_link() + { + } + /** + * Author's email address + * + * @return string|null + */ + public function get_email() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Used to create cache objects + * + * This class can be overloaded with {@see SimplePie::set_cache_class()}, + * although the preferred way is to create your own handler + * via {@see register()} + * + * @package SimplePie + * @subpackage Caching + */ + class SimplePie_Cache + { + /** + * Cache handler classes + * + * These receive 3 parameters to their constructor, as documented in + * {@see register()} + * @var array + */ + protected static $handlers = array('mysql' => 'SimplePie_Cache_MySQL', 'memcache' => 'SimplePie_Cache_Memcache', 'memcached' => 'SimplePie_Cache_Memcached', 'redis' => 'SimplePie_Cache_Redis'); + /** + * Create a new SimplePie_Cache object + * + * @param string $location URL location (scheme is used to determine handler) + * @param string $filename Unique identifier for cache object + * @param string $extension 'spi' or 'spc' + * @return SimplePie_Cache_Base Type of object depends on scheme of `$location` + */ + public static function get_handler($location, $filename, $extension) + { + } + /** + * Create a new SimplePie_Cache object + * + * @deprecated Use {@see get_handler} instead + */ + public function create($location, $filename, $extension) + { + } + /** + * Register a handler + * + * @param string $type DSN type to register for + * @param string $class Name of handler class. Must implement SimplePie_Cache_Base + */ + public static function register($type, $class) + { + } + /** + * Parse a URL into an array + * + * @param string $url + * @return array + */ + public static function parse_URL($url) + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Base for cache objects + * + * Classes to be used with {@see SimplePie_Cache::register()} are expected + * to implement this interface. + * + * @package SimplePie + * @subpackage Caching + */ + interface SimplePie_Cache_Base + { + /** + * Feed cache type + * + * @var string + */ + const TYPE_FEED = 'spc'; + /** + * Image cache type + * + * @var string + */ + const TYPE_IMAGE = 'spi'; + /** + * Create a new cache object + * + * @param string $location Location string (from SimplePie::$cache_location) + * @param string $name Unique ID for the cache + * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data + */ + public function __construct($location, $name, $type); + /** + * Save data to the cache + * + * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property + * @return bool Successfulness + */ + public function save($data); + /** + * Retrieve the data saved to the cache + * + * @return array Data for SimplePie::$data + */ + public function load(); + /** + * Retrieve the last modified time for the cache + * + * @return int Timestamp + */ + public function mtime(); + /** + * Set the last modified time to the current time + * + * @return bool Success status + */ + public function touch(); + /** + * Remove the cache + * + * @return bool Success status + */ + public function unlink(); + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Base class for database-based caches + * + * @package SimplePie + * @subpackage Caching + */ + abstract class SimplePie_Cache_DB implements \SimplePie_Cache_Base + { + /** + * Helper for database conversion + * + * Converts a given {@see SimplePie} object into data to be stored + * + * @param SimplePie $data + * @return array First item is the serialized data for storage, second item is the unique ID for this item + */ + protected static function prepare_simplepie_object_for_cache($data) + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Caches data to the filesystem + * + * @package SimplePie + * @subpackage Caching + */ + class SimplePie_Cache_File implements \SimplePie_Cache_Base + { + /** + * Location string + * + * @see SimplePie::$cache_location + * @var string + */ + protected $location; + /** + * Filename + * + * @var string + */ + protected $filename; + /** + * File extension + * + * @var string + */ + protected $extension; + /** + * File path + * + * @var string + */ + protected $name; + /** + * Create a new cache object + * + * @param string $location Location string (from SimplePie::$cache_location) + * @param string $name Unique ID for the cache + * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data + */ + public function __construct($location, $name, $type) + { + } + /** + * Save data to the cache + * + * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property + * @return bool Successfulness + */ + public function save($data) + { + } + /** + * Retrieve the data saved to the cache + * + * @return array Data for SimplePie::$data + */ + public function load() + { + } + /** + * Retrieve the last modified time for the cache + * + * @return int Timestamp + */ + public function mtime() + { + } + /** + * Set the last modified time to the current time + * + * @return bool Success status + */ + public function touch() + { + } + /** + * Remove the cache + * + * @return bool Success status + */ + public function unlink() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Caches data to memcache + * + * Registered for URLs with the "memcache" protocol + * + * For example, `memcache://localhost:11211/?timeout=3600&prefix=sp_` will + * connect to memcache on `localhost` on port 11211. All tables will be + * prefixed with `sp_` and data will expire after 3600 seconds + * + * @package SimplePie + * @subpackage Caching + * @uses Memcache + */ + class SimplePie_Cache_Memcache implements \SimplePie_Cache_Base + { + /** + * Memcache instance + * + * @var Memcache + */ + protected $cache; + /** + * Options + * + * @var array + */ + protected $options; + /** + * Cache name + * + * @var string + */ + protected $name; + /** + * Create a new cache object + * + * @param string $location Location string (from SimplePie::$cache_location) + * @param string $name Unique ID for the cache + * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data + */ + public function __construct($location, $name, $type) + { + } + /** + * Save data to the cache + * + * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property + * @return bool Successfulness + */ + public function save($data) + { + } + /** + * Retrieve the data saved to the cache + * + * @return array Data for SimplePie::$data + */ + public function load() + { + } + /** + * Retrieve the last modified time for the cache + * + * @return int Timestamp + */ + public function mtime() + { + } + /** + * Set the last modified time to the current time + * + * @return bool Success status + */ + public function touch() + { + } + /** + * Remove the cache + * + * @return bool Success status + */ + public function unlink() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Caches data to memcached + * + * Registered for URLs with the "memcached" protocol + * + * For example, `memcached://localhost:11211/?timeout=3600&prefix=sp_` will + * connect to memcached on `localhost` on port 11211. All tables will be + * prefixed with `sp_` and data will expire after 3600 seconds + * + * @package SimplePie + * @subpackage Caching + * @author Paul L. McNeely + * @uses Memcached + */ + class SimplePie_Cache_Memcached implements \SimplePie_Cache_Base + { + /** + * Memcached instance + * @var Memcached + */ + protected $cache; + /** + * Options + * @var array + */ + protected $options; + /** + * Cache name + * @var string + */ + protected $name; + /** + * Create a new cache object + * @param string $location Location string (from SimplePie::$cache_location) + * @param string $name Unique ID for the cache + * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data + */ + public function __construct($location, $name, $type) + { + } + /** + * Save data to the cache + * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property + * @return bool Successfulness + */ + public function save($data) + { + } + /** + * Retrieve the data saved to the cache + * @return array Data for SimplePie::$data + */ + public function load() + { + } + /** + * Retrieve the last modified time for the cache + * @return int Timestamp + */ + public function mtime() + { + } + /** + * Set the last modified time to the current time + * @return bool Success status + */ + public function touch() + { + } + /** + * Remove the cache + * @return bool Success status + */ + public function unlink() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Caches data to a MySQL database + * + * Registered for URLs with the "mysql" protocol + * + * For example, `mysql://root:password@localhost:3306/mydb?prefix=sp_` will + * connect to the `mydb` database on `localhost` on port 3306, with the user + * `root` and the password `password`. All tables will be prefixed with `sp_` + * + * @package SimplePie + * @subpackage Caching + */ + class SimplePie_Cache_MySQL extends \SimplePie_Cache_DB + { + /** + * PDO instance + * + * @var PDO + */ + protected $mysql; + /** + * Options + * + * @var array + */ + protected $options; + /** + * Cache ID + * + * @var string + */ + protected $id; + /** + * Create a new cache object + * + * @param string $location Location string (from SimplePie::$cache_location) + * @param string $name Unique ID for the cache + * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data + */ + public function __construct($location, $name, $type) + { + } + /** + * Save data to the cache + * + * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property + * @return bool Successfulness + */ + public function save($data) + { + } + /** + * Retrieve the data saved to the cache + * + * @return array Data for SimplePie::$data + */ + public function load() + { + } + /** + * Retrieve the last modified time for the cache + * + * @return int Timestamp + */ + public function mtime() + { + } + /** + * Set the last modified time to the current time + * + * @return bool Success status + */ + public function touch() + { + } + /** + * Remove the cache + * + * @return bool Success status + */ + public function unlink() + { + } + } + /** + * SimplePie Redis Cache Extension + * + * @package SimplePie + * @author Jan Kozak + * @link http://galvani.cz/ + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version 0.2.9 + */ + /** + * Caches data to redis + * + * Registered for URLs with the "redis" protocol + * + * For example, `redis://localhost:6379/?timeout=3600&prefix=sp_&dbIndex=0` will + * connect to redis on `localhost` on port 6379. All tables will be + * prefixed with `simple_primary-` and data will expire after 3600 seconds + * + * @package SimplePie + * @subpackage Caching + * @uses Redis + */ + class SimplePie_Cache_Redis implements \SimplePie_Cache_Base + { + /** + * Redis instance + * + * @var \Redis + */ + protected $cache; + /** + * Options + * + * @var array + */ + protected $options; + /** + * Cache name + * + * @var string + */ + protected $name; + /** + * Cache Data + * + * @var type + */ + protected $data; + /** + * Create a new cache object + * + * @param string $location Location string (from SimplePie::$cache_location) + * @param string $name Unique ID for the cache + * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data + */ + public function __construct($location, $name, $options = \null) + { + } + /** + * @param \Redis $cache + */ + public function setRedisClient(\Redis $cache) + { + } + /** + * Save data to the cache + * + * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property + * @return bool Successfulness + */ + public function save($data) + { + } + /** + * Retrieve the data saved to the cache + * + * @return array Data for SimplePie::$data + */ + public function load() + { + } + /** + * Retrieve the last modified time for the cache + * + * @return int Timestamp + */ + public function mtime() + { + } + /** + * Set the last modified time to the current time + * + * @return bool Success status + */ + public function touch() + { + } + /** + * Remove the cache + * + * @return bool Success status + */ + public function unlink() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Handles `` captions as defined in Media RSS. + * + * Used by {@see SimplePie_Enclosure::get_caption()} and {@see SimplePie_Enclosure::get_captions()} + * + * This class can be overloaded with {@see SimplePie::set_caption_class()} + * + * @package SimplePie + * @subpackage API + */ + class SimplePie_Caption + { + /** + * Content type + * + * @var string + * @see get_type() + */ + var $type; + /** + * Language + * + * @var string + * @see get_language() + */ + var $lang; + /** + * Start time + * + * @var string + * @see get_starttime() + */ + var $startTime; + /** + * End time + * + * @var string + * @see get_endtime() + */ + var $endTime; + /** + * Caption text + * + * @var string + * @see get_text() + */ + var $text; + /** + * Constructor, used to input the data + * + * For documentation on all the parameters, see the corresponding + * properties and their accessors + */ + public function __construct($type = \null, $lang = \null, $startTime = \null, $endTime = \null, $text = \null) + { + } + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + } + /** + * Get the end time + * + * @return string|null Time in the format 'hh:mm:ss.SSS' + */ + public function get_endtime() + { + } + /** + * Get the language + * + * @link http://tools.ietf.org/html/rfc3066 + * @return string|null Language code as per RFC 3066 + */ + public function get_language() + { + } + /** + * Get the start time + * + * @return string|null Time in the format 'hh:mm:ss.SSS' + */ + public function get_starttime() + { + } + /** + * Get the text of the caption + * + * @return string|null + */ + public function get_text() + { + } + /** + * Get the content type (not MIME type) + * + * @return string|null Either 'text' or 'html' + */ + public function get_type() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Manages all category-related data + * + * Used by {@see SimplePie_Item::get_category()} and {@see SimplePie_Item::get_categories()} + * + * This class can be overloaded with {@see SimplePie::set_category_class()} + * + * @package SimplePie + * @subpackage API + */ + class SimplePie_Category + { + /** + * Category identifier + * + * @var string|null + * @see get_term + */ + var $term; + /** + * Categorization scheme identifier + * + * @var string|null + * @see get_scheme() + */ + var $scheme; + /** + * Human readable label + * + * @var string|null + * @see get_label() + */ + var $label; + /** + * Category type + * + * category for + * subject for + * + * @var string|null + * @see get_type() + */ + var $type; + /** + * Constructor, used to input the data + * + * @param string|null $term + * @param string|null $scheme + * @param string|null $label + * @param string|null $type + */ + public function __construct($term = \null, $scheme = \null, $label = \null, $type = \null) + { + } + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + } + /** + * Get the category identifier + * + * @return string|null + */ + public function get_term() + { + } + /** + * Get the categorization scheme identifier + * + * @return string|null + */ + public function get_scheme() + { + } + /** + * Get the human readable label + * + * @param bool $strict + * @return string|null + */ + public function get_label($strict = \false) + { + } + /** + * Get the category type + * + * @return string|null + */ + public function get_type() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Content-type sniffing + * + * Based on the rules in http://tools.ietf.org/html/draft-abarth-mime-sniff-06 + * + * This is used since we can't always trust Content-Type headers, and is based + * upon the HTML5 parsing rules. + * + * + * This class can be overloaded with {@see SimplePie::set_content_type_sniffer_class()} + * + * @package SimplePie + * @subpackage HTTP + */ + class SimplePie_Content_Type_Sniffer + { + /** + * File object + * + * @var SimplePie_File + */ + var $file; + /** + * Create an instance of the class with the input file + * + * @param SimplePie_Content_Type_Sniffer $file Input file + */ + public function __construct($file) + { + } + /** + * Get the Content-Type of the specified file + * + * @return string Actual Content-Type + */ + public function get_type() + { + } + /** + * Sniff text or binary + * + * @return string Actual Content-Type + */ + public function text_or_binary() + { + } + /** + * Sniff unknown + * + * @return string Actual Content-Type + */ + public function unknown() + { + } + /** + * Sniff images + * + * @return string Actual Content-Type + */ + public function image() + { + } + /** + * Sniff HTML + * + * @return string Actual Content-Type + */ + public function feed_or_html() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Manages `` copyright tags as defined in Media RSS + * + * Used by {@see SimplePie_Enclosure::get_copyright()} + * + * This class can be overloaded with {@see SimplePie::set_copyright_class()} + * + * @package SimplePie + * @subpackage API + */ + class SimplePie_Copyright + { + /** + * Copyright URL + * + * @var string + * @see get_url() + */ + var $url; + /** + * Attribution + * + * @var string + * @see get_attribution() + */ + var $label; + /** + * Constructor, used to input the data + * + * For documentation on all the parameters, see the corresponding + * properties and their accessors + */ + public function __construct($url = \null, $label = \null) + { + } + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + } + /** + * Get the copyright URL + * + * @return string|null URL to copyright information + */ + public function get_url() + { + } + /** + * Get the attribution text + * + * @return string|null + */ + public function get_attribution() + { + } + } + /** + * SimplePie + * + * @package SimplePie + * @subpackage API + */ + class SimplePie + { + /** + * @var array Raw data + * @access private + */ + public $data = array(); + /** + * @var mixed Error string + * @access private + */ + public $error; + /** + * @var int HTTP status code + * @see SimplePie::status_code() + * @access private + */ + public $status_code; + /** + * @var object Instance of SimplePie_Sanitize (or other class) + * @see SimplePie::set_sanitize_class() + * @access private + */ + public $sanitize; + /** + * @var string SimplePie Useragent + * @see SimplePie::set_useragent() + * @access private + */ + public $useragent = \SIMPLEPIE_USERAGENT; + /** + * @var string Feed URL + * @see SimplePie::set_feed_url() + * @access private + */ + public $feed_url; + /** + * @var string Original feed URL, or new feed URL iff HTTP 301 Moved Permanently + * @see SimplePie::subscribe_url() + * @access private + */ + public $permanent_url = \null; + /** + * @var object Instance of SimplePie_File to use as a feed + * @see SimplePie::set_file() + * @access private + */ + public $file; + /** + * @var string Raw feed data + * @see SimplePie::set_raw_data() + * @access private + */ + public $raw_data; + /** + * @var int Timeout for fetching remote files + * @see SimplePie::set_timeout() + * @access private + */ + public $timeout = 10; + /** + * @var array Custom curl options + * @see SimplePie::set_curl_options() + * @access private + */ + public $curl_options = array(); + /** + * @var bool Forces fsockopen() to be used for remote files instead + * of cURL, even if a new enough version is installed + * @see SimplePie::force_fsockopen() + * @access private + */ + public $force_fsockopen = \false; + /** + * @var bool Force the given data/URL to be treated as a feed no matter what + * it appears like + * @see SimplePie::force_feed() + * @access private + */ + public $force_feed = \false; + /** + * @var bool Enable/Disable Caching + * @see SimplePie::enable_cache() + * @access private + */ + public $cache = \true; + /** + * @var bool Force SimplePie to fallback to expired cache, if enabled, + * when feed is unavailable. + * @see SimplePie::force_cache_fallback() + * @access private + */ + public $force_cache_fallback = \false; + /** + * @var int Cache duration (in seconds) + * @see SimplePie::set_cache_duration() + * @access private + */ + public $cache_duration = 3600; + /** + * @var int Auto-discovery cache duration (in seconds) + * @see SimplePie::set_autodiscovery_cache_duration() + * @access private + */ + public $autodiscovery_cache_duration = 604800; + // 7 Days. + /** + * @var string Cache location (relative to executing script) + * @see SimplePie::set_cache_location() + * @access private + */ + public $cache_location = './cache'; + /** + * @var string Function that creates the cache filename + * @see SimplePie::set_cache_name_function() + * @access private + */ + public $cache_name_function = 'md5'; + /** + * @var bool Reorder feed by date descending + * @see SimplePie::enable_order_by_date() + * @access private + */ + public $order_by_date = \true; + /** + * @var mixed Force input encoding to be set to the follow value + * (false, or anything type-cast to false, disables this feature) + * @see SimplePie::set_input_encoding() + * @access private + */ + public $input_encoding = \false; + /** + * @var int Feed Autodiscovery Level + * @see SimplePie::set_autodiscovery_level() + * @access private + */ + public $autodiscovery = \SIMPLEPIE_LOCATOR_ALL; + /** + * Class registry object + * + * @var SimplePie_Registry + */ + public $registry; + /** + * @var int Maximum number of feeds to check with autodiscovery + * @see SimplePie::set_max_checked_feeds() + * @access private + */ + public $max_checked_feeds = 10; + /** + * @var array All the feeds found during the autodiscovery process + * @see SimplePie::get_all_discovered_feeds() + * @access private + */ + public $all_discovered_feeds = array(); + /** + * @var string Web-accessible path to the handler_image.php file. + * @see SimplePie::set_image_handler() + * @access private + */ + public $image_handler = ''; + /** + * @var array Stores the URLs when multiple feeds are being initialized. + * @see SimplePie::set_feed_url() + * @access private + */ + public $multifeed_url = array(); + /** + * @var array Stores SimplePie objects when multiple feeds initialized. + * @access private + */ + public $multifeed_objects = array(); + /** + * @var array Stores the get_object_vars() array for use with multifeeds. + * @see SimplePie::set_feed_url() + * @access private + */ + public $config_settings = \null; + /** + * @var integer Stores the number of items to return per-feed with multifeeds. + * @see SimplePie::set_item_limit() + * @access private + */ + public $item_limit = 0; + /** + * @var bool Stores if last-modified and/or etag headers were sent with the + * request when checking a feed. + */ + public $check_modified = \false; + /** + * @var array Stores the default attributes to be stripped by strip_attributes(). + * @see SimplePie::strip_attributes() + * @access private + */ + public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'); + /** + * @var array Stores the default attributes to add to different tags by add_attributes(). + * @see SimplePie::add_attributes() + * @access private + */ + public $add_attributes = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none')); + /** + * @var array Stores the default tags to be stripped by strip_htmltags(). + * @see SimplePie::strip_htmltags() + * @access private + */ + public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'); + /** + * @var bool Should we throw exceptions, or use the old-style error property? + * @access private + */ + public $enable_exceptions = \false; + /** + * The SimplePie class contains feed level data and options + * + * To use SimplePie, create the SimplePie object with no parameters. You can + * then set configuration options using the provided methods. After setting + * them, you must initialise the feed using $feed->init(). At that point the + * object's methods and properties will be available to you. + * + * Previously, it was possible to pass in the feed URL along with cache + * options directly into the constructor. This has been removed as of 1.3 as + * it caused a lot of confusion. + * + * @since 1.0 Preview Release + */ + public function __construct() + { + } + /** + * Used for converting object to a string + */ + public function __toString() + { + } + /** + * Remove items that link back to this before destroying this object + */ + public function __destruct() + { + } + /** + * Force the given data/URL to be treated as a feed + * + * This tells SimplePie to ignore the content-type provided by the server. + * Be careful when using this option, as it will also disable autodiscovery. + * + * @since 1.1 + * @param bool $enable Force the given data/URL to be treated as a feed + */ + public function force_feed($enable = \false) + { + } + /** + * Set the URL of the feed you want to parse + * + * This allows you to enter the URL of the feed you want to parse, or the + * website you want to try to use auto-discovery on. This takes priority + * over any set raw data. + * + * You can set multiple feeds to mash together by passing an array instead + * of a string for the $url. Remember that with each additional feed comes + * additional processing and resources. + * + * @since 1.0 Preview Release + * @see set_raw_data() + * @param string|array $url This is the URL (or array of URLs) that you want to parse. + */ + public function set_feed_url($url) + { + } + /** + * Set an instance of {@see SimplePie_File} to use as a feed + * + * @param SimplePie_File &$file + * @return bool True on success, false on failure + */ + public function set_file(&$file) + { + } + /** + * Set the raw XML data to parse + * + * Allows you to use a string of RSS/Atom data instead of a remote feed. + * + * If you have a feed available as a string in PHP, you can tell SimplePie + * to parse that data string instead of a remote feed. Any set feed URL + * takes precedence. + * + * @since 1.0 Beta 3 + * @param string $data RSS or Atom data as a string. + * @see set_feed_url() + */ + public function set_raw_data($data) + { + } + /** + * Set the default timeout for fetching remote feeds + * + * This allows you to change the maximum time the feed's server to respond + * and send the feed back. + * + * @since 1.0 Beta 3 + * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed. + */ + public function set_timeout($timeout = 10) + { + } + /** + * Set custom curl options + * + * This allows you to change default curl options + * + * @since 1.0 Beta 3 + * @param array $curl_options Curl options to add to default settings + */ + public function set_curl_options(array $curl_options = array()) + { + } + /** + * Force SimplePie to use fsockopen() instead of cURL + * + * @since 1.0 Beta 3 + * @param bool $enable Force fsockopen() to be used + */ + public function force_fsockopen($enable = \false) + { + } + /** + * Enable/disable caching in SimplePie. + * + * This option allows you to disable caching all-together in SimplePie. + * However, disabling the cache can lead to longer load times. + * + * @since 1.0 Preview Release + * @param bool $enable Enable caching + */ + public function enable_cache($enable = \true) + { + } + /** + * SimplePie to continue to fall back to expired cache, if enabled, when + * feed is unavailable. + * + * This tells SimplePie to ignore any file errors and fall back to cache + * instead. This only works if caching is enabled and cached content + * still exists. + * @param bool $enable Force use of cache on fail. + */ + public function force_cache_fallback($enable = \false) + { + } + /** + * Set the length of time (in seconds) that the contents of a feed will be + * cached + * + * @param int $seconds The feed content cache duration + */ + public function set_cache_duration($seconds = 3600) + { + } + /** + * Set the length of time (in seconds) that the autodiscovered feed URL will + * be cached + * + * @param int $seconds The autodiscovered feed URL cache duration. + */ + public function set_autodiscovery_cache_duration($seconds = 604800) + { + } + /** + * Set the file system location where the cached files should be stored + * + * @param string $location The file system location. + */ + public function set_cache_location($location = './cache') + { + } + /** + * Return the filename (i.e. hash, without path and without extension) of the file to cache a given URL. + * @param string $url The URL of the feed to be cached. + * @return string A filename (i.e. hash, without path and without extension). + */ + public function get_cache_filename($url) + { + } + /** + * Set whether feed items should be sorted into reverse chronological order + * + * @param bool $enable Sort as reverse chronological order. + */ + public function enable_order_by_date($enable = \true) + { + } + /** + * Set the character encoding used to parse the feed + * + * This overrides the encoding reported by the feed, however it will fall + * back to the normal encoding detection if the override fails + * + * @param string $encoding Character encoding + */ + public function set_input_encoding($encoding = \false) + { + } + /** + * Set how much feed autodiscovery to do + * + * @see SIMPLEPIE_LOCATOR_NONE + * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY + * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION + * @see SIMPLEPIE_LOCATOR_LOCAL_BODY + * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION + * @see SIMPLEPIE_LOCATOR_REMOTE_BODY + * @see SIMPLEPIE_LOCATOR_ALL + * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator) + */ + public function set_autodiscovery_level($level = \SIMPLEPIE_LOCATOR_ALL) + { + } + /** + * Get the class registry + * + * Use this to override SimplePie's default classes + * @see SimplePie_Registry + * @return SimplePie_Registry + */ + public function &get_registry() + { + } + /**#@+ + * Useful when you are overloading or extending SimplePie's default classes. + * + * @deprecated Use {@see get_registry()} instead + * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation + * @param string $class Name of custom class + * @return boolean True on success, false otherwise + */ + /** + * Set which class SimplePie uses for caching + */ + public function set_cache_class($class = 'SimplePie_Cache') + { + } + /** + * Set which class SimplePie uses for auto-discovery + */ + public function set_locator_class($class = 'SimplePie_Locator') + { + } + /** + * Set which class SimplePie uses for XML parsing + */ + public function set_parser_class($class = 'SimplePie_Parser') + { + } + /** + * Set which class SimplePie uses for remote file fetching + */ + public function set_file_class($class = 'SimplePie_File') + { + } + /** + * Set which class SimplePie uses for data sanitization + */ + public function set_sanitize_class($class = 'SimplePie_Sanitize') + { + } + /** + * Set which class SimplePie uses for handling feed items + */ + public function set_item_class($class = 'SimplePie_Item') + { + } + /** + * Set which class SimplePie uses for handling author data + */ + public function set_author_class($class = 'SimplePie_Author') + { + } + /** + * Set which class SimplePie uses for handling category data + */ + public function set_category_class($class = 'SimplePie_Category') + { + } + /** + * Set which class SimplePie uses for feed enclosures + */ + public function set_enclosure_class($class = 'SimplePie_Enclosure') + { + } + /** + * Set which class SimplePie uses for `` captions + */ + public function set_caption_class($class = 'SimplePie_Caption') + { + } + /** + * Set which class SimplePie uses for `` + */ + public function set_copyright_class($class = 'SimplePie_Copyright') + { + } + /** + * Set which class SimplePie uses for `` + */ + public function set_credit_class($class = 'SimplePie_Credit') + { + } + /** + * Set which class SimplePie uses for `` + */ + public function set_rating_class($class = 'SimplePie_Rating') + { + } + /** + * Set which class SimplePie uses for `` + */ + public function set_restriction_class($class = 'SimplePie_Restriction') + { + } + /** + * Set which class SimplePie uses for content-type sniffing + */ + public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer') + { + } + /** + * Set which class SimplePie uses item sources + */ + public function set_source_class($class = 'SimplePie_Source') + { + } + /**#@-*/ + /** + * Set the user agent string + * + * @param string $ua New user agent string. + */ + public function set_useragent($ua = \SIMPLEPIE_USERAGENT) + { + } + /** + * Set callback function to create cache filename with + * + * @param mixed $function Callback function + */ + public function set_cache_name_function($function = 'md5') + { + } + /** + * Set options to make SP as fast as possible + * + * Forgoes a substantial amount of data sanitization in favor of speed. This + * turns SimplePie into a dumb parser of feeds. + * + * @param bool $set Whether to set them or not + */ + public function set_stupidly_fast($set = \false) + { + } + /** + * Set maximum number of feeds to check with autodiscovery + * + * @param int $max Maximum number of feeds to check + */ + public function set_max_checked_feeds($max = 10) + { + } + public function remove_div($enable = \true) + { + } + public function strip_htmltags($tags = '', $encode = \null) + { + } + public function encode_instead_of_strip($enable = \true) + { + } + public function strip_attributes($attribs = '') + { + } + public function add_attributes($attribs = '') + { + } + /** + * Set the output encoding + * + * Allows you to override SimplePie's output to match that of your webpage. + * This is useful for times when your webpages are not being served as + * UTF-8. This setting will be obeyed by {@see handle_content_type()}, and + * is similar to {@see set_input_encoding()}. + * + * It should be noted, however, that not all character encodings can support + * all characters. If your page is being served as ISO-8859-1 and you try + * to display a Japanese feed, you'll likely see garbled characters. + * Because of this, it is highly recommended to ensure that your webpages + * are served as UTF-8. + * + * The number of supported character encodings depends on whether your web + * host supports {@link http://php.net/mbstring mbstring}, + * {@link http://php.net/iconv iconv}, or both. See + * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for + * more information. + * + * @param string $encoding + */ + public function set_output_encoding($encoding = 'UTF-8') + { + } + public function strip_comments($strip = \false) + { + } + /** + * Set element/attribute key/value pairs of HTML attributes + * containing URLs that need to be resolved relative to the feed + * + * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite, + * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite, + * |q|@cite + * + * @since 1.0 + * @param array|null $element_attribute Element/attribute key/value pairs, null for default + */ + public function set_url_replacements($element_attribute = \null) + { + } + /** + * Set the list of domains for which to force HTTPS. + * @see SimplePie_Sanitize::set_https_domains() + * @param array List of HTTPS domains. Example array('biz', 'example.com', 'example.org', 'www.example.net'). + */ + public function set_https_domains($domains = array()) + { + } + /** + * Set the handler to enable the display of cached images. + * + * @param string $page Web-accessible path to the handler_image.php file. + * @param string $qs The query string that the value should be passed to. + */ + public function set_image_handler($page = \false, $qs = 'i') + { + } + /** + * Set the limit for items returned per-feed with multifeeds + * + * @param integer $limit The maximum number of items to return. + */ + public function set_item_limit($limit = 0) + { + } + /** + * Enable throwing exceptions + * + * @param boolean $enable Should we throw exceptions, or use the old-style error property? + */ + public function enable_exceptions($enable = \true) + { + } + /** + * Initialize the feed object + * + * This is what makes everything happen. Period. This is where all of the + * configuration options get processed, feeds are fetched, cached, and + * parsed, and all of that other good stuff. + * + * @return boolean True if successful, false otherwise + */ + public function init() + { + } + /** + * Fetch the data via SimplePie_File + * + * If the data is already cached, attempt to fetch it from there instead + * @param SimplePie_Cache_Base|false $cache Cache handler, or false to not load from the cache + * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type + */ + protected function fetch_data(&$cache) + { + } + /** + * Get the error message for the occurred error + * + * @return string|array Error message, or array of messages for multifeeds + */ + public function error() + { + } + /** + * Get the last HTTP status code + * + * @return int Status code + */ + public function status_code() + { + } + /** + * Get the raw XML + * + * This is the same as the old `$feed->enable_xml_dump(true)`, but returns + * the data instead of printing it. + * + * @return string|boolean Raw XML data, false if the cache is used + */ + public function get_raw_data() + { + } + /** + * Get the character encoding used for output + * + * @since Preview Release + * @return string + */ + public function get_encoding() + { + } + /** + * Send the content-type header with correct encoding + * + * This method ensures that the SimplePie-enabled page is being served with + * the correct {@link http://www.iana.org/assignments/media-types/ mime-type} + * and character encoding HTTP headers (character encoding determined by the + * {@see set_output_encoding} config option). + * + * This won't work properly if any content or whitespace has already been + * sent to the browser, because it relies on PHP's + * {@link http://php.net/header header()} function, and these are the + * circumstances under which the function works. + * + * Because it's setting these settings for the entire page (as is the nature + * of HTTP headers), this should only be used once per page (again, at the + * top). + * + * @param string $mime MIME type to serve the page as + */ + public function handle_content_type($mime = 'text/html') + { + } + /** + * Get the type of the feed + * + * This returns a SIMPLEPIE_TYPE_* constant, which can be tested against + * using {@link http://php.net/language.operators.bitwise bitwise operators} + * + * @since 0.8 (usage changed to using constants in 1.0) + * @see SIMPLEPIE_TYPE_NONE Unknown. + * @see SIMPLEPIE_TYPE_RSS_090 RSS 0.90. + * @see SIMPLEPIE_TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape). + * @see SIMPLEPIE_TYPE_RSS_091_USERLAND RSS 0.91 (Userland). + * @see SIMPLEPIE_TYPE_RSS_091 RSS 0.91. + * @see SIMPLEPIE_TYPE_RSS_092 RSS 0.92. + * @see SIMPLEPIE_TYPE_RSS_093 RSS 0.93. + * @see SIMPLEPIE_TYPE_RSS_094 RSS 0.94. + * @see SIMPLEPIE_TYPE_RSS_10 RSS 1.0. + * @see SIMPLEPIE_TYPE_RSS_20 RSS 2.0.x. + * @see SIMPLEPIE_TYPE_RSS_RDF RDF-based RSS. + * @see SIMPLEPIE_TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format). + * @see SIMPLEPIE_TYPE_RSS_ALL Any version of RSS. + * @see SIMPLEPIE_TYPE_ATOM_03 Atom 0.3. + * @see SIMPLEPIE_TYPE_ATOM_10 Atom 1.0. + * @see SIMPLEPIE_TYPE_ATOM_ALL Any version of Atom. + * @see SIMPLEPIE_TYPE_ALL Any known/supported feed type. + * @return int SIMPLEPIE_TYPE_* constant + */ + public function get_type() + { + } + /** + * Get the URL for the feed + * + * When the 'permanent' mode is enabled, returns the original feed URL, + * except in the case of an `HTTP 301 Moved Permanently` status response, + * in which case the location of the first redirection is returned. + * + * When the 'permanent' mode is disabled (default), + * may or may not be different from the URL passed to {@see set_feed_url()}, + * depending on whether auto-discovery was used, and whether there were + * any redirects along the way. + * + * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.) + * @todo Support + * @todo Also, |atom:link|@rel=self + * @param bool $permanent Permanent mode to return only the original URL or the first redirection + * iff it is a 301 redirection + * @return string|null + */ + public function subscribe_url($permanent = \false) + { + } + /** + * Get data for an feed-level element + * + * This method allows you to get access to ANY element/attribute that is a + * sub-element of the opening feed tag. + * + * The return value is an indexed array of elements matching the given + * namespace and tag name. Each element has `attribs`, `data` and `child` + * subkeys. For `attribs` and `child`, these contain namespace subkeys. + * `attribs` then has one level of associative name => value data (where + * `value` is a string) after the namespace. `child` has tag-indexed keys + * after the namespace, each member of which is an indexed array matching + * this same format. + * + * For example: + *
    +         * // This is probably a bad example because we already support
    +         * //  natively, but it shows you how to parse through
    +         * // the nodes.
    +         * $group = $item->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group');
    +         * $content = $group[0]['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'];
    +         * $file = $content[0]['attribs']['']['url'];
    +         * echo $file;
    +         * 
    + * + * @since 1.0 + * @see http://simplepie.org/wiki/faq/supported_xml_namespaces + * @param string $namespace The URL of the XML namespace of the elements you're trying to access + * @param string $tag Tag name + * @return array + */ + public function get_feed_tags($namespace, $tag) + { + } + /** + * Get data for an channel-level element + * + * This method allows you to get access to ANY element/attribute in the + * channel/header section of the feed. + * + * See {@see SimplePie::get_feed_tags()} for a description of the return value + * + * @since 1.0 + * @see http://simplepie.org/wiki/faq/supported_xml_namespaces + * @param string $namespace The URL of the XML namespace of the elements you're trying to access + * @param string $tag Tag name + * @return array + */ + public function get_channel_tags($namespace, $tag) + { + } + /** + * Get data for an channel-level element + * + * This method allows you to get access to ANY element/attribute in the + * image/logo section of the feed. + * + * See {@see SimplePie::get_feed_tags()} for a description of the return value + * + * @since 1.0 + * @see http://simplepie.org/wiki/faq/supported_xml_namespaces + * @param string $namespace The URL of the XML namespace of the elements you're trying to access + * @param string $tag Tag name + * @return array + */ + public function get_image_tags($namespace, $tag) + { + } + /** + * Get the base URL value from the feed + * + * Uses `` if available, otherwise uses the first link in the + * feed, or failing that, the URL of the feed itself. + * + * @see get_link + * @see subscribe_url + * + * @param array $element + * @return string + */ + public function get_base($element = array()) + { + } + /** + * Sanitize feed data + * + * @access private + * @see SimplePie_Sanitize::sanitize() + * @param string $data Data to sanitize + * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants + * @param string $base Base URL to resolve URLs against + * @return string Sanitized data + */ + public function sanitize($data, $type, $base = '') + { + } + /** + * Get the title of the feed + * + * Uses ``, `` or `<dc:title>` + * + * @since 1.0 (previously called `get_feed_title` since 0.8) + * @return string|null + */ + public function get_title() + { + } + /** + * Get a category for the feed + * + * @since Unknown + * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Category|null + */ + public function get_category($key = 0) + { + } + /** + * Get all categories for the feed + * + * Uses `<atom:category>`, `<category>` or `<dc:subject>` + * + * @since Unknown + * @return array|null List of {@see SimplePie_Category} objects + */ + public function get_categories() + { + } + /** + * Get an author for the feed + * + * @since 1.1 + * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Author|null + */ + public function get_author($key = 0) + { + } + /** + * Get all authors for the feed + * + * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>` + * + * @since 1.1 + * @return array|null List of {@see SimplePie_Author} objects + */ + public function get_authors() + { + } + /** + * Get a contributor for the feed + * + * @since 1.1 + * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Author|null + */ + public function get_contributor($key = 0) + { + } + /** + * Get all contributors for the feed + * + * Uses `<atom:contributor>` + * + * @since 1.1 + * @return array|null List of {@see SimplePie_Author} objects + */ + public function get_contributors() + { + } + /** + * Get a single link for the feed + * + * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8) + * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1 + * @param string $rel The relationship of the link to return + * @return string|null Link URL + */ + public function get_link($key = 0, $rel = 'alternate') + { + } + /** + * Get the permalink for the item + * + * Returns the first link available with a relationship of "alternate". + * Identical to {@see get_link()} with key 0 + * + * @see get_link + * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8) + * @internal Added for parity between the parent-level and the item/entry-level. + * @return string|null Link URL + */ + public function get_permalink() + { + } + /** + * Get all links for the feed + * + * Uses `<atom:link>` or `<link>` + * + * @since Beta 2 + * @param string $rel The relationship of links to return + * @return array|null Links found for the feed (strings) + */ + public function get_links($rel = 'alternate') + { + } + public function get_all_discovered_feeds() + { + } + /** + * Get the content for the item + * + * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`, + * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>` + * + * @since 1.0 (previously called `get_feed_description()` since 0.8) + * @return string|null + */ + public function get_description() + { + } + /** + * Get the copyright info for the feed + * + * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>` + * + * @since 1.0 (previously called `get_feed_copyright()` since 0.8) + * @return string|null + */ + public function get_copyright() + { + } + /** + * Get the language for the feed + * + * Uses `<language>`, `<dc:language>`, or @xml_lang + * + * @since 1.0 (previously called `get_feed_language()` since 0.8) + * @return string|null + */ + public function get_language() + { + } + /** + * Get the latitude coordinates for the item + * + * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications + * + * Uses `<geo:lat>` or `<georss:point>` + * + * @since 1.0 + * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo + * @link http://www.georss.org/ GeoRSS + * @return string|null + */ + public function get_latitude() + { + } + /** + * Get the longitude coordinates for the feed + * + * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications + * + * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>` + * + * @since 1.0 + * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo + * @link http://www.georss.org/ GeoRSS + * @return string|null + */ + public function get_longitude() + { + } + /** + * Get the feed logo's title + * + * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title. + * + * Uses `<image><title>` or `<image><dc:title>` + * + * @return string|null + */ + public function get_image_title() + { + } + /** + * Get the feed logo's URL + * + * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to + * have a "feed logo" URL. This points directly to the image itself. + * + * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`, + * `<image><title>` or `<image><dc:title>` + * + * @return string|null + */ + public function get_image_url() + { + } + /** + * Get the feed logo's link + * + * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This + * points to a human-readable page that the image should link to. + * + * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`, + * `<image><title>` or `<image><dc:title>` + * + * @return string|null + */ + public function get_image_link() + { + } + /** + * Get the feed logo's link + * + * RSS 2.0 feeds are allowed to have a "feed logo" width. + * + * Uses `<image><width>` or defaults to 88.0 if no width is specified and + * the feed is an RSS 2.0 feed. + * + * @return int|float|null + */ + public function get_image_width() + { + } + /** + * Get the feed logo's height + * + * RSS 2.0 feeds are allowed to have a "feed logo" height. + * + * Uses `<image><height>` or defaults to 31.0 if no height is specified and + * the feed is an RSS 2.0 feed. + * + * @return int|float|null + */ + public function get_image_height() + { + } + /** + * Get the number of items in the feed + * + * This is well-suited for {@link http://php.net/for for()} loops with + * {@see get_item()} + * + * @param int $max Maximum value to return. 0 for no limit + * @return int Number of items in the feed + */ + public function get_item_quantity($max = 0) + { + } + /** + * Get a single item from the feed + * + * This is better suited for {@link http://php.net/for for()} loops, whereas + * {@see get_items()} is better suited for + * {@link http://php.net/foreach foreach()} loops. + * + * @see get_item_quantity() + * @since Beta 2 + * @param int $key The item that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Item|null + */ + public function get_item($key = 0) + { + } + /** + * Get all items from the feed + * + * This is better suited for {@link http://php.net/for for()} loops, whereas + * {@see get_items()} is better suited for + * {@link http://php.net/foreach foreach()} loops. + * + * @see get_item_quantity + * @since Beta 2 + * @param int $start Index to start at + * @param int $end Number of items to return. 0 for all items after `$start` + * @return SimplePie_Item[]|null List of {@see SimplePie_Item} objects + */ + public function get_items($start = 0, $end = 0) + { + } + /** + * Set the favicon handler + * + * @deprecated Use your own favicon handling instead + */ + public function set_favicon_handler($page = \false, $qs = 'i') + { + } + /** + * Get the favicon for the current feed + * + * @deprecated Use your own favicon handling instead + */ + public function get_favicon() + { + } + /** + * Magic method handler + * + * @param string $method Method name + * @param array $args Arguments to the method + * @return mixed + */ + public function __call($method, $args) + { + } + /** + * Sorting callback for items + * + * @access private + * @param SimplePie $a + * @param SimplePie $b + * @return boolean + */ + public static function sort_items($a, $b) + { + } + /** + * Merge items from several feeds into one + * + * If you're merging multiple feeds together, they need to all have dates + * for the items or else SimplePie will refuse to sort them. + * + * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings + * @param array $urls List of SimplePie feed objects to merge + * @param int $start Starting item + * @param int $end Number of items to return + * @param int $limit Maximum number of items per feed + * @return array + */ + public static function merge_items($urls, $start = 0, $end = 0, $limit = 0) + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * SimplePie class. + * + * Class for backward compatibility. + * + * @deprecated Use {@see SimplePie} directly + * @package SimplePie + * @subpackage API + */ + class SimplePie_Core extends \SimplePie + { + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Handles `<media:credit>` as defined in Media RSS + * + * Used by {@see SimplePie_Enclosure::get_credit()} and {@see SimplePie_Enclosure::get_credits()} + * + * This class can be overloaded with {@see SimplePie::set_credit_class()} + * + * @package SimplePie + * @subpackage API + */ + class SimplePie_Credit + { + /** + * Credited role + * + * @var string + * @see get_role() + */ + var $role; + /** + * Organizational scheme + * + * @var string + * @see get_scheme() + */ + var $scheme; + /** + * Credited name + * + * @var string + * @see get_name() + */ + var $name; + /** + * Constructor, used to input the data + * + * For documentation on all the parameters, see the corresponding + * properties and their accessors + */ + public function __construct($role = \null, $scheme = \null, $name = \null) + { + } + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + } + /** + * Get the role of the person receiving credit + * + * @return string|null + */ + public function get_role() + { + } + /** + * Get the organizational scheme + * + * @return string|null + */ + public function get_scheme() + { + } + /** + * Get the credited person/entity's name + * + * @return string|null + */ + public function get_name() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Decode HTML Entities + * + * This implements HTML5 as of revision 967 (2007-06-28) + * + * @deprecated Use DOMDocument instead! + * @package SimplePie + */ + class SimplePie_Decode_HTML_Entities + { + /** + * Data to be parsed + * + * @access private + * @var string + */ + var $data = ''; + /** + * Currently consumed bytes + * + * @access private + * @var string + */ + var $consumed = ''; + /** + * Position of the current byte being parsed + * + * @access private + * @var int + */ + var $position = 0; + /** + * Create an instance of the class with the input data + * + * @access public + * @param string $data Input data + */ + public function __construct($data) + { + } + /** + * Parse the input data + * + * @access public + * @return string Output data + */ + public function parse() + { + } + /** + * Consume the next byte + * + * @access private + * @return mixed The next byte, or false, if there is no more data + */ + public function consume() + { + } + /** + * Consume a range of characters + * + * @access private + * @param string $chars Characters to consume + * @return mixed A series of characters that match the range, or false + */ + public function consume_range($chars) + { + } + /** + * Unconsume one byte + * + * @access private + */ + public function unconsume() + { + } + /** + * Decode an entity + * + * @access private + */ + public function entity() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Handles everything related to enclosures (including Media RSS and iTunes RSS) + * + * Used by {@see SimplePie_Item::get_enclosure()} and {@see SimplePie_Item::get_enclosures()} + * + * This class can be overloaded with {@see SimplePie::set_enclosure_class()} + * + * @package SimplePie + * @subpackage API + */ + class SimplePie_Enclosure + { + /** + * @var string + * @see get_bitrate() + */ + var $bitrate; + /** + * @var array + * @see get_captions() + */ + var $captions; + /** + * @var array + * @see get_categories() + */ + var $categories; + /** + * @var int + * @see get_channels() + */ + var $channels; + /** + * @var SimplePie_Copyright + * @see get_copyright() + */ + var $copyright; + /** + * @var array + * @see get_credits() + */ + var $credits; + /** + * @var string + * @see get_description() + */ + var $description; + /** + * @var int + * @see get_duration() + */ + var $duration; + /** + * @var string + * @see get_expression() + */ + var $expression; + /** + * @var string + * @see get_framerate() + */ + var $framerate; + /** + * @var string + * @see get_handler() + */ + var $handler; + /** + * @var array + * @see get_hashes() + */ + var $hashes; + /** + * @var string + * @see get_height() + */ + var $height; + /** + * @deprecated + * @var null + */ + var $javascript; + /** + * @var array + * @see get_keywords() + */ + var $keywords; + /** + * @var string + * @see get_language() + */ + var $lang; + /** + * @var string + * @see get_length() + */ + var $length; + /** + * @var string + * @see get_link() + */ + var $link; + /** + * @var string + * @see get_medium() + */ + var $medium; + /** + * @var string + * @see get_player() + */ + var $player; + /** + * @var array + * @see get_ratings() + */ + var $ratings; + /** + * @var array + * @see get_restrictions() + */ + var $restrictions; + /** + * @var string + * @see get_sampling_rate() + */ + var $samplingrate; + /** + * @var array + * @see get_thumbnails() + */ + var $thumbnails; + /** + * @var string + * @see get_title() + */ + var $title; + /** + * @var string + * @see get_type() + */ + var $type; + /** + * @var string + * @see get_width() + */ + var $width; + /** + * Constructor, used to input the data + * + * For documentation on all the parameters, see the corresponding + * properties and their accessors + * + * @uses idna_convert If available, this will convert an IDN + */ + public function __construct($link = \null, $type = \null, $length = \null, $javascript = \null, $bitrate = \null, $captions = \null, $categories = \null, $channels = \null, $copyright = \null, $credits = \null, $description = \null, $duration = \null, $expression = \null, $framerate = \null, $hashes = \null, $height = \null, $keywords = \null, $lang = \null, $medium = \null, $player = \null, $ratings = \null, $restrictions = \null, $samplingrate = \null, $thumbnails = \null, $title = \null, $width = \null) + { + } + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + } + /** + * Get the bitrate + * + * @return string|null + */ + public function get_bitrate() + { + } + /** + * Get a single caption + * + * @param int $key + * @return SimplePie_Caption|null + */ + public function get_caption($key = 0) + { + } + /** + * Get all captions + * + * @return array|null Array of {@see SimplePie_Caption} objects + */ + public function get_captions() + { + } + /** + * Get a single category + * + * @param int $key + * @return SimplePie_Category|null + */ + public function get_category($key = 0) + { + } + /** + * Get all categories + * + * @return array|null Array of {@see SimplePie_Category} objects + */ + public function get_categories() + { + } + /** + * Get the number of audio channels + * + * @return int|null + */ + public function get_channels() + { + } + /** + * Get the copyright information + * + * @return SimplePie_Copyright|null + */ + public function get_copyright() + { + } + /** + * Get a single credit + * + * @param int $key + * @return SimplePie_Credit|null + */ + public function get_credit($key = 0) + { + } + /** + * Get all credits + * + * @return array|null Array of {@see SimplePie_Credit} objects + */ + public function get_credits() + { + } + /** + * Get the description of the enclosure + * + * @return string|null + */ + public function get_description() + { + } + /** + * Get the duration of the enclosure + * + * @param bool $convert Convert seconds into hh:mm:ss + * @return string|int|null 'hh:mm:ss' string if `$convert` was specified, otherwise integer (or null if none found) + */ + public function get_duration($convert = \false) + { + } + /** + * Get the expression + * + * @return string Probably one of 'sample', 'full', 'nonstop', 'clip'. Defaults to 'full' + */ + public function get_expression() + { + } + /** + * Get the file extension + * + * @return string|null + */ + public function get_extension() + { + } + /** + * Get the framerate (in frames-per-second) + * + * @return string|null + */ + public function get_framerate() + { + } + /** + * Get the preferred handler + * + * @return string|null One of 'flash', 'fmedia', 'quicktime', 'wmedia', 'mp3' + */ + public function get_handler() + { + } + /** + * Get a single hash + * + * @link http://www.rssboard.org/media-rss#media-hash + * @param int $key + * @return string|null Hash as per `media:hash`, prefixed with "$algo:" + */ + public function get_hash($key = 0) + { + } + /** + * Get all credits + * + * @return array|null Array of strings, see {@see get_hash()} + */ + public function get_hashes() + { + } + /** + * Get the height + * + * @return string|null + */ + public function get_height() + { + } + /** + * Get the language + * + * @link http://tools.ietf.org/html/rfc3066 + * @return string|null Language code as per RFC 3066 + */ + public function get_language() + { + } + /** + * Get a single keyword + * + * @param int $key + * @return string|null + */ + public function get_keyword($key = 0) + { + } + /** + * Get all keywords + * + * @return array|null Array of strings + */ + public function get_keywords() + { + } + /** + * Get length + * + * @return float Length in bytes + */ + public function get_length() + { + } + /** + * Get the URL + * + * @return string|null + */ + public function get_link() + { + } + /** + * Get the medium + * + * @link http://www.rssboard.org/media-rss#media-content + * @return string|null Should be one of 'image', 'audio', 'video', 'document', 'executable' + */ + public function get_medium() + { + } + /** + * Get the player URL + * + * Typically the same as {@see get_permalink()} + * @return string|null Player URL + */ + public function get_player() + { + } + /** + * Get a single rating + * + * @param int $key + * @return SimplePie_Rating|null + */ + public function get_rating($key = 0) + { + } + /** + * Get all ratings + * + * @return array|null Array of {@see SimplePie_Rating} objects + */ + public function get_ratings() + { + } + /** + * Get a single restriction + * + * @param int $key + * @return SimplePie_Restriction|null + */ + public function get_restriction($key = 0) + { + } + /** + * Get all restrictions + * + * @return array|null Array of {@see SimplePie_Restriction} objects + */ + public function get_restrictions() + { + } + /** + * Get the sampling rate (in kHz) + * + * @return string|null + */ + public function get_sampling_rate() + { + } + /** + * Get the file size (in MiB) + * + * @return float|null File size in mebibytes (1048 bytes) + */ + public function get_size() + { + } + /** + * Get a single thumbnail + * + * @param int $key + * @return string|null Thumbnail URL + */ + public function get_thumbnail($key = 0) + { + } + /** + * Get all thumbnails + * + * @return array|null Array of thumbnail URLs + */ + public function get_thumbnails() + { + } + /** + * Get the title + * + * @return string|null + */ + public function get_title() + { + } + /** + * Get mimetype of the enclosure + * + * @see get_real_type() + * @return string|null MIME type + */ + public function get_type() + { + } + /** + * Get the width + * + * @return string|null + */ + public function get_width() + { + } + /** + * Embed the enclosure using `<embed>` + * + * @deprecated Use the second parameter to {@see embed} instead + * + * @param array|string $options See first paramter to {@see embed} + * @return string HTML string to output + */ + public function native_embed($options = '') + { + } + /** + * Embed the enclosure using Javascript + * + * `$options` is an array or comma-separated key:value string, with the + * following properties: + * + * - `alt` (string): Alternate content for when an end-user does not have + * the appropriate handler installed or when a file type is + * unsupported. Can be any text or HTML. Defaults to blank. + * - `altclass` (string): If a file type is unsupported, the end-user will + * see the alt text (above) linked directly to the content. That link + * will have this value as its class name. Defaults to blank. + * - `audio` (string): This is an image that should be used as a + * placeholder for audio files before they're loaded (QuickTime-only). + * Can be any relative or absolute URL. Defaults to blank. + * - `bgcolor` (string): The background color for the media, if not + * already transparent. Defaults to `#ffffff`. + * - `height` (integer): The height of the embedded media. Accepts any + * numeric pixel value (such as `360`) or `auto`. Defaults to `auto`, + * and it is recommended that you use this default. + * - `loop` (boolean): Do you want the media to loop when it's done? + * Defaults to `false`. + * - `mediaplayer` (string): The location of the included + * `mediaplayer.swf` file. This allows for the playback of Flash Video + * (`.flv`) files, and is the default handler for non-Odeo MP3's. + * Defaults to blank. + * - `video` (string): This is an image that should be used as a + * placeholder for video files before they're loaded (QuickTime-only). + * Can be any relative or absolute URL. Defaults to blank. + * - `width` (integer): The width of the embedded media. Accepts any + * numeric pixel value (such as `480`) or `auto`. Defaults to `auto`, + * and it is recommended that you use this default. + * - `widescreen` (boolean): Is the enclosure widescreen or standard? + * This applies only to video enclosures, and will automatically resize + * the content appropriately. Defaults to `false`, implying 4:3 mode. + * + * Note: Non-widescreen (4:3) mode with `width` and `height` set to `auto` + * will default to 480x360 video resolution. Widescreen (16:9) mode with + * `width` and `height` set to `auto` will default to 480x270 video resolution. + * + * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'. + * @param array|string $options Comma-separated key:value list, or array + * @param bool $native Use `<embed>` + * @return string HTML string to output + */ + public function embed($options = '', $native = \false) + { + } + /** + * Get the real media type + * + * Often, feeds lie to us, necessitating a bit of deeper inspection. This + * converts types to their canonical representations based on the file + * extension + * + * @see get_type() + * @param bool $find_handler Internal use only, use {@see get_handler()} instead + * @return string MIME type + */ + public function get_real_type($find_handler = \false) + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * General SimplePie exception class + * + * @package SimplePie + */ + class SimplePie_Exception extends \Exception + { + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Used for fetching remote files and reading local files + * + * Supports HTTP 1.0 via cURL or fsockopen, with spotty HTTP 1.1 support + * + * This class can be overloaded with {@see SimplePie::set_file_class()} + * + * @package SimplePie + * @subpackage HTTP + * @todo Move to properly supporting RFC2616 (HTTP/1.1) + */ + class SimplePie_File + { + var $url; + var $useragent; + var $success = \true; + var $headers = array(); + var $body; + var $status_code; + var $redirects = 0; + var $error; + var $method = \SIMPLEPIE_FILE_SOURCE_NONE; + var $permanent_url; + public function __construct($url, $timeout = 10, $redirects = 5, $headers = \null, $useragent = \null, $force_fsockopen = \false, $curl_options = array()) + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * HTTP Response Parser + * + * @package SimplePie + * @subpackage HTTP + */ + class SimplePie_HTTP_Parser + { + /** + * HTTP Version + * + * @var float + */ + public $http_version = 0.0; + /** + * Status code + * + * @var int + */ + public $status_code = 0; + /** + * Reason phrase + * + * @var string + */ + public $reason = ''; + /** + * Key/value pairs of the headers + * + * @var array + */ + public $headers = array(); + /** + * Body of the response + * + * @var string + */ + public $body = ''; + /** + * Current state of the state machine + * + * @var string + */ + protected $state = 'http_version'; + /** + * Input data + * + * @var string + */ + protected $data = ''; + /** + * Input data length (to avoid calling strlen() everytime this is needed) + * + * @var int + */ + protected $data_length = 0; + /** + * Current position of the pointer + * + * @var int + */ + protected $position = 0; + /** + * Name of the hedaer currently being parsed + * + * @var string + */ + protected $name = ''; + /** + * Value of the hedaer currently being parsed + * + * @var string + */ + protected $value = ''; + /** + * Create an instance of the class with the input data + * + * @param string $data Input data + */ + public function __construct($data) + { + } + /** + * Parse the input data + * + * @return bool true on success, false on failure + */ + public function parse() + { + } + /** + * Check whether there is data beyond the pointer + * + * @return bool true if there is further data, false if not + */ + protected function has_data() + { + } + /** + * See if the next character is LWS + * + * @return bool true if the next character is LWS, false if not + */ + protected function is_linear_whitespace() + { + } + /** + * Parse the HTTP version + */ + protected function http_version() + { + } + /** + * Parse the status code + */ + protected function status() + { + } + /** + * Parse the reason phrase + */ + protected function reason() + { + } + /** + * Deal with a new line, shifting data around as needed + */ + protected function new_line() + { + } + /** + * Parse a header name + */ + protected function name() + { + } + /** + * Parse LWS, replacing consecutive LWS characters with a single space + */ + protected function linear_whitespace() + { + } + /** + * See what state to move to while within non-quoted header values + */ + protected function value() + { + } + /** + * Parse a header value while outside quotes + */ + protected function value_char() + { + } + /** + * See what state to move to while within quoted header values + */ + protected function quote() + { + } + /** + * Parse a header value while within quotes + */ + protected function quote_char() + { + } + /** + * Parse an escaped character within quotes + */ + protected function quote_escaped() + { + } + /** + * Parse the body + */ + protected function body() + { + } + /** + * Parsed a "Transfer-Encoding: chunked" body + */ + protected function chunked() + { + } + /** + * Prepare headers (take care of proxies headers) + * + * @param string $headers Raw headers + * @param integer $count Redirection count. Default to 1. + * + * @return string + */ + public static function prepareHeaders($headers, $count = 1) + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * IRI parser/serialiser/normaliser + * + * @package SimplePie + * @subpackage HTTP + * @author Sam Sneddon + * @author Steve Minutillo + * @author Ryan McCue + * @copyright 2007-2012 Sam Sneddon, Steve Minutillo, Ryan McCue + * @license http://www.opensource.org/licenses/bsd-license.php + */ + class SimplePie_IRI + { + /** + * Scheme + * + * @var string + */ + protected $scheme = \null; + /** + * User Information + * + * @var string + */ + protected $iuserinfo = \null; + /** + * ihost + * + * @var string + */ + protected $ihost = \null; + /** + * Port + * + * @var string + */ + protected $port = \null; + /** + * ipath + * + * @var string + */ + protected $ipath = ''; + /** + * iquery + * + * @var string + */ + protected $iquery = \null; + /** + * ifragment + * + * @var string + */ + protected $ifragment = \null; + /** + * Normalization database + * + * Each key is the scheme, each value is an array with each key as the IRI + * part and value as the default value for that part. + */ + protected $normalization = array('acap' => array('port' => 674), 'dict' => array('port' => 2628), 'file' => array('ihost' => 'localhost'), 'http' => array('port' => 80, 'ipath' => '/'), 'https' => array('port' => 443, 'ipath' => '/')); + /** + * Return the entire IRI when you try and read the object as a string + * + * @return string + */ + public function __toString() + { + } + /** + * Overload __set() to provide access via properties + * + * @param string $name Property name + * @param mixed $value Property value + */ + public function __set($name, $value) + { + } + /** + * Overload __get() to provide access via properties + * + * @param string $name Property name + * @return mixed + */ + public function __get($name) + { + } + /** + * Overload __isset() to provide access via properties + * + * @param string $name Property name + * @return bool + */ + public function __isset($name) + { + } + /** + * Overload __unset() to provide access via properties + * + * @param string $name Property name + */ + public function __unset($name) + { + } + /** + * Create a new IRI object, from a specified string + * + * @param string $iri + */ + public function __construct($iri = \null) + { + } + /** + * Clean up + */ + public function __destruct() + { + } + /** + * Create a new IRI object by resolving a relative IRI + * + * Returns false if $base is not absolute, otherwise an IRI. + * + * @param IRI|string $base (Absolute) Base IRI + * @param IRI|string $relative Relative IRI + * @return IRI|false + */ + public static function absolutize($base, $relative) + { + } + /** + * Parse an IRI into scheme/authority/path/query/fragment segments + * + * @param string $iri + * @return array + */ + protected function parse_iri($iri) + { + } + /** + * Remove dot segments from a path + * + * @param string $input + * @return string + */ + protected function remove_dot_segments($input) + { + } + /** + * Replace invalid character with percent encoding + * + * @param string $string Input string + * @param string $extra_chars Valid characters not in iunreserved or + * iprivate (this is ASCII-only) + * @param bool $iprivate Allow iprivate + * @return string + */ + protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = \false) + { + } + /** + * Callback function for preg_replace_callback. + * + * Removes sequences of percent encoded bytes that represent UTF-8 + * encoded characters in iunreserved + * + * @param array $match PCRE match + * @return string Replacement + */ + protected function remove_iunreserved_percent_encoded($match) + { + } + protected function scheme_normalization() + { + } + /** + * Check if the object represents a valid IRI. This needs to be done on each + * call as some things change depending on another part of the IRI. + * + * @return bool + */ + public function is_valid() + { + } + /** + * Set the entire IRI. Returns true on success, false on failure (if there + * are any invalid characters). + * + * @param string $iri + * @return bool + */ + public function set_iri($iri, $clear_cache = \false) + { + } + /** + * Set the scheme. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $scheme + * @return bool + */ + public function set_scheme($scheme) + { + } + /** + * Set the authority. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $authority + * @return bool + */ + public function set_authority($authority, $clear_cache = \false) + { + } + /** + * Set the iuserinfo. + * + * @param string $iuserinfo + * @return bool + */ + public function set_userinfo($iuserinfo) + { + } + /** + * Set the ihost. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $ihost + * @return bool + */ + public function set_host($ihost) + { + } + /** + * Set the port. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $port + * @return bool + */ + public function set_port($port) + { + } + /** + * Set the ipath. + * + * @param string $ipath + * @return bool + */ + public function set_path($ipath, $clear_cache = \false) + { + } + /** + * Set the iquery. + * + * @param string $iquery + * @return bool + */ + public function set_query($iquery) + { + } + /** + * Set the ifragment. + * + * @param string $ifragment + * @return bool + */ + public function set_fragment($ifragment) + { + } + /** + * Convert an IRI to a URI (or parts thereof) + * + * @return string + */ + public function to_uri($string) + { + } + /** + * Get the complete IRI + * + * @return string + */ + public function get_iri() + { + } + /** + * Get the complete URI + * + * @return string + */ + public function get_uri() + { + } + /** + * Get the complete iauthority + * + * @return string + */ + protected function get_iauthority() + { + } + /** + * Get the complete authority + * + * @return string + */ + protected function get_authority() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Manages all item-related data + * + * Used by {@see SimplePie::get_item()} and {@see SimplePie::get_items()} + * + * This class can be overloaded with {@see SimplePie::set_item_class()} + * + * @package SimplePie + * @subpackage API + */ + class SimplePie_Item + { + /** + * Parent feed + * + * @access private + * @var SimplePie + */ + var $feed; + /** + * Raw data + * + * @access private + * @var array + */ + var $data = array(); + /** + * Registry object + * + * @see set_registry + * @var SimplePie_Registry + */ + protected $registry; + /** + * Create a new item object + * + * This is usually used by {@see SimplePie::get_items} and + * {@see SimplePie::get_item}. Avoid creating this manually. + * + * @param SimplePie $feed Parent feed + * @param array $data Raw data + */ + public function __construct($feed, $data) + { + } + /** + * Set the registry handler + * + * This is usually used by {@see SimplePie_Registry::create} + * + * @since 1.3 + * @param SimplePie_Registry $registry + */ + public function set_registry(\SimplePie_Registry $registry) + { + } + /** + * Get a string representation of the item + * + * @return string + */ + public function __toString() + { + } + /** + * Remove items that link back to this before destroying this object + */ + public function __destruct() + { + } + /** + * Get data for an item-level element + * + * This method allows you to get access to ANY element/attribute that is a + * sub-element of the item/entry tag. + * + * See {@see SimplePie::get_feed_tags()} for a description of the return value + * + * @since 1.0 + * @see http://simplepie.org/wiki/faq/supported_xml_namespaces + * @param string $namespace The URL of the XML namespace of the elements you're trying to access + * @param string $tag Tag name + * @return array + */ + public function get_item_tags($namespace, $tag) + { + } + /** + * Get the base URL value from the parent feed + * + * Uses `<xml:base>` + * + * @param array $element + * @return string + */ + public function get_base($element = array()) + { + } + /** + * Sanitize feed data + * + * @access private + * @see SimplePie::sanitize() + * @param string $data Data to sanitize + * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants + * @param string $base Base URL to resolve URLs against + * @return string Sanitized data + */ + public function sanitize($data, $type, $base = '') + { + } + /** + * Get the parent feed + * + * Note: this may not work as you think for multifeeds! + * + * @link http://simplepie.org/faq/typical_multifeed_gotchas#missing_data_from_feed + * @since 1.0 + * @return SimplePie + */ + public function get_feed() + { + } + /** + * Get the unique identifier for the item + * + * This is usually used when writing code to check for new items in a feed. + * + * Uses `<atom:id>`, `<guid>`, `<dc:identifier>` or the `about` attribute + * for RDF. If none of these are supplied (or `$hash` is true), creates an + * MD5 hash based on the permalink, title and content. + * + * @since Beta 2 + * @param boolean $hash Should we force using a hash instead of the supplied ID? + * @param string|false $fn User-supplied function to generate an hash + * @return string|null + */ + public function get_id($hash = \false, $fn = 'md5') + { + } + /** + * Get the title of the item + * + * Uses `<atom:title>`, `<title>` or `<dc:title>` + * + * @since Beta 2 (previously called `get_item_title` since 0.8) + * @return string|null + */ + public function get_title() + { + } + /** + * Get the content for the item + * + * Prefers summaries over full content , but will return full content if a + * summary does not exist. + * + * To prefer full content instead, use {@see get_content} + * + * Uses `<atom:summary>`, `<description>`, `<dc:description>` or + * `<itunes:subtitle>` + * + * @since 0.8 + * @param boolean $description_only Should we avoid falling back to the content? + * @return string|null + */ + public function get_description($description_only = \false) + { + } + /** + * Get the content for the item + * + * Prefers full content over summaries, but will return a summary if full + * content does not exist. + * + * To prefer summaries instead, use {@see get_description} + * + * Uses `<atom:content>` or `<content:encoded>` (RSS 1.0 Content Module) + * + * @since 1.0 + * @param boolean $content_only Should we avoid falling back to the description? + * @return string|null + */ + public function get_content($content_only = \false) + { + } + /** + * Get the media:thumbnail of the item + * + * Uses `<media:thumbnail>` + * + * + * @return array|null + */ + public function get_thumbnail() + { + } + /** + * Get a category for the item + * + * @since Beta 3 (previously called `get_categories()` since Beta 2) + * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Category|null + */ + public function get_category($key = 0) + { + } + /** + * Get all categories for the item + * + * Uses `<atom:category>`, `<category>` or `<dc:subject>` + * + * @since Beta 3 + * @return SimplePie_Category[]|null List of {@see SimplePie_Category} objects + */ + public function get_categories() + { + } + /** + * Get an author for the item + * + * @since Beta 2 + * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Author|null + */ + public function get_author($key = 0) + { + } + /** + * Get a contributor for the item + * + * @since 1.1 + * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Author|null + */ + public function get_contributor($key = 0) + { + } + /** + * Get all contributors for the item + * + * Uses `<atom:contributor>` + * + * @since 1.1 + * @return SimplePie_Author[]|null List of {@see SimplePie_Author} objects + */ + public function get_contributors() + { + } + /** + * Get all authors for the item + * + * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>` + * + * @since Beta 2 + * @return SimplePie_Author[]|null List of {@see SimplePie_Author} objects + */ + public function get_authors() + { + } + /** + * Get the copyright info for the item + * + * Uses `<atom:rights>` or `<dc:rights>` + * + * @since 1.1 + * @return string + */ + public function get_copyright() + { + } + /** + * Get the posting date/time for the item + * + * Uses `<atom:published>`, `<atom:updated>`, `<atom:issued>`, + * `<atom:modified>`, `<pubDate>` or `<dc:date>` + * + * Note: obeys PHP's timezone setting. To get a UTC date/time, use + * {@see get_gmdate} + * + * @since Beta 2 (previously called `get_item_date` since 0.8) + * + * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data) + * @return int|string|null + */ + public function get_date($date_format = 'j F Y, g:i a') + { + } + /** + * Get the update date/time for the item + * + * Uses `<atom:updated>` + * + * Note: obeys PHP's timezone setting. To get a UTC date/time, use + * {@see get_gmdate} + * + * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data) + * @return int|string|null + */ + public function get_updated_date($date_format = 'j F Y, g:i a') + { + } + /** + * Get the localized posting date/time for the item + * + * Returns the date formatted in the localized language. To display in + * languages other than the server's default, you need to change the locale + * with {@link http://php.net/setlocale setlocale()}. The available + * localizations depend on which ones are installed on your web server. + * + * @since 1.0 + * + * @param string $date_format Supports any PHP date format from {@see http://php.net/strftime} (empty for the raw data) + * @return int|string|null + */ + public function get_local_date($date_format = '%c') + { + } + /** + * Get the posting date/time for the item (UTC time) + * + * @see get_date + * @param string $date_format Supports any PHP date format from {@see http://php.net/date} + * @return int|string|null + */ + public function get_gmdate($date_format = 'j F Y, g:i a') + { + } + /** + * Get the update date/time for the item (UTC time) + * + * @see get_updated_date + * @param string $date_format Supports any PHP date format from {@see http://php.net/date} + * @return int|string|null + */ + public function get_updated_gmdate($date_format = 'j F Y, g:i a') + { + } + /** + * Get the permalink for the item + * + * Returns the first link available with a relationship of "alternate". + * Identical to {@see get_link()} with key 0 + * + * @see get_link + * @since 0.8 + * @return string|null Permalink URL + */ + public function get_permalink() + { + } + /** + * Get a single link for the item + * + * @since Beta 3 + * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1 + * @param string $rel The relationship of the link to return + * @return string|null Link URL + */ + public function get_link($key = 0, $rel = 'alternate') + { + } + /** + * Get all links for the item + * + * Uses `<atom:link>`, `<link>` or `<guid>` + * + * @since Beta 2 + * @param string $rel The relationship of links to return + * @return array|null Links found for the item (strings) + */ + public function get_links($rel = 'alternate') + { + } + /** + * Get an enclosure from the item + * + * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS. + * + * @since Beta 2 + * @todo Add ability to prefer one type of content over another (in a media group). + * @param int $key The enclosure that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Enclosure|null + */ + public function get_enclosure($key = 0, $prefer = \null) + { + } + /** + * Get all available enclosures (podcasts, etc.) + * + * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS. + * + * At this point, we're pretty much assuming that all enclosures for an item + * are the same content. Anything else is too complicated to + * properly support. + * + * @since Beta 2 + * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4). + * @todo If an element exists at a level, but its value is empty, we should fall back to the value from the parent (if it exists). + * @return SimplePie_Enclosure[]|null List of SimplePie_Enclosure items + */ + public function get_enclosures() + { + } + /** + * Get the latitude coordinates for the item + * + * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications + * + * Uses `<geo:lat>` or `<georss:point>` + * + * @since 1.0 + * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo + * @link http://www.georss.org/ GeoRSS + * @return string|null + */ + public function get_latitude() + { + } + /** + * Get the longitude coordinates for the item + * + * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications + * + * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>` + * + * @since 1.0 + * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo + * @link http://www.georss.org/ GeoRSS + * @return string|null + */ + public function get_longitude() + { + } + /** + * Get the `<atom:source>` for the item + * + * @since 1.1 + * @return SimplePie_Source|null + */ + public function get_source() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Used for feed auto-discovery + * + * + * This class can be overloaded with {@see SimplePie::set_locator_class()} + * + * @package SimplePie + */ + class SimplePie_Locator + { + var $useragent; + var $timeout; + var $file; + var $local = array(); + var $elsewhere = array(); + var $cached_entities = array(); + var $http_base; + var $base; + var $base_location = 0; + var $checked_feeds = 0; + var $max_checked_feeds = 10; + var $force_fsockopen = \false; + var $curl_options = array(); + var $dom; + protected $registry; + public function __construct(\SimplePie_File $file, $timeout = 10, $useragent = \null, $max_checked_feeds = 10, $force_fsockopen = \false, $curl_options = array()) + { + } + public function set_registry(\SimplePie_Registry $registry) + { + } + public function find($type = \SIMPLEPIE_LOCATOR_ALL, &$working = \null) + { + } + public function is_feed($file, $check_html = \false) + { + } + public function get_base() + { + } + public function autodiscovery() + { + } + protected function search_elements_by_tag($name, &$done, $feeds) + { + } + public function get_links() + { + } + public function get_rel_link($rel) + { + } + public function extension(&$array) + { + } + public function body(&$array) + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Miscellanous utilities + * + * @package SimplePie + */ + class SimplePie_Misc + { + public static function time_hms($seconds) + { + } + public static function absolutize_url($relative, $base) + { + } + /** + * Get a HTML/XML element from a HTML string + * + * @deprecated Use DOMDocument instead (parsing HTML with regex is bad!) + * @param string $realname Element name (including namespace prefix if applicable) + * @param string $string HTML document + * @return array + */ + public static function get_element($realname, $string) + { + } + public static function element_implode($element) + { + } + public static function error($message, $level, $file, $line) + { + } + public static function fix_protocol($url, $http = 1) + { + } + public static function array_merge_recursive($array1, $array2) + { + } + public static function parse_url($url) + { + } + public static function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '') + { + } + public static function normalize_url($url) + { + } + public static function percent_encoding_normalization($match) + { + } + /** + * Converts a Windows-1252 encoded string to a UTF-8 encoded string + * + * @static + * @param string $string Windows-1252 encoded string + * @return string UTF-8 encoded string + */ + public static function windows_1252_to_utf8($string) + { + } + /** + * Change a string from one encoding to another + * + * @param string $data Raw data in $input encoding + * @param string $input Encoding of $data + * @param string $output Encoding you want + * @return string|boolean False if we can't convert it + */ + public static function change_encoding($data, $input, $output) + { + } + protected static function change_encoding_mbstring($data, $input, $output) + { + } + protected static function change_encoding_iconv($data, $input, $output) + { + } + /** + * @param string $data + * @param string $input + * @param string $output + * @return string|false + */ + protected static function change_encoding_uconverter($data, $input, $output) + { + } + /** + * Normalize an encoding name + * + * This is automatically generated by create.php + * + * To generate it, run `php create.php` on the command line, and copy the + * output to replace this function. + * + * @param string $charset Character set to standardise + * @return string Standardised name + */ + public static function encoding($charset) + { + } + public static function get_curl_version() + { + } + /** + * Strip HTML comments + * + * @param string $data Data to strip comments from + * @return string Comment stripped string + */ + public static function strip_comments($data) + { + } + public static function parse_date($dt) + { + } + /** + * Decode HTML entities + * + * @deprecated Use DOMDocument instead + * @param string $data Input data + * @return string Output data + */ + public static function entities_decode($data) + { + } + /** + * Remove RFC822 comments + * + * @param string $data Data to strip comments from + * @return string Comment stripped string + */ + public static function uncomment_rfc822($string) + { + } + public static function parse_mime($mime) + { + } + public static function atom_03_construct_type($attribs) + { + } + public static function atom_10_construct_type($attribs) + { + } + public static function atom_10_content_construct_type($attribs) + { + } + public static function is_isegment_nz_nc($string) + { + } + public static function space_separated_tokens($string) + { + } + /** + * Converts a unicode codepoint to a UTF-8 character + * + * @static + * @param int $codepoint Unicode codepoint + * @return string UTF-8 character + */ + public static function codepoint_to_utf8($codepoint) + { + } + /** + * Similar to parse_str() + * + * Returns an associative array of name/value pairs, where the value is an + * array of values that have used the same name + * + * @static + * @param string $str The input string. + * @return array + */ + public static function parse_str($str) + { + } + /** + * Detect XML encoding, as per XML 1.0 Appendix F.1 + * + * @todo Add support for EBCDIC + * @param string $data XML data + * @param SimplePie_Registry $registry Class registry + * @return array Possible encodings + */ + public static function xml_encoding($data, $registry) + { + } + public static function output_javascript() + { + } + /** + * Get the SimplePie build timestamp + * + * Uses the git index if it exists, otherwise uses the modification time + * of the newest file. + */ + public static function get_build() + { + } + /** + * Format debugging information + */ + public static function debug(&$sp) + { + } + public static function silence_errors($num, $str) + { + } + /** + * Sanitize a URL by removing HTTP credentials. + * @param string $url the URL to sanitize. + * @return string the same URL without HTTP credentials. + */ + public static function url_remove_credentials($url) + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Class to validate and to work with IPv6 addresses. + * + * @package SimplePie + * @subpackage HTTP + * @copyright 2003-2005 The PHP Group + * @license http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/package/Net_IPv6 + * @author Alexander Merz <alexander.merz@web.de> + * @author elfrink at introweb dot nl + * @author Josh Peck <jmp at joshpeck dot org> + * @author Sam Sneddon <geoffers@gmail.com> + */ + class SimplePie_Net_IPv6 + { + /** + * Uncompresses an IPv6 address + * + * RFC 4291 allows you to compress concecutive zero pieces in an address to + * '::'. This method expects a valid IPv6 address and expands the '::' to + * the required number of zero pieces. + * + * Example: FF01::101 -> FF01:0:0:0:0:0:0:101 + * ::1 -> 0:0:0:0:0:0:0:1 + * + * @author Alexander Merz <alexander.merz@web.de> + * @author elfrink at introweb dot nl + * @author Josh Peck <jmp at joshpeck dot org> + * @copyright 2003-2005 The PHP Group + * @license http://www.opensource.org/licenses/bsd-license.php + * @param string $ip An IPv6 address + * @return string The uncompressed IPv6 address + */ + public static function uncompress($ip) + { + } + /** + * Compresses an IPv6 address + * + * RFC 4291 allows you to compress concecutive zero pieces in an address to + * '::'. This method expects a valid IPv6 address and compresses consecutive + * zero pieces to '::'. + * + * Example: FF01:0:0:0:0:0:0:101 -> FF01::101 + * 0:0:0:0:0:0:0:1 -> ::1 + * + * @see uncompress() + * @param string $ip An IPv6 address + * @return string The compressed IPv6 address + */ + public static function compress($ip) + { + } + /** + * Checks an IPv6 address + * + * Checks if the given IP is a valid IPv6 address + * + * @param string $ip An IPv6 address + * @return bool true if $ip is a valid IPv6 address + */ + public static function check_ipv6($ip) + { + } + /** + * Checks if the given IP is a valid IPv6 address + * + * @codeCoverageIgnore + * @deprecated Use {@see SimplePie_Net_IPv6::check_ipv6()} instead + * @see check_ipv6 + * @param string $ip An IPv6 address + * @return bool true if $ip is a valid IPv6 address + */ + public static function checkIPv6($ip) + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Date Parser + * + * @package SimplePie + * @subpackage Parsing + */ + class SimplePie_Parse_Date + { + /** + * Input data + * + * @access protected + * @var string + */ + var $date; + /** + * List of days, calendar day name => ordinal day number in the week + * + * @access protected + * @var array + */ + var $day = array( + // English + 'mon' => 1, + 'monday' => 1, + 'tue' => 2, + 'tuesday' => 2, + 'wed' => 3, + 'wednesday' => 3, + 'thu' => 4, + 'thursday' => 4, + 'fri' => 5, + 'friday' => 5, + 'sat' => 6, + 'saturday' => 6, + 'sun' => 7, + 'sunday' => 7, + // Dutch + 'maandag' => 1, + 'dinsdag' => 2, + 'woensdag' => 3, + 'donderdag' => 4, + 'vrijdag' => 5, + 'zaterdag' => 6, + 'zondag' => 7, + // French + 'lundi' => 1, + 'mardi' => 2, + 'mercredi' => 3, + 'jeudi' => 4, + 'vendredi' => 5, + 'samedi' => 6, + 'dimanche' => 7, + // German + 'montag' => 1, + 'mo' => 1, + 'dienstag' => 2, + 'di' => 2, + 'mittwoch' => 3, + 'mi' => 3, + 'donnerstag' => 4, + 'do' => 4, + 'freitag' => 5, + 'fr' => 5, + 'samstag' => 6, + 'sa' => 6, + 'sonnabend' => 6, + // AFAIK no short form for sonnabend + 'so' => 7, + 'sonntag' => 7, + // Italian + 'lunedì' => 1, + 'martedì' => 2, + 'mercoledì' => 3, + 'giovedì' => 4, + 'venerdì' => 5, + 'sabato' => 6, + 'domenica' => 7, + // Spanish + 'lunes' => 1, + 'martes' => 2, + 'miércoles' => 3, + 'jueves' => 4, + 'viernes' => 5, + 'sábado' => 6, + 'domingo' => 7, + // Finnish + 'maanantai' => 1, + 'tiistai' => 2, + 'keskiviikko' => 3, + 'torstai' => 4, + 'perjantai' => 5, + 'lauantai' => 6, + 'sunnuntai' => 7, + // Hungarian + 'hétfő' => 1, + 'kedd' => 2, + 'szerda' => 3, + 'csütörtok' => 4, + 'péntek' => 5, + 'szombat' => 6, + 'vasárnap' => 7, + // Greek + 'Δευ' => 1, + 'Τρι' => 2, + 'Τετ' => 3, + 'Πεμ' => 4, + 'Παρ' => 5, + 'Σαβ' => 6, + 'Κυρ' => 7, + // Russian + 'Пн.' => 1, + 'Вт.' => 2, + 'Ср.' => 3, + 'Чт.' => 4, + 'Пт.' => 5, + 'Сб.' => 6, + 'Вс.' => 7, + ); + /** + * List of months, calendar month name => calendar month number + * + * @access protected + * @var array + */ + var $month = array( + // English + 'jan' => 1, + 'january' => 1, + 'feb' => 2, + 'february' => 2, + 'mar' => 3, + 'march' => 3, + 'apr' => 4, + 'april' => 4, + 'may' => 5, + // No long form of May + 'jun' => 6, + 'june' => 6, + 'jul' => 7, + 'july' => 7, + 'aug' => 8, + 'august' => 8, + 'sep' => 9, + 'september' => 9, + 'oct' => 10, + 'october' => 10, + 'nov' => 11, + 'november' => 11, + 'dec' => 12, + 'december' => 12, + // Dutch + 'januari' => 1, + 'februari' => 2, + 'maart' => 3, + 'april' => 4, + 'mei' => 5, + 'juni' => 6, + 'juli' => 7, + 'augustus' => 8, + 'september' => 9, + 'oktober' => 10, + 'november' => 11, + 'december' => 12, + // French + 'janvier' => 1, + 'février' => 2, + 'mars' => 3, + 'avril' => 4, + 'mai' => 5, + 'juin' => 6, + 'juillet' => 7, + 'août' => 8, + 'septembre' => 9, + 'octobre' => 10, + 'novembre' => 11, + 'décembre' => 12, + // German + 'januar' => 1, + 'jan' => 1, + 'februar' => 2, + 'feb' => 2, + 'märz' => 3, + 'mär' => 3, + 'april' => 4, + 'apr' => 4, + 'mai' => 5, + // no short form for may + 'juni' => 6, + 'jun' => 6, + 'juli' => 7, + 'jul' => 7, + 'august' => 8, + 'aug' => 8, + 'september' => 9, + 'sep' => 9, + 'oktober' => 10, + 'okt' => 10, + 'november' => 11, + 'nov' => 11, + 'dezember' => 12, + 'dez' => 12, + // Italian + 'gennaio' => 1, + 'febbraio' => 2, + 'marzo' => 3, + 'aprile' => 4, + 'maggio' => 5, + 'giugno' => 6, + 'luglio' => 7, + 'agosto' => 8, + 'settembre' => 9, + 'ottobre' => 10, + 'novembre' => 11, + 'dicembre' => 12, + // Spanish + 'enero' => 1, + 'febrero' => 2, + 'marzo' => 3, + 'abril' => 4, + 'mayo' => 5, + 'junio' => 6, + 'julio' => 7, + 'agosto' => 8, + 'septiembre' => 9, + 'setiembre' => 9, + 'octubre' => 10, + 'noviembre' => 11, + 'diciembre' => 12, + // Finnish + 'tammikuu' => 1, + 'helmikuu' => 2, + 'maaliskuu' => 3, + 'huhtikuu' => 4, + 'toukokuu' => 5, + 'kesäkuu' => 6, + 'heinäkuu' => 7, + 'elokuu' => 8, + 'suuskuu' => 9, + 'lokakuu' => 10, + 'marras' => 11, + 'joulukuu' => 12, + // Hungarian + 'január' => 1, + 'február' => 2, + 'március' => 3, + 'április' => 4, + 'május' => 5, + 'június' => 6, + 'július' => 7, + 'augusztus' => 8, + 'szeptember' => 9, + 'október' => 10, + 'november' => 11, + 'december' => 12, + // Greek + 'Ιαν' => 1, + 'Φεβ' => 2, + 'Μάώ' => 3, + 'Μαώ' => 3, + 'Απρ' => 4, + 'Μάι' => 5, + 'Μαϊ' => 5, + 'Μαι' => 5, + 'Ιούν' => 6, + 'Ιον' => 6, + 'Ιούλ' => 7, + 'Ιολ' => 7, + 'Αύγ' => 8, + 'Αυγ' => 8, + 'Σεπ' => 9, + 'Οκτ' => 10, + 'Νοέ' => 11, + 'Δεκ' => 12, + // Russian + 'Янв' => 1, + 'января' => 1, + 'Фев' => 2, + 'февраля' => 2, + 'Мар' => 3, + 'марта' => 3, + 'Апр' => 4, + 'апреля' => 4, + 'Май' => 5, + 'мая' => 5, + 'Июн' => 6, + 'июня' => 6, + 'Июл' => 7, + 'июля' => 7, + 'Авг' => 8, + 'августа' => 8, + 'Сен' => 9, + 'сентября' => 9, + 'Окт' => 10, + 'октября' => 10, + 'Ноя' => 11, + 'ноября' => 11, + 'Дек' => 12, + 'декабря' => 12, + ); + /** + * List of timezones, abbreviation => offset from UTC + * + * @access protected + * @var array + */ + var $timezone = array('ACDT' => 37800, 'ACIT' => 28800, 'ACST' => 34200, 'ACT' => -18000, 'ACWDT' => 35100, 'ACWST' => 31500, 'AEDT' => 39600, 'AEST' => 36000, 'AFT' => 16200, 'AKDT' => -28800, 'AKST' => -32400, 'AMDT' => 18000, 'AMT' => -14400, 'ANAST' => 46800, 'ANAT' => 43200, 'ART' => -10800, 'AZOST' => -3600, 'AZST' => 18000, 'AZT' => 14400, 'BIOT' => 21600, 'BIT' => -43200, 'BOT' => -14400, 'BRST' => -7200, 'BRT' => -10800, 'BST' => 3600, 'BTT' => 21600, 'CAST' => 18000, 'CAT' => 7200, 'CCT' => 23400, 'CDT' => -18000, 'CEDT' => 7200, 'CEST' => 7200, 'CET' => 3600, 'CGST' => -7200, 'CGT' => -10800, 'CHADT' => 49500, 'CHAST' => 45900, 'CIST' => -28800, 'CKT' => -36000, 'CLDT' => -10800, 'CLST' => -14400, 'COT' => -18000, 'CST' => -21600, 'CVT' => -3600, 'CXT' => 25200, 'DAVT' => 25200, 'DTAT' => 36000, 'EADT' => -18000, 'EAST' => -21600, 'EAT' => 10800, 'ECT' => -18000, 'EDT' => -14400, 'EEST' => 10800, 'EET' => 7200, 'EGT' => -3600, 'EKST' => 21600, 'EST' => -18000, 'FJT' => 43200, 'FKDT' => -10800, 'FKST' => -14400, 'FNT' => -7200, 'GALT' => -21600, 'GEDT' => 14400, 'GEST' => 10800, 'GFT' => -10800, 'GILT' => 43200, 'GIT' => -32400, 'GST' => 14400, 'GST' => -7200, 'GYT' => -14400, 'HAA' => -10800, 'HAC' => -18000, 'HADT' => -32400, 'HAE' => -14400, 'HAP' => -25200, 'HAR' => -21600, 'HAST' => -36000, 'HAT' => -9000, 'HAY' => -28800, 'HKST' => 28800, 'HMT' => 18000, 'HNA' => -14400, 'HNC' => -21600, 'HNE' => -18000, 'HNP' => -28800, 'HNR' => -25200, 'HNT' => -12600, 'HNY' => -32400, 'IRDT' => 16200, 'IRKST' => 32400, 'IRKT' => 28800, 'IRST' => 12600, 'JFDT' => -10800, 'JFST' => -14400, 'JST' => 32400, 'KGST' => 21600, 'KGT' => 18000, 'KOST' => 39600, 'KOVST' => 28800, 'KOVT' => 25200, 'KRAST' => 28800, 'KRAT' => 25200, 'KST' => 32400, 'LHDT' => 39600, 'LHST' => 37800, 'LINT' => 50400, 'LKT' => 21600, 'MAGST' => 43200, 'MAGT' => 39600, 'MAWT' => 21600, 'MDT' => -21600, 'MESZ' => 7200, 'MEZ' => 3600, 'MHT' => 43200, 'MIT' => -34200, 'MNST' => 32400, 'MSDT' => 14400, 'MSST' => 10800, 'MST' => -25200, 'MUT' => 14400, 'MVT' => 18000, 'MYT' => 28800, 'NCT' => 39600, 'NDT' => -9000, 'NFT' => 41400, 'NMIT' => 36000, 'NOVST' => 25200, 'NOVT' => 21600, 'NPT' => 20700, 'NRT' => 43200, 'NST' => -12600, 'NUT' => -39600, 'NZDT' => 46800, 'NZST' => 43200, 'OMSST' => 25200, 'OMST' => 21600, 'PDT' => -25200, 'PET' => -18000, 'PETST' => 46800, 'PETT' => 43200, 'PGT' => 36000, 'PHOT' => 46800, 'PHT' => 28800, 'PKT' => 18000, 'PMDT' => -7200, 'PMST' => -10800, 'PONT' => 39600, 'PST' => -28800, 'PWT' => 32400, 'PYST' => -10800, 'PYT' => -14400, 'RET' => 14400, 'ROTT' => -10800, 'SAMST' => 18000, 'SAMT' => 14400, 'SAST' => 7200, 'SBT' => 39600, 'SCDT' => 46800, 'SCST' => 43200, 'SCT' => 14400, 'SEST' => 3600, 'SGT' => 28800, 'SIT' => 28800, 'SRT' => -10800, 'SST' => -39600, 'SYST' => 10800, 'SYT' => 7200, 'TFT' => 18000, 'THAT' => -36000, 'TJT' => 18000, 'TKT' => -36000, 'TMT' => 18000, 'TOT' => 46800, 'TPT' => 32400, 'TRUT' => 36000, 'TVT' => 43200, 'TWT' => 28800, 'UYST' => -7200, 'UYT' => -10800, 'UZT' => 18000, 'VET' => -14400, 'VLAST' => 39600, 'VLAT' => 36000, 'VOST' => 21600, 'VUT' => 39600, 'WAST' => 7200, 'WAT' => 3600, 'WDT' => 32400, 'WEST' => 3600, 'WFT' => 43200, 'WIB' => 25200, 'WIT' => 32400, 'WITA' => 28800, 'WKST' => 18000, 'WST' => 28800, 'YAKST' => 36000, 'YAKT' => 32400, 'YAPT' => 36000, 'YEKST' => 21600, 'YEKT' => 18000); + /** + * Cached PCRE for SimplePie_Parse_Date::$day + * + * @access protected + * @var string + */ + var $day_pcre; + /** + * Cached PCRE for SimplePie_Parse_Date::$month + * + * @access protected + * @var string + */ + var $month_pcre; + /** + * Array of user-added callback methods + * + * @access private + * @var array + */ + var $built_in = array(); + /** + * Array of user-added callback methods + * + * @access private + * @var array + */ + var $user = array(); + /** + * Create new SimplePie_Parse_Date object, and set self::day_pcre, + * self::month_pcre, and self::built_in + * + * @access private + */ + public function __construct() + { + } + /** + * Get the object + * + * @access public + */ + public static function get() + { + } + /** + * Parse a date + * + * @final + * @access public + * @param string $date Date to parse + * @return int Timestamp corresponding to date string, or false on failure + */ + public function parse($date) + { + } + /** + * Add a callback method to parse a date + * + * @final + * @access public + * @param callback $callback + */ + public function add_callback($callback) + { + } + /** + * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as + * well as allowing any of upper or lower case "T", horizontal tabs, or + * spaces to be used as the time separator (including more than one)) + * + * @access protected + * @return int Timestamp + */ + public function date_w3cdtf($date) + { + } + /** + * Remove RFC822 comments + * + * @access protected + * @param string $data Data to strip comments from + * @return string Comment stripped string + */ + public function remove_rfc2822_comments($string) + { + } + /** + * Parse RFC2822's date format + * + * @access protected + * @return int Timestamp + */ + public function date_rfc2822($date) + { + } + /** + * Parse RFC850's date format + * + * @access protected + * @return int Timestamp + */ + public function date_rfc850($date) + { + } + /** + * Parse C99's asctime()'s date format + * + * @access protected + * @return int Timestamp + */ + public function date_asctime($date) + { + } + /** + * Parse dates using strtotime() + * + * @access protected + * @return int Timestamp + */ + public function date_strtotime($date) + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Parses XML into something sane + * + * + * This class can be overloaded with {@see SimplePie::set_parser_class()} + * + * @package SimplePie + * @subpackage Parsing + */ + class SimplePie_Parser + { + var $error_code; + var $error_string; + var $current_line; + var $current_column; + var $current_byte; + var $separator = ' '; + var $namespace = array(''); + var $element = array(''); + var $xml_base = array(''); + var $xml_base_explicit = array(\false); + var $xml_lang = array(''); + var $data = array(); + var $datas = array(array()); + var $current_xhtml_construct = -1; + var $encoding; + protected $registry; + public function set_registry(\SimplePie_Registry $registry) + { + } + public function parse(&$data, $encoding, $url = '') + { + } + public function get_error_code() + { + } + public function get_error_string() + { + } + public function get_current_line() + { + } + public function get_current_column() + { + } + public function get_current_byte() + { + } + public function get_data() + { + } + public function tag_open($parser, $tag, $attributes) + { + } + public function cdata($parser, $cdata) + { + } + public function tag_close($parser, $tag) + { + } + public function split_ns($string) + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Handles `<media:rating>` or `<itunes:explicit>` tags as defined in Media RSS and iTunes RSS respectively + * + * Used by {@see SimplePie_Enclosure::get_rating()} and {@see SimplePie_Enclosure::get_ratings()} + * + * This class can be overloaded with {@see SimplePie::set_rating_class()} + * + * @package SimplePie + * @subpackage API + */ + class SimplePie_Rating + { + /** + * Rating scheme + * + * @var string + * @see get_scheme() + */ + var $scheme; + /** + * Rating value + * + * @var string + * @see get_value() + */ + var $value; + /** + * Constructor, used to input the data + * + * For documentation on all the parameters, see the corresponding + * properties and their accessors + */ + public function __construct($scheme = \null, $value = \null) + { + } + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + } + /** + * Get the organizational scheme for the rating + * + * @return string|null + */ + public function get_scheme() + { + } + /** + * Get the value of the rating + * + * @return string|null + */ + public function get_value() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Handles creating objects and calling methods + * + * Access this via {@see SimplePie::get_registry()} + * + * @package SimplePie + */ + class SimplePie_Registry + { + /** + * Default class mapping + * + * Overriding classes *must* subclass these. + * + * @var array + */ + protected $default = array('Cache' => 'SimplePie_Cache', 'Locator' => 'SimplePie_Locator', 'Parser' => 'SimplePie_Parser', 'File' => 'SimplePie_File', 'Sanitize' => 'SimplePie_Sanitize', 'Item' => 'SimplePie_Item', 'Author' => 'SimplePie_Author', 'Category' => 'SimplePie_Category', 'Enclosure' => 'SimplePie_Enclosure', 'Caption' => 'SimplePie_Caption', 'Copyright' => 'SimplePie_Copyright', 'Credit' => 'SimplePie_Credit', 'Rating' => 'SimplePie_Rating', 'Restriction' => 'SimplePie_Restriction', 'Content_Type_Sniffer' => 'SimplePie_Content_Type_Sniffer', 'Source' => 'SimplePie_Source', 'Misc' => 'SimplePie_Misc', 'XML_Declaration_Parser' => 'SimplePie_XML_Declaration_Parser', 'Parse_Date' => 'SimplePie_Parse_Date'); + /** + * Class mapping + * + * @see register() + * @var array + */ + protected $classes = array(); + /** + * Legacy classes + * + * @see register() + * @var array + */ + protected $legacy = array(); + /** + * Constructor + * + * No-op + */ + public function __construct() + { + } + /** + * Register a class + * + * @param string $type See {@see $default} for names + * @param string $class Class name, must subclass the corresponding default + * @param bool $legacy Whether to enable legacy support for this class + * @return bool Successfulness + */ + public function register($type, $class, $legacy = \false) + { + } + /** + * Get the class registered for a type + * + * Where possible, use {@see create()} or {@see call()} instead + * + * @param string $type + * @return string|null + */ + public function get_class($type) + { + } + /** + * Create a new instance of a given type + * + * @param string $type + * @param array $parameters Parameters to pass to the constructor + * @return object Instance of class + */ + public function &create($type, $parameters = array()) + { + } + /** + * Call a static method for a type + * + * @param string $type + * @param string $method + * @param array $parameters + * @return mixed + */ + public function &call($type, $method, $parameters = array()) + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Handles `<media:restriction>` as defined in Media RSS + * + * Used by {@see SimplePie_Enclosure::get_restriction()} and {@see SimplePie_Enclosure::get_restrictions()} + * + * This class can be overloaded with {@see SimplePie::set_restriction_class()} + * + * @package SimplePie + * @subpackage API + */ + class SimplePie_Restriction + { + /** + * Relationship ('allow'/'deny') + * + * @var string + * @see get_relationship() + */ + var $relationship; + /** + * Type of restriction + * + * @var string + * @see get_type() + */ + var $type; + /** + * Restricted values + * + * @var string + * @see get_value() + */ + var $value; + /** + * Constructor, used to input the data + * + * For documentation on all the parameters, see the corresponding + * properties and their accessors + */ + public function __construct($relationship = \null, $type = \null, $value = \null) + { + } + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + } + /** + * Get the relationship + * + * @return string|null Either 'allow' or 'deny' + */ + public function get_relationship() + { + } + /** + * Get the type + * + * @return string|null + */ + public function get_type() + { + } + /** + * Get the list of restricted things + * + * @return string|null + */ + public function get_value() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Used for data cleanup and post-processing + * + * + * This class can be overloaded with {@see SimplePie::set_sanitize_class()} + * + * @package SimplePie + * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags + */ + class SimplePie_Sanitize + { + // Private vars + var $base; + // Options + var $remove_div = \true; + var $image_handler = ''; + var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'); + var $encode_instead_of_strip = \false; + var $strip_attributes = array('bgsound', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'); + var $add_attributes = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none')); + var $strip_comments = \false; + var $output_encoding = 'UTF-8'; + var $enable_cache = \true; + var $cache_location = './cache'; + var $cache_name_function = 'md5'; + var $timeout = 10; + var $useragent = ''; + var $force_fsockopen = \false; + var $replace_url_attributes = \null; + var $registry; + /** + * List of domains for which to force HTTPS. + * @see SimplePie_Sanitize::set_https_domains() + * Array is a tree split at DNS levels. Example: + * array('biz' => true, 'com' => array('example' => true), 'net' => array('example' => array('www' => true))) + */ + var $https_domains = array(); + public function __construct() + { + } + public function remove_div($enable = \true) + { + } + public function set_image_handler($page = \false) + { + } + public function set_registry(\SimplePie_Registry $registry) + { + } + public function pass_cache_data($enable_cache = \true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache') + { + } + public function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = \false) + { + } + public function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style')) + { + } + public function encode_instead_of_strip($encode = \false) + { + } + public function strip_attributes($attribs = array('bgsound', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc')) + { + } + public function add_attributes($attribs = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none'))) + { + } + public function strip_comments($strip = \false) + { + } + public function set_output_encoding($encoding = 'UTF-8') + { + } + /** + * Set element/attribute key/value pairs of HTML attributes + * containing URLs that need to be resolved relative to the feed + * + * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite, + * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite, + * |q|@cite + * + * @since 1.0 + * @param array|null $element_attribute Element/attribute key/value pairs, null for default + */ + public function set_url_replacements($element_attribute = \null) + { + } + /** + * Set the list of domains for which to force HTTPS. + * @see SimplePie_Misc::https_url() + * Example array('biz', 'example.com', 'example.org', 'www.example.net'); + */ + public function set_https_domains($domains) + { + } + /** + * Check if the domain is in the list of forced HTTPS. + */ + protected function is_https_domain($domain) + { + } + /** + * Force HTTPS for selected Web sites. + */ + public function https_url($url) + { + } + public function sanitize($data, $type, $base = '') + { + } + protected function preprocess($html, $type) + { + } + public function replace_urls($document, $tag, $attributes) + { + } + public function do_strip_htmltags($match) + { + } + protected function strip_tag($tag, $document, $xpath, $type) + { + } + protected function strip_attr($attrib, $xpath) + { + } + protected function add_attr($tag, $valuePairs, $document) + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Handles `<atom:source>` + * + * Used by {@see SimplePie_Item::get_source()} + * + * This class can be overloaded with {@see SimplePie::set_source_class()} + * + * @package SimplePie + * @subpackage API + */ + class SimplePie_Source + { + var $item; + var $data = array(); + protected $registry; + public function __construct($item, $data) + { + } + public function set_registry(\SimplePie_Registry $registry) + { + } + public function __toString() + { + } + public function get_source_tags($namespace, $tag) + { + } + public function get_base($element = array()) + { + } + public function sanitize($data, $type, $base = '') + { + } + public function get_item() + { + } + public function get_title() + { + } + public function get_category($key = 0) + { + } + public function get_categories() + { + } + public function get_author($key = 0) + { + } + public function get_authors() + { + } + public function get_contributor($key = 0) + { + } + public function get_contributors() + { + } + public function get_link($key = 0, $rel = 'alternate') + { + } + /** + * Added for parity between the parent-level and the item/entry-level. + */ + public function get_permalink() + { + } + public function get_links($rel = 'alternate') + { + } + public function get_description() + { + } + public function get_copyright() + { + } + public function get_language() + { + } + public function get_latitude() + { + } + public function get_longitude() + { + } + public function get_image_url() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Parses the XML Declaration + * + * @package SimplePie + * @subpackage Parsing + */ + class SimplePie_XML_Declaration_Parser + { + /** + * XML Version + * + * @access public + * @var string + */ + var $version = '1.0'; + /** + * Encoding + * + * @access public + * @var string + */ + var $encoding = 'UTF-8'; + /** + * Standalone + * + * @access public + * @var bool + */ + var $standalone = \false; + /** + * Current state of the state machine + * + * @access private + * @var string + */ + var $state = 'before_version_name'; + /** + * Input data + * + * @access private + * @var string + */ + var $data = ''; + /** + * Input data length (to avoid calling strlen() everytime this is needed) + * + * @access private + * @var int + */ + var $data_length = 0; + /** + * Current position of the pointer + * + * @var int + * @access private + */ + var $position = 0; + /** + * Create an instance of the class with the input data + * + * @access public + * @param string $data Input data + */ + public function __construct($data) + { + } + /** + * Parse the input data + * + * @access public + * @return bool true on success, false on failure + */ + public function parse() + { + } + /** + * Check whether there is data beyond the pointer + * + * @access private + * @return bool true if there is further data, false if not + */ + public function has_data() + { + } + /** + * Advance past any whitespace + * + * @return int Number of whitespace characters passed + */ + public function skip_whitespace() + { + } + /** + * Read value + */ + public function get_value() + { + } + public function before_version_name() + { + } + public function version_name() + { + } + public function version_equals() + { + } + public function version_value() + { + } + public function encoding_name() + { + } + public function encoding_equals() + { + } + public function encoding_value() + { + } + public function standalone_name() + { + } + public function standalone_equals() + { + } + public function standalone_value() + { + } + } + /** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue + * @author Ryan Parman + * @author Sam Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + /** + * Decode 'gzip' encoded HTTP data + * + * @package SimplePie + * @subpackage HTTP + * @link http://www.gzip.org/format.txt + */ + class SimplePie_gzdecode + { + /** + * Compressed data + * + * @access private + * @var string + * @see gzdecode::$data + */ + var $compressed_data; + /** + * Size of compressed data + * + * @access private + * @var int + */ + var $compressed_size; + /** + * Minimum size of a valid gzip string + * + * @access private + * @var int + */ + var $min_compressed_size = 18; + /** + * Current position of pointer + * + * @access private + * @var int + */ + var $position = 0; + /** + * Flags (FLG) + * + * @access private + * @var int + */ + var $flags; + /** + * Uncompressed data + * + * @access public + * @see gzdecode::$compressed_data + * @var string + */ + var $data; + /** + * Modified time + * + * @access public + * @var int + */ + var $MTIME; + /** + * Extra Flags + * + * @access public + * @var int + */ + var $XFL; + /** + * Operating System + * + * @access public + * @var int + */ + var $OS; + /** + * Subfield ID 1 + * + * @access public + * @see gzdecode::$extra_field + * @see gzdecode::$SI2 + * @var string + */ + var $SI1; + /** + * Subfield ID 2 + * + * @access public + * @see gzdecode::$extra_field + * @see gzdecode::$SI1 + * @var string + */ + var $SI2; + /** + * Extra field content + * + * @access public + * @see gzdecode::$SI1 + * @see gzdecode::$SI2 + * @var string + */ + var $extra_field; + /** + * Original filename + * + * @access public + * @var string + */ + var $filename; + /** + * Human readable comment + * + * @access public + * @var string + */ + var $comment; + /** + * Don't allow anything to be set + * + * @param string $name + * @param mixed $value + */ + public function __set($name, $value) + { + } + /** + * Set the compressed string and related properties + * + * @param string $data + */ + public function __construct($data) + { + } + /** + * Decode the GZIP stream + * + * @return bool Successfulness + */ + public function parse() + { + } + } + /** + * General API for generating and formatting diffs - the differences between + * two sequences of strings. + * + * The original PHP version of this code was written by Geoffrey T. Dairiki + * <dairiki@dairiki.org>, and is used/adapted with his permission. + * + * Copyright 2004 Geoffrey T. Dairiki <dairiki@dairiki.org> + * Copyright 2004-2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @package Text_Diff + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + */ + class Text_Diff + { + /** + * Array of changes. + * + * @var array + */ + var $_edits; + /** + * Computes diffs between sequences of strings. + * + * @param string $engine Name of the diffing engine to use. 'auto' + * will automatically select the best. + * @param array $params Parameters to pass to the diffing engine. + * Normally an array of two arrays, each + * containing the lines from a file. + */ + function __construct($engine, $params) + { + } + /** + * PHP4 constructor. + */ + public function Text_Diff($engine, $params) + { + } + /** + * Returns the array of differences. + */ + function getDiff() + { + } + /** + * returns the number of new (added) lines in a given diff. + * + * @since Text_Diff 1.1.0 + * + * @return int The number of new lines + */ + function countAddedLines() + { + } + /** + * Returns the number of deleted (removed) lines in a given diff. + * + * @since Text_Diff 1.1.0 + * + * @return int The number of deleted lines + */ + function countDeletedLines() + { + } + /** + * Computes a reversed diff. + * + * Example: + * <code> + * $diff = new Text_Diff($lines1, $lines2); + * $rev = $diff->reverse(); + * </code> + * + * @return Text_Diff A Diff object representing the inverse of the + * original diff. Note that we purposely don't return a + * reference here, since this essentially is a clone() + * method. + */ + function reverse() + { + } + /** + * Checks for an empty diff. + * + * @return bool True if two sequences were identical. + */ + function isEmpty() + { + } + /** + * Computes the length of the Longest Common Subsequence (LCS). + * + * This is mostly for diagnostic purposes. + * + * @return int The length of the LCS. + */ + function lcs() + { + } + /** + * Gets the original set of lines. + * + * This reconstructs the $from_lines parameter passed to the constructor. + * + * @return array The original sequence of strings. + */ + function getOriginal() + { + } + /** + * Gets the final set of lines. + * + * This reconstructs the $to_lines parameter passed to the constructor. + * + * @return array The sequence of strings. + */ + function getFinal() + { + } + /** + * Removes trailing newlines from a line of text. This is meant to be used + * with array_walk(). + * + * @param string $line The line to trim. + * @param int $key The index of the line in the array. Not used. + */ + static function trimNewlines(&$line, $key) + { + } + /** + * Determines the location of the system temporary directory. + * + * @access protected + * + * @return string A directory name which can be used for temp files. + * Returns false if one could not be found. + */ + static function _getTempDir() + { + } + /** + * Checks a diff for validity. + * + * This is here only for debugging purposes. + */ + function _check($from_lines, $to_lines) + { + } + } + /** + * @package Text_Diff + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + */ + class Text_MappedDiff extends \Text_Diff + { + /** + * Computes a diff between sequences of strings. + * + * This can be used to compute things like case-insensitve diffs, or diffs + * which ignore changes in white-space. + * + * @param array $from_lines An array of strings. + * @param array $to_lines An array of strings. + * @param array $mapped_from_lines This array should have the same size + * number of elements as $from_lines. The + * elements in $mapped_from_lines and + * $mapped_to_lines are what is actually + * compared when computing the diff. + * @param array $mapped_to_lines This array should have the same number + * of elements as $to_lines. + */ + function __construct($from_lines, $to_lines, $mapped_from_lines, $mapped_to_lines) + { + } + /** + * PHP4 constructor. + */ + public function Text_MappedDiff($from_lines, $to_lines, $mapped_from_lines, $mapped_to_lines) + { + } + } + /** + * @package Text_Diff + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + * + * @access private + */ + class Text_Diff_Op + { + var $orig; + var $final; + function &reverse() + { + } + function norig() + { + } + function nfinal() + { + } + } + /** + * @package Text_Diff + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + * + * @access private + */ + class Text_Diff_Op_copy extends \Text_Diff_Op + { + /** + * PHP5 constructor. + */ + function __construct($orig, $final = \false) + { + } + /** + * PHP4 constructor. + */ + public function Text_Diff_Op_copy($orig, $final = \false) + { + } + function &reverse() + { + } + } + /** + * @package Text_Diff + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + * + * @access private + */ + class Text_Diff_Op_delete extends \Text_Diff_Op + { + /** + * PHP5 constructor. + */ + function __construct($lines) + { + } + /** + * PHP4 constructor. + */ + public function Text_Diff_Op_delete($lines) + { + } + function &reverse() + { + } + } + /** + * @package Text_Diff + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + * + * @access private + */ + class Text_Diff_Op_add extends \Text_Diff_Op + { + /** + * PHP5 constructor. + */ + function __construct($lines) + { + } + /** + * PHP4 constructor. + */ + public function Text_Diff_Op_add($lines) + { + } + function &reverse() + { + } + } + /** + * @package Text_Diff + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + * + * @access private + */ + class Text_Diff_Op_change extends \Text_Diff_Op + { + /** + * PHP5 constructor. + */ + function __construct($orig, $final) + { + } + /** + * PHP4 constructor. + */ + public function Text_Diff_Op_change($orig, $final) + { + } + function &reverse() + { + } + } + /** + * Class used internally by Text_Diff to actually compute the diffs. + * + * This class is implemented using native PHP code. + * + * The algorithm used here is mostly lifted from the perl module + * Algorithm::Diff (version 1.06) by Ned Konz, which is available at: + * http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip + * + * More ideas are taken from: http://www.ics.uci.edu/~eppstein/161/960229.html + * + * Some ideas (and a bit of code) are taken from analyze.c, of GNU + * diffutils-2.7, which can be found at: + * ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz + * + * Some ideas (subdivision by NCHUNKS > 2, and some optimizations) are from + * Geoffrey T. Dairiki <dairiki@dairiki.org>. The original PHP version of this + * code was written by him, and is used/adapted with his permission. + * + * Copyright 2004-2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + * @package Text_Diff + */ + class Text_Diff_Engine_native + { + function diff($from_lines, $to_lines) + { + } + /** + * Divides the Largest Common Subsequence (LCS) of the sequences (XOFF, + * XLIM) and (YOFF, YLIM) into NCHUNKS approximately equally sized + * segments. + * + * Returns (LCS, PTS). LCS is the length of the LCS. PTS is an array of + * NCHUNKS+1 (X, Y) indexes giving the diving points between sub + * sequences. The first sub-sequence is contained in (X0, X1), (Y0, Y1), + * the second in (X1, X2), (Y1, Y2) and so on. Note that (X0, Y0) == + * (XOFF, YOFF) and (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM). + * + * This function assumes that the first lines of the specified portions of + * the two files do not match, and likewise that the last lines do not + * match. The caller must trim matching lines from the beginning and end + * of the portions it is going to specify. + */ + function _diag($xoff, $xlim, $yoff, $ylim, $nchunks) + { + } + function _lcsPos($ypos) + { + } + /** + * Finds LCS of two sequences. + * + * The results are recorded in the vectors $this->{x,y}changed[], by + * storing a 1 in the element for each line that is an insertion or + * deletion (ie. is not in the LCS). + * + * The subsequence of file 0 is (XOFF, XLIM) and likewise for file 1. + * + * Note that XLIM, YLIM are exclusive bounds. All line numbers are + * origin-0 and discarded lines are not counted. + */ + function _compareseq($xoff, $xlim, $yoff, $ylim) + { + } + /** + * Adjusts inserts/deletes of identical lines to join changes as much as + * possible. + * + * We do something when a run of changed lines include a line at one end + * and has an excluded, identical line at the other. We are free to + * choose which identical line is included. `compareseq' usually chooses + * the one at the beginning, but usually it is cleaner to consider the + * following identical line to be the "change". + * + * This is extracted verbatim from analyze.c (GNU diffutils-2.7). + */ + function _shiftBoundaries($lines, &$changed, $other_changed) + { + } + } + /** + * Class used internally by Diff to actually compute the diffs. + * + * This class uses the Unix `diff` program via shell_exec to compute the + * differences between the two input arrays. + * + * Copyright 2007-2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @author Milian Wolff <mail@milianw.de> + * @package Text_Diff + * @since 0.3.0 + */ + class Text_Diff_Engine_shell + { + /** + * Path to the diff executable + * + * @var string + */ + var $_diffCommand = 'diff'; + /** + * Returns the array of differences. + * + * @param array $from_lines lines of text from old file + * @param array $to_lines lines of text from new file + * + * @return array all changes made (array with Text_Diff_Op_* objects) + */ + function diff($from_lines, $to_lines) + { + } + /** + * Get lines from either the old or new text + * + * @access private + * + * @param array $text_lines Either $from_lines or $to_lines (passed by reference). + * @param int $line_no Current line number (passed by reference). + * @param int $end Optional end line, when we want to chop more + * than one line. + * + * @return array The chopped lines + */ + function _getLines(&$text_lines, &$line_no, $end = \false) + { + } + } + /** + * Parses unified or context diffs output from eg. the diff utility. + * + * Example: + * <code> + * $patch = file_get_contents('example.patch'); + * $diff = new Text_Diff('string', array($patch)); + * $renderer = new Text_Diff_Renderer_inline(); + * echo $renderer->render($diff); + * </code> + * + * Copyright 2005 Örjan Persson <o@42mm.org> + * Copyright 2005-2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @author Örjan Persson <o@42mm.org> + * @package Text_Diff + * @since 0.2.0 + */ + class Text_Diff_Engine_string + { + /** + * Parses a unified or context diff. + * + * First param contains the whole diff and the second can be used to force + * a specific diff type. If the second parameter is 'autodetect', the + * diff will be examined to find out which type of diff this is. + * + * @param string $diff The diff content. + * @param string $mode The diff mode of the content in $diff. One of + * 'context', 'unified', or 'autodetect'. + * + * @return array List of all diff operations. + */ + function diff($diff, $mode = 'autodetect') + { + } + /** + * Parses an array containing the unified diff. + * + * @param array $diff Array of lines. + * + * @return array List of all diff operations. + */ + function parseUnifiedDiff($diff) + { + } + /** + * Parses an array containing the context diff. + * + * @param array $diff Array of lines. + * + * @return array List of all diff operations. + */ + function parseContextDiff(&$diff) + { + } + } + /** + * Class used internally by Diff to actually compute the diffs. + * + * This class uses the xdiff PECL package (http://pecl.php.net/package/xdiff) + * to compute the differences between the two input arrays. + * + * Copyright 2004-2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @author Jon Parise <jon@horde.org> + * @package Text_Diff + */ + class Text_Diff_Engine_xdiff + { + /** + */ + function diff($from_lines, $to_lines) + { + } + } + /** + * A class to render Diffs in different formats. + * + * This class renders the diff in classic diff format. It is intended that + * this class be customized via inheritance, to obtain fancier outputs. + * + * Copyright 2004-2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @package Text_Diff + */ + class Text_Diff_Renderer + { + /** + * Number of leading context "lines" to preserve. + * + * This should be left at zero for this class, but subclasses may want to + * set this to other values. + */ + var $_leading_context_lines = 0; + /** + * Number of trailing context "lines" to preserve. + * + * This should be left at zero for this class, but subclasses may want to + * set this to other values. + */ + var $_trailing_context_lines = 0; + /** + * Constructor. + */ + function __construct($params = array()) + { + } + /** + * PHP4 constructor. + */ + public function Text_Diff_Renderer($params = array()) + { + } + /** + * Get any renderer parameters. + * + * @return array All parameters of this renderer object. + */ + function getParams() + { + } + /** + * Renders a diff. + * + * @param Text_Diff $diff A Text_Diff object. + * + * @return string The formatted output. + */ + function render($diff) + { + } + function _block($xbeg, $xlen, $ybeg, $ylen, &$edits) + { + } + function _startDiff() + { + } + function _endDiff() + { + } + function _blockHeader($xbeg, $xlen, $ybeg, $ylen) + { + } + function _startBlock($header) + { + } + function _endBlock() + { + } + function _lines($lines, $prefix = ' ') + { + } + function _context($lines) + { + } + function _added($lines) + { + } + function _deleted($lines) + { + } + function _changed($orig, $final) + { + } + } + /** + * "Inline" diff renderer. + * + * This class renders diffs in the Wiki-style "inline" format. + * + * @author Ciprian Popovici + * @package Text_Diff + */ + class Text_Diff_Renderer_inline extends \Text_Diff_Renderer + { + /** + * Number of leading context "lines" to preserve. + * + * @var integer + */ + var $_leading_context_lines = 10000; + /** + * Number of trailing context "lines" to preserve. + * + * @var integer + */ + var $_trailing_context_lines = 10000; + /** + * Prefix for inserted text. + * + * @var string + */ + var $_ins_prefix = '<ins>'; + /** + * Suffix for inserted text. + * + * @var string + */ + var $_ins_suffix = '</ins>'; + /** + * Prefix for deleted text. + * + * @var string + */ + var $_del_prefix = '<del>'; + /** + * Suffix for deleted text. + * + * @var string + */ + var $_del_suffix = '</del>'; + /** + * Header for each change block. + * + * @var string + */ + var $_block_header = ''; + /** + * Whether to split down to character-level. + * + * @var boolean + */ + var $_split_characters = \false; + /** + * What are we currently splitting on? Used to recurse to show word-level + * or character-level changes. + * + * @var string + */ + var $_split_level = 'lines'; + function _blockHeader($xbeg, $xlen, $ybeg, $ylen) + { + } + function _startBlock($header) + { + } + function _lines($lines, $prefix = ' ', $encode = \true) + { + } + function _added($lines) + { + } + function _deleted($lines, $words = \false) + { + } + function _changed($orig, $final) + { + } + function _splitOnWords($string, $newlineEscape = "\n") + { + } + function _encode(&$string) + { + } + } + /** + * Atom Syndication Format PHP Library + * + * @package AtomLib + * @link http://code.google.com/p/phpatomlib/ + * + * @author Elias Torres <elias@torrez.us> + * @version 0.4 + * @since 2.3.0 + */ + /** + * Structure that store common Atom Feed Properties + * + * @package AtomLib + */ + class AtomFeed + { + /** + * Stores Links + * @var array + * @access public + */ + var $links = array(); + /** + * Stores Categories + * @var array + * @access public + */ + var $categories = array(); + /** + * Stores Entries + * + * @var array + * @access public + */ + var $entries = array(); + } + /** + * Structure that store Atom Entry Properties + * + * @package AtomLib + */ + class AtomEntry + { + /** + * Stores Links + * @var array + * @access public + */ + var $links = array(); + /** + * Stores Categories + * @var array + * @access public + */ + var $categories = array(); + } + /** + * AtomLib Atom Parser API + * + * @package AtomLib + */ + class AtomParser + { + var $NS = 'http://www.w3.org/2005/Atom'; + var $ATOM_CONTENT_ELEMENTS = array('content', 'summary', 'title', 'subtitle', 'rights'); + var $ATOM_SIMPLE_ELEMENTS = array('id', 'updated', 'published', 'draft'); + var $debug = \false; + var $depth = 0; + var $indent = 2; + var $in_content; + var $ns_contexts = array(); + var $ns_decls = array(); + var $content_ns_decls = array(); + var $content_ns_contexts = array(); + var $is_xhtml = \false; + var $is_html = \false; + var $is_text = \true; + var $skipped_div = \false; + var $FILE = "php://input"; + var $feed; + var $current; + /** + * PHP5 constructor. + */ + function __construct() + { + } + /** + * PHP4 constructor. + */ + public function AtomParser() + { + } + /** + * Map attributes to key="val" + * + * @param string $k Key + * @param string $v Value + * @return string + */ + public static function map_attrs($k, $v) + { + } + /** + * Map XML namespace to string. + * + * @param indexish $p XML Namespace element index + * @param array $n Two-element array pair. [ 0 => {namespace}, 1 => {url} ] + * @return string 'xmlns="{url}"' or 'xmlns:{namespace}="{url}"' + */ + public static function map_xmlns($p, $n) + { + } + function _p($msg) + { + } + function error_handler($log_level, $log_text, $error_file, $error_line) + { + } + function parse() + { + } + function start_element($parser, $name, $attrs) + { + } + function end_element($parser, $name) + { + } + function start_ns($parser, $prefix, $uri) + { + } + function end_ns($parser, $prefix) + { + } + function cdata($parser, $data) + { + } + function _default($parser, $data) + { + } + function ns_to_prefix($qname, $attr = \false) + { + } + function is_declared_content_ns($new_mapping) + { + } + function xml_escape($content) + { + } + } + /** + * Portable PHP password hashing framework. + * @package phpass + * @since 2.5.0 + * @version 0.5 / WordPress + * @link https://www.openwall.com/phpass/ + */ + # + # Portable PHP password hashing framework. + # + # Version 0.5 / WordPress. + # + # Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in + # the public domain. Revised in subsequent years, still public domain. + # + # There's absolutely no warranty. + # + # The homepage URL for this framework is: + # + # http://www.openwall.com/phpass/ + # + # Please be sure to update the Version line if you edit this file in any way. + # It is suggested that you leave the main version number intact, but indicate + # your project name (after the slash) and add your own revision information. + # + # Please do not change the "private" password hashing method implemented in + # here, thereby making your hashes incompatible. However, if you must, please + # change the hash type identifier (the "$P$") to something different. + # + # Obviously, since this code is in the public domain, the above are not + # requirements (there can be none), but merely suggestions. + # + /** + * Portable PHP password hashing framework. + * + * @package phpass + * @version 0.5 / WordPress + * @link https://www.openwall.com/phpass/ + * @since 2.5.0 + */ + class PasswordHash + { + var $itoa64; + var $iteration_count_log2; + var $portable_hashes; + var $random_state; + function __construct($iteration_count_log2, $portable_hashes) + { + } + function PasswordHash($iteration_count_log2, $portable_hashes) + { + } + function get_random_bytes($count) + { + } + function encode64($input, $count) + { + } + function gensalt_private($input) + { + } + function crypt_private($password, $setting) + { + } + function gensalt_blowfish($input) + { + } + function HashPassword($password) + { + } + function CheckPassword($password, $stored_hash) + { + } + } + /** + * mail_fetch/setup.php + * + * Copyright (c) 1999-2011 CDI (cdi@thewebmasters.net) All Rights Reserved + * Modified by Philippe Mingo 2001-2009 mingo@rotedic.com + * An RFC 1939 compliant wrapper class for the POP3 protocol. + * + * Licensed under the GNU GPL. For full terms see the file COPYING. + * + * POP3 class + * + * @copyright 1999-2011 The SquirrelMail Project Team + * @license http://opensource.org/licenses/gpl-license.php GNU Public License + * @package plugins + * @subpackage mail_fetch + */ + class POP3 + { + var $ERROR = ''; + // Error string. + var $TIMEOUT = 60; + // Default timeout before giving up on a + // network operation. + var $COUNT = -1; + // Mailbox msg count + var $BUFFER = 512; + // Socket buffer for socket fgets() calls. + // Per RFC 1939 the returned line a POP3 + // server can send is 512 bytes. + var $FP = ''; + // The connection to the server's + // file descriptor + var $MAILSERVER = ''; + // Set this to hard code the server name + var $DEBUG = \FALSE; + // set to true to echo pop3 + // commands and responses to error_log + // this WILL log passwords! + var $BANNER = ''; + // Holds the banner returned by the + // pop server - used for apop() + var $ALLOWAPOP = \FALSE; + // Allow or disallow apop() + // This must be set to true + // manually + /** + * PHP5 constructor. + */ + function __construct($server = '', $timeout = '') + { + } + /** + * PHP4 constructor. + */ + public function POP3($server = '', $timeout = '') + { + } + function update_timer() + { + } + function connect($server, $port = 110) + { + } + function user($user = "") + { + } + function pass($pass = "") + { + } + function apop($login, $pass) + { + } + function login($login = "", $pass = "") + { + } + function top($msgNum, $numLines = "0") + { + } + function pop_list($msgNum = "") + { + } + function get($msgNum) + { + } + function last($type = "count") + { + } + function reset() + { + } + function send_cmd($cmd = "") + { + } + function quit() + { + } + function popstat() + { + } + function uidl($msgNum = "") + { + } + function delete($msgNum = "") + { + } + // ********************************************************* + // The following methods are internal to the class. + function is_ok($cmd = "") + { + } + function strip_clf($text = "") + { + } + function parse_banner($server_text) + { + } + } + /** + * Requests for PHP + * + * Inspired by Requests for Python. + * + * Based on concepts from SimplePie_File, RequestCore and WP_Http. + * + * @package Requests + */ + /** + * Requests for PHP + * + * Inspired by Requests for Python. + * + * Based on concepts from SimplePie_File, RequestCore and WP_Http. + * + * @package Requests + */ + class Requests + { + /** + * POST method + * + * @var string + */ + const POST = 'POST'; + /** + * PUT method + * + * @var string + */ + const PUT = 'PUT'; + /** + * GET method + * + * @var string + */ + const GET = 'GET'; + /** + * HEAD method + * + * @var string + */ + const HEAD = 'HEAD'; + /** + * DELETE method + * + * @var string + */ + const DELETE = 'DELETE'; + /** + * OPTIONS method + * + * @var string + */ + const OPTIONS = 'OPTIONS'; + /** + * TRACE method + * + * @var string + */ + const TRACE = 'TRACE'; + /** + * PATCH method + * + * @link https://tools.ietf.org/html/rfc5789 + * @var string + */ + const PATCH = 'PATCH'; + /** + * Default size of buffer size to read streams + * + * @var integer + */ + const BUFFER_SIZE = 1160; + /** + * Current version of Requests + * + * @var string + */ + const VERSION = '1.8.1'; + /** + * Registered transport classes + * + * @var array + */ + protected static $transports = array(); + /** + * Selected transport name + * + * Use {@see get_transport()} instead + * + * @var array + */ + public static $transport = array(); + /** + * Default certificate path. + * + * @see Requests::get_certificate_path() + * @see Requests::set_certificate_path() + * + * @var string + */ + protected static $certificate_path; + /** + * Autoloader for Requests + * + * Register this with {@see register_autoloader()} if you'd like to avoid + * having to create your own. + * + * (You can also use `spl_autoload_register` directly if you'd prefer.) + * + * @codeCoverageIgnore + * + * @param string $class Class name to load + */ + public static function autoloader($class) + { + } + /** + * Register the built-in autoloader + * + * @codeCoverageIgnore + */ + public static function register_autoloader() + { + } + /** + * Register a transport + * + * @param string $transport Transport class to add, must support the Requests_Transport interface + */ + public static function add_transport($transport) + { + } + /** + * Get a working transport + * + * @throws Requests_Exception If no valid transport is found (`notransport`) + * @return Requests_Transport + */ + protected static function get_transport($capabilities = array()) + { + } + /**#@+ + * @see request() + * @param string $url + * @param array $headers + * @param array $options + * @return Requests_Response + */ + /** + * Send a GET request + */ + public static function get($url, $headers = array(), $options = array()) + { + } + /** + * Send a HEAD request + */ + public static function head($url, $headers = array(), $options = array()) + { + } + /** + * Send a DELETE request + */ + public static function delete($url, $headers = array(), $options = array()) + { + } + /** + * Send a TRACE request + */ + public static function trace($url, $headers = array(), $options = array()) + { + } + /**#@-*/ + /**#@+ + * @see request() + * @param string $url + * @param array $headers + * @param array $data + * @param array $options + * @return Requests_Response + */ + /** + * Send a POST request + */ + public static function post($url, $headers = array(), $data = array(), $options = array()) + { + } + /** + * Send a PUT request + */ + public static function put($url, $headers = array(), $data = array(), $options = array()) + { + } + /** + * Send an OPTIONS request + */ + public static function options($url, $headers = array(), $data = array(), $options = array()) + { + } + /** + * Send a PATCH request + * + * Note: Unlike {@see post} and {@see put}, `$headers` is required, as the + * specification recommends that should send an ETag + * + * @link https://tools.ietf.org/html/rfc5789 + */ + public static function patch($url, $headers, $data = array(), $options = array()) + { + } + /**#@-*/ + /** + * Main interface for HTTP requests + * + * This method initiates a request and sends it via a transport before + * parsing. + * + * The `$options` parameter takes an associative array with the following + * options: + * + * - `timeout`: How long should we wait for a response? + * Note: for cURL, a minimum of 1 second applies, as DNS resolution + * operates at second-resolution only. + * (float, seconds with a millisecond precision, default: 10, example: 0.01) + * - `connect_timeout`: How long should we wait while trying to connect? + * (float, seconds with a millisecond precision, default: 10, example: 0.01) + * - `useragent`: Useragent to send to the server + * (string, default: php-requests/$version) + * - `follow_redirects`: Should we follow 3xx redirects? + * (boolean, default: true) + * - `redirects`: How many times should we redirect before erroring? + * (integer, default: 10) + * - `blocking`: Should we block processing on this request? + * (boolean, default: true) + * - `filename`: File to stream the body to instead. + * (string|boolean, default: false) + * - `auth`: Authentication handler or array of user/password details to use + * for Basic authentication + * (Requests_Auth|array|boolean, default: false) + * - `proxy`: Proxy details to use for proxy by-passing and authentication + * (Requests_Proxy|array|string|boolean, default: false) + * - `max_bytes`: Limit for the response body size. + * (integer|boolean, default: false) + * - `idn`: Enable IDN parsing + * (boolean, default: true) + * - `transport`: Custom transport. Either a class name, or a + * transport object. Defaults to the first working transport from + * {@see getTransport()} + * (string|Requests_Transport, default: {@see getTransport()}) + * - `hooks`: Hooks handler. + * (Requests_Hooker, default: new Requests_Hooks()) + * - `verify`: Should we verify SSL certificates? Allows passing in a custom + * certificate file as a string. (Using true uses the system-wide root + * certificate store instead, but this may have different behaviour + * across transports.) + * (string|boolean, default: library/Requests/Transport/cacert.pem) + * - `verifyname`: Should we verify the common name in the SSL certificate? + * (boolean, default: true) + * - `data_format`: How should we send the `$data` parameter? + * (string, one of 'query' or 'body', default: 'query' for + * HEAD/GET/DELETE, 'body' for POST/PUT/OPTIONS/PATCH) + * + * @throws Requests_Exception On invalid URLs (`nonhttp`) + * + * @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 (use Requests constants) + * @param array $options Options for the request (see description for more information) + * @return Requests_Response + */ + public static function request($url, $headers = array(), $data = array(), $type = self::GET, $options = array()) + { + } + /** + * Send multiple HTTP requests simultaneously + * + * The `$requests` parameter takes an associative or indexed array of + * request fields. The key of each request can be used to match up the + * request with the returned data, or with the request passed into your + * `multiple.request.complete` callback. + * + * The request fields value is an associative array with the following keys: + * + * - `url`: Request URL Same as the `$url` parameter to + * {@see Requests::request} + * (string, required) + * - `headers`: Associative array of header fields. Same as the `$headers` + * parameter to {@see Requests::request} + * (array, default: `array()`) + * - `data`: Associative array of data fields or a string. Same as the + * `$data` parameter to {@see Requests::request} + * (array|string, default: `array()`) + * - `type`: HTTP request type (use Requests constants). Same as the `$type` + * parameter to {@see Requests::request} + * (string, default: `Requests::GET`) + * - `cookies`: Associative array of cookie name to value, or cookie jar. + * (array|Requests_Cookie_Jar) + * + * If the `$options` parameter is specified, individual requests will + * inherit options from it. This can be used to use a single hooking system, + * or set all the types to `Requests::POST`, for example. + * + * In addition, the `$options` parameter takes the following global options: + * + * - `complete`: A callback for when a request is complete. Takes two + * parameters, a Requests_Response/Requests_Exception reference, and the + * ID from the request array (Note: this can also be overridden on a + * per-request basis, although that's a little silly) + * (callback) + * + * @param array $requests Requests data (see description for more information) + * @param array $options Global and default options (see {@see Requests::request}) + * @return array Responses (either Requests_Response or a Requests_Exception object) + */ + public static function request_multiple($requests, $options = array()) + { + } + /** + * Get the default options + * + * @see Requests::request() for values returned by this method + * @param boolean $multirequest Is this a multirequest? + * @return array Default option values + */ + protected static function get_default_options($multirequest = \false) + { + } + /** + * Get default certificate path. + * + * @return string Default certificate path. + */ + public static function get_certificate_path() + { + } + /** + * Set default certificate path. + * + * @param string $path Certificate path, pointing to a PEM file. + */ + public static function set_certificate_path($path) + { + } + /** + * Set the default values + * + * @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 array $options + */ + protected static function set_defaults(&$url, &$headers, &$data, &$type, &$options) + { + } + /** + * HTTP response parser + * + * @throws Requests_Exception On missing head/body separator (`requests.no_crlf_separator`) + * @throws Requests_Exception On missing head/body separator (`noversion`) + * @throws Requests_Exception On missing head/body separator (`toomanyredirects`) + * + * @param string $headers Full response text including headers and body + * @param string $url Original request URL + * @param array $req_headers Original $headers array passed to {@link request()}, in case we need to follow redirects + * @param array $req_data Original $data array passed to {@link request()}, in case we need to follow redirects + * @param array $options Original $options array passed to {@link request()}, in case we need to follow redirects + * @return Requests_Response + */ + protected static function parse_response($headers, $url, $req_headers, $req_data, $options) + { + } + /** + * Callback for `transport.internal.parse_response` + * + * Internal use only. Converts a raw HTTP response to a Requests_Response + * while still executing a multiple request. + * + * @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 Requests::request_multiple()} + * @return null `$response` is either set to a Requests_Response instance, or a Requests_Exception object + */ + public static function parse_multiple(&$response, $request) + { + } + /** + * Decoded a chunked body as per RFC 2616 + * + * @see https://tools.ietf.org/html/rfc2616#section-3.6.1 + * @param string $data Chunked body + * @return string Decoded body + */ + protected static function decode_chunked($data) + { + } + // @codeCoverageIgnoreEnd + /** + * Convert a key => value array to a 'key: value' array for headers + * + * @param array $array Dictionary of header values + * @return array List of headers + */ + public static function flatten($array) + { + } + /** + * Convert a key => value array to a 'key: value' array for headers + * + * @codeCoverageIgnore + * @deprecated Misspelling of {@see Requests::flatten} + * @param array $array Dictionary of header values + * @return array List of headers + */ + public static function flattern($array) + { + } + /** + * Decompress an encoded body + * + * Implements gzip, compress and deflate. Guesses which it is by attempting + * to decode. + * + * @param string $data Compressed data in one of the above formats + * @return string Decompressed string + */ + public static function decompress($data) + { + } + /** + * Decompression of deflated string while staying compatible with the majority of servers. + * + * Certain Servers will return deflated data with headers which PHP's gzinflate() + * function cannot handle out of the box. The following function has been created from + * various snippets on the gzinflate() PHP documentation. + * + * Warning: Magic numbers within. Due to the potential different formats that the compressed + * data may be returned in, some "magic offsets" are needed to ensure proper decompression + * takes place. For a simple progmatic way to determine the magic offset in use, see: + * https://core.trac.wordpress.org/ticket/18273 + * + * @since 2.8.1 + * @link https://core.trac.wordpress.org/ticket/18273 + * @link https://secure.php.net/manual/en/function.gzinflate.php#70875 + * @link https://secure.php.net/manual/en/function.gzinflate.php#77336 + * + * @param string $gz_data String to decompress. + * @return string|bool False on failure. + */ + public static function compatible_gzinflate($gz_data) + { + } + public static function match_domain($host, $reference) + { + } + } + /** + * Taxonomy API: Walker_CategoryDropdown class + * + * @package WordPress + * @subpackage Template + * @since 4.4.0 + */ + /** + * Core class used to create an HTML dropdown list of Categories. + * + * @since 2.1.0 + * + * @see Walker + */ + class Walker_CategoryDropdown extends \Walker + { + /** + * What the class handles. + * + * @since 2.1.0 + * @var string + * + * @see Walker::$tree_type + */ + public $tree_type = 'category'; + /** + * Database fields to use. + * + * @since 2.1.0 + * @todo Decouple this + * @var string[] + * + * @see Walker::$db_fields + */ + public $db_fields = array('parent' => 'parent', 'id' => 'term_id'); + /** + * Starts the element output. + * + * @since 2.1.0 + * @since 5.9.0 Renamed `$category` to `$data_object` and `$id` to `$current_object_id` + * to match parent class for PHP 8 named parameter support. + * + * @see Walker::start_el() + * + * @param string $output Used to append additional content (passed by reference). + * @param WP_Term $data_object Category data object. + * @param int $depth Depth of category. Used for padding. + * @param array $args Uses 'selected', 'show_count', and 'value_field' keys, if they exist. + * See wp_dropdown_categories(). + * @param int $current_object_id Optional. ID of the current category. Default 0. + * @phpstan-param array{ + * show_option_all?: string, + * show_option_none?: string, + * option_none_value?: string, + * orderby?: string, + * pad_counts?: bool, + * show_count?: bool|int, + * echo?: bool|int, + * hierarchical?: bool|int, + * depth?: int, + * tab_index?: int, + * name?: string, + * id?: string, + * class?: string, + * selected?: int|string, + * value_field?: string, + * taxonomy?: string|array, + * hide_if_empty?: bool, + * required?: bool, + * walker?: Walker, + * aria_describedby?: string, + * } $args See wp_dropdown_categories() + */ + public function start_el(&$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0) + { + } + } + /** + * Taxonomy API: Walker_Category class + * + * @package WordPress + * @subpackage Template + * @since 4.4.0 + */ + /** + * Core class used to create an HTML list of categories. + * + * @since 2.1.0 + * + * @see Walker + */ + class Walker_Category extends \Walker + { + /** + * What the class handles. + * + * @since 2.1.0 + * @var string + * + * @see Walker::$tree_type + */ + public $tree_type = 'category'; + /** + * Database fields to use. + * + * @since 2.1.0 + * @var string[] + * + * @see Walker::$db_fields + * @todo Decouple this + */ + public $db_fields = array('parent' => 'parent', 'id' => 'term_id'); + /** + * Starts the list before the elements are added. + * + * @since 2.1.0 + * + * @see Walker::start_lvl() + * + * @param string $output Used to append additional content. Passed by reference. + * @param int $depth Optional. Depth of category. Used for tab indentation. Default 0. + * @param array $args Optional. An array of arguments. Will only append content if style argument + * value is 'list'. See wp_list_categories(). Default empty array. + * @phpstan-param array{ + * current_category?: int|int[], + * depth?: int, + * echo?: bool|int, + * exclude?: int[]|string, + * exclude_tree?: int[]|string, + * feed?: string, + * feed_image?: string, + * feed_type?: string, + * hide_title_if_empty?: bool, + * separator?: string, + * show_count?: bool|int, + * show_option_all?: string, + * show_option_none?: string, + * style?: string, + * taxonomy?: string, + * title_li?: string, + * use_desc_for_title?: bool|int, + * walker?: Walker, + * } $args See wp_list_categories() + */ + public function start_lvl(&$output, $depth = 0, $args = array()) + { + } + /** + * Ends the list of after the elements are added. + * + * @since 2.1.0 + * + * @see Walker::end_lvl() + * + * @param string $output Used to append additional content. Passed by reference. + * @param int $depth Optional. Depth of category. Used for tab indentation. Default 0. + * @param array $args Optional. An array of arguments. Will only append content if style argument + * value is 'list'. See wp_list_categories(). Default empty array. + * @phpstan-param array{ + * current_category?: int|int[], + * depth?: int, + * echo?: bool|int, + * exclude?: int[]|string, + * exclude_tree?: int[]|string, + * feed?: string, + * feed_image?: string, + * feed_type?: string, + * hide_title_if_empty?: bool, + * separator?: string, + * show_count?: bool|int, + * show_option_all?: string, + * show_option_none?: string, + * style?: string, + * taxonomy?: string, + * title_li?: string, + * use_desc_for_title?: bool|int, + * walker?: Walker, + * } $args See wp_list_categories() + */ + public function end_lvl(&$output, $depth = 0, $args = array()) + { + } + /** + * Starts the element output. + * + * @since 2.1.0 + * @since 5.9.0 Renamed `$category` to `$data_object` and `$id` to `$current_object_id` + * to match parent class for PHP 8 named parameter support. + * + * @see Walker::start_el() + * + * @param string $output Used to append additional content (passed by reference). + * @param WP_Term $data_object Category data object. + * @param int $depth Optional. Depth of category in reference to parents. Default 0. + * @param array $args Optional. An array of arguments. See wp_list_categories(). + * Default empty array. + * @param int $current_object_id Optional. ID of the current category. Default 0. + * @phpstan-param array{ + * current_category?: int|int[], + * depth?: int, + * echo?: bool|int, + * exclude?: int[]|string, + * exclude_tree?: int[]|string, + * feed?: string, + * feed_image?: string, + * feed_type?: string, + * hide_title_if_empty?: bool, + * separator?: string, + * show_count?: bool|int, + * show_option_all?: string, + * show_option_none?: string, + * style?: string, + * taxonomy?: string, + * title_li?: string, + * use_desc_for_title?: bool|int, + * walker?: Walker, + * } $args See wp_list_categories() + */ + public function start_el(&$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0) + { + } + /** + * Ends the element output, if needed. + * + * @since 2.1.0 + * @since 5.9.0 Renamed `$page` to `$data_object` to match parent class for PHP 8 named parameter support. + * + * @see Walker::end_el() + * + * @param string $output Used to append additional content (passed by reference). + * @param object $data_object Category data object. Not used. + * @param int $depth Optional. Depth of category. Not used. + * @param array $args Optional. An array of arguments. Only uses 'list' for whether should + * append to output. See wp_list_categories(). Default empty array. + * @phpstan-param array{ + * current_category?: int|int[], + * depth?: int, + * echo?: bool|int, + * exclude?: int[]|string, + * exclude_tree?: int[]|string, + * feed?: string, + * feed_image?: string, + * feed_type?: string, + * hide_title_if_empty?: bool, + * separator?: string, + * show_count?: bool|int, + * show_option_all?: string, + * show_option_none?: string, + * style?: string, + * taxonomy?: string, + * title_li?: string, + * use_desc_for_title?: bool|int, + * walker?: Walker, + * } $args See wp_list_categories() + */ + public function end_el(&$output, $data_object, $depth = 0, $args = array()) + { + } + } + /** + * Comment API: Walker_Comment class + * + * @package WordPress + * @subpackage Comments + * @since 4.4.0 + */ + /** + * Core walker class used to create an HTML list of comments. + * + * @since 2.7.0 + * + * @see Walker + */ + class Walker_Comment extends \Walker + { + /** + * What the class handles. + * + * @since 2.7.0 + * @var string + * + * @see Walker::$tree_type + */ + public $tree_type = 'comment'; + /** + * Database fields to use. + * + * @since 2.7.0 + * @var string[] + * + * @see Walker::$db_fields + * @todo Decouple this + */ + public $db_fields = array('parent' => 'comment_parent', 'id' => 'comment_ID'); + /** + * Starts the list before the elements are added. + * + * @since 2.7.0 + * + * @see Walker::start_lvl() + * @global int $comment_depth + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Optional. Depth of the current comment. Default 0. + * @param array $args Optional. Uses 'style' argument for type of HTML list. Default empty array. + */ + public function start_lvl(&$output, $depth = 0, $args = array()) + { + } + /** + * Ends the list of items after the elements are added. + * + * @since 2.7.0 + * + * @see Walker::end_lvl() + * @global int $comment_depth + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Optional. Depth of the current comment. Default 0. + * @param array $args Optional. Will only append content if style argument value is 'ol' or 'ul'. + * Default empty array. + */ + public function end_lvl(&$output, $depth = 0, $args = array()) + { + } + /** + * Traverses elements to create list from elements. + * + * This function is designed to enhance Walker::display_element() to + * display children of higher nesting levels than selected inline on + * the highest depth level displayed. This prevents them being orphaned + * at the end of the comment list. + * + * Example: max_depth = 2, with 5 levels of nested content. + * 1 + * 1.1 + * 1.1.1 + * 1.1.1.1 + * 1.1.1.1.1 + * 1.1.2 + * 1.1.2.1 + * 2 + * 2.2 + * + * @since 2.7.0 + * + * @see Walker::display_element() + * @see wp_list_comments() + * + * @param WP_Comment $element Comment data object. + * @param array $children_elements List of elements to continue traversing. Passed by reference. + * @param int $max_depth Max depth to traverse. + * @param int $depth Depth of the current element. + * @param array $args An array of arguments. + * @param string $output Used to append additional content. Passed by reference. + */ + public function display_element($element, &$children_elements, $max_depth, $depth, $args, &$output) + { + } + /** + * Starts the element output. + * + * @since 2.7.0 + * @since 5.9.0 Renamed `$comment` to `$data_object` and `$id` to `$current_object_id` + * to match parent class for PHP 8 named parameter support. + * + * @see Walker::start_el() + * @see wp_list_comments() + * @global int $comment_depth + * @global WP_Comment $comment Global comment object. + * + * @param string $output Used to append additional content. Passed by reference. + * @param WP_Comment $data_object Comment data object. + * @param int $depth Optional. Depth of the current comment in reference to parents. Default 0. + * @param array $args Optional. An array of arguments. Default empty array. + * @param int $current_object_id Optional. ID of the current comment. Default 0. + */ + public function start_el(&$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0) + { + } + /** + * Ends the element output, if needed. + * + * @since 2.7.0 + * @since 5.9.0 Renamed `$comment` to `$data_object` to match parent class for PHP 8 named parameter support. + * + * @see Walker::end_el() + * @see wp_list_comments() + * + * @param string $output Used to append additional content. Passed by reference. + * @param WP_Comment $data_object Comment data object. + * @param int $depth Optional. Depth of the current comment. Default 0. + * @param array $args Optional. An array of arguments. Default empty array. + */ + public function end_el(&$output, $data_object, $depth = 0, $args = array()) + { + } + /** + * Outputs a pingback comment. + * + * @since 3.6.0 + * + * @see wp_list_comments() + * + * @param WP_Comment $comment The comment object. + * @param int $depth Depth of the current comment. + * @param array $args An array of arguments. + */ + protected function ping($comment, $depth, $args) + { + } + /** + * Filters the comment text. + * + * Removes links from the pending comment's text if the commenter did not consent + * to the comment cookies. + * + * @since 5.4.2 + * + * @param string $comment_text Text of the current comment. + * @param WP_Comment|null $comment The comment object. Null if not found. + * @return string Filtered text of the current comment. + */ + public function filter_comment_text($comment_text, $comment) + { + } + /** + * Outputs a single comment. + * + * @since 3.6.0 + * + * @see wp_list_comments() + * + * @param WP_Comment $comment Comment to display. + * @param int $depth Depth of the current comment. + * @param array $args An array of arguments. + */ + protected function comment($comment, $depth, $args) + { + } + /** + * Outputs a comment in the HTML5 format. + * + * @since 3.6.0 + * + * @see wp_list_comments() + * + * @param WP_Comment $comment Comment to display. + * @param int $depth Depth of the current comment. + * @param array $args An array of arguments. + */ + protected function html5_comment($comment, $depth, $args) + { + } + } + /** + * Post API: Walker_PageDropdown class + * + * @package WordPress + * @subpackage Post + * @since 4.4.0 + */ + /** + * Core class used to create an HTML drop-down list of pages. + * + * @since 2.1.0 + * + * @see Walker + */ + class Walker_PageDropdown extends \Walker + { + /** + * What the class handles. + * + * @since 2.1.0 + * @var string + * + * @see Walker::$tree_type + */ + public $tree_type = 'page'; + /** + * Database fields to use. + * + * @since 2.1.0 + * @var string[] + * + * @see Walker::$db_fields + * @todo Decouple this + */ + public $db_fields = array('parent' => 'post_parent', 'id' => 'ID'); + /** + * Starts the element output. + * + * @since 2.1.0 + * @since 5.9.0 Renamed `$page` to `$data_object` and `$id` to `$current_object_id` + * to match parent class for PHP 8 named parameter support. + * + * @see Walker::start_el() + * + * @param string $output Used to append additional content. Passed by reference. + * @param WP_Post $data_object Page data object. + * @param int $depth Optional. Depth of page in reference to parent pages. + * Used for padding. Default 0. + * @param array $args Optional. Uses 'selected' argument for selected page to + * set selected HTML attribute for option element. Uses + * 'value_field' argument to fill "value" attribute. + * See wp_dropdown_pages(). Default empty array. + * @param int $current_object_id Optional. ID of the current page. Default 0. + * @phpstan-param array{ + * depth?: int, + * child_of?: int, + * selected?: int|string, + * echo?: bool|int, + * name?: string, + * id?: string, + * class?: string, + * show_option_none?: string, + * show_option_no_change?: string, + * option_none_value?: string, + * value_field?: string, + * } $args See wp_dropdown_pages() + */ + public function start_el(&$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0) + { + } + } + /** + * Post API: Walker_Page class + * + * @package WordPress + * @subpackage Template + * @since 4.4.0 + */ + /** + * Core walker class used to create an HTML list of pages. + * + * @since 2.1.0 + * + * @see Walker + */ + class Walker_Page extends \Walker + { + /** + * What the class handles. + * + * @since 2.1.0 + * @var string + * + * @see Walker::$tree_type + */ + public $tree_type = 'page'; + /** + * Database fields to use. + * + * @since 2.1.0 + * @var string[] + * + * @see Walker::$db_fields + * @todo Decouple this. + */ + public $db_fields = array('parent' => 'post_parent', 'id' => 'ID'); + /** + * Outputs the beginning of the current level in the tree before elements are output. + * + * @since 2.1.0 + * + * @see Walker::start_lvl() + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Optional. Depth of page. Used for padding. Default 0. + * @param array $args Optional. Arguments for outputting the next level. + * Default empty array. + */ + public function start_lvl(&$output, $depth = 0, $args = array()) + { + } + /** + * Outputs the end of the current level in the tree after elements are output. + * + * @since 2.1.0 + * + * @see Walker::end_lvl() + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Optional. Depth of page. Used for padding. Default 0. + * @param array $args Optional. Arguments for outputting the end of the current level. + * Default empty array. + */ + public function end_lvl(&$output, $depth = 0, $args = array()) + { + } + /** + * Outputs the beginning of the current element in the tree. + * + * @see Walker::start_el() + * @since 2.1.0 + * @since 5.9.0 Renamed `$page` to `$data_object` and `$current_page` to `$current_object_id` + * to match parent class for PHP 8 named parameter support. + * + * @param string $output Used to append additional content. Passed by reference. + * @param WP_Post $data_object Page data object. + * @param int $depth Optional. Depth of page. Used for padding. Default 0. + * @param array $args Optional. Array of arguments. Default empty array. + * @param int $current_object_id Optional. ID of the current page. Default 0. + */ + public function start_el(&$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0) + { + } + /** + * Outputs the end of the current element in the tree. + * + * @since 2.1.0 + * @since 5.9.0 Renamed `$page` to `$data_object` to match parent class for PHP 8 named parameter support. + * + * @see Walker::end_el() + * + * @param string $output Used to append additional content. Passed by reference. + * @param WP_Post $data_object Page data object. Not used. + * @param int $depth Optional. Depth of page. Default 0 (unused). + * @param array $args Optional. Array of arguments. Default empty array. + */ + public function end_el(&$output, $data_object, $depth = 0, $args = array()) + { + } + } + /** + * Toolbar API: WP_Admin_Bar class + * + * @package WordPress + * @subpackage Toolbar + * @since 3.1.0 + */ + /** + * Core class used to implement the Toolbar API. + * + * @since 3.1.0 + */ + #[\AllowDynamicProperties] + class WP_Admin_Bar + { + public $user; + /** + * @since 3.3.0 + * + * @param string $name + * @return string|array|void + */ + public function __get($name) + { + } + /** + * Initializes the admin bar. + * + * @since 3.1.0 + */ + public function initialize() + { + } + /** + * Adds a node (menu item) to the admin bar menu. + * + * @since 3.3.0 + * + * @param array $node The attributes that define the node. + */ + public function add_menu($node) + { + } + /** + * Removes a node from the admin bar. + * + * @since 3.1.0 + * + * @param string $id The menu slug to remove. + */ + public function remove_menu($id) + { + } + /** + * Adds a node to the menu. + * + * @since 3.1.0 + * @since 4.5.0 Added the ability to pass 'lang' and 'dir' meta data. + * + * @param array $args { + * Arguments for adding a node. + * + * @type string $id ID of the item. + * @type string $title Title of the node. + * @type string $parent Optional. ID of the parent node. + * @type string $href Optional. Link for the item. + * @type bool $group Optional. Whether or not the node is a group. Default false. + * @type array $meta Meta data including the following keys: 'html', 'class', 'rel', 'lang', 'dir', + * 'onclick', 'target', 'title', 'tabindex'. Default empty. + * } + * @phpstan-param array{ + * id?: string, + * title?: string, + * parent?: string, + * href?: string, + * group?: bool, + * meta?: array, + * } $args + */ + public function add_node($args) + { + } + /** + * @since 3.3.0 + * + * @param array $args + */ + protected final function _set_node($args) + { + } + /** + * Gets a node. + * + * @since 3.3.0 + * + * @param string $id + * @return object|void Node. + */ + public final function get_node($id) + { + } + /** + * @since 3.3.0 + * + * @param string $id + * @return object|void + */ + protected final function _get_node($id) + { + } + /** + * @since 3.3.0 + * + * @return array|void + */ + public final function get_nodes() + { + } + /** + * @since 3.3.0 + * + * @return array|void + */ + protected final function _get_nodes() + { + } + /** + * Adds a group to a toolbar menu node. + * + * Groups can be used to organize toolbar items into distinct sections of a toolbar menu. + * + * @since 3.3.0 + * + * @param array $args { + * Array of arguments for adding a group. + * + * @type string $id ID of the item. + * @type string $parent Optional. ID of the parent node. Default 'root'. + * @type array $meta Meta data for the group including the following keys: + * 'class', 'onclick', 'target', and 'title'. + * } + * @phpstan-param array{ + * id?: string, + * parent?: string, + * meta?: array, + * } $args + */ + public final function add_group($args) + { + } + /** + * Remove a node. + * + * @since 3.1.0 + * + * @param string $id The ID of the item. + */ + public function remove_node($id) + { + } + /** + * @since 3.3.0 + * + * @param string $id + */ + protected final function _unset_node($id) + { + } + /** + * @since 3.1.0 + */ + public function render() + { + } + /** + * @since 3.3.0 + * + * @return object|void + */ + protected final function _bind() + { + } + /** + * @since 3.3.0 + * + * @param object $root + */ + protected final function _render($root) + { + } + /** + * @since 3.3.0 + * + * @param object $node + */ + protected final function _render_container($node) + { + } + /** + * @since 3.3.0 + * + * @param object $node + */ + protected final function _render_group($node) + { + } + /** + * @since 3.3.0 + * + * @param object $node + */ + protected final function _render_item($node) + { + } + /** + * Renders toolbar items recursively. + * + * @since 3.1.0 + * @deprecated 3.3.0 Use WP_Admin_Bar::_render_item() or WP_Admin_bar::render() instead. + * @see WP_Admin_Bar::_render_item() + * @see WP_Admin_Bar::render() + * + * @param string $id Unused. + * @param object $node + */ + public function recursive_render($id, $node) + { + } + /** + * Adds menus to the admin bar. + * + * @since 3.1.0 + */ + public function add_menus() + { + } + } + /** + * Send XML response back to Ajax request. + * + * @package WordPress + * @since 2.1.0 + */ + #[\AllowDynamicProperties] + class WP_Ajax_Response + { + /** + * Store XML responses to send. + * + * @since 2.1.0 + * @var array + */ + public $responses = array(); + /** + * Constructor - Passes args to WP_Ajax_Response::add(). + * + * @since 2.1.0 + * + * @see WP_Ajax_Response::add() + * + * @param string|array $args Optional. Will be passed to add() method. + */ + public function __construct($args = '') + { + } + /** + * Appends data to an XML response based on given arguments. + * + * With `$args` defaults, extra data output would be: + * + * <response action='{$action}_$id'> + * <$what id='$id' position='$position'> + * <response_data><![CDATA[$data]]></response_data> + * </$what> + * </response> + * + * @since 2.1.0 + * + * @param string|array $args { + * Optional. An array or string of XML response arguments. + * + * @type string $what XML-RPC response type. Used as a child element of `<response>`. + * Default 'object' (`<object>`). + * @type string|false $action Value to use for the `action` attribute in `<response>`. Will be + * appended with `_$id` on output. If false, `$action` will default to + * the value of `$_POST['action']`. Default false. + * @type int|WP_Error $id The response ID, used as the response type `id` attribute. Also + * accepts a `WP_Error` object if the ID does not exist. Default 0. + * @type int|false $old_id The previous response ID. Used as the value for the response type + * `old_id` attribute. False hides the attribute. Default false. + * @type string $position Value of the response type `position` attribute. Accepts 1 (bottom), + * -1 (top), HTML ID (after), or -HTML ID (before). Default 1 (bottom). + * @type string|WP_Error $data The response content/message. Also accepts a WP_Error object if the + * ID does not exist. Default empty. + * @type array $supplemental An array of extra strings that will be output within a `<supplemental>` + * element as CDATA. Default empty array. + * } + * @return string XML response. + * @phpstan-param array{ + * what?: string, + * action?: string|false, + * id?: int|WP_Error, + * old_id?: int|false, + * position?: string, + * data?: string|WP_Error, + * supplemental?: array, + * } $args + */ + public function add($args = '') + { + } + /** + * Display XML formatted responses. + * + * Sets the content type header to text/xml. + * + * @since 2.1.0 + */ + public function send() + { + } + } + /** + * WP_Application_Passwords class + * + * @package WordPress + * @since 5.6.0 + */ + /** + * Class for displaying, modifying, and sanitizing application passwords. + * + * @package WordPress + */ + #[\AllowDynamicProperties] + class WP_Application_Passwords + { + /** + * The application passwords user meta key. + * + * @since 5.6.0 + * + * @var string + */ + const USERMETA_KEY_APPLICATION_PASSWORDS = '_application_passwords'; + /** + * The option name used to store whether application passwords are in use. + * + * @since 5.6.0 + * + * @var string + */ + const OPTION_KEY_IN_USE = 'using_application_passwords'; + /** + * The generated application password length. + * + * @since 5.6.0 + * + * @var int + */ + const PW_LENGTH = 24; + /** + * Checks if application passwords are being used by the site. + * + * This returns true if at least one application password has ever been created. + * + * @since 5.6.0 + * + * @return bool + */ + public static function is_in_use() + { + } + /** + * Creates a new application password. + * + * @since 5.6.0 + * @since 5.7.0 Returns WP_Error if application name already exists. + * + * @param int $user_id User ID. + * @param array $args { + * Arguments used to create the application password. + * + * @type string $name The name of the application password. + * @type string $app_id A UUID provided by the application to uniquely identify it. + * } + * @return array|WP_Error The first key in the array is the new password, the second is its detailed information. + * A WP_Error instance is returned on error. + * @phpstan-param array{ + * name?: string, + * app_id?: string, + * } $args + */ + public static function create_new_application_password($user_id, $args = array()) + { + } + /** + * Gets a user's application passwords. + * + * @since 5.6.0 + * + * @param int $user_id User ID. + * @return array { + * The list of app passwords. + * + * @type array ...$0 { + * @type string $uuid The unique identifier for the application password. + * @type string $app_id A UUID provided by the application to uniquely identify it. + * @type string $name The name of the application password. + * @type string $password A one-way hash of the password. + * @type int $created Unix timestamp of when the password was created. + * @type int|null $last_used The Unix timestamp of the GMT date the application password was last used. + * @type string|null $last_ip The IP address the application password was last used by. + * } + * } + * @phpstan-return array<int|string, array{ + * uuid: string, + * app_id: string, + * name: string, + * password: string, + * created: int, + * last_used: int|null, + * last_ip: string|null, + * }> + */ + public static function get_user_application_passwords($user_id) + { + } + /** + * Gets a user's application password with the given UUID. + * + * @since 5.6.0 + * + * @param int $user_id User ID. + * @param string $uuid The password's UUID. + * @return array|null The application password if found, null otherwise. + */ + public static function get_user_application_password($user_id, $uuid) + { + } + /** + * Checks if an application password with the given name exists for this user. + * + * @since 5.7.0 + * + * @param int $user_id User ID. + * @param string $name Application name. + * @return bool Whether the provided application name exists. + */ + public static function application_name_exists_for_user($user_id, $name) + { + } + /** + * Updates an application password. + * + * @since 5.6.0 + * + * @param int $user_id User ID. + * @param string $uuid The password's UUID. + * @param array $update Information about the application password to update. + * @return true|WP_Error True if successful, otherwise a WP_Error instance is returned on error. + */ + public static function update_application_password($user_id, $uuid, $update = array()) + { + } + /** + * Records that an application password has been used. + * + * @since 5.6.0 + * + * @param int $user_id User ID. + * @param string $uuid The password's UUID. + * @return true|WP_Error True if the usage was recorded, a WP_Error if an error occurs. + */ + public static function record_application_password_usage($user_id, $uuid) + { + } + /** + * Deletes an application password. + * + * @since 5.6.0 + * + * @param int $user_id User ID. + * @param string $uuid The password's UUID. + * @return true|WP_Error Whether the password was successfully found and deleted, a WP_Error otherwise. + */ + public static function delete_application_password($user_id, $uuid) + { + } + /** + * Deletes all application passwords for the given user. + * + * @since 5.6.0 + * + * @param int $user_id User ID. + * @return int|WP_Error The number of passwords that were deleted or a WP_Error on failure. + */ + public static function delete_all_application_passwords($user_id) + { + } + /** + * Sets a user's application passwords. + * + * @since 5.6.0 + * + * @param int $user_id User ID. + * @param array $passwords Application passwords. + * + * @return bool + */ + protected static function set_user_application_passwords($user_id, $passwords) + { + } + /** + * Sanitizes and then splits a password into smaller chunks. + * + * @since 5.6.0 + * + * @param string $raw_password The raw application password. + * @return string The chunked password. + */ + public static function chunk_password($raw_password) + { + } + } + /** + * Blocks API: WP_Block_Editor_Context class + * + * @package WordPress + * @since 5.8.0 + */ + /** + * Contains information about a block editor being rendered. + * + * @since 5.8.0 + */ + #[\AllowDynamicProperties] + final class WP_Block_Editor_Context + { + /** + * String that identifies the block editor being rendered. Can be one of: + * + * - `'core/edit-post'` - The post editor at `/wp-admin/edit.php`. + * - `'core/edit-widgets'` - The widgets editor at `/wp-admin/widgets.php`. + * - `'core/customize-widgets'` - The widgets editor at `/wp-admin/customize.php`. + * - `'core/edit-site'` - The site editor at `/wp-admin/site-editor.php`. + * + * Defaults to 'core/edit-post'. + * + * @since 6.0.0 + * + * @var string + */ + public $name = 'core/edit-post'; + /** + * The post being edited by the block editor. Optional. + * + * @since 5.8.0 + * + * @var WP_Post|null + */ + public $post = \null; + /** + * Constructor. + * + * Populates optional properties for a given block editor context. + * + * @since 5.8.0 + * + * @param array $settings The list of optional settings to expose in a given context. + */ + public function __construct(array $settings = array()) + { + } + } + /** + * Blocks API: WP_Block_List class + * + * @package WordPress + * @since 5.5.0 + */ + /** + * Class representing a list of block instances. + * + * @since 5.5.0 + */ + #[\AllowDynamicProperties] + class WP_Block_List implements \Iterator, \ArrayAccess, \Countable + { + /** + * Original array of parsed block data, or block instances. + * + * @since 5.5.0 + * @var array[]|WP_Block[] + * @access protected + */ + protected $blocks; + /** + * All available context of the current hierarchy. + * + * @since 5.5.0 + * @var array + * @access protected + */ + protected $available_context; + /** + * Block type registry to use in constructing block instances. + * + * @since 5.5.0 + * @var WP_Block_Type_Registry + * @access protected + */ + protected $registry; + /** + * Constructor. + * + * Populates object properties from the provided block instance argument. + * + * @since 5.5.0 + * + * @param array[]|WP_Block[] $blocks Array of parsed block data, or block instances. + * @param array $available_context Optional array of ancestry context values. + * @param WP_Block_Type_Registry $registry Optional block type registry. + */ + public function __construct($blocks, $available_context = array(), $registry = \null) + { + } + /** + * Returns true if a block exists by the specified block index, or false + * otherwise. + * + * @since 5.5.0 + * + * @link https://www.php.net/manual/en/arrayaccess.offsetexists.php + * + * @param string $index Index of block to check. + * @return bool Whether block exists. + */ + #[\ReturnTypeWillChange] + public function offsetExists($index) + { + } + /** + * Returns the value by the specified block index. + * + * @since 5.5.0 + * + * @link https://www.php.net/manual/en/arrayaccess.offsetget.php + * + * @param string $index Index of block value to retrieve. + * @return mixed|null Block value if exists, or null. + */ + #[\ReturnTypeWillChange] + public function offsetGet($index) + { + } + /** + * Assign a block value by the specified block index. + * + * @since 5.5.0 + * + * @link https://www.php.net/manual/en/arrayaccess.offsetset.php + * + * @param string $index Index of block value to set. + * @param mixed $value Block value. + */ + #[\ReturnTypeWillChange] + public function offsetSet($index, $value) + { + } + /** + * Unset a block. + * + * @since 5.5.0 + * + * @link https://www.php.net/manual/en/arrayaccess.offsetunset.php + * + * @param string $index Index of block value to unset. + */ + #[\ReturnTypeWillChange] + public function offsetUnset($index) + { + } + /** + * Rewinds back to the first element of the Iterator. + * + * @since 5.5.0 + * + * @link https://www.php.net/manual/en/iterator.rewind.php + */ + #[\ReturnTypeWillChange] + public function rewind() + { + } + /** + * Returns the current element of the block list. + * + * @since 5.5.0 + * + * @link https://www.php.net/manual/en/iterator.current.php + * + * @return mixed Current element. + */ + #[\ReturnTypeWillChange] + public function current() + { + } + /** + * Returns the key of the current element of the block list. + * + * @since 5.5.0 + * + * @link https://www.php.net/manual/en/iterator.key.php + * + * @return mixed Key of the current element. + */ + #[\ReturnTypeWillChange] + public function key() + { + } + /** + * Moves the current position of the block list to the next element. + * + * @since 5.5.0 + * + * @link https://www.php.net/manual/en/iterator.next.php + */ + #[\ReturnTypeWillChange] + public function next() + { + } + /** + * Checks if current position is valid. + * + * @since 5.5.0 + * + * @link https://www.php.net/manual/en/iterator.valid.php + */ + #[\ReturnTypeWillChange] + public function valid() + { + } + /** + * Returns the count of blocks in the list. + * + * @since 5.5.0 + * + * @link https://www.php.net/manual/en/countable.count.php + * + * @return int Block count. + */ + #[\ReturnTypeWillChange] + public function count() + { + } + } + /** + * Block Serialization Parser + * + * @package WordPress + */ + /** + * Class WP_Block_Parser_Block + * + * Holds the block structure in memory + * + * @since 5.0.0 + */ + class WP_Block_Parser_Block + { + /** + * Name of block + * + * @example "core/paragraph" + * + * @since 5.0.0 + * @var string + */ + public $blockName; + /** + * Optional set of attributes from block comment delimiters + * + * @example null + * @example array( 'columns' => 3 ) + * + * @since 5.0.0 + * @var array|null + */ + public $attrs; + /** + * List of inner blocks (of this same class) + * + * @since 5.0.0 + * @var WP_Block_Parser_Block[] + */ + public $innerBlocks; + /** + * Resultant HTML from inside block comment delimiters + * after removing inner blocks + * + * @example "...Just <!-- wp:test /--> testing..." -> "Just testing..." + * + * @since 5.0.0 + * @var string + */ + public $innerHTML; + /** + * List of string fragments and null markers where inner blocks were found + * + * @example array( + * 'innerHTML' => 'BeforeInnerAfter', + * 'innerBlocks' => array( block, block ), + * 'innerContent' => array( 'Before', null, 'Inner', null, 'After' ), + * ) + * + * @since 4.2.0 + * @var array + */ + public $innerContent; + /** + * Constructor. + * + * Will populate object properties from the provided arguments. + * + * @since 5.0.0 + * + * @param string $name Name of block. + * @param array $attrs Optional set of attributes from block comment delimiters. + * @param array $innerBlocks List of inner blocks (of this same class). + * @param string $innerHTML Resultant HTML from inside block comment delimiters after removing inner blocks. + * @param array $innerContent List of string fragments and null markers where inner blocks were found. + */ + function __construct($name, $attrs, $innerBlocks, $innerHTML, $innerContent) + { + } + } + /** + * Class WP_Block_Parser_Frame + * + * Holds partial blocks in memory while parsing + * + * @internal + * @since 5.0.0 + */ + class WP_Block_Parser_Frame + { + /** + * Full or partial block + * + * @since 5.0.0 + * @var WP_Block_Parser_Block + */ + public $block; + /** + * Byte offset into document for start of parse token + * + * @since 5.0.0 + * @var int + */ + public $token_start; + /** + * Byte length of entire parse token string + * + * @since 5.0.0 + * @var int + */ + public $token_length; + /** + * Byte offset into document for after parse token ends + * (used during reconstruction of stack into parse production) + * + * @since 5.0.0 + * @var int + */ + public $prev_offset; + /** + * Byte offset into document where leading HTML before token starts + * + * @since 5.0.0 + * @var int + */ + public $leading_html_start; + /** + * Constructor + * + * Will populate object properties from the provided arguments. + * + * @since 5.0.0 + * + * @param WP_Block_Parser_Block $block Full or partial block. + * @param int $token_start Byte offset into document for start of parse token. + * @param int $token_length Byte length of entire parse token string. + * @param int $prev_offset Byte offset into document for after parse token ends. + * @param int $leading_html_start Byte offset into document where leading HTML before token starts. + */ + function __construct($block, $token_start, $token_length, $prev_offset = \null, $leading_html_start = \null) + { + } + } + /** + * Class WP_Block_Parser + * + * Parses a document and constructs a list of parsed block objects + * + * @since 5.0.0 + * @since 4.0.0 returns arrays not objects, all attributes are arrays + */ + class WP_Block_Parser + { + /** + * Input document being parsed + * + * @example "Pre-text\n<!-- wp:paragraph -->This is inside a block!<!-- /wp:paragraph -->" + * + * @since 5.0.0 + * @var string + */ + public $document; + /** + * Tracks parsing progress through document + * + * @since 5.0.0 + * @var int + */ + public $offset; + /** + * List of parsed blocks + * + * @since 5.0.0 + * @var WP_Block_Parser_Block[] + */ + public $output; + /** + * Stack of partially-parsed structures in memory during parse + * + * @since 5.0.0 + * @var WP_Block_Parser_Frame[] + */ + public $stack; + /** + * Empty associative array, here due to PHP quirks + * + * @since 4.4.0 + * @var array empty associative array + */ + public $empty_attrs; + /** + * Parses a document and returns a list of block structures + * + * When encountering an invalid parse will return a best-effort + * parse. In contrast to the specification parser this does not + * return an error on invalid inputs. + * + * @since 5.0.0 + * + * @param string $document Input document being parsed. + * @return array[] + */ + function parse($document) + { + } + /** + * Processes the next token from the input document + * and returns whether to proceed eating more tokens + * + * This is the "next step" function that essentially + * takes a token as its input and decides what to do + * with that token before descending deeper into a + * nested block tree or continuing along the document + * or breaking out of a level of nesting. + * + * @internal + * @since 5.0.0 + * @return bool + */ + function proceed() + { + } + /** + * Scans the document from where we last left off + * and finds the next valid token to parse if it exists + * + * Returns the type of the find: kind of find, block information, attributes + * + * @internal + * @since 5.0.0 + * @since 4.6.1 fixed a bug in attribute parsing which caused catastrophic backtracking on invalid block comments + * @return array + */ + function next_token() + { + } + /** + * Returns a new block object for freeform HTML + * + * @internal + * @since 3.9.0 + * + * @param string $innerHTML HTML content of block. + * @return WP_Block_Parser_Block freeform block object. + */ + function freeform($innerHTML) + { + } + /** + * Pushes a length of text from the input document + * to the output list as a freeform block. + * + * @internal + * @since 5.0.0 + * @param null $length how many bytes of document text to output. + */ + function add_freeform($length = \null) + { + } + /** + * Given a block structure from memory pushes + * a new block to the output list. + * + * @internal + * @since 5.0.0 + * @param WP_Block_Parser_Block $block The block to add to the output. + * @param int $token_start Byte offset into the document where the first token for the block starts. + * @param int $token_length Byte length of entire block from start of opening token to end of closing token. + * @param int|null $last_offset Last byte offset into document if continuing form earlier output. + */ + function add_inner_block(\WP_Block_Parser_Block $block, $token_start, $token_length, $last_offset = \null) + { + } + /** + * Pushes the top block from the parsing stack to the output list. + * + * @internal + * @since 5.0.0 + * @param int|null $end_offset byte offset into document for where we should stop sending text output as HTML. + */ + function add_block_from_stack($end_offset = \null) + { + } + } + /** + * Blocks API: WP_Block_Pattern_Categories_Registry class + * + * @package WordPress + * @subpackage Blocks + * @since 5.5.0 + */ + /** + * Class used for interacting with block pattern categories. + */ + #[\AllowDynamicProperties] + final class WP_Block_Pattern_Categories_Registry + { + /** + * Registers a pattern category. + * + * @since 5.5.0 + * + * @param string $category_name Pattern category name including namespace. + * @param array $category_properties { + * List of properties for the block pattern category. + * + * @type string $label Required. A human-readable label for the pattern category. + * } + * @return bool True if the pattern was registered with success and false otherwise. + * @phpstan-param array{ + * label?: string, + * } $category_properties + */ + public function register($category_name, $category_properties) + { + } + /** + * Unregisters a pattern category. + * + * @since 5.5.0 + * + * @param string $category_name Pattern category name including namespace. + * @return bool True if the pattern was unregistered with success and false otherwise. + */ + public function unregister($category_name) + { + } + /** + * Retrieves an array containing the properties of a registered pattern category. + * + * @since 5.5.0 + * + * @param string $category_name Pattern category name including namespace. + * @return array Registered pattern properties. + */ + public function get_registered($category_name) + { + } + /** + * Retrieves all registered pattern categories. + * + * @since 5.5.0 + * + * @param bool $outside_init_only Return only categories registered outside the `init` action. + * @return array[] Array of arrays containing the registered pattern categories properties. + */ + public function get_all_registered($outside_init_only = \false) + { + } + /** + * Checks if a pattern category is registered. + * + * @since 5.5.0 + * + * @param string $category_name Pattern category name including namespace. + * @return bool True if the pattern category is registered, false otherwise. + */ + public function is_registered($category_name) + { + } + /** + * Utility method to retrieve the main instance of the class. + * + * The instance will be created if it does not exist yet. + * + * @since 5.5.0 + * + * @return WP_Block_Pattern_Categories_Registry The main instance. + */ + public static function get_instance() + { + } + } + /** + * Blocks API: WP_Block_Patterns_Registry class + * + * @package WordPress + * @subpackage Blocks + * @since 5.5.0 + */ + /** + * Class used for interacting with block patterns. + * + * @since 5.5.0 + */ + #[\AllowDynamicProperties] + final class WP_Block_Patterns_Registry + { + /** + * Registers a block pattern. + * + * @since 5.5.0 + * @since 5.8.0 Added support for the `blockTypes` property. + * + * @param string $pattern_name Block pattern name including namespace. + * @param array $pattern_properties { + * List of properties for the block pattern. + * + * @type string $title Required. A human-readable title for the pattern. + * @type string $content Required. Block HTML markup for the pattern. + * @type string $description Optional. Visually hidden text used to describe the pattern in the + * inserter. A description is optional, but is strongly + * encouraged when the title does not fully describe what the + * pattern does. The description will help users discover the + * pattern while searching. + * @type int $viewportWidth Optional. The intended width of the pattern to allow for a scaled + * preview within the pattern inserter. + * @type array $categories Optional. A list of registered pattern categories used to group block + * patterns. Block patterns can be shown on multiple categories. + * A category must be registered separately in order to be used + * here. + * @type array $blockTypes Optional. A list of block names including namespace that could use + * the block pattern in certain contexts (placeholder, transforms). + * The block pattern is available in the block editor inserter + * regardless of this list of block names. + * Certain blocks support further specificity besides the block name + * (e.g. for `core/template-part` you can specify areas + * like `core/template-part/header` or `core/template-part/footer`). + * @type array $keywords Optional. A list of aliases or keywords that help users discover the + * pattern while searching. + * } + * @return bool True if the pattern was registered with success and false otherwise. + * @phpstan-param array{ + * title?: string, + * content?: string, + * description?: string, + * viewportWidth?: int, + * categories?: array, + * blockTypes?: array, + * keywords?: array, + * } $pattern_properties + */ + public function register($pattern_name, $pattern_properties) + { + } + /** + * Unregisters a block pattern. + * + * @since 5.5.0 + * + * @param string $pattern_name Block pattern name including namespace. + * @return bool True if the pattern was unregistered with success and false otherwise. + */ + public function unregister($pattern_name) + { + } + /** + * Retrieves an array containing the properties of a registered block pattern. + * + * @since 5.5.0 + * + * @param string $pattern_name Block pattern name including namespace. + * @return array Registered pattern properties. + */ + public function get_registered($pattern_name) + { + } + /** + * Retrieves all registered block patterns. + * + * @since 5.5.0 + * + * @param bool $outside_init_only Return only patterns registered outside the `init` action. + * @return array[] Array of arrays containing the registered block patterns properties, + * and per style. + */ + public function get_all_registered($outside_init_only = \false) + { + } + /** + * Checks if a block pattern is registered. + * + * @since 5.5.0 + * + * @param string $pattern_name Block pattern name including namespace. + * @return bool True if the pattern is registered, false otherwise. + */ + public function is_registered($pattern_name) + { + } + /** + * Utility method to retrieve the main instance of the class. + * + * The instance will be created if it does not exist yet. + * + * @since 5.5.0 + * + * @return WP_Block_Patterns_Registry The main instance. + */ + public static function get_instance() + { + } + } + /** + * Blocks API: WP_Block_Styles_Registry class + * + * @package WordPress + * @subpackage Blocks + * @since 5.3.0 + */ + /** + * Class used for interacting with block styles. + * + * @since 5.3.0 + */ + #[\AllowDynamicProperties] + final class WP_Block_Styles_Registry + { + /** + * Registers a block style for the given block type. + * + * If the block styles are present in a standalone stylesheet, register it and pass + * its handle as the `style_handle` argument. If the block styles should be inline, + * use the `inline_style` argument. Usually, one of them would be used to pass CSS + * styles. However, you could also skip them and provide CSS styles in any stylesheet + * or with an inline tag. + * + * @since 5.3.0 + * + * @link https://developer.wordpress.org/block-editor/reference-guides/block-api/block-styles/ + * + * @param string $block_name Block type name including namespace. + * @param array $style_properties { + * Array containing the properties of the style. + * + * @type string $name The identifier of the style used to compute a CSS class. + * @type string $label A human-readable label for the style. + * @type string $inline_style Inline CSS code that registers the CSS class required + * for the style. + * @type string $style_handle The handle to an already registered style that should be + * enqueued in places where block styles are needed. + * @type bool $is_default Whether this is the default style for the block type. + * } + * @return bool True if the block style was registered with success and false otherwise. + * @phpstan-param array{ + * name?: string, + * label?: string, + * inline_style?: string, + * style_handle?: string, + * is_default?: bool, + * } $style_properties + */ + public function register($block_name, $style_properties) + { + } + /** + * Unregisters a block style of the given block type. + * + * @since 5.3.0 + * + * @param string $block_name Block type name including namespace. + * @param string $block_style_name Block style name. + * @return bool True if the block style was unregistered with success and false otherwise. + */ + public function unregister($block_name, $block_style_name) + { + } + /** + * Retrieves the properties of a registered block style for the given block type. + * + * @since 5.3.0 + * + * @param string $block_name Block type name including namespace. + * @param string $block_style_name Block style name. + * @return array Registered block style properties. + */ + public function get_registered($block_name, $block_style_name) + { + } + /** + * Retrieves all registered block styles. + * + * @since 5.3.0 + * + * @return array[] Array of arrays containing the registered block styles properties grouped by block type. + */ + public function get_all_registered() + { + } + /** + * Retrieves registered block styles for a specific block type. + * + * @since 5.3.0 + * + * @param string $block_name Block type name including namespace. + * @return array[] Array whose keys are block style names and whose values are block style properties. + */ + public function get_registered_styles_for_block($block_name) + { + } + /** + * Checks if a block style is registered for the given block type. + * + * @since 5.3.0 + * + * @param string $block_name Block type name including namespace. + * @param string $block_style_name Block style name. + * @return bool True if the block style is registered, false otherwise. + */ + public function is_registered($block_name, $block_style_name) + { + } + /** + * Utility method to retrieve the main instance of the class. + * + * The instance will be created if it does not exist yet. + * + * @since 5.3.0 + * + * @return WP_Block_Styles_Registry The main instance. + */ + public static function get_instance() + { + } + } + /** + * Block support flags. + * + * @package WordPress + * + * @since 5.6.0 + */ + /** + * Class encapsulating and implementing Block Supports. + * + * @since 5.6.0 + * + * @access private + */ + #[\AllowDynamicProperties] + class WP_Block_Supports + { + /** + * Tracks the current block to be rendered. + * + * @since 5.6.0 + * @var array + */ + public static $block_to_render = \null; + /** + * Utility method to retrieve the main instance of the class. + * + * The instance will be created if it does not exist yet. + * + * @since 5.6.0 + * + * @return WP_Block_Supports The main instance. + */ + public static function get_instance() + { + } + /** + * Initializes the block supports. It registers the block supports block attributes. + * + * @since 5.6.0 + */ + public static function init() + { + } + /** + * Registers a block support. + * + * @since 5.6.0 + * + * @link https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/ + * + * @param string $block_support_name Block support name. + * @param array $block_support_config Array containing the properties of the block support. + */ + public function register($block_support_name, $block_support_config) + { + } + /** + * Generates an array of HTML attributes, such as classes, by applying to + * the given block all of the features that the block supports. + * + * @since 5.6.0 + * + * @return string[] Array of HTML attributes. + */ + public function apply_block_supports() + { + } + } + /** + * Blocks API: WP_Block_Template class + * + * @package WordPress + * @since 5.8.0 + */ + /** + * Class representing a block template. + * + * @since 5.8.0 + */ + #[\AllowDynamicProperties] + class WP_Block_Template + { + /** + * Type: wp_template. + * + * @since 5.8.0 + * @var string + */ + public $type; + /** + * Theme. + * + * @since 5.8.0 + * @var string + */ + public $theme; + /** + * Template slug. + * + * @since 5.8.0 + * @var string + */ + public $slug; + /** + * ID. + * + * @since 5.8.0 + * @var string + */ + public $id; + /** + * Title. + * + * @since 5.8.0 + * @var string + */ + public $title = ''; + /** + * Content. + * + * @since 5.8.0 + * @var string + */ + public $content = ''; + /** + * Description. + * + * @since 5.8.0 + * @var string + */ + public $description = ''; + /** + * Source of the content. `theme` and `custom` is used for now. + * + * @since 5.8.0 + * @var string + */ + public $source = 'theme'; + /** + * Origin of the content when the content has been customized. + * When customized, origin takes on the value of source and source becomes + * 'custom'. + * + * @since 5.9.0 + * @var string + */ + public $origin; + /** + * Post ID. + * + * @since 5.8.0 + * @var int|null + */ + public $wp_id; + /** + * Template Status. + * + * @since 5.8.0 + * @var string + */ + public $status; + /** + * Whether a template is, or is based upon, an existing template file. + * + * @since 5.8.0 + * @var bool + */ + public $has_theme_file; + /** + * Whether a template is a custom template. + * + * @since 5.9.0 + * + * @var bool + */ + public $is_custom = \true; + /** + * Author. + * + * A value of 0 means no author. + * + * @since 5.9.0 + * @var int + */ + public $author; + /** + * Post types. + * + * @since 5.9.0 + * @var array + */ + public $post_types; + /** + * Area. + * + * @since 5.9.0 + * @var string + */ + public $area; + } + /** + * Blocks API: WP_Block_Type_Registry class + * + * @package WordPress + * @subpackage Blocks + * @since 5.0.0 + */ + /** + * Core class used for interacting with block types. + * + * @since 5.0.0 + */ + #[\AllowDynamicProperties] + final class WP_Block_Type_Registry + { + /** + * Registers a block type. + * + * @since 5.0.0 + * + * @see WP_Block_Type::__construct() + * + * @param string|WP_Block_Type $name Block type name including namespace, or alternatively + * a complete WP_Block_Type instance. In case a WP_Block_Type + * is provided, the $args parameter will be ignored. + * @param array $args Optional. Array of block type arguments. Accepts any public property + * of `WP_Block_Type`. See WP_Block_Type::__construct() for information + * on accepted arguments. Default empty array. + * @return WP_Block_Type|false The registered block type on success, or false on failure. + * @phpstan-param array{ + * api_version?: string, + * title?: string, + * category?: string|null, + * parent?: string[]|null, + * ancestor?: string[]|null, + * icon?: string|null, + * description?: string, + * keywords?: string[], + * textdomain?: string|null, + * styles?: array[], + * variations?: array[], + * supports?: array|null, + * example?: array|null, + * render_callback?: callable|null, + * attributes?: array|null, + * uses_context?: string[], + * provides_context?: string[]|null, + * editor_script_handles?: string[], + * script_handles?: string[], + * view_script_handles?: string[], + * editor_style_handles?: string[], + * style_handles?: string[], + * } $args See WP_Block_Type::__construct() + */ + public function register($name, $args = array()) + { + } + /** + * Unregisters a block type. + * + * @since 5.0.0 + * + * @param string|WP_Block_Type $name Block type name including namespace, or alternatively + * a complete WP_Block_Type instance. + * @return WP_Block_Type|false The unregistered block type on success, or false on failure. + */ + public function unregister($name) + { + } + /** + * Retrieves a registered block type. + * + * @since 5.0.0 + * + * @param string $name Block type name including namespace. + * @return WP_Block_Type|null The registered block type, or null if it is not registered. + */ + public function get_registered($name) + { + } + /** + * Retrieves all registered block types. + * + * @since 5.0.0 + * + * @return WP_Block_Type[] Associative array of `$block_type_name => $block_type` pairs. + */ + public function get_all_registered() + { + } + /** + * Checks if a block type is registered. + * + * @since 5.0.0 + * + * @param string $name Block type name including namespace. + * @return bool True if the block type is registered, false otherwise. + */ + public function is_registered($name) + { + } + /** + * Utility method to retrieve the main instance of the class. + * + * The instance will be created if it does not exist yet. + * + * @since 5.0.0 + * + * @return WP_Block_Type_Registry The main instance. + */ + public static function get_instance() + { + } + } + /** + * Blocks API: WP_Block_Type class + * + * @package WordPress + * @subpackage Blocks + * @since 5.0.0 + */ + /** + * Core class representing a block type. + * + * @since 5.0.0 + * + * @see register_block_type() + */ + #[\AllowDynamicProperties] + class WP_Block_Type + { + /** + * Block API version. + * + * @since 5.6.0 + * @var int + */ + public $api_version = 1; + /** + * Block type key. + * + * @since 5.0.0 + * @var string + */ + public $name; + /** + * Human-readable block type label. + * + * @since 5.5.0 + * @var string + */ + public $title = ''; + /** + * Block type category classification, used in search interfaces + * to arrange block types by category. + * + * @since 5.5.0 + * @var string|null + */ + public $category = \null; + /** + * Setting parent lets a block require that it is only available + * when nested within the specified blocks. + * + * @since 5.5.0 + * @var string[]|null + */ + public $parent = \null; + /** + * Setting ancestor makes a block available only inside the specified + * block types at any position of the ancestor's block subtree. + * + * @since 6.0.0 + * @var string[]|null + */ + public $ancestor = \null; + /** + * Block type icon. + * + * @since 5.5.0 + * @var string|null + */ + public $icon = \null; + /** + * A detailed block type description. + * + * @since 5.5.0 + * @var string + */ + public $description = ''; + /** + * Additional keywords to produce block type as result + * in search interfaces. + * + * @since 5.5.0 + * @var string[] + */ + public $keywords = array(); + /** + * The translation textdomain. + * + * @since 5.5.0 + * @var string|null + */ + public $textdomain = \null; + /** + * Alternative block styles. + * + * @since 5.5.0 + * @var array + */ + public $styles = array(); + /** + * Block variations. + * + * @since 5.8.0 + * @var array[] + */ + public $variations = array(); + /** + * Supported features. + * + * @since 5.5.0 + * @var array|null + */ + public $supports = \null; + /** + * Structured data for the block preview. + * + * @since 5.5.0 + * @var array|null + */ + public $example = \null; + /** + * Block type render callback. + * + * @since 5.0.0 + * @var callable + */ + public $render_callback = \null; + /** + * Block type attributes property schemas. + * + * @since 5.0.0 + * @var array|null + */ + public $attributes = \null; + /** + * Context values inherited by blocks of this type. + * + * @since 5.5.0 + * @var string[] + */ + public $uses_context = array(); + /** + * Context provided by blocks of this type. + * + * @since 5.5.0 + * @var string[]|null + */ + public $provides_context = \null; + /** + * Block type editor only script handles. + * + * @since 6.1.0 + * @var string[] + */ + public $editor_script_handles = array(); + /** + * Block type front end and editor script handles. + * + * @since 6.1.0 + * @var string[] + */ + public $script_handles = array(); + /** + * Block type front end only script handles. + * + * @since 6.1.0 + * @var string[] + */ + public $view_script_handles = array(); + /** + * Block type editor only style handles. + * + * @since 6.1.0 + * @var string[] + */ + public $editor_style_handles = array(); + /** + * Block type front end and editor style handles. + * + * @since 6.1.0 + * @var string[] + */ + public $style_handles = array(); + /** + * Attributes supported by every block. + * + * @since 6.0.0 + * @var array + */ + const GLOBAL_ATTRIBUTES = array('lock' => array('type' => 'object')); + /** + * Constructor. + * + * Will populate object properties from the provided arguments. + * + * @since 5.0.0 + * @since 5.5.0 Added the `title`, `category`, `parent`, `icon`, `description`, + * `keywords`, `textdomain`, `styles`, `supports`, `example`, + * `uses_context`, and `provides_context` properties. + * @since 5.6.0 Added the `api_version` property. + * @since 5.8.0 Added the `variations` property. + * @since 5.9.0 Added the `view_script` property. + * @since 6.0.0 Added the `ancestor` property. + * @since 6.1.0 Added the `editor_script_handles`, `script_handles`, `view_script_handles, + * `editor_style_handles`, and `style_handles` properties. + * Deprecated the `editor_script`, `script`, `view_script`, `editor_style`, and `style` properties. + * + * @see register_block_type() + * + * @param string $block_type Block type name including namespace. + * @param array|string $args { + * Optional. Array or string of arguments for registering a block type. Any arguments may be defined, + * however the ones described below are supported by default. Default empty array. + * + * @type string $api_version Block API version. + * @type string $title Human-readable block type label. + * @type string|null $category Block type category classification, used in + * search interfaces to arrange block types by category. + * @type string[]|null $parent Setting parent lets a block require that it is only + * available when nested within the specified blocks. + * @type string[]|null $ancestor Setting ancestor makes a block available only inside the specified + * block types at any position of the ancestor's block subtree. + * @type string|null $icon Block type icon. + * @type string $description A detailed block type description. + * @type string[] $keywords Additional keywords to produce block type as + * result in search interfaces. + * @type string|null $textdomain The translation textdomain. + * @type array[] $styles Alternative block styles. + * @type array[] $variations Block variations. + * @type array|null $supports Supported features. + * @type array|null $example Structured data for the block preview. + * @type callable|null $render_callback Block type render callback. + * @type array|null $attributes Block type attributes property schemas. + * @type string[] $uses_context Context values inherited by blocks of this type. + * @type string[]|null $provides_context Context provided by blocks of this type. + * @type string[] $editor_script_handles Block type editor only script handles. + * @type string[] $script_handles Block type front end and editor script handles. + * @type string[] $view_script_handles Block type front end only script handles. + * @type string[] $editor_style_handles Block type editor only style handles. + * @type string[] $style_handles Block type front end and editor style handles. + * } + * @phpstan-param array{ + * api_version?: string, + * title?: string, + * category?: string|null, + * parent?: string[]|null, + * ancestor?: string[]|null, + * icon?: string|null, + * description?: string, + * keywords?: string[], + * textdomain?: string|null, + * styles?: array[], + * variations?: array[], + * supports?: array|null, + * example?: array|null, + * render_callback?: callable|null, + * attributes?: array|null, + * uses_context?: string[], + * provides_context?: string[]|null, + * editor_script_handles?: string[], + * script_handles?: string[], + * view_script_handles?: string[], + * editor_style_handles?: string[], + * style_handles?: string[], + * } $args + */ + public function __construct($block_type, $args = array()) + { + } + /** + * Proxies getting values for deprecated properties for script and style handles for backward compatibility. + * Gets the value for the corresponding new property if the first item in the array provided. + * + * @since 6.1.0 + * + * @param string $name Deprecated property name. + * + * @return string|string[]|null|void The value read from the new property if the first item in the array provided, + * null when value not found, or void when unknown property name provided. + */ + public function __get($name) + { + } + /** + * Proxies checking for deprecated properties for script and style handles for backward compatibility. + * Checks whether the corresponding new property has the first item in the array provided. + * + * @since 6.1.0 + * + * @param string $name Deprecated property name. + * + * @return boolean Returns true when for the new property the first item in the array exists, + * or false otherwise. + */ + public function __isset($name) + { + } + /** + * Proxies setting values for deprecated properties for script and style handles for backward compatibility. + * Sets the value for the corresponding new property as the first item in the array. + * It also allows setting custom properties for backward compatibility. + * + * @since 6.1.0 + * + * @param string $name Property name. + * @param mixed $value Property value. + */ + public function __set($name, $value) + { + } + /** + * Renders the block type output for given attributes. + * + * @since 5.0.0 + * + * @param array $attributes Optional. Block attributes. Default empty array. + * @param string $content Optional. Block content. Default empty string. + * @return string Rendered block type output. + */ + public function render($attributes = array(), $content = '') + { + } + /** + * Returns true if the block type is dynamic, or false otherwise. A dynamic + * block is one which defers its rendering to occur on-demand at runtime. + * + * @since 5.0.0 + * + * @return bool Whether block type is dynamic. + */ + public function is_dynamic() + { + } + /** + * Validates attributes against the current block schema, populating + * defaulted and missing values. + * + * @since 5.0.0 + * + * @param array $attributes Original block attributes. + * @return array Prepared block attributes. + */ + public function prepare_attributes_for_render($attributes) + { + } + /** + * Sets block type properties. + * + * @since 5.0.0 + * + * @param array|string $args Array or string of arguments for registering a block type. + * See WP_Block_Type::__construct() for information on accepted arguments. + * @phpstan-param array{ + * api_version?: string, + * title?: string, + * category?: string|null, + * parent?: string[]|null, + * ancestor?: string[]|null, + * icon?: string|null, + * description?: string, + * keywords?: string[], + * textdomain?: string|null, + * styles?: array[], + * variations?: array[], + * supports?: array|null, + * example?: array|null, + * render_callback?: callable|null, + * attributes?: array|null, + * uses_context?: string[], + * provides_context?: string[]|null, + * editor_script_handles?: string[], + * script_handles?: string[], + * view_script_handles?: string[], + * editor_style_handles?: string[], + * style_handles?: string[], + * } $args See WP_Block_Type::__construct() + */ + public function set_props($args) + { + } + /** + * Get all available block attributes including possible layout attribute from Columns block. + * + * @since 5.0.0 + * + * @return array Array of attributes. + */ + public function get_attributes() + { + } + } + /** + * Blocks API: WP_Block class + * + * @package WordPress + * @since 5.5.0 + */ + /** + * Class representing a parsed instance of a block. + * + * @since 5.5.0 + * @property array $attributes + */ + #[\AllowDynamicProperties] + class WP_Block + { + /** + * Original parsed array representation of block. + * + * @since 5.5.0 + * @var array + */ + public $parsed_block; + /** + * Name of block. + * + * @example "core/paragraph" + * + * @since 5.5.0 + * @var string + */ + public $name; + /** + * Block type associated with the instance. + * + * @since 5.5.0 + * @var WP_Block_Type + */ + public $block_type; + /** + * Block context values. + * + * @since 5.5.0 + * @var array + */ + public $context = array(); + /** + * All available context of the current hierarchy. + * + * @since 5.5.0 + * @var array + * @access protected + */ + protected $available_context; + /** + * Block type registry. + * + * @since 5.9.0 + * @var WP_Block_Type_Registry + * @access protected + */ + protected $registry; + /** + * List of inner blocks (of this same class) + * + * @since 5.5.0 + * @var WP_Block_List + */ + public $inner_blocks = array(); + /** + * Resultant HTML from inside block comment delimiters after removing inner + * blocks. + * + * @example "...Just <!-- wp:test /--> testing..." -> "Just testing..." + * + * @since 5.5.0 + * @var string + */ + public $inner_html = ''; + /** + * List of string fragments and null markers where inner blocks were found + * + * @example array( + * 'inner_html' => 'BeforeInnerAfter', + * 'inner_blocks' => array( block, block ), + * 'inner_content' => array( 'Before', null, 'Inner', null, 'After' ), + * ) + * + * @since 5.5.0 + * @var array + */ + public $inner_content = array(); + /** + * Constructor. + * + * Populates object properties from the provided block instance argument. + * + * The given array of context values will not necessarily be available on + * the instance itself, but is treated as the full set of values provided by + * the block's ancestry. This is assigned to the private `available_context` + * property. Only values which are configured to consumed by the block via + * its registered type will be assigned to the block's `context` property. + * + * @since 5.5.0 + * + * @param array $block Array of parsed block properties. + * @param array $available_context Optional array of ancestry context values. + * @param WP_Block_Type_Registry $registry Optional block type registry. + */ + public function __construct($block, $available_context = array(), $registry = \null) + { + } + /** + * Returns a value from an inaccessible property. + * + * This is used to lazily initialize the `attributes` property of a block, + * such that it is only prepared with default attributes at the time that + * the property is accessed. For all other inaccessible properties, a `null` + * value is returned. + * + * @since 5.5.0 + * + * @param string $name Property name. + * @return array|null Prepared attributes, or null. + */ + public function __get($name) + { + } + /** + * Generates the render output for the block. + * + * @since 5.5.0 + * + * @param array $options { + * Optional options object. + * + * @type bool $dynamic Defaults to 'true'. Optionally set to false to avoid using the block's render_callback. + * } + * @return string Rendered block output. + * @phpstan-param array{ + * dynamic?: bool, + * } $options + */ + public function render($options = array()) + { + } + } + /** + * Comment API: WP_Comment_Query class + * + * @package WordPress + * @subpackage Comments + * @since 4.4.0 + */ + /** + * Core class used for querying comments. + * + * @since 3.1.0 + * + * @see WP_Comment_Query::__construct() for accepted arguments. + */ + #[\AllowDynamicProperties] + class WP_Comment_Query + { + /** + * SQL for database query. + * + * @since 4.0.1 + * @var string + */ + public $request; + /** + * Metadata query container + * + * @since 3.5.0 + * @var WP_Meta_Query A meta query instance. + */ + public $meta_query = \false; + /** + * Metadata query clauses. + * + * @since 4.4.0 + * @var array + */ + protected $meta_query_clauses; + /** + * SQL query clauses. + * + * @since 4.4.0 + * @var array + */ + protected $sql_clauses = array('select' => '', 'from' => '', 'where' => array(), 'groupby' => '', 'orderby' => '', 'limits' => ''); + /** + * SQL WHERE clause. + * + * Stored after the {@see 'comments_clauses'} filter is run on the compiled WHERE sub-clauses. + * + * @since 4.4.2 + * @var string + */ + protected $filtered_where_clause; + /** + * Date query container + * + * @since 3.7.0 + * @var WP_Date_Query A date query instance. + */ + public $date_query = \false; + /** + * Query vars set by the user. + * + * @since 3.1.0 + * @var array + */ + public $query_vars; + /** + * Default values for query vars. + * + * @since 4.2.0 + * @var array + */ + public $query_var_defaults; + /** + * List of comments located by the query. + * + * @since 4.0.0 + * @var int[]|WP_Comment[] + */ + public $comments; + /** + * The amount of found comments for the current query. + * + * @since 4.4.0 + * @var int + */ + public $found_comments = 0; + /** + * The number of pages. + * + * @since 4.4.0 + * @var int + */ + public $max_num_pages = 0; + /** + * Make private/protected methods readable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Method to call. + * @param array $arguments Arguments to pass when calling. + * @return mixed|false Return value of the callback, false otherwise. + */ + public function __call($name, $arguments) + { + } + /** + * Constructor. + * + * Sets up the comment query, based on the query vars passed. + * + * @since 4.2.0 + * @since 4.4.0 `$parent__in` and `$parent__not_in` were added. + * @since 4.4.0 Order by `comment__in` was added. `$update_comment_meta_cache`, `$no_found_rows`, + * `$hierarchical`, and `$update_comment_post_cache` were added. + * @since 4.5.0 Introduced the `$author_url` argument. + * @since 4.6.0 Introduced the `$cache_domain` argument. + * @since 4.9.0 Introduced the `$paged` argument. + * @since 5.1.0 Introduced the `$meta_compare_key` argument. + * @since 5.3.0 Introduced the `$meta_type_key` argument. + * + * @param string|array $query { + * Optional. Array or query string of comment query parameters. Default empty. + * + * @type string $author_email Comment author email address. Default empty. + * @type string $author_url Comment author URL. Default empty. + * @type int[] $author__in Array of author IDs to include comments for. Default empty. + * @type int[] $author__not_in Array of author IDs to exclude comments for. Default empty. + * @type int[] $comment__in Array of comment IDs to include. Default empty. + * @type int[] $comment__not_in Array of comment IDs to exclude. Default empty. + * @type bool $count Whether to return a comment count (true) or array of + * comment objects (false). Default false. + * @type array $date_query Date query clauses to limit comments by. See WP_Date_Query. + * Default null. + * @type string $fields Comment fields to return. Accepts 'ids' for comment IDs + * only or empty for all fields. Default empty. + * @type array $include_unapproved Array of IDs or email addresses of users whose unapproved + * comments will be returned by the query regardless of + * `$status`. Default empty. + * @type int $karma Karma score to retrieve matching comments for. + * Default empty. + * @type string|string[] $meta_key Meta key or keys to filter by. + * @type string|string[] $meta_value Meta value or values to filter by. + * @type string $meta_compare MySQL operator used for comparing the meta value. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_compare_key MySQL operator used for comparing the meta key. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_type MySQL data type that the meta_value column will be CAST to for comparisons. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_type_key MySQL data type that the meta_key column will be CAST to for comparisons. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type array $meta_query An associative array of WP_Meta_Query arguments. + * See WP_Meta_Query::__construct() for accepted values. + * @type int $number Maximum number of comments to retrieve. + * Default empty (no limit). + * @type int $paged When used with `$number`, defines the page of results to return. + * When used with `$offset`, `$offset` takes precedence. Default 1. + * @type int $offset Number of comments to offset the query. Used to build + * LIMIT clause. Default 0. + * @type bool $no_found_rows Whether to disable the `SQL_CALC_FOUND_ROWS` query. + * Default: true. + * @type string|array $orderby Comment status or array of statuses. To use 'meta_value' + * or 'meta_value_num', `$meta_key` must also be defined. + * To sort by a specific `$meta_query` clause, use that + * clause's array key. Accepts: + * - 'comment_agent' + * - 'comment_approved' + * - 'comment_author' + * - 'comment_author_email' + * - 'comment_author_IP' + * - 'comment_author_url' + * - 'comment_content' + * - 'comment_date' + * - 'comment_date_gmt' + * - 'comment_ID' + * - 'comment_karma' + * - 'comment_parent' + * - 'comment_post_ID' + * - 'comment_type' + * - 'user_id' + * - 'comment__in' + * - 'meta_value' + * - 'meta_value_num' + * - The value of `$meta_key` + * - The array keys of `$meta_query` + * - false, an empty array, or 'none' to disable `ORDER BY` clause. + * Default: 'comment_date_gmt'. + * @type string $order How to order retrieved comments. Accepts 'ASC', 'DESC'. + * Default: 'DESC'. + * @type int $parent Parent ID of comment to retrieve children of. + * Default empty. + * @type int[] $parent__in Array of parent IDs of comments to retrieve children for. + * Default empty. + * @type int[] $parent__not_in Array of parent IDs of comments *not* to retrieve + * children for. Default empty. + * @type int[] $post_author__in Array of author IDs to retrieve comments for. + * Default empty. + * @type int[] $post_author__not_in Array of author IDs *not* to retrieve comments for. + * Default empty. + * @type int $post_id Limit results to those affiliated with a given post ID. + * Default 0. + * @type int[] $post__in Array of post IDs to include affiliated comments for. + * Default empty. + * @type int[] $post__not_in Array of post IDs to exclude affiliated comments for. + * Default empty. + * @type int $post_author Post author ID to limit results by. Default empty. + * @type string|string[] $post_status Post status or array of post statuses to retrieve + * affiliated comments for. Pass 'any' to match any value. + * Default empty. + * @type string|string[] $post_type Post type or array of post types to retrieve affiliated + * comments for. Pass 'any' to match any value. Default empty. + * @type string $post_name Post name to retrieve affiliated comments for. + * Default empty. + * @type int $post_parent Post parent ID to retrieve affiliated comments for. + * Default empty. + * @type string $search Search term(s) to retrieve matching comments for. + * Default empty. + * @type string|array $status Comment statuses to limit results by. Accepts an array + * or space/comma-separated list of 'hold' (`comment_status=0`), + * 'approve' (`comment_status=1`), 'all', or a custom + * comment status. Default 'all'. + * @type string|string[] $type Include comments of a given type, or array of types. + * Accepts 'comment', 'pings' (includes 'pingback' and + * 'trackback'), or any custom type string. Default empty. + * @type string[] $type__in Include comments from a given array of comment types. + * Default empty. + * @type string[] $type__not_in Exclude comments from a given array of comment types. + * Default empty. + * @type int $user_id Include comments for a specific user ID. Default empty. + * @type bool|string $hierarchical Whether to include comment descendants in the results. + * - 'threaded' returns a tree, with each comment's children + * stored in a `children` property on the `WP_Comment` object. + * - 'flat' returns a flat array of found comments plus + * their children. + * - Boolean `false` leaves out descendants. + * The parameter is ignored (forced to `false`) when + * `$fields` is 'ids' or 'counts'. Accepts 'threaded', + * 'flat', or false. Default: false. + * @type string $cache_domain Unique cache key to be produced when this query is stored in + * an object cache. Default is 'core'. + * @type bool $update_comment_meta_cache Whether to prime the metadata cache for found comments. + * Default true. + * @type bool $update_comment_post_cache Whether to prime the cache for comment posts. + * Default false. + * } + * @phpstan-param array{ + * author_email?: string, + * author_url?: string, + * author__in?: int[], + * author__not_in?: int[], + * comment__in?: int[], + * comment__not_in?: int[], + * count?: bool, + * date_query?: array, + * fields?: string, + * include_unapproved?: array, + * karma?: int, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * number?: int, + * paged?: int, + * offset?: int, + * no_found_rows?: bool, + * orderby?: string|array, + * order?: string, + * parent?: int, + * parent__in?: int[], + * parent__not_in?: int[], + * post_author__in?: int[], + * post_author__not_in?: int[], + * post_id?: int, + * post__in?: int[], + * post__not_in?: int[], + * post_author?: int, + * post_status?: string|string[], + * post_type?: string|string[], + * post_name?: string, + * post_parent?: int, + * search?: string, + * status?: string|array, + * type?: string|string[], + * type__in?: string[], + * type__not_in?: string[], + * user_id?: int, + * hierarchical?: bool|string, + * cache_domain?: string, + * update_comment_meta_cache?: bool, + * update_comment_post_cache?: bool, + * } $query + */ + public function __construct($query = '') + { + } + /** + * Parse arguments passed to the comment query with default query parameters. + * + * @since 4.2.0 Extracted from WP_Comment_Query::query(). + * + * @param string|array $query WP_Comment_Query arguments. See WP_Comment_Query::__construct() + * @phpstan-param array{ + * author_email?: string, + * author_url?: string, + * author__in?: int[], + * author__not_in?: int[], + * comment__in?: int[], + * comment__not_in?: int[], + * count?: bool, + * date_query?: array, + * fields?: string, + * include_unapproved?: array, + * karma?: int, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * number?: int, + * paged?: int, + * offset?: int, + * no_found_rows?: bool, + * orderby?: string|array, + * order?: string, + * parent?: int, + * parent__in?: int[], + * parent__not_in?: int[], + * post_author__in?: int[], + * post_author__not_in?: int[], + * post_id?: int, + * post__in?: int[], + * post__not_in?: int[], + * post_author?: int, + * post_status?: string|string[], + * post_type?: string|string[], + * post_name?: string, + * post_parent?: int, + * search?: string, + * status?: string|array, + * type?: string|string[], + * type__in?: string[], + * type__not_in?: string[], + * user_id?: int, + * hierarchical?: bool|string, + * cache_domain?: string, + * update_comment_meta_cache?: bool, + * update_comment_post_cache?: bool, + * } $query See WP_Comment_Query::__construct() + */ + public function parse_query($query = '') + { + } + /** + * Sets up the WordPress query for retrieving comments. + * + * @since 3.1.0 + * @since 4.1.0 Introduced 'comment__in', 'comment__not_in', 'post_author__in', + * 'post_author__not_in', 'author__in', 'author__not_in', 'post__in', + * 'post__not_in', 'include_unapproved', 'type__in', and 'type__not_in' + * arguments to $query_vars. + * @since 4.2.0 Moved parsing to WP_Comment_Query::parse_query(). + * + * @param string|array $query Array or URL query string of parameters. + * @return array|int List of comments, or number of comments when 'count' is passed as a query var. + */ + public function query($query) + { + } + /** + * Get a list of comments matching the query vars. + * + * @since 4.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return int|int[]|WP_Comment[] List of comments or number of found comments if `$count` argument is true. + */ + public function get_comments() + { + } + /** + * Used internally to get a list of comment IDs matching the query vars. + * + * @since 4.4.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return int|array A single count of comment IDs if a count query. An array of comment IDs if a full query. + */ + protected function get_comment_ids() + { + } + /** + * Fetch descendants for located comments. + * + * Instead of calling `get_children()` separately on each child comment, we do a single set of queries to fetch + * the descendant trees for all matched top-level comments. + * + * @since 4.4.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param WP_Comment[] $comments Array of top-level comments whose descendants should be filled in. + * @return array + */ + protected function fill_descendants($comments) + { + } + /** + * Used internally to generate an SQL string for searching across multiple columns. + * + * @since 3.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $search Search string. + * @param string[] $columns Array of columns to search. + * @return string Search SQL. + */ + protected function get_search_sql($search, $columns) + { + } + /** + * Parse and sanitize 'orderby' keys passed to the comment query. + * + * @since 4.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $orderby Alias for the field to order by. + * @return string|false Value to used in the ORDER clause. False otherwise. + */ + protected function parse_orderby($orderby) + { + } + /** + * Parse an 'order' query variable and cast it to ASC or DESC as necessary. + * + * @since 4.2.0 + * + * @param string $order The 'order' query variable. + * @return string The sanitized 'order' query variable. + */ + protected function parse_order($order) + { + } + } + /** + * Comment API: WP_Comment class + * + * @package WordPress + * @subpackage Comments + * @since 4.4.0 + */ + /** + * Core class used to organize comments as instantiated objects with defined members. + * + * @since 4.4.0 + */ + #[\AllowDynamicProperties] + final class WP_Comment + { + /** + * Comment ID. + * + * A numeric string, for compatibility reasons. + * + * @since 4.4.0 + * @var string + */ + public $comment_ID; + /** + * ID of the post the comment is associated with. + * + * A numeric string, for compatibility reasons. + * + * @since 4.4.0 + * @var string + */ + public $comment_post_ID = 0; + /** + * Comment author name. + * + * @since 4.4.0 + * @var string + */ + public $comment_author = ''; + /** + * Comment author email address. + * + * @since 4.4.0 + * @var string + */ + public $comment_author_email = ''; + /** + * Comment author URL. + * + * @since 4.4.0 + * @var string + */ + public $comment_author_url = ''; + /** + * Comment author IP address (IPv4 format). + * + * @since 4.4.0 + * @var string + */ + public $comment_author_IP = ''; + /** + * Comment date in YYYY-MM-DD HH:MM:SS format. + * + * @since 4.4.0 + * @var string + */ + public $comment_date = '0000-00-00 00:00:00'; + /** + * Comment GMT date in YYYY-MM-DD HH::MM:SS format. + * + * @since 4.4.0 + * @var string + */ + public $comment_date_gmt = '0000-00-00 00:00:00'; + /** + * Comment content. + * + * @since 4.4.0 + * @var string + */ + public $comment_content; + /** + * Comment karma count. + * + * A numeric string, for compatibility reasons. + * + * @since 4.4.0 + * @var string + */ + public $comment_karma = 0; + /** + * Comment approval status. + * + * @since 4.4.0 + * @var string + */ + public $comment_approved = '1'; + /** + * Comment author HTTP user agent. + * + * @since 4.4.0 + * @var string + */ + public $comment_agent = ''; + /** + * Comment type. + * + * @since 4.4.0 + * @since 5.5.0 Default value changed to `comment`. + * @var string + */ + public $comment_type = 'comment'; + /** + * Parent comment ID. + * + * A numeric string, for compatibility reasons. + * + * @since 4.4.0 + * @var string + */ + public $comment_parent = 0; + /** + * Comment author ID. + * + * A numeric string, for compatibility reasons. + * + * @since 4.4.0 + * @var string + */ + public $user_id = 0; + /** + * Retrieves a WP_Comment instance. + * + * @since 4.4.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $id Comment ID. + * @return WP_Comment|false Comment object, otherwise false. + */ + public static function get_instance($id) + { + } + /** + * Constructor. + * + * Populates properties with object vars. + * + * @since 4.4.0 + * + * @param WP_Comment $comment Comment object. + */ + public function __construct($comment) + { + } + /** + * Convert object to array. + * + * @since 4.4.0 + * + * @return array Object as array. + */ + public function to_array() + { + } + /** + * Get the children of a comment. + * + * @since 4.4.0 + * + * @param array $args { + * Array of arguments used to pass to get_comments() and determine format. + * + * @type string $format Return value format. 'tree' for a hierarchical tree, 'flat' for a flattened array. + * Default 'tree'. + * @type string $status Comment status to limit results by. Accepts 'hold' (`comment_status=0`), + * 'approve' (`comment_status=1`), 'all', or a custom comment status. + * Default 'all'. + * @type string $hierarchical Whether to include comment descendants in the results. + * 'threaded' returns a tree, with each comment's children + * stored in a `children` property on the `WP_Comment` object. + * 'flat' returns a flat array of found comments plus their children. + * Pass `false` to leave out descendants. + * The parameter is ignored (forced to `false`) when `$fields` is 'ids' or 'counts'. + * Accepts 'threaded', 'flat', or false. Default: 'threaded'. + * @type string|array $orderby Comment status or array of statuses. To use 'meta_value' + * or 'meta_value_num', `$meta_key` must also be defined. + * To sort by a specific `$meta_query` clause, use that + * clause's array key. Accepts 'comment_agent', + * 'comment_approved', 'comment_author', + * 'comment_author_email', 'comment_author_IP', + * 'comment_author_url', 'comment_content', 'comment_date', + * 'comment_date_gmt', 'comment_ID', 'comment_karma', + * 'comment_parent', 'comment_post_ID', 'comment_type', + * 'user_id', 'comment__in', 'meta_value', 'meta_value_num', + * the value of $meta_key, and the array keys of + * `$meta_query`. Also accepts false, an empty array, or + * 'none' to disable `ORDER BY` clause. + * } + * @return WP_Comment[] Array of `WP_Comment` objects. + * @phpstan-param array{ + * format?: string, + * status?: string, + * hierarchical?: string, + * orderby?: string|array, + * } $args + */ + public function get_children($args = array()) + { + } + /** + * Add a child to the comment. + * + * Used by `WP_Comment_Query` when bulk-filling descendants. + * + * @since 4.4.0 + * + * @param WP_Comment $child Child comment. + */ + public function add_child(\WP_Comment $child) + { + } + /** + * Get a child comment by ID. + * + * @since 4.4.0 + * + * @param int $child_id ID of the child. + * @return WP_Comment|false Returns the comment object if found, otherwise false. + */ + public function get_child($child_id) + { + } + /** + * Set the 'populated_children' flag. + * + * This flag is important for ensuring that calling `get_children()` on a childless comment will not trigger + * unneeded database queries. + * + * @since 4.4.0 + * + * @param bool $set Whether the comment's children have already been populated. + */ + public function populated_children($set) + { + } + /** + * Check whether a non-public property is set. + * + * If `$name` matches a post field, the comment post will be loaded and the post's value checked. + * + * @since 4.4.0 + * + * @param string $name Property name. + * @return bool + */ + public function __isset($name) + { + } + /** + * Magic getter. + * + * If `$name` matches a post field, the comment post will be loaded and the post's value returned. + * + * @since 4.4.0 + * + * @param string $name + * @return mixed + */ + public function __get($name) + { + } + } + /** + * WordPress Customize Control classes + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ + /** + * Customize Control class. + * + * @since 3.4.0 + */ + #[\AllowDynamicProperties] + class WP_Customize_Control + { + /** + * Incremented with each new class instantiation, then stored in $instance_number. + * + * Used when sorting two instances whose priorities are equal. + * + * @since 4.1.0 + * @var int + */ + protected static $instance_count = 0; + /** + * Order in which this instance was created in relation to other instances. + * + * @since 4.1.0 + * @var int + */ + public $instance_number; + /** + * Customizer manager. + * + * @since 3.4.0 + * @var WP_Customize_Manager + */ + public $manager; + /** + * Control ID. + * + * @since 3.4.0 + * @var string + */ + public $id; + /** + * All settings tied to the control. + * + * @since 3.4.0 + * @var array + */ + public $settings; + /** + * The primary setting for the control (if there is one). + * + * @since 3.4.0 + * @var string|WP_Customize_Setting|null + */ + public $setting = 'default'; + /** + * Capability required to use this control. + * + * Normally this is empty and the capability is derived from the capabilities + * of the associated `$settings`. + * + * @since 4.5.0 + * @var string + */ + public $capability; + /** + * Order priority to load the control in Customizer. + * + * @since 3.4.0 + * @var int + */ + public $priority = 10; + /** + * Section the control belongs to. + * + * @since 3.4.0 + * @var string + */ + public $section = ''; + /** + * Label for the control. + * + * @since 3.4.0 + * @var string + */ + public $label = ''; + /** + * Description for the control. + * + * @since 4.0.0 + * @var string + */ + public $description = ''; + /** + * List of choices for 'radio' or 'select' type controls, where values are the keys, and labels are the values. + * + * @since 3.4.0 + * @var array + */ + public $choices = array(); + /** + * List of custom input attributes for control output, where attribute names are the keys and values are the values. + * + * Not used for 'checkbox', 'radio', 'select', 'textarea', or 'dropdown-pages' control types. + * + * @since 4.0.0 + * @var array + */ + public $input_attrs = array(); + /** + * Show UI for adding new content, currently only used for the dropdown-pages control. + * + * @since 4.7.0 + * @var bool + */ + public $allow_addition = \false; + /** + * @deprecated It is better to just call the json() method + * @since 3.4.0 + * @var array + */ + public $json = array(); + /** + * Control's Type. + * + * @since 3.4.0 + * @var string + */ + public $type = 'text'; + /** + * Callback. + * + * @since 4.0.0 + * + * @see WP_Customize_Control::active() + * + * @var callable Callback is called with one argument, the instance of + * WP_Customize_Control, and returns bool to indicate whether + * the control is active (such as it relates to the URL + * currently being previewed). + */ + public $active_callback = ''; + /** + * Constructor. + * + * Supplied `$args` override class property defaults. + * + * If `$args['settings']` is not defined, use the `$id` as the setting ID. + * + * @since 3.4.0 + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + * @param string $id Control ID. + * @param array $args { + * Optional. Array of properties for the new Control object. Default empty array. + * + * @type int $instance_number Order in which this instance was created in relation + * to other instances. + * @type WP_Customize_Manager $manager Customizer bootstrap instance. + * @type string $id Control ID. + * @type array $settings All settings tied to the control. If undefined, `$id` will + * be used. + * @type string $setting The primary setting for the control (if there is one). + * Default 'default'. + * @type string $capability Capability required to use this control. Normally this is empty + * and the capability is derived from `$settings`. + * @type int $priority Order priority to load the control. Default 10. + * @type string $section Section the control belongs to. Default empty. + * @type string $label Label for the control. Default empty. + * @type string $description Description for the control. Default empty. + * @type array $choices List of choices for 'radio' or 'select' type controls, where + * values are the keys, and labels are the values. + * Default empty array. + * @type array $input_attrs List of custom input attributes for control output, where + * attribute names are the keys and values are the values. Not + * used for 'checkbox', 'radio', 'select', 'textarea', or + * 'dropdown-pages' control types. Default empty array. + * @type bool $allow_addition Show UI for adding new content, currently only used for the + * dropdown-pages control. Default false. + * @type array $json Deprecated. Use WP_Customize_Control::json() instead. + * @type string $type Control type. Core controls include 'text', 'checkbox', + * 'textarea', 'radio', 'select', and 'dropdown-pages'. Additional + * input types such as 'email', 'url', 'number', 'hidden', and + * 'date' are supported implicitly. Default 'text'. + * @type callable $active_callback Active callback. + * } + * @phpstan-param array{ + * instance_number?: int, + * manager?: WP_Customize_Manager, + * id?: string, + * settings?: array, + * setting?: string, + * capability?: string, + * priority?: int, + * section?: string, + * label?: string, + * description?: string, + * choices?: array, + * input_attrs?: array, + * allow_addition?: bool, + * json?: array, + * type?: string, + * active_callback?: callable, + * } $args + */ + public function __construct($manager, $id, $args = array()) + { + } + /** + * Enqueue control related scripts/styles. + * + * @since 3.4.0 + */ + public function enqueue() + { + } + /** + * Check whether control is active to current Customizer preview. + * + * @since 4.0.0 + * + * @return bool Whether the control is active to the current preview. + */ + public final function active() + { + } + /** + * Default callback used when invoking WP_Customize_Control::active(). + * + * Subclasses can override this with their specific logic, or they may + * provide an 'active_callback' argument to the constructor. + * + * @since 4.0.0 + * + * @return true Always true. + */ + public function active_callback() + { + } + /** + * Fetch a setting's value. + * Grabs the main setting by default. + * + * @since 3.4.0 + * + * @param string $setting_key + * @return mixed The requested setting's value, if the setting exists. + */ + public final function value($setting_key = 'default') + { + } + /** + * Refresh the parameters passed to the JavaScript via JSON. + * + * @since 3.4.0 + */ + public function to_json() + { + } + /** + * Get the data to export to the client via JSON. + * + * @since 4.1.0 + * + * @return array Array of parameters passed to the JavaScript. + */ + public function json() + { + } + /** + * Checks if the user can use this control. + * + * Returns false if the user cannot manipulate one of the associated settings, + * or if one of the associated settings does not exist. Also returns false if + * the associated section does not exist or if its capability check returns + * false. + * + * @since 3.4.0 + * + * @return bool False if theme doesn't support the control or user doesn't have the required permissions, otherwise true. + */ + public final function check_capabilities() + { + } + /** + * Get the control's content for insertion into the Customizer pane. + * + * @since 4.1.0 + * + * @return string Contents of the control. + */ + public final function get_content() + { + } + /** + * Check capabilities and render the control. + * + * @since 3.4.0 + * @uses WP_Customize_Control::render() + */ + public final function maybe_render() + { + } + /** + * Renders the control wrapper and calls $this->render_content() for the internals. + * + * @since 3.4.0 + */ + protected function render() + { + } + /** + * Get the data link attribute for a setting. + * + * @since 3.4.0 + * @since 4.9.0 Return a `data-customize-setting-key-link` attribute if a setting is not registered for the supplied setting key. + * + * @param string $setting_key + * @return string Data link parameter, a `data-customize-setting-link` attribute if the `$setting_key` refers to a pre-registered setting, + * and a `data-customize-setting-key-link` attribute if the setting is not yet registered. + */ + public function get_link($setting_key = 'default') + { + } + /** + * Render the data link attribute for the control's input element. + * + * @since 3.4.0 + * @uses WP_Customize_Control::get_link() + * + * @param string $setting_key + */ + public function link($setting_key = 'default') + { + } + /** + * Render the custom attributes for the control's input element. + * + * @since 4.0.0 + */ + public function input_attrs() + { + } + /** + * Render the control's content. + * + * Allows the content to be overridden without having to rewrite the wrapper in `$this::render()`. + * + * Supports basic input types `text`, `checkbox`, `textarea`, `radio`, `select` and `dropdown-pages`. + * Additional input types such as `email`, `url`, `number`, `hidden` and `date` are supported implicitly. + * + * Control content can alternately be rendered in JS. See WP_Customize_Control::print_template(). + * + * @since 3.4.0 + */ + protected function render_content() + { + } + /** + * Render the control's JS template. + * + * This function is only run for control types that have been registered with + * WP_Customize_Manager::register_control_type(). + * + * In the future, this will also print the template for the control's container + * element and be override-able. + * + * @since 4.1.0 + */ + public final function print_template() + { + } + /** + * An Underscore (JS) template for this control's content (but not its container). + * + * Class variables for this control class are available in the `data` JS object; + * export custom variables by overriding WP_Customize_Control::to_json(). + * + * @see WP_Customize_Control::print_template() + * + * @since 4.1.0 + */ + protected function content_template() + { + } + } + /** + * WordPress Customize Manager classes + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ + /** + * Customize Manager class. + * + * Bootstraps the Customize experience on the server-side. + * + * Sets up the theme-switching process if a theme other than the active one is + * being previewed and customized. + * + * Serves as a factory for Customize Controls and Settings, and + * instantiates default Customize Controls and Settings. + * + * @since 3.4.0 + */ + #[\AllowDynamicProperties] + final class WP_Customize_Manager + { + /** + * Methods and properties dealing with managing widgets in the Customizer. + * + * @since 3.9.0 + * @var WP_Customize_Widgets + */ + public $widgets; + /** + * Methods and properties dealing with managing nav menus in the Customizer. + * + * @since 4.3.0 + * @var WP_Customize_Nav_Menus + */ + public $nav_menus; + /** + * Methods and properties dealing with selective refresh in the Customizer preview. + * + * @since 4.5.0 + * @var WP_Customize_Selective_Refresh + */ + public $selective_refresh; + /** + * Constructor. + * + * @since 3.4.0 + * @since 4.7.0 Added `$args` parameter. + * + * @param array $args { + * Args. + * + * @type null|string|false $changeset_uuid Changeset UUID, the `post_name` for the customize_changeset post containing the customized state. + * Defaults to `null` resulting in a UUID to be immediately generated. If `false` is provided, then + * then the changeset UUID will be determined during `after_setup_theme`: when the + * `customize_changeset_branching` filter returns false, then the default UUID will be that + * of the most recent `customize_changeset` post that has a status other than 'auto-draft', + * 'publish', or 'trash'. Otherwise, if changeset branching is enabled, then a random UUID will be used. + * @type string $theme Theme to be previewed (for theme switch). Defaults to customize_theme or theme query params. + * @type string $messenger_channel Messenger channel. Defaults to customize_messenger_channel query param. + * @type bool $settings_previewed If settings should be previewed. Defaults to true. + * @type bool $branching If changeset branching is allowed; otherwise, changesets are linear. Defaults to true. + * @type bool $autosaved If data from a changeset's autosaved revision should be loaded if it exists. Defaults to false. + * } + * @phpstan-param array{ + * changeset_uuid?: null|string|false, + * theme?: string, + * messenger_channel?: string, + * settings_previewed?: bool, + * branching?: bool, + * autosaved?: bool, + * } $args + */ + public function __construct($args = array()) + { + } + /** + * Returns true if it's an Ajax request. + * + * @since 3.4.0 + * @since 4.2.0 Added `$action` param. + * + * @param string|null $action Whether the supplied Ajax action is being run. + * @return bool True if it's an Ajax request, false otherwise. + */ + public function doing_ajax($action = \null) + { + } + /** + * Returns the Ajax wp_die() handler if it's a customized request. + * + * @since 3.4.0 + * @deprecated 4.7.0 + * + * @return callable Die handler. + */ + public function wp_die_handler() + { + } + /** + * Starts preview and customize theme. + * + * Check if customize query variable exist. Init filters to filter the active theme. + * + * @since 3.4.0 + * + * @global string $pagenow The filename of the current screen. + */ + public function setup_theme() + { + } + /** + * Establishes the loaded changeset. + * + * This method runs right at after_setup_theme and applies the 'customize_changeset_branching' filter to determine + * whether concurrent changesets are allowed. Then if the Customizer is not initialized with a `changeset_uuid` param, + * this method will determine which UUID should be used. If changeset branching is disabled, then the most saved + * changeset will be loaded by default. Otherwise, if there are no existing saved changesets or if changeset branching is + * enabled, then a new UUID will be generated. + * + * @since 4.9.0 + * + * @global string $pagenow The filename of the current screen. + */ + public function establish_loaded_changeset() + { + } + /** + * Callback to validate a theme once it is loaded + * + * @since 3.4.0 + */ + public function after_setup_theme() + { + } + /** + * If the theme to be previewed isn't the active theme, add filter callbacks + * to swap it out at runtime. + * + * @since 3.4.0 + */ + public function start_previewing_theme() + { + } + /** + * Stops previewing the selected theme. + * + * Removes filters to change the active theme. + * + * @since 3.4.0 + */ + public function stop_previewing_theme() + { + } + /** + * Gets whether settings are or will be previewed. + * + * @since 4.9.0 + * + * @see WP_Customize_Setting::preview() + * + * @return bool + */ + public function settings_previewed() + { + } + /** + * Gets whether data from a changeset's autosaved revision should be loaded if it exists. + * + * @since 4.9.0 + * + * @see WP_Customize_Manager::changeset_data() + * + * @return bool Is using autosaved changeset revision. + */ + public function autosaved() + { + } + /** + * Whether the changeset branching is allowed. + * + * @since 4.9.0 + * + * @see WP_Customize_Manager::establish_loaded_changeset() + * + * @return bool Is changeset branching. + */ + public function branching() + { + } + /** + * Gets the changeset UUID. + * + * @since 4.7.0 + * + * @see WP_Customize_Manager::establish_loaded_changeset() + * + * @return string UUID. + */ + public function changeset_uuid() + { + } + /** + * Gets the theme being customized. + * + * @since 3.4.0 + * + * @return WP_Theme + */ + public function theme() + { + } + /** + * Gets the registered settings. + * + * @since 3.4.0 + * + * @return array + */ + public function settings() + { + } + /** + * Gets the registered controls. + * + * @since 3.4.0 + * + * @return array + */ + public function controls() + { + } + /** + * Gets the registered containers. + * + * @since 4.0.0 + * + * @return array + */ + public function containers() + { + } + /** + * Gets the registered sections. + * + * @since 3.4.0 + * + * @return array + */ + public function sections() + { + } + /** + * Gets the registered panels. + * + * @since 4.0.0 + * + * @return array Panels. + */ + public function panels() + { + } + /** + * Checks if the current theme is active. + * + * @since 3.4.0 + * + * @return bool + */ + public function is_theme_active() + { + } + /** + * Registers styles/scripts and initialize the preview of each setting + * + * @since 3.4.0 + */ + public function wp_loaded() + { + } + /** + * Prevents Ajax requests from following redirects when previewing a theme + * by issuing a 200 response instead of a 30x. + * + * Instead, the JS will sniff out the location header. + * + * @since 3.4.0 + * @deprecated 4.7.0 + * + * @param int $status Status. + * @return int + */ + public function wp_redirect_status($status) + { + } + /** + * Finds the changeset post ID for a given changeset UUID. + * + * @since 4.7.0 + * + * @param string $uuid Changeset UUID. + * @return int|null Returns post ID on success and null on failure. + */ + public function find_changeset_post_id($uuid) + { + } + /** + * Gets the changeset post ID for the loaded changeset. + * + * @since 4.7.0 + * + * @return int|null Post ID on success or null if there is no post yet saved. + */ + public function changeset_post_id() + { + } + /** + * Gets changeset data. + * + * @since 4.7.0 + * @since 4.9.0 This will return the changeset's data with a user's autosave revision merged on top, if one exists and $autosaved is true. + * + * @return array Changeset data. + */ + public function changeset_data() + { + } + /** + * Imports theme starter content into the customized state. + * + * @since 4.7.0 + * + * @param array $starter_content Starter content. Defaults to `get_theme_starter_content()`. + */ + public function import_theme_starter_content($starter_content = array()) + { + } + /** + * Saves starter content changeset. + * + * @since 4.7.0 + */ + public function _save_starter_content_changeset() + { + } + /** + * Gets dirty pre-sanitized setting values in the current customized state. + * + * The returned array consists of a merge of three sources: + * 1. If the theme is not currently active, then the base array is any stashed + * theme mods that were modified previously but never published. + * 2. The values from the current changeset, if it exists. + * 3. If the user can customize, the values parsed from the incoming + * `$_POST['customized']` JSON data. + * 4. Any programmatically-set post values via `WP_Customize_Manager::set_post_value()`. + * + * The name "unsanitized_post_values" is a carry-over from when the customized + * state was exclusively sourced from `$_POST['customized']`. Nevertheless, + * the value returned will come from the current changeset post and from the + * incoming post data. + * + * @since 4.1.1 + * @since 4.7.0 Added `$args` parameter and merging with changeset values and stashed theme mods. + * + * @param array $args { + * Args. + * + * @type bool $exclude_changeset Whether the changeset values should also be excluded. Defaults to false. + * @type bool $exclude_post_data Whether the post input values should also be excluded. Defaults to false when lacking the customize capability. + * } + * @return array + * @phpstan-param array{ + * exclude_changeset?: bool, + * exclude_post_data?: bool, + * } $args + */ + public function unsanitized_post_values($args = array()) + { + } + /** + * Returns the sanitized value for a given setting from the current customized state. + * + * The name "post_value" is a carry-over from when the customized state was exclusively + * sourced from `$_POST['customized']`. Nevertheless, the value returned will come + * from the current changeset post and from the incoming post data. + * + * @since 3.4.0 + * @since 4.1.1 Introduced the `$default_value` parameter. + * @since 4.6.0 `$default_value` is now returned early when the setting post value is invalid. + * + * @see WP_REST_Server::dispatch() + * @see WP_REST_Request::sanitize_params() + * @see WP_REST_Request::has_valid_params() + * + * @param WP_Customize_Setting $setting A WP_Customize_Setting derived object. + * @param mixed $default_value Value returned if `$setting` has no post value (added in 4.2.0) + * or the post value is invalid (added in 4.6.0). + * @return string|mixed Sanitized value or the `$default_value` provided. + */ + public function post_value($setting, $default_value = \null) + { + } + /** + * Overrides a setting's value in the current customized state. + * + * The name "post_value" is a carry-over from when the customized state was + * exclusively sourced from `$_POST['customized']`. + * + * @since 4.2.0 + * + * @param string $setting_id ID for the WP_Customize_Setting instance. + * @param mixed $value Post value. + */ + public function set_post_value($setting_id, $value) + { + } + /** + * Prints JavaScript settings. + * + * @since 3.4.0 + */ + public function customize_preview_init() + { + } + /** + * Filters the X-Frame-Options and Content-Security-Policy headers to ensure frontend can load in customizer. + * + * @since 4.7.0 + * + * @param array $headers Headers. + * @return array Headers. + */ + public function filter_iframe_security_headers($headers) + { + } + /** + * Adds customize state query params to a given URL if preview is allowed. + * + * @since 4.7.0 + * + * @see wp_redirect() + * @see WP_Customize_Manager::get_allowed_url() + * + * @param string $url URL. + * @return string URL. + */ + public function add_state_query_params($url) + { + } + /** + * Prevents sending a 404 status when returning the response for the customize + * preview, since it causes the jQuery Ajax to fail. Send 200 instead. + * + * @since 4.0.0 + * @deprecated 4.7.0 + */ + public function customize_preview_override_404_status() + { + } + /** + * Prints base element for preview frame. + * + * @since 3.4.0 + * @deprecated 4.7.0 + */ + public function customize_preview_base() + { + } + /** + * Prints a workaround to handle HTML5 tags in IE < 9. + * + * @since 3.4.0 + * @deprecated 4.7.0 Customizer no longer supports IE8, so all supported browsers recognize HTML5. + */ + public function customize_preview_html5() + { + } + /** + * Prints CSS for loading indicators for the Customizer preview. + * + * @since 4.2.0 + */ + public function customize_preview_loading_style() + { + } + /** + * Removes customize_messenger_channel query parameter from the preview window when it is not in an iframe. + * + * This ensures that the admin bar will be shown. It also ensures that link navigation will + * work as expected since the parent frame is not being sent the URL to navigate to. + * + * @since 4.7.0 + */ + public function remove_frameless_preview_messenger_channel() + { + } + /** + * Prints JavaScript settings for preview frame. + * + * @since 3.4.0 + */ + public function customize_preview_settings() + { + } + /** + * Prints a signature so we can ensure the Customizer was properly executed. + * + * @since 3.4.0 + * @deprecated 4.7.0 + */ + public function customize_preview_signature() + { + } + /** + * Removes the signature in case we experience a case where the Customizer was not properly executed. + * + * @since 3.4.0 + * @deprecated 4.7.0 + * + * @param callable|null $callback Optional. Value passed through for {@see 'wp_die_handler'} filter. + * Default null. + * @return callable|null Value passed through for {@see 'wp_die_handler'} filter. + */ + public function remove_preview_signature($callback = \null) + { + } + /** + * Determines whether it is a theme preview or not. + * + * @since 3.4.0 + * + * @return bool True if it's a preview, false if not. + */ + public function is_preview() + { + } + /** + * Retrieves the template name of the previewed theme. + * + * @since 3.4.0 + * + * @return string Template name. + */ + public function get_template() + { + } + /** + * Retrieves the stylesheet name of the previewed theme. + * + * @since 3.4.0 + * + * @return string Stylesheet name. + */ + public function get_stylesheet() + { + } + /** + * Retrieves the template root of the previewed theme. + * + * @since 3.4.0 + * + * @return string Theme root. + */ + public function get_template_root() + { + } + /** + * Retrieves the stylesheet root of the previewed theme. + * + * @since 3.4.0 + * + * @return string Theme root. + */ + public function get_stylesheet_root() + { + } + /** + * Filters the active theme and return the name of the previewed theme. + * + * @since 3.4.0 + * + * @param mixed $current_theme {@internal Parameter is not used} + * @return string Theme name. + */ + public function current_theme($current_theme) + { + } + /** + * Validates setting values. + * + * Validation is skipped for unregistered settings or for values that are + * already null since they will be skipped anyway. Sanitization is applied + * to values that pass validation, and values that become null or `WP_Error` + * after sanitizing are marked invalid. + * + * @since 4.6.0 + * + * @see WP_REST_Request::has_valid_params() + * @see WP_Customize_Setting::validate() + * + * @param array $setting_values Mapping of setting IDs to values to validate and sanitize. + * @param array $options { + * Options. + * + * @type bool $validate_existence Whether a setting's existence will be checked. + * @type bool $validate_capability Whether the setting capability will be checked. + * } + * @return array Mapping of setting IDs to return value of validate method calls, either `true` or `WP_Error`. + * @phpstan-param array{ + * validate_existence?: bool, + * validate_capability?: bool, + * } $options + */ + public function validate_setting_values($setting_values, $options = array()) + { + } + /** + * Prepares setting validity for exporting to the client (JS). + * + * Converts `WP_Error` instance into array suitable for passing into the + * `wp.customize.Notification` JS model. + * + * @since 4.6.0 + * + * @param true|WP_Error $validity Setting validity. + * @return true|array If `$validity` was a WP_Error, the error codes will be array-mapped + * to their respective `message` and `data` to pass into the + * `wp.customize.Notification` JS model. + */ + public function prepare_setting_validity_for_js($validity) + { + } + /** + * Handles customize_save WP Ajax request to save/update a changeset. + * + * @since 3.4.0 + * @since 4.7.0 The semantics of this method have changed to update a changeset, optionally to also change the status and other attributes. + */ + public function save() + { + } + /** + * Saves the post for the loaded changeset. + * + * @since 4.7.0 + * + * @param array $args { + * Args for changeset post. + * + * @type array $data Optional additional changeset data. Values will be merged on top of any existing post values. + * @type string $status Post status. Optional. If supplied, the save will be transactional and a post revision will be allowed. + * @type string $title Post title. Optional. + * @type string $date_gmt Date in GMT. Optional. + * @type int $user_id ID for user who is saving the changeset. Optional, defaults to the current user ID. + * @type bool $starter_content Whether the data is starter content. If false (default), then $starter_content will be cleared for any $data being saved. + * @type bool $autosave Whether this is a request to create an autosave revision. + * } + * + * @return array|WP_Error Returns array on success and WP_Error with array data on error. + * @phpstan-param array{ + * data?: array, + * status?: string, + * title?: string, + * date_gmt?: string, + * user_id?: int, + * starter_content?: bool, + * autosave?: bool, + * } $args + */ + public function save_changeset_post($args = array()) + { + } + /** + * Preserves the initial JSON post_content passed to save into the post. + * + * This is needed to prevent KSES and other {@see 'content_save_pre'} filters + * from corrupting JSON data. + * + * Note that WP_Customize_Manager::validate_setting_values() have already + * run on the setting values being serialized as JSON into the post content + * so it is pre-sanitized. + * + * Also, the sanitization logic is re-run through the respective + * WP_Customize_Setting::sanitize() method when being read out of the + * changeset, via WP_Customize_Manager::post_value(), and this sanitized + * value will also be sent into WP_Customize_Setting::update() for + * persisting to the DB. + * + * Multiple users can collaborate on a single changeset, where one user may + * have the unfiltered_html capability but another may not. A user with + * unfiltered_html may add a script tag to some field which needs to be kept + * intact even when another user updates the changeset to modify another field + * when they do not have unfiltered_html. + * + * @since 5.4.1 + * + * @param array $data An array of slashed and processed post data. + * @param array $postarr An array of sanitized (and slashed) but otherwise unmodified post data. + * @param array $unsanitized_postarr An array of slashed yet *unsanitized* and unprocessed post data as originally passed to wp_insert_post(). + * @return array Filtered post data. + */ + public function preserve_insert_changeset_post_content($data, $postarr, $unsanitized_postarr) + { + } + /** + * Trashes or deletes a changeset post. + * + * The following re-formulates the logic from `wp_trash_post()` as done in + * `wp_publish_post()`. The reason for bypassing `wp_trash_post()` is that it + * will mutate the the `post_content` and the `post_name` when they should be + * untouched. + * + * @since 4.9.0 + * + * @see wp_trash_post() + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|WP_Post $post The changeset post. + * @return mixed A WP_Post object for the trashed post or an empty value on failure. + */ + public function trash_changeset_post($post) + { + } + /** + * Handles request to trash a changeset. + * + * @since 4.9.0 + */ + public function handle_changeset_trash_request() + { + } + /** + * Re-maps 'edit_post' meta cap for a customize_changeset post to be the same as 'customize' maps. + * + * There is essentially a "meta meta" cap in play here, where 'edit_post' meta cap maps to + * the 'customize' meta cap which then maps to 'edit_theme_options'. This is currently + * required in core for `wp_create_post_autosave()` because it will call + * `_wp_translate_postdata()` which in turn will check if a user can 'edit_post', but the + * the caps for the customize_changeset post type are all mapping to the meta capability. + * This should be able to be removed once #40922 is addressed in core. + * + * @since 4.9.0 + * + * @link https://core.trac.wordpress.org/ticket/40922 + * @see WP_Customize_Manager::save_changeset_post() + * @see _wp_translate_postdata() + * + * @param string[] $caps Array of the user's capabilities. + * @param string $cap Capability name. + * @param int $user_id The user ID. + * @param array $args Adds the context to the cap. Typically the object ID. + * @return array Capabilities. + */ + public function grant_edit_post_capability_for_changeset($caps, $cap, $user_id, $args) + { + } + /** + * Marks the changeset post as being currently edited by the current user. + * + * @since 4.9.0 + * + * @param int $changeset_post_id Changeset post ID. + * @param bool $take_over Whether to take over the changeset. Default false. + */ + public function set_changeset_lock($changeset_post_id, $take_over = \false) + { + } + /** + * Refreshes changeset lock with the current time if current user edited the changeset before. + * + * @since 4.9.0 + * + * @param int $changeset_post_id Changeset post ID. + */ + public function refresh_changeset_lock($changeset_post_id) + { + } + /** + * Filters heartbeat settings for the Customizer. + * + * @since 4.9.0 + * + * @global string $pagenow The filename of the current screen. + * + * @param array $settings Current settings to filter. + * @return array Heartbeat settings. + */ + public function add_customize_screen_to_heartbeat_settings($settings) + { + } + /** + * Checks locked changeset with heartbeat API. + * + * @since 4.9.0 + * + * @param array $response The Heartbeat response. + * @param array $data The $_POST data sent. + * @param string $screen_id The screen id. + * @return array The Heartbeat response. + */ + public function check_changeset_lock_with_heartbeat($response, $data, $screen_id) + { + } + /** + * Removes changeset lock when take over request is sent via Ajax. + * + * @since 4.9.0 + */ + public function handle_override_changeset_lock_request() + { + } + /** + * Filters whether a changeset has changed to create a new revision. + * + * Note that this will not be called while a changeset post remains in auto-draft status. + * + * @since 4.7.0 + * + * @param bool $post_has_changed Whether the post has changed. + * @param WP_Post $latest_revision The latest revision post object. + * @param WP_Post $post The post object. + * @return bool Whether a revision should be made. + */ + public function _filter_revision_post_has_changed($post_has_changed, $latest_revision, $post) + { + } + /** + * Publishes the values of a changeset. + * + * This will publish the values contained in a changeset, even changesets that do not + * correspond to current manager instance. This is called by + * `_wp_customize_publish_changeset()` when a customize_changeset post is + * transitioned to the `publish` status. As such, this method should not be + * called directly and instead `wp_publish_post()` should be used. + * + * Please note that if the settings in the changeset are for a non-activated + * theme, the theme must first be switched to (via `switch_theme()`) before + * invoking this method. + * + * @since 4.7.0 + * + * @see _wp_customize_publish_changeset() + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $changeset_post_id ID for customize_changeset post. Defaults to the changeset for the current manager instance. + * @return true|WP_Error True or error info. + */ + public function _publish_changeset_values($changeset_post_id) + { + } + /** + * Refreshes nonces for the current preview. + * + * @since 4.2.0 + */ + public function refresh_nonces() + { + } + /** + * Deletes a given auto-draft changeset or the autosave revision for a given changeset or delete changeset lock. + * + * @since 4.9.0 + */ + public function handle_dismiss_autosave_or_lock_request() + { + } + /** + * Adds a customize setting. + * + * @since 3.4.0 + * @since 4.5.0 Return added WP_Customize_Setting instance. + * + * @see WP_Customize_Setting::__construct() + * @link https://developer.wordpress.org/themes/customize-api + * + * @param WP_Customize_Setting|string $id Customize Setting object, or ID. + * @param array $args Optional. Array of properties for the new Setting object. + * See WP_Customize_Setting::__construct() for information + * on accepted arguments. Default empty array. + * @return WP_Customize_Setting The instance of the setting that was added. + * @phpstan-param array{ + * type?: string, + * capability?: string, + * theme_supports?: string|string[], + * default?: string, + * transport?: string, + * validate_callback?: callable, + * sanitize_callback?: callable, + * sanitize_js_callback?: callable, + * dirty?: bool, + * } $args See WP_Customize_Setting::__construct() + */ + public function add_setting($id, $args = array()) + { + } + /** + * Registers any dynamically-created settings, such as those from $_POST['customized'] + * that have no corresponding setting created. + * + * This is a mechanism to "wake up" settings that have been dynamically created + * on the front end and have been sent to WordPress in `$_POST['customized']`. When WP + * loads, the dynamically-created settings then will get created and previewed + * even though they are not directly created statically with code. + * + * @since 4.2.0 + * + * @param array $setting_ids The setting IDs to add. + * @return array The WP_Customize_Setting objects added. + */ + public function add_dynamic_settings($setting_ids) + { + } + /** + * Retrieves a customize setting. + * + * @since 3.4.0 + * + * @param string $id Customize Setting ID. + * @return WP_Customize_Setting|void The setting, if set. + */ + public function get_setting($id) + { + } + /** + * Removes a customize setting. + * + * Note that removing the setting doesn't destroy the WP_Customize_Setting instance or remove its filters. + * + * @since 3.4.0 + * + * @param string $id Customize Setting ID. + */ + public function remove_setting($id) + { + } + /** + * Adds a customize panel. + * + * @since 4.0.0 + * @since 4.5.0 Return added WP_Customize_Panel instance. + * + * @see WP_Customize_Panel::__construct() + * + * @param WP_Customize_Panel|string $id Customize Panel object, or ID. + * @param array $args Optional. Array of properties for the new Panel object. + * See WP_Customize_Panel::__construct() for information + * on accepted arguments. Default empty array. + * @return WP_Customize_Panel The instance of the panel that was added. + * @phpstan-param array{ + * priority?: int, + * capability?: string, + * theme_supports?: mixed[], + * title?: string, + * description?: string, + * type?: string, + * active_callback?: callable, + * } $args See WP_Customize_Panel::__construct() + */ + public function add_panel($id, $args = array()) + { + } + /** + * Retrieves a customize panel. + * + * @since 4.0.0 + * + * @param string $id Panel ID to get. + * @return WP_Customize_Panel|void Requested panel instance, if set. + */ + public function get_panel($id) + { + } + /** + * Removes a customize panel. + * + * Note that removing the panel doesn't destroy the WP_Customize_Panel instance or remove its filters. + * + * @since 4.0.0 + * + * @param string $id Panel ID to remove. + */ + public function remove_panel($id) + { + } + /** + * Registers a customize panel type. + * + * Registered types are eligible to be rendered via JS and created dynamically. + * + * @since 4.3.0 + * + * @see WP_Customize_Panel + * + * @param string $panel Name of a custom panel which is a subclass of WP_Customize_Panel. + */ + public function register_panel_type($panel) + { + } + /** + * Renders JS templates for all registered panel types. + * + * @since 4.3.0 + */ + public function render_panel_templates() + { + } + /** + * Adds a customize section. + * + * @since 3.4.0 + * @since 4.5.0 Return added WP_Customize_Section instance. + * + * @see WP_Customize_Section::__construct() + * + * @param WP_Customize_Section|string $id Customize Section object, or ID. + * @param array $args Optional. Array of properties for the new Section object. + * See WP_Customize_Section::__construct() for information + * on accepted arguments. Default empty array. + * @return WP_Customize_Section The instance of the section that was added. + * @phpstan-param array{ + * priority?: int, + * panel?: string, + * capability?: string, + * theme_supports?: string|string[], + * title?: string, + * description?: string, + * type?: string, + * active_callback?: callable, + * description_hidden?: bool, + * } $args See WP_Customize_Section::__construct() + */ + public function add_section($id, $args = array()) + { + } + /** + * Retrieves a customize section. + * + * @since 3.4.0 + * + * @param string $id Section ID. + * @return WP_Customize_Section|void The section, if set. + */ + public function get_section($id) + { + } + /** + * Removes a customize section. + * + * Note that removing the section doesn't destroy the WP_Customize_Section instance or remove its filters. + * + * @since 3.4.0 + * + * @param string $id Section ID. + */ + public function remove_section($id) + { + } + /** + * Registers a customize section type. + * + * Registered types are eligible to be rendered via JS and created dynamically. + * + * @since 4.3.0 + * + * @see WP_Customize_Section + * + * @param string $section Name of a custom section which is a subclass of WP_Customize_Section. + */ + public function register_section_type($section) + { + } + /** + * Renders JS templates for all registered section types. + * + * @since 4.3.0 + */ + public function render_section_templates() + { + } + /** + * Adds a customize control. + * + * @since 3.4.0 + * @since 4.5.0 Return added WP_Customize_Control instance. + * + * @see WP_Customize_Control::__construct() + * + * @param WP_Customize_Control|string $id Customize Control object, or ID. + * @param array $args Optional. Array of properties for the new Control object. + * See WP_Customize_Control::__construct() for information + * on accepted arguments. Default empty array. + * @return WP_Customize_Control The instance of the control that was added. + * @phpstan-param array{ + * instance_number?: int, + * manager?: WP_Customize_Manager, + * id?: string, + * settings?: array, + * setting?: string, + * capability?: string, + * priority?: int, + * section?: string, + * label?: string, + * description?: string, + * choices?: array, + * input_attrs?: array, + * allow_addition?: bool, + * json?: array, + * type?: string, + * active_callback?: callable, + * } $args See WP_Customize_Control::__construct() + */ + public function add_control($id, $args = array()) + { + } + /** + * Retrieves a customize control. + * + * @since 3.4.0 + * + * @param string $id ID of the control. + * @return WP_Customize_Control|void The control object, if set. + */ + public function get_control($id) + { + } + /** + * Removes a customize control. + * + * Note that removing the control doesn't destroy the WP_Customize_Control instance or remove its filters. + * + * @since 3.4.0 + * + * @param string $id ID of the control. + */ + public function remove_control($id) + { + } + /** + * Registers a customize control type. + * + * Registered types are eligible to be rendered via JS and created dynamically. + * + * @since 4.1.0 + * + * @param string $control Name of a custom control which is a subclass of + * WP_Customize_Control. + */ + public function register_control_type($control) + { + } + /** + * Renders JS templates for all registered control types. + * + * @since 4.1.0 + */ + public function render_control_templates() + { + } + /** + * Prepares panels, sections, and controls. + * + * For each, check if required related components exist, + * whether the user has the necessary capabilities, + * and sort by priority. + * + * @since 3.4.0 + */ + public function prepare_controls() + { + } + /** + * Enqueues scripts for customize controls. + * + * @since 3.4.0 + */ + public function enqueue_control_scripts() + { + } + /** + * Determines whether the user agent is iOS. + * + * @since 4.4.0 + * + * @return bool Whether the user agent is iOS. + */ + public function is_ios() + { + } + /** + * Gets the template string for the Customizer pane document title. + * + * @since 4.4.0 + * + * @return string The template string for the document title. + */ + public function get_document_title_template() + { + } + /** + * Sets the initial URL to be previewed. + * + * URL is validated. + * + * @since 4.4.0 + * + * @param string $preview_url URL to be previewed. + */ + public function set_preview_url($preview_url) + { + } + /** + * Gets the initial URL to be previewed. + * + * @since 4.4.0 + * + * @return string URL being previewed. + */ + public function get_preview_url() + { + } + /** + * Determines whether the admin and the frontend are on different domains. + * + * @since 4.7.0 + * + * @return bool Whether cross-domain. + */ + public function is_cross_domain() + { + } + /** + * Gets URLs allowed to be previewed. + * + * If the front end and the admin are served from the same domain, load the + * preview over ssl if the Customizer is being loaded over ssl. This avoids + * insecure content warnings. This is not attempted if the admin and front end + * are on different domains to avoid the case where the front end doesn't have + * ssl certs. Domain mapping plugins can allow other urls in these conditions + * using the customize_allowed_urls filter. + * + * @since 4.7.0 + * + * @return array Allowed URLs. + */ + public function get_allowed_urls() + { + } + /** + * Gets messenger channel. + * + * @since 4.7.0 + * + * @return string Messenger channel. + */ + public function get_messenger_channel() + { + } + /** + * Sets URL to link the user to when closing the Customizer. + * + * URL is validated. + * + * @since 4.4.0 + * + * @param string $return_url URL for return link. + */ + public function set_return_url($return_url) + { + } + /** + * Gets URL to link the user to when closing the Customizer. + * + * @since 4.4.0 + * + * @global array $_registered_pages + * + * @return string URL for link to close Customizer. + */ + public function get_return_url() + { + } + /** + * Sets the autofocused constructs. + * + * @since 4.4.0 + * + * @param array $autofocus { + * Mapping of 'panel', 'section', 'control' to the ID which should be autofocused. + * + * @type string $control ID for control to be autofocused. + * @type string $section ID for section to be autofocused. + * @type string $panel ID for panel to be autofocused. + * } + * @phpstan-param array{ + * control?: string, + * section?: string, + * panel?: string, + * } $autofocus + */ + public function set_autofocus($autofocus) + { + } + /** + * Gets the autofocused constructs. + * + * @since 4.4.0 + * + * @return string[] { + * Mapping of 'panel', 'section', 'control' to the ID which should be autofocused. + * + * @type string $control ID for control to be autofocused. + * @type string $section ID for section to be autofocused. + * @type string $panel ID for panel to be autofocused. + * } + * @phpstan-return array{ + * control: string, + * section: string, + * panel: string, + * } + */ + public function get_autofocus() + { + } + /** + * Gets nonces for the Customizer. + * + * @since 4.5.0 + * + * @return array Nonces. + */ + public function get_nonces() + { + } + /** + * Prints JavaScript settings for parent window. + * + * @since 4.4.0 + */ + public function customize_pane_settings() + { + } + /** + * Returns a list of devices to allow previewing. + * + * @since 4.5.0 + * + * @return array List of devices with labels and default setting. + */ + public function get_previewable_devices() + { + } + /** + * Registers some default controls. + * + * @since 3.4.0 + */ + public function register_controls() + { + } + /** + * Returns whether there are published pages. + * + * Used as active callback for static front page section and controls. + * + * @since 4.7.0 + * + * @return bool Whether there are published (or to be published) pages. + */ + public function has_published_pages() + { + } + /** + * Adds settings from the POST data that were not added with code, e.g. dynamically-created settings for Widgets + * + * @since 4.2.0 + * + * @see add_dynamic_settings() + */ + public function register_dynamic_settings() + { + } + /** + * Loads themes into the theme browsing/installation UI. + * + * @since 4.9.0 + */ + public function handle_load_themes_request() + { + } + /** + * Callback for validating the header_textcolor value. + * + * Accepts 'blank', and otherwise uses sanitize_hex_color_no_hash(). + * Returns default text color if hex color is empty. + * + * @since 3.4.0 + * + * @param string $color + * @return mixed + */ + public function _sanitize_header_textcolor($color) + { + } + /** + * Callback for validating a background setting value. + * + * @since 4.7.0 + * + * @param string $value Repeat value. + * @param WP_Customize_Setting $setting Setting. + * @return string|WP_Error Background value or validation error. + */ + public function _sanitize_background_setting($value, $setting) + { + } + /** + * Exports header video settings to facilitate selective refresh. + * + * @since 4.7.0 + * + * @param array $response Response. + * @param WP_Customize_Selective_Refresh $selective_refresh Selective refresh component. + * @param array $partials Array of partials. + * @return array + */ + public function export_header_video_settings($response, $selective_refresh, $partials) + { + } + /** + * Callback for validating the header_video value. + * + * Ensures that the selected video is less than 8MB and provides an error message. + * + * @since 4.7.0 + * + * @param WP_Error $validity + * @param mixed $value + * @return mixed + */ + public function _validate_header_video($validity, $value) + { + } + /** + * Callback for validating the external_header_video value. + * + * Ensures that the provided URL is supported. + * + * @since 4.7.0 + * + * @param WP_Error $validity + * @param mixed $value + * @return mixed + */ + public function _validate_external_header_video($validity, $value) + { + } + /** + * Callback for sanitizing the external_header_video value. + * + * @since 4.7.1 + * + * @param string $value URL. + * @return string Sanitized URL. + */ + public function _sanitize_external_header_video($value) + { + } + /** + * Callback for rendering the custom logo, used in the custom_logo partial. + * + * This method exists because the partial object and context data are passed + * into a partial's render_callback so we cannot use get_custom_logo() as + * the render_callback directly since it expects a blog ID as the first + * argument. When WP no longer supports PHP 5.3, this method can be removed + * in favor of an anonymous function. + * + * @see WP_Customize_Manager::register_controls() + * + * @since 4.5.0 + * + * @return string Custom logo. + */ + public function _render_custom_logo_partial() + { + } + } + /** + * WordPress Customize Nav Menus classes + * + * @package WordPress + * @subpackage Customize + * @since 4.3.0 + */ + /** + * Customize Nav Menus class. + * + * Implements menu management in the Customizer. + * + * @since 4.3.0 + * + * @see WP_Customize_Manager + */ + #[\AllowDynamicProperties] + final class WP_Customize_Nav_Menus + { + /** + * WP_Customize_Manager instance. + * + * @since 4.3.0 + * @var WP_Customize_Manager + */ + public $manager; + /** + * Constructor. + * + * @since 4.3.0 + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + */ + public function __construct($manager) + { + } + /** + * Adds a nonce for customizing menus. + * + * @since 4.5.0 + * + * @param string[] $nonces Array of nonces. + * @return string[] Modified array of nonces. + */ + public function filter_nonces($nonces) + { + } + /** + * Ajax handler for loading available menu items. + * + * @since 4.3.0 + */ + public function ajax_load_available_items() + { + } + /** + * Performs the post_type and taxonomy queries for loading available menu items. + * + * @since 4.3.0 + * + * @param string $object_type Optional. Accepts any custom object type and has built-in support for + * 'post_type' and 'taxonomy'. Default is 'post_type'. + * @param string $object_name Optional. Accepts any registered taxonomy or post type name. Default is 'page'. + * @param int $page Optional. The page number used to generate the query offset. Default is '0'. + * @return array|WP_Error An array of menu items on success, a WP_Error object on failure. + */ + public function load_available_items_query($object_type = 'post_type', $object_name = 'page', $page = 0) + { + } + /** + * Ajax handler for searching available menu items. + * + * @since 4.3.0 + */ + public function ajax_search_available_items() + { + } + /** + * Performs post queries for available-item searching. + * + * Based on WP_Editor::wp_link_query(). + * + * @since 4.3.0 + * + * @param array $args Optional. Accepts 'pagenum' and 's' (search) arguments. + * @return array Menu items. + */ + public function search_available_items_query($args = array()) + { + } + /** + * Enqueues scripts and styles for Customizer pane. + * + * @since 4.3.0 + */ + public function enqueue_scripts() + { + } + /** + * Filters a dynamic setting's constructor args. + * + * For a dynamic setting to be registered, this filter must be employed + * to override the default false value with an array of args to pass to + * the WP_Customize_Setting constructor. + * + * @since 4.3.0 + * + * @param false|array $setting_args The arguments to the WP_Customize_Setting constructor. + * @param string $setting_id ID for dynamic setting, usually coming from `$_POST['customized']`. + * @return array|false + */ + public function filter_dynamic_setting_args($setting_args, $setting_id) + { + } + /** + * Allows non-statically created settings to be constructed with custom WP_Customize_Setting subclass. + * + * @since 4.3.0 + * + * @param string $setting_class WP_Customize_Setting or a subclass. + * @param string $setting_id ID for dynamic setting, usually coming from `$_POST['customized']`. + * @param array $setting_args WP_Customize_Setting or a subclass. + * @return string + */ + public function filter_dynamic_setting_class($setting_class, $setting_id, $setting_args) + { + } + /** + * Adds the customizer settings and controls. + * + * @since 4.3.0 + */ + public function customize_register() + { + } + /** + * Gets the base10 intval. + * + * This is used as a setting's sanitize_callback; we can't use just plain + * intval because the second argument is not what intval() expects. + * + * @since 4.3.0 + * + * @param mixed $value Number to convert. + * @return int Integer. + */ + public function intval_base10($value) + { + } + /** + * Returns an array of all the available item types. + * + * @since 4.3.0 + * @since 4.7.0 Each array item now includes a `$type_label` in addition to `$title`, `$type`, and `$object`. + * + * @return array The available menu item types. + */ + public function available_item_types() + { + } + /** + * Adds a new `auto-draft` post. + * + * @since 4.7.0 + * + * @param array $postarr { + * Post array. Note that post_status is overridden to be `auto-draft`. + * + * @var string $post_title Post title. Required. + * @var string $post_type Post type. Required. + * @var string $post_name Post name. + * @var string $post_content Post content. + * } + * @return WP_Post|WP_Error Inserted auto-draft post object or error. + */ + public function insert_auto_draft_post($postarr) + { + } + /** + * Ajax handler for adding a new auto-draft post. + * + * @since 4.7.0 + */ + public function ajax_insert_auto_draft_post() + { + } + /** + * Prints the JavaScript templates used to render Menu Customizer components. + * + * Templates are imported into the JS use wp.template. + * + * @since 4.3.0 + */ + public function print_templates() + { + } + /** + * Prints the HTML template used to render the add-menu-item frame. + * + * @since 4.3.0 + */ + public function available_items_template() + { + } + // + // Start functionality specific to partial-refresh of menu changes in Customizer preview. + // + /** + * Nav menu args used for each instance, keyed by the args HMAC. + * + * @since 4.3.0 + * @var array + */ + public $preview_nav_menu_instance_args = array(); + /** + * Filters arguments for dynamic nav_menu selective refresh partials. + * + * @since 4.5.0 + * + * @param array|false $partial_args Partial args. + * @param string $partial_id Partial ID. + * @return array Partial args. + */ + public function customize_dynamic_partial_args($partial_args, $partial_id) + { + } + /** + * Adds hooks for the Customizer preview. + * + * @since 4.3.0 + */ + public function customize_preview_init() + { + } + /** + * Makes the auto-draft status protected so that it can be queried. + * + * @since 4.7.0 + * + * @global stdClass[] $wp_post_statuses List of post statuses. + */ + public function make_auto_draft_status_previewable() + { + } + /** + * Sanitizes post IDs for posts created for nav menu items to be published. + * + * @since 4.7.0 + * + * @param array $value Post IDs. + * @return array Post IDs. + */ + public function sanitize_nav_menus_created_posts($value) + { + } + /** + * Publishes the auto-draft posts that were created for nav menu items. + * + * The post IDs will have been sanitized by already by + * `WP_Customize_Nav_Menu_Items::sanitize_nav_menus_created_posts()` to + * remove any post IDs for which the user cannot publish or for which the + * post is not an auto-draft. + * + * @since 4.7.0 + * + * @param WP_Customize_Setting $setting Customizer setting object. + */ + public function save_nav_menus_created_posts($setting) + { + } + /** + * Keeps track of the arguments that are being passed to wp_nav_menu(). + * + * @since 4.3.0 + * + * @see wp_nav_menu() + * @see WP_Customize_Widgets::filter_dynamic_sidebar_params() + * + * @param array $args An array containing wp_nav_menu() arguments. + * @return array Arguments. + */ + public function filter_wp_nav_menu_args($args) + { + } + /** + * Prepares wp_nav_menu() calls for partial refresh. + * + * Injects attributes into container element. + * + * @since 4.3.0 + * + * @see wp_nav_menu() + * + * @param string $nav_menu_content The HTML content for the navigation menu. + * @param object $args An object containing wp_nav_menu() arguments. + * @return string Nav menu HTML with selective refresh attributes added if partial can be refreshed. + */ + public function filter_wp_nav_menu($nav_menu_content, $args) + { + } + /** + * Hashes (hmac) the nav menu arguments to ensure they are not tampered with when + * submitted in the Ajax request. + * + * Note that the array is expected to be pre-sorted. + * + * @since 4.3.0 + * + * @param array $args The arguments to hash. + * @return string Hashed nav menu arguments. + */ + public function hash_nav_menu_args($args) + { + } + /** + * Enqueues scripts for the Customizer preview. + * + * @since 4.3.0 + */ + public function customize_preview_enqueue_deps() + { + } + /** + * Exports data from PHP to JS. + * + * @since 4.3.0 + */ + public function export_preview_data() + { + } + /** + * Exports any wp_nav_menu() calls during the rendering of any partials. + * + * @since 4.5.0 + * + * @param array $response Response. + * @return array Response. + */ + public function export_partial_rendered_nav_menu_instances($response) + { + } + /** + * Renders a specific menu via wp_nav_menu() using the supplied arguments. + * + * @since 4.3.0 + * + * @see wp_nav_menu() + * + * @param WP_Customize_Partial $partial Partial. + * @param array $nav_menu_args Nav menu args supplied as container context. + * @return string|false + */ + public function render_nav_menu_partial($partial, $nav_menu_args) + { + } + } + /** + * WordPress Customize Panel classes + * + * @package WordPress + * @subpackage Customize + * @since 4.0.0 + */ + /** + * Customize Panel class. + * + * A UI container for sections, managed by the WP_Customize_Manager. + * + * @since 4.0.0 + * + * @see WP_Customize_Manager + */ + #[\AllowDynamicProperties] + class WP_Customize_Panel + { + /** + * Incremented with each new class instantiation, then stored in $instance_number. + * + * Used when sorting two instances whose priorities are equal. + * + * @since 4.1.0 + * @var int + */ + protected static $instance_count = 0; + /** + * Order in which this instance was created in relation to other instances. + * + * @since 4.1.0 + * @var int + */ + public $instance_number; + /** + * WP_Customize_Manager instance. + * + * @since 4.0.0 + * @var WP_Customize_Manager + */ + public $manager; + /** + * Unique identifier. + * + * @since 4.0.0 + * @var string + */ + public $id; + /** + * Priority of the panel, defining the display order of panels and sections. + * + * @since 4.0.0 + * @var int + */ + public $priority = 160; + /** + * Capability required for the panel. + * + * @since 4.0.0 + * @var string + */ + public $capability = 'edit_theme_options'; + /** + * Theme features required to support the panel. + * + * @since 4.0.0 + * @var mixed[] + */ + public $theme_supports = ''; + /** + * Title of the panel to show in UI. + * + * @since 4.0.0 + * @var string + */ + public $title = ''; + /** + * Description to show in the UI. + * + * @since 4.0.0 + * @var string + */ + public $description = ''; + /** + * Auto-expand a section in a panel when the panel is expanded when the panel only has the one section. + * + * @since 4.7.4 + * @var bool + */ + public $auto_expand_sole_section = \false; + /** + * Customizer sections for this panel. + * + * @since 4.0.0 + * @var array + */ + public $sections; + /** + * Type of this panel. + * + * @since 4.1.0 + * @var string + */ + public $type = 'default'; + /** + * Active callback. + * + * @since 4.1.0 + * + * @see WP_Customize_Section::active() + * + * @var callable Callback is called with one argument, the instance of + * WP_Customize_Section, and returns bool to indicate whether + * the section is active (such as it relates to the URL currently + * being previewed). + */ + public $active_callback = ''; + /** + * Constructor. + * + * Any supplied $args override class property defaults. + * + * @since 4.0.0 + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + * @param string $id A specific ID for the panel. + * @param array $args { + * Optional. Array of properties for the new Panel object. Default empty array. + * + * @type int $priority Priority of the panel, defining the display order + * of panels and sections. Default 160. + * @type string $capability Capability required for the panel. + * Default `edit_theme_options`. + * @type mixed[] $theme_supports Theme features required to support the panel. + * @type string $title Title of the panel to show in UI. + * @type string $description Description to show in the UI. + * @type string $type Type of the panel. + * @type callable $active_callback Active callback. + * } + * @phpstan-param array{ + * priority?: int, + * capability?: string, + * theme_supports?: mixed[], + * title?: string, + * description?: string, + * type?: string, + * active_callback?: callable, + * } $args + */ + public function __construct($manager, $id, $args = array()) + { + } + /** + * Check whether panel is active to current Customizer preview. + * + * @since 4.1.0 + * + * @return bool Whether the panel is active to the current preview. + */ + public final function active() + { + } + /** + * Default callback used when invoking WP_Customize_Panel::active(). + * + * Subclasses can override this with their specific logic, or they may + * provide an 'active_callback' argument to the constructor. + * + * @since 4.1.0 + * + * @return bool Always true. + */ + public function active_callback() + { + } + /** + * Gather the parameters passed to client JavaScript via JSON. + * + * @since 4.1.0 + * + * @return array The array to be exported to the client as JSON. + */ + public function json() + { + } + /** + * Checks required user capabilities and whether the theme has the + * feature support required by the panel. + * + * @since 4.0.0 + * @since 5.9.0 Method was marked non-final. + * + * @return bool False if theme doesn't support the panel or the user doesn't have the capability. + */ + public function check_capabilities() + { + } + /** + * Get the panel's content template for insertion into the Customizer pane. + * + * @since 4.1.0 + * + * @return string Content for the panel. + */ + public final function get_content() + { + } + /** + * Check capabilities and render the panel. + * + * @since 4.0.0 + */ + public final function maybe_render() + { + } + /** + * Render the panel container, and then its contents (via `this->render_content()`) in a subclass. + * + * Panel containers are now rendered in JS by default, see WP_Customize_Panel::print_template(). + * + * @since 4.0.0 + */ + protected function render() + { + } + /** + * Render the panel UI in a subclass. + * + * Panel contents are now rendered in JS by default, see WP_Customize_Panel::print_template(). + * + * @since 4.1.0 + */ + protected function render_content() + { + } + /** + * Render the panel's JS templates. + * + * This function is only run for panel types that have been registered with + * WP_Customize_Manager::register_panel_type(). + * + * @since 4.3.0 + * + * @see WP_Customize_Manager::register_panel_type() + */ + public function print_template() + { + } + /** + * An Underscore (JS) template for rendering this panel's container. + * + * Class variables for this panel class are available in the `data` JS object; + * export custom variables by overriding WP_Customize_Panel::json(). + * + * @see WP_Customize_Panel::print_template() + * + * @since 4.3.0 + */ + protected function render_template() + { + } + /** + * An Underscore (JS) template for this panel's content (but not its container). + * + * Class variables for this panel class are available in the `data` JS object; + * export custom variables by overriding WP_Customize_Panel::json(). + * + * @see WP_Customize_Panel::print_template() + * + * @since 4.3.0 + */ + protected function content_template() + { + } + } + /** + * WordPress Customize Section classes + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ + /** + * Customize Section class. + * + * A UI container for controls, managed by the WP_Customize_Manager class. + * + * @since 3.4.0 + * + * @see WP_Customize_Manager + */ + #[\AllowDynamicProperties] + class WP_Customize_Section + { + /** + * Incremented with each new class instantiation, then stored in $instance_number. + * + * Used when sorting two instances whose priorities are equal. + * + * @since 4.1.0 + * @var int + */ + protected static $instance_count = 0; + /** + * Order in which this instance was created in relation to other instances. + * + * @since 4.1.0 + * @var int + */ + public $instance_number; + /** + * WP_Customize_Manager instance. + * + * @since 3.4.0 + * @var WP_Customize_Manager + */ + public $manager; + /** + * Unique identifier. + * + * @since 3.4.0 + * @var string + */ + public $id; + /** + * Priority of the section which informs load order of sections. + * + * @since 3.4.0 + * @var int + */ + public $priority = 160; + /** + * Panel in which to show the section, making it a sub-section. + * + * @since 4.0.0 + * @var string + */ + public $panel = ''; + /** + * Capability required for the section. + * + * @since 3.4.0 + * @var string + */ + public $capability = 'edit_theme_options'; + /** + * Theme features required to support the section. + * + * @since 3.4.0 + * @var string|string[] + */ + public $theme_supports = ''; + /** + * Title of the section to show in UI. + * + * @since 3.4.0 + * @var string + */ + public $title = ''; + /** + * Description to show in the UI. + * + * @since 3.4.0 + * @var string + */ + public $description = ''; + /** + * Customizer controls for this section. + * + * @since 3.4.0 + * @var array + */ + public $controls; + /** + * Type of this section. + * + * @since 4.1.0 + * @var string + */ + public $type = 'default'; + /** + * Active callback. + * + * @since 4.1.0 + * + * @see WP_Customize_Section::active() + * + * @var callable Callback is called with one argument, the instance of + * WP_Customize_Section, and returns bool to indicate whether + * the section is active (such as it relates to the URL currently + * being previewed). + */ + public $active_callback = ''; + /** + * Show the description or hide it behind the help icon. + * + * @since 4.7.0 + * + * @var bool Indicates whether the Section's description should be + * hidden behind a help icon ("?") in the Section header, + * similar to how help icons are displayed on Panels. + */ + public $description_hidden = \false; + /** + * Constructor. + * + * Any supplied $args override class property defaults. + * + * @since 3.4.0 + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + * @param string $id A specific ID of the section. + * @param array $args { + * Optional. Array of properties for the new Section object. Default empty array. + * + * @type int $priority Priority of the section, defining the display order + * of panels and sections. Default 160. + * @type string $panel The panel this section belongs to (if any). + * Default empty. + * @type string $capability Capability required for the section. + * Default 'edit_theme_options' + * @type string|string[] $theme_supports Theme features required to support the section. + * @type string $title Title of the section to show in UI. + * @type string $description Description to show in the UI. + * @type string $type Type of the section. + * @type callable $active_callback Active callback. + * @type bool $description_hidden Hide the description behind a help icon, + * instead of inline above the first control. + * Default false. + * } + * @phpstan-param array{ + * priority?: int, + * panel?: string, + * capability?: string, + * theme_supports?: string|string[], + * title?: string, + * description?: string, + * type?: string, + * active_callback?: callable, + * description_hidden?: bool, + * } $args + */ + public function __construct($manager, $id, $args = array()) + { + } + /** + * Check whether section is active to current Customizer preview. + * + * @since 4.1.0 + * + * @return bool Whether the section is active to the current preview. + */ + public final function active() + { + } + /** + * Default callback used when invoking WP_Customize_Section::active(). + * + * Subclasses can override this with their specific logic, or they may provide + * an 'active_callback' argument to the constructor. + * + * @since 4.1.0 + * + * @return true Always true. + */ + public function active_callback() + { + } + /** + * Gather the parameters passed to client JavaScript via JSON. + * + * @since 4.1.0 + * + * @return array The array to be exported to the client as JSON. + */ + public function json() + { + } + /** + * Checks required user capabilities and whether the theme has the + * feature support required by the section. + * + * @since 3.4.0 + * + * @return bool False if theme doesn't support the section or user doesn't have the capability. + */ + public final function check_capabilities() + { + } + /** + * Get the section's content for insertion into the Customizer pane. + * + * @since 4.1.0 + * + * @return string Contents of the section. + */ + public final function get_content() + { + } + /** + * Check capabilities and render the section. + * + * @since 3.4.0 + */ + public final function maybe_render() + { + } + /** + * Render the section UI in a subclass. + * + * Sections are now rendered in JS by default, see WP_Customize_Section::print_template(). + * + * @since 3.4.0 + */ + protected function render() + { + } + /** + * Render the section's JS template. + * + * This function is only run for section types that have been registered with + * WP_Customize_Manager::register_section_type(). + * + * @since 4.3.0 + * + * @see WP_Customize_Manager::render_template() + */ + public function print_template() + { + } + /** + * An Underscore (JS) template for rendering this section. + * + * Class variables for this section class are available in the `data` JS object; + * export custom variables by overriding WP_Customize_Section::json(). + * + * @since 4.3.0 + * + * @see WP_Customize_Section::print_template() + */ + protected function render_template() + { + } + } + /** + * WordPress Customize Setting classes + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ + /** + * Customize Setting class. + * + * Handles saving and sanitizing of settings. + * + * @since 3.4.0 + * + * @see WP_Customize_Manager + * @link https://developer.wordpress.org/themes/customize-api + */ + #[\AllowDynamicProperties] + class WP_Customize_Setting + { + /** + * Customizer bootstrap instance. + * + * @since 3.4.0 + * @var WP_Customize_Manager + */ + public $manager; + /** + * Unique string identifier for the setting. + * + * @since 3.4.0 + * @var string + */ + public $id; + /** + * Type of customize settings. + * + * @since 3.4.0 + * @var string + */ + public $type = 'theme_mod'; + /** + * Capability required to edit this setting. + * + * @since 3.4.0 + * @var string|array + */ + public $capability = 'edit_theme_options'; + /** + * Theme features required to support the setting. + * + * @since 3.4.0 + * @var string|string[] + */ + public $theme_supports = ''; + /** + * The default value for the setting. + * + * @since 3.4.0 + * @var string + */ + public $default = ''; + /** + * Options for rendering the live preview of changes in Customizer. + * + * Set this value to 'postMessage' to enable a custom JavaScript handler to render changes to this setting + * as opposed to reloading the whole page. + * + * @since 3.4.0 + * @var string + */ + public $transport = 'refresh'; + /** + * Server-side validation callback for the setting's value. + * + * @since 4.6.0 + * @var callable + */ + public $validate_callback = ''; + /** + * Callback to filter a Customize setting value in un-slashed form. + * + * @since 3.4.0 + * @var callable + */ + public $sanitize_callback = ''; + /** + * Callback to convert a Customize PHP setting value to a value that is JSON serializable. + * + * @since 3.4.0 + * @var callable + */ + public $sanitize_js_callback = ''; + /** + * Whether or not the setting is initially dirty when created. + * + * This is used to ensure that a setting will be sent from the pane to the + * preview when loading the Customizer. Normally a setting only is synced to + * the preview if it has been changed. This allows the setting to be sent + * from the start. + * + * @since 4.2.0 + * @var bool + */ + public $dirty = \false; + /** + * ID Data. + * + * @since 3.4.0 + * @var array + */ + protected $id_data = array(); + /** + * Whether or not preview() was called. + * + * @since 4.4.0 + * @var bool + */ + protected $is_previewed = \false; + /** + * Cache of multidimensional values to improve performance. + * + * @since 4.4.0 + * @var array + */ + protected static $aggregated_multidimensionals = array(); + /** + * Whether the multidimensional setting is aggregated. + * + * @since 4.4.0 + * @var bool + */ + protected $is_multidimensional_aggregated = \false; + /** + * Constructor. + * + * Any supplied $args override class property defaults. + * + * @since 3.4.0 + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + * @param string $id A specific ID of the setting. + * Can be a theme mod or option name. + * @param array $args { + * Optional. Array of properties for the new Setting object. Default empty array. + * + * @type string $type Type of the setting. Default 'theme_mod'. + * @type string $capability Capability required for the setting. Default 'edit_theme_options' + * @type string|string[] $theme_supports Theme features required to support the panel. Default is none. + * @type string $default Default value for the setting. Default is empty string. + * @type string $transport Options for rendering the live preview of changes in Customizer. + * Using 'refresh' makes the change visible by reloading the whole preview. + * Using 'postMessage' allows a custom JavaScript to handle live changes. + * Default is 'refresh'. + * @type callable $validate_callback Server-side validation callback for the setting's value. + * @type callable $sanitize_callback Callback to filter a Customize setting value in un-slashed form. + * @type callable $sanitize_js_callback Callback to convert a Customize PHP setting value to a value that is + * JSON serializable. + * @type bool $dirty Whether or not the setting is initially dirty when created. + * } + * @phpstan-param array{ + * type?: string, + * capability?: string, + * theme_supports?: string|string[], + * default?: string, + * transport?: string, + * validate_callback?: callable, + * sanitize_callback?: callable, + * sanitize_js_callback?: callable, + * dirty?: bool, + * } $args + */ + public function __construct($manager, $id, $args = array()) + { + } + /** + * Get parsed ID data for multidimensional setting. + * + * @since 4.4.0 + * + * @return array { + * ID data for multidimensional setting. + * + * @type string $base ID base + * @type array $keys Keys for multidimensional array. + * } + * @phpstan-return array{ + * base: string, + * keys: array, + * } + */ + public final function id_data() + { + } + /** + * Set up the setting for aggregated multidimensional values. + * + * When a multidimensional setting gets aggregated, all of its preview and update + * calls get combined into one call, greatly improving performance. + * + * @since 4.4.0 + */ + protected function aggregate_multidimensional() + { + } + /** + * Reset `$aggregated_multidimensionals` static variable. + * + * This is intended only for use by unit tests. + * + * @since 4.5.0 + * @ignore + */ + public static function reset_aggregated_multidimensionals() + { + } + /** + * The ID for the current site when the preview() method was called. + * + * @since 4.2.0 + * @var int + */ + protected $_previewed_blog_id; + /** + * Return true if the current site is not the same as the previewed site. + * + * @since 4.2.0 + * + * @return bool If preview() has been called. + */ + public function is_current_blog_previewed() + { + } + /** + * Original non-previewed value stored by the preview method. + * + * @see WP_Customize_Setting::preview() + * @since 4.1.1 + * @var mixed + */ + protected $_original_value; + /** + * Add filters to supply the setting's value when accessed. + * + * If the setting already has a pre-existing value and there is no incoming + * post value for the setting, then this method will short-circuit since + * there is no change to preview. + * + * @since 3.4.0 + * @since 4.4.0 Added boolean return value. + * + * @return bool False when preview short-circuits due no change needing to be previewed. + */ + public function preview() + { + } + /** + * Clear out the previewed-applied flag for a multidimensional-aggregated value whenever its post value is updated. + * + * This ensures that the new value will get sanitized and used the next time + * that `WP_Customize_Setting::_multidimensional_preview_filter()` + * is called for this setting. + * + * @since 4.4.0 + * + * @see WP_Customize_Manager::set_post_value() + * @see WP_Customize_Setting::_multidimensional_preview_filter() + */ + public final function _clear_aggregated_multidimensional_preview_applied_flag() + { + } + /** + * Callback function to filter non-multidimensional theme mods and options. + * + * If switch_to_blog() was called after the preview() method, and the current + * site is now not the same site, then this method does a no-op and returns + * the original value. + * + * @since 3.4.0 + * + * @param mixed $original Old value. + * @return mixed New or old value. + */ + public function _preview_filter($original) + { + } + /** + * Callback function to filter multidimensional theme mods and options. + * + * For all multidimensional settings of a given type, the preview filter for + * the first setting previewed will be used to apply the values for the others. + * + * @since 4.4.0 + * + * @see WP_Customize_Setting::$aggregated_multidimensionals + * @param mixed $original Original root value. + * @return mixed New or old value. + */ + public final function _multidimensional_preview_filter($original) + { + } + /** + * Checks user capabilities and theme supports, and then saves + * the value of the setting. + * + * @since 3.4.0 + * + * @return void|false Void on success, false if cap check fails + * or value isn't set or is invalid. + */ + public final function save() + { + } + /** + * Fetch and sanitize the $_POST value for the setting. + * + * During a save request prior to save, post_value() provides the new value while value() does not. + * + * @since 3.4.0 + * + * @param mixed $default_value A default value which is used as a fallback. Default null. + * @return mixed The default value on failure, otherwise the sanitized and validated value. + */ + public final function post_value($default_value = \null) + { + } + /** + * Sanitize an input. + * + * @since 3.4.0 + * + * @param string|array $value The value to sanitize. + * @return string|array|null|WP_Error Sanitized value, or `null`/`WP_Error` if invalid. + */ + public function sanitize($value) + { + } + /** + * Validates an input. + * + * @since 4.6.0 + * + * @see WP_REST_Request::has_valid_params() + * + * @param mixed $value Value to validate. + * @return true|WP_Error True if the input was validated, otherwise WP_Error. + */ + public function validate($value) + { + } + /** + * Get the root value for a setting, especially for multidimensional ones. + * + * @since 4.4.0 + * + * @param mixed $default_value Value to return if root does not exist. + * @return mixed + */ + protected function get_root_value($default_value = \null) + { + } + /** + * Set the root value for a setting, especially for multidimensional ones. + * + * @since 4.4.0 + * + * @param mixed $value Value to set as root of multidimensional setting. + * @return bool Whether the multidimensional root was updated successfully. + */ + protected function set_root_value($value) + { + } + /** + * Save the value of the setting, using the related API. + * + * @since 3.4.0 + * + * @param mixed $value The value to update. + * @return bool The result of saving the value. + */ + protected function update($value) + { + } + /** + * Deprecated method. + * + * @since 3.4.0 + * @deprecated 4.4.0 Deprecated in favor of update() method. + */ + protected function _update_theme_mod() + { + } + /** + * Deprecated method. + * + * @since 3.4.0 + * @deprecated 4.4.0 Deprecated in favor of update() method. + */ + protected function _update_option() + { + } + /** + * Fetch the value of the setting. + * + * @since 3.4.0 + * + * @return mixed The value. + */ + public function value() + { + } + /** + * Sanitize the setting's value for use in JavaScript. + * + * @since 3.4.0 + * + * @return mixed The requested escaped value. + */ + public function js_value() + { + } + /** + * Retrieves the data to export to the client via JSON. + * + * @since 4.6.0 + * + * @return array Array of parameters passed to JavaScript. + */ + public function json() + { + } + /** + * Validate user capabilities whether the theme supports the setting. + * + * @since 3.4.0 + * + * @return bool False if theme doesn't support the setting or user can't change setting, otherwise true. + */ + public final function check_capabilities() + { + } + /** + * Multidimensional helper function. + * + * @since 3.4.0 + * + * @param array $root + * @param array $keys + * @param bool $create Default false. + * @return array|void Keys are 'root', 'node', and 'key'. + */ + protected final function multidimensional(&$root, $keys, $create = \false) + { + } + /** + * Will attempt to replace a specific value in a multidimensional array. + * + * @since 3.4.0 + * + * @param array $root + * @param array $keys + * @param mixed $value The value to update. + * @return mixed + */ + protected final function multidimensional_replace($root, $keys, $value) + { + } + /** + * Will attempt to fetch a specific value from a multidimensional array. + * + * @since 3.4.0 + * + * @param array $root + * @param array $keys + * @param mixed $default_value A default value which is used as a fallback. Default null. + * @return mixed The requested value or the default value. + */ + protected final function multidimensional_get($root, $keys, $default_value = \null) + { + } + /** + * Will attempt to check if a specific value in a multidimensional array is set. + * + * @since 3.4.0 + * + * @param array $root + * @param array $keys + * @return bool True if value is set, false if not. + */ + protected final function multidimensional_isset($root, $keys) + { + } + } + /** + * WordPress Customize Widgets classes + * + * @package WordPress + * @subpackage Customize + * @since 3.9.0 + */ + /** + * Customize Widgets class. + * + * Implements widget management in the Customizer. + * + * @since 3.9.0 + * + * @see WP_Customize_Manager + */ + #[\AllowDynamicProperties] + final class WP_Customize_Widgets + { + /** + * WP_Customize_Manager instance. + * + * @since 3.9.0 + * @var WP_Customize_Manager + */ + public $manager; + /** + * Initial loader. + * + * @since 3.9.0 + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + */ + public function __construct($manager) + { + } + /** + * List whether each registered widget can be use selective refresh. + * + * If the theme does not support the customize-selective-refresh-widgets feature, + * then this will always return an empty array. + * + * @since 4.5.0 + * + * @global WP_Widget_Factory $wp_widget_factory + * + * @return array Mapping of id_base to support. If theme doesn't support + * selective refresh, an empty array is returned. + */ + public function get_selective_refreshable_widgets() + { + } + /** + * Determines if a widget supports selective refresh. + * + * @since 4.5.0 + * + * @param string $id_base Widget ID Base. + * @return bool Whether the widget can be selective refreshed. + */ + public function is_widget_selective_refreshable($id_base) + { + } + /** + * Inspects the incoming customized data for any widget settings, and dynamically adds + * them up-front so widgets will be initialized properly. + * + * @since 4.2.0 + */ + public function register_settings() + { + } + /** + * Determines the arguments for a dynamically-created setting. + * + * @since 4.2.0 + * + * @param false|array $args The arguments to the WP_Customize_Setting constructor. + * @param string $setting_id ID for dynamic setting, usually coming from `$_POST['customized']`. + * @return array|false Setting arguments, false otherwise. + */ + public function filter_customize_dynamic_setting_args($args, $setting_id) + { + } + /** + * Override sidebars_widgets for theme switch. + * + * When switching a theme via the Customizer, supply any previously-configured + * sidebars_widgets from the target theme as the initial sidebars_widgets + * setting. Also store the old theme's existing settings so that they can + * be passed along for storing in the sidebars_widgets theme_mod when the + * theme gets switched. + * + * @since 3.9.0 + * + * @global array $sidebars_widgets + * @global array $_wp_sidebars_widgets + */ + public function override_sidebars_widgets_for_theme_switch() + { + } + /** + * Filters old_sidebars_widgets_data Customizer setting. + * + * When switching themes, filter the Customizer setting old_sidebars_widgets_data + * to supply initial $sidebars_widgets before they were overridden by retrieve_widgets(). + * The value for old_sidebars_widgets_data gets set in the old theme's sidebars_widgets + * theme_mod. + * + * @since 3.9.0 + * + * @see WP_Customize_Widgets::handle_theme_switch() + * + * @param array $old_sidebars_widgets + * @return array + */ + public function filter_customize_value_old_sidebars_widgets_data($old_sidebars_widgets) + { + } + /** + * Filters sidebars_widgets option for theme switch. + * + * When switching themes, the retrieve_widgets() function is run when the Customizer initializes, + * and then the new sidebars_widgets here get supplied as the default value for the sidebars_widgets + * option. + * + * @since 3.9.0 + * + * @see WP_Customize_Widgets::handle_theme_switch() + * @global array $sidebars_widgets + * + * @param array $sidebars_widgets + * @return array + */ + public function filter_option_sidebars_widgets_for_theme_switch($sidebars_widgets) + { + } + /** + * Ensures all widgets get loaded into the Customizer. + * + * Note: these actions are also fired in wp_ajax_update_widget(). + * + * @since 3.9.0 + */ + public function customize_controls_init() + { + } + /** + * Ensures widgets are available for all types of previews. + * + * When in preview, hook to {@see 'customize_register'} for settings after WordPress is loaded + * so that all filters have been initialized (e.g. Widget Visibility). + * + * @since 3.9.0 + */ + public function schedule_customize_register() + { + } + /** + * Registers Customizer settings and controls for all sidebars and widgets. + * + * @since 3.9.0 + * + * @global array $wp_registered_widgets + * @global array $wp_registered_widget_controls + * @global array $wp_registered_sidebars + */ + public function customize_register() + { + } + /** + * Determines whether the widgets panel is active, based on whether there are sidebars registered. + * + * @since 4.4.0 + * + * @see WP_Customize_Panel::$active_callback + * + * @global array $wp_registered_sidebars + * @return bool Active. + */ + public function is_panel_active() + { + } + /** + * Converts a widget_id into its corresponding Customizer setting ID (option name). + * + * @since 3.9.0 + * + * @param string $widget_id Widget ID. + * @return string Maybe-parsed widget ID. + */ + public function get_setting_id($widget_id) + { + } + /** + * Determines whether the widget is considered "wide". + * + * Core widgets which may have controls wider than 250, but can still be shown + * in the narrow Customizer panel. The RSS and Text widgets in Core, for example, + * have widths of 400 and yet they still render fine in the Customizer panel. + * + * This method will return all Core widgets as being not wide, but this can be + * overridden with the {@see 'is_wide_widget_in_customizer'} filter. + * + * @since 3.9.0 + * + * @global array $wp_registered_widget_controls + * + * @param string $widget_id Widget ID. + * @return bool Whether or not the widget is a "wide" widget. + */ + public function is_wide_widget($widget_id) + { + } + /** + * Converts a widget ID into its id_base and number components. + * + * @since 3.9.0 + * + * @param string $widget_id Widget ID. + * @return array Array containing a widget's id_base and number components. + */ + public function parse_widget_id($widget_id) + { + } + /** + * Converts a widget setting ID (option path) to its id_base and number components. + * + * @since 3.9.0 + * + * @param string $setting_id Widget setting ID. + * @return array|WP_Error Array containing a widget's id_base and number components, + * or a WP_Error object. + */ + public function parse_widget_setting_id($setting_id) + { + } + /** + * Calls admin_print_styles-widgets.php and admin_print_styles hooks to + * allow custom styles from plugins. + * + * @since 3.9.0 + */ + public function print_styles() + { + } + /** + * Calls admin_print_scripts-widgets.php and admin_print_scripts hooks to + * allow custom scripts from plugins. + * + * @since 3.9.0 + */ + public function print_scripts() + { + } + /** + * Enqueues scripts and styles for Customizer panel and export data to JavaScript. + * + * @since 3.9.0 + * + * @global WP_Scripts $wp_scripts + * @global array $wp_registered_sidebars + * @global array $wp_registered_widgets + */ + public function enqueue_scripts() + { + } + /** + * Renders the widget form control templates into the DOM. + * + * @since 3.9.0 + */ + public function output_widget_control_templates() + { + } + /** + * Calls admin_print_footer_scripts and admin_print_scripts hooks to + * allow custom scripts from plugins. + * + * @since 3.9.0 + */ + public function print_footer_scripts() + { + } + /** + * Retrieves common arguments to supply when constructing a Customizer setting. + * + * @since 3.9.0 + * + * @param string $id Widget setting ID. + * @param array $overrides Array of setting overrides. + * @return array Possibly modified setting arguments. + */ + public function get_setting_args($id, $overrides = array()) + { + } + /** + * Ensures sidebar widget arrays only ever contain widget IDS. + * + * Used as the 'sanitize_callback' for each $sidebars_widgets setting. + * + * @since 3.9.0 + * + * @param string[] $widget_ids Array of widget IDs. + * @return string[] Array of sanitized widget IDs. + */ + public function sanitize_sidebar_widgets($widget_ids) + { + } + /** + * Builds up an index of all available widgets for use in Backbone models. + * + * @since 3.9.0 + * + * @global array $wp_registered_widgets + * @global array $wp_registered_widget_controls + * + * @see wp_list_widgets() + * + * @return array List of available widgets. + */ + public function get_available_widgets() + { + } + /** + * Retrieves the widget control markup. + * + * @since 3.9.0 + * + * @param array $args Widget control arguments. + * @return string Widget control form HTML markup. + */ + public function get_widget_control($args) + { + } + /** + * Retrieves the widget control markup parts. + * + * @since 4.4.0 + * + * @param array $args Widget control arguments. + * @return array { + * @type string $control Markup for widget control wrapping form. + * @type string $content The contents of the widget form itself. + * } + * @phpstan-return array{ + * control: string, + * content: string, + * } + */ + public function get_widget_control_parts($args) + { + } + /** + * Adds hooks for the Customizer preview. + * + * @since 3.9.0 + */ + public function customize_preview_init() + { + } + /** + * Refreshes the nonce for widget updates. + * + * @since 4.2.0 + * + * @param array $nonces Array of nonces. + * @return array Array of nonces. + */ + public function refresh_nonces($nonces) + { + } + /** + * Tells the script loader to load the scripts and styles of custom blocks + * if the widgets block editor is enabled. + * + * @since 5.8.0 + * + * @param bool $is_block_editor_screen Current decision about loading block assets. + * @return bool Filtered decision about loading block assets. + */ + public function should_load_block_editor_scripts_and_styles($is_block_editor_screen) + { + } + /** + * When previewing, ensures the proper previewing widgets are used. + * + * Because wp_get_sidebars_widgets() gets called early at {@see 'init' } (via + * wp_convert_widget_settings()) and can set global variable `$_wp_sidebars_widgets` + * to the value of `get_option( 'sidebars_widgets' )` before the Customizer preview + * filter is added, it has to be reset after the filter has been added. + * + * @since 3.9.0 + * + * @param array $sidebars_widgets List of widgets for the current sidebar. + * @return array + */ + public function preview_sidebars_widgets($sidebars_widgets) + { + } + /** + * Enqueues scripts for the Customizer preview. + * + * @since 3.9.0 + */ + public function customize_preview_enqueue() + { + } + /** + * Inserts default style for highlighted widget at early point so theme + * stylesheet can override. + * + * @since 3.9.0 + */ + public function print_preview_css() + { + } + /** + * Communicates the sidebars that appeared on the page at the very end of the page, + * and at the very end of the wp_footer, + * + * @since 3.9.0 + * + * @global array $wp_registered_sidebars + * @global array $wp_registered_widgets + */ + public function export_preview_data() + { + } + /** + * Tracks the widgets that were rendered. + * + * @since 3.9.0 + * + * @param array $widget Rendered widget to tally. + */ + public function tally_rendered_widgets($widget) + { + } + /** + * Determine if a widget is rendered on the page. + * + * @since 4.0.0 + * + * @param string $widget_id Widget ID to check. + * @return bool Whether the widget is rendered. + */ + public function is_widget_rendered($widget_id) + { + } + /** + * Determines if a sidebar is rendered on the page. + * + * @since 4.0.0 + * + * @param string $sidebar_id Sidebar ID to check. + * @return bool Whether the sidebar is rendered. + */ + public function is_sidebar_rendered($sidebar_id) + { + } + /** + * Tallies the sidebars rendered via is_active_sidebar(). + * + * Keep track of the times that is_active_sidebar() is called in the template, + * and assume that this means that the sidebar would be rendered on the template + * if there were widgets populating it. + * + * @since 3.9.0 + * + * @param bool $is_active Whether the sidebar is active. + * @param string $sidebar_id Sidebar ID. + * @return bool Whether the sidebar is active. + */ + public function tally_sidebars_via_is_active_sidebar_calls($is_active, $sidebar_id) + { + } + /** + * Tallies the sidebars rendered via dynamic_sidebar(). + * + * Keep track of the times that dynamic_sidebar() is called in the template, + * and assume this means the sidebar would be rendered on the template if + * there were widgets populating it. + * + * @since 3.9.0 + * + * @param bool $has_widgets Whether the current sidebar has widgets. + * @param string $sidebar_id Sidebar ID. + * @return bool Whether the current sidebar has widgets. + */ + public function tally_sidebars_via_dynamic_sidebar_calls($has_widgets, $sidebar_id) + { + } + /** + * Sanitizes a widget instance. + * + * Unserialize the JS-instance for storing in the options. It's important that this filter + * only get applied to an instance *once*. + * + * @since 3.9.0 + * @since 5.8.0 Added the `$id_base` parameter. + * + * @global WP_Widget_Factory $wp_widget_factory + * + * @param array $value Widget instance to sanitize. + * @param string $id_base Optional. Base of the ID of the widget being sanitized. Default null. + * @return array|void Sanitized widget instance. + */ + public function sanitize_widget_instance($value, $id_base = \null) + { + } + /** + * Converts a widget instance into JSON-representable format. + * + * @since 3.9.0 + * @since 5.8.0 Added the `$id_base` parameter. + * + * @global WP_Widget_Factory $wp_widget_factory + * + * @param array $value Widget instance to convert to JSON. + * @param string $id_base Optional. Base of the ID of the widget being sanitized. Default null. + * @return array JSON-converted widget instance. + */ + public function sanitize_widget_js_instance($value, $id_base = \null) + { + } + /** + * Strips out widget IDs for widgets which are no longer registered. + * + * One example where this might happen is when a plugin orphans a widget + * in a sidebar upon deactivation. + * + * @since 3.9.0 + * + * @global array $wp_registered_widgets + * + * @param array $widget_ids List of widget IDs. + * @return array Parsed list of widget IDs. + */ + public function sanitize_sidebar_widgets_js_instance($widget_ids) + { + } + /** + * Finds and invokes the widget update and control callbacks. + * + * Requires that `$_POST` be populated with the instance data. + * + * @since 3.9.0 + * + * @global array $wp_registered_widget_updates + * @global array $wp_registered_widget_controls + * + * @param string $widget_id Widget ID. + * @return array|WP_Error Array containing the updated widget information. + * A WP_Error object, otherwise. + */ + public function call_widget_update($widget_id) + { + } + /** + * Updates widget settings asynchronously. + * + * Allows the Customizer to update a widget using its form, but return the new + * instance info via Ajax instead of saving it to the options table. + * + * Most code here copied from wp_ajax_save_widget(). + * + * @since 3.9.0 + * + * @see wp_ajax_save_widget() + */ + public function wp_ajax_update_widget() + { + } + /* + * Selective Refresh Methods + */ + /** + * Filters arguments for dynamic widget partials. + * + * @since 4.5.0 + * + * @param array|false $partial_args Partial arguments. + * @param string $partial_id Partial ID. + * @return array (Maybe) modified partial arguments. + */ + public function customize_dynamic_partial_args($partial_args, $partial_id) + { + } + /** + * Adds hooks for selective refresh. + * + * @since 4.5.0 + */ + public function selective_refresh_init() + { + } + /** + * Inject selective refresh data attributes into widget container elements. + * + * @since 4.5.0 + * + * @param array $params { + * Dynamic sidebar params. + * + * @type array $args Sidebar args. + * @type array $widget_args Widget args. + * } + * @see WP_Customize_Nav_Menus::filter_wp_nav_menu_args() + * + * @return array Params. + * @phpstan-param array{ + * args?: array, + * widget_args?: array, + * } $params + */ + public function filter_dynamic_sidebar_params($params) + { + } + /** + * Ensures the HTML data-* attributes for selective refresh are allowed by kses. + * + * This is needed in case the `$before_widget` is run through wp_kses() when printed. + * + * @since 4.5.0 + * + * @param array $allowed_html Allowed HTML. + * @return array (Maybe) modified allowed HTML. + */ + public function filter_wp_kses_allowed_data_attributes($allowed_html) + { + } + /** + * Begins keeping track of the current sidebar being rendered. + * + * Insert marker before widgets are rendered in a dynamic sidebar. + * + * @since 4.5.0 + * + * @param int|string $index Index, name, or ID of the dynamic sidebar. + */ + public function start_dynamic_sidebar($index) + { + } + /** + * Finishes keeping track of the current sidebar being rendered. + * + * Inserts a marker after widgets are rendered in a dynamic sidebar. + * + * @since 4.5.0 + * + * @param int|string $index Index, name, or ID of the dynamic sidebar. + */ + public function end_dynamic_sidebar($index) + { + } + /** + * Filters sidebars_widgets to ensure the currently-rendered widget is the only widget in the current sidebar. + * + * @since 4.5.0 + * + * @param array $sidebars_widgets Sidebars widgets. + * @return array Filtered sidebars widgets. + */ + public function filter_sidebars_widgets_for_rendering_widget($sidebars_widgets) + { + } + /** + * Renders a specific widget using the supplied sidebar arguments. + * + * @since 4.5.0 + * + * @see dynamic_sidebar() + * + * @param WP_Customize_Partial $partial Partial. + * @param array $context { + * Sidebar args supplied as container context. + * + * @type string $sidebar_id ID for sidebar for widget to render into. + * @type int $sidebar_instance_number Disambiguating instance number. + * } + * @return string|false + * @phpstan-param array{ + * sidebar_id?: string, + * sidebar_instance_number?: int, + * } $context + */ + public function render_widget_partial($partial, $context) + { + } + /** + * Pre-filters captured option values before updating. + * + * @since 3.9.0 + * + * @param mixed $new_value The new option value. + * @param string $option_name Name of the option. + * @param mixed $old_value The old option value. + * @return mixed Filtered option value. + */ + public function capture_filter_pre_update_option($new_value, $option_name, $old_value) + { + } + /** + * Pre-filters captured option values before retrieving. + * + * @since 3.9.0 + * + * @param mixed $value Value to return instead of the option value. + * @return mixed Filtered option value. + */ + public function capture_filter_pre_get_option($value) + { + } + /** + * {@internal Missing Summary} + * + * See the {@see 'customize_dynamic_setting_args'} filter. + * + * @since 3.9.0 + * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. + */ + public function setup_widget_addition_previews() + { + } + /** + * {@internal Missing Summary} + * + * See the {@see 'customize_dynamic_setting_args'} filter. + * + * @since 3.9.0 + * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. + */ + public function prepreview_added_sidebars_widgets() + { + } + /** + * {@internal Missing Summary} + * + * See the {@see 'customize_dynamic_setting_args'} filter. + * + * @since 3.9.0 + * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. + */ + public function prepreview_added_widget_instance() + { + } + /** + * {@internal Missing Summary} + * + * See the {@see 'customize_dynamic_setting_args'} filter. + * + * @since 3.9.0 + * @deprecated 4.2.0 Deprecated in favor of the {@see 'customize_dynamic_setting_args'} filter. + */ + public function remove_prepreview_filters() + { + } + } + /** + * Class for generating SQL clauses that filter a primary query according to date. + * + * WP_Date_Query is a helper that allows primary query classes, such as WP_Query, to filter + * their results by date columns, by generating `WHERE` subclauses to be attached to the + * primary SQL query string. + * + * Attempting to filter by an invalid date value (eg month=13) will generate SQL that will + * return no results. In these cases, a _doing_it_wrong() error notice is also thrown. + * See WP_Date_Query::validate_date_values(). + * + * @link https://developer.wordpress.org/reference/classes/wp_query/ + * + * @since 3.7.0 + */ + #[\AllowDynamicProperties] + class WP_Date_Query + { + /** + * Array of date queries. + * + * See WP_Date_Query::__construct() for information on date query arguments. + * + * @since 3.7.0 + * @var array + */ + public $queries = array(); + /** + * The default relation between top-level queries. Can be either 'AND' or 'OR'. + * + * @since 3.7.0 + * @var string + */ + public $relation = 'AND'; + /** + * The column to query against. Can be changed via the query arguments. + * + * @since 3.7.0 + * @var string + */ + public $column = 'post_date'; + /** + * The value comparison operator. Can be changed via the query arguments. + * + * @since 3.7.0 + * @var string + */ + public $compare = '='; + /** + * Supported time-related parameter keys. + * + * @since 4.1.0 + * @var string[] + */ + public $time_keys = array('after', 'before', 'year', 'month', 'monthnum', 'week', 'w', 'dayofyear', 'day', 'dayofweek', 'dayofweek_iso', 'hour', 'minute', 'second'); + /** + * Constructor. + * + * Time-related parameters that normally require integer values ('year', 'month', 'week', 'dayofyear', 'day', + * 'dayofweek', 'dayofweek_iso', 'hour', 'minute', 'second') accept arrays of integers for some values of + * 'compare'. When 'compare' is 'IN' or 'NOT IN', arrays are accepted; when 'compare' is 'BETWEEN' or 'NOT + * BETWEEN', arrays of two valid values are required. See individual argument descriptions for accepted values. + * + * @since 3.7.0 + * @since 4.0.0 The $inclusive logic was updated to include all times within the date range. + * @since 4.1.0 Introduced 'dayofweek_iso' time type parameter. + * + * @param array $date_query { + * Array of date query clauses. + * + * @type array ...$0 { + * @type string $column Optional. The column to query against. If undefined, inherits the value of + * the `$default_column` parameter. See WP_Date_Query::validate_column() and + * the {@see 'date_query_valid_columns'} filter for the list of accepted values. + * Default 'post_date'. + * @type string $compare Optional. The comparison operator. Accepts '=', '!=', '>', '>=', '<', '<=', + * 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'. Default '='. + * @type string $relation Optional. The boolean relationship between the date queries. Accepts 'OR' or 'AND'. + * Default 'OR'. + * @type array ...$0 { + * Optional. An array of first-order clause parameters, or another fully-formed date query. + * + * @type string|array $before { + * Optional. Date to retrieve posts before. Accepts `strtotime()`-compatible string, + * or array of 'year', 'month', 'day' values. + * + * @type string $year The four-digit year. Default empty. Accepts any four-digit year. + * @type string $month Optional when passing array.The month of the year. + * Default (string:empty)|(array:1). Accepts numbers 1-12. + * @type string $day Optional when passing array.The day of the month. + * Default (string:empty)|(array:1). Accepts numbers 1-31. + * } + * @type string|array $after { + * Optional. Date to retrieve posts after. Accepts `strtotime()`-compatible string, + * or array of 'year', 'month', 'day' values. + * + * @type string $year The four-digit year. Accepts any four-digit year. Default empty. + * @type string $month Optional when passing array. The month of the year. Accepts numbers 1-12. + * Default (string:empty)|(array:12). + * @type string $day Optional when passing array.The day of the month. Accepts numbers 1-31. + * Default (string:empty)|(array:last day of month). + * } + * @type string $column Optional. Used to add a clause comparing a column other than + * the column specified in the top-level `$column` parameter. + * See WP_Date_Query::validate_column() and + * the {@see 'date_query_valid_columns'} filter for the list + * of accepted values. Default is the value of top-level `$column`. + * @type string $compare Optional. The comparison operator. Accepts '=', '!=', '>', '>=', + * '<', '<=', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'. 'IN', + * 'NOT IN', 'BETWEEN', and 'NOT BETWEEN'. Comparisons support + * arrays in some time-related parameters. Default '='. + * @type bool $inclusive Optional. Include results from dates specified in 'before' or + * 'after'. Default false. + * @type int|int[] $year Optional. The four-digit year number. Accepts any four-digit year + * or an array of years if `$compare` supports it. Default empty. + * @type int|int[] $month Optional. The two-digit month number. Accepts numbers 1-12 or an + * array of valid numbers if `$compare` supports it. Default empty. + * @type int|int[] $week Optional. The week number of the year. Accepts numbers 0-53 or an + * array of valid numbers if `$compare` supports it. Default empty. + * @type int|int[] $dayofyear Optional. The day number of the year. Accepts numbers 1-366 or an + * array of valid numbers if `$compare` supports it. + * @type int|int[] $day Optional. The day of the month. Accepts numbers 1-31 or an array + * of valid numbers if `$compare` supports it. Default empty. + * @type int|int[] $dayofweek Optional. The day number of the week. Accepts numbers 1-7 (1 is + * Sunday) or an array of valid numbers if `$compare` supports it. + * Default empty. + * @type int|int[] $dayofweek_iso Optional. The day number of the week (ISO). Accepts numbers 1-7 + * (1 is Monday) or an array of valid numbers if `$compare` supports it. + * Default empty. + * @type int|int[] $hour Optional. The hour of the day. Accepts numbers 0-23 or an array + * of valid numbers if `$compare` supports it. Default empty. + * @type int|int[] $minute Optional. The minute of the hour. Accepts numbers 0-59 or an array + * of valid numbers if `$compare` supports it. Default empty. + * @type int|int[] $second Optional. The second of the minute. Accepts numbers 0-59 or an + * array of valid numbers if `$compare` supports it. Default empty. + * } + * } + * } + * @param string $default_column Optional. Default column to query against. See WP_Date_Query::validate_column() + * and the {@see 'date_query_valid_columns'} filter for the list of accepted values. + * Default 'post_date'. + */ + public function __construct($date_query, $default_column = 'post_date') + { + } + /** + * Recursive-friendly query sanitizer. + * + * Ensures that each query-level clause has a 'relation' key, and that + * each first-order clause contains all the necessary keys from `$defaults`. + * + * @since 4.1.0 + * + * @param array $queries + * @param array $parent_query + * @return array Sanitized queries. + */ + public function sanitize_query($queries, $parent_query = \null) + { + } + /** + * Determines whether this is a first-order clause. + * + * Checks to see if the current clause has any time-related keys. + * If so, it's first-order. + * + * @since 4.1.0 + * + * @param array $query Query clause. + * @return bool True if this is a first-order clause. + */ + protected function is_first_order_clause($query) + { + } + /** + * Determines and validates what comparison operator to use. + * + * @since 3.7.0 + * + * @param array $query A date query or a date subquery. + * @return string The comparison operator. + */ + public function get_compare($query) + { + } + /** + * Validates the given date_query values and triggers errors if something is not valid. + * + * Note that date queries with invalid date ranges are allowed to + * continue (though of course no items will be found for impossible dates). + * This method only generates debug notices for these cases. + * + * @since 4.1.0 + * + * @param array $date_query The date_query array. + * @return bool True if all values in the query are valid, false if one or more fail. + */ + public function validate_date_values($date_query = array()) + { + } + /** + * Validates a column name parameter. + * + * Column names without a table prefix (like 'post_date') are checked against a list of + * allowed and known tables, and then, if found, have a table prefix (such as 'wp_posts.') + * prepended. Prefixed column names (such as 'wp_posts.post_date') bypass this allowed + * check, and are only sanitized to remove illegal characters. + * + * @since 3.7.0 + * + * @param string $column The user-supplied column name. + * @return string A validated column name value. + */ + public function validate_column($column) + { + } + /** + * Generates WHERE clause to be appended to a main query. + * + * @since 3.7.0 + * + * @return string MySQL WHERE clause. + */ + public function get_sql() + { + } + /** + * Generates SQL clauses to be appended to a main query. + * + * Called by the public WP_Date_Query::get_sql(), this method is abstracted + * out to maintain parity with the other Query classes. + * + * @since 4.1.0 + * + * @return string[] { + * Array containing JOIN and WHERE SQL clauses to append to the main query. + * + * @type string $join SQL fragment to append to the main JOIN clause. + * @type string $where SQL fragment to append to the main WHERE clause. + * } + * @phpstan-return array{ + * join: string, + * where: string, + * } + */ + protected function get_sql_clauses() + { + } + /** + * Generates SQL clauses for a single query array. + * + * If nested subqueries are found, this method recurses the tree to + * produce the properly nested SQL. + * + * @since 4.1.0 + * + * @param array $query Query to parse. + * @param int $depth Optional. Number of tree levels deep we currently are. + * Used to calculate indentation. Default 0. + * @return array { + * Array containing JOIN and WHERE SQL clauses to append to a single query array. + * + * @type string $join SQL fragment to append to the main JOIN clause. + * @type string $where SQL fragment to append to the main WHERE clause. + * } + * @phpstan-return array{ + * join: string, + * where: string, + * } + */ + protected function get_sql_for_query($query, $depth = 0) + { + } + /** + * Turns a single date clause into pieces for a WHERE clause. + * + * A wrapper for get_sql_for_clause(), included here for backward + * compatibility while retaining the naming convention across Query classes. + * + * @since 3.7.0 + * + * @param array $query Date query arguments. + * @return string[] { + * Array containing JOIN and WHERE SQL clauses to append to the main query. + * + * @type string $join SQL fragment to append to the main JOIN clause. + * @type string $where SQL fragment to append to the main WHERE clause. + * } + * @phpstan-return array{ + * join: string, + * where: string, + * } + */ + protected function get_sql_for_subquery($query) + { + } + /** + * Turns a first-order date query into SQL for a WHERE clause. + * + * @since 4.1.0 + * + * @param array $query Date query clause. + * @param array $parent_query Parent query of the current date query. + * @return string[] { + * Array containing JOIN and WHERE SQL clauses to append to the main query. + * + * @type string $join SQL fragment to append to the main JOIN clause. + * @type string $where SQL fragment to append to the main WHERE clause. + * } + * @phpstan-return array{ + * join: string, + * where: string, + * } + */ + protected function get_sql_for_clause($query, $parent_query) + { + } + /** + * Builds and validates a value string based on the comparison operator. + * + * @since 3.7.0 + * + * @param string $compare The compare operator to use. + * @param string|array $value The value. + * @return string|false|int The value to be used in SQL or false on error. + */ + public function build_value($compare, $value) + { + } + /** + * Builds a MySQL format date/time based on some query parameters. + * + * You can pass an array of values (year, month, etc.) with missing parameter values being defaulted to + * either the maximum or minimum values (controlled by the $default_to parameter). Alternatively you can + * pass a string that will be passed to date_create(). + * + * @since 3.7.0 + * + * @param string|array $datetime An array of parameters or a strotime() string. + * @param bool $default_to_max Whether to round up incomplete dates. Supported by values + * of $datetime that are arrays, or string values that are a + * subset of MySQL date format ('Y', 'Y-m', 'Y-m-d', 'Y-m-d H:i'). + * Default: false. + * @return string|false A MySQL format date/time or false on failure. + */ + public function build_mysql_datetime($datetime, $default_to_max = \false) + { + } + /** + * Builds a query string for comparing time values (hour, minute, second). + * + * If just hour, minute, or second is set than a normal comparison will be done. + * However if multiple values are passed, a pseudo-decimal time will be created + * in order to be able to accurately compare against. + * + * @since 3.7.0 + * + * @param string $column The column to query against. Needs to be pre-validated! + * @param string $compare The comparison operator. Needs to be pre-validated! + * @param int|null $hour Optional. An hour value (0-23). + * @param int|null $minute Optional. A minute value (0-59). + * @param int|null $second Optional. A second value (0-59). + * @return string|false A query part or false on failure. + */ + public function build_time_query($column, $compare, $hour = \null, $minute = \null, $second = \null) + { + } + /** + * Sanitizes a 'relation' operator. + * + * @since 6.0.3 + * + * @param string $relation Raw relation key from the query argument. + * @return string Sanitized relation ('AND' or 'OR'). + */ + public function sanitize_relation($relation) + { + } + } + /** + * Dependencies API: WP_Dependencies base class + * + * @since 2.6.0 + * + * @package WordPress + * @subpackage Dependencies + */ + /** + * Core base class extended to register items. + * + * @since 2.6.0 + * + * @see _WP_Dependency + */ + #[\AllowDynamicProperties] + class WP_Dependencies + { + /** + * An array of all registered dependencies keyed by handle. + * + * @since 2.6.8 + * + * @var _WP_Dependency[] + */ + public $registered = array(); + /** + * An array of handles of queued dependencies. + * + * @since 2.6.8 + * + * @var string[] + */ + public $queue = array(); + /** + * An array of handles of dependencies to queue. + * + * @since 2.6.0 + * + * @var string[] + */ + public $to_do = array(); + /** + * An array of handles of dependencies already queued. + * + * @since 2.6.0 + * + * @var string[] + */ + public $done = array(); + /** + * An array of additional arguments passed when a handle is registered. + * + * Arguments are appended to the item query string. + * + * @since 2.6.0 + * + * @var array + */ + public $args = array(); + /** + * An array of dependency groups to enqueue. + * + * Each entry is keyed by handle and represents the integer group level or boolean + * false if the handle has no group. + * + * @since 2.8.0 + * + * @var (int|false)[] + */ + public $groups = array(); + /** + * A handle group to enqueue. + * + * @since 2.8.0 + * + * @deprecated 4.5.0 + * @var int + */ + public $group = 0; + /** + * Processes the items and dependencies. + * + * Processes the items passed to it or the queue, and their dependencies. + * + * @since 2.6.0 + * @since 2.8.0 Added the `$group` parameter. + * + * @param string|string[]|false $handles Optional. Items to be processed: queue (false), + * single item (string), or multiple items (array of strings). + * Default false. + * @param int|false $group Optional. Group level: level (int), no group (false). + * @return string[] Array of handles of items that have been processed. + */ + public function do_items($handles = \false, $group = \false) + { + } + /** + * Processes a dependency. + * + * @since 2.6.0 + * @since 5.5.0 Added the `$group` parameter. + * + * @param string $handle Name of the item. Should be unique. + * @param int|false $group Optional. Group level: level (int), no group (false). + * Default false. + * @return bool True on success, false if not set. + */ + public function do_item($handle, $group = \false) + { + } + /** + * Determines dependencies. + * + * Recursively builds an array of items to process taking + * dependencies into account. Does NOT catch infinite loops. + * + * @since 2.1.0 + * @since 2.6.0 Moved from `WP_Scripts`. + * @since 2.8.0 Added the `$group` parameter. + * + * @param string|string[] $handles Item handle (string) or item handles (array of strings). + * @param bool $recursion Optional. Internal flag that function is calling itself. + * Default false. + * @param int|false $group Optional. Group level: level (int), no group (false). + * Default false. + * @return bool True on success, false on failure. + */ + public function all_deps($handles, $recursion = \false, $group = \false) + { + } + /** + * Register an item. + * + * Registers the item if no item of that name already exists. + * + * @since 2.1.0 + * @since 2.6.0 Moved from `WP_Scripts`. + * + * @param string $handle Name of the item. Should be unique. + * @param string|false $src Full URL of the item, or path of the item relative + * to the WordPress root directory. If source is set to false, + * item is an alias of other items it depends on. + * @param string[] $deps Optional. An array of registered item handles this item depends on. + * Default empty array. + * @param string|bool|null $ver Optional. String specifying item version number, if it has one, + * which is added to the URL as a query string for cache busting purposes. + * If version is set to false, a version number is automatically added + * equal to current installed WordPress version. + * If set to null, no version is added. + * @param mixed $args Optional. Custom property of the item. NOT the class property $args. + * Examples: $media, $in_footer. + * @return bool Whether the item has been registered. True on success, false on failure. + */ + public function add($handle, $src, $deps = array(), $ver = \false, $args = \null) + { + } + /** + * Add extra item data. + * + * Adds data to a registered item. + * + * @since 2.6.0 + * + * @param string $handle Name of the item. Should be unique. + * @param string $key The data key. + * @param mixed $value The data value. + * @return bool True on success, false on failure. + */ + public function add_data($handle, $key, $value) + { + } + /** + * Get extra item data. + * + * Gets data associated with a registered item. + * + * @since 3.3.0 + * + * @param string $handle Name of the item. Should be unique. + * @param string $key The data key. + * @return mixed Extra item data (string), false otherwise. + */ + public function get_data($handle, $key) + { + } + /** + * Un-register an item or items. + * + * @since 2.1.0 + * @since 2.6.0 Moved from `WP_Scripts`. + * + * @param string|string[] $handles Item handle (string) or item handles (array of strings). + */ + public function remove($handles) + { + } + /** + * Queue an item or items. + * + * Decodes handles and arguments, then queues handles and stores + * arguments in the class property $args. For example in extending + * classes, $args is appended to the item url as a query string. + * Note $args is NOT the $args property of items in the $registered array. + * + * @since 2.1.0 + * @since 2.6.0 Moved from `WP_Scripts`. + * + * @param string|string[] $handles Item handle (string) or item handles (array of strings). + */ + public function enqueue($handles) + { + } + /** + * Dequeue an item or items. + * + * Decodes handles and arguments, then dequeues handles + * and removes arguments from the class property $args. + * + * @since 2.1.0 + * @since 2.6.0 Moved from `WP_Scripts`. + * + * @param string|string[] $handles Item handle (string) or item handles (array of strings). + */ + public function dequeue($handles) + { + } + /** + * Recursively search the passed dependency tree for a handle. + * + * @since 4.0.0 + * + * @param string[] $queue An array of queued _WP_Dependency handles. + * @param string $handle Name of the item. Should be unique. + * @return bool Whether the handle is found after recursively searching the dependency tree. + */ + protected function recurse_deps($queue, $handle) + { + } + /** + * Query the list for an item. + * + * @since 2.1.0 + * @since 2.6.0 Moved from `WP_Scripts`. + * + * @param string $handle Name of the item. Should be unique. + * @param string $status Optional. Status of the item to query. Default 'registered'. + * @return bool|_WP_Dependency Found, or object Item data. + */ + public function query($handle, $status = 'registered') + { + } + /** + * Set item group, unless already in a lower group. + * + * @since 2.8.0 + * + * @param string $handle Name of the item. Should be unique. + * @param bool $recursion Internal flag that calling function was called recursively. + * @param int|false $group Group level: level (int), no group (false). + * @return bool Not already in the group or a lower group. + */ + public function set_group($handle, $recursion, $group) + { + } + } + /** + * Dependencies API: _WP_Dependency class + * + * @since 4.7.0 + * + * @package WordPress + * @subpackage Dependencies + */ + /** + * Class _WP_Dependency + * + * Helper class to register a handle and associated data. + * + * @access private + * @since 2.6.0 + */ + #[\AllowDynamicProperties] + class _WP_Dependency + { + /** + * The handle name. + * + * @since 2.6.0 + * @var string + */ + public $handle; + /** + * The handle source. + * + * @since 2.6.0 + * @var string + */ + public $src; + /** + * An array of handle dependencies. + * + * @since 2.6.0 + * @var string[] + */ + public $deps = array(); + /** + * The handle version. + * + * Used for cache-busting. + * + * @since 2.6.0 + * @var bool|string + */ + public $ver = \false; + /** + * Additional arguments for the handle. + * + * @since 2.6.0 + * @var array + */ + public $args = \null; + // Custom property, such as $in_footer or $media. + /** + * Extra data to supply to the handle. + * + * @since 2.6.0 + * @var array + */ + public $extra = array(); + /** + * Translation textdomain set for this dependency. + * + * @since 5.0.0 + * @var string + */ + public $textdomain; + /** + * Translation path set for this dependency. + * + * @since 5.0.0 + * @var string + */ + public $translations_path; + /** + * Setup dependencies. + * + * @since 2.6.0 + * @since 5.3.0 Formalized the existing `...$args` parameter by adding it + * to the function signature. + * + * @param mixed ...$args Dependency information. + */ + public function __construct(...$args) + { + } + /** + * Add handle data. + * + * @since 2.6.0 + * + * @param string $name The data key to add. + * @param mixed $data The data value to add. + * @return bool False if not scalar, true otherwise. + */ + public function add_data($name, $data) + { + } + /** + * Sets the translation domain for this dependency. + * + * @since 5.0.0 + * + * @param string $domain The translation textdomain. + * @param string $path Optional. The full file path to the directory containing translation files. + * @return bool False if $domain is not a string, true otherwise. + */ + public function set_translations($domain, $path = '') + { + } + } + /** + * Facilitates adding of the WordPress editor as used on the Write and Edit screens. + * + * @package WordPress + * @since 3.3.0 + * + * Private, not included by default. See wp_editor() in wp-includes/general-template.php. + */ + #[\AllowDynamicProperties] + final class _WP_Editors + { + public static $mce_locale; + /** + * Parse default arguments for the editor instance. + * + * @since 3.3.0 + * + * @param string $editor_id HTML ID for the textarea and TinyMCE and Quicktags instances. + * Should not contain square brackets. + * @param array $settings { + * Array of editor arguments. + * + * @type bool $wpautop Whether to use wpautop(). Default true. + * @type bool $media_buttons Whether to show the Add Media/other media buttons. + * @type string $default_editor When both TinyMCE and Quicktags are used, set which + * editor is shown on page load. Default empty. + * @type bool $drag_drop_upload Whether to enable drag & drop on the editor uploading. Default false. + * Requires the media modal. + * @type string $textarea_name Give the textarea a unique name here. Square brackets + * can be used here. Default $editor_id. + * @type int $textarea_rows Number rows in the editor textarea. Default 20. + * @type string|int $tabindex Tabindex value to use. Default empty. + * @type string $tabfocus_elements The previous and next element ID to move the focus to + * when pressing the Tab key in TinyMCE. Default ':prev,:next'. + * @type string $editor_css Intended for extra styles for both Visual and Text editors. + * Should include `<style>` tags, and can use "scoped". Default empty. + * @type string $editor_class Extra classes to add to the editor textarea element. Default empty. + * @type bool $teeny Whether to output the minimal editor config. Examples include + * Press This and the Comment editor. Default false. + * @type bool $dfw Deprecated in 4.1. Unused. + * @type bool|array $tinymce Whether to load TinyMCE. Can be used to pass settings directly to + * TinyMCE using an array. Default true. + * @type bool|array $quicktags Whether to load Quicktags. Can be used to pass settings directly to + * Quicktags using an array. Default true. + * } + * @return array Parsed arguments array. + * @phpstan-param array{ + * wpautop?: bool, + * media_buttons?: bool, + * default_editor?: string, + * drag_drop_upload?: bool, + * textarea_name?: string, + * textarea_rows?: int, + * tabindex?: string|int, + * tabfocus_elements?: string, + * editor_css?: string, + * editor_class?: string, + * teeny?: bool, + * dfw?: bool, + * tinymce?: bool|array, + * quicktags?: bool|array, + * } $settings + */ + public static function parse_settings($editor_id, $settings) + { + } + /** + * Outputs the HTML for a single instance of the editor. + * + * @since 3.3.0 + * + * @param string $content Initial content for the editor. + * @param string $editor_id HTML ID for the textarea and TinyMCE and Quicktags instances. + * Should not contain square brackets. + * @param array $settings See _WP_Editors::parse_settings() for description. + * @phpstan-param array{ + * wpautop?: bool, + * media_buttons?: bool, + * default_editor?: string, + * drag_drop_upload?: bool, + * textarea_name?: string, + * textarea_rows?: int, + * tabindex?: string|int, + * tabfocus_elements?: string, + * editor_css?: string, + * editor_class?: string, + * teeny?: bool, + * dfw?: bool, + * tinymce?: bool|array, + * quicktags?: bool|array, + * } $settings See _WP_Editors::parse_settings() + */ + public static function editor($content, $editor_id, $settings = array()) + { + } + /** + * @since 3.3.0 + * + * @param string $editor_id Unique editor identifier, e.g. 'content'. + * @param array $set Array of editor arguments. + */ + public static function editor_settings($editor_id, $set) + { + } + /** + * @since 3.3.0 + * + * @param bool $default_scripts Optional. Whether default scripts should be enqueued. Default false. + */ + public static function enqueue_scripts($default_scripts = \false) + { + } + /** + * Enqueue all editor scripts. + * For use when the editor is going to be initialized after page load. + * + * @since 4.8.0 + */ + public static function enqueue_default_editor() + { + } + /** + * Print (output) all editor scripts and default settings. + * For use when the editor is going to be initialized after page load. + * + * @since 4.8.0 + */ + public static function print_default_editor_scripts() + { + } + /** + * Returns the TinyMCE locale. + * + * @since 4.8.0 + * + * @return string + */ + public static function get_mce_locale() + { + } + /** + * Returns the TinyMCE base URL. + * + * @since 4.8.0 + * + * @return string + */ + public static function get_baseurl() + { + } + /** + * Translates the default TinyMCE strings and returns them as JSON encoded object ready to be loaded with tinymce.addI18n(), + * or as JS snippet that should run after tinymce.js is loaded. + * + * @since 3.9.0 + * + * @param string $mce_locale The locale used for the editor. + * @param bool $json_only Optional. Whether to include the JavaScript calls to tinymce.addI18n() and + * tinymce.ScriptLoader.markDone(). + * @return string Translation object, JSON encoded. + */ + public static function wp_mce_translation($mce_locale = '', $json_only = \false) + { + } + /** + * Force uncompressed TinyMCE when a custom theme has been defined. + * + * The compressed TinyMCE file cannot deal with custom themes, so this makes + * sure that we use the uncompressed TinyMCE file if a theme is defined. + * Even if we are on a production environment. + * + * @since 5.0.0 + */ + public static function force_uncompressed_tinymce() + { + } + /** + * Print (output) the main TinyMCE scripts. + * + * @since 4.8.0 + * + * @global bool $concatenate_scripts + */ + public static function print_tinymce_scripts() + { + } + /** + * Print (output) the TinyMCE configuration and initialization scripts. + * + * @since 3.3.0 + * + * @global string $tinymce_version + */ + public static function editor_js() + { + } + /** + * Outputs the HTML for distraction-free writing mode. + * + * @since 3.2.0 + * @deprecated 4.3.0 + */ + public static function wp_fullscreen_html() + { + } + /** + * Performs post queries for internal linking. + * + * @since 3.1.0 + * + * @param array $args Optional. Accepts 'pagenum' and 's' (search) arguments. + * @return array|false $results { + * An array of associative arrays of query results, false if there are none. + * + * @type array ...$0 { + * @type int $ID Post ID. + * @type string $title The trimmed, escaped post title. + * @type string $permalink Post permalink. + * @type string $info A 'Y/m/d'-formatted date for 'post' post type, + * the 'singular_name' post type label otherwise. + * } + * } + * @phpstan-return false|array<int|string, array{ + * ID: int, + * title: string, + * permalink: string, + * info: string, + * }> + */ + public static function wp_link_query($args = array()) + { + } + /** + * Dialog for internal linking. + * + * @since 3.1.0 + */ + public static function wp_link_dialog() + { + } + } + /** + * API for easily embedding rich media such as videos and images into content. + * + * @package WordPress + * @subpackage Embed + * @since 2.9.0 + */ + #[\AllowDynamicProperties] + class WP_Embed + { + public $handlers = array(); + public $post_ID; + public $usecache = \true; + public $linkifunknown = \true; + public $last_attr = array(); + public $last_url = ''; + /** + * When a URL cannot be embedded, return false instead of returning a link + * or the URL. + * + * Bypasses the {@see 'embed_maybe_make_link'} filter. + * + * @var bool + */ + public $return_false_on_fail = \false; + /** + * Constructor + */ + public function __construct() + { + } + /** + * Processes the [embed] shortcode. + * + * Since the [embed] shortcode needs to be run earlier than other shortcodes, + * this function removes all existing shortcodes, registers the [embed] shortcode, + * calls do_shortcode(), and then re-registers the old shortcodes. + * + * @global array $shortcode_tags + * + * @param string $content Content to parse. + * @return string Content with shortcode parsed. + */ + public function run_shortcode($content) + { + } + /** + * If a post/page was saved, then output JavaScript to make + * an Ajax request that will call WP_Embed::cache_oembed(). + */ + public function maybe_run_ajax_cache() + { + } + /** + * Registers an embed handler. + * + * Do not use this function directly, use wp_embed_register_handler() instead. + * + * This function should probably also only be used for sites that do not support oEmbed. + * + * @param string $id An internal ID/name for the handler. Needs to be unique. + * @param string $regex The regex that will be used to see if this handler should be used for a URL. + * @param callable $callback The callback function that will be called if the regex is matched. + * @param int $priority Optional. Used to specify the order in which the registered handlers will be tested. + * Lower numbers correspond with earlier testing, and handlers with the same priority are + * tested in the order in which they were added to the action. Default 10. + */ + public function register_handler($id, $regex, $callback, $priority = 10) + { + } + /** + * Unregisters a previously-registered embed handler. + * + * Do not use this function directly, use wp_embed_unregister_handler() instead. + * + * @param string $id The handler ID that should be removed. + * @param int $priority Optional. The priority of the handler to be removed (default: 10). + */ + public function unregister_handler($id, $priority = 10) + { + } + /** + * Returns embed HTML for a given URL from embed handlers. + * + * Attempts to convert a URL into embed HTML by checking the URL + * against the regex of the registered embed handlers. + * + * @since 5.5.0 + * + * @param array $attr { + * Shortcode attributes. Optional. + * + * @type int $width Width of the embed in pixels. + * @type int $height Height of the embed in pixels. + * } + * @param string $url The URL attempting to be embedded. + * @return string|false The embed HTML on success, false otherwise. + * @phpstan-param array{ + * width?: int, + * height?: int, + * } $attr + */ + public function get_embed_handler_html($attr, $url) + { + } + /** + * The do_shortcode() callback function. + * + * Attempts to convert a URL into embed HTML. Starts by checking the URL against the regex of + * the registered embed handlers. If none of the regex matches and it's enabled, then the URL + * will be given to the WP_oEmbed class. + * + * @param array $attr { + * Shortcode attributes. Optional. + * + * @type int $width Width of the embed in pixels. + * @type int $height Height of the embed in pixels. + * } + * @param string $url The URL attempting to be embedded. + * @return string|false The embed HTML on success, otherwise the original URL. + * `->maybe_make_link()` can return false on failure. + * @phpstan-param array{ + * width?: int, + * height?: int, + * } $attr + */ + public function shortcode($attr, $url = '') + { + } + /** + * Deletes all oEmbed caches. Unused by core as of 4.0.0. + * + * @param int $post_ID Post ID to delete the caches for. + */ + public function delete_oembed_caches($post_ID) + { + } + /** + * Triggers a caching of all oEmbed results. + * + * @param int $post_ID Post ID to do the caching for. + */ + public function cache_oembed($post_ID) + { + } + /** + * Passes any unlinked URLs that are on their own line to WP_Embed::shortcode() for potential embedding. + * + * @see WP_Embed::autoembed_callback() + * + * @param string $content The content to be searched. + * @return string Potentially modified $content. + */ + public function autoembed($content) + { + } + /** + * Callback function for WP_Embed::autoembed(). + * + * @param array $matches A regex match array. + * @return string The embed HTML on success, otherwise the original URL. + */ + public function autoembed_callback($matches) + { + } + /** + * Conditionally makes a hyperlink based on an internal class variable. + * + * @param string $url URL to potentially be linked. + * @return string|false Linked URL or the original URL. False if 'return_false_on_fail' is true. + */ + public function maybe_make_link($url) + { + } + /** + * Finds the oEmbed cache post ID for a given cache key. + * + * @since 4.9.0 + * + * @param string $cache_key oEmbed cache key. + * @return int|null Post ID on success, null on failure. + */ + public function find_oembed_post_id($cache_key) + { + } + } + /** + * WordPress Error API. + * + * @package WordPress + */ + /** + * WordPress Error class. + * + * Container for checking for WordPress errors and error messages. Return + * WP_Error and use is_wp_error() to check if this class is returned. Many + * core WordPress functions pass this class in the event of an error and + * if not handled properly will result in code errors. + * + * @since 2.1.0 + */ + #[\AllowDynamicProperties] + class WP_Error + { + /** + * Stores the list of errors. + * + * @since 2.1.0 + * @var array + */ + public $errors = array(); + /** + * Stores the most recently added data for each error code. + * + * @since 2.1.0 + * @var array + */ + public $error_data = array(); + /** + * Stores previously added data added for error codes, oldest-to-newest by code. + * + * @since 5.6.0 + * @var array[] + */ + protected $additional_data = array(); + /** + * Initializes the error. + * + * If `$code` is empty, the other parameters will be ignored. + * When `$code` is not empty, `$message` will be used even if + * it is empty. The `$data` parameter will be used only if it + * is not empty. + * + * Though the class is constructed with a single error code and + * message, multiple codes can be added using the `add()` method. + * + * @since 2.1.0 + * + * @param string|int $code Error code. + * @param string $message Error message. + * @param mixed $data Optional. Error data. + */ + public function __construct($code = '', $message = '', $data = '') + { + } + /** + * Retrieves all error codes. + * + * @since 2.1.0 + * + * @return array List of error codes, if available. + */ + public function get_error_codes() + { + } + /** + * Retrieves the first error code available. + * + * @since 2.1.0 + * + * @return string|int Empty string, if no error codes. + */ + public function get_error_code() + { + } + /** + * Retrieves all error messages, or the error messages for the given error code. + * + * @since 2.1.0 + * + * @param string|int $code Optional. Retrieve messages matching code, if exists. + * @return string[] Error strings on success, or empty array if there are none. + */ + public function get_error_messages($code = '') + { + } + /** + * Gets a single error message. + * + * This will get the first message available for the code. If no code is + * given then the first code available will be used. + * + * @since 2.1.0 + * + * @param string|int $code Optional. Error code to retrieve message. + * @return string The error message. + */ + public function get_error_message($code = '') + { + } + /** + * Retrieves the most recently added error data for an error code. + * + * @since 2.1.0 + * + * @param string|int $code Optional. Error code. + * @return mixed Error data, if it exists. + */ + public function get_error_data($code = '') + { + } + /** + * Verifies if the instance contains errors. + * + * @since 5.1.0 + * + * @return bool If the instance contains errors. + */ + public function has_errors() + { + } + /** + * Adds an error or appends an additional message to an existing error. + * + * @since 2.1.0 + * + * @param string|int $code Error code. + * @param string $message Error message. + * @param mixed $data Optional. Error data. + */ + public function add($code, $message, $data = '') + { + } + /** + * Adds data to an error with the given code. + * + * @since 2.1.0 + * @since 5.6.0 Errors can now contain more than one item of error data. {@see WP_Error::$additional_data}. + * + * @param mixed $data Error data. + * @param string|int $code Error code. + */ + public function add_data($data, $code = '') + { + } + /** + * Retrieves all error data for an error code in the order in which the data was added. + * + * @since 5.6.0 + * + * @param string|int $code Error code. + * @return mixed[] Array of error data, if it exists. + */ + public function get_all_error_data($code = '') + { + } + /** + * Removes the specified error. + * + * This function removes all error messages associated with the specified + * error code, along with any error data for that code. + * + * @since 4.1.0 + * + * @param string|int $code Error code. + */ + public function remove($code) + { + } + /** + * Merges the errors in the given error object into this one. + * + * @since 5.6.0 + * + * @param WP_Error $error Error object to merge. + */ + public function merge_from(\WP_Error $error) + { + } + /** + * Exports the errors in this object into the given one. + * + * @since 5.6.0 + * + * @param WP_Error $error Error object to export into. + */ + public function export_to(\WP_Error $error) + { + } + /** + * Copies errors from one WP_Error instance to another. + * + * @since 5.6.0 + * + * @param WP_Error $from The WP_Error to copy from. + * @param WP_Error $to The WP_Error to copy to. + */ + protected static function copy_errors(\WP_Error $from, \WP_Error $to) + { + } + } + /** + * Error Protection API: WP_Fatal_Error_Handler class + * + * @package WordPress + * @since 5.2.0 + */ + /** + * Core class used as the default shutdown handler for fatal errors. + * + * A drop-in 'fatal-error-handler.php' can be used to override the instance of this class and use a custom + * implementation for the fatal error handler that WordPress registers. The custom class should extend this class and + * can override its methods individually as necessary. The file must return the instance of the class that should be + * registered. + * + * @since 5.2.0 + */ + #[\AllowDynamicProperties] + class WP_Fatal_Error_Handler + { + /** + * Runs the shutdown handler. + * + * This method is registered via `register_shutdown_function()`. + * + * @since 5.2.0 + */ + public function handle() + { + } + /** + * Detects the error causing the crash if it should be handled. + * + * @since 5.2.0 + * + * @return array|null Error information returned by `error_get_last()`, or null + * if none was recorded or the error should not be handled. + */ + protected function detect_error() + { + } + /** + * Determines whether we are dealing with an error that WordPress should handle + * in order to protect the admin backend against WSODs. + * + * @since 5.2.0 + * + * @param array $error Error information retrieved from `error_get_last()`. + * @return bool Whether WordPress should handle this error. + */ + protected function should_handle_error($error) + { + } + /** + * Displays the PHP error template and sends the HTTP status code, typically 500. + * + * A drop-in 'php-error.php' can be used as a custom template. This drop-in should control the HTTP status code and + * print the HTML markup indicating that a PHP error occurred. Note that this drop-in may potentially be executed + * very early in the WordPress bootstrap process, so any core functions used that are not part of + * `wp-includes/load.php` should be checked for before being called. + * + * If no such drop-in is available, this will call {@see WP_Fatal_Error_Handler::display_default_error_template()}. + * + * @since 5.2.0 + * @since 5.3.0 The `$handled` parameter was added. + * + * @param array $error Error information retrieved from `error_get_last()`. + * @param true|WP_Error $handled Whether Recovery Mode handled the fatal error. + */ + protected function display_error_template($error, $handled) + { + } + /** + * Displays the default PHP error template. + * + * This method is called conditionally if no 'php-error.php' drop-in is available. + * + * It calls {@see wp_die()} with a message indicating that the site is experiencing technical difficulties and a + * login link to the admin backend. The {@see 'wp_php_error_message'} and {@see 'wp_php_error_args'} filters can + * be used to modify these parameters. + * + * @since 5.2.0 + * @since 5.3.0 The `$handled` parameter was added. + * + * @param array $error Error information retrieved from `error_get_last()`. + * @param true|WP_Error $handled Whether Recovery Mode handled the fatal error. + */ + protected function display_default_error_template($error, $handled) + { + } + } + /** + * Feed API: WP_Feed_Cache_Transient class + * + * @package WordPress + * @subpackage Feed + * @since 4.7.0 + */ + /** + * Core class used to implement feed cache transients. + * + * @since 2.8.0 + */ + #[\AllowDynamicProperties] + class WP_Feed_Cache_Transient + { + /** + * Holds the transient name. + * + * @since 2.8.0 + * @var string + */ + public $name; + /** + * Holds the transient mod name. + * + * @since 2.8.0 + * @var string + */ + public $mod_name; + /** + * Holds the cache duration in seconds. + * + * Defaults to 43200 seconds (12 hours). + * + * @since 2.8.0 + * @var int + */ + public $lifetime = 43200; + /** + * Constructor. + * + * @since 2.8.0 + * @since 3.2.0 Updated to use a PHP5 constructor. + * + * @param string $location URL location (scheme is used to determine handler). + * @param string $filename Unique identifier for cache object. + * @param string $extension 'spi' or 'spc'. + */ + public function __construct($location, $filename, $extension) + { + } + /** + * Sets the transient. + * + * @since 2.8.0 + * + * @param SimplePie $data Data to save. + * @return true Always true. + */ + public function save($data) + { + } + /** + * Gets the transient. + * + * @since 2.8.0 + * + * @return mixed Transient value. + */ + public function load() + { + } + /** + * Gets mod transient. + * + * @since 2.8.0 + * + * @return mixed Transient value. + */ + public function mtime() + { + } + /** + * Sets mod transient. + * + * @since 2.8.0 + * + * @return bool False if value was not set and true if value was set. + */ + public function touch() + { + } + /** + * Deletes transients. + * + * @since 2.8.0 + * + * @return true Always true. + */ + public function unlink() + { + } + } + /** + * Core class used to implement a feed cache. + * + * @since 2.8.0 + * + * @see SimplePie_Cache + */ + #[\AllowDynamicProperties] + class WP_Feed_Cache extends \SimplePie_Cache + { + /** + * Creates a new SimplePie_Cache object. + * + * @since 2.8.0 + * + * @param string $location URL location (scheme is used to determine handler). + * @param string $filename Unique identifier for cache object. + * @param string $extension 'spi' or 'spc'. + * @return WP_Feed_Cache_Transient Feed cache handler object that uses transients. + */ + public function create($location, $filename, $extension) + { + } + } + /** + * Plugin API: WP_Hook class + * + * @package WordPress + * @subpackage Plugin + * @since 4.7.0 + */ + /** + * Core class used to implement action and filter hook functionality. + * + * @since 4.7.0 + * + * @see Iterator + * @see ArrayAccess + */ + #[\AllowDynamicProperties] + final class WP_Hook implements \Iterator, \ArrayAccess + { + /** + * Hook callbacks. + * + * @since 4.7.0 + * @var array + */ + public $callbacks = array(); + /** + * Adds a callback function to a filter hook. + * + * @since 4.7.0 + * + * @param string $hook_name The name of the filter to add the callback to. + * @param callable $callback The callback to be run when the filter is applied. + * @param int $priority The order in which the functions associated with a particular filter + * are executed. Lower numbers correspond with earlier execution, + * and functions with the same priority are executed in the order + * in which they were added to the filter. + * @param int $accepted_args The number of arguments the function accepts. + */ + public function add_filter($hook_name, $callback, $priority, $accepted_args) + { + } + /** + * Removes a callback function from a filter hook. + * + * @since 4.7.0 + * + * @param string $hook_name The filter hook to which the function to be removed is hooked. + * @param callable|string|array $callback The callback to be removed from running when the filter is applied. + * This method can be called unconditionally to speculatively remove + * a callback that may or may not exist. + * @param int $priority The exact priority used when adding the original filter callback. + * @return bool Whether the callback existed before it was removed. + */ + public function remove_filter($hook_name, $callback, $priority) + { + } + /** + * Checks if a specific callback has been registered for this hook. + * + * When using the `$callback` argument, this function may return a non-boolean value + * that evaluates to false (e.g. 0), so use the `===` operator for testing the return value. + * + * @since 4.7.0 + * + * @param string $hook_name Optional. The name of the filter hook. Default empty. + * @param callable|string|array|false $callback Optional. The callback to check for. + * This method can be called unconditionally to speculatively check + * a callback that may or may not exist. Default false. + * @return bool|int If `$callback` is omitted, returns boolean for whether the hook has + * anything registered. When checking a specific function, the priority + * of that hook is returned, or false if the function is not attached. + */ + public function has_filter($hook_name = '', $callback = \false) + { + } + /** + * Checks if any callbacks have been registered for this hook. + * + * @since 4.7.0 + * + * @return bool True if callbacks have been registered for the current hook, otherwise false. + */ + public function has_filters() + { + } + /** + * Removes all callbacks from the current filter. + * + * @since 4.7.0 + * + * @param int|false $priority Optional. The priority number to remove. Default false. + */ + public function remove_all_filters($priority = \false) + { + } + /** + * Calls the callback functions that have been added to a filter hook. + * + * @since 4.7.0 + * + * @param mixed $value The value to filter. + * @param array $args Additional parameters to pass to the callback functions. + * This array is expected to include $value at index 0. + * @return mixed The filtered value after all hooked functions are applied to it. + */ + public function apply_filters($value, $args) + { + } + /** + * Calls the callback functions that have been added to an action hook. + * + * @since 4.7.0 + * + * @param array $args Parameters to pass to the callback functions. + */ + public function do_action($args) + { + } + /** + * Processes the functions hooked into the 'all' hook. + * + * @since 4.7.0 + * + * @param array $args Arguments to pass to the hook callbacks. Passed by reference. + */ + public function do_all_hook(&$args) + { + } + /** + * Return the current priority level of the currently running iteration of the hook. + * + * @since 4.7.0 + * + * @return int|false If the hook is running, return the current priority level. + * If it isn't running, return false. + */ + public function current_priority() + { + } + /** + * Normalizes filters set up before WordPress has initialized to WP_Hook objects. + * + * The `$filters` parameter should be an array keyed by hook name, with values + * containing either: + * + * - A `WP_Hook` instance + * - An array of callbacks keyed by their priorities + * + * Examples: + * + * $filters = array( + * 'wp_fatal_error_handler_enabled' => array( + * 10 => array( + * array( + * 'accepted_args' => 0, + * 'function' => function() { + * return false; + * }, + * ), + * ), + * ), + * ); + * + * @since 4.7.0 + * + * @param array $filters Filters to normalize. See documentation above for details. + * @return WP_Hook[] Array of normalized filters. + */ + public static function build_preinitialized_hooks($filters) + { + } + /** + * Determines whether an offset value exists. + * + * @since 4.7.0 + * + * @link https://www.php.net/manual/en/arrayaccess.offsetexists.php + * + * @param mixed $offset An offset to check for. + * @return bool True if the offset exists, false otherwise. + */ + #[\ReturnTypeWillChange] + public function offsetExists($offset) + { + } + /** + * Retrieves a value at a specified offset. + * + * @since 4.7.0 + * + * @link https://www.php.net/manual/en/arrayaccess.offsetget.php + * + * @param mixed $offset The offset to retrieve. + * @return mixed If set, the value at the specified offset, null otherwise. + */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + } + /** + * Sets a value at a specified offset. + * + * @since 4.7.0 + * + * @link https://www.php.net/manual/en/arrayaccess.offsetset.php + * + * @param mixed $offset The offset to assign the value to. + * @param mixed $value The value to set. + */ + #[\ReturnTypeWillChange] + public function offsetSet($offset, $value) + { + } + /** + * Unsets a specified offset. + * + * @since 4.7.0 + * + * @link https://www.php.net/manual/en/arrayaccess.offsetunset.php + * + * @param mixed $offset The offset to unset. + */ + #[\ReturnTypeWillChange] + public function offsetUnset($offset) + { + } + /** + * Returns the current element. + * + * @since 4.7.0 + * + * @link https://www.php.net/manual/en/iterator.current.php + * + * @return array Of callbacks at current priority. + */ + #[\ReturnTypeWillChange] + public function current() + { + } + /** + * Moves forward to the next element. + * + * @since 4.7.0 + * + * @link https://www.php.net/manual/en/iterator.next.php + * + * @return array Of callbacks at next priority. + */ + #[\ReturnTypeWillChange] + public function next() + { + } + /** + * Returns the key of the current element. + * + * @since 4.7.0 + * + * @link https://www.php.net/manual/en/iterator.key.php + * + * @return mixed Returns current priority on success, or NULL on failure + */ + #[\ReturnTypeWillChange] + public function key() + { + } + /** + * Checks if current position is valid. + * + * @since 4.7.0 + * + * @link https://www.php.net/manual/en/iterator.valid.php + * + * @return bool Whether the current position is valid. + */ + #[\ReturnTypeWillChange] + public function valid() + { + } + /** + * Rewinds the Iterator to the first element. + * + * @since 4.7.0 + * + * @link https://www.php.net/manual/en/iterator.rewind.php + */ + #[\ReturnTypeWillChange] + public function rewind() + { + } + } + /** + * HTTP API: WP_Http_Cookie class + * + * @package WordPress + * @subpackage HTTP + * @since 4.4.0 + */ + /** + * Core class used to encapsulate a single cookie object for internal use. + * + * Returned cookies are represented using this class, and when cookies are set, if they are not + * already a WP_Http_Cookie() object, then they are turned into one. + * + * @todo The WordPress convention is to use underscores instead of camelCase for function and method + * names. Need to switch to use underscores instead for the methods. + * + * @since 2.8.0 + */ + #[\AllowDynamicProperties] + class WP_Http_Cookie + { + /** + * Cookie name. + * + * @since 2.8.0 + * + * @var string + */ + public $name; + /** + * Cookie value. + * + * @since 2.8.0 + * + * @var string + */ + public $value; + /** + * When the cookie expires. Unix timestamp or formatted date. + * + * @since 2.8.0 + * + * @var string|int|null + */ + public $expires; + /** + * Cookie URL path. + * + * @since 2.8.0 + * + * @var string + */ + public $path; + /** + * Cookie Domain. + * + * @since 2.8.0 + * + * @var string + */ + public $domain; + /** + * Cookie port or comma-separated list of ports. + * + * @since 2.8.0 + * + * @var int|string + */ + public $port; + /** + * host-only flag. + * + * @since 5.2.0 + * + * @var bool + */ + public $host_only; + /** + * Sets up this cookie object. + * + * The parameter $data should be either an associative array containing the indices names below + * or a header string detailing it. + * + * @since 2.8.0 + * @since 5.2.0 Added `host_only` to the `$data` parameter. + * + * @param string|array $data { + * Raw cookie data as header string or data array. + * + * @type string $name Cookie name. + * @type mixed $value Value. Should NOT already be urlencoded. + * @type string|int|null $expires Optional. Unix timestamp or formatted date. Default null. + * @type string $path Optional. Path. Default '/'. + * @type string $domain Optional. Domain. Default host of parsed $requested_url. + * @type int|string $port Optional. Port or comma-separated list of ports. Default null. + * @type bool $host_only Optional. host-only storage flag. Default true. + * } + * @param string $requested_url The URL which the cookie was set on, used for default $domain + * and $port values. + * @phpstan-param array{ + * name?: string, + * value?: mixed, + * expires?: string|int|null, + * path?: string, + * domain?: string, + * port?: int|string, + * host_only?: bool, + * } $data + */ + public function __construct($data, $requested_url = '') + { + } + /** + * Confirms that it's OK to send this cookie to the URL checked against. + * + * Decision is based on RFC 2109/2965, so look there for details on validity. + * + * @since 2.8.0 + * + * @param string $url URL you intend to send this cookie to + * @return bool true if allowed, false otherwise. + */ + public function test($url) + { + } + /** + * Convert cookie name and value back to header string. + * + * @since 2.8.0 + * + * @return string Header encoded cookie name and value. + */ + public function getHeaderValue() + { + } + /** + * Retrieve cookie header for usage in the rest of the WordPress HTTP API. + * + * @since 2.8.0 + * + * @return string + */ + public function getFullHeader() + { + } + /** + * Retrieves cookie attributes. + * + * @since 4.6.0 + * + * @return array { + * List of attributes. + * + * @type string|int|null $expires When the cookie expires. Unix timestamp or formatted date. + * @type string $path Cookie URL path. + * @type string $domain Cookie domain. + * } + * @phpstan-return array{ + * expires: string|int|null, + * path: string, + * domain: string, + * } + */ + public function get_attributes() + { + } + } + /** + * HTTP API: WP_Http_Curl class + * + * @package WordPress + * @subpackage HTTP + * @since 4.4.0 + */ + /** + * Core class used to integrate Curl as an HTTP transport. + * + * HTTP request method uses Curl extension to retrieve the url. + * + * Requires the Curl extension to be installed. + * + * @since 2.7.0 + */ + #[\AllowDynamicProperties] + class WP_Http_Curl + { + /** + * Send a HTTP request to a URI using cURL extension. + * + * @since 2.7.0 + * + * @param string $url The request URL. + * @param string|array $args Optional. Override the defaults. + * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error + */ + public function request($url, $args = array()) + { + } + /** + * Determines whether this class can be used for retrieving a URL. + * + * @since 2.7.0 + * + * @param array $args Optional. Array of request arguments. Default empty array. + * @return bool False means this class can not be used, true means it can. + */ + public static function test($args = array()) + { + } + } + /** + * HTTP API: WP_Http_Encoding class + * + * @package WordPress + * @subpackage HTTP + * @since 4.4.0 + */ + /** + * Core class used to implement deflate and gzip transfer encoding support for HTTP requests. + * + * Includes RFC 1950, RFC 1951, and RFC 1952. + * + * @since 2.8.0 + */ + #[\AllowDynamicProperties] + class WP_Http_Encoding + { + /** + * Compress raw string using the deflate format. + * + * Supports the RFC 1951 standard. + * + * @since 2.8.0 + * + * @param string $raw String to compress. + * @param int $level Optional. Compression level, 9 is highest. Default 9. + * @param string $supports Optional, not used. When implemented it will choose + * the right compression based on what the server supports. + * @return string|false Compressed string on success, false on failure. + */ + public static function compress($raw, $level = 9, $supports = \null) + { + } + /** + * Decompression of deflated string. + * + * Will attempt to decompress using the RFC 1950 standard, and if that fails + * then the RFC 1951 standard deflate will be attempted. Finally, the RFC + * 1952 standard gzip decode will be attempted. If all fail, then the + * original compressed string will be returned. + * + * @since 2.8.0 + * + * @param string $compressed String to decompress. + * @param int $length The optional length of the compressed data. + * @return string|false Decompressed string on success, false on failure. + */ + public static function decompress($compressed, $length = \null) + { + } + /** + * Decompression of deflated string while staying compatible with the majority of servers. + * + * Certain Servers will return deflated data with headers which PHP's gzinflate() + * function cannot handle out of the box. The following function has been created from + * various snippets on the gzinflate() PHP documentation. + * + * Warning: Magic numbers within. Due to the potential different formats that the compressed + * data may be returned in, some "magic offsets" are needed to ensure proper decompression + * takes place. For a simple pragmatic way to determine the magic offset in use, see: + * https://core.trac.wordpress.org/ticket/18273 + * + * @since 2.8.1 + * + * @link https://core.trac.wordpress.org/ticket/18273 + * @link https://www.php.net/manual/en/function.gzinflate.php#70875 + * @link https://www.php.net/manual/en/function.gzinflate.php#77336 + * + * @param string $gz_data String to decompress. + * @return string|false Decompressed string on success, false on failure. + */ + public static function compatible_gzinflate($gz_data) + { + } + /** + * What encoding types to accept and their priority values. + * + * @since 2.8.0 + * + * @param string $url + * @param array $args + * @return string Types of encoding to accept. + */ + public static function accept_encoding($url, $args) + { + } + /** + * What encoding the content used when it was compressed to send in the headers. + * + * @since 2.8.0 + * + * @return string Content-Encoding string to send in the header. + */ + public static function content_encoding() + { + } + /** + * Whether the content be decoded based on the headers. + * + * @since 2.8.0 + * + * @param array|string $headers All of the available headers. + * @return bool + */ + public static function should_decode($headers) + { + } + /** + * Whether decompression and compression are supported by the PHP version. + * + * Each function is tested instead of checking for the zlib extension, to + * ensure that the functions all exist in the PHP version and aren't + * disabled. + * + * @since 2.8.0 + * + * @return bool + */ + public static function is_available() + { + } + } + /** + * WP_HTTP_IXR_Client + * + * @package WordPress + * @since 3.1.0 + */ + #[\AllowDynamicProperties] + class WP_HTTP_IXR_Client extends \IXR_Client + { + public $scheme; + /** + * @var IXR_Error + */ + public $error; + /** + * @param string $server + * @param string|false $path + * @param int|false $port + * @param int $timeout + */ + public function __construct($server, $path = \false, $port = \false, $timeout = 15) + { + } + /** + * @since 3.1.0 + * @since 5.5.0 Formalized the existing `...$args` parameter by adding it + * to the function signature. + * + * @return bool + */ + public function query(...$args) + { + } + } + /** + * HTTP API: WP_HTTP_Proxy class + * + * @package WordPress + * @subpackage HTTP + * @since 4.4.0 + */ + /** + * Core class used to implement HTTP API proxy support. + * + * There are caveats to proxy support. It requires that defines be made in the wp-config.php file to + * enable proxy support. There are also a few filters that plugins can hook into for some of the + * constants. + * + * Please note that only BASIC authentication is supported by most transports. + * cURL MAY support more methods (such as NTLM authentication) depending on your environment. + * + * The constants are as follows: + * <ol> + * <li>WP_PROXY_HOST - Enable proxy support and host for connecting.</li> + * <li>WP_PROXY_PORT - Proxy port for connection. No default, must be defined.</li> + * <li>WP_PROXY_USERNAME - Proxy username, if it requires authentication.</li> + * <li>WP_PROXY_PASSWORD - Proxy password, if it requires authentication.</li> + * <li>WP_PROXY_BYPASS_HOSTS - Will prevent the hosts in this list from going through the proxy. + * You do not need to have localhost and the site host in this list, because they will not be passed + * through the proxy. The list should be presented in a comma separated list, wildcards using * are supported. Example: *.wordpress.org</li> + * </ol> + * + * An example can be as seen below. + * + * define('WP_PROXY_HOST', '192.168.84.101'); + * define('WP_PROXY_PORT', '8080'); + * define('WP_PROXY_BYPASS_HOSTS', 'localhost, www.example.com, *.wordpress.org'); + * + * @link https://core.trac.wordpress.org/ticket/4011 Proxy support ticket in WordPress. + * @link https://core.trac.wordpress.org/ticket/14636 Allow wildcard domains in WP_PROXY_BYPASS_HOSTS + * + * @since 2.8.0 + */ + #[\AllowDynamicProperties] + class WP_HTTP_Proxy + { + /** + * Whether proxy connection should be used. + * + * Constants which control this behaviour: + * + * - `WP_PROXY_HOST` + * - `WP_PROXY_PORT` + * + * @since 2.8.0 + * + * @return bool + */ + public function is_enabled() + { + } + /** + * Whether authentication should be used. + * + * Constants which control this behaviour: + * + * - `WP_PROXY_USERNAME` + * - `WP_PROXY_PASSWORD` + * + * @since 2.8.0 + * + * @return bool + */ + public function use_authentication() + { + } + /** + * Retrieve the host for the proxy server. + * + * @since 2.8.0 + * + * @return string + */ + public function host() + { + } + /** + * Retrieve the port for the proxy server. + * + * @since 2.8.0 + * + * @return string + */ + public function port() + { + } + /** + * Retrieve the username for proxy authentication. + * + * @since 2.8.0 + * + * @return string + */ + public function username() + { + } + /** + * Retrieve the password for proxy authentication. + * + * @since 2.8.0 + * + * @return string + */ + public function password() + { + } + /** + * Retrieve authentication string for proxy authentication. + * + * @since 2.8.0 + * + * @return string + */ + public function authentication() + { + } + /** + * Retrieve header string for proxy authentication. + * + * @since 2.8.0 + * + * @return string + */ + public function authentication_header() + { + } + /** + * Determines whether the request should be sent through a proxy. + * + * We want to keep localhost and the site URL from being sent through the proxy, because + * some proxies can not handle this. We also have the constant available for defining other + * hosts that won't be sent through the proxy. + * + * @since 2.8.0 + * + * @param string $uri URL of the request. + * @return bool Whether to send the request through the proxy. + */ + public function send_through_proxy($uri) + { + } + } + /** + * HTTP API: Requests hook bridge class + * + * @package WordPress + * @subpackage HTTP + * @since 4.7.0 + */ + /** + * Bridge to connect Requests internal hooks to WordPress actions. + * + * @since 4.7.0 + * + * @see Requests_Hooks + */ + #[\AllowDynamicProperties] + class WP_HTTP_Requests_Hooks extends \Requests_Hooks + { + /** + * Requested URL. + * + * @var string Requested URL. + */ + protected $url; + /** + * WordPress WP_HTTP request data. + * + * @var array Request data in WP_Http format. + */ + protected $request = array(); + /** + * Constructor. + * + * @param string $url URL to request. + * @param array $request Request data in WP_Http format. + */ + public function __construct($url, $request) + { + } + /** + * Dispatch a Requests hook to a native WordPress action. + * + * @param string $hook Hook name. + * @param array $parameters Parameters to pass to callbacks. + * @return bool True if hooks were run, false if nothing was hooked. + */ + public function dispatch($hook, $parameters = array()) + { + } + } + /** + * HTTP API: WP_HTTP_Response class + * + * @package WordPress + * @subpackage HTTP + * @since 4.4.0 + */ + /** + * Core class used to prepare HTTP responses. + * + * @since 4.4.0 + */ + #[\AllowDynamicProperties] + class WP_HTTP_Response + { + /** + * Response data. + * + * @since 4.4.0 + * @var mixed + */ + public $data; + /** + * Response headers. + * + * @since 4.4.0 + * @var array + */ + public $headers; + /** + * Response status. + * + * @since 4.4.0 + * @var int + */ + public $status; + /** + * Constructor. + * + * @since 4.4.0 + * + * @param mixed $data Response data. Default null. + * @param int $status Optional. HTTP status code. Default 200. + * @param array $headers Optional. HTTP header map. Default empty array. + */ + public function __construct($data = \null, $status = 200, $headers = array()) + { + } + /** + * Retrieves headers associated with the response. + * + * @since 4.4.0 + * + * @return array Map of header name to header value. + */ + public function get_headers() + { + } + /** + * Sets all header values. + * + * @since 4.4.0 + * + * @param array $headers Map of header name to header value. + */ + public function set_headers($headers) + { + } + /** + * Sets a single HTTP header. + * + * @since 4.4.0 + * + * @param string $key Header name. + * @param string $value Header value. + * @param bool $replace Optional. Whether to replace an existing header of the same name. + * Default true. + */ + public function header($key, $value, $replace = \true) + { + } + /** + * Retrieves the HTTP return code for the response. + * + * @since 4.4.0 + * + * @return int The 3-digit HTTP status code. + */ + public function get_status() + { + } + /** + * Sets the 3-digit HTTP status code. + * + * @since 4.4.0 + * + * @param int $code HTTP status. + */ + public function set_status($code) + { + } + /** + * Retrieves the response data. + * + * @since 4.4.0 + * + * @return mixed Response data. + */ + public function get_data() + { + } + /** + * Sets the response data. + * + * @since 4.4.0 + * + * @param mixed $data Response data. + */ + public function set_data($data) + { + } + /** + * Retrieves the response data for JSON serialization. + * + * It is expected that in most implementations, this will return the same as get_data(), + * however this may be different if you want to do custom JSON data handling. + * + * @since 4.4.0 + * + * @return mixed Any JSON-serializable value. + */ + public function jsonSerialize() + { + } + } + /** + * HTTP API: WP_HTTP_Requests_Response class + * + * @package WordPress + * @subpackage HTTP + * @since 4.6.0 + */ + /** + * Core wrapper object for a Requests_Response for standardisation. + * + * @since 4.6.0 + * + * @see WP_HTTP_Response + */ + class WP_HTTP_Requests_Response extends \WP_HTTP_Response + { + /** + * Requests Response object. + * + * @since 4.6.0 + * @var Requests_Response + */ + protected $response; + /** + * Filename the response was saved to. + * + * @since 4.6.0 + * @var string|null + */ + protected $filename; + /** + * Constructor. + * + * @since 4.6.0 + * + * @param Requests_Response $response HTTP response. + * @param string $filename Optional. File name. Default empty. + */ + public function __construct(\Requests_Response $response, $filename = '') + { + } + /** + * Retrieves the response object for the request. + * + * @since 4.6.0 + * + * @return Requests_Response HTTP response. + */ + public function get_response_object() + { + } + /** + * Retrieves headers associated with the response. + * + * @since 4.6.0 + * + * @return \Requests_Utility_CaseInsensitiveDictionary Map of header name to header value. + */ + public function get_headers() + { + } + /** + * Sets all header values. + * + * @since 4.6.0 + * + * @param array $headers Map of header name to header value. + */ + public function set_headers($headers) + { + } + /** + * Sets a single HTTP header. + * + * @since 4.6.0 + * + * @param string $key Header name. + * @param string $value Header value. + * @param bool $replace Optional. Whether to replace an existing header of the same name. + * Default true. + */ + public function header($key, $value, $replace = \true) + { + } + /** + * Retrieves the HTTP return code for the response. + * + * @since 4.6.0 + * + * @return int The 3-digit HTTP status code. + */ + public function get_status() + { + } + /** + * Sets the 3-digit HTTP status code. + * + * @since 4.6.0 + * + * @param int $code HTTP status. + */ + public function set_status($code) + { + } + /** + * Retrieves the response data. + * + * @since 4.6.0 + * + * @return string Response data. + */ + public function get_data() + { + } + /** + * Sets the response data. + * + * @since 4.6.0 + * + * @param string $data Response data. + */ + public function set_data($data) + { + } + /** + * Retrieves cookies from the response. + * + * @since 4.6.0 + * + * @return WP_HTTP_Cookie[] List of cookie objects. + */ + public function get_cookies() + { + } + /** + * Converts the object to a WP_Http response array. + * + * @since 4.6.0 + * + * @return array WP_Http response array, per WP_Http::request(). + */ + public function to_array() + { + } + } + /** + * HTTP API: WP_Http_Streams class + * + * @package WordPress + * @subpackage HTTP + * @since 4.4.0 + */ + /** + * Core class used to integrate PHP Streams as an HTTP transport. + * + * @since 2.7.0 + * @since 3.7.0 Combined with the fsockopen transport and switched to `stream_socket_client()`. + */ + #[\AllowDynamicProperties] + class WP_Http_Streams + { + /** + * Send a HTTP request to a URI using PHP Streams. + * + * @see WP_Http::request() For default options descriptions. + * + * @since 2.7.0 + * @since 3.7.0 Combined with the fsockopen transport and switched to stream_socket_client(). + * + * @param string $url The request URL. + * @param string|array $args Optional. Override the defaults. + * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error + */ + public function request($url, $args = array()) + { + } + /** + * Verifies the received SSL certificate against its Common Names and subjectAltName fields. + * + * PHP's SSL verifications only verify that it's a valid Certificate, it doesn't verify if + * the certificate is valid for the hostname which was requested. + * This function verifies the requested hostname against certificate's subjectAltName field, + * if that is empty, or contains no DNS entries, a fallback to the Common Name field is used. + * + * IP Address support is included if the request is being made to an IP address. + * + * @since 3.7.0 + * + * @param resource $stream The PHP Stream which the SSL request is being made over + * @param string $host The hostname being requested + * @return bool If the certificate presented in $stream is valid for $host + */ + public static function verify_ssl_certificate($stream, $host) + { + } + /** + * Determines whether this class can be used for retrieving a URL. + * + * @since 2.7.0 + * @since 3.7.0 Combined with the fsockopen transport and switched to stream_socket_client(). + * + * @param array $args Optional. Array of request arguments. Default empty array. + * @return bool False means this class can not be used, true means it can. + */ + public static function test($args = array()) + { + } + } + /** + * Deprecated HTTP Transport method which used fsockopen. + * + * This class is not used, and is included for backward compatibility only. + * All code should make use of WP_Http directly through its API. + * + * @see WP_HTTP::request + * + * @since 2.7.0 + * @deprecated 3.7.0 Please use WP_HTTP::request() directly + */ + class WP_HTTP_Fsockopen extends \WP_Http_Streams + { + // For backward compatibility for users who are using the class directly. + } + /** + * Core class used for managing HTTP transports and making HTTP requests. + * + * This class is used to consistently make outgoing HTTP requests easy for developers + * while still being compatible with the many PHP configurations under which + * WordPress runs. + * + * Debugging includes several actions, which pass different variables for debugging the HTTP API. + * + * @since 2.7.0 + */ + #[\AllowDynamicProperties] + class WP_Http + { + // Aliases for HTTP response codes. + const HTTP_CONTINUE = 100; + const SWITCHING_PROTOCOLS = 101; + const PROCESSING = 102; + const EARLY_HINTS = 103; + const OK = 200; + const CREATED = 201; + const ACCEPTED = 202; + const NON_AUTHORITATIVE_INFORMATION = 203; + const NO_CONTENT = 204; + const RESET_CONTENT = 205; + const PARTIAL_CONTENT = 206; + const MULTI_STATUS = 207; + const IM_USED = 226; + const MULTIPLE_CHOICES = 300; + const MOVED_PERMANENTLY = 301; + const FOUND = 302; + const SEE_OTHER = 303; + const NOT_MODIFIED = 304; + const USE_PROXY = 305; + const RESERVED = 306; + const TEMPORARY_REDIRECT = 307; + const PERMANENT_REDIRECT = 308; + const BAD_REQUEST = 400; + const UNAUTHORIZED = 401; + const PAYMENT_REQUIRED = 402; + const FORBIDDEN = 403; + const NOT_FOUND = 404; + const METHOD_NOT_ALLOWED = 405; + const NOT_ACCEPTABLE = 406; + const PROXY_AUTHENTICATION_REQUIRED = 407; + const REQUEST_TIMEOUT = 408; + const CONFLICT = 409; + const GONE = 410; + const LENGTH_REQUIRED = 411; + const PRECONDITION_FAILED = 412; + const REQUEST_ENTITY_TOO_LARGE = 413; + const REQUEST_URI_TOO_LONG = 414; + const UNSUPPORTED_MEDIA_TYPE = 415; + const REQUESTED_RANGE_NOT_SATISFIABLE = 416; + const EXPECTATION_FAILED = 417; + const IM_A_TEAPOT = 418; + const MISDIRECTED_REQUEST = 421; + const UNPROCESSABLE_ENTITY = 422; + const LOCKED = 423; + const FAILED_DEPENDENCY = 424; + const UPGRADE_REQUIRED = 426; + const PRECONDITION_REQUIRED = 428; + const TOO_MANY_REQUESTS = 429; + const REQUEST_HEADER_FIELDS_TOO_LARGE = 431; + const UNAVAILABLE_FOR_LEGAL_REASONS = 451; + const INTERNAL_SERVER_ERROR = 500; + const NOT_IMPLEMENTED = 501; + const BAD_GATEWAY = 502; + const SERVICE_UNAVAILABLE = 503; + const GATEWAY_TIMEOUT = 504; + const HTTP_VERSION_NOT_SUPPORTED = 505; + const VARIANT_ALSO_NEGOTIATES = 506; + const INSUFFICIENT_STORAGE = 507; + const NOT_EXTENDED = 510; + const NETWORK_AUTHENTICATION_REQUIRED = 511; + /** + * Send an HTTP request to a URI. + * + * Please note: The only URI that are supported in the HTTP Transport implementation + * are the HTTP and HTTPS protocols. + * + * @since 2.7.0 + * + * @param string $url The request URL. + * @param string|array $args { + * Optional. Array or string of HTTP request arguments. + * + * @type string $method Request method. Accepts 'GET', 'POST', 'HEAD', 'PUT', 'DELETE', + * 'TRACE', 'OPTIONS', or 'PATCH'. + * Some transports technically allow others, but should not be + * assumed. Default 'GET'. + * @type float $timeout How long the connection should stay open in seconds. Default 5. + * @type int $redirection Number of allowed redirects. Not supported by all transports. + * Default 5. + * @type string $httpversion Version of the HTTP protocol to use. Accepts '1.0' and '1.1'. + * Default '1.0'. + * @type string $user-agent User-agent value sent. + * Default 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ). + * @type bool $reject_unsafe_urls Whether to pass URLs through wp_http_validate_url(). + * Default false. + * @type bool $blocking Whether the calling code requires the result of the request. + * If set to false, the request will be sent to the remote server, + * and processing returned to the calling code immediately, the caller + * will know if the request succeeded or failed, but will not receive + * any response from the remote server. Default true. + * @type string|array $headers Array or string of headers to send with the request. + * Default empty array. + * @type array $cookies List of cookies to send with the request. Default empty array. + * @type string|array $body Body to send with the request. Default null. + * @type bool $compress Whether to compress the $body when sending the request. + * Default false. + * @type bool $decompress Whether to decompress a compressed response. If set to false and + * compressed content is returned in the response anyway, it will + * need to be separately decompressed. Default true. + * @type bool $sslverify Whether to verify SSL for the request. Default true. + * @type string $sslcertificates Absolute path to an SSL certificate .crt file. + * Default ABSPATH . WPINC . '/certificates/ca-bundle.crt'. + * @type bool $stream Whether to stream to a file. If set to true and no filename was + * given, it will be dropped it in the WP temp dir and its name will + * be set using the basename of the URL. Default false. + * @type string $filename Filename of the file to write to when streaming. $stream must be + * set to true. Default null. + * @type int $limit_response_size Size in bytes to limit the response to. Default null. + * + * } + * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. + * A WP_Error instance upon error. + * @phpstan-param array{ + * method?: string, + * timeout?: float, + * redirection?: int, + * httpversion?: string, + * user-agent?: string, + * reject_unsafe_urls?: bool, + * blocking?: bool, + * headers?: string|array, + * cookies?: array, + * body?: string|array, + * compress?: bool, + * decompress?: bool, + * sslverify?: bool, + * sslcertificates?: string, + * stream?: bool, + * filename?: string, + * limit_response_size?: int, + * } $args + * @phpstan-return array{headers: \Requests_Utility_CaseInsensitiveDictionary, body: string, response: array{code: int,message: string}, cookies: array<int, \WP_HTTP_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error + */ + public function request($url, $args = array()) + { + } + /** + * Normalizes cookies for using in Requests. + * + * @since 4.6.0 + * + * @param array $cookies Array of cookies to send with the request. + * @return Requests_Cookie_Jar Cookie holder object. + */ + public static function normalize_cookies($cookies) + { + } + /** + * Match redirect behaviour to browser handling. + * + * Changes 302 redirects from POST to GET to match browser handling. Per + * RFC 7231, user agents can deviate from the strict reading of the + * specification for compatibility purposes. + * + * @since 4.6.0 + * + * @param string $location URL to redirect to. + * @param array $headers Headers for the redirect. + * @param string|array $data Body to send with the request. + * @param array $options Redirect request options. + * @param Requests_Response $original Response object. + */ + public static function browser_redirect_compatibility($location, $headers, $data, &$options, $original) + { + } + /** + * Validate redirected URLs. + * + * @since 4.7.5 + * + * @throws Requests_Exception On unsuccessful URL validation. + * @param string $location URL to redirect to. + */ + public static function validate_redirects($location) + { + } + /** + * Tests which transports are capable of supporting the request. + * + * @since 3.2.0 + * + * @param array $args Request arguments. + * @param string $url URL to request. + * @return string|false Class name for the first transport that claims to support the request. + * False if no transport claims to support the request. + */ + public function _get_first_available_transport($args, $url = \null) + { + } + /** + * Uses the POST HTTP method. + * + * Used for sending data that is expected to be in the body. + * + * @since 2.7.0 + * + * @param string $url The request URL. + * @param string|array $args Optional. Override the defaults. + * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. + * A WP_Error instance upon error. + * @phpstan-return array{headers: \Requests_Utility_CaseInsensitiveDictionary, body: string, response: array{code: int,message: string}, cookies: array<int, \WP_HTTP_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error + */ + public function post($url, $args = array()) + { + } + /** + * Uses the GET HTTP method. + * + * Used for sending data that is expected to be in the body. + * + * @since 2.7.0 + * + * @param string $url The request URL. + * @param string|array $args Optional. Override the defaults. + * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. + * A WP_Error instance upon error. + * @phpstan-return array{headers: \Requests_Utility_CaseInsensitiveDictionary, body: string, response: array{code: int,message: string}, cookies: array<int, \WP_HTTP_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error + */ + public function get($url, $args = array()) + { + } + /** + * Uses the HEAD HTTP method. + * + * Used for sending data that is expected to be in the body. + * + * @since 2.7.0 + * + * @param string $url The request URL. + * @param string|array $args Optional. Override the defaults. + * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. + * A WP_Error instance upon error. + * @phpstan-return array{headers: \Requests_Utility_CaseInsensitiveDictionary, body: string, response: array{code: int,message: string}, cookies: array<int, \WP_HTTP_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error + */ + public function head($url, $args = array()) + { + } + /** + * Parses the responses and splits the parts into headers and body. + * + * @since 2.7.0 + * + * @param string $response The full response string. + * @return array { + * Array with response headers and body. + * + * @type string $headers HTTP response headers. + * @type string $body HTTP response body. + * } + * @phpstan-return array{ + * headers: string, + * body: string, + * } + */ + public static function processResponse($response) + { + } + /** + * Transforms header string into an array. + * + * @since 2.7.0 + * + * @param string|array $headers The original headers. If a string is passed, it will be converted + * to an array. If an array is passed, then it is assumed to be + * raw header data with numeric keys with the headers as the values. + * No headers must be passed that were already processed. + * @param string $url Optional. The URL that was requested. Default empty. + * @return array { + * Processed string headers. If duplicate headers are encountered, + * then a numbered array is returned as the value of that header-key. + * + * @type array $response { + * @type int $code The response status code. Default 0. + * @type string $message The response message. Default empty. + * } + * @type array $newheaders The processed header data as a multidimensional array. + * @type WP_Http_Cookie[] $cookies If the original headers contain the 'Set-Cookie' key, + * an array containing `WP_Http_Cookie` objects is returned. + * } + * @phpstan-return array{ + * response: array{ + * code: int, + * message: string, + * }, + * newheaders: array, + * cookies: WP_Http_Cookie[], + * } + */ + public static function processHeaders($headers, $url = '') + { + } + /** + * Takes the arguments for a ::request() and checks for the cookie array. + * + * If it's found, then it upgrades any basic name => value pairs to WP_Http_Cookie instances, + * which are each parsed into strings and added to the Cookie: header (within the arguments array). + * Edits the array by reference. + * + * @since 2.8.0 + * + * @param array $r Full array of args passed into ::request() + */ + public static function buildCookieHeader(&$r) + { + } + /** + * Decodes chunk transfer-encoding, based off the HTTP 1.1 specification. + * + * Based off the HTTP http_encoding_dechunk function. + * + * @link https://tools.ietf.org/html/rfc2616#section-19.4.6 Process for chunked decoding. + * + * @since 2.7.0 + * + * @param string $body Body content. + * @return string Chunked decoded body on success or raw body on failure. + */ + public static function chunkTransferDecode($body) + { + } + /** + * Determines whether an HTTP API request to the given URL should be blocked. + * + * Those who are behind a proxy and want to prevent access to certain hosts may do so. This will + * prevent plugins from working and core functionality, if you don't include `api.wordpress.org`. + * + * You block external URL requests by defining `WP_HTTP_BLOCK_EXTERNAL` as true in your `wp-config.php` + * file and this will only allow localhost and your site to make requests. The constant + * `WP_ACCESSIBLE_HOSTS` will allow additional hosts to go through for requests. The format of the + * `WP_ACCESSIBLE_HOSTS` constant is a comma separated list of hostnames to allow, wildcard domains + * are supported, eg `*.wordpress.org` will allow for all subdomains of `wordpress.org` to be contacted. + * + * @since 2.8.0 + * + * @link https://core.trac.wordpress.org/ticket/8927 Allow preventing external requests. + * @link https://core.trac.wordpress.org/ticket/14636 Allow wildcard domains in WP_ACCESSIBLE_HOSTS + * + * @param string $uri URI of url. + * @return bool True to block, false to allow. + */ + public function block_request($uri) + { + } + /** + * Used as a wrapper for PHP's parse_url() function that handles edgecases in < PHP 5.4.7. + * + * @deprecated 4.4.0 Use wp_parse_url() + * @see wp_parse_url() + * + * @param string $url The URL to parse. + * @return bool|array False on failure; Array of URL components on success; + * See parse_url()'s return values. + */ + protected static function parse_url($url) + { + } + /** + * Converts a relative URL to an absolute URL relative to a given URL. + * + * If an Absolute URL is provided, no processing of that URL is done. + * + * @since 3.4.0 + * + * @param string $maybe_relative_path The URL which might be relative. + * @param string $url The URL which $maybe_relative_path is relative to. + * @return string An Absolute URL, in a failure condition where the URL cannot be parsed, the relative URL will be returned. + */ + public static function make_absolute_url($maybe_relative_path, $url) + { + } + /** + * Handles an HTTP redirect and follows it if appropriate. + * + * @since 3.7.0 + * + * @param string $url The URL which was requested. + * @param array $args The arguments which were used to make the request. + * @param array $response The response of the HTTP request. + * @return array|false|WP_Error An HTTP API response array if the redirect is successfully followed, + * false if no redirect is present, or a WP_Error object if there's an error. + */ + public static function handle_redirects($url, $args, $response) + { + } + /** + * Determines if a specified string represents an IP address or not. + * + * This function also detects the type of the IP address, returning either + * '4' or '6' to represent a IPv4 and IPv6 address respectively. + * This does not verify if the IP is a valid IP, only that it appears to be + * an IP address. + * + * @link http://home.deds.nl/~aeron/regex/ for IPv6 regex. + * + * @since 3.7.0 + * + * @param string $maybe_ip A suspected IP address. + * @return int|false Upon success, '4' or '6' to represent a IPv4 or IPv6 address, false upon failure + */ + public static function is_ip_address($maybe_ip) + { + } + } + /** + * Base WordPress Image Editor + * + * @package WordPress + * @subpackage Image_Editor + */ + /** + * Base image editor class from which implementations extend + * + * @since 3.5.0 + */ + #[\AllowDynamicProperties] + abstract class WP_Image_Editor + { + protected $file = \null; + protected $size = \null; + protected $mime_type = \null; + protected $output_mime_type = \null; + protected $default_mime_type = 'image/jpeg'; + protected $quality = \false; + // Deprecated since 5.8.1. See get_default_quality() below. + protected $default_quality = 82; + /** + * Each instance handles a single file. + * + * @param string $file Path to the file to load. + */ + public function __construct($file) + { + } + /** + * Checks to see if current environment supports the editor chosen. + * Must be overridden in a subclass. + * + * @since 3.5.0 + * + * @abstract + * + * @param array $args + * @return bool + */ + public static function test($args = array()) + { + } + /** + * Checks to see if editor supports the mime-type specified. + * Must be overridden in a subclass. + * + * @since 3.5.0 + * + * @abstract + * + * @param string $mime_type + * @return bool + */ + public static function supports_mime_type($mime_type) + { + } + /** + * Loads image from $this->file into editor. + * + * @since 3.5.0 + * @abstract + * + * @return true|WP_Error True if loaded; WP_Error on failure. + */ + public abstract function load(); + /** + * Saves current image to file. + * + * @since 3.5.0 + * @since 6.0.0 The `$filesize` value was added to the returned array. + * @abstract + * + * @param string $destfilename Optional. Destination filename. Default null. + * @param string $mime_type Optional. The mime-type. Default null. + * @return array|WP_Error { + * Array on success or WP_Error if the file failed to save. + * + * @type string $path Path to the image file. + * @type string $file Name of the image file. + * @type int $width Image width. + * @type int $height Image height. + * @type string $mime-type The mime type of the image. + * @type int $filesize File size of the image. + * } + * @phpstan-return \WP_Error|array{ + * path: string, + * file: string, + * width: int, + * height: int, + * mime-type: string, + * filesize: int, + * } + */ + public abstract function save($destfilename = \null, $mime_type = \null); + /** + * Resizes current image. + * + * At minimum, either a height or width must be provided. + * If one of the two is set to null, the resize will + * maintain aspect ratio according to the provided dimension. + * + * @since 3.5.0 + * @abstract + * + * @param int|null $max_w Image width. + * @param int|null $max_h Image height. + * @param bool $crop + * @return true|WP_Error + */ + public abstract function resize($max_w, $max_h, $crop = \false); + /** + * Resize multiple images from a single source. + * + * @since 3.5.0 + * @abstract + * + * @param array $sizes { + * An array of image size arrays. Default sizes are 'small', 'medium', 'large'. + * + * @type array ...$0 { + * @type int $width Image width. + * @type int $height Image height. + * @type bool $crop Optional. Whether to crop the image. Default false. + * } + * } + * @return array An array of resized images metadata by size. + * @phpstan-param array<int|string, array{ + * width: int, + * height: int, + * crop?: bool, + * }> $sizes + */ + public abstract function multi_resize($sizes); + /** + * Crops Image. + * + * @since 3.5.0 + * @abstract + * + * @param int $src_x The start x position to crop from. + * @param int $src_y The start y position to crop from. + * @param int $src_w The width to crop. + * @param int $src_h The height to crop. + * @param int $dst_w Optional. The destination width. + * @param int $dst_h Optional. The destination height. + * @param bool $src_abs Optional. If the source crop points are absolute. + * @return true|WP_Error + */ + public abstract function crop($src_x, $src_y, $src_w, $src_h, $dst_w = \null, $dst_h = \null, $src_abs = \false); + /** + * Rotates current image counter-clockwise by $angle. + * + * @since 3.5.0 + * @abstract + * + * @param float $angle + * @return true|WP_Error + */ + public abstract function rotate($angle); + /** + * Flips current image. + * + * @since 3.5.0 + * @abstract + * + * @param bool $horz Flip along Horizontal Axis + * @param bool $vert Flip along Vertical Axis + * @return true|WP_Error + */ + public abstract function flip($horz, $vert); + /** + * Streams current image to browser. + * + * @since 3.5.0 + * @abstract + * + * @param string $mime_type The mime type of the image. + * @return true|WP_Error True on success, WP_Error object on failure. + */ + public abstract function stream($mime_type = \null); + /** + * Gets dimensions of image. + * + * @since 3.5.0 + * + * @return int[] { + * Dimensions of the image. + * + * @type int $width The image width. + * @type int $height The image height. + * } + * @phpstan-return array{ + * width: int, + * height: int, + * } + */ + public function get_size() + { + } + /** + * Sets current image size. + * + * @since 3.5.0 + * + * @param int $width + * @param int $height + * @return true + */ + protected function update_size($width = \null, $height = \null) + { + } + /** + * Gets the Image Compression quality on a 1-100% scale. + * + * @since 4.0.0 + * + * @return int Compression Quality. Range: [1,100] + */ + public function get_quality() + { + } + /** + * Sets Image Compression quality on a 1-100% scale. + * + * @since 3.5.0 + * + * @param int $quality Compression Quality. Range: [1,100] + * @return true|WP_Error True if set successfully; WP_Error on failure. + */ + public function set_quality($quality = \null) + { + } + /** + * Returns the default compression quality setting for the mime type. + * + * @since 5.8.1 + * + * @param string $mime_type + * @return int The default quality setting for the mime type. + */ + protected function get_default_quality($mime_type) + { + } + /** + * Returns preferred mime-type and extension based on provided + * file's extension and mime, or current file's extension and mime. + * + * Will default to $this->default_mime_type if requested is not supported. + * + * Provides corrected filename only if filename is provided. + * + * @since 3.5.0 + * + * @param string $filename + * @param string $mime_type + * @return array { filename|null, extension, mime-type } + */ + protected function get_output_format($filename = \null, $mime_type = \null) + { + } + /** + * Builds an output filename based on current file, and adding proper suffix + * + * @since 3.5.0 + * + * @param string $suffix + * @param string $dest_path + * @param string $extension + * @return string filename + */ + public function generate_filename($suffix = \null, $dest_path = \null, $extension = \null) + { + } + /** + * Builds and returns proper suffix for file based on height and width. + * + * @since 3.5.0 + * + * @return string|false suffix + */ + public function get_suffix() + { + } + /** + * Check if a JPEG image has EXIF Orientation tag and rotate it if needed. + * + * @since 5.3.0 + * + * @return bool|WP_Error True if the image was rotated. False if not rotated (no EXIF data or the image doesn't need to be rotated). + * WP_Error if error while rotating. + */ + public function maybe_exif_rotate() + { + } + /** + * Either calls editor's save function or handles file as a stream. + * + * @since 3.5.0 + * + * @param string $filename + * @param callable $callback + * @param array $arguments + * @return bool + */ + protected function make_image($filename, $callback, $arguments) + { + } + /** + * Returns first matched mime-type from extension, + * as mapped from wp_get_mime_types() + * + * @since 3.5.0 + * + * @param string $extension + * @return string|false + */ + protected static function get_mime_type($extension = \null) + { + } + /** + * Returns first matched extension from Mime-type, + * as mapped from wp_get_mime_types() + * + * @since 3.5.0 + * + * @param string $mime_type + * @return string|false + */ + protected static function get_extension($mime_type = \null) + { + } + } + /** + * WordPress GD Image Editor + * + * @package WordPress + * @subpackage Image_Editor + */ + /** + * WordPress Image Editor Class for Image Manipulation through GD + * + * @since 3.5.0 + * + * @see WP_Image_Editor + */ + class WP_Image_Editor_GD extends \WP_Image_Editor + { + /** + * GD Resource. + * + * @var resource|GdImage + */ + protected $image; + public function __destruct() + { + } + /** + * Checks to see if current environment supports GD. + * + * @since 3.5.0 + * + * @param array $args + * @return bool + */ + public static function test($args = array()) + { + } + /** + * Checks to see if editor supports the mime-type specified. + * + * @since 3.5.0 + * + * @param string $mime_type + * @return bool + */ + public static function supports_mime_type($mime_type) + { + } + /** + * Loads image from $this->file into new GD Resource. + * + * @since 3.5.0 + * + * @return true|WP_Error True if loaded successfully; WP_Error on failure. + */ + public function load() + { + } + /** + * Sets or updates current image size. + * + * @since 3.5.0 + * + * @param int $width + * @param int $height + * @return true + */ + protected function update_size($width = \false, $height = \false) + { + } + /** + * Resizes current image. + * + * Wraps `::_resize()` which returns a GD resource or GdImage instance. + * + * At minimum, either a height or width must be provided. If one of the two is set + * to null, the resize will maintain aspect ratio according to the provided dimension. + * + * @since 3.5.0 + * + * @param int|null $max_w Image width. + * @param int|null $max_h Image height. + * @param bool $crop + * @return true|WP_Error + */ + public function resize($max_w, $max_h, $crop = \false) + { + } + /** + * @param int $max_w + * @param int $max_h + * @param bool|array $crop + * @return resource|GdImage|WP_Error + */ + protected function _resize($max_w, $max_h, $crop = \false) + { + } + /** + * Create multiple smaller images from a single source. + * + * Attempts to create all sub-sizes and returns the meta data at the end. This + * may result in the server running out of resources. When it fails there may be few + * "orphaned" images left over as the meta data is never returned and saved. + * + * As of 5.3.0 the preferred way to do this is with `make_subsize()`. It creates + * the new images one at a time and allows for the meta data to be saved after + * each new image is created. + * + * @since 3.5.0 + * + * @param array $sizes { + * An array of image size data arrays. + * + * Either a height or width must be provided. + * If one of the two is set to null, the resize will + * maintain aspect ratio according to the source image. + * + * @type array ...$0 { + * Array of height, width values, and whether to crop. + * + * @type int $width Image width. Optional if `$height` is specified. + * @type int $height Image height. Optional if `$width` is specified. + * @type bool $crop Optional. Whether to crop the image. Default false. + * } + * } + * @return array An array of resized images' metadata by size. + * @phpstan-param array<int|string, array{ + * width?: int, + * height?: int, + * crop?: bool, + * }> $sizes + */ + public function multi_resize($sizes) + { + } + /** + * Create an image sub-size and return the image meta data value for it. + * + * @since 5.3.0 + * + * @param array $size_data { + * Array of size data. + * + * @type int $width The maximum width in pixels. + * @type int $height The maximum height in pixels. + * @type bool $crop Whether to crop the image to exact dimensions. + * } + * @return array|WP_Error The image data array for inclusion in the `sizes` array in the image meta, + * WP_Error object on error. + * @phpstan-param array{ + * width?: int, + * height?: int, + * crop?: bool, + * } $size_data + */ + public function make_subsize($size_data) + { + } + /** + * Crops Image. + * + * @since 3.5.0 + * + * @param int $src_x The start x position to crop from. + * @param int $src_y The start y position to crop from. + * @param int $src_w The width to crop. + * @param int $src_h The height to crop. + * @param int $dst_w Optional. The destination width. + * @param int $dst_h Optional. The destination height. + * @param bool $src_abs Optional. If the source crop points are absolute. + * @return true|WP_Error + */ + public function crop($src_x, $src_y, $src_w, $src_h, $dst_w = \null, $dst_h = \null, $src_abs = \false) + { + } + /** + * Rotates current image counter-clockwise by $angle. + * Ported from image-edit.php + * + * @since 3.5.0 + * + * @param float $angle + * @return true|WP_Error + */ + public function rotate($angle) + { + } + /** + * Flips current image. + * + * @since 3.5.0 + * + * @param bool $horz Flip along Horizontal Axis. + * @param bool $vert Flip along Vertical Axis. + * @return true|WP_Error + */ + public function flip($horz, $vert) + { + } + /** + * Saves current in-memory image to file. + * + * @since 3.5.0 + * @since 5.9.0 Renamed `$filename` to `$destfilename` to match parent class + * for PHP 8 named parameter support. + * @since 6.0.0 The `$filesize` value was added to the returned array. + * + * @param string|null $destfilename Optional. Destination filename. Default null. + * @param string|null $mime_type Optional. The mime-type. Default null. + * @return array|WP_Error { + * Array on success or WP_Error if the file failed to save. + * + * @type string $path Path to the image file. + * @type string $file Name of the image file. + * @type int $width Image width. + * @type int $height Image height. + * @type string $mime-type The mime type of the image. + * @type int $filesize File size of the image. + * } + * @phpstan-return \WP_Error|array{ + * path: string, + * file: string, + * width: int, + * height: int, + * mime-type: string, + * filesize: int, + * } + */ + public function save($destfilename = \null, $mime_type = \null) + { + } + /** + * @since 3.5.0 + * @since 6.0.0 The `$filesize` value was added to the returned array. + * + * @param resource|GdImage $image + * @param string|null $filename + * @param string|null $mime_type + * @return array|WP_Error { + * Array on success or WP_Error if the file failed to save. + * + * @type string $path Path to the image file. + * @type string $file Name of the image file. + * @type int $width Image width. + * @type int $height Image height. + * @type string $mime-type The mime type of the image. + * @type int $filesize File size of the image. + * } + * @phpstan-return \WP_Error|array{ + * path: string, + * file: string, + * width: int, + * height: int, + * mime-type: string, + * filesize: int, + * } + */ + protected function _save($image, $filename = \null, $mime_type = \null) + { + } + /** + * Returns stream of current image. + * + * @since 3.5.0 + * + * @param string $mime_type The mime type of the image. + * @return bool True on success, false on failure. + */ + public function stream($mime_type = \null) + { + } + /** + * Either calls editor's save function or handles file as a stream. + * + * @since 3.5.0 + * + * @param string $filename + * @param callable $callback + * @param array $arguments + * @return bool + */ + protected function make_image($filename, $callback, $arguments) + { + } + } + /** + * WordPress Imagick Image Editor + * + * @package WordPress + * @subpackage Image_Editor + */ + /** + * WordPress Image Editor Class for Image Manipulation through Imagick PHP Module + * + * @since 3.5.0 + * + * @see WP_Image_Editor + */ + class WP_Image_Editor_Imagick extends \WP_Image_Editor + { + /** + * Imagick object. + * + * @var Imagick + */ + protected $image; + public function __destruct() + { + } + /** + * Checks to see if current environment supports Imagick. + * + * We require Imagick 2.2.0 or greater, based on whether the queryFormats() + * method can be called statically. + * + * @since 3.5.0 + * + * @param array $args + * @return bool + */ + public static function test($args = array()) + { + } + /** + * Checks to see if editor supports the mime-type specified. + * + * @since 3.5.0 + * + * @param string $mime_type + * @return bool + */ + public static function supports_mime_type($mime_type) + { + } + /** + * Loads image from $this->file into new Imagick Object. + * + * @since 3.5.0 + * + * @return true|WP_Error True if loaded; WP_Error on failure. + */ + public function load() + { + } + /** + * Sets Image Compression quality on a 1-100% scale. + * + * @since 3.5.0 + * + * @param int $quality Compression Quality. Range: [1,100] + * @return true|WP_Error True if set successfully; WP_Error on failure. + */ + public function set_quality($quality = \null) + { + } + /** + * Sets or updates current image size. + * + * @since 3.5.0 + * + * @param int $width + * @param int $height + * @return true|WP_Error + */ + protected function update_size($width = \null, $height = \null) + { + } + /** + * Resizes current image. + * + * At minimum, either a height or width must be provided. + * If one of the two is set to null, the resize will + * maintain aspect ratio according to the provided dimension. + * + * @since 3.5.0 + * + * @param int|null $max_w Image width. + * @param int|null $max_h Image height. + * @param bool $crop + * @return true|WP_Error + */ + public function resize($max_w, $max_h, $crop = \false) + { + } + /** + * Efficiently resize the current image + * + * This is a WordPress specific implementation of Imagick::thumbnailImage(), + * which resizes an image to given dimensions and removes any associated profiles. + * + * @since 4.5.0 + * + * @param int $dst_w The destination width. + * @param int $dst_h The destination height. + * @param string $filter_name Optional. The Imagick filter to use when resizing. Default 'FILTER_TRIANGLE'. + * @param bool $strip_meta Optional. Strip all profiles, excluding color profiles, from the image. Default true. + * @return void|WP_Error + */ + protected function thumbnail_image($dst_w, $dst_h, $filter_name = 'FILTER_TRIANGLE', $strip_meta = \true) + { + } + /** + * Create multiple smaller images from a single source. + * + * Attempts to create all sub-sizes and returns the meta data at the end. This + * may result in the server running out of resources. When it fails there may be few + * "orphaned" images left over as the meta data is never returned and saved. + * + * As of 5.3.0 the preferred way to do this is with `make_subsize()`. It creates + * the new images one at a time and allows for the meta data to be saved after + * each new image is created. + * + * @since 3.5.0 + * + * @param array $sizes { + * An array of image size data arrays. + * + * Either a height or width must be provided. + * If one of the two is set to null, the resize will + * maintain aspect ratio according to the provided dimension. + * + * @type array ...$0 { + * Array of height, width values, and whether to crop. + * + * @type int $width Image width. Optional if `$height` is specified. + * @type int $height Image height. Optional if `$width` is specified. + * @type bool $crop Optional. Whether to crop the image. Default false. + * } + * } + * @return array An array of resized images' metadata by size. + * @phpstan-param array<int|string, array{ + * width?: int, + * height?: int, + * crop?: bool, + * }> $sizes + */ + public function multi_resize($sizes) + { + } + /** + * Create an image sub-size and return the image meta data value for it. + * + * @since 5.3.0 + * + * @param array $size_data { + * Array of size data. + * + * @type int $width The maximum width in pixels. + * @type int $height The maximum height in pixels. + * @type bool $crop Whether to crop the image to exact dimensions. + * } + * @return array|WP_Error The image data array for inclusion in the `sizes` array in the image meta, + * WP_Error object on error. + * @phpstan-param array{ + * width?: int, + * height?: int, + * crop?: bool, + * } $size_data + */ + public function make_subsize($size_data) + { + } + /** + * Crops Image. + * + * @since 3.5.0 + * + * @param int $src_x The start x position to crop from. + * @param int $src_y The start y position to crop from. + * @param int $src_w The width to crop. + * @param int $src_h The height to crop. + * @param int $dst_w Optional. The destination width. + * @param int $dst_h Optional. The destination height. + * @param bool $src_abs Optional. If the source crop points are absolute. + * @return true|WP_Error + */ + public function crop($src_x, $src_y, $src_w, $src_h, $dst_w = \null, $dst_h = \null, $src_abs = \false) + { + } + /** + * Rotates current image counter-clockwise by $angle. + * + * @since 3.5.0 + * + * @param float $angle + * @return true|WP_Error + */ + public function rotate($angle) + { + } + /** + * Flips current image. + * + * @since 3.5.0 + * + * @param bool $horz Flip along Horizontal Axis + * @param bool $vert Flip along Vertical Axis + * @return true|WP_Error + */ + public function flip($horz, $vert) + { + } + /** + * Check if a JPEG image has EXIF Orientation tag and rotate it if needed. + * + * As ImageMagick copies the EXIF data to the flipped/rotated image, proceed only + * if EXIF Orientation can be reset afterwards. + * + * @since 5.3.0 + * + * @return bool|WP_Error True if the image was rotated. False if no EXIF data or if the image doesn't need rotation. + * WP_Error if error while rotating. + */ + public function maybe_exif_rotate() + { + } + /** + * Saves current image to file. + * + * @since 3.5.0 + * @since 6.0.0 The `$filesize` value was added to the returned array. + * + * @param string $destfilename Optional. Destination filename. Default null. + * @param string $mime_type Optional. The mime-type. Default null. + * @return array|WP_Error { + * Array on success or WP_Error if the file failed to save. + * + * @type string $path Path to the image file. + * @type string $file Name of the image file. + * @type int $width Image width. + * @type int $height Image height. + * @type string $mime-type The mime type of the image. + * @type int $filesize File size of the image. + * } + * @phpstan-return \WP_Error|array{ + * path: string, + * file: string, + * width: int, + * height: int, + * mime-type: string, + * filesize: int, + * } + */ + public function save($destfilename = \null, $mime_type = \null) + { + } + /** + * @since 3.5.0 + * @since 6.0.0 The `$filesize` value was added to the returned array. + * + * @param Imagick $image + * @param string $filename + * @param string $mime_type + * @return array|WP_Error { + * Array on success or WP_Error if the file failed to save. + * + * @type string $path Path to the image file. + * @type string $file Name of the image file. + * @type int $width Image width. + * @type int $height Image height. + * @type string $mime-type The mime type of the image. + * @type int $filesize File size of the image. + * } + * @phpstan-return \WP_Error|array{ + * path: string, + * file: string, + * width: int, + * height: int, + * mime-type: string, + * filesize: int, + * } + */ + protected function _save($image, $filename = \null, $mime_type = \null) + { + } + /** + * Streams current image to browser. + * + * @since 3.5.0 + * + * @param string $mime_type The mime type of the image. + * @return true|WP_Error True on success, WP_Error object on failure. + */ + public function stream($mime_type = \null) + { + } + /** + * Strips all image meta except color profiles from an image. + * + * @since 4.5.0 + * + * @return true|WP_Error True if stripping metadata was successful. WP_Error object on error. + */ + protected function strip_meta() + { + } + /** + * Sets up Imagick for PDF processing. + * Increases rendering DPI and only loads first page. + * + * @since 4.7.0 + * + * @return string|WP_Error File to load or WP_Error on failure. + */ + protected function pdf_setup() + { + } + /** + * Load the image produced by Ghostscript. + * + * Includes a workaround for a bug in Ghostscript 8.70 that prevents processing of some PDF files + * when `use-cropbox` is set. + * + * @since 5.6.0 + * + * @return true|WP_Error + */ + protected function pdf_load_source() + { + } + } + /** + * WordPress List utility class + * + * @package WordPress + * @since 4.7.0 + */ + /** + * List utility. + * + * Utility class to handle operations on an array of objects or arrays. + * + * @since 4.7.0 + */ + #[\AllowDynamicProperties] + class WP_List_Util + { + /** + * Constructor. + * + * Sets the input array. + * + * @since 4.7.0 + * + * @param array $input Array to perform operations on. + */ + public function __construct($input) + { + } + /** + * Returns the original input array. + * + * @since 4.7.0 + * + * @return array The input array. + */ + public function get_input() + { + } + /** + * Returns the output array. + * + * @since 4.7.0 + * + * @return array The output array. + */ + public function get_output() + { + } + /** + * Filters the list, based on a set of key => value arguments. + * + * Retrieves the objects from the list that match the given arguments. + * Key represents property name, and value represents property value. + * + * If an object has more properties than those specified in arguments, + * that will not disqualify it. When using the 'AND' operator, + * any missing properties will disqualify it. + * + * @since 4.7.0 + * + * @param array $args Optional. An array of key => value arguments to match + * against each object. Default empty array. + * @param string $operator Optional. The logical operation to perform. 'AND' means + * all elements from the array must match. 'OR' means only + * one element needs to match. 'NOT' means no elements may + * match. Default 'AND'. + * @return array Array of found values. + */ + public function filter($args = array(), $operator = 'AND') + { + } + /** + * Plucks a certain field out of each element in the input array. + * + * This has the same functionality and prototype of + * array_column() (PHP 5.5) but also supports objects. + * + * @since 4.7.0 + * + * @param int|string $field Field to fetch from the object or array. + * @param int|string $index_key Optional. Field from the element to use as keys for the new array. + * Default null. + * @return array Array of found values. If `$index_key` is set, an array of found values with keys + * corresponding to `$index_key`. If `$index_key` is null, array keys from the original + * `$list` will be preserved in the results. + */ + public function pluck($field, $index_key = \null) + { + } + /** + * Sorts the input array based on one or more orderby arguments. + * + * @since 4.7.0 + * + * @param string|array $orderby Optional. Either the field name to order by or an array + * of multiple orderby fields as $orderby => $order. + * @param string $order Optional. Either 'ASC' or 'DESC'. Only used if $orderby + * is a string. + * @param bool $preserve_keys Optional. Whether to preserve keys. Default false. + * @return array The sorted array. + */ + public function sort($orderby = array(), $order = 'ASC', $preserve_keys = \false) + { + } + } + /** + * Locale API: WP_Locale_Switcher class + * + * @package WordPress + * @subpackage i18n + * @since 4.7.0 + */ + /** + * Core class used for switching locales. + * + * @since 4.7.0 + */ + #[\AllowDynamicProperties] + class WP_Locale_Switcher + { + /** + * Constructor. + * + * Stores the original locale as well as a list of all available languages. + * + * @since 4.7.0 + */ + public function __construct() + { + } + /** + * Initializes the locale switcher. + * + * Hooks into the {@see 'locale'} filter to change the locale on the fly. + * + * @since 4.7.0 + */ + public function init() + { + } + /** + * Switches the translations according to the given locale. + * + * @since 4.7.0 + * + * @param string $locale The locale to switch to. + * @return bool True on success, false on failure. + */ + public function switch_to_locale($locale) + { + } + /** + * Restores the translations according to the previous locale. + * + * @since 4.7.0 + * + * @return string|false Locale on success, false on failure. + */ + public function restore_previous_locale() + { + } + /** + * Restores the translations according to the original locale. + * + * @since 4.7.0 + * + * @return string|false Locale on success, false on failure. + */ + public function restore_current_locale() + { + } + /** + * Whether switch_to_locale() is in effect. + * + * @since 4.7.0 + * + * @return bool True if the locale has been switched, false otherwise. + */ + public function is_switched() + { + } + /** + * Filters the locale of the WordPress installation. + * + * @since 4.7.0 + * + * @param string $locale The locale of the WordPress installation. + * @return string The locale currently being switched to. + */ + public function filter_locale($locale) + { + } + } + /** + * Locale API: WP_Locale class + * + * @package WordPress + * @subpackage i18n + * @since 4.6.0 + */ + /** + * Core class used to store translated data for a locale. + * + * @since 2.1.0 + * @since 4.6.0 Moved to its own file from wp-includes/locale.php. + */ + #[\AllowDynamicProperties] + class WP_Locale + { + /** + * Stores the translated strings for the full weekday names. + * + * @since 2.1.0 + * @var string[] + */ + public $weekday; + /** + * Stores the translated strings for the one character weekday names. + * + * There is a hack to make sure that Tuesday and Thursday, as well + * as Sunday and Saturday, don't conflict. See init() method for more. + * + * @see WP_Locale::init() for how to handle the hack. + * + * @since 2.1.0 + * @var string[] + */ + public $weekday_initial; + /** + * Stores the translated strings for the abbreviated weekday names. + * + * @since 2.1.0 + * @var string[] + */ + public $weekday_abbrev; + /** + * Stores the translated strings for the full month names. + * + * @since 2.1.0 + * @var string[] + */ + public $month; + /** + * Stores the translated strings for the month names in genitive case, if the locale specifies. + * + * @since 4.4.0 + * @var string[] + */ + public $month_genitive; + /** + * Stores the translated strings for the abbreviated month names. + * + * @since 2.1.0 + * @var string[] + */ + public $month_abbrev; + /** + * Stores the translated strings for 'am' and 'pm'. + * + * Also the capitalized versions. + * + * @since 2.1.0 + * @var string[] + */ + public $meridiem; + /** + * The text direction of the locale language. + * + * Default is left to right 'ltr'. + * + * @since 2.1.0 + * @var string + */ + public $text_direction = 'ltr'; + /** + * The thousands separator and decimal point values used for localizing numbers. + * + * @since 2.3.0 + * @var array + */ + public $number_format; + /** + * The separator string used for localizing list item separator. + * + * @since 6.0.0 + * @var string + */ + public $list_item_separator; + /** + * Constructor which calls helper methods to set up object variables. + * + * @since 2.1.0 + */ + public function __construct() + { + } + /** + * Sets up the translated strings and object properties. + * + * The method creates the translatable strings for various + * calendar elements. Which allows for specifying locale + * specific calendar names and text direction. + * + * @since 2.1.0 + * + * @global string $text_direction + * @global string $wp_version The WordPress version string. + */ + public function init() + { + } + /** + * Retrieves the full translated weekday word. + * + * Week starts on translated Sunday and can be fetched + * by using 0 (zero). So the week starts with 0 (zero) + * and ends on Saturday with is fetched by using 6 (six). + * + * @since 2.1.0 + * + * @param int $weekday_number 0 for Sunday through 6 Saturday. + * @return string Full translated weekday. + */ + public function get_weekday($weekday_number) + { + } + /** + * Retrieves the translated weekday initial. + * + * The weekday initial is retrieved by the translated + * full weekday word. When translating the weekday initial + * pay attention to make sure that the starting letter does + * not conflict. + * + * @since 2.1.0 + * + * @param string $weekday_name Full translated weekday word. + * @return string Translated weekday initial. + */ + public function get_weekday_initial($weekday_name) + { + } + /** + * Retrieves the translated weekday abbreviation. + * + * The weekday abbreviation is retrieved by the translated + * full weekday word. + * + * @since 2.1.0 + * + * @param string $weekday_name Full translated weekday word. + * @return string Translated weekday abbreviation. + */ + public function get_weekday_abbrev($weekday_name) + { + } + /** + * Retrieves the full translated month by month number. + * + * The $month_number parameter has to be a string + * because it must have the '0' in front of any number + * that is less than 10. Starts from '01' and ends at + * '12'. + * + * You can use an integer instead and it will add the + * '0' before the numbers less than 10 for you. + * + * @since 2.1.0 + * + * @param string|int $month_number '01' through '12'. + * @return string Translated full month name. + */ + public function get_month($month_number) + { + } + /** + * Retrieves translated version of month abbreviation string. + * + * The $month_name parameter is expected to be the translated or + * translatable version of the month. + * + * @since 2.1.0 + * + * @param string $month_name Translated month to get abbreviated version. + * @return string Translated abbreviated month. + */ + public function get_month_abbrev($month_name) + { + } + /** + * Retrieves translated version of meridiem string. + * + * The $meridiem parameter is expected to not be translated. + * + * @since 2.1.0 + * + * @param string $meridiem Either 'am', 'pm', 'AM', or 'PM'. Not translated version. + * @return string Translated version + */ + public function get_meridiem($meridiem) + { + } + /** + * Global variables are deprecated. + * + * For backward compatibility only. + * + * @deprecated For backward compatibility only. + * + * @global array $weekday + * @global array $weekday_initial + * @global array $weekday_abbrev + * @global array $month + * @global array $month_abbrev + * + * @since 2.1.0 + */ + public function register_globals() + { + } + /** + * Checks if current locale is RTL. + * + * @since 3.0.0 + * @return bool Whether locale is RTL. + */ + public function is_rtl() + { + } + /** + * Registers date/time format strings for general POT. + * + * Private, unused method to add some date/time formats translated + * on wp-admin/options-general.php to the general POT that would + * otherwise be added to the admin POT. + * + * @since 3.6.0 + */ + public function _strings_for_pot() + { + } + /** + * Retrieves the localized list item separator. + * + * @since 6.0.0 + * + * @return string Localized list item separator. + */ + public function get_list_item_separator() + { + } + } + /** + * WP_MatchesMapRegex helper class + * + * @package WordPress + * @since 4.7.0 + */ + /** + * Helper class to remove the need to use eval to replace $matches[] in query strings. + * + * @since 2.9.0 + */ + #[\AllowDynamicProperties] + class WP_MatchesMapRegex + { + /** + * store for mapping result + * + * @var string + */ + public $output; + /** + * regexp pattern to match $matches[] references + * + * @var string + */ + public $_pattern = '(\\$matches\\[[1-9]+[0-9]*\\])'; + // Magic number. + /** + * constructor + * + * @param string $subject subject if regex + * @param array $matches data to use in map + */ + public function __construct($subject, $matches) + { + } + /** + * Substitute substring matches in subject. + * + * static helper function to ease use + * + * @param string $subject subject + * @param array $matches data used for substitution + * @return string + */ + public static function apply($subject, $matches) + { + } + /** + * preg_replace_callback hook + * + * @param array $matches preg_replace regexp matches + * @return string + */ + public function callback($matches) + { + } + } + /** + * Meta API: WP_Meta_Query class + * + * @package WordPress + * @subpackage Meta + * @since 4.4.0 + */ + /** + * Core class used to implement meta queries for the Meta API. + * + * Used for generating SQL clauses that filter a primary query according to metadata keys and values. + * + * WP_Meta_Query is a helper that allows primary query classes, such as WP_Query and WP_User_Query, + * + * to filter their results by object metadata, by generating `JOIN` and `WHERE` subclauses to be attached + * to the primary SQL query string. + * + * @since 3.2.0 + */ + #[\AllowDynamicProperties] + class WP_Meta_Query + { + /** + * Array of metadata queries. + * + * See WP_Meta_Query::__construct() for information on meta query arguments. + * + * @since 3.2.0 + * @var array + */ + public $queries = array(); + /** + * The relation between the queries. Can be one of 'AND' or 'OR'. + * + * @since 3.2.0 + * @var string + */ + public $relation; + /** + * Database table to query for the metadata. + * + * @since 4.1.0 + * @var string + */ + public $meta_table; + /** + * Column in meta_table that represents the ID of the object the metadata belongs to. + * + * @since 4.1.0 + * @var string + */ + public $meta_id_column; + /** + * Database table that where the metadata's objects are stored (eg $wpdb->users). + * + * @since 4.1.0 + * @var string + */ + public $primary_table; + /** + * Column in primary_table that represents the ID of the object. + * + * @since 4.1.0 + * @var string + */ + public $primary_id_column; + /** + * A flat list of table aliases used in JOIN clauses. + * + * @since 4.1.0 + * @var array + */ + protected $table_aliases = array(); + /** + * A flat list of clauses, keyed by clause 'name'. + * + * @since 4.2.0 + * @var array + */ + protected $clauses = array(); + /** + * Whether the query contains any OR relations. + * + * @since 4.3.0 + * @var bool + */ + protected $has_or_relation = \false; + /** + * Constructor. + * + * @since 3.2.0 + * @since 4.2.0 Introduced support for naming query clauses by associative array keys. + * @since 5.1.0 Introduced `$compare_key` clause parameter, which enables LIKE key matches. + * @since 5.3.0 Increased the number of operators available to `$compare_key`. Introduced `$type_key`, + * which enables the `$key` to be cast to a new data type for comparisons. + * + * @param array $meta_query { + * Array of meta query clauses. When first-order clauses or sub-clauses use strings as + * their array keys, they may be referenced in the 'orderby' parameter of the parent query. + * + * @type string $relation Optional. The MySQL keyword used to join the clauses of the query. + * Accepts 'AND' or 'OR'. Default 'AND'. + * @type array ...$0 { + * Optional. An array of first-order clause parameters, or another fully-formed meta query. + * + * @type string|string[] $key Meta key or keys to filter by. + * @type string $compare_key MySQL operator used for comparing the $key. Accepts: + * - '=' + * - '!=' + * - 'LIKE' + * - 'NOT LIKE' + * - 'IN' + * - 'NOT IN' + * - 'REGEXP' + * - 'NOT REGEXP' + * - 'RLIKE', + * - 'EXISTS' (alias of '=') + * - 'NOT EXISTS' (alias of '!=') + * Default is 'IN' when `$key` is an array, '=' otherwise. + * @type string $type_key MySQL data type that the meta_key column will be CAST to for + * comparisons. Accepts 'BINARY' for case-sensitive regular expression + * comparisons. Default is ''. + * @type string|string[] $value Meta value or values to filter by. + * @type string $compare MySQL operator used for comparing the $value. Accepts: + * - '=', + * - '!=' + * - '>' + * - '>=' + * - '<' + * - '<=' + * - 'LIKE' + * - 'NOT LIKE' + * - 'IN' + * - 'NOT IN' + * - 'BETWEEN' + * - 'NOT BETWEEN' + * - 'REGEXP' + * - 'NOT REGEXP' + * - 'RLIKE' + * - 'EXISTS' + * - 'NOT EXISTS' + * Default is 'IN' when `$value` is an array, '=' otherwise. + * @type string $type MySQL data type that the meta_value column will be CAST to for + * comparisons. Accepts: + * - 'NUMERIC' + * - 'BINARY' + * - 'CHAR' + * - 'DATE' + * - 'DATETIME' + * - 'DECIMAL' + * - 'SIGNED' + * - 'TIME' + * - 'UNSIGNED' + * Default is 'CHAR'. + * } + * } + */ + public function __construct($meta_query = \false) + { + } + /** + * Ensure the 'meta_query' argument passed to the class constructor is well-formed. + * + * Eliminates empty items and ensures that a 'relation' is set. + * + * @since 4.1.0 + * + * @param array $queries Array of query clauses. + * @return array Sanitized array of query clauses. + */ + public function sanitize_query($queries) + { + } + /** + * Determine whether a query clause is first-order. + * + * A first-order meta query clause is one that has either a 'key' or + * a 'value' array key. + * + * @since 4.1.0 + * + * @param array $query Meta query arguments. + * @return bool Whether the query clause is a first-order clause. + */ + protected function is_first_order_clause($query) + { + } + /** + * Constructs a meta query based on 'meta_*' query vars + * + * @since 3.2.0 + * + * @param array $qv The query variables + */ + public function parse_query_vars($qv) + { + } + /** + * Return the appropriate alias for the given meta type if applicable. + * + * @since 3.7.0 + * + * @param string $type MySQL type to cast meta_value. + * @return string MySQL type. + */ + public function get_cast_for_type($type = '') + { + } + /** + * Generates SQL clauses to be appended to a main query. + * + * @since 3.2.0 + * + * @param string $type Type of meta. Possible values include but are not limited + * to 'post', 'comment', 'blog', 'term', and 'user'. + * @param string $primary_table Database table where the object being filtered is stored (eg wp_users). + * @param string $primary_id_column ID column for the filtered object in $primary_table. + * @param object $context Optional. The main query object that corresponds to the type, for + * example a `WP_Query`, `WP_User_Query`, or `WP_Site_Query`. + * @return string[]|false { + * Array containing JOIN and WHERE SQL clauses to append to the main query, + * or false if no table exists for the requested meta type. + * + * @type string $join SQL fragment to append to the main JOIN clause. + * @type string $where SQL fragment to append to the main WHERE clause. + * } + * @phpstan-return false|array{ + * join: string, + * where: string, + * } + */ + public function get_sql($type, $primary_table, $primary_id_column, $context = \null) + { + } + /** + * Generate SQL clauses to be appended to a main query. + * + * Called by the public WP_Meta_Query::get_sql(), this method is abstracted + * out to maintain parity with the other Query classes. + * + * @since 4.1.0 + * + * @return string[] { + * Array containing JOIN and WHERE SQL clauses to append to the main query. + * + * @type string $join SQL fragment to append to the main JOIN clause. + * @type string $where SQL fragment to append to the main WHERE clause. + * } + * @phpstan-return array{ + * join: string, + * where: string, + * } + */ + protected function get_sql_clauses() + { + } + /** + * Generate SQL clauses for a single query array. + * + * If nested subqueries are found, this method recurses the tree to + * produce the properly nested SQL. + * + * @since 4.1.0 + * + * @param array $query Query to parse (passed by reference). + * @param int $depth Optional. Number of tree levels deep we currently are. + * Used to calculate indentation. Default 0. + * @return string[] { + * Array containing JOIN and WHERE SQL clauses to append to a single query array. + * + * @type string $join SQL fragment to append to the main JOIN clause. + * @type string $where SQL fragment to append to the main WHERE clause. + * } + * @phpstan-return array{ + * join: string, + * where: string, + * } + */ + protected function get_sql_for_query(&$query, $depth = 0) + { + } + /** + * Generate SQL JOIN and WHERE clauses for a first-order query clause. + * + * "First-order" means that it's an array with a 'key' or 'value'. + * + * @since 4.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $clause Query clause (passed by reference). + * @param array $parent_query Parent query array. + * @param string $clause_key Optional. The array key used to name the clause in the original `$meta_query` + * parameters. If not provided, a key will be generated automatically. + * @return string[] { + * Array containing JOIN and WHERE SQL clauses to append to a first-order query. + * + * @type string $join SQL fragment to append to the main JOIN clause. + * @type string $where SQL fragment to append to the main WHERE clause. + * } + * @phpstan-return array{ + * join: string, + * where: string, + * } + */ + public function get_sql_for_clause(&$clause, $parent_query, $clause_key = '') + { + } + /** + * Get a flattened list of sanitized meta clauses. + * + * This array should be used for clause lookup, as when the table alias and CAST type must be determined for + * a value of 'orderby' corresponding to a meta clause. + * + * @since 4.2.0 + * + * @return array Meta clauses. + */ + public function get_clauses() + { + } + /** + * Identify an existing table alias that is compatible with the current + * query clause. + * + * We avoid unnecessary table joins by allowing each clause to look for + * an existing table alias that is compatible with the query that it + * needs to perform. + * + * An existing alias is compatible if (a) it is a sibling of `$clause` + * (ie, it's under the scope of the same relation), and (b) the combination + * of operator and relation between the clauses allows for a shared table join. + * In the case of WP_Meta_Query, this only applies to 'IN' clauses that are + * connected by the relation 'OR'. + * + * @since 4.1.0 + * + * @param array $clause Query clause. + * @param array $parent_query Parent query of $clause. + * @return string|false Table alias if found, otherwise false. + */ + protected function find_compatible_table_alias($clause, $parent_query) + { + } + /** + * Checks whether the current query has any OR relations. + * + * In some cases, the presence of an OR relation somewhere in the query will require + * the use of a `DISTINCT` or `GROUP BY` keyword in the `SELECT` clause. The current + * method can be used in these cases to determine whether such a clause is necessary. + * + * @since 4.3.0 + * + * @return bool True if the query contains any `OR` relations, otherwise false. + */ + public function has_or_relation() + { + } + } + /** + * Meta API: WP_Metadata_Lazyloader class + * + * @package WordPress + * @subpackage Meta + * @since 4.5.0 + */ + /** + * Core class used for lazy-loading object metadata. + * + * When loading many objects of a given type, such as posts in a WP_Query loop, it often makes + * sense to prime various metadata caches at the beginning of the loop. This means fetching all + * relevant metadata with a single database query, a technique that has the potential to improve + * performance dramatically in some cases. + * + * In cases where the given metadata may not even be used in the loop, we can improve performance + * even more by only priming the metadata cache for affected items the first time a piece of metadata + * is requested - ie, by lazy-loading it. So, for example, comment meta may not be loaded into the + * cache in the comments section of a post until the first time get_comment_meta() is called in the + * context of the comment loop. + * + * WP uses the WP_Metadata_Lazyloader class to queue objects for metadata cache priming. The class + * then detects the relevant get_*_meta() function call, and queries the metadata of all queued objects. + * + * Do not access this class directly. Use the wp_metadata_lazyloader() function. + * + * @since 4.5.0 + */ + #[\AllowDynamicProperties] + class WP_Metadata_Lazyloader + { + /** + * Pending objects queue. + * + * @since 4.5.0 + * @var array + */ + protected $pending_objects; + /** + * Settings for supported object types. + * + * @since 4.5.0 + * @var array + */ + protected $settings = array(); + /** + * Constructor. + * + * @since 4.5.0 + */ + public function __construct() + { + } + /** + * Adds objects to the metadata lazy-load queue. + * + * @since 4.5.0 + * + * @param string $object_type Type of object whose meta is to be lazy-loaded. Accepts 'term' or 'comment'. + * @param array $object_ids Array of object IDs. + * @return void|WP_Error WP_Error on failure. + */ + public function queue_objects($object_type, $object_ids) + { + } + /** + * Resets lazy-load queue for a given object type. + * + * @since 4.5.0 + * + * @param string $object_type Object type. Accepts 'comment' or 'term'. + * @return void|WP_Error WP_Error on failure. + */ + public function reset_queue($object_type) + { + } + /** + * Lazy-loads term meta for queued terms. + * + * This method is public so that it can be used as a filter callback. As a rule, there + * is no need to invoke it directly. + * + * @since 4.5.0 + * + * @param mixed $check The `$check` param passed from the 'get_term_metadata' hook. + * @return mixed In order not to short-circuit `get_metadata()`. Generally, this is `null`, but it could be + * another value if filtered by a plugin. + */ + public function lazyload_term_meta($check) + { + } + /** + * Lazy-loads comment meta for queued comments. + * + * This method is public so that it can be used as a filter callback. As a rule, there is no need to invoke it + * directly, from either inside or outside the `WP_Query` object. + * + * @since 4.5.0 + * + * @param mixed $check The `$check` param passed from the {@see 'get_comment_metadata'} hook. + * @return mixed The original value of `$check`, so as not to short-circuit `get_comment_metadata()`. + */ + public function lazyload_comment_meta($check) + { + } + } + /** + * Network API: WP_Network_Query class + * + * @package WordPress + * @subpackage Multisite + * @since 4.6.0 + */ + /** + * Core class used for querying networks. + * + * @since 4.6.0 + * + * @see WP_Network_Query::__construct() for accepted arguments. + */ + #[\AllowDynamicProperties] + class WP_Network_Query + { + /** + * SQL for database query. + * + * @since 4.6.0 + * @var string + */ + public $request; + /** + * SQL query clauses. + * + * @since 4.6.0 + * @var array + */ + protected $sql_clauses = array('select' => '', 'from' => '', 'where' => array(), 'groupby' => '', 'orderby' => '', 'limits' => ''); + /** + * Query vars set by the user. + * + * @since 4.6.0 + * @var array + */ + public $query_vars; + /** + * Default values for query vars. + * + * @since 4.6.0 + * @var array + */ + public $query_var_defaults; + /** + * List of networks located by the query. + * + * @since 4.6.0 + * @var array + */ + public $networks; + /** + * The amount of found networks for the current query. + * + * @since 4.6.0 + * @var int + */ + public $found_networks = 0; + /** + * The number of pages. + * + * @since 4.6.0 + * @var int + */ + public $max_num_pages = 0; + /** + * Constructor. + * + * Sets up the network query, based on the query vars passed. + * + * @since 4.6.0 + * + * @param string|array $query { + * Optional. Array or query string of network query parameters. Default empty. + * + * @type int[] $network__in Array of network IDs to include. Default empty. + * @type int[] $network__not_in Array of network IDs to exclude. Default empty. + * @type bool $count Whether to return a network count (true) or array of network objects. + * Default false. + * @type string $fields Network fields to return. Accepts 'ids' (returns an array of network IDs) + * or empty (returns an array of complete network objects). Default empty. + * @type int $number Maximum number of networks to retrieve. Default empty (no limit). + * @type int $offset Number of networks to offset the query. Used to build LIMIT clause. + * Default 0. + * @type bool $no_found_rows Whether to disable the `SQL_CALC_FOUND_ROWS` query. Default true. + * @type string|array $orderby Network status or array of statuses. Accepts 'id', 'domain', 'path', + * 'domain_length', 'path_length' and 'network__in'. Also accepts false, + * an empty array, or 'none' to disable `ORDER BY` clause. Default 'id'. + * @type string $order How to order retrieved networks. Accepts 'ASC', 'DESC'. Default 'ASC'. + * @type string $domain Limit results to those affiliated with a given domain. Default empty. + * @type string[] $domain__in Array of domains to include affiliated networks for. Default empty. + * @type string[] $domain__not_in Array of domains to exclude affiliated networks for. Default empty. + * @type string $path Limit results to those affiliated with a given path. Default empty. + * @type string[] $path__in Array of paths to include affiliated networks for. Default empty. + * @type string[] $path__not_in Array of paths to exclude affiliated networks for. Default empty. + * @type string $search Search term(s) to retrieve matching networks for. Default empty. + * @type bool $update_network_cache Whether to prime the cache for found networks. Default true. + * } + * @phpstan-param array{ + * network__in?: int[], + * network__not_in?: int[], + * count?: bool, + * fields?: string, + * number?: int, + * offset?: int, + * no_found_rows?: bool, + * orderby?: string|array, + * order?: string, + * domain?: string, + * domain__in?: string[], + * domain__not_in?: string[], + * path?: string, + * path__in?: string[], + * path__not_in?: string[], + * search?: string, + * update_network_cache?: bool, + * } $query + */ + public function __construct($query = '') + { + } + /** + * Parses arguments passed to the network query with default query parameters. + * + * @since 4.6.0 + * + * @param string|array $query WP_Network_Query arguments. See WP_Network_Query::__construct() + * @phpstan-param array{ + * network__in?: int[], + * network__not_in?: int[], + * count?: bool, + * fields?: string, + * number?: int, + * offset?: int, + * no_found_rows?: bool, + * orderby?: string|array, + * order?: string, + * domain?: string, + * domain__in?: string[], + * domain__not_in?: string[], + * path?: string, + * path__in?: string[], + * path__not_in?: string[], + * search?: string, + * update_network_cache?: bool, + * } $query See WP_Network_Query::__construct() + */ + public function parse_query($query = '') + { + } + /** + * Sets up the WordPress query for retrieving networks. + * + * @since 4.6.0 + * + * @param string|array $query Array or URL query string of parameters. + * @return array|int List of WP_Network objects, a list of network IDs when 'fields' is set to 'ids', + * or the number of networks when 'count' is passed as a query var. + */ + public function query($query) + { + } + /** + * Gets a list of networks matching the query vars. + * + * @since 4.6.0 + * + * @return array|int List of WP_Network objects, a list of network IDs when 'fields' is set to 'ids', + * or the number of networks when 'count' is passed as a query var. + */ + public function get_networks() + { + } + /** + * Used internally to get a list of network IDs matching the query vars. + * + * @since 4.6.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return int|array A single count of network IDs if a count query. An array of network IDs if a full query. + */ + protected function get_network_ids() + { + } + /** + * Used internally to generate an SQL string for searching across multiple columns. + * + * @since 4.6.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $search Search string. + * @param string[] $columns Array of columns to search. + * @return string Search SQL. + */ + protected function get_search_sql($search, $columns) + { + } + /** + * Parses and sanitizes 'orderby' keys passed to the network query. + * + * @since 4.6.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $orderby Alias for the field to order by. + * @return string|false Value to used in the ORDER clause. False otherwise. + */ + protected function parse_orderby($orderby) + { + } + /** + * Parses an 'order' query variable and cast it to 'ASC' or 'DESC' as necessary. + * + * @since 4.6.0 + * + * @param string $order The 'order' query variable. + * @return string The sanitized 'order' query variable. + */ + protected function parse_order($order) + { + } + } + /** + * Network API: WP_Network class + * + * @package WordPress + * @subpackage Multisite + * @since 4.4.0 + */ + /** + * Core class used for interacting with a multisite network. + * + * This class is used during load to populate the `$current_site` global and + * setup the current network. + * + * This class is most useful in WordPress multi-network installations where the + * ability to interact with any network of sites is required. + * + * @since 4.4.0 + * + * @property int $id + * @property int $site_id + */ + #[\AllowDynamicProperties] + class WP_Network + { + /** + * Domain of the network. + * + * @since 4.4.0 + * @var string + */ + public $domain = ''; + /** + * Path of the network. + * + * @since 4.4.0 + * @var string + */ + public $path = ''; + /** + * Domain used to set cookies for this network. + * + * @since 4.4.0 + * @var string + */ + public $cookie_domain = ''; + /** + * Name of this network. + * + * Named "site" vs. "network" for legacy reasons. + * + * @since 4.4.0 + * @var string + */ + public $site_name = ''; + /** + * Retrieves a network from the database by its ID. + * + * @since 4.4.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $network_id The ID of the network to retrieve. + * @return WP_Network|false The network's object if found. False if not. + */ + public static function get_instance($network_id) + { + } + /** + * Creates a new WP_Network object. + * + * Will populate object properties from the object provided and assign other + * default properties based on that information. + * + * @since 4.4.0 + * + * @param WP_Network|object $network A network object. + */ + public function __construct($network) + { + } + /** + * Getter. + * + * Allows current multisite naming conventions when getting properties. + * + * @since 4.6.0 + * + * @param string $key Property to get. + * @return mixed Value of the property. Null if not available. + */ + public function __get($key) + { + } + /** + * Isset-er. + * + * Allows current multisite naming conventions when checking for properties. + * + * @since 4.6.0 + * + * @param string $key Property to check if set. + * @return bool Whether the property is set. + */ + public function __isset($key) + { + } + /** + * Setter. + * + * Allows current multisite naming conventions while setting properties. + * + * @since 4.6.0 + * + * @param string $key Property to set. + * @param mixed $value Value to assign to the property. + */ + public function __set($key, $value) + { + } + /** + * Retrieves the closest matching network for a domain and path. + * + * This will not necessarily return an exact match for a domain and path. Instead, it + * breaks the domain and path into pieces that are then used to match the closest + * possibility from a query. + * + * The intent of this method is to match a network during bootstrap for a + * requested site address. + * + * @since 4.4.0 + * + * @param string $domain Domain to check. + * @param string $path Path to check. + * @param int|null $segments Path segments to use. Defaults to null, or the full path. + * @return WP_Network|false Network object if successful. False when no network is found. + */ + public static function get_by_path($domain = '', $path = '', $segments = \null) + { + } + } + /** + * Object Cache API: WP_Object_Cache class + * + * @package WordPress + * @subpackage Cache + * @since 5.4.0 + */ + /** + * Core class that implements an object cache. + * + * The WordPress Object Cache is used to save on trips to the database. The + * Object Cache stores all of the cache data to memory and makes the cache + * contents available by using a key, which is used to name and later retrieve + * the cache contents. + * + * The Object Cache can be replaced by other caching mechanisms by placing files + * in the wp-content folder which is looked at in wp-settings. If that file + * exists, then this file will not be included. + * + * @since 2.0.0 + */ + #[\AllowDynamicProperties] + class WP_Object_Cache + { + /** + * The amount of times the cache data was already stored in the cache. + * + * @since 2.5.0 + * @var int + */ + public $cache_hits = 0; + /** + * Amount of times the cache did not have the request in cache. + * + * @since 2.0.0 + * @var int + */ + public $cache_misses = 0; + /** + * List of global cache groups. + * + * @since 3.0.0 + * @var string[] + */ + protected $global_groups = array(); + /** + * Sets up object properties; PHP 5 style constructor. + * + * @since 2.0.8 + */ + public function __construct() + { + } + /** + * Makes private properties readable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to get. + * @return mixed Property. + */ + public function __get($name) + { + } + /** + * Makes private properties settable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to set. + * @param mixed $value Property value. + * @return mixed Newly-set property. + */ + public function __set($name, $value) + { + } + /** + * Makes private properties checkable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to check if set. + * @return bool Whether the property is set. + */ + public function __isset($name) + { + } + /** + * Makes private properties un-settable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to unset. + */ + public function __unset($name) + { + } + /** + * Serves as a utility function to determine whether a key is valid. + * + * @since 6.1.0 + * + * @param int|string $key Cache key to check for validity. + * @return bool Whether the key is valid. + */ + protected function is_valid_key($key) + { + } + /** + * Serves as a utility function to determine whether a key exists in the cache. + * + * @since 3.4.0 + * + * @param int|string $key Cache key to check for existence. + * @param string $group Cache group for the key existence check. + * @return bool Whether the key exists in the cache for the given group. + */ + protected function _exists($key, $group) + { + } + /** + * Adds data to the cache if it doesn't already exist. + * + * @since 2.0.0 + * + * @uses WP_Object_Cache::_exists() Checks to see if the cache already has data. + * @uses WP_Object_Cache::set() Sets the data after the checking the cache + * contents existence. + * + * @param int|string $key What to call the contents in the cache. + * @param mixed $data The contents to store in the cache. + * @param string $group Optional. Where to group the cache contents. Default 'default'. + * @param int $expire Optional. When to expire the cache contents, in seconds. + * Default 0 (no expiration). + * @return bool True on success, false if cache key and group already exist. + */ + public function add($key, $data, $group = 'default', $expire = 0) + { + } + /** + * Adds multiple values to the cache in one call. + * + * @since 6.0.0 + * + * @param array $data Array of keys and values to be added. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @param int $expire Optional. When to expire the cache contents, in seconds. + * Default 0 (no expiration). + * @return bool[] Array of return values, grouped by key. Each value is either + * true on success, or false if cache key and group already exist. + */ + public function add_multiple(array $data, $group = '', $expire = 0) + { + } + /** + * Replaces the contents in the cache, if contents already exist. + * + * @since 2.0.0 + * + * @see WP_Object_Cache::set() + * + * @param int|string $key What to call the contents in the cache. + * @param mixed $data The contents to store in the cache. + * @param string $group Optional. Where to group the cache contents. Default 'default'. + * @param int $expire Optional. When to expire the cache contents, in seconds. + * Default 0 (no expiration). + * @return bool True if contents were replaced, false if original value does not exist. + */ + public function replace($key, $data, $group = 'default', $expire = 0) + { + } + /** + * Sets the data contents into the cache. + * + * The cache contents are grouped by the $group parameter followed by the + * $key. This allows for duplicate IDs in unique groups. Therefore, naming of + * the group should be used with care and should follow normal function + * naming guidelines outside of core WordPress usage. + * + * The $expire parameter is not used, because the cache will automatically + * expire for each time a page is accessed and PHP finishes. The method is + * more for cache plugins which use files. + * + * @since 2.0.0 + * @since 6.1.0 Returns false if cache key is invalid. + * + * @param int|string $key What to call the contents in the cache. + * @param mixed $data The contents to store in the cache. + * @param string $group Optional. Where to group the cache contents. Default 'default'. + * @param int $expire Optional. Not used. + * @return bool True if contents were set, false if key is invalid. + */ + public function set($key, $data, $group = 'default', $expire = 0) + { + } + /** + * Sets multiple values to the cache in one call. + * + * @since 6.0.0 + * + * @param array $data Array of key and value to be set. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @param int $expire Optional. When to expire the cache contents, in seconds. + * Default 0 (no expiration). + * @return bool[] Array of return values, grouped by key. Each value is always true. + */ + public function set_multiple(array $data, $group = '', $expire = 0) + { + } + /** + * Retrieves the cache contents, if it exists. + * + * The contents will be first attempted to be retrieved by searching by the + * key in the cache group. If the cache is hit (success) then the contents + * are returned. + * + * On failure, the number of cache misses will be incremented. + * + * @since 2.0.0 + * + * @param int|string $key The key under which the cache contents are stored. + * @param string $group Optional. Where the cache contents are grouped. Default 'default'. + * @param bool $force Optional. Unused. Whether to force an update of the local cache + * from the persistent cache. Default false. + * @param bool $found Optional. Whether the key was found in the cache (passed by reference). + * Disambiguates a return of false, a storable value. Default null. + * @return mixed|false The cache contents on success, false on failure to retrieve contents. + */ + public function get($key, $group = 'default', $force = \false, &$found = \null) + { + } + /** + * Retrieves multiple values from the cache in one call. + * + * @since 5.5.0 + * + * @param array $keys Array of keys under which the cache contents are stored. + * @param string $group Optional. Where the cache contents are grouped. Default 'default'. + * @param bool $force Optional. Whether to force an update of the local cache + * from the persistent cache. Default false. + * @return array Array of return values, grouped by key. Each value is either + * the cache contents on success, or false on failure. + */ + public function get_multiple($keys, $group = 'default', $force = \false) + { + } + /** + * Removes the contents of the cache key in the group. + * + * If the cache key does not exist in the group, then nothing will happen. + * + * @since 2.0.0 + * + * @param int|string $key What the contents in the cache are called. + * @param string $group Optional. Where the cache contents are grouped. Default 'default'. + * @param bool $deprecated Optional. Unused. Default false. + * @return bool True on success, false if the contents were not deleted. + */ + public function delete($key, $group = 'default', $deprecated = \false) + { + } + /** + * Deletes multiple values from the cache in one call. + * + * @since 6.0.0 + * + * @param array $keys Array of keys to be deleted. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @return bool[] Array of return values, grouped by key. Each value is either + * true on success, or false if the contents were not deleted. + */ + public function delete_multiple(array $keys, $group = '') + { + } + /** + * Increments numeric cache item's value. + * + * @since 3.3.0 + * + * @param int|string $key The cache key to increment. + * @param int $offset Optional. The amount by which to increment the item's value. + * Default 1. + * @param string $group Optional. The group the key is in. Default 'default'. + * @return int|false The item's new value on success, false on failure. + */ + public function incr($key, $offset = 1, $group = 'default') + { + } + /** + * Decrements numeric cache item's value. + * + * @since 3.3.0 + * + * @param int|string $key The cache key to decrement. + * @param int $offset Optional. The amount by which to decrement the item's value. + * Default 1. + * @param string $group Optional. The group the key is in. Default 'default'. + * @return int|false The item's new value on success, false on failure. + */ + public function decr($key, $offset = 1, $group = 'default') + { + } + /** + * Clears the object cache of all data. + * + * @since 2.0.0 + * + * @return true Always returns true. + */ + public function flush() + { + } + /** + * Removes all cache items in a group. + * + * @since 6.1.0 + * + * @param string $group Name of group to remove from cache. + * @return true Always returns true. + */ + public function flush_group($group) + { + } + /** + * Sets the list of global cache groups. + * + * @since 3.0.0 + * + * @param string|string[] $groups List of groups that are global. + */ + public function add_global_groups($groups) + { + } + /** + * Switches the internal blog ID. + * + * This changes the blog ID used to create keys in blog specific groups. + * + * @since 3.5.0 + * + * @param int $blog_id Blog ID. + */ + public function switch_to_blog($blog_id) + { + } + /** + * Resets cache keys. + * + * @since 3.0.0 + * + * @deprecated 3.5.0 Use WP_Object_Cache::switch_to_blog() + * @see switch_to_blog() + */ + public function reset() + { + } + /** + * Echoes the stats of the caching. + * + * Gives the cache hits, and cache misses. Also prints every cached group, + * key and the data. + * + * @since 2.0.0 + */ + public function stats() + { + } + } + /** + * WP_oEmbed_Controller class, used to provide an oEmbed endpoint. + * + * @package WordPress + * @subpackage Embeds + * @since 4.4.0 + */ + /** + * oEmbed API endpoint controller. + * + * Registers the REST API route and delivers the response data. + * The output format (XML or JSON) is handled by the REST API. + * + * @since 4.4.0 + */ + #[\AllowDynamicProperties] + final class WP_oEmbed_Controller + { + /** + * Register the oEmbed REST API route. + * + * @since 4.4.0 + */ + public function register_routes() + { + } + /** + * Callback for the embed API endpoint. + * + * Returns the JSON object for the post. + * + * @since 4.4.0 + * + * @param WP_REST_Request $request Full data about the request. + * @return array|WP_Error oEmbed response data or WP_Error on failure. + */ + public function get_item($request) + { + } + /** + * Checks if current user can make a proxy oEmbed request. + * + * @since 4.8.0 + * + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_proxy_item_permissions_check() + { + } + /** + * Callback for the proxy API endpoint. + * + * Returns the JSON object for the proxied item. + * + * @since 4.8.0 + * + * @see WP_oEmbed::get_html() + * @global WP_Embed $wp_embed + * + * @param WP_REST_Request $request Full data about the request. + * @return object|WP_Error oEmbed response data or WP_Error on failure. + */ + public function get_proxy_item($request) + { + } + } + /** + * API for fetching the HTML to embed remote content based on a provided URL + * + * Used internally by the WP_Embed class, but is designed to be generic. + * + * @link https://wordpress.org/support/article/embeds/ + * @link http://oembed.com/ + * + * @package WordPress + * @subpackage oEmbed + */ + /** + * Core class used to implement oEmbed functionality. + * + * @since 2.9.0 + */ + #[\AllowDynamicProperties] + class WP_oEmbed + { + /** + * A list of oEmbed providers. + * + * @since 2.9.0 + * @var array + */ + public $providers = array(); + /** + * A list of an early oEmbed providers. + * + * @since 4.0.0 + * @var array + */ + public static $early_providers = array(); + /** + * Constructor. + * + * @since 2.9.0 + */ + public function __construct() + { + } + /** + * Exposes private/protected methods for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Method to call. + * @param array $arguments Arguments to pass when calling. + * @return mixed|false Return value of the callback, false otherwise. + */ + public function __call($name, $arguments) + { + } + /** + * Takes a URL and returns the corresponding oEmbed provider's URL, if there is one. + * + * @since 4.0.0 + * + * @see WP_oEmbed::discover() + * + * @param string $url The URL to the content. + * @param string|array $args { + * Optional. Additional provider arguments. Default empty. + * + * @type bool $discover Optional. Determines whether to attempt to discover link tags + * at the given URL for an oEmbed provider when the provider URL + * is not found in the built-in providers list. Default true. + * } + * @return string|false The oEmbed provider URL on success, false on failure. + * @phpstan-param array{ + * discover?: bool, + * } $args + */ + public function get_provider($url, $args = '') + { + } + /** + * Adds an oEmbed provider. + * + * The provider is added just-in-time when wp_oembed_add_provider() is called before + * the {@see 'plugins_loaded'} hook. + * + * The just-in-time addition is for the benefit of the {@see 'oembed_providers'} filter. + * + * @since 4.0.0 + * + * @see wp_oembed_add_provider() + * + * @param string $format Format of URL that this provider can handle. You can use + * asterisks as wildcards. + * @param string $provider The URL to the oEmbed provider.. + * @param bool $regex Optional. Whether the $format parameter is in a regex format. + * Default false. + */ + public static function _add_provider_early($format, $provider, $regex = \false) + { + } + /** + * Removes an oEmbed provider. + * + * The provider is removed just-in-time when wp_oembed_remove_provider() is called before + * the {@see 'plugins_loaded'} hook. + * + * The just-in-time removal is for the benefit of the {@see 'oembed_providers'} filter. + * + * @since 4.0.0 + * + * @see wp_oembed_remove_provider() + * + * @param string $format The format of URL that this provider can handle. You can use + * asterisks as wildcards. + */ + public static function _remove_provider_early($format) + { + } + /** + * Takes a URL and attempts to return the oEmbed data. + * + * @see WP_oEmbed::fetch() + * + * @since 4.8.0 + * + * @param string $url The URL to the content that should be attempted to be embedded. + * @param string|array $args Optional. Additional arguments for retrieving embed HTML. + * See wp_oembed_get() for accepted arguments. Default empty. + * @return object|false The result in the form of an object on success, false on failure. + * @phpstan-param array{ + * width?: int|string, + * height?: int|string, + * discover?: bool, + * } $args See wp_oembed_get() + */ + public function get_data($url, $args = '') + { + } + /** + * The do-it-all function that takes a URL and attempts to return the HTML. + * + * @see WP_oEmbed::fetch() + * @see WP_oEmbed::data2html() + * + * @since 2.9.0 + * + * @param string $url The URL to the content that should be attempted to be embedded. + * @param string|array $args Optional. Additional arguments for retrieving embed HTML. + * See wp_oembed_get() for accepted arguments. Default empty. + * @return string|false The UNSANITIZED (and potentially unsafe) HTML that should be used to embed + * on success, false on failure. + * @phpstan-param array{ + * width?: int|string, + * height?: int|string, + * discover?: bool, + * } $args See wp_oembed_get() + */ + public function get_html($url, $args = '') + { + } + /** + * Attempts to discover link tags at the given URL for an oEmbed provider. + * + * @since 2.9.0 + * + * @param string $url The URL that should be inspected for discovery `<link>` tags. + * @return string|false The oEmbed provider URL on success, false on failure. + */ + public function discover($url) + { + } + /** + * Connects to a oEmbed provider and returns the result. + * + * @since 2.9.0 + * + * @param string $provider The URL to the oEmbed provider. + * @param string $url The URL to the content that is desired to be embedded. + * @param string|array $args Optional. Additional arguments for retrieving embed HTML. + * See wp_oembed_get() for accepted arguments. Default empty. + * @return object|false The result in the form of an object on success, false on failure. + * @phpstan-param array{ + * width?: int|string, + * height?: int|string, + * discover?: bool, + * } $args See wp_oembed_get() + */ + public function fetch($provider, $url, $args = '') + { + } + /** + * Converts a data object from WP_oEmbed::fetch() and returns the HTML. + * + * @since 2.9.0 + * + * @param object $data A data object result from an oEmbed provider. + * @param string $url The URL to the content that is desired to be embedded. + * @return string|false The HTML needed to embed on success, false on failure. + */ + public function data2html($data, $url) + { + } + /** + * Strips any new lines from the HTML. + * + * @since 2.9.0 as strip_scribd_newlines() + * @since 3.0.0 + * + * @param string $html Existing HTML. + * @param object $data Data object from WP_oEmbed::data2html() + * @param string $url The original URL passed to oEmbed. + * @return string Possibly modified $html + */ + public function _strip_newlines($html, $data, $url) + { + } + } + /** + * Error Protection API: WP_Paused_Extensions_Storage class + * + * @package WordPress + * @since 5.2.0 + */ + /** + * Core class used for storing paused extensions. + * + * @since 5.2.0 + */ + #[\AllowDynamicProperties] + class WP_Paused_Extensions_Storage + { + /** + * Type of extension. Used to key extension storage. + * + * @since 5.2.0 + * @var string + */ + protected $type; + /** + * Constructor. + * + * @since 5.2.0 + * + * @param string $extension_type Extension type. Either 'plugin' or 'theme'. + */ + public function __construct($extension_type) + { + } + /** + * Records an extension error. + * + * Only one error is stored per extension, with subsequent errors for the same extension overriding the + * previously stored error. + * + * @since 5.2.0 + * + * @param string $extension Plugin or theme directory name. + * @param array $error { + * Error information returned by `error_get_last()`. + * + * @type int $type The error type. + * @type string $file The name of the file in which the error occurred. + * @type int $line The line number in which the error occurred. + * @type string $message The error message. + * } + * @return bool True on success, false on failure. + * @phpstan-param array{ + * type?: int, + * file?: string, + * line?: int, + * message?: string, + * } $error + */ + public function set($extension, $error) + { + } + /** + * Forgets a previously recorded extension error. + * + * @since 5.2.0 + * + * @param string $extension Plugin or theme directory name. + * @return bool True on success, false on failure. + */ + public function delete($extension) + { + } + /** + * Gets the error for an extension, if paused. + * + * @since 5.2.0 + * + * @param string $extension Plugin or theme directory name. + * @return array|null Error that is stored, or null if the extension is not paused. + */ + public function get($extension) + { + } + /** + * Gets the paused extensions with their errors. + * + * @since 5.2.0 + * + * @return array { + * Associative array of errors keyed by extension slug. + * + * @type array ...$0 Error information returned by `error_get_last()`. + * } + * @phpstan-return array<int|string, array> + */ + public function get_all() + { + } + /** + * Remove all paused extensions. + * + * @since 5.2.0 + * + * @return bool + */ + public function delete_all() + { + } + /** + * Checks whether the underlying API to store paused extensions is loaded. + * + * @since 5.2.0 + * + * @return bool True if the API is loaded, false otherwise. + */ + protected function is_api_loaded() + { + } + /** + * Get the option name for storing paused extensions. + * + * @since 5.2.0 + * + * @return string + */ + protected function get_option_name() + { + } + } + /** + * Post API: WP_Post_Type class + * + * @package WordPress + * @subpackage Post + * @since 4.6.0 + */ + /** + * Core class used for interacting with post types. + * + * @since 4.6.0 + * + * @see register_post_type() + */ + #[\AllowDynamicProperties] + final class WP_Post_Type + { + /** + * Post type key. + * + * @since 4.6.0 + * @var string $name + */ + public $name; + /** + * Name of the post type shown in the menu. Usually plural. + * + * @since 4.6.0 + * @var string $label + */ + public $label; + /** + * Labels object for this post type. + * + * If not set, post labels are inherited for non-hierarchical types + * and page labels for hierarchical ones. + * + * @see get_post_type_labels() + * + * @since 4.6.0 + * @var stdClass $labels + */ + public $labels; + /** + * A short descriptive summary of what the post type is. + * + * Default empty. + * + * @since 4.6.0 + * @var string $description + */ + public $description = ''; + /** + * Whether a post type is intended for use publicly either via the admin interface or by front-end users. + * + * While the default settings of $exclude_from_search, $publicly_queryable, $show_ui, and $show_in_nav_menus + * are inherited from public, each does not rely on this relationship and controls a very specific intention. + * + * Default false. + * + * @since 4.6.0 + * @var bool $public + */ + public $public = \false; + /** + * Whether the post type is hierarchical (e.g. page). + * + * Default false. + * + * @since 4.6.0 + * @var bool $hierarchical + */ + public $hierarchical = \false; + /** + * Whether to exclude posts with this post type from front end search + * results. + * + * Default is the opposite value of $public. + * + * @since 4.6.0 + * @var bool $exclude_from_search + */ + public $exclude_from_search = \null; + /** + * Whether queries can be performed on the front end for the post type as part of `parse_request()`. + * + * Endpoints would include: + * + * - `?post_type={post_type_key}` + * - `?{post_type_key}={single_post_slug}` + * - `?{post_type_query_var}={single_post_slug}` + * + * Default is the value of $public. + * + * @since 4.6.0 + * @var bool $publicly_queryable + */ + public $publicly_queryable = \null; + /** + * Whether to generate and allow a UI for managing this post type in the admin. + * + * Default is the value of $public. + * + * @since 4.6.0 + * @var bool $show_ui + */ + public $show_ui = \null; + /** + * Where to show the post type in the admin menu. + * + * To work, $show_ui must be true. If true, the post type is shown in its own top level menu. If false, no menu is + * shown. If a string of an existing top level menu ('tools.php' or 'edit.php?post_type=page', for example), the + * post type will be placed as a sub-menu of that. + * + * Default is the value of $show_ui. + * + * @since 4.6.0 + * @var bool|string $show_in_menu + */ + public $show_in_menu = \null; + /** + * Makes this post type available for selection in navigation menus. + * + * Default is the value $public. + * + * @since 4.6.0 + * @var bool $show_in_nav_menus + */ + public $show_in_nav_menus = \null; + /** + * Makes this post type available via the admin bar. + * + * Default is the value of $show_in_menu. + * + * @since 4.6.0 + * @var bool $show_in_admin_bar + */ + public $show_in_admin_bar = \null; + /** + * The position in the menu order the post type should appear. + * + * To work, $show_in_menu must be true. Default null (at the bottom). + * + * @since 4.6.0 + * @var int $menu_position + */ + public $menu_position = \null; + /** + * The URL or reference to the icon to be used for this menu. + * + * Pass a base64-encoded SVG using a data URI, which will be colored to match the color scheme. + * This should begin with 'data:image/svg+xml;base64,'. Pass the name of a Dashicons helper class + * to use a font icon, e.g. 'dashicons-chart-pie'. Pass 'none' to leave div.wp-menu-image empty + * so an icon can be added via CSS. + * + * Defaults to use the posts icon. + * + * @since 4.6.0 + * @var string $menu_icon + */ + public $menu_icon = \null; + /** + * The string to use to build the read, edit, and delete capabilities. + * + * May be passed as an array to allow for alternative plurals when using + * this argument as a base to construct the capabilities, e.g. + * array( 'story', 'stories' ). Default 'post'. + * + * @since 4.6.0 + * @var string $capability_type + */ + public $capability_type = 'post'; + /** + * Whether to use the internal default meta capability handling. + * + * Default false. + * + * @since 4.6.0 + * @var bool $map_meta_cap + */ + public $map_meta_cap = \false; + /** + * Provide a callback function that sets up the meta boxes for the edit form. + * + * Do `remove_meta_box()` and `add_meta_box()` calls in the callback. Default null. + * + * @since 4.6.0 + * @var callable $register_meta_box_cb + */ + public $register_meta_box_cb = \null; + /** + * An array of taxonomy identifiers that will be registered for the post type. + * + * Taxonomies can be registered later with `register_taxonomy()` or `register_taxonomy_for_object_type()`. + * + * Default empty array. + * + * @since 4.6.0 + * @var string[] $taxonomies + */ + public $taxonomies = array(); + /** + * Whether there should be post type archives, or if a string, the archive slug to use. + * + * Will generate the proper rewrite rules if $rewrite is enabled. Default false. + * + * @since 4.6.0 + * @var bool|string $has_archive + */ + public $has_archive = \false; + /** + * Sets the query_var key for this post type. + * + * Defaults to $post_type key. If false, a post type cannot be loaded at `?{query_var}={post_slug}`. + * If specified as a string, the query `?{query_var_string}={post_slug}` will be valid. + * + * @since 4.6.0 + * @var string|bool $query_var + */ + public $query_var; + /** + * Whether to allow this post type to be exported. + * + * Default true. + * + * @since 4.6.0 + * @var bool $can_export + */ + public $can_export = \true; + /** + * Whether to delete posts of this type when deleting a user. + * + * - If true, posts of this type belonging to the user will be moved to Trash when the user is deleted. + * - If false, posts of this type belonging to the user will *not* be trashed or deleted. + * - If not set (the default), posts are trashed if post type supports the 'author' feature. + * Otherwise posts are not trashed or deleted. + * + * Default null. + * + * @since 4.6.0 + * @var bool $delete_with_user + */ + public $delete_with_user = \null; + /** + * Array of blocks to use as the default initial state for an editor session. + * + * Each item should be an array containing block name and optional attributes. + * + * Default empty array. + * + * @link https://developer.wordpress.org/block-editor/developers/block-api/block-templates/ + * + * @since 5.0.0 + * @var array[] $template + */ + public $template = array(); + /** + * Whether the block template should be locked if $template is set. + * + * - If set to 'all', the user is unable to insert new blocks, move existing blocks + * and delete blocks. + * - If set to 'insert', the user is able to move existing blocks but is unable to insert + * new blocks and delete blocks. + * + * Default false. + * + * @link https://developer.wordpress.org/block-editor/developers/block-api/block-templates/ + * + * @since 5.0.0 + * @var string|false $template_lock + */ + public $template_lock = \false; + /** + * Whether this post type is a native or "built-in" post_type. + * + * Default false. + * + * @since 4.6.0 + * @var bool $_builtin + */ + public $_builtin = \false; + /** + * URL segment to use for edit link of this post type. + * + * Default 'post.php?post=%d'. + * + * @since 4.6.0 + * @var string $_edit_link + */ + public $_edit_link = 'post.php?post=%d'; + /** + * Post type capabilities. + * + * @since 4.6.0 + * @var stdClass $cap + */ + public $cap; + /** + * Triggers the handling of rewrites for this post type. + * + * Defaults to true, using $post_type as slug. + * + * @since 4.6.0 + * @var array|false $rewrite + */ + public $rewrite; + /** + * The features supported by the post type. + * + * @since 4.6.0 + * @var array|bool $supports + */ + public $supports; + /** + * Whether this post type should appear in the REST API. + * + * Default false. If true, standard endpoints will be registered with + * respect to $rest_base and $rest_controller_class. + * + * @since 4.7.4 + * @var bool $show_in_rest + */ + public $show_in_rest; + /** + * The base path for this post type's REST API endpoints. + * + * @since 4.7.4 + * @var string|bool $rest_base + */ + public $rest_base; + /** + * The namespace for this post type's REST API endpoints. + * + * @since 5.9.0 + * @var string|bool $rest_namespace + */ + public $rest_namespace; + /** + * The controller for this post type's REST API endpoints. + * + * Custom controllers must extend WP_REST_Controller. + * + * @since 4.7.4 + * @var string|bool $rest_controller_class + */ + public $rest_controller_class; + /** + * The controller instance for this post type's REST API endpoints. + * + * Lazily computed. Should be accessed using {@see WP_Post_Type::get_rest_controller()}. + * + * @since 5.3.0 + * @var WP_REST_Controller $rest_controller + */ + public $rest_controller; + /** + * Constructor. + * + * See the register_post_type() function for accepted arguments for `$args`. + * + * Will populate object properties from the provided arguments and assign other + * default properties based on that information. + * + * @since 4.6.0 + * + * @see register_post_type() + * + * @param string $post_type Post type key. + * @param array|string $args Optional. Array or string of arguments for registering a post type. + * Default empty array. + */ + public function __construct($post_type, $args = array()) + { + } + /** + * Sets post type properties. + * + * See the register_post_type() function for accepted arguments for `$args`. + * + * @since 4.6.0 + * + * @param array|string $args Array or string of arguments for registering a post type. + */ + public function set_props($args) + { + } + /** + * Sets the features support for the post type. + * + * @since 4.6.0 + */ + public function add_supports() + { + } + /** + * Adds the necessary rewrite rules for the post type. + * + * @since 4.6.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * @global WP $wp Current WordPress environment instance. + */ + public function add_rewrite_rules() + { + } + /** + * Registers the post type meta box if a custom callback was specified. + * + * @since 4.6.0 + */ + public function register_meta_boxes() + { + } + /** + * Adds the future post hook action for the post type. + * + * @since 4.6.0 + */ + public function add_hooks() + { + } + /** + * Registers the taxonomies for the post type. + * + * @since 4.6.0 + */ + public function register_taxonomies() + { + } + /** + * Removes the features support for the post type. + * + * @since 4.6.0 + * + * @global array $_wp_post_type_features Post type features. + */ + public function remove_supports() + { + } + /** + * Removes any rewrite rules, permastructs, and rules for the post type. + * + * @since 4.6.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * @global WP $wp Current WordPress environment instance. + * @global array $post_type_meta_caps Used to remove meta capabilities. + */ + public function remove_rewrite_rules() + { + } + /** + * Unregisters the post type meta box if a custom callback was specified. + * + * @since 4.6.0 + */ + public function unregister_meta_boxes() + { + } + /** + * Removes the post type from all taxonomies. + * + * @since 4.6.0 + */ + public function unregister_taxonomies() + { + } + /** + * Removes the future post hook action for the post type. + * + * @since 4.6.0 + */ + public function remove_hooks() + { + } + /** + * Gets the REST API controller for this post type. + * + * Will only instantiate the controller class once per request. + * + * @since 5.3.0 + * + * @return WP_REST_Controller|null The controller instance, or null if the post type + * is set not to show in rest. + */ + public function get_rest_controller() + { + } + /** + * Returns the default labels for post types. + * + * @since 6.0.0 + * + * @return (string|null)[][] The default labels for post types. + */ + public static function get_default_labels() + { + } + /** + * Resets the cache for the default labels. + * + * @since 6.0.0 + */ + public static function reset_default_labels() + { + } + } + /** + * Post API: WP_Post class + * + * @package WordPress + * @subpackage Post + * @since 4.4.0 + */ + /** + * Core class used to implement the WP_Post object. + * + * @since 3.5.0 + * + * @property string $page_template + * + * @property-read int[] $ancestors + * @property-read int[] $post_category + * @property-read string[] $tags_input + */ + #[\AllowDynamicProperties] + final class WP_Post + { + /** + * Post ID. + * + * @since 3.5.0 + * @var int + */ + public $ID; + /** + * ID of post author. + * + * A numeric string, for compatibility reasons. + * + * @since 3.5.0 + * @var string + */ + public $post_author = 0; + /** + * The post's local publication time. + * + * @since 3.5.0 + * @var string + */ + public $post_date = '0000-00-00 00:00:00'; + /** + * The post's GMT publication time. + * + * @since 3.5.0 + * @var string + */ + public $post_date_gmt = '0000-00-00 00:00:00'; + /** + * The post's content. + * + * @since 3.5.0 + * @var string + */ + public $post_content = ''; + /** + * The post's title. + * + * @since 3.5.0 + * @var string + */ + public $post_title = ''; + /** + * The post's excerpt. + * + * @since 3.5.0 + * @var string + */ + public $post_excerpt = ''; + /** + * The post's status. + * + * @since 3.5.0 + * @var string + */ + public $post_status = 'publish'; + /** + * Whether comments are allowed. + * + * @since 3.5.0 + * @var string + */ + public $comment_status = 'open'; + /** + * Whether pings are allowed. + * + * @since 3.5.0 + * @var string + */ + public $ping_status = 'open'; + /** + * The post's password in plain text. + * + * @since 3.5.0 + * @var string + */ + public $post_password = ''; + /** + * The post's slug. + * + * @since 3.5.0 + * @var string + */ + public $post_name = ''; + /** + * URLs queued to be pinged. + * + * @since 3.5.0 + * @var string + */ + public $to_ping = ''; + /** + * URLs that have been pinged. + * + * @since 3.5.0 + * @var string + */ + public $pinged = ''; + /** + * The post's local modified time. + * + * @since 3.5.0 + * @var string + */ + public $post_modified = '0000-00-00 00:00:00'; + /** + * The post's GMT modified time. + * + * @since 3.5.0 + * @var string + */ + public $post_modified_gmt = '0000-00-00 00:00:00'; + /** + * A utility DB field for post content. + * + * @since 3.5.0 + * @var string + */ + public $post_content_filtered = ''; + /** + * ID of a post's parent post. + * + * @since 3.5.0 + * @var int + */ + public $post_parent = 0; + /** + * The unique identifier for a post, not necessarily a URL, used as the feed GUID. + * + * @since 3.5.0 + * @var string + */ + public $guid = ''; + /** + * A field used for ordering posts. + * + * @since 3.5.0 + * @var int + */ + public $menu_order = 0; + /** + * The post's type, like post or page. + * + * @since 3.5.0 + * @var string + */ + public $post_type = 'post'; + /** + * An attachment's mime type. + * + * @since 3.5.0 + * @var string + */ + public $post_mime_type = ''; + /** + * Cached comment count. + * + * A numeric string, for compatibility reasons. + * + * @since 3.5.0 + * @var string + */ + public $comment_count = 0; + /** + * Stores the post object's sanitization level. + * + * Does not correspond to a DB field. + * + * @since 3.5.0 + * @var string + */ + public $filter; + /** + * Retrieve WP_Post instance. + * + * @since 3.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $post_id Post ID. + * @return WP_Post|false Post object, false otherwise. + */ + public static function get_instance($post_id) + { + } + /** + * Constructor. + * + * @since 3.5.0 + * + * @param WP_Post|object $post Post object. + */ + public function __construct($post) + { + } + /** + * Isset-er. + * + * @since 3.5.0 + * + * @param string $key Property to check if set. + * @return bool + */ + public function __isset($key) + { + } + /** + * Getter. + * + * @since 3.5.0 + * + * @param string $key Key to get. + * @return mixed + */ + public function __get($key) + { + } + /** + * {@Missing Summary} + * + * @since 3.5.0 + * + * @param string $filter Filter. + * @return WP_Post + */ + public function filter($filter) + { + } + /** + * Convert object to array. + * + * @since 3.5.0 + * + * @return array Object as array. + */ + public function to_array() + { + } + } + /** + * Query API: WP_Query class + * + * @package WordPress + * @subpackage Query + * @since 4.7.0 + */ + /** + * The WordPress Query class. + * + * @link https://developer.wordpress.org/reference/classes/wp_query/ + * + * @since 1.5.0 + * @since 4.5.0 Removed the `$comments_popup` property. + */ + #[\AllowDynamicProperties] + class WP_Query + { + /** + * Query vars set by the user. + * + * @since 1.5.0 + * @var array + */ + public $query; + /** + * Query vars, after parsing. + * + * @since 1.5.0 + * @var array + */ + public $query_vars = array(); + /** + * Taxonomy query, as passed to get_tax_sql(). + * + * @since 3.1.0 + * @var WP_Tax_Query A taxonomy query instance. + */ + public $tax_query; + /** + * Metadata query container. + * + * @since 3.2.0 + * @var WP_Meta_Query A meta query instance. + */ + public $meta_query = \false; + /** + * Date query container. + * + * @since 3.7.0 + * @var WP_Date_Query A date query instance. + */ + public $date_query = \false; + /** + * Holds the data for a single object that is queried. + * + * Holds the contents of a post, page, category, attachment. + * + * @since 1.5.0 + * @var WP_Term|WP_Post_Type|WP_Post|WP_User|null + */ + public $queried_object; + /** + * The ID of the queried object. + * + * @since 1.5.0 + * @var int + */ + public $queried_object_id; + /** + * SQL for the database query. + * + * @since 2.0.1 + * @var string + */ + public $request; + /** + * Array of post objects or post IDs. + * + * @since 1.5.0 + * @var WP_Post[]|int[] + */ + public $posts; + /** + * The number of posts for the current query. + * + * @since 1.5.0 + * @var int + */ + public $post_count = 0; + /** + * Index of the current item in the loop. + * + * @since 1.5.0 + * @var int + */ + public $current_post = -1; + /** + * Whether the loop has started and the caller is in the loop. + * + * @since 2.0.0 + * @var bool + */ + public $in_the_loop = \false; + /** + * The current post. + * + * This property does not get populated when the `fields` argument is set to + * `ids` or `id=>parent`. + * + * @since 1.5.0 + * @var WP_Post|null + */ + public $post; + /** + * The list of comments for current post. + * + * @since 2.2.0 + * @var WP_Comment[] + */ + public $comments; + /** + * The number of comments for the posts. + * + * @since 2.2.0 + * @var int + */ + public $comment_count = 0; + /** + * The index of the comment in the comment loop. + * + * @since 2.2.0 + * @var int + */ + public $current_comment = -1; + /** + * Current comment object. + * + * @since 2.2.0 + * @var WP_Comment + */ + public $comment; + /** + * The number of found posts for the current query. + * + * If limit clause was not used, equals $post_count. + * + * @since 2.1.0 + * @var int + */ + public $found_posts = 0; + /** + * The number of pages. + * + * @since 2.1.0 + * @var int + */ + public $max_num_pages = 0; + /** + * The number of comment pages. + * + * @since 2.7.0 + * @var int + */ + public $max_num_comment_pages = 0; + /** + * Signifies whether the current query is for a single post. + * + * @since 1.5.0 + * @var bool + */ + public $is_single = \false; + /** + * Signifies whether the current query is for a preview. + * + * @since 2.0.0 + * @var bool + */ + public $is_preview = \false; + /** + * Signifies whether the current query is for a page. + * + * @since 1.5.0 + * @var bool + */ + public $is_page = \false; + /** + * Signifies whether the current query is for an archive. + * + * @since 1.5.0 + * @var bool + */ + public $is_archive = \false; + /** + * Signifies whether the current query is for a date archive. + * + * @since 1.5.0 + * @var bool + */ + public $is_date = \false; + /** + * Signifies whether the current query is for a year archive. + * + * @since 1.5.0 + * @var bool + */ + public $is_year = \false; + /** + * Signifies whether the current query is for a month archive. + * + * @since 1.5.0 + * @var bool + */ + public $is_month = \false; + /** + * Signifies whether the current query is for a day archive. + * + * @since 1.5.0 + * @var bool + */ + public $is_day = \false; + /** + * Signifies whether the current query is for a specific time. + * + * @since 1.5.0 + * @var bool + */ + public $is_time = \false; + /** + * Signifies whether the current query is for an author archive. + * + * @since 1.5.0 + * @var bool + */ + public $is_author = \false; + /** + * Signifies whether the current query is for a category archive. + * + * @since 1.5.0 + * @var bool + */ + public $is_category = \false; + /** + * Signifies whether the current query is for a tag archive. + * + * @since 2.3.0 + * @var bool + */ + public $is_tag = \false; + /** + * Signifies whether the current query is for a taxonomy archive. + * + * @since 2.5.0 + * @var bool + */ + public $is_tax = \false; + /** + * Signifies whether the current query is for a search. + * + * @since 1.5.0 + * @var bool + */ + public $is_search = \false; + /** + * Signifies whether the current query is for a feed. + * + * @since 1.5.0 + * @var bool + */ + public $is_feed = \false; + /** + * Signifies whether the current query is for a comment feed. + * + * @since 2.2.0 + * @var bool + */ + public $is_comment_feed = \false; + /** + * Signifies whether the current query is for trackback endpoint call. + * + * @since 1.5.0 + * @var bool + */ + public $is_trackback = \false; + /** + * Signifies whether the current query is for the site homepage. + * + * @since 1.5.0 + * @var bool + */ + public $is_home = \false; + /** + * Signifies whether the current query is for the Privacy Policy page. + * + * @since 5.2.0 + * @var bool + */ + public $is_privacy_policy = \false; + /** + * Signifies whether the current query couldn't find anything. + * + * @since 1.5.0 + * @var bool + */ + public $is_404 = \false; + /** + * Signifies whether the current query is for an embed. + * + * @since 4.4.0 + * @var bool + */ + public $is_embed = \false; + /** + * Signifies whether the current query is for a paged result and not for the first page. + * + * @since 1.5.0 + * @var bool + */ + public $is_paged = \false; + /** + * Signifies whether the current query is for an administrative interface page. + * + * @since 1.5.0 + * @var bool + */ + public $is_admin = \false; + /** + * Signifies whether the current query is for an attachment page. + * + * @since 2.0.0 + * @var bool + */ + public $is_attachment = \false; + /** + * Signifies whether the current query is for an existing single post of any post type + * (post, attachment, page, custom post types). + * + * @since 2.1.0 + * @var bool + */ + public $is_singular = \false; + /** + * Signifies whether the current query is for the robots.txt file. + * + * @since 2.1.0 + * @var bool + */ + public $is_robots = \false; + /** + * Signifies whether the current query is for the favicon.ico file. + * + * @since 5.4.0 + * @var bool + */ + public $is_favicon = \false; + /** + * Signifies whether the current query is for the page_for_posts page. + * + * Basically, the homepage if the option isn't set for the static homepage. + * + * @since 2.1.0 + * @var bool + */ + public $is_posts_page = \false; + /** + * Signifies whether the current query is for a post type archive. + * + * @since 3.1.0 + * @var bool + */ + public $is_post_type_archive = \false; + /** + * Set if post thumbnails are cached + * + * @since 3.2.0 + * @var bool + */ + public $thumbnails_cached = \false; + /** + * Controls whether an attachment query should include filenames or not. + * + * @since 6.0.3 + * @var bool + */ + protected $allow_query_attachment_by_filename = \false; + /** + * Initiates object properties and sets default values. + * + * @since 1.5.0 + */ + public function init() + { + } + /** + * Reparse the query vars. + * + * @since 1.5.0 + */ + public function parse_query_vars() + { + } + /** + * Fills in the query variables, which do not exist within the parameter. + * + * @since 2.1.0 + * @since 4.5.0 Removed the `comments_popup` public query variable. + * + * @param array $query_vars Defined query variables. + * @return array Complete query variables with undefined ones filled in empty. + */ + public function fill_query_vars($query_vars) + { + } + /** + * Parse a query string and set query type booleans. + * + * @since 1.5.0 + * @since 4.2.0 Introduced the ability to order by specific clauses of a `$meta_query`, by passing the clause's + * array key to `$orderby`. + * @since 4.4.0 Introduced `$post_name__in` and `$title` parameters. `$s` was updated to support excluded + * search terms, by prepending a hyphen. + * @since 4.5.0 Removed the `$comments_popup` parameter. + * Introduced the `$comment_status` and `$ping_status` parameters. + * Introduced `RAND(x)` syntax for `$orderby`, which allows an integer seed value to random sorts. + * @since 4.6.0 Added 'post_name__in' support for `$orderby`. Introduced the `$lazy_load_term_meta` argument. + * @since 4.9.0 Introduced the `$comment_count` parameter. + * @since 5.1.0 Introduced the `$meta_compare_key` parameter. + * @since 5.3.0 Introduced the `$meta_type_key` parameter. + * @since 6.1.0 Introduced the `$update_menu_item_cache` parameter. + * + * @param string|array $query { + * Optional. Array or string of Query parameters. + * + * @type int $attachment_id Attachment post ID. Used for 'attachment' post_type. + * @type int|string $author Author ID, or comma-separated list of IDs. + * @type string $author_name User 'user_nicename'. + * @type int[] $author__in An array of author IDs to query from. + * @type int[] $author__not_in An array of author IDs not to query from. + * @type bool $cache_results Whether to cache post information. Default true. + * @type int|string $cat Category ID or comma-separated list of IDs (this or any children). + * @type int[] $category__and An array of category IDs (AND in). + * @type int[] $category__in An array of category IDs (OR in, no children). + * @type int[] $category__not_in An array of category IDs (NOT in). + * @type string $category_name Use category slug (not name, this or any children). + * @type array|int $comment_count Filter results by comment count. Provide an integer to match + * comment count exactly. Provide an array with integer 'value' + * and 'compare' operator ('=', '!=', '>', '>=', '<', '<=' ) to + * compare against comment_count in a specific way. + * @type string $comment_status Comment status. + * @type int $comments_per_page The number of comments to return per page. + * Default 'comments_per_page' option. + * @type array $date_query An associative array of WP_Date_Query arguments. + * See WP_Date_Query::__construct(). + * @type int $day Day of the month. Default empty. Accepts numbers 1-31. + * @type bool $exact Whether to search by exact keyword. Default false. + * @type string $fields Post fields to query for. Accepts: + * - '' Returns an array of complete post objects (`WP_Post[]`). + * - 'ids' Returns an array of post IDs (`int[]`). + * - 'id=>parent' Returns an associative array of parent post IDs, + * keyed by post ID (`int[]`). + * Default ''. + * @type int $hour Hour of the day. Default empty. Accepts numbers 0-23. + * @type int|bool $ignore_sticky_posts Whether to ignore sticky posts or not. Setting this to false + * excludes stickies from 'post__in'. Accepts 1|true, 0|false. + * Default false. + * @type int $m Combination YearMonth. Accepts any four-digit year and month + * numbers 01-12. Default empty. + * @type string|string[] $meta_key Meta key or keys to filter by. + * @type string|string[] $meta_value Meta value or values to filter by. + * @type string $meta_compare MySQL operator used for comparing the meta value. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_compare_key MySQL operator used for comparing the meta key. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_type MySQL data type that the meta_value column will be CAST to for comparisons. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_type_key MySQL data type that the meta_key column will be CAST to for comparisons. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type array $meta_query An associative array of WP_Meta_Query arguments. + * See WP_Meta_Query::__construct() for accepted values. + * @type int $menu_order The menu order of the posts. + * @type int $minute Minute of the hour. Default empty. Accepts numbers 0-59. + * @type int $monthnum The two-digit month. Default empty. Accepts numbers 1-12. + * @type string $name Post slug. + * @type bool $nopaging Show all posts (true) or paginate (false). Default false. + * @type bool $no_found_rows Whether to skip counting the total rows found. Enabling can improve + * performance. Default false. + * @type int $offset The number of posts to offset before retrieval. + * @type string $order Designates ascending or descending order of posts. Default 'DESC'. + * Accepts 'ASC', 'DESC'. + * @type string|array $orderby Sort retrieved posts by parameter. One or more options may be passed. + * To use 'meta_value', or 'meta_value_num', 'meta_key=keyname' must be + * also be defined. To sort by a specific `$meta_query` clause, use that + * clause's array key. Accepts: + * - 'none' + * - 'name' + * - 'author' + * - 'date' + * - 'title' + * - 'modified' + * - 'menu_order' + * - 'parent' + * - 'ID' + * - 'rand' + * - 'relevance' + * - 'RAND(x)' (where 'x' is an integer seed value) + * - 'comment_count' + * - 'meta_value' + * - 'meta_value_num' + * - 'post__in' + * - 'post_name__in' + * - 'post_parent__in' + * - The array keys of `$meta_query`. + * Default is 'date', except when a search is being performed, when + * the default is 'relevance'. + * @type int $p Post ID. + * @type int $page Show the number of posts that would show up on page X of a + * static front page. + * @type int $paged The number of the current page. + * @type int $page_id Page ID. + * @type string $pagename Page slug. + * @type string $perm Show posts if user has the appropriate capability. + * @type string $ping_status Ping status. + * @type int[] $post__in An array of post IDs to retrieve, sticky posts will be included. + * @type int[] $post__not_in An array of post IDs not to retrieve. Note: a string of comma- + * separated IDs will NOT work. + * @type string $post_mime_type The mime type of the post. Used for 'attachment' post_type. + * @type string[] $post_name__in An array of post slugs that results must match. + * @type int $post_parent Page ID to retrieve child pages for. Use 0 to only retrieve + * top-level pages. + * @type int[] $post_parent__in An array containing parent page IDs to query child pages from. + * @type int[] $post_parent__not_in An array containing parent page IDs not to query child pages from. + * @type string|string[] $post_type A post type slug (string) or array of post type slugs. + * Default 'any' if using 'tax_query'. + * @type string|string[] $post_status A post status (string) or array of post statuses. + * @type int $posts_per_page The number of posts to query for. Use -1 to request all posts. + * @type int $posts_per_archive_page The number of posts to query for by archive page. Overrides + * 'posts_per_page' when is_archive(), or is_search() are true. + * @type string $s Search keyword(s). Prepending a term with a hyphen will + * exclude posts matching that term. Eg, 'pillow -sofa' will + * return posts containing 'pillow' but not 'sofa'. The + * character used for exclusion can be modified using the + * the 'wp_query_search_exclusion_prefix' filter. + * @type int $second Second of the minute. Default empty. Accepts numbers 0-59. + * @type bool $sentence Whether to search by phrase. Default false. + * @type bool $suppress_filters Whether to suppress filters. Default false. + * @type string $tag Tag slug. Comma-separated (either), Plus-separated (all). + * @type int[] $tag__and An array of tag IDs (AND in). + * @type int[] $tag__in An array of tag IDs (OR in). + * @type int[] $tag__not_in An array of tag IDs (NOT in). + * @type int $tag_id Tag id or comma-separated list of IDs. + * @type string[] $tag_slug__and An array of tag slugs (AND in). + * @type string[] $tag_slug__in An array of tag slugs (OR in). unless 'ignore_sticky_posts' is + * true. Note: a string of comma-separated IDs will NOT work. + * @type array $tax_query An associative array of WP_Tax_Query arguments. + * See WP_Tax_Query::__construct(). + * @type string $title Post title. + * @type bool $update_post_meta_cache Whether to update the post meta cache. Default true. + * @type bool $update_post_term_cache Whether to update the post term cache. Default true. + * @type bool $update_menu_item_cache Whether to update the menu item cache. Default false. + * @type bool $lazy_load_term_meta Whether to lazy-load term meta. Setting to false will + * disable cache priming for term meta, so that each + * get_term_meta() call will hit the database. + * Defaults to the value of `$update_post_term_cache`. + * @type int $w The week number of the year. Default empty. Accepts numbers 0-53. + * @type int $year The four-digit year. Default empty. Accepts any four-digit year. + * } + * @phpstan-param array{ + * attachment_id?: int, + * author?: int|string, + * author_name?: string, + * author__in?: int[], + * author__not_in?: int[], + * cache_results?: bool, + * cat?: int|string, + * category__and?: int[], + * category__in?: int[], + * category__not_in?: int[], + * category_name?: string, + * comment_count?: array|int, + * comment_status?: string, + * comments_per_page?: int, + * date_query?: array, + * day?: int, + * exact?: bool, + * fields?: string, + * hour?: int, + * ignore_sticky_posts?: int|bool, + * m?: int, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * menu_order?: int, + * minute?: int, + * monthnum?: int, + * name?: string, + * nopaging?: bool, + * no_found_rows?: bool, + * offset?: int, + * order?: string, + * orderby?: string|array, + * p?: int, + * page?: int, + * paged?: int, + * page_id?: int, + * pagename?: string, + * perm?: string, + * ping_status?: string, + * post__in?: int[], + * post__not_in?: int[], + * post_mime_type?: string, + * post_name__in?: string[], + * post_parent?: int, + * post_parent__in?: int[], + * post_parent__not_in?: int[], + * post_type?: string|string[], + * post_status?: string|string[], + * posts_per_page?: int, + * posts_per_archive_page?: int, + * s?: string, + * second?: int, + * sentence?: bool, + * suppress_filters?: bool, + * tag?: string, + * tag__and?: int[], + * tag__in?: int[], + * tag__not_in?: int[], + * tag_id?: int, + * tag_slug__and?: string[], + * tag_slug__in?: string[], + * tax_query?: array, + * title?: string, + * update_post_meta_cache?: bool, + * update_post_term_cache?: bool, + * update_menu_item_cache?: bool, + * lazy_load_term_meta?: bool, + * w?: int, + * year?: int, + * } $query + */ + public function parse_query($query = '') + { + } + /** + * Parses various taxonomy related query vars. + * + * For BC, this method is not marked as protected. See [28987]. + * + * @since 3.1.0 + * + * @param array $q The query variables. Passed by reference. + */ + public function parse_tax_query(&$q) + { + } + /** + * Generates SQL for the WHERE clause based on passed search terms. + * + * @since 3.7.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $q Query variables. + * @return string WHERE clause. + */ + protected function parse_search(&$q) + { + } + /** + * Check if the terms are suitable for searching. + * + * Uses an array of stopwords (terms) that are excluded from the separate + * term matching when searching for posts. The list of English stopwords is + * the approximate search engines list, and is translatable. + * + * @since 3.7.0 + * + * @param string[] $terms Array of terms to check. + * @return string[] Terms that are not stopwords. + */ + protected function parse_search_terms($terms) + { + } + /** + * Retrieve stopwords used when parsing search terms. + * + * @since 3.7.0 + * + * @return string[] Stopwords. + */ + protected function get_search_stopwords() + { + } + /** + * Generates SQL for the ORDER BY condition based on passed search terms. + * + * @since 3.7.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $q Query variables. + * @return string ORDER BY clause. + */ + protected function parse_search_order(&$q) + { + } + /** + * Converts the given orderby alias (if allowed) to a properly-prefixed value. + * + * @since 4.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $orderby Alias for the field to order by. + * @return string|false Table-prefixed value to used in the ORDER clause. False otherwise. + */ + protected function parse_orderby($orderby) + { + } + /** + * Parse an 'order' query variable and cast it to ASC or DESC as necessary. + * + * @since 4.0.0 + * + * @param string $order The 'order' query variable. + * @return string The sanitized 'order' query variable. + */ + protected function parse_order($order) + { + } + /** + * Sets the 404 property and saves whether query is feed. + * + * @since 2.0.0 + */ + public function set_404() + { + } + /** + * Retrieves the value of a query variable. + * + * @since 1.5.0 + * @since 3.9.0 The `$default_value` argument was introduced. + * + * @param string $query_var Query variable key. + * @param mixed $default_value Optional. Value to return if the query variable is not set. Default empty string. + * @return mixed Contents of the query variable. + */ + public function get($query_var, $default_value = '') + { + } + /** + * Sets the value of a query variable. + * + * @since 1.5.0 + * + * @param string $query_var Query variable key. + * @param mixed $value Query variable value. + */ + public function set($query_var, $value) + { + } + /** + * Retrieves an array of posts based on query variables. + * + * There are a few filters and actions that can be used to modify the post + * database query. + * + * @since 1.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return WP_Post[]|int[] Array of post objects or post IDs. + */ + public function get_posts() + { + } + /** + * Set up the next post and iterate current post index. + * + * @since 1.5.0 + * + * @return WP_Post Next post. + */ + public function next_post() + { + } + /** + * Sets up the current post. + * + * Retrieves the next post, sets up the post, sets the 'in the loop' + * property to true. + * + * @since 1.5.0 + * + * @global WP_Post $post Global post object. + */ + public function the_post() + { + } + /** + * Determines whether there are more posts available in the loop. + * + * Calls the {@see 'loop_end'} action when the loop is complete. + * + * @since 1.5.0 + * + * @return bool True if posts are available, false if end of the loop. + */ + public function have_posts() + { + } + /** + * Rewind the posts and reset post index. + * + * @since 1.5.0 + */ + public function rewind_posts() + { + } + /** + * Iterate current comment index and return WP_Comment object. + * + * @since 2.2.0 + * + * @return WP_Comment Comment object. + */ + public function next_comment() + { + } + /** + * Sets up the current comment. + * + * @since 2.2.0 + * + * @global WP_Comment $comment Global comment object. + */ + public function the_comment() + { + } + /** + * Whether there are more comments available. + * + * Automatically rewinds comments when finished. + * + * @since 2.2.0 + * + * @return bool True if comments are available, false if no more comments. + */ + public function have_comments() + { + } + /** + * Rewind the comments, resets the comment index and comment to first. + * + * @since 2.2.0 + */ + public function rewind_comments() + { + } + /** + * Sets up the WordPress query by parsing query string. + * + * @since 1.5.0 + * + * @see WP_Query::parse_query() for all available arguments. + * + * @param string|array $query URL query string or array of query arguments. + * @return WP_Post[]|int[] Array of post objects or post IDs. + */ + public function query($query) + { + } + /** + * Retrieves the currently queried object. + * + * If queried object is not set, then the queried object will be set from + * the category, tag, taxonomy, posts page, single post, page, or author + * query variable. After it is set up, it will be returned. + * + * @since 1.5.0 + * + * @return WP_Term|WP_Post_Type|WP_Post|WP_User|null The queried object. + */ + public function get_queried_object() + { + } + /** + * Retrieves the ID of the currently queried object. + * + * @since 1.5.0 + * + * @return int + */ + public function get_queried_object_id() + { + } + /** + * Constructor. + * + * Sets up the WordPress query, if parameter is not empty. + * + * @since 1.5.0 + * + * @see WP_Query::parse_query() for all available arguments. + * + * @param string|array $query URL query string or array of vars. + */ + public function __construct($query = '') + { + } + /** + * Make private properties readable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to get. + * @return mixed Property. + */ + public function __get($name) + { + } + /** + * Make private properties checkable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to check if set. + * @return bool Whether the property is set. + */ + public function __isset($name) + { + } + /** + * Make private/protected methods readable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Method to call. + * @param array $arguments Arguments to pass when calling. + * @return mixed|false Return value of the callback, false otherwise. + */ + public function __call($name, $arguments) + { + } + /** + * Is the query for an existing archive page? + * + * Archive pages include category, tag, author, date, custom post type, + * and custom taxonomy based archives. + * + * @since 3.1.0 + * + * @see WP_Query::is_category() + * @see WP_Query::is_tag() + * @see WP_Query::is_author() + * @see WP_Query::is_date() + * @see WP_Query::is_post_type_archive() + * @see WP_Query::is_tax() + * + * @return bool Whether the query is for an existing archive page. + */ + public function is_archive() + { + } + /** + * Is the query for an existing post type archive page? + * + * @since 3.1.0 + * + * @param string|string[] $post_types Optional. Post type or array of posts types + * to check against. Default empty. + * @return bool Whether the query is for an existing post type archive page. + */ + public function is_post_type_archive($post_types = '') + { + } + /** + * Is the query for an existing attachment page? + * + * @since 3.1.0 + * + * @param int|string|int[]|string[] $attachment Optional. Attachment ID, title, slug, or array of such + * to check against. Default empty. + * @return bool Whether the query is for an existing attachment page. + */ + public function is_attachment($attachment = '') + { + } + /** + * Is the query for an existing author archive page? + * + * If the $author parameter is specified, this function will additionally + * check if the query is for one of the authors specified. + * + * @since 3.1.0 + * + * @param int|string|int[]|string[] $author Optional. User ID, nickname, nicename, or array of such + * to check against. Default empty. + * @return bool Whether the query is for an existing author archive page. + */ + public function is_author($author = '') + { + } + /** + * Is the query for an existing category archive page? + * + * If the $category parameter is specified, this function will additionally + * check if the query is for one of the categories specified. + * + * @since 3.1.0 + * + * @param int|string|int[]|string[] $category Optional. Category ID, name, slug, or array of such + * to check against. Default empty. + * @return bool Whether the query is for an existing category archive page. + */ + public function is_category($category = '') + { + } + /** + * Is the query for an existing tag archive page? + * + * If the $tag parameter is specified, this function will additionally + * check if the query is for one of the tags specified. + * + * @since 3.1.0 + * + * @param int|string|int[]|string[] $tag Optional. Tag ID, name, slug, or array of such + * to check against. Default empty. + * @return bool Whether the query is for an existing tag archive page. + */ + public function is_tag($tag = '') + { + } + /** + * Is the query for an existing custom taxonomy archive page? + * + * If the $taxonomy parameter is specified, this function will additionally + * check if the query is for that specific $taxonomy. + * + * If the $term parameter is specified in addition to the $taxonomy parameter, + * this function will additionally check if the query is for one of the terms + * specified. + * + * @since 3.1.0 + * + * @global WP_Taxonomy[] $wp_taxonomies Registered taxonomies. + * + * @param string|string[] $taxonomy Optional. Taxonomy slug or slugs to check against. + * Default empty. + * @param int|string|int[]|string[] $term Optional. Term ID, name, slug, or array of such + * to check against. Default empty. + * @return bool Whether the query is for an existing custom taxonomy archive page. + * True for custom taxonomy archive pages, false for built-in taxonomies + * (category and tag archives). + */ + public function is_tax($taxonomy = '', $term = '') + { + } + /** + * Whether the current URL is within the comments popup window. + * + * @since 3.1.0 + * @deprecated 4.5.0 + * + * @return false Always returns false. + */ + public function is_comments_popup() + { + } + /** + * Is the query for an existing date archive? + * + * @since 3.1.0 + * + * @return bool Whether the query is for an existing date archive. + */ + public function is_date() + { + } + /** + * Is the query for an existing day archive? + * + * @since 3.1.0 + * + * @return bool Whether the query is for an existing day archive. + */ + public function is_day() + { + } + /** + * Is the query for a feed? + * + * @since 3.1.0 + * + * @param string|string[] $feeds Optional. Feed type or array of feed types + * to check against. Default empty. + * @return bool Whether the query is for a feed. + */ + public function is_feed($feeds = '') + { + } + /** + * Is the query for a comments feed? + * + * @since 3.1.0 + * + * @return bool Whether the query is for a comments feed. + */ + public function is_comment_feed() + { + } + /** + * Is the query for the front page of the site? + * + * This is for what is displayed at your site's main URL. + * + * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_on_front'. + * + * If you set a static page for the front page of your site, this function will return + * true when viewing that page. + * + * Otherwise the same as @see WP_Query::is_home() + * + * @since 3.1.0 + * + * @return bool Whether the query is for the front page of the site. + */ + public function is_front_page() + { + } + /** + * Is the query for the blog homepage? + * + * This is the page which shows the time based blog content of your site. + * + * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_for_posts'. + * + * If you set a static page for the front page of your site, this function will return + * true only on the page you set as the "Posts page". + * + * @since 3.1.0 + * + * @see WP_Query::is_front_page() + * + * @return bool Whether the query is for the blog homepage. + */ + public function is_home() + { + } + /** + * Is the query for the Privacy Policy page? + * + * This is the page which shows the Privacy Policy content of your site. + * + * Depends on the site's "Change your Privacy Policy page" Privacy Settings 'wp_page_for_privacy_policy'. + * + * This function will return true only on the page you set as the "Privacy Policy page". + * + * @since 5.2.0 + * + * @return bool Whether the query is for the Privacy Policy page. + */ + public function is_privacy_policy() + { + } + /** + * Is the query for an existing month archive? + * + * @since 3.1.0 + * + * @return bool Whether the query is for an existing month archive. + */ + public function is_month() + { + } + /** + * Is the query for an existing single page? + * + * If the $page parameter is specified, this function will additionally + * check if the query is for one of the pages specified. + * + * @since 3.1.0 + * + * @see WP_Query::is_single() + * @see WP_Query::is_singular() + * + * @param int|string|int[]|string[] $page Optional. Page ID, title, slug, path, or array of such + * to check against. Default empty. + * @return bool Whether the query is for an existing single page. + */ + public function is_page($page = '') + { + } + /** + * Is the query for a paged result and not for the first page? + * + * @since 3.1.0 + * + * @return bool Whether the query is for a paged result. + */ + public function is_paged() + { + } + /** + * Is the query for a post or page preview? + * + * @since 3.1.0 + * + * @return bool Whether the query is for a post or page preview. + */ + public function is_preview() + { + } + /** + * Is the query for the robots.txt file? + * + * @since 3.1.0 + * + * @return bool Whether the query is for the robots.txt file. + */ + public function is_robots() + { + } + /** + * Is the query for the favicon.ico file? + * + * @since 5.4.0 + * + * @return bool Whether the query is for the favicon.ico file. + */ + public function is_favicon() + { + } + /** + * Is the query for a search? + * + * @since 3.1.0 + * + * @return bool Whether the query is for a search. + */ + public function is_search() + { + } + /** + * Is the query for an existing single post? + * + * Works for any post type excluding pages. + * + * If the $post parameter is specified, this function will additionally + * check if the query is for one of the Posts specified. + * + * @since 3.1.0 + * + * @see WP_Query::is_page() + * @see WP_Query::is_singular() + * + * @param int|string|int[]|string[] $post Optional. Post ID, title, slug, path, or array of such + * to check against. Default empty. + * @return bool Whether the query is for an existing single post. + */ + public function is_single($post = '') + { + } + /** + * Is the query for an existing single post of any post type (post, attachment, page, + * custom post types)? + * + * If the $post_types parameter is specified, this function will additionally + * check if the query is for one of the Posts Types specified. + * + * @since 3.1.0 + * + * @see WP_Query::is_page() + * @see WP_Query::is_single() + * + * @param string|string[] $post_types Optional. Post type or array of post types + * to check against. Default empty. + * @return bool Whether the query is for an existing single post + * or any of the given post types. + */ + public function is_singular($post_types = '') + { + } + /** + * Is the query for a specific time? + * + * @since 3.1.0 + * + * @return bool Whether the query is for a specific time. + */ + public function is_time() + { + } + /** + * Is the query for a trackback endpoint call? + * + * @since 3.1.0 + * + * @return bool Whether the query is for a trackback endpoint call. + */ + public function is_trackback() + { + } + /** + * Is the query for an existing year archive? + * + * @since 3.1.0 + * + * @return bool Whether the query is for an existing year archive. + */ + public function is_year() + { + } + /** + * Is the query a 404 (returns no results)? + * + * @since 3.1.0 + * + * @return bool Whether the query is a 404 error. + */ + public function is_404() + { + } + /** + * Is the query for an embedded post? + * + * @since 4.4.0 + * + * @return bool Whether the query is for an embedded post. + */ + public function is_embed() + { + } + /** + * Is the query the main query? + * + * @since 3.3.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is the main query. + */ + public function is_main_query() + { + } + /** + * Set up global post data. + * + * @since 4.1.0 + * @since 4.4.0 Added the ability to pass a post ID to `$post`. + * + * @global int $id + * @global WP_User $authordata + * @global string $currentday + * @global string $currentmonth + * @global int $page + * @global array $pages + * @global int $multipage + * @global int $more + * @global int $numpages + * + * @param WP_Post|object|int $post WP_Post instance or Post ID/object. + * @return true True when finished. + */ + public function setup_postdata($post) + { + } + /** + * Generate post data. + * + * @since 5.2.0 + * + * @param WP_Post|object|int $post WP_Post instance or Post ID/object. + * @return array|false Elements of post or false on failure. + */ + public function generate_postdata($post) + { + } + /** + * Generate cache key. + * + * @since 6.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $args Query arguments. + * @param string $sql SQL statement. + * + * @return string Cache key. + */ + protected function generate_cache_key(array $args, $sql) + { + } + /** + * After looping through a nested query, this function + * restores the $post global to the current post in this query. + * + * @since 3.7.0 + * + * @global WP_Post $post Global post object. + */ + public function reset_postdata() + { + } + /** + * Lazyload term meta for posts in the loop. + * + * @since 4.4.0 + * @deprecated 4.5.0 See wp_queue_posts_for_term_meta_lazyload(). + * + * @param mixed $check + * @param int $term_id + * @return mixed + */ + public function lazyload_term_meta($check, $term_id) + { + } + /** + * Lazyload comment meta for comments in the loop. + * + * @since 4.4.0 + * @deprecated 4.5.0 See wp_queue_comments_for_comment_meta_lazyload(). + * + * @param mixed $check + * @param int $comment_id + * @return mixed + */ + public function lazyload_comment_meta($check, $comment_id) + { + } + } + /** + * Error Protection API: WP_Recovery_Mode_Cookie_Service class + * + * @package WordPress + * @since 5.2.0 + */ + /** + * Core class used to set, validate, and clear cookies that identify a Recovery Mode session. + * + * @since 5.2.0 + */ + #[\AllowDynamicProperties] + final class WP_Recovery_Mode_Cookie_Service + { + /** + * Checks whether the recovery mode cookie is set. + * + * @since 5.2.0 + * + * @return bool True if the cookie is set, false otherwise. + */ + public function is_cookie_set() + { + } + /** + * Sets the recovery mode cookie. + * + * This must be immediately followed by exiting the request. + * + * @since 5.2.0 + */ + public function set_cookie() + { + } + /** + * Clears the recovery mode cookie. + * + * @since 5.2.0 + */ + public function clear_cookie() + { + } + /** + * Validates the recovery mode cookie. + * + * @since 5.2.0 + * + * @param string $cookie Optionally specify the cookie string. + * If omitted, it will be retrieved from the super global. + * @return true|WP_Error True on success, error object on failure. + */ + public function validate_cookie($cookie = '') + { + } + /** + * Gets the session identifier from the cookie. + * + * The cookie should be validated before calling this API. + * + * @since 5.2.0 + * + * @param string $cookie Optionally specify the cookie string. + * If omitted, it will be retrieved from the super global. + * @return string|WP_Error Session ID on success, or error object on failure. + */ + public function get_session_id_from_cookie($cookie = '') + { + } + } + /** + * Error Protection API: WP_Recovery_Mode_Email_Link class + * + * @package WordPress + * @since 5.2.0 + */ + /** + * Core class used to send an email with a link to begin Recovery Mode. + * + * @since 5.2.0 + */ + #[\AllowDynamicProperties] + final class WP_Recovery_Mode_Email_Service + { + const RATE_LIMIT_OPTION = 'recovery_mode_email_last_sent'; + /** + * WP_Recovery_Mode_Email_Service constructor. + * + * @since 5.2.0 + * + * @param WP_Recovery_Mode_Link_Service $link_service + */ + public function __construct(\WP_Recovery_Mode_Link_Service $link_service) + { + } + /** + * Sends the recovery mode email if the rate limit has not been sent. + * + * @since 5.2.0 + * + * @param int $rate_limit Number of seconds before another email can be sent. + * @param array $error Error details from `error_get_last()`. + * @param array $extension { + * The extension that caused the error. + * + * @type string $slug The extension slug. The plugin or theme's directory. + * @type string $type The extension type. Either 'plugin' or 'theme'. + * } + * @return true|WP_Error True if email sent, WP_Error otherwise. + * @phpstan-param array{ + * slug?: string, + * type?: string, + * } $extension + */ + public function maybe_send_recovery_mode_email($rate_limit, $error, $extension) + { + } + /** + * Clears the rate limit, allowing a new recovery mode email to be sent immediately. + * + * @since 5.2.0 + * + * @return bool True on success, false on failure. + */ + public function clear_rate_limit() + { + } + } + /** + * Error Protection API: WP_Recovery_Mode_Key_Service class + * + * @package WordPress + * @since 5.2.0 + */ + /** + * Core class used to generate and validate keys used to enter Recovery Mode. + * + * @since 5.2.0 + */ + #[\AllowDynamicProperties] + final class WP_Recovery_Mode_Key_Service + { + /** + * Creates a recovery mode token. + * + * @since 5.2.0 + * + * @return string A random string to identify its associated key in storage. + */ + public function generate_recovery_mode_token() + { + } + /** + * Creates a recovery mode key. + * + * @since 5.2.0 + * + * @global PasswordHash $wp_hasher + * + * @param string $token A token generated by {@see generate_recovery_mode_token()}. + * @return string Recovery mode key. + */ + public function generate_and_store_recovery_mode_key($token) + { + } + /** + * Verifies if the recovery mode key is correct. + * + * Recovery mode keys can only be used once; the key will be consumed in the process. + * + * @since 5.2.0 + * + * @param string $token The token used when generating the given key. + * @param string $key The unhashed key. + * @param int $ttl Time in seconds for the key to be valid for. + * @return true|WP_Error True on success, error object on failure. + */ + public function validate_recovery_mode_key($token, $key, $ttl) + { + } + /** + * Removes expired recovery mode keys. + * + * @since 5.2.0 + * + * @param int $ttl Time in seconds for the keys to be valid for. + */ + public function clean_expired_keys($ttl) + { + } + } + /** + * Error Protection API: WP_Recovery_Mode_Link_Handler class + * + * @package WordPress + * @since 5.2.0 + */ + /** + * Core class used to generate and handle recovery mode links. + * + * @since 5.2.0 + */ + #[\AllowDynamicProperties] + class WP_Recovery_Mode_Link_Service + { + const LOGIN_ACTION_ENTER = 'enter_recovery_mode'; + const LOGIN_ACTION_ENTERED = 'entered_recovery_mode'; + /** + * WP_Recovery_Mode_Link_Service constructor. + * + * @since 5.2.0 + * + * @param WP_Recovery_Mode_Cookie_Service $cookie_service Service to handle setting the recovery mode cookie. + * @param WP_Recovery_Mode_Key_Service $key_service Service to handle generating recovery mode keys. + */ + public function __construct(\WP_Recovery_Mode_Cookie_Service $cookie_service, \WP_Recovery_Mode_Key_Service $key_service) + { + } + /** + * Generates a URL to begin recovery mode. + * + * Only one recovery mode URL can may be valid at the same time. + * + * @since 5.2.0 + * + * @return string Generated URL. + */ + public function generate_url() + { + } + /** + * Enters recovery mode when the user hits wp-login.php with a valid recovery mode link. + * + * @since 5.2.0 + * + * @global string $pagenow The filename of the current screen. + * + * @param int $ttl Number of seconds the link should be valid for. + */ + public function handle_begin_link($ttl) + { + } + } + /** + * Error Protection API: WP_Recovery_Mode class + * + * @package WordPress + * @since 5.2.0 + */ + /** + * Core class used to implement Recovery Mode. + * + * @since 5.2.0 + */ + #[\AllowDynamicProperties] + class WP_Recovery_Mode + { + const EXIT_ACTION = 'exit_recovery_mode'; + /** + * WP_Recovery_Mode constructor. + * + * @since 5.2.0 + */ + public function __construct() + { + } + /** + * Initialize recovery mode for the current request. + * + * @since 5.2.0 + */ + public function initialize() + { + } + /** + * Checks whether recovery mode is active. + * + * This will not change after recovery mode has been initialized. {@see WP_Recovery_Mode::run()}. + * + * @since 5.2.0 + * + * @return bool True if recovery mode is active, false otherwise. + */ + public function is_active() + { + } + /** + * Gets the recovery mode session ID. + * + * @since 5.2.0 + * + * @return string The session ID if recovery mode is active, empty string otherwise. + */ + public function get_session_id() + { + } + /** + * Checks whether recovery mode has been initialized. + * + * Recovery mode should not be used until this point. Initialization happens immediately before loading plugins. + * + * @since 5.2.0 + * + * @return bool + */ + public function is_initialized() + { + } + /** + * Handles a fatal error occurring. + * + * The calling API should immediately die() after calling this function. + * + * @since 5.2.0 + * + * @param array $error Error details from `error_get_last()`. + * @return true|WP_Error True if the error was handled and headers have already been sent. + * Or the request will exit to try and catch multiple errors at once. + * WP_Error if an error occurred preventing it from being handled. + */ + public function handle_error(array $error) + { + } + /** + * Ends the current recovery mode session. + * + * @since 5.2.0 + * + * @return bool True on success, false on failure. + */ + public function exit_recovery_mode() + { + } + /** + * Handles a request to exit Recovery Mode. + * + * @since 5.2.0 + */ + public function handle_exit_recovery_mode() + { + } + /** + * Cleans any recovery mode keys that have expired according to the link TTL. + * + * Executes on a daily cron schedule. + * + * @since 5.2.0 + */ + public function clean_expired_keys() + { + } + /** + * Handles checking for the recovery mode cookie and validating it. + * + * @since 5.2.0 + */ + protected function handle_cookie() + { + } + /** + * Gets the rate limit between sending new recovery mode email links. + * + * @since 5.2.0 + * + * @return int Rate limit in seconds. + */ + protected function get_email_rate_limit() + { + } + /** + * Gets the number of seconds the recovery mode link is valid for. + * + * @since 5.2.0 + * + * @return int Interval in seconds. + */ + protected function get_link_ttl() + { + } + /** + * Gets the extension that the error occurred in. + * + * @since 5.2.0 + * + * @global array $wp_theme_directories + * + * @param array $error Error details from `error_get_last()`. + * @return array|false { + * Extension details. + * + * @type string $slug The extension slug. This is the plugin or theme's directory. + * @type string $type The extension type. Either 'plugin' or 'theme'. + * } + * @phpstan-return false|array{ + * slug: string, + * type: string, + * } + */ + protected function get_extension_for_error($error) + { + } + /** + * Checks whether the given extension a network activated plugin. + * + * @since 5.2.0 + * + * @param array $extension Extension data. + * @return bool True if network plugin, false otherwise. + */ + protected function is_network_plugin($extension) + { + } + /** + * Stores the given error so that the extension causing it is paused. + * + * @since 5.2.0 + * + * @param array $error Error details from `error_get_last()`. + * @return bool True if the error was stored successfully, false otherwise. + */ + protected function store_error($error) + { + } + /** + * Redirects the current request to allow recovering multiple errors in one go. + * + * The redirection will only happen when on a protected endpoint. + * + * It must be ensured that this method is only called when an error actually occurred and will not occur on the + * next request again. Otherwise it will create a redirect loop. + * + * @since 5.2.0 + */ + protected function redirect_protected() + { + } + } + /** + * Rewrite API: WP_Rewrite class + * + * @package WordPress + * @subpackage Rewrite + * @since 1.5.0 + */ + /** + * Core class used to implement a rewrite component API. + * + * The WordPress Rewrite class writes the rewrite module rules to the .htaccess + * file. It also handles parsing the request to get the correct setup for the + * WordPress Query class. + * + * The Rewrite along with WP class function as a front controller for WordPress. + * You can add rules to trigger your page view and processing using this + * component. The full functionality of a front controller does not exist, + * meaning you can't define how the template files load based on the rewrite + * rules. + * + * @since 1.5.0 + */ + #[\AllowDynamicProperties] + class WP_Rewrite + { + /** + * Permalink structure for posts. + * + * @since 1.5.0 + * @var string + */ + public $permalink_structure; + /** + * Whether to add trailing slashes. + * + * @since 2.2.0 + * @var bool + */ + public $use_trailing_slashes; + /** + * Base for the author permalink structure (example.com/$author_base/authorname). + * + * @since 1.5.0 + * @var string + */ + public $author_base = 'author'; + /** + * Permalink structure for author archives. + * + * @since 1.5.0 + * @var string + */ + public $author_structure; + /** + * Permalink structure for date archives. + * + * @since 1.5.0 + * @var string + */ + public $date_structure; + /** + * Permalink structure for pages. + * + * @since 1.5.0 + * @var string + */ + public $page_structure; + /** + * Base of the search permalink structure (example.com/$search_base/query). + * + * @since 1.5.0 + * @var string + */ + public $search_base = 'search'; + /** + * Permalink structure for searches. + * + * @since 1.5.0 + * @var string + */ + public $search_structure; + /** + * Comments permalink base. + * + * @since 1.5.0 + * @var string + */ + public $comments_base = 'comments'; + /** + * Pagination permalink base. + * + * @since 3.1.0 + * @var string + */ + public $pagination_base = 'page'; + /** + * Comments pagination permalink base. + * + * @since 4.2.0 + * @var string + */ + public $comments_pagination_base = 'comment-page'; + /** + * Feed permalink base. + * + * @since 1.5.0 + * @var string + */ + public $feed_base = 'feed'; + /** + * Comments feed permalink structure. + * + * @since 1.5.0 + * @var string + */ + public $comment_feed_structure; + /** + * Feed request permalink structure. + * + * @since 1.5.0 + * @var string + */ + public $feed_structure; + /** + * The static portion of the post permalink structure. + * + * If the permalink structure is "/archive/%post_id%" then the front + * is "/archive/". If the permalink structure is "/%year%/%postname%/" + * then the front is "/". + * + * @since 1.5.0 + * @var string + * + * @see WP_Rewrite::init() + */ + public $front; + /** + * The prefix for all permalink structures. + * + * If PATHINFO/index permalinks are in use then the root is the value of + * `WP_Rewrite::$index` with a trailing slash appended. Otherwise the root + * will be empty. + * + * @since 1.5.0 + * @var string + * + * @see WP_Rewrite::init() + * @see WP_Rewrite::using_index_permalinks() + */ + public $root = ''; + /** + * The name of the index file which is the entry point to all requests. + * + * @since 1.5.0 + * @var string + */ + public $index = 'index.php'; + /** + * Variable name to use for regex matches in the rewritten query. + * + * @since 1.5.0 + * @var string + */ + public $matches = ''; + /** + * Rewrite rules to match against the request to find the redirect or query. + * + * @since 1.5.0 + * @var string[] + */ + public $rules; + /** + * Additional rules added external to the rewrite class. + * + * Those not generated by the class, see add_rewrite_rule(). + * + * @since 2.1.0 + * @var string[] + */ + public $extra_rules = array(); + /** + * Additional rules that belong at the beginning to match first. + * + * Those not generated by the class, see add_rewrite_rule(). + * + * @since 2.3.0 + * @var string[] + */ + public $extra_rules_top = array(); + /** + * Rules that don't redirect to WordPress' index.php. + * + * These rules are written to the mod_rewrite portion of the .htaccess, + * and are added by add_external_rule(). + * + * @since 2.1.0 + * @var string[] + */ + public $non_wp_rules = array(); + /** + * Extra permalink structures, e.g. categories, added by add_permastruct(). + * + * @since 2.1.0 + * @var array[] + */ + public $extra_permastructs = array(); + /** + * Endpoints (like /trackback/) added by add_rewrite_endpoint(). + * + * @since 2.1.0 + * @var array[] + */ + public $endpoints; + /** + * Whether to write every mod_rewrite rule for WordPress into the .htaccess file. + * + * This is off by default, turning it on might print a lot of rewrite rules + * to the .htaccess file. + * + * @since 2.0.0 + * @var bool + * + * @see WP_Rewrite::mod_rewrite_rules() + */ + public $use_verbose_rules = \false; + /** + * Could post permalinks be confused with those of pages? + * + * If the first rewrite tag in the post permalink structure is one that could + * also match a page name (e.g. %postname% or %author%) then this flag is + * set to true. Prior to WordPress 3.3 this flag indicated that every page + * would have a set of rules added to the top of the rewrite rules array. + * Now it tells WP::parse_request() to check if a URL matching the page + * permastruct is actually a page before accepting it. + * + * @since 2.5.0 + * @var bool + * + * @see WP_Rewrite::init() + */ + public $use_verbose_page_rules = \true; + /** + * Rewrite tags that can be used in permalink structures. + * + * These are translated into the regular expressions stored in + * `WP_Rewrite::$rewritereplace` and are rewritten to the query + * variables listed in WP_Rewrite::$queryreplace. + * + * Additional tags can be added with add_rewrite_tag(). + * + * @since 1.5.0 + * @var string[] + */ + public $rewritecode = array('%year%', '%monthnum%', '%day%', '%hour%', '%minute%', '%second%', '%postname%', '%post_id%', '%author%', '%pagename%', '%search%'); + /** + * Regular expressions to be substituted into rewrite rules in place + * of rewrite tags, see WP_Rewrite::$rewritecode. + * + * @since 1.5.0 + * @var string[] + */ + public $rewritereplace = array('([0-9]{4})', '([0-9]{1,2})', '([0-9]{1,2})', '([0-9]{1,2})', '([0-9]{1,2})', '([0-9]{1,2})', '([^/]+)', '([0-9]+)', '([^/]+)', '([^/]+?)', '(.+)'); + /** + * Query variables that rewrite tags map to, see WP_Rewrite::$rewritecode. + * + * @since 1.5.0 + * @var string[] + */ + public $queryreplace = array('year=', 'monthnum=', 'day=', 'hour=', 'minute=', 'second=', 'name=', 'p=', 'author_name=', 'pagename=', 's='); + /** + * Supported default feeds. + * + * @since 1.5.0 + * @var string[] + */ + public $feeds = array('feed', 'rdf', 'rss', 'rss2', 'atom'); + /** + * Determines whether permalinks are being used. + * + * This can be either rewrite module or permalink in the HTTP query string. + * + * @since 1.5.0 + * + * @return bool True, if permalinks are enabled. + */ + public function using_permalinks() + { + } + /** + * Determines whether permalinks are being used and rewrite module is not enabled. + * + * Means that permalink links are enabled and index.php is in the URL. + * + * @since 1.5.0 + * + * @return bool Whether permalink links are enabled and index.php is in the URL. + */ + public function using_index_permalinks() + { + } + /** + * Determines whether permalinks are being used and rewrite module is enabled. + * + * Using permalinks and index.php is not in the URL. + * + * @since 1.5.0 + * + * @return bool Whether permalink links are enabled and index.php is NOT in the URL. + */ + public function using_mod_rewrite_permalinks() + { + } + /** + * Indexes for matches for usage in preg_*() functions. + * + * The format of the string is, with empty matches property value, '$NUM'. + * The 'NUM' will be replaced with the value in the $number parameter. With + * the matches property not empty, the value of the returned string will + * contain that value of the matches property. The format then will be + * '$MATCHES[NUM]', with MATCHES as the value in the property and NUM the + * value of the $number parameter. + * + * @since 1.5.0 + * + * @param int $number Index number. + * @return string + */ + public function preg_index($number) + { + } + /** + * Retrieves all pages and attachments for pages URIs. + * + * The attachments are for those that have pages as parents and will be + * retrieved. + * + * @since 2.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return array Array of page URIs as first element and attachment URIs as second element. + */ + public function page_uri_index() + { + } + /** + * Retrieves all of the rewrite rules for pages. + * + * @since 1.5.0 + * + * @return string[] Page rewrite rules. + */ + public function page_rewrite_rules() + { + } + /** + * Retrieves date permalink structure, with year, month, and day. + * + * The permalink structure for the date, if not set already depends on the + * permalink structure. It can be one of three formats. The first is year, + * month, day; the second is day, month, year; and the last format is month, + * day, year. These are matched against the permalink structure for which + * one is used. If none matches, then the default will be used, which is + * year, month, day. + * + * Prevents post ID and date permalinks from overlapping. In the case of + * post_id, the date permalink will be prepended with front permalink with + * 'date/' before the actual permalink to form the complete date permalink + * structure. + * + * @since 1.5.0 + * + * @return string|false Date permalink structure on success, false on failure. + */ + public function get_date_permastruct() + { + } + /** + * Retrieves the year permalink structure without month and day. + * + * Gets the date permalink structure and strips out the month and day + * permalink structures. + * + * @since 1.5.0 + * + * @return string|false Year permalink structure on success, false on failure. + */ + public function get_year_permastruct() + { + } + /** + * Retrieves the month permalink structure without day and with year. + * + * Gets the date permalink structure and strips out the day permalink + * structures. Keeps the year permalink structure. + * + * @since 1.5.0 + * + * @return string|false Year/Month permalink structure on success, false on failure. + */ + public function get_month_permastruct() + { + } + /** + * Retrieves the day permalink structure with month and year. + * + * Keeps date permalink structure with all year, month, and day. + * + * @since 1.5.0 + * + * @return string|false Year/Month/Day permalink structure on success, false on failure. + */ + public function get_day_permastruct() + { + } + /** + * Retrieves the permalink structure for categories. + * + * If the category_base property has no value, then the category structure + * will have the front property value, followed by 'category', and finally + * '%category%'. If it does, then the root property will be used, along with + * the category_base property value. + * + * @since 1.5.0 + * + * @return string|false Category permalink structure on success, false on failure. + */ + public function get_category_permastruct() + { + } + /** + * Retrieves the permalink structure for tags. + * + * If the tag_base property has no value, then the tag structure will have + * the front property value, followed by 'tag', and finally '%tag%'. If it + * does, then the root property will be used, along with the tag_base + * property value. + * + * @since 2.3.0 + * + * @return string|false Tag permalink structure on success, false on failure. + */ + public function get_tag_permastruct() + { + } + /** + * Retrieves an extra permalink structure by name. + * + * @since 2.5.0 + * + * @param string $name Permalink structure name. + * @return string|false Permalink structure string on success, false on failure. + */ + public function get_extra_permastruct($name) + { + } + /** + * Retrieves the author permalink structure. + * + * The permalink structure is front property, author base, and finally + * '/%author%'. Will set the author_structure property and then return it + * without attempting to set the value again. + * + * @since 1.5.0 + * + * @return string|false Author permalink structure on success, false on failure. + */ + public function get_author_permastruct() + { + } + /** + * Retrieves the search permalink structure. + * + * The permalink structure is root property, search base, and finally + * '/%search%'. Will set the search_structure property and then return it + * without attempting to set the value again. + * + * @since 1.5.0 + * + * @return string|false Search permalink structure on success, false on failure. + */ + public function get_search_permastruct() + { + } + /** + * Retrieves the page permalink structure. + * + * The permalink structure is root property, and '%pagename%'. Will set the + * page_structure property and then return it without attempting to set the + * value again. + * + * @since 1.5.0 + * + * @return string|false Page permalink structure on success, false on failure. + */ + public function get_page_permastruct() + { + } + /** + * Retrieves the feed permalink structure. + * + * The permalink structure is root property, feed base, and finally + * '/%feed%'. Will set the feed_structure property and then return it + * without attempting to set the value again. + * + * @since 1.5.0 + * + * @return string|false Feed permalink structure on success, false on failure. + */ + public function get_feed_permastruct() + { + } + /** + * Retrieves the comment feed permalink structure. + * + * The permalink structure is root property, comment base property, feed + * base and finally '/%feed%'. Will set the comment_feed_structure property + * and then return it without attempting to set the value again. + * + * @since 1.5.0 + * + * @return string|false Comment feed permalink structure on success, false on failure. + */ + public function get_comment_feed_permastruct() + { + } + /** + * Adds or updates existing rewrite tags (e.g. %postname%). + * + * If the tag already exists, replace the existing pattern and query for + * that tag, otherwise add the new tag. + * + * @since 1.5.0 + * + * @see WP_Rewrite::$rewritecode + * @see WP_Rewrite::$rewritereplace + * @see WP_Rewrite::$queryreplace + * + * @param string $tag Name of the rewrite tag to add or update. + * @param string $regex Regular expression to substitute the tag for in rewrite rules. + * @param string $query String to append to the rewritten query. Must end in '='. + */ + public function add_rewrite_tag($tag, $regex, $query) + { + } + /** + * Removes an existing rewrite tag. + * + * @since 4.5.0 + * + * @see WP_Rewrite::$rewritecode + * @see WP_Rewrite::$rewritereplace + * @see WP_Rewrite::$queryreplace + * + * @param string $tag Name of the rewrite tag to remove. + */ + public function remove_rewrite_tag($tag) + { + } + /** + * Generates rewrite rules from a permalink structure. + * + * The main WP_Rewrite function for building the rewrite rule list. The + * contents of the function is a mix of black magic and regular expressions, + * so best just ignore the contents and move to the parameters. + * + * @since 1.5.0 + * + * @param string $permalink_structure The permalink structure. + * @param int $ep_mask Optional. Endpoint mask defining what endpoints are added to the structure. + * Accepts a mask of: + * - `EP_ALL` + * - `EP_NONE` + * - `EP_ALL_ARCHIVES` + * - `EP_ATTACHMENT` + * - `EP_AUTHORS` + * - `EP_CATEGORIES` + * - `EP_COMMENTS` + * - `EP_DATE` + * - `EP_DAY` + * - `EP_MONTH` + * - `EP_PAGES` + * - `EP_PERMALINK` + * - `EP_ROOT` + * - `EP_SEARCH` + * - `EP_TAGS` + * - `EP_YEAR` + * Default `EP_NONE`. + * @param bool $paged Optional. Whether archive pagination rules should be added for the structure. + * Default true. + * @param bool $feed Optional. Whether feed rewrite rules should be added for the structure. + * Default true. + * @param bool $forcomments Optional. Whether the feed rules should be a query for a comments feed. + * Default false. + * @param bool $walk_dirs Optional. Whether the 'directories' making up the structure should be walked + * over and rewrite rules built for each in-turn. Default true. + * @param bool $endpoints Optional. Whether endpoints should be applied to the generated rewrite rules. + * Default true. + * @return string[] Array of rewrite rules keyed by their regex pattern. + */ + public function generate_rewrite_rules($permalink_structure, $ep_mask = \EP_NONE, $paged = \true, $feed = \true, $forcomments = \false, $walk_dirs = \true, $endpoints = \true) + { + } + /** + * Generates rewrite rules with permalink structure and walking directory only. + * + * Shorten version of WP_Rewrite::generate_rewrite_rules() that allows for shorter + * list of parameters. See the method for longer description of what generating + * rewrite rules does. + * + * @since 1.5.0 + * + * @see WP_Rewrite::generate_rewrite_rules() See for long description and rest of parameters. + * + * @param string $permalink_structure The permalink structure to generate rules. + * @param bool $walk_dirs Optional. Whether to create list of directories to walk over. + * Default false. + * @return array An array of rewrite rules keyed by their regex pattern. + */ + public function generate_rewrite_rule($permalink_structure, $walk_dirs = \false) + { + } + /** + * Constructs rewrite matches and queries from permalink structure. + * + * Runs the action {@see 'generate_rewrite_rules'} with the parameter that is an + * reference to the current WP_Rewrite instance to further manipulate the + * permalink structures and rewrite rules. Runs the {@see 'rewrite_rules_array'} + * filter on the full rewrite rule array. + * + * There are two ways to manipulate the rewrite rules, one by hooking into + * the {@see 'generate_rewrite_rules'} action and gaining full control of the + * object or just manipulating the rewrite rule array before it is passed + * from the function. + * + * @since 1.5.0 + * + * @return string[] An associative array of matches and queries. + */ + public function rewrite_rules() + { + } + /** + * Retrieves the rewrite rules. + * + * The difference between this method and WP_Rewrite::rewrite_rules() is that + * this method stores the rewrite rules in the 'rewrite_rules' option and retrieves + * it. This prevents having to process all of the permalinks to get the rewrite rules + * in the form of caching. + * + * @since 1.5.0 + * + * @return string[] Array of rewrite rules keyed by their regex pattern. + */ + public function wp_rewrite_rules() + { + } + /** + * Retrieves mod_rewrite-formatted rewrite rules to write to .htaccess. + * + * Does not actually write to the .htaccess file, but creates the rules for + * the process that will. + * + * Will add the non_wp_rules property rules to the .htaccess file before + * the WordPress rewrite rules one. + * + * @since 1.5.0 + * + * @return string + */ + public function mod_rewrite_rules() + { + } + /** + * Retrieves IIS7 URL Rewrite formatted rewrite rules to write to web.config file. + * + * Does not actually write to the web.config file, but creates the rules for + * the process that will. + * + * @since 2.8.0 + * + * @param bool $add_parent_tags Optional. Whether to add parent tags to the rewrite rule sets. + * Default false. + * @return string IIS7 URL rewrite rule sets. + */ + public function iis7_url_rewrite_rules($add_parent_tags = \false) + { + } + /** + * Adds a rewrite rule that transforms a URL structure to a set of query vars. + * + * Any value in the $after parameter that isn't 'bottom' will result in the rule + * being placed at the top of the rewrite rules. + * + * @since 2.1.0 + * @since 4.4.0 Array support was added to the `$query` parameter. + * + * @param string $regex Regular expression to match request against. + * @param string|array $query The corresponding query vars for this rewrite rule. + * @param string $after Optional. Priority of the new rule. Accepts 'top' + * or 'bottom'. Default 'bottom'. + */ + public function add_rule($regex, $query, $after = 'bottom') + { + } + /** + * Adds a rewrite rule that doesn't correspond to index.php. + * + * @since 2.1.0 + * + * @param string $regex Regular expression to match request against. + * @param string $query The corresponding query vars for this rewrite rule. + */ + public function add_external_rule($regex, $query) + { + } + /** + * Adds an endpoint, like /trackback/. + * + * @since 2.1.0 + * @since 3.9.0 $query_var parameter added. + * @since 4.3.0 Added support for skipping query var registration by passing `false` to `$query_var`. + * + * @see add_rewrite_endpoint() for full documentation. + * @global WP $wp Current WordPress environment instance. + * + * @param string $name Name of the endpoint. + * @param int $places Endpoint mask describing the places the endpoint should be added. + * Accepts a mask of: + * - `EP_ALL` + * - `EP_NONE` + * - `EP_ALL_ARCHIVES` + * - `EP_ATTACHMENT` + * - `EP_AUTHORS` + * - `EP_CATEGORIES` + * - `EP_COMMENTS` + * - `EP_DATE` + * - `EP_DAY` + * - `EP_MONTH` + * - `EP_PAGES` + * - `EP_PERMALINK` + * - `EP_ROOT` + * - `EP_SEARCH` + * - `EP_TAGS` + * - `EP_YEAR` + * @param string|bool $query_var Optional. Name of the corresponding query variable. Pass `false` to + * skip registering a query_var for this endpoint. Defaults to the + * value of `$name`. + */ + public function add_endpoint($name, $places, $query_var = \true) + { + } + /** + * Adds a new permalink structure. + * + * A permalink structure (permastruct) is an abstract definition of a set of rewrite rules; + * it is an easy way of expressing a set of regular expressions that rewrite to a set of + * query strings. The new permastruct is added to the WP_Rewrite::$extra_permastructs array. + * + * When the rewrite rules are built by WP_Rewrite::rewrite_rules(), all of these extra + * permastructs are passed to WP_Rewrite::generate_rewrite_rules() which transforms them + * into the regular expressions that many love to hate. + * + * The `$args` parameter gives you control over how WP_Rewrite::generate_rewrite_rules() + * works on the new permastruct. + * + * @since 2.5.0 + * + * @param string $name Name for permalink structure. + * @param string $struct Permalink structure (e.g. category/%category%) + * @param array $args { + * Optional. Arguments for building rewrite rules based on the permalink structure. + * Default empty array. + * + * @type bool $with_front Whether the structure should be prepended with `WP_Rewrite::$front`. + * Default true. + * @type int $ep_mask The endpoint mask defining which endpoints are added to the structure. + * Accepts a mask of: + * - `EP_ALL` + * - `EP_NONE` + * - `EP_ALL_ARCHIVES` + * - `EP_ATTACHMENT` + * - `EP_AUTHORS` + * - `EP_CATEGORIES` + * - `EP_COMMENTS` + * - `EP_DATE` + * - `EP_DAY` + * - `EP_MONTH` + * - `EP_PAGES` + * - `EP_PERMALINK` + * - `EP_ROOT` + * - `EP_SEARCH` + * - `EP_TAGS` + * - `EP_YEAR` + * Default `EP_NONE`. + * @type bool $paged Whether archive pagination rules should be added for the structure. + * Default true. + * @type bool $feed Whether feed rewrite rules should be added for the structure. Default true. + * @type bool $forcomments Whether the feed rules should be a query for a comments feed. Default false. + * @type bool $walk_dirs Whether the 'directories' making up the structure should be walked over + * and rewrite rules built for each in-turn. Default true. + * @type bool $endpoints Whether endpoints should be applied to the generated rules. Default true. + * } + * @phpstan-param array{ + * with_front?: bool, + * ep_mask?: int, + * paged?: bool, + * feed?: bool, + * forcomments?: bool, + * walk_dirs?: bool, + * endpoints?: bool, + * } $args + */ + public function add_permastruct($name, $struct, $args = array()) + { + } + /** + * Removes a permalink structure. + * + * @since 4.5.0 + * + * @param string $name Name for permalink structure. + */ + public function remove_permastruct($name) + { + } + /** + * Removes rewrite rules and then recreate rewrite rules. + * + * Calls WP_Rewrite::wp_rewrite_rules() after removing the 'rewrite_rules' option. + * If the function named 'save_mod_rewrite_rules' exists, it will be called. + * + * @since 2.0.1 + * + * @param bool $hard Whether to update .htaccess (hard flush) or just update rewrite_rules option (soft flush). Default is true (hard). + */ + public function flush_rules($hard = \true) + { + } + /** + * Sets up the object's properties. + * + * The 'use_verbose_page_rules' object property will be set to true if the + * permalink structure begins with one of the following: '%postname%', '%category%', + * '%tag%', or '%author%'. + * + * @since 1.5.0 + */ + public function init() + { + } + /** + * Sets the main permalink structure for the site. + * + * Will update the 'permalink_structure' option, if there is a difference + * between the current permalink structure and the parameter value. Calls + * WP_Rewrite::init() after the option is updated. + * + * Fires the {@see 'permalink_structure_changed'} action once the init call has + * processed passing the old and new values + * + * @since 1.5.0 + * + * @param string $permalink_structure Permalink structure. + */ + public function set_permalink_structure($permalink_structure) + { + } + /** + * Sets the category base for the category permalink. + * + * Will update the 'category_base' option, if there is a difference between + * the current category base and the parameter value. Calls WP_Rewrite::init() + * after the option is updated. + * + * @since 1.5.0 + * + * @param string $category_base Category permalink structure base. + */ + public function set_category_base($category_base) + { + } + /** + * Sets the tag base for the tag permalink. + * + * Will update the 'tag_base' option, if there is a difference between the + * current tag base and the parameter value. Calls WP_Rewrite::init() after + * the option is updated. + * + * @since 2.3.0 + * + * @param string $tag_base Tag permalink structure base. + */ + public function set_tag_base($tag_base) + { + } + /** + * Constructor - Calls init(), which runs setup. + * + * @since 1.5.0 + */ + public function __construct() + { + } + } + /** + * User API: WP_Role class + * + * @package WordPress + * @subpackage Users + * @since 4.4.0 + */ + /** + * Core class used to extend the user roles API. + * + * @since 2.0.0 + */ + #[\AllowDynamicProperties] + class WP_Role + { + /** + * Role name. + * + * @since 2.0.0 + * @var string + */ + public $name; + /** + * List of capabilities the role contains. + * + * @since 2.0.0 + * @var bool[] Array of key/value pairs where keys represent a capability name and boolean values + * represent whether the role has that capability. + */ + public $capabilities; + /** + * Constructor - Set up object properties. + * + * The list of capabilities must have the key as the name of the capability + * and the value a boolean of whether it is granted to the role. + * + * @since 2.0.0 + * + * @param string $role Role name. + * @param bool[] $capabilities Array of key/value pairs where keys represent a capability name and boolean values + * represent whether the role has that capability. + */ + public function __construct($role, $capabilities) + { + } + /** + * Assign role a capability. + * + * @since 2.0.0 + * + * @param string $cap Capability name. + * @param bool $grant Whether role has capability privilege. + */ + public function add_cap($cap, $grant = \true) + { + } + /** + * Removes a capability from a role. + * + * @since 2.0.0 + * + * @param string $cap Capability name. + */ + public function remove_cap($cap) + { + } + /** + * Determines whether the role has the given capability. + * + * @since 2.0.0 + * + * @param string $cap Capability name. + * @return bool Whether the role has the given capability. + */ + public function has_cap($cap) + { + } + } + /** + * User API: WP_Roles class + * + * @package WordPress + * @subpackage Users + * @since 4.4.0 + */ + /** + * Core class used to implement a user roles API. + * + * The role option is simple, the structure is organized by role name that store + * the name in value of the 'name' key. The capabilities are stored as an array + * in the value of the 'capability' key. + * + * array ( + * 'rolename' => array ( + * 'name' => 'rolename', + * 'capabilities' => array() + * ) + * ) + * + * @since 2.0.0 + */ + #[\AllowDynamicProperties] + class WP_Roles + { + /** + * List of roles and capabilities. + * + * @since 2.0.0 + * @var array[] + */ + public $roles; + /** + * List of the role objects. + * + * @since 2.0.0 + * @var WP_Role[] + */ + public $role_objects = array(); + /** + * List of role names. + * + * @since 2.0.0 + * @var string[] + */ + public $role_names = array(); + /** + * Option name for storing role list. + * + * @since 2.0.0 + * @var string + */ + public $role_key; + /** + * Whether to use the database for retrieval and storage. + * + * @since 2.1.0 + * @var bool + */ + public $use_db = \true; + /** + * The site ID the roles are initialized for. + * + * @since 4.9.0 + * @var int + */ + protected $site_id = 0; + /** + * Constructor. + * + * @since 2.0.0 + * @since 4.9.0 The `$site_id` argument was added. + * + * @global array $wp_user_roles Used to set the 'roles' property value. + * + * @param int $site_id Site ID to initialize roles for. Default is the current site. + */ + public function __construct($site_id = \null) + { + } + /** + * Makes private/protected methods readable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Method to call. + * @param array $arguments Arguments to pass when calling. + * @return mixed|false Return value of the callback, false otherwise. + */ + public function __call($name, $arguments) + { + } + /** + * Sets up the object properties. + * + * The role key is set to the current prefix for the $wpdb object with + * 'user_roles' appended. If the $wp_user_roles global is set, then it will + * be used and the role option will not be updated or used. + * + * @since 2.1.0 + * @deprecated 4.9.0 Use WP_Roles::for_site() + */ + protected function _init() + { + } + /** + * Reinitializes the object. + * + * Recreates the role objects. This is typically called only by switch_to_blog() + * after switching wpdb to a new site ID. + * + * @since 3.5.0 + * @deprecated 4.7.0 Use WP_Roles::for_site() + */ + public function reinit() + { + } + /** + * Adds a role name with capabilities to the list. + * + * Updates the list of roles, if the role doesn't already exist. + * + * The capabilities are defined in the following format: `array( 'read' => true )`. + * To explicitly deny the role a capability, set the value for that capability to false. + * + * @since 2.0.0 + * + * @param string $role Role name. + * @param string $display_name Role display name. + * @param bool[] $capabilities Optional. List of capabilities keyed by the capability name, + * e.g. `array( 'edit_posts' => true, 'delete_posts' => false )`. + * Default empty array. + * @return WP_Role|void WP_Role object, if the role is added. + */ + public function add_role($role, $display_name, $capabilities = array()) + { + } + /** + * Removes a role by name. + * + * @since 2.0.0 + * + * @param string $role Role name. + */ + public function remove_role($role) + { + } + /** + * Adds a capability to role. + * + * @since 2.0.0 + * + * @param string $role Role name. + * @param string $cap Capability name. + * @param bool $grant Optional. Whether role is capable of performing capability. + * Default true. + */ + public function add_cap($role, $cap, $grant = \true) + { + } + /** + * Removes a capability from role. + * + * @since 2.0.0 + * + * @param string $role Role name. + * @param string $cap Capability name. + */ + public function remove_cap($role, $cap) + { + } + /** + * Retrieves a role object by name. + * + * @since 2.0.0 + * + * @param string $role Role name. + * @return WP_Role|null WP_Role object if found, null if the role does not exist. + */ + public function get_role($role) + { + } + /** + * Retrieves a list of role names. + * + * @since 2.0.0 + * + * @return string[] List of role names. + */ + public function get_names() + { + } + /** + * Determines whether a role name is currently in the list of available roles. + * + * @since 2.0.0 + * + * @param string $role Role name to look up. + * @return bool + */ + public function is_role($role) + { + } + /** + * Initializes all of the available roles. + * + * @since 4.9.0 + */ + public function init_roles() + { + } + /** + * Sets the site to operate on. Defaults to the current site. + * + * @since 4.9.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $site_id Site ID to initialize roles for. Default is the current site. + */ + public function for_site($site_id = \null) + { + } + /** + * Gets the ID of the site for which roles are currently initialized. + * + * @since 4.9.0 + * + * @return int Site ID. + */ + public function get_site_id() + { + } + /** + * Gets the available roles data. + * + * @since 4.9.0 + * + * @global array $wp_user_roles Used to set the 'roles' property value. + * + * @return array Roles array. + */ + protected function get_roles_data() + { + } + } + /** + * Dependencies API: WP_Scripts class + * + * @since 2.6.0 + * + * @package WordPress + * @subpackage Dependencies + */ + /** + * Core class used to register scripts. + * + * @since 2.1.0 + * + * @see WP_Dependencies + */ + class WP_Scripts extends \WP_Dependencies + { + /** + * Base URL for scripts. + * + * Full URL with trailing slash. + * + * @since 2.6.0 + * @var string + */ + public $base_url; + /** + * URL of the content directory. + * + * @since 2.8.0 + * @var string + */ + public $content_url; + /** + * Default version string for scripts. + * + * @since 2.6.0 + * @var string + */ + public $default_version; + /** + * Holds handles of scripts which are enqueued in footer. + * + * @since 2.8.0 + * @var array + */ + public $in_footer = array(); + /** + * Holds a list of script handles which will be concatenated. + * + * @since 2.8.0 + * @var string + */ + public $concat = ''; + /** + * Holds a string which contains script handles and their version. + * + * @since 2.8.0 + * @deprecated 3.4.0 + * @var string + */ + public $concat_version = ''; + /** + * Whether to perform concatenation. + * + * @since 2.8.0 + * @var bool + */ + public $do_concat = \false; + /** + * Holds HTML markup of scripts and additional data if concatenation + * is enabled. + * + * @since 2.8.0 + * @var string + */ + public $print_html = ''; + /** + * Holds inline code if concatenation is enabled. + * + * @since 2.8.0 + * @var string + */ + public $print_code = ''; + /** + * Holds a list of script handles which are not in the default directory + * if concatenation is enabled. + * + * Unused in core. + * + * @since 2.8.0 + * @var string + */ + public $ext_handles = ''; + /** + * Holds a string which contains handles and versions of scripts which + * are not in the default directory if concatenation is enabled. + * + * Unused in core. + * + * @since 2.8.0 + * @var string + */ + public $ext_version = ''; + /** + * List of default directories. + * + * @since 2.8.0 + * @var array + */ + public $default_dirs; + /** + * Constructor. + * + * @since 2.6.0 + */ + public function __construct() + { + } + /** + * Initialize the class. + * + * @since 3.4.0 + */ + public function init() + { + } + /** + * Prints scripts. + * + * Prints the scripts passed to it or the print queue. Also prints all necessary dependencies. + * + * @since 2.1.0 + * @since 2.8.0 Added the `$group` parameter. + * + * @param string|string[]|false $handles Optional. Scripts to be printed: queue (false), + * single script (string), or multiple scripts (array of strings). + * Default false. + * @param int|false $group Optional. Group level: level (int), no groups (false). + * Default false. + * @return string[] Handles of scripts that have been printed. + */ + public function print_scripts($handles = \false, $group = \false) + { + } + /** + * Prints extra scripts of a registered script. + * + * @since 2.1.0 + * @since 2.8.0 Added the `$display` parameter. + * @deprecated 3.3.0 + * + * @see print_extra_script() + * + * @param string $handle The script's registered handle. + * @param bool $display Optional. Whether to print the extra script + * instead of just returning it. Default true. + * @return bool|string|void Void if no data exists, extra scripts if `$display` is true, + * true otherwise. + */ + public function print_scripts_l10n($handle, $display = \true) + { + } + /** + * Prints extra scripts of a registered script. + * + * @since 3.3.0 + * + * @param string $handle The script's registered handle. + * @param bool $display Optional. Whether to print the extra script + * instead of just returning it. Default true. + * @return bool|string|void Void if no data exists, extra scripts if `$display` is true, + * true otherwise. + */ + public function print_extra_script($handle, $display = \true) + { + } + /** + * Processes a script dependency. + * + * @since 2.6.0 + * @since 2.8.0 Added the `$group` parameter. + * + * @see WP_Dependencies::do_item() + * + * @param string $handle The script's registered handle. + * @param int|false $group Optional. Group level: level (int), no groups (false). + * Default false. + * @return bool True on success, false on failure. + */ + public function do_item($handle, $group = \false) + { + } + /** + * Adds extra code to a registered script. + * + * @since 4.5.0 + * + * @param string $handle Name of the script to add the inline script to. + * Must be lowercase. + * @param string $data String containing the JavaScript to be added. + * @param string $position Optional. Whether to add the inline script + * before the handle or after. Default 'after'. + * @return bool True on success, false on failure. + */ + public function add_inline_script($handle, $data, $position = 'after') + { + } + /** + * Prints inline scripts registered for a specific handle. + * + * @since 4.5.0 + * + * @param string $handle Name of the script to add the inline script to. + * Must be lowercase. + * @param string $position Optional. Whether to add the inline script + * before the handle or after. Default 'after'. + * @param bool $display Optional. Whether to print the script + * instead of just returning it. Default true. + * @return string|false Script on success, false otherwise. + */ + public function print_inline_script($handle, $position = 'after', $display = \true) + { + } + /** + * Localizes a script, only if the script has already been added. + * + * @since 2.1.0 + * + * @param string $handle Name of the script to attach data to. + * @param string $object_name Name of the variable that will contain the data. + * @param array $l10n Array of data to localize. + * @return bool True on success, false on failure. + */ + public function localize($handle, $object_name, $l10n) + { + } + /** + * Sets handle group. + * + * @since 2.8.0 + * + * @see WP_Dependencies::set_group() + * + * @param string $handle Name of the item. Should be unique. + * @param bool $recursion Internal flag that calling function was called recursively. + * @param int|false $group Optional. Group level: level (int), no groups (false). + * Default false. + * @return bool Not already in the group or a lower group. + */ + public function set_group($handle, $recursion, $group = \false) + { + } + /** + * Sets a translation textdomain. + * + * @since 5.0.0 + * @since 5.1.0 The `$domain` parameter was made optional. + * + * @param string $handle Name of the script to register a translation domain to. + * @param string $domain Optional. Text domain. Default 'default'. + * @param string $path Optional. The full file path to the directory containing translation files. + * @return bool True if the text domain was registered, false if not. + */ + public function set_translations($handle, $domain = 'default', $path = '') + { + } + /** + * Prints translations set for a specific handle. + * + * @since 5.0.0 + * + * @param string $handle Name of the script to add the inline script to. + * Must be lowercase. + * @param bool $display Optional. Whether to print the script + * instead of just returning it. Default true. + * @return string|false Script on success, false otherwise. + */ + public function print_translations($handle, $display = \true) + { + } + /** + * Determines script dependencies. + * + * @since 2.1.0 + * + * @see WP_Dependencies::all_deps() + * + * @param string|string[] $handles Item handle (string) or item handles (array of strings). + * @param bool $recursion Optional. Internal flag that function is calling itself. + * Default false. + * @param int|false $group Optional. Group level: level (int), no groups (false). + * Default false. + * @return bool True on success, false on failure. + */ + public function all_deps($handles, $recursion = \false, $group = \false) + { + } + /** + * Processes items and dependencies for the head group. + * + * @since 2.8.0 + * + * @see WP_Dependencies::do_items() + * + * @return string[] Handles of items that have been processed. + */ + public function do_head_items() + { + } + /** + * Processes items and dependencies for the footer group. + * + * @since 2.8.0 + * + * @see WP_Dependencies::do_items() + * + * @return string[] Handles of items that have been processed. + */ + public function do_footer_items() + { + } + /** + * Whether a handle's source is in a default directory. + * + * @since 2.8.0 + * + * @param string $src The source of the enqueued script. + * @return bool True if found, false if not. + */ + public function in_default_dir($src) + { + } + /** + * Resets class properties. + * + * @since 2.8.0 + */ + public function reset() + { + } + } + /** + * Session API: WP_Session_Tokens class + * + * @package WordPress + * @subpackage Session + * @since 4.7.0 + */ + /** + * Abstract class for managing user session tokens. + * + * @since 4.0.0 + */ + #[\AllowDynamicProperties] + abstract class WP_Session_Tokens + { + /** + * User ID. + * + * @since 4.0.0 + * @var int User ID. + */ + protected $user_id; + /** + * Protected constructor. Use the `get_instance()` method to get the instance. + * + * @since 4.0.0 + * + * @param int $user_id User whose session to manage. + */ + protected function __construct($user_id) + { + } + /** + * Retrieves a session manager instance for a user. + * + * This method contains a {@see 'session_token_manager'} filter, allowing a plugin to swap out + * the session manager for a subclass of `WP_Session_Tokens`. + * + * @since 4.0.0 + * + * @param int $user_id User whose session to manage. + * @return WP_Session_Tokens The session object, which is by default an instance of + * the `WP_User_Meta_Session_Tokens` class. + */ + public static final function get_instance($user_id) + { + } + /** + * Retrieves a user's session for the given token. + * + * @since 4.0.0 + * + * @param string $token Session token. + * @return array|null The session, or null if it does not exist. + */ + public final function get($token) + { + } + /** + * Validates the given session token for authenticity and validity. + * + * Checks that the given token is present and hasn't expired. + * + * @since 4.0.0 + * + * @param string $token Token to verify. + * @return bool Whether the token is valid for the user. + */ + public final function verify($token) + { + } + /** + * Generates a session token and attaches session information to it. + * + * A session token is a long, random string. It is used in a cookie + * to link that cookie to an expiration time and to ensure the cookie + * becomes invalidated when the user logs out. + * + * This function generates a token and stores it with the associated + * expiration time (and potentially other session information via the + * {@see 'attach_session_information'} filter). + * + * @since 4.0.0 + * + * @param int $expiration Session expiration timestamp. + * @return string Session token. + */ + public final function create($expiration) + { + } + /** + * Updates the data for the session with the given token. + * + * @since 4.0.0 + * + * @param string $token Session token to update. + * @param array $session Session information. + */ + public final function update($token, $session) + { + } + /** + * Destroys the session with the given token. + * + * @since 4.0.0 + * + * @param string $token Session token to destroy. + */ + public final function destroy($token) + { + } + /** + * Destroys all sessions for this user except the one with the given token (presumably the one in use). + * + * @since 4.0.0 + * + * @param string $token_to_keep Session token to keep. + */ + public final function destroy_others($token_to_keep) + { + } + /** + * Determines whether a session is still valid, based on its expiration timestamp. + * + * @since 4.0.0 + * + * @param array $session Session to check. + * @return bool Whether session is valid. + */ + protected final function is_still_valid($session) + { + } + /** + * Destroys all sessions for a user. + * + * @since 4.0.0 + */ + public final function destroy_all() + { + } + /** + * Destroys all sessions for all users. + * + * @since 4.0.0 + */ + public static final function destroy_all_for_all_users() + { + } + /** + * Retrieves all sessions for a user. + * + * @since 4.0.0 + * + * @return array Sessions for a user. + */ + public final function get_all() + { + } + /** + * Retrieves all sessions of the user. + * + * @since 4.0.0 + * + * @return array Sessions of the user. + */ + protected abstract function get_sessions(); + /** + * Retrieves a session based on its verifier (token hash). + * + * @since 4.0.0 + * + * @param string $verifier Verifier for the session to retrieve. + * @return array|null The session, or null if it does not exist. + */ + protected abstract function get_session($verifier); + /** + * Updates a session based on its verifier (token hash). + * + * Omitting the second argument destroys the session. + * + * @since 4.0.0 + * + * @param string $verifier Verifier for the session to update. + * @param array $session Optional. Session. Omitting this argument destroys the session. + */ + protected abstract function update_session($verifier, $session = \null); + /** + * Destroys all sessions for this user, except the single session with the given verifier. + * + * @since 4.0.0 + * + * @param string $verifier Verifier of the session to keep. + */ + protected abstract function destroy_other_sessions($verifier); + /** + * Destroys all sessions for the user. + * + * @since 4.0.0 + */ + protected abstract function destroy_all_sessions(); + /** + * Destroys all sessions for all users. + * + * @since 4.0.0 + */ + public static function drop_sessions() + { + } + } + /** + * Feed API: WP_SimplePie_File class + * + * @package WordPress + * @subpackage Feed + * @since 4.7.0 + */ + /** + * Core class for fetching remote files and reading local files with SimplePie. + * + * This uses Core's HTTP API to make requests, which gives plugins the ability + * to hook into the process. + * + * @since 2.8.0 + * + * @see SimplePie_File + */ + #[\AllowDynamicProperties] + class WP_SimplePie_File extends \SimplePie_File + { + /** + * Timeout. + * + * @var int How long the connection should stay open in seconds. + */ + public $timeout = 10; + /** + * Constructor. + * + * @since 2.8.0 + * @since 3.2.0 Updated to use a PHP5 constructor. + * @since 5.6.1 Multiple headers are concatenated into a comma-separated string, + * rather than remaining an array. + * + * @param string $url Remote file URL. + * @param int $timeout Optional. How long the connection should stay open in seconds. + * Default 10. + * @param int $redirects Optional. The number of allowed redirects. Default 5. + * @param string|array $headers Optional. Array or string of headers to send with the request. + * Default null. + * @param string $useragent Optional. User-agent value sent. Default null. + * @param bool $force_fsockopen Optional. Whether to force opening internet or unix domain socket + * connection or not. Default false. + */ + public function __construct($url, $timeout = 10, $redirects = 5, $headers = \null, $useragent = \null, $force_fsockopen = \false) + { + } + } + /** + * Feed API: WP_SimplePie_Sanitize_KSES class + * + * @package WordPress + * @subpackage Feed + * @since 4.7.0 + */ + /** + * Core class used to implement SimplePie feed sanitization. + * + * Extends the SimplePie_Sanitize class to use KSES, because + * we cannot universally count on DOMDocument being available. + * + * @since 3.5.0 + * + * @see SimplePie_Sanitize + */ + #[\AllowDynamicProperties] + class WP_SimplePie_Sanitize_KSES extends \SimplePie_Sanitize + { + /** + * WordPress SimplePie sanitization using KSES. + * + * Sanitizes the incoming data, to ensure that it matches the type of data expected, using KSES. + * + * @since 3.5.0 + * + * @param mixed $data The data that needs to be sanitized. + * @param int $type The type of data that it's supposed to be. + * @param string $base Optional. The `xml:base` value to use when converting relative + * URLs to absolute ones. Default empty. + * @return mixed Sanitized data. + */ + public function sanitize($data, $type, $base = '') + { + } + } + /** + * Site API: WP_Site_Query class + * + * @package WordPress + * @subpackage Sites + * @since 4.6.0 + */ + /** + * Core class used for querying sites. + * + * @since 4.6.0 + * + * @see WP_Site_Query::__construct() for accepted arguments. + */ + #[\AllowDynamicProperties] + class WP_Site_Query + { + /** + * SQL for database query. + * + * @since 4.6.0 + * @var string + */ + public $request; + /** + * SQL query clauses. + * + * @since 4.6.0 + * @var array + */ + protected $sql_clauses = array('select' => '', 'from' => '', 'where' => array(), 'groupby' => '', 'orderby' => '', 'limits' => ''); + /** + * Metadata query container. + * + * @since 5.1.0 + * @var WP_Meta_Query + */ + public $meta_query = \false; + /** + * Metadata query clauses. + * + * @since 5.1.0 + * @var array + */ + protected $meta_query_clauses; + /** + * Date query container. + * + * @since 4.6.0 + * @var WP_Date_Query A date query instance. + */ + public $date_query = \false; + /** + * Query vars set by the user. + * + * @since 4.6.0 + * @var array + */ + public $query_vars; + /** + * Default values for query vars. + * + * @since 4.6.0 + * @var array + */ + public $query_var_defaults; + /** + * List of sites located by the query. + * + * @since 4.6.0 + * @var array + */ + public $sites; + /** + * The amount of found sites for the current query. + * + * @since 4.6.0 + * @var int + */ + public $found_sites = 0; + /** + * The number of pages. + * + * @since 4.6.0 + * @var int + */ + public $max_num_pages = 0; + /** + * Sets up the site query, based on the query vars passed. + * + * @since 4.6.0 + * @since 4.8.0 Introduced the 'lang_id', 'lang__in', and 'lang__not_in' parameters. + * @since 5.1.0 Introduced the 'update_site_meta_cache', 'meta_query', 'meta_key', + * 'meta_compare_key', 'meta_value', 'meta_type', and 'meta_compare' parameters. + * @since 5.3.0 Introduced the 'meta_type_key' parameter. + * + * @param string|array $query { + * Optional. Array or query string of site query parameters. Default empty. + * + * @type int[] $site__in Array of site IDs to include. Default empty. + * @type int[] $site__not_in Array of site IDs to exclude. Default empty. + * @type bool $count Whether to return a site count (true) or array of site objects. + * Default false. + * @type array $date_query Date query clauses to limit sites by. See WP_Date_Query. + * Default null. + * @type string $fields Site fields to return. Accepts 'ids' (returns an array of site IDs) + * or empty (returns an array of complete site objects). Default empty. + * @type int $ID A site ID to only return that site. Default empty. + * @type int $number Maximum number of sites to retrieve. Default 100. + * @type int $offset Number of sites to offset the query. Used to build LIMIT clause. + * Default 0. + * @type bool $no_found_rows Whether to disable the `SQL_CALC_FOUND_ROWS` query. Default true. + * @type string|array $orderby Site status or array of statuses. Accepts: + * - 'id' + * - 'domain' + * - 'path' + * - 'network_id' + * - 'last_updated' + * - 'registered' + * - 'domain_length' + * - 'path_length' + * - 'site__in' + * - 'network__in' + * - 'deleted' + * - 'mature' + * - 'spam' + * - 'archived' + * - 'public' + * - false, an empty array, or 'none' to disable `ORDER BY` clause. + * Default 'id'. + * @type string $order How to order retrieved sites. Accepts 'ASC', 'DESC'. Default 'ASC'. + * @type int $network_id Limit results to those affiliated with a given network ID. If 0, + * include all networks. Default 0. + * @type int[] $network__in Array of network IDs to include affiliated sites for. Default empty. + * @type int[] $network__not_in Array of network IDs to exclude affiliated sites for. Default empty. + * @type string $domain Limit results to those affiliated with a given domain. Default empty. + * @type string[] $domain__in Array of domains to include affiliated sites for. Default empty. + * @type string[] $domain__not_in Array of domains to exclude affiliated sites for. Default empty. + * @type string $path Limit results to those affiliated with a given path. Default empty. + * @type string[] $path__in Array of paths to include affiliated sites for. Default empty. + * @type string[] $path__not_in Array of paths to exclude affiliated sites for. Default empty. + * @type int $public Limit results to public sites. Accepts '1' or '0'. Default empty. + * @type int $archived Limit results to archived sites. Accepts '1' or '0'. Default empty. + * @type int $mature Limit results to mature sites. Accepts '1' or '0'. Default empty. + * @type int $spam Limit results to spam sites. Accepts '1' or '0'. Default empty. + * @type int $deleted Limit results to deleted sites. Accepts '1' or '0'. Default empty. + * @type int $lang_id Limit results to a language ID. Default empty. + * @type string[] $lang__in Array of language IDs to include affiliated sites for. Default empty. + * @type string[] $lang__not_in Array of language IDs to exclude affiliated sites for. Default empty. + * @type string $search Search term(s) to retrieve matching sites for. Default empty. + * @type string[] $search_columns Array of column names to be searched. Accepts 'domain' and 'path'. + * Default empty array. + * @type bool $update_site_cache Whether to prime the cache for found sites. Default true. + * @type bool $update_site_meta_cache Whether to prime the metadata cache for found sites. Default true. + * @type string|string[] $meta_key Meta key or keys to filter by. + * @type string|string[] $meta_value Meta value or values to filter by. + * @type string $meta_compare MySQL operator used for comparing the meta value. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_compare_key MySQL operator used for comparing the meta key. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_type MySQL data type that the meta_value column will be CAST to for comparisons. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_type_key MySQL data type that the meta_key column will be CAST to for comparisons. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type array $meta_query An associative array of WP_Meta_Query arguments. + * See WP_Meta_Query::__construct() for accepted values. + * } + * @phpstan-param array{ + * site__in?: int[], + * site__not_in?: int[], + * count?: bool, + * date_query?: array, + * fields?: string, + * ID?: int, + * number?: int, + * offset?: int, + * no_found_rows?: bool, + * orderby?: string|array, + * order?: string, + * network_id?: int, + * network__in?: int[], + * network__not_in?: int[], + * domain?: string, + * domain__in?: string[], + * domain__not_in?: string[], + * path?: string, + * path__in?: string[], + * path__not_in?: string[], + * public?: int, + * archived?: int, + * mature?: int, + * spam?: int, + * deleted?: int, + * lang_id?: int, + * lang__in?: string[], + * lang__not_in?: string[], + * search?: string, + * search_columns?: string[], + * update_site_cache?: bool, + * update_site_meta_cache?: bool, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * } $query + */ + public function __construct($query = '') + { + } + /** + * Parses arguments passed to the site query with default query parameters. + * + * @since 4.6.0 + * + * @see WP_Site_Query::__construct() + * + * @param string|array $query Array or string of WP_Site_Query arguments. See WP_Site_Query::__construct(). + * @phpstan-param array{ + * site__in?: int[], + * site__not_in?: int[], + * count?: bool, + * date_query?: array, + * fields?: string, + * ID?: int, + * number?: int, + * offset?: int, + * no_found_rows?: bool, + * orderby?: string|array, + * order?: string, + * network_id?: int, + * network__in?: int[], + * network__not_in?: int[], + * domain?: string, + * domain__in?: string[], + * domain__not_in?: string[], + * path?: string, + * path__in?: string[], + * path__not_in?: string[], + * public?: int, + * archived?: int, + * mature?: int, + * spam?: int, + * deleted?: int, + * lang_id?: int, + * lang__in?: string[], + * lang__not_in?: string[], + * search?: string, + * search_columns?: string[], + * update_site_cache?: bool, + * update_site_meta_cache?: bool, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * } $query See WP_Site_Query::__construct() + */ + public function parse_query($query = '') + { + } + /** + * Sets up the WordPress query for retrieving sites. + * + * @since 4.6.0 + * + * @param string|array $query Array or URL query string of parameters. + * @return array|int List of WP_Site objects, a list of site IDs when 'fields' is set to 'ids', + * or the number of sites when 'count' is passed as a query var. + */ + public function query($query) + { + } + /** + * Retrieves a list of sites matching the query vars. + * + * @since 4.6.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return array|int List of WP_Site objects, a list of site IDs when 'fields' is set to 'ids', + * or the number of sites when 'count' is passed as a query var. + */ + public function get_sites() + { + } + /** + * Used internally to get a list of site IDs matching the query vars. + * + * @since 4.6.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return int|array A single count of site IDs if a count query. An array of site IDs if a full query. + */ + protected function get_site_ids() + { + } + /** + * Used internally to generate an SQL string for searching across multiple columns. + * + * @since 4.6.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $search Search string. + * @param string[] $columns Array of columns to search. + * @return string Search SQL. + */ + protected function get_search_sql($search, $columns) + { + } + /** + * Parses and sanitizes 'orderby' keys passed to the site query. + * + * @since 4.6.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $orderby Alias for the field to order by. + * @return string|false Value to used in the ORDER clause. False otherwise. + */ + protected function parse_orderby($orderby) + { + } + /** + * Parses an 'order' query variable and cast it to 'ASC' or 'DESC' as necessary. + * + * @since 4.6.0 + * + * @param string $order The 'order' query variable. + * @return string The sanitized 'order' query variable. + */ + protected function parse_order($order) + { + } + } + /** + * Site API: WP_Site class + * + * @package WordPress + * @subpackage Multisite + * @since 4.5.0 + */ + /** + * Core class used for interacting with a multisite site. + * + * This class is used during load to populate the `$current_blog` global and + * setup the current site. + * + * @since 4.5.0 + * + * @property int $id + * @property int $network_id + * @property string $blogname + * @property string $siteurl + * @property int $post_count + * @property string $home + */ + #[\AllowDynamicProperties] + final class WP_Site + { + /** + * Site ID. + * + * Named "blog" vs. "site" for legacy reasons. + * + * A numeric string, for compatibility reasons. + * + * @since 4.5.0 + * @var string + */ + public $blog_id; + /** + * Domain of the site. + * + * @since 4.5.0 + * @var string + */ + public $domain = ''; + /** + * Path of the site. + * + * @since 4.5.0 + * @var string + */ + public $path = ''; + /** + * The ID of the site's parent network. + * + * Named "site" vs. "network" for legacy reasons. An individual site's "site" is + * its network. + * + * A numeric string, for compatibility reasons. + * + * @since 4.5.0 + * @var string + */ + public $site_id = '0'; + /** + * The date and time on which the site was created or registered. + * + * @since 4.5.0 + * @var string Date in MySQL's datetime format. + */ + public $registered = '0000-00-00 00:00:00'; + /** + * The date and time on which site settings were last updated. + * + * @since 4.5.0 + * @var string Date in MySQL's datetime format. + */ + public $last_updated = '0000-00-00 00:00:00'; + /** + * Whether the site should be treated as public. + * + * A numeric string, for compatibility reasons. + * + * @since 4.5.0 + * @var string + */ + public $public = '1'; + /** + * Whether the site should be treated as archived. + * + * A numeric string, for compatibility reasons. + * + * @since 4.5.0 + * @var string + */ + public $archived = '0'; + /** + * Whether the site should be treated as mature. + * + * Handling for this does not exist throughout WordPress core, but custom + * implementations exist that require the property to be present. + * + * A numeric string, for compatibility reasons. + * + * @since 4.5.0 + * @var string + */ + public $mature = '0'; + /** + * Whether the site should be treated as spam. + * + * A numeric string, for compatibility reasons. + * + * @since 4.5.0 + * @var string + */ + public $spam = '0'; + /** + * Whether the site should be treated as deleted. + * + * A numeric string, for compatibility reasons. + * + * @since 4.5.0 + * @var string + */ + public $deleted = '0'; + /** + * The language pack associated with this site. + * + * A numeric string, for compatibility reasons. + * + * @since 4.5.0 + * @var string + */ + public $lang_id = '0'; + /** + * Retrieves a site from the database by its ID. + * + * @since 4.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $site_id The ID of the site to retrieve. + * @return WP_Site|false The site's object if found. False if not. + */ + public static function get_instance($site_id) + { + } + /** + * Creates a new WP_Site object. + * + * Will populate object properties from the object provided and assign other + * default properties based on that information. + * + * @since 4.5.0 + * + * @param WP_Site|object $site A site object. + */ + public function __construct($site) + { + } + /** + * Converts an object to array. + * + * @since 4.6.0 + * + * @return array Object as array. + */ + public function to_array() + { + } + /** + * Getter. + * + * Allows current multisite naming conventions when getting properties. + * Allows access to extended site properties. + * + * @since 4.6.0 + * + * @param string $key Property to get. + * @return mixed Value of the property. Null if not available. + */ + public function __get($key) + { + } + /** + * Isset-er. + * + * Allows current multisite naming conventions when checking for properties. + * Checks for extended site properties. + * + * @since 4.6.0 + * + * @param string $key Property to check if set. + * @return bool Whether the property is set. + */ + public function __isset($key) + { + } + /** + * Setter. + * + * Allows current multisite naming conventions while setting properties. + * + * @since 4.6.0 + * + * @param string $key Property to set. + * @param mixed $value Value to assign to the property. + */ + public function __set($key, $value) + { + } + } + /** + * Dependencies API: WP_Styles class + * + * @since 2.6.0 + * + * @package WordPress + * @subpackage Dependencies + */ + /** + * Core class used to register styles. + * + * @since 2.6.0 + * + * @see WP_Dependencies + */ + class WP_Styles extends \WP_Dependencies + { + /** + * Base URL for styles. + * + * Full URL with trailing slash. + * + * @since 2.6.0 + * @var string + */ + public $base_url; + /** + * URL of the content directory. + * + * @since 2.8.0 + * @var string + */ + public $content_url; + /** + * Default version string for stylesheets. + * + * @since 2.6.0 + * @var string + */ + public $default_version; + /** + * The current text direction. + * + * @since 2.6.0 + * @var string + */ + public $text_direction = 'ltr'; + /** + * Holds a list of style handles which will be concatenated. + * + * @since 2.8.0 + * @var string + */ + public $concat = ''; + /** + * Holds a string which contains style handles and their version. + * + * @since 2.8.0 + * @deprecated 3.4.0 + * @var string + */ + public $concat_version = ''; + /** + * Whether to perform concatenation. + * + * @since 2.8.0 + * @var bool + */ + public $do_concat = \false; + /** + * Holds HTML markup of styles and additional data if concatenation + * is enabled. + * + * @since 2.8.0 + * @var string + */ + public $print_html = ''; + /** + * Holds inline styles if concatenation is enabled. + * + * @since 3.3.0 + * @var string + */ + public $print_code = ''; + /** + * List of default directories. + * + * @since 2.8.0 + * @var array + */ + public $default_dirs; + /** + * Constructor. + * + * @since 2.6.0 + */ + public function __construct() + { + } + /** + * Processes a style dependency. + * + * @since 2.6.0 + * @since 5.5.0 Added the `$group` parameter. + * + * @see WP_Dependencies::do_item() + * + * @param string $handle The style's registered handle. + * @param int|false $group Optional. Group level: level (int), no groups (false). + * Default false. + * @return bool True on success, false on failure. + */ + public function do_item($handle, $group = \false) + { + } + /** + * Adds extra CSS styles to a registered stylesheet. + * + * @since 3.3.0 + * + * @param string $handle The style's registered handle. + * @param string $code String containing the CSS styles to be added. + * @return bool True on success, false on failure. + */ + public function add_inline_style($handle, $code) + { + } + /** + * Prints extra CSS styles of a registered stylesheet. + * + * @since 3.3.0 + * + * @param string $handle The style's registered handle. + * @param bool $display Optional. Whether to print the inline style + * instead of just returning it. Default true. + * @return string|bool False if no data exists, inline styles if `$display` is true, + * true otherwise. + */ + public function print_inline_style($handle, $display = \true) + { + } + /** + * Determines style dependencies. + * + * @since 2.6.0 + * + * @see WP_Dependencies::all_deps() + * + * @param string|string[] $handles Item handle (string) or item handles (array of strings). + * @param bool $recursion Optional. Internal flag that function is calling itself. + * Default false. + * @param int|false $group Optional. Group level: level (int), no groups (false). + * Default false. + * @return bool True on success, false on failure. + */ + public function all_deps($handles, $recursion = \false, $group = \false) + { + } + /** + * Generates an enqueued style's fully-qualified URL. + * + * @since 2.6.0 + * + * @param string $src The source of the enqueued style. + * @param string $ver The version of the enqueued style. + * @param string $handle The style's registered handle. + * @return string Style's fully-qualified URL. + */ + public function _css_href($src, $ver, $handle) + { + } + /** + * Whether a handle's source is in a default directory. + * + * @since 2.8.0 + * + * @param string $src The source of the enqueued style. + * @return bool True if found, false if not. + */ + public function in_default_dir($src) + { + } + /** + * Processes items and dependencies for the footer group. + * + * HTML 5 allows styles in the body, grab late enqueued items and output them in the footer. + * + * @since 3.3.0 + * + * @see WP_Dependencies::do_items() + * + * @return string[] Handles of items that have been processed. + */ + public function do_footer_items() + { + } + /** + * Resets class properties. + * + * @since 3.3.0 + */ + public function reset() + { + } + } + /** + * Taxonomy API: WP_Tax_Query class + * + * @package WordPress + * @subpackage Taxonomy + * @since 4.4.0 + */ + /** + * Core class used to implement taxonomy queries for the Taxonomy API. + * + * Used for generating SQL clauses that filter a primary query according to object + * taxonomy terms. + * + * WP_Tax_Query is a helper that allows primary query classes, such as WP_Query, to filter + * their results by object metadata, by generating `JOIN` and `WHERE` subclauses to be + * attached to the primary SQL query string. + * + * @since 3.1.0 + */ + #[\AllowDynamicProperties] + class WP_Tax_Query + { + /** + * Array of taxonomy queries. + * + * See WP_Tax_Query::__construct() for information on tax query arguments. + * + * @since 3.1.0 + * @var array + */ + public $queries = array(); + /** + * The relation between the queries. Can be one of 'AND' or 'OR'. + * + * @since 3.1.0 + * @var string + */ + public $relation; + /** + * A flat list of table aliases used in the JOIN clauses. + * + * @since 4.1.0 + * @var array + */ + protected $table_aliases = array(); + /** + * Terms and taxonomies fetched by this query. + * + * We store this data in a flat array because they are referenced in a + * number of places by WP_Query. + * + * @since 4.1.0 + * @var array + */ + public $queried_terms = array(); + /** + * Database table that where the metadata's objects are stored (eg $wpdb->users). + * + * @since 4.1.0 + * @var string + */ + public $primary_table; + /** + * Column in 'primary_table' that represents the ID of the object. + * + * @since 4.1.0 + * @var string + */ + public $primary_id_column; + /** + * Constructor. + * + * @since 3.1.0 + * @since 4.1.0 Added support for `$operator` 'NOT EXISTS' and 'EXISTS' values. + * + * @param array $tax_query { + * Array of taxonomy query clauses. + * + * @type string $relation Optional. The MySQL keyword used to join + * the clauses of the query. Accepts 'AND', or 'OR'. Default 'AND'. + * @type array ...$0 { + * An array of first-order clause parameters, or another fully-formed tax query. + * + * @type string $taxonomy Taxonomy being queried. Optional when field=term_taxonomy_id. + * @type string|int|array $terms Term or terms to filter by. + * @type string $field Field to match $terms against. Accepts 'term_id', 'slug', + * 'name', or 'term_taxonomy_id'. Default: 'term_id'. + * @type string $operator MySQL operator to be used with $terms in the WHERE clause. + * Accepts 'AND', 'IN', 'NOT IN', 'EXISTS', 'NOT EXISTS'. + * Default: 'IN'. + * @type bool $include_children Optional. Whether to include child terms. + * Requires a $taxonomy. Default: true. + * } + * } + */ + public function __construct($tax_query) + { + } + /** + * Ensures the 'tax_query' argument passed to the class constructor is well-formed. + * + * Ensures that each query-level clause has a 'relation' key, and that + * each first-order clause contains all the necessary keys from `$defaults`. + * + * @since 4.1.0 + * + * @param array $queries Array of queries clauses. + * @return array Sanitized array of query clauses. + */ + public function sanitize_query($queries) + { + } + /** + * Sanitizes a 'relation' operator. + * + * @since 4.1.0 + * + * @param string $relation Raw relation key from the query argument. + * @return string Sanitized relation ('AND' or 'OR'). + */ + public function sanitize_relation($relation) + { + } + /** + * Determines whether a clause is first-order. + * + * A "first-order" clause is one that contains any of the first-order + * clause keys ('terms', 'taxonomy', 'include_children', 'field', + * 'operator'). An empty clause also counts as a first-order clause, + * for backward compatibility. Any clause that doesn't meet this is + * determined, by process of elimination, to be a higher-order query. + * + * @since 4.1.0 + * + * @param array $query Tax query arguments. + * @return bool Whether the query clause is a first-order clause. + */ + protected static function is_first_order_clause($query) + { + } + /** + * Generates SQL clauses to be appended to a main query. + * + * @since 3.1.0 + * + * @param string $primary_table Database table where the object being filtered is stored (eg wp_users). + * @param string $primary_id_column ID column for the filtered object in $primary_table. + * @return string[] { + * Array containing JOIN and WHERE SQL clauses to append to the main query. + * + * @type string $join SQL fragment to append to the main JOIN clause. + * @type string $where SQL fragment to append to the main WHERE clause. + * } + * @phpstan-return array{ + * join: string, + * where: string, + * } + */ + public function get_sql($primary_table, $primary_id_column) + { + } + /** + * Generates SQL clauses to be appended to a main query. + * + * Called by the public WP_Tax_Query::get_sql(), this method + * is abstracted out to maintain parity with the other Query classes. + * + * @since 4.1.0 + * + * @return string[] { + * Array containing JOIN and WHERE SQL clauses to append to the main query. + * + * @type string $join SQL fragment to append to the main JOIN clause. + * @type string $where SQL fragment to append to the main WHERE clause. + * } + * @phpstan-return array{ + * join: string, + * where: string, + * } + */ + protected function get_sql_clauses() + { + } + /** + * Generates SQL clauses for a single query array. + * + * If nested subqueries are found, this method recurses the tree to + * produce the properly nested SQL. + * + * @since 4.1.0 + * + * @param array $query Query to parse (passed by reference). + * @param int $depth Optional. Number of tree levels deep we currently are. + * Used to calculate indentation. Default 0. + * @return string[] { + * Array containing JOIN and WHERE SQL clauses to append to a single query array. + * + * @type string $join SQL fragment to append to the main JOIN clause. + * @type string $where SQL fragment to append to the main WHERE clause. + * } + * @phpstan-return array{ + * join: string, + * where: string, + * } + */ + protected function get_sql_for_query(&$query, $depth = 0) + { + } + /** + * Generates SQL JOIN and WHERE clauses for a "first-order" query clause. + * + * @since 4.1.0 + * + * @global wpdb $wpdb The WordPress database abstraction object. + * + * @param array $clause Query clause (passed by reference). + * @param array $parent_query Parent query array. + * @return string[] { + * Array containing JOIN and WHERE SQL clauses to append to a first-order query. + * + * @type string $join SQL fragment to append to the main JOIN clause. + * @type string $where SQL fragment to append to the main WHERE clause. + * } + * @phpstan-return array{ + * join: string, + * where: string, + * } + */ + public function get_sql_for_clause(&$clause, $parent_query) + { + } + /** + * Identifies an existing table alias that is compatible with the current query clause. + * + * We avoid unnecessary table joins by allowing each clause to look for + * an existing table alias that is compatible with the query that it + * needs to perform. + * + * An existing alias is compatible if (a) it is a sibling of `$clause` + * (ie, it's under the scope of the same relation), and (b) the combination + * of operator and relation between the clauses allows for a shared table + * join. In the case of WP_Tax_Query, this only applies to 'IN' + * clauses that are connected by the relation 'OR'. + * + * @since 4.1.0 + * + * @param array $clause Query clause. + * @param array $parent_query Parent query of $clause. + * @return string|false Table alias if found, otherwise false. + */ + protected function find_compatible_table_alias($clause, $parent_query) + { + } + /** + * Transforms a single query, from one field to another. + * + * Operates on the `$query` object by reference. In the case of error, + * `$query` is converted to a WP_Error object. + * + * @since 3.2.0 + * + * @global wpdb $wpdb The WordPress database abstraction object. + * + * @param array $query The single query. Passed by reference. + * @param string $resulting_field The resulting field. Accepts 'slug', 'name', 'term_taxonomy_id', + * or 'term_id'. Default 'term_id'. + */ + public function transform_query(&$query, $resulting_field) + { + } + } + /** + * Taxonomy API: WP_Taxonomy class + * + * @package WordPress + * @subpackage Taxonomy + * @since 4.7.0 + */ + /** + * Core class used for interacting with taxonomies. + * + * @since 4.7.0 + */ + #[\AllowDynamicProperties] + final class WP_Taxonomy + { + /** + * Taxonomy key. + * + * @since 4.7.0 + * @var string + */ + public $name; + /** + * Name of the taxonomy shown in the menu. Usually plural. + * + * @since 4.7.0 + * @var string + */ + public $label; + /** + * Labels object for this taxonomy. + * + * If not set, tag labels are inherited for non-hierarchical types + * and category labels for hierarchical ones. + * + * @see get_taxonomy_labels() + * + * @since 4.7.0 + * @var stdClass + */ + public $labels; + /** + * A short descriptive summary of what the taxonomy is for. + * + * @since 4.7.0 + * @var string + */ + public $description = ''; + /** + * Whether a taxonomy is intended for use publicly either via the admin interface or by front-end users. + * + * @since 4.7.0 + * @var bool + */ + public $public = \true; + /** + * Whether the taxonomy is publicly queryable. + * + * @since 4.7.0 + * @var bool + */ + public $publicly_queryable = \true; + /** + * Whether the taxonomy is hierarchical. + * + * @since 4.7.0 + * @var bool + */ + public $hierarchical = \false; + /** + * Whether to generate and allow a UI for managing terms in this taxonomy in the admin. + * + * @since 4.7.0 + * @var bool + */ + public $show_ui = \true; + /** + * Whether to show the taxonomy in the admin menu. + * + * If true, the taxonomy is shown as a submenu of the object type menu. If false, no menu is shown. + * + * @since 4.7.0 + * @var bool + */ + public $show_in_menu = \true; + /** + * Whether the taxonomy is available for selection in navigation menus. + * + * @since 4.7.0 + * @var bool + */ + public $show_in_nav_menus = \true; + /** + * Whether to list the taxonomy in the tag cloud widget controls. + * + * @since 4.7.0 + * @var bool + */ + public $show_tagcloud = \true; + /** + * Whether to show the taxonomy in the quick/bulk edit panel. + * + * @since 4.7.0 + * @var bool + */ + public $show_in_quick_edit = \true; + /** + * Whether to display a column for the taxonomy on its post type listing screens. + * + * @since 4.7.0 + * @var bool + */ + public $show_admin_column = \false; + /** + * The callback function for the meta box display. + * + * @since 4.7.0 + * @var bool|callable + */ + public $meta_box_cb = \null; + /** + * The callback function for sanitizing taxonomy data saved from a meta box. + * + * @since 5.1.0 + * @var callable + */ + public $meta_box_sanitize_cb = \null; + /** + * An array of object types this taxonomy is registered for. + * + * @since 4.7.0 + * @var string[] + */ + public $object_type = \null; + /** + * Capabilities for this taxonomy. + * + * @since 4.7.0 + * @var stdClass + */ + public $cap; + /** + * Rewrites information for this taxonomy. + * + * @since 4.7.0 + * @var array|false + */ + public $rewrite; + /** + * Query var string for this taxonomy. + * + * @since 4.7.0 + * @var string|false + */ + public $query_var; + /** + * Function that will be called when the count is updated. + * + * @since 4.7.0 + * @var callable + */ + public $update_count_callback; + /** + * Whether this taxonomy should appear in the REST API. + * + * Default false. If true, standard endpoints will be registered with + * respect to $rest_base and $rest_controller_class. + * + * @since 4.7.4 + * @var bool $show_in_rest + */ + public $show_in_rest; + /** + * The base path for this taxonomy's REST API endpoints. + * + * @since 4.7.4 + * @var string|bool $rest_base + */ + public $rest_base; + /** + * The namespace for this taxonomy's REST API endpoints. + * + * @since 5.9.0 + * @var string|bool $rest_namespace + */ + public $rest_namespace; + /** + * The controller for this taxonomy's REST API endpoints. + * + * Custom controllers must extend WP_REST_Controller. + * + * @since 4.7.4 + * @var string|bool $rest_controller_class + */ + public $rest_controller_class; + /** + * The controller instance for this taxonomy's REST API endpoints. + * + * Lazily computed. Should be accessed using {@see WP_Taxonomy::get_rest_controller()}. + * + * @since 5.5.0 + * @var WP_REST_Controller $rest_controller + */ + public $rest_controller; + /** + * The default term name for this taxonomy. If you pass an array you have + * to set 'name' and optionally 'slug' and 'description'. + * + * @since 5.5.0 + * @var array|string + */ + public $default_term; + /** + * Whether terms in this taxonomy should be sorted in the order they are provided to `wp_set_object_terms()`. + * + * Use this in combination with `'orderby' => 'term_order'` when fetching terms. + * + * @since 2.5.0 + * @var bool|null + */ + public $sort = \null; + /** + * Array of arguments to automatically use inside `wp_get_object_terms()` for this taxonomy. + * + * @since 2.6.0 + * @var array|null + */ + public $args = \null; + /** + * Whether it is a built-in taxonomy. + * + * @since 4.7.0 + * @var bool + */ + public $_builtin; + /** + * Constructor. + * + * See the register_taxonomy() function for accepted arguments for `$args`. + * + * @since 4.7.0 + * + * @global WP $wp Current WordPress environment instance. + * + * @param string $taxonomy Taxonomy key, must not exceed 32 characters. + * @param array|string $object_type Name of the object type for the taxonomy object. + * @param array|string $args Optional. Array or query string of arguments for registering a taxonomy. + * Default empty array. + */ + public function __construct($taxonomy, $object_type, $args = array()) + { + } + /** + * Sets taxonomy properties. + * + * See the register_taxonomy() function for accepted arguments for `$args`. + * + * @since 4.7.0 + * + * @param string|string[] $object_type Name or array of names of the object types for the taxonomy. + * @param array|string $args Array or query string of arguments for registering a taxonomy. + */ + public function set_props($object_type, $args) + { + } + /** + * Adds the necessary rewrite rules for the taxonomy. + * + * @since 4.7.0 + * + * @global WP $wp Current WordPress environment instance. + */ + public function add_rewrite_rules() + { + } + /** + * Removes any rewrite rules, permastructs, and rules for the taxonomy. + * + * @since 4.7.0 + * + * @global WP $wp Current WordPress environment instance. + */ + public function remove_rewrite_rules() + { + } + /** + * Registers the ajax callback for the meta box. + * + * @since 4.7.0 + */ + public function add_hooks() + { + } + /** + * Removes the ajax callback for the meta box. + * + * @since 4.7.0 + */ + public function remove_hooks() + { + } + /** + * Gets the REST API controller for this taxonomy. + * + * Will only instantiate the controller class once per request. + * + * @since 5.5.0 + * + * @return WP_REST_Controller|null The controller instance, or null if the taxonomy + * is set not to show in rest. + */ + public function get_rest_controller() + { + } + /** + * Returns the default labels for taxonomies. + * + * @since 6.0.0 + * + * @return (string|null)[][] The default labels for taxonomies. + */ + public static function get_default_labels() + { + } + /** + * Resets the cache for the default labels. + * + * @since 6.0.0 + */ + public static function reset_default_labels() + { + } + } + /** + * Taxonomy API: WP_Term_Query class. + * + * @package WordPress + * @subpackage Taxonomy + * @since 4.6.0 + */ + /** + * Class used for querying terms. + * + * @since 4.6.0 + * + * @see WP_Term_Query::__construct() for accepted arguments. + */ + #[\AllowDynamicProperties] + class WP_Term_Query + { + /** + * SQL string used to perform database query. + * + * @since 4.6.0 + * @var string + */ + public $request; + /** + * Metadata query container. + * + * @since 4.6.0 + * @var WP_Meta_Query A meta query instance. + */ + public $meta_query = \false; + /** + * Metadata query clauses. + * + * @since 4.6.0 + * @var array + */ + protected $meta_query_clauses; + /** + * SQL query clauses. + * + * @since 4.6.0 + * @var array + */ + protected $sql_clauses = array('select' => '', 'from' => '', 'where' => array(), 'orderby' => '', 'limits' => ''); + /** + * Query vars set by the user. + * + * @since 4.6.0 + * @var array + */ + public $query_vars; + /** + * Default values for query vars. + * + * @since 4.6.0 + * @var array + */ + public $query_var_defaults; + /** + * List of terms located by the query. + * + * @since 4.6.0 + * @var array + */ + public $terms; + /** + * Constructor. + * + * Sets up the term query, based on the query vars passed. + * + * @since 4.6.0 + * @since 4.6.0 Introduced 'term_taxonomy_id' parameter. + * @since 4.7.0 Introduced 'object_ids' parameter. + * @since 4.9.0 Added 'slug__in' support for 'orderby'. + * @since 5.1.0 Introduced the 'meta_compare_key' parameter. + * @since 5.3.0 Introduced the 'meta_type_key' parameter. + * + * @param string|array $query { + * Optional. Array or query string of term query parameters. Default empty. + * + * @type string|string[] $taxonomy Taxonomy name, or array of taxonomy names, to which results + * should be limited. + * @type int|int[] $object_ids Object ID, or array of object IDs. Results will be + * limited to terms associated with these objects. + * @type string $orderby Field(s) to order terms by. Accepts: + * - Term fields ('name', 'slug', 'term_group', 'term_id', 'id', + * 'description', 'parent', 'term_order'). Unless `$object_ids` + * is not empty, 'term_order' is treated the same as 'term_id'. + * - 'count' to use the number of objects associated with the term. + * - 'include' to match the 'order' of the `$include` param. + * - 'slug__in' to match the 'order' of the `$slug` param. + * - 'meta_value' + * - 'meta_value_num'. + * - The value of `$meta_key`. + * - The array keys of `$meta_query`. + * - 'none' to omit the ORDER BY clause. + * Default 'name'. + * @type string $order Whether to order terms in ascending or descending order. + * Accepts 'ASC' (ascending) or 'DESC' (descending). + * Default 'ASC'. + * @type bool|int $hide_empty Whether to hide terms not assigned to any posts. Accepts + * 1|true or 0|false. Default 1|true. + * @type int[]|string $include Array or comma/space-separated string of term IDs to include. + * Default empty array. + * @type int[]|string $exclude Array or comma/space-separated string of term IDs to exclude. + * If `$include` is non-empty, `$exclude` is ignored. + * Default empty array. + * @type int[]|string $exclude_tree Array or comma/space-separated string of term IDs to exclude + * along with all of their descendant terms. If `$include` is + * non-empty, `$exclude_tree` is ignored. Default empty array. + * @type int|string $number Maximum number of terms to return. Accepts ''|0 (all) or any + * positive number. Default ''|0 (all). Note that `$number` may + * not return accurate results when coupled with `$object_ids`. + * See #41796 for details. + * @type int $offset The number by which to offset the terms query. Default empty. + * @type string $fields Term fields to query for. Accepts: + * - 'all' Returns an array of complete term objects (`WP_Term[]`). + * - 'all_with_object_id' Returns an array of term objects + * with the 'object_id' param (`WP_Term[]`). Works only + * when the `$object_ids` parameter is populated. + * - 'ids' Returns an array of term IDs (`int[]`). + * - 'tt_ids' Returns an array of term taxonomy IDs (`int[]`). + * - 'names' Returns an array of term names (`string[]`). + * - 'slugs' Returns an array of term slugs (`string[]`). + * - 'count' Returns the number of matching terms (`int`). + * - 'id=>parent' Returns an associative array of parent term IDs, + * keyed by term ID (`int[]`). + * - 'id=>name' Returns an associative array of term names, + * keyed by term ID (`string[]`). + * - 'id=>slug' Returns an associative array of term slugs, + * keyed by term ID (`string[]`). + * Default 'all'. + * @type bool $count Whether to return a term count. If true, will take precedence + * over `$fields`. Default false. + * @type string|string[] $name Name or array of names to return term(s) for. + * Default empty. + * @type string|string[] $slug Slug or array of slugs to return term(s) for. + * Default empty. + * @type int|int[] $term_taxonomy_id Term taxonomy ID, or array of term taxonomy IDs, + * to match when querying terms. + * @type bool $hierarchical Whether to include terms that have non-empty descendants + * (even if `$hide_empty` is set to true). Default true. + * @type string $search Search criteria to match terms. Will be SQL-formatted with + * wildcards before and after. Default empty. + * @type string $name__like Retrieve terms with criteria by which a term is LIKE + * `$name__like`. Default empty. + * @type string $description__like Retrieve terms where the description is LIKE + * `$description__like`. Default empty. + * @type bool $pad_counts Whether to pad the quantity of a term's children in the + * quantity of each term's "count" object variable. + * Default false. + * @type string $get Whether to return terms regardless of ancestry or whether the + * terms are empty. Accepts 'all' or '' (disabled). + * Default ''. + * @type int $child_of Term ID to retrieve child terms of. If multiple taxonomies + * are passed, `$child_of` is ignored. Default 0. + * @type int $parent Parent term ID to retrieve direct-child terms of. + * Default empty. + * @type bool $childless True to limit results to terms that have no children. + * This parameter has no effect on non-hierarchical taxonomies. + * Default false. + * @type string $cache_domain Unique cache key to be produced when this query is stored in + * an object cache. Default 'core'. + * @type bool $update_term_meta_cache Whether to prime meta caches for matched terms. Default true. + * @type string|string[] $meta_key Meta key or keys to filter by. + * @type string|string[] $meta_value Meta value or values to filter by. + * @type string $meta_compare MySQL operator used for comparing the meta value. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_compare_key MySQL operator used for comparing the meta key. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_type MySQL data type that the meta_value column will be CAST to for comparisons. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_type_key MySQL data type that the meta_key column will be CAST to for comparisons. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type array $meta_query An associative array of WP_Meta_Query arguments. + * See WP_Meta_Query::__construct() for accepted values. + * } + * @phpstan-param array{ + * taxonomy?: string|string[], + * object_ids?: int|int[], + * orderby?: string, + * order?: string, + * hide_empty?: bool|int, + * include?: int[]|string, + * exclude?: int[]|string, + * exclude_tree?: int[]|string, + * number?: int|string, + * offset?: int, + * fields?: string, + * count?: bool, + * name?: string|string[], + * slug?: string|string[], + * term_taxonomy_id?: int|int[], + * hierarchical?: bool, + * search?: string, + * name__like?: string, + * description__like?: string, + * pad_counts?: bool, + * get?: string, + * child_of?: int, + * parent?: int, + * childless?: bool, + * cache_domain?: string, + * update_term_meta_cache?: bool, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * } $query + */ + public function __construct($query = '') + { + } + /** + * Parse arguments passed to the term query with default query parameters. + * + * @since 4.6.0 + * + * @param string|array $query WP_Term_Query arguments. See WP_Term_Query::__construct() + * @phpstan-param array{ + * taxonomy?: string|string[], + * object_ids?: int|int[], + * orderby?: string, + * order?: string, + * hide_empty?: bool|int, + * include?: int[]|string, + * exclude?: int[]|string, + * exclude_tree?: int[]|string, + * number?: int|string, + * offset?: int, + * fields?: string, + * count?: bool, + * name?: string|string[], + * slug?: string|string[], + * term_taxonomy_id?: int|int[], + * hierarchical?: bool, + * search?: string, + * name__like?: string, + * description__like?: string, + * pad_counts?: bool, + * get?: string, + * child_of?: int, + * parent?: int, + * childless?: bool, + * cache_domain?: string, + * update_term_meta_cache?: bool, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * } $query See WP_Term_Query::__construct() + */ + public function parse_query($query = '') + { + } + /** + * Sets up the query and retrieves the results. + * + * The return type varies depending on the value passed to `$args['fields']`. See + * WP_Term_Query::get_terms() for details. + * + * @since 4.6.0 + * + * @param string|array $query Array or URL query string of parameters. + * @return WP_Term[]|int[]|string[]|string Array of terms, or number of terms as numeric string + * when 'count' is passed as a query var. + */ + public function query($query) + { + } + /** + * Retrieves the query results. + * + * The return type varies depending on the value passed to `$args['fields']`. + * + * The following will result in an array of `WP_Term` objects being returned: + * + * - 'all' + * - 'all_with_object_id' + * + * The following will result in a numeric string being returned: + * + * - 'count' + * + * The following will result in an array of text strings being returned: + * + * - 'id=>name' + * - 'id=>slug' + * - 'names' + * - 'slugs' + * + * The following will result in an array of numeric strings being returned: + * + * - 'id=>parent' + * + * The following will result in an array of integers being returned: + * + * - 'ids' + * - 'tt_ids' + * + * @since 4.6.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return WP_Term[]|int[]|string[]|string Array of terms, or number of terms as numeric string + * when 'count' is passed as a query var. + */ + public function get_terms() + { + } + /** + * Parse and sanitize 'orderby' keys passed to the term query. + * + * @since 4.6.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $orderby_raw Alias for the field to order by. + * @return string|false Value to used in the ORDER clause. False otherwise. + */ + protected function parse_orderby($orderby_raw) + { + } + /** + * Format response depending on field requested. + * + * @since 6.0.0 + * + * @param WP_Term[] $term_objects Array of term objects. + * @param string $_fields Field to format. + * + * @return WP_Term[]|int[]|string[] Array of terms / strings / ints depending on field requested. + */ + protected function format_terms($term_objects, $_fields) + { + } + /** + * Generate the ORDER BY clause for an 'orderby' param that is potentially related to a meta query. + * + * @since 4.6.0 + * + * @param string $orderby_raw Raw 'orderby' value passed to WP_Term_Query. + * @return string ORDER BY clause. + */ + protected function parse_orderby_meta($orderby_raw) + { + } + /** + * Parse an 'order' query variable and cast it to ASC or DESC as necessary. + * + * @since 4.6.0 + * + * @param string $order The 'order' query variable. + * @return string The sanitized 'order' query variable. + */ + protected function parse_order($order) + { + } + /** + * Used internally to generate a SQL string related to the 'search' parameter. + * + * @since 4.6.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $search Search string. + * @return string Search SQL. + */ + protected function get_search_sql($search) + { + } + /** + * Creates an array of term objects from an array of term IDs. + * + * Also discards invalid term objects. + * + * @since 4.9.8 + * + * @param Object[]|int[] $terms List of objects or term ids. + * @return WP_Term[] Array of `WP_Term` objects. + */ + protected function populate_terms($terms) + { + } + } + /** + * Taxonomy API: WP_Term class + * + * @package WordPress + * @subpackage Taxonomy + * @since 4.4.0 + */ + /** + * Core class used to implement the WP_Term object. + * + * @since 4.4.0 + * + * @property-read object $data Sanitized term data. + */ + #[\AllowDynamicProperties] + final class WP_Term + { + /** + * Term ID. + * + * @since 4.4.0 + * @var int + */ + public $term_id; + /** + * The term's name. + * + * @since 4.4.0 + * @var string + */ + public $name = ''; + /** + * The term's slug. + * + * @since 4.4.0 + * @var string + */ + public $slug = ''; + /** + * The term's term_group. + * + * @since 4.4.0 + * @var int + */ + public $term_group = ''; + /** + * Term Taxonomy ID. + * + * @since 4.4.0 + * @var int + */ + public $term_taxonomy_id = 0; + /** + * The term's taxonomy name. + * + * @since 4.4.0 + * @var string + */ + public $taxonomy = ''; + /** + * The term's description. + * + * @since 4.4.0 + * @var string + */ + public $description = ''; + /** + * ID of a term's parent term. + * + * @since 4.4.0 + * @var int + */ + public $parent = 0; + /** + * Cached object count for this term. + * + * @since 4.4.0 + * @var int + */ + public $count = 0; + /** + * Stores the term object's sanitization level. + * + * Does not correspond to a database field. + * + * @since 4.4.0 + * @var string + */ + public $filter = 'raw'; + /** + * Retrieve WP_Term instance. + * + * @since 4.4.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $term_id Term ID. + * @param string $taxonomy Optional. Limit matched terms to those matching `$taxonomy`. Only used for + * disambiguating potentially shared terms. + * @return WP_Term|WP_Error|false Term object, if found. WP_Error if `$term_id` is shared between taxonomies and + * there's insufficient data to distinguish which term is intended. + * False for other failures. + */ + public static function get_instance($term_id, $taxonomy = \null) + { + } + /** + * Constructor. + * + * @since 4.4.0 + * + * @param WP_Term|object $term Term object. + */ + public function __construct($term) + { + } + /** + * Sanitizes term fields, according to the filter type provided. + * + * @since 4.4.0 + * + * @param string $filter Filter context. Accepts 'edit', 'db', 'display', 'attribute', 'js', 'rss', or 'raw'. + */ + public function filter($filter) + { + } + /** + * Converts an object to array. + * + * @since 4.4.0 + * + * @return array Object as array. + */ + public function to_array() + { + } + /** + * Getter. + * + * @since 4.4.0 + * + * @param string $key Property to get. + * @return mixed Property value. + */ + public function __get($key) + { + } + } + /** + * Diff API: WP_Text_Diff_Renderer_inline class + * + * @package WordPress + * @subpackage Diff + * @since 4.7.0 + */ + /** + * Better word splitting than the PEAR package provides. + * + * @since 2.6.0 + * @uses Text_Diff_Renderer_inline Extends + */ + #[\AllowDynamicProperties] + class WP_Text_Diff_Renderer_inline extends \Text_Diff_Renderer_inline + { + /** + * @ignore + * @since 2.6.0 + * + * @param string $string + * @param string $newlineEscape + * @return string + */ + public function _splitOnWords($string, $newlineEscape = "\n") + { + } + } + /** + * Diff API: WP_Text_Diff_Renderer_Table class + * + * @package WordPress + * @subpackage Diff + * @since 4.7.0 + */ + /** + * Table renderer to display the diff lines. + * + * @since 2.6.0 + * @uses Text_Diff_Renderer Extends + */ + #[\AllowDynamicProperties] + class WP_Text_Diff_Renderer_Table extends \Text_Diff_Renderer + { + /** + * @see Text_Diff_Renderer::_leading_context_lines + * @var int + * @since 2.6.0 + */ + public $_leading_context_lines = 10000; + /** + * @see Text_Diff_Renderer::_trailing_context_lines + * @var int + * @since 2.6.0 + */ + public $_trailing_context_lines = 10000; + /** + * Threshold for when a diff should be saved or omitted. + * + * @var float + * @since 2.6.0 + */ + protected $_diff_threshold = 0.6; + /** + * Inline display helper object name. + * + * @var string + * @since 2.6.0 + */ + protected $inline_diff_renderer = 'WP_Text_Diff_Renderer_inline'; + /** + * Should we show the split view or not + * + * @var string + * @since 3.6.0 + */ + protected $_show_split_view = \true; + protected $compat_fields = array('_show_split_view', 'inline_diff_renderer', '_diff_threshold'); + /** + * Caches the output of count_chars() in compute_string_distance() + * + * @var array + * @since 5.0.0 + */ + protected $count_cache = array(); + /** + * Caches the difference calculation in compute_string_distance() + * + * @var array + * @since 5.0.0 + */ + protected $difference_cache = array(); + /** + * Constructor - Call parent constructor with params array. + * + * This will set class properties based on the key value pairs in the array. + * + * @since 2.6.0 + * + * @param array $params + */ + public function __construct($params = array()) + { + } + /** + * @ignore + * + * @param string $header + * @return string + */ + public function _startBlock($header) + { + } + /** + * @ignore + * + * @param array $lines + * @param string $prefix + */ + public function _lines($lines, $prefix = ' ') + { + } + /** + * @ignore + * + * @param string $line HTML-escape the value. + * @return string + */ + public function addedLine($line) + { + } + /** + * @ignore + * + * @param string $line HTML-escape the value. + * @return string + */ + public function deletedLine($line) + { + } + /** + * @ignore + * + * @param string $line HTML-escape the value. + * @return string + */ + public function contextLine($line) + { + } + /** + * @ignore + * + * @return string + */ + public function emptyLine() + { + } + /** + * @ignore + * + * @param array $lines + * @param bool $encode + * @return string + */ + public function _added($lines, $encode = \true) + { + } + /** + * @ignore + * + * @param array $lines + * @param bool $encode + * @return string + */ + public function _deleted($lines, $encode = \true) + { + } + /** + * @ignore + * + * @param array $lines + * @param bool $encode + * @return string + */ + public function _context($lines, $encode = \true) + { + } + /** + * Process changed lines to do word-by-word diffs for extra highlighting. + * + * (TRAC style) sometimes these lines can actually be deleted or added rows. + * We do additional processing to figure that out + * + * @since 2.6.0 + * + * @param array $orig + * @param array $final + * @return string + */ + public function _changed($orig, $final) + { + } + /** + * Takes changed blocks and matches which rows in orig turned into which rows in final. + * + * @since 2.6.0 + * + * @param array $orig Lines of the original version of the text. + * @param array $final Lines of the final version of the text. + * @return array { + * Array containing results of comparing the original text to the final text. + * + * @type array $orig_matches Associative array of original matches. Index == row + * number of `$orig`, value == corresponding row number + * of that same line in `$final` or 'x' if there is no + * corresponding row (indicating it is a deleted line). + * @type array $final_matches Associative array of final matches. Index == row + * number of `$final`, value == corresponding row number + * of that same line in `$orig` or 'x' if there is no + * corresponding row (indicating it is a new line). + * @type array $orig_rows Associative array of interleaved rows of `$orig` with + * blanks to keep matches aligned with side-by-side diff + * of `$final`. A value >= 0 corresponds to index of `$orig`. + * Value < 0 indicates a blank row. + * @type array $final_rows Associative array of interleaved rows of `$final` with + * blanks to keep matches aligned with side-by-side diff + * of `$orig`. A value >= 0 corresponds to index of `$final`. + * Value < 0 indicates a blank row. + * } + * @phpstan-return array{ + * orig_matches: array, + * final_matches: array, + * orig_rows: array, + * final_rows: array, + * } + */ + public function interleave_changed_lines($orig, $final) + { + } + /** + * Computes a number that is intended to reflect the "distance" between two strings. + * + * @since 2.6.0 + * + * @param string $string1 + * @param string $string2 + * @return int + */ + public function compute_string_distance($string1, $string2) + { + } + /** + * @ignore + * @since 2.6.0 + * + * @param int $a + * @param int $b + * @return int + */ + public function difference($a, $b) + { + } + /** + * Make private properties readable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to get. + * @return mixed Property. + */ + public function __get($name) + { + } + /** + * Make private properties settable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to check if set. + * @param mixed $value Property value. + * @return mixed Newly-set property. + */ + public function __set($name, $value) + { + } + /** + * Make private properties checkable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to check if set. + * @return bool Whether the property is set. + */ + public function __isset($name) + { + } + /** + * Make private properties un-settable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to unset. + */ + public function __unset($name) + { + } + } + /** + * Locale API: WP_Textdomain_Registry class + * + * @package WordPress + * @subpackage i18n + * @since 6.1.0 + */ + /** + * Core class used for registering text domains. + * + * @since 6.1.0 + */ + #[\AllowDynamicProperties] + class WP_Textdomain_Registry + { + /** + * List of domains and all their language directory paths for each locale. + * + * @since 6.1.0 + * + * @var array + */ + protected $all = array(); + /** + * List of domains and their language directory path for the current (most recent) locale. + * + * @since 6.1.0 + * + * @var array + */ + protected $current = array(); + /** + * List of domains and their custom language directory paths. + * + * @see load_plugin_textdomain() + * @see load_theme_textdomain() + * + * @since 6.1.0 + * + * @var array + */ + protected $custom_paths = array(); + /** + * Holds a cached list of available .mo files to improve performance. + * + * @since 6.1.0 + * + * @var array + */ + protected $cached_mo_files; + /** + * Returns the languages directory path for a specific domain and locale. + * + * @since 6.1.0 + * + * @param string $domain Text domain. + * @param string $locale Locale. + * + * @return string|false MO file path or false if there is none available. + */ + public function get($domain, $locale) + { + } + /** + * Determines whether any MO file paths are available for the domain. + * + * This is the case if a path has been set for the current locale, + * or if there is no information stored yet, in which case + * {@see _load_textdomain_just_in_time()} will fetch the information first. + * + * @since 6.1.0 + * + * @param string $domain Text domain. + * @return bool Whether any MO file paths are available for the domain. + */ + public function has($domain) + { + } + /** + * Sets the language directory path for a specific domain and locale. + * + * Also sets the 'current' property for direct access + * to the path for the current (most recent) locale. + * + * @since 6.1.0 + * + * @param string $domain Text domain. + * @param string $locale Locale. + * @param string|false $path Language directory path or false if there is none available. + */ + public function set($domain, $locale, $path) + { + } + /** + * Sets the custom path to the plugin's/theme's languages directory. + * + * Used by {@see load_plugin_textdomain()} and {@see load_theme_textdomain()}. + * + * @param string $domain Text domain. + * @param string $path Language directory path. + */ + public function set_custom_path($domain, $path) + { + } + } + /** + * WP_Theme_JSON_Data class + * + * @package WordPress + * @subpackage Theme + * @since 6.1.0 + */ + /** + * Class to provide access to update a theme.json structure. + */ + #[\AllowDynamicProperties] + class WP_Theme_JSON_Data + { + /** + * Constructor. + * + * @since 6.1.0 + * + * @link https://developer.wordpress.org/block-editor/reference-guides/theme-json-reference/ + * + * @param array $data Array following the theme.json specification. + * @param string $origin The origin of the data: default, theme, user. + */ + public function __construct($data = array(), $origin = 'theme') + { + } + /** + * Updates the theme.json with the the given data. + * + * @since 6.1.0 + * + * @param array $new_data Array following the theme.json specification. + * + * @return WP_Theme_JSON_Data The own instance with access to the modified data. + */ + public function update_with($new_data) + { + } + /** + * Returns an array containing the underlying data + * following the theme.json specification. + * + * @since 6.1.0 + * + * @return array + */ + public function get_data() + { + } + } + /** + * WP_Theme_JSON_Resolver class + * + * @package WordPress + * @subpackage Theme + * @since 5.8.0 + */ + /** + * Class that abstracts the processing of the different data sources + * for site-level config and offers an API to work with them. + * + * This class is for internal core usage and is not supposed to be used by extenders (plugins and/or themes). + * This is a low-level API that may need to do breaking changes. Please, + * use get_global_settings, get_global_styles, and get_global_stylesheet instead. + * + * @access private + */ + #[\AllowDynamicProperties] + class WP_Theme_JSON_Resolver + { + /** + * Container for keep track of registered blocks. + * + * @since 6.1.0 + * @var array + */ + protected static $blocks_cache = array('core' => array(), 'blocks' => array(), 'theme' => array(), 'user' => array()); + /** + * Container for data coming from core. + * + * @since 5.8.0 + * @var WP_Theme_JSON + */ + protected static $core = \null; + /** + * Container for data coming from the blocks. + * + * @since 6.1.0 + * @var WP_Theme_JSON + */ + protected static $blocks = \null; + /** + * Container for data coming from the theme. + * + * @since 5.8.0 + * @var WP_Theme_JSON + */ + protected static $theme = \null; + /** + * Whether or not the theme supports theme.json. + * + * @since 5.8.0 + * @var bool + */ + protected static $theme_has_support = \null; + /** + * Container for data coming from the user. + * + * @since 5.9.0 + * @var WP_Theme_JSON + */ + protected static $user = \null; + /** + * Stores the ID of the custom post type + * that holds the user data. + * + * @since 5.9.0 + * @var int + */ + protected static $user_custom_post_type_id = \null; + /** + * Container to keep loaded i18n schema for `theme.json`. + * + * @since 5.8.0 As `$theme_json_i18n`. + * @since 5.9.0 Renamed from `$theme_json_i18n` to `$i18n_schema`. + * @var array + */ + protected static $i18n_schema = \null; + /** + * `theme.json` file cache. + * + * @since 6.1.0 + * @var array + */ + protected static $theme_json_file_cache = array(); + /** + * Processes a file that adheres to the theme.json schema + * and returns an array with its contents, or a void array if none found. + * + * @since 5.8.0 + * @since 6.1.0 Added caching. + * + * @param string $file_path Path to file. Empty if no file. + * @return array Contents that adhere to the theme.json schema. + */ + protected static function read_json_file($file_path) + { + } + /** + * Returns a data structure used in theme.json translation. + * + * @since 5.8.0 + * @deprecated 5.9.0 + * + * @return array An array of theme.json fields that are translatable and the keys that are translatable. + */ + public static function get_fields_to_translate() + { + } + /** + * Given a theme.json structure modifies it in place to update certain values + * by its translated strings according to the language set by the user. + * + * @since 5.8.0 + * + * @param array $theme_json The theme.json to translate. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + * @return array Returns the modified $theme_json_structure. + */ + protected static function translate($theme_json, $domain = 'default') + { + } + /** + * Returns core's origin config. + * + * @since 5.8.0 + * + * @return WP_Theme_JSON Entity that holds core data. + */ + public static function get_core_data() + { + } + /** + * Checks whether the registered blocks were already processed for this origin. + * + * @since 6.1.0 + * + * @param string $origin Data source for which to cache the blocks. + * Valid values are 'core', 'blocks', 'theme', and 'user'. + * @return bool True on success, false otherwise. + */ + protected static function has_same_registered_blocks($origin) + { + } + /** + * Returns the theme's data. + * + * Data from theme.json will be backfilled from existing + * theme supports, if any. Note that if the same data + * is present in theme.json and in theme supports, + * the theme.json takes precedence. + * + * @since 5.8.0 + * @since 5.9.0 Theme supports have been inlined and the `$theme_support_data` argument removed. + * @since 6.0.0 Added an `$options` parameter to allow the theme data to be returned without theme supports. + * + * @param array $deprecated Deprecated. Not used. + * @param array $options { + * Options arguments. + * + * @type bool $with_supports Whether to include theme supports in the data. Default true. + * } + * @return WP_Theme_JSON Entity that holds theme data. + * @phpstan-param array{ + * with_supports?: bool, + * } $options + */ + public static function get_theme_data($deprecated = array(), $options = array()) + { + } + /** + * Gets the styles for blocks from the block.json file. + * + * @since 6.1.0 + * + * @return WP_Theme_JSON + */ + public static function get_block_data() + { + } + /** + * Returns the custom post type that contains the user's origin config + * for the active theme or a void array if none are found. + * + * This can also create and return a new draft custom post type. + * + * @since 5.9.0 + * + * @param WP_Theme $theme The theme object. If empty, it + * defaults to the active theme. + * @param bool $create_post Optional. Whether a new custom post + * type should be created if none are + * found. Default false. + * @param array $post_status_filter Optional. Filter custom post type by + * post status. Default `array( 'publish' )`, + * so it only fetches published posts. + * @return array Custom Post Type for the user's origin config. + */ + public static function get_user_data_from_wp_global_styles($theme, $create_post = \false, $post_status_filter = array('publish')) + { + } + /** + * Returns the user's origin config. + * + * @since 5.9.0 + * + * @return WP_Theme_JSON Entity that holds styles for user data. + */ + public static function get_user_data() + { + } + /** + * Returns the data merged from multiple origins. + * + * There are three sources of data (origins) for a site: + * default, theme, and custom. The custom's has higher priority + * than the theme's, and the theme's higher than default's. + * + * Unlike the getters + * {@link https://developer.wordpress.org/reference/classes/wp_theme_json_resolver/get_core_data/ get_core_data}, + * {@link https://developer.wordpress.org/reference/classes/wp_theme_json_resolver/get_theme_data/ get_theme_data}, + * and {@link https://developer.wordpress.org/reference/classes/wp_theme_json_resolver/get_user_data/ get_user_data}, + * this method returns data after it has been merged with the previous origins. + * This means that if the same piece of data is declared in different origins + * (user, theme, and core), the last origin overrides the previous. + * + * For example, if the user has set a background color + * for the paragraph block, and the theme has done it as well, + * the user preference wins. + * + * @since 5.8.0 + * @since 5.9.0 Added user data, removed the `$settings` parameter, + * added the `$origin` parameter. + * @since 6.1.0 Added block data and generation of spacingSizes array. + * + * @param string $origin Optional. To what level should we merge data. + * Valid values are 'theme' or 'custom'. Default 'custom'. + * @return WP_Theme_JSON + */ + public static function get_merged_data($origin = 'custom') + { + } + /** + * Returns the ID of the custom post type + * that stores user data. + * + * @since 5.9.0 + * + * @return integer|null + */ + public static function get_user_global_styles_post_id() + { + } + /** + * Determines whether the active theme has a theme.json file. + * + * @since 5.8.0 + * @since 5.9.0 Added a check in the parent theme. + * + * @return bool + */ + public static function theme_has_support() + { + } + /** + * Builds the path to the given file and checks that it is readable. + * + * If it isn't, returns an empty string, otherwise returns the whole file path. + * + * @since 5.8.0 + * @since 5.9.0 Adapted to work with child themes, added the `$template` argument. + * + * @param string $file_name Name of the file. + * @param bool $template Optional. Use template theme directory. Default false. + * @return string The whole file path or empty if the file doesn't exist. + */ + protected static function get_file_path_from_theme($file_name, $template = \false) + { + } + /** + * Cleans the cached data so it can be recalculated. + * + * @since 5.8.0 + * @since 5.9.0 Added the `$user`, `$user_custom_post_type_id`, + * and `$i18n_schema` variables to reset. + * @since 6.1.0 Added the `$blocks` and `$blocks_cache` variables + * to reset. + */ + public static function clean_cached_data() + { + } + /** + * Returns the style variations defined by the theme. + * + * @since 6.0.0 + * + * @return array + */ + public static function get_style_variations() + { + } + } + /** + * WP_Theme_JSON_Schema class + * + * @package WordPress + * @subpackage Theme + * @since 5.9.0 + */ + /** + * Class that migrates a given theme.json structure to the latest schema. + * + * This class is for internal core usage and is not supposed to be used by extenders (plugins and/or themes). + * This is a low-level API that may need to do breaking changes. Please, + * use get_global_settings, get_global_styles, and get_global_stylesheet instead. + * + * @since 5.9.0 + * @access private + */ + #[\AllowDynamicProperties] + class WP_Theme_JSON_Schema + { + /** + * Maps old properties to their new location within the schema's settings. + * This will be applied at both the defaults and individual block levels. + */ + const V1_TO_V2_RENAMED_PATHS = array('border.customRadius' => 'border.radius', 'spacing.customMargin' => 'spacing.margin', 'spacing.customPadding' => 'spacing.padding', 'typography.customLineHeight' => 'typography.lineHeight'); + /** + * Function that migrates a given theme.json structure to the last version. + * + * @since 5.9.0 + * + * @param array $theme_json The structure to migrate. + * + * @return array The structure in the last version. + */ + public static function migrate($theme_json) + { + } + } + /** + * WP_Theme_JSON class + * + * @package WordPress + * @subpackage Theme + * @since 5.8.0 + */ + /** + * Class that encapsulates the processing of structures that adhere to the theme.json spec. + * + * This class is for internal core usage and is not supposed to be used by extenders (plugins and/or themes). + * This is a low-level API that may need to do breaking changes. Please, + * use get_global_settings, get_global_styles, and get_global_stylesheet instead. + * + * @access private + */ + #[\AllowDynamicProperties] + class WP_Theme_JSON + { + /** + * Container of data in theme.json format. + * + * @since 5.8.0 + * @var array + */ + protected $theme_json = \null; + /** + * Holds block metadata extracted from block.json + * to be shared among all instances so we don't + * process it twice. + * + * @since 5.8.0 + * @since 6.1.0 Initialize as an empty array. + * @var array + */ + protected static $blocks_metadata = array(); + /** + * The CSS selector for the top-level styles. + * + * @since 5.8.0 + * @var string + */ + const ROOT_BLOCK_SELECTOR = 'body'; + /** + * The sources of data this object can represent. + * + * @since 5.8.0 + * @since 6.1.0 Added 'blocks'. + * @var string[] + */ + const VALID_ORIGINS = array('default', 'blocks', 'theme', 'custom'); + /** + * Presets are a set of values that serve + * to bootstrap some styles: colors, font sizes, etc. + * + * They are a unkeyed array of values such as: + * + * ```php + * array( + * array( + * 'slug' => 'unique-name-within-the-set', + * 'name' => 'Name for the UI', + * <value_key> => 'value' + * ), + * ) + * ``` + * + * This contains the necessary metadata to process them: + * + * - path => Where to find the preset within the settings section. + * - prevent_override => Disables override of default presets by theme presets. + * The relationship between whether to override the defaults + * and whether the defaults are enabled is inverse: + * - If defaults are enabled => theme presets should not be overriden + * - If defaults are disabled => theme presets should be overriden + * For example, a theme sets defaultPalette to false, + * making the default palette hidden from the user. + * In that case, we want all the theme presets to be present, + * so they should override the defaults by setting this false. + * - use_default_names => whether to use the default names + * - value_key => the key that represents the value + * - value_func => optionally, instead of value_key, a function to generate + * the value that takes a preset as an argument + * (either value_key or value_func should be present) + * - css_vars => template string to use in generating the CSS Custom Property. + * Example output: "--wp--preset--duotone--blue: <value>" will generate as many CSS Custom Properties as presets defined + * substituting the $slug for the slug's value for each preset value. + * - classes => array containing a structure with the classes to + * generate for the presets, where for each array item + * the key is the class name and the value the property name. + * The "$slug" substring will be replaced by the slug of each preset. + * For example: + * 'classes' => array( + * '.has-$slug-color' => 'color', + * '.has-$slug-background-color' => 'background-color', + * '.has-$slug-border-color' => 'border-color', + * ) + * - properties => array of CSS properties to be used by kses to + * validate the content of each preset + * by means of the remove_insecure_properties method. + * + * @since 5.8.0 + * @since 5.9.0 Added the `color.duotone` and `typography.fontFamilies` presets, + * `use_default_names` preset key, and simplified the metadata structure. + * @since 6.0.0 Replaced `override` with `prevent_override` and updated the + * `prevent_overried` value for `color.duotone` to use `color.defaultDuotone`. + * @var array + */ + const PRESETS_METADATA = array(array('path' => array('color', 'palette'), 'prevent_override' => array('color', 'defaultPalette'), 'use_default_names' => \false, 'value_key' => 'color', 'css_vars' => '--wp--preset--color--$slug', 'classes' => array('.has-$slug-color' => 'color', '.has-$slug-background-color' => 'background-color', '.has-$slug-border-color' => 'border-color'), 'properties' => array('color', 'background-color', 'border-color')), array('path' => array('color', 'gradients'), 'prevent_override' => array('color', 'defaultGradients'), 'use_default_names' => \false, 'value_key' => 'gradient', 'css_vars' => '--wp--preset--gradient--$slug', 'classes' => array('.has-$slug-gradient-background' => 'background'), 'properties' => array('background')), array('path' => array('color', 'duotone'), 'prevent_override' => array('color', 'defaultDuotone'), 'use_default_names' => \false, 'value_func' => 'wp_get_duotone_filter_property', 'css_vars' => '--wp--preset--duotone--$slug', 'classes' => array(), 'properties' => array('filter')), array('path' => array('typography', 'fontSizes'), 'prevent_override' => \false, 'use_default_names' => \true, 'value_func' => 'wp_get_typography_font_size_value', 'css_vars' => '--wp--preset--font-size--$slug', 'classes' => array('.has-$slug-font-size' => 'font-size'), 'properties' => array('font-size')), array('path' => array('typography', 'fontFamilies'), 'prevent_override' => \false, 'use_default_names' => \false, 'value_key' => 'fontFamily', 'css_vars' => '--wp--preset--font-family--$slug', 'classes' => array('.has-$slug-font-family' => 'font-family'), 'properties' => array('font-family')), array('path' => array('spacing', 'spacingSizes'), 'prevent_override' => \false, 'use_default_names' => \true, 'value_key' => 'size', 'css_vars' => '--wp--preset--spacing--$slug', 'classes' => array(), 'properties' => array('padding', 'margin'))); + /** + * Metadata for style properties. + * + * Each element is a direct mapping from the CSS property name to the + * path to the value in theme.json & block attributes. + * + * @since 5.8.0 + * @since 5.9.0 Added the `border-*`, `font-family`, `font-style`, `font-weight`, + * `letter-spacing`, `margin-*`, `padding-*`, `--wp--style--block-gap`, + * `text-decoration`, `text-transform`, and `filter` properties, + * simplified the metadata structure. + * @since 6.1.0 Added the `border-*-color`, `border-*-width`, `border-*-style`, + * `--wp--style--root--padding-*`, and `box-shadow` properties, + * removed the `--wp--style--block-gap` property. + * @var array + */ + const PROPERTIES_METADATA = array('background' => array('color', 'gradient'), 'background-color' => array('color', 'background'), 'border-radius' => array('border', 'radius'), 'border-top-left-radius' => array('border', 'radius', 'topLeft'), 'border-top-right-radius' => array('border', 'radius', 'topRight'), 'border-bottom-left-radius' => array('border', 'radius', 'bottomLeft'), 'border-bottom-right-radius' => array('border', 'radius', 'bottomRight'), 'border-color' => array('border', 'color'), 'border-width' => array('border', 'width'), 'border-style' => array('border', 'style'), 'border-top-color' => array('border', 'top', 'color'), 'border-top-width' => array('border', 'top', 'width'), 'border-top-style' => array('border', 'top', 'style'), 'border-right-color' => array('border', 'right', 'color'), 'border-right-width' => array('border', 'right', 'width'), 'border-right-style' => array('border', 'right', 'style'), 'border-bottom-color' => array('border', 'bottom', 'color'), 'border-bottom-width' => array('border', 'bottom', 'width'), 'border-bottom-style' => array('border', 'bottom', 'style'), 'border-left-color' => array('border', 'left', 'color'), 'border-left-width' => array('border', 'left', 'width'), 'border-left-style' => array('border', 'left', 'style'), 'color' => array('color', 'text'), 'font-family' => array('typography', 'fontFamily'), 'font-size' => array('typography', 'fontSize'), 'font-style' => array('typography', 'fontStyle'), 'font-weight' => array('typography', 'fontWeight'), 'letter-spacing' => array('typography', 'letterSpacing'), 'line-height' => array('typography', 'lineHeight'), 'margin' => array('spacing', 'margin'), 'margin-top' => array('spacing', 'margin', 'top'), 'margin-right' => array('spacing', 'margin', 'right'), 'margin-bottom' => array('spacing', 'margin', 'bottom'), 'margin-left' => array('spacing', 'margin', 'left'), 'padding' => array('spacing', 'padding'), 'padding-top' => array('spacing', 'padding', 'top'), 'padding-right' => array('spacing', 'padding', 'right'), 'padding-bottom' => array('spacing', 'padding', 'bottom'), 'padding-left' => array('spacing', 'padding', 'left'), '--wp--style--root--padding' => array('spacing', 'padding'), '--wp--style--root--padding-top' => array('spacing', 'padding', 'top'), '--wp--style--root--padding-right' => array('spacing', 'padding', 'right'), '--wp--style--root--padding-bottom' => array('spacing', 'padding', 'bottom'), '--wp--style--root--padding-left' => array('spacing', 'padding', 'left'), 'text-decoration' => array('typography', 'textDecoration'), 'text-transform' => array('typography', 'textTransform'), 'filter' => array('filter', 'duotone'), 'box-shadow' => array('shadow')); + /** + * Protected style properties. + * + * These style properties are only rendered if a setting enables it + * via a value other than `null`. + * + * Each element maps the style property to the corresponding theme.json + * setting key. + * + * @since 5.9.0 + */ + const PROTECTED_PROPERTIES = array('spacing.blockGap' => array('spacing', 'blockGap')); + /** + * The top-level keys a theme.json can have. + * + * @since 5.8.0 As `ALLOWED_TOP_LEVEL_KEYS`. + * @since 5.9.0 Renamed from `ALLOWED_TOP_LEVEL_KEYS` to `VALID_TOP_LEVEL_KEYS`, + * added the `customTemplates` and `templateParts` values. + * @var string[] + */ + const VALID_TOP_LEVEL_KEYS = array('customTemplates', 'patterns', 'settings', 'styles', 'templateParts', 'version', 'title'); + /** + * The valid properties under the settings key. + * + * @since 5.8.0 As `ALLOWED_SETTINGS`. + * @since 5.9.0 Renamed from `ALLOWED_SETTINGS` to `VALID_SETTINGS`, + * added new properties for `border`, `color`, `spacing`, + * and `typography`, and renamed others according to the new schema. + * @since 6.0.0 Added `color.defaultDuotone`. + * @since 6.1.0 Added `layout.definitions` and `useRootPaddingAwareAlignments`. + * @var array + */ + const VALID_SETTINGS = array('appearanceTools' => \null, 'useRootPaddingAwareAlignments' => \null, 'border' => array('color' => \null, 'radius' => \null, 'style' => \null, 'width' => \null), 'color' => array('background' => \null, 'custom' => \null, 'customDuotone' => \null, 'customGradient' => \null, 'defaultDuotone' => \null, 'defaultGradients' => \null, 'defaultPalette' => \null, 'duotone' => \null, 'gradients' => \null, 'link' => \null, 'palette' => \null, 'text' => \null), 'custom' => \null, 'layout' => array('contentSize' => \null, 'definitions' => \null, 'wideSize' => \null), 'spacing' => array('customSpacingSize' => \null, 'spacingSizes' => \null, 'spacingScale' => \null, 'blockGap' => \null, 'margin' => \null, 'padding' => \null, 'units' => \null), 'typography' => array('fluid' => \null, 'customFontSize' => \null, 'dropCap' => \null, 'fontFamilies' => \null, 'fontSizes' => \null, 'fontStyle' => \null, 'fontWeight' => \null, 'letterSpacing' => \null, 'lineHeight' => \null, 'textDecoration' => \null, 'textTransform' => \null)); + /** + * The valid properties under the styles key. + * + * @since 5.8.0 As `ALLOWED_STYLES`. + * @since 5.9.0 Renamed from `ALLOWED_STYLES` to `VALID_STYLES`, + * added new properties for `border`, `filter`, `spacing`, + * and `typography`. + * @since 6.1.0 Added new side properties for `border`, + * added new property `shadow`, + * updated `blockGap` to be allowed at any level. + * @var array + */ + const VALID_STYLES = array('border' => array('color' => \null, 'radius' => \null, 'style' => \null, 'width' => \null, 'top' => \null, 'right' => \null, 'bottom' => \null, 'left' => \null), 'color' => array('background' => \null, 'gradient' => \null, 'text' => \null), 'filter' => array('duotone' => \null), 'shadow' => \null, 'spacing' => array('margin' => \null, 'padding' => \null, 'blockGap' => \null), 'typography' => array('fontFamily' => \null, 'fontSize' => \null, 'fontStyle' => \null, 'fontWeight' => \null, 'letterSpacing' => \null, 'lineHeight' => \null, 'textDecoration' => \null, 'textTransform' => \null)); + /** + * Defines which pseudo selectors are enabled for which elements. + * + * The order of the selectors should be: visited, hover, focus, active. + * This is to ensure that 'visited' has the lowest specificity + * and the other selectors can always overwrite it. + * + * See https://core.trac.wordpress.org/ticket/56928. + * Note: this will affect both top-level and block-level elements. + * + * @since 6.1.0 + */ + const VALID_ELEMENT_PSEUDO_SELECTORS = array('link' => array(':visited', ':hover', ':focus', ':active'), 'button' => array(':visited', ':hover', ':focus', ':active')); + /** + * The valid elements that can be found under styles. + * + * @since 5.8.0 + * @since 6.1.0 Added `heading`, `button`. and `caption` elements. + * @var string[] + */ + const ELEMENTS = array( + 'link' => 'a:where(:not(.wp-element-button))', + // The `where` is needed to lower the specificity. + 'heading' => 'h1, h2, h3, h4, h5, h6', + 'h1' => 'h1', + 'h2' => 'h2', + 'h3' => 'h3', + 'h4' => 'h4', + 'h5' => 'h5', + 'h6' => 'h6', + // We have the .wp-block-button__link class so that this will target older buttons that have been serialized. + 'button' => '.wp-element-button, .wp-block-button__link', + // The block classes are necessary to target older content that won't use the new class names. + 'caption' => '.wp-element-caption, .wp-block-audio figcaption, .wp-block-embed figcaption, .wp-block-gallery figcaption, .wp-block-image figcaption, .wp-block-table figcaption, .wp-block-video figcaption', + 'cite' => 'cite', + ); + const __EXPERIMENTAL_ELEMENT_CLASS_NAMES = array('button' => 'wp-element-button', 'caption' => 'wp-element-caption'); + /** + * List of block support features that can have their related styles + * generated under their own feature level selector rather than the block's. + * + * @since 6.1.0 + * @var string[] + */ + const BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS = array('__experimentalBorder' => 'border', 'color' => 'color', 'spacing' => 'spacing', 'typography' => 'typography'); + /** + * Returns a class name by an element name. + * + * @since 6.1.0 + * + * @param string $element The name of the element. + * @return string The name of the class. + */ + public static function get_element_class_name($element) + { + } + /** + * Options that settings.appearanceTools enables. + * + * @since 6.0.0 + * @var array + */ + const APPEARANCE_TOOLS_OPT_INS = array(array('border', 'color'), array('border', 'radius'), array('border', 'style'), array('border', 'width'), array('color', 'link'), array('spacing', 'blockGap'), array('spacing', 'margin'), array('spacing', 'padding'), array('typography', 'lineHeight')); + /** + * The latest version of the schema in use. + * + * @since 5.8.0 + * @since 5.9.0 Changed value from 1 to 2. + * @var int + */ + const LATEST_SCHEMA = 2; + /** + * Constructor. + * + * @since 5.8.0 + * + * @param array $theme_json A structure that follows the theme.json schema. + * @param string $origin Optional. What source of data this object represents. + * One of 'default', 'theme', or 'custom'. Default 'theme'. + */ + public function __construct($theme_json = array(), $origin = 'theme') + { + } + /** + * Enables some opt-in settings if theme declared support. + * + * @since 5.9.0 + * + * @param array $theme_json A theme.json structure to modify. + * @return array The modified theme.json structure. + */ + protected static function maybe_opt_in_into_settings($theme_json) + { + } + /** + * Enables some settings. + * + * @since 5.9.0 + * + * @param array $context The context to which the settings belong. + */ + protected static function do_opt_in_into_settings(&$context) + { + } + /** + * Sanitizes the input according to the schemas. + * + * @since 5.8.0 + * @since 5.9.0 Added the `$valid_block_names` and `$valid_element_name` parameters. + * + * @param array $input Structure to sanitize. + * @param array $valid_block_names List of valid block names. + * @param array $valid_element_names List of valid element names. + * @return array The sanitized output. + */ + protected static function sanitize($input, $valid_block_names, $valid_element_names) + { + } + /** + * Appends a sub-selector to an existing one. + * + * Given the compounded $selector "h1, h2, h3" + * and the $to_append selector ".some-class" the result will be + * "h1.some-class, h2.some-class, h3.some-class". + * + * @since 5.8.0 + * @since 6.1.0 Added append position. + * + * @param string $selector Original selector. + * @param string $to_append Selector to append. + * @param string $position A position sub-selector should be appended. Default 'right'. + * @return string The new selector. + */ + protected static function append_to_selector($selector, $to_append, $position = 'right') + { + } + /** + * Returns the metadata for each block. + * + * Example: + * + * { + * 'core/paragraph': { + * 'selector': 'p', + * 'elements': { + * 'link' => 'link selector', + * 'etc' => 'element selector' + * } + * }, + * 'core/heading': { + * 'selector': 'h1', + * 'elements': {} + * }, + * 'core/image': { + * 'selector': '.wp-block-image', + * 'duotone': 'img', + * 'elements': {} + * } + * } + * + * @since 5.8.0 + * @since 5.9.0 Added `duotone` key with CSS selector. + * @since 6.1.0 Added `features` key with block support feature level selectors. + * + * @return array Block metadata. + */ + protected static function get_blocks_metadata() + { + } + /** + * Given a tree, removes the keys that are not present in the schema. + * + * It is recursive and modifies the input in-place. + * + * @since 5.8.0 + * + * @param array $tree Input to process. + * @param array $schema Schema to adhere to. + * @return array The modified $tree. + */ + protected static function remove_keys_not_in_schema($tree, $schema) + { + } + /** + * Returns the existing settings for each block. + * + * Example: + * + * { + * 'root': { + * 'color': { + * 'custom': true + * } + * }, + * 'core/paragraph': { + * 'spacing': { + * 'customPadding': true + * } + * } + * } + * + * @since 5.8.0 + * + * @return array Settings per block. + */ + public function get_settings() + { + } + /** + * Returns the stylesheet that results of processing + * the theme.json structure this object represents. + * + * @since 5.8.0 + * @since 5.9.0 Removed the `$type` parameter`, added the `$types` and `$origins` parameters. + * + * @param array $types Types of styles to load. Will load all by default. It accepts: + * - `variables`: only the CSS Custom Properties for presets & custom ones. + * - `styles`: only the styles section in theme.json. + * - `presets`: only the classes for the presets. + * @param array $origins A list of origins to include. By default it includes VALID_ORIGINS. + * @return string The resulting stylesheet. + */ + public function get_stylesheet($types = array('variables', 'styles', 'presets'), $origins = \null) + { + } + /** + * Returns the page templates of the active theme. + * + * @since 5.9.0 + * + * @return array + */ + public function get_custom_templates() + { + } + /** + * Returns the template part data of active theme. + * + * @since 5.9.0 + * + * @return array + */ + public function get_template_parts() + { + } + /** + * Converts each style section into a list of rulesets + * containing the block styles to be appended to the stylesheet. + * + * See glossary at https://developer.mozilla.org/en-US/docs/Web/CSS/Syntax + * + * For each section this creates a new ruleset such as: + * + * block-selector { + * style-property-one: value; + * } + * + * @since 5.8.0 As `get_block_styles()`. + * @since 5.9.0 Renamed from `get_block_styles()` to `get_block_classes()` + * and no longer returns preset classes. + * Removed the `$setting_nodes` parameter. + * @since 6.1.0 Moved most internal logic to `get_styles_for_block()`. + * + * @param array $style_nodes Nodes with styles. + * @return string The new stylesheet. + */ + protected function get_block_classes($style_nodes) + { + } + /** + * Gets the CSS layout rules for a particular block from theme.json layout definitions. + * + * @since 6.1.0 + * + * @param array $block_metadata Metadata about the block to get styles for. + * @return string Layout styles for the block. + */ + protected function get_layout_styles($block_metadata) + { + } + /** + * Creates new rulesets as classes for each preset value such as: + * + * .has-value-color { + * color: value; + * } + * + * .has-value-background-color { + * background-color: value; + * } + * + * .has-value-font-size { + * font-size: value; + * } + * + * .has-value-gradient-background { + * background: value; + * } + * + * p.has-value-gradient-background { + * background: value; + * } + * + * @since 5.9.0 + * + * @param array $setting_nodes Nodes with settings. + * @param array $origins List of origins to process presets from. + * @return string The new stylesheet. + */ + protected function get_preset_classes($setting_nodes, $origins) + { + } + /** + * Converts each styles section into a list of rulesets + * to be appended to the stylesheet. + * These rulesets contain all the css variables (custom variables and preset variables). + * + * See glossary at https://developer.mozilla.org/en-US/docs/Web/CSS/Syntax + * + * For each section this creates a new ruleset such as: + * + * block-selector { + * --wp--preset--category--slug: value; + * --wp--custom--variable: value; + * } + * + * @since 5.8.0 + * @since 5.9.0 Added the `$origins` parameter. + * + * @param array $nodes Nodes with settings. + * @param array $origins List of origins to process. + * @return string The new stylesheet. + */ + protected function get_css_variables($nodes, $origins) + { + } + /** + * Given a selector and a declaration list, + * creates the corresponding ruleset. + * + * @since 5.8.0 + * + * @param string $selector CSS selector. + * @param array $declarations List of declarations. + * @return string The resulting CSS ruleset. + */ + protected static function to_ruleset($selector, $declarations) + { + } + /** + * Given a settings array, returns the generated rulesets + * for the preset classes. + * + * @since 5.8.0 + * @since 5.9.0 Added the `$origins` parameter. + * + * @param array $settings Settings to process. + * @param string $selector Selector wrapping the classes. + * @param array $origins List of origins to process. + * @return string The result of processing the presets. + */ + protected static function compute_preset_classes($settings, $selector, $origins) + { + } + /** + * Function that scopes a selector with another one. This works a bit like + * SCSS nesting except the `&` operator isn't supported. + * + * <code> + * $scope = '.a, .b .c'; + * $selector = '> .x, .y'; + * $merged = scope_selector( $scope, $selector ); + * // $merged is '.a > .x, .a .y, .b .c > .x, .b .c .y' + * </code> + * + * @since 5.9.0 + * + * @param string $scope Selector to scope to. + * @param string $selector Original selector. + * @return string Scoped selector. + */ + protected static function scope_selector($scope, $selector) + { + } + /** + * Gets preset values keyed by slugs based on settings and metadata. + * + * <code> + * $settings = array( + * 'typography' => array( + * 'fontFamilies' => array( + * array( + * 'slug' => 'sansSerif', + * 'fontFamily' => '"Helvetica Neue", sans-serif', + * ), + * array( + * 'slug' => 'serif', + * 'colors' => 'Georgia, serif', + * ) + * ), + * ), + * ); + * $meta = array( + * 'path' => array( 'typography', 'fontFamilies' ), + * 'value_key' => 'fontFamily', + * ); + * $values_by_slug = get_settings_values_by_slug(); + * // $values_by_slug === array( + * // 'sans-serif' => '"Helvetica Neue", sans-serif', + * // 'serif' => 'Georgia, serif', + * // ); + * </code> + * + * @since 5.9.0 + * + * @param array $settings Settings to process. + * @param array $preset_metadata One of the PRESETS_METADATA values. + * @param array $origins List of origins to process. + * @return array Array of presets where each key is a slug and each value is the preset value. + */ + protected static function get_settings_values_by_slug($settings, $preset_metadata, $origins) + { + } + /** + * Similar to get_settings_values_by_slug, but doesn't compute the value. + * + * @since 5.9.0 + * + * @param array $settings Settings to process. + * @param array $preset_metadata One of the PRESETS_METADATA values. + * @param array $origins List of origins to process. + * @return array Array of presets where the key and value are both the slug. + */ + protected static function get_settings_slugs($settings, $preset_metadata, $origins = \null) + { + } + /** + * Transforms a slug into a CSS Custom Property. + * + * @since 5.9.0 + * + * @param string $input String to replace. + * @param string $slug The slug value to use to generate the custom property. + * @return string The CSS Custom Property. Something along the lines of `--wp--preset--color--black`. + */ + protected static function replace_slug_in_string($input, $slug) + { + } + /** + * Given the block settings, extracts the CSS Custom Properties + * for the presets and adds them to the $declarations array + * following the format: + * + * array( + * 'name' => 'property_name', + * 'value' => 'property_value, + * ) + * + * @since 5.8.0 + * @since 5.9.0 Added the `$origins` parameter. + * + * @param array $settings Settings to process. + * @param array $origins List of origins to process. + * @return array The modified $declarations. + */ + protected static function compute_preset_vars($settings, $origins) + { + } + /** + * Given an array of settings, extracts the CSS Custom Properties + * for the custom values and adds them to the $declarations + * array following the format: + * + * array( + * 'name' => 'property_name', + * 'value' => 'property_value, + * ) + * + * @since 5.8.0 + * + * @param array $settings Settings to process. + * @return array The modified $declarations. + */ + protected static function compute_theme_vars($settings) + { + } + /** + * Given a tree, it creates a flattened one + * by merging the keys and binding the leaf values + * to the new keys. + * + * It also transforms camelCase names into kebab-case + * and substitutes '/' by '-'. + * + * This is thought to be useful to generate + * CSS Custom Properties from a tree, + * although there's nothing in the implementation + * of this function that requires that format. + * + * For example, assuming the given prefix is '--wp' + * and the token is '--', for this input tree: + * + * { + * 'some/property': 'value', + * 'nestedProperty': { + * 'sub-property': 'value' + * } + * } + * + * it'll return this output: + * + * { + * '--wp--some-property': 'value', + * '--wp--nested-property--sub-property': 'value' + * } + * + * @since 5.8.0 + * + * @param array $tree Input tree to process. + * @param string $prefix Optional. Prefix to prepend to each variable. Default empty string. + * @param string $token Optional. Token to use between levels. Default '--'. + * @return array The flattened tree. + */ + protected static function flatten_tree($tree, $prefix = '', $token = '--') + { + } + /** + * Given a styles array, it extracts the style properties + * and adds them to the $declarations array following the format: + * + * array( + * 'name' => 'property_name', + * 'value' => 'property_value, + * ) + * + * @since 5.8.0 + * @since 5.9.0 Added the `$settings` and `$properties` parameters. + * @since 6.1.0 Added `$theme_json`, `$selector`, and `$use_root_padding` parameters. + * + * @param array $styles Styles to process. + * @param array $settings Theme settings. + * @param array $properties Properties metadata. + * @param array $theme_json Theme JSON array. + * @param string $selector The style block selector. + * @param boolean $use_root_padding Whether to add custom properties at root level. + * @return array Returns the modified $declarations. + */ + protected static function compute_style_properties($styles, $settings = array(), $properties = \null, $theme_json = \null, $selector = \null, $use_root_padding = \null) + { + } + /** + * Returns the style property for the given path. + * + * It also converts CSS Custom Property stored as + * "var:preset|color|secondary" to the form + * "--wp--preset--color--secondary". + * + * It also converts references to a path to the value + * stored at that location, e.g. + * { "ref": "style.color.background" } => "#fff". + * + * @since 5.8.0 + * @since 5.9.0 Added support for values of array type, which are returned as is. + * @since 6.1.0 Added the `$theme_json` parameter. + * + * @param array $styles Styles subtree. + * @param array $path Which property to process. + * @param array $theme_json Theme JSON array. + * @return string|array Style property value. + */ + protected static function get_property_value($styles, $path, $theme_json = \null) + { + } + /** + * Builds metadata for the setting nodes, which returns in the form of: + * + * [ + * [ + * 'path' => ['path', 'to', 'some', 'node' ], + * 'selector' => 'CSS selector for some node' + * ], + * [ + * 'path' => [ 'path', 'to', 'other', 'node' ], + * 'selector' => 'CSS selector for other node' + * ], + * ] + * + * @since 5.8.0 + * + * @param array $theme_json The tree to extract setting nodes from. + * @param array $selectors List of selectors per block. + * @return array An array of setting nodes metadata. + */ + protected static function get_setting_nodes($theme_json, $selectors = array()) + { + } + /** + * Builds metadata for the style nodes, which returns in the form of: + * + * [ + * [ + * 'path' => [ 'path', 'to', 'some', 'node' ], + * 'selector' => 'CSS selector for some node', + * 'duotone' => 'CSS selector for duotone for some node' + * ], + * [ + * 'path' => ['path', 'to', 'other', 'node' ], + * 'selector' => 'CSS selector for other node', + * 'duotone' => null + * ], + * ] + * + * @since 5.8.0 + * + * @param array $theme_json The tree to extract style nodes from. + * @param array $selectors List of selectors per block. + * @return array An array of style nodes metadata. + */ + protected static function get_style_nodes($theme_json, $selectors = array()) + { + } + /** + * A public helper to get the block nodes from a theme.json file. + * + * @since 6.1.0 + * + * @return array The block nodes in theme.json. + */ + public function get_styles_block_nodes() + { + } + /** + * Gets the CSS rules for a particular block from theme.json. + * + * @since 6.1.0 + * + * @param array $block_metadata Metadata about the block to get styles for. + * + * @return string Styles for the block. + */ + public function get_styles_for_block($block_metadata) + { + } + /** + * Outputs the CSS for layout rules on the root. + * + * @since 6.1.0 + * + * @param string $selector The root node selector. + * @param array $block_metadata The metadata for the root block. + * @return string The additional root rules CSS. + */ + public function get_root_layout_rules($selector, $block_metadata) + { + } + /** + * For metadata values that can either be booleans or paths to booleans, gets the value. + * + * ```php + * $data = array( + * 'color' => array( + * 'defaultPalette' => true + * ) + * ); + * + * static::get_metadata_boolean( $data, false ); + * // => false + * + * static::get_metadata_boolean( $data, array( 'color', 'defaultPalette' ) ); + * // => true + * ``` + * + * @since 6.0.0 + * + * @param array $data The data to inspect. + * @param bool|array $path Boolean or path to a boolean. + * @param bool $default Default value if the referenced path is missing. + * Default false. + * @return bool Value of boolean metadata. + */ + protected static function get_metadata_boolean($data, $path, $default = \false) + { + } + /** + * Merges new incoming data. + * + * @since 5.8.0 + * @since 5.9.0 Duotone preset also has origins. + * + * @param WP_Theme_JSON $incoming Data to merge. + */ + public function merge($incoming) + { + } + /** + * Converts all filter (duotone) presets into SVGs. + * + * @since 5.9.1 + * + * @param array $origins List of origins to process. + * @return string SVG filters. + */ + public function get_svg_filters($origins) + { + } + /** + * Determines whether a presets should be overridden or not. + * + * @since 5.9.0 + * @deprecated 6.0.0 Use {@see 'get_metadata_boolean'} instead. + * + * @param array $theme_json The theme.json like structure to inspect. + * @param array $path Path to inspect. + * @param bool|array $override Data to compute whether to override the preset. + * @return boolean + */ + protected static function should_override_preset($theme_json, $path, $override) + { + } + /** + * Returns the default slugs for all the presets in an associative array + * whose keys are the preset paths and the leafs is the list of slugs. + * + * For example: + * + * array( + * 'color' => array( + * 'palette' => array( 'slug-1', 'slug-2' ), + * 'gradients' => array( 'slug-3', 'slug-4' ), + * ), + * ) + * + * @since 5.9.0 + * + * @param array $data A theme.json like structure. + * @param array $node_path The path to inspect. It's 'settings' by default. + * @return array + */ + protected static function get_default_slugs($data, $node_path) + { + } + /** + * Gets a `default`'s preset name by a provided slug. + * + * @since 5.9.0 + * + * @param string $slug The slug we want to find a match from default presets. + * @param array $base_path The path to inspect. It's 'settings' by default. + * @return string|null + */ + protected function get_name_from_defaults($slug, $base_path) + { + } + /** + * Removes the preset values whose slug is equal to any of given slugs. + * + * @since 5.9.0 + * + * @param array $node The node with the presets to validate. + * @param array $slugs The slugs that should not be overridden. + * @return array The new node. + */ + protected static function filter_slugs($node, $slugs) + { + } + /** + * Removes insecure data from theme.json. + * + * @since 5.9.0 + * + * @param array $theme_json Structure to sanitize. + * @return array Sanitized structure. + */ + public static function remove_insecure_properties($theme_json) + { + } + /** + * Processes a setting node and returns the same node + * without the insecure settings. + * + * @since 5.9.0 + * + * @param array $input Node to process. + * @return array + */ + protected static function remove_insecure_settings($input) + { + } + /** + * Processes a style node and returns the same node + * without the insecure styles. + * + * @since 5.9.0 + * + * @param array $input Node to process. + * @return array + */ + protected static function remove_insecure_styles($input) + { + } + /** + * Checks that a declaration provided by the user is safe. + * + * @since 5.9.0 + * + * @param string $property_name Property name in a CSS declaration, i.e. the `color` in `color: red`. + * @param string $property_value Value in a CSS declaration, i.e. the `red` in `color: red`. + * @return bool + */ + protected static function is_safe_css_declaration($property_name, $property_value) + { + } + /** + * Returns the raw data. + * + * @since 5.8.0 + * + * @return array Raw data. + */ + public function get_raw_data() + { + } + /** + * Transforms the given editor settings according the + * add_theme_support format to the theme.json format. + * + * @since 5.8.0 + * + * @param array $settings Existing editor settings. + * @return array Config that adheres to the theme.json schema. + */ + public static function get_from_editor_settings($settings) + { + } + /** + * Returns the current theme's wanted patterns(slugs) to be + * registered from Pattern Directory. + * + * @since 6.0.0 + * + * @return string[] + */ + public function get_patterns() + { + } + /** + * Returns a valid theme.json as provided by a theme. + * + * Unlike get_raw_data() this returns the presets flattened, as provided by a theme. + * This also uses appearanceTools instead of their opt-ins if all of them are true. + * + * @since 6.0.0 + * + * @return array + */ + public function get_data() + { + } + /** + * Sets the spacingSizes array based on the spacingScale values from theme.json. + * + * @since 6.1.0 + * + * @return null|void + */ + public function set_spacing_sizes() + { + } + } + /** + * WP_Theme Class + * + * @package WordPress + * @subpackage Theme + * @since 3.4.0 + */ + #[\AllowDynamicProperties] + final class WP_Theme implements \ArrayAccess + { + /** + * Whether the theme has been marked as updateable. + * + * @since 4.4.0 + * @var bool + * + * @see WP_MS_Themes_List_Table + */ + public $update = \false; + /** + * Constructor for WP_Theme. + * + * @since 3.4.0 + * + * @global array $wp_theme_directories + * + * @param string $theme_dir Directory of the theme within the theme_root. + * @param string $theme_root Theme root. + * @param WP_Theme|null $_child If this theme is a parent theme, the child may be passed for validation purposes. + */ + public function __construct($theme_dir, $theme_root, $_child = \null) + { + } + /** + * When converting the object to a string, the theme name is returned. + * + * @since 3.4.0 + * + * @return string Theme name, ready for display (translated) + */ + public function __toString() + { + } + /** + * __isset() magic method for properties formerly returned by current_theme_info() + * + * @since 3.4.0 + * + * @param string $offset Property to check if set. + * @return bool Whether the given property is set. + */ + public function __isset($offset) + { + } + /** + * __get() magic method for properties formerly returned by current_theme_info() + * + * @since 3.4.0 + * + * @param string $offset Property to get. + * @return mixed Property value. + */ + public function __get($offset) + { + } + /** + * Method to implement ArrayAccess for keys formerly returned by get_themes() + * + * @since 3.4.0 + * + * @param mixed $offset + * @param mixed $value + */ + #[\ReturnTypeWillChange] + public function offsetSet($offset, $value) + { + } + /** + * Method to implement ArrayAccess for keys formerly returned by get_themes() + * + * @since 3.4.0 + * + * @param mixed $offset + */ + #[\ReturnTypeWillChange] + public function offsetUnset($offset) + { + } + /** + * Method to implement ArrayAccess for keys formerly returned by get_themes() + * + * @since 3.4.0 + * + * @param mixed $offset + * @return bool + */ + #[\ReturnTypeWillChange] + public function offsetExists($offset) + { + } + /** + * Method to implement ArrayAccess for keys formerly returned by get_themes(). + * + * Author, Author Name, Author URI, and Description did not previously return + * translated data. We are doing so now as it is safe to do. However, as + * Name and Title could have been used as the key for get_themes(), both remain + * untranslated for back compatibility. This means that ['Name'] is not ideal, + * and care should be taken to use `$theme::display( 'Name' )` to get a properly + * translated header. + * + * @since 3.4.0 + * + * @param mixed $offset + * @return mixed + */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + } + /** + * Returns errors property. + * + * @since 3.4.0 + * + * @return WP_Error|false WP_Error if there are errors, or false. + */ + public function errors() + { + } + /** + * Determines whether the theme exists. + * + * A theme with errors exists. A theme with the error of 'theme_not_found', + * meaning that the theme's directory was not found, does not exist. + * + * @since 3.4.0 + * + * @return bool Whether the theme exists. + */ + public function exists() + { + } + /** + * Returns reference to the parent theme. + * + * @since 3.4.0 + * + * @return WP_Theme|false Parent theme, or false if the active theme is not a child theme. + */ + public function parent() + { + } + /** + * Clears the cache for the theme. + * + * @since 3.4.0 + */ + public function cache_delete() + { + } + /** + * Gets a raw, unformatted theme header. + * + * The header is sanitized, but is not translated, and is not marked up for display. + * To get a theme header for display, use the display() method. + * + * Use the get_template() method, not the 'Template' header, for finding the template. + * The 'Template' header is only good for what was written in the style.css, while + * get_template() takes into account where WordPress actually located the theme and + * whether it is actually valid. + * + * @since 3.4.0 + * + * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags. + * @return string|array|false String or array (for Tags header) on success, false on failure. + */ + public function get($header) + { + } + /** + * Gets a theme header, formatted and translated for display. + * + * @since 3.4.0 + * + * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags. + * @param bool $markup Optional. Whether to mark up the header. Defaults to true. + * @param bool $translate Optional. Whether to translate the header. Defaults to true. + * @return string|array|false Processed header. An array for Tags if `$markup` is false, string otherwise. + * False on failure. + */ + public function display($header, $markup = \true, $translate = \true) + { + } + /** + * Returns the directory name of the theme's "stylesheet" files, inside the theme root. + * + * In the case of a child theme, this is directory name of the child theme. + * Otherwise, get_stylesheet() is the same as get_template(). + * + * @since 3.4.0 + * + * @return string Stylesheet + */ + public function get_stylesheet() + { + } + /** + * Returns the directory name of the theme's "template" files, inside the theme root. + * + * In the case of a child theme, this is the directory name of the parent theme. + * Otherwise, the get_template() is the same as get_stylesheet(). + * + * @since 3.4.0 + * + * @return string Template + */ + public function get_template() + { + } + /** + * Returns the absolute path to the directory of a theme's "stylesheet" files. + * + * In the case of a child theme, this is the absolute path to the directory + * of the child theme's files. + * + * @since 3.4.0 + * + * @return string Absolute path of the stylesheet directory. + */ + public function get_stylesheet_directory() + { + } + /** + * Returns the absolute path to the directory of a theme's "template" files. + * + * In the case of a child theme, this is the absolute path to the directory + * of the parent theme's files. + * + * @since 3.4.0 + * + * @return string Absolute path of the template directory. + */ + public function get_template_directory() + { + } + /** + * Returns the URL to the directory of a theme's "stylesheet" files. + * + * In the case of a child theme, this is the URL to the directory of the + * child theme's files. + * + * @since 3.4.0 + * + * @return string URL to the stylesheet directory. + */ + public function get_stylesheet_directory_uri() + { + } + /** + * Returns the URL to the directory of a theme's "template" files. + * + * In the case of a child theme, this is the URL to the directory of the + * parent theme's files. + * + * @since 3.4.0 + * + * @return string URL to the template directory. + */ + public function get_template_directory_uri() + { + } + /** + * Returns the absolute path to the directory of the theme root. + * + * This is typically the absolute path to wp-content/themes. + * + * @since 3.4.0 + * + * @return string Theme root. + */ + public function get_theme_root() + { + } + /** + * Returns the URL to the directory of the theme root. + * + * This is typically the absolute URL to wp-content/themes. This forms the basis + * for all other URLs returned by WP_Theme, so we pass it to the public function + * get_theme_root_uri() and allow it to run the {@see 'theme_root_uri'} filter. + * + * @since 3.4.0 + * + * @return string Theme root URI. + */ + public function get_theme_root_uri() + { + } + /** + * Returns the main screenshot file for the theme. + * + * The main screenshot is called screenshot.png. gif and jpg extensions are also allowed. + * + * Screenshots for a theme must be in the stylesheet directory. (In the case of child + * themes, parent theme screenshots are not inherited.) + * + * @since 3.4.0 + * + * @param string $uri Type of URL to return, either 'relative' or an absolute URI. Defaults to absolute URI. + * @return string|false Screenshot file. False if the theme does not have a screenshot. + */ + public function get_screenshot($uri = 'uri') + { + } + /** + * Returns files in the theme's directory. + * + * @since 3.4.0 + * + * @param string[]|string $type Optional. Array of extensions to find, string of a single extension, + * or null for all extensions. Default null. + * @param int $depth Optional. How deep to search for files. Defaults to a flat scan (0 depth). + * -1 depth is infinite. + * @param bool $search_parent Optional. Whether to return parent files. Default false. + * @return string[] Array of files, keyed by the path to the file relative to the theme's directory, with the values + * being absolute paths. + */ + public function get_files($type = \null, $depth = 0, $search_parent = \false) + { + } + /** + * Returns the theme's post templates. + * + * @since 4.7.0 + * @since 5.8.0 Include block templates. + * + * @return array[] Array of page template arrays, keyed by post type and filename, + * with the value of the translated header name. + */ + public function get_post_templates() + { + } + /** + * Returns the theme's post templates for a given post type. + * + * @since 3.4.0 + * @since 4.7.0 Added the `$post_type` parameter. + * + * @param WP_Post|null $post Optional. The post being edited, provided for context. + * @param string $post_type Optional. Post type to get the templates for. Default 'page'. + * If a post is provided, its post type is used. + * @return string[] Array of template header names keyed by the template file name. + */ + public function get_page_templates($post = \null, $post_type = 'page') + { + } + /** + * Loads the theme's textdomain. + * + * Translation files are not inherited from the parent theme. TODO: If this fails for the + * child theme, it should probably try to load the parent theme's translations. + * + * @since 3.4.0 + * + * @return bool True if the textdomain was successfully loaded or has already been loaded. + * False if no textdomain was specified in the file headers, or if the domain could not be loaded. + */ + public function load_textdomain() + { + } + /** + * Determines whether the theme is allowed (multisite only). + * + * @since 3.4.0 + * + * @param string $check Optional. Whether to check only the 'network'-wide settings, the 'site' + * settings, or 'both'. Defaults to 'both'. + * @param int $blog_id Optional. Ignored if only network-wide settings are checked. Defaults to current site. + * @return bool Whether the theme is allowed for the network. Returns true in single-site. + */ + public function is_allowed($check = 'both', $blog_id = \null) + { + } + /** + * Returns whether this theme is a block-based theme or not. + * + * @since 5.9.0 + * + * @return bool + */ + public function is_block_theme() + { + } + /** + * Retrieves the path of a file in the theme. + * + * Searches in the stylesheet directory before the template directory so themes + * which inherit from a parent theme can just override one file. + * + * @since 5.9.0 + * + * @param string $file Optional. File to search for in the stylesheet directory. + * @return string The path of the file. + */ + public function get_file_path($file = '') + { + } + /** + * Determines the latest WordPress default theme that is installed. + * + * This hits the filesystem. + * + * @since 4.4.0 + * + * @return WP_Theme|false Object, or false if no theme is installed, which would be bad. + */ + public static function get_core_default_theme() + { + } + /** + * Returns array of stylesheet names of themes allowed on the site or network. + * + * @since 3.4.0 + * + * @param int $blog_id Optional. ID of the site. Defaults to the current site. + * @return string[] Array of stylesheet names. + */ + public static function get_allowed($blog_id = \null) + { + } + /** + * Returns array of stylesheet names of themes allowed on the network. + * + * @since 3.4.0 + * + * @return string[] Array of stylesheet names. + */ + public static function get_allowed_on_network() + { + } + /** + * Returns array of stylesheet names of themes allowed on the site. + * + * @since 3.4.0 + * + * @param int $blog_id Optional. ID of the site. Defaults to the current site. + * @return string[] Array of stylesheet names. + */ + public static function get_allowed_on_site($blog_id = \null) + { + } + /** + * Enables a theme for all sites on the current network. + * + * @since 4.6.0 + * + * @param string|string[] $stylesheets Stylesheet name or array of stylesheet names. + */ + public static function network_enable_theme($stylesheets) + { + } + /** + * Disables a theme for all sites on the current network. + * + * @since 4.6.0 + * + * @param string|string[] $stylesheets Stylesheet name or array of stylesheet names. + */ + public static function network_disable_theme($stylesheets) + { + } + /** + * Sorts themes by name. + * + * @since 3.4.0 + * + * @param WP_Theme[] $themes Array of theme objects to sort (passed by reference). + */ + public static function sort_by_name(&$themes) + { + } + } + /** + * Session API: WP_User_Meta_Session_Tokens class + * + * @package WordPress + * @subpackage Session + * @since 4.7.0 + */ + /** + * Meta-based user sessions token manager. + * + * @since 4.0.0 + * + * @see WP_Session_Tokens + */ + class WP_User_Meta_Session_Tokens extends \WP_Session_Tokens + { + /** + * Retrieves all sessions of the user. + * + * @since 4.0.0 + * + * @return array Sessions of the user. + */ + protected function get_sessions() + { + } + /** + * Converts an expiration to an array of session information. + * + * @param mixed $session Session or expiration. + * @return array Session. + */ + protected function prepare_session($session) + { + } + /** + * Retrieves a session based on its verifier (token hash). + * + * @since 4.0.0 + * + * @param string $verifier Verifier for the session to retrieve. + * @return array|null The session, or null if it does not exist + */ + protected function get_session($verifier) + { + } + /** + * Updates a session based on its verifier (token hash). + * + * @since 4.0.0 + * + * @param string $verifier Verifier for the session to update. + * @param array $session Optional. Session. Omitting this argument destroys the session. + */ + protected function update_session($verifier, $session = \null) + { + } + /** + * Updates the user's sessions in the usermeta table. + * + * @since 4.0.0 + * + * @param array $sessions Sessions. + */ + protected function update_sessions($sessions) + { + } + /** + * Destroys all sessions for this user, except the single session with the given verifier. + * + * @since 4.0.0 + * + * @param string $verifier Verifier of the session to keep. + */ + protected function destroy_other_sessions($verifier) + { + } + /** + * Destroys all session tokens for the user. + * + * @since 4.0.0 + */ + protected function destroy_all_sessions() + { + } + /** + * Destroys all sessions for all users. + * + * @since 4.0.0 + */ + public static function drop_sessions() + { + } + } + /** + * User API: WP_User_Query class + * + * @package WordPress + * @subpackage Users + * @since 4.4.0 + */ + /** + * Core class used for querying users. + * + * @since 3.1.0 + * + * @see WP_User_Query::prepare_query() for information on accepted arguments. + */ + #[\AllowDynamicProperties] + class WP_User_Query + { + /** + * Query vars, after parsing + * + * @since 3.5.0 + * @var array + */ + public $query_vars = array(); + /** + * Metadata query container. + * + * @since 4.2.0 + * @var WP_Meta_Query + */ + public $meta_query = \false; + /** + * The SQL query used to fetch matching users. + * + * @since 4.4.0 + * @var string + */ + public $request; + // SQL clauses. + public $query_fields; + public $query_from; + public $query_where; + public $query_orderby; + public $query_limit; + /** + * PHP5 constructor. + * + * @since 3.1.0 + * + * @param null|string|array $query Optional. The query variables. + */ + public function __construct($query = \null) + { + } + /** + * Fills in missing query variables with default values. + * + * @since 4.4.0 + * + * @param array $args Query vars, as passed to `WP_User_Query`. + * @return array Complete query variables with undefined ones filled in with defaults. + */ + public static function fill_query_vars($args) + { + } + /** + * Prepares the query variables. + * + * @since 3.1.0 + * @since 4.1.0 Added the ability to order by the `include` value. + * @since 4.2.0 Added 'meta_value_num' support for `$orderby` parameter. Added multi-dimensional array syntax + * for `$orderby` parameter. + * @since 4.3.0 Added 'has_published_posts' parameter. + * @since 4.4.0 Added 'paged', 'role__in', and 'role__not_in' parameters. The 'role' parameter was updated to + * permit an array or comma-separated list of values. The 'number' parameter was updated to support + * querying for all users with using -1. + * @since 4.7.0 Added 'nicename', 'nicename__in', 'nicename__not_in', 'login', 'login__in', + * and 'login__not_in' parameters. + * @since 5.1.0 Introduced the 'meta_compare_key' parameter. + * @since 5.3.0 Introduced the 'meta_type_key' parameter. + * @since 5.9.0 Added 'capability', 'capability__in', and 'capability__not_in' parameters. + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global WP_Roles $wp_roles WordPress role management object. + * + * @param string|array $query { + * Optional. Array or string of Query parameters. + * + * @type int $blog_id The site ID. Default is the current site. + * @type string|string[] $role An array or a comma-separated list of role names that users must match + * to be included in results. Note that this is an inclusive list: users + * must match *each* role. Default empty. + * @type string[] $role__in An array of role names. Matched users must have at least one of these + * roles. Default empty array. + * @type string[] $role__not_in An array of role names to exclude. Users matching one or more of these + * roles will not be included in results. Default empty array. + * @type string|string[] $meta_key Meta key or keys to filter by. + * @type string|string[] $meta_value Meta value or values to filter by. + * @type string $meta_compare MySQL operator used for comparing the meta value. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_compare_key MySQL operator used for comparing the meta key. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_type MySQL data type that the meta_value column will be CAST to for comparisons. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type string $meta_type_key MySQL data type that the meta_key column will be CAST to for comparisons. + * See WP_Meta_Query::__construct() for accepted values and default value. + * @type array $meta_query An associative array of WP_Meta_Query arguments. + * See WP_Meta_Query::__construct() for accepted values. + * @type string|string[] $capability An array or a comma-separated list of capability names that users must match + * to be included in results. Note that this is an inclusive list: users + * must match *each* capability. + * Does NOT work for capabilities not in the database or filtered via {@see 'map_meta_cap'}. + * Default empty. + * @type string[] $capability__in An array of capability names. Matched users must have at least one of these + * capabilities. + * Does NOT work for capabilities not in the database or filtered via {@see 'map_meta_cap'}. + * Default empty array. + * @type string[] $capability__not_in An array of capability names to exclude. Users matching one or more of these + * capabilities will not be included in results. + * Does NOT work for capabilities not in the database or filtered via {@see 'map_meta_cap'}. + * Default empty array. + * @type int[] $include An array of user IDs to include. Default empty array. + * @type int[] $exclude An array of user IDs to exclude. Default empty array. + * @type string $search Search keyword. Searches for possible string matches on columns. + * When `$search_columns` is left empty, it tries to determine which + * column to search in based on search string. Default empty. + * @type string[] $search_columns Array of column names to be searched. Accepts 'ID', 'user_login', + * 'user_email', 'user_url', 'user_nicename', 'display_name'. + * Default empty array. + * @type string|array $orderby Field(s) to sort the retrieved users by. May be a single value, + * an array of values, or a multi-dimensional array with fields as + * keys and orders ('ASC' or 'DESC') as values. Accepted values are: + * - 'ID' + * - 'display_name' (or 'name') + * - 'include' + * - 'user_login' (or 'login') + * - 'login__in' + * - 'user_nicename' (or 'nicename'), + * - 'nicename__in' + * - 'user_email (or 'email') + * - 'user_url' (or 'url'), + * - 'user_registered' (or 'registered') + * - 'post_count' + * - 'meta_value', + * - 'meta_value_num' + * - The value of `$meta_key` + * - An array key of `$meta_query` + * To use 'meta_value' or 'meta_value_num', `$meta_key` + * must be also be defined. Default 'user_login'. + * @type string $order Designates ascending or descending order of users. Order values + * passed as part of an `$orderby` array take precedence over this + * parameter. Accepts 'ASC', 'DESC'. Default 'ASC'. + * @type int $offset Number of users to offset in retrieved results. Can be used in + * conjunction with pagination. Default 0. + * @type int $number Number of users to limit the query for. Can be used in + * conjunction with pagination. Value -1 (all) is supported, but + * should be used with caution on larger sites. + * Default -1 (all users). + * @type int $paged When used with number, defines the page of results to return. + * Default 1. + * @type bool $count_total Whether to count the total number of users found. If pagination + * is not needed, setting this to false can improve performance. + * Default true. + * @type string|string[] $fields Which fields to return. Single or all fields (string), or array + * of fields. Accepts: + * - 'ID' + * - 'display_name' + * - 'user_login' + * - 'user_nicename' + * - 'user_email' + * - 'user_url' + * - 'user_registered' + * - 'user_pass' + * - 'user_activation_key' + * - 'user_status' + * - 'spam' (only available on multisite installs) + * - 'deleted' (only available on multisite installs) + * - 'all' for all fields and loads user meta. + * - 'all_with_meta' Deprecated. Use 'all'. + * Default 'all'. + * @type string $who Type of users to query. Accepts 'authors'. + * Default empty (all users). + * @type bool|string[] $has_published_posts Pass an array of post types to filter results to users who have + * published posts in those post types. `true` is an alias for all + * public post types. + * @type string $nicename The user nicename. Default empty. + * @type string[] $nicename__in An array of nicenames to include. Users matching one of these + * nicenames will be included in results. Default empty array. + * @type string[] $nicename__not_in An array of nicenames to exclude. Users matching one of these + * nicenames will not be included in results. Default empty array. + * @type string $login The user login. Default empty. + * @type string[] $login__in An array of logins to include. Users matching one of these + * logins will be included in results. Default empty array. + * @type string[] $login__not_in An array of logins to exclude. Users matching one of these + * logins will not be included in results. Default empty array. + * } + * @phpstan-param array{ + * blog_id?: int, + * role?: string|string[], + * role__in?: string[], + * role__not_in?: string[], + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * capability?: string|string[], + * capability__in?: string[], + * capability__not_in?: string[], + * include?: int[], + * exclude?: int[], + * search?: string, + * search_columns?: string[], + * orderby?: string|array, + * order?: string, + * offset?: int, + * number?: int, + * paged?: int, + * count_total?: bool, + * fields?: string|string[], + * who?: string, + * has_published_posts?: bool|string[], + * nicename?: string, + * nicename__in?: string[], + * nicename__not_in?: string[], + * login?: string, + * login__in?: string[], + * login__not_in?: string[], + * } $query + */ + public function prepare_query($query = array()) + { + } + /** + * Executes the query, with the current variables. + * + * @since 3.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + public function query() + { + } + /** + * Retrieves query variable. + * + * @since 3.5.0 + * + * @param string $query_var Query variable key. + * @return mixed + */ + public function get($query_var) + { + } + /** + * Sets query variable. + * + * @since 3.5.0 + * + * @param string $query_var Query variable key. + * @param mixed $value Query variable value. + */ + public function set($query_var, $value) + { + } + /** + * Used internally to generate an SQL string for searching across multiple columns. + * + * @since 3.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $search Search string. + * @param string[] $columns Array of columns to search. + * @param bool $wild Whether to allow wildcard searches. Default is false for Network Admin, true for single site. + * Single site allows leading and trailing wildcards, Network Admin only trailing. + * @return string + */ + protected function get_search_sql($search, $columns, $wild = \false) + { + } + /** + * Returns the list of users. + * + * @since 3.1.0 + * + * @return array Array of results. + */ + public function get_results() + { + } + /** + * Returns the total number of users for the current query. + * + * @since 3.1.0 + * + * @return int Number of total users. + */ + public function get_total() + { + } + /** + * Parses and sanitizes 'orderby' keys passed to the user query. + * + * @since 4.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $orderby Alias for the field to order by. + * @return string Value to used in the ORDER clause, if `$orderby` is valid. + */ + protected function parse_orderby($orderby) + { + } + /** + * Parses an 'order' query variable and casts it to ASC or DESC as necessary. + * + * @since 4.2.0 + * + * @param string $order The 'order' query variable. + * @return string The sanitized 'order' query variable. + */ + protected function parse_order($order) + { + } + /** + * Makes private properties readable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to get. + * @return mixed Property. + */ + public function __get($name) + { + } + /** + * Makes private properties settable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to check if set. + * @param mixed $value Property value. + * @return mixed Newly-set property. + */ + public function __set($name, $value) + { + } + /** + * Makes private properties checkable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to check if set. + * @return bool Whether the property is set. + */ + public function __isset($name) + { + } + /** + * Makes private properties un-settable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Property to unset. + */ + public function __unset($name) + { + } + /** + * Makes private/protected methods readable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Method to call. + * @param array $arguments Arguments to pass when calling. + * @return mixed Return value of the callback, false otherwise. + */ + public function __call($name, $arguments) + { + } + } + /** + * WP_User_Request class. + * + * Represents user request data loaded from a WP_Post object. + * + * @since 4.9.6 + */ + #[\AllowDynamicProperties] + final class WP_User_Request + { + /** + * Request ID. + * + * @since 4.9.6 + * @var int + */ + public $ID = 0; + /** + * User ID. + * + * @since 4.9.6 + * @var int + */ + public $user_id = 0; + /** + * User email. + * + * @since 4.9.6 + * @var string + */ + public $email = ''; + /** + * Action name. + * + * @since 4.9.6 + * @var string + */ + public $action_name = ''; + /** + * Current status. + * + * @since 4.9.6 + * @var string + */ + public $status = ''; + /** + * Timestamp this request was created. + * + * @since 4.9.6 + * @var int|null + */ + public $created_timestamp = \null; + /** + * Timestamp this request was last modified. + * + * @since 4.9.6 + * @var int|null + */ + public $modified_timestamp = \null; + /** + * Timestamp this request was confirmed. + * + * @since 4.9.6 + * @var int|null + */ + public $confirmed_timestamp = \null; + /** + * Timestamp this request was completed. + * + * @since 4.9.6 + * @var int|null + */ + public $completed_timestamp = \null; + /** + * Misc data assigned to this request. + * + * @since 4.9.6 + * @var array + */ + public $request_data = array(); + /** + * Key used to confirm this request. + * + * @since 4.9.6 + * @var string + */ + public $confirm_key = ''; + /** + * Constructor. + * + * @since 4.9.6 + * + * @param WP_Post|object $post Post object. + */ + public function __construct($post) + { + } + } + /** + * User API: WP_User class + * + * @package WordPress + * @subpackage Users + * @since 4.4.0 + */ + /** + * Core class used to implement the WP_User object. + * + * @since 2.0.0 + * + * @property string $nickname + * @property string $description + * @property string $user_description + * @property string $first_name + * @property string $user_firstname + * @property string $last_name + * @property string $user_lastname + * @property string $user_login + * @property string $user_pass + * @property string $user_nicename + * @property string $user_email + * @property string $user_url + * @property string $user_registered + * @property string $user_activation_key + * @property string $user_status + * @property int $user_level + * @property string $display_name + * @property string $spam + * @property string $deleted + * @property string $locale + * @property string $rich_editing + * @property string $syntax_highlighting + * @property string $use_ssl + */ + #[\AllowDynamicProperties] + class WP_User + { + /** + * User data container. + * + * @since 2.0.0 + * @var stdClass + */ + public $data; + /** + * The user's ID. + * + * @since 2.1.0 + * @var int + */ + public $ID = 0; + /** + * Capabilities that the individual user has been granted outside of those inherited from their role. + * + * @since 2.0.0 + * @var bool[] Array of key/value pairs where keys represent a capability name + * and boolean values represent whether the user has that capability. + */ + public $caps = array(); + /** + * User metadata option name. + * + * @since 2.0.0 + * @var string + */ + public $cap_key; + /** + * The roles the user is part of. + * + * @since 2.0.0 + * @var string[] + */ + public $roles = array(); + /** + * All capabilities the user has, including individual and role based. + * + * @since 2.0.0 + * @var bool[] Array of key/value pairs where keys represent a capability name + * and boolean values represent whether the user has that capability. + */ + public $allcaps = array(); + /** + * The filter context applied to user data fields. + * + * @since 2.9.0 + * @var string + */ + public $filter = \null; + /** + * Constructor. + * + * Retrieves the userdata and passes it to WP_User::init(). + * + * @since 2.0.0 + * + * @param int|string|stdClass|WP_User $id User's ID, a WP_User object, or a user object from the DB. + * @param string $name Optional. User's username + * @param int $site_id Optional Site ID, defaults to current site. + */ + public function __construct($id = 0, $name = '', $site_id = '') + { + } + /** + * Sets up object properties, including capabilities. + * + * @since 3.3.0 + * + * @param object $data User DB row object. + * @param int $site_id Optional. The site ID to initialize for. + */ + public function init($data, $site_id = '') + { + } + /** + * Returns only the main user fields. + * + * @since 3.3.0 + * @since 4.4.0 Added 'ID' as an alias of 'id' for the `$field` parameter. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $field The field to query against: 'id', 'ID', 'slug', 'email' or 'login'. + * @param string|int $value The field value. + * @return object|false Raw user object. + */ + public static function get_data_by($field, $value) + { + } + /** + * Magic method for checking the existence of a certain custom field. + * + * @since 3.3.0 + * + * @param string $key User meta key to check if set. + * @return bool Whether the given user meta key is set. + */ + public function __isset($key) + { + } + /** + * Magic method for accessing custom fields. + * + * @since 3.3.0 + * + * @param string $key User meta key to retrieve. + * @return mixed Value of the given user meta key (if set). If `$key` is 'id', the user ID. + */ + public function __get($key) + { + } + /** + * Magic method for setting custom user fields. + * + * This method does not update custom fields in the database. It only stores + * the value on the WP_User instance. + * + * @since 3.3.0 + * + * @param string $key User meta key. + * @param mixed $value User meta value. + */ + public function __set($key, $value) + { + } + /** + * Magic method for unsetting a certain custom field. + * + * @since 4.4.0 + * + * @param string $key User meta key to unset. + */ + public function __unset($key) + { + } + /** + * Determines whether the user exists in the database. + * + * @since 3.4.0 + * + * @return bool True if user exists in the database, false if not. + */ + public function exists() + { + } + /** + * Retrieves the value of a property or meta key. + * + * Retrieves from the users and usermeta table. + * + * @since 3.3.0 + * + * @param string $key Property + * @return mixed + */ + public function get($key) + { + } + /** + * Determines whether a property or meta key is set. + * + * Consults the users and usermeta tables. + * + * @since 3.3.0 + * + * @param string $key Property. + * @return bool + */ + public function has_prop($key) + { + } + /** + * Returns an array representation. + * + * @since 3.5.0 + * + * @return array Array representation. + */ + public function to_array() + { + } + /** + * Makes private/protected methods readable for backward compatibility. + * + * @since 4.3.0 + * + * @param string $name Method to call. + * @param array $arguments Arguments to pass when calling. + * @return mixed|false Return value of the callback, false otherwise. + */ + public function __call($name, $arguments) + { + } + /** + * Sets up capability object properties. + * + * Will set the value for the 'cap_key' property to current database table + * prefix, followed by 'capabilities'. Will then check to see if the + * property matching the 'cap_key' exists and is an array. If so, it will be + * used. + * + * @since 2.1.0 + * @deprecated 4.9.0 Use WP_User::for_site() + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $cap_key Optional capability key + */ + protected function _init_caps($cap_key = '') + { + } + /** + * Retrieves all of the capabilities of the user's roles, and merges them with + * individual user capabilities. + * + * All of the capabilities of the user's roles are merged with the user's individual + * capabilities. This means that the user can be denied specific capabilities that + * their role might have, but the user is specifically denied. + * + * @since 2.0.0 + * + * @return bool[] Array of key/value pairs where keys represent a capability name + * and boolean values represent whether the user has that capability. + */ + public function get_role_caps() + { + } + /** + * Adds role to user. + * + * Updates the user's meta data option with capabilities and roles. + * + * @since 2.0.0 + * + * @param string $role Role name. + */ + public function add_role($role) + { + } + /** + * Removes role from user. + * + * @since 2.0.0 + * + * @param string $role Role name. + */ + public function remove_role($role) + { + } + /** + * Sets the role of the user. + * + * This will remove the previous roles of the user and assign the user the + * new one. You can set the role to an empty string and it will remove all + * of the roles from the user. + * + * @since 2.0.0 + * + * @param string $role Role name. + */ + public function set_role($role) + { + } + /** + * Chooses the maximum level the user has. + * + * Will compare the level from the $item parameter against the $max + * parameter. If the item is incorrect, then just the $max parameter value + * will be returned. + * + * Used to get the max level based on the capabilities the user has. This + * is also based on roles, so if the user is assigned the Administrator role + * then the capability 'level_10' will exist and the user will get that + * value. + * + * @since 2.0.0 + * + * @param int $max Max level of user. + * @param string $item Level capability name. + * @return int Max Level. + */ + public function level_reduction($max, $item) + { + } + /** + * Updates the maximum user level for the user. + * + * Updates the 'user_level' user metadata (includes prefix that is the + * database table prefix) with the maximum user level. Gets the value from + * the all of the capabilities that the user has. + * + * @since 2.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + public function update_user_level_from_caps() + { + } + /** + * Adds capability and grant or deny access to capability. + * + * @since 2.0.0 + * + * @param string $cap Capability name. + * @param bool $grant Whether to grant capability to user. + */ + public function add_cap($cap, $grant = \true) + { + } + /** + * Removes capability from user. + * + * @since 2.0.0 + * + * @param string $cap Capability name. + */ + public function remove_cap($cap) + { + } + /** + * Removes all of the capabilities of the user. + * + * @since 2.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + public function remove_all_caps() + { + } + /** + * Returns whether the user has the specified capability. + * + * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta + * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to + * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`. + * + * Example usage: + * + * $user->has_cap( 'edit_posts' ); + * $user->has_cap( 'edit_post', $post->ID ); + * $user->has_cap( 'edit_post_meta', $post->ID, $meta_key ); + * + * While checking against a role in place of a capability is supported in part, this practice is discouraged as it + * may produce unreliable results. + * + * @since 2.0.0 + * @since 5.3.0 Formalized the existing and already documented `...$args` parameter + * by adding it to the function signature. + * + * @see map_meta_cap() + * + * @param string $cap Capability name. + * @param mixed ...$args Optional further parameters, typically starting with an object ID. + * @return bool Whether the user has the given capability, or, if an object ID is passed, whether the user has + * the given capability for that object. + */ + public function has_cap($cap, ...$args) + { + } + /** + * Converts numeric level to level capability name. + * + * Prepends 'level_' to level number. + * + * @since 2.0.0 + * + * @param int $level Level number, 1 to 10. + * @return string + */ + public function translate_level_to_cap($level) + { + } + /** + * Sets the site to operate on. Defaults to the current site. + * + * @since 3.0.0 + * @deprecated 4.9.0 Use WP_User::for_site() + * + * @param int $blog_id Optional. Site ID, defaults to current site. + */ + public function for_blog($blog_id = '') + { + } + /** + * Sets the site to operate on. Defaults to the current site. + * + * @since 4.9.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $site_id Site ID to initialize user capabilities for. Default is the current site. + */ + public function for_site($site_id = '') + { + } + /** + * Gets the ID of the site for which the user's capabilities are currently initialized. + * + * @since 4.9.0 + * + * @return int Site ID. + */ + public function get_site_id() + { + } + } + /** + * Widget API: WP_Widget_Factory class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Singleton that registers and instantiates WP_Widget classes. + * + * @since 2.8.0 + * @since 4.4.0 Moved to its own file from wp-includes/widgets.php + */ + #[\AllowDynamicProperties] + class WP_Widget_Factory + { + /** + * Widgets array. + * + * @since 2.8.0 + * @var array + */ + public $widgets = array(); + /** + * PHP5 constructor. + * + * @since 4.3.0 + */ + public function __construct() + { + } + /** + * PHP4 constructor. + * + * @since 2.8.0 + * @deprecated 4.3.0 Use __construct() instead. + * + * @see WP_Widget_Factory::__construct() + */ + public function WP_Widget_Factory() + { + } + /** + * Registers a widget subclass. + * + * @since 2.8.0 + * @since 4.6.0 Updated the `$widget` parameter to also accept a WP_Widget instance object + * instead of simply a `WP_Widget` subclass name. + * + * @param string|WP_Widget $widget Either the name of a `WP_Widget` subclass or an instance of a `WP_Widget` subclass. + */ + public function register($widget) + { + } + /** + * Un-registers a widget subclass. + * + * @since 2.8.0 + * @since 4.6.0 Updated the `$widget` parameter to also accept a WP_Widget instance object + * instead of simply a `WP_Widget` subclass name. + * + * @param string|WP_Widget $widget Either the name of a `WP_Widget` subclass or an instance of a `WP_Widget` subclass. + */ + public function unregister($widget) + { + } + /** + * Serves as a utility method for adding widgets to the registered widgets global. + * + * @since 2.8.0 + * + * @global array $wp_registered_widgets + */ + public function _register_widgets() + { + } + /** + * Returns the registered WP_Widget object for the given widget type. + * + * @since 5.8.0 + * + * @param string $id_base Widget type ID. + * @return WP_Widget|null + */ + public function get_widget_object($id_base) + { + } + /** + * Returns the registered key for the given widget type. + * + * @since 5.8.0 + * + * @param string $id_base Widget type ID. + * @return string + */ + public function get_widget_key($id_base) + { + } + } + /** + * Widget API: WP_Widget base class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Core base class extended to register widgets. + * + * This class must be extended for each widget, and WP_Widget::widget() must be overridden. + * + * If adding widget options, WP_Widget::update() and WP_Widget::form() should also be overridden. + * + * @since 2.8.0 + * @since 4.4.0 Moved to its own file from wp-includes/widgets.php + */ + #[\AllowDynamicProperties] + class WP_Widget + { + /** + * Root ID for all widgets of this type. + * + * @since 2.8.0 + * @var mixed|string + */ + public $id_base; + /** + * Name for this widget type. + * + * @since 2.8.0 + * @var string + */ + public $name; + /** + * Option name for this widget type. + * + * @since 2.8.0 + * @var string + */ + public $option_name; + /** + * Alt option name for this widget type. + * + * @since 2.8.0 + * @var string + */ + public $alt_option_name; + /** + * Option array passed to wp_register_sidebar_widget(). + * + * @since 2.8.0 + * @var array + */ + public $widget_options; + /** + * Option array passed to wp_register_widget_control(). + * + * @since 2.8.0 + * @var array + */ + public $control_options; + /** + * Unique ID number of the current instance. + * + * @since 2.8.0 + * @var bool|int + */ + public $number = \false; + /** + * Unique ID string of the current instance (id_base-number). + * + * @since 2.8.0 + * @var bool|string + */ + public $id = \false; + /** + * Whether the widget data has been updated. + * + * Set to true when the data is updated after a POST submit - ensures it does + * not happen twice. + * + * @since 2.8.0 + * @var bool + */ + public $updated = \false; + // + // Member functions that must be overridden by subclasses. + // + /** + * Echoes the widget content. + * + * Subclasses should override this function to generate their widget code. + * + * @since 2.8.0 + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance The settings for the particular instance of the widget. + */ + public function widget($args, $instance) + { + } + /** + * Updates a particular instance of a widget. + * + * This function should check that `$new_instance` is set correctly. The newly-calculated + * value of `$instance` should be returned. If false is returned, the instance won't be + * saved/updated. + * + * @since 2.8.0 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Settings to save or bool false to cancel saving. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Outputs the settings update form. + * + * @since 2.8.0 + * + * @param array $instance Current settings. + * @return string Default return is 'noform'. + */ + public function form($instance) + { + } + // Functions you'll need to call. + /** + * PHP5 constructor. + * + * @since 2.8.0 + * + * @param string $id_base Optional. Base ID for the widget, lowercase and unique. If left empty, + * a portion of the widget's PHP class name will be used. Has to be unique. + * @param string $name Name for the widget displayed on the configuration page. + * @param array $widget_options Optional. Widget options. See wp_register_sidebar_widget() for + * information on accepted arguments. Default empty array. + * @param array $control_options Optional. Widget control options. See wp_register_widget_control() for + * information on accepted arguments. Default empty array. + * @phpstan-param array{ + * classname?: string, + * description?: string, + * show_instance_in_rest?: bool, + * } $widget_options See wp_register_sidebar_widget() + * @phpstan-param array{ + * height?: int, + * width?: int, + * id_base?: int|string, + * } $control_options See wp_register_widget_control() + */ + public function __construct($id_base, $name, $widget_options = array(), $control_options = array()) + { + } + /** + * PHP4 constructor. + * + * @since 2.8.0 + * @deprecated 4.3.0 Use __construct() instead. + * + * @see WP_Widget::__construct() + * + * @param string $id_base Optional. Base ID for the widget, lowercase and unique. If left empty, + * a portion of the widget's PHP class name will be used. Has to be unique. + * @param string $name Name for the widget displayed on the configuration page. + * @param array $widget_options Optional. Widget options. See wp_register_sidebar_widget() for + * information on accepted arguments. Default empty array. + * @param array $control_options Optional. Widget control options. See wp_register_widget_control() for + * information on accepted arguments. Default empty array. + * @phpstan-param array{ + * classname?: string, + * description?: string, + * show_instance_in_rest?: bool, + * } $widget_options See wp_register_sidebar_widget() + * @phpstan-param array{ + * height?: int, + * width?: int, + * id_base?: int|string, + * } $control_options See wp_register_widget_control() + */ + public function WP_Widget($id_base, $name, $widget_options = array(), $control_options = array()) + { + } + /** + * Constructs name attributes for use in form() fields + * + * This function should be used in form() methods to create name attributes for fields + * to be saved by update() + * + * @since 2.8.0 + * @since 4.4.0 Array format field names are now accepted. + * + * @param string $field_name Field name. + * @return string Name attribute for `$field_name`. + */ + public function get_field_name($field_name) + { + } + /** + * Constructs id attributes for use in WP_Widget::form() fields. + * + * This function should be used in form() methods to create id attributes + * for fields to be saved by WP_Widget::update(). + * + * @since 2.8.0 + * @since 4.4.0 Array format field IDs are now accepted. + * + * @param string $field_name Field name. + * @return string ID attribute for `$field_name`. + */ + public function get_field_id($field_name) + { + } + /** + * Register all widget instances of this widget class. + * + * @since 2.8.0 + */ + public function _register() + { + } + /** + * Sets the internal order number for the widget instance. + * + * @since 2.8.0 + * + * @param int $number The unique order number of this widget instance compared to other + * instances of the same class. + */ + public function _set($number) + { + } + /** + * Retrieves the widget display callback. + * + * @since 2.8.0 + * + * @return callable Display callback. + */ + public function _get_display_callback() + { + } + /** + * Retrieves the widget update callback. + * + * @since 2.8.0 + * + * @return callable Update callback. + */ + public function _get_update_callback() + { + } + /** + * Retrieves the form callback. + * + * @since 2.8.0 + * + * @return callable Form callback. + */ + public function _get_form_callback() + { + } + /** + * Determines whether the current request is inside the Customizer preview. + * + * If true -- the current request is inside the Customizer preview, then + * the object cache gets suspended and widgets should check this to decide + * whether they should store anything persistently to the object cache, + * to transients, or anywhere else. + * + * @since 3.9.0 + * + * @global WP_Customize_Manager $wp_customize + * + * @return bool True if within the Customizer preview, false if not. + */ + public function is_preview() + { + } + /** + * Generates the actual widget content (Do NOT override). + * + * Finds the instance and calls WP_Widget::widget(). + * + * @since 2.8.0 + * + * @param array $args Display arguments. See WP_Widget::widget() for information + * on accepted arguments. + * @param int|array $widget_args { + * Optional. Internal order number of the widget instance, or array of multi-widget arguments. + * Default 1. + * + * @type int $number Number increment used for multiples of the same widget. + * } + * @phpstan-param int|array{ + * number?: int, + * } $widget_args + */ + public function display_callback($args, $widget_args = 1) + { + } + /** + * Handles changed settings (Do NOT override). + * + * @since 2.8.0 + * + * @global array $wp_registered_widgets + * + * @param int $deprecated Not used. + */ + public function update_callback($deprecated = 1) + { + } + /** + * Generates the widget control form (Do NOT override). + * + * @since 2.8.0 + * + * @param int|array $widget_args { + * Optional. Internal order number of the widget instance, or array of multi-widget arguments. + * Default 1. + * + * @type int $number Number increment used for multiples of the same widget. + * } + * @return string|null + * @phpstan-param int|array{ + * number?: int, + * } $widget_args + */ + public function form_callback($widget_args = 1) + { + } + /** + * Registers an instance of the widget class. + * + * @since 2.8.0 + * + * @param int $number Optional. The unique order number of this widget instance + * compared to other instances of the same class. Default -1. + */ + public function _register_one($number = -1) + { + } + /** + * Saves the settings for all instances of the widget class. + * + * @since 2.8.0 + * + * @param array $settings Multi-dimensional array of widget instance settings. + */ + public function save_settings($settings) + { + } + /** + * Retrieves the settings for all instances of the widget class. + * + * @since 2.8.0 + * + * @return array Multi-dimensional array of widget instance settings. + */ + public function get_settings() + { + } + } + /** + * XML-RPC protocol support for WordPress + * + * @package WordPress + * @subpackage Publishing + */ + /** + * WordPress XMLRPC server implementation. + * + * Implements compatibility for Blogger API, MetaWeblog API, MovableType, and + * pingback. Additional WordPress API for managing comments, pages, posts, + * options, etc. + * + * As of WordPress 3.5.0, XML-RPC is enabled by default. It can be disabled + * via the {@see 'xmlrpc_enabled'} filter found in wp_xmlrpc_server::set_is_enabled(). + * + * @since 1.5.0 + * + * @see IXR_Server + */ + #[\AllowDynamicProperties] + class wp_xmlrpc_server extends \IXR_Server + { + /** + * Methods. + * + * @var array + */ + public $methods; + /** + * Blog options. + * + * @var array + */ + public $blog_options; + /** + * IXR_Error instance. + * + * @var IXR_Error + */ + public $error; + /** + * Flags that the user authentication has failed in this instance of wp_xmlrpc_server. + * + * @var bool + */ + protected $auth_failed = \false; + /** + * Registers all of the XMLRPC methods that XMLRPC server understands. + * + * Sets up server and method property. Passes XMLRPC + * methods through the {@see 'xmlrpc_methods'} filter to allow plugins to extend + * or replace XML-RPC methods. + * + * @since 1.5.0 + */ + public function __construct() + { + } + /** + * Make private/protected methods readable for backward compatibility. + * + * @since 4.0.0 + * + * @param string $name Method to call. + * @param array $arguments Arguments to pass when calling. + * @return array|IXR_Error|false Return value of the callback, false otherwise. + */ + public function __call($name, $arguments) + { + } + /** + * Serves the XML-RPC request. + * + * @since 2.9.0 + */ + public function serve_request() + { + } + /** + * Test XMLRPC API by saying, "Hello!" to client. + * + * @since 1.5.0 + * + * @return string Hello string response. + */ + public function sayHello() + { + } + /** + * Test XMLRPC API by adding two numbers for client. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 A number to add. + * @type int $1 A second number to add. + * } + * @return int Sum of the two given numbers. + * @phpstan-param array{ + * 0: int, + * 1: int, + * } $args + */ + public function addTwoNumbers($args) + { + } + /** + * Log user in. + * + * @since 2.8.0 + * + * @param string $username User's username. + * @param string $password User's password. + * @return WP_User|false WP_User object if authentication passed, false otherwise + */ + public function login($username, $password) + { + } + /** + * Check user's credentials. Deprecated. + * + * @since 1.5.0 + * @deprecated 2.8.0 Use wp_xmlrpc_server::login() + * @see wp_xmlrpc_server::login() + * + * @param string $username User's username. + * @param string $password User's password. + * @return bool Whether authentication passed. + */ + public function login_pass_ok($username, $password) + { + } + /** + * Escape string or array of strings for database. + * + * @since 1.5.2 + * + * @param string|array $data Escape single string or array of strings. + * @return string|void Returns with string is passed, alters by-reference + * when array is passed. + */ + public function escape(&$data) + { + } + /** + * Send error response to client. + * + * Send an XML error response to the client. If the endpoint is enabled + * an HTTP 200 response is always sent per the XML-RPC specification. + * + * @since 5.7.3 + * + * @param IXR_Error|string $error Error code or an error object. + * @param false $message Error message. Optional. + */ + public function error($error, $message = \false) + { + } + /** + * Retrieve custom fields for post. + * + * @since 2.5.0 + * + * @param int $post_id Post ID. + * @return array Custom fields, if exist. + */ + public function get_custom_fields($post_id) + { + } + /** + * Set custom fields for post. + * + * @since 2.5.0 + * + * @param int $post_id Post ID. + * @param array $fields Custom fields. + */ + public function set_custom_fields($post_id, $fields) + { + } + /** + * Retrieve custom fields for a term. + * + * @since 4.9.0 + * + * @param int $term_id Term ID. + * @return array Array of custom fields, if they exist. + */ + public function get_term_custom_fields($term_id) + { + } + /** + * Set custom fields for a term. + * + * @since 4.9.0 + * + * @param int $term_id Term ID. + * @param array $fields Custom fields. + */ + public function set_term_custom_fields($term_id, $fields) + { + } + /** + * Set up blog options property. + * + * Passes property through {@see 'xmlrpc_blog_options'} filter. + * + * @since 2.6.0 + */ + public function initialise_blog_option_info() + { + } + /** + * Retrieve the blogs of the user. + * + * @since 2.6.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type string $0 Username. + * @type string $1 Password. + * } + * @return array|IXR_Error Array contains: + * - 'isAdmin' + * - 'isPrimary' - whether the blog is the user's primary blog + * - 'url' + * - 'blogid' + * - 'blogName' + * - 'xmlrpc' - url of xmlrpc endpoint + * @phpstan-param array{ + * 0: string, + * 1: string, + * } $args + */ + public function wp_getUsersBlogs($args) + { + } + /** + * Checks if the method received at least the minimum number of arguments. + * + * @since 3.4.0 + * + * @param array $args An array of arguments to check. + * @param int $count Minimum number of arguments. + * @return bool True if `$args` contains at least `$count` arguments, false otherwise. + */ + protected function minimum_args($args, $count) + { + } + /** + * Prepares taxonomy data for return in an XML-RPC object. + * + * @param WP_Taxonomy $taxonomy The unprepared taxonomy data. + * @param array $fields The subset of taxonomy fields to return. + * @return array The prepared taxonomy data. + */ + protected function _prepare_taxonomy($taxonomy, $fields) + { + } + /** + * Prepares term data for return in an XML-RPC object. + * + * @param array|object $term The unprepared term data. + * @return array The prepared term data. + */ + protected function _prepare_term($term) + { + } + /** + * Convert a WordPress date string to an IXR_Date object. + * + * @param string $date Date string to convert. + * @return IXR_Date IXR_Date object. + */ + protected function _convert_date($date) + { + } + /** + * Convert a WordPress GMT date string to an IXR_Date object. + * + * @param string $date_gmt WordPress GMT date string. + * @param string $date Date string. + * @return IXR_Date IXR_Date object. + */ + protected function _convert_date_gmt($date_gmt, $date) + { + } + /** + * Prepares post data for return in an XML-RPC object. + * + * @param array $post The unprepared post data. + * @param array $fields The subset of post type fields to return. + * @return array The prepared post data. + */ + protected function _prepare_post($post, $fields) + { + } + /** + * Prepares post data for return in an XML-RPC object. + * + * @since 3.4.0 + * @since 4.6.0 Converted the `$post_type` parameter to accept a WP_Post_Type object. + * + * @param WP_Post_Type $post_type Post type object. + * @param array $fields The subset of post fields to return. + * @return array The prepared post type data. + */ + protected function _prepare_post_type($post_type, $fields) + { + } + /** + * Prepares media item data for return in an XML-RPC object. + * + * @param WP_Post $media_item The unprepared media item data. + * @param string $thumbnail_size The image size to use for the thumbnail URL. + * @return array The prepared media item data. + */ + protected function _prepare_media_item($media_item, $thumbnail_size = 'thumbnail') + { + } + /** + * Prepares page data for return in an XML-RPC object. + * + * @param WP_Post $page The unprepared page data. + * @return array The prepared page data. + */ + protected function _prepare_page($page) + { + } + /** + * Prepares comment data for return in an XML-RPC object. + * + * @param WP_Comment $comment The unprepared comment data. + * @return array The prepared comment data. + */ + protected function _prepare_comment($comment) + { + } + /** + * Prepares user data for return in an XML-RPC object. + * + * @param WP_User $user The unprepared user object. + * @param array $fields The subset of user fields to return. + * @return array The prepared user data. + */ + protected function _prepare_user($user, $fields) + { + } + /** + * Create a new post for any registered post type. + * + * @since 3.4.0 + * + * @link https://en.wikipedia.org/wiki/RSS_enclosure for information on RSS enclosures. + * + * @param array $args { + * Method arguments. Note: top-level arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 { + * Content struct for adding a new post. See wp_insert_post() for information on + * additional post fields + * + * @type string $post_type Post type. Default 'post'. + * @type string $post_status Post status. Default 'draft' + * @type string $post_title Post title. + * @type int $post_author Post author ID. + * @type string $post_excerpt Post excerpt. + * @type string $post_content Post content. + * @type string $post_date_gmt Post date in GMT. + * @type string $post_date Post date. + * @type string $post_password Post password (20-character limit). + * @type string $comment_status Post comment enabled status. Accepts 'open' or 'closed'. + * @type string $ping_status Post ping status. Accepts 'open' or 'closed'. + * @type bool $sticky Whether the post should be sticky. Automatically false if + * `$post_status` is 'private'. + * @type int $post_thumbnail ID of an image to use as the post thumbnail/featured image. + * @type array $custom_fields Array of meta key/value pairs to add to the post. + * @type array $terms Associative array with taxonomy names as keys and arrays + * of term IDs as values. + * @type array $terms_names Associative array with taxonomy names as keys and arrays + * of term names as values. + * @type array $enclosure { + * Array of feed enclosure data to add to post meta. + * + * @type string $url URL for the feed enclosure. + * @type int $length Size in bytes of the enclosure. + * @type string $type Mime-type for the enclosure. + * } + * } + * } + * @return int|IXR_Error Post ID on success, IXR_Error instance otherwise. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array{ + * post_type?: string, + * post_status?: string, + * post_title: string, + * post_author: int, + * post_excerpt: string, + * post_content: string, + * post_date_gmt: string, + * post_date: string, + * post_password: string, + * comment_status: string, + * ping_status: string, + * sticky: bool, + * post_thumbnail: int, + * custom_fields: array, + * terms: array, + * terms_names: array, + * enclosure: array{ + * url: string, + * length: int, + * type: string, + * }, + * }, + * } $args + */ + public function wp_newPost($args) + { + } + /** + * Helper method for wp_newPost() and wp_editPost(), containing shared logic. + * + * @since 3.4.0 + * + * @see wp_insert_post() + * + * @param WP_User $user The post author if post_author isn't set in $content_struct. + * @param array|IXR_Error $content_struct Post data to insert. + * @return IXR_Error|string + */ + protected function _insert_post($user, $content_struct) + { + } + /** + * Edit a post for any registered post type. + * + * The $content_struct parameter only needs to contain fields that + * should be changed. All other fields will retain their existing values. + * + * @since 3.4.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Post ID. + * @type array $4 Extra content arguments. + * } + * @return true|IXR_Error True on success, IXR_Error on failure. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * 4: array, + * } $args + */ + public function wp_editPost($args) + { + } + /** + * Delete a post for any registered post type. + * + * @since 3.4.0 + * + * @see wp_delete_post() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Post ID. + * } + * @return true|IXR_Error True on success, IXR_Error instance on failure. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * } $args + */ + public function wp_deletePost($args) + { + } + /** + * Retrieve a post. + * + * @since 3.4.0 + * + * The optional $fields parameter specifies what fields will be included + * in the response array. This should be a list of field names. 'post_id' will + * always be included in the response regardless of the value of $fields. + * + * Instead of, or in addition to, individual field names, conceptual group + * names can be used to specify multiple fields. The available conceptual + * groups are 'post' (all basic fields), 'taxonomies', 'custom_fields', + * and 'enclosure'. + * + * @see get_post() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Post ID. + * @type array $4 Optional. The subset of post type fields to return. + * } + * @return array|IXR_Error Array contains (based on $fields parameter): + * - 'post_id' + * - 'post_title' + * - 'post_date' + * - 'post_date_gmt' + * - 'post_modified' + * - 'post_modified_gmt' + * - 'post_status' + * - 'post_type' + * - 'post_name' + * - 'post_author' + * - 'post_password' + * - 'post_excerpt' + * - 'post_content' + * - 'link' + * - 'comment_status' + * - 'ping_status' + * - 'sticky' + * - 'custom_fields' + * - 'terms' + * - 'categories' + * - 'tags' + * - 'enclosure' + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * 4: array, + * } $args + */ + public function wp_getPost($args) + { + } + /** + * Retrieve posts. + * + * @since 3.4.0 + * + * @see wp_get_recent_posts() + * @see wp_getPost() for more on `$fields` + * @see get_posts() for more on `$filter` values + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Optional. Modifies the query used to retrieve posts. Accepts 'post_type', + * 'post_status', 'number', 'offset', 'orderby', 's', and 'order'. + * Default empty array. + * @type array $4 Optional. The subset of post type fields to return in the response array. + * } + * @return array|IXR_Error Array contains a collection of posts. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * 4: array, + * } $args + */ + public function wp_getPosts($args) + { + } + /** + * Create a new term. + * + * @since 3.4.0 + * + * @see wp_insert_term() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Content struct for adding a new term. The struct must contain + * the term 'name' and 'taxonomy'. Optional accepted values include + * 'parent', 'description', and 'slug'. + * } + * @return int|IXR_Error The term ID on success, or an IXR_Error object on failure. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * } $args + */ + public function wp_newTerm($args) + { + } + /** + * Edit a term. + * + * @since 3.4.0 + * + * @see wp_update_term() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Term ID. + * @type array $4 Content struct for editing a term. The struct must contain the + * term 'taxonomy'. Optional accepted values include 'name', 'parent', + * 'description', and 'slug'. + * } + * @return true|IXR_Error True on success, IXR_Error instance on failure. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * 4: array, + * } $args + */ + public function wp_editTerm($args) + { + } + /** + * Delete a term. + * + * @since 3.4.0 + * + * @see wp_delete_term() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type string $3 Taxonomy name. + * @type int $4 Term ID. + * } + * @return true|IXR_Error True on success, IXR_Error instance on failure. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: string, + * 4: int, + * } $args + */ + public function wp_deleteTerm($args) + { + } + /** + * Retrieve a term. + * + * @since 3.4.0 + * + * @see get_term() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type string $3 Taxonomy name. + * @type int $4 Term ID. + * } + * @return array|IXR_Error IXR_Error on failure, array on success, containing: + * - 'term_id' + * - 'name' + * - 'slug' + * - 'term_group' + * - 'term_taxonomy_id' + * - 'taxonomy' + * - 'description' + * - 'parent' + * - 'count' + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: string, + * 4: int, + * } $args + */ + public function wp_getTerm($args) + { + } + /** + * Retrieve all terms for a taxonomy. + * + * @since 3.4.0 + * + * The optional $filter parameter modifies the query used to retrieve terms. + * Accepted keys are 'number', 'offset', 'orderby', 'order', 'hide_empty', and 'search'. + * + * @see get_terms() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type string $3 Taxonomy name. + * @type array $4 Optional. Modifies the query used to retrieve posts. Accepts 'number', + * 'offset', 'orderby', 'order', 'hide_empty', and 'search'. Default empty array. + * } + * @return array|IXR_Error An associative array of terms data on success, IXR_Error instance otherwise. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: string, + * 4: array, + * } $args + */ + public function wp_getTerms($args) + { + } + /** + * Retrieve a taxonomy. + * + * @since 3.4.0 + * + * @see get_taxonomy() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type string $3 Taxonomy name. + * @type array $4 Optional. Array of taxonomy fields to limit to in the return. + * Accepts 'labels', 'cap', 'menu', and 'object_type'. + * Default empty array. + * } + * @return array|IXR_Error An array of taxonomy data on success, IXR_Error instance otherwise. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: string, + * 4: array, + * } $args + */ + public function wp_getTaxonomy($args) + { + } + /** + * Retrieve all taxonomies. + * + * @since 3.4.0 + * + * @see get_taxonomies() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Optional. An array of arguments for retrieving taxonomies. + * @type array $4 Optional. The subset of taxonomy fields to return. + * } + * @return array|IXR_Error An associative array of taxonomy data with returned fields determined + * by `$fields`, or an IXR_Error instance on failure. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * 4: array, + * } $args + */ + public function wp_getTaxonomies($args) + { + } + /** + * Retrieve a user. + * + * The optional $fields parameter specifies what fields will be included + * in the response array. This should be a list of field names. 'user_id' will + * always be included in the response regardless of the value of $fields. + * + * Instead of, or in addition to, individual field names, conceptual group + * names can be used to specify multiple fields. The available conceptual + * groups are 'basic' and 'all'. + * + * @uses get_userdata() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 User ID. + * @type array $4 Optional. Array of fields to return. + * } + * @return array|IXR_Error Array contains (based on $fields parameter): + * - 'user_id' + * - 'username' + * - 'first_name' + * - 'last_name' + * - 'registered' + * - 'bio' + * - 'email' + * - 'nickname' + * - 'nicename' + * - 'url' + * - 'display_name' + * - 'roles' + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * 4: array, + * } $args + */ + public function wp_getUser($args) + { + } + /** + * Retrieve users. + * + * The optional $filter parameter modifies the query used to retrieve users. + * Accepted keys are 'number' (default: 50), 'offset' (default: 0), 'role', + * 'who', 'orderby', and 'order'. + * + * The optional $fields parameter specifies what fields will be included + * in the response array. + * + * @uses get_users() + * @see wp_getUser() for more on $fields and return values + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Optional. Arguments for the user query. + * @type array $4 Optional. Fields to return. + * } + * @return array|IXR_Error users data + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * 4: array, + * } $args + */ + public function wp_getUsers($args) + { + } + /** + * Retrieve information about the requesting user. + * + * @uses get_userdata() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username + * @type string $2 Password + * @type array $3 Optional. Fields to return. + * } + * @return array|IXR_Error (@see wp_getUser) + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * } $args + */ + public function wp_getProfile($args) + { + } + /** + * Edit user's profile. + * + * @uses wp_update_user() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Content struct. It can optionally contain: + * - 'first_name' + * - 'last_name' + * - 'website' + * - 'display_name' + * - 'nickname' + * - 'nicename' + * - 'bio' + * } + * @return true|IXR_Error True, on success. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * } $args + */ + public function wp_editProfile($args) + { + } + /** + * Retrieve page. + * + * @since 2.2.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type int $1 Page ID. + * @type string $2 Username. + * @type string $3 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: int, + * 2: string, + * 3: string, + * } $args + */ + public function wp_getPage($args) + { + } + /** + * Retrieve Pages. + * + * @since 2.2.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Optional. Number of pages. Default 10. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * } $args + */ + public function wp_getPages($args) + { + } + /** + * Create new page. + * + * @since 2.2.0 + * + * @see wp_xmlrpc_server::mw_newPost() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Content struct. + * } + * @return int|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * } $args + */ + public function wp_newPage($args) + { + } + /** + * Delete page. + * + * @since 2.2.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Page ID. + * } + * @return true|IXR_Error True, if success. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * } $args + */ + public function wp_deletePage($args) + { + } + /** + * Edit page. + * + * @since 2.2.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type int $1 Page ID. + * @type string $2 Username. + * @type string $3 Password. + * @type string $4 Content. + * @type int $5 Publish flag. 0 for draft, 1 for publish. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: int, + * 2: string, + * 3: string, + * 4: string, + * 5: int, + * } $args + */ + public function wp_editPage($args) + { + } + /** + * Retrieve page list. + * + * @since 2.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function wp_getPageList($args) + { + } + /** + * Retrieve authors list. + * + * @since 2.2.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function wp_getAuthors($args) + { + } + /** + * Get list of all tags + * + * @since 2.7.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function wp_getTags($args) + { + } + /** + * Create new category. + * + * @since 2.2.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Category. + * } + * @return int|IXR_Error Category ID. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * } $args + */ + public function wp_newCategory($args) + { + } + /** + * Remove category. + * + * @since 2.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Category ID. + * } + * @return bool|IXR_Error See wp_delete_term() for return info. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * } $args + */ + public function wp_deleteCategory($args) + { + } + /** + * Retrieve category list. + * + * @since 2.2.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Category + * @type int $4 Max number of results. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * 4: int, + * } $args + */ + public function wp_suggestCategories($args) + { + } + /** + * Retrieve comment. + * + * @since 2.7.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Comment ID. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * } $args + */ + public function wp_getComment($args) + { + } + /** + * Retrieve comments. + * + * Besides the common blog_id (unused), username, and password arguments, it takes a filter + * array as last argument. + * + * Accepted 'filter' keys are 'status', 'post_id', 'offset', and 'number'. + * + * The defaults are as follows: + * - 'status' - Default is ''. Filter by status (e.g., 'approve', 'hold') + * - 'post_id' - Default is ''. The post where the comment is posted. Empty string shows all comments. + * - 'number' - Default is 10. Total number of media items to retrieve. + * - 'offset' - Default is 0. See WP_Query::query() for more. + * + * @since 2.7.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Optional. Query arguments. + * } + * @return array|IXR_Error Contains a collection of comments. See wp_xmlrpc_server::wp_getComment() for a description of each item contents + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * } $args + */ + public function wp_getComments($args) + { + } + /** + * Delete a comment. + * + * By default, the comment will be moved to the Trash instead of deleted. + * See wp_delete_comment() for more information on this behavior. + * + * @since 2.7.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Comment ID. + * } + * @return bool|IXR_Error See wp_delete_comment(). + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * } $args + */ + public function wp_deleteComment($args) + { + } + /** + * Edit comment. + * + * Besides the common blog_id (unused), username, and password arguments, it takes a + * comment_id integer and a content_struct array as last argument. + * + * The allowed keys in the content_struct array are: + * - 'author' + * - 'author_url' + * - 'author_email' + * - 'content' + * - 'date_created_gmt' + * - 'status'. Common statuses are 'approve', 'hold', 'spam'. See get_comment_statuses() for more details + * + * @since 2.7.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Comment ID. + * @type array $4 Content structure. + * } + * @return true|IXR_Error True, on success. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * 4: array, + * } $args + */ + public function wp_editComment($args) + { + } + /** + * Create new comment. + * + * @since 2.7.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type string|int $3 Post ID or URL. + * @type array $4 Content structure. + * } + * @return int|IXR_Error See wp_new_comment(). + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: string|int, + * 4: array, + * } $args + */ + public function wp_newComment($args) + { + } + /** + * Retrieve all of the comment status. + * + * @since 2.7.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function wp_getCommentStatusList($args) + { + } + /** + * Retrieve comment count. + * + * @since 2.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Post ID. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * } $args + */ + public function wp_getCommentCount($args) + { + } + /** + * Retrieve post statuses. + * + * @since 2.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function wp_getPostStatusList($args) + { + } + /** + * Retrieve page statuses. + * + * @since 2.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function wp_getPageStatusList($args) + { + } + /** + * Retrieve page templates. + * + * @since 2.6.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function wp_getPageTemplates($args) + { + } + /** + * Retrieve blog options. + * + * @since 2.6.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Optional. Options. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * } $args + */ + public function wp_getOptions($args) + { + } + /** + * Retrieve blog options value from list. + * + * @since 2.6.0 + * + * @param array $options Options to retrieve. + * @return array + */ + public function _getOptions($options) + { + } + /** + * Update blog options. + * + * @since 2.6.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Options. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * } $args + */ + public function wp_setOptions($args) + { + } + /** + * Retrieve a media item by ID + * + * @since 3.1.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Attachment ID. + * } + * @return array|IXR_Error Associative array contains: + * - 'date_created_gmt' + * - 'parent' + * - 'link' + * - 'thumbnail' + * - 'title' + * - 'caption' + * - 'description' + * - 'metadata' + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * } $args + */ + public function wp_getMediaItem($args) + { + } + /** + * Retrieves a collection of media library items (or attachments) + * + * Besides the common blog_id (unused), username, and password arguments, it takes a filter + * array as last argument. + * + * Accepted 'filter' keys are 'parent_id', 'mime_type', 'offset', and 'number'. + * + * The defaults are as follows: + * - 'number' - Default is 5. Total number of media items to retrieve. + * - 'offset' - Default is 0. See WP_Query::query() for more. + * - 'parent_id' - Default is ''. The post where the media item is attached. Empty string shows all media items. 0 shows unattached media items. + * - 'mime_type' - Default is ''. Filter by mime type (e.g., 'image/jpeg', 'application/pdf') + * + * @since 3.1.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Query arguments. + * } + * @return array|IXR_Error Contains a collection of media items. See wp_xmlrpc_server::wp_getMediaItem() for a description of each item contents + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * } $args + */ + public function wp_getMediaLibrary($args) + { + } + /** + * Retrieves a list of post formats used by the site. + * + * @since 3.1.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error List of post formats, otherwise IXR_Error object. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function wp_getPostFormats($args) + { + } + /** + * Retrieves a post type + * + * @since 3.4.0 + * + * @see get_post_type_object() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type string $3 Post type name. + * @type array $4 Optional. Fields to fetch. + * } + * @return array|IXR_Error Array contains: + * - 'labels' + * - 'description' + * - 'capability_type' + * - 'cap' + * - 'map_meta_cap' + * - 'hierarchical' + * - 'menu_position' + * - 'taxonomies' + * - 'supports' + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: string, + * 4: array, + * } $args + */ + public function wp_getPostType($args) + { + } + /** + * Retrieves a post types + * + * @since 3.4.0 + * + * @see get_post_types() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Optional. Query arguments. + * @type array $4 Optional. Fields to fetch. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * 4: array, + * } $args + */ + public function wp_getPostTypes($args) + { + } + /** + * Retrieve revisions for a specific post. + * + * @since 3.5.0 + * + * The optional $fields parameter specifies what fields will be included + * in the response array. + * + * @uses wp_get_post_revisions() + * @see wp_getPost() for more on $fields + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Post ID. + * @type array $4 Optional. Fields to fetch. + * } + * @return array|IXR_Error contains a collection of posts. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * 4: array, + * } $args + */ + public function wp_getRevisions($args) + { + } + /** + * Restore a post revision + * + * @since 3.5.0 + * + * @uses wp_restore_post_revision() + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Revision ID. + * } + * @return bool|IXR_Error false if there was an error restoring, true if success. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * } $args + */ + public function wp_restoreRevision($args) + { + } + /* + * Blogger API functions. + * Specs on http://plant.blogger.com/api and https://groups.yahoo.com/group/bloggerDev/ + */ + /** + * Retrieve blogs that user owns. + * + * Will make more sense once we support multiple blogs. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function blogger_getUsersBlogs($args) + { + } + /** + * Private function for retrieving a users blogs for multisite setups + * + * @since 3.0.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + protected function _multisite_getUsersBlogs($args) + { + } + /** + * Retrieve user's data. + * + * Gives your client some info about you, so you don't have to. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function blogger_getUserInfo($args) + { + } + /** + * Retrieve post. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type int $1 Post ID. + * @type string $2 Username. + * @type string $3 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: int, + * 2: string, + * 3: string, + * } $args + */ + public function blogger_getPost($args) + { + } + /** + * Retrieve list of recent posts. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type string $0 App key (unused). + * @type int $1 Blog ID (unused). + * @type string $2 Username. + * @type string $3 Password. + * @type int $4 Optional. Number of posts. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: string, + * 1: int, + * 2: string, + * 3: string, + * 4: int, + * } $args + */ + public function blogger_getRecentPosts($args) + { + } + /** + * Deprecated. + * + * @since 1.5.0 + * @deprecated 3.5.0 + * + * @param array $args Unused. + * @return IXR_Error Error object. + */ + public function blogger_getTemplate($args) + { + } + /** + * Deprecated. + * + * @since 1.5.0 + * @deprecated 3.5.0 + * + * @param array $args Unused. + * @return IXR_Error Error object. + */ + public function blogger_setTemplate($args) + { + } + /** + * Creates new post. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type string $0 App key (unused). + * @type int $1 Blog ID (unused). + * @type string $2 Username. + * @type string $3 Password. + * @type string $4 Content. + * @type int $5 Publish flag. 0 for draft, 1 for publish. + * } + * @return int|IXR_Error + * @phpstan-param array{ + * 0: string, + * 1: int, + * 2: string, + * 3: string, + * 4: string, + * 5: int, + * } $args + */ + public function blogger_newPost($args) + { + } + /** + * Edit a post. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type int $1 Post ID. + * @type string $2 Username. + * @type string $3 Password. + * @type string $4 Content + * @type int $5 Publish flag. 0 for draft, 1 for publish. + * } + * @return true|IXR_Error true when done. + * @phpstan-param array{ + * 0: int, + * 1: int, + * 2: string, + * 3: string, + * 4: string, + * 5: int, + * } $args + */ + public function blogger_editPost($args) + { + } + /** + * Remove a post. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type int $1 Post ID. + * @type string $2 Username. + * @type string $3 Password. + * } + * @return true|IXR_Error True when post is deleted. + * @phpstan-param array{ + * 0: int, + * 1: int, + * 2: string, + * 3: string, + * } $args + */ + public function blogger_deletePost($args) + { + } + /* + * MetaWeblog API functions. + * Specs on wherever Dave Winer wants them to be. + */ + /** + * Create a new post. + * + * The 'content_struct' argument must contain: + * - title + * - description + * - mt_excerpt + * - mt_text_more + * - mt_keywords + * - mt_tb_ping_urls + * - categories + * + * Also, it can optionally contain: + * - wp_slug + * - wp_password + * - wp_page_parent_id + * - wp_page_order + * - wp_author_id + * - post_status | page_status - can be 'draft', 'private', 'publish', or 'pending' + * - mt_allow_comments - can be 'open' or 'closed' + * - mt_allow_pings - can be 'open' or 'closed' + * - date_created_gmt + * - dateCreated + * - wp_post_thumbnail + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Content structure. + * @type int $4 Optional. Publish flag. 0 for draft, 1 for publish. Default 0. + * } + * @return int|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * 4: int, + * } $args + */ + public function mw_newPost($args) + { + } + /** + * Adds an enclosure to a post if it's new. + * + * @since 2.8.0 + * + * @param int $post_ID Post ID. + * @param array $enclosure Enclosure data. + */ + public function add_enclosure_if_new($post_ID, $enclosure) + { + } + /** + * Attach upload to a post. + * + * @since 2.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $post_ID Post ID. + * @param string $post_content Post Content for attachment. + */ + public function attach_uploads($post_ID, $post_content) + { + } + /** + * Edit a post. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Post ID. + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Content structure. + * @type int $4 Optional. Publish flag. 0 for draft, 1 for publish. Default 0. + * } + * @return true|IXR_Error True on success. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * 4: int, + * } $args + */ + public function mw_editPost($args) + { + } + /** + * Retrieve post. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Post ID. + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function mw_getPost($args) + { + } + /** + * Retrieve list of recent posts. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Optional. Number of posts. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * } $args + */ + public function mw_getRecentPosts($args) + { + } + /** + * Retrieve the list of categories on a given blog. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function mw_getCategories($args) + { + } + /** + * Uploads a file, following your settings. + * + * Adapted from a patch by Johann Richard. + * + * @link http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/ + * + * @since 1.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Data. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * } $args + */ + public function mw_newMediaObject($args) + { + } + /* + * MovableType API functions. + * Specs on http://www.movabletype.org/docs/mtmanual_programmatic.html + */ + /** + * Retrieve the post titles of recent posts. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * @type int $3 Optional. Number of posts. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: int, + * } $args + */ + public function mt_getRecentPostTitles($args) + { + } + /** + * Retrieve list of all categories on blog. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Blog ID (unused). + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function mt_getCategoryList($args) + { + } + /** + * Retrieve post categories. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Post ID. + * @type string $1 Username. + * @type string $2 Password. + * } + * @return array|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function mt_getPostCategories($args) + { + } + /** + * Sets categories for a post. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Post ID. + * @type string $1 Username. + * @type string $2 Password. + * @type array $3 Categories. + * } + * @return true|IXR_Error True on success. + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * 3: array, + * } $args + */ + public function mt_setPostCategories($args) + { + } + /** + * Retrieve an array of methods supported by this server. + * + * @since 1.5.0 + * + * @return array + */ + public function mt_supportedMethods() + { + } + /** + * Retrieve an empty array because we don't support per-post text filters. + * + * @since 1.5.0 + */ + public function mt_supportedTextFilters() + { + } + /** + * Retrieve trackbacks sent to a given post. + * + * @since 1.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $post_ID + * @return array|IXR_Error + */ + public function mt_getTrackbackPings($post_ID) + { + } + /** + * Sets a post's publish status to 'publish'. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type int $0 Post ID. + * @type string $1 Username. + * @type string $2 Password. + * } + * @return int|IXR_Error + * @phpstan-param array{ + * 0: int, + * 1: string, + * 2: string, + * } $args + */ + public function mt_publishPost($args) + { + } + /* + * Pingback functions. + * Specs on www.hixie.ch/specs/pingback/pingback + */ + /** + * Retrieves a pingback and registers it. + * + * @since 1.5.0 + * + * @param array $args { + * Method arguments. Note: arguments must be ordered as documented. + * + * @type string $0 URL of page linked from. + * @type string $1 URL of page linked to. + * } + * @return string|IXR_Error + * @phpstan-param array{ + * 0: string, + * 1: string, + * } $args + */ + public function pingback_ping($args) + { + } + /** + * Retrieve array of URLs that pingbacked the given URL. + * + * Specs on http://www.aquarionics.com/misc/archives/blogite/0198.html + * + * @since 1.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $url + * @return array|IXR_Error + */ + public function pingback_extensions_getPingbacks($url) + { + } + /** + * Sends a pingback error based on the given error code and message. + * + * @since 3.6.0 + * + * @param int $code Error code. + * @param string $message Error message. + * @return IXR_Error Error object. + */ + protected function pingback_error($code, $message) + { + } + } + /** + * WordPress environment setup class. + * + * @package WordPress + * @since 2.0.0 + */ + #[\AllowDynamicProperties] + class WP + { + /** + * Public query variables. + * + * Long list of public query variables. + * + * @since 2.0.0 + * @var string[] + */ + public $public_query_vars = array('m', 'p', 'posts', 'w', 'cat', 'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence', 'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order', 'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second', 'name', 'category_name', 'tag', 'feed', 'author_name', 'pagename', 'page_id', 'error', 'attachment', 'attachment_id', 'subpost', 'subpost_id', 'preview', 'robots', 'favicon', 'taxonomy', 'term', 'cpage', 'post_type', 'embed'); + /** + * Private query variables. + * + * Long list of private query variables. + * + * @since 2.0.0 + * @var string[] + */ + public $private_query_vars = array('offset', 'posts_per_page', 'posts_per_archive_page', 'showposts', 'nopaging', 'post_type', 'post_status', 'category__in', 'category__not_in', 'category__and', 'tag__in', 'tag__not_in', 'tag__and', 'tag_slug__in', 'tag_slug__and', 'tag_id', 'post_mime_type', 'perm', 'comments_per_page', 'post__in', 'post__not_in', 'post_parent', 'post_parent__in', 'post_parent__not_in', 'title', 'fields'); + /** + * Extra query variables set by the user. + * + * @since 2.1.0 + * @var array + */ + public $extra_query_vars = array(); + /** + * Query variables for setting up the WordPress Query Loop. + * + * @since 2.0.0 + * @var array + */ + public $query_vars = array(); + /** + * String parsed to set the query variables. + * + * @since 2.0.0 + * @var string + */ + public $query_string = ''; + /** + * The request path, e.g. 2015/05/06. + * + * @since 2.0.0 + * @var string + */ + public $request = ''; + /** + * Rewrite rule the request matched. + * + * @since 2.0.0 + * @var string + */ + public $matched_rule = ''; + /** + * Rewrite query the request matched. + * + * @since 2.0.0 + * @var string + */ + public $matched_query = ''; + /** + * Whether already did the permalink. + * + * @since 2.0.0 + * @var bool + */ + public $did_permalink = \false; + /** + * Adds a query variable to the list of public query variables. + * + * @since 2.1.0 + * + * @param string $qv Query variable name. + */ + public function add_query_var($qv) + { + } + /** + * Removes a query variable from a list of public query variables. + * + * @since 4.5.0 + * + * @param string $name Query variable name. + */ + public function remove_query_var($name) + { + } + /** + * Sets the value of a query variable. + * + * @since 2.3.0 + * + * @param string $key Query variable name. + * @param mixed $value Query variable value. + */ + public function set_query_var($key, $value) + { + } + /** + * Parses the request to find the correct WordPress query. + * + * Sets up the query variables based on the request. There are also many + * filters and actions that can be used to further manipulate the result. + * + * @since 2.0.0 + * @since 6.0.0 A return value was added. + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param array|string $extra_query_vars Set the extra query variables. + * @return bool Whether the request was parsed. + */ + public function parse_request($extra_query_vars = '') + { + } + /** + * Sends additional HTTP headers for caching, content type, etc. + * + * Sets the Content-Type header. Sets the 'error' status (if passed) and optionally exits. + * If showing a feed, it will also send Last-Modified, ETag, and 304 status if needed. + * + * @since 2.0.0 + * @since 4.4.0 `X-Pingback` header is added conditionally for single posts that allow pings. + * @since 6.1.0 Runs after posts have been queried. + * + * @global WP_Query $wp_query WordPress Query object. + */ + public function send_headers() + { + } + /** + * Sets the query string property based off of the query variable property. + * + * The {@see 'query_string'} filter is deprecated, but still works. Plugins should + * use the {@see 'request'} filter instead. + * + * @since 2.0.0 + */ + public function build_query_string() + { + } + /** + * Set up the WordPress Globals. + * + * The query_vars property will be extracted to the GLOBALS. So care should + * be taken when naming global variables that might interfere with the + * WordPress environment. + * + * @since 2.0.0 + * + * @global WP_Query $wp_query WordPress Query object. + * @global string $query_string Query string for the loop. + * @global array $posts The found posts. + * @global WP_Post|null $post The current post, if available. + * @global string $request The SQL statement for the request. + * @global int $more Only set, if single page or post. + * @global int $single If single page or post. Only set, if single page or post. + * @global WP_User $authordata Only set, if author archive. + */ + public function register_globals() + { + } + /** + * Set up the current user. + * + * @since 2.0.0 + */ + public function init() + { + } + /** + * Set up the Loop based on the query variables. + * + * @since 2.0.0 + * + * @global WP_Query $wp_the_query WordPress Query object. + */ + public function query_posts() + { + } + /** + * Set the Headers for 404, if nothing is found for requested URL. + * + * Issue a 404 if a request doesn't match any posts and doesn't match any object + * (e.g. an existing-but-empty category, tag, author) and a 404 was not already issued, + * and if the request was not a search or the homepage. + * + * Otherwise, issue a 200. + * + * This sets headers after posts have been queried. handle_404() really means "handle status". + * By inspecting the result of querying posts, seemingly successful requests can be switched to + * a 404 so that canonical redirection logic can kick in. + * + * @since 2.0.0 + * + * @global WP_Query $wp_query WordPress Query object. + */ + public function handle_404() + { + } + /** + * Sets up all of the variables required by the WordPress environment. + * + * The action {@see 'wp'} has one parameter that references the WP object. It + * allows for accessing the properties and methods to further manipulate the + * object. + * + * @since 2.0.0 + * + * @param string|array $query_args Passed to parse_request(). + */ + public function main($query_args = '') + { + } + } + /** + * WordPress database access abstraction class. + * + * This class is used to interact with a database without needing to use raw SQL statements. + * By default, WordPress uses this class to instantiate the global $wpdb object, providing + * access to the WordPress database. + * + * It is possible to replace this class with your own by setting the $wpdb global variable + * in wp-content/db.php file to your class. The wpdb class will still be included, so you can + * extend it or simply use your own. + * + * @link https://developer.wordpress.org/reference/classes/wpdb/ + * + * @since 0.71 + */ + #[\AllowDynamicProperties] + class wpdb + { + /** + * Whether to show SQL/DB errors. + * + * Default is to show errors if both WP_DEBUG and WP_DEBUG_DISPLAY evaluate to true. + * + * @since 0.71 + * + * @var bool + */ + public $show_errors = \false; + /** + * Whether to suppress errors during the DB bootstrapping. Default false. + * + * @since 2.5.0 + * + * @var bool + */ + public $suppress_errors = \false; + /** + * The error encountered during the last query. + * + * @since 2.5.0 + * + * @var string + */ + public $last_error = ''; + /** + * The number of queries made. + * + * @since 1.2.0 + * + * @var int + */ + public $num_queries = 0; + /** + * Count of rows returned by the last query. + * + * @since 0.71 + * + * @var int + */ + public $num_rows = 0; + /** + * Count of rows affected by the last query. + * + * @since 0.71 + * + * @var int + */ + public $rows_affected = 0; + /** + * The ID generated for an AUTO_INCREMENT column by the last query (usually INSERT). + * + * @since 0.71 + * + * @var int + */ + public $insert_id = 0; + /** + * The last query made. + * + * @since 0.71 + * + * @var string + */ + public $last_query; + /** + * Results of the last query. + * + * @since 0.71 + * + * @var stdClass[]|null + */ + public $last_result; + /** + * Database query result. + * + * Possible values: + * + * - For successful SELECT, SHOW, DESCRIBE, or EXPLAIN queries: + * - `mysqli_result` instance when the `mysqli` driver is in use + * - `resource` when the older `mysql` driver is in use + * - `true` for other query types that were successful + * - `null` if a query is yet to be made or if the result has since been flushed + * - `false` if the query returned an error + * + * @since 0.71 + * + * @var mysqli_result|resource|bool|null + */ + protected $result; + /** + * Cached column info, for sanity checking data before inserting. + * + * @since 4.2.0 + * + * @var array + */ + protected $col_meta = array(); + /** + * Calculated character sets keyed by table name. + * + * @since 4.2.0 + * + * @var string[] + */ + protected $table_charset = array(); + /** + * Whether text fields in the current query need to be sanity checked. + * + * @since 4.2.0 + * + * @var bool + */ + protected $check_current_query = \true; + /** + * Saved info on the table column. + * + * @since 0.71 + * + * @var array + */ + protected $col_info; + /** + * Log of queries that were executed, for debugging purposes. + * + * @since 1.5.0 + * @since 2.5.0 The third element in each query log was added to record the calling functions. + * @since 5.1.0 The fourth element in each query log was added to record the start time. + * @since 5.3.0 The fifth element in each query log was added to record custom data. + * + * @var array[] { + * Array of arrays containing information about queries that were executed. + * + * @type array ...$0 { + * Data for each query. + * + * @type string $0 The query's SQL. + * @type float $1 Total time spent on the query, in seconds. + * @type string $2 Comma-separated list of the calling functions. + * @type float $3 Unix timestamp of the time at the start of the query. + * @type array $4 Custom query data. + * } + * } + * @phpstan-var array<int|string, array{ + * 0: string, + * 1: float, + * 2: string, + * 3: float, + * 4: array, + * }> + */ + public $queries; + /** + * The number of times to retry reconnecting before dying. Default 5. + * + * @since 3.9.0 + * + * @see wpdb::check_connection() + * @var int + */ + protected $reconnect_retries = 5; + /** + * WordPress table prefix. + * + * You can set this to have multiple WordPress installations in a single database. + * The second reason is for possible security precautions. + * + * @since 2.5.0 + * + * @var string + */ + public $prefix = ''; + /** + * WordPress base table prefix. + * + * @since 3.0.0 + * + * @var string + */ + public $base_prefix; + /** + * Whether the database queries are ready to start executing. + * + * @since 2.3.2 + * + * @var bool + */ + public $ready = \false; + /** + * Blog ID. + * + * @since 3.0.0 + * + * @var int + */ + public $blogid = 0; + /** + * Site ID. + * + * @since 3.0.0 + * + * @var int + */ + public $siteid = 0; + /** + * List of WordPress per-site tables. + * + * @since 2.5.0 + * + * @see wpdb::tables() + * @var string[] + */ + public $tables = array('posts', 'comments', 'links', 'options', 'postmeta', 'terms', 'term_taxonomy', 'term_relationships', 'termmeta', 'commentmeta'); + /** + * List of deprecated WordPress tables. + * + * 'categories', 'post2cat', and 'link2cat' were deprecated in 2.3.0, db version 5539. + * + * @since 2.9.0 + * + * @see wpdb::tables() + * @var string[] + */ + public $old_tables = array('categories', 'post2cat', 'link2cat'); + /** + * List of WordPress global tables. + * + * @since 3.0.0 + * + * @see wpdb::tables() + * @var string[] + */ + public $global_tables = array('users', 'usermeta'); + /** + * List of Multisite global tables. + * + * @since 3.0.0 + * + * @see wpdb::tables() + * @var string[] + */ + public $ms_global_tables = array('blogs', 'blogmeta', 'signups', 'site', 'sitemeta', 'registration_log'); + /** + * List of deprecated WordPress Multisite global tables. + * + * @since 6.1.0 + * + * @see wpdb::tables() + * @var string[] + */ + public $old_ms_global_tables = array('sitecategories'); + /** + * WordPress Comments table. + * + * @since 1.5.0 + * + * @var string + */ + public $comments; + /** + * WordPress Comment Metadata table. + * + * @since 2.9.0 + * + * @var string + */ + public $commentmeta; + /** + * WordPress Links table. + * + * @since 1.5.0 + * + * @var string + */ + public $links; + /** + * WordPress Options table. + * + * @since 1.5.0 + * + * @var string + */ + public $options; + /** + * WordPress Post Metadata table. + * + * @since 1.5.0 + * + * @var string + */ + public $postmeta; + /** + * WordPress Posts table. + * + * @since 1.5.0 + * + * @var string + */ + public $posts; + /** + * WordPress Terms table. + * + * @since 2.3.0 + * + * @var string + */ + public $terms; + /** + * WordPress Term Relationships table. + * + * @since 2.3.0 + * + * @var string + */ + public $term_relationships; + /** + * WordPress Term Taxonomy table. + * + * @since 2.3.0 + * + * @var string + */ + public $term_taxonomy; + /** + * WordPress Term Meta table. + * + * @since 4.4.0 + * + * @var string + */ + public $termmeta; + // + // Global and Multisite tables + // + /** + * WordPress User Metadata table. + * + * @since 2.3.0 + * + * @var string + */ + public $usermeta; + /** + * WordPress Users table. + * + * @since 1.5.0 + * + * @var string + */ + public $users; + /** + * Multisite Blogs table. + * + * @since 3.0.0 + * + * @var string + */ + public $blogs; + /** + * Multisite Blog Metadata table. + * + * @since 5.1.0 + * + * @var string + */ + public $blogmeta; + /** + * Multisite Registration Log table. + * + * @since 3.0.0 + * + * @var string + */ + public $registration_log; + /** + * Multisite Signups table. + * + * @since 3.0.0 + * + * @var string + */ + public $signups; + /** + * Multisite Sites table. + * + * @since 3.0.0 + * + * @var string + */ + public $site; + /** + * Multisite Sitewide Terms table. + * + * @since 3.0.0 + * + * @var string + */ + public $sitecategories; + /** + * Multisite Site Metadata table. + * + * @since 3.0.0 + * + * @var string + */ + public $sitemeta; + /** + * Format specifiers for DB columns. + * + * Columns not listed here default to %s. Initialized during WP load. + * Keys are column names, values are format types: 'ID' => '%d'. + * + * @since 2.8.0 + * + * @see wpdb::prepare() + * @see wpdb::insert() + * @see wpdb::update() + * @see wpdb::delete() + * @see wp_set_wpdb_vars() + * @var array + */ + public $field_types = array(); + /** + * Database table columns charset. + * + * @since 2.2.0 + * + * @var string + */ + public $charset; + /** + * Database table columns collate. + * + * @since 2.2.0 + * + * @var string + */ + public $collate; + /** + * Database Username. + * + * @since 2.9.0 + * + * @var string + */ + protected $dbuser; + /** + * Database Password. + * + * @since 3.1.0 + * + * @var string + */ + protected $dbpassword; + /** + * Database Name. + * + * @since 3.1.0 + * + * @var string + */ + protected $dbname; + /** + * Database Host. + * + * @since 3.1.0 + * + * @var string + */ + protected $dbhost; + /** + * Database handle. + * + * Possible values: + * + * - `mysqli` instance when the `mysqli` driver is in use + * - `resource` when the older `mysql` driver is in use + * - `null` if the connection is yet to be made or has been closed + * - `false` if the connection has failed + * + * @since 0.71 + * + * @var mysqli|resource|false|null + */ + protected $dbh; + /** + * A textual description of the last query/get_row/get_var call. + * + * @since 3.0.0 + * + * @var string + */ + public $func_call; + /** + * Whether MySQL is used as the database engine. + * + * Set in wpdb::db_connect() to true, by default. This is used when checking + * against the required MySQL version for WordPress. Normally, a replacement + * database drop-in (db.php) will skip these checks, but setting this to true + * will force the checks to occur. + * + * @since 3.3.0 + * + * @var bool + */ + public $is_mysql = \null; + /** + * A list of incompatible SQL modes. + * + * @since 3.9.0 + * + * @var string[] + */ + protected $incompatible_modes = array('NO_ZERO_DATE', 'ONLY_FULL_GROUP_BY', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'TRADITIONAL', 'ANSI'); + /** + * Time when the last query was performed. + * + * Only set when `SAVEQUERIES` is defined and truthy. + * + * @since 1.5.0 + * + * @var float + */ + public $time_start = \null; + /** + * The last SQL error that was encountered. + * + * @since 2.5.0 + * + * @var WP_Error|string + */ + public $error = \null; + /** + * Connects to the database server and selects a database. + * + * Does the actual setting up + * of the class properties and connection to the database. + * + * @since 2.0.8 + * + * @link https://core.trac.wordpress.org/ticket/3354 + * + * @param string $dbuser Database user. + * @param string $dbpassword Database password. + * @param string $dbname Database name. + * @param string $dbhost Database host. + */ + public function __construct($dbuser, $dbpassword, $dbname, $dbhost) + { + } + /** + * Makes private properties readable for backward compatibility. + * + * @since 3.5.0 + * + * @param string $name The private member to get, and optionally process. + * @return mixed The private member. + */ + public function __get($name) + { + } + /** + * Makes private properties settable for backward compatibility. + * + * @since 3.5.0 + * + * @param string $name The private member to set. + * @param mixed $value The value to set. + */ + public function __set($name, $value) + { + } + /** + * Makes private properties check-able for backward compatibility. + * + * @since 3.5.0 + * + * @param string $name The private member to check. + * @return bool If the member is set or not. + */ + public function __isset($name) + { + } + /** + * Makes private properties un-settable for backward compatibility. + * + * @since 3.5.0 + * + * @param string $name The private member to unset + */ + public function __unset($name) + { + } + /** + * Sets $this->charset and $this->collate. + * + * @since 3.1.0 + */ + public function init_charset() + { + } + /** + * Determines the best charset and collation to use given a charset and collation. + * + * For example, when able, utf8mb4 should be used instead of utf8. + * + * @since 4.6.0 + * + * @param string $charset The character set to check. + * @param string $collate The collation to check. + * @return array { + * The most appropriate character set and collation to use. + * + * @type string $charset Character set. + * @type string $collate Collation. + * } + * @phpstan-return array{ + * charset: string, + * collate: string, + * } + */ + public function determine_charset($charset, $collate) + { + } + /** + * Sets the connection's character set. + * + * @since 3.1.0 + * + * @param mysqli|resource $dbh The connection returned by `mysqli_connect()` or `mysql_connect()`. + * @param string $charset Optional. The character set. Default null. + * @param string $collate Optional. The collation. Default null. + */ + public function set_charset($dbh, $charset = \null, $collate = \null) + { + } + /** + * Changes the current SQL mode, and ensures its WordPress compatibility. + * + * If no modes are passed, it will ensure the current MySQL server modes are compatible. + * + * @since 3.9.0 + * + * @param array $modes Optional. A list of SQL modes to set. Default empty array. + */ + public function set_sql_mode($modes = array()) + { + } + /** + * Sets the table prefix for the WordPress tables. + * + * @since 2.5.0 + * + * @param string $prefix Alphanumeric name for the new prefix. + * @param bool $set_table_names Optional. Whether the table names, e.g. wpdb::$posts, + * should be updated or not. Default true. + * @return string|WP_Error Old prefix or WP_Error on error. + */ + public function set_prefix($prefix, $set_table_names = \true) + { + } + /** + * Sets blog ID. + * + * @since 3.0.0 + * + * @param int $blog_id + * @param int $network_id Optional. + * @return int Previous blog ID. + */ + public function set_blog_id($blog_id, $network_id = 0) + { + } + /** + * Gets blog prefix. + * + * @since 3.0.0 + * + * @param int $blog_id Optional. + * @return string Blog prefix. + */ + public function get_blog_prefix($blog_id = \null) + { + } + /** + * Returns an array of WordPress tables. + * + * Also allows for the `CUSTOM_USER_TABLE` and `CUSTOM_USER_META_TABLE` to override the WordPress users + * and usermeta tables that would otherwise be determined by the prefix. + * + * The `$scope` argument can take one of the following: + * + * - 'all' - returns 'all' and 'global' tables. No old tables are returned. + * - 'blog' - returns the blog-level tables for the queried blog. + * - 'global' - returns the global tables for the installation, returning multisite tables only on multisite. + * - 'ms_global' - returns the multisite global tables, regardless if current installation is multisite. + * - 'old' - returns tables which are deprecated. + * + * @since 3.0.0 + * @since 6.1.0 `old` now includes deprecated multisite global tables only on multisite. + * + * @uses wpdb::$tables + * @uses wpdb::$old_tables + * @uses wpdb::$global_tables + * @uses wpdb::$ms_global_tables + * @uses wpdb::$old_ms_global_tables + * + * @param string $scope Optional. Possible values include 'all', 'global', 'ms_global', 'blog', + * or 'old' tables. Default 'all'. + * @param bool $prefix Optional. Whether to include table prefixes. If blog prefix is requested, + * then the custom users and usermeta tables will be mapped. Default true. + * @param int $blog_id Optional. The blog_id to prefix. Used only when prefix is requested. + * Defaults to `wpdb::$blogid`. + * @return string[] Table names. When a prefix is requested, the key is the unprefixed table name. + */ + public function tables($scope = 'all', $prefix = \true, $blog_id = 0) + { + } + /** + * Selects a database using the current or provided database connection. + * + * The database name will be changed based on the current database connection. + * On failure, the execution will bail and display a DB error. + * + * @since 0.71 + * + * @param string $db Database name. + * @param mysqli|resource $dbh Optional database connection. + */ + public function select($db, $dbh = \null) + { + } + /** + * Do not use, deprecated. + * + * Use esc_sql() or wpdb::prepare() instead. + * + * @since 2.8.0 + * @deprecated 3.6.0 Use wpdb::prepare() + * @see wpdb::prepare() + * @see esc_sql() + * + * @param string $string + * @return string + */ + public function _weak_escape($string) + { + } + /** + * Real escape, using mysqli_real_escape_string() or mysql_real_escape_string(). + * + * @since 2.8.0 + * + * @see mysqli_real_escape_string() + * @see mysql_real_escape_string() + * + * @param string $string String to escape. + * @return string Escaped string. + */ + public function _real_escape($string) + { + } + /** + * Escapes data. Works on arrays. + * + * @since 2.8.0 + * + * @uses wpdb::_real_escape() + * + * @param string|array $data Data to escape. + * @return string|array Escaped data, in the same type as supplied. + */ + public function _escape($data) + { + } + /** + * Do not use, deprecated. + * + * Use esc_sql() or wpdb::prepare() instead. + * + * @since 0.71 + * @deprecated 3.6.0 Use wpdb::prepare() + * @see wpdb::prepare() + * @see esc_sql() + * + * @param string|array $data Data to escape. + * @return string|array Escaped data, in the same type as supplied. + */ + public function escape($data) + { + } + /** + * Escapes content by reference for insertion into the database, for security. + * + * @uses wpdb::_real_escape() + * + * @since 2.3.0 + * + * @param string $string String to escape. + */ + public function escape_by_ref(&$string) + { + } + /** + * Prepares a SQL query for safe execution. + * + * Uses sprintf()-like syntax. The following placeholders can be used in the query string: + * + * - %d (integer) + * - %f (float) + * - %s (string) + * + * All placeholders MUST be left unquoted in the query string. A corresponding argument + * MUST be passed for each placeholder. + * + * Note: There is one exception to the above: for compatibility with old behavior, + * numbered or formatted string placeholders (eg, `%1$s`, `%5s`) will not have quotes + * added by this function, so should be passed with appropriate quotes around them. + * + * Literal percentage signs (`%`) in the query string must be written as `%%`. Percentage wildcards + * (for example, to use in LIKE syntax) must be passed via a substitution argument containing + * the complete LIKE string, these cannot be inserted directly in the query string. + * Also see wpdb::esc_like(). + * + * Arguments may be passed as individual arguments to the method, or as a single array + * containing all arguments. A combination of the two is not supported. + * + * Examples: + * + * $wpdb->prepare( + * "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d OR `other_field` LIKE %s", + * array( 'foo', 1337, '%bar' ) + * ); + * + * $wpdb->prepare( + * "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", + * 'foo' + * ); + * + * @since 2.3.0 + * @since 5.3.0 Formalized the existing and already documented `...$args` parameter + * by updating the function signature. The second parameter was changed + * from `$args` to `...$args`. + * + * @link https://www.php.net/sprintf Description of syntax. + * + * @param string $query Query statement with sprintf()-like placeholders. + * @param array|mixed $args The array of variables to substitute into the query's placeholders + * if being called with an array of arguments, or the first variable + * to substitute into the query's placeholders if being called with + * individual arguments. + * @param mixed ...$args Further variables to substitute into the query's placeholders + * if being called with individual arguments. + * @return string|void Sanitized query string, if there is a query to prepare. + */ + public function prepare($query, ...$args) + { + } + /** + * First half of escaping for `LIKE` special characters `%` and `_` before preparing for SQL. + * + * Use this only before wpdb::prepare() or esc_sql(). Reversing the order is very bad for security. + * + * Example Prepared Statement: + * + * $wild = '%'; + * $find = 'only 43% of planets'; + * $like = $wild . $wpdb->esc_like( $find ) . $wild; + * $sql = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE %s", $like ); + * + * Example Escape Chain: + * + * $sql = esc_sql( $wpdb->esc_like( $input ) ); + * + * @since 4.0.0 + * + * @param string $text The raw text to be escaped. The input typed by the user + * should have no extra or deleted slashes. + * @return string Text in the form of a LIKE phrase. The output is not SQL safe. + * Call wpdb::prepare() or wpdb::_real_escape() next. + */ + public function esc_like($text) + { + } + /** + * Prints SQL/DB error. + * + * @since 0.71 + * + * @global array $EZSQL_ERROR Stores error information of query and error string. + * + * @param string $str The error to display. + * @return void|false Void if the showing of errors is enabled, false if disabled. + */ + public function print_error($str = '') + { + } + /** + * Enables showing of database errors. + * + * This function should be used only to enable showing of errors. + * wpdb::hide_errors() should be used instead for hiding errors. + * + * @since 0.71 + * + * @see wpdb::hide_errors() + * + * @param bool $show Optional. Whether to show errors. Default true. + * @return bool Whether showing of errors was previously active. + */ + public function show_errors($show = \true) + { + } + /** + * Disables showing of database errors. + * + * By default database errors are not shown. + * + * @since 0.71 + * + * @see wpdb::show_errors() + * + * @return bool Whether showing of errors was previously active. + */ + public function hide_errors() + { + } + /** + * Enables or disables suppressing of database errors. + * + * By default database errors are suppressed. + * + * @since 2.5.0 + * + * @see wpdb::hide_errors() + * + * @param bool $suppress Optional. Whether to suppress errors. Default true. + * @return bool Whether suppressing of errors was previously active. + */ + public function suppress_errors($suppress = \true) + { + } + /** + * Kills cached query results. + * + * @since 0.71 + */ + public function flush() + { + } + /** + * Connects to and selects database. + * + * If `$allow_bail` is false, the lack of database connection will need to be handled manually. + * + * @since 3.0.0 + * @since 3.9.0 $allow_bail parameter added. + * + * @param bool $allow_bail Optional. Allows the function to bail. Default true. + * @return bool True with a successful connection, false on failure. + */ + public function db_connect($allow_bail = \true) + { + } + /** + * Parses the DB_HOST setting to interpret it for mysqli_real_connect(). + * + * mysqli_real_connect() doesn't support the host param including a port or socket + * like mysql_connect() does. This duplicates how mysql_connect() detects a port + * and/or socket file. + * + * @since 4.9.0 + * + * @param string $host The DB_HOST setting to parse. + * @return array|false { + * Array containing the host, the port, the socket and + * whether it is an IPv6 address, in that order. + * False if the host couldn't be parsed. + * + * @type string $0 Host name. + * @type string|null $1 Port. + * @type string|null $2 Socket. + * @type bool $3 Whether it is an IPv6 address. + * } + * @phpstan-return false|array{ + * 0: string, + * 1: string|null, + * 2: string|null, + * 3: bool, + * } + */ + public function parse_db_host($host) + { + } + /** + * Checks that the connection to the database is still up. If not, try to reconnect. + * + * If this function is unable to reconnect, it will forcibly die, or if called + * after the {@see 'template_redirect'} hook has been fired, return false instead. + * + * If `$allow_bail` is false, the lack of database connection will need to be handled manually. + * + * @since 3.9.0 + * + * @param bool $allow_bail Optional. Allows the function to bail. Default true. + * @return bool|void True if the connection is up. + */ + public function check_connection($allow_bail = \true) + { + } + /** + * Performs a database query, using current database connection. + * + * More information can be found on the documentation page. + * + * @since 0.71 + * + * @link https://developer.wordpress.org/reference/classes/wpdb/ + * + * @param string $query Database query. + * @return int|bool Boolean true for CREATE, ALTER, TRUNCATE and DROP queries. Number of rows + * affected/selected for all other queries. Boolean false on error. + */ + public function query($query) + { + } + /** + * Logs query data. + * + * @since 5.3.0 + * + * @param string $query The query's SQL. + * @param float $query_time Total time spent on the query, in seconds. + * @param string $query_callstack Comma-separated list of the calling functions. + * @param float $query_start Unix timestamp of the time at the start of the query. + * @param array $query_data Custom query data. + */ + public function log_query($query, $query_time, $query_callstack, $query_start, $query_data) + { + } + /** + * Generates and returns a placeholder escape string for use in queries returned by ::prepare(). + * + * @since 4.8.3 + * + * @return string String to escape placeholders. + */ + public function placeholder_escape() + { + } + /** + * Adds a placeholder escape string, to escape anything that resembles a printf() placeholder. + * + * @since 4.8.3 + * + * @param string $query The query to escape. + * @return string The query with the placeholder escape string inserted where necessary. + */ + public function add_placeholder_escape($query) + { + } + /** + * Removes the placeholder escape strings from a query. + * + * @since 4.8.3 + * + * @param string $query The query from which the placeholder will be removed. + * @return string The query with the placeholder removed. + */ + public function remove_placeholder_escape($query) + { + } + /** + * Inserts a row into the table. + * + * Examples: + * + * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 'bar' ) ) + * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) ) + * + * @since 2.5.0 + * + * @see wpdb::prepare() + * @see wpdb::$field_types + * @see wp_set_wpdb_vars() + * + * @param string $table Table name. + * @param array $data Data to insert (in column => value pairs). + * Both $data columns and $data values should be "raw" (neither should be SQL escaped). + * Sending a null value will cause the column to be set to NULL - the corresponding + * format is ignored in this case. + * @param array|string $format Optional. An array of formats to be mapped to each of the value in $data. + * If string, that format will be used for all of the values in $data. + * A format is one of '%d', '%f', '%s' (integer, float, string). + * If omitted, all values in $data will be treated as strings unless otherwise + * specified in wpdb::$field_types. + * @return int|false The number of rows inserted, or false on error. + */ + public function insert($table, $data, $format = \null) + { + } + /** + * Replaces a row in the table. + * + * Examples: + * + * wpdb::replace( 'table', array( 'column' => 'foo', 'field' => 'bar' ) ) + * wpdb::replace( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) ) + * + * @since 3.0.0 + * + * @see wpdb::prepare() + * @see wpdb::$field_types + * @see wp_set_wpdb_vars() + * + * @param string $table Table name. + * @param array $data Data to insert (in column => value pairs). + * Both $data columns and $data values should be "raw" (neither should be SQL escaped). + * Sending a null value will cause the column to be set to NULL - the corresponding + * format is ignored in this case. + * @param array|string $format Optional. An array of formats to be mapped to each of the value in $data. + * If string, that format will be used for all of the values in $data. + * A format is one of '%d', '%f', '%s' (integer, float, string). + * If omitted, all values in $data will be treated as strings unless otherwise + * specified in wpdb::$field_types. + * @return int|false The number of rows affected, or false on error. + */ + public function replace($table, $data, $format = \null) + { + } + /** + * Helper function for insert and replace. + * + * Runs an insert or replace query based on $type argument. + * + * @since 3.0.0 + * + * @see wpdb::prepare() + * @see wpdb::$field_types + * @see wp_set_wpdb_vars() + * + * @param string $table Table name. + * @param array $data Data to insert (in column => value pairs). + * Both $data columns and $data values should be "raw" (neither should be SQL escaped). + * Sending a null value will cause the column to be set to NULL - the corresponding + * format is ignored in this case. + * @param array|string $format Optional. An array of formats to be mapped to each of the value in $data. + * If string, that format will be used for all of the values in $data. + * A format is one of '%d', '%f', '%s' (integer, float, string). + * If omitted, all values in $data will be treated as strings unless otherwise + * specified in wpdb::$field_types. + * @param string $type Optional. Type of operation. Possible values include 'INSERT' or 'REPLACE'. + * Default 'INSERT'. + * @return int|false The number of rows affected, or false on error. + */ + public function _insert_replace_helper($table, $data, $format = \null, $type = 'INSERT') + { + } + /** + * Updates a row in the table. + * + * Examples: + * + * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 'bar' ), array( 'ID' => 1 ) ) + * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) ) + * + * @since 2.5.0 + * + * @see wpdb::prepare() + * @see wpdb::$field_types + * @see wp_set_wpdb_vars() + * + * @param string $table Table name. + * @param array $data Data to update (in column => value pairs). + * Both $data columns and $data values should be "raw" (neither should be SQL escaped). + * Sending a null value will cause the column to be set to NULL - the corresponding + * format is ignored in this case. + * @param array $where A named array of WHERE clauses (in column => value pairs). + * Multiple clauses will be joined with ANDs. + * Both $where columns and $where values should be "raw". + * Sending a null value will create an IS NULL comparison - the corresponding + * format will be ignored in this case. + * @param array|string $format Optional. An array of formats to be mapped to each of the values in $data. + * If string, that format will be used for all of the values in $data. + * A format is one of '%d', '%f', '%s' (integer, float, string). + * If omitted, all values in $data will be treated as strings unless otherwise + * specified in wpdb::$field_types. + * @param array|string $where_format Optional. An array of formats to be mapped to each of the values in $where. + * If string, that format will be used for all of the items in $where. + * A format is one of '%d', '%f', '%s' (integer, float, string). + * If omitted, all values in $where will be treated as strings. + * @return int|false The number of rows updated, or false on error. + */ + public function update($table, $data, $where, $format = \null, $where_format = \null) + { + } + /** + * Deletes a row in the table. + * + * Examples: + * + * wpdb::delete( 'table', array( 'ID' => 1 ) ) + * wpdb::delete( 'table', array( 'ID' => 1 ), array( '%d' ) ) + * + * @since 3.4.0 + * + * @see wpdb::prepare() + * @see wpdb::$field_types + * @see wp_set_wpdb_vars() + * + * @param string $table Table name. + * @param array $where A named array of WHERE clauses (in column => value pairs). + * Multiple clauses will be joined with ANDs. + * Both $where columns and $where values should be "raw". + * Sending a null value will create an IS NULL comparison - the corresponding + * format will be ignored in this case. + * @param array|string $where_format Optional. An array of formats to be mapped to each of the values in $where. + * If string, that format will be used for all of the items in $where. + * A format is one of '%d', '%f', '%s' (integer, float, string). + * If omitted, all values in $data will be treated as strings unless otherwise + * specified in wpdb::$field_types. + * @return int|false The number of rows deleted, or false on error. + */ + public function delete($table, $where, $where_format = \null) + { + } + /** + * Processes arrays of field/value pairs and field formats. + * + * This is a helper method for wpdb's CRUD methods, which take field/value pairs + * for inserts, updates, and where clauses. This method first pairs each value + * with a format. Then it determines the charset of that field, using that + * to determine if any invalid text would be stripped. If text is stripped, + * then field processing is rejected and the query fails. + * + * @since 4.2.0 + * + * @param string $table Table name. + * @param array $data Field/value pair. + * @param mixed $format Format for each field. + * @return array|false An array of fields that contain paired value and formats. + * False for invalid values. + */ + protected function process_fields($table, $data, $format) + { + } + /** + * Prepares arrays of value/format pairs as passed to wpdb CRUD methods. + * + * @since 4.2.0 + * + * @param array $data Array of fields to values. + * @param mixed $format Formats to be mapped to the values in $data. + * @return array Array, keyed by field names with values being an array + * of 'value' and 'format' keys. + */ + protected function process_field_formats($data, $format) + { + } + /** + * Adds field charsets to field/value/format arrays generated by wpdb::process_field_formats(). + * + * @since 4.2.0 + * + * @param array $data As it comes from the wpdb::process_field_formats() method. + * @param string $table Table name. + * @return array|false The same array as $data with additional 'charset' keys. + * False on failure. + */ + protected function process_field_charsets($data, $table) + { + } + /** + * For string fields, records the maximum string length that field can safely save. + * + * @since 4.2.1 + * + * @param array $data As it comes from the wpdb::process_field_charsets() method. + * @param string $table Table name. + * @return array|false The same array as $data with additional 'length' keys, or false if + * any of the values were too long for their corresponding field. + */ + protected function process_field_lengths($data, $table) + { + } + /** + * Retrieves one variable from the database. + * + * Executes a SQL query and returns the value from the SQL result. + * If the SQL result contains more than one column and/or more than one row, + * the value in the column and row specified is returned. If $query is null, + * the value in the specified column and row from the previous SQL result is returned. + * + * @since 0.71 + * + * @param string|null $query Optional. SQL query. Defaults to null, use the result from the previous query. + * @param int $x Optional. Column of value to return. Indexed from 0. + * @param int $y Optional. Row of value to return. Indexed from 0. + * @return string|null Database query result (as string), or null on failure. + */ + public function get_var($query = \null, $x = 0, $y = 0) + { + } + /** + * Retrieves one row from the database. + * + * Executes a SQL query and returns the row from the SQL result. + * + * @since 0.71 + * + * @param string|null $query SQL query. + * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which + * correspond to an stdClass object, an associative array, or a numeric array, + * respectively. Default OBJECT. + * @param int $y Optional. Row to return. Indexed from 0. + * @return array|object|null|void Database query result in format specified by $output or null on failure. + */ + public function get_row($query = \null, $output = \OBJECT, $y = 0) + { + } + /** + * Retrieves one column from the database. + * + * Executes a SQL query and returns the column from the SQL result. + * If the SQL result contains more than one column, the column specified is returned. + * If $query is null, the specified column from the previous SQL result is returned. + * + * @since 0.71 + * + * @param string|null $query Optional. SQL query. Defaults to previous query. + * @param int $x Optional. Column to return. Indexed from 0. + * @return array Database query result. Array indexed from 0 by SQL result row number. + */ + public function get_col($query = \null, $x = 0) + { + } + /** + * Retrieves an entire SQL result set from the database (i.e., many rows). + * + * Executes a SQL query and returns the entire SQL result. + * + * @since 0.71 + * + * @param string $query SQL query. + * @param string $output Optional. Any of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K constants. + * With one of the first three, return an array of rows indexed + * from 0 by SQL result row number. Each row is an associative array + * (column => value, ...), a numerically indexed array (0 => value, ...), + * or an object ( ->column = value ), respectively. With OBJECT_K, + * return an associative array of row objects keyed by the value + * of each row's first column's value. Duplicate keys are discarded. + * @return array|object|null Database query results. + */ + public function get_results($query = \null, $output = \OBJECT) + { + } + /** + * Retrieves the character set for the given table. + * + * @since 4.2.0 + * + * @param string $table Table name. + * @return string|WP_Error Table character set, WP_Error object if it couldn't be found. + */ + protected function get_table_charset($table) + { + } + /** + * Retrieves the character set for the given column. + * + * @since 4.2.0 + * + * @param string $table Table name. + * @param string $column Column name. + * @return string|false|WP_Error Column character set as a string. False if the column has + * no character set. WP_Error object if there was an error. + */ + public function get_col_charset($table, $column) + { + } + /** + * Retrieves the maximum string length allowed in a given column. + * + * The length may either be specified as a byte length or a character length. + * + * @since 4.2.1 + * + * @param string $table Table name. + * @param string $column Column name. + * @return array|false|WP_Error { + * Array of column length information, false if the column has no length (for + * example, numeric column), WP_Error object if there was an error. + * + * @type int $length The column length. + * @type string $type One of 'byte' or 'char'. + */ + public function get_col_length($table, $column) + { + } + /** + * Checks if a string is ASCII. + * + * The negative regex is faster for non-ASCII strings, as it allows + * the search to finish as soon as it encounters a non-ASCII character. + * + * @since 4.2.0 + * + * @param string $string String to check. + * @return bool True if ASCII, false if not. + */ + protected function check_ascii($string) + { + } + /** + * Checks if the query is accessing a collation considered safe on the current version of MySQL. + * + * @since 4.2.0 + * + * @param string $query The query to check. + * @return bool True if the collation is safe, false if it isn't. + */ + protected function check_safe_collation($query) + { + } + /** + * Strips any invalid characters based on value/charset pairs. + * + * @since 4.2.0 + * + * @param array $data Array of value arrays. Each value array has the keys 'value' and 'charset'. + * An optional 'ascii' key can be set to false to avoid redundant ASCII checks. + * @return array|WP_Error The $data parameter, with invalid characters removed from each value. + * This works as a passthrough: any additional keys such as 'field' are + * retained in each value array. If we cannot remove invalid characters, + * a WP_Error object is returned. + */ + protected function strip_invalid_text($data) + { + } + /** + * Strips any invalid characters from the query. + * + * @since 4.2.0 + * + * @param string $query Query to convert. + * @return string|WP_Error The converted query, or a WP_Error object if the conversion fails. + */ + protected function strip_invalid_text_from_query($query) + { + } + /** + * Strips any invalid characters from the string for a given table and column. + * + * @since 4.2.0 + * + * @param string $table Table name. + * @param string $column Column name. + * @param string $value The text to check. + * @return string|WP_Error The converted string, or a WP_Error object if the conversion fails. + */ + public function strip_invalid_text_for_column($table, $column, $value) + { + } + /** + * Finds the first table name referenced in a query. + * + * @since 4.2.0 + * + * @param string $query The query to search. + * @return string|false The table name found, or false if a table couldn't be found. + */ + protected function get_table_from_query($query) + { + } + /** + * Loads the column metadata from the last query. + * + * @since 3.5.0 + */ + protected function load_col_info() + { + } + /** + * Retrieves column metadata from the last query. + * + * @since 0.71 + * + * @param string $info_type Optional. Possible values include 'name', 'table', 'def', 'max_length', + * 'not_null', 'primary_key', 'multiple_key', 'unique_key', 'numeric', + * 'blob', 'type', 'unsigned', 'zerofill'. Default 'name'. + * @param int $col_offset Optional. 0: col name. 1: which table the col's in. 2: col's max length. + * 3: if the col is numeric. 4: col's type. Default -1. + * @return mixed Column results. + */ + public function get_col_info($info_type = 'name', $col_offset = -1) + { + } + /** + * Starts the timer, for debugging purposes. + * + * @since 1.5.0 + * + * @return true + */ + public function timer_start() + { + } + /** + * Stops the debugging timer. + * + * @since 1.5.0 + * + * @return float Total time spent on the query, in seconds. + */ + public function timer_stop() + { + } + /** + * Wraps errors in a nice header and footer and dies. + * + * Will not die if wpdb::$show_errors is false. + * + * @since 1.5.0 + * + * @param string $message The error message. + * @param string $error_code Optional. A computer-readable string to identify the error. + * Default '500'. + * @return void|false Void if the showing of errors is enabled, false if disabled. + */ + public function bail($message, $error_code = '500') + { + } + /** + * Closes the current database connection. + * + * @since 4.5.0 + * + * @return bool True if the connection was successfully closed, + * false if it wasn't, or if the connection doesn't exist. + */ + public function close() + { + } + /** + * Determines whether MySQL database is at least the required minimum version. + * + * @since 2.5.0 + * + * @global string $wp_version The WordPress version string. + * @global string $required_mysql_version The required MySQL version string. + * @return void|WP_Error + */ + public function check_database_version() + { + } + /** + * Determines whether the database supports collation. + * + * Called when WordPress is generating the table scheme. + * + * Use `wpdb::has_cap( 'collation' )`. + * + * @since 2.5.0 + * @deprecated 3.5.0 Use wpdb::has_cap() + * + * @return bool True if collation is supported, false if not. + */ + public function supports_collation() + { + } + /** + * Retrieves the database character collate. + * + * @since 3.5.0 + * + * @return string The database character collate. + */ + public function get_charset_collate() + { + } + /** + * Determines whether the database or WPDB supports a particular feature. + * + * Capability sniffs for the database server and current version of WPDB. + * + * Database sniffs are based on the version of MySQL the site is using. + * + * WPDB sniffs are added as new features are introduced to allow theme and plugin + * developers to determine feature support. This is to account for drop-ins which may + * introduce feature support at a different time to WordPress. + * + * @since 2.7.0 + * @since 4.1.0 Added support for the 'utf8mb4' feature. + * @since 4.6.0 Added support for the 'utf8mb4_520' feature. + * + * @see wpdb::db_version() + * + * @param string $db_cap The feature to check for. Accepts 'collation', 'group_concat', + * 'subqueries', 'set_charset', 'utf8mb4', or 'utf8mb4_520'. + * @return bool True when the database feature is supported, false otherwise. + */ + public function has_cap($db_cap) + { + } + /** + * Retrieves a comma-separated list of the names of the functions that called wpdb. + * + * @since 2.5.0 + * + * @return string Comma-separated list of the calling functions. + */ + public function get_caller() + { + } + /** + * Retrieves the database server version. + * + * @since 2.7.0 + * + * @return string|null Version number on success, null on failure. + */ + public function db_version() + { + } + /** + * Retrieves full database server information. + * + * @since 5.5.0 + * + * @return string|false Server info on success, false on failure. + */ + public function db_server_info() + { + } + } + /** + * Customize API: WP_Customize_Media_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Media Control class. + * + * @since 4.2.0 + * + * @see WP_Customize_Control + */ + class WP_Customize_Media_Control extends \WP_Customize_Control + { + /** + * Control type. + * + * @since 4.2.0 + * @var string + */ + public $type = 'media'; + /** + * Media control mime type. + * + * @since 4.2.0 + * @var string + */ + public $mime_type = ''; + /** + * Button labels. + * + * @since 4.2.0 + * @var array + */ + public $button_labels = array(); + /** + * Constructor. + * + * @since 4.1.0 + * @since 4.2.0 Moved from WP_Customize_Upload_Control. + * + * @see WP_Customize_Control::__construct() + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + * @param string $id Control ID. + * @param array $args Optional. Arguments to override class property defaults. + * See WP_Customize_Control::__construct() for information + * on accepted arguments. Default empty array. + * @phpstan-param array{ + * instance_number?: int, + * manager?: WP_Customize_Manager, + * id?: string, + * settings?: array, + * setting?: string, + * capability?: string, + * priority?: int, + * section?: string, + * label?: string, + * description?: string, + * choices?: array, + * input_attrs?: array, + * allow_addition?: bool, + * json?: array, + * type?: string, + * active_callback?: callable, + * } $args See WP_Customize_Control::__construct() + */ + public function __construct($manager, $id, $args = array()) + { + } + /** + * Enqueue control related scripts/styles. + * + * @since 3.4.0 + * @since 4.2.0 Moved from WP_Customize_Upload_Control. + */ + public function enqueue() + { + } + /** + * Refresh the parameters passed to the JavaScript via JSON. + * + * @since 3.4.0 + * @since 4.2.0 Moved from WP_Customize_Upload_Control. + * + * @see WP_Customize_Control::to_json() + */ + public function to_json() + { + } + /** + * Don't render any content for this control from PHP. + * + * @since 3.4.0 + * @since 4.2.0 Moved from WP_Customize_Upload_Control. + * + * @see WP_Customize_Media_Control::content_template() + */ + public function render_content() + { + } + /** + * Render a JS template for the content of the media control. + * + * @since 4.1.0 + * @since 4.2.0 Moved from WP_Customize_Upload_Control. + */ + public function content_template() + { + } + /** + * Get default button labels. + * + * Provides an array of the default button labels based on the mime type of the current control. + * + * @since 4.9.0 + * + * @return string[] An associative array of default button labels keyed by the button name. + */ + public function get_default_button_labels() + { + } + } + /** + * Customize API: WP_Customize_Upload_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Upload Control Class. + * + * @since 3.4.0 + * + * @see WP_Customize_Media_Control + */ + class WP_Customize_Upload_Control extends \WP_Customize_Media_Control + { + /** + * Control type. + * + * @since 3.4.0 + * @var string + */ + public $type = 'upload'; + /** + * Media control mime type. + * + * @since 4.1.0 + * @var string + */ + public $mime_type = ''; + /** + * Button labels. + * + * @since 4.1.0 + * @var array + */ + public $button_labels = array(); + public $removed = ''; + // Unused. + public $context; + // Unused. + public $extensions = array(); + // Unused. + /** + * Refresh the parameters passed to the JavaScript via JSON. + * + * @since 3.4.0 + * + * @uses WP_Customize_Media_Control::to_json() + */ + public function to_json() + { + } + } + /** + * Customize API: WP_Customize_Image_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Image Control class. + * + * @since 3.4.0 + * + * @see WP_Customize_Upload_Control + */ + class WP_Customize_Image_Control extends \WP_Customize_Upload_Control + { + /** + * Control type. + * + * @since 3.4.0 + * @var string + */ + public $type = 'image'; + /** + * Media control mime type. + * + * @since 4.1.0 + * @var string + */ + public $mime_type = 'image'; + /** + * @since 3.4.2 + * @deprecated 4.1.0 + */ + public function prepare_control() + { + } + /** + * @since 3.4.0 + * @deprecated 4.1.0 + * + * @param string $id + * @param string $label + * @param mixed $callback + */ + public function add_tab($id, $label, $callback) + { + } + /** + * @since 3.4.0 + * @deprecated 4.1.0 + * + * @param string $id + */ + public function remove_tab($id) + { + } + /** + * @since 3.4.0 + * @deprecated 4.1.0 + * + * @param string $url + * @param string $thumbnail_url + */ + public function print_tab_image($url, $thumbnail_url = \null) + { + } + } + /** + * Customize API: WP_Customize_Background_Image_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Background Image Control class. + * + * @since 3.4.0 + * + * @see WP_Customize_Image_Control + */ + class WP_Customize_Background_Image_Control extends \WP_Customize_Image_Control + { + /** + * Customize control type. + * + * @since 4.1.0 + * @var string + */ + public $type = 'background'; + /** + * Constructor. + * + * @since 3.4.0 + * @uses WP_Customize_Image_Control::__construct() + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + */ + public function __construct($manager) + { + } + /** + * Enqueue control related scripts/styles. + * + * @since 4.1.0 + */ + public function enqueue() + { + } + } + /** + * Customize API: WP_Customize_Background_Image_Setting class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customizer Background Image Setting class. + * + * @since 3.4.0 + * + * @see WP_Customize_Setting + */ + final class WP_Customize_Background_Image_Setting extends \WP_Customize_Setting + { + /** + * Unique string identifier for the setting. + * + * @since 3.4.0 + * @var string + */ + public $id = 'background_image_thumb'; + /** + * @since 3.4.0 + * + * @param mixed $value The value to update. Not used. + */ + public function update($value) + { + } + } + /** + * Customize API: WP_Customize_Background_Position_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.7.0 + */ + /** + * Customize Background Position Control class. + * + * @since 4.7.0 + * + * @see WP_Customize_Control + */ + class WP_Customize_Background_Position_Control extends \WP_Customize_Control + { + /** + * Type. + * + * @since 4.7.0 + * @var string + */ + public $type = 'background_position'; + /** + * Don't render the control content from PHP, as it's rendered via JS on load. + * + * @since 4.7.0 + */ + public function render_content() + { + } + /** + * Render a JS template for the content of the position control. + * + * @since 4.7.0 + */ + public function content_template() + { + } + } + /** + * Customize API: WP_Customize_Code_Editor_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.9.0 + */ + /** + * Customize Code Editor Control class. + * + * @since 4.9.0 + * + * @see WP_Customize_Control + */ + class WP_Customize_Code_Editor_Control extends \WP_Customize_Control + { + /** + * Customize control type. + * + * @since 4.9.0 + * @var string + */ + public $type = 'code_editor'; + /** + * Type of code that is being edited. + * + * @since 4.9.0 + * @var string + */ + public $code_type = ''; + /** + * Code editor settings. + * + * @see wp_enqueue_code_editor() + * @since 4.9.0 + * @var array|false + */ + public $editor_settings = array(); + /** + * Enqueue control related scripts/styles. + * + * @since 4.9.0 + */ + public function enqueue() + { + } + /** + * Refresh the parameters passed to the JavaScript via JSON. + * + * @since 4.9.0 + * + * @see WP_Customize_Control::json() + * + * @return array Array of parameters passed to the JavaScript. + */ + public function json() + { + } + /** + * Don't render the control content from PHP, as it's rendered via JS on load. + * + * @since 4.9.0 + */ + public function render_content() + { + } + /** + * Render a JS template for control display. + * + * @since 4.9.0 + */ + public function content_template() + { + } + } + /** + * Customize API: WP_Customize_Color_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Color Control class. + * + * @since 3.4.0 + * + * @see WP_Customize_Control + */ + class WP_Customize_Color_Control extends \WP_Customize_Control + { + /** + * Type. + * + * @var string + */ + public $type = 'color'; + /** + * Statuses. + * + * @var array + */ + public $statuses; + /** + * Mode. + * + * @since 4.7.0 + * @var string + */ + public $mode = 'full'; + /** + * Constructor. + * + * @since 3.4.0 + * + * @see WP_Customize_Control::__construct() + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + * @param string $id Control ID. + * @param array $args Optional. Arguments to override class property defaults. + * See WP_Customize_Control::__construct() for information + * on accepted arguments. Default empty array. + * @phpstan-param array{ + * instance_number?: int, + * manager?: WP_Customize_Manager, + * id?: string, + * settings?: array, + * setting?: string, + * capability?: string, + * priority?: int, + * section?: string, + * label?: string, + * description?: string, + * choices?: array, + * input_attrs?: array, + * allow_addition?: bool, + * json?: array, + * type?: string, + * active_callback?: callable, + * } $args See WP_Customize_Control::__construct() + */ + public function __construct($manager, $id, $args = array()) + { + } + /** + * Enqueue scripts/styles for the color picker. + * + * @since 3.4.0 + */ + public function enqueue() + { + } + /** + * Refresh the parameters passed to the JavaScript via JSON. + * + * @since 3.4.0 + * @uses WP_Customize_Control::to_json() + */ + public function to_json() + { + } + /** + * Don't render the control content from PHP, as it's rendered via JS on load. + * + * @since 3.4.0 + */ + public function render_content() + { + } + /** + * Render a JS template for the content of the color picker control. + * + * @since 4.1.0 + */ + public function content_template() + { + } + } + /** + * Customize API: WP_Customize_Cropped_Image_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Cropped Image Control class. + * + * @since 4.3.0 + * + * @see WP_Customize_Image_Control + */ + class WP_Customize_Cropped_Image_Control extends \WP_Customize_Image_Control + { + /** + * Control type. + * + * @since 4.3.0 + * @var string + */ + public $type = 'cropped_image'; + /** + * Suggested width for cropped image. + * + * @since 4.3.0 + * @var int + */ + public $width = 150; + /** + * Suggested height for cropped image. + * + * @since 4.3.0 + * @var int + */ + public $height = 150; + /** + * Whether the width is flexible. + * + * @since 4.3.0 + * @var bool + */ + public $flex_width = \false; + /** + * Whether the height is flexible. + * + * @since 4.3.0 + * @var bool + */ + public $flex_height = \false; + /** + * Enqueue control related scripts/styles. + * + * @since 4.3.0 + */ + public function enqueue() + { + } + /** + * Refresh the parameters passed to the JavaScript via JSON. + * + * @since 4.3.0 + * + * @see WP_Customize_Control::to_json() + */ + public function to_json() + { + } + } + /** + * Customize API: WP_Customize_Custom_CSS_Setting class + * + * This handles validation, sanitization and saving of the value. + * + * @package WordPress + * @subpackage Customize + * @since 4.7.0 + */ + /** + * Custom Setting to handle WP Custom CSS. + * + * @since 4.7.0 + * + * @see WP_Customize_Setting + */ + final class WP_Customize_Custom_CSS_Setting extends \WP_Customize_Setting + { + /** + * The setting type. + * + * @since 4.7.0 + * @var string + */ + public $type = 'custom_css'; + /** + * Setting Transport + * + * @since 4.7.0 + * @var string + */ + public $transport = 'postMessage'; + /** + * Capability required to edit this setting. + * + * @since 4.7.0 + * @var string + */ + public $capability = 'edit_css'; + /** + * Stylesheet + * + * @since 4.7.0 + * @var string + */ + public $stylesheet = ''; + /** + * WP_Customize_Custom_CSS_Setting constructor. + * + * @since 4.7.0 + * + * @throws Exception If the setting ID does not match the pattern `custom_css[$stylesheet]`. + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + * @param string $id A specific ID of the setting. + * Can be a theme mod or option name. + * @param array $args Setting arguments. + */ + public function __construct($manager, $id, $args = array()) + { + } + /** + * Add filter to preview post value. + * + * @since 4.7.9 + * + * @return bool False when preview short-circuits due no change needing to be previewed. + */ + public function preview() + { + } + /** + * Filters `wp_get_custom_css` for applying the customized value. + * + * This is used in the preview when `wp_get_custom_css()` is called for rendering the styles. + * + * @since 4.7.0 + * + * @see wp_get_custom_css() + * + * @param string $css Original CSS. + * @param string $stylesheet Current stylesheet. + * @return string CSS. + */ + public function filter_previewed_wp_get_custom_css($css, $stylesheet) + { + } + /** + * Fetch the value of the setting. Will return the previewed value when `preview()` is called. + * + * @since 4.7.0 + * + * @see WP_Customize_Setting::value() + * + * @return string + */ + public function value() + { + } + /** + * Validate a received value for being valid CSS. + * + * Checks for imbalanced braces, brackets, and comments. + * Notifications are rendered when the customizer state is saved. + * + * @since 4.7.0 + * @since 4.9.0 Checking for balanced characters has been moved client-side via linting in code editor. + * @since 5.9.0 Renamed `$css` to `$value` for PHP 8 named parameter support. + * + * @param string $value CSS to validate. + * @return true|WP_Error True if the input was validated, otherwise WP_Error. + */ + public function validate($value) + { + } + /** + * Store the CSS setting value in the custom_css custom post type for the stylesheet. + * + * @since 4.7.0 + * @since 5.9.0 Renamed `$css` to `$value` for PHP 8 named parameter support. + * + * @param string $value CSS to update. + * @return int|false The post ID or false if the value could not be saved. + */ + public function update($value) + { + } + } + /** + * Customize API: WP_Customize_Date_Time_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.9.0 + */ + /** + * Customize Date Time Control class. + * + * @since 4.9.0 + * + * @see WP_Customize_Control + */ + class WP_Customize_Date_Time_Control extends \WP_Customize_Control + { + /** + * Customize control type. + * + * @since 4.9.0 + * @var string + */ + public $type = 'date_time'; + /** + * Minimum Year. + * + * @since 4.9.0 + * @var int + */ + public $min_year = 1000; + /** + * Maximum Year. + * + * @since 4.9.0 + * @var int + */ + public $max_year = 9999; + /** + * Allow past date, if set to false user can only select future date. + * + * @since 4.9.0 + * @var bool + */ + public $allow_past_date = \true; + /** + * Whether hours, minutes, and meridian should be shown. + * + * @since 4.9.0 + * @var bool + */ + public $include_time = \true; + /** + * If set to false the control will appear in 24 hour format, + * the value will still be saved in Y-m-d H:i:s format. + * + * @since 4.9.0 + * @var bool + */ + public $twelve_hour_format = \true; + /** + * Don't render the control's content - it's rendered with a JS template. + * + * @since 4.9.0 + */ + public function render_content() + { + } + /** + * Export data to JS. + * + * @since 4.9.0 + * @return array + */ + public function json() + { + } + /** + * Renders a JS template for the content of date time control. + * + * @since 4.9.0 + */ + public function content_template() + { + } + /** + * Generate options for the month Select. + * + * Based on touch_time(). + * + * @since 4.9.0 + * + * @see touch_time() + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @return array + */ + public function get_month_choices() + { + } + /** + * Get timezone info. + * + * @since 4.9.0 + * + * @return array { + * Timezone info. All properties are optional. + * + * @type string $abbr Timezone abbreviation. Examples: PST or CEST. + * @type string $description Human-readable timezone description as HTML. + * } + * @phpstan-return array{ + * abbr: string, + * description: string, + * } + */ + public function get_timezone_info() + { + } + /** + * Format GMT Offset. + * + * @since 4.9.0 + * + * @see wp_timezone_choice() + * + * @param float $offset Offset in hours. + * @return string Formatted offset. + */ + public function format_gmt_offset($offset) + { + } + } + /** + * Customize API: WP_Customize_Filter_Setting class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * A setting that is used to filter a value, but will not save the results. + * + * Results should be properly handled using another setting or callback. + * + * @since 3.4.0 + * + * @see WP_Customize_Setting + */ + class WP_Customize_Filter_Setting extends \WP_Customize_Setting + { + /** + * Saves the value of the setting, using the related API. + * + * @since 3.4.0 + * + * @param mixed $value The value to update. + */ + public function update($value) + { + } + } + /** + * Customize API: WP_Customize_Header_Image_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Header Image Control class. + * + * @since 3.4.0 + * + * @see WP_Customize_Image_Control + */ + class WP_Customize_Header_Image_Control extends \WP_Customize_Image_Control + { + /** + * Customize control type. + * + * @since 4.2.0 + * @var string + */ + public $type = 'header'; + /** + * Uploaded header images. + * + * @since 3.9.0 + * @var string + */ + public $uploaded_headers; + /** + * Default header images. + * + * @since 3.9.0 + * @var string + */ + public $default_headers; + /** + * Constructor. + * + * @since 3.4.0 + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + */ + public function __construct($manager) + { + } + /** + */ + public function enqueue() + { + } + /** + * @global Custom_Image_Header $custom_image_header + */ + public function prepare_control() + { + } + /** + */ + public function print_header_image_template() + { + } + /** + * @return string|void + */ + public function get_current_image_src() + { + } + /** + */ + public function render_content() + { + } + } + /** + * Customize API: WP_Customize_Header_Image_Setting class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * A setting that is used to filter a value, but will not save the results. + * + * Results should be properly handled using another setting or callback. + * + * @since 3.4.0 + * + * @see WP_Customize_Setting + */ + final class WP_Customize_Header_Image_Setting extends \WP_Customize_Setting + { + /** + * Unique string identifier for the setting. + * + * @since 3.4.0 + * @var string + */ + public $id = 'header_image_data'; + /** + * @since 3.4.0 + * + * @global Custom_Image_Header $custom_image_header + * + * @param mixed $value The value to update. + */ + public function update($value) + { + } + } + /** + * Customize API: WP_Customize_Nav_Menu_Auto_Add_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize control to represent the auto_add field for a given menu. + * + * @since 4.3.0 + * + * @see WP_Customize_Control + */ + class WP_Customize_Nav_Menu_Auto_Add_Control extends \WP_Customize_Control + { + /** + * Type of control, used by JS. + * + * @since 4.3.0 + * @var string + */ + public $type = 'nav_menu_auto_add'; + /** + * No-op since we're using JS template. + * + * @since 4.3.0 + */ + protected function render_content() + { + } + /** + * Render the Underscore template for this control. + * + * @since 4.3.0 + */ + protected function content_template() + { + } + } + /** + * Customize API: WP_Customize_Nav_Menu_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Nav Menu Control Class. + * + * @since 4.3.0 + * + * @see WP_Customize_Control + */ + class WP_Customize_Nav_Menu_Control extends \WP_Customize_Control + { + /** + * Control type. + * + * @since 4.3.0 + * @var string + */ + public $type = 'nav_menu'; + /** + * Don't render the control's content - it uses a JS template instead. + * + * @since 4.3.0 + */ + public function render_content() + { + } + /** + * JS/Underscore template for the control UI. + * + * @since 4.3.0 + */ + public function content_template() + { + } + /** + * Return parameters for this control. + * + * @since 4.3.0 + * + * @return array Exported parameters. + */ + public function json() + { + } + } + /** + * Customize API: WP_Customize_Nav_Menu_Item_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize control to represent the name field for a given menu. + * + * @since 4.3.0 + * + * @see WP_Customize_Control + */ + class WP_Customize_Nav_Menu_Item_Control extends \WP_Customize_Control + { + /** + * Control type. + * + * @since 4.3.0 + * @var string + */ + public $type = 'nav_menu_item'; + /** + * The nav menu item setting. + * + * @since 4.3.0 + * @var WP_Customize_Nav_Menu_Item_Setting + */ + public $setting; + /** + * Constructor. + * + * @since 4.3.0 + * + * @see WP_Customize_Control::__construct() + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + * @param string $id The control ID. + * @param array $args Optional. Arguments to override class property defaults. + * See WP_Customize_Control::__construct() for information + * on accepted arguments. Default empty array. + * @phpstan-param array{ + * instance_number?: int, + * manager?: WP_Customize_Manager, + * id?: string, + * settings?: array, + * setting?: string, + * capability?: string, + * priority?: int, + * section?: string, + * label?: string, + * description?: string, + * choices?: array, + * input_attrs?: array, + * allow_addition?: bool, + * json?: array, + * type?: string, + * active_callback?: callable, + * } $args See WP_Customize_Control::__construct() + */ + public function __construct($manager, $id, $args = array()) + { + } + /** + * Don't render the control's content - it's rendered with a JS template. + * + * @since 4.3.0 + */ + public function render_content() + { + } + /** + * JS/Underscore template for the control UI. + * + * @since 4.3.0 + */ + public function content_template() + { + } + /** + * Return parameters for this control. + * + * @since 4.3.0 + * + * @return array Exported parameters. + */ + public function json() + { + } + } + /** + * Customize API: WP_Customize_Nav_Menu_Item_Setting class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Setting to represent a nav_menu. + * + * Subclass of WP_Customize_Setting to represent a nav_menu taxonomy term, and + * the IDs for the nav_menu_items associated with the nav menu. + * + * @since 4.3.0 + * + * @see WP_Customize_Setting + */ + class WP_Customize_Nav_Menu_Item_Setting extends \WP_Customize_Setting + { + const ID_PATTERN = '/^nav_menu_item\\[(?P<id>-?\\d+)\\]$/'; + const POST_TYPE = 'nav_menu_item'; + const TYPE = 'nav_menu_item'; + /** + * Setting type. + * + * @since 4.3.0 + * @var string + */ + public $type = self::TYPE; + /** + * Default setting value. + * + * @since 4.3.0 + * @var array + * + * @see wp_setup_nav_menu_item() + */ + public $default = array( + // The $menu_item_data for wp_update_nav_menu_item(). + 'object_id' => 0, + 'object' => '', + // Taxonomy name. + 'menu_item_parent' => 0, + // A.K.A. menu-item-parent-id; note that post_parent is different, and not included. + 'position' => 0, + // A.K.A. menu_order. + 'type' => 'custom', + // Note that type_label is not included here. + 'title' => '', + 'url' => '', + 'target' => '', + 'attr_title' => '', + 'description' => '', + 'classes' => '', + 'xfn' => '', + 'status' => 'publish', + 'original_title' => '', + 'nav_menu_term_id' => 0, + // This will be supplied as the $menu_id arg for wp_update_nav_menu_item(). + '_invalid' => \false, + ); + /** + * Default transport. + * + * @since 4.3.0 + * @since 4.5.0 Default changed to 'refresh' + * @var string + */ + public $transport = 'refresh'; + /** + * The post ID represented by this setting instance. This is the db_id. + * + * A negative value represents a placeholder ID for a new menu not yet saved. + * + * @since 4.3.0 + * @var int + */ + public $post_id; + /** + * Storage of pre-setup menu item to prevent wasted calls to wp_setup_nav_menu_item(). + * + * @since 4.3.0 + * @var array|null + */ + protected $value; + /** + * Previous (placeholder) post ID used before creating a new menu item. + * + * This value will be exported to JS via the customize_save_response filter + * so that JavaScript can update the settings to refer to the newly-assigned + * post ID. This value is always negative to indicate it does not refer to + * a real post. + * + * @since 4.3.0 + * @var int + * + * @see WP_Customize_Nav_Menu_Item_Setting::update() + * @see WP_Customize_Nav_Menu_Item_Setting::amend_customize_save_response() + */ + public $previous_post_id; + /** + * When previewing or updating a menu item, this stores the previous nav_menu_term_id + * which ensures that we can apply the proper filters. + * + * @since 4.3.0 + * @var int + */ + public $original_nav_menu_term_id; + /** + * Whether or not update() was called. + * + * @since 4.3.0 + * @var bool + */ + protected $is_updated = \false; + /** + * Status for calling the update method, used in customize_save_response filter. + * + * See {@see 'customize_save_response'}. + * + * When status is inserted, the placeholder post ID is stored in $previous_post_id. + * When status is error, the error is stored in $update_error. + * + * @since 4.3.0 + * @var string updated|inserted|deleted|error + * + * @see WP_Customize_Nav_Menu_Item_Setting::update() + * @see WP_Customize_Nav_Menu_Item_Setting::amend_customize_save_response() + */ + public $update_status; + /** + * Any error object returned by wp_update_nav_menu_item() when setting is updated. + * + * @since 4.3.0 + * @var WP_Error + * + * @see WP_Customize_Nav_Menu_Item_Setting::update() + * @see WP_Customize_Nav_Menu_Item_Setting::amend_customize_save_response() + */ + public $update_error; + /** + * Constructor. + * + * Any supplied $args override class property defaults. + * + * @since 4.3.0 + * + * @throws Exception If $id is not valid for this setting type. + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + * @param string $id A specific ID of the setting. + * Can be a theme mod or option name. + * @param array $args Optional. Setting arguments. + */ + public function __construct(\WP_Customize_Manager $manager, $id, array $args = array()) + { + } + /** + * Clear the cached value when this nav menu item is updated. + * + * @since 4.3.0 + * + * @param int $menu_id The term ID for the menu. + * @param int $menu_item_id The post ID for the menu item. + */ + public function flush_cached_value($menu_id, $menu_item_id) + { + } + /** + * Get the instance data for a given nav_menu_item setting. + * + * @since 4.3.0 + * + * @see wp_setup_nav_menu_item() + * + * @return array|false Instance data array, or false if the item is marked for deletion. + */ + public function value() + { + } + /** + * Get original title. + * + * @since 4.7.0 + * + * @param object $item Nav menu item. + * @return string The original title. + */ + protected function get_original_title($item) + { + } + /** + * Get type label. + * + * @since 4.7.0 + * + * @param object $item Nav menu item. + * @return string The type label. + */ + protected function get_type_label($item) + { + } + /** + * Ensure that the value is fully populated with the necessary properties. + * + * Translates some properties added by wp_setup_nav_menu_item() and removes others. + * + * @since 4.3.0 + * + * @see WP_Customize_Nav_Menu_Item_Setting::value() + */ + protected function populate_value() + { + } + /** + * Handle previewing the setting. + * + * @since 4.3.0 + * @since 4.4.0 Added boolean return value. + * + * @see WP_Customize_Manager::post_value() + * + * @return bool False if method short-circuited due to no-op. + */ + public function preview() + { + } + /** + * Filters the wp_get_nav_menu_items() result to supply the previewed menu items. + * + * @since 4.3.0 + * + * @see wp_get_nav_menu_items() + * + * @param WP_Post[] $items An array of menu item post objects. + * @param WP_Term $menu The menu object. + * @param array $args An array of arguments used to retrieve menu item objects. + * @return WP_Post[] Array of menu item objects. + */ + public function filter_wp_get_nav_menu_items($items, $menu, $args) + { + } + /** + * Re-apply the tail logic also applied on $items by wp_get_nav_menu_items(). + * + * @since 4.3.0 + * + * @see wp_get_nav_menu_items() + * + * @param WP_Post[] $items An array of menu item post objects. + * @param WP_Term $menu The menu object. + * @param array $args An array of arguments used to retrieve menu item objects. + * @return WP_Post[] Array of menu item objects. + */ + public static function sort_wp_get_nav_menu_items($items, $menu, $args) + { + } + /** + * Get the value emulated into a WP_Post and set up as a nav_menu_item. + * + * @since 4.3.0 + * + * @return WP_Post With wp_setup_nav_menu_item() applied. + */ + public function value_as_wp_post_nav_menu_item() + { + } + /** + * Sanitize an input. + * + * Note that parent::sanitize() erroneously does wp_unslash() on $value, but + * we remove that in this override. + * + * @since 4.3.0 + * @since 5.9.0 Renamed `$menu_item_value` to `$value` for PHP 8 named parameter support. + * + * @param array $value The menu item value to sanitize. + * @return array|false|null|WP_Error Null or WP_Error if an input isn't valid. False if it is marked for deletion. + * Otherwise the sanitized value. + */ + public function sanitize($value) + { + } + /** + * Creates/updates the nav_menu_item post for this setting. + * + * Any created menu items will have their assigned post IDs exported to the client + * via the {@see 'customize_save_response'} filter. Likewise, any errors will be + * exported to the client via the customize_save_response() filter. + * + * To delete a menu, the client can send false as the value. + * + * @since 4.3.0 + * + * @see wp_update_nav_menu_item() + * + * @param array|false $value The menu item array to update. If false, then the menu item will be deleted + * entirely. See WP_Customize_Nav_Menu_Item_Setting::$default for what the value + * should consist of. + * @return null|void + */ + protected function update($value) + { + } + /** + * Export data for the JS client. + * + * @since 4.3.0 + * + * @see WP_Customize_Nav_Menu_Item_Setting::update() + * + * @param array $data Additional information passed back to the 'saved' event on `wp.customize`. + * @return array Save response data. + */ + public function amend_customize_save_response($data) + { + } + } + /** + * Customize API: WP_Customize_Nav_Menu_Location_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Menu Location Control Class. + * + * This custom control is only needed for JS. + * + * @since 4.3.0 + * + * @see WP_Customize_Control + */ + class WP_Customize_Nav_Menu_Location_Control extends \WP_Customize_Control + { + /** + * Control type. + * + * @since 4.3.0 + * @var string + */ + public $type = 'nav_menu_location'; + /** + * Location ID. + * + * @since 4.3.0 + * @var string + */ + public $location_id = ''; + /** + * Refresh the parameters passed to JavaScript via JSON. + * + * @since 4.3.0 + * + * @see WP_Customize_Control::to_json() + */ + public function to_json() + { + } + /** + * Render content just like a normal select control. + * + * @since 4.3.0 + * @since 4.9.0 Added a button to create menus. + */ + public function render_content() + { + } + } + /** + * Customize API: WP_Customize_Nav_Menu_Locations_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.9.0 + */ + /** + * Customize Nav Menu Locations Control Class. + * + * @since 4.9.0 + * + * @see WP_Customize_Control + */ + class WP_Customize_Nav_Menu_Locations_Control extends \WP_Customize_Control + { + /** + * Control type. + * + * @since 4.9.0 + * @var string + */ + public $type = 'nav_menu_locations'; + /** + * Don't render the control's content - it uses a JS template instead. + * + * @since 4.9.0 + */ + public function render_content() + { + } + /** + * JS/Underscore template for the control UI. + * + * @since 4.9.0 + */ + public function content_template() + { + } + } + /** + * Customize API: WP_Customize_Nav_Menu_Name_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize control to represent the name field for a given menu. + * + * @since 4.3.0 + * + * @see WP_Customize_Control + */ + class WP_Customize_Nav_Menu_Name_Control extends \WP_Customize_Control + { + /** + * Type of control, used by JS. + * + * @since 4.3.0 + * @var string + */ + public $type = 'nav_menu_name'; + /** + * No-op since we're using JS template. + * + * @since 4.3.0 + */ + protected function render_content() + { + } + /** + * Render the Underscore template for this control. + * + * @since 4.3.0 + */ + protected function content_template() + { + } + } + /** + * Customize API: WP_Customize_Nav_Menu_Section class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Menu Section Class + * + * Custom section only needed in JS. + * + * @since 4.3.0 + * + * @see WP_Customize_Section + */ + class WP_Customize_Nav_Menu_Section extends \WP_Customize_Section + { + /** + * Control type. + * + * @since 4.3.0 + * @var string + */ + public $type = 'nav_menu'; + /** + * Get section parameters for JS. + * + * @since 4.3.0 + * @return array Exported parameters. + */ + public function json() + { + } + } + /** + * Customize API: WP_Customize_Nav_Menu_Setting class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Setting to represent a nav_menu. + * + * Subclass of WP_Customize_Setting to represent a nav_menu taxonomy term, and + * the IDs for the nav_menu_items associated with the nav menu. + * + * @since 4.3.0 + * + * @see wp_get_nav_menu_object() + * @see WP_Customize_Setting + */ + class WP_Customize_Nav_Menu_Setting extends \WP_Customize_Setting + { + const ID_PATTERN = '/^nav_menu\\[(?P<id>-?\\d+)\\]$/'; + const TAXONOMY = 'nav_menu'; + const TYPE = 'nav_menu'; + /** + * Setting type. + * + * @since 4.3.0 + * @var string + */ + public $type = self::TYPE; + /** + * Default setting value. + * + * @since 4.3.0 + * @var array + * + * @see wp_get_nav_menu_object() + */ + public $default = array('name' => '', 'description' => '', 'parent' => 0, 'auto_add' => \false); + /** + * Default transport. + * + * @since 4.3.0 + * @var string + */ + public $transport = 'postMessage'; + /** + * The term ID represented by this setting instance. + * + * A negative value represents a placeholder ID for a new menu not yet saved. + * + * @since 4.3.0 + * @var int + */ + public $term_id; + /** + * Previous (placeholder) term ID used before creating a new menu. + * + * This value will be exported to JS via the {@see 'customize_save_response'} filter + * so that JavaScript can update the settings to refer to the newly-assigned + * term ID. This value is always negative to indicate it does not refer to + * a real term. + * + * @since 4.3.0 + * @var int + * + * @see WP_Customize_Nav_Menu_Setting::update() + * @see WP_Customize_Nav_Menu_Setting::amend_customize_save_response() + */ + public $previous_term_id; + /** + * Whether or not update() was called. + * + * @since 4.3.0 + * @var bool + */ + protected $is_updated = \false; + /** + * Status for calling the update method, used in customize_save_response filter. + * + * See {@see 'customize_save_response'}. + * + * When status is inserted, the placeholder term ID is stored in `$previous_term_id`. + * When status is error, the error is stored in `$update_error`. + * + * @since 4.3.0 + * @var string updated|inserted|deleted|error + * + * @see WP_Customize_Nav_Menu_Setting::update() + * @see WP_Customize_Nav_Menu_Setting::amend_customize_save_response() + */ + public $update_status; + /** + * Any error object returned by wp_update_nav_menu_object() when setting is updated. + * + * @since 4.3.0 + * @var WP_Error + * + * @see WP_Customize_Nav_Menu_Setting::update() + * @see WP_Customize_Nav_Menu_Setting::amend_customize_save_response() + */ + public $update_error; + /** + * Constructor. + * + * Any supplied $args override class property defaults. + * + * @since 4.3.0 + * + * @throws Exception If $id is not valid for this setting type. + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + * @param string $id A specific ID of the setting. + * Can be a theme mod or option name. + * @param array $args Optional. Setting arguments. + */ + public function __construct(\WP_Customize_Manager $manager, $id, array $args = array()) + { + } + /** + * Get the instance data for a given widget setting. + * + * @since 4.3.0 + * + * @see wp_get_nav_menu_object() + * + * @return array Instance data. + */ + public function value() + { + } + /** + * Handle previewing the setting. + * + * @since 4.3.0 + * @since 4.4.0 Added boolean return value + * + * @see WP_Customize_Manager::post_value() + * + * @return bool False if method short-circuited due to no-op. + */ + public function preview() + { + } + /** + * Filters the wp_get_nav_menus() result to ensure the inserted menu object is included, and the deleted one is removed. + * + * @since 4.3.0 + * + * @see wp_get_nav_menus() + * + * @param WP_Term[] $menus An array of menu objects. + * @param array $args An array of arguments used to retrieve menu objects. + * @return WP_Term[] Array of menu objects. + */ + public function filter_wp_get_nav_menus($menus, $args) + { + } + /** + * Temporary non-closure passing of orderby value to function. + * + * @since 4.3.0 + * @var string + * + * @see WP_Customize_Nav_Menu_Setting::filter_wp_get_nav_menus() + * @see WP_Customize_Nav_Menu_Setting::_sort_menus_by_orderby() + */ + protected $_current_menus_sort_orderby; + /** + * Sort menu objects by the class-supplied orderby property. + * + * This is a workaround for a lack of closures. + * + * @since 4.3.0 + * @deprecated 4.7.0 Use wp_list_sort() + * + * @param object $menu1 + * @param object $menu2 + * @return int + * + * @see WP_Customize_Nav_Menu_Setting::filter_wp_get_nav_menus() + */ + protected function _sort_menus_by_orderby($menu1, $menu2) + { + } + /** + * Filters the wp_get_nav_menu_object() result to supply the previewed menu object. + * + * Requesting a nav_menu object by anything but ID is not supported. + * + * @since 4.3.0 + * + * @see wp_get_nav_menu_object() + * + * @param object|null $menu_obj Object returned by wp_get_nav_menu_object(). + * @param string $menu_id ID of the nav_menu term. Requests by slug or name will be ignored. + * @return object|null + */ + public function filter_wp_get_nav_menu_object($menu_obj, $menu_id) + { + } + /** + * Filters the nav_menu_options option to include this menu's auto_add preference. + * + * @since 4.3.0 + * + * @param array $nav_menu_options Nav menu options including auto_add. + * @return array (Maybe) modified nav menu options. + */ + public function filter_nav_menu_options($nav_menu_options) + { + } + /** + * Sanitize an input. + * + * Note that parent::sanitize() erroneously does wp_unslash() on $value, but + * we remove that in this override. + * + * @since 4.3.0 + * + * @param array $value The menu value to sanitize. + * @return array|false|null Null if an input isn't valid. False if it is marked for deletion. + * Otherwise the sanitized value. + */ + public function sanitize($value) + { + } + /** + * Storage for data to be sent back to client in customize_save_response filter. + * + * See {@see 'customize_save_response'}. + * + * @since 4.3.0 + * @var array + * + * @see WP_Customize_Nav_Menu_Setting::amend_customize_save_response() + */ + protected $_widget_nav_menu_updates = array(); + /** + * Create/update the nav_menu term for this setting. + * + * Any created menus will have their assigned term IDs exported to the client + * via the {@see 'customize_save_response'} filter. Likewise, any errors will be exported + * to the client via the customize_save_response() filter. + * + * To delete a menu, the client can send false as the value. + * + * @since 4.3.0 + * + * @see wp_update_nav_menu_object() + * + * @param array|false $value { + * The value to update. Note that slug cannot be updated via wp_update_nav_menu_object(). + * If false, then the menu will be deleted entirely. + * + * @type string $name The name of the menu to save. + * @type string $description The term description. Default empty string. + * @type int $parent The id of the parent term. Default 0. + * @type bool $auto_add Whether pages will auto_add to this menu. Default false. + * } + * @return null|void + * @phpstan-param false|array{ + * name?: string, + * description?: string, + * parent?: int, + * auto_add?: bool, + * } $value + */ + protected function update($value) + { + } + /** + * Updates a nav_menu_options array. + * + * @since 4.3.0 + * + * @see WP_Customize_Nav_Menu_Setting::filter_nav_menu_options() + * @see WP_Customize_Nav_Menu_Setting::update() + * + * @param array $nav_menu_options Array as returned by get_option( 'nav_menu_options' ). + * @param int $menu_id The term ID for the given menu. + * @param bool $auto_add Whether to auto-add or not. + * @return array (Maybe) modified nav_menu_options array. + */ + protected function filter_nav_menu_options_value($nav_menu_options, $menu_id, $auto_add) + { + } + /** + * Export data for the JS client. + * + * @since 4.3.0 + * + * @see WP_Customize_Nav_Menu_Setting::update() + * + * @param array $data Additional information passed back to the 'saved' event on `wp.customize`. + * @return array Export data. + */ + public function amend_customize_save_response($data) + { + } + } + /** + * Customize API: WP_Customize_Nav_Menus_Panel class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Nav Menus Panel Class + * + * Needed to add screen options. + * + * @since 4.3.0 + * + * @see WP_Customize_Panel + */ + class WP_Customize_Nav_Menus_Panel extends \WP_Customize_Panel + { + /** + * Control type. + * + * @since 4.3.0 + * @var string + */ + public $type = 'nav_menus'; + /** + * Render screen options for Menus. + * + * @since 4.3.0 + */ + public function render_screen_options() + { + } + /** + * Returns the advanced options for the nav menus page. + * + * Link title attribute added as it's a relatively advanced concept for new users. + * + * @since 4.3.0 + * @deprecated 4.5.0 Deprecated in favor of wp_nav_menu_manage_columns(). + */ + public function wp_nav_menu_manage_columns() + { + } + /** + * An Underscore (JS) template for this panel's content (but not its container). + * + * Class variables for this panel class are available in the `data` JS object; + * export custom variables by overriding WP_Customize_Panel::json(). + * + * @since 4.3.0 + * + * @see WP_Customize_Panel::print_template() + */ + protected function content_template() + { + } + } + /** + * Customize control class for new menus. + * + * @since 4.3.0 + * @deprecated 4.9.0 This class is no longer used as of the menu creation UX introduced in #40104. + * + * @see WP_Customize_Control + */ + class WP_Customize_New_Menu_Control extends \WP_Customize_Control + { + /** + * Control type. + * + * @since 4.3.0 + * @var string + */ + public $type = 'new_menu'; + /** + * Constructor. + * + * @since 4.9.0 + * @deprecated 4.9.0 + * + * @see WP_Customize_Control::__construct() + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + * @param string $id The control ID. + * @param array $args Optional. Arguments to override class property defaults. + * See WP_Customize_Control::__construct() for information + * on accepted arguments. Default empty array. + * @phpstan-param array{ + * instance_number?: int, + * manager?: WP_Customize_Manager, + * id?: string, + * settings?: array, + * setting?: string, + * capability?: string, + * priority?: int, + * section?: string, + * label?: string, + * description?: string, + * choices?: array, + * input_attrs?: array, + * allow_addition?: bool, + * json?: array, + * type?: string, + * active_callback?: callable, + * } $args See WP_Customize_Control::__construct() + */ + public function __construct(\WP_Customize_Manager $manager, $id, array $args = array()) + { + } + /** + * Render the control's content. + * + * @since 4.3.0 + * @deprecated 4.9.0 + */ + public function render_content() + { + } + } + /** + * Customize Menu Section Class + * + * @since 4.3.0 + * @deprecated 4.9.0 This class is no longer used as of the menu creation UX introduced in #40104. + * + * @see WP_Customize_Section + */ + class WP_Customize_New_Menu_Section extends \WP_Customize_Section + { + /** + * Control type. + * + * @since 4.3.0 + * @var string + */ + public $type = 'new_menu'; + /** + * Constructor. + * + * Any supplied $args override class property defaults. + * + * @since 4.9.0 + * @deprecated 4.9.0 + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + * @param string $id A specific ID of the section. + * @param array $args Section arguments. + */ + public function __construct(\WP_Customize_Manager $manager, $id, array $args = array()) + { + } + /** + * Render the section, and the controls that have been added to it. + * + * @since 4.3.0 + * @deprecated 4.9.0 + */ + protected function render() + { + } + } + /** + * Customize API: WP_Customize_Partial class + * + * @package WordPress + * @subpackage Customize + * @since 4.5.0 + */ + /** + * Core Customizer class for implementing selective refresh partials. + * + * Representation of a rendered region in the previewed page that gets + * selectively refreshed when an associated setting is changed. + * This class is analogous of WP_Customize_Control. + * + * @since 4.5.0 + */ + #[\AllowDynamicProperties] + class WP_Customize_Partial + { + /** + * Component. + * + * @since 4.5.0 + * @var WP_Customize_Selective_Refresh + */ + public $component; + /** + * Unique identifier for the partial. + * + * If the partial is used to display a single setting, this would generally + * be the same as the associated setting's ID. + * + * @since 4.5.0 + * @var string + */ + public $id; + /** + * Parsed ID. + * + * @since 4.5.0 + * @var array { + * @type string $base ID base. + * @type array $keys Keys for multidimensional. + * } + * @phpstan-var array{ + * base: string, + * keys: array, + * } + */ + protected $id_data = array(); + /** + * Type of this partial. + * + * @since 4.5.0 + * @var string + */ + public $type = 'default'; + /** + * The jQuery selector to find the container element for the partial. + * + * @since 4.5.0 + * @var string + */ + public $selector; + /** + * IDs for settings tied to the partial. + * + * @since 4.5.0 + * @var string[] + */ + public $settings; + /** + * The ID for the setting that this partial is primarily responsible for rendering. + * + * If not supplied, it will default to the ID of the first setting. + * + * @since 4.5.0 + * @var string + */ + public $primary_setting; + /** + * Capability required to edit this partial. + * + * Normally this is empty and the capability is derived from the capabilities + * of the associated `$settings`. + * + * @since 4.5.0 + * @var string + */ + public $capability; + /** + * Render callback. + * + * @since 4.5.0 + * + * @see WP_Customize_Partial::render() + * @var callable Callback is called with one argument, the instance of + * WP_Customize_Partial. The callback can either echo the + * partial or return the partial as a string, or return false if error. + */ + public $render_callback; + /** + * Whether the container element is included in the partial, or if only the contents are rendered. + * + * @since 4.5.0 + * @var bool + */ + public $container_inclusive = \false; + /** + * Whether to refresh the entire preview in case a partial cannot be refreshed. + * + * A partial render is considered a failure if the render_callback returns false. + * + * @since 4.5.0 + * @var bool + */ + public $fallback_refresh = \true; + /** + * Constructor. + * + * Supplied `$args` override class property defaults. + * + * If `$args['settings']` is not defined, use the $id as the setting ID. + * + * @since 4.5.0 + * + * @param WP_Customize_Selective_Refresh $component Customize Partial Refresh plugin instance. + * @param string $id Control ID. + * @param array $args { + * Optional. Array of properties for the new Partials object. Default empty array. + * + * @type string $type Type of the partial to be created. + * @type string $selector The jQuery selector to find the container element for the partial, that is, + * a partial's placement. + * @type string[] $settings IDs for settings tied to the partial. If undefined, `$id` will be used. + * @type string $primary_setting The ID for the setting that this partial is primarily responsible for + * rendering. If not supplied, it will default to the ID of the first setting. + * @type string $capability Capability required to edit this partial. + * Normally this is empty and the capability is derived from the capabilities + * of the associated `$settings`. + * @type callable $render_callback Render callback. + * Callback is called with one argument, the instance of WP_Customize_Partial. + * The callback can either echo the partial or return the partial as a string, + * or return false if error. + * @type bool $container_inclusive Whether the container element is included in the partial, or if only + * the contents are rendered. + * @type bool $fallback_refresh Whether to refresh the entire preview in case a partial cannot be refreshed. + * A partial render is considered a failure if the render_callback returns + * false. + * } + * @phpstan-param array{ + * type?: string, + * selector?: string, + * settings?: string[], + * primary_setting?: string, + * capability?: string, + * render_callback?: callable, + * container_inclusive?: bool, + * fallback_refresh?: bool, + * } $args + */ + public function __construct(\WP_Customize_Selective_Refresh $component, $id, $args = array()) + { + } + /** + * Retrieves parsed ID data for multidimensional setting. + * + * @since 4.5.0 + * + * @return array { + * ID data for multidimensional partial. + * + * @type string $base ID base. + * @type array $keys Keys for multidimensional array. + * } + * @phpstan-return array{ + * base: string, + * keys: array, + * } + */ + public final function id_data() + { + } + /** + * Renders the template partial involving the associated settings. + * + * @since 4.5.0 + * + * @param array $container_context Optional. Array of context data associated with the target container (placement). + * Default empty array. + * @return string|array|false The rendered partial as a string, raw data array (for client-side JS template), + * or false if no render applied. + */ + public final function render($container_context = array()) + { + } + /** + * Default callback used when invoking WP_Customize_Control::render(). + * + * Note that this method may echo the partial *or* return the partial as + * a string or array, but not both. Output buffering is performed when this + * is called. Subclasses can override this with their specific logic, or they + * may provide an 'render_callback' argument to the constructor. + * + * This method may return an HTML string for straight DOM injection, or it + * may return an array for supporting Partial JS subclasses to render by + * applying to client-side templating. + * + * @since 4.5.0 + * + * @param WP_Customize_Partial $partial Partial. + * @param array $context Context. + * @return string|array|false + */ + public function render_callback(\WP_Customize_Partial $partial, $context = array()) + { + } + /** + * Retrieves the data to export to the client via JSON. + * + * @since 4.5.0 + * + * @return array Array of parameters passed to the JavaScript. + */ + public function json() + { + } + /** + * Checks if the user can refresh this partial. + * + * Returns false if the user cannot manipulate one of the associated settings, + * or if one of the associated settings does not exist. + * + * @since 4.5.0 + * + * @return bool False if user can't edit one of the related settings, + * or if one of the associated settings does not exist. + */ + public final function check_capabilities() + { + } + } + /** + * Customize API: WP_Customize_Selective_Refresh class + * + * @package WordPress + * @subpackage Customize + * @since 4.5.0 + */ + /** + * Core Customizer class for implementing selective refresh. + * + * @since 4.5.0 + */ + #[\AllowDynamicProperties] + final class WP_Customize_Selective_Refresh + { + /** + * Query var used in requests to render partials. + * + * @since 4.5.0 + */ + const RENDER_QUERY_VAR = 'wp_customize_render_partials'; + /** + * Customize manager. + * + * @since 4.5.0 + * @var WP_Customize_Manager + */ + public $manager; + /** + * Plugin bootstrap for Partial Refresh functionality. + * + * @since 4.5.0 + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + */ + public function __construct(\WP_Customize_Manager $manager) + { + } + /** + * Retrieves the registered partials. + * + * @since 4.5.0 + * + * @return array Partials. + */ + public function partials() + { + } + /** + * Adds a partial. + * + * @since 4.5.0 + * + * @see WP_Customize_Partial::__construct() + * + * @param WP_Customize_Partial|string $id Customize Partial object, or Partial ID. + * @param array $args Optional. Array of properties for the new Partials object. + * See WP_Customize_Partial::__construct() for information + * on accepted arguments. Default empty array. + * @return WP_Customize_Partial The instance of the partial that was added. + * @phpstan-param array{ + * type?: string, + * selector?: string, + * settings?: string[], + * primary_setting?: string, + * capability?: string, + * render_callback?: callable, + * container_inclusive?: bool, + * fallback_refresh?: bool, + * } $args See WP_Customize_Partial::__construct() + */ + public function add_partial($id, $args = array()) + { + } + /** + * Retrieves a partial. + * + * @since 4.5.0 + * + * @param string $id Customize Partial ID. + * @return WP_Customize_Partial|null The partial, if set. Otherwise null. + */ + public function get_partial($id) + { + } + /** + * Removes a partial. + * + * @since 4.5.0 + * + * @param string $id Customize Partial ID. + */ + public function remove_partial($id) + { + } + /** + * Initializes the Customizer preview. + * + * @since 4.5.0 + */ + public function init_preview() + { + } + /** + * Enqueues preview scripts. + * + * @since 4.5.0 + */ + public function enqueue_preview_scripts() + { + } + /** + * Exports data in preview after it has finished rendering so that partials can be added at runtime. + * + * @since 4.5.0 + */ + public function export_preview_data() + { + } + /** + * Registers dynamically-created partials. + * + * @since 4.5.0 + * + * @see WP_Customize_Manager::add_dynamic_settings() + * + * @param string[] $partial_ids Array of the partial IDs to add. + * @return WP_Customize_Partial[] Array of added WP_Customize_Partial instances. + */ + public function add_dynamic_partials($partial_ids) + { + } + /** + * Checks whether the request is for rendering partials. + * + * Note that this will not consider whether the request is authorized or valid, + * just that essentially the route is a match. + * + * @since 4.5.0 + * + * @return bool Whether the request is for rendering partials. + */ + public function is_render_partials_request() + { + } + /** + * Handles PHP errors triggered during rendering the partials. + * + * These errors will be relayed back to the client in the Ajax response. + * + * @since 4.5.0 + * + * @param int $errno Error number. + * @param string $errstr Error string. + * @param string $errfile Error file. + * @param int $errline Error line. + * @return true Always true. + */ + public function handle_error($errno, $errstr, $errfile = \null, $errline = \null) + { + } + /** + * Handles the Ajax request to return the rendered partials for the requested placements. + * + * @since 4.5.0 + */ + public function handle_render_partials_request() + { + } + } + /** + * Customize API: WP_Customize_Sidebar_Section class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customizer section representing widget area (sidebar). + * + * @since 4.1.0 + * + * @see WP_Customize_Section + */ + class WP_Customize_Sidebar_Section extends \WP_Customize_Section + { + /** + * Type of this section. + * + * @since 4.1.0 + * @var string + */ + public $type = 'sidebar'; + /** + * Unique identifier. + * + * @since 4.1.0 + * @var string + */ + public $sidebar_id; + /** + * Gather the parameters passed to client JavaScript via JSON. + * + * @since 4.1.0 + * + * @return array The array to be exported to the client as JSON. + */ + public function json() + { + } + /** + * Whether the current sidebar is rendered on the page. + * + * @since 4.1.0 + * + * @return bool Whether sidebar is rendered. + */ + public function active_callback() + { + } + } + /** + * Customize API: WP_Customize_Site_Icon_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Site Icon control class. + * + * Used only for custom functionality in JavaScript. + * + * @since 4.3.0 + * + * @see WP_Customize_Cropped_Image_Control + */ + class WP_Customize_Site_Icon_Control extends \WP_Customize_Cropped_Image_Control + { + /** + * Control type. + * + * @since 4.3.0 + * @var string + */ + public $type = 'site_icon'; + /** + * Constructor. + * + * @since 4.3.0 + * + * @see WP_Customize_Control::__construct() + * + * @param WP_Customize_Manager $manager Customizer bootstrap instance. + * @param string $id Control ID. + * @param array $args Optional. Arguments to override class property defaults. + * See WP_Customize_Control::__construct() for information + * on accepted arguments. Default empty array. + * @phpstan-param array{ + * instance_number?: int, + * manager?: WP_Customize_Manager, + * id?: string, + * settings?: array, + * setting?: string, + * capability?: string, + * priority?: int, + * section?: string, + * label?: string, + * description?: string, + * choices?: array, + * input_attrs?: array, + * allow_addition?: bool, + * json?: array, + * type?: string, + * active_callback?: callable, + * } $args See WP_Customize_Control::__construct() + */ + public function __construct($manager, $id, $args = array()) + { + } + /** + * Renders a JS template for the content of the site icon control. + * + * @since 4.5.0 + */ + public function content_template() + { + } + } + /** + * Customize API: WP_Customize_Theme_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Theme Control class. + * + * @since 4.2.0 + * + * @see WP_Customize_Control + */ + class WP_Customize_Theme_Control extends \WP_Customize_Control + { + /** + * Customize control type. + * + * @since 4.2.0 + * @var string + */ + public $type = 'theme'; + /** + * Theme object. + * + * @since 4.2.0 + * @var WP_Theme + */ + public $theme; + /** + * Refresh the parameters passed to the JavaScript via JSON. + * + * @since 4.2.0 + * + * @see WP_Customize_Control::to_json() + */ + public function to_json() + { + } + /** + * Don't render the control content from PHP, as it's rendered via JS on load. + * + * @since 4.2.0 + */ + public function render_content() + { + } + /** + * Render a JS template for theme display. + * + * @since 4.2.0 + */ + public function content_template() + { + } + } + /** + * Customize API: WP_Customize_Themes_Panel class + * + * @package WordPress + * @subpackage Customize + * @since 4.9.0 + */ + /** + * Customize Themes Panel Class + * + * @since 4.9.0 + * + * @see WP_Customize_Panel + */ + class WP_Customize_Themes_Panel extends \WP_Customize_Panel + { + /** + * Panel type. + * + * @since 4.9.0 + * @var string + */ + public $type = 'themes'; + /** + * An Underscore (JS) template for rendering this panel's container. + * + * The themes panel renders a custom panel heading with the active theme and a switch themes button. + * + * @see WP_Customize_Panel::print_template() + * + * @since 4.9.0 + */ + protected function render_template() + { + } + /** + * An Underscore (JS) template for this panel's content (but not its container). + * + * Class variables for this panel class are available in the `data` JS object; + * export custom variables by overriding WP_Customize_Panel::json(). + * + * @since 4.9.0 + * + * @see WP_Customize_Panel::print_template() + */ + protected function content_template() + { + } + } + /** + * Customize API: WP_Customize_Themes_Section class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Customize Themes Section class. + * + * A UI container for theme controls, which are displayed within sections. + * + * @since 4.2.0 + * + * @see WP_Customize_Section + */ + class WP_Customize_Themes_Section extends \WP_Customize_Section + { + /** + * Section type. + * + * @since 4.2.0 + * @var string + */ + public $type = 'themes'; + /** + * Theme section action. + * + * Defines the type of themes to load (installed, wporg, etc.). + * + * @since 4.9.0 + * @var string + */ + public $action = ''; + /** + * Theme section filter type. + * + * Determines whether filters are applied to loaded (local) themes or by initiating a new remote query (remote). + * When filtering is local, the initial themes query is not paginated by default. + * + * @since 4.9.0 + * @var string + */ + public $filter_type = 'local'; + /** + * Get section parameters for JS. + * + * @since 4.9.0 + * @return array Exported parameters. + */ + public function json() + { + } + /** + * Render a themes section as a JS template. + * + * The template is only rendered by PHP once, so all actions are prepared at once on the server side. + * + * @since 4.9.0 + */ + protected function render_template() + { + } + /** + * Render the filter bar portion of a themes section as a JS template. + * + * The template is only rendered by PHP once, so all actions are prepared at once on the server side. + * The filter bar container is rendered by @see `render_template()`. + * + * @since 4.9.0 + */ + protected function filter_bar_content_template() + { + } + /** + * Render the filter drawer portion of a themes section as a JS template. + * + * The filter bar container is rendered by @see `render_template()`. + * + * @since 4.9.0 + */ + protected function filter_drawer_content_template() + { + } + } + /** + * Customize API: WP_Sidebar_Block_Editor_Control class. + * + * @package WordPress + * @subpackage Customize + * @since 5.8.0 + */ + /** + * Core class used to implement the widgets block editor control in the + * customizer. + * + * @since 5.8.0 + * + * @see WP_Customize_Control + */ + class WP_Sidebar_Block_Editor_Control extends \WP_Customize_Control + { + /** + * The control type. + * + * @since 5.8.0 + * + * @var string + */ + public $type = 'sidebar_block_editor'; + /** + * Render the widgets block editor container. + * + * @since 5.8.0 + */ + public function render_content() + { + } + } + /** + * Customize API: WP_Widget_Area_Customize_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Widget Area Customize Control class. + * + * @since 3.9.0 + * + * @see WP_Customize_Control + */ + class WP_Widget_Area_Customize_Control extends \WP_Customize_Control + { + /** + * Customize control type. + * + * @since 3.9.0 + * @var string + */ + public $type = 'sidebar_widgets'; + /** + * Sidebar ID. + * + * @since 3.9.0 + * @var int|string + */ + public $sidebar_id; + /** + * Refreshes the parameters passed to the JavaScript via JSON. + * + * @since 3.9.0 + */ + public function to_json() + { + } + /** + * Renders the control's content. + * + * @since 3.9.0 + */ + public function render_content() + { + } + } + /** + * Customize API: WP_Widget_Form_Customize_Control class + * + * @package WordPress + * @subpackage Customize + * @since 4.4.0 + */ + /** + * Widget Form Customize Control class. + * + * @since 3.9.0 + * + * @see WP_Customize_Control + */ + class WP_Widget_Form_Customize_Control extends \WP_Customize_Control + { + /** + * Customize control type. + * + * @since 3.9.0 + * @var string + */ + public $type = 'widget_form'; + /** + * Widget ID. + * + * @since 3.9.0 + * @var string + */ + public $widget_id; + /** + * Widget ID base. + * + * @since 3.9.0 + * @var string + */ + public $widget_id_base; + /** + * Sidebar ID. + * + * @since 3.9.0 + * @var string + */ + public $sidebar_id; + /** + * Widget status. + * + * @since 3.9.0 + * @var bool True if new, false otherwise. Default false. + */ + public $is_new = \false; + /** + * Widget width. + * + * @since 3.9.0 + * @var int + */ + public $width; + /** + * Widget height. + * + * @since 3.9.0 + * @var int + */ + public $height; + /** + * Widget mode. + * + * @since 3.9.0 + * @var bool True if wide, false otherwise. Default false. + */ + public $is_wide = \false; + /** + * Gather control params for exporting to JavaScript. + * + * @since 3.9.0 + * + * @global array $wp_registered_widgets + */ + public function to_json() + { + } + /** + * Override render_content to be no-op since content is exported via to_json for deferred embedding. + * + * @since 3.9.0 + */ + public function render_content() + { + } + /** + * Whether the current widget is rendered on the page. + * + * @since 4.0.0 + * + * @return bool Whether the widget is rendered. + */ + public function active_callback() + { + } + } + class wp_atom_server + { + public function __call($name, $arguments) + { + } + public static function __callStatic($name, $arguments) + { + } + } + /** + * Translation_Entry class encapsulates a translatable string. + */ + #[\AllowDynamicProperties] + class Translation_Entry + { + /** + * Whether the entry contains a string and its plural form, default is false. + * + * @var bool + */ + public $is_plural = \false; + public $context = \null; + public $singular = \null; + public $plural = \null; + public $translations = array(); + public $translator_comments = ''; + public $extracted_comments = ''; + public $references = array(); + public $flags = array(); + /** + * @param array $args { + * Arguments array, supports the following keys: + * + * @type string $singular The string to translate, if omitted an + * empty entry will be created. + * @type string $plural The plural form of the string, setting + * this will set `$is_plural` to true. + * @type array $translations Translations of the string and possibly + * its plural forms. + * @type string $context A string differentiating two equal strings + * used in different contexts. + * @type string $translator_comments Comments left by translators. + * @type string $extracted_comments Comments left by developers. + * @type array $references Places in the code this string is used, in + * relative_to_root_path/file.php:linenum form. + * @type array $flags Flags like php-format. + * } + * @phpstan-param array{ + * singular?: string, + * plural?: string, + * translations?: array, + * context?: string, + * translator_comments?: string, + * extracted_comments?: string, + * references?: array, + * flags?: array, + * } $args + */ + public function __construct($args = array()) + { + } + /** + * PHP4 constructor. + * + * @deprecated 5.4.0 Use __construct() instead. + * + * @see Translation_Entry::__construct() + */ + public function Translation_Entry($args = array()) + { + } + /** + * Generates a unique key for this entry. + * + * @return string|false The key or false if the entry is null. + */ + public function key() + { + } + /** + * @param object $other + */ + public function merge_with(&$other) + { + } + } + #[\AllowDynamicProperties] + class Translations + { + public $entries = array(); + public $headers = array(); + /** + * Add entry to the PO structure + * + * @param array|Translation_Entry $entry + * @return bool true on success, false if the entry doesn't have a key + */ + public function add_entry($entry) + { + } + /** + * @param array|Translation_Entry $entry + * @return bool + */ + public function add_entry_or_merge($entry) + { + } + /** + * Sets $header PO header to $value + * + * If the header already exists, it will be overwritten + * + * TODO: this should be out of this class, it is gettext specific + * + * @param string $header header name, without trailing : + * @param string $value header value, without trailing \n + */ + public function set_header($header, $value) + { + } + /** + * @param array $headers + */ + public function set_headers($headers) + { + } + /** + * @param string $header + */ + public function get_header($header) + { + } + /** + * @param Translation_Entry $entry + */ + public function translate_entry(&$entry) + { + } + /** + * @param string $singular + * @param string $context + * @return string + */ + public function translate($singular, $context = \null) + { + } + /** + * Given the number of items, returns the 0-based index of the plural form to use + * + * Here, in the base Translations class, the common logic for English is implemented: + * 0 if there is one element, 1 otherwise + * + * This function should be overridden by the subclasses. For example MO/PO can derive the logic + * from their headers. + * + * @param int $count number of items + */ + public function select_plural_form($count) + { + } + /** + * @return int + */ + public function get_plural_forms_count() + { + } + /** + * @param string $singular + * @param string $plural + * @param int $count + * @param string $context + */ + public function translate_plural($singular, $plural, $count, $context = \null) + { + } + /** + * Merge $other in the current object. + * + * @param Object $other Another Translation object, whose translations will be merged in this one (passed by reference). + */ + public function merge_with(&$other) + { + } + /** + * @param object $other + */ + public function merge_originals_with(&$other) + { + } + } + class Gettext_Translations extends \Translations + { + /** + * Number of plural forms. + * + * @var int + */ + public $_nplurals; + /** + * Callback to retrieve the plural form. + * + * @var callable + */ + public $_gettext_select_plural_form; + /** + * The gettext implementation of select_plural_form. + * + * It lives in this class, because there are more than one descendand, which will use it and + * they can't share it effectively. + * + * @param int $count + */ + public function gettext_select_plural_form($count) + { + } + /** + * @param string $header + * @return array + */ + public function nplurals_and_expression_from_header($header) + { + } + /** + * Makes a function, which will return the right translation index, according to the + * plural forms header + * + * @param int $nplurals + * @param string $expression + */ + public function make_plural_form_function($nplurals, $expression) + { + } + /** + * Adds parentheses to the inner parts of ternary operators in + * plural expressions, because PHP evaluates ternary oerators from left to right + * + * @param string $expression the expression without parentheses + * @return string the expression with parentheses added + */ + public function parenthesize_plural_exression($expression) + { + } + /** + * @param string $translation + * @return array + */ + public function make_headers($translation) + { + } + /** + * @param string $header + * @param string $value + */ + public function set_header($header, $value) + { + } + } + class MO extends \Gettext_Translations + { + /** + * Number of plural forms. + * + * @var int + */ + public $_nplurals = 2; + /** + * Returns the loaded MO file. + * + * @return string The loaded MO file. + */ + public function get_filename() + { + } + /** + * Fills up with the entries from MO file $filename + * + * @param string $filename MO file to load + * @return bool True if the import from file was successful, otherwise false. + */ + public function import_from_file($filename) + { + } + /** + * @param string $filename + * @return bool + */ + public function export_to_file($filename) + { + } + /** + * @return string|false + */ + public function export() + { + } + /** + * @param Translation_Entry $entry + * @return bool + */ + public function is_entry_good_for_export($entry) + { + } + /** + * @param resource $fh + * @return true + */ + public function export_to_file_handle($fh) + { + } + /** + * @param Translation_Entry $entry + * @return string + */ + public function export_original($entry) + { + } + /** + * @param Translation_Entry $entry + * @return string + */ + public function export_translations($entry) + { + } + /** + * @return string + */ + public function export_headers() + { + } + /** + * @param int $magic + * @return string|false + */ + public function get_byteorder($magic) + { + } + /** + * @param POMO_FileReader $reader + * @return bool True if the import was successful, otherwise false. + */ + public function import_from_reader($reader) + { + } + /** + * Build a Translation_Entry from original string and translation strings, + * found in a MO file + * + * @static + * @param string $original original string to translate from MO file. Might contain + * 0x04 as context separator or 0x00 as singular/plural separator + * @param string $translation translation string from MO file. Might contain + * 0x00 as a plural translations separator + * @return Translation_Entry Entry instance. + */ + public function &make_entry($original, $translation) + { + } + /** + * @param int $count + * @return string + */ + public function select_plural_form($count) + { + } + /** + * @return int + */ + public function get_plural_forms_count() + { + } + } + #[\AllowDynamicProperties] + class Plural_Forms + { + /** + * Operator characters. + * + * @since 4.9.0 + * @var string OP_CHARS Operator characters. + */ + const OP_CHARS = '|&><!=%?:'; + /** + * Valid number characters. + * + * @since 4.9.0 + * @var string NUM_CHARS Valid number characters. + */ + const NUM_CHARS = '0123456789'; + /** + * Operator precedence. + * + * Operator precedence from highest to lowest. Higher numbers indicate + * higher precedence, and are executed first. + * + * @see https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence + * + * @since 4.9.0 + * @var array $op_precedence Operator precedence from highest to lowest. + */ + protected static $op_precedence = array('%' => 6, '<' => 5, '<=' => 5, '>' => 5, '>=' => 5, '==' => 4, '!=' => 4, '&&' => 3, '||' => 2, '?:' => 1, '?' => 1, '(' => 0, ')' => 0); + /** + * Tokens generated from the string. + * + * @since 4.9.0 + * @var array $tokens List of tokens. + */ + protected $tokens = array(); + /** + * Cache for repeated calls to the function. + * + * @since 4.9.0 + * @var array $cache Map of $n => $result + */ + protected $cache = array(); + /** + * Constructor. + * + * @since 4.9.0 + * + * @param string $str Plural function (just the bit after `plural=` from Plural-Forms) + */ + public function __construct($str) + { + } + /** + * Parse a Plural-Forms string into tokens. + * + * Uses the shunting-yard algorithm to convert the string to Reverse Polish + * Notation tokens. + * + * @since 4.9.0 + * + * @throws Exception If there is a syntax or parsing error with the string. + * + * @param string $str String to parse. + */ + protected function parse($str) + { + } + /** + * Get the plural form for a number. + * + * Caches the value for repeated calls. + * + * @since 4.9.0 + * + * @param int $num Number to get plural form for. + * @return int Plural form value. + */ + public function get($num) + { + } + /** + * Execute the plural form function. + * + * @since 4.9.0 + * + * @throws Exception If the plural form value cannot be calculated. + * + * @param int $n Variable "n" to substitute. + * @return int Plural form value. + */ + public function execute($n) + { + } + } + class PO extends \Gettext_Translations + { + public $comments_before_headers = ''; + /** + * Exports headers to a PO entry + * + * @return string msgid/msgstr PO entry for this PO file headers, doesn't contain newline at the end + */ + public function export_headers() + { + } + /** + * Exports all entries to PO format + * + * @return string sequence of mgsgid/msgstr PO strings, doesn't containt newline at the end + */ + public function export_entries() + { + } + /** + * Exports the whole PO file as a string + * + * @param bool $include_headers whether to include the headers in the export + * @return string ready for inclusion in PO file string for headers and all the enrtries + */ + public function export($include_headers = \true) + { + } + /** + * Same as {@link export}, but writes the result to a file + * + * @param string $filename Where to write the PO string. + * @param bool $include_headers Whether to include the headers in the export. + * @return bool true on success, false on error + */ + public function export_to_file($filename, $include_headers = \true) + { + } + /** + * Text to include as a comment before the start of the PO contents + * + * Doesn't need to include # in the beginning of lines, these are added automatically + * + * @param string $text Text to include as a comment. + */ + public function set_comment_before_headers($text) + { + } + /** + * Formats a string in PO-style + * + * @param string $string the string to format + * @return string the poified string + */ + public static function poify($string) + { + } + /** + * Gives back the original string from a PO-formatted string + * + * @param string $string PO-formatted string + * @return string enascaped string + */ + public static function unpoify($string) + { + } + /** + * Inserts $with in the beginning of every new line of $string and + * returns the modified string + * + * @param string $string prepend lines in this string + * @param string $with prepend lines with this string + */ + public static function prepend_each_line($string, $with) + { + } + /** + * Prepare a text as a comment -- wraps the lines and prepends # + * and a special character to each line + * + * @access private + * @param string $text the comment text + * @param string $char character to denote a special PO comment, + * like :, default is a space + */ + public static function comment_block($text, $char = ' ') + { + } + /** + * Builds a string from the entry for inclusion in PO file + * + * @param Translation_Entry $entry the entry to convert to po string. + * @return string|false PO-style formatted string for the entry or + * false if the entry is empty + */ + public static function export_entry($entry) + { + } + public static function match_begin_and_end_newlines($translation, $original) + { + } + /** + * @param string $filename + * @return bool + */ + public function import_from_file($filename) + { + } + /** + * Helper function for read_entry + * + * @param string $context + * @return bool + */ + protected static function is_final($context) + { + } + /** + * @param resource $f + * @param int $lineno + * @return null|false|array + */ + public function read_entry($f, $lineno = 0) + { + } + /** + * @param resource $f + * @param string $action + * @return bool + */ + public function read_line($f, $action = 'read') + { + } + /** + * @param Translation_Entry $entry + * @param string $po_comment_line + */ + public function add_comment_to_entry(&$entry, $po_comment_line) + { + } + /** + * @param string $s + * @return string + */ + public static function trim_quotes($s) + { + } + } + #[\AllowDynamicProperties] + class POMO_Reader + { + public $endian = 'little'; + public $_pos; + public $is_overloaded; + /** + * PHP5 constructor. + */ + public function __construct() + { + } + /** + * PHP4 constructor. + * + * @deprecated 5.4.0 Use __construct() instead. + * + * @see POMO_Reader::__construct() + */ + public function POMO_Reader() + { + } + /** + * Sets the endianness of the file. + * + * @param string $endian Set the endianness of the file. Accepts 'big', or 'little'. + */ + public function setEndian($endian) + { + } + /** + * Reads a 32bit Integer from the Stream + * + * @return mixed The integer, corresponding to the next 32 bits from + * the stream of false if there are not enough bytes or on error + */ + public function readint32() + { + } + /** + * Reads an array of 32-bit Integers from the Stream + * + * @param int $count How many elements should be read + * @return mixed Array of integers or false if there isn't + * enough data or on error + */ + public function readint32array($count) + { + } + /** + * @param string $string + * @param int $start + * @param int $length + * @return string + */ + public function substr($string, $start, $length) + { + } + /** + * @param string $string + * @return int + */ + public function strlen($string) + { + } + /** + * @param string $string + * @param int $chunk_size + * @return array + */ + public function str_split($string, $chunk_size) + { + } + /** + * @return int + */ + public function pos() + { + } + /** + * @return true + */ + public function is_resource() + { + } + /** + * @return true + */ + public function close() + { + } + } + class POMO_FileReader extends \POMO_Reader + { + /** + * File pointer resource. + * + * @var resource|false + */ + public $_f; + /** + * @param string $filename + */ + public function __construct($filename) + { + } + /** + * PHP4 constructor. + * + * @deprecated 5.4.0 Use __construct() instead. + * + * @see POMO_FileReader::__construct() + */ + public function POMO_FileReader($filename) + { + } + /** + * @param int $bytes + * @return string|false Returns read string, otherwise false. + */ + public function read($bytes) + { + } + /** + * @param int $pos + * @return bool + */ + public function seekto($pos) + { + } + /** + * @return bool + */ + public function is_resource() + { + } + /** + * @return bool + */ + public function feof() + { + } + /** + * @return bool + */ + public function close() + { + } + /** + * @return string + */ + public function read_all() + { + } + } + /** + * Provides file-like methods for manipulating a string instead + * of a physical file. + */ + class POMO_StringReader extends \POMO_Reader + { + public $_str = ''; + /** + * PHP5 constructor. + */ + public function __construct($str = '') + { + } + /** + * PHP4 constructor. + * + * @deprecated 5.4.0 Use __construct() instead. + * + * @see POMO_StringReader::__construct() + */ + public function POMO_StringReader($str = '') + { + } + /** + * @param string $bytes + * @return string + */ + public function read($bytes) + { + } + /** + * @param int $pos + * @return int + */ + public function seekto($pos) + { + } + /** + * @return int + */ + public function length() + { + } + /** + * @return string + */ + public function read_all() + { + } + } + /** + * Reads the contents of the file in the beginning. + */ + class POMO_CachedFileReader extends \POMO_StringReader + { + /** + * PHP5 constructor. + */ + public function __construct($filename) + { + } + /** + * PHP4 constructor. + * + * @deprecated 5.4.0 Use __construct() instead. + * + * @see POMO_CachedFileReader::__construct() + */ + public function POMO_CachedFileReader($filename) + { + } + } + /** + * Reads the contents of the file in the beginning. + */ + class POMO_CachedIntFileReader extends \POMO_CachedFileReader + { + /** + * PHP5 constructor. + */ + public function __construct($filename) + { + } + /** + * PHP4 constructor. + * + * @deprecated 5.4.0 Use __construct() instead. + * + * @see POMO_CachedIntFileReader::__construct() + */ + public function POMO_CachedIntFileReader($filename) + { + } + } + /** + * Provides the same interface as Translations, but doesn't do anything + */ + #[\AllowDynamicProperties] + class NOOP_Translations + { + public $entries = array(); + public $headers = array(); + public function add_entry($entry) + { + } + /** + * @param string $header + * @param string $value + */ + public function set_header($header, $value) + { + } + /** + * @param array $headers + */ + public function set_headers($headers) + { + } + /** + * @param string $header + * @return false + */ + public function get_header($header) + { + } + /** + * @param Translation_Entry $entry + * @return false + */ + public function translate_entry(&$entry) + { + } + /** + * @param string $singular + * @param string $context + */ + public function translate($singular, $context = \null) + { + } + /** + * @param int $count + * @return bool + */ + public function select_plural_form($count) + { + } + /** + * @return int + */ + public function get_plural_forms_count() + { + } + /** + * @param string $singular + * @param string $plural + * @param int $count + * @param string $context + */ + public function translate_plural($singular, $plural, $count, $context = \null) + { + } + /** + * @param object $other + */ + public function merge_with(&$other) + { + } + } + /** + * REST API: WP_REST_Request class + * + * @package WordPress + * @subpackage REST_API + * @since 4.4.0 + */ + /** + * Core class used to implement a REST request object. + * + * Contains data from the request, to be passed to the callback. + * + * Note: This implements ArrayAccess, and acts as an array of parameters when + * used in that manner. It does not use ArrayObject (as we cannot rely on SPL), + * so be aware it may have non-array behaviour in some cases. + * + * Note: When using features provided by ArrayAccess, be aware that WordPress deliberately + * does not distinguish between arguments of the same name for different request methods. + * For instance, in a request with `GET id=1` and `POST id=2`, `$request['id']` will equal + * 2 (`POST`) not 1 (`GET`). For more precision between request methods, use + * WP_REST_Request::get_body_params(), WP_REST_Request::get_url_params(), etc. + * + * @since 4.4.0 + * + * @link https://www.php.net/manual/en/class.arrayaccess.php + */ + #[\AllowDynamicProperties] + class WP_REST_Request implements \ArrayAccess + { + /** + * HTTP method. + * + * @since 4.4.0 + * @var string + */ + protected $method = ''; + /** + * Parameters passed to the request. + * + * These typically come from the `$_GET`, `$_POST` and `$_FILES` + * superglobals when being created from the global scope. + * + * @since 4.4.0 + * @var array Contains GET, POST and FILES keys mapping to arrays of data. + */ + protected $params; + /** + * HTTP headers for the request. + * + * @since 4.4.0 + * @var array Map of key to value. Key is always lowercase, as per HTTP specification. + */ + protected $headers = array(); + /** + * Body data. + * + * @since 4.4.0 + * @var string Binary data from the request. + */ + protected $body = \null; + /** + * Route matched for the request. + * + * @since 4.4.0 + * @var string + */ + protected $route; + /** + * Attributes (options) for the route that was matched. + * + * This is the options array used when the route was registered, typically + * containing the callback as well as the valid methods for the route. + * + * @since 4.4.0 + * @var array Attributes for the request. + */ + protected $attributes = array(); + /** + * Used to determine if the JSON data has been parsed yet. + * + * Allows lazy-parsing of JSON data where possible. + * + * @since 4.4.0 + * @var bool + */ + protected $parsed_json = \false; + /** + * Used to determine if the body data has been parsed yet. + * + * @since 4.4.0 + * @var bool + */ + protected $parsed_body = \false; + /** + * Constructor. + * + * @since 4.4.0 + * + * @param string $method Optional. Request method. Default empty. + * @param string $route Optional. Request route. Default empty. + * @param array $attributes Optional. Request attributes. Default empty array. + */ + public function __construct($method = '', $route = '', $attributes = array()) + { + } + /** + * Retrieves the HTTP method for the request. + * + * @since 4.4.0 + * + * @return string HTTP method. + */ + public function get_method() + { + } + /** + * Sets HTTP method for the request. + * + * @since 4.4.0 + * + * @param string $method HTTP method. + */ + public function set_method($method) + { + } + /** + * Retrieves all headers from the request. + * + * @since 4.4.0 + * + * @return array Map of key to value. Key is always lowercase, as per HTTP specification. + */ + public function get_headers() + { + } + /** + * Canonicalizes the header name. + * + * Ensures that header names are always treated the same regardless of + * source. Header names are always case insensitive. + * + * Note that we treat `-` (dashes) and `_` (underscores) as the same + * character, as per header parsing rules in both Apache and nginx. + * + * @link https://stackoverflow.com/q/18185366 + * @link https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#missing-disappearing-http-headers + * @link https://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers + * + * @since 4.4.0 + * + * @param string $key Header name. + * @return string Canonicalized name. + */ + public static function canonicalize_header_name($key) + { + } + /** + * Retrieves the given header from the request. + * + * If the header has multiple values, they will be concatenated with a comma + * as per the HTTP specification. Be aware that some non-compliant headers + * (notably cookie headers) cannot be joined this way. + * + * @since 4.4.0 + * + * @param string $key Header name, will be canonicalized to lowercase. + * @return string|null String value if set, null otherwise. + */ + public function get_header($key) + { + } + /** + * Retrieves header values from the request. + * + * @since 4.4.0 + * + * @param string $key Header name, will be canonicalized to lowercase. + * @return array|null List of string values if set, null otherwise. + */ + public function get_header_as_array($key) + { + } + /** + * Sets the header on request. + * + * @since 4.4.0 + * + * @param string $key Header name. + * @param string $value Header value, or list of values. + */ + public function set_header($key, $value) + { + } + /** + * Appends a header value for the given header. + * + * @since 4.4.0 + * + * @param string $key Header name. + * @param string $value Header value, or list of values. + */ + public function add_header($key, $value) + { + } + /** + * Removes all values for a header. + * + * @since 4.4.0 + * + * @param string $key Header name. + */ + public function remove_header($key) + { + } + /** + * Sets headers on the request. + * + * @since 4.4.0 + * + * @param array $headers Map of header name to value. + * @param bool $override If true, replace the request's headers. Otherwise, merge with existing. + */ + public function set_headers($headers, $override = \true) + { + } + /** + * Retrieves the content-type of the request. + * + * @since 4.4.0 + * + * @return array|null Map containing 'value' and 'parameters' keys + * or null when no valid content-type header was + * available. + */ + public function get_content_type() + { + } + /** + * Checks if the request has specified a JSON content-type. + * + * @since 5.6.0 + * + * @return bool True if the content-type header is JSON. + */ + public function is_json_content_type() + { + } + /** + * Retrieves the parameter priority order. + * + * Used when checking parameters in WP_REST_Request::get_param(). + * + * @since 4.4.0 + * + * @return string[] Array of types to check, in order of priority. + */ + protected function get_parameter_order() + { + } + /** + * Retrieves a parameter from the request. + * + * @since 4.4.0 + * + * @param string $key Parameter name. + * @return mixed|null Value if set, null otherwise. + */ + public function get_param($key) + { + } + /** + * Checks if a parameter exists in the request. + * + * This allows distinguishing between an omitted parameter, + * and a parameter specifically set to null. + * + * @since 5.3.0 + * + * @param string $key Parameter name. + * @return bool True if a param exists for the given key. + */ + public function has_param($key) + { + } + /** + * Sets a parameter on the request. + * + * If the given parameter key exists in any parameter type an update will take place, + * otherwise a new param will be created in the first parameter type (respecting + * get_parameter_order()). + * + * @since 4.4.0 + * + * @param string $key Parameter name. + * @param mixed $value Parameter value. + */ + public function set_param($key, $value) + { + } + /** + * Retrieves merged parameters from the request. + * + * The equivalent of get_param(), but returns all parameters for the request. + * Handles merging all the available values into a single array. + * + * @since 4.4.0 + * + * @return array Map of key to value. + */ + public function get_params() + { + } + /** + * Retrieves parameters from the route itself. + * + * These are parsed from the URL using the regex. + * + * @since 4.4.0 + * + * @return array Parameter map of key to value. + */ + public function get_url_params() + { + } + /** + * Sets parameters from the route. + * + * Typically, this is set after parsing the URL. + * + * @since 4.4.0 + * + * @param array $params Parameter map of key to value. + */ + public function set_url_params($params) + { + } + /** + * Retrieves parameters from the query string. + * + * These are the parameters you'd typically find in `$_GET`. + * + * @since 4.4.0 + * + * @return array Parameter map of key to value + */ + public function get_query_params() + { + } + /** + * Sets parameters from the query string. + * + * Typically, this is set from `$_GET`. + * + * @since 4.4.0 + * + * @param array $params Parameter map of key to value. + */ + public function set_query_params($params) + { + } + /** + * Retrieves parameters from the body. + * + * These are the parameters you'd typically find in `$_POST`. + * + * @since 4.4.0 + * + * @return array Parameter map of key to value. + */ + public function get_body_params() + { + } + /** + * Sets parameters from the body. + * + * Typically, this is set from `$_POST`. + * + * @since 4.4.0 + * + * @param array $params Parameter map of key to value. + */ + public function set_body_params($params) + { + } + /** + * Retrieves multipart file parameters from the body. + * + * These are the parameters you'd typically find in `$_FILES`. + * + * @since 4.4.0 + * + * @return array Parameter map of key to value + */ + public function get_file_params() + { + } + /** + * Sets multipart file parameters from the body. + * + * Typically, this is set from `$_FILES`. + * + * @since 4.4.0 + * + * @param array $params Parameter map of key to value. + */ + public function set_file_params($params) + { + } + /** + * Retrieves the default parameters. + * + * These are the parameters set in the route registration. + * + * @since 4.4.0 + * + * @return array Parameter map of key to value + */ + public function get_default_params() + { + } + /** + * Sets default parameters. + * + * These are the parameters set in the route registration. + * + * @since 4.4.0 + * + * @param array $params Parameter map of key to value. + */ + public function set_default_params($params) + { + } + /** + * Retrieves the request body content. + * + * @since 4.4.0 + * + * @return string Binary data from the request body. + */ + public function get_body() + { + } + /** + * Sets body content. + * + * @since 4.4.0 + * + * @param string $data Binary data from the request body. + */ + public function set_body($data) + { + } + /** + * Retrieves the parameters from a JSON-formatted body. + * + * @since 4.4.0 + * + * @return array Parameter map of key to value. + */ + public function get_json_params() + { + } + /** + * Parses the JSON parameters. + * + * Avoids parsing the JSON data until we need to access it. + * + * @since 4.4.0 + * @since 4.7.0 Returns error instance if value cannot be decoded. + * @return true|WP_Error True if the JSON data was passed or no JSON data was provided, WP_Error if invalid JSON was passed. + */ + protected function parse_json_params() + { + } + /** + * Parses the request body parameters. + * + * Parses out URL-encoded bodies for request methods that aren't supported + * natively by PHP. In PHP 5.x, only POST has these parsed automatically. + * + * @since 4.4.0 + */ + protected function parse_body_params() + { + } + /** + * Retrieves the route that matched the request. + * + * @since 4.4.0 + * + * @return string Route matching regex. + */ + public function get_route() + { + } + /** + * Sets the route that matched the request. + * + * @since 4.4.0 + * + * @param string $route Route matching regex. + */ + public function set_route($route) + { + } + /** + * Retrieves the attributes for the request. + * + * These are the options for the route that was matched. + * + * @since 4.4.0 + * + * @return array Attributes for the request. + */ + public function get_attributes() + { + } + /** + * Sets the attributes for the request. + * + * @since 4.4.0 + * + * @param array $attributes Attributes for the request. + */ + public function set_attributes($attributes) + { + } + /** + * Sanitizes (where possible) the params on the request. + * + * This is primarily based off the sanitize_callback param on each registered + * argument. + * + * @since 4.4.0 + * + * @return true|WP_Error True if parameters were sanitized, WP_Error if an error occurred during sanitization. + */ + public function sanitize_params() + { + } + /** + * Checks whether this request is valid according to its attributes. + * + * @since 4.4.0 + * + * @return true|WP_Error True if there are no parameters to validate or if all pass validation, + * WP_Error if required parameters are missing. + */ + public function has_valid_params() + { + } + /** + * Checks if a parameter is set. + * + * @since 4.4.0 + * + * @param string $offset Parameter name. + * @return bool Whether the parameter is set. + */ + #[\ReturnTypeWillChange] + public function offsetExists($offset) + { + } + /** + * Retrieves a parameter from the request. + * + * @since 4.4.0 + * + * @param string $offset Parameter name. + * @return mixed|null Value if set, null otherwise. + */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + } + /** + * Sets a parameter on the request. + * + * @since 4.4.0 + * + * @param string $offset Parameter name. + * @param mixed $value Parameter value. + */ + #[\ReturnTypeWillChange] + public function offsetSet($offset, $value) + { + } + /** + * Removes a parameter from the request. + * + * @since 4.4.0 + * + * @param string $offset Parameter name. + */ + #[\ReturnTypeWillChange] + public function offsetUnset($offset) + { + } + /** + * Retrieves a WP_REST_Request object from a full URL. + * + * @since 4.5.0 + * + * @param string $url URL with protocol, domain, path and query args. + * @return WP_REST_Request|false WP_REST_Request object on success, false on failure. + */ + public static function from_url($url) + { + } + } + /** + * REST API: WP_REST_Response class + * + * @package WordPress + * @subpackage REST_API + * @since 4.4.0 + */ + /** + * Core class used to implement a REST response object. + * + * @since 4.4.0 + * + * @see WP_HTTP_Response + */ + class WP_REST_Response extends \WP_HTTP_Response + { + /** + * Links related to the response. + * + * @since 4.4.0 + * @var array + */ + protected $links = array(); + /** + * The route that was to create the response. + * + * @since 4.4.0 + * @var string + */ + protected $matched_route = ''; + /** + * The handler that was used to create the response. + * + * @since 4.4.0 + * @var null|array + */ + protected $matched_handler = \null; + /** + * Adds a link to the response. + * + * @internal The $rel parameter is first, as this looks nicer when sending multiple. + * + * @since 4.4.0 + * + * @link https://tools.ietf.org/html/rfc5988 + * @link https://www.iana.org/assignments/link-relations/link-relations.xml + * + * @param string $rel Link relation. Either an IANA registered type, + * or an absolute URL. + * @param string $href Target URI for the link. + * @param array $attributes Optional. Link parameters to send along with the URL. Default empty array. + */ + public function add_link($rel, $href, $attributes = array()) + { + } + /** + * Removes a link from the response. + * + * @since 4.4.0 + * + * @param string $rel Link relation. Either an IANA registered type, or an absolute URL. + * @param string $href Optional. Only remove links for the relation matching the given href. + * Default null. + */ + public function remove_link($rel, $href = \null) + { + } + /** + * Adds multiple links to the response. + * + * Link data should be an associative array with link relation as the key. + * The value can either be an associative array of link attributes + * (including `href` with the URL for the response), or a list of these + * associative arrays. + * + * @since 4.4.0 + * + * @param array $links Map of link relation to list of links. + */ + public function add_links($links) + { + } + /** + * Retrieves links for the response. + * + * @since 4.4.0 + * + * @return array List of links. + */ + public function get_links() + { + } + /** + * Sets a single link header. + * + * @internal The $rel parameter is first, as this looks nicer when sending multiple. + * + * @since 4.4.0 + * + * @link https://tools.ietf.org/html/rfc5988 + * @link https://www.iana.org/assignments/link-relations/link-relations.xml + * + * @param string $rel Link relation. Either an IANA registered type, or an absolute URL. + * @param string $link Target IRI for the link. + * @param array $other Optional. Other parameters to send, as an associative array. + * Default empty array. + */ + public function link_header($rel, $link, $other = array()) + { + } + /** + * Retrieves the route that was used. + * + * @since 4.4.0 + * + * @return string The matched route. + */ + public function get_matched_route() + { + } + /** + * Sets the route (regex for path) that caused the response. + * + * @since 4.4.0 + * + * @param string $route Route name. + */ + public function set_matched_route($route) + { + } + /** + * Retrieves the handler that was used to generate the response. + * + * @since 4.4.0 + * + * @return null|array The handler that was used to create the response. + */ + public function get_matched_handler() + { + } + /** + * Sets the handler that was responsible for generating the response. + * + * @since 4.4.0 + * + * @param array $handler The matched handler. + */ + public function set_matched_handler($handler) + { + } + /** + * Checks if the response is an error, i.e. >= 400 response code. + * + * @since 4.4.0 + * + * @return bool Whether the response is an error. + */ + public function is_error() + { + } + /** + * Retrieves a WP_Error object from the response. + * + * @since 4.4.0 + * + * @return WP_Error|null WP_Error or null on not an errored response. + */ + public function as_error() + { + } + /** + * Retrieves the CURIEs (compact URIs) used for relations. + * + * @since 4.5.0 + * + * @return array Compact URIs. + */ + public function get_curies() + { + } + } + /** + * REST API: WP_REST_Server class + * + * @package WordPress + * @subpackage REST_API + * @since 4.4.0 + */ + /** + * Core class used to implement the WordPress REST API server. + * + * @since 4.4.0 + */ + #[\AllowDynamicProperties] + class WP_REST_Server + { + /** + * Alias for GET transport method. + * + * @since 4.4.0 + * @var string + */ + const READABLE = 'GET'; + /** + * Alias for POST transport method. + * + * @since 4.4.0 + * @var string + */ + const CREATABLE = 'POST'; + /** + * Alias for POST, PUT, PATCH transport methods together. + * + * @since 4.4.0 + * @var string + */ + const EDITABLE = 'POST, PUT, PATCH'; + /** + * Alias for DELETE transport method. + * + * @since 4.4.0 + * @var string + */ + const DELETABLE = 'DELETE'; + /** + * Alias for GET, POST, PUT, PATCH & DELETE transport methods together. + * + * @since 4.4.0 + * @var string + */ + const ALLMETHODS = 'GET, POST, PUT, PATCH, DELETE'; + /** + * Namespaces registered to the server. + * + * @since 4.4.0 + * @var array + */ + protected $namespaces = array(); + /** + * Endpoints registered to the server. + * + * @since 4.4.0 + * @var array + */ + protected $endpoints = array(); + /** + * Options defined for the routes. + * + * @since 4.4.0 + * @var array + */ + protected $route_options = array(); + /** + * Caches embedded requests. + * + * @since 5.4.0 + * @var array + */ + protected $embed_cache = array(); + /** + * Instantiates the REST server. + * + * @since 4.4.0 + */ + public function __construct() + { + } + /** + * Checks the authentication headers if supplied. + * + * @since 4.4.0 + * + * @return WP_Error|null WP_Error indicates unsuccessful login, null indicates successful + * or no authentication provided + */ + public function check_authentication() + { + } + /** + * Converts an error to a response object. + * + * This iterates over all error codes and messages to change it into a flat + * array. This enables simpler client behaviour, as it is represented as a + * list in JSON rather than an object/map. + * + * @since 4.4.0 + * @since 5.7.0 Converted to a wrapper of {@see rest_convert_error_to_response()}. + * + * @param WP_Error $error WP_Error instance. + * @return WP_REST_Response List of associative arrays with code and message keys. + */ + protected function error_to_response($error) + { + } + /** + * Retrieves an appropriate error representation in JSON. + * + * Note: This should only be used in WP_REST_Server::serve_request(), as it + * cannot handle WP_Error internally. All callbacks and other internal methods + * should instead return a WP_Error with the data set to an array that includes + * a 'status' key, with the value being the HTTP status to send. + * + * @since 4.4.0 + * + * @param string $code WP_Error-style code. + * @param string $message Human-readable message. + * @param int $status Optional. HTTP status code to send. Default null. + * @return string JSON representation of the error + */ + protected function json_error($code, $message, $status = \null) + { + } + /** + * Gets the encoding options passed to {@see wp_json_encode}. + * + * @since 6.1.0 + * + * @param \WP_REST_Request $request The current request object. + * + * @return int The JSON encode options. + */ + protected function get_json_encode_options(\WP_REST_Request $request) + { + } + /** + * Handles serving a REST API request. + * + * Matches the current server URI to a route and runs the first matching + * callback then outputs a JSON representation of the returned value. + * + * @since 4.4.0 + * + * @see WP_REST_Server::dispatch() + * + * @global WP_User $current_user The currently authenticated user. + * + * @param string $path Optional. The request route. If not set, `$_SERVER['PATH_INFO']` will be used. + * Default null. + * @return null|false Null if not served and a HEAD request, false otherwise. + */ + public function serve_request($path = \null) + { + } + /** + * Converts a response to data to send. + * + * @since 4.4.0 + * @since 5.4.0 The $embed parameter can now contain a list of link relations to include. + * + * @param WP_REST_Response $response Response object. + * @param bool|string[] $embed Whether to embed all links, a filtered list of link relations, or no links. + * @return array { + * Data with sub-requests embedded. + * + * @type array $_links Links. + * @type array $_embedded Embedded objects. + * } + * @phpstan-return array{ + * _links: array, + * _embedded: array, + * } + */ + public function response_to_data($response, $embed) + { + } + /** + * Retrieves links from a response. + * + * Extracts the links from a response into a structured hash, suitable for + * direct output. + * + * @since 4.4.0 + * + * @param WP_REST_Response $response Response to extract links from. + * @return array Map of link relation to list of link hashes. + */ + public static function get_response_links($response) + { + } + /** + * Retrieves the CURIEs (compact URIs) used for relations. + * + * Extracts the links from a response into a structured hash, suitable for + * direct output. + * + * @since 4.5.0 + * + * @param WP_REST_Response $response Response to extract links from. + * @return array Map of link relation to list of link hashes. + */ + public static function get_compact_response_links($response) + { + } + /** + * Embeds the links from the data into the request. + * + * @since 4.4.0 + * @since 5.4.0 The $embed parameter can now contain a list of link relations to include. + * + * @param array $data Data from the request. + * @param bool|string[] $embed Whether to embed all links or a filtered list of link relations. + * @return array { + * Data with sub-requests embedded. + * + * @type array $_links Links. + * @type array $_embedded Embedded objects. + * } + * @phpstan-return array{ + * _links: array, + * _embedded: array, + * } + */ + protected function embed_links($data, $embed = \true) + { + } + /** + * Wraps the response in an envelope. + * + * The enveloping technique is used to work around browser/client + * compatibility issues. Essentially, it converts the full HTTP response to + * data instead. + * + * @since 4.4.0 + * @since 6.0.0 The $embed parameter can now contain a list of link relations to include + * + * @param WP_REST_Response $response Response object. + * @param bool|string[] $embed Whether to embed all links, a filtered list of link relations, or no links. + * @return WP_REST_Response New response with wrapped data + */ + public function envelope_response($response, $embed) + { + } + /** + * Registers a route to the server. + * + * @since 4.4.0 + * + * @param string $namespace Namespace. + * @param string $route The REST route. + * @param array $route_args Route arguments. + * @param bool $override Optional. Whether the route should be overridden if it already exists. + * Default false. + */ + public function register_route($namespace, $route, $route_args, $override = \false) + { + } + /** + * Retrieves the route map. + * + * The route map is an associative array with path regexes as the keys. The + * value is an indexed array with the callback function/method as the first + * item, and a bitmask of HTTP methods as the second item (see the class + * constants). + * + * Each route can be mapped to more than one callback by using an array of + * the indexed arrays. This allows mapping e.g. GET requests to one callback + * and POST requests to another. + * + * Note that the path regexes (array keys) must have @ escaped, as this is + * used as the delimiter with preg_match() + * + * @since 4.4.0 + * @since 5.4.0 Add $namespace parameter. + * + * @param string $namespace Optionally, only return routes in the given namespace. + * @return array `'/path/regex' => array( $callback, $bitmask )` or + * `'/path/regex' => array( array( $callback, $bitmask ), ...)`. + */ + public function get_routes($namespace = '') + { + } + /** + * Retrieves namespaces registered on the server. + * + * @since 4.4.0 + * + * @return string[] List of registered namespaces. + */ + public function get_namespaces() + { + } + /** + * Retrieves specified options for a route. + * + * @since 4.4.0 + * + * @param string $route Route pattern to fetch options for. + * @return array|null Data as an associative array if found, or null if not found. + */ + public function get_route_options($route) + { + } + /** + * Matches the request to a callback and call it. + * + * @since 4.4.0 + * + * @param WP_REST_Request $request Request to attempt dispatching. + * @return WP_REST_Response Response returned by the callback. + */ + public function dispatch($request) + { + } + /** + * Matches a request object to its handler. + * + * @access private + * @since 5.6.0 + * + * @param WP_REST_Request $request The request object. + * @return array|WP_Error The route and request handler on success or a WP_Error instance if no handler was found. + */ + protected function match_request_to_handler($request) + { + } + /** + * Dispatches the request to the callback handler. + * + * @access private + * @since 5.6.0 + * + * @param WP_REST_Request $request The request object. + * @param string $route The matched route regex. + * @param array $handler The matched route handler. + * @param WP_Error|null $response The current error object if any. + * @return WP_REST_Response + */ + protected function respond_to_request($request, $route, $handler, $response) + { + } + /** + * Returns if an error occurred during most recent JSON encode/decode. + * + * Strings to be translated will be in format like + * "Encoding error: Maximum stack depth exceeded". + * + * @since 4.4.0 + * + * @return false|string Boolean false or string error message. + */ + protected function get_json_last_error() + { + } + /** + * Retrieves the site index. + * + * This endpoint describes the capabilities of the site. + * + * @since 4.4.0 + * + * @param array $request { + * Request. + * + * @type string $context Context. + * } + * @return WP_REST_Response The API root index data. + * @phpstan-param array{ + * context?: string, + * } $request + */ + public function get_index($request) + { + } + /** + * Adds a link to the active theme for users who have proper permissions. + * + * @since 5.7.0 + * + * @param WP_REST_Response $response REST API response. + */ + protected function add_active_theme_link_to_index(\WP_REST_Response $response) + { + } + /** + * Exposes the site logo through the WordPress REST API. + * + * This is used for fetching this information when user has no rights + * to update settings. + * + * @since 5.8.0 + * + * @param WP_REST_Response $response REST API response. + */ + protected function add_site_logo_to_index(\WP_REST_Response $response) + { + } + /** + * Exposes the site icon through the WordPress REST API. + * + * This is used for fetching this information when user has no rights + * to update settings. + * + * @since 5.9.0 + * + * @param WP_REST_Response $response REST API response. + */ + protected function add_site_icon_to_index(\WP_REST_Response $response) + { + } + /** + * Exposes an image through the WordPress REST API. + * This is used for fetching this information when user has no rights + * to update settings. + * + * @since 5.9.0 + * + * @param WP_REST_Response $response REST API response. + * @param int $image_id Image attachment ID. + * @param string $type Type of Image. + */ + protected function add_image_to_index(\WP_REST_Response $response, $image_id, $type) + { + } + /** + * Retrieves the index for a namespace. + * + * @since 4.4.0 + * + * @param WP_REST_Request $request REST request instance. + * @return WP_REST_Response|WP_Error WP_REST_Response instance if the index was found, + * WP_Error if the namespace isn't set. + */ + public function get_namespace_index($request) + { + } + /** + * Retrieves the publicly-visible data for routes. + * + * @since 4.4.0 + * + * @param array $routes Routes to get data for. + * @param string $context Optional. Context for data. Accepts 'view' or 'help'. Default 'view'. + * @return array[] Route data to expose in indexes, keyed by route. + */ + public function get_data_for_routes($routes, $context = 'view') + { + } + /** + * Retrieves publicly-visible data for the route. + * + * @since 4.4.0 + * + * @param string $route Route to get data for. + * @param array $callbacks Callbacks to convert to data. + * @param string $context Optional. Context for the data. Accepts 'view' or 'help'. Default 'view'. + * @return array|null Data for the route, or null if no publicly-visible data. + */ + public function get_data_for_route($route, $callbacks, $context = 'view') + { + } + /** + * Gets the maximum number of requests that can be included in a batch. + * + * @since 5.6.0 + * + * @return int The maximum requests. + */ + protected function get_max_batch_size() + { + } + /** + * Serves the batch/v1 request. + * + * @since 5.6.0 + * + * @param WP_REST_Request $batch_request The batch request object. + * @return WP_REST_Response The generated response object. + */ + public function serve_batch_request_v1(\WP_REST_Request $batch_request) + { + } + /** + * Sends an HTTP status code. + * + * @since 4.4.0 + * + * @param int $code HTTP status. + */ + protected function set_status($code) + { + } + /** + * Sends an HTTP header. + * + * @since 4.4.0 + * + * @param string $key Header key. + * @param string $value Header value. + */ + public function send_header($key, $value) + { + } + /** + * Sends multiple HTTP headers. + * + * @since 4.4.0 + * + * @param array $headers Map of header name to header value. + */ + public function send_headers($headers) + { + } + /** + * Removes an HTTP header from the current response. + * + * @since 4.8.0 + * + * @param string $key Header key. + */ + public function remove_header($key) + { + } + /** + * Retrieves the raw request entity (body). + * + * @since 4.4.0 + * + * @global string $HTTP_RAW_POST_DATA Raw post data. + * + * @return string Raw request data. + */ + public static function get_raw_data() + { + } + /** + * Extracts headers from a PHP-style $_SERVER array. + * + * @since 4.4.0 + * + * @param array $server Associative array similar to `$_SERVER`. + * @return array Headers extracted from the input. + */ + public function get_headers($server) + { + } + } + /** + * REST API: WP_REST_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core base controller for managing and interacting with REST API items. + * + * @since 4.7.0 + */ + #[\AllowDynamicProperties] + abstract class WP_REST_Controller + { + /** + * The namespace of this controller's route. + * + * @since 4.7.0 + * @var string + */ + protected $namespace; + /** + * The base of this controller's route. + * + * @since 4.7.0 + * @var string + */ + protected $rest_base; + /** + * Cached results of get_item_schema. + * + * @since 5.3.0 + * @var array + */ + protected $schema; + /** + * Registers the routes for the objects of the controller. + * + * @since 4.7.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Checks if a given request has access to get items. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves a collection of items. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Checks if a given request has access to get a specific item. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Retrieves one item from the collection. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Checks if a given request has access to create items. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise. + */ + public function create_item_permissions_check($request) + { + } + /** + * Creates one item from the collection. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function create_item($request) + { + } + /** + * Checks if a given request has access to update a specific item. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise. + */ + public function update_item_permissions_check($request) + { + } + /** + * Updates one item from the collection. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function update_item($request) + { + } + /** + * Checks if a given request has access to delete a specific item. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise. + */ + public function delete_item_permissions_check($request) + { + } + /** + * Deletes one item from the collection. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function delete_item($request) + { + } + /** + * Prepares one item for create or update operation. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Request object. + * @return object|WP_Error The prepared item, or WP_Error object on failure. + */ + protected function prepare_item_for_database($request) + { + } + /** + * Prepares the item for the REST response. + * + * @since 4.7.0 + * + * @param mixed $item WordPress representation of the item. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares a response for insertion into a collection. + * + * @since 4.7.0 + * + * @param WP_REST_Response $response Response object. + * @return array|mixed Response data, ready for insertion into collection data. + */ + public function prepare_response_for_collection($response) + { + } + /** + * Filters a response based on the context defined in the schema. + * + * @since 4.7.0 + * + * @param array $data Response data to filter. + * @param string $context Context defined in the schema. + * @return array Filtered response. + */ + public function filter_response_by_context($data, $context) + { + } + /** + * Retrieves the item's schema, conforming to JSON Schema. + * + * @since 4.7.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the item's schema for display / public consumption purposes. + * + * @since 4.7.0 + * + * @return array Public item schema data. + */ + public function get_public_item_schema() + { + } + /** + * Retrieves the query params for the collections. + * + * @since 4.7.0 + * + * @return array Query parameters for the collection. + */ + public function get_collection_params() + { + } + /** + * Retrieves the magical context param. + * + * Ensures consistent descriptions between endpoints, and populates enum from schema. + * + * @since 4.7.0 + * + * @param array $args Optional. Additional arguments for context parameter. Default empty array. + * @return array Context parameter details. + */ + public function get_context_param($args = array()) + { + } + /** + * Adds the values from additional fields to a data object. + * + * @since 4.7.0 + * + * @param array $prepared Prepared response array. + * @param WP_REST_Request $request Full details about the request. + * @return array Modified data object with additional fields. + */ + protected function add_additional_fields_to_object($prepared, $request) + { + } + /** + * Updates the values of additional fields added to a data object. + * + * @since 4.7.0 + * + * @param object $object Data model like WP_Term or WP_Post. + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True on success, WP_Error object if a field cannot be updated. + */ + protected function update_additional_fields_for_object($object, $request) + { + } + /** + * Adds the schema from additional fields to a schema array. + * + * The type of object is inferred from the passed schema. + * + * @since 4.7.0 + * + * @param array $schema Schema array. + * @return array Modified Schema array. + */ + protected function add_additional_fields_schema($schema) + { + } + /** + * Retrieves all of the registered additional fields for a given object-type. + * + * @since 4.7.0 + * + * @global array $wp_rest_additional_fields Holds registered fields, organized by object type. + * + * @param string $object_type Optional. The object type. + * @return array Registered additional fields (if any), empty array if none or if the object type + * could not be inferred. + */ + protected function get_additional_fields($object_type = \null) + { + } + /** + * Retrieves the object type this controller is responsible for managing. + * + * @since 4.7.0 + * + * @return string Object type for the controller. + */ + protected function get_object_type() + { + } + /** + * Gets an array of fields to be included on the response. + * + * Included fields are based on item schema and `_fields=` request argument. + * + * @since 4.9.6 + * + * @param WP_REST_Request $request Full details about the request. + * @return string[] Fields to be included in the response. + */ + public function get_fields_for_response($request) + { + } + /** + * Retrieves an array of endpoint arguments from the item schema for the controller. + * + * @since 4.7.0 + * + * @param string $method Optional. HTTP method of the request. The arguments for `CREATABLE` requests are + * checked for required values and may fall-back to a given default, this is not done + * on `EDITABLE` requests. Default WP_REST_Server::CREATABLE. + * @return array Endpoint arguments. + */ + public function get_endpoint_args_for_item_schema($method = \WP_REST_Server::CREATABLE) + { + } + /** + * Sanitizes the slug value. + * + * @since 4.7.0 + * + * @internal We can't use sanitize_title() directly, as the second + * parameter is the fallback title, which would end up being set to the + * request object. + * + * @see https://github.com/WP-API/WP-API/issues/1585 + * + * @todo Remove this in favour of https://core.trac.wordpress.org/ticket/34659 + * + * @param string $slug Slug value passed in request. + * @return string Sanitized value for the slug. + */ + public function sanitize_slug($slug) + { + } + } + /** + * REST API: WP_REST_Application_Passwords_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.6.0 + */ + /** + * Core class to access a user's application passwords via the REST API. + * + * @since 5.6.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Application_Passwords_Controller extends \WP_REST_Controller + { + /** + * Application Passwords controller constructor. + * + * @since 5.6.0 + */ + public function __construct() + { + } + /** + * Registers the REST API routes for the application passwords controller. + * + * @since 5.6.0 + */ + public function register_routes() + { + } + /** + * Checks if a given request has access to get application passwords. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves a collection of application passwords. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Checks if a given request has access to get a specific application password. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Retrieves one application password from the collection. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Checks if a given request has access to create application passwords. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise. + */ + public function create_item_permissions_check($request) + { + } + /** + * Creates an application password. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function create_item($request) + { + } + /** + * Checks if a given request has access to update application passwords. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise. + */ + public function update_item_permissions_check($request) + { + } + /** + * Updates an application password. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function update_item($request) + { + } + /** + * Checks if a given request has access to delete all application passwords for a user. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise. + */ + public function delete_items_permissions_check($request) + { + } + /** + * Deletes all application passwords for a user. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function delete_items($request) + { + } + /** + * Checks if a given request has access to delete a specific application password for a user. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise. + */ + public function delete_item_permissions_check($request) + { + } + /** + * Deletes an application password for a user. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function delete_item($request) + { + } + /** + * Checks if a given request has access to get the currently used application password for a user. + * + * @since 5.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_current_item_permissions_check($request) + { + } + /** + * Retrieves the application password being currently used for authentication of a user. + * + * @since 5.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_current_item($request) + { + } + /** + * Performs a permissions check for the request. + * + * @since 5.6.0 + * @deprecated 5.7.0 Use `edit_user` directly or one of the specific meta capabilities introduced in 5.7.0. + * + * @param WP_REST_Request $request + * @return true|WP_Error + */ + protected function do_permissions_check($request) + { + } + /** + * Prepares an application password for a create or update operation. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Request object. + * @return object|WP_Error The prepared item, or WP_Error object on failure. + */ + protected function prepare_item_for_database($request) + { + } + /** + * Prepares the application password for the REST response. + * + * @since 5.6.0 + * + * @param array $item WordPress representation of the item. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the request. + * + * @since 5.6.0 + * + * @param WP_User $user The requested user. + * @param array $item The application password. + * @return array The list of links. + */ + protected function prepare_links(\WP_User $user, $item) + { + } + /** + * Gets the requested user. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request The request object. + * @return WP_User|WP_Error The WordPress user associated with the request, or a WP_Error if none found. + */ + protected function get_user($request) + { + } + /** + * Gets the requested application password for a user. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request The request object. + * @return array|WP_Error The application password details if found, a WP_Error otherwise. + */ + protected function get_application_password($request) + { + } + /** + * Retrieves the query params for the collections. + * + * @since 5.6.0 + * + * @return array Query parameters for the collection. + */ + public function get_collection_params() + { + } + /** + * Retrieves the application password's schema, conforming to JSON Schema. + * + * @since 5.6.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + } + /** + * REST API: WP_REST_Posts_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core class to access posts via the REST API. + * + * @since 4.7.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Posts_Controller extends \WP_REST_Controller + { + /** + * Post type. + * + * @since 4.7.0 + * @var string + */ + protected $post_type; + /** + * Instance of a post meta fields object. + * + * @since 4.7.0 + * @var WP_REST_Post_Meta_Fields + */ + protected $meta; + /** + * Passwordless post access permitted. + * + * @since 5.7.1 + * @var int[] + */ + protected $password_check_passed = array(); + /** + * Whether the controller supports batching. + * + * @since 5.9.0 + * @var array + */ + protected $allow_batch = array('v1' => \true); + /** + * Constructor. + * + * @since 4.7.0 + * + * @param string $post_type Post type. + */ + public function __construct($post_type) + { + } + /** + * Registers the routes for posts. + * + * @since 4.7.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Checks if a given request has access to read posts. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Overrides the result of the post password check for REST requested posts. + * + * Allow users to read the content of password protected posts if they have + * previously passed a permission check or if they have the `edit_post` capability + * for the post being checked. + * + * @since 5.7.1 + * + * @param bool $required Whether the post requires a password check. + * @param WP_Post $post The post been password checked. + * @return bool Result of password check taking in to account REST API considerations. + */ + public function check_password_required($required, $post) + { + } + /** + * Retrieves a collection of posts. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Gets the post, if the ID is valid. + * + * @since 4.7.2 + * + * @param int $id Supplied ID. + * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise. + */ + protected function get_post($id) + { + } + /** + * Checks if a given request has access to read a post. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Checks if the user can access password-protected content. + * + * This method determines whether we need to override the regular password + * check in core with a filter. + * + * @since 4.7.0 + * + * @param WP_Post $post Post to check against. + * @param WP_REST_Request $request Request data to check. + * @return bool True if the user can access password-protected content, otherwise false. + */ + public function can_access_password_content($post, $request) + { + } + /** + * Retrieves a single post. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Checks if a given request has access to create a post. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise. + */ + public function create_item_permissions_check($request) + { + } + /** + * Creates a single post. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function create_item($request) + { + } + /** + * Checks if a given request has access to update a post. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise. + */ + public function update_item_permissions_check($request) + { + } + /** + * Updates a single post. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function update_item($request) + { + } + /** + * Checks if a given request has access to delete a post. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise. + */ + public function delete_item_permissions_check($request) + { + } + /** + * Deletes a single post. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function delete_item($request) + { + } + /** + * Determines the allowed query_vars for a get_items() response and prepares + * them for WP_Query. + * + * @since 4.7.0 + * + * @param array $prepared_args Optional. Prepared WP_Query arguments. Default empty array. + * @param WP_REST_Request $request Optional. Full details about the request. + * @return array Items query arguments. + */ + protected function prepare_items_query($prepared_args = array(), $request = \null) + { + } + /** + * Checks the post_date_gmt or modified_gmt and prepare any post or + * modified date for single post output. + * + * @since 4.7.0 + * + * @param string $date_gmt GMT publication time. + * @param string|null $date Optional. Local publication time. Default null. + * @return string|null ISO8601/RFC3339 formatted datetime. + */ + protected function prepare_date_response($date_gmt, $date = \null) + { + } + /** + * Prepares a single post for create or update. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Request object. + * @return stdClass|WP_Error Post object or WP_Error. + */ + protected function prepare_item_for_database($request) + { + } + /** + * Checks whether the status is valid for the given post. + * + * Allows for sending an update request with the current status, even if that status would not be acceptable. + * + * @since 5.6.0 + * + * @param string $status The provided status. + * @param WP_REST_Request $request The request object. + * @param string $param The parameter name. + * @return true|WP_Error True if the status is valid, or WP_Error if not. + */ + public function check_status($status, $request, $param) + { + } + /** + * Determines validity and normalizes the given status parameter. + * + * @since 4.7.0 + * + * @param string $post_status Post status. + * @param WP_Post_Type $post_type Post type. + * @return string|WP_Error Post status or WP_Error if lacking the proper permission. + */ + protected function handle_status_param($post_status, $post_type) + { + } + /** + * Determines the featured media based on a request param. + * + * @since 4.7.0 + * + * @param int $featured_media Featured Media ID. + * @param int $post_id Post ID. + * @return bool|WP_Error Whether the post thumbnail was successfully deleted, otherwise WP_Error. + */ + protected function handle_featured_media($featured_media, $post_id) + { + } + /** + * Checks whether the template is valid for the given post. + * + * @since 4.9.0 + * + * @param string $template Page template filename. + * @param WP_REST_Request $request Request. + * @return bool|WP_Error True if template is still valid or if the same as existing value, or false if template not supported. + */ + public function check_template($template, $request) + { + } + /** + * Sets the template for a post. + * + * @since 4.7.0 + * @since 4.9.0 Added the `$validate` parameter. + * + * @param string $template Page template filename. + * @param int $post_id Post ID. + * @param bool $validate Whether to validate that the template selected is valid. + */ + public function handle_template($template, $post_id, $validate = \false) + { + } + /** + * Updates the post's terms from a REST request. + * + * @since 4.7.0 + * + * @param int $post_id The post ID to update the terms form. + * @param WP_REST_Request $request The request object with post and terms data. + * @return null|WP_Error WP_Error on an error assigning any of the terms, otherwise null. + */ + protected function handle_terms($post_id, $request) + { + } + /** + * Checks whether current user can assign all terms sent with the current request. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request The request object with post and terms data. + * @return bool Whether the current user can assign the provided terms. + */ + protected function check_assign_terms_permission($request) + { + } + /** + * Checks if a given post type can be viewed or managed. + * + * @since 4.7.0 + * + * @param WP_Post_Type|string $post_type Post type name or object. + * @return bool Whether the post type is allowed in REST. + */ + protected function check_is_post_type_allowed($post_type) + { + } + /** + * Checks if a post can be read. + * + * Correctly handles posts with the inherit status. + * + * @since 4.7.0 + * + * @param WP_Post $post Post object. + * @return bool Whether the post can be read. + */ + public function check_read_permission($post) + { + } + /** + * Checks if a post can be edited. + * + * @since 4.7.0 + * + * @param WP_Post $post Post object. + * @return bool Whether the post can be edited. + */ + protected function check_update_permission($post) + { + } + /** + * Checks if a post can be created. + * + * @since 4.7.0 + * + * @param WP_Post $post Post object. + * @return bool Whether the post can be created. + */ + protected function check_create_permission($post) + { + } + /** + * Checks if a post can be deleted. + * + * @since 4.7.0 + * + * @param WP_Post $post Post object. + * @return bool Whether the post can be deleted. + */ + protected function check_delete_permission($post) + { + } + /** + * Prepares a single post output for response. + * + * @since 4.7.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Post $item Post object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Overwrites the default protected title format. + * + * By default, WordPress will show password protected posts with a title of + * "Protected: %s", as the REST API communicates the protected status of a post + * in a machine readable format, we remove the "Protected: " prefix. + * + * @since 4.7.0 + * + * @return string Protected title format. + */ + public function protected_title_format() + { + } + /** + * Prepares links for the request. + * + * @since 4.7.0 + * + * @param WP_Post $post Post object. + * @return array Links for the given post. + */ + protected function prepare_links($post) + { + } + /** + * Gets the link relations available for the post and current user. + * + * @since 4.9.8 + * + * @param WP_Post $post Post object. + * @param WP_REST_Request $request Request object. + * @return array List of link relations. + */ + protected function get_available_actions($post, $request) + { + } + /** + * Retrieves the post's schema, conforming to JSON Schema. + * + * @since 4.7.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves Link Description Objects that should be added to the Schema for the posts collection. + * + * @since 4.9.8 + * + * @return array + */ + protected function get_schema_links() + { + } + /** + * Retrieves the query params for the posts collection. + * + * @since 4.7.0 + * @since 5.4.0 The `tax_relation` query parameter was added. + * @since 5.7.0 The `modified_after` and `modified_before` query parameters were added. + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + /** + * Sanitizes and validates the list of post statuses, including whether the + * user can query private statuses. + * + * @since 4.7.0 + * + * @param string|array $statuses One or more post statuses. + * @param WP_REST_Request $request Full details about the request. + * @param string $parameter Additional parameter to pass to validation. + * @return array|WP_Error A list of valid statuses, otherwise WP_Error object. + */ + public function sanitize_post_statuses($statuses, $request, $parameter) + { + } + } + /** + * REST API: WP_REST_Attachments_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core controller used to access attachments via the REST API. + * + * @since 4.7.0 + * + * @see WP_REST_Posts_Controller + */ + class WP_REST_Attachments_Controller extends \WP_REST_Posts_Controller + { + /** + * Whether the controller supports batching. + * + * @since 5.9.0 + * @var false + */ + protected $allow_batch = \false; + /** + * Registers the routes for attachments. + * + * @since 5.3.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Determines the allowed query_vars for a get_items() response and + * prepares for WP_Query. + * + * @since 4.7.0 + * + * @param array $prepared_args Optional. Array of prepared arguments. Default empty array. + * @param WP_REST_Request $request Optional. Request to prepare items for. + * @return array Array of query arguments. + */ + protected function prepare_items_query($prepared_args = array(), $request = \null) + { + } + /** + * Checks if a given request has access to create an attachment. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error Boolean true if the attachment may be created, or a WP_Error if not. + */ + public function create_item_permissions_check($request) + { + } + /** + * Creates a single attachment. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure. + */ + public function create_item($request) + { + } + /** + * Inserts the attachment post in the database. Does not update the attachment meta. + * + * @since 5.3.0 + * + * @param WP_REST_Request $request + * @return array|WP_Error + */ + protected function insert_attachment($request) + { + } + /** + * Updates a single attachment. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure. + */ + public function update_item($request) + { + } + /** + * Performs post processing on an attachment. + * + * @since 5.3.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure. + */ + public function post_process_item($request) + { + } + /** + * Checks if a given request can perform post processing on an attachment. + * + * @since 5.3.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise. + */ + public function post_process_item_permissions_check($request) + { + } + /** + * Checks if a given request has access to editing media. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function edit_media_item_permissions_check($request) + { + } + /** + * Applies edits to a media item and creates a new attachment record. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure. + */ + public function edit_media_item($request) + { + } + /** + * Prepares a single attachment for create or update. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Request object. + * @return stdClass|WP_Error Post object. + */ + protected function prepare_item_for_database($request) + { + } + /** + * Prepares a single attachment output for response. + * + * @since 4.7.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Post $item Attachment object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Retrieves the attachment's schema, conforming to JSON Schema. + * + * @since 4.7.0 + * + * @return array Item schema as an array. + */ + public function get_item_schema() + { + } + /** + * Handles an upload via raw POST data. + * + * @since 4.7.0 + * + * @param array $data Supplied file data. + * @param array $headers HTTP headers from the request. + * @return array|WP_Error Data from wp_handle_sideload(). + */ + protected function upload_from_data($data, $headers) + { + } + /** + * Parses filename from a Content-Disposition header value. + * + * As per RFC6266: + * + * content-disposition = "Content-Disposition" ":" + * disposition-type *( ";" disposition-parm ) + * + * disposition-type = "inline" | "attachment" | disp-ext-type + * ; case-insensitive + * disp-ext-type = token + * + * disposition-parm = filename-parm | disp-ext-parm + * + * filename-parm = "filename" "=" value + * | "filename*" "=" ext-value + * + * disp-ext-parm = token "=" value + * | ext-token "=" ext-value + * ext-token = <the characters in token, followed by "*"> + * + * @since 4.7.0 + * + * @link https://tools.ietf.org/html/rfc2388 + * @link https://tools.ietf.org/html/rfc6266 + * + * @param string[] $disposition_header List of Content-Disposition header values. + * @return string|null Filename if available, or null if not found. + */ + public static function get_filename_from_disposition($disposition_header) + { + } + /** + * Retrieves the query params for collections of attachments. + * + * @since 4.7.0 + * + * @return array Query parameters for the attachment collection as an array. + */ + public function get_collection_params() + { + } + /** + * Handles an upload via multipart/form-data ($_FILES). + * + * @since 4.7.0 + * + * @param array $files Data from the `$_FILES` superglobal. + * @param array $headers HTTP headers from the request. + * @return array|WP_Error Data from wp_handle_upload(). + */ + protected function upload_from_file($files, $headers) + { + } + /** + * Retrieves the supported media types. + * + * Media types are considered the MIME type category. + * + * @since 4.7.0 + * + * @return array Array of supported media types. + */ + protected function get_media_types() + { + } + /** + * Determine if uploaded file exceeds space quota on multisite. + * + * Replicates check_upload_size(). + * + * @since 4.9.8 + * + * @param array $file $_FILES array for a given file. + * @return true|WP_Error True if can upload, error for errors. + */ + protected function check_upload_size($file) + { + } + /** + * Gets the request args for the edit item route. + * + * @since 5.5.0 + * + * @return array + */ + protected function get_edit_media_item_args() + { + } + } + /** + * REST API: WP_REST_Revisions_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core class used to access revisions via the REST API. + * + * @since 4.7.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Revisions_Controller extends \WP_REST_Controller + { + /** + * Constructor. + * + * @since 4.7.0 + * + * @param string $parent_post_type Post type of the parent. + */ + public function __construct($parent_post_type) + { + } + /** + * Registers the routes for revisions based on post types supporting revisions. + * + * @since 4.7.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Get the parent post, if the ID is valid. + * + * @since 4.7.2 + * + * @param int $parent Supplied ID. + * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise. + */ + protected function get_parent($parent) + { + } + /** + * Checks if a given request has access to get revisions. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Get the revision, if the ID is valid. + * + * @since 4.7.2 + * + * @param int $id Supplied ID. + * @return WP_Post|WP_Error Revision post object if ID is valid, WP_Error otherwise. + */ + protected function get_revision($id) + { + } + /** + * Gets a collection of revisions. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Checks if a given request has access to get a specific revision. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Retrieves one revision from the collection. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Checks if a given request has access to delete a revision. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise. + */ + public function delete_item_permissions_check($request) + { + } + /** + * Deletes a single revision. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function delete_item($request) + { + } + /** + * Determines the allowed query_vars for a get_items() response and prepares + * them for WP_Query. + * + * @since 5.0.0 + * + * @param array $prepared_args Optional. Prepared WP_Query arguments. Default empty array. + * @param WP_REST_Request $request Optional. Full details about the request. + * @return array Items query arguments. + */ + protected function prepare_items_query($prepared_args = array(), $request = \null) + { + } + /** + * Prepares the revision for the REST response. + * + * @since 4.7.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Post $item Post revision object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Checks the post_date_gmt or modified_gmt and prepare any post or + * modified date for single post output. + * + * @since 4.7.0 + * + * @param string $date_gmt GMT publication time. + * @param string|null $date Optional. Local publication time. Default null. + * @return string|null ISO8601/RFC3339 formatted datetime, otherwise null. + */ + protected function prepare_date_response($date_gmt, $date = \null) + { + } + /** + * Retrieves the revision's schema, conforming to JSON Schema. + * + * @since 4.7.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the query params for collections. + * + * @since 4.7.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + /** + * Checks the post excerpt and prepare it for single post output. + * + * @since 4.7.0 + * + * @param string $excerpt The post excerpt. + * @param WP_Post $post Post revision object. + * @return string Prepared excerpt or empty string. + */ + protected function prepare_excerpt_response($excerpt, $post) + { + } + } + /** + * REST API: WP_REST_Autosaves_Controller class. + * + * @package WordPress + * @subpackage REST_API + * @since 5.0.0 + */ + /** + * Core class used to access autosaves via the REST API. + * + * @since 5.0.0 + * + * @see WP_REST_Revisions_Controller + * @see WP_REST_Controller + */ + class WP_REST_Autosaves_Controller extends \WP_REST_Revisions_Controller + { + /** + * Constructor. + * + * @since 5.0.0 + * + * @param string $parent_post_type Post type of the parent. + */ + public function __construct($parent_post_type) + { + } + /** + * Registers the routes for autosaves. + * + * @since 5.0.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Get the parent post. + * + * @since 5.0.0 + * + * @param int $parent_id Supplied ID. + * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise. + */ + protected function get_parent($parent_id) + { + } + /** + * Checks if a given request has access to get autosaves. + * + * @since 5.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Checks if a given request has access to create an autosave revision. + * + * Autosave revisions inherit permissions from the parent post, + * check if the current user has permission to edit the post. + * + * @since 5.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to create the item, WP_Error object otherwise. + */ + public function create_item_permissions_check($request) + { + } + /** + * Creates, updates or deletes an autosave revision. + * + * @since 5.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function create_item($request) + { + } + /** + * Get the autosave, if the ID is valid. + * + * @since 5.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_Post|WP_Error Revision post object if ID is valid, WP_Error otherwise. + */ + public function get_item($request) + { + } + /** + * Gets a collection of autosaves using wp_get_post_autosave. + * + * Contains the user's autosave, for empty if it doesn't exist. + * + * @since 5.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Retrieves the autosave's schema, conforming to JSON Schema. + * + * @since 5.0.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Creates autosave for the specified post. + * + * From wp-admin/post.php. + * + * @since 5.0.0 + * + * @param array $post_data Associative array containing the post data. + * @return mixed The autosave revision ID or WP_Error. + */ + public function create_post_autosave($post_data) + { + } + /** + * Prepares the revision for the REST response. + * + * @since 5.0.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Post $item Post revision object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Retrieves the query params for the autosaves collection. + * + * @since 5.0.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + } + /** + * REST API: WP_REST_Block_Directory_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.5.0 + */ + /** + * Controller which provides REST endpoint for the blocks. + * + * @since 5.5.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Block_Directory_Controller extends \WP_REST_Controller + { + /** + * Constructs the controller. + */ + public function __construct() + { + } + /** + * Registers the necessary REST API routes. + */ + public function register_routes() + { + } + /** + * Checks whether a given request has permission to install and activate plugins. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has permission, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Search and retrieve blocks metadata + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Parse block metadata for a block, and prepare it for an API response. + * + * @since 5.5.0 + * @since 5.9.0 Renamed `$plugin` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param array $item The plugin metadata. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Generates a list of links to include in the response for the plugin. + * + * @since 5.5.0 + * + * @param array $plugin The plugin data from WordPress.org. + * @return array + */ + protected function prepare_links($plugin) + { + } + /** + * Finds an installed plugin for the given slug. + * + * @since 5.5.0 + * + * @param string $slug The WordPress.org directory slug for a plugin. + * @return string The plugin file found matching it. + */ + protected function find_plugin_for_slug($slug) + { + } + /** + * Retrieves the theme's schema, conforming to JSON Schema. + * + * @since 5.5.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the search params for the blocks collection. + * + * @since 5.5.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + } + /** + * REST API: WP_REST_Block_Pattern_Catergories_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 6.0.0 + */ + /** + * Core class used to access block pattern categories via the REST API. + * + * @since 6.0.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Block_Pattern_Categories_Controller extends \WP_REST_Controller + { + /** + * Constructs the controller. + * + * @since 6.0.0 + */ + public function __construct() + { + } + /** + * Registers the routes for the objects of the controller. + * + * @since 6.0.0 + */ + public function register_routes() + { + } + /** + * Checks whether a given request has permission to read block patterns. + * + * @since 6.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves all block pattern categories. + * + * @since 6.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Prepare a raw block pattern category before it gets output in a REST API response. + * + * @since 6.0.0 + * + * @param array $item Raw category as registered, before any changes. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Retrieves the block pattern category schema, conforming to JSON Schema. + * + * @since 6.0.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + } + /** + * REST API: WP_REST_Block_Patterns_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 6.0.0 + */ + /** + * Core class used to access block patterns via the REST API. + * + * @since 6.0.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Block_Patterns_Controller extends \WP_REST_Controller + { + /** + * Constructs the controller. + * + * @since 6.0.0 + */ + public function __construct() + { + } + /** + * Registers the routes for the objects of the controller. + * + * @since 6.0.0 + */ + public function register_routes() + { + } + /** + * Checks whether a given request has permission to read block patterns. + * + * @since 6.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves all block patterns. + * + * @since 6.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Prepare a raw block pattern before it gets output in a REST API response. + * + * @since 6.0.0 + * + * @param array $item Raw pattern as registered, before any changes. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Retrieves the block pattern schema, conforming to JSON Schema. + * + * @since 6.0.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + } + /** + * Block Renderer REST API: WP_REST_Block_Renderer_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.0.0 + */ + /** + * Controller which provides REST endpoint for rendering a block. + * + * @since 5.0.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Block_Renderer_Controller extends \WP_REST_Controller + { + /** + * Constructs the controller. + * + * @since 5.0.0 + */ + public function __construct() + { + } + /** + * Registers the necessary REST API routes, one for each dynamic block. + * + * @since 5.0.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Checks if a given request has access to read blocks. + * + * @since 5.0.0 + * + * @global WP_Post $post Global post object. + * + * @param WP_REST_Request $request Request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Returns block output from block's registered render_callback. + * + * @since 5.0.0 + * + * @global WP_Post $post Global post object. + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Retrieves block's output schema, conforming to JSON Schema. + * + * @since 5.0.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + } + /** + * REST API: WP_REST_Block_Types_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.5.0 + */ + /** + * Core class used to access block types via the REST API. + * + * @since 5.5.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Block_Types_Controller extends \WP_REST_Controller + { + /** + * Instance of WP_Block_Type_Registry. + * + * @since 5.5.0 + * @var WP_Block_Type_Registry + */ + protected $block_registry; + /** + * Instance of WP_Block_Styles_Registry. + * + * @since 5.5.0 + * @var WP_Block_Styles_Registry + */ + protected $style_registry; + /** + * Constructor. + * + * @since 5.5.0 + */ + public function __construct() + { + } + /** + * Registers the routes for block types. + * + * @since 5.5.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Checks whether a given request has permission to read post block types. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves all post block types, depending on user context. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Checks if a given request has access to read a block type. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Checks whether a given block type should be visible. + * + * @since 5.5.0 + * + * @return true|WP_Error True if the block type is visible, WP_Error otherwise. + */ + protected function check_read_permission() + { + } + /** + * Get the block, if the name is valid. + * + * @since 5.5.0 + * + * @param string $name Block name. + * @return WP_Block_Type|WP_Error Block type object if name is valid, WP_Error otherwise. + */ + protected function get_block($name) + { + } + /** + * Retrieves a specific block type. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Prepares a block type object for serialization. + * + * @since 5.5.0 + * @since 5.9.0 Renamed `$block_type` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Block_Type $item Block type data. + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response Block type data. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the request. + * + * @since 5.5.0 + * + * @param WP_Block_Type $block_type Block type data. + * @return array Links for the given block type. + */ + protected function prepare_links($block_type) + { + } + /** + * Retrieves the block type' schema, conforming to JSON Schema. + * + * @since 5.5.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the query params for collections. + * + * @since 5.5.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + } + /** + * Reusable blocks REST API: WP_REST_Blocks_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.0.0 + */ + /** + * Controller which provides a REST endpoint for the editor to read, create, + * edit and delete reusable blocks. Blocks are stored as posts with the wp_block + * post type. + * + * @since 5.0.0 + * + * @see WP_REST_Posts_Controller + * @see WP_REST_Controller + */ + class WP_REST_Blocks_Controller extends \WP_REST_Posts_Controller + { + /** + * Checks if a block can be read. + * + * @since 5.0.0 + * + * @param WP_Post $post Post object that backs the block. + * @return bool Whether the block can be read. + */ + public function check_read_permission($post) + { + } + /** + * Filters a response based on the context defined in the schema. + * + * @since 5.0.0 + * + * @param array $data Response data to filter. + * @param string $context Context defined in the schema. + * @return array Filtered response. + */ + public function filter_response_by_context($data, $context) + { + } + /** + * Retrieves the block's schema, conforming to JSON Schema. + * + * @since 5.0.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + } + /** + * REST API: WP_REST_Comments_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core controller used to access comments via the REST API. + * + * @since 4.7.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Comments_Controller extends \WP_REST_Controller + { + /** + * Instance of a comment meta fields object. + * + * @since 4.7.0 + * @var WP_REST_Comment_Meta_Fields + */ + protected $meta; + /** + * Constructor. + * + * @since 4.7.0 + */ + public function __construct() + { + } + /** + * Registers the routes for comments. + * + * @since 4.7.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Checks if a given request has access to read comments. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves a list of comment items. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or error object on failure. + */ + public function get_items($request) + { + } + /** + * Get the comment, if the ID is valid. + * + * @since 4.7.2 + * + * @param int $id Supplied ID. + * @return WP_Comment|WP_Error Comment object if ID is valid, WP_Error otherwise. + */ + protected function get_comment($id) + { + } + /** + * Checks if a given request has access to read the comment. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Retrieves a comment. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or error object on failure. + */ + public function get_item($request) + { + } + /** + * Checks if a given request has access to create a comment. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to create items, error object otherwise. + */ + public function create_item_permissions_check($request) + { + } + /** + * Creates a comment. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or error object on failure. + */ + public function create_item($request) + { + } + /** + * Checks if a given REST request has access to update a comment. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to update the item, error object otherwise. + */ + public function update_item_permissions_check($request) + { + } + /** + * Updates a comment. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or error object on failure. + */ + public function update_item($request) + { + } + /** + * Checks if a given request has access to delete a comment. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to delete the item, error object otherwise. + */ + public function delete_item_permissions_check($request) + { + } + /** + * Deletes a comment. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or error object on failure. + */ + public function delete_item($request) + { + } + /** + * Prepares a single comment output for response. + * + * @since 4.7.0 + * @since 5.9.0 Renamed `$comment` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Comment $item Comment object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the request. + * + * @since 4.7.0 + * + * @param WP_Comment $comment Comment object. + * @return array Links for the given comment. + */ + protected function prepare_links($comment) + { + } + /** + * Prepends internal property prefix to query parameters to match our response fields. + * + * @since 4.7.0 + * + * @param string $query_param Query parameter. + * @return string The normalized query parameter. + */ + protected function normalize_query_param($query_param) + { + } + /** + * Checks comment_approved to set comment status for single comment output. + * + * @since 4.7.0 + * + * @param string|int $comment_approved comment status. + * @return string Comment status. + */ + protected function prepare_status_response($comment_approved) + { + } + /** + * Prepares a single comment to be inserted into the database. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Request object. + * @return array|WP_Error Prepared comment, otherwise WP_Error object. + */ + protected function prepare_item_for_database($request) + { + } + /** + * Retrieves the comment's schema, conforming to JSON Schema. + * + * @since 4.7.0 + * + * @return array + */ + public function get_item_schema() + { + } + /** + * Retrieves the query params for collections. + * + * @since 4.7.0 + * + * @return array Comments collection parameters. + */ + public function get_collection_params() + { + } + /** + * Sets the comment_status of a given comment object when creating or updating a comment. + * + * @since 4.7.0 + * + * @param string|int $new_status New comment status. + * @param int $comment_id Comment ID. + * @return bool Whether the status was changed. + */ + protected function handle_status_param($new_status, $comment_id) + { + } + /** + * Checks if the post can be read. + * + * Correctly handles posts with the inherit status. + * + * @since 4.7.0 + * + * @param WP_Post $post Post object. + * @param WP_REST_Request $request Request data to check. + * @return bool Whether post can be read. + */ + protected function check_read_post_permission($post, $request) + { + } + /** + * Checks if the comment can be read. + * + * @since 4.7.0 + * + * @param WP_Comment $comment Comment object. + * @param WP_REST_Request $request Request data to check. + * @return bool Whether the comment can be read. + */ + protected function check_read_permission($comment, $request) + { + } + /** + * Checks if a comment can be edited or deleted. + * + * @since 4.7.0 + * + * @param WP_Comment $comment Comment object. + * @return bool Whether the comment can be edited or deleted. + */ + protected function check_edit_permission($comment) + { + } + /** + * Checks a comment author email for validity. + * + * Accepts either a valid email address or empty string as a valid comment + * author email address. Setting the comment author email to an empty + * string is allowed when a comment is being updated. + * + * @since 4.7.0 + * + * @param string $value Author email value submitted. + * @param WP_REST_Request $request Full details about the request. + * @param string $param The parameter name. + * @return string|WP_Error The sanitized email address, if valid, + * otherwise an error. + */ + public function check_comment_author_email($value, $request, $param) + { + } + /** + * If empty comments are not allowed, checks if the provided comment content is not empty. + * + * @since 5.6.0 + * + * @param array $prepared_comment The prepared comment data. + * @return bool True if the content is allowed, false otherwise. + */ + protected function check_is_comment_content_allowed($prepared_comment) + { + } + } + /** + * REST API: WP_REST_Edit_Site_Export_Controller class + * + * @package WordPress + * @subpackage REST_API + */ + /** + * Controller which provides REST endpoint for exporting current templates + * and template parts. + * + * @since 5.9.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Edit_Site_Export_Controller extends \WP_REST_Controller + { + /** + * Constructor. + * + * @since 5.9.0 + */ + public function __construct() + { + } + /** + * Registers the site export route. + * + * @since 5.9.0 + */ + public function register_routes() + { + } + /** + * Checks whether a given request has permission to export. + * + * @since 5.9.0 + * + * @return WP_Error|true True if the request has access, or WP_Error object. + */ + public function permissions_check() + { + } + /** + * Output a ZIP file with an export of the current templates + * and template parts from the site editor, and close the connection. + * + * @since 5.9.0 + * + * @return WP_Error|void + */ + public function export() + { + } + } + /** + * REST API: WP_REST_Global_Styles_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.9.0 + */ + /** + * Base Global Styles REST API Controller. + */ + class WP_REST_Global_Styles_Controller extends \WP_REST_Controller + { + /** + * Post type. + * + * @since 5.9.0 + * @var string + */ + protected $post_type; + /** + * Constructor. + * @since 5.9.0 + */ + public function __construct() + { + } + /** + * Registers the controllers routes. + * + * @since 5.9.0 + * + * @return void + */ + public function register_routes() + { + } + /** + * Sanitize the global styles ID or stylesheet to decode endpoint. + * For example, `wp/v2/global-styles/twentytwentytwo%200.4.0` + * would be decoded to `twentytwentytwo 0.4.0`. + * + * @since 5.9.0 + * + * @param string $id_or_stylesheet Global styles ID or stylesheet. + * @return string Sanitized global styles ID or stylesheet. + */ + public function _sanitize_global_styles_callback($id_or_stylesheet) + { + } + /** + * Get the post, if the ID is valid. + * + * @since 5.9.0 + * + * @param int $id Supplied ID. + * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise. + */ + protected function get_post($id) + { + } + /** + * Checks if a given request has access to read a single global style. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Checks if a global style can be read. + * + * @since 5.9.0 + * + * @param WP_Post $post Post object. + * @return bool Whether the post can be read. + */ + protected function check_read_permission($post) + { + } + /** + * Returns the given global styles config. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request The request instance. + * + * @return WP_REST_Response|WP_Error + */ + public function get_item($request) + { + } + /** + * Checks if a given request has access to write a single global styles config. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has write access for the item, WP_Error object otherwise. + */ + public function update_item_permissions_check($request) + { + } + /** + * Checks if a global style can be edited. + * + * @since 5.9.0 + * + * @param WP_Post $post Post object. + * @return bool Whether the post can be edited. + */ + protected function check_update_permission($post) + { + } + /** + * Updates a single global style config. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function update_item($request) + { + } + /** + * Prepares a single global styles config for update. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Request object. + * @return stdClass Changes to pass to wp_update_post. + */ + protected function prepare_item_for_database($request) + { + } + /** + * Prepare a global styles config output for response. + * + * @since 5.9.0 + * + * @param WP_Post $post Global Styles post object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($post, $request) + { + } + /** + * Prepares links for the request. + * + * @since 5.9.0 + * + * @param integer $id ID. + * @return array Links for the given post. + */ + protected function prepare_links($id) + { + } + /** + * Get the link relations available for the post and current user. + * + * @since 5.9.0 + * + * @return array List of link relations. + */ + protected function get_available_actions() + { + } + /** + * Overwrites the default protected title format. + * + * By default, WordPress will show password protected posts with a title of + * "Protected: %s", as the REST API communicates the protected status of a post + * in a machine readable format, we remove the "Protected: " prefix. + * + * @since 5.9.0 + * + * @return string Protected title format. + */ + public function protected_title_format() + { + } + /** + * Retrieves the query params for the global styles collection. + * + * @since 5.9.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + /** + * Retrieves the global styles type' schema, conforming to JSON Schema. + * + * @since 5.9.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Checks if a given request has access to read a single theme global styles config. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_theme_item_permissions_check($request) + { + } + /** + * Returns the given theme global styles config. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request The request instance. + * @return WP_REST_Response|WP_Error + */ + public function get_theme_item($request) + { + } + /** + * Checks if a given request has access to read a single theme global styles config. + * + * @since 6.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_theme_items_permissions_check($request) + { + } + /** + * Returns the given theme global styles variations. + * + * @since 6.0.0 + * + * @param WP_REST_Request $request The request instance. + * + * @return WP_REST_Response|WP_Error + */ + public function get_theme_items($request) + { + } + } + /** + * REST API: WP_REST_Menu_Items_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.9.0 + */ + /** + * Core class to access nav items via the REST API. + * + * @since 5.9.0 + * + * @see WP_REST_Posts_Controller + */ + class WP_REST_Menu_Items_Controller extends \WP_REST_Posts_Controller + { + /** + * Gets the nav menu item, if the ID is valid. + * + * @since 5.9.0 + * + * @param int $id Supplied ID. + * @return object|WP_Error Post object if ID is valid, WP_Error otherwise. + */ + protected function get_nav_menu_item($id) + { + } + /** + * Checks if a given request has access to read menu items. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Checks if a given request has access to read a menu item if they have access to edit them. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return bool|WP_Error True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Checks whether the current user has read permission for the endpoint. + * + * This allows for any user that can `edit_theme_options` or edit any REST API available post type. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return bool|WP_Error Whether the current user has permission. + */ + protected function check_has_read_only_access($request) + { + } + /** + * Creates a single post. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function create_item($request) + { + } + /** + * Updates a single nav menu item. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function update_item($request) + { + } + /** + * Deletes a single menu item. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error True on success, or WP_Error object on failure. + */ + public function delete_item($request) + { + } + /** + * Prepares a single post for create or update. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Request object. + * + * @return object|WP_Error + */ + protected function prepare_item_for_database($request) + { + } + /** + * Prepares a single post output for response. + * + * @since 5.9.0 + * + * @param WP_Post $item Post object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the request. + * + * @since 5.9.0 + * + * @param WP_Post $post Post object. + * @return array Links for the given post. + */ + protected function prepare_links($post) + { + } + /** + * Retrieves Link Description Objects that should be added to the Schema for the posts collection. + * + * @since 5.9.0 + * + * @return array + */ + protected function get_schema_links() + { + } + /** + * Retrieves the term's schema, conforming to JSON Schema. + * + * @since 5.9.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the query params for the posts collection. + * + * @since 5.9.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + /** + * Determines the allowed query_vars for a get_items() response and prepares + * them for WP_Query. + * + * @since 5.9.0 + * + * @param array $prepared_args Optional. Prepared WP_Query arguments. Default empty array. + * @param WP_REST_Request $request Optional. Full details about the request. + * @return array Items query arguments. + */ + protected function prepare_items_query($prepared_args = array(), $request = \null) + { + } + /** + * Gets the id of the menu that the given menu item belongs to. + * + * @since 5.9.0 + * + * @param int $menu_item_id Menu item id. + * @return int + */ + protected function get_menu_id($menu_item_id) + { + } + } + /** + * REST API: WP_REST_Menu_Locations_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.9.0 + */ + /** + * Core class used to access menu locations via the REST API. + * + * @since 5.9.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Menu_Locations_Controller extends \WP_REST_Controller + { + /** + * Menu Locations Constructor. + * + * @since 5.9.0 + */ + public function __construct() + { + } + /** + * Registers the routes for the objects of the controller. + * + * @since 5.9.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Checks whether a given request has permission to read menu locations. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_Error|bool True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves all menu locations, depending on user context. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Checks if a given request has access to read a menu location. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_Error|bool True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Retrieves a specific menu location. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Prepares a menu location object for serialization. + * + * @since 5.9.0 + * + * @param stdClass $item Post status data. + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response Menu location data. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the request. + * + * @since 5.9.0 + * + * @param stdClass $location Menu location. + * @return array Links for the given menu location. + */ + protected function prepare_links($location) + { + } + /** + * Retrieves the menu location's schema, conforming to JSON Schema. + * + * @since 5.9.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the query params for collections. + * + * @since 5.9.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + } + /** + * REST API: WP_REST_Terms_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core class used to managed terms associated with a taxonomy via the REST API. + * + * @since 4.7.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Terms_Controller extends \WP_REST_Controller + { + /** + * Taxonomy key. + * + * @since 4.7.0 + * @var string + */ + protected $taxonomy; + /** + * Instance of a term meta fields object. + * + * @since 4.7.0 + * @var WP_REST_Term_Meta_Fields + */ + protected $meta; + /** + * Column to have the terms be sorted by. + * + * @since 4.7.0 + * @var string + */ + protected $sort_column; + /** + * Number of terms that were found. + * + * @since 4.7.0 + * @var int + */ + protected $total_terms; + /** + * Whether the controller supports batching. + * + * @since 5.9.0 + * @var array + */ + protected $allow_batch = array('v1' => \true); + /** + * Constructor. + * + * @since 4.7.0 + * + * @param string $taxonomy Taxonomy key. + */ + public function __construct($taxonomy) + { + } + /** + * Registers the routes for terms. + * + * @since 4.7.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Checks if the terms for a post can be read. + * + * @since 6.0.3 + * + * @param WP_Post $post Post object. + * @param WP_REST_Request $request Full details about the request. + * @return bool Whether the terms for the post can be read. + */ + public function check_read_terms_permission_for_post($post, $request) + { + } + /** + * Checks if a request has access to read terms in the specified taxonomy. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, otherwise false or WP_Error object. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves terms associated with a taxonomy. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Get the term, if the ID is valid. + * + * @since 4.7.2 + * + * @param int $id Supplied ID. + * @return WP_Term|WP_Error Term object if ID is valid, WP_Error otherwise. + */ + protected function get_term($id) + { + } + /** + * Checks if a request has access to read or edit the specified term. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, otherwise false or WP_Error object. + */ + public function get_item_permissions_check($request) + { + } + /** + * Gets a single term from a taxonomy. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Checks if a request has access to create a term. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to create items, false or WP_Error object otherwise. + */ + public function create_item_permissions_check($request) + { + } + /** + * Creates a single term in a taxonomy. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function create_item($request) + { + } + /** + * Checks if a request has access to update the specified term. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to update the item, false or WP_Error object otherwise. + */ + public function update_item_permissions_check($request) + { + } + /** + * Updates a single term from a taxonomy. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function update_item($request) + { + } + /** + * Checks if a request has access to delete the specified term. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to delete the item, otherwise false or WP_Error object. + */ + public function delete_item_permissions_check($request) + { + } + /** + * Deletes a single term from a taxonomy. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function delete_item($request) + { + } + /** + * Prepares a single term for create or update. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Request object. + * @return object Term object. + */ + public function prepare_item_for_database($request) + { + } + /** + * Prepares a single term output for response. + * + * @since 4.7.0 + * + * @param WP_Term $item Term object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the request. + * + * @since 4.7.0 + * + * @param WP_Term $term Term object. + * @return array Links for the given term. + */ + protected function prepare_links($term) + { + } + /** + * Retrieves the term's schema, conforming to JSON Schema. + * + * @since 4.7.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the query params for collections. + * + * @since 4.7.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + /** + * Checks that the taxonomy is valid. + * + * @since 4.7.0 + * + * @param string $taxonomy Taxonomy to check. + * @return bool Whether the taxonomy is allowed for REST management. + */ + protected function check_is_taxonomy_allowed($taxonomy) + { + } + } + /** + * REST API: WP_REST_Menus_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.9.0 + */ + /** + * Core class used to managed menu terms associated via the REST API. + * + * @since 5.9.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Menus_Controller extends \WP_REST_Terms_Controller + { + /** + * Checks if a request has access to read menus. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return bool|WP_Error True if the request has read access, otherwise false or WP_Error object. + */ + public function get_items_permissions_check($request) + { + } + /** + * Checks if a request has access to read or edit the specified menu. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return bool|WP_Error True if the request has read access for the item, otherwise false or WP_Error object. + */ + public function get_item_permissions_check($request) + { + } + /** + * Gets the term, if the ID is valid. + * + * @since 5.9.0 + * + * @param int $id Supplied ID. + * @return WP_Term|WP_Error Term object if ID is valid, WP_Error otherwise. + */ + protected function get_term($id) + { + } + /** + * Checks whether the current user has read permission for the endpoint. + * + * This allows for any user that can `edit_theme_options` or edit any REST API available post type. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return bool|WP_Error Whether the current user has permission. + */ + protected function check_has_read_only_access($request) + { + } + /** + * Prepares a single term output for response. + * + * @since 5.9.0 + * + * @param WP_Term $term Term object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($term, $request) + { + } + /** + * Prepares links for the request. + * + * @since 5.9.0 + * + * @param WP_Term $term Term object. + * @return array Links for the given term. + */ + protected function prepare_links($term) + { + } + /** + * Prepares a single term for create or update. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Request object. + * @return object Prepared term data. + */ + public function prepare_item_for_database($request) + { + } + /** + * Creates a single term in a taxonomy. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function create_item($request) + { + } + /** + * Updates a single term from a taxonomy. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function update_item($request) + { + } + /** + * Deletes a single term from a taxonomy. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function delete_item($request) + { + } + /** + * Returns the value of a menu's auto_add setting. + * + * @since 5.9.0 + * + * @param int $menu_id The menu id to query. + * @return bool The value of auto_add. + */ + protected function get_menu_auto_add($menu_id) + { + } + /** + * Updates the menu's auto add from a REST request. + * + * @since 5.9.0 + * + * @param int $menu_id The menu id to update. + * @param WP_REST_Request $request Full details about the request. + * @return bool True if the auto add setting was successfully updated. + */ + protected function handle_auto_add($menu_id, $request) + { + } + /** + * Returns the names of the locations assigned to the menu. + * + * @since 5.9.0 + * + * @param int $menu_id The menu id. + * @return string[] The locations assigned to the menu. + */ + protected function get_menu_locations($menu_id) + { + } + /** + * Updates the menu's locations from a REST request. + * + * @since 5.9.0 + * + * @param int $menu_id The menu id to update. + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True on success, a WP_Error on an error updating any of the locations. + */ + protected function handle_locations($menu_id, $request) + { + } + /** + * Retrieves the term's schema, conforming to JSON Schema. + * + * @since 5.9.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + } + /** + * Block Pattern Directory REST API: WP_REST_Pattern_Directory_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.8.0 + */ + /** + * Controller which provides REST endpoint for block patterns. + * + * This simply proxies the endpoint at http://api.wordpress.org/patterns/1.0/. That isn't necessary for + * functionality, but is desired for privacy. It prevents api.wordpress.org from knowing the user's IP address. + * + * @since 5.8.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Pattern_Directory_Controller extends \WP_REST_Controller + { + /** + * Constructs the controller. + * + * @since 5.8.0 + */ + public function __construct() + { + } + /** + * Registers the necessary REST API routes. + * + * @since 5.8.0 + */ + public function register_routes() + { + } + /** + * Checks whether a given request has permission to view the local block pattern directory. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has permission, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Search and retrieve block patterns metadata + * + * @since 5.8.0 + * @since 6.0.0 Added 'slug' to request. + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Prepare a raw block pattern before it gets output in a REST API response. + * + * @since 5.8.0 + * @since 5.9.0 Renamed `$raw_pattern` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param object $item Raw pattern from api.wordpress.org, before any changes. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Retrieves the block pattern's schema, conforming to JSON Schema. + * + * @since 5.8.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the search parameters for the block pattern's collection. + * + * @since 5.8.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + /* + * Include a hash of the query args, so that different requests are stored in + * separate caches. + * + * MD5 is chosen for its speed, low-collision rate, universal availability, and to stay + * under the character limit for `_site_transient_timeout_{...}` keys. + * + * @link https://stackoverflow.com/questions/3665247/fastest-hash-for-non-cryptographic-uses + * + * @since 6.0.0 + * + * @param array $query_args Query arguments to generate a transient key from. + * @return string Transient key. + */ + protected function get_transient_key($query_args) + { + } + } + /** + * REST API: WP_REST_Plugins_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.5.0 + */ + /** + * Core class to access plugins via the REST API. + * + * @since 5.5.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Plugins_Controller extends \WP_REST_Controller + { + const PATTERN = '[^.\\/]+(?:\\/[^.\\/]+)?'; + /** + * Plugins controller constructor. + * + * @since 5.5.0 + */ + public function __construct() + { + } + /** + * Registers the routes for the plugins controller. + * + * @since 5.5.0 + */ + public function register_routes() + { + } + /** + * Checks if a given request has access to get plugins. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves a collection of plugins. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Checks if a given request has access to get a specific plugin. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Retrieves one plugin from the site. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Checks if the given plugin can be viewed by the current user. + * + * On multisite, this hides non-active network only plugins if the user does not have permission + * to manage network plugins. + * + * @since 5.5.0 + * + * @param string $plugin The plugin file to check. + * @return true|WP_Error True if can read, a WP_Error instance otherwise. + */ + protected function check_read_permission($plugin) + { + } + /** + * Checks if a given request has access to upload plugins. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise. + */ + public function create_item_permissions_check($request) + { + } + /** + * Uploads a plugin and optionally activates it. + * + * @since 5.5.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function create_item($request) + { + } + /** + * Checks if a given request has access to update a specific plugin. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise. + */ + public function update_item_permissions_check($request) + { + } + /** + * Updates one plugin. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function update_item($request) + { + } + /** + * Checks if a given request has access to delete a specific plugin. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise. + */ + public function delete_item_permissions_check($request) + { + } + /** + * Deletes one plugin from the site. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function delete_item($request) + { + } + /** + * Prepares the plugin for the REST response. + * + * @since 5.5.0 + * + * @param array $item Unmarked up and untranslated plugin data from {@see get_plugin_data()}. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the request. + * + * @since 5.5.0 + * + * @param array $item The plugin item. + * @return array[] + */ + protected function prepare_links($item) + { + } + /** + * Gets the plugin header data for a plugin. + * + * @since 5.5.0 + * + * @param string $plugin The plugin file to get data for. + * @return array|WP_Error The plugin data, or a WP_Error if the plugin is not installed. + */ + protected function get_plugin_data($plugin) + { + } + /** + * Get's the activation status for a plugin. + * + * @since 5.5.0 + * + * @param string $plugin The plugin file to check. + * @return string Either 'network-active', 'active' or 'inactive'. + */ + protected function get_plugin_status($plugin) + { + } + /** + * Handle updating a plugin's status. + * + * @since 5.5.0 + * + * @param string $plugin The plugin file to update. + * @param string $new_status The plugin's new status. + * @param string $current_status The plugin's current status. + * @return true|WP_Error + */ + protected function plugin_status_permission_check($plugin, $new_status, $current_status) + { + } + /** + * Handle updating a plugin's status. + * + * @since 5.5.0 + * + * @param string $plugin The plugin file to update. + * @param string $new_status The plugin's new status. + * @param string $current_status The plugin's current status. + * @return true|WP_Error + */ + protected function handle_plugin_status($plugin, $new_status, $current_status) + { + } + /** + * Checks that the "plugin" parameter is a valid path. + * + * @since 5.5.0 + * + * @param string $file The plugin file parameter. + * @return bool + */ + public function validate_plugin_param($file) + { + } + /** + * Sanitizes the "plugin" parameter to be a proper plugin file with ".php" appended. + * + * @since 5.5.0 + * + * @param string $file The plugin file parameter. + * @return string + */ + public function sanitize_plugin_param($file) + { + } + /** + * Checks if the plugin matches the requested parameters. + * + * @since 5.5.0 + * + * @param WP_REST_Request $request The request to require the plugin matches against. + * @param array $item The plugin item. + * @return bool + */ + protected function does_plugin_match_request($request, $item) + { + } + /** + * Checks if the plugin is installed. + * + * @since 5.5.0 + * + * @param string $plugin The plugin file. + * @return bool + */ + protected function is_plugin_installed($plugin) + { + } + /** + * Determine if the endpoints are available. + * + * Only the 'Direct' filesystem transport, and SSH/FTP when credentials are stored are supported at present. + * + * @since 5.5.0 + * + * @return true|WP_Error True if filesystem is available, WP_Error otherwise. + */ + protected function is_filesystem_available() + { + } + /** + * Retrieves the plugin's schema, conforming to JSON Schema. + * + * @since 5.5.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the query params for the collections. + * + * @since 5.5.0 + * + * @return array Query parameters for the collection. + */ + public function get_collection_params() + { + } + } + /** + * REST API: WP_REST_Post_Statuses_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core class used to access post statuses via the REST API. + * + * @since 4.7.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Post_Statuses_Controller extends \WP_REST_Controller + { + /** + * Constructor. + * + * @since 4.7.0 + */ + public function __construct() + { + } + /** + * Registers the routes for post statuses. + * + * @since 4.7.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Checks whether a given request has permission to read post statuses. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves all post statuses, depending on user context. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Checks if a given request has access to read a post status. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Checks whether a given post status should be visible. + * + * @since 4.7.0 + * + * @param object $status Post status. + * @return bool True if the post status is visible, otherwise false. + */ + protected function check_read_permission($status) + { + } + /** + * Retrieves a specific post status. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Prepares a post status object for serialization. + * + * @since 4.7.0 + * @since 5.9.0 Renamed `$status` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param stdClass $item Post status data. + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response Post status data. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Retrieves the post status' schema, conforming to JSON Schema. + * + * @since 4.7.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the query params for collections. + * + * @since 4.7.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + } + /** + * REST API: WP_REST_Post_Types_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core class to access post types via the REST API. + * + * @since 4.7.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Post_Types_Controller extends \WP_REST_Controller + { + /** + * Constructor. + * + * @since 4.7.0 + */ + public function __construct() + { + } + /** + * Registers the routes for post types. + * + * @since 4.7.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Checks whether a given request has permission to read types. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves all public post types. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Retrieves a specific post type. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Prepares a post type object for serialization. + * + * @since 4.7.0 + * @since 5.9.0 Renamed `$post_type` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Post_Type $item Post type object. + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the request. + * + * @since 6.1.0 + * + * @param WP_Post_Type $post_type The post type. + * @return array Links for the given post type. + */ + protected function prepare_links($post_type) + { + } + /** + * Retrieves the post type's schema, conforming to JSON Schema. + * + * @since 4.7.0 + * @since 4.8.0 The `supports` property was added. + * @since 5.9.0 The `visibility` and `rest_namespace` properties were added. + * @since 6.1.0 The `icon` property was added. + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the query params for collections. + * + * @since 4.7.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + } + /** + * REST API: WP_REST_Search_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.0.0 + */ + /** + * Core class to search through all WordPress content via the REST API. + * + * @since 5.0.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Search_Controller extends \WP_REST_Controller + { + /** + * ID property name. + */ + const PROP_ID = 'id'; + /** + * Title property name. + */ + const PROP_TITLE = 'title'; + /** + * URL property name. + */ + const PROP_URL = 'url'; + /** + * Type property name. + */ + const PROP_TYPE = 'type'; + /** + * Subtype property name. + */ + const PROP_SUBTYPE = 'subtype'; + /** + * Identifier for the 'any' type. + */ + const TYPE_ANY = 'any'; + /** + * Search handlers used by the controller. + * + * @since 5.0.0 + * @var WP_REST_Search_Handler[] + */ + protected $search_handlers = array(); + /** + * Constructor. + * + * @since 5.0.0 + * + * @param array $search_handlers List of search handlers to use in the controller. Each search + * handler instance must extend the `WP_REST_Search_Handler` class. + */ + public function __construct(array $search_handlers) + { + } + /** + * Registers the routes for the search controller. + * + * @since 5.0.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Checks if a given request has access to search content. + * + * @since 5.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has search access, WP_Error object otherwise. + */ + public function get_items_permission_check($request) + { + } + /** + * Retrieves a collection of search results. + * + * @since 5.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Prepares a single search result for response. + * + * @since 5.0.0 + * @since 5.6.0 The `$id` parameter can accept a string. + * @since 5.9.0 Renamed `$id` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param int|string $item ID of the item to prepare. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Retrieves the item schema, conforming to JSON Schema. + * + * @since 5.0.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the query params for the search results collection. + * + * @since 5.0.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + /** + * Sanitizes the list of subtypes, to ensure only subtypes of the passed type are included. + * + * @since 5.0.0 + * + * @param string|array $subtypes One or more subtypes. + * @param WP_REST_Request $request Full details about the request. + * @param string $parameter Parameter name. + * @return array|WP_Error List of valid subtypes, or WP_Error object on failure. + */ + public function sanitize_subtypes($subtypes, $request, $parameter) + { + } + /** + * Gets the search handler to handle the current request. + * + * @since 5.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Search_Handler|WP_Error Search handler for the request type, or WP_Error object on failure. + */ + protected function get_search_handler($request) + { + } + } + /** + * REST API: WP_REST_Settings_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core class used to manage a site's settings via the REST API. + * + * @since 4.7.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Settings_Controller extends \WP_REST_Controller + { + /** + * Constructor. + * + * @since 4.7.0 + */ + public function __construct() + { + } + /** + * Registers the routes for the site's settings. + * + * @since 4.7.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Checks if a given request has access to read and manage settings. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return bool True if the request has read access for the item, otherwise false. + */ + public function get_item_permissions_check($request) + { + } + /** + * Retrieves the settings. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return array|WP_Error Array on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Prepares a value for output based off a schema array. + * + * @since 4.7.0 + * + * @param mixed $value Value to prepare. + * @param array $schema Schema to match. + * @return mixed The prepared value. + */ + protected function prepare_value($value, $schema) + { + } + /** + * Updates settings for the settings object. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return array|WP_Error Array on success, or error object on failure. + */ + public function update_item($request) + { + } + /** + * Retrieves all of the registered options for the Settings API. + * + * @since 4.7.0 + * + * @return array Array of registered options. + */ + protected function get_registered_options() + { + } + /** + * Retrieves the site setting schema, conforming to JSON Schema. + * + * @since 4.7.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Custom sanitize callback used for all options to allow the use of 'null'. + * + * By default, the schema of settings will throw an error if a value is set to + * `null` as it's not a valid value for something like "type => string". We + * provide a wrapper sanitizer to allow the use of `null`. + * + * @since 4.7.0 + * + * @param mixed $value The value for the setting. + * @param WP_REST_Request $request The request object. + * @param string $param The parameter name. + * @return mixed|WP_Error + */ + public function sanitize_callback($value, $request, $param) + { + } + /** + * Recursively add additionalProperties = false to all objects in a schema + * if no additionalProperties setting is specified. + * + * This is needed to restrict properties of objects in settings values to only + * registered items, as the REST API will allow additional properties by + * default. + * + * @since 4.9.0 + * @deprecated 6.1.0 Use {@see rest_default_additional_properties_to_false()} instead. + * + * @param array $schema The schema array. + * @return array + */ + protected function set_additional_properties_to_false($schema) + { + } + } + /** + * REST API: WP_REST_Sidebars_Controller class + * + * Original code from {@link https://github.com/martin-pettersson/wp-rest-api-sidebars Martin Pettersson (martin_pettersson@outlook.com)}. + * + * @package WordPress + * @subpackage REST_API + * @since 5.8.0 + */ + /** + * Core class used to manage a site's sidebars. + * + * @since 5.8.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Sidebars_Controller extends \WP_REST_Controller + { + /** + * Tracks whether {@see retrieve_widgets()} has been called in the current request. + * + * @since 5.9.0 + * @var bool + */ + protected $widgets_retrieved = \false; + /** + * Sidebars controller constructor. + * + * @since 5.8.0 + */ + public function __construct() + { + } + /** + * Registers the controllers routes. + * + * @since 5.8.0 + */ + public function register_routes() + { + } + /** + * Checks if a given request has access to get sidebars. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves the list of sidebars (active or inactive). + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response Response object on success. + */ + public function get_items($request) + { + } + /** + * Checks if a given request has access to get a single sidebar. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Checks if a sidebar can be read publicly. + * + * @since 5.9.0 + * + * @param array $sidebar The registered sidebar configuration. + * @return bool Whether the side can be read. + */ + protected function check_read_permission($sidebar) + { + } + /** + * Retrieves one sidebar from the collection. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Checks if a given request has access to update sidebars. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function update_item_permissions_check($request) + { + } + /** + * Updates a sidebar. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response Response object on success, or WP_Error object on failure. + */ + public function update_item($request) + { + } + /** + * Checks if the user has permissions to make the request. + * + * @since 5.8.0 + * + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + protected function do_permissions_check() + { + } + /** + * Retrieves the registered sidebar with the given id. + * + * @since 5.8.0 + * + * @param string|int $id ID of the sidebar. + * @return array|null The discovered sidebar, or null if it is not registered. + */ + protected function get_sidebar($id) + { + } + /** + * Looks for "lost" widgets once per request. + * + * @since 5.9.0 + * + * @see retrieve_widgets() + */ + protected function retrieve_widgets() + { + } + /** + * Prepares a single sidebar output for response. + * + * @since 5.8.0 + * @since 5.9.0 Renamed `$raw_sidebar` to `$item` to match parent class for PHP 8 named parameter support. + * + * @global array $wp_registered_sidebars The registered sidebars. + * @global array $wp_registered_widgets The registered widgets. + * + * @param array $item Sidebar instance. + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response Prepared response object. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the sidebar. + * + * @since 5.8.0 + * + * @param array $sidebar Sidebar. + * @return array Links for the given widget. + */ + protected function prepare_links($sidebar) + { + } + /** + * Retrieves the block type' schema, conforming to JSON Schema. + * + * @since 5.8.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + } + /** + * REST API: WP_REST_Site_Health_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.6.0 + */ + /** + * Core class for interacting with Site Health tests. + * + * @since 5.6.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Site_Health_Controller extends \WP_REST_Controller + { + /** + * Site Health controller constructor. + * + * @since 5.6.0 + * + * @param WP_Site_Health $site_health An instance of the site health class. + */ + public function __construct($site_health) + { + } + /** + * Registers API routes. + * + * @since 5.6.0 + * @since 6.1.0 Adds page-cache async test. + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Validates if the current user can request this REST endpoint. + * + * @since 5.6.0 + * + * @param string $check The endpoint check being ran. + * @return bool + */ + protected function validate_request_permission($check) + { + } + /** + * Checks if background updates work as expected. + * + * @since 5.6.0 + * + * @return array + */ + public function test_background_updates() + { + } + /** + * Checks that the site can reach the WordPress.org API. + * + * @since 5.6.0 + * + * @return array + */ + public function test_dotorg_communication() + { + } + /** + * Checks that loopbacks can be performed. + * + * @since 5.6.0 + * + * @return array + */ + public function test_loopback_requests() + { + } + /** + * Checks that the site's frontend can be accessed over HTTPS. + * + * @since 5.7.0 + * + * @return array + */ + public function test_https_status() + { + } + /** + * Checks that the authorization header is valid. + * + * @since 5.6.0 + * + * @return array + */ + public function test_authorization_header() + { + } + /** + * Checks that full page cache is active. + * + * @since 6.1.0 + * + * @return array The test result. + */ + public function test_page_cache() + { + } + /** + * Gets the current directory sizes for this install. + * + * @since 5.6.0 + * + * @return array|WP_Error + */ + public function get_directory_sizes() + { + } + /** + * Loads the admin textdomain for Site Health tests. + * + * The {@see WP_Site_Health} class is defined in WP-Admin, while the REST API operates in a front-end context. + * This means that the translations for Site Health won't be loaded by default in {@see load_default_textdomain()}. + * + * @since 5.6.0 + */ + protected function load_admin_textdomain() + { + } + /** + * Gets the schema for each site health test. + * + * @since 5.6.0 + * + * @return array The test schema. + */ + public function get_item_schema() + { + } + } + /** + * REST API: WP_REST_Taxonomies_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core class used to manage taxonomies via the REST API. + * + * @since 4.7.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Taxonomies_Controller extends \WP_REST_Controller + { + /** + * Constructor. + * + * @since 4.7.0 + */ + public function __construct() + { + } + /** + * Registers the routes for taxonomies. + * + * @since 4.7.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Checks whether a given request has permission to read taxonomies. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves all public taxonomies. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Checks if a given request has access to a taxonomy. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, otherwise false or WP_Error object. + */ + public function get_item_permissions_check($request) + { + } + /** + * Retrieves a specific taxonomy. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Prepares a taxonomy object for serialization. + * + * @since 4.7.0 + * @since 5.9.0 Renamed `$taxonomy` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Taxonomy $item Taxonomy data. + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the request. + * + * @since 6.1.0 + * + * @param WP_Taxonomy $taxonomy The taxonomy. + * @return array Links for the given taxonomy. + */ + protected function prepare_links($taxonomy) + { + } + /** + * Retrieves the taxonomy's schema, conforming to JSON Schema. + * + * @since 4.7.0 + * @since 5.0.0 The `visibility` property was added. + * @since 5.9.0 The `rest_namespace` property was added. + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the query params for collections. + * + * @since 4.7.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + } + /** + * REST API: WP_REST_Templates_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.8.0 + */ + /** + * Base Templates REST API Controller. + * + * @since 5.8.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Templates_Controller extends \WP_REST_Controller + { + /** + * Post type. + * + * @since 5.8.0 + * @var string + */ + protected $post_type; + /** + * Constructor. + * + * @since 5.8.0 + * + * @param string $post_type Post type. + */ + public function __construct($post_type) + { + } + /** + * Registers the controllers routes. + * + * @since 5.8.0 + * @since 6.1.0 Endpoint for fallback template content. + */ + public function register_routes() + { + } + /** + * Returns the fallback template for the given slug. + * + * @since 6.1.0 + * + * @param WP_REST_Request $request The request instance. + * @return WP_REST_Response|WP_Error + */ + public function get_template_fallback($request) + { + } + /** + * Checks if the user has permissions to make the request. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + protected function permissions_check($request) + { + } + /** + * Requesting this endpoint for a template like 'twentytwentytwo//home' + * requires using a path like /wp/v2/templates/twentytwentytwo//home. There + * are special cases when WordPress routing corrects the name to contain + * only a single slash like 'twentytwentytwo/home'. + * + * This method doubles the last slash if it's not already doubled. It relies + * on the template ID format {theme_name}//{template_slug} and the fact that + * slugs cannot contain slashes. + * + * @since 5.9.0 + * @see https://core.trac.wordpress.org/ticket/54507 + * + * @param string $id Template ID. + * @return string Sanitized template ID. + */ + public function _sanitize_template_id($id) + { + } + /** + * Checks if a given request has access to read templates. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Returns a list of templates. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request The request instance. + * @return WP_REST_Response + */ + public function get_items($request) + { + } + /** + * Checks if a given request has access to read a single template. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Returns the given template + * + * @since 5.8.0 + * + * @param WP_REST_Request $request The request instance. + * @return WP_REST_Response|WP_Error + */ + public function get_item($request) + { + } + /** + * Checks if a given request has access to write a single template. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has write access for the item, WP_Error object otherwise. + */ + public function update_item_permissions_check($request) + { + } + /** + * Updates a single template. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function update_item($request) + { + } + /** + * Checks if a given request has access to create a template. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise. + */ + public function create_item_permissions_check($request) + { + } + /** + * Creates a single template. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function create_item($request) + { + } + /** + * Checks if a given request has access to delete a single template. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has delete access for the item, WP_Error object otherwise. + */ + public function delete_item_permissions_check($request) + { + } + /** + * Deletes a single template. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function delete_item($request) + { + } + /** + * Prepares a single template for create or update. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Request object. + * @return stdClass Changes to pass to wp_update_post. + */ + protected function prepare_item_for_database($request) + { + } + /** + * Prepare a single template output for response + * + * @since 5.8.0 + * @since 5.9.0 Renamed `$template` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Block_Template $item Template instance. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the request. + * + * @since 5.8.0 + * + * @param integer $id ID. + * @return array Links for the given post. + */ + protected function prepare_links($id) + { + } + /** + * Get the link relations available for the post and current user. + * + * @since 5.8.0 + * + * @return string[] List of link relations. + */ + protected function get_available_actions() + { + } + /** + * Retrieves the query params for the posts collection. + * + * @since 5.8.0 + * @since 5.9.0 Added `'area'` and `'post_type'`. + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + /** + * Retrieves the block type' schema, conforming to JSON Schema. + * + * @since 5.8.0 + * @since 5.9.0 Added `'area'`. + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + } + /** + * REST API: WP_REST_Themes_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.0.0 + */ + /** + * Core class used to manage themes via the REST API. + * + * @since 5.0.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Themes_Controller extends \WP_REST_Controller + { + /** + * Matches theme's directory: `/themes/<subdirectory>/<theme>/` or `/themes/<theme>/`. + * Excludes invalid directory name characters: `/:<>*?"|`. + */ + const PATTERN = '[^\\/:<>\\*\\?"\\|]+(?:\\/[^\\/:<>\\*\\?"\\|]+)?'; + /** + * Constructor. + * + * @since 5.0.0 + */ + public function __construct() + { + } + /** + * Registers the routes for themes. + * + * @since 5.0.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Sanitize the stylesheet to decode endpoint. + * + * @since 5.9.0 + * + * @param string $stylesheet The stylesheet name. + * @return string Sanitized stylesheet. + */ + public function _sanitize_stylesheet_callback($stylesheet) + { + } + /** + * Checks if a given request has access to read the theme. + * + * @since 5.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, otherwise WP_Error object. + */ + public function get_items_permissions_check($request) + { + } + /** + * Checks if a given request has access to read the theme. + * + * @since 5.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return bool|WP_Error True if the request has read access for the item, otherwise WP_Error object. + */ + public function get_item_permissions_check($request) + { + } + /** + * Checks if a theme can be read. + * + * @since 5.7.0 + * + * @return bool|WP_Error Whether the theme can be read. + */ + protected function check_read_active_theme_permission() + { + } + /** + * Retrieves a single theme. + * + * @since 5.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Retrieves a collection of themes. + * + * @since 5.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Prepares a single theme output for response. + * + * @since 5.0.0 + * @since 5.9.0 Renamed `$theme` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Theme $item Theme object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the request. + * + * @since 5.7.0 + * + * @param WP_Theme $theme Theme data. + * @return array Links for the given block type. + */ + protected function prepare_links($theme) + { + } + /** + * Helper function to compare two themes. + * + * @since 5.7.0 + * + * @param WP_Theme $theme_a First theme to compare. + * @param WP_Theme $theme_b Second theme to compare. + * @return bool + */ + protected function is_same_theme($theme_a, $theme_b) + { + } + /** + * Prepares the theme support value for inclusion in the REST API response. + * + * @since 5.5.0 + * + * @param mixed $support The raw value from get_theme_support(). + * @param array $args The feature's registration args. + * @param string $feature The feature name. + * @param WP_REST_Request $request The request object. + * @return mixed The prepared support value. + */ + protected function prepare_theme_support($support, $args, $feature, $request) + { + } + /** + * Retrieves the theme's schema, conforming to JSON Schema. + * + * @since 5.0.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the search params for the themes collection. + * + * @since 5.0.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + /** + * Sanitizes and validates the list of theme status. + * + * @since 5.0.0 + * @deprecated 5.7.0 + * + * @param string|array $statuses One or more theme statuses. + * @param WP_REST_Request $request Full details about the request. + * @param string $parameter Additional parameter to pass to validation. + * @return array|WP_Error A list of valid statuses, otherwise WP_Error object. + */ + public function sanitize_theme_status($statuses, $request, $parameter) + { + } + } + /** + * REST API: WP_REST_URL_Details_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.9.0 + */ + /** + * Controller which provides REST endpoint for retrieving information + * from a remote site's HTML response. + * + * @since 5.9.0 + * + * @see WP_REST_Controller + */ + class WP_REST_URL_Details_Controller extends \WP_REST_Controller + { + /** + * Constructs the controller. + * + * @since 5.9.0 + */ + public function __construct() + { + } + /** + * Registers the necessary REST API routes. + * + * @since 5.9.0 + */ + public function register_routes() + { + } + /** + * Retrieves the item's schema, conforming to JSON Schema. + * + * @since 5.9.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the contents of the title tag from the HTML response. + * + * @since 5.9.0 + * + * @param WP_REST_REQUEST $request Full details about the request. + * @return WP_REST_Response|WP_Error The parsed details as a response object. WP_Error if there are errors. + */ + public function parse_url_details($request) + { + } + /** + * Checks whether a given request has permission to read remote URLs. + * + * @since 5.9.0 + * + * @return WP_Error|bool True if the request has permission, else WP_Error. + */ + public function permissions_check() + { + } + } + /** + * REST API: WP_REST_Users_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core class used to manage users via the REST API. + * + * @since 4.7.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Users_Controller extends \WP_REST_Controller + { + /** + * Instance of a user meta fields object. + * + * @since 4.7.0 + * @var WP_REST_User_Meta_Fields + */ + protected $meta; + /** + * Constructor. + * + * @since 4.7.0 + */ + public function __construct() + { + } + /** + * Registers the routes for users. + * + * @since 4.7.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Checks for a valid value for the reassign parameter when deleting users. + * + * The value can be an integer, 'false', false, or ''. + * + * @since 4.7.0 + * + * @param int|bool $value The value passed to the reassign parameter. + * @param WP_REST_Request $request Full details about the request. + * @param string $param The parameter that is being sanitized. + * @return int|bool|WP_Error + */ + public function check_reassign($value, $request, $param) + { + } + /** + * Permissions check for getting all users. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, otherwise WP_Error object. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves all users. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Get the user, if the ID is valid. + * + * @since 4.7.2 + * + * @param int $id Supplied ID. + * @return WP_User|WP_Error True if ID is valid, WP_Error otherwise. + */ + protected function get_user($id) + { + } + /** + * Checks if a given request has access to read a user. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, otherwise WP_Error object. + */ + public function get_item_permissions_check($request) + { + } + /** + * Retrieves a single user. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Retrieves the current user. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_current_item($request) + { + } + /** + * Checks if a given request has access create users. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise. + */ + public function create_item_permissions_check($request) + { + } + /** + * Creates a single user. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function create_item($request) + { + } + /** + * Checks if a given request has access to update a user. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise. + */ + public function update_item_permissions_check($request) + { + } + /** + * Updates a single user. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function update_item($request) + { + } + /** + * Checks if a given request has access to update the current user. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise. + */ + public function update_current_item_permissions_check($request) + { + } + /** + * Updates the current user. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function update_current_item($request) + { + } + /** + * Checks if a given request has access delete a user. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise. + */ + public function delete_item_permissions_check($request) + { + } + /** + * Deletes a single user. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function delete_item($request) + { + } + /** + * Checks if a given request has access to delete the current user. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise. + */ + public function delete_current_item_permissions_check($request) + { + } + /** + * Deletes the current user. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function delete_current_item($request) + { + } + /** + * Prepares a single user output for response. + * + * @since 4.7.0 + * @since 5.9.0 Renamed `$user` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_User $item User object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response Response object. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the user request. + * + * @since 4.7.0 + * + * @param WP_User $user User object. + * @return array Links for the given user. + */ + protected function prepare_links($user) + { + } + /** + * Prepares a single user for creation or update. + * + * @since 4.7.0 + * + * @param WP_REST_Request $request Request object. + * @return object User object. + */ + protected function prepare_item_for_database($request) + { + } + /** + * Determines if the current user is allowed to make the desired roles change. + * + * @since 4.7.0 + * + * @global WP_Roles $wp_roles WordPress role management object. + * + * @param int $user_id User ID. + * @param array $roles New user roles. + * @return true|WP_Error True if the current user is allowed to make the role change, + * otherwise a WP_Error object. + */ + protected function check_role_update($user_id, $roles) + { + } + /** + * Check a username for the REST API. + * + * Performs a couple of checks like edit_user() in wp-admin/includes/user.php. + * + * @since 4.7.0 + * + * @param string $value The username submitted in the request. + * @param WP_REST_Request $request Full details about the request. + * @param string $param The parameter name. + * @return string|WP_Error The sanitized username, if valid, otherwise an error. + */ + public function check_username($value, $request, $param) + { + } + /** + * Check a user password for the REST API. + * + * Performs a couple of checks like edit_user() in wp-admin/includes/user.php. + * + * @since 4.7.0 + * + * @param string $value The password submitted in the request. + * @param WP_REST_Request $request Full details about the request. + * @param string $param The parameter name. + * @return string|WP_Error The sanitized password, if valid, otherwise an error. + */ + public function check_user_password($value, $request, $param) + { + } + /** + * Retrieves the user's schema, conforming to JSON Schema. + * + * @since 4.7.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * Retrieves the query params for collections. + * + * @since 4.7.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + } + /** + * REST API: WP_REST_Widget_Types_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.8.0 + */ + /** + * Core class to access widget types via the REST API. + * + * @since 5.8.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Widget_Types_Controller extends \WP_REST_Controller + { + /** + * Constructor. + * + * @since 5.8.0 + */ + public function __construct() + { + } + /** + * Registers the widget type routes. + * + * @since 5.8.0 + * + * @see register_rest_route() + */ + public function register_routes() + { + } + /** + * Checks whether a given request has permission to read widget types. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves the list of all widget types. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Checks if a given request has access to read a widget type. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Checks whether the user can read widget types. + * + * @since 5.8.0 + * + * @return true|WP_Error True if the widget type is visible, WP_Error otherwise. + */ + protected function check_read_permission() + { + } + /** + * Gets the details about the requested widget. + * + * @since 5.8.0 + * + * @param string $id The widget type id. + * @return array|WP_Error The array of widget data if the name is valid, WP_Error otherwise. + */ + public function get_widget($id) + { + } + /** + * Normalize array of widgets. + * + * @since 5.8.0 + * + * @global WP_Widget_Factory $wp_widget_factory + * @global array $wp_registered_widgets The list of registered widgets. + * + * @return array Array of widgets. + */ + protected function get_widgets() + { + } + /** + * Retrieves a single widget type from the collection. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Prepares a widget type object for serialization. + * + * @since 5.8.0 + * @since 5.9.0 Renamed `$widget_type` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param array $item Widget type data. + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response Widget type data. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the widget type. + * + * @since 5.8.0 + * + * @param array $widget_type Widget type data. + * @return array Links for the given widget type. + */ + protected function prepare_links($widget_type) + { + } + /** + * Retrieves the widget type's schema, conforming to JSON Schema. + * + * @since 5.8.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + /** + * An RPC-style endpoint which can be used by clients to turn user input in + * a widget admin form into an encoded instance object. + * + * Accepts: + * + * - id: A widget type ID. + * - instance: A widget's encoded instance object. Optional. + * - form_data: Form data from submitting a widget's admin form. Optional. + * + * Returns: + * - instance: The encoded instance object after updating the widget with + * the given form data. + * - form: The widget's admin form after updating the widget with the + * given form data. + * + * @since 5.8.0 + * + * @global WP_Widget_Factory $wp_widget_factory + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function encode_form_data($request) + { + } + /** + * Renders a single Legacy Widget and wraps it in a JSON-encodable array. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request Full details about the request. + * + * @return array An array with rendered Legacy Widget HTML. + */ + public function render($request) + { + } + /** + * Retrieves the query params for collections. + * + * @since 5.8.0 + * + * @return array Collection parameters. + */ + public function get_collection_params() + { + } + } + /** + * REST API: WP_REST_Widgets_Controller class + * + * @package WordPress + * @subpackage REST_API + * @since 5.8.0 + */ + /** + * Core class to access widgets via the REST API. + * + * @since 5.8.0 + * + * @see WP_REST_Controller + */ + class WP_REST_Widgets_Controller extends \WP_REST_Controller + { + /** + * Tracks whether {@see retrieve_widgets()} has been called in the current request. + * + * @since 5.9.0 + * @var bool + */ + protected $widgets_retrieved = \false; + /** + * Whether the controller supports batching. + * + * @since 5.9.0 + * @var array + */ + protected $allow_batch = array('v1' => \true); + /** + * Widgets controller constructor. + * + * @since 5.8.0 + */ + public function __construct() + { + } + /** + * Registers the widget routes for the controller. + * + * @since 5.8.0 + */ + public function register_routes() + { + } + /** + * Checks if a given request has access to get widgets. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check($request) + { + } + /** + * Retrieves a collection of widgets. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items($request) + { + } + /** + * Checks if a given request has access to get a widget. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_item_permissions_check($request) + { + } + /** + * Checks if a sidebar can be read publicly. + * + * @since 5.9.0 + * + * @param string $sidebar_id The sidebar ID. + * @return bool Whether the sidebar can be read. + */ + protected function check_read_sidebar_permission($sidebar_id) + { + } + /** + * Gets an individual widget. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_item($request) + { + } + /** + * Checks if a given request has access to create widgets. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function create_item_permissions_check($request) + { + } + /** + * Creates a widget. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function create_item($request) + { + } + /** + * Checks if a given request has access to update widgets. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function update_item_permissions_check($request) + { + } + /** + * Updates an existing widget. + * + * @since 5.8.0 + * + * @global WP_Widget_Factory $wp_widget_factory + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function update_item($request) + { + } + /** + * Checks if a given request has access to delete widgets. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function delete_item_permissions_check($request) + { + } + /** + * Deletes a widget. + * + * @since 5.8.0 + * + * @global WP_Widget_Factory $wp_widget_factory + * @global array $wp_registered_widget_updates The registered widget update functions. + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function delete_item($request) + { + } + /** + * Performs a permissions check for managing widgets. + * + * @since 5.8.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error + */ + protected function permissions_check($request) + { + } + /** + * Looks for "lost" widgets once per request. + * + * @since 5.9.0 + * + * @see retrieve_widgets() + */ + protected function retrieve_widgets() + { + } + /** + * Saves the widget in the request object. + * + * @since 5.8.0 + * + * @global WP_Widget_Factory $wp_widget_factory + * @global array $wp_registered_widget_updates The registered widget update functions. + * + * @param WP_REST_Request $request Full details about the request. + * @param string $sidebar_id ID of the sidebar the widget belongs to. + * @return string|WP_Error The saved widget ID. + */ + protected function save_widget($request, $sidebar_id) + { + } + /** + * Prepares the widget for the REST response. + * + * @since 5.8.0 + * + * @global WP_Widget_Factory $wp_widget_factory + * @global array $wp_registered_widgets The registered widgets. + * + * @param array $item An array containing a widget_id and sidebar_id. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function prepare_item_for_response($item, $request) + { + } + /** + * Prepares links for the widget. + * + * @since 5.8.0 + * + * @param array $prepared Widget. + * @return array Links for the given widget. + */ + protected function prepare_links($prepared) + { + } + /** + * Gets the list of collection params. + * + * @since 5.8.0 + * + * @return array[] + */ + public function get_collection_params() + { + } + /** + * Retrieves the widget's schema, conforming to JSON Schema. + * + * @since 5.8.0 + * + * @return array Item schema data. + */ + public function get_item_schema() + { + } + } + /** + * REST API: WP_REST_Meta_Fields class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core class to manage meta values for an object via the REST API. + * + * @since 4.7.0 + */ + #[\AllowDynamicProperties] + abstract class WP_REST_Meta_Fields + { + /** + * Retrieves the object meta type. + * + * @since 4.7.0 + * + * @return string One of 'post', 'comment', 'term', 'user', or anything + * else supported by `_get_meta_table()`. + */ + protected abstract function get_meta_type(); + /** + * Retrieves the object meta subtype. + * + * @since 4.9.8 + * + * @return string Subtype for the meta type, or empty string if no specific subtype. + */ + protected function get_meta_subtype() + { + } + /** + * Retrieves the object type for register_rest_field(). + * + * @since 4.7.0 + * + * @return string The REST field type, such as post type name, taxonomy name, 'comment', or `user`. + */ + protected abstract function get_rest_field_type(); + /** + * Registers the meta field. + * + * @since 4.7.0 + * @deprecated 5.6.0 + * + * @see register_rest_field() + */ + public function register_field() + { + } + /** + * Retrieves the meta field value. + * + * @since 4.7.0 + * + * @param int $object_id Object ID to fetch meta for. + * @param WP_REST_Request $request Full details about the request. + * @return array Array containing the meta values keyed by name. + */ + public function get_value($object_id, $request) + { + } + /** + * Prepares a meta value for a response. + * + * This is required because some native types cannot be stored correctly + * in the database, such as booleans. We need to cast back to the relevant + * type before passing back to JSON. + * + * @since 4.7.0 + * + * @param mixed $value Meta value to prepare. + * @param WP_REST_Request $request Current request object. + * @param array $args Options for the field. + * @return mixed Prepared value. + */ + protected function prepare_value_for_response($value, $request, $args) + { + } + /** + * Updates meta values. + * + * @since 4.7.0 + * + * @param array $meta Array of meta parsed from the request. + * @param int $object_id Object ID to fetch meta for. + * @return null|WP_Error Null on success, WP_Error object on failure. + */ + public function update_value($meta, $object_id) + { + } + /** + * Deletes a meta value for an object. + * + * @since 4.7.0 + * + * @param int $object_id Object ID the field belongs to. + * @param string $meta_key Key for the field. + * @param string $name Name for the field that is exposed in the REST API. + * @return true|WP_Error True if meta field is deleted, WP_Error otherwise. + */ + protected function delete_meta_value($object_id, $meta_key, $name) + { + } + /** + * Updates multiple meta values for an object. + * + * Alters the list of values in the database to match the list of provided values. + * + * @since 4.7.0 + * + * @param int $object_id Object ID to update. + * @param string $meta_key Key for the custom field. + * @param string $name Name for the field that is exposed in the REST API. + * @param array $values List of values to update to. + * @return true|WP_Error True if meta fields are updated, WP_Error otherwise. + */ + protected function update_multi_meta_value($object_id, $meta_key, $name, $values) + { + } + /** + * Updates a meta value for an object. + * + * @since 4.7.0 + * + * @param int $object_id Object ID to update. + * @param string $meta_key Key for the custom field. + * @param string $name Name for the field that is exposed in the REST API. + * @param mixed $value Updated value. + * @return true|WP_Error True if the meta field was updated, WP_Error otherwise. + */ + protected function update_meta_value($object_id, $meta_key, $name, $value) + { + } + /** + * Checks if the user provided value is equivalent to a stored value for the given meta key. + * + * @since 5.5.0 + * + * @param string $meta_key The meta key being checked. + * @param string $subtype The object subtype. + * @param mixed $stored_value The currently stored value retrieved from get_metadata(). + * @param mixed $user_value The value provided by the user. + * @return bool + */ + protected function is_meta_value_same_as_stored_value($meta_key, $subtype, $stored_value, $user_value) + { + } + /** + * Retrieves all the registered meta fields. + * + * @since 4.7.0 + * + * @return array Registered fields. + */ + protected function get_registered_fields() + { + } + /** + * Retrieves the object's meta schema, conforming to JSON Schema. + * + * @since 4.7.0 + * + * @return array Field schema data. + */ + public function get_field_schema() + { + } + /** + * Prepares a meta value for output. + * + * Default preparation for meta fields. Override by passing the + * `prepare_callback` in your `show_in_rest` options. + * + * @since 4.7.0 + * + * @param mixed $value Meta value from the database. + * @param WP_REST_Request $request Request object. + * @param array $args REST-specific options for the meta key. + * @return mixed Value prepared for output. If a non-JsonSerializable object, null. + */ + public static function prepare_value($value, $request, $args) + { + } + /** + * Check the 'meta' value of a request is an associative array. + * + * @since 4.7.0 + * + * @param mixed $value The meta value submitted in the request. + * @param WP_REST_Request $request Full details about the request. + * @param string $param The parameter name. + * @return array|false The meta array, if valid, false otherwise. + */ + public function check_meta_is_array($value, $request, $param) + { + } + /** + * Recursively add additionalProperties = false to all objects in a schema if no additionalProperties setting + * is specified. + * + * This is needed to restrict properties of objects in meta values to only + * registered items, as the REST API will allow additional properties by + * default. + * + * @since 5.3.0 + * @deprecated 5.6.0 Use rest_default_additional_properties_to_false() instead. + * + * @param array $schema The schema array. + * @return array + */ + protected function default_additional_properties_to_false($schema) + { + } + /** + * Gets the empty value for a schema type. + * + * @since 5.3.0 + * + * @param string $type The schema type. + * @return mixed + */ + protected static function get_empty_value_for_type($type) + { + } + } + /** + * REST API: WP_REST_Comment_Meta_Fields class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core class to manage comment meta via the REST API. + * + * @since 4.7.0 + * + * @see WP_REST_Meta_Fields + */ + class WP_REST_Comment_Meta_Fields extends \WP_REST_Meta_Fields + { + /** + * Retrieves the comment type for comment meta. + * + * @since 4.7.0 + * + * @return string The meta type. + */ + protected function get_meta_type() + { + } + /** + * Retrieves the comment meta subtype. + * + * @since 4.9.8 + * + * @return string 'comment' There are no subtypes. + */ + protected function get_meta_subtype() + { + } + /** + * Retrieves the type for register_rest_field() in the context of comments. + * + * @since 4.7.0 + * + * @return string The REST field type. + */ + public function get_rest_field_type() + { + } + } + /** + * REST API: WP_REST_Post_Meta_Fields class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core class used to manage meta values for posts via the REST API. + * + * @since 4.7.0 + * + * @see WP_REST_Meta_Fields + */ + class WP_REST_Post_Meta_Fields extends \WP_REST_Meta_Fields + { + /** + * Post type to register fields for. + * + * @since 4.7.0 + * @var string + */ + protected $post_type; + /** + * Constructor. + * + * @since 4.7.0 + * + * @param string $post_type Post type to register fields for. + */ + public function __construct($post_type) + { + } + /** + * Retrieves the post meta type. + * + * @since 4.7.0 + * + * @return string The meta type. + */ + protected function get_meta_type() + { + } + /** + * Retrieves the post meta subtype. + * + * @since 4.9.8 + * + * @return string Subtype for the meta type, or empty string if no specific subtype. + */ + protected function get_meta_subtype() + { + } + /** + * Retrieves the type for register_rest_field(). + * + * @since 4.7.0 + * + * @see register_rest_field() + * + * @return string The REST field type. + */ + public function get_rest_field_type() + { + } + } + /** + * REST API: WP_REST_Term_Meta_Fields class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core class used to manage meta values for terms via the REST API. + * + * @since 4.7.0 + * + * @see WP_REST_Meta_Fields + */ + class WP_REST_Term_Meta_Fields extends \WP_REST_Meta_Fields + { + /** + * Taxonomy to register fields for. + * + * @since 4.7.0 + * @var string + */ + protected $taxonomy; + /** + * Constructor. + * + * @since 4.7.0 + * + * @param string $taxonomy Taxonomy to register fields for. + */ + public function __construct($taxonomy) + { + } + /** + * Retrieves the term meta type. + * + * @since 4.7.0 + * + * @return string The meta type. + */ + protected function get_meta_type() + { + } + /** + * Retrieves the term meta subtype. + * + * @since 4.9.8 + * + * @return string Subtype for the meta type, or empty string if no specific subtype. + */ + protected function get_meta_subtype() + { + } + /** + * Retrieves the type for register_rest_field(). + * + * @since 4.7.0 + * + * @return string The REST field type. + */ + public function get_rest_field_type() + { + } + } + /** + * REST API: WP_REST_User_Meta_Fields class + * + * @package WordPress + * @subpackage REST_API + * @since 4.7.0 + */ + /** + * Core class used to manage meta values for users via the REST API. + * + * @since 4.7.0 + * + * @see WP_REST_Meta_Fields + */ + class WP_REST_User_Meta_Fields extends \WP_REST_Meta_Fields + { + /** + * Retrieves the user meta type. + * + * @since 4.7.0 + * + * @return string The user meta type. + */ + protected function get_meta_type() + { + } + /** + * Retrieves the user meta subtype. + * + * @since 4.9.8 + * + * @return string 'user' There are no subtypes. + */ + protected function get_meta_subtype() + { + } + /** + * Retrieves the type for register_rest_field(). + * + * @since 4.7.0 + * + * @return string The user REST field type. + */ + public function get_rest_field_type() + { + } + } + /** + * REST API: WP_REST_Search_Handler class + * + * @package WordPress + * @subpackage REST_API + * @since 5.0.0 + */ + /** + * Core base class representing a search handler for an object type in the REST API. + * + * @since 5.0.0 + */ + #[\AllowDynamicProperties] + abstract class WP_REST_Search_Handler + { + /** + * Field containing the IDs in the search result. + */ + const RESULT_IDS = 'ids'; + /** + * Field containing the total count in the search result. + */ + const RESULT_TOTAL = 'total'; + /** + * Object type managed by this search handler. + * + * @since 5.0.0 + * @var string + */ + protected $type = ''; + /** + * Object subtypes managed by this search handler. + * + * @since 5.0.0 + * @var array + */ + protected $subtypes = array(); + /** + * Gets the object type managed by this search handler. + * + * @since 5.0.0 + * + * @return string Object type identifier. + */ + public function get_type() + { + } + /** + * Gets the object subtypes managed by this search handler. + * + * @since 5.0.0 + * + * @return array Array of object subtype identifiers. + */ + public function get_subtypes() + { + } + /** + * Searches the object type content for a given search request. + * + * @since 5.0.0 + * + * @param WP_REST_Request $request Full REST request. + * @return array Associative array containing an `WP_REST_Search_Handler::RESULT_IDS` containing + * an array of found IDs and `WP_REST_Search_Handler::RESULT_TOTAL` containing the + * total count for the matching search results. + */ + public abstract function search_items(\WP_REST_Request $request); + /** + * Prepares the search result for a given ID. + * + * @since 5.0.0 + * @since 5.6.0 The `$id` parameter can accept a string. + * + * @param int|string $id Item ID. + * @param array $fields Fields to include for the item. + * @return array Associative array containing all fields for the item. + */ + public abstract function prepare_item($id, array $fields); + /** + * Prepares links for the search result of a given ID. + * + * @since 5.0.0 + * @since 5.6.0 The `$id` parameter can accept a string. + * + * @param int|string $id Item ID. + * @return array Links for the given item. + */ + public abstract function prepare_item_links($id); + } + /** + * REST API: WP_REST_Post_Format_Search_Handler class + * + * @package WordPress + * @subpackage REST_API + * @since 5.6.0 + */ + /** + * Core class representing a search handler for post formats in the REST API. + * + * @since 5.6.0 + * + * @see WP_REST_Search_Handler + */ + class WP_REST_Post_Format_Search_Handler extends \WP_REST_Search_Handler + { + /** + * Constructor. + * + * @since 5.6.0 + */ + public function __construct() + { + } + /** + * Searches the object type content for a given search request. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Full REST request. + * @return array Associative array containing an `WP_REST_Search_Handler::RESULT_IDS` containing + * an array of found IDs and `WP_REST_Search_Handler::RESULT_TOTAL` containing the + * total count for the matching search results. + */ + public function search_items(\WP_REST_Request $request) + { + } + /** + * Prepares the search result for a given ID. + * + * @since 5.6.0 + * + * @param string $id Item ID, the post format slug. + * @param array $fields Fields to include for the item. + * @return array Associative array containing all fields for the item. + */ + public function prepare_item($id, array $fields) + { + } + /** + * Prepares links for the search result. + * + * @since 5.6.0 + * + * @param string $id Item ID, the post format slug. + * @return array Links for the given item. + */ + public function prepare_item_links($id) + { + } + } + /** + * REST API: WP_REST_Post_Search_Handler class + * + * @package WordPress + * @subpackage REST_API + * @since 5.0.0 + */ + /** + * Core class representing a search handler for posts in the REST API. + * + * @since 5.0.0 + * + * @see WP_REST_Search_Handler + */ + class WP_REST_Post_Search_Handler extends \WP_REST_Search_Handler + { + /** + * Constructor. + * + * @since 5.0.0 + */ + public function __construct() + { + } + /** + * Searches the object type content for a given search request. + * + * @since 5.0.0 + * + * @param WP_REST_Request $request Full REST request. + * @return array Associative array containing an `WP_REST_Search_Handler::RESULT_IDS` containing + * an array of found IDs and `WP_REST_Search_Handler::RESULT_TOTAL` containing the + * total count for the matching search results. + */ + public function search_items(\WP_REST_Request $request) + { + } + /** + * Prepares the search result for a given ID. + * + * @since 5.0.0 + * + * @param int $id Item ID. + * @param array $fields Fields to include for the item. + * @return array Associative array containing all fields for the item. + */ + public function prepare_item($id, array $fields) + { + } + /** + * Prepares links for the search result of a given ID. + * + * @since 5.0.0 + * + * @param int $id Item ID. + * @return array Links for the given item. + */ + public function prepare_item_links($id) + { + } + /** + * Overwrites the default protected title format. + * + * By default, WordPress will show password protected posts with a title of + * "Protected: %s". As the REST API communicates the protected status of a post + * in a machine readable format, we remove the "Protected: " prefix. + * + * @since 5.0.0 + * + * @return string Protected title format. + */ + public function protected_title_format() + { + } + /** + * Attempts to detect the route to access a single item. + * + * @since 5.0.0 + * @deprecated 5.5.0 Use rest_get_route_for_post() + * @see rest_get_route_for_post() + * + * @param WP_Post $post Post object. + * @return string REST route relative to the REST base URI, or empty string if unknown. + */ + protected function detect_rest_item_route($post) + { + } + } + /** + * REST API: WP_REST_Term_Search_Handler class + * + * @package WordPress + * @subpackage REST_API + * @since 5.6.0 + */ + /** + * Core class representing a search handler for terms in the REST API. + * + * @since 5.6.0 + * + * @see WP_REST_Search_Handler + */ + class WP_REST_Term_Search_Handler extends \WP_REST_Search_Handler + { + /** + * Constructor. + * + * @since 5.6.0 + */ + public function __construct() + { + } + /** + * Searches the object type content for a given search request. + * + * @since 5.6.0 + * + * @param WP_REST_Request $request Full REST request. + * @return array { + * Associative array containing found IDs and total count for the matching search results. + * + * @type int[] $ids Found IDs. + * @type string|int|WP_Error $total Numeric string containing the number of terms in that + * taxonomy, 0 if there are no results, or WP_Error if + * the requested taxonomy does not exist. + * } + * @phpstan-return array{ + * ids: int[], + * total: string|int|WP_Error, + * } + */ + public function search_items(\WP_REST_Request $request) + { + } + /** + * Prepares the search result for a given ID. + * + * @since 5.6.0 + * + * @param int $id Item ID. + * @param array $fields Fields to include for the item. + * @return array Associative array containing all fields for the item. + */ + public function prepare_item($id, array $fields) + { + } + /** + * Prepares links for the search result of a given ID. + * + * @since 5.6.0 + * + * @param int $id Item ID. + * @return array[] Array of link arrays for the given item. + */ + public function prepare_item_links($id) + { + } + } + /** + * Sitemaps: WP_Sitemaps_Index class. + * + * Generates the sitemap index. + * + * @package WordPress + * @subpackage Sitemaps + * @since 5.5.0 + */ + /** + * Class WP_Sitemaps_Index. + * Builds the sitemap index page that lists the links to all of the sitemaps. + * + * @since 5.5.0 + */ + #[\AllowDynamicProperties] + class WP_Sitemaps_Index + { + /** + * The main registry of supported sitemaps. + * + * @since 5.5.0 + * @var WP_Sitemaps_Registry + */ + protected $registry; + /** + * WP_Sitemaps_Index constructor. + * + * @since 5.5.0 + * + * @param WP_Sitemaps_Registry $registry Sitemap provider registry. + */ + public function __construct(\WP_Sitemaps_Registry $registry) + { + } + /** + * Gets a sitemap list for the index. + * + * @since 5.5.0 + * + * @return array[] Array of all sitemaps. + */ + public function get_sitemap_list() + { + } + /** + * Builds the URL for the sitemap index. + * + * @since 5.5.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @return string The sitemap index URL. + */ + public function get_index_url() + { + } + } + /** + * Sitemaps: WP_Sitemaps_Provider class + * + * This class is a base class for other sitemap providers to extend and contains shared functionality. + * + * @package WordPress + * @subpackage Sitemaps + * @since 5.5.0 + */ + /** + * Class WP_Sitemaps_Provider. + * + * @since 5.5.0 + */ + #[\AllowDynamicProperties] + abstract class WP_Sitemaps_Provider + { + /** + * Provider name. + * + * This will also be used as the public-facing name in URLs. + * + * @since 5.5.0 + * + * @var string + */ + protected $name = ''; + /** + * Object type name (e.g. 'post', 'term', 'user'). + * + * @since 5.5.0 + * + * @var string + */ + protected $object_type = ''; + /** + * Gets a URL list for a sitemap. + * + * @since 5.5.0 + * + * @param int $page_num Page of results. + * @param string $object_subtype Optional. Object subtype name. Default empty. + * @return array[] Array of URL information for a sitemap. + */ + public abstract function get_url_list($page_num, $object_subtype = ''); + /** + * Gets the max number of pages available for the object type. + * + * @since 5.5.0 + * + * @param string $object_subtype Optional. Object subtype. Default empty. + * @return int Total number of pages. + */ + public abstract function get_max_num_pages($object_subtype = ''); + /** + * Gets data about each sitemap type. + * + * @since 5.5.0 + * + * @return array[] Array of sitemap types including object subtype name and number of pages. + */ + public function get_sitemap_type_data() + { + } + /** + * Lists sitemap pages exposed by this provider. + * + * The returned data is used to populate the sitemap entries of the index. + * + * @since 5.5.0 + * + * @return array[] Array of sitemap entries. + */ + public function get_sitemap_entries() + { + } + /** + * Gets the URL of a sitemap entry. + * + * @since 5.5.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $name The name of the sitemap. + * @param int $page The page of the sitemap. + * @return string The composed URL for a sitemap entry. + */ + public function get_sitemap_url($name, $page) + { + } + /** + * Returns the list of supported object subtypes exposed by the provider. + * + * @since 5.5.0 + * + * @return array List of object subtypes objects keyed by their name. + */ + public function get_object_subtypes() + { + } + } + /** + * Sitemaps: WP_Sitemaps_Registry class + * + * Handles registering sitemap providers. + * + * @package WordPress + * @subpackage Sitemaps + * @since 5.5.0 + */ + /** + * Class WP_Sitemaps_Registry. + * + * @since 5.5.0 + */ + #[\AllowDynamicProperties] + class WP_Sitemaps_Registry + { + /** + * Adds a new sitemap provider. + * + * @since 5.5.0 + * + * @param string $name Name of the sitemap provider. + * @param WP_Sitemaps_Provider $provider Instance of a WP_Sitemaps_Provider. + * @return bool Whether the provider was added successfully. + */ + public function add_provider($name, \WP_Sitemaps_Provider $provider) + { + } + /** + * Returns a single registered sitemap provider. + * + * @since 5.5.0 + * + * @param string $name Sitemap provider name. + * @return WP_Sitemaps_Provider|null Sitemap provider if it exists, null otherwise. + */ + public function get_provider($name) + { + } + /** + * Returns all registered sitemap providers. + * + * @since 5.5.0 + * + * @return WP_Sitemaps_Provider[] Array of sitemap providers. + */ + public function get_providers() + { + } + } + /** + * Sitemaps: WP_Sitemaps_Renderer class + * + * Responsible for rendering Sitemaps data to XML in accordance with sitemap protocol. + * + * @package WordPress + * @subpackage Sitemaps + * @since 5.5.0 + */ + /** + * Class WP_Sitemaps_Renderer + * + * @since 5.5.0 + */ + #[\AllowDynamicProperties] + class WP_Sitemaps_Renderer + { + /** + * XSL stylesheet for styling a sitemap for web browsers. + * + * @since 5.5.0 + * + * @var string + */ + protected $stylesheet = ''; + /** + * XSL stylesheet for styling a sitemap for web browsers. + * + * @since 5.5.0 + * + * @var string + */ + protected $stylesheet_index = ''; + /** + * WP_Sitemaps_Renderer constructor. + * + * @since 5.5.0 + */ + public function __construct() + { + } + /** + * Gets the URL for the sitemap stylesheet. + * + * @since 5.5.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @return string The sitemap stylesheet URL. + */ + public function get_sitemap_stylesheet_url() + { + } + /** + * Gets the URL for the sitemap index stylesheet. + * + * @since 5.5.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @return string The sitemap index stylesheet URL. + */ + public function get_sitemap_index_stylesheet_url() + { + } + /** + * Renders a sitemap index. + * + * @since 5.5.0 + * + * @param array $sitemaps Array of sitemap URLs. + */ + public function render_index($sitemaps) + { + } + /** + * Gets XML for a sitemap index. + * + * @since 5.5.0 + * + * @param array $sitemaps Array of sitemap URLs. + * @return string|false A well-formed XML string for a sitemap index. False on error. + */ + public function get_sitemap_index_xml($sitemaps) + { + } + /** + * Renders a sitemap. + * + * @since 5.5.0 + * + * @param array $url_list Array of URLs for a sitemap. + */ + public function render_sitemap($url_list) + { + } + /** + * Gets XML for a sitemap. + * + * @since 5.5.0 + * + * @param array $url_list Array of URLs for a sitemap. + * @return string|false A well-formed XML string for a sitemap index. False on error. + */ + public function get_sitemap_xml($url_list) + { + } + } + /** + * Sitemaps: WP_Sitemaps_Stylesheet class + * + * This class provides the XSL stylesheets to style all sitemaps. + * + * @package WordPress + * @subpackage Sitemaps + * @since 5.5.0 + */ + /** + * Stylesheet provider class. + * + * @since 5.5.0 + */ + #[\AllowDynamicProperties] + class WP_Sitemaps_Stylesheet + { + /** + * Renders the XSL stylesheet depending on whether it's the sitemap index or not. + * + * @param string $type Stylesheet type. Either 'sitemap' or 'index'. + */ + public function render_stylesheet($type) + { + } + /** + * Returns the escaped XSL for all sitemaps, except index. + * + * @since 5.5.0 + */ + public function get_sitemap_stylesheet() + { + } + /** + * Returns the escaped XSL for the index sitemaps. + * + * @since 5.5.0 + */ + public function get_sitemap_index_stylesheet() + { + } + /** + * Gets the CSS to be included in sitemap XSL stylesheets. + * + * @since 5.5.0 + * + * @return string The CSS. + */ + public function get_stylesheet_css() + { + } + } + /** + * Sitemaps: WP_Sitemaps class + * + * This is the main class integrating all other classes. + * + * @package WordPress + * @subpackage Sitemaps + * @since 5.5.0 + */ + /** + * Class WP_Sitemaps. + * + * @since 5.5.0 + */ + #[\AllowDynamicProperties] + class WP_Sitemaps + { + /** + * The main index of supported sitemaps. + * + * @since 5.5.0 + * + * @var WP_Sitemaps_Index + */ + public $index; + /** + * The main registry of supported sitemaps. + * + * @since 5.5.0 + * + * @var WP_Sitemaps_Registry + */ + public $registry; + /** + * An instance of the renderer class. + * + * @since 5.5.0 + * + * @var WP_Sitemaps_Renderer + */ + public $renderer; + /** + * WP_Sitemaps constructor. + * + * @since 5.5.0 + */ + public function __construct() + { + } + /** + * Initiates all sitemap functionality. + * + * If sitemaps are disabled, only the rewrite rules will be registered + * by this method, in order to properly send 404s. + * + * @since 5.5.0 + */ + public function init() + { + } + /** + * Determines whether sitemaps are enabled or not. + * + * @since 5.5.0 + * + * @return bool Whether sitemaps are enabled. + */ + public function sitemaps_enabled() + { + } + /** + * Registers and sets up the functionality for all supported sitemaps. + * + * @since 5.5.0 + */ + public function register_sitemaps() + { + } + /** + * Registers sitemap rewrite tags and routing rules. + * + * @since 5.5.0 + */ + public function register_rewrites() + { + } + /** + * Renders sitemap templates based on rewrite rules. + * + * @since 5.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + */ + public function render_sitemaps() + { + } + /** + * Redirects a URL to the wp-sitemap.xml + * + * @since 5.5.0 + * + * @param bool $bypass Pass-through of the pre_handle_404 filter value. + * @param WP_Query $query The WP_Query object. + * @return bool Bypass value. + */ + public function redirect_sitemapxml($bypass, $query) + { + } + /** + * Adds the sitemap index to robots.txt. + * + * @since 5.5.0 + * + * @param string $output robots.txt output. + * @param bool $public Whether the site is public. + * @return string The robots.txt output. + */ + public function add_robots($output, $public) + { + } + } + /** + * Sitemaps: WP_Sitemaps_Posts class + * + * Builds the sitemaps for the 'post' object type. + * + * @package WordPress + * @subpackage Sitemaps + * @since 5.5.0 + */ + /** + * Posts XML sitemap provider. + * + * @since 5.5.0 + */ + class WP_Sitemaps_Posts extends \WP_Sitemaps_Provider + { + /** + * WP_Sitemaps_Posts constructor. + * + * @since 5.5.0 + */ + public function __construct() + { + } + /** + * Returns the public post types, which excludes nav_items and similar types. + * Attachments are also excluded. This includes custom post types with public = true. + * + * @since 5.5.0 + * + * @return WP_Post_Type[] Array of registered post type objects keyed by their name. + */ + public function get_object_subtypes() + { + } + /** + * Gets a URL list for a post type sitemap. + * + * @since 5.5.0 + * @since 5.9.0 Renamed `$post_type` to `$object_subtype` to match parent class + * for PHP 8 named parameter support. + * + * @param int $page_num Page of results. + * @param string $object_subtype Optional. Post type name. Default empty. + * + * @return array[] Array of URL information for a sitemap. + */ + public function get_url_list($page_num, $object_subtype = '') + { + } + /** + * Gets the max number of pages available for the object type. + * + * @since 5.5.0 + * @since 5.9.0 Renamed `$post_type` to `$object_subtype` to match parent class + * for PHP 8 named parameter support. + * + * @param string $object_subtype Optional. Post type name. Default empty. + * @return int Total number of pages. + */ + public function get_max_num_pages($object_subtype = '') + { + } + /** + * Returns the query args for retrieving posts to list in the sitemap. + * + * @since 5.5.0 + * @since 6.1.0 Added `ignore_sticky_posts` default parameter. + * + * @param string $post_type Post type name. + * @return array Array of WP_Query arguments. + */ + protected function get_posts_query_args($post_type) + { + } + } + /** + * Sitemaps: WP_Sitemaps_Taxonomies class + * + * Builds the sitemaps for the 'taxonomy' object type. + * + * @package WordPress + * @subpackage Sitemaps + * @since 5.5.0 + */ + /** + * Taxonomies XML sitemap provider. + * + * @since 5.5.0 + */ + class WP_Sitemaps_Taxonomies extends \WP_Sitemaps_Provider + { + /** + * WP_Sitemaps_Taxonomies constructor. + * + * @since 5.5.0 + */ + public function __construct() + { + } + /** + * Returns all public, registered taxonomies. + * + * @since 5.5.0 + * + * @return WP_Taxonomy[] Array of registered taxonomy objects keyed by their name. + */ + public function get_object_subtypes() + { + } + /** + * Gets a URL list for a taxonomy sitemap. + * + * @since 5.5.0 + * @since 5.9.0 Renamed `$taxonomy` to `$object_subtype` to match parent class + * for PHP 8 named parameter support. + * + * @param int $page_num Page of results. + * @param string $object_subtype Optional. Taxonomy name. Default empty. + * @return array[] Array of URL information for a sitemap. + */ + public function get_url_list($page_num, $object_subtype = '') + { + } + /** + * Gets the max number of pages available for the object type. + * + * @since 5.5.0 + * @since 5.9.0 Renamed `$taxonomy` to `$object_subtype` to match parent class + * for PHP 8 named parameter support. + * + * @param string $object_subtype Optional. Taxonomy name. Default empty. + * @return int Total number of pages. + */ + public function get_max_num_pages($object_subtype = '') + { + } + /** + * Returns the query args for retrieving taxonomy terms to list in the sitemap. + * + * @since 5.5.0 + * + * @param string $taxonomy Taxonomy name. + * @return array Array of WP_Term_Query arguments. + */ + protected function get_taxonomies_query_args($taxonomy) + { + } + } + /** + * Sitemaps: WP_Sitemaps_Users class + * + * Builds the sitemaps for the 'user' object type. + * + * @package WordPress + * @subpackage Sitemaps + * @since 5.5.0 + */ + /** + * Users XML sitemap provider. + * + * @since 5.5.0 + */ + class WP_Sitemaps_Users extends \WP_Sitemaps_Provider + { + /** + * WP_Sitemaps_Users constructor. + * + * @since 5.5.0 + */ + public function __construct() + { + } + /** + * Gets a URL list for a user sitemap. + * + * @since 5.5.0 + * + * @param int $page_num Page of results. + * @param string $object_subtype Optional. Not applicable for Users but + * required for compatibility with the parent + * provider class. Default empty. + * @return array[] Array of URL information for a sitemap. + */ + public function get_url_list($page_num, $object_subtype = '') + { + } + /** + * Gets the max number of pages available for the object type. + * + * @since 5.5.0 + * + * @see WP_Sitemaps_Provider::max_num_pages + * + * @param string $object_subtype Optional. Not applicable for Users but + * required for compatibility with the parent + * provider class. Default empty. + * @return int Total page count. + */ + public function get_max_num_pages($object_subtype = '') + { + } + /** + * Returns the query args for retrieving users to list in the sitemap. + * + * @since 5.5.0 + * + * @return array Array of WP_User_Query arguments. + */ + protected function get_users_query_args() + { + } + } + /** + * WP_Style_Engine_CSS_Declarations + * + * Holds, sanitizes and prints CSS rules declarations + * + * @package WordPress + * @subpackage StyleEngine + * @since 6.1.0 + */ + /** + * Class WP_Style_Engine_CSS_Declarations. + * + * Holds, sanitizes, processes and prints CSS declarations for the style engine. + * + * @since 6.1.0 + */ + #[\AllowDynamicProperties] + class WP_Style_Engine_CSS_Declarations + { + /** + * An array of CSS declarations (property => value pairs). + * + * @since 6.1.0 + * + * @var array + */ + protected $declarations = array(); + /** + * Constructor for this object. + * + * If a `$declarations` array is passed, it will be used to populate + * the initial $declarations prop of the object by calling add_declarations(). + * + * @since 6.1.0 + * + * @param string[] $declarations An associative array of CSS definitions, e.g., array( "$property" => "$value", "$property" => "$value" ). + */ + public function __construct($declarations = array()) + { + } + /** + * Adds a single declaration. + * + * @since 6.1.0 + * + * @param string $property The CSS property. + * @param string $value The CSS value. + * + * @return WP_Style_Engine_CSS_Declarations Returns the object to allow chaining methods. + */ + public function add_declaration($property, $value) + { + } + /** + * Removes a single declaration. + * + * @since 6.1.0 + * + * @param string $property The CSS property. + * + * @return WP_Style_Engine_CSS_Declarations Returns the object to allow chaining methods. + */ + public function remove_declaration($property) + { + } + /** + * Adds multiple declarations. + * + * @since 6.1.0 + * + * @param array $declarations An array of declarations. + * + * @return WP_Style_Engine_CSS_Declarations Returns the object to allow chaining methods. + */ + public function add_declarations($declarations) + { + } + /** + * Removes multiple declarations. + * + * @since 6.1.0 + * + * @param array $properties An array of properties. + * + * @return WP_Style_Engine_CSS_Declarations Returns the object to allow chaining methods. + */ + public function remove_declarations($properties = array()) + { + } + /** + * Gets the declarations array. + * + * @since 6.1.0 + * + * @return array + */ + public function get_declarations() + { + } + /** + * Filters a CSS property + value pair. + * + * @since 6.1.0 + * + * @param string $property The CSS property. + * @param string $value The value to be filtered. + * @param string $spacer The spacer between the colon and the value. Defaults to an empty string. + * + * @return string The filtered declaration or an empty string. + */ + protected static function filter_declaration($property, $value, $spacer = '') + { + } + /** + * Filters and compiles the CSS declarations. + * + * @since 6.1.0 + * + * @param bool $should_prettify Whether to add spacing, new lines and indents. + * @param number $indent_count The number of tab indents to apply to the rule. Applies if `prettify` is `true`. + * + * @return string The CSS declarations. + */ + public function get_declarations_string($should_prettify = \false, $indent_count = 0) + { + } + /** + * Sanitizes property names. + * + * @since 6.1.0 + * + * @param string $property The CSS property. + * + * @return string The sanitized property name. + */ + protected function sanitize_property($property) + { + } + } + /** + * WP_Style_Engine_CSS_Rule + * + * An object for CSS rules. + * + * @package WordPress + * @subpackage StyleEngine + * @since 6.1.0 + */ + /** + * Class WP_Style_Engine_CSS_Rule. + * + * Holds, sanitizes, processes and prints CSS declarations for the style engine. + * + * @since 6.1.0 + */ + #[\AllowDynamicProperties] + class WP_Style_Engine_CSS_Rule + { + /** + * The selector. + * + * @since 6.1.0 + * @var string + */ + protected $selector; + /** + * The selector declarations. + * + * Contains a WP_Style_Engine_CSS_Declarations object. + * + * @since 6.1.0 + * @var WP_Style_Engine_CSS_Declarations + */ + protected $declarations; + /** + * Constructor + * + * @since 6.1.0 + * + * @param string $selector The CSS selector. + * @param string[]|WP_Style_Engine_CSS_Declarations $declarations An associative array of CSS definitions, e.g., array( "$property" => "$value", "$property" => "$value" ), + * or a WP_Style_Engine_CSS_Declarations object. + */ + public function __construct($selector = '', $declarations = array()) + { + } + /** + * Sets the selector. + * + * @since 6.1.0 + * + * @param string $selector The CSS selector. + * + * @return WP_Style_Engine_CSS_Rule Returns the object to allow chaining of methods. + */ + public function set_selector($selector) + { + } + /** + * Sets the declarations. + * + * @since 6.1.0 + * + * @param array|WP_Style_Engine_CSS_Declarations $declarations An array of declarations (property => value pairs), + * or a WP_Style_Engine_CSS_Declarations object. + * + * @return WP_Style_Engine_CSS_Rule Returns the object to allow chaining of methods. + */ + public function add_declarations($declarations) + { + } + /** + * Gets the declarations object. + * + * @since 6.1.0 + * + * @return WP_Style_Engine_CSS_Declarations The declarations object. + */ + public function get_declarations() + { + } + /** + * Gets the full selector. + * + * @since 6.1.0 + * + * @return string + */ + public function get_selector() + { + } + /** + * Gets the CSS. + * + * @since 6.1.0 + * + * @param bool $should_prettify Whether to add spacing, new lines and indents. + * @param number $indent_count The number of tab indents to apply to the rule. Applies if `prettify` is `true`. + * + * @return string + */ + public function get_css($should_prettify = \false, $indent_count = 0) + { + } + } + /** + * WP_Style_Engine_CSS_Rules_Store + * + * A store for WP_Style_Engine_CSS_Rule objects. + * + * @package WordPress + * @subpackage StyleEngine + * @since 6.1.0 + */ + /** + * Class WP_Style_Engine_CSS_Rules_Store. + * + * Holds, sanitizes, processes and prints CSS declarations for the style engine. + * + * @since 6.1.0 + */ + #[\AllowDynamicProperties] + class WP_Style_Engine_CSS_Rules_Store + { + /** + * An array of named WP_Style_Engine_CSS_Rules_Store objects. + * + * @static + * + * @since 6.1.0 + * @var WP_Style_Engine_CSS_Rules_Store[] + */ + protected static $stores = array(); + /** + * The store name. + * + * @since 6.1.0 + * @var string + */ + protected $name = ''; + /** + * An array of CSS Rules objects assigned to the store. + * + * @since 6.1.0 + * @var WP_Style_Engine_CSS_Rule[] + */ + protected $rules = array(); + /** + * Gets an instance of the store. + * + * @since 6.1.0 + * + * @param string $store_name The name of the store. + * + * @return WP_Style_Engine_CSS_Rules_Store|void + */ + public static function get_store($store_name = 'default') + { + } + /** + * Gets an array of all available stores. + * + * @since 6.1.0 + * + * @return WP_Style_Engine_CSS_Rules_Store[] + */ + public static function get_stores() + { + } + /** + * Clears all stores from static::$stores. + * + * @since 6.1.0 + * + * @return void + */ + public static function remove_all_stores() + { + } + /** + * Sets the store name. + * + * @since 6.1.0 + * + * @param string $name The store name. + * + * @return void + */ + public function set_name($name) + { + } + /** + * Gets the store name. + * + * @since 6.1.0 + * + * @return string + */ + public function get_name() + { + } + /** + * Gets an array of all rules. + * + * @since 6.1.0 + * + * @return WP_Style_Engine_CSS_Rule[] + */ + public function get_all_rules() + { + } + /** + * Gets a WP_Style_Engine_CSS_Rule object by its selector. + * If the rule does not exist, it will be created. + * + * @since 6.1.0 + * + * @param string $selector The CSS selector. + * + * @return WP_Style_Engine_CSS_Rule|void Returns a WP_Style_Engine_CSS_Rule object, or null if the selector is empty. + */ + public function add_rule($selector) + { + } + /** + * Removes a selector from the store. + * + * @since 6.1.0 + * + * @param string $selector The CSS selector. + * + * @return void + */ + public function remove_rule($selector) + { + } + } + /** + * WP_Style_Engine_Processor + * + * Compiles styles from stores or collection of CSS rules. + * + * @package WordPress + * @subpackage StyleEngine + * @since 6.1.0 + */ + /** + * Class WP_Style_Engine_Processor. + * + * Compiles styles from stores or collection of CSS rules. + * + * @since 6.1.0 + */ + #[\AllowDynamicProperties] + class WP_Style_Engine_Processor + { + /** + * A collection of Style Engine Store objects. + * + * @since 6.1.0 + * @var WP_Style_Engine_CSS_Rules_Store[] + */ + protected $stores = array(); + /** + * The set of CSS rules that this processor will work on. + * + * @since 6.1.0 + * @var WP_Style_Engine_CSS_Rule[] + */ + protected $css_rules = array(); + /** + * Adds a store to the processor. + * + * @since 6.1.0 + * + * @param WP_Style_Engine_CSS_Rules_Store $store The store to add. + * + * @return WP_Style_Engine_Processor Returns the object to allow chaining methods. + */ + public function add_store($store) + { + } + /** + * Adds rules to be processed. + * + * @since 6.1.0 + * + * @param WP_Style_Engine_CSS_Rule|WP_Style_Engine_CSS_Rule[] $css_rules A single, or an array of, WP_Style_Engine_CSS_Rule objects from a store or otherwise. + * + * @return WP_Style_Engine_Processor Returns the object to allow chaining methods. + */ + public function add_rules($css_rules) + { + } + /** + * Gets the CSS rules as a string. + * + * @since 6.1.0 + * + * @param array $options { + * Optional. An array of options. Default empty array. + * + * @type bool $optimize Whether to optimize the CSS output, e.g., combine rules. Default is `false`. + * @type bool $prettify Whether to add new lines and indents to output. Default is the test of whether the global constant `SCRIPT_DEBUG` is defined. + * } + * + * @return string The computed CSS. + * @phpstan-param array{ + * optimize?: bool, + * prettify?: bool, + * } $options + */ + public function get_css($options = array()) + { + } + } + /** + * StyleEngine: WP_Style_Engine class + * + * This is the main class integrating all other WP_Style_Engine_* classes. + * + * @package WordPress + * @subpackage StyleEngine + * @since 6.1.0 + */ + /** + * Class WP_Style_Engine. + * + * The Style Engine aims to provide a consistent API for rendering styling for blocks across both client-side and server-side applications. + * + * This class is final and should not be extended. + * This class is for internal Core usage and is not supposed to be used by extenders (plugins and/or themes). + * This is a low-level API that may need to do breaking changes. Please, use wp_style_engine_get_styles instead. + * + * @access private + * @since 6.1.0 + */ + #[\AllowDynamicProperties] + final class WP_Style_Engine + { + /** + * Style definitions that contain the instructions to + * parse/output valid Gutenberg styles from a block's attributes. + * For every style definition, the follow properties are valid: + * - classnames => (array) an array of classnames to be returned for block styles. The key is a classname or pattern. + * A value of `true` means the classname should be applied always. Otherwise, a valid CSS property (string) + * to match the incoming value, e.g., "color" to match var:preset|color|somePresetSlug. + * - css_vars => (array) an array of key value pairs used to generate CSS var values. The key is a CSS var pattern, whose `$slug` fragment will be replaced with a preset slug. + * The value should be a valid CSS property (string) to match the incoming value, e.g., "color" to match var:preset|color|somePresetSlug. + * - property_keys => (array) array of keys whose values represent a valid CSS property, e.g., "margin" or "border". + * - path => (array) a path that accesses the corresponding style value in the block style object. + * - value_func => (string) the name of a function to generate a CSS definition array for a particular style object. The output of this function should be `array( "$property" => "$value", ... )`. + * + * @since 6.1.0 + * @var array + */ + const BLOCK_STYLE_DEFINITIONS_METADATA = array('color' => array('text' => array('property_keys' => array('default' => 'color'), 'path' => array('color', 'text'), 'css_vars' => array('color' => '--wp--preset--color--$slug'), 'classnames' => array('has-text-color' => \true, 'has-$slug-color' => 'color')), 'background' => array('property_keys' => array('default' => 'background-color'), 'path' => array('color', 'background'), 'classnames' => array('has-background' => \true, 'has-$slug-background-color' => 'color')), 'gradient' => array('property_keys' => array('default' => 'background'), 'path' => array('color', 'gradient'), 'classnames' => array('has-background' => \true, 'has-$slug-gradient-background' => 'gradient'))), 'border' => array('color' => array('property_keys' => array('default' => 'border-color', 'individual' => 'border-%s-color'), 'path' => array('border', 'color'), 'classnames' => array('has-border-color' => \true, 'has-$slug-border-color' => 'color')), 'radius' => array('property_keys' => array('default' => 'border-radius', 'individual' => 'border-%s-radius'), 'path' => array('border', 'radius')), 'style' => array('property_keys' => array('default' => 'border-style', 'individual' => 'border-%s-style'), 'path' => array('border', 'style')), 'width' => array('property_keys' => array('default' => 'border-width', 'individual' => 'border-%s-width'), 'path' => array('border', 'width')), 'top' => array('value_func' => array(self::class, 'get_individual_property_css_declarations'), 'path' => array('border', 'top'), 'css_vars' => array('color' => '--wp--preset--color--$slug')), 'right' => array('value_func' => array(self::class, 'get_individual_property_css_declarations'), 'path' => array('border', 'right'), 'css_vars' => array('color' => '--wp--preset--color--$slug')), 'bottom' => array('value_func' => array(self::class, 'get_individual_property_css_declarations'), 'path' => array('border', 'bottom'), 'css_vars' => array('color' => '--wp--preset--color--$slug')), 'left' => array('value_func' => array(self::class, 'get_individual_property_css_declarations'), 'path' => array('border', 'left'), 'css_vars' => array('color' => '--wp--preset--color--$slug'))), 'spacing' => array('padding' => array('property_keys' => array('default' => 'padding', 'individual' => 'padding-%s'), 'path' => array('spacing', 'padding'), 'css_vars' => array('spacing' => '--wp--preset--spacing--$slug')), 'margin' => array('property_keys' => array('default' => 'margin', 'individual' => 'margin-%s'), 'path' => array('spacing', 'margin'), 'css_vars' => array('spacing' => '--wp--preset--spacing--$slug'))), 'typography' => array('fontSize' => array('property_keys' => array('default' => 'font-size'), 'path' => array('typography', 'fontSize'), 'classnames' => array('has-$slug-font-size' => 'font-size')), 'fontFamily' => array('property_keys' => array('default' => 'font-family'), 'path' => array('typography', 'fontFamily'), 'classnames' => array('has-$slug-font-family' => 'font-family')), 'fontStyle' => array('property_keys' => array('default' => 'font-style'), 'path' => array('typography', 'fontStyle')), 'fontWeight' => array('property_keys' => array('default' => 'font-weight'), 'path' => array('typography', 'fontWeight')), 'lineHeight' => array('property_keys' => array('default' => 'line-height'), 'path' => array('typography', 'lineHeight')), 'textDecoration' => array('property_keys' => array('default' => 'text-decoration'), 'path' => array('typography', 'textDecoration')), 'textTransform' => array('property_keys' => array('default' => 'text-transform'), 'path' => array('typography', 'textTransform')), 'letterSpacing' => array('property_keys' => array('default' => 'letter-spacing'), 'path' => array('typography', 'letterSpacing')))); + /** + * Stores a CSS rule using the provided CSS selector and CSS declarations. + * + * @since 6.1.0 + * + * @param string $store_name A valid store key. + * @param string $css_selector When a selector is passed, the function will return a full CSS rule `$selector { ...rules }`, otherwise a concatenated string of properties and values. + * @param string[] $css_declarations An associative array of CSS definitions, e.g., array( "$property" => "$value", "$property" => "$value" ). + * + * @return void. + */ + public static function store_css_rule($store_name, $css_selector, $css_declarations) + { + } + /** + * Returns a store by store key. + * + * @since 6.1.0 + * + * @param string $store_name A store key. + * + * @return WP_Style_Engine_CSS_Rules_Store + */ + public static function get_store($store_name) + { + } + /** + * Returns classnames and CSS based on the values in a styles object. + * Return values are parsed based on the instructions in BLOCK_STYLE_DEFINITIONS_METADATA. + * + * @since 6.1.0 + * + * @param array $block_styles The style object. + * @param array $options { + * Optional. An array of options. Default empty array. + * + * @type bool $convert_vars_to_classnames Whether to skip converting incoming CSS var patterns, e.g., `var:preset|<PRESET_TYPE>|<PRESET_SLUG>`, to var( --wp--preset--* ) values. Default `false`. + * @type string $selector Optional. When a selector is passed, the value of `$css` in the return value will comprise a full CSS rule `$selector { ...$css_declarations }`, + * otherwise, the value will be a concatenated string of CSS declarations. + * } + * + * @return array { + * @type string $classnames Classnames separated by a space. + * @type string[] $declarations An associative array of CSS definitions, e.g., array( "$property" => "$value", "$property" => "$value" ). + * } + * @phpstan-param array{ + * convert_vars_to_classnames?: bool, + * selector?: string, + * } $options + * @phpstan-return array{ + * classnames: string, + * declarations: string[], + * } + */ + public static function parse_block_styles($block_styles, $options) + { + } + /** + * Returns compiled CSS from css_declarations. + * + * @since 6.1.0 + * + * @param string[] $css_declarations An associative array of CSS definitions, e.g., array( "$property" => "$value", "$property" => "$value" ). + * @param string $css_selector When a selector is passed, the function will return a full CSS rule `$selector { ...rules }`, otherwise a concatenated string of properties and values. + * + * @return string A compiled CSS string. + */ + public static function compile_css($css_declarations, $css_selector) + { + } + /** + * Returns a compiled stylesheet from stored CSS rules. + * + * @since 6.1.0 + * + * @param WP_Style_Engine_CSS_Rule[] $css_rules An array of WP_Style_Engine_CSS_Rule objects from a store or otherwise. + * @param array $options { + * Optional. An array of options. Default empty array. + * + * @type bool $optimize Whether to optimize the CSS output, e.g., combine rules. Default is `false`. + * @type bool $prettify Whether to add new lines and indents to output. Default is the test of whether the global constant `SCRIPT_DEBUG` is defined. + * } + * + * @return string A compiled stylesheet from stored CSS rules. + * @phpstan-param array{ + * optimize?: bool, + * prettify?: bool, + * } $options + */ + public static function compile_stylesheet_from_css_rules($css_rules, $options = array()) + { + } + } + /** + * Widget API: WP_Nav_Menu_Widget class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Core class used to implement the Navigation Menu widget. + * + * @since 3.0.0 + * + * @see WP_Widget + */ + class WP_Nav_Menu_Widget extends \WP_Widget + { + /** + * Sets up a new Navigation Menu widget instance. + * + * @since 3.0.0 + */ + public function __construct() + { + } + /** + * Outputs the content for the current Navigation Menu widget instance. + * + * @since 3.0.0 + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current Navigation Menu widget instance. + */ + public function widget($args, $instance) + { + } + /** + * Handles updating settings for the current Navigation Menu widget instance. + * + * @since 3.0.0 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Updated settings to save. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Outputs the settings form for the Navigation Menu widget. + * + * @since 3.0.0 + * + * @param array $instance Current settings. + * @global WP_Customize_Manager $wp_customize + */ + public function form($instance) + { + } + } + /** + * Widget API: WP_Widget_Archives class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Core class used to implement the Archives widget. + * + * @since 2.8.0 + * + * @see WP_Widget + */ + class WP_Widget_Archives extends \WP_Widget + { + /** + * Sets up a new Archives widget instance. + * + * @since 2.8.0 + */ + public function __construct() + { + } + /** + * Outputs the content for the current Archives widget instance. + * + * @since 2.8.0 + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current Archives widget instance. + */ + public function widget($args, $instance) + { + } + /** + * Handles updating settings for the current Archives widget instance. + * + * @since 2.8.0 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget_Archives::form(). + * @param array $old_instance Old settings for this instance. + * @return array Updated settings to save. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Outputs the settings form for the Archives widget. + * + * @since 2.8.0 + * + * @param array $instance Current settings. + */ + public function form($instance) + { + } + } + /** + * Widget API: WP_Widget_Block class + * + * @package WordPress + * @subpackage Widgets + * @since 5.8.0 + */ + /** + * Core class used to implement a Block widget. + * + * @since 5.8.0 + * + * @see WP_Widget + */ + class WP_Widget_Block extends \WP_Widget + { + /** + * Default instance. + * + * @since 5.8.0 + * @var array + */ + protected $default_instance = array('content' => ''); + /** + * Sets up a new Block widget instance. + * + * @since 5.8.0 + */ + public function __construct() + { + } + /** + * Outputs the content for the current Block widget instance. + * + * @since 5.8.0 + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current Block widget instance. + */ + public function widget($args, $instance) + { + } + /** + * Handles updating settings for the current Block widget instance. + * + * @since 5.8.0 + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Settings to save or bool false to cancel saving. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Outputs the Block widget settings form. + * + * @since 5.8.0 + * + * @see WP_Widget_Custom_HTML::render_control_template_scripts() + * + * @param array $instance Current instance. + */ + public function form($instance) + { + } + /** + * Makes sure no block widget is considered to be wide. + * + * @since 5.8.0 + * + * @param bool $is_wide Whether the widget is considered wide. + * @param string $widget_id Widget ID. + * @return bool Updated `is_wide` value. + */ + public function set_is_wide_widget_in_customizer($is_wide, $widget_id) + { + } + } + /** + * Widget API: WP_Widget_Calendar class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Core class used to implement the Calendar widget. + * + * @since 2.8.0 + * + * @see WP_Widget + */ + class WP_Widget_Calendar extends \WP_Widget + { + /** + * Sets up a new Calendar widget instance. + * + * @since 2.8.0 + */ + public function __construct() + { + } + /** + * Outputs the content for the current Calendar widget instance. + * + * @since 2.8.0 + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance The settings for the particular instance of the widget. + */ + public function widget($args, $instance) + { + } + /** + * Handles updating settings for the current Calendar widget instance. + * + * @since 2.8.0 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Updated settings to save. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Outputs the settings form for the Calendar widget. + * + * @since 2.8.0 + * + * @param array $instance Current settings. + */ + public function form($instance) + { + } + } + /** + * Widget API: WP_Widget_Categories class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Core class used to implement a Categories widget. + * + * @since 2.8.0 + * + * @see WP_Widget + */ + class WP_Widget_Categories extends \WP_Widget + { + /** + * Sets up a new Categories widget instance. + * + * @since 2.8.0 + */ + public function __construct() + { + } + /** + * Outputs the content for the current Categories widget instance. + * + * @since 2.8.0 + * @since 4.2.0 Creates a unique HTML ID for the `<select>` element + * if more than one instance is displayed on the page. + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current Categories widget instance. + */ + public function widget($args, $instance) + { + } + /** + * Handles updating settings for the current Categories widget instance. + * + * @since 2.8.0 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Updated settings to save. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Outputs the settings form for the Categories widget. + * + * @since 2.8.0 + * + * @param array $instance Current settings. + */ + public function form($instance) + { + } + } + /** + * Widget API: WP_Widget_Custom_HTML class + * + * @package WordPress + * @subpackage Widgets + * @since 4.8.1 + */ + /** + * Core class used to implement a Custom HTML widget. + * + * @since 4.8.1 + * + * @see WP_Widget + */ + class WP_Widget_Custom_HTML extends \WP_Widget + { + /** + * Whether or not the widget has been registered yet. + * + * @since 4.9.0 + * @var bool + */ + protected $registered = \false; + /** + * Default instance. + * + * @since 4.8.1 + * @var array + */ + protected $default_instance = array('title' => '', 'content' => ''); + /** + * Sets up a new Custom HTML widget instance. + * + * @since 4.8.1 + */ + public function __construct() + { + } + /** + * Add hooks for enqueueing assets when registering all widget instances of this widget class. + * + * @since 4.9.0 + * + * @param int $number Optional. The unique order number of this widget instance + * compared to other instances of the same class. Default -1. + */ + public function _register_one($number = -1) + { + } + /** + * Filters gallery shortcode attributes. + * + * Prevents all of a site's attachments from being shown in a gallery displayed on a + * non-singular template where a $post context is not available. + * + * @since 4.9.0 + * + * @param array $attrs Attributes. + * @return array Attributes. + */ + public function _filter_gallery_shortcode_attrs($attrs) + { + } + /** + * Outputs the content for the current Custom HTML widget instance. + * + * @since 4.8.1 + * + * @global WP_Post $post Global post object. + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current Custom HTML widget instance. + */ + public function widget($args, $instance) + { + } + /** + * Handles updating settings for the current Custom HTML widget instance. + * + * @since 4.8.1 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Settings to save or bool false to cancel saving. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Loads the required scripts and styles for the widget control. + * + * @since 4.9.0 + */ + public function enqueue_admin_scripts() + { + } + /** + * Outputs the Custom HTML widget settings form. + * + * @since 4.8.1 + * @since 4.9.0 The form contains only hidden sync inputs. For the control UI, see `WP_Widget_Custom_HTML::render_control_template_scripts()`. + * + * @see WP_Widget_Custom_HTML::render_control_template_scripts() + * + * @param array $instance Current instance. + */ + public function form($instance) + { + } + /** + * Render form template scripts. + * + * @since 4.9.0 + */ + public static function render_control_template_scripts() + { + } + /** + * Add help text to widgets admin screen. + * + * @since 4.9.0 + */ + public static function add_help_text() + { + } + } + /** + * Widget API: WP_Widget_Links class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Core class used to implement a Links widget. + * + * @since 2.8.0 + * + * @see WP_Widget + */ + class WP_Widget_Links extends \WP_Widget + { + /** + * Sets up a new Links widget instance. + * + * @since 2.8.0 + */ + public function __construct() + { + } + /** + * Outputs the content for the current Links widget instance. + * + * @since 2.8.0 + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current Links widget instance. + */ + public function widget($args, $instance) + { + } + /** + * Handles updating settings for the current Links widget instance. + * + * @since 2.8.0 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Updated settings to save. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Outputs the settings form for the Links widget. + * + * @since 2.8.0 + * + * @param array $instance Current settings. + */ + public function form($instance) + { + } + } + /** + * Widget API: WP_Media_Widget class + * + * @package WordPress + * @subpackage Widgets + * @since 4.8.0 + */ + /** + * Core class that implements a media widget. + * + * @since 4.8.0 + * + * @see WP_Widget + */ + abstract class WP_Widget_Media extends \WP_Widget + { + /** + * Translation labels. + * + * @since 4.8.0 + * @var array + */ + public $l10n = array('add_to_widget' => '', 'replace_media' => '', 'edit_media' => '', 'media_library_state_multi' => '', 'media_library_state_single' => '', 'missing_attachment' => '', 'no_media_selected' => '', 'add_media' => ''); + /** + * Whether or not the widget has been registered yet. + * + * @since 4.8.1 + * @var bool + */ + protected $registered = \false; + /** + * The default widget description. + * + * @since 6.0.0 + * @var string + */ + protected static $default_description = ''; + /** + * The default localized strings used by the widget. + * + * @since 6.0.0 + * @var string[] + */ + protected static $l10n_defaults = array(); + /** + * Constructor. + * + * @since 4.8.0 + * + * @param string $id_base Base ID for the widget, lowercase and unique. + * @param string $name Name for the widget displayed on the configuration page. + * @param array $widget_options Optional. Widget options. See wp_register_sidebar_widget() for + * information on accepted arguments. Default empty array. + * @param array $control_options Optional. Widget control options. See wp_register_widget_control() + * for information on accepted arguments. Default empty array. + * @phpstan-param array{ + * classname?: string, + * description?: string, + * show_instance_in_rest?: bool, + * } $widget_options See wp_register_sidebar_widget() + * @phpstan-param array{ + * height?: int, + * width?: int, + * id_base?: int|string, + * } $control_options See wp_register_widget_control() + */ + public function __construct($id_base, $name, $widget_options = array(), $control_options = array()) + { + } + /** + * Add hooks while registering all widget instances of this widget class. + * + * @since 4.8.0 + * + * @param int $number Optional. The unique order number of this widget instance + * compared to other instances of the same class. Default -1. + */ + public function _register_one($number = -1) + { + } + /** + * Get schema for properties of a widget instance (item). + * + * @since 4.8.0 + * + * @see WP_REST_Controller::get_item_schema() + * @see WP_REST_Controller::get_additional_fields() + * @link https://core.trac.wordpress.org/ticket/35574 + * + * @return array Schema for properties. + */ + public function get_instance_schema() + { + } + /** + * Determine if the supplied attachment is for a valid attachment post with the specified MIME type. + * + * @since 4.8.0 + * + * @param int|WP_Post $attachment Attachment post ID or object. + * @param string $mime_type MIME type. + * @return bool Is matching MIME type. + */ + public function is_attachment_with_mime_type($attachment, $mime_type) + { + } + /** + * Sanitize a token list string, such as used in HTML rel and class attributes. + * + * @since 4.8.0 + * + * @link http://w3c.github.io/html/infrastructure.html#space-separated-tokens + * @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList + * @param string|array $tokens List of tokens separated by spaces, or an array of tokens. + * @return string Sanitized token string list. + */ + public function sanitize_token_list($tokens) + { + } + /** + * Displays the widget on the front-end. + * + * @since 4.8.0 + * + * @see WP_Widget::widget() + * + * @param array $args Display arguments including before_title, after_title, before_widget, and after_widget. + * @param array $instance Saved setting from the database. + */ + public function widget($args, $instance) + { + } + /** + * Sanitizes the widget form values as they are saved. + * + * @since 4.8.0 + * @since 5.9.0 Renamed `$instance` to `$old_instance` to match parent class + * for PHP 8 named parameter support. + * + * @see WP_Widget::update() + * @see WP_REST_Request::has_valid_params() + * @see WP_REST_Request::sanitize_params() + * + * @param array $new_instance Values just sent to be saved. + * @param array $old_instance Previously saved values from database. + * @return array Updated safe values to be saved. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Render the media on the frontend. + * + * @since 4.8.0 + * + * @param array $instance Widget instance props. + */ + public abstract function render_media($instance); + /** + * Outputs the settings update form. + * + * Note that the widget UI itself is rendered with JavaScript via `MediaWidgetControl#render()`. + * + * @since 4.8.0 + * + * @see \WP_Widget_Media::render_control_template_scripts() Where the JS template is located. + * + * @param array $instance Current settings. + */ + public final function form($instance) + { + } + /** + * Filters the default media display states for items in the Media list table. + * + * @since 4.8.0 + * + * @param array $states An array of media states. + * @param WP_Post $post The current attachment object. + * @return array + */ + public function display_media_state($states, $post = \null) + { + } + /** + * Enqueue preview scripts. + * + * These scripts normally are enqueued just-in-time when a widget is rendered. + * In the customizer, however, widgets can be dynamically added and rendered via + * selective refresh, and so it is important to unconditionally enqueue them in + * case a widget does get added. + * + * @since 4.8.0 + */ + public function enqueue_preview_scripts() + { + } + /** + * Loads the required scripts and styles for the widget control. + * + * @since 4.8.0 + */ + public function enqueue_admin_scripts() + { + } + /** + * Render form template scripts. + * + * @since 4.8.0 + */ + public function render_control_template_scripts() + { + } + /** + * Resets the cache for the default labels. + * + * @since 6.0.0 + */ + public static function reset_default_labels() + { + } + /** + * Whether the widget has content to show. + * + * @since 4.8.0 + * + * @param array $instance Widget instance props. + * @return bool Whether widget has content. + */ + protected function has_content($instance) + { + } + /** + * Returns the default description of the widget. + * + * @since 6.0.0 + * + * @return string + */ + protected static function get_default_description() + { + } + /** + * Returns the default localized strings used by the widget. + * + * @since 6.0.0 + * + * @return (string|array)[] + */ + protected static function get_l10n_defaults() + { + } + } + /** + * Widget API: WP_Widget_Media_Audio class + * + * @package WordPress + * @subpackage Widgets + * @since 4.8.0 + */ + /** + * Core class that implements an audio widget. + * + * @since 4.8.0 + * + * @see WP_Widget_Media + * @see WP_Widget + */ + class WP_Widget_Media_Audio extends \WP_Widget_Media + { + /** + * Constructor. + * + * @since 4.8.0 + */ + public function __construct() + { + } + /** + * Get schema for properties of a widget instance (item). + * + * @since 4.8.0 + * + * @see WP_REST_Controller::get_item_schema() + * @see WP_REST_Controller::get_additional_fields() + * @link https://core.trac.wordpress.org/ticket/35574 + * + * @return array Schema for properties. + */ + public function get_instance_schema() + { + } + /** + * Render the media on the frontend. + * + * @since 4.8.0 + * + * @param array $instance Widget instance props. + */ + public function render_media($instance) + { + } + /** + * Enqueue preview scripts. + * + * These scripts normally are enqueued just-in-time when an audio shortcode is used. + * In the customizer, however, widgets can be dynamically added and rendered via + * selective refresh, and so it is important to unconditionally enqueue them in + * case a widget does get added. + * + * @since 4.8.0 + */ + public function enqueue_preview_scripts() + { + } + /** + * Loads the required media files for the media manager and scripts for media widgets. + * + * @since 4.8.0 + */ + public function enqueue_admin_scripts() + { + } + /** + * Render form template scripts. + * + * @since 4.8.0 + */ + public function render_control_template_scripts() + { + } + } + /** + * Widget API: WP_Widget_Media_Gallery class + * + * @package WordPress + * @subpackage Widgets + * @since 4.9.0 + */ + /** + * Core class that implements a gallery widget. + * + * @since 4.9.0 + * + * @see WP_Widget_Media + * @see WP_Widget + */ + class WP_Widget_Media_Gallery extends \WP_Widget_Media + { + /** + * Constructor. + * + * @since 4.9.0 + */ + public function __construct() + { + } + /** + * Get schema for properties of a widget instance (item). + * + * @since 4.9.0 + * + * @see WP_REST_Controller::get_item_schema() + * @see WP_REST_Controller::get_additional_fields() + * @link https://core.trac.wordpress.org/ticket/35574 + * + * @return array Schema for properties. + */ + public function get_instance_schema() + { + } + /** + * Render the media on the frontend. + * + * @since 4.9.0 + * + * @param array $instance Widget instance props. + */ + public function render_media($instance) + { + } + /** + * Loads the required media files for the media manager and scripts for media widgets. + * + * @since 4.9.0 + */ + public function enqueue_admin_scripts() + { + } + /** + * Render form template scripts. + * + * @since 4.9.0 + */ + public function render_control_template_scripts() + { + } + /** + * Whether the widget has content to show. + * + * @since 4.9.0 + * @access protected + * + * @param array $instance Widget instance props. + * @return bool Whether widget has content. + */ + protected function has_content($instance) + { + } + } + /** + * Widget API: WP_Widget_Media_Image class + * + * @package WordPress + * @subpackage Widgets + * @since 4.8.0 + */ + /** + * Core class that implements an image widget. + * + * @since 4.8.0 + * + * @see WP_Widget_Media + * @see WP_Widget + */ + class WP_Widget_Media_Image extends \WP_Widget_Media + { + /** + * Constructor. + * + * @since 4.8.0 + */ + public function __construct() + { + } + /** + * Get schema for properties of a widget instance (item). + * + * @since 4.8.0 + * + * @see WP_REST_Controller::get_item_schema() + * @see WP_REST_Controller::get_additional_fields() + * @link https://core.trac.wordpress.org/ticket/35574 + * + * @return array Schema for properties. + */ + public function get_instance_schema() + { + } + /** + * Render the media on the frontend. + * + * @since 4.8.0 + * + * @param array $instance Widget instance props. + */ + public function render_media($instance) + { + } + /** + * Loads the required media files for the media manager and scripts for media widgets. + * + * @since 4.8.0 + */ + public function enqueue_admin_scripts() + { + } + /** + * Render form template scripts. + * + * @since 4.8.0 + */ + public function render_control_template_scripts() + { + } + } + /** + * Widget API: WP_Widget_Media_Video class + * + * @package WordPress + * @subpackage Widgets + * @since 4.8.0 + */ + /** + * Core class that implements a video widget. + * + * @since 4.8.0 + * + * @see WP_Widget_Media + * @see WP_Widget + */ + class WP_Widget_Media_Video extends \WP_Widget_Media + { + /** + * Constructor. + * + * @since 4.8.0 + */ + public function __construct() + { + } + /** + * Get schema for properties of a widget instance (item). + * + * @since 4.8.0 + * + * @see WP_REST_Controller::get_item_schema() + * @see WP_REST_Controller::get_additional_fields() + * @link https://core.trac.wordpress.org/ticket/35574 + * + * @return array Schema for properties. + */ + public function get_instance_schema() + { + } + /** + * Render the media on the frontend. + * + * @since 4.8.0 + * + * @param array $instance Widget instance props. + */ + public function render_media($instance) + { + } + /** + * Inject max-width and remove height for videos too constrained to fit inside sidebars on frontend. + * + * @since 4.8.0 + * + * @param string $html Video shortcode HTML output. + * @return string HTML Output. + */ + public function inject_video_max_width_style($html) + { + } + /** + * Enqueue preview scripts. + * + * These scripts normally are enqueued just-in-time when a video shortcode is used. + * In the customizer, however, widgets can be dynamically added and rendered via + * selective refresh, and so it is important to unconditionally enqueue them in + * case a widget does get added. + * + * @since 4.8.0 + */ + public function enqueue_preview_scripts() + { + } + /** + * Loads the required scripts and styles for the widget control. + * + * @since 4.8.0 + */ + public function enqueue_admin_scripts() + { + } + /** + * Render form template scripts. + * + * @since 4.8.0 + */ + public function render_control_template_scripts() + { + } + } + /** + * Widget API: WP_Widget_Meta class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Core class used to implement a Meta widget. + * + * Displays log in/out, RSS feed links, etc. + * + * @since 2.8.0 + * + * @see WP_Widget + */ + class WP_Widget_Meta extends \WP_Widget + { + /** + * Sets up a new Meta widget instance. + * + * @since 2.8.0 + */ + public function __construct() + { + } + /** + * Outputs the content for the current Meta widget instance. + * + * @since 2.8.0 + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current Meta widget instance. + */ + public function widget($args, $instance) + { + } + /** + * Handles updating settings for the current Meta widget instance. + * + * @since 2.8.0 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Updated settings to save. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Outputs the settings form for the Meta widget. + * + * @since 2.8.0 + * + * @param array $instance Current settings. + */ + public function form($instance) + { + } + } + /** + * Widget API: WP_Widget_Pages class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Core class used to implement a Pages widget. + * + * @since 2.8.0 + * + * @see WP_Widget + */ + class WP_Widget_Pages extends \WP_Widget + { + /** + * Sets up a new Pages widget instance. + * + * @since 2.8.0 + */ + public function __construct() + { + } + /** + * Outputs the content for the current Pages widget instance. + * + * @since 2.8.0 + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current Pages widget instance. + */ + public function widget($args, $instance) + { + } + /** + * Handles updating settings for the current Pages widget instance. + * + * @since 2.8.0 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Updated settings to save. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Outputs the settings form for the Pages widget. + * + * @since 2.8.0 + * + * @param array $instance Current settings. + */ + public function form($instance) + { + } + } + /** + * Widget API: WP_Widget_Recent_Comments class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Core class used to implement a Recent Comments widget. + * + * @since 2.8.0 + * + * @see WP_Widget + */ + class WP_Widget_Recent_Comments extends \WP_Widget + { + /** + * Sets up a new Recent Comments widget instance. + * + * @since 2.8.0 + */ + public function __construct() + { + } + /** + * Outputs the default styles for the Recent Comments widget. + * + * @since 2.8.0 + */ + public function recent_comments_style() + { + } + /** + * Outputs the content for the current Recent Comments widget instance. + * + * @since 2.8.0 + * @since 5.4.0 Creates a unique HTML ID for the `<ul>` element + * if more than one instance is displayed on the page. + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current Recent Comments widget instance. + */ + public function widget($args, $instance) + { + } + /** + * Handles updating settings for the current Recent Comments widget instance. + * + * @since 2.8.0 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Updated settings to save. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Outputs the settings form for the Recent Comments widget. + * + * @since 2.8.0 + * + * @param array $instance Current settings. + */ + public function form($instance) + { + } + /** + * Flushes the Recent Comments widget cache. + * + * @since 2.8.0 + * + * @deprecated 4.4.0 Fragment caching was removed in favor of split queries. + */ + public function flush_widget_cache() + { + } + } + /** + * Widget API: WP_Widget_Recent_Posts class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Core class used to implement a Recent Posts widget. + * + * @since 2.8.0 + * + * @see WP_Widget + */ + class WP_Widget_Recent_Posts extends \WP_Widget + { + /** + * Sets up a new Recent Posts widget instance. + * + * @since 2.8.0 + */ + public function __construct() + { + } + /** + * Outputs the content for the current Recent Posts widget instance. + * + * @since 2.8.0 + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current Recent Posts widget instance. + */ + public function widget($args, $instance) + { + } + /** + * Handles updating the settings for the current Recent Posts widget instance. + * + * @since 2.8.0 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Updated settings to save. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Outputs the settings form for the Recent Posts widget. + * + * @since 2.8.0 + * + * @param array $instance Current settings. + */ + public function form($instance) + { + } + } + /** + * Widget API: WP_Widget_RSS class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Core class used to implement a RSS widget. + * + * @since 2.8.0 + * + * @see WP_Widget + */ + class WP_Widget_RSS extends \WP_Widget + { + /** + * Sets up a new RSS widget instance. + * + * @since 2.8.0 + */ + public function __construct() + { + } + /** + * Outputs the content for the current RSS widget instance. + * + * @since 2.8.0 + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current RSS widget instance. + */ + public function widget($args, $instance) + { + } + /** + * Handles updating settings for the current RSS widget instance. + * + * @since 2.8.0 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Updated settings to save. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Outputs the settings form for the RSS widget. + * + * @since 2.8.0 + * + * @param array $instance Current settings. + */ + public function form($instance) + { + } + } + /** + * Widget API: WP_Widget_Search class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Core class used to implement a Search widget. + * + * @since 2.8.0 + * + * @see WP_Widget + */ + class WP_Widget_Search extends \WP_Widget + { + /** + * Sets up a new Search widget instance. + * + * @since 2.8.0 + */ + public function __construct() + { + } + /** + * Outputs the content for the current Search widget instance. + * + * @since 2.8.0 + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current Search widget instance. + */ + public function widget($args, $instance) + { + } + /** + * Outputs the settings form for the Search widget. + * + * @since 2.8.0 + * + * @param array $instance Current settings. + */ + public function form($instance) + { + } + /** + * Handles updating settings for the current Search widget instance. + * + * @since 2.8.0 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Updated settings. + */ + public function update($new_instance, $old_instance) + { + } + } + /** + * Widget API: WP_Widget_Tag_Cloud class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Core class used to implement a Tag cloud widget. + * + * @since 2.8.0 + * + * @see WP_Widget + */ + class WP_Widget_Tag_Cloud extends \WP_Widget + { + /** + * Sets up a new Tag Cloud widget instance. + * + * @since 2.8.0 + */ + public function __construct() + { + } + /** + * Outputs the content for the current Tag Cloud widget instance. + * + * @since 2.8.0 + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current Tag Cloud widget instance. + */ + public function widget($args, $instance) + { + } + /** + * Handles updating settings for the current Tag Cloud widget instance. + * + * @since 2.8.0 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Settings to save or bool false to cancel saving. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Outputs the Tag Cloud widget settings form. + * + * @since 2.8.0 + * + * @param array $instance Current settings. + */ + public function form($instance) + { + } + /** + * Retrieves the taxonomy for the current Tag cloud widget instance. + * + * @since 4.4.0 + * + * @param array $instance Current settings. + * @return string Name of the current taxonomy if set, otherwise 'post_tag'. + */ + public function _get_current_taxonomy($instance) + { + } + } + /** + * Widget API: WP_Widget_Text class + * + * @package WordPress + * @subpackage Widgets + * @since 4.4.0 + */ + /** + * Core class used to implement a Text widget. + * + * @since 2.8.0 + * + * @see WP_Widget + */ + class WP_Widget_Text extends \WP_Widget + { + /** + * Whether or not the widget has been registered yet. + * + * @since 4.8.1 + * @var bool + */ + protected $registered = \false; + /** + * Sets up a new Text widget instance. + * + * @since 2.8.0 + */ + public function __construct() + { + } + /** + * Add hooks for enqueueing assets when registering all widget instances of this widget class. + * + * @param int $number Optional. The unique order number of this widget instance + * compared to other instances of the same class. Default -1. + */ + public function _register_one($number = -1) + { + } + /** + * Determines whether a given instance is legacy and should bypass using TinyMCE. + * + * @since 4.8.1 + * + * @param array $instance { + * Instance data. + * + * @type string $text Content. + * @type bool|string $filter Whether autop or content filters should apply. + * @type bool $legacy Whether widget is in legacy mode. + * } + * @return bool Whether Text widget instance contains legacy data. + * @phpstan-param array{ + * text?: string, + * filter?: bool|string, + * legacy?: bool, + * } $instance + */ + public function is_legacy_instance($instance) + { + } + /** + * Filters gallery shortcode attributes. + * + * Prevents all of a site's attachments from being shown in a gallery displayed on a + * non-singular template where a $post context is not available. + * + * @since 4.9.0 + * + * @param array $attrs Attributes. + * @return array Attributes. + */ + public function _filter_gallery_shortcode_attrs($attrs) + { + } + /** + * Outputs the content for the current Text widget instance. + * + * @since 2.8.0 + * + * @global WP_Post $post Global post object. + * + * @param array $args Display arguments including 'before_title', 'after_title', + * 'before_widget', and 'after_widget'. + * @param array $instance Settings for the current Text widget instance. + */ + public function widget($args, $instance) + { + } + /** + * Inject max-width and remove height for videos too constrained to fit inside sidebars on frontend. + * + * @since 4.9.0 + * + * @see WP_Widget_Media_Video::inject_video_max_width_style() + * + * @param array $matches Pattern matches from preg_replace_callback. + * @return string HTML Output. + */ + public function inject_video_max_width_style($matches) + { + } + /** + * Handles updating settings for the current Text widget instance. + * + * @since 2.8.0 + * + * @param array $new_instance New settings for this instance as input by the user via + * WP_Widget::form(). + * @param array $old_instance Old settings for this instance. + * @return array Settings to save or bool false to cancel saving. + */ + public function update($new_instance, $old_instance) + { + } + /** + * Enqueue preview scripts. + * + * These scripts normally are enqueued just-in-time when a playlist shortcode is used. + * However, in the customizer, a playlist shortcode may be used in a text widget and + * dynamically added via selective refresh, so it is important to unconditionally enqueue them. + * + * @since 4.9.3 + */ + public function enqueue_preview_scripts() + { + } + /** + * Loads the required scripts and styles for the widget control. + * + * @since 4.8.0 + */ + public function enqueue_admin_scripts() + { + } + /** + * Outputs the Text widget settings form. + * + * @since 2.8.0 + * @since 4.8.0 Form only contains hidden inputs which are synced with JS template. + * @since 4.8.1 Restored original form to be displayed when in legacy mode. + * + * @see WP_Widget_Text::render_control_template_scripts() + * @see _WP_Editors::editor() + * + * @param array $instance Current settings. + */ + public function form($instance) + { + } + /** + * Render form template scripts. + * + * @since 4.8.0 + * @since 4.9.0 The method is now static. + */ + public static function render_control_template_scripts() + { + } + } +} +namespace { + /** + * Adds an action hook specific to this page. + * + * Fires on {@see 'wp_head'}. + * + * @since MU (3.0.0) + */ + function do_activate_header() + { + } + /** + * Loads styles specific to this page. + * + * @since MU (3.0.0) + */ + function wpmu_activate_stylesheet() + { + } + /** + * Display JavaScript on the page. + * + * @since 3.5.0 + */ + function export_add_js() + { + } + /** + * Create the date options fields for exporting a given post type. + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @since 3.1.0 + * + * @param string $post_type The post type. Default 'post'. + */ + function export_date_options($post_type = 'post') + { + } + /** + * Administration API: Core Ajax handlers + * + * @package WordPress + * @subpackage Administration + * @since 2.1.0 + */ + // + // No-privilege Ajax handlers. + // + /** + * Ajax handler for the Heartbeat API in the no-privilege context. + * + * Runs when the user is not logged in. + * + * @since 3.6.0 + */ + function wp_ajax_nopriv_heartbeat() + { + } + // + // GET-based Ajax handlers. + // + /** + * Ajax handler for fetching a list table. + * + * @since 3.1.0 + */ + function wp_ajax_fetch_list() + { + } + /** + * Ajax handler for tag search. + * + * @since 3.1.0 + */ + function wp_ajax_ajax_tag_search() + { + } + /** + * Ajax handler for compression testing. + * + * @since 3.1.0 + */ + function wp_ajax_wp_compression_test() + { + } + /** + * Ajax handler for image editor previews. + * + * @since 3.1.0 + */ + function wp_ajax_imgedit_preview() + { + } + /** + * Ajax handler for oEmbed caching. + * + * @since 3.1.0 + * + * @global WP_Embed $wp_embed + */ + function wp_ajax_oembed_cache() + { + } + /** + * Ajax handler for user autocomplete. + * + * @since 3.4.0 + */ + function wp_ajax_autocomplete_user() + { + } + /** + * Handles Ajax requests for community events + * + * @since 4.8.0 + */ + function wp_ajax_get_community_events() + { + } + /** + * Ajax handler for dashboard widgets. + * + * @since 3.4.0 + */ + function wp_ajax_dashboard_widgets() + { + } + /** + * Ajax handler for Customizer preview logged-in status. + * + * @since 3.4.0 + */ + function wp_ajax_logged_in() + { + } + // + // Ajax helpers. + // + /** + * Sends back current comment total and new page links if they need to be updated. + * + * Contrary to normal success Ajax response ("1"), die with time() on success. + * + * @since 2.7.0 + * @access private + * + * @param int $comment_id + * @param int $delta + */ + function _wp_ajax_delete_comment_response($comment_id, $delta = -1) + { + } + // + // POST-based Ajax handlers. + // + /** + * Ajax handler for adding a hierarchical term. + * + * @since 3.1.0 + * @access private + */ + function _wp_ajax_add_hierarchical_term() + { + } + /** + * Ajax handler for deleting a comment. + * + * @since 3.1.0 + */ + function wp_ajax_delete_comment() + { + } + /** + * Ajax handler for deleting a tag. + * + * @since 3.1.0 + */ + function wp_ajax_delete_tag() + { + } + /** + * Ajax handler for deleting a link. + * + * @since 3.1.0 + */ + function wp_ajax_delete_link() + { + } + /** + * Ajax handler for deleting meta. + * + * @since 3.1.0 + */ + function wp_ajax_delete_meta() + { + } + /** + * Ajax handler for deleting a post. + * + * @since 3.1.0 + * + * @param string $action Action to perform. + */ + function wp_ajax_delete_post($action) + { + } + /** + * Ajax handler for sending a post to the Trash. + * + * @since 3.1.0 + * + * @param string $action Action to perform. + */ + function wp_ajax_trash_post($action) + { + } + /** + * Ajax handler to restore a post from the Trash. + * + * @since 3.1.0 + * + * @param string $action Action to perform. + */ + function wp_ajax_untrash_post($action) + { + } + /** + * Ajax handler to delete a page. + * + * @since 3.1.0 + * + * @param string $action Action to perform. + */ + function wp_ajax_delete_page($action) + { + } + /** + * Ajax handler to dim a comment. + * + * @since 3.1.0 + */ + function wp_ajax_dim_comment() + { + } + /** + * Ajax handler for adding a link category. + * + * @since 3.1.0 + * + * @param string $action Action to perform. + */ + function wp_ajax_add_link_category($action) + { + } + /** + * Ajax handler to add a tag. + * + * @since 3.1.0 + */ + function wp_ajax_add_tag() + { + } + /** + * Ajax handler for getting a tagcloud. + * + * @since 3.1.0 + */ + function wp_ajax_get_tagcloud() + { + } + /** + * Ajax handler for getting comments. + * + * @since 3.1.0 + * + * @global int $post_id + * + * @param string $action Action to perform. + */ + function wp_ajax_get_comments($action) + { + } + /** + * Ajax handler for replying to a comment. + * + * @since 3.1.0 + * + * @param string $action Action to perform. + */ + function wp_ajax_replyto_comment($action) + { + } + /** + * Ajax handler for editing a comment. + * + * @since 3.1.0 + */ + function wp_ajax_edit_comment() + { + } + /** + * Ajax handler for adding a menu item. + * + * @since 3.1.0 + */ + function wp_ajax_add_menu_item() + { + } + /** + * Ajax handler for adding meta. + * + * @since 3.1.0 + */ + function wp_ajax_add_meta() + { + } + /** + * Ajax handler for adding a user. + * + * @since 3.1.0 + * + * @param string $action Action to perform. + */ + function wp_ajax_add_user($action) + { + } + /** + * Ajax handler for closed post boxes. + * + * @since 3.1.0 + */ + function wp_ajax_closed_postboxes() + { + } + /** + * Ajax handler for hidden columns. + * + * @since 3.1.0 + */ + function wp_ajax_hidden_columns() + { + } + /** + * Ajax handler for updating whether to display the welcome panel. + * + * @since 3.1.0 + */ + function wp_ajax_update_welcome_panel() + { + } + /** + * Ajax handler for retrieving menu meta boxes. + * + * @since 3.1.0 + */ + function wp_ajax_menu_get_metabox() + { + } + /** + * Ajax handler for internal linking. + * + * @since 3.1.0 + */ + function wp_ajax_wp_link_ajax() + { + } + /** + * Ajax handler for menu locations save. + * + * @since 3.1.0 + */ + function wp_ajax_menu_locations_save() + { + } + /** + * Ajax handler for saving the meta box order. + * + * @since 3.1.0 + */ + function wp_ajax_meta_box_order() + { + } + /** + * Ajax handler for menu quick searching. + * + * @since 3.1.0 + */ + function wp_ajax_menu_quick_search() + { + } + /** + * Ajax handler to retrieve a permalink. + * + * @since 3.1.0 + */ + function wp_ajax_get_permalink() + { + } + /** + * Ajax handler to retrieve a sample permalink. + * + * @since 3.1.0 + */ + function wp_ajax_sample_permalink() + { + } + /** + * Ajax handler for Quick Edit saving a post from a list table. + * + * @since 3.1.0 + * + * @global string $mode List table view mode. + */ + function wp_ajax_inline_save() + { + } + /** + * Ajax handler for quick edit saving for a term. + * + * @since 3.1.0 + */ + function wp_ajax_inline_save_tax() + { + } + /** + * Ajax handler for querying posts for the Find Posts modal. + * + * @see window.findPosts + * + * @since 3.1.0 + */ + function wp_ajax_find_posts() + { + } + /** + * Ajax handler for saving the widgets order. + * + * @since 3.1.0 + */ + function wp_ajax_widgets_order() + { + } + /** + * Ajax handler for saving a widget. + * + * @since 3.1.0 + * + * @global array $wp_registered_widgets + * @global array $wp_registered_widget_controls + * @global array $wp_registered_widget_updates + */ + function wp_ajax_save_widget() + { + } + /** + * Ajax handler for updating a widget. + * + * @since 3.9.0 + * + * @global WP_Customize_Manager $wp_customize + */ + function wp_ajax_update_widget() + { + } + /** + * Ajax handler for removing inactive widgets. + * + * @since 4.4.0 + */ + function wp_ajax_delete_inactive_widgets() + { + } + /** + * Ajax handler for creating missing image sub-sizes for just uploaded images. + * + * @since 5.3.0 + */ + function wp_ajax_media_create_image_subsizes() + { + } + /** + * Ajax handler for uploading attachments + * + * @since 3.3.0 + */ + function wp_ajax_upload_attachment() + { + } + /** + * Ajax handler for image editing. + * + * @since 3.1.0 + */ + function wp_ajax_image_editor() + { + } + /** + * Ajax handler for setting the featured image. + * + * @since 3.1.0 + */ + function wp_ajax_set_post_thumbnail() + { + } + /** + * Ajax handler for retrieving HTML for the featured image. + * + * @since 4.6.0 + */ + function wp_ajax_get_post_thumbnail_html() + { + } + /** + * Ajax handler for setting the featured image for an attachment. + * + * @since 4.0.0 + * + * @see set_post_thumbnail() + */ + function wp_ajax_set_attachment_thumbnail() + { + } + /** + * Ajax handler for date formatting. + * + * @since 3.1.0 + */ + function wp_ajax_date_format() + { + } + /** + * Ajax handler for time formatting. + * + * @since 3.1.0 + */ + function wp_ajax_time_format() + { + } + /** + * Ajax handler for saving posts from the fullscreen editor. + * + * @since 3.1.0 + * @deprecated 4.3.0 + */ + function wp_ajax_wp_fullscreen_save_post() + { + } + /** + * Ajax handler for removing a post lock. + * + * @since 3.1.0 + */ + function wp_ajax_wp_remove_post_lock() + { + } + /** + * Ajax handler for dismissing a WordPress pointer. + * + * @since 3.1.0 + */ + function wp_ajax_dismiss_wp_pointer() + { + } + /** + * Ajax handler for getting an attachment. + * + * @since 3.5.0 + */ + function wp_ajax_get_attachment() + { + } + /** + * Ajax handler for querying attachments. + * + * @since 3.5.0 + */ + function wp_ajax_query_attachments() + { + } + /** + * Ajax handler for updating attachment attributes. + * + * @since 3.5.0 + */ + function wp_ajax_save_attachment() + { + } + /** + * Ajax handler for saving backward compatible attachment attributes. + * + * @since 3.5.0 + */ + function wp_ajax_save_attachment_compat() + { + } + /** + * Ajax handler for saving the attachment order. + * + * @since 3.5.0 + */ + function wp_ajax_save_attachment_order() + { + } + /** + * Ajax handler for sending an attachment to the editor. + * + * Generates the HTML to send an attachment to the editor. + * Backward compatible with the {@see 'media_send_to_editor'} filter + * and the chain of filters that follow. + * + * @since 3.5.0 + */ + function wp_ajax_send_attachment_to_editor() + { + } + /** + * Ajax handler for sending a link to the editor. + * + * Generates the HTML to send a non-image embed link to the editor. + * + * Backward compatible with the following filters: + * - file_send_to_editor_url + * - audio_send_to_editor_url + * - video_send_to_editor_url + * + * @since 3.5.0 + * + * @global WP_Post $post Global post object. + * @global WP_Embed $wp_embed + */ + function wp_ajax_send_link_to_editor() + { + } + /** + * Ajax handler for the Heartbeat API. + * + * Runs when the user is logged in. + * + * @since 3.6.0 + */ + function wp_ajax_heartbeat() + { + } + /** + * Ajax handler for getting revision diffs. + * + * @since 3.6.0 + */ + function wp_ajax_get_revision_diffs() + { + } + /** + * Ajax handler for auto-saving the selected color scheme for + * a user's own profile. + * + * @since 3.8.0 + * + * @global array $_wp_admin_css_colors + */ + function wp_ajax_save_user_color_scheme() + { + } + /** + * Ajax handler for getting themes from themes_api(). + * + * @since 3.9.0 + * + * @global array $themes_allowedtags + * @global array $theme_field_defaults + */ + function wp_ajax_query_themes() + { + } + /** + * Apply [embed] Ajax handlers to a string. + * + * @since 4.0.0 + * + * @global WP_Post $post Global post object. + * @global WP_Embed $wp_embed Embed API instance. + * @global WP_Scripts $wp_scripts + * @global int $content_width + */ + function wp_ajax_parse_embed() + { + } + /** + * @since 4.0.0 + * + * @global WP_Post $post Global post object. + * @global WP_Scripts $wp_scripts + */ + function wp_ajax_parse_media_shortcode() + { + } + /** + * Ajax handler for destroying multiple open sessions for a user. + * + * @since 4.1.0 + */ + function wp_ajax_destroy_sessions() + { + } + /** + * Ajax handler for cropping an image. + * + * @since 4.3.0 + */ + function wp_ajax_crop_image() + { + } + /** + * Ajax handler for generating a password. + * + * @since 4.4.0 + */ + function wp_ajax_generate_password() + { + } + /** + * Ajax handler for generating a password in the no-privilege context. + * + * @since 5.7.0 + */ + function wp_ajax_nopriv_generate_password() + { + } + /** + * Ajax handler for saving the user's WordPress.org username. + * + * @since 4.4.0 + */ + function wp_ajax_save_wporg_username() + { + } + /** + * Ajax handler for installing a theme. + * + * @since 4.6.0 + * + * @see Theme_Upgrader + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + */ + function wp_ajax_install_theme() + { + } + /** + * Ajax handler for updating a theme. + * + * @since 4.6.0 + * + * @see Theme_Upgrader + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + */ + function wp_ajax_update_theme() + { + } + /** + * Ajax handler for deleting a theme. + * + * @since 4.6.0 + * + * @see delete_theme() + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + */ + function wp_ajax_delete_theme() + { + } + /** + * Ajax handler for installing a plugin. + * + * @since 4.6.0 + * + * @see Plugin_Upgrader + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + */ + function wp_ajax_install_plugin() + { + } + /** + * Ajax handler for updating a plugin. + * + * @since 4.2.0 + * + * @see Plugin_Upgrader + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + */ + function wp_ajax_update_plugin() + { + } + /** + * Ajax handler for deleting a plugin. + * + * @since 4.6.0 + * + * @see delete_plugins() + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + */ + function wp_ajax_delete_plugin() + { + } + /** + * Ajax handler for searching plugins. + * + * @since 4.6.0 + * + * @global string $s Search term. + */ + function wp_ajax_search_plugins() + { + } + /** + * Ajax handler for searching plugins to install. + * + * @since 4.6.0 + */ + function wp_ajax_search_install_plugins() + { + } + /** + * Ajax handler for editing a theme or plugin file. + * + * @since 4.9.0 + * + * @see wp_edit_theme_plugin_file() + */ + function wp_ajax_edit_theme_plugin_file() + { + } + /** + * Ajax handler for exporting a user's personal data. + * + * @since 4.9.6 + */ + function wp_ajax_wp_privacy_export_personal_data() + { + } + /** + * Ajax handler for erasing personal data. + * + * @since 4.9.6 + */ + function wp_ajax_wp_privacy_erase_personal_data() + { + } + /** + * Ajax handler for site health checks on server communication. + * + * @since 5.2.0 + * @deprecated 5.6.0 Use WP_REST_Site_Health_Controller::test_dotorg_communication() + * @see WP_REST_Site_Health_Controller::test_dotorg_communication() + */ + function wp_ajax_health_check_dotorg_communication() + { + } + /** + * Ajax handler for site health checks on background updates. + * + * @since 5.2.0 + * @deprecated 5.6.0 Use WP_REST_Site_Health_Controller::test_background_updates() + * @see WP_REST_Site_Health_Controller::test_background_updates() + */ + function wp_ajax_health_check_background_updates() + { + } + /** + * Ajax handler for site health checks on loopback requests. + * + * @since 5.2.0 + * @deprecated 5.6.0 Use WP_REST_Site_Health_Controller::test_loopback_requests() + * @see WP_REST_Site_Health_Controller::test_loopback_requests() + */ + function wp_ajax_health_check_loopback_requests() + { + } + /** + * Ajax handler for site health check to update the result status. + * + * @since 5.2.0 + */ + function wp_ajax_health_check_site_status_result() + { + } + /** + * Ajax handler for site health check to get directories and database sizes. + * + * @since 5.2.0 + * @deprecated 5.6.0 Use WP_REST_Site_Health_Controller::get_directory_sizes() + * @see WP_REST_Site_Health_Controller::get_directory_sizes() + */ + function wp_ajax_health_check_get_sizes() + { + } + /** + * Ajax handler to renew the REST API nonce. + * + * @since 5.3.0 + */ + function wp_ajax_rest_nonce() + { + } + /** + * Ajax handler to enable or disable plugin and theme auto-updates. + * + * @since 5.5.0 + */ + function wp_ajax_toggle_auto_updates() + { + } + /** + * Ajax handler sends a password reset link. + * + * @since 5.7.0 + */ + function wp_ajax_send_password_reset() + { + } + /** + * WordPress Bookmark Administration API + * + * @package WordPress + * @subpackage Administration + */ + /** + * Add a link to using values provided in $_POST. + * + * @since 2.0.0 + * + * @return int|WP_Error Value 0 or WP_Error on failure. The link ID on success. + */ + function add_link() + { + } + /** + * Updates or inserts a link using values provided in $_POST. + * + * @since 2.0.0 + * + * @param int $link_id Optional. ID of the link to edit. Default 0. + * @return int|WP_Error Value 0 or WP_Error on failure. The link ID on success. + */ + function edit_link($link_id = 0) + { + } + /** + * Retrieves the default link for editing. + * + * @since 2.0.0 + * + * @return stdClass Default link object. + */ + function get_default_link_to_edit() + { + } + /** + * Deletes a specified link from the database. + * + * @since 2.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $link_id ID of the link to delete + * @return true Always true. + */ + function wp_delete_link($link_id) + { + } + /** + * Retrieves the link category IDs associated with the link specified. + * + * @since 2.1.0 + * + * @param int $link_id Link ID to look up. + * @return int[] The IDs of the requested link's categories. + */ + function wp_get_link_cats($link_id = 0) + { + } + /** + * Retrieves link data based on its ID. + * + * @since 2.0.0 + * + * @param int|stdClass $link Link ID or object to retrieve. + * @return object Link object for editing. + */ + function get_link_to_edit($link) + { + } + /** + * Inserts a link into the database, or updates an existing link. + * + * Runs all the necessary sanitizing, provides default values if arguments are missing, + * and finally saves the link. + * + * @since 2.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $linkdata { + * Elements that make up the link to insert. + * + * @type int $link_id Optional. The ID of the existing link if updating. + * @type string $link_url The URL the link points to. + * @type string $link_name The title of the link. + * @type string $link_image Optional. A URL of an image. + * @type string $link_target Optional. The target element for the anchor tag. + * @type string $link_description Optional. A short description of the link. + * @type string $link_visible Optional. 'Y' means visible, anything else means not. + * @type int $link_owner Optional. A user ID. + * @type int $link_rating Optional. A rating for the link. + * @type string $link_rel Optional. A relationship of the link to you. + * @type string $link_notes Optional. An extended description of or notes on the link. + * @type string $link_rss Optional. A URL of an associated RSS feed. + * @type int $link_category Optional. The term ID of the link category. + * If empty, uses default link category. + * } + * @param bool $wp_error Optional. Whether to return a WP_Error object on failure. Default false. + * @return int|WP_Error Value 0 or WP_Error on failure. The link ID on success. + * @phpstan-param array{ + * link_id?: int, + * link_url?: string, + * link_name?: string, + * link_image?: string, + * link_target?: string, + * link_description?: string, + * link_visible?: string, + * link_owner?: int, + * link_rating?: int, + * link_rel?: string, + * link_notes?: string, + * link_rss?: string, + * link_category?: int, + * } $linkdata + */ + function wp_insert_link($linkdata, $wp_error = \false) + { + } + /** + * Update link with the specified link categories. + * + * @since 2.1.0 + * + * @param int $link_id ID of the link to update. + * @param int[] $link_categories Array of link category IDs to add the link to. + */ + function wp_set_link_cats($link_id = 0, $link_categories = array()) + { + } + /** + * Updates a link in the database. + * + * @since 2.0.0 + * + * @param array $linkdata Link data to update. See wp_insert_link() for accepted arguments. + * @return int|WP_Error Value 0 or WP_Error on failure. The updated link ID on success. + * @phpstan-param array{ + * link_id?: int, + * link_url?: string, + * link_name?: string, + * link_image?: string, + * link_target?: string, + * link_description?: string, + * link_visible?: string, + * link_owner?: int, + * link_rating?: int, + * link_rel?: string, + * link_notes?: string, + * link_rss?: string, + * link_category?: int, + * } $linkdata See wp_insert_link() + */ + function wp_update_link($linkdata) + { + } + /** + * Outputs the 'disabled' message for the WordPress Link Manager. + * + * @since 3.5.0 + * @access private + * + * @global string $pagenow The filename of the current screen. + */ + function wp_link_manager_disabled_message() + { + } + // End of class + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : PclZipUtilPathReduction() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function PclZipUtilPathReduction($p_dir) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : PclZipUtilPathInclusion() + // Description : + // This function indicates if the path $p_path is under the $p_dir tree. Or, + // said in an other way, if the file or sub-dir $p_path is inside the dir + // $p_dir. + // The function indicates also if the path is exactly the same as the dir. + // This function supports path with duplicated '/' like '//', but does not + // support '.' or '..' statements. + // Parameters : + // Return Values : + // 0 if $p_path is not inside directory $p_dir + // 1 if $p_path is inside directory $p_dir + // 2 if $p_path is exactly the same as $p_dir + // -------------------------------------------------------------------------------- + function PclZipUtilPathInclusion($p_dir, $p_path) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : PclZipUtilCopyBlock() + // Description : + // Parameters : + // $p_mode : read/write compression mode + // 0 : src & dest normal + // 1 : src gzip, dest normal + // 2 : src normal, dest gzip + // 3 : src & dest gzip + // Return Values : + // -------------------------------------------------------------------------------- + function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode = 0) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : PclZipUtilRename() + // Description : + // This function tries to do a simple rename() function. If it fails, it + // tries to copy the $p_src file in a new $p_dest file and then unlink the + // first one. + // Parameters : + // $p_src : Old filename + // $p_dest : New filename + // Return Values : + // 1 on success, 0 on failure. + // -------------------------------------------------------------------------------- + function PclZipUtilRename($p_src, $p_dest) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : PclZipUtilOptionText() + // Description : + // Translate option value in text. Mainly for debug purpose. + // Parameters : + // $p_option : the option value. + // Return Values : + // The option text value. + // -------------------------------------------------------------------------------- + function PclZipUtilOptionText($p_option) + { + } + // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- + // Function : PclZipUtilTranslateWinPath() + // Description : + // Translate windows path by replacing '\' by '/' and optionally removing + // drive letter. + // Parameters : + // $p_path : path to translate. + // $p_remove_disk_letter : true | false + // Return Values : + // The path translated. + // -------------------------------------------------------------------------------- + function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter = \true) + { + } + /** + * Returns value of command line params. + * Exits when a required param is not set. + * + * @param string $param + * @param bool $required + * @return mixed + */ + function get_cli_args($param, $required = \false) + { + } + /** + * WordPress Comment Administration API. + * + * @package WordPress + * @subpackage Administration + * @since 2.3.0 + */ + /** + * Determines if a comment exists based on author and date. + * + * For best performance, use `$timezone = 'gmt'`, which queries a field that is properly indexed. The default value + * for `$timezone` is 'blog' for legacy reasons. + * + * @since 2.0.0 + * @since 4.4.0 Added the `$timezone` parameter. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $comment_author Author of the comment. + * @param string $comment_date Date of the comment. + * @param string $timezone Timezone. Accepts 'blog' or 'gmt'. Default 'blog'. + * @return string|null Comment post ID on success. + */ + function comment_exists($comment_author, $comment_date, $timezone = 'blog') + { + } + /** + * Updates a comment with values provided in $_POST. + * + * @since 2.0.0 + * @since 5.5.0 A return value was added. + * + * @return int|WP_Error The value 1 if the comment was updated, 0 if not updated. + * A WP_Error object on failure. + */ + function edit_comment() + { + } + /** + * Returns a WP_Comment object based on comment ID. + * + * @since 2.0.0 + * + * @param int $id ID of comment to retrieve. + * @return WP_Comment|false Comment if found. False on failure. + */ + function get_comment_to_edit($id) + { + } + /** + * Gets the number of pending comments on a post or posts. + * + * @since 2.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|int[] $post_id Either a single Post ID or an array of Post IDs + * @return int|int[] Either a single Posts pending comments as an int or an array of ints keyed on the Post IDs + */ + function get_pending_comments_num($post_id) + { + } + /** + * Adds avatars to relevant places in admin. + * + * @since 2.5.0 + * + * @param string $name User name. + * @return string Avatar with the user name. + */ + function floated_admin_avatar($name) + { + } + /** + * Enqueues comment shortcuts jQuery script. + * + * @since 2.7.0 + */ + function enqueue_comment_hotkeys_js() + { + } + /** + * Displays error message at bottom of comments. + * + * @param string $msg Error Message. Assumed to contain HTML and be sanitized. + */ + function comment_footer_die($msg) + { + } + /** + * WordPress Credits Administration API. + * + * @package WordPress + * @subpackage Administration + * @since 4.4.0 + */ + /** + * Retrieve the contributor credits. + * + * @since 3.2.0 + * @since 5.6.0 Added the `$version` and `$locale` parameters. + * + * @param string $version WordPress version. Defaults to the current version. + * @param string $locale WordPress locale. Defaults to the current user's locale. + * @return array|false A list of all of the contributors, or false on error. + */ + function wp_credits($version = '', $locale = '') + { + } + /** + * Retrieve the link to a contributor's WordPress.org profile page. + * + * @access private + * @since 3.2.0 + * + * @param string $display_name The contributor's display name (passed by reference). + * @param string $username The contributor's username. + * @param string $profiles URL to the contributor's WordPress.org profile page. + */ + function _wp_credits_add_profile_link(&$display_name, $username, $profiles) + { + } + /** + * Retrieve the link to an external library used in WordPress. + * + * @access private + * @since 3.2.0 + * + * @param string $data External library data (passed by reference). + */ + function _wp_credits_build_object_link(&$data) + { + } + /** + * Displays the title for a given group of contributors. + * + * @since 5.3.0 + * + * @param array $group_data The current contributor group. + */ + function wp_credits_section_title($group_data = array()) + { + } + /** + * Displays a list of contributors for a given group. + * + * @since 5.3.0 + * + * @param array $credits The credits groups returned from the API. + * @param string $slug The current group to display. + */ + function wp_credits_section_list($credits = array(), $slug = '') + { + } + /** + * WordPress Dashboard Widget Administration Screen API + * + * @package WordPress + * @subpackage Administration + */ + /** + * Registers dashboard widgets. + * + * Handles POST data, sets up filters. + * + * @since 2.5.0 + * + * @global array $wp_registered_widgets + * @global array $wp_registered_widget_controls + * @global callable[] $wp_dashboard_control_callbacks + */ + function wp_dashboard_setup() + { + } + /** + * Adds a new dashboard widget. + * + * @since 2.7.0 + * @since 5.6.0 The `$context` and `$priority` parameters were added. + * + * @global callable[] $wp_dashboard_control_callbacks + * + * @param string $widget_id Widget ID (used in the 'id' attribute for the widget). + * @param string $widget_name Title of the widget. + * @param callable $callback Function that fills the widget with the desired content. + * The function should echo its output. + * @param callable $control_callback Optional. Function that outputs controls for the widget. Default null. + * @param array $callback_args Optional. Data that should be set as the $args property of the widget array + * (which is the second parameter passed to your callback). Default null. + * @param string $context Optional. The context within the screen where the box should display. + * Accepts 'normal', 'side', 'column3', or 'column4'. Default 'normal'. + * @param string $priority Optional. The priority within the context where the box should show. + * Accepts 'high', 'core', 'default', or 'low'. Default 'core'. + */ + function wp_add_dashboard_widget($widget_id, $widget_name, $callback, $control_callback = \null, $callback_args = \null, $context = 'normal', $priority = 'core') + { + } + /** + * Outputs controls for the current dashboard widget. + * + * @access private + * @since 2.7.0 + * + * @param mixed $dashboard + * @param array $meta_box + */ + function _wp_dashboard_control_callback($dashboard, $meta_box) + { + } + /** + * Displays the dashboard. + * + * @since 2.5.0 + */ + function wp_dashboard() + { + } + // + // Dashboard Widgets. + // + /** + * Dashboard widget that displays some basic stats about the site. + * + * Formerly 'Right Now'. A streamlined 'At a Glance' as of 3.8. + * + * @since 2.7.0 + */ + function wp_dashboard_right_now() + { + } + /** + * @since 3.1.0 + */ + function wp_network_dashboard_right_now() + { + } + /** + * The Quick Draft widget display and creation of drafts. + * + * @since 3.8.0 + * + * @global int $post_ID + * + * @param string|false $error_msg Optional. Error message. Default false. + */ + function wp_dashboard_quick_press($error_msg = \false) + { + } + /** + * Show recent drafts of the user on the dashboard. + * + * @since 2.7.0 + * + * @param WP_Post[]|false $drafts Optional. Array of posts to display. Default false. + */ + function wp_dashboard_recent_drafts($drafts = \false) + { + } + /** + * Outputs a row for the Recent Comments widget. + * + * @access private + * @since 2.7.0 + * + * @global WP_Comment $comment Global comment object. + * + * @param WP_Comment $comment The current comment. + * @param bool $show_date Optional. Whether to display the date. + */ + function _wp_dashboard_recent_comments_row(&$comment, $show_date = \true) + { + } + /** + * Callback function for Activity widget. + * + * @since 3.8.0 + */ + function wp_dashboard_site_activity() + { + } + /** + * Generates Publishing Soon and Recently Published sections. + * + * @since 3.8.0 + * + * @param array $args { + * An array of query and display arguments. + * + * @type int $max Number of posts to display. + * @type string $status Post status. + * @type string $order Designates ascending ('ASC') or descending ('DESC') order. + * @type string $title Section title. + * @type string $id The container id. + * } + * @return bool False if no posts were found. True otherwise. + * @phpstan-param array{ + * max?: int, + * status?: string, + * order?: string, + * title?: string, + * id?: string, + * } $args + */ + function wp_dashboard_recent_posts($args) + { + } + /** + * Show Comments section. + * + * @since 3.8.0 + * + * @param int $total_items Optional. Number of comments to query. Default 5. + * @return bool False if no comments were found. True otherwise. + */ + function wp_dashboard_recent_comments($total_items = 5) + { + } + /** + * Display generic dashboard RSS widget feed. + * + * @since 2.5.0 + * + * @param string $widget_id + */ + function wp_dashboard_rss_output($widget_id) + { + } + /** + * Checks to see if all of the feed url in $check_urls are cached. + * + * If $check_urls is empty, look for the rss feed url found in the dashboard + * widget options of $widget_id. If cached, call $callback, a function that + * echoes out output for this widget. If not cache, echo a "Loading..." stub + * which is later replaced by Ajax call (see top of /wp-admin/index.php) + * + * @since 2.5.0 + * @since 5.3.0 Formalized the existing and already documented `...$args` parameter + * by adding it to the function signature. + * + * @param string $widget_id The widget ID. + * @param callable $callback The callback function used to display each feed. + * @param array $check_urls RSS feeds. + * @param mixed ...$args Optional additional parameters to pass to the callback function. + * @return bool True on success, false on failure. + */ + function wp_dashboard_cached_rss_widget($widget_id, $callback, $check_urls = array(), ...$args) + { + } + // + // Dashboard Widgets Controls. + // + /** + * Calls widget control callback. + * + * @since 2.5.0 + * + * @global callable[] $wp_dashboard_control_callbacks + * + * @param int|false $widget_control_id Optional. Registered widget ID. Default false. + */ + function wp_dashboard_trigger_widget_control($widget_control_id = \false) + { + } + /** + * The RSS dashboard widget control. + * + * Sets up $args to be used as input to wp_widget_rss_form(). Handles POST data + * from RSS-type widgets. + * + * @since 2.5.0 + * + * @param string $widget_id + * @param array $form_inputs + */ + function wp_dashboard_rss_control($widget_id, $form_inputs = array()) + { + } + /** + * Renders the Events and News dashboard widget. + * + * @since 4.8.0 + */ + function wp_dashboard_events_news() + { + } + /** + * Prints the markup for the Community Events section of the Events and News Dashboard widget. + * + * @since 4.8.0 + */ + function wp_print_community_events_markup() + { + } + /** + * Renders the events templates for the Event and News widget. + * + * @since 4.8.0 + */ + function wp_print_community_events_templates() + { + } + /** + * 'WordPress Events and News' dashboard widget. + * + * @since 2.7.0 + * @since 4.8.0 Removed popular plugins feed. + */ + function wp_dashboard_primary() + { + } + /** + * Displays the WordPress events and news feeds. + * + * @since 3.8.0 + * @since 4.8.0 Removed popular plugins feed. + * + * @param string $widget_id Widget ID. + * @param array $feeds Array of RSS feeds. + */ + function wp_dashboard_primary_output($widget_id, $feeds) + { + } + /** + * Displays file upload quota on dashboard. + * + * Runs on the {@see 'activity_box_end'} hook in wp_dashboard_right_now(). + * + * @since 3.0.0 + * + * @return true|void True if not multisite, user can't upload files, or the space check option is disabled. + */ + function wp_dashboard_quota() + { + } + /** + * Displays the browser update nag. + * + * @since 3.2.0 + * @since 5.8.0 Added a special message for Internet Explorer users. + * + * @global bool $is_IE + */ + function wp_dashboard_browser_nag() + { + } + /** + * Adds an additional class to the browser nag if the current version is insecure. + * + * @since 3.2.0 + * + * @param string[] $classes Array of meta box classes. + * @return string[] Modified array of meta box classes. + */ + function dashboard_browser_nag_class($classes) + { + } + /** + * Checks if the user needs a browser update. + * + * @since 3.2.0 + * + * @return array|false Array of browser data on success, false on failure. + */ + function wp_check_browser_version() + { + } + /** + * Displays the PHP update nag. + * + * @since 5.1.0 + */ + function wp_dashboard_php_nag() + { + } + /** + * Adds an additional class to the PHP nag if the current version is insecure. + * + * @since 5.1.0 + * + * @param string[] $classes Array of meta box classes. + * @return string[] Modified array of meta box classes. + */ + function dashboard_php_nag_class($classes) + { + } + /** + * Displays the Site Health Status widget. + * + * @since 5.4.0 + */ + function wp_dashboard_site_health() + { + } + /** + * Empty function usable by plugins to output empty dashboard widget (to be populated later by JS). + * + * @since 2.5.0 + */ + function wp_dashboard_empty() + { + } + /** + * Displays a welcome panel to introduce users to WordPress. + * + * @since 3.3.0 + * @since 5.9.0 Send users to the Site Editor if the active theme is block-based. + */ + function wp_welcome_panel() + { + } + /** + * Deprecated admin functions from past WordPress versions. You shouldn't use these + * functions and look for the alternatives instead. The functions will be removed + * in a later version. + * + * @package WordPress + * @subpackage Deprecated + */ + /* + * Deprecated functions come here to die. + */ + /** + * @since 2.1.0 + * @deprecated 2.1.0 Use wp_editor() + * @see wp_editor() + */ + function tinymce_include() + { + } + /** + * Unused Admin function. + * + * @since 2.0.0 + * @deprecated 2.5.0 + * + */ + function documentation_link() + { + } + /** + * Calculates the new dimensions for a downsampled image. + * + * @since 2.0.0 + * @deprecated 3.0.0 Use wp_constrain_dimensions() + * @see wp_constrain_dimensions() + * + * @param int $width Current width of the image + * @param int $height Current height of the image + * @param int $wmax Maximum wanted width + * @param int $hmax Maximum wanted height + * @return array Shrunk dimensions (width, height). + */ + function wp_shrink_dimensions($width, $height, $wmax = 128, $hmax = 96) + { + } + /** + * Calculated the new dimensions for a downsampled image. + * + * @since 2.0.0 + * @deprecated 3.5.0 Use wp_constrain_dimensions() + * @see wp_constrain_dimensions() + * + * @param int $width Current width of the image + * @param int $height Current height of the image + * @return array Shrunk dimensions (width, height). + */ + function get_udims($width, $height) + { + } + /** + * Legacy function used to generate the categories checklist control. + * + * @since 0.71 + * @deprecated 2.6.0 Use wp_category_checklist() + * @see wp_category_checklist() + * + * @global int $post_ID + * + * @param int $default_category Unused. + * @param int $category_parent Unused. + * @param array $popular_ids Unused. + */ + function dropdown_categories($default_category = 0, $category_parent = 0, $popular_ids = array()) + { + } + /** + * Legacy function used to generate a link categories checklist control. + * + * @since 2.1.0 + * @deprecated 2.6.0 Use wp_link_category_checklist() + * @see wp_link_category_checklist() + * + * @global int $link_id + * + * @param int $default_link_category Unused. + */ + function dropdown_link_categories($default_link_category = 0) + { + } + /** + * Get the real filesystem path to a file to edit within the admin. + * + * @since 1.5.0 + * @deprecated 2.9.0 + * @uses WP_CONTENT_DIR Full filesystem path to the wp-content directory. + * + * @param string $file Filesystem path relative to the wp-content directory. + * @return string Full filesystem path to edit. + */ + function get_real_file_to_edit($file) + { + } + /** + * Legacy function used for generating a categories drop-down control. + * + * @since 1.2.0 + * @deprecated 3.0.0 Use wp_dropdown_categories() + * @see wp_dropdown_categories() + * + * @param int $current_cat Optional. ID of the current category. Default 0. + * @param int $current_parent Optional. Current parent category ID. Default 0. + * @param int $category_parent Optional. Parent ID to retrieve categories for. Default 0. + * @param int $level Optional. Number of levels deep to display. Default 0. + * @param array $categories Optional. Categories to include in the control. Default 0. + * @return void|false Void on success, false if no categories were found. + */ + function wp_dropdown_cats($current_cat = 0, $current_parent = 0, $category_parent = 0, $level = 0, $categories = 0) + { + } + /** + * Register a setting and its sanitization callback + * + * @since 2.7.0 + * @deprecated 3.0.0 Use register_setting() + * @see register_setting() + * + * @param string $option_group A settings group name. Should correspond to an allowed option key name. + * Default allowed option key names include 'general', 'discussion', 'media', + * 'reading', 'writing', and 'options'. + * @param string $option_name The name of an option to sanitize and save. + * @param callable $sanitize_callback Optional. A callback function that sanitizes the option's value. + */ + function add_option_update_handler($option_group, $option_name, $sanitize_callback = '') + { + } + /** + * Unregister a setting + * + * @since 2.7.0 + * @deprecated 3.0.0 Use unregister_setting() + * @see unregister_setting() + * + * @param string $option_group The settings group name used during registration. + * @param string $option_name The name of the option to unregister. + * @param callable $sanitize_callback Optional. Deprecated. + */ + function remove_option_update_handler($option_group, $option_name, $sanitize_callback = '') + { + } + /** + * Determines the language to use for CodePress syntax highlighting. + * + * @since 2.8.0 + * @deprecated 3.0.0 + * + * @param string $filename + **/ + function codepress_get_lang($filename) + { + } + /** + * Adds JavaScript required to make CodePress work on the theme/plugin file editors. + * + * @since 2.8.0 + * @deprecated 3.0.0 + **/ + function codepress_footer_js() + { + } + /** + * Determine whether to use CodePress. + * + * @since 2.8.0 + * @deprecated 3.0.0 + **/ + function use_codepress() + { + } + /** + * Get all user IDs. + * + * @deprecated 3.1.0 Use get_users() + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return array List of user IDs. + */ + function get_author_user_ids() + { + } + /** + * Gets author users who can edit posts. + * + * @deprecated 3.1.0 Use get_users() + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $user_id User ID. + * @return array|false List of editable authors. False if no editable users. + */ + function get_editable_authors($user_id) + { + } + /** + * Gets the IDs of any users who can edit posts. + * + * @deprecated 3.1.0 Use get_users() + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $user_id User ID. + * @param bool $exclude_zeros Optional. Whether to exclude zeroes. Default true. + * @return array Array of editable user IDs, empty array otherwise. + */ + function get_editable_user_ids($user_id, $exclude_zeros = \true, $post_type = 'post') + { + } + /** + * Gets all users who are not authors. + * + * @deprecated 3.1.0 Use get_users() + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function get_nonauthor_user_ids() + { + } + /** + * Retrieves editable posts from other users. + * + * @since 2.3.0 + * @deprecated 3.1.0 Use get_posts() + * @see get_posts() + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $user_id User ID to not retrieve posts from. + * @param string $type Optional. Post type to retrieve. Accepts 'draft', 'pending' or 'any' (all). + * Default 'any'. + * @return array List of posts from others. + */ + function get_others_unpublished_posts($user_id, $type = 'any') + { + } + /** + * Retrieve drafts from other users. + * + * @deprecated 3.1.0 Use get_posts() + * @see get_posts() + * + * @param int $user_id User ID. + * @return array List of drafts from other users. + */ + function get_others_drafts($user_id) + { + } + /** + * Retrieve pending review posts from other users. + * + * @deprecated 3.1.0 Use get_posts() + * @see get_posts() + * + * @param int $user_id User ID. + * @return array List of posts with pending review post type from other users. + */ + function get_others_pending($user_id) + { + } + /** + * Output the QuickPress dashboard widget. + * + * @since 3.0.0 + * @deprecated 3.2.0 Use wp_dashboard_quick_press() + * @see wp_dashboard_quick_press() + */ + function wp_dashboard_quick_press_output() + { + } + /** + * Outputs the TinyMCE editor. + * + * @since 2.7.0 + * @deprecated 3.3.0 Use wp_editor() + * @see wp_editor() + */ + function wp_tiny_mce($teeny = \false, $settings = \false) + { + } + /** + * Preloads TinyMCE dialogs. + * + * @deprecated 3.3.0 Use wp_editor() + * @see wp_editor() + */ + function wp_preload_dialogs() + { + } + /** + * Prints TinyMCE editor JS. + * + * @deprecated 3.3.0 Use wp_editor() + * @see wp_editor() + */ + function wp_print_editor_js() + { + } + /** + * Handles quicktags. + * + * @deprecated 3.3.0 Use wp_editor() + * @see wp_editor() + */ + function wp_quicktags() + { + } + /** + * Returns the screen layout options. + * + * @since 2.8.0 + * @deprecated 3.3.0 WP_Screen::render_screen_layout() + * @see WP_Screen::render_screen_layout() + */ + function screen_layout($screen) + { + } + /** + * Returns the screen's per-page options. + * + * @since 2.8.0 + * @deprecated 3.3.0 Use WP_Screen::render_per_page_options() + * @see WP_Screen::render_per_page_options() + */ + function screen_options($screen) + { + } + /** + * Renders the screen's help. + * + * @since 2.7.0 + * @deprecated 3.3.0 Use WP_Screen::render_screen_meta() + * @see WP_Screen::render_screen_meta() + */ + function screen_meta($screen) + { + } + /** + * Favorite actions were deprecated in version 3.2. Use the admin bar instead. + * + * @since 2.7.0 + * @deprecated 3.2.0 Use WP_Admin_Bar + * @see WP_Admin_Bar + */ + function favorite_actions() + { + } + /** + * Handles uploading an image. + * + * @deprecated 3.3.0 Use wp_media_upload_handler() + * @see wp_media_upload_handler() + * + * @return null|string + */ + function media_upload_image() + { + } + /** + * Handles uploading an audio file. + * + * @deprecated 3.3.0 Use wp_media_upload_handler() + * @see wp_media_upload_handler() + * + * @return null|string + */ + function media_upload_audio() + { + } + /** + * Handles uploading a video file. + * + * @deprecated 3.3.0 Use wp_media_upload_handler() + * @see wp_media_upload_handler() + * + * @return null|string + */ + function media_upload_video() + { + } + /** + * Handles uploading a generic file. + * + * @deprecated 3.3.0 Use wp_media_upload_handler() + * @see wp_media_upload_handler() + * + * @return null|string + */ + function media_upload_file() + { + } + /** + * Handles retrieving the insert-from-URL form for an image. + * + * @deprecated 3.3.0 Use wp_media_insert_url_form() + * @see wp_media_insert_url_form() + * + * @return string + */ + function type_url_form_image() + { + } + /** + * Handles retrieving the insert-from-URL form for an audio file. + * + * @deprecated 3.3.0 Use wp_media_insert_url_form() + * @see wp_media_insert_url_form() + * + * @return string + */ + function type_url_form_audio() + { + } + /** + * Handles retrieving the insert-from-URL form for a video file. + * + * @deprecated 3.3.0 Use wp_media_insert_url_form() + * @see wp_media_insert_url_form() + * + * @return string + */ + function type_url_form_video() + { + } + /** + * Handles retrieving the insert-from-URL form for a generic file. + * + * @deprecated 3.3.0 Use wp_media_insert_url_form() + * @see wp_media_insert_url_form() + * + * @return string + */ + function type_url_form_file() + { + } + /** + * Add contextual help text for a page. + * + * Creates an 'Overview' help tab. + * + * @since 2.7.0 + * @deprecated 3.3.0 Use WP_Screen::add_help_tab() + * @see WP_Screen::add_help_tab() + * + * @param string $screen The handle for the screen to add help to. This is usually + * the hook name returned by the `add_*_page()` functions. + * @param string $help The content of an 'Overview' help tab. + */ + function add_contextual_help($screen, $help) + { + } + /** + * Get the allowed themes for the current site. + * + * @since 3.0.0 + * @deprecated 3.4.0 Use wp_get_themes() + * @see wp_get_themes() + * + * @return WP_Theme[] Array of WP_Theme objects keyed by their name. + */ + function get_allowed_themes() + { + } + /** + * Retrieves a list of broken themes. + * + * @since 1.5.0 + * @deprecated 3.4.0 Use wp_get_themes() + * @see wp_get_themes() + * + * @return array + */ + function get_broken_themes() + { + } + /** + * Retrieves information on the current active theme. + * + * @since 2.0.0 + * @deprecated 3.4.0 Use wp_get_theme() + * @see wp_get_theme() + * + * @return WP_Theme + */ + function current_theme_info() + { + } + /** + * This was once used to display an 'Insert into Post' button. + * + * Now it is deprecated and stubbed. + * + * @deprecated 3.5.0 + */ + function _insert_into_post_button($type) + { + } + /** + * This was once used to display a media button. + * + * Now it is deprecated and stubbed. + * + * @deprecated 3.5.0 + */ + function _media_button($title, $icon, $type, $id) + { + } + /** + * Gets an existing post and format it for editing. + * + * @since 2.0.0 + * @deprecated 3.5.0 Use get_post() + * @see get_post() + * + * @param int $id + * @return WP_Post + */ + function get_post_to_edit($id) + { + } + /** + * Gets the default page information to use. + * + * @since 2.5.0 + * @deprecated 3.5.0 Use get_default_post_to_edit() + * @see get_default_post_to_edit() + * + * @return WP_Post Post object containing all the default post data as attributes + */ + function get_default_page_to_edit() + { + } + /** + * This was once used to create a thumbnail from an Image given a maximum side size. + * + * @since 1.2.0 + * @deprecated 3.5.0 Use image_resize() + * @see image_resize() + * + * @param mixed $file Filename of the original image, Or attachment ID. + * @param int $max_side Maximum length of a single side for the thumbnail. + * @param mixed $deprecated Never used. + * @return string Thumbnail path on success, Error string on failure. + */ + function wp_create_thumbnail($file, $max_side, $deprecated = '') + { + } + /** + * This was once used to display a meta box for the nav menu theme locations. + * + * Deprecated in favor of a 'Manage Locations' tab added to nav menus management screen. + * + * @since 3.0.0 + * @deprecated 3.6.0 + */ + function wp_nav_menu_locations_meta_box() + { + } + /** + * This was once used to kick-off the Core Updater. + * + * Deprecated in favor of instantating a Core_Upgrader instance directly, + * and calling the 'upgrade' method. + * + * @since 2.7.0 + * @deprecated 3.7.0 Use Core_Upgrader + * @see Core_Upgrader + */ + function wp_update_core($current, $feedback = '') + { + } + /** + * This was once used to kick-off the Plugin Updater. + * + * Deprecated in favor of instantating a Plugin_Upgrader instance directly, + * and calling the 'upgrade' method. + * Unused since 2.8.0. + * + * @since 2.5.0 + * @deprecated 3.7.0 Use Plugin_Upgrader + * @see Plugin_Upgrader + */ + function wp_update_plugin($plugin, $feedback = '') + { + } + /** + * This was once used to kick-off the Theme Updater. + * + * Deprecated in favor of instantiating a Theme_Upgrader instance directly, + * and calling the 'upgrade' method. + * Unused since 2.8.0. + * + * @since 2.7.0 + * @deprecated 3.7.0 Use Theme_Upgrader + * @see Theme_Upgrader + */ + function wp_update_theme($theme, $feedback = '') + { + } + /** + * This was once used to display attachment links. Now it is deprecated and stubbed. + * + * @since 2.0.0 + * @deprecated 3.7.0 + * + * @param int|bool $id + */ + function the_attachment_links($id = \false) + { + } + /** + * Displays a screen icon. + * + * @since 2.7.0 + * @deprecated 3.8.0 + */ + function screen_icon() + { + } + /** + * Retrieves the screen icon (no longer used in 3.8+). + * + * @since 3.2.0 + * @deprecated 3.8.0 + * + * @return string An HTML comment explaining that icons are no longer used. + */ + function get_screen_icon() + { + } + /** + * Deprecated dashboard widget controls. + * + * @since 2.5.0 + * @deprecated 3.8.0 + */ + function wp_dashboard_incoming_links_output() + { + } + /** + * Deprecated dashboard secondary output. + * + * @deprecated 3.8.0 + */ + function wp_dashboard_secondary_output() + { + } + /** + * Deprecated dashboard widget controls. + * + * @since 2.7.0 + * @deprecated 3.8.0 + */ + function wp_dashboard_incoming_links() + { + } + /** + * Deprecated dashboard incoming links control. + * + * @deprecated 3.8.0 + */ + function wp_dashboard_incoming_links_control() + { + } + /** + * Deprecated dashboard plugins control. + * + * @deprecated 3.8.0 + */ + function wp_dashboard_plugins() + { + } + /** + * Deprecated dashboard primary control. + * + * @deprecated 3.8.0 + */ + function wp_dashboard_primary_control() + { + } + /** + * Deprecated dashboard recent comments control. + * + * @deprecated 3.8.0 + */ + function wp_dashboard_recent_comments_control() + { + } + /** + * Deprecated dashboard secondary section. + * + * @deprecated 3.8.0 + */ + function wp_dashboard_secondary() + { + } + /** + * Deprecated dashboard secondary control. + * + * @deprecated 3.8.0 + */ + function wp_dashboard_secondary_control() + { + } + /** + * Display plugins text for the WordPress news widget. + * + * @since 2.5.0 + * @deprecated 4.8.0 + * + * @param string $rss The RSS feed URL. + * @param array $args Array of arguments for this RSS feed. + */ + function wp_dashboard_plugins_output($rss, $args = array()) + { + } + /** + * This was once used to move child posts to a new parent. + * + * @since 2.3.0 + * @deprecated 3.9.0 + * @access private + * + * @param int $old_ID + * @param int $new_ID + */ + function _relocate_children($old_ID, $new_ID) + { + } + /** + * Add a top-level menu page in the 'objects' section. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 2.7.0 + * + * @deprecated 4.5.0 Use add_menu_page() + * @see add_menu_page() + * @global int $_wp_last_object_menu + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param string $icon_url Optional. The URL to the icon to be used for this menu. + * @return string The resulting page's hook_suffix. + */ + function add_object_page($page_title, $menu_title, $capability, $menu_slug, $callback = '', $icon_url = '') + { + } + /** + * Add a top-level menu page in the 'utility' section. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 2.7.0 + * + * @deprecated 4.5.0 Use add_menu_page() + * @see add_menu_page() + * @global int $_wp_last_utility_menu + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param string $icon_url Optional. The URL to the icon to be used for this menu. + * @return string The resulting page's hook_suffix. + */ + function add_utility_page($page_title, $menu_title, $capability, $menu_slug, $callback = '', $icon_url = '') + { + } + /** + * Disables autocomplete on the 'post' form (Add/Edit Post screens) for WebKit browsers, + * as they disregard the autocomplete setting on the editor textarea. That can break the editor + * when the user navigates to it with the browser's Back button. See #28037 + * + * Replaced with wp_page_reload_on_back_button_js() that also fixes this problem. + * + * @since 4.0.0 + * @deprecated 4.6.0 + * + * @link https://core.trac.wordpress.org/ticket/35852 + * + * @global bool $is_safari + * @global bool $is_chrome + */ + function post_form_autocomplete_off() + { + } + /** + * Display JavaScript on the page. + * + * @since 3.5.0 + * @deprecated 4.9.0 + */ + function options_permalink_add_js() + { + } + /** + * Was used to add options for the privacy requests screens before they were separate files. + * + * @since 4.9.8 + * @access private + * @deprecated 5.3.0 + */ + function _wp_privacy_requests_screen_options() + { + } + /** + * Was used to filter input from media_upload_form_handler() and to assign a default + * post_title from the file name if none supplied. + * + * @since 2.5.0 + * @deprecated 6.0.0 + * + * @param array $post The WP_Post attachment object converted to an array. + * @param array $attachment An array of attachment metadata. + * @return array Attachment post object converted to an array. + */ + function image_attachment_fields_to_save($post, $attachment) + { + } + /** + * Generates the WXR export file for download. + * + * Default behavior is to export all content, however, note that post content will only + * be exported for post types with the `can_export` argument enabled. Any posts with the + * 'auto-draft' status will be skipped. + * + * @since 2.1.0 + * @since 5.7.0 Added the `post_modified` and `post_modified_gmt` fields to the export file. + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global WP_Post $post Global post object. + * + * @param array $args { + * Optional. Arguments for generating the WXR export file for download. Default empty array. + * + * @type string $content Type of content to export. If set, only the post content of this post type + * will be exported. Accepts 'all', 'post', 'page', 'attachment', or a defined + * custom post. If an invalid custom post type is supplied, every post type for + * which `can_export` is enabled will be exported instead. If a valid custom post + * type is supplied but `can_export` is disabled, then 'posts' will be exported + * instead. When 'all' is supplied, only post types with `can_export` enabled will + * be exported. Default 'all'. + * @type string $author Author to export content for. Only used when `$content` is 'post', 'page', or + * 'attachment'. Accepts false (all) or a specific author ID. Default false (all). + * @type string $category Category (slug) to export content for. Used only when `$content` is 'post'. If + * set, only post content assigned to `$category` will be exported. Accepts false + * or a specific category slug. Default is false (all categories). + * @type string $start_date Start date to export content from. Expected date format is 'Y-m-d'. Used only + * when `$content` is 'post', 'page' or 'attachment'. Default false (since the + * beginning of time). + * @type string $end_date End date to export content to. Expected date format is 'Y-m-d'. Used only when + * `$content` is 'post', 'page' or 'attachment'. Default false (latest publish date). + * @type string $status Post status to export posts for. Used only when `$content` is 'post' or 'page'. + * Accepts false (all statuses except 'auto-draft'), or a specific status, i.e. + * 'publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit', or + * 'trash'. Default false (all statuses except 'auto-draft'). + * } + * @phpstan-param array{ + * content?: string, + * author?: string, + * category?: string, + * start_date?: string, + * end_date?: string, + * status?: string, + * } $args + */ + function export_wp($args = array()) + { + } + /** + * Gets the description for standard WordPress theme files. + * + * @since 1.5.0 + * + * @global array $wp_file_descriptions Theme file descriptions. + * @global array $allowed_files List of allowed files. + * + * @param string $file Filesystem path or filename. + * @return string Description of file from $wp_file_descriptions or basename of $file if description doesn't exist. + * Appends 'Page Template' to basename of $file if the file is a page template. + */ + function get_file_description($file) + { + } + /** + * Gets the absolute filesystem path to the root of the WordPress installation. + * + * @since 1.5.0 + * + * @return string Full filesystem path to the root of the WordPress installation. + */ + function get_home_path() + { + } + /** + * Returns a listing of all files in the specified folder and all subdirectories up to 100 levels deep. + * + * The depth of the recursiveness can be controlled by the $levels param. + * + * @since 2.6.0 + * @since 4.9.0 Added the `$exclusions` parameter. + * + * @param string $folder Optional. Full path to folder. Default empty. + * @param int $levels Optional. Levels of folders to follow, Default 100 (PHP Loop limit). + * @param string[] $exclusions Optional. List of folders and files to skip. + * @return string[]|false Array of files on success, false on failure. + */ + function list_files($folder = '', $levels = 100, $exclusions = array()) + { + } + /** + * Gets the list of file extensions that are editable in plugins. + * + * @since 4.9.0 + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @return string[] Array of editable file extensions. + */ + function wp_get_plugin_file_editable_extensions($plugin) + { + } + /** + * Gets the list of file extensions that are editable for a given theme. + * + * @since 4.9.0 + * + * @param WP_Theme $theme Theme object. + * @return string[] Array of editable file extensions. + */ + function wp_get_theme_file_editable_extensions($theme) + { + } + /** + * Prints file editor templates (for plugins and themes). + * + * @since 4.9.0 + */ + function wp_print_file_editor_templates() + { + } + /** + * Attempts to edit a file for a theme or plugin. + * + * When editing a PHP file, loopback requests will be made to the admin and the homepage + * to attempt to see if there is a fatal error introduced. If so, the PHP change will be + * reverted. + * + * @since 4.9.0 + * + * @param string[] $args { + * Args. Note that all of the arg values are already unslashed. They are, however, + * coming straight from `$_POST` and are not validated or sanitized in any way. + * + * @type string $file Relative path to file. + * @type string $plugin Path to the plugin file relative to the plugins directory. + * @type string $theme Theme being edited. + * @type string $newcontent New content for the file. + * @type string $nonce Nonce. + * } + * @return true|WP_Error True on success or `WP_Error` on failure. + * @phpstan-param array{ + * file?: string, + * plugin?: string, + * theme?: string, + * newcontent?: string, + * nonce?: string, + * } $args + */ + function wp_edit_theme_plugin_file($args) + { + } + /** + * Returns a filename of a temporary unique file. + * + * Please note that the calling function must unlink() this itself. + * + * The filename is based off the passed parameter or defaults to the current unix timestamp, + * while the directory can either be passed as well, or by leaving it blank, default to a writable + * temporary directory. + * + * @since 2.6.0 + * + * @param string $filename Optional. Filename to base the Unique file off. Default empty. + * @param string $dir Optional. Directory to store the file in. Default empty. + * @return string A writable filename. + */ + function wp_tempnam($filename = '', $dir = '') + { + } + /** + * Makes sure that the file that was requested to be edited is allowed to be edited. + * + * Function will die if you are not allowed to edit the file. + * + * @since 1.5.0 + * + * @param string $file File the user is attempting to edit. + * @param string[] $allowed_files Optional. Array of allowed files to edit. + * `$file` must match an entry exactly. + * @return string|void Returns the file name on success, dies on failure. + */ + function validate_file_to_edit($file, $allowed_files = array()) + { + } + /** + * Handles PHP uploads in WordPress. + * + * Sanitizes file names, checks extensions for mime type, and moves the file + * to the appropriate directory within the uploads directory. + * + * @access private + * @since 4.0.0 + * + * @see wp_handle_upload_error + * + * @param array $file { + * Reference to a single element from `$_FILES`. Call the function once for each uploaded file. + * + * @type string $name The original name of the file on the client machine. + * @type string $type The mime type of the file, if the browser provided this information. + * @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server. + * @type int $size The size, in bytes, of the uploaded file. + * @type int $error The error code associated with this file upload. + * } + * @param array|false $overrides { + * An array of override parameters for this file, or boolean false if none are provided. + * + * @type callable $upload_error_handler Function to call when there is an error during the upload process. + * @see wp_handle_upload_error(). + * @type callable $unique_filename_callback Function to call when determining a unique file name for the file. + * @see wp_unique_filename(). + * @type string[] $upload_error_strings The strings that describe the error indicated in + * `$_FILES[{form field}]['error']`. + * @type bool $test_form Whether to test that the `$_POST['action']` parameter is as expected. + * @type bool $test_size Whether to test that the file size is greater than zero bytes. + * @type bool $test_type Whether to test that the mime type of the file is as expected. + * @type string[] $mimes Array of allowed mime types keyed by their file extension regex. + * } + * @param string $time Time formatted in 'yyyy/mm'. + * @param string $action Expected value for `$_POST['action']`. + * @return array { + * On success, returns an associative array of file attributes. + * On failure, returns `$overrides['upload_error_handler']( &$file, $message )` + * or `array( 'error' => $message )`. + * + * @type string $file Filename of the newly-uploaded file. + * @type string $url URL of the newly-uploaded file. + * @type string $type Mime type of the newly-uploaded file. + * } + * @phpstan-param array{ + * name?: string, + * type?: string, + * tmp_name?: string, + * size?: int, + * error?: int, + * } $file + * @phpstan-param false|array{ + * upload_error_handler?: callable, + * unique_filename_callback?: callable, + * upload_error_strings?: string[], + * test_form?: bool, + * test_size?: bool, + * test_type?: bool, + * mimes?: string[], + * } $overrides + * @phpstan-return array{ + * file: string, + * url: string, + * type: string, + * } + */ + function _wp_handle_upload(&$file, $overrides, $time, $action) + { + } + /** + * Wrapper for _wp_handle_upload(). + * + * Passes the {@see 'wp_handle_upload'} action. + * + * @since 2.0.0 + * + * @see _wp_handle_upload() + * + * @param array $file Reference to a single element of `$_FILES`. + * Call the function once for each uploaded file. + * See _wp_handle_upload() for accepted values. + * @param array|false $overrides Optional. An associative array of names => values + * to override default variables. Default false. + * See _wp_handle_upload() for accepted values. + * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null. + * @return array See _wp_handle_upload() for return value. + * @phpstan-param array{ + * name?: string, + * type?: string, + * tmp_name?: string, + * size?: int, + * error?: int, + * } $file See _wp_handle_upload() + * @phpstan-param false|array{ + * upload_error_handler?: callable, + * unique_filename_callback?: callable, + * upload_error_strings?: string[], + * test_form?: bool, + * test_size?: bool, + * test_type?: bool, + * mimes?: string[], + * } $overrides See _wp_handle_upload() + */ + function wp_handle_upload(&$file, $overrides = \false, $time = \null) + { + } + /** + * Wrapper for _wp_handle_upload(). + * + * Passes the {@see 'wp_handle_sideload'} action. + * + * @since 2.6.0 + * + * @see _wp_handle_upload() + * + * @param array $file Reference to a single element of `$_FILES`. + * Call the function once for each uploaded file. + * See _wp_handle_upload() for accepted values. + * @param array|false $overrides Optional. An associative array of names => values + * to override default variables. Default false. + * See _wp_handle_upload() for accepted values. + * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null. + * @return array See _wp_handle_upload() for return value. + * @phpstan-param array{ + * name?: string, + * type?: string, + * tmp_name?: string, + * size?: int, + * error?: int, + * } $file See _wp_handle_upload() + * @phpstan-param false|array{ + * upload_error_handler?: callable, + * unique_filename_callback?: callable, + * upload_error_strings?: string[], + * test_form?: bool, + * test_size?: bool, + * test_type?: bool, + * mimes?: string[], + * } $overrides See _wp_handle_upload() + */ + function wp_handle_sideload(&$file, $overrides = \false, $time = \null) + { + } + /** + * Downloads a URL to a local temporary file using the WordPress HTTP API. + * + * Please note that the calling function must unlink() the file. + * + * @since 2.5.0 + * @since 5.2.0 Signature Verification with SoftFail was added. + * @since 5.9.0 Support for Content-Disposition filename was added. + * + * @param string $url The URL of the file to download. + * @param int $timeout The timeout for the request to download the file. + * Default 300 seconds. + * @param bool $signature_verification Whether to perform Signature Verification. + * Default false. + * @return string|WP_Error Filename on success, WP_Error on failure. + */ + function download_url($url, $timeout = 300, $signature_verification = \false) + { + } + /** + * Calculates and compares the MD5 of a file to its expected value. + * + * @since 3.7.0 + * + * @param string $filename The filename to check the MD5 of. + * @param string $expected_md5 The expected MD5 of the file, either a base64-encoded raw md5, + * or a hex-encoded md5. + * @return bool|WP_Error True on success, false when the MD5 format is unknown/unexpected, + * WP_Error on failure. + */ + function verify_file_md5($filename, $expected_md5) + { + } + /** + * Verifies the contents of a file against its ED25519 signature. + * + * @since 5.2.0 + * + * @param string $filename The file to validate. + * @param string|array $signatures A Signature provided for the file. + * @param string|false $filename_for_errors Optional. A friendly filename for errors. + * @return bool|WP_Error True on success, false if verification not attempted, + * or WP_Error describing an error condition. + */ + function verify_file_signature($filename, $signatures, $filename_for_errors = \false) + { + } + /** + * Retrieves the list of signing keys trusted by WordPress. + * + * @since 5.2.0 + * + * @return string[] Array of base64-encoded signing keys. + */ + function wp_trusted_keys() + { + } + /** + * Unzips a specified ZIP file to a location on the filesystem via the WordPress + * Filesystem Abstraction. + * + * Assumes that WP_Filesystem() has already been called and set up. Does not extract + * a root-level __MACOSX directory, if present. + * + * Attempts to increase the PHP memory limit to 256M before uncompressing. However, + * the most memory required shouldn't be much larger than the archive itself. + * + * @since 2.5.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param string $file Full path and filename of ZIP archive. + * @param string $to Full path on the filesystem to extract archive to. + * @return true|WP_Error True on success, WP_Error on failure. + */ + function unzip_file($file, $to) + { + } + /** + * Attempts to unzip an archive using the ZipArchive class. + * + * This function should not be called directly, use `unzip_file()` instead. + * + * Assumes that WP_Filesystem() has already been called and set up. + * + * @since 3.0.0 + * @access private + * + * @see unzip_file() + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param string $file Full path and filename of ZIP archive. + * @param string $to Full path on the filesystem to extract archive to. + * @param string[] $needed_dirs A partial list of required folders needed to be created. + * @return true|WP_Error True on success, WP_Error on failure. + */ + function _unzip_file_ziparchive($file, $to, $needed_dirs = array()) + { + } + /** + * Attempts to unzip an archive using the PclZip library. + * + * This function should not be called directly, use `unzip_file()` instead. + * + * Assumes that WP_Filesystem() has already been called and set up. + * + * @since 3.0.0 + * @access private + * + * @see unzip_file() + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param string $file Full path and filename of ZIP archive. + * @param string $to Full path on the filesystem to extract archive to. + * @param string[] $needed_dirs A partial list of required folders needed to be created. + * @return true|WP_Error True on success, WP_Error on failure. + */ + function _unzip_file_pclzip($file, $to, $needed_dirs = array()) + { + } + /** + * Copies a directory from one location to another via the WordPress Filesystem + * Abstraction. + * + * Assumes that WP_Filesystem() has already been called and setup. + * + * @since 2.5.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param string $from Source directory. + * @param string $to Destination directory. + * @param string[] $skip_list An array of files/folders to skip copying. + * @return true|WP_Error True on success, WP_Error on failure. + */ + function copy_dir($from, $to, $skip_list = array()) + { + } + /** + * Initializes and connects the WordPress Filesystem Abstraction classes. + * + * This function will include the chosen transport and attempt connecting. + * + * Plugins may add extra transports, And force WordPress to use them by returning + * the filename via the {@see 'filesystem_method_file'} filter. + * + * @since 2.5.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param array|false $args Optional. Connection args, These are passed + * directly to the `WP_Filesystem_*()` classes. + * Default false. + * @param string|false $context Optional. Context for get_filesystem_method(). + * Default false. + * @param bool $allow_relaxed_file_ownership Optional. Whether to allow Group/World writable. + * Default false. + * @return bool|null True on success, false on failure, + * null if the filesystem method class file does not exist. + */ + function WP_Filesystem($args = \false, $context = \false, $allow_relaxed_file_ownership = \false) + { + } + /** + * Determines which method to use for reading, writing, modifying, or deleting + * files on the filesystem. + * + * The priority of the transports are: Direct, SSH2, FTP PHP Extension, FTP Sockets + * (Via Sockets class, or `fsockopen()`). Valid values for these are: 'direct', 'ssh2', + * 'ftpext' or 'ftpsockets'. + * + * The return value can be overridden by defining the `FS_METHOD` constant in `wp-config.php`, + * or filtering via {@see 'filesystem_method'}. + * + * @link https://wordpress.org/support/article/editing-wp-config-php/#wordpress-upgrade-constants + * + * Plugins may define a custom transport handler, See WP_Filesystem(). + * + * @since 2.5.0 + * + * @global callable $_wp_filesystem_direct_method + * + * @param array $args Optional. Connection details. Default empty array. + * @param string $context Optional. Full path to the directory that is tested + * for being writable. Default empty. + * @param bool $allow_relaxed_file_ownership Optional. Whether to allow Group/World writable. + * Default false. + * @return string The transport to use, see description for valid return values. + */ + function get_filesystem_method($args = array(), $context = '', $allow_relaxed_file_ownership = \false) + { + } + /** + * Displays a form to the user to request for their FTP/SSH details in order + * to connect to the filesystem. + * + * All chosen/entered details are saved, excluding the password. + * + * Hostnames may be in the form of hostname:portnumber (eg: wordpress.org:2467) + * to specify an alternate FTP/SSH port. + * + * Plugins may override this form by returning true|false via the {@see 'request_filesystem_credentials'} filter. + * + * @since 2.5.0 + * @since 4.6.0 The `$context` parameter default changed from `false` to an empty string. + * + * @global string $pagenow The filename of the current screen. + * + * @param string $form_post The URL to post the form to. + * @param string $type Optional. Chosen type of filesystem. Default empty. + * @param bool|WP_Error $error Optional. Whether the current request has failed + * to connect, or an error object. Default false. + * @param string $context Optional. Full path to the directory that is tested + * for being writable. Default empty. + * @param array $extra_fields Optional. Extra `POST` fields to be checked + * for inclusion in the post. Default null. + * @param bool $allow_relaxed_file_ownership Optional. Whether to allow Group/World writable. + * Default false. + * @return bool|array True if no filesystem credentials are required, + * false if they are required but have not been provided, + * array of credentials if they are required and have been provided. + */ + function request_filesystem_credentials($form_post, $type = '', $error = \false, $context = '', $extra_fields = \null, $allow_relaxed_file_ownership = \false) + { + } + /** + * Prints the filesystem credentials modal when needed. + * + * @since 4.2.0 + */ + function wp_print_request_filesystem_credentials_modal() + { + } + /** + * Attempts to clear the opcode cache for an individual PHP file. + * + * This function can be called safely without having to check the file extension + * or availability of the OPcache extension. + * + * Whether or not invalidation is possible is cached to improve performance. + * + * @since 5.5.0 + * + * @link https://www.php.net/manual/en/function.opcache-invalidate.php + * + * @param string $filepath Path to the file, including extension, for which the opcode cache is to be cleared. + * @param bool $force Invalidate even if the modification time is not newer than the file in cache. + * Default false. + * @return bool True if opcache was invalidated for `$filepath`, or there was nothing to invalidate. + * False if opcache invalidation is not available, or is disabled via filter. + */ + function wp_opcache_invalidate($filepath, $force = \false) + { + } + /** + * WordPress Image Editor + * + * @package WordPress + * @subpackage Administration + */ + /** + * Loads the WP image-editing interface. + * + * @since 2.9.0 + * + * @param int $post_id Attachment post ID. + * @param false|object $msg Optional. Message to display for image editor updates or errors. + * Default false. + */ + function wp_image_editor($post_id, $msg = \false) + { + } + /** + * Streams image in WP_Image_Editor to browser. + * + * @since 2.9.0 + * + * @param WP_Image_Editor $image The image editor instance. + * @param string $mime_type The mime type of the image. + * @param int $attachment_id The image's attachment post ID. + * @return bool True on success, false on failure. + */ + function wp_stream_image($image, $mime_type, $attachment_id) + { + } + /** + * Saves image to file. + * + * @since 2.9.0 + * @since 3.5.0 The `$image` parameter expects a `WP_Image_Editor` instance. + * @since 6.0.0 The `$filesize` value was added to the returned array. + * + * @param string $filename Name of the file to be saved. + * @param WP_Image_Editor $image The image editor instance. + * @param string $mime_type The mime type of the image. + * @param int $post_id Attachment post ID. + * @return array|WP_Error|bool { + * Array on success or WP_Error if the file failed to save. + * When called with a deprecated value for the `$image` parameter, + * i.e. a non-`WP_Image_Editor` image resource or `GdImage` instance, + * the function will return true on success, false on failure. + * + * @type string $path Path to the image file. + * @type string $file Name of the image file. + * @type int $width Image width. + * @type int $height Image height. + * @type string $mime-type The mime type of the image. + * @type int $filesize File size of the image. + * } + * @phpstan-return \WP_Error|bool|array{ + * path: string, + * file: string, + * width: int, + * height: int, + * mime-type: string, + * filesize: int, + * } + */ + function wp_save_image_file($filename, $image, $mime_type, $post_id) + { + } + /** + * Image preview ratio. Internal use only. + * + * @since 2.9.0 + * + * @ignore + * @param int $w Image width in pixels. + * @param int $h Image height in pixels. + * @return float|int Image preview ratio. + */ + function _image_get_preview_ratio($w, $h) + { + } + /** + * Returns an image resource. Internal use only. + * + * @since 2.9.0 + * @deprecated 3.5.0 Use WP_Image_Editor::rotate() + * @see WP_Image_Editor::rotate() + * + * @ignore + * @param resource|GdImage $img Image resource. + * @param float|int $angle Image rotation angle, in degrees. + * @return resource|GdImage|false GD image resource or GdImage instance, false otherwise. + */ + function _rotate_image_resource($img, $angle) + { + } + /** + * Flips an image resource. Internal use only. + * + * @since 2.9.0 + * @deprecated 3.5.0 Use WP_Image_Editor::flip() + * @see WP_Image_Editor::flip() + * + * @ignore + * @param resource|GdImage $img Image resource or GdImage instance. + * @param bool $horz Whether to flip horizontally. + * @param bool $vert Whether to flip vertically. + * @return resource|GdImage (maybe) flipped image resource or GdImage instance. + */ + function _flip_image_resource($img, $horz, $vert) + { + } + /** + * Crops an image resource. Internal use only. + * + * @since 2.9.0 + * + * @ignore + * @param resource|GdImage $img Image resource or GdImage instance. + * @param float $x Source point x-coordinate. + * @param float $y Source point y-coordinate. + * @param float $w Source width. + * @param float $h Source height. + * @return resource|GdImage (maybe) cropped image resource or GdImage instance. + */ + function _crop_image_resource($img, $x, $y, $w, $h) + { + } + /** + * Performs group of changes on Editor specified. + * + * @since 2.9.0 + * + * @param WP_Image_Editor $image WP_Image_Editor instance. + * @param array $changes Array of change operations. + * @return WP_Image_Editor WP_Image_Editor instance with changes applied. + */ + function image_edit_apply_changes($image, $changes) + { + } + /** + * Streams image in post to browser, along with enqueued changes + * in `$_REQUEST['history']`. + * + * @since 2.9.0 + * + * @param int $post_id Attachment post ID. + * @return bool True on success, false on failure. + */ + function stream_preview_image($post_id) + { + } + /** + * Restores the metadata for a given attachment. + * + * @since 2.9.0 + * + * @param int $post_id Attachment post ID. + * @return stdClass Image restoration message object. + */ + function wp_restore_image($post_id) + { + } + /** + * Saves image to post, along with enqueued changes + * in `$_REQUEST['history']`. + * + * @since 2.9.0 + * + * @param int $post_id Attachment post ID. + * @return stdClass + */ + function wp_save_image($post_id) + { + } + /** + * File contains all the administration image manipulation functions. + * + * @package WordPress + * @subpackage Administration + */ + /** + * Crops an image to a given size. + * + * @since 2.1.0 + * + * @param string|int $src The source file or Attachment ID. + * @param int $src_x The start x position to crop from. + * @param int $src_y The start y position to crop from. + * @param int $src_w The width to crop. + * @param int $src_h The height to crop. + * @param int $dst_w The destination width. + * @param int $dst_h The destination height. + * @param bool|false $src_abs Optional. If the source crop points are absolute. + * @param string|false $dst_file Optional. The destination file to write to. + * @return string|WP_Error New filepath on success, WP_Error on failure. + */ + function wp_crop_image($src, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs = \false, $dst_file = \false) + { + } + /** + * Compare the existing image sub-sizes (as saved in the attachment meta) + * to the currently registered image sub-sizes, and return the difference. + * + * Registered sub-sizes that are larger than the image are skipped. + * + * @since 5.3.0 + * + * @param int $attachment_id The image attachment post ID. + * @return array[] Associative array of arrays of image sub-size information for + * missing image sizes, keyed by image size name. + */ + function wp_get_missing_image_subsizes($attachment_id) + { + } + /** + * If any of the currently registered image sub-sizes are missing, + * create them and update the image meta data. + * + * @since 5.3.0 + * + * @param int $attachment_id The image attachment post ID. + * @return array|WP_Error The updated image meta data array or WP_Error object + * if both the image meta and the attached file are missing. + */ + function wp_update_image_subsizes($attachment_id) + { + } + /** + * Updates the attached file and image meta data when the original image was edited. + * + * @since 5.3.0 + * @since 6.0.0 The `$filesize` value was added to the returned array. + * @access private + * + * @param array $saved_data The data returned from WP_Image_Editor after successfully saving an image. + * @param string $original_file Path to the original file. + * @param array $image_meta The image meta data. + * @param int $attachment_id The attachment post ID. + * @return array The updated image meta data. + */ + function _wp_image_meta_replace_original($saved_data, $original_file, $image_meta, $attachment_id) + { + } + /** + * Creates image sub-sizes, adds the new data to the image meta `sizes` array, and updates the image metadata. + * + * Intended for use after an image is uploaded. Saves/updates the image metadata after each + * sub-size is created. If there was an error, it is added to the returned image metadata array. + * + * @since 5.3.0 + * + * @param string $file Full path to the image file. + * @param int $attachment_id Attachment ID to process. + * @return array The image attachment meta data. + */ + function wp_create_image_subsizes($file, $attachment_id) + { + } + /** + * Low-level function to create image sub-sizes. + * + * Updates the image meta after each sub-size is created. + * Errors are stored in the returned image metadata array. + * + * @since 5.3.0 + * @access private + * + * @param array $new_sizes Array defining what sizes to create. + * @param string $file Full path to the image file. + * @param array $image_meta The attachment meta data array. + * @param int $attachment_id Attachment ID to process. + * @return array The attachment meta data with updated `sizes` array. Includes an array of errors encountered while resizing. + */ + function _wp_make_subsizes($new_sizes, $file, $image_meta, $attachment_id) + { + } + /** + * Generates attachment meta data and create image sub-sizes for images. + * + * @since 2.1.0 + * @since 6.0.0 The `$filesize` value was added to the returned array. + * + * @param int $attachment_id Attachment ID to process. + * @param string $file Filepath of the attached image. + * @return array Metadata for attachment. + */ + function wp_generate_attachment_metadata($attachment_id, $file) + { + } + /** + * Converts a fraction string to a decimal. + * + * @since 2.5.0 + * + * @param string $str Fraction string. + * @return int|float Returns calculated fraction or integer 0 on invalid input. + */ + function wp_exif_frac2dec($str) + { + } + /** + * Converts the exif date format to a unix timestamp. + * + * @since 2.5.0 + * + * @param string $str A date string expected to be in Exif format (Y:m:d H:i:s). + * @return int|false The unix timestamp, or false on failure. + */ + function wp_exif_date2ts($str) + { + } + /** + * Gets extended image metadata, exif or iptc as available. + * + * Retrieves the EXIF metadata aperture, credit, camera, caption, copyright, iso + * created_timestamp, focal_length, shutter_speed, and title. + * + * The IPTC metadata that is retrieved is APP13, credit, byline, created date + * and time, caption, copyright, and title. Also includes FNumber, Model, + * DateTimeDigitized, FocalLength, ISOSpeedRatings, and ExposureTime. + * + * @todo Try other exif libraries if available. + * @since 2.5.0 + * + * @param string $file + * @return array|false Image metadata array on success, false on failure. + */ + function wp_read_image_metadata($file) + { + } + /** + * Validates that file is an image. + * + * @since 2.5.0 + * + * @param string $path File path to test if valid image. + * @return bool True if valid image, false if not valid image. + */ + function file_is_valid_image($path) + { + } + /** + * Validates that file is suitable for displaying within a web page. + * + * @since 2.5.0 + * + * @param string $path File path to test. + * @return bool True if suitable, false if not suitable. + */ + function file_is_displayable_image($path) + { + } + /** + * Loads an image resource for editing. + * + * @since 2.9.0 + * + * @param int $attachment_id Attachment ID. + * @param string $mime_type Image mime type. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array + * of width and height values in pixels (in that order). Default 'full'. + * @return resource|GdImage|false The resulting image resource or GdImage instance on success, + * false on failure. + */ + function load_image_to_edit($attachment_id, $mime_type, $size = 'full') + { + } + /** + * Retrieves the path or URL of an attachment's attached file. + * + * If the attached file is not present on the local filesystem (usually due to replication plugins), + * then the URL of the file is returned if `allow_url_fopen` is supported. + * + * @since 3.4.0 + * @access private + * + * @param int $attachment_id Attachment ID. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array + * of width and height values in pixels (in that order). Default 'full'. + * @return string|false File path or URL on success, false on failure. + */ + function _load_image_to_edit_path($attachment_id, $size = 'full') + { + } + /** + * Copies an existing image file. + * + * @since 3.4.0 + * @access private + * + * @param int $attachment_id Attachment ID. + * @return string|false New file path on success, false on failure. + */ + function _copy_image_file($attachment_id) + { + } + /** + * WordPress Administration Importer API. + * + * @package WordPress + * @subpackage Administration + */ + /** + * Retrieves the list of importers. + * + * @since 2.0.0 + * + * @global array $wp_importers + * @return array + */ + function get_importers() + { + } + /** + * Sorts a multidimensional array by first member of each top level member. + * + * Used by uasort() as a callback, should not be used directly. + * + * @since 2.9.0 + * @access private + * + * @param array $a + * @param array $b + * @return int + */ + function _usort_by_first_member($a, $b) + { + } + /** + * Registers importer for WordPress. + * + * @since 2.0.0 + * + * @global array $wp_importers + * + * @param string $id Importer tag. Used to uniquely identify importer. + * @param string $name Importer name and title. + * @param string $description Importer description. + * @param callable $callback Callback to run. + * @return void|WP_Error Void on success. WP_Error when $callback is WP_Error. + */ + function register_importer($id, $name, $description, $callback) + { + } + /** + * Cleanup importer. + * + * Removes attachment based on ID. + * + * @since 2.0.0 + * + * @param string $id Importer ID. + */ + function wp_import_cleanup($id) + { + } + /** + * Handles importer uploading and adds attachment. + * + * @since 2.0.0 + * + * @return array Uploaded file's details on success, error message on failure. + */ + function wp_import_handle_upload() + { + } + /** + * Returns a list from WordPress.org of popular importer plugins. + * + * @since 3.5.0 + * + * @return array Importers with metadata for each. + */ + function wp_get_popular_importers() + { + } + /** + * Helper functions for displaying a list of items in an ajaxified HTML table. + * + * @package WordPress + * @subpackage List_Table + * @since 3.1.0 + */ + /** + * Fetches an instance of a WP_List_Table class. + * + * @since 3.1.0 + * + * @global string $hook_suffix + * + * @param string $class_name The type of the list table, which is the class name. + * @param array $args Optional. Arguments to pass to the class. Accepts 'screen'. + * @return WP_List_Table|false List table object on success, false if the class does not exist. + */ + function _get_list_table($class_name, $args = array()) + { + } + /** + * Register column headers for a particular screen. + * + * @see get_column_headers(), print_column_headers(), get_hidden_columns() + * + * @since 2.7.0 + * + * @param string $screen The handle for the screen to register column headers for. This is + * usually the hook name returned by the `add_*_page()` functions. + * @param string[] $columns An array of columns with column IDs as the keys and translated + * column names as the values. + */ + function register_column_headers($screen, $columns) + { + } + /** + * Prints column headers for a particular screen. + * + * @since 2.7.0 + * + * @param string|WP_Screen $screen The screen hook name or screen object. + * @param bool $with_id Whether to set the ID attribute or not. + */ + function print_column_headers($screen, $with_id = \true) + { + } + /** + * WordPress Administration Media API. + * + * @package WordPress + * @subpackage Administration + */ + /** + * Defines the default media upload tabs. + * + * @since 2.5.0 + * + * @return string[] Default tabs. + */ + function media_upload_tabs() + { + } + /** + * Adds the gallery tab back to the tabs array if post has image attachments. + * + * @since 2.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $tabs + * @return array $tabs with gallery if post has image attachment + */ + function update_gallery_tab($tabs) + { + } + /** + * Outputs the legacy media upload tabs UI. + * + * @since 2.5.0 + * + * @global string $redir_tab + */ + function the_media_upload_tabs() + { + } + /** + * Retrieves the image HTML to send to the editor. + * + * @since 2.5.0 + * + * @param int $id Image attachment ID. + * @param string $caption Image caption. + * @param string $title Image title attribute. + * @param string $align Image CSS alignment property. + * @param string $url Optional. Image src URL. Default empty. + * @param bool|string $rel Optional. Value for rel attribute or whether to add a default value. Default false. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array of + * width and height values in pixels (in that order). Default 'medium'. + * @param string $alt Optional. Image alt attribute. Default empty. + * @return string The HTML output to insert into the editor. + */ + function get_image_send_to_editor($id, $caption, $title, $align, $url = '', $rel = \false, $size = 'medium', $alt = '') + { + } + /** + * Adds image shortcode with caption to editor. + * + * @since 2.6.0 + * + * @param string $html The image HTML markup to send. + * @param int $id Image attachment ID. + * @param string $caption Image caption. + * @param string $title Image title attribute (not used). + * @param string $align Image CSS alignment property. + * @param string $url Image source URL (not used). + * @param string $size Image size (not used). + * @param string $alt Image `alt` attribute (not used). + * @return string The image HTML markup with caption shortcode. + */ + function image_add_caption($html, $id, $caption, $title, $align, $url, $size, $alt = '') + { + } + /** + * Private preg_replace callback used in image_add_caption(). + * + * @access private + * @since 3.4.0 + */ + function _cleanup_image_add_caption($matches) + { + } + /** + * Adds image HTML to editor. + * + * @since 2.5.0 + * + * @param string $html + */ + function media_send_to_editor($html) + { + } + /** + * Saves a file submitted from a POST request and create an attachment post for it. + * + * @since 2.5.0 + * + * @param string $file_id Index of the `$_FILES` array that the file was sent. + * @param int $post_id The post ID of a post to attach the media item to. Required, but can + * be set to 0, creating a media item that has no relationship to a post. + * @param array $post_data Optional. Overwrite some of the attachment. + * @param array $overrides Optional. Override the wp_handle_upload() behavior. + * @return int|WP_Error ID of the attachment or a WP_Error object on failure. + */ + function media_handle_upload($file_id, $post_id, $post_data = array(), $overrides = array('test_form' => \false)) + { + } + /** + * Handles a side-loaded file in the same way as an uploaded file is handled by media_handle_upload(). + * + * @since 2.6.0 + * @since 5.3.0 The `$post_id` parameter was made optional. + * + * @param string[] $file_array Array that represents a `$_FILES` upload array. + * @param int $post_id Optional. The post ID the media is associated with. + * @param string $desc Optional. Description of the side-loaded file. Default null. + * @param array $post_data Optional. Post data to override. Default empty array. + * @return int|WP_Error The ID of the attachment or a WP_Error on failure. + */ + function media_handle_sideload($file_array, $post_id = 0, $desc = \null, $post_data = array()) + { + } + /** + * Outputs the iframe to display the media upload page. + * + * @since 2.5.0 + * @since 5.3.0 Formalized the existing and already documented `...$args` parameter + * by adding it to the function signature. + * + * @global int $body_id + * + * @param callable $content_func Function that outputs the content. + * @param mixed ...$args Optional additional parameters to pass to the callback function when it's called. + */ + function wp_iframe($content_func, ...$args) + { + } + /** + * Adds the media button to the editor. + * + * @since 2.5.0 + * + * @global int $post_ID + * + * @param string $editor_id + */ + function media_buttons($editor_id = 'content') + { + } + /** + * Retrieves the upload iframe source URL. + * + * @since 3.0.0 + * + * @global int $post_ID + * + * @param string $type Media type. + * @param int $post_id Post ID. + * @param string $tab Media upload tab. + * @return string Upload iframe source URL. + */ + function get_upload_iframe_src($type = \null, $post_id = \null, $tab = \null) + { + } + /** + * Handles form submissions for the legacy media uploader. + * + * @since 2.5.0 + * + * @return null|array|void Array of error messages keyed by attachment ID, null or void on success. + */ + function media_upload_form_handler() + { + } + /** + * Handles the process of uploading media. + * + * @since 2.5.0 + * + * @return null|string + */ + function wp_media_upload_handler() + { + } + /** + * Downloads an image from the specified URL, saves it as an attachment, and optionally attaches it to a post. + * + * @since 2.6.0 + * @since 4.2.0 Introduced the `$return_type` parameter. + * @since 4.8.0 Introduced the 'id' option for the `$return_type` parameter. + * @since 5.3.0 The `$post_id` parameter was made optional. + * @since 5.4.0 The original URL of the attachment is stored in the `_source_url` + * post meta value. + * + * @param string $file The URL of the image to download. + * @param int $post_id Optional. The post ID the media is to be associated with. + * @param string $desc Optional. Description of the image. + * @param string $return_type Optional. Accepts 'html' (image tag html) or 'src' (URL), + * or 'id' (attachment ID). Default 'html'. + * @return string|int|WP_Error Populated HTML img tag, attachment ID, or attachment source + * on success, WP_Error object otherwise. + */ + function media_sideload_image($file, $post_id = 0, $desc = \null, $return_type = 'html') + { + } + /** + * Retrieves the legacy media uploader form in an iframe. + * + * @since 2.5.0 + * + * @return string|null + */ + function media_upload_gallery() + { + } + /** + * Retrieves the legacy media library form in an iframe. + * + * @since 2.5.0 + * + * @return string|null + */ + function media_upload_library() + { + } + /** + * Retrieves HTML for the image alignment radio buttons with the specified one checked. + * + * @since 2.7.0 + * + * @param WP_Post $post + * @param string $checked + * @return string + */ + function image_align_input_fields($post, $checked = '') + { + } + /** + * Retrieves HTML for the size radio buttons with the specified one checked. + * + * @since 2.7.0 + * + * @param WP_Post $post + * @param bool|string $check + * @return array + */ + function image_size_input_fields($post, $check = '') + { + } + /** + * Retrieves HTML for the Link URL buttons with the default link type as specified. + * + * @since 2.7.0 + * + * @param WP_Post $post + * @param string $url_type + * @return string + */ + function image_link_input_fields($post, $url_type = '') + { + } + /** + * Outputs a textarea element for inputting an attachment caption. + * + * @since 3.4.0 + * + * @param WP_Post $edit_post Attachment WP_Post object. + * @return string HTML markup for the textarea element. + */ + function wp_caption_input_textarea($edit_post) + { + } + /** + * Retrieves the image attachment fields to edit form fields. + * + * @since 2.5.0 + * + * @param array $form_fields + * @param object $post + * @return array + */ + function image_attachment_fields_to_edit($form_fields, $post) + { + } + /** + * Retrieves the single non-image attachment fields to edit form fields. + * + * @since 2.5.0 + * + * @param array $form_fields An array of attachment form fields. + * @param WP_Post $post The WP_Post attachment object. + * @return array Filtered attachment form fields. + */ + function media_single_attachment_fields_to_edit($form_fields, $post) + { + } + /** + * Retrieves the post non-image attachment fields to edit form fields. + * + * @since 2.8.0 + * + * @param array $form_fields An array of attachment form fields. + * @param WP_Post $post The WP_Post attachment object. + * @return array Filtered attachment form fields. + */ + function media_post_single_attachment_fields_to_edit($form_fields, $post) + { + } + /** + * Retrieves the media element HTML to send to the editor. + * + * @since 2.5.0 + * + * @param string $html + * @param int $attachment_id + * @param array $attachment + * @return string + */ + function image_media_send_to_editor($html, $attachment_id, $attachment) + { + } + /** + * Retrieves the attachment fields to edit form fields. + * + * @since 2.5.0 + * + * @param WP_Post $post + * @param array $errors + * @return array + */ + function get_attachment_fields_to_edit($post, $errors = \null) + { + } + /** + * Retrieves HTML for media items of post gallery. + * + * The HTML markup retrieved will be created for the progress of SWF Upload + * component. Will also create link for showing and hiding the form to modify + * the image attachment. + * + * @since 2.5.0 + * + * @global WP_Query $wp_the_query WordPress Query object. + * + * @param int $post_id Post ID. + * @param array $errors Errors for attachment, if any. + * @return string HTML content for media items of post gallery. + */ + function get_media_items($post_id, $errors) + { + } + /** + * Retrieves HTML form for modifying the image attachment. + * + * @since 2.5.0 + * + * @global string $redir_tab + * + * @param int $attachment_id Attachment ID for modification. + * @param string|array $args Optional. Override defaults. + * @return string HTML form for attachment. + */ + function get_media_item($attachment_id, $args = \null) + { + } + /** + * @since 3.5.0 + * + * @param int $attachment_id + * @param array $args + * @return array + */ + function get_compat_media_markup($attachment_id, $args = \null) + { + } + /** + * Outputs the legacy media upload header. + * + * @since 2.5.0 + */ + function media_upload_header() + { + } + /** + * Outputs the legacy media upload form. + * + * @since 2.5.0 + * + * @global string $type + * @global string $tab + * @global bool $is_IE + * @global bool $is_opera + * + * @param array $errors + */ + function media_upload_form($errors = \null) + { + } + /** + * Outputs the legacy media upload form for a given media type. + * + * @since 2.5.0 + * + * @param string $type + * @param array $errors + * @param int|WP_Error $id + */ + function media_upload_type_form($type = 'file', $errors = \null, $id = \null) + { + } + /** + * Outputs the legacy media upload form for external media. + * + * @since 2.7.0 + * + * @param string $type + * @param object $errors + * @param int $id + */ + function media_upload_type_url_form($type = \null, $errors = \null, $id = \null) + { + } + /** + * Adds gallery form to upload iframe. + * + * @since 2.5.0 + * + * @global string $redir_tab + * @global string $type + * @global string $tab + * + * @param array $errors + */ + function media_upload_gallery_form($errors) + { + } + /** + * Outputs the legacy media upload form for the media library. + * + * @since 2.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global WP_Query $wp_query WordPress Query object. + * @global WP_Locale $wp_locale WordPress date and time locale object. + * @global string $type + * @global string $tab + * @global array $post_mime_types + * + * @param array $errors + */ + function media_upload_library_form($errors) + { + } + /** + * Creates the form for external url. + * + * @since 2.7.0 + * + * @param string $default_view + * @return string HTML content of the form. + */ + function wp_media_insert_url_form($default_view = 'image') + { + } + /** + * Displays the multi-file uploader message. + * + * @since 2.6.0 + * + * @global int $post_ID + */ + function media_upload_flash_bypass() + { + } + /** + * Displays the browser's built-in uploader message. + * + * @since 2.6.0 + */ + function media_upload_html_bypass() + { + } + /** + * Used to display a "After a file has been uploaded..." help message. + * + * @since 3.3.0 + */ + function media_upload_text_after() + { + } + /** + * Displays the checkbox to scale images. + * + * @since 3.3.0 + */ + function media_upload_max_image_resize() + { + } + /** + * Displays the out of storage quota message in Multisite. + * + * @since 3.5.0 + */ + function multisite_over_quota_message() + { + } + /** + * Displays the image and editor in the post editor + * + * @since 3.5.0 + * + * @param WP_Post $post A post object. + */ + function edit_form_image_editor($post) + { + } + /** + * Displays non-editable attachment metadata in the publish meta box. + * + * @since 3.5.0 + */ + function attachment_submitbox_metadata() + { + } + /** + * Parses ID3v2, ID3v1, and getID3 comments to extract usable data. + * + * @since 3.6.0 + * + * @param array $metadata An existing array with data. + * @param array $data Data supplied by ID3 tags. + */ + function wp_add_id3_tag_data(&$metadata, $data) + { + } + /** + * Retrieves metadata from a video file's ID3 tags. + * + * @since 3.6.0 + * + * @param string $file Path to file. + * @return array|false Returns array of metadata, if found. + */ + function wp_read_video_metadata($file) + { + } + /** + * Retrieves metadata from an audio file's ID3 tags. + * + * @since 3.6.0 + * + * @param string $file Path to file. + * @return array|false Returns array of metadata, if found. + */ + function wp_read_audio_metadata($file) + { + } + /** + * Parses creation date from media metadata. + * + * The getID3 library doesn't have a standard method for getting creation dates, + * so the location of this data can vary based on the MIME type. + * + * @since 4.9.0 + * + * @link https://github.com/JamesHeinrich/getID3/blob/master/structure.txt + * + * @param array $metadata The metadata returned by getID3::analyze(). + * @return int|false A UNIX timestamp for the media's creation date if available + * or a boolean FALSE if a timestamp could not be determined. + */ + function wp_get_media_creation_timestamp($metadata) + { + } + /** + * Encapsulates the logic for Attach/Detach actions. + * + * @since 4.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $parent_id Attachment parent ID. + * @param string $action Optional. Attach/detach action. Accepts 'attach' or 'detach'. + * Default 'attach'. + */ + function wp_media_attach_action($parent_id, $action = 'attach') + { + } + /** + * Adds a CSS class to a string. + * + * @since 2.7.0 + * + * @param string $class_to_add The CSS class to add. + * @param string $classes The string to add the CSS class to. + * @return string The string with the CSS class added. + */ + function add_cssclass($class_to_add, $classes) + { + } + /** + * Adds CSS classes for top-level administration menu items. + * + * The list of added classes includes `.menu-top-first` and `.menu-top-last`. + * + * @since 2.7.0 + * + * @param array $menu The array of administration menu items. + * @return array The array of administration menu items with the CSS classes added. + */ + function add_menu_classes($menu) + { + } + /** + * @global array $menu_order + * @global array $default_menu_order + * + * @param array $a + * @param array $b + * @return int + */ + function sort_menu($a, $b) + { + } + /** + * WordPress Administration Meta Boxes API. + * + * @package WordPress + * @subpackage Administration + */ + // + // Post-related Meta Boxes. + // + /** + * Displays post submit form fields. + * + * @since 2.7.0 + * + * @global string $action + * + * @param WP_Post $post Current post object. + * @param array $args { + * Array of arguments for building the post submit meta box. + * + * @type string $id Meta box 'id' attribute. + * @type string $title Meta box title. + * @type callable $callback Meta box display callback. + * @type array $args Extra meta box arguments. + * } + * @phpstan-param array{ + * id?: string, + * title?: string, + * callback?: callable, + * args?: array, + * } $args + */ + function post_submit_meta_box($post, $args = array()) + { + } + /** + * Displays attachment submit form fields. + * + * @since 3.5.0 + * + * @param WP_Post $post Current post object. + */ + function attachment_submit_meta_box($post) + { + } + /** + * Displays post format form elements. + * + * @since 3.1.0 + * + * @param WP_Post $post Current post object. + * @param array $box { + * Post formats meta box arguments. + * + * @type string $id Meta box 'id' attribute. + * @type string $title Meta box title. + * @type callable $callback Meta box display callback. + * @type array $args Extra meta box arguments. + * } + * @phpstan-param array{ + * id?: string, + * title?: string, + * callback?: callable, + * args?: array, + * } $box + */ + function post_format_meta_box($post, $box) + { + } + /** + * Displays post tags form fields. + * + * @since 2.6.0 + * + * @todo Create taxonomy-agnostic wrapper for this. + * + * @param WP_Post $post Current post object. + * @param array $box { + * Tags meta box arguments. + * + * @type string $id Meta box 'id' attribute. + * @type string $title Meta box title. + * @type callable $callback Meta box display callback. + * @type array $args { + * Extra meta box arguments. + * + * @type string $taxonomy Taxonomy. Default 'post_tag'. + * } + * } + * @phpstan-param array{ + * id?: string, + * title?: string, + * callback?: callable, + * args?: array{ + * taxonomy?: string, + * }, + * } $box + */ + function post_tags_meta_box($post, $box) + { + } + /** + * Displays post categories form fields. + * + * @since 2.6.0 + * + * @todo Create taxonomy-agnostic wrapper for this. + * + * @param WP_Post $post Current post object. + * @param array $box { + * Categories meta box arguments. + * + * @type string $id Meta box 'id' attribute. + * @type string $title Meta box title. + * @type callable $callback Meta box display callback. + * @type array $args { + * Extra meta box arguments. + * + * @type string $taxonomy Taxonomy. Default 'category'. + * } + * } + * @phpstan-param array{ + * id?: string, + * title?: string, + * callback?: callable, + * args?: array{ + * taxonomy?: string, + * }, + * } $box + */ + function post_categories_meta_box($post, $box) + { + } + /** + * Displays post excerpt form fields. + * + * @since 2.6.0 + * + * @param WP_Post $post Current post object. + */ + function post_excerpt_meta_box($post) + { + } + /** + * Displays trackback links form fields. + * + * @since 2.6.0 + * + * @param WP_Post $post Current post object. + */ + function post_trackback_meta_box($post) + { + } + /** + * Displays custom fields form fields. + * + * @since 2.6.0 + * + * @param WP_Post $post Current post object. + */ + function post_custom_meta_box($post) + { + } + /** + * Displays comments status form fields. + * + * @since 2.6.0 + * + * @param WP_Post $post Current post object. + */ + function post_comment_status_meta_box($post) + { + } + /** + * Displays comments for post table header + * + * @since 3.0.0 + * + * @param array $result Table header rows. + * @return array + */ + function post_comment_meta_box_thead($result) + { + } + /** + * Displays comments for post. + * + * @since 2.8.0 + * + * @param WP_Post $post Current post object. + */ + function post_comment_meta_box($post) + { + } + /** + * Displays slug form fields. + * + * @since 2.6.0 + * + * @param WP_Post $post Current post object. + */ + function post_slug_meta_box($post) + { + } + /** + * Displays form field with list of authors. + * + * @since 2.6.0 + * + * @global int $user_ID + * + * @param WP_Post $post Current post object. + */ + function post_author_meta_box($post) + { + } + /** + * Displays list of revisions. + * + * @since 2.6.0 + * + * @param WP_Post $post Current post object. + */ + function post_revisions_meta_box($post) + { + } + // + // Page-related Meta Boxes. + // + /** + * Displays page attributes form fields. + * + * @since 2.7.0 + * + * @param WP_Post $post Current post object. + */ + function page_attributes_meta_box($post) + { + } + // + // Link-related Meta Boxes. + // + /** + * Displays link create form fields. + * + * @since 2.7.0 + * + * @param object $link Current link object. + */ + function link_submit_meta_box($link) + { + } + /** + * Displays link categories form fields. + * + * @since 2.6.0 + * + * @param object $link Current link object. + */ + function link_categories_meta_box($link) + { + } + /** + * Displays form fields for changing link target. + * + * @since 2.6.0 + * + * @param object $link Current link object. + */ + function link_target_meta_box($link) + { + } + /** + * Displays 'checked' checkboxes attribute for XFN microformat options. + * + * @since 1.0.1 + * + * @global object $link Current link object. + * + * @param string $xfn_relationship XFN relationship category. Possible values are: + * 'friendship', 'physical', 'professional', + * 'geographical', 'family', 'romantic', 'identity'. + * @param string $xfn_value Optional. The XFN value to mark as checked + * if it matches the current link's relationship. + * Default empty string. + * @param mixed $deprecated Deprecated. Not used. + */ + function xfn_check($xfn_relationship, $xfn_value = '', $deprecated = '') + { + } + /** + * Displays XFN form fields. + * + * @since 2.6.0 + * + * @param object $link Current link object. + */ + function link_xfn_meta_box($link) + { + } + /** + * Displays advanced link options form fields. + * + * @since 2.6.0 + * + * @param object $link Current link object. + */ + function link_advanced_meta_box($link) + { + } + /** + * Displays post thumbnail meta box. + * + * @since 2.9.0 + * + * @param WP_Post $post Current post object. + */ + function post_thumbnail_meta_box($post) + { + } + /** + * Displays fields for ID3 data. + * + * @since 3.9.0 + * + * @param WP_Post $post Current post object. + */ + function attachment_id3_data_meta_box($post) + { + } + /** + * Registers the default post meta boxes, and runs the `do_meta_boxes` actions. + * + * @since 5.0.0 + * + * @param WP_Post $post The post object that these meta boxes are being generated for. + */ + function register_and_do_post_meta_boxes($post) + { + } + /** + * Misc WordPress Administration API. + * + * @package WordPress + * @subpackage Administration + */ + /** + * Returns whether the server is running Apache with the mod_rewrite module loaded. + * + * @since 2.0.0 + * + * @return bool Whether the server is running Apache with the mod_rewrite module loaded. + */ + function got_mod_rewrite() + { + } + /** + * Returns whether the server supports URL rewriting. + * + * Detects Apache's mod_rewrite, IIS 7.0+ permalink support, and nginx. + * + * @since 3.7.0 + * + * @global bool $is_nginx + * + * @return bool Whether the server supports URL rewriting. + */ + function got_url_rewrite() + { + } + /** + * Extracts strings from between the BEGIN and END markers in the .htaccess file. + * + * @since 1.5.0 + * + * @param string $filename Filename to extract the strings from. + * @param string $marker The marker to extract the strings from. + * @return string[] An array of strings from a file (.htaccess) from between BEGIN and END markers. + */ + function extract_from_markers($filename, $marker) + { + } + /** + * Inserts an array of strings into a file (.htaccess), placing it between + * BEGIN and END markers. + * + * Replaces existing marked info. Retains surrounding + * data. Creates file if none exists. + * + * @since 1.5.0 + * + * @param string $filename Filename to alter. + * @param string $marker The marker to alter. + * @param array|string $insertion The new content to insert. + * @return bool True on write success, false on failure. + */ + function insert_with_markers($filename, $marker, $insertion) + { + } + /** + * Updates the htaccess file with the current rules if it is writable. + * + * Always writes to the file if it exists and is writable to ensure that we + * blank out old rules. + * + * @since 1.5.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @return bool|null True on write success, false on failure. Null in multisite. + */ + function save_mod_rewrite_rules() + { + } + /** + * Updates the IIS web.config file with the current rules if it is writable. + * If the permalinks do not require rewrite rules then the rules are deleted from the web.config file. + * + * @since 2.8.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @return bool|null True on write success, false on failure. Null in multisite. + */ + function iis7_save_url_rewrite_rules() + { + } + /** + * Updates the "recently-edited" file for the plugin or theme file editor. + * + * @since 1.5.0 + * + * @param string $file + */ + function update_recently_edited($file) + { + } + /** + * Makes a tree structure for the theme file editor's file list. + * + * @since 4.9.0 + * @access private + * + * @param array $allowed_files List of theme file paths. + * @return array Tree structure for listing theme files. + */ + function wp_make_theme_file_tree($allowed_files) + { + } + /** + * Outputs the formatted file list for the theme file editor. + * + * @since 4.9.0 + * @access private + * + * @global string $relative_file Name of the file being edited relative to the + * theme directory. + * @global string $stylesheet The stylesheet name of the theme being edited. + * + * @param array|string $tree List of file/folder paths, or filename. + * @param int $level The aria-level for the current iteration. + * @param int $size The aria-setsize for the current iteration. + * @param int $index The aria-posinset for the current iteration. + */ + function wp_print_theme_file_tree($tree, $level = 2, $size = 1, $index = 1) + { + } + /** + * Makes a tree structure for the plugin file editor's file list. + * + * @since 4.9.0 + * @access private + * + * @param array $plugin_editable_files List of plugin file paths. + * @return array Tree structure for listing plugin files. + */ + function wp_make_plugin_file_tree($plugin_editable_files) + { + } + /** + * Outputs the formatted file list for the plugin file editor. + * + * @since 4.9.0 + * @access private + * + * @param array|string $tree List of file/folder paths, or filename. + * @param string $label Name of file or folder to print. + * @param int $level The aria-level for the current iteration. + * @param int $size The aria-setsize for the current iteration. + * @param int $index The aria-posinset for the current iteration. + */ + function wp_print_plugin_file_tree($tree, $label = '', $level = 2, $size = 1, $index = 1) + { + } + /** + * Flushes rewrite rules if siteurl, home or page_on_front changed. + * + * @since 2.1.0 + * + * @param string $old_value + * @param string $value + */ + function update_home_siteurl($old_value, $value) + { + } + /** + * Resets global variables based on $_GET and $_POST. + * + * This function resets global variables based on the names passed + * in the $vars array to the value of $_POST[$var] or $_GET[$var] or '' + * if neither is defined. + * + * @since 2.0.0 + * + * @param array $vars An array of globals to reset. + */ + function wp_reset_vars($vars) + { + } + /** + * Displays the given administration message. + * + * @since 2.1.0 + * + * @param string|WP_Error $message + */ + function show_message($message) + { + } + /** + * @since 2.8.0 + * + * @param string $content + * @return array + */ + function wp_doc_link_parse($content) + { + } + /** + * Saves option for number of rows when listing posts, pages, comments, etc. + * + * @since 2.8.0 + */ + function set_screen_options() + { + } + /** + * Checks if rewrite rule for WordPress already exists in the IIS 7+ configuration file. + * + * @since 2.8.0 + * + * @param string $filename The file path to the configuration file. + * @return bool + */ + function iis7_rewrite_rule_exists($filename) + { + } + /** + * Deletes WordPress rewrite rule from web.config file if it exists there. + * + * @since 2.8.0 + * + * @param string $filename Name of the configuration file. + * @return bool + */ + function iis7_delete_rewrite_rule($filename) + { + } + /** + * Adds WordPress rewrite rule to the IIS 7+ configuration file. + * + * @since 2.8.0 + * + * @param string $filename The file path to the configuration file. + * @param string $rewrite_rule The XML fragment with URL Rewrite rule. + * @return bool + */ + function iis7_add_rewrite_rule($filename, $rewrite_rule) + { + } + /** + * Saves the XML document into a file. + * + * @since 2.8.0 + * + * @param DOMDocument $doc + * @param string $filename + */ + function saveDomDocument($doc, $filename) + { + } + /** + * Displays the default admin color scheme picker (Used in user-edit.php). + * + * @since 3.0.0 + * + * @global array $_wp_admin_css_colors + * + * @param int $user_id User ID. + */ + function admin_color_scheme_picker($user_id) + { + } + /** + * + * @global array $_wp_admin_css_colors + */ + function wp_color_scheme_settings() + { + } + /** + * Displays the viewport meta in the admin. + * + * @since 5.5.0 + */ + function wp_admin_viewport_meta() + { + } + /** + * Adds viewport meta for mobile in Customizer. + * + * Hooked to the {@see 'admin_viewport_meta'} filter. + * + * @since 5.5.0 + * + * @param string $viewport_meta The viewport meta. + * @return string Filtered viewport meta. + */ + function _customizer_mobile_viewport_meta($viewport_meta) + { + } + /** + * Checks lock status for posts displayed on the Posts screen. + * + * @since 3.6.0 + * + * @param array $response The Heartbeat response. + * @param array $data The $_POST data sent. + * @param string $screen_id The screen ID. + * @return array The Heartbeat response. + */ + function wp_check_locked_posts($response, $data, $screen_id) + { + } + /** + * Checks lock status on the New/Edit Post screen and refresh the lock. + * + * @since 3.6.0 + * + * @param array $response The Heartbeat response. + * @param array $data The $_POST data sent. + * @param string $screen_id The screen ID. + * @return array The Heartbeat response. + */ + function wp_refresh_post_lock($response, $data, $screen_id) + { + } + /** + * Checks nonce expiration on the New/Edit Post screen and refresh if needed. + * + * @since 3.6.0 + * + * @param array $response The Heartbeat response. + * @param array $data The $_POST data sent. + * @param string $screen_id The screen ID. + * @return array The Heartbeat response. + */ + function wp_refresh_post_nonces($response, $data, $screen_id) + { + } + /** + * Refresh nonces used with meta boxes in the block editor. + * + * @since 6.1.0 + * + * @param array $response The Heartbeat response. + * @param array $data The $_POST data sent. + * @return array The Heartbeat response. + */ + function wp_refresh_metabox_loader_nonces($response, $data) + { + } + /** + * Adds the latest Heartbeat and REST-API nonce to the Heartbeat response. + * + * @since 5.0.0 + * + * @param array $response The Heartbeat response. + * @return array The Heartbeat response. + */ + function wp_refresh_heartbeat_nonces($response) + { + } + /** + * Disables suspension of Heartbeat on the Add/Edit Post screens. + * + * @since 3.8.0 + * + * @global string $pagenow The filename of the current screen. + * + * @param array $settings An array of Heartbeat settings. + * @return array Filtered Heartbeat settings. + */ + function wp_heartbeat_set_suspension($settings) + { + } + /** + * Performs autosave with heartbeat. + * + * @since 3.9.0 + * + * @param array $response The Heartbeat response. + * @param array $data The $_POST data sent. + * @return array The Heartbeat response. + */ + function heartbeat_autosave($response, $data) + { + } + /** + * Removes single-use URL parameters and create canonical link based on new URL. + * + * Removes specific query string parameters from a URL, create the canonical link, + * put it in the admin header, and change the current URL to match. + * + * @since 4.2.0 + */ + function wp_admin_canonical_url() + { + } + /** + * Sends a referrer policy header so referrers are not sent externally from administration screens. + * + * @since 4.9.0 + */ + function wp_admin_headers() + { + } + /** + * Outputs JS that reloads the page if the user navigated to it with the Back or Forward button. + * + * Used on the Edit Post and Add New Post screens. Needed to ensure the page is not loaded from browser cache, + * so the post title and editor content are the last saved versions. Ideally this script should run first in the head. + * + * @since 4.6.0 + */ + function wp_page_reload_on_back_button_js() + { + } + /** + * Sends a confirmation request email when a change of site admin email address is attempted. + * + * The new site admin address will not become active until confirmed. + * + * @since 3.0.0 + * @since 4.9.0 This function was moved from wp-admin/includes/ms.php so it's no longer Multisite specific. + * + * @param string $old_value The old site admin email address. + * @param string $value The proposed new site admin email address. + */ + function update_option_new_admin_email($old_value, $value) + { + } + /** + * Appends '(Draft)' to draft page titles in the privacy page dropdown + * so that unpublished content is obvious. + * + * @since 4.9.8 + * @access private + * + * @param string $title Page title. + * @param WP_Post $page Page data object. + * @return string Page title. + */ + function _wp_privacy_settings_filter_draft_page_titles($title, $page) + { + } + /** + * Checks if the user needs to update PHP. + * + * @since 5.1.0 + * @since 5.1.1 Added the {@see 'wp_is_php_version_acceptable'} filter. + * + * @return array|false Array of PHP version data. False on failure. + */ + function wp_check_php_version() + { + } + /** + * Multisite: Deprecated admin functions from past versions and WordPress MU + * + * These functions should not be used and will be removed in a later version. + * It is suggested to use for the alternatives instead when available. + * + * @package WordPress + * @subpackage Deprecated + * @since 3.0.0 + */ + /** + * Outputs the WPMU menu. + * + * @deprecated 3.0.0 + */ + function wpmu_menu() + { + } + /** + * Determines if the available space defined by the admin has been exceeded by the user. + * + * @deprecated 3.0.0 Use is_upload_space_available() + * @see is_upload_space_available() + */ + function wpmu_checkAvailableSpace() + { + } + /** + * WPMU options. + * + * @deprecated 3.0.0 + */ + function mu_options($options) + { + } + /** + * Deprecated functionality for activating a network-only plugin. + * + * @deprecated 3.0.0 Use activate_plugin() + * @see activate_plugin() + */ + function activate_sitewide_plugin() + { + } + /** + * Deprecated functionality for deactivating a network-only plugin. + * + * @deprecated 3.0.0 Use deactivate_plugin() + * @see deactivate_plugin() + */ + function deactivate_sitewide_plugin($plugin = \false) + { + } + /** + * Deprecated functionality for determining if the current plugin is network-only. + * + * @deprecated 3.0.0 Use is_network_only_plugin() + * @see is_network_only_plugin() + */ + function is_wpmu_sitewide_plugin($file) + { + } + /** + * Deprecated functionality for getting themes network-enabled themes. + * + * @deprecated 3.4.0 Use WP_Theme::get_allowed_on_network() + * @see WP_Theme::get_allowed_on_network() + */ + function get_site_allowed_themes() + { + } + /** + * Deprecated functionality for getting themes allowed on a specific site. + * + * @deprecated 3.4.0 Use WP_Theme::get_allowed_on_site() + * @see WP_Theme::get_allowed_on_site() + */ + function wpmu_get_blog_allowedthemes($blog_id = 0) + { + } + /** + * Deprecated functionality for determining whether a file is deprecated. + * + * @deprecated 3.5.0 + */ + function ms_deprecated_blogs_file() + { + } + /** + * Install global terms. + * + * @since 3.0.0 + * @since 6.1.0 This function no longer does anything. + * @deprecated 6.1.0 + */ + function install_global_terms() + { + } + /** + * Synchronizes category and post tag slugs when global terms are enabled. + * + * @since 3.0.0 + * @since 6.1.0 This function no longer does anything. + * @deprecated 6.1.0 + * + * @param WP_Term|array $term The term. + * @param string $taxonomy The taxonomy for `$term`. + * @return WP_Term|array Always returns `$term`. + */ + function sync_category_tag_slugs($term, $taxonomy) + { + } + /** + * Multisite administration functions. + * + * @package WordPress + * @subpackage Multisite + * @since 3.0.0 + */ + /** + * Determine if uploaded file exceeds space quota. + * + * @since 3.0.0 + * + * @param array $file An element from the `$_FILES` array for a given file. + * @return array The `$_FILES` array element with 'error' key set if file exceeds quota. 'error' is empty otherwise. + */ + function check_upload_size($file) + { + } + /** + * Delete a site. + * + * @since 3.0.0 + * @since 5.1.0 Use wp_delete_site() internally to delete the site row from the database. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $blog_id Site ID. + * @param bool $drop True if site's database tables should be dropped. Default false. + */ + function wpmu_delete_blog($blog_id, $drop = \false) + { + } + /** + * Delete a user from the network and remove from all sites. + * + * @since 3.0.0 + * + * @todo Merge with wp_delete_user()? + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $id The user ID. + * @return bool True if the user was deleted, otherwise false. + */ + function wpmu_delete_user($id) + { + } + /** + * Check whether a site has used its allotted upload space. + * + * @since MU (3.0.0) + * + * @param bool $display_message Optional. If set to true and the quota is exceeded, + * a warning message is displayed. Default true. + * @return bool True if user is over upload space quota, otherwise false. + */ + function upload_is_user_over_quota($display_message = \true) + { + } + /** + * Displays the amount of disk space used by the current site. Not used in core. + * + * @since MU (3.0.0) + */ + function display_space_usage() + { + } + /** + * Get the remaining upload space for this site. + * + * @since MU (3.0.0) + * + * @param int $size Current max size in bytes + * @return int Max size in bytes + */ + function fix_import_form_size($size) + { + } + /** + * Displays the site upload space quota setting form on the Edit Site Settings screen. + * + * @since 3.0.0 + * + * @param int $id The ID of the site to display the setting for. + */ + function upload_space_setting($id) + { + } + /** + * Cleans the user cache for a specific user. + * + * @since 3.0.0 + * + * @param int $id The user ID. + * @return int|false The ID of the refreshed user or false if the user does not exist. + */ + function refresh_user_details($id) + { + } + /** + * Returns the language for a language code. + * + * @since 3.0.0 + * + * @param string $code Optional. The two-letter language code. Default empty. + * @return string The language corresponding to $code if it exists. If it does not exist, + * then the first two letters of $code is returned. + */ + function format_code_lang($code = '') + { + } + /** + * Displays an access denied message when a user tries to view a site's dashboard they + * do not have access to. + * + * @since 3.2.0 + * @access private + */ + function _access_denied_splash() + { + } + /** + * Checks if the current user has permissions to import new users. + * + * @since 3.0.0 + * + * @param string $permission A permission to be checked. Currently not used. + * @return bool True if the user has proper permissions, false if they do not. + */ + function check_import_new_users($permission) + { + } + // See "import_allow_fetch_attachments" and "import_attachment_size_limit" filters too. + /** + * Generates and displays a drop-down of available languages. + * + * @since 3.0.0 + * + * @param string[] $lang_files Optional. An array of the language files. Default empty array. + * @param string $current Optional. The current language code. Default empty. + */ + function mu_dropdown_languages($lang_files = array(), $current = '') + { + } + /** + * Displays an admin notice to upgrade all sites after a core upgrade. + * + * @since 3.0.0 + * + * @global int $wp_db_version WordPress database version. + * @global string $pagenow The filename of the current screen. + * + * @return void|false Void on success. False if the current user is not a super admin. + */ + function site_admin_notice() + { + } + /** + * Avoids a collision between a site slug and a permalink slug. + * + * In a subdirectory installation this will make sure that a site and a post do not use the + * same subdirectory by checking for a site with the same name as a new post. + * + * @since 3.0.0 + * + * @param array $data An array of post data. + * @param array $postarr An array of posts. Not currently used. + * @return array The new array of post data after checking for collisions. + */ + function avoid_blog_page_permalink_collision($data, $postarr) + { + } + /** + * Handles the display of choosing a user's primary site. + * + * This displays the user's primary site and allows the user to choose + * which site is primary. + * + * @since 3.0.0 + */ + function choose_primary_blog() + { + } + /** + * Whether or not we can edit this network from this page. + * + * By default editing of network is restricted to the Network Admin for that `$network_id`. + * This function allows for this to be overridden. + * + * @since 3.1.0 + * + * @param int $network_id The network ID to check. + * @return bool True if network can be edited, otherwise false. + */ + function can_edit_network($network_id) + { + } + /** + * Thickbox image paths for Network Admin. + * + * @since 3.1.0 + * + * @access private + */ + function _thickbox_path_admin_subfolder() + { + } + /** + * @param array $users + */ + function confirm_delete_users($users) + { + } + /** + * Print JavaScript in the header on the Network Settings screen. + * + * @since 4.1.0 + */ + function network_settings_add_js() + { + } + /** + * Outputs the HTML for a network's "Edit Site" tabular interface. + * + * @since 4.6.0 + * + * @global string $pagenow The filename of the current screen. + * + * @param array $args { + * Optional. Array or string of Query parameters. Default empty array. + * + * @type int $blog_id The site ID. Default is the current site. + * @type array $links The tabs to include with (label|url|cap) keys. + * @type string $selected The ID of the selected link. + * } + * @phpstan-param array{ + * blog_id?: int, + * links?: array, + * selected?: string, + * } $args + */ + function network_edit_site_nav($args = array()) + { + } + /** + * Returns the arguments for the help tab on the Edit Site screens. + * + * @since 4.9.0 + * + * @return array Help tab arguments. + */ + function get_site_screen_help_tab_args() + { + } + /** + * Returns the content for the help sidebar on the Edit Site screens. + * + * @since 4.9.0 + * + * @return string Help sidebar content. + */ + function get_site_screen_help_sidebar_content() + { + } + /** + * Prints the appropriate response to a menu quick search. + * + * @since 3.0.0 + * + * @param array $request The unsanitized request values. + */ + function _wp_ajax_menu_quick_search($request = array()) + { + } + /** + * Register nav menu meta boxes and advanced menu items. + * + * @since 3.0.0 + */ + function wp_nav_menu_setup() + { + } + /** + * Limit the amount of meta boxes to pages, posts, links, and categories for first time users. + * + * @since 3.0.0 + * + * @global array $wp_meta_boxes + */ + function wp_initial_nav_menu_meta_boxes() + { + } + /** + * Creates meta boxes for any post type menu item.. + * + * @since 3.0.0 + */ + function wp_nav_menu_post_type_meta_boxes() + { + } + /** + * Creates meta boxes for any taxonomy menu item. + * + * @since 3.0.0 + */ + function wp_nav_menu_taxonomy_meta_boxes() + { + } + /** + * Check whether to disable the Menu Locations meta box submit button and inputs. + * + * @since 3.6.0 + * @since 5.3.1 The `$display` parameter was added. + * + * @global bool $one_theme_location_no_menus to determine if no menus exist + * + * @param int|string $nav_menu_selected_id ID, name, or slug of the currently selected menu. + * @param bool $display Whether to display or just return the string. + * @return string|false Disabled attribute if at least one menu exists, false if not. + */ + function wp_nav_menu_disabled_check($nav_menu_selected_id, $display = \true) + { + } + /** + * Displays a meta box for the custom links menu item. + * + * @since 3.0.0 + * + * @global int $_nav_menu_placeholder + * @global int|string $nav_menu_selected_id + */ + function wp_nav_menu_item_link_meta_box() + { + } + /** + * Displays a meta box for a post type menu item. + * + * @since 3.0.0 + * + * @global int $_nav_menu_placeholder + * @global int|string $nav_menu_selected_id + * + * @param string $data_object Not used. + * @param array $box { + * Post type menu item meta box arguments. + * + * @type string $id Meta box 'id' attribute. + * @type string $title Meta box title. + * @type callable $callback Meta box display callback. + * @type WP_Post_Type $args Extra meta box arguments (the post type object for this meta box). + * } + * @phpstan-param array{ + * id?: string, + * title?: string, + * callback?: callable, + * args?: WP_Post_Type, + * } $box + */ + function wp_nav_menu_item_post_type_meta_box($data_object, $box) + { + } + /** + * Displays a meta box for a taxonomy menu item. + * + * @since 3.0.0 + * + * @global int|string $nav_menu_selected_id + * + * @param string $data_object Not used. + * @param array $box { + * Taxonomy menu item meta box arguments. + * + * @type string $id Meta box 'id' attribute. + * @type string $title Meta box title. + * @type callable $callback Meta box display callback. + * @type object $args Extra meta box arguments (the taxonomy object for this meta box). + * } + * @phpstan-param array{ + * id?: string, + * title?: string, + * callback?: callable, + * args?: object, + * } $box + */ + function wp_nav_menu_item_taxonomy_meta_box($data_object, $box) + { + } + /** + * Save posted nav menu item data. + * + * @since 3.0.0 + * + * @param int $menu_id The menu ID for which to save this item. Value of 0 makes a draft, orphaned menu item. Default 0. + * @param array[] $menu_data The unsanitized POSTed menu item data. + * @return int[] The database IDs of the items saved + */ + function wp_save_nav_menu_items($menu_id = 0, $menu_data = array()) + { + } + /** + * Adds custom arguments to some of the meta box object types. + * + * @since 3.0.0 + * + * @access private + * + * @param object $data_object The post type or taxonomy meta-object. + * @return object The post type or taxonomy object. + */ + function _wp_nav_menu_meta_box_object($data_object = \null) + { + } + /** + * Returns the menu formatted to edit. + * + * @since 3.0.0 + * + * @param int $menu_id Optional. The ID of the menu to format. Default 0. + * @return string|WP_Error The menu formatted to edit or error object on failure. + */ + function wp_get_nav_menu_to_edit($menu_id = 0) + { + } + /** + * Returns the columns for the nav menus page. + * + * @since 3.0.0 + * + * @return string[] Array of column titles keyed by their column name. + */ + function wp_nav_menu_manage_columns() + { + } + /** + * Deletes orphaned draft menu items + * + * @access private + * @since 3.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function _wp_delete_orphaned_draft_menu_items() + { + } + /** + * Saves nav menu items + * + * @since 3.6.0 + * + * @param int|string $nav_menu_selected_id ID, slug, or name of the currently-selected menu. + * @param string $nav_menu_selected_title Title of the currently-selected menu. + * @return array The menu updated message + */ + function wp_nav_menu_update_menu_items($nav_menu_selected_id, $nav_menu_selected_title) + { + } + /** + * If a JSON blob of navigation menu data is in POST data, expand it and inject + * it into `$_POST` to avoid PHP `max_input_vars` limitations. See #14134. + * + * @ignore + * @since 4.5.3 + * @access private + */ + function _wp_expand_nav_menu_post_data() + { + } + /** + * WordPress Network Administration API. + * + * @package WordPress + * @subpackage Administration + * @since 4.4.0 + */ + /** + * Check for an existing network. + * + * @since 3.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return string|false Base domain if network exists, otherwise false. + */ + function network_domain_check() + { + } + /** + * Allow subdomain installation + * + * @since 3.0.0 + * @return bool Whether subdomain installation is allowed + */ + function allow_subdomain_install() + { + } + /** + * Allow subdirectory installation. + * + * @since 3.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return bool Whether subdirectory installation is allowed + */ + function allow_subdirectory_install() + { + } + /** + * Get base domain of network. + * + * @since 3.0.0 + * @return string Base domain. + */ + function get_clean_basedomain() + { + } + /** + * Prints step 1 for Network installation process. + * + * @todo Realistically, step 1 should be a welcome screen explaining what a Network is and such. + * Navigating to Tools > Network should not be a sudden "Welcome to a new install process! + * Fill this out and click here." See also contextual help todo. + * + * @since 3.0.0 + * + * @global bool $is_apache + * + * @param false|WP_Error $errors Optional. Error object. Default false. + */ + function network_step1($errors = \false) + { + } + /** + * Prints step 2 for Network installation process. + * + * @since 3.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global bool $is_nginx Whether the server software is Nginx or something else. + * + * @param false|WP_Error $errors Optional. Error object. Default false. + */ + function network_step2($errors = \false) + { + } + /** + * WordPress Options Administration API. + * + * @package WordPress + * @subpackage Administration + * @since 4.4.0 + */ + /** + * Output JavaScript to toggle display of additional settings if avatars are disabled. + * + * @since 4.2.0 + */ + function options_discussion_add_js() + { + } + /** + * Display JavaScript on the page. + * + * @since 3.5.0 + */ + function options_general_add_js() + { + } + /** + * Display JavaScript on the page. + * + * @since 3.5.0 + */ + function options_reading_add_js() + { + } + /** + * Render the site charset setting. + * + * @since 3.5.0 + */ + function options_reading_blog_charset() + { + } + /** + * WordPress Plugin Install Administration API + * + * @package WordPress + * @subpackage Administration + */ + /** + * Retrieves plugin installer pages from the WordPress.org Plugins API. + * + * It is possible for a plugin to override the Plugin API result with three + * filters. Assume this is for plugins, which can extend on the Plugin Info to + * offer more choices. This is very powerful and must be used with care when + * overriding the filters. + * + * The first filter, {@see 'plugins_api_args'}, is for the args and gives the action + * as the second parameter. The hook for {@see 'plugins_api_args'} must ensure that + * an object is returned. + * + * The second filter, {@see 'plugins_api'}, allows a plugin to override the WordPress.org + * Plugin Installation API entirely. If `$action` is 'query_plugins' or 'plugin_information', + * an object MUST be passed. If `$action` is 'hot_tags' or 'hot_categories', an array MUST + * be passed. + * + * Finally, the third filter, {@see 'plugins_api_result'}, makes it possible to filter the + * response object or array, depending on the `$action` type. + * + * Supported arguments per action: + * + * | Argument Name | query_plugins | plugin_information | hot_tags | hot_categories | + * | -------------------- | :-----------: | :----------------: | :------: | :------------: | + * | `$slug` | No | Yes | No | No | + * | `$per_page` | Yes | No | No | No | + * | `$page` | Yes | No | No | No | + * | `$number` | No | No | Yes | Yes | + * | `$search` | Yes | No | No | No | + * | `$tag` | Yes | No | No | No | + * | `$author` | Yes | No | No | No | + * | `$user` | Yes | No | No | No | + * | `$browse` | Yes | No | No | No | + * | `$locale` | Yes | Yes | No | No | + * | `$installed_plugins` | Yes | No | No | No | + * | `$is_ssl` | Yes | Yes | No | No | + * | `$fields` | Yes | Yes | No | No | + * + * @since 2.7.0 + * + * @param string $action API action to perform: 'query_plugins', 'plugin_information', + * 'hot_tags' or 'hot_categories'. + * @param array|object $args { + * Optional. Array or object of arguments to serialize for the Plugin Info API. + * + * @type string $slug The plugin slug. Default empty. + * @type int $per_page Number of plugins per page. Default 24. + * @type int $page Number of current page. Default 1. + * @type int $number Number of tags or categories to be queried. + * @type string $search A search term. Default empty. + * @type string $tag Tag to filter plugins. Default empty. + * @type string $author Username of an plugin author to filter plugins. Default empty. + * @type string $user Username to query for their favorites. Default empty. + * @type string $browse Browse view: 'popular', 'new', 'beta', 'recommended'. + * @type string $locale Locale to provide context-sensitive results. Default is the value + * of get_locale(). + * @type string $installed_plugins Installed plugins to provide context-sensitive results. + * @type bool $is_ssl Whether links should be returned with https or not. Default false. + * @type array $fields { + * Array of fields which should or should not be returned. + * + * @type bool $short_description Whether to return the plugin short description. Default true. + * @type bool $description Whether to return the plugin full description. Default false. + * @type bool $sections Whether to return the plugin readme sections: description, installation, + * FAQ, screenshots, other notes, and changelog. Default false. + * @type bool $tested Whether to return the 'Compatible up to' value. Default true. + * @type bool $requires Whether to return the required WordPress version. Default true. + * @type bool $requires_php Whether to return the required PHP version. Default true. + * @type bool $rating Whether to return the rating in percent and total number of ratings. + * Default true. + * @type bool $ratings Whether to return the number of rating for each star (1-5). Default true. + * @type bool $downloaded Whether to return the download count. Default true. + * @type bool $downloadlink Whether to return the download link for the package. Default true. + * @type bool $last_updated Whether to return the date of the last update. Default true. + * @type bool $added Whether to return the date when the plugin was added to the wordpress.org + * repository. Default true. + * @type bool $tags Whether to return the assigned tags. Default true. + * @type bool $compatibility Whether to return the WordPress compatibility list. Default true. + * @type bool $homepage Whether to return the plugin homepage link. Default true. + * @type bool $versions Whether to return the list of all available versions. Default false. + * @type bool $donate_link Whether to return the donation link. Default true. + * @type bool $reviews Whether to return the plugin reviews. Default false. + * @type bool $banners Whether to return the banner images links. Default false. + * @type bool $icons Whether to return the icon links. Default false. + * @type bool $active_installs Whether to return the number of active installations. Default false. + * @type bool $group Whether to return the assigned group. Default false. + * @type bool $contributors Whether to return the list of contributors. Default false. + * } + * } + * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the + * {@link https://developer.wordpress.org/reference/functions/plugins_api/ function reference article} + * for more information on the make-up of possible return values depending on the value of `$action`. + * @phpstan-param object|array{ + * slug?: string, + * per_page?: int, + * page?: int, + * number?: int, + * search?: string, + * tag?: string, + * author?: string, + * user?: string, + * browse?: string, + * locale?: string, + * installed_plugins?: string, + * is_ssl?: bool, + * fields?: array{ + * short_description?: bool, + * description?: bool, + * sections?: bool, + * tested?: bool, + * requires?: bool, + * requires_php?: bool, + * rating?: bool, + * ratings?: bool, + * downloaded?: bool, + * downloadlink?: bool, + * last_updated?: bool, + * added?: bool, + * tags?: bool, + * compatibility?: bool, + * homepage?: bool, + * versions?: bool, + * donate_link?: bool, + * reviews?: bool, + * banners?: bool, + * icons?: bool, + * active_installs?: bool, + * group?: bool, + * contributors?: bool, + * }, + * } $args + */ + function plugins_api($action, $args = array()) + { + } + /** + * Retrieves popular WordPress plugin tags. + * + * @since 2.7.0 + * + * @param array $args + * @return array|WP_Error + */ + function install_popular_tags($args = array()) + { + } + /** + * Displays the Featured tab of Add Plugins screen. + * + * @since 2.7.0 + */ + function install_dashboard() + { + } + /** + * Displays a search form for searching plugins. + * + * @since 2.7.0 + * @since 4.6.0 The `$type_selector` parameter was deprecated. + * + * @param bool $deprecated Not used. + */ + function install_search_form($deprecated = \true) + { + } + /** + * Displays a form to upload plugins from zip files. + * + * @since 2.8.0 + */ + function install_plugins_upload() + { + } + /** + * Shows a username form for the favorites page. + * + * @since 3.5.0 + */ + function install_plugins_favorites_form() + { + } + /** + * Displays plugin content based on plugin list. + * + * @since 2.7.0 + * + * @global WP_List_Table $wp_list_table + */ + function display_plugins_table() + { + } + /** + * Determines the status we can perform on a plugin. + * + * @since 3.0.0 + * + * @param array|object $api Data about the plugin retrieved from the API. + * @param bool $loop Optional. Disable further loops. Default false. + * @return array { + * Plugin installation status data. + * + * @type string $status Status of a plugin. Could be one of 'install', 'update_available', 'latest_installed' or 'newer_installed'. + * @type string $url Plugin installation URL. + * @type string $version The most recent version of the plugin. + * @type string $file Plugin filename relative to the plugins directory. + * } + * @phpstan-return array{ + * status: string, + * url: string, + * version: string, + * file: string, + * } + */ + function install_plugin_install_status($api, $loop = \false) + { + } + /** + * Displays plugin information in dialog box form. + * + * @since 2.7.0 + * + * @global string $tab + */ + function install_plugin_information() + { + } + /** + * WordPress Plugin Administration API + * + * @package WordPress + * @subpackage Administration + */ + /** + * Parses the plugin contents to retrieve plugin's metadata. + * + * All plugin headers must be on their own line. Plugin description must not have + * any newlines, otherwise only parts of the description will be displayed. + * The below is formatted for printing. + * + * /* + * Plugin Name: Name of the plugin. + * Plugin URI: The home page of the plugin. + * Description: Plugin description. + * Author: Plugin author's name. + * Author URI: Link to the author's website. + * Version: Plugin version. + * Text Domain: Optional. Unique identifier, should be same as the one used in + * load_plugin_textdomain(). + * Domain Path: Optional. Only useful if the translations are located in a + * folder above the plugin's base path. For example, if .mo files are + * located in the locale folder then Domain Path will be "/locale/" and + * must have the first slash. Defaults to the base folder the plugin is + * located in. + * Network: Optional. Specify "Network: true" to require that a plugin is activated + * across all sites in an installation. This will prevent a plugin from being + * activated on a single site when Multisite is enabled. + * Requires at least: Optional. Specify the minimum required WordPress version. + * Requires PHP: Optional. Specify the minimum required PHP version. + * * / # Remove the space to close comment. + * + * The first 8 KB of the file will be pulled in and if the plugin data is not + * within that first 8 KB, then the plugin author should correct their plugin + * and move the plugin data headers to the top. + * + * The plugin file is assumed to have permissions to allow for scripts to read + * the file. This is not checked however and the file is only opened for + * reading. + * + * @since 1.5.0 + * @since 5.3.0 Added support for `Requires at least` and `Requires PHP` headers. + * @since 5.8.0 Added support for `Update URI` header. + * + * @param string $plugin_file Absolute path to the main plugin file. + * @param bool $markup Optional. If the returned data should have HTML markup applied. + * Default true. + * @param bool $translate Optional. If the returned data should be translated. Default true. + * @return array { + * Plugin data. Values will be empty if not supplied by the plugin. + * + * @type string $Name Name of the plugin. Should be unique. + * @type string $PluginURI Plugin URI. + * @type string $Version Plugin version. + * @type string $Description Plugin description. + * @type string $Author Plugin author's name. + * @type string $AuthorURI Plugin author's website address (if set). + * @type string $TextDomain Plugin textdomain. + * @type string $DomainPath Plugin's relative directory path to .mo files. + * @type bool $Network Whether the plugin can only be activated network-wide. + * @type string $RequiresWP Minimum required version of WordPress. + * @type string $RequiresPHP Minimum required version of PHP. + * @type string $UpdateURI ID of the plugin for update purposes, should be a URI. + * @type string $Title Title of the plugin and link to the plugin's site (if set). + * @type string $AuthorName Plugin author's name. + * } + * @phpstan-return array{ + * Name: string, + * PluginURI: string, + * Version: string, + * Description: string, + * Author: string, + * AuthorURI: string, + * TextDomain: string, + * DomainPath: string, + * Network: bool, + * RequiresWP: string, + * RequiresPHP: string, + * UpdateURI: string, + * Title: string, + * AuthorName: string, + * } + */ + function get_plugin_data($plugin_file, $markup = \true, $translate = \true) + { + } + /** + * Sanitizes plugin data, optionally adds markup, optionally translates. + * + * @since 2.7.0 + * + * @see get_plugin_data() + * + * @access private + * + * @param string $plugin_file Path to the main plugin file. + * @param array $plugin_data An array of plugin data. See get_plugin_data(). + * @param bool $markup Optional. If the returned data should have HTML markup applied. + * Default true. + * @param bool $translate Optional. If the returned data should be translated. Default true. + * @return array Plugin data. Values will be empty if not supplied by the plugin. + * See get_plugin_data() for the list of possible values. + */ + function _get_plugin_data_markup_translate($plugin_file, $plugin_data, $markup = \true, $translate = \true) + { + } + /** + * Gets a list of a plugin's files. + * + * @since 2.8.0 + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @return string[] Array of file names relative to the plugin root. + */ + function get_plugin_files($plugin) + { + } + /** + * Checks the plugins directory and retrieve all plugin files with plugin data. + * + * WordPress only supports plugin files in the base plugins directory + * (wp-content/plugins) and in one directory above the plugins directory + * (wp-content/plugins/my-plugin). The file it looks for has the plugin data + * and must be found in those two locations. It is recommended to keep your + * plugin files in their own directories. + * + * The file with the plugin data is the file that will be included and therefore + * needs to have the main execution for the plugin. This does not mean + * everything must be contained in the file and it is recommended that the file + * be split for maintainability. Keep everything in one file for extreme + * optimization purposes. + * + * @since 1.5.0 + * + * @param string $plugin_folder Optional. Relative path to single plugin folder. + * @return array[] Array of arrays of plugin data, keyed by plugin file name. See get_plugin_data(). + */ + function get_plugins($plugin_folder = '') + { + } + /** + * Checks the mu-plugins directory and retrieve all mu-plugin files with any plugin data. + * + * WordPress only includes mu-plugin files in the base mu-plugins directory (wp-content/mu-plugins). + * + * @since 3.0.0 + * @return array[] Array of arrays of mu-plugin data, keyed by plugin file name. See get_plugin_data(). + */ + function get_mu_plugins() + { + } + /** + * Declares a callback to sort array by a 'Name' key. + * + * @since 3.1.0 + * + * @access private + * + * @param array $a array with 'Name' key. + * @param array $b array with 'Name' key. + * @return int Return 0 or 1 based on two string comparison. + */ + function _sort_uname_callback($a, $b) + { + } + /** + * Checks the wp-content directory and retrieve all drop-ins with any plugin data. + * + * @since 3.0.0 + * @return array[] Array of arrays of dropin plugin data, keyed by plugin file name. See get_plugin_data(). + */ + function get_dropins() + { + } + /** + * Returns drop-ins that WordPress uses. + * + * Includes Multisite drop-ins only when is_multisite() + * + * @since 3.0.0 + * @return array[] Key is file name. The value is an array, with the first value the + * purpose of the drop-in and the second value the name of the constant that must be + * true for the drop-in to be used, or true if no constant is required. + */ + function _get_dropins() + { + } + /** + * Determines whether a plugin is active. + * + * Only plugins installed in the plugins/ folder can be active. + * + * Plugins in the mu-plugins/ folder can't be "activated," so this function will + * return false for those plugins. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.5.0 + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @return bool True, if in the active plugins list. False, not in the list. + */ + function is_plugin_active($plugin) + { + } + /** + * Determines whether the plugin is inactive. + * + * Reverse of is_plugin_active(). Used as a callback. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 3.1.0 + * + * @see is_plugin_active() + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @return bool True if inactive. False if active. + */ + function is_plugin_inactive($plugin) + { + } + /** + * Determines whether the plugin is active for the entire network. + * + * Only plugins installed in the plugins/ folder can be active. + * + * Plugins in the mu-plugins/ folder can't be "activated," so this function will + * return false for those plugins. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 3.0.0 + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @return bool True if active for the network, otherwise false. + */ + function is_plugin_active_for_network($plugin) + { + } + /** + * Checks for "Network: true" in the plugin header to see if this should + * be activated only as a network wide plugin. The plugin would also work + * when Multisite is not enabled. + * + * Checks for "Site Wide Only: true" for backward compatibility. + * + * @since 3.0.0 + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @return bool True if plugin is network only, false otherwise. + */ + function is_network_only_plugin($plugin) + { + } + /** + * Attempts activation of plugin in a "sandbox" and redirects on success. + * + * A plugin that is already activated will not attempt to be activated again. + * + * The way it works is by setting the redirection to the error before trying to + * include the plugin file. If the plugin fails, then the redirection will not + * be overwritten with the success message. Also, the options will not be + * updated and the activation hook will not be called on plugin error. + * + * It should be noted that in no way the below code will actually prevent errors + * within the file. The code should not be used elsewhere to replicate the + * "sandbox", which uses redirection to work. + * {@source 13 1} + * + * If any errors are found or text is outputted, then it will be captured to + * ensure that the success redirection will update the error redirection. + * + * @since 2.5.0 + * @since 5.2.0 Test for WordPress version and PHP version compatibility. + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @param string $redirect Optional. URL to redirect to. + * @param bool $network_wide Optional. Whether to enable the plugin for all sites in the network + * or just the current site. Multisite only. Default false. + * @param bool $silent Optional. Whether to prevent calling activation hooks. Default false. + * @return null|WP_Error Null on success, WP_Error on invalid file. + */ + function activate_plugin($plugin, $redirect = '', $network_wide = \false, $silent = \false) + { + } + /** + * Deactivates a single plugin or multiple plugins. + * + * The deactivation hook is disabled by the plugin upgrader by using the $silent + * parameter. + * + * @since 2.5.0 + * + * @param string|string[] $plugins Single plugin or list of plugins to deactivate. + * @param bool $silent Prevent calling deactivation hooks. Default false. + * @param bool|null $network_wide Whether to deactivate the plugin for all sites in the network. + * A value of null will deactivate plugins for both the network + * and the current site. Multisite only. Default null. + */ + function deactivate_plugins($plugins, $silent = \false, $network_wide = \null) + { + } + /** + * Activates multiple plugins. + * + * When WP_Error is returned, it does not mean that one of the plugins had + * errors. It means that one or more of the plugin file paths were invalid. + * + * The execution will be halted as soon as one of the plugins has an error. + * + * @since 2.6.0 + * + * @param string|string[] $plugins Single plugin or list of plugins to activate. + * @param string $redirect Redirect to page after successful activation. + * @param bool $network_wide Whether to enable the plugin for all sites in the network. + * Default false. + * @param bool $silent Prevent calling activation hooks. Default false. + * @return bool|WP_Error True when finished or WP_Error if there were errors during a plugin activation. + */ + function activate_plugins($plugins, $redirect = '', $network_wide = \false, $silent = \false) + { + } + /** + * Removes directory and files of a plugin for a list of plugins. + * + * @since 2.6.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param string[] $plugins List of plugin paths to delete, relative to the plugins directory. + * @param string $deprecated Not used. + * @return bool|null|WP_Error True on success, false if `$plugins` is empty, `WP_Error` on failure. + * `null` if filesystem credentials are required to proceed. + */ + function delete_plugins($plugins, $deprecated = '') + { + } + /** + * Validates active plugins. + * + * Validate all active plugins, deactivates invalid and + * returns an array of deactivated ones. + * + * @since 2.5.0 + * @return WP_Error[] Array of plugin errors keyed by plugin file name. + */ + function validate_active_plugins() + { + } + /** + * Validates the plugin path. + * + * Checks that the main plugin file exists and is a valid plugin. See validate_file(). + * + * @since 2.5.0 + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @return int|WP_Error 0 on success, WP_Error on failure. + */ + function validate_plugin($plugin) + { + } + /** + * Validates the plugin requirements for WordPress version and PHP version. + * + * Uses the information from `Requires at least` and `Requires PHP` headers + * defined in the plugin's main PHP file. + * + * @since 5.2.0 + * @since 5.3.0 Added support for reading the headers from the plugin's + * main PHP file, with `readme.txt` as a fallback. + * @since 5.8.0 Removed support for using `readme.txt` as a fallback. + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @return true|WP_Error True if requirements are met, WP_Error on failure. + */ + function validate_plugin_requirements($plugin) + { + } + /** + * Determines whether the plugin can be uninstalled. + * + * @since 2.7.0 + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @return bool Whether plugin can be uninstalled. + */ + function is_uninstallable_plugin($plugin) + { + } + /** + * Uninstalls a single plugin. + * + * Calls the uninstall hook, if it is available. + * + * @since 2.7.0 + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @return true|void True if a plugin's uninstall.php file has been found and included. + * Void otherwise. + */ + function uninstall_plugin($plugin) + { + } + // + // Menu. + // + /** + * Adds a top-level menu page. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 1.5.0 + * + * @global array $menu + * @global array $admin_page_hooks + * @global array $_registered_pages + * @global array $_parent_pages + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by. Should be unique for this menu page and only + * include lowercase alphanumeric, dashes, and underscores characters to be compatible + * with sanitize_key(). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param string $icon_url Optional. The URL to the icon to be used for this menu. + * * Pass a base64-encoded SVG using a data URI, which will be colored to match + * the color scheme. This should begin with 'data:image/svg+xml;base64,'. + * * Pass the name of a Dashicons helper class to use a font icon, + * e.g. 'dashicons-chart-pie'. + * * Pass 'none' to leave div.wp-menu-image empty so an icon can be added via CSS. + * @param int|float $position Optional. The position in the menu order this item should appear. + * @return string The resulting page's hook_suffix. + */ + function add_menu_page($page_title, $menu_title, $capability, $menu_slug, $callback = '', $icon_url = '', $position = \null) + { + } + /** + * Adds a submenu page. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 1.5.0 + * @since 5.3.0 Added the `$position` parameter. + * + * @global array $submenu + * @global array $menu + * @global array $_wp_real_parent_file + * @global bool $_wp_submenu_nopriv + * @global array $_registered_pages + * @global array $_parent_pages + * + * @param string $parent_slug The slug name for the parent menu (or the file name of a standard + * WordPress admin page). + * @param string $page_title The text to be displayed in the title tags of the page when the menu + * is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by. Should be unique for this menu + * and only include lowercase alphanumeric, dashes, and underscores characters + * to be compatible with sanitize_key(). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param int|float $position Optional. The position in the menu order this item should appear. + * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + */ + function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = \null) + { + } + /** + * Adds a submenu page to the Tools main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 1.5.0 + * @since 5.3.0 Added the `$position` parameter. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param int $position Optional. The position in the menu order this item should appear. + * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + */ + function add_management_page($page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = \null) + { + } + /** + * Adds a submenu page to the Settings main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 1.5.0 + * @since 5.3.0 Added the `$position` parameter. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param int $position Optional. The position in the menu order this item should appear. + * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + */ + function add_options_page($page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = \null) + { + } + /** + * Adds a submenu page to the Appearance main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 2.0.0 + * @since 5.3.0 Added the `$position` parameter. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param int $position Optional. The position in the menu order this item should appear. + * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + */ + function add_theme_page($page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = \null) + { + } + /** + * Adds a submenu page to the Plugins main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 3.0.0 + * @since 5.3.0 Added the `$position` parameter. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param int $position Optional. The position in the menu order this item should appear. + * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + */ + function add_plugins_page($page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = \null) + { + } + /** + * Adds a submenu page to the Users/Profile main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 2.1.3 + * @since 5.3.0 Added the `$position` parameter. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param int $position Optional. The position in the menu order this item should appear. + * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + */ + function add_users_page($page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = \null) + { + } + /** + * Adds a submenu page to the Dashboard main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 2.7.0 + * @since 5.3.0 Added the `$position` parameter. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param int $position Optional. The position in the menu order this item should appear. + * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + */ + function add_dashboard_page($page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = \null) + { + } + /** + * Adds a submenu page to the Posts main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 2.7.0 + * @since 5.3.0 Added the `$position` parameter. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param int $position Optional. The position in the menu order this item should appear. + * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + */ + function add_posts_page($page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = \null) + { + } + /** + * Adds a submenu page to the Media main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 2.7.0 + * @since 5.3.0 Added the `$position` parameter. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param int $position Optional. The position in the menu order this item should appear. + * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + */ + function add_media_page($page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = \null) + { + } + /** + * Adds a submenu page to the Links main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 2.7.0 + * @since 5.3.0 Added the `$position` parameter. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param int $position Optional. The position in the menu order this item should appear. + * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + */ + function add_links_page($page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = \null) + { + } + /** + * Adds a submenu page to the Pages main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 2.7.0 + * @since 5.3.0 Added the `$position` parameter. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param int $position Optional. The position in the menu order this item should appear. + * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + */ + function add_pages_page($page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = \null) + { + } + /** + * Adds a submenu page to the Comments main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @since 2.7.0 + * @since 5.3.0 Added the `$position` parameter. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. + * @param string $menu_title The text to be used for the menu. + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). + * @param callable $callback Optional. The function to be called to output the content for this page. + * @param int $position Optional. The position in the menu order this item should appear. + * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + */ + function add_comments_page($page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = \null) + { + } + /** + * Removes a top-level admin menu. + * + * Example usage: + * + * - `remove_menu_page( 'tools.php' )` + * - `remove_menu_page( 'plugin_menu_slug' )` + * + * @since 3.1.0 + * + * @global array $menu + * + * @param string $menu_slug The slug of the menu. + * @return array|false The removed menu on success, false if not found. + */ + function remove_menu_page($menu_slug) + { + } + /** + * Removes an admin submenu. + * + * Example usage: + * + * - `remove_submenu_page( 'themes.php', 'nav-menus.php' )` + * - `remove_submenu_page( 'tools.php', 'plugin_submenu_slug' )` + * - `remove_submenu_page( 'plugin_menu_slug', 'plugin_submenu_slug' )` + * + * @since 3.1.0 + * + * @global array $submenu + * + * @param string $menu_slug The slug for the parent menu. + * @param string $submenu_slug The slug of the submenu. + * @return array|false The removed submenu on success, false if not found. + */ + function remove_submenu_page($menu_slug, $submenu_slug) + { + } + /** + * Gets the URL to access a particular menu page based on the slug it was registered with. + * + * If the slug hasn't been registered properly, no URL will be returned. + * + * @since 3.0.0 + * + * @global array $_parent_pages + * + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). + * @param bool $display Optional. Whether or not to display the URL. Default true. + * @return string The menu page URL. + */ + function menu_page_url($menu_slug, $display = \true) + { + } + // + // Pluggable Menu Support -- Private. + // + /** + * Gets the parent file of the current admin page. + * + * @since 1.5.0 + * + * @global string $parent_file + * @global array $menu + * @global array $submenu + * @global string $pagenow The filename of the current screen. + * @global string $typenow The post type of the current screen. + * @global string $plugin_page + * @global array $_wp_real_parent_file + * @global array $_wp_menu_nopriv + * @global array $_wp_submenu_nopriv + * + * @param string $parent_page Optional. The slug name for the parent menu (or the file name + * of a standard WordPress admin page). Default empty string. + * @return string The parent file of the current admin page. + */ + function get_admin_page_parent($parent_page = '') + { + } + /** + * Gets the title of the current admin page. + * + * @since 1.5.0 + * + * @global string $title + * @global array $menu + * @global array $submenu + * @global string $pagenow The filename of the current screen. + * @global string $typenow The post type of the current screen. + * @global string $plugin_page + * + * @return string The title of the current admin page. + */ + function get_admin_page_title() + { + } + /** + * Gets the hook attached to the administrative page of a plugin. + * + * @since 1.5.0 + * + * @param string $plugin_page The slug name of the plugin page. + * @param string $parent_page The slug name for the parent menu (or the file name of a standard + * WordPress admin page). + * @return string|null Hook attached to the plugin page, null otherwise. + */ + function get_plugin_page_hook($plugin_page, $parent_page) + { + } + /** + * Gets the hook name for the administrative page of a plugin. + * + * @since 1.5.0 + * + * @global array $admin_page_hooks + * + * @param string $plugin_page The slug name of the plugin page. + * @param string $parent_page The slug name for the parent menu (or the file name of a standard + * WordPress admin page). + * @return string Hook name for the plugin page. + */ + function get_plugin_page_hookname($plugin_page, $parent_page) + { + } + /** + * Determines whether the current user can access the current admin page. + * + * @since 1.5.0 + * + * @global string $pagenow The filename of the current screen. + * @global array $menu + * @global array $submenu + * @global array $_wp_menu_nopriv + * @global array $_wp_submenu_nopriv + * @global string $plugin_page + * @global array $_registered_pages + * + * @return bool True if the current user can access the admin page, false otherwise. + */ + function user_can_access_admin_page() + { + } + /* Allowed list functions */ + /** + * Refreshes the value of the allowed options list available via the 'allowed_options' hook. + * + * See the {@see 'allowed_options'} filter. + * + * @since 2.7.0 + * @since 5.5.0 `$new_whitelist_options` was renamed to `$new_allowed_options`. + * Please consider writing more inclusive code. + * + * @global array $new_allowed_options + * + * @param array $options + * @return array + */ + function option_update_filter($options) + { + } + /** + * Adds an array of options to the list of allowed options. + * + * @since 5.5.0 + * + * @global array $allowed_options + * + * @param array $new_options + * @param string|array $options + * @return array + */ + function add_allowed_options($new_options, $options = '') + { + } + /** + * Removes a list of options from the allowed options list. + * + * @since 5.5.0 + * + * @global array $allowed_options + * + * @param array $del_options + * @param string|array $options + * @return array + */ + function remove_allowed_options($del_options, $options = '') + { + } + /** + * Outputs nonce, action, and option_page fields for a settings page. + * + * @since 2.7.0 + * + * @param string $option_group A settings group name. This should match the group name + * used in register_setting(). + */ + function settings_fields($option_group) + { + } + /** + * Clears the plugins cache used by get_plugins() and by default, the plugin updates cache. + * + * @since 3.7.0 + * + * @param bool $clear_update_cache Whether to clear the plugin updates cache. Default true. + */ + function wp_clean_plugins_cache($clear_update_cache = \true) + { + } + /** + * Loads a given plugin attempt to generate errors. + * + * @since 3.0.0 + * @since 4.4.0 Function was moved into the `wp-admin/includes/plugin.php` file. + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + */ + function plugin_sandbox_scrape($plugin) + { + } + /** + * Declares a helper function for adding content to the Privacy Policy Guide. + * + * Plugins and themes should suggest text for inclusion in the site's privacy policy. + * The suggested text should contain information about any functionality that affects user privacy, + * and will be shown on the Privacy Policy Guide screen. + * + * A plugin or theme can use this function multiple times as long as it will help to better present + * the suggested policy content. For example modular plugins such as WooCommerse or Jetpack + * can add or remove suggested content depending on the modules/extensions that are enabled. + * For more information see the Plugin Handbook: + * https://developer.wordpress.org/plugins/privacy/suggesting-text-for-the-site-privacy-policy/. + * + * The HTML contents of the `$policy_text` supports use of a specialized `.privacy-policy-tutorial` + * CSS class which can be used to provide supplemental information. Any content contained within + * HTML elements that have the `.privacy-policy-tutorial` CSS class applied will be omitted + * from the clipboard when the section content is copied. + * + * Intended for use with the `'admin_init'` action. + * + * @since 4.9.6 + * + * @param string $plugin_name The name of the plugin or theme that is suggesting content + * for the site's privacy policy. + * @param string $policy_text The suggested content for inclusion in the policy. + */ + function wp_add_privacy_policy_content($plugin_name, $policy_text) + { + } + /** + * Determines whether a plugin is technically active but was paused while + * loading. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 5.2.0 + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @return bool True, if in the list of paused plugins. False, if not in the list. + */ + function is_plugin_paused($plugin) + { + } + /** + * Gets the error that was recorded for a paused plugin. + * + * @since 5.2.0 + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @return array|false Array of error information as returned by `error_get_last()`, + * or false if none was recorded. + */ + function wp_get_plugin_error($plugin) + { + } + /** + * Tries to resume a single plugin. + * + * If a redirect was provided, we first ensure the plugin does not throw fatal + * errors anymore. + * + * The way it works is by setting the redirection to the error before trying to + * include the plugin file. If the plugin fails, then the redirection will not + * be overwritten with the success message and the plugin will not be resumed. + * + * @since 5.2.0 + * + * @param string $plugin Single plugin to resume. + * @param string $redirect Optional. URL to redirect to. Default empty string. + * @return bool|WP_Error True on success, false if `$plugin` was not paused, + * `WP_Error` on failure. + */ + function resume_plugin($plugin, $redirect = '') + { + } + /** + * Renders an admin notice in case some plugins have been paused due to errors. + * + * @since 5.2.0 + * + * @global string $pagenow The filename of the current screen. + */ + function paused_plugins_notice() + { + } + /** + * Renders an admin notice when a plugin was deactivated during an update. + * + * Displays an admin notice in case a plugin has been deactivated during an + * upgrade due to incompatibility with the current version of WordPress. + * + * @since 5.8.0 + * @access private + * + * @global string $pagenow The filename of the current screen. + * @global string $wp_version The WordPress version string. + */ + function deactivated_plugins_notice() + { + } + /** + * WordPress Post Administration API. + * + * @package WordPress + * @subpackage Administration + */ + /** + * Renames `$_POST` data from form names to DB post columns. + * + * Manipulates `$_POST` directly. + * + * @since 2.6.0 + * + * @param bool $update Whether the post already exists. + * @param array|null $post_data Optional. The array of post data to process. + * Defaults to the `$_POST` superglobal. + * @return array|WP_Error Array of post data on success, WP_Error on failure. + */ + function _wp_translate_postdata($update = \false, $post_data = \null) + { + } + /** + * Returns only allowed post data fields. + * + * @since 5.0.1 + * + * @param array|WP_Error|null $post_data The array of post data to process, or an error object. + * Defaults to the `$_POST` superglobal. + * @return array|WP_Error Array of post data on success, WP_Error on failure. + */ + function _wp_get_allowed_postdata($post_data = \null) + { + } + /** + * Updates an existing post with values provided in `$_POST`. + * + * If post data is passed as an argument, it is treated as an array of data + * keyed appropriately for turning into a post object. + * + * If post data is not passed, the `$_POST` global variable is used instead. + * + * @since 1.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array|null $post_data Optional. The array of post data to process. + * Defaults to the `$_POST` superglobal. + * @return int Post ID. + */ + function edit_post($post_data = \null) + { + } + /** + * Processes the post data for the bulk editing of posts. + * + * Updates all bulk edited posts/pages, adding (but not removing) tags and + * categories. Skips pages when they would be their own parent or child. + * + * @since 2.7.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array|null $post_data Optional. The array of post data to process. + * Defaults to the `$_POST` superglobal. + * @return array + */ + function bulk_edit_posts($post_data = \null) + { + } + /** + * Returns default post information to use when populating the "Write Post" form. + * + * @since 2.0.0 + * + * @param string $post_type Optional. A post type string. Default 'post'. + * @param bool $create_in_db Optional. Whether to insert the post into database. Default false. + * @return WP_Post Post object containing all the default post data as attributes + */ + function get_default_post_to_edit($post_type = 'post', $create_in_db = \false) + { + } + /** + * Determines if a post exists based on title, content, date and type. + * + * @since 2.0.0 + * @since 5.2.0 Added the `$type` parameter. + * @since 5.8.0 Added the `$status` parameter. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $title Post title. + * @param string $content Optional. Post content. + * @param string $date Optional. Post date. + * @param string $type Optional. Post type. + * @param string $status Optional. Post status. + * @return int Post ID if post exists, 0 otherwise. + */ + function post_exists($title, $content = '', $date = '', $type = '', $status = '') + { + } + /** + * Creates a new post from the "Write Post" form using `$_POST` information. + * + * @since 2.1.0 + * + * @global WP_User $current_user + * + * @return int|WP_Error Post ID on success, WP_Error on failure. + */ + function wp_write_post() + { + } + /** + * Calls wp_write_post() and handles the errors. + * + * @since 2.0.0 + * + * @return int|void Post ID on success, void on failure. + */ + function write_post() + { + } + // + // Post Meta. + // + /** + * Adds post meta data defined in the `$_POST` superglobal for a post with given ID. + * + * @since 1.2.0 + * + * @param int $post_ID + * @return int|bool + */ + function add_meta($post_ID) + { + } + /** + * Deletes post meta data by meta ID. + * + * @since 1.2.0 + * + * @param int $mid + * @return bool + */ + function delete_meta($mid) + { + } + /** + * Returns a list of previously defined keys. + * + * @since 1.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return string[] Array of meta key names. + */ + function get_meta_keys() + { + } + /** + * Returns post meta data by meta ID. + * + * @since 2.1.0 + * + * @param int $mid + * @return object|bool + */ + function get_post_meta_by_id($mid) + { + } + /** + * Returns meta data for the given post ID. + * + * @since 1.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $postid A post ID. + * @return array[] { + * Array of meta data arrays for the given post ID. + * + * @type array ...$0 { + * Associative array of meta data. + * + * @type string $meta_key Meta key. + * @type mixed $meta_value Meta value. + * @type string $meta_id Meta ID as a numeric string. + * @type string $post_id Post ID as a numeric string. + * } + * } + * @phpstan-return array<int|string, array{ + * meta_key: string, + * meta_value: mixed, + * meta_id: string, + * post_id: string, + * }> + */ + function has_meta($postid) + { + } + /** + * Updates post meta data by meta ID. + * + * @since 1.2.0 + * + * @param int $meta_id Meta ID. + * @param string $meta_key Meta key. Expect slashed. + * @param string $meta_value Meta value. Expect slashed. + * @return bool + */ + function update_meta($meta_id, $meta_key, $meta_value) + { + } + // + // Private. + // + /** + * Replaces hrefs of attachment anchors with up-to-date permalinks. + * + * @since 2.3.0 + * @access private + * + * @param int|object $post Post ID or post object. + * @return void|int|WP_Error Void if nothing fixed. 0 or WP_Error on update failure. The post ID on update success. + */ + function _fix_attachment_links($post) + { + } + /** + * Returns all the possible statuses for a post type. + * + * @since 2.5.0 + * + * @param string $type The post_type you want the statuses for. Default 'post'. + * @return string[] An array of all the statuses for the supplied post type. + */ + function get_available_post_statuses($type = 'post') + { + } + /** + * Runs the query to fetch the posts for listing on the edit posts page. + * + * @since 2.5.0 + * + * @param array|false $q Optional. Array of query variables to use to build the query. + * Defaults to the `$_GET` superglobal. + * @return array + */ + function wp_edit_posts_query($q = \false) + { + } + /** + * Returns the query variables for the current attachments request. + * + * @since 4.2.0 + * + * @param array|false $q Optional. Array of query variables to use to build the query. + * Defaults to the `$_GET` superglobal. + * @return array The parsed query vars. + */ + function wp_edit_attachments_query_vars($q = \false) + { + } + /** + * Executes a query for attachments. An array of WP_Query arguments + * can be passed in, which will override the arguments set by this function. + * + * @since 2.5.0 + * + * @param array|false $q Optional. Array of query variables to use to build the query. + * Defaults to the `$_GET` superglobal. + * @return array + */ + function wp_edit_attachments_query($q = \false) + { + } + /** + * Returns the list of classes to be used by a meta box. + * + * @since 2.5.0 + * + * @param string $box_id Meta box ID (used in the 'id' attribute for the meta box). + * @param string $screen_id The screen on which the meta box is shown. + * @return string Space-separated string of class names. + */ + function postbox_classes($box_id, $screen_id) + { + } + /** + * Returns a sample permalink based on the post name. + * + * @since 2.5.0 + * + * @param int|WP_Post $post Post ID or post object. + * @param string|null $title Optional. Title to override the post's current title + * when generating the post name. Default null. + * @param string|null $name Optional. Name to override the post name. Default null. + * @return array { + * Array containing the sample permalink with placeholder for the post name, and the post name. + * + * @type string $0 The permalink with placeholder for the post name. + * @type string $1 The post name. + * } + * @phpstan-return array{ + * 0: string, + * 1: string, + * } + */ + function get_sample_permalink($post, $title = \null, $name = \null) + { + } + /** + * Returns the HTML of the sample permalink slug editor. + * + * @since 2.5.0 + * + * @param int|WP_Post $post Post ID or post object. + * @param string|null $new_title Optional. New title. Default null. + * @param string|null $new_slug Optional. New slug. Default null. + * @return string The HTML of the sample permalink slug editor. + */ + function get_sample_permalink_html($post, $new_title = \null, $new_slug = \null) + { + } + /** + * Returns HTML for the post thumbnail meta box. + * + * @since 2.9.0 + * + * @param int|null $thumbnail_id Optional. Thumbnail attachment ID. Default null. + * @param int|WP_Post|null $post Optional. The post ID or object associated + * with the thumbnail. Defaults to global $post. + * @return string The post thumbnail HTML. + */ + function _wp_post_thumbnail_html($thumbnail_id = \null, $post = \null) + { + } + /** + * Determines whether the post is currently being edited by another user. + * + * @since 2.5.0 + * + * @param int|WP_Post $post ID or object of the post to check for editing. + * @return int|false ID of the user with lock. False if the post does not exist, post is not locked, + * the user with lock does not exist, or the post is locked by current user. + */ + function wp_check_post_lock($post) + { + } + /** + * Marks the post as currently being edited by the current user. + * + * @since 2.5.0 + * + * @param int|WP_Post $post ID or object of the post being edited. + * @return array|false { + * Array of the lock time and user ID. False if the post does not exist, or there + * is no current user. + * + * @type int $0 The current time as a Unix timestamp. + * @type int $1 The ID of the current user. + * } + * @phpstan-return false|array{ + * 0: int, + * 1: int, + * } + */ + function wp_set_post_lock($post) + { + } + /** + * Outputs the HTML for the notice to say that someone else is editing or has taken over editing of this post. + * + * @since 2.8.5 + */ + function _admin_notice_post_locked() + { + } + /** + * Creates autosave data for the specified post from `$_POST` data. + * + * @since 2.6.0 + * + * @param array|int $post_data Associative array containing the post data, or integer post ID. + * If a numeric post ID is provided, will use the `$_POST` superglobal. + * @return int|WP_Error The autosave revision ID. WP_Error or 0 on error. + */ + function wp_create_post_autosave($post_data) + { + } + /** + * Saves a draft or manually autosaves for the purpose of showing a post preview. + * + * @since 2.7.0 + * + * @return string URL to redirect to show the preview. + */ + function post_preview() + { + } + /** + * Saves a post submitted with XHR. + * + * Intended for use with heartbeat and autosave.js + * + * @since 3.9.0 + * + * @param array $post_data Associative array of the submitted post data. + * @return mixed The value 0 or WP_Error on failure. The saved post ID on success. + * The ID can be the draft post_id or the autosave revision post_id. + */ + function wp_autosave($post_data) + { + } + /** + * Redirects to previous page. + * + * @since 2.7.0 + * + * @param int $post_id Optional. Post ID. + */ + function redirect_post($post_id = '') + { + } + /** + * Sanitizes POST values from a checkbox taxonomy metabox. + * + * @since 5.1.0 + * + * @param string $taxonomy The taxonomy name. + * @param array $terms Raw term data from the 'tax_input' field. + * @return int[] Array of sanitized term IDs. + */ + function taxonomy_meta_box_sanitize_cb_checkboxes($taxonomy, $terms) + { + } + /** + * Sanitizes POST values from an input taxonomy metabox. + * + * @since 5.1.0 + * + * @param string $taxonomy The taxonomy name. + * @param array|string $terms Raw term data from the 'tax_input' field. + * @return array + */ + function taxonomy_meta_box_sanitize_cb_input($taxonomy, $terms) + { + } + /** + * Prepares server-registered blocks for the block editor. + * + * Returns an associative array of registered block data keyed by block name. Data includes properties + * of a block relevant for client registration. + * + * @since 5.0.0 + * + * @return array An associative array of registered block data. + */ + function get_block_editor_server_block_settings() + { + } + /** + * Renders the meta boxes forms. + * + * @since 5.0.0 + */ + function the_block_editor_meta_boxes() + { + } + /** + * Renders the hidden form required for the meta boxes form. + * + * @since 5.0.0 + * + * @param WP_Post $post Current post object. + */ + function the_block_editor_meta_box_post_form_hidden_fields($post) + { + } + /** + * Disables block editor for wp_navigation type posts so they can be managed via the UI. + * + * @since 5.9.0 + * @access private + * + * @param bool $value Whether the CPT supports block editor or not. + * @param string $post_type Post type. + * @return bool Whether the block editor should be disabled or not. + */ + function _disable_block_editor_for_navigation_post_type($value, $post_type) + { + } + /** + * This callback disables the content editor for wp_navigation type posts. + * Content editor cannot handle wp_navigation type posts correctly. + * We cannot disable the "editor" feature in the wp_navigation's CPT definition + * because it disables the ability to save navigation blocks via REST API. + * + * @since 5.9.0 + * @access private + * + * @param WP_Post $post An instance of WP_Post class. + */ + function _disable_content_editor_for_navigation_post_type($post) + { + } + /** + * This callback enables content editor for wp_navigation type posts. + * We need to enable it back because we disable it to hide + * the content editor for wp_navigation type posts. + * + * @since 5.9.0 + * @access private + * + * @see _disable_content_editor_for_navigation_post_type + * + * @param WP_Post $post An instance of WP_Post class. + */ + function _enable_content_editor_for_navigation_post_type($post) + { + } + /** + * WordPress Administration Privacy Tools API. + * + * @package WordPress + * @subpackage Administration + */ + /** + * Resend an existing request and return the result. + * + * @since 4.9.6 + * @access private + * + * @param int $request_id Request ID. + * @return true|WP_Error Returns true if sending the email was successful, or a WP_Error object. + */ + function _wp_privacy_resend_request($request_id) + { + } + /** + * Marks a request as completed by the admin and logs the current timestamp. + * + * @since 4.9.6 + * @access private + * + * @param int $request_id Request ID. + * @return int|WP_Error Request ID on success, or a WP_Error on failure. + */ + function _wp_privacy_completed_request($request_id) + { + } + /** + * Handle list table actions. + * + * @since 4.9.6 + * @access private + */ + function _wp_personal_data_handle_actions() + { + } + /** + * Cleans up failed and expired requests before displaying the list table. + * + * @since 4.9.6 + * @access private + */ + function _wp_personal_data_cleanup_requests() + { + } + /** + * Generate a single group for the personal data export report. + * + * @since 4.9.6 + * @since 5.4.0 Added the `$group_id` and `$groups_count` parameters. + * + * @param array $group_data { + * The group data to render. + * + * @type string $group_label The user-facing heading for the group, e.g. 'Comments'. + * @type array $items { + * An array of group items. + * + * @type array $group_item_data { + * An array of name-value pairs for the item. + * + * @type string $name The user-facing name of an item name-value pair, e.g. 'IP Address'. + * @type string $value The user-facing value of an item data pair, e.g. '50.60.70.0'. + * } + * } + * } + * @param string $group_id The group identifier. + * @param int $groups_count The number of all groups + * @return string The HTML for this group and its items. + * @phpstan-param array{ + * group_label?: string, + * items?: array{ + * group_item_data: array{ + * name: string, + * value: string, + * }, + * }, + * } $group_data + */ + function wp_privacy_generate_personal_data_export_group_html($group_data, $group_id = '', $groups_count = 1) + { + } + /** + * Generate the personal data export file. + * + * @since 4.9.6 + * + * @param int $request_id The export request ID. + */ + function wp_privacy_generate_personal_data_export_file($request_id) + { + } + /** + * Send an email to the user with a link to the personal data export file + * + * @since 4.9.6 + * + * @param int $request_id The request ID for this personal data export. + * @return true|WP_Error True on success or `WP_Error` on failure. + */ + function wp_privacy_send_personal_data_export_email($request_id) + { + } + /** + * Intercept personal data exporter page Ajax responses in order to assemble the personal data export file. + * + * @since 4.9.6 + * + * @see 'wp_privacy_personal_data_export_page' + * + * @param array $response The response from the personal data exporter for the given page. + * @param int $exporter_index The index of the personal data exporter. Begins at 1. + * @param string $email_address The email address of the user whose personal data this is. + * @param int $page The page of personal data for this exporter. Begins at 1. + * @param int $request_id The request ID for this personal data export. + * @param bool $send_as_email Whether the final results of the export should be emailed to the user. + * @param string $exporter_key The slug (key) of the exporter. + * @return array The filtered response. + */ + function wp_privacy_process_personal_data_export_page($response, $exporter_index, $email_address, $page, $request_id, $send_as_email, $exporter_key) + { + } + /** + * Mark erasure requests as completed after processing is finished. + * + * This intercepts the Ajax responses to personal data eraser page requests, and + * monitors the status of a request. Once all of the processing has finished, the + * request is marked as completed. + * + * @since 4.9.6 + * + * @see 'wp_privacy_personal_data_erasure_page' + * + * @param array $response The response from the personal data eraser for + * the given page. + * @param int $eraser_index The index of the personal data eraser. Begins + * at 1. + * @param string $email_address The email address of the user whose personal + * data this is. + * @param int $page The page of personal data for this eraser. + * Begins at 1. + * @param int $request_id The request ID for this personal data erasure. + * @return array The filtered response. + */ + function wp_privacy_process_personal_data_erasure_page($response, $eraser_index, $email_address, $page, $request_id) + { + } + /** + * WordPress Administration Revisions API + * + * @package WordPress + * @subpackage Administration + * @since 3.6.0 + */ + /** + * Get the revision UI diff. + * + * @since 3.6.0 + * + * @param WP_Post|int $post The post object or post ID. + * @param int $compare_from The revision ID to compare from. + * @param int $compare_to The revision ID to come to. + * @return array|false Associative array of a post's revisioned fields and their diffs. + * Or, false on failure. + */ + function wp_get_revision_ui_diff($post, $compare_from, $compare_to) + { + } + /** + * Prepare revisions for JavaScript. + * + * @since 3.6.0 + * + * @param WP_Post|int $post The post object or post ID. + * @param int $selected_revision_id The selected revision ID. + * @param int $from Optional. The revision ID to compare from. + * @return array An associative array of revision data and related settings. + */ + function wp_prepare_revisions_for_js($post, $selected_revision_id, $from = \null) + { + } + /** + * Print JavaScript templates required for the revisions experience. + * + * @since 4.1.0 + * + * @global WP_Post $post Global post object. + */ + function wp_print_revision_templates() + { + } + /** + * Retrieve the SQL for creating database tables. + * + * @since 3.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $scope Optional. The tables for which to retrieve SQL. Can be all, global, ms_global, or blog tables. Defaults to all. + * @param int $blog_id Optional. The site ID for which to retrieve SQL. Default is the current site ID. + * @return string The SQL needed to create the requested tables. + */ + function wp_get_db_schema($scope = 'all', $blog_id = \null) + { + } + /** + * Create WordPress options and set the default values. + * + * @since 1.5.0 + * @since 5.1.0 The $options parameter has been added. + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global int $wp_db_version WordPress database version. + * @global int $wp_current_db_version The old (current) database version. + * + * @param array $options Optional. Custom option $key => $value pairs to use. Default empty array. + */ + function populate_options(array $options = array()) + { + } + /** + * Execute WordPress role creation for the various WordPress versions. + * + * @since 2.0.0 + */ + function populate_roles() + { + } + /** + * Create the roles for WordPress 2.0 + * + * @since 2.0.0 + */ + function populate_roles_160() + { + } + /** + * Create and modify WordPress roles for WordPress 2.1. + * + * @since 2.1.0 + */ + function populate_roles_210() + { + } + /** + * Create and modify WordPress roles for WordPress 2.3. + * + * @since 2.3.0 + */ + function populate_roles_230() + { + } + /** + * Create and modify WordPress roles for WordPress 2.5. + * + * @since 2.5.0 + */ + function populate_roles_250() + { + } + /** + * Create and modify WordPress roles for WordPress 2.6. + * + * @since 2.6.0 + */ + function populate_roles_260() + { + } + /** + * Create and modify WordPress roles for WordPress 2.7. + * + * @since 2.7.0 + */ + function populate_roles_270() + { + } + /** + * Create and modify WordPress roles for WordPress 2.8. + * + * @since 2.8.0 + */ + function populate_roles_280() + { + } + /** + * Create and modify WordPress roles for WordPress 3.0. + * + * @since 3.0.0 + */ + function populate_roles_300() + { + } + /** + * Install Network. + * + * @since 3.0.0 + */ + function install_network() + { + } + /** + * Populate network settings. + * + * @since 3.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global object $current_site + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param int $network_id ID of network to populate. + * @param string $domain The domain name for the network. Example: "example.com". + * @param string $email Email address for the network administrator. + * @param string $site_name The name of the network. + * @param string $path Optional. The path to append to the network's domain name. Default '/'. + * @param bool $subdomain_install Optional. Whether the network is a subdomain installation or a subdirectory installation. + * Default false, meaning the network is a subdirectory installation. + * @return bool|WP_Error True on success, or WP_Error on warning (with the installation otherwise successful, + * so the error code must be checked) or failure. + */ + function populate_network($network_id = 1, $domain = '', $email = '', $site_name = '', $path = '/', $subdomain_install = \false) + { + } + /** + * Creates WordPress network meta and sets the default values. + * + * @since 5.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global int $wp_db_version WordPress database version. + * + * @param int $network_id Network ID to populate meta for. + * @param array $meta Optional. Custom meta $key => $value pairs to use. Default empty array. + */ + function populate_network_meta($network_id, array $meta = array()) + { + } + /** + * Creates WordPress site meta and sets the default values. + * + * @since 5.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $site_id Site ID to populate meta for. + * @param array $meta Optional. Custom meta $key => $value pairs to use. Default empty array. + */ + function populate_site_meta($site_id, array $meta = array()) + { + } + /** + * WordPress Administration Screen API. + * + * @package WordPress + * @subpackage Administration + */ + /** + * Get the column headers for a screen + * + * @since 2.7.0 + * + * @param string|WP_Screen $screen The screen you want the headers for + * @return string[] The column header labels keyed by column ID. + */ + function get_column_headers($screen) + { + } + /** + * Get a list of hidden columns. + * + * @since 2.7.0 + * + * @param string|WP_Screen $screen The screen you want the hidden columns for + * @return string[] Array of IDs of hidden columns. + */ + function get_hidden_columns($screen) + { + } + /** + * Prints the meta box preferences for screen meta. + * + * @since 2.7.0 + * + * @global array $wp_meta_boxes + * + * @param WP_Screen $screen + */ + function meta_box_prefs($screen) + { + } + /** + * Gets an array of IDs of hidden meta boxes. + * + * @since 2.7.0 + * + * @param string|WP_Screen $screen Screen identifier + * @return string[] IDs of hidden meta boxes. + */ + function get_hidden_meta_boxes($screen) + { + } + /** + * Register and configure an admin screen option + * + * @since 3.1.0 + * + * @param string $option An option name. + * @param mixed $args Option-dependent arguments. + */ + function add_screen_option($option, $args = array()) + { + } + /** + * Get the current screen object + * + * @since 3.1.0 + * + * @global WP_Screen $current_screen WordPress current screen object. + * + * @return WP_Screen|null Current screen object or null when screen not defined. + */ + function get_current_screen() + { + } + /** + * Set the current screen object + * + * @since 3.0.0 + * + * @param string|WP_Screen $hook_name Optional. The hook name (also known as the hook suffix) used to determine the screen, + * or an existing screen object. + */ + function set_current_screen($hook_name = '') + { + } + /** + * WordPress Taxonomy Administration API. + * + * @package WordPress + * @subpackage Administration + */ + // + // Category. + // + /** + * Checks whether a category exists. + * + * @since 2.0.0 + * + * @see term_exists() + * + * @param int|string $cat_name Category name. + * @param int $category_parent Optional. ID of parent category. + * @return string|null Returns the category ID as a numeric string if the pairing exists, null if not. + */ + function category_exists($cat_name, $category_parent = \null) + { + } + /** + * Gets category object for given ID and 'edit' filter context. + * + * @since 2.0.0 + * + * @param int $id + * @return object + */ + function get_category_to_edit($id) + { + } + /** + * Adds a new category to the database if it does not already exist. + * + * @since 2.0.0 + * + * @param int|string $cat_name Category name. + * @param int $category_parent Optional. ID of parent category. + * @return int|WP_Error + */ + function wp_create_category($cat_name, $category_parent = 0) + { + } + /** + * Creates categories for the given post. + * + * @since 2.0.0 + * + * @param string[] $categories Array of category names to create. + * @param int $post_id Optional. The post ID. Default empty. + * @return int[] Array of IDs of categories assigned to the given post. + */ + function wp_create_categories($categories, $post_id = '') + { + } + /** + * Updates an existing Category or creates a new Category. + * + * @since 2.0.0 + * @since 2.5.0 $wp_error parameter was added. + * @since 3.0.0 The 'taxonomy' argument was added. + * + * @param array $catarr { + * Array of arguments for inserting a new category. + * + * @type int $cat_ID Category ID. A non-zero value updates an existing category. + * Default 0. + * @type string $taxonomy Taxonomy slug. Default 'category'. + * @type string $cat_name Category name. Default empty. + * @type string $category_description Category description. Default empty. + * @type string $category_nicename Category nice (display) name. Default empty. + * @type int|string $category_parent Category parent ID. Default empty. + * } + * @param bool $wp_error Optional. Default false. + * @return int|WP_Error The ID number of the new or updated Category on success. Zero or a WP_Error on failure, + * depending on param `$wp_error`. + * @phpstan-param array{ + * cat_ID?: int, + * taxonomy?: string, + * cat_name?: string, + * category_description?: string, + * category_nicename?: string, + * category_parent?: int|string, + * } $catarr + */ + function wp_insert_category($catarr, $wp_error = \false) + { + } + /** + * Aliases wp_insert_category() with minimal args. + * + * If you want to update only some fields of an existing category, call this + * function with only the new values set inside $catarr. + * + * @since 2.0.0 + * + * @param array $catarr The 'cat_ID' value is required. All other keys are optional. + * @return int|false The ID number of the new or updated Category on success. Zero or FALSE on failure. + */ + function wp_update_category($catarr) + { + } + // + // Tags. + // + /** + * Checks whether a post tag with a given name exists. + * + * @since 2.3.0 + * + * @param int|string $tag_name + * @return mixed Returns null if the term does not exist. + * Returns an array of the term ID and the term taxonomy ID if the pairing exists. + * Returns 0 if term ID 0 is passed to the function. + */ + function tag_exists($tag_name) + { + } + /** + * Adds a new tag to the database if it does not already exist. + * + * @since 2.3.0 + * + * @param int|string $tag_name + * @return array|WP_Error + */ + function wp_create_tag($tag_name) + { + } + /** + * Gets comma-separated list of tags available to edit. + * + * @since 2.3.0 + * + * @param int $post_id + * @param string $taxonomy Optional. The taxonomy for which to retrieve terms. Default 'post_tag'. + * @return string|false|WP_Error + */ + function get_tags_to_edit($post_id, $taxonomy = 'post_tag') + { + } + /** + * Gets comma-separated list of terms available to edit for the given post ID. + * + * @since 2.8.0 + * + * @param int $post_id + * @param string $taxonomy Optional. The taxonomy for which to retrieve terms. Default 'post_tag'. + * @return string|false|WP_Error + */ + function get_terms_to_edit($post_id, $taxonomy = 'post_tag') + { + } + /** + * Adds a new term to the database if it does not already exist. + * + * @since 2.8.0 + * + * @param string $tag_name The term name. + * @param string $taxonomy Optional. The taxonomy within which to create the term. Default 'post_tag'. + * @return array|WP_Error + */ + function wp_create_term($tag_name, $taxonomy = 'post_tag') + { + } + // + // Category Checklists. + // + /** + * Outputs an unordered list of checkbox input elements labeled with category names. + * + * @since 2.5.1 + * + * @see wp_terms_checklist() + * + * @param int $post_id Optional. Post to generate a categories checklist for. Default 0. + * $selected_cats must not be an array. Default 0. + * @param int $descendants_and_self Optional. ID of the category to output along with its descendants. + * Default 0. + * @param int[]|false $selected_cats Optional. Array of category IDs to mark as checked. Default false. + * @param int[]|false $popular_cats Optional. Array of category IDs to receive the "popular-category" class. + * Default false. + * @param Walker $walker Optional. Walker object to use to build the output. + * Default is a Walker_Category_Checklist instance. + * @param bool $checked_ontop Optional. Whether to move checked items out of the hierarchy and to + * the top of the list. Default true. + */ + function wp_category_checklist($post_id = 0, $descendants_and_self = 0, $selected_cats = \false, $popular_cats = \false, $walker = \null, $checked_ontop = \true) + { + } + /** + * Outputs an unordered list of checkbox input elements labelled with term names. + * + * Taxonomy-independent version of wp_category_checklist(). + * + * @since 3.0.0 + * @since 4.4.0 Introduced the `$echo` argument. + * + * @param int $post_id Optional. Post ID. Default 0. + * @param array|string $args { + * Optional. Array or string of arguments for generating a terms checklist. Default empty array. + * + * @type int $descendants_and_self ID of the category to output along with its descendants. + * Default 0. + * @type int[] $selected_cats Array of category IDs to mark as checked. Default false. + * @type int[] $popular_cats Array of category IDs to receive the "popular-category" class. + * Default false. + * @type Walker $walker Walker object to use to build the output. Default empty which + * results in a Walker_Category_Checklist instance being used. + * @type string $taxonomy Taxonomy to generate the checklist for. Default 'category'. + * @type bool $checked_ontop Whether to move checked items out of the hierarchy and to + * the top of the list. Default true. + * @type bool $echo Whether to echo the generated markup. False to return the markup instead + * of echoing it. Default true. + * } + * @return string HTML list of input elements. + * @phpstan-param array{ + * descendants_and_self?: int, + * selected_cats?: int[], + * popular_cats?: int[], + * walker?: Walker, + * taxonomy?: string, + * checked_ontop?: bool, + * echo?: bool, + * } $args + */ + function wp_terms_checklist($post_id = 0, $args = array()) + { + } + /** + * Retrieves a list of the most popular terms from the specified taxonomy. + * + * If the `$display` argument is true then the elements for a list of checkbox + * `<input>` elements labelled with the names of the selected terms is output. + * If the `$post_ID` global is not empty then the terms associated with that + * post will be marked as checked. + * + * @since 2.5.0 + * + * @param string $taxonomy Taxonomy to retrieve terms from. + * @param int $default_term Optional. Not used. + * @param int $number Optional. Number of terms to retrieve. Default 10. + * @param bool $display Optional. Whether to display the list as well. Default true. + * @return int[] Array of popular term IDs. + */ + function wp_popular_terms_checklist($taxonomy, $default_term = 0, $number = 10, $display = \true) + { + } + /** + * Outputs a link category checklist element. + * + * @since 2.5.1 + * + * @param int $link_id + */ + function wp_link_category_checklist($link_id = 0) + { + } + /** + * Adds hidden fields with the data for use in the inline editor for posts and pages. + * + * @since 2.7.0 + * + * @param WP_Post $post Post object. + */ + function get_inline_data($post) + { + } + /** + * Outputs the in-line comment reply-to form in the Comments list table. + * + * @since 2.7.0 + * + * @global WP_List_Table $wp_list_table + * + * @param int $position + * @param bool $checkbox + * @param string $mode + * @param bool $table_row + */ + function wp_comment_reply($position = 1, $checkbox = \false, $mode = 'single', $table_row = \true) + { + } + /** + * Outputs 'undo move to Trash' text for comments. + * + * @since 2.9.0 + */ + function wp_comment_trashnotice() + { + } + /** + * Outputs a post's public meta data in the Custom Fields meta box. + * + * @since 1.2.0 + * + * @param array $meta + */ + function list_meta($meta) + { + } + /** + * Outputs a single row of public meta data in the Custom Fields meta box. + * + * @since 2.5.0 + * + * @param array $entry + * @param int $count + * @return string + */ + function _list_meta_row($entry, &$count) + { + } + /** + * Prints the form in the Custom Fields meta box. + * + * @since 1.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param WP_Post $post Optional. The post being edited. + */ + function meta_form($post = \null) + { + } + /** + * Prints out HTML form date elements for editing post or comment publish date. + * + * @since 0.71 + * @since 4.4.0 Converted to use get_comment() instead of the global `$comment`. + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @param int|bool $edit Accepts 1|true for editing the date, 0|false for adding the date. + * @param int|bool $for_post Accepts 1|true for applying the date to a post, 0|false for a comment. + * @param int $tab_index The tabindex attribute to add. Default 0. + * @param int|bool $multi Optional. Whether the additional fields and buttons should be added. + * Default 0|false. + */ + function touch_time($edit = 1, $for_post = 1, $tab_index = 0, $multi = 0) + { + } + /** + * Prints out option HTML elements for the page templates drop-down. + * + * @since 1.5.0 + * @since 4.7.0 Added the `$post_type` parameter. + * + * @param string $default_template Optional. The template file name. Default empty. + * @param string $post_type Optional. Post type to get templates for. Default 'post'. + */ + function page_template_dropdown($default_template = '', $post_type = 'page') + { + } + /** + * Prints out option HTML elements for the page parents drop-down. + * + * @since 1.5.0 + * @since 4.4.0 `$post` argument was added. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $default_page Optional. The default page ID to be pre-selected. Default 0. + * @param int $parent_page Optional. The parent page ID. Default 0. + * @param int $level Optional. Page depth level. Default 0. + * @param int|WP_Post $post Post ID or WP_Post object. + * @return void|false Void on success, false if the page has no children. + */ + function parent_dropdown($default_page = 0, $parent_page = 0, $level = 0, $post = \null) + { + } + /** + * Prints out option HTML elements for role selectors. + * + * @since 2.1.0 + * + * @param string $selected Slug for the role that should be already selected. + */ + function wp_dropdown_roles($selected = '') + { + } + /** + * Outputs the form used by the importers to accept the data to be imported. + * + * @since 2.0.0 + * + * @param string $action The action attribute for the form. + */ + function wp_import_upload_form($action) + { + } + /** + * Adds a meta box to one or more screens. + * + * @since 2.5.0 + * @since 4.4.0 The `$screen` parameter now accepts an array of screen IDs. + * + * @global array $wp_meta_boxes + * + * @param string $id Meta box ID (used in the 'id' attribute for the meta box). + * @param string $title Title of the meta box. + * @param callable $callback Function that fills the box with the desired content. + * The function should echo its output. + * @param string|array|WP_Screen $screen Optional. The screen or screens on which to show the box + * (such as a post type, 'link', or 'comment'). Accepts a single + * screen ID, WP_Screen object, or array of screen IDs. Default + * is the current screen. If you have used add_menu_page() or + * add_submenu_page() to create a new screen (and hence screen_id), + * make sure your menu slug conforms to the limits of sanitize_key() + * otherwise the 'screen' menu may not correctly render on your page. + * @param string $context Optional. The context within the screen where the box + * should display. Available contexts vary from screen to + * screen. Post edit screen contexts include 'normal', 'side', + * and 'advanced'. Comments screen contexts include 'normal' + * and 'side'. Menus meta boxes (accordion sections) all use + * the 'side' context. Global default is 'advanced'. + * @param string $priority Optional. The priority within the context where the box should show. + * Accepts 'high', 'core', 'default', or 'low'. Default 'default'. + * @param array $callback_args Optional. Data that should be set as the $args property + * of the box array (which is the second parameter passed + * to your callback). Default null. + * @phpstan-param "normal"|"side"|"advanced" $context + * @phpstan-param "high"|"core"|"default"|"low" $priority + * @phpstan-return void + */ + function add_meta_box($id, $title, $callback, $screen = \null, $context = 'advanced', $priority = 'default', $callback_args = \null) + { + } + /** + * Renders a "fake" meta box with an information message, + * shown on the block editor, when an incompatible meta box is found. + * + * @since 5.0.0 + * + * @param mixed $data_object The data object being rendered on this screen. + * @param array $box { + * Custom formats meta box arguments. + * + * @type string $id Meta box 'id' attribute. + * @type string $title Meta box title. + * @type callable $old_callback The original callback for this meta box. + * @type array $args Extra meta box arguments. + * } + * @phpstan-param array{ + * id?: string, + * title?: string, + * old_callback?: callable, + * args?: array, + * } $box + */ + function do_block_editor_incompatible_meta_box($data_object, $box) + { + } + /** + * Internal helper function to find the plugin from a meta box callback. + * + * @since 5.0.0 + * + * @access private + * + * @param callable $callback The callback function to check. + * @return array|null The plugin that the callback belongs to, or null if it doesn't belong to a plugin. + */ + function _get_plugin_from_callback($callback) + { + } + /** + * Meta-Box template function. + * + * @since 2.5.0 + * + * @global array $wp_meta_boxes + * + * @param string|WP_Screen $screen The screen identifier. If you have used add_menu_page() or + * add_submenu_page() to create a new screen (and hence screen_id) + * make sure your menu slug conforms to the limits of sanitize_key() + * otherwise the 'screen' menu may not correctly render on your page. + * @param string $context The screen context for which to display meta boxes. + * @param mixed $data_object Gets passed to the meta box callback function as the first parameter. + * Often this is the object that's the focus of the current screen, + * for example a `WP_Post` or `WP_Comment` object. + * @return int Number of meta_boxes. + */ + function do_meta_boxes($screen, $context, $data_object) + { + } + /** + * Removes a meta box from one or more screens. + * + * @since 2.6.0 + * @since 4.4.0 The `$screen` parameter now accepts an array of screen IDs. + * + * @global array $wp_meta_boxes + * + * @param string $id Meta box ID (used in the 'id' attribute for the meta box). + * @param string|array|WP_Screen $screen The screen or screens on which the meta box is shown (such as a + * post type, 'link', or 'comment'). Accepts a single screen ID, + * WP_Screen object, or array of screen IDs. + * @param string $context The context within the screen where the box is set to display. + * Contexts vary from screen to screen. Post edit screen contexts + * include 'normal', 'side', and 'advanced'. Comments screen contexts + * include 'normal' and 'side'. Menus meta boxes (accordion sections) + * all use the 'side' context. + * @phpstan-param "normal"|"side"|"advanced" $context + * @phpstan-return void + */ + function remove_meta_box($id, $screen, $context) + { + } + /** + * Meta Box Accordion Template Function. + * + * Largely made up of abstracted code from do_meta_boxes(), this + * function serves to build meta boxes as list items for display as + * a collapsible accordion. + * + * @since 3.6.0 + * + * @uses global $wp_meta_boxes Used to retrieve registered meta boxes. + * + * @param string|object $screen The screen identifier. + * @param string $context The screen context for which to display accordion sections. + * @param mixed $data_object Gets passed to the section callback function as the first parameter. + * @return int Number of meta boxes as accordion sections. + */ + function do_accordion_sections($screen, $context, $data_object) + { + } + /** + * Adds a new section to a settings page. + * + * Part of the Settings API. Use this to define new settings sections for an admin page. + * Show settings sections in your admin page callback function with do_settings_sections(). + * Add settings fields to your section with add_settings_field(). + * + * The $callback argument should be the name of a function that echoes out any + * content you want to show at the top of the settings section before the actual + * fields. It can output nothing if you want. + * + * @since 2.7.0 + * @since 6.1.0 Added an `$args` parameter for the section's HTML wrapper and class name. + * + * @global array $wp_settings_sections Storage array of all settings sections added to admin pages. + * + * @param string $id Slug-name to identify the section. Used in the 'id' attribute of tags. + * @param string $title Formatted title of the section. Shown as the heading for the section. + * @param callable $callback Function that echos out any content at the top of the section (between heading and fields). + * @param string $page The slug-name of the settings page on which to show the section. Built-in pages include + * 'general', 'reading', 'writing', 'discussion', 'media', etc. Create your own using + * add_options_page(); + * @param array $args { + * Arguments used to create the settings section. + * + * @type string $before_section HTML content to prepend to the section's HTML output. + * Receives the section's class name as `%s`. Default empty. + * @type string $after_section HTML content to append to the section's HTML output. Default empty. + * @type string $section_class The class name to use for the section. Default empty. + * } + * @phpstan-param array{ + * before_section?: string, + * after_section?: string, + * section_class?: string, + * } $args + */ + function add_settings_section($id, $title, $callback, $page, $args = array()) + { + } + /** + * Adds a new field to a section of a settings page. + * + * Part of the Settings API. Use this to define a settings field that will show + * as part of a settings section inside a settings page. The fields are shown using + * do_settings_fields() in do_settings_sections(). + * + * The $callback argument should be the name of a function that echoes out the + * HTML input tags for this setting field. Use get_option() to retrieve existing + * values to show. + * + * @since 2.7.0 + * @since 4.2.0 The `$class` argument was added. + * + * @global array $wp_settings_fields Storage array of settings fields and info about their pages/sections. + * + * @param string $id Slug-name to identify the field. Used in the 'id' attribute of tags. + * @param string $title Formatted title of the field. Shown as the label for the field + * during output. + * @param callable $callback Function that fills the field with the desired form inputs. The + * function should echo its output. + * @param string $page The slug-name of the settings page on which to show the section + * (general, reading, writing, ...). + * @param string $section Optional. The slug-name of the section of the settings page + * in which to show the box. Default 'default'. + * @param array $args { + * Optional. Extra arguments that get passed to the callback function. + * + * @type string $label_for When supplied, the setting title will be wrapped + * in a `<label>` element, its `for` attribute populated + * with this value. + * @type string $class CSS Class to be added to the `<tr>` element when the + * field is output. + * } + * @phpstan-param array{ + * label_for?: string, + * class?: string, + * } $args + */ + function add_settings_field($id, $title, $callback, $page, $section = 'default', $args = array()) + { + } + /** + * Prints out all settings sections added to a particular settings page. + * + * Part of the Settings API. Use this in a settings page callback function + * to output all the sections and fields that were added to that $page with + * add_settings_section() and add_settings_field() + * + * @global array $wp_settings_sections Storage array of all settings sections added to admin pages. + * @global array $wp_settings_fields Storage array of settings fields and info about their pages/sections. + * @since 2.7.0 + * + * @param string $page The slug name of the page whose settings sections you want to output. + */ + function do_settings_sections($page) + { + } + /** + * Prints out the settings fields for a particular settings section. + * + * Part of the Settings API. Use this in a settings page to output + * a specific section. Should normally be called by do_settings_sections() + * rather than directly. + * + * @global array $wp_settings_fields Storage array of settings fields and their pages/sections. + * + * @since 2.7.0 + * + * @param string $page Slug title of the admin page whose settings fields you want to show. + * @param string $section Slug title of the settings section whose fields you want to show. + */ + function do_settings_fields($page, $section) + { + } + /** + * Registers a settings error to be displayed to the user. + * + * Part of the Settings API. Use this to show messages to users about settings validation + * problems, missing settings or anything else. + * + * Settings errors should be added inside the $sanitize_callback function defined in + * register_setting() for a given setting to give feedback about the submission. + * + * By default messages will show immediately after the submission that generated the error. + * Additional calls to settings_errors() can be used to show errors even when the settings + * page is first accessed. + * + * @since 3.0.0 + * @since 5.3.0 Added `warning` and `info` as possible values for `$type`. + * + * @global array[] $wp_settings_errors Storage array of errors registered during this pageload + * + * @param string $setting Slug title of the setting to which this error applies. + * @param string $code Slug-name to identify the error. Used as part of 'id' attribute in HTML output. + * @param string $message The formatted message text to display to the user (will be shown inside styled + * `<div>` and `<p>` tags). + * @param string $type Optional. Message type, controls HTML class. Possible values include 'error', + * 'success', 'warning', 'info'. Default 'error'. + */ + function add_settings_error($setting, $code, $message, $type = 'error') + { + } + /** + * Fetches settings errors registered by add_settings_error(). + * + * Checks the $wp_settings_errors array for any errors declared during the current + * pageload and returns them. + * + * If changes were just submitted ($_GET['settings-updated']) and settings errors were saved + * to the 'settings_errors' transient then those errors will be returned instead. This + * is used to pass errors back across pageloads. + * + * Use the $sanitize argument to manually re-sanitize the option before returning errors. + * This is useful if you have errors or notices you want to show even when the user + * hasn't submitted data (i.e. when they first load an options page, or in the {@see 'admin_notices'} + * action hook). + * + * @since 3.0.0 + * + * @global array[] $wp_settings_errors Storage array of errors registered during this pageload + * + * @param string $setting Optional. Slug title of a specific setting whose errors you want. + * @param bool $sanitize Optional. Whether to re-sanitize the setting value before returning errors. + * @return array { + * Array of settings errors. + * + * @type string $setting Slug title of the setting to which this error applies. + * @type string $code Slug-name to identify the error. Used as part of 'id' attribute in HTML output. + * @type string $message The formatted message text to display to the user (will be shown inside styled + * `<div>` and `<p>` tags). + * @type string $type Optional. Message type, controls HTML class. Possible values include 'error', + * 'success', 'warning', 'info'. Default 'error'. + * } + * @phpstan-return array{ + * setting: string, + * code: string, + * message: string, + * type: string, + * } + */ + function get_settings_errors($setting = '', $sanitize = \false) + { + } + /** + * Displays settings errors registered by add_settings_error(). + * + * Part of the Settings API. Outputs a div for each error retrieved by + * get_settings_errors(). + * + * This is called automatically after a settings page based on the + * Settings API is submitted. Errors should be added during the validation + * callback function for a setting defined in register_setting(). + * + * The $sanitize option is passed into get_settings_errors() and will + * re-run the setting sanitization + * on its current value. + * + * The $hide_on_update option will cause errors to only show when the settings + * page is first loaded. if the user has already saved new values it will be + * hidden to avoid repeating messages already shown in the default error + * reporting after submission. This is useful to show general errors like + * missing settings when the user arrives at the settings page. + * + * @since 3.0.0 + * @since 5.3.0 Legacy `error` and `updated` CSS classes are mapped to + * `notice-error` and `notice-success`. + * + * @param string $setting Optional slug title of a specific setting whose errors you want. + * @param bool $sanitize Whether to re-sanitize the setting value before returning errors. + * @param bool $hide_on_update If set to true errors will not be shown if the settings page has + * already been submitted. + */ + function settings_errors($setting = '', $sanitize = \false, $hide_on_update = \false) + { + } + /** + * Outputs the modal window used for attaching media to posts or pages in the media-listing screen. + * + * @since 2.7.0 + * + * @param string $found_action + */ + function find_posts_div($found_action = '') + { + } + /** + * Displays the post password. + * + * The password is passed through esc_attr() to ensure that it is safe for placing in an HTML attribute. + * + * @since 2.7.0 + */ + function the_post_password() + { + } + /** + * Gets the post title. + * + * The post title is fetched and if it is blank then a default string is + * returned. + * + * @since 2.7.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @return string The post title if set. + */ + function _draft_or_post_title($post = 0) + { + } + /** + * Displays the search query. + * + * A simple wrapper to display the "s" parameter in a `GET` URI. This function + * should only be used when the_search_query() cannot. + * + * @since 2.7.0 + */ + function _admin_search_query() + { + } + /** + * Generic Iframe header for use with Thickbox. + * + * @since 2.7.0 + * + * @global string $hook_suffix + * @global string $admin_body_class + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @param string $title Optional. Title of the Iframe page. Default empty. + * @param bool $deprecated Not used. + */ + function iframe_header($title = '', $deprecated = \false) + { + } + /** + * Generic Iframe footer for use with Thickbox. + * + * @since 2.7.0 + */ + function iframe_footer() + { + } + /** + * Echoes or returns the post states as HTML. + * + * @since 2.7.0 + * @since 5.3.0 Added the `$display` parameter and a return value. + * + * @see get_post_states() + * + * @param WP_Post $post The post to retrieve states for. + * @param bool $display Optional. Whether to display the post states as an HTML string. + * Default true. + * @return string Post states string. + */ + function _post_states($post, $display = \true) + { + } + /** + * Retrieves an array of post states from a post. + * + * @since 5.3.0 + * + * @param WP_Post $post The post to retrieve states for. + * @return string[] Array of post state labels keyed by their state. + */ + function get_post_states($post) + { + } + /** + * Outputs the attachment media states as HTML. + * + * @since 3.2.0 + * @since 5.6.0 Added the `$display` parameter and a return value. + * + * @param WP_Post $post The attachment post to retrieve states for. + * @param bool $display Optional. Whether to display the post states as an HTML string. + * Default true. + * @return string Media states string. + */ + function _media_states($post, $display = \true) + { + } + /** + * Retrieves an array of media states from an attachment. + * + * @since 5.6.0 + * + * @param WP_Post $post The attachment to retrieve states for. + * @return string[] Array of media state labels keyed by their state. + */ + function get_media_states($post) + { + } + /** + * Tests support for compressing JavaScript from PHP. + * + * Outputs JavaScript that tests if compression from PHP works as expected + * and sets an option with the result. Has no effect when the current user + * is not an administrator. To run the test again the option 'can_compress_scripts' + * has to be deleted. + * + * @since 2.8.0 + */ + function compression_test() + { + } + /** + * Echoes a submit button, with provided text and appropriate class(es). + * + * @since 3.1.0 + * + * @see get_submit_button() + * + * @param string $text The text of the button (defaults to 'Save Changes') + * @param string $type Optional. The type and CSS class(es) of the button. Core values + * include 'primary', 'small', and 'large'. Default 'primary'. + * @param string $name The HTML name of the submit button. Defaults to "submit". If no + * id attribute is given in $other_attributes below, $name will be + * used as the button's id. + * @param bool $wrap True if the output button should be wrapped in a paragraph tag, + * false otherwise. Defaults to true. + * @param array|string $other_attributes Other attributes that should be output with the button, mapping + * attributes to their values, such as setting tabindex to 1, etc. + * These key/value attribute pairs will be output as attribute="value", + * where attribute is the key. Other attributes can also be provided + * as a string such as 'tabindex="1"', though the array format is + * preferred. Default null. + */ + function submit_button($text = \null, $type = 'primary', $name = 'submit', $wrap = \true, $other_attributes = \null) + { + } + /** + * Returns a submit button, with provided text and appropriate class. + * + * @since 3.1.0 + * + * @param string $text Optional. The text of the button. Default 'Save Changes'. + * @param string $type Optional. The type and CSS class(es) of the button. Core values + * include 'primary', 'small', and 'large'. Default 'primary large'. + * @param string $name Optional. The HTML name of the submit button. Defaults to "submit". + * If no id attribute is given in $other_attributes below, `$name` will + * be used as the button's id. Default 'submit'. + * @param bool $wrap Optional. True if the output button should be wrapped in a paragraph + * tag, false otherwise. Default true. + * @param array|string $other_attributes Optional. Other attributes that should be output with the button, + * mapping attributes to their values, such as `array( 'tabindex' => '1' )`. + * These attributes will be output as `attribute="value"`, such as + * `tabindex="1"`. Other attributes can also be provided as a string such + * as `tabindex="1"`, though the array format is typically cleaner. + * Default empty. + * @return string Submit button HTML. + */ + function get_submit_button($text = '', $type = 'primary large', $name = 'submit', $wrap = \true, $other_attributes = '') + { + } + /** + * Prints out the beginning of the admin HTML header. + * + * @global bool $is_IE + */ + function _wp_admin_html_begin() + { + } + /** + * Converts a screen string to a screen object. + * + * @since 3.0.0 + * + * @param string $hook_name The hook name (also known as the hook suffix) used to determine the screen. + * @return WP_Screen Screen object. + */ + function convert_to_screen($hook_name) + { + } + /** + * Outputs the HTML for restoring the post data from DOM storage + * + * @since 3.6.0 + * @access private + */ + function _local_storage_notice() + { + } + /** + * Outputs a HTML element with a star rating for a given rating. + * + * Outputs a HTML element with the star rating exposed on a 0..5 scale in + * half star increments (ie. 1, 1.5, 2 stars). Optionally, if specified, the + * number of ratings may also be displayed by passing the $number parameter. + * + * @since 3.8.0 + * @since 4.4.0 Introduced the `echo` parameter. + * + * @param array $args { + * Optional. Array of star ratings arguments. + * + * @type int|float $rating The rating to display, expressed in either a 0.5 rating increment, + * or percentage. Default 0. + * @type string $type Format that the $rating is in. Valid values are 'rating' (default), + * or, 'percent'. Default 'rating'. + * @type int $number The number of ratings that makes up this rating. Default 0. + * @type bool $echo Whether to echo the generated markup. False to return the markup instead + * of echoing it. Default true. + * } + * @return string Star rating HTML. + * @phpstan-param array{ + * rating?: int|float, + * type?: string, + * number?: int, + * echo?: bool, + * } $args + */ + function wp_star_rating($args = array()) + { + } + /** + * Outputs a notice when editing the page for posts (internal use only). + * + * @ignore + * @since 4.2.0 + */ + function _wp_posts_page_notice() + { + } + /** + * Outputs a notice when editing the page for posts in the block editor (internal use only). + * + * @ignore + * @since 5.8.0 + */ + function _wp_block_editor_posts_page_notice() + { + } + /** + * Retrieves the list of WordPress theme features (aka theme tags). + * + * @since 2.8.0 + * + * @deprecated 3.1.0 Use get_theme_feature_list() instead. + * + * @return array + */ + function install_themes_feature_list() + { + } + /** + * Displays search form for searching themes. + * + * @since 2.8.0 + * + * @param bool $type_selector + */ + function install_theme_search_form($type_selector = \true) + { + } + /** + * Displays tags filter for themes. + * + * @since 2.8.0 + */ + function install_themes_dashboard() + { + } + /** + * Displays a form to upload themes from zip files. + * + * @since 2.8.0 + */ + function install_themes_upload() + { + } + /** + * Prints a theme on the Install Themes pages. + * + * @deprecated 3.4.0 + * + * @global WP_Theme_Install_List_Table $wp_list_table + * + * @param object $theme + */ + function display_theme($theme) + { + } + /** + * Displays theme content based on theme list. + * + * @since 2.8.0 + * + * @global WP_Theme_Install_List_Table $wp_list_table + */ + function display_themes() + { + } + /** + * Displays theme information in dialog box form. + * + * @since 2.8.0 + * + * @global WP_Theme_Install_List_Table $wp_list_table + */ + function install_theme_information() + { + } + /** + * WordPress Theme Administration API + * + * @package WordPress + * @subpackage Administration + */ + /** + * Removes a theme. + * + * @since 2.8.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param string $stylesheet Stylesheet of the theme to delete. + * @param string $redirect Redirect to page when complete. + * @return bool|null|WP_Error True on success, false if `$stylesheet` is empty, WP_Error on failure. + * Null if filesystem credentials are required to proceed. + */ + function delete_theme($stylesheet, $redirect = '') + { + } + /** + * Gets the page templates available in this theme. + * + * @since 1.5.0 + * @since 4.7.0 Added the `$post_type` parameter. + * + * @param WP_Post|null $post Optional. The post being edited, provided for context. + * @param string $post_type Optional. Post type to get the templates for. Default 'page'. + * @return string[] Array of template file names keyed by the template header name. + */ + function get_page_templates($post = \null, $post_type = 'page') + { + } + /** + * Tidies a filename for url display by the theme file editor. + * + * @since 2.9.0 + * @access private + * + * @param string $fullpath Full path to the theme file + * @param string $containingfolder Path of the theme parent folder + * @return string + */ + function _get_template_edit_filename($fullpath, $containingfolder) + { + } + /** + * Check if there is an update for a theme available. + * + * Will display link, if there is an update available. + * + * @since 2.7.0 + * + * @see get_theme_update_available() + * + * @param WP_Theme $theme Theme data object. + */ + function theme_update_available($theme) + { + } + /** + * Retrieves the update link if there is a theme update available. + * + * Will return a link if there is an update available. + * + * @since 3.8.0 + * + * @param WP_Theme $theme WP_Theme object. + * @return string|false HTML for the update link, or false if invalid info was passed. + */ + function get_theme_update_available($theme) + { + } + /** + * Retrieves list of WordPress theme features (aka theme tags). + * + * @since 3.1.0 + * @since 3.2.0 Added 'Gray' color and 'Featured Image Header', 'Featured Images', + * 'Full Width Template', and 'Post Formats' features. + * @since 3.5.0 Added 'Flexible Header' feature. + * @since 3.8.0 Renamed 'Width' filter to 'Layout'. + * @since 3.8.0 Renamed 'Fixed Width' and 'Flexible Width' options + * to 'Fixed Layout' and 'Fluid Layout'. + * @since 3.8.0 Added 'Accessibility Ready' feature and 'Responsive Layout' option. + * @since 3.9.0 Combined 'Layout' and 'Columns' filters. + * @since 4.6.0 Removed 'Colors' filter. + * @since 4.6.0 Added 'Grid Layout' option. + * Removed 'Fixed Layout', 'Fluid Layout', and 'Responsive Layout' options. + * @since 4.6.0 Added 'Custom Logo' and 'Footer Widgets' features. + * Removed 'Blavatar' feature. + * @since 4.6.0 Added 'Blog', 'E-Commerce', 'Education', 'Entertainment', 'Food & Drink', + * 'Holiday', 'News', 'Photography', and 'Portfolio' subjects. + * Removed 'Photoblogging' and 'Seasonal' subjects. + * @since 4.9.0 Reordered the filters from 'Layout', 'Features', 'Subject' + * to 'Subject', 'Features', 'Layout'. + * @since 4.9.0 Removed 'BuddyPress', 'Custom Menu', 'Flexible Header', + * 'Front Page Posting', 'Microformats', 'RTL Language Support', + * 'Threaded Comments', and 'Translation Ready' features. + * @since 5.5.0 Added 'Block Editor Patterns', 'Block Editor Styles', + * and 'Full Site Editing' features. + * @since 5.5.0 Added 'Wide Blocks' layout option. + * @since 5.8.1 Added 'Template Editing' feature. + * @since 6.1.1 Replaced 'Full Site Editing' feature name with 'Site Editor'. + * + * @param bool $api Optional. Whether try to fetch tags from the WordPress.org API. Defaults to true. + * @return array Array of features keyed by category with translations keyed by slug. + */ + function get_theme_feature_list($api = \true) + { + } + /** + * Retrieves theme installer pages from the WordPress.org Themes API. + * + * It is possible for a theme to override the Themes API result with three + * filters. Assume this is for themes, which can extend on the Theme Info to + * offer more choices. This is very powerful and must be used with care, when + * overriding the filters. + * + * The first filter, {@see 'themes_api_args'}, is for the args and gives the action + * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that + * an object is returned. + * + * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org + * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list', + * an object MUST be passed. If `$action` is 'hot_tags', an array should be passed. + * + * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the + * response object or array, depending on the `$action` type. + * + * Supported arguments per action: + * + * | Argument Name | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list' | + * | -------------------| :------------: | :-----------------: | :--------: | :--------------: | + * | `$slug` | No | Yes | No | No | + * | `$per_page` | Yes | No | No | No | + * | `$page` | Yes | No | No | No | + * | `$number` | No | No | Yes | No | + * | `$search` | Yes | No | No | No | + * | `$tag` | Yes | No | No | No | + * | `$author` | Yes | No | No | No | + * | `$user` | Yes | No | No | No | + * | `$browse` | Yes | No | No | No | + * | `$locale` | Yes | Yes | No | No | + * | `$fields` | Yes | Yes | No | No | + * + * @since 2.8.0 + * + * @param string $action API action to perform: 'query_themes', 'theme_information', + * 'hot_tags' or 'feature_list'. + * @param array|object $args { + * Optional. Array or object of arguments to serialize for the Themes API. + * + * @type string $slug The theme slug. Default empty. + * @type int $per_page Number of themes per page. Default 24. + * @type int $page Number of current page. Default 1. + * @type int $number Number of tags to be queried. + * @type string $search A search term. Default empty. + * @type string $tag Tag to filter themes. Default empty. + * @type string $author Username of an author to filter themes. Default empty. + * @type string $user Username to query for their favorites. Default empty. + * @type string $browse Browse view: 'featured', 'popular', 'updated', 'favorites'. + * @type string $locale Locale to provide context-sensitive results. Default is the value of get_locale(). + * @type array $fields { + * Array of fields which should or should not be returned. + * + * @type bool $description Whether to return the theme full description. Default false. + * @type bool $sections Whether to return the theme readme sections: description, installation, + * FAQ, screenshots, other notes, and changelog. Default false. + * @type bool $rating Whether to return the rating in percent and total number of ratings. + * Default false. + * @type bool $ratings Whether to return the number of rating for each star (1-5). Default false. + * @type bool $downloaded Whether to return the download count. Default false. + * @type bool $downloadlink Whether to return the download link for the package. Default false. + * @type bool $last_updated Whether to return the date of the last update. Default false. + * @type bool $tags Whether to return the assigned tags. Default false. + * @type bool $homepage Whether to return the theme homepage link. Default false. + * @type bool $screenshots Whether to return the screenshots. Default false. + * @type int $screenshot_count Number of screenshots to return. Default 1. + * @type bool $screenshot_url Whether to return the URL of the first screenshot. Default false. + * @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false. + * @type bool $template Whether to return the slug of the parent theme. Default false. + * @type bool $parent Whether to return the slug, name and homepage of the parent theme. Default false. + * @type bool $versions Whether to return the list of all available versions. Default false. + * @type bool $theme_url Whether to return theme's URL. Default false. + * @type bool $extended_author Whether to return nicename or nicename and display name. Default false. + * } + * } + * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the + * {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article} + * for more information on the make-up of possible return objects depending on the value of `$action`. + * @phpstan-param object|array{ + * slug?: string, + * per_page?: int, + * page?: int, + * number?: int, + * search?: string, + * tag?: string, + * author?: string, + * user?: string, + * browse?: string, + * locale?: string, + * fields?: array{ + * description?: bool, + * sections?: bool, + * rating?: bool, + * ratings?: bool, + * downloaded?: bool, + * downloadlink?: bool, + * last_updated?: bool, + * tags?: bool, + * homepage?: bool, + * screenshots?: bool, + * screenshot_count?: int, + * screenshot_url?: bool, + * photon_screenshots?: bool, + * template?: bool, + * parent?: bool, + * versions?: bool, + * theme_url?: bool, + * extended_author?: bool, + * }, + * } $args + */ + function themes_api($action, $args = array()) + { + } + /** + * Prepares themes for JavaScript. + * + * @since 3.8.0 + * + * @param WP_Theme[] $themes Optional. Array of theme objects to prepare. + * Defaults to all allowed themes. + * + * @return array An associative array of theme data, sorted by name. + */ + function wp_prepare_themes_for_js($themes = \null) + { + } + /** + * Prints JS templates for the theme-browsing UI in the Customizer. + * + * @since 4.2.0 + */ + function customize_themes_print_templates() + { + } + /** + * Determines whether a theme is technically active but was paused while + * loading. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 5.2.0 + * + * @param string $theme Path to the theme directory relative to the themes directory. + * @return bool True, if in the list of paused themes. False, not in the list. + */ + function is_theme_paused($theme) + { + } + /** + * Gets the error that was recorded for a paused theme. + * + * @since 5.2.0 + * + * @param string $theme Path to the theme directory relative to the themes + * directory. + * @return array|false Array of error information as it was returned by + * `error_get_last()`, or false if none was recorded. + */ + function wp_get_theme_error($theme) + { + } + /** + * Tries to resume a single theme. + * + * If a redirect was provided and a functions.php file was found, we first ensure that + * functions.php file does not throw fatal errors anymore. + * + * The way it works is by setting the redirection to the error before trying to + * include the file. If the theme fails, then the redirection will not be overwritten + * with the success message and the theme will not be resumed. + * + * @since 5.2.0 + * + * @param string $theme Single theme to resume. + * @param string $redirect Optional. URL to redirect to. Default empty string. + * @return bool|WP_Error True on success, false if `$theme` was not paused, + * `WP_Error` on failure. + */ + function resume_theme($theme, $redirect = '') + { + } + /** + * Renders an admin notice in case some themes have been paused due to errors. + * + * @since 5.2.0 + * + * @global string $pagenow The filename of the current screen. + */ + function paused_themes_notice() + { + } + /** + * WordPress Translation Installation Administration API + * + * @package WordPress + * @subpackage Administration + */ + /** + * Retrieve translations from WordPress Translation API. + * + * @since 4.0.0 + * + * @param string $type Type of translations. Accepts 'plugins', 'themes', 'core'. + * @param array|object $args Translation API arguments. Optional. + * @return array|WP_Error On success an associative array of translations, WP_Error on failure. + */ + function translations_api($type, $args = \null) + { + } + /** + * Get available translations from the WordPress.org API. + * + * @since 4.0.0 + * + * @see translations_api() + * + * @return array[] Array of translations, each an array of data, keyed by the language. If the API response results + * in an error, an empty array will be returned. + */ + function wp_get_available_translations() + { + } + /** + * Output the select form for the language selection on the installation screen. + * + * @since 4.0.0 + * + * @global string $wp_local_package Locale code of the package. + * + * @param array[] $languages Array of available languages (populated via the Translation API). + */ + function wp_install_language_form($languages) + { + } + /** + * Download a language pack. + * + * @since 4.0.0 + * + * @see wp_get_available_translations() + * + * @param string $download Language code to download. + * @return string|false Returns the language code if successfully downloaded + * (or already installed), or false on failure. + */ + function wp_download_language_pack($download) + { + } + /** + * Check if WordPress has access to the filesystem without asking for + * credentials. + * + * @since 4.0.0 + * + * @return bool Returns true on success, false on failure. + */ + function wp_can_install_language_pack() + { + } + /** + * Upgrades the core of WordPress. + * + * This will create a .maintenance file at the base of the WordPress directory + * to ensure that people can not access the web site, when the files are being + * copied to their locations. + * + * The files in the `$_old_files` list will be removed and the new files + * copied from the zip file after the database is upgraded. + * + * The files in the `$_new_bundled_files` list will be added to the installation + * if the version is greater than or equal to the old version being upgraded. + * + * The steps for the upgrader for after the new release is downloaded and + * unzipped is: + * 1. Test unzipped location for select files to ensure that unzipped worked. + * 2. Create the .maintenance file in current WordPress base. + * 3. Copy new WordPress directory over old WordPress files. + * 4. Upgrade WordPress to new version. + * 4.1. Copy all files/folders other than wp-content + * 4.2. Copy any language files to WP_LANG_DIR (which may differ from WP_CONTENT_DIR + * 4.3. Copy any new bundled themes/plugins to their respective locations + * 5. Delete new WordPress directory path. + * 6. Delete .maintenance file. + * 7. Remove old files. + * 8. Delete 'update_core' option. + * + * There are several areas of failure. For instance if PHP times out before step + * 6, then you will not be able to access any portion of your site. Also, since + * the upgrade will not continue where it left off, you will not be able to + * automatically remove old files and remove the 'update_core' option. This + * isn't that bad. + * + * If the copy of the new WordPress over the old fails, then the worse is that + * the new WordPress directory will remain. + * + * If it is assumed that every file will be copied over, including plugins and + * themes, then if you edit the default theme, you should rename it, so that + * your changes remain. + * + * @since 2.7.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * @global array $_old_files + * @global array $_new_bundled_files + * @global wpdb $wpdb WordPress database abstraction object. + * @global string $wp_version + * @global string $required_php_version + * @global string $required_mysql_version + * + * @param string $from New release unzipped path. + * @param string $to Path to old WordPress installation. + * @return string|WP_Error New WordPress version on success, WP_Error on failure. + */ + function update_core($from, $to) + { + } + /** + * Redirect to the About WordPress page after a successful upgrade. + * + * This function is only needed when the existing installation is older than 3.4.0. + * + * @since 3.3.0 + * + * @global string $wp_version The WordPress version string. + * @global string $pagenow The filename of the current screen. + * @global string $action + * + * @param string $new_version + */ + function _redirect_to_about_wordpress($new_version) + { + } + /** + * Cleans up Genericons example files. + * + * @since 4.2.2 + * + * @global array $wp_theme_directories + * @global WP_Filesystem_Base $wp_filesystem + */ + function _upgrade_422_remove_genericons() + { + } + /** + * Recursively find Genericons example files in a given folder. + * + * @ignore + * @since 4.2.2 + * + * @param string $directory Directory path. Expects trailingslashed. + * @return array + */ + function _upgrade_422_find_genericons_files_in_folder($directory) + { + } + /** + * @ignore + * @since 4.4.0 + */ + function _upgrade_440_force_deactivate_incompatible_plugins() + { + } + /** + * @access private + * @ignore + * @since 5.8.0 + * @since 5.9.0 The minimum compatible version of Gutenberg is 11.9. + * @since 6.1.1 The minimum compatible version of Gutenberg is 14.1. + */ + function _upgrade_core_deactivate_incompatible_plugins() + { + } + /** + * WordPress Administration Update API + * + * @package WordPress + * @subpackage Administration + */ + /** + * Selects the first update version from the update_core option. + * + * @since 2.7.0 + * + * @return object|array|false The response from the API on success, false on failure. + */ + function get_preferred_from_update_core() + { + } + /** + * Gets available core updates. + * + * @since 2.7.0 + * + * @param array $options Set $options['dismissed'] to true to show dismissed upgrades too, + * set $options['available'] to false to skip not-dismissed updates. + * @return array|false Array of the update objects on success, false on failure. + */ + function get_core_updates($options = array()) + { + } + /** + * Gets the best available (and enabled) Auto-Update for WordPress core. + * + * If there's 1.2.3 and 1.3 on offer, it'll choose 1.3 if the installation allows it, else, 1.2.3. + * + * @since 3.7.0 + * + * @return object|false The core update offering on success, false on failure. + */ + function find_core_auto_update() + { + } + /** + * Gets and caches the checksums for the given version of WordPress. + * + * @since 3.7.0 + * + * @param string $version Version string to query. + * @param string $locale Locale to query. + * @return array|false An array of checksums on success, false on failure. + */ + function get_core_checksums($version, $locale) + { + } + /** + * Dismisses core update. + * + * @since 2.7.0 + * + * @param object $update + * @return bool + */ + function dismiss_core_update($update) + { + } + /** + * Undismisses core update. + * + * @since 2.7.0 + * + * @param string $version + * @param string $locale + * @return bool + */ + function undismiss_core_update($version, $locale) + { + } + /** + * Finds the available update for WordPress core. + * + * @since 2.7.0 + * + * @param string $version Version string to find the update for. + * @param string $locale Locale to find the update for. + * @return object|false The core update offering on success, false on failure. + */ + function find_core_update($version, $locale) + { + } + /** + * Returns core update footer message. + * + * @since 2.3.0 + * + * @param string $msg + * @return string + */ + function core_update_footer($msg = '') + { + } + /** + * Returns core update notification message. + * + * @since 2.3.0 + * + * @global string $pagenow The filename of the current screen. + * @return void|false + */ + function update_nag() + { + } + /** + * Displays WordPress version and active theme in the 'At a Glance' dashboard widget. + * + * @since 2.5.0 + */ + function update_right_now_message() + { + } + /** + * Retrieves plugins with updates available. + * + * @since 2.9.0 + * + * @return array + */ + function get_plugin_updates() + { + } + /** + * Adds a callback to display update information for plugins with updates available. + * + * @since 2.9.0 + */ + function wp_plugin_update_rows() + { + } + /** + * Displays update information for a plugin. + * + * @since 2.3.0 + * + * @param string $file Plugin basename. + * @param array $plugin_data Plugin information. + * @return void|false + */ + function wp_plugin_update_row($file, $plugin_data) + { + } + /** + * Retrieves themes with updates available. + * + * @since 2.9.0 + * + * @return array + */ + function get_theme_updates() + { + } + /** + * Adds a callback to display update information for themes with updates available. + * + * @since 3.1.0 + */ + function wp_theme_update_rows() + { + } + /** + * Displays update information for a theme. + * + * @since 3.1.0 + * + * @param string $theme_key Theme stylesheet. + * @param WP_Theme $theme Theme object. + * @return void|false + */ + function wp_theme_update_row($theme_key, $theme) + { + } + /** + * Displays maintenance nag HTML message. + * + * @since 2.7.0 + * + * @global int $upgrading + * @return void|false + */ + function maintenance_nag() + { + } + /** + * Prints the JavaScript templates for update admin notices. + * + * @since 4.6.0 + * + * Template takes one argument with four values: + * + * param {object} data { + * Arguments for admin notice. + * + * @type string id ID of the notice. + * @type string className Class names for the notice. + * @type string message The notice's message. + * @type string type The type of update the notice is for. Either 'plugin' or 'theme'. + * } + */ + function wp_print_admin_notice_templates() + { + } + /** + * Prints the JavaScript templates for update and deletion rows in list tables. + * + * @since 4.6.0 + * + * The update template takes one argument with four values: + * + * param {object} data { + * Arguments for the update row + * + * @type string slug Plugin slug. + * @type string plugin Plugin base name. + * @type string colspan The number of table columns this row spans. + * @type string content The row content. + * } + * + * The delete template takes one argument with four values: + * + * param {object} data { + * Arguments for the update row + * + * @type string slug Plugin slug. + * @type string plugin Plugin base name. + * @type string name Plugin name. + * @type string colspan The number of table columns this row spans. + * } + */ + function wp_print_update_row_templates() + { + } + /** + * Displays a notice when the user is in recovery mode. + * + * @since 5.2.0 + */ + function wp_recovery_mode_nag() + { + } + /** + * Checks whether auto-updates are enabled. + * + * @since 5.5.0 + * + * @param string $type The type of update being checked: 'theme' or 'plugin'. + * @return bool True if auto-updates are enabled for `$type`, false otherwise. + */ + function wp_is_auto_update_enabled_for_type($type) + { + } + /** + * Checks whether auto-updates are forced for an item. + * + * @since 5.6.0 + * + * @param string $type The type of update being checked: 'theme' or 'plugin'. + * @param bool|null $update Whether to update. The value of null is internally used + * to detect whether nothing has hooked into this filter. + * @param object $item The update offer. + * @return bool True if auto-updates are forced for `$item`, false otherwise. + */ + function wp_is_auto_update_forced_for_item($type, $update, $item) + { + } + /** + * Determines the appropriate auto-update message to be displayed. + * + * @since 5.5.0 + * + * @return string The update message to be shown. + */ + function wp_get_auto_update_message() + { + } + /** + * Installs the site. + * + * Runs the required functions to set up and populate the database, + * including primary admin user and initial options. + * + * @since 2.1.0 + * + * @param string $blog_title Site title. + * @param string $user_name User's username. + * @param string $user_email User's email. + * @param bool $is_public Whether the site is public. + * @param string $deprecated Optional. Not used. + * @param string $user_password Optional. User's chosen password. Default empty (random password). + * @param string $language Optional. Language chosen. Default empty. + * @return array { + * Data for the newly installed site. + * + * @type string $url The URL of the site. + * @type int $user_id The ID of the site owner. + * @type string $password The password of the site owner, if their user account didn't already exist. + * @type string $password_message The explanatory message regarding the password. + * } + * @phpstan-return array{ + * url: string, + * user_id: int, + * password: string, + * password_message: string, + * } + */ + function wp_install($blog_title, $user_name, $user_email, $is_public, $deprecated = '', $user_password = '', $language = '') + { + } + /** + * Creates the initial content for a newly-installed site. + * + * Adds the default "Uncategorized" category, the first post (with comment), + * first page, and default widgets for default theme for the current version. + * + * @since 2.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * @global string $table_prefix + * + * @param int $user_id User ID. + */ + function wp_install_defaults($user_id) + { + } + /** + * Maybe enable pretty permalinks on installation. + * + * If after enabling pretty permalinks don't work, fallback to query-string permalinks. + * + * @since 4.2.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @return bool Whether pretty permalinks are enabled. False otherwise. + */ + function wp_install_maybe_enable_pretty_permalinks() + { + } + /** + * Notifies the site admin that the installation of WordPress is complete. + * + * Sends an email to the new administrator that the installation is complete + * and provides them with a record of their login credentials. + * + * @since 2.1.0 + * + * @param string $blog_title Site title. + * @param string $blog_url Site URL. + * @param int $user_id Administrator's user ID. + * @param string $password Administrator's password. Note that a placeholder message is + * usually passed instead of the actual password. + */ + function wp_new_blog_notification($blog_title, $blog_url, $user_id, $password) + { + } + /** + * Runs WordPress Upgrade functions. + * + * Upgrades the database if needed during a site update. + * + * @since 2.1.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global int $wp_db_version The new database version. + * @global wpdb $wpdb WordPress database abstraction object. + */ + function wp_upgrade() + { + } + /** + * Functions to be called in installation and upgrade scripts. + * + * Contains conditional checks to determine which upgrade scripts to run, + * based on database version and WP version being updated-to. + * + * @ignore + * @since 1.0.1 + * + * @global int $wp_current_db_version The old (current) database version. + * @global int $wp_db_version The new database version. + */ + function upgrade_all() + { + } + /** + * Execute changes made in WordPress 1.0. + * + * @ignore + * @since 1.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_100() + { + } + /** + * Execute changes made in WordPress 1.0.1. + * + * @ignore + * @since 1.0.1 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_101() + { + } + /** + * Execute changes made in WordPress 1.2. + * + * @ignore + * @since 1.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_110() + { + } + /** + * Execute changes made in WordPress 1.5. + * + * @ignore + * @since 1.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_130() + { + } + /** + * Execute changes made in WordPress 2.0. + * + * @ignore + * @since 2.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global int $wp_current_db_version The old (current) database version. + */ + function upgrade_160() + { + } + /** + * Execute changes made in WordPress 2.1. + * + * @ignore + * @since 2.1.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_210() + { + } + /** + * Execute changes made in WordPress 2.3. + * + * @ignore + * @since 2.3.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_230() + { + } + /** + * Remove old options from the database. + * + * @ignore + * @since 2.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_230_options_table() + { + } + /** + * Remove old categories, link2cat, and post2cat database tables. + * + * @ignore + * @since 2.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_230_old_tables() + { + } + /** + * Upgrade old slugs made in version 2.2. + * + * @ignore + * @since 2.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_old_slugs() + { + } + /** + * Execute changes made in WordPress 2.5.0. + * + * @ignore + * @since 2.5.0 + * + * @global int $wp_current_db_version The old (current) database version. + */ + function upgrade_250() + { + } + /** + * Execute changes made in WordPress 2.5.2. + * + * @ignore + * @since 2.5.2 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_252() + { + } + /** + * Execute changes made in WordPress 2.6. + * + * @ignore + * @since 2.6.0 + * + * @global int $wp_current_db_version The old (current) database version. + */ + function upgrade_260() + { + } + /** + * Execute changes made in WordPress 2.7. + * + * @ignore + * @since 2.7.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_270() + { + } + /** + * Execute changes made in WordPress 2.8. + * + * @ignore + * @since 2.8.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_280() + { + } + /** + * Execute changes made in WordPress 2.9. + * + * @ignore + * @since 2.9.0 + * + * @global int $wp_current_db_version The old (current) database version. + */ + function upgrade_290() + { + } + /** + * Execute changes made in WordPress 3.0. + * + * @ignore + * @since 3.0.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_300() + { + } + /** + * Execute changes made in WordPress 3.3. + * + * @ignore + * @since 3.3.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global wpdb $wpdb WordPress database abstraction object. + * @global array $wp_registered_widgets + * @global array $sidebars_widgets + */ + function upgrade_330() + { + } + /** + * Execute changes made in WordPress 3.4. + * + * @ignore + * @since 3.4.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_340() + { + } + /** + * Execute changes made in WordPress 3.5. + * + * @ignore + * @since 3.5.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_350() + { + } + /** + * Execute changes made in WordPress 3.7. + * + * @ignore + * @since 3.7.0 + * + * @global int $wp_current_db_version The old (current) database version. + */ + function upgrade_370() + { + } + /** + * Execute changes made in WordPress 3.7.2. + * + * @ignore + * @since 3.7.2 + * + * @global int $wp_current_db_version The old (current) database version. + */ + function upgrade_372() + { + } + /** + * Execute changes made in WordPress 3.8.0. + * + * @ignore + * @since 3.8.0 + * + * @global int $wp_current_db_version The old (current) database version. + */ + function upgrade_380() + { + } + /** + * Execute changes made in WordPress 4.0.0. + * + * @ignore + * @since 4.0.0 + * + * @global int $wp_current_db_version The old (current) database version. + */ + function upgrade_400() + { + } + /** + * Execute changes made in WordPress 4.2.0. + * + * @ignore + * @since 4.2.0 + */ + function upgrade_420() + { + } + /** + * Executes changes made in WordPress 4.3.0. + * + * @ignore + * @since 4.3.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_430() + { + } + /** + * Executes comments changes made in WordPress 4.3.0. + * + * @ignore + * @since 4.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_430_fix_comments() + { + } + /** + * Executes changes made in WordPress 4.3.1. + * + * @ignore + * @since 4.3.1 + */ + function upgrade_431() + { + } + /** + * Executes changes made in WordPress 4.4.0. + * + * @ignore + * @since 4.4.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_440() + { + } + /** + * Executes changes made in WordPress 4.5.0. + * + * @ignore + * @since 4.5.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_450() + { + } + /** + * Executes changes made in WordPress 4.6.0. + * + * @ignore + * @since 4.6.0 + * + * @global int $wp_current_db_version The old (current) database version. + */ + function upgrade_460() + { + } + /** + * Executes changes made in WordPress 5.0.0. + * + * @ignore + * @since 5.0.0 + * @deprecated 5.1.0 + */ + function upgrade_500() + { + } + /** + * Executes changes made in WordPress 5.1.0. + * + * @ignore + * @since 5.1.0 + */ + function upgrade_510() + { + } + /** + * Executes changes made in WordPress 5.3.0. + * + * @ignore + * @since 5.3.0 + */ + function upgrade_530() + { + } + /** + * Executes changes made in WordPress 5.5.0. + * + * @ignore + * @since 5.5.0 + */ + function upgrade_550() + { + } + /** + * Executes changes made in WordPress 5.6.0. + * + * @ignore + * @since 5.6.0 + */ + function upgrade_560() + { + } + /** + * Executes changes made in WordPress 5.9.0. + * + * @ignore + * @since 5.9.0 + * + * @global int $wp_current_db_version The old (current) database version. + */ + function upgrade_590() + { + } + /** + * Executes changes made in WordPress 6.0.0. + * + * @ignore + * @since 6.0.0 + * + * @global int $wp_current_db_version The old (current) database version. + */ + function upgrade_600() + { + } + /** + * Executes network-level upgrade routines. + * + * @since 3.0.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global wpdb $wpdb WordPress database abstraction object. + */ + function upgrade_network() + { + } + // + // General functions we use to actually do stuff. + // + /** + * Creates a table in the database, if it doesn't already exist. + * + * This method checks for an existing database and creates a new one if it's not + * already present. It doesn't rely on MySQL's "IF NOT EXISTS" statement, but chooses + * to query all tables first and then run the SQL statement creating the table. + * + * @since 1.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $table_name Database table name. + * @param string $create_ddl SQL statement to create table. + * @return bool True on success or if the table already exists. False on failure. + */ + function maybe_create_table($table_name, $create_ddl) + { + } + /** + * Drops a specified index from a table. + * + * @since 1.0.1 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $table Database table name. + * @param string $index Index name to drop. + * @return true True, when finished. + */ + function drop_index($table, $index) + { + } + /** + * Adds an index to a specified table. + * + * @since 1.0.1 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $table Database table name. + * @param string $index Database table index column. + * @return true True, when done with execution. + */ + function add_clean_index($table, $index) + { + } + /** + * Adds column to a database table, if it doesn't already exist. + * + * @since 1.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $table_name Database table name. + * @param string $column_name Table column name. + * @param string $create_ddl SQL statement to add column. + * @return bool True on success or if the column already exists. False on failure. + */ + function maybe_add_column($table_name, $column_name, $create_ddl) + { + } + /** + * If a table only contains utf8 or utf8mb4 columns, convert it to utf8mb4. + * + * @since 4.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $table The table to convert. + * @return bool True if the table was converted, false if it wasn't. + */ + function maybe_convert_table_to_utf8mb4($table) + { + } + /** + * Retrieve all options as it was for 1.2. + * + * @since 1.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return stdClass List of options. + */ + function get_alloptions_110() + { + } + /** + * Utility version of get_option that is private to installation/upgrade. + * + * @ignore + * @since 1.5.1 + * @access private + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $setting Option name. + * @return mixed + */ + function __get_option($setting) + { + } + /** + * Filters for content to remove unnecessary slashes. + * + * @since 1.5.0 + * + * @param string $content The content to modify. + * @return string The de-slashed content. + */ + function deslash($content) + { + } + /** + * Modifies the database based on specified SQL statements. + * + * Useful for creating new tables and updating existing tables to a new structure. + * + * @since 1.5.0 + * @since 6.1.0 Ignores display width for integer data types on MySQL 8.0.17 or later, + * to match MySQL behavior. Note: This does not affect MariaDB. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string[]|string $queries Optional. The query to run. Can be multiple queries + * in an array, or a string of queries separated by + * semicolons. Default empty string. + * @param bool $execute Optional. Whether or not to execute the query right away. + * Default true. + * @return array Strings containing the results of the various update queries. + */ + function dbDelta($queries = '', $execute = \true) + { + } + /** + * Updates the database tables to a new schema. + * + * By default, updates all the tables to use the latest defined schema, but can also + * be used to update a specific set of tables in wp_get_db_schema(). + * + * @since 1.5.0 + * + * @uses dbDelta + * + * @param string $tables Optional. Which set of tables to update. Default is 'all'. + */ + function make_db_current($tables = 'all') + { + } + /** + * Updates the database tables to a new schema, but without displaying results. + * + * By default, updates all the tables to use the latest defined schema, but can + * also be used to update a specific set of tables in wp_get_db_schema(). + * + * @since 1.5.0 + * + * @see make_db_current() + * + * @param string $tables Optional. Which set of tables to update. Default is 'all'. + */ + function make_db_current_silent($tables = 'all') + { + } + /** + * Creates a site theme from an existing theme. + * + * {@internal Missing Long Description}} + * + * @since 1.5.0 + * + * @param string $theme_name The name of the theme. + * @param string $template The directory name of the theme. + * @return bool + */ + function make_site_theme_from_oldschool($theme_name, $template) + { + } + /** + * Creates a site theme from the default theme. + * + * {@internal Missing Long Description}} + * + * @since 1.5.0 + * + * @param string $theme_name The name of the theme. + * @param string $template The directory name of the theme. + * @return void|false + */ + function make_site_theme_from_default($theme_name, $template) + { + } + /** + * Creates a site theme. + * + * {@internal Missing Long Description}} + * + * @since 1.5.0 + * + * @return string|false + */ + function make_site_theme() + { + } + /** + * Translate user level to user role name. + * + * @since 2.0.0 + * + * @param int $level User level. + * @return string User role name. + */ + function translate_level_to_role($level) + { + } + /** + * Checks the version of the installed MySQL binary. + * + * @since 2.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function wp_check_mysql_version() + { + } + /** + * Disables the Automattic widgets plugin, which was merged into core. + * + * @since 2.2.0 + */ + function maybe_disable_automattic_widgets() + { + } + /** + * Disables the Link Manager on upgrade if, at the time of upgrade, no links exist in the DB. + * + * @since 3.5.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global wpdb $wpdb WordPress database abstraction object. + */ + function maybe_disable_link_manager() + { + } + /** + * Runs before the schema is upgraded. + * + * @since 2.9.0 + * + * @global int $wp_current_db_version The old (current) database version. + * @global wpdb $wpdb WordPress database abstraction object. + */ + function pre_schema_upgrade() + { + } + /** + * Determine if global tables should be upgraded. + * + * This function performs a series of checks to ensure the environment allows + * for the safe upgrading of global WordPress database tables. It is necessary + * because global tables will commonly grow to millions of rows on large + * installations, and the ability to control their upgrade routines can be + * critical to the operation of large networks. + * + * In a future iteration, this function may use `wp_is_large_network()` to more- + * intelligently prevent global table upgrades. Until then, we make sure + * WordPress is on the main site of the main network, to avoid running queries + * more than once in multi-site or multi-network environments. + * + * @since 4.3.0 + * + * @return bool Whether to run the upgrade routines on global tables. + */ + function wp_should_upgrade_global_tables() + { + } + /** + * WordPress user administration API. + * + * @package WordPress + * @subpackage Administration + */ + /** + * Creates a new user from the "Users" form using $_POST information. + * + * @since 2.0.0 + * + * @return int|WP_Error WP_Error or User ID. + */ + function add_user() + { + } + /** + * Edit user settings based on contents of $_POST + * + * Used on user-edit.php and profile.php to manage and process user options, passwords etc. + * + * @since 2.0.0 + * + * @param int $user_id Optional. User ID. + * @return int|WP_Error User ID of the updated user or WP_Error on failure. + */ + function edit_user($user_id = 0) + { + } + /** + * Fetch a filtered list of user roles that the current user is + * allowed to edit. + * + * Simple function whose main purpose is to allow filtering of the + * list of roles in the $wp_roles object so that plugins can remove + * inappropriate ones depending on the situation or user making edits. + * Specifically because without filtering anyone with the edit_users + * capability can edit others to be administrators, even if they are + * only editors or authors. This filter allows admins to delegate + * user management. + * + * @since 2.8.0 + * + * @return array[] Array of arrays containing role information. + */ + function get_editable_roles() + { + } + /** + * Retrieve user data and filter it. + * + * @since 2.0.5 + * + * @param int $user_id User ID. + * @return WP_User|false WP_User object on success, false on failure. + */ + function get_user_to_edit($user_id) + { + } + /** + * Retrieve the user's drafts. + * + * @since 2.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $user_id User ID. + * @return array + */ + function get_users_drafts($user_id) + { + } + /** + * Remove user and optionally reassign posts and links to another user. + * + * If the $reassign parameter is not assigned to a User ID, then all posts will + * be deleted of that user. The action {@see 'delete_user'} that is passed the User ID + * being deleted will be run after the posts are either reassigned or deleted. + * The user meta will also be deleted that are for that User ID. + * + * @since 2.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $id User ID. + * @param int $reassign Optional. Reassign posts and links to new User ID. + * @return bool True when finished. + */ + function wp_delete_user($id, $reassign = \null) + { + } + /** + * Remove all capabilities from user. + * + * @since 2.1.0 + * + * @param int $id User ID. + */ + function wp_revoke_user($id) + { + } + /** + * @since 2.8.0 + * + * @global int $user_ID + * + * @param false $errors Deprecated. + */ + function default_password_nag_handler($errors = \false) + { + } + /** + * @since 2.8.0 + * + * @param int $user_ID + * @param WP_User $old_data + */ + function default_password_nag_edit_user($user_ID, $old_data) + { + } + /** + * @since 2.8.0 + * + * @global string $pagenow The filename of the current screen. + */ + function default_password_nag() + { + } + /** + * @since 3.5.0 + * @access private + */ + function delete_users_add_js() + { + } + /** + * Optional SSL preference that can be turned on by hooking to the 'personal_options' action. + * + * See the {@see 'personal_options'} action. + * + * @since 2.7.0 + * + * @param WP_User $user User data object. + */ + function use_ssl_preference($user) + { + } + /** + * @since MU (3.0.0) + * + * @param string $text + * @return string + */ + function admin_created_user_email($text) + { + } + /** + * Checks if the Authorize Application Password request is valid. + * + * @since 5.6.0 + * + * @param array $request { + * The array of request data. All arguments are optional and may be empty. + * + * @type string $app_name The suggested name of the application. + * @type string $app_id A UUID provided by the application to uniquely identify it. + * @type string $success_url The URL the user will be redirected to after approving the application. + * @type string $reject_url The URL the user will be redirected to after rejecting the application. + * } + * @param WP_User $user The user authorizing the application. + * @return true|WP_Error True if the request is valid, a WP_Error object contains errors if not. + * @phpstan-param array{ + * app_name?: string, + * app_id?: string, + * success_url?: string, + * reject_url?: string, + * } $request + */ + function wp_is_authorize_application_password_request_valid($request, $user) + { + } + /** + * WordPress Widgets Administration API + * + * @package WordPress + * @subpackage Administration + */ + /** + * Display list of the available widgets. + * + * @since 2.5.0 + * + * @global array $wp_registered_widgets + * @global array $wp_registered_widget_controls + */ + function wp_list_widgets() + { + } + /** + * Callback to sort array by a 'name' key. + * + * @since 3.1.0 + * @access private + * + * @return int + */ + function _sort_name_callback($a, $b) + { + } + /** + * Show the widgets and their settings for a sidebar. + * Used in the admin widget config screen. + * + * @since 2.5.0 + * + * @param string $sidebar Sidebar ID. + * @param string $sidebar_name Optional. Sidebar name. Default empty. + */ + function wp_list_widget_controls($sidebar, $sidebar_name = '') + { + } + /** + * Retrieves the widget control arguments. + * + * @since 2.5.0 + * + * @global array $wp_registered_widgets + * + * @param array $params + * @return array + */ + function wp_list_widget_controls_dynamic_sidebar($params) + { + } + /** + * @global array $wp_registered_widgets + * + * @param string $id_base + * @return int + */ + function next_widget_id_number($id_base) + { + } + /** + * Meta widget used to display the control form for a widget. + * + * Called from dynamic_sidebar(). + * + * @since 2.5.0 + * + * @global array $wp_registered_widgets + * @global array $wp_registered_widget_controls + * @global array $sidebars_widgets + * + * @param array $sidebar_args + * @return array + */ + function wp_widget_control($sidebar_args) + { + } + /** + * @param string $classes + * @return string + */ + function wp_widgets_access_body_class($classes) + { + } + /** + * Display installation header. + * + * @since 2.5.0 + * + * @param string $body_classes + */ + function display_header($body_classes = '') + { + } + // End display_header(). + /** + * Displays installer setup form. + * + * @since 2.8.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string|null $error + */ + function display_setup_form($error = \null) + { + } + /** + * XML callback function for the start of a new XML tag. + * + * @since 0.71 + * @access private + * + * @global array $names + * @global array $urls + * @global array $targets + * @global array $descriptions + * @global array $feeds + * + * @param resource $parser XML Parser resource. + * @param string $tag_name XML element name. + * @param array $attrs XML element attributes. + */ + function startElement($parser, $tag_name, $attrs) + { + } + /** + * XML callback function that is called at the end of a XML tag. + * + * @since 0.71 + * @access private + * + * @param resource $parser XML Parser resource. + * @param string $tag_name XML tag name. + */ + function endElement($parser, $tag_name) + { + } + /** + * Display menu. + * + * @access private + * @since 2.7.0 + * + * @global string $self + * @global string $parent_file + * @global string $submenu_file + * @global string $plugin_page + * @global string $typenow The post type of the current screen. + * + * @param array $menu + * @param array $submenu + * @param bool $submenu_as_parent + */ + function _wp_menu_output($menu, $submenu, $submenu_as_parent = \true) + { + } + /** + * Adds the 'Theme File Editor' menu item to the bottom of the Appearance (non-block themes) + * or Tools (block themes) menu. + * + * @access private + * @since 3.0.0 + * @since 5.9.0 Renamed 'Theme Editor' to 'Theme File Editor'. + * Relocates to Tools for block themes. + */ + function _add_themes_utility_last() + { + } + /** + * Adds the 'Plugin File Editor' menu item after the 'Themes File Editor' in Tools + * for block themes. + * + * @access private + * @since 5.9.0 + */ + function _add_plugin_file_editor_to_tools() + { + } + /** + * @global int $_wp_nav_menu_max_depth + * + * @param string $classes + * @return string + */ + function wp_nav_menu_max_depth($classes) + { + } + function wp_load_press_this() + { + } + /** + * Display setup wp-config.php file header. + * + * @ignore + * @since 2.3.0 + * + * @param string|string[] $body_classes Class attribute values for the body tag. + */ + function setup_config_display_header($body_classes = array()) + { + } + /** + * Returns the JavaScript template used to display the auto-update setting for a theme. + * + * @since 5.5.0 + * + * @return string The template for displaying the auto-update setting link. + */ + function wp_theme_auto_update_setting_template() + { + } + /** + * Lists available core updates. + * + * @since 2.7.0 + * + * @global string $wp_local_package Locale code of the package. + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param object $update + */ + function list_core_update($update) + { + } + /** + * Display dismissed updates. + * + * @since 2.7.0 + */ + function dismissed_updates() + { + } + /** + * Display upgrade WordPress for downloading latest or upgrading automatically form. + * + * @since 2.7.0 + * + * @global string $required_php_version The required PHP version string. + * @global string $required_mysql_version The required MySQL version string. + */ + function core_upgrade_preamble() + { + } + /** + * Display WordPress auto-updates settings. + * + * @since 5.6.0 + */ + function core_auto_updates_settings() + { + } + /** + * Display the upgrade plugins form. + * + * @since 2.9.0 + */ + function list_plugin_updates() + { + } + /** + * Display the upgrade themes form. + * + * @since 2.9.0 + */ + function list_theme_updates() + { + } + /** + * Display the update translations form. + * + * @since 3.7.0 + */ + function list_translation_updates() + { + } + /** + * Upgrade WordPress core display. + * + * @since 2.7.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param bool $reinstall + */ + function do_core_upgrade($reinstall = \false) + { + } + /** + * Dismiss a core update. + * + * @since 2.7.0 + */ + function do_dismiss_core_update() + { + } + /** + * Undismiss a core update. + * + * @since 2.7.0 + */ + function do_undismiss_core_update() + { + } + /** + * Retrieves the cron lock. + * + * Returns the uncached `doing_cron` transient. + * + * @ignore + * @since 3.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return string|int|false Value of the `doing_cron` transient, 0|false otherwise. + */ + function _get_cron_lock() + { + } + /** + * Toolbar API: Top-level Toolbar functionality + * + * @package WordPress + * @subpackage Toolbar + * @since 3.1.0 + */ + /** + * Instantiates the admin bar object and set it up as a global for access elsewhere. + * + * UNHOOKING THIS FUNCTION WILL NOT PROPERLY REMOVE THE ADMIN BAR. + * For that, use show_admin_bar(false) or the {@see 'show_admin_bar'} filter. + * + * @since 3.1.0 + * @access private + * + * @global WP_Admin_Bar $wp_admin_bar + * + * @return bool Whether the admin bar was successfully initialized. + */ + function _wp_admin_bar_init() + { + } + /** + * Renders the admin bar to the page based on the $wp_admin_bar->menu member var. + * + * This is called very early on the {@see 'wp_body_open'} action so that it will render + * before anything else being added to the page body. + * + * For backward compatibility with themes not using the 'wp_body_open' action, + * the function is also called late on {@see 'wp_footer'}. + * + * It includes the {@see 'admin_bar_menu'} action which should be used to hook in and + * add new menus to the admin bar. That way you can be sure that you are adding at most + * optimal point, right before the admin bar is rendered. This also gives you access to + * the `$post` global, among others. + * + * @since 3.1.0 + * @since 5.4.0 Called on 'wp_body_open' action first, with 'wp_footer' as a fallback. + * + * @global WP_Admin_Bar $wp_admin_bar + */ + function wp_admin_bar_render() + { + } + /** + * Adds the WordPress logo menu. + * + * @since 3.3.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_wp_menu($wp_admin_bar) + { + } + /** + * Adds the sidebar toggle button. + * + * @since 3.8.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_sidebar_toggle($wp_admin_bar) + { + } + /** + * Adds the "My Account" item. + * + * @since 3.3.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_my_account_item($wp_admin_bar) + { + } + /** + * Adds the "My Account" submenu items. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_my_account_menu($wp_admin_bar) + { + } + /** + * Adds the "Site Name" menu. + * + * @since 3.3.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_site_menu($wp_admin_bar) + { + } + /** + * Adds the "Edit site" link to the Toolbar. + * + * @since 5.9.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_edit_site_menu($wp_admin_bar) + { + } + /** + * Adds the "Customize" link to the Toolbar. + * + * @since 4.3.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + * @global WP_Customize_Manager $wp_customize + */ + function wp_admin_bar_customize_menu($wp_admin_bar) + { + } + /** + * Adds the "My Sites/[Site Name]" menu and all submenus. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_my_sites_menu($wp_admin_bar) + { + } + /** + * Provides a shortlink. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_shortlink_menu($wp_admin_bar) + { + } + /** + * Provides an edit link for posts and terms. + * + * @since 3.1.0 + * @since 5.5.0 Added a "View Post" link on Comments screen for a single post. + * + * @global WP_Term $tag + * @global WP_Query $wp_the_query WordPress Query object. + * @global int $user_id The ID of the user being edited. Not to be confused with the + * global $user_ID, which contains the ID of the current user. + * @global int $post_id The ID of the post when editing comments for a single post. + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_edit_menu($wp_admin_bar) + { + } + /** + * Adds "Add New" menu. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_new_content_menu($wp_admin_bar) + { + } + /** + * Adds edit comments link with awaiting moderation count bubble. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_comments_menu($wp_admin_bar) + { + } + /** + * Adds appearance submenu items to the "Site Name" menu. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_appearance_menu($wp_admin_bar) + { + } + /** + * Provides an update link if theme/plugin/core updates are available. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_updates_menu($wp_admin_bar) + { + } + /** + * Adds search form. + * + * @since 3.3.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_search_menu($wp_admin_bar) + { + } + /** + * Adds a link to exit recovery mode when Recovery Mode is active. + * + * @since 5.2.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_recovery_mode_menu($wp_admin_bar) + { + } + /** + * Adds secondary menus. + * + * @since 3.3.0 + * + * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance. + */ + function wp_admin_bar_add_secondary_groups($wp_admin_bar) + { + } + /** + * Prints style and scripts for the admin bar. + * + * @since 3.1.0 + */ + function wp_admin_bar_header() + { + } + /** + * Prints default admin bar callback. + * + * @since 3.1.0 + */ + function _admin_bar_bump_cb() + { + } + /** + * Sets the display status of the admin bar. + * + * This can be called immediately upon plugin load. It does not need to be called + * from a function hooked to the {@see 'init'} action. + * + * @since 3.1.0 + * + * @global bool $show_admin_bar + * + * @param bool $show Whether to allow the admin bar to show. + */ + function show_admin_bar($show) + { + } + /** + * Determines whether the admin bar should be showing. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 3.1.0 + * + * @global bool $show_admin_bar + * @global string $pagenow The filename of the current screen. + * + * @return bool Whether the admin bar should be showing. + */ + function is_admin_bar_showing() + { + } + /** + * Retrieves the admin bar display preference of a user. + * + * @since 3.1.0 + * @access private + * + * @param string $context Context of this preference check. Defaults to 'front'. The 'admin' + * preference is no longer used. + * @param int $user Optional. ID of the user to check, defaults to 0 for current user. + * @return bool Whether the admin bar should be showing for this user. + */ + function _get_admin_bar_pref($context = 'front', $user = 0) + { + } + /** + * Author Template functions for use in themes. + * + * These functions must be used within the WordPress Loop. + * + * @link https://codex.wordpress.org/Author_Templates + * + * @package WordPress + * @subpackage Template + */ + /** + * Retrieves the author of the current post. + * + * @since 1.5.0 + * + * @global WP_User $authordata The current author's data. + * + * @param string $deprecated Deprecated. + * @return string|null The author's display name. + */ + function get_the_author($deprecated = '') + { + } + /** + * Displays the name of the author of the current post. + * + * The behavior of this function is based off of old functionality predating + * get_the_author(). This function is not deprecated, but is designed to echo + * the value from get_the_author() and as an result of any old theme that might + * still use the old behavior will also pass the value from get_the_author(). + * + * The normal, expected behavior of this function is to echo the author and not + * return it. However, backward compatibility has to be maintained. + * + * @since 0.71 + * + * @see get_the_author() + * @link https://developer.wordpress.org/reference/functions/the_author/ + * + * @param string $deprecated Deprecated. + * @param bool $deprecated_echo Deprecated. Use get_the_author(). Echo the string or return it. + * @return string|null The author's display name, from get_the_author(). + */ + function the_author($deprecated = '', $deprecated_echo = \true) + { + } + /** + * Retrieves the author who last edited the current post. + * + * @since 2.8.0 + * + * @return string|void The author's display name, empty string if unknown. + */ + function get_the_modified_author() + { + } + /** + * Displays the name of the author who last edited the current post, + * if the author's ID is available. + * + * @since 2.8.0 + * + * @see get_the_author() + */ + function the_modified_author() + { + } + /** + * Retrieves the requested data of the author of the current post. + * + * Valid values for the `$field` parameter include: + * + * - admin_color + * - aim + * - comment_shortcuts + * - description + * - display_name + * - first_name + * - ID + * - jabber + * - last_name + * - nickname + * - plugins_last_view + * - plugins_per_page + * - rich_editing + * - syntax_highlighting + * - user_activation_key + * - user_description + * - user_email + * - user_firstname + * - user_lastname + * - user_level + * - user_login + * - user_nicename + * - user_pass + * - user_registered + * - user_status + * - user_url + * - yim + * + * @since 2.8.0 + * + * @global WP_User $authordata The current author's data. + * + * @param string $field Optional. The user field to retrieve. Default empty. + * @param int|false $user_id Optional. User ID. + * @return string The author's field from the current author's DB object, otherwise an empty string. + */ + function get_the_author_meta($field = '', $user_id = \false) + { + } + /** + * Outputs the field from the user's DB object. Defaults to current post's author. + * + * @since 2.8.0 + * + * @param string $field Selects the field of the users record. See get_the_author_meta() + * for the list of possible fields. + * @param int|false $user_id Optional. User ID. + * + * @see get_the_author_meta() + */ + function the_author_meta($field = '', $user_id = \false) + { + } + /** + * Retrieves either author's link or author's name. + * + * If the author has a home page set, return an HTML link, otherwise just return the + * author's name. + * + * @since 3.0.0 + * + * @global WP_User $authordata The current author's data. + * + * @return string|null An HTML link if the author's url exist in user meta, + * else the result of get_the_author(). + */ + function get_the_author_link() + { + } + /** + * Displays either author's link or author's name. + * + * If the author has a home page set, echo an HTML link, otherwise just echo the + * author's name. + * + * @link https://developer.wordpress.org/reference/functions/the_author_link/ + * + * @since 2.1.0 + */ + function the_author_link() + { + } + /** + * Retrieves the number of posts by the author of the current post. + * + * @since 1.5.0 + * + * @return int The number of posts by the author. + */ + function get_the_author_posts() + { + } + /** + * Displays the number of posts by the author of the current post. + * + * @link https://developer.wordpress.org/reference/functions/the_author_posts/ + * @since 0.71 + */ + function the_author_posts() + { + } + /** + * Retrieves an HTML link to the author page of the current post's author. + * + * Returns an HTML-formatted link using get_author_posts_url(). + * + * @since 4.4.0 + * + * @global WP_User $authordata The current author's data. + * + * @return string An HTML link to the author page, or an empty string if $authordata isn't defined. + */ + function get_the_author_posts_link() + { + } + /** + * Displays an HTML link to the author page of the current post's author. + * + * @since 1.2.0 + * @since 4.4.0 Converted into a wrapper for get_the_author_posts_link() + * + * @param string $deprecated Unused. + */ + function the_author_posts_link($deprecated = '') + { + } + /** + * Retrieves the URL to the author page for the user with the ID provided. + * + * @since 2.1.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param int $author_id Author ID. + * @param string $author_nicename Optional. The author's nicename (slug). Default empty. + * @return string The URL to the author's page. + */ + function get_author_posts_url($author_id, $author_nicename = '') + { + } + /** + * Lists all the authors of the site, with several options available. + * + * @link https://developer.wordpress.org/reference/functions/wp_list_authors/ + * + * @since 1.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string|array $args { + * Optional. Array or string of default arguments. + * + * @type string $orderby How to sort the authors. Accepts 'nicename', 'email', 'url', 'registered', + * 'user_nicename', 'user_email', 'user_url', 'user_registered', 'name', + * 'display_name', 'post_count', 'ID', 'meta_value', 'user_login'. Default 'name'. + * @type string $order Sorting direction for $orderby. Accepts 'ASC', 'DESC'. Default 'ASC'. + * @type int $number Maximum authors to return or display. Default empty (all authors). + * @type bool $optioncount Show the count in parenthesis next to the author's name. Default false. + * @type bool $exclude_admin Whether to exclude the 'admin' account, if it exists. Default true. + * @type bool $show_fullname Whether to show the author's full name. Default false. + * @type bool $hide_empty Whether to hide any authors with no posts. Default true. + * @type string $feed If not empty, show a link to the author's feed and use this text as the alt + * parameter of the link. Default empty. + * @type string $feed_image If not empty, show a link to the author's feed and use this image URL as + * clickable anchor. Default empty. + * @type string $feed_type The feed type to link to. Possible values include 'rss2', 'atom'. + * Default is the value of get_default_feed(). + * @type bool $echo Whether to output the result or instead return it. Default true. + * @type string $style If 'list', each author is wrapped in an `<li>` element, otherwise the authors + * will be separated by commas. + * @type bool $html Whether to list the items in HTML form or plaintext. Default true. + * @type int[]|string $exclude Array or comma/space-separated list of author IDs to exclude. Default empty. + * @type int[]|string $include Array or comma/space-separated list of author IDs to include. Default empty. + * } + * @return void|string Void if 'echo' argument is true, list of authors if 'echo' is false. + * @phpstan-param array{ + * orderby?: string, + * order?: string, + * number?: int, + * optioncount?: bool, + * exclude_admin?: bool, + * show_fullname?: bool, + * hide_empty?: bool, + * feed?: string, + * feed_image?: string, + * feed_type?: string, + * echo?: bool, + * style?: string, + * html?: bool, + * exclude?: int[]|string, + * include?: int[]|string, + * } $args + */ + function wp_list_authors($args = '') + { + } + /** + * Determines whether this site has more than one author. + * + * Checks to see if more than one author has published posts. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 3.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return bool Whether or not we have more than one author + */ + function is_multi_author() + { + } + /** + * Helper function to clear the cache for number of authors. + * + * @since 3.2.0 + * @access private + */ + function __clear_multi_author_cache() + { + } + /** + * Block Editor API. + * + * @package WordPress + * @subpackage Editor + * @since 5.8.0 + */ + /** + * Returns the list of default categories for block types. + * + * @since 5.8.0 + * + * @return array[] Array of categories for block types. + */ + function get_default_block_categories() + { + } + /** + * Returns all the categories for block types that will be shown in the block editor. + * + * @since 5.0.0 + * @since 5.8.0 It is possible to pass the block editor context as param. + * + * @param WP_Post|WP_Block_Editor_Context $post_or_block_editor_context The current post object or + * the block editor context. + * + * @return array[] Array of categories for block types. + */ + function get_block_categories($post_or_block_editor_context) + { + } + /** + * Gets the list of allowed block types to use in the block editor. + * + * @since 5.8.0 + * + * @param WP_Block_Editor_Context $block_editor_context The current block editor context. + * + * @return bool|string[] Array of block type slugs, or boolean to enable/disable all. + */ + function get_allowed_block_types($block_editor_context) + { + } + /** + * Returns the default block editor settings. + * + * @since 5.8.0 + * + * @return array The default block editor settings. + */ + function get_default_block_editor_settings() + { + } + /** + * Returns the block editor settings needed to use the Legacy Widget block which + * is not registered by default. + * + * @since 5.8.0 + * + * @return array Settings to be used with get_block_editor_settings(). + */ + function get_legacy_widget_block_editor_settings() + { + } + /** + * Collect the block editor assets that need to be loaded into the editor's iframe. + * + * @since 6.0.0 + * @access private + * + * @global string $pagenow The filename of the current screen. + * + * @return array { + * The block editor assets. + * + * @type string|false $styles String containing the HTML for styles. + * @type string|false $scripts String containing the HTML for scripts. + * } + * @phpstan-return array{ + * styles: string|false, + * scripts: string|false, + * } + */ + function _wp_get_iframed_editor_assets() + { + } + /** + * Returns the contextualized block editor settings for a selected editor context. + * + * @since 5.8.0 + * + * @param array $custom_settings Custom settings to use with the given editor type. + * @param WP_Block_Editor_Context $block_editor_context The current block editor context. + * + * @return array The contextualized block editor settings. + */ + function get_block_editor_settings(array $custom_settings, $block_editor_context) + { + } + /** + * Preloads common data used with the block editor by specifying an array of + * REST API paths that will be preloaded for a given block editor context. + * + * @since 5.8.0 + * + * @global WP_Post $post Global post object. + * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts. + * @global WP_Styles $wp_styles The WP_Styles object for printing styles. + * + * @param string[] $preload_paths List of paths to preload. + * @param WP_Block_Editor_Context $block_editor_context The current block editor context. + */ + function block_editor_rest_api_preload(array $preload_paths, $block_editor_context) + { + } + /** + * Creates an array of theme styles to load into the block editor. + * + * @since 5.8.0 + * + * @global array $editor_styles + * + * @return array An array of theme styles for the block editor. + */ + function get_block_editor_theme_styles() + { + } + /** + * Registers the core block patterns and categories. + * + * @since 5.5.0 + * @access private + */ + function _register_core_block_patterns_and_categories() + { + } + /** + * Register Core's official patterns from wordpress.org/patterns. + * + * @since 5.8.0 + * @since 5.9.0 The $current_screen argument was removed. + * + * @param WP_Screen $deprecated Unused. Formerly the screen that the current request was triggered from. + */ + function _load_remote_block_patterns($deprecated = \null) + { + } + /** + * Register `Featured` (category) patterns from wordpress.org/patterns. + * + * @since 5.9.0 + */ + function _load_remote_featured_patterns() + { + } + /** + * Registers patterns from Pattern Directory provided by a theme's + * `theme.json` file. + * + * @since 6.0.0 + * @access private + */ + function _register_remote_theme_patterns() + { + } + /** + * Register any patterns that the active theme may provide under its + * `./patterns/` directory. Each pattern is defined as a PHP file and defines + * its metadata using plugin-style headers. The minimum required definition is: + * + * /** + * * Title: My Pattern + * * Slug: my-theme/my-pattern + * * + * + * The output of the PHP source corresponds to the content of the pattern, e.g.: + * + * <main><p><?php echo "Hello"; ?></p></main> + * + * If applicable, this will collect from both parent and child theme. + * + * Other settable fields include: + * + * - Description + * - Viewport Width + * - Categories (comma-separated values) + * - Keywords (comma-separated values) + * - Block Types (comma-separated values) + * - Post Types (comma-separated values) + * - Inserter (yes/no) + * + * @since 6.0.0 + * @access private + */ + function _register_theme_block_patterns() + { + } + /** + * Align block support flag. + * + * @package WordPress + * @since 5.6.0 + */ + /** + * Registers the align block attribute for block types that support it. + * + * @since 5.6.0 + * @access private + * + * @param WP_Block_Type $block_type Block Type. + */ + function wp_register_alignment_support($block_type) + { + } + /** + * Adds CSS classes for block alignment to the incoming attributes array. + * This will be applied to the block markup in the front-end. + * + * @since 5.6.0 + * @access private + * + * @param WP_Block_Type $block_type Block Type. + * @param array $block_attributes Block attributes. + * @return array Block alignment CSS classes and inline styles. + */ + function wp_apply_alignment_support($block_type, $block_attributes) + { + } + /** + * Border block support flag. + * + * @package WordPress + * @since 5.8.0 + */ + /** + * Registers the style attribute used by the border feature if needed for block + * types that support borders. + * + * @since 5.8.0 + * @since 6.1.0 Improved conditional blocks optimization. + * @access private + * + * @param WP_Block_Type $block_type Block Type. + */ + function wp_register_border_support($block_type) + { + } + /** + * Adds CSS classes and inline styles for border styles to the incoming + * attributes array. This will be applied to the block markup in the front-end. + * + * @since 5.8.0 + * @since 6.1.0 Implemented the style engine to generate CSS and classnames. + * @access private + * + * @param WP_Block_Type $block_type Block type. + * @param array $block_attributes Block attributes. + * @return array Border CSS classes and inline styles. + */ + function wp_apply_border_support($block_type, $block_attributes) + { + } + /** + * Checks whether the current block type supports the border feature requested. + * + * If the `__experimentalBorder` support flag is a boolean `true` all border + * support features are available. Otherwise, the specific feature's support + * flag nested under `experimentalBorder` must be enabled for the feature + * to be opted into. + * + * @since 5.8.0 + * @access private + * + * @param WP_Block_Type $block_type Block type to check for support. + * @param string $feature Name of the feature to check support for. + * @param mixed $default_value Fallback value for feature support, defaults to false. + * @return bool Whether the feature is supported. + */ + function wp_has_border_feature_support($block_type, $feature, $default_value = \false) + { + } + /** + * Colors block support flag. + * + * @package WordPress + * @since 5.6.0 + */ + /** + * Registers the style and colors block attributes for block types that support it. + * + * @since 5.6.0 + * @since 6.1.0 Improved $color_support assignment optimization. + * @access private + * + * @param WP_Block_Type $block_type Block Type. + */ + function wp_register_colors_support($block_type) + { + } + /** + * Add CSS classes and inline styles for colors to the incoming attributes array. + * This will be applied to the block markup in the front-end. + * + * @since 5.6.0 + * @since 6.1.0 Implemented the style engine to generate CSS and classnames. + * @access private + * + * @param WP_Block_Type $block_type Block type. + * @param array $block_attributes Block attributes. + * + * @return array Colors CSS classes and inline styles. + */ + function wp_apply_colors_support($block_type, $block_attributes) + { + } + /** + * Custom classname block support flag. + * + * @package WordPress + * @since 5.6.0 + */ + /** + * Registers the custom classname block attribute for block types that support it. + * + * @since 5.6.0 + * @access private + * + * @param WP_Block_Type $block_type Block Type. + */ + function wp_register_custom_classname_support($block_type) + { + } + /** + * Add the custom classnames to the output. + * + * @since 5.6.0 + * @access private + * + * @param WP_Block_Type $block_type Block Type. + * @param array $block_attributes Block attributes. + * + * @return array Block CSS classes and inline styles. + */ + function wp_apply_custom_classname_support($block_type, $block_attributes) + { + } + /** + * Dimensions block support flag. + * + * This does not include the `spacing` block support even though that visually + * appears under the "Dimensions" panel in the editor. It remains in its + * original `spacing.php` file for compatibility with core. + * + * @package WordPress + * @since 5.9.0 + */ + /** + * Registers the style block attribute for block types that support it. + * + * @since 5.9.0 + * @access private + * + * @param WP_Block_Type $block_type Block Type. + */ + function wp_register_dimensions_support($block_type) + { + } + /** + * Adds CSS classes for block dimensions to the incoming attributes array. + * This will be applied to the block markup in the front-end. + * + * @since 5.9.0 + * @access private + * + * @param WP_Block_Type $block_type Block Type. + * @param array $block_attributes Block attributes. + * @return array Block dimensions CSS classes and inline styles. + */ + function wp_apply_dimensions_support($block_type, $block_attributes) + { + } + /** + * Duotone block support flag. + * + * Parts of this source were derived and modified from TinyColor, + * released under the MIT license. + * + * https://github.com/bgrins/TinyColor + * + * Copyright (c), Brian Grinstead, http://briangrinstead.com + * + * 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. + * + * @package WordPress + * @since 5.8.0 + */ + /** + * Takes input from [0, n] and returns it as [0, 1]. + * + * Direct port of TinyColor's function, lightly simplified to maintain + * consistency with TinyColor. + * + * @see https://github.com/bgrins/TinyColor + * + * @since 5.8.0 + * @access private + * + * @param mixed $n Number of unknown type. + * @param int $max Upper value of the range to bound to. + * @return float Value in the range [0, 1]. + */ + function wp_tinycolor_bound01($n, $max) + { + } + /** + * Direct port of tinycolor's boundAlpha function to maintain consistency with + * how tinycolor works. + * + * @see https://github.com/bgrins/TinyColor + * + * @since 5.9.0 + * @access private + * + * @param mixed $n Number of unknown type. + * @return float Value in the range [0,1]. + */ + function _wp_tinycolor_bound_alpha($n) + { + } + /** + * Rounds and converts values of an RGB object. + * + * Direct port of TinyColor's function, lightly simplified to maintain + * consistency with TinyColor. + * + * @see https://github.com/bgrins/TinyColor + * + * @since 5.8.0 + * @access private + * + * @param array $rgb_color RGB object. + * @return array Rounded and converted RGB object. + */ + function wp_tinycolor_rgb_to_rgb($rgb_color) + { + } + /** + * Helper function for hsl to rgb conversion. + * + * Direct port of TinyColor's function, lightly simplified to maintain + * consistency with TinyColor. + * + * @see https://github.com/bgrins/TinyColor + * + * @since 5.8.0 + * @access private + * + * @param float $p first component. + * @param float $q second component. + * @param float $t third component. + * @return float R, G, or B component. + */ + function wp_tinycolor_hue_to_rgb($p, $q, $t) + { + } + /** + * Converts an HSL object to an RGB object with converted and rounded values. + * + * Direct port of TinyColor's function, lightly simplified to maintain + * consistency with TinyColor. + * + * @see https://github.com/bgrins/TinyColor + * + * @since 5.8.0 + * @access private + * + * @param array $hsl_color HSL object. + * @return array Rounded and converted RGB object. + */ + function wp_tinycolor_hsl_to_rgb($hsl_color) + { + } + /** + * Parses hex, hsl, and rgb CSS strings using the same regex as TinyColor v1.4.2 + * used in the JavaScript. Only colors output from react-color are implemented. + * + * Direct port of TinyColor's function, lightly simplified to maintain + * consistency with TinyColor. + * + * @see https://github.com/bgrins/TinyColor + * @see https://github.com/casesandberg/react-color/ + * + * @since 5.8.0 + * @since 5.9.0 Added alpha processing. + * @access private + * + * @param string $color_str CSS color string. + * @return array RGB object. + */ + function wp_tinycolor_string_to_rgb($color_str) + { + } + /** + * Returns the prefixed id for the duotone filter for use as a CSS id. + * + * @since 5.9.1 + * @access private + * + * @param array $preset Duotone preset value as seen in theme.json. + * @return string Duotone filter CSS id. + */ + function wp_get_duotone_filter_id($preset) + { + } + /** + * Returns the CSS filter property url to reference the rendered SVG. + * + * @since 5.9.0 + * @since 6.1.0 Allow unset for preset colors. + * @access private + * + * @param array $preset Duotone preset value as seen in theme.json. + * @return string Duotone CSS filter property url value. + */ + function wp_get_duotone_filter_property($preset) + { + } + /** + * Returns the duotone filter SVG string for the preset. + * + * @since 5.9.1 + * @access private + * + * @param array $preset Duotone preset value as seen in theme.json. + * @return string Duotone SVG filter. + */ + function wp_get_duotone_filter_svg($preset) + { + } + /** + * Registers the style and colors block attributes for block types that support it. + * + * @since 5.8.0 + * @access private + * + * @param WP_Block_Type $block_type Block Type. + */ + function wp_register_duotone_support($block_type) + { + } + /** + * Render out the duotone stylesheet and SVG. + * + * @since 5.8.0 + * @since 6.1.0 Allow unset for preset colors. + * @access private + * + * @param string $block_content Rendered block content. + * @param array $block Block object. + * @return string Filtered block content. + */ + function wp_render_duotone_support($block_content, $block) + { + } + /** + * Elements styles block support. + * + * @package WordPress + * @since 5.8.0 + */ + /** + * Get the elements class names. + * + * @since 6.0.0 + * @access private + * + * @param array $block Block object. + * @return string The unique class name. + */ + function wp_get_elements_class_name($block) + { + } + /** + * Update the block content with elements class names. + * + * @since 5.8.0 + * @access private + * + * @param string $block_content Rendered block content. + * @param array $block Block object. + * @return string Filtered block content. + */ + function wp_render_elements_support($block_content, $block) + { + } + /** + * Render the elements stylesheet. + * + * In the case of nested blocks we want the parent element styles to be rendered before their descendants. + * This solves the issue of an element (e.g.: link color) being styled in both the parent and a descendant: + * we want the descendant style to take priority, and this is done by loading it after, in DOM order. + * + * @since 6.0.0 + * @since 6.1.0 Implemented the style engine to generate CSS and classnames. + * @access private + * + * @param string|null $pre_render The pre-rendered content. Default null. + * @param array $block The block being rendered. + * + * @return null + */ + function wp_render_elements_support_styles($pre_render, $block) + { + } + /** + * Generated classname block support flag. + * + * @package WordPress + * @since 5.6.0 + */ + /** + * Get the generated classname from a given block name. + * + * @since 5.6.0 + * + * @access private + * + * @param string $block_name Block Name. + * @return string Generated classname. + */ + function wp_get_block_default_classname($block_name) + { + } + /** + * Add the generated classnames to the output. + * + * @since 5.6.0 + * + * @access private + * + * @param WP_Block_Type $block_type Block Type. + * + * @return array Block CSS classes and inline styles. + */ + function wp_apply_generated_classname_support($block_type) + { + } + /** + * Layout block support flag. + * + * @package WordPress + * @since 5.8.0 + */ + /** + * Registers the layout block attribute for block types that support it. + * + * @since 5.8.0 + * @access private + * + * @param WP_Block_Type $block_type Block Type. + */ + function wp_register_layout_support($block_type) + { + } + /** + * Generates the CSS corresponding to the provided layout. + * + * @since 5.9.0 + * @since 6.1.0 Added `$block_spacing` param, use style engine to enqueue styles. + * @access private + * + * @param string $selector CSS selector. + * @param array $layout Layout object. The one that is passed has already checked + * the existence of default block layout. + * @param bool $has_block_gap_support Optional. Whether the theme has support for the block gap. Default false. + * @param string|string[]|null $gap_value Optional. The block gap value to apply. Default null. + * @param bool $should_skip_gap_serialization Optional. Whether to skip applying the user-defined value set in the editor. Default false. + * @param string $fallback_gap_value Optional. The block gap value to apply. Default '0.5em'. + * @param array|null $block_spacing Optional. Custom spacing set on the block. Default null. + * @return string CSS styles on success. Else, empty string. + */ + function wp_get_layout_style($selector, $layout, $has_block_gap_support = \false, $gap_value = \null, $should_skip_gap_serialization = \false, $fallback_gap_value = '0.5em', $block_spacing = \null) + { + } + /** + * Renders the layout config to the block wrapper. + * + * @since 5.8.0 + * @access private + * + * @param string $block_content Rendered block content. + * @param array $block Block object. + * @return string Filtered block content. + */ + function wp_render_layout_support_flag($block_content, $block) + { + } + /** + * For themes without theme.json file, make sure + * to restore the inner div for the group block + * to avoid breaking styles relying on that div. + * + * @since 5.8.0 + * @access private + * + * @param string $block_content Rendered block content. + * @param array $block Block object. + * @return string Filtered block content. + */ + function wp_restore_group_inner_container($block_content, $block) + { + } + /** + * For themes without theme.json file, make sure + * to restore the outer div for the aligned image block + * to avoid breaking styles relying on that div. + * + * @since 6.0.0 + * @access private + * + * @param string $block_content Rendered block content. + * @param array $block Block object. + * @return string Filtered block content. + */ + function wp_restore_image_outer_container($block_content, $block) + { + } + /** + * Spacing block support flag. + * For backwards compatibility, this remains separate to the dimensions.php + * block support despite both belonging under a single panel in the editor. + * + * @package WordPress + * @since 5.8.0 + */ + /** + * Registers the style block attribute for block types that support it. + * + * @since 5.8.0 + * @access private + * + * @param WP_Block_Type $block_type Block Type. + */ + function wp_register_spacing_support($block_type) + { + } + /** + * Add CSS classes for block spacing to the incoming attributes array. + * This will be applied to the block markup in the front-end. + * + * @since 5.8.0 + * @since 6.1.0 Implemented the style engine to generate CSS and classnames. + * @access private + * + * @param WP_Block_Type $block_type Block Type. + * @param array $block_attributes Block attributes. + * @return array Block spacing CSS classes and inline styles. + */ + function wp_apply_spacing_support($block_type, $block_attributes) + { + } + /** + * Typography block support flag. + * + * @package WordPress + * @since 5.6.0 + */ + /** + * Registers the style and typography block attributes for block types that support it. + * + * @since 5.6.0 + * @access private + * + * @param WP_Block_Type $block_type Block Type. + */ + function wp_register_typography_support($block_type) + { + } + /** + * Adds CSS classes and inline styles for typography features such as font sizes + * to the incoming attributes array. This will be applied to the block markup in + * the front-end. + * + * @since 5.6.0 + * @since 6.1.0 Used the style engine to generate CSS and classnames. + * @access private + * + * @param WP_Block_Type $block_type Block type. + * @param array $block_attributes Block attributes. + * @return array Typography CSS classes and inline styles. + */ + function wp_apply_typography_support($block_type, $block_attributes) + { + } + /** + * Generates an inline style value for a typography feature e.g. text decoration, + * text transform, and font style. + * + * Note: This function is for backwards compatibility. + * * It is necessary to parse older blocks whose typography styles contain presets. + * * It mostly replaces the deprecated `wp_typography_get_css_variable_inline_style()`, + * but skips compiling a CSS declaration as the style engine takes over this role. + * @link https://github.com/wordpress/gutenberg/pull/27555 + * + * @since 6.1.0 + * + * @param string $style_value A raw style value for a single typography feature from a block's style attribute. + * @param string $css_property Slug for the CSS property the inline style sets. + * @return string A CSS inline style value. + */ + function wp_typography_get_preset_inline_style_value($style_value, $css_property) + { + } + /** + * Renders typography styles/content to the block wrapper. + * + * @since 6.1.0 + * + * @param string $block_content Rendered block content. + * @param array $block Block object. + * @return string Filtered block content. + */ + function wp_render_typography_support($block_content, $block) + { + } + /** + * Checks a string for a unit and value and returns an array + * consisting of `'value'` and `'unit'`, e.g. array( '42', 'rem' ). + * + * @since 6.1.0 + * + * @param string|int|float $raw_value Raw size value from theme.json. + * @param array $options { + * Optional. An associative array of options. Default is empty array. + * + * @type string $coerce_to Coerce the value to rem or px. Default `'rem'`. + * @type int $root_size_value Value of root font size for rem|em <-> px conversion. Default `16`. + * @type string[] $acceptable_units An array of font size units. Default `array( 'rem', 'px', 'em' )`; + * } + * @return array|null An array consisting of `'value'` and `'unit'` properties on success. + * `null` on failure. + * @phpstan-param array{ + * coerce_to?: string, + * root_size_value?: int, + * acceptable_units?: string[], + * } $options + */ + function wp_get_typography_value_and_unit($raw_value, $options = array()) + { + } + /** + * Internal implementation of CSS clamp() based on available min/max viewport + * width and min/max font sizes. + * + * @since 6.1.0 + * @access private + * + * @param array $args { + * Optional. An associative array of values to calculate a fluid formula + * for font size. Default is empty array. + * + * @type string $maximum_viewport_width Maximum size up to which type will have fluidity. + * @type string $minimum_viewport_width Minimum viewport size from which type will have fluidity. + * @type string $maximum_font_size Maximum font size for any clamp() calculation. + * @type string $minimum_font_size Minimum font size for any clamp() calculation. + * @type int $scale_factor A scale factor to determine how fast a font scales within boundaries. + * } + * @return string|null A font-size value using clamp() on success, otherwise null. + * @phpstan-param array{ + * maximum_viewport_width?: string, + * minimum_viewport_width?: string, + * maximum_font_size?: string, + * minimum_font_size?: string, + * scale_factor?: int, + * } $args + */ + function wp_get_computed_fluid_typography_value($args = array()) + { + } + /** + * Returns a font-size value based on a given font-size preset. + * Takes into account fluid typography parameters and attempts to return a CSS + * formula depending on available, valid values. + * + * @since 6.1.0 + * @since 6.1.1 Adjusted rules for min and max font sizes. + * + * @param array $preset { + * Required. fontSizes preset value as seen in theme.json. + * + * @type string $name Name of the font size preset. + * @type string $slug Kebab-case, unique identifier for the font size preset. + * @type string|int|float $size CSS font-size value, including units if applicable. + * } + * @param bool $should_use_fluid_typography An override to switch fluid typography "on". Can be used for unit testing. + * Default is false. + * @return string|null Font-size value or null if a size is not passed in $preset. + * @phpstan-param array{ + * name?: string, + * slug?: string, + * size?: string|int|float, + * } $preset + */ + function wp_get_typography_font_size_value($preset, $should_use_fluid_typography = \false) + { + } + /** + * Block support utility functions. + * + * @package WordPress + * @subpackage Block Supports + * @since 6.0.0 + */ + /** + * Checks whether serialization of the current block's supported properties + * should occur. + * + * @since 6.0.0 + * @access private + * + * @param WP_Block_Type $block_type Block type. + * @param string $feature_set Name of block support feature set.. + * @param string $feature Optional name of individual feature to check. + * + * @return boolean Whether to serialize block support styles & classes. + */ + function wp_should_skip_block_supports_serialization($block_type, $feature_set, $feature = \null) + { + } + /** + * For backward compatibility reasons, + * block themes might be using block-templates or block-template-parts, + * this function ensures we fallback to these folders properly. + * + * @since 5.9.0 + * + * @param string $theme_stylesheet The stylesheet. Default is to leverage the main theme root. + * + * @return string[] { + * Folder names used by block themes. + * + * @type string $wp_template Theme-relative directory name for block templates. + * @type string $wp_template_part Theme-relative directory name for block template parts. + * } + * @phpstan-return array{ + * wp_template: string, + * wp_template_part: string, + * } + */ + function get_block_theme_folders($theme_stylesheet = \null) + { + } + /** + * Returns a filtered list of allowed area values for template parts. + * + * @since 5.9.0 + * + * @return array The supported template part area values. + */ + function get_allowed_block_template_part_areas() + { + } + /** + * Returns a filtered list of default template types, containing their + * localized titles and descriptions. + * + * @since 5.9.0 + * + * @return array The default template types. + */ + function get_default_block_template_types() + { + } + /** + * Checks whether the input 'area' is a supported value. + * Returns the input if supported, otherwise returns the 'uncategorized' value. + * + * @since 5.9.0 + * @access private + * + * @param string $type Template part area name. + * @return string Input if supported, else the uncategorized value. + */ + function _filter_block_template_part_area($type) + { + } + /** + * Finds all nested template part file paths in a theme's directory. + * + * @since 5.9.0 + * @access private + * + * @param string $base_directory The theme's file path. + * @return array A list of paths to all template part files. + */ + function _get_block_templates_paths($base_directory) + { + } + /** + * Retrieves the template file from the theme for a given slug. + * + * @since 5.9.0 + * @access private + * + * @param string $template_type 'wp_template' or 'wp_template_part'. + * @param string $slug Template slug. + * @return array|null Template. + */ + function _get_block_template_file($template_type, $slug) + { + } + /** + * Retrieves the template files from the theme. + * + * @since 5.9.0 + * @access private + * + * @param string $template_type 'wp_template' or 'wp_template_part'. + * @return array Template. + */ + function _get_block_templates_files($template_type) + { + } + /** + * Attempts to add custom template information to the template item. + * + * @since 5.9.0 + * @access private + * + * @param array $template_item Template to add information to (requires 'slug' field). + * @return array Template item. + */ + function _add_block_template_info($template_item) + { + } + /** + * Attempts to add the template part's area information to the input template. + * + * @since 5.9.0 + * @access private + * + * @param array $template_info Template to add information to (requires 'type' and 'slug' fields). + * @return array Template info. + */ + function _add_block_template_part_area_info($template_info) + { + } + /** + * Returns an array containing the references of + * the passed blocks and their inner blocks. + * + * @since 5.9.0 + * @access private + * + * @param array $blocks array of blocks. + * @return array block references to the passed blocks and their inner blocks. + */ + function _flatten_blocks(&$blocks) + { + } + /** + * Parses wp_template content and injects the active theme's + * stylesheet as a theme attribute into each wp_template_part + * + * @since 5.9.0 + * @access private + * + * @param string $template_content serialized wp_template content. + * @return string Updated 'wp_template' content. + */ + function _inject_theme_attribute_in_block_template_content($template_content) + { + } + /** + * Parses a block template and removes the theme attribute from each template part. + * + * @since 5.9.0 + * @access private + * + * @param string $template_content Serialized block template content. + * @return string Updated block template content. + */ + function _remove_theme_attribute_in_block_template_content($template_content) + { + } + /** + * Builds a unified template object based on a theme file. + * + * @since 5.9.0 + * @access private + * + * @param array $template_file Theme file. + * @param string $template_type 'wp_template' or 'wp_template_part'. + * @return WP_Block_Template Template. + */ + function _build_block_template_result_from_file($template_file, $template_type) + { + } + /** + * Builds the title and description of a post-specific template based on the underlying referenced post. + * + * Mutates the underlying template object. + * + * @since 6.1.0 + * @access private + * + * @param string $post_type Post type, e.g. page, post, product. + * @param string $slug Slug of the post, e.g. a-story-about-shoes. + * @param WP_Block_Template $template Template to mutate adding the description and title computed. + * @return bool Returns true if the referenced post was found and false otherwise. + */ + function _wp_build_title_and_description_for_single_post_type_block_template($post_type, $slug, \WP_Block_Template $template) + { + } + /** + * Builds the title and description of a taxonomy-specific template based on the underlying entity referenced. + * + * Mutates the underlying template object. + * + * @since 6.1.0 + * @access private + * + * @param string $taxonomy Identifier of the taxonomy, e.g. category. + * @param string $slug Slug of the term, e.g. shoes. + * @param WP_Block_Template $template Template to mutate adding the description and title computed. + * @return bool True if the term referenced was found and false otherwise. + */ + function _wp_build_title_and_description_for_taxonomy_block_template($taxonomy, $slug, \WP_Block_Template $template) + { + } + /** + * Builds a unified template object based a post Object. + * + * @since 5.9.0 + * @access private + * + * @param WP_Post $post Template post. + * @return WP_Block_Template|WP_Error Template. + */ + function _build_block_template_result_from_post($post) + { + } + /** + * Retrieves a list of unified template objects based on a query. + * + * @since 5.8.0 + * + * @param array $query { + * Optional. Arguments to retrieve templates. + * + * @type array $slug__in List of slugs to include. + * @type int $wp_id Post ID of customized template. + * @type string $area A 'wp_template_part_area' taxonomy value to filter by (for wp_template_part template type only). + * @type string $post_type Post type to get the templates for. + * } + * @param string $template_type 'wp_template' or 'wp_template_part'. + * @return array Templates. + * @phpstan-param array{ + * slug__in?: array, + * wp_id?: int, + * area?: string, + * post_type?: string, + * } $query + */ + function get_block_templates($query = array(), $template_type = 'wp_template') + { + } + /** + * Retrieves a single unified template object using its id. + * + * @since 5.8.0 + * + * @param string $id Template unique identifier (example: theme_slug//template_slug). + * @param string $template_type Optional. Template type: `'wp_template'` or '`wp_template_part'`. + * Default `'wp_template'`. + * @return WP_Block_Template|null Template. + */ + function get_block_template($id, $template_type = 'wp_template') + { + } + /** + * Retrieves a unified template object based on a theme file. + * + * This is a fallback of get_block_template(), used when no templates are found in the database. + * + * @since 5.9.0 + * + * @param string $id Template unique identifier (example: theme_slug//template_slug). + * @param string $template_type Optional. Template type: `'wp_template'` or '`wp_template_part'`. + * Default `'wp_template'`. + * @return WP_Block_Template|null The found block template, or null if there isn't one. + */ + function get_block_file_template($id, $template_type = 'wp_template') + { + } + /** + * Prints a block template part. + * + * @since 5.9.0 + * + * @param string $part The block template part to print. Use "header" or "footer". + */ + function block_template_part($part) + { + } + /** + * Prints the header block template part. + * + * @since 5.9.0 + */ + function block_header_area() + { + } + /** + * Prints the footer block template part. + * + * @since 5.9.0 + */ + function block_footer_area() + { + } + /** + * Determines whether a theme directory should be ignored during export. + * + * @since 6.0.0 + * + * @param string $path The path of the file in the theme. + * @return Bool Whether this file is in an ignored directory. + */ + function wp_is_theme_directory_ignored($path) + { + } + /** + * Creates an export of the current templates and + * template parts from the site editor at the + * specified path in a ZIP file. + * + * @since 5.9.0 + * @since 6.0.0 Adds the whole theme to the export archive. + * + * @return WP_Error|string Path of the ZIP file or error on failure. + */ + function wp_generate_block_templates_export_file() + { + } + /** + * Gets the template hierarchy for the given template slug to be created. + * + * + * Note: Always add `index` as the last fallback template. + * + * @since 6.1.0 + * + * @param string $slug The template slug to be created. + * @param boolean $is_custom Optional. Indicates if a template is custom or + * part of the template hierarchy. Default false. + * @param string $template_prefix Optional. The template prefix for the created template. + * Used to extract the main template type, e.g. + * in `taxonomy-books` the `taxonomy` is extracted. + * Default empty string. + * @return string[] The template hierarchy. + */ + function get_template_hierarchy($slug, $is_custom = \false, $template_prefix = '') + { + } + /** + * Block template loader functions. + * + * @package WordPress + */ + /** + * Adds necessary filters to use 'wp_template' posts instead of theme template files. + * + * @access private + * @since 5.9.0 + */ + function _add_template_loader_filters() + { + } + /** + * Finds a block template with equal or higher specificity than a given PHP template file. + * + * Internally, this communicates the block content that needs to be used by the template canvas through a global variable. + * + * @since 5.8.0 + * + * @global string $_wp_current_template_content + * + * @param string $template Path to the template. See locate_template(). + * @param string $type Sanitized filename without extension. + * @param string[] $templates A list of template candidates, in descending order of priority. + * @return string The path to the Site Editor template canvas file, or the fallback PHP template. + */ + function locate_block_template($template, $type, array $templates) + { + } + /** + * Returns the correct 'wp_template' to render for the request template type. + * + * @access private + * @since 5.8.0 + * @since 5.9.0 Added the `$fallback_template` parameter. + * + * @param string $template_type The current template type. + * @param string[] $template_hierarchy The current template hierarchy, ordered by priority. + * @param string $fallback_template A PHP fallback template to use if no matching block template is found. + * @return WP_Block_Template|null template A template object, or null if none could be found. + */ + function resolve_block_template($template_type, $template_hierarchy, $fallback_template) + { + } + /** + * Displays title tag with content, regardless of whether theme has title-tag support. + * + * @access private + * @since 5.8.0 + * + * @see _wp_render_title_tag() + */ + function _block_template_render_title_tag() + { + } + /** + * Returns the markup for the current template. + * + * @access private + * @since 5.8.0 + * + * @global string $_wp_current_template_content + * @global WP_Embed $wp_embed + * + * @return string Block template markup. + */ + function get_the_block_template_html() + { + } + /** + * Renders a 'viewport' meta tag. + * + * This is hooked into {@see 'wp_head'} to decouple its output from the default template canvas. + * + * @access private + * @since 5.8.0 + */ + function _block_template_viewport_meta_tag() + { + } + /** + * Strips .php or .html suffix from template file names. + * + * @access private + * @since 5.8.0 + * + * @param string $template_file Template file name. + * @return string Template file name without extension. + */ + function _strip_template_file_suffix($template_file) + { + } + /** + * Removes post details from block context when rendering a block template. + * + * @access private + * @since 5.8.0 + * + * @param array $context Default context. + * + * @return array Filtered context. + */ + function _block_template_render_without_post_block_context($context) + { + } + /** + * Sets the current WP_Query to return auto-draft posts. + * + * The auto-draft status indicates a new post, so allow the the WP_Query instance to + * return an auto-draft post for template resolution when editing a new post. + * + * @access private + * @since 5.9.0 + * + * @param WP_Query $wp_query Current WP_Query instance, passed by reference. + */ + function _resolve_template_for_new_post($wp_query) + { + } + /** + * Returns the correct template for the site's home page. + * + * @access private + * @since 6.0.0 + * + * @return array|null A template object, or null if none could be found. + */ + function _resolve_home_block_template() + { + } + /** + * Functions related to registering and parsing blocks. + * + * @package WordPress + * @subpackage Blocks + * @since 5.0.0 + */ + /** + * Removes the block asset's path prefix if provided. + * + * @since 5.5.0 + * + * @param string $asset_handle_or_path Asset handle or prefixed path. + * @return string Path without the prefix or the original value. + */ + function remove_block_asset_path_prefix($asset_handle_or_path) + { + } + /** + * Generates the name for an asset based on the name of the block + * and the field name provided. + * + * @since 5.5.0 + * @since 6.1.0 Added `$index` parameter. + * + * @param string $block_name Name of the block. + * @param string $field_name Name of the metadata field. + * @param int $index Optional. Index of the asset when multiple items passed. + * Default 0. + * @return string Generated asset name for the block's field. + */ + function generate_block_asset_handle($block_name, $field_name, $index = 0) + { + } + /** + * Finds a script handle for the selected block metadata field. It detects + * when a path to file was provided and finds a corresponding asset file + * with details necessary to register the script under automatically + * generated handle name. It returns unprocessed script handle otherwise. + * + * @since 5.5.0 + * @since 6.1.0 Added `$index` parameter. + * + * @param array $metadata Block metadata. + * @param string $field_name Field name to pick from metadata. + * @param int $index Optional. Index of the script to register when multiple items passed. + * Default 0. + * @return string|false Script handle provided directly or created through + * script's registration, or false on failure. + */ + function register_block_script_handle($metadata, $field_name, $index = 0) + { + } + /** + * Finds a style handle for the block metadata field. It detects when a path + * to file was provided and registers the style under automatically + * generated handle name. It returns unprocessed style handle otherwise. + * + * @since 5.5.0 + * @since 6.1.0 Added `$index` parameter. + * + * @param array $metadata Block metadata. + * @param string $field_name Field name to pick from metadata. + * @param int $index Optional. Index of the style to register when multiple items passed. + * Default 0. + * @return string|false Style handle provided directly or created through + * style's registration, or false on failure. + */ + function register_block_style_handle($metadata, $field_name, $index = 0) + { + } + /** + * Gets i18n schema for block's metadata read from `block.json` file. + * + * @since 5.9.0 + * + * @return object The schema for block's metadata. + */ + function get_block_metadata_i18n_schema() + { + } + /** + * Registers a block type from the metadata stored in the `block.json` file. + * + * @since 5.5.0 + * @since 5.7.0 Added support for `textdomain` field and i18n handling for all translatable fields. + * @since 5.9.0 Added support for `variations` and `viewScript` fields. + * @since 6.1.0 Added support for `render` field. + * + * @param string $file_or_folder Path to the JSON file with metadata definition for + * the block or path to the folder where the `block.json` file is located. + * If providing the path to a JSON file, the filename must end with `block.json`. + * @param array $args Optional. Array of block type arguments. Accepts any public property + * of `WP_Block_Type`. See WP_Block_Type::__construct() for information + * on accepted arguments. Default empty array. + * @return WP_Block_Type|false The registered block type on success, or false on failure. + * @phpstan-param array{ + * api_version?: string, + * title?: string, + * category?: string|null, + * parent?: string[]|null, + * ancestor?: string[]|null, + * icon?: string|null, + * description?: string, + * keywords?: string[], + * textdomain?: string|null, + * styles?: array[], + * variations?: array[], + * supports?: array|null, + * example?: array|null, + * render_callback?: callable|null, + * attributes?: array|null, + * uses_context?: string[], + * provides_context?: string[]|null, + * editor_script_handles?: string[], + * script_handles?: string[], + * view_script_handles?: string[], + * editor_style_handles?: string[], + * style_handles?: string[], + * } $args See WP_Block_Type::__construct() + */ + function register_block_type_from_metadata($file_or_folder, $args = array()) + { + } + /** + * Registers a block type. The recommended way is to register a block type using + * the metadata stored in the `block.json` file. + * + * @since 5.0.0 + * @since 5.8.0 First parameter now accepts a path to the `block.json` file. + * + * @param string|WP_Block_Type $block_type Block type name including namespace, or alternatively + * a path to the JSON file with metadata definition for the block, + * or a path to the folder where the `block.json` file is located, + * or a complete WP_Block_Type instance. + * In case a WP_Block_Type is provided, the $args parameter will be ignored. + * @param array $args Optional. Array of block type arguments. Accepts any public property + * of `WP_Block_Type`. See WP_Block_Type::__construct() for information + * on accepted arguments. Default empty array. + * + * @return WP_Block_Type|false The registered block type on success, or false on failure. + * @phpstan-param array{ + * api_version?: string, + * title?: string, + * category?: string|null, + * parent?: string[]|null, + * ancestor?: string[]|null, + * icon?: string|null, + * description?: string, + * keywords?: string[], + * textdomain?: string|null, + * styles?: array[], + * variations?: array[], + * supports?: array|null, + * example?: array|null, + * render_callback?: callable|null, + * attributes?: array|null, + * uses_context?: string[], + * provides_context?: string[]|null, + * editor_script_handles?: string[], + * script_handles?: string[], + * view_script_handles?: string[], + * editor_style_handles?: string[], + * style_handles?: string[], + * } $args See WP_Block_Type::__construct() + */ + function register_block_type($block_type, $args = array()) + { + } + /** + * Unregisters a block type. + * + * @since 5.0.0 + * + * @param string|WP_Block_Type $name Block type name including namespace, or alternatively + * a complete WP_Block_Type instance. + * @return WP_Block_Type|false The unregistered block type on success, or false on failure. + */ + function unregister_block_type($name) + { + } + /** + * Determines whether a post or content string has blocks. + * + * This test optimizes for performance rather than strict accuracy, detecting + * the pattern of a block but not validating its structure. For strict accuracy, + * you should use the block parser on post content. + * + * @since 5.0.0 + * + * @see parse_blocks() + * + * @param int|string|WP_Post|null $post Optional. Post content, post ID, or post object. + * Defaults to global $post. + * @return bool Whether the post has blocks. + */ + function has_blocks($post = \null) + { + } + /** + * Determines whether a $post or a string contains a specific block type. + * + * This test optimizes for performance rather than strict accuracy, detecting + * whether the block type exists but not validating its structure and not checking + * reusable blocks. For strict accuracy, you should use the block parser on post content. + * + * @since 5.0.0 + * + * @see parse_blocks() + * + * @param string $block_name Full block type to look for. + * @param int|string|WP_Post|null $post Optional. Post content, post ID, or post object. + * Defaults to global $post. + * @return bool Whether the post content contains the specified block. + */ + function has_block($block_name, $post = \null) + { + } + /** + * Returns an array of the names of all registered dynamic block types. + * + * @since 5.0.0 + * + * @return string[] Array of dynamic block names. + */ + function get_dynamic_block_names() + { + } + /** + * Given an array of attributes, returns a string in the serialized attributes + * format prepared for post content. + * + * The serialized result is a JSON-encoded string, with unicode escape sequence + * substitution for characters which might otherwise interfere with embedding + * the result in an HTML comment. + * + * This function must produce output that remains in sync with the output of + * the serializeAttributes JavaScript function in the block editor in order + * to ensure consistent operation between PHP and JavaScript. + * + * @since 5.3.1 + * + * @param array $block_attributes Attributes object. + * @return string Serialized attributes. + */ + function serialize_block_attributes($block_attributes) + { + } + /** + * Returns the block name to use for serialization. This will remove the default + * "core/" namespace from a block name. + * + * @since 5.3.1 + * + * @param string|null $block_name Optional. Original block name. Null if the block name is unknown, + * e.g. Classic blocks have their name set to null. Default null. + * @return string Block name to use for serialization. + */ + function strip_core_block_namespace($block_name = \null) + { + } + /** + * Returns the content of a block, including comment delimiters. + * + * @since 5.3.1 + * + * @param string|null $block_name Block name. Null if the block name is unknown, + * e.g. Classic blocks have their name set to null. + * @param array $block_attributes Block attributes. + * @param string $block_content Block save content. + * @return string Comment-delimited block content. + */ + function get_comment_delimited_block_content($block_name, $block_attributes, $block_content) + { + } + /** + * Returns the content of a block, including comment delimiters, serializing all + * attributes from the given parsed block. + * + * This should be used when preparing a block to be saved to post content. + * Prefer `render_block` when preparing a block for display. Unlike + * `render_block`, this does not evaluate a block's `render_callback`, and will + * instead preserve the markup as parsed. + * + * @since 5.3.1 + * + * @param array $block A representative array of a single parsed block object. See WP_Block_Parser_Block. + * @return string String of rendered HTML. + */ + function serialize_block($block) + { + } + /** + * Returns a joined string of the aggregate serialization of the given + * parsed blocks. + * + * @since 5.3.1 + * + * @param array[] $blocks An array of representative arrays of parsed block objects. See serialize_block(). + * @return string String of rendered HTML. + */ + function serialize_blocks($blocks) + { + } + /** + * Filters and sanitizes block content to remove non-allowable HTML + * from parsed block attribute values. + * + * @since 5.3.1 + * + * @param string $text Text that may contain block content. + * @param array[]|string $allowed_html Optional. An array of allowed HTML elements and attributes, + * or a context name such as 'post'. See wp_kses_allowed_html() + * for the list of accepted context names. Default 'post'. + * @param string[] $allowed_protocols Optional. Array of allowed URL protocols. + * Defaults to the result of wp_allowed_protocols(). + * @return string The filtered and sanitized content result. + */ + function filter_block_content($text, $allowed_html = 'post', $allowed_protocols = array()) + { + } + /** + * Filters and sanitizes a parsed block to remove non-allowable HTML + * from block attribute values. + * + * @since 5.3.1 + * + * @param WP_Block_Parser_Block $block The parsed block object. + * @param array[]|string $allowed_html An array of allowed HTML elements and attributes, + * or a context name such as 'post'. See wp_kses_allowed_html() + * for the list of accepted context names. + * @param string[] $allowed_protocols Optional. Array of allowed URL protocols. + * Defaults to the result of wp_allowed_protocols(). + * @return array The filtered and sanitized block object result. + */ + function filter_block_kses($block, $allowed_html, $allowed_protocols = array()) + { + } + /** + * Filters and sanitizes a parsed block attribute value to remove + * non-allowable HTML. + * + * @since 5.3.1 + * + * @param string[]|string $value The attribute value to filter. + * @param array[]|string $allowed_html An array of allowed HTML elements and attributes, + * or a context name such as 'post'. See wp_kses_allowed_html() + * for the list of accepted context names. + * @param string[] $allowed_protocols Optional. Array of allowed URL protocols. + * Defaults to the result of wp_allowed_protocols(). + * @return string[]|string The filtered and sanitized result. + */ + function filter_block_kses_value($value, $allowed_html, $allowed_protocols = array()) + { + } + /** + * Parses blocks out of a content string, and renders those appropriate for the excerpt. + * + * As the excerpt should be a small string of text relevant to the full post content, + * this function renders the blocks that are most likely to contain such text. + * + * @since 5.0.0 + * + * @param string $content The content to parse. + * @return string The parsed and filtered content. + */ + function excerpt_remove_blocks($content) + { + } + /** + * Renders inner blocks from the allowed wrapper blocks + * for generating an excerpt. + * + * @since 5.8.0 + * @access private + * + * @param array $parsed_block The parsed block. + * @param array $allowed_blocks The list of allowed inner blocks. + * @return string The rendered inner blocks. + */ + function _excerpt_render_inner_blocks($parsed_block, $allowed_blocks) + { + } + /** + * Renders a single block into a HTML string. + * + * @since 5.0.0 + * + * @global WP_Post $post The post to edit. + * + * @param array $parsed_block A single parsed block object. + * @return string String of rendered HTML. + */ + function render_block($parsed_block) + { + } + /** + * Parses blocks out of a content string. + * + * @since 5.0.0 + * + * @param string $content Post content. + * @return array[] Array of parsed block objects. + */ + function parse_blocks($content) + { + } + /** + * Parses dynamic blocks out of `post_content` and re-renders them. + * + * @since 5.0.0 + * + * @param string $content Post content. + * @return string Updated post content. + */ + function do_blocks($content) + { + } + /** + * If do_blocks() needs to remove wpautop() from the `the_content` filter, this re-adds it afterwards, + * for subsequent `the_content` usage. + * + * @since 5.0.0 + * @access private + * + * @param string $content The post content running through this filter. + * @return string The unmodified content. + */ + function _restore_wpautop_hook($content) + { + } + /** + * Returns the current version of the block format that the content string is using. + * + * If the string doesn't contain blocks, it returns 0. + * + * @since 5.0.0 + * + * @param string $content Content to test. + * @return int The block format version is 1 if the content contains one or more blocks, 0 otherwise. + */ + function block_version($content) + { + } + /** + * Registers a new block style. + * + * @since 5.3.0 + * + * @link https://developer.wordpress.org/block-editor/reference-guides/block-api/block-styles/ + * + * @param string $block_name Block type name including namespace. + * @param array $style_properties Array containing the properties of the style name, + * label, style (name of the stylesheet to be enqueued), + * inline_style (string containing the CSS to be added). + * @return bool True if the block style was registered with success and false otherwise. + */ + function register_block_style($block_name, $style_properties) + { + } + /** + * Unregisters a block style. + * + * @since 5.3.0 + * + * @param string $block_name Block type name including namespace. + * @param string $block_style_name Block style name. + * @return bool True if the block style was unregistered with success and false otherwise. + */ + function unregister_block_style($block_name, $block_style_name) + { + } + /** + * Checks whether the current block type supports the feature requested. + * + * @since 5.8.0 + * + * @param WP_Block_Type $block_type Block type to check for support. + * @param array $feature Path to a specific feature to check support for. + * @param mixed $default Optional. Fallback value for feature support. Default false. + * @return bool Whether the feature is supported. + */ + function block_has_support($block_type, $feature, $default = \false) + { + } + /** + * Converts typography keys declared under `supports.*` to `supports.typography.*`. + * + * Displays a `_doing_it_wrong()` notice when a block using the older format is detected. + * + * @since 5.8.0 + * + * @param array $metadata Metadata for registering a block type. + * @return array Filtered metadata for registering a block type. + */ + function wp_migrate_old_typography_shape($metadata) + { + } + /** + * Helper function that constructs a WP_Query args array from + * a `Query` block properties. + * + * It's used in Query Loop, Query Pagination Numbers and Query Pagination Next blocks. + * + * @since 5.8.0 + * @since 6.1.0 Added `query_loop_block_query_vars` filter and `parents` support in query. + * + * @param WP_Block $block Block instance. + * @param int $page Current query's page. + * + * @return array Returns the constructed WP_Query arguments. + */ + function build_query_vars_from_query_block($block, $page) + { + } + /** + * Helper function that returns the proper pagination arrow HTML for + * `QueryPaginationNext` and `QueryPaginationPrevious` blocks based + * on the provided `paginationArrow` from `QueryPagination` context. + * + * It's used in QueryPaginationNext and QueryPaginationPrevious blocks. + * + * @since 5.9.0 + * + * @param WP_Block $block Block instance. + * @param bool $is_next Flag for handling `next/previous` blocks. + * @return string|null The pagination arrow HTML or null if there is none. + */ + function get_query_pagination_arrow($block, $is_next) + { + } + /** + * Helper function that constructs a comment query vars array from the passed + * block properties. + * + * It's used with the Comment Query Loop inner blocks. + * + * @since 6.0.0 + * + * @param WP_Block $block Block instance. + * @return array Returns the comment query parameters to use with the + * WP_Comment_Query constructor. + */ + function build_comment_query_vars_from_block($block) + { + } + /** + * Helper function that returns the proper pagination arrow HTML for + * `CommentsPaginationNext` and `CommentsPaginationPrevious` blocks based on the + * provided `paginationArrow` from `CommentsPagination` context. + * + * It's used in CommentsPaginationNext and CommentsPaginationPrevious blocks. + * + * @since 6.0.0 + * + * @param WP_Block $block Block instance. + * @param string $pagination_type Optional. Type of the arrow we will be rendering. + * Accepts 'next' or 'previous'. Default 'next'. + * @return string|null The pagination arrow HTML or null if there is none. + */ + function get_comments_pagination_arrow($block, $pagination_type = 'next') + { + } + /** + * Server-side rendering of the `core/archives` block. + * + * @package WordPress + */ + /** + * Renders the `core/archives` block on server. + * + * @see WP_Widget_Archives + * + * @param array $attributes The block attributes. + * + * @return string Returns the post content with archives added. + */ + function render_block_core_archives($attributes) + { + } + /** + * Register archives block. + */ + function register_block_core_archives() + { + } + /** + * Server-side rendering of the `core/avatar` block. + * + * @package WordPress + */ + /** + * Renders the `core/avatar` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Return the avatar. + */ + function render_block_core_avatar($attributes, $content, $block) + { + } + /** + * Registers the `core/avatar` block on the server. + */ + function register_block_core_avatar() + { + } + /** + * Server-side rendering of the `core/block` block. + * + * @package WordPress + */ + /** + * Renders the `core/block` block on server. + * + * @param array $attributes The block attributes. + * + * @return string Rendered HTML of the referenced block. + */ + function render_block_core_block($attributes) + { + } + /** + * Registers the `core/block` block. + */ + function register_block_core_block() + { + } + /** + * Server-side rendering of the `core/calendar` block. + * + * @package WordPress + */ + /** + * Renders the `core/calendar` block on server. + * + * @param array $attributes The block attributes. + * + * @return string Returns the block content. + */ + function render_block_core_calendar($attributes) + { + } + /** + * Registers the `core/calendar` block on server. + */ + function register_block_core_calendar() + { + } + /** + * Returns whether or not there are any published posts. + * + * Used to hide the calendar block when there are no published posts. + * This compensates for a known Core bug: https://core.trac.wordpress.org/ticket/12016 + * + * @return bool Has any published posts or not. + */ + function block_core_calendar_has_published_posts() + { + } + /** + * Queries the database for any published post and saves + * a flag whether any published post exists or not. + * + * @return bool Has any published posts or not. + */ + function block_core_calendar_update_has_published_posts() + { + } + /** + * Handler for updating the has published posts flag when a post is deleted. + * + * @param int $post_id Deleted post ID. + */ + function block_core_calendar_update_has_published_post_on_delete($post_id) + { + } + /** + * Handler for updating the has published posts flag when a post status changes. + * + * @param string $new_status The status the post is changing to. + * @param string $old_status The status the post is changing from. + * @param WP_Post $post Post object. + */ + function block_core_calendar_update_has_published_post_on_transition_post_status($new_status, $old_status, $post) + { + } + /** + * Server-side rendering of the `core/categories` block. + * + * @package WordPress + */ + /** + * Renders the `core/categories` block on server. + * + * @param array $attributes The block attributes. + * + * @return string Returns the categories list/dropdown markup. + */ + function render_block_core_categories($attributes) + { + } + /** + * Generates the inline script for a categories dropdown field. + * + * @param string $dropdown_id ID of the dropdown field. + * + * @return string Returns the dropdown onChange redirection script. + */ + function build_dropdown_script_block_core_categories($dropdown_id) + { + } + /** + * Registers the `core/categories` block on server. + */ + function register_block_core_categories() + { + } + /** + * Server-side rendering of the `core/comment-author-name` block. + * + * @package WordPress + */ + /** + * Renders the `core/comment-author-name` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Return the post comment's author. + */ + function render_block_core_comment_author_name($attributes, $content, $block) + { + } + /** + * Registers the `core/comment-author-name` block on the server. + */ + function register_block_core_comment_author_name() + { + } + /** + * Server-side rendering of the `core/comment-content` block. + * + * @package WordPress + */ + /** + * Renders the `core/comment-content` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Return the post comment's content. + */ + function render_block_core_comment_content($attributes, $content, $block) + { + } + /** + * Registers the `core/comment-content` block on the server. + */ + function register_block_core_comment_content() + { + } + /** + * Server-side rendering of the `core/comment-date` block. + * + * @package WordPress + */ + /** + * Renders the `core/comment-date` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Return the post comment's date. + */ + function render_block_core_comment_date($attributes, $content, $block) + { + } + /** + * Registers the `core/comment-date` block on the server. + */ + function register_block_core_comment_date() + { + } + /** + * Server-side rendering of the `core/comment-edit-link` block. + * + * @package WordPress + */ + /** + * Renders the `core/comment-edit-link` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * + * @return string Return the post comment's date. + */ + function render_block_core_comment_edit_link($attributes, $content, $block) + { + } + /** + * Registers the `core/comment-edit-link` block on the server. + */ + function register_block_core_comment_edit_link() + { + } + /** + * Server-side rendering of the `core/comment-reply-link` block. + * + * @package WordPress + */ + /** + * Renders the `core/comment-reply-link` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Return the post comment's reply link. + */ + function render_block_core_comment_reply_link($attributes, $content, $block) + { + } + /** + * Registers the `core/comment-reply-link` block on the server. + */ + function register_block_core_comment_reply_link() + { + } + /** + * Server-side rendering of the `core/comment-template` block. + * + * @package WordPress + */ + /** + * Function that recursively renders a list of nested comments. + * + * @global int $comment_depth + * + * @param WP_Comment[] $comments The array of comments. + * @param WP_Block $block Block instance. + * @return string + */ + function block_core_comment_template_render_comments($comments, $block) + { + } + /** + * Renders the `core/comment-template` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * + * @return string Returns the HTML representing the comments using the layout + * defined by the block's inner blocks. + */ + function render_block_core_comment_template($attributes, $content, $block) + { + } + /** + * Registers the `core/comment-template` block on the server. + */ + function register_block_core_comment_template() + { + } + /** + * Server-side rendering of the `core/comments-pagination-next` block. + * + * @package WordPress + */ + /** + * Renders the `core/comments-pagination-next` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * + * @return string Returns the next comments link for the query pagination. + */ + function render_block_core_comments_pagination_next($attributes, $content, $block) + { + } + /** + * Registers the `core/comments-pagination-next` block on the server. + */ + function register_block_core_comments_pagination_next() + { + } + /** + * Server-side rendering of the `core/comments-pagination-numbers` block. + * + * @package WordPress + */ + /** + * Renders the `core/comments-pagination-numbers` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * + * @return string Returns the pagination numbers for the comments. + */ + function render_block_core_comments_pagination_numbers($attributes, $content, $block) + { + } + /** + * Registers the `core/comments-pagination-numbers` block on the server. + */ + function register_block_core_comments_pagination_numbers() + { + } + /** + * Server-side rendering of the `core/comments-pagination-previous` block. + * + * @package WordPress + */ + /** + * Renders the `core/comments-pagination-previous` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * + * @return string Returns the previous posts link for the comments pagination. + */ + function render_block_core_comments_pagination_previous($attributes, $content, $block) + { + } + /** + * Registers the `core/comments-pagination-previous` block on the server. + */ + function register_block_core_comments_pagination_previous() + { + } + /** + * Server-side rendering of the `core/comments-pagination` block. + * + * @package WordPress + */ + /** + * Renders the `core/comments-pagination` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * + * @return string Returns the wrapper for the Comments pagination. + */ + function render_block_core_comments_pagination($attributes, $content) + { + } + /** + * Registers the `core/comments-pagination` block on the server. + */ + function register_block_core_comments_pagination() + { + } + /** + * Server-side rendering of the `core/comments-title` block. + * + * @package WordPress + */ + /** + * Renders the `core/comments-title` block on the server. + * + * @param array $attributes Block attributes. + * + * @return string Return the post comments title. + */ + function render_block_core_comments_title($attributes) + { + } + /** + * Registers the `core/comments-title` block on the server. + */ + function register_block_core_comments_title() + { + } + /** + * Server-side rendering of the `core/comments` block. + * + * @package WordPress + */ + /** + * Renders the `core/comments` block on the server. + * + * This render callback is mainly for rendering a dynamic, legacy version of + * this block (the old `core/post-comments`). It uses the `comments_template()` + * function to generate the output, in the same way as classic PHP themes. + * + * As this callback will always run during SSR, first we need to check whether + * the block is in legacy mode. If not, the HTML generated in the editor is + * returned instead. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Returns the filtered post comments for the current post wrapped inside "p" tags. + */ + function render_block_core_comments($attributes, $content, $block) + { + } + /** + * Registers the `core/comments` block on the server. + */ + function register_block_core_comments() + { + } + /** + * Use the button block classes for the form-submit button. + * + * @param array $fields The default comment form arguments. + * + * @return array Returns the modified fields. + */ + function comments_block_form_defaults($fields) + { + } + /** + * Enqueues styles from the legacy `core/post-comments` block. These styles are + * required only by the block's fallback. + * + * @param string $block_name Name of the new block type. + */ + function enqueue_legacy_post_comments_block_styles($block_name) + { + } + /** + * Ensures backwards compatibility for any users running the Gutenberg plugin + * who have used Post Comments before it was merged into Comments Query Loop. + * + * The same approach was followed when core/query-loop was renamed to + * core/post-template. + * + * @see https://github.com/WordPress/gutenberg/pull/41807 + * @see https://github.com/WordPress/gutenberg/pull/32514 + */ + function register_legacy_post_comments_block() + { + } + /** + * Server-side rendering of the `core/cover` block. + * + * @package WordPress + */ + /** + * Renders the `core/cover` block on server. + * + * @param array $attributes The block attributes. + * @param string $content The block rendered content. + * + * @return string Returns the cover block markup, if useFeaturedImage is true. + */ + function render_block_core_cover($attributes, $content) + { + } + /** + * Registers the `core/cover` block renderer on server. + */ + function register_block_core_cover() + { + } + /** + * Server-side rendering of the `core/file` block. + * + * @package WordPress + */ + /** + * When the `core/file` block is rendering, check if we need to enqueue the `'wp-block-file-view` script. + * + * @param array $attributes The block attributes. + * @param string $content The block content. + * + * @return string Returns the block content. + */ + function render_block_core_file($attributes, $content) + { + } + /** + * Registers the `core/file` block on server. + */ + function register_block_core_file() + { + } + /** + * Server-side rendering of the `core/gallery` block. + * + * @package WordPress + */ + /** + * Handles backwards compatibility for Gallery Blocks, + * whose images feature a `data-id` attribute. + * + * Now that the Gallery Block contains inner Image Blocks, + * we add a custom `data-id` attribute before rendering the gallery + * so that the Image Block can pick it up in its render_callback. + * + * @param array $parsed_block The block being rendered. + * @return array The migrated block object. + */ + function block_core_gallery_data_id_backcompatibility($parsed_block) + { + } + /** + * Adds a style tag for the --wp--style--unstable-gallery-gap var. + * + * The Gallery block needs to recalculate Image block width based on + * the current gap setting in order to maintain the number of flex columns + * so a css var is added to allow this. + * + * @param array $attributes Attributes of the block being rendered. + * @param string $content Content of the block being rendered. + * @return string The content of the block being rendered. + */ + function block_core_gallery_render($attributes, $content) + { + } + /** + * Registers the `core/gallery` block on server. + */ + function register_block_core_gallery() + { + } + /** + * Server-side rendering of the `core/home-link` block. + * + * @package WordPress + */ + /** + * Build an array with CSS classes and inline styles defining the colors + * which will be applied to the home link markup in the front-end. + * + * @param array $context home link block context. + * @return array Colors CSS classes and inline styles. + */ + function block_core_home_link_build_css_colors($context) + { + } + /** + * Build an array with CSS classes and inline styles defining the font sizes + * which will be applied to the home link markup in the front-end. + * + * @param array $context Home link block context. + * @return array Font size CSS classes and inline styles. + */ + function block_core_home_link_build_css_font_sizes($context) + { + } + /** + * Builds an array with classes and style for the li wrapper + * + * @param array $context Home link block context. + * @return string The li wrapper attributes. + */ + function block_core_home_link_build_li_wrapper_attributes($context) + { + } + /** + * Renders the `core/home-link` block. + * + * @param array $attributes The block attributes. + * @param string $content The saved content. + * @param WP_Block $block The parsed block. + * + * @return string Returns the post content with the home url added. + */ + function render_block_core_home_link($attributes, $content, $block) + { + } + /** + * Register the home block + * + * @uses render_block_core_home_link() + * @throws WP_Error An WP_Error exception parsing the block definition. + */ + function register_block_core_home_link() + { + } + /** + * Server-side rendering of the `core/image` block. + * + * @package WordPress + */ + /** + * Renders the `core/image` block on the server, + * adding a data-id attribute to the element if core/gallery has added on pre-render. + * + * @param array $attributes The block attributes. + * @param string $content The block content. + * @return string Returns the block content with the data-id attribute added. + */ + function render_block_core_image($attributes, $content) + { + } + /** + * Registers the `core/image` block on server. + */ + function register_block_core_image() + { + } + /** + * Registers core block types using metadata files. + * Dynamic core blocks are registered separately. + * + * @since 5.5.0 + */ + function register_core_block_types_from_metadata() + { + } + /** + * Server-side rendering of the `core/latest-comments` block. + * + * @package WordPress + */ + /** + * Get the post title. + * + * The post title is fetched and if it is blank then a default string is + * returned. + * + * Copied from `wp-admin/includes/template.php`, but we can't include that + * file because: + * + * 1. It causes bugs with test fixture generation and strange Docker 255 error + * codes. + * 2. It's in the admin; ideally we *shouldn't* be including files from the + * admin for a block's output. It's a very small/simple function as well, + * so duplicating it isn't too terrible. + * + * @since 3.3.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @return string The post title if set; "(no title)" if no title is set. + */ + function wp_latest_comments_draft_or_post_title($post = 0) + { + } + /** + * Renders the `core/latest-comments` block on server. + * + * @param array $attributes The block attributes. + * + * @return string Returns the post content with latest comments added. + */ + function render_block_core_latest_comments($attributes = array()) + { + } + /** + * Registers the `core/latest-comments` block. + */ + function register_block_core_latest_comments() + { + } + /** + * Callback for the excerpt_length filter used by + * the Latest Posts block at render time. + * + * @return int Returns the global $block_core_latest_posts_excerpt_length variable + * to allow the excerpt_length filter respect the Latest Block setting. + */ + function block_core_latest_posts_get_excerpt_length() + { + } + /** + * Renders the `core/latest-posts` block on server. + * + * @param array $attributes The block attributes. + * + * @return string Returns the post content with latest posts added. + */ + function render_block_core_latest_posts($attributes) + { + } + /** + * Registers the `core/latest-posts` block on server. + */ + function register_block_core_latest_posts() + { + } + /** + * Handles outdated versions of the `core/latest-posts` block by converting + * attribute `categories` from a numeric string to an array with key `id`. + * + * This is done to accommodate the changes introduced in #20781 that sought to + * add support for multiple categories to the block. However, given that this + * block is dynamic, the usual provisions for block migration are insufficient, + * as they only act when a block is loaded in the editor. + * + * TODO: Remove when and if the bottom client-side deprecation for this block + * is removed. + * + * @param array $block A single parsed block object. + * + * @return array The migrated block object. + */ + function block_core_latest_posts_migrate_categories($block) + { + } + /** + * Server-side rendering of the `core/legacy-widget` block. + * + * @package WordPress + */ + /** + * Renders the 'core/legacy-widget' block. + * + * @param array $attributes The block attributes. + * + * @return string Rendered block. + */ + function render_block_core_legacy_widget($attributes) + { + } + /** + * Registers the 'core/legacy-widget' block. + */ + function register_block_core_legacy_widget() + { + } + /** + * Intercepts any request with legacy-widget-preview in the query param and, if + * set, renders a page containing a preview of the requested Legacy Widget + * block. + */ + function handle_legacy_widget_preview_iframe() + { + } + /** + * Server-side rendering of the `core/loginout` block. + * + * @package WordPress + */ + /** + * Renders the `core/loginout` block on server. + * + * @param array $attributes The block attributes. + * + * @return string Returns the login-out link or form. + */ + function render_block_core_loginout($attributes) + { + } + /** + * Registers the `core/loginout` block on server. + */ + function register_block_core_loginout() + { + } + /** + * Server-side rendering of the `core/navigation-link` block. + * + * @package WordPress + */ + /** + * Build an array with CSS classes and inline styles defining the colors + * which will be applied to the navigation markup in the front-end. + * + * @param array $context Navigation block context. + * @param array $attributes Block attributes. + * @return array Colors CSS classes and inline styles. + */ + function block_core_navigation_link_build_css_colors($context, $attributes) + { + } + /** + * Build an array with CSS classes and inline styles defining the font sizes + * which will be applied to the navigation markup in the front-end. + * + * @param array $context Navigation block context. + * @return array Font size CSS classes and inline styles. + */ + function block_core_navigation_link_build_css_font_sizes($context) + { + } + /** + * Returns the top-level submenu SVG chevron icon. + * + * @return string + */ + function block_core_navigation_link_render_submenu_icon() + { + } + /** + * Renders the `core/navigation-link` block. + * + * @param array $attributes The block attributes. + * @param string $content The saved content. + * @param WP_Block $block The parsed block. + * + * @return string Returns the post content with the legacy widget added. + */ + function render_block_core_navigation_link($attributes, $content, $block) + { + } + /** + * Returns a navigation link variation + * + * @param WP_Taxonomy|WP_Post_Type $entity post type or taxonomy entity. + * @param string $kind string of value 'taxonomy' or 'post-type'. + * + * @return array + */ + function build_variation_for_navigation_link($entity, $kind) + { + } + /** + * Register the navigation link block. + * + * @uses render_block_core_navigation() + * @throws WP_Error An WP_Error exception parsing the block definition. + */ + function register_block_core_navigation_link() + { + } + /** + * Server-side rendering of the `core/navigation-submenu` block. + * + * @package WordPress + */ + /** + * Build an array with CSS classes and inline styles defining the colors + * which will be applied to the navigation markup in the front-end. + * + * @param array $context Navigation block context. + * @param array $attributes Block attributes. + * @return array Colors CSS classes and inline styles. + */ + function block_core_navigation_submenu_build_css_colors($context, $attributes) + { + } + /** + * Build an array with CSS classes and inline styles defining the font sizes + * which will be applied to the navigation markup in the front-end. + * + * @param array $context Navigation block context. + * @return array Font size CSS classes and inline styles. + */ + function block_core_navigation_submenu_build_css_font_sizes($context) + { + } + /** + * Returns the top-level submenu SVG chevron icon. + * + * @return string + */ + function block_core_navigation_submenu_render_submenu_icon() + { + } + /** + * Renders the `core/navigation-submenu` block. + * + * @param array $attributes The block attributes. + * @param string $content The saved content. + * @param WP_Block $block The parsed block. + * + * @return string Returns the post content with the legacy widget added. + */ + function render_block_core_navigation_submenu($attributes, $content, $block) + { + } + /** + * Register the navigation submenu block. + * + * @uses render_block_core_navigation_submenu() + * @throws WP_Error An WP_Error exception parsing the block definition. + */ + function register_block_core_navigation_submenu() + { + } + /** + * Returns the menu items for a WordPress menu location. + * + * @param string $location The menu location. + * @return array Menu items for the location. + */ + function block_core_navigation_get_menu_items_at_location($location) + { + } + /** + * Sorts a standard array of menu items into a nested structure keyed by the + * id of the parent menu. + * + * @param array $menu_items Menu items to sort. + * @return array An array keyed by the id of the parent menu where each element + * is an array of menu items that belong to that parent. + */ + function block_core_navigation_sort_menu_items_by_parent_id($menu_items) + { + } + /** + * Turns menu item data into a nested array of parsed blocks + * + * @param array $menu_items An array of menu items that represent + * an individual level of a menu. + * @param array $menu_items_by_parent_id An array keyed by the id of the + * parent menu where each element is an + * array of menu items that belong to + * that parent. + * @return array An array of parsed block data. + */ + function block_core_navigation_parse_blocks_from_menu_items($menu_items, $menu_items_by_parent_id) + { + } + /** + * Build an array with CSS classes and inline styles defining the colors + * which will be applied to the navigation markup in the front-end. + * + * @param array $attributes Navigation block attributes. + * + * @return array Colors CSS classes and inline styles. + */ + function block_core_navigation_build_css_colors($attributes) + { + } + /** + * Build an array with CSS classes and inline styles defining the font sizes + * which will be applied to the navigation markup in the front-end. + * + * @param array $attributes Navigation block attributes. + * + * @return array Font size CSS classes and inline styles. + */ + function block_core_navigation_build_css_font_sizes($attributes) + { + } + /** + * Returns the top-level submenu SVG chevron icon. + * + * @return string + */ + function block_core_navigation_render_submenu_icon() + { + } + /** + * Finds the most recently published `wp_navigation` Post. + * + * @return WP_Post|null the first non-empty Navigation or null. + */ + function block_core_navigation_get_most_recently_published_navigation() + { + } + /** + * Filter out empty "null" blocks from the block list. + * 'parse_blocks' includes a null block with '\n\n' as the content when + * it encounters whitespace. This is not a bug but rather how the parser + * is designed. + * + * @param array $parsed_blocks the parsed blocks to be normalized. + * @return array the normalized parsed blocks. + */ + function block_core_navigation_filter_out_empty_blocks($parsed_blocks) + { + } + /** + * Retrieves the appropriate fallback to be used on the front of the + * site when there is no menu assigned to the Nav block. + * + * This aims to mirror how the fallback mechanic for wp_nav_menu works. + * See https://developer.wordpress.org/reference/functions/wp_nav_menu/#more-information. + * + * @return array the array of blocks to be used as a fallback. + */ + function block_core_navigation_get_fallback_blocks() + { + } + /** + * Iterate through all inner blocks recursively and get navigation link block's post IDs. + * + * @param WP_Block_List $inner_blocks Block list class instance. + * + * @return array Array of post IDs. + */ + function block_core_navigation_get_post_ids($inner_blocks) + { + } + /** + * Get post IDs from a navigation link block instance. + * + * @param WP_Block $block Instance of a block. + * + * @return array Array of post IDs. + */ + function block_core_navigation_from_block_get_post_ids($block) + { + } + /** + * Renders the `core/navigation` block on server. + * + * @param array $attributes The block attributes. + * @param string $content The saved content. + * @param WP_Block $block The parsed block. + * + * @return string Returns the post content with the legacy widget added. + */ + function render_block_core_navigation($attributes, $content, $block) + { + } + /** + * Register the navigation block. + * + * @uses render_block_core_navigation() + * @throws WP_Error An WP_Error exception parsing the block definition. + */ + function register_block_core_navigation() + { + } + /** + * Filter that changes the parsed attribute values of navigation blocks contain typographic presets to contain the values directly. + * + * @param array $parsed_block The block being rendered. + * + * @return array The block being rendered without typographic presets. + */ + function block_core_navigation_typographic_presets_backcompatibility($parsed_block) + { + } + /** + * Server-side rendering of the `core/pages` block. + * + * @package WordPress + */ + /** + * Build an array with CSS classes and inline styles defining the colors + * which will be applied to the pages markup in the front-end when it is a descendant of navigation. + * + * @param array $attributes Block attributes. + * @param array $context Navigation block context. + * @return array Colors CSS classes and inline styles. + */ + function block_core_page_list_build_css_colors($attributes, $context) + { + } + /** + * Build an array with CSS classes and inline styles defining the font sizes + * which will be applied to the pages markup in the front-end when it is a descendant of navigation. + * + * @param array $context Navigation block context. + * @return array Font size CSS classes and inline styles. + */ + function block_core_page_list_build_css_font_sizes($context) + { + } + /** + * Outputs Page list markup from an array of pages with nested children. + * + * @param boolean $open_submenus_on_click Whether to open submenus on click instead of hover. + * @param boolean $show_submenu_icons Whether to show submenu indicator icons. + * @param boolean $is_navigation_child If block is a child of Navigation block. + * @param array $nested_pages The array of nested pages. + * @param array $active_page_ancestor_ids An array of ancestor ids for active page. + * @param array $colors Color information for overlay styles. + * @param integer $depth The nesting depth. + * + * @return string List markup. + */ + function block_core_page_list_render_nested_page_list($open_submenus_on_click, $show_submenu_icons, $is_navigation_child, $nested_pages, $active_page_ancestor_ids = array(), $colors = array(), $depth = 0) + { + } + /** + * Outputs nested array of pages + * + * @param array $current_level The level being iterated through. + * @param array $children The children grouped by parent post ID. + * + * @return array The nested array of pages. + */ + function block_core_page_list_nest_pages($current_level, $children) + { + } + /** + * Renders the `core/page-list` block on server. + * + * @param array $attributes The block attributes. + * @param string $content The saved content. + * @param WP_Block $block The parsed block. + * + * @return string Returns the page list markup. + */ + function render_block_core_page_list($attributes, $content, $block) + { + } + /** + * Registers the `core/pages` block on server. + */ + function register_block_core_page_list() + { + } + /** + * Server-side rendering of the `core/pattern` block. + * + * @package WordPress + */ + /** + * Registers the `core/pattern` block on the server. + * + * @return void + */ + function register_block_core_pattern() + { + } + /** + * Renders the `core/pattern` block on the server. + * + * @param array $attributes Block attributes. + * + * @return string Returns the output of the pattern. + */ + function render_block_core_pattern($attributes) + { + } + /** + * Server-side rendering of the `core/post-author-biography` block. + * + * @package WordPress + */ + /** + * Renders the `core/post-author-biography` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Returns the rendered post author biography block. + */ + function render_block_core_post_author_biography($attributes, $content, $block) + { + } + /** + * Registers the `core/post-author-biography` block on the server. + */ + function register_block_core_post_author_biography() + { + } + /** + * Server-side rendering of the `core/post-author` block. + * + * @package WordPress + */ + /** + * Renders the `core/post-author` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Returns the rendered author block. + */ + function render_block_core_post_author($attributes, $content, $block) + { + } + /** + * Registers the `core/post-author` block on the server. + */ + function register_block_core_post_author() + { + } + /** + * Server-side rendering of the `core/post-comments-form` block. + * + * @package WordPress + */ + /** + * Renders the `core/post-comments-form` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Returns the filtered post comments form for the current post. + */ + function render_block_core_post_comments_form($attributes, $content, $block) + { + } + /** + * Registers the `core/post-comments-form` block on the server. + */ + function register_block_core_post_comments_form() + { + } + /** + * Use the button block classes for the form-submit button. + * + * @param array $fields The default comment form arguments. + * + * @return array Returns the modified fields. + */ + function post_comments_form_block_form_defaults($fields) + { + } + /** + * Server-side rendering of the `core/post-content` block. + * + * @package WordPress + */ + /** + * Renders the `core/post-content` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Returns the filtered post content of the current post. + */ + function render_block_core_post_content($attributes, $content, $block) + { + } + /** + * Registers the `core/post-content` block on the server. + */ + function register_block_core_post_content() + { + } + /** + * Server-side rendering of the `core/post-date` block. + * + * @package WordPress + */ + /** + * Renders the `core/post-date` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Returns the filtered post date for the current post wrapped inside "time" tags. + */ + function render_block_core_post_date($attributes, $content, $block) + { + } + /** + * Registers the `core/post-date` block on the server. + */ + function register_block_core_post_date() + { + } + /** + * Server-side rendering of the `core/post-excerpt` block. + * + * @package WordPress + */ + /** + * Renders the `core/post-excerpt` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Returns the filtered post excerpt for the current post wrapped inside "p" tags. + */ + function render_block_core_post_excerpt($attributes, $content, $block) + { + } + /** + * Registers the `core/post-excerpt` block on the server. + */ + function register_block_core_post_excerpt() + { + } + /** + * Server-side rendering of the `core/post-featured-image` block. + * + * @package WordPress + */ + /** + * Renders the `core/post-featured-image` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Returns the featured image for the current post. + */ + function render_block_core_post_featured_image($attributes, $content, $block) + { + } + /** + * Generate markup for the HTML element that will be used for the overlay. + * + * @param array $attributes Block attributes. + * + * @return string HTML markup in string format. + */ + function get_block_core_post_featured_image_overlay_element_markup($attributes) + { + } + /** + * Generates class names and styles to apply the border support styles for + * the Post Featured Image block. + * + * @param array $attributes The block attributes. + * @return array The border-related classnames and styles for the block. + */ + function get_block_core_post_featured_image_border_attributes($attributes) + { + } + /** + * Registers the `core/post-featured-image` block on the server. + */ + function register_block_core_post_featured_image() + { + } + /** + * Server-side rendering of the `core/post-navigation-link` block. + * + * @package WordPress + */ + /** + * Renders the `core/post-navigation-link` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * + * @return string Returns the next or previous post link that is adjacent to the current post. + */ + function render_block_core_post_navigation_link($attributes, $content) + { + } + /** + * Registers the `core/post-navigation-link` block on the server. + */ + function register_block_core_post_navigation_link() + { + } + /** + * Server-side rendering of the `core/post-template` block. + * + * @package WordPress + */ + /** + * Determines whether a block list contains a block that uses the featured image. + * + * @param WP_Block_List $inner_blocks Inner block instance. + * + * @return bool Whether the block list contains a block that uses the featured image. + */ + function block_core_post_template_uses_featured_image($inner_blocks) + { + } + /** + * Renders the `core/post-template` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * + * @return string Returns the output of the query, structured using the layout defined by the block's inner blocks. + */ + function render_block_core_post_template($attributes, $content, $block) + { + } + /** + * Registers the `core/post-template` block on the server. + */ + function register_block_core_post_template() + { + } + /** + * Server-side rendering of the `core/post-terms` block. + * + * @package WordPress + */ + /** + * Renders the `core/post-terms` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Returns the filtered post terms for the current post wrapped inside "a" tags. + */ + function render_block_core_post_terms($attributes, $content, $block) + { + } + /** + * Registers the `core/post-terms` block on the server. + */ + function register_block_core_post_terms() + { + } + /** + * Server-side rendering of the `core/post-title` block. + * + * @package WordPress + */ + /** + * Renders the `core/post-title` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * + * @return string Returns the filtered post title for the current post wrapped inside "h1" tags. + */ + function render_block_core_post_title($attributes, $content, $block) + { + } + /** + * Registers the `core/post-title` block on the server. + */ + function register_block_core_post_title() + { + } + /** + * Server-side rendering of the `core/query-no-results` block. + * + * @package WordPress + */ + /** + * Renders the `core/query-no-results` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * + * @return string Returns the wrapper for the no results block. + */ + function render_block_core_query_no_results($attributes, $content, $block) + { + } + /** + * Registers the `core/query-no-results` block on the server. + */ + function register_block_core_query_no_results() + { + } + /** + * Server-side rendering of the `core/query-pagination-next` block. + * + * @package WordPress + */ + /** + * Renders the `core/query-pagination-next` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * + * @return string Returns the next posts link for the query pagination. + */ + function render_block_core_query_pagination_next($attributes, $content, $block) + { + } + /** + * Registers the `core/query-pagination-next` block on the server. + */ + function register_block_core_query_pagination_next() + { + } + /** + * Server-side rendering of the `core/query-pagination-numbers` block. + * + * @package WordPress + */ + /** + * Renders the `core/query-pagination-numbers` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * + * @return string Returns the pagination numbers for the Query. + */ + function render_block_core_query_pagination_numbers($attributes, $content, $block) + { + } + /** + * Registers the `core/query-pagination-numbers` block on the server. + */ + function register_block_core_query_pagination_numbers() + { + } + /** + * Server-side rendering of the `core/query-pagination-previous` block. + * + * @package WordPress + */ + /** + * Renders the `core/query-pagination-previous` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * + * @return string Returns the previous posts link for the query. + */ + function render_block_core_query_pagination_previous($attributes, $content, $block) + { + } + /** + * Registers the `core/query-pagination-previous` block on the server. + */ + function register_block_core_query_pagination_previous() + { + } + /** + * Server-side rendering of the `core/query-pagination` block. + * + * @package WordPress + */ + /** + * Renders the `core/query-pagination` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * + * @return string Returns the wrapper for the Query pagination. + */ + function render_block_core_query_pagination($attributes, $content) + { + } + /** + * Registers the `core/query-pagination` block on the server. + */ + function register_block_core_query_pagination() + { + } + /** + * Server-side rendering of the `core/query-title` block. + * + * @package WordPress + */ + /** + * Renders the `core/query-title` block on the server. + * For now it only supports Archive title, + * using queried object information + * + * @param array $attributes Block attributes. + * + * @return string Returns the query title based on the queried object. + */ + function render_block_core_query_title($attributes) + { + } + /** + * Registers the `core/query-title` block on the server. + */ + function register_block_core_query_title() + { + } + /** + * Server-side rendering of the `core/query` block. + * + * @package WordPress + */ + /** + * Registers the `core/query` block on the server. + */ + function register_block_core_query() + { + } + /** + * Server-side rendering of the `core/read-more` block. + * + * @package WordPress + */ + /** + * Renders the `core/read-more` block on the server. + * + * @param array $attributes Block attributes. + * @param string $content Block default content. + * @param WP_Block $block Block instance. + * @return string Returns the post link. + */ + function render_block_core_read_more($attributes, $content, $block) + { + } + /** + * Registers the `core/read-more` block on the server. + */ + function register_block_core_read_more() + { + } + /** + * Server-side rendering of the `core/rss` block. + * + * @package WordPress + */ + /** + * Renders the `core/rss` block on server. + * + * @param array $attributes The block attributes. + * + * @return string Returns the block content with received rss items. + */ + function render_block_core_rss($attributes) + { + } + /** + * Registers the `core/rss` block on server. + */ + function register_block_core_rss() + { + } + /** + * Server-side rendering of the `core/search` block. + * + * @package WordPress + */ + /** + * Dynamically renders the `core/search` block. + * + * @param array $attributes The block attributes. + * + * @return string The search block markup. + */ + function render_block_core_search($attributes) + { + } + /** + * Registers the `core/search` block on the server. + */ + function register_block_core_search() + { + } + /** + * Builds the correct top level classnames for the 'core/search' block. + * + * @param array $attributes The block attributes. + * + * @return string The classnames used in the block. + */ + function classnames_for_block_core_search($attributes) + { + } + /** + * This generates a CSS rule for the given border property and side if provided. + * Based on whether the Search block is configured to display the button inside + * or not, the generated rule is injected into the appropriate collection of + * styles for later application in the block's markup. + * + * @param array $attributes The block attributes. + * @param string $property Border property to generate rule for e.g. width or color. + * @param string $side Optional side border. The dictates the value retrieved and final CSS property. + * @param array $wrapper_styles Current collection of wrapper styles. + * @param array $button_styles Current collection of button styles. + * @param array $input_styles Current collection of input styles. + * + * @return void + */ + function apply_block_core_search_border_style($attributes, $property, $side, &$wrapper_styles, &$button_styles, &$input_styles) + { + } + /** + * This adds CSS rules for a given border property e.g. width or color. It + * injects rules into the provided wrapper, button and input style arrays for + * uniform "flat" borders or those with individual sides configured. + * + * @param array $attributes The block attributes. + * @param string $property Border property to generate rule for e.g. width or color. + * @param array $wrapper_styles Current collection of wrapper styles. + * @param array $button_styles Current collection of button styles. + * @param array $input_styles Current collection of input styles. + * + * @return void + */ + function apply_block_core_search_border_styles($attributes, $property, &$wrapper_styles, &$button_styles, &$input_styles) + { + } + /** + * Builds an array of inline styles for the search block. + * + * The result will contain one entry for shared styles such as those for the + * inner input or button and a second for the inner wrapper should the block + * be positioning the button "inside". + * + * @param array $attributes The block attributes. + * + * @return array Style HTML attribute. + */ + function styles_for_block_core_search($attributes) + { + } + /** + * Returns typography classnames depending on whether there are named font sizes/families . + * + * @param array $attributes The block attributes. + * + * @return string The typography color classnames to be applied to the block elements. + */ + function get_typography_classes_for_block_core_search($attributes) + { + } + /** + * Returns typography styles to be included in an HTML style tag. + * This excludes text-decoration, which is applied only to the label and button elements of the search block. + * + * @param array $attributes The block attributes. + * + * @return string A string of typography CSS declarations. + */ + function get_typography_styles_for_block_core_search($attributes) + { + } + /** + * Returns border color classnames depending on whether there are named or custom border colors. + * + * @param array $attributes The block attributes. + * + * @return string The border color classnames to be applied to the block elements. + */ + function get_border_color_classes_for_block_core_search($attributes) + { + } + /** + * Returns color classnames depending on whether there are named or custom text and background colors. + * + * @param array $attributes The block attributes. + * + * @return string The color classnames to be applied to the block elements. + */ + function get_color_classes_for_block_core_search($attributes) + { + } + /** + * Server-side rendering of the `core/shortcode` block. + * + * @package WordPress + */ + /** + * Performs wpautop() on the shortcode block content. + * + * @param array $attributes The block attributes. + * @param string $content The block content. + * + * @return string Returns the block content. + */ + function render_block_core_shortcode($attributes, $content) + { + } + /** + * Registers the `core/shortcode` block on server. + */ + function register_block_core_shortcode() + { + } + /** + * Server-side rendering of the `core/site-logo` block. + * + * @package WordPress + */ + /** + * Renders the `core/site-logo` block on the server. + * + * @param array $attributes The block attributes. + * + * @return string The render. + */ + function render_block_core_site_logo($attributes) + { + } + /** + * Register a core site setting for a site logo + */ + function register_block_core_site_logo_setting() + { + } + /** + * Register a core site setting for a site icon + */ + function register_block_core_site_icon_setting() + { + } + /** + * Registers the `core/site-logo` block on the server. + */ + function register_block_core_site_logo() + { + } + /** + * Overrides the custom logo with a site logo, if the option is set. + * + * @param string $custom_logo The custom logo set by a theme. + * + * @return string The site logo if set. + */ + function _override_custom_logo_theme_mod($custom_logo) + { + } + /** + * Updates the site_logo option when the custom_logo theme-mod gets updated. + * + * @param mixed $value Attachment ID of the custom logo or an empty value. + * @return mixed + */ + function _sync_custom_logo_to_site_logo($value) + { + } + /** + * Deletes the site_logo when the custom_logo theme mod is removed. + * + * @param array $old_value Previous theme mod settings. + * @param array $value Updated theme mod settings. + */ + function _delete_site_logo_on_remove_custom_logo($old_value, $value) + { + } + /** + * Deletes the site logo when all theme mods are being removed. + */ + function _delete_site_logo_on_remove_theme_mods() + { + } + /** + * Hooks `_delete_site_logo_on_remove_custom_logo` in `update_option_theme_mods_$theme`. + * Hooks `_delete_site_logo_on_remove_theme_mods` in `delete_option_theme_mods_$theme`. + * + * Runs on `setup_theme` to account for dynamically-switched themes in the Customizer. + */ + function _delete_site_logo_on_remove_custom_logo_on_setup_theme() + { + } + /** + * Removes the custom_logo theme-mod when the site_logo option gets deleted. + */ + function _delete_custom_logo_on_remove_site_logo() + { + } + /** + * Server-side rendering of the `core/site-tagline` block. + * + * @package WordPress + */ + /** + * Renders the `core/site-tagline` block on the server. + * + * @param array $attributes The block attributes. + * + * @return string The render. + */ + function render_block_core_site_tagline($attributes) + { + } + /** + * Registers the `core/site-tagline` block on the server. + */ + function register_block_core_site_tagline() + { + } + /** + * Server-side rendering of the `core/site-title` block. + * + * @package WordPress + */ + /** + * Renders the `core/site-title` block on the server. + * + * @param array $attributes The block attributes. + * + * @return string The render. + */ + function render_block_core_site_title($attributes) + { + } + /** + * Registers the `core/site-title` block on the server. + */ + function register_block_core_site_title() + { + } + /** + * Server-side rendering of the `core/social-link` blocks. + * + * @package WordPress + */ + /** + * Renders the `core/social-link` block on server. + * + * @param Array $attributes The block attributes. + * @param String $content InnerBlocks content of the Block. + * @param WP_Block $block Block object. + * + * @return string Rendered HTML of the referenced block. + */ + function render_block_core_social_link($attributes, $content, $block) + { + } + /** + * Registers the `core/social-link` blocks. + */ + function register_block_core_social_link() + { + } + /** + * Returns the SVG for social link. + * + * @param string $service The service icon. + * + * @return string SVG Element for service icon. + */ + function block_core_social_link_get_icon($service) + { + } + /** + * Returns the brand name for social link. + * + * @param string $service The service icon. + * + * @return string Brand label. + */ + function block_core_social_link_get_name($service) + { + } + /** + * Returns the SVG for social link. + * + * @param string $service The service slug to extract data from. + * @param string $field The field ('name', 'icon', etc) to extract for a service. + * + * @return array|string + */ + function block_core_social_link_services($service = '', $field = '') + { + } + /** + * Returns CSS styles for icon and icon background colors. + * + * @param array $context Block context passed to Social Link. + * + * @return string Inline CSS styles for link's icon and background colors. + */ + function block_core_social_link_get_color_styles($context) + { + } + /** + * Server-side rendering of the `core/tag-cloud` block. + * + * @package WordPress + */ + /** + * Renders the `core/tag-cloud` block on server. + * + * @param array $attributes The block attributes. + * + * @return string Returns the tag cloud for selected taxonomy. + */ + function render_block_core_tag_cloud($attributes) + { + } + /** + * Registers the `core/tag-cloud` block on server. + */ + function register_block_core_tag_cloud() + { + } + /** + * Server-side rendering of the `core/template-part` block. + * + * @package WordPress + */ + /** + * Renders the `core/template-part` block on the server. + * + * @param array $attributes The block attributes. + * + * @return string The render. + */ + function render_block_core_template_part($attributes) + { + } + /** + * Returns an array of area variation objects for the template part block. + * + * @return array Array containing the block variation objects. + */ + function build_template_part_block_area_variations() + { + } + /** + * Returns an array of instance variation objects for the template part block + * + * @return array Array containing the block variation objects. + */ + function build_template_part_block_instance_variations() + { + } + /** + * Returns an array of all template part block variations. + * + * @return array Array containing the block variation objects. + */ + function build_template_part_block_variations() + { + } + /** + * Registers the `core/template-part` block on the server. + */ + function register_block_core_template_part() + { + } + /** + * Server-side rendering of the `core/term-description` block. + * + * @package WordPress + */ + /** + * Renders the `core/term-description` block on the server. + * + * @param array $attributes Block attributes. + * + * @return string Returns the description of the current taxonomy term, if available + */ + function render_block_core_term_description($attributes) + { + } + /** + * Registers the `core/term-description` block on the server. + */ + function register_block_core_term_description() + { + } + /** + * Server-side rendering of the `core/widget-group` block. + * + * @package WordPress + */ + /** + * Renders the 'core/widget-group' block. + * + * @param array $attributes The block attributes. + * @param string $content The block content. + * @param WP_Block $block The block. + * + * @return string Rendered block. + */ + function render_block_core_widget_group($attributes, $content, $block) + { + } + /** + * Registers the 'core/widget-group' block. + */ + function register_block_core_widget_group() + { + } + /** + * Make a note of the sidebar being rendered before WordPress starts rendering + * it. This lets us get to the current sidebar in + * render_block_core_widget_group(). + * + * @param int|string $index Index, name, or ID of the dynamic sidebar. + */ + function note_sidebar_being_rendered($index) + { + } + /** + * Clear whatever we set in note_sidebar_being_rendered() after WordPress + * finishes rendering a sidebar. + */ + function discard_sidebar_being_rendered() + { + } + /** + * Bookmark Template Functions for usage in Themes. + * + * @package WordPress + * @subpackage Template + */ + /** + * The formatted output of a list of bookmarks. + * + * The $bookmarks array must contain bookmark objects and will be iterated over + * to retrieve the bookmark to be used in the output. + * + * The output is formatted as HTML with no way to change that format. However, + * what is between, before, and after can be changed. The link itself will be + * HTML. + * + * This function is used internally by wp_list_bookmarks() and should not be + * used by themes. + * + * @since 2.1.0 + * @access private + * + * @param array $bookmarks List of bookmarks to traverse. + * @param string|array $args { + * Optional. Bookmarks arguments. + * + * @type int|bool $show_updated Whether to show the time the bookmark was last updated. + * Accepts 1|true or 0|false. Default 0|false. + * @type int|bool $show_description Whether to show the bookmark description. Accepts 1|true, + * Accepts 1|true or 0|false. Default 0|false. + * @type int|bool $show_images Whether to show the link image if available. Accepts 1|true + * or 0|false. Default 1|true. + * @type int|bool $show_name Whether to show link name if available. Accepts 1|true or + * 0|false. Default 0|false. + * @type string $before The HTML or text to prepend to each bookmark. Default `<li>`. + * @type string $after The HTML or text to append to each bookmark. Default `</li>`. + * @type string $link_before The HTML or text to prepend to each bookmark inside the anchor + * tags. Default empty. + * @type string $link_after The HTML or text to append to each bookmark inside the anchor + * tags. Default empty. + * @type string $between The string for use in between the link, description, and image. + * Default "\n". + * @type int|bool $show_rating Whether to show the link rating. Accepts 1|true or 0|false. + * Default 0|false. + * + * } + * @return string Formatted output in HTML + * @phpstan-param array{ + * show_updated?: int|bool, + * show_description?: int|bool, + * show_images?: int|bool, + * show_name?: int|bool, + * before?: string, + * after?: string, + * link_before?: string, + * link_after?: string, + * between?: string, + * show_rating?: int|bool, + * } $args + */ + function _walk_bookmarks($bookmarks, $args = '') + { + } + /** + * Retrieves or echoes all of the bookmarks. + * + * List of default arguments are as follows: + * + * These options define how the Category name will appear before the category + * links are displayed, if 'categorize' is 1. If 'categorize' is 0, then it will + * display for only the 'title_li' string and only if 'title_li' is not empty. + * + * @since 2.1.0 + * + * @see _walk_bookmarks() + * + * @param string|array $args { + * Optional. String or array of arguments to list bookmarks. + * + * @type string $orderby How to order the links by. Accepts post fields. Default 'name'. + * @type string $order Whether to order bookmarks in ascending or descending order. + * Accepts 'ASC' (ascending) or 'DESC' (descending). Default 'ASC'. + * @type int $limit Amount of bookmarks to display. Accepts 1+ or -1 for all. + * Default -1. + * @type string $category Comma-separated list of category IDs to include links from. + * Default empty. + * @type string $category_name Category to retrieve links for by name. Default empty. + * @type int|bool $hide_invisible Whether to show or hide links marked as 'invisible'. Accepts + * 1|true or 0|false. Default 1|true. + * @type int|bool $show_updated Whether to display the time the bookmark was last updated. + * Accepts 1|true or 0|false. Default 0|false. + * @type int|bool $echo Whether to echo or return the formatted bookmarks. Accepts + * 1|true (echo) or 0|false (return). Default 1|true. + * @type int|bool $categorize Whether to show links listed by category or in a single column. + * Accepts 1|true (by category) or 0|false (one column). Default 1|true. + * @type int|bool $show_description Whether to show the bookmark descriptions. Accepts 1|true or 0|false. + * Default 0|false. + * @type string $title_li What to show before the links appear. Default 'Bookmarks'. + * @type string $title_before The HTML or text to prepend to the $title_li string. Default '<h2>'. + * @type string $title_after The HTML or text to append to the $title_li string. Default '</h2>'. + * @type string|array $class The CSS class or an array of classes to use for the $title_li. + * Default 'linkcat'. + * @type string $category_before The HTML or text to prepend to $title_before if $categorize is true. + * String must contain '%id' and '%class' to inherit the category ID and + * the $class argument used for formatting in themes. + * Default '<li id="%id" class="%class">'. + * @type string $category_after The HTML or text to append to $title_after if $categorize is true. + * Default '</li>'. + * @type string $category_orderby How to order the bookmark category based on term scheme if $categorize + * is true. Default 'name'. + * @type string $category_order Whether to order categories in ascending or descending order if + * $categorize is true. Accepts 'ASC' (ascending) or 'DESC' (descending). + * Default 'ASC'. + * } + * @return void|string Void if 'echo' argument is true, HTML list of bookmarks if 'echo' is false. + * @phpstan-param array{ + * orderby?: string, + * order?: string, + * limit?: int, + * category?: string, + * category_name?: string, + * hide_invisible?: int|bool, + * show_updated?: int|bool, + * echo?: int|bool, + * categorize?: int|bool, + * show_description?: int|bool, + * title_li?: string, + * title_before?: string, + * title_after?: string, + * class?: string|array, + * category_before?: string, + * category_after?: string, + * category_orderby?: string, + * category_order?: string, + * } $args + */ + function wp_list_bookmarks($args = '') + { + } + /** + * Link/Bookmark API + * + * @package WordPress + * @subpackage Bookmark + */ + /** + * Retrieves bookmark data. + * + * @since 2.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|stdClass $bookmark + * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which + * correspond to an stdClass object, an associative array, or a numeric array, + * respectively. Default OBJECT. + * @param string $filter Optional. How to sanitize bookmark fields. Default 'raw'. + * @return array|object|null Type returned depends on $output value. + */ + function get_bookmark($bookmark, $output = \OBJECT, $filter = 'raw') + { + } + /** + * Retrieves single bookmark data item or field. + * + * @since 2.3.0 + * + * @param string $field The name of the data field to return. + * @param int $bookmark The bookmark ID to get field. + * @param string $context Optional. The context of how the field will be used. + * @return string|WP_Error + */ + function get_bookmark_field($field, $bookmark, $context = 'display') + { + } + /** + * Retrieves the list of bookmarks. + * + * Attempts to retrieve from the cache first based on MD5 hash of arguments. If + * that fails, then the query will be built from the arguments and executed. The + * results will be stored to the cache. + * + * @since 2.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string|array $args { + * Optional. String or array of arguments to retrieve bookmarks. + * + * @type string $orderby How to order the links by. Accepts 'id', 'link_id', 'name', 'link_name', + * 'url', 'link_url', 'visible', 'link_visible', 'rating', 'link_rating', + * 'owner', 'link_owner', 'updated', 'link_updated', 'notes', 'link_notes', + * 'description', 'link_description', 'length' and 'rand'. + * When `$orderby` is 'length', orders by the character length of + * 'link_name'. Default 'name'. + * @type string $order Whether to order bookmarks in ascending or descending order. + * Accepts 'ASC' (ascending) or 'DESC' (descending). Default 'ASC'. + * @type int $limit Amount of bookmarks to display. Accepts any positive number or + * -1 for all. Default -1. + * @type string $category Comma-separated list of category IDs to include links from. + * Default empty. + * @type string $category_name Category to retrieve links for by name. Default empty. + * @type int|bool $hide_invisible Whether to show or hide links marked as 'invisible'. Accepts + * 1|true or 0|false. Default 1|true. + * @type int|bool $show_updated Whether to display the time the bookmark was last updated. + * Accepts 1|true or 0|false. Default 0|false. + * @type string $include Comma-separated list of bookmark IDs to include. Default empty. + * @type string $exclude Comma-separated list of bookmark IDs to exclude. Default empty. + * @type string $search Search terms. Will be SQL-formatted with wildcards before and after + * and searched in 'link_url', 'link_name' and 'link_description'. + * Default empty. + * } + * @return object[] List of bookmark row objects. + * @phpstan-param array{ + * orderby?: string, + * order?: string, + * limit?: int, + * category?: string, + * category_name?: string, + * hide_invisible?: int|bool, + * show_updated?: int|bool, + * include?: string, + * exclude?: string, + * search?: string, + * } $args + */ + function get_bookmarks($args = '') + { + } + /** + * Sanitizes all bookmark fields. + * + * @since 2.3.0 + * + * @param stdClass|array $bookmark Bookmark row. + * @param string $context Optional. How to filter the fields. Default 'display'. + * @return stdClass|array Same type as $bookmark but with fields sanitized. + */ + function sanitize_bookmark($bookmark, $context = 'display') + { + } + /** + * Sanitizes a bookmark field. + * + * Sanitizes the bookmark fields based on what the field name is. If the field + * has a strict value set, then it will be tested for that, else a more generic + * filtering is applied. After the more strict filter is applied, if the `$context` + * is 'raw' then the value is immediately return. + * + * Hooks exist for the more generic cases. With the 'edit' context, the {@see 'edit_$field'} + * filter will be called and passed the `$value` and `$bookmark_id` respectively. + * + * With the 'db' context, the {@see 'pre_$field'} filter is called and passed the value. + * The 'display' context is the final context and has the `$field` has the filter name + * and is passed the `$value`, `$bookmark_id`, and `$context`, respectively. + * + * @since 2.3.0 + * + * @param string $field The bookmark field. + * @param mixed $value The bookmark field value. + * @param int $bookmark_id Bookmark ID. + * @param string $context How to filter the field value. Accepts 'raw', 'edit', 'db', + * 'display', 'attribute', or 'js'. Default 'display'. + * @return mixed The filtered value. + */ + function sanitize_bookmark_field($field, $value, $bookmark_id, $context) + { + } + /** + * Deletes the bookmark cache. + * + * @since 2.7.0 + * + * @param int $bookmark_id Bookmark ID. + */ + function clean_bookmark_cache($bookmark_id) + { + } + /** + * Sets up Object Cache Global and assigns it. + * + * @since 2.0.0 + * + * @global WP_Object_Cache $wp_object_cache + */ + function wp_cache_init() + { + } + /** + * Adds data to the cache, if the cache key doesn't already exist. + * + * @since 2.0.0 + * + * @see WP_Object_Cache::add() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @param int|string $key The cache key to use for retrieval later. + * @param mixed $data The data to add to the cache. + * @param string $group Optional. The group to add the cache to. Enables the same key + * to be used across groups. Default empty. + * @param int $expire Optional. When the cache data should expire, in seconds. + * Default 0 (no expiration). + * @return bool True on success, false if cache key and group already exist. + */ + function wp_cache_add($key, $data, $group = '', $expire = 0) + { + } + /** + * Adds multiple values to the cache in one call. + * + * @since 6.0.0 + * + * @see WP_Object_Cache::add_multiple() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @param array $data Array of keys and values to be set. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @param int $expire Optional. When to expire the cache contents, in seconds. + * Default 0 (no expiration). + * @return bool[] Array of return values, grouped by key. Each value is either + * true on success, or false if cache key and group already exist. + */ + function wp_cache_add_multiple(array $data, $group = '', $expire = 0) + { + } + /** + * Replaces the contents of the cache with new data. + * + * @since 2.0.0 + * + * @see WP_Object_Cache::replace() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @param int|string $key The key for the cache data that should be replaced. + * @param mixed $data The new data to store in the cache. + * @param string $group Optional. The group for the cache data that should be replaced. + * Default empty. + * @param int $expire Optional. When to expire the cache contents, in seconds. + * Default 0 (no expiration). + * @return bool True if contents were replaced, false if original value does not exist. + */ + function wp_cache_replace($key, $data, $group = '', $expire = 0) + { + } + /** + * Saves the data to the cache. + * + * Differs from wp_cache_add() and wp_cache_replace() in that it will always write data. + * + * @since 2.0.0 + * + * @see WP_Object_Cache::set() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @param int|string $key The cache key to use for retrieval later. + * @param mixed $data The contents to store in the cache. + * @param string $group Optional. Where to group the cache contents. Enables the same key + * to be used across groups. Default empty. + * @param int $expire Optional. When to expire the cache contents, in seconds. + * Default 0 (no expiration). + * @return bool True on success, false on failure. + */ + function wp_cache_set($key, $data, $group = '', $expire = 0) + { + } + /** + * Sets multiple values to the cache in one call. + * + * @since 6.0.0 + * + * @see WP_Object_Cache::set_multiple() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @param array $data Array of keys and values to be set. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @param int $expire Optional. When to expire the cache contents, in seconds. + * Default 0 (no expiration). + * @return bool[] Array of return values, grouped by key. Each value is either + * true on success, or false on failure. + */ + function wp_cache_set_multiple(array $data, $group = '', $expire = 0) + { + } + /** + * Retrieves the cache contents from the cache by key and group. + * + * @since 2.0.0 + * + * @see WP_Object_Cache::get() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @param int|string $key The key under which the cache contents are stored. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @param bool $force Optional. Whether to force an update of the local cache + * from the persistent cache. Default false. + * @param bool $found Optional. Whether the key was found in the cache (passed by reference). + * Disambiguates a return of false, a storable value. Default null. + * @return mixed|false The cache contents on success, false on failure to retrieve contents. + */ + function wp_cache_get($key, $group = '', $force = \false, &$found = \null) + { + } + /** + * Retrieves multiple values from the cache in one call. + * + * @since 5.5.0 + * + * @see WP_Object_Cache::get_multiple() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @param array $keys Array of keys under which the cache contents are stored. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @param bool $force Optional. Whether to force an update of the local cache + * from the persistent cache. Default false. + * @return array Array of return values, grouped by key. Each value is either + * the cache contents on success, or false on failure. + */ + function wp_cache_get_multiple($keys, $group = '', $force = \false) + { + } + /** + * Removes the cache contents matching key and group. + * + * @since 2.0.0 + * + * @see WP_Object_Cache::delete() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @param int|string $key What the contents in the cache are called. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @return bool True on successful removal, false on failure. + */ + function wp_cache_delete($key, $group = '') + { + } + /** + * Deletes multiple values from the cache in one call. + * + * @since 6.0.0 + * + * @see WP_Object_Cache::delete_multiple() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @param array $keys Array of keys under which the cache to deleted. + * @param string $group Optional. Where the cache contents are grouped. Default empty. + * @return bool[] Array of return values, grouped by key. Each value is either + * true on success, or false if the contents were not deleted. + */ + function wp_cache_delete_multiple(array $keys, $group = '') + { + } + /** + * Increments numeric cache item's value. + * + * @since 3.3.0 + * + * @see WP_Object_Cache::incr() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @param int|string $key The key for the cache contents that should be incremented. + * @param int $offset Optional. The amount by which to increment the item's value. + * Default 1. + * @param string $group Optional. The group the key is in. Default empty. + * @return int|false The item's new value on success, false on failure. + */ + function wp_cache_incr($key, $offset = 1, $group = '') + { + } + /** + * Decrements numeric cache item's value. + * + * @since 3.3.0 + * + * @see WP_Object_Cache::decr() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @param int|string $key The cache key to decrement. + * @param int $offset Optional. The amount by which to decrement the item's value. + * Default 1. + * @param string $group Optional. The group the key is in. Default empty. + * @return int|false The item's new value on success, false on failure. + */ + function wp_cache_decr($key, $offset = 1, $group = '') + { + } + /** + * Removes all cache items. + * + * @since 2.0.0 + * + * @see WP_Object_Cache::flush() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @return bool True on success, false on failure. + */ + function wp_cache_flush() + { + } + /** + * Removes all cache items from the in-memory runtime cache. + * + * @since 6.0.0 + * + * @see WP_Object_Cache::flush() + * + * @return bool True on success, false on failure. + */ + function wp_cache_flush_runtime() + { + } + /** + * Removes all cache items in a group, if the object cache implementation supports it. + * + * Before calling this function, always check for group flushing support using the + * `wp_cache_supports( 'flush_group' )` function. + * + * @since 6.1.0 + * + * @see WP_Object_Cache::flush_group() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @param string $group Name of group to remove from cache. + * @return bool True if group was flushed, false otherwise. + */ + function wp_cache_flush_group($group) + { + } + /** + * Determines whether the object cache implementation supports a particular feature. + * + * @since 6.1.0 + * + * @param string $feature Name of the feature to check for. Possible values include: + * 'add_multiple', 'set_multiple', 'get_multiple', 'delete_multiple', + * 'flush_runtime', 'flush_group'. + * @return bool True if the feature is supported, false otherwise. + */ + function wp_cache_supports($feature) + { + } + /** + * Closes the cache. + * + * This function has ceased to do anything since WordPress 2.5. The + * functionality was removed along with the rest of the persistent cache. + * + * This does not mean that plugins can't implement this function when they need + * to make sure that the cache is cleaned up after WordPress no longer needs it. + * + * @since 2.0.0 + * + * @return true Always returns true. + */ + function wp_cache_close() + { + } + /** + * Adds a group or set of groups to the list of global groups. + * + * @since 2.6.0 + * + * @see WP_Object_Cache::add_global_groups() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @param string|string[] $groups A group or an array of groups to add. + */ + function wp_cache_add_global_groups($groups) + { + } + /** + * Adds a group or set of groups to the list of non-persistent groups. + * + * @since 2.6.0 + * + * @param string|string[] $groups A group or an array of groups to add. + */ + function wp_cache_add_non_persistent_groups($groups) + { + } + /** + * Switches the internal blog ID. + * + * This changes the blog id used to create keys in blog specific groups. + * + * @since 3.5.0 + * + * @see WP_Object_Cache::switch_to_blog() + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + * + * @param int $blog_id Site ID. + */ + function wp_cache_switch_to_blog($blog_id) + { + } + /** + * Resets internal cache keys and structures. + * + * If the cache back end uses global blog or site IDs as part of its cache keys, + * this function instructs the back end to reset those keys and perform any cleanup + * since blog or site IDs have changed since cache init. + * + * This function is deprecated. Use wp_cache_switch_to_blog() instead of this + * function when preparing the cache for a blog switch. For clearing the cache + * during unit tests, consider using wp_cache_init(). wp_cache_init() is not + * recommended outside of unit tests as the performance penalty for using it is high. + * + * @since 3.0.0 + * @deprecated 3.5.0 Use wp_cache_switch_to_blog() + * @see WP_Object_Cache::reset() + * + * @global WP_Object_Cache $wp_object_cache Object cache global instance. + */ + function wp_cache_reset() + { + } + /** + * Canonical API to handle WordPress Redirecting + * + * Based on "Permalink Redirect" from Scott Yang and "Enforce www. Preference" + * by Mark Jaquith + * + * @package WordPress + * @since 2.3.0 + */ + /** + * Redirects incoming links to the proper URL based on the site url. + * + * Search engines consider www.somedomain.com and somedomain.com to be two + * different URLs when they both go to the same location. This SEO enhancement + * prevents penalty for duplicate content by redirecting all incoming links to + * one or the other. + * + * Prevents redirection for feeds, trackbacks, searches, and + * admin URLs. Does not redirect on non-pretty-permalink-supporting IIS 7+, + * page/post previews, WP admin, Trackbacks, robots.txt, favicon.ico, searches, + * or on POST requests. + * + * Will also attempt to find the correct link when a user enters a URL that does + * not exist based on exact WordPress query. Will instead try to parse the URL + * or query in an attempt to figure the correct page to go to. + * + * @since 2.3.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * @global bool $is_IIS + * @global WP_Query $wp_query WordPress Query object. + * @global wpdb $wpdb WordPress database abstraction object. + * @global WP $wp Current WordPress environment instance. + * + * @param string $requested_url Optional. The URL that was requested, used to + * figure if redirect is needed. + * @param bool $do_redirect Optional. Redirect to the new URL. + * @return string|void The string of the URL, if redirect needed. + */ + function redirect_canonical($requested_url = \null, $do_redirect = \true) + { + } + /** + * Removes arguments from a query string if they are not present in a URL + * DO NOT use this in plugin code. + * + * @since 3.4.0 + * @access private + * + * @param string $query_string + * @param array $args_to_check + * @param string $url + * @return string The altered query string + */ + function _remove_qs_args_if_not_in_url($query_string, array $args_to_check, $url) + { + } + /** + * Strips the #fragment from a URL, if one is present. + * + * @since 4.4.0 + * + * @param string $url The URL to strip. + * @return string The altered URL. + */ + function strip_fragment_from_url($url) + { + } + /** + * Attempts to guess the correct URL for a 404 request based on query vars. + * + * @since 2.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return string|false The correct URL if one is found. False on failure. + */ + function redirect_guess_404_permalink() + { + } + /** + * Redirects a variety of shorthand URLs to the admin. + * + * If a user visits example.com/admin, they'll be redirected to /wp-admin. + * Visiting /login redirects to /wp-login.php, and so on. + * + * @since 3.4.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + */ + function wp_redirect_admin_locations() + { + } + /** + * Core User Role & Capabilities API + * + * @package WordPress + * @subpackage Users + */ + /** + * Maps a capability to the primitive capabilities required of the given user to + * satisfy the capability being checked. + * + * This function also accepts an ID of an object to map against if the capability is a meta capability. Meta + * capabilities such as `edit_post` and `edit_user` are capabilities used by this function to map to primitive + * capabilities that a user or role requires, such as `edit_posts` and `edit_others_posts`. + * + * Example usage: + * + * map_meta_cap( 'edit_posts', $user->ID ); + * map_meta_cap( 'edit_post', $user->ID, $post->ID ); + * map_meta_cap( 'edit_post_meta', $user->ID, $post->ID, $meta_key ); + * + * This function does not check whether the user has the required capabilities, + * it just returns what the required capabilities are. + * + * @since 2.0.0 + * @since 4.9.6 Added the `export_others_personal_data`, `erase_others_personal_data`, + * and `manage_privacy_options` capabilities. + * @since 5.1.0 Added the `update_php` capability. + * @since 5.2.0 Added the `resume_plugin` and `resume_theme` capabilities. + * @since 5.3.0 Formalized the existing and already documented `...$args` parameter + * by adding it to the function signature. + * @since 5.7.0 Added the `create_app_password`, `list_app_passwords`, `read_app_password`, + * `edit_app_password`, `delete_app_passwords`, `delete_app_password`, + * and `update_https` capabilities. + * + * @global array $post_type_meta_caps Used to get post type meta capabilities. + * + * @param string $cap Capability being checked. + * @param int $user_id User ID. + * @param mixed ...$args Optional further parameters, typically starting with an object ID. + * @return string[] Primitive capabilities required of the user. + */ + function map_meta_cap($cap, $user_id, ...$args) + { + } + /** + * Returns whether the current user has the specified capability. + * + * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta + * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to + * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`. + * + * Example usage: + * + * current_user_can( 'edit_posts' ); + * current_user_can( 'edit_post', $post->ID ); + * current_user_can( 'edit_post_meta', $post->ID, $meta_key ); + * + * While checking against particular roles in place of a capability is supported + * in part, this practice is discouraged as it may produce unreliable results. + * + * Note: Will always return true if the current user is a super admin, unless specifically denied. + * + * @since 2.0.0 + * @since 5.3.0 Formalized the existing and already documented `...$args` parameter + * by adding it to the function signature. + * @since 5.8.0 Converted to wrapper for the user_can() function. + * + * @see WP_User::has_cap() + * @see map_meta_cap() + * + * @param string $capability Capability name. + * @param mixed ...$args Optional further parameters, typically starting with an object ID. + * @return bool Whether the current user has the given capability. If `$capability` is a meta cap and `$object_id` is + * passed, whether the current user has the given meta capability for the given object. + */ + function current_user_can($capability, ...$args) + { + } + /** + * Returns whether the current user has the specified capability for a given site. + * + * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta + * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to + * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`. + * + * Example usage: + * + * current_user_can_for_blog( $blog_id, 'edit_posts' ); + * current_user_can_for_blog( $blog_id, 'edit_post', $post->ID ); + * current_user_can_for_blog( $blog_id, 'edit_post_meta', $post->ID, $meta_key ); + * + * @since 3.0.0 + * @since 5.3.0 Formalized the existing and already documented `...$args` parameter + * by adding it to the function signature. + * @since 5.8.0 Wraps current_user_can() after switching to blog. + * + * @param int $blog_id Site ID. + * @param string $capability Capability name. + * @param mixed ...$args Optional further parameters, typically starting with an object ID. + * @return bool Whether the user has the given capability. + */ + function current_user_can_for_blog($blog_id, $capability, ...$args) + { + } + /** + * Returns whether the author of the supplied post has the specified capability. + * + * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta + * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to + * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`. + * + * Example usage: + * + * author_can( $post, 'edit_posts' ); + * author_can( $post, 'edit_post', $post->ID ); + * author_can( $post, 'edit_post_meta', $post->ID, $meta_key ); + * + * @since 2.9.0 + * @since 5.3.0 Formalized the existing and already documented `...$args` parameter + * by adding it to the function signature. + * + * @param int|WP_Post $post Post ID or post object. + * @param string $capability Capability name. + * @param mixed ...$args Optional further parameters, typically starting with an object ID. + * @return bool Whether the post author has the given capability. + */ + function author_can($post, $capability, ...$args) + { + } + /** + * Returns whether a particular user has the specified capability. + * + * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta + * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to + * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`. + * + * Example usage: + * + * user_can( $user->ID, 'edit_posts' ); + * user_can( $user->ID, 'edit_post', $post->ID ); + * user_can( $user->ID, 'edit_post_meta', $post->ID, $meta_key ); + * + * @since 3.1.0 + * @since 5.3.0 Formalized the existing and already documented `...$args` parameter + * by adding it to the function signature. + * + * @param int|WP_User $user User ID or object. + * @param string $capability Capability name. + * @param mixed ...$args Optional further parameters, typically starting with an object ID. + * @return bool Whether the user has the given capability. + */ + function user_can($user, $capability, ...$args) + { + } + /** + * Retrieves the global WP_Roles instance and instantiates it if necessary. + * + * @since 4.3.0 + * + * @global WP_Roles $wp_roles WordPress role management object. + * + * @return WP_Roles WP_Roles global instance if not already instantiated. + */ + function wp_roles() + { + } + /** + * Retrieves role object. + * + * @since 2.0.0 + * + * @param string $role Role name. + * @return WP_Role|null WP_Role object if found, null if the role does not exist. + */ + function get_role($role) + { + } + /** + * Adds a role, if it does not exist. + * + * @since 2.0.0 + * + * @param string $role Role name. + * @param string $display_name Display name for role. + * @param bool[] $capabilities List of capabilities keyed by the capability name, + * e.g. array( 'edit_posts' => true, 'delete_posts' => false ). + * @return WP_Role|void WP_Role object, if the role is added. + */ + function add_role($role, $display_name, $capabilities = array()) + { + } + /** + * Removes a role, if it exists. + * + * @since 2.0.0 + * + * @param string $role Role name. + */ + function remove_role($role) + { + } + /** + * Retrieves a list of super admins. + * + * @since 3.0.0 + * + * @global array $super_admins + * + * @return string[] List of super admin logins. + */ + function get_super_admins() + { + } + /** + * Determines whether user is a site admin. + * + * @since 3.0.0 + * + * @param int|false $user_id Optional. The ID of a user. Defaults to false, to check the current user. + * @return bool Whether the user is a site admin. + */ + function is_super_admin($user_id = \false) + { + } + /** + * Grants Super Admin privileges. + * + * @since 3.0.0 + * + * @global array $super_admins + * + * @param int $user_id ID of the user to be granted Super Admin privileges. + * @return bool True on success, false on failure. This can fail when the user is + * already a super admin or when the `$super_admins` global is defined. + */ + function grant_super_admin($user_id) + { + } + /** + * Revokes Super Admin privileges. + * + * @since 3.0.0 + * + * @global array $super_admins + * + * @param int $user_id ID of the user Super Admin privileges to be revoked from. + * @return bool True on success, false on failure. This can fail when the user's email + * is the network admin email or when the `$super_admins` global is defined. + */ + function revoke_super_admin($user_id) + { + } + /** + * Filters the user capabilities to grant the 'install_languages' capability as necessary. + * + * A user must have at least one out of the 'update_core', 'install_plugins', and + * 'install_themes' capabilities to qualify for 'install_languages'. + * + * @since 4.9.0 + * + * @param bool[] $allcaps An array of all the user's capabilities. + * @return bool[] Filtered array of the user's capabilities. + */ + function wp_maybe_grant_install_languages_cap($allcaps) + { + } + /** + * Filters the user capabilities to grant the 'resume_plugins' and 'resume_themes' capabilities as necessary. + * + * @since 5.2.0 + * + * @param bool[] $allcaps An array of all the user's capabilities. + * @return bool[] Filtered array of the user's capabilities. + */ + function wp_maybe_grant_resume_extensions_caps($allcaps) + { + } + /** + * Filters the user capabilities to grant the 'view_site_health_checks' capabilities as necessary. + * + * @since 5.2.2 + * + * @param bool[] $allcaps An array of all the user's capabilities. + * @param string[] $caps Required primitive capabilities for the requested capability. + * @param array $args { + * Arguments that accompany the requested capability check. + * + * @type string $0 Requested capability. + * @type int $1 Concerned user ID. + * @type mixed ...$2 Optional second and further parameters, typically object ID. + * } + * @param WP_User $user The user object. + * @return bool[] Filtered array of the user's capabilities. + */ + function wp_maybe_grant_site_health_caps($allcaps, $caps, $args, $user) + { + } + /** + * Taxonomy API: Core category-specific template tags + * + * @package WordPress + * @subpackage Template + * @since 1.2.0 + */ + /** + * Retrieves category link URL. + * + * @since 1.0.0 + * + * @see get_term_link() + * + * @param int|object $category Category ID or object. + * @return string Link on success, empty string if category does not exist. + */ + function get_category_link($category) + { + } + /** + * Retrieves category parents with separator. + * + * @since 1.2.0 + * @since 4.8.0 The `$visited` parameter was deprecated and renamed to `$deprecated`. + * + * @param int $category_id Category ID. + * @param bool $link Optional. Whether to format with link. Default false. + * @param string $separator Optional. How to separate categories. Default '/'. + * @param bool $nicename Optional. Whether to use nice name for display. Default false. + * @param array $deprecated Not used. + * @return string|WP_Error A list of category parents on success, WP_Error on failure. + */ + function get_category_parents($category_id, $link = \false, $separator = '/', $nicename = \false, $deprecated = array()) + { + } + /** + * Retrieves post categories. + * + * This tag may be used outside The Loop by passing a post ID as the parameter. + * + * Note: This function only returns results from the default "category" taxonomy. + * For custom taxonomies use get_the_terms(). + * + * @since 0.71 + * + * @param int $post_id Optional. The post ID. Defaults to current post ID. + * @return WP_Term[] Array of WP_Term objects, one for each category assigned to the post. + */ + function get_the_category($post_id = \false) + { + } + /** + * Retrieves category name based on category ID. + * + * @since 0.71 + * + * @param int $cat_id Category ID. + * @return string|WP_Error Category name on success, WP_Error on failure. + */ + function get_the_category_by_ID($cat_id) + { + } + /** + * Retrieves category list for a post in either HTML list or custom format. + * + * Generally used for quick, delimited (e.g. comma-separated) lists of categories, + * as part of a post entry meta. + * + * For a more powerful, list-based function, see wp_list_categories(). + * + * @since 1.5.1 + * + * @see wp_list_categories() + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $separator Optional. Separator between the categories. By default, the links are placed + * in an unordered list. An empty string will result in the default behavior. + * @param string $parents Optional. How to display the parents. Accepts 'multiple', 'single', or empty. + * Default empty string. + * @param int $post_id Optional. ID of the post to retrieve categories for. Defaults to the current post. + * @return string Category list for a post. + */ + function get_the_category_list($separator = '', $parents = '', $post_id = \false) + { + } + /** + * Checks if the current post is within any of the given categories. + * + * The given categories are checked against the post's categories' term_ids, names and slugs. + * Categories given as integers will only be checked against the post's categories' term_ids. + * + * Prior to v2.5 of WordPress, category names were not supported. + * Prior to v2.7, category slugs were not supported. + * Prior to v2.7, only one category could be compared: in_category( $single_category ). + * Prior to v2.7, this function could only be used in the WordPress Loop. + * As of 2.7, the function can be used anywhere if it is provided a post ID or post object. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.2.0 + * @since 2.7.0 The `$post` parameter was added. + * + * @param int|string|int[]|string[] $category Category ID, name, slug, or array of such + * to check against. + * @param int|WP_Post $post Optional. Post to check. Defaults to the current post. + * @return bool True if the current post is in any of the given categories. + */ + function in_category($category, $post = \null) + { + } + /** + * Displays category list for a post in either HTML list or custom format. + * + * @since 0.71 + * + * @param string $separator Optional. Separator between the categories. By default, the links are placed + * in an unordered list. An empty string will result in the default behavior. + * @param string $parents Optional. How to display the parents. Accepts 'multiple', 'single', or empty. + * Default empty string. + * @param int $post_id Optional. ID of the post to retrieve categories for. Defaults to the current post. + */ + function the_category($separator = '', $parents = '', $post_id = \false) + { + } + /** + * Retrieves category description. + * + * @since 1.0.0 + * + * @param int $category Optional. Category ID. Defaults to the current category ID. + * @return string Category description, if available. + */ + function category_description($category = 0) + { + } + /** + * Displays or retrieves the HTML dropdown list of categories. + * + * The 'hierarchical' argument, which is disabled by default, will override the + * depth argument, unless it is true. When the argument is false, it will + * display all of the categories. When it is enabled it will use the value in + * the 'depth' argument. + * + * @since 2.1.0 + * @since 4.2.0 Introduced the `value_field` argument. + * @since 4.6.0 Introduced the `required` argument. + * @since 6.1.0 Introduced the `aria_describedby` argument. + * + * @param array|string $args { + * Optional. Array or string of arguments to generate a categories drop-down element. See WP_Term_Query::__construct() + * for information on additional accepted arguments. + * + * @type string $show_option_all Text to display for showing all categories. Default empty. + * @type string $show_option_none Text to display for showing no categories. Default empty. + * @type string $option_none_value Value to use when no category is selected. Default empty. + * @type string $orderby Which column to use for ordering categories. See get_terms() for a list + * of accepted values. Default 'id' (term_id). + * @type bool $pad_counts See get_terms() for an argument description. Default false. + * @type bool|int $show_count Whether to include post counts. Accepts 0, 1, or their bool equivalents. + * Default 0. + * @type bool|int $echo Whether to echo or return the generated markup. Accepts 0, 1, or their + * bool equivalents. Default 1. + * @type bool|int $hierarchical Whether to traverse the taxonomy hierarchy. Accepts 0, 1, or their bool + * equivalents. Default 0. + * @type int $depth Maximum depth. Default 0. + * @type int $tab_index Tab index for the select element. Default 0 (no tabindex). + * @type string $name Value for the 'name' attribute of the select element. Default 'cat'. + * @type string $id Value for the 'id' attribute of the select element. Defaults to the value + * of `$name`. + * @type string $class Value for the 'class' attribute of the select element. Default 'postform'. + * @type int|string $selected Value of the option that should be selected. Default 0. + * @type string $value_field Term field that should be used to populate the 'value' attribute + * of the option elements. Accepts any valid term field: 'term_id', 'name', + * 'slug', 'term_group', 'term_taxonomy_id', 'taxonomy', 'description', + * 'parent', 'count'. Default 'term_id'. + * @type string|array $taxonomy Name of the taxonomy or taxonomies to retrieve. Default 'category'. + * @type bool $hide_if_empty True to skip generating markup if no categories are found. + * Default false (create select element even if no categories are found). + * @type bool $required Whether the `<select>` element should have the HTML5 'required' attribute. + * Default false. + * @type Walker $walker Walker object to use to build the output. Default empty which results in a + * Walker_CategoryDropdown instance being used. + * @type string $aria_describedby The 'id' of an element that contains descriptive text for the select. + * Default empty string. + * } + * @return string HTML dropdown list of categories. + * @phpstan-param array{ + * show_option_all?: string, + * show_option_none?: string, + * option_none_value?: string, + * orderby?: string, + * pad_counts?: bool, + * show_count?: bool|int, + * echo?: bool|int, + * hierarchical?: bool|int, + * depth?: int, + * tab_index?: int, + * name?: string, + * id?: string, + * class?: string, + * selected?: int|string, + * value_field?: string, + * taxonomy?: string|array, + * hide_if_empty?: bool, + * required?: bool, + * walker?: Walker, + * aria_describedby?: string, + * taxonomy?: string|string[], + * object_ids?: int|int[], + * orderby?: string, + * order?: string, + * hide_empty?: bool|int, + * include?: int[]|string, + * exclude?: int[]|string, + * exclude_tree?: int[]|string, + * number?: int|string, + * offset?: int, + * fields?: string, + * count?: bool, + * name?: string|string[], + * slug?: string|string[], + * term_taxonomy_id?: int|int[], + * hierarchical?: bool, + * search?: string, + * name__like?: string, + * description__like?: string, + * pad_counts?: bool, + * get?: string, + * child_of?: int, + * parent?: int, + * childless?: bool, + * cache_domain?: string, + * update_term_meta_cache?: bool, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * } $args + */ + function wp_dropdown_categories($args = '') + { + } + /** + * Displays or retrieves the HTML list of categories. + * + * @since 2.1.0 + * @since 4.4.0 Introduced the `hide_title_if_empty` and `separator` arguments. + * @since 4.4.0 The `current_category` argument was modified to optionally accept an array of values. + * @since 6.1.0 Default value of the 'use_desc_for_title' argument was changed from 1 to 0. + * + * @param array|string $args { + * Array of optional arguments. See get_categories(), get_terms(), and WP_Term_Query::__construct() + * for information on additional accepted arguments. + * + * @type int|int[] $current_category ID of category, or array of IDs of categories, that should get the + * 'current-cat' class. Default 0. + * @type int $depth Category depth. Used for tab indentation. Default 0. + * @type bool|int $echo Whether to echo or return the generated markup. Accepts 0, 1, or their + * bool equivalents. Default 1. + * @type int[]|string $exclude Array or comma/space-separated string of term IDs to exclude. + * If `$hierarchical` is true, descendants of `$exclude` terms will also + * be excluded; see `$exclude_tree`. See get_terms(). + * Default empty string. + * @type int[]|string $exclude_tree Array or comma/space-separated string of term IDs to exclude, along + * with their descendants. See get_terms(). Default empty string. + * @type string $feed Text to use for the feed link. Default 'Feed for all posts filed + * under [cat name]'. + * @type string $feed_image URL of an image to use for the feed link. Default empty string. + * @type string $feed_type Feed type. Used to build feed link. See get_term_feed_link(). + * Default empty string (default feed). + * @type bool $hide_title_if_empty Whether to hide the `$title_li` element if there are no terms in + * the list. Default false (title will always be shown). + * @type string $separator Separator between links. Default '<br />'. + * @type bool|int $show_count Whether to include post counts. Accepts 0, 1, or their bool equivalents. + * Default 0. + * @type string $show_option_all Text to display for showing all categories. Default empty string. + * @type string $show_option_none Text to display for the 'no categories' option. + * Default 'No categories'. + * @type string $style The style used to display the categories list. If 'list', categories + * will be output as an unordered list. If left empty or another value, + * categories will be output separated by `<br>` tags. Default 'list'. + * @type string $taxonomy Name of the taxonomy to retrieve. Default 'category'. + * @type string $title_li Text to use for the list title `<li>` element. Pass an empty string + * to disable. Default 'Categories'. + * @type bool|int $use_desc_for_title Whether to use the category description as the title attribute. + * Accepts 0, 1, or their bool equivalents. Default 0. + * @type Walker $walker Walker object to use to build the output. Default empty which results + * in a Walker_Category instance being used. + * } + * @return void|string|false Void if 'echo' argument is true, HTML list of categories if 'echo' is false. + * False if the taxonomy does not exist. + * @phpstan-param array{ + * current_category?: int|int[], + * depth?: int, + * echo?: bool|int, + * exclude?: int[]|string, + * exclude_tree?: int[]|string, + * feed?: string, + * feed_image?: string, + * feed_type?: string, + * hide_title_if_empty?: bool, + * separator?: string, + * show_count?: bool|int, + * show_option_all?: string, + * show_option_none?: string, + * style?: string, + * taxonomy?: string, + * title_li?: string, + * use_desc_for_title?: bool|int, + * walker?: Walker, + * taxonomy?: string, + * } $args + */ + function wp_list_categories($args = '') + { + } + /** + * Displays a tag cloud. + * + * Outputs a list of tags in what is called a 'tag cloud', where the size of each tag + * is determined by how many times that particular tag has been assigned to posts. + * + * @since 2.3.0 + * @since 2.8.0 Added the `taxonomy` argument. + * @since 4.8.0 Added the `show_count` argument. + * + * @param array|string $args { + * Optional. Array or string of arguments for displaying a tag cloud. See wp_generate_tag_cloud() + * and get_terms() for the full lists of arguments that can be passed in `$args`. + * + * @type int $number The number of tags to display. Accepts any positive integer + * or zero to return all. Default 45. + * @type string $link Whether to display term editing links or term permalinks. + * Accepts 'edit' and 'view'. Default 'view'. + * @type string $post_type The post type. Used to highlight the proper post type menu + * on the linked edit page. Defaults to the first post type + * associated with the taxonomy. + * @type bool $echo Whether or not to echo the return value. Default true. + * } + * @return void|string|string[] Void if 'echo' argument is true, or on failure. Otherwise, tag cloud + * as a string or an array, depending on 'format' argument. + * @phpstan-param array{ + * number?: int, + * link?: string, + * post_type?: string, + * echo?: bool, + * smallest?: int, + * largest?: int, + * unit?: string, + * number?: int, + * format?: string, + * separator?: string, + * orderby?: string, + * order?: string, + * filter?: int|bool, + * topic_count_text?: array, + * topic_count_text_callback?: callable, + * topic_count_scale_callback?: callable, + * show_count?: bool|int, + * } $args + */ + function wp_tag_cloud($args = '') + { + } + /** + * Default topic count scaling for tag links. + * + * @since 2.9.0 + * + * @param int $count Number of posts with that tag. + * @return int Scaled count. + */ + function default_topic_count_scale($count) + { + } + /** + * Generates a tag cloud (heatmap) from provided data. + * + * @todo Complete functionality. + * @since 2.3.0 + * @since 4.8.0 Added the `show_count` argument. + * + * @param WP_Term[] $tags Array of WP_Term objects to generate the tag cloud for. + * @param string|array $args { + * Optional. Array or string of arguments for generating a tag cloud. + * + * @type int $smallest Smallest font size used to display tags. Paired + * with the value of `$unit`, to determine CSS text + * size unit. Default 8 (pt). + * @type int $largest Largest font size used to display tags. Paired + * with the value of `$unit`, to determine CSS text + * size unit. Default 22 (pt). + * @type string $unit CSS text size unit to use with the `$smallest` + * and `$largest` values. Accepts any valid CSS text + * size unit. Default 'pt'. + * @type int $number The number of tags to return. Accepts any + * positive integer or zero to return all. + * Default 0. + * @type string $format Format to display the tag cloud in. Accepts 'flat' + * (tags separated with spaces), 'list' (tags displayed + * in an unordered list), or 'array' (returns an array). + * Default 'flat'. + * @type string $separator HTML or text to separate the tags. Default "\n" (newline). + * @type string $orderby Value to order tags by. Accepts 'name' or 'count'. + * Default 'name'. The {@see 'tag_cloud_sort'} filter + * can also affect how tags are sorted. + * @type string $order How to order the tags. Accepts 'ASC' (ascending), + * 'DESC' (descending), or 'RAND' (random). Default 'ASC'. + * @type int|bool $filter Whether to enable filtering of the final output + * via {@see 'wp_generate_tag_cloud'}. Default 1. + * @type array $topic_count_text Nooped plural text from _n_noop() to supply to + * tag counts. Default null. + * @type callable $topic_count_text_callback Callback used to generate nooped plural text for + * tag counts based on the count. Default null. + * @type callable $topic_count_scale_callback Callback used to determine the tag count scaling + * value. Default default_topic_count_scale(). + * @type bool|int $show_count Whether to display the tag counts. Default 0. Accepts + * 0, 1, or their bool equivalents. + * } + * @return string|string[] Tag cloud as a string or an array, depending on 'format' argument. + * @phpstan-param array{ + * smallest?: int, + * largest?: int, + * unit?: string, + * number?: int, + * format?: string, + * separator?: string, + * orderby?: string, + * order?: string, + * filter?: int|bool, + * topic_count_text?: array, + * topic_count_text_callback?: callable, + * topic_count_scale_callback?: callable, + * show_count?: bool|int, + * } $args + */ + function wp_generate_tag_cloud($tags, $args = '') + { + } + /** + * Serves as a callback for comparing objects based on name. + * + * Used with `uasort()`. + * + * @since 3.1.0 + * @access private + * + * @param object $a The first object to compare. + * @param object $b The second object to compare. + * @return int Negative number if `$a->name` is less than `$b->name`, zero if they are equal, + * or greater than zero if `$a->name` is greater than `$b->name`. + */ + function _wp_object_name_sort_cb($a, $b) + { + } + /** + * Serves as a callback for comparing objects based on count. + * + * Used with `uasort()`. + * + * @since 3.1.0 + * @access private + * + * @param object $a The first object to compare. + * @param object $b The second object to compare. + * @return bool Whether the count value for `$a` is greater than the count value for `$b`. + */ + function _wp_object_count_sort_cb($a, $b) + { + } + // + // Helper functions. + // + /** + * Retrieves HTML list content for category list. + * + * @since 2.1.0 + * @since 5.3.0 Formalized the existing `...$args` parameter by adding it + * to the function signature. + * + * @uses Walker_Category to create HTML list content. + * @see Walker::walk() for parameters and return description. + * + * @param mixed ...$args Elements array, maximum hierarchical depth and optional additional arguments. + * @return string + */ + function walk_category_tree(...$args) + { + } + /** + * Retrieves HTML dropdown (select) content for category list. + * + * @since 2.1.0 + * @since 5.3.0 Formalized the existing `...$args` parameter by adding it + * to the function signature. + * + * @uses Walker_CategoryDropdown to create HTML dropdown content. + * @see Walker::walk() for parameters and return description. + * + * @param mixed ...$args Elements array, maximum hierarchical depth and optional additional arguments. + * @return string + */ + function walk_category_dropdown_tree(...$args) + { + } + // + // Tags. + // + /** + * Retrieves the link to the tag. + * + * @since 2.3.0 + * + * @see get_term_link() + * + * @param int|object $tag Tag ID or object. + * @return string Link on success, empty string if tag does not exist. + */ + function get_tag_link($tag) + { + } + /** + * Retrieves the tags for a post. + * + * @since 2.3.0 + * + * @param int|WP_Post $post Post ID or object. + * @return WP_Term[]|false|WP_Error Array of WP_Term objects on success, false if there are no terms + * or the post does not exist, WP_Error on failure. + */ + function get_the_tags($post = 0) + { + } + /** + * Retrieves the tags for a post formatted as a string. + * + * @since 2.3.0 + * + * @param string $before Optional. String to use before the tags. Default empty. + * @param string $sep Optional. String to use between the tags. Default empty. + * @param string $after Optional. String to use after the tags. Default empty. + * @param int $post_id Optional. Post ID. Defaults to the current post ID. + * @return string|false|WP_Error A list of tags on success, false if there are no terms, + * WP_Error on failure. + */ + function get_the_tag_list($before = '', $sep = '', $after = '', $post_id = 0) + { + } + /** + * Displays the tags for a post. + * + * @since 2.3.0 + * + * @param string $before Optional. String to use before the tags. Defaults to 'Tags:'. + * @param string $sep Optional. String to use between the tags. Default ', '. + * @param string $after Optional. String to use after the tags. Default empty. + */ + function the_tags($before = \null, $sep = ', ', $after = '') + { + } + /** + * Retrieves tag description. + * + * @since 2.8.0 + * + * @param int $tag Optional. Tag ID. Defaults to the current tag ID. + * @return string Tag description, if available. + */ + function tag_description($tag = 0) + { + } + /** + * Retrieves term description. + * + * @since 2.8.0 + * @since 4.9.2 The `$taxonomy` parameter was deprecated. + * + * @param int $term Optional. Term ID. Defaults to the current term ID. + * @param null $deprecated Deprecated. Not used. + * @return string Term description, if available. + */ + function term_description($term = 0, $deprecated = \null) + { + } + /** + * Retrieves the terms of the taxonomy that are attached to the post. + * + * @since 2.5.0 + * + * @param int|WP_Post $post Post ID or object. + * @param string $taxonomy Taxonomy name. + * @return WP_Term[]|false|WP_Error Array of WP_Term objects on success, false if there are no terms + * or the post does not exist, WP_Error on failure. + */ + function get_the_terms($post, $taxonomy) + { + } + /** + * Retrieves a post's terms as a list with specified format. + * + * Terms are linked to their respective term listing pages. + * + * @since 2.5.0 + * + * @param int $post_id Post ID. + * @param string $taxonomy Taxonomy name. + * @param string $before Optional. String to use before the terms. Default empty. + * @param string $sep Optional. String to use between the terms. Default empty. + * @param string $after Optional. String to use after the terms. Default empty. + * @return string|false|WP_Error A list of terms on success, false if there are no terms, + * WP_Error on failure. + */ + function get_the_term_list($post_id, $taxonomy, $before = '', $sep = '', $after = '') + { + } + /** + * Retrieves term parents with separator. + * + * @since 4.8.0 + * + * @param int $term_id Term ID. + * @param string $taxonomy Taxonomy name. + * @param string|array $args { + * Array of optional arguments. + * + * @type string $format Use term names or slugs for display. Accepts 'name' or 'slug'. + * Default 'name'. + * @type string $separator Separator for between the terms. Default '/'. + * @type bool $link Whether to format as a link. Default true. + * @type bool $inclusive Include the term to get the parents for. Default true. + * } + * @return string|WP_Error A list of term parents on success, WP_Error or empty string on failure. + * @phpstan-param array{ + * format?: string, + * separator?: string, + * link?: bool, + * inclusive?: bool, + * } $args + */ + function get_term_parents_list($term_id, $taxonomy, $args = array()) + { + } + /** + * Displays the terms for a post in a list. + * + * @since 2.5.0 + * + * @param int $post_id Post ID. + * @param string $taxonomy Taxonomy name. + * @param string $before Optional. String to use before the terms. Default empty. + * @param string $sep Optional. String to use between the terms. Default ', '. + * @param string $after Optional. String to use after the terms. Default empty. + * @return void|false Void on success, false on failure. + */ + function the_terms($post_id, $taxonomy, $before = '', $sep = ', ', $after = '') + { + } + /** + * Checks if the current post has any of given category. + * + * The given categories are checked against the post's categories' term_ids, names and slugs. + * Categories given as integers will only be checked against the post's categories' term_ids. + * + * If no categories are given, determines if post has any categories. + * + * @since 3.1.0 + * + * @param string|int|array $category Optional. The category name/term_id/slug, + * or an array of them to check for. Default empty. + * @param int|WP_Post $post Optional. Post to check. Defaults to the current post. + * @return bool True if the current post has any of the given categories + * (or any category, if no category specified). False otherwise. + */ + function has_category($category = '', $post = \null) + { + } + /** + * Checks if the current post has any of given tags. + * + * The given tags are checked against the post's tags' term_ids, names and slugs. + * Tags given as integers will only be checked against the post's tags' term_ids. + * + * If no tags are given, determines if post has any tags. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.6.0 + * @since 2.7.0 Tags given as integers are only checked against + * the post's tags' term_ids, not names or slugs. + * @since 2.7.0 Can be used outside of the WordPress Loop if `$post` is provided. + * + * @param string|int|array $tag Optional. The tag name/term_id/slug, + * or an array of them to check for. Default empty. + * @param int|WP_Post $post Optional. Post to check. Defaults to the current post. + * @return bool True if the current post has any of the given tags + * (or any tag, if no tag specified). False otherwise. + */ + function has_tag($tag = '', $post = \null) + { + } + /** + * Checks if the current post has any of given terms. + * + * The given terms are checked against the post's terms' term_ids, names and slugs. + * Terms given as integers will only be checked against the post's terms' term_ids. + * + * If no terms are given, determines if post has any terms. + * + * @since 3.1.0 + * + * @param string|int|array $term Optional. The term name/term_id/slug, + * or an array of them to check for. Default empty. + * @param string $taxonomy Optional. Taxonomy name. Default empty. + * @param int|WP_Post $post Optional. Post to check. Defaults to the current post. + * @return bool True if the current post has any of the given terms + * (or any term, if no term specified). False otherwise. + */ + function has_term($term = '', $taxonomy = '', $post = \null) + { + } + /** + * Taxonomy API: Core category-specific functionality + * + * @package WordPress + * @subpackage Taxonomy + */ + /** + * Retrieves a list of category objects. + * + * If you set the 'taxonomy' argument to 'link_category', the link categories + * will be returned instead. + * + * @since 2.1.0 + * + * @see get_terms() Type of arguments that can be changed. + * + * @param string|array $args { + * Optional. Arguments to retrieve categories. See get_terms() for additional options. + * + * @type string $taxonomy Taxonomy to retrieve terms for. Default 'category'. + * } + * @return array List of category objects. + * @phpstan-param array{ + * taxonomy?: string, + * } $args + */ + function get_categories($args = '') + { + } + /** + * Retrieves category data given a category ID or category object. + * + * If you pass the $category parameter an object, which is assumed to be the + * category row object retrieved the database. It will cache the category data. + * + * If you pass $category an integer of the category ID, then that category will + * be retrieved from the database, if it isn't already cached, and pass it back. + * + * If you look at get_term(), then both types will be passed through several + * filters and finally sanitized based on the $filter parameter value. + * + * @since 1.5.1 + * + * @param int|object $category Category ID or category row object. + * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which + * correspond to a WP_Term object, an associative array, or a numeric array, + * respectively. Default OBJECT. + * @param string $filter Optional. How to sanitize category fields. Default 'raw'. + * @return object|array|WP_Error|null Category data in type defined by $output parameter. + * WP_Error if $category is empty, null if it does not exist. + */ + function get_category($category, $output = \OBJECT, $filter = 'raw') + { + } + /** + * Retrieves a category based on URL containing the category slug. + * + * Breaks the $category_path parameter up to get the category slug. + * + * Tries to find the child path and will return it. If it doesn't find a + * match, then it will return the first category matching slug, if $full_match, + * is set to false. If it does not, then it will return null. + * + * It is also possible that it will return a WP_Error object on failure. Check + * for it when using this function. + * + * @since 2.1.0 + * + * @param string $category_path URL containing category slugs. + * @param bool $full_match Optional. Whether full path should be matched. + * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which + * correspond to a WP_Term object, an associative array, or a numeric array, + * respectively. Default OBJECT. + * @return WP_Term|array|WP_Error|null Type is based on $output value. + */ + function get_category_by_path($category_path, $full_match = \true, $output = \OBJECT) + { + } + /** + * Retrieves a category object by category slug. + * + * @since 2.3.0 + * + * @param string $slug The category slug. + * @return object|false Category data object on success, false if not found. + */ + function get_category_by_slug($slug) + { + } + /** + * Retrieves the ID of a category from its name. + * + * @since 1.0.0 + * + * @param string $cat_name Category name. + * @return int Category ID on success, 0 if the category doesn't exist. + */ + function get_cat_ID($cat_name) + { + } + /** + * Retrieves the name of a category from its ID. + * + * @since 1.0.0 + * + * @param int $cat_id Category ID. + * @return string Category name, or an empty string if the category doesn't exist. + */ + function get_cat_name($cat_id) + { + } + /** + * Checks if a category is an ancestor of another category. + * + * You can use either an ID or the category object for both parameters. + * If you use an integer, the category will be retrieved. + * + * @since 2.1.0 + * + * @param int|object $cat1 ID or object to check if this is the parent category. + * @param int|object $cat2 The child category. + * @return bool Whether $cat2 is child of $cat1. + */ + function cat_is_ancestor_of($cat1, $cat2) + { + } + /** + * Sanitizes category data based on context. + * + * @since 2.3.0 + * + * @param object|array $category Category data. + * @param string $context Optional. Default 'display'. + * @return object|array Same type as $category with sanitized data for safe use. + * @phpstan-template T of array|object + * @phpstan-param T $category + * @phpstan-return T + */ + function sanitize_category($category, $context = 'display') + { + } + /** + * Sanitizes data in single category key field. + * + * @since 2.3.0 + * + * @param string $field Category key to sanitize. + * @param mixed $value Category value to sanitize. + * @param int $cat_id Category ID. + * @param string $context What filter to use, 'raw', 'display', etc. + * @return mixed Value after $value has been sanitized. + */ + function sanitize_category_field($field, $value, $cat_id, $context) + { + } + /* Tags */ + /** + * Retrieves all post tags. + * + * @since 2.3.0 + * + * @param string|array $args { + * Optional. Arguments to retrieve tags. See get_terms() for additional options. + * + * @type string $taxonomy Taxonomy to retrieve terms for. Default 'post_tag'. + * } + * @return WP_Term[]|int|WP_Error Array of 'post_tag' term objects, a count thereof, + * or WP_Error if any of the taxonomies do not exist. + * @phpstan-param array{ + * taxonomy?: string, + * } $args + */ + function get_tags($args = '') + { + } + /** + * Retrieves a post tag by tag ID or tag object. + * + * If you pass the $tag parameter an object, which is assumed to be the tag row + * object retrieved from the database, it will cache the tag data. + * + * If you pass $tag an integer of the tag ID, then that tag will be retrieved + * from the database, if it isn't already cached, and passed back. + * + * If you look at get_term(), both types will be passed through several filters + * and finally sanitized based on the $filter parameter value. + * + * @since 2.3.0 + * + * @param int|WP_Term|object $tag A tag ID or object. + * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which + * correspond to a WP_Term object, an associative array, or a numeric array, + * respectively. Default OBJECT. + * @param string $filter Optional. How to sanitize tag fields. Default 'raw'. + * @return WP_Term|array|WP_Error|null Tag data in type defined by $output parameter. + * WP_Error if $tag is empty, null if it does not exist. + */ + function get_tag($tag, $output = \OBJECT, $filter = 'raw') + { + } + /* Cache */ + /** + * Removes the category cache data based on ID. + * + * @since 2.1.0 + * + * @param int $id Category ID + */ + function clean_category_cache($id) + { + } + /** + * Updates category structure to old pre-2.3 from new taxonomy structure. + * + * This function was added for the taxonomy support to update the new category + * structure with the old category one. This will maintain compatibility with + * plugins and themes which depend on the old key or property names. + * + * The parameter should only be passed a variable and not create the array or + * object inline to the parameter. The reason for this is that parameter is + * passed by reference and PHP will fail unless it has the variable. + * + * There is no return value, because everything is updated on the variable you + * pass to it. This is one of the features with using pass by reference in PHP. + * + * @since 2.3.0 + * @since 4.4.0 The `$category` parameter now also accepts a WP_Term object. + * @access private + * + * @param array|object|WP_Term $category Category row object or array. + */ + function _make_cat_compat(&$category) + { + } + /** + * WordPress autoloader for SimplePie. + * + * @since 3.5.0 + */ + function wp_simplepie_autoload($class) + { + } + /** + * Registers a new pattern category. + * + * @since 5.5.0 + * + * @param string $category_name Pattern category name including namespace. + * @param array $category_properties List of properties for the block pattern. + * See WP_Block_Pattern_Categories_Registry::register() for + * accepted arguments. + * @return bool True if the pattern category was registered with success and false otherwise. + * @phpstan-param array{ + * label?: string, + * } $category_properties See WP_Block_Pattern_Categories_Registry::register() + */ + function register_block_pattern_category($category_name, $category_properties) + { + } + /** + * Unregisters a pattern category. + * + * @since 5.5.0 + * + * @param string $category_name Pattern category name including namespace. + * @return bool True if the pattern category was unregistered with success and false otherwise. + */ + function unregister_block_pattern_category($category_name) + { + } + /** + * Registers a new block pattern. + * + * @since 5.5.0 + * + * @param string $pattern_name Block pattern name including namespace. + * @param array $pattern_properties List of properties for the block pattern. + * See WP_Block_Patterns_Registry::register() for accepted arguments. + * @return bool True if the pattern was registered with success and false otherwise. + * @phpstan-param array{ + * title?: string, + * content?: string, + * description?: string, + * viewportWidth?: int, + * categories?: array, + * blockTypes?: array, + * keywords?: array, + * } $pattern_properties See WP_Block_Patterns_Registry::register() + */ + function register_block_pattern($pattern_name, $pattern_properties) + { + } + /** + * Unregisters a block pattern. + * + * @since 5.5.0 + * + * @param string $pattern_name Block pattern name including namespace. + * @return bool True if the pattern was unregistered with success and false otherwise. + */ + function unregister_block_pattern($pattern_name) + { + } + /** + * Generates a string of attributes by applying to the current block being + * rendered all of the features that the block supports. + * + * @since 5.6.0 + * + * @param string[] $extra_attributes Optional. Array of extra attributes to render on the block wrapper. + * @return string String of HTML attributes. + */ + function get_block_wrapper_attributes($extra_attributes = array()) + { + } + /** + * Comment template functions + * + * These functions are meant to live inside of the WordPress loop. + * + * @package WordPress + * @subpackage Template + */ + /** + * Retrieves the author of the current comment. + * + * If the comment has an empty comment_author field, then 'Anonymous' person is + * assumed. + * + * @since 1.5.0 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to retrieve the author. + * Default current comment. + * @return string The comment author + */ + function get_comment_author($comment_ID = 0) + { + } + /** + * Displays the author of the current comment. + * + * @since 0.71 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to print the author. + * Default current comment. + */ + function comment_author($comment_ID = 0) + { + } + /** + * Retrieves the email of the author of the current comment. + * + * @since 1.5.0 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to get the author's email. + * Default current comment. + * @return string The current comment author's email + */ + function get_comment_author_email($comment_ID = 0) + { + } + /** + * Displays the email of the author of the current global $comment. + * + * Care should be taken to protect the email address and assure that email + * harvesters do not capture your commenter's email address. Most assume that + * their email address will not appear in raw form on the site. Doing so will + * enable anyone, including those that people don't want to get the email + * address and use it for their own means good and bad. + * + * @since 0.71 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to print the author's email. + * Default current comment. + */ + function comment_author_email($comment_ID = 0) + { + } + /** + * Displays the HTML email link to the author of the current comment. + * + * Care should be taken to protect the email address and assure that email + * harvesters do not capture your commenter's email address. Most assume that + * their email address will not appear in raw form on the site. Doing so will + * enable anyone, including those that people don't want to get the email + * address and use it for their own means good and bad. + * + * @since 0.71 + * @since 4.6.0 Added the `$comment` parameter. + * + * @param string $linktext Optional. Text to display instead of the comment author's email address. + * Default empty. + * @param string $before Optional. Text or HTML to display before the email link. Default empty. + * @param string $after Optional. Text or HTML to display after the email link. Default empty. + * @param int|WP_Comment $comment Optional. Comment ID or WP_Comment object. Default is the current comment. + */ + function comment_author_email_link($linktext = '', $before = '', $after = '', $comment = \null) + { + } + /** + * Returns the HTML email link to the author of the current comment. + * + * Care should be taken to protect the email address and assure that email + * harvesters do not capture your commenter's email address. Most assume that + * their email address will not appear in raw form on the site. Doing so will + * enable anyone, including those that people don't want to get the email + * address and use it for their own means good and bad. + * + * @since 2.7.0 + * @since 4.6.0 Added the `$comment` parameter. + * + * @param string $linktext Optional. Text to display instead of the comment author's email address. + * Default empty. + * @param string $before Optional. Text or HTML to display before the email link. Default empty. + * @param string $after Optional. Text or HTML to display after the email link. Default empty. + * @param int|WP_Comment $comment Optional. Comment ID or WP_Comment object. Default is the current comment. + * @return string HTML markup for the comment author email link. By default, the email address is obfuscated + * via the {@see 'comment_email'} filter with antispambot(). + */ + function get_comment_author_email_link($linktext = '', $before = '', $after = '', $comment = \null) + { + } + /** + * Retrieves the HTML link to the URL of the author of the current comment. + * + * Both get_comment_author_url() and get_comment_author() rely on get_comment(), + * which falls back to the global comment variable if the $comment_ID argument is empty. + * + * @since 1.5.0 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to get the author's link. + * Default current comment. + * @return string The comment author name or HTML link for author's URL. + */ + function get_comment_author_link($comment_ID = 0) + { + } + /** + * Displays the HTML link to the URL of the author of the current comment. + * + * @since 0.71 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to print the author's link. + * Default current comment. + */ + function comment_author_link($comment_ID = 0) + { + } + /** + * Retrieves the IP address of the author of the current comment. + * + * @since 1.5.0 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to get the author's IP address. + * Default current comment. + * @return string Comment author's IP address, or an empty string if it's not available. + */ + function get_comment_author_IP($comment_ID = 0) + { + } + /** + * Displays the IP address of the author of the current comment. + * + * @since 0.71 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to print the author's IP address. + * Default current comment. + */ + function comment_author_IP($comment_ID = 0) + { + } + /** + * Retrieves the URL of the author of the current comment, not linked. + * + * @since 1.5.0 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to get the author's URL. + * Default current comment. + * @return string Comment author URL, if provided, an empty string otherwise. + */ + function get_comment_author_url($comment_ID = 0) + { + } + /** + * Displays the URL of the author of the current comment, not linked. + * + * @since 0.71 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to print the author's URL. + * Default current comment. + */ + function comment_author_url($comment_ID = 0) + { + } + /** + * Retrieves the HTML link of the URL of the author of the current comment. + * + * $linktext parameter is only used if the URL does not exist for the comment + * author. If the URL does exist then the URL will be used and the $linktext + * will be ignored. + * + * Encapsulate the HTML link between the $before and $after. So it will appear + * in the order of $before, link, and finally $after. + * + * @since 1.5.0 + * @since 4.6.0 Added the `$comment` parameter. + * + * @param string $linktext Optional. The text to display instead of the comment + * author's email address. Default empty. + * @param string $before Optional. The text or HTML to display before the email link. + * Default empty. + * @param string $after Optional. The text or HTML to display after the email link. + * Default empty. + * @param int|WP_Comment $comment Optional. Comment ID or WP_Comment object. + * Default is the current comment. + * @return string The HTML link between the $before and $after parameters. + */ + function get_comment_author_url_link($linktext = '', $before = '', $after = '', $comment = 0) + { + } + /** + * Displays the HTML link of the URL of the author of the current comment. + * + * @since 0.71 + * @since 4.6.0 Added the `$comment` parameter. + * + * @param string $linktext Optional. Text to display instead of the comment author's + * email address. Default empty. + * @param string $before Optional. Text or HTML to display before the email link. + * Default empty. + * @param string $after Optional. Text or HTML to display after the email link. + * Default empty. + * @param int|WP_Comment $comment Optional. Comment ID or WP_Comment object. + * Default is the current comment. + */ + function comment_author_url_link($linktext = '', $before = '', $after = '', $comment = 0) + { + } + /** + * Generates semantic classes for each comment element. + * + * @since 2.7.0 + * @since 4.4.0 Added the ability for `$comment` to also accept a WP_Comment object. + * + * @param string|string[] $css_class Optional. One or more classes to add to the class list. + * Default empty. + * @param int|WP_Comment $comment Comment ID or WP_Comment object. Default current comment. + * @param int|WP_Post $post Post ID or WP_Post object. Default current post. + * @param bool $display Optional. Whether to print or return the output. + * Default true. + * @return void|string Void if `$display` argument is true, comment classes if `$display` is false. + */ + function comment_class($css_class = '', $comment = \null, $post = \null, $display = \true) + { + } + /** + * Returns the classes for the comment div as an array. + * + * @since 2.7.0 + * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object. + * + * @global int $comment_alt + * @global int $comment_depth + * @global int $comment_thread_alt + * + * @param string|string[] $css_class Optional. One or more classes to add to the class list. Default empty. + * @param int|WP_Comment $comment_id Comment ID or WP_Comment object. Default current comment. + * @param int|WP_Post $post Post ID or WP_Post object. Default current post. + * @return string[] An array of classes. + */ + function get_comment_class($css_class = '', $comment_id = \null, $post = \null) + { + } + /** + * Retrieves the comment date of the current comment. + * + * @since 1.5.0 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param string $format Optional. PHP date format. Defaults to the 'date_format' option. + * @param int|WP_Comment $comment_ID WP_Comment or ID of the comment for which to get the date. + * Default current comment. + * @return string The comment's date. + */ + function get_comment_date($format = '', $comment_ID = 0) + { + } + /** + * Displays the comment date of the current comment. + * + * @since 0.71 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param string $format Optional. PHP date format. Defaults to the 'date_format' option. + * @param int|WP_Comment $comment_ID WP_Comment or ID of the comment for which to print the date. + * Default current comment. + */ + function comment_date($format = '', $comment_ID = 0) + { + } + /** + * Retrieves the excerpt of the given comment. + * + * Returns a maximum of 20 words with an ellipsis appended if necessary. + * + * @since 1.5.0 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param int|WP_Comment $comment_ID WP_Comment or ID of the comment for which to get the excerpt. + * Default current comment. + * @return string The possibly truncated comment excerpt. + */ + function get_comment_excerpt($comment_ID = 0) + { + } + /** + * Displays the excerpt of the current comment. + * + * @since 1.2.0 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param int|WP_Comment $comment_ID WP_Comment or ID of the comment for which to print the excerpt. + * Default current comment. + */ + function comment_excerpt($comment_ID = 0) + { + } + /** + * Retrieves the comment ID of the current comment. + * + * @since 1.5.0 + * + * @return string The comment ID as a numeric string. + */ + function get_comment_ID() + { + } + /** + * Displays the comment ID of the current comment. + * + * @since 0.71 + */ + function comment_ID() + { + } + /** + * Retrieves the link to a given comment. + * + * @since 1.5.0 + * @since 4.4.0 Added the ability for `$comment` to also accept a WP_Comment object. Added `$cpage` argument. + * + * @see get_page_of_comment() + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * @global bool $in_comment_loop + * + * @param WP_Comment|int|null $comment Comment to retrieve. Default current comment. + * @param array $args { + * An array of optional arguments to override the defaults. + * + * @type string $type Passed to get_page_of_comment(). + * @type int $page Current page of comments, for calculating comment pagination. + * @type int $per_page Per-page value for comment pagination. + * @type int $max_depth Passed to get_page_of_comment(). + * @type int|string $cpage Value to use for the comment's "comment-page" or "cpage" value. + * If provided, this value overrides any value calculated from `$page` + * and `$per_page`. + * } + * @return string The permalink to the given comment. + * @phpstan-param array{ + * type?: string, + * page?: int, + * per_page?: int, + * max_depth?: int, + * cpage?: int|string, + * } $args + */ + function get_comment_link($comment = \null, $args = array()) + { + } + /** + * Retrieves the link to the current post comments. + * + * @since 1.5.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @return string The link to the comments. + */ + function get_comments_link($post = 0) + { + } + /** + * Displays the link to the current post comments. + * + * @since 0.71 + * + * @param string $deprecated Not Used. + * @param string $deprecated_2 Not Used. + */ + function comments_link($deprecated = '', $deprecated_2 = '') + { + } + /** + * Retrieves the amount of comments a post has. + * + * @since 1.5.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is the global `$post`. + * @return string|int If the post exists, a numeric string representing the number of comments + * the post has, otherwise 0. + */ + function get_comments_number($post = 0) + { + } + /** + * Displays the language string for the number of comments the current post has. + * + * @since 0.71 + * @since 5.4.0 The `$deprecated` parameter was changed to `$post`. + * + * @param string|false $zero Optional. Text for no comments. Default false. + * @param string|false $one Optional. Text for one comment. Default false. + * @param string|false $more Optional. Text for more than one comment. Default false. + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is the global `$post`. + */ + function comments_number($zero = \false, $one = \false, $more = \false, $post = 0) + { + } + /** + * Displays the language string for the number of comments the current post has. + * + * @since 4.0.0 + * @since 5.4.0 Added the `$post` parameter to allow using the function outside of the loop. + * + * @param string $zero Optional. Text for no comments. Default false. + * @param string $one Optional. Text for one comment. Default false. + * @param string $more Optional. Text for more than one comment. Default false. + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is the global `$post`. + * @return string Language string for the number of comments a post has. + */ + function get_comments_number_text($zero = \false, $one = \false, $more = \false, $post = 0) + { + } + /** + * Retrieves the text of the current comment. + * + * @since 1.5.0 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * @since 5.4.0 Added 'In reply to %s.' prefix to child comments in comments feed. + * + * @see Walker_Comment::comment() + * + * @param int|WP_Comment $comment_ID WP_Comment or ID of the comment for which to get the text. + * Default current comment. + * @param array $args Optional. An array of arguments. Default empty array. + * @return string The comment content. + */ + function get_comment_text($comment_ID = 0, $args = array()) + { + } + /** + * Displays the text of the current comment. + * + * @since 0.71 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @see Walker_Comment::comment() + * + * @param int|WP_Comment $comment_ID WP_Comment or ID of the comment for which to print the text. + * Default current comment. + * @param array $args Optional. An array of arguments. Default empty array. + */ + function comment_text($comment_ID = 0, $args = array()) + { + } + /** + * Retrieves the comment time of the current comment. + * + * @since 1.5.0 + * + * @param string $format Optional. PHP time format. Defaults to the 'time_format' option. + * @param bool $gmt Optional. Whether to use the GMT date. Default false. + * @param bool $translate Optional. Whether to translate the time (for use in feeds). + * Default true. + * @return string The formatted time. + */ + function get_comment_time($format = '', $gmt = \false, $translate = \true) + { + } + /** + * Displays the comment time of the current comment. + * + * @since 0.71 + * + * @param string $format Optional. PHP time format. Defaults to the 'time_format' option. + */ + function comment_time($format = '') + { + } + /** + * Retrieves the comment type of the current comment. + * + * @since 1.5.0 + * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. + * + * @param int|WP_Comment $comment_ID Optional. WP_Comment or ID of the comment for which to get the type. + * Default current comment. + * @return string The comment type. + */ + function get_comment_type($comment_ID = 0) + { + } + /** + * Displays the comment type of the current comment. + * + * @since 0.71 + * + * @param string|false $commenttxt Optional. String to display for comment type. Default false. + * @param string|false $trackbacktxt Optional. String to display for trackback type. Default false. + * @param string|false $pingbacktxt Optional. String to display for pingback type. Default false. + */ + function comment_type($commenttxt = \false, $trackbacktxt = \false, $pingbacktxt = \false) + { + } + /** + * Retrieves the current post's trackback URL. + * + * There is a check to see if permalink's have been enabled and if so, will + * retrieve the pretty path. If permalinks weren't enabled, the ID of the + * current post is used and appended to the correct page to go to. + * + * @since 1.5.0 + * + * @return string The trackback URL after being filtered. + */ + function get_trackback_url() + { + } + /** + * Displays the current post's trackback URL. + * + * @since 0.71 + * + * @param bool $deprecated_echo Not used. + * @return void|string Should only be used to echo the trackback URL, use get_trackback_url() + * for the result instead. + */ + function trackback_url($deprecated_echo = \true) + { + } + /** + * Generates and displays the RDF for the trackback information of current post. + * + * Deprecated in 3.0.0, and restored in 3.0.1. + * + * @since 0.71 + * + * @param int|string $deprecated Not used (Was $timezone = 0). + */ + function trackback_rdf($deprecated = '') + { + } + /** + * Determines whether the current post is open for comments. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @param int|WP_Post $post Post ID or WP_Post object. Default current post. + * @return bool True if the comments are open. + */ + function comments_open($post = \null) + { + } + /** + * Determines whether the current post is open for pings. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @param int|WP_Post $post Post ID or WP_Post object. Default current post. + * @return bool True if pings are accepted + */ + function pings_open($post = \null) + { + } + /** + * Displays form token for unfiltered comments. + * + * Will only display nonce token if the current user has permissions for + * unfiltered html. Won't display the token for other users. + * + * The function was backported to 2.0.10 and was added to versions 2.1.3 and + * above. Does not exist in versions prior to 2.0.10 in the 2.0 branch and in + * the 2.1 branch, prior to 2.1.3. Technically added in 2.2.0. + * + * Backported to 2.0.10. + * + * @since 2.1.3 + */ + function wp_comment_form_unfiltered_html_nonce() + { + } + /** + * Loads the comment template specified in $file. + * + * Will not display the comments template if not on single post or page, or if + * the post does not have comments. + * + * Uses the WordPress database object to query for the comments. The comments + * are passed through the {@see 'comments_array'} filter hook with the list of comments + * and the post ID respectively. + * + * The `$file` path is passed through a filter hook called {@see 'comments_template'}, + * which includes the TEMPLATEPATH and $file combined. Tries the $filtered path + * first and if it fails it will require the default comment template from the + * default theme. If either does not exist, then the WordPress process will be + * halted. It is advised for that reason, that the default theme is not deleted. + * + * Will not try to get the comments if the post has none. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * @global WP_Post $post Global post object. + * @global wpdb $wpdb WordPress database abstraction object. + * @global int $id + * @global WP_Comment $comment Global comment object. + * @global string $user_login + * @global string $user_identity + * @global bool $overridden_cpage + * @global bool $withcomments + * + * @param string $file Optional. The file to load. Default '/comments.php'. + * @param bool $separate_comments Optional. Whether to separate the comments by comment type. + * Default false. + */ + function comments_template($file = '/comments.php', $separate_comments = \false) + { + } + /** + * Displays the link to the comments for the current post ID. + * + * @since 0.71 + * + * @param false|string $zero Optional. String to display when no comments. Default false. + * @param false|string $one Optional. String to display when only one comment is available. Default false. + * @param false|string $more Optional. String to display when there are more than one comment. Default false. + * @param string $css_class Optional. CSS class to use for comments. Default empty. + * @param false|string $none Optional. String to display when comments have been turned off. Default false. + */ + function comments_popup_link($zero = \false, $one = \false, $more = \false, $css_class = '', $none = \false) + { + } + /** + * Retrieves HTML content for reply to comment link. + * + * @since 2.7.0 + * @since 4.4.0 Added the ability for `$comment` to also accept a WP_Comment object. + * + * @param array $args { + * Optional. Override default arguments. + * + * @type string $add_below The first part of the selector used to identify the comment to respond below. + * The resulting value is passed as the first parameter to addComment.moveForm(), + * concatenated as $add_below-$comment->comment_ID. Default 'comment'. + * @type string $respond_id The selector identifying the responding comment. Passed as the third parameter + * to addComment.moveForm(), and appended to the link URL as a hash value. + * Default 'respond'. + * @type string $reply_text The text of the Reply link. Default 'Reply'. + * @type string $login_text The text of the link to reply if logged out. Default 'Log in to Reply'. + * @type int $max_depth The max depth of the comment tree. Default 0. + * @type int $depth The depth of the new comment. Must be greater than 0 and less than the value + * of the 'thread_comments_depth' option set in Settings > Discussion. Default 0. + * @type string $before The text or HTML to add before the reply link. Default empty. + * @type string $after The text or HTML to add after the reply link. Default empty. + * } + * @param int|WP_Comment $comment Comment being replied to. Default current comment. + * @param int|WP_Post $post Post ID or WP_Post object the comment is going to be displayed on. + * Default current post. + * @return string|false|null Link to show comment form, if successful. False, if comments are closed. + * @phpstan-param array{ + * add_below?: string, + * respond_id?: string, + * reply_text?: string, + * login_text?: string, + * max_depth?: int, + * depth?: int, + * before?: string, + * after?: string, + * } $args + */ + function get_comment_reply_link($args = array(), $comment = \null, $post = \null) + { + } + /** + * Displays the HTML content for reply to comment link. + * + * @since 2.7.0 + * + * @see get_comment_reply_link() + * + * @param array $args Optional. Override default options. Default empty array. + * @param int|WP_Comment $comment Comment being replied to. Default current comment. + * @param int|WP_Post $post Post ID or WP_Post object the comment is going to be displayed on. + * Default current post. + */ + function comment_reply_link($args = array(), $comment = \null, $post = \null) + { + } + /** + * Retrieves HTML content for reply to post link. + * + * @since 2.7.0 + * + * @param array $args { + * Optional. Override default arguments. + * + * @type string $add_below The first part of the selector used to identify the comment to respond below. + * The resulting value is passed as the first parameter to addComment.moveForm(), + * concatenated as $add_below-$comment->comment_ID. Default is 'post'. + * @type string $respond_id The selector identifying the responding comment. Passed as the third parameter + * to addComment.moveForm(), and appended to the link URL as a hash value. + * Default 'respond'. + * @type string $reply_text Text of the Reply link. Default is 'Leave a Comment'. + * @type string $login_text Text of the link to reply if logged out. Default is 'Log in to leave a Comment'. + * @type string $before Text or HTML to add before the reply link. Default empty. + * @type string $after Text or HTML to add after the reply link. Default empty. + * } + * @param int|WP_Post $post Optional. Post ID or WP_Post object the comment is going to be displayed on. + * Default current post. + * @return string|false|null Link to show comment form, if successful. False, if comments are closed. + * @phpstan-param array{ + * add_below?: string, + * respond_id?: string, + * reply_text?: string, + * login_text?: string, + * before?: string, + * after?: string, + * } $args + */ + function get_post_reply_link($args = array(), $post = \null) + { + } + /** + * Displays the HTML content for reply to post link. + * + * @since 2.7.0 + * + * @see get_post_reply_link() + * + * @param array $args Optional. Override default options. Default empty array. + * @param int|WP_Post $post Post ID or WP_Post object the comment is going to be displayed on. + * Default current post. + */ + function post_reply_link($args = array(), $post = \null) + { + } + /** + * Retrieves HTML content for cancel comment reply link. + * + * @since 2.7.0 + * + * @param string $text Optional. Text to display for cancel reply link. If empty, + * defaults to 'Click here to cancel reply'. Default empty. + * @return string + */ + function get_cancel_comment_reply_link($text = '') + { + } + /** + * Displays HTML content for cancel comment reply link. + * + * @since 2.7.0 + * + * @param string $text Optional. Text to display for cancel reply link. If empty, + * defaults to 'Click here to cancel reply'. Default empty. + */ + function cancel_comment_reply_link($text = '') + { + } + /** + * Retrieves hidden input HTML for replying to comments. + * + * @since 3.0.0 + * + * @param int $post_id Optional. Post ID. Defaults to the current post ID. + * @return string Hidden input HTML for replying to comments. + */ + function get_comment_id_fields($post_id = 0) + { + } + /** + * Outputs hidden input HTML for replying to comments. + * + * Adds two hidden inputs to the comment form to identify the `comment_post_ID` + * and `comment_parent` values for threaded comments. + * + * This tag must be within the `<form>` section of the `comments.php` template. + * + * @since 2.7.0 + * + * @see get_comment_id_fields() + * + * @param int $post_id Optional. Post ID. Defaults to the current post ID. + */ + function comment_id_fields($post_id = 0) + { + } + /** + * Displays text based on comment reply status. + * + * Only affects users with JavaScript disabled. + * + * @internal The $comment global must be present to allow template tags access to the current + * comment. See https://core.trac.wordpress.org/changeset/36512. + * + * @since 2.7.0 + * + * @global WP_Comment $comment Global comment object. + * + * @param string|false $no_reply_text Optional. Text to display when not replying to a comment. + * Default false. + * @param string|false $reply_text Optional. Text to display when replying to a comment. + * Default false. Accepts "%s" for the author of the comment + * being replied to. + * @param bool $link_to_parent Optional. Boolean to control making the author's name a link + * to their comment. Default true. + */ + function comment_form_title($no_reply_text = \false, $reply_text = \false, $link_to_parent = \true) + { + } + /** + * Displays a list of comments. + * + * Used in the comments.php template to list comments for a particular post. + * + * @since 2.7.0 + * + * @see WP_Query::$comments + * + * @global WP_Query $wp_query WordPress Query object. + * @global int $comment_alt + * @global int $comment_depth + * @global int $comment_thread_alt + * @global bool $overridden_cpage + * @global bool $in_comment_loop + * + * @param string|array $args { + * Optional. Formatting options. + * + * @type object $walker Instance of a Walker class to list comments. Default null. + * @type int $max_depth The maximum comments depth. Default empty. + * @type string $style The style of list ordering. Accepts 'ul', 'ol', or 'div'. + * 'div' will result in no additional list markup. Default 'ul'. + * @type callable $callback Callback function to use. Default null. + * @type callable $end-callback Callback function to use at the end. Default null. + * @type string $type Type of comments to list. Accepts 'all', 'comment', + * 'pingback', 'trackback', 'pings'. Default 'all'. + * @type int $page Page ID to list comments for. Default empty. + * @type int $per_page Number of comments to list per page. Default empty. + * @type int $avatar_size Height and width dimensions of the avatar size. Default 32. + * @type bool $reverse_top_level Ordering of the listed comments. If true, will display + * newest comments first. Default null. + * @type bool $reverse_children Whether to reverse child comments in the list. Default null. + * @type string $format How to format the comments list. Accepts 'html5', 'xhtml'. + * Default 'html5' if the theme supports it. + * @type bool $short_ping Whether to output short pings. Default false. + * @type bool $echo Whether to echo the output or return it. Default true. + * } + * @param WP_Comment[] $comments Optional. Array of WP_Comment objects. + * @return void|string Void if 'echo' argument is true, or no comments to list. + * Otherwise, HTML list of comments. + * @phpstan-param array{ + * walker?: object, + * max_depth?: int, + * style?: string, + * callback?: callable, + * end-callback?: callable, + * type?: string, + * page?: int, + * per_page?: int, + * avatar_size?: int, + * reverse_top_level?: bool, + * reverse_children?: bool, + * format?: string, + * short_ping?: bool, + * echo?: bool, + * } $args + */ + function wp_list_comments($args = array(), $comments = \null) + { + } + /** + * Outputs a complete commenting form for use within a template. + * + * Most strings and form fields may be controlled through the `$args` array passed + * into the function, while you may also choose to use the {@see 'comment_form_default_fields'} + * filter to modify the array of default fields if you'd just like to add a new + * one or remove a single field. All fields are also individually passed through + * a filter of the {@see 'comment_form_field_$name'} where `$name` is the key used + * in the array of fields. + * + * @since 3.0.0 + * @since 4.1.0 Introduced the 'class_submit' argument. + * @since 4.2.0 Introduced the 'submit_button' and 'submit_fields' arguments. + * @since 4.4.0 Introduced the 'class_form', 'title_reply_before', 'title_reply_after', + * 'cancel_reply_before', and 'cancel_reply_after' arguments. + * @since 4.5.0 The 'author', 'email', and 'url' form fields are limited to 245, 100, + * and 200 characters, respectively. + * @since 4.6.0 Introduced the 'action' argument. + * @since 4.9.6 Introduced the 'cookies' default comment field. + * @since 5.5.0 Introduced the 'class_container' argument. + * + * @param array $args { + * Optional. Default arguments and form fields to override. + * + * @type array $fields { + * Default comment fields, filterable by default via the {@see 'comment_form_default_fields'} hook. + * + * @type string $author Comment author field HTML. + * @type string $email Comment author email field HTML. + * @type string $url Comment author URL field HTML. + * @type string $cookies Comment cookie opt-in field HTML. + * } + * @type string $comment_field The comment textarea field HTML. + * @type string $must_log_in HTML element for a 'must be logged in to comment' message. + * @type string $logged_in_as The HTML for the 'logged in as [user]' message, the Edit profile link, + * and the Log out link. + * @type string $comment_notes_before HTML element for a message displayed before the comment fields + * if the user is not logged in. + * Default 'Your email address will not be published.'. + * @type string $comment_notes_after HTML element for a message displayed after the textarea field. + * @type string $action The comment form element action attribute. Default '/wp-comments-post.php'. + * @type string $id_form The comment form element id attribute. Default 'commentform'. + * @type string $id_submit The comment submit element id attribute. Default 'submit'. + * @type string $class_container The comment form container class attribute. Default 'comment-respond'. + * @type string $class_form The comment form element class attribute. Default 'comment-form'. + * @type string $class_submit The comment submit element class attribute. Default 'submit'. + * @type string $name_submit The comment submit element name attribute. Default 'submit'. + * @type string $title_reply The translatable 'reply' button label. Default 'Leave a Reply'. + * @type string $title_reply_to The translatable 'reply-to' button label. Default 'Leave a Reply to %s', + * where %s is the author of the comment being replied to. + * @type string $title_reply_before HTML displayed before the comment form title. + * Default: '<h3 id="reply-title" class="comment-reply-title">'. + * @type string $title_reply_after HTML displayed after the comment form title. + * Default: '</h3>'. + * @type string $cancel_reply_before HTML displayed before the cancel reply link. + * @type string $cancel_reply_after HTML displayed after the cancel reply link. + * @type string $cancel_reply_link The translatable 'cancel reply' button label. Default 'Cancel reply'. + * @type string $label_submit The translatable 'submit' button label. Default 'Post a comment'. + * @type string $submit_button HTML format for the Submit button. + * Default: '<input name="%1$s" type="submit" id="%2$s" class="%3$s" value="%4$s" />'. + * @type string $submit_field HTML format for the markup surrounding the Submit button and comment hidden + * fields. Default: '<p class="form-submit">%1$s %2$s</p>', where %1$s is the + * submit button markup and %2$s is the comment hidden fields. + * @type string $format The comment form format. Default 'xhtml'. Accepts 'xhtml', 'html5'. + * } + * @param int|WP_Post $post Post ID or WP_Post object to generate the form for. Default current post. + * @phpstan-param array{ + * fields?: array{ + * author: string, + * email: string, + * url: string, + * cookies: string, + * }, + * comment_field?: string, + * must_log_in?: string, + * logged_in_as?: string, + * comment_notes_before?: string, + * comment_notes_after?: string, + * action?: string, + * id_form?: string, + * id_submit?: string, + * class_container?: string, + * class_form?: string, + * class_submit?: string, + * name_submit?: string, + * title_reply?: string, + * title_reply_to?: string, + * title_reply_before?: string, + * title_reply_after?: string, + * cancel_reply_before?: string, + * cancel_reply_after?: string, + * cancel_reply_link?: string, + * label_submit?: string, + * submit_button?: string, + * submit_field?: string, + * format?: string, + * } $args + */ + function comment_form($args = array(), $post = \null) + { + } + /** + * Core Comment API + * + * @package WordPress + * @subpackage Comment + */ + /** + * Checks whether a comment passes internal checks to be allowed to add. + * + * If manual comment moderation is set in the administration, then all checks, + * regardless of their type and substance, will fail and the function will + * return false. + * + * If the number of links exceeds the amount in the administration, then the + * check fails. If any of the parameter contents contain any disallowed words, + * then the check fails. + * + * If the comment author was approved before, then the comment is automatically + * approved. + * + * If all checks pass, the function will return true. + * + * @since 1.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $author Comment author name. + * @param string $email Comment author email. + * @param string $url Comment author URL. + * @param string $comment Content of the comment. + * @param string $user_ip Comment author IP address. + * @param string $user_agent Comment author User-Agent. + * @param string $comment_type Comment type, either user-submitted comment, + * trackback, or pingback. + * @return bool If all checks pass, true, otherwise false. + */ + function check_comment($author, $email, $url, $comment, $user_ip, $user_agent, $comment_type) + { + } + /** + * Retrieves the approved comments for a post. + * + * @since 2.0.0 + * @since 4.1.0 Refactored to leverage WP_Comment_Query over a direct query. + * + * @param int $post_id The ID of the post. + * @param array $args Optional. See WP_Comment_Query::__construct() for information on accepted arguments. + * @return WP_Comment[]|int[]|int The approved comments, or number of comments if `$count` + * argument is true. + * @phpstan-param array{ + * author_email?: string, + * author_url?: string, + * author__in?: int[], + * author__not_in?: int[], + * comment__in?: int[], + * comment__not_in?: int[], + * count?: bool, + * date_query?: array, + * fields?: string, + * include_unapproved?: array, + * karma?: int, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * number?: int, + * paged?: int, + * offset?: int, + * no_found_rows?: bool, + * orderby?: string|array, + * order?: string, + * parent?: int, + * parent__in?: int[], + * parent__not_in?: int[], + * post_author__in?: int[], + * post_author__not_in?: int[], + * post_id?: int, + * post__in?: int[], + * post__not_in?: int[], + * post_author?: int, + * post_status?: string|string[], + * post_type?: string|string[], + * post_name?: string, + * post_parent?: int, + * search?: string, + * status?: string|array, + * type?: string|string[], + * type__in?: string[], + * type__not_in?: string[], + * user_id?: int, + * hierarchical?: bool|string, + * cache_domain?: string, + * update_comment_meta_cache?: bool, + * update_comment_post_cache?: bool, + * } $args See WP_Comment_Query::__construct() + */ + function get_approved_comments($post_id, $args = array()) + { + } + /** + * Retrieves comment data given a comment ID or comment object. + * + * If an object is passed then the comment data will be cached and then returned + * after being passed through a filter. If the comment is empty, then the global + * comment variable will be used, if it is set. + * + * @since 2.0.0 + * + * @global WP_Comment $comment Global comment object. + * + * @param WP_Comment|string|int $comment Comment to retrieve. + * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which + * correspond to a WP_Comment object, an associative array, or a numeric array, + * respectively. Default OBJECT. + * @return WP_Comment|array|null Depends on $output value. + */ + function get_comment($comment = \null, $output = \OBJECT) + { + } + /** + * Retrieves a list of comments. + * + * The comment list can be for the blog as a whole or for an individual post. + * + * @since 2.7.0 + * + * @param string|array $args Optional. Array or string of arguments. See WP_Comment_Query::__construct() + * for information on accepted arguments. Default empty. + * @return WP_Comment[]|int[]|int List of comments or number of found comments if `$count` argument is true. + * @phpstan-param array{ + * author_email?: string, + * author_url?: string, + * author__in?: int[], + * author__not_in?: int[], + * comment__in?: int[], + * comment__not_in?: int[], + * count?: bool, + * date_query?: array, + * fields?: string, + * include_unapproved?: array, + * karma?: int, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * number?: int, + * paged?: int, + * offset?: int, + * no_found_rows?: bool, + * orderby?: string|array, + * order?: string, + * parent?: int, + * parent__in?: int[], + * parent__not_in?: int[], + * post_author__in?: int[], + * post_author__not_in?: int[], + * post_id?: int, + * post__in?: int[], + * post__not_in?: int[], + * post_author?: int, + * post_status?: string|string[], + * post_type?: string|string[], + * post_name?: string, + * post_parent?: int, + * search?: string, + * status?: string|array, + * type?: string|string[], + * type__in?: string[], + * type__not_in?: string[], + * user_id?: int, + * hierarchical?: bool|string, + * cache_domain?: string, + * update_comment_meta_cache?: bool, + * update_comment_post_cache?: bool, + * } $args See WP_Comment_Query::__construct() + */ + function get_comments($args = '') + { + } + /** + * Retrieves all of the WordPress supported comment statuses. + * + * Comments have a limited set of valid status values, this provides the comment + * status values and descriptions. + * + * @since 2.7.0 + * + * @return string[] List of comment status labels keyed by status. + */ + function get_comment_statuses() + { + } + /** + * Gets the default comment status for a post type. + * + * @since 4.3.0 + * + * @param string $post_type Optional. Post type. Default 'post'. + * @param string $comment_type Optional. Comment type. Default 'comment'. + * @return string Expected return value is 'open' or 'closed'. + */ + function get_default_comment_status($post_type = 'post', $comment_type = 'comment') + { + } + /** + * Retrieves the date the last comment was modified. + * + * @since 1.5.0 + * @since 4.7.0 Replaced caching the modified date in a local static variable + * with the Object Cache API. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $timezone Which timezone to use in reference to 'gmt', 'blog', or 'server' locations. + * @return string|false Last comment modified date on success, false on failure. + */ + function get_lastcommentmodified($timezone = 'server') + { + } + /** + * Retrieves the total comment counts for the whole site or a single post. + * + * @since 2.0.0 + * + * @param int $post_id Optional. Restrict the comment counts to the given post. Default 0, which indicates that + * comment counts for the whole site will be retrieved. + * @return int[] { + * The number of comments keyed by their status. + * + * @type int $approved The number of approved comments. + * @type int $awaiting_moderation The number of comments awaiting moderation (a.k.a. pending). + * @type int $spam The number of spam comments. + * @type int $trash The number of trashed comments. + * @type int $post-trashed The number of comments for posts that are in the trash. + * @type int $total_comments The total number of non-trashed comments, including spam. + * @type int $all The total number of pending or approved comments. + * } + * @phpstan-return array{ + * approved: int, + * awaiting_moderation: int, + * spam: int, + * trash: int, + * post-trashed: int, + * total_comments: int, + * all: int, + * } + */ + function get_comment_count($post_id = 0) + { + } + // + // Comment meta functions. + // + /** + * Adds meta data field to a comment. + * + * @since 2.9.0 + * + * @link https://developer.wordpress.org/reference/functions/add_comment_meta/ + * + * @param int $comment_id Comment ID. + * @param string $meta_key Metadata name. + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. + * @param bool $unique Optional. Whether the same key should not be added. + * Default false. + * @return int|false Meta ID on success, false on failure. + */ + function add_comment_meta($comment_id, $meta_key, $meta_value, $unique = \false) + { + } + /** + * Removes metadata matching criteria from a comment. + * + * You can match based on the key, or key and value. Removing based on key and + * value, will keep from removing duplicate metadata with the same key. It also + * allows removing all metadata matching key, if needed. + * + * @since 2.9.0 + * + * @link https://developer.wordpress.org/reference/functions/delete_comment_meta/ + * + * @param int $comment_id Comment ID. + * @param string $meta_key Metadata name. + * @param mixed $meta_value Optional. Metadata value. If provided, + * rows will only be removed that match the value. + * Must be serializable if non-scalar. Default empty. + * @return bool True on success, false on failure. + */ + function delete_comment_meta($comment_id, $meta_key, $meta_value = '') + { + } + /** + * Retrieves comment meta field for a comment. + * + * @since 2.9.0 + * + * @link https://developer.wordpress.org/reference/functions/get_comment_meta/ + * + * @param int $comment_id Comment ID. + * @param string $key Optional. The meta key to retrieve. By default, + * returns data for all keys. + * @param bool $single Optional. Whether to return a single value. + * This parameter has no effect if `$key` is not specified. + * Default false. + * @return mixed An array of values if `$single` is false. + * The value of meta data field if `$single` is true. + * False for an invalid `$comment_id` (non-numeric, zero, or negative value). + * An empty string if a valid but non-existing comment ID is passed. + */ + function get_comment_meta($comment_id, $key = '', $single = \false) + { + } + /** + * Updates comment meta field based on comment ID. + * + * Use the $prev_value parameter to differentiate between meta fields with the + * same key and comment ID. + * + * If the meta field for the comment does not exist, it will be added. + * + * @since 2.9.0 + * + * @link https://developer.wordpress.org/reference/functions/update_comment_meta/ + * + * @param int $comment_id Comment ID. + * @param string $meta_key Metadata key. + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. + * @param mixed $prev_value Optional. Previous value to check before updating. + * If specified, only update existing metadata entries with + * this value. Otherwise, update all entries. Default empty. + * @return int|bool Meta ID if the key didn't exist, true on successful update, + * false on failure or if the value passed to the function + * is the same as the one that is already in the database. + */ + function update_comment_meta($comment_id, $meta_key, $meta_value, $prev_value = '') + { + } + /** + * Queues comments for metadata lazy-loading. + * + * @since 4.5.0 + * + * @param WP_Comment[] $comments Array of comment objects. + */ + function wp_queue_comments_for_comment_meta_lazyload($comments) + { + } + /** + * Sets the cookies used to store an unauthenticated commentator's identity. Typically used + * to recall previous comments by this commentator that are still held in moderation. + * + * @since 3.4.0 + * @since 4.9.6 The `$cookies_consent` parameter was added. + * + * @param WP_Comment $comment Comment object. + * @param WP_User $user Comment author's user object. The user may not exist. + * @param bool $cookies_consent Optional. Comment author's consent to store cookies. Default true. + */ + function wp_set_comment_cookies($comment, $user, $cookies_consent = \true) + { + } + /** + * Sanitizes the cookies sent to the user already. + * + * Will only do anything if the cookies have already been created for the user. + * Mostly used after cookies had been sent to use elsewhere. + * + * @since 2.0.4 + */ + function sanitize_comment_cookies() + { + } + /** + * Validates whether this comment is allowed to be made. + * + * @since 2.0.0 + * @since 4.7.0 The `$avoid_die` parameter was added, allowing the function + * to return a WP_Error object instead of dying. + * @since 5.5.0 The `$avoid_die` parameter was renamed to `$wp_error`. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $commentdata Contains information on the comment. + * @param bool $wp_error When true, a disallowed comment will result in the function + * returning a WP_Error object, rather than executing wp_die(). + * Default false. + * @return int|string|WP_Error Allowed comments return the approval status (0|1|'spam'|'trash'). + * If `$wp_error` is true, disallowed comments return a WP_Error. + */ + function wp_allow_comment($commentdata, $wp_error = \false) + { + } + /** + * Hooks WP's native database-based comment-flood check. + * + * This wrapper maintains backward compatibility with plugins that expect to + * be able to unhook the legacy check_comment_flood_db() function from + * 'check_comment_flood' using remove_action(). + * + * @since 2.3.0 + * @since 4.7.0 Converted to be an add_filter() wrapper. + */ + function check_comment_flood_db() + { + } + /** + * Checks whether comment flooding is occurring. + * + * Won't run, if current user can manage options, so to not block + * administrators. + * + * @since 4.7.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param bool $is_flood Is a comment flooding occurring? + * @param string $ip Comment author's IP address. + * @param string $email Comment author's email address. + * @param string $date MySQL time string. + * @param bool $avoid_die When true, a disallowed comment will result in the function + * returning without executing wp_die() or die(). Default false. + * @return bool Whether comment flooding is occurring. + */ + function wp_check_comment_flood($is_flood, $ip, $email, $date, $avoid_die = \false) + { + } + /** + * Separates an array of comments into an array keyed by comment_type. + * + * @since 2.7.0 + * + * @param WP_Comment[] $comments Array of comments + * @return WP_Comment[] Array of comments keyed by comment_type. + */ + function separate_comments(&$comments) + { + } + /** + * Calculates the total number of comment pages. + * + * @since 2.7.0 + * + * @uses Walker_Comment + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param WP_Comment[] $comments Optional. Array of WP_Comment objects. Defaults to `$wp_query->comments`. + * @param int $per_page Optional. Comments per page. + * @param bool $threaded Optional. Control over flat or threaded comments. + * @return int Number of comment pages. + */ + function get_comment_pages_count($comments = \null, $per_page = \null, $threaded = \null) + { + } + /** + * Calculates what page number a comment will appear on for comment paging. + * + * @since 2.7.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $comment_ID Comment ID. + * @param array $args { + * Array of optional arguments. + * + * @type string $type Limit paginated comments to those matching a given type. + * Accepts 'comment', 'trackback', 'pingback', 'pings' + * (trackbacks and pingbacks), or 'all'. Default 'all'. + * @type int $per_page Per-page count to use when calculating pagination. + * Defaults to the value of the 'comments_per_page' option. + * @type int|string $max_depth If greater than 1, comment page will be determined + * for the top-level parent `$comment_ID`. + * Defaults to the value of the 'thread_comments_depth' option. + * } * + * @return int|null Comment page number or null on error. + * @phpstan-param array{ + * type?: string, + * per_page?: int, + * max_depth?: int|string, + * } $args + */ + function get_page_of_comment($comment_ID, $args = array()) + { + } + /** + * Retrieves the maximum character lengths for the comment form fields. + * + * @since 4.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return int[] Array of maximum lengths keyed by field name. + */ + function wp_get_comment_fields_max_lengths() + { + } + /** + * Compares the lengths of comment data against the maximum character limits. + * + * @since 4.7.0 + * + * @param array $comment_data Array of arguments for inserting a comment. + * @return WP_Error|true WP_Error when a comment field exceeds the limit, + * otherwise true. + */ + function wp_check_comment_data_max_lengths($comment_data) + { + } + /** + * Checks if a comment contains disallowed characters or words. + * + * @since 5.5.0 + * + * @param string $author The author of the comment + * @param string $email The email of the comment + * @param string $url The url used in the comment + * @param string $comment The comment content + * @param string $user_ip The comment author's IP address + * @param string $user_agent The author's browser user agent + * @return bool True if comment contains disallowed content, false if comment does not + */ + function wp_check_comment_disallowed_list($author, $email, $url, $comment, $user_ip, $user_agent) + { + } + /** + * Retrieves the total comment counts for the whole site or a single post. + * + * The comment stats are cached and then retrieved, if they already exist in the + * cache. + * + * @see get_comment_count() Which handles fetching the live comment counts. + * + * @since 2.5.0 + * + * @param int $post_id Optional. Restrict the comment counts to the given post. Default 0, which indicates that + * comment counts for the whole site will be retrieved. + * @return stdClass { + * The number of comments keyed by their status. + * + * @type int $approved The number of approved comments. + * @type int $moderated The number of comments awaiting moderation (a.k.a. pending). + * @type int $spam The number of spam comments. + * @type int $trash The number of trashed comments. + * @type int $post-trashed The number of comments for posts that are in the trash. + * @type int $total_comments The total number of non-trashed comments, including spam. + * @type int $all The total number of pending or approved comments. + * } + */ + function wp_count_comments($post_id = 0) + { + } + /** + * Trashes or deletes a comment. + * + * The comment is moved to Trash instead of permanently deleted unless Trash is + * disabled, item is already in the Trash, or $force_delete is true. + * + * The post comment count will be updated if the comment was approved and has a + * post ID available. + * + * @since 2.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|WP_Comment $comment_id Comment ID or WP_Comment object. + * @param bool $force_delete Whether to bypass Trash and force deletion. Default false. + * @return bool True on success, false on failure. + */ + function wp_delete_comment($comment_id, $force_delete = \false) + { + } + /** + * Moves a comment to the Trash + * + * If Trash is disabled, comment is permanently deleted. + * + * @since 2.9.0 + * + * @param int|WP_Comment $comment_id Comment ID or WP_Comment object. + * @return bool True on success, false on failure. + */ + function wp_trash_comment($comment_id) + { + } + /** + * Removes a comment from the Trash + * + * @since 2.9.0 + * + * @param int|WP_Comment $comment_id Comment ID or WP_Comment object. + * @return bool True on success, false on failure. + */ + function wp_untrash_comment($comment_id) + { + } + /** + * Marks a comment as Spam. + * + * @since 2.9.0 + * + * @param int|WP_Comment $comment_id Comment ID or WP_Comment object. + * @return bool True on success, false on failure. + */ + function wp_spam_comment($comment_id) + { + } + /** + * Removes a comment from the Spam. + * + * @since 2.9.0 + * + * @param int|WP_Comment $comment_id Comment ID or WP_Comment object. + * @return bool True on success, false on failure. + */ + function wp_unspam_comment($comment_id) + { + } + /** + * Retrieves the status of a comment by comment ID. + * + * @since 1.0.0 + * + * @param int|WP_Comment $comment_id Comment ID or WP_Comment object + * @return string|false Status might be 'trash', 'approved', 'unapproved', 'spam'. False on failure. + */ + function wp_get_comment_status($comment_id) + { + } + /** + * Calls hooks for when a comment status transition occurs. + * + * Calls hooks for comment status transitions. If the new comment status is not the same + * as the previous comment status, then two hooks will be ran, the first is + * {@see 'transition_comment_status'} with new status, old status, and comment data. + * The next action called is {@see 'comment_$old_status_to_$new_status'}. It has + * the comment data. + * + * The final action will run whether or not the comment statuses are the same. + * The action is named {@see 'comment_$new_status_$comment->comment_type'}. + * + * @since 2.7.0 + * + * @param string $new_status New comment status. + * @param string $old_status Previous comment status. + * @param WP_Comment $comment Comment object. + */ + function wp_transition_comment_status($new_status, $old_status, $comment) + { + } + /** + * Clears the lastcommentmodified cached value when a comment status is changed. + * + * Deletes the lastcommentmodified cache key when a comment enters or leaves + * 'approved' status. + * + * @since 4.7.0 + * @access private + * + * @param string $new_status The new comment status. + * @param string $old_status The old comment status. + */ + function _clear_modified_cache_on_transition_comment_status($new_status, $old_status) + { + } + /** + * Gets current commenter's name, email, and URL. + * + * Expects cookies content to already be sanitized. User of this function might + * wish to recheck the returned array for validity. + * + * @see sanitize_comment_cookies() Use to sanitize cookies + * + * @since 2.0.4 + * + * @return array { + * An array of current commenter variables. + * + * @type string $comment_author The name of the current commenter, or an empty string. + * @type string $comment_author_email The email address of the current commenter, or an empty string. + * @type string $comment_author_url The URL address of the current commenter, or an empty string. + * } + * @phpstan-return array{ + * comment_author: string, + * comment_author_email: string, + * comment_author_url: string, + * } + */ + function wp_get_current_commenter() + { + } + /** + * Gets unapproved comment author's email. + * + * Used to allow the commenter to see their pending comment. + * + * @since 5.1.0 + * @since 5.7.0 The window within which the author email for an unapproved comment + * can be retrieved was extended to 10 minutes. + * + * @return string The unapproved comment author's email (when supplied). + */ + function wp_get_unapproved_comment_author_email() + { + } + /** + * Inserts a comment into the database. + * + * @since 2.0.0 + * @since 4.4.0 Introduced the `$comment_meta` argument. + * @since 5.5.0 Default value for `$comment_type` argument changed to `comment`. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $commentdata { + * Array of arguments for inserting a new comment. + * + * @type string $comment_agent The HTTP user agent of the `$comment_author` when + * the comment was submitted. Default empty. + * @type int|string $comment_approved Whether the comment has been approved. Default 1. + * @type string $comment_author The name of the author of the comment. Default empty. + * @type string $comment_author_email The email address of the `$comment_author`. Default empty. + * @type string $comment_author_IP The IP address of the `$comment_author`. Default empty. + * @type string $comment_author_url The URL address of the `$comment_author`. Default empty. + * @type string $comment_content The content of the comment. Default empty. + * @type string $comment_date The date the comment was submitted. To set the date + * manually, `$comment_date_gmt` must also be specified. + * Default is the current time. + * @type string $comment_date_gmt The date the comment was submitted in the GMT timezone. + * Default is `$comment_date` in the site's GMT timezone. + * @type int $comment_karma The karma of the comment. Default 0. + * @type int $comment_parent ID of this comment's parent, if any. Default 0. + * @type int $comment_post_ID ID of the post that relates to the comment, if any. + * Default 0. + * @type string $comment_type Comment type. Default 'comment'. + * @type array $comment_meta Optional. Array of key/value pairs to be stored in commentmeta for the + * new comment. + * @type int $user_id ID of the user who submitted the comment. Default 0. + * } + * @return int|false The new comment's ID on success, false on failure. + * @phpstan-param array{ + * comment_agent?: string, + * comment_approved?: int|string, + * comment_author?: string, + * comment_author_email?: string, + * comment_author_IP?: string, + * comment_author_url?: string, + * comment_content?: string, + * comment_date?: string, + * comment_date_gmt?: string, + * comment_karma?: int, + * comment_parent?: int, + * comment_post_ID?: int, + * comment_type?: string, + * comment_meta?: array, + * user_id?: int, + * } $commentdata + */ + function wp_insert_comment($commentdata) + { + } + /** + * Filters and sanitizes comment data. + * + * Sets the comment data 'filtered' field to true when finished. This can be + * checked as to whether the comment should be filtered and to keep from + * filtering the same comment more than once. + * + * @since 2.0.0 + * + * @param array $commentdata Contains information on the comment. + * @return array Parsed comment information. + */ + function wp_filter_comment($commentdata) + { + } + /** + * Determines whether a comment should be blocked because of comment flood. + * + * @since 2.1.0 + * + * @param bool $block Whether plugin has already blocked comment. + * @param int $time_lastcomment Timestamp for last comment. + * @param int $time_newcomment Timestamp for new comment. + * @return bool Whether comment should be blocked. + */ + function wp_throttle_comment_flood($block, $time_lastcomment, $time_newcomment) + { + } + /** + * Adds a new comment to the database. + * + * Filters new comment to ensure that the fields are sanitized and valid before + * inserting comment into database. Calls {@see 'comment_post'} action with comment ID + * and whether comment is approved by WordPress. Also has {@see 'preprocess_comment'} + * filter for processing the comment data before the function handles it. + * + * We use `REMOTE_ADDR` here directly. If you are behind a proxy, you should ensure + * that it is properly set, such as in wp-config.php, for your environment. + * + * See {@link https://core.trac.wordpress.org/ticket/9235} + * + * @since 1.5.0 + * @since 4.3.0 Introduced the `comment_agent` and `comment_author_IP` arguments. + * @since 4.7.0 The `$avoid_die` parameter was added, allowing the function + * to return a WP_Error object instead of dying. + * @since 5.5.0 The `$avoid_die` parameter was renamed to `$wp_error`. + * @since 5.5.0 Introduced the `comment_type` argument. + * + * @see wp_insert_comment() + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $commentdata { + * Comment data. + * + * @type string $comment_author The name of the comment author. + * @type string $comment_author_email The comment author email address. + * @type string $comment_author_url The comment author URL. + * @type string $comment_content The content of the comment. + * @type string $comment_date The date the comment was submitted. Default is the current time. + * @type string $comment_date_gmt The date the comment was submitted in the GMT timezone. + * Default is `$comment_date` in the GMT timezone. + * @type string $comment_type Comment type. Default 'comment'. + * @type int $comment_parent The ID of this comment's parent, if any. Default 0. + * @type int $comment_post_ID The ID of the post that relates to the comment. + * @type int $user_id The ID of the user who submitted the comment. Default 0. + * @type int $user_ID Kept for backward-compatibility. Use `$user_id` instead. + * @type string $comment_agent Comment author user agent. Default is the value of 'HTTP_USER_AGENT' + * in the `$_SERVER` superglobal sent in the original request. + * @type string $comment_author_IP Comment author IP address in IPv4 format. Default is the value of + * 'REMOTE_ADDR' in the `$_SERVER` superglobal sent in the original request. + * } + * @param bool $wp_error Should errors be returned as WP_Error objects instead of + * executing wp_die()? Default false. + * @return int|false|WP_Error The ID of the comment on success, false or WP_Error on failure. + * @phpstan-param array{ + * comment_author?: string, + * comment_author_email?: string, + * comment_author_url?: string, + * comment_content?: string, + * comment_date?: string, + * comment_date_gmt?: string, + * comment_type?: string, + * comment_parent?: int, + * comment_post_ID?: int, + * user_id?: int, + * user_ID?: int, + * comment_agent?: string, + * comment_author_IP?: string, + * } $commentdata + */ + function wp_new_comment($commentdata, $wp_error = \false) + { + } + /** + * Sends a comment moderation notification to the comment moderator. + * + * @since 4.4.0 + * + * @param int $comment_ID ID of the comment. + * @return bool True on success, false on failure. + */ + function wp_new_comment_notify_moderator($comment_ID) + { + } + /** + * Sends a notification of a new comment to the post author. + * + * @since 4.4.0 + * + * Uses the {@see 'notify_post_author'} filter to determine whether the post author + * should be notified when a new comment is added, overriding site setting. + * + * @param int $comment_ID Comment ID. + * @return bool True on success, false on failure. + */ + function wp_new_comment_notify_postauthor($comment_ID) + { + } + /** + * Sets the status of a comment. + * + * The {@see 'wp_set_comment_status'} action is called after the comment is handled. + * If the comment status is not in the list, then false is returned. + * + * @since 1.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|WP_Comment $comment_id Comment ID or WP_Comment object. + * @param string $comment_status New comment status, either 'hold', 'approve', 'spam', or 'trash'. + * @param bool $wp_error Whether to return a WP_Error object if there is a failure. Default false. + * @return bool|WP_Error True on success, false or WP_Error on failure. + */ + function wp_set_comment_status($comment_id, $comment_status, $wp_error = \false) + { + } + /** + * Updates an existing comment in the database. + * + * Filters the comment and makes sure certain fields are valid before updating. + * + * @since 2.0.0 + * @since 4.9.0 Add updating comment meta during comment update. + * @since 5.5.0 The `$wp_error` parameter was added. + * @since 5.5.0 The return values for an invalid comment or post ID + * were changed to false instead of 0. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $commentarr Contains information on the comment. + * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. + * @return int|false|WP_Error The value 1 if the comment was updated, 0 if not updated. + * False or a WP_Error object on failure. + */ + function wp_update_comment($commentarr, $wp_error = \false) + { + } + /** + * Determines whether to defer comment counting. + * + * When setting $defer to true, all post comment counts will not be updated + * until $defer is set to false. When $defer is set to false, then all + * previously deferred updated post comment counts will then be automatically + * updated without having to call wp_update_comment_count() after. + * + * @since 2.5.0 + * + * @param bool $defer + * @return bool + */ + function wp_defer_comment_counting($defer = \null) + { + } + /** + * Updates the comment count for post(s). + * + * When $do_deferred is false (is by default) and the comments have been set to + * be deferred, the post_id will be added to a queue, which will be updated at a + * later date and only updated once per post ID. + * + * If the comments have not be set up to be deferred, then the post will be + * updated. When $do_deferred is set to true, then all previous deferred post + * IDs will be updated along with the current $post_id. + * + * @since 2.1.0 + * + * @see wp_update_comment_count_now() For what could cause a false return value + * + * @param int|null $post_id Post ID. + * @param bool $do_deferred Optional. Whether to process previously deferred + * post comment counts. Default false. + * @return bool|void True on success, false on failure or if post with ID does + * not exist. + */ + function wp_update_comment_count($post_id, $do_deferred = \false) + { + } + /** + * Updates the comment count for the post. + * + * @since 2.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $post_id Post ID + * @return bool True on success, false if the post does not exist. + */ + function wp_update_comment_count_now($post_id) + { + } + // + // Ping and trackback functions. + // + /** + * Finds a pingback server URI based on the given URL. + * + * Checks the HTML for the rel="pingback" link and x-pingback headers. It does + * a check for the x-pingback headers first and returns that, if available. The + * check for the rel="pingback" has more overhead than just the header. + * + * @since 1.5.0 + * + * @param string $url URL to ping. + * @param string $deprecated Not Used. + * @return string|false String containing URI on success, false on failure. + */ + function discover_pingback_server_uri($url, $deprecated = '') + { + } + /** + * Performs all pingbacks, enclosures, trackbacks, and sends to pingback services. + * + * @since 2.1.0 + * @since 5.6.0 Introduced `do_all_pings` action hook for individual services. + */ + function do_all_pings() + { + } + /** + * Performs all pingbacks. + * + * @since 5.6.0 + */ + function do_all_pingbacks() + { + } + /** + * Performs all enclosures. + * + * @since 5.6.0 + */ + function do_all_enclosures() + { + } + /** + * Performs all trackbacks. + * + * @since 5.6.0 + */ + function do_all_trackbacks() + { + } + /** + * Performs trackbacks. + * + * @since 1.5.0 + * @since 4.7.0 `$post` can be a WP_Post object. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|WP_Post $post Post ID or object to do trackbacks on. + */ + function do_trackbacks($post) + { + } + /** + * Sends pings to all of the ping site services. + * + * @since 1.2.0 + * + * @param int $post_id Post ID. + * @return int Same post ID as provided. + */ + function generic_ping($post_id = 0) + { + } + /** + * Pings back the links found in a post. + * + * @since 0.71 + * @since 4.7.0 `$post` can be a WP_Post object. + * + * @param string $content Post content to check for links. If empty will retrieve from post. + * @param int|WP_Post $post Post ID or object. + */ + function pingback($content, $post) + { + } + /** + * Checks whether blog is public before returning sites. + * + * @since 2.1.0 + * + * @param mixed $sites Will return if blog is public, will not return if not public. + * @return mixed Empty string if blog is not public, returns $sites, if site is public. + */ + function privacy_ping_filter($sites) + { + } + /** + * Sends a Trackback. + * + * Updates database when sending trackback to prevent duplicates. + * + * @since 0.71 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $trackback_url URL to send trackbacks. + * @param string $title Title of post. + * @param string $excerpt Excerpt of post. + * @param int $ID Post ID. + * @return int|false|void Database query from update. + */ + function trackback($trackback_url, $title, $excerpt, $ID) + { + } + /** + * Sends a pingback. + * + * @since 1.2.0 + * + * @param string $server Host of blog to connect to. + * @param string $path Path to send the ping. + */ + function weblog_ping($server = '', $path = '') + { + } + /** + * Default filter attached to pingback_ping_source_uri to validate the pingback's Source URI. + * + * @since 3.5.1 + * + * @see wp_http_validate_url() + * + * @param string $source_uri + * @return string + */ + function pingback_ping_source_uri($source_uri) + { + } + /** + * Default filter attached to xmlrpc_pingback_error. + * + * Returns a generic pingback error code unless the error code is 48, + * which reports that the pingback is already registered. + * + * @since 3.5.1 + * + * @link https://www.hixie.ch/specs/pingback/pingback#TOC3 + * + * @param IXR_Error $ixr_error + * @return IXR_Error + */ + function xmlrpc_pingback_error($ixr_error) + { + } + // + // Cache. + // + /** + * Removes a comment from the object cache. + * + * @since 2.3.0 + * + * @param int|array $ids Comment ID or an array of comment IDs to remove from cache. + */ + function clean_comment_cache($ids) + { + } + /** + * Updates the comment cache of given comments. + * + * Will add the comments in $comments to the cache. If comment ID already exists + * in the comment cache then it will not be updated. The comment is added to the + * cache using the comment group with the key using the ID of the comments. + * + * @since 2.3.0 + * @since 4.4.0 Introduced the `$update_meta_cache` parameter. + * + * @param WP_Comment[] $comments Array of comment objects + * @param bool $update_meta_cache Whether to update commentmeta cache. Default true. + */ + function update_comment_cache($comments, $update_meta_cache = \true) + { + } + /** + * Adds any comments from the given IDs to the cache that do not already exist in cache. + * + * @since 4.4.0 + * @since 6.1.0 This function is no longer marked as "private". + * + * @see update_comment_cache() + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int[] $comment_ids Array of comment IDs. + * @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true. + */ + function _prime_comment_caches($comment_ids, $update_meta_cache = \true) + { + } + // + // Internal. + // + /** + * Closes comments on old posts on the fly, without any extra DB queries. Hooked to the_posts. + * + * @since 2.7.0 + * @access private + * + * @param WP_Post $posts Post data object. + * @param WP_Query $query Query object. + * @return array + */ + function _close_comments_for_old_posts($posts, $query) + { + } + /** + * Closes comments on an old post. Hooked to comments_open and pings_open. + * + * @since 2.7.0 + * @access private + * + * @param bool $open Comments open or closed. + * @param int $post_id Post ID. + * @return bool $open + */ + function _close_comments_for_old_post($open, $post_id) + { + } + /** + * Handles the submission of a comment, usually posted to wp-comments-post.php via a comment form. + * + * This function expects unslashed data, as opposed to functions such as `wp_new_comment()` which + * expect slashed data. + * + * @since 4.4.0 + * + * @param array $comment_data { + * Comment data. + * + * @type string|int $comment_post_ID The ID of the post that relates to the comment. + * @type string $author The name of the comment author. + * @type string $email The comment author email address. + * @type string $url The comment author URL. + * @type string $comment The content of the comment. + * @type string|int $comment_parent The ID of this comment's parent, if any. Default 0. + * @type string $_wp_unfiltered_html_comment The nonce value for allowing unfiltered HTML. + * } + * @return WP_Comment|WP_Error A WP_Comment object on success, a WP_Error object on failure. + * @phpstan-param array{ + * comment_post_ID?: string|int, + * author?: string, + * email?: string, + * url?: string, + * comment?: string, + * comment_parent?: string|int, + * _wp_unfiltered_html_comment?: string, + * } $comment_data + */ + function wp_handle_comment_submission($comment_data) + { + } + /** + * Registers the personal data exporter for comments. + * + * @since 4.9.6 + * + * @param array $exporters An array of personal data exporters. + * @return array An array of personal data exporters. + */ + function wp_register_comment_personal_data_exporter($exporters) + { + } + /** + * Finds and exports personal data associated with an email address from the comments table. + * + * @since 4.9.6 + * + * @param string $email_address The comment author email address. + * @param int $page Comment page. + * @return array An array of personal data. + */ + function wp_comments_personal_data_exporter($email_address, $page = 1) + { + } + /** + * Registers the personal data eraser for comments. + * + * @since 4.9.6 + * + * @param array $erasers An array of personal data erasers. + * @return array An array of personal data erasers. + */ + function wp_register_comment_personal_data_eraser($erasers) + { + } + /** + * Erases personal data associated with an email address from the comments table. + * + * @since 4.9.6 + * + * @param string $email_address The comment author email address. + * @param int $page Comment page. + * @return array + */ + function wp_comments_personal_data_eraser($email_address, $page = 1) + { + } + /** + * Sets the last changed time for the 'comment' cache group. + * + * @since 5.0.0 + */ + function wp_cache_set_comments_last_changed() + { + } + /** + * Updates the comment type for a batch of comments. + * + * @since 5.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function _wp_batch_update_comment_type() + { + } + /** + * In order to avoid the _wp_batch_update_comment_type() job being accidentally removed, + * check that it's still scheduled while we haven't finished updating comment types. + * + * @ignore + * @since 5.5.0 + */ + function _wp_check_for_scheduled_update_comment_type() + { + } + /** + * WordPress Cron API + * + * @package WordPress + */ + /** + * Schedules an event to run only once. + * + * Schedules a hook which will be triggered by WordPress at the specified UTC time. + * The action will trigger when someone visits your WordPress site if the scheduled + * time has passed. + * + * Note that scheduling an event to occur within 10 minutes of an existing event + * with the same action hook will be ignored unless you pass unique `$args` values + * for each scheduled event. + * + * Use wp_next_scheduled() to prevent duplicate events. + * + * Use wp_schedule_event() to schedule a recurring event. + * + * @since 2.1.0 + * @since 5.1.0 Return value modified to boolean indicating success or failure, + * {@see 'pre_schedule_event'} filter added to short-circuit the function. + * @since 5.7.0 The `$wp_error` parameter was added. + * + * @link https://developer.wordpress.org/reference/functions/wp_schedule_single_event/ + * + * @param int $timestamp Unix timestamp (UTC) for when to next run the event. + * @param string $hook Action hook to execute when the event is run. + * @param array $args Optional. Array containing arguments to pass to the + * hook's callback function. Each value in the array + * is passed to the callback as an individual parameter. + * The array keys are ignored. Default empty array. + * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. + * @return bool|WP_Error True if event successfully scheduled. False or WP_Error on failure. + * @phpstan-param list<mixed> $args + * @phpstan-return bool|WP_Error + */ + function wp_schedule_single_event($timestamp, $hook, $args = array(), $wp_error = \false) + { + } + /** + * Schedules a recurring event. + * + * Schedules a hook which will be triggered by WordPress at the specified interval. + * The action will trigger when someone visits your WordPress site if the scheduled + * time has passed. + * + * Valid values for the recurrence are 'hourly', 'daily', and 'twicedaily'. These can + * be extended using the {@see 'cron_schedules'} filter in wp_get_schedules(). + * + * Use wp_next_scheduled() to prevent duplicate events. + * + * Use wp_schedule_single_event() to schedule a non-recurring event. + * + * @since 2.1.0 + * @since 5.1.0 Return value modified to boolean indicating success or failure, + * {@see 'pre_schedule_event'} filter added to short-circuit the function. + * @since 5.7.0 The `$wp_error` parameter was added. + * + * @link https://developer.wordpress.org/reference/functions/wp_schedule_event/ + * + * @param int $timestamp Unix timestamp (UTC) for when to next run the event. + * @param string $recurrence How often the event should subsequently recur. + * See wp_get_schedules() for accepted values. + * @param string $hook Action hook to execute when the event is run. + * @param array $args Optional. Array containing arguments to pass to the + * hook's callback function. Each value in the array + * is passed to the callback as an individual parameter. + * The array keys are ignored. Default empty array. + * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. + * @return bool|WP_Error True if event successfully scheduled. False or WP_Error on failure. + * @phpstan-param list<mixed> $args + * @phpstan-return bool|WP_Error + */ + function wp_schedule_event($timestamp, $recurrence, $hook, $args = array(), $wp_error = \false) + { + } + /** + * Reschedules a recurring event. + * + * Mainly for internal use, this takes the UTC timestamp of a previously run + * recurring event and reschedules it for its next run. + * + * To change upcoming scheduled events, use wp_schedule_event() to + * change the recurrence frequency. + * + * @since 2.1.0 + * @since 5.1.0 Return value modified to boolean indicating success or failure, + * {@see 'pre_reschedule_event'} filter added to short-circuit the function. + * @since 5.7.0 The `$wp_error` parameter was added. + * + * @param int $timestamp Unix timestamp (UTC) for when the event was scheduled. + * @param string $recurrence How often the event should subsequently recur. + * See wp_get_schedules() for accepted values. + * @param string $hook Action hook to execute when the event is run. + * @param array $args Optional. Array containing arguments to pass to the + * hook's callback function. Each value in the array + * is passed to the callback as an individual parameter. + * The array keys are ignored. Default empty array. + * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. + * @return bool|WP_Error True if event successfully rescheduled. False or WP_Error on failure. + * @phpstan-param list<mixed> $args + * @phpstan-return bool|WP_Error + */ + function wp_reschedule_event($timestamp, $recurrence, $hook, $args = array(), $wp_error = \false) + { + } + /** + * Unschedule a previously scheduled event. + * + * The $timestamp and $hook parameters are required so that the event can be + * identified. + * + * @since 2.1.0 + * @since 5.1.0 Return value modified to boolean indicating success or failure, + * {@see 'pre_unschedule_event'} filter added to short-circuit the function. + * @since 5.7.0 The `$wp_error` parameter was added. + * + * @param int $timestamp Unix timestamp (UTC) of the event. + * @param string $hook Action hook of the event. + * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. + * Although not passed to a callback, these arguments are used to uniquely identify the + * event, so they should be the same as those used when originally scheduling the event. + * Default empty array. + * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. + * @return bool|WP_Error True if event successfully unscheduled. False or WP_Error on failure. + * @phpstan-param list<mixed> $args + * @phpstan-return bool|WP_Error + */ + function wp_unschedule_event($timestamp, $hook, $args = array(), $wp_error = \false) + { + } + /** + * Unschedules all events attached to the hook with the specified arguments. + * + * Warning: This function may return Boolean FALSE, but may also return a non-Boolean + * value which evaluates to FALSE. For information about casting to booleans see the + * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}. Use + * the `===` operator for testing the return value of this function. + * + * @since 2.1.0 + * @since 5.1.0 Return value modified to indicate success or failure, + * {@see 'pre_clear_scheduled_hook'} filter added to short-circuit the function. + * @since 5.7.0 The `$wp_error` parameter was added. + * + * @param string $hook Action hook, the execution of which will be unscheduled. + * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. + * Although not passed to a callback, these arguments are used to uniquely identify the + * event, so they should be the same as those used when originally scheduling the event. + * Default empty array. + * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. + * @return int|false|WP_Error On success an integer indicating number of events unscheduled (0 indicates no + * events were registered with the hook and arguments combination), false or WP_Error + * if unscheduling one or more events fail. + * @phpstan-param list<mixed> $args + * @phpstan-return int|false|WP_Error + */ + function wp_clear_scheduled_hook($hook, $args = array(), $wp_error = \false) + { + } + /** + * Unschedules all events attached to the hook. + * + * Can be useful for plugins when deactivating to clean up the cron queue. + * + * Warning: This function may return Boolean FALSE, but may also return a non-Boolean + * value which evaluates to FALSE. For information about casting to booleans see the + * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}. Use + * the `===` operator for testing the return value of this function. + * + * @since 4.9.0 + * @since 5.1.0 Return value added to indicate success or failure. + * @since 5.7.0 The `$wp_error` parameter was added. + * + * @param string $hook Action hook, the execution of which will be unscheduled. + * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. + * @return int|false|WP_Error On success an integer indicating number of events unscheduled (0 indicates no + * events were registered on the hook), false or WP_Error if unscheduling fails. + */ + function wp_unschedule_hook($hook, $wp_error = \false) + { + } + /** + * Retrieve a scheduled event. + * + * Retrieve the full event object for a given event, if no timestamp is specified the next + * scheduled event is returned. + * + * @since 5.1.0 + * + * @param string $hook Action hook of the event. + * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. + * Although not passed to a callback, these arguments are used to uniquely identify the + * event, so they should be the same as those used when originally scheduling the event. + * Default empty array. + * @param int|null $timestamp Optional. Unix timestamp (UTC) of the event. If not specified, the next scheduled event + * is returned. Default null. + * @return object|false The event object. False if the event does not exist. + * @phpstan-param list<mixed> $args + * @phpstan-return object|false + */ + function wp_get_scheduled_event($hook, $args = array(), $timestamp = \null) + { + } + /** + * Retrieve the next timestamp for an event. + * + * @since 2.1.0 + * + * @param string $hook Action hook of the event. + * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. + * Although not passed to a callback, these arguments are used to uniquely identify the + * event, so they should be the same as those used when originally scheduling the event. + * Default empty array. + * @return int|false The Unix timestamp of the next time the event will occur. False if the event doesn't exist. + * @phpstan-param list<mixed> $args + * @phpstan-return int|false + */ + function wp_next_scheduled($hook, $args = array()) + { + } + /** + * Sends a request to run cron through HTTP request that doesn't halt page loading. + * + * @since 2.1.0 + * @since 5.1.0 Return values added. + * + * @param int $gmt_time Optional. Unix timestamp (UTC). Default 0 (current time is used). + * @return bool True if spawned, false if no events spawned. + */ + function spawn_cron($gmt_time = 0) + { + } + /** + * Register _wp_cron() to run on the {@see 'wp_loaded'} action. + * + * If the {@see 'wp_loaded'} action has already fired, this function calls + * _wp_cron() directly. + * + * Warning: This function may return Boolean FALSE, but may also return a non-Boolean + * value which evaluates to FALSE. For information about casting to booleans see the + * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}. Use + * the `===` operator for testing the return value of this function. + * + * @since 2.1.0 + * @since 5.1.0 Return value added to indicate success or failure. + * @since 5.7.0 Functionality moved to _wp_cron() to which this becomes a wrapper. + * + * @return bool|int|void On success an integer indicating number of events spawned (0 indicates no + * events needed to be spawned), false if spawning fails for one or more events or + * void if the function registered _wp_cron() to run on the action. + */ + function wp_cron() + { + } + /** + * Run scheduled callbacks or spawn cron for all scheduled events. + * + * Warning: This function may return Boolean FALSE, but may also return a non-Boolean + * value which evaluates to FALSE. For information about casting to booleans see the + * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}. Use + * the `===` operator for testing the return value of this function. + * + * @since 5.7.0 + * @access private + * + * @return int|false On success an integer indicating number of events spawned (0 indicates no + * events needed to be spawned), false if spawning fails for one or more events. + */ + function _wp_cron() + { + } + /** + * Retrieve supported event recurrence schedules. + * + * The default supported recurrences are 'hourly', 'twicedaily', 'daily', and 'weekly'. + * A plugin may add more by hooking into the {@see 'cron_schedules'} filter. + * The filter accepts an array of arrays. The outer array has a key that is the name + * of the schedule, for example 'monthly'. The value is an array with two keys, + * one is 'interval' and the other is 'display'. + * + * The 'interval' is a number in seconds of when the cron job should run. + * So for 'hourly' the time is `HOUR_IN_SECONDS` (60 * 60 or 3600). For 'monthly', + * the value would be `MONTH_IN_SECONDS` (30 * 24 * 60 * 60 or 2592000). + * + * The 'display' is the description. For the 'monthly' key, the 'display' + * would be `__( 'Once Monthly' )`. + * + * For your plugin, you will be passed an array. You can easily add your + * schedule by doing the following. + * + * // Filter parameter variable name is 'array'. + * $array['monthly'] = array( + * 'interval' => MONTH_IN_SECONDS, + * 'display' => __( 'Once Monthly' ) + * ); + * + * @since 2.1.0 + * @since 5.4.0 The 'weekly' schedule was added. + * + * @return array[] + */ + function wp_get_schedules() + { + } + /** + * Retrieve the recurrence schedule for an event. + * + * @see wp_get_schedules() for available schedules. + * + * @since 2.1.0 + * @since 5.1.0 {@see 'get_schedule'} filter added. + * + * @param string $hook Action hook to identify the event. + * @param array $args Optional. Arguments passed to the event's callback function. + * Default empty array. + * @return string|false Schedule name on success, false if no schedule. + * @phpstan-param list<mixed> $args + * @phpstan-return string|false + */ + function wp_get_schedule($hook, $args = array()) + { + } + /** + * Retrieve cron jobs ready to be run. + * + * Returns the results of _get_cron_array() limited to events ready to be run, + * ie, with a timestamp in the past. + * + * @since 5.1.0 + * + * @return array[] Array of cron job arrays ready to be run. + */ + function wp_get_ready_cron_jobs() + { + } + // + // Private functions. + // + /** + * Retrieve cron info array option. + * + * @since 2.1.0 + * @since 6.1.0 Return type modified to consistently return an array. + * @access private + * + * @return array[] Array of cron events. + */ + function _get_cron_array() + { + } + /** + * Updates the cron option with the new cron array. + * + * @since 2.1.0 + * @since 5.1.0 Return value modified to outcome of update_option(). + * @since 5.7.0 The `$wp_error` parameter was added. + * + * @access private + * + * @param array[] $cron Array of cron info arrays from _get_cron_array(). + * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. + * @return bool|WP_Error True if cron array updated. False or WP_Error on failure. + */ + function _set_cron_array($cron, $wp_error = \false) + { + } + /** + * Upgrade a cron info array. + * + * This function upgrades the cron info array to version 2. + * + * @since 2.1.0 + * @access private + * + * @param array $cron Cron info array from _get_cron_array(). + * @return array An upgraded cron info array. + */ + function _upgrade_cron_array($cron) + { + } + /** + * Defines constants and global variables that can be overridden, generally in wp-config.php. + * + * @package WordPress + */ + /** + * Defines initial WordPress constants. + * + * @see wp_debug_mode() + * + * @since 3.0.0 + * + * @global int $blog_id The current site ID. + * @global string $wp_version The WordPress version string. + */ + function wp_initial_constants() + { + } + /** + * Defines plugin directory WordPress constants. + * + * Defines must-use plugin directory constants, which may be overridden in the sunrise.php drop-in. + * + * @since 3.0.0 + */ + function wp_plugin_directory_constants() + { + } + /** + * Defines cookie-related WordPress constants. + * + * Defines constants after multisite is loaded. + * + * @since 3.0.0 + */ + function wp_cookie_constants() + { + } + /** + * Defines SSL-related WordPress constants. + * + * @since 3.0.0 + */ + function wp_ssl_constants() + { + } + /** + * Defines functionality-related WordPress constants. + * + * @since 3.0.0 + */ + function wp_functionality_constants() + { + } + /** + * Defines templating-related WordPress constants. + * + * @since 3.0.0 + */ + function wp_templating_constants() + { + } + /** + * Deprecated functions from past WordPress versions. You shouldn't use these + * functions and look for the alternatives instead. The functions will be + * removed in a later version. + * + * @package WordPress + * @subpackage Deprecated + */ + /* + * Deprecated functions come here to die. + */ + /** + * Retrieves all post data for a given post. + * + * @since 0.71 + * @deprecated 1.5.1 Use get_post() + * @see get_post() + * + * @param int $postid Post ID. + * @return array Post data. + */ + function get_postdata($postid) + { + } + /** + * Sets up the WordPress Loop. + * + * Use The Loop instead. + * + * @link https://developer.wordpress.org/themes/basics/the-loop/ + * + * @since 1.0.1 + * @deprecated 1.5.0 + */ + function start_wp() + { + } + /** + * Returns or prints a category ID. + * + * @since 0.71 + * @deprecated 0.71 Use get_the_category() + * @see get_the_category() + * + * @param bool $display Optional. Whether to display the output. Default true. + * @return int Category ID. + */ + function the_category_ID($display = \true) + { + } + /** + * Prints a category with optional text before and after. + * + * @since 0.71 + * @deprecated 0.71 Use get_the_category_by_ID() + * @see get_the_category_by_ID() + * + * @param string $before Optional. Text to display before the category. Default empty. + * @param string $after Optional. Text to display after the category. Default empty. + */ + function the_category_head($before = '', $after = '') + { + } + /** + * Prints a link to the previous post. + * + * @since 1.5.0 + * @deprecated 2.0.0 Use previous_post_link() + * @see previous_post_link() + * + * @param string $format + * @param string $previous + * @param string $title + * @param string $in_same_cat + * @param int $limitprev + * @param string $excluded_categories + */ + function previous_post($format = '%', $previous = 'previous post: ', $title = 'yes', $in_same_cat = 'no', $limitprev = 1, $excluded_categories = '') + { + } + /** + * Prints link to the next post. + * + * @since 0.71 + * @deprecated 2.0.0 Use next_post_link() + * @see next_post_link() + * + * @param string $format + * @param string $next + * @param string $title + * @param string $in_same_cat + * @param int $limitnext + * @param string $excluded_categories + */ + function next_post($format = '%', $next = 'next post: ', $title = 'yes', $in_same_cat = 'no', $limitnext = 1, $excluded_categories = '') + { + } + /** + * Whether user can create a post. + * + * @since 1.5.0 + * @deprecated 2.0.0 Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $blog_id Not Used + * @param int $category_id Not Used + * @return bool + */ + function user_can_create_post($user_id, $blog_id = 1, $category_id = 'None') + { + } + /** + * Whether user can create a post. + * + * @since 1.5.0 + * @deprecated 2.0.0 Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $blog_id Not Used + * @param int $category_id Not Used + * @return bool + */ + function user_can_create_draft($user_id, $blog_id = 1, $category_id = 'None') + { + } + /** + * Whether user can edit a post. + * + * @since 1.5.0 + * @deprecated 2.0.0 Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $post_id + * @param int $blog_id Not Used + * @return bool + */ + function user_can_edit_post($user_id, $post_id, $blog_id = 1) + { + } + /** + * Whether user can delete a post. + * + * @since 1.5.0 + * @deprecated 2.0.0 Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $post_id + * @param int $blog_id Not Used + * @return bool + */ + function user_can_delete_post($user_id, $post_id, $blog_id = 1) + { + } + /** + * Whether user can set new posts' dates. + * + * @since 1.5.0 + * @deprecated 2.0.0 Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $blog_id Not Used + * @param int $category_id Not Used + * @return bool + */ + function user_can_set_post_date($user_id, $blog_id = 1, $category_id = 'None') + { + } + /** + * Whether user can delete a post. + * + * @since 1.5.0 + * @deprecated 2.0.0 Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $post_id + * @param int $blog_id Not Used + * @return bool returns true if $user_id can edit $post_id's date + */ + function user_can_edit_post_date($user_id, $post_id, $blog_id = 1) + { + } + /** + * Whether user can delete a post. + * + * @since 1.5.0 + * @deprecated 2.0.0 Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $post_id + * @param int $blog_id Not Used + * @return bool returns true if $user_id can edit $post_id's comments + */ + function user_can_edit_post_comments($user_id, $post_id, $blog_id = 1) + { + } + /** + * Whether user can delete a post. + * + * @since 1.5.0 + * @deprecated 2.0.0 Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $post_id + * @param int $blog_id Not Used + * @return bool returns true if $user_id can delete $post_id's comments + */ + function user_can_delete_post_comments($user_id, $post_id, $blog_id = 1) + { + } + /** + * Can user can edit other user. + * + * @since 1.5.0 + * @deprecated 2.0.0 Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $other_user + * @return bool + */ + function user_can_edit_user($user_id, $other_user) + { + } + /** + * Gets the links associated with category $cat_name. + * + * @since 0.71 + * @deprecated 2.1.0 Use get_bookmarks() + * @see get_bookmarks() + * + * @param string $cat_name Optional. The category name to use. If no match is found, uses all. + * Default 'noname'. + * @param string $before Optional. The HTML to output before the link. Default empty. + * @param string $after Optional. The HTML to output after the link. Default '<br />'. + * @param string $between Optional. The HTML to output between the link/image and its description. + * Not used if no image or $show_images is true. Default ' '. + * @param bool $show_images Optional. Whether to show images (if defined). Default true. + * @param string $orderby Optional. The order to output the links. E.g. 'id', 'name', 'url', + * 'description', 'rating', or 'owner'. Default 'id'. + * If you start the name with an underscore, the order will be reversed. + * Specifying 'rand' as the order will return links in a random order. + * @param bool $show_description Optional. Whether to show the description if show_images=false/not defined. + * Default true. + * @param bool $show_rating Optional. Show rating stars/chars. Default false. + * @param int $limit Optional. Limit to X entries. If not specified, all entries are shown. + * Default -1. + * @param int $show_updated Optional. Whether to show last updated timestamp. Default 0. + */ + function get_linksbyname($cat_name = "noname", $before = '', $after = '<br />', $between = " ", $show_images = \true, $orderby = 'id', $show_description = \true, $show_rating = \false, $limit = -1, $show_updated = 0) + { + } + /** + * Gets the links associated with the named category. + * + * @since 1.0.1 + * @deprecated 2.1.0 Use wp_list_bookmarks() + * @see wp_list_bookmarks() + * + * @param string $category The category to use. + * @param string $args + * @return string|null + */ + function wp_get_linksbyname($category, $args = '') + { + } + /** + * Gets an array of link objects associated with category $cat_name. + * + * $links = get_linkobjectsbyname( 'fred' ); + * foreach ( $links as $link ) { + * echo '<li>' . $link->link_name . '</li>'; + * } + * + * @since 1.0.1 + * @deprecated 2.1.0 Use get_bookmarks() + * @see get_bookmarks() + * + * @param string $cat_name Optional. The category name to use. If no match is found, uses all. + * Default 'noname'. + * @param string $orderby Optional. The order to output the links. E.g. 'id', 'name', 'url', + * 'description', 'rating', or 'owner'. Default 'name'. + * If you start the name with an underscore, the order will be reversed. + * Specifying 'rand' as the order will return links in a random order. + * @param int $limit Optional. Limit to X entries. If not specified, all entries are shown. + * Default -1. + * @return array + */ + function get_linkobjectsbyname($cat_name = "noname", $orderby = 'name', $limit = -1) + { + } + /** + * Gets an array of link objects associated with category n. + * + * Usage: + * + * $links = get_linkobjects(1); + * if ($links) { + * foreach ($links as $link) { + * echo '<li>'.$link->link_name.'<br />'.$link->link_description.'</li>'; + * } + * } + * + * Fields are: + * + * - link_id + * - link_url + * - link_name + * - link_image + * - link_target + * - link_category + * - link_description + * - link_visible + * - link_owner + * - link_rating + * - link_updated + * - link_rel + * - link_notes + * + * @since 1.0.1 + * @deprecated 2.1.0 Use get_bookmarks() + * @see get_bookmarks() + * + * @param int $category Optional. The category to use. If no category supplied, uses all. + * Default 0. + * @param string $orderby Optional. The order to output the links. E.g. 'id', 'name', 'url', + * 'description', 'rating', or 'owner'. Default 'name'. + * If you start the name with an underscore, the order will be reversed. + * Specifying 'rand' as the order will return links in a random order. + * @param int $limit Optional. Limit to X entries. If not specified, all entries are shown. + * Default 0. + * @return array + */ + function get_linkobjects($category = 0, $orderby = 'name', $limit = 0) + { + } + /** + * Gets the links associated with category 'cat_name' and display rating stars/chars. + * + * @since 0.71 + * @deprecated 2.1.0 Use get_bookmarks() + * @see get_bookmarks() + * + * @param string $cat_name Optional. The category name to use. If no match is found, uses all. + * Default 'noname'. + * @param string $before Optional. The HTML to output before the link. Default empty. + * @param string $after Optional. The HTML to output after the link. Default '<br />'. + * @param string $between Optional. The HTML to output between the link/image and its description. + * Not used if no image or $show_images is true. Default ' '. + * @param bool $show_images Optional. Whether to show images (if defined). Default true. + * @param string $orderby Optional. The order to output the links. E.g. 'id', 'name', 'url', + * 'description', 'rating', or 'owner'. Default 'id'. + * If you start the name with an underscore, the order will be reversed. + * Specifying 'rand' as the order will return links in a random order. + * @param bool $show_description Optional. Whether to show the description if show_images=false/not defined. + * Default true. + * @param int $limit Optional. Limit to X entries. If not specified, all entries are shown. + * Default -1. + * @param int $show_updated Optional. Whether to show last updated timestamp. Default 0. + */ + function get_linksbyname_withrating($cat_name = "noname", $before = '', $after = '<br />', $between = " ", $show_images = \true, $orderby = 'id', $show_description = \true, $limit = -1, $show_updated = 0) + { + } + /** + * Gets the links associated with category n and display rating stars/chars. + * + * @since 0.71 + * @deprecated 2.1.0 Use get_bookmarks() + * @see get_bookmarks() + * + * @param int $category Optional. The category to use. If no category supplied, uses all. + * Default 0. + * @param string $before Optional. The HTML to output before the link. Default empty. + * @param string $after Optional. The HTML to output after the link. Default '<br />'. + * @param string $between Optional. The HTML to output between the link/image and its description. + * Not used if no image or $show_images is true. Default ' '. + * @param bool $show_images Optional. Whether to show images (if defined). Default true. + * @param string $orderby Optional. The order to output the links. E.g. 'id', 'name', 'url', + * 'description', 'rating', or 'owner'. Default 'id'. + * If you start the name with an underscore, the order will be reversed. + * Specifying 'rand' as the order will return links in a random order. + * @param bool $show_description Optional. Whether to show the description if show_images=false/not defined. + * Default true. + * @param int $limit Optional. Limit to X entries. If not specified, all entries are shown. + * Default -1. + * @param int $show_updated Optional. Whether to show last updated timestamp. Default 0. + */ + function get_links_withrating($category = -1, $before = '', $after = '<br />', $between = " ", $show_images = \true, $orderby = 'id', $show_description = \true, $limit = -1, $show_updated = 0) + { + } + /** + * Gets the auto_toggle setting. + * + * @since 0.71 + * @deprecated 2.1.0 + * + * @param int $id The category to get. If no category supplied uses 0 + * @return int Only returns 0. + */ + function get_autotoggle($id = 0) + { + } + /** + * Lists categories. + * + * @since 0.71 + * @deprecated 2.1.0 Use wp_list_categories() + * @see wp_list_categories() + * + * @param int $optionall + * @param string $all + * @param string $sort_column + * @param string $sort_order + * @param string $file + * @param bool $list + * @param int $optiondates + * @param int $optioncount + * @param int $hide_empty + * @param int $use_desc_for_title + * @param bool $children + * @param int $child_of + * @param int $categories + * @param int $recurse + * @param string $feed + * @param string $feed_image + * @param string $exclude + * @param bool $hierarchical + * @return null|false + */ + function list_cats($optionall = 1, $all = 'All', $sort_column = 'ID', $sort_order = 'asc', $file = '', $list = \true, $optiondates = 0, $optioncount = 0, $hide_empty = 1, $use_desc_for_title = 1, $children = \false, $child_of = 0, $categories = 0, $recurse = 0, $feed = '', $feed_image = '', $exclude = '', $hierarchical = \false) + { + } + /** + * Lists categories. + * + * @since 1.2.0 + * @deprecated 2.1.0 Use wp_list_categories() + * @see wp_list_categories() + * + * @param string|array $args + * @return null|string|false + */ + function wp_list_cats($args = '') + { + } + /** + * Deprecated method for generating a drop-down of categories. + * + * @since 0.71 + * @deprecated 2.1.0 Use wp_dropdown_categories() + * @see wp_dropdown_categories() + * + * @param int $optionall + * @param string $all + * @param string $orderby + * @param string $order + * @param int $show_last_update + * @param int $show_count + * @param int $hide_empty + * @param bool $optionnone + * @param int $selected + * @param int $exclude + * @return string + */ + function dropdown_cats($optionall = 1, $all = 'All', $orderby = 'ID', $order = 'asc', $show_last_update = 0, $show_count = 0, $hide_empty = 1, $optionnone = \false, $selected = 0, $exclude = 0) + { + } + /** + * Lists authors. + * + * @since 1.2.0 + * @deprecated 2.1.0 Use wp_list_authors() + * @see wp_list_authors() + * + * @param bool $optioncount + * @param bool $exclude_admin + * @param bool $show_fullname + * @param bool $hide_empty + * @param string $feed + * @param string $feed_image + * @return null|string + */ + function list_authors($optioncount = \false, $exclude_admin = \true, $show_fullname = \false, $hide_empty = \true, $feed = '', $feed_image = '') + { + } + /** + * Retrieves a list of post categories. + * + * @since 1.0.1 + * @deprecated 2.1.0 Use wp_get_post_categories() + * @see wp_get_post_categories() + * + * @param int $blogid Not Used + * @param int $post_ID + * @return array + */ + function wp_get_post_cats($blogid = '1', $post_ID = 0) + { + } + /** + * Sets the categories that the post ID belongs to. + * + * @since 1.0.1 + * @deprecated 2.1.0 + * @deprecated Use wp_set_post_categories() + * @see wp_set_post_categories() + * + * @param int $blogid Not used + * @param int $post_ID + * @param array $post_categories + * @return bool|mixed + */ + function wp_set_post_cats($blogid = '1', $post_ID = 0, $post_categories = array()) + { + } + /** + * Retrieves a list of archives. + * + * @since 0.71 + * @deprecated 2.1.0 Use wp_get_archives() + * @see wp_get_archives() + * + * @param string $type + * @param string $limit + * @param string $format + * @param string $before + * @param string $after + * @param bool $show_post_count + * @return string|null + */ + function get_archives($type = '', $limit = '', $format = 'html', $before = '', $after = '', $show_post_count = \false) + { + } + /** + * Returns or Prints link to the author's posts. + * + * @since 1.2.0 + * @deprecated 2.1.0 Use get_author_posts_url() + * @see get_author_posts_url() + * + * @param bool $display + * @param int $author_id + * @param string $author_nicename Optional. + * @return string|null + */ + function get_author_link($display, $author_id, $author_nicename = '') + { + } + /** + * Print list of pages based on arguments. + * + * @since 0.71 + * @deprecated 2.1.0 Use wp_link_pages() + * @see wp_link_pages() + * + * @param string $before + * @param string $after + * @param string $next_or_number + * @param string $nextpagelink + * @param string $previouspagelink + * @param string $pagelink + * @param string $more_file + * @return string + */ + function link_pages($before = '<br />', $after = '<br />', $next_or_number = 'number', $nextpagelink = 'next page', $previouspagelink = 'previous page', $pagelink = '%', $more_file = '') + { + } + /** + * Get value based on option. + * + * @since 0.71 + * @deprecated 2.1.0 Use get_option() + * @see get_option() + * + * @param string $option + * @return string + */ + function get_settings($option) + { + } + /** + * Print the permalink of the current post in the loop. + * + * @since 0.71 + * @deprecated 1.2.0 Use the_permalink() + * @see the_permalink() + */ + function permalink_link() + { + } + /** + * Print the permalink to the RSS feed. + * + * @since 0.71 + * @deprecated 2.3.0 Use the_permalink_rss() + * @see the_permalink_rss() + * + * @param string $deprecated + */ + function permalink_single_rss($deprecated = '') + { + } + /** + * Gets the links associated with category. + * + * @since 1.0.1 + * @deprecated 2.1.0 Use wp_list_bookmarks() + * @see wp_list_bookmarks() + * + * @param string $args a query string + * @return null|string + */ + function wp_get_links($args = '') + { + } + /** + * Gets the links associated with category by ID. + * + * @since 0.71 + * @deprecated 2.1.0 Use get_bookmarks() + * @see get_bookmarks() + * + * @param int $category Optional. The category to use. If no category supplied uses all. + * Default 0. + * @param string $before Optional. The HTML to output before the link. Default empty. + * @param string $after Optional. The HTML to output after the link. Default '<br />'. + * @param string $between Optional. The HTML to output between the link/image and its description. + * Not used if no image or $show_images is true. Default ' '. + * @param bool $show_images Optional. Whether to show images (if defined). Default true. + * @param string $orderby Optional. The order to output the links. E.g. 'id', 'name', 'url', + * 'description', 'rating', or 'owner'. Default 'name'. + * If you start the name with an underscore, the order will be reversed. + * Specifying 'rand' as the order will return links in a random order. + * @param bool $show_description Optional. Whether to show the description if show_images=false/not defined. + * Default true. + * @param bool $show_rating Optional. Show rating stars/chars. Default false. + * @param int $limit Optional. Limit to X entries. If not specified, all entries are shown. + * Default -1. + * @param int $show_updated Optional. Whether to show last updated timestamp. Default 1. + * @param bool $display Whether to display the results, or return them instead. + * @return null|string + */ + function get_links($category = -1, $before = '', $after = '<br />', $between = ' ', $show_images = \true, $orderby = 'name', $show_description = \true, $show_rating = \false, $limit = -1, $show_updated = 1, $display = \true) + { + } + /** + * Output entire list of links by category. + * + * Output a list of all links, listed by category, using the settings in + * $wpdb->linkcategories and output it as a nested HTML unordered list. + * + * @since 1.0.1 + * @deprecated 2.1.0 Use wp_list_bookmarks() + * @see wp_list_bookmarks() + * + * @param string $order Sort link categories by 'name' or 'id' + */ + function get_links_list($order = 'name') + { + } + /** + * Show the link to the links popup and the number of links. + * + * @since 0.71 + * @deprecated 2.1.0 + * + * @param string $text the text of the link + * @param int $width the width of the popup window + * @param int $height the height of the popup window + * @param string $file the page to open in the popup window + * @param bool $count the number of links in the db + */ + function links_popup_script($text = 'Links', $width = 400, $height = 400, $file = 'links.all.php', $count = \true) + { + } + /** + * Legacy function that retrieved the value of a link's link_rating field. + * + * @since 1.0.1 + * @deprecated 2.1.0 Use sanitize_bookmark_field() + * @see sanitize_bookmark_field() + * + * @param object $link Link object. + * @return mixed Value of the 'link_rating' field, false otherwise. + */ + function get_linkrating($link) + { + } + /** + * Gets the name of category by ID. + * + * @since 0.71 + * @deprecated 2.1.0 Use get_category() + * @see get_category() + * + * @param int $id The category to get. If no category supplied uses 0 + * @return string + */ + function get_linkcatname($id = 0) + { + } + /** + * Print RSS comment feed link. + * + * @since 1.0.1 + * @deprecated 2.5.0 Use post_comments_feed_link() + * @see post_comments_feed_link() + * + * @param string $link_text + */ + function comments_rss_link($link_text = 'Comments RSS') + { + } + /** + * Print/Return link to category RSS2 feed. + * + * @since 1.2.0 + * @deprecated 2.5.0 Use get_category_feed_link() + * @see get_category_feed_link() + * + * @param bool $display + * @param int $cat_ID + * @return string + */ + function get_category_rss_link($display = \false, $cat_ID = 1) + { + } + /** + * Print/Return link to author RSS feed. + * + * @since 1.2.0 + * @deprecated 2.5.0 Use get_author_feed_link() + * @see get_author_feed_link() + * + * @param bool $display + * @param int $author_id + * @return string + */ + function get_author_rss_link($display = \false, $author_id = 1) + { + } + /** + * Return link to the post RSS feed. + * + * @since 1.5.0 + * @deprecated 2.2.0 Use get_post_comments_feed_link() + * @see get_post_comments_feed_link() + * + * @return string + */ + function comments_rss() + { + } + /** + * An alias of wp_create_user(). + * + * @since 2.0.0 + * @deprecated 2.0.0 Use wp_create_user() + * @see wp_create_user() + * + * @param string $username The user's username. + * @param string $password The user's password. + * @param string $email The user's email. + * @return int The new user's ID. + */ + function create_user($username, $password, $email) + { + } + /** + * Unused function. + * + * @deprecated 2.5.0 + */ + function gzip_compression() + { + } + /** + * Retrieve an array of comment data about comment $comment_ID. + * + * @since 0.71 + * @deprecated 2.7.0 Use get_comment() + * @see get_comment() + * + * @param int $comment_ID The ID of the comment + * @param int $no_cache Whether to use the cache (cast to bool) + * @param bool $include_unapproved Whether to include unapproved comments + * @return array The comment data + */ + function get_commentdata($comment_ID, $no_cache = 0, $include_unapproved = \false) + { + } + /** + * Retrieve the category name by the category ID. + * + * @since 0.71 + * @deprecated 2.8.0 Use get_cat_name() + * @see get_cat_name() + * + * @param int $cat_ID Category ID + * @return string category name + */ + function get_catname($cat_ID) + { + } + /** + * Retrieve category children list separated before and after the term IDs. + * + * @since 1.2.0 + * @deprecated 2.8.0 Use get_term_children() + * @see get_term_children() + * + * @param int $id Category ID to retrieve children. + * @param string $before Optional. Prepend before category term ID. Default '/'. + * @param string $after Optional. Append after category term ID. Default empty string. + * @param array $visited Optional. Category Term IDs that have already been added. + * Default empty array. + * @return string + */ + function get_category_children($id, $before = '/', $after = '', $visited = array()) + { + } + /** + * Retrieves all category IDs. + * + * @since 2.0.0 + * @deprecated 4.0.0 Use get_terms() + * @see get_terms() + * + * @link https://developer.wordpress.org/reference/functions/get_all_category_ids/ + * + * @return int[] List of all of the category IDs. + */ + function get_all_category_ids() + { + } + /** + * Retrieve the description of the author of the current post. + * + * @since 1.5.0 + * @deprecated 2.8.0 Use get_the_author_meta() + * @see get_the_author_meta() + * + * @return string The author's description. + */ + function get_the_author_description() + { + } + /** + * Display the description of the author of the current post. + * + * @since 1.0.0 + * @deprecated 2.8.0 Use the_author_meta() + * @see the_author_meta() + */ + function the_author_description() + { + } + /** + * Retrieve the login name of the author of the current post. + * + * @since 1.5.0 + * @deprecated 2.8.0 Use get_the_author_meta() + * @see get_the_author_meta() + * + * @return string The author's login name (username). + */ + function get_the_author_login() + { + } + /** + * Display the login name of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8.0 Use the_author_meta() + * @see the_author_meta() + */ + function the_author_login() + { + } + /** + * Retrieve the first name of the author of the current post. + * + * @since 1.5.0 + * @deprecated 2.8.0 Use get_the_author_meta() + * @see get_the_author_meta() + * + * @return string The author's first name. + */ + function get_the_author_firstname() + { + } + /** + * Display the first name of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8.0 Use the_author_meta() + * @see the_author_meta() + */ + function the_author_firstname() + { + } + /** + * Retrieve the last name of the author of the current post. + * + * @since 1.5.0 + * @deprecated 2.8.0 Use get_the_author_meta() + * @see get_the_author_meta() + * + * @return string The author's last name. + */ + function get_the_author_lastname() + { + } + /** + * Display the last name of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8.0 Use the_author_meta() + * @see the_author_meta() + */ + function the_author_lastname() + { + } + /** + * Retrieve the nickname of the author of the current post. + * + * @since 1.5.0 + * @deprecated 2.8.0 Use get_the_author_meta() + * @see get_the_author_meta() + * + * @return string The author's nickname. + */ + function get_the_author_nickname() + { + } + /** + * Display the nickname of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8.0 Use the_author_meta() + * @see the_author_meta() + */ + function the_author_nickname() + { + } + /** + * Retrieve the email of the author of the current post. + * + * @since 1.5.0 + * @deprecated 2.8.0 Use get_the_author_meta() + * @see get_the_author_meta() + * + * @return string The author's username. + */ + function get_the_author_email() + { + } + /** + * Display the email of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8.0 Use the_author_meta() + * @see the_author_meta() + */ + function the_author_email() + { + } + /** + * Retrieve the ICQ number of the author of the current post. + * + * @since 1.5.0 + * @deprecated 2.8.0 Use get_the_author_meta() + * @see get_the_author_meta() + * + * @return string The author's ICQ number. + */ + function get_the_author_icq() + { + } + /** + * Display the ICQ number of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8.0 Use the_author_meta() + * @see the_author_meta() + */ + function the_author_icq() + { + } + /** + * Retrieve the Yahoo! IM name of the author of the current post. + * + * @since 1.5.0 + * @deprecated 2.8.0 Use get_the_author_meta() + * @see get_the_author_meta() + * + * @return string The author's Yahoo! IM name. + */ + function get_the_author_yim() + { + } + /** + * Display the Yahoo! IM name of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8.0 Use the_author_meta() + * @see the_author_meta() + */ + function the_author_yim() + { + } + /** + * Retrieve the MSN address of the author of the current post. + * + * @since 1.5.0 + * @deprecated 2.8.0 Use get_the_author_meta() + * @see get_the_author_meta() + * + * @return string The author's MSN address. + */ + function get_the_author_msn() + { + } + /** + * Display the MSN address of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8.0 Use the_author_meta() + * @see the_author_meta() + */ + function the_author_msn() + { + } + /** + * Retrieve the AIM address of the author of the current post. + * + * @since 1.5.0 + * @deprecated 2.8.0 Use get_the_author_meta() + * @see get_the_author_meta() + * + * @return string The author's AIM address. + */ + function get_the_author_aim() + { + } + /** + * Display the AIM address of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8.0 Use the_author_meta('aim') + * @see the_author_meta() + */ + function the_author_aim() + { + } + /** + * Retrieve the specified author's preferred display name. + * + * @since 1.0.0 + * @deprecated 2.8.0 Use get_the_author_meta() + * @see get_the_author_meta() + * + * @param int $auth_id The ID of the author. + * @return string The author's display name. + */ + function get_author_name($auth_id = \false) + { + } + /** + * Retrieve the URL to the home page of the author of the current post. + * + * @since 1.5.0 + * @deprecated 2.8.0 Use get_the_author_meta() + * @see get_the_author_meta() + * + * @return string The URL to the author's page. + */ + function get_the_author_url() + { + } + /** + * Display the URL to the home page of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8.0 Use the_author_meta() + * @see the_author_meta() + */ + function the_author_url() + { + } + /** + * Retrieve the ID of the author of the current post. + * + * @since 1.5.0 + * @deprecated 2.8.0 Use get_the_author_meta() + * @see get_the_author_meta() + * + * @return string|int The author's ID. + */ + function get_the_author_ID() + { + } + /** + * Display the ID of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8.0 Use the_author_meta() + * @see the_author_meta() + */ + function the_author_ID() + { + } + /** + * Display the post content for the feed. + * + * For encoding the HTML or the $encode_html parameter, there are three possible values: + * - '0' will make urls footnotes and use make_url_footnote(). + * - '1' will encode special characters and automatically display all of the content. + * - '2' will strip all HTML tags from the content. + * + * Also note that you cannot set the amount of words and not set the HTML encoding. + * If that is the case, then the HTML encoding will default to 2, which will strip + * all HTML tags. + * + * To restrict the amount of words of the content, you can use the cut parameter. + * If the content is less than the amount, then there won't be any dots added to the end. + * If there is content left over, then dots will be added and the rest of the content + * will be removed. + * + * @since 0.71 + * + * @deprecated 2.9.0 Use the_content_feed() + * @see the_content_feed() + * + * @param string $more_link_text Optional. Text to display when more content is available + * but not displayed. Default '(more...)'. + * @param int $stripteaser Optional. Default 0. + * @param string $more_file Optional. + * @param int $cut Optional. Amount of words to keep for the content. + * @param int $encode_html Optional. How to encode the content. + */ + function the_content_rss($more_link_text = '(more...)', $stripteaser = 0, $more_file = '', $cut = 0, $encode_html = 0) + { + } + /** + * Strip HTML and put links at the bottom of stripped content. + * + * Searches for all of the links, strips them out of the content, and places + * them at the bottom of the content with numbers. + * + * @since 0.71 + * @deprecated 2.9.0 + * + * @param string $content Content to get links. + * @return string HTML stripped out of content with links at the bottom. + */ + function make_url_footnote($content) + { + } + /** + * Retrieve translated string with vertical bar context + * + * Quite a few times, there will be collisions with similar translatable text + * found in more than two places but with different translated context. + * + * In order to use the separate contexts, the _c() function is used and the + * translatable string uses a pipe ('|') which has the context the string is in. + * + * When the translated string is returned, it is everything before the pipe, not + * including the pipe character. If there is no pipe in the translated text then + * everything is returned. + * + * @since 2.2.0 + * @deprecated 2.9.0 Use _x() + * @see _x() + * + * @param string $text Text to translate. + * @param string $domain Optional. Domain to retrieve the translated text. + * @return string Translated context string without pipe. + */ + function _c($text, $domain = 'default') + { + } + /** + * Translates $text like translate(), but assumes that the text + * contains a context after its last vertical bar. + * + * @since 2.5.0 + * @deprecated 3.0.0 Use _x() + * @see _x() + * + * @param string $text Text to translate. + * @param string $domain Domain to retrieve the translated text. + * @return string Translated text. + */ + function translate_with_context($text, $domain = 'default') + { + } + /** + * Legacy version of _n(), which supports contexts. + * + * Strips everything from the translation after the last bar. + * + * @since 2.7.0 + * @deprecated 3.0.0 Use _nx() + * @see _nx() + * + * @param string $single The text to be used if the number is singular. + * @param string $plural The text to be used if the number is plural. + * @param int $number The number to compare against to use either the singular or plural form. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + * @return string The translated singular or plural form. + */ + function _nc($single, $plural, $number, $domain = 'default') + { + } + /** + * Retrieve the plural or single form based on the amount. + * + * @since 1.2.0 + * @deprecated 2.8.0 Use _n() + * @see _n() + */ + function __ngettext(...$args) + { + } + /** + * Register plural strings in POT file, but don't translate them. + * + * @since 2.5.0 + * @deprecated 2.8.0 Use _n_noop() + * @see _n_noop() + */ + function __ngettext_noop(...$args) + { + } + /** + * Retrieve all autoload options, or all options if no autoloaded ones exist. + * + * @since 1.0.0 + * @deprecated 3.0.0 Use wp_load_alloptions()) + * @see wp_load_alloptions() + * + * @return array List of all options. + */ + function get_alloptions() + { + } + /** + * Retrieve HTML content of attachment image with link. + * + * @since 2.0.0 + * @deprecated 2.5.0 Use wp_get_attachment_link() + * @see wp_get_attachment_link() + * + * @param int $id Optional. Post ID. + * @param bool $fullsize Optional. Whether to use full size image. Default false. + * @param array $max_dims Optional. Max image dimensions. + * @param bool $permalink Optional. Whether to include permalink to image. Default false. + * @return string + */ + function get_the_attachment_link($id = 0, $fullsize = \false, $max_dims = \false, $permalink = \false) + { + } + /** + * Retrieve icon URL and Path. + * + * @since 2.1.0 + * @deprecated 2.5.0 Use wp_get_attachment_image_src() + * @see wp_get_attachment_image_src() + * + * @param int $id Optional. Post ID. + * @param bool $fullsize Optional. Whether to have full image. Default false. + * @return array Icon URL and full path to file, respectively. + */ + function get_attachment_icon_src($id = 0, $fullsize = \false) + { + } + /** + * Retrieve HTML content of icon attachment image element. + * + * @since 2.0.0 + * @deprecated 2.5.0 Use wp_get_attachment_image() + * @see wp_get_attachment_image() + * + * @param int $id Optional. Post ID. + * @param bool $fullsize Optional. Whether to have full size image. Default false. + * @param array $max_dims Optional. Dimensions of image. + * @return string|false HTML content. + */ + function get_attachment_icon($id = 0, $fullsize = \false, $max_dims = \false) + { + } + /** + * Retrieve HTML content of image element. + * + * @since 2.0.0 + * @deprecated 2.5.0 Use wp_get_attachment_image() + * @see wp_get_attachment_image() + * + * @param int $id Optional. Post ID. + * @param bool $fullsize Optional. Whether to have full size image. Default false. + * @param array $max_dims Optional. Dimensions of image. + * @return string|false + */ + function get_attachment_innerHTML($id = 0, $fullsize = \false, $max_dims = \false) + { + } + /** + * Retrieves bookmark data based on ID. + * + * @since 2.0.0 + * @deprecated 2.1.0 Use get_bookmark() + * @see get_bookmark() + * + * @param int $bookmark_id ID of link + * @param string $output Optional. Type of output. Accepts OBJECT, ARRAY_N, or ARRAY_A. + * Default OBJECT. + * @param string $filter Optional. How to filter the link for output. Accepts 'raw', 'edit', + * 'attribute', 'js', 'db', or 'display'. Default 'raw'. + * @return object|array Bookmark object or array, depending on the type specified by `$output`. + */ + function get_link($bookmark_id, $output = \OBJECT, $filter = 'raw') + { + } + /** + * Checks and cleans a URL. + * + * A number of characters are removed from the URL. If the URL is for displaying + * (the default behaviour) ampersands are also replaced. The 'clean_url' filter + * is applied to the returned cleaned URL. + * + * @since 1.2.0 + * @deprecated 3.0.0 Use esc_url() + * @see esc_url() + * + * @param string $url The URL to be cleaned. + * @param array $protocols Optional. An array of acceptable protocols. + * @param string $context Optional. How the URL will be used. Default is 'display'. + * @return string The cleaned $url after the {@see 'clean_url'} filter is applied. + */ + function clean_url($url, $protocols = \null, $context = 'display') + { + } + /** + * Escape single quotes, specialchar double quotes, and fix line endings. + * + * The filter {@see 'js_escape'} is also applied by esc_js(). + * + * @since 2.0.4 + * @deprecated 2.8.0 Use esc_js() + * @see esc_js() + * + * @param string $text The text to be escaped. + * @return string Escaped text. + */ + function js_escape($text) + { + } + /** + * Legacy escaping for HTML blocks. + * + * @deprecated 2.8.0 Use esc_html() + * @see esc_html() + * + * @param string $text Text to escape. + * @param string $quote_style Unused. + * @param false|string $charset Unused. + * @param false $double_encode Whether to double encode. Unused. + * @return string Escaped `$text`. + */ + function wp_specialchars($text, $quote_style = \ENT_NOQUOTES, $charset = \false, $double_encode = \false) + { + } + /** + * Escaping for HTML attributes. + * + * @since 2.0.6 + * @deprecated 2.8.0 Use esc_attr() + * @see esc_attr() + * + * @param string $text + * @return string + */ + function attribute_escape($text) + { + } + /** + * Register widget for sidebar with backward compatibility. + * + * Allows $name to be an array that accepts either three elements to grab the + * first element and the third for the name or just uses the first element of + * the array for the name. + * + * Passes to wp_register_sidebar_widget() after argument list and backward + * compatibility is complete. + * + * @since 2.2.0 + * @deprecated 2.8.0 Use wp_register_sidebar_widget() + * @see wp_register_sidebar_widget() + * + * @param string|int $name Widget ID. + * @param callable $output_callback Run when widget is called. + * @param string $classname Optional. Classname widget option. Default empty. + * @param mixed ...$params Widget parameters. + */ + function register_sidebar_widget($name, $output_callback, $classname = '', ...$params) + { + } + /** + * Serves as an alias of wp_unregister_sidebar_widget(). + * + * @since 2.2.0 + * @deprecated 2.8.0 Use wp_unregister_sidebar_widget() + * @see wp_unregister_sidebar_widget() + * + * @param int|string $id Widget ID. + */ + function unregister_sidebar_widget($id) + { + } + /** + * Registers widget control callback for customizing options. + * + * Allows $name to be an array that accepts either three elements to grab the + * first element and the third for the name or just uses the first element of + * the array for the name. + * + * Passes to wp_register_widget_control() after the argument list has + * been compiled. + * + * @since 2.2.0 + * @deprecated 2.8.0 Use wp_register_widget_control() + * @see wp_register_widget_control() + * + * @param int|string $name Sidebar ID. + * @param callable $control_callback Widget control callback to display and process form. + * @param int $width Widget width. + * @param int $height Widget height. + * @param mixed ...$params Widget parameters. + */ + function register_widget_control($name, $control_callback, $width = '', $height = '', ...$params) + { + } + /** + * Alias of wp_unregister_widget_control(). + * + * @since 2.2.0 + * @deprecated 2.8.0 Use wp_unregister_widget_control() + * @see wp_unregister_widget_control() + * + * @param int|string $id Widget ID. + */ + function unregister_widget_control($id) + { + } + /** + * Remove user meta data. + * + * @since 2.0.0 + * @deprecated 3.0.0 Use delete_user_meta() + * @see delete_user_meta() + * + * @param int $user_id User ID. + * @param string $meta_key Metadata key. + * @param mixed $meta_value Optional. Metadata value. Default empty. + * @return bool True deletion completed and false if user_id is not a number. + */ + function delete_usermeta($user_id, $meta_key, $meta_value = '') + { + } + /** + * Retrieve user metadata. + * + * If $user_id is not a number, then the function will fail over with a 'false' + * boolean return value. Other returned values depend on whether there is only + * one item to be returned, which be that single item type. If there is more + * than one metadata value, then it will be list of metadata values. + * + * @since 2.0.0 + * @deprecated 3.0.0 Use get_user_meta() + * @see get_user_meta() + * + * @param int $user_id User ID + * @param string $meta_key Optional. Metadata key. Default empty. + * @return mixed + */ + function get_usermeta($user_id, $meta_key = '') + { + } + /** + * Update metadata of user. + * + * There is no need to serialize values, they will be serialized if it is + * needed. The metadata key can only be a string with underscores. All else will + * be removed. + * + * Will remove the metadata, if the meta value is empty. + * + * @since 2.0.0 + * @deprecated 3.0.0 Use update_user_meta() + * @see update_user_meta() + * + * @param int $user_id User ID + * @param string $meta_key Metadata key. + * @param mixed $meta_value Metadata value. + * @return bool True on successful update, false on failure. + */ + function update_usermeta($user_id, $meta_key, $meta_value) + { + } + /** + * Get users for the site. + * + * For setups that use the multisite feature. Can be used outside of the + * multisite feature. + * + * @since 2.2.0 + * @deprecated 3.1.0 Use get_users() + * @see get_users() + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $id Site ID. + * @return array List of users that are part of that site ID + */ + function get_users_of_blog($id = '') + { + } + /** + * Enable/disable automatic general feed link outputting. + * + * @since 2.8.0 + * @deprecated 3.0.0 Use add_theme_support() + * @see add_theme_support() + * + * @param bool $add Optional. Add or remove links. Default true. + */ + function automatic_feed_links($add = \true) + { + } + /** + * Retrieve user data based on field. + * + * @since 1.5.0 + * @deprecated 3.0.0 Use get_the_author_meta() + * @see get_the_author_meta() + * + * @param string $field User meta field. + * @param false|int $user Optional. User ID to retrieve the field for. Default false (current user). + * @return string The author's field from the current author's DB object. + */ + function get_profile($field, $user = \false) + { + } + /** + * Retrieves the number of posts a user has written. + * + * @since 0.71 + * @deprecated 3.0.0 Use count_user_posts() + * @see count_user_posts() + * + * @param int $userid User to count posts for. + * @return int Number of posts the given user has written. + */ + function get_usernumposts($userid) + { + } + /** + * Callback used to change %uXXXX to &#YYY; syntax + * + * @since 2.8.0 + * @access private + * @deprecated 3.0.0 + * + * @param array $matches Single Match + * @return string An HTML entity + */ + function funky_javascript_callback($matches) + { + } + /** + * Fixes JavaScript bugs in browsers. + * + * Converts unicode characters to HTML numbered entities. + * + * @since 1.5.0 + * @deprecated 3.0.0 + * + * @global $is_macIE + * @global $is_winIE + * + * @param string $text Text to be made safe. + * @return string Fixed text. + */ + function funky_javascript_fix($text) + { + } + /** + * Checks that the taxonomy name exists. + * + * @since 2.3.0 + * @deprecated 3.0.0 Use taxonomy_exists() + * @see taxonomy_exists() + * + * @param string $taxonomy Name of taxonomy object + * @return bool Whether the taxonomy exists. + */ + function is_taxonomy($taxonomy) + { + } + /** + * Check if Term exists. + * + * @since 2.3.0 + * @deprecated 3.0.0 Use term_exists() + * @see term_exists() + * + * @param int|string $term The term to check + * @param string $taxonomy The taxonomy name to use + * @param int $parent ID of parent term under which to confine the exists search. + * @return mixed Get the term ID or term object, if exists. + */ + function is_term($term, $taxonomy = '', $parent = 0) + { + } + /** + * Determines whether the current admin page is generated by a plugin. + * + * Use global $plugin_page and/or get_plugin_page_hookname() hooks. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * @deprecated 3.1.0 + * + * @global $plugin_page + * + * @return bool + */ + function is_plugin_page() + { + } + /** + * Update the categories cache. + * + * This function does not appear to be used anymore or does not appear to be + * needed. It might be a legacy function left over from when there was a need + * for updating the category cache. + * + * @since 1.5.0 + * @deprecated 3.1.0 + * + * @return bool Always return True + */ + function update_category_cache() + { + } + /** + * Check for PHP timezone support + * + * @since 2.9.0 + * @deprecated 3.2.0 + * + * @return bool + */ + function wp_timezone_supported() + { + } + /** + * Displays an editor: TinyMCE, HTML, or both. + * + * @since 2.1.0 + * @deprecated 3.3.0 Use wp_editor() + * @see wp_editor() + * + * @param string $content Textarea content. + * @param string $id Optional. HTML ID attribute value. Default 'content'. + * @param string $prev_id Optional. Unused. + * @param bool $media_buttons Optional. Whether to display media buttons. Default true. + * @param int $tab_index Optional. Unused. + * @param bool $extended Optional. Unused. + */ + function the_editor($content, $id = 'content', $prev_id = 'title', $media_buttons = \true, $tab_index = 2, $extended = \true) + { + } + /** + * Perform the query to get the $metavalues array(s) needed by _fill_user and _fill_many_users + * + * @since 3.0.0 + * @deprecated 3.3.0 + * + * @param array $ids User ID numbers list. + * @return array of arrays. The array is indexed by user_id, containing $metavalues object arrays. + */ + function get_user_metavalues($ids) + { + } + /** + * Sanitize every user field. + * + * If the context is 'raw', then the user object or array will get minimal santization of the int fields. + * + * @since 2.3.0 + * @deprecated 3.3.0 + * + * @param object|array $user The user object or array. + * @param string $context Optional. How to sanitize user fields. Default 'display'. + * @return object|array The now sanitized user object or array (will be the same type as $user). + */ + function sanitize_user_object($user, $context = 'display') + { + } + /** + * Get boundary post relational link. + * + * Can either be start or end post relational link. + * + * @since 2.8.0 + * @deprecated 3.3.0 + * + * @param string $title Optional. Link title format. Default '%title'. + * @param bool $in_same_cat Optional. Whether link should be in a same category. + * Default false. + * @param string $excluded_categories Optional. Excluded categories IDs. Default empty. + * @param bool $start Optional. Whether to display link to first or last post. + * Default true. + * @return string + */ + function get_boundary_post_rel_link($title = '%title', $in_same_cat = \false, $excluded_categories = '', $start = \true) + { + } + /** + * Display relational link for the first post. + * + * @since 2.8.0 + * @deprecated 3.3.0 + * + * @param string $title Optional. Link title format. + * @param bool $in_same_cat Optional. Whether link should be in a same category. + * @param string $excluded_categories Optional. Excluded categories IDs. + */ + function start_post_rel_link($title = '%title', $in_same_cat = \false, $excluded_categories = '') + { + } + /** + * Get site index relational link. + * + * @since 2.8.0 + * @deprecated 3.3.0 + * + * @return string + */ + function get_index_rel_link() + { + } + /** + * Display relational link for the site index. + * + * @since 2.8.0 + * @deprecated 3.3.0 + */ + function index_rel_link() + { + } + /** + * Get parent post relational link. + * + * @since 2.8.0 + * @deprecated 3.3.0 + * + * @param string $title Optional. Link title format. Default '%title'. + * @return string + */ + function get_parent_post_rel_link($title = '%title') + { + } + /** + * Display relational link for parent item + * + * @since 2.8.0 + * @deprecated 3.3.0 + * + * @param string $title Optional. Link title format. Default '%title'. + */ + function parent_post_rel_link($title = '%title') + { + } + /** + * Add the "Dashboard"/"Visit Site" menu. + * + * @since 3.2.0 + * @deprecated 3.3.0 + * + * @param WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance. + */ + function wp_admin_bar_dashboard_view_site_menu($wp_admin_bar) + { + } + /** + * Checks if the current user belong to a given site. + * + * @since MU (3.0.0) + * @deprecated 3.3.0 Use is_user_member_of_blog() + * @see is_user_member_of_blog() + * + * @param int $blog_id Site ID + * @return bool True if the current users belong to $blog_id, false if not. + */ + function is_blog_user($blog_id = 0) + { + } + /** + * Open the file handle for debugging. + * + * @since 0.71 + * @deprecated 3.4.0 Use error_log() + * @see error_log() + * + * @link https://www.php.net/manual/en/function.error-log.php + * + * @param string $filename File name. + * @param string $mode Type of access you required to the stream. + * @return false Always false. + */ + function debug_fopen($filename, $mode) + { + } + /** + * Write contents to the file used for debugging. + * + * @since 0.71 + * @deprecated 3.4.0 Use error_log() + * @see error_log() + * + * @link https://www.php.net/manual/en/function.error-log.php + * + * @param mixed $fp Unused. + * @param string $message Message to log. + */ + function debug_fwrite($fp, $message) + { + } + /** + * Close the debugging file handle. + * + * @since 0.71 + * @deprecated 3.4.0 Use error_log() + * @see error_log() + * + * @link https://www.php.net/manual/en/function.error-log.php + * + * @param mixed $fp Unused. + */ + function debug_fclose($fp) + { + } + /** + * Retrieve list of themes with theme data in theme directory. + * + * The theme is broken, if it doesn't have a parent theme and is missing either + * style.css and, or index.php. If the theme has a parent theme then it is + * broken, if it is missing style.css; index.php is optional. + * + * @since 1.5.0 + * @deprecated 3.4.0 Use wp_get_themes() + * @see wp_get_themes() + * + * @return array Theme list with theme data. + */ + function get_themes() + { + } + /** + * Retrieve theme data. + * + * @since 1.5.0 + * @deprecated 3.4.0 Use wp_get_theme() + * @see wp_get_theme() + * + * @param string $theme Theme name. + * @return array|null Null, if theme name does not exist. Theme data, if exists. + */ + function get_theme($theme) + { + } + /** + * Retrieve current theme name. + * + * @since 1.5.0 + * @deprecated 3.4.0 Use wp_get_theme() + * @see wp_get_theme() + * + * @return string + */ + function get_current_theme() + { + } + /** + * Accepts matches array from preg_replace_callback in wpautop() or a string. + * + * Ensures that the contents of a `<pre>...</pre>` HTML block are not + * converted into paragraphs or line breaks. + * + * @since 1.2.0 + * @deprecated 3.4.0 + * + * @param array|string $matches The array or string + * @return string The pre block without paragraph/line break conversion. + */ + function clean_pre($matches) + { + } + /** + * Add callbacks for image header display. + * + * @since 2.1.0 + * @deprecated 3.4.0 Use add_theme_support() + * @see add_theme_support() + * + * @param callable $wp_head_callback Call on the {@see 'wp_head'} action. + * @param callable $admin_head_callback Call on custom header administration screen. + * @param callable $admin_preview_callback Output a custom header image div on the custom header administration screen. Optional. + */ + function add_custom_image_header($wp_head_callback, $admin_head_callback, $admin_preview_callback = '') + { + } + /** + * Remove image header support. + * + * @since 3.1.0 + * @deprecated 3.4.0 Use remove_theme_support() + * @see remove_theme_support() + * + * @return null|bool Whether support was removed. + */ + function remove_custom_image_header() + { + } + /** + * Add callbacks for background image display. + * + * @since 3.0.0 + * @deprecated 3.4.0 Use add_theme_support() + * @see add_theme_support() + * + * @param callable $wp_head_callback Call on the {@see 'wp_head'} action. + * @param callable $admin_head_callback Call on custom background administration screen. + * @param callable $admin_preview_callback Output a custom background image div on the custom background administration screen. Optional. + */ + function add_custom_background($wp_head_callback = '', $admin_head_callback = '', $admin_preview_callback = '') + { + } + /** + * Remove custom background support. + * + * @since 3.1.0 + * @deprecated 3.4.0 Use add_custom_background() + * @see add_custom_background() + * + * @return null|bool Whether support was removed. + */ + function remove_custom_background() + { + } + /** + * Retrieve theme data from parsed theme file. + * + * @since 1.5.0 + * @deprecated 3.4.0 Use wp_get_theme() + * @see wp_get_theme() + * + * @param string $theme_file Theme file path. + * @return array Theme data. + */ + function get_theme_data($theme_file) + { + } + /** + * Alias of update_post_cache(). + * + * @see update_post_cache() Posts and pages are the same, alias is intentional + * + * @since 1.5.1 + * @deprecated 3.4.0 Use update_post_cache() + * @see update_post_cache() + * + * @param array $pages list of page objects + */ + function update_page_cache(&$pages) + { + } + /** + * Will clean the page in the cache. + * + * Clean (read: delete) page from cache that matches $id. Will also clean cache + * associated with 'all_page_ids' and 'get_pages'. + * + * @since 2.0.0 + * @deprecated 3.4.0 Use clean_post_cache + * @see clean_post_cache() + * + * @param int $id Page ID to clean + */ + function clean_page_cache($id) + { + } + /** + * Retrieve nonce action "Are you sure" message. + * + * Deprecated in 3.4.1 and 3.5.0. Backported to 3.3.3. + * + * @since 2.0.4 + * @deprecated 3.4.1 Use wp_nonce_ays() + * @see wp_nonce_ays() + * + * @param string $action Nonce action. + * @return string Are you sure message. + */ + function wp_explain_nonce($action) + { + } + /** + * Display "sticky" CSS class, if a post is sticky. + * + * @since 2.7.0 + * @deprecated 3.5.0 Use post_class() + * @see post_class() + * + * @param int $post_id An optional post ID. + */ + function sticky_class($post_id = \null) + { + } + /** + * Retrieve post ancestors. + * + * This is no longer needed as WP_Post lazy-loads the ancestors + * property with get_post_ancestors(). + * + * @since 2.3.4 + * @deprecated 3.5.0 Use get_post_ancestors() + * @see get_post_ancestors() + * + * @param WP_Post $post Post object, passed by reference (unused). + */ + function _get_post_ancestors(&$post) + { + } + /** + * Load an image from a string, if PHP supports it. + * + * @since 2.1.0 + * @deprecated 3.5.0 Use wp_get_image_editor() + * @see wp_get_image_editor() + * + * @param string $file Filename of the image to load. + * @return resource|GdImage|string The resulting image resource or GdImage instance on success, + * error string on failure. + */ + function wp_load_image($file) + { + } + /** + * Scale down an image to fit a particular size and save a new copy of the image. + * + * The PNG transparency will be preserved using the function, as well as the + * image type. If the file going in is PNG, then the resized image is going to + * be PNG. The only supported image types are PNG, GIF, and JPEG. + * + * Some functionality requires API to exist, so some PHP version may lose out + * support. This is not the fault of WordPress (where functionality is + * downgraded, not actual defects), but of your PHP version. + * + * @since 2.5.0 + * @deprecated 3.5.0 Use wp_get_image_editor() + * @see wp_get_image_editor() + * + * @param string $file Image file path. + * @param int $max_w Maximum width to resize to. + * @param int $max_h Maximum height to resize to. + * @param bool $crop Optional. Whether to crop image or resize. Default false. + * @param string $suffix Optional. File suffix. Default null. + * @param string $dest_path Optional. New image file path. Default null. + * @param int $jpeg_quality Optional. Image quality percentage. Default 90. + * @return mixed WP_Error on failure. String with new destination path. + */ + function image_resize($file, $max_w, $max_h, $crop = \false, $suffix = \null, $dest_path = \null, $jpeg_quality = 90) + { + } + /** + * Retrieve a single post, based on post ID. + * + * Has categories in 'post_category' property or key. Has tags in 'tags_input' + * property or key. + * + * @since 1.0.0 + * @deprecated 3.5.0 Use get_post() + * @see get_post() + * + * @param int $postid Post ID. + * @param string $mode How to return result, either OBJECT, ARRAY_N, or ARRAY_A. + * @return WP_Post|null Post object or array holding post contents and information + */ + function wp_get_single_post($postid = 0, $mode = \OBJECT) + { + } + /** + * Check that the user login name and password is correct. + * + * @since 0.71 + * @deprecated 3.5.0 Use wp_authenticate() + * @see wp_authenticate() + * + * @param string $user_login User name. + * @param string $user_pass User password. + * @return bool False if does not authenticate, true if username and password authenticates. + */ + function user_pass_ok($user_login, $user_pass) + { + } + /** + * Callback formerly fired on the save_post hook. No longer needed. + * + * @since 2.3.0 + * @deprecated 3.5.0 + */ + function _save_post_hook() + { + } + /** + * Check if the installed version of GD supports particular image type + * + * @since 2.9.0 + * @deprecated 3.5.0 Use wp_image_editor_supports() + * @see wp_image_editor_supports() + * + * @param string $mime_type + * @return bool + */ + function gd_edit_image_support($mime_type) + { + } + /** + * Converts an integer byte value to a shorthand byte value. + * + * @since 2.3.0 + * @deprecated 3.6.0 Use size_format() + * @see size_format() + * + * @param int $bytes An integer byte value. + * @return string A shorthand byte value. + */ + function wp_convert_bytes_to_hr($bytes) + { + } + /** + * Formerly used internally to tidy up the search terms. + * + * @since 2.9.0 + * @access private + * @deprecated 3.7.0 + * + * @param string $t Search terms to "tidy", e.g. trim. + * @return string Trimmed search terms. + */ + function _search_terms_tidy($t) + { + } + /** + * Determine if TinyMCE is available. + * + * Checks to see if the user has deleted the tinymce files to slim down + * their WordPress installation. + * + * @since 2.1.0 + * @deprecated 3.9.0 + * + * @return bool Whether TinyMCE exists. + */ + function rich_edit_exists() + { + } + /** + * Old callback for tag link tooltips. + * + * @since 2.7.0 + * @access private + * @deprecated 3.9.0 + * + * @param int $count Number of topics. + * @return int Number of topics. + */ + function default_topic_count_text($count) + { + } + /** + * Formerly used to escape strings before inserting into the DB. + * + * Has not performed this function for many, many years. Use wpdb::prepare() instead. + * + * @since 0.71 + * @deprecated 3.9.0 + * + * @param string $content The text to format. + * @return string The very same text. + */ + function format_to_post($content) + { + } + /** + * Formerly used to escape strings before searching the DB. It was poorly documented and never worked as described. + * + * @since 2.5.0 + * @deprecated 4.0.0 Use wpdb::esc_like() + * @see wpdb::esc_like() + * + * @param string $text The text to be escaped. + * @return string text, safe for inclusion in LIKE query. + */ + function like_escape($text) + { + } + /** + * Determines if the URL can be accessed over SSL. + * + * Determines if the URL can be accessed over SSL by using the WordPress HTTP API to access + * the URL using https as the scheme. + * + * @since 2.5.0 + * @deprecated 4.0.0 + * + * @param string $url The URL to test. + * @return bool Whether SSL access is available. + */ + function url_is_accessable_via_ssl($url) + { + } + /** + * Start preview theme output buffer. + * + * Will only perform task if the user has permissions and template and preview + * query variables exist. + * + * @since 2.6.0 + * @deprecated 4.3.0 + */ + function preview_theme() + { + } + /** + * Private function to modify the current template when previewing a theme + * + * @since 2.9.0 + * @deprecated 4.3.0 + * @access private + * + * @return string + */ + function _preview_theme_template_filter() + { + } + /** + * Private function to modify the current stylesheet when previewing a theme + * + * @since 2.9.0 + * @deprecated 4.3.0 + * @access private + * + * @return string + */ + function _preview_theme_stylesheet_filter() + { + } + /** + * Callback function for ob_start() to capture all links in the theme. + * + * @since 2.6.0 + * @deprecated 4.3.0 + * @access private + * + * @param string $content + * @return string + */ + function preview_theme_ob_filter($content) + { + } + /** + * Manipulates preview theme links in order to control and maintain location. + * + * Callback function for preg_replace_callback() to accept and filter matches. + * + * @since 2.6.0 + * @deprecated 4.3.0 + * @access private + * + * @param array $matches + * @return string + */ + function preview_theme_ob_filter_callback($matches) + { + } + /** + * Formats text for the rich text editor. + * + * The {@see 'richedit_pre'} filter is applied here. If `$text` is empty the filter will + * be applied to an empty string. + * + * @since 2.0.0 + * @deprecated 4.3.0 Use format_for_editor() + * @see format_for_editor() + * + * @param string $text The text to be formatted. + * @return string The formatted text after filter is applied. + */ + function wp_richedit_pre($text) + { + } + /** + * Formats text for the HTML editor. + * + * Unless $output is empty it will pass through htmlspecialchars before the + * {@see 'htmledit_pre'} filter is applied. + * + * @since 2.5.0 + * @deprecated 4.3.0 Use format_for_editor() + * @see format_for_editor() + * + * @param string $output The text to be formatted. + * @return string Formatted text after filter applied. + */ + function wp_htmledit_pre($output) + { + } + /** + * Retrieve permalink from post ID. + * + * @since 1.0.0 + * @deprecated 4.4.0 Use get_permalink() + * @see get_permalink() + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @return string|false + */ + function post_permalink($post = 0) + { + } + /** + * Perform a HTTP HEAD or GET request. + * + * If $file_path is a writable filename, this will do a GET request and write + * the file to that path. + * + * @since 2.5.0 + * @deprecated 4.4.0 Use WP_Http + * @see WP_Http + * + * @param string $url URL to fetch. + * @param string|bool $file_path Optional. File path to write request to. Default false. + * @param int $red Optional. The number of Redirects followed, Upon 5 being hit, + * returns false. Default 1. + * @return \Requests_Utility_CaseInsensitiveDictionary|false Headers on success, false on failure. + */ + function wp_get_http($url, $file_path = \false, $red = 1) + { + } + /** + * Whether SSL login should be forced. + * + * @since 2.6.0 + * @deprecated 4.4.0 Use force_ssl_admin() + * @see force_ssl_admin() + * + * @param string|bool $force Optional Whether to force SSL login. Default null. + * @return bool True if forced, false if not forced. + */ + function force_ssl_login($force = \null) + { + } + /** + * Retrieve path of comment popup template in current or parent template. + * + * @since 1.5.0 + * @deprecated 4.5.0 + * + * @return string Full path to comments popup template file. + */ + function get_comments_popup_template() + { + } + /** + * Determines whether the current URL is within the comments popup window. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * @deprecated 4.5.0 + * + * @return false Always returns false. + */ + function is_comments_popup() + { + } + /** + * Display the JS popup script to show a comment. + * + * @since 0.71 + * @deprecated 4.5.0 + */ + function comments_popup_script() + { + } + /** + * Adds element attributes to open links in new tabs. + * + * @since 0.71 + * @deprecated 4.5.0 + * + * @param string $text Content to replace links to open in a new tab. + * @return string Content that has filtered links. + */ + function popuplinks($text) + { + } + /** + * The Google Video embed handler callback. + * + * Deprecated function that previously assisted in turning Google Video URLs + * into embeds but that service has since been shut down. + * + * @since 2.9.0 + * @deprecated 4.6.0 + * + * @return string An empty string. + */ + function wp_embed_handler_googlevideo($matches, $attr, $url, $rawattr) + { + } + /** + * Retrieve path of paged template in current or parent template. + * + * @since 1.5.0 + * @deprecated 4.7.0 The paged.php template is no longer part of the theme template hierarchy. + * + * @return string Full path to paged template file. + */ + function get_paged_template() + { + } + /** + * Removes the HTML JavaScript entities found in early versions of Netscape 4. + * + * Previously, this function was pulled in from the original + * import of kses and removed a specific vulnerability only + * existent in early version of Netscape 4. However, this + * vulnerability never affected any other browsers and can + * be considered safe for the modern web. + * + * The regular expression which sanitized this vulnerability + * has been removed in consideration of the performance and + * energy demands it placed, now merely passing through its + * input to the return. + * + * @since 1.0.0 + * @deprecated 4.7.0 Officially dropped security support for Netscape 4. + * + * @param string $content + * @return string + */ + function wp_kses_js_entities($content) + { + } + /** + * Sort categories by ID. + * + * Used by usort() as a callback, should not be used directly. Can actually be + * used to sort any term object. + * + * @since 2.3.0 + * @deprecated 4.7.0 Use wp_list_sort() + * @access private + * + * @param object $a + * @param object $b + * @return int + */ + function _usort_terms_by_ID($a, $b) + { + } + /** + * Sort categories by name. + * + * Used by usort() as a callback, should not be used directly. Can actually be + * used to sort any term object. + * + * @since 2.3.0 + * @deprecated 4.7.0 Use wp_list_sort() + * @access private + * + * @param object $a + * @param object $b + * @return int + */ + function _usort_terms_by_name($a, $b) + { + } + /** + * Sort menu items by the desired key. + * + * @since 3.0.0 + * @deprecated 4.7.0 Use wp_list_sort() + * @access private + * + * @global string $_menu_item_sort_prop + * + * @param object $a The first object to compare + * @param object $b The second object to compare + * @return int -1, 0, or 1 if $a is considered to be respectively less than, equal to, or greater than $b. + */ + function _sort_nav_menu_items($a, $b) + { + } + /** + * Retrieves the Press This bookmarklet link. + * + * @since 2.6.0 + * @deprecated 4.9.0 + * + */ + function get_shortcut_link() + { + } + /** + * Ajax handler for saving a post from Press This. + * + * @since 4.2.0 + * @deprecated 4.9.0 + */ + function wp_ajax_press_this_save_post() + { + } + /** + * Ajax handler for creating new category from Press This. + * + * @since 4.2.0 + * @deprecated 4.9.0 + */ + function wp_ajax_press_this_add_category() + { + } + /** + * Return the user request object for the specified request ID. + * + * @since 4.9.6 + * @deprecated 5.4.0 Use wp_get_user_request() + * @see wp_get_user_request() + * + * @param int $request_id The ID of the user request. + * @return WP_User_Request|false + */ + function wp_get_user_request_data($request_id) + { + } + /** + * Filters 'img' elements in post content to add 'srcset' and 'sizes' attributes. + * + * @since 4.4.0 + * @deprecated 5.5.0 + * + * @see wp_image_add_srcset_and_sizes() + * + * @param string $content The raw post content to be filtered. + * @return string Converted content with 'srcset' and 'sizes' attributes added to images. + */ + function wp_make_content_images_responsive($content) + { + } + /** + * Turn register globals off. + * + * @since 2.1.0 + * @access private + * @deprecated 5.5.0 + */ + function wp_unregister_GLOBALS() + { + } + /** + * Does comment contain disallowed characters or words. + * + * @since 1.5.0 + * @deprecated 5.5.0 Use wp_check_comment_disallowed_list() instead. + * Please consider writing more inclusive code. + * + * @param string $author The author of the comment + * @param string $email The email of the comment + * @param string $url The url used in the comment + * @param string $comment The comment content + * @param string $user_ip The comment author's IP address + * @param string $user_agent The author's browser user agent + * @return bool True if comment contains disallowed content, false if comment does not + */ + function wp_blacklist_check($author, $email, $url, $comment, $user_ip, $user_agent) + { + } + /** + * Filters out `register_meta()` args based on an allowed list. + * + * `register_meta()` args may change over time, so requiring the allowed list + * to be explicitly turned off is a warranty seal of sorts. + * + * @access private + * @since 4.6.0 + * @deprecated 5.5.0 Use _wp_register_meta_args_allowed_list() instead. + * Please consider writing more inclusive code. + * + * @param array $args Arguments from `register_meta()`. + * @param array $default_args Default arguments for `register_meta()`. + * @return array Filtered arguments. + */ + function _wp_register_meta_args_whitelist($args, $default_args) + { + } + /** + * Adds an array of options to the list of allowed options. + * + * @since 2.7.0 + * @deprecated 5.5.0 Use add_allowed_options() instead. + * Please consider writing more inclusive code. + * + * @global array $allowed_options + * + * @param array $new_options + * @param string|array $options + * @return array + */ + function add_option_whitelist($new_options, $options = '') + { + } + /** + * Removes a list of options from the allowed options list. + * + * @since 2.7.0 + * @deprecated 5.5.0 Use remove_allowed_options() instead. + * Please consider writing more inclusive code. + * + * @global array $allowed_options + * + * @param array $del_options + * @param string|array $options + * @return array + */ + function remove_option_whitelist($del_options, $options = '') + { + } + /** + * Adds slashes to only string values in an array of values. + * + * This should be used when preparing data for core APIs that expect slashed data. + * This should not be used to escape data going directly into an SQL query. + * + * @since 5.3.0 + * @deprecated 5.6.0 Use wp_slash() + * + * @see wp_slash() + * + * @param mixed $value Scalar or array of scalars. + * @return mixed Slashes $value + */ + function wp_slash_strings_only($value) + { + } + /** + * Adds slashes only if the provided value is a string. + * + * @since 5.3.0 + * @deprecated 5.6.0 + * + * @see wp_slash() + * + * @param mixed $value + * @return mixed + */ + function addslashes_strings_only($value) + { + } + /** + * Displays a `noindex` meta tag if required by the blog configuration. + * + * If a blog is marked as not being public then the `noindex` meta tag will be + * output to tell web robots not to index the page content. + * + * Typical usage is as a {@see 'wp_head'} callback: + * + * add_action( 'wp_head', 'noindex' ); + * + * @see wp_no_robots() + * + * @since 2.1.0 + * @deprecated 5.7.0 Use wp_robots_noindex() instead on 'wp_robots' filter. + */ + function noindex() + { + } + /** + * Display a `noindex` meta tag. + * + * Outputs a `noindex` meta tag that tells web robots not to index the page content. + * + * Typical usage is as a {@see 'wp_head'} callback: + * + * add_action( 'wp_head', 'wp_no_robots' ); + * + * @since 3.3.0 + * @since 5.3.0 Echo `noindex,nofollow` if search engine visibility is discouraged. + * @deprecated 5.7.0 Use wp_robots_no_robots() instead on 'wp_robots' filter. + */ + function wp_no_robots() + { + } + /** + * Display a `noindex,noarchive` meta tag and referrer `strict-origin-when-cross-origin` meta tag. + * + * Outputs a `noindex,noarchive` meta tag that tells web robots not to index or cache the page content. + * Outputs a referrer `strict-origin-when-cross-origin` meta tag that tells the browser not to send + * the full URL as a referrer to other sites when cross-origin assets are loaded. + * + * Typical usage is as a {@see 'wp_head'} callback: + * + * add_action( 'wp_head', 'wp_sensitive_page_meta' ); + * + * @since 5.0.1 + * @deprecated 5.7.0 Use wp_robots_sensitive_page() instead on 'wp_robots' filter + * and wp_strict_cross_origin_referrer() on 'wp_head' action. + * + * @see wp_robots_sensitive_page() + */ + function wp_sensitive_page_meta() + { + } + /** + * Render inner blocks from the `core/columns` block for generating an excerpt. + * + * @since 5.2.0 + * @access private + * @deprecated 5.8.0 Use _excerpt_render_inner_blocks() introduced in 5.8.0. + * + * @see _excerpt_render_inner_blocks() + * + * @param array $columns The parsed columns block. + * @param array $allowed_blocks The list of allowed inner blocks. + * @return string The rendered inner blocks. + */ + function _excerpt_render_inner_columns_blocks($columns, $allowed_blocks) + { + } + /** + * Renders the duotone filter SVG and returns the CSS filter property to + * reference the rendered SVG. + * + * @since 5.9.0 + * @deprecated 5.9.1 Use wp_get_duotone_filter_property() introduced in 5.9.1. + * + * @see wp_get_duotone_filter_property() + * + * @param array $preset Duotone preset value as seen in theme.json. + * @return string Duotone CSS filter property. + */ + function wp_render_duotone_filter_preset($preset) + { + } + /** + * Checks whether serialization of the current block's border properties should occur. + * + * @since 5.8.0 + * @access private + * @deprecated 6.0.0 Use wp_should_skip_block_supports_serialization() introduced in 6.0.0. + * + * @see wp_should_skip_block_supports_serialization() + * + * @param WP_Block_Type $block_type Block type. + * @return bool Whether serialization of the current block's border properties + * should occur. + */ + function wp_skip_border_serialization($block_type) + { + } + /** + * Checks whether serialization of the current block's dimensions properties should occur. + * + * @since 5.9.0 + * @access private + * @deprecated 6.0.0 Use wp_should_skip_block_supports_serialization() introduced in 6.0.0. + * + * @see wp_should_skip_block_supports_serialization() + * + * @param WP_Block_type $block_type Block type. + * @return bool Whether to serialize spacing support styles & classes. + */ + function wp_skip_dimensions_serialization($block_type) + { + } + /** + * Checks whether serialization of the current block's spacing properties should occur. + * + * @since 5.9.0 + * @access private + * @deprecated 6.0.0 Use wp_should_skip_block_supports_serialization() introduced in 6.0.0. + * + * @see wp_should_skip_block_supports_serialization() + * + * @param WP_Block_Type $block_type Block type. + * @return bool Whether to serialize spacing support styles & classes. + */ + function wp_skip_spacing_serialization($block_type) + { + } + /** + * Inject the block editor assets that need to be loaded into the editor's iframe as an inline script. + * + * @since 5.8.0 + * @deprecated 6.0.0 + */ + function wp_add_iframed_editor_assets_html() + { + } + /** + * Retrieves thumbnail for an attachment. + * Note that this works only for the (very) old image metadata style where 'thumb' was set, + * and the 'sizes' array did not exist. This function returns false for the newer image metadata style + * despite that 'thumbnail' is present in the 'sizes' array. + * + * @since 2.1.0 + * @deprecated 6.1.0 + * + * @param int $post_id Optional. Attachment ID. Default is the ID of the global `$post`. + * @return string|false Thumbnail file path on success, false on failure. + */ + function wp_get_attachment_thumb_file($post_id = 0) + { + } + /** + * Gets the path to a translation file for loading a textdomain just in time. + * + * Caches the retrieved results internally. + * + * @since 4.7.0 + * @deprecated 6.1.0 + * @access private + * + * @see _load_textdomain_just_in_time() + * + * @param string $domain Text domain. Unique identifier for retrieving translated strings. + * @param bool $reset Whether to reset the internal cache. Used by the switch to locale functionality. + * @return string|false The path to the translation file or false if no translation file was found. + */ + function _get_path_to_translation($domain, $reset = \false) + { + } + /** + * Gets the path to a translation file in the languages directory for the current locale. + * + * Holds a cached list of available .mo files to improve performance. + * + * @since 4.7.0 + * @deprecated 6.1.0 + * @access private + * + * @see _get_path_to_translation() + * + * @param string $domain Text domain. Unique identifier for retrieving translated strings. + * @return string|false The path to the translation file or false if no translation file was found. + */ + function _get_path_to_translation_from_lang_dir($domain) + { + } + /** + * Allows multiple block styles. + * + * @since 5.9.0 + * @deprecated 6.1.0 + * + * @param array $metadata Metadata for registering a block type. + * @return array Metadata for registering a block type. + */ + function _wp_multiple_block_styles($metadata) + { + } + /** + * Generates an inline style for a typography feature e.g. text decoration, + * text transform, and font style. + * + * @since 5.8.0 + * @access private + * @deprecated 6.1.0 Use wp_style_engine_get_styles() introduced in 6.1.0. + * + * @see wp_style_engine_get_styles() + * + * @param array $attributes Block's attributes. + * @param string $feature Key for the feature within the typography styles. + * @param string $css_property Slug for the CSS property the inline style sets. + * @return string CSS inline style. + */ + function wp_typography_get_css_variable_inline_style($attributes, $feature, $css_property) + { + } + /** + * Determines whether global terms are enabled. + * + * @since 3.0.0 + * @since 6.1.0 This function now always returns false. + * @deprecated 6.1.0 + * + * @return bool Always returns false. + */ + function global_terms_enabled() + { + } + /** + * Filter the SQL clauses of an attachment query to include filenames. + * + * @since 4.7.0 + * @deprecated 6.0.3 + * @access private + * + * @param array $clauses An array including WHERE, GROUP BY, JOIN, ORDER BY, + * DISTINCT, fields (SELECT), and LIMITS clauses. + * @return array The unmodified clauses. + */ + function _filter_query_attachment_filenames($clauses) + { + } + /** + * oEmbed API: Top-level oEmbed functionality + * + * @package WordPress + * @subpackage oEmbed + * @since 4.4.0 + */ + /** + * Registers an embed handler. + * + * Should probably only be used for sites that do not support oEmbed. + * + * @since 2.9.0 + * + * @global WP_Embed $wp_embed + * + * @param string $id An internal ID/name for the handler. Needs to be unique. + * @param string $regex The regex that will be used to see if this handler should be used for a URL. + * @param callable $callback The callback function that will be called if the regex is matched. + * @param int $priority Optional. Used to specify the order in which the registered handlers will + * be tested. Default 10. + */ + function wp_embed_register_handler($id, $regex, $callback, $priority = 10) + { + } + /** + * Unregisters a previously-registered embed handler. + * + * @since 2.9.0 + * + * @global WP_Embed $wp_embed + * + * @param string $id The handler ID that should be removed. + * @param int $priority Optional. The priority of the handler to be removed. Default 10. + */ + function wp_embed_unregister_handler($id, $priority = 10) + { + } + /** + * Creates default array of embed parameters. + * + * The width defaults to the content width as specified by the theme. If the + * theme does not specify a content width, then 500px is used. + * + * The default height is 1.5 times the width, or 1000px, whichever is smaller. + * + * The {@see 'embed_defaults'} filter can be used to adjust either of these values. + * + * @since 2.9.0 + * + * @global int $content_width + * + * @param string $url Optional. The URL that should be embedded. Default empty. + * @return int[] { + * Indexed array of the embed width and height in pixels. + * + * @type int $0 The embed width. + * @type int $1 The embed height. + * } + * @phpstan-return array{ + * 0: int, + * 1: int, + * } + */ + function wp_embed_defaults($url = '') + { + } + /** + * Attempts to fetch the embed HTML for a provided URL using oEmbed. + * + * @since 2.9.0 + * + * @see WP_oEmbed + * + * @param string $url The URL that should be embedded. + * @param array|string $args { + * Optional. Additional arguments for retrieving embed HTML. Default empty. + * + * @type int|string $width Optional. The `maxwidth` value passed to the provider URL. + * @type int|string $height Optional. The `maxheight` value passed to the provider URL. + * @type bool $discover Optional. Determines whether to attempt to discover link tags + * at the given URL for an oEmbed provider when the provider URL + * is not found in the built-in providers list. Default true. + * } + * @return string|false The embed HTML on success, false on failure. + * @phpstan-param array{ + * width?: int|string, + * height?: int|string, + * discover?: bool, + * } $args + */ + function wp_oembed_get($url, $args = '') + { + } + /** + * Returns the initialized WP_oEmbed object. + * + * @since 2.9.0 + * @access private + * + * @return WP_oEmbed object. + */ + function _wp_oembed_get_object() + { + } + /** + * Adds a URL format and oEmbed provider URL pair. + * + * @since 2.9.0 + * + * @see WP_oEmbed + * + * @param string $format The format of URL that this provider can handle. You can use asterisks + * as wildcards. + * @param string $provider The URL to the oEmbed provider. + * @param bool $regex Optional. Whether the `$format` parameter is in a RegEx format. Default false. + */ + function wp_oembed_add_provider($format, $provider, $regex = \false) + { + } + /** + * Removes an oEmbed provider. + * + * @since 3.5.0 + * + * @see WP_oEmbed + * + * @param string $format The URL format for the oEmbed provider to remove. + * @return bool Was the provider removed successfully? + */ + function wp_oembed_remove_provider($format) + { + } + /** + * Determines if default embed handlers should be loaded. + * + * Checks to make sure that the embeds library hasn't already been loaded. If + * it hasn't, then it will load the embeds library. + * + * @since 2.9.0 + * + * @see wp_embed_register_handler() + */ + function wp_maybe_load_embeds() + { + } + /** + * YouTube iframe embed handler callback. + * + * Catches YouTube iframe embed URLs that are not parsable by oEmbed but can be translated into a URL that is. + * + * @since 4.0.0 + * + * @global WP_Embed $wp_embed + * + * @param array $matches The RegEx matches from the provided regex when calling + * wp_embed_register_handler(). + * @param array $attr Embed attributes. + * @param string $url The original URL that was matched by the regex. + * @param array $rawattr The original unmodified attributes. + * @return string The embed HTML. + */ + function wp_embed_handler_youtube($matches, $attr, $url, $rawattr) + { + } + /** + * Audio embed handler callback. + * + * @since 3.6.0 + * + * @param array $matches The RegEx matches from the provided regex when calling wp_embed_register_handler(). + * @param array $attr Embed attributes. + * @param string $url The original URL that was matched by the regex. + * @param array $rawattr The original unmodified attributes. + * @return string The embed HTML. + */ + function wp_embed_handler_audio($matches, $attr, $url, $rawattr) + { + } + /** + * Video embed handler callback. + * + * @since 3.6.0 + * + * @param array $matches The RegEx matches from the provided regex when calling wp_embed_register_handler(). + * @param array $attr Embed attributes. + * @param string $url The original URL that was matched by the regex. + * @param array $rawattr The original unmodified attributes. + * @return string The embed HTML. + */ + function wp_embed_handler_video($matches, $attr, $url, $rawattr) + { + } + /** + * Registers the oEmbed REST API route. + * + * @since 4.4.0 + */ + function wp_oembed_register_route() + { + } + /** + * Adds oEmbed discovery links in the head element of the website. + * + * @since 4.4.0 + */ + function wp_oembed_add_discovery_links() + { + } + /** + * Adds the necessary JavaScript to communicate with the embedded iframes. + * + * This function is no longer used directly. For back-compat it exists exclusively as a way to indicate that the oEmbed + * host JS _should_ be added. In `default-filters.php` there remains this code: + * + * add_action( 'wp_head', 'wp_oembed_add_host_js' ) + * + * Historically a site has been able to disable adding the oEmbed host script by doing: + * + * remove_action( 'wp_head', 'wp_oembed_add_host_js' ) + * + * In order to ensure that such code still works as expected, this function remains. There is now a `has_action()` check + * in `wp_maybe_enqueue_oembed_host_js()` to see if `wp_oembed_add_host_js()` has not been unhooked from running at the + * `wp_head` action. + * + * @since 4.4.0 + * @deprecated 5.9.0 Use {@see wp_maybe_enqueue_oembed_host_js()} instead. + */ + function wp_oembed_add_host_js() + { + } + /** + * Enqueue the wp-embed script if the provided oEmbed HTML contains a post embed. + * + * In order to only enqueue the wp-embed script on pages that actually contain post embeds, this function checks if the + * provided HTML contains post embed markup and if so enqueues the script so that it will get printed in the footer. + * + * @since 5.9.0 + * + * @param string $html Embed markup. + * @return string Embed markup (without modifications). + */ + function wp_maybe_enqueue_oembed_host_js($html) + { + } + /** + * Retrieves the URL to embed a specific post in an iframe. + * + * @since 4.4.0 + * + * @param int|WP_Post $post Optional. Post ID or object. Defaults to the current post. + * @return string|false The post embed URL on success, false if the post doesn't exist. + */ + function get_post_embed_url($post = \null) + { + } + /** + * Retrieves the oEmbed endpoint URL for a given permalink. + * + * Pass an empty string as the first argument to get the endpoint base URL. + * + * @since 4.4.0 + * + * @param string $permalink Optional. The permalink used for the `url` query arg. Default empty. + * @param string $format Optional. The requested response format. Default 'json'. + * @return string The oEmbed endpoint URL. + */ + function get_oembed_endpoint_url($permalink = '', $format = 'json') + { + } + /** + * Retrieves the embed code for a specific post. + * + * @since 4.4.0 + * + * @param int $width The width for the response. + * @param int $height The height for the response. + * @param int|WP_Post $post Optional. Post ID or object. Default is global `$post`. + * @return string|false Embed code on success, false if post doesn't exist. + */ + function get_post_embed_html($width, $height, $post = \null) + { + } + /** + * Retrieves the oEmbed response data for a given post. + * + * @since 4.4.0 + * + * @param WP_Post|int $post Post ID or post object. + * @param int $width The requested width. + * @return array|false Response data on success, false if post doesn't exist + * or is not publicly viewable. + */ + function get_oembed_response_data($post, $width) + { + } + /** + * Retrieves the oEmbed response data for a given URL. + * + * @since 5.0.0 + * + * @param string $url The URL that should be inspected for discovery `<link>` tags. + * @param array $args oEmbed remote get arguments. + * @return object|false oEmbed response data if the URL does belong to the current site. False otherwise. + */ + function get_oembed_response_data_for_url($url, $args) + { + } + /** + * Filters the oEmbed response data to return an iframe embed code. + * + * @since 4.4.0 + * + * @param array $data The response data. + * @param WP_Post $post The post object. + * @param int $width The requested width. + * @param int $height The calculated height. + * @return array The modified response data. + */ + function get_oembed_response_data_rich($data, $post, $width, $height) + { + } + /** + * Ensures that the specified format is either 'json' or 'xml'. + * + * @since 4.4.0 + * + * @param string $format The oEmbed response format. Accepts 'json' or 'xml'. + * @return string The format, either 'xml' or 'json'. Default 'json'. + */ + function wp_oembed_ensure_format($format) + { + } + /** + * Hooks into the REST API output to print XML instead of JSON. + * + * This is only done for the oEmbed API endpoint, + * which supports both formats. + * + * @access private + * @since 4.4.0 + * + * @param bool $served Whether the request has already been served. + * @param WP_HTTP_Response $result Result to send to the client. Usually a `WP_REST_Response`. + * @param WP_REST_Request $request Request used to generate the response. + * @param WP_REST_Server $server Server instance. + * @return true + */ + function _oembed_rest_pre_serve_request($served, $result, $request, $server) + { + } + /** + * Creates an XML string from a given array. + * + * @since 4.4.0 + * @access private + * + * @param array $data The original oEmbed response data. + * @param SimpleXMLElement $node Optional. XML node to append the result to recursively. + * @return string|false XML string on success, false on error. + */ + function _oembed_create_xml($data, $node = \null) + { + } + /** + * Filters the given oEmbed HTML to make sure iframes have a title attribute. + * + * @since 5.2.0 + * + * @param string $result The oEmbed HTML result. + * @param object $data A data object result from an oEmbed provider. + * @param string $url The URL of the content to be embedded. + * @return string The filtered oEmbed result. + */ + function wp_filter_oembed_iframe_title_attribute($result, $data, $url) + { + } + /** + * Filters the given oEmbed HTML. + * + * If the `$url` isn't on the trusted providers list, + * we need to filter the HTML heavily for security. + * + * Only filters 'rich' and 'video' response types. + * + * @since 4.4.0 + * + * @param string $result The oEmbed HTML result. + * @param object $data A data object result from an oEmbed provider. + * @param string $url The URL of the content to be embedded. + * @return string The filtered and sanitized oEmbed result. + */ + function wp_filter_oembed_result($result, $data, $url) + { + } + /** + * Filters the string in the 'more' link displayed after a trimmed excerpt. + * + * Replaces '[...]' (appended to automatically generated excerpts) with an + * ellipsis and a "Continue reading" link in the embed template. + * + * @since 4.4.0 + * + * @param string $more_string Default 'more' string. + * @return string 'Continue reading' link prepended with an ellipsis. + */ + function wp_embed_excerpt_more($more_string) + { + } + /** + * Displays the post excerpt for the embed template. + * + * Intended to be used in 'The Loop'. + * + * @since 4.4.0 + */ + function the_excerpt_embed() + { + } + /** + * Filters the post excerpt for the embed template. + * + * Shows players for video and audio attachments. + * + * @since 4.4.0 + * + * @param string $content The current post excerpt. + * @return string The modified post excerpt. + */ + function wp_embed_excerpt_attachment($content) + { + } + /** + * Enqueues embed iframe default CSS and JS. + * + * Enqueue PNG fallback CSS for embed iframe for legacy versions of IE. + * + * Allows plugins to queue scripts for the embed iframe end using wp_enqueue_script(). + * Runs first in oembed_head(). + * + * @since 4.4.0 + */ + function enqueue_embed_scripts() + { + } + /** + * Prints the CSS in the embed iframe header. + * + * @since 4.4.0 + */ + function print_embed_styles() + { + } + /** + * Prints the JavaScript in the embed iframe header. + * + * @since 4.4.0 + */ + function print_embed_scripts() + { + } + /** + * Prepare the oembed HTML to be displayed in an RSS feed. + * + * @since 4.4.0 + * @access private + * + * @param string $content The content to filter. + * @return string The filtered content. + */ + function _oembed_filter_feed_content($content) + { + } + /** + * Prints the necessary markup for the embed comments button. + * + * @since 4.4.0 + */ + function print_embed_comments_button() + { + } + /** + * Prints the necessary markup for the embed sharing button. + * + * @since 4.4.0 + */ + function print_embed_sharing_button() + { + } + /** + * Prints the necessary markup for the embed sharing dialog. + * + * @since 4.4.0 + */ + function print_embed_sharing_dialog() + { + } + /** + * Prints the necessary markup for the site title in an embed template. + * + * @since 4.5.0 + */ + function the_embed_site_title() + { + } + /** + * Filters the oEmbed result before any HTTP requests are made. + * + * If the URL belongs to the current site, the result is fetched directly instead of + * going through the oEmbed discovery process. + * + * @since 4.5.3 + * + * @param null|string $result The UNSANITIZED (and potentially unsafe) HTML that should be used to embed. Default null. + * @param string $url The URL that should be inspected for discovery `<link>` tags. + * @param array $args oEmbed remote get arguments. + * @return null|string The UNSANITIZED (and potentially unsafe) HTML that should be used to embed. + * Null if the URL does not belong to the current site. + */ + function wp_filter_pre_oembed_result($result, $url, $args) + { + } + /** + * Error Protection API: Functions + * + * @package WordPress + * @since 5.2.0 + */ + /** + * Get the instance for storing paused plugins. + * + * @return WP_Paused_Extensions_Storage + */ + function wp_paused_plugins() + { + } + /** + * Get the instance for storing paused extensions. + * + * @return WP_Paused_Extensions_Storage + */ + function wp_paused_themes() + { + } + /** + * Get a human readable description of an extension's error. + * + * @since 5.2.0 + * + * @param array $error Error details from `error_get_last()`. + * @return string Formatted error description. + */ + function wp_get_extension_error_description($error) + { + } + /** + * Registers the shutdown handler for fatal errors. + * + * The handler will only be registered if {@see wp_is_fatal_error_handler_enabled()} returns true. + * + * @since 5.2.0 + */ + function wp_register_fatal_error_handler() + { + } + /** + * Checks whether the fatal error handler is enabled. + * + * A constant `WP_DISABLE_FATAL_ERROR_HANDLER` can be set in `wp-config.php` to disable it, or alternatively the + * {@see 'wp_fatal_error_handler_enabled'} filter can be used to modify the return value. + * + * @since 5.2.0 + * + * @return bool True if the fatal error handler is enabled, false otherwise. + */ + function wp_is_fatal_error_handler_enabled() + { + } + /** + * Access the WordPress Recovery Mode instance. + * + * @since 5.2.0 + * + * @return WP_Recovery_Mode + */ + function wp_recovery_mode() + { + } + /** + * WordPress Feed API + * + * Many of the functions used in here belong in The Loop, or The Loop for the + * Feeds. + * + * @package WordPress + * @subpackage Feed + * @since 2.1.0 + */ + /** + * Retrieves RSS container for the bloginfo function. + * + * You can retrieve anything that you can using the get_bloginfo() function. + * Everything will be stripped of tags and characters converted, when the values + * are retrieved for use in the feeds. + * + * @since 1.5.1 + * + * @see get_bloginfo() For the list of possible values to display. + * + * @param string $show See get_bloginfo() for possible values. + * @return string + */ + function get_bloginfo_rss($show = '') + { + } + /** + * Displays RSS container for the bloginfo function. + * + * You can retrieve anything that you can using the get_bloginfo() function. + * Everything will be stripped of tags and characters converted, when the values + * are retrieved for use in the feeds. + * + * @since 0.71 + * + * @see get_bloginfo() For the list of possible values to display. + * + * @param string $show See get_bloginfo() for possible values. + */ + function bloginfo_rss($show = '') + { + } + /** + * Retrieves the default feed. + * + * The default feed is 'rss2', unless a plugin changes it through the + * {@see 'default_feed'} filter. + * + * @since 2.5.0 + * + * @return string Default feed, or for example 'rss2', 'atom', etc. + */ + function get_default_feed() + { + } + /** + * Retrieves the blog title for the feed title. + * + * @since 2.2.0 + * @since 4.4.0 The optional `$sep` parameter was deprecated and renamed to `$deprecated`. + * + * @param string $deprecated Unused. + * @return string The document title. + */ + function get_wp_title_rss($deprecated = '–') + { + } + /** + * Displays the blog title for display of the feed title. + * + * @since 2.2.0 + * @since 4.4.0 The optional `$sep` parameter was deprecated and renamed to `$deprecated`. + * + * @param string $deprecated Unused. + */ + function wp_title_rss($deprecated = '–') + { + } + /** + * Retrieves the current post title for the feed. + * + * @since 2.0.0 + * + * @return string Current post title. + */ + function get_the_title_rss() + { + } + /** + * Displays the post title in the feed. + * + * @since 0.71 + */ + function the_title_rss() + { + } + /** + * Retrieves the post content for feeds. + * + * @since 2.9.0 + * + * @see get_the_content() + * + * @param string $feed_type The type of feed. rss2 | atom | rss | rdf + * @return string The filtered content. + */ + function get_the_content_feed($feed_type = \null) + { + } + /** + * Displays the post content for feeds. + * + * @since 2.9.0 + * + * @param string $feed_type The type of feed. rss2 | atom | rss | rdf + */ + function the_content_feed($feed_type = \null) + { + } + /** + * Displays the post excerpt for the feed. + * + * @since 0.71 + */ + function the_excerpt_rss() + { + } + /** + * Displays the permalink to the post for use in feeds. + * + * @since 2.3.0 + */ + function the_permalink_rss() + { + } + /** + * Outputs the link to the comments for the current post in an XML safe way. + * + * @since 3.0.0 + */ + function comments_link_feed() + { + } + /** + * Displays the feed GUID for the current comment. + * + * @since 2.5.0 + * + * @param int|WP_Comment $comment_id Optional comment object or ID. Defaults to global comment object. + */ + function comment_guid($comment_id = \null) + { + } + /** + * Retrieves the feed GUID for the current comment. + * + * @since 2.5.0 + * + * @param int|WP_Comment $comment_id Optional comment object or ID. Defaults to global comment object. + * @return string|false GUID for comment on success, false on failure. + */ + function get_comment_guid($comment_id = \null) + { + } + /** + * Displays the link to the comments. + * + * @since 1.5.0 + * @since 4.4.0 Introduced the `$comment` argument. + * + * @param int|WP_Comment $comment Optional. Comment object or ID. Defaults to global comment object. + */ + function comment_link($comment = \null) + { + } + /** + * Retrieves the current comment author for use in the feeds. + * + * @since 2.0.0 + * + * @return string Comment Author. + */ + function get_comment_author_rss() + { + } + /** + * Displays the current comment author in the feed. + * + * @since 1.0.0 + */ + function comment_author_rss() + { + } + /** + * Displays the current comment content for use in the feeds. + * + * @since 1.0.0 + */ + function comment_text_rss() + { + } + /** + * Retrieves all of the post categories, formatted for use in feeds. + * + * All of the categories for the current post in the feed loop, will be + * retrieved and have feed markup added, so that they can easily be added to the + * RSS2, Atom, or RSS1 and RSS0.91 RDF feeds. + * + * @since 2.1.0 + * + * @param string $type Optional, default is the type returned by get_default_feed(). + * @return string All of the post categories for displaying in the feed. + */ + function get_the_category_rss($type = \null) + { + } + /** + * Displays the post categories in the feed. + * + * @since 0.71 + * + * @see get_the_category_rss() For better explanation. + * + * @param string $type Optional, default is the type returned by get_default_feed(). + */ + function the_category_rss($type = \null) + { + } + /** + * Displays the HTML type based on the blog setting. + * + * The two possible values are either 'xhtml' or 'html'. + * + * @since 2.2.0 + */ + function html_type_rss() + { + } + /** + * Displays the rss enclosure for the current post. + * + * Uses the global $post to check whether the post requires a password and if + * the user has the password for the post. If not then it will return before + * displaying. + * + * Also uses the function get_post_custom() to get the post's 'enclosure' + * metadata field and parses the value to display the enclosure(s). The + * enclosure(s) consist of enclosure HTML tag(s) with a URI and other + * attributes. + * + * @since 1.5.0 + */ + function rss_enclosure() + { + } + /** + * Displays the atom enclosure for the current post. + * + * Uses the global $post to check whether the post requires a password and if + * the user has the password for the post. If not then it will return before + * displaying. + * + * Also uses the function get_post_custom() to get the post's 'enclosure' + * metadata field and parses the value to display the enclosure(s). The + * enclosure(s) consist of link HTML tag(s) with a URI and other attributes. + * + * @since 2.2.0 + */ + function atom_enclosure() + { + } + /** + * Determines the type of a string of data with the data formatted. + * + * Tell whether the type is text, HTML, or XHTML, per RFC 4287 section 3.1. + * + * In the case of WordPress, text is defined as containing no markup, + * XHTML is defined as "well formed", and HTML as tag soup (i.e., the rest). + * + * Container div tags are added to XHTML values, per section 3.1.1.3. + * + * @link http://www.atomenabled.org/developers/syndication/atom-format-spec.php#rfc.section.3.1 + * + * @since 2.5.0 + * + * @param string $data Input string. + * @return array array(type, value) + */ + function prep_atom_text_construct($data) + { + } + /** + * Displays Site Icon in atom feeds. + * + * @since 4.3.0 + * + * @see get_site_icon_url() + */ + function atom_site_icon() + { + } + /** + * Displays Site Icon in RSS2. + * + * @since 4.3.0 + */ + function rss2_site_icon() + { + } + /** + * Returns the link for the currently displayed feed. + * + * @since 5.3.0 + * + * @return string Correct link for the atom:self element. + */ + function get_self_link() + { + } + /** + * Displays the link for the currently displayed feed in a XSS safe way. + * + * Generate a correct link for the atom:self element. + * + * @since 2.5.0 + */ + function self_link() + { + } + /** + * Gets the UTC time of the most recently modified post from WP_Query. + * + * If viewing a comment feed, the time of the most recently modified + * comment will be returned. + * + * @global WP_Query $wp_query WordPress Query object. + * + * @since 5.2.0 + * + * @param string $format Date format string to return the time in. + * @return string|false The time in requested format, or false on failure. + */ + function get_feed_build_date($format) + { + } + /** + * Returns the content type for specified feed type. + * + * @since 2.8.0 + * + * @param string $type Type of feed. Possible values include 'rss', rss2', 'atom', and 'rdf'. + */ + function feed_content_type($type = '') + { + } + /** + * Builds SimplePie object based on RSS or Atom feed from URL. + * + * @since 2.8.0 + * + * @param string|string[] $url URL of feed to retrieve. If an array of URLs, the feeds are merged + * using SimplePie's multifeed feature. + * See also {@link http://simplepie.org/wiki/faq/typical_multifeed_gotchas} + * @return SimplePie|WP_Error SimplePie object on success or WP_Error object on failure. + */ + function fetch_feed($url) + { + } + /** + * Main WordPress Formatting API. + * + * Handles many functions for formatting output. + * + * @package WordPress + */ + /** + * Replaces common plain text characters with formatted entities. + * + * Returns given text with transformations of quotes into smart quotes, apostrophes, + * dashes, ellipses, the trademark symbol, and the multiplication symbol. + * + * As an example, + * + * 'cause today's effort makes it worth tomorrow's "holiday" ... + * + * Becomes: + * + * ’cause today’s effort makes it worth tomorrow’s “holiday” … + * + * Code within certain HTML blocks are skipped. + * + * Do not use this function before the {@see 'init'} action hook; everything will break. + * + * @since 0.71 + * + * @global array $wp_cockneyreplace Array of formatted entities for certain common phrases. + * @global array $shortcode_tags + * + * @param string $text The text to be formatted. + * @param bool $reset Set to true for unit testing. Translated patterns will reset. + * @return string The string replaced with HTML entities. + */ + function wptexturize($text, $reset = \false) + { + } + /** + * Implements a logic tree to determine whether or not "7'." represents seven feet, + * then converts the special char into either a prime char or a closing quote char. + * + * @since 4.3.0 + * + * @param string $haystack The plain text to be searched. + * @param string $needle The character to search for such as ' or ". + * @param string $prime The prime char to use for replacement. + * @param string $open_quote The opening quote char. Opening quote replacement must be + * accomplished already. + * @param string $close_quote The closing quote char to use for replacement. + * @return string The $haystack value after primes and quotes replacements. + */ + function wptexturize_primes($haystack, $needle, $prime, $open_quote, $close_quote) + { + } + /** + * Searches for disabled element tags. Pushes element to stack on tag open + * and pops on tag close. + * + * Assumes first char of `$text` is tag opening and last char is tag closing. + * Assumes second char of `$text` is optionally `/` to indicate closing as in `</html>`. + * + * @since 2.9.0 + * @access private + * + * @param string $text Text to check. Must be a tag like `<html>` or `[shortcode]`. + * @param string[] $stack Array of open tag elements. + * @param string[] $disabled_elements Array of tag names to match against. Spaces are not allowed in tag names. + */ + function _wptexturize_pushpop_element($text, &$stack, $disabled_elements) + { + } + /** + * Replaces double line breaks with paragraph elements. + * + * A group of regex replaces used to identify text formatted with newlines and + * replace double line breaks with HTML paragraph tags. The remaining line breaks + * after conversion become `<br />` tags, unless `$br` is set to '0' or 'false'. + * + * @since 0.71 + * + * @param string $text The text which has to be formatted. + * @param bool $br Optional. If set, this will convert all remaining line breaks + * after paragraphing. Line breaks within `<script>`, `<style>`, + * and `<svg>` tags are not affected. Default true. + * @return string Text which has been converted into correct paragraph tags. + */ + function wpautop($text, $br = \true) + { + } + /** + * Separates HTML elements and comments from the text. + * + * @since 4.2.4 + * + * @param string $input The text which has to be formatted. + * @return string[] Array of the formatted text. + */ + function wp_html_split($input) + { + } + /** + * Retrieves the regular expression for an HTML element. + * + * @since 4.4.0 + * + * @return string The regular expression + */ + function get_html_split_regex() + { + } + /** + * Retrieves the combined regular expression for HTML and shortcodes. + * + * @access private + * @ignore + * @internal This function will be removed in 4.5.0 per Shortcode API Roadmap. + * @since 4.4.0 + * + * @param string $shortcode_regex Optional. The result from _get_wptexturize_shortcode_regex(). + * @return string The regular expression + */ + function _get_wptexturize_split_regex($shortcode_regex = '') + { + } + /** + * Retrieves the regular expression for shortcodes. + * + * @access private + * @ignore + * @since 4.4.0 + * + * @param string[] $tagnames Array of shortcodes to find. + * @return string The regular expression + */ + function _get_wptexturize_shortcode_regex($tagnames) + { + } + /** + * Replaces characters or phrases within HTML elements only. + * + * @since 4.2.3 + * + * @param string $haystack The text which has to be formatted. + * @param array $replace_pairs In the form array('from' => 'to', ...). + * @return string The formatted text. + */ + function wp_replace_in_html_tags($haystack, $replace_pairs) + { + } + /** + * Newline preservation help function for wpautop(). + * + * @since 3.1.0 + * @access private + * + * @param array $matches preg_replace_callback matches array + * @return string + */ + function _autop_newline_preservation_helper($matches) + { + } + /** + * Don't auto-p wrap shortcodes that stand alone. + * + * Ensures that shortcodes are not wrapped in `<p>...</p>`. + * + * @since 2.9.0 + * + * @global array $shortcode_tags + * + * @param string $text The content. + * @return string The filtered content. + */ + function shortcode_unautop($text) + { + } + /** + * Checks to see if a string is utf8 encoded. + * + * NOTE: This function checks for 5-Byte sequences, UTF8 + * has Bytes Sequences with a maximum length of 4. + * + * @author bmorel at ssi dot fr (modified) + * @since 1.2.1 + * + * @param string $str The string to be checked + * @return bool True if $str fits a UTF-8 model, false otherwise. + */ + function seems_utf8($str) + { + } + /** + * Converts a number of special characters into their HTML entities. + * + * Specifically deals with: `&`, `<`, `>`, `"`, and `'`. + * + * `$quote_style` can be set to ENT_COMPAT to encode `"` to + * `"`, or ENT_QUOTES to do both. Default is ENT_NOQUOTES where no quotes are encoded. + * + * @since 1.2.2 + * @since 5.5.0 `$quote_style` also accepts `ENT_XML1`. + * @access private + * + * @param string $string The text which is to be encoded. + * @param int|string $quote_style Optional. Converts double quotes if set to ENT_COMPAT, + * both single and double if set to ENT_QUOTES or none if set to ENT_NOQUOTES. + * Converts single and double quotes, as well as converting HTML + * named entities (that are not also XML named entities) to their + * code points if set to ENT_XML1. Also compatible with old values; + * converting single quotes if set to 'single', + * double if set to 'double' or both if otherwise set. + * Default is ENT_NOQUOTES. + * @param false|string $charset Optional. The character encoding of the string. Default false. + * @param bool $double_encode Optional. Whether to encode existing HTML entities. Default false. + * @return string The encoded text with HTML entities. + */ + function _wp_specialchars($string, $quote_style = \ENT_NOQUOTES, $charset = \false, $double_encode = \false) + { + } + /** + * Converts a number of HTML entities into their special characters. + * + * Specifically deals with: `&`, `<`, `>`, `"`, and `'`. + * + * `$quote_style` can be set to ENT_COMPAT to decode `"` entities, + * or ENT_QUOTES to do both `"` and `'`. Default is ENT_NOQUOTES where no quotes are decoded. + * + * @since 2.8.0 + * + * @param string $string The text which is to be decoded. + * @param string|int $quote_style Optional. Converts double quotes if set to ENT_COMPAT, + * both single and double if set to ENT_QUOTES or + * none if set to ENT_NOQUOTES. + * Also compatible with old _wp_specialchars() values; + * converting single quotes if set to 'single', + * double if set to 'double' or both if otherwise set. + * Default is ENT_NOQUOTES. + * @return string The decoded text without HTML entities. + */ + function wp_specialchars_decode($string, $quote_style = \ENT_NOQUOTES) + { + } + /** + * Checks for invalid UTF8 in a string. + * + * @since 2.8.0 + * + * @param string $string The text which is to be checked. + * @param bool $strip Optional. Whether to attempt to strip out invalid UTF8. Default false. + * @return string The checked text. + */ + function wp_check_invalid_utf8($string, $strip = \false) + { + } + /** + * Encodes the Unicode values to be used in the URI. + * + * @since 1.5.0 + * @since 5.8.3 Added the `encode_ascii_characters` parameter. + * + * @param string $utf8_string String to encode. + * @param int $length Max length of the string + * @param bool $encode_ascii_characters Whether to encode ascii characters such as < " ' + * @return string String with Unicode encoded for URI. + */ + function utf8_uri_encode($utf8_string, $length = 0, $encode_ascii_characters = \false) + { + } + /** + * Converts all accent characters to ASCII characters. + * + * If there are no accent characters, then the string given is just returned. + * + * **Accent characters converted:** + * + * Currency signs: + * + * | Code | Glyph | Replacement | Description | + * | -------- | ----- | ----------- | ------------------- | + * | U+00A3 | £ | (empty) | British Pound sign | + * | U+20AC | € | E | Euro sign | + * + * Decompositions for Latin-1 Supplement: + * + * | Code | Glyph | Replacement | Description | + * | ------- | ----- | ----------- | -------------------------------------- | + * | U+00AA | ª | a | Feminine ordinal indicator | + * | U+00BA | º | o | Masculine ordinal indicator | + * | U+00C0 | À | A | Latin capital letter A with grave | + * | U+00C1 | Á | A | Latin capital letter A with acute | + * | U+00C2 |  | A | Latin capital letter A with circumflex | + * | U+00C3 | à | A | Latin capital letter A with tilde | + * | U+00C4 | Ä | A | Latin capital letter A with diaeresis | + * | U+00C5 | Å | A | Latin capital letter A with ring above | + * | U+00C6 | Æ | AE | Latin capital letter AE | + * | U+00C7 | Ç | C | Latin capital letter C with cedilla | + * | U+00C8 | È | E | Latin capital letter E with grave | + * | U+00C9 | É | E | Latin capital letter E with acute | + * | U+00CA | Ê | E | Latin capital letter E with circumflex | + * | U+00CB | Ë | E | Latin capital letter E with diaeresis | + * | U+00CC | Ì | I | Latin capital letter I with grave | + * | U+00CD | Í | I | Latin capital letter I with acute | + * | U+00CE | Î | I | Latin capital letter I with circumflex | + * | U+00CF | Ï | I | Latin capital letter I with diaeresis | + * | U+00D0 | Ð | D | Latin capital letter Eth | + * | U+00D1 | Ñ | N | Latin capital letter N with tilde | + * | U+00D2 | Ò | O | Latin capital letter O with grave | + * | U+00D3 | Ó | O | Latin capital letter O with acute | + * | U+00D4 | Ô | O | Latin capital letter O with circumflex | + * | U+00D5 | Õ | O | Latin capital letter O with tilde | + * | U+00D6 | Ö | O | Latin capital letter O with diaeresis | + * | U+00D8 | Ø | O | Latin capital letter O with stroke | + * | U+00D9 | Ù | U | Latin capital letter U with grave | + * | U+00DA | Ú | U | Latin capital letter U with acute | + * | U+00DB | Û | U | Latin capital letter U with circumflex | + * | U+00DC | Ü | U | Latin capital letter U with diaeresis | + * | U+00DD | Ý | Y | Latin capital letter Y with acute | + * | U+00DE | Þ | TH | Latin capital letter Thorn | + * | U+00DF | ß | s | Latin small letter sharp s | + * | U+00E0 | à | a | Latin small letter a with grave | + * | U+00E1 | á | a | Latin small letter a with acute | + * | U+00E2 | â | a | Latin small letter a with circumflex | + * | U+00E3 | ã | a | Latin small letter a with tilde | + * | U+00E4 | ä | a | Latin small letter a with diaeresis | + * | U+00E5 | å | a | Latin small letter a with ring above | + * | U+00E6 | æ | ae | Latin small letter ae | + * | U+00E7 | ç | c | Latin small letter c with cedilla | + * | U+00E8 | è | e | Latin small letter e with grave | + * | U+00E9 | é | e | Latin small letter e with acute | + * | U+00EA | ê | e | Latin small letter e with circumflex | + * | U+00EB | ë | e | Latin small letter e with diaeresis | + * | U+00EC | ì | i | Latin small letter i with grave | + * | U+00ED | í | i | Latin small letter i with acute | + * | U+00EE | î | i | Latin small letter i with circumflex | + * | U+00EF | ï | i | Latin small letter i with diaeresis | + * | U+00F0 | ð | d | Latin small letter Eth | + * | U+00F1 | ñ | n | Latin small letter n with tilde | + * | U+00F2 | ò | o | Latin small letter o with grave | + * | U+00F3 | ó | o | Latin small letter o with acute | + * | U+00F4 | ô | o | Latin small letter o with circumflex | + * | U+00F5 | õ | o | Latin small letter o with tilde | + * | U+00F6 | ö | o | Latin small letter o with diaeresis | + * | U+00F8 | ø | o | Latin small letter o with stroke | + * | U+00F9 | ù | u | Latin small letter u with grave | + * | U+00FA | ú | u | Latin small letter u with acute | + * | U+00FB | û | u | Latin small letter u with circumflex | + * | U+00FC | ü | u | Latin small letter u with diaeresis | + * | U+00FD | ý | y | Latin small letter y with acute | + * | U+00FE | þ | th | Latin small letter Thorn | + * | U+00FF | ÿ | y | Latin small letter y with diaeresis | + * + * Decompositions for Latin Extended-A: + * + * | Code | Glyph | Replacement | Description | + * | ------- | ----- | ----------- | ------------------------------------------------- | + * | U+0100 | Ā | A | Latin capital letter A with macron | + * | U+0101 | ā | a | Latin small letter a with macron | + * | U+0102 | Ă | A | Latin capital letter A with breve | + * | U+0103 | ă | a | Latin small letter a with breve | + * | U+0104 | Ą | A | Latin capital letter A with ogonek | + * | U+0105 | ą | a | Latin small letter a with ogonek | + * | U+01006 | Ć | C | Latin capital letter C with acute | + * | U+0107 | ć | c | Latin small letter c with acute | + * | U+0108 | Ĉ | C | Latin capital letter C with circumflex | + * | U+0109 | ĉ | c | Latin small letter c with circumflex | + * | U+010A | Ċ | C | Latin capital letter C with dot above | + * | U+010B | ċ | c | Latin small letter c with dot above | + * | U+010C | Č | C | Latin capital letter C with caron | + * | U+010D | č | c | Latin small letter c with caron | + * | U+010E | Ď | D | Latin capital letter D with caron | + * | U+010F | ď | d | Latin small letter d with caron | + * | U+0110 | Đ | D | Latin capital letter D with stroke | + * | U+0111 | đ | d | Latin small letter d with stroke | + * | U+0112 | Ē | E | Latin capital letter E with macron | + * | U+0113 | ē | e | Latin small letter e with macron | + * | U+0114 | Ĕ | E | Latin capital letter E with breve | + * | U+0115 | ĕ | e | Latin small letter e with breve | + * | U+0116 | Ė | E | Latin capital letter E with dot above | + * | U+0117 | ė | e | Latin small letter e with dot above | + * | U+0118 | Ę | E | Latin capital letter E with ogonek | + * | U+0119 | ę | e | Latin small letter e with ogonek | + * | U+011A | Ě | E | Latin capital letter E with caron | + * | U+011B | ě | e | Latin small letter e with caron | + * | U+011C | Ĝ | G | Latin capital letter G with circumflex | + * | U+011D | ĝ | g | Latin small letter g with circumflex | + * | U+011E | Ğ | G | Latin capital letter G with breve | + * | U+011F | ğ | g | Latin small letter g with breve | + * | U+0120 | Ġ | G | Latin capital letter G with dot above | + * | U+0121 | ġ | g | Latin small letter g with dot above | + * | U+0122 | Ģ | G | Latin capital letter G with cedilla | + * | U+0123 | ģ | g | Latin small letter g with cedilla | + * | U+0124 | Ĥ | H | Latin capital letter H with circumflex | + * | U+0125 | ĥ | h | Latin small letter h with circumflex | + * | U+0126 | Ħ | H | Latin capital letter H with stroke | + * | U+0127 | ħ | h | Latin small letter h with stroke | + * | U+0128 | Ĩ | I | Latin capital letter I with tilde | + * | U+0129 | ĩ | i | Latin small letter i with tilde | + * | U+012A | Ī | I | Latin capital letter I with macron | + * | U+012B | ī | i | Latin small letter i with macron | + * | U+012C | Ĭ | I | Latin capital letter I with breve | + * | U+012D | ĭ | i | Latin small letter i with breve | + * | U+012E | Į | I | Latin capital letter I with ogonek | + * | U+012F | į | i | Latin small letter i with ogonek | + * | U+0130 | İ | I | Latin capital letter I with dot above | + * | U+0131 | ı | i | Latin small letter dotless i | + * | U+0132 | IJ | IJ | Latin capital ligature IJ | + * | U+0133 | ij | ij | Latin small ligature ij | + * | U+0134 | Ĵ | J | Latin capital letter J with circumflex | + * | U+0135 | ĵ | j | Latin small letter j with circumflex | + * | U+0136 | Ķ | K | Latin capital letter K with cedilla | + * | U+0137 | ķ | k | Latin small letter k with cedilla | + * | U+0138 | ĸ | k | Latin small letter Kra | + * | U+0139 | Ĺ | L | Latin capital letter L with acute | + * | U+013A | ĺ | l | Latin small letter l with acute | + * | U+013B | Ļ | L | Latin capital letter L with cedilla | + * | U+013C | ļ | l | Latin small letter l with cedilla | + * | U+013D | Ľ | L | Latin capital letter L with caron | + * | U+013E | ľ | l | Latin small letter l with caron | + * | U+013F | Ŀ | L | Latin capital letter L with middle dot | + * | U+0140 | ŀ | l | Latin small letter l with middle dot | + * | U+0141 | Ł | L | Latin capital letter L with stroke | + * | U+0142 | ł | l | Latin small letter l with stroke | + * | U+0143 | Ń | N | Latin capital letter N with acute | + * | U+0144 | ń | n | Latin small letter N with acute | + * | U+0145 | Ņ | N | Latin capital letter N with cedilla | + * | U+0146 | ņ | n | Latin small letter n with cedilla | + * | U+0147 | Ň | N | Latin capital letter N with caron | + * | U+0148 | ň | n | Latin small letter n with caron | + * | U+0149 | ʼn | n | Latin small letter n preceded by apostrophe | + * | U+014A | Ŋ | N | Latin capital letter Eng | + * | U+014B | ŋ | n | Latin small letter Eng | + * | U+014C | Ō | O | Latin capital letter O with macron | + * | U+014D | ō | o | Latin small letter o with macron | + * | U+014E | Ŏ | O | Latin capital letter O with breve | + * | U+014F | ŏ | o | Latin small letter o with breve | + * | U+0150 | Ő | O | Latin capital letter O with double acute | + * | U+0151 | ő | o | Latin small letter o with double acute | + * | U+0152 | Œ | OE | Latin capital ligature OE | + * | U+0153 | œ | oe | Latin small ligature oe | + * | U+0154 | Ŕ | R | Latin capital letter R with acute | + * | U+0155 | ŕ | r | Latin small letter r with acute | + * | U+0156 | Ŗ | R | Latin capital letter R with cedilla | + * | U+0157 | ŗ | r | Latin small letter r with cedilla | + * | U+0158 | Ř | R | Latin capital letter R with caron | + * | U+0159 | ř | r | Latin small letter r with caron | + * | U+015A | Ś | S | Latin capital letter S with acute | + * | U+015B | ś | s | Latin small letter s with acute | + * | U+015C | Ŝ | S | Latin capital letter S with circumflex | + * | U+015D | ŝ | s | Latin small letter s with circumflex | + * | U+015E | Ş | S | Latin capital letter S with cedilla | + * | U+015F | ş | s | Latin small letter s with cedilla | + * | U+0160 | Š | S | Latin capital letter S with caron | + * | U+0161 | š | s | Latin small letter s with caron | + * | U+0162 | Ţ | T | Latin capital letter T with cedilla | + * | U+0163 | ţ | t | Latin small letter t with cedilla | + * | U+0164 | Ť | T | Latin capital letter T with caron | + * | U+0165 | ť | t | Latin small letter t with caron | + * | U+0166 | Ŧ | T | Latin capital letter T with stroke | + * | U+0167 | ŧ | t | Latin small letter t with stroke | + * | U+0168 | Ũ | U | Latin capital letter U with tilde | + * | U+0169 | ũ | u | Latin small letter u with tilde | + * | U+016A | Ū | U | Latin capital letter U with macron | + * | U+016B | ū | u | Latin small letter u with macron | + * | U+016C | Ŭ | U | Latin capital letter U with breve | + * | U+016D | ŭ | u | Latin small letter u with breve | + * | U+016E | Ů | U | Latin capital letter U with ring above | + * | U+016F | ů | u | Latin small letter u with ring above | + * | U+0170 | Ű | U | Latin capital letter U with double acute | + * | U+0171 | ű | u | Latin small letter u with double acute | + * | U+0172 | Ų | U | Latin capital letter U with ogonek | + * | U+0173 | ų | u | Latin small letter u with ogonek | + * | U+0174 | Ŵ | W | Latin capital letter W with circumflex | + * | U+0175 | ŵ | w | Latin small letter w with circumflex | + * | U+0176 | Ŷ | Y | Latin capital letter Y with circumflex | + * | U+0177 | ŷ | y | Latin small letter y with circumflex | + * | U+0178 | Ÿ | Y | Latin capital letter Y with diaeresis | + * | U+0179 | Ź | Z | Latin capital letter Z with acute | + * | U+017A | ź | z | Latin small letter z with acute | + * | U+017B | Ż | Z | Latin capital letter Z with dot above | + * | U+017C | ż | z | Latin small letter z with dot above | + * | U+017D | Ž | Z | Latin capital letter Z with caron | + * | U+017E | ž | z | Latin small letter z with caron | + * | U+017F | ſ | s | Latin small letter long s | + * | U+01A0 | Ơ | O | Latin capital letter O with horn | + * | U+01A1 | ơ | o | Latin small letter o with horn | + * | U+01AF | Ư | U | Latin capital letter U with horn | + * | U+01B0 | ư | u | Latin small letter u with horn | + * | U+01CD | Ǎ | A | Latin capital letter A with caron | + * | U+01CE | ǎ | a | Latin small letter a with caron | + * | U+01CF | Ǐ | I | Latin capital letter I with caron | + * | U+01D0 | ǐ | i | Latin small letter i with caron | + * | U+01D1 | Ǒ | O | Latin capital letter O with caron | + * | U+01D2 | ǒ | o | Latin small letter o with caron | + * | U+01D3 | Ǔ | U | Latin capital letter U with caron | + * | U+01D4 | ǔ | u | Latin small letter u with caron | + * | U+01D5 | Ǖ | U | Latin capital letter U with diaeresis and macron | + * | U+01D6 | ǖ | u | Latin small letter u with diaeresis and macron | + * | U+01D7 | Ǘ | U | Latin capital letter U with diaeresis and acute | + * | U+01D8 | ǘ | u | Latin small letter u with diaeresis and acute | + * | U+01D9 | Ǚ | U | Latin capital letter U with diaeresis and caron | + * | U+01DA | ǚ | u | Latin small letter u with diaeresis and caron | + * | U+01DB | Ǜ | U | Latin capital letter U with diaeresis and grave | + * | U+01DC | ǜ | u | Latin small letter u with diaeresis and grave | + * + * Decompositions for Latin Extended-B: + * + * | Code | Glyph | Replacement | Description | + * | -------- | ----- | ----------- | ----------------------------------------- | + * | U+0218 | Ș | S | Latin capital letter S with comma below | + * | U+0219 | ș | s | Latin small letter s with comma below | + * | U+021A | Ț | T | Latin capital letter T with comma below | + * | U+021B | ț | t | Latin small letter t with comma below | + * + * Vowels with diacritic (Chinese, Hanyu Pinyin): + * + * | Code | Glyph | Replacement | Description | + * | -------- | ----- | ----------- | ----------------------------------------------------- | + * | U+0251 | ɑ | a | Latin small letter alpha | + * | U+1EA0 | Ạ | A | Latin capital letter A with dot below | + * | U+1EA1 | ạ | a | Latin small letter a with dot below | + * | U+1EA2 | Ả | A | Latin capital letter A with hook above | + * | U+1EA3 | ả | a | Latin small letter a with hook above | + * | U+1EA4 | Ấ | A | Latin capital letter A with circumflex and acute | + * | U+1EA5 | ấ | a | Latin small letter a with circumflex and acute | + * | U+1EA6 | Ầ | A | Latin capital letter A with circumflex and grave | + * | U+1EA7 | ầ | a | Latin small letter a with circumflex and grave | + * | U+1EA8 | Ẩ | A | Latin capital letter A with circumflex and hook above | + * | U+1EA9 | ẩ | a | Latin small letter a with circumflex and hook above | + * | U+1EAA | Ẫ | A | Latin capital letter A with circumflex and tilde | + * | U+1EAB | ẫ | a | Latin small letter a with circumflex and tilde | + * | U+1EA6 | Ậ | A | Latin capital letter A with circumflex and dot below | + * | U+1EAD | ậ | a | Latin small letter a with circumflex and dot below | + * | U+1EAE | Ắ | A | Latin capital letter A with breve and acute | + * | U+1EAF | ắ | a | Latin small letter a with breve and acute | + * | U+1EB0 | Ằ | A | Latin capital letter A with breve and grave | + * | U+1EB1 | ằ | a | Latin small letter a with breve and grave | + * | U+1EB2 | Ẳ | A | Latin capital letter A with breve and hook above | + * | U+1EB3 | ẳ | a | Latin small letter a with breve and hook above | + * | U+1EB4 | Ẵ | A | Latin capital letter A with breve and tilde | + * | U+1EB5 | ẵ | a | Latin small letter a with breve and tilde | + * | U+1EB6 | Ặ | A | Latin capital letter A with breve and dot below | + * | U+1EB7 | ặ | a | Latin small letter a with breve and dot below | + * | U+1EB8 | Ẹ | E | Latin capital letter E with dot below | + * | U+1EB9 | ẹ | e | Latin small letter e with dot below | + * | U+1EBA | Ẻ | E | Latin capital letter E with hook above | + * | U+1EBB | ẻ | e | Latin small letter e with hook above | + * | U+1EBC | Ẽ | E | Latin capital letter E with tilde | + * | U+1EBD | ẽ | e | Latin small letter e with tilde | + * | U+1EBE | Ế | E | Latin capital letter E with circumflex and acute | + * | U+1EBF | ế | e | Latin small letter e with circumflex and acute | + * | U+1EC0 | Ề | E | Latin capital letter E with circumflex and grave | + * | U+1EC1 | ề | e | Latin small letter e with circumflex and grave | + * | U+1EC2 | Ể | E | Latin capital letter E with circumflex and hook above | + * | U+1EC3 | ể | e | Latin small letter e with circumflex and hook above | + * | U+1EC4 | Ễ | E | Latin capital letter E with circumflex and tilde | + * | U+1EC5 | ễ | e | Latin small letter e with circumflex and tilde | + * | U+1EC6 | Ệ | E | Latin capital letter E with circumflex and dot below | + * | U+1EC7 | ệ | e | Latin small letter e with circumflex and dot below | + * | U+1EC8 | Ỉ | I | Latin capital letter I with hook above | + * | U+1EC9 | ỉ | i | Latin small letter i with hook above | + * | U+1ECA | Ị | I | Latin capital letter I with dot below | + * | U+1ECB | ị | i | Latin small letter i with dot below | + * | U+1ECC | Ọ | O | Latin capital letter O with dot below | + * | U+1ECD | ọ | o | Latin small letter o with dot below | + * | U+1ECE | Ỏ | O | Latin capital letter O with hook above | + * | U+1ECF | ỏ | o | Latin small letter o with hook above | + * | U+1ED0 | Ố | O | Latin capital letter O with circumflex and acute | + * | U+1ED1 | ố | o | Latin small letter o with circumflex and acute | + * | U+1ED2 | Ồ | O | Latin capital letter O with circumflex and grave | + * | U+1ED3 | ồ | o | Latin small letter o with circumflex and grave | + * | U+1ED4 | Ổ | O | Latin capital letter O with circumflex and hook above | + * | U+1ED5 | ổ | o | Latin small letter o with circumflex and hook above | + * | U+1ED6 | Ỗ | O | Latin capital letter O with circumflex and tilde | + * | U+1ED7 | ỗ | o | Latin small letter o with circumflex and tilde | + * | U+1ED8 | Ộ | O | Latin capital letter O with circumflex and dot below | + * | U+1ED9 | ộ | o | Latin small letter o with circumflex and dot below | + * | U+1EDA | Ớ | O | Latin capital letter O with horn and acute | + * | U+1EDB | ớ | o | Latin small letter o with horn and acute | + * | U+1EDC | Ờ | O | Latin capital letter O with horn and grave | + * | U+1EDD | ờ | o | Latin small letter o with horn and grave | + * | U+1EDE | Ở | O | Latin capital letter O with horn and hook above | + * | U+1EDF | ở | o | Latin small letter o with horn and hook above | + * | U+1EE0 | Ỡ | O | Latin capital letter O with horn and tilde | + * | U+1EE1 | ỡ | o | Latin small letter o with horn and tilde | + * | U+1EE2 | Ợ | O | Latin capital letter O with horn and dot below | + * | U+1EE3 | ợ | o | Latin small letter o with horn and dot below | + * | U+1EE4 | Ụ | U | Latin capital letter U with dot below | + * | U+1EE5 | ụ | u | Latin small letter u with dot below | + * | U+1EE6 | Ủ | U | Latin capital letter U with hook above | + * | U+1EE7 | ủ | u | Latin small letter u with hook above | + * | U+1EE8 | Ứ | U | Latin capital letter U with horn and acute | + * | U+1EE9 | ứ | u | Latin small letter u with horn and acute | + * | U+1EEA | Ừ | U | Latin capital letter U with horn and grave | + * | U+1EEB | ừ | u | Latin small letter u with horn and grave | + * | U+1EEC | Ử | U | Latin capital letter U with horn and hook above | + * | U+1EED | ử | u | Latin small letter u with horn and hook above | + * | U+1EEE | Ữ | U | Latin capital letter U with horn and tilde | + * | U+1EEF | ữ | u | Latin small letter u with horn and tilde | + * | U+1EF0 | Ự | U | Latin capital letter U with horn and dot below | + * | U+1EF1 | ự | u | Latin small letter u with horn and dot below | + * | U+1EF2 | Ỳ | Y | Latin capital letter Y with grave | + * | U+1EF3 | ỳ | y | Latin small letter y with grave | + * | U+1EF4 | Ỵ | Y | Latin capital letter Y with dot below | + * | U+1EF5 | ỵ | y | Latin small letter y with dot below | + * | U+1EF6 | Ỷ | Y | Latin capital letter Y with hook above | + * | U+1EF7 | ỷ | y | Latin small letter y with hook above | + * | U+1EF8 | Ỹ | Y | Latin capital letter Y with tilde | + * | U+1EF9 | ỹ | y | Latin small letter y with tilde | + * + * German (`de_DE`), German formal (`de_DE_formal`), German (Switzerland) formal (`de_CH`), + * German (Switzerland) informal (`de_CH_informal`), and German (Austria) (`de_AT`) locales: + * + * | Code | Glyph | Replacement | Description | + * | -------- | ----- | ----------- | --------------------------------------- | + * | U+00C4 | Ä | Ae | Latin capital letter A with diaeresis | + * | U+00E4 | ä | ae | Latin small letter a with diaeresis | + * | U+00D6 | Ö | Oe | Latin capital letter O with diaeresis | + * | U+00F6 | ö | oe | Latin small letter o with diaeresis | + * | U+00DC | Ü | Ue | Latin capital letter U with diaeresis | + * | U+00FC | ü | ue | Latin small letter u with diaeresis | + * | U+00DF | ß | ss | Latin small letter sharp s | + * + * Danish (`da_DK`) locale: + * + * | Code | Glyph | Replacement | Description | + * | -------- | ----- | ----------- | --------------------------------------- | + * | U+00C6 | Æ | Ae | Latin capital letter AE | + * | U+00E6 | æ | ae | Latin small letter ae | + * | U+00D8 | Ø | Oe | Latin capital letter O with stroke | + * | U+00F8 | ø | oe | Latin small letter o with stroke | + * | U+00C5 | Å | Aa | Latin capital letter A with ring above | + * | U+00E5 | å | aa | Latin small letter a with ring above | + * + * Catalan (`ca`) locale: + * + * | Code | Glyph | Replacement | Description | + * | -------- | ----- | ----------- | --------------------------------------- | + * | U+00B7 | l·l | ll | Flown dot (between two Ls) | + * + * Serbian (`sr_RS`) and Bosnian (`bs_BA`) locales: + * + * | Code | Glyph | Replacement | Description | + * | -------- | ----- | ----------- | --------------------------------------- | + * | U+0110 | Đ | DJ | Latin capital letter D with stroke | + * | U+0111 | đ | dj | Latin small letter d with stroke | + * + * @since 1.2.1 + * @since 4.6.0 Added locale support for `de_CH`, `de_CH_informal`, and `ca`. + * @since 4.7.0 Added locale support for `sr_RS`. + * @since 4.8.0 Added locale support for `bs_BA`. + * @since 5.7.0 Added locale support for `de_AT`. + * @since 6.0.0 Added the `$locale` parameter. + * @since 6.1.0 Added Unicode NFC encoding normalization support. + * + * @param string $string Text that might have accent characters. + * @param string $locale Optional. The locale to use for accent removal. Some character + * replacements depend on the locale being used (e.g. 'de_DE'). + * Defaults to the current locale. + * @return string Filtered string with replaced "nice" characters. + */ + function remove_accents($string, $locale = '') + { + } + /** + * Sanitizes a filename, replacing whitespace with dashes. + * + * Removes special characters that are illegal in filenames on certain + * operating systems and special characters requiring special escaping + * to manipulate at the command line. Replaces spaces and consecutive + * dashes with a single dash. Trims period, dash and underscore from beginning + * and end of filename. It is not guaranteed that this function will return a + * filename that is allowed to be uploaded. + * + * @since 2.1.0 + * + * @param string $filename The filename to be sanitized. + * @return string The sanitized filename. + */ + function sanitize_file_name($filename) + { + } + /** + * Sanitizes a username, stripping out unsafe characters. + * + * Removes tags, octets, entities, and if strict is enabled, will only keep + * alphanumeric, _, space, ., -, @. After sanitizing, it passes the username, + * raw username (the username in the parameter), and the value of $strict as + * parameters for the {@see 'sanitize_user'} filter. + * + * @since 2.0.0 + * + * @param string $username The username to be sanitized. + * @param bool $strict Optional. If set limits $username to specific characters. + * Default false. + * @return string The sanitized username, after passing through filters. + */ + function sanitize_user($username, $strict = \false) + { + } + /** + * Sanitizes a string key. + * + * Keys are used as internal identifiers. Lowercase alphanumeric characters, + * dashes, and underscores are allowed. + * + * @since 3.0.0 + * + * @param string $key String key. + * @return string Sanitized key. + */ + function sanitize_key($key) + { + } + /** + * Sanitizes a string into a slug, which can be used in URLs or HTML attributes. + * + * By default, converts accent characters to ASCII characters and further + * limits the output to alphanumeric characters, underscore (_) and dash (-) + * through the {@see 'sanitize_title'} filter. + * + * If `$title` is empty and `$fallback_title` is set, the latter will be used. + * + * @since 1.0.0 + * + * @param string $title The string to be sanitized. + * @param string $fallback_title Optional. A title to use if $title is empty. Default empty. + * @param string $context Optional. The operation for which the string is sanitized. + * When set to 'save', the string runs through remove_accents(). + * Default 'save'. + * @return string The sanitized string. + */ + function sanitize_title($title, $fallback_title = '', $context = 'save') + { + } + /** + * Sanitizes a title with the 'query' context. + * + * Used for querying the database for a value from URL. + * + * @since 3.1.0 + * + * @param string $title The string to be sanitized. + * @return string The sanitized string. + */ + function sanitize_title_for_query($title) + { + } + /** + * Sanitizes a title, replacing whitespace and a few other characters with dashes. + * + * Limits the output to alphanumeric characters, underscore (_) and dash (-). + * Whitespace becomes a dash. + * + * @since 1.2.0 + * + * @param string $title The title to be sanitized. + * @param string $raw_title Optional. Not used. Default empty. + * @param string $context Optional. The operation for which the string is sanitized. + * When set to 'save', additional entities are converted to hyphens + * or stripped entirely. Default 'display'. + * @return string The sanitized title. + */ + function sanitize_title_with_dashes($title, $raw_title = '', $context = 'display') + { + } + /** + * Ensures a string is a valid SQL 'order by' clause. + * + * Accepts one or more columns, with or without a sort order (ASC / DESC). + * e.g. 'column_1', 'column_1, column_2', 'column_1 ASC, column_2 DESC' etc. + * + * Also accepts 'RAND()'. + * + * @since 2.5.1 + * + * @param string $orderby Order by clause to be validated. + * @return string|false Returns $orderby if valid, false otherwise. + */ + function sanitize_sql_orderby($orderby) + { + } + /** + * Sanitizes an HTML classname to ensure it only contains valid characters. + * + * Strips the string down to A-Z,a-z,0-9,_,-. If this results in an empty + * string then it will return the alternative value supplied. + * + * @todo Expand to support the full range of CDATA that a class attribute can contain. + * + * @since 2.8.0 + * + * @param string $class The classname to be sanitized + * @param string $fallback Optional. The value to return if the sanitization ends up as an empty string. + * Defaults to an empty string. + * @return string The sanitized value + */ + function sanitize_html_class($class, $fallback = '') + { + } + /** + * Converts lone & characters into `&` (a.k.a. `&`) + * + * @since 0.71 + * + * @param string $content String of characters to be converted. + * @param string $deprecated Not used. + * @return string Converted string. + */ + function convert_chars($content, $deprecated = '') + { + } + /** + * Converts invalid Unicode references range to valid range. + * + * @since 4.3.0 + * + * @param string $content String with entities that need converting. + * @return string Converted string. + */ + function convert_invalid_entities($content) + { + } + /** + * Balances tags if forced to, or if the 'use_balanceTags' option is set to true. + * + * @since 0.71 + * + * @param string $text Text to be balanced + * @param bool $force If true, forces balancing, ignoring the value of the option. Default false. + * @return string Balanced text + */ + function balanceTags($text, $force = \false) + { + } + /** + * Balances tags of string using a modified stack. + * + * @since 2.0.4 + * @since 5.3.0 Improve accuracy and add support for custom element tags. + * + * @author Leonard Lin <leonard@acm.org> + * @license GPL + * @copyright November 4, 2001 + * @version 1.1 + * @todo Make better - change loop condition to $text in 1.2 + * @internal Modified by Scott Reilly (coffee2code) 02 Aug 2004 + * 1.1 Fixed handling of append/stack pop order of end text + * Added Cleaning Hooks + * 1.0 First Version + * + * @param string $text Text to be balanced. + * @return string Balanced text. + */ + function force_balance_tags($text) + { + } + /** + * Acts on text which is about to be edited. + * + * The $content is run through esc_textarea(), which uses htmlspecialchars() + * to convert special characters to HTML entities. If `$richedit` is set to true, + * it is simply a holder for the {@see 'format_to_edit'} filter. + * + * @since 0.71 + * @since 4.4.0 The `$richedit` parameter was renamed to `$rich_text` for clarity. + * + * @param string $content The text about to be edited. + * @param bool $rich_text Optional. Whether `$content` should be considered rich text, + * in which case it would not be passed through esc_textarea(). + * Default false. + * @return string The text after the filter (and possibly htmlspecialchars()) has been run. + */ + function format_to_edit($content, $rich_text = \false) + { + } + /** + * Add leading zeros when necessary. + * + * If you set the threshold to '4' and the number is '10', then you will get + * back '0010'. If you set the threshold to '4' and the number is '5000', then you + * will get back '5000'. + * + * Uses sprintf to append the amount of zeros based on the $threshold parameter + * and the size of the number. If the number is large enough, then no zeros will + * be appended. + * + * @since 0.71 + * + * @param int $number Number to append zeros to if not greater than threshold. + * @param int $threshold Digit places number needs to be to not have zeros added. + * @return string Adds leading zeros to number if needed. + */ + function zeroise($number, $threshold) + { + } + /** + * Adds backslashes before letters and before a number at the start of a string. + * + * @since 0.71 + * + * @param string $string Value to which backslashes will be added. + * @return string String with backslashes inserted. + */ + function backslashit($string) + { + } + /** + * Appends a trailing slash. + * + * Will remove trailing forward and backslashes if it exists already before adding + * a trailing forward slash. This prevents double slashing a string or path. + * + * The primary use of this is for paths and thus should be used for paths. It is + * not restricted to paths and offers no specific path support. + * + * @since 1.2.0 + * + * @param string $string What to add the trailing slash to. + * @return string String with trailing slash added. + */ + function trailingslashit($string) + { + } + /** + * Removes trailing forward slashes and backslashes if they exist. + * + * The primary use of this is for paths and thus should be used for paths. It is + * not restricted to paths and offers no specific path support. + * + * @since 2.2.0 + * + * @param string $string What to remove the trailing slashes from. + * @return string String without the trailing slashes. + */ + function untrailingslashit($string) + { + } + /** + * Adds slashes to a string or recursively adds slashes to strings within an array. + * + * @since 0.71 + * + * @param string|array $gpc String or array of data to slash. + * @return string|array Slashed `$gpc`. + * @phpstan-template T + * @phpstan-param T $gpc + * @phpstan-return T + */ + function addslashes_gpc($gpc) + { + } + /** + * Navigates through an array, object, or scalar, and removes slashes from the values. + * + * @since 2.0.0 + * + * @param mixed $value The value to be stripped. + * @return mixed Stripped value. + * @phpstan-template T + * @phpstan-param T $value + * @phpstan-return T + */ + function stripslashes_deep($value) + { + } + /** + * Callback function for `stripslashes_deep()` which strips slashes from strings. + * + * @since 4.4.0 + * + * @param mixed $value The array or string to be stripped. + * @return mixed The stripped value. + */ + function stripslashes_from_strings_only($value) + { + } + /** + * Navigates through an array, object, or scalar, and encodes the values to be used in a URL. + * + * @since 2.2.0 + * + * @param mixed $value The array or string to be encoded. + * @return mixed The encoded value. + * @phpstan-template T + * @phpstan-param T $value + * @phpstan-return T + */ + function urlencode_deep($value) + { + } + /** + * Navigates through an array, object, or scalar, and raw-encodes the values to be used in a URL. + * + * @since 3.4.0 + * + * @param mixed $value The array or string to be encoded. + * @return mixed The encoded value. + * @phpstan-template T + * @phpstan-param T $value + * @phpstan-return T + */ + function rawurlencode_deep($value) + { + } + /** + * Navigates through an array, object, or scalar, and decodes URL-encoded values + * + * @since 4.4.0 + * + * @param mixed $value The array or string to be decoded. + * @return mixed The decoded value. + * @phpstan-template T + * @phpstan-param T $value + * @phpstan-return T + */ + function urldecode_deep($value) + { + } + /** + * Converts email addresses characters to HTML entities to block spam bots. + * + * @since 0.71 + * + * @param string $email_address Email address. + * @param int $hex_encoding Optional. Set to 1 to enable hex encoding. + * @return string Converted email address. + */ + function antispambot($email_address, $hex_encoding = 0) + { + } + /** + * Callback to convert URI match to HTML A element. + * + * This function was backported from 2.5.0 to 2.3.2. Regex callback for make_clickable(). + * + * @since 2.3.2 + * @access private + * + * @param array $matches Single Regex Match. + * @return string HTML A element with URI address. + */ + function _make_url_clickable_cb($matches) + { + } + /** + * Callback to convert URL match to HTML A element. + * + * This function was backported from 2.5.0 to 2.3.2. Regex callback for make_clickable(). + * + * @since 2.3.2 + * @access private + * + * @param array $matches Single Regex Match. + * @return string HTML A element with URL address. + */ + function _make_web_ftp_clickable_cb($matches) + { + } + /** + * Callback to convert email address match to HTML A element. + * + * This function was backported from 2.5.0 to 2.3.2. Regex callback for make_clickable(). + * + * @since 2.3.2 + * @access private + * + * @param array $matches Single Regex Match. + * @return string HTML A element with email address. + */ + function _make_email_clickable_cb($matches) + { + } + /** + * Converts plaintext URI to HTML links. + * + * Converts URI, www and ftp, and email addresses. Finishes by fixing links + * within links. + * + * @since 0.71 + * + * @param string $text Content to convert URIs. + * @return string Content with converted URIs. + */ + function make_clickable($text) + { + } + /** + * Breaks a string into chunks by splitting at whitespace characters. + * + * The length of each returned chunk is as close to the specified length goal as possible, + * with the caveat that each chunk includes its trailing delimiter. + * Chunks longer than the goal are guaranteed to not have any inner whitespace. + * + * Joining the returned chunks with empty delimiters reconstructs the input string losslessly. + * + * Input string must have no null characters (or eventual transformations on output chunks must not care about null characters) + * + * _split_str_by_whitespace( "1234 67890 1234 67890a cd 1234 890 123456789 1234567890a 45678 1 3 5 7 90 ", 10 ) == + * array ( + * 0 => '1234 67890 ', // 11 characters: Perfect split. + * 1 => '1234 ', // 5 characters: '1234 67890a' was too long. + * 2 => '67890a cd ', // 10 characters: '67890a cd 1234' was too long. + * 3 => '1234 890 ', // 11 characters: Perfect split. + * 4 => '123456789 ', // 10 characters: '123456789 1234567890a' was too long. + * 5 => '1234567890a ', // 12 characters: Too long, but no inner whitespace on which to split. + * 6 => ' 45678 ', // 11 characters: Perfect split. + * 7 => '1 3 5 7 90 ', // 11 characters: End of $string. + * ); + * + * @since 3.4.0 + * @access private + * + * @param string $string The string to split. + * @param int $goal The desired chunk length. + * @return array Numeric array of chunks. + */ + function _split_str_by_whitespace($string, $goal) + { + } + /** + * Callback to add a rel attribute to HTML A element. + * + * Will remove already existing string before adding to prevent invalidating (X)HTML. + * + * @since 5.3.0 + * + * @param array $matches Single match. + * @param string $rel The rel attribute to add. + * @return string HTML A element with the added rel attribute. + */ + function wp_rel_callback($matches, $rel) + { + } + /** + * Adds `rel="nofollow"` string to all HTML A elements in content. + * + * @since 1.5.0 + * + * @param string $text Content that may contain HTML A elements. + * @return string Converted content. + */ + function wp_rel_nofollow($text) + { + } + /** + * Callback to add `rel="nofollow"` string to HTML A element. + * + * @since 2.3.0 + * @deprecated 5.3.0 Use wp_rel_callback() + * + * @param array $matches Single match. + * @return string HTML A Element with `rel="nofollow"`. + */ + function wp_rel_nofollow_callback($matches) + { + } + /** + * Adds `rel="nofollow ugc"` string to all HTML A elements in content. + * + * @since 5.3.0 + * + * @param string $text Content that may contain HTML A elements. + * @return string Converted content. + */ + function wp_rel_ugc($text) + { + } + /** + * Adds `rel="noopener"` to all HTML A elements that have a target. + * + * @since 5.1.0 + * @since 5.6.0 Removed 'noreferrer' relationship. + * + * @param string $text Content that may contain HTML A elements. + * @return string Converted content. + */ + function wp_targeted_link_rel($text) + { + } + /** + * Callback to add `rel="noopener"` string to HTML A element. + * + * Will not duplicate an existing 'noopener' value to avoid invalidating the HTML. + * + * @since 5.1.0 + * @since 5.6.0 Removed 'noreferrer' relationship. + * + * @param array $matches Single match. + * @return string HTML A Element with `rel="noopener"` in addition to any existing values. + */ + function wp_targeted_link_rel_callback($matches) + { + } + /** + * Adds all filters modifying the rel attribute of targeted links. + * + * @since 5.1.0 + */ + function wp_init_targeted_link_rel_filters() + { + } + /** + * Removes all filters modifying the rel attribute of targeted links. + * + * @since 5.1.0 + */ + function wp_remove_targeted_link_rel_filters() + { + } + /** + * Converts one smiley code to the icon graphic file equivalent. + * + * Callback handler for convert_smilies(). + * + * Looks up one smiley code in the $wpsmiliestrans global array and returns an + * `<img>` string for that smiley. + * + * @since 2.8.0 + * + * @global array $wpsmiliestrans + * + * @param array $matches Single match. Smiley code to convert to image. + * @return string Image string for smiley. + */ + function translate_smiley($matches) + { + } + /** + * Converts text equivalent of smilies to images. + * + * Will only convert smilies if the option 'use_smilies' is true and the global + * used in the function isn't empty. + * + * @since 0.71 + * + * @global string|array $wp_smiliessearch + * + * @param string $text Content to convert smilies from text. + * @return string Converted content with text smilies replaced with images. + */ + function convert_smilies($text) + { + } + /** + * Verifies that an email is valid. + * + * Does not grok i18n domains. Not RFC compliant. + * + * @since 0.71 + * + * @param string $email Email address to verify. + * @param bool $deprecated Deprecated. + * @return string|false Valid email address on success, false on failure. + */ + function is_email($email, $deprecated = \false) + { + } + /** + * Converts to ASCII from email subjects. + * + * @since 1.2.0 + * + * @param string $string Subject line. + * @return string Converted string to ASCII. + */ + function wp_iso_descrambler($string) + { + } + /** + * Helper function to convert hex encoded chars to ASCII. + * + * @since 3.1.0 + * @access private + * + * @param array $match The preg_replace_callback matches array. + * @return string Converted chars. + */ + function _wp_iso_convert($match) + { + } + /** + * Given a date in the timezone of the site, returns that date in UTC. + * + * Requires and returns a date in the Y-m-d H:i:s format. + * Return format can be overridden using the $format parameter. + * + * @since 1.2.0 + * + * @param string $string The date to be converted, in the timezone of the site. + * @param string $format The format string for the returned date. Default 'Y-m-d H:i:s'. + * @return string Formatted version of the date, in UTC. + */ + function get_gmt_from_date($string, $format = 'Y-m-d H:i:s') + { + } + /** + * Given a date in UTC or GMT timezone, returns that date in the timezone of the site. + * + * Requires a date in the Y-m-d H:i:s format. + * Default return format of 'Y-m-d H:i:s' can be overridden using the `$format` parameter. + * + * @since 1.2.0 + * + * @param string $string The date to be converted, in UTC or GMT timezone. + * @param string $format The format string for the returned date. Default 'Y-m-d H:i:s'. + * @return string Formatted version of the date, in the site's timezone. + */ + function get_date_from_gmt($string, $format = 'Y-m-d H:i:s') + { + } + /** + * Given an ISO 8601 timezone, returns its UTC offset in seconds. + * + * @since 1.5.0 + * + * @param string $timezone Either 'Z' for 0 offset or '±hhmm'. + * @return int|float The offset in seconds. + */ + function iso8601_timezone_to_offset($timezone) + { + } + /** + * Given an ISO 8601 (Ymd\TH:i:sO) date, returns a MySQL DateTime (Y-m-d H:i:s) format used by post_date[_gmt]. + * + * @since 1.5.0 + * + * @param string $date_string Date and time in ISO 8601 format {@link https://en.wikipedia.org/wiki/ISO_8601}. + * @param string $timezone Optional. If set to 'gmt' returns the result in UTC. Default 'user'. + * @return string|false The date and time in MySQL DateTime format - Y-m-d H:i:s, or false on failure. + */ + function iso8601_to_datetime($date_string, $timezone = 'user') + { + } + /** + * Strips out all characters that are not allowable in an email. + * + * @since 1.5.0 + * + * @param string $email Email address to filter. + * @return string Filtered email address. + */ + function sanitize_email($email) + { + } + /** + * Determines the difference between two timestamps. + * + * The difference is returned in a human readable format such as "1 hour", + * "5 mins", "2 days". + * + * @since 1.5.0 + * @since 5.3.0 Added support for showing a difference in seconds. + * + * @param int $from Unix timestamp from which the difference begins. + * @param int $to Optional. Unix timestamp to end the time difference. Default becomes time() if not set. + * @return string Human readable time difference. + */ + function human_time_diff($from, $to = 0) + { + } + /** + * Generates an excerpt from the content, if needed. + * + * Returns a maximum of 55 words with an ellipsis appended if necessary. + * + * The 55 word limit can be modified by plugins/themes using the {@see 'excerpt_length'} filter + * The ' […]' string can be modified by plugins/themes using the {@see 'excerpt_more'} filter + * + * @since 1.5.0 + * @since 5.2.0 Added the `$post` parameter. + * + * @param string $text Optional. The excerpt. If set to empty, an excerpt is generated. + * @param WP_Post|object|int $post Optional. WP_Post instance or Post ID/object. Default null. + * @return string The excerpt. + */ + function wp_trim_excerpt($text = '', $post = \null) + { + } + /** + * Trims text to a certain number of words. + * + * This function is localized. For languages that count 'words' by the individual + * character (such as East Asian languages), the $num_words argument will apply + * to the number of individual characters. + * + * @since 3.3.0 + * + * @param string $text Text to trim. + * @param int $num_words Number of words. Default 55. + * @param string $more Optional. What to append if $text needs to be trimmed. Default '…'. + * @return string Trimmed text. + */ + function wp_trim_words($text, $num_words = 55, $more = \null) + { + } + /** + * Converts named entities into numbered entities. + * + * @since 1.5.1 + * + * @param string $text The text within which entities will be converted. + * @return string Text with converted entities. + */ + function ent2ncr($text) + { + } + /** + * Formats text for the editor. + * + * Generally the browsers treat everything inside a textarea as text, but + * it is still a good idea to HTML entity encode `<`, `>` and `&` in the content. + * + * The filter {@see 'format_for_editor'} is applied here. If `$text` is empty the + * filter will be applied to an empty string. + * + * @since 4.3.0 + * + * @see _WP_Editors::editor() + * + * @param string $text The text to be formatted. + * @param string $default_editor The default editor for the current user. + * It is usually either 'html' or 'tinymce'. + * @return string The formatted text after filter is applied. + */ + function format_for_editor($text, $default_editor = \null) + { + } + /** + * Performs a deep string replace operation to ensure the values in $search are no longer present. + * + * Repeats the replacement operation until it no longer replaces anything so as to remove "nested" values + * e.g. $subject = '%0%0%0DDD', $search ='%0D', $result ='' rather than the '%0%0DD' that + * str_replace would return + * + * @since 2.8.1 + * @access private + * + * @param string|array $search The value being searched for, otherwise known as the needle. + * An array may be used to designate multiple needles. + * @param string $subject The string being searched and replaced on, otherwise known as the haystack. + * @return string The string with the replaced values. + */ + function _deep_replace($search, $subject) + { + } + /** + * Escapes data for use in a MySQL query. + * + * Usually you should prepare queries using wpdb::prepare(). + * Sometimes, spot-escaping is required or useful. One example + * is preparing an array for use in an IN clause. + * + * NOTE: Since 4.8.3, '%' characters will be replaced with a placeholder string, + * this prevents certain SQLi attacks from taking place. This change in behaviour + * may cause issues for code that expects the return value of esc_sql() to be useable + * for other purposes. + * + * @since 2.8.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string|array $data Unescaped data. + * @return string|array Escaped data, in the same type as supplied. + */ + function esc_sql($data) + { + } + /** + * Checks and cleans a URL. + * + * A number of characters are removed from the URL. If the URL is for displaying + * (the default behaviour) ampersands are also replaced. The {@see 'clean_url'} filter + * is applied to the returned cleaned URL. + * + * @since 2.8.0 + * + * @param string $url The URL to be cleaned. + * @param string[] $protocols Optional. An array of acceptable protocols. + * Defaults to return value of wp_allowed_protocols(). + * @param string $_context Private. Use sanitize_url() for database usage. + * @return string The cleaned URL after the {@see 'clean_url'} filter is applied. + * An empty string is returned if `$url` specifies a protocol other than + * those in `$protocols`, or if `$url` contains an empty string. + */ + function esc_url($url, $protocols = \null, $_context = 'display') + { + } + /** + * Sanitizes a URL for database or redirect usage. + * + * This function is an alias for sanitize_url(). + * + * @since 2.8.0 + * @since 6.1.0 Turned into an alias for sanitize_url(). + * + * @see sanitize_url() + * + * @param string $url The URL to be cleaned. + * @param string[] $protocols Optional. An array of acceptable protocols. + * Defaults to return value of wp_allowed_protocols(). + * @return string The cleaned URL after sanitize_url() is run. + */ + function esc_url_raw($url, $protocols = \null) + { + } + /** + * Sanitizes a URL for database or redirect usage. + * + * @since 2.3.1 + * @since 2.8.0 Deprecated in favor of esc_url_raw(). + * @since 5.9.0 Restored (un-deprecated). + * + * @see esc_url() + * + * @param string $url The URL to be cleaned. + * @param string[] $protocols Optional. An array of acceptable protocols. + * Defaults to return value of wp_allowed_protocols(). + * @return string The cleaned URL after esc_url() is run with the 'db' context. + */ + function sanitize_url($url, $protocols = \null) + { + } + /** + * Converts entities, while preserving already-encoded entities. + * + * @link https://www.php.net/htmlentities Borrowed from the PHP Manual user notes. + * + * @since 1.2.2 + * + * @param string $myHTML The text to be converted. + * @return string Converted text. + */ + function htmlentities2($myHTML) + { + } + /** + * Escapes single quotes, `"`, `<`, `>`, `&`, and fixes line endings. + * + * Escapes text strings for echoing in JS. It is intended to be used for inline JS + * (in a tag attribute, for example `onclick="..."`). Note that the strings have to + * be in single quotes. The {@see 'js_escape'} filter is also applied here. + * + * @since 2.8.0 + * + * @param string $text The text to be escaped. + * @return string Escaped text. + */ + function esc_js($text) + { + } + /** + * Escaping for HTML blocks. + * + * @since 2.8.0 + * + * @param string $text + * @return string + */ + function esc_html($text) + { + } + /** + * Escaping for HTML attributes. + * + * @since 2.8.0 + * + * @param string $text + * @return string + */ + function esc_attr($text) + { + } + /** + * Escaping for textarea values. + * + * @since 3.1.0 + * + * @param string $text + * @return string + */ + function esc_textarea($text) + { + } + /** + * Escaping for XML blocks. + * + * @since 5.5.0 + * + * @param string $text Text to escape. + * @return string Escaped text. + */ + function esc_xml($text) + { + } + /** + * Escapes an HTML tag name. + * + * @since 2.5.0 + * + * @param string $tag_name + * @return string + */ + function tag_escape($tag_name) + { + } + /** + * Converts full URL paths to absolute paths. + * + * Removes the http or https protocols and the domain. Keeps the path '/' at the + * beginning, so it isn't a true relative link, but from the web root base. + * + * @since 2.1.0 + * @since 4.1.0 Support was added for relative URLs. + * + * @param string $link Full URL path. + * @return string Absolute path. + */ + function wp_make_link_relative($link) + { + } + /** + * Sanitizes various option values based on the nature of the option. + * + * This is basically a switch statement which will pass $value through a number + * of functions depending on the $option. + * + * @since 2.0.5 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $option The name of the option. + * @param string $value The unsanitised value. + * @return string Sanitized value. + */ + function sanitize_option($option, $value) + { + } + /** + * Maps a function to all non-iterable elements of an array or an object. + * + * This is similar to `array_walk_recursive()` but acts upon objects too. + * + * @since 4.4.0 + * + * @param mixed $value The array, object, or scalar. + * @param callable $callback The function to map onto $value. + * @return mixed The value with the callback applied to all non-arrays and non-objects inside it. + */ + function map_deep($value, $callback) + { + } + /** + * Parses a string into variables to be stored in an array. + * + * @since 2.2.1 + * + * @param string $string The string to be parsed. + * @param array $array Variables will be stored in this array. + */ + function wp_parse_str($string, &$array) + { + } + /** + * Converts lone less than signs. + * + * KSES already converts lone greater than signs. + * + * @since 2.3.0 + * + * @param string $text Text to be converted. + * @return string Converted text. + */ + function wp_pre_kses_less_than($text) + { + } + /** + * Callback function used by preg_replace. + * + * @since 2.3.0 + * + * @param string[] $matches Populated by matches to preg_replace. + * @return string The text returned after esc_html if needed. + */ + function wp_pre_kses_less_than_callback($matches) + { + } + /** + * Removes non-allowable HTML from parsed block attribute values when filtering + * in the post context. + * + * @since 5.3.1 + * + * @param string $string Content to be run through KSES. + * @param array[]|string $allowed_html An array of allowed HTML elements + * and attributes, or a context name + * such as 'post'. + * @param string[] $allowed_protocols Array of allowed URL protocols. + * @return string Filtered text to run through KSES. + */ + function wp_pre_kses_block_attributes($string, $allowed_html, $allowed_protocols) + { + } + /** + * WordPress implementation of PHP sprintf() with filters. + * + * @since 2.5.0 + * @since 5.3.0 Formalized the existing and already documented `...$args` parameter + * by adding it to the function signature. + * + * @link https://www.php.net/sprintf + * + * @param string $pattern The string which formatted args are inserted. + * @param mixed ...$args Arguments to be formatted into the $pattern string. + * @return string The formatted string. + */ + function wp_sprintf($pattern, ...$args) + { + } + /** + * Localizes list items before the rest of the content. + * + * The '%l' must be at the first characters can then contain the rest of the + * content. The list items will have ', ', ', and', and ' and ' added depending + * on the amount of list items in the $args parameter. + * + * @since 2.5.0 + * + * @param string $pattern Content containing '%l' at the beginning. + * @param array $args List items to prepend to the content and replace '%l'. + * @return string Localized list items and rest of the content. + */ + function wp_sprintf_l($pattern, $args) + { + } + /** + * Safely extracts not more than the first $count characters from HTML string. + * + * UTF-8, tags and entities safe prefix extraction. Entities inside will *NOT* + * be counted as one character. For example & will be counted as 4, < as + * 3, etc. + * + * @since 2.5.0 + * + * @param string $str String to get the excerpt from. + * @param int $count Maximum number of characters to take. + * @param string $more Optional. What to append if $str needs to be trimmed. Defaults to empty string. + * @return string The excerpt. + */ + function wp_html_excerpt($str, $count, $more = \null) + { + } + /** + * Adds a base URL to relative links in passed content. + * + * By default it supports the 'src' and 'href' attributes. However this can be + * changed via the 3rd param. + * + * @since 2.7.0 + * + * @global string $_links_add_base + * + * @param string $content String to search for links in. + * @param string $base The base URL to prefix to links. + * @param array $attrs The attributes which should be processed. + * @return string The processed content. + */ + function links_add_base_url($content, $base, $attrs = array('src', 'href')) + { + } + /** + * Callback to add a base URL to relative links in passed content. + * + * @since 2.7.0 + * @access private + * + * @global string $_links_add_base + * + * @param string $m The matched link. + * @return string The processed link. + */ + function _links_add_base($m) + { + } + /** + * Adds a Target attribute to all links in passed content. + * + * This function by default only applies to `<a>` tags, however this can be + * modified by the 3rd param. + * + * *NOTE:* Any current target attributed will be stripped and replaced. + * + * @since 2.7.0 + * + * @global string $_links_add_target + * + * @param string $content String to search for links in. + * @param string $target The Target to add to the links. + * @param string[] $tags An array of tags to apply to. + * @return string The processed content. + */ + function links_add_target($content, $target = '_blank', $tags = array('a')) + { + } + /** + * Callback to add a target attribute to all links in passed content. + * + * @since 2.7.0 + * @access private + * + * @global string $_links_add_target + * + * @param string $m The matched link. + * @return string The processed link. + */ + function _links_add_target($m) + { + } + /** + * Normalizes EOL characters and strips duplicate whitespace. + * + * @since 2.7.0 + * + * @param string $str The string to normalize. + * @return string The normalized string. + */ + function normalize_whitespace($str) + { + } + /** + * Properly strips all HTML tags including script and style + * + * This differs from strip_tags() because it removes the contents of + * the `<script>` and `<style>` tags. E.g. `strip_tags( '<script>something</script>' )` + * will return 'something'. wp_strip_all_tags will return '' + * + * @since 2.9.0 + * + * @param string $string String containing HTML tags + * @param bool $remove_breaks Optional. Whether to remove left over line breaks and white space chars + * @return string The processed string. + */ + function wp_strip_all_tags($string, $remove_breaks = \false) + { + } + /** + * Sanitizes a string from user input or from the database. + * + * - Checks for invalid UTF-8, + * - Converts single `<` characters to entities + * - Strips all tags + * - Removes line breaks, tabs, and extra whitespace + * - Strips octets + * + * @since 2.9.0 + * + * @see sanitize_textarea_field() + * @see wp_check_invalid_utf8() + * @see wp_strip_all_tags() + * + * @param string $str String to sanitize. + * @return string Sanitized string. + */ + function sanitize_text_field($str) + { + } + /** + * Sanitizes a multiline string from user input or from the database. + * + * The function is like sanitize_text_field(), but preserves + * new lines (\n) and other whitespace, which are legitimate + * input in textarea elements. + * + * @see sanitize_text_field() + * + * @since 4.7.0 + * + * @param string $str String to sanitize. + * @return string Sanitized string. + */ + function sanitize_textarea_field($str) + { + } + /** + * Internal helper function to sanitize a string from user input or from the database. + * + * @since 4.7.0 + * @access private + * + * @param string $str String to sanitize. + * @param bool $keep_newlines Optional. Whether to keep newlines. Default: false. + * @return string Sanitized string. + */ + function _sanitize_text_fields($str, $keep_newlines = \false) + { + } + /** + * i18n-friendly version of basename(). + * + * @since 3.1.0 + * + * @param string $path A path. + * @param string $suffix If the filename ends in suffix this will also be cut off. + * @return string + */ + function wp_basename($path, $suffix = '') + { + } + // phpcs:disable WordPress.WP.CapitalPDangit.Misspelled, WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid -- 8-) + /** + * Forever eliminate "Wordpress" from the planet (or at least the little bit we can influence). + * + * Violating our coding standards for a good function name. + * + * @since 3.0.0 + * + * @param string $text The text to be modified. + * @return string The modified text. + */ + function capital_P_dangit($text) + { + } + // phpcs:enable + /** + * Sanitizes a mime type + * + * @since 3.1.3 + * + * @param string $mime_type Mime type. + * @return string Sanitized mime type. + */ + function sanitize_mime_type($mime_type) + { + } + /** + * Sanitizes space or carriage return separated URLs that are used to send trackbacks. + * + * @since 3.4.0 + * + * @param string $to_ping Space or carriage return separated URLs + * @return string URLs starting with the http or https protocol, separated by a carriage return. + */ + function sanitize_trackback_urls($to_ping) + { + } + /** + * Adds slashes to a string or recursively adds slashes to strings within an array. + * + * This should be used when preparing data for core API that expects slashed data. + * This should not be used to escape data going directly into an SQL query. + * + * @since 3.6.0 + * @since 5.5.0 Non-string values are left untouched. + * + * @param string|array $value String or array of data to slash. + * @return string|array Slashed `$value`, in the same type as supplied. + * @phpstan-template T + * @phpstan-param T $value + * @phpstan-return T + */ + function wp_slash($value) + { + } + /** + * Removes slashes from a string or recursively removes slashes from strings within an array. + * + * This should be used to remove slashes from data passed to core API that + * expects data to be unslashed. + * + * @since 3.6.0 + * + * @param string|array $value String or array of data to unslash. + * @return string|array Unslashed `$value`, in the same type as supplied. + * @phpstan-template T + * @phpstan-param T $value + * @phpstan-return T + */ + function wp_unslash($value) + { + } + /** + * Extracts and returns the first URL from passed content. + * + * @since 3.6.0 + * + * @param string $content A string which might contain a URL. + * @return string|false The found URL. + */ + function get_url_in_content($content) + { + } + /** + * Returns the regexp for common whitespace characters. + * + * By default, spaces include new lines, tabs, nbsp entities, and the UTF-8 nbsp. + * This is designed to replace the PCRE \s sequence. In ticket #22692, that + * sequence was found to be unreliable due to random inclusion of the A0 byte. + * + * @since 4.0.0 + * + * @return string The spaces regexp. + */ + function wp_spaces_regexp() + { + } + /** + * Prints the important emoji-related styles. + * + * @since 4.2.0 + */ + function print_emoji_styles() + { + } + /** + * Prints the inline Emoji detection script if it is not already printed. + * + * @since 4.2.0 + */ + function print_emoji_detection_script() + { + } + /** + * Prints inline Emoji detection script. + * + * @ignore + * @since 4.6.0 + * @access private + */ + function _print_emoji_detection_script() + { + } + /** + * Converts emoji characters to their equivalent HTML entity. + * + * This allows us to store emoji in a DB using the utf8 character set. + * + * @since 4.2.0 + * + * @param string $content The content to encode. + * @return string The encoded content. + */ + function wp_encode_emoji($content) + { + } + /** + * Converts emoji to a static img element. + * + * @since 4.2.0 + * + * @param string $text The content to encode. + * @return string The encoded content. + */ + function wp_staticize_emoji($text) + { + } + /** + * Converts emoji in emails into static images. + * + * @since 4.2.0 + * + * @param array $mail The email data array. + * @return array The email data array, with emoji in the message staticized. + */ + function wp_staticize_emoji_for_email($mail) + { + } + /** + * Returns arrays of emoji data. + * + * These arrays are automatically built from the regex in twemoji.js - if they need to be updated, + * you should update the regex there, then run the `npm run grunt precommit:emoji` job. + * + * @since 4.9.0 + * @access private + * + * @param string $type Optional. Which array type to return. Accepts 'partials' or 'entities', default 'entities'. + * @return array An array to match all emoji that WordPress recognises. + */ + function _wp_emoji_list($type = 'entities') + { + } + /** + * Shortens a URL, to be used as link text. + * + * @since 1.2.0 + * @since 4.4.0 Moved to wp-includes/formatting.php from wp-admin/includes/misc.php and added $length param. + * + * @param string $url URL to shorten. + * @param int $length Optional. Maximum length of the shortened URL. Default 35 characters. + * @return string Shortened URL. + */ + function url_shorten($url, $length = 35) + { + } + /** + * Sanitizes a hex color. + * + * Returns either '', a 3 or 6 digit hex color (with #), or nothing. + * For sanitizing values without a #, see sanitize_hex_color_no_hash(). + * + * @since 3.4.0 + * + * @param string $color + * @return string|void + */ + function sanitize_hex_color($color) + { + } + /** + * Sanitizes a hex color without a hash. Use sanitize_hex_color() when possible. + * + * Saving hex colors without a hash puts the burden of adding the hash on the + * UI, which makes it difficult to use or upgrade to other color types such as + * rgba, hsl, rgb, and HTML color names. + * + * Returns either '', a 3 or 6 digit hex color (without a #), or null. + * + * @since 3.4.0 + * + * @param string $color + * @return string|null + */ + function sanitize_hex_color_no_hash($color) + { + } + /** + * Ensures that any hex color is properly hashed. + * Otherwise, returns value untouched. + * + * This method should only be necessary if using sanitize_hex_color_no_hash(). + * + * @since 3.4.0 + * + * @param string $color + * @return string + */ + function maybe_hash_hex_color($color) + { + } + /** + * Converts given MySQL date string into a different format. + * + * - `$format` should be a PHP date format string. + * - 'U' and 'G' formats will return an integer sum of timestamp with timezone offset. + * - `$date` is expected to be local time in MySQL format (`Y-m-d H:i:s`). + * + * Historically UTC time could be passed to the function to produce Unix timestamp. + * + * If `$translate` is true then the given date and format string will + * be passed to `wp_date()` for translation. + * + * @since 0.71 + * + * @param string $format Format of the date to return. + * @param string $date Date string to convert. + * @param bool $translate Whether the return date should be translated. Default true. + * @return string|int|false Integer if `$format` is 'U' or 'G', string otherwise. + * False on failure. + */ + function mysql2date($format, $date, $translate = \true) + { + } + /** + * Retrieves the current time based on specified type. + * + * - The 'mysql' type will return the time in the format for MySQL DATETIME field. + * - The 'timestamp' or 'U' types will return the current timestamp or a sum of timestamp + * and timezone offset, depending on `$gmt`. + * - Other strings will be interpreted as PHP date formats (e.g. 'Y-m-d'). + * + * If `$gmt` is a truthy value then both types will use GMT time, otherwise the + * output is adjusted with the GMT offset for the site. + * + * @since 1.0.0 + * @since 5.3.0 Now returns an integer if `$type` is 'U'. Previously a string was returned. + * + * @param string $type Type of time to retrieve. Accepts 'mysql', 'timestamp', 'U', + * or PHP date format string (e.g. 'Y-m-d'). + * @param int|bool $gmt Optional. Whether to use GMT timezone. Default false. + * @return int|string Integer if `$type` is 'timestamp' or 'U', string otherwise. + */ + function current_time($type, $gmt = 0) + { + } + /** + * Retrieves the current time as an object using the site's timezone. + * + * @since 5.3.0 + * + * @return DateTimeImmutable Date and time object. + */ + function current_datetime() + { + } + /** + * Retrieves the timezone of the site as a string. + * + * Uses the `timezone_string` option to get a proper timezone name if available, + * otherwise falls back to a manual UTC ± offset. + * + * Example return values: + * + * - 'Europe/Rome' + * - 'America/North_Dakota/New_Salem' + * - 'UTC' + * - '-06:30' + * - '+00:00' + * - '+08:45' + * + * @since 5.3.0 + * + * @return string PHP timezone name or a ±HH:MM offset. + */ + function wp_timezone_string() + { + } + /** + * Retrieves the timezone of the site as a `DateTimeZone` object. + * + * Timezone can be based on a PHP timezone string or a ±HH:MM offset. + * + * @since 5.3.0 + * + * @return DateTimeZone Timezone object. + */ + function wp_timezone() + { + } + /** + * Retrieves the date in localized format, based on a sum of Unix timestamp and + * timezone offset in seconds. + * + * If the locale specifies the locale month and weekday, then the locale will + * take over the format for the date. If it isn't, then the date format string + * will be used instead. + * + * Note that due to the way WP typically generates a sum of timestamp and offset + * with `strtotime()`, it implies offset added at a _current_ time, not at the time + * the timestamp represents. Storing such timestamps or calculating them differently + * will lead to invalid output. + * + * @since 0.71 + * @since 5.3.0 Converted into a wrapper for wp_date(). + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @param string $format Format to display the date. + * @param int|bool $timestamp_with_offset Optional. A sum of Unix timestamp and timezone offset + * in seconds. Default false. + * @param bool $gmt Optional. Whether to use GMT timezone. Only applies + * if timestamp is not provided. Default false. + * @return string The date, translated if locale specifies it. + */ + function date_i18n($format, $timestamp_with_offset = \false, $gmt = \false) + { + } + /** + * Retrieves the date, in localized format. + * + * This is a newer function, intended to replace `date_i18n()` without legacy quirks in it. + * + * Note that, unlike `date_i18n()`, this function accepts a true Unix timestamp, not summed + * with timezone offset. + * + * @since 5.3.0 + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @param string $format PHP date format. + * @param int $timestamp Optional. Unix timestamp. Defaults to current time. + * @param DateTimeZone $timezone Optional. Timezone to output result in. Defaults to timezone + * from site settings. + * @return string|false The date, translated if locale specifies it. False on invalid timestamp input. + */ + function wp_date($format, $timestamp = \null, $timezone = \null) + { + } + /** + * Determines if the date should be declined. + * + * If the locale specifies that month names require a genitive case in certain + * formats (like 'j F Y'), the month name will be replaced with a correct form. + * + * @since 4.4.0 + * @since 5.4.0 The `$format` parameter was added. + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @param string $date Formatted date string. + * @param string $format Optional. Date format to check. Default empty string. + * @return string The date, declined if locale specifies it. + */ + function wp_maybe_decline_date($date, $format = '') + { + } + /** + * Converts float number to format based on the locale. + * + * @since 2.3.0 + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @param float $number The number to convert based on locale. + * @param int $decimals Optional. Precision of the number of decimal places. Default 0. + * @return string Converted number in string format. + */ + function number_format_i18n($number, $decimals = 0) + { + } + /** + * Converts a number of bytes to the largest unit the bytes will fit into. + * + * It is easier to read 1 KB than 1024 bytes and 1 MB than 1048576 bytes. Converts + * number of bytes to human readable number by taking the number of that unit + * that the bytes will go into it. Supports YB value. + * + * Please note that integers in PHP are limited to 32 bits, unless they are on + * 64 bit architecture, then they have 64 bit size. If you need to place the + * larger size then what PHP integer type will hold, then use a string. It will + * be converted to a double, which should always have 64 bit length. + * + * Technically the correct unit names for powers of 1024 are KiB, MiB etc. + * + * @since 2.3.0 + * @since 6.0.0 Support for PB, EB, ZB, and YB was added. + * + * @param int|string $bytes Number of bytes. Note max integer size for integers. + * @param int $decimals Optional. Precision of number of decimal places. Default 0. + * @return string|false Number string on success, false on failure. + */ + function size_format($bytes, $decimals = 0) + { + } + /** + * Converts a duration to human readable format. + * + * @since 5.1.0 + * + * @param string $duration Duration will be in string format (HH:ii:ss) OR (ii:ss), + * with a possible prepended negative sign (-). + * @return string|false A human readable duration string, false on failure. + */ + function human_readable_duration($duration = '') + { + } + /** + * Gets the week start and end from the datetime or date string from MySQL. + * + * @since 0.71 + * + * @param string $mysqlstring Date or datetime field type from MySQL. + * @param int|string $start_of_week Optional. Start of the week as an integer. Default empty string. + * @return int[] { + * Week start and end dates as Unix timestamps. + * + * @type int $start The week start date as a Unix timestamp. + * @type int $end The week end date as a Unix timestamp. + * } + * @phpstan-return array{ + * start: int, + * end: int, + * } + */ + function get_weekstartend($mysqlstring, $start_of_week = '') + { + } + /** + * Serializes data, if needed. + * + * @since 2.0.5 + * + * @param string|array|object $data Data that might be serialized. + * @return mixed A scalar data. + */ + function maybe_serialize($data) + { + } + /** + * Unserializes data only if it was serialized. + * + * @since 2.0.0 + * + * @param string $data Data that might be unserialized. + * @return mixed Unserialized data can be any type. + */ + function maybe_unserialize($data) + { + } + /** + * Checks value to find if it was serialized. + * + * If $data is not a string, then returned value will always be false. + * Serialized data is always a string. + * + * @since 2.0.5 + * @since 6.1.0 Added Enum support. + * + * @param string $data Value to check to see if was serialized. + * @param bool $strict Optional. Whether to be strict about the end of the string. Default true. + * @return bool False if not serialized and true if it was. + */ + function is_serialized($data, $strict = \true) + { + } + /** + * Checks whether serialized data is of string type. + * + * @since 2.0.5 + * + * @param string $data Serialized data. + * @return bool False if not a serialized string, true if it is. + */ + function is_serialized_string($data) + { + } + /** + * Retrieves post title from XMLRPC XML. + * + * If the title element is not part of the XML, then the default post title from + * the $post_default_title will be used instead. + * + * @since 0.71 + * + * @global string $post_default_title Default XML-RPC post title. + * + * @param string $content XMLRPC XML Request content + * @return string Post title + */ + function xmlrpc_getposttitle($content) + { + } + /** + * Retrieves the post category or categories from XMLRPC XML. + * + * If the category element is not found, then the default post category will be + * used. The return type then would be what $post_default_category. If the + * category is found, then it will always be an array. + * + * @since 0.71 + * + * @global string $post_default_category Default XML-RPC post category. + * + * @param string $content XMLRPC XML Request content + * @return string|array List of categories or category name. + */ + function xmlrpc_getpostcategory($content) + { + } + /** + * XMLRPC XML content without title and category elements. + * + * @since 0.71 + * + * @param string $content XML-RPC XML Request content. + * @return string XMLRPC XML Request content without title and category elements. + */ + function xmlrpc_removepostdata($content) + { + } + /** + * Uses RegEx to extract URLs from arbitrary content. + * + * @since 3.7.0 + * @since 6.0.0 Fixes support for HTML entities (Trac 30580). + * + * @param string $content Content to extract URLs from. + * @return string[] Array of URLs found in passed string. + */ + function wp_extract_urls($content) + { + } + /** + * Checks content for video and audio links to add as enclosures. + * + * Will not add enclosures that have already been added and will + * remove enclosures that are no longer in the post. This is called as + * pingbacks and trackbacks. + * + * @since 1.5.0 + * @since 5.3.0 The `$content` parameter was made optional, and the `$post` parameter was + * updated to accept a post ID or a WP_Post object. + * @since 5.6.0 The `$content` parameter is no longer optional, but passing `null` to skip it + * is still supported. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string|null $content Post content. If `null`, the `post_content` field from `$post` is used. + * @param int|WP_Post $post Post ID or post object. + * @return void|false Void on success, false if the post is not found. + */ + function do_enclose($content, $post) + { + } + /** + * Retrieves HTTP Headers from URL. + * + * @since 1.5.1 + * + * @param string $url URL to retrieve HTTP headers from. + * @param bool $deprecated Not Used. + * @return \Requests_Utility_CaseInsensitiveDictionary|false Headers on success, false on failure. + */ + function wp_get_http_headers($url, $deprecated = \false) + { + } + /** + * Determines whether the publish date of the current post in the loop is different + * from the publish date of the previous post in the loop. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 0.71 + * + * @global string $currentday The day of the current post in the loop. + * @global string $previousday The day of the previous post in the loop. + * + * @return int 1 when new day, 0 if not a new day. + */ + function is_new_day() + { + } + /** + * Builds URL query based on an associative and, or indexed array. + * + * This is a convenient function for easily building url queries. It sets the + * separator to '&' and uses _http_build_query() function. + * + * @since 2.3.0 + * + * @see _http_build_query() Used to build the query + * @link https://www.php.net/manual/en/function.http-build-query.php for more on what + * http_build_query() does. + * + * @param array $data URL-encode key/value pairs. + * @return string URL-encoded string. + */ + function build_query($data) + { + } + /** + * From php.net (modified by Mark Jaquith to behave like the native PHP5 function). + * + * @since 3.2.0 + * @access private + * + * @see https://www.php.net/manual/en/function.http-build-query.php + * + * @param array|object $data An array or object of data. Converted to array. + * @param string $prefix Optional. Numeric index. If set, start parameter numbering with it. + * Default null. + * @param string $sep Optional. Argument separator; defaults to 'arg_separator.output'. + * Default null. + * @param string $key Optional. Used to prefix key name. Default empty. + * @param bool $urlencode Optional. Whether to use urlencode() in the result. Default true. + * @return string The query string. + */ + function _http_build_query($data, $prefix = \null, $sep = \null, $key = '', $urlencode = \true) + { + } + /** + * Retrieves a modified URL query string. + * + * You can rebuild the URL and append query variables to the URL query by using this function. + * There are two ways to use this function; either a single key and value, or an associative array. + * + * Using a single key and value: + * + * add_query_arg( 'key', 'value', 'http://example.com' ); + * + * Using an associative array: + * + * add_query_arg( array( + * 'key1' => 'value1', + * 'key2' => 'value2', + * ), 'http://example.com' ); + * + * Omitting the URL from either use results in the current URL being used + * (the value of `$_SERVER['REQUEST_URI']`). + * + * Values are expected to be encoded appropriately with urlencode() or rawurlencode(). + * + * Setting any query variable's value to boolean false removes the key (see remove_query_arg()). + * + * Important: The return value of add_query_arg() is not escaped by default. Output should be + * late-escaped with esc_url() or similar to help prevent vulnerability to cross-site scripting + * (XSS) attacks. + * + * @since 1.5.0 + * @since 5.3.0 Formalized the existing and already documented parameters + * by adding `...$args` to the function signature. + * + * @param string|array $key Either a query variable key, or an associative array of query variables. + * @param string $value Optional. Either a query variable value, or a URL to act upon. + * @param string $url Optional. A URL to act upon. + * @return string New URL query string (unescaped). + */ + function add_query_arg(...$args) + { + } + /** + * Removes an item or items from a query string. + * + * @since 1.5.0 + * + * @param string|string[] $key Query key or keys to remove. + * @param false|string $query Optional. When false uses the current URL. Default false. + * @return string New URL query string. + */ + function remove_query_arg($key, $query = \false) + { + } + /** + * Returns an array of single-use query variable names that can be removed from a URL. + * + * @since 4.4.0 + * + * @return string[] An array of query variable names to remove from the URL. + */ + function wp_removable_query_args() + { + } + /** + * Walks the array while sanitizing the contents. + * + * @since 0.71 + * @since 5.5.0 Non-string values are left untouched. + * + * @param array $array Array to walk while sanitizing contents. + * @return array Sanitized $array. + */ + function add_magic_quotes($array) + { + } + /** + * HTTP request for URI to retrieve content. + * + * @since 1.5.1 + * + * @see wp_safe_remote_get() + * + * @param string $uri URI/URL of web page to retrieve. + * @return string|false HTTP content. False on failure. + */ + function wp_remote_fopen($uri) + { + } + /** + * Sets up the WordPress query. + * + * @since 2.0.0 + * + * @global WP $wp Current WordPress environment instance. + * @global WP_Query $wp_query WordPress Query object. + * @global WP_Query $wp_the_query Copy of the WordPress Query object. + * + * @param string|array $query_vars Default WP_Query arguments. + */ + function wp($query_vars = '') + { + } + /** + * Retrieves the description for the HTTP status. + * + * @since 2.3.0 + * @since 3.9.0 Added status codes 418, 428, 429, 431, and 511. + * @since 4.5.0 Added status codes 308, 421, and 451. + * @since 5.1.0 Added status code 103. + * + * @global array $wp_header_to_desc + * + * @param int $code HTTP status code. + * @return string Status description if found, an empty string otherwise. + */ + function get_status_header_desc($code) + { + } + /** + * Sets HTTP status header. + * + * @since 2.0.0 + * @since 4.4.0 Added the `$description` parameter. + * + * @see get_status_header_desc() + * + * @param int $code HTTP status code. + * @param string $description Optional. A custom description for the HTTP status. + */ + function status_header($code, $description = '') + { + } + /** + * Gets the header information to prevent caching. + * + * The several different headers cover the different ways cache prevention + * is handled by different browsers + * + * @since 2.8.0 + * + * @return array The associative array of header names and field values. + */ + function wp_get_nocache_headers() + { + } + /** + * Sets the headers to prevent caching for the different browsers. + * + * Different browsers support different nocache headers, so several + * headers must be sent so that all of them get the point that no + * caching should occur. + * + * @since 2.0.0 + * + * @see wp_get_nocache_headers() + */ + function nocache_headers() + { + } + /** + * Sets the headers for caching for 10 days with JavaScript content type. + * + * @since 2.1.0 + */ + function cache_javascript_headers() + { + } + /** + * Retrieves the number of database queries during the WordPress execution. + * + * @since 2.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return int Number of database queries. + */ + function get_num_queries() + { + } + /** + * Determines whether input is yes or no. + * + * Must be 'y' to be true. + * + * @since 1.0.0 + * + * @param string $yn Character string containing either 'y' (yes) or 'n' (no). + * @return bool True if 'y', false on anything else. + */ + function bool_from_yn($yn) + { + } + /** + * Loads the feed template from the use of an action hook. + * + * If the feed action does not have a hook, then the function will die with a + * message telling the visitor that the feed is not valid. + * + * It is better to only have one hook for each feed. + * + * @since 2.1.0 + * + * @global WP_Query $wp_query WordPress Query object. + */ + function do_feed() + { + } + /** + * Loads the RDF RSS 0.91 Feed template. + * + * @since 2.1.0 + * + * @see load_template() + */ + function do_feed_rdf() + { + } + /** + * Loads the RSS 1.0 Feed Template. + * + * @since 2.1.0 + * + * @see load_template() + */ + function do_feed_rss() + { + } + /** + * Loads either the RSS2 comment feed or the RSS2 posts feed. + * + * @since 2.1.0 + * + * @see load_template() + * + * @param bool $for_comments True for the comment feed, false for normal feed. + */ + function do_feed_rss2($for_comments) + { + } + /** + * Loads either Atom comment feed or Atom posts feed. + * + * @since 2.1.0 + * + * @see load_template() + * + * @param bool $for_comments True for the comment feed, false for normal feed. + */ + function do_feed_atom($for_comments) + { + } + /** + * Displays the default robots.txt file content. + * + * @since 2.1.0 + * @since 5.3.0 Remove the "Disallow: /" output if search engine visiblity is + * discouraged in favor of robots meta HTML tag via wp_robots_no_robots() + * filter callback. + */ + function do_robots() + { + } + /** + * Displays the favicon.ico file content. + * + * @since 5.4.0 + */ + function do_favicon() + { + } + /** + * Determines whether WordPress is already installed. + * + * The cache will be checked first. If you have a cache plugin, which saves + * the cache values, then this will work. If you use the default WordPress + * cache, and the database goes away, then you might have problems. + * + * Checks for the 'siteurl' option for whether WordPress is installed. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return bool Whether the site is already installed. + */ + function is_blog_installed() + { + } + /** + * Retrieves URL with nonce added to URL query. + * + * @since 2.0.4 + * + * @param string $actionurl URL to add nonce action. + * @param int|string $action Optional. Nonce action name. Default -1. + * @param string $name Optional. Nonce name. Default '_wpnonce'. + * @return string Escaped URL with nonce action added. + */ + function wp_nonce_url($actionurl, $action = -1, $name = '_wpnonce') + { + } + /** + * Retrieves or display nonce hidden field for forms. + * + * The nonce field is used to validate that the contents of the form came from + * the location on the current site and not somewhere else. The nonce does not + * offer absolute protection, but should protect against most cases. It is very + * important to use nonce field in forms. + * + * The $action and $name are optional, but if you want to have better security, + * it is strongly suggested to set those two parameters. It is easier to just + * call the function without any parameters, because validation of the nonce + * doesn't require any parameters, but since crackers know what the default is + * it won't be difficult for them to find a way around your nonce and cause + * damage. + * + * The input name will be whatever $name value you gave. The input value will be + * the nonce creation value. + * + * @since 2.0.4 + * + * @param int|string $action Optional. Action name. Default -1. + * @param string $name Optional. Nonce name. Default '_wpnonce'. + * @param bool $referer Optional. Whether to set the referer field for validation. Default true. + * @param bool $echo Optional. Whether to display or return hidden form field. Default true. + * @return string Nonce field HTML markup. + */ + function wp_nonce_field($action = -1, $name = '_wpnonce', $referer = \true, $echo = \true) + { + } + /** + * Retrieves or displays referer hidden field for forms. + * + * The referer link is the current Request URI from the server super global. The + * input name is '_wp_http_referer', in case you wanted to check manually. + * + * @since 2.0.4 + * + * @param bool $echo Optional. Whether to echo or return the referer field. Default true. + * @return string Referer field HTML markup. + */ + function wp_referer_field($echo = \true) + { + } + /** + * Retrieves or displays original referer hidden field for forms. + * + * The input name is '_wp_original_http_referer' and will be either the same + * value of wp_referer_field(), if that was posted already or it will be the + * current page, if it doesn't exist. + * + * @since 2.0.4 + * + * @param bool $echo Optional. Whether to echo the original http referer. Default true. + * @param string $jump_back_to Optional. Can be 'previous' or page you want to jump back to. + * Default 'current'. + * @return string Original referer field. + */ + function wp_original_referer_field($echo = \true, $jump_back_to = 'current') + { + } + /** + * Retrieves referer from '_wp_http_referer' or HTTP referer. + * + * If it's the same as the current request URL, will return false. + * + * @since 2.0.4 + * + * @return string|false Referer URL on success, false on failure. + */ + function wp_get_referer() + { + } + /** + * Retrieves unvalidated referer from '_wp_http_referer' or HTTP referer. + * + * Do not use for redirects, use wp_get_referer() instead. + * + * @since 4.5.0 + * + * @return string|false Referer URL on success, false on failure. + */ + function wp_get_raw_referer() + { + } + /** + * Retrieves original referer that was posted, if it exists. + * + * @since 2.0.4 + * + * @return string|false Original referer URL on success, false on failure. + */ + function wp_get_original_referer() + { + } + /** + * Recursive directory creation based on full path. + * + * Will attempt to set permissions on folders. + * + * @since 2.0.1 + * + * @param string $target Full path to attempt to create. + * @return bool Whether the path was created. True if path already exists. + */ + function wp_mkdir_p($target) + { + } + /** + * Tests if a given filesystem path is absolute. + * + * For example, '/foo/bar', or 'c:\windows'. + * + * @since 2.5.0 + * + * @param string $path File path. + * @return bool True if path is absolute, false is not absolute. + */ + function path_is_absolute($path) + { + } + /** + * Joins two filesystem paths together. + * + * For example, 'give me $path relative to $base'. If the $path is absolute, + * then it the full path is returned. + * + * @since 2.5.0 + * + * @param string $base Base path. + * @param string $path Path relative to $base. + * @return string The path with the base or absolute path. + */ + function path_join($base, $path) + { + } + /** + * Normalizes a filesystem path. + * + * On windows systems, replaces backslashes with forward slashes + * and forces upper-case drive letters. + * Allows for two leading slashes for Windows network shares, but + * ensures that all other duplicate slashes are reduced to a single. + * + * @since 3.9.0 + * @since 4.4.0 Ensures upper-case drive letters on Windows systems. + * @since 4.5.0 Allows for Windows network shares. + * @since 4.9.7 Allows for PHP file wrappers. + * + * @param string $path Path to normalize. + * @return string Normalized path. + */ + function wp_normalize_path($path) + { + } + /** + * Determines a writable directory for temporary files. + * + * Function's preference is the return value of sys_get_temp_dir(), + * followed by your PHP temporary upload directory, followed by WP_CONTENT_DIR, + * before finally defaulting to /tmp/ + * + * In the event that this function does not find a writable location, + * It may be overridden by the WP_TEMP_DIR constant in your wp-config.php file. + * + * @since 2.5.0 + * + * @return string Writable temporary directory. + */ + function get_temp_dir() + { + } + /** + * Determines if a directory is writable. + * + * This function is used to work around certain ACL issues in PHP primarily + * affecting Windows Servers. + * + * @since 3.6.0 + * + * @see win_is_writable() + * + * @param string $path Path to check for write-ability. + * @return bool Whether the path is writable. + */ + function wp_is_writable($path) + { + } + /** + * Workaround for Windows bug in is_writable() function + * + * PHP has issues with Windows ACL's for determine if a + * directory is writable or not, this works around them by + * checking the ability to open files rather than relying + * upon PHP to interprate the OS ACL. + * + * @since 2.8.0 + * + * @see https://bugs.php.net/bug.php?id=27609 + * @see https://bugs.php.net/bug.php?id=30931 + * + * @param string $path Windows path to check for write-ability. + * @return bool Whether the path is writable. + */ + function win_is_writable($path) + { + } + /** + * Retrieves uploads directory information. + * + * Same as wp_upload_dir() but "light weight" as it doesn't attempt to create the uploads directory. + * Intended for use in themes, when only 'basedir' and 'baseurl' are needed, generally in all cases + * when not uploading files. + * + * @since 4.5.0 + * + * @see wp_upload_dir() + * + * @return array See wp_upload_dir() for description. + */ + function wp_get_upload_dir() + { + } + /** + * Returns an array containing the current upload directory's path and URL. + * + * Checks the 'upload_path' option, which should be from the web root folder, + * and if it isn't empty it will be used. If it is empty, then the path will be + * 'WP_CONTENT_DIR/uploads'. If the 'UPLOADS' constant is defined, then it will + * override the 'upload_path' option and 'WP_CONTENT_DIR/uploads' path. + * + * The upload URL path is set either by the 'upload_url_path' option or by using + * the 'WP_CONTENT_URL' constant and appending '/uploads' to the path. + * + * If the 'uploads_use_yearmonth_folders' is set to true (checkbox if checked in + * the administration settings panel), then the time will be used. The format + * will be year first and then month. + * + * If the path couldn't be created, then an error will be returned with the key + * 'error' containing the error message. The error suggests that the parent + * directory is not writable by the server. + * + * @since 2.0.0 + * @uses _wp_upload_dir() + * + * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null. + * @param bool $create_dir Optional. Whether to check and create the uploads directory. + * Default true for backward compatibility. + * @param bool $refresh_cache Optional. Whether to refresh the cache. Default false. + * @return array { + * Array of information about the upload directory. + * + * @type string $path Base directory and subdirectory or full path to upload directory. + * @type string $url Base URL and subdirectory or absolute URL to upload directory. + * @type string $subdir Subdirectory if uploads use year/month folders option is on. + * @type string $basedir Path without subdir. + * @type string $baseurl URL path without subdir. + * @type string|false $error False or error message. + * } + * @phpstan-return array{ + * path: string, + * url: string, + * subdir: string, + * basedir: string, + * baseurl: string, + * error: string|false, + * } + */ + function wp_upload_dir($time = \null, $create_dir = \true, $refresh_cache = \false) + { + } + /** + * A non-filtered, non-cached version of wp_upload_dir() that doesn't check the path. + * + * @since 4.5.0 + * @access private + * + * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null. + * @return array See wp_upload_dir() + */ + function _wp_upload_dir($time = \null) + { + } + /** + * Gets a filename that is sanitized and unique for the given directory. + * + * If the filename is not unique, then a number will be added to the filename + * before the extension, and will continue adding numbers until the filename + * is unique. + * + * The callback function allows the caller to use their own method to create + * unique file names. If defined, the callback should take three arguments: + * - directory, base filename, and extension - and return a unique filename. + * + * @since 2.5.0 + * + * @param string $dir Directory. + * @param string $filename File name. + * @param callable $unique_filename_callback Callback. Default null. + * @return string New filename, if given wasn't unique. + */ + function wp_unique_filename($dir, $filename, $unique_filename_callback = \null) + { + } + /** + * Helper function to test if each of an array of file names could conflict with existing files. + * + * @since 5.8.1 + * @access private + * + * @param string[] $filenames Array of file names to check. + * @param string $dir The directory containing the files. + * @param array $files An array of existing files in the directory. May be empty. + * @return bool True if the tested file name could match an existing file, false otherwise. + */ + function _wp_check_alternate_file_names($filenames, $dir, $files) + { + } + /** + * Helper function to check if a file name could match an existing image sub-size file name. + * + * @since 5.3.1 + * @access private + * + * @param string $filename The file name to check. + * @param array $files An array of existing files in the directory. + * @return bool True if the tested file name could match an existing file, false otherwise. + */ + function _wp_check_existing_file_names($filename, $files) + { + } + /** + * Creates a file in the upload folder with given content. + * + * If there is an error, then the key 'error' will exist with the error message. + * If success, then the key 'file' will have the unique file path, the 'url' key + * will have the link to the new file. and the 'error' key will be set to false. + * + * This function will not move an uploaded file to the upload folder. It will + * create a new file with the content in $bits parameter. If you move the upload + * file, read the content of the uploaded file, and then you can give the + * filename and content to this function, which will add it to the upload + * folder. + * + * The permissions will be set on the new file automatically by this function. + * + * @since 2.0.0 + * + * @param string $name Filename. + * @param null|string $deprecated Never used. Set to null. + * @param string $bits File content + * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null. + * @return array { + * Information about the newly-uploaded file. + * + * @type string $file Filename of the newly-uploaded file. + * @type string $url URL of the uploaded file. + * @type string $type File type. + * @type string|false $error Error message, if there has been an error. + * } + * @phpstan-return array{ + * file: string, + * url: string, + * type: string, + * error: string|false, + * } + */ + function wp_upload_bits($name, $deprecated, $bits, $time = \null) + { + } + /** + * Retrieves the file type based on the extension name. + * + * @since 2.5.0 + * + * @param string $ext The extension to search. + * @return string|void The file type, example: audio, video, document, spreadsheet, etc. + */ + function wp_ext2type($ext) + { + } + /** + * Returns first matched extension for the mime-type, + * as mapped from wp_get_mime_types(). + * + * @since 5.8.1 + * + * @param string $mime_type + * + * @return string|false + */ + function wp_get_default_extension_for_mime_type($mime_type) + { + } + /** + * Retrieves the file type from the file name. + * + * You can optionally define the mime array, if needed. + * + * @since 2.0.4 + * + * @param string $filename File name or path. + * @param string[] $mimes Optional. Array of allowed mime types keyed by their file extension regex. + * @return array { + * Values for the extension and mime type. + * + * @type string|false $ext File extension, or false if the file doesn't match a mime type. + * @type string|false $type File mime type, or false if the file doesn't match a mime type. + * } + * @phpstan-return array{ + * ext: string|false, + * type: string|false, + * } + */ + function wp_check_filetype($filename, $mimes = \null) + { + } + /** + * Attempts to determine the real file type of a file. + * + * If unable to, the file name extension will be used to determine type. + * + * If it's determined that the extension does not match the file's real type, + * then the "proper_filename" value will be set with a proper filename and extension. + * + * Currently this function only supports renaming images validated via wp_get_image_mime(). + * + * @since 3.0.0 + * + * @param string $file Full path to the file. + * @param string $filename The name of the file (may differ from $file due to $file being + * in a tmp directory). + * @param string[] $mimes Optional. Array of allowed mime types keyed by their file extension regex. + * @return array { + * Values for the extension, mime type, and corrected filename. + * + * @type string|false $ext File extension, or false if the file doesn't match a mime type. + * @type string|false $type File mime type, or false if the file doesn't match a mime type. + * @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined. + * } + * @phpstan-return array{ + * ext: string|false, + * type: string|false, + * proper_filename: string|false, + * } + */ + function wp_check_filetype_and_ext($file, $filename, $mimes = \null) + { + } + /** + * Returns the real mime type of an image file. + * + * This depends on exif_imagetype() or getimagesize() to determine real mime types. + * + * @since 4.7.1 + * @since 5.8.0 Added support for WebP images. + * + * @param string $file Full path to the file. + * @return string|false The actual mime type or false if the type cannot be determined. + */ + function wp_get_image_mime($file) + { + } + /** + * Retrieves the list of mime types and file extensions. + * + * @since 3.5.0 + * @since 4.2.0 Support was added for GIMP (.xcf) files. + * @since 4.9.2 Support was added for Flac (.flac) files. + * @since 4.9.6 Support was added for AAC (.aac) files. + * + * @return string[] Array of mime types keyed by the file extension regex corresponding to those types. + */ + function wp_get_mime_types() + { + } + /** + * Retrieves the list of common file extensions and their types. + * + * @since 4.6.0 + * + * @return array[] Multi-dimensional array of file extensions types keyed by the type of file. + */ + function wp_get_ext_types() + { + } + /** + * Wrapper for PHP filesize with filters and casting the result as an integer. + * + * @since 6.0.0 + * + * @link https://www.php.net/manual/en/function.filesize.php + * + * @param string $path Path to the file. + * @return int The size of the file in bytes, or 0 in the event of an error. + */ + function wp_filesize($path) + { + } + /** + * Retrieves the list of allowed mime types and file extensions. + * + * @since 2.8.6 + * + * @param int|WP_User $user Optional. User to check. Defaults to current user. + * @return string[] Array of mime types keyed by the file extension regex corresponding + * to those types. + */ + function get_allowed_mime_types($user = \null) + { + } + /** + * Displays "Are You Sure" message to confirm the action being taken. + * + * If the action has the nonce explain message, then it will be displayed + * along with the "Are you sure?" message. + * + * @since 2.0.4 + * + * @param string $action The nonce action. + */ + function wp_nonce_ays($action) + { + } + /** + * Kills WordPress execution and displays HTML page with an error message. + * + * This function complements the `die()` PHP function. The difference is that + * HTML will be displayed to the user. It is recommended to use this function + * only when the execution should not continue any further. It is not recommended + * to call this function very often, and try to handle as many errors as possible + * silently or more gracefully. + * + * As a shorthand, the desired HTTP response code may be passed as an integer to + * the `$title` parameter (the default title would apply) or the `$args` parameter. + * + * @since 2.0.4 + * @since 4.1.0 The `$title` and `$args` parameters were changed to optionally accept + * an integer to be used as the response code. + * @since 5.1.0 The `$link_url`, `$link_text`, and `$exit` arguments were added. + * @since 5.3.0 The `$charset` argument was added. + * @since 5.5.0 The `$text_direction` argument has a priority over get_language_attributes() + * in the default handler. + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param string|WP_Error $message Optional. Error message. If this is a WP_Error object, + * and not an Ajax or XML-RPC request, the error's messages are used. + * Default empty. + * @param string|int $title Optional. Error title. If `$message` is a `WP_Error` object, + * error data with the key 'title' may be used to specify the title. + * If `$title` is an integer, then it is treated as the response + * code. Default empty. + * @param string|array|int $args { + * Optional. Arguments to control behavior. If `$args` is an integer, then it is treated + * as the response code. Default empty array. + * + * @type int $response The HTTP response code. Default 200 for Ajax requests, 500 otherwise. + * @type string $link_url A URL to include a link to. Only works in combination with $link_text. + * Default empty string. + * @type string $link_text A label for the link to include. Only works in combination with $link_url. + * Default empty string. + * @type bool $back_link Whether to include a link to go back. Default false. + * @type string $text_direction The text direction. This is only useful internally, when WordPress is still + * loading and the site's locale is not set up yet. Accepts 'rtl' and 'ltr'. + * Default is the value of is_rtl(). + * @type string $charset Character set of the HTML output. Default 'utf-8'. + * @type string $code Error code to use. Default is 'wp_die', or the main error code if $message + * is a WP_Error. + * @type bool $exit Whether to exit the process after completion. Default true. + * } + * @phpstan-param int|array{ + * response?: int, + * link_url?: string, + * link_text?: string, + * back_link?: bool, + * text_direction?: string, + * charset?: string, + * code?: string, + * exit?: bool, + * } $args + */ + function wp_die($message = '', $title = '', $args = array()) + { + } + /** + * Kills WordPress execution and displays HTML page with an error message. + * + * This is the default handler for wp_die(). If you want a custom one, + * you can override this using the {@see 'wp_die_handler'} filter in wp_die(). + * + * @since 3.0.0 + * @access private + * + * @param string|WP_Error $message Error message or WP_Error object. + * @param string $title Optional. Error title. Default empty. + * @param string|array $args Optional. Arguments to control behavior. Default empty array. + */ + function _default_wp_die_handler($message, $title = '', $args = array()) + { + } + /** + * Kills WordPress execution and displays Ajax response with an error message. + * + * This is the handler for wp_die() when processing Ajax requests. + * + * @since 3.4.0 + * @access private + * + * @param string $message Error message. + * @param string $title Optional. Error title (unused). Default empty. + * @param string|array $args Optional. Arguments to control behavior. Default empty array. + */ + function _ajax_wp_die_handler($message, $title = '', $args = array()) + { + } + /** + * Kills WordPress execution and displays JSON response with an error message. + * + * This is the handler for wp_die() when processing JSON requests. + * + * @since 5.1.0 + * @access private + * + * @param string $message Error message. + * @param string $title Optional. Error title. Default empty. + * @param string|array $args Optional. Arguments to control behavior. Default empty array. + */ + function _json_wp_die_handler($message, $title = '', $args = array()) + { + } + /** + * Kills WordPress execution and displays JSONP response with an error message. + * + * This is the handler for wp_die() when processing JSONP requests. + * + * @since 5.2.0 + * @access private + * + * @param string $message Error message. + * @param string $title Optional. Error title. Default empty. + * @param string|array $args Optional. Arguments to control behavior. Default empty array. + */ + function _jsonp_wp_die_handler($message, $title = '', $args = array()) + { + } + /** + * Kills WordPress execution and displays XML response with an error message. + * + * This is the handler for wp_die() when processing XMLRPC requests. + * + * @since 3.2.0 + * @access private + * + * @global wp_xmlrpc_server $wp_xmlrpc_server + * + * @param string $message Error message. + * @param string $title Optional. Error title. Default empty. + * @param string|array $args Optional. Arguments to control behavior. Default empty array. + */ + function _xmlrpc_wp_die_handler($message, $title = '', $args = array()) + { + } + /** + * Kills WordPress execution and displays XML response with an error message. + * + * This is the handler for wp_die() when processing XML requests. + * + * @since 5.2.0 + * @access private + * + * @param string $message Error message. + * @param string $title Optional. Error title. Default empty. + * @param string|array $args Optional. Arguments to control behavior. Default empty array. + */ + function _xml_wp_die_handler($message, $title = '', $args = array()) + { + } + /** + * Kills WordPress execution and displays an error message. + * + * This is the handler for wp_die() when processing APP requests. + * + * @since 3.4.0 + * @since 5.1.0 Added the $title and $args parameters. + * @access private + * + * @param string $message Optional. Response to print. Default empty. + * @param string $title Optional. Error title (unused). Default empty. + * @param string|array $args Optional. Arguments to control behavior. Default empty array. + */ + function _scalar_wp_die_handler($message = '', $title = '', $args = array()) + { + } + /** + * Processes arguments passed to wp_die() consistently for its handlers. + * + * @since 5.1.0 + * @access private + * + * @param string|WP_Error $message Error message or WP_Error object. + * @param string $title Optional. Error title. Default empty. + * @param string|array $args Optional. Arguments to control behavior. Default empty array. + * @return array { + * Processed arguments. + * + * @type string $0 Error message. + * @type string $1 Error title. + * @type array $2 Arguments to control behavior. + * } + * @phpstan-return array{ + * 0: string, + * 1: string, + * 2: array, + * } + */ + function _wp_die_process_input($message, $title = '', $args = array()) + { + } + /** + * Encodes a variable into JSON, with some sanity checks. + * + * @since 4.1.0 + * @since 5.3.0 No longer handles support for PHP < 5.6. + * + * @param mixed $data Variable (usually an array or object) to encode as JSON. + * @param int $options Optional. Options to be passed to json_encode(). Default 0. + * @param int $depth Optional. Maximum depth to walk through $data. Must be + * greater than 0. Default 512. + * @return string|false The JSON encoded string, or false if it cannot be encoded. + */ + function wp_json_encode($data, $options = 0, $depth = 512) + { + } + /** + * Performs sanity checks on data that shall be encoded to JSON. + * + * @ignore + * @since 4.1.0 + * @access private + * + * @see wp_json_encode() + * + * @throws Exception If depth limit is reached. + * + * @param mixed $data Variable (usually an array or object) to encode as JSON. + * @param int $depth Maximum depth to walk through $data. Must be greater than 0. + * @return mixed The sanitized data that shall be encoded to JSON. + */ + function _wp_json_sanity_check($data, $depth) + { + } + /** + * Converts a string to UTF-8, so that it can be safely encoded to JSON. + * + * @ignore + * @since 4.1.0 + * @access private + * + * @see _wp_json_sanity_check() + * + * @param string $string The string which is to be converted. + * @return string The checked string. + */ + function _wp_json_convert_string($string) + { + } + /** + * Prepares response data to be serialized to JSON. + * + * This supports the JsonSerializable interface for PHP 5.2-5.3 as well. + * + * @ignore + * @since 4.4.0 + * @deprecated 5.3.0 This function is no longer needed as support for PHP 5.2-5.3 + * has been dropped. + * @access private + * + * @param mixed $data Native representation. + * @return bool|int|float|null|string|array Data ready for `json_encode()`. + */ + function _wp_json_prepare_data($data) + { + } + /** + * Sends a JSON response back to an Ajax request. + * + * @since 3.5.0 + * @since 4.7.0 The `$status_code` parameter was added. + * @since 5.6.0 The `$options` parameter was added. + * + * @param mixed $response Variable (usually an array or object) to encode as JSON, + * then print and die. + * @param int $status_code Optional. The HTTP status code to output. Default null. + * @param int $options Optional. Options to be passed to json_encode(). Default 0. + */ + function wp_send_json($response, $status_code = \null, $options = 0) + { + } + /** + * Sends a JSON response back to an Ajax request, indicating success. + * + * @since 3.5.0 + * @since 4.7.0 The `$status_code` parameter was added. + * @since 5.6.0 The `$options` parameter was added. + * + * @param mixed $data Optional. Data to encode as JSON, then print and die. Default null. + * @param int $status_code Optional. The HTTP status code to output. Default null. + * @param int $options Optional. Options to be passed to json_encode(). Default 0. + */ + function wp_send_json_success($data = \null, $status_code = \null, $options = 0) + { + } + /** + * Sends a JSON response back to an Ajax request, indicating failure. + * + * If the `$data` parameter is a WP_Error object, the errors + * within the object are processed and output as an array of error + * codes and corresponding messages. All other types are output + * without further processing. + * + * @since 3.5.0 + * @since 4.1.0 The `$data` parameter is now processed if a WP_Error object is passed in. + * @since 4.7.0 The `$status_code` parameter was added. + * @since 5.6.0 The `$options` parameter was added. + * + * @param mixed $data Optional. Data to encode as JSON, then print and die. Default null. + * @param int $status_code Optional. The HTTP status code to output. Default null. + * @param int $options Optional. Options to be passed to json_encode(). Default 0. + */ + function wp_send_json_error($data = \null, $status_code = \null, $options = 0) + { + } + /** + * Checks that a JSONP callback is a valid JavaScript callback name. + * + * Only allows alphanumeric characters and the dot character in callback + * function names. This helps to mitigate XSS attacks caused by directly + * outputting user input. + * + * @since 4.6.0 + * + * @param string $callback Supplied JSONP callback function name. + * @return bool Whether the callback function name is valid. + */ + function wp_check_jsonp_callback($callback) + { + } + /** + * Reads and decodes a JSON file. + * + * @since 5.9.0 + * + * @param string $filename Path to the JSON file. + * @param array $options { + * Optional. Options to be used with `json_decode()`. + * + * @type bool $associative Optional. When `true`, JSON objects will be returned as associative arrays. + * When `false`, JSON objects will be returned as objects. + * } + * + * @return mixed Returns the value encoded in JSON in appropriate PHP type. + * `null` is returned if the file is not found, or its content can't be decoded. + * @phpstan-param array{ + * associative?: bool, + * } $options + */ + function wp_json_file_decode($filename, $options = array()) + { + } + /** + * Retrieves the WordPress home page URL. + * + * If the constant named 'WP_HOME' exists, then it will be used and returned + * by the function. This can be used to counter the redirection on your local + * development environment. + * + * @since 2.2.0 + * @access private + * + * @see WP_HOME + * + * @param string $url URL for the home location. + * @return string Homepage location. + */ + function _config_wp_home($url = '') + { + } + /** + * Retrieves the WordPress site URL. + * + * If the constant named 'WP_SITEURL' is defined, then the value in that + * constant will always be returned. This can be used for debugging a site + * on your localhost while not having to change the database to your URL. + * + * @since 2.2.0 + * @access private + * + * @see WP_SITEURL + * + * @param string $url URL to set the WordPress site location. + * @return string The WordPress site URL. + */ + function _config_wp_siteurl($url = '') + { + } + /** + * Deletes the fresh site option. + * + * @since 4.7.0 + * @access private + */ + function _delete_option_fresh_site() + { + } + /** + * Sets the localized direction for MCE plugin. + * + * Will only set the direction to 'rtl', if the WordPress locale has + * the text direction set to 'rtl'. + * + * Fills in the 'directionality' setting, enables the 'directionality' + * plugin, and adds the 'ltr' button to 'toolbar1', formerly + * 'theme_advanced_buttons1' array keys. These keys are then returned + * in the $mce_init (TinyMCE settings) array. + * + * @since 2.1.0 + * @access private + * + * @param array $mce_init MCE settings array. + * @return array Direction set for 'rtl', if needed by locale. + */ + function _mce_set_direction($mce_init) + { + } + /** + * Converts smiley code to the icon graphic file equivalent. + * + * You can turn off smilies, by going to the write setting screen and unchecking + * the box, or by setting 'use_smilies' option to false or removing the option. + * + * Plugins may override the default smiley list by setting the $wpsmiliestrans + * to an array, with the key the code the blogger types in and the value the + * image file. + * + * The $wp_smiliessearch global is for the regular expression and is set each + * time the function is called. + * + * The full list of smilies can be found in the function and won't be listed in + * the description. Probably should create a Codex page for it, so that it is + * available. + * + * @global array $wpsmiliestrans + * @global array $wp_smiliessearch + * + * @since 2.2.0 + */ + function smilies_init() + { + } + /** + * Merges user defined arguments into defaults array. + * + * This function is used throughout WordPress to allow for both string or array + * to be merged into another array. + * + * @since 2.2.0 + * @since 2.3.0 `$args` can now also be an object. + * + * @param string|array|object $args Value to merge with $defaults. + * @param array $defaults Optional. Array that serves as the defaults. + * Default empty array. + * @return array Merged user defined values with defaults. + */ + function wp_parse_args($args, $defaults = array()) + { + } + /** + * Converts a comma- or space-separated list of scalar values to an array. + * + * @since 5.1.0 + * + * @param array|string $list List of values. + * @return array Array of values. + */ + function wp_parse_list($list) + { + } + /** + * Cleans up an array, comma- or space-separated list of IDs. + * + * @since 3.0.0 + * @since 5.1.0 Refactored to use wp_parse_list(). + * + * @param array|string $list List of IDs. + * @return int[] Sanitized array of IDs. + */ + function wp_parse_id_list($list) + { + } + /** + * Cleans up an array, comma- or space-separated list of slugs. + * + * @since 4.7.0 + * @since 5.1.0 Refactored to use wp_parse_list(). + * + * @param array|string $list List of slugs. + * @return string[] Sanitized array of slugs. + */ + function wp_parse_slug_list($list) + { + } + /** + * Extracts a slice of an array, given a list of keys. + * + * @since 3.1.0 + * + * @param array $array The original array. + * @param array $keys The list of keys. + * @return array The array slice. + */ + function wp_array_slice_assoc($array, $keys) + { + } + /** + * Accesses an array in depth based on a path of keys. + * + * It is the PHP equivalent of JavaScript's `lodash.get()` and mirroring it may help other components + * retain some symmetry between client and server implementations. + * + * Example usage: + * + * $array = array( + * 'a' => array( + * 'b' => array( + * 'c' => 1, + * ), + * ), + * ); + * _wp_array_get( $array, array( 'a', 'b', 'c' ) ); + * + * @internal + * + * @since 5.6.0 + * @access private + * + * @param array $array An array from which we want to retrieve some information. + * @param array $path An array of keys describing the path with which to retrieve information. + * @param mixed $default Optional. The return value if the path does not exist within the array, + * or if `$array` or `$path` are not arrays. Default null. + * @return mixed The value from the path specified. + */ + function _wp_array_get($array, $path, $default = \null) + { + } + /** + * Sets an array in depth based on a path of keys. + * + * It is the PHP equivalent of JavaScript's `lodash.set()` and mirroring it may help other components + * retain some symmetry between client and server implementations. + * + * Example usage: + * + * $array = array(); + * _wp_array_set( $array, array( 'a', 'b', 'c', 1 ) ); + * + * $array becomes: + * array( + * 'a' => array( + * 'b' => array( + * 'c' => 1, + * ), + * ), + * ); + * + * @internal + * + * @since 5.8.0 + * @access private + * + * @param array $array An array that we want to mutate to include a specific value in a path. + * @param array $path An array of keys describing the path that we want to mutate. + * @param mixed $value The value that will be set. + */ + function _wp_array_set(&$array, $path, $value = \null) + { + } + /** + * This function is trying to replicate what + * lodash's kebabCase (JS library) does in the client. + * + * The reason we need this function is that we do some processing + * in both the client and the server (e.g.: we generate + * preset classes from preset slugs) that needs to + * create the same output. + * + * We can't remove or update the client's library due to backward compatibility + * (some of the output of lodash's kebabCase is saved in the post content). + * We have to make the server behave like the client. + * + * Changes to this function should follow updates in the client + * with the same logic. + * + * @link https://github.com/lodash/lodash/blob/4.17/dist/lodash.js#L14369 + * @link https://github.com/lodash/lodash/blob/4.17/dist/lodash.js#L278 + * @link https://github.com/lodash-php/lodash-php/blob/master/src/String/kebabCase.php + * @link https://github.com/lodash-php/lodash-php/blob/master/src/internal/unicodeWords.php + * + * @param string $string The string to kebab-case. + * + * @return string kebab-cased-string. + */ + function _wp_to_kebab_case($string) + { + } + /** + * Determines if the variable is a numeric-indexed array. + * + * @since 4.4.0 + * + * @param mixed $data Variable to check. + * @return bool Whether the variable is a list. + */ + function wp_is_numeric_array($data) + { + } + /** + * Filters a list of objects, based on a set of key => value arguments. + * + * Retrieves the objects from the list that match the given arguments. + * Key represents property name, and value represents property value. + * + * If an object has more properties than those specified in arguments, + * that will not disqualify it. When using the 'AND' operator, + * any missing properties will disqualify it. + * + * When using the `$field` argument, this function can also retrieve + * a particular field from all matching objects, whereas wp_list_filter() + * only does the filtering. + * + * @since 3.0.0 + * @since 4.7.0 Uses `WP_List_Util` class. + * + * @param array $list An array of objects to filter. + * @param array $args Optional. An array of key => value arguments to match + * against each object. Default empty array. + * @param string $operator Optional. The logical operation to perform. 'AND' means + * all elements from the array must match. 'OR' means only + * one element needs to match. 'NOT' means no elements may + * match. Default 'AND'. + * @param bool|string $field Optional. A field from the object to place instead + * of the entire object. Default false. + * @return array A list of objects or object fields. + */ + function wp_filter_object_list($list, $args = array(), $operator = 'and', $field = \false) + { + } + /** + * Filters a list of objects, based on a set of key => value arguments. + * + * Retrieves the objects from the list that match the given arguments. + * Key represents property name, and value represents property value. + * + * If an object has more properties than those specified in arguments, + * that will not disqualify it. When using the 'AND' operator, + * any missing properties will disqualify it. + * + * If you want to retrieve a particular field from all matching objects, + * use wp_filter_object_list() instead. + * + * @since 3.1.0 + * @since 4.7.0 Uses `WP_List_Util` class. + * @since 5.9.0 Converted into a wrapper for `wp_filter_object_list()`. + * + * @param array $list An array of objects to filter. + * @param array $args Optional. An array of key => value arguments to match + * against each object. Default empty array. + * @param string $operator Optional. The logical operation to perform. 'AND' means + * all elements from the array must match. 'OR' means only + * one element needs to match. 'NOT' means no elements may + * match. Default 'AND'. + * @return array Array of found values. + */ + function wp_list_filter($list, $args = array(), $operator = 'AND') + { + } + /** + * Plucks a certain field out of each object or array in an array. + * + * This has the same functionality and prototype of + * array_column() (PHP 5.5) but also supports objects. + * + * @since 3.1.0 + * @since 4.0.0 $index_key parameter added. + * @since 4.7.0 Uses `WP_List_Util` class. + * + * @param array $list List of objects or arrays. + * @param int|string $field Field from the object to place instead of the entire object. + * @param int|string $index_key Optional. Field from the object to use as keys for the new array. + * Default null. + * @return array Array of found values. If `$index_key` is set, an array of found values with keys + * corresponding to `$index_key`. If `$index_key` is null, array keys from the original + * `$list` will be preserved in the results. + */ + function wp_list_pluck($list, $field, $index_key = \null) + { + } + /** + * Sorts an array of objects or arrays based on one or more orderby arguments. + * + * @since 4.7.0 + * + * @param array $list An array of objects or arrays to sort. + * @param string|array $orderby Optional. Either the field name to order by or an array + * of multiple orderby fields as $orderby => $order. + * @param string $order Optional. Either 'ASC' or 'DESC'. Only used if $orderby + * is a string. + * @param bool $preserve_keys Optional. Whether to preserve keys. Default false. + * @return array The sorted array. + */ + function wp_list_sort($list, $orderby = array(), $order = 'ASC', $preserve_keys = \false) + { + } + /** + * Determines if Widgets library should be loaded. + * + * Checks to make sure that the widgets library hasn't already been loaded. + * If it hasn't, then it will load the widgets library and run an action hook. + * + * @since 2.2.0 + */ + function wp_maybe_load_widgets() + { + } + /** + * Appends the Widgets menu to the themes main menu. + * + * @since 2.2.0 + * @since 5.9.3 Don't specify menu order when the active theme is a block theme. + * + * @global array $submenu + */ + function wp_widgets_add_menu() + { + } + /** + * Flushes all output buffers for PHP 5.2. + * + * Make sure all output buffers are flushed before our singletons are destroyed. + * + * @since 2.2.0 + */ + function wp_ob_end_flush_all() + { + } + /** + * Loads custom DB error or display WordPress DB error. + * + * If a file exists in the wp-content directory named db-error.php, then it will + * be loaded instead of displaying the WordPress DB error. If it is not found, + * then the WordPress DB error will be displayed instead. + * + * The WordPress DB error sets the HTTP status header to 500 to try to prevent + * search engines from caching the message. Custom DB messages should do the + * same. + * + * This function was backported to WordPress 2.3.2, but originally was added + * in WordPress 2.5.0. + * + * @since 2.3.2 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function dead_db() + { + } + /** + * Converts a value to non-negative integer. + * + * @since 2.5.0 + * + * @param mixed $maybeint Data you wish to have converted to a non-negative integer. + * @return int A non-negative integer. + */ + function absint($maybeint) + { + } + /** + * Marks a function as deprecated and inform when it has been used. + * + * There is a hook {@see 'deprecated_function_run'} that will be called that can be used + * to get the backtrace up to what file and function called the deprecated + * function. + * + * The current behavior is to trigger a user error if `WP_DEBUG` is true. + * + * This function is to be used in every function that is deprecated. + * + * @since 2.5.0 + * @since 5.4.0 This function is no longer marked as "private". + * @since 5.4.0 The error type is now classified as E_USER_DEPRECATED (used to default to E_USER_NOTICE). + * + * @param string $function The function that was called. + * @param string $version The version of WordPress that deprecated the function. + * @param string $replacement Optional. The function that should have been called. Default empty. + */ + function _deprecated_function($function, $version, $replacement = '') + { + } + /** + * Marks a constructor as deprecated and informs when it has been used. + * + * Similar to _deprecated_function(), but with different strings. Used to + * remove PHP4 style constructors. + * + * The current behavior is to trigger a user error if `WP_DEBUG` is true. + * + * This function is to be used in every PHP4 style constructor method that is deprecated. + * + * @since 4.3.0 + * @since 4.5.0 Added the `$parent_class` parameter. + * @since 5.4.0 This function is no longer marked as "private". + * @since 5.4.0 The error type is now classified as E_USER_DEPRECATED (used to default to E_USER_NOTICE). + * + * @param string $class The class containing the deprecated constructor. + * @param string $version The version of WordPress that deprecated the function. + * @param string $parent_class Optional. The parent class calling the deprecated constructor. + * Default empty string. + */ + function _deprecated_constructor($class, $version, $parent_class = '') + { + } + /** + * Marks a file as deprecated and inform when it has been used. + * + * There is a hook {@see 'deprecated_file_included'} that will be called that can be used + * to get the backtrace up to what file and function included the deprecated + * file. + * + * The current behavior is to trigger a user error if `WP_DEBUG` is true. + * + * This function is to be used in every file that is deprecated. + * + * @since 2.5.0 + * @since 5.4.0 This function is no longer marked as "private". + * @since 5.4.0 The error type is now classified as E_USER_DEPRECATED (used to default to E_USER_NOTICE). + * + * @param string $file The file that was included. + * @param string $version The version of WordPress that deprecated the file. + * @param string $replacement Optional. The file that should have been included based on ABSPATH. + * Default empty. + * @param string $message Optional. A message regarding the change. Default empty. + */ + function _deprecated_file($file, $version, $replacement = '', $message = '') + { + } + /** + * Marks a function argument as deprecated and inform when it has been used. + * + * This function is to be used whenever a deprecated function argument is used. + * Before this function is called, the argument must be checked for whether it was + * used by comparing it to its default value or evaluating whether it is empty. + * For example: + * + * if ( ! empty( $deprecated ) ) { + * _deprecated_argument( __FUNCTION__, '3.0.0' ); + * } + * + * There is a hook deprecated_argument_run that will be called that can be used + * to get the backtrace up to what file and function used the deprecated + * argument. + * + * The current behavior is to trigger a user error if WP_DEBUG is true. + * + * @since 3.0.0 + * @since 5.4.0 This function is no longer marked as "private". + * @since 5.4.0 The error type is now classified as E_USER_DEPRECATED (used to default to E_USER_NOTICE). + * + * @param string $function The function that was called. + * @param string $version The version of WordPress that deprecated the argument used. + * @param string $message Optional. A message regarding the change. Default empty. + */ + function _deprecated_argument($function, $version, $message = '') + { + } + /** + * Marks a deprecated action or filter hook as deprecated and throws a notice. + * + * Use the {@see 'deprecated_hook_run'} action to get the backtrace describing where + * the deprecated hook was called. + * + * Default behavior is to trigger a user error if `WP_DEBUG` is true. + * + * This function is called by the do_action_deprecated() and apply_filters_deprecated() + * functions, and so generally does not need to be called directly. + * + * @since 4.6.0 + * @since 5.4.0 The error type is now classified as E_USER_DEPRECATED (used to default to E_USER_NOTICE). + * @access private + * + * @param string $hook The hook that was used. + * @param string $version The version of WordPress that deprecated the hook. + * @param string $replacement Optional. The hook that should have been used. Default empty. + * @param string $message Optional. A message regarding the change. Default empty. + */ + function _deprecated_hook($hook, $version, $replacement = '', $message = '') + { + } + /** + * Marks something as being incorrectly called. + * + * There is a hook {@see 'doing_it_wrong_run'} that will be called that can be used + * to get the backtrace up to what file and function called the deprecated + * function. + * + * The current behavior is to trigger a user error if `WP_DEBUG` is true. + * + * @since 3.1.0 + * @since 5.4.0 This function is no longer marked as "private". + * + * @param string $function The function that was called. + * @param string $message A message explaining what has been done incorrectly. + * @param string $version The version of WordPress where the message was added. + */ + function _doing_it_wrong($function, $message, $version) + { + } + /** + * Determines whether the server is running an earlier than 1.5.0 version of lighttpd. + * + * @since 2.5.0 + * + * @return bool Whether the server is running lighttpd < 1.5.0. + */ + function is_lighttpd_before_150() + { + } + /** + * Determines whether the specified module exist in the Apache config. + * + * @since 2.5.0 + * + * @global bool $is_apache + * + * @param string $mod The module, e.g. mod_rewrite. + * @param bool $default Optional. The default return value if the module is not found. Default false. + * @return bool Whether the specified module is loaded. + */ + function apache_mod_loaded($mod, $default = \false) + { + } + /** + * Checks if IIS 7+ supports pretty permalinks. + * + * @since 2.8.0 + * + * @global bool $is_iis7 + * + * @return bool Whether IIS7 supports permalinks. + */ + function iis7_supports_permalinks() + { + } + /** + * Validates a file name and path against an allowed set of rules. + * + * A return value of `1` means the file path contains directory traversal. + * + * A return value of `2` means the file path contains a Windows drive path. + * + * A return value of `3` means the file is not in the allowed files list. + * + * @since 1.2.0 + * + * @param string $file File path. + * @param string[] $allowed_files Optional. Array of allowed files. + * @return int 0 means nothing is wrong, greater than 0 means something was wrong. + */ + function validate_file($file, $allowed_files = array()) + { + } + /** + * Determines whether to force SSL used for the Administration Screens. + * + * @since 2.6.0 + * + * @param string|bool $force Optional. Whether to force SSL in admin screens. Default null. + * @return bool True if forced, false if not forced. + */ + function force_ssl_admin($force = \null) + { + } + /** + * Guesses the URL for the site. + * + * Will remove wp-admin links to retrieve only return URLs not in the wp-admin + * directory. + * + * @since 2.6.0 + * + * @return string The guessed URL. + */ + function wp_guess_url() + { + } + /** + * Temporarily suspends cache additions. + * + * Stops more data being added to the cache, but still allows cache retrieval. + * This is useful for actions, such as imports, when a lot of data would otherwise + * be almost uselessly added to the cache. + * + * Suspension lasts for a single page load at most. Remember to call this + * function again if you wish to re-enable cache adds earlier. + * + * @since 3.3.0 + * + * @param bool $suspend Optional. Suspends additions if true, re-enables them if false. + * @return bool The current suspend setting + */ + function wp_suspend_cache_addition($suspend = \null) + { + } + /** + * Suspends cache invalidation. + * + * Turns cache invalidation on and off. Useful during imports where you don't want to do + * invalidations every time a post is inserted. Callers must be sure that what they are + * doing won't lead to an inconsistent cache when invalidation is suspended. + * + * @since 2.7.0 + * + * @global bool $_wp_suspend_cache_invalidation + * + * @param bool $suspend Optional. Whether to suspend or enable cache invalidation. Default true. + * @return bool The current suspend setting. + */ + function wp_suspend_cache_invalidation($suspend = \true) + { + } + /** + * Determines whether a site is the main site of the current network. + * + * @since 3.0.0 + * @since 4.9.0 The `$network_id` parameter was added. + * + * @param int $site_id Optional. Site ID to test. Defaults to current site. + * @param int $network_id Optional. Network ID of the network to check for. + * Defaults to current network. + * @return bool True if $site_id is the main site of the network, or if not + * running Multisite. + */ + function is_main_site($site_id = \null, $network_id = \null) + { + } + /** + * Gets the main site ID. + * + * @since 4.9.0 + * + * @param int $network_id Optional. The ID of the network for which to get the main site. + * Defaults to the current network. + * @return int The ID of the main site. + */ + function get_main_site_id($network_id = \null) + { + } + /** + * Determines whether a network is the main network of the Multisite installation. + * + * @since 3.7.0 + * + * @param int $network_id Optional. Network ID to test. Defaults to current network. + * @return bool True if $network_id is the main network, or if not running Multisite. + */ + function is_main_network($network_id = \null) + { + } + /** + * Gets the main network ID. + * + * @since 4.3.0 + * + * @return int The ID of the main network. + */ + function get_main_network_id() + { + } + /** + * Determines whether site meta is enabled. + * + * This function checks whether the 'blogmeta' database table exists. The result is saved as + * a setting for the main network, making it essentially a global setting. Subsequent requests + * will refer to this setting instead of running the query. + * + * @since 5.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return bool True if site meta is supported, false otherwise. + */ + function is_site_meta_supported() + { + } + /** + * Modifies gmt_offset for smart timezone handling. + * + * Overrides the gmt_offset option if we have a timezone_string available. + * + * @since 2.8.0 + * + * @return float|false Timezone GMT offset, false otherwise. + */ + function wp_timezone_override_offset() + { + } + /** + * Sort-helper for timezones. + * + * @since 2.9.0 + * @access private + * + * @param array $a + * @param array $b + * @return int + */ + function _wp_timezone_choice_usort_callback($a, $b) + { + } + /** + * Gives a nicely-formatted list of timezone strings. + * + * @since 2.9.0 + * @since 4.7.0 Added the `$locale` parameter. + * + * @param string $selected_zone Selected timezone. + * @param string $locale Optional. Locale to load the timezones in. Default current site locale. + * @return string + */ + function wp_timezone_choice($selected_zone, $locale = \null) + { + } + /** + * Strips close comment and close php tags from file headers used by WP. + * + * @since 2.8.0 + * @access private + * + * @see https://core.trac.wordpress.org/ticket/8497 + * + * @param string $str Header comment to clean up. + * @return string + */ + function _cleanup_header_comment($str) + { + } + /** + * Permanently deletes comments or posts of any type that have held a status + * of 'trash' for the number of days defined in EMPTY_TRASH_DAYS. + * + * The default value of `EMPTY_TRASH_DAYS` is 30 (days). + * + * @since 2.9.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function wp_scheduled_delete() + { + } + /** + * Retrieves metadata from a file. + * + * Searches for metadata in the first 8 KB of a file, such as a plugin or theme. + * Each piece of metadata must be on its own line. Fields can not span multiple + * lines, the value will get cut at the end of the first line. + * + * If the file data is not within that first 8 KB, then the author should correct + * their plugin file and move the data headers to the top. + * + * @link https://codex.wordpress.org/File_Header + * + * @since 2.9.0 + * + * @param string $file Absolute path to the file. + * @param array $default_headers List of headers, in the format `array( 'HeaderKey' => 'Header Name' )`. + * @param string $context Optional. If specified adds filter hook {@see 'extra_$context_headers'}. + * Default empty. + * @return string[] Array of file header values keyed by header name. + */ + function get_file_data($file, $default_headers, $context = '') + { + } + /** + * Returns true. + * + * Useful for returning true to filters easily. + * + * @since 3.0.0 + * + * @see __return_false() + * + * @return true True. + */ + function __return_true() + { + } + /** + * Returns false. + * + * Useful for returning false to filters easily. + * + * @since 3.0.0 + * + * @see __return_true() + * + * @return false False. + */ + function __return_false() + { + } + /** + * Returns 0. + * + * Useful for returning 0 to filters easily. + * + * @since 3.0.0 + * + * @return int 0. + */ + function __return_zero() + { + } + /** + * Returns an empty array. + * + * Useful for returning an empty array to filters easily. + * + * @since 3.0.0 + * + * @return array Empty array. + */ + function __return_empty_array() + { + } + /** + * Returns null. + * + * Useful for returning null to filters easily. + * + * @since 3.4.0 + * + * @return null Null value. + */ + function __return_null() + { + } + /** + * Returns an empty string. + * + * Useful for returning an empty string to filters easily. + * + * @since 3.7.0 + * + * @see __return_null() + * + * @return string Empty string. + */ + function __return_empty_string() + { + } + /** + * Sends a HTTP header to disable content type sniffing in browsers which support it. + * + * @since 3.0.0 + * + * @see https://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx + * @see https://src.chromium.org/viewvc/chrome?view=rev&revision=6985 + */ + function send_nosniff_header() + { + } + /** + * Returns a MySQL expression for selecting the week number based on the start_of_week option. + * + * @ignore + * @since 3.0.0 + * + * @param string $column Database column. + * @return string SQL clause. + */ + function _wp_mysql_week($column) + { + } + /** + * Finds hierarchy loops using a callback function that maps object IDs to parent IDs. + * + * @since 3.1.0 + * @access private + * + * @param callable $callback Function that accepts ( ID, $callback_args ) and outputs parent_ID. + * @param int $start The ID to start the loop check at. + * @param int $start_parent The parent_ID of $start to use instead of calling $callback( $start ). + * Use null to always use $callback + * @param array $callback_args Optional. Additional arguments to send to $callback. + * @return array IDs of all members of loop. + */ + function wp_find_hierarchy_loop($callback, $start, $start_parent, $callback_args = array()) + { + } + /** + * Uses the "The Tortoise and the Hare" algorithm to detect loops. + * + * For every step of the algorithm, the hare takes two steps and the tortoise one. + * If the hare ever laps the tortoise, there must be a loop. + * + * @since 3.1.0 + * @access private + * + * @param callable $callback Function that accepts ( ID, callback_arg, ... ) and outputs parent_ID. + * @param int $start The ID to start the loop check at. + * @param array $override Optional. An array of ( ID => parent_ID, ... ) to use instead of $callback. + * Default empty array. + * @param array $callback_args Optional. Additional arguments to send to $callback. Default empty array. + * @param bool $_return_loop Optional. Return loop members or just detect presence of loop? Only set + * to true if you already know the given $start is part of a loop (otherwise + * the returned array might include branches). Default false. + * @return mixed Scalar ID of some arbitrary member of the loop, or array of IDs of all members of loop if + * $_return_loop + */ + function wp_find_hierarchy_loop_tortoise_hare($callback, $start, $override = array(), $callback_args = array(), $_return_loop = \false) + { + } + /** + * Sends a HTTP header to limit rendering of pages to same origin iframes. + * + * @since 3.1.3 + * + * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options + */ + function send_frame_options_header() + { + } + /** + * Retrieves a list of protocols to allow in HTML attributes. + * + * @since 3.3.0 + * @since 4.3.0 Added 'webcal' to the protocols array. + * @since 4.7.0 Added 'urn' to the protocols array. + * @since 5.3.0 Added 'sms' to the protocols array. + * @since 5.6.0 Added 'irc6' and 'ircs' to the protocols array. + * + * @see wp_kses() + * @see esc_url() + * + * @return string[] Array of allowed protocols. Defaults to an array containing 'http', 'https', + * 'ftp', 'ftps', 'mailto', 'news', 'irc', 'irc6', 'ircs', 'gopher', 'nntp', 'feed', + * 'telnet', 'mms', 'rtsp', 'sms', 'svn', 'tel', 'fax', 'xmpp', 'webcal', and 'urn'. + * This covers all common link protocols, except for 'javascript' which should not + * be allowed for untrusted users. + */ + function wp_allowed_protocols() + { + } + /** + * Returns a comma-separated string or array of functions that have been called to get + * to the current point in code. + * + * @since 3.4.0 + * + * @see https://core.trac.wordpress.org/ticket/19589 + * + * @param string $ignore_class Optional. A class to ignore all function calls within - useful + * when you want to just give info about the callee. Default null. + * @param int $skip_frames Optional. A number of stack frames to skip - useful for unwinding + * back to the source of the issue. Default 0. + * @param bool $pretty Optional. Whether you want a comma separated string instead of + * the raw array returned. Default true. + * @return string|array Either a string containing a reversed comma separated trace or an array + * of individual calls. + */ + function wp_debug_backtrace_summary($ignore_class = \null, $skip_frames = 0, $pretty = \true) + { + } + /** + * Retrieves IDs that are not already present in the cache. + * + * @since 3.4.0 + * @since 6.1.0 This function is no longer marked as "private". + * + * @param int[] $object_ids Array of IDs. + * @param string $cache_key The cache bucket to check against. + * @return int[] Array of IDs not present in the cache. + */ + function _get_non_cached_ids($object_ids, $cache_key) + { + } + /** + * Tests if the current device has the capability to upload files. + * + * @since 3.4.0 + * @access private + * + * @return bool Whether the device is able to upload files. + */ + function _device_can_upload() + { + } + /** + * Tests if a given path is a stream URL + * + * @since 3.5.0 + * + * @param string $path The resource path or URL. + * @return bool True if the path is a stream URL. + */ + function wp_is_stream($path) + { + } + /** + * Tests if the supplied date is valid for the Gregorian calendar. + * + * @since 3.5.0 + * + * @link https://www.php.net/manual/en/function.checkdate.php + * + * @param int $month Month number. + * @param int $day Day number. + * @param int $year Year number. + * @param string $source_date The date to filter. + * @return bool True if valid date, false if not valid date. + */ + function wp_checkdate($month, $day, $year, $source_date) + { + } + /** + * Loads the auth check for monitoring whether the user is still logged in. + * + * Can be disabled with remove_action( 'admin_enqueue_scripts', 'wp_auth_check_load' ); + * + * This is disabled for certain screens where a login screen could cause an + * inconvenient interruption. A filter called {@see 'wp_auth_check_load'} can be used + * for fine-grained control. + * + * @since 3.6.0 + */ + function wp_auth_check_load() + { + } + /** + * Outputs the HTML that shows the wp-login dialog when the user is no longer logged in. + * + * @since 3.6.0 + */ + function wp_auth_check_html() + { + } + /** + * Checks whether a user is still logged in, for the heartbeat. + * + * Send a result that shows a log-in box if the user is no longer logged in, + * or if their cookie is within the grace period. + * + * @since 3.6.0 + * + * @global int $login_grace_period + * + * @param array $response The Heartbeat response. + * @return array The Heartbeat response with 'wp-auth-check' value set. + */ + function wp_auth_check($response) + { + } + /** + * Returns RegEx body to liberally match an opening HTML tag. + * + * Matches an opening HTML tag that: + * 1. Is self-closing or + * 2. Has no body but has a closing tag of the same name or + * 3. Contains a body and a closing tag of the same name + * + * Note: this RegEx does not balance inner tags and does not attempt + * to produce valid HTML + * + * @since 3.6.0 + * + * @param string $tag An HTML tag name. Example: 'video'. + * @return string Tag RegEx. + */ + function get_tag_regex($tag) + { + } + /** + * Retrieves a canonical form of the provided charset appropriate for passing to PHP + * functions such as htmlspecialchars() and charset HTML attributes. + * + * @since 3.6.0 + * @access private + * + * @see https://core.trac.wordpress.org/ticket/23688 + * + * @param string $charset A charset name. + * @return string The canonical form of the charset. + */ + function _canonical_charset($charset) + { + } + /** + * Sets the mbstring internal encoding to a binary safe encoding when func_overload + * is enabled. + * + * When mbstring.func_overload is in use for multi-byte encodings, the results from + * strlen() and similar functions respect the utf8 characters, causing binary data + * to return incorrect lengths. + * + * This function overrides the mbstring encoding to a binary-safe encoding, and + * resets it to the users expected encoding afterwards through the + * `reset_mbstring_encoding` function. + * + * It is safe to recursively call this function, however each + * `mbstring_binary_safe_encoding()` call must be followed up with an equal number + * of `reset_mbstring_encoding()` calls. + * + * @since 3.7.0 + * + * @see reset_mbstring_encoding() + * + * @param bool $reset Optional. Whether to reset the encoding back to a previously-set encoding. + * Default false. + */ + function mbstring_binary_safe_encoding($reset = \false) + { + } + /** + * Resets the mbstring internal encoding to a users previously set encoding. + * + * @see mbstring_binary_safe_encoding() + * + * @since 3.7.0 + */ + function reset_mbstring_encoding() + { + } + /** + * Filters/validates a variable as a boolean. + * + * Alternative to `filter_var( $var, FILTER_VALIDATE_BOOLEAN )`. + * + * @since 4.0.0 + * + * @param mixed $var Boolean value to validate. + * @return bool Whether the value is validated. + */ + function wp_validate_boolean($var) + { + } + /** + * Deletes a file. + * + * @since 4.2.0 + * + * @param string $file The path to the file to delete. + */ + function wp_delete_file($file) + { + } + /** + * Deletes a file if its path is within the given directory. + * + * @since 4.9.7 + * + * @param string $file Absolute path to the file to delete. + * @param string $directory Absolute path to a directory. + * @return bool True on success, false on failure. + */ + function wp_delete_file_from_directory($file, $directory) + { + } + /** + * Outputs a small JS snippet on preview tabs/windows to remove `window.name` on unload. + * + * This prevents reusing the same tab for a preview when the user has navigated away. + * + * @since 4.3.0 + * + * @global WP_Post $post Global post object. + */ + function wp_post_preview_js() + { + } + /** + * Parses and formats a MySQL datetime (Y-m-d H:i:s) for ISO8601 (Y-m-d\TH:i:s). + * + * Explicitly strips timezones, as datetimes are not saved with any timezone + * information. Including any information on the offset could be misleading. + * + * Despite historical function name, the output does not conform to RFC3339 format, + * which must contain timezone. + * + * @since 4.4.0 + * + * @param string $date_string Date string to parse and format. + * @return string Date formatted for ISO8601 without time zone. + */ + function mysql_to_rfc3339($date_string) + { + } + /** + * Attempts to raise the PHP memory limit for memory intensive processes. + * + * Only allows raising the existing limit and prevents lowering it. + * + * @since 4.6.0 + * + * @param string $context Optional. Context in which the function is called. Accepts either 'admin', + * 'image', or an arbitrary other context. If an arbitrary context is passed, + * the similarly arbitrary {@see '$context_memory_limit'} filter will be + * invoked. Default 'admin'. + * @return int|string|false The limit that was set or false on failure. + */ + function wp_raise_memory_limit($context = 'admin') + { + } + /** + * Generates a random UUID (version 4). + * + * @since 4.7.0 + * + * @return string UUID. + */ + function wp_generate_uuid4() + { + } + /** + * Validates that a UUID is valid. + * + * @since 4.9.0 + * + * @param mixed $uuid UUID to check. + * @param int $version Specify which version of UUID to check against. Default is none, + * to accept any UUID version. Otherwise, only version allowed is `4`. + * @return bool The string is a valid UUID or false on failure. + */ + function wp_is_uuid($uuid, $version = \null) + { + } + /** + * Gets unique ID. + * + * This is a PHP implementation of Underscore's uniqueId method. A static variable + * contains an integer that is incremented with each call. This number is returned + * with the optional prefix. As such the returned value is not universally unique, + * but it is unique across the life of the PHP process. + * + * @since 5.0.3 + * + * @param string $prefix Prefix for the returned ID. + * @return string Unique ID. + */ + function wp_unique_id($prefix = '') + { + } + /** + * Gets last changed date for the specified cache group. + * + * @since 4.7.0 + * + * @param string $group Where the cache contents are grouped. + * @return string UNIX timestamp with microseconds representing when the group was last changed. + */ + function wp_cache_get_last_changed($group) + { + } + /** + * Sends an email to the old site admin email address when the site admin email address changes. + * + * @since 4.9.0 + * + * @param string $old_email The old site admin email address. + * @param string $new_email The new site admin email address. + * @param string $option_name The relevant database option name. + */ + function wp_site_admin_email_change_notification($old_email, $new_email, $option_name) + { + } + /** + * Returns an anonymized IPv4 or IPv6 address. + * + * @since 4.9.6 Abstracted from `WP_Community_Events::get_unsafe_client_ip()`. + * + * @param string $ip_addr The IPv4 or IPv6 address to be anonymized. + * @param bool $ipv6_fallback Optional. Whether to return the original IPv6 address if the needed functions + * to anonymize it are not present. Default false, return `::` (unspecified address). + * @return string The anonymized IP address. + */ + function wp_privacy_anonymize_ip($ip_addr, $ipv6_fallback = \false) + { + } + /** + * Returns uniform "anonymous" data by type. + * + * @since 4.9.6 + * + * @param string $type The type of data to be anonymized. + * @param string $data Optional The data to be anonymized. + * @return string The anonymous data for the requested type. + */ + function wp_privacy_anonymize_data($type, $data = '') + { + } + /** + * Returns the directory used to store personal data export files. + * + * @since 4.9.6 + * + * @see wp_privacy_exports_url + * + * @return string Exports directory. + */ + function wp_privacy_exports_dir() + { + } + /** + * Returns the URL of the directory used to store personal data export files. + * + * @since 4.9.6 + * + * @see wp_privacy_exports_dir + * + * @return string Exports directory URL. + */ + function wp_privacy_exports_url() + { + } + /** + * Schedules a `WP_Cron` job to delete expired export files. + * + * @since 4.9.6 + */ + function wp_schedule_delete_old_privacy_export_files() + { + } + /** + * Cleans up export files older than three days old. + * + * The export files are stored in `wp-content/uploads`, and are therefore publicly + * accessible. A CSPRN is appended to the filename to mitigate the risk of an + * unauthorized person downloading the file, but it is still possible. Deleting + * the file after the data subject has had a chance to delete it adds an additional + * layer of protection. + * + * @since 4.9.6 + */ + function wp_privacy_delete_old_export_files() + { + } + /** + * Gets the URL to learn more about updating the PHP version the site is running on. + * + * This URL can be overridden by specifying an environment variable `WP_UPDATE_PHP_URL` or by using the + * {@see 'wp_update_php_url'} filter. Providing an empty string is not allowed and will result in the + * default URL being used. Furthermore the page the URL links to should preferably be localized in the + * site language. + * + * @since 5.1.0 + * + * @return string URL to learn more about updating PHP. + */ + function wp_get_update_php_url() + { + } + /** + * Gets the default URL to learn more about updating the PHP version the site is running on. + * + * Do not use this function to retrieve this URL. Instead, use {@see wp_get_update_php_url()} when relying on the URL. + * This function does not allow modifying the returned URL, and is only used to compare the actually used URL with the + * default one. + * + * @since 5.1.0 + * @access private + * + * @return string Default URL to learn more about updating PHP. + */ + function wp_get_default_update_php_url() + { + } + /** + * Prints the default annotation for the web host altering the "Update PHP" page URL. + * + * This function is to be used after {@see wp_get_update_php_url()} to display a consistent + * annotation if the web host has altered the default "Update PHP" page URL. + * + * @since 5.1.0 + * @since 5.2.0 Added the `$before` and `$after` parameters. + * + * @param string $before Markup to output before the annotation. Default `<p class="description">`. + * @param string $after Markup to output after the annotation. Default `</p>`. + */ + function wp_update_php_annotation($before = '<p class="description">', $after = '</p>') + { + } + /** + * Returns the default annotation for the web hosting altering the "Update PHP" page URL. + * + * This function is to be used after {@see wp_get_update_php_url()} to return a consistent + * annotation if the web host has altered the default "Update PHP" page URL. + * + * @since 5.2.0 + * + * @return string Update PHP page annotation. An empty string if no custom URLs are provided. + */ + function wp_get_update_php_annotation() + { + } + /** + * Gets the URL for directly updating the PHP version the site is running on. + * + * A URL will only be returned if the `WP_DIRECT_UPDATE_PHP_URL` environment variable is specified or + * by using the {@see 'wp_direct_php_update_url'} filter. This allows hosts to send users directly to + * the page where they can update PHP to a newer version. + * + * @since 5.1.1 + * + * @return string URL for directly updating PHP or empty string. + */ + function wp_get_direct_php_update_url() + { + } + /** + * Displays a button directly linking to a PHP update process. + * + * This provides hosts with a way for users to be sent directly to their PHP update process. + * + * The button is only displayed if a URL is returned by `wp_get_direct_php_update_url()`. + * + * @since 5.1.1 + */ + function wp_direct_php_update_button() + { + } + /** + * Gets the URL to learn more about updating the site to use HTTPS. + * + * This URL can be overridden by specifying an environment variable `WP_UPDATE_HTTPS_URL` or by using the + * {@see 'wp_update_https_url'} filter. Providing an empty string is not allowed and will result in the + * default URL being used. Furthermore the page the URL links to should preferably be localized in the + * site language. + * + * @since 5.7.0 + * + * @return string URL to learn more about updating to HTTPS. + */ + function wp_get_update_https_url() + { + } + /** + * Gets the default URL to learn more about updating the site to use HTTPS. + * + * Do not use this function to retrieve this URL. Instead, use {@see wp_get_update_https_url()} when relying on the URL. + * This function does not allow modifying the returned URL, and is only used to compare the actually used URL with the + * default one. + * + * @since 5.7.0 + * @access private + * + * @return string Default URL to learn more about updating to HTTPS. + */ + function wp_get_default_update_https_url() + { + } + /** + * Gets the URL for directly updating the site to use HTTPS. + * + * A URL will only be returned if the `WP_DIRECT_UPDATE_HTTPS_URL` environment variable is specified or + * by using the {@see 'wp_direct_update_https_url'} filter. This allows hosts to send users directly to + * the page where they can update their site to use HTTPS. + * + * @since 5.7.0 + * + * @return string URL for directly updating to HTTPS or empty string. + */ + function wp_get_direct_update_https_url() + { + } + /** + * Gets the size of a directory. + * + * A helper function that is used primarily to check whether + * a blog has exceeded its allowed upload space. + * + * @since MU (3.0.0) + * @since 5.2.0 $max_execution_time parameter added. + * + * @param string $directory Full path of a directory. + * @param int $max_execution_time Maximum time to run before giving up. In seconds. + * The timeout is global and is measured from the moment WordPress started to load. + * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout. + */ + function get_dirsize($directory, $max_execution_time = \null) + { + } + /** + * Gets the size of a directory recursively. + * + * Used by get_dirsize() to get a directory size when it contains other directories. + * + * @since MU (3.0.0) + * @since 4.3.0 The `$exclude` parameter was added. + * @since 5.2.0 The `$max_execution_time` parameter was added. + * @since 5.6.0 The `$directory_cache` parameter was added. + * + * @param string $directory Full path of a directory. + * @param string|string[] $exclude Optional. Full path of a subdirectory to exclude from the total, + * or array of paths. Expected without trailing slash(es). + * @param int $max_execution_time Optional. Maximum time to run before giving up. In seconds. + * The timeout is global and is measured from the moment + * WordPress started to load. + * @param array $directory_cache Optional. Array of cached directory paths. + * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout. + */ + function recurse_dirsize($directory, $exclude = \null, $max_execution_time = \null, &$directory_cache = \null) + { + } + /** + * Cleans directory size cache used by recurse_dirsize(). + * + * Removes the current directory and all parent directories from the `dirsize_cache` transient. + * + * @since 5.6.0 + * @since 5.9.0 Added input validation with a notice for invalid input. + * + * @param string $path Full path of a directory or file. + */ + function clean_dirsize_cache($path) + { + } + /** + * Checks compatibility with the current WordPress version. + * + * @since 5.2.0 + * + * @global string $wp_version The WordPress version string. + * + * @param string $required Minimum required WordPress version. + * @return bool True if required version is compatible or empty, false if not. + */ + function is_wp_version_compatible($required) + { + } + /** + * Checks compatibility with the current PHP version. + * + * @since 5.2.0 + * + * @param string $required Minimum required PHP version. + * @return bool True if required version is compatible or empty, false if not. + */ + function is_php_version_compatible($required) + { + } + /** + * Checks if two numbers are nearly the same. + * + * This is similar to using `round()` but the precision is more fine-grained. + * + * @since 5.3.0 + * + * @param int|float $expected The expected value. + * @param int|float $actual The actual number. + * @param int|float $precision The allowed variation. + * @return bool Whether the numbers match within the specified precision. + */ + function wp_fuzzy_number_match($expected, $actual, $precision = 1) + { + } + /** + * Sorts the keys of an array alphabetically. + * The array is passed by reference so it doesn't get returned + * which mimics the behaviour of ksort. + * + * @since 6.0.0 + * + * @param array $array The array to sort, passed by reference. + */ + function wp_recursive_ksort(&$array) + { + } + /** + * Dependencies API: Scripts functions + * + * @since 2.6.0 + * + * @package WordPress + * @subpackage Dependencies + */ + /** + * Initialize $wp_scripts if it has not been set. + * + * @global WP_Scripts $wp_scripts + * + * @since 4.2.0 + * + * @return WP_Scripts WP_Scripts instance. + */ + function wp_scripts() + { + } + /** + * Helper function to output a _doing_it_wrong message when applicable. + * + * @ignore + * @since 4.2.0 + * @since 5.5.0 Added the `$handle` parameter. + * + * @param string $function Function name. + * @param string $handle Optional. Name of the script or stylesheet that was + * registered or enqueued too early. Default empty. + */ + function _wp_scripts_maybe_doing_it_wrong($function, $handle = '') + { + } + /** + * Prints scripts in document head that are in the $handles queue. + * + * Called by admin-header.php and {@see 'wp_head'} hook. Since it is called by wp_head on every page load, + * the function does not instantiate the WP_Scripts object unless script names are explicitly passed. + * Makes use of already-instantiated $wp_scripts global if present. Use provided {@see 'wp_print_scripts'} + * hook to register/enqueue new scripts. + * + * @see WP_Scripts::do_item() + * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts. + * + * @since 2.1.0 + * + * @param string|bool|array $handles Optional. Scripts to be printed. Default 'false'. + * @return string[] On success, an array of handles of processed WP_Dependencies items; otherwise, an empty array. + */ + function wp_print_scripts($handles = \false) + { + } + /** + * Adds extra code to a registered script. + * + * Code will only be added if the script is already in the queue. + * Accepts a string $data containing the Code. If two or more code blocks + * are added to the same script $handle, they will be printed in the order + * they were added, i.e. the latter added code can redeclare the previous. + * + * @since 4.5.0 + * + * @see WP_Scripts::add_inline_script() + * + * @param string $handle Name of the script to add the inline script to. + * @param string $data String containing the JavaScript to be added. + * @param string $position Optional. Whether to add the inline script before the handle + * or after. Default 'after'. + * @return bool True on success, false on failure. + */ + function wp_add_inline_script($handle, $data, $position = 'after') + { + } + /** + * Register a new script. + * + * Registers a script to be enqueued later using the wp_enqueue_script() function. + * + * @see WP_Dependencies::add() + * @see WP_Dependencies::add_data() + * + * @since 2.1.0 + * @since 4.3.0 A return value was added. + * + * @param string $handle Name of the script. Should be unique. + * @param string|false $src Full URL of the script, or path of the script relative to the WordPress root directory. + * If source is set to false, script is an alias of other scripts it depends on. + * @param string[] $deps Optional. An array of registered script handles this script depends on. Default empty array. + * @param string|bool|null $ver Optional. String specifying script version number, if it has one, which is added to the URL + * as a query string for cache busting purposes. If version is set to false, a version + * number is automatically added equal to current installed WordPress version. + * If set to null, no version is added. + * @param bool $in_footer Optional. Whether to enqueue the script before `</body>` instead of in the `<head>`. + * Default 'false'. + * @return bool Whether the script has been registered. True on success, false on failure. + */ + function wp_register_script($handle, $src, $deps = array(), $ver = \false, $in_footer = \false) + { + } + /** + * Localize a script. + * + * Works only if the script has already been registered. + * + * Accepts an associative array $l10n and creates a JavaScript object: + * + * "$object_name" = { + * key: value, + * key: value, + * ... + * } + * + * @see WP_Scripts::localize() + * @link https://core.trac.wordpress.org/ticket/11520 + * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts. + * + * @since 2.2.0 + * + * @todo Documentation cleanup + * + * @param string $handle Script handle the data will be attached to. + * @param string $object_name Name for the JavaScript object. Passed directly, so it should be qualified JS variable. + * Example: '/[a-zA-Z0-9_]+/'. + * @param array $l10n The data itself. The data can be either a single or multi-dimensional array. + * @return bool True if the script was successfully localized, false otherwise. + */ + function wp_localize_script($handle, $object_name, $l10n) + { + } + /** + * Sets translated strings for a script. + * + * Works only if the script has already been registered. + * + * @see WP_Scripts::set_translations() + * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts. + * + * @since 5.0.0 + * @since 5.1.0 The `$domain` parameter was made optional. + * + * @param string $handle Script handle the textdomain will be attached to. + * @param string $domain Optional. Text domain. Default 'default'. + * @param string $path Optional. The full file path to the directory containing translation files. + * @return bool True if the text domain was successfully localized, false otherwise. + */ + function wp_set_script_translations($handle, $domain = 'default', $path = '') + { + } + /** + * Remove a registered script. + * + * Note: there are intentional safeguards in place to prevent critical admin scripts, + * such as jQuery core, from being unregistered. + * + * @see WP_Dependencies::remove() + * + * @since 2.1.0 + * + * @global string $pagenow The filename of the current screen. + * + * @param string $handle Name of the script to be removed. + */ + function wp_deregister_script($handle) + { + } + /** + * Enqueue a script. + * + * Registers the script if $src provided (does NOT overwrite), and enqueues it. + * + * @see WP_Dependencies::add() + * @see WP_Dependencies::add_data() + * @see WP_Dependencies::enqueue() + * + * @since 2.1.0 + * + * @param string $handle Name of the script. Should be unique. + * @param string $src Full URL of the script, or path of the script relative to the WordPress root directory. + * Default empty. + * @param string[] $deps Optional. An array of registered script handles this script depends on. Default empty array. + * @param string|bool|null $ver Optional. String specifying script version number, if it has one, which is added to the URL + * as a query string for cache busting purposes. If version is set to false, a version + * number is automatically added equal to current installed WordPress version. + * If set to null, no version is added. + * @param bool $in_footer Optional. Whether to enqueue the script before `</body>` instead of in the `<head>`. + * Default 'false'. + */ + function wp_enqueue_script($handle, $src = '', $deps = array(), $ver = \false, $in_footer = \false) + { + } + /** + * Remove a previously enqueued script. + * + * @see WP_Dependencies::dequeue() + * + * @since 3.1.0 + * + * @param string $handle Name of the script to be removed. + */ + function wp_dequeue_script($handle) + { + } + /** + * Determines whether a script has been added to the queue. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.8.0 + * @since 3.5.0 'enqueued' added as an alias of the 'queue' list. + * + * @param string $handle Name of the script. + * @param string $list Optional. Status of the script to check. Default 'enqueued'. + * Accepts 'enqueued', 'registered', 'queue', 'to_do', and 'done'. + * @return bool Whether the script is queued. + */ + function wp_script_is($handle, $list = 'enqueued') + { + } + /** + * Add metadata to a script. + * + * Works only if the script has already been registered. + * + * Possible values for $key and $value: + * 'conditional' string Comments for IE 6, lte IE 7, etc. + * + * @since 4.2.0 + * + * @see WP_Dependencies::add_data() + * + * @param string $handle Name of the script. + * @param string $key Name of data point for which we're storing a value. + * @param mixed $value String containing the data to be added. + * @return bool True on success, false on failure. + */ + function wp_script_add_data($handle, $key, $value) + { + } + /** + * Dependencies API: Styles functions + * + * @since 2.6.0 + * + * @package WordPress + * @subpackage Dependencies + */ + /** + * Initialize $wp_styles if it has not been set. + * + * @global WP_Styles $wp_styles + * + * @since 4.2.0 + * + * @return WP_Styles WP_Styles instance. + */ + function wp_styles() + { + } + /** + * Display styles that are in the $handles queue. + * + * Passing an empty array to $handles prints the queue, + * passing an array with one string prints that style, + * and passing an array of strings prints those styles. + * + * @global WP_Styles $wp_styles The WP_Styles object for printing styles. + * + * @since 2.6.0 + * + * @param string|bool|array $handles Styles to be printed. Default 'false'. + * @return string[] On success, an array of handles of processed WP_Dependencies items; otherwise, an empty array. + */ + function wp_print_styles($handles = \false) + { + } + /** + * Add extra CSS styles to a registered stylesheet. + * + * Styles will only be added if the stylesheet is already in the queue. + * Accepts a string $data containing the CSS. If two or more CSS code blocks + * are added to the same stylesheet $handle, they will be printed in the order + * they were added, i.e. the latter added styles can redeclare the previous. + * + * @see WP_Styles::add_inline_style() + * + * @since 3.3.0 + * + * @param string $handle Name of the stylesheet to add the extra styles to. + * @param string $data String containing the CSS styles to be added. + * @return bool True on success, false on failure. + */ + function wp_add_inline_style($handle, $data) + { + } + /** + * Register a CSS stylesheet. + * + * @see WP_Dependencies::add() + * @link https://www.w3.org/TR/CSS2/media.html#media-types List of CSS media types. + * + * @since 2.6.0 + * @since 4.3.0 A return value was added. + * + * @param string $handle Name of the stylesheet. Should be unique. + * @param string|false $src Full URL of the stylesheet, or path of the stylesheet relative to the WordPress root directory. + * If source is set to false, stylesheet is an alias of other stylesheets it depends on. + * @param string[] $deps Optional. An array of registered stylesheet handles this stylesheet depends on. Default empty array. + * @param string|bool|null $ver Optional. String specifying stylesheet version number, if it has one, which is added to the URL + * as a query string for cache busting purposes. If version is set to false, a version + * number is automatically added equal to current installed WordPress version. + * If set to null, no version is added. + * @param string $media Optional. The media for which this stylesheet has been defined. + * Default 'all'. Accepts media types like 'all', 'print' and 'screen', or media queries like + * '(orientation: portrait)' and '(max-width: 640px)'. + * @return bool Whether the style has been registered. True on success, false on failure. + */ + function wp_register_style($handle, $src, $deps = array(), $ver = \false, $media = 'all') + { + } + /** + * Remove a registered stylesheet. + * + * @see WP_Dependencies::remove() + * + * @since 2.1.0 + * + * @param string $handle Name of the stylesheet to be removed. + */ + function wp_deregister_style($handle) + { + } + /** + * Enqueue a CSS stylesheet. + * + * Registers the style if source provided (does NOT overwrite) and enqueues. + * + * @see WP_Dependencies::add() + * @see WP_Dependencies::enqueue() + * @link https://www.w3.org/TR/CSS2/media.html#media-types List of CSS media types. + * + * @since 2.6.0 + * + * @param string $handle Name of the stylesheet. Should be unique. + * @param string $src Full URL of the stylesheet, or path of the stylesheet relative to the WordPress root directory. + * Default empty. + * @param string[] $deps Optional. An array of registered stylesheet handles this stylesheet depends on. Default empty array. + * @param string|bool|null $ver Optional. String specifying stylesheet version number, if it has one, which is added to the URL + * as a query string for cache busting purposes. If version is set to false, a version + * number is automatically added equal to current installed WordPress version. + * If set to null, no version is added. + * @param string $media Optional. The media for which this stylesheet has been defined. + * Default 'all'. Accepts media types like 'all', 'print' and 'screen', or media queries like + * '(orientation: portrait)' and '(max-width: 640px)'. + */ + function wp_enqueue_style($handle, $src = '', $deps = array(), $ver = \false, $media = 'all') + { + } + /** + * Remove a previously enqueued CSS stylesheet. + * + * @see WP_Dependencies::dequeue() + * + * @since 3.1.0 + * + * @param string $handle Name of the stylesheet to be removed. + */ + function wp_dequeue_style($handle) + { + } + /** + * Check whether a CSS stylesheet has been added to the queue. + * + * @since 2.8.0 + * + * @param string $handle Name of the stylesheet. + * @param string $list Optional. Status of the stylesheet to check. Default 'enqueued'. + * Accepts 'enqueued', 'registered', 'queue', 'to_do', and 'done'. + * @return bool Whether style is queued. + */ + function wp_style_is($handle, $list = 'enqueued') + { + } + /** + * Add metadata to a CSS stylesheet. + * + * Works only if the stylesheet has already been registered. + * + * Possible values for $key and $value: + * 'conditional' string Comments for IE 6, lte IE 7 etc. + * 'rtl' bool|string To declare an RTL stylesheet. + * 'suffix' string Optional suffix, used in combination with RTL. + * 'alt' bool For rel="alternate stylesheet". + * 'title' string For preferred/alternate stylesheets. + * 'path' string The absolute path to a stylesheet. Stylesheet will + * load inline when 'path'' is set. + * + * @see WP_Dependencies::add_data() + * + * @since 3.6.0 + * @since 5.8.0 Added 'path' as an official value for $key. + * See {@see wp_maybe_inline_styles()}. + * + * @param string $handle Name of the stylesheet. + * @param string $key Name of data point for which we're storing a value. + * Accepts 'conditional', 'rtl' and 'suffix', 'alt', 'title' and 'path'. + * @param mixed $value String containing the CSS data to be added. + * @return bool True on success, false on failure. + */ + function wp_style_add_data($handle, $key, $value) + { + } + /** + * General template tags that can go anywhere in a template. + * + * @package WordPress + * @subpackage Template + */ + /** + * Loads header template. + * + * Includes the header template for a theme or if a name is specified then a + * specialised header will be included. + * + * For the parameter, if the file is called "header-special.php" then specify + * "special". + * + * @since 1.5.0 + * @since 5.5.0 A return value was added. + * @since 5.5.0 The `$args` parameter was added. + * + * @param string $name The name of the specialised header. + * @param array $args Optional. Additional arguments passed to the header template. + * Default empty array. + * @return void|false Void on success, false if the template does not exist. + */ + function get_header($name = \null, $args = array()) + { + } + /** + * Loads footer template. + * + * Includes the footer template for a theme or if a name is specified then a + * specialised footer will be included. + * + * For the parameter, if the file is called "footer-special.php" then specify + * "special". + * + * @since 1.5.0 + * @since 5.5.0 A return value was added. + * @since 5.5.0 The `$args` parameter was added. + * + * @param string $name The name of the specialised footer. + * @param array $args Optional. Additional arguments passed to the footer template. + * Default empty array. + * @return void|false Void on success, false if the template does not exist. + */ + function get_footer($name = \null, $args = array()) + { + } + /** + * Loads sidebar template. + * + * Includes the sidebar template for a theme or if a name is specified then a + * specialised sidebar will be included. + * + * For the parameter, if the file is called "sidebar-special.php" then specify + * "special". + * + * @since 1.5.0 + * @since 5.5.0 A return value was added. + * @since 5.5.0 The `$args` parameter was added. + * + * @param string $name The name of the specialised sidebar. + * @param array $args Optional. Additional arguments passed to the sidebar template. + * Default empty array. + * @return void|false Void on success, false if the template does not exist. + */ + function get_sidebar($name = \null, $args = array()) + { + } + /** + * Loads a template part into a template. + * + * Provides a simple mechanism for child themes to overload reusable sections of code + * in the theme. + * + * Includes the named template part for a theme or if a name is specified then a + * specialised part will be included. If the theme contains no {slug}.php file + * then no template will be included. + * + * The template is included using require, not require_once, so you may include the + * same template part multiple times. + * + * For the $name parameter, if the file is called "{slug}-special.php" then specify + * "special". + * + * @since 3.0.0 + * @since 5.5.0 A return value was added. + * @since 5.5.0 The `$args` parameter was added. + * + * @param string $slug The slug name for the generic template. + * @param string $name The name of the specialised template. + * @param array $args Optional. Additional arguments passed to the template. + * Default empty array. + * @return void|false Void on success, false if the template does not exist. + */ + function get_template_part($slug, $name = \null, $args = array()) + { + } + /** + * Displays search form. + * + * Will first attempt to locate the searchform.php file in either the child or + * the parent, then load it. If it doesn't exist, then the default search form + * will be displayed. The default search form is HTML, which will be displayed. + * There is a filter applied to the search form HTML in order to edit or replace + * it. The filter is {@see 'get_search_form'}. + * + * This function is primarily used by themes which want to hardcode the search + * form into the sidebar and also by the search widget in WordPress. + * + * There is also an action that is called whenever the function is run called, + * {@see 'pre_get_search_form'}. This can be useful for outputting JavaScript that the + * search relies on or various formatting that applies to the beginning of the + * search. To give a few examples of what it can be used for. + * + * @since 2.7.0 + * @since 5.2.0 The `$args` array parameter was added in place of an `$echo` boolean flag. + * + * @param array $args { + * Optional. Array of display arguments. + * + * @type bool $echo Whether to echo or return the form. Default true. + * @type string $aria_label ARIA label for the search form. Useful to distinguish + * multiple search forms on the same page and improve + * accessibility. Default empty. + * } + * @return void|string Void if 'echo' argument is true, search form HTML if 'echo' is false. + * @phpstan-param array{ + * echo?: bool, + * aria_label?: string, + * } $args + */ + function get_search_form($args = array()) + { + } + /** + * Displays the Log In/Out link. + * + * Displays a link, which allows users to navigate to the Log In page to log in + * or log out depending on whether they are currently logged in. + * + * @since 1.5.0 + * + * @param string $redirect Optional path to redirect to on login/logout. + * @param bool $echo Default to echo and not return the link. + * @return void|string Void if `$echo` argument is true, log in/out link if `$echo` is false. + */ + function wp_loginout($redirect = '', $echo = \true) + { + } + /** + * Retrieves the logout URL. + * + * Returns the URL that allows the user to log out of the site. + * + * @since 2.7.0 + * + * @param string $redirect Path to redirect to on logout. + * @return string The logout URL. Note: HTML-encoded via esc_html() in wp_nonce_url(). + */ + function wp_logout_url($redirect = '') + { + } + /** + * Retrieves the login URL. + * + * @since 2.7.0 + * + * @param string $redirect Path to redirect to on log in. + * @param bool $force_reauth Whether to force reauthorization, even if a cookie is present. + * Default false. + * @return string The login URL. Not HTML-encoded. + */ + function wp_login_url($redirect = '', $force_reauth = \false) + { + } + /** + * Returns the URL that allows the user to register on the site. + * + * @since 3.6.0 + * + * @return string User registration URL. + */ + function wp_registration_url() + { + } + /** + * Provides a simple login form for use anywhere within WordPress. + * + * The login form HTML is echoed by default. Pass a false value for `$echo` to return it instead. + * + * @since 3.0.0 + * + * @param array $args { + * Optional. Array of options to control the form output. Default empty array. + * + * @type bool $echo Whether to display the login form or return the form HTML code. + * Default true (echo). + * @type string $redirect URL to redirect to. Must be absolute, as in "https://example.com/mypage/". + * Default is to redirect back to the request URI. + * @type string $form_id ID attribute value for the form. Default 'loginform'. + * @type string $label_username Label for the username or email address field. Default 'Username or Email Address'. + * @type string $label_password Label for the password field. Default 'Password'. + * @type string $label_remember Label for the remember field. Default 'Remember Me'. + * @type string $label_log_in Label for the submit button. Default 'Log In'. + * @type string $id_username ID attribute value for the username field. Default 'user_login'. + * @type string $id_password ID attribute value for the password field. Default 'user_pass'. + * @type string $id_remember ID attribute value for the remember field. Default 'rememberme'. + * @type string $id_submit ID attribute value for the submit button. Default 'wp-submit'. + * @type bool $remember Whether to display the "rememberme" checkbox in the form. + * @type string $value_username Default value for the username field. Default empty. + * @type bool $value_remember Whether the "Remember Me" checkbox should be checked by default. + * Default false (unchecked). + * + * } + * @return void|string Void if 'echo' argument is true, login form HTML if 'echo' is false. + * @phpstan-param array{ + * echo?: bool, + * redirect?: string, + * form_id?: string, + * label_username?: string, + * label_password?: string, + * label_remember?: string, + * label_log_in?: string, + * id_username?: string, + * id_password?: string, + * id_remember?: string, + * id_submit?: string, + * remember?: bool, + * value_username?: string, + * value_remember?: bool, + * } $args + */ + function wp_login_form($args = array()) + { + } + /** + * Returns the URL that allows the user to reset the lost password. + * + * @since 2.8.0 + * + * @param string $redirect Path to redirect to on login. + * @return string Lost password URL. + */ + function wp_lostpassword_url($redirect = '') + { + } + /** + * Displays the Registration or Admin link. + * + * Display a link which allows the user to navigate to the registration page if + * not logged in and registration is enabled or to the dashboard if logged in. + * + * @since 1.5.0 + * + * @param string $before Text to output before the link. Default `<li>`. + * @param string $after Text to output after the link. Default `</li>`. + * @param bool $echo Default to echo and not return the link. + * @return void|string Void if `$echo` argument is true, registration or admin link + * if `$echo` is false. + */ + function wp_register($before = '<li>', $after = '</li>', $echo = \true) + { + } + /** + * Theme container function for the 'wp_meta' action. + * + * The {@see 'wp_meta'} action can have several purposes, depending on how you use it, + * but one purpose might have been to allow for theme switching. + * + * @since 1.5.0 + * + * @link https://core.trac.wordpress.org/ticket/1458 Explanation of 'wp_meta' action. + */ + function wp_meta() + { + } + /** + * Displays information about the current site. + * + * @since 0.71 + * + * @see get_bloginfo() For possible `$show` values + * + * @param string $show Optional. Site information to display. Default empty. + */ + function bloginfo($show = '') + { + } + /** + * Retrieves information about the current site. + * + * Possible values for `$show` include: + * + * - 'name' - Site title (set in Settings > General) + * - 'description' - Site tagline (set in Settings > General) + * - 'wpurl' - The WordPress address (URL) (set in Settings > General) + * - 'url' - The Site address (URL) (set in Settings > General) + * - 'admin_email' - Admin email (set in Settings > General) + * - 'charset' - The "Encoding for pages and feeds" (set in Settings > Reading) + * - 'version' - The current WordPress version + * - 'html_type' - The content-type (default: "text/html"). Themes and plugins + * can override the default value using the {@see 'pre_option_html_type'} filter + * - 'text_direction' - The text direction determined by the site's language. is_rtl() + * should be used instead + * - 'language' - Language code for the current site + * - 'stylesheet_url' - URL to the stylesheet for the active theme. An active child theme + * will take precedence over this value + * - 'stylesheet_directory' - Directory path for the active theme. An active child theme + * will take precedence over this value + * - 'template_url' / 'template_directory' - URL of the active theme's directory. An active + * child theme will NOT take precedence over this value + * - 'pingback_url' - The pingback XML-RPC file URL (xmlrpc.php) + * - 'atom_url' - The Atom feed URL (/feed/atom) + * - 'rdf_url' - The RDF/RSS 1.0 feed URL (/feed/rdf) + * - 'rss_url' - The RSS 0.92 feed URL (/feed/rss) + * - 'rss2_url' - The RSS 2.0 feed URL (/feed) + * - 'comments_atom_url' - The comments Atom feed URL (/comments/feed) + * - 'comments_rss2_url' - The comments RSS 2.0 feed URL (/comments/feed) + * + * Some `$show` values are deprecated and will be removed in future versions. + * These options will trigger the _deprecated_argument() function. + * + * Deprecated arguments include: + * + * - 'siteurl' - Use 'url' instead + * - 'home' - Use 'url' instead + * + * @since 0.71 + * + * @global string $wp_version The WordPress version string. + * + * @param string $show Optional. Site info to retrieve. Default empty (site name). + * @param string $filter Optional. How to filter what is retrieved. Default 'raw'. + * @return string Mostly string values, might be empty. + */ + function get_bloginfo($show = '', $filter = 'raw') + { + } + /** + * Returns the Site Icon URL. + * + * @since 4.3.0 + * + * @param int $size Optional. Size of the site icon. Default 512 (pixels). + * @param string $url Optional. Fallback url if no site icon is found. Default empty. + * @param int $blog_id Optional. ID of the blog to get the site icon for. Default current blog. + * @return string Site Icon URL. + */ + function get_site_icon_url($size = 512, $url = '', $blog_id = 0) + { + } + /** + * Displays the Site Icon URL. + * + * @since 4.3.0 + * + * @param int $size Optional. Size of the site icon. Default 512 (pixels). + * @param string $url Optional. Fallback url if no site icon is found. Default empty. + * @param int $blog_id Optional. ID of the blog to get the site icon for. Default current blog. + */ + function site_icon_url($size = 512, $url = '', $blog_id = 0) + { + } + /** + * Determines whether the site has a Site Icon. + * + * @since 4.3.0 + * + * @param int $blog_id Optional. ID of the blog in question. Default current blog. + * @return bool Whether the site has a site icon or not. + */ + function has_site_icon($blog_id = 0) + { + } + /** + * Determines whether the site has a custom logo. + * + * @since 4.5.0 + * + * @param int $blog_id Optional. ID of the blog in question. Default is the ID of the current blog. + * @return bool Whether the site has a custom logo or not. + */ + function has_custom_logo($blog_id = 0) + { + } + /** + * Returns a custom logo, linked to home unless the theme supports removing the link on the home page. + * + * @since 4.5.0 + * @since 5.5.0 Added option to remove the link on the home page with `unlink-homepage-logo` theme support + * for the `custom-logo` theme feature. + * @since 5.5.1 Disabled lazy-loading by default. + * + * @param int $blog_id Optional. ID of the blog in question. Default is the ID of the current blog. + * @return string Custom logo markup. + */ + function get_custom_logo($blog_id = 0) + { + } + /** + * Displays a custom logo, linked to home unless the theme supports removing the link on the home page. + * + * @since 4.5.0 + * + * @param int $blog_id Optional. ID of the blog in question. Default is the ID of the current blog. + */ + function the_custom_logo($blog_id = 0) + { + } + /** + * Returns document title for the current page. + * + * @since 4.4.0 + * + * @global int $page Page number of a single post. + * @global int $paged Page number of a list of posts. + * + * @return string Tag with the document title. + */ + function wp_get_document_title() + { + } + /** + * Displays title tag with content. + * + * @ignore + * @since 4.1.0 + * @since 4.4.0 Improved title output replaced `wp_title()`. + * @access private + */ + function _wp_render_title_tag() + { + } + /** + * Displays or retrieves page title for all areas of blog. + * + * By default, the page title will display the separator before the page title, + * so that the blog title will be before the page title. This is not good for + * title display, since the blog title shows up on most tabs and not what is + * important, which is the page that the user is looking at. + * + * There are also SEO benefits to having the blog title after or to the 'right' + * of the page title. However, it is mostly common sense to have the blog title + * to the right with most browsers supporting tabs. You can achieve this by + * using the seplocation parameter and setting the value to 'right'. This change + * was introduced around 2.5.0, in case backward compatibility of themes is + * important. + * + * @since 1.0.0 + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @param string $sep Optional. How to separate the various items within the page title. + * Default '»'. + * @param bool $display Optional. Whether to display or retrieve title. Default true. + * @param string $seplocation Optional. Location of the separator ('left' or 'right'). + * @return string|void String when `$display` is false, nothing otherwise. + */ + function wp_title($sep = '»', $display = \true, $seplocation = '') + { + } + /** + * Displays or retrieves page title for post. + * + * This is optimized for single.php template file for displaying the post title. + * + * It does not support placing the separator after the title, but by leaving the + * prefix parameter empty, you can set the title separator manually. The prefix + * does not automatically place a space between the prefix, so if there should + * be a space, the parameter value will need to have it at the end. + * + * @since 0.71 + * + * @param string $prefix Optional. What to display before the title. + * @param bool $display Optional. Whether to display or retrieve title. Default true. + * @return string|void Title when retrieving. + */ + function single_post_title($prefix = '', $display = \true) + { + } + /** + * Displays or retrieves title for a post type archive. + * + * This is optimized for archive.php and archive-{$post_type}.php template files + * for displaying the title of the post type. + * + * @since 3.1.0 + * + * @param string $prefix Optional. What to display before the title. + * @param bool $display Optional. Whether to display or retrieve title. Default true. + * @return string|void Title when retrieving, null when displaying or failure. + */ + function post_type_archive_title($prefix = '', $display = \true) + { + } + /** + * Displays or retrieves page title for category archive. + * + * Useful for category template files for displaying the category page title. + * The prefix does not automatically place a space between the prefix, so if + * there should be a space, the parameter value will need to have it at the end. + * + * @since 0.71 + * + * @param string $prefix Optional. What to display before the title. + * @param bool $display Optional. Whether to display or retrieve title. Default true. + * @return string|void Title when retrieving. + */ + function single_cat_title($prefix = '', $display = \true) + { + } + /** + * Displays or retrieves page title for tag post archive. + * + * Useful for tag template files for displaying the tag page title. The prefix + * does not automatically place a space between the prefix, so if there should + * be a space, the parameter value will need to have it at the end. + * + * @since 2.3.0 + * + * @param string $prefix Optional. What to display before the title. + * @param bool $display Optional. Whether to display or retrieve title. Default true. + * @return string|void Title when retrieving. + */ + function single_tag_title($prefix = '', $display = \true) + { + } + /** + * Displays or retrieves page title for taxonomy term archive. + * + * Useful for taxonomy term template files for displaying the taxonomy term page title. + * The prefix does not automatically place a space between the prefix, so if there should + * be a space, the parameter value will need to have it at the end. + * + * @since 3.1.0 + * + * @param string $prefix Optional. What to display before the title. + * @param bool $display Optional. Whether to display or retrieve title. Default true. + * @return string|void Title when retrieving. + */ + function single_term_title($prefix = '', $display = \true) + { + } + /** + * Displays or retrieves page title for post archive based on date. + * + * Useful for when the template only needs to display the month and year, + * if either are available. The prefix does not automatically place a space + * between the prefix, so if there should be a space, the parameter value + * will need to have it at the end. + * + * @since 0.71 + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @param string $prefix Optional. What to display before the title. + * @param bool $display Optional. Whether to display or retrieve title. Default true. + * @return string|false|void False if there's no valid title for the month. Title when retrieving. + */ + function single_month_title($prefix = '', $display = \true) + { + } + /** + * Displays the archive title based on the queried object. + * + * @since 4.1.0 + * + * @see get_the_archive_title() + * + * @param string $before Optional. Content to prepend to the title. Default empty. + * @param string $after Optional. Content to append to the title. Default empty. + */ + function the_archive_title($before = '', $after = '') + { + } + /** + * Retrieves the archive title based on the queried object. + * + * @since 4.1.0 + * @since 5.5.0 The title part is wrapped in a `<span>` element. + * + * @return string Archive title. + */ + function get_the_archive_title() + { + } + /** + * Displays category, tag, term, or author description. + * + * @since 4.1.0 + * + * @see get_the_archive_description() + * + * @param string $before Optional. Content to prepend to the description. Default empty. + * @param string $after Optional. Content to append to the description. Default empty. + */ + function the_archive_description($before = '', $after = '') + { + } + /** + * Retrieves the description for an author, post type, or term archive. + * + * @since 4.1.0 + * @since 4.7.0 Added support for author archives. + * @since 4.9.0 Added support for post type archives. + * + * @see term_description() + * + * @return string Archive description. + */ + function get_the_archive_description() + { + } + /** + * Retrieves the description for a post type archive. + * + * @since 4.9.0 + * + * @return string The post type description. + */ + function get_the_post_type_description() + { + } + /** + * Retrieves archive link content based on predefined or custom code. + * + * The format can be one of four styles. The 'link' for head element, 'option' + * for use in the select element, 'html' for use in list (either ol or ul HTML + * elements). Custom content is also supported using the before and after + * parameters. + * + * The 'link' format uses the `<link>` HTML element with the **archives** + * relationship. The before and after parameters are not used. The text + * parameter is used to describe the link. + * + * The 'option' format uses the option HTML element for use in select element. + * The value is the url parameter and the before and after parameters are used + * between the text description. + * + * The 'html' format, which is the default, uses the li HTML element for use in + * the list HTML elements. The before parameter is before the link and the after + * parameter is after the closing link. + * + * The custom format uses the before parameter before the link ('a' HTML + * element) and the after parameter after the closing link tag. If the above + * three values for the format are not used, then custom format is assumed. + * + * @since 1.0.0 + * @since 5.2.0 Added the `$selected` parameter. + * + * @param string $url URL to archive. + * @param string $text Archive text description. + * @param string $format Optional. Can be 'link', 'option', 'html', or custom. Default 'html'. + * @param string $before Optional. Content to prepend to the description. Default empty. + * @param string $after Optional. Content to append to the description. Default empty. + * @param bool $selected Optional. Set to true if the current page is the selected archive page. + * @return string HTML link content for archive. + */ + function get_archives_link($url, $text, $format = 'html', $before = '', $after = '', $selected = \false) + { + } + /** + * Displays archive links based on type and format. + * + * @since 1.2.0 + * @since 4.4.0 The `$post_type` argument was added. + * @since 5.2.0 The `$year`, `$monthnum`, `$day`, and `$w` arguments were added. + * + * @see get_archives_link() + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @param string|array $args { + * Default archive links arguments. Optional. + * + * @type string $type Type of archive to retrieve. Accepts 'daily', 'weekly', 'monthly', + * 'yearly', 'postbypost', or 'alpha'. Both 'postbypost' and 'alpha' + * display the same archive link list as well as post titles instead + * of displaying dates. The difference between the two is that 'alpha' + * will order by post title and 'postbypost' will order by post date. + * Default 'monthly'. + * @type string|int $limit Number of links to limit the query to. Default empty (no limit). + * @type string $format Format each link should take using the $before and $after args. + * Accepts 'link' (`<link>` tag), 'option' (`<option>` tag), 'html' + * (`<li>` tag), or a custom format, which generates a link anchor + * with $before preceding and $after succeeding. Default 'html'. + * @type string $before Markup to prepend to the beginning of each link. Default empty. + * @type string $after Markup to append to the end of each link. Default empty. + * @type bool $show_post_count Whether to display the post count alongside the link. Default false. + * @type bool|int $echo Whether to echo or return the links list. Default 1|true to echo. + * @type string $order Whether to use ascending or descending order. Accepts 'ASC', or 'DESC'. + * Default 'DESC'. + * @type string $post_type Post type. Default 'post'. + * @type string $year Year. Default current year. + * @type string $monthnum Month number. Default current month number. + * @type string $day Day. Default current day. + * @type string $w Week. Default current week. + * } + * @return void|string Void if 'echo' argument is true, archive links if 'echo' is false. + * @phpstan-param array{ + * type?: string, + * limit?: string|int, + * format?: string, + * before?: string, + * after?: string, + * show_post_count?: bool, + * echo?: bool|int, + * order?: string, + * post_type?: string, + * year?: string, + * monthnum?: string, + * day?: string, + * w?: string, + * } $args + */ + function wp_get_archives($args = '') + { + } + /** + * Gets number of days since the start of the week. + * + * @since 1.5.0 + * + * @param int $num Number of day. + * @return float Days since the start of the week. + */ + function calendar_week_mod($num) + { + } + /** + * Displays calendar with days that have posts as links. + * + * The calendar is cached, which will be retrieved, if it exists. If there are + * no posts for the month, then it will not be displayed. + * + * @since 1.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global int $m + * @global int $monthnum + * @global int $year + * @global WP_Locale $wp_locale WordPress date and time locale object. + * @global array $posts + * + * @param bool $initial Optional. Whether to use initial calendar names. Default true. + * @param bool $echo Optional. Whether to display the calendar output. Default true. + * @return void|string Void if `$echo` argument is true, calendar HTML if `$echo` is false. + */ + function get_calendar($initial = \true, $echo = \true) + { + } + /** + * Purges the cached results of get_calendar. + * + * @see get_calendar() + * @since 2.1.0 + */ + function delete_get_calendar_cache() + { + } + /** + * Displays all of the allowed tags in HTML format with attributes. + * + * This is useful for displaying in the comment area, which elements and + * attributes are supported. As well as any plugins which want to display it. + * + * @since 1.0.1 + * @since 4.4.0 No longer used in core. + * + * @global array $allowedtags + * + * @return string HTML allowed tags entity encoded. + */ + function allowed_tags() + { + } + /***** Date/Time tags */ + /** + * Outputs the date in iso8601 format for xml files. + * + * @since 1.0.0 + */ + function the_date_xml() + { + } + /** + * Displays or retrieves the date the current post was written (once per date) + * + * Will only output the date if the current post's date is different from the + * previous one output. + * + * i.e. Only one date listing will show per day worth of posts shown in the loop, even if the + * function is called several times for each post. + * + * HTML output can be filtered with 'the_date'. + * Date string output can be filtered with 'get_the_date'. + * + * @since 0.71 + * + * @global string $currentday The day of the current post in the loop. + * @global string $previousday The day of the previous post in the loop. + * + * @param string $format Optional. PHP date format. Defaults to the 'date_format' option. + * @param string $before Optional. Output before the date. Default empty. + * @param string $after Optional. Output after the date. Default empty. + * @param bool $echo Optional. Whether to echo the date or return it. Default true. + * @return string|void String if retrieving. + */ + function the_date($format = '', $before = '', $after = '', $echo = \true) + { + } + /** + * Retrieves the date on which the post was written. + * + * Unlike the_date() this function will always return the date. + * Modify output with the {@see 'get_the_date'} filter. + * + * @since 3.0.0 + * + * @param string $format Optional. PHP date format. Defaults to the 'date_format' option. + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default current post. + * @return string|int|false Date the current post was written. False on failure. + */ + function get_the_date($format = '', $post = \null) + { + } + /** + * Displays the date on which the post was last modified. + * + * @since 2.1.0 + * + * @param string $format Optional. PHP date format. Defaults to the 'date_format' option. + * @param string $before Optional. Output before the date. Default empty. + * @param string $after Optional. Output after the date. Default empty. + * @param bool $echo Optional. Whether to echo the date or return it. Default true. + * @return string|void String if retrieving. + */ + function the_modified_date($format = '', $before = '', $after = '', $echo = \true) + { + } + /** + * Retrieves the date on which the post was last modified. + * + * @since 2.1.0 + * @since 4.6.0 Added the `$post` parameter. + * + * @param string $format Optional. PHP date format. Defaults to the 'date_format' option. + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default current post. + * @return string|int|false Date the current post was modified. False on failure. + */ + function get_the_modified_date($format = '', $post = \null) + { + } + /** + * Displays the time at which the post was written. + * + * @since 0.71 + * + * @param string $format Optional. Format to use for retrieving the time the post + * was written. Accepts 'G', 'U', or PHP date format. + * Defaults to the 'time_format' option. + */ + function the_time($format = '') + { + } + /** + * Retrieves the time at which the post was written. + * + * @since 1.5.0 + * + * @param string $format Optional. Format to use for retrieving the time the post + * was written. Accepts 'G', 'U', or PHP date format. + * Defaults to the 'time_format' option. + * @param int|WP_Post $post Post ID or post object. Default is global `$post` object. + * @return string|int|false Formatted date string or Unix timestamp if `$format` is 'U' or 'G'. + * False on failure. + */ + function get_the_time($format = '', $post = \null) + { + } + /** + * Retrieves the time at which the post was written. + * + * @since 2.0.0 + * + * @param string $format Optional. Format to use for retrieving the time the post + * was written. Accepts 'G', 'U', or PHP date format. Default 'U'. + * @param bool $gmt Optional. Whether to retrieve the GMT time. Default false. + * @param int|WP_Post $post Post ID or post object. Default is global `$post` object. + * @param bool $translate Whether to translate the time string. Default false. + * @return string|int|false Formatted date string or Unix timestamp if `$format` is 'U' or 'G'. + * False on failure. + */ + function get_post_time($format = 'U', $gmt = \false, $post = \null, $translate = \false) + { + } + /** + * Retrieves post published or modified time as a `DateTimeImmutable` object instance. + * + * The object will be set to the timezone from WordPress settings. + * + * For legacy reasons, this function allows to choose to instantiate from local or UTC time in database. + * Normally this should make no difference to the result. However, the values might get out of sync in database, + * typically because of timezone setting changes. The parameter ensures the ability to reproduce backwards + * compatible behaviors in such cases. + * + * @since 5.3.0 + * + * @param int|WP_Post $post Optional. Post ID or post object. Default is global `$post` object. + * @param string $field Optional. Published or modified time to use from database. Accepts 'date' or 'modified'. + * Default 'date'. + * @param string $source Optional. Local or UTC time to use from database. Accepts 'local' or 'gmt'. + * Default 'local'. + * @return DateTimeImmutable|false Time object on success, false on failure. + */ + function get_post_datetime($post = \null, $field = 'date', $source = 'local') + { + } + /** + * Retrieves post published or modified time as a Unix timestamp. + * + * Note that this function returns a true Unix timestamp, not summed with timezone offset + * like older WP functions. + * + * @since 5.3.0 + * + * @param int|WP_Post $post Optional. Post ID or post object. Default is global `$post` object. + * @param string $field Optional. Published or modified time to use from database. Accepts 'date' or 'modified'. + * Default 'date'. + * @return int|false Unix timestamp on success, false on failure. + */ + function get_post_timestamp($post = \null, $field = 'date') + { + } + /** + * Displays the time at which the post was last modified. + * + * @since 2.0.0 + * + * @param string $format Optional. Format to use for retrieving the time the post + * was modified. Accepts 'G', 'U', or PHP date format. + * Defaults to the 'time_format' option. + */ + function the_modified_time($format = '') + { + } + /** + * Retrieves the time at which the post was last modified. + * + * @since 2.0.0 + * @since 4.6.0 Added the `$post` parameter. + * + * @param string $format Optional. Format to use for retrieving the time the post + * was modified. Accepts 'G', 'U', or PHP date format. + * Defaults to the 'time_format' option. + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default current post. + * @return string|int|false Formatted date string or Unix timestamp. False on failure. + */ + function get_the_modified_time($format = '', $post = \null) + { + } + /** + * Retrieves the time at which the post was last modified. + * + * @since 2.0.0 + * + * @param string $format Optional. Format to use for retrieving the time the post + * was modified. Accepts 'G', 'U', or PHP date format. Default 'U'. + * @param bool $gmt Optional. Whether to retrieve the GMT time. Default false. + * @param int|WP_Post $post Post ID or post object. Default is global `$post` object. + * @param bool $translate Whether to translate the time string. Default false. + * @return string|int|false Formatted date string or Unix timestamp if `$format` is 'U' or 'G'. + * False on failure. + */ + function get_post_modified_time($format = 'U', $gmt = \false, $post = \null, $translate = \false) + { + } + /** + * Displays the weekday on which the post was written. + * + * @since 0.71 + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + */ + function the_weekday() + { + } + /** + * Displays the weekday on which the post was written. + * + * Will only output the weekday if the current post's weekday is different from + * the previous one output. + * + * @since 0.71 + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * @global string $currentday The day of the current post in the loop. + * @global string $previousweekday The day of the previous post in the loop. + * + * @param string $before Optional. Output before the date. Default empty. + * @param string $after Optional. Output after the date. Default empty. + */ + function the_weekday_date($before = '', $after = '') + { + } + /** + * Fires the wp_head action. + * + * See {@see 'wp_head'}. + * + * @since 1.2.0 + */ + function wp_head() + { + } + /** + * Fires the wp_footer action. + * + * See {@see 'wp_footer'}. + * + * @since 1.5.1 + */ + function wp_footer() + { + } + /** + * Fires the wp_body_open action. + * + * See {@see 'wp_body_open'}. + * + * @since 5.2.0 + */ + function wp_body_open() + { + } + /** + * Displays the links to the general feeds. + * + * @since 2.8.0 + * + * @param array $args Optional arguments. + */ + function feed_links($args = array()) + { + } + /** + * Displays the links to the extra feeds such as category feeds. + * + * @since 2.8.0 + * + * @param array $args Optional arguments. + */ + function feed_links_extra($args = array()) + { + } + /** + * Displays the link to the Really Simple Discovery service endpoint. + * + * @link http://archipelago.phrasewise.com/rsd + * @since 2.0.0 + */ + function rsd_link() + { + } + /** + * Displays the link to the Windows Live Writer manifest file. + * + * @link https://msdn.microsoft.com/en-us/library/bb463265.aspx + * @since 2.3.1 + */ + function wlwmanifest_link() + { + } + /** + * Displays a referrer `strict-origin-when-cross-origin` meta tag. + * + * Outputs a referrer `strict-origin-when-cross-origin` meta tag that tells the browser not to send + * the full URL as a referrer to other sites when cross-origin assets are loaded. + * + * Typical usage is as a {@see 'wp_head'} callback: + * + * add_action( 'wp_head', 'wp_strict_cross_origin_referrer' ); + * + * @since 5.7.0 + */ + function wp_strict_cross_origin_referrer() + { + } + /** + * Displays site icon meta tags. + * + * @since 4.3.0 + * + * @link https://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#rel-icon HTML5 specification link icon. + */ + function wp_site_icon() + { + } + /** + * Prints resource hints to browsers for pre-fetching, pre-rendering + * and pre-connecting to web sites. + * + * Gives hints to browsers to prefetch specific pages or render them + * in the background, to perform DNS lookups or to begin the connection + * handshake (DNS, TCP, TLS) in the background. + * + * These performance improving indicators work by using `<link rel"…">`. + * + * @since 4.6.0 + */ + function wp_resource_hints() + { + } + /** + * Prints resource preloads directives to browsers. + * + * Gives directive to browsers to preload specific resources that website will + * need very soon, this ensures that they are available earlier and are less + * likely to block the page's render. Preload directives should not be used for + * non-render-blocking elements, as then they would compete with the + * render-blocking ones, slowing down the render. + * + * These performance improving indicators work by using `<link rel="preload">`. + * + * @link https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload + * @link https://web.dev/preload-responsive-images/ + * + * @since 6.1.0 + */ + function wp_preload_resources() + { + } + /** + * Retrieves a list of unique hosts of all enqueued scripts and styles. + * + * @since 4.6.0 + * + * @return string[] A list of unique hosts of enqueued scripts and styles. + */ + function wp_dependencies_unique_hosts() + { + } + /** + * Determines whether the user can access the visual editor. + * + * Checks if the user can access the visual editor and that it's supported by the user's browser. + * + * @since 2.0.0 + * + * @global bool $wp_rich_edit Whether the user can access the visual editor. + * @global bool $is_gecko Whether the browser is Gecko-based. + * @global bool $is_opera Whether the browser is Opera. + * @global bool $is_safari Whether the browser is Safari. + * @global bool $is_chrome Whether the browser is Chrome. + * @global bool $is_IE Whether the browser is Internet Explorer. + * @global bool $is_edge Whether the browser is Microsoft Edge. + * + * @return bool True if the user can access the visual editor, false otherwise. + */ + function user_can_richedit() + { + } + /** + * Finds out which editor should be displayed by default. + * + * Works out which of the two editors to display as the current editor for a + * user. The 'html' setting is for the "Text" editor tab. + * + * @since 2.5.0 + * + * @return string Either 'tinymce', or 'html', or 'test' + */ + function wp_default_editor() + { + } + /** + * Renders an editor. + * + * Using this function is the proper way to output all needed components for both TinyMCE and Quicktags. + * _WP_Editors should not be used directly. See https://core.trac.wordpress.org/ticket/17144. + * + * NOTE: Once initialized the TinyMCE editor cannot be safely moved in the DOM. For that reason + * running wp_editor() inside of a meta box is not a good idea unless only Quicktags is used. + * On the post edit screen several actions can be used to include additional editors + * containing TinyMCE: 'edit_page_form', 'edit_form_advanced' and 'dbx_post_sidebar'. + * See https://core.trac.wordpress.org/ticket/19173 for more information. + * + * @see _WP_Editors::editor() + * @see _WP_Editors::parse_settings() + * @since 3.3.0 + * + * @param string $content Initial content for the editor. + * @param string $editor_id HTML ID attribute value for the textarea and TinyMCE. + * Should not contain square brackets. + * @param array $settings See _WP_Editors::parse_settings() for description. + * @phpstan-param array{ + * wpautop?: bool, + * media_buttons?: bool, + * default_editor?: string, + * drag_drop_upload?: bool, + * textarea_name?: string, + * textarea_rows?: int, + * tabindex?: string|int, + * tabfocus_elements?: string, + * editor_css?: string, + * editor_class?: string, + * teeny?: bool, + * dfw?: bool, + * tinymce?: bool|array, + * quicktags?: bool|array, + * } $settings See _WP_Editors::parse_settings() + */ + function wp_editor($content, $editor_id, $settings = array()) + { + } + /** + * Outputs the editor scripts, stylesheets, and default settings. + * + * The editor can be initialized when needed after page load. + * See wp.editor.initialize() in wp-admin/js/editor.js for initialization options. + * + * @uses _WP_Editors + * @since 4.8.0 + */ + function wp_enqueue_editor() + { + } + /** + * Enqueues assets needed by the code editor for the given settings. + * + * @since 4.9.0 + * + * @see wp_enqueue_editor() + * @see wp_get_code_editor_settings(); + * @see _WP_Editors::parse_settings() + * + * @param array $args { + * Args. + * + * @type string $type The MIME type of the file to be edited. + * @type string $file Filename to be edited. Extension is used to sniff the type. Can be supplied as alternative to `$type` param. + * @type WP_Theme $theme Theme being edited when on the theme file editor. + * @type string $plugin Plugin being edited when on the plugin file editor. + * @type array $codemirror Additional CodeMirror setting overrides. + * @type array $csslint CSSLint rule overrides. + * @type array $jshint JSHint rule overrides. + * @type array $htmlhint HTMLHint rule overrides. + * } + * @return array|false Settings for the enqueued code editor, or false if the editor was not enqueued. + * @phpstan-param array{ + * type?: string, + * file?: string, + * theme?: WP_Theme, + * plugin?: string, + * codemirror?: array, + * csslint?: array, + * jshint?: array, + * htmlhint?: array, + * } $args + */ + function wp_enqueue_code_editor($args) + { + } + /** + * Generates and returns code editor settings. + * + * @since 5.0.0 + * + * @see wp_enqueue_code_editor() + * + * @param array $args { + * Args. + * + * @type string $type The MIME type of the file to be edited. + * @type string $file Filename to be edited. Extension is used to sniff the type. Can be supplied as alternative to `$type` param. + * @type WP_Theme $theme Theme being edited when on the theme file editor. + * @type string $plugin Plugin being edited when on the plugin file editor. + * @type array $codemirror Additional CodeMirror setting overrides. + * @type array $csslint CSSLint rule overrides. + * @type array $jshint JSHint rule overrides. + * @type array $htmlhint HTMLHint rule overrides. + * } + * @return array|false Settings for the code editor. + * @phpstan-param array{ + * type?: string, + * file?: string, + * theme?: WP_Theme, + * plugin?: string, + * codemirror?: array, + * csslint?: array, + * jshint?: array, + * htmlhint?: array, + * } $args + */ + function wp_get_code_editor_settings($args) + { + } + /** + * Retrieves the contents of the search WordPress query variable. + * + * The search query string is passed through esc_attr() to ensure that it is safe + * for placing in an HTML attribute. + * + * @since 2.3.0 + * + * @param bool $escaped Whether the result is escaped. Default true. + * Only use when you are later escaping it. Do not use unescaped. + * @return string + */ + function get_search_query($escaped = \true) + { + } + /** + * Displays the contents of the search query variable. + * + * The search query string is passed through esc_attr() to ensure that it is safe + * for placing in an HTML attribute. + * + * @since 2.1.0 + */ + function the_search_query() + { + } + /** + * Gets the language attributes for the 'html' tag. + * + * Builds up a set of HTML attributes containing the text direction and language + * information for the page. + * + * @since 4.3.0 + * + * @param string $doctype Optional. The type of HTML document. Accepts 'xhtml' or 'html'. Default 'html'. + * @return string A space-separated list of language attributes. + */ + function get_language_attributes($doctype = 'html') + { + } + /** + * Displays the language attributes for the 'html' tag. + * + * Builds up a set of HTML attributes containing the text direction and language + * information for the page. + * + * @since 2.1.0 + * @since 4.3.0 Converted into a wrapper for get_language_attributes(). + * + * @param string $doctype Optional. The type of HTML document. Accepts 'xhtml' or 'html'. Default 'html'. + */ + function language_attributes($doctype = 'html') + { + } + /** + * Retrieves paginated links for archive post pages. + * + * Technically, the function can be used to create paginated link list for any + * area. The 'base' argument is used to reference the url, which will be used to + * create the paginated links. The 'format' argument is then used for replacing + * the page number. It is however, most likely and by default, to be used on the + * archive post pages. + * + * The 'type' argument controls format of the returned value. The default is + * 'plain', which is just a string with the links separated by a newline + * character. The other possible values are either 'array' or 'list'. The + * 'array' value will return an array of the paginated link list to offer full + * control of display. The 'list' value will place all of the paginated links in + * an unordered HTML list. + * + * The 'total' argument is the total amount of pages and is an integer. The + * 'current' argument is the current page number and is also an integer. + * + * An example of the 'base' argument is "http://example.com/all_posts.php%_%" + * and the '%_%' is required. The '%_%' will be replaced by the contents of in + * the 'format' argument. An example for the 'format' argument is "?page=%#%" + * and the '%#%' is also required. The '%#%' will be replaced with the page + * number. + * + * You can include the previous and next links in the list by setting the + * 'prev_next' argument to true, which it is by default. You can set the + * previous text, by using the 'prev_text' argument. You can set the next text + * by setting the 'next_text' argument. + * + * If the 'show_all' argument is set to true, then it will show all of the pages + * instead of a short list of the pages near the current page. By default, the + * 'show_all' is set to false and controlled by the 'end_size' and 'mid_size' + * arguments. The 'end_size' argument is how many numbers on either the start + * and the end list edges, by default is 1. The 'mid_size' argument is how many + * numbers to either side of current page, but not including current page. + * + * It is possible to add query vars to the link by using the 'add_args' argument + * and see add_query_arg() for more information. + * + * The 'before_page_number' and 'after_page_number' arguments allow users to + * augment the links themselves. Typically this might be to add context to the + * numbered links so that screen reader users understand what the links are for. + * The text strings are added before and after the page number - within the + * anchor tag. + * + * @since 2.1.0 + * @since 4.9.0 Added the `aria_current` argument. + * + * @global WP_Query $wp_query WordPress Query object. + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string|array $args { + * Optional. Array or string of arguments for generating paginated links for archives. + * + * @type string $base Base of the paginated url. Default empty. + * @type string $format Format for the pagination structure. Default empty. + * @type int $total The total amount of pages. Default is the value WP_Query's + * `max_num_pages` or 1. + * @type int $current The current page number. Default is 'paged' query var or 1. + * @type string $aria_current The value for the aria-current attribute. Possible values are 'page', + * 'step', 'location', 'date', 'time', 'true', 'false'. Default is 'page'. + * @type bool $show_all Whether to show all pages. Default false. + * @type int $end_size How many numbers on either the start and the end list edges. + * Default 1. + * @type int $mid_size How many numbers to either side of the current pages. Default 2. + * @type bool $prev_next Whether to include the previous and next links in the list. Default true. + * @type string $prev_text The previous page text. Default '« Previous'. + * @type string $next_text The next page text. Default 'Next »'. + * @type string $type Controls format of the returned value. Possible values are 'plain', + * 'array' and 'list'. Default is 'plain'. + * @type array $add_args An array of query args to add. Default false. + * @type string $add_fragment A string to append to each link. Default empty. + * @type string $before_page_number A string to appear before the page number. Default empty. + * @type string $after_page_number A string to append after the page number. Default empty. + * } + * @return string|string[]|void String of page links or array of page links, depending on 'type' argument. + * Void if total number of pages is less than 2. + * @phpstan-param array{ + * base?: string, + * format?: string, + * total?: int, + * current?: int, + * aria_current?: string, + * show_all?: bool, + * end_size?: int, + * mid_size?: int, + * prev_next?: bool, + * prev_text?: string, + * next_text?: string, + * type?: string, + * add_args?: array, + * add_fragment?: string, + * before_page_number?: string, + * after_page_number?: string, + * } $args + */ + function paginate_links($args = '') + { + } + /** + * Registers an admin color scheme css file. + * + * Allows a plugin to register a new admin color scheme. For example: + * + * wp_admin_css_color( 'classic', __( 'Classic' ), admin_url( "css/colors-classic.css" ), array( + * '#07273E', '#14568A', '#D54E21', '#2683AE' + * ) ); + * + * @since 2.5.0 + * + * @global array $_wp_admin_css_colors + * + * @param string $key The unique key for this theme. + * @param string $name The name of the theme. + * @param string $url The URL of the CSS file containing the color scheme. + * @param array $colors Optional. An array of CSS color definition strings which are used + * to give the user a feel for the theme. + * @param array $icons { + * Optional. CSS color definitions used to color any SVG icons. + * + * @type string $base SVG icon base color. + * @type string $focus SVG icon color on focus. + * @type string $current SVG icon color of current admin menu link. + * } + * @phpstan-param array{ + * base?: string, + * focus?: string, + * current?: string, + * } $icons + */ + function wp_admin_css_color($key, $name, $url, $colors = array(), $icons = array()) + { + } + /** + * Registers the default admin color schemes. + * + * Registers the initial set of eight color schemes in the Profile section + * of the dashboard which allows for styling the admin menu and toolbar. + * + * @see wp_admin_css_color() + * + * @since 3.0.0 + */ + function register_admin_color_schemes() + { + } + /** + * Displays the URL of a WordPress admin CSS file. + * + * @see WP_Styles::_css_href() and its {@see 'style_loader_src'} filter. + * + * @since 2.3.0 + * + * @param string $file file relative to wp-admin/ without its ".css" extension. + * @return string + */ + function wp_admin_css_uri($file = 'wp-admin') + { + } + /** + * Enqueues or directly prints a stylesheet link to the specified CSS file. + * + * "Intelligently" decides to enqueue or to print the CSS file. If the + * {@see 'wp_print_styles'} action has *not* yet been called, the CSS file will be + * enqueued. If the {@see 'wp_print_styles'} action has been called, the CSS link will + * be printed. Printing may be forced by passing true as the $force_echo + * (second) parameter. + * + * For backward compatibility with WordPress 2.3 calling method: If the $file + * (first) parameter does not correspond to a registered CSS file, we assume + * $file is a file relative to wp-admin/ without its ".css" extension. A + * stylesheet link to that generated URL is printed. + * + * @since 2.3.0 + * + * @param string $file Optional. Style handle name or file name (without ".css" extension) relative + * to wp-admin/. Defaults to 'wp-admin'. + * @param bool $force_echo Optional. Force the stylesheet link to be printed rather than enqueued. + */ + function wp_admin_css($file = 'wp-admin', $force_echo = \false) + { + } + /** + * Enqueues the default ThickBox js and css. + * + * If any of the settings need to be changed, this can be done with another js + * file similar to media-upload.js. That file should + * require array('thickbox') to ensure it is loaded after. + * + * @since 2.5.0 + */ + function add_thickbox() + { + } + /** + * Displays the XHTML generator that is generated on the wp_head hook. + * + * See {@see 'wp_head'}. + * + * @since 2.5.0 + */ + function wp_generator() + { + } + /** + * Displays the generator XML or Comment for RSS, ATOM, etc. + * + * Returns the correct generator type for the requested output format. Allows + * for a plugin to filter generators overall the {@see 'the_generator'} filter. + * + * @since 2.5.0 + * + * @param string $type The type of generator to output - (html|xhtml|atom|rss2|rdf|comment|export). + */ + function the_generator($type) + { + } + /** + * Creates the generator XML or Comment for RSS, ATOM, etc. + * + * Returns the correct generator type for the requested output format. Allows + * for a plugin to filter generators on an individual basis using the + * {@see 'get_the_generator_$type'} filter. + * + * @since 2.5.0 + * + * @param string $type The type of generator to return - (html|xhtml|atom|rss2|rdf|comment|export). + * @return string|void The HTML content for the generator. + */ + function get_the_generator($type = '') + { + } + /** + * Outputs the HTML checked attribute. + * + * Compares the first two arguments and if identical marks as checked. + * + * @since 1.0.0 + * + * @param mixed $checked One of the values to compare. + * @param mixed $current Optional. The other value to compare if not just true. + * Default true. + * @param bool $echo Optional. Whether to echo or just return the string. + * Default true. + * @return string HTML attribute or empty string. + */ + function checked($checked, $current = \true, $echo = \true) + { + } + /** + * Outputs the HTML selected attribute. + * + * Compares the first two arguments and if identical marks as selected. + * + * @since 1.0.0 + * + * @param mixed $selected One of the values to compare. + * @param mixed $current Optional. The other value to compare if not just true. + * Default true. + * @param bool $echo Optional. Whether to echo or just return the string. + * Default true. + * @return string HTML attribute or empty string. + */ + function selected($selected, $current = \true, $echo = \true) + { + } + /** + * Outputs the HTML disabled attribute. + * + * Compares the first two arguments and if identical marks as disabled. + * + * @since 3.0.0 + * + * @param mixed $disabled One of the values to compare. + * @param mixed $current Optional. The other value to compare if not just true. + * Default true. + * @param bool $echo Optional. Whether to echo or just return the string. + * Default true. + * @return string HTML attribute or empty string. + */ + function disabled($disabled, $current = \true, $echo = \true) + { + } + /** + * Outputs the HTML readonly attribute. + * + * Compares the first two arguments and if identical marks as readonly. + * + * @since 5.9.0 + * + * @param mixed $readonly One of the values to compare. + * @param mixed $current Optional. The other value to compare if not just true. + * Default true. + * @param bool $echo Optional. Whether to echo or just return the string. + * Default true. + * @return string HTML attribute or empty string. + */ + function wp_readonly($readonly, $current = \true, $echo = \true) + { + } + /** + * Private helper function for checked, selected, disabled and readonly. + * + * Compares the first two arguments and if identical marks as `$type`. + * + * @since 2.8.0 + * @access private + * + * @param mixed $helper One of the values to compare. + * @param mixed $current The other value to compare if not just true. + * @param bool $echo Whether to echo or just return the string. + * @param string $type The type of checked|selected|disabled|readonly we are doing. + * @return string HTML attribute or empty string. + */ + function __checked_selected_helper($helper, $current, $echo, $type) + { + } + /** + * Assigns a visual indicator for required form fields. + * + * @since 6.1.0 + * + * @return string Indicator glyph wrapped in a `span` tag. + */ + function wp_required_field_indicator() + { + } + /** + * Creates a message to explain required form fields. + * + * @since 6.1.0 + * + * @return string Message text and glyph wrapped in a `span` tag. + */ + function wp_required_field_message() + { + } + /** + * Default settings for heartbeat. + * + * Outputs the nonce used in the heartbeat XHR. + * + * @since 3.6.0 + * + * @param array $settings + * @return array Heartbeat settings. + */ + function wp_heartbeat_settings($settings) + { + } + /** + * APIs to interact with global settings & styles. + * + * @package WordPress + */ + /** + * Gets the settings resulting of merging core, theme, and user data. + * + * @since 5.9.0 + * + * @param array $path Path to the specific setting to retrieve. Optional. + * If empty, will return all settings. + * @param array $context { + * Metadata to know where to retrieve the $path from. Optional. + * + * @type string $block_name Which block to retrieve the settings from. + * If empty, it'll return the settings for the global context. + * @type string $origin Which origin to take data from. + * Valid values are 'all' (core, theme, and user) or 'base' (core and theme). + * If empty or unknown, 'all' is used. + * } + * @return array The settings to retrieve. + * @phpstan-param array{ + * block_name?: string, + * origin?: string, + * } $context + */ + function wp_get_global_settings($path = array(), $context = array()) + { + } + /** + * Gets the styles resulting of merging core, theme, and user data. + * + * @since 5.9.0 + * + * @param array $path Path to the specific style to retrieve. Optional. + * If empty, will return all styles. + * @param array $context { + * Metadata to know where to retrieve the $path from. Optional. + * + * @type string $block_name Which block to retrieve the styles from. + * If empty, it'll return the styles for the global context. + * @type string $origin Which origin to take data from. + * Valid values are 'all' (core, theme, and user) or 'base' (core and theme). + * If empty or unknown, 'all' is used. + * } + * @return array The styles to retrieve. + * @phpstan-param array{ + * block_name?: string, + * origin?: string, + * } $context + */ + function wp_get_global_styles($path = array(), $context = array()) + { + } + /** + * Returns the stylesheet resulting of merging core, theme, and user data. + * + * @since 5.9.0 + * + * @param array $types Types of styles to load. Optional. + * It accepts 'variables', 'styles', 'presets' as values. + * If empty, it'll load all for themes with theme.json support + * and only [ 'variables', 'presets' ] for themes without theme.json support. + * @return string Stylesheet. + */ + function wp_get_global_stylesheet($types = array()) + { + } + /** + * Returns a string containing the SVGs to be referenced as filters (duotone). + * + * @since 5.9.1 + * + * @return string + */ + function wp_get_global_styles_svg_filters() + { + } + /** + * Adds global style rules to the inline style for each block. + * + * @since 6.1.0 + */ + function wp_add_global_styles_for_blocks() + { + } + /** + * Core HTTP Request API + * + * Standardizes the HTTP requests for WordPress. Handles cookies, gzip encoding and decoding, chunk + * decoding, if HTTP 1.1 and various other difficult HTTP protocol implementations. + * + * @package WordPress + * @subpackage HTTP + */ + /** + * Returns the initialized WP_Http Object + * + * @since 2.7.0 + * @access private + * + * @return WP_Http HTTP Transport object. + */ + function _wp_http_get_object() + { + } + /** + * Retrieve the raw response from a safe HTTP request. + * + * This function is ideal when the HTTP request is being made to an arbitrary + * URL. The URL is validated to avoid redirection and request forgery attacks. + * + * @since 3.6.0 + * + * @see wp_remote_request() For more information on the response array format. + * @see WP_Http::request() For default arguments information. + * + * @param string $url URL to retrieve. + * @param array $args Optional. Request arguments. Default empty array. + * @return array|WP_Error The response or WP_Error on failure. + * @phpstan-return array{headers: \Requests_Utility_CaseInsensitiveDictionary, body: string, response: array{code: int,message: string}, cookies: array<int, \WP_HTTP_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error + */ + function wp_safe_remote_request($url, $args = array()) + { + } + /** + * Retrieve the raw response from a safe HTTP request using the GET method. + * + * This function is ideal when the HTTP request is being made to an arbitrary + * URL. The URL is validated to avoid redirection and request forgery attacks. + * + * @since 3.6.0 + * + * @see wp_remote_request() For more information on the response array format. + * @see WP_Http::request() For default arguments information. + * + * @param string $url URL to retrieve. + * @param array $args Optional. Request arguments. Default empty array. + * @return array|WP_Error The response or WP_Error on failure. + * @phpstan-return array{headers: \Requests_Utility_CaseInsensitiveDictionary, body: string, response: array{code: int,message: string}, cookies: array<int, \WP_HTTP_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error + */ + function wp_safe_remote_get($url, $args = array()) + { + } + /** + * Retrieve the raw response from a safe HTTP request using the POST method. + * + * This function is ideal when the HTTP request is being made to an arbitrary + * URL. The URL is validated to avoid redirection and request forgery attacks. + * + * @since 3.6.0 + * + * @see wp_remote_request() For more information on the response array format. + * @see WP_Http::request() For default arguments information. + * + * @param string $url URL to retrieve. + * @param array $args Optional. Request arguments. Default empty array. + * @return array|WP_Error The response or WP_Error on failure. + * @phpstan-return array{headers: \Requests_Utility_CaseInsensitiveDictionary, body: string, response: array{code: int,message: string}, cookies: array<int, \WP_HTTP_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error + */ + function wp_safe_remote_post($url, $args = array()) + { + } + /** + * Retrieve the raw response from a safe HTTP request using the HEAD method. + * + * This function is ideal when the HTTP request is being made to an arbitrary + * URL. The URL is validated to avoid redirection and request forgery attacks. + * + * @since 3.6.0 + * + * @see wp_remote_request() For more information on the response array format. + * @see WP_Http::request() For default arguments information. + * + * @param string $url URL to retrieve. + * @param array $args Optional. Request arguments. Default empty array. + * @return array|WP_Error The response or WP_Error on failure. + * @phpstan-return array{headers: \Requests_Utility_CaseInsensitiveDictionary, body: string, response: array{code: int,message: string}, cookies: array<int, \WP_HTTP_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error + */ + function wp_safe_remote_head($url, $args = array()) + { + } + /** + * Performs an HTTP request and returns its response. + * + * There are other API functions available which abstract away the HTTP method: + * + * - Default 'GET' for wp_remote_get() + * - Default 'POST' for wp_remote_post() + * - Default 'HEAD' for wp_remote_head() + * + * @since 2.7.0 + * + * @see WP_Http::request() For information on default arguments. + * + * @param string $url URL to retrieve. + * @param array $args Optional. Request arguments. Default empty array. + * @return array|WP_Error { + * The response array or a WP_Error on failure. + * + * @type string[] $headers Array of response headers keyed by their name. + * @type string $body Response body. + * @type array $response { + * Data about the HTTP response. + * + * @type int|false $code HTTP response code. + * @type string|false $message HTTP response message. + * } + * @type WP_HTTP_Cookie[] $cookies Array of response cookies. + * @type WP_HTTP_Requests_Response|null $http_response Raw HTTP response object. + * } + * @phpstan-return \WP_Error|array{ + * headers: string[], + * body: string, + * response: array{ + * code: int|false, + * message: string|false, + * }, + * cookies: WP_HTTP_Cookie[], + * http_response: WP_HTTP_Requests_Response|null, + * } + * @phpstan-return array{headers: \Requests_Utility_CaseInsensitiveDictionary, body: string, response: array{code: int,message: string}, cookies: array<int, \WP_HTTP_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error + */ + function wp_remote_request($url, $args = array()) + { + } + /** + * Performs an HTTP request using the GET method and returns its response. + * + * @since 2.7.0 + * + * @see wp_remote_request() For more information on the response array format. + * @see WP_Http::request() For default arguments information. + * + * @param string $url URL to retrieve. + * @param array $args Optional. Request arguments. Default empty array. + * @return array|WP_Error The response or WP_Error on failure. + * @phpstan-return array{headers: \Requests_Utility_CaseInsensitiveDictionary, body: string, response: array{code: int,message: string}, cookies: array<int, \WP_HTTP_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error + */ + function wp_remote_get($url, $args = array()) + { + } + /** + * Performs an HTTP request using the POST method and returns its response. + * + * @since 2.7.0 + * + * @see wp_remote_request() For more information on the response array format. + * @see WP_Http::request() For default arguments information. + * + * @param string $url URL to retrieve. + * @param array $args Optional. Request arguments. Default empty array. + * @return array|WP_Error The response or WP_Error on failure. + * @phpstan-return array{headers: \Requests_Utility_CaseInsensitiveDictionary, body: string, response: array{code: int,message: string}, cookies: array<int, \WP_HTTP_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error + */ + function wp_remote_post($url, $args = array()) + { + } + /** + * Performs an HTTP request using the HEAD method and returns its response. + * + * @since 2.7.0 + * + * @see wp_remote_request() For more information on the response array format. + * @see WP_Http::request() For default arguments information. + * + * @param string $url URL to retrieve. + * @param array $args Optional. Request arguments. Default empty array. + * @return array|WP_Error The response or WP_Error on failure. + * @phpstan-return array{headers: \Requests_Utility_CaseInsensitiveDictionary, body: string, response: array{code: int,message: string}, cookies: array<int, \WP_HTTP_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error + */ + function wp_remote_head($url, $args = array()) + { + } + /** + * Retrieve only the headers from the raw response. + * + * @since 2.7.0 + * @since 4.6.0 Return value changed from an array to an Requests_Utility_CaseInsensitiveDictionary instance. + * + * @see \Requests_Utility_CaseInsensitiveDictionary + * + * @param array|WP_Error $response HTTP response. + * @return \Requests_Utility_CaseInsensitiveDictionary|array The headers of the response, or empty array + * if incorrect parameter given. + */ + function wp_remote_retrieve_headers($response) + { + } + /** + * Retrieve a single header by name from the raw response. + * + * @since 2.7.0 + * + * @param array|WP_Error $response HTTP response. + * @param string $header Header name to retrieve value from. + * @return array|string The header(s) value(s). Array if multiple headers with the same name are retrieved. + * Empty string if incorrect parameter given, or if the header doesn't exist. + */ + function wp_remote_retrieve_header($response, $header) + { + } + /** + * Retrieve only the response code from the raw response. + * + * Will return an empty string if incorrect parameter value is given. + * + * @since 2.7.0 + * + * @param array|WP_Error $response HTTP response. + * @return int|string The response code as an integer. Empty string if incorrect parameter given. + */ + function wp_remote_retrieve_response_code($response) + { + } + /** + * Retrieve only the response message from the raw response. + * + * Will return an empty string if incorrect parameter value is given. + * + * @since 2.7.0 + * + * @param array|WP_Error $response HTTP response. + * @return string The response message. Empty string if incorrect parameter given. + */ + function wp_remote_retrieve_response_message($response) + { + } + /** + * Retrieve only the body from the raw response. + * + * @since 2.7.0 + * + * @param array|WP_Error $response HTTP response. + * @return string The body of the response. Empty string if no body or incorrect parameter given. + */ + function wp_remote_retrieve_body($response) + { + } + /** + * Retrieve only the cookies from the raw response. + * + * @since 4.4.0 + * + * @param array|WP_Error $response HTTP response. + * @return WP_Http_Cookie[] An array of `WP_Http_Cookie` objects from the response. + * Empty array if there are none, or the response is a WP_Error. + */ + function wp_remote_retrieve_cookies($response) + { + } + /** + * Retrieve a single cookie by name from the raw response. + * + * @since 4.4.0 + * + * @param array|WP_Error $response HTTP response. + * @param string $name The name of the cookie to retrieve. + * @return WP_Http_Cookie|string The `WP_Http_Cookie` object, or empty string + * if the cookie is not present in the response. + */ + function wp_remote_retrieve_cookie($response, $name) + { + } + /** + * Retrieve a single cookie's value by name from the raw response. + * + * @since 4.4.0 + * + * @param array|WP_Error $response HTTP response. + * @param string $name The name of the cookie to retrieve. + * @return string The value of the cookie, or empty string + * if the cookie is not present in the response. + */ + function wp_remote_retrieve_cookie_value($response, $name) + { + } + /** + * Determines if there is an HTTP Transport that can process this request. + * + * @since 3.2.0 + * + * @param array $capabilities Array of capabilities to test or a wp_remote_request() $args array. + * @param string $url Optional. If given, will check if the URL requires SSL and adds + * that requirement to the capabilities array. + * + * @return bool + */ + function wp_http_supports($capabilities = array(), $url = \null) + { + } + /** + * Get the HTTP Origin of the current request. + * + * @since 3.4.0 + * + * @return string URL of the origin. Empty string if no origin. + */ + function get_http_origin() + { + } + /** + * Retrieve list of allowed HTTP origins. + * + * @since 3.4.0 + * + * @return string[] Array of origin URLs. + */ + function get_allowed_http_origins() + { + } + /** + * Determines if the HTTP origin is an authorized one. + * + * @since 3.4.0 + * + * @param string|null $origin Origin URL. If not provided, the value of get_http_origin() is used. + * @return string Origin URL if allowed, empty string if not. + */ + function is_allowed_http_origin($origin = \null) + { + } + /** + * Send Access-Control-Allow-Origin and related headers if the current request + * is from an allowed origin. + * + * If the request is an OPTIONS request, the script exits with either access + * control headers sent, or a 403 response if the origin is not allowed. For + * other request methods, you will receive a return value. + * + * @since 3.4.0 + * + * @return string|false Returns the origin URL if headers are sent. Returns false + * if headers are not sent. + */ + function send_origin_headers() + { + } + /** + * Validate a URL for safe use in the HTTP API. + * + * @since 3.5.2 + * + * @param string $url Request URL. + * @return string|false URL or false on failure. + */ + function wp_http_validate_url($url) + { + } + /** + * Mark allowed redirect hosts safe for HTTP requests as well. + * + * Attached to the {@see 'http_request_host_is_external'} filter. + * + * @since 3.6.0 + * + * @param bool $is_external + * @param string $host + * @return bool + */ + function allowed_http_request_hosts($is_external, $host) + { + } + /** + * Adds any domain in a multisite installation for safe HTTP requests to the + * allowed list. + * + * Attached to the {@see 'http_request_host_is_external'} filter. + * + * @since 3.6.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param bool $is_external + * @param string $host + * @return bool + */ + function ms_allowed_http_request_hosts($is_external, $host) + { + } + /** + * A wrapper for PHP's parse_url() function that handles consistency in the return values + * across PHP versions. + * + * PHP 5.4.7 expanded parse_url()'s ability to handle non-absolute URLs, including + * schemeless and relative URLs with "://" in the path. This function works around + * those limitations providing a standard output on PHP 5.2~5.4+. + * + * Secondly, across various PHP versions, schemeless URLs containing a ":" in the query + * are being handled inconsistently. This function works around those differences as well. + * + * @since 4.4.0 + * @since 4.7.0 The `$component` parameter was added for parity with PHP's `parse_url()`. + * + * @link https://www.php.net/manual/en/function.parse-url.php + * + * @param string $url The URL to parse. + * @param int $component The specific component to retrieve. Use one of the PHP + * predefined constants to specify which one. + * Defaults to -1 (= return all parts as an array). + * @return mixed False on parse failure; Array of URL components on success; + * When a specific component has been requested: null if the component + * doesn't exist in the given URL; a string or - in the case of + * PHP_URL_PORT - integer when it does. See parse_url()'s return values. + */ + function wp_parse_url($url, $component = -1) + { + } + /** + * Retrieve a specific component from a parsed URL array. + * + * @internal + * + * @since 4.7.0 + * @access private + * + * @link https://www.php.net/manual/en/function.parse-url.php + * + * @param array|false $url_parts The parsed URL. Can be false if the URL failed to parse. + * @param int $component The specific component to retrieve. Use one of the PHP + * predefined constants to specify which one. + * Defaults to -1 (= return all parts as an array). + * @return mixed False on parse failure; Array of URL components on success; + * When a specific component has been requested: null if the component + * doesn't exist in the given URL; a string or - in the case of + * PHP_URL_PORT - integer when it does. See parse_url()'s return values. + */ + function _get_component_from_parsed_url_array($url_parts, $component = -1) + { + } + /** + * Translate a PHP_URL_* constant to the named array keys PHP uses. + * + * @internal + * + * @since 4.7.0 + * @access private + * + * @link https://www.php.net/manual/en/url.constants.php + * + * @param int $constant PHP_URL_* constant. + * @return string|false The named key or false. + */ + function _wp_translate_php_url_constant_to_key($constant) + { + } + /** + * HTTPS detection functions. + * + * @package WordPress + * @since 5.7.0 + */ + /** + * Checks whether the website is using HTTPS. + * + * This is based on whether both the home and site URL are using HTTPS. + * + * @since 5.7.0 + * @see wp_is_home_url_using_https() + * @see wp_is_site_url_using_https() + * + * @return bool True if using HTTPS, false otherwise. + */ + function wp_is_using_https() + { + } + /** + * Checks whether the current site URL is using HTTPS. + * + * @since 5.7.0 + * @see home_url() + * + * @return bool True if using HTTPS, false otherwise. + */ + function wp_is_home_url_using_https() + { + } + /** + * Checks whether the current site's URL where WordPress is stored is using HTTPS. + * + * This checks the URL where WordPress application files (e.g. wp-blog-header.php or the wp-admin/ folder) + * are accessible. + * + * @since 5.7.0 + * @see site_url() + * + * @return bool True if using HTTPS, false otherwise. + */ + function wp_is_site_url_using_https() + { + } + /** + * Checks whether HTTPS is supported for the server and domain. + * + * @since 5.7.0 + * + * @return bool True if HTTPS is supported, false otherwise. + */ + function wp_is_https_supported() + { + } + /** + * Runs a remote HTTPS request to detect whether HTTPS supported, and stores potential errors. + * + * This internal function is called by a regular Cron hook to ensure HTTPS support is detected and maintained. + * + * @since 5.7.0 + * @access private + */ + function wp_update_https_detection_errors() + { + } + /** + * Schedules the Cron hook for detecting HTTPS support. + * + * @since 5.7.0 + * @access private + */ + function wp_schedule_https_detection() + { + } + /** + * Disables SSL verification if the 'cron_request' arguments include an HTTPS URL. + * + * This prevents an issue if HTTPS breaks, where there would be a failed attempt to verify HTTPS. + * + * @since 5.7.0 + * @access private + * + * @param array $request The cron request arguments. + * @return array The filtered cron request arguments. + */ + function wp_cron_conditionally_prevent_sslverify($request) + { + } + /** + * Checks whether a given HTML string is likely an output from this WordPress site. + * + * This function attempts to check for various common WordPress patterns whether they are included in the HTML string. + * Since any of these actions may be disabled through third-party code, this function may also return null to indicate + * that it was not possible to determine ownership. + * + * @since 5.7.0 + * @access private + * + * @param string $html Full HTML output string, e.g. from a HTTP response. + * @return bool|null True/false for whether HTML was generated by this site, null if unable to determine. + */ + function wp_is_local_html_output($html) + { + } + /** + * HTTPS migration functions. + * + * @package WordPress + * @since 5.7.0 + */ + /** + * Checks whether WordPress should replace old HTTP URLs to the site with their HTTPS counterpart. + * + * If a WordPress site had its URL changed from HTTP to HTTPS, by default this will return `true`, causing WordPress to + * add frontend filters to replace insecure site URLs that may be present in older database content. The + * {@see 'wp_should_replace_insecure_home_url'} filter can be used to modify that behavior. + * + * @since 5.7.0 + * + * @return bool True if insecure URLs should replaced, false otherwise. + */ + function wp_should_replace_insecure_home_url() + { + } + /** + * Replaces insecure HTTP URLs to the site in the given content, if configured to do so. + * + * This function replaces all occurrences of the HTTP version of the site's URL with its HTTPS counterpart, if + * determined via {@see wp_should_replace_insecure_home_url()}. + * + * @since 5.7.0 + * + * @param string $content Content to replace URLs in. + * @return string Filtered content. + */ + function wp_replace_insecure_home_url($content) + { + } + /** + * Update the 'home' and 'siteurl' option to use the HTTPS variant of their URL. + * + * If this update does not result in WordPress recognizing that the site is now using HTTPS (e.g. due to constants + * overriding the URLs used), the changes will be reverted. In such a case the function will return false. + * + * @since 5.7.0 + * + * @return bool True on success, false on failure. + */ + function wp_update_urls_to_https() + { + } + /** + * Updates the 'https_migration_required' option if needed when the given URL has been updated from HTTP to HTTPS. + * + * If this is a fresh site, a migration will not be required, so the option will be set as `false`. + * + * This is hooked into the {@see 'update_option_home'} action. + * + * @since 5.7.0 + * @access private + * + * @param mixed $old_url Previous value of the URL option. + * @param mixed $new_url New value of the URL option. + */ + function wp_update_https_migration_required($old_url, $new_url) + { + } + function get_file($path) + { + } + /** + * Filters text content and strips out disallowed HTML. + * + * This function makes sure that only the allowed HTML element names, attribute + * names, attribute values, and HTML entities will occur in the given text string. + * + * This function expects unslashed data. + * + * @see wp_kses_post() for specifically filtering post content and fields. + * @see wp_allowed_protocols() for the default allowed protocols in link URLs. + * + * @since 1.0.0 + * + * @param string $string Text content to filter. + * @param array[]|string $allowed_html An array of allowed HTML elements and attributes, + * or a context name such as 'post'. See wp_kses_allowed_html() + * for the list of accepted context names. + * @param string[] $allowed_protocols Optional. Array of allowed URL protocols. + * Defaults to the result of wp_allowed_protocols(). + * @return string Filtered content containing only the allowed HTML. + */ + function wp_kses($string, $allowed_html, $allowed_protocols = array()) + { + } + /** + * Filters one HTML attribute and ensures its value is allowed. + * + * This function can escape data in some situations where `wp_kses()` must strip the whole attribute. + * + * @since 4.2.3 + * + * @param string $string The 'whole' attribute, including name and value. + * @param string $element The HTML element name to which the attribute belongs. + * @return string Filtered attribute. + */ + function wp_kses_one_attr($string, $element) + { + } + /** + * Returns an array of allowed HTML tags and attributes for a given context. + * + * @since 3.5.0 + * @since 5.0.1 `form` removed as allowable HTML tag. + * + * @global array $allowedposttags + * @global array $allowedtags + * @global array $allowedentitynames + * + * @param string|array $context The context for which to retrieve tags. Allowed values are 'post', + * 'strip', 'data', 'entities', or the name of a field filter such as + * 'pre_user_description', or an array of allowed HTML elements and attributes. + * @return array Array of allowed HTML tags and their allowed attributes. + */ + function wp_kses_allowed_html($context = '') + { + } + /** + * You add any KSES hooks here. + * + * There is currently only one KSES WordPress hook, {@see 'pre_kses'}, and it is called here. + * All parameters are passed to the hooks and expected to receive a string. + * + * @since 1.0.0 + * + * @param string $string Content to filter through KSES. + * @param array[]|string $allowed_html An array of allowed HTML elements and attributes, + * or a context name such as 'post'. See wp_kses_allowed_html() + * for the list of accepted context names. + * @param string[] $allowed_protocols Array of allowed URL protocols. + * @return string Filtered content through {@see 'pre_kses'} hook. + */ + function wp_kses_hook($string, $allowed_html, $allowed_protocols) + { + } + /** + * Returns the version number of KSES. + * + * @since 1.0.0 + * + * @return string KSES version number. + */ + function wp_kses_version() + { + } + /** + * Searches for HTML tags, no matter how malformed. + * + * It also matches stray `>` characters. + * + * @since 1.0.0 + * + * @global array[]|string $pass_allowed_html An array of allowed HTML elements and attributes, + * or a context name such as 'post'. + * @global string[] $pass_allowed_protocols Array of allowed URL protocols. + * + * @param string $string Content to filter. + * @param array[]|string $allowed_html An array of allowed HTML elements and attributes, + * or a context name such as 'post'. See wp_kses_allowed_html() + * for the list of accepted context names. + * @param string[] $allowed_protocols Array of allowed URL protocols. + * @return string Content with fixed HTML tags + */ + function wp_kses_split($string, $allowed_html, $allowed_protocols) + { + } + /** + * Returns an array of HTML attribute names whose value contains a URL. + * + * This function returns a list of all HTML attributes that must contain + * a URL according to the HTML specification. + * + * This list includes URI attributes both allowed and disallowed by KSES. + * + * @link https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes + * + * @since 5.0.1 + * + * @return string[] HTML attribute names whose value contains a URL. + */ + function wp_kses_uri_attributes() + { + } + /** + * Callback for `wp_kses_split()`. + * + * @since 3.1.0 + * @access private + * @ignore + * + * @global array[]|string $pass_allowed_html An array of allowed HTML elements and attributes, + * or a context name such as 'post'. + * @global string[] $pass_allowed_protocols Array of allowed URL protocols. + * + * @param array $match preg_replace regexp matches + * @return string + */ + function _wp_kses_split_callback($match) + { + } + /** + * Callback for `wp_kses_split()` for fixing malformed HTML tags. + * + * This function does a lot of work. It rejects some very malformed things like + * `<:::>`. It returns an empty string, if the element isn't allowed (look ma, no + * `strip_tags()`!). Otherwise it splits the tag into an element and an attribute + * list. + * + * After the tag is split into an element and an attribute list, it is run + * through another filter which will remove illegal attributes and once that is + * completed, will be returned. + * + * @access private + * @ignore + * @since 1.0.0 + * + * @param string $string Content to filter. + * @param array[]|string $allowed_html An array of allowed HTML elements and attributes, + * or a context name such as 'post'. See wp_kses_allowed_html() + * for the list of accepted context names. + * @param string[] $allowed_protocols Array of allowed URL protocols. + * @return string Fixed HTML element + */ + function wp_kses_split2($string, $allowed_html, $allowed_protocols) + { + } + /** + * Removes all attributes, if none are allowed for this element. + * + * If some are allowed it calls `wp_kses_hair()` to split them further, and then + * it builds up new HTML code from the data that `wp_kses_hair()` returns. It also + * removes `<` and `>` characters, if there are any left. One more thing it does + * is to check if the tag has a closing XHTML slash, and if it does, it puts one + * in the returned code as well. + * + * An array of allowed values can be defined for attributes. If the attribute value + * doesn't fall into the list, the attribute will be removed from the tag. + * + * Attributes can be marked as required. If a required attribute is not present, + * KSES will remove all attributes from the tag. As KSES doesn't match opening and + * closing tags, it's not possible to safely remove the tag itself, the safest + * fallback is to strip all attributes from the tag, instead. + * + * @since 1.0.0 + * @since 5.9.0 Added support for an array of allowed values for attributes. + * Added support for required attributes. + * + * @param string $element HTML element/tag. + * @param string $attr HTML attributes from HTML element to closing HTML element tag. + * @param array[]|string $allowed_html An array of allowed HTML elements and attributes, + * or a context name such as 'post'. See wp_kses_allowed_html() + * for the list of accepted context names. + * @param string[] $allowed_protocols Array of allowed URL protocols. + * @return string Sanitized HTML element. + */ + function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) + { + } + /** + * Determines whether an attribute is allowed. + * + * @since 4.2.3 + * @since 5.0.0 Added support for `data-*` wildcard attributes. + * + * @param string $name The attribute name. Passed by reference. Returns empty string when not allowed. + * @param string $value The attribute value. Passed by reference. Returns a filtered value. + * @param string $whole The `name=value` input. Passed by reference. Returns filtered input. + * @param string $vless Whether the attribute is valueless. Use 'y' or 'n'. + * @param string $element The name of the element to which this attribute belongs. + * @param array $allowed_html The full list of allowed elements and attributes. + * @return bool Whether or not the attribute is allowed. + */ + function wp_kses_attr_check(&$name, &$value, &$whole, $vless, $element, $allowed_html) + { + } + /** + * Builds an attribute list from string containing attributes. + * + * This function does a lot of work. It parses an attribute list into an array + * with attribute data, and tries to do the right thing even if it gets weird + * input. It will add quotes around attribute values that don't have any quotes + * or apostrophes around them, to make it easier to produce HTML code that will + * conform to W3C's HTML specification. It will also remove bad URL protocols + * from attribute values. It also reduces duplicate attributes by using the + * attribute defined first (`foo='bar' foo='baz'` will result in `foo='bar'`). + * + * @since 1.0.0 + * + * @param string $attr Attribute list from HTML element to closing HTML element tag. + * @param string[] $allowed_protocols Array of allowed URL protocols. + * @return array[] Array of attribute information after parsing. + */ + function wp_kses_hair($attr, $allowed_protocols) + { + } + /** + * Finds all attributes of an HTML element. + * + * Does not modify input. May return "evil" output. + * + * Based on `wp_kses_split2()` and `wp_kses_attr()`. + * + * @since 4.2.3 + * + * @param string $element HTML element. + * @return array|false List of attributes found in the element. Returns false on failure. + */ + function wp_kses_attr_parse($element) + { + } + /** + * Builds an attribute list from string containing attributes. + * + * Does not modify input. May return "evil" output. + * In case of unexpected input, returns false instead of stripping things. + * + * Based on `wp_kses_hair()` but does not return a multi-dimensional array. + * + * @since 4.2.3 + * + * @param string $attr Attribute list from HTML element to closing HTML element tag. + * @return array|false List of attributes found in $attr. Returns false on failure. + */ + function wp_kses_hair_parse($attr) + { + } + /** + * Performs different checks for attribute values. + * + * The currently implemented checks are "maxlen", "minlen", "maxval", "minval", + * and "valueless". + * + * @since 1.0.0 + * + * @param string $value Attribute value. + * @param string $vless Whether the attribute is valueless. Use 'y' or 'n'. + * @param string $checkname What $checkvalue is checking for. + * @param mixed $checkvalue What constraint the value should pass. + * @return bool Whether check passes. + */ + function wp_kses_check_attr_val($value, $vless, $checkname, $checkvalue) + { + } + /** + * Sanitizes a string and removed disallowed URL protocols. + * + * This function removes all non-allowed protocols from the beginning of the + * string. It ignores whitespace and the case of the letters, and it does + * understand HTML entities. It does its work recursively, so it won't be + * fooled by a string like `javascript:javascript:alert(57)`. + * + * @since 1.0.0 + * + * @param string $string Content to filter bad protocols from. + * @param string[] $allowed_protocols Array of allowed URL protocols. + * @return string Filtered content. + */ + function wp_kses_bad_protocol($string, $allowed_protocols) + { + } + /** + * Removes any invalid control characters in a text string. + * + * Also removes any instance of the `\0` string. + * + * @since 1.0.0 + * + * @param string $string Content to filter null characters from. + * @param array $options Set 'slash_zero' => 'keep' when '\0' is allowed. Default is 'remove'. + * @return string Filtered content. + */ + function wp_kses_no_null($string, $options = \null) + { + } + /** + * Strips slashes from in front of quotes. + * + * This function changes the character sequence `\"` to just `"`. It leaves all other + * slashes alone. The quoting from `preg_replace(//e)` requires this. + * + * @since 1.0.0 + * + * @param string $string String to strip slashes from. + * @return string Fixed string with quoted slashes. + */ + function wp_kses_stripslashes($string) + { + } + /** + * Converts the keys of an array to lowercase. + * + * @since 1.0.0 + * + * @param array $inarray Unfiltered array. + * @return array Fixed array with all lowercase keys. + */ + function wp_kses_array_lc($inarray) + { + } + /** + * Handles parsing errors in `wp_kses_hair()`. + * + * The general plan is to remove everything to and including some whitespace, + * but it deals with quotes and apostrophes as well. + * + * @since 1.0.0 + * + * @param string $string + * @return string + */ + function wp_kses_html_error($string) + { + } + /** + * Sanitizes content from bad protocols and other characters. + * + * This function searches for URL protocols at the beginning of the string, while + * handling whitespace and HTML entities. + * + * @since 1.0.0 + * + * @param string $string Content to check for bad protocols. + * @param string[] $allowed_protocols Array of allowed URL protocols. + * @param int $count Depth of call recursion to this function. + * @return string Sanitized content. + */ + function wp_kses_bad_protocol_once($string, $allowed_protocols, $count = 1) + { + } + /** + * Callback for `wp_kses_bad_protocol_once()` regular expression. + * + * This function processes URL protocols, checks to see if they're in the + * list of allowed protocols or not, and returns different data depending + * on the answer. + * + * @access private + * @ignore + * @since 1.0.0 + * + * @param string $string URI scheme to check against the list of allowed protocols. + * @param string[] $allowed_protocols Array of allowed URL protocols. + * @return string Sanitized content. + */ + function wp_kses_bad_protocol_once2($string, $allowed_protocols) + { + } + /** + * Converts and fixes HTML entities. + * + * This function normalizes HTML entities. It will convert `AT&T` to the correct + * `AT&T`, `:` to `:`, `&#XYZZY;` to `&#XYZZY;` and so on. + * + * When `$context` is set to 'xml', HTML entities are converted to their code points. For + * example, `AT&T…&#XYZZY;` is converted to `AT&T…&#XYZZY;`. + * + * @since 1.0.0 + * @since 5.5.0 Added `$context` parameter. + * + * @param string $string Content to normalize entities. + * @param string $context Context for normalization. Can be either 'html' or 'xml'. + * Default 'html'. + * @return string Content with normalized entities. + */ + function wp_kses_normalize_entities($string, $context = 'html') + { + } + /** + * Callback for `wp_kses_normalize_entities()` regular expression. + * + * This function only accepts valid named entity references, which are finite, + * case-sensitive, and highly scrutinized by HTML and XML validators. + * + * @since 3.0.0 + * + * @global array $allowedentitynames + * + * @param array $matches preg_replace_callback() matches array. + * @return string Correctly encoded entity. + */ + function wp_kses_named_entities($matches) + { + } + /** + * Callback for `wp_kses_normalize_entities()` regular expression. + * + * This function only accepts valid named entity references, which are finite, + * case-sensitive, and highly scrutinized by XML validators. HTML named entity + * references are converted to their code points. + * + * @since 5.5.0 + * + * @global array $allowedentitynames + * @global array $allowedxmlentitynames + * + * @param array $matches preg_replace_callback() matches array. + * @return string Correctly encoded entity. + */ + function wp_kses_xml_named_entities($matches) + { + } + /** + * Callback for `wp_kses_normalize_entities()` regular expression. + * + * This function helps `wp_kses_normalize_entities()` to only accept 16-bit + * values and nothing more for `&#number;` entities. + * + * @access private + * @ignore + * @since 1.0.0 + * + * @param array $matches `preg_replace_callback()` matches array. + * @return string Correctly encoded entity. + */ + function wp_kses_normalize_entities2($matches) + { + } + /** + * Callback for `wp_kses_normalize_entities()` for regular expression. + * + * This function helps `wp_kses_normalize_entities()` to only accept valid Unicode + * numeric entities in hex form. + * + * @since 2.7.0 + * @access private + * @ignore + * + * @param array $matches `preg_replace_callback()` matches array. + * @return string Correctly encoded entity. + */ + function wp_kses_normalize_entities3($matches) + { + } + /** + * Determines if a Unicode codepoint is valid. + * + * @since 2.7.0 + * + * @param int $i Unicode codepoint. + * @return bool Whether or not the codepoint is a valid Unicode codepoint. + */ + function valid_unicode($i) + { + } + /** + * Converts all numeric HTML entities to their named counterparts. + * + * This function decodes numeric HTML entities (`A` and `A`). + * It doesn't do anything with named entities like `ä`, but we don't + * need them in the allowed URL protocols system anyway. + * + * @since 1.0.0 + * + * @param string $string Content to change entities. + * @return string Content after decoded entities. + */ + function wp_kses_decode_entities($string) + { + } + /** + * Regex callback for `wp_kses_decode_entities()`. + * + * @since 2.9.0 + * @access private + * @ignore + * + * @param array $match preg match + * @return string + */ + function _wp_kses_decode_entities_chr($match) + { + } + /** + * Regex callback for `wp_kses_decode_entities()`. + * + * @since 2.9.0 + * @access private + * @ignore + * + * @param array $match preg match + * @return string + */ + function _wp_kses_decode_entities_chr_hexdec($match) + { + } + /** + * Sanitize content with allowed HTML KSES rules. + * + * This function expects slashed data. + * + * @since 1.0.0 + * + * @param string $data Content to filter, expected to be escaped with slashes. + * @return string Filtered content. + */ + function wp_filter_kses($data) + { + } + /** + * Sanitize content with allowed HTML KSES rules. + * + * This function expects unslashed data. + * + * @since 2.9.0 + * + * @param string $data Content to filter, expected to not be escaped. + * @return string Filtered content. + */ + function wp_kses_data($data) + { + } + /** + * Sanitizes content for allowed HTML tags for post content. + * + * Post content refers to the page contents of the 'post' type and not `$_POST` + * data from forms. + * + * This function expects slashed data. + * + * @since 2.0.0 + * + * @param string $data Post content to filter, expected to be escaped with slashes. + * @return string Filtered post content with allowed HTML tags and attributes intact. + */ + function wp_filter_post_kses($data) + { + } + /** + * Sanitizes global styles user content removing unsafe rules. + * + * @since 5.9.0 + * + * @param string $data Post content to filter. + * @return string Filtered post content with unsafe rules removed. + */ + function wp_filter_global_styles_post($data) + { + } + /** + * Sanitizes content for allowed HTML tags for post content. + * + * Post content refers to the page contents of the 'post' type and not `$_POST` + * data from forms. + * + * This function expects unslashed data. + * + * @since 2.9.0 + * + * @param string $data Post content to filter. + * @return string Filtered post content with allowed HTML tags and attributes intact. + */ + function wp_kses_post($data) + { + } + /** + * Navigates through an array, object, or scalar, and sanitizes content for + * allowed HTML tags for post content. + * + * @since 4.4.2 + * + * @see map_deep() + * + * @param mixed $data The array, object, or scalar value to inspect. + * @return mixed The filtered content. + */ + function wp_kses_post_deep($data) + { + } + /** + * Strips all HTML from a text string. + * + * This function expects slashed data. + * + * @since 2.1.0 + * + * @param string $data Content to strip all HTML from. + * @return string Filtered content without any HTML. + */ + function wp_filter_nohtml_kses($data) + { + } + /** + * Adds all KSES input form content filters. + * + * All hooks have default priority. The `wp_filter_kses()` function is added to + * the 'pre_comment_content' and 'title_save_pre' hooks. + * + * The `wp_filter_post_kses()` function is added to the 'content_save_pre', + * 'excerpt_save_pre', and 'content_filtered_save_pre' hooks. + * + * @since 2.0.0 + */ + function kses_init_filters() + { + } + /** + * Removes all KSES input form content filters. + * + * A quick procedural method to removing all of the filters that KSES uses for + * content in WordPress Loop. + * + * Does not remove the `kses_init()` function from {@see 'init'} hook (priority is + * default). Also does not remove `kses_init()` function from {@see 'set_current_user'} + * hook (priority is also default). + * + * @since 2.0.6 + */ + function kses_remove_filters() + { + } + /** + * Sets up most of the KSES filters for input form content. + * + * First removes all of the KSES filters in case the current user does not need + * to have KSES filter the content. If the user does not have `unfiltered_html` + * capability, then KSES filters are added. + * + * @since 2.0.0 + */ + function kses_init() + { + } + /** + * Filters an inline style attribute and removes disallowed rules. + * + * @since 2.8.1 + * @since 4.4.0 Added support for `min-height`, `max-height`, `min-width`, and `max-width`. + * @since 4.6.0 Added support for `list-style-type`. + * @since 5.0.0 Added support for `background-image`. + * @since 5.1.0 Added support for `text-transform`. + * @since 5.2.0 Added support for `background-position` and `grid-template-columns`. + * @since 5.3.0 Added support for `grid`, `flex` and `column` layout properties. + * Extended `background-*` support for individual properties. + * @since 5.3.1 Added support for gradient backgrounds. + * @since 5.7.1 Added support for `object-position`. + * @since 5.8.0 Added support for `calc()` and `var()` values. + * @since 6.1.0 Added support for `min()`, `max()`, `minmax()`, `clamp()`, + * nested `var()` values, and assigning values to CSS variables. + * Added support for `object-fit`, `gap`, `column-gap`, `row-gap`, and `flex-wrap`. + * Extended `margin-*` and `padding-*` support for logical properties. + * + * @param string $css A string of CSS rules. + * @param string $deprecated Not used. + * @return string Filtered string of CSS rules. + */ + function safecss_filter_attr($css, $deprecated = '') + { + } + /** + * Helper function to add global attributes to a tag in the allowed HTML list. + * + * @since 3.5.0 + * @since 5.0.0 Added support for `data-*` wildcard attributes. + * @since 6.0.0 Added `dir`, `lang`, and `xml:lang` to global attributes. + * + * @access private + * @ignore + * + * @param array $value An array of attributes. + * @return array The array of attributes with global attributes added. + */ + function _wp_add_global_attributes($value) + { + } + /** + * Helper function to check if this is a safe PDF URL. + * + * @since 5.9.0 + * @access private + * @ignore + * + * @param string $url The URL to check. + * @return bool True if the URL is safe, false otherwise. + */ + function _wp_kses_allow_pdf_objects($url) + { + } + /** + * Core Translation API + * + * @package WordPress + * @subpackage i18n + * @since 1.2.0 + */ + /** + * Retrieves the current locale. + * + * If the locale is set, then it will filter the locale in the {@see 'locale'} + * filter hook and return the value. + * + * If the locale is not set already, then the WPLANG constant is used if it is + * defined. Then it is filtered through the {@see 'locale'} filter hook and + * the value for the locale global set and the locale is returned. + * + * The process to get the locale should only be done once, but the locale will + * always be filtered using the {@see 'locale'} hook. + * + * @since 1.5.0 + * + * @global string $locale The current locale. + * @global string $wp_local_package Locale code of the package. + * + * @return string The locale of the blog or from the {@see 'locale'} hook. + */ + function get_locale() + { + } + /** + * Retrieves the locale of a user. + * + * If the user has a locale set to a non-empty string then it will be + * returned. Otherwise it returns the locale of get_locale(). + * + * @since 4.7.0 + * + * @param int|WP_User $user User's ID or a WP_User object. Defaults to current user. + * @return string The locale of the user. + */ + function get_user_locale($user = 0) + { + } + /** + * Determines the current locale desired for the request. + * + * @since 5.0.0 + * + * @global string $pagenow The filename of the current screen. + * + * @return string The determined locale. + */ + function determine_locale() + { + } + /** + * Retrieves the translation of $text. + * + * If there is no translation, or the text domain isn't loaded, the original text is returned. + * + * *Note:* Don't use translate() directly, use __() or related functions. + * + * @since 2.2.0 + * @since 5.5.0 Introduced gettext-{$domain} filter. + * + * @param string $text Text to translate. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + * @return string Translated text. + */ + function translate($text, $domain = 'default') + { + } + /** + * Removes last item on a pipe-delimited string. + * + * Meant for removing the last item in a string, such as 'Role name|User role'. The original + * string will be returned if no pipe '|' characters are found in the string. + * + * @since 2.8.0 + * + * @param string $string A pipe-delimited string. + * @return string Either $string or everything before the last pipe. + */ + function before_last_bar($string) + { + } + /** + * Retrieves the translation of $text in the context defined in $context. + * + * If there is no translation, or the text domain isn't loaded, the original text is returned. + * + * *Note:* Don't use translate_with_gettext_context() directly, use _x() or related functions. + * + * @since 2.8.0 + * @since 5.5.0 Introduced gettext_with_context-{$domain} filter. + * + * @param string $text Text to translate. + * @param string $context Context information for the translators. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + * @return string Translated text on success, original text on failure. + */ + function translate_with_gettext_context($text, $context, $domain = 'default') + { + } + /** + * Retrieves the translation of $text. + * + * If there is no translation, or the text domain isn't loaded, the original text is returned. + * + * @since 2.1.0 + * + * @param string $text Text to translate. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + * @return string Translated text. + */ + function __($text, $domain = 'default') + { + } + /** + * Retrieves the translation of $text and escapes it for safe use in an attribute. + * + * If there is no translation, or the text domain isn't loaded, the original text is returned. + * + * @since 2.8.0 + * + * @param string $text Text to translate. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + * @return string Translated text on success, original text on failure. + */ + function esc_attr__($text, $domain = 'default') + { + } + /** + * Retrieves the translation of $text and escapes it for safe use in HTML output. + * + * If there is no translation, or the text domain isn't loaded, the original text + * is escaped and returned. + * + * @since 2.8.0 + * + * @param string $text Text to translate. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + * @return string Translated text. + */ + function esc_html__($text, $domain = 'default') + { + } + /** + * Displays translated text. + * + * @since 1.2.0 + * + * @param string $text Text to translate. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + */ + function _e($text, $domain = 'default') + { + } + /** + * Displays translated text that has been escaped for safe use in an attribute. + * + * Encodes `< > & " '` (less than, greater than, ampersand, double quote, single quote). + * Will never double encode entities. + * + * If you need the value for use in PHP, use esc_attr__(). + * + * @since 2.8.0 + * + * @param string $text Text to translate. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + */ + function esc_attr_e($text, $domain = 'default') + { + } + /** + * Displays translated text that has been escaped for safe use in HTML output. + * + * If there is no translation, or the text domain isn't loaded, the original text + * is escaped and displayed. + * + * If you need the value for use in PHP, use esc_html__(). + * + * @since 2.8.0 + * + * @param string $text Text to translate. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + */ + function esc_html_e($text, $domain = 'default') + { + } + /** + * Retrieves translated string with gettext context. + * + * Quite a few times, there will be collisions with similar translatable text + * found in more than two places, but with different translated context. + * + * By including the context in the pot file, translators can translate the two + * strings differently. + * + * @since 2.8.0 + * + * @param string $text Text to translate. + * @param string $context Context information for the translators. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + * @return string Translated context string without pipe. + */ + function _x($text, $context, $domain = 'default') + { + } + /** + * Displays translated string with gettext context. + * + * @since 3.0.0 + * + * @param string $text Text to translate. + * @param string $context Context information for the translators. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + */ + function _ex($text, $context, $domain = 'default') + { + } + /** + * Translates string with gettext context, and escapes it for safe use in an attribute. + * + * If there is no translation, or the text domain isn't loaded, the original text + * is escaped and returned. + * + * @since 2.8.0 + * + * @param string $text Text to translate. + * @param string $context Context information for the translators. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + * @return string Translated text. + */ + function esc_attr_x($text, $context, $domain = 'default') + { + } + /** + * Translates string with gettext context, and escapes it for safe use in HTML output. + * + * If there is no translation, or the text domain isn't loaded, the original text + * is escaped and returned. + * + * @since 2.9.0 + * + * @param string $text Text to translate. + * @param string $context Context information for the translators. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + * @return string Translated text. + */ + function esc_html_x($text, $context, $domain = 'default') + { + } + /** + * Translates and retrieves the singular or plural form based on the supplied number. + * + * Used when you want to use the appropriate form of a string based on whether a + * number is singular or plural. + * + * Example: + * + * printf( _n( '%s person', '%s people', $count, 'text-domain' ), number_format_i18n( $count ) ); + * + * @since 2.8.0 + * @since 5.5.0 Introduced ngettext-{$domain} filter. + * + * @param string $single The text to be used if the number is singular. + * @param string $plural The text to be used if the number is plural. + * @param int $number The number to compare against to use either the singular or plural form. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + * @return string The translated singular or plural form. + */ + function _n($single, $plural, $number, $domain = 'default') + { + } + /** + * Translates and retrieves the singular or plural form based on the supplied number, with gettext context. + * + * This is a hybrid of _n() and _x(). It supports context and plurals. + * + * Used when you want to use the appropriate form of a string with context based on whether a + * number is singular or plural. + * + * Example of a generic phrase which is disambiguated via the context parameter: + * + * printf( _nx( '%s group', '%s groups', $people, 'group of people', 'text-domain' ), number_format_i18n( $people ) ); + * printf( _nx( '%s group', '%s groups', $animals, 'group of animals', 'text-domain' ), number_format_i18n( $animals ) ); + * + * @since 2.8.0 + * @since 5.5.0 Introduced ngettext_with_context-{$domain} filter. + * + * @param string $single The text to be used if the number is singular. + * @param string $plural The text to be used if the number is plural. + * @param int $number The number to compare against to use either the singular or plural form. + * @param string $context Context information for the translators. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + * @return string The translated singular or plural form. + */ + function _nx($single, $plural, $number, $context, $domain = 'default') + { + } + /** + * Registers plural strings in POT file, but does not translate them. + * + * Used when you want to keep structures with translatable plural + * strings and use them later when the number is known. + * + * Example: + * + * $message = _n_noop( '%s post', '%s posts', 'text-domain' ); + * ... + * printf( translate_nooped_plural( $message, $count, 'text-domain' ), number_format_i18n( $count ) ); + * + * @since 2.5.0 + * + * @param string $singular Singular form to be localized. + * @param string $plural Plural form to be localized. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default null. + * @return array { + * Array of translation information for the strings. + * + * @type string $0 Singular form to be localized. No longer used. + * @type string $1 Plural form to be localized. No longer used. + * @type string $singular Singular form to be localized. + * @type string $plural Plural form to be localized. + * @type null $context Context information for the translators. + * @type string|null $domain Text domain. + * } + * @phpstan-return array{ + * 0: string, + * 1: string, + * singular: string, + * plural: string, + * context: null, + * domain: string|null, + * } + */ + function _n_noop($singular, $plural, $domain = \null) + { + } + /** + * Registers plural strings with gettext context in POT file, but does not translate them. + * + * Used when you want to keep structures with translatable plural + * strings and use them later when the number is known. + * + * Example of a generic phrase which is disambiguated via the context parameter: + * + * $messages = array( + * 'people' => _nx_noop( '%s group', '%s groups', 'people', 'text-domain' ), + * 'animals' => _nx_noop( '%s group', '%s groups', 'animals', 'text-domain' ), + * ); + * ... + * $message = $messages[ $type ]; + * printf( translate_nooped_plural( $message, $count, 'text-domain' ), number_format_i18n( $count ) ); + * + * @since 2.8.0 + * + * @param string $singular Singular form to be localized. + * @param string $plural Plural form to be localized. + * @param string $context Context information for the translators. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default null. + * @return array { + * Array of translation information for the strings. + * + * @type string $0 Singular form to be localized. No longer used. + * @type string $1 Plural form to be localized. No longer used. + * @type string $2 Context information for the translators. No longer used. + * @type string $singular Singular form to be localized. + * @type string $plural Plural form to be localized. + * @type string $context Context information for the translators. + * @type string|null $domain Text domain. + * } + * @phpstan-return array{ + * 0: string, + * 1: string, + * 2: string, + * singular: string, + * plural: string, + * context: string, + * domain: string|null, + * } + */ + function _nx_noop($singular, $plural, $context, $domain = \null) + { + } + /** + * Translates and returns the singular or plural form of a string that's been registered + * with _n_noop() or _nx_noop(). + * + * Used when you want to use a translatable plural string once the number is known. + * + * Example: + * + * $message = _n_noop( '%s post', '%s posts', 'text-domain' ); + * ... + * printf( translate_nooped_plural( $message, $count, 'text-domain' ), number_format_i18n( $count ) ); + * + * @since 3.1.0 + * + * @param array $nooped_plural { + * Array that is usually a return value from _n_noop() or _nx_noop(). + * + * @type string $singular Singular form to be localized. + * @type string $plural Plural form to be localized. + * @type string|null $context Context information for the translators. + * @type string|null $domain Text domain. + * } + * @param int $count Number of objects. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. If $nooped_plural contains + * a text domain passed to _n_noop() or _nx_noop(), it will override this value. Default 'default'. + * @return string Either $singular or $plural translated text. + * @phpstan-param array{ + * singular?: string, + * plural?: string, + * context?: string|null, + * domain?: string|null, + * } $nooped_plural + */ + function translate_nooped_plural($nooped_plural, $count, $domain = 'default') + { + } + /** + * Loads a .mo file into the text domain $domain. + * + * If the text domain already exists, the translations will be merged. If both + * sets have the same string, the translation from the original value will be taken. + * + * On success, the .mo file will be placed in the $l10n global by $domain + * and will be a MO object. + * + * @since 1.5.0 + * @since 6.1.0 Added the `$locale` parameter. + * + * @global MO[] $l10n An array of all currently loaded text domains. + * @global MO[] $l10n_unloaded An array of all text domains that have been unloaded again. + * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry. + * + * @param string $domain Text domain. Unique identifier for retrieving translated strings. + * @param string $mofile Path to the .mo file. + * @param string $locale Optional. Locale. Default is the current locale. + * @return bool True on success, false on failure. + */ + function load_textdomain($domain, $mofile, $locale = \null) + { + } + /** + * Unloads translations for a text domain. + * + * @since 3.0.0 + * @since 6.1.0 Added the `$reloadable` parameter. + * + * @global MO[] $l10n An array of all currently loaded text domains. + * @global MO[] $l10n_unloaded An array of all text domains that have been unloaded again. + * + * @param string $domain Text domain. Unique identifier for retrieving translated strings. + * @param bool $reloadable Whether the text domain can be loaded just-in-time again. + * @return bool Whether textdomain was unloaded. + */ + function unload_textdomain($domain, $reloadable = \false) + { + } + /** + * Loads default translated strings based on locale. + * + * Loads the .mo file in WP_LANG_DIR constant path from WordPress root. + * The translated (.mo) file is named based on the locale. + * + * @see load_textdomain() + * + * @since 1.5.0 + * + * @param string $locale Optional. Locale to load. Default is the value of get_locale(). + * @return bool Whether the textdomain was loaded. + */ + function load_default_textdomain($locale = \null) + { + } + /** + * Loads a plugin's translated strings. + * + * If the path is not given then it will be the root of the plugin directory. + * + * The .mo file should be named based on the text domain with a dash, and then the locale exactly. + * + * @since 1.5.0 + * @since 4.6.0 The function now tries to load the .mo file from the languages directory first. + * + * @param string $domain Unique identifier for retrieving translated strings + * @param string|false $deprecated Optional. Deprecated. Use the $plugin_rel_path parameter instead. + * Default false. + * @param string|false $plugin_rel_path Optional. Relative path to WP_PLUGIN_DIR where the .mo file resides. + * Default false. + * @return bool True when textdomain is successfully loaded, false otherwise. + */ + function load_plugin_textdomain($domain, $deprecated = \false, $plugin_rel_path = \false) + { + } + /** + * Loads the translated strings for a plugin residing in the mu-plugins directory. + * + * @since 3.0.0 + * @since 4.6.0 The function now tries to load the .mo file from the languages directory first. + * + * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry. + * + * @param string $domain Text domain. Unique identifier for retrieving translated strings. + * @param string $mu_plugin_rel_path Optional. Relative to `WPMU_PLUGIN_DIR` directory in which the .mo + * file resides. Default empty string. + * @return bool True when textdomain is successfully loaded, false otherwise. + */ + function load_muplugin_textdomain($domain, $mu_plugin_rel_path = '') + { + } + /** + * Loads the theme's translated strings. + * + * If the current locale exists as a .mo file in the theme's root directory, it + * will be included in the translated strings by the $domain. + * + * The .mo files must be named based on the locale exactly. + * + * @since 1.5.0 + * @since 4.6.0 The function now tries to load the .mo file from the languages directory first. + * + * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry. + * + * @param string $domain Text domain. Unique identifier for retrieving translated strings. + * @param string|false $path Optional. Path to the directory containing the .mo file. + * Default false. + * @return bool True when textdomain is successfully loaded, false otherwise. + */ + function load_theme_textdomain($domain, $path = \false) + { + } + /** + * Loads the child themes translated strings. + * + * If the current locale exists as a .mo file in the child themes + * root directory, it will be included in the translated strings by the $domain. + * + * The .mo files must be named based on the locale exactly. + * + * @since 2.9.0 + * + * @param string $domain Text domain. Unique identifier for retrieving translated strings. + * @param string|false $path Optional. Path to the directory containing the .mo file. + * Default false. + * @return bool True when the theme textdomain is successfully loaded, false otherwise. + */ + function load_child_theme_textdomain($domain, $path = \false) + { + } + /** + * Loads the script translated strings. + * + * @since 5.0.0 + * @since 5.0.2 Uses load_script_translations() to load translation data. + * @since 5.1.0 The `$domain` parameter was made optional. + * + * @see WP_Scripts::set_translations() + * + * @param string $handle Name of the script to register a translation domain to. + * @param string $domain Optional. Text domain. Default 'default'. + * @param string $path Optional. The full file path to the directory containing translation files. + * @return string|false The translated strings in JSON encoding on success, + * false if the script textdomain could not be loaded. + */ + function load_script_textdomain($handle, $domain = 'default', $path = '') + { + } + /** + * Loads the translation data for the given script handle and text domain. + * + * @since 5.0.2 + * + * @param string|false $file Path to the translation file to load. False if there isn't one. + * @param string $handle Name of the script to register a translation domain to. + * @param string $domain The text domain. + * @return string|false The JSON-encoded translated strings for the given script handle and text domain. + * False if there are none. + */ + function load_script_translations($file, $handle, $domain) + { + } + /** + * Loads plugin and theme text domains just-in-time. + * + * When a textdomain is encountered for the first time, we try to load + * the translation file from `wp-content/languages`, removing the need + * to call load_plugin_textdomain() or load_theme_textdomain(). + * + * @since 4.6.0 + * @access private + * + * @global MO[] $l10n_unloaded An array of all text domains that have been unloaded again. + * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry. + * + * @param string $domain Text domain. Unique identifier for retrieving translated strings. + * @return bool True when the textdomain is successfully loaded, false otherwise. + */ + function _load_textdomain_just_in_time($domain) + { + } + /** + * Returns the Translations instance for a text domain. + * + * If there isn't one, returns empty Translations instance. + * + * @since 2.8.0 + * + * @global MO[] $l10n An array of all currently loaded text domains. + * + * @param string $domain Text domain. Unique identifier for retrieving translated strings. + * @return Translations|NOOP_Translations A Translations instance. + */ + function get_translations_for_domain($domain) + { + } + /** + * Determines whether there are translations for the text domain. + * + * @since 3.0.0 + * + * @global MO[] $l10n An array of all currently loaded text domains. + * + * @param string $domain Text domain. Unique identifier for retrieving translated strings. + * @return bool Whether there are translations. + */ + function is_textdomain_loaded($domain) + { + } + /** + * Translates role name. + * + * Since the role names are in the database and not in the source there + * are dummy gettext calls to get them into the POT file and this function + * properly translates them back. + * + * The before_last_bar() call is needed, because older installations keep the roles + * using the old context format: 'Role name|User role' and just skipping the + * content after the last bar is easier than fixing them in the DB. New installations + * won't suffer from that problem. + * + * @since 2.8.0 + * @since 5.2.0 Added the `$domain` parameter. + * + * @param string $name The role name. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * Default 'default'. + * @return string Translated role name on success, original name on failure. + */ + function translate_user_role($name, $domain = 'default') + { + } + /** + * Gets all available languages based on the presence of *.mo files in a given directory. + * + * The default directory is WP_LANG_DIR. + * + * @since 3.0.0 + * @since 4.7.0 The results are now filterable with the {@see 'get_available_languages'} filter. + * + * @param string $dir A directory to search for language files. + * Default WP_LANG_DIR. + * @return string[] An array of language codes or an empty array if no languages are present. Language codes are formed by stripping the .mo extension from the language file names. + */ + function get_available_languages($dir = \null) + { + } + /** + * Gets installed translations. + * + * Looks in the wp-content/languages directory for translations of + * plugins or themes. + * + * @since 3.7.0 + * + * @param string $type What to search for. Accepts 'plugins', 'themes', 'core'. + * @return array Array of language data. + */ + function wp_get_installed_translations($type) + { + } + /** + * Extracts headers from a PO file. + * + * @since 3.7.0 + * + * @param string $po_file Path to PO file. + * @return string[] Array of PO file header values keyed by header name. + */ + function wp_get_pomo_file_data($po_file) + { + } + /** + * Displays or returns a Language selector. + * + * @since 4.0.0 + * @since 4.3.0 Introduced the `echo` argument. + * @since 4.7.0 Introduced the `show_option_site_default` argument. + * @since 5.1.0 Introduced the `show_option_en_us` argument. + * @since 5.9.0 Introduced the `explicit_option_en_us` argument. + * + * @see get_available_languages() + * @see wp_get_available_translations() + * + * @param string|array $args { + * Optional. Array or string of arguments for outputting the language selector. + * + * @type string $id ID attribute of the select element. Default 'locale'. + * @type string $name Name attribute of the select element. Default 'locale'. + * @type array $languages List of installed languages, contain only the locales. + * Default empty array. + * @type array $translations List of available translations. Default result of + * wp_get_available_translations(). + * @type string $selected Language which should be selected. Default empty. + * @type bool|int $echo Whether to echo the generated markup. Accepts 0, 1, or their + * boolean equivalents. Default 1. + * @type bool $show_available_translations Whether to show available translations. Default true. + * @type bool $show_option_site_default Whether to show an option to fall back to the site's locale. Default false. + * @type bool $show_option_en_us Whether to show an option for English (United States). Default true. + * @type bool $explicit_option_en_us Whether the English (United States) option uses an explicit value of en_US + * instead of an empty value. Default false. + * } + * @return string HTML dropdown list of languages. + * @phpstan-param array{ + * id?: string, + * name?: string, + * languages?: array, + * translations?: array, + * selected?: string, + * echo?: bool|int, + * show_available_translations?: bool, + * show_option_site_default?: bool, + * show_option_en_us?: bool, + * explicit_option_en_us?: bool, + * } $args + */ + function wp_dropdown_languages($args = array()) + { + } + /** + * Determines whether the current locale is right-to-left (RTL). + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 3.0.0 + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @return bool Whether locale is RTL. + */ + function is_rtl() + { + } + /** + * Switches the translations according to the given locale. + * + * @since 4.7.0 + * + * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object. + * + * @param string $locale The locale. + * @return bool True on success, false on failure. + */ + function switch_to_locale($locale) + { + } + /** + * Restores the translations according to the previous locale. + * + * @since 4.7.0 + * + * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object. + * + * @return string|false Locale on success, false on error. + */ + function restore_previous_locale() + { + } + /** + * Restores the translations according to the original locale. + * + * @since 4.7.0 + * + * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object. + * + * @return string|false Locale on success, false on error. + */ + function restore_current_locale() + { + } + /** + * Determines whether switch_to_locale() is in effect. + * + * @since 4.7.0 + * + * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object. + * + * @return bool True if the locale has been switched, false otherwise. + */ + function is_locale_switched() + { + } + /** + * Translates the provided settings value using its i18n schema. + * + * @since 5.9.0 + * @access private + * + * @param string|string[]|array[]|object $i18n_schema I18n schema for the setting. + * @param string|string[]|array[] $settings Value for the settings. + * @param string $textdomain Textdomain to use with translations. + * + * @return string|string[]|array[] Translated settings. + */ + function translate_settings_using_i18n_schema($i18n_schema, $settings, $textdomain) + { + } + /** + * Retrieves the list item separator based on the locale. + * + * @since 6.0.0 + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @return string Locale-specific list item separator. + */ + function wp_get_list_item_separator() + { + } + /** + * WordPress Link Template Functions + * + * @package WordPress + * @subpackage Template + */ + /** + * Displays the permalink for the current post. + * + * @since 1.2.0 + * @since 4.4.0 Added the `$post` parameter. + * + * @param int|WP_Post $post Optional. Post ID or post object. Default is the global `$post`. + */ + function the_permalink($post = 0) + { + } + /** + * Retrieves a trailing-slashed string if the site is set for adding trailing slashes. + * + * Conditionally adds a trailing slash if the permalink structure has a trailing + * slash, strips the trailing slash if not. The string is passed through the + * {@see 'user_trailingslashit'} filter. Will remove trailing slash from string, if + * site is not set to have them. + * + * @since 2.2.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $string URL with or without a trailing slash. + * @param string $type_of_url Optional. The type of URL being considered (e.g. single, category, etc) + * for use in the filter. Default empty string. + * @return string The URL with the trailing slash appended or stripped. + */ + function user_trailingslashit($string, $type_of_url = '') + { + } + /** + * Displays the permalink anchor for the current post. + * + * The permalink mode title will use the post title for the 'a' element 'id' + * attribute. The id mode uses 'post-' with the post ID for the 'id' attribute. + * + * @since 0.71 + * + * @param string $mode Optional. Permalink mode. Accepts 'title' or 'id'. Default 'id'. + */ + function permalink_anchor($mode = 'id') + { + } + /** + * Determine whether post should always use a plain permalink structure. + * + * @since 5.7.0 + * + * @param WP_Post|int|null $post Optional. Post ID or post object. Defaults to global $post. + * @param bool|null $sample Optional. Whether to force consideration based on sample links. + * If omitted, a sample link is generated if a post object is passed + * with the filter property set to 'sample'. + * @return bool Whether to use a plain permalink structure. + */ + function wp_force_plain_post_permalink($post = \null, $sample = \null) + { + } + /** + * Retrieves the full permalink for the current post or post ID. + * + * This function is an alias for get_permalink(). + * + * @since 3.9.0 + * + * @see get_permalink() + * + * @param int|WP_Post $post Optional. Post ID or post object. Default is the global `$post`. + * @param bool $leavename Optional. Whether to keep post name or page name. Default false. + * @return string|false The permalink URL. False if the post does not exist. + */ + function get_the_permalink($post = 0, $leavename = \false) + { + } + /** + * Retrieves the full permalink for the current post or post ID. + * + * @since 1.0.0 + * + * @param int|WP_Post $post Optional. Post ID or post object. Default is the global `$post`. + * @param bool $leavename Optional. Whether to keep post name or page name. Default false. + * @return string|false The permalink URL. False if the post does not exist. + */ + function get_permalink($post = 0, $leavename = \false) + { + } + /** + * Retrieves the permalink for a post of a custom post type. + * + * @since 3.0.0 + * @since 6.1.0 Returns false if the post does not exist. + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param int|WP_Post $post Optional. Post ID or post object. Default is the global `$post`. + * @param bool $leavename Optional. Whether to keep post name. Default false. + * @param bool $sample Optional. Is it a sample permalink. Default false. + * @return string|false The post permalink URL. False if the post does not exist. + */ + function get_post_permalink($post = 0, $leavename = \false, $sample = \false) + { + } + /** + * Retrieves the permalink for the current page or page ID. + * + * Respects page_on_front. Use this one. + * + * @since 1.5.0 + * + * @param int|WP_Post $post Optional. Post ID or object. Default uses the global `$post`. + * @param bool $leavename Optional. Whether to keep the page name. Default false. + * @param bool $sample Optional. Whether it should be treated as a sample permalink. + * Default false. + * @return string The page permalink. + */ + function get_page_link($post = \false, $leavename = \false, $sample = \false) + { + } + /** + * Retrieves the page permalink. + * + * Ignores page_on_front. Internal use only. + * + * @since 2.1.0 + * @access private + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param int|WP_Post $post Optional. Post ID or object. Default uses the global `$post`. + * @param bool $leavename Optional. Whether to keep the page name. Default false. + * @param bool $sample Optional. Whether it should be treated as a sample permalink. + * Default false. + * @return string The page permalink. + */ + function _get_page_link($post = \false, $leavename = \false, $sample = \false) + { + } + /** + * Retrieves the permalink for an attachment. + * + * This can be used in the WordPress Loop or outside of it. + * + * @since 2.0.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param int|object $post Optional. Post ID or object. Default uses the global `$post`. + * @param bool $leavename Optional. Whether to keep the page name. Default false. + * @return string The attachment permalink. + */ + function get_attachment_link($post = \null, $leavename = \false) + { + } + /** + * Retrieves the permalink for the year archives. + * + * @since 1.5.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param int|false $year Integer of year. False for current year. + * @return string The permalink for the specified year archive. + */ + function get_year_link($year) + { + } + /** + * Retrieves the permalink for the month archives with year. + * + * @since 1.0.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param int|false $year Integer of year. False for current year. + * @param int|false $month Integer of month. False for current month. + * @return string The permalink for the specified month and year archive. + */ + function get_month_link($year, $month) + { + } + /** + * Retrieves the permalink for the day archives with year and month. + * + * @since 1.0.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param int|false $year Integer of year. False for current year. + * @param int|false $month Integer of month. False for current month. + * @param int|false $day Integer of day. False for current day. + * @return string The permalink for the specified day, month, and year archive. + */ + function get_day_link($year, $month, $day) + { + } + /** + * Displays the permalink for the feed type. + * + * @since 3.0.0 + * + * @param string $anchor The link's anchor text. + * @param string $feed Optional. Feed type. Possible values include 'rss2', 'atom'. + * Default is the value of get_default_feed(). + */ + function the_feed_link($anchor, $feed = '') + { + } + /** + * Retrieves the permalink for the feed type. + * + * @since 1.5.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $feed Optional. Feed type. Possible values include 'rss2', 'atom'. + * Default is the value of get_default_feed(). + * @return string The feed permalink. + */ + function get_feed_link($feed = '') + { + } + /** + * Retrieves the permalink for the post comments feed. + * + * @since 2.2.0 + * + * @param int $post_id Optional. Post ID. Default is the ID of the global `$post`. + * @param string $feed Optional. Feed type. Possible values include 'rss2', 'atom'. + * Default is the value of get_default_feed(). + * @return string The permalink for the comments feed for the given post on success, empty string on failure. + */ + function get_post_comments_feed_link($post_id = 0, $feed = '') + { + } + /** + * Displays the comment feed link for a post. + * + * Prints out the comment feed link for a post. Link text is placed in the + * anchor. If no link text is specified, default text is used. If no post ID is + * specified, the current post is used. + * + * @since 2.5.0 + * + * @param string $link_text Optional. Descriptive link text. Default 'Comments Feed'. + * @param int $post_id Optional. Post ID. Default is the ID of the global `$post`. + * @param string $feed Optional. Feed type. Possible values include 'rss2', 'atom'. + * Default is the value of get_default_feed(). + */ + function post_comments_feed_link($link_text = '', $post_id = '', $feed = '') + { + } + /** + * Retrieves the feed link for a given author. + * + * Returns a link to the feed for all posts by a given author. A specific feed + * can be requested or left blank to get the default feed. + * + * @since 2.5.0 + * + * @param int $author_id Author ID. + * @param string $feed Optional. Feed type. Possible values include 'rss2', 'atom'. + * Default is the value of get_default_feed(). + * @return string Link to the feed for the author specified by $author_id. + */ + function get_author_feed_link($author_id, $feed = '') + { + } + /** + * Retrieves the feed link for a category. + * + * Returns a link to the feed for all posts in a given category. A specific feed + * can be requested or left blank to get the default feed. + * + * @since 2.5.0 + * + * @param int|WP_Term|object $cat The ID or category object whose feed link will be retrieved. + * @param string $feed Optional. Feed type. Possible values include 'rss2', 'atom'. + * Default is the value of get_default_feed(). + * @return string Link to the feed for the category specified by `$cat`. + */ + function get_category_feed_link($cat, $feed = '') + { + } + /** + * Retrieves the feed link for a term. + * + * Returns a link to the feed for all posts in a given term. A specific feed + * can be requested or left blank to get the default feed. + * + * @since 3.0.0 + * + * @param int|WP_Term|object $term The ID or term object whose feed link will be retrieved. + * @param string $taxonomy Optional. Taxonomy of `$term_id`. + * @param string $feed Optional. Feed type. Possible values include 'rss2', 'atom'. + * Default is the value of get_default_feed(). + * @return string|false Link to the feed for the term specified by `$term` and `$taxonomy`. + */ + function get_term_feed_link($term, $taxonomy = '', $feed = '') + { + } + /** + * Retrieves the permalink for a tag feed. + * + * @since 2.3.0 + * + * @param int|WP_Term|object $tag The ID or term object whose feed link will be retrieved. + * @param string $feed Optional. Feed type. Possible values include 'rss2', 'atom'. + * Default is the value of get_default_feed(). + * @return string The feed permalink for the given tag. + */ + function get_tag_feed_link($tag, $feed = '') + { + } + /** + * Retrieves the edit link for a tag. + * + * @since 2.7.0 + * + * @param int|WP_Term|object $tag The ID or term object whose edit link will be retrieved. + * @param string $taxonomy Optional. Taxonomy slug. Default 'post_tag'. + * @return string The edit tag link URL for the given tag. + */ + function get_edit_tag_link($tag, $taxonomy = 'post_tag') + { + } + /** + * Displays or retrieves the edit link for a tag with formatting. + * + * @since 2.7.0 + * + * @param string $link Optional. Anchor text. If empty, default is 'Edit This'. Default empty. + * @param string $before Optional. Display before edit link. Default empty. + * @param string $after Optional. Display after edit link. Default empty. + * @param WP_Term $tag Optional. Term object. If null, the queried object will be inspected. + * Default null. + */ + function edit_tag_link($link = '', $before = '', $after = '', $tag = \null) + { + } + /** + * Retrieves the URL for editing a given term. + * + * @since 3.1.0 + * @since 4.5.0 The `$taxonomy` parameter was made optional. + * + * @param int|WP_Term|object $term The ID or term object whose edit link will be retrieved. + * @param string $taxonomy Optional. Taxonomy. Defaults to the taxonomy of the term identified + * by `$term`. + * @param string $object_type Optional. The object type. Used to highlight the proper post type + * menu on the linked page. Defaults to the first object_type associated + * with the taxonomy. + * @return string|null The edit term link URL for the given term, or null on failure. + */ + function get_edit_term_link($term, $taxonomy = '', $object_type = '') + { + } + /** + * Displays or retrieves the edit term link with formatting. + * + * @since 3.1.0 + * + * @param string $link Optional. Anchor text. If empty, default is 'Edit This'. Default empty. + * @param string $before Optional. Display before edit link. Default empty. + * @param string $after Optional. Display after edit link. Default empty. + * @param int|WP_Term|null $term Optional. Term ID or object. If null, the queried object will be inspected. Default null. + * @param bool $echo Optional. Whether or not to echo the return. Default true. + * @return string|void HTML content. + */ + function edit_term_link($link = '', $before = '', $after = '', $term = \null, $echo = \true) + { + } + /** + * Retrieves the permalink for a search. + * + * @since 3.0.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $query Optional. The query string to use. If empty the current query is used. Default empty. + * @return string The search permalink. + */ + function get_search_link($query = '') + { + } + /** + * Retrieves the permalink for the search results feed. + * + * @since 2.5.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $search_query Optional. Search query. Default empty. + * @param string $feed Optional. Feed type. Possible values include 'rss2', 'atom'. + * Default is the value of get_default_feed(). + * @return string The search results feed permalink. + */ + function get_search_feed_link($search_query = '', $feed = '') + { + } + /** + * Retrieves the permalink for the search results comments feed. + * + * @since 2.5.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $search_query Optional. Search query. Default empty. + * @param string $feed Optional. Feed type. Possible values include 'rss2', 'atom'. + * Default is the value of get_default_feed(). + * @return string The comments feed search results permalink. + */ + function get_search_comments_feed_link($search_query = '', $feed = '') + { + } + /** + * Retrieves the permalink for a post type archive. + * + * @since 3.1.0 + * @since 4.5.0 Support for posts was added. + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $post_type Post type. + * @return string|false The post type archive permalink. False if the post type + * does not exist or does not have an archive. + */ + function get_post_type_archive_link($post_type) + { + } + /** + * Retrieves the permalink for a post type archive feed. + * + * @since 3.1.0 + * + * @param string $post_type Post type. + * @param string $feed Optional. Feed type. Possible values include 'rss2', 'atom'. + * Default is the value of get_default_feed(). + * @return string|false The post type feed permalink. False if the post type + * does not exist or does not have an archive. + */ + function get_post_type_archive_feed_link($post_type, $feed = '') + { + } + /** + * Retrieves the URL used for the post preview. + * + * Allows additional query args to be appended. + * + * @since 4.4.0 + * + * @param int|WP_Post $post Optional. Post ID or `WP_Post` object. Defaults to global `$post`. + * @param array $query_args Optional. Array of additional query args to be appended to the link. + * Default empty array. + * @param string $preview_link Optional. Base preview link to be used if it should differ from the + * post permalink. Default empty. + * @return string|null URL used for the post preview, or null if the post does not exist. + */ + function get_preview_post_link($post = \null, $query_args = array(), $preview_link = '') + { + } + /** + * Retrieves the edit post link for post. + * + * Can be used within the WordPress loop or outside of it. Can be used with + * pages, posts, attachments, and revisions. + * + * @since 2.3.0 + * + * @param int|WP_Post $post Optional. Post ID or post object. Default is the global `$post`. + * @param string $context Optional. How to output the '&' character. Default '&'. + * @return string|null The edit post link for the given post. Null if the post type does not exist + * or does not allow an editing UI. + */ + function get_edit_post_link($post = 0, $context = 'display') + { + } + /** + * Displays the edit post link for post. + * + * @since 1.0.0 + * @since 4.4.0 The `$class` argument was added. + * + * @param string $text Optional. Anchor text. If null, default is 'Edit This'. Default null. + * @param string $before Optional. Display before edit link. Default empty. + * @param string $after Optional. Display after edit link. Default empty. + * @param int|WP_Post $post Optional. Post ID or post object. Default is the global `$post`. + * @param string $class Optional. Add custom class to link. Default 'post-edit-link'. + */ + function edit_post_link($text = \null, $before = '', $after = '', $post = 0, $class = 'post-edit-link') + { + } + /** + * Retrieves the delete posts link for post. + * + * Can be used within the WordPress loop or outside of it, with any post type. + * + * @since 2.9.0 + * + * @param int|WP_Post $post Optional. Post ID or post object. Default is the global `$post`. + * @param string $deprecated Not used. + * @param bool $force_delete Optional. Whether to bypass Trash and force deletion. Default false. + * @return string|void The delete post link URL for the given post. + */ + function get_delete_post_link($post = 0, $deprecated = '', $force_delete = \false) + { + } + /** + * Retrieves the edit comment link. + * + * @since 2.3.0 + * + * @param int|WP_Comment $comment_id Optional. Comment ID or WP_Comment object. + * @return string|void The edit comment link URL for the given comment. + */ + function get_edit_comment_link($comment_id = 0) + { + } + /** + * Displays the edit comment link with formatting. + * + * @since 1.0.0 + * + * @param string $text Optional. Anchor text. If null, default is 'Edit This'. Default null. + * @param string $before Optional. Display before edit link. Default empty. + * @param string $after Optional. Display after edit link. Default empty. + */ + function edit_comment_link($text = \null, $before = '', $after = '') + { + } + /** + * Displays the edit bookmark link. + * + * @since 2.7.0 + * + * @param int|stdClass $link Optional. Bookmark ID. Default is the ID of the current bookmark. + * @return string|void The edit bookmark link URL. + */ + function get_edit_bookmark_link($link = 0) + { + } + /** + * Displays the edit bookmark link anchor content. + * + * @since 2.7.0 + * + * @param string $link Optional. Anchor text. If empty, default is 'Edit This'. Default empty. + * @param string $before Optional. Display before edit link. Default empty. + * @param string $after Optional. Display after edit link. Default empty. + * @param int $bookmark Optional. Bookmark ID. Default is the current bookmark. + */ + function edit_bookmark_link($link = '', $before = '', $after = '', $bookmark = \null) + { + } + /** + * Retrieves the edit user link. + * + * @since 3.5.0 + * + * @param int $user_id Optional. User ID. Defaults to the current user. + * @return string URL to edit user page or empty string. + */ + function get_edit_user_link($user_id = \null) + { + } + // + // Navigation links. + // + /** + * Retrieves the previous post that is adjacent to the current post. + * + * @since 1.5.0 + * + * @param bool $in_same_term Optional. Whether post should be in a same taxonomy term. Default false. + * @param int[]|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default empty. + * @param string $taxonomy Optional. Taxonomy, if $in_same_term is true. Default 'category'. + * @return WP_Post|null|string Post object if successful. Null if global $post is not set. Empty string if no + * corresponding post exists. + */ + function get_previous_post($in_same_term = \false, $excluded_terms = '', $taxonomy = 'category') + { + } + /** + * Retrieves the next post that is adjacent to the current post. + * + * @since 1.5.0 + * + * @param bool $in_same_term Optional. Whether post should be in a same taxonomy term. Default false. + * @param int[]|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default empty. + * @param string $taxonomy Optional. Taxonomy, if $in_same_term is true. Default 'category'. + * @return WP_Post|null|string Post object if successful. Null if global $post is not set. Empty string if no + * corresponding post exists. + */ + function get_next_post($in_same_term = \false, $excluded_terms = '', $taxonomy = 'category') + { + } + /** + * Retrieves the adjacent post. + * + * Can either be next or previous post. + * + * @since 2.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param bool $in_same_term Optional. Whether post should be in a same taxonomy term. Default false. + * @param int[]|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default empty string. + * @param bool $previous Optional. Whether to retrieve previous post. Default true + * @param string $taxonomy Optional. Taxonomy, if $in_same_term is true. Default 'category'. + * @return WP_Post|null|string Post object if successful. Null if global $post is not set. Empty string if no + * corresponding post exists. + */ + function get_adjacent_post($in_same_term = \false, $excluded_terms = '', $previous = \true, $taxonomy = 'category') + { + } + /** + * Retrieves the adjacent post relational link. + * + * Can either be next or previous post relational link. + * + * @since 2.8.0 + * + * @param string $title Optional. Link title format. Default '%title'. + * @param bool $in_same_term Optional. Whether link should be in a same taxonomy term. Default false. + * @param int[]|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default empty. + * @param bool $previous Optional. Whether to display link to previous or next post. Default true. + * @param string $taxonomy Optional. Taxonomy, if $in_same_term is true. Default 'category'. + * @return string|void The adjacent post relational link URL. + */ + function get_adjacent_post_rel_link($title = '%title', $in_same_term = \false, $excluded_terms = '', $previous = \true, $taxonomy = 'category') + { + } + /** + * Displays the relational links for the posts adjacent to the current post. + * + * @since 2.8.0 + * + * @param string $title Optional. Link title format. Default '%title'. + * @param bool $in_same_term Optional. Whether link should be in a same taxonomy term. Default false. + * @param int[]|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default empty. + * @param string $taxonomy Optional. Taxonomy, if $in_same_term is true. Default 'category'. + */ + function adjacent_posts_rel_link($title = '%title', $in_same_term = \false, $excluded_terms = '', $taxonomy = 'category') + { + } + /** + * Displays relational links for the posts adjacent to the current post for single post pages. + * + * This is meant to be attached to actions like 'wp_head'. Do not call this directly in plugins + * or theme templates. + * + * @since 3.0.0 + * @since 5.6.0 No longer used in core. + * + * @see adjacent_posts_rel_link() + */ + function adjacent_posts_rel_link_wp_head() + { + } + /** + * Displays the relational link for the next post adjacent to the current post. + * + * @since 2.8.0 + * + * @see get_adjacent_post_rel_link() + * + * @param string $title Optional. Link title format. Default '%title'. + * @param bool $in_same_term Optional. Whether link should be in a same taxonomy term. Default false. + * @param int[]|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default empty. + * @param string $taxonomy Optional. Taxonomy, if $in_same_term is true. Default 'category'. + */ + function next_post_rel_link($title = '%title', $in_same_term = \false, $excluded_terms = '', $taxonomy = 'category') + { + } + /** + * Displays the relational link for the previous post adjacent to the current post. + * + * @since 2.8.0 + * + * @see get_adjacent_post_rel_link() + * + * @param string $title Optional. Link title format. Default '%title'. + * @param bool $in_same_term Optional. Whether link should be in a same taxonomy term. Default false. + * @param int[]|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default true. + * @param string $taxonomy Optional. Taxonomy, if $in_same_term is true. Default 'category'. + */ + function prev_post_rel_link($title = '%title', $in_same_term = \false, $excluded_terms = '', $taxonomy = 'category') + { + } + /** + * Retrieves the boundary post. + * + * Boundary being either the first or last post by publish date within the constraints specified + * by $in_same_term or $excluded_terms. + * + * @since 2.8.0 + * + * @param bool $in_same_term Optional. Whether returned post should be in a same taxonomy term. + * Default false. + * @param int[]|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. + * Default empty. + * @param bool $start Optional. Whether to retrieve first or last post. Default true + * @param string $taxonomy Optional. Taxonomy, if $in_same_term is true. Default 'category'. + * @return null|array Array containing the boundary post object if successful, null otherwise. + */ + function get_boundary_post($in_same_term = \false, $excluded_terms = '', $start = \true, $taxonomy = 'category') + { + } + /** + * Retrieves the previous post link that is adjacent to the current post. + * + * @since 3.7.0 + * + * @param string $format Optional. Link anchor format. Default '« %link'. + * @param string $link Optional. Link permalink format. Default '%title'. + * @param bool $in_same_term Optional. Whether link should be in a same taxonomy term. Default false. + * @param int[]|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default empty. + * @param string $taxonomy Optional. Taxonomy, if $in_same_term is true. Default 'category'. + * @return string The link URL of the previous post in relation to the current post. + */ + function get_previous_post_link($format = '« %link', $link = '%title', $in_same_term = \false, $excluded_terms = '', $taxonomy = 'category') + { + } + /** + * Displays the previous post link that is adjacent to the current post. + * + * @since 1.5.0 + * + * @see get_previous_post_link() + * + * @param string $format Optional. Link anchor format. Default '« %link'. + * @param string $link Optional. Link permalink format. Default '%title'. + * @param bool $in_same_term Optional. Whether link should be in a same taxonomy term. Default false. + * @param int[]|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default empty. + * @param string $taxonomy Optional. Taxonomy, if $in_same_term is true. Default 'category'. + */ + function previous_post_link($format = '« %link', $link = '%title', $in_same_term = \false, $excluded_terms = '', $taxonomy = 'category') + { + } + /** + * Retrieves the next post link that is adjacent to the current post. + * + * @since 3.7.0 + * + * @param string $format Optional. Link anchor format. Default '« %link'. + * @param string $link Optional. Link permalink format. Default '%title'. + * @param bool $in_same_term Optional. Whether link should be in a same taxonomy term. Default false. + * @param int[]|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default empty. + * @param string $taxonomy Optional. Taxonomy, if $in_same_term is true. Default 'category'. + * @return string The link URL of the next post in relation to the current post. + */ + function get_next_post_link($format = '%link »', $link = '%title', $in_same_term = \false, $excluded_terms = '', $taxonomy = 'category') + { + } + /** + * Displays the next post link that is adjacent to the current post. + * + * @since 1.5.0 + * + * @see get_next_post_link() + * + * @param string $format Optional. Link anchor format. Default '« %link'. + * @param string $link Optional. Link permalink format. Default '%title' + * @param bool $in_same_term Optional. Whether link should be in a same taxonomy term. Default false. + * @param int[]|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default empty. + * @param string $taxonomy Optional. Taxonomy, if $in_same_term is true. Default 'category'. + */ + function next_post_link($format = '%link »', $link = '%title', $in_same_term = \false, $excluded_terms = '', $taxonomy = 'category') + { + } + /** + * Retrieves the adjacent post link. + * + * Can be either next post link or previous. + * + * @since 3.7.0 + * + * @param string $format Link anchor format. + * @param string $link Link permalink format. + * @param bool $in_same_term Optional. Whether link should be in a same taxonomy term. Default false. + * @param int[]|string $excluded_terms Optional. Array or comma-separated list of excluded terms IDs. Default empty. + * @param bool $previous Optional. Whether to display link to previous or next post. Default true. + * @param string $taxonomy Optional. Taxonomy, if $in_same_term is true. Default 'category'. + * @return string The link URL of the previous or next post in relation to the current post. + */ + function get_adjacent_post_link($format, $link, $in_same_term = \false, $excluded_terms = '', $previous = \true, $taxonomy = 'category') + { + } + /** + * Displays the adjacent post link. + * + * Can be either next post link or previous. + * + * @since 2.5.0 + * + * @param string $format Link anchor format. + * @param string $link Link permalink format. + * @param bool $in_same_term Optional. Whether link should be in a same taxonomy term. Default false. + * @param int[]|string $excluded_terms Optional. Array or comma-separated list of excluded category IDs. Default empty. + * @param bool $previous Optional. Whether to display link to previous or next post. Default true. + * @param string $taxonomy Optional. Taxonomy, if $in_same_term is true. Default 'category'. + */ + function adjacent_post_link($format, $link, $in_same_term = \false, $excluded_terms = '', $previous = \true, $taxonomy = 'category') + { + } + /** + * Retrieves the link for a page number. + * + * @since 1.5.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param int $pagenum Optional. Page number. Default 1. + * @param bool $escape Optional. Whether to escape the URL for display, with esc_url(). Defaults to true. + * Otherwise, prepares the URL with sanitize_url(). + * @return string The link URL for the given page number. + */ + function get_pagenum_link($pagenum = 1, $escape = \true) + { + } + /** + * Retrieves the next posts page link. + * + * Backported from 2.1.3 to 2.0.10. + * + * @since 2.0.10 + * + * @global int $paged + * + * @param int $max_page Optional. Max pages. Default 0. + * @return string|void The link URL for next posts page. + */ + function get_next_posts_page_link($max_page = 0) + { + } + /** + * Displays or retrieves the next posts page link. + * + * @since 0.71 + * + * @param int $max_page Optional. Max pages. Default 0. + * @param bool $echo Optional. Whether to echo the link. Default true. + * @return string|void The link URL for next posts page if `$echo = false`. + */ + function next_posts($max_page = 0, $echo = \true) + { + } + /** + * Retrieves the next posts page link. + * + * @since 2.7.0 + * + * @global int $paged + * @global WP_Query $wp_query WordPress Query object. + * + * @param string $label Content for link text. + * @param int $max_page Optional. Max pages. Default 0. + * @return string|void HTML-formatted next posts page link. + */ + function get_next_posts_link($label = \null, $max_page = 0) + { + } + /** + * Displays the next posts page link. + * + * @since 0.71 + * + * @param string $label Content for link text. + * @param int $max_page Optional. Max pages. Default 0. + */ + function next_posts_link($label = \null, $max_page = 0) + { + } + /** + * Retrieves the previous posts page link. + * + * Will only return string, if not on a single page or post. + * + * Backported to 2.0.10 from 2.1.3. + * + * @since 2.0.10 + * + * @global int $paged + * + * @return string|void The link for the previous posts page. + */ + function get_previous_posts_page_link() + { + } + /** + * Displays or retrieves the previous posts page link. + * + * @since 0.71 + * + * @param bool $echo Optional. Whether to echo the link. Default true. + * @return string|void The previous posts page link if `$echo = false`. + */ + function previous_posts($echo = \true) + { + } + /** + * Retrieves the previous posts page link. + * + * @since 2.7.0 + * + * @global int $paged + * + * @param string $label Optional. Previous page link text. + * @return string|void HTML-formatted previous page link. + */ + function get_previous_posts_link($label = \null) + { + } + /** + * Displays the previous posts page link. + * + * @since 0.71 + * + * @param string $label Optional. Previous page link text. + */ + function previous_posts_link($label = \null) + { + } + /** + * Retrieves the post pages link navigation for previous and next pages. + * + * @since 2.8.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param string|array $args { + * Optional. Arguments to build the post pages link navigation. + * + * @type string $sep Separator character. Default '—'. + * @type string $prelabel Link text to display for the previous page link. + * Default '« Previous Page'. + * @type string $nxtlabel Link text to display for the next page link. + * Default 'Next Page »'. + * } + * @return string The posts link navigation. + * @phpstan-param array{ + * sep?: string, + * prelabel?: string, + * nxtlabel?: string, + * } $args + */ + function get_posts_nav_link($args = array()) + { + } + /** + * Displays the post pages link navigation for previous and next pages. + * + * @since 0.71 + * + * @param string $sep Optional. Separator for posts navigation links. Default empty. + * @param string $prelabel Optional. Label for previous pages. Default empty. + * @param string $nxtlabel Optional Label for next pages. Default empty. + */ + function posts_nav_link($sep = '', $prelabel = '', $nxtlabel = '') + { + } + /** + * Retrieves the navigation to next/previous post, when applicable. + * + * @since 4.1.0 + * @since 4.4.0 Introduced the `in_same_term`, `excluded_terms`, and `taxonomy` arguments. + * @since 5.3.0 Added the `aria_label` parameter. + * @since 5.5.0 Added the `class` parameter. + * + * @param array $args { + * Optional. Default post navigation arguments. Default empty array. + * + * @type string $prev_text Anchor text to display in the previous post link. Default '%title'. + * @type string $next_text Anchor text to display in the next post link. Default '%title'. + * @type bool $in_same_term Whether link should be in a same taxonomy term. Default false. + * @type int[]|string $excluded_terms Array or comma-separated list of excluded term IDs. Default empty. + * @type string $taxonomy Taxonomy, if `$in_same_term` is true. Default 'category'. + * @type string $screen_reader_text Screen reader text for the nav element. Default 'Post navigation'. + * @type string $aria_label ARIA label text for the nav element. Default 'Posts'. + * @type string $class Custom class for the nav element. Default 'post-navigation'. + * } + * @return string Markup for post links. + * @phpstan-param array{ + * prev_text?: string, + * next_text?: string, + * in_same_term?: bool, + * excluded_terms?: int[]|string, + * taxonomy?: string, + * screen_reader_text?: string, + * aria_label?: string, + * class?: string, + * } $args + */ + function get_the_post_navigation($args = array()) + { + } + /** + * Displays the navigation to next/previous post, when applicable. + * + * @since 4.1.0 + * + * @param array $args Optional. See get_the_post_navigation() for available arguments. + * Default empty array. + * @phpstan-param array{ + * prev_text?: string, + * next_text?: string, + * in_same_term?: bool, + * excluded_terms?: int[]|string, + * taxonomy?: string, + * screen_reader_text?: string, + * aria_label?: string, + * class?: string, + * } $args See get_the_post_navigation() + */ + function the_post_navigation($args = array()) + { + } + /** + * Returns the navigation to next/previous set of posts, when applicable. + * + * @since 4.1.0 + * @since 5.3.0 Added the `aria_label` parameter. + * @since 5.5.0 Added the `class` parameter. + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param array $args { + * Optional. Default posts navigation arguments. Default empty array. + * + * @type string $prev_text Anchor text to display in the previous posts link. + * Default 'Older posts'. + * @type string $next_text Anchor text to display in the next posts link. + * Default 'Newer posts'. + * @type string $screen_reader_text Screen reader text for the nav element. + * Default 'Posts navigation'. + * @type string $aria_label ARIA label text for the nav element. Default 'Posts'. + * @type string $class Custom class for the nav element. Default 'posts-navigation'. + * } + * @return string Markup for posts links. + * @phpstan-param array{ + * prev_text?: string, + * next_text?: string, + * screen_reader_text?: string, + * aria_label?: string, + * class?: string, + * } $args + */ + function get_the_posts_navigation($args = array()) + { + } + /** + * Displays the navigation to next/previous set of posts, when applicable. + * + * @since 4.1.0 + * + * @param array $args Optional. See get_the_posts_navigation() for available arguments. + * Default empty array. + * @phpstan-param array{ + * prev_text?: string, + * next_text?: string, + * screen_reader_text?: string, + * aria_label?: string, + * class?: string, + * } $args See get_the_posts_navigation() + */ + function the_posts_navigation($args = array()) + { + } + /** + * Retrieves a paginated navigation to next/previous set of posts, when applicable. + * + * @since 4.1.0 + * @since 5.3.0 Added the `aria_label` parameter. + * @since 5.5.0 Added the `class` parameter. + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param array $args { + * Optional. Default pagination arguments, see paginate_links(). + * + * @type string $screen_reader_text Screen reader text for navigation element. + * Default 'Posts navigation'. + * @type string $aria_label ARIA label text for the nav element. Default 'Posts'. + * @type string $class Custom class for the nav element. Default 'pagination'. + * } + * @return string Markup for pagination links. + * @phpstan-param array{ + * screen_reader_text?: string, + * aria_label?: string, + * class?: string, + * base?: string, + * format?: string, + * total?: int, + * current?: int, + * aria_current?: string, + * show_all?: bool, + * end_size?: int, + * mid_size?: int, + * prev_next?: bool, + * prev_text?: string, + * next_text?: string, + * type?: string, + * add_args?: array, + * add_fragment?: string, + * before_page_number?: string, + * after_page_number?: string, + * } $args + */ + function get_the_posts_pagination($args = array()) + { + } + /** + * Displays a paginated navigation to next/previous set of posts, when applicable. + * + * @since 4.1.0 + * + * @param array $args Optional. See get_the_posts_pagination() for available arguments. + * Default empty array. + * @phpstan-param array{ + * screen_reader_text?: string, + * aria_label?: string, + * class?: string, + * base?: string, + * format?: string, + * total?: int, + * current?: int, + * aria_current?: string, + * show_all?: bool, + * end_size?: int, + * mid_size?: int, + * prev_next?: bool, + * prev_text?: string, + * next_text?: string, + * type?: string, + * add_args?: array, + * add_fragment?: string, + * before_page_number?: string, + * after_page_number?: string, + * } $args See get_the_posts_pagination() + */ + function the_posts_pagination($args = array()) + { + } + /** + * Wraps passed links in navigational markup. + * + * @since 4.1.0 + * @since 5.3.0 Added the `aria_label` parameter. + * @access private + * + * @param string $links Navigational links. + * @param string $class Optional. Custom class for the nav element. + * Default 'posts-navigation'. + * @param string $screen_reader_text Optional. Screen reader text for the nav element. + * Default 'Posts navigation'. + * @param string $aria_label Optional. ARIA label for the nav element. + * Defaults to the value of `$screen_reader_text`. + * @return string Navigation template tag. + */ + function _navigation_markup($links, $class = 'posts-navigation', $screen_reader_text = '', $aria_label = '') + { + } + /** + * Retrieves the comments page number link. + * + * @since 2.7.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param int $pagenum Optional. Page number. Default 1. + * @param int $max_page Optional. The maximum number of comment pages. Default 0. + * @return string The comments page number link URL. + */ + function get_comments_pagenum_link($pagenum = 1, $max_page = 0) + { + } + /** + * Retrieves the link to the next comments page. + * + * @since 2.7.1 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param string $label Optional. Label for link text. Default empty. + * @param int $max_page Optional. Max page. Default 0. + * @return string|void HTML-formatted link for the next page of comments. + */ + function get_next_comments_link($label = '', $max_page = 0) + { + } + /** + * Displays the link to the next comments page. + * + * @since 2.7.0 + * + * @param string $label Optional. Label for link text. Default empty. + * @param int $max_page Optional. Max page. Default 0. + */ + function next_comments_link($label = '', $max_page = 0) + { + } + /** + * Retrieves the link to the previous comments page. + * + * @since 2.7.1 + * + * @param string $label Optional. Label for comments link text. Default empty. + * @return string|void HTML-formatted link for the previous page of comments. + */ + function get_previous_comments_link($label = '') + { + } + /** + * Displays the link to the previous comments page. + * + * @since 2.7.0 + * + * @param string $label Optional. Label for comments link text. Default empty. + */ + function previous_comments_link($label = '') + { + } + /** + * Displays or retrieves pagination links for the comments on the current post. + * + * @see paginate_links() + * @since 2.7.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string|array $args Optional args. See paginate_links(). Default empty array. + * @return void|string|array Void if 'echo' argument is true and 'type' is not an array, + * or if the query is not for an existing single post of any post type. + * Otherwise, markup for comment page links or array of comment page links, + * depending on 'type' argument. + * @phpstan-param array{ + * base?: string, + * format?: string, + * total?: int, + * current?: int, + * aria_current?: string, + * show_all?: bool, + * end_size?: int, + * mid_size?: int, + * prev_next?: bool, + * prev_text?: string, + * next_text?: string, + * type?: string, + * add_args?: array, + * add_fragment?: string, + * before_page_number?: string, + * after_page_number?: string, + * } $args See paginate_links() + */ + function paginate_comments_links($args = array()) + { + } + /** + * Retrieves navigation to next/previous set of comments, when applicable. + * + * @since 4.4.0 + * @since 5.3.0 Added the `aria_label` parameter. + * @since 5.5.0 Added the `class` parameter. + * + * @param array $args { + * Optional. Default comments navigation arguments. + * + * @type string $prev_text Anchor text to display in the previous comments link. + * Default 'Older comments'. + * @type string $next_text Anchor text to display in the next comments link. + * Default 'Newer comments'. + * @type string $screen_reader_text Screen reader text for the nav element. Default 'Comments navigation'. + * @type string $aria_label ARIA label text for the nav element. Default 'Comments'. + * @type string $class Custom class for the nav element. Default 'comment-navigation'. + * } + * @return string Markup for comments links. + * @phpstan-param array{ + * prev_text?: string, + * next_text?: string, + * screen_reader_text?: string, + * aria_label?: string, + * class?: string, + * } $args + */ + function get_the_comments_navigation($args = array()) + { + } + /** + * Displays navigation to next/previous set of comments, when applicable. + * + * @since 4.4.0 + * + * @param array $args See get_the_comments_navigation() for available arguments. Default empty array. + * @phpstan-param array{ + * prev_text?: string, + * next_text?: string, + * screen_reader_text?: string, + * aria_label?: string, + * class?: string, + * } $args See get_the_comments_navigation() + */ + function the_comments_navigation($args = array()) + { + } + /** + * Retrieves a paginated navigation to next/previous set of comments, when applicable. + * + * @since 4.4.0 + * @since 5.3.0 Added the `aria_label` parameter. + * @since 5.5.0 Added the `class` parameter. + * + * @see paginate_comments_links() + * + * @param array $args { + * Optional. Default pagination arguments. + * + * @type string $screen_reader_text Screen reader text for the nav element. Default 'Comments navigation'. + * @type string $aria_label ARIA label text for the nav element. Default 'Comments'. + * @type string $class Custom class for the nav element. Default 'comments-pagination'. + * } + * @return string Markup for pagination links. + * @phpstan-param array{ + * screen_reader_text?: string, + * aria_label?: string, + * class?: string, + * } $args + */ + function get_the_comments_pagination($args = array()) + { + } + /** + * Displays a paginated navigation to next/previous set of comments, when applicable. + * + * @since 4.4.0 + * + * @param array $args See get_the_comments_pagination() for available arguments. Default empty array. + * @phpstan-param array{ + * screen_reader_text?: string, + * aria_label?: string, + * class?: string, + * } $args See get_the_comments_pagination() + */ + function the_comments_pagination($args = array()) + { + } + /** + * Retrieves the URL for the current site where the front end is accessible. + * + * Returns the 'home' option with the appropriate protocol. The protocol will be 'https' + * if is_ssl() evaluates to true; otherwise, it will be the same as the 'home' option. + * If `$scheme` is 'http' or 'https', is_ssl() is overridden. + * + * @since 3.0.0 + * + * @param string $path Optional. Path relative to the home URL. Default empty. + * @param string|null $scheme Optional. Scheme to give the home URL context. Accepts + * 'http', 'https', 'relative', 'rest', or null. Default null. + * @return string Home URL link with optional path appended. + */ + function home_url($path = '', $scheme = \null) + { + } + /** + * Retrieves the URL for a given site where the front end is accessible. + * + * Returns the 'home' option with the appropriate protocol. The protocol will be 'https' + * if is_ssl() evaluates to true; otherwise, it will be the same as the 'home' option. + * If `$scheme` is 'http' or 'https', is_ssl() is overridden. + * + * @since 3.0.0 + * + * @param int|null $blog_id Optional. Site ID. Default null (current site). + * @param string $path Optional. Path relative to the home URL. Default empty. + * @param string|null $scheme Optional. Scheme to give the home URL context. Accepts + * 'http', 'https', 'relative', 'rest', or null. Default null. + * @return string Home URL link with optional path appended. + */ + function get_home_url($blog_id = \null, $path = '', $scheme = \null) + { + } + /** + * Retrieves the URL for the current site where WordPress application files + * (e.g. wp-blog-header.php or the wp-admin/ folder) are accessible. + * + * Returns the 'site_url' option with the appropriate protocol, 'https' if + * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is + * overridden. + * + * @since 3.0.0 + * + * @param string $path Optional. Path relative to the site URL. Default empty. + * @param string|null $scheme Optional. Scheme to give the site URL context. See set_url_scheme(). + * @return string Site URL link with optional path appended. + */ + function site_url($path = '', $scheme = \null) + { + } + /** + * Retrieves the URL for a given site where WordPress application files + * (e.g. wp-blog-header.php or the wp-admin/ folder) are accessible. + * + * Returns the 'site_url' option with the appropriate protocol, 'https' if + * is_ssl() and 'http' otherwise. If `$scheme` is 'http' or 'https', + * `is_ssl()` is overridden. + * + * @since 3.0.0 + * + * @param int|null $blog_id Optional. Site ID. Default null (current site). + * @param string $path Optional. Path relative to the site URL. Default empty. + * @param string|null $scheme Optional. Scheme to give the site URL context. Accepts + * 'http', 'https', 'login', 'login_post', 'admin', or + * 'relative'. Default null. + * @return string Site URL link with optional path appended. + */ + function get_site_url($blog_id = \null, $path = '', $scheme = \null) + { + } + /** + * Retrieves the URL to the admin area for the current site. + * + * @since 2.6.0 + * + * @param string $path Optional. Path relative to the admin URL. Default empty. + * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). + * 'http' or 'https' can be passed to force those schemes. + * @return string Admin URL link with optional path appended. + */ + function admin_url($path = '', $scheme = 'admin') + { + } + /** + * Retrieves the URL to the admin area for a given site. + * + * @since 3.0.0 + * + * @param int|null $blog_id Optional. Site ID. Default null (current site). + * @param string $path Optional. Path relative to the admin URL. Default empty. + * @param string $scheme Optional. The scheme to use. Accepts 'http' or 'https', + * to force those schemes. Default 'admin', which obeys + * force_ssl_admin() and is_ssl(). + * @return string Admin URL link with optional path appended. + */ + function get_admin_url($blog_id = \null, $path = '', $scheme = 'admin') + { + } + /** + * Retrieves the URL to the includes directory. + * + * @since 2.6.0 + * + * @param string $path Optional. Path relative to the includes URL. Default empty. + * @param string|null $scheme Optional. Scheme to give the includes URL context. Accepts + * 'http', 'https', or 'relative'. Default null. + * @return string Includes URL link with optional path appended. + */ + function includes_url($path = '', $scheme = \null) + { + } + /** + * Retrieves the URL to the content directory. + * + * @since 2.6.0 + * + * @param string $path Optional. Path relative to the content URL. Default empty. + * @return string Content URL link with optional path appended. + */ + function content_url($path = '') + { + } + /** + * Retrieves a URL within the plugins or mu-plugins directory. + * + * Defaults to the plugins directory URL if no arguments are supplied. + * + * @since 2.6.0 + * + * @param string $path Optional. Extra path appended to the end of the URL, including + * the relative directory if $plugin is supplied. Default empty. + * @param string $plugin Optional. A full path to a file inside a plugin or mu-plugin. + * The URL will be relative to its directory. Default empty. + * Typically this is done by passing `__FILE__` as the argument. + * @return string Plugins URL link with optional paths appended. + */ + function plugins_url($path = '', $plugin = '') + { + } + /** + * Retrieves the site URL for the current network. + * + * Returns the site URL with the appropriate protocol, 'https' if + * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is + * overridden. + * + * @since 3.0.0 + * + * @see set_url_scheme() + * + * @param string $path Optional. Path relative to the site URL. Default empty. + * @param string|null $scheme Optional. Scheme to give the site URL context. Accepts + * 'http', 'https', or 'relative'. Default null. + * @return string Site URL link with optional path appended. + */ + function network_site_url($path = '', $scheme = \null) + { + } + /** + * Retrieves the home URL for the current network. + * + * Returns the home URL with the appropriate protocol, 'https' is_ssl() + * and 'http' otherwise. If `$scheme` is 'http' or 'https', `is_ssl()` is + * overridden. + * + * @since 3.0.0 + * + * @param string $path Optional. Path relative to the home URL. Default empty. + * @param string|null $scheme Optional. Scheme to give the home URL context. Accepts + * 'http', 'https', or 'relative'. Default null. + * @return string Home URL link with optional path appended. + */ + function network_home_url($path = '', $scheme = \null) + { + } + /** + * Retrieves the URL to the admin area for the network. + * + * @since 3.0.0 + * + * @param string $path Optional path relative to the admin URL. Default empty. + * @param string $scheme Optional. The scheme to use. Default is 'admin', which obeys force_ssl_admin() + * and is_ssl(). 'http' or 'https' can be passed to force those schemes. + * @return string Admin URL link with optional path appended. + */ + function network_admin_url($path = '', $scheme = 'admin') + { + } + /** + * Retrieves the URL to the admin area for the current user. + * + * @since 3.0.0 + * + * @param string $path Optional. Path relative to the admin URL. Default empty. + * @param string $scheme Optional. The scheme to use. Default is 'admin', which obeys force_ssl_admin() + * and is_ssl(). 'http' or 'https' can be passed to force those schemes. + * @return string Admin URL link with optional path appended. + */ + function user_admin_url($path = '', $scheme = 'admin') + { + } + /** + * Retrieves the URL to the admin area for either the current site or the network depending on context. + * + * @since 3.1.0 + * + * @param string $path Optional. Path relative to the admin URL. Default empty. + * @param string $scheme Optional. The scheme to use. Default is 'admin', which obeys force_ssl_admin() + * and is_ssl(). 'http' or 'https' can be passed to force those schemes. + * @return string Admin URL link with optional path appended. + */ + function self_admin_url($path = '', $scheme = 'admin') + { + } + /** + * Sets the scheme for a URL. + * + * @since 3.4.0 + * @since 4.4.0 The 'rest' scheme was added. + * + * @param string $url Absolute URL that includes a scheme + * @param string|null $scheme Optional. Scheme to give $url. Currently 'http', 'https', 'login', + * 'login_post', 'admin', 'relative', 'rest', 'rpc', or null. Default null. + * @return string URL with chosen scheme. + */ + function set_url_scheme($url, $scheme = \null) + { + } + /** + * Retrieves the URL to the user's dashboard. + * + * If a user does not belong to any site, the global user dashboard is used. If the user + * belongs to the current site, the dashboard for the current site is returned. If the user + * cannot edit the current site, the dashboard to the user's primary site is returned. + * + * @since 3.1.0 + * + * @param int $user_id Optional. User ID. Defaults to current user. + * @param string $path Optional path relative to the dashboard. Use only paths known to + * both site and user admins. Default empty. + * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() + * and is_ssl(). 'http' or 'https' can be passed to force those schemes. + * @return string Dashboard URL link with optional path appended. + */ + function get_dashboard_url($user_id = 0, $path = '', $scheme = 'admin') + { + } + /** + * Retrieves the URL to the user's profile editor. + * + * @since 3.1.0 + * + * @param int $user_id Optional. User ID. Defaults to current user. + * @param string $scheme Optional. The scheme to use. Default is 'admin', which obeys force_ssl_admin() + * and is_ssl(). 'http' or 'https' can be passed to force those schemes. + * @return string Dashboard URL link with optional path appended. + */ + function get_edit_profile_url($user_id = 0, $scheme = 'admin') + { + } + /** + * Returns the canonical URL for a post. + * + * When the post is the same as the current requested page the function will handle the + * pagination arguments too. + * + * @since 4.6.0 + * + * @param int|WP_Post $post Optional. Post ID or object. Default is global `$post`. + * @return string|false The canonical URL. False if the post does not exist + * or has not been published yet. + */ + function wp_get_canonical_url($post = \null) + { + } + /** + * Outputs rel=canonical for singular queries. + * + * @since 2.9.0 + * @since 4.6.0 Adjusted to use `wp_get_canonical_url()`. + */ + function rel_canonical() + { + } + /** + * Returns a shortlink for a post, page, attachment, or site. + * + * This function exists to provide a shortlink tag that all themes and plugins can target. + * A plugin must hook in to provide the actual shortlinks. Default shortlink support is + * limited to providing ?p= style links for posts. Plugins can short-circuit this function + * via the {@see 'pre_get_shortlink'} filter or filter the output via the {@see 'get_shortlink'} + * filter. + * + * @since 3.0.0 + * + * @param int $id Optional. A post or site ID. Default is 0, which means the current post or site. + * @param string $context Optional. Whether the ID is a 'site' ID, 'post' ID, or 'media' ID. If 'post', + * the post_type of the post is consulted. If 'query', the current query is consulted + * to determine the ID and context. Default 'post'. + * @param bool $allow_slugs Optional. Whether to allow post slugs in the shortlink. It is up to the plugin how + * and whether to honor this. Default true. + * @return string A shortlink or an empty string if no shortlink exists for the requested resource or if shortlinks + * are not enabled. + */ + function wp_get_shortlink($id = 0, $context = 'post', $allow_slugs = \true) + { + } + /** + * Injects rel=shortlink into the head if a shortlink is defined for the current page. + * + * Attached to the {@see 'wp_head'} action. + * + * @since 3.0.0 + */ + function wp_shortlink_wp_head() + { + } + /** + * Sends a Link: rel=shortlink header if a shortlink is defined for the current page. + * + * Attached to the {@see 'wp'} action. + * + * @since 3.0.0 + */ + function wp_shortlink_header() + { + } + /** + * Displays the shortlink for a post. + * + * Must be called from inside "The Loop" + * + * Call like the_shortlink( __( 'Shortlinkage FTW' ) ) + * + * @since 3.0.0 + * + * @param string $text Optional The link text or HTML to be displayed. Defaults to 'This is the short link.' + * @param string $title Optional The tooltip for the link. Must be sanitized. Defaults to the sanitized post title. + * @param string $before Optional HTML to display before the link. Default empty. + * @param string $after Optional HTML to display after the link. Default empty. + */ + function the_shortlink($text = '', $title = '', $before = '', $after = '') + { + } + /** + * Retrieves the avatar URL. + * + * @since 4.2.0 + * + * @param mixed $id_or_email The Gravatar to retrieve a URL for. Accepts a user_id, gravatar md5 hash, + * user email, WP_User object, WP_Post object, or WP_Comment object. + * @param array $args { + * Optional. Arguments to use instead of the default arguments. + * + * @type int $size Height and width of the avatar in pixels. Default 96. + * @type string $default URL for the default image or a default type. Accepts '404' (return + * a 404 instead of a default image), 'retro' (8bit), 'monsterid' (monster), + * 'wavatar' (cartoon face), 'indenticon' (the "quilt"), 'mystery', 'mm', + * or 'mysteryman' (The Oyster Man), 'blank' (transparent GIF), or + * 'gravatar_default' (the Gravatar logo). Default is the value of the + * 'avatar_default' option, with a fallback of 'mystery'. + * @type bool $force_default Whether to always show the default image, never the Gravatar. Default false. + * @type string $rating What rating to display avatars up to. Accepts 'G', 'PG', 'R', 'X', and are + * judged in that order. Default is the value of the 'avatar_rating' option. + * @type string $scheme URL scheme to use. See set_url_scheme() for accepted values. + * Default null. + * @type array $processed_args When the function returns, the value will be the processed/sanitized $args + * plus a "found_avatar" guess. Pass as a reference. Default null. + * } + * @return string|false The URL of the avatar on success, false on failure. + * @phpstan-param array{ + * size?: int, + * default?: string, + * force_default?: bool, + * rating?: string, + * scheme?: string, + * processed_args?: array, + * } $args + */ + function get_avatar_url($id_or_email, $args = \null) + { + } + /** + * Check if this comment type allows avatars to be retrieved. + * + * @since 5.1.0 + * + * @param string $comment_type Comment type to check. + * @return bool Whether the comment type is allowed for retrieving avatars. + */ + function is_avatar_comment_type($comment_type) + { + } + /** + * Retrieves default data about the avatar. + * + * @since 4.2.0 + * + * @param mixed $id_or_email The avatar to retrieve. Accepts a user ID, Gravatar MD5 hash, + * user email, WP_User object, WP_Post object, or WP_Comment object. + * @param array $args { + * Optional. Arguments to use instead of the default arguments. + * + * @type int $size Height and width of the avatar image file in pixels. Default 96. + * @type int $height Display height of the avatar in pixels. Defaults to $size. + * @type int $width Display width of the avatar in pixels. Defaults to $size. + * @type string $default URL for the default image or a default type. Accepts '404' (return + * a 404 instead of a default image), 'retro' (8bit), 'monsterid' (monster), + * 'wavatar' (cartoon face), 'indenticon' (the "quilt"), 'mystery', 'mm', + * or 'mysteryman' (The Oyster Man), 'blank' (transparent GIF), or + * 'gravatar_default' (the Gravatar logo). Default is the value of the + * 'avatar_default' option, with a fallback of 'mystery'. + * @type bool $force_default Whether to always show the default image, never the Gravatar. Default false. + * @type string $rating What rating to display avatars up to. Accepts 'G', 'PG', 'R', 'X', and are + * judged in that order. Default is the value of the 'avatar_rating' option. + * @type string $scheme URL scheme to use. See set_url_scheme() for accepted values. + * Default null. + * @type array $processed_args When the function returns, the value will be the processed/sanitized $args + * plus a "found_avatar" guess. Pass as a reference. Default null. + * @type string $extra_attr HTML attributes to insert in the IMG element. Is not sanitized. Default empty. + * } + * @return array { + * Along with the arguments passed in `$args`, this will contain a couple of extra arguments. + * + * @type bool $found_avatar True if an avatar was found for this user, + * false or not set if none was found. + * @type string|false $url The URL of the avatar that was found, or false. + * } + * @phpstan-param array{ + * size?: int, + * height?: int, + * width?: int, + * default?: string, + * force_default?: bool, + * rating?: string, + * scheme?: string, + * processed_args?: array, + * extra_attr?: string, + * } $args + * @phpstan-return array{ + * found_avatar: bool, + * url: string|false, + * } + */ + function get_avatar_data($id_or_email, $args = \null) + { + } + /** + * Retrieves the URL of a file in the theme. + * + * Searches in the stylesheet directory before the template directory so themes + * which inherit from a parent theme can just override one file. + * + * @since 4.7.0 + * + * @param string $file Optional. File to search for in the stylesheet directory. + * @return string The URL of the file. + */ + function get_theme_file_uri($file = '') + { + } + /** + * Retrieves the URL of a file in the parent theme. + * + * @since 4.7.0 + * + * @param string $file Optional. File to return the URL for in the template directory. + * @return string The URL of the file. + */ + function get_parent_theme_file_uri($file = '') + { + } + /** + * Retrieves the path of a file in the theme. + * + * Searches in the stylesheet directory before the template directory so themes + * which inherit from a parent theme can just override one file. + * + * @since 4.7.0 + * + * @param string $file Optional. File to search for in the stylesheet directory. + * @return string The path of the file. + */ + function get_theme_file_path($file = '') + { + } + /** + * Retrieves the path of a file in the parent theme. + * + * @since 4.7.0 + * + * @param string $file Optional. File to return the path for in the template directory. + * @return string The path of the file. + */ + function get_parent_theme_file_path($file = '') + { + } + /** + * Retrieves the URL to the privacy policy page. + * + * @since 4.9.6 + * + * @return string The URL to the privacy policy page. Empty string if it doesn't exist. + */ + function get_privacy_policy_url() + { + } + /** + * Displays the privacy policy link with formatting, when applicable. + * + * @since 4.9.6 + * + * @param string $before Optional. Display before privacy policy link. Default empty. + * @param string $after Optional. Display after privacy policy link. Default empty. + */ + function the_privacy_policy_link($before = '', $after = '') + { + } + /** + * Returns the privacy policy link with formatting, when applicable. + * + * @since 4.9.6 + * + * @param string $before Optional. Display before privacy policy link. Default empty. + * @param string $after Optional. Display after privacy policy link. Default empty. + * @return string Markup for the link and surrounding elements. Empty string if it + * doesn't exist. + */ + function get_the_privacy_policy_link($before = '', $after = '') + { + } + /** + * These functions are needed to load WordPress. + * + * @package WordPress + */ + /** + * Return the HTTP protocol sent by the server. + * + * @since 4.4.0 + * + * @return string The HTTP protocol. Default: HTTP/1.0. + */ + function wp_get_server_protocol() + { + } + /** + * Fix `$_SERVER` variables for various setups. + * + * @since 3.0.0 + * @access private + * + * @global string $PHP_SELF The filename of the currently executing script, + * relative to the document root. + */ + function wp_fix_server_vars() + { + } + /** + * Populates the Basic Auth server details from the Authorization header. + * + * Some servers running in CGI or FastCGI mode don't pass the Authorization + * header on to WordPress. If it's been rewritten to the `HTTP_AUTHORIZATION` header, + * fill in the proper $_SERVER variables instead. + * + * @since 5.6.0 + */ + function wp_populate_basic_auth_from_authorization_header() + { + } + /** + * Check for the required PHP version, and the MySQL extension or + * a database drop-in. + * + * Dies if requirements are not met. + * + * @since 3.0.0 + * @access private + * + * @global string $required_php_version The required PHP version string. + * @global string $wp_version The WordPress version string. + */ + function wp_check_php_mysql_versions() + { + } + /** + * Retrieves the current environment type. + * + * The type can be set via the `WP_ENVIRONMENT_TYPE` global system variable, + * or a constant of the same name. + * + * Possible values are 'local', 'development', 'staging', and 'production'. + * If not set, the type defaults to 'production'. + * + * @since 5.5.0 + * @since 5.5.1 Added the 'local' type. + * @since 5.5.1 Removed the ability to alter the list of types. + * + * @return string The current environment type. + */ + function wp_get_environment_type() + { + } + /** + * Don't load all of WordPress when handling a favicon.ico request. + * + * Instead, send the headers for a zero-length favicon and bail. + * + * @since 3.0.0 + * @deprecated 5.4.0 Deprecated in favor of do_favicon(). + */ + function wp_favicon_request() + { + } + /** + * Die with a maintenance message when conditions are met. + * + * The default message can be replaced by using a drop-in (maintenance.php in + * the wp-content directory). + * + * @since 3.0.0 + * @access private + */ + function wp_maintenance() + { + } + /** + * Check if maintenance mode is enabled. + * + * Checks for a file in the WordPress root directory named ".maintenance". + * This file will contain the variable $upgrading, set to the time the file + * was created. If the file was created less than 10 minutes ago, WordPress + * is in maintenance mode. + * + * @since 5.5.0 + * + * @global int $upgrading The Unix timestamp marking when upgrading WordPress began. + * + * @return bool True if maintenance mode is enabled, false otherwise. + */ + function wp_is_maintenance_mode() + { + } + /** + * Get the time elapsed so far during this PHP script. + * + * Uses REQUEST_TIME_FLOAT that appeared in PHP 5.4.0. + * + * @since 5.8.0 + * + * @return float Seconds since the PHP script started. + */ + function timer_float() + { + } + /** + * Start the WordPress micro-timer. + * + * @since 0.71 + * @access private + * + * @global float $timestart Unix timestamp set at the beginning of the page load. + * @see timer_stop() + * + * @return bool Always returns true. + */ + function timer_start() + { + } + /** + * Retrieve or display the time from the page start to when function is called. + * + * @since 0.71 + * + * @global float $timestart Seconds from when timer_start() is called. + * @global float $timeend Seconds from when function is called. + * + * @param int|bool $display Whether to echo or return the results. Accepts 0|false for return, + * 1|true for echo. Default 0|false. + * @param int $precision The number of digits from the right of the decimal to display. + * Default 3. + * @return string The "second.microsecond" finished time calculation. The number is formatted + * for human consumption, both localized and rounded. + */ + function timer_stop($display = 0, $precision = 3) + { + } + /** + * Set PHP error reporting based on WordPress debug settings. + * + * Uses three constants: `WP_DEBUG`, `WP_DEBUG_DISPLAY`, and `WP_DEBUG_LOG`. + * All three can be defined in wp-config.php. By default, `WP_DEBUG` and + * `WP_DEBUG_LOG` are set to false, and `WP_DEBUG_DISPLAY` is set to true. + * + * When `WP_DEBUG` is true, all PHP notices are reported. WordPress will also + * display internal notices: when a deprecated WordPress function, function + * argument, or file is used. Deprecated code may be removed from a later + * version. + * + * It is strongly recommended that plugin and theme developers use `WP_DEBUG` + * in their development environments. + * + * `WP_DEBUG_DISPLAY` and `WP_DEBUG_LOG` perform no function unless `WP_DEBUG` + * is true. + * + * When `WP_DEBUG_DISPLAY` is true, WordPress will force errors to be displayed. + * `WP_DEBUG_DISPLAY` defaults to true. Defining it as null prevents WordPress + * from changing the global configuration setting. Defining `WP_DEBUG_DISPLAY` + * as false will force errors to be hidden. + * + * When `WP_DEBUG_LOG` is true, errors will be logged to `wp-content/debug.log`. + * When `WP_DEBUG_LOG` is a valid path, errors will be logged to the specified file. + * + * Errors are never displayed for XML-RPC, REST, `ms-files.php`, and Ajax requests. + * + * @since 3.0.0 + * @since 5.1.0 `WP_DEBUG_LOG` can be a file path. + * @access private + */ + function wp_debug_mode() + { + } + /** + * Set the location of the language directory. + * + * To set directory manually, define the `WP_LANG_DIR` constant + * in wp-config.php. + * + * If the language directory exists within `WP_CONTENT_DIR`, it + * is used. Otherwise the language directory is assumed to live + * in `WPINC`. + * + * @since 3.0.0 + * @access private + */ + function wp_set_lang_dir() + { + } + /** + * Load the database class file and instantiate the `$wpdb` global. + * + * @since 2.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function require_wp_db() + { + } + /** + * Set the database table prefix and the format specifiers for database + * table columns. + * + * Columns not listed here default to `%s`. + * + * @since 3.0.0 + * @access private + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global string $table_prefix The database table prefix. + */ + function wp_set_wpdb_vars() + { + } + /** + * Toggle `$_wp_using_ext_object_cache` on and off without directly + * touching global. + * + * @since 3.7.0 + * + * @global bool $_wp_using_ext_object_cache + * + * @param bool $using Whether external object cache is being used. + * @return bool The current 'using' setting. + */ + function wp_using_ext_object_cache($using = \null) + { + } + /** + * Start the WordPress object cache. + * + * If an object-cache.php file exists in the wp-content directory, + * it uses that drop-in as an external object cache. + * + * @since 3.0.0 + * @access private + * + * @global array $wp_filter Stores all of the filters. + */ + function wp_start_object_cache() + { + } + /** + * Redirect to the installer if WordPress is not installed. + * + * Dies with an error message when Multisite is enabled. + * + * @since 3.0.0 + * @access private + */ + function wp_not_installed() + { + } + /** + * Retrieve an array of must-use plugin files. + * + * The default directory is wp-content/mu-plugins. To change the default + * directory manually, define `WPMU_PLUGIN_DIR` and `WPMU_PLUGIN_URL` + * in wp-config.php. + * + * @since 3.0.0 + * @access private + * + * @return string[] Array of absolute paths of files to include. + */ + function wp_get_mu_plugins() + { + } + /** + * Retrieve an array of active and valid plugin files. + * + * While upgrading or installing WordPress, no plugins are returned. + * + * The default directory is `wp-content/plugins`. To change the default + * directory manually, define `WP_PLUGIN_DIR` and `WP_PLUGIN_URL` + * in `wp-config.php`. + * + * @since 3.0.0 + * @access private + * + * @return string[] Array of paths to plugin files relative to the plugins directory. + */ + function wp_get_active_and_valid_plugins() + { + } + /** + * Filters a given list of plugins, removing any paused plugins from it. + * + * @since 5.2.0 + * + * @param string[] $plugins Array of absolute plugin main file paths. + * @return string[] Filtered array of plugins, without any paused plugins. + */ + function wp_skip_paused_plugins(array $plugins) + { + } + /** + * Retrieves an array of active and valid themes. + * + * While upgrading or installing WordPress, no themes are returned. + * + * @since 5.1.0 + * @access private + * + * @global string $pagenow The filename of the current screen. + * + * @return string[] Array of absolute paths to theme directories. + */ + function wp_get_active_and_valid_themes() + { + } + /** + * Filters a given list of themes, removing any paused themes from it. + * + * @since 5.2.0 + * + * @param string[] $themes Array of absolute theme directory paths. + * @return string[] Filtered array of absolute paths to themes, without any paused themes. + */ + function wp_skip_paused_themes(array $themes) + { + } + /** + * Is WordPress in Recovery Mode. + * + * In this mode, plugins or themes that cause WSODs will be paused. + * + * @since 5.2.0 + * + * @return bool + */ + function wp_is_recovery_mode() + { + } + /** + * Determines whether we are currently on an endpoint that should be protected against WSODs. + * + * @since 5.2.0 + * + * @global string $pagenow The filename of the current screen. + * + * @return bool True if the current endpoint should be protected. + */ + function is_protected_endpoint() + { + } + /** + * Determines whether we are currently handling an Ajax action that should be protected against WSODs. + * + * @since 5.2.0 + * + * @return bool True if the current Ajax action should be protected. + */ + function is_protected_ajax_action() + { + } + /** + * Set internal encoding. + * + * In most cases the default internal encoding is latin1, which is + * of no use, since we want to use the `mb_` functions for `utf-8` strings. + * + * @since 3.0.0 + * @access private + */ + function wp_set_internal_encoding() + { + } + /** + * Add magic quotes to `$_GET`, `$_POST`, `$_COOKIE`, and `$_SERVER`. + * + * Also forces `$_REQUEST` to be `$_GET + $_POST`. If `$_SERVER`, + * `$_COOKIE`, or `$_ENV` are needed, use those superglobals directly. + * + * @since 3.0.0 + * @access private + */ + function wp_magic_quotes() + { + } + /** + * Runs just before PHP shuts down execution. + * + * @since 1.2.0 + * @access private + */ + function shutdown_action_hook() + { + } + /** + * Copy an object. + * + * @since 2.7.0 + * @deprecated 3.2.0 + * + * @param object $object The object to clone. + * @return object The cloned object. + */ + function wp_clone($object) + { + } + /** + * Determines whether the current request is for the login screen. + * + * @since 6.1.0 + * + * @see wp_login_url() + * + * @return bool True if inside WordPress login screen, false otherwise. + */ + function is_login() + { + } + /** + * Determines whether the current request is for an administrative interface page. + * + * Does not check if the user is an administrator; use current_user_can() + * for checking roles and capabilities. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.1 + * + * @global WP_Screen $current_screen WordPress current screen object. + * + * @return bool True if inside WordPress administration interface, false otherwise. + */ + function is_admin() + { + } + /** + * Determines whether the current request is for a site's administrative interface. + * + * e.g. `/wp-admin/` + * + * Does not check if the user is an administrator; use current_user_can() + * for checking roles and capabilities. + * + * @since 3.1.0 + * + * @global WP_Screen $current_screen WordPress current screen object. + * + * @return bool True if inside WordPress site administration pages. + */ + function is_blog_admin() + { + } + /** + * Determines whether the current request is for the network administrative interface. + * + * e.g. `/wp-admin/network/` + * + * Does not check if the user is an administrator; use current_user_can() + * for checking roles and capabilities. + * + * Does not check if the site is a Multisite network; use is_multisite() + * for checking if Multisite is enabled. + * + * @since 3.1.0 + * + * @global WP_Screen $current_screen WordPress current screen object. + * + * @return bool True if inside WordPress network administration pages. + */ + function is_network_admin() + { + } + /** + * Determines whether the current request is for a user admin screen. + * + * e.g. `/wp-admin/user/` + * + * Does not check if the user is an administrator; use current_user_can() + * for checking roles and capabilities. + * + * @since 3.1.0 + * + * @global WP_Screen $current_screen WordPress current screen object. + * + * @return bool True if inside WordPress user administration pages. + */ + function is_user_admin() + { + } + /** + * If Multisite is enabled. + * + * @since 3.0.0 + * + * @return bool True if Multisite is enabled, false otherwise. + */ + function is_multisite() + { + } + /** + * Retrieve the current site ID. + * + * @since 3.1.0 + * + * @global int $blog_id + * + * @return int Site ID. + */ + function get_current_blog_id() + { + } + /** + * Retrieves the current network ID. + * + * @since 4.6.0 + * + * @return int The ID of the current network. + */ + function get_current_network_id() + { + } + /** + * Attempt an early load of translations. + * + * Used for errors encountered during the initial loading process, before + * the locale has been properly detected and loaded. + * + * Designed for unusual load sequences (like setup-config.php) or for when + * the script will then terminate with an error, otherwise there is a risk + * that a file can be double-included. + * + * @since 3.4.0 + * @access private + * + * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry. + * @global WP_Locale $wp_locale WordPress date and time locale object. + */ + function wp_load_translations_early() + { + } + /** + * Check or set whether WordPress is in "installation" mode. + * + * If the `WP_INSTALLING` constant is defined during the bootstrap, `wp_installing()` will default to `true`. + * + * @since 4.4.0 + * + * @param bool $is_installing Optional. True to set WP into Installing mode, false to turn Installing mode off. + * Omit this parameter if you only want to fetch the current status. + * @return bool True if WP is installing, otherwise false. When a `$is_installing` is passed, the function will + * report whether WP was in installing mode prior to the change to `$is_installing`. + */ + function wp_installing($is_installing = \null) + { + } + /** + * Determines if SSL is used. + * + * @since 2.6.0 + * @since 4.6.0 Moved from functions.php to load.php. + * + * @return bool True if SSL, otherwise false. + */ + function is_ssl() + { + } + /** + * Converts a shorthand byte value to an integer byte value. + * + * @since 2.3.0 + * @since 4.6.0 Moved from media.php to load.php. + * + * @link https://www.php.net/manual/en/function.ini-get.php + * @link https://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes + * + * @param string $value A (PHP ini) byte value, either shorthand or ordinary. + * @return int An integer byte value. + */ + function wp_convert_hr_to_bytes($value) + { + } + /** + * Determines whether a PHP ini value is changeable at runtime. + * + * @since 4.6.0 + * + * @link https://www.php.net/manual/en/function.ini-get-all.php + * + * @param string $setting The name of the ini setting to check. + * @return bool True if the value is changeable at runtime. False otherwise. + */ + function wp_is_ini_value_changeable($setting) + { + } + /** + * Determines whether the current request is a WordPress Ajax request. + * + * @since 4.7.0 + * + * @return bool True if it's a WordPress Ajax request, false otherwise. + */ + function wp_doing_ajax() + { + } + /** + * Determines whether the current request should use themes. + * + * @since 5.1.0 + * + * @return bool True if themes should be used, false otherwise. + */ + function wp_using_themes() + { + } + /** + * Determines whether the current request is a WordPress cron request. + * + * @since 4.8.0 + * + * @return bool True if it's a WordPress cron request, false otherwise. + */ + function wp_doing_cron() + { + } + /** + * Checks whether the given variable is a WordPress Error. + * + * Returns whether `$thing` is an instance of the `WP_Error` class. + * + * @since 2.1.0 + * + * @param mixed $thing The variable to check. + * @return bool Whether the variable is an instance of WP_Error. + */ + function is_wp_error($thing) + { + } + /** + * Determines whether file modifications are allowed. + * + * @since 4.8.0 + * + * @param string $context The usage context. + * @return bool True if file modification is allowed, false otherwise. + */ + function wp_is_file_mod_allowed($context) + { + } + /** + * Start scraping edited file errors. + * + * @since 4.9.0 + */ + function wp_start_scraping_edited_file_errors() + { + } + /** + * Finalize scraping for edited file errors. + * + * @since 4.9.0 + * + * @param string $scrape_key Scrape key. + */ + function wp_finalize_scraping_edited_file_errors($scrape_key) + { + } + /** + * Checks whether current request is a JSON request, or is expecting a JSON response. + * + * @since 5.0.0 + * + * @return bool True if `Accepts` or `Content-Type` headers contain `application/json`. + * False otherwise. + */ + function wp_is_json_request() + { + } + /** + * Checks whether current request is a JSONP request, or is expecting a JSONP response. + * + * @since 5.2.0 + * + * @return bool True if JSONP request, false otherwise. + */ + function wp_is_jsonp_request() + { + } + /** + * Checks whether a string is a valid JSON Media Type. + * + * @since 5.6.0 + * + * @param string $media_type A Media Type string to check. + * @return bool True if string is a valid JSON Media Type. + */ + function wp_is_json_media_type($media_type) + { + } + /** + * Checks whether current request is an XML request, or is expecting an XML response. + * + * @since 5.2.0 + * + * @return bool True if `Accepts` or `Content-Type` headers contain `text/xml` + * or one of the related MIME types. False otherwise. + */ + function wp_is_xml_request() + { + } + /** + * Checks if this site is protected by HTTP Basic Auth. + * + * At the moment, this merely checks for the present of Basic Auth credentials. Therefore, calling + * this function with a context different from the current context may give inaccurate results. + * In a future release, this evaluation may be made more robust. + * + * Currently, this is only used by Application Passwords to prevent a conflict since it also utilizes + * Basic Auth. + * + * @since 5.6.1 + * + * @global string $pagenow The filename of the current screen. + * + * @param string $context The context to check for protection. Accepts 'login', 'admin', and 'front'. + * Defaults to the current context. + * @return bool Whether the site is protected by Basic Auth. + */ + function wp_is_site_protected_by_basic_auth($context = '') + { + } + /** + * WordPress media templates. + * + * @package WordPress + * @subpackage Media + * @since 3.5.0 + */ + /** + * Outputs the markup for a audio tag to be used in an Underscore template + * when data.model is passed. + * + * @since 3.9.0 + */ + function wp_underscore_audio_template() + { + } + /** + * Outputs the markup for a video tag to be used in an Underscore template + * when data.model is passed. + * + * @since 3.9.0 + */ + function wp_underscore_video_template() + { + } + /** + * Prints the templates used in the media manager. + * + * @since 3.5.0 + */ + function wp_print_media_templates() + { + } + /** + * WordPress API for media display. + * + * @package WordPress + * @subpackage Media + */ + /** + * Retrieves additional image sizes. + * + * @since 4.7.0 + * + * @global array $_wp_additional_image_sizes + * + * @return array Additional images size data. + */ + function wp_get_additional_image_sizes() + { + } + /** + * Scales down the default size of an image. + * + * This is so that the image is a better fit for the editor and theme. + * + * The `$size` parameter accepts either an array or a string. The supported string + * values are 'thumb' or 'thumbnail' for the given thumbnail size or defaults at + * 128 width and 96 height in pixels. Also supported for the string value is + * 'medium', 'medium_large' and 'full'. The 'full' isn't actually supported, but any value other + * than the supported will result in the content_width size or 500 if that is + * not set. + * + * Finally, there is a filter named {@see 'editor_max_image_size'}, that will be + * called on the calculated array for width and height, respectively. + * + * @since 2.5.0 + * + * @global int $content_width + * + * @param int $width Width of the image in pixels. + * @param int $height Height of the image in pixels. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array + * of width and height values in pixels (in that order). Default 'medium'. + * @param string $context Optional. Could be 'display' (like in a theme) or 'edit' + * (like inserting into an editor). Default null. + * @return int[] { + * An array of width and height values. + * + * @type int $0 The maximum width in pixels. + * @type int $1 The maximum height in pixels. + * } + * @phpstan-return array{ + * 0: int, + * 1: int, + * } + */ + function image_constrain_size_for_editor($width, $height, $size = 'medium', $context = \null) + { + } + /** + * Retrieves width and height attributes using given width and height values. + * + * Both attributes are required in the sense that both parameters must have a + * value, but are optional in that if you set them to false or null, then they + * will not be added to the returned string. + * + * You can set the value using a string, but it will only take numeric values. + * If you wish to put 'px' after the numbers, then it will be stripped out of + * the return. + * + * @since 2.5.0 + * + * @param int|string $width Image width in pixels. + * @param int|string $height Image height in pixels. + * @return string HTML attributes for width and, or height. + */ + function image_hwstring($width, $height) + { + } + /** + * Scales an image to fit a particular size (such as 'thumb' or 'medium'). + * + * The URL might be the original image, or it might be a resized version. This + * function won't create a new resized copy, it will just return an already + * resized one if it exists. + * + * A plugin may use the {@see 'image_downsize'} filter to hook into and offer image + * resizing services for images. The hook must return an array with the same + * elements that are normally returned from the function. + * + * @since 2.5.0 + * + * @param int $id Attachment ID for image. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array + * of width and height values in pixels (in that order). Default 'medium'. + * @return array|false { + * Array of image data, or boolean false if no image is available. + * + * @type string $0 Image source URL. + * @type int $1 Image width in pixels. + * @type int $2 Image height in pixels. + * @type bool $3 Whether the image is a resized image. + * } + * @phpstan-return false|array{ + * 0: string, + * 1: int, + * 2: int, + * 3: bool, + * } + */ + function image_downsize($id, $size = 'medium') + { + } + /** + * Registers a new image size. + * + * @since 2.9.0 + * + * @global array $_wp_additional_image_sizes Associative array of additional image sizes. + * + * @param string $name Image size identifier. + * @param int $width Optional. Image width in pixels. Default 0. + * @param int $height Optional. Image height in pixels. Default 0. + * @param bool|array $crop Optional. Image cropping behavior. If false, the image will be scaled (default), + * If true, image will be cropped to the specified dimensions using center positions. + * If an array, the image will be cropped using the array to specify the crop location. + * Array values must be in the format: array( x_crop_position, y_crop_position ) where: + * - x_crop_position accepts: 'left', 'center', or 'right'. + * - y_crop_position accepts: 'top', 'center', or 'bottom'. + */ + function add_image_size($name, $width = 0, $height = 0, $crop = \false) + { + } + /** + * Checks if an image size exists. + * + * @since 3.9.0 + * + * @param string $name The image size to check. + * @return bool True if the image size exists, false if not. + */ + function has_image_size($name) + { + } + /** + * Removes a new image size. + * + * @since 3.9.0 + * + * @global array $_wp_additional_image_sizes + * + * @param string $name The image size to remove. + * @return bool True if the image size was successfully removed, false on failure. + */ + function remove_image_size($name) + { + } + /** + * Registers an image size for the post thumbnail. + * + * @since 2.9.0 + * + * @see add_image_size() for details on cropping behavior. + * + * @param int $width Image width in pixels. + * @param int $height Image height in pixels. + * @param bool|array $crop Optional. Whether to crop images to specified width and height or resize. + * An array can specify positioning of the crop area. Default false. + */ + function set_post_thumbnail_size($width = 0, $height = 0, $crop = \false) + { + } + /** + * Gets an img tag for an image attachment, scaling it down if requested. + * + * The {@see 'get_image_tag_class'} filter allows for changing the class name for the + * image without having to use regular expressions on the HTML content. The + * parameters are: what WordPress will use for the class, the Attachment ID, + * image align value, and the size the image should be. + * + * The second filter, {@see 'get_image_tag'}, has the HTML content, which can then be + * further manipulated by a plugin to change all attribute values and even HTML + * content. + * + * @since 2.5.0 + * + * @param int $id Attachment ID. + * @param string $alt Image description for the alt attribute. + * @param string $title Image description for the title attribute. + * @param string $align Part of the class name for aligning the image. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array of + * width and height values in pixels (in that order). Default 'medium'. + * @return string HTML IMG element for given image attachment? + */ + function get_image_tag($id, $alt, $title, $align, $size = 'medium') + { + } + /** + * Calculates the new dimensions for a down-sampled image. + * + * If either width or height are empty, no constraint is applied on + * that dimension. + * + * @since 2.5.0 + * + * @param int $current_width Current width of the image. + * @param int $current_height Current height of the image. + * @param int $max_width Optional. Max width in pixels to constrain to. Default 0. + * @param int $max_height Optional. Max height in pixels to constrain to. Default 0. + * @return int[] { + * An array of width and height values. + * + * @type int $0 The width in pixels. + * @type int $1 The height in pixels. + * } + * @phpstan-return array{ + * 0: int, + * 1: int, + * } + */ + function wp_constrain_dimensions($current_width, $current_height, $max_width = 0, $max_height = 0) + { + } + /** + * Retrieves calculated resize dimensions for use in WP_Image_Editor. + * + * Calculates dimensions and coordinates for a resized image that fits + * within a specified width and height. + * + * Cropping behavior is dependent on the value of $crop: + * 1. If false (default), images will not be cropped. + * 2. If an array in the form of array( x_crop_position, y_crop_position ): + * - x_crop_position accepts 'left' 'center', or 'right'. + * - y_crop_position accepts 'top', 'center', or 'bottom'. + * Images will be cropped to the specified dimensions within the defined crop area. + * 3. If true, images will be cropped to the specified dimensions using center positions. + * + * @since 2.5.0 + * + * @param int $orig_w Original width in pixels. + * @param int $orig_h Original height in pixels. + * @param int $dest_w New width in pixels. + * @param int $dest_h New height in pixels. + * @param bool|array $crop Optional. Whether to crop image to specified width and height or resize. + * An array can specify positioning of the crop area. Default false. + * @return array|false Returned array matches parameters for `imagecopyresampled()`. False on failure. + */ + function image_resize_dimensions($orig_w, $orig_h, $dest_w, $dest_h, $crop = \false) + { + } + /** + * Resizes an image to make a thumbnail or intermediate size. + * + * The returned array has the file size, the image width, and image height. The + * {@see 'image_make_intermediate_size'} filter can be used to hook in and change the + * values of the returned array. The only parameter is the resized file path. + * + * @since 2.5.0 + * + * @param string $file File path. + * @param int $width Image width. + * @param int $height Image height. + * @param bool $crop Optional. Whether to crop image to specified width and height or resize. + * Default false. + * @return array|false Metadata array on success. False if no image was created. + */ + function image_make_intermediate_size($file, $width, $height, $crop = \false) + { + } + /** + * Helper function to test if aspect ratios for two images match. + * + * @since 4.6.0 + * + * @param int $source_width Width of the first image in pixels. + * @param int $source_height Height of the first image in pixels. + * @param int $target_width Width of the second image in pixels. + * @param int $target_height Height of the second image in pixels. + * @return bool True if aspect ratios match within 1px. False if not. + */ + function wp_image_matches_ratio($source_width, $source_height, $target_width, $target_height) + { + } + /** + * Retrieves the image's intermediate size (resized) path, width, and height. + * + * The $size parameter can be an array with the width and height respectively. + * If the size matches the 'sizes' metadata array for width and height, then it + * will be used. If there is no direct match, then the nearest image size larger + * than the specified size will be used. If nothing is found, then the function + * will break out and return false. + * + * The metadata 'sizes' is used for compatible sizes that can be used for the + * parameter $size value. + * + * The url path will be given, when the $size parameter is a string. + * + * If you are passing an array for the $size, you should consider using + * add_image_size() so that a cropped version is generated. It's much more + * efficient than having to find the closest-sized image and then having the + * browser scale down the image. + * + * @since 2.5.0 + * + * @param int $post_id Attachment ID. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array + * of width and height values in pixels (in that order). Default 'thumbnail'. + * @return array|false { + * Array of file relative path, width, and height on success. Additionally includes absolute + * path and URL if registered size is passed to `$size` parameter. False on failure. + * + * @type string $file Path of image relative to uploads directory. + * @type int $width Width of image in pixels. + * @type int $height Height of image in pixels. + * @type string $path Absolute filesystem path of image. + * @type string $url URL of image. + * } + * @phpstan-return false|array{ + * file: string, + * width: int, + * height: int, + * path: string, + * url: string, + * } + */ + function image_get_intermediate_size($post_id, $size = 'thumbnail') + { + } + /** + * Gets the available intermediate image size names. + * + * @since 3.0.0 + * + * @return string[] An array of image size names. + */ + function get_intermediate_image_sizes() + { + } + /** + * Returns a normalized list of all currently registered image sub-sizes. + * + * @since 5.3.0 + * @uses wp_get_additional_image_sizes() + * @uses get_intermediate_image_sizes() + * + * @return array[] Associative array of arrays of image sub-size information, + * keyed by image size name. + */ + function wp_get_registered_image_subsizes() + { + } + /** + * Retrieves an image to represent an attachment. + * + * @since 2.5.0 + * + * @param int $attachment_id Image attachment ID. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array of + * width and height values in pixels (in that order). Default 'thumbnail'. + * @param bool $icon Optional. Whether the image should fall back to a mime type icon. Default false. + * @return array|false { + * Array of image data, or boolean false if no image is available. + * + * @type string $0 Image source URL. + * @type int $1 Image width in pixels. + * @type int $2 Image height in pixels. + * @type bool $3 Whether the image is a resized image. + * } + * @phpstan-return false|array{ + * 0: string, + * 1: int, + * 2: int, + * 3: bool, + * } + */ + function wp_get_attachment_image_src($attachment_id, $size = 'thumbnail', $icon = \false) + { + } + /** + * Gets an HTML img element representing an image attachment. + * + * While `$size` will accept an array, it is better to register a size with + * add_image_size() so that a cropped version is generated. It's much more + * efficient than having to find the closest-sized image and then having the + * browser scale down the image. + * + * @since 2.5.0 + * @since 4.4.0 The `$srcset` and `$sizes` attributes were added. + * @since 5.5.0 The `$loading` attribute was added. + * @since 6.1.0 The `$decoding` attribute was added. + * + * @param int $attachment_id Image attachment ID. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array + * of width and height values in pixels (in that order). Default 'thumbnail'. + * @param bool $icon Optional. Whether the image should be treated as an icon. Default false. + * @param string|array $attr { + * Optional. Attributes for the image markup. + * + * @type string $src Image attachment URL. + * @type string $class CSS class name or space-separated list of classes. + * Default `attachment-$size_class size-$size_class`, + * where `$size_class` is the image size being requested. + * @type string $alt Image description for the alt attribute. + * @type string $srcset The 'srcset' attribute value. + * @type string $sizes The 'sizes' attribute value. + * @type string|false $loading The 'loading' attribute value. Passing a value of false + * will result in the attribute being omitted for the image. + * Defaults to 'lazy', depending on wp_lazy_loading_enabled(). + * @type string $decoding The 'decoding' attribute value. Possible values are + * 'async' (default), 'sync', or 'auto'. + * } + * @return string HTML img element or empty string on failure. + * @phpstan-param array{ + * src?: string, + * class?: string, + * alt?: string, + * srcset?: string, + * sizes?: string, + * loading?: string|false, + * decoding?: string, + * } $attr + */ + function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = \false, $attr = '') + { + } + /** + * Gets the URL of an image attachment. + * + * @since 4.4.0 + * + * @param int $attachment_id Image attachment ID. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array of + * width and height values in pixels (in that order). Default 'thumbnail'. + * @param bool $icon Optional. Whether the image should be treated as an icon. Default false. + * @return string|false Attachment URL or false if no image is available. If `$size` does not match + * any registered image size, the original image URL will be returned. + */ + function wp_get_attachment_image_url($attachment_id, $size = 'thumbnail', $icon = \false) + { + } + /** + * Gets the attachment path relative to the upload directory. + * + * @since 4.4.1 + * @access private + * + * @param string $file Attachment file name. + * @return string Attachment path relative to the upload directory. + */ + function _wp_get_attachment_relative_path($file) + { + } + /** + * Gets the image size as array from its meta data. + * + * Used for responsive images. + * + * @since 4.4.0 + * @access private + * + * @param string $size_name Image size. Accepts any registered image size name. + * @param array $image_meta The image meta data. + * @return array|false { + * Array of width and height or false if the size isn't present in the meta data. + * + * @type int $0 Image width. + * @type int $1 Image height. + * } + * @phpstan-return false|array{ + * 0: int, + * 1: int, + * } + */ + function _wp_get_image_size_from_meta($size_name, $image_meta) + { + } + /** + * Retrieves the value for an image attachment's 'srcset' attribute. + * + * @since 4.4.0 + * + * @see wp_calculate_image_srcset() + * + * @param int $attachment_id Image attachment ID. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array of + * width and height values in pixels (in that order). Default 'medium'. + * @param array $image_meta Optional. The image meta data as returned by 'wp_get_attachment_metadata()'. + * Default null. + * @return string|false A 'srcset' value string or false. + */ + function wp_get_attachment_image_srcset($attachment_id, $size = 'medium', $image_meta = \null) + { + } + /** + * A helper function to calculate the image sources to include in a 'srcset' attribute. + * + * @since 4.4.0 + * + * @param int[] $size_array { + * An array of width and height values. + * + * @type int $0 The width in pixels. + * @type int $1 The height in pixels. + * } + * @param string $image_src The 'src' of the image. + * @param array $image_meta The image meta data as returned by 'wp_get_attachment_metadata()'. + * @param int $attachment_id Optional. The image attachment ID. Default 0. + * @return string|false The 'srcset' attribute value. False on error or when only one source exists. + * @phpstan-param array{ + * 0: int, + * 1: int, + * } $size_array + */ + function wp_calculate_image_srcset($size_array, $image_src, $image_meta, $attachment_id = 0) + { + } + /** + * Retrieves the value for an image attachment's 'sizes' attribute. + * + * @since 4.4.0 + * + * @see wp_calculate_image_sizes() + * + * @param int $attachment_id Image attachment ID. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array of + * width and height values in pixels (in that order). Default 'medium'. + * @param array $image_meta Optional. The image meta data as returned by 'wp_get_attachment_metadata()'. + * Default null. + * @return string|false A valid source size value for use in a 'sizes' attribute or false. + */ + function wp_get_attachment_image_sizes($attachment_id, $size = 'medium', $image_meta = \null) + { + } + /** + * Creates a 'sizes' attribute value for an image. + * + * @since 4.4.0 + * + * @param string|int[] $size Image size. Accepts any registered image size name, or an array of + * width and height values in pixels (in that order). + * @param string $image_src Optional. The URL to the image file. Default null. + * @param array $image_meta Optional. The image meta data as returned by 'wp_get_attachment_metadata()'. + * Default null. + * @param int $attachment_id Optional. Image attachment ID. Either `$image_meta` or `$attachment_id` + * is needed when using the image size name as argument for `$size`. Default 0. + * @return string|false A valid source size value for use in a 'sizes' attribute or false. + */ + function wp_calculate_image_sizes($size, $image_src = \null, $image_meta = \null, $attachment_id = 0) + { + } + /** + * Determines if the image meta data is for the image source file. + * + * The image meta data is retrieved by attachment post ID. In some cases the post IDs may change. + * For example when the website is exported and imported at another website. Then the + * attachment post IDs that are in post_content for the exported website may not match + * the same attachments at the new website. + * + * @since 5.5.0 + * + * @param string $image_location The full path or URI to the image file. + * @param array $image_meta The attachment meta data as returned by 'wp_get_attachment_metadata()'. + * @param int $attachment_id Optional. The image attachment ID. Default 0. + * @return bool Whether the image meta is for this image file. + */ + function wp_image_file_matches_image_meta($image_location, $image_meta, $attachment_id = 0) + { + } + /** + * Determines an image's width and height dimensions based on the source file. + * + * @since 5.5.0 + * + * @param string $image_src The image source file. + * @param array $image_meta The image meta data as returned by 'wp_get_attachment_metadata()'. + * @param int $attachment_id Optional. The image attachment ID. Default 0. + * @return array|false Array with first element being the width and second element being the height, + * or false if dimensions cannot be determined. + */ + function wp_image_src_get_dimensions($image_src, $image_meta, $attachment_id = 0) + { + } + /** + * Adds 'srcset' and 'sizes' attributes to an existing 'img' element. + * + * @since 4.4.0 + * + * @see wp_calculate_image_srcset() + * @see wp_calculate_image_sizes() + * + * @param string $image An HTML 'img' element to be filtered. + * @param array $image_meta The image meta data as returned by 'wp_get_attachment_metadata()'. + * @param int $attachment_id Image attachment ID. + * @return string Converted 'img' element with 'srcset' and 'sizes' attributes added. + */ + function wp_image_add_srcset_and_sizes($image, $image_meta, $attachment_id) + { + } + /** + * Determines whether to add the `loading` attribute to the specified tag in the specified context. + * + * @since 5.5.0 + * @since 5.7.0 Now returns `true` by default for `iframe` tags. + * + * @param string $tag_name The tag name. + * @param string $context Additional context, like the current filter name + * or the function name from where this was called. + * @return bool Whether to add the attribute. + */ + function wp_lazy_loading_enabled($tag_name, $context) + { + } + /** + * Filters specific tags in post content and modifies their markup. + * + * Modifies HTML tags in post content to include new browser and HTML technologies + * that may not have existed at the time of post creation. These modifications currently + * include adding `srcset`, `sizes`, and `loading` attributes to `img` HTML tags, as well + * as adding `loading` attributes to `iframe` HTML tags. + * Future similar optimizations should be added/expected here. + * + * @since 5.5.0 + * @since 5.7.0 Now supports adding `loading` attributes to `iframe` tags. + * + * @see wp_img_tag_add_width_and_height_attr() + * @see wp_img_tag_add_srcset_and_sizes_attr() + * @see wp_img_tag_add_loading_attr() + * @see wp_iframe_tag_add_loading_attr() + * + * @param string $content The HTML content to be filtered. + * @param string $context Optional. Additional context to pass to the filters. + * Defaults to `current_filter()` when not set. + * @return string Converted content with images modified. + */ + function wp_filter_content_tags($content, $context = \null) + { + } + /** + * Adds `loading` attribute to an `img` HTML tag. + * + * @since 5.5.0 + * + * @param string $image The HTML `img` tag where the attribute should be added. + * @param string $context Additional context to pass to the filters. + * @return string Converted `img` tag with `loading` attribute added. + */ + function wp_img_tag_add_loading_attr($image, $context) + { + } + /** + * Adds `decoding` attribute to an `img` HTML tag. + * + * The `decoding` attribute allows developers to indicate whether the + * browser can decode the image off the main thread (`async`), on the + * main thread (`sync`) or as determined by the browser (`auto`). + * + * By default WordPress adds `decoding="async"` to images but developers + * can use the {@see 'wp_img_tag_add_decoding_attr'} filter to modify this + * to remove the attribute or set it to another accepted value. + * + * @since 6.1.0 + * + * @param string $image The HTML `img` tag where the attribute should be added. + * @param string $context Additional context to pass to the filters. + * + * @return string Converted `img` tag with `decoding` attribute added. + */ + function wp_img_tag_add_decoding_attr($image, $context) + { + } + /** + * Adds `width` and `height` attributes to an `img` HTML tag. + * + * @since 5.5.0 + * + * @param string $image The HTML `img` tag where the attribute should be added. + * @param string $context Additional context to pass to the filters. + * @param int $attachment_id Image attachment ID. + * @return string Converted 'img' element with 'width' and 'height' attributes added. + */ + function wp_img_tag_add_width_and_height_attr($image, $context, $attachment_id) + { + } + /** + * Adds `srcset` and `sizes` attributes to an existing `img` HTML tag. + * + * @since 5.5.0 + * + * @param string $image The HTML `img` tag where the attribute should be added. + * @param string $context Additional context to pass to the filters. + * @param int $attachment_id Image attachment ID. + * @return string Converted 'img' element with 'loading' attribute added. + */ + function wp_img_tag_add_srcset_and_sizes_attr($image, $context, $attachment_id) + { + } + /** + * Adds `loading` attribute to an `iframe` HTML tag. + * + * @since 5.7.0 + * + * @param string $iframe The HTML `iframe` tag where the attribute should be added. + * @param string $context Additional context to pass to the filters. + * @return string Converted `iframe` tag with `loading` attribute added. + */ + function wp_iframe_tag_add_loading_attr($iframe, $context) + { + } + /** + * Adds a 'wp-post-image' class to post thumbnails. Internal use only. + * + * Uses the {@see 'begin_fetch_post_thumbnail_html'} and {@see 'end_fetch_post_thumbnail_html'} + * action hooks to dynamically add/remove itself so as to only filter post thumbnails. + * + * @ignore + * @since 2.9.0 + * + * @param string[] $attr Array of thumbnail attributes including src, class, alt, title, keyed by attribute name. + * @return string[] Modified array of attributes including the new 'wp-post-image' class. + */ + function _wp_post_thumbnail_class_filter($attr) + { + } + /** + * Adds '_wp_post_thumbnail_class_filter' callback to the 'wp_get_attachment_image_attributes' + * filter hook. Internal use only. + * + * @ignore + * @since 2.9.0 + * + * @param string[] $attr Array of thumbnail attributes including src, class, alt, title, keyed by attribute name. + */ + function _wp_post_thumbnail_class_filter_add($attr) + { + } + /** + * Removes the '_wp_post_thumbnail_class_filter' callback from the 'wp_get_attachment_image_attributes' + * filter hook. Internal use only. + * + * @ignore + * @since 2.9.0 + * + * @param string[] $attr Array of thumbnail attributes including src, class, alt, title, keyed by attribute name. + */ + function _wp_post_thumbnail_class_filter_remove($attr) + { + } + /** + * Builds the Caption shortcode output. + * + * Allows a plugin to replace the content that would otherwise be returned. The + * filter is {@see 'img_caption_shortcode'} and passes an empty string, the attr + * parameter and the content parameter values. + * + * The supported attributes for the shortcode are 'id', 'caption_id', 'align', + * 'width', 'caption', and 'class'. + * + * @since 2.6.0 + * @since 3.9.0 The `class` attribute was added. + * @since 5.1.0 The `caption_id` attribute was added. + * @since 5.9.0 The `$content` parameter default value changed from `null` to `''`. + * + * @param array $attr { + * Attributes of the caption shortcode. + * + * @type string $id ID of the image and caption container element, i.e. `<figure>` or `<div>`. + * @type string $caption_id ID of the caption element, i.e. `<figcaption>` or `<p>`. + * @type string $align Class name that aligns the caption. Default 'alignnone'. Accepts 'alignleft', + * 'aligncenter', alignright', 'alignnone'. + * @type int $width The width of the caption, in pixels. + * @type string $caption The caption text. + * @type string $class Additional class name(s) added to the caption container. + * } + * @param string $content Optional. Shortcode content. Default empty string. + * @return string HTML content to display the caption. + * @phpstan-param array{ + * id?: string, + * caption_id?: string, + * align?: string, + * width?: int, + * caption?: string, + * class?: string, + * } $attr + */ + function img_caption_shortcode($attr, $content = '') + { + } + /** + * Builds the Gallery shortcode output. + * + * This implements the functionality of the Gallery Shortcode for displaying + * WordPress images on a post. + * + * @since 2.5.0 + * @since 2.8.0 Added the `$attr` parameter to set the shortcode output. New attributes included + * such as `size`, `itemtag`, `icontag`, `captiontag`, and columns. Changed markup from + * `div` tags to `dl`, `dt` and `dd` tags. Support more than one gallery on the + * same page. + * @since 2.9.0 Added support for `include` and `exclude` to shortcode. + * @since 3.5.0 Use get_post() instead of global `$post`. Handle mapping of `ids` to `include` + * and `orderby`. + * @since 3.6.0 Added validation for tags used in gallery shortcode. Add orientation information to items. + * @since 3.7.0 Introduced the `link` attribute. + * @since 3.9.0 `html5` gallery support, accepting 'itemtag', 'icontag', and 'captiontag' attributes. + * @since 4.0.0 Removed use of `extract()`. + * @since 4.1.0 Added attribute to `wp_get_attachment_link()` to output `aria-describedby`. + * @since 4.2.0 Passed the shortcode instance ID to `post_gallery` and `post_playlist` filters. + * @since 4.6.0 Standardized filter docs to match documentation standards for PHP. + * @since 5.1.0 Code cleanup for WPCS 1.0.0 coding standards. + * @since 5.3.0 Saved progress of intermediate image creation after upload. + * @since 5.5.0 Ensured that galleries can be output as a list of links in feeds. + * @since 5.6.0 Replaced order-style PHP type conversion functions with typecasts. Fix logic for + * an array of image dimensions. + * + * @param array $attr { + * Attributes of the gallery shortcode. + * + * @type string $order Order of the images in the gallery. Default 'ASC'. Accepts 'ASC', 'DESC'. + * @type string $orderby The field to use when ordering the images. Default 'menu_order ID'. + * Accepts any valid SQL ORDERBY statement. + * @type int $id Post ID. + * @type string $itemtag HTML tag to use for each image in the gallery. + * Default 'dl', or 'figure' when the theme registers HTML5 gallery support. + * @type string $icontag HTML tag to use for each image's icon. + * Default 'dt', or 'div' when the theme registers HTML5 gallery support. + * @type string $captiontag HTML tag to use for each image's caption. + * Default 'dd', or 'figcaption' when the theme registers HTML5 gallery support. + * @type int $columns Number of columns of images to display. Default 3. + * @type string|int[] $size Size of the images to display. Accepts any registered image size name, or an array + * of width and height values in pixels (in that order). Default 'thumbnail'. + * @type string $ids A comma-separated list of IDs of attachments to display. Default empty. + * @type string $include A comma-separated list of IDs of attachments to include. Default empty. + * @type string $exclude A comma-separated list of IDs of attachments to exclude. Default empty. + * @type string $link What to link each image to. Default empty (links to the attachment page). + * Accepts 'file', 'none'. + * } + * @return string HTML content to display gallery. + * @phpstan-param array{ + * order?: string, + * orderby?: string, + * id?: int, + * itemtag?: string, + * icontag?: string, + * captiontag?: string, + * columns?: int, + * size?: string|int[], + * ids?: string, + * include?: string, + * exclude?: string, + * link?: string, + * } $attr + */ + function gallery_shortcode($attr) + { + } + /** + * Outputs the templates used by playlists. + * + * @since 3.9.0 + */ + function wp_underscore_playlist_templates() + { + } + /** + * Outputs and enqueues default scripts and styles for playlists. + * + * @since 3.9.0 + * + * @param string $type Type of playlist. Accepts 'audio' or 'video'. + */ + function wp_playlist_scripts($type) + { + } + /** + * Builds the Playlist shortcode output. + * + * This implements the functionality of the playlist shortcode for displaying + * a collection of WordPress audio or video files in a post. + * + * @since 3.9.0 + * + * @global int $content_width + * + * @param array $attr { + * Array of default playlist attributes. + * + * @type string $type Type of playlist to display. Accepts 'audio' or 'video'. Default 'audio'. + * @type string $order Designates ascending or descending order of items in the playlist. + * Accepts 'ASC', 'DESC'. Default 'ASC'. + * @type string $orderby Any column, or columns, to sort the playlist. If $ids are + * passed, this defaults to the order of the $ids array ('post__in'). + * Otherwise default is 'menu_order ID'. + * @type int $id If an explicit $ids array is not present, this parameter + * will determine which attachments are used for the playlist. + * Default is the current post ID. + * @type array $ids Create a playlist out of these explicit attachment IDs. If empty, + * a playlist will be created from all $type attachments of $id. + * Default empty. + * @type array $exclude List of specific attachment IDs to exclude from the playlist. Default empty. + * @type string $style Playlist style to use. Accepts 'light' or 'dark'. Default 'light'. + * @type bool $tracklist Whether to show or hide the playlist. Default true. + * @type bool $tracknumbers Whether to show or hide the numbers next to entries in the playlist. Default true. + * @type bool $images Show or hide the video or audio thumbnail (Featured Image/post + * thumbnail). Default true. + * @type bool $artists Whether to show or hide artist name in the playlist. Default true. + * } + * + * @return string Playlist output. Empty string if the passed type is unsupported. + * @phpstan-param array{ + * type?: string, + * order?: string, + * orderby?: string, + * id?: int, + * ids?: array, + * exclude?: array, + * style?: string, + * tracklist?: bool, + * tracknumbers?: bool, + * images?: bool, + * artists?: bool, + * } $attr + */ + function wp_playlist_shortcode($attr) + { + } + /** + * Provides a No-JS Flash fallback as a last resort for audio / video. + * + * @since 3.6.0 + * + * @param string $url The media element URL. + * @return string Fallback HTML. + */ + function wp_mediaelement_fallback($url) + { + } + /** + * Returns a filtered list of supported audio formats. + * + * @since 3.6.0 + * + * @return string[] Supported audio formats. + */ + function wp_get_audio_extensions() + { + } + /** + * Returns useful keys to use to lookup data from an attachment's stored metadata. + * + * @since 3.9.0 + * + * @param WP_Post $attachment The current attachment, provided for context. + * @param string $context Optional. The context. Accepts 'edit', 'display'. Default 'display'. + * @return string[] Key/value pairs of field keys to labels. + */ + function wp_get_attachment_id3_keys($attachment, $context = 'display') + { + } + /** + * Builds the Audio shortcode output. + * + * This implements the functionality of the Audio Shortcode for displaying + * WordPress mp3s in a post. + * + * @since 3.6.0 + * + * @param array $attr { + * Attributes of the audio shortcode. + * + * @type string $src URL to the source of the audio file. Default empty. + * @type string $loop The 'loop' attribute for the `<audio>` element. Default empty. + * @type string $autoplay The 'autoplay' attribute for the `<audio>` element. Default empty. + * @type string $preload The 'preload' attribute for the `<audio>` element. Default 'none'. + * @type string $class The 'class' attribute for the `<audio>` element. Default 'wp-audio-shortcode'. + * @type string $style The 'style' attribute for the `<audio>` element. Default 'width: 100%;'. + * } + * @param string $content Shortcode content. + * @return string|void HTML content to display audio. + * @phpstan-param array{ + * src?: string, + * loop?: string, + * autoplay?: string, + * preload?: string, + * class?: string, + * style?: string, + * } $attr + */ + function wp_audio_shortcode($attr, $content = '') + { + } + /** + * Returns a filtered list of supported video formats. + * + * @since 3.6.0 + * + * @return string[] List of supported video formats. + */ + function wp_get_video_extensions() + { + } + /** + * Builds the Video shortcode output. + * + * This implements the functionality of the Video Shortcode for displaying + * WordPress mp4s in a post. + * + * @since 3.6.0 + * + * @global int $content_width + * + * @param array $attr { + * Attributes of the shortcode. + * + * @type string $src URL to the source of the video file. Default empty. + * @type int $height Height of the video embed in pixels. Default 360. + * @type int $width Width of the video embed in pixels. Default $content_width or 640. + * @type string $poster The 'poster' attribute for the `<video>` element. Default empty. + * @type string $loop The 'loop' attribute for the `<video>` element. Default empty. + * @type string $autoplay The 'autoplay' attribute for the `<video>` element. Default empty. + * @type string $muted The 'muted' attribute for the `<video>` element. Default false. + * @type string $preload The 'preload' attribute for the `<video>` element. + * Default 'metadata'. + * @type string $class The 'class' attribute for the `<video>` element. + * Default 'wp-video-shortcode'. + * } + * @param string $content Shortcode content. + * @return string|void HTML content to display video. + * @phpstan-param array{ + * src?: string, + * height?: int, + * width?: int, + * poster?: string, + * loop?: string, + * autoplay?: string, + * muted?: string, + * preload?: string, + * class?: string, + * } $attr + */ + function wp_video_shortcode($attr, $content = '') + { + } + /** + * Gets the previous image link that has the same post parent. + * + * @since 5.8.0 + * + * @see get_adjacent_image_link() + * + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array + * of width and height values in pixels (in that order). Default 'thumbnail'. + * @param string|false $text Optional. Link text. Default false. + * @return string Markup for previous image link. + */ + function get_previous_image_link($size = 'thumbnail', $text = \false) + { + } + /** + * Displays previous image link that has the same post parent. + * + * @since 2.5.0 + * + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array + * of width and height values in pixels (in that order). Default 'thumbnail'. + * @param string|false $text Optional. Link text. Default false. + */ + function previous_image_link($size = 'thumbnail', $text = \false) + { + } + /** + * Gets the next image link that has the same post parent. + * + * @since 5.8.0 + * + * @see get_adjacent_image_link() + * + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array + * of width and height values in pixels (in that order). Default 'thumbnail'. + * @param string|false $text Optional. Link text. Default false. + * @return string Markup for next image link. + */ + function get_next_image_link($size = 'thumbnail', $text = \false) + { + } + /** + * Displays next image link that has the same post parent. + * + * @since 2.5.0 + * + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array + * of width and height values in pixels (in that order). Default 'thumbnail'. + * @param string|false $text Optional. Link text. Default false. + */ + function next_image_link($size = 'thumbnail', $text = \false) + { + } + /** + * Gets the next or previous image link that has the same post parent. + * + * Retrieves the current attachment object from the $post global. + * + * @since 5.8.0 + * + * @param bool $prev Optional. Whether to display the next (false) or previous (true) link. Default true. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array + * of width and height values in pixels (in that order). Default 'thumbnail'. + * @param bool $text Optional. Link text. Default false. + * @return string Markup for image link. + */ + function get_adjacent_image_link($prev = \true, $size = 'thumbnail', $text = \false) + { + } + /** + * Displays next or previous image link that has the same post parent. + * + * Retrieves the current attachment object from the $post global. + * + * @since 2.5.0 + * + * @param bool $prev Optional. Whether to display the next (false) or previous (true) link. Default true. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array + * of width and height values in pixels (in that order). Default 'thumbnail'. + * @param bool $text Optional. Link text. Default false. + */ + function adjacent_image_link($prev = \true, $size = 'thumbnail', $text = \false) + { + } + /** + * Retrieves taxonomies attached to given the attachment. + * + * @since 2.5.0 + * @since 4.7.0 Introduced the `$output` parameter. + * + * @param int|array|object $attachment Attachment ID, data array, or data object. + * @param string $output Output type. 'names' to return an array of taxonomy names, + * or 'objects' to return an array of taxonomy objects. + * Default is 'names'. + * @return string[]|WP_Taxonomy[] List of taxonomies or taxonomy names. Empty array on failure. + */ + function get_attachment_taxonomies($attachment, $output = 'names') + { + } + /** + * Retrieves all of the taxonomies that are registered for attachments. + * + * Handles mime-type-specific taxonomies such as attachment:image and attachment:video. + * + * @since 3.5.0 + * + * @see get_taxonomies() + * + * @param string $output Optional. The type of taxonomy output to return. Accepts 'names' or 'objects'. + * Default 'names'. + * @return string[]|WP_Taxonomy[] Array of names or objects of registered taxonomies for attachments. + */ + function get_taxonomies_for_attachments($output = 'names') + { + } + /** + * Determines whether the value is an acceptable type for GD image functions. + * + * In PHP 8.0, the GD extension uses GdImage objects for its data structures. + * This function checks if the passed value is either a resource of type `gd` + * or a GdImage object instance. Any other type will return false. + * + * @since 5.6.0 + * + * @param resource|GdImage|false $image A value to check the type for. + * @return bool True if $image is either a GD image resource or GdImage instance, + * false otherwise. + */ + function is_gd_image($image) + { + } + /** + * Creates new GD image resource with transparency support. + * + * @todo Deprecate if possible. + * + * @since 2.9.0 + * + * @param int $width Image width in pixels. + * @param int $height Image height in pixels. + * @return resource|GdImage|false The GD image resource or GdImage instance on success. + * False on failure. + */ + function wp_imagecreatetruecolor($width, $height) + { + } + /** + * Based on a supplied width/height example, returns the biggest possible dimensions based on the max width/height. + * + * @since 2.9.0 + * + * @see wp_constrain_dimensions() + * + * @param int $example_width The width of an example embed. + * @param int $example_height The height of an example embed. + * @param int $max_width The maximum allowed width. + * @param int $max_height The maximum allowed height. + * @return int[] { + * An array of maximum width and height values. + * + * @type int $0 The maximum width in pixels. + * @type int $1 The maximum height in pixels. + * } + * @phpstan-return array{ + * 0: int, + * 1: int, + * } + */ + function wp_expand_dimensions($example_width, $example_height, $max_width, $max_height) + { + } + /** + * Determines the maximum upload size allowed in php.ini. + * + * @since 2.5.0 + * + * @return int Allowed upload size. + */ + function wp_max_upload_size() + { + } + /** + * Returns a WP_Image_Editor instance and loads file into it. + * + * @since 3.5.0 + * + * @param string $path Path to the file to load. + * @param array $args Optional. Additional arguments for retrieving the image editor. + * Default empty array. + * @return WP_Image_Editor|WP_Error The WP_Image_Editor object on success, + * a WP_Error object otherwise. + */ + function wp_get_image_editor($path, $args = array()) + { + } + /** + * Tests whether there is an editor that supports a given mime type or methods. + * + * @since 3.5.0 + * + * @param string|array $args Optional. Array of arguments to retrieve the image editor supports. + * Default empty array. + * @return bool True if an eligible editor is found; false otherwise. + */ + function wp_image_editor_supports($args = array()) + { + } + /** + * Tests which editors are capable of supporting the request. + * + * @ignore + * @since 3.5.0 + * + * @param array $args Optional. Array of arguments for choosing a capable editor. Default empty array. + * @return string|false Class name for the first editor that claims to support the request. + * False if no editor claims to support the request. + */ + function _wp_image_editor_choose($args = array()) + { + } + /** + * Prints default Plupload arguments. + * + * @since 3.4.0 + */ + function wp_plupload_default_settings() + { + } + /** + * Prepares an attachment post object for JS, where it is expected + * to be JSON-encoded and fit into an Attachment model. + * + * @since 3.5.0 + * + * @param int|WP_Post $attachment Attachment ID or object. + * @return array|void { + * Array of attachment details, or void if the parameter does not correspond to an attachment. + * + * @type string $alt Alt text of the attachment. + * @type string $author ID of the attachment author, as a string. + * @type string $authorName Name of the attachment author. + * @type string $caption Caption for the attachment. + * @type array $compat Containing item and meta. + * @type string $context Context, whether it's used as the site icon for example. + * @type int $date Uploaded date, timestamp in milliseconds. + * @type string $dateFormatted Formatted date (e.g. June 29, 2018). + * @type string $description Description of the attachment. + * @type string $editLink URL to the edit page for the attachment. + * @type string $filename File name of the attachment. + * @type string $filesizeHumanReadable Filesize of the attachment in human readable format (e.g. 1 MB). + * @type int $filesizeInBytes Filesize of the attachment in bytes. + * @type int $height If the attachment is an image, represents the height of the image in pixels. + * @type string $icon Icon URL of the attachment (e.g. /wp-includes/images/media/archive.png). + * @type int $id ID of the attachment. + * @type string $link URL to the attachment. + * @type int $menuOrder Menu order of the attachment post. + * @type array $meta Meta data for the attachment. + * @type string $mime Mime type of the attachment (e.g. image/jpeg or application/zip). + * @type int $modified Last modified, timestamp in milliseconds. + * @type string $name Name, same as title of the attachment. + * @type array $nonces Nonces for update, delete and edit. + * @type string $orientation If the attachment is an image, represents the image orientation + * (landscape or portrait). + * @type array $sizes If the attachment is an image, contains an array of arrays + * for the images sizes: thumbnail, medium, large, and full. + * @type string $status Post status of the attachment (usually 'inherit'). + * @type string $subtype Mime subtype of the attachment (usually the last part, e.g. jpeg or zip). + * @type string $title Title of the attachment (usually slugified file name without the extension). + * @type string $type Type of the attachment (usually first part of the mime type, e.g. image). + * @type int $uploadedTo Parent post to which the attachment was uploaded. + * @type string $uploadedToLink URL to the edit page of the parent post of the attachment. + * @type string $uploadedToTitle Post title of the parent of the attachment. + * @type string $url Direct URL to the attachment file (from wp-content). + * @type int $width If the attachment is an image, represents the width of the image in pixels. + * } + * + * @phpstan-return void|array{ + * alt: string, + * author: string, + * authorName: string, + * caption: string, + * compat: array, + * context: string, + * date: int, + * dateFormatted: string, + * description: string, + * editLink: string, + * filename: string, + * filesizeHumanReadable: string, + * filesizeInBytes: int, + * height: int, + * icon: string, + * id: int, + * link: string, + * menuOrder: int, + * meta: array, + * mime: string, + * modified: int, + * name: string, + * nonces: array, + * orientation: string, + * sizes: array, + * status: string, + * subtype: string, + * title: string, + * type: string, + * uploadedTo: int, + * uploadedToLink: string, + * uploadedToTitle: string, + * url: string, + * width: int, + * } + */ + function wp_prepare_attachment_for_js($attachment) + { + } + /** + * Enqueues all scripts, styles, settings, and templates necessary to use + * all media JS APIs. + * + * @since 3.5.0 + * + * @global int $content_width + * @global wpdb $wpdb WordPress database abstraction object. + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @param array $args { + * Arguments for enqueuing media scripts. + * + * @type int|WP_Post $post Post ID or post object. + * } + * @phpstan-param array{ + * post?: int|WP_Post, + * } $args + */ + function wp_enqueue_media($args = array()) + { + } + /** + * Retrieves media attached to the passed post. + * + * @since 3.6.0 + * + * @param string $type Mime type. + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @return WP_Post[] Array of media attached to the given post. + */ + function get_attached_media($type, $post = 0) + { + } + /** + * Checks the HTML content for a audio, video, object, embed, or iframe tags. + * + * @since 3.6.0 + * + * @param string $content A string of HTML which might contain media elements. + * @param string[] $types An array of media types: 'audio', 'video', 'object', 'embed', or 'iframe'. + * @return string[] Array of found HTML media elements. + */ + function get_media_embedded_in_content($content, $types = \null) + { + } + /** + * Retrieves galleries from the passed post's content. + * + * @since 3.6.0 + * + * @param int|WP_Post $post Post ID or object. + * @param bool $html Optional. Whether to return HTML or data in the array. Default true. + * @return array A list of arrays, each containing gallery data and srcs parsed + * from the expanded shortcode. + */ + function get_post_galleries($post, $html = \true) + { + } + /** + * Checks a specified post's content for gallery and, if present, return the first + * + * @since 3.6.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @param bool $html Optional. Whether to return HTML or data. Default is true. + * @return string|array Gallery data and srcs parsed from the expanded shortcode. + */ + function get_post_gallery($post = 0, $html = \true) + { + } + /** + * Retrieves the image srcs from galleries from a post's content, if present. + * + * @since 3.6.0 + * + * @see get_post_galleries() + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global `$post`. + * @return array A list of lists, each containing image srcs parsed. + * from an expanded shortcode + */ + function get_post_galleries_images($post = 0) + { + } + /** + * Checks a post's content for galleries and return the image srcs for the first found gallery. + * + * @since 3.6.0 + * + * @see get_post_gallery() + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global `$post`. + * @return string[] A list of a gallery's image srcs in order. + */ + function get_post_gallery_images($post = 0) + { + } + /** + * Maybe attempts to generate attachment metadata, if missing. + * + * @since 3.9.0 + * + * @param WP_Post $attachment Attachment object. + */ + function wp_maybe_generate_attachment_metadata($attachment) + { + } + /** + * Tries to convert an attachment URL into a post ID. + * + * @since 4.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $url The URL to resolve. + * @return int The found post ID, or 0 on failure. + */ + function attachment_url_to_postid($url) + { + } + /** + * Returns the URLs for CSS files used in an iframe-sandbox'd TinyMCE media view. + * + * @since 4.0.0 + * + * @return string[] The relevant CSS file URLs. + */ + function wpview_media_sandbox_styles() + { + } + /** + * Registers the personal data exporter for media. + * + * @param array[] $exporters An array of personal data exporters, keyed by their ID. + * @return array[] Updated array of personal data exporters. + */ + function wp_register_media_personal_data_exporter($exporters) + { + } + /** + * Finds and exports attachments associated with an email address. + * + * @since 4.9.6 + * + * @param string $email_address The attachment owner email address. + * @param int $page Attachment page. + * @return array An array of personal data. + */ + function wp_media_personal_data_exporter($email_address, $page = 1) + { + } + /** + * Adds additional default image sub-sizes. + * + * These sizes are meant to enhance the way WordPress displays images on the front-end on larger, + * high-density devices. They make it possible to generate more suitable `srcset` and `sizes` attributes + * when the users upload large images. + * + * The sizes can be changed or removed by themes and plugins but that is not recommended. + * The size "names" reflect the image dimensions, so changing the sizes would be quite misleading. + * + * @since 5.3.0 + * @access private + */ + function _wp_add_additional_image_sizes() + { + } + /** + * Callback to enable showing of the user error when uploading .heic images. + * + * @since 5.5.0 + * + * @param array[] $plupload_settings The settings for Plupload.js. + * @return array[] Modified settings for Plupload.js. + */ + function wp_show_heic_upload_error($plupload_settings) + { + } + /** + * Allows PHP's getimagesize() to be debuggable when necessary. + * + * @since 5.7.0 + * @since 5.8.0 Added support for WebP images. + * + * @param string $filename The file path. + * @param array $image_info Optional. Extended image information (passed by reference). + * @return array|false Array of image information or false on failure. + */ + function wp_getimagesize($filename, array &$image_info = \null) + { + } + /** + * Extracts meta information about a WebP file: width, height, and type. + * + * @since 5.8.0 + * + * @param string $filename Path to a WebP file. + * @return array { + * An array of WebP image information. + * + * @type int|false $width Image width on success, false on failure. + * @type int|false $height Image height on success, false on failure. + * @type string|false $type The WebP type: one of 'lossy', 'lossless' or 'animated-alpha'. + * False on failure. + * } + * @phpstan-return array{ + * width: int|false, + * height: int|false, + * type: string|false, + * } + */ + function wp_get_webp_info($filename) + { + } + /** + * Gets the default value to use for a `loading` attribute on an element. + * + * This function should only be called for a tag and context if lazy-loading is generally enabled. + * + * The function usually returns 'lazy', but uses certain heuristics to guess whether the current element is likely to + * appear above the fold, in which case it returns a boolean `false`, which will lead to the `loading` attribute being + * omitted on the element. The purpose of this refinement is to avoid lazy-loading elements that are within the initial + * viewport, which can have a negative performance impact. + * + * Under the hood, the function uses {@see wp_increase_content_media_count()} every time it is called for an element + * within the main content. If the element is the very first content element, the `loading` attribute will be omitted. + * This default threshold of 1 content element to omit the `loading` attribute for can be customized using the + * {@see 'wp_omit_loading_attr_threshold'} filter. + * + * @since 5.9.0 + * + * @param string $context Context for the element for which the `loading` attribute value is requested. + * @return string|bool The default `loading` attribute value. Either 'lazy', 'eager', or a boolean `false`, to indicate + * that the `loading` attribute should be skipped. + */ + function wp_get_loading_attr_default($context) + { + } + /** + * Gets the threshold for how many of the first content media elements to not lazy-load. + * + * This function runs the {@see 'wp_omit_loading_attr_threshold'} filter, which uses a default threshold value of 1. + * The filter is only run once per page load, unless the `$force` parameter is used. + * + * @since 5.9.0 + * + * @param bool $force Optional. If set to true, the filter will be (re-)applied even if it already has been before. + * Default false. + * @return int The number of content media elements to not lazy-load. + */ + function wp_omit_loading_attr_threshold($force = \false) + { + } + /** + * Increases an internal content media count variable. + * + * @since 5.9.0 + * @access private + * + * @param int $amount Optional. Amount to increase by. Default 1. + * @return int The latest content media count, after the increase. + */ + function wp_increase_content_media_count($amount = 1) + { + } + /** + * Core Metadata API + * + * Functions for retrieving and manipulating metadata of various WordPress object types. Metadata + * for an object is a represented by a simple key-value pair. Objects may contain multiple + * metadata entries that share the same key and differ only in their value. + * + * @package WordPress + * @subpackage Meta + */ + /** + * Adds metadata for the specified object. + * + * @since 2.9.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param int $object_id ID of the object metadata is for. + * @param string $meta_key Metadata key. + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. + * @param bool $unique Optional. Whether the specified metadata key should be unique for the object. + * If true, and the object already has a value for the specified metadata key, + * no change will be made. Default false. + * @return int|false The meta ID on success, false on failure. + */ + function add_metadata($meta_type, $object_id, $meta_key, $meta_value, $unique = \false) + { + } + /** + * Updates metadata for the specified object. If no value already exists for the specified object + * ID and metadata key, the metadata will be added. + * + * @since 2.9.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param int $object_id ID of the object metadata is for. + * @param string $meta_key Metadata key. + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. + * @param mixed $prev_value Optional. Previous value to check before updating. + * If specified, only update existing metadata entries with + * this value. Otherwise, update all entries. Default empty. + * @return int|bool The new meta field ID if a field with the given key didn't exist + * and was therefore added, true on successful update, + * false on failure or if the value passed to the function + * is the same as the one that is already in the database. + */ + function update_metadata($meta_type, $object_id, $meta_key, $meta_value, $prev_value = '') + { + } + /** + * Deletes metadata for the specified object. + * + * @since 2.9.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param int $object_id ID of the object metadata is for. + * @param string $meta_key Metadata key. + * @param mixed $meta_value Optional. Metadata value. Must be serializable if non-scalar. + * If specified, only delete metadata entries with this value. + * Otherwise, delete all entries with the specified meta_key. + * Pass `null`, `false`, or an empty string to skip this check. + * (For backward compatibility, it is not possible to pass an empty string + * to delete those entries with an empty string for a value.) + * @param bool $delete_all Optional. If true, delete matching metadata entries for all objects, + * ignoring the specified object_id. Otherwise, only delete + * matching metadata entries for the specified object_id. Default false. + * @return bool True on successful delete, false on failure. + */ + function delete_metadata($meta_type, $object_id, $meta_key, $meta_value = '', $delete_all = \false) + { + } + /** + * Retrieves the value of a metadata field for the specified object type and ID. + * + * If the meta field exists, a single value is returned if `$single` is true, + * or an array of values if it's false. + * + * If the meta field does not exist, the result depends on get_metadata_default(). + * By default, an empty string is returned if `$single` is true, or an empty array + * if it's false. + * + * @since 2.9.0 + * + * @see get_metadata_raw() + * @see get_metadata_default() + * + * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param int $object_id ID of the object metadata is for. + * @param string $meta_key Optional. Metadata key. If not specified, retrieve all metadata for + * the specified object. Default empty. + * @param bool $single Optional. If true, return only the first value of the specified `$meta_key`. + * This parameter has no effect if `$meta_key` is not specified. Default false. + * @return mixed An array of values if `$single` is false. + * The value of the meta field if `$single` is true. + * False for an invalid `$object_id` (non-numeric, zero, or negative value), + * or if `$meta_type` is not specified. + * An empty string if a valid but non-existing object ID is passed. + */ + function get_metadata($meta_type, $object_id, $meta_key = '', $single = \false) + { + } + /** + * Retrieves raw metadata value for the specified object. + * + * @since 5.5.0 + * + * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param int $object_id ID of the object metadata is for. + * @param string $meta_key Optional. Metadata key. If not specified, retrieve all metadata for + * the specified object. Default empty. + * @param bool $single Optional. If true, return only the first value of the specified `$meta_key`. + * This parameter has no effect if `$meta_key` is not specified. Default false. + * @return mixed An array of values if `$single` is false. + * The value of the meta field if `$single` is true. + * False for an invalid `$object_id` (non-numeric, zero, or negative value), + * or if `$meta_type` is not specified. + * Null if the value does not exist. + */ + function get_metadata_raw($meta_type, $object_id, $meta_key = '', $single = \false) + { + } + /** + * Retrieves default metadata value for the specified meta key and object. + * + * By default, an empty string is returned if `$single` is true, or an empty array + * if it's false. + * + * @since 5.5.0 + * + * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param int $object_id ID of the object metadata is for. + * @param string $meta_key Metadata key. + * @param bool $single Optional. If true, return only the first value of the specified `$meta_key`. + * This parameter has no effect if `$meta_key` is not specified. Default false. + * @return mixed An array of default values if `$single` is false. + * The default value of the meta field if `$single` is true. + */ + function get_metadata_default($meta_type, $object_id, $meta_key, $single = \false) + { + } + /** + * Determines if a meta field with the given key exists for the given object ID. + * + * @since 3.3.0 + * + * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param int $object_id ID of the object metadata is for. + * @param string $meta_key Metadata key. + * @return bool Whether a meta field with the given key exists. + */ + function metadata_exists($meta_type, $object_id, $meta_key) + { + } + /** + * Retrieves metadata by meta ID. + * + * @since 3.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param int $meta_id ID for a specific meta row. + * @return stdClass|false { + * Metadata object, or boolean `false` if the metadata doesn't exist. + * + * @type string $meta_key The meta key. + * @type mixed $meta_value The unserialized meta value. + * @type string $meta_id Optional. The meta ID when the meta type is any value except 'user'. + * @type string $umeta_id Optional. The meta ID when the meta type is 'user'. + * @type string $post_id Optional. The object ID when the meta type is 'post'. + * @type string $comment_id Optional. The object ID when the meta type is 'comment'. + * @type string $term_id Optional. The object ID when the meta type is 'term'. + * @type string $user_id Optional. The object ID when the meta type is 'user'. + * } + */ + function get_metadata_by_mid($meta_type, $meta_id) + { + } + /** + * Updates metadata by meta ID. + * + * @since 3.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param int $meta_id ID for a specific meta row. + * @param string $meta_value Metadata value. Must be serializable if non-scalar. + * @param string|false $meta_key Optional. You can provide a meta key to update it. Default false. + * @return bool True on successful update, false on failure. + */ + function update_metadata_by_mid($meta_type, $meta_id, $meta_value, $meta_key = \false) + { + } + /** + * Deletes metadata by meta ID. + * + * @since 3.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param int $meta_id ID for a specific meta row. + * @return bool True on successful delete, false on failure. + */ + function delete_metadata_by_mid($meta_type, $meta_id) + { + } + /** + * Updates the metadata cache for the specified objects. + * + * @since 2.9.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param string|int[] $object_ids Array or comma delimited list of object IDs to update cache for. + * @return array|false Metadata cache for the specified objects, or false on failure. + */ + function update_meta_cache($meta_type, $object_ids) + { + } + /** + * Retrieves the queue for lazy-loading metadata. + * + * @since 4.5.0 + * + * @return WP_Metadata_Lazyloader Metadata lazyloader queue. + */ + function wp_metadata_lazyloader() + { + } + /** + * Given a meta query, generates SQL clauses to be appended to a main query. + * + * @since 3.2.0 + * + * @see WP_Meta_Query + * + * @param array $meta_query A meta query. + * @param string $type Type of meta. + * @param string $primary_table Primary database table name. + * @param string $primary_id_column Primary ID column name. + * @param object $context Optional. The main query object + * @return string[]|false { + * Array containing JOIN and WHERE SQL clauses to append to the main query, + * or false if no table exists for the requested meta type. + * + * @type string $join SQL fragment to append to the main JOIN clause. + * @type string $where SQL fragment to append to the main WHERE clause. + * } + * @phpstan-return false|array{ + * join: string, + * where: string, + * } + */ + function get_meta_sql($meta_query, $type, $primary_table, $primary_id_column, $context = \null) + { + } + /** + * Retrieves the name of the metadata table for the specified object type. + * + * @since 2.9.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @return string|false Metadata table name, or false if no metadata table exists + */ + function _get_meta_table($type) + { + } + /** + * Determines whether a meta key is considered protected. + * + * @since 3.1.3 + * + * @param string $meta_key Metadata key. + * @param string $meta_type Optional. Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. Default empty. + * @return bool Whether the meta key is considered protected. + */ + function is_protected_meta($meta_key, $meta_type = '') + { + } + /** + * Sanitizes meta value. + * + * @since 3.1.3 + * @since 4.9.8 The `$object_subtype` parameter was added. + * + * @param string $meta_key Metadata key. + * @param mixed $meta_value Metadata value to sanitize. + * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param string $object_subtype Optional. The subtype of the object type. + * @return mixed Sanitized $meta_value. + */ + function sanitize_meta($meta_key, $meta_value, $object_type, $object_subtype = '') + { + } + /** + * Registers a meta key. + * + * It is recommended to register meta keys for a specific combination of object type and object subtype. If passing + * an object subtype is omitted, the meta key will be registered for the entire object type, however it can be partly + * overridden in case a more specific meta key of the same name exists for the same object type and a subtype. + * + * If an object type does not support any subtypes, such as users or comments, you should commonly call this function + * without passing a subtype. + * + * @since 3.3.0 + * @since 4.6.0 {@link https://core.trac.wordpress.org/ticket/35658 Modified + * to support an array of data to attach to registered meta keys}. Previous arguments for + * `$sanitize_callback` and `$auth_callback` have been folded into this array. + * @since 4.9.8 The `$object_subtype` argument was added to the arguments array. + * @since 5.3.0 Valid meta types expanded to include "array" and "object". + * @since 5.5.0 The `$default` argument was added to the arguments array. + * + * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param string $meta_key Meta key to register. + * @param array $args { + * Data used to describe the meta key when registered. + * + * @type string $object_subtype A subtype; e.g. if the object type is "post", the post type. If left empty, + * the meta key will be registered on the entire object type. Default empty. + * @type string $type The type of data associated with this meta key. + * Valid values are 'string', 'boolean', 'integer', 'number', 'array', and 'object'. + * @type string $description A description of the data attached to this meta key. + * @type bool $single Whether the meta key has one value per object, or an array of values per object. + * @type mixed $default The default value returned from get_metadata() if no value has been set yet. + * When using a non-single meta key, the default value is for the first entry. + * In other words, when calling get_metadata() with `$single` set to `false`, + * the default value given here will be wrapped in an array. + * @type callable $sanitize_callback A function or method to call when sanitizing `$meta_key` data. + * @type callable $auth_callback Optional. A function or method to call when performing edit_post_meta, + * add_post_meta, and delete_post_meta capability checks. + * @type bool|array $show_in_rest Whether data associated with this meta key can be considered public and + * should be accessible via the REST API. A custom post type must also declare + * support for custom fields for registered meta to be accessible via REST. + * When registering complex meta values this argument may optionally be an + * array with 'schema' or 'prepare_callback' keys instead of a boolean. + * } + * @param string|array $deprecated Deprecated. Use `$args` instead. + * @return bool True if the meta key was successfully registered in the global array, false if not. + * Registering a meta key with distinct sanitize and auth callbacks will fire those callbacks, + * but will not add to the global registry. + * @phpstan-param array{ + * object_subtype?: string, + * type?: string, + * description?: string, + * single?: bool, + * default?: mixed, + * sanitize_callback?: callable, + * auth_callback?: callable, + * show_in_rest?: bool|array, + * } $args + */ + function register_meta($object_type, $meta_key, $args, $deprecated = \null) + { + } + /** + * Filters into default_{$object_type}_metadata and adds in default value. + * + * @since 5.5.0 + * + * @param mixed $value Current value passed to filter. + * @param int $object_id ID of the object metadata is for. + * @param string $meta_key Metadata key. + * @param bool $single If true, return only the first value of the specified `$meta_key`. + * This parameter has no effect if `$meta_key` is not specified. + * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @return mixed An array of default values if `$single` is false. + * The default value of the meta field if `$single` is true. + */ + function filter_default_metadata($value, $object_id, $meta_key, $single, $meta_type) + { + } + /** + * Checks if a meta key is registered. + * + * @since 4.6.0 + * @since 4.9.8 The `$object_subtype` parameter was added. + * + * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param string $meta_key Metadata key. + * @param string $object_subtype Optional. The subtype of the object type. + * @return bool True if the meta key is registered to the object type and, if provided, + * the object subtype. False if not. + */ + function registered_meta_key_exists($object_type, $meta_key, $object_subtype = '') + { + } + /** + * Unregisters a meta key from the list of registered keys. + * + * @since 4.6.0 + * @since 4.9.8 The `$object_subtype` parameter was added. + * + * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param string $meta_key Metadata key. + * @param string $object_subtype Optional. The subtype of the object type. + * @return bool True if successful. False if the meta key was not registered. + */ + function unregister_meta_key($object_type, $meta_key, $object_subtype = '') + { + } + /** + * Retrieves a list of registered metadata args for an object type, keyed by their meta keys. + * + * @since 4.6.0 + * @since 4.9.8 The `$object_subtype` parameter was added. + * + * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param string $object_subtype Optional. The subtype of the object type. + * @return array[] List of registered metadata args, keyed by their meta keys. + */ + function get_registered_meta_keys($object_type, $object_subtype = '') + { + } + /** + * Retrieves registered metadata for a specified object. + * + * The results include both meta that is registered specifically for the + * object's subtype and meta that is registered for the entire object type. + * + * @since 4.6.0 + * + * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param int $object_id ID of the object the metadata is for. + * @param string $meta_key Optional. Registered metadata key. If not specified, retrieve all registered + * metadata for the specified object. + * @return mixed A single value or array of values for a key if specified. An array of all registered keys + * and values for an object ID if not. False if a given $meta_key is not registered. + */ + function get_registered_metadata($object_type, $object_id, $meta_key = '') + { + } + /** + * Filters out `register_meta()` args based on an allowed list. + * + * `register_meta()` args may change over time, so requiring the allowed list + * to be explicitly turned off is a warranty seal of sorts. + * + * @access private + * @since 5.5.0 + * + * @param array $args Arguments from `register_meta()`. + * @param array $default_args Default arguments for `register_meta()`. + * @return array Filtered arguments. + */ + function _wp_register_meta_args_allowed_list($args, $default_args) + { + } + /** + * Returns the object subtype for a given object ID of a specific type. + * + * @since 4.9.8 + * + * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', + * or any other object type with an associated meta table. + * @param int $object_id ID of the object to retrieve its subtype. + * @return string The object subtype or an empty string if unspecified subtype. + */ + function get_object_subtype($object_type, $object_id) + { + } + /** + * Update the last_updated field for the current site. + * + * @since MU (3.0.0) + */ + function wpmu_update_blogs_date() + { + } + /** + * Get a full blog URL, given a blog ID. + * + * @since MU (3.0.0) + * + * @param int $blog_id Blog ID. + * @return string Full URL of the blog if found. Empty string if not. + */ + function get_blogaddress_by_id($blog_id) + { + } + /** + * Get a full blog URL, given a blog name. + * + * @since MU (3.0.0) + * + * @param string $blogname The (subdomain or directory) name + * @return string + */ + function get_blogaddress_by_name($blogname) + { + } + /** + * Retrieves a site's ID given its (subdomain or directory) slug. + * + * @since MU (3.0.0) + * @since 4.7.0 Converted to use `get_sites()`. + * + * @param string $slug A site's slug. + * @return int|null The site ID, or null if no site is found for the given slug. + */ + function get_id_from_blogname($slug) + { + } + /** + * Retrieve the details for a blog from the blogs table and blog options. + * + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|string|array $fields Optional. A blog ID, a blog slug, or an array of fields to query against. + * If not specified the current blog ID is used. + * @param bool $get_all Whether to retrieve all details or only the details in the blogs table. + * Default is true. + * @return WP_Site|false Blog details on success. False on failure. + */ + function get_blog_details($fields = \null, $get_all = \true) + { + } + /** + * Clear the blog details cache. + * + * @since MU (3.0.0) + * + * @param int $blog_id Optional. Blog ID. Defaults to current blog. + */ + function refresh_blog_details($blog_id = 0) + { + } + /** + * Update the details for a blog. Updates the blogs table for a given blog ID. + * + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $blog_id Blog ID. + * @param array $details Array of details keyed by blogs table field names. + * @return bool True if update succeeds, false otherwise. + */ + function update_blog_details($blog_id, $details = array()) + { + } + /** + * Cleans the site details cache for a site. + * + * @since 4.7.4 + * + * @param int $site_id Optional. Site ID. Default is the current site ID. + */ + function clean_site_details_cache($site_id = 0) + { + } + /** + * Retrieve option value for a given blog id based on name of option. + * + * If the option does not exist or does not have a value, then the return value + * will be false. This is useful to check whether you need to install an option + * and is commonly used during installation of plugin options and to test + * whether upgrading is required. + * + * If the option was serialized then it will be unserialized when it is returned. + * + * @since MU (3.0.0) + * + * @param int $id A blog ID. Can be null to refer to the current blog. + * @param string $option Name of option to retrieve. Expected to not be SQL-escaped. + * @param mixed $default Optional. Default value to return if the option does not exist. + * @return mixed Value set for the option. + */ + function get_blog_option($id, $option, $default = \false) + { + } + /** + * Add a new option for a given blog ID. + * + * You do not need to serialize values. If the value needs to be serialized, then + * it will be serialized before it is inserted into the database. Remember, + * resources can not be serialized or added as an option. + * + * You can create options without values and then update the values later. + * Existing options will not be updated and checks are performed to ensure that you + * aren't adding a protected WordPress option. Care should be taken to not name + * options the same as the ones which are protected. + * + * @since MU (3.0.0) + * + * @param int $id A blog ID. Can be null to refer to the current blog. + * @param string $option Name of option to add. Expected to not be SQL-escaped. + * @param mixed $value Optional. Option value, can be anything. Expected to not be SQL-escaped. + * @return bool True if the option was added, false otherwise. + */ + function add_blog_option($id, $option, $value) + { + } + /** + * Removes option by name for a given blog ID. Prevents removal of protected WordPress options. + * + * @since MU (3.0.0) + * + * @param int $id A blog ID. Can be null to refer to the current blog. + * @param string $option Name of option to remove. Expected to not be SQL-escaped. + * @return bool True if the option was deleted, false otherwise. + */ + function delete_blog_option($id, $option) + { + } + /** + * Update an option for a particular blog. + * + * @since MU (3.0.0) + * + * @param int $id The blog ID. + * @param string $option The option key. + * @param mixed $value The option value. + * @param mixed $deprecated Not used. + * @return bool True if the value was updated, false otherwise. + */ + function update_blog_option($id, $option, $value, $deprecated = \null) + { + } + /** + * Switch the current blog. + * + * This function is useful if you need to pull posts, or other information, + * from other blogs. You can switch back afterwards using restore_current_blog(). + * + * Things that aren't switched: + * - plugins. See #14941 + * + * @see restore_current_blog() + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global int $blog_id + * @global array $_wp_switched_stack + * @global bool $switched + * @global string $table_prefix + * @global WP_Object_Cache $wp_object_cache + * + * @param int $new_blog_id The ID of the blog to switch to. Default: current blog. + * @param bool $deprecated Not used. + * @return true Always returns true. + */ + function switch_to_blog($new_blog_id, $deprecated = \null) + { + } + /** + * Restore the current blog, after calling switch_to_blog(). + * + * @see switch_to_blog() + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global array $_wp_switched_stack + * @global int $blog_id + * @global bool $switched + * @global string $table_prefix + * @global WP_Object_Cache $wp_object_cache + * + * @return bool True on success, false if we're already on the current blog. + */ + function restore_current_blog() + { + } + /** + * Switches the initialized roles and current user capabilities to another site. + * + * @since 4.9.0 + * + * @param int $new_site_id New site ID. + * @param int $old_site_id Old site ID. + */ + function wp_switch_roles_and_user($new_site_id, $old_site_id) + { + } + /** + * Determines if switch_to_blog() is in effect + * + * @since 3.5.0 + * + * @global array $_wp_switched_stack + * + * @return bool True if switched, false otherwise. + */ + function ms_is_switched() + { + } + /** + * Check if a particular blog is archived. + * + * @since MU (3.0.0) + * + * @param int $id Blog ID. + * @return string Whether the blog is archived or not. + */ + function is_archived($id) + { + } + /** + * Update the 'archived' status of a particular blog. + * + * @since MU (3.0.0) + * + * @param int $id Blog ID. + * @param string $archived The new status. + * @return string $archived + */ + function update_archived($id, $archived) + { + } + /** + * Update a blog details field. + * + * @since MU (3.0.0) + * @since 5.1.0 Use wp_update_site() internally. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $blog_id Blog ID. + * @param string $pref Field name. + * @param string $value Field value. + * @param null $deprecated Not used. + * @return string|false $value + */ + function update_blog_status($blog_id, $pref, $value, $deprecated = \null) + { + } + /** + * Get a blog details field. + * + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $id Blog ID. + * @param string $pref Field name. + * @return bool|string|null $value + */ + function get_blog_status($id, $pref) + { + } + /** + * Get a list of most recently updated blogs. + * + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param mixed $deprecated Not used. + * @param int $start Optional. Number of blogs to offset the query. Used to build LIMIT clause. + * Can be used for pagination. Default 0. + * @param int $quantity Optional. The maximum number of blogs to retrieve. Default 40. + * @return array The list of blogs. + */ + function get_last_updated($deprecated = '', $start = 0, $quantity = 40) + { + } + /** + * Handler for updating the site's last updated date when a post is published or + * an already published post is changed. + * + * @since 3.3.0 + * + * @param string $new_status The new post status. + * @param string $old_status The old post status. + * @param WP_Post $post Post object. + */ + function _update_blog_date_on_post_publish($new_status, $old_status, $post) + { + } + /** + * Handler for updating the current site's last updated date when a published + * post is deleted. + * + * @since 3.4.0 + * + * @param int $post_id Post ID + */ + function _update_blog_date_on_post_delete($post_id) + { + } + /** + * Handler for updating the current site's posts count when a post is deleted. + * + * @since 4.0.0 + * + * @param int $post_id Post ID. + */ + function _update_posts_count_on_delete($post_id) + { + } + /** + * Handler for updating the current site's posts count when a post status changes. + * + * @since 4.0.0 + * @since 4.9.0 Added the `$post` parameter. + * + * @param string $new_status The status the post is changing to. + * @param string $old_status The status the post is changing from. + * @param WP_Post $post Post object + */ + function _update_posts_count_on_transition_post_status($new_status, $old_status, $post = \null) + { + } + /** + * Count number of sites grouped by site status. + * + * @since 5.3.0 + * + * @param int $network_id Optional. The network to get counts for. Default is the current network ID. + * @return int[] { + * Numbers of sites grouped by site status. + * + * @type int $all The total number of sites. + * @type int $public The number of public sites. + * @type int $archived The number of archived sites. + * @type int $mature The number of mature sites. + * @type int $spam The number of spam sites. + * @type int $deleted The number of deleted sites. + * } + * @phpstan-return array{ + * all: int, + * public: int, + * archived: int, + * mature: int, + * spam: int, + * deleted: int, + * } + */ + function wp_count_sites($network_id = \null) + { + } + /** + * Defines constants and global variables that can be overridden, generally in wp-config.php. + * + * @package WordPress + * @subpackage Multisite + * @since 3.0.0 + */ + /** + * Defines Multisite upload constants. + * + * Exists for backward compatibility with legacy file-serving through + * wp-includes/ms-files.php (wp-content/blogs.php in MU). + * + * @since 3.0.0 + */ + function ms_upload_constants() + { + } + /** + * Defines Multisite cookie constants. + * + * @since 3.0.0 + */ + function ms_cookie_constants() + { + } + /** + * Defines Multisite file constants. + * + * Exists for backward compatibility with legacy file-serving through + * wp-includes/ms-files.php (wp-content/blogs.php in MU). + * + * @since 3.0.0 + */ + function ms_file_constants() + { + } + /** + * Defines Multisite subdomain constants and handles warnings and notices. + * + * VHOST is deprecated in favor of SUBDOMAIN_INSTALL, which is a bool. + * + * On first call, the constants are checked and defined. On second call, + * we will have translations loaded and can trigger warnings easily. + * + * @since 3.0.0 + */ + function ms_subdomain_constants() + { + } + /** + * Deprecated functions from WordPress MU and the multisite feature. You shouldn't + * use these functions and look for the alternatives instead. The functions will be + * removed in a later version. + * + * @package WordPress + * @subpackage Deprecated + * @since 3.0.0 + */ + /* + * Deprecated functions come here to die. + */ + /** + * Get the "dashboard blog", the blog where users without a blog edit their profile data. + * Dashboard blog functionality was removed in WordPress 3.1, replaced by the user admin. + * + * @since MU (3.0.0) + * @deprecated 3.1.0 Use get_site() + * @see get_site() + * + * @return WP_Site Current site object. + */ + function get_dashboard_blog() + { + } + /** + * Generates a random password. + * + * @since MU (3.0.0) + * @deprecated 3.0.0 Use wp_generate_password() + * @see wp_generate_password() + * + * @param int $len Optional. The length of password to generate. Default 8. + */ + function generate_random_password($len = 8) + { + } + /** + * Determine if user is a site admin. + * + * Plugins should use is_multisite() instead of checking if this function exists + * to determine if multisite is enabled. + * + * This function must reside in a file included only if is_multisite() due to + * legacy function_exists() checks to determine if multisite is enabled. + * + * @since MU (3.0.0) + * @deprecated 3.0.0 Use is_super_admin() + * @see is_super_admin() + * + * @param string $user_login Optional. Username for the user to check. Default empty. + */ + function is_site_admin($user_login = '') + { + } + /** + * Deprecated functionality to gracefully fail. + * + * @since MU (3.0.0) + * @deprecated 3.0.0 Use wp_die() + * @see wp_die() + */ + function graceful_fail($message) + { + } + /** + * Deprecated functionality to retrieve user information. + * + * @since MU (3.0.0) + * @deprecated 3.0.0 Use get_user_by() + * @see get_user_by() + * + * @param string $username Username. + */ + function get_user_details($username) + { + } + /** + * Deprecated functionality to clear the global post cache. + * + * @since MU (3.0.0) + * @deprecated 3.0.0 Use clean_post_cache() + * @see clean_post_cache() + * + * @param int $post_id Post ID. + */ + function clear_global_post_cache($post_id) + { + } + /** + * Deprecated functionality to determin if the current site is the main site. + * + * @since MU (3.0.0) + * @deprecated 3.0.0 Use is_main_site() + * @see is_main_site() + */ + function is_main_blog() + { + } + /** + * Deprecated functionality to validate an email address. + * + * @since MU (3.0.0) + * @deprecated 3.0.0 Use is_email() + * @see is_email() + * + * @param string $email Email address to verify. + * @param bool $check_domain Deprecated. + * @return string|false Valid email address on success, false on failure. + */ + function validate_email($email, $check_domain = \true) + { + } + /** + * Deprecated functionality to retrieve a list of all sites. + * + * @since MU (3.0.0) + * @deprecated 3.0.0 Use wp_get_sites() + * @see wp_get_sites() + * + * @param int $start Optional. Offset for retrieving the blog list. Default 0. + * @param int $num Optional. Number of blogs to list. Default 10. + * @param string $deprecated Unused. + */ + function get_blog_list($start = 0, $num = 10, $deprecated = '') + { + } + /** + * Deprecated functionality to retrieve a list of the most active sites. + * + * @since MU (3.0.0) + * @deprecated 3.0.0 + * + * @param int $num Optional. Number of activate blogs to retrieve. Default 10. + * @param bool $display Optional. Whether or not to display the most active blogs list. Default true. + * @return array List of "most active" sites. + */ + function get_most_active_blogs($num = 10, $display = \true) + { + } + /** + * Redirect a user based on $_GET or $_POST arguments. + * + * The function looks for redirect arguments in the following order: + * 1) $_GET['ref'] + * 2) $_POST['ref'] + * 3) $_SERVER['HTTP_REFERER'] + * 4) $_GET['redirect'] + * 5) $_POST['redirect'] + * 6) $url + * + * @since MU (3.0.0) + * @deprecated 3.3.0 Use wp_redirect() + * @see wp_redirect() + * + * @param string $url Optional. Redirect URL. Default empty. + */ + function wpmu_admin_do_redirect($url = '') + { + } + /** + * Adds an 'updated=true' argument to a URL. + * + * @since MU (3.0.0) + * @deprecated 3.3.0 Use add_query_arg() + * @see add_query_arg() + * + * @param string $url Optional. Redirect URL. Default empty. + * @return string + */ + function wpmu_admin_redirect_add_updated_param($url = '') + { + } + /** + * Get a numeric user ID from either an email address or a login. + * + * A numeric string is considered to be an existing user ID + * and is simply returned as such. + * + * @since MU (3.0.0) + * @deprecated 3.6.0 Use get_user_by() + * @see get_user_by() + * + * @param string $string Either an email address or a login. + * @return int + */ + function get_user_id_from_string($string) + { + } + /** + * Get a full blog URL, given a domain and a path. + * + * @since MU (3.0.0) + * @deprecated 3.7.0 + * + * @param string $domain + * @param string $path + * @return string + */ + function get_blogaddress_by_domain($domain, $path) + { + } + /** + * Create an empty blog. + * + * @since MU (3.0.0) + * @deprecated 4.4.0 + * + * @param string $domain The new blog's domain. + * @param string $path The new blog's path. + * @param string $weblog_title The new blog's title. + * @param int $site_id Optional. Defaults to 1. + * @return string|int The ID of the newly created blog + */ + function create_empty_blog($domain, $path, $weblog_title, $site_id = 1) + { + } + /** + * Get the admin for a domain/path combination. + * + * @since MU (3.0.0) + * @deprecated 4.4.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $domain Optional. Network domain. + * @param string $path Optional. Network path. + * @return array|false The network admins. + */ + function get_admin_users_for_domain($domain = '', $path = '') + { + } + /** + * Return an array of sites for a network or networks. + * + * @since 3.7.0 + * @deprecated 4.6.0 Use get_sites() + * @see get_sites() + * + * @param array $args { + * Array of default arguments. Optional. + * + * @type int|int[] $network_id A network ID or array of network IDs. Set to null to retrieve sites + * from all networks. Defaults to current network ID. + * @type int $public Retrieve public or non-public sites. Default null, for any. + * @type int $archived Retrieve archived or non-archived sites. Default null, for any. + * @type int $mature Retrieve mature or non-mature sites. Default null, for any. + * @type int $spam Retrieve spam or non-spam sites. Default null, for any. + * @type int $deleted Retrieve deleted or non-deleted sites. Default null, for any. + * @type int $limit Number of sites to limit the query to. Default 100. + * @type int $offset Exclude the first x sites. Used in combination with the $limit parameter. Default 0. + * } + * @return array[] An empty array if the installation is considered "large" via wp_is_large_network(). Otherwise, + * an associative array of WP_Site data as arrays. + * @phpstan-param array{ + * network_id?: int|int[], + * public?: int, + * archived?: int, + * mature?: int, + * spam?: int, + * deleted?: int, + * limit?: int, + * offset?: int, + * } $args + */ + function wp_get_sites($args = array()) + { + } + /** + * Check whether a usermeta key has to do with the current blog. + * + * @since MU (3.0.0) + * @deprecated 4.9.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $key + * @param int $user_id Optional. Defaults to current user. + * @param int $blog_id Optional. Defaults to current blog. + * @return bool + */ + function is_user_option_local($key, $user_id = 0, $blog_id = 0) + { + } + /** + * Store basic site info in the blogs table. + * + * This function creates a row in the wp_blogs table and returns + * the new blog's ID. It is the first step in creating a new blog. + * + * @since MU (3.0.0) + * @deprecated 5.1.0 Use wp_insert_site() + * @see wp_insert_site() + * + * @param string $domain The domain of the new site. + * @param string $path The path of the new site. + * @param int $site_id Unless you're running a multi-network install, be sure to set this value to 1. + * @return int|false The ID of the new row + */ + function insert_blog($domain, $path, $site_id) + { + } + /** + * Install an empty blog. + * + * Creates the new blog tables and options. If calling this function + * directly, be sure to use switch_to_blog() first, so that $wpdb + * points to the new blog. + * + * @since MU (3.0.0) + * @deprecated 5.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global WP_Roles $wp_roles WordPress role management object. + * + * @param int $blog_id The value returned by wp_insert_site(). + * @param string $blog_title The title of the new site. + */ + function install_blog($blog_id, $blog_title = '') + { + } + /** + * Set blog defaults. + * + * This function creates a row in the wp_blogs table. + * + * @since MU (3.0.0) + * @deprecated MU + * @deprecated Use wp_install_defaults() + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $blog_id Ignored in this function. + * @param int $user_id + */ + function install_blog_defaults($blog_id, $user_id) + { + } + /** + * Update the status of a user in the database. + * + * Previously used in core to mark a user as spam or "ham" (not spam) in Multisite. + * + * @since 3.0.0 + * @deprecated 5.3.0 Use wp_update_user() + * @see wp_update_user() + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $id The user ID. + * @param string $pref The column in the wp_users table to update the user's status + * in (presumably user_status, spam, or deleted). + * @param int $value The new status for the user. + * @param null $deprecated Deprecated as of 3.0.2 and should not be used. + * @return int The initially passed $value. + */ + function update_user_status($id, $pref, $value, $deprecated = \null) + { + } + /** + * Maintains a canonical list of terms by syncing terms created for each blog with the global terms table. + * + * @since 3.0.0 + * @since 6.1.0 This function no longer does anything. + * @deprecated 6.1.0 + * + * @param int $term_id An ID for a term on the current blog. + * @param string $deprecated Not used. + * @return int An ID from the global terms table mapped from $term_id. + */ + function global_terms($term_id, $deprecated = '') + { + } + /** + * Multisite WordPress API + * + * @package WordPress + * @subpackage Multisite + * @since 3.0.0 + */ + /** + * Gets the network's site and user counts. + * + * @since MU (3.0.0) + * + * @return int[] { + * Site and user count for the network. + * + * @type int $blogs Number of sites on the network. + * @type int $users Number of users on the network. + * } + * @phpstan-return array{ + * blogs: int, + * users: int, + * } + */ + function get_sitestats() + { + } + /** + * Gets one of a user's active blogs. + * + * Returns the user's primary blog, if they have one and + * it is active. If it's inactive, function returns another + * active blog of the user. If none are found, the user + * is added as a Subscriber to the Dashboard Blog and that blog + * is returned. + * + * @since MU (3.0.0) + * + * @param int $user_id The unique ID of the user + * @return WP_Site|void The blog object + */ + function get_active_blog_for_user($user_id) + { + } + /** + * Gets the number of active sites on the installation. + * + * The count is cached and updated twice daily. This is not a live count. + * + * @since MU (3.0.0) + * @since 3.7.0 The `$network_id` parameter has been deprecated. + * @since 4.8.0 The `$network_id` parameter is now being used. + * + * @param int|null $network_id ID of the network. Default is the current network. + * @return int Number of active sites on the network. + */ + function get_blog_count($network_id = \null) + { + } + /** + * Gets a blog post from any site on the network. + * + * This function is similar to get_post(), except that it can retrieve a post + * from any site on the network, not just the current site. + * + * @since MU (3.0.0) + * + * @param int $blog_id ID of the blog. + * @param int $post_id ID of the post being looked for. + * @return WP_Post|null WP_Post object on success, null on failure + */ + function get_blog_post($blog_id, $post_id) + { + } + /** + * Adds a user to a blog, along with specifying the user's role. + * + * Use the {@see 'add_user_to_blog'} action to fire an event when users are added to a blog. + * + * @since MU (3.0.0) + * + * @param int $blog_id ID of the blog the user is being added to. + * @param int $user_id ID of the user being added. + * @param string $role The role you want the user to have. + * @return true|WP_Error True on success or a WP_Error object if the user doesn't exist + * or could not be added. + */ + function add_user_to_blog($blog_id, $user_id, $role) + { + } + /** + * Removes a user from a blog. + * + * Use the {@see 'remove_user_from_blog'} action to fire an event when + * users are removed from a blog. + * + * Accepts an optional `$reassign` parameter, if you want to + * reassign the user's blog posts to another user upon removal. + * + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $user_id ID of the user being removed. + * @param int $blog_id Optional. ID of the blog the user is being removed from. Default 0. + * @param int $reassign Optional. ID of the user to whom to reassign posts. Default 0. + * @return true|WP_Error True on success or a WP_Error object if the user doesn't exist. + */ + function remove_user_from_blog($user_id, $blog_id = 0, $reassign = 0) + { + } + /** + * Gets the permalink for a post on another blog. + * + * @since MU (3.0.0) 1.0 + * + * @param int $blog_id ID of the source blog. + * @param int $post_id ID of the desired post. + * @return string The post's permalink + */ + function get_blog_permalink($blog_id, $post_id) + { + } + /** + * Gets a blog's numeric ID from its URL. + * + * On a subdirectory installation like example.com/blog1/, + * $domain will be the root 'example.com' and $path the + * subdirectory '/blog1/'. With subdomains like blog1.example.com, + * $domain is 'blog1.example.com' and $path is '/'. + * + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $domain + * @param string $path Optional. Not required for subdomain installations. + * @return int 0 if no blog found, otherwise the ID of the matching blog + */ + function get_blog_id_from_url($domain, $path = '/') + { + } + // + // Admin functions. + // + /** + * Checks an email address against a list of banned domains. + * + * This function checks against the Banned Email Domains list + * at wp-admin/network/settings.php. The check is only run on + * self-registrations; user creation at wp-admin/network/users.php + * bypasses this check. + * + * @since MU (3.0.0) + * + * @param string $user_email The email provided by the user at registration. + * @return bool True when the email address is banned, false otherwise. + */ + function is_email_address_unsafe($user_email) + { + } + /** + * Sanitizes and validates data required for a user sign-up. + * + * Verifies the validity and uniqueness of user names and user email addresses, + * and checks email addresses against allowed and disallowed domains provided by + * administrators. + * + * The {@see 'wpmu_validate_user_signup'} hook provides an easy way to modify the sign-up + * process. The value $result, which is passed to the hook, contains both the user-provided + * info and the error messages created by the function. {@see 'wpmu_validate_user_signup'} + * allows you to process the data in any way you'd like, and unset the relevant errors if + * necessary. + * + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $user_name The login name provided by the user. + * @param string $user_email The email provided by the user. + * @return array { + * The array of user name, email, and the error messages. + * + * @type string $user_name Sanitized and unique username. + * @type string $orig_username Original username. + * @type string $user_email User email address. + * @type WP_Error $errors WP_Error object containing any errors found. + * } + * @phpstan-return array{ + * user_name: string, + * orig_username: string, + * user_email: string, + * errors: WP_Error, + * } + */ + function wpmu_validate_user_signup($user_name, $user_email) + { + } + /** + * Processes new site registrations. + * + * Checks the data provided by the user during blog signup. Verifies + * the validity and uniqueness of blog paths and domains. + * + * This function prevents the current user from registering a new site + * with a blogname equivalent to another user's login name. Passing the + * $user parameter to the function, where $user is the other user, is + * effectively an override of this limitation. + * + * Filter {@see 'wpmu_validate_blog_signup'} if you want to modify + * the way that WordPress validates new site signups. + * + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global string $domain + * + * @param string $blogname The blog name provided by the user. Must be unique. + * @param string $blog_title The blog title provided by the user. + * @param WP_User|string $user Optional. The user object to check against the new site name. + * @return array { + * Array of domain, path, blog name, blog title, user and error messages. + * + * @type string $domain Domain for the site. + * @type string $path Path for the site. Used in subdirectory installations. + * @type string $blogname The unique site name (slug). + * @type string $blog_title Blog title. + * @type string|WP_User $user By default, an empty string. A user object if provided. + * @type WP_Error $errors WP_Error containing any errors found. + * } + * @phpstan-return array{ + * domain: string, + * path: string, + * blogname: string, + * blog_title: string, + * user: string|WP_User, + * errors: WP_Error, + * } + */ + function wpmu_validate_blog_signup($blogname, $blog_title, $user = '') + { + } + /** + * Records site signup information for future activation. + * + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $domain The requested domain. + * @param string $path The requested path. + * @param string $title The requested site title. + * @param string $user The user's requested login name. + * @param string $user_email The user's email address. + * @param array $meta Optional. Signup meta data. By default, contains the requested privacy setting and lang_id. + */ + function wpmu_signup_blog($domain, $path, $title, $user, $user_email, $meta = array()) + { + } + /** + * Records user signup information for future activation. + * + * This function is used when user registration is open but + * new site registration is not. + * + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $user The user's requested login name. + * @param string $user_email The user's email address. + * @param array $meta Optional. Signup meta data. Default empty array. + */ + function wpmu_signup_user($user, $user_email, $meta = array()) + { + } + /** + * Sends a confirmation request email to a user when they sign up for a new site. The new site will not become active + * until the confirmation link is clicked. + * + * This is the notification function used when site registration + * is enabled. + * + * Filter {@see 'wpmu_signup_blog_notification'} to bypass this function or + * replace it with your own notification behavior. + * + * Filter {@see 'wpmu_signup_blog_notification_email'} and + * {@see 'wpmu_signup_blog_notification_subject'} to change the content + * and subject line of the email sent to newly registered users. + * + * @since MU (3.0.0) + * + * @param string $domain The new blog domain. + * @param string $path The new blog path. + * @param string $title The site title. + * @param string $user_login The user's login name. + * @param string $user_email The user's email address. + * @param string $key The activation key created in wpmu_signup_blog() + * @param array $meta Optional. Signup meta data. By default, contains the requested privacy setting and lang_id. + * @return bool + */ + function wpmu_signup_blog_notification($domain, $path, $title, $user_login, $user_email, $key, $meta = array()) + { + } + /** + * Sends a confirmation request email to a user when they sign up for a new user account (without signing up for a site + * at the same time). The user account will not become active until the confirmation link is clicked. + * + * This is the notification function used when no new site has + * been requested. + * + * Filter {@see 'wpmu_signup_user_notification'} to bypass this function or + * replace it with your own notification behavior. + * + * Filter {@see 'wpmu_signup_user_notification_email'} and + * {@see 'wpmu_signup_user_notification_subject'} to change the content + * and subject line of the email sent to newly registered users. + * + * @since MU (3.0.0) + * + * @param string $user_login The user's login name. + * @param string $user_email The user's email address. + * @param string $key The activation key created in wpmu_signup_user() + * @param array $meta Optional. Signup meta data. Default empty array. + * @return bool + */ + function wpmu_signup_user_notification($user_login, $user_email, $key, $meta = array()) + { + } + /** + * Activates a signup. + * + * Hook to {@see 'wpmu_activate_user'} or {@see 'wpmu_activate_blog'} for events + * that should happen only when users or sites are self-created (since + * those actions are not called when users and sites are created + * by a Super Admin). + * + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $key The activation key provided to the user. + * @return array|WP_Error An array containing information about the activated user and/or blog + */ + function wpmu_activate_signup($key) + { + } + /** + * Deletes an associated signup entry when a user is deleted from the database. + * + * @since 5.5.0 + * + * @param int $id ID of the user to delete. + * @param int|null $reassign ID of the user to reassign posts and links to. + * @param WP_User $user User object. + */ + function wp_delete_signup_on_user_delete($id, $reassign, $user) + { + } + /** + * Creates a user. + * + * This function runs when a user self-registers as well as when + * a Super Admin creates a new user. Hook to {@see 'wpmu_new_user'} for events + * that should affect all new users, but only on Multisite (otherwise + * use {@see 'user_register'}). + * + * @since MU (3.0.0) + * + * @param string $user_name The new user's login name. + * @param string $password The new user's password. + * @param string $email The new user's email address. + * @return int|false Returns false on failure, or int $user_id on success + */ + function wpmu_create_user($user_name, $password, $email) + { + } + /** + * Creates a site. + * + * This function runs when a user self-registers a new site as well + * as when a Super Admin creates a new site. Hook to {@see 'wpmu_new_blog'} + * for events that should affect all new sites. + * + * On subdirectory installations, $domain is the same as the main site's + * domain, and the path is the subdirectory name (eg 'example.com' + * and '/blog1/'). On subdomain installations, $domain is the new subdomain + + * root domain (eg 'blog1.example.com'), and $path is '/'. + * + * @since MU (3.0.0) + * + * @param string $domain The new site's domain. + * @param string $path The new site's path. + * @param string $title The new site's title. + * @param int $user_id The user ID of the new site's admin. + * @param array $options Optional. Array of key=>value pairs used to set initial site options. + * If valid status keys are included ('public', 'archived', 'mature', + * 'spam', 'deleted', or 'lang_id') the given site status(es) will be + * updated. Otherwise, keys and values will be used to set options for + * the new site. Default empty array. + * @param int $network_id Optional. Network ID. Only relevant on multi-network installations. + * @return int|WP_Error Returns WP_Error object on failure, the new site ID on success. + */ + function wpmu_create_blog($domain, $path, $title, $user_id, $options = array(), $network_id = 1) + { + } + /** + * Notifies the network admin that a new site has been activated. + * + * Filter {@see 'newblog_notify_siteadmin'} to change the content of + * the notification email. + * + * @since MU (3.0.0) + * @since 5.1.0 $blog_id now supports input from the {@see 'wp_initialize_site'} action. + * + * @param WP_Site|int $blog_id The new site's object or ID. + * @param string $deprecated Not used. + * @return bool + */ + function newblog_notify_siteadmin($blog_id, $deprecated = '') + { + } + /** + * Notifies the network admin that a new user has been activated. + * + * Filter {@see 'newuser_notify_siteadmin'} to change the content of + * the notification email. + * + * @since MU (3.0.0) + * + * @param int $user_id The new user's ID. + * @return bool + */ + function newuser_notify_siteadmin($user_id) + { + } + /** + * Checks whether a site name is already taken. + * + * The name is the site's subdomain or the site's subdirectory + * path depending on the network settings. + * + * Used during the new site registration process to ensure + * that each site name is unique. + * + * @since MU (3.0.0) + * + * @param string $domain The domain to be checked. + * @param string $path The path to be checked. + * @param int $network_id Optional. Network ID. Relevant only on multi-network installations. + * @return int|null The site ID if the site name exists, null otherwise. + */ + function domain_exists($domain, $path, $network_id = 1) + { + } + /** + * Notifies the site administrator that their site activation was successful. + * + * Filter {@see 'wpmu_welcome_notification'} to disable or bypass. + * + * Filter {@see 'update_welcome_email'} and {@see 'update_welcome_subject'} to + * modify the content and subject line of the notification email. + * + * @since MU (3.0.0) + * + * @param int $blog_id Site ID. + * @param int $user_id User ID. + * @param string $password User password, or "N/A" if the user account is not new. + * @param string $title Site title. + * @param array $meta Optional. Signup meta data. By default, contains the requested privacy setting and lang_id. + * @return bool Whether the email notification was sent. + */ + function wpmu_welcome_notification($blog_id, $user_id, $password, $title, $meta = array()) + { + } + /** + * Notifies the Multisite network administrator that a new site was created. + * + * Filter {@see 'send_new_site_email'} to disable or bypass. + * + * Filter {@see 'new_site_email'} to filter the contents. + * + * @since 5.6.0 + * + * @param int $site_id Site ID of the new site. + * @param int $user_id User ID of the administrator of the new site. + * @return bool Whether the email notification was sent. + */ + function wpmu_new_site_admin_notification($site_id, $user_id) + { + } + /** + * Notifies a user that their account activation has been successful. + * + * Filter {@see 'wpmu_welcome_user_notification'} to disable or bypass. + * + * Filter {@see 'update_welcome_user_email'} and {@see 'update_welcome_user_subject'} to + * modify the content and subject line of the notification email. + * + * @since MU (3.0.0) + * + * @param int $user_id User ID. + * @param string $password User password. + * @param array $meta Optional. Signup meta data. Default empty array. + * @return bool + */ + function wpmu_welcome_user_notification($user_id, $password, $meta = array()) + { + } + /** + * Gets the current network. + * + * Returns an object containing the 'id', 'domain', 'path', and 'site_name' + * properties of the network being viewed. + * + * @see wpmu_current_site() + * + * @since MU (3.0.0) + * + * @global WP_Network $current_site + * + * @return WP_Network + */ + function get_current_site() + { + } + /** + * Gets a user's most recent post. + * + * Walks through each of a user's blogs to find the post with + * the most recent post_date_gmt. + * + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $user_id + * @return array Contains the blog_id, post_id, post_date_gmt, and post_gmt_ts + */ + function get_most_recent_post_of_user($user_id) + { + } + // + // Misc functions. + // + /** + * Checks an array of MIME types against a list of allowed types. + * + * WordPress ships with a set of allowed upload filetypes, + * which is defined in wp-includes/functions.php in + * get_allowed_mime_types(). This function is used to filter + * that list against the filetypes allowed provided by Multisite + * Super Admins at wp-admin/network/settings.php. + * + * @since MU (3.0.0) + * + * @param array $mimes + * @return array + */ + function check_upload_mimes($mimes) + { + } + /** + * Updates a blog's post count. + * + * WordPress MS stores a blog's post count as an option so as + * to avoid extraneous COUNTs when a blog's details are fetched + * with get_site(). This function is called when posts are published + * or unpublished to make sure the count stays current. + * + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $deprecated Not used. + */ + function update_posts_count($deprecated = '') + { + } + /** + * Logs the user email, IP, and registration date of a new site. + * + * @since MU (3.0.0) + * @since 5.1.0 Parameters now support input from the {@see 'wp_initialize_site'} action. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param WP_Site|int $blog_id The new site's object or ID. + * @param int|array $user_id User ID, or array of arguments including 'user_id'. + */ + function wpmu_log_new_registrations($blog_id, $user_id) + { + } + /** + * Ensures that the current site's domain is listed in the allowed redirect host list. + * + * @see wp_validate_redirect() + * @since MU (3.0.0) + * + * @param array|string $deprecated Not used. + * @return string[] { + * An array containing the current site's domain. + * + * @type string $0 The current site's domain. + * } + * @phpstan-return array{ + * 0: string, + * } + */ + function redirect_this_site($deprecated = '') + { + } + /** + * Checks whether an upload is too big. + * + * @since MU (3.0.0) + * + * @blessed + * + * @param array $upload + * @return string|array If the upload is under the size limit, $upload is returned. Otherwise returns an error message. + */ + function upload_is_file_too_big($upload) + { + } + /** + * Adds a nonce field to the signup page. + * + * @since MU (3.0.0) + */ + function signup_nonce_fields() + { + } + /** + * Processes the signup nonce created in signup_nonce_fields(). + * + * @since MU (3.0.0) + * + * @param array $result + * @return array + */ + function signup_nonce_check($result) + { + } + /** + * Corrects 404 redirects when NOBLOGREDIRECT is defined. + * + * @since MU (3.0.0) + */ + function maybe_redirect_404() + { + } + /** + * Adds a new user to a blog by visiting /newbloguser/{key}/. + * + * This will only work when the user's details are saved as an option + * keyed as 'new_user_{key}', where '{key}' is a hash generated for the user to be + * added, as when a user is invited through the regular WP Add User interface. + * + * @since MU (3.0.0) + */ + function maybe_add_existing_user_to_blog() + { + } + /** + * Adds a user to a blog based on details from maybe_add_existing_user_to_blog(). + * + * @since MU (3.0.0) + * + * @param array|false $details { + * User details. Must at least contain values for the keys listed below. + * + * @type int $user_id The ID of the user being added to the current blog. + * @type string $role The role to be assigned to the user. + * } + * @return true|WP_Error|void True on success or a WP_Error object if the user doesn't exist + * or could not be added. Void if $details array was not provided. + * @phpstan-param false|array{ + * user_id?: int, + * role?: string, + * } $details + */ + function add_existing_user_to_blog($details = \false) + { + } + /** + * Adds a newly created user to the appropriate blog + * + * To add a user in general, use add_user_to_blog(). This function + * is specifically hooked into the {@see 'wpmu_activate_user'} action. + * + * @since MU (3.0.0) + * + * @see add_user_to_blog() + * + * @param int $user_id User ID. + * @param string $password User password. Ignored. + * @param array $meta Signup meta data. + */ + function add_new_user_to_blog($user_id, $password, $meta) + { + } + /** + * Corrects From host on outgoing mail to match the site domain + * + * @since MU (3.0.0) + * + * @param PHPMailer $phpmailer The PHPMailer instance (passed by reference). + */ + function fix_phpmailer_messageid($phpmailer) + { + } + /** + * Determines whether a user is marked as a spammer, based on user login. + * + * @since MU (3.0.0) + * + * @param string|WP_User $user Optional. Defaults to current user. WP_User object, + * or user login name as a string. + * @return bool + */ + function is_user_spammy($user = \null) + { + } + /** + * Updates this blog's 'public' setting in the global blogs table. + * + * Public blogs have a setting of 1, private blogs are 0. + * + * @since MU (3.0.0) + * + * @param int $old_value + * @param int $value The new public value + */ + function update_blog_public($old_value, $value) + { + } + /** + * Determines whether users can self-register, based on Network settings. + * + * @since MU (3.0.0) + * + * @return bool + */ + function users_can_register_signup_filter() + { + } + /** + * Ensures that the welcome message is not empty. Currently unused. + * + * @since MU (3.0.0) + * + * @param string $text + * @return string + */ + function welcome_user_msg_filter($text) + { + } + /** + * Determines whether to force SSL on content. + * + * @since 2.8.5 + * + * @param bool $force + * @return bool True if forced, false if not forced. + */ + function force_ssl_content($force = '') + { + } + /** + * Formats a URL to use https. + * + * Useful as a filter. + * + * @since 2.8.5 + * + * @param string $url URL + * @return string URL with https as the scheme + */ + function filter_SSL($url) + { + } + /** + * Schedules update of the network-wide counts for the current network. + * + * @since 3.1.0 + */ + function wp_schedule_update_network_counts() + { + } + /** + * Updates the network-wide counts for the current network. + * + * @since 3.1.0 + * @since 4.8.0 The `$network_id` parameter has been added. + * + * @param int|null $network_id ID of the network. Default is the current network. + */ + function wp_update_network_counts($network_id = \null) + { + } + /** + * Updates the count of sites for the current network. + * + * If enabled through the {@see 'enable_live_network_counts'} filter, update the sites count + * on a network when a site is created or its status is updated. + * + * @since 3.7.0 + * @since 4.8.0 The `$network_id` parameter has been added. + * + * @param int|null $network_id ID of the network. Default is the current network. + */ + function wp_maybe_update_network_site_counts($network_id = \null) + { + } + /** + * Updates the network-wide users count. + * + * If enabled through the {@see 'enable_live_network_counts'} filter, update the users count + * on a network when a user is created or its status is updated. + * + * @since 3.7.0 + * @since 4.8.0 The `$network_id` parameter has been added. + * + * @param int|null $network_id ID of the network. Default is the current network. + */ + function wp_maybe_update_network_user_counts($network_id = \null) + { + } + /** + * Updates the network-wide site count. + * + * @since 3.7.0 + * @since 4.8.0 The `$network_id` parameter has been added. + * + * @param int|null $network_id ID of the network. Default is the current network. + */ + function wp_update_network_site_counts($network_id = \null) + { + } + /** + * Updates the network-wide user count. + * + * @since 3.7.0 + * @since 4.8.0 The `$network_id` parameter has been added. + * @since 6.0.0 This function is now a wrapper for wp_update_user_counts(). + * + * @param int|null $network_id ID of the network. Default is the current network. + */ + function wp_update_network_user_counts($network_id = \null) + { + } + /** + * Returns the space used by the current site. + * + * @since 3.5.0 + * + * @return int Used space in megabytes. + */ + function get_space_used() + { + } + /** + * Returns the upload quota for the current blog. + * + * @since MU (3.0.0) + * + * @return int Quota in megabytes + */ + function get_space_allowed() + { + } + /** + * Determines if there is any upload space left in the current blog's quota. + * + * @since 3.0.0 + * + * @return int of upload space available in bytes + */ + function get_upload_space_available() + { + } + /** + * Determines if there is any upload space left in the current blog's quota. + * + * @since 3.0.0 + * @return bool True if space is available, false otherwise. + */ + function is_upload_space_available() + { + } + /** + * Filters the maximum upload file size allowed, in bytes. + * + * @since 3.0.0 + * + * @param int $size Upload size limit in bytes. + * @return int Upload size limit in bytes. + */ + function upload_size_limit_filter($size) + { + } + /** + * Determines whether or not we have a large network. + * + * The default criteria for a large network is either more than 10,000 users or more than 10,000 sites. + * Plugins can alter this criteria using the {@see 'wp_is_large_network'} filter. + * + * @since 3.3.0 + * @since 4.8.0 The `$network_id` parameter has been added. + * + * @param string $using 'sites or 'users'. Default is 'sites'. + * @param int|null $network_id ID of the network. Default is the current network. + * @return bool True if the network meets the criteria for large. False otherwise. + */ + function wp_is_large_network($using = 'sites', $network_id = \null) + { + } + /** + * Retrieves a list of reserved site on a sub-directory Multisite installation. + * + * @since 4.4.0 + * + * @return string[] Array of reserved names. + */ + function get_subdirectory_reserved_names() + { + } + /** + * Sends a confirmation request email when a change of network admin email address is attempted. + * + * The new network admin address will not become active until confirmed. + * + * @since 4.9.0 + * + * @param string $old_value The old network admin email address. + * @param string $value The proposed new network admin email address. + */ + function update_network_option_new_admin_email($old_value, $value) + { + } + /** + * Sends an email to the old network admin email address when the network admin email address changes. + * + * @since 4.9.0 + * + * @param string $option_name The relevant database option name. + * @param string $new_email The new network admin email address. + * @param string $old_email The old network admin email address. + * @param int $network_id ID of the network. + */ + function wp_network_admin_email_change_notification($option_name, $new_email, $old_email, $network_id) + { + } + /** + * These functions are needed to load Multisite. + * + * @since 3.0.0 + * + * @package WordPress + * @subpackage Multisite + */ + /** + * Whether a subdomain configuration is enabled. + * + * @since 3.0.0 + * + * @return bool True if subdomain configuration is enabled, false otherwise. + */ + function is_subdomain_install() + { + } + /** + * Returns array of network plugin files to be included in global scope. + * + * The default directory is wp-content/plugins. To change the default directory + * manually, define `WP_PLUGIN_DIR` and `WP_PLUGIN_URL` in `wp-config.php`. + * + * @access private + * @since 3.1.0 + * + * @return string[] Array of absolute paths to files to include. + */ + function wp_get_active_network_plugins() + { + } + /** + * Checks status of current blog. + * + * Checks if the blog is deleted, inactive, archived, or spammed. + * + * Dies with a default message if the blog does not pass the check. + * + * To change the default message when a blog does not pass the check, + * use the wp-content/blog-deleted.php, blog-inactive.php and + * blog-suspended.php drop-ins. + * + * @since 3.0.0 + * + * @return true|string Returns true on success, or drop-in file to include. + */ + function ms_site_check() + { + } + /** + * Retrieves the closest matching network for a domain and path. + * + * @since 3.9.0 + * + * @internal In 4.4.0, converted to a wrapper for WP_Network::get_by_path() + * + * @param string $domain Domain to check. + * @param string $path Path to check. + * @param int|null $segments Path segments to use. Defaults to null, or the full path. + * @return WP_Network|false Network object if successful. False when no network is found. + */ + function get_network_by_path($domain, $path, $segments = \null) + { + } + /** + * Retrieves the closest matching site object by its domain and path. + * + * This will not necessarily return an exact match for a domain and path. Instead, it + * breaks the domain and path into pieces that are then used to match the closest + * possibility from a query. + * + * The intent of this method is to match a site object during bootstrap for a + * requested site address + * + * @since 3.9.0 + * @since 4.7.0 Updated to always return a `WP_Site` object. + * + * @param string $domain Domain to check. + * @param string $path Path to check. + * @param int|null $segments Path segments to use. Defaults to null, or the full path. + * @return WP_Site|false Site object if successful. False when no site is found. + */ + function get_site_by_path($domain, $path, $segments = \null) + { + } + /** + * Identifies the network and site of a requested domain and path and populates the + * corresponding network and site global objects as part of the multisite bootstrap process. + * + * Prior to 4.6.0, this was a procedural block in `ms-settings.php`. It was wrapped into + * a function to facilitate unit tests. It should not be used outside of core. + * + * Usually, it's easier to query the site first, which then declares its network. + * In limited situations, we either can or must find the network first. + * + * If a network and site are found, a `true` response will be returned so that the + * request can continue. + * + * If neither a network or site is found, `false` or a URL string will be returned + * so that either an error can be shown or a redirect can occur. + * + * @since 4.6.0 + * @access private + * + * @global WP_Network $current_site The current network. + * @global WP_Site $current_blog The current site. + * + * @param string $domain The requested domain. + * @param string $path The requested path. + * @param bool $subdomain Optional. Whether a subdomain (true) or subdirectory (false) configuration. + * Default false. + * @return bool|string True if bootstrap successfully populated `$current_blog` and `$current_site`. + * False if bootstrap could not be properly completed. + * Redirect URL if parts exist, but the request as a whole can not be fulfilled. + */ + function ms_load_current_site_and_network($domain, $path, $subdomain = \false) + { + } + /** + * Displays a failure message. + * + * Used when a blog's tables do not exist. Checks for a missing $wpdb->site table as well. + * + * @access private + * @since 3.0.0 + * @since 4.4.0 The `$domain` and `$path` parameters were added. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $domain The requested domain for the error to reference. + * @param string $path The requested path for the error to reference. + */ + function ms_not_installed($domain, $path) + { + } + /** + * This deprecated function formerly set the site_name property of the $current_site object. + * + * This function simply returns the object, as before. + * The bootstrap takes care of setting site_name. + * + * @access private + * @since 3.0.0 + * @deprecated 3.9.0 Use get_current_site() instead. + * + * @param WP_Network $current_site + * @return WP_Network + */ + function get_current_site_name($current_site) + { + } + /** + * This deprecated function managed much of the site and network loading in multisite. + * + * The current bootstrap code is now responsible for parsing the site and network load as + * well as setting the global $current_site object. + * + * @access private + * @since 3.0.0 + * @deprecated 3.9.0 + * + * @global WP_Network $current_site + * + * @return WP_Network + */ + function wpmu_current_site() + { + } + /** + * Retrieves an object containing information about the requested network. + * + * @since 3.9.0 + * @deprecated 4.7.0 Use get_network() + * @see get_network() + * + * @internal In 4.6.0, converted to use get_network() + * + * @param object|int $network The network's database row or ID. + * @return WP_Network|false Object containing network information if found, false if not. + */ + function wp_get_network($network) + { + } + /** + * Network API + * + * @package WordPress + * @subpackage Multisite + * @since 5.1.0 + */ + /** + * Retrieves network data given a network ID or network object. + * + * Network data will be cached and returned after being passed through a filter. + * If the provided network is empty, the current network global will be used. + * + * @since 4.6.0 + * + * @global WP_Network $current_site + * + * @param WP_Network|int|null $network Optional. Network to retrieve. Default is the current network. + * @return WP_Network|null The network object or null if not found. + */ + function get_network($network = \null) + { + } + /** + * Retrieves a list of networks. + * + * @since 4.6.0 + * + * @param string|array $args Optional. Array or string of arguments. See WP_Network_Query::parse_query() + * for information on accepted arguments. Default empty array. + * @return array|int List of WP_Network objects, a list of network IDs when 'fields' is set to 'ids', + * or the number of networks when 'count' is passed as a query var. + */ + function get_networks($args = array()) + { + } + /** + * Removes a network from the object cache. + * + * @since 4.6.0 + * + * @global bool $_wp_suspend_cache_invalidation + * + * @param int|array $ids Network ID or an array of network IDs to remove from cache. + */ + function clean_network_cache($ids) + { + } + /** + * Updates the network cache of given networks. + * + * Will add the networks in $networks to the cache. If network ID already exists + * in the network cache then it will not be updated. The network is added to the + * cache using the network group with the key using the ID of the networks. + * + * @since 4.6.0 + * + * @param array $networks Array of network row objects. + */ + function update_network_cache($networks) + { + } + /** + * Adds any networks from the given IDs to the cache that do not already exist in cache. + * + * @since 4.6.0 + * @since 6.1.0 This function is no longer marked as "private". + * + * @see update_network_cache() + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $network_ids Array of network IDs. + */ + function _prime_network_caches($network_ids) + { + } + /** + * Site API + * + * @package WordPress + * @subpackage Multisite + * @since 5.1.0 + */ + /** + * Inserts a new site into the database. + * + * @since 5.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $data { + * Data for the new site that should be inserted. + * + * @type string $domain Site domain. Default empty string. + * @type string $path Site path. Default '/'. + * @type int $network_id The site's network ID. Default is the current network ID. + * @type string $registered When the site was registered, in SQL datetime format. Default is + * the current time. + * @type string $last_updated When the site was last updated, in SQL datetime format. Default is + * the value of $registered. + * @type int $public Whether the site is public. Default 1. + * @type int $archived Whether the site is archived. Default 0. + * @type int $mature Whether the site is mature. Default 0. + * @type int $spam Whether the site is spam. Default 0. + * @type int $deleted Whether the site is deleted. Default 0. + * @type int $lang_id The site's language ID. Currently unused. Default 0. + * @type int $user_id User ID for the site administrator. Passed to the + * `wp_initialize_site` hook. + * @type string $title Site title. Default is 'Site %d' where %d is the site ID. Passed + * to the `wp_initialize_site` hook. + * @type array $options Custom option $key => $value pairs to use. Default empty array. Passed + * to the `wp_initialize_site` hook. + * @type array $meta Custom site metadata $key => $value pairs to use. Default empty array. + * Passed to the `wp_initialize_site` hook. + * } + * @return int|WP_Error The new site's ID on success, or error object on failure. + * @phpstan-param array{ + * domain?: string, + * path?: string, + * network_id?: int, + * registered?: string, + * last_updated?: string, + * public?: int, + * archived?: int, + * mature?: int, + * spam?: int, + * deleted?: int, + * lang_id?: int, + * user_id?: int, + * title?: string, + * options?: array, + * meta?: array, + * } $data + */ + function wp_insert_site(array $data) + { + } + /** + * Updates a site in the database. + * + * @since 5.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $site_id ID of the site that should be updated. + * @param array $data Site data to update. See {@see wp_insert_site()} for the list of supported keys. + * @return int|WP_Error The updated site's ID on success, or error object on failure. + */ + function wp_update_site($site_id, array $data) + { + } + /** + * Deletes a site from the database. + * + * @since 5.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $site_id ID of the site that should be deleted. + * @return WP_Site|WP_Error The deleted site object on success, or error object on failure. + */ + function wp_delete_site($site_id) + { + } + /** + * Retrieves site data given a site ID or site object. + * + * Site data will be cached and returned after being passed through a filter. + * If the provided site is empty, the current site global will be used. + * + * @since 4.6.0 + * + * @param WP_Site|int|null $site Optional. Site to retrieve. Default is the current site. + * @return WP_Site|null The site object or null if not found. + */ + function get_site($site = \null) + { + } + /** + * Adds any sites from the given IDs to the cache that do not already exist in cache. + * + * @since 4.6.0 + * @since 5.1.0 Introduced the `$update_meta_cache` parameter. + * @since 6.1.0 This function is no longer marked as "private". + * + * @see update_site_cache() + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $ids ID list. + * @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true. + */ + function _prime_site_caches($ids, $update_meta_cache = \true) + { + } + /** + * Updates sites in cache. + * + * @since 4.6.0 + * @since 5.1.0 Introduced the `$update_meta_cache` parameter. + * + * @param array $sites Array of site objects. + * @param bool $update_meta_cache Whether to update site meta cache. Default true. + */ + function update_site_cache($sites, $update_meta_cache = \true) + { + } + /** + * Updates metadata cache for list of site IDs. + * + * Performs SQL query to retrieve all metadata for the sites matching `$site_ids` and stores them in the cache. + * Subsequent calls to `get_site_meta()` will not need to query the database. + * + * @since 5.1.0 + * + * @param array $site_ids List of site IDs. + * @return array|false An array of metadata on success, false if there is nothing to update. + */ + function update_sitemeta_cache($site_ids) + { + } + /** + * Retrieves a list of sites matching requested arguments. + * + * @since 4.6.0 + * @since 4.8.0 Introduced the 'lang_id', 'lang__in', and 'lang__not_in' parameters. + * + * @see WP_Site_Query::parse_query() + * + * @param string|array $args Optional. Array or string of arguments. See WP_Site_Query::__construct() + * for information on accepted arguments. Default empty array. + * @return array|int List of WP_Site objects, a list of site IDs when 'fields' is set to 'ids', + * or the number of sites when 'count' is passed as a query var. + * @phpstan-param array{ + * site__in?: int[], + * site__not_in?: int[], + * count?: bool, + * date_query?: array, + * fields?: string, + * ID?: int, + * number?: int, + * offset?: int, + * no_found_rows?: bool, + * orderby?: string|array, + * order?: string, + * network_id?: int, + * network__in?: int[], + * network__not_in?: int[], + * domain?: string, + * domain__in?: string[], + * domain__not_in?: string[], + * path?: string, + * path__in?: string[], + * path__not_in?: string[], + * public?: int, + * archived?: int, + * mature?: int, + * spam?: int, + * deleted?: int, + * lang_id?: int, + * lang__in?: string[], + * lang__not_in?: string[], + * search?: string, + * search_columns?: string[], + * update_site_cache?: bool, + * update_site_meta_cache?: bool, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * } $args See WP_Site_Query::__construct() + */ + function get_sites($args = array()) + { + } + /** + * Prepares site data for insertion or update in the database. + * + * @since 5.1.0 + * + * @param array $data Associative array of site data passed to the respective function. + * See {@see wp_insert_site()} for the possibly included data. + * @param array $defaults Site data defaults to parse $data against. + * @param WP_Site|null $old_site Optional. Old site object if an update, or null if an insertion. + * Default null. + * @return array|WP_Error Site data ready for a database transaction, or WP_Error in case a validation + * error occurred. + */ + function wp_prepare_site_data($data, $defaults, $old_site = \null) + { + } + /** + * Normalizes data for a site prior to inserting or updating in the database. + * + * @since 5.1.0 + * + * @param array $data Associative array of site data passed to the respective function. + * See {@see wp_insert_site()} for the possibly included data. + * @return array Normalized site data. + */ + function wp_normalize_site_data($data) + { + } + /** + * Validates data for a site prior to inserting or updating in the database. + * + * @since 5.1.0 + * + * @param WP_Error $errors Error object, passed by reference. Will contain validation errors if + * any occurred. + * @param array $data Associative array of complete site data. See {@see wp_insert_site()} + * for the included data. + * @param WP_Site|null $old_site The old site object if the data belongs to a site being updated, + * or null if it is a new site being inserted. + */ + function wp_validate_site_data($errors, $data, $old_site = \null) + { + } + /** + * Runs the initialization routine for a given site. + * + * This process includes creating the site's database tables and + * populating them with defaults. + * + * @since 5.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global WP_Roles $wp_roles WordPress role management object. + * + * @param int|WP_Site $site_id Site ID or object. + * @param array $args { + * Optional. Arguments to modify the initialization behavior. + * + * @type int $user_id Required. User ID for the site administrator. + * @type string $title Site title. Default is 'Site %d' where %d is the + * site ID. + * @type array $options Custom option $key => $value pairs to use. Default + * empty array. + * @type array $meta Custom site metadata $key => $value pairs to use. + * Default empty array. + * } + * @return true|WP_Error True on success, or error object on failure. + * @phpstan-param array{ + * user_id?: int, + * title?: string, + * options?: array, + * meta?: array, + * } $args + */ + function wp_initialize_site($site_id, array $args = array()) + { + } + /** + * Runs the uninitialization routine for a given site. + * + * This process includes dropping the site's database tables and deleting its uploads directory. + * + * @since 5.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|WP_Site $site_id Site ID or object. + * @return true|WP_Error True on success, or error object on failure. + */ + function wp_uninitialize_site($site_id) + { + } + /** + * Checks whether a site is initialized. + * + * A site is considered initialized when its database tables are present. + * + * @since 5.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|WP_Site $site_id Site ID or object. + * @return bool True if the site is initialized, false otherwise. + */ + function wp_is_site_initialized($site_id) + { + } + /** + * Clean the blog cache + * + * @since 3.5.0 + * + * @global bool $_wp_suspend_cache_invalidation + * + * @param WP_Site|int $blog The site object or ID to be cleared from cache. + */ + function clean_blog_cache($blog) + { + } + /** + * Adds metadata to a site. + * + * @since 5.1.0 + * + * @param int $site_id Site ID. + * @param string $meta_key Metadata name. + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. + * @param bool $unique Optional. Whether the same key should not be added. + * Default false. + * @return int|false Meta ID on success, false on failure. + */ + function add_site_meta($site_id, $meta_key, $meta_value, $unique = \false) + { + } + /** + * Removes metadata matching criteria from a site. + * + * You can match based on the key, or key and value. Removing based on key and + * value, will keep from removing duplicate metadata with the same key. It also + * allows removing all metadata matching key, if needed. + * + * @since 5.1.0 + * + * @param int $site_id Site ID. + * @param string $meta_key Metadata name. + * @param mixed $meta_value Optional. Metadata value. If provided, + * rows will only be removed that match the value. + * Must be serializable if non-scalar. Default empty. + * @return bool True on success, false on failure. + */ + function delete_site_meta($site_id, $meta_key, $meta_value = '') + { + } + /** + * Retrieves metadata for a site. + * + * @since 5.1.0 + * + * @param int $site_id Site ID. + * @param string $key Optional. The meta key to retrieve. By default, + * returns data for all keys. Default empty. + * @param bool $single Optional. Whether to return a single value. + * This parameter has no effect if `$key` is not specified. + * Default false. + * @return mixed An array of values if `$single` is false. + * The value of meta data field if `$single` is true. + * False for an invalid `$site_id` (non-numeric, zero, or negative value). + * An empty string if a valid but non-existing site ID is passed. + */ + function get_site_meta($site_id, $key = '', $single = \false) + { + } + /** + * Updates metadata for a site. + * + * Use the $prev_value parameter to differentiate between meta fields with the + * same key and site ID. + * + * If the meta field for the site does not exist, it will be added. + * + * @since 5.1.0 + * + * @param int $site_id Site ID. + * @param string $meta_key Metadata key. + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. + * @param mixed $prev_value Optional. Previous value to check before updating. + * If specified, only update existing metadata entries with + * this value. Otherwise, update all entries. Default empty. + * @return int|bool Meta ID if the key didn't exist, true on successful update, + * false on failure or if the value passed to the function + * is the same as the one that is already in the database. + */ + function update_site_meta($site_id, $meta_key, $meta_value, $prev_value = '') + { + } + /** + * Deletes everything from site meta matching meta key. + * + * @since 5.1.0 + * + * @param string $meta_key Metadata key to search for when deleting. + * @return bool Whether the site meta key was deleted from the database. + */ + function delete_site_meta_by_key($meta_key) + { + } + /** + * Updates the count of sites for a network based on a changed site. + * + * @since 5.1.0 + * + * @param WP_Site $new_site The site object that has been inserted, updated or deleted. + * @param WP_Site|null $old_site Optional. If $new_site has been updated, this must be the previous + * state of that site. Default null. + */ + function wp_maybe_update_network_site_counts_on_update($new_site, $old_site = \null) + { + } + /** + * Triggers actions on site status updates. + * + * @since 5.1.0 + * + * @param WP_Site $new_site The site object after the update. + * @param WP_Site|null $old_site Optional. If $new_site has been updated, this must be the previous + * state of that site. Default null. + */ + function wp_maybe_transition_site_statuses_on_update($new_site, $old_site = \null) + { + } + /** + * Cleans the necessary caches after specific site data has been updated. + * + * @since 5.1.0 + * + * @param WP_Site $new_site The site object after the update. + * @param WP_Site $old_site The site object prior to the update. + */ + function wp_maybe_clean_new_site_cache_on_update($new_site, $old_site) + { + } + /** + * Updates the `blog_public` option for a given site ID. + * + * @since 5.1.0 + * + * @param int $site_id Site ID. + * @param string $public The value of the site status. + */ + function wp_update_blog_public_option_on_site_update($site_id, $public) + { + } + /** + * Sets the last changed time for the 'sites' cache group. + * + * @since 5.1.0 + */ + function wp_cache_set_sites_last_changed() + { + } + /** + * Aborts calls to site meta if it is not supported. + * + * @since 5.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param mixed $check Skip-value for whether to proceed site meta function execution. + * @return mixed Original value of $check, or false if site meta is not supported. + */ + function wp_check_site_meta_support_prefilter($check) + { + } + /** + * Displays a navigation menu. + * + * @since 3.0.0 + * @since 4.7.0 Added the `item_spacing` argument. + * @since 5.5.0 Added the `container_aria_label` argument. + * + * @param array $args { + * Optional. Array of nav menu arguments. + * + * @type int|string|WP_Term $menu Desired menu. Accepts a menu ID, slug, name, or object. + * Default empty. + * @type string $menu_class CSS class to use for the ul element which forms the menu. + * Default 'menu'. + * @type string $menu_id The ID that is applied to the ul element which forms the menu. + * Default is the menu slug, incremented. + * @type string $container Whether to wrap the ul, and what to wrap it with. + * Default 'div'. + * @type string $container_class Class that is applied to the container. + * Default 'menu-{menu slug}-container'. + * @type string $container_id The ID that is applied to the container. Default empty. + * @type string $container_aria_label The aria-label attribute that is applied to the container + * when it's a nav element. Default empty. + * @type callable|false $fallback_cb If the menu doesn't exist, a callback function will fire. + * Default is 'wp_page_menu'. Set to false for no fallback. + * @type string $before Text before the link markup. Default empty. + * @type string $after Text after the link markup. Default empty. + * @type string $link_before Text before the link text. Default empty. + * @type string $link_after Text after the link text. Default empty. + * @type bool $echo Whether to echo the menu or return it. Default true. + * @type int $depth How many levels of the hierarchy are to be included. + * 0 means all. Default 0. + * Default 0. + * @type object $walker Instance of a custom walker class. Default empty. + * @type string $theme_location Theme location to be used. Must be registered with + * register_nav_menu() in order to be selectable by the user. + * @type string $items_wrap How the list items should be wrapped. Uses printf() format with + * numbered placeholders. Default is a ul with an id and class. + * @type string $item_spacing Whether to preserve whitespace within the menu's HTML. + * Accepts 'preserve' or 'discard'. Default 'preserve'. + * } + * @return void|string|false Void if 'echo' argument is true, menu output if 'echo' is false. + * False if there are no items or no menu was found. + * @phpstan-param array{ + * menu?: int|string|WP_Term, + * menu_class?: string, + * menu_id?: string, + * container?: string, + * container_class?: string, + * container_id?: string, + * container_aria_label?: string, + * fallback_cb?: callable|false, + * before?: string, + * after?: string, + * link_before?: string, + * link_after?: string, + * echo?: bool, + * depth?: int, + * walker?: object, + * theme_location?: string, + * items_wrap?: string, + * item_spacing?: string, + * } $args + */ + function wp_nav_menu($args = array()) + { + } + /** + * Adds the class property classes for the current context, if applicable. + * + * @access private + * @since 3.0.0 + * + * @global WP_Query $wp_query WordPress Query object. + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param array $menu_items The current menu item objects to which to add the class property information. + */ + function _wp_menu_item_classes_by_context(&$menu_items) + { + } + /** + * Retrieves the HTML list content for nav menu items. + * + * @uses Walker_Nav_Menu to create HTML list content. + * @since 3.0.0 + * + * @param array $items The menu items, sorted by each menu item's menu order. + * @param int $depth Depth of the item in reference to parents. + * @param stdClass $args An object containing wp_nav_menu() arguments. + * @return string The HTML list content for the menu items. + */ + function walk_nav_menu_tree($items, $depth, $args) + { + } + /** + * Prevents a menu item ID from being used more than once. + * + * @since 3.0.1 + * @access private + * + * @param string $id + * @param object $item + * @return string + */ + function _nav_menu_item_id_use_once($id, $item) + { + } + /** + * Navigation Menu functions + * + * @package WordPress + * @subpackage Nav_Menus + * @since 3.0.0 + */ + /** + * Returns a navigation menu object. + * + * @since 3.0.0 + * + * @param int|string|WP_Term $menu Menu ID, slug, name, or object. + * @return WP_Term|false Menu object on success, false if $menu param isn't supplied or term does not exist. + */ + function wp_get_nav_menu_object($menu) + { + } + /** + * Determines whether the given ID is a navigation menu. + * + * Returns true if it is; false otherwise. + * + * @since 3.0.0 + * + * @param int|string|WP_Term $menu Menu ID, slug, name, or object of menu to check. + * @return bool Whether the menu exists. + */ + function is_nav_menu($menu) + { + } + /** + * Registers navigation menu locations for a theme. + * + * @since 3.0.0 + * + * @global array $_wp_registered_nav_menus + * + * @param string[] $locations Associative array of menu location identifiers (like a slug) and descriptive text. + */ + function register_nav_menus($locations = array()) + { + } + /** + * Unregisters a navigation menu location for a theme. + * + * @since 3.1.0 + * + * @global array $_wp_registered_nav_menus + * + * @param string $location The menu location identifier. + * @return bool True on success, false on failure. + */ + function unregister_nav_menu($location) + { + } + /** + * Registers a navigation menu location for a theme. + * + * @since 3.0.0 + * + * @param string $location Menu location identifier, like a slug. + * @param string $description Menu location descriptive text. + */ + function register_nav_menu($location, $description) + { + } + /** + * Retrieves all registered navigation menu locations in a theme. + * + * @since 3.0.0 + * + * @global array $_wp_registered_nav_menus + * + * @return string[] Associative array of egistered navigation menu descriptions keyed + * by their location. If none are registered, an empty array. + */ + function get_registered_nav_menus() + { + } + /** + * Retrieves all registered navigation menu locations and the menus assigned to them. + * + * @since 3.0.0 + * + * @return int[] Associative array of registered navigation menu IDs keyed by their + * location name. If none are registered, an empty array. + */ + function get_nav_menu_locations() + { + } + /** + * Determines whether a registered nav menu location has a menu assigned to it. + * + * @since 3.0.0 + * + * @param string $location Menu location identifier. + * @return bool Whether location has a menu. + */ + function has_nav_menu($location) + { + } + /** + * Returns the name of a navigation menu. + * + * @since 4.9.0 + * + * @param string $location Menu location identifier. + * @return string Menu name. + */ + function wp_get_nav_menu_name($location) + { + } + /** + * Determines whether the given ID is a nav menu item. + * + * @since 3.0.0 + * + * @param int $menu_item_id The ID of the potential nav menu item. + * @return bool Whether the given ID is that of a nav menu item. + */ + function is_nav_menu_item($menu_item_id = 0) + { + } + /** + * Creates a navigation menu. + * + * Note that `$menu_name` is expected to be pre-slashed. + * + * @since 3.0.0 + * + * @param string $menu_name Menu name. + * @return int|WP_Error Menu ID on success, WP_Error object on failure. + */ + function wp_create_nav_menu($menu_name) + { + } + /** + * Deletes a navigation menu. + * + * @since 3.0.0 + * + * @param int|string|WP_Term $menu Menu ID, slug, name, or object. + * @return bool|WP_Error True on success, false or WP_Error object on failure. + */ + function wp_delete_nav_menu($menu) + { + } + /** + * Saves the properties of a menu or create a new menu with those properties. + * + * Note that `$menu_data` is expected to be pre-slashed. + * + * @since 3.0.0 + * + * @param int $menu_id The ID of the menu or "0" to create a new menu. + * @param array $menu_data The array of menu data. + * @return int|WP_Error Menu ID on success, WP_Error object on failure. + */ + function wp_update_nav_menu_object($menu_id = 0, $menu_data = array()) + { + } + /** + * Saves the properties of a menu item or create a new one. + * + * The menu-item-title, menu-item-description and menu-item-attr-title are expected + * to be pre-slashed since they are passed directly to APIs that expect slashed data. + * + * @since 3.0.0 + * @since 5.9.0 Added the `$fire_after_hooks` parameter. + * + * @param int $menu_id The ID of the menu. If 0, makes the menu item a draft orphan. + * @param int $menu_item_db_id The ID of the menu item. If 0, creates a new menu item. + * @param array $menu_item_data The menu item's data. + * @param bool $fire_after_hooks Whether to fire the after insert hooks. Default true. + * @return int|WP_Error The menu item's database ID or WP_Error object on failure. + */ + function wp_update_nav_menu_item($menu_id = 0, $menu_item_db_id = 0, $menu_item_data = array(), $fire_after_hooks = \true) + { + } + /** + * Returns all navigation menu objects. + * + * @since 3.0.0 + * @since 4.1.0 Default value of the 'orderby' argument was changed from 'none' + * to 'name'. + * + * @param array $args Optional. Array of arguments passed on to get_terms(). + * Default empty array. + * @return WP_Term[] An array of menu objects. + */ + function wp_get_nav_menus($args = array()) + { + } + /** + * Determines whether a menu item is valid. + * + * @link https://core.trac.wordpress.org/ticket/13958 + * + * @since 3.2.0 + * @access private + * + * @param object $item The menu item to check. + * @return bool False if invalid, otherwise true. + */ + function _is_valid_nav_menu_item($item) + { + } + /** + * Retrieves all menu items of a navigation menu. + * + * Note: Most arguments passed to the `$args` parameter – save for 'output_key' – are + * specifically for retrieving nav_menu_item posts from get_posts() and may only + * indirectly affect the ultimate ordering and content of the resulting nav menu + * items that get returned from this function. + * + * @since 3.0.0 + * + * @param int|string|WP_Term $menu Menu ID, slug, name, or object. + * @param array $args { + * Optional. Arguments to pass to get_posts(). + * + * @type string $order How to order nav menu items as queried with get_posts(). Will be ignored + * if 'output' is ARRAY_A. Default 'ASC'. + * @type string $orderby Field to order menu items by as retrieved from get_posts(). Supply an orderby + * field via 'output_key' to affect the output order of nav menu items. + * Default 'menu_order'. + * @type string $post_type Menu items post type. Default 'nav_menu_item'. + * @type string $post_status Menu items post status. Default 'publish'. + * @type string $output How to order outputted menu items. Default ARRAY_A. + * @type string $output_key Key to use for ordering the actual menu items that get returned. Note that + * that is not a get_posts() argument and will only affect output of menu items + * processed in this function. Default 'menu_order'. + * @type bool $nopaging Whether to retrieve all menu items (true) or paginate (false). Default true. + * } + * @return array|false Array of menu items, otherwise false. + * @phpstan-param array{ + * order?: string, + * orderby?: string, + * post_type?: string, + * post_status?: string, + * output?: string, + * output_key?: string, + * nopaging?: bool, + * } $args + */ + function wp_get_nav_menu_items($menu, $args = array()) + { + } + /** + * Updates post and term caches for all linked objects for a list of menu items. + * + * @since 6.1.0 + * + * @param WP_Post[] $menu_items Array of menu item post objects. + */ + function update_menu_item_cache($menu_items) + { + } + /** + * Decorates a menu item object with the shared navigation menu item properties. + * + * Properties: + * - ID: The term_id if the menu item represents a taxonomy term. + * - attr_title: The title attribute of the link element for this menu item. + * - classes: The array of class attribute values for the link element of this menu item. + * - db_id: The DB ID of this item as a nav_menu_item object, if it exists (0 if it doesn't exist). + * - description: The description of this menu item. + * - menu_item_parent: The DB ID of the nav_menu_item that is this item's menu parent, if any. 0 otherwise. + * - object: The type of object originally represented, such as 'category', 'post', or 'attachment'. + * - object_id: The DB ID of the original object this menu item represents, e.g. ID for posts and term_id for categories. + * - post_parent: The DB ID of the original object's parent object, if any (0 otherwise). + * - post_title: A "no title" label if menu item represents a post that lacks a title. + * - target: The target attribute of the link element for this menu item. + * - title: The title of this menu item. + * - type: The family of objects originally represented, such as 'post_type' or 'taxonomy'. + * - type_label: The singular label used to describe this type of menu item. + * - url: The URL to which this menu item points. + * - xfn: The XFN relationship expressed in the link of this menu item. + * - _invalid: Whether the menu item represents an object that no longer exists. + * + * @since 3.0.0 + * + * @param object $menu_item The menu item to modify. + * @return object The menu item with standard menu item properties. + */ + function wp_setup_nav_menu_item($menu_item) + { + } + /** + * Returns the menu items associated with a particular object. + * + * @since 3.0.0 + * + * @param int $object_id Optional. The ID of the original object. Default 0. + * @param string $object_type Optional. The type of object, such as 'post_type' or 'taxonomy'. + * Default 'post_type'. + * @param string $taxonomy Optional. If $object_type is 'taxonomy', $taxonomy is the name + * of the tax that $object_id belongs to. Default empty. + * @return int[] The array of menu item IDs; empty array if none. + */ + function wp_get_associated_nav_menu_items($object_id = 0, $object_type = 'post_type', $taxonomy = '') + { + } + /** + * Callback for handling a menu item when its original object is deleted. + * + * @since 3.0.0 + * @access private + * + * @param int $object_id The ID of the original object being trashed. + */ + function _wp_delete_post_menu_item($object_id) + { + } + /** + * Serves as a callback for handling a menu item when its original object is deleted. + * + * @since 3.0.0 + * @access private + * + * @param int $object_id The ID of the original object being trashed. + * @param int $tt_id Term taxonomy ID. Unused. + * @param string $taxonomy Taxonomy slug. + */ + function _wp_delete_tax_menu_item($object_id, $tt_id, $taxonomy) + { + } + /** + * Automatically add newly published page objects to menus with that as an option. + * + * @since 3.0.0 + * @access private + * + * @param string $new_status The new status of the post object. + * @param string $old_status The old status of the post object. + * @param WP_Post $post The post object being transitioned from one status to another. + */ + function _wp_auto_add_pages_to_menu($new_status, $old_status, $post) + { + } + /** + * Deletes auto-draft posts associated with the supplied changeset. + * + * @since 4.8.0 + * @access private + * + * @param int $post_id Post ID for the customize_changeset. + */ + function _wp_delete_customize_changeset_dependent_auto_drafts($post_id) + { + } + /** + * Handles menu config after theme change. + * + * @access private + * @since 4.9.0 + */ + function _wp_menus_changed() + { + } + /** + * Maps nav menu locations according to assignments in previously active theme. + * + * @since 4.9.0 + * + * @param array $new_nav_menu_locations New nav menu locations assignments. + * @param array $old_nav_menu_locations Old nav menu locations assignments. + * @return array Nav menus mapped to new nav menu locations. + */ + function wp_map_nav_menu_locations($new_nav_menu_locations, $old_nav_menu_locations) + { + } + /** + * Option API + * + * @package WordPress + * @subpackage Option + */ + /** + * Retrieves an option value based on an option name. + * + * If the option does not exist, and a default value is not provided, + * boolean false is returned. This could be used to check whether you need + * to initialize an option during installation of a plugin, however that + * can be done better by using add_option() which will not overwrite + * existing options. + * + * Not initializing an option and using boolean `false` as a return value + * is a bad practice as it triggers an additional database query. + * + * The type of the returned value can be different from the type that was passed + * when saving or updating the option. If the option value was serialized, + * then it will be unserialized when it is returned. In this case the type will + * be the same. For example, storing a non-scalar value like an array will + * return the same array. + * + * In most cases non-string scalar and null values will be converted and returned + * as string equivalents. + * + * Exceptions: + * + * 1. When the option has not been saved in the database, the `$default` value + * is returned if provided. If not, boolean `false` is returned. + * 2. When one of the Options API filters is used: {@see 'pre_option_$option'}, + * {@see 'default_option_$option'}, or {@see 'option_$option'}, the returned + * value may not match the expected type. + * 3. When the option has just been saved in the database, and get_option() + * is used right after, non-string scalar and null values are not converted to + * string equivalents and the original type is returned. + * + * Examples: + * + * When adding options like this: `add_option( 'my_option_name', 'value' )` + * and then retrieving them with `get_option( 'my_option_name' )`, the returned + * values will be: + * + * - `false` returns `string(0) ""` + * - `true` returns `string(1) "1"` + * - `0` returns `string(1) "0"` + * - `1` returns `string(1) "1"` + * - `'0'` returns `string(1) "0"` + * - `'1'` returns `string(1) "1"` + * - `null` returns `string(0) ""` + * + * When adding options with non-scalar values like + * `add_option( 'my_array', array( false, 'str', null ) )`, the returned value + * will be identical to the original as it is serialized before saving + * it in the database: + * + * array(3) { + * [0] => bool(false) + * [1] => string(3) "str" + * [2] => NULL + * } + * + * @since 1.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $option Name of the option to retrieve. Expected to not be SQL-escaped. + * @param mixed $default Optional. Default value to return if the option does not exist. + * @return mixed Value of the option. A value of any type may be returned, including + * scalar (string, boolean, float, integer), null, array, object. + * Scalar and null values will be returned as strings as long as they originate + * from a database stored option value. If there is no option in the database, + * boolean `false` is returned. + */ + function get_option($option, $default = \false) + { + } + /** + * Protects WordPress special option from being modified. + * + * Will die if $option is in protected list. Protected options are 'alloptions' + * and 'notoptions' options. + * + * @since 2.2.0 + * + * @param string $option Option name. + */ + function wp_protect_special_option($option) + { + } + /** + * Prints option value after sanitizing for forms. + * + * @since 1.5.0 + * + * @param string $option Option name. + */ + function form_option($option) + { + } + /** + * Loads and caches all autoloaded options, if available or all options. + * + * @since 2.2.0 + * @since 5.3.1 The `$force_cache` parameter was added. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param bool $force_cache Optional. Whether to force an update of the local cache + * from the persistent cache. Default false. + * @return array List of all options. + */ + function wp_load_alloptions($force_cache = \false) + { + } + /** + * Loads and caches certain often requested site options if is_multisite() and a persistent cache is not being used. + * + * @since 3.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $network_id Optional site ID for which to query the options. Defaults to the current site. + */ + function wp_load_core_site_options($network_id = \null) + { + } + /** + * Updates the value of an option that was already added. + * + * You do not need to serialize values. If the value needs to be serialized, + * then it will be serialized before it is inserted into the database. + * Remember, resources cannot be serialized or added as an option. + * + * If the option does not exist, it will be created. + * This function is designed to work with or without a logged-in user. In terms of security, + * plugin developers should check the current user's capabilities before updating any options. + * + * @since 1.0.0 + * @since 4.2.0 The `$autoload` parameter was added. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $option Name of the option to update. Expected to not be SQL-escaped. + * @param mixed $value Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped. + * @param string|bool $autoload Optional. Whether to load the option when WordPress starts up. For existing options, + * `$autoload` can only be updated using `update_option()` if `$value` is also changed. + * Accepts 'yes'|true to enable or 'no'|false to disable. For non-existent options, + * the default value is 'yes'. Default null. + * @return bool True if the value was updated, false otherwise. + */ + function update_option($option, $value, $autoload = \null) + { + } + /** + * Adds a new option. + * + * You do not need to serialize values. If the value needs to be serialized, + * then it will be serialized before it is inserted into the database. + * Remember, resources cannot be serialized or added as an option. + * + * You can create options without values and then update the values later. + * Existing options will not be updated and checks are performed to ensure that you + * aren't adding a protected WordPress option. Care should be taken to not name + * options the same as the ones which are protected. + * + * @since 1.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $option Name of the option to add. Expected to not be SQL-escaped. + * @param mixed $value Optional. Option value. Must be serializable if non-scalar. + * Expected to not be SQL-escaped. + * @param string $deprecated Optional. Description. Not used anymore. + * @param string|bool $autoload Optional. Whether to load the option when WordPress starts up. + * Default is enabled. Accepts 'no' to disable for legacy reasons. + * @return bool True if the option was added, false otherwise. + */ + function add_option($option, $value = '', $deprecated = '', $autoload = 'yes') + { + } + /** + * Removes option by name. Prevents removal of protected WordPress options. + * + * @since 1.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $option Name of the option to delete. Expected to not be SQL-escaped. + * @return bool True if the option was deleted, false otherwise. + */ + function delete_option($option) + { + } + /** + * Deletes a transient. + * + * @since 2.8.0 + * + * @param string $transient Transient name. Expected to not be SQL-escaped. + * @return bool True if the transient was deleted, false otherwise. + */ + function delete_transient($transient) + { + } + /** + * Retrieves the value of a transient. + * + * If the transient does not exist, does not have a value, or has expired, + * then the return value will be false. + * + * @since 2.8.0 + * + * @param string $transient Transient name. Expected to not be SQL-escaped. + * @return mixed Value of transient. + */ + function get_transient($transient) + { + } + /** + * Sets/updates the value of a transient. + * + * You do not need to serialize values. If the value needs to be serialized, + * then it will be serialized before it is set. + * + * @since 2.8.0 + * + * @param string $transient Transient name. Expected to not be SQL-escaped. + * Must be 172 characters or fewer in length. + * @param mixed $value Transient value. Must be serializable if non-scalar. + * Expected to not be SQL-escaped. + * @param int $expiration Optional. Time until expiration in seconds. Default 0 (no expiration). + * @return bool True if the value was set, false otherwise. + */ + function set_transient($transient, $value, $expiration = 0) + { + } + /** + * Deletes all expired transients. + * + * Note that this function won't do anything if an external object cache is in use. + * + * The multi-table delete syntax is used to delete the transient record + * from table a, and the corresponding transient_timeout record from table b. + * + * @since 4.9.0 + * + * @param bool $force_db Optional. Force cleanup to run against the database even when an external object cache is used. + */ + function delete_expired_transients($force_db = \false) + { + } + /** + * Saves and restores user interface settings stored in a cookie. + * + * Checks if the current user-settings cookie is updated and stores it. When no + * cookie exists (different browser used), adds the last saved cookie restoring + * the settings. + * + * @since 2.7.0 + */ + function wp_user_settings() + { + } + /** + * Retrieves user interface setting value based on setting name. + * + * @since 2.7.0 + * + * @param string $name The name of the setting. + * @param string|false $default Optional. Default value to return when $name is not set. Default false. + * @return mixed The last saved user setting or the default value/false if it doesn't exist. + */ + function get_user_setting($name, $default = \false) + { + } + /** + * Adds or updates user interface setting. + * + * Both `$name` and `$value` can contain only ASCII letters, numbers, hyphens, and underscores. + * + * This function has to be used before any output has started as it calls `setcookie()`. + * + * @since 2.8.0 + * + * @param string $name The name of the setting. + * @param string $value The value for the setting. + * @return bool|null True if set successfully, false otherwise. + * Null if the current user is not a member of the site. + */ + function set_user_setting($name, $value) + { + } + /** + * Deletes user interface settings. + * + * Deleting settings would reset them to the defaults. + * + * This function has to be used before any output has started as it calls `setcookie()`. + * + * @since 2.7.0 + * + * @param string $names The name or array of names of the setting to be deleted. + * @return bool|null True if deleted successfully, false otherwise. + * Null if the current user is not a member of the site. + */ + function delete_user_setting($names) + { + } + /** + * Retrieves all user interface settings. + * + * @since 2.7.0 + * + * @global array $_updated_user_settings + * + * @return array The last saved user settings or empty array. + */ + function get_all_user_settings() + { + } + /** + * Private. Sets all user interface settings. + * + * @since 2.8.0 + * @access private + * + * @global array $_updated_user_settings + * + * @param array $user_settings User settings. + * @return bool|null True if set successfully, false if the current user could not be found. + * Null if the current user is not a member of the site. + */ + function wp_set_all_user_settings($user_settings) + { + } + /** + * Deletes the user settings of the current user. + * + * @since 2.7.0 + */ + function delete_all_user_settings() + { + } + /** + * Retrieve an option value for the current network based on name of option. + * + * @since 2.8.0 + * @since 4.4.0 The `$use_cache` parameter was deprecated. + * @since 4.4.0 Modified into wrapper for get_network_option() + * + * @see get_network_option() + * + * @param string $option Name of the option to retrieve. Expected to not be SQL-escaped. + * @param mixed $default Optional. Value to return if the option doesn't exist. Default false. + * @param bool $deprecated Whether to use cache. Multisite only. Always set to true. + * @return mixed Value set for the option. + */ + function get_site_option($option, $default = \false, $deprecated = \true) + { + } + /** + * Adds a new option for the current network. + * + * Existing options will not be updated. Note that prior to 3.3 this wasn't the case. + * + * @since 2.8.0 + * @since 4.4.0 Modified into wrapper for add_network_option() + * + * @see add_network_option() + * + * @param string $option Name of the option to add. Expected to not be SQL-escaped. + * @param mixed $value Option value, can be anything. Expected to not be SQL-escaped. + * @return bool True if the option was added, false otherwise. + */ + function add_site_option($option, $value) + { + } + /** + * Removes a option by name for the current network. + * + * @since 2.8.0 + * @since 4.4.0 Modified into wrapper for delete_network_option() + * + * @see delete_network_option() + * + * @param string $option Name of the option to delete. Expected to not be SQL-escaped. + * @return bool True if the option was deleted, false otherwise. + */ + function delete_site_option($option) + { + } + /** + * Updates the value of an option that was already added for the current network. + * + * @since 2.8.0 + * @since 4.4.0 Modified into wrapper for update_network_option() + * + * @see update_network_option() + * + * @param string $option Name of the option. Expected to not be SQL-escaped. + * @param mixed $value Option value. Expected to not be SQL-escaped. + * @return bool True if the value was updated, false otherwise. + */ + function update_site_option($option, $value) + { + } + /** + * Retrieves a network's option value based on the option name. + * + * @since 4.4.0 + * + * @see get_option() + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $network_id ID of the network. Can be null to default to the current network ID. + * @param string $option Name of the option to retrieve. Expected to not be SQL-escaped. + * @param mixed $default Optional. Value to return if the option doesn't exist. Default false. + * @return mixed Value set for the option. + */ + function get_network_option($network_id, $option, $default = \false) + { + } + /** + * Adds a new network option. + * + * Existing options will not be updated. + * + * @since 4.4.0 + * + * @see add_option() + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $network_id ID of the network. Can be null to default to the current network ID. + * @param string $option Name of the option to add. Expected to not be SQL-escaped. + * @param mixed $value Option value, can be anything. Expected to not be SQL-escaped. + * @return bool True if the option was added, false otherwise. + */ + function add_network_option($network_id, $option, $value) + { + } + /** + * Removes a network option by name. + * + * @since 4.4.0 + * + * @see delete_option() + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $network_id ID of the network. Can be null to default to the current network ID. + * @param string $option Name of the option to delete. Expected to not be SQL-escaped. + * @return bool True if the option was deleted, false otherwise. + */ + function delete_network_option($network_id, $option) + { + } + /** + * Updates the value of a network option that was already added. + * + * @since 4.4.0 + * + * @see update_option() + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $network_id ID of the network. Can be null to default to the current network ID. + * @param string $option Name of the option. Expected to not be SQL-escaped. + * @param mixed $value Option value. Expected to not be SQL-escaped. + * @return bool True if the value was updated, false otherwise. + */ + function update_network_option($network_id, $option, $value) + { + } + /** + * Deletes a site transient. + * + * @since 2.9.0 + * + * @param string $transient Transient name. Expected to not be SQL-escaped. + * @return bool True if the transient was deleted, false otherwise. + */ + function delete_site_transient($transient) + { + } + /** + * Retrieves the value of a site transient. + * + * If the transient does not exist, does not have a value, or has expired, + * then the return value will be false. + * + * @since 2.9.0 + * + * @see get_transient() + * + * @param string $transient Transient name. Expected to not be SQL-escaped. + * @return mixed Value of transient. + */ + function get_site_transient($transient) + { + } + /** + * Sets/updates the value of a site transient. + * + * You do not need to serialize values. If the value needs to be serialized, + * then it will be serialized before it is set. + * + * @since 2.9.0 + * + * @see set_transient() + * + * @param string $transient Transient name. Expected to not be SQL-escaped. Must be + * 167 characters or fewer in length. + * @param mixed $value Transient value. Expected to not be SQL-escaped. + * @param int $expiration Optional. Time until expiration in seconds. Default 0 (no expiration). + * @return bool True if the value was set, false otherwise. + */ + function set_site_transient($transient, $value, $expiration = 0) + { + } + /** + * Registers default settings available in WordPress. + * + * The settings registered here are primarily useful for the REST API, so this + * does not encompass all settings available in WordPress. + * + * @since 4.7.0 + * @since 6.0.1 The `show_on_front`, `page_on_front`, and `page_for_posts` options were added. + */ + function register_initial_settings() + { + } + /** + * Registers a setting and its data. + * + * @since 2.7.0 + * @since 3.0.0 The `misc` option group was deprecated. + * @since 3.5.0 The `privacy` option group was deprecated. + * @since 4.7.0 `$args` can be passed to set flags on the setting, similar to `register_meta()`. + * @since 5.5.0 `$new_whitelist_options` was renamed to `$new_allowed_options`. + * Please consider writing more inclusive code. + * + * @global array $new_allowed_options + * @global array $wp_registered_settings + * + * @param string $option_group A settings group name. Should correspond to an allowed option key name. + * Default allowed option key names include 'general', 'discussion', 'media', + * 'reading', 'writing', and 'options'. + * @param string $option_name The name of an option to sanitize and save. + * @param array $args { + * Data used to describe the setting when registered. + * + * @type string $type The type of data associated with this setting. + * Valid values are 'string', 'boolean', 'integer', 'number', 'array', and 'object'. + * @type string $description A description of the data attached to this setting. + * @type callable $sanitize_callback A callback function that sanitizes the option's value. + * @type bool|array $show_in_rest Whether data associated with this setting should be included in the REST API. + * When registering complex settings, this argument may optionally be an + * array with a 'schema' key. + * @type mixed $default Default value when calling `get_option()`. + * } + * @phpstan-param array{ + * type?: string, + * description?: string, + * sanitize_callback?: callable, + * show_in_rest?: bool|array, + * default?: mixed, + * } $args + */ + function register_setting($option_group, $option_name, $args = array()) + { + } + /** + * Unregisters a setting. + * + * @since 2.7.0 + * @since 4.7.0 `$sanitize_callback` was deprecated. The callback from `register_setting()` is now used instead. + * @since 5.5.0 `$new_whitelist_options` was renamed to `$new_allowed_options`. + * Please consider writing more inclusive code. + * + * @global array $new_allowed_options + * @global array $wp_registered_settings + * + * @param string $option_group The settings group name used during registration. + * @param string $option_name The name of the option to unregister. + * @param callable $deprecated Optional. Deprecated. + */ + function unregister_setting($option_group, $option_name, $deprecated = '') + { + } + /** + * Retrieves an array of registered settings. + * + * @since 4.7.0 + * + * @global array $wp_registered_settings + * + * @return array List of registered settings, keyed by option name. + */ + function get_registered_settings() + { + } + /** + * Filters the default value for the option. + * + * For settings which register a default setting in `register_setting()`, this + * function is added as a filter to `default_option_{$option}`. + * + * @since 4.7.0 + * + * @param mixed $default Existing default value to return. + * @param string $option Option name. + * @param bool $passed_default Was `get_option()` passed a default value? + * @return mixed Filtered default value. + */ + function filter_default_option($default, $option, $passed_default) + { + } + /** + * Changes the current user by ID or name. + * + * Set $id to null and specify a name if you do not know a user's ID. + * + * @since 2.0.1 + * @deprecated 3.0.0 Use wp_set_current_user() + * @see wp_set_current_user() + * + * @param int|null $id User ID. + * @param string $name Optional. The user's username + * @return WP_User returns wp_set_current_user() + */ + function set_current_user($id, $name = '') + { + } + /** + * Populate global variables with information about the currently logged in user. + * + * @since 0.71 + * @deprecated 4.5.0 Use wp_get_current_user() + * @see wp_get_current_user() + * + * @return bool|WP_User False on XMLRPC Request and invalid auth cookie, WP_User instance otherwise. + */ + function get_currentuserinfo() + { + } + /** + * Retrieve user info by login name. + * + * @since 0.71 + * @deprecated 3.3.0 Use get_user_by() + * @see get_user_by() + * + * @param string $user_login User's username + * @return bool|object False on failure, User DB row object + */ + function get_userdatabylogin($user_login) + { + } + /** + * Retrieve user info by email. + * + * @since 2.5.0 + * @deprecated 3.3.0 Use get_user_by() + * @see get_user_by() + * + * @param string $email User's email address + * @return bool|object False on failure, User DB row object + */ + function get_user_by_email($email) + { + } + /** + * Sets a cookie for a user who just logged in. This function is deprecated. + * + * @since 1.5.0 + * @deprecated 2.5.0 Use wp_set_auth_cookie() + * @see wp_set_auth_cookie() + * + * @param string $username The user's username + * @param string $password Optional. The user's password + * @param bool $already_md5 Optional. Whether the password has already been through MD5 + * @param string $home Optional. Will be used instead of COOKIEPATH if set + * @param string $siteurl Optional. Will be used instead of SITECOOKIEPATH if set + * @param bool $remember Optional. Remember that the user is logged in + */ + function wp_setcookie($username, $password = '', $already_md5 = \false, $home = '', $siteurl = '', $remember = \false) + { + } + /** + * Clears the authentication cookie, logging the user out. This function is deprecated. + * + * @since 1.5.0 + * @deprecated 2.5.0 Use wp_clear_auth_cookie() + * @see wp_clear_auth_cookie() + */ + function wp_clearcookie() + { + } + /** + * Gets the user cookie login. This function is deprecated. + * + * This function is deprecated and should no longer be extended as it won't be + * used anywhere in WordPress. Also, plugins shouldn't use it either. + * + * @since 2.0.3 + * @deprecated 2.5.0 + * + * @return bool Always returns false + */ + function wp_get_cookie_login() + { + } + /** + * Checks a users login information and logs them in if it checks out. This function is deprecated. + * + * Use the global $error to get the reason why the login failed. If the username + * is blank, no error will be set, so assume blank username on that case. + * + * Plugins extending this function should also provide the global $error and set + * what the error is, so that those checking the global for why there was a + * failure can utilize it later. + * + * @since 1.2.2 + * @deprecated 2.5.0 Use wp_signon() + * @see wp_signon() + * + * @global string $error Error when false is returned + * + * @param string $username User's username + * @param string $password User's password + * @param string $deprecated Not used + * @return bool True on successful check, false on login failure. + */ + function wp_login($username, $password, $deprecated = '') + { + } + /** + * Changes the current user by ID or name. + * + * Set $id to null and specify a name if you do not know a user's ID. + * + * Some WordPress functionality is based on the current user and not based on + * the signed in user. Therefore, it opens the ability to edit and perform + * actions on users who aren't signed in. + * + * @since 2.0.3 + * + * @global WP_User $current_user The current user object which holds the user data. + * + * @param int|null $id User ID. + * @param string $name User's username. + * @return WP_User Current user User object. + */ + function wp_set_current_user($id, $name = '') + { + } + /** + * Retrieves the current user object. + * + * Will set the current user, if the current user is not set. The current user + * will be set to the logged-in person. If no user is logged-in, then it will + * set the current user to 0, which is invalid and won't have any permissions. + * + * @since 2.0.3 + * + * @see _wp_get_current_user() + * @global WP_User $current_user Checks if the current user is set. + * + * @return WP_User Current WP_User instance. + */ + function wp_get_current_user() + { + } + /** + * Retrieves user info by user ID. + * + * @since 0.71 + * + * @param int $user_id User ID + * @return WP_User|false WP_User object on success, false on failure. + */ + function get_userdata($user_id) + { + } + /** + * Retrieves user info by a given field. + * + * @since 2.8.0 + * @since 4.4.0 Added 'ID' as an alias of 'id' for the `$field` parameter. + * + * @global WP_User $current_user The current user object which holds the user data. + * + * @param string $field The field to retrieve the user with. id | ID | slug | email | login. + * @param int|string $value A value for $field. A user ID, slug, email address, or login name. + * @return WP_User|false WP_User object on success, false on failure. + */ + function get_user_by($field, $value) + { + } + /** + * Retrieves info for user lists to prevent multiple queries by get_userdata(). + * + * @since 3.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int[] $user_ids User ID numbers list + */ + function cache_users($user_ids) + { + } + /** + * Sends an email, similar to PHP's mail function. + * + * A true return value does not automatically mean that the user received the + * email successfully. It just only means that the method used was able to + * process the request without any errors. + * + * The default content type is `text/plain` which does not allow using HTML. + * However, you can set the content type of the email by using the + * {@see 'wp_mail_content_type'} filter. + * + * The default charset is based on the charset used on the blog. The charset can + * be set using the {@see 'wp_mail_charset'} filter. + * + * @since 1.2.1 + * @since 5.5.0 is_email() is used for email validation, + * instead of PHPMailer's default validator. + * + * @global PHPMailer\PHPMailer\PHPMailer $phpmailer + * + * @param string|string[] $to Array or comma-separated list of email addresses to send message. + * @param string $subject Email subject. + * @param string $message Message contents. + * @param string|string[] $headers Optional. Additional headers. + * @param string|string[] $attachments Optional. Paths to files to attach. + * @return bool Whether the email was sent successfully. + */ + function wp_mail($to, $subject, $message, $headers = '', $attachments = array()) + { + } + /** + * Authenticates a user, confirming the login credentials are valid. + * + * @since 2.5.0 + * @since 4.5.0 `$username` now accepts an email address. + * + * @param string $username User's username or email address. + * @param string $password User's password. + * @return WP_User|WP_Error WP_User object if the credentials are valid, + * otherwise WP_Error. + */ + function wp_authenticate($username, $password) + { + } + /** + * Logs the current user out. + * + * @since 2.5.0 + */ + function wp_logout() + { + } + /** + * Validates authentication cookie. + * + * The checks include making sure that the authentication cookie is set and + * pulling in the contents (if $cookie is not used). + * + * Makes sure the cookie is not expired. Verifies the hash in cookie is what is + * should be and compares the two. + * + * @since 2.5.0 + * + * @global int $login_grace_period + * + * @param string $cookie Optional. If used, will validate contents instead of cookie's. + * @param string $scheme Optional. The cookie scheme to use: 'auth', 'secure_auth', or 'logged_in'. + * @return int|false User ID if valid cookie, false if invalid. + */ + function wp_validate_auth_cookie($cookie = '', $scheme = '') + { + } + /** + * Generates authentication cookie contents. + * + * @since 2.5.0 + * @since 4.0.0 The `$token` parameter was added. + * + * @param int $user_id User ID. + * @param int $expiration The time the cookie expires as a UNIX timestamp. + * @param string $scheme Optional. The cookie scheme to use: 'auth', 'secure_auth', or 'logged_in'. + * Default 'auth'. + * @param string $token User's session token to use for this cookie. + * @return string Authentication cookie contents. Empty string if user does not exist. + */ + function wp_generate_auth_cookie($user_id, $expiration, $scheme = 'auth', $token = '') + { + } + /** + * Parses a cookie into its components. + * + * @since 2.7.0 + * @since 4.0.0 The `$token` element was added to the return value. + * + * @param string $cookie Authentication cookie. + * @param string $scheme Optional. The cookie scheme to use: 'auth', 'secure_auth', or 'logged_in'. + * @return string[]|false { + * Authentication cookie components. None of the components should be assumed + * to be valid as they come directly from a client-provided cookie value. If + * the cookie value is malformed, false is returned. + * + * @type string $username User's username. + * @type string $expiration The time the cookie expires as a UNIX timestamp. + * @type string $token User's session token used. + * @type string $hmac The security hash for the cookie. + * @type string $scheme The cookie scheme to use. + * } + * @phpstan-return false|array{ + * username: string, + * expiration: string, + * token: string, + * hmac: string, + * scheme: string, + * } + */ + function wp_parse_auth_cookie($cookie = '', $scheme = '') + { + } + /** + * Sets the authentication cookies based on user ID. + * + * The $remember parameter increases the time that the cookie will be kept. The + * default the cookie is kept without remembering is two days. When $remember is + * set, the cookies will be kept for 14 days or two weeks. + * + * @since 2.5.0 + * @since 4.3.0 Added the `$token` parameter. + * + * @param int $user_id User ID. + * @param bool $remember Whether to remember the user. + * @param bool|string $secure Whether the auth cookie should only be sent over HTTPS. Default is an empty + * string which means the value of `is_ssl()` will be used. + * @param string $token Optional. User's session token to use for this cookie. + */ + function wp_set_auth_cookie($user_id, $remember = \false, $secure = '', $token = '') + { + } + /** + * Removes all of the cookies associated with authentication. + * + * @since 2.5.0 + */ + function wp_clear_auth_cookie() + { + } + /** + * Determines whether the current visitor is a logged in user. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.0.0 + * + * @return bool True if user is logged in, false if not logged in. + */ + function is_user_logged_in() + { + } + /** + * Checks if a user is logged in, if not it redirects them to the login page. + * + * When this code is called from a page, it checks to see if the user viewing the page is logged in. + * If the user is not logged in, they are redirected to the login page. The user is redirected + * in such a way that, upon logging in, they will be sent directly to the page they were originally + * trying to access. + * + * @since 1.5.0 + */ + function auth_redirect() + { + } + /** + * Ensures intent by verifying that a user was referred from another admin page with the correct security nonce. + * + * This function ensures the user intends to perform a given action, which helps protect against clickjacking style + * attacks. It verifies intent, not authorisation, therefore it does not verify the user's capabilities. This should + * be performed with `current_user_can()` or similar. + * + * If the nonce value is invalid, the function will exit with an "Are You Sure?" style message. + * + * @since 1.2.0 + * @since 2.5.0 The `$query_arg` parameter was added. + * + * @param int|string $action The nonce action. + * @param string $query_arg Optional. Key to check for nonce in `$_REQUEST`. Default '_wpnonce'. + * @return int|false 1 if the nonce is valid and generated between 0-12 hours ago, + * 2 if the nonce is valid and generated between 12-24 hours ago. + * False if the nonce is invalid. + */ + function check_admin_referer($action = -1, $query_arg = '_wpnonce') + { + } + /** + * Verifies the Ajax request to prevent processing requests external of the blog. + * + * @since 2.0.3 + * + * @param int|string $action Action nonce. + * @param false|string $query_arg Optional. Key to check for the nonce in `$_REQUEST` (since 2.5). If false, + * `$_REQUEST` values will be evaluated for '_ajax_nonce', and '_wpnonce' + * (in that order). Default false. + * @param bool $die Optional. Whether to die early when the nonce cannot be verified. + * Default true. + * @return int|false 1 if the nonce is valid and generated between 0-12 hours ago, + * 2 if the nonce is valid and generated between 12-24 hours ago. + * False if the nonce is invalid. + */ + function check_ajax_referer($action = -1, $query_arg = \false, $die = \true) + { + } + /** + * Redirects to another page. + * + * Note: wp_redirect() does not exit automatically, and should almost always be + * followed by a call to `exit;`: + * + * wp_redirect( $url ); + * exit; + * + * Exiting can also be selectively manipulated by using wp_redirect() as a conditional + * in conjunction with the {@see 'wp_redirect'} and {@see 'wp_redirect_location'} filters: + * + * if ( wp_redirect( $url ) ) { + * exit; + * } + * + * @since 1.5.1 + * @since 5.1.0 The `$x_redirect_by` parameter was added. + * @since 5.4.0 On invalid status codes, wp_die() is called. + * + * @global bool $is_IIS + * + * @param string $location The path or URL to redirect to. + * @param int $status Optional. HTTP response status code to use. Default '302' (Moved Temporarily). + * @param string $x_redirect_by Optional. The application doing the redirect. Default 'WordPress'. + * @return bool False if the redirect was cancelled, true otherwise. + */ + function wp_redirect($location, $status = 302, $x_redirect_by = 'WordPress') + { + } + /** + * Sanitizes a URL for use in a redirect. + * + * @since 2.3.0 + * + * @param string $location The path to redirect to. + * @return string Redirect-sanitized URL. + */ + function wp_sanitize_redirect($location) + { + } + /** + * URL encodes UTF-8 characters in a URL. + * + * @ignore + * @since 4.2.0 + * @access private + * + * @see wp_sanitize_redirect() + * + * @param array $matches RegEx matches against the redirect location. + * @return string URL-encoded version of the first RegEx match. + */ + function _wp_sanitize_utf8_in_redirect($matches) + { + } + /** + * Performs a safe (local) redirect, using wp_redirect(). + * + * Checks whether the $location is using an allowed host, if it has an absolute + * path. A plugin can therefore set or remove allowed host(s) to or from the + * list. + * + * If the host is not allowed, then the redirect defaults to wp-admin on the siteurl + * instead. This prevents malicious redirects which redirect to another host, + * but only used in a few places. + * + * Note: wp_safe_redirect() does not exit automatically, and should almost always be + * followed by a call to `exit;`: + * + * wp_safe_redirect( $url ); + * exit; + * + * Exiting can also be selectively manipulated by using wp_safe_redirect() as a conditional + * in conjunction with the {@see 'wp_redirect'} and {@see 'wp_redirect_location'} filters: + * + * if ( wp_safe_redirect( $url ) ) { + * exit; + * } + * + * @since 2.3.0 + * @since 5.1.0 The return value from wp_redirect() is now passed on, and the `$x_redirect_by` parameter was added. + * + * @param string $location The path or URL to redirect to. + * @param int $status Optional. HTTP response status code to use. Default '302' (Moved Temporarily). + * @param string $x_redirect_by Optional. The application doing the redirect. Default 'WordPress'. + * @return bool False if the redirect was cancelled, true otherwise. + */ + function wp_safe_redirect($location, $status = 302, $x_redirect_by = 'WordPress') + { + } + /** + * Validates a URL for use in a redirect. + * + * Checks whether the $location is using an allowed host, if it has an absolute + * path. A plugin can therefore set or remove allowed host(s) to or from the + * list. + * + * If the host is not allowed, then the redirect is to $default supplied. + * + * @since 2.8.1 + * + * @param string $location The redirect to validate. + * @param string $default The value to return if $location is not allowed. + * @return string redirect-sanitized URL. + */ + function wp_validate_redirect($location, $default = '') + { + } + /** + * Notifies an author (and/or others) of a comment/trackback/pingback on a post. + * + * @since 1.0.0 + * + * @param int|WP_Comment $comment_id Comment ID or WP_Comment object. + * @param string $deprecated Not used. + * @return bool True on completion. False if no email addresses were specified. + */ + function wp_notify_postauthor($comment_id, $deprecated = \null) + { + } + /** + * Notifies the moderator of the site about a new comment that is awaiting approval. + * + * @since 1.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * Uses the {@see 'notify_moderator'} filter to determine whether the site moderator + * should be notified, overriding the site setting. + * + * @param int $comment_id Comment ID. + * @return true Always returns true. + */ + function wp_notify_moderator($comment_id) + { + } + /** + * Notifies the blog admin of a user changing password, normally via email. + * + * @since 2.7.0 + * + * @param WP_User $user User object. + */ + function wp_password_change_notification($user) + { + } + /** + * Emails login credentials to a newly-registered user. + * + * A new user registration notification is also sent to admin email. + * + * @since 2.0.0 + * @since 4.3.0 The `$plaintext_pass` parameter was changed to `$notify`. + * @since 4.3.1 The `$plaintext_pass` parameter was deprecated. `$notify` added as a third parameter. + * @since 4.6.0 The `$notify` parameter accepts 'user' for sending notification only to the user created. + * + * @param int $user_id User ID. + * @param null $deprecated Not used (argument deprecated). + * @param string $notify Optional. Type of notification that should happen. Accepts 'admin' or an empty + * string (admin only), 'user', or 'both' (admin and user). Default empty. + */ + function wp_new_user_notification($user_id, $deprecated = \null, $notify = '') + { + } + /** + * Returns the time-dependent variable for nonce creation. + * + * A nonce has a lifespan of two ticks. Nonces in their second tick may be + * updated, e.g. by autosave. + * + * @since 2.5.0 + * @since 6.1.0 Added `$action` argument. + * + * @param string|int $action Optional. The nonce action. Default -1. + * @return float Float value rounded up to the next highest integer. + */ + function wp_nonce_tick($action = -1) + { + } + /** + * Verifies that a correct security nonce was used with time limit. + * + * A nonce is valid for 24 hours (by default). + * + * @since 2.0.3 + * + * @param string $nonce Nonce value that was used for verification, usually via a form field. + * @param string|int $action Should give context to what is taking place and be the same when nonce was created. + * @return int|false 1 if the nonce is valid and generated between 0-12 hours ago, + * 2 if the nonce is valid and generated between 12-24 hours ago. + * False if the nonce is invalid. + */ + function wp_verify_nonce($nonce, $action = -1) + { + } + /** + * Creates a cryptographic token tied to a specific action, user, user session, + * and window of time. + * + * @since 2.0.3 + * @since 4.0.0 Session tokens were integrated with nonce creation. + * + * @param string|int $action Scalar value to add context to the nonce. + * @return string The token. + */ + function wp_create_nonce($action = -1) + { + } + /** + * Returns a salt to add to hashes. + * + * Salts are created using secret keys. Secret keys are located in two places: + * in the database and in the wp-config.php file. The secret key in the database + * is randomly generated and will be appended to the secret keys in wp-config.php. + * + * The secret keys in wp-config.php should be updated to strong, random keys to maximize + * security. Below is an example of how the secret key constants are defined. + * Do not paste this example directly into wp-config.php. Instead, have a + * {@link https://api.wordpress.org/secret-key/1.1/salt/ secret key created} just + * for you. + * + * define('AUTH_KEY', ' Xakm<o xQy rw4EMsLKM-?!T+,PFF})H4lzcW57AF0U@N@< >M%G4Yt>f`z]MON'); + * define('SECURE_AUTH_KEY', 'LzJ}op]mr|6+![P}Ak:uNdJCJZd>(Hx.-Mh#Tz)pCIU#uGEnfFz|f ;;eU%/U^O~'); + * define('LOGGED_IN_KEY', '|i|Ux`9<p-h$aFf(qnT:sDO:D1P^wZ$$/Ra@miTJi9G;ddp_<q}6H1)o|a +&JCM'); + * define('NONCE_KEY', '%:R{[P|,s.KuMltH5}cI;/k<Gx~j!f0I)m_sIyu+&NJZ)-iO>z7X>QYR0Z_XnZ@|'); + * define('AUTH_SALT', 'eZyT)-Naw]F8CwA*VaW#q*|.)g@o}||wf~@C-YSt}(dh_r6EbI#A,y|nU2{B#JBW'); + * define('SECURE_AUTH_SALT', '!=oLUTXh,QW=H `}`L|9/^4-3 STz},T(w}W<I`.JjPi)<Bmf1v,HpGe}T1:Xt7n'); + * define('LOGGED_IN_SALT', '+XSqHc;@Q*K_b|Z?NC[3H!!EONbh.n<+=uKR:>*c(u`g~EJBf#8u#R{mUEZrozmm'); + * define('NONCE_SALT', 'h`GXHhD>SLWVfg1(1(N{;.V!MoE(SfbA_ksP@&`+AycHcAV$+?@3q+rxV{%^VyKT'); + * + * Salting passwords helps against tools which has stored hashed values of + * common dictionary strings. The added values makes it harder to crack. + * + * @since 2.5.0 + * + * @link https://api.wordpress.org/secret-key/1.1/salt/ Create secrets for wp-config.php + * + * @param string $scheme Authentication scheme (auth, secure_auth, logged_in, nonce). + * @return string Salt value + */ + function wp_salt($scheme = 'auth') + { + } + /** + * Gets hash of given string. + * + * @since 2.0.3 + * + * @param string $data Plain text to hash. + * @param string $scheme Authentication scheme (auth, secure_auth, logged_in, nonce). + * @return string Hash of $data. + */ + function wp_hash($data, $scheme = 'auth') + { + } + /** + * Creates a hash (encrypt) of a plain text password. + * + * For integration with other applications, this function can be overwritten to + * instead use the other package password checking algorithm. + * + * @since 2.5.0 + * + * @global PasswordHash $wp_hasher PHPass object + * + * @param string $password Plain text user password to hash. + * @return string The hash string of the password. + */ + function wp_hash_password($password) + { + } + /** + * Checks the plaintext password against the encrypted Password. + * + * Maintains compatibility between old version and the new cookie authentication + * protocol using PHPass library. The $hash parameter is the encrypted password + * and the function compares the plain text password when encrypted similarly + * against the already encrypted password to see if they match. + * + * For integration with other applications, this function can be overwritten to + * instead use the other package password checking algorithm. + * + * @since 2.5.0 + * + * @global PasswordHash $wp_hasher PHPass object used for checking the password + * against the $hash + $password. + * @uses PasswordHash::CheckPassword + * + * @param string $password Plaintext user's password. + * @param string $hash Hash of the user's password to check against. + * @param string|int $user_id Optional. User ID. + * @return bool False, if the $password does not match the hashed password. + */ + function wp_check_password($password, $hash, $user_id = '') + { + } + /** + * Generates a random password drawn from the defined set of characters. + * + * Uses wp_rand() is used to create passwords with far less predictability + * than similar native PHP functions like `rand()` or `mt_rand()`. + * + * @since 2.5.0 + * + * @param int $length Optional. The length of password to generate. Default 12. + * @param bool $special_chars Optional. Whether to include standard special characters. + * Default true. + * @param bool $extra_special_chars Optional. Whether to include other special characters. + * Used when generating secret keys and salts. Default false. + * @return string The random password. + */ + function wp_generate_password($length = 12, $special_chars = \true, $extra_special_chars = \false) + { + } + /** + * Generates a random non-negative number. + * + * @since 2.6.2 + * @since 4.4.0 Uses PHP7 random_int() or the random_compat library if available. + * @since 6.1.0 Returns zero instead of a random number if both `$min` and `$max` are zero. + * + * @global string $rnd_value + * + * @param int $min Optional. Lower limit for the generated number. + * Accepts positive integers or zero. Defaults to 0. + * @param int $max Optional. Upper limit for the generated number. + * Accepts positive integers. Defaults to 4294967295. + * @return int A random non-negative number between min and max. + */ + function wp_rand($min = \null, $max = \null) + { + } + /** + * Updates the user's password with a new encrypted one. + * + * For integration with other applications, this function can be overwritten to + * instead use the other package password checking algorithm. + * + * Please note: This function should be used sparingly and is really only meant for single-time + * application. Leveraging this improperly in a plugin or theme could result in an endless loop + * of password resets if precautions are not taken to ensure it does not execute on every page load. + * + * @since 2.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $password The plaintext new user password. + * @param int $user_id User ID. + */ + function wp_set_password($password, $user_id) + { + } + /** + * Retrieves the avatar `<img>` tag for a user, email address, MD5 hash, comment, or post. + * + * @since 2.5.0 + * @since 4.2.0 Optional `$args` parameter added. + * + * @param mixed $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash, + * user email, WP_User object, WP_Post object, or WP_Comment object. + * @param int $size Optional. Height and width of the avatar image file in pixels. Default 96. + * @param string $default Optional. URL for the default image or a default type. Accepts '404' + * (return a 404 instead of a default image), 'retro' (8bit), 'monsterid' + * (monster), 'wavatar' (cartoon face), 'indenticon' (the "quilt"), + * 'mystery', 'mm', or 'mysteryman' (The Oyster Man), 'blank' (transparent GIF), + * or 'gravatar_default' (the Gravatar logo). Default is the value of the + * 'avatar_default' option, with a fallback of 'mystery'. + * @param string $alt Optional. Alternative text to use in img tag. Default empty. + * @param array $args { + * Optional. Extra arguments to retrieve the avatar. + * + * @type int $height Display height of the avatar in pixels. Defaults to $size. + * @type int $width Display width of the avatar in pixels. Defaults to $size. + * @type bool $force_default Whether to always show the default image, never the Gravatar. Default false. + * @type string $rating What rating to display avatars up to. Accepts 'G', 'PG', 'R', 'X', and are + * judged in that order. Default is the value of the 'avatar_rating' option. + * @type string $scheme URL scheme to use. See set_url_scheme() for accepted values. + * Default null. + * @type array|string $class Array or string of additional classes to add to the img element. + * Default null. + * @type bool $force_display Whether to always show the avatar - ignores the show_avatars option. + * Default false. + * @type string $loading Value for the `loading` attribute. + * Default null. + * @type string $extra_attr HTML attributes to insert in the IMG element. Is not sanitized. Default empty. + * } + * @return string|false `<img>` tag for the user's avatar. False on failure. + * @phpstan-param array{ + * height?: int, + * width?: int, + * force_default?: bool, + * rating?: string, + * scheme?: string, + * class?: array|string, + * force_display?: bool, + * loading?: string, + * extra_attr?: string, + * } $args + */ + function get_avatar($id_or_email, $size = 96, $default = '', $alt = '', $args = \null) + { + } + /** + * Displays a human readable HTML representation of the difference between two strings. + * + * The Diff is available for getting the changes between versions. The output is + * HTML, so the primary use is for displaying the changes. If the two strings + * are equivalent, then an empty string will be returned. + * + * @since 2.6.0 + * + * @see wp_parse_args() Used to change defaults to user defined settings. + * @uses Text_Diff + * @uses WP_Text_Diff_Renderer_Table + * + * @param string $left_string "old" (left) version of string. + * @param string $right_string "new" (right) version of string. + * @param string|array $args { + * Associative array of options to pass to WP_Text_Diff_Renderer_Table(). + * + * @type string $title Titles the diff in a manner compatible + * with the output. Default empty. + * @type string $title_left Change the HTML to the left of the title. + * Default empty. + * @type string $title_right Change the HTML to the right of the title. + * Default empty. + * @type bool $show_split_view True for split view (two columns), false for + * un-split view (single column). Default true. + * } + * @return string Empty string if strings are equivalent or HTML with differences. + * @phpstan-param array{ + * title?: string, + * title_left?: string, + * title_right?: string, + * show_split_view?: bool, + * } $args + */ + function wp_text_diff($left_string, $right_string, $args = \null) + { + } + /** + * Adds a callback function to a filter hook. + * + * WordPress offers filter hooks to allow plugins to modify + * various types of internal data at runtime. + * + * A plugin can modify data by binding a callback to a filter hook. When the filter + * is later applied, each bound callback is run in order of priority, and given + * the opportunity to modify a value by returning a new value. + * + * The following example shows how a callback function is bound to a filter hook. + * + * Note that `$example` is passed to the callback, (maybe) modified, then returned: + * + * function example_callback( $example ) { + * // Maybe modify $example in some way. + * return $example; + * } + * add_filter( 'example_filter', 'example_callback' ); + * + * Bound callbacks can accept from none to the total number of arguments passed as parameters + * in the corresponding apply_filters() call. + * + * In other words, if an apply_filters() call passes four total arguments, callbacks bound to + * it can accept none (the same as 1) of the arguments or up to four. The important part is that + * the `$accepted_args` value must reflect the number of arguments the bound callback *actually* + * opted to accept. If no arguments were accepted by the callback that is considered to be the + * same as accepting 1 argument. For example: + * + * // Filter call. + * $value = apply_filters( 'hook', $value, $arg2, $arg3 ); + * + * // Accepting zero/one arguments. + * function example_callback() { + * ... + * return 'some value'; + * } + * add_filter( 'hook', 'example_callback' ); // Where $priority is default 10, $accepted_args is default 1. + * + * // Accepting two arguments (three possible). + * function example_callback( $value, $arg2 ) { + * ... + * return $maybe_modified_value; + * } + * add_filter( 'hook', 'example_callback', 10, 2 ); // Where $priority is 10, $accepted_args is 2. + * + * *Note:* The function will return true whether or not the callback is valid. + * It is up to you to take care. This is done for optimization purposes, so + * everything is as quick as possible. + * + * @since 0.71 + * + * @global WP_Hook[] $wp_filter A multidimensional array of all hooks and the callbacks hooked to them. + * + * @param string $hook_name The name of the filter to add the callback to. + * @param callable $callback The callback to be run when the filter is applied. + * @param int $priority Optional. Used to specify the order in which the functions + * associated with a particular filter are executed. + * Lower numbers correspond with earlier execution, + * and functions with the same priority are executed + * in the order in which they were added to the filter. Default 10. + * @param int $accepted_args Optional. The number of arguments the function accepts. Default 1. + * @return true Always returns true. + */ + function add_filter($hook_name, $callback, $priority = 10, $accepted_args = 1) + { + } + /** + * Calls the callback functions that have been added to a filter hook. + * + * This function invokes all functions attached to filter hook `$hook_name`. + * It is possible to create new filter hooks by simply calling this function, + * specifying the name of the new hook using the `$hook_name` parameter. + * + * The function also allows for multiple additional arguments to be passed to hooks. + * + * Example usage: + * + * // The filter callback function. + * function example_callback( $string, $arg1, $arg2 ) { + * // (maybe) modify $string. + * return $string; + * } + * add_filter( 'example_filter', 'example_callback', 10, 3 ); + * + * /* + * * Apply the filters by calling the 'example_callback()' function + * * that's hooked onto `example_filter` above. + * * + * * - 'example_filter' is the filter hook. + * * - 'filter me' is the value being filtered. + * * - $arg1 and $arg2 are the additional arguments passed to the callback. + * $value = apply_filters( 'example_filter', 'filter me', $arg1, $arg2 ); + * + * @since 0.71 + * @since 6.0.0 Formalized the existing and already documented `...$args` parameter + * by adding it to the function signature. + * + * @global WP_Hook[] $wp_filter Stores all of the filters and actions. + * @global int[] $wp_filters Stores the number of times each filter was triggered. + * @global string[] $wp_current_filter Stores the list of current filters with the current one last. + * + * @param string $hook_name The name of the filter hook. + * @param mixed $value The value to filter. + * @param mixed ...$args Additional parameters to pass to the callback functions. + * @return mixed The filtered value after all hooked functions are applied to it. + */ + function apply_filters($hook_name, $value, ...$args) + { + } + /** + * Calls the callback functions that have been added to a filter hook, specifying arguments in an array. + * + * @since 3.0.0 + * + * @see apply_filters() This function is identical, but the arguments passed to the + * functions hooked to `$hook_name` are supplied using an array. + * + * @global WP_Hook[] $wp_filter Stores all of the filters and actions. + * @global int[] $wp_filters Stores the number of times each filter was triggered. + * @global string[] $wp_current_filter Stores the list of current filters with the current one last. + * + * @param string $hook_name The name of the filter hook. + * @param array $args The arguments supplied to the functions hooked to `$hook_name`. + * @return mixed The filtered value after all hooked functions are applied to it. + */ + function apply_filters_ref_array($hook_name, $args) + { + } + /** + * Checks if any filter has been registered for a hook. + * + * When using the `$callback` argument, this function may return a non-boolean value + * that evaluates to false (e.g. 0), so use the `===` operator for testing the return value. + * + * @since 2.5.0 + * + * @global WP_Hook[] $wp_filter Stores all of the filters and actions. + * + * @param string $hook_name The name of the filter hook. + * @param callable|string|array|false $callback Optional. The callback to check for. + * This function can be called unconditionally to speculatively check + * a callback that may or may not exist. Default false. + * @return bool|int If `$callback` is omitted, returns boolean for whether the hook has + * anything registered. When checking a specific function, the priority + * of that hook is returned, or false if the function is not attached. + */ + function has_filter($hook_name, $callback = \false) + { + } + /** + * Removes a callback function from a filter hook. + * + * This can be used to remove default functions attached to a specific filter + * hook and possibly replace them with a substitute. + * + * To remove a hook, the `$callback` and `$priority` arguments must match + * when the hook was added. This goes for both filters and actions. No warning + * will be given on removal failure. + * + * @since 1.2.0 + * + * @global WP_Hook[] $wp_filter Stores all of the filters and actions. + * + * @param string $hook_name The filter hook to which the function to be removed is hooked. + * @param callable|string|array $callback The callback to be removed from running when the filter is applied. + * This function can be called unconditionally to speculatively remove + * a callback that may or may not exist. + * @param int $priority Optional. The exact priority used when adding the original + * filter callback. Default 10. + * @return bool Whether the function existed before it was removed. + */ + function remove_filter($hook_name, $callback, $priority = 10) + { + } + /** + * Removes all of the callback functions from a filter hook. + * + * @since 2.7.0 + * + * @global WP_Hook[] $wp_filter Stores all of the filters and actions. + * + * @param string $hook_name The filter to remove callbacks from. + * @param int|false $priority Optional. The priority number to remove them from. + * Default false. + * @return true Always returns true. + */ + function remove_all_filters($hook_name, $priority = \false) + { + } + /** + * Retrieves the name of the current filter hook. + * + * @since 2.5.0 + * + * @global string[] $wp_current_filter Stores the list of current filters with the current one last + * + * @return string Hook name of the current filter. + */ + function current_filter() + { + } + /** + * Returns whether or not a filter hook is currently being processed. + * + * The function current_filter() only returns the most recent filter being executed. + * did_filter() returns the number of times a filter has been applied during + * the current request. + * + * This function allows detection for any filter currently being executed + * (regardless of whether it's the most recent filter to fire, in the case of + * hooks called from hook callbacks) to be verified. + * + * @since 3.9.0 + * + * @see current_filter() + * @see did_filter() + * @global string[] $wp_current_filter Current filter. + * + * @param string|null $hook_name Optional. Filter hook to check. Defaults to null, + * which checks if any filter is currently being run. + * @return bool Whether the filter is currently in the stack. + */ + function doing_filter($hook_name = \null) + { + } + /** + * Retrieves the number of times a filter has been applied during the current request. + * + * @since 6.1.0 + * + * @global int[] $wp_filters Stores the number of times each filter was triggered. + * + * @param string $hook_name The name of the filter hook. + * @return int The number of times the filter hook has been applied. + */ + function did_filter($hook_name) + { + } + /** + * Adds a callback function to an action hook. + * + * Actions are the hooks that the WordPress core launches at specific points + * during execution, or when specific events occur. Plugins can specify that + * one or more of its PHP functions are executed at these points, using the + * Action API. + * + * @since 1.2.0 + * + * @param string $hook_name The name of the action to add the callback to. + * @param callable $callback The callback to be run when the action is called. + * @param int $priority Optional. Used to specify the order in which the functions + * associated with a particular action are executed. + * Lower numbers correspond with earlier execution, + * and functions with the same priority are executed + * in the order in which they were added to the action. Default 10. + * @param int $accepted_args Optional. The number of arguments the function accepts. Default 1. + * @return true Always returns true. + */ + function add_action($hook_name, $callback, $priority = 10, $accepted_args = 1) + { + } + /** + * Calls the callback functions that have been added to an action hook. + * + * This function invokes all functions attached to action hook `$hook_name`. + * It is possible to create new action hooks by simply calling this function, + * specifying the name of the new hook using the `$hook_name` parameter. + * + * You can pass extra arguments to the hooks, much like you can with `apply_filters()`. + * + * Example usage: + * + * // The action callback function. + * function example_callback( $arg1, $arg2 ) { + * // (maybe) do something with the args. + * } + * add_action( 'example_action', 'example_callback', 10, 2 ); + * + * /* + * * Trigger the actions by calling the 'example_callback()' function + * * that's hooked onto `example_action` above. + * * + * * - 'example_action' is the action hook. + * * - $arg1 and $arg2 are the additional arguments passed to the callback. + * do_action( 'example_action', $arg1, $arg2 ); + * + * @since 1.2.0 + * @since 5.3.0 Formalized the existing and already documented `...$arg` parameter + * by adding it to the function signature. + * + * @global WP_Hook[] $wp_filter Stores all of the filters and actions. + * @global int[] $wp_actions Stores the number of times each action was triggered. + * @global string[] $wp_current_filter Stores the list of current filters with the current one last. + * + * @param string $hook_name The name of the action to be executed. + * @param mixed ...$arg Optional. Additional arguments which are passed on to the + * functions hooked to the action. Default empty. + */ + function do_action($hook_name, ...$arg) + { + } + /** + * Calls the callback functions that have been added to an action hook, specifying arguments in an array. + * + * @since 2.1.0 + * + * @see do_action() This function is identical, but the arguments passed to the + * functions hooked to `$hook_name` are supplied using an array. + * + * @global WP_Hook[] $wp_filter Stores all of the filters and actions. + * @global int[] $wp_actions Stores the number of times each action was triggered. + * @global string[] $wp_current_filter Stores the list of current filters with the current one last. + * + * @param string $hook_name The name of the action to be executed. + * @param array $args The arguments supplied to the functions hooked to `$hook_name`. + */ + function do_action_ref_array($hook_name, $args) + { + } + /** + * Checks if any action has been registered for a hook. + * + * When using the `$callback` argument, this function may return a non-boolean value + * that evaluates to false (e.g. 0), so use the `===` operator for testing the return value. + * + * @since 2.5.0 + * + * @see has_filter() has_action() is an alias of has_filter(). + * + * @param string $hook_name The name of the action hook. + * @param callable|string|array|false $callback Optional. The callback to check for. + * This function can be called unconditionally to speculatively check + * a callback that may or may not exist. Default false. + * @return bool|int If `$callback` is omitted, returns boolean for whether the hook has + * anything registered. When checking a specific function, the priority + * of that hook is returned, or false if the function is not attached. + */ + function has_action($hook_name, $callback = \false) + { + } + /** + * Removes a callback function from an action hook. + * + * This can be used to remove default functions attached to a specific action + * hook and possibly replace them with a substitute. + * + * To remove a hook, the `$callback` and `$priority` arguments must match + * when the hook was added. This goes for both filters and actions. No warning + * will be given on removal failure. + * + * @since 1.2.0 + * + * @param string $hook_name The action hook to which the function to be removed is hooked. + * @param callable|string|array $callback The name of the function which should be removed. + * This function can be called unconditionally to speculatively remove + * a callback that may or may not exist. + * @param int $priority Optional. The exact priority used when adding the original + * action callback. Default 10. + * @return bool Whether the function is removed. + */ + function remove_action($hook_name, $callback, $priority = 10) + { + } + /** + * Removes all of the callback functions from an action hook. + * + * @since 2.7.0 + * + * @param string $hook_name The action to remove callbacks from. + * @param int|false $priority Optional. The priority number to remove them from. + * Default false. + * @return true Always returns true. + */ + function remove_all_actions($hook_name, $priority = \false) + { + } + /** + * Retrieves the name of the current action hook. + * + * @since 3.9.0 + * + * @return string Hook name of the current action. + */ + function current_action() + { + } + /** + * Returns whether or not an action hook is currently being processed. + * + * The function current_action() only returns the most recent action being executed. + * did_action() returns the number of times an action has been fired during + * the current request. + * + * This function allows detection for any action currently being executed + * (regardless of whether it's the most recent action to fire, in the case of + * hooks called from hook callbacks) to be verified. + * + * @since 3.9.0 + * + * @see current_action() + * @see did_action() + * + * @param string|null $hook_name Optional. Action hook to check. Defaults to null, + * which checks if any action is currently being run. + * @return bool Whether the action is currently in the stack. + */ + function doing_action($hook_name = \null) + { + } + /** + * Retrieves the number of times an action has been fired during the current request. + * + * @since 2.1.0 + * + * @global int[] $wp_actions Stores the number of times each action was triggered. + * + * @param string $hook_name The name of the action hook. + * @return int The number of times the action hook has been fired. + */ + function did_action($hook_name) + { + } + /** + * Fires functions attached to a deprecated filter hook. + * + * When a filter hook is deprecated, the apply_filters() call is replaced with + * apply_filters_deprecated(), which triggers a deprecation notice and then fires + * the original filter hook. + * + * Note: the value and extra arguments passed to the original apply_filters() call + * must be passed here to `$args` as an array. For example: + * + * // Old filter. + * return apply_filters( 'wpdocs_filter', $value, $extra_arg ); + * + * // Deprecated. + * return apply_filters_deprecated( 'wpdocs_filter', array( $value, $extra_arg ), '4.9.0', 'wpdocs_new_filter' ); + * + * @since 4.6.0 + * + * @see _deprecated_hook() + * + * @param string $hook_name The name of the filter hook. + * @param array $args Array of additional function arguments to be passed to apply_filters(). + * @param string $version The version of WordPress that deprecated the hook. + * @param string $replacement Optional. The hook that should have been used. Default empty. + * @param string $message Optional. A message regarding the change. Default empty. + */ + function apply_filters_deprecated($hook_name, $args, $version, $replacement = '', $message = '') + { + } + /** + * Fires functions attached to a deprecated action hook. + * + * When an action hook is deprecated, the do_action() call is replaced with + * do_action_deprecated(), which triggers a deprecation notice and then fires + * the original hook. + * + * @since 4.6.0 + * + * @see _deprecated_hook() + * + * @param string $hook_name The name of the action hook. + * @param array $args Array of additional function arguments to be passed to do_action(). + * @param string $version The version of WordPress that deprecated the hook. + * @param string $replacement Optional. The hook that should have been used. Default empty. + * @param string $message Optional. A message regarding the change. Default empty. + */ + function do_action_deprecated($hook_name, $args, $version, $replacement = '', $message = '') + { + } + // + // Functions for handling plugins. + // + /** + * Gets the basename of a plugin. + * + * This method extracts the name of a plugin from its filename. + * + * @since 1.5.0 + * + * @global array $wp_plugin_paths + * + * @param string $file The filename of plugin. + * @return string The name of a plugin. + */ + function plugin_basename($file) + { + } + /** + * Register a plugin's real path. + * + * This is used in plugin_basename() to resolve symlinked paths. + * + * @since 3.9.0 + * + * @see wp_normalize_path() + * + * @global array $wp_plugin_paths + * + * @param string $file Known path to the file. + * @return bool Whether the path was able to be registered. + */ + function wp_register_plugin_realpath($file) + { + } + /** + * Get the filesystem directory path (with trailing slash) for the plugin __FILE__ passed in. + * + * @since 2.8.0 + * + * @param string $file The filename of the plugin (__FILE__). + * @return string the filesystem path of the directory that contains the plugin. + */ + function plugin_dir_path($file) + { + } + /** + * Get the URL directory path (with trailing slash) for the plugin __FILE__ passed in. + * + * @since 2.8.0 + * + * @param string $file The filename of the plugin (__FILE__). + * @return string the URL path of the directory that contains the plugin. + */ + function plugin_dir_url($file) + { + } + /** + * Set the activation hook for a plugin. + * + * When a plugin is activated, the action 'activate_PLUGINNAME' hook is + * called. In the name of this hook, PLUGINNAME is replaced with the name + * of the plugin, including the optional subdirectory. For example, when the + * plugin is located in wp-content/plugins/sampleplugin/sample.php, then + * the name of this hook will become 'activate_sampleplugin/sample.php'. + * + * When the plugin consists of only one file and is (as by default) located at + * wp-content/plugins/sample.php the name of this hook will be + * 'activate_sample.php'. + * + * @since 2.0.0 + * + * @param string $file The filename of the plugin including the path. + * @param callable $callback The function hooked to the 'activate_PLUGIN' action. + */ + function register_activation_hook($file, $callback) + { + } + /** + * Sets the deactivation hook for a plugin. + * + * When a plugin is deactivated, the action 'deactivate_PLUGINNAME' hook is + * called. In the name of this hook, PLUGINNAME is replaced with the name + * of the plugin, including the optional subdirectory. For example, when the + * plugin is located in wp-content/plugins/sampleplugin/sample.php, then + * the name of this hook will become 'deactivate_sampleplugin/sample.php'. + * + * When the plugin consists of only one file and is (as by default) located at + * wp-content/plugins/sample.php the name of this hook will be + * 'deactivate_sample.php'. + * + * @since 2.0.0 + * + * @param string $file The filename of the plugin including the path. + * @param callable $callback The function hooked to the 'deactivate_PLUGIN' action. + */ + function register_deactivation_hook($file, $callback) + { + } + /** + * Sets the uninstallation hook for a plugin. + * + * Registers the uninstall hook that will be called when the user clicks on the + * uninstall link that calls for the plugin to uninstall itself. The link won't + * be active unless the plugin hooks into the action. + * + * The plugin should not run arbitrary code outside of functions, when + * registering the uninstall hook. In order to run using the hook, the plugin + * will have to be included, which means that any code laying outside of a + * function will be run during the uninstallation process. The plugin should not + * hinder the uninstallation process. + * + * If the plugin can not be written without running code within the plugin, then + * the plugin should create a file named 'uninstall.php' in the base plugin + * folder. This file will be called, if it exists, during the uninstallation process + * bypassing the uninstall hook. The plugin, when using the 'uninstall.php' + * should always check for the 'WP_UNINSTALL_PLUGIN' constant, before + * executing. + * + * @since 2.7.0 + * + * @param string $file Plugin file. + * @param callable $callback The callback to run when the hook is called. Must be + * a static method or function. + */ + function register_uninstall_hook($file, $callback) + { + } + /** + * Calls the 'all' hook, which will process the functions hooked into it. + * + * The 'all' hook passes all of the arguments or parameters that were used for + * the hook, which this function was called for. + * + * This function is used internally for apply_filters(), do_action(), and + * do_action_ref_array() and is not meant to be used from outside those + * functions. This function does not check for the existence of the all hook, so + * it will fail unless the all hook exists prior to this function call. + * + * @since 2.5.0 + * @access private + * + * @global WP_Hook[] $wp_filter Stores all of the filters and actions. + * + * @param array $args The collected parameters from the hook that was called. + */ + function _wp_call_all_hook($args) + { + } + /** + * Builds Unique ID for storage and retrieval. + * + * The old way to serialize the callback caused issues and this function is the + * solution. It works by checking for objects and creating a new property in + * the class to keep track of the object and new objects of the same class that + * need to be added. + * + * It also allows for the removal of actions and filters for objects after they + * change class properties. It is possible to include the property $wp_filter_id + * in your class and set it to "null" or a number to bypass the workaround. + * However this will prevent you from adding new classes and any new classes + * will overwrite the previous hook by the same class. + * + * Functions and static method callbacks are just returned as strings and + * shouldn't have any speed penalty. + * + * @link https://core.trac.wordpress.org/ticket/3875 + * + * @since 2.2.3 + * @since 5.3.0 Removed workarounds for spl_object_hash(). + * `$hook_name` and `$priority` are no longer used, + * and the function always returns a string. + * + * @access private + * + * @param string $hook_name Unused. The name of the filter to build ID for. + * @param callable|string|array $callback The callback to generate ID for. The callback may + * or may not exist. + * @param int $priority Unused. The order in which the functions + * associated with a particular action are executed. + * @return string Unique function ID for usage as array key. + */ + function _wp_filter_build_unique_id($hook_name, $callback, $priority) + { + } + /** + * Post format functions. + * + * @package WordPress + * @subpackage Post + */ + /** + * Retrieve the format slug for a post + * + * @since 3.1.0 + * + * @param int|WP_Post|null $post Optional. Post ID or post object. Defaults to the current post in the loop. + * @return string|false The format if successful. False otherwise. + */ + function get_post_format($post = \null) + { + } + /** + * Check if a post has any of the given formats, or any format. + * + * @since 3.1.0 + * + * @param string|string[] $format Optional. The format or formats to check. + * @param WP_Post|int|null $post Optional. The post to check. Defaults to the current post in the loop. + * @return bool True if the post has any of the given formats (or any format, if no format specified), + * false otherwise. + */ + function has_post_format($format = array(), $post = \null) + { + } + /** + * Assign a format to a post + * + * @since 3.1.0 + * + * @param int|object $post The post for which to assign a format. + * @param string $format A format to assign. Use an empty string or array to remove all formats from the post. + * @return array|WP_Error|false Array of affected term IDs on success. WP_Error on error. + */ + function set_post_format($post, $format) + { + } + /** + * Returns an array of post format slugs to their translated and pretty display versions + * + * @since 3.1.0 + * + * @return string[] Array of post format labels keyed by format slug. + */ + function get_post_format_strings() + { + } + /** + * Retrieves the array of post format slugs. + * + * @since 3.1.0 + * + * @return string[] The array of post format slugs as both keys and values. + */ + function get_post_format_slugs() + { + } + /** + * Returns a pretty, translated version of a post format slug + * + * @since 3.1.0 + * + * @param string $slug A post format slug. + * @return string The translated post format name. + */ + function get_post_format_string($slug) + { + } + /** + * Returns a link to a post format index. + * + * @since 3.1.0 + * + * @param string $format The post format slug. + * @return string|WP_Error|false The post format term link. + */ + function get_post_format_link($format) + { + } + /** + * Filters the request to allow for the format prefix. + * + * @access private + * @since 3.1.0 + * + * @param array $qvs + * @return array + */ + function _post_format_request($qvs) + { + } + /** + * Filters the post format term link to remove the format prefix. + * + * @access private + * @since 3.1.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $link + * @param WP_Term $term + * @param string $taxonomy + * @return string + */ + function _post_format_link($link, $term, $taxonomy) + { + } + /** + * Remove the post format prefix from the name property of the term object created by get_term(). + * + * @access private + * @since 3.1.0 + * + * @param object $term + * @return object + */ + function _post_format_get_term($term) + { + } + /** + * Remove the post format prefix from the name property of the term objects created by get_terms(). + * + * @access private + * @since 3.1.0 + * + * @param array $terms + * @param string|array $taxonomies + * @param array $args + * @return array + */ + function _post_format_get_terms($terms, $taxonomies, $args) + { + } + /** + * Remove the post format prefix from the name property of the term objects created by wp_get_object_terms(). + * + * @access private + * @since 3.1.0 + * + * @param array $terms + * @return array + */ + function _post_format_wp_get_object_terms($terms) + { + } + /** + * WordPress Post Template Functions. + * + * Gets content for the current post in the loop. + * + * @package WordPress + * @subpackage Template + */ + /** + * Displays the ID of the current item in the WordPress Loop. + * + * @since 0.71 + */ + function the_ID() + { + } + /** + * Retrieves the ID of the current item in the WordPress Loop. + * + * @since 2.1.0 + * + * @return int|false The ID of the current item in the WordPress Loop. False if $post is not set. + */ + function get_the_ID() + { + } + /** + * Displays or retrieves the current post title with optional markup. + * + * @since 0.71 + * + * @param string $before Optional. Markup to prepend to the title. Default empty. + * @param string $after Optional. Markup to append to the title. Default empty. + * @param bool $echo Optional. Whether to echo or return the title. Default true for echo. + * @return void|string Void if `$echo` argument is true, current post title if `$echo` is false. + */ + function the_title($before = '', $after = '', $echo = \true) + { + } + /** + * Sanitizes the current title when retrieving or displaying. + * + * Works like the_title(), except the parameters can be in a string or + * an array. See the function for what can be override in the $args parameter. + * + * The title before it is displayed will have the tags stripped and esc_attr() + * before it is passed to the user or displayed. The default as with the_title(), + * is to display the title. + * + * @since 2.3.0 + * + * @param string|array $args { + * Title attribute arguments. Optional. + * + * @type string $before Markup to prepend to the title. Default empty. + * @type string $after Markup to append to the title. Default empty. + * @type bool $echo Whether to echo or return the title. Default true for echo. + * @type WP_Post $post Current post object to retrieve the title for. + * } + * @return void|string Void if 'echo' argument is true, the title attribute if 'echo' is false. + * @phpstan-param array{ + * before?: string, + * after?: string, + * echo?: bool, + * post?: WP_Post, + * } $args + */ + function the_title_attribute($args = '') + { + } + /** + * Retrieves the post title. + * + * If the post is protected and the visitor is not an admin, then "Protected" + * will be inserted before the post title. If the post is private, then + * "Private" will be inserted before the post title. + * + * @since 0.71 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @return string + */ + function get_the_title($post = 0) + { + } + /** + * Displays the Post Global Unique Identifier (guid). + * + * The guid will appear to be a link, but should not be used as a link to the + * post. The reason you should not use it as a link, is because of moving the + * blog across domains. + * + * URL is escaped to make it XML-safe. + * + * @since 1.5.0 + * + * @param int|WP_Post $post Optional. Post ID or post object. Default is global $post. + */ + function the_guid($post = 0) + { + } + /** + * Retrieves the Post Global Unique Identifier (guid). + * + * The guid will appear to be a link, but should not be used as an link to the + * post. The reason you should not use it as a link, is because of moving the + * blog across domains. + * + * @since 1.5.0 + * + * @param int|WP_Post $post Optional. Post ID or post object. Default is global $post. + * @return string + */ + function get_the_guid($post = 0) + { + } + /** + * Displays the post content. + * + * @since 0.71 + * + * @param string $more_link_text Optional. Content for when there is more text. + * @param bool $strip_teaser Optional. Strip teaser content before the more text. Default false. + */ + function the_content($more_link_text = \null, $strip_teaser = \false) + { + } + /** + * Retrieves the post content. + * + * @since 0.71 + * @since 5.2.0 Added the `$post` parameter. + * + * @global int $page Page number of a single post/page. + * @global int $more Boolean indicator for whether single post/page is being viewed. + * @global bool $preview Whether post/page is in preview mode. + * @global array $pages Array of all pages in post/page. Each array element contains + * part of the content separated by the `<!--nextpage-->` tag. + * @global int $multipage Boolean indicator for whether multiple pages are in play. + * + * @param string $more_link_text Optional. Content for when there is more text. + * @param bool $strip_teaser Optional. Strip teaser content before the more text. Default false. + * @param WP_Post|object|int $post Optional. WP_Post instance or Post ID/object. Default null. + * @return string + */ + function get_the_content($more_link_text = \null, $strip_teaser = \false, $post = \null) + { + } + /** + * Displays the post excerpt. + * + * @since 0.71 + */ + function the_excerpt() + { + } + /** + * Retrieves the post excerpt. + * + * @since 0.71 + * @since 4.5.0 Introduced the `$post` parameter. + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @return string Post excerpt. + */ + function get_the_excerpt($post = \null) + { + } + /** + * Determines whether the post has a custom excerpt. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.3.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @return bool True if the post has a custom excerpt, false otherwise. + */ + function has_excerpt($post = 0) + { + } + /** + * Displays the classes for the post container element. + * + * @since 2.7.0 + * + * @param string|string[] $class One or more classes to add to the class list. + * @param int|WP_Post $post Optional. Post ID or post object. Defaults to the global `$post`. + */ + function post_class($class = '', $post = \null) + { + } + /** + * Retrieves an array of the class names for the post container element. + * + * The class names are many. If the post is a sticky, then the 'sticky' + * class name. The class 'hentry' is always added to each post. If the post has a + * post thumbnail, 'has-post-thumbnail' is added as a class. For each taxonomy that + * the post belongs to, a class will be added of the format '{$taxonomy}-{$slug}' - + * eg 'category-foo' or 'my_custom_taxonomy-bar'. + * + * The 'post_tag' taxonomy is a special + * case; the class has the 'tag-' prefix instead of 'post_tag-'. All class names are + * passed through the filter, {@see 'post_class'}, with the list of class names, followed by + * $class parameter value, with the post ID as the last parameter. + * + * @since 2.7.0 + * @since 4.2.0 Custom taxonomy class names were added. + * + * @param string|string[] $class Space-separated string or array of class names to add to the class list. + * @param int|WP_Post $post Optional. Post ID or post object. + * @return string[] Array of class names. + */ + function get_post_class($class = '', $post = \null) + { + } + /** + * Displays the class names for the body element. + * + * @since 2.8.0 + * + * @param string|string[] $class Space-separated string or array of class names to add to the class list. + */ + function body_class($class = '') + { + } + /** + * Retrieves an array of the class names for the body element. + * + * @since 2.8.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param string|string[] $class Space-separated string or array of class names to add to the class list. + * @return string[] Array of class names. + */ + function get_body_class($class = '') + { + } + /** + * Determines whether the post requires password and whether a correct password has been provided. + * + * @since 2.7.0 + * + * @param int|WP_Post|null $post An optional post. Global $post used if not provided. + * @return bool false if a password is not required or the correct password cookie is present, true otherwise. + */ + function post_password_required($post = \null) + { + } + // + // Page Template Functions for usage in Themes. + // + /** + * The formatted output of a list of pages. + * + * Displays page links for paginated posts (i.e. including the `<!--nextpage-->` + * Quicktag one or more times). This tag must be within The Loop. + * + * @since 1.2.0 + * @since 5.1.0 Added the `aria_current` argument. + * + * @global int $page + * @global int $numpages + * @global int $multipage + * @global int $more + * + * @param string|array $args { + * Optional. Array or string of default arguments. + * + * @type string $before HTML or text to prepend to each link. Default is `<p> Pages:`. + * @type string $after HTML or text to append to each link. Default is `</p>`. + * @type string $link_before HTML or text to prepend to each link, inside the `<a>` tag. + * Also prepended to the current item, which is not linked. Default empty. + * @type string $link_after HTML or text to append to each Pages link inside the `<a>` tag. + * Also appended to the current item, which is not linked. Default empty. + * @type string $aria_current The value for the aria-current attribute. Possible values are 'page', + * 'step', 'location', 'date', 'time', 'true', 'false'. Default is 'page'. + * @type string $next_or_number Indicates whether page numbers should be used. Valid values are number + * and next. Default is 'number'. + * @type string $separator Text between pagination links. Default is ' '. + * @type string $nextpagelink Link text for the next page link, if available. Default is 'Next Page'. + * @type string $previouspagelink Link text for the previous page link, if available. Default is 'Previous Page'. + * @type string $pagelink Format string for page numbers. The % in the parameter string will be + * replaced with the page number, so 'Page %' generates "Page 1", "Page 2", etc. + * Defaults to '%', just the page number. + * @type int|bool $echo Whether to echo or not. Accepts 1|true or 0|false. Default 1|true. + * } + * @return string Formatted output in HTML. + * @phpstan-param array{ + * before?: string, + * after?: string, + * link_before?: string, + * link_after?: string, + * aria_current?: string, + * next_or_number?: string, + * separator?: string, + * nextpagelink?: string, + * previouspagelink?: string, + * pagelink?: string, + * echo?: int|bool, + * } $args + */ + function wp_link_pages($args = '') + { + } + /** + * Helper function for wp_link_pages(). + * + * @since 3.1.0 + * @access private + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param int $i Page number. + * @return string Link. + */ + function _wp_link_page($i) + { + } + // + // Post-meta: Custom per-post fields. + // + /** + * Retrieves post custom meta data field. + * + * @since 1.5.0 + * + * @param string $key Meta data key name. + * @return array|string|false Array of values, or single value if only one element exists. + * False if the key does not exist. + */ + function post_custom($key = '') + { + } + /** + * Displays a list of post custom fields. + * + * @since 1.2.0 + * + * @deprecated 6.0.2 Use get_post_meta() to retrieve post meta and render manually. + */ + function the_meta() + { + } + // + // Pages. + // + /** + * Retrieves or displays a list of pages as a dropdown (select list). + * + * @since 2.1.0 + * @since 4.2.0 The `$value_field` argument was added. + * @since 4.3.0 The `$class` argument was added. + * + * @see get_pages() + * + * @param array|string $args { + * Optional. Array or string of arguments to generate a page dropdown. See get_pages() for additional arguments. + * + * @type int $depth Maximum depth. Default 0. + * @type int $child_of Page ID to retrieve child pages of. Default 0. + * @type int|string $selected Value of the option that should be selected. Default 0. + * @type bool|int $echo Whether to echo or return the generated markup. Accepts 0, 1, + * or their bool equivalents. Default 1. + * @type string $name Value for the 'name' attribute of the select element. + * Default 'page_id'. + * @type string $id Value for the 'id' attribute of the select element. + * @type string $class Value for the 'class' attribute of the select element. Default: none. + * Defaults to the value of `$name`. + * @type string $show_option_none Text to display for showing no pages. Default empty (does not display). + * @type string $show_option_no_change Text to display for "no change" option. Default empty (does not display). + * @type string $option_none_value Value to use when no page is selected. Default empty. + * @type string $value_field Post field used to populate the 'value' attribute of the option + * elements. Accepts any valid post field. Default 'ID'. + * } + * @return string HTML dropdown list of pages. + * @phpstan-param array{ + * depth?: int, + * child_of?: int, + * selected?: int|string, + * echo?: bool|int, + * name?: string, + * id?: string, + * class?: string, + * show_option_none?: string, + * show_option_no_change?: string, + * option_none_value?: string, + * value_field?: string, + * child_of?: int, + * sort_order?: string, + * sort_column?: string, + * hierarchical?: bool, + * exclude?: int[], + * include?: int[], + * meta_key?: string, + * meta_value?: string, + * authors?: string, + * parent?: int, + * exclude_tree?: string|int[], + * number?: int, + * offset?: int, + * post_type?: string, + * post_status?: string|array, + * } $args + */ + function wp_dropdown_pages($args = '') + { + } + /** + * Retrieves or displays a list of pages (or hierarchical post type items) in list (li) format. + * + * @since 1.5.0 + * @since 4.7.0 Added the `item_spacing` argument. + * + * @see get_pages() + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param array|string $args { + * Optional. Array or string of arguments to generate a list of pages. See get_pages() for additional arguments. + * + * @type int $child_of Display only the sub-pages of a single page by ID. Default 0 (all pages). + * @type string $authors Comma-separated list of author IDs. Default empty (all authors). + * @type string $date_format PHP date format to use for the listed pages. Relies on the 'show_date' parameter. + * Default is the value of 'date_format' option. + * @type int $depth Number of levels in the hierarchy of pages to include in the generated list. + * Accepts -1 (any depth), 0 (all pages), 1 (top-level pages only), and n (pages to + * the given n depth). Default 0. + * @type bool $echo Whether or not to echo the list of pages. Default true. + * @type string $exclude Comma-separated list of page IDs to exclude. Default empty. + * @type array $include Comma-separated list of page IDs to include. Default empty. + * @type string $link_after Text or HTML to follow the page link label. Default null. + * @type string $link_before Text or HTML to precede the page link label. Default null. + * @type string $post_type Post type to query for. Default 'page'. + * @type string|array $post_status Comma-separated list or array of post statuses to include. Default 'publish'. + * @type string $show_date Whether to display the page publish or modified date for each page. Accepts + * 'modified' or any other value. An empty value hides the date. Default empty. + * @type string $sort_column Comma-separated list of column names to sort the pages by. Accepts 'post_author', + * 'post_date', 'post_title', 'post_name', 'post_modified', 'post_modified_gmt', + * 'menu_order', 'post_parent', 'ID', 'rand', or 'comment_count'. Default 'post_title'. + * @type string $title_li List heading. Passing a null or empty value will result in no heading, and the list + * will not be wrapped with unordered list `<ul>` tags. Default 'Pages'. + * @type string $item_spacing Whether to preserve whitespace within the menu's HTML. Accepts 'preserve' or 'discard'. + * Default 'preserve'. + * @type Walker $walker Walker instance to use for listing pages. Default empty which results in a + * Walker_Page instance being used. + * } + * @return void|string Void if 'echo' argument is true, HTML list of pages if 'echo' is false. + * @phpstan-param array{ + * child_of?: int, + * authors?: string, + * date_format?: string, + * depth?: int, + * echo?: bool, + * exclude?: string, + * include?: array, + * link_after?: string, + * link_before?: string, + * post_type?: string, + * post_status?: string|array, + * show_date?: string, + * sort_column?: string, + * title_li?: string, + * item_spacing?: string, + * walker?: Walker, + * child_of?: int, + * sort_order?: string, + * sort_column?: string, + * hierarchical?: bool, + * exclude?: int[], + * include?: int[], + * meta_key?: string, + * meta_value?: string, + * authors?: string, + * parent?: int, + * exclude_tree?: string|int[], + * number?: int, + * offset?: int, + * post_type?: string, + * post_status?: string|array, + * } $args + */ + function wp_list_pages($args = '') + { + } + /** + * Displays or retrieves a list of pages with an optional home link. + * + * The arguments are listed below and part of the arguments are for wp_list_pages() function. + * Check that function for more info on those arguments. + * + * @since 2.7.0 + * @since 4.4.0 Added `menu_id`, `container`, `before`, `after`, and `walker` arguments. + * @since 4.7.0 Added the `item_spacing` argument. + * + * @param array|string $args { + * Optional. Array or string of arguments to generate a page menu. See wp_list_pages() for additional arguments. + * + * @type string $sort_column How to sort the list of pages. Accepts post column names. + * Default 'menu_order, post_title'. + * @type string $menu_id ID for the div containing the page list. Default is empty string. + * @type string $menu_class Class to use for the element containing the page list. Default 'menu'. + * @type string $container Element to use for the element containing the page list. Default 'div'. + * @type bool $echo Whether to echo the list or return it. Accepts true (echo) or false (return). + * Default true. + * @type int|bool|string $show_home Whether to display the link to the home page. Can just enter the text + * you'd like shown for the home link. 1|true defaults to 'Home'. + * @type string $link_before The HTML or text to prepend to $show_home text. Default empty. + * @type string $link_after The HTML or text to append to $show_home text. Default empty. + * @type string $before The HTML or text to prepend to the menu. Default is '<ul>'. + * @type string $after The HTML or text to append to the menu. Default is '</ul>'. + * @type string $item_spacing Whether to preserve whitespace within the menu's HTML. Accepts 'preserve' + * or 'discard'. Default 'discard'. + * @type Walker $walker Walker instance to use for listing pages. Default empty which results in a + * Walker_Page instance being used. + * } + * @return void|string Void if 'echo' argument is true, HTML menu if 'echo' is false. + * @phpstan-param array{ + * sort_column?: string, + * menu_id?: string, + * menu_class?: string, + * container?: string, + * echo?: bool, + * show_home?: int|bool|string, + * link_before?: string, + * link_after?: string, + * before?: string, + * after?: string, + * item_spacing?: string, + * walker?: Walker, + * child_of?: int, + * authors?: string, + * date_format?: string, + * depth?: int, + * echo?: bool, + * exclude?: string, + * include?: array, + * link_after?: string, + * link_before?: string, + * post_type?: string, + * post_status?: string|array, + * show_date?: string, + * sort_column?: string, + * title_li?: string, + * item_spacing?: string, + * walker?: Walker, + * child_of?: int, + * sort_order?: string, + * sort_column?: string, + * hierarchical?: bool, + * exclude?: int[], + * include?: int[], + * meta_key?: string, + * meta_value?: string, + * authors?: string, + * parent?: int, + * exclude_tree?: string|int[], + * number?: int, + * offset?: int, + * post_type?: string, + * post_status?: string|array, + * } $args + */ + function wp_page_menu($args = array()) + { + } + // + // Page helpers. + // + /** + * Retrieves HTML list content for page list. + * + * @uses Walker_Page to create HTML list content. + * @since 2.1.0 + * + * @param array $pages + * @param int $depth + * @param int $current_page + * @param array $args + * @return string + */ + function walk_page_tree($pages, $depth, $current_page, $args) + { + } + /** + * Retrieves HTML dropdown (select) content for page list. + * + * @since 2.1.0 + * @since 5.3.0 Formalized the existing `...$args` parameter by adding it + * to the function signature. + * + * @uses Walker_PageDropdown to create HTML dropdown content. + * @see Walker_PageDropdown::walk() for parameters and return description. + * + * @param mixed ...$args Elements array, maximum hierarchical depth and optional additional arguments. + * @return string + */ + function walk_page_dropdown_tree(...$args) + { + } + // + // Attachments. + // + /** + * Displays an attachment page link using an image or icon. + * + * @since 2.0.0 + * + * @param int|WP_Post $post Optional. Post ID or post object. + * @param bool $fullsize Optional. Whether to use full size. Default false. + * @param bool $deprecated Deprecated. Not used. + * @param bool $permalink Optional. Whether to include permalink. Default false. + */ + function the_attachment_link($post = 0, $fullsize = \false, $deprecated = \false, $permalink = \false) + { + } + /** + * Retrieves an attachment page link using an image or icon, if possible. + * + * @since 2.5.0 + * @since 4.4.0 The `$post` parameter can now accept either a post ID or `WP_Post` object. + * + * @param int|WP_Post $post Optional. Post ID or post object. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array + * of width and height values in pixels (in that order). Default 'thumbnail'. + * @param bool $permalink Optional. Whether to add permalink to image. Default false. + * @param bool $icon Optional. Whether the attachment is an icon. Default false. + * @param string|false $text Optional. Link text to use. Activated by passing a string, false otherwise. + * Default false. + * @param array|string $attr Optional. Array or string of attributes. Default empty. + * @return string HTML content. + */ + function wp_get_attachment_link($post = 0, $size = 'thumbnail', $permalink = \false, $icon = \false, $text = \false, $attr = '') + { + } + /** + * Wraps attachment in paragraph tag before content. + * + * @since 2.0.0 + * + * @param string $content + * @return string + */ + function prepend_attachment($content) + { + } + // + // Misc. + // + /** + * Retrieves protected post password form content. + * + * @since 1.0.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @return string HTML content for password form for password protected post. + */ + function get_the_password_form($post = 0) + { + } + /** + * Determines whether the current post uses a page template. + * + * This template tag allows you to determine if you are in a page template. + * You can optionally provide a template filename or array of template filenames + * and then the check will be specific to that template. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.5.0 + * @since 4.2.0 The `$template` parameter was changed to also accept an array of page templates. + * @since 4.7.0 Now works with any post type, not just pages. + * + * @param string|string[] $template The specific template filename or array of templates to match. + * @return bool True on success, false on failure. + */ + function is_page_template($template = '') + { + } + /** + * Gets the specific template filename for a given post. + * + * @since 3.4.0 + * @since 4.7.0 Now works with any post type, not just pages. + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @return string|false Page template filename. Returns an empty string when the default page template + * is in use. Returns false if the post does not exist. + */ + function get_page_template_slug($post = \null) + { + } + /** + * Retrieves formatted date timestamp of a revision (linked to that revisions's page). + * + * @since 2.6.0 + * + * @param int|object $revision Revision ID or revision object. + * @param bool $link Optional. Whether to link to revision's page. Default true. + * @return string|false i18n formatted datetimestamp or localized 'Current Revision'. + */ + function wp_post_revision_title($revision, $link = \true) + { + } + /** + * Retrieves formatted date timestamp of a revision (linked to that revisions's page). + * + * @since 3.6.0 + * + * @param int|object $revision Revision ID or revision object. + * @param bool $link Optional. Whether to link to revision's page. Default true. + * @return string|false gravatar, user, i18n formatted datetimestamp or localized 'Current Revision'. + */ + function wp_post_revision_title_expanded($revision, $link = \true) + { + } + /** + * Displays a list of a post's revisions. + * + * Can output either a UL with edit links or a TABLE with diff interface, and + * restore action links. + * + * @since 2.6.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @param string $type 'all' (default), 'revision' or 'autosave' + */ + function wp_list_post_revisions($post = 0, $type = 'all') + { + } + /** + * Retrieves the parent post object for the given post. + * + * @since 5.7.0 + * + * @param int|WP_Post|null $post Optional. Post ID or WP_Post object. Default is global $post. + * @return WP_Post|null Parent post object, or null if there isn't one. + */ + function get_post_parent($post = \null) + { + } + /** + * Returns whether the given post has a parent post. + * + * @since 5.7.0 + * + * @param int|WP_Post|null $post Optional. Post ID or WP_Post object. Default is global $post. + * @return bool Whether the post has a parent post. + */ + function has_post_parent($post = \null) + { + } + /** + * WordPress Post Thumbnail Template Functions. + * + * Support for post thumbnails. + * Theme's functions.php must call add_theme_support( 'post-thumbnails' ) to use these. + * + * @package WordPress + * @subpackage Template + */ + /** + * Determines whether a post has an image attached. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.9.0 + * @since 4.4.0 `$post` can be a post ID or WP_Post object. + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global `$post`. + * @return bool Whether the post has an image attached. + */ + function has_post_thumbnail($post = \null) + { + } + /** + * Retrieves the post thumbnail ID. + * + * @since 2.9.0 + * @since 4.4.0 `$post` can be a post ID or WP_Post object. + * @since 5.5.0 The return value for a non-existing post + * was changed to false instead of an empty string. + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global `$post`. + * @return int|false Post thumbnail ID (which can be 0 if the thumbnail is not set), + * or false if the post does not exist. + */ + function get_post_thumbnail_id($post = \null) + { + } + /** + * Displays the post thumbnail. + * + * When a theme adds 'post-thumbnail' support, a special 'post-thumbnail' image size + * is registered, which differs from the 'thumbnail' image size managed via the + * Settings > Media screen. + * + * When using the_post_thumbnail() or related functions, the 'post-thumbnail' image + * size is used by default, though a different size can be specified instead as needed. + * + * @since 2.9.0 + * + * @see get_the_post_thumbnail() + * + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array of + * width and height values in pixels (in that order). Default 'post-thumbnail'. + * @param string|array $attr Optional. Query string or array of attributes. Default empty. + */ + function the_post_thumbnail($size = 'post-thumbnail', $attr = '') + { + } + /** + * Updates cache for thumbnails in the current loop. + * + * @since 3.2.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param WP_Query $wp_query Optional. A WP_Query instance. Defaults to the $wp_query global. + */ + function update_post_thumbnail_cache($wp_query = \null) + { + } + /** + * Retrieves the post thumbnail. + * + * When a theme adds 'post-thumbnail' support, a special 'post-thumbnail' image size + * is registered, which differs from the 'thumbnail' image size managed via the + * Settings > Media screen. + * + * When using the_post_thumbnail() or related functions, the 'post-thumbnail' image + * size is used by default, though a different size can be specified instead as needed. + * + * @since 2.9.0 + * @since 4.4.0 `$post` can be a post ID or WP_Post object. + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global `$post`. + * @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array of + * width and height values in pixels (in that order). Default 'post-thumbnail'. + * @param string|array $attr Optional. Query string or array of attributes. Default empty. + * @return string The post thumbnail image tag. + */ + function get_the_post_thumbnail($post = \null, $size = 'post-thumbnail', $attr = '') + { + } + /** + * Returns the post thumbnail URL. + * + * @since 4.4.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global `$post`. + * @param string|int[] $size Optional. Registered image size to retrieve the source for or a flat array + * of height and width dimensions. Default 'post-thumbnail'. + * @return string|false Post thumbnail URL or false if no image is available. If `$size` does not match + * any registered image size, the original image URL will be returned. + */ + function get_the_post_thumbnail_url($post = \null, $size = 'post-thumbnail') + { + } + /** + * Displays the post thumbnail URL. + * + * @since 4.4.0 + * + * @param string|int[] $size Optional. Image size to use. Accepts any valid image size, + * or an array of width and height values in pixels (in that order). + * Default 'post-thumbnail'. + */ + function the_post_thumbnail_url($size = 'post-thumbnail') + { + } + /** + * Returns the post thumbnail caption. + * + * @since 4.6.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global `$post`. + * @return string Post thumbnail caption. + */ + function get_the_post_thumbnail_caption($post = \null) + { + } + /** + * Displays the post thumbnail caption. + * + * @since 4.6.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global `$post`. + */ + function the_post_thumbnail_caption($post = \null) + { + } + /** + * Core Post API + * + * @package WordPress + * @subpackage Post + */ + // + // Post Type registration. + // + /** + * Creates the initial post types when 'init' action is fired. + * + * See {@see 'init'}. + * + * @since 2.9.0 + */ + function create_initial_post_types() + { + } + /** + * Retrieves attached file path based on attachment ID. + * + * By default the path will go through the 'get_attached_file' filter, but + * passing a true to the $unfiltered argument of get_attached_file() will + * return the file path unfiltered. + * + * The function works by getting the single post meta name, named + * '_wp_attached_file' and returning it. This is a convenience function to + * prevent looking up the meta name and provide a mechanism for sending the + * attached filename through a filter. + * + * @since 2.0.0 + * + * @param int $attachment_id Attachment ID. + * @param bool $unfiltered Optional. Whether to apply filters. Default false. + * @return string|false The file path to where the attached file should be, false otherwise. + */ + function get_attached_file($attachment_id, $unfiltered = \false) + { + } + /** + * Updates attachment file path based on attachment ID. + * + * Used to update the file path of the attachment, which uses post meta name + * '_wp_attached_file' to store the path of the attachment. + * + * @since 2.1.0 + * + * @param int $attachment_id Attachment ID. + * @param string $file File path for the attachment. + * @return bool True on success, false on failure. + */ + function update_attached_file($attachment_id, $file) + { + } + /** + * Returns relative path to an uploaded file. + * + * The path is relative to the current upload dir. + * + * @since 2.9.0 + * @access private + * + * @param string $path Full path to the file. + * @return string Relative path on success, unchanged path on failure. + */ + function _wp_relative_upload_path($path) + { + } + /** + * Retrieves all children of the post parent ID. + * + * Normally, without any enhancements, the children would apply to pages. In the + * context of the inner workings of WordPress, pages, posts, and attachments + * share the same table, so therefore the functionality could apply to any one + * of them. It is then noted that while this function does not work on posts, it + * does not mean that it won't work on posts. It is recommended that you know + * what context you wish to retrieve the children of. + * + * Attachments may also be made the child of a post, so if that is an accurate + * statement (which needs to be verified), it would then be possible to get + * all of the attachments for a post. Attachments have since changed since + * version 2.5, so this is most likely inaccurate, but serves generally as an + * example of what is possible. + * + * The arguments listed as defaults are for this function and also of the + * get_posts() function. The arguments are combined with the get_children defaults + * and are then passed to the get_posts() function, which accepts additional arguments. + * You can replace the defaults in this function, listed below and the additional + * arguments listed in the get_posts() function. + * + * The 'post_parent' is the most important argument and important attention + * needs to be paid to the $args parameter. If you pass either an object or an + * integer (number), then just the 'post_parent' is grabbed and everything else + * is lost. If you don't specify any arguments, then it is assumed that you are + * in The Loop and the post parent will be grabbed for from the current post. + * + * The 'post_parent' argument is the ID to get the children. The 'numberposts' + * is the amount of posts to retrieve that has a default of '-1', which is + * used to get all of the posts. Giving a number higher than 0 will only + * retrieve that amount of posts. + * + * The 'post_type' and 'post_status' arguments can be used to choose what + * criteria of posts to retrieve. The 'post_type' can be anything, but WordPress + * post types are 'post', 'pages', and 'attachments'. The 'post_status' + * argument will accept any post status within the write administration panels. + * + * @since 2.0.0 + * + * @see get_posts() + * @todo Check validity of description. + * + * @global WP_Post $post Global post object. + * + * @param mixed $args Optional. User defined arguments for replacing the defaults. Default empty. + * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which + * correspond to a WP_Post object, an associative array, or a numeric array, + * respectively. Default OBJECT. + * @return WP_Post[]|array[]|int[] Array of post objects, arrays, or IDs, depending on `$output`. + */ + function get_children($args = '', $output = \OBJECT) + { + } + /** + * Gets extended entry info (<!--more-->). + * + * There should not be any space after the second dash and before the word + * 'more'. There can be text or space(s) after the word 'more', but won't be + * referenced. + * + * The returned array has 'main', 'extended', and 'more_text' keys. Main has the text before + * the `<!--more-->`. The 'extended' key has the content after the + * `<!--more-->` comment. The 'more_text' key has the custom "Read More" text. + * + * @since 1.0.0 + * + * @param string $post Post content. + * @return string[] { + * Extended entry info. + * + * @type string $main Content before the more tag. + * @type string $extended Content after the more tag. + * @type string $more_text Custom read more text, or empty string. + * } + * @phpstan-return array{ + * main: string, + * extended: string, + * more_text: string, + * } + */ + function get_extended($post) + { + } + /** + * Retrieves post data given a post ID or post object. + * + * See sanitize_post() for optional $filter values. Also, the parameter + * `$post`, must be given as a variable, since it is passed by reference. + * + * @since 1.5.1 + * + * @global WP_Post $post Global post object. + * + * @param int|WP_Post|null $post Optional. Post ID or post object. `null`, `false`, `0` and other PHP falsey values + * return the current global post inside the loop. A numerically valid post ID that + * points to a non-existent post returns `null`. Defaults to global $post. + * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which + * correspond to a WP_Post object, an associative array, or a numeric array, + * respectively. Default OBJECT. + * @param string $filter Optional. Type of filter to apply. Accepts 'raw', 'edit', 'db', + * or 'display'. Default 'raw'. + * @return WP_Post|array|null Type corresponding to $output on success or null on failure. + * When $output is OBJECT, a `WP_Post` instance is returned. + */ + function get_post($post = \null, $output = \OBJECT, $filter = 'raw') + { + } + /** + * Retrieves the IDs of the ancestors of a post. + * + * @since 2.5.0 + * + * @param int|WP_Post $post Post ID or post object. + * @return int[] Array of ancestor IDs or empty array if there are none. + */ + function get_post_ancestors($post) + { + } + /** + * Retrieves data from a post field based on Post ID. + * + * Examples of the post field will be, 'post_type', 'post_status', 'post_content', + * etc and based off of the post object property or key names. + * + * The context values are based off of the taxonomy filter functions and + * supported values are found within those functions. + * + * @since 2.3.0 + * @since 4.5.0 The `$post` parameter was made optional. + * + * @see sanitize_post_field() + * + * @param string $field Post field name. + * @param int|WP_Post $post Optional. Post ID or post object. Defaults to global $post. + * @param string $context Optional. How to filter the field. Accepts 'raw', 'edit', 'db', + * or 'display'. Default 'display'. + * @return string The value of the post field on success, empty string on failure. + */ + function get_post_field($field, $post = \null, $context = 'display') + { + } + /** + * Retrieves the mime type of an attachment based on the ID. + * + * This function can be used with any post type, but it makes more sense with + * attachments. + * + * @since 2.0.0 + * + * @param int|WP_Post $post Optional. Post ID or post object. Defaults to global $post. + * @return string|false The mime type on success, false on failure. + */ + function get_post_mime_type($post = \null) + { + } + /** + * Retrieves the post status based on the post ID. + * + * If the post ID is of an attachment, then the parent post status will be given + * instead. + * + * @since 2.0.0 + * + * @param int|WP_Post $post Optional. Post ID or post object. Defaults to global $post. + * @return string|false Post status on success, false on failure. + */ + function get_post_status($post = \null) + { + } + /** + * Retrieves all of the WordPress supported post statuses. + * + * Posts have a limited set of valid status values, this provides the + * post_status values and descriptions. + * + * @since 2.5.0 + * + * @return string[] Array of post status labels keyed by their status. + */ + function get_post_statuses() + { + } + /** + * Retrieves all of the WordPress support page statuses. + * + * Pages have a limited set of valid status values, this provides the + * post_status values and descriptions. + * + * @since 2.5.0 + * + * @return string[] Array of page status labels keyed by their status. + */ + function get_page_statuses() + { + } + /** + * Returns statuses for privacy requests. + * + * @since 4.9.6 + * @access private + * + * @return array + */ + function _wp_privacy_statuses() + { + } + /** + * Registers a post status. Do not use before init. + * + * A simple function for creating or modifying a post status based on the + * parameters given. The function will accept an array (second optional + * parameter), along with a string for the post status name. + * + * Arguments prefixed with an _underscore shouldn't be used by plugins and themes. + * + * @since 3.0.0 + * + * @global stdClass[] $wp_post_statuses Inserts new post status object into the list + * + * @param string $post_status Name of the post status. + * @param array|string $args { + * Optional. Array or string of post status arguments. + * + * @type bool|string $label A descriptive name for the post status marked + * for translation. Defaults to value of $post_status. + * @type array|false $label_count Nooped plural text from _n_noop() to provide the singular + * and plural forms of the label for counts. Default false + * which means the `$label` argument will be used for both + * the singular and plural forms of this label. + * @type bool $exclude_from_search Whether to exclude posts with this post status + * from search results. Default is value of $internal. + * @type bool $_builtin Whether the status is built-in. Core-use only. + * Default false. + * @type bool $public Whether posts of this status should be shown + * in the front end of the site. Default false. + * @type bool $internal Whether the status is for internal use only. + * Default false. + * @type bool $protected Whether posts with this status should be protected. + * Default false. + * @type bool $private Whether posts with this status should be private. + * Default false. + * @type bool $publicly_queryable Whether posts with this status should be publicly- + * queryable. Default is value of $public. + * @type bool $show_in_admin_all_list Whether to include posts in the edit listing for + * their post type. Default is the opposite value + * of $internal. + * @type bool $show_in_admin_status_list Show in the list of statuses with post counts at + * the top of the edit listings, + * e.g. All (12) | Published (9) | My Custom Status (2) + * Default is the opposite value of $internal. + * @type bool $date_floating Whether the post has a floating creation date. + * Default to false. + * } + * @return object + * @phpstan-param array{ + * label?: bool|string, + * label_count?: array|false, + * exclude_from_search?: bool, + * _builtin?: bool, + * public?: bool, + * internal?: bool, + * protected?: bool, + * private?: bool, + * publicly_queryable?: bool, + * show_in_admin_all_list?: bool, + * show_in_admin_status_list?: bool, + * date_floating?: bool, + * } $args + */ + function register_post_status($post_status, $args = array()) + { + } + /** + * Retrieves a post status object by name. + * + * @since 3.0.0 + * + * @global stdClass[] $wp_post_statuses List of post statuses. + * + * @see register_post_status() + * + * @param string $post_status The name of a registered post status. + * @return stdClass|null A post status object. + */ + function get_post_status_object($post_status) + { + } + /** + * Gets a list of post statuses. + * + * @since 3.0.0 + * + * @global stdClass[] $wp_post_statuses List of post statuses. + * + * @see register_post_status() + * + * @param array|string $args Optional. Array or string of post status arguments to compare against + * properties of the global `$wp_post_statuses objects`. Default empty array. + * @param string $output Optional. The type of output to return, either 'names' or 'objects'. Default 'names'. + * @param string $operator Optional. The logical operation to perform. 'or' means only one element + * from the array needs to match; 'and' means all elements must match. + * Default 'and'. + * @return string[]|stdClass[] A list of post status names or objects. + */ + function get_post_stati($args = array(), $output = 'names', $operator = 'and') + { + } + /** + * Determines whether the post type is hierarchical. + * + * A false return value might also mean that the post type does not exist. + * + * @since 3.0.0 + * + * @see get_post_type_object() + * + * @param string $post_type Post type name + * @return bool Whether post type is hierarchical. + */ + function is_post_type_hierarchical($post_type) + { + } + /** + * Determines whether a post type is registered. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 3.0.0 + * + * @see get_post_type_object() + * + * @param string $post_type Post type name. + * @return bool Whether post type is registered. + */ + function post_type_exists($post_type) + { + } + /** + * Retrieves the post type of the current post or of a given post. + * + * @since 2.1.0 + * + * @param int|WP_Post|null $post Optional. Post ID or post object. Default is global $post. + * @return string|false Post type on success, false on failure. + */ + function get_post_type($post = \null) + { + } + /** + * Retrieves a post type object by name. + * + * @since 3.0.0 + * @since 4.6.0 Object returned is now an instance of `WP_Post_Type`. + * + * @global array $wp_post_types List of post types. + * + * @see register_post_type() + * + * @param string $post_type The name of a registered post type. + * @return WP_Post_Type|null WP_Post_Type object if it exists, null otherwise. + */ + function get_post_type_object($post_type) + { + } + /** + * Gets a list of all registered post type objects. + * + * @since 2.9.0 + * + * @global array $wp_post_types List of post types. + * + * @see register_post_type() for accepted arguments. + * + * @param array|string $args Optional. An array of key => value arguments to match against + * the post type objects. Default empty array. + * @param string $output Optional. The type of output to return. Accepts post type 'names' + * or 'objects'. Default 'names'. + * @param string $operator Optional. The logical operation to perform. 'or' means only one + * element from the array needs to match; 'and' means all elements + * must match; 'not' means no elements may match. Default 'and'. + * @return string[]|WP_Post_Type[] An array of post type names or objects. + */ + function get_post_types($args = array(), $output = 'names', $operator = 'and') + { + } + /** + * Registers a post type. + * + * Note: Post type registrations should not be hooked before the + * {@see 'init'} action. Also, any taxonomy connections should be + * registered via the `$taxonomies` argument to ensure consistency + * when hooks such as {@see 'parse_query'} or {@see 'pre_get_posts'} + * are used. + * + * Post types can support any number of built-in core features such + * as meta boxes, custom fields, post thumbnails, post statuses, + * comments, and more. See the `$supports` argument for a complete + * list of supported features. + * + * @since 2.9.0 + * @since 3.0.0 The `show_ui` argument is now enforced on the new post screen. + * @since 4.4.0 The `show_ui` argument is now enforced on the post type listing + * screen and post editing screen. + * @since 4.6.0 Post type object returned is now an instance of `WP_Post_Type`. + * @since 4.7.0 Introduced `show_in_rest`, `rest_base` and `rest_controller_class` + * arguments to register the post type in REST API. + * @since 5.0.0 The `template` and `template_lock` arguments were added. + * @since 5.3.0 The `supports` argument will now accept an array of arguments for a feature. + * @since 5.9.0 The `rest_namespace` argument was added. + * + * @global array $wp_post_types List of post types. + * + * @param string $post_type Post type key. Must not exceed 20 characters and may + * only contain lowercase alphanumeric characters, dashes, + * and underscores. See sanitize_key(). + * @param array|string $args { + * Array or string of arguments for registering a post type. + * + * @type string $label Name of the post type shown in the menu. Usually plural. + * Default is value of $labels['name']. + * @type string[] $labels An array of labels for this post type. If not set, post + * labels are inherited for non-hierarchical types and page + * labels for hierarchical ones. See get_post_type_labels() for a full + * list of supported labels. + * @type string $description A short descriptive summary of what the post type is. + * Default empty. + * @type bool $public Whether a post type is intended for use publicly either via + * the admin interface or by front-end users. While the default + * settings of $exclude_from_search, $publicly_queryable, $show_ui, + * and $show_in_nav_menus are inherited from $public, each does not + * rely on this relationship and controls a very specific intention. + * Default false. + * @type bool $hierarchical Whether the post type is hierarchical (e.g. page). Default false. + * @type bool $exclude_from_search Whether to exclude posts with this post type from front end search + * results. Default is the opposite value of $public. + * @type bool $publicly_queryable Whether queries can be performed on the front end for the post type + * as part of parse_request(). Endpoints would include: + * * ?post_type={post_type_key} + * * ?{post_type_key}={single_post_slug} + * * ?{post_type_query_var}={single_post_slug} + * If not set, the default is inherited from $public. + * @type bool $show_ui Whether to generate and allow a UI for managing this post type in the + * admin. Default is value of $public. + * @type bool|string $show_in_menu Where to show the post type in the admin menu. To work, $show_ui + * must be true. If true, the post type is shown in its own top level + * menu. If false, no menu is shown. If a string of an existing top + * level menu ('tools.php' or 'edit.php?post_type=page', for example), the + * post type will be placed as a sub-menu of that. + * Default is value of $show_ui. + * @type bool $show_in_nav_menus Makes this post type available for selection in navigation menus. + * Default is value of $public. + * @type bool $show_in_admin_bar Makes this post type available via the admin bar. Default is value + * of $show_in_menu. + * @type bool $show_in_rest Whether to include the post type in the REST API. Set this to true + * for the post type to be available in the block editor. + * @type string $rest_base To change the base URL of REST API route. Default is $post_type. + * @type string $rest_namespace To change the namespace URL of REST API route. Default is wp/v2. + * @type string $rest_controller_class REST API controller class name. Default is 'WP_REST_Posts_Controller'. + * @type int $menu_position The position in the menu order the post type should appear. To work, + * $show_in_menu must be true. Default null (at the bottom). + * @type string $menu_icon The URL to the icon to be used for this menu. Pass a base64-encoded + * SVG using a data URI, which will be colored to match the color scheme + * -- this should begin with 'data:image/svg+xml;base64,'. Pass the name + * of a Dashicons helper class to use a font icon, e.g. + * 'dashicons-chart-pie'. Pass 'none' to leave div.wp-menu-image empty + * so an icon can be added via CSS. Defaults to use the posts icon. + * @type string|array $capability_type The string to use to build the read, edit, and delete capabilities. + * May be passed as an array to allow for alternative plurals when using + * this argument as a base to construct the capabilities, e.g. + * array('story', 'stories'). Default 'post'. + * @type string[] $capabilities Array of capabilities for this post type. $capability_type is used + * as a base to construct capabilities by default. + * See get_post_type_capabilities(). + * @type bool $map_meta_cap Whether to use the internal default meta capability handling. + * Default false. + * @type array $supports Core feature(s) the post type supports. Serves as an alias for calling + * add_post_type_support() directly. Core features include 'title', + * 'editor', 'comments', 'revisions', 'trackbacks', 'author', 'excerpt', + * 'page-attributes', 'thumbnail', 'custom-fields', and 'post-formats'. + * Additionally, the 'revisions' feature dictates whether the post type + * will store revisions, and the 'comments' feature dictates whether the + * comments count will show on the edit screen. A feature can also be + * specified as an array of arguments to provide additional information + * about supporting that feature. + * Example: `array( 'my_feature', array( 'field' => 'value' ) )`. + * Default is an array containing 'title' and 'editor'. + * @type callable $register_meta_box_cb Provide a callback function that sets up the meta boxes for the + * edit form. Do remove_meta_box() and add_meta_box() calls in the + * callback. Default null. + * @type string[] $taxonomies An array of taxonomy identifiers that will be registered for the + * post type. Taxonomies can be registered later with register_taxonomy() + * or register_taxonomy_for_object_type(). + * Default empty array. + * @type bool|string $has_archive Whether there should be post type archives, or if a string, the + * archive slug to use. Will generate the proper rewrite rules if + * $rewrite is enabled. Default false. + * @type bool|array $rewrite { + * Triggers the handling of rewrites for this post type. To prevent rewrite, set to false. + * Defaults to true, using $post_type as slug. To specify rewrite rules, an array can be + * passed with any of these keys: + * + * @type string $slug Customize the permastruct slug. Defaults to $post_type key. + * @type bool $with_front Whether the permastruct should be prepended with WP_Rewrite::$front. + * Default true. + * @type bool $feeds Whether the feed permastruct should be built for this post type. + * Default is value of $has_archive. + * @type bool $pages Whether the permastruct should provide for pagination. Default true. + * @type int $ep_mask Endpoint mask to assign. If not specified and permalink_epmask is set, + * inherits from $permalink_epmask. If not specified and permalink_epmask + * is not set, defaults to EP_PERMALINK. + * } + * @type string|bool $query_var Sets the query_var key for this post type. Defaults to $post_type + * key. If false, a post type cannot be loaded at + * ?{query_var}={post_slug}. If specified as a string, the query + * ?{query_var_string}={post_slug} will be valid. + * @type bool $can_export Whether to allow this post type to be exported. Default true. + * @type bool $delete_with_user Whether to delete posts of this type when deleting a user. + * * If true, posts of this type belonging to the user will be moved + * to Trash when the user is deleted. + * * If false, posts of this type belonging to the user will *not* + * be trashed or deleted. + * * If not set (the default), posts are trashed if post type supports + * the 'author' feature. Otherwise posts are not trashed or deleted. + * Default null. + * @type array $template Array of blocks to use as the default initial state for an editor + * session. Each item should be an array containing block name and + * optional attributes. Default empty array. + * @type string|false $template_lock Whether the block template should be locked if $template is set. + * * If set to 'all', the user is unable to insert new blocks, + * move existing blocks and delete blocks. + * * If set to 'insert', the user is able to move existing blocks + * but is unable to insert new blocks and delete blocks. + * Default false. + * @type bool $_builtin FOR INTERNAL USE ONLY! True if this post type is a native or + * "built-in" post_type. Default false. + * @type string $_edit_link FOR INTERNAL USE ONLY! URL segment to use for edit link of + * this post type. Default 'post.php?post=%d'. + * } + * @return WP_Post_Type|WP_Error The registered post type object on success, + * WP_Error object on failure. + * @phpstan-param array{ + * label?: string, + * labels?: string[], + * description?: string, + * public?: bool, + * hierarchical?: bool, + * exclude_from_search?: bool, + * publicly_queryable?: bool, + * show_ui?: bool, + * show_in_menu?: bool|string, + * show_in_nav_menus?: bool, + * show_in_admin_bar?: bool, + * show_in_rest?: bool, + * rest_base?: string, + * rest_namespace?: string, + * rest_controller_class?: string, + * menu_position?: int, + * menu_icon?: string, + * capability_type?: string|array, + * capabilities?: string[], + * map_meta_cap?: bool, + * supports?: array, + * register_meta_box_cb?: callable, + * taxonomies?: string[], + * has_archive?: bool|string, + * rewrite?: bool|array{ + * slug?: string, + * with_front?: bool, + * feeds?: bool, + * pages?: bool, + * ep_mask?: int, + * }, + * query_var?: string|bool, + * can_export?: bool, + * delete_with_user?: bool, + * template?: array, + * template_lock?: string|false, + * _builtin?: bool, + * _edit_link?: string, + * } $args + */ + function register_post_type($post_type, $args = array()) + { + } + /** + * Unregisters a post type. + * + * Cannot be used to unregister built-in post types. + * + * @since 4.5.0 + * + * @global array $wp_post_types List of post types. + * + * @param string $post_type Post type to unregister. + * @return true|WP_Error True on success, WP_Error on failure or if the post type doesn't exist. + */ + function unregister_post_type($post_type) + { + } + /** + * Builds an object with all post type capabilities out of a post type object + * + * Post type capabilities use the 'capability_type' argument as a base, if the + * capability is not set in the 'capabilities' argument array or if the + * 'capabilities' argument is not supplied. + * + * The capability_type argument can optionally be registered as an array, with + * the first value being singular and the second plural, e.g. array('story, 'stories') + * Otherwise, an 's' will be added to the value for the plural form. After + * registration, capability_type will always be a string of the singular value. + * + * By default, eight keys are accepted as part of the capabilities array: + * + * - edit_post, read_post, and delete_post are meta capabilities, which are then + * generally mapped to corresponding primitive capabilities depending on the + * context, which would be the post being edited/read/deleted and the user or + * role being checked. Thus these capabilities would generally not be granted + * directly to users or roles. + * + * - edit_posts - Controls whether objects of this post type can be edited. + * - edit_others_posts - Controls whether objects of this type owned by other users + * can be edited. If the post type does not support an author, then this will + * behave like edit_posts. + * - delete_posts - Controls whether objects of this post type can be deleted. + * - publish_posts - Controls publishing objects of this post type. + * - read_private_posts - Controls whether private objects can be read. + * + * These five primitive capabilities are checked in core in various locations. + * There are also six other primitive capabilities which are not referenced + * directly in core, except in map_meta_cap(), which takes the three aforementioned + * meta capabilities and translates them into one or more primitive capabilities + * that must then be checked against the user or role, depending on the context. + * + * - read - Controls whether objects of this post type can be read. + * - delete_private_posts - Controls whether private objects can be deleted. + * - delete_published_posts - Controls whether published objects can be deleted. + * - delete_others_posts - Controls whether objects owned by other users can be + * can be deleted. If the post type does not support an author, then this will + * behave like delete_posts. + * - edit_private_posts - Controls whether private objects can be edited. + * - edit_published_posts - Controls whether published objects can be edited. + * + * These additional capabilities are only used in map_meta_cap(). Thus, they are + * only assigned by default if the post type is registered with the 'map_meta_cap' + * argument set to true (default is false). + * + * @since 3.0.0 + * @since 5.4.0 'delete_posts' is included in default capabilities. + * + * @see register_post_type() + * @see map_meta_cap() + * + * @param object $args Post type registration arguments. + * @return object Object with all the capabilities as member variables. + */ + function get_post_type_capabilities($args) + { + } + /** + * Stores or returns a list of post type meta caps for map_meta_cap(). + * + * @since 3.1.0 + * @access private + * + * @global array $post_type_meta_caps Used to store meta capabilities. + * + * @param string[] $capabilities Post type meta capabilities. + */ + function _post_type_meta_capabilities($capabilities = \null) + { + } + /** + * Builds an object with all post type labels out of a post type object. + * + * Accepted keys of the label array in the post type object: + * + * - `name` - General name for the post type, usually plural. The same and overridden + * by `$post_type_object->label`. Default is 'Posts' / 'Pages'. + * - `singular_name` - Name for one object of this post type. Default is 'Post' / 'Page'. + * - `add_new` - Default is 'Add New' for both hierarchical and non-hierarchical types. + * When internationalizing this string, please use a {@link https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/#disambiguation-by-context gettext context} + * matching your post type. Example: `_x( 'Add New', 'product', 'textdomain' );`. + * - `add_new_item` - Label for adding a new singular item. Default is 'Add New Post' / 'Add New Page'. + * - `edit_item` - Label for editing a singular item. Default is 'Edit Post' / 'Edit Page'. + * - `new_item` - Label for the new item page title. Default is 'New Post' / 'New Page'. + * - `view_item` - Label for viewing a singular item. Default is 'View Post' / 'View Page'. + * - `view_items` - Label for viewing post type archives. Default is 'View Posts' / 'View Pages'. + * - `search_items` - Label for searching plural items. Default is 'Search Posts' / 'Search Pages'. + * - `not_found` - Label used when no items are found. Default is 'No posts found' / 'No pages found'. + * - `not_found_in_trash` - Label used when no items are in the Trash. Default is 'No posts found in Trash' / + * 'No pages found in Trash'. + * - `parent_item_colon` - Label used to prefix parents of hierarchical items. Not used on non-hierarchical + * post types. Default is 'Parent Page:'. + * - `all_items` - Label to signify all items in a submenu link. Default is 'All Posts' / 'All Pages'. + * - `archives` - Label for archives in nav menus. Default is 'Post Archives' / 'Page Archives'. + * - `attributes` - Label for the attributes meta box. Default is 'Post Attributes' / 'Page Attributes'. + * - `insert_into_item` - Label for the media frame button. Default is 'Insert into post' / 'Insert into page'. + * - `uploaded_to_this_item` - Label for the media frame filter. Default is 'Uploaded to this post' / + * 'Uploaded to this page'. + * - `featured_image` - Label for the featured image meta box title. Default is 'Featured image'. + * - `set_featured_image` - Label for setting the featured image. Default is 'Set featured image'. + * - `remove_featured_image` - Label for removing the featured image. Default is 'Remove featured image'. + * - `use_featured_image` - Label in the media frame for using a featured image. Default is 'Use as featured image'. + * - `menu_name` - Label for the menu name. Default is the same as `name`. + * - `filter_items_list` - Label for the table views hidden heading. Default is 'Filter posts list' / + * 'Filter pages list'. + * - `filter_by_date` - Label for the date filter in list tables. Default is 'Filter by date'. + * - `items_list_navigation` - Label for the table pagination hidden heading. Default is 'Posts list navigation' / + * 'Pages list navigation'. + * - `items_list` - Label for the table hidden heading. Default is 'Posts list' / 'Pages list'. + * - `item_published` - Label used when an item is published. Default is 'Post published.' / 'Page published.' + * - `item_published_privately` - Label used when an item is published with private visibility. + * Default is 'Post published privately.' / 'Page published privately.' + * - `item_reverted_to_draft` - Label used when an item is switched to a draft. + * Default is 'Post reverted to draft.' / 'Page reverted to draft.' + * - `item_scheduled` - Label used when an item is scheduled for publishing. Default is 'Post scheduled.' / + * 'Page scheduled.' + * - `item_updated` - Label used when an item is updated. Default is 'Post updated.' / 'Page updated.' + * - `item_link` - Title for a navigation link block variation. Default is 'Post Link' / 'Page Link'. + * - `item_link_description` - Description for a navigation link block variation. Default is 'A link to a post.' / + * 'A link to a page.' + * + * Above, the first default value is for non-hierarchical post types (like posts) + * and the second one is for hierarchical post types (like pages). + * + * Note: To set labels used in post type admin notices, see the {@see 'post_updated_messages'} filter. + * + * @since 3.0.0 + * @since 4.3.0 Added the `featured_image`, `set_featured_image`, `remove_featured_image`, + * and `use_featured_image` labels. + * @since 4.4.0 Added the `archives`, `insert_into_item`, `uploaded_to_this_item`, `filter_items_list`, + * `items_list_navigation`, and `items_list` labels. + * @since 4.6.0 Converted the `$post_type` parameter to accept a `WP_Post_Type` object. + * @since 4.7.0 Added the `view_items` and `attributes` labels. + * @since 5.0.0 Added the `item_published`, `item_published_privately`, `item_reverted_to_draft`, + * `item_scheduled`, and `item_updated` labels. + * @since 5.7.0 Added the `filter_by_date` label. + * @since 5.8.0 Added the `item_link` and `item_link_description` labels. + * + * @access private + * + * @param object|WP_Post_Type $post_type_object Post type object. + * @return object Object with all the labels as member variables. + */ + function get_post_type_labels($post_type_object) + { + } + /** + * Builds an object with custom-something object (post type, taxonomy) labels + * out of a custom-something object + * + * @since 3.0.0 + * @access private + * + * @param object $object A custom-something object. + * @param array $nohier_vs_hier_defaults Hierarchical vs non-hierarchical default labels. + * @return object Object containing labels for the given custom-something object. + */ + function _get_custom_object_labels($object, $nohier_vs_hier_defaults) + { + } + /** + * Adds submenus for post types. + * + * @access private + * @since 3.1.0 + */ + function _add_post_type_submenus() + { + } + /** + * Registers support of certain features for a post type. + * + * All core features are directly associated with a functional area of the edit + * screen, such as the editor or a meta box. Features include: 'title', 'editor', + * 'comments', 'revisions', 'trackbacks', 'author', 'excerpt', 'page-attributes', + * 'thumbnail', 'custom-fields', and 'post-formats'. + * + * Additionally, the 'revisions' feature dictates whether the post type will + * store revisions, and the 'comments' feature dictates whether the comments + * count will show on the edit screen. + * + * A third, optional parameter can also be passed along with a feature to provide + * additional information about supporting that feature. + * + * Example usage: + * + * add_post_type_support( 'my_post_type', 'comments' ); + * add_post_type_support( 'my_post_type', array( + * 'author', 'excerpt', + * ) ); + * add_post_type_support( 'my_post_type', 'my_feature', array( + * 'field' => 'value', + * ) ); + * + * @since 3.0.0 + * @since 5.3.0 Formalized the existing and already documented `...$args` parameter + * by adding it to the function signature. + * + * @global array $_wp_post_type_features + * + * @param string $post_type The post type for which to add the feature. + * @param string|array $feature The feature being added, accepts an array of + * feature strings or a single string. + * @param mixed ...$args Optional extra arguments to pass along with certain features. + */ + function add_post_type_support($post_type, $feature, ...$args) + { + } + /** + * Removes support for a feature from a post type. + * + * @since 3.0.0 + * + * @global array $_wp_post_type_features + * + * @param string $post_type The post type for which to remove the feature. + * @param string $feature The feature being removed. + */ + function remove_post_type_support($post_type, $feature) + { + } + /** + * Gets all the post type features + * + * @since 3.4.0 + * + * @global array $_wp_post_type_features + * + * @param string $post_type The post type. + * @return array Post type supports list. + */ + function get_all_post_type_supports($post_type) + { + } + /** + * Checks a post type's support for a given feature. + * + * @since 3.0.0 + * + * @global array $_wp_post_type_features + * + * @param string $post_type The post type being checked. + * @param string $feature The feature being checked. + * @return bool Whether the post type supports the given feature. + */ + function post_type_supports($post_type, $feature) + { + } + /** + * Retrieves a list of post type names that support a specific feature. + * + * @since 4.5.0 + * + * @global array $_wp_post_type_features Post type features + * + * @param array|string $feature Single feature or an array of features the post types should support. + * @param string $operator Optional. The logical operation to perform. 'or' means + * only one element from the array needs to match; 'and' + * means all elements must match; 'not' means no elements may + * match. Default 'and'. + * @return string[] A list of post type names. + */ + function get_post_types_by_support($feature, $operator = 'and') + { + } + /** + * Updates the post type for the post ID. + * + * The page or post cache will be cleaned for the post ID. + * + * @since 2.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $post_id Optional. Post ID to change post type. Default 0. + * @param string $post_type Optional. Post type. Accepts 'post' or 'page' to + * name a few. Default 'post'. + * @return int|false Amount of rows changed. Should be 1 for success and 0 for failure. + */ + function set_post_type($post_id = 0, $post_type = 'post') + { + } + /** + * Determines whether a post type is considered "viewable". + * + * For built-in post types such as posts and pages, the 'public' value will be evaluated. + * For all others, the 'publicly_queryable' value will be used. + * + * @since 4.4.0 + * @since 4.5.0 Added the ability to pass a post type name in addition to object. + * @since 4.6.0 Converted the `$post_type` parameter to accept a `WP_Post_Type` object. + * @since 5.9.0 Added `is_post_type_viewable` hook to filter the result. + * + * @param string|WP_Post_Type $post_type Post type name or object. + * @return bool Whether the post type should be considered viewable. + */ + function is_post_type_viewable($post_type) + { + } + /** + * Determines whether a post status is considered "viewable". + * + * For built-in post statuses such as publish and private, the 'public' value will be evaluated. + * For all others, the 'publicly_queryable' value will be used. + * + * @since 5.7.0 + * @since 5.9.0 Added `is_post_status_viewable` hook to filter the result. + * + * @param string|stdClass $post_status Post status name or object. + * @return bool Whether the post status should be considered viewable. + */ + function is_post_status_viewable($post_status) + { + } + /** + * Determines whether a post is publicly viewable. + * + * Posts are considered publicly viewable if both the post status and post type + * are viewable. + * + * @since 5.7.0 + * + * @param int|WP_Post|null $post Optional. Post ID or post object. Defaults to global $post. + * @return bool Whether the post is publicly viewable. + */ + function is_post_publicly_viewable($post = \null) + { + } + /** + * Retrieves an array of the latest posts, or posts matching the given criteria. + * + * For more information on the accepted arguments, see the + * {@link https://developer.wordpress.org/reference/classes/wp_query/ + * WP_Query} documentation in the Developer Handbook. + * + * The `$ignore_sticky_posts` and `$no_found_rows` arguments are ignored by + * this function and both are set to `true`. + * + * The defaults are as follows: + * + * @since 1.2.0 + * + * @see WP_Query + * @see WP_Query::parse_query() + * + * @param array $args { + * Optional. Arguments to retrieve posts. See WP_Query::parse_query() for all available arguments. + * + * @type int $numberposts Total number of posts to retrieve. Is an alias of `$posts_per_page` + * in WP_Query. Accepts -1 for all. Default 5. + * @type int|string $category Category ID or comma-separated list of IDs (this or any children). + * Is an alias of `$cat` in WP_Query. Default 0. + * @type int[] $include An array of post IDs to retrieve, sticky posts will be included. + * Is an alias of `$post__in` in WP_Query. Default empty array. + * @type int[] $exclude An array of post IDs not to retrieve. Default empty array. + * @type bool $suppress_filters Whether to suppress filters. Default true. + * } + * @return WP_Post[]|int[] Array of post objects or post IDs. + * @phpstan-param array{ + * numberposts?: int, + * category?: int|string, + * include?: int[], + * exclude?: int[], + * suppress_filters?: bool, + * attachment_id?: int, + * author?: int|string, + * author_name?: string, + * author__in?: int[], + * author__not_in?: int[], + * cache_results?: bool, + * cat?: int|string, + * category__and?: int[], + * category__in?: int[], + * category__not_in?: int[], + * category_name?: string, + * comment_count?: array|int, + * comment_status?: string, + * comments_per_page?: int, + * date_query?: array, + * day?: int, + * exact?: bool, + * fields?: string, + * hour?: int, + * ignore_sticky_posts?: int|bool, + * m?: int, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * menu_order?: int, + * minute?: int, + * monthnum?: int, + * name?: string, + * nopaging?: bool, + * no_found_rows?: bool, + * offset?: int, + * order?: string, + * orderby?: string|array, + * p?: int, + * page?: int, + * paged?: int, + * page_id?: int, + * pagename?: string, + * perm?: string, + * ping_status?: string, + * post__in?: int[], + * post__not_in?: int[], + * post_mime_type?: string, + * post_name__in?: string[], + * post_parent?: int, + * post_parent__in?: int[], + * post_parent__not_in?: int[], + * post_type?: string|string[], + * post_status?: string|string[], + * posts_per_page?: int, + * posts_per_archive_page?: int, + * s?: string, + * second?: int, + * sentence?: bool, + * suppress_filters?: bool, + * tag?: string, + * tag__and?: int[], + * tag__in?: int[], + * tag__not_in?: int[], + * tag_id?: int, + * tag_slug__and?: string[], + * tag_slug__in?: string[], + * tax_query?: array, + * title?: string, + * update_post_meta_cache?: bool, + * update_post_term_cache?: bool, + * update_menu_item_cache?: bool, + * lazy_load_term_meta?: bool, + * w?: int, + * year?: int, + * } $args + */ + function get_posts($args = \null) + { + } + // + // Post meta functions. + // + /** + * Adds a meta field to the given post. + * + * Post meta data is called "Custom Fields" on the Administration Screen. + * + * @since 1.5.0 + * + * @param int $post_id Post ID. + * @param string $meta_key Metadata name. + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. + * @param bool $unique Optional. Whether the same key should not be added. + * Default false. + * @return int|false Meta ID on success, false on failure. + */ + function add_post_meta($post_id, $meta_key, $meta_value, $unique = \false) + { + } + /** + * Deletes a post meta field for the given post ID. + * + * You can match based on the key, or key and value. Removing based on key and + * value, will keep from removing duplicate metadata with the same key. It also + * allows removing all metadata matching the key, if needed. + * + * @since 1.5.0 + * + * @param int $post_id Post ID. + * @param string $meta_key Metadata name. + * @param mixed $meta_value Optional. Metadata value. If provided, + * rows will only be removed that match the value. + * Must be serializable if non-scalar. Default empty. + * @return bool True on success, false on failure. + */ + function delete_post_meta($post_id, $meta_key, $meta_value = '') + { + } + /** + * Retrieves a post meta field for the given post ID. + * + * @since 1.5.0 + * + * @param int $post_id Post ID. + * @param string $key Optional. The meta key to retrieve. By default, + * returns data for all keys. Default empty. + * @param bool $single Optional. Whether to return a single value. + * This parameter has no effect if `$key` is not specified. + * Default false. + * @return mixed An array of values if `$single` is false. + * The value of the meta field if `$single` is true. + * False for an invalid `$post_id` (non-numeric, zero, or negative value). + * An empty string if a valid but non-existing post ID is passed. + */ + function get_post_meta($post_id, $key = '', $single = \false) + { + } + /** + * Updates a post meta field based on the given post ID. + * + * Use the `$prev_value` parameter to differentiate between meta fields with the + * same key and post ID. + * + * If the meta field for the post does not exist, it will be added and its ID returned. + * + * Can be used in place of add_post_meta(). + * + * @since 1.5.0 + * + * @param int $post_id Post ID. + * @param string $meta_key Metadata key. + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. + * @param mixed $prev_value Optional. Previous value to check before updating. + * If specified, only update existing metadata entries with + * this value. Otherwise, update all entries. Default empty. + * @return int|bool Meta ID if the key didn't exist, true on successful update, + * false on failure or if the value passed to the function + * is the same as the one that is already in the database. + */ + function update_post_meta($post_id, $meta_key, $meta_value, $prev_value = '') + { + } + /** + * Deletes everything from post meta matching the given meta key. + * + * @since 2.3.0 + * + * @param string $post_meta_key Key to search for when deleting. + * @return bool Whether the post meta key was deleted from the database. + */ + function delete_post_meta_by_key($post_meta_key) + { + } + /** + * Registers a meta key for posts. + * + * @since 4.9.8 + * + * @param string $post_type Post type to register a meta key for. Pass an empty string + * to register the meta key across all existing post types. + * @param string $meta_key The meta key to register. + * @param array $args Data used to describe the meta key when registered. See + * {@see register_meta()} for a list of supported arguments. + * @return bool True if the meta key was successfully registered, false if not. + */ + function register_post_meta($post_type, $meta_key, array $args) + { + } + /** + * Unregisters a meta key for posts. + * + * @since 4.9.8 + * + * @param string $post_type Post type the meta key is currently registered for. Pass + * an empty string if the meta key is registered across all + * existing post types. + * @param string $meta_key The meta key to unregister. + * @return bool True on success, false if the meta key was not previously registered. + */ + function unregister_post_meta($post_type, $meta_key) + { + } + /** + * Retrieves post meta fields, based on post ID. + * + * The post meta fields are retrieved from the cache where possible, + * so the function is optimized to be called more than once. + * + * @since 1.2.0 + * + * @param int $post_id Optional. Post ID. Default is the ID of the global `$post`. + * @return mixed An array of values. + * False for an invalid `$post_id` (non-numeric, zero, or negative value). + * An empty string if a valid but non-existing post ID is passed. + */ + function get_post_custom($post_id = 0) + { + } + /** + * Retrieves meta field names for a post. + * + * If there are no meta fields, then nothing (null) will be returned. + * + * @since 1.2.0 + * + * @param int $post_id Optional. Post ID. Default is the ID of the global `$post`. + * @return array|void Array of the keys, if retrieved. + */ + function get_post_custom_keys($post_id = 0) + { + } + /** + * Retrieves values for a custom post field. + * + * The parameters must not be considered optional. All of the post meta fields + * will be retrieved and only the meta field key values returned. + * + * @since 1.2.0 + * + * @param string $key Optional. Meta field key. Default empty. + * @param int $post_id Optional. Post ID. Default is the ID of the global `$post`. + * @return array|null Meta field values. + */ + function get_post_custom_values($key = '', $post_id = 0) + { + } + /** + * Determines whether a post is sticky. + * + * Sticky posts should remain at the top of The Loop. If the post ID is not + * given, then The Loop ID for the current post will be used. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.7.0 + * + * @param int $post_id Optional. Post ID. Default is the ID of the global `$post`. + * @return bool Whether post is sticky. + */ + function is_sticky($post_id = 0) + { + } + /** + * Sanitizes every post field. + * + * If the context is 'raw', then the post object or array will get minimal + * sanitization of the integer fields. + * + * @since 2.3.0 + * + * @see sanitize_post_field() + * + * @param object|WP_Post|array $post The post object or array + * @param string $context Optional. How to sanitize post fields. + * Accepts 'raw', 'edit', 'db', 'display', + * 'attribute', or 'js'. Default 'display'. + * @return object|WP_Post|array The now sanitized post object or array (will be the + * same type as `$post`). + * @phpstan-template T of array|object + * @phpstan-param T $post + * @phpstan-return T + */ + function sanitize_post($post, $context = 'display') + { + } + /** + * Sanitizes a post field based on context. + * + * Possible context values are: 'raw', 'edit', 'db', 'display', 'attribute' and + * 'js'. The 'display' context is used by default. 'attribute' and 'js' contexts + * are treated like 'display' when calling filters. + * + * @since 2.3.0 + * @since 4.4.0 Like `sanitize_post()`, `$context` defaults to 'display'. + * + * @param string $field The Post Object field name. + * @param mixed $value The Post Object value. + * @param int $post_id Post ID. + * @param string $context Optional. How to sanitize the field. Possible values are 'raw', 'edit', + * 'db', 'display', 'attribute' and 'js'. Default 'display'. + * @return mixed Sanitized value. + */ + function sanitize_post_field($field, $value, $post_id, $context = 'display') + { + } + /** + * Makes a post sticky. + * + * Sticky posts should be displayed at the top of the front page. + * + * @since 2.7.0 + * + * @param int $post_id Post ID. + */ + function stick_post($post_id) + { + } + /** + * Un-sticks a post. + * + * Sticky posts should be displayed at the top of the front page. + * + * @since 2.7.0 + * + * @param int $post_id Post ID. + */ + function unstick_post($post_id) + { + } + /** + * Returns the cache key for wp_count_posts() based on the passed arguments. + * + * @since 3.9.0 + * @access private + * + * @param string $type Optional. Post type to retrieve count Default 'post'. + * @param string $perm Optional. 'readable' or empty. Default empty. + * @return string The cache key. + */ + function _count_posts_cache_key($type = 'post', $perm = '') + { + } + /** + * Counts number of posts of a post type and if user has permissions to view. + * + * This function provides an efficient method of finding the amount of post's + * type a blog has. Another method is to count the amount of items in + * get_posts(), but that method has a lot of overhead with doing so. Therefore, + * when developing for 2.5+, use this function instead. + * + * The $perm parameter checks for 'readable' value and if the user can read + * private posts, it will display that for the user that is signed in. + * + * @since 2.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $type Optional. Post type to retrieve count. Default 'post'. + * @param string $perm Optional. 'readable' or empty. Default empty. + * @return stdClass Number of posts for each status. + */ + function wp_count_posts($type = 'post', $perm = '') + { + } + /** + * Counts number of attachments for the mime type(s). + * + * If you set the optional mime_type parameter, then an array will still be + * returned, but will only have the item you are looking for. It does not give + * you the number of attachments that are children of a post. You can get that + * by counting the number of children that post has. + * + * @since 2.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string|string[] $mime_type Optional. Array or comma-separated list of + * MIME patterns. Default empty. + * @return stdClass An object containing the attachment counts by mime type. + */ + function wp_count_attachments($mime_type = '') + { + } + /** + * Gets default post mime types. + * + * @since 2.9.0 + * @since 5.3.0 Added the 'Documents', 'Spreadsheets', and 'Archives' mime type groups. + * + * @return array List of post mime types. + */ + function get_post_mime_types() + { + } + /** + * Checks a MIME-Type against a list. + * + * If the `$wildcard_mime_types` parameter is a string, it must be comma separated + * list. If the `$real_mime_types` is a string, it is also comma separated to + * create the list. + * + * @since 2.5.0 + * + * @param string|string[] $wildcard_mime_types Mime types, e.g. `audio/mpeg`, `image` (same as `image/*`), + * or `flash` (same as `*flash*`). + * @param string|string[] $real_mime_types Real post mime type values. + * @return array array(wildcard=>array(real types)). + */ + function wp_match_mime_types($wildcard_mime_types, $real_mime_types) + { + } + /** + * Converts MIME types into SQL. + * + * @since 2.5.0 + * + * @param string|string[] $post_mime_types List of mime types or comma separated string + * of mime types. + * @param string $table_alias Optional. Specify a table alias, if needed. + * Default empty. + * @return string The SQL AND clause for mime searching. + */ + function wp_post_mime_type_where($post_mime_types, $table_alias = '') + { + } + /** + * Trashes or deletes a post or page. + * + * When the post and page is permanently deleted, everything that is tied to + * it is deleted also. This includes comments, post meta fields, and terms + * associated with the post. + * + * The post or page is moved to Trash instead of permanently deleted unless + * Trash is disabled, item is already in the Trash, or $force_delete is true. + * + * @since 1.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * @see wp_delete_attachment() + * @see wp_trash_post() + * + * @param int $postid Optional. Post ID. Default 0. + * @param bool $force_delete Optional. Whether to bypass Trash and force deletion. + * Default false. + * @return WP_Post|false|null Post data on success, false or null on failure. + */ + function wp_delete_post($postid = 0, $force_delete = \false) + { + } + /** + * Resets the page_on_front, show_on_front, and page_for_post settings when + * a linked page is deleted or trashed. + * + * Also ensures the post is no longer sticky. + * + * @since 3.7.0 + * @access private + * + * @param int $post_id Post ID. + */ + function _reset_front_page_settings_for_post($post_id) + { + } + /** + * Moves a post or page to the Trash + * + * If Trash is disabled, the post or page is permanently deleted. + * + * @since 2.9.0 + * + * @see wp_delete_post() + * + * @param int $post_id Optional. Post ID. Default is the ID of the global `$post` + * if `EMPTY_TRASH_DAYS` equals true. + * @return WP_Post|false|null Post data on success, false or null on failure. + */ + function wp_trash_post($post_id = 0) + { + } + /** + * Restores a post from the Trash. + * + * @since 2.9.0 + * @since 5.6.0 An untrashed post is now returned to 'draft' status by default, except for + * attachments which are returned to their original 'inherit' status. + * + * @param int $post_id Optional. Post ID. Default is the ID of the global `$post`. + * @return WP_Post|false|null Post data on success, false or null on failure. + */ + function wp_untrash_post($post_id = 0) + { + } + /** + * Moves comments for a post to the Trash. + * + * @since 2.9.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|WP_Post|null $post Optional. Post ID or post object. Defaults to global $post. + * @return mixed|void False on failure. + */ + function wp_trash_post_comments($post = \null) + { + } + /** + * Restores comments for a post from the Trash. + * + * @since 2.9.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|WP_Post|null $post Optional. Post ID or post object. Defaults to global $post. + * @return true|void + */ + function wp_untrash_post_comments($post = \null) + { + } + /** + * Retrieves the list of categories for a post. + * + * Compatibility layer for themes and plugins. Also an easy layer of abstraction + * away from the complexity of the taxonomy layer. + * + * @since 2.1.0 + * + * @see wp_get_object_terms() + * + * @param int $post_id Optional. The Post ID. Does not default to the ID of the + * global $post. Default 0. + * @param array $args Optional. Category query parameters. Default empty array. + * See WP_Term_Query::__construct() for supported arguments. + * @return array|WP_Error List of categories. If the `$fields` argument passed via `$args` is 'all' or + * 'all_with_object_id', an array of WP_Term objects will be returned. If `$fields` + * is 'ids', an array of category IDs. If `$fields` is 'names', an array of category names. + * WP_Error object if 'category' taxonomy doesn't exist. + * @phpstan-param array{ + * taxonomy?: string|string[], + * object_ids?: int|int[], + * orderby?: string, + * order?: string, + * hide_empty?: bool|int, + * include?: int[]|string, + * exclude?: int[]|string, + * exclude_tree?: int[]|string, + * number?: int|string, + * offset?: int, + * fields?: string, + * count?: bool, + * name?: string|string[], + * slug?: string|string[], + * term_taxonomy_id?: int|int[], + * hierarchical?: bool, + * search?: string, + * name__like?: string, + * description__like?: string, + * pad_counts?: bool, + * get?: string, + * child_of?: int, + * parent?: int, + * childless?: bool, + * cache_domain?: string, + * update_term_meta_cache?: bool, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * } $args See WP_Term_Query::__construct() + */ + function wp_get_post_categories($post_id = 0, $args = array()) + { + } + /** + * Retrieves the tags for a post. + * + * There is only one default for this function, called 'fields' and by default + * is set to 'all'. There are other defaults that can be overridden in + * wp_get_object_terms(). + * + * @since 2.3.0 + * + * @param int $post_id Optional. The Post ID. Does not default to the ID of the + * global $post. Default 0. + * @param array $args Optional. Tag query parameters. Default empty array. + * See WP_Term_Query::__construct() for supported arguments. + * @return array|WP_Error Array of WP_Term objects on success or empty array if no tags were found. + * WP_Error object if 'post_tag' taxonomy doesn't exist. + * @phpstan-param array{ + * taxonomy?: string|string[], + * object_ids?: int|int[], + * orderby?: string, + * order?: string, + * hide_empty?: bool|int, + * include?: int[]|string, + * exclude?: int[]|string, + * exclude_tree?: int[]|string, + * number?: int|string, + * offset?: int, + * fields?: string, + * count?: bool, + * name?: string|string[], + * slug?: string|string[], + * term_taxonomy_id?: int|int[], + * hierarchical?: bool, + * search?: string, + * name__like?: string, + * description__like?: string, + * pad_counts?: bool, + * get?: string, + * child_of?: int, + * parent?: int, + * childless?: bool, + * cache_domain?: string, + * update_term_meta_cache?: bool, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * } $args See WP_Term_Query::__construct() + */ + function wp_get_post_tags($post_id = 0, $args = array()) + { + } + /** + * Retrieves the terms for a post. + * + * @since 2.8.0 + * + * @param int $post_id Optional. The Post ID. Does not default to the ID of the + * global $post. Default 0. + * @param string|string[] $taxonomy Optional. The taxonomy slug or array of slugs for which + * to retrieve terms. Default 'post_tag'. + * @param array $args { + * Optional. Term query parameters. See WP_Term_Query::__construct() for supported arguments. + * + * @type string $fields Term fields to retrieve. Default 'all'. + * } + * @return array|WP_Error Array of WP_Term objects on success or empty array if no terms were found. + * WP_Error object if `$taxonomy` doesn't exist. + * @phpstan-param array{ + * fields?: string, + * taxonomy?: string|string[], + * object_ids?: int|int[], + * orderby?: string, + * order?: string, + * hide_empty?: bool|int, + * include?: int[]|string, + * exclude?: int[]|string, + * exclude_tree?: int[]|string, + * number?: int|string, + * offset?: int, + * fields?: string, + * count?: bool, + * name?: string|string[], + * slug?: string|string[], + * term_taxonomy_id?: int|int[], + * hierarchical?: bool, + * search?: string, + * name__like?: string, + * description__like?: string, + * pad_counts?: bool, + * get?: string, + * child_of?: int, + * parent?: int, + * childless?: bool, + * cache_domain?: string, + * update_term_meta_cache?: bool, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * } $args + */ + function wp_get_post_terms($post_id = 0, $taxonomy = 'post_tag', $args = array()) + { + } + /** + * Retrieves a number of recent posts. + * + * @since 1.0.0 + * + * @see get_posts() + * + * @param array $args Optional. Arguments to retrieve posts. Default empty array. + * @param string $output Optional. The required return type. One of OBJECT or ARRAY_A, which + * correspond to a WP_Post object or an associative array, respectively. + * Default ARRAY_A. + * @return array|false Array of recent posts, where the type of each element is determined + * by the `$output` parameter. Empty array on failure. + */ + function wp_get_recent_posts($args = array(), $output = \ARRAY_A) + { + } + /** + * Inserts or update a post. + * + * If the $postarr parameter has 'ID' set to a value, then post will be updated. + * + * You can set the post date manually, by setting the values for 'post_date' + * and 'post_date_gmt' keys. You can close the comments or open the comments by + * setting the value for 'comment_status' key. + * + * @since 1.0.0 + * @since 2.6.0 Added the `$wp_error` parameter to allow a WP_Error to be returned on failure. + * @since 4.2.0 Support was added for encoding emoji in the post title, content, and excerpt. + * @since 4.4.0 A 'meta_input' array can now be passed to `$postarr` to add post meta data. + * @since 5.6.0 Added the `$fire_after_hooks` parameter. + * + * @see sanitize_post() + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $postarr { + * An array of elements that make up a post to update or insert. + * + * @type int $ID The post ID. If equal to something other than 0, + * the post with that ID will be updated. Default 0. + * @type int $post_author The ID of the user who added the post. Default is + * the current user ID. + * @type string $post_date The date of the post. Default is the current time. + * @type string $post_date_gmt The date of the post in the GMT timezone. Default is + * the value of `$post_date`. + * @type string $post_content The post content. Default empty. + * @type string $post_content_filtered The filtered post content. Default empty. + * @type string $post_title The post title. Default empty. + * @type string $post_excerpt The post excerpt. Default empty. + * @type string $post_status The post status. Default 'draft'. + * @type string $post_type The post type. Default 'post'. + * @type string $comment_status Whether the post can accept comments. Accepts 'open' or 'closed'. + * Default is the value of 'default_comment_status' option. + * @type string $ping_status Whether the post can accept pings. Accepts 'open' or 'closed'. + * Default is the value of 'default_ping_status' option. + * @type string $post_password The password to access the post. Default empty. + * @type string $post_name The post name. Default is the sanitized post title + * when creating a new post. + * @type string $to_ping Space or carriage return-separated list of URLs to ping. + * Default empty. + * @type string $pinged Space or carriage return-separated list of URLs that have + * been pinged. Default empty. + * @type string $post_modified The date when the post was last modified. Default is + * the current time. + * @type string $post_modified_gmt The date when the post was last modified in the GMT + * timezone. Default is the current time. + * @type int $post_parent Set this for the post it belongs to, if any. Default 0. + * @type int $menu_order The order the post should be displayed in. Default 0. + * @type string $post_mime_type The mime type of the post. Default empty. + * @type string $guid Global Unique ID for referencing the post. Default empty. + * @type int $import_id The post ID to be used when inserting a new post. + * If specified, must not match any existing post ID. Default 0. + * @type int[] $post_category Array of category IDs. + * Defaults to value of the 'default_category' option. + * @type array $tags_input Array of tag names, slugs, or IDs. Default empty. + * @type array $tax_input An array of taxonomy terms keyed by their taxonomy name. + * If the taxonomy is hierarchical, the term list needs to be + * either an array of term IDs or a comma-separated string of IDs. + * If the taxonomy is non-hierarchical, the term list can be an array + * that contains term names or slugs, or a comma-separated string + * of names or slugs. This is because, in hierarchical taxonomy, + * child terms can have the same names with different parent terms, + * so the only way to connect them is using ID. Default empty. + * @type array $meta_input Array of post meta values keyed by their post meta key. Default empty. + * @type string $page_template Page template to use. + * } + * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. + * @param bool $fire_after_hooks Optional. Whether to fire the after insert hooks. Default true. + * @return int|WP_Error The post ID on success. The value 0 or WP_Error on failure. + * @phpstan-param array{ + * ID?: int, + * post_author?: int, + * post_date?: string, + * post_date_gmt?: string, + * post_content?: string, + * post_content_filtered?: string, + * post_title?: string, + * post_excerpt?: string, + * post_status?: string, + * post_type?: string, + * comment_status?: string, + * ping_status?: string, + * post_password?: string, + * post_name?: string, + * to_ping?: string, + * pinged?: string, + * post_modified?: string, + * post_modified_gmt?: string, + * post_parent?: int, + * menu_order?: int, + * post_mime_type?: string, + * guid?: string, + * import_id?: int, + * post_category?: int[], + * tags_input?: array, + * tax_input?: array, + * meta_input?: array, + * page_template?: string, + * } $postarr + */ + function wp_insert_post($postarr, $wp_error = \false, $fire_after_hooks = \true) + { + } + /** + * Updates a post with new post data. + * + * The date does not have to be set for drafts. You can set the date and it will + * not be overridden. + * + * @since 1.0.0 + * @since 3.5.0 Added the `$wp_error` parameter to allow a WP_Error to be returned on failure. + * @since 5.6.0 Added the `$fire_after_hooks` parameter. + * + * @param array|object $postarr Optional. Post data. Arrays are expected to be escaped, + * objects are not. See wp_insert_post() for accepted arguments. + * Default array. + * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. + * @param bool $fire_after_hooks Optional. Whether to fire the after insert hooks. Default true. + * @return int|WP_Error The post ID on success. The value 0 or WP_Error on failure. + * @phpstan-param array{ + * ID?: int, + * post_author?: int, + * post_date?: string, + * post_date_gmt?: string, + * post_content?: string, + * post_content_filtered?: string, + * post_title?: string, + * post_excerpt?: string, + * post_status?: string, + * post_type?: string, + * comment_status?: string, + * ping_status?: string, + * post_password?: string, + * post_name?: string, + * to_ping?: string, + * pinged?: string, + * post_modified?: string, + * post_modified_gmt?: string, + * post_parent?: int, + * menu_order?: int, + * post_mime_type?: string, + * guid?: string, + * import_id?: int, + * post_category?: int[], + * tags_input?: array, + * tax_input?: array, + * meta_input?: array, + * page_template?: string, + * } $postarr See wp_insert_post() + */ + function wp_update_post($postarr = array(), $wp_error = \false, $fire_after_hooks = \true) + { + } + /** + * Publishes a post by transitioning the post status. + * + * @since 2.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|WP_Post $post Post ID or post object. + */ + function wp_publish_post($post) + { + } + /** + * Publishes future post and make sure post ID has future post status. + * + * Invoked by cron 'publish_future_post' event. This safeguard prevents cron + * from publishing drafts, etc. + * + * @since 2.5.0 + * + * @param int|WP_Post $post Post ID or post object. + */ + function check_and_publish_future_post($post) + { + } + /** + * Uses wp_checkdate to return a valid Gregorian-calendar value for post_date. + * If post_date is not provided, this first checks post_date_gmt if provided, + * then falls back to use the current time. + * + * For back-compat purposes in wp_insert_post, an empty post_date and an invalid + * post_date_gmt will continue to return '1970-01-01 00:00:00' rather than false. + * + * @since 5.7.0 + * + * @param string $post_date The date in mysql format. + * @param string $post_date_gmt The GMT date in mysql format. + * @return string|false A valid Gregorian-calendar date string, or false on failure. + */ + function wp_resolve_post_date($post_date = '', $post_date_gmt = '') + { + } + /** + * Computes a unique slug for the post, when given the desired slug and some post details. + * + * @since 2.8.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $slug The desired slug (post_name). + * @param int $post_ID Post ID. + * @param string $post_status No uniqueness checks are made if the post is still draft or pending. + * @param string $post_type Post type. + * @param int $post_parent Post parent ID. + * @return string Unique slug for the post, based on $post_name (with a -1, -2, etc. suffix) + */ + function wp_unique_post_slug($slug, $post_ID, $post_status, $post_type, $post_parent) + { + } + /** + * Truncates a post slug. + * + * @since 3.6.0 + * @access private + * + * @see utf8_uri_encode() + * + * @param string $slug The slug to truncate. + * @param int $length Optional. Max length of the slug. Default 200 (characters). + * @return string The truncated slug. + */ + function _truncate_post_slug($slug, $length = 200) + { + } + /** + * Adds tags to a post. + * + * @see wp_set_post_tags() + * + * @since 2.3.0 + * + * @param int $post_id Optional. The Post ID. Does not default to the ID of the global $post. + * @param string|array $tags Optional. An array of tags to set for the post, or a string of tags + * separated by commas. Default empty. + * @return array|false|WP_Error Array of affected term IDs. WP_Error or false on failure. + */ + function wp_add_post_tags($post_id = 0, $tags = '') + { + } + /** + * Sets the tags for a post. + * + * @since 2.3.0 + * + * @see wp_set_object_terms() + * + * @param int $post_id Optional. The Post ID. Does not default to the ID of the global $post. + * @param string|array $tags Optional. An array of tags to set for the post, or a string of tags + * separated by commas. Default empty. + * @param bool $append Optional. If true, don't delete existing tags, just add on. If false, + * replace the tags with the new tags. Default false. + * @return array|false|WP_Error Array of term taxonomy IDs of affected terms. WP_Error or false on failure. + */ + function wp_set_post_tags($post_id = 0, $tags = '', $append = \false) + { + } + /** + * Sets the terms for a post. + * + * @since 2.8.0 + * + * @see wp_set_object_terms() + * + * @param int $post_id Optional. The Post ID. Does not default to the ID of the global $post. + * @param string|array $terms Optional. An array of terms to set for the post, or a string of terms + * separated by commas. Hierarchical taxonomies must always pass IDs rather + * than names so that children with the same names but different parents + * aren't confused. Default empty. + * @param string $taxonomy Optional. Taxonomy name. Default 'post_tag'. + * @param bool $append Optional. If true, don't delete existing terms, just add on. If false, + * replace the terms with the new terms. Default false. + * @return array|false|WP_Error Array of term taxonomy IDs of affected terms. WP_Error or false on failure. + */ + function wp_set_post_terms($post_id = 0, $terms = '', $taxonomy = 'post_tag', $append = \false) + { + } + /** + * Sets categories for a post. + * + * If no categories are provided, the default category is used. + * + * @since 2.1.0 + * + * @param int $post_ID Optional. The Post ID. Does not default to the ID + * of the global $post. Default 0. + * @param int[]|int $post_categories Optional. List of category IDs, or the ID of a single category. + * Default empty array. + * @param bool $append If true, don't delete existing categories, just add on. + * If false, replace the categories with the new categories. + * @return array|false|WP_Error Array of term taxonomy IDs of affected categories. WP_Error or false on failure. + */ + function wp_set_post_categories($post_ID = 0, $post_categories = array(), $append = \false) + { + } + /** + * Fires actions related to the transitioning of a post's status. + * + * When a post is saved, the post status is "transitioned" from one status to another, + * though this does not always mean the status has actually changed before and after + * the save. This function fires a number of action hooks related to that transition: + * the generic {@see 'transition_post_status'} action, as well as the dynamic hooks + * {@see '$old_status_to_$new_status'} and {@see '$new_status_$post->post_type'}. Note + * that the function does not transition the post object in the database. + * + * For instance: When publishing a post for the first time, the post status may transition + * from 'draft' – or some other status – to 'publish'. However, if a post is already + * published and is simply being updated, the "old" and "new" statuses may both be 'publish' + * before and after the transition. + * + * @since 2.3.0 + * + * @param string $new_status Transition to this post status. + * @param string $old_status Previous post status. + * @param WP_Post $post Post data. + */ + function wp_transition_post_status($new_status, $old_status, $post) + { + } + /** + * Fires actions after a post, its terms and meta data has been saved. + * + * @since 5.6.0 + * + * @param int|WP_Post $post The post ID or object that has been saved. + * @param bool $update Whether this is an existing post being updated. + * @param null|WP_Post $post_before Null for new posts, the WP_Post object prior + * to the update for updated posts. + */ + function wp_after_insert_post($post, $update, $post_before) + { + } + // + // Comment, trackback, and pingback functions. + // + /** + * Adds a URL to those already pinged. + * + * @since 1.5.0 + * @since 4.7.0 `$post` can be a WP_Post object. + * @since 4.7.0 `$uri` can be an array of URIs. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|WP_Post $post Post ID or post object. + * @param string|array $uri Ping URI or array of URIs. + * @return int|false How many rows were updated. + */ + function add_ping($post, $uri) + { + } + /** + * Retrieves enclosures already enclosed for a post. + * + * @since 1.5.0 + * + * @param int $post_id Post ID. + * @return string[] Array of enclosures for the given post. + */ + function get_enclosed($post_id) + { + } + /** + * Retrieves URLs already pinged for a post. + * + * @since 1.5.0 + * + * @since 4.7.0 `$post` can be a WP_Post object. + * + * @param int|WP_Post $post Post ID or object. + * @return string[]|false Array of URLs already pinged for the given post, false if the post is not found. + */ + function get_pung($post) + { + } + /** + * Retrieves URLs that need to be pinged. + * + * @since 1.5.0 + * @since 4.7.0 `$post` can be a WP_Post object. + * + * @param int|WP_Post $post Post ID or post object. + * @return string[]|false List of URLs yet to ping. + */ + function get_to_ping($post) + { + } + /** + * Does trackbacks for a list of URLs. + * + * @since 1.0.0 + * + * @param string $tb_list Comma separated list of URLs. + * @param int $post_id Post ID. + */ + function trackback_url_list($tb_list, $post_id) + { + } + // + // Page functions. + // + /** + * Gets a list of page IDs. + * + * @since 2.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @return string[] List of page IDs as strings. + */ + function get_all_page_ids() + { + } + /** + * Retrieves page data given a page ID or page object. + * + * Use get_post() instead of get_page(). + * + * @since 1.5.1 + * @deprecated 3.5.0 Use get_post() + * + * @param int|WP_Post $page Page object or page ID. Passed by reference. + * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which + * correspond to a WP_Post object, an associative array, or a numeric array, + * respectively. Default OBJECT. + * @param string $filter Optional. How the return value should be filtered. Accepts 'raw', + * 'edit', 'db', 'display'. Default 'raw'. + * @return WP_Post|array|null WP_Post or array on success, null on failure. + */ + function get_page($page, $output = \OBJECT, $filter = 'raw') + { + } + /** + * Retrieves a page given its path. + * + * @since 2.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $page_path Page path. + * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which + * correspond to a WP_Post object, an associative array, or a numeric array, + * respectively. Default OBJECT. + * @param string|array $post_type Optional. Post type or array of post types. Default 'page'. + * @return WP_Post|array|null WP_Post (or array) on success, or null on failure. + */ + function get_page_by_path($page_path, $output = \OBJECT, $post_type = 'page') + { + } + /** + * Retrieves a page given its title. + * + * If more than one post uses the same title, the post with the smallest ID will be returned. + * Be careful: in case of more than one post having the same title, it will check the oldest + * publication date, not the smallest ID. + * + * Because this function uses the MySQL '=' comparison, $page_title will usually be matched + * as case-insensitive with default collation. + * + * @since 2.1.0 + * @since 3.0.0 The `$post_type` parameter was added. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $page_title Page title. + * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which + * correspond to a WP_Post object, an associative array, or a numeric array, + * respectively. Default OBJECT. + * @param string|array $post_type Optional. Post type or array of post types. Default 'page'. + * @return WP_Post|array|null WP_Post (or array) on success, or null on failure. + */ + function get_page_by_title($page_title, $output = \OBJECT, $post_type = 'page') + { + } + /** + * Identifies descendants of a given page ID in a list of page objects. + * + * Descendants are identified from the `$pages` array passed to the function. No database queries are performed. + * + * @since 1.5.1 + * + * @param int $page_id Page ID. + * @param WP_Post[] $pages List of page objects from which descendants should be identified. + * @return WP_Post[] List of page children. + */ + function get_page_children($page_id, $pages) + { + } + /** + * Orders the pages with children under parents in a flat list. + * + * It uses auxiliary structure to hold parent-children relationships and + * runs in O(N) complexity + * + * @since 2.0.0 + * + * @param WP_Post[] $pages Posts array (passed by reference). + * @param int $page_id Optional. Parent page ID. Default 0. + * @return string[] Array of post names keyed by ID and arranged by hierarchy. Children immediately follow their parents. + */ + function get_page_hierarchy(&$pages, $page_id = 0) + { + } + /** + * Traverses and return all the nested children post names of a root page. + * + * $children contains parent-children relations + * + * @since 2.9.0 + * @access private + * + * @see _page_traverse_name() + * + * @param int $page_id Page ID. + * @param array $children Parent-children relations (passed by reference). + * @param string[] $result Array of page names keyed by ID (passed by reference). + */ + function _page_traverse_name($page_id, &$children, &$result) + { + } + /** + * Builds the URI path for a page. + * + * Sub pages will be in the "directory" under the parent page post name. + * + * @since 1.5.0 + * @since 4.6.0 The `$page` parameter was made optional. + * + * @param WP_Post|object|int $page Optional. Page ID or WP_Post object. Default is global $post. + * @return string|false Page URI, false on error. + */ + function get_page_uri($page = 0) + { + } + /** + * Retrieves an array of pages (or hierarchical post type items). + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @since 1.5.0 + * + * @param array|string $args { + * Optional. Array or string of arguments to retrieve pages. + * + * @type int $child_of Page ID to return child and grandchild pages of. Note: The value + * of `$hierarchical` has no bearing on whether `$child_of` returns + * hierarchical results. Default 0, or no restriction. + * @type string $sort_order How to sort retrieved pages. Accepts 'ASC', 'DESC'. Default 'ASC'. + * @type string $sort_column What columns to sort pages by, comma-separated. Accepts 'post_author', + * 'post_date', 'post_title', 'post_name', 'post_modified', 'menu_order', + * 'post_modified_gmt', 'post_parent', 'ID', 'rand', 'comment_count'. + * 'post_' can be omitted for any values that start with it. + * Default 'post_title'. + * @type bool $hierarchical Whether to return pages hierarchically. If false in conjunction with + * `$child_of` also being false, both arguments will be disregarded. + * Default true. + * @type int[] $exclude Array of page IDs to exclude. Default empty array. + * @type int[] $include Array of page IDs to include. Cannot be used with `$child_of`, + * `$parent`, `$exclude`, `$meta_key`, `$meta_value`, or `$hierarchical`. + * Default empty array. + * @type string $meta_key Only include pages with this meta key. Default empty. + * @type string $meta_value Only include pages with this meta value. Requires `$meta_key`. + * Default empty. + * @type string $authors A comma-separated list of author IDs. Default empty. + * @type int $parent Page ID to return direct children of. Default -1, or no restriction. + * @type string|int[] $exclude_tree Comma-separated string or array of page IDs to exclude. + * Default empty array. + * @type int $number The number of pages to return. Default 0, or all pages. + * @type int $offset The number of pages to skip before returning. Requires `$number`. + * Default 0. + * @type string $post_type The post type to query. Default 'page'. + * @type string|array $post_status A comma-separated list or array of post statuses to include. + * Default 'publish'. + * } + * @return WP_Post[]|false Array of pages (or hierarchical post type items). Boolean false if the + * specified post type is not hierarchical or the specified status is not + * supported by the post type. + * @phpstan-param array{ + * child_of?: int, + * sort_order?: string, + * sort_column?: string, + * hierarchical?: bool, + * exclude?: int[], + * include?: int[], + * meta_key?: string, + * meta_value?: string, + * authors?: string, + * parent?: int, + * exclude_tree?: string|int[], + * number?: int, + * offset?: int, + * post_type?: string, + * post_status?: string|array, + * } $args + */ + function get_pages($args = array()) + { + } + // + // Attachment functions. + // + /** + * Determines whether an attachment URI is local and really an attachment. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.0.0 + * + * @param string $url URL to check + * @return bool True on success, false on failure. + */ + function is_local_attachment($url) + { + } + /** + * Inserts an attachment. + * + * If you set the 'ID' in the $args parameter, it will mean that you are + * updating and attempt to update the attachment. You can also set the + * attachment name or title by setting the key 'post_name' or 'post_title'. + * + * You can set the dates for the attachment manually by setting the 'post_date' + * and 'post_date_gmt' keys' values. + * + * By default, the comments will use the default settings for whether the + * comments are allowed. You can close them manually or keep them open by + * setting the value for the 'comment_status' key. + * + * @since 2.0.0 + * @since 4.7.0 Added the `$wp_error` parameter to allow a WP_Error to be returned on failure. + * @since 5.6.0 Added the `$fire_after_hooks` parameter. + * + * @see wp_insert_post() + * + * @param string|array $args Arguments for inserting an attachment. + * @param string|false $file Optional. Filename. + * @param int $parent Optional. Parent post ID. + * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. + * @param bool $fire_after_hooks Optional. Whether to fire the after insert hooks. Default true. + * @return int|WP_Error The attachment ID on success. The value 0 or WP_Error on failure. + */ + function wp_insert_attachment($args, $file = \false, $parent = 0, $wp_error = \false, $fire_after_hooks = \true) + { + } + /** + * Trashes or deletes an attachment. + * + * When an attachment is permanently deleted, the file will also be removed. + * Deletion removes all post meta fields, taxonomy, comments, etc. associated + * with the attachment (except the main post). + * + * The attachment is moved to the Trash instead of permanently deleted unless Trash + * for media is disabled, item is already in the Trash, or $force_delete is true. + * + * @since 2.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $post_id Attachment ID. + * @param bool $force_delete Optional. Whether to bypass Trash and force deletion. + * Default false. + * @return WP_Post|false|null Post data on success, false or null on failure. + */ + function wp_delete_attachment($post_id, $force_delete = \false) + { + } + /** + * Deletes all files that belong to the given attachment. + * + * @since 4.9.7 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $post_id Attachment ID. + * @param array $meta The attachment's meta data. + * @param array $backup_sizes The meta data for the attachment's backup images. + * @param string $file Absolute path to the attachment's file. + * @return bool True on success, false on failure. + */ + function wp_delete_attachment_files($post_id, $meta, $backup_sizes, $file) + { + } + /** + * Retrieves attachment metadata for attachment ID. + * + * @since 2.1.0 + * @since 6.0.0 The `$filesize` value was added to the returned array. + * + * @param int $attachment_id Attachment post ID. Defaults to global $post. + * @param bool $unfiltered Optional. If true, filters are not run. Default false. + * @return array|false { + * Attachment metadata. False on failure. + * + * @type int $width The width of the attachment. + * @type int $height The height of the attachment. + * @type string $file The file path relative to `wp-content/uploads`. + * @type array $sizes Keys are size slugs, each value is an array containing + * 'file', 'width', 'height', and 'mime-type'. + * @type array $image_meta Image metadata. + * @type int $filesize File size of the attachment. + * } + * @phpstan-return false|array{ + * width: int, + * height: int, + * file: string, + * sizes: array, + * image_meta: array, + * filesize: int, + * } + */ + function wp_get_attachment_metadata($attachment_id = 0, $unfiltered = \false) + { + } + /** + * Updates metadata for an attachment. + * + * @since 2.1.0 + * + * @param int $attachment_id Attachment post ID. + * @param array $data Attachment meta data. + * @return int|false False if $post is invalid. + */ + function wp_update_attachment_metadata($attachment_id, $data) + { + } + /** + * Retrieves the URL for an attachment. + * + * @since 2.1.0 + * + * @global string $pagenow The filename of the current screen. + * + * @param int $attachment_id Optional. Attachment post ID. Defaults to global $post. + * @return string|false Attachment URL, otherwise false. + */ + function wp_get_attachment_url($attachment_id = 0) + { + } + /** + * Retrieves the caption for an attachment. + * + * @since 4.6.0 + * + * @param int $post_id Optional. Attachment ID. Default is the ID of the global `$post`. + * @return string|false Attachment caption on success, false on failure. + */ + function wp_get_attachment_caption($post_id = 0) + { + } + /** + * Retrieves URL for an attachment thumbnail. + * + * @since 2.1.0 + * @since 6.1.0 Changed to use wp_get_attachment_image_url(). + * + * @param int $post_id Optional. Attachment ID. Default is the ID of the global `$post`. + * @return string|false Thumbnail URL on success, false on failure. + */ + function wp_get_attachment_thumb_url($post_id = 0) + { + } + /** + * Verifies an attachment is of a given type. + * + * @since 4.2.0 + * + * @param string $type Attachment type. Accepts 'image', 'audio', or 'video'. + * @param int|WP_Post $post Optional. Attachment ID or object. Default is global $post. + * @return bool True if one of the accepted types, false otherwise. + */ + function wp_attachment_is($type, $post = \null) + { + } + /** + * Determines whether an attachment is an image. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.1.0 + * @since 4.2.0 Modified into wrapper for wp_attachment_is() and + * allowed WP_Post object to be passed. + * + * @param int|WP_Post $post Optional. Attachment ID or object. Default is global $post. + * @return bool Whether the attachment is an image. + */ + function wp_attachment_is_image($post = \null) + { + } + /** + * Retrieves the icon for a MIME type or attachment. + * + * @since 2.1.0 + * + * @param string|int $mime MIME type or attachment ID. + * @return string|false Icon, false otherwise. + */ + function wp_mime_type_icon($mime = 0) + { + } + /** + * Checks for changed slugs for published post objects and save the old slug. + * + * The function is used when a post object of any type is updated, + * by comparing the current and previous post objects. + * + * If the slug was changed and not already part of the old slugs then it will be + * added to the post meta field ('_wp_old_slug') for storing old slugs for that + * post. + * + * The most logically usage of this function is redirecting changed post objects, so + * that those that linked to an changed post will be redirected to the new post. + * + * @since 2.1.0 + * + * @param int $post_id Post ID. + * @param WP_Post $post The post object. + * @param WP_Post $post_before The previous post object. + */ + function wp_check_for_changed_slugs($post_id, $post, $post_before) + { + } + /** + * Checks for changed dates for published post objects and save the old date. + * + * The function is used when a post object of any type is updated, + * by comparing the current and previous post objects. + * + * If the date was changed and not already part of the old dates then it will be + * added to the post meta field ('_wp_old_date') for storing old dates for that + * post. + * + * The most logically usage of this function is redirecting changed post objects, so + * that those that linked to an changed post will be redirected to the new post. + * + * @since 4.9.3 + * + * @param int $post_id Post ID. + * @param WP_Post $post The post object. + * @param WP_Post $post_before The previous post object. + */ + function wp_check_for_changed_dates($post_id, $post, $post_before) + { + } + /** + * Retrieves the private post SQL based on capability. + * + * This function provides a standardized way to appropriately select on the + * post_status of a post type. The function will return a piece of SQL code + * that can be added to a WHERE clause; this SQL is constructed to allow all + * published posts, and all private posts to which the user has access. + * + * @since 2.2.0 + * @since 4.3.0 Added the ability to pass an array to `$post_type`. + * + * @param string|array $post_type Single post type or an array of post types. Currently only supports 'post' or 'page'. + * @return string SQL code that can be added to a where clause. + */ + function get_private_posts_cap_sql($post_type) + { + } + /** + * Retrieves the post SQL based on capability, author, and type. + * + * @since 3.0.0 + * @since 4.3.0 Introduced the ability to pass an array of post types to `$post_type`. + * + * @see get_private_posts_cap_sql() + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string|string[] $post_type Single post type or an array of post types. + * @param bool $full Optional. Returns a full WHERE statement instead of just + * an 'andalso' term. Default true. + * @param int $post_author Optional. Query posts having a single author ID. Default null. + * @param bool $public_only Optional. Only return public posts. Skips cap checks for + * $current_user. Default false. + * @return string SQL WHERE code that can be added to a query. + */ + function get_posts_by_author_sql($post_type, $full = \true, $post_author = \null, $public_only = \false) + { + } + /** + * Retrieves the most recent time that a post on the site was published. + * + * The server timezone is the default and is the difference between GMT and + * server time. The 'blog' value is the date when the last post was posted. + * The 'gmt' is when the last post was posted in GMT formatted date. + * + * @since 0.71 + * @since 4.4.0 The `$post_type` argument was added. + * + * @param string $timezone Optional. The timezone for the timestamp. Accepts 'server', 'blog', or 'gmt'. + * 'server' uses the server's internal timezone. + * 'blog' uses the `post_date` field, which proxies to the timezone set for the site. + * 'gmt' uses the `post_date_gmt` field. + * Default 'server'. + * @param string $post_type Optional. The post type to check. Default 'any'. + * @return string The date of the last post, or false on failure. + */ + function get_lastpostdate($timezone = 'server', $post_type = 'any') + { + } + /** + * Gets the most recent time that a post on the site was modified. + * + * The server timezone is the default and is the difference between GMT and + * server time. The 'blog' value is just when the last post was modified. + * The 'gmt' is when the last post was modified in GMT time. + * + * @since 1.2.0 + * @since 4.4.0 The `$post_type` argument was added. + * + * @param string $timezone Optional. The timezone for the timestamp. See get_lastpostdate() + * for information on accepted values. + * Default 'server'. + * @param string $post_type Optional. The post type to check. Default 'any'. + * @return string The timestamp in 'Y-m-d H:i:s' format, or false on failure. + */ + function get_lastpostmodified($timezone = 'server', $post_type = 'any') + { + } + /** + * Gets the timestamp of the last time any post was modified or published. + * + * @since 3.1.0 + * @since 4.4.0 The `$post_type` argument was added. + * @access private + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $timezone The timezone for the timestamp. See get_lastpostdate(). + * for information on accepted values. + * @param string $field Post field to check. Accepts 'date' or 'modified'. + * @param string $post_type Optional. The post type to check. Default 'any'. + * @return string|false The timestamp in 'Y-m-d H:i:s' format, or false on failure. + */ + function _get_last_post_time($timezone, $field, $post_type = 'any') + { + } + /** + * Updates posts in cache. + * + * @since 1.5.1 + * + * @param WP_Post[] $posts Array of post objects (passed by reference). + */ + function update_post_cache(&$posts) + { + } + /** + * Will clean the post in the cache. + * + * Cleaning means delete from the cache of the post. Will call to clean the term + * object cache associated with the post ID. + * + * This function not run if $_wp_suspend_cache_invalidation is not empty. See + * wp_suspend_cache_invalidation(). + * + * @since 2.0.0 + * + * @global bool $_wp_suspend_cache_invalidation + * + * @param int|WP_Post $post Post ID or post object to remove from the cache. + */ + function clean_post_cache($post) + { + } + /** + * Updates post, term, and metadata caches for a list of post objects. + * + * @since 1.5.0 + * + * @param WP_Post[] $posts Array of post objects (passed by reference). + * @param string $post_type Optional. Post type. Default 'post'. + * @param bool $update_term_cache Optional. Whether to update the term cache. Default true. + * @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true. + */ + function update_post_caches(&$posts, $post_type = 'post', $update_term_cache = \true, $update_meta_cache = \true) + { + } + /** + * Updates post author user caches for a list of post objects. + * + * @since 6.1.0 + * + * @param WP_Post[] $posts Array of post objects. + */ + function update_post_author_caches($posts) + { + } + /** + * Updates parent post caches for a list of post objects. + * + * @since 6.1.0 + * + * @param WP_Post[] $posts Array of post objects. + */ + function update_post_parent_caches($posts) + { + } + /** + * Updates metadata cache for a list of post IDs. + * + * Performs SQL query to retrieve the metadata for the post IDs and updates the + * metadata cache for the posts. Therefore, the functions, which call this + * function, do not need to perform SQL queries on their own. + * + * @since 2.1.0 + * + * @param int[] $post_ids Array of post IDs. + * @return array|false An array of metadata on success, false if there is nothing to update. + */ + function update_postmeta_cache($post_ids) + { + } + /** + * Will clean the attachment in the cache. + * + * Cleaning means delete from the cache. Optionally will clean the term + * object cache associated with the attachment ID. + * + * This function will not run if $_wp_suspend_cache_invalidation is not empty. + * + * @since 3.0.0 + * + * @global bool $_wp_suspend_cache_invalidation + * + * @param int $id The attachment ID in the cache to clean. + * @param bool $clean_terms Optional. Whether to clean terms cache. Default false. + */ + function clean_attachment_cache($id, $clean_terms = \false) + { + } + // + // Hooks. + // + /** + * Hook for managing future post transitions to published. + * + * @since 2.3.0 + * @access private + * + * @see wp_clear_scheduled_hook() + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $new_status New post status. + * @param string $old_status Previous post status. + * @param WP_Post $post Post object. + */ + function _transition_post_status($new_status, $old_status, $post) + { + } + /** + * Hook used to schedule publication for a post marked for the future. + * + * The $post properties used and must exist are 'ID' and 'post_date_gmt'. + * + * @since 2.3.0 + * @access private + * + * @param int $deprecated Not used. Can be set to null. Never implemented. Not marked + * as deprecated with _deprecated_argument() as it conflicts with + * wp_transition_post_status() and the default filter for _future_post_hook(). + * @param WP_Post $post Post object. + */ + function _future_post_hook($deprecated, $post) + { + } + /** + * Hook to schedule pings and enclosures when a post is published. + * + * Uses XMLRPC_REQUEST and WP_IMPORTING constants. + * + * @since 2.3.0 + * @access private + * + * @param int $post_id The ID of the post being published. + */ + function _publish_post_hook($post_id) + { + } + /** + * Returns the ID of the post's parent. + * + * @since 3.1.0 + * @since 5.9.0 The `$post` parameter was made optional. + * + * @param int|WP_Post|null $post Optional. Post ID or post object. Defaults to global $post. + * @return int|false Post parent ID (which can be 0 if there is no parent), + * or false if the post does not exist. + */ + function wp_get_post_parent_id($post = \null) + { + } + /** + * Checks the given subset of the post hierarchy for hierarchy loops. + * + * Prevents loops from forming and breaks those that it finds. Attached + * to the {@see 'wp_insert_post_parent'} filter. + * + * @since 3.1.0 + * + * @see wp_find_hierarchy_loop() + * + * @param int $post_parent ID of the parent for the post we're checking. + * @param int $post_ID ID of the post we're checking. + * @return int The new post_parent for the post, 0 otherwise. + */ + function wp_check_post_hierarchy_for_loops($post_parent, $post_ID) + { + } + /** + * Sets the post thumbnail (featured image) for the given post. + * + * @since 3.1.0 + * + * @param int|WP_Post $post Post ID or post object where thumbnail should be attached. + * @param int $thumbnail_id Thumbnail to attach. + * @return int|bool True on success, false on failure. + */ + function set_post_thumbnail($post, $thumbnail_id) + { + } + /** + * Removes the thumbnail (featured image) from the given post. + * + * @since 3.3.0 + * + * @param int|WP_Post $post Post ID or post object from which the thumbnail should be removed. + * @return bool True on success, false on failure. + */ + function delete_post_thumbnail($post) + { + } + /** + * Deletes auto-drafts for new posts that are > 7 days old. + * + * @since 3.4.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function wp_delete_auto_drafts() + { + } + /** + * Queues posts for lazy-loading of term meta. + * + * @since 4.5.0 + * + * @param WP_Post[] $posts Array of WP_Post objects. + */ + function wp_queue_posts_for_term_meta_lazyload($posts) + { + } + /** + * Updates the custom taxonomies' term counts when a post's status is changed. + * + * For example, default posts term counts (for custom taxonomies) don't include + * private / draft posts. + * + * @since 3.3.0 + * @access private + * + * @param string $new_status New post status. + * @param string $old_status Old post status. + * @param WP_Post $post Post object. + */ + function _update_term_count_on_transition_post_status($new_status, $old_status, $post) + { + } + /** + * Adds any posts from the given IDs to the cache that do not already exist in cache. + * + * @since 3.4.0 + * @since 6.1.0 This function is no longer marked as "private". + * + * @see update_post_caches() + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int[] $ids ID list. + * @param bool $update_term_cache Optional. Whether to update the term cache. Default true. + * @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true. + */ + function _prime_post_caches($ids, $update_term_cache = \true, $update_meta_cache = \true) + { + } + /** + * Adds a suffix if any trashed posts have a given slug. + * + * Store its desired (i.e. current) slug so it can try to reclaim it + * if the post is untrashed. + * + * For internal use. + * + * @since 4.5.0 + * @access private + * + * @param string $post_name Post slug. + * @param int $post_ID Optional. Post ID that should be ignored. Default 0. + */ + function wp_add_trashed_suffix_to_post_name_for_trashed_posts($post_name, $post_ID = 0) + { + } + /** + * Adds a trashed suffix for a given post. + * + * Store its desired (i.e. current) slug so it can try to reclaim it + * if the post is untrashed. + * + * For internal use. + * + * @since 4.5.0 + * @access private + * + * @param WP_Post $post The post. + * @return string New slug for the post. + */ + function wp_add_trashed_suffix_to_post_name_for_post($post) + { + } + /** + * Sets the last changed time for the 'posts' cache group. + * + * @since 5.0.0 + */ + function wp_cache_set_posts_last_changed() + { + } + /** + * Gets all available post MIME types for a given post type. + * + * @since 2.5.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $type + * @return string[] An array of MIME types. + */ + function get_available_post_mime_types($type = 'attachment') + { + } + /** + * Retrieves the path to an uploaded image file. + * + * Similar to `get_attached_file()` however some images may have been processed after uploading + * to make them suitable for web use. In this case the attached "full" size file is usually replaced + * with a scaled down version of the original image. This function always returns the path + * to the originally uploaded image file. + * + * @since 5.3.0 + * @since 5.4.0 Added the `$unfiltered` parameter. + * + * @param int $attachment_id Attachment ID. + * @param bool $unfiltered Optional. Passed through to `get_attached_file()`. Default false. + * @return string|false Path to the original image file or false if the attachment is not an image. + */ + function wp_get_original_image_path($attachment_id, $unfiltered = \false) + { + } + /** + * Retrieves the URL to an original attachment image. + * + * Similar to `wp_get_attachment_url()` however some images may have been + * processed after uploading. In this case this function returns the URL + * to the originally uploaded image file. + * + * @since 5.3.0 + * + * @param int $attachment_id Attachment post ID. + * @return string|false Attachment image URL, false on error or if the attachment is not an image. + */ + function wp_get_original_image_url($attachment_id) + { + } + /** + * Filters callback which sets the status of an untrashed post to its previous status. + * + * This can be used as a callback on the `wp_untrash_post_status` filter. + * + * @since 5.6.0 + * + * @param string $new_status The new status of the post being restored. + * @param int $post_id The ID of the post being restored. + * @param string $previous_status The status of the post at the point where it was trashed. + * @return string The new status of the post. + */ + function wp_untrash_post_set_previous_status($new_status, $post_id, $previous_status) + { + } + /** + * Returns whether the post can be edited in the block editor. + * + * @since 5.0.0 + * @since 6.1.0 Moved to wp-includes from wp-admin. + * + * @param int|WP_Post $post Post ID or WP_Post object. + * @return bool Whether the post can be edited in the block editor. + */ + function use_block_editor_for_post($post) + { + } + /** + * Returns whether a post type is compatible with the block editor. + * + * The block editor depends on the REST API, and if the post type is not shown in the + * REST API, then it won't work with the block editor. + * + * @since 5.0.0 + * @since 6.1.0 Moved to wp-includes from wp-admin. + * + * @param string $post_type The post type. + * @return bool Whether the post type can be edited with the block editor. + */ + function use_block_editor_for_post_type($post_type) + { + } + /** + * WordPress Query API + * + * The query API attempts to get which part of WordPress the user is on. It + * also provides functionality for getting URL query information. + * + * @link https://developer.wordpress.org/themes/basics/the-loop/ More information on The Loop. + * + * @package WordPress + * @subpackage Query + */ + /** + * Retrieves the value of a query variable in the WP_Query class. + * + * @since 1.5.0 + * @since 3.9.0 The `$default` argument was introduced. + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param string $var The variable key to retrieve. + * @param mixed $default Optional. Value to return if the query variable is not set. Default empty. + * @return mixed Contents of the query variable. + */ + function get_query_var($var, $default = '') + { + } + /** + * Retrieves the currently queried object. + * + * Wrapper for WP_Query::get_queried_object(). + * + * @since 3.1.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return WP_Term|WP_Post_Type|WP_Post|WP_User|null The queried object. + */ + function get_queried_object() + { + } + /** + * Retrieves the ID of the currently queried object. + * + * Wrapper for WP_Query::get_queried_object_id(). + * + * @since 3.1.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return int ID of the queried object. + */ + function get_queried_object_id() + { + } + /** + * Sets the value of a query variable in the WP_Query class. + * + * @since 2.2.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param string $var Query variable key. + * @param mixed $value Query variable value. + */ + function set_query_var($var, $value) + { + } + /** + * Sets up The Loop with query parameters. + * + * Note: This function will completely override the main query and isn't intended for use + * by plugins or themes. Its overly-simplistic approach to modifying the main query can be + * problematic and should be avoided wherever possible. In most cases, there are better, + * more performant options for modifying the main query such as via the {@see 'pre_get_posts'} + * action within WP_Query. + * + * This must not be used within the WordPress Loop. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param array|string $query Array or string of WP_Query arguments. + * @return WP_Post[]|int[] Array of post objects or post IDs. + */ + function query_posts($query) + { + } + /** + * Destroys the previous query and sets up a new query. + * + * This should be used after query_posts() and before another query_posts(). + * This will remove obscure bugs that occur when the previous WP_Query object + * is not destroyed properly before another is set up. + * + * @since 2.3.0 + * + * @global WP_Query $wp_query WordPress Query object. + * @global WP_Query $wp_the_query Copy of the global WP_Query instance created during wp_reset_query(). + */ + function wp_reset_query() + { + } + /** + * After looping through a separate query, this function restores + * the $post global to the current post in the main query. + * + * @since 3.0.0 + * + * @global WP_Query $wp_query WordPress Query object. + */ + function wp_reset_postdata() + { + } + /* + * Query type checks. + */ + /** + * Determines whether the query is for an existing archive page. + * + * Archive pages include category, tag, author, date, custom post type, + * and custom taxonomy based archives. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @see is_category() + * @see is_tag() + * @see is_author() + * @see is_date() + * @see is_post_type_archive() + * @see is_tax() + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for an existing archive page. + */ + function is_archive() + { + } + /** + * Determines whether the query is for an existing post type archive page. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 3.1.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param string|string[] $post_types Optional. Post type or array of posts types + * to check against. Default empty. + * @return bool Whether the query is for an existing post type archive page. + */ + function is_post_type_archive($post_types = '') + { + } + /** + * Determines whether the query is for an existing attachment page. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.0.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param int|string|int[]|string[] $attachment Optional. Attachment ID, title, slug, or array of such + * to check against. Default empty. + * @return bool Whether the query is for an existing attachment page. + */ + function is_attachment($attachment = '') + { + } + /** + * Determines whether the query is for an existing author archive page. + * + * If the $author parameter is specified, this function will additionally + * check if the query is for one of the authors specified. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param int|string|int[]|string[] $author Optional. User ID, nickname, nicename, or array of such + * to check against. Default empty. + * @return bool Whether the query is for an existing author archive page. + */ + function is_author($author = '') + { + } + /** + * Determines whether the query is for an existing category archive page. + * + * If the $category parameter is specified, this function will additionally + * check if the query is for one of the categories specified. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param int|string|int[]|string[] $category Optional. Category ID, name, slug, or array of such + * to check against. Default empty. + * @return bool Whether the query is for an existing category archive page. + */ + function is_category($category = '') + { + } + /** + * Determines whether the query is for an existing tag archive page. + * + * If the $tag parameter is specified, this function will additionally + * check if the query is for one of the tags specified. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.3.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param int|string|int[]|string[] $tag Optional. Tag ID, name, slug, or array of such + * to check against. Default empty. + * @return bool Whether the query is for an existing tag archive page. + */ + function is_tag($tag = '') + { + } + /** + * Determines whether the query is for an existing custom taxonomy archive page. + * + * If the $taxonomy parameter is specified, this function will additionally + * check if the query is for that specific $taxonomy. + * + * If the $term parameter is specified in addition to the $taxonomy parameter, + * this function will additionally check if the query is for one of the terms + * specified. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param string|string[] $taxonomy Optional. Taxonomy slug or slugs to check against. + * Default empty. + * @param int|string|int[]|string[] $term Optional. Term ID, name, slug, or array of such + * to check against. Default empty. + * @return bool Whether the query is for an existing custom taxonomy archive page. + * True for custom taxonomy archive pages, false for built-in taxonomies + * (category and tag archives). + */ + function is_tax($taxonomy = '', $term = '') + { + } + /** + * Determines whether the query is for an existing date archive. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for an existing date archive. + */ + function is_date() + { + } + /** + * Determines whether the query is for an existing day archive. + * + * A conditional check to test whether the page is a date-based archive page displaying posts for the current day. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for an existing day archive. + */ + function is_day() + { + } + /** + * Determines whether the query is for a feed. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param string|string[] $feeds Optional. Feed type or array of feed types + * to check against. Default empty. + * @return bool Whether the query is for a feed. + */ + function is_feed($feeds = '') + { + } + /** + * Is the query for a comments feed? + * + * @since 3.0.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for a comments feed. + */ + function is_comment_feed() + { + } + /** + * Determines whether the query is for the front page of the site. + * + * This is for what is displayed at your site's main URL. + * + * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_on_front'. + * + * If you set a static page for the front page of your site, this function will return + * true when viewing that page. + * + * Otherwise the same as @see is_home() + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for the front page of the site. + */ + function is_front_page() + { + } + /** + * Determines whether the query is for the blog homepage. + * + * The blog homepage is the page that shows the time-based blog content of the site. + * + * is_home() is dependent on the site's "Front page displays" Reading Settings 'show_on_front' + * and 'page_for_posts'. + * + * If a static page is set for the front page of the site, this function will return true only + * on the page you set as the "Posts page". + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @see is_front_page() + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for the blog homepage. + */ + function is_home() + { + } + /** + * Determines whether the query is for the Privacy Policy page. + * + * The Privacy Policy page is the page that shows the Privacy Policy content of the site. + * + * is_privacy_policy() is dependent on the site's "Change your Privacy Policy page" Privacy Settings 'wp_page_for_privacy_policy'. + * + * This function will return true only on the page you set as the "Privacy Policy page". + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 5.2.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for the Privacy Policy page. + */ + function is_privacy_policy() + { + } + /** + * Determines whether the query is for an existing month archive. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for an existing month archive. + */ + function is_month() + { + } + /** + * Determines whether the query is for an existing single page. + * + * If the $page parameter is specified, this function will additionally + * check if the query is for one of the pages specified. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @see is_single() + * @see is_singular() + * @global WP_Query $wp_query WordPress Query object. + * + * @param int|string|int[]|string[] $page Optional. Page ID, title, slug, or array of such + * to check against. Default empty. + * @return bool Whether the query is for an existing single page. + */ + function is_page($page = '') + { + } + /** + * Determines whether the query is for a paged result and not for the first page. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for a paged result. + */ + function is_paged() + { + } + /** + * Determines whether the query is for a post or page preview. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.0.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for a post or page preview. + */ + function is_preview() + { + } + /** + * Is the query for the robots.txt file? + * + * @since 2.1.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for the robots.txt file. + */ + function is_robots() + { + } + /** + * Is the query for the favicon.ico file? + * + * @since 5.4.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for the favicon.ico file. + */ + function is_favicon() + { + } + /** + * Determines whether the query is for a search. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for a search. + */ + function is_search() + { + } + /** + * Determines whether the query is for an existing single post. + * + * Works for any post type, except attachments and pages + * + * If the $post parameter is specified, this function will additionally + * check if the query is for one of the Posts specified. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @see is_page() + * @see is_singular() + * @global WP_Query $wp_query WordPress Query object. + * + * @param int|string|int[]|string[] $post Optional. Post ID, title, slug, or array of such + * to check against. Default empty. + * @return bool Whether the query is for an existing single post. + */ + function is_single($post = '') + { + } + /** + * Determines whether the query is for an existing single post of any post type + * (post, attachment, page, custom post types). + * + * If the $post_types parameter is specified, this function will additionally + * check if the query is for one of the Posts Types specified. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @see is_page() + * @see is_single() + * @global WP_Query $wp_query WordPress Query object. + * + * @param string|string[] $post_types Optional. Post type or array of post types + * to check against. Default empty. + * @return bool Whether the query is for an existing single post + * or any of the given post types. + */ + function is_singular($post_types = '') + { + } + /** + * Determines whether the query is for a specific time. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for a specific time. + */ + function is_time() + { + } + /** + * Determines whether the query is for a trackback endpoint call. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for a trackback endpoint call. + */ + function is_trackback() + { + } + /** + * Determines whether the query is for an existing year archive. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for an existing year archive. + */ + function is_year() + { + } + /** + * Determines whether the query has resulted in a 404 (returns no results). + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is a 404 error. + */ + function is_404() + { + } + /** + * Is the query for an embedded post? + * + * @since 4.4.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is for an embedded post. + */ + function is_embed() + { + } + /** + * Determines whether the query is the main query. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 3.3.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool Whether the query is the main query. + */ + function is_main_query() + { + } + /* + * The Loop. Post loop control. + */ + /** + * Determines whether current WordPress query has posts to loop over. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool True if posts are available, false if end of the loop. + */ + function have_posts() + { + } + /** + * Determines whether the caller is in the Loop. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.0.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool True if caller is within loop, false if loop hasn't started or ended. + */ + function in_the_loop() + { + } + /** + * Rewind the loop posts. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + */ + function rewind_posts() + { + } + /** + * Iterate the post index in the loop. + * + * @since 1.5.0 + * + * @global WP_Query $wp_query WordPress Query object. + */ + function the_post() + { + } + /* + * Comments loop. + */ + /** + * Determines whether current WordPress query has comments to loop over. + * + * @since 2.2.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @return bool True if comments are available, false if no more comments. + */ + function have_comments() + { + } + /** + * Iterate comment index in the comment loop. + * + * @since 2.2.0 + * + * @global WP_Query $wp_query WordPress Query object. + */ + function the_comment() + { + } + /** + * Redirect old slugs to the correct permalink. + * + * Attempts to find the current slug from the past slugs. + * + * @since 2.1.0 + */ + function wp_old_slug_redirect() + { + } + /** + * Find the post ID for redirecting an old slug. + * + * @since 4.9.3 + * @access private + * + * @see wp_old_slug_redirect() + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $post_type The current post type based on the query vars. + * @return int The Post ID. + */ + function _find_post_by_old_slug($post_type) + { + } + /** + * Find the post ID for redirecting an old date. + * + * @since 4.9.3 + * @access private + * + * @see wp_old_slug_redirect() + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $post_type The current post type based on the query vars. + * @return int The Post ID. + */ + function _find_post_by_old_date($post_type) + { + } + /** + * Set up global post data. + * + * @since 1.5.0 + * @since 4.4.0 Added the ability to pass a post ID to `$post`. + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param WP_Post|object|int $post WP_Post instance or Post ID/object. + * @return bool True when finished. + */ + function setup_postdata($post) + { + } + /** + * Generates post data. + * + * @since 5.2.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param WP_Post|object|int $post WP_Post instance or Post ID/object. + * @return array|false Elements of post, or false on failure. + */ + function generate_postdata($post) + { + } + /** + * Registers a REST API route. + * + * Note: Do not use before the {@see 'rest_api_init'} hook. + * + * @since 4.4.0 + * @since 5.1.0 Added a `_doing_it_wrong()` notice when not called on or after the `rest_api_init` hook. + * @since 5.5.0 Added a `_doing_it_wrong()` notice when the required `permission_callback` argument is not set. + * + * @param string $namespace The first URL segment after core prefix. Should be unique to your package/plugin. + * @param string $route The base URL for route you are adding. + * @param array $args Optional. Either an array of options for the endpoint, or an array of arrays for + * multiple methods. Default empty array. + * @param bool $override Optional. If the route already exists, should we override it? True overrides, + * false merges (with newer overriding if duplicate keys exist). Default false. + * @return bool True on success, false on error. + */ + function register_rest_route($namespace, $route, $args = array(), $override = \false) + { + } + /** + * Registers a new field on an existing WordPress object type. + * + * @since 4.7.0 + * + * @global array $wp_rest_additional_fields Holds registered fields, organized + * by object type. + * + * @param string|array $object_type Object(s) the field is being registered to, + * "post"|"term"|"comment" etc. + * @param string $attribute The attribute name. + * @param array $args { + * Optional. An array of arguments used to handle the registered field. + * + * @type callable|null $get_callback Optional. The callback function used to retrieve the field value. Default is + * 'null', the field will not be returned in the response. The function will + * be passed the prepared object data. + * @type callable|null $update_callback Optional. The callback function used to set and update the field value. Default + * is 'null', the value cannot be set or updated. The function will be passed + * the model object, like WP_Post. + * @type array|null $schema Optional. The schema for this field. + * Default is 'null', no schema entry will be returned. + * } + * @phpstan-param array{ + * get_callback?: callable|null, + * update_callback?: callable|null, + * schema?: array|null, + * } $args + */ + function register_rest_field($object_type, $attribute, $args = array()) + { + } + /** + * Registers rewrite rules for the REST API. + * + * @since 4.4.0 + * + * @see rest_api_register_rewrites() + * @global WP $wp Current WordPress environment instance. + */ + function rest_api_init() + { + } + /** + * Adds REST rewrite rules. + * + * @since 4.4.0 + * + * @see add_rewrite_rule() + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + */ + function rest_api_register_rewrites() + { + } + /** + * Registers the default REST API filters. + * + * Attached to the {@see 'rest_api_init'} action + * to make testing and disabling these filters easier. + * + * @since 4.4.0 + */ + function rest_api_default_filters() + { + } + /** + * Registers default REST API routes. + * + * @since 4.7.0 + */ + function create_initial_rest_routes() + { + } + /** + * Loads the REST API. + * + * @since 4.4.0 + * + * @global WP $wp Current WordPress environment instance. + */ + function rest_api_loaded() + { + } + /** + * Retrieves the URL prefix for any API resource. + * + * @since 4.4.0 + * + * @return string Prefix. + */ + function rest_get_url_prefix() + { + } + /** + * Retrieves the URL to a REST endpoint on a site. + * + * Note: The returned URL is NOT escaped. + * + * @since 4.4.0 + * + * @todo Check if this is even necessary + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param int|null $blog_id Optional. Blog ID. Default of null returns URL for current blog. + * @param string $path Optional. REST route. Default '/'. + * @param string $scheme Optional. Sanitization scheme. Default 'rest'. + * @return string Full URL to the endpoint. + */ + function get_rest_url($blog_id = \null, $path = '/', $scheme = 'rest') + { + } + /** + * Retrieves the URL to a REST endpoint. + * + * Note: The returned URL is NOT escaped. + * + * @since 4.4.0 + * + * @param string $path Optional. REST route. Default empty. + * @param string $scheme Optional. Sanitization scheme. Default 'rest'. + * @return string Full URL to the endpoint. + */ + function rest_url($path = '', $scheme = 'rest') + { + } + /** + * Do a REST request. + * + * Used primarily to route internal requests through WP_REST_Server. + * + * @since 4.4.0 + * + * @param WP_REST_Request|string $request Request. + * @return WP_REST_Response REST response. + */ + function rest_do_request($request) + { + } + /** + * Retrieves the current REST server instance. + * + * Instantiates a new instance if none exists already. + * + * @since 4.5.0 + * + * @global WP_REST_Server $wp_rest_server REST server instance. + * + * @return WP_REST_Server REST server instance. + */ + function rest_get_server() + { + } + /** + * Ensures request arguments are a request object (for consistency). + * + * @since 4.4.0 + * @since 5.3.0 Accept string argument for the request path. + * + * @param array|string|WP_REST_Request $request Request to check. + * @return WP_REST_Request REST request instance. + */ + function rest_ensure_request($request) + { + } + /** + * Ensures a REST response is a response object (for consistency). + * + * This implements WP_REST_Response, allowing usage of `set_status`/`header`/etc + * without needing to double-check the object. Will also allow WP_Error to indicate error + * responses, so users should immediately check for this value. + * + * @since 4.4.0 + * + * @param WP_REST_Response|WP_Error|WP_HTTP_Response|mixed $response Response to check. + * @return WP_REST_Response|WP_Error If response generated an error, WP_Error, if response + * is already an instance, WP_REST_Response, otherwise + * returns a new WP_REST_Response instance. + */ + function rest_ensure_response($response) + { + } + /** + * Handles _deprecated_function() errors. + * + * @since 4.4.0 + * + * @param string $function The function that was called. + * @param string $replacement The function that should have been called. + * @param string $version Version. + */ + function rest_handle_deprecated_function($function, $replacement, $version) + { + } + /** + * Handles _deprecated_argument() errors. + * + * @since 4.4.0 + * + * @param string $function The function that was called. + * @param string $message A message regarding the change. + * @param string $version Version. + */ + function rest_handle_deprecated_argument($function, $message, $version) + { + } + /** + * Handles _doing_it_wrong errors. + * + * @since 5.5.0 + * + * @param string $function The function that was called. + * @param string $message A message explaining what has been done incorrectly. + * @param string|null $version The version of WordPress where the message was added. + */ + function rest_handle_doing_it_wrong($function, $message, $version) + { + } + /** + * Sends Cross-Origin Resource Sharing headers with API requests. + * + * @since 4.4.0 + * + * @param mixed $value Response data. + * @return mixed Response data. + */ + function rest_send_cors_headers($value) + { + } + /** + * Handles OPTIONS requests for the server. + * + * This is handled outside of the server code, as it doesn't obey normal route + * mapping. + * + * @since 4.4.0 + * + * @param mixed $response Current response, either response or `null` to indicate pass-through. + * @param WP_REST_Server $handler ResponseHandler instance (usually WP_REST_Server). + * @param WP_REST_Request $request The request that was used to make current response. + * @return WP_REST_Response Modified response, either response or `null` to indicate pass-through. + */ + function rest_handle_options_request($response, $handler, $request) + { + } + /** + * Sends the "Allow" header to state all methods that can be sent to the current route. + * + * @since 4.4.0 + * + * @param WP_REST_Response $response Current response being served. + * @param WP_REST_Server $server ResponseHandler instance (usually WP_REST_Server). + * @param WP_REST_Request $request The request that was used to make current response. + * @return WP_REST_Response Response to be served, with "Allow" header if route has allowed methods. + */ + function rest_send_allow_header($response, $server, $request) + { + } + /** + * Recursively computes the intersection of arrays using keys for comparison. + * + * @since 5.3.0 + * + * @param array $array1 The array with master keys to check. + * @param array $array2 An array to compare keys against. + * @return array An associative array containing all the entries of array1 which have keys + * that are present in all arguments. + */ + function _rest_array_intersect_key_recursive($array1, $array2) + { + } + /** + * Filters the REST API response to include only a white-listed set of response object fields. + * + * @since 4.8.0 + * + * @param WP_REST_Response $response Current response being served. + * @param WP_REST_Server $server ResponseHandler instance (usually WP_REST_Server). + * @param WP_REST_Request $request The request that was used to make current response. + * @return WP_REST_Response Response to be served, trimmed down to contain a subset of fields. + */ + function rest_filter_response_fields($response, $server, $request) + { + } + /** + * Given an array of fields to include in a response, some of which may be + * `nested.fields`, determine whether the provided field should be included + * in the response body. + * + * If a parent field is passed in, the presence of any nested field within + * that parent will cause the method to return `true`. For example "title" + * will return true if any of `title`, `title.raw` or `title.rendered` is + * provided. + * + * @since 5.3.0 + * + * @param string $field A field to test for inclusion in the response body. + * @param array $fields An array of string fields supported by the endpoint. + * @return bool Whether to include the field or not. + */ + function rest_is_field_included($field, $fields) + { + } + /** + * Adds the REST API URL to the WP RSD endpoint. + * + * @since 4.4.0 + * + * @see get_rest_url() + */ + function rest_output_rsd() + { + } + /** + * Outputs the REST API link tag into page header. + * + * @since 4.4.0 + * + * @see get_rest_url() + */ + function rest_output_link_wp_head() + { + } + /** + * Sends a Link header for the REST API. + * + * @since 4.4.0 + */ + function rest_output_link_header() + { + } + /** + * Checks for errors when using cookie-based authentication. + * + * WordPress' built-in cookie authentication is always active + * for logged in users. However, the API has to check nonces + * for each request to ensure users are not vulnerable to CSRF. + * + * @since 4.4.0 + * + * @global mixed $wp_rest_auth_cookie + * + * @param WP_Error|mixed $result Error from another authentication handler, + * null if we should handle it, or another value if not. + * @return WP_Error|mixed|bool WP_Error if the cookie is invalid, the $result, otherwise true. + */ + function rest_cookie_check_errors($result) + { + } + /** + * Collects cookie authentication status. + * + * Collects errors from wp_validate_auth_cookie for use by rest_cookie_check_errors. + * + * @since 4.4.0 + * + * @see current_action() + * @global mixed $wp_rest_auth_cookie + */ + function rest_cookie_collect_status() + { + } + /** + * Collects the status of authenticating with an application password. + * + * @since 5.6.0 + * @since 5.7.0 Added the `$app_password` parameter. + * + * @global WP_User|WP_Error|null $wp_rest_application_password_status + * @global string|null $wp_rest_application_password_uuid + * + * @param WP_Error $user_or_error The authenticated user or error instance. + * @param array $app_password The Application Password used to authenticate. + */ + function rest_application_password_collect_status($user_or_error, $app_password = array()) + { + } + /** + * Gets the Application Password used for authenticating the request. + * + * @since 5.7.0 + * + * @global string|null $wp_rest_application_password_uuid + * + * @return string|null The Application Password UUID, or null if Application Passwords was not used. + */ + function rest_get_authenticated_app_password() + { + } + /** + * Checks for errors when using application password-based authentication. + * + * @since 5.6.0 + * + * @global WP_User|WP_Error|null $wp_rest_application_password_status + * + * @param WP_Error|null|true $result Error from another authentication handler, + * null if we should handle it, or another value if not. + * @return WP_Error|null|true WP_Error if the application password is invalid, the $result, otherwise true. + */ + function rest_application_password_check_errors($result) + { + } + /** + * Adds Application Passwords info to the REST API index. + * + * @since 5.6.0 + * + * @param WP_REST_Response $response The index response object. + * @return WP_REST_Response + */ + function rest_add_application_passwords_to_index($response) + { + } + /** + * Retrieves the avatar urls in various sizes. + * + * @since 4.7.0 + * + * @see get_avatar_url() + * + * @param mixed $id_or_email The Gravatar to retrieve a URL for. Accepts a user_id, gravatar md5 hash, + * user email, WP_User object, WP_Post object, or WP_Comment object. + * @return (string|false)[] Avatar URLs keyed by size. Each value can be a URL string or boolean false. + */ + function rest_get_avatar_urls($id_or_email) + { + } + /** + * Retrieves the pixel sizes for avatars. + * + * @since 4.7.0 + * + * @return int[] List of pixel sizes for avatars. Default `[ 24, 48, 96 ]`. + */ + function rest_get_avatar_sizes() + { + } + /** + * Parses an RFC3339 time into a Unix timestamp. + * + * @since 4.4.0 + * + * @param string $date RFC3339 timestamp. + * @param bool $force_utc Optional. Whether to force UTC timezone instead of using + * the timestamp's timezone. Default false. + * @return int Unix timestamp. + */ + function rest_parse_date($date, $force_utc = \false) + { + } + /** + * Parses a 3 or 6 digit hex color (with #). + * + * @since 5.4.0 + * + * @param string $color 3 or 6 digit hex color (with #). + * @return string|false + */ + function rest_parse_hex_color($color) + { + } + /** + * Parses a date into both its local and UTC equivalent, in MySQL datetime format. + * + * @since 4.4.0 + * + * @see rest_parse_date() + * + * @param string $date RFC3339 timestamp. + * @param bool $is_utc Whether the provided date should be interpreted as UTC. Default false. + * @return array|null Local and UTC datetime strings, in MySQL datetime format (Y-m-d H:i:s), + * null on failure. + */ + function rest_get_date_with_gmt($date, $is_utc = \false) + { + } + /** + * Returns a contextual HTTP error code for authorization failure. + * + * @since 4.7.0 + * + * @return int 401 if the user is not logged in, 403 if the user is logged in. + */ + function rest_authorization_required_code() + { + } + /** + * Validate a request argument based on details registered to the route. + * + * @since 4.7.0 + * + * @param mixed $value + * @param WP_REST_Request $request + * @param string $param + * @return true|WP_Error + */ + function rest_validate_request_arg($value, $request, $param) + { + } + /** + * Sanitize a request argument based on details registered to the route. + * + * @since 4.7.0 + * + * @param mixed $value + * @param WP_REST_Request $request + * @param string $param + * @return mixed + */ + function rest_sanitize_request_arg($value, $request, $param) + { + } + /** + * Parse a request argument based on details registered to the route. + * + * Runs a validation check and sanitizes the value, primarily to be used via + * the `sanitize_callback` arguments in the endpoint args registration. + * + * @since 4.7.0 + * + * @param mixed $value + * @param WP_REST_Request $request + * @param string $param + * @return mixed + */ + function rest_parse_request_arg($value, $request, $param) + { + } + /** + * Determines if an IP address is valid. + * + * Handles both IPv4 and IPv6 addresses. + * + * @since 4.7.0 + * + * @param string $ip IP address. + * @return string|false The valid IP address, otherwise false. + */ + function rest_is_ip_address($ip) + { + } + /** + * Changes a boolean-like value into the proper boolean value. + * + * @since 4.7.0 + * + * @param bool|string|int $value The value being evaluated. + * @return bool Returns the proper associated boolean value. + */ + function rest_sanitize_boolean($value) + { + } + /** + * Determines if a given value is boolean-like. + * + * @since 4.7.0 + * + * @param bool|string $maybe_bool The value being evaluated. + * @return bool True if a boolean, otherwise false. + */ + function rest_is_boolean($maybe_bool) + { + } + /** + * Determines if a given value is integer-like. + * + * @since 5.5.0 + * + * @param mixed $maybe_integer The value being evaluated. + * @return bool True if an integer, otherwise false. + */ + function rest_is_integer($maybe_integer) + { + } + /** + * Determines if a given value is array-like. + * + * @since 5.5.0 + * + * @param mixed $maybe_array The value being evaluated. + * @return bool + */ + function rest_is_array($maybe_array) + { + } + /** + * Converts an array-like value to an array. + * + * @since 5.5.0 + * + * @param mixed $maybe_array The value being evaluated. + * @return array Returns the array extracted from the value. + */ + function rest_sanitize_array($maybe_array) + { + } + /** + * Determines if a given value is object-like. + * + * @since 5.5.0 + * + * @param mixed $maybe_object The value being evaluated. + * @return bool True if object like, otherwise false. + */ + function rest_is_object($maybe_object) + { + } + /** + * Converts an object-like value to an object. + * + * @since 5.5.0 + * + * @param mixed $maybe_object The value being evaluated. + * @return array Returns the object extracted from the value. + */ + function rest_sanitize_object($maybe_object) + { + } + /** + * Gets the best type for a value. + * + * @since 5.5.0 + * + * @param mixed $value The value to check. + * @param array $types The list of possible types. + * @return string The best matching type, an empty string if no types match. + */ + function rest_get_best_type_for_value($value, $types) + { + } + /** + * Handles getting the best type for a multi-type schema. + * + * This is a wrapper for {@see rest_get_best_type_for_value()} that handles + * backward compatibility for schemas that use invalid types. + * + * @since 5.5.0 + * + * @param mixed $value The value to check. + * @param array $args The schema array to use. + * @param string $param The parameter name, used in error messages. + * @return string + */ + function rest_handle_multi_type_schema($value, $args, $param = '') + { + } + /** + * Checks if an array is made up of unique items. + * + * @since 5.5.0 + * + * @param array $array The array to check. + * @return bool True if the array contains unique items, false otherwise. + */ + function rest_validate_array_contains_unique_items($array) + { + } + /** + * Stabilizes a value following JSON Schema semantics. + * + * For lists, order is preserved. For objects, properties are reordered alphabetically. + * + * @since 5.5.0 + * + * @param mixed $value The value to stabilize. Must already be sanitized. Objects should have been converted to arrays. + * @return mixed The stabilized value. + */ + function rest_stabilize_value($value) + { + } + /** + * Validates if the JSON Schema pattern matches a value. + * + * @since 5.6.0 + * + * @param string $pattern The pattern to match against. + * @param string $value The value to check. + * @return bool True if the pattern matches the given value, false otherwise. + */ + function rest_validate_json_schema_pattern($pattern, $value) + { + } + /** + * Finds the schema for a property using the patternProperties keyword. + * + * @since 5.6.0 + * + * @param string $property The property name to check. + * @param array $args The schema array to use. + * @return array|null The schema of matching pattern property, or null if no patterns match. + */ + function rest_find_matching_pattern_property_schema($property, $args) + { + } + /** + * Formats a combining operation error into a WP_Error object. + * + * @since 5.6.0 + * + * @param string $param The parameter name. + * @param array $error The error details. + * @return WP_Error + */ + function rest_format_combining_operation_error($param, $error) + { + } + /** + * Gets the error of combining operation. + * + * @since 5.6.0 + * + * @param array $value The value to validate. + * @param string $param The parameter name, used in error messages. + * @param array $errors The errors array, to search for possible error. + * @return WP_Error The combining operation error. + */ + function rest_get_combining_operation_error($value, $param, $errors) + { + } + /** + * Finds the matching schema among the "anyOf" schemas. + * + * @since 5.6.0 + * + * @param mixed $value The value to validate. + * @param array $args The schema array to use. + * @param string $param The parameter name, used in error messages. + * @return array|WP_Error The matching schema or WP_Error instance if all schemas do not match. + */ + function rest_find_any_matching_schema($value, $args, $param) + { + } + /** + * Finds the matching schema among the "oneOf" schemas. + * + * @since 5.6.0 + * + * @param mixed $value The value to validate. + * @param array $args The schema array to use. + * @param string $param The parameter name, used in error messages. + * @param bool $stop_after_first_match Optional. Whether the process should stop after the first successful match. + * @return array|WP_Error The matching schema or WP_Error instance if the number of matching schemas is not equal to one. + */ + function rest_find_one_matching_schema($value, $args, $param, $stop_after_first_match = \false) + { + } + /** + * Checks the equality of two values, following JSON Schema semantics. + * + * Property order is ignored for objects. + * + * Values must have been previously sanitized/coerced to their native types. + * + * @since 5.7.0 + * + * @param mixed $value1 The first value to check. + * @param mixed $value2 The second value to check. + * @return bool True if the values are equal or false otherwise. + */ + function rest_are_values_equal($value1, $value2) + { + } + /** + * Validates that the given value is a member of the JSON Schema "enum". + * + * @since 5.7.0 + * + * @param mixed $value The value to validate. + * @param array $args The schema array to use. + * @param string $param The parameter name, used in error messages. + * @return true|WP_Error True if the "enum" contains the value or a WP_Error instance otherwise. + */ + function rest_validate_enum($value, $args, $param) + { + } + /** + * Get all valid JSON schema properties. + * + * @since 5.6.0 + * + * @return string[] All valid JSON schema properties. + */ + function rest_get_allowed_schema_keywords() + { + } + /** + * Validate a value based on a schema. + * + * @since 4.7.0 + * @since 4.9.0 Support the "object" type. + * @since 5.2.0 Support validating "additionalProperties" against a schema. + * @since 5.3.0 Support multiple types. + * @since 5.4.0 Convert an empty string to an empty object. + * @since 5.5.0 Add the "uuid" and "hex-color" formats. + * Support the "minLength", "maxLength" and "pattern" keywords for strings. + * Support the "minItems", "maxItems" and "uniqueItems" keywords for arrays. + * Validate required properties. + * @since 5.6.0 Support the "minProperties" and "maxProperties" keywords for objects. + * Support the "multipleOf" keyword for numbers and integers. + * Support the "patternProperties" keyword for objects. + * Support the "anyOf" and "oneOf" keywords. + * + * @param mixed $value The value to validate. + * @param array $args Schema array to use for validation. + * @param string $param The parameter name, used in error messages. + * @return true|WP_Error + */ + function rest_validate_value_from_schema($value, $args, $param = '') + { + } + /** + * Validates a null value based on a schema. + * + * @since 5.7.0 + * + * @param mixed $value The value to validate. + * @param string $param The parameter name, used in error messages. + * @return true|WP_Error + */ + function rest_validate_null_value_from_schema($value, $param) + { + } + /** + * Validates a boolean value based on a schema. + * + * @since 5.7.0 + * + * @param mixed $value The value to validate. + * @param string $param The parameter name, used in error messages. + * @return true|WP_Error + */ + function rest_validate_boolean_value_from_schema($value, $param) + { + } + /** + * Validates an object value based on a schema. + * + * @since 5.7.0 + * + * @param mixed $value The value to validate. + * @param array $args Schema array to use for validation. + * @param string $param The parameter name, used in error messages. + * @return true|WP_Error + */ + function rest_validate_object_value_from_schema($value, $args, $param) + { + } + /** + * Validates an array value based on a schema. + * + * @since 5.7.0 + * + * @param mixed $value The value to validate. + * @param array $args Schema array to use for validation. + * @param string $param The parameter name, used in error messages. + * @return true|WP_Error + */ + function rest_validate_array_value_from_schema($value, $args, $param) + { + } + /** + * Validates a number value based on a schema. + * + * @since 5.7.0 + * + * @param mixed $value The value to validate. + * @param array $args Schema array to use for validation. + * @param string $param The parameter name, used in error messages. + * @return true|WP_Error + */ + function rest_validate_number_value_from_schema($value, $args, $param) + { + } + /** + * Validates a string value based on a schema. + * + * @since 5.7.0 + * + * @param mixed $value The value to validate. + * @param array $args Schema array to use for validation. + * @param string $param The parameter name, used in error messages. + * @return true|WP_Error + */ + function rest_validate_string_value_from_schema($value, $args, $param) + { + } + /** + * Validates an integer value based on a schema. + * + * @since 5.7.0 + * + * @param mixed $value The value to validate. + * @param array $args Schema array to use for validation. + * @param string $param The parameter name, used in error messages. + * @return true|WP_Error + */ + function rest_validate_integer_value_from_schema($value, $args, $param) + { + } + /** + * Sanitize a value based on a schema. + * + * @since 4.7.0 + * @since 5.5.0 Added the `$param` parameter. + * @since 5.6.0 Support the "anyOf" and "oneOf" keywords. + * @since 5.9.0 Added `text-field` and `textarea-field` formats. + * + * @param mixed $value The value to sanitize. + * @param array $args Schema array to use for sanitization. + * @param string $param The parameter name, used in error messages. + * @return mixed|WP_Error The sanitized value or a WP_Error instance if the value cannot be safely sanitized. + */ + function rest_sanitize_value_from_schema($value, $args, $param = '') + { + } + /** + * Append result of internal request to REST API for purpose of preloading data to be attached to a page. + * Expected to be called in the context of `array_reduce`. + * + * @since 5.0.0 + * + * @param array $memo Reduce accumulator. + * @param string $path REST API path to preload. + * @return array Modified reduce accumulator. + */ + function rest_preload_api_request($memo, $path) + { + } + /** + * Parses the "_embed" parameter into the list of resources to embed. + * + * @since 5.4.0 + * + * @param string|array $embed Raw "_embed" parameter value. + * @return true|string[] Either true to embed all embeds, or a list of relations to embed. + */ + function rest_parse_embed_param($embed) + { + } + /** + * Filters the response to remove any fields not available in the given context. + * + * @since 5.5.0 + * @since 5.6.0 Support the "patternProperties" keyword for objects. + * Support the "anyOf" and "oneOf" keywords. + * + * @param array|object $data The response data to modify. + * @param array $schema The schema for the endpoint used to filter the response. + * @param string $context The requested context. + * @return array|object The filtered response data. + */ + function rest_filter_response_by_context($data, $schema, $context) + { + } + /** + * Sets the "additionalProperties" to false by default for all object definitions in the schema. + * + * @since 5.5.0 + * @since 5.6.0 Support the "patternProperties" keyword. + * + * @param array $schema The schema to modify. + * @return array The modified schema. + */ + function rest_default_additional_properties_to_false($schema) + { + } + /** + * Gets the REST API route for a post. + * + * @since 5.5.0 + * + * @param int|WP_Post $post Post ID or post object. + * @return string The route path with a leading slash for the given post, + * or an empty string if there is not a route. + */ + function rest_get_route_for_post($post) + { + } + /** + * Gets the REST API route for a post type. + * + * @since 5.9.0 + * + * @param string $post_type The name of a registered post type. + * @return string The route path with a leading slash for the given post type, + * or an empty string if there is not a route. + */ + function rest_get_route_for_post_type_items($post_type) + { + } + /** + * Gets the REST API route for a term. + * + * @since 5.5.0 + * + * @param int|WP_Term $term Term ID or term object. + * @return string The route path with a leading slash for the given term, + * or an empty string if there is not a route. + */ + function rest_get_route_for_term($term) + { + } + /** + * Gets the REST API route for a taxonomy. + * + * @since 5.9.0 + * + * @param string $taxonomy Name of taxonomy. + * @return string The route path with a leading slash for the given taxonomy. + */ + function rest_get_route_for_taxonomy_items($taxonomy) + { + } + /** + * Gets the REST route for the currently queried object. + * + * @since 5.5.0 + * + * @return string The REST route of the resource, or an empty string if no resource identified. + */ + function rest_get_queried_resource_route() + { + } + /** + * Retrieves an array of endpoint arguments from the item schema and endpoint method. + * + * @since 5.6.0 + * + * @param array $schema The full JSON schema for the endpoint. + * @param string $method Optional. HTTP method of the endpoint. The arguments for `CREATABLE` endpoints are + * checked for required values and may fall-back to a given default, this is not done + * on `EDITABLE` endpoints. Default WP_REST_Server::CREATABLE. + * @return array The endpoint arguments. + */ + function rest_get_endpoint_args_for_schema($schema, $method = \WP_REST_Server::CREATABLE) + { + } + /** + * Converts an error to a response object. + * + * This iterates over all error codes and messages to change it into a flat + * array. This enables simpler client behaviour, as it is represented as a + * list in JSON rather than an object/map. + * + * @since 5.7.0 + * + * @param WP_Error $error WP_Error instance. + * + * @return WP_REST_Response List of associative arrays with code and message keys. + */ + function rest_convert_error_to_response($error) + { + } + /** + * Post revision functions. + * + * @package WordPress + * @subpackage Post_Revisions + */ + /** + * Determines which fields of posts are to be saved in revisions. + * + * @since 2.6.0 + * @since 4.5.0 A `WP_Post` object can now be passed to the `$post` parameter. + * @since 4.5.0 The optional `$autosave` parameter was deprecated and renamed to `$deprecated`. + * @access private + * + * @param array|WP_Post $post Optional. A post array or a WP_Post object being processed + * for insertion as a post revision. Default empty array. + * @param bool $deprecated Not used. + * @return string[] Array of fields that can be versioned. + */ + function _wp_post_revision_fields($post = array(), $deprecated = \false) + { + } + /** + * Returns a post array ready to be inserted into the posts table as a post revision. + * + * @since 4.5.0 + * @access private + * + * @param array|WP_Post $post Optional. A post array or a WP_Post object to be processed + * for insertion as a post revision. Default empty array. + * @param bool $autosave Optional. Is the revision an autosave? Default false. + * @return array Post array ready to be inserted as a post revision. + */ + function _wp_post_revision_data($post = array(), $autosave = \false) + { + } + /** + * Creates a revision for the current version of a post. + * + * Typically used immediately after a post update, as every update is a revision, + * and the most recent revision always matches the current post. + * + * @since 2.6.0 + * + * @param int $post_id The ID of the post to save as a revision. + * @return int|WP_Error|void Void or 0 if error, new revision ID, if success. + */ + function wp_save_post_revision($post_id) + { + } + /** + * Retrieves the autosaved data of the specified post. + * + * Returns a post object with the information that was autosaved for the specified post. + * If the optional $user_id is passed, returns the autosave for that user, otherwise + * returns the latest autosave. + * + * @since 2.6.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $post_id The post ID. + * @param int $user_id Optional. The post author ID. + * @return WP_Post|false The autosaved data or false on failure or when no autosave exists. + */ + function wp_get_post_autosave($post_id, $user_id = 0) + { + } + /** + * Determines if the specified post is a revision. + * + * @since 2.6.0 + * + * @param int|WP_Post $post Post ID or post object. + * @return int|false ID of revision's parent on success, false if not a revision. + */ + function wp_is_post_revision($post) + { + } + /** + * Determines if the specified post is an autosave. + * + * @since 2.6.0 + * + * @param int|WP_Post $post Post ID or post object. + * @return int|false ID of autosave's parent on success, false if not a revision. + */ + function wp_is_post_autosave($post) + { + } + /** + * Inserts post data into the posts table as a post revision. + * + * @since 2.6.0 + * @access private + * + * @param int|WP_Post|array|null $post Post ID, post object OR post array. + * @param bool $autosave Optional. Whether the revision is an autosave or not. + * @return int|WP_Error WP_Error or 0 if error, new revision ID if success. + */ + function _wp_put_post_revision($post = \null, $autosave = \false) + { + } + /** + * Gets a post revision. + * + * @since 2.6.0 + * + * @param int|WP_Post $post Post ID or post object. + * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which + * correspond to a WP_Post object, an associative array, or a numeric array, + * respectively. Default OBJECT. + * @param string $filter Optional sanitization filter. See sanitize_post(). + * @return WP_Post|array|null WP_Post (or array) on success, or null on failure. + */ + function wp_get_post_revision(&$post, $output = \OBJECT, $filter = 'raw') + { + } + /** + * Restores a post to the specified revision. + * + * Can restore a past revision using all fields of the post revision, or only selected fields. + * + * @since 2.6.0 + * + * @param int|WP_Post $revision Revision ID or revision object. + * @param array $fields Optional. What fields to restore from. Defaults to all. + * @return int|false|null Null if error, false if no fields to restore, (int) post ID if success. + */ + function wp_restore_post_revision($revision, $fields = \null) + { + } + /** + * Deletes a revision. + * + * Deletes the row from the posts table corresponding to the specified revision. + * + * @since 2.6.0 + * + * @param int|WP_Post $revision Revision ID or revision object. + * @return WP_Post|false|null Null or false if error, deleted post object if success. + */ + function wp_delete_post_revision($revision) + { + } + /** + * Returns all revisions of specified post. + * + * @since 2.6.0 + * + * @see get_children() + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global `$post`. + * @param array|null $args Optional. Arguments for retrieving post revisions. Default null. + * @return WP_Post[]|int[] Array of revision objects or IDs, or an empty array if none. + */ + function wp_get_post_revisions($post = 0, $args = \null) + { + } + /** + * Returns the latest revision ID and count of revisions for a post. + * + * @since 6.1.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @return array|WP_Error { + * Returns associative array with latest revision ID and total count, + * or a WP_Error if the post does not exist or revisions are not enabled. + * + * @type int $latest_id The latest revision post ID or 0 if no revisions exist. + * @type int $count The total count of revisions for the given post. + * } + * @phpstan-return \WP_Error|array{ + * latest_id: int, + * count: int, + * } + */ + function wp_get_latest_revision_id_and_total_count($post = 0) + { + } + /** + * Returns the url for viewing and potentially restoring revisions of a given post. + * + * @since 5.9.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global `$post`. + * @return string|null The URL for editing revisions on the given post, otherwise null. + */ + function wp_get_post_revisions_url($post = 0) + { + } + /** + * Determines whether revisions are enabled for a given post. + * + * @since 3.6.0 + * + * @param WP_Post $post The post object. + * @return bool True if number of revisions to keep isn't zero, false otherwise. + */ + function wp_revisions_enabled($post) + { + } + /** + * Determines how many revisions to retain for a given post. + * + * By default, an infinite number of revisions are kept. + * + * The constant WP_POST_REVISIONS can be set in wp-config to specify the limit + * of revisions to keep. + * + * @since 3.6.0 + * + * @param WP_Post $post The post object. + * @return int The number of revisions to keep. + */ + function wp_revisions_to_keep($post) + { + } + /** + * Sets up the post object for preview based on the post autosave. + * + * @since 2.7.0 + * @access private + * + * @param WP_Post $post + * @return WP_Post|false + */ + function _set_preview($post) + { + } + /** + * Filters the latest content for preview from the post autosave. + * + * @since 2.7.0 + * @access private + */ + function _show_post_preview() + { + } + /** + * Filters terms lookup to set the post format. + * + * @since 3.6.0 + * @access private + * + * @param array $terms + * @param int $post_id + * @param string $taxonomy + * @return array + */ + function _wp_preview_terms_filter($terms, $post_id, $taxonomy) + { + } + /** + * Filters post thumbnail lookup to set the post thumbnail. + * + * @since 4.6.0 + * @access private + * + * @param null|array|string $value The value to return - a single metadata value, or an array of values. + * @param int $post_id Post ID. + * @param string $meta_key Meta key. + * @return null|array The default return value or the post thumbnail meta array. + */ + function _wp_preview_post_thumbnail_filter($value, $post_id, $meta_key) + { + } + /** + * Gets the post revision version. + * + * @since 3.6.0 + * @access private + * + * @param WP_Post $revision + * @return int|false + */ + function _wp_get_post_revision_version($revision) + { + } + /** + * Upgrades the revisions author, adds the current post as a revision and sets the revisions version to 1. + * + * @since 3.6.0 + * @access private + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param WP_Post $post Post object. + * @param array $revisions Current revisions of the post. + * @return bool true if the revisions were upgraded, false if problems. + */ + function _wp_upgrade_revisions_of_post($post, $revisions) + { + } + /** + * Adds a rewrite rule that transforms a URL structure to a set of query vars. + * + * Any value in the $after parameter that isn't 'bottom' will result in the rule + * being placed at the top of the rewrite rules. + * + * @since 2.1.0 + * @since 4.4.0 Array support was added to the `$query` parameter. + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $regex Regular expression to match request against. + * @param string|array $query The corresponding query vars for this rewrite rule. + * @param string $after Optional. Priority of the new rule. Accepts 'top' + * or 'bottom'. Default 'bottom'. + */ + function add_rewrite_rule($regex, $query, $after = 'bottom') + { + } + /** + * Adds a new rewrite tag (like %postname%). + * + * The `$query` parameter is optional. If it is omitted you must ensure that you call + * this on, or before, the {@see 'init'} hook. This is because `$query` defaults to + * `$tag=`, and for this to work a new query var has to be added. + * + * @since 2.1.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * @global WP $wp Current WordPress environment instance. + * + * @param string $tag Name of the new rewrite tag. + * @param string $regex Regular expression to substitute the tag for in rewrite rules. + * @param string $query Optional. String to append to the rewritten query. Must end in '='. Default empty. + */ + function add_rewrite_tag($tag, $regex, $query = '') + { + } + /** + * Removes an existing rewrite tag (like %postname%). + * + * @since 4.5.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $tag Name of the rewrite tag. + */ + function remove_rewrite_tag($tag) + { + } + /** + * Adds a permalink structure. + * + * @since 3.0.0 + * + * @see WP_Rewrite::add_permastruct() + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $name Name for permalink structure. + * @param string $struct Permalink structure. + * @param array $args Optional. Arguments for building the rules from the permalink structure, + * see WP_Rewrite::add_permastruct() for full details. Default empty array. + * @phpstan-param array{ + * with_front?: bool, + * ep_mask?: int, + * paged?: bool, + * feed?: bool, + * forcomments?: bool, + * walk_dirs?: bool, + * endpoints?: bool, + * } $args See WP_Rewrite::add_permastruct() + */ + function add_permastruct($name, $struct, $args = array()) + { + } + /** + * Removes a permalink structure. + * + * Can only be used to remove permastructs that were added using add_permastruct(). + * Built-in permastructs cannot be removed. + * + * @since 4.5.0 + * + * @see WP_Rewrite::remove_permastruct() + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $name Name for permalink structure. + */ + function remove_permastruct($name) + { + } + /** + * Adds a new feed type like /atom1/. + * + * @since 2.1.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $feedname Feed name. + * @param callable $function Callback to run on feed display. + * @return string Feed action name. + */ + function add_feed($feedname, $function) + { + } + /** + * Removes rewrite rules and then recreate rewrite rules. + * + * @since 3.0.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param bool $hard Whether to update .htaccess (hard flush) or just update + * rewrite_rules option (soft flush). Default is true (hard). + */ + function flush_rewrite_rules($hard = \true) + { + } + /** + * Adds an endpoint, like /trackback/. + * + * Adding an endpoint creates extra rewrite rules for each of the matching + * places specified by the provided bitmask. For example: + * + * add_rewrite_endpoint( 'json', EP_PERMALINK | EP_PAGES ); + * + * will add a new rewrite rule ending with "json(/(.*))?/?$" for every permastruct + * that describes a permalink (post) or page. This is rewritten to "json=$match" + * where $match is the part of the URL matched by the endpoint regex (e.g. "foo" in + * "[permalink]/json/foo/"). + * + * A new query var with the same name as the endpoint will also be created. + * + * When specifying $places ensure that you are using the EP_* constants (or a + * combination of them using the bitwise OR operator) as their values are not + * guaranteed to remain static (especially `EP_ALL`). + * + * Be sure to flush the rewrite rules - see flush_rewrite_rules() - when your plugin gets + * activated and deactivated. + * + * @since 2.1.0 + * @since 4.3.0 Added support for skipping query var registration by passing `false` to `$query_var`. + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param string $name Name of the endpoint. + * @param int $places Endpoint mask describing the places the endpoint should be added. + * Accepts a mask of: + * - `EP_ALL` + * - `EP_NONE` + * - `EP_ALL_ARCHIVES` + * - `EP_ATTACHMENT` + * - `EP_AUTHORS` + * - `EP_CATEGORIES` + * - `EP_COMMENTS` + * - `EP_DATE` + * - `EP_DAY` + * - `EP_MONTH` + * - `EP_PAGES` + * - `EP_PERMALINK` + * - `EP_ROOT` + * - `EP_SEARCH` + * - `EP_TAGS` + * - `EP_YEAR` + * @param string|bool $query_var Name of the corresponding query variable. Pass `false` to skip registering a query_var + * for this endpoint. Defaults to the value of `$name`. + */ + function add_rewrite_endpoint($name, $places, $query_var = \true) + { + } + /** + * Filters the URL base for taxonomies. + * + * To remove any manually prepended /index.php/. + * + * @access private + * @since 2.6.0 + * + * @param string $base The taxonomy base that we're going to filter + * @return string + */ + function _wp_filter_taxonomy_base($base) + { + } + /** + * Resolves numeric slugs that collide with date permalinks. + * + * Permalinks of posts with numeric slugs can sometimes look to WP_Query::parse_query() + * like a date archive, as when your permalink structure is `/%year%/%postname%/` and + * a post with post_name '05' has the URL `/2015/05/`. + * + * This function detects conflicts of this type and resolves them in favor of the + * post permalink. + * + * Note that, since 4.3.0, wp_unique_post_slug() prevents the creation of post slugs + * that would result in a date archive conflict. The resolution performed in this + * function is primarily for legacy content, as well as cases when the admin has changed + * the site's permalink structure in a way that introduces URL conflicts. + * + * @since 4.3.0 + * + * @param array $query_vars Optional. Query variables for setting up the loop, as determined in + * WP::parse_request(). Default empty array. + * @return array Returns the original array of query vars, with date/post conflicts resolved. + */ + function wp_resolve_numeric_slug_conflicts($query_vars = array()) + { + } + /** + * Examines a URL and try to determine the post ID it represents. + * + * Checks are supposedly from the hosted site blog. + * + * @since 1.0.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * @global WP $wp Current WordPress environment instance. + * + * @param string $url Permalink to check. + * @return int Post ID, or 0 on failure. + */ + function url_to_postid($url) + { + } + /** + * Robots template functions. + * + * @package WordPress + * @subpackage Robots + * @since 5.7.0 + */ + /** + * Displays the robots meta tag as necessary. + * + * Gathers robots directives to include for the current context, using the + * {@see 'wp_robots'} filter. The directives are then sanitized, and the + * robots meta tag is output if there is at least one relevant directive. + * + * @since 5.7.0 + * @since 5.7.1 No longer prevents specific directives to occur together. + */ + function wp_robots() + { + } + /** + * Adds `noindex` to the robots meta tag if required by the site configuration. + * + * If a blog is marked as not being public then noindex will be output to + * tell web robots not to index the page content. Add this to the + * {@see 'wp_robots'} filter. + * + * Typical usage is as a {@see 'wp_robots'} callback: + * + * add_filter( 'wp_robots', 'wp_robots_noindex' ); + * + * @since 5.7.0 + * + * @see wp_robots_no_robots() + * + * @param array $robots Associative array of robots directives. + * @return array Filtered robots directives. + */ + function wp_robots_noindex(array $robots) + { + } + /** + * Adds `noindex` to the robots meta tag for embeds. + * + * Typical usage is as a {@see 'wp_robots'} callback: + * + * add_filter( 'wp_robots', 'wp_robots_noindex_embeds' ); + * + * @since 5.7.0 + * + * @see wp_robots_no_robots() + * + * @param array $robots Associative array of robots directives. + * @return array Filtered robots directives. + */ + function wp_robots_noindex_embeds(array $robots) + { + } + /** + * Adds `noindex` to the robots meta tag if a search is being performed. + * + * If a search is being performed then noindex will be output to + * tell web robots not to index the page content. Add this to the + * {@see 'wp_robots'} filter. + * + * Typical usage is as a {@see 'wp_robots'} callback: + * + * add_filter( 'wp_robots', 'wp_robots_noindex_search' ); + * + * @since 5.7.0 + * + * @see wp_robots_no_robots() + * + * @param array $robots Associative array of robots directives. + * @return array Filtered robots directives. + */ + function wp_robots_noindex_search(array $robots) + { + } + /** + * Adds `noindex` to the robots meta tag. + * + * This directive tells web robots not to index the page content. + * + * Typical usage is as a {@see 'wp_robots'} callback: + * + * add_filter( 'wp_robots', 'wp_robots_no_robots' ); + * + * @since 5.7.0 + * + * @param array $robots Associative array of robots directives. + * @return array Filtered robots directives. + */ + function wp_robots_no_robots(array $robots) + { + } + /** + * Adds `noindex` and `noarchive` to the robots meta tag. + * + * This directive tells web robots not to index or archive the page content and + * is recommended to be used for sensitive pages. + * + * Typical usage is as a {@see 'wp_robots'} callback: + * + * add_filter( 'wp_robots', 'wp_robots_sensitive_page' ); + * + * @since 5.7.0 + * + * @param array $robots Associative array of robots directives. + * @return array Filtered robots directives. + */ + function wp_robots_sensitive_page(array $robots) + { + } + /** + * Adds `max-image-preview:large` to the robots meta tag. + * + * This directive tells web robots that large image previews are allowed to be + * displayed, e.g. in search engines, unless the blog is marked as not being public. + * + * Typical usage is as a {@see 'wp_robots'} callback: + * + * add_filter( 'wp_robots', 'wp_robots_max_image_preview_large' ); + * + * @since 5.7.0 + * + * @param array $robots Associative array of robots directives. + * @return array Filtered robots directives. + */ + function wp_robots_max_image_preview_large(array $robots) + { + } + /** + * Registers TinyMCE scripts. + * + * @since 5.0.0 + * + * @global string $tinymce_version + * @global bool $concatenate_scripts + * @global bool $compress_scripts + * + * @param WP_Scripts $scripts WP_Scripts object. + * @param bool $force_uncompressed Whether to forcibly prevent gzip compression. Default false. + */ + function wp_register_tinymce_scripts($scripts, $force_uncompressed = \false) + { + } + /** + * Registers all the WordPress vendor scripts that are in the standardized + * `js/dist/vendor/` location. + * + * For the order of `$scripts->add` see `wp_default_scripts`. + * + * @since 5.0.0 + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @param WP_Scripts $scripts WP_Scripts object. + */ + function wp_default_packages_vendor($scripts) + { + } + /** + * Returns contents of an inline script used in appending polyfill scripts for + * browsers which fail the provided tests. The provided array is a mapping from + * a condition to verify feature support to its polyfill script handle. + * + * @since 5.0.0 + * + * @param WP_Scripts $scripts WP_Scripts object. + * @param string[] $tests Features to detect. + * @return string Conditional polyfill inline script. + */ + function wp_get_script_polyfill($scripts, $tests) + { + } + /** + * Registers development scripts that integrate with `@wordpress/scripts`. + * + * @see https://github.com/WordPress/gutenberg/tree/trunk/packages/scripts#start + * + * @since 6.0.0 + * + * @param WP_Scripts $scripts WP_Scripts object. + */ + function wp_register_development_scripts($scripts) + { + } + /** + * Registers all the WordPress packages scripts that are in the standardized + * `js/dist/` location. + * + * For the order of `$scripts->add` see `wp_default_scripts`. + * + * @since 5.0.0 + * + * @param WP_Scripts $scripts WP_Scripts object. + */ + function wp_default_packages_scripts($scripts) + { + } + /** + * Adds inline scripts required for the WordPress JavaScript packages. + * + * @since 5.0.0 + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param WP_Scripts $scripts WP_Scripts object. + */ + function wp_default_packages_inline_scripts($scripts) + { + } + /** + * Adds inline scripts required for the TinyMCE in the block editor. + * + * These TinyMCE init settings are used to extend and override the default settings + * from `_WP_Editors::default_settings()` for the Classic block. + * + * @since 5.0.0 + * + * @global WP_Scripts $wp_scripts + */ + function wp_tinymce_inline_scripts() + { + } + /** + * Registers all the WordPress packages scripts. + * + * @since 5.0.0 + * + * @param WP_Scripts $scripts WP_Scripts object. + */ + function wp_default_packages($scripts) + { + } + /** + * Returns the suffix that can be used for the scripts. + * + * There are two suffix types, the normal one and the dev suffix. + * + * @since 5.0.0 + * + * @param string $type The type of suffix to retrieve. + * @return string The script suffix. + */ + function wp_scripts_get_suffix($type = '') + { + } + /** + * Registers all WordPress scripts. + * + * Localizes some of them. + * args order: `$scripts->add( 'handle', 'url', 'dependencies', 'query-string', 1 );` + * when last arg === 1 queues the script for the footer + * + * @since 2.6.0 + * + * @param WP_Scripts $scripts WP_Scripts object. + */ + function wp_default_scripts($scripts) + { + } + /** + * Assigns default styles to $styles object. + * + * Nothing is returned, because the $styles parameter is passed by reference. + * Meaning that whatever object is passed will be updated without having to + * reassign the variable that was passed back to the same value. This saves + * memory. + * + * Adding default styles is not the only task, it also assigns the base_url + * property, the default version, and text direction for the object. + * + * @since 2.6.0 + * + * @global array $editor_styles + * + * @param WP_Styles $styles + */ + function wp_default_styles($styles) + { + } + /** + * Reorders JavaScript scripts array to place prototype before jQuery. + * + * @since 2.3.1 + * + * @param string[] $js_array JavaScript scripts array + * @return string[] Reordered array, if needed. + */ + function wp_prototype_before_jquery($js_array) + { + } + /** + * Loads localized data on print rather than initialization. + * + * These localizations require information that may not be loaded even by init. + * + * @since 2.5.0 + */ + function wp_just_in_time_script_localization() + { + } + /** + * Localizes the jQuery UI datepicker. + * + * @since 4.6.0 + * + * @link https://api.jqueryui.com/datepicker/#options + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + */ + function wp_localize_jquery_ui_datepicker() + { + } + /** + * Localizes community events data that needs to be passed to dashboard.js. + * + * @since 4.8.0 + */ + function wp_localize_community_events() + { + } + /** + * Administration Screen CSS for changing the styles. + * + * If installing the 'wp-admin/' directory will be replaced with './'. + * + * The $_wp_admin_css_colors global manages the Administration Screens CSS + * stylesheet that is loaded. The option that is set is 'admin_color' and is the + * color and key for the array. The value for the color key is an object with + * a 'url' parameter that has the URL path to the CSS file. + * + * The query from $src parameter will be appended to the URL that is given from + * the $_wp_admin_css_colors array value URL. + * + * @since 2.6.0 + * + * @global array $_wp_admin_css_colors + * + * @param string $src Source URL. + * @param string $handle Either 'colors' or 'colors-rtl'. + * @return string|false URL path to CSS stylesheet for Administration Screens. + */ + function wp_style_loader_src($src, $handle) + { + } + /** + * Prints the script queue in the HTML head on admin pages. + * + * Postpones the scripts that were queued for the footer. + * print_footer_scripts() is called in the footer to print these scripts. + * + * @since 2.8.0 + * + * @see wp_print_scripts() + * + * @global bool $concatenate_scripts + * + * @return array + */ + function print_head_scripts() + { + } + /** + * Prints the scripts that were queued for the footer or too late for the HTML head. + * + * @since 2.8.0 + * + * @global WP_Scripts $wp_scripts + * @global bool $concatenate_scripts + * + * @return array + */ + function print_footer_scripts() + { + } + /** + * Prints scripts (internal use only) + * + * @ignore + * + * @global WP_Scripts $wp_scripts + * @global bool $compress_scripts + */ + function _print_scripts() + { + } + /** + * Prints the script queue in the HTML head on the front end. + * + * Postpones the scripts that were queued for the footer. + * wp_print_footer_scripts() is called in the footer to print these scripts. + * + * @since 2.8.0 + * + * @global WP_Scripts $wp_scripts + * + * @return array + */ + function wp_print_head_scripts() + { + } + /** + * Private, for use in *_footer_scripts hooks + * + * @since 3.3.0 + */ + function _wp_footer_scripts() + { + } + /** + * Hooks to print the scripts and styles in the footer. + * + * @since 2.8.0 + */ + function wp_print_footer_scripts() + { + } + /** + * Wrapper for do_action( 'wp_enqueue_scripts' ). + * + * Allows plugins to queue scripts for the front end using wp_enqueue_script(). + * Runs first in wp_head() where all is_home(), is_page(), etc. functions are available. + * + * @since 2.8.0 + */ + function wp_enqueue_scripts() + { + } + /** + * Prints the styles queue in the HTML head on admin pages. + * + * @since 2.8.0 + * + * @global bool $concatenate_scripts + * + * @return array + */ + function print_admin_styles() + { + } + /** + * Prints the styles that were queued too late for the HTML head. + * + * @since 3.3.0 + * + * @global WP_Styles $wp_styles + * @global bool $concatenate_scripts + * + * @return array|void + */ + function print_late_styles() + { + } + /** + * Prints styles (internal use only). + * + * @ignore + * @since 3.3.0 + * + * @global bool $compress_css + */ + function _print_styles() + { + } + /** + * Determines the concatenation and compression settings for scripts and styles. + * + * @since 2.8.0 + * + * @global bool $concatenate_scripts + * @global bool $compress_scripts + * @global bool $compress_css + */ + function script_concat_settings() + { + } + /** + * Handles the enqueueing of block scripts and styles that are common to both + * the editor and the front-end. + * + * @since 5.0.0 + */ + function wp_common_block_scripts_and_styles() + { + } + /** + * Applies a filter to the list of style nodes that comes from WP_Theme_JSON::get_style_nodes(). + * + * This particular filter removes all of the blocks from the array. + * + * We want WP_Theme_JSON to be ignorant of the implementation details of how the CSS is being used. + * This filter allows us to modify the output of WP_Theme_JSON depending on whether or not we are + * loading separate assets, without making the class aware of that detail. + * + * @since 6.1.0 + * + * @param array $nodes The nodes to filter. + * @return array A filtered array of style nodes. + */ + function wp_filter_out_block_nodes($nodes) + { + } + /** + * Enqueues the global styles defined via theme.json. + * + * @since 5.8.0 + */ + function wp_enqueue_global_styles() + { + } + /** + * Renders the SVG filters supplied by theme.json. + * + * Note that this doesn't render the per-block user-defined + * filters which are handled by wp_render_duotone_support, + * but it should be rendered before the filtered content + * in the body to satisfy Safari's rendering quirks. + * + * @since 5.9.1 + */ + function wp_global_styles_render_svg_filters() + { + } + /** + * Checks if the editor scripts and styles for all registered block types + * should be enqueued on the current screen. + * + * @since 5.6.0 + * + * @global WP_Screen $current_screen WordPress current screen object. + * + * @return bool Whether scripts and styles should be enqueued. + */ + function wp_should_load_block_editor_scripts_and_styles() + { + } + /** + * Checks whether separate styles should be loaded for core blocks on-render. + * + * When this function returns true, other functions ensure that core blocks + * only load their assets on-render, and each block loads its own, individual + * assets. Third-party blocks only load their assets when rendered. + * + * When this function returns false, all core block assets are loaded regardless + * of whether they are rendered in a page or not, because they are all part of + * the `block-library/style.css` file. Assets for third-party blocks are always + * enqueued regardless of whether they are rendered or not. + * + * This only affects front end and not the block editor screens. + * + * @see wp_enqueue_registered_block_scripts_and_styles() + * @see register_block_style_handle() + * + * @since 5.8.0 + * + * @return bool Whether separate assets will be loaded. + */ + function wp_should_load_separate_core_block_assets() + { + } + /** + * Enqueues registered block scripts and styles, depending on current rendered + * context (only enqueuing editor scripts while in context of the editor). + * + * @since 5.0.0 + * + * @global WP_Screen $current_screen WordPress current screen object. + */ + function wp_enqueue_registered_block_scripts_and_styles() + { + } + /** + * Function responsible for enqueuing the styles required for block styles functionality on the editor and on the frontend. + * + * @since 5.3.0 + * + * @global WP_Styles $wp_styles + */ + function enqueue_block_styles_assets() + { + } + /** + * Function responsible for enqueuing the assets required for block styles functionality on the editor. + * + * @since 5.3.0 + */ + function enqueue_editor_block_styles_assets() + { + } + /** + * Enqueues the assets required for the block directory within the block editor. + * + * @since 5.5.0 + */ + function wp_enqueue_editor_block_directory_assets() + { + } + /** + * Enqueues the assets required for the format library within the block editor. + * + * @since 5.8.0 + */ + function wp_enqueue_editor_format_library_assets() + { + } + /** + * Sanitizes an attributes array into an attributes string to be placed inside a `<script>` tag. + * + * Automatically injects type attribute if needed. + * Used by {@see wp_get_script_tag()} and {@see wp_get_inline_script_tag()}. + * + * @since 5.7.0 + * + * @param array $attributes Key-value pairs representing `<script>` tag attributes. + * @return string String made of sanitized `<script>` tag attributes. + */ + function wp_sanitize_script_attributes($attributes) + { + } + /** + * Formats `<script>` loader tags. + * + * It is possible to inject attributes in the `<script>` tag via the {@see 'wp_script_attributes'} filter. + * Automatically injects type attribute if needed. + * + * @since 5.7.0 + * + * @param array $attributes Key-value pairs representing `<script>` tag attributes. + * @return string String containing `<script>` opening and closing tags. + */ + function wp_get_script_tag($attributes) + { + } + /** + * Prints formatted `<script>` loader tag. + * + * It is possible to inject attributes in the `<script>` tag via the {@see 'wp_script_attributes'} filter. + * Automatically injects type attribute if needed. + * + * @since 5.7.0 + * + * @param array $attributes Key-value pairs representing `<script>` tag attributes. + */ + function wp_print_script_tag($attributes) + { + } + /** + * Wraps inline JavaScript in `<script>` tag. + * + * It is possible to inject attributes in the `<script>` tag via the {@see 'wp_script_attributes'} filter. + * Automatically injects type attribute if needed. + * + * @since 5.7.0 + * + * @param string $javascript Inline JavaScript code. + * @param array $attributes Optional. Key-value pairs representing `<script>` tag attributes. + * @return string String containing inline JavaScript code wrapped around `<script>` tag. + */ + function wp_get_inline_script_tag($javascript, $attributes = array()) + { + } + /** + * Prints inline JavaScript wrapped in `<script>` tag. + * + * It is possible to inject attributes in the `<script>` tag via the {@see 'wp_script_attributes'} filter. + * Automatically injects type attribute if needed. + * + * @since 5.7.0 + * + * @param string $javascript Inline JavaScript code. + * @param array $attributes Optional. Key-value pairs representing `<script>` tag attributes. + */ + function wp_print_inline_script_tag($javascript, $attributes = array()) + { + } + /** + * Allows small styles to be inlined. + * + * This improves performance and sustainability, and is opt-in. Stylesheets can opt in + * by adding `path` data using `wp_style_add_data`, and defining the file's absolute path: + * + * wp_style_add_data( $style_handle, 'path', $file_path ); + * + * @since 5.8.0 + * + * @global WP_Styles $wp_styles + */ + function wp_maybe_inline_styles() + { + } + /** + * Makes URLs relative to the WordPress installation. + * + * @since 5.9.0 + * @access private + * + * @param string $css The CSS to make URLs relative to the WordPress installation. + * @param string $stylesheet_url The URL to the stylesheet. + * + * @return string The CSS with URLs made relative to the WordPress installation. + */ + function _wp_normalize_relative_css_links($css, $stylesheet_url) + { + } + /** + * Function that enqueues the CSS Custom Properties coming from theme.json. + * + * @since 5.9.0 + */ + function wp_enqueue_global_styles_css_custom_properties() + { + } + /** + * Hooks inline styles in the proper place, depending on the active theme. + * + * @since 5.9.1 + * @since 6.1.0 Added the `$priority` parameter. + * + * For block themes, styles are loaded in the head. + * For classic ones, styles are loaded in the body because the wp_head action happens before render_block. + * + * @link https://core.trac.wordpress.org/ticket/53494. + * + * @param string $style String containing the CSS styles to be added. + * @param int $priority To set the priority for the add_action. + */ + function wp_enqueue_block_support_styles($style, $priority = 10) + { + } + /** + * Fetches, processes and compiles stored core styles, then combines and renders them to the page. + * Styles are stored via the style engine API. + * + * @link https://developer.wordpress.org/block-editor/reference-guides/packages/packages-style-engine/ + * + * @since 6.1.0 + * + * @param array $options { + * Optional. An array of options to pass to wp_style_engine_get_stylesheet_from_context(). Default empty array. + * + * @type bool $optimize Whether to optimize the CSS output, e.g., combine rules. Default is `false`. + * @type bool $prettify Whether to add new lines and indents to output. Default is the test of whether the global constant `SCRIPT_DEBUG` is defined. + * } + * + * @return void + * @phpstan-param array{ + * optimize?: bool, + * prettify?: bool, + * } $options + */ + function wp_enqueue_stored_styles($options = array()) + { + } + /** + * Enqueues a stylesheet for a specific block. + * + * If the theme has opted-in to separate-styles loading, + * then the stylesheet will be enqueued on-render, + * otherwise when the block inits. + * + * @since 5.9.0 + * + * @param string $block_name The block-name, including namespace. + * @param array $args An array of arguments [handle,src,deps,ver,media]. + */ + function wp_enqueue_block_style($block_name, $args) + { + } + /** + * Runs the theme.json webfonts handler. + * + * Using `WP_Theme_JSON_Resolver`, it gets the fonts defined + * in the `theme.json` for the current selection and style + * variations, validates the font-face properties, generates + * the '@font-face' style declarations, and then enqueues the + * styles for both the editor and front-end. + * + * Design Notes: + * This is not a public API, but rather an internal handler. + * A future public Webfonts API will replace this stopgap code. + * + * This code design is intentional. + * a. It hides the inner-workings. + * b. It does not expose API ins or outs for consumption. + * c. It only works with a theme's `theme.json`. + * + * Why? + * a. To avoid backwards-compatibility issues when + * the Webfonts API is introduced in Core. + * b. To make `fontFace` declarations in `theme.json` work. + * + * @link https://github.com/WordPress/gutenberg/issues/40472 + * + * @since 6.0.0 + * @access private + */ + function _wp_theme_json_webfonts_handler() + { + } + /** + * Loads classic theme styles on classic themes in the frontend. + * + * This is needed for backwards compatibility for button blocks specifically. + * + * @since 6.1.0 + */ + function wp_enqueue_classic_theme_styles() + { + } + /** + * Loads classic theme styles on classic themes in the editor. + * + * This is needed for backwards compatibility for button blocks specifically. + * + * @since 6.1.0 + * + * @param array $editor_settings The array of editor settings. + * @return array A filtered array of editor settings. + */ + function wp_add_editor_classic_theme_styles($editor_settings) + { + } + /** + * Adds a new shortcode. + * + * Care should be taken through prefixing or other means to ensure that the + * shortcode tag being added is unique and will not conflict with other, + * already-added shortcode tags. In the event of a duplicated tag, the tag + * loaded last will take precedence. + * + * @since 2.5.0 + * + * @global array $shortcode_tags + * + * @param string $tag Shortcode tag to be searched in post content. + * @param callable $callback The callback function to run when the shortcode is found. + * Every shortcode callback is passed three parameters by default, + * including an array of attributes (`$atts`), the shortcode content + * or null if not set (`$content`), and finally the shortcode tag + * itself (`$shortcode_tag`), in that order. + */ + function add_shortcode($tag, $callback) + { + } + /** + * Removes hook for shortcode. + * + * @since 2.5.0 + * + * @global array $shortcode_tags + * + * @param string $tag Shortcode tag to remove hook for. + */ + function remove_shortcode($tag) + { + } + /** + * Clears all shortcodes. + * + * This function clears all of the shortcode tags by replacing the shortcodes global with + * an empty array. This is actually an efficient method for removing all shortcodes. + * + * @since 2.5.0 + * + * @global array $shortcode_tags + */ + function remove_all_shortcodes() + { + } + /** + * Determines whether a registered shortcode exists named $tag. + * + * @since 3.6.0 + * + * @global array $shortcode_tags List of shortcode tags and their callback hooks. + * + * @param string $tag Shortcode tag to check. + * @return bool Whether the given shortcode exists. + */ + function shortcode_exists($tag) + { + } + /** + * Determines whether the passed content contains the specified shortcode. + * + * @since 3.6.0 + * + * @global array $shortcode_tags + * + * @param string $content Content to search for shortcodes. + * @param string $tag Shortcode tag to check. + * @return bool Whether the passed content contains the given shortcode. + */ + function has_shortcode($content, $tag) + { + } + /** + * Searches content for shortcodes and filter shortcodes through their hooks. + * + * This function is an alias for do_shortcode(). + * + * @since 5.4.0 + * + * @see do_shortcode() + * + * @param string $content Content to search for shortcodes. + * @param bool $ignore_html When true, shortcodes inside HTML elements will be skipped. + * Default false. + * @return string Content with shortcodes filtered out. + */ + function apply_shortcodes($content, $ignore_html = \false) + { + } + /** + * Searches content for shortcodes and filter shortcodes through their hooks. + * + * If there are no shortcode tags defined, then the content will be returned + * without any filtering. This might cause issues when plugins are disabled but + * the shortcode will still show up in the post or content. + * + * @since 2.5.0 + * + * @global array $shortcode_tags List of shortcode tags and their callback hooks. + * + * @param string $content Content to search for shortcodes. + * @param bool $ignore_html When true, shortcodes inside HTML elements will be skipped. + * Default false. + * @return string Content with shortcodes filtered out. + */ + function do_shortcode($content, $ignore_html = \false) + { + } + /** + * Retrieves the shortcode regular expression for searching. + * + * The regular expression combines the shortcode tags in the regular expression + * in a regex class. + * + * The regular expression contains 6 different sub matches to help with parsing. + * + * 1 - An extra [ to allow for escaping shortcodes with double [[]] + * 2 - The shortcode name + * 3 - The shortcode argument list + * 4 - The self closing / + * 5 - The content of a shortcode when it wraps some content. + * 6 - An extra ] to allow for escaping shortcodes with double [[]] + * + * @since 2.5.0 + * @since 4.4.0 Added the `$tagnames` parameter. + * + * @global array $shortcode_tags + * + * @param array $tagnames Optional. List of shortcodes to find. Defaults to all registered shortcodes. + * @return string The shortcode search regular expression + */ + function get_shortcode_regex($tagnames = \null) + { + } + /** + * Regular Expression callable for do_shortcode() for calling shortcode hook. + * + * @see get_shortcode_regex() for details of the match array contents. + * + * @since 2.5.0 + * @access private + * + * @global array $shortcode_tags + * + * @param array $m Regular expression match array. + * @return string|false Shortcode output on success, false on failure. + */ + function do_shortcode_tag($m) + { + } + /** + * Searches only inside HTML elements for shortcodes and process them. + * + * Any [ or ] characters remaining inside elements will be HTML encoded + * to prevent interference with shortcodes that are outside the elements. + * Assumes $content processed by KSES already. Users with unfiltered_html + * capability may get unexpected output if angle braces are nested in tags. + * + * @since 4.2.3 + * + * @param string $content Content to search for shortcodes. + * @param bool $ignore_html When true, all square braces inside elements will be encoded. + * @param array $tagnames List of shortcodes to find. + * @return string Content with shortcodes filtered out. + */ + function do_shortcodes_in_html_tags($content, $ignore_html, $tagnames) + { + } + /** + * Removes placeholders added by do_shortcodes_in_html_tags(). + * + * @since 4.2.3 + * + * @param string $content Content to search for placeholders. + * @return string Content with placeholders removed. + */ + function unescape_invalid_shortcodes($content) + { + } + /** + * Retrieves the shortcode attributes regex. + * + * @since 4.4.0 + * + * @return string The shortcode attribute regular expression. + */ + function get_shortcode_atts_regex() + { + } + /** + * Retrieves all attributes from the shortcodes tag. + * + * The attributes list has the attribute name as the key and the value of the + * attribute as the value in the key/value pair. This allows for easier + * retrieval of the attributes, since all attributes have to be known. + * + * @since 2.5.0 + * + * @param string $text + * @return array|string List of attribute values. + * Returns empty array if '""' === trim( $text ). + * Returns empty string if '' === trim( $text ). + * All other matches are checked for not empty(). + */ + function shortcode_parse_atts($text) + { + } + /** + * Combines user attributes with known attributes and fill in defaults when needed. + * + * The pairs should be considered to be all of the attributes which are + * supported by the caller and given as a list. The returned attributes will + * only contain the attributes in the $pairs list. + * + * If the $atts list has unsupported attributes, then they will be ignored and + * removed from the final returned list. + * + * @since 2.5.0 + * + * @param array $pairs Entire list of supported attributes and their defaults. + * @param array $atts User defined attributes in shortcode tag. + * @param string $shortcode Optional. The name of the shortcode, provided for context to enable filtering + * @return array Combined and filtered attribute list. + */ + function shortcode_atts($pairs, $atts, $shortcode = '') + { + } + /** + * Removes all shortcode tags from the given content. + * + * @since 2.5.0 + * + * @global array $shortcode_tags + * + * @param string $content Content to remove shortcode tags. + * @return string Content without shortcode tags. + */ + function strip_shortcodes($content) + { + } + /** + * Strips a shortcode tag based on RegEx matches against post content. + * + * @since 3.3.0 + * + * @param array $m RegEx matches against post content. + * @return string|false The content stripped of the tag, otherwise false. + */ + function strip_shortcode_tag($m) + { + } + /** + * Sitemaps: Public functions + * + * This file contains a variety of public functions developers can use to interact with + * the XML Sitemaps API. + * + * @package WordPress + * @subpackage Sitemaps + * @since 5.5.0 + */ + /** + * Retrieves the current Sitemaps server instance. + * + * @since 5.5.0 + * + * @global WP_Sitemaps $wp_sitemaps Global Core Sitemaps instance. + * + * @return WP_Sitemaps Sitemaps instance. + */ + function wp_sitemaps_get_server() + { + } + /** + * Gets an array of sitemap providers. + * + * @since 5.5.0 + * + * @return WP_Sitemaps_Provider[] Array of sitemap providers. + */ + function wp_get_sitemap_providers() + { + } + /** + * Registers a new sitemap provider. + * + * @since 5.5.0 + * + * @param string $name Unique name for the sitemap provider. + * @param WP_Sitemaps_Provider $provider The `Sitemaps_Provider` instance implementing the sitemap. + * @return bool Whether the sitemap was added. + */ + function wp_register_sitemap_provider($name, \WP_Sitemaps_Provider $provider) + { + } + /** + * Gets the maximum number of URLs for a sitemap. + * + * @since 5.5.0 + * + * @param string $object_type Object type for sitemap to be filtered (e.g. 'post', 'term', 'user'). + * @return int The maximum number of URLs. + */ + function wp_sitemaps_get_max_urls($object_type) + { + } + /** + * Retrieves the full URL for a sitemap. + * + * @since 5.5.1 + * + * @param string $name The sitemap name. + * @param string $subtype_name The sitemap subtype name. Default empty string. + * @param int $page The page of the sitemap. Default 1. + * @return string|false The sitemap URL or false if the sitemap doesn't exist. + */ + function get_sitemap_url($name, $subtype_name = '', $page = 1) + { + } + /** + * Style engine: Public functions + * + * This file contains a variety of public functions developers can use to interact with + * the Style Engine API. + * + * @package WordPress + * @subpackage StyleEngine + * @since 6.1.0 + */ + /** + * Global public interface method to generate styles from a single style object, e.g., + * the value of a block's attributes.style object or the top level styles in theme.json. + * See: https://developer.wordpress.org/block-editor/reference-guides/theme-json-reference/theme-json-living/#styles and + * https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/ + * + * Example usage: + * + * $styles = wp_style_engine_get_styles( array( 'color' => array( 'text' => '#cccccc' ) ) ); + * // Returns `array( 'css' => 'color: #cccccc', 'declarations' => array( 'color' => '#cccccc' ), 'classnames' => 'has-color' )`. + * + * @access public + * @since 6.1.0 + * + * @param array $block_styles The style object. + * @param array $options { + * Optional. An array of options. Default empty array. + * + * @type string|null $context An identifier describing the origin of the style object, e.g., 'block-supports' or 'global-styles'. Default is `null`. + * When set, the style engine will attempt to store the CSS rules, where a selector is also passed. + * @type bool $convert_vars_to_classnames Whether to skip converting incoming CSS var patterns, e.g., `var:preset|<PRESET_TYPE>|<PRESET_SLUG>`, to var( --wp--preset--* ) values. Default `false`. + * @type string $selector Optional. When a selector is passed, the value of `$css` in the return value will comprise a full CSS rule `$selector { ...$css_declarations }`, + * otherwise, the value will be a concatenated string of CSS declarations. + * } + * + * @return array { + * @type string $css A CSS ruleset or declarations block formatted to be placed in an HTML `style` attribute or tag. + * @type string[] $declarations An associative array of CSS definitions, e.g., array( "$property" => "$value", "$property" => "$value" ). + * @type string $classnames Classnames separated by a space. + * } + * @phpstan-param array{ + * context?: string|null, + * convert_vars_to_classnames?: bool, + * selector?: string, + * } $options + * @phpstan-return array{ + * css: string, + * declarations: string[], + * classnames: string, + * } + */ + function wp_style_engine_get_styles($block_styles, $options = array()) + { + } + /** + * Returns compiled CSS from a collection of selectors and declarations. + * Useful for returning a compiled stylesheet from any collection of CSS selector + declarations. + * + * Example usage: + * $css_rules = array( array( 'selector' => '.elephant-are-cool', 'declarations' => array( 'color' => 'gray', 'width' => '3em' ) ) ); + * $css = wp_style_engine_get_stylesheet_from_css_rules( $css_rules ); + * // Returns `.elephant-are-cool{color:gray;width:3em}`. + * + * @since 6.1.0 + * + * @param array $css_rules { + * Required. A collection of CSS rules. + * + * @type array ...$0 { + * @type string $selector A CSS selector. + * @type string[] $declarations An associative array of CSS definitions, e.g., array( "$property" => "$value", "$property" => "$value" ). + * } + * } + * @param array $options { + * Optional. An array of options. Default empty array. + * + * @type string|null $context An identifier describing the origin of the style object, e.g., 'block-supports' or 'global-styles'. Default is 'block-supports'. + * When set, the style engine will attempt to store the CSS rules. + * @type bool $optimize Whether to optimize the CSS output, e.g., combine rules. Default is `false`. + * @type bool $prettify Whether to add new lines and indents to output. Default is the test of whether the global constant `SCRIPT_DEBUG` is defined. + * } + * + * @return string A string of compiled CSS declarations, or empty string. + * @phpstan-param array<int|string, array{ + * selector: string, + * declarations: string[], + * }> $css_rules + * @phpstan-param array{ + * context?: string|null, + * optimize?: bool, + * prettify?: bool, + * } $options + */ + function wp_style_engine_get_stylesheet_from_css_rules($css_rules, $options = array()) + { + } + /** + * Returns compiled CSS from a store, if found. + * + * @since 6.1.0 + * + * @param string $context A valid context name, corresponding to an existing store key. + * @param array $options { + * Optional. An array of options. Default empty array. + * + * @type bool $optimize Whether to optimize the CSS output, e.g., combine rules. Default is `false`. + * @type bool $prettify Whether to add new lines and indents to output. Default is the test of whether the global constant `SCRIPT_DEBUG` is defined. + * } + * + * @return string A compiled CSS string. + * @phpstan-param array{ + * optimize?: bool, + * prettify?: bool, + * } $options + */ + function wp_style_engine_get_stylesheet_from_context($context, $options = array()) + { + } + /** + * Core Taxonomy API + * + * @package WordPress + * @subpackage Taxonomy + */ + // + // Taxonomy registration. + // + /** + * Creates the initial taxonomies. + * + * This function fires twice: in wp-settings.php before plugins are loaded (for + * backward compatibility reasons), and again on the {@see 'init'} action. We must + * avoid registering rewrite rules before the {@see 'init'} action. + * + * @since 2.8.0 + * @since 5.9.0 Added `'wp_template_part_area'` taxonomy. + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + */ + function create_initial_taxonomies() + { + } + /** + * Retrieves a list of registered taxonomy names or objects. + * + * @since 3.0.0 + * + * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies. + * + * @param array $args Optional. An array of `key => value` arguments to match against the taxonomy objects. + * Default empty array. + * @param string $output Optional. The type of output to return in the array. Accepts either taxonomy 'names' + * or 'objects'. Default 'names'. + * @param string $operator Optional. The logical operation to perform. Accepts 'and' or 'or'. 'or' means only + * one element from the array needs to match; 'and' means all elements must match. + * Default 'and'. + * @return string[]|WP_Taxonomy[] An array of taxonomy names or objects. + */ + function get_taxonomies($args = array(), $output = 'names', $operator = 'and') + { + } + /** + * Returns the names or objects of the taxonomies which are registered for the requested object or object type, + * such as a post object or post type name. + * + * Example: + * + * $taxonomies = get_object_taxonomies( 'post' ); + * + * This results in: + * + * Array( 'category', 'post_tag' ) + * + * @since 2.3.0 + * + * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies. + * + * @param string|string[]|WP_Post $object Name of the type of taxonomy object, or an object (row from posts) + * @param string $output Optional. The type of output to return in the array. Accepts either + * 'names' or 'objects'. Default 'names'. + * @return string[]|WP_Taxonomy[] The names or objects of all taxonomies of `$object_type`. + */ + function get_object_taxonomies($object, $output = 'names') + { + } + /** + * Retrieves the taxonomy object of $taxonomy. + * + * The get_taxonomy function will first check that the parameter string given + * is a taxonomy object and if it is, it will return it. + * + * @since 2.3.0 + * + * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies. + * + * @param string $taxonomy Name of taxonomy object to return. + * @return WP_Taxonomy|false The taxonomy object or false if $taxonomy doesn't exist. + */ + function get_taxonomy($taxonomy) + { + } + /** + * Determines whether the taxonomy name exists. + * + * Formerly is_taxonomy(), introduced in 2.3.0. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 3.0.0 + * + * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies. + * + * @param string $taxonomy Name of taxonomy object. + * @return bool Whether the taxonomy exists. + */ + function taxonomy_exists($taxonomy) + { + } + /** + * Determines whether the taxonomy object is hierarchical. + * + * Checks to make sure that the taxonomy is an object first. Then Gets the + * object, and finally returns the hierarchical value in the object. + * + * A false return value might also mean that the taxonomy does not exist. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.3.0 + * + * @param string $taxonomy Name of taxonomy object. + * @return bool Whether the taxonomy is hierarchical. + */ + function is_taxonomy_hierarchical($taxonomy) + { + } + /** + * Creates or modifies a taxonomy object. + * + * Note: Do not use before the {@see 'init'} hook. + * + * A simple function for creating or modifying a taxonomy object based on + * the parameters given. If modifying an existing taxonomy object, note + * that the `$object_type` value from the original registration will be + * overwritten. + * + * @since 2.3.0 + * @since 4.2.0 Introduced `show_in_quick_edit` argument. + * @since 4.4.0 The `show_ui` argument is now enforced on the term editing screen. + * @since 4.4.0 The `public` argument now controls whether the taxonomy can be queried on the front end. + * @since 4.5.0 Introduced `publicly_queryable` argument. + * @since 4.7.0 Introduced `show_in_rest`, 'rest_base' and 'rest_controller_class' + * arguments to register the taxonomy in REST API. + * @since 5.1.0 Introduced `meta_box_sanitize_cb` argument. + * @since 5.4.0 Added the registered taxonomy object as a return value. + * @since 5.5.0 Introduced `default_term` argument. + * @since 5.9.0 Introduced `rest_namespace` argument. + * + * @global WP_Taxonomy[] $wp_taxonomies Registered taxonomies. + * + * @param string $taxonomy Taxonomy key, must not exceed 32 characters and may only contain lowercase alphanumeric + * characters, dashes, and underscores. See sanitize_key(). + * @param array|string $object_type Object type or array of object types with which the taxonomy should be associated. + * @param array|string $args { + * Optional. Array or query string of arguments for registering a taxonomy. + * + * @type string[] $labels An array of labels for this taxonomy. By default, Tag labels are + * used for non-hierarchical taxonomies, and Category labels are used + * for hierarchical taxonomies. See accepted values in + * get_taxonomy_labels(). Default empty array. + * @type string $description A short descriptive summary of what the taxonomy is for. Default empty. + * @type bool $public Whether a taxonomy is intended for use publicly either via + * the admin interface or by front-end users. The default settings + * of `$publicly_queryable`, `$show_ui`, and `$show_in_nav_menus` + * are inherited from `$public`. + * @type bool $publicly_queryable Whether the taxonomy is publicly queryable. + * If not set, the default is inherited from `$public` + * @type bool $hierarchical Whether the taxonomy is hierarchical. Default false. + * @type bool $show_ui Whether to generate and allow a UI for managing terms in this taxonomy in + * the admin. If not set, the default is inherited from `$public` + * (default true). + * @type bool $show_in_menu Whether to show the taxonomy in the admin menu. If true, the taxonomy is + * shown as a submenu of the object type menu. If false, no menu is shown. + * `$show_ui` must be true. If not set, default is inherited from `$show_ui` + * (default true). + * @type bool $show_in_nav_menus Makes this taxonomy available for selection in navigation menus. If not + * set, the default is inherited from `$public` (default true). + * @type bool $show_in_rest Whether to include the taxonomy in the REST API. Set this to true + * for the taxonomy to be available in the block editor. + * @type string $rest_base To change the base url of REST API route. Default is $taxonomy. + * @type string $rest_namespace To change the namespace URL of REST API route. Default is wp/v2. + * @type string $rest_controller_class REST API Controller class name. Default is 'WP_REST_Terms_Controller'. + * @type bool $show_tagcloud Whether to list the taxonomy in the Tag Cloud Widget controls. If not set, + * the default is inherited from `$show_ui` (default true). + * @type bool $show_in_quick_edit Whether to show the taxonomy in the quick/bulk edit panel. It not set, + * the default is inherited from `$show_ui` (default true). + * @type bool $show_admin_column Whether to display a column for the taxonomy on its post type listing + * screens. Default false. + * @type bool|callable $meta_box_cb Provide a callback function for the meta box display. If not set, + * post_categories_meta_box() is used for hierarchical taxonomies, and + * post_tags_meta_box() is used for non-hierarchical. If false, no meta + * box is shown. + * @type callable $meta_box_sanitize_cb Callback function for sanitizing taxonomy data saved from a meta + * box. If no callback is defined, an appropriate one is determined + * based on the value of `$meta_box_cb`. + * @type string[] $capabilities { + * Array of capabilities for this taxonomy. + * + * @type string $manage_terms Default 'manage_categories'. + * @type string $edit_terms Default 'manage_categories'. + * @type string $delete_terms Default 'manage_categories'. + * @type string $assign_terms Default 'edit_posts'. + * } + * @type bool|array $rewrite { + * Triggers the handling of rewrites for this taxonomy. Default true, using $taxonomy as slug. To prevent + * rewrite, set to false. To specify rewrite rules, an array can be passed with any of these keys: + * + * @type string $slug Customize the permastruct slug. Default `$taxonomy` key. + * @type bool $with_front Should the permastruct be prepended with WP_Rewrite::$front. Default true. + * @type bool $hierarchical Either hierarchical rewrite tag or not. Default false. + * @type int $ep_mask Assign an endpoint mask. Default `EP_NONE`. + * } + * @type string|bool $query_var Sets the query var key for this taxonomy. Default `$taxonomy` key. If + * false, a taxonomy cannot be loaded at `?{query_var}={term_slug}`. If a + * string, the query `?{query_var}={term_slug}` will be valid. + * @type callable $update_count_callback Works much like a hook, in that it will be called when the count is + * updated. Default _update_post_term_count() for taxonomies attached + * to post types, which confirms that the objects are published before + * counting them. Default _update_generic_term_count() for taxonomies + * attached to other object types, such as users. + * @type string|array $default_term { + * Default term to be used for the taxonomy. + * + * @type string $name Name of default term. + * @type string $slug Slug for default term. Default empty. + * @type string $description Description for default term. Default empty. + * } + * @type bool $sort Whether terms in this taxonomy should be sorted in the order they are + * provided to `wp_set_object_terms()`. Default null which equates to false. + * @type array $args Array of arguments to automatically use inside `wp_get_object_terms()` + * for this taxonomy. + * @type bool $_builtin This taxonomy is a "built-in" taxonomy. INTERNAL USE ONLY! + * Default false. + * } + * @return WP_Taxonomy|WP_Error The registered taxonomy object on success, WP_Error object on failure. + * @phpstan-param array{ + * labels?: string[], + * description?: string, + * public?: bool, + * publicly_queryable?: bool, + * hierarchical?: bool, + * show_ui?: bool, + * show_in_menu?: bool, + * show_in_nav_menus?: bool, + * show_in_rest?: bool, + * rest_base?: string, + * rest_namespace?: string, + * rest_controller_class?: string, + * show_tagcloud?: bool, + * show_in_quick_edit?: bool, + * show_admin_column?: bool, + * meta_box_cb?: bool|callable, + * meta_box_sanitize_cb?: callable, + * capabilities?: array{ + * manage_terms?: string, + * edit_terms?: string, + * delete_terms?: string, + * assign_terms?: string, + * }, + * rewrite?: bool|array{ + * slug?: string, + * with_front?: bool, + * hierarchical?: bool, + * ep_mask?: int, + * }, + * query_var?: string|bool, + * update_count_callback?: callable, + * default_term?: string|array{ + * name?: string, + * slug?: string, + * description?: string, + * }, + * sort?: bool, + * args?: array, + * _builtin?: bool, + * } $args + */ + function register_taxonomy($taxonomy, $object_type, $args = array()) + { + } + /** + * Unregisters a taxonomy. + * + * Can not be used to unregister built-in taxonomies. + * + * @since 4.5.0 + * + * @global WP $wp Current WordPress environment instance. + * @global WP_Taxonomy[] $wp_taxonomies List of taxonomies. + * + * @param string $taxonomy Taxonomy name. + * @return true|WP_Error True on success, WP_Error on failure or if the taxonomy doesn't exist. + */ + function unregister_taxonomy($taxonomy) + { + } + /** + * Builds an object with all taxonomy labels out of a taxonomy object. + * + * @since 3.0.0 + * @since 4.3.0 Added the `no_terms` label. + * @since 4.4.0 Added the `items_list_navigation` and `items_list` labels. + * @since 4.9.0 Added the `most_used` and `back_to_items` labels. + * @since 5.7.0 Added the `filter_by_item` label. + * @since 5.8.0 Added the `item_link` and `item_link_description` labels. + * @since 5.9.0 Added the `name_field_description`, `slug_field_description`, + * `parent_field_description`, and `desc_field_description` labels. + * + * @param WP_Taxonomy $tax Taxonomy object. + * @return object { + * Taxonomy labels object. The first default value is for non-hierarchical taxonomies + * (like tags) and the second one is for hierarchical taxonomies (like categories). + * + * @type string $name General name for the taxonomy, usually plural. The same + * as and overridden by `$tax->label`. Default 'Tags'/'Categories'. + * @type string $singular_name Name for one object of this taxonomy. Default 'Tag'/'Category'. + * @type string $search_items Default 'Search Tags'/'Search Categories'. + * @type string $popular_items This label is only used for non-hierarchical taxonomies. + * Default 'Popular Tags'. + * @type string $all_items Default 'All Tags'/'All Categories'. + * @type string $parent_item This label is only used for hierarchical taxonomies. Default + * 'Parent Category'. + * @type string $parent_item_colon The same as `parent_item`, but with colon `:` in the end. + * @type string $name_field_description Description for the Name field on Edit Tags screen. + * Default 'The name is how it appears on your site'. + * @type string $slug_field_description Description for the Slug field on Edit Tags screen. + * Default 'The “slug” is the URL-friendly version + * of the name. It is usually all lowercase and contains + * only letters, numbers, and hyphens'. + * @type string $parent_field_description Description for the Parent field on Edit Tags screen. + * Default 'Assign a parent term to create a hierarchy. + * The term Jazz, for example, would be the parent + * of Bebop and Big Band'. + * @type string $desc_field_description Description for the Description field on Edit Tags screen. + * Default 'The description is not prominent by default; + * however, some themes may show it'. + * @type string $edit_item Default 'Edit Tag'/'Edit Category'. + * @type string $view_item Default 'View Tag'/'View Category'. + * @type string $update_item Default 'Update Tag'/'Update Category'. + * @type string $add_new_item Default 'Add New Tag'/'Add New Category'. + * @type string $new_item_name Default 'New Tag Name'/'New Category Name'. + * @type string $separate_items_with_commas This label is only used for non-hierarchical taxonomies. Default + * 'Separate tags with commas', used in the meta box. + * @type string $add_or_remove_items This label is only used for non-hierarchical taxonomies. Default + * 'Add or remove tags', used in the meta box when JavaScript + * is disabled. + * @type string $choose_from_most_used This label is only used on non-hierarchical taxonomies. Default + * 'Choose from the most used tags', used in the meta box. + * @type string $not_found Default 'No tags found'/'No categories found', used in + * the meta box and taxonomy list table. + * @type string $no_terms Default 'No tags'/'No categories', used in the posts and media + * list tables. + * @type string $filter_by_item This label is only used for hierarchical taxonomies. Default + * 'Filter by category', used in the posts list table. + * @type string $items_list_navigation Label for the table pagination hidden heading. + * @type string $items_list Label for the table hidden heading. + * @type string $most_used Title for the Most Used tab. Default 'Most Used'. + * @type string $back_to_items Label displayed after a term has been updated. + * @type string $item_link Used in the block editor. Title for a navigation link block variation. + * Default 'Tag Link'/'Category Link'. + * @type string $item_link_description Used in the block editor. Description for a navigation link block + * variation. Default 'A link to a tag'/'A link to a category'. + * } + */ + function get_taxonomy_labels($tax) + { + } + /** + * Adds an already registered taxonomy to an object type. + * + * @since 3.0.0 + * + * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies. + * + * @param string $taxonomy Name of taxonomy object. + * @param string $object_type Name of the object type. + * @return bool True if successful, false if not. + */ + function register_taxonomy_for_object_type($taxonomy, $object_type) + { + } + /** + * Removes an already registered taxonomy from an object type. + * + * @since 3.7.0 + * + * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies. + * + * @param string $taxonomy Name of taxonomy object. + * @param string $object_type Name of the object type. + * @return bool True if successful, false if not. + */ + function unregister_taxonomy_for_object_type($taxonomy, $object_type) + { + } + // + // Term API. + // + /** + * Retrieves object IDs of valid taxonomy and term. + * + * The strings of `$taxonomies` must exist before this function will continue. + * On failure of finding a valid taxonomy, it will return a WP_Error. + * + * The `$terms` aren't checked the same as `$taxonomies`, but still need to exist + * for object IDs to be returned. + * + * It is possible to change the order that object IDs are returned by using `$args` + * with either ASC or DESC array. The value should be in the key named 'order'. + * + * @since 2.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|int[] $term_ids Term ID or array of term IDs of terms that will be used. + * @param string|string[] $taxonomies String of taxonomy name or Array of string values of taxonomy names. + * @param array|string $args Change the order of the object IDs, either ASC or DESC. + * @return string[]|WP_Error An array of object IDs as numeric strings on success, + * WP_Error if the taxonomy does not exist. + */ + function get_objects_in_term($term_ids, $taxonomies, $args = array()) + { + } + /** + * Given a taxonomy query, generates SQL to be appended to a main query. + * + * @since 3.1.0 + * + * @see WP_Tax_Query + * + * @param array $tax_query A compact tax query + * @param string $primary_table + * @param string $primary_id_column + * @return string[] + */ + function get_tax_sql($tax_query, $primary_table, $primary_id_column) + { + } + /** + * Gets all term data from database by term ID. + * + * The usage of the get_term function is to apply filters to a term object. It + * is possible to get a term object from the database before applying the + * filters. + * + * $term ID must be part of $taxonomy, to get from the database. Failure, might + * be able to be captured by the hooks. Failure would be the same value as $wpdb + * returns for the get_row method. + * + * There are two hooks, one is specifically for each term, named 'get_term', and + * the second is for the taxonomy name, 'term_$taxonomy'. Both hooks gets the + * term object, and the taxonomy name as parameters. Both hooks are expected to + * return a term object. + * + * {@see 'get_term'} hook - Takes two parameters the term Object and the taxonomy name. + * Must return term object. Used in get_term() as a catch-all filter for every + * $term. + * + * {@see 'get_$taxonomy'} hook - Takes two parameters the term Object and the taxonomy + * name. Must return term object. $taxonomy will be the taxonomy name, so for + * example, if 'category', it would be 'get_category' as the filter name. Useful + * for custom taxonomies or plugging into default taxonomies. + * + * @todo Better formatting for DocBlock + * + * @since 2.3.0 + * @since 4.4.0 Converted to return a WP_Term object if `$output` is `OBJECT`. + * The `$taxonomy` parameter was made optional. + * + * @see sanitize_term_field() The $context param lists the available values for get_term_by() $filter param. + * + * @param int|WP_Term|object $term If integer, term data will be fetched from the database, + * or from the cache if available. + * If stdClass object (as in the results of a database query), + * will apply filters and return a `WP_Term` object with the `$term` data. + * If `WP_Term`, will return `$term`. + * @param string $taxonomy Optional. Taxonomy name that `$term` is part of. + * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which + * correspond to a WP_Term object, an associative array, or a numeric array, + * respectively. Default OBJECT. + * @param string $filter Optional. How to sanitize term fields. Default 'raw'. + * @return WP_Term|array|WP_Error|null WP_Term instance (or array) on success, depending on the `$output` value. + * WP_Error if `$taxonomy` does not exist. Null for miscellaneous failure. + */ + function get_term($term, $taxonomy = '', $output = \OBJECT, $filter = 'raw') + { + } + /** + * Gets all term data from database by term field and data. + * + * Warning: $value is not escaped for 'name' $field. You must do it yourself, if + * required. + * + * The default $field is 'id', therefore it is possible to also use null for + * field, but not recommended that you do so. + * + * If $value does not exist, the return value will be false. If $taxonomy exists + * and $field and $value combinations exist, the term will be returned. + * + * This function will always return the first term that matches the `$field`- + * `$value`-`$taxonomy` combination specified in the parameters. If your query + * is likely to match more than one term (as is likely to be the case when + * `$field` is 'name', for example), consider using get_terms() instead; that + * way, you will get all matching terms, and can provide your own logic for + * deciding which one was intended. + * + * @todo Better formatting for DocBlock. + * + * @since 2.3.0 + * @since 4.4.0 `$taxonomy` is optional if `$field` is 'term_taxonomy_id'. Converted to return + * a WP_Term object if `$output` is `OBJECT`. + * @since 5.5.0 Added 'ID' as an alias of 'id' for the `$field` parameter. + * + * @see sanitize_term_field() The $context param lists the available values for get_term_by() $filter param. + * + * @param string $field Either 'slug', 'name', 'term_id' (or 'id', 'ID'), or 'term_taxonomy_id'. + * @param string|int $value Search for this term value. + * @param string $taxonomy Taxonomy name. Optional, if `$field` is 'term_taxonomy_id'. + * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which + * correspond to a WP_Term object, an associative array, or a numeric array, + * respectively. Default OBJECT. + * @param string $filter Optional. How to sanitize term fields. Default 'raw'. + * @return WP_Term|array|false WP_Term instance (or array) on success, depending on the `$output` value. + * False if `$taxonomy` does not exist or `$term` was not found. + */ + function get_term_by($field, $value, $taxonomy = '', $output = \OBJECT, $filter = 'raw') + { + } + /** + * Merges all term children into a single array of their IDs. + * + * This recursive function will merge all of the children of $term into the same + * array of term IDs. Only useful for taxonomies which are hierarchical. + * + * Will return an empty array if $term does not exist in $taxonomy. + * + * @since 2.3.0 + * + * @param int $term_id ID of term to get children. + * @param string $taxonomy Taxonomy name. + * @return array|WP_Error List of term IDs. WP_Error returned if `$taxonomy` does not exist. + */ + function get_term_children($term_id, $taxonomy) + { + } + /** + * Gets sanitized term field. + * + * The function is for contextual reasons and for simplicity of usage. + * + * @since 2.3.0 + * @since 4.4.0 The `$taxonomy` parameter was made optional. `$term` can also now accept a WP_Term object. + * + * @see sanitize_term_field() + * + * @param string $field Term field to fetch. + * @param int|WP_Term $term Term ID or object. + * @param string $taxonomy Optional. Taxonomy name. Default empty. + * @param string $context Optional. How to sanitize term fields. Look at sanitize_term_field() for available options. + * Default 'display'. + * @return string|int|null|WP_Error Will return an empty string if $term is not an object or if $field is not set in $term. + */ + function get_term_field($field, $term, $taxonomy = '', $context = 'display') + { + } + /** + * Sanitizes term for editing. + * + * Return value is sanitize_term() and usage is for sanitizing the term for + * editing. Function is for contextual and simplicity. + * + * @since 2.3.0 + * + * @param int|object $id Term ID or object. + * @param string $taxonomy Taxonomy name. + * @return string|int|null|WP_Error Will return empty string if $term is not an object. + */ + function get_term_to_edit($id, $taxonomy) + { + } + /** + * Retrieves the terms in a given taxonomy or list of taxonomies. + * + * You can fully inject any customizations to the query before it is sent, as + * well as control the output with a filter. + * + * The return type varies depending on the value passed to `$args['fields']`. See + * WP_Term_Query::get_terms() for details. In all cases, a `WP_Error` object will + * be returned if an invalid taxonomy is requested. + * + * The {@see 'get_terms'} filter will be called when the cache has the term and will + * pass the found term along with the array of $taxonomies and array of $args. + * This filter is also called before the array of terms is passed and will pass + * the array of terms, along with the $taxonomies and $args. + * + * The {@see 'list_terms_exclusions'} filter passes the compiled exclusions along with + * the $args. + * + * The {@see 'get_terms_orderby'} filter passes the `ORDER BY` clause for the query + * along with the $args array. + * + * Prior to 4.5.0, the first parameter of `get_terms()` was a taxonomy or list of taxonomies: + * + * $terms = get_terms( 'post_tag', array( + * 'hide_empty' => false, + * ) ); + * + * Since 4.5.0, taxonomies should be passed via the 'taxonomy' argument in the `$args` array: + * + * $terms = get_terms( array( + * 'taxonomy' => 'post_tag', + * 'hide_empty' => false, + * ) ); + * + * @since 2.3.0 + * @since 4.2.0 Introduced 'name' and 'childless' parameters. + * @since 4.4.0 Introduced the ability to pass 'term_id' as an alias of 'id' for the `orderby` parameter. + * Introduced the 'meta_query' and 'update_term_meta_cache' parameters. Converted to return + * a list of WP_Term objects. + * @since 4.5.0 Changed the function signature so that the `$args` array can be provided as the first parameter. + * Introduced 'meta_key' and 'meta_value' parameters. Introduced the ability to order results by metadata. + * @since 4.8.0 Introduced 'suppress_filter' parameter. + * + * @internal The `$deprecated` parameter is parsed for backward compatibility only. + * + * @param array|string $args Optional. Array or string of arguments. See WP_Term_Query::__construct() + * for information on accepted arguments. Default empty array. + * @param array|string $deprecated Optional. Argument array, when using the legacy function parameter format. + * If present, this parameter will be interpreted as `$args`, and the first + * function parameter will be parsed as a taxonomy or array of taxonomies. + * Default empty. + * @return WP_Term[]|int[]|string[]|string|WP_Error Array of terms, a count thereof as a numeric string, + * or WP_Error if any of the taxonomies do not exist. + * See the function description for more information. + * @phpstan-param array{ + * taxonomy?: string|string[], + * object_ids?: int|int[], + * orderby?: string, + * order?: string, + * hide_empty?: bool|int, + * include?: int[]|string, + * exclude?: int[]|string, + * exclude_tree?: int[]|string, + * number?: int|string, + * offset?: int, + * fields?: string, + * count?: bool, + * name?: string|string[], + * slug?: string|string[], + * term_taxonomy_id?: int|int[], + * hierarchical?: bool, + * search?: string, + * name__like?: string, + * description__like?: string, + * pad_counts?: bool, + * get?: string, + * child_of?: int, + * parent?: int, + * childless?: bool, + * cache_domain?: string, + * update_term_meta_cache?: bool, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * } $args See WP_Term_Query::__construct() + */ + function get_terms($args = array(), $deprecated = '') + { + } + /** + * Adds metadata to a term. + * + * @since 4.4.0 + * + * @param int $term_id Term ID. + * @param string $meta_key Metadata name. + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. + * @param bool $unique Optional. Whether the same key should not be added. + * Default false. + * @return int|false|WP_Error Meta ID on success, false on failure. + * WP_Error when term_id is ambiguous between taxonomies. + */ + function add_term_meta($term_id, $meta_key, $meta_value, $unique = \false) + { + } + /** + * Removes metadata matching criteria from a term. + * + * @since 4.4.0 + * + * @param int $term_id Term ID. + * @param string $meta_key Metadata name. + * @param mixed $meta_value Optional. Metadata value. If provided, + * rows will only be removed that match the value. + * Must be serializable if non-scalar. Default empty. + * @return bool True on success, false on failure. + */ + function delete_term_meta($term_id, $meta_key, $meta_value = '') + { + } + /** + * Retrieves metadata for a term. + * + * @since 4.4.0 + * + * @param int $term_id Term ID. + * @param string $key Optional. The meta key to retrieve. By default, + * returns data for all keys. Default empty. + * @param bool $single Optional. Whether to return a single value. + * This parameter has no effect if `$key` is not specified. + * Default false. + * @return mixed An array of values if `$single` is false. + * The value of the meta field if `$single` is true. + * False for an invalid `$term_id` (non-numeric, zero, or negative value). + * An empty string if a valid but non-existing term ID is passed. + */ + function get_term_meta($term_id, $key = '', $single = \false) + { + } + /** + * Updates term metadata. + * + * Use the `$prev_value` parameter to differentiate between meta fields with the same key and term ID. + * + * If the meta field for the term does not exist, it will be added. + * + * @since 4.4.0 + * + * @param int $term_id Term ID. + * @param string $meta_key Metadata key. + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. + * @param mixed $prev_value Optional. Previous value to check before updating. + * If specified, only update existing metadata entries with + * this value. Otherwise, update all entries. Default empty. + * @return int|bool|WP_Error Meta ID if the key didn't exist. true on successful update, + * false on failure or if the value passed to the function + * is the same as the one that is already in the database. + * WP_Error when term_id is ambiguous between taxonomies. + */ + function update_term_meta($term_id, $meta_key, $meta_value, $prev_value = '') + { + } + /** + * Updates metadata cache for list of term IDs. + * + * Performs SQL query to retrieve all metadata for the terms matching `$term_ids` and stores them in the cache. + * Subsequent calls to `get_term_meta()` will not need to query the database. + * + * @since 4.4.0 + * + * @param array $term_ids List of term IDs. + * @return array|false An array of metadata on success, false if there is nothing to update. + */ + function update_termmeta_cache($term_ids) + { + } + /** + * Gets all meta data, including meta IDs, for the given term ID. + * + * @since 4.9.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $term_id Term ID. + * @return array|false Array with meta data, or false when the meta table is not installed. + */ + function has_term_meta($term_id) + { + } + /** + * Registers a meta key for terms. + * + * @since 4.9.8 + * + * @param string $taxonomy Taxonomy to register a meta key for. Pass an empty string + * to register the meta key across all existing taxonomies. + * @param string $meta_key The meta key to register. + * @param array $args Data used to describe the meta key when registered. See + * {@see register_meta()} for a list of supported arguments. + * @return bool True if the meta key was successfully registered, false if not. + */ + function register_term_meta($taxonomy, $meta_key, array $args) + { + } + /** + * Unregisters a meta key for terms. + * + * @since 4.9.8 + * + * @param string $taxonomy Taxonomy the meta key is currently registered for. Pass + * an empty string if the meta key is registered across all + * existing taxonomies. + * @param string $meta_key The meta key to unregister. + * @return bool True on success, false if the meta key was not previously registered. + */ + function unregister_term_meta($taxonomy, $meta_key) + { + } + /** + * Determines whether a taxonomy term exists. + * + * Formerly is_term(), introduced in 2.3.0. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 3.0.0 + * @since 6.0.0 Converted to use `get_terms()`. + * + * @global bool $_wp_suspend_cache_invalidation + * + * @param int|string $term The term to check. Accepts term ID, slug, or name. + * @param string $taxonomy Optional. The taxonomy name to use. + * @param int $parent Optional. ID of parent term under which to confine the exists search. + * @return mixed Returns null if the term does not exist. + * Returns the term ID if no taxonomy is specified and the term ID exists. + * Returns an array of the term ID and the term taxonomy ID if the taxonomy is specified and the pairing exists. + * Returns 0 if term ID 0 is passed to the function. + */ + function term_exists($term, $taxonomy = '', $parent = \null) + { + } + /** + * Checks if a term is an ancestor of another term. + * + * You can use either an ID or the term object for both parameters. + * + * @since 3.4.0 + * + * @param int|object $term1 ID or object to check if this is the parent term. + * @param int|object $term2 The child term. + * @param string $taxonomy Taxonomy name that $term1 and `$term2` belong to. + * @return bool Whether `$term2` is a child of `$term1`. + */ + function term_is_ancestor_of($term1, $term2, $taxonomy) + { + } + /** + * Sanitizes all term fields. + * + * Relies on sanitize_term_field() to sanitize the term. The difference is that + * this function will sanitize **all** fields. The context is based + * on sanitize_term_field(). + * + * The `$term` is expected to be either an array or an object. + * + * @since 2.3.0 + * + * @param array|object $term The term to check. + * @param string $taxonomy The taxonomy name to use. + * @param string $context Optional. Context in which to sanitize the term. + * Accepts 'raw', 'edit', 'db', 'display', 'rss', + * 'attribute', or 'js'. Default 'display'. + * @return array|object Term with all fields sanitized. + * @phpstan-template T of array|object + * @phpstan-param T $term + * @phpstan-return T + */ + function sanitize_term($term, $taxonomy, $context = 'display') + { + } + /** + * Sanitizes the field value in the term based on the context. + * + * Passing a term field value through the function should be assumed to have + * cleansed the value for whatever context the term field is going to be used. + * + * If no context or an unsupported context is given, then default filters will + * be applied. + * + * There are enough filters for each context to support a custom filtering + * without creating your own filter function. Simply create a function that + * hooks into the filter you need. + * + * @since 2.3.0 + * + * @param string $field Term field to sanitize. + * @param string $value Search for this term value. + * @param int $term_id Term ID. + * @param string $taxonomy Taxonomy name. + * @param string $context Context in which to sanitize the term field. + * Accepts 'raw', 'edit', 'db', 'display', 'rss', + * 'attribute', or 'js'. Default 'display'. + * @return mixed Sanitized field. + */ + function sanitize_term_field($field, $value, $term_id, $taxonomy, $context) + { + } + /** + * Counts how many terms are in taxonomy. + * + * Default $args is 'hide_empty' which can be 'hide_empty=true' or array('hide_empty' => true). + * + * @since 2.3.0 + * @since 5.6.0 Changed the function signature so that the `$args` array can be provided as the first parameter. + * + * @internal The `$deprecated` parameter is parsed for backward compatibility only. + * + * @param array|string $args Optional. Array or string of arguments. See WP_Term_Query::__construct() + * for information on accepted arguments. Default empty array. + * @param array|string $deprecated Optional. Argument array, when using the legacy function parameter format. + * If present, this parameter will be interpreted as `$args`, and the first + * function parameter will be parsed as a taxonomy or array of taxonomies. + * Default empty. + * @return string|WP_Error Numeric string containing the number of terms in that + * taxonomy or WP_Error if the taxonomy does not exist. + * @phpstan-param array{ + * taxonomy?: string|string[], + * object_ids?: int|int[], + * orderby?: string, + * order?: string, + * hide_empty?: bool|int, + * include?: int[]|string, + * exclude?: int[]|string, + * exclude_tree?: int[]|string, + * number?: int|string, + * offset?: int, + * fields?: string, + * count?: bool, + * name?: string|string[], + * slug?: string|string[], + * term_taxonomy_id?: int|int[], + * hierarchical?: bool, + * search?: string, + * name__like?: string, + * description__like?: string, + * pad_counts?: bool, + * get?: string, + * child_of?: int, + * parent?: int, + * childless?: bool, + * cache_domain?: string, + * update_term_meta_cache?: bool, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * } $args See WP_Term_Query::__construct() + */ + function wp_count_terms($args = array(), $deprecated = '') + { + } + /** + * Unlinks the object from the taxonomy or taxonomies. + * + * Will remove all relationships between the object and any terms in + * a particular taxonomy or taxonomies. Does not remove the term or + * taxonomy itself. + * + * @since 2.3.0 + * + * @param int $object_id The term object ID that refers to the term. + * @param string|array $taxonomies List of taxonomy names or single taxonomy name. + */ + function wp_delete_object_term_relationships($object_id, $taxonomies) + { + } + /** + * Removes a term from the database. + * + * If the term is a parent of other terms, then the children will be updated to + * that term's parent. + * + * Metadata associated with the term will be deleted. + * + * @since 2.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $term Term ID. + * @param string $taxonomy Taxonomy name. + * @param array|string $args { + * Optional. Array of arguments to override the default term ID. Default empty array. + * + * @type int $default The term ID to make the default term. This will only override + * the terms found if there is only one term found. Any other and + * the found terms are used. + * @type bool $force_default Optional. Whether to force the supplied term as default to be + * assigned even if the object was not going to be term-less. + * Default false. + * } + * @return bool|int|WP_Error True on success, false if term does not exist. Zero on attempted + * deletion of default Category. WP_Error if the taxonomy does not exist. + * @phpstan-param array{ + * default?: int, + * force_default?: bool, + * } $args + */ + function wp_delete_term($term, $taxonomy, $args = array()) + { + } + /** + * Deletes one existing category. + * + * @since 2.0.0 + * + * @param int $cat_ID Category term ID. + * @return bool|int|WP_Error Returns true if completes delete action; false if term doesn't exist; + * Zero on attempted deletion of default Category; WP_Error object is + * also a possibility. + */ + function wp_delete_category($cat_ID) + { + } + /** + * Retrieves the terms associated with the given object(s), in the supplied taxonomies. + * + * @since 2.3.0 + * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`. + * Introduced `$parent` argument. + * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or + * 'all_with_object_id', an array of `WP_Term` objects will be returned. + * @since 4.7.0 Refactored to use WP_Term_Query, and to support any WP_Term_Query arguments. + * + * @param int|int[] $object_ids The ID(s) of the object(s) to retrieve. + * @param string|string[] $taxonomies The taxonomy names to retrieve terms from. + * @param array|string $args See WP_Term_Query::__construct() for supported arguments. + * @return WP_Term[]|int[]|string[]|string|WP_Error Array of terms, a count thereof as a numeric string, + * or WP_Error if any of the taxonomies do not exist. + * See WP_Term_Query::get_terms() for more information. + * @phpstan-param array{ + * taxonomy?: string|string[], + * object_ids?: int|int[], + * orderby?: string, + * order?: string, + * hide_empty?: bool|int, + * include?: int[]|string, + * exclude?: int[]|string, + * exclude_tree?: int[]|string, + * number?: int|string, + * offset?: int, + * fields?: string, + * count?: bool, + * name?: string|string[], + * slug?: string|string[], + * term_taxonomy_id?: int|int[], + * hierarchical?: bool, + * search?: string, + * name__like?: string, + * description__like?: string, + * pad_counts?: bool, + * get?: string, + * child_of?: int, + * parent?: int, + * childless?: bool, + * cache_domain?: string, + * update_term_meta_cache?: bool, + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * } $args See WP_Term_Query::__construct() + */ + function wp_get_object_terms($object_ids, $taxonomies, $args = array()) + { + } + /** + * Adds a new term to the database. + * + * A non-existent term is inserted in the following sequence: + * 1. The term is added to the term table, then related to the taxonomy. + * 2. If everything is correct, several actions are fired. + * 3. The 'term_id_filter' is evaluated. + * 4. The term cache is cleaned. + * 5. Several more actions are fired. + * 6. An array is returned containing the `term_id` and `term_taxonomy_id`. + * + * If the 'slug' argument is not empty, then it is checked to see if the term + * is invalid. If it is not a valid, existing term, it is added and the term_id + * is given. + * + * If the taxonomy is hierarchical, and the 'parent' argument is not empty, + * the term is inserted and the term_id will be given. + * + * Error handling: + * If `$taxonomy` does not exist or `$term` is empty, + * a WP_Error object will be returned. + * + * If the term already exists on the same hierarchical level, + * or the term slug and name are not unique, a WP_Error object will be returned. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @since 2.3.0 + * + * @param string $term The term name to add. + * @param string $taxonomy The taxonomy to which to add the term. + * @param array|string $args { + * Optional. Array or query string of arguments for inserting a term. + * + * @type string $alias_of Slug of the term to make this term an alias of. + * Default empty string. Accepts a term slug. + * @type string $description The term description. Default empty string. + * @type int $parent The id of the parent term. Default 0. + * @type string $slug The term slug to use. Default empty string. + * } + * @return array|WP_Error { + * An array of the new term data, WP_Error otherwise. + * + * @type int $term_id The new term ID. + * @type int|string $term_taxonomy_id The new term taxonomy ID. Can be a numeric string. + * } + * @phpstan-param array{ + * alias_of?: string, + * description?: string, + * parent?: int, + * slug?: string, + * } $args + * @phpstan-return \WP_Error|array{ + * term_id: int, + * term_taxonomy_id: int|string, + * } + */ + function wp_insert_term($term, $taxonomy, $args = array()) + { + } + /** + * Creates term and taxonomy relationships. + * + * Relates an object (post, link, etc.) to a term and taxonomy type. Creates the + * term and taxonomy relationship if it doesn't already exist. Creates a term if + * it doesn't exist (using the slug). + * + * A relationship means that the term is grouped in or belongs to the taxonomy. + * A term has no meaning until it is given context by defining which taxonomy it + * exists under. + * + * @since 2.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $object_id The object to relate to. + * @param string|int|array $terms A single term slug, single term ID, or array of either term slugs or IDs. + * Will replace all existing related terms in this taxonomy. Passing an + * empty value will remove all related terms. + * @param string $taxonomy The context in which to relate the term to the object. + * @param bool $append Optional. If false will delete difference of terms. Default false. + * @return array|WP_Error Term taxonomy IDs of the affected terms or WP_Error on failure. + */ + function wp_set_object_terms($object_id, $terms, $taxonomy, $append = \false) + { + } + /** + * Adds term(s) associated with a given object. + * + * @since 3.6.0 + * + * @param int $object_id The ID of the object to which the terms will be added. + * @param string|int|array $terms The slug(s) or ID(s) of the term(s) to add. + * @param array|string $taxonomy Taxonomy name. + * @return array|WP_Error Term taxonomy IDs of the affected terms. + */ + function wp_add_object_terms($object_id, $terms, $taxonomy) + { + } + /** + * Removes term(s) associated with a given object. + * + * @since 3.6.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $object_id The ID of the object from which the terms will be removed. + * @param string|int|array $terms The slug(s) or ID(s) of the term(s) to remove. + * @param string $taxonomy Taxonomy name. + * @return bool|WP_Error True on success, false or WP_Error on failure. + */ + function wp_remove_object_terms($object_id, $terms, $taxonomy) + { + } + /** + * Makes term slug unique, if it isn't already. + * + * The `$slug` has to be unique global to every taxonomy, meaning that one + * taxonomy term can't have a matching slug with another taxonomy term. Each + * slug has to be globally unique for every taxonomy. + * + * The way this works is that if the taxonomy that the term belongs to is + * hierarchical and has a parent, it will append that parent to the $slug. + * + * If that still doesn't return a unique slug, then it tries to append a number + * until it finds a number that is truly unique. + * + * The only purpose for `$term` is for appending a parent, if one exists. + * + * @since 2.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $slug The string that will be tried for a unique slug. + * @param object $term The term object that the `$slug` will belong to. + * @return string Will return a true unique slug. + */ + function wp_unique_term_slug($slug, $term) + { + } + /** + * Updates term based on arguments provided. + * + * The `$args` will indiscriminately override all values with the same field name. + * Care must be taken to not override important information need to update or + * update will fail (or perhaps create a new term, neither would be acceptable). + * + * Defaults will set 'alias_of', 'description', 'parent', and 'slug' if not + * defined in `$args` already. + * + * 'alias_of' will create a term group, if it doesn't already exist, and + * update it for the `$term`. + * + * If the 'slug' argument in `$args` is missing, then the 'name' will be used. + * If you set 'slug' and it isn't unique, then a WP_Error is returned. + * If you don't pass any slug, then a unique one will be created. + * + * @since 2.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $term_id The ID of the term. + * @param string $taxonomy The taxonomy of the term. + * @param array $args { + * Optional. Array of arguments for updating a term. + * + * @type string $alias_of Slug of the term to make this term an alias of. + * Default empty string. Accepts a term slug. + * @type string $description The term description. Default empty string. + * @type int $parent The id of the parent term. Default 0. + * @type string $slug The term slug to use. Default empty string. + * } + * @return array|WP_Error An array containing the `term_id` and `term_taxonomy_id`, + * WP_Error otherwise. + * @phpstan-param array{ + * alias_of?: string, + * description?: string, + * parent?: int, + * slug?: string, + * } $args + */ + function wp_update_term($term_id, $taxonomy, $args = array()) + { + } + /** + * Enables or disables term counting. + * + * @since 2.5.0 + * + * @param bool $defer Optional. Enable if true, disable if false. + * @return bool Whether term counting is enabled or disabled. + */ + function wp_defer_term_counting($defer = \null) + { + } + /** + * Updates the amount of terms in taxonomy. + * + * If there is a taxonomy callback applied, then it will be called for updating + * the count. + * + * The default action is to count what the amount of terms have the relationship + * of term ID. Once that is done, then update the database. + * + * @since 2.3.0 + * + * @param int|array $terms The term_taxonomy_id of the terms. + * @param string $taxonomy The context of the term. + * @param bool $do_deferred Whether to flush the deferred term counts too. Default false. + * @return bool If no terms will return false, and if successful will return true. + */ + function wp_update_term_count($terms, $taxonomy, $do_deferred = \false) + { + } + /** + * Performs term count update immediately. + * + * @since 2.5.0 + * + * @param array $terms The term_taxonomy_id of terms to update. + * @param string $taxonomy The context of the term. + * @return true Always true when complete. + */ + function wp_update_term_count_now($terms, $taxonomy) + { + } + // + // Cache. + // + /** + * Removes the taxonomy relationship to terms from the cache. + * + * Will remove the entire taxonomy relationship containing term `$object_id`. The + * term IDs have to exist within the taxonomy `$object_type` for the deletion to + * take place. + * + * @since 2.3.0 + * + * @global bool $_wp_suspend_cache_invalidation + * + * @see get_object_taxonomies() for more on $object_type. + * + * @param int|array $object_ids Single or list of term object ID(s). + * @param array|string $object_type The taxonomy object type. + */ + function clean_object_term_cache($object_ids, $object_type) + { + } + /** + * Removes all of the term IDs from the cache. + * + * @since 2.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global bool $_wp_suspend_cache_invalidation + * + * @param int|int[] $ids Single or array of term IDs. + * @param string $taxonomy Optional. Taxonomy slug. Can be empty, in which case the taxonomies of the passed + * term IDs will be used. Default empty. + * @param bool $clean_taxonomy Optional. Whether to clean taxonomy wide caches (true), or just individual + * term object caches (false). Default true. + */ + function clean_term_cache($ids, $taxonomy = '', $clean_taxonomy = \true) + { + } + /** + * Cleans the caches for a taxonomy. + * + * @since 4.9.0 + * + * @param string $taxonomy Taxonomy slug. + */ + function clean_taxonomy_cache($taxonomy) + { + } + /** + * Retrieves the cached term objects for the given object ID. + * + * Upstream functions (like get_the_terms() and is_object_in_term()) are + * responsible for populating the object-term relationship cache. The current + * function only fetches relationship data that is already in the cache. + * + * @since 2.3.0 + * @since 4.7.0 Returns a `WP_Error` object if there's an error with + * any of the matched terms. + * + * @param int $id Term object ID, for example a post, comment, or user ID. + * @param string $taxonomy Taxonomy name. + * @return bool|WP_Term[]|WP_Error Array of `WP_Term` objects, if cached. + * False if cache is empty for `$taxonomy` and `$id`. + * WP_Error if get_term() returns an error object for any term. + */ + function get_object_term_cache($id, $taxonomy) + { + } + /** + * Updates the cache for the given term object ID(s). + * + * Note: Due to performance concerns, great care should be taken to only update + * term caches when necessary. Processing time can increase exponentially depending + * on both the number of passed term IDs and the number of taxonomies those terms + * belong to. + * + * Caches will only be updated for terms not already cached. + * + * @since 2.3.0 + * + * @param string|int[] $object_ids Comma-separated list or array of term object IDs. + * @param string|string[] $object_type The taxonomy object type or array of the same. + * @return void|false Void on success or if the `$object_ids` parameter is empty, + * false if all of the terms in `$object_ids` are already cached. + */ + function update_object_term_cache($object_ids, $object_type) + { + } + /** + * Updates terms in cache. + * + * @since 2.3.0 + * + * @param WP_Term[] $terms Array of term objects to change. + * @param string $taxonomy Not used. + */ + function update_term_cache($terms, $taxonomy = '') + { + } + // + // Private. + // + /** + * Retrieves children of taxonomy as term IDs. + * + * @access private + * @since 2.3.0 + * + * @param string $taxonomy Taxonomy name. + * @return array Empty if $taxonomy isn't hierarchical or returns children as term IDs. + */ + function _get_term_hierarchy($taxonomy) + { + } + /** + * Gets the subset of $terms that are descendants of $term_id. + * + * If `$terms` is an array of objects, then _get_term_children() returns an array of objects. + * If `$terms` is an array of IDs, then _get_term_children() returns an array of IDs. + * + * @access private + * @since 2.3.0 + * + * @param int $term_id The ancestor term: all returned terms should be descendants of `$term_id`. + * @param array $terms The set of terms - either an array of term objects or term IDs - from which those that + * are descendants of $term_id will be chosen. + * @param string $taxonomy The taxonomy which determines the hierarchy of the terms. + * @param array $ancestors Optional. Term ancestors that have already been identified. Passed by reference, to keep + * track of found terms when recursing the hierarchy. The array of located ancestors is used + * to prevent infinite recursion loops. For performance, `term_ids` are used as array keys, + * with 1 as value. Default empty array. + * @return array|WP_Error The subset of $terms that are descendants of $term_id. + */ + function _get_term_children($term_id, $terms, $taxonomy, &$ancestors = array()) + { + } + /** + * Adds count of children to parent count. + * + * Recalculates term counts by including items from child terms. Assumes all + * relevant children are already in the $terms argument. + * + * @access private + * @since 2.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param object[]|WP_Term[] $terms List of term objects (passed by reference). + * @param string $taxonomy Term context. + */ + function _pad_term_counts(&$terms, $taxonomy) + { + } + /** + * Adds any terms from the given IDs to the cache that do not already exist in cache. + * + * @since 4.6.0 + * @since 6.1.0 This function is no longer marked as "private". + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $term_ids Array of term IDs. + * @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true. + */ + function _prime_term_caches($term_ids, $update_meta_cache = \true) + { + } + // + // Default callbacks. + // + /** + * Updates term count based on object types of the current taxonomy. + * + * Private function for the default callback for post_tag and category + * taxonomies. + * + * @access private + * @since 2.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int[] $terms List of term taxonomy IDs. + * @param WP_Taxonomy $taxonomy Current taxonomy object of terms. + */ + function _update_post_term_count($terms, $taxonomy) + { + } + /** + * Updates term count based on number of objects. + * + * Default callback for the 'link_category' taxonomy. + * + * @since 3.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int[] $terms List of term taxonomy IDs. + * @param WP_Taxonomy $taxonomy Current taxonomy object of terms. + */ + function _update_generic_term_count($terms, $taxonomy) + { + } + /** + * Creates a new term for a term_taxonomy item that currently shares its term + * with another term_taxonomy. + * + * @ignore + * @since 4.2.0 + * @since 4.3.0 Introduced `$record` parameter. Also, `$term_id` and + * `$term_taxonomy_id` can now accept objects. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int|object $term_id ID of the shared term, or the shared term object. + * @param int|object $term_taxonomy_id ID of the term_taxonomy item to receive a new term, or the term_taxonomy object + * (corresponding to a row from the term_taxonomy table). + * @param bool $record Whether to record data about the split term in the options table. The recording + * process has the potential to be resource-intensive, so during batch operations + * it can be beneficial to skip inline recording and do it just once, after the + * batch is processed. Only set this to `false` if you know what you are doing. + * Default: true. + * @return int|WP_Error When the current term does not need to be split (or cannot be split on the current + * database schema), `$term_id` is returned. When the term is successfully split, the + * new term_id is returned. A WP_Error is returned for miscellaneous errors. + */ + function _split_shared_term($term_id, $term_taxonomy_id, $record = \true) + { + } + /** + * Splits a batch of shared taxonomy terms. + * + * @since 4.3.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function _wp_batch_split_terms() + { + } + /** + * In order to avoid the _wp_batch_split_terms() job being accidentally removed, + * checks that it's still scheduled while we haven't finished splitting terms. + * + * @ignore + * @since 4.3.0 + */ + function _wp_check_for_scheduled_split_terms() + { + } + /** + * Checks default categories when a term gets split to see if any of them need to be updated. + * + * @ignore + * @since 4.2.0 + * + * @param int $term_id ID of the formerly shared term. + * @param int $new_term_id ID of the new term created for the $term_taxonomy_id. + * @param int $term_taxonomy_id ID for the term_taxonomy row affected by the split. + * @param string $taxonomy Taxonomy for the split term. + */ + function _wp_check_split_default_terms($term_id, $new_term_id, $term_taxonomy_id, $taxonomy) + { + } + /** + * Checks menu items when a term gets split to see if any of them need to be updated. + * + * @ignore + * @since 4.2.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $term_id ID of the formerly shared term. + * @param int $new_term_id ID of the new term created for the $term_taxonomy_id. + * @param int $term_taxonomy_id ID for the term_taxonomy row affected by the split. + * @param string $taxonomy Taxonomy for the split term. + */ + function _wp_check_split_terms_in_menus($term_id, $new_term_id, $term_taxonomy_id, $taxonomy) + { + } + /** + * If the term being split is a nav_menu, changes associations. + * + * @ignore + * @since 4.3.0 + * + * @param int $term_id ID of the formerly shared term. + * @param int $new_term_id ID of the new term created for the $term_taxonomy_id. + * @param int $term_taxonomy_id ID for the term_taxonomy row affected by the split. + * @param string $taxonomy Taxonomy for the split term. + */ + function _wp_check_split_nav_menu_terms($term_id, $new_term_id, $term_taxonomy_id, $taxonomy) + { + } + /** + * Gets data about terms that previously shared a single term_id, but have since been split. + * + * @since 4.2.0 + * + * @param int $old_term_id Term ID. This is the old, pre-split term ID. + * @return array Array of new term IDs, keyed by taxonomy. + */ + function wp_get_split_terms($old_term_id) + { + } + /** + * Gets the new term ID corresponding to a previously split term. + * + * @since 4.2.0 + * + * @param int $old_term_id Term ID. This is the old, pre-split term ID. + * @param string $taxonomy Taxonomy that the term belongs to. + * @return int|false If a previously split term is found corresponding to the old term_id and taxonomy, + * the new term_id will be returned. If no previously split term is found matching + * the parameters, returns false. + */ + function wp_get_split_term($old_term_id, $taxonomy) + { + } + /** + * Determines whether a term is shared between multiple taxonomies. + * + * Shared taxonomy terms began to be split in 4.3, but failed cron tasks or + * other delays in upgrade routines may cause shared terms to remain. + * + * @since 4.4.0 + * + * @param int $term_id Term ID. + * @return bool Returns false if a term is not shared between multiple taxonomies or + * if splitting shared taxonomy terms is finished. + */ + function wp_term_is_shared($term_id) + { + } + /** + * Generates a permalink for a taxonomy term archive. + * + * @since 2.5.0 + * + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * + * @param WP_Term|int|string $term The term object, ID, or slug whose link will be retrieved. + * @param string $taxonomy Optional. Taxonomy. Default empty. + * @return string|WP_Error URL of the taxonomy term archive on success, WP_Error if term does not exist. + */ + function get_term_link($term, $taxonomy = '') + { + } + /** + * Displays the taxonomies of a post with available options. + * + * This function can be used within the loop to display the taxonomies for a + * post without specifying the Post ID. You can also use it outside the Loop to + * display the taxonomies for a specific post. + * + * @since 2.5.0 + * + * @param array $args { + * Arguments about which post to use and how to format the output. Shares all of the arguments + * supported by get_the_taxonomies(), in addition to the following. + * + * @type int|WP_Post $post Post ID or object to get taxonomies of. Default current post. + * @type string $before Displays before the taxonomies. Default empty string. + * @type string $sep Separates each taxonomy. Default is a space. + * @type string $after Displays after the taxonomies. Default empty string. + * } + * @phpstan-param array{ + * post?: int|WP_Post, + * before?: string, + * sep?: string, + * after?: string, + * } $args + */ + function the_taxonomies($args = array()) + { + } + /** + * Retrieves all taxonomies associated with a post. + * + * This function can be used within the loop. It will also return an array of + * the taxonomies with links to the taxonomy and name. + * + * @since 2.5.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @param array $args { + * Optional. Arguments about how to format the list of taxonomies. Default empty array. + * + * @type string $template Template for displaying a taxonomy label and list of terms. + * Default is "Label: Terms." + * @type string $term_template Template for displaying a single term in the list. Default is the term name + * linked to its archive. + * } + * @return string[] List of taxonomies. + * @phpstan-param array{ + * template?: string, + * term_template?: string, + * } $args + */ + function get_the_taxonomies($post = 0, $args = array()) + { + } + /** + * Retrieves all taxonomy names for the given post. + * + * @since 2.5.0 + * + * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. + * @return string[] An array of all taxonomy names for the given post. + */ + function get_post_taxonomies($post = 0) + { + } + /** + * Determines if the given object is associated with any of the given terms. + * + * The given terms are checked against the object's terms' term_ids, names and slugs. + * Terms given as integers will only be checked against the object's terms' term_ids. + * If no terms are given, determines if object is associated with any terms in the given taxonomy. + * + * @since 2.7.0 + * + * @param int $object_id ID of the object (post ID, link ID, ...). + * @param string $taxonomy Single taxonomy name. + * @param int|string|int[]|string[] $terms Optional. Term ID, name, slug, or array of such + * to check against. Default null. + * @return bool|WP_Error WP_Error on input error. + */ + function is_object_in_term($object_id, $taxonomy, $terms = \null) + { + } + /** + * Determines if the given object type is associated with the given taxonomy. + * + * @since 3.0.0 + * + * @param string $object_type Object type string. + * @param string $taxonomy Single taxonomy name. + * @return bool True if object is associated with the taxonomy, otherwise false. + */ + function is_object_in_taxonomy($object_type, $taxonomy) + { + } + /** + * Gets an array of ancestor IDs for a given object. + * + * @since 3.1.0 + * @since 4.1.0 Introduced the `$resource_type` argument. + * + * @param int $object_id Optional. The ID of the object. Default 0. + * @param string $object_type Optional. The type of object for which we'll be retrieving + * ancestors. Accepts a post type or a taxonomy name. Default empty. + * @param string $resource_type Optional. Type of resource $object_type is. Accepts 'post_type' + * or 'taxonomy'. Default empty. + * @return int[] An array of IDs of ancestors from lowest to highest in the hierarchy. + */ + function get_ancestors($object_id = 0, $object_type = '', $resource_type = '') + { + } + /** + * Returns the term's parent's term ID. + * + * @since 3.1.0 + * + * @param int $term_id Term ID. + * @param string $taxonomy Taxonomy name. + * @return int|false Parent term ID on success, false on failure. + */ + function wp_get_term_taxonomy_parent_id($term_id, $taxonomy) + { + } + /** + * Checks the given subset of the term hierarchy for hierarchy loops. + * Prevents loops from forming and breaks those that it finds. + * + * Attached to the {@see 'wp_update_term_parent'} filter. + * + * @since 3.1.0 + * + * @param int $parent `term_id` of the parent for the term we're checking. + * @param int $term_id The term we're checking. + * @param string $taxonomy The taxonomy of the term we're checking. + * @return int The new parent for the term. + */ + function wp_check_term_hierarchy_for_loops($parent, $term_id, $taxonomy) + { + } + /** + * Determines whether a taxonomy is considered "viewable". + * + * @since 5.1.0 + * + * @param string|WP_Taxonomy $taxonomy Taxonomy name or object. + * @return bool Whether the taxonomy should be considered viewable. + */ + function is_taxonomy_viewable($taxonomy) + { + } + /** + * Determines whether a term is publicly viewable. + * + * A term is considered publicly viewable if its taxonomy is viewable. + * + * @since 6.1.0 + * + * @param int|WP_Term $term Term ID or term object. + * @return bool Whether the term is publicly viewable. + */ + function is_term_publicly_viewable($term) + { + } + /** + * Sets the last changed time for the 'terms' cache group. + * + * @since 5.0.0 + */ + function wp_cache_set_terms_last_changed() + { + } + /** + * Aborts calls to term meta if it is not supported. + * + * @since 5.0.0 + * + * @param mixed $check Skip-value for whether to proceed term meta function execution. + * @return mixed Original value of $check, or false if term meta is not supported. + */ + function wp_check_term_meta_support_prefilter($check) + { + } + /** + * Template loading functions. + * + * @package WordPress + * @subpackage Template + */ + /** + * Retrieves path to a template. + * + * Used to quickly retrieve the path of a template without including the file + * extension. It will also check the parent theme, if the file exists, with + * the use of locate_template(). Allows for more generic template location + * without the use of the other get_*_template() functions. + * + * @since 1.5.0 + * + * @param string $type Filename without extension. + * @param string[] $templates An optional list of template candidates. + * @return string Full path to template file. + */ + function get_query_template($type, $templates = array()) + { + } + /** + * Retrieves path of index template in current or parent template. + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'index'. + * + * @since 3.0.0 + * + * @see get_query_template() + * + * @return string Full path to index template file. + */ + function get_index_template() + { + } + /** + * Retrieves path of 404 template in current or parent template. + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is '404'. + * + * @since 1.5.0 + * + * @see get_query_template() + * + * @return string Full path to 404 template file. + */ + function get_404_template() + { + } + /** + * Retrieves path of archive template in current or parent template. + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'archive'. + * + * @since 1.5.0 + * + * @see get_query_template() + * + * @return string Full path to archive template file. + */ + function get_archive_template() + { + } + /** + * Retrieves path of post type archive template in current or parent template. + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'archive'. + * + * @since 3.7.0 + * + * @see get_archive_template() + * + * @return string Full path to archive template file. + */ + function get_post_type_archive_template() + { + } + /** + * Retrieves path of author template in current or parent template. + * + * The hierarchy for this template looks like: + * + * 1. author-{nicename}.php + * 2. author-{id}.php + * 3. author.php + * + * An example of this is: + * + * 1. author-john.php + * 2. author-1.php + * 3. author.php + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'author'. + * + * @since 1.5.0 + * + * @see get_query_template() + * + * @return string Full path to author template file. + */ + function get_author_template() + { + } + /** + * Retrieves path of category template in current or parent template. + * + * The hierarchy for this template looks like: + * + * 1. category-{slug}.php + * 2. category-{id}.php + * 3. category.php + * + * An example of this is: + * + * 1. category-news.php + * 2. category-2.php + * 3. category.php + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'category'. + * + * @since 1.5.0 + * @since 4.7.0 The decoded form of `category-{slug}.php` was added to the top of the + * template hierarchy when the category slug contains multibyte characters. + * + * @see get_query_template() + * + * @return string Full path to category template file. + */ + function get_category_template() + { + } + /** + * Retrieves path of tag template in current or parent template. + * + * The hierarchy for this template looks like: + * + * 1. tag-{slug}.php + * 2. tag-{id}.php + * 3. tag.php + * + * An example of this is: + * + * 1. tag-wordpress.php + * 2. tag-3.php + * 3. tag.php + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'tag'. + * + * @since 2.3.0 + * @since 4.7.0 The decoded form of `tag-{slug}.php` was added to the top of the + * template hierarchy when the tag slug contains multibyte characters. + * + * @see get_query_template() + * + * @return string Full path to tag template file. + */ + function get_tag_template() + { + } + /** + * Retrieves path of custom taxonomy term template in current or parent template. + * + * The hierarchy for this template looks like: + * + * 1. taxonomy-{taxonomy_slug}-{term_slug}.php + * 2. taxonomy-{taxonomy_slug}.php + * 3. taxonomy.php + * + * An example of this is: + * + * 1. taxonomy-location-texas.php + * 2. taxonomy-location.php + * 3. taxonomy.php + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'taxonomy'. + * + * @since 2.5.0 + * @since 4.7.0 The decoded form of `taxonomy-{taxonomy_slug}-{term_slug}.php` was added to the top of the + * template hierarchy when the term slug contains multibyte characters. + * + * @see get_query_template() + * + * @return string Full path to custom taxonomy term template file. + */ + function get_taxonomy_template() + { + } + /** + * Retrieves path of date template in current or parent template. + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'date'. + * + * @since 1.5.0 + * + * @see get_query_template() + * + * @return string Full path to date template file. + */ + function get_date_template() + { + } + /** + * Retrieves path of home template in current or parent template. + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'home'. + * + * @since 1.5.0 + * + * @see get_query_template() + * + * @return string Full path to home template file. + */ + function get_home_template() + { + } + /** + * Retrieves path of front page template in current or parent template. + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'frontpage'. + * + * @since 3.0.0 + * + * @see get_query_template() + * + * @return string Full path to front page template file. + */ + function get_front_page_template() + { + } + /** + * Retrieves path of Privacy Policy page template in current or parent template. + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'privacypolicy'. + * + * @since 5.2.0 + * + * @see get_query_template() + * + * @return string Full path to privacy policy template file. + */ + function get_privacy_policy_template() + { + } + /** + * Retrieves path of page template in current or parent template. + * + * Note: For block themes, use locate_block_template function instead. + * + * The hierarchy for this template looks like: + * + * 1. {Page Template}.php + * 2. page-{page_name}.php + * 3. page-{id}.php + * 4. page.php + * + * An example of this is: + * + * 1. page-templates/full-width.php + * 2. page-about.php + * 3. page-4.php + * 4. page.php + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'page'. + * + * @since 1.5.0 + * @since 4.7.0 The decoded form of `page-{page_name}.php` was added to the top of the + * template hierarchy when the page name contains multibyte characters. + * + * @see get_query_template() + * + * @return string Full path to page template file. + */ + function get_page_template() + { + } + /** + * Retrieves path of search template in current or parent template. + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'search'. + * + * @since 1.5.0 + * + * @see get_query_template() + * + * @return string Full path to search template file. + */ + function get_search_template() + { + } + /** + * Retrieves path of single template in current or parent template. Applies to single Posts, + * single Attachments, and single custom post types. + * + * The hierarchy for this template looks like: + * + * 1. {Post Type Template}.php + * 2. single-{post_type}-{post_name}.php + * 3. single-{post_type}.php + * 4. single.php + * + * An example of this is: + * + * 1. templates/full-width.php + * 2. single-post-hello-world.php + * 3. single-post.php + * 4. single.php + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'single'. + * + * @since 1.5.0 + * @since 4.4.0 `single-{post_type}-{post_name}.php` was added to the top of the template hierarchy. + * @since 4.7.0 The decoded form of `single-{post_type}-{post_name}.php` was added to the top of the + * template hierarchy when the post name contains multibyte characters. + * @since 4.7.0 `{Post Type Template}.php` was added to the top of the template hierarchy. + * + * @see get_query_template() + * + * @return string Full path to single template file. + */ + function get_single_template() + { + } + /** + * Retrieves an embed template path in the current or parent template. + * + * The hierarchy for this template looks like: + * + * 1. embed-{post_type}-{post_format}.php + * 2. embed-{post_type}.php + * 3. embed.php + * + * An example of this is: + * + * 1. embed-post-audio.php + * 2. embed-post.php + * 3. embed.php + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'embed'. + * + * @since 4.5.0 + * + * @see get_query_template() + * + * @return string Full path to embed template file. + */ + function get_embed_template() + { + } + /** + * Retrieves the path of the singular template in current or parent template. + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'singular'. + * + * @since 4.3.0 + * + * @see get_query_template() + * + * @return string Full path to singular template file + */ + function get_singular_template() + { + } + /** + * Retrieves path of attachment template in current or parent template. + * + * The hierarchy for this template looks like: + * + * 1. {mime_type}-{sub_type}.php + * 2. {sub_type}.php + * 3. {mime_type}.php + * 4. attachment.php + * + * An example of this is: + * + * 1. image-jpeg.php + * 2. jpeg.php + * 3. image.php + * 4. attachment.php + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'attachment'. + * + * @since 2.0.0 + * @since 4.3.0 The order of the mime type logic was reversed so the hierarchy is more logical. + * + * @see get_query_template() + * + * @global array $posts + * + * @return string Full path to attachment template file. + */ + function get_attachment_template() + { + } + /** + * Retrieves the name of the highest priority template file that exists. + * + * Searches in the STYLESHEETPATH before TEMPLATEPATH and wp-includes/theme-compat + * so that themes which inherit from a parent theme can just overload one file. + * + * @since 2.7.0 + * @since 5.5.0 The `$args` parameter was added. + * + * @param string|array $template_names Template file(s) to search for, in order. + * @param bool $load If true the template file will be loaded if it is found. + * @param bool $require_once Whether to require_once or require. Has no effect if `$load` is false. + * Default true. + * @param array $args Optional. Additional arguments passed to the template. + * Default empty array. + * @return string The template filename if one is located. + */ + function locate_template($template_names, $load = \false, $require_once = \true, $args = array()) + { + } + /** + * Requires the template file with WordPress environment. + * + * The globals are set up for the template file to ensure that the WordPress + * environment is available from within the function. The query variables are + * also available. + * + * @since 1.5.0 + * @since 5.5.0 The `$args` parameter was added. + * + * @global array $posts + * @global WP_Post $post Global post object. + * @global bool $wp_did_header + * @global WP_Query $wp_query WordPress Query object. + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. + * @global wpdb $wpdb WordPress database abstraction object. + * @global string $wp_version + * @global WP $wp Current WordPress environment instance. + * @global int $id + * @global WP_Comment $comment Global comment object. + * @global int $user_ID + * + * @param string $_template_file Path to template file. + * @param bool $require_once Whether to require_once or require. Default true. + * @param array $args Optional. Additional arguments passed to the template. + * Default empty array. + */ + function load_template($_template_file, $require_once = \true, $args = array()) + { + } + /** + * Sets a custom slug when creating auto-draft template parts. + * + * This is only needed for auto-drafts created by the regular WP editor. + * If this page is to be removed, this will not be necessary. + * + * @since 5.9.0 + * + * @param int $post_id Post ID. + */ + function wp_set_unique_slug_on_create_template_part($post_id) + { + } + /** + * Generates a unique slug for templates. + * + * @access private + * @since 5.8.0 + * + * @param string $override_slug The filtered value of the slug (starts as `null` from apply_filter). + * @param string $slug The original/un-filtered slug (post_name). + * @param int $post_ID Post ID. + * @param string $post_status No uniqueness checks are made if the post is still draft or pending. + * @param string $post_type Post type. + * @return string The original, desired slug. + */ + function wp_filter_wp_template_unique_post_slug($override_slug, $slug, $post_ID, $post_status, $post_type) + { + } + /** + * Prints the skip-link script & styles. + * + * @access private + * @since 5.8.0 + * + * @global string $_wp_current_template_content + */ + function the_block_template_skip_link() + { + } + /** + * Enables the block templates (editor mode) for themes with theme.json by default. + * + * @access private + * @since 5.8.0 + */ + function wp_enable_block_templates() + { + } + /** + * Theme, template, and stylesheet functions. + * + * @package WordPress + * @subpackage Theme + */ + /** + * Returns an array of WP_Theme objects based on the arguments. + * + * Despite advances over get_themes(), this function is quite expensive, and grows + * linearly with additional themes. Stick to wp_get_theme() if possible. + * + * @since 3.4.0 + * + * @global array $wp_theme_directories + * + * @param array $args { + * Optional. The search arguments. + * + * @type mixed $errors True to return themes with errors, false to return + * themes without errors, null to return all themes. + * Default false. + * @type mixed $allowed (Multisite) True to return only allowed themes for a site. + * False to return only disallowed themes for a site. + * 'site' to return only site-allowed themes. + * 'network' to return only network-allowed themes. + * Null to return all themes. Default null. + * @type int $blog_id (Multisite) The blog ID used to calculate which themes + * are allowed. Default 0, synonymous for the current blog. + * } + * @return WP_Theme[] Array of WP_Theme objects. + * @phpstan-param array{ + * errors?: mixed, + * allowed?: mixed, + * blog_id?: int, + * } $args + */ + function wp_get_themes($args = array()) + { + } + /** + * Gets a WP_Theme object for a theme. + * + * @since 3.4.0 + * + * @global array $wp_theme_directories + * + * @param string $stylesheet Optional. Directory name for the theme. Defaults to active theme. + * @param string $theme_root Optional. Absolute path of the theme root to look in. + * If not specified, get_raw_theme_root() is used to calculate + * the theme root for the $stylesheet provided (or active theme). + * @return WP_Theme Theme object. Be sure to check the object's exists() method + * if you need to confirm the theme's existence. + */ + function wp_get_theme($stylesheet = '', $theme_root = '') + { + } + /** + * Clears the cache held by get_theme_roots() and WP_Theme. + * + * @since 3.5.0 + * @param bool $clear_update_cache Whether to clear the theme updates cache. + */ + function wp_clean_themes_cache($clear_update_cache = \true) + { + } + /** + * Whether a child theme is in use. + * + * @since 3.0.0 + * + * @return bool True if a child theme is in use, false otherwise. + */ + function is_child_theme() + { + } + /** + * Retrieves name of the current stylesheet. + * + * The theme name that is currently set as the front end theme. + * + * For all intents and purposes, the template name and the stylesheet name + * are going to be the same for most cases. + * + * @since 1.5.0 + * + * @return string Stylesheet name. + */ + function get_stylesheet() + { + } + /** + * Retrieves stylesheet directory path for the active theme. + * + * @since 1.5.0 + * + * @return string Path to active theme's stylesheet directory. + */ + function get_stylesheet_directory() + { + } + /** + * Retrieves stylesheet directory URI for the active theme. + * + * @since 1.5.0 + * + * @return string URI to active theme's stylesheet directory. + */ + function get_stylesheet_directory_uri() + { + } + /** + * Retrieves stylesheet URI for the active theme. + * + * The stylesheet file name is 'style.css' which is appended to the stylesheet directory URI path. + * See get_stylesheet_directory_uri(). + * + * @since 1.5.0 + * + * @return string URI to active theme's stylesheet. + */ + function get_stylesheet_uri() + { + } + /** + * Retrieves the localized stylesheet URI. + * + * The stylesheet directory for the localized stylesheet files are located, by + * default, in the base theme directory. The name of the locale file will be the + * locale followed by '.css'. If that does not exist, then the text direction + * stylesheet will be checked for existence, for example 'ltr.css'. + * + * The theme may change the location of the stylesheet directory by either using + * the {@see 'stylesheet_directory_uri'} or {@see 'locale_stylesheet_uri'} filters. + * + * If you want to change the location of the stylesheet files for the entire + * WordPress workflow, then change the former. If you just have the locale in a + * separate folder, then change the latter. + * + * @since 2.1.0 + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @return string URI to active theme's localized stylesheet. + */ + function get_locale_stylesheet_uri() + { + } + /** + * Retrieves name of the active theme. + * + * @since 1.5.0 + * + * @return string Template name. + */ + function get_template() + { + } + /** + * Retrieves template directory path for the active theme. + * + * @since 1.5.0 + * + * @return string Path to active theme's template directory. + */ + function get_template_directory() + { + } + /** + * Retrieves template directory URI for the active theme. + * + * @since 1.5.0 + * + * @return string URI to active theme's template directory. + */ + function get_template_directory_uri() + { + } + /** + * Retrieves theme roots. + * + * @since 2.9.0 + * + * @global array $wp_theme_directories + * + * @return array|string An array of theme roots keyed by template/stylesheet + * or a single theme root if all themes have the same root. + */ + function get_theme_roots() + { + } + /** + * Registers a directory that contains themes. + * + * @since 2.9.0 + * + * @global array $wp_theme_directories + * + * @param string $directory Either the full filesystem path to a theme folder + * or a folder within WP_CONTENT_DIR. + * @return bool True if successfully registered a directory that contains themes, + * false if the directory does not exist. + */ + function register_theme_directory($directory) + { + } + /** + * Searches all registered theme directories for complete and valid themes. + * + * @since 2.9.0 + * + * @global array $wp_theme_directories + * + * @param bool $force Optional. Whether to force a new directory scan. Default false. + * @return array|false Valid themes found on success, false on failure. + */ + function search_theme_directories($force = \false) + { + } + /** + * Retrieves path to themes directory. + * + * Does not have trailing slash. + * + * @since 1.5.0 + * + * @global array $wp_theme_directories + * + * @param string $stylesheet_or_template Optional. The stylesheet or template name of the theme. + * Default is to leverage the main theme root. + * @return string Themes directory path. + */ + function get_theme_root($stylesheet_or_template = '') + { + } + /** + * Retrieves URI for themes directory. + * + * Does not have trailing slash. + * + * @since 1.5.0 + * + * @global array $wp_theme_directories + * + * @param string $stylesheet_or_template Optional. The stylesheet or template name of the theme. + * Default is to leverage the main theme root. + * @param string $theme_root Optional. The theme root for which calculations will be based, + * preventing the need for a get_raw_theme_root() call. Default empty. + * @return string Themes directory URI. + */ + function get_theme_root_uri($stylesheet_or_template = '', $theme_root = '') + { + } + /** + * Gets the raw theme root relative to the content directory with no filters applied. + * + * @since 3.1.0 + * + * @global array $wp_theme_directories + * + * @param string $stylesheet_or_template The stylesheet or template name of the theme. + * @param bool $skip_cache Optional. Whether to skip the cache. + * Defaults to false, meaning the cache is used. + * @return string Theme root. + */ + function get_raw_theme_root($stylesheet_or_template, $skip_cache = \false) + { + } + /** + * Displays localized stylesheet link element. + * + * @since 2.1.0 + */ + function locale_stylesheet() + { + } + /** + * Switches the theme. + * + * Accepts one argument: $stylesheet of the theme. It also accepts an additional function signature + * of two arguments: $template then $stylesheet. This is for backward compatibility. + * + * @since 2.5.0 + * + * @global array $wp_theme_directories + * @global WP_Customize_Manager $wp_customize + * @global array $sidebars_widgets + * + * @param string $stylesheet Stylesheet name. + */ + function switch_theme($stylesheet) + { + } + /** + * Checks that the active theme has the required files. + * + * Standalone themes need to have a `templates/index.html` or `index.php` template file. + * Child themes need to have a `Template` header in the `style.css` stylesheet. + * + * Does not initially check the default theme, which is the fallback and should always exist. + * But if it doesn't exist, it'll fall back to the latest core default theme that does exist. + * Will switch theme to the fallback theme if active theme does not validate. + * + * You can use the {@see 'validate_current_theme'} filter to return false to disable + * this functionality. + * + * @since 1.5.0 + * @since 6.0.0 Removed the requirement for block themes to have an `index.php` template. + * + * @see WP_DEFAULT_THEME + * + * @return bool + */ + function validate_current_theme() + { + } + /** + * Validates the theme requirements for WordPress version and PHP version. + * + * Uses the information from `Requires at least` and `Requires PHP` headers + * defined in the theme's `style.css` file. + * + * @since 5.5.0 + * @since 5.8.0 Removed support for using `readme.txt` as a fallback. + * + * @param string $stylesheet Directory name for the theme. + * @return true|WP_Error True if requirements are met, WP_Error on failure. + */ + function validate_theme_requirements($stylesheet) + { + } + /** + * Retrieves all theme modifications. + * + * @since 3.1.0 + * @since 5.9.0 The return value is always an array. + * + * @return array Theme modifications. + */ + function get_theme_mods() + { + } + /** + * Retrieves theme modification value for the active theme. + * + * If the modification name does not exist and `$default` is a string, then the + * default will be passed through the {@link https://www.php.net/sprintf sprintf()} + * PHP function with the template directory URI as the first value and the + * stylesheet directory URI as the second value. + * + * @since 2.1.0 + * + * @param string $name Theme modification name. + * @param mixed $default Optional. Theme modification default value. Default false. + * @return mixed Theme modification value. + */ + function get_theme_mod($name, $default = \false) + { + } + /** + * Updates theme modification value for the active theme. + * + * @since 2.1.0 + * @since 5.6.0 A return value was added. + * + * @param string $name Theme modification name. + * @param mixed $value Theme modification value. + * @return bool True if the value was updated, false otherwise. + */ + function set_theme_mod($name, $value) + { + } + /** + * Removes theme modification name from active theme list. + * + * If removing the name also removes all elements, then the entire option + * will be removed. + * + * @since 2.1.0 + * + * @param string $name Theme modification name. + */ + function remove_theme_mod($name) + { + } + /** + * Removes theme modifications option for the active theme. + * + * @since 2.1.0 + */ + function remove_theme_mods() + { + } + /** + * Retrieves the custom header text color in 3- or 6-digit hexadecimal form. + * + * @since 2.1.0 + * + * @return string Header text color in 3- or 6-digit hexadecimal form (minus the hash symbol). + */ + function get_header_textcolor() + { + } + /** + * Displays the custom header text color in 3- or 6-digit hexadecimal form (minus the hash symbol). + * + * @since 2.1.0 + */ + function header_textcolor() + { + } + /** + * Whether to display the header text. + * + * @since 3.4.0 + * + * @return bool + */ + function display_header_text() + { + } + /** + * Checks whether a header image is set or not. + * + * @since 4.2.0 + * + * @see get_header_image() + * + * @return bool Whether a header image is set or not. + */ + function has_header_image() + { + } + /** + * Retrieves header image for custom header. + * + * @since 2.1.0 + * + * @return string|false + */ + function get_header_image() + { + } + /** + * Creates image tag markup for a custom header image. + * + * @since 4.4.0 + * + * @param array $attr Optional. Additional attributes for the image tag. Can be used + * to override the default attributes. Default empty. + * @return string HTML image element markup or empty string on failure. + */ + function get_header_image_tag($attr = array()) + { + } + /** + * Displays the image markup for a custom header image. + * + * @since 4.4.0 + * + * @param array $attr Optional. Attributes for the image markup. Default empty. + */ + function the_header_image_tag($attr = array()) + { + } + /** + * Gets random header image data from registered images in theme. + * + * @since 3.4.0 + * + * @access private + * + * @global array $_wp_default_headers + * + * @return object + */ + function _get_random_header_data() + { + } + /** + * Gets random header image URL from registered images in theme. + * + * @since 3.2.0 + * + * @return string Path to header image. + */ + function get_random_header_image() + { + } + /** + * Checks if random header image is in use. + * + * Always true if user expressly chooses the option in Appearance > Header. + * Also true if theme has multiple header images registered, no specific header image + * is chosen, and theme turns on random headers with add_theme_support(). + * + * @since 3.2.0 + * + * @param string $type The random pool to use. Possible values include 'any', + * 'default', 'uploaded'. Default 'any'. + * @return bool + */ + function is_random_header_image($type = 'any') + { + } + /** + * Displays header image URL. + * + * @since 2.1.0 + */ + function header_image() + { + } + /** + * Gets the header images uploaded for the active theme. + * + * @since 3.2.0 + * + * @return array + */ + function get_uploaded_header_images() + { + } + /** + * Gets the header image data. + * + * @since 3.4.0 + * + * @global array $_wp_default_headers + * + * @return object + */ + function get_custom_header() + { + } + /** + * Registers a selection of default headers to be displayed by the custom header admin UI. + * + * @since 3.0.0 + * + * @global array $_wp_default_headers + * + * @param array $headers Array of headers keyed by a string ID. The IDs point to arrays + * containing 'url', 'thumbnail_url', and 'description' keys. + */ + function register_default_headers($headers) + { + } + /** + * Unregisters default headers. + * + * This function must be called after register_default_headers() has already added the + * header you want to remove. + * + * @see register_default_headers() + * @since 3.0.0 + * + * @global array $_wp_default_headers + * + * @param string|array $header The header string id (key of array) to remove, or an array thereof. + * @return bool|void A single header returns true on success, false on failure. + * There is currently no return value for multiple headers. + */ + function unregister_default_headers($header) + { + } + /** + * Checks whether a header video is set or not. + * + * @since 4.7.0 + * + * @see get_header_video_url() + * + * @return bool Whether a header video is set or not. + */ + function has_header_video() + { + } + /** + * Retrieves header video URL for custom header. + * + * Uses a local video if present, or falls back to an external video. + * + * @since 4.7.0 + * + * @return string|false Header video URL or false if there is no video. + */ + function get_header_video_url() + { + } + /** + * Displays header video URL. + * + * @since 4.7.0 + */ + function the_header_video_url() + { + } + /** + * Retrieves header video settings. + * + * @since 4.7.0 + * + * @return array + */ + function get_header_video_settings() + { + } + /** + * Checks whether a custom header is set or not. + * + * @since 4.7.0 + * + * @return bool True if a custom header is set. False if not. + */ + function has_custom_header() + { + } + /** + * Checks whether the custom header video is eligible to show on the current page. + * + * @since 4.7.0 + * + * @return bool True if the custom header video should be shown. False if not. + */ + function is_header_video_active() + { + } + /** + * Retrieves the markup for a custom header. + * + * The container div will always be returned in the Customizer preview. + * + * @since 4.7.0 + * + * @return string The markup for a custom header on success. + */ + function get_custom_header_markup() + { + } + /** + * Prints the markup for a custom header. + * + * A container div will always be printed in the Customizer preview. + * + * @since 4.7.0 + */ + function the_custom_header_markup() + { + } + /** + * Retrieves background image for custom background. + * + * @since 3.0.0 + * + * @return string + */ + function get_background_image() + { + } + /** + * Displays background image path. + * + * @since 3.0.0 + */ + function background_image() + { + } + /** + * Retrieves value for custom background color. + * + * @since 3.0.0 + * + * @return string + */ + function get_background_color() + { + } + /** + * Displays background color value. + * + * @since 3.0.0 + */ + function background_color() + { + } + /** + * Default custom background callback. + * + * @since 3.0.0 + */ + function _custom_background_cb() + { + } + /** + * Renders the Custom CSS style element. + * + * @since 4.7.0 + */ + function wp_custom_css_cb() + { + } + /** + * Fetches the `custom_css` post for a given theme. + * + * @since 4.7.0 + * + * @param string $stylesheet Optional. A theme object stylesheet name. Defaults to the active theme. + * @return WP_Post|null The custom_css post or null if none exists. + */ + function wp_get_custom_css_post($stylesheet = '') + { + } + /** + * Fetches the saved Custom CSS content for rendering. + * + * @since 4.7.0 + * + * @param string $stylesheet Optional. A theme object stylesheet name. Defaults to the active theme. + * @return string The Custom CSS Post content. + */ + function wp_get_custom_css($stylesheet = '') + { + } + /** + * Updates the `custom_css` post for a given theme. + * + * Inserts a `custom_css` post when one doesn't yet exist. + * + * @since 4.7.0 + * + * @param string $css CSS, stored in `post_content`. + * @param array $args { + * Args. + * + * @type string $preprocessed Optional. Pre-processed CSS, stored in `post_content_filtered`. + * Normally empty string. + * @type string $stylesheet Optional. Stylesheet (child theme) to update. + * Defaults to active theme/stylesheet. + * } + * @return WP_Post|WP_Error Post on success, error on failure. + * @phpstan-param array{ + * preprocessed?: string, + * stylesheet?: string, + * } $args + */ + function wp_update_custom_css_post($css, $args = array()) + { + } + /** + * Adds callback for custom TinyMCE editor stylesheets. + * + * The parameter $stylesheet is the name of the stylesheet, relative to + * the theme root. It also accepts an array of stylesheets. + * It is optional and defaults to 'editor-style.css'. + * + * This function automatically adds another stylesheet with -rtl prefix, e.g. editor-style-rtl.css. + * If that file doesn't exist, it is removed before adding the stylesheet(s) to TinyMCE. + * If an array of stylesheets is passed to add_editor_style(), + * RTL is only added for the first stylesheet. + * + * Since version 3.4 the TinyMCE body has .rtl CSS class. + * It is a better option to use that class and add any RTL styles to the main stylesheet. + * + * @since 3.0.0 + * + * @global array $editor_styles + * + * @param array|string $stylesheet Optional. Stylesheet name or array thereof, relative to theme root. + * Defaults to 'editor-style.css' + */ + function add_editor_style($stylesheet = 'editor-style.css') + { + } + /** + * Removes all visual editor stylesheets. + * + * @since 3.1.0 + * + * @global array $editor_styles + * + * @return bool True on success, false if there were no stylesheets to remove. + */ + function remove_editor_styles() + { + } + /** + * Retrieves any registered editor stylesheet URLs. + * + * @since 4.0.0 + * + * @global array $editor_styles Registered editor stylesheets + * + * @return string[] If registered, a list of editor stylesheet URLs. + */ + function get_editor_stylesheets() + { + } + /** + * Expands a theme's starter content configuration using core-provided data. + * + * @since 4.7.0 + * + * @return array Array of starter content. + */ + function get_theme_starter_content() + { + } + /** + * Registers theme support for a given feature. + * + * Must be called in the theme's functions.php file to work. + * If attached to a hook, it must be {@see 'after_setup_theme'}. + * The {@see 'init'} hook may be too late for some features. + * + * Example usage: + * + * add_theme_support( 'title-tag' ); + * add_theme_support( 'custom-logo', array( + * 'height' => 480, + * 'width' => 720, + * ) ); + * + * @since 2.9.0 + * @since 3.4.0 The `custom-header-uploads` feature was deprecated. + * @since 3.6.0 The `html5` feature was added. + * @since 3.6.1 The `html5` feature requires an array of types to be passed. Defaults to + * 'comment-list', 'comment-form', 'search-form' for backward compatibility. + * @since 3.9.0 The `html5` feature now also accepts 'gallery' and 'caption'. + * @since 4.1.0 The `title-tag` feature was added. + * @since 4.5.0 The `customize-selective-refresh-widgets` feature was added. + * @since 4.7.0 The `starter-content` feature was added. + * @since 5.0.0 The `responsive-embeds`, `align-wide`, `dark-editor-style`, `disable-custom-colors`, + * `disable-custom-font-sizes`, `editor-color-palette`, `editor-font-sizes`, + * `editor-styles`, and `wp-block-styles` features were added. + * @since 5.3.0 The `html5` feature now also accepts 'script' and 'style'. + * @since 5.3.0 Formalized the existing and already documented `...$args` parameter + * by adding it to the function signature. + * @since 5.5.0 The `core-block-patterns` feature was added and is enabled by default. + * @since 5.5.0 The `custom-logo` feature now also accepts 'unlink-homepage-logo'. + * @since 5.6.0 The `post-formats` feature warns if no array is passed as the second parameter. + * @since 5.8.0 The `widgets-block-editor` feature enables the Widgets block editor. + * @since 6.0.0 The `html5` feature warns if no array is passed as the second parameter. + * + * @global array $_wp_theme_features + * + * @param string $feature The feature being added. Likely core values include: + * - 'admin-bar' + * - 'align-wide' + * - 'automatic-feed-links' + * - 'core-block-patterns' + * - 'custom-background' + * - 'custom-header' + * - 'custom-line-height' + * - 'custom-logo' + * - 'customize-selective-refresh-widgets' + * - 'custom-spacing' + * - 'custom-units' + * - 'dark-editor-style' + * - 'disable-custom-colors' + * - 'disable-custom-font-sizes' + * - 'editor-color-palette' + * - 'editor-gradient-presets' + * - 'editor-font-sizes' + * - 'editor-styles' + * - 'featured-content' + * - 'html5' + * - 'menus' + * - 'post-formats' + * - 'post-thumbnails' + * - 'responsive-embeds' + * - 'starter-content' + * - 'title-tag' + * - 'wp-block-styles' + * - 'widgets' + * - 'widgets-block-editor' + * @param mixed ...$args Optional extra arguments to pass along with certain features. + * @return void|false Void on success, false on failure. + */ + function add_theme_support($feature, ...$args) + { + } + /** + * Registers the internal custom header and background routines. + * + * @since 3.4.0 + * @access private + * + * @global Custom_Image_Header $custom_image_header + * @global Custom_Background $custom_background + */ + function _custom_header_background_just_in_time() + { + } + /** + * Adds CSS to hide header text for custom logo, based on Customizer setting. + * + * @since 4.5.0 + * @access private + */ + function _custom_logo_header_styles() + { + } + /** + * Gets the theme support arguments passed when registering that support. + * + * Example usage: + * + * get_theme_support( 'custom-logo' ); + * get_theme_support( 'custom-header', 'width' ); + * + * @since 3.1.0 + * @since 5.3.0 Formalized the existing and already documented `...$args` parameter + * by adding it to the function signature. + * + * @global array $_wp_theme_features + * + * @param string $feature The feature to check. See add_theme_support() for the list + * of possible values. + * @param mixed ...$args Optional extra arguments to be checked against certain features. + * @return mixed The array of extra arguments or the value for the registered feature. + */ + function get_theme_support($feature, ...$args) + { + } + /** + * Allows a theme to de-register its support of a certain feature + * + * Should be called in the theme's functions.php file. Generally would + * be used for child themes to override support from the parent theme. + * + * @since 3.0.0 + * + * @see add_theme_support() + * + * @param string $feature The feature being removed. See add_theme_support() for the list + * of possible values. + * @return bool|void Whether feature was removed. + */ + function remove_theme_support($feature) + { + } + /** + * Do not use. Removes theme support internally without knowledge of those not used + * by themes directly. + * + * @access private + * @since 3.1.0 + * @global array $_wp_theme_features + * @global Custom_Image_Header $custom_image_header + * @global Custom_Background $custom_background + * + * @param string $feature The feature being removed. See add_theme_support() for the list + * of possible values. + * @return bool True if support was removed, false if the feature was not registered. + */ + function _remove_theme_support($feature) + { + } + /** + * Checks a theme's support for a given feature. + * + * Example usage: + * + * current_theme_supports( 'custom-logo' ); + * current_theme_supports( 'html5', 'comment-form' ); + * + * @since 2.9.0 + * @since 5.3.0 Formalized the existing and already documented `...$args` parameter + * by adding it to the function signature. + * + * @global array $_wp_theme_features + * + * @param string $feature The feature being checked. See add_theme_support() for the list + * of possible values. + * @param mixed ...$args Optional extra arguments to be checked against certain features. + * @return bool True if the active theme supports the feature, false otherwise. + */ + function current_theme_supports($feature, ...$args) + { + } + /** + * Checks a theme's support for a given feature before loading the functions which implement it. + * + * @since 2.9.0 + * + * @param string $feature The feature being checked. See add_theme_support() for the list + * of possible values. + * @param string $include Path to the file. + * @return bool True if the active theme supports the supplied feature, false otherwise. + */ + function require_if_theme_supports($feature, $include) + { + } + /** + * Registers a theme feature for use in add_theme_support(). + * + * This does not indicate that the active theme supports the feature, it only describes + * the feature's supported options. + * + * @since 5.5.0 + * + * @see add_theme_support() + * + * @global array $_wp_registered_theme_features + * + * @param string $feature The name uniquely identifying the feature. See add_theme_support() + * for the list of possible values. + * @param array $args { + * Data used to describe the theme. + * + * @type string $type The type of data associated with this feature. + * Valid values are 'string', 'boolean', 'integer', + * 'number', 'array', and 'object'. Defaults to 'boolean'. + * @type bool $variadic Does this feature utilize the variadic support + * of add_theme_support(), or are all arguments specified + * as the second parameter. Must be used with the "array" type. + * @type string $description A short description of the feature. Included in + * the Themes REST API schema. Intended for developers. + * @type bool|array $show_in_rest { + * Whether this feature should be included in the Themes REST API endpoint. + * Defaults to not being included. When registering an 'array' or 'object' type, + * this argument must be an array with the 'schema' key. + * + * @type array $schema Specifies the JSON Schema definition describing + * the feature. If any objects in the schema do not include + * the 'additionalProperties' keyword, it is set to false. + * @type string $name An alternate name to be used as the property name + * in the REST API. + * @type callable $prepare_callback A function used to format the theme support in the REST API. + * Receives the raw theme support value. + * } + * } + * @return true|WP_Error True if the theme feature was successfully registered, a WP_Error object if not. + * @phpstan-param array{ + * type?: string, + * variadic?: bool, + * description?: string, + * show_in_rest?: bool|array{ + * schema: array, + * name: string, + * prepare_callback: callable, + * }, + * } $args + */ + function register_theme_feature($feature, $args = array()) + { + } + /** + * Gets the list of registered theme features. + * + * @since 5.5.0 + * + * @global array $_wp_registered_theme_features + * + * @return array[] List of theme features, keyed by their name. + */ + function get_registered_theme_features() + { + } + /** + * Gets the registration config for a theme feature. + * + * @since 5.5.0 + * + * @global array $_wp_registered_theme_features + * + * @param string $feature The feature name. See add_theme_support() for the list + * of possible values. + * @return array|null The registration args, or null if the feature was not registered. + */ + function get_registered_theme_feature($feature) + { + } + /** + * Checks an attachment being deleted to see if it's a header or background image. + * + * If true it removes the theme modification which would be pointing at the deleted + * attachment. + * + * @access private + * @since 3.0.0 + * @since 4.3.0 Also removes `header_image_data`. + * @since 4.5.0 Also removes custom logo theme mods. + * + * @param int $id The attachment ID. + */ + function _delete_attachment_theme_mod($id) + { + } + /** + * Checks if a theme has been changed and runs 'after_switch_theme' hook on the next WP load. + * + * See {@see 'after_switch_theme'}. + * + * @since 3.3.0 + */ + function check_theme_switched() + { + } + /** + * Includes and instantiates the WP_Customize_Manager class. + * + * Loads the Customizer at plugins_loaded when accessing the customize.php admin + * page or when any request includes a wp_customize=on param or a customize_changeset + * param (a UUID). This param is a signal for whether to bootstrap the Customizer when + * WordPress is loading, especially in the Customizer preview + * or when making Customizer Ajax requests for widgets or menus. + * + * @since 3.4.0 + * + * @global WP_Customize_Manager $wp_customize + */ + function _wp_customize_include() + { + } + /** + * Publishes a snapshot's changes. + * + * @since 4.7.0 + * @access private + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global WP_Customize_Manager $wp_customize Customizer instance. + * + * @param string $new_status New post status. + * @param string $old_status Old post status. + * @param WP_Post $changeset_post Changeset post object. + */ + function _wp_customize_publish_changeset($new_status, $old_status, $changeset_post) + { + } + /** + * Filters changeset post data upon insert to ensure post_name is intact. + * + * This is needed to prevent the post_name from being dropped when the post is + * transitioned into pending status by a contributor. + * + * @since 4.7.0 + * + * @see wp_insert_post() + * + * @param array $post_data An array of slashed post data. + * @param array $supplied_post_data An array of sanitized, but otherwise unmodified post data. + * @return array Filtered data. + */ + function _wp_customize_changeset_filter_insert_post_data($post_data, $supplied_post_data) + { + } + /** + * Adds settings for the customize-loader script. + * + * @since 3.4.0 + */ + function _wp_customize_loader_settings() + { + } + /** + * Returns a URL to load the Customizer. + * + * @since 3.4.0 + * + * @param string $stylesheet Optional. Theme to customize. Defaults to active theme. + * The theme's stylesheet will be urlencoded if necessary. + * @return string + */ + function wp_customize_url($stylesheet = '') + { + } + /** + * Prints a script to check whether or not the Customizer is supported, + * and apply either the no-customize-support or customize-support class + * to the body. + * + * This function MUST be called inside the body tag. + * + * Ideally, call this function immediately after the body tag is opened. + * This prevents a flash of unstyled content. + * + * It is also recommended that you add the "no-customize-support" class + * to the body tag by default. + * + * @since 3.4.0 + * @since 4.7.0 Support for IE8 and below is explicitly removed via conditional comments. + * @since 5.5.0 IE8 and older are no longer supported. + */ + function wp_customize_support_script() + { + } + /** + * Whether the site is being previewed in the Customizer. + * + * @since 4.0.0 + * + * @global WP_Customize_Manager $wp_customize Customizer instance. + * + * @return bool True if the site is being previewed in the Customizer, false otherwise. + */ + function is_customize_preview() + { + } + /** + * Makes sure that auto-draft posts get their post_date bumped or status changed + * to draft to prevent premature garbage-collection. + * + * When a changeset is updated but remains an auto-draft, ensure the post_date + * for the auto-draft posts remains the same so that it will be + * garbage-collected at the same time by `wp_delete_auto_drafts()`. Otherwise, + * if the changeset is updated to be a draft then update the posts + * to have a far-future post_date so that they will never be garbage collected + * unless the changeset post itself is deleted. + * + * When a changeset is updated to be a persistent draft or to be scheduled for + * publishing, then transition any dependent auto-drafts to a draft status so + * that they likewise will not be garbage-collected but also so that they can + * be edited in the admin before publishing since there is not yet a post/page + * editing flow in the Customizer. See #39752. + * + * @link https://core.trac.wordpress.org/ticket/39752 + * + * @since 4.8.0 + * @access private + * @see wp_delete_auto_drafts() + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $new_status Transition to this post status. + * @param string $old_status Previous post status. + * @param \WP_Post $post Post data. + */ + function _wp_keep_alive_customize_changeset_dependent_auto_drafts($new_status, $old_status, $post) + { + } + /** + * Creates the initial theme features when the 'setup_theme' action is fired. + * + * See {@see 'setup_theme'}. + * + * @since 5.5.0 + * @since 6.0.1 The `block-templates` feature was added. + */ + function create_initial_theme_features() + { + } + /** + * Returns whether the active theme is a block-based theme or not. + * + * @since 5.9.0 + * + * @return boolean Whether the active theme is a block-based theme or not. + */ + function wp_is_block_theme() + { + } + /** + * Given an element name, returns a class name. + * + * Alias of WP_Theme_JSON::get_element_class_name. + * + * @since 6.1.0 + * + * @param string $element The name of the element. + * + * @return string The name of the class. + */ + function wp_theme_get_element_class_name($element) + { + } + /** + * Adds default theme supports for block themes when the 'setup_theme' action fires. + * + * See {@see 'setup_theme'}. + * + * @since 5.9.0 + * @access private + */ + function _add_default_theme_supports() + { + } + /** + * A simple set of functions to check the WordPress.org Version Update service. + * + * @package WordPress + * @since 2.3.0 + */ + /** + * Checks WordPress version against the newest version. + * + * The WordPress version, PHP version, and locale is sent. + * + * Checks against the WordPress server at api.wordpress.org. Will only check + * if WordPress isn't installing. + * + * @since 2.3.0 + * + * @global string $wp_version Used to check against the newest WordPress version. + * @global wpdb $wpdb WordPress database abstraction object. + * @global string $wp_local_package Locale code of the package. + * + * @param array $extra_stats Extra statistics to report to the WordPress.org API. + * @param bool $force_check Whether to bypass the transient cache and force a fresh update check. + * Defaults to false, true if $extra_stats is set. + */ + function wp_version_check($extra_stats = array(), $force_check = \false) + { + } + /** + * Checks for available updates to plugins based on the latest versions hosted on WordPress.org. + * + * Despite its name this function does not actually perform any updates, it only checks for available updates. + * + * A list of all plugins installed is sent to WP, along with the site locale. + * + * Checks against the WordPress server at api.wordpress.org. Will only check + * if WordPress isn't installing. + * + * @since 2.3.0 + * + * @global string $wp_version The WordPress version string. + * + * @param array $extra_stats Extra statistics to report to the WordPress.org API. + */ + function wp_update_plugins($extra_stats = array()) + { + } + /** + * Checks for available updates to themes based on the latest versions hosted on WordPress.org. + * + * Despite its name this function does not actually perform any updates, it only checks for available updates. + * + * A list of all themes installed is sent to WP, along with the site locale. + * + * Checks against the WordPress server at api.wordpress.org. Will only check + * if WordPress isn't installing. + * + * @since 2.7.0 + * + * @global string $wp_version The WordPress version string. + * + * @param array $extra_stats Extra statistics to report to the WordPress.org API. + */ + function wp_update_themes($extra_stats = array()) + { + } + /** + * Performs WordPress automatic background updates. + * + * Updates WordPress core plus any plugins and themes that have automatic updates enabled. + * + * @since 3.7.0 + */ + function wp_maybe_auto_update() + { + } + /** + * Retrieves a list of all language updates available. + * + * @since 3.7.0 + * + * @return object[] Array of translation objects that have available updates. + */ + function wp_get_translation_updates() + { + } + /** + * Collects counts and UI strings for available updates. + * + * @since 3.3.0 + * + * @return array + */ + function wp_get_update_data() + { + } + /** + * Determines whether core should be updated. + * + * @since 2.8.0 + * + * @global string $wp_version The WordPress version string. + */ + function _maybe_update_core() + { + } + /** + * Checks the last time plugins were run before checking plugin versions. + * + * This might have been backported to WordPress 2.6.1 for performance reasons. + * This is used for the wp-admin to check only so often instead of every page + * load. + * + * @since 2.7.0 + * @access private + */ + function _maybe_update_plugins() + { + } + /** + * Checks themes versions only after a duration of time. + * + * This is for performance reasons to make sure that on the theme version + * checker is not run on every page load. + * + * @since 2.7.0 + * @access private + */ + function _maybe_update_themes() + { + } + /** + * Schedules core, theme, and plugin update checks. + * + * @since 3.1.0 + */ + function wp_schedule_update_checks() + { + } + /** + * Clears existing update caches for plugins, themes, and core. + * + * @since 4.1.0 + */ + function wp_clean_update_cache() + { + } + /** + * Core User API + * + * @package WordPress + * @subpackage Users + */ + /** + * Authenticates and logs a user in with 'remember' capability. + * + * The credentials is an array that has 'user_login', 'user_password', and + * 'remember' indices. If the credentials is not given, then the log in form + * will be assumed and used if set. + * + * The various authentication cookies will be set by this function and will be + * set for a longer period depending on if the 'remember' credential is set to + * true. + * + * Note: wp_signon() doesn't handle setting the current user. This means that if the + * function is called before the {@see 'init'} hook is fired, is_user_logged_in() will + * evaluate as false until that point. If is_user_logged_in() is needed in conjunction + * with wp_signon(), wp_set_current_user() should be called explicitly. + * + * @since 2.5.0 + * + * @global string $auth_secure_cookie + * + * @param array $credentials Optional. User info in order to sign on. + * @param string|bool $secure_cookie Optional. Whether to use secure cookie. + * @return WP_User|WP_Error WP_User on success, WP_Error on failure. + */ + function wp_signon($credentials = array(), $secure_cookie = '') + { + } + /** + * Authenticates a user, confirming the username and password are valid. + * + * @since 2.8.0 + * + * @param WP_User|WP_Error|null $user WP_User or WP_Error object from a previous callback. Default null. + * @param string $username Username for authentication. + * @param string $password Password for authentication. + * @return WP_User|WP_Error WP_User on success, WP_Error on failure. + */ + function wp_authenticate_username_password($user, $username, $password) + { + } + /** + * Authenticates a user using the email and password. + * + * @since 4.5.0 + * + * @param WP_User|WP_Error|null $user WP_User or WP_Error object if a previous + * callback failed authentication. + * @param string $email Email address for authentication. + * @param string $password Password for authentication. + * @return WP_User|WP_Error WP_User on success, WP_Error on failure. + */ + function wp_authenticate_email_password($user, $email, $password) + { + } + /** + * Authenticates the user using the WordPress auth cookie. + * + * @since 2.8.0 + * + * @global string $auth_secure_cookie + * + * @param WP_User|WP_Error|null $user WP_User or WP_Error object from a previous callback. Default null. + * @param string $username Username. If not empty, cancels the cookie authentication. + * @param string $password Password. If not empty, cancels the cookie authentication. + * @return WP_User|WP_Error WP_User on success, WP_Error on failure. + */ + function wp_authenticate_cookie($user, $username, $password) + { + } + /** + * Authenticates the user using an application password. + * + * @since 5.6.0 + * + * @param WP_User|WP_Error|null $input_user WP_User or WP_Error object if a previous + * callback failed authentication. + * @param string $username Username for authentication. + * @param string $password Password for authentication. + * @return WP_User|WP_Error|null WP_User on success, WP_Error on failure, null if + * null is passed in and this isn't an API request. + */ + function wp_authenticate_application_password($input_user, $username, $password) + { + } + /** + * Validates the application password credentials passed via Basic Authentication. + * + * @since 5.6.0 + * + * @param int|false $input_user User ID if one has been determined, false otherwise. + * @return int|false The authenticated user ID if successful, false otherwise. + */ + function wp_validate_application_password($input_user) + { + } + /** + * For Multisite blogs, checks if the authenticated user has been marked as a + * spammer, or if the user's primary blog has been marked as spam. + * + * @since 3.7.0 + * + * @param WP_User|WP_Error|null $user WP_User or WP_Error object from a previous callback. Default null. + * @return WP_User|WP_Error WP_User on success, WP_Error if the user is considered a spammer. + */ + function wp_authenticate_spam_check($user) + { + } + /** + * Validates the logged-in cookie. + * + * Checks the logged-in cookie if the previous auth cookie could not be + * validated and parsed. + * + * This is a callback for the {@see 'determine_current_user'} filter, rather than API. + * + * @since 3.9.0 + * + * @param int|false $user_id The user ID (or false) as received from + * the `determine_current_user` filter. + * @return int|false User ID if validated, false otherwise. If a user ID from + * an earlier filter callback is received, that value is returned. + */ + function wp_validate_logged_in_cookie($user_id) + { + } + /** + * Gets the number of posts a user has written. + * + * @since 3.0.0 + * @since 4.1.0 Added `$post_type` argument. + * @since 4.3.0 Added `$public_only` argument. Added the ability to pass an array + * of post types to `$post_type`. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $userid User ID. + * @param array|string $post_type Optional. Single post type or array of post types to count the number of posts for. Default 'post'. + * @param bool $public_only Optional. Whether to only return counts for public posts. Default false. + * @return string Number of posts the user has written in this post type. + */ + function count_user_posts($userid, $post_type = 'post', $public_only = \false) + { + } + /** + * Gets the number of posts written by a list of users. + * + * @since 3.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int[] $users Array of user IDs. + * @param string|string[] $post_type Optional. Single post type or array of post types to check. Defaults to 'post'. + * @param bool $public_only Optional. Only return counts for public posts. Defaults to false. + * @return string[] Amount of posts each user has written, as strings, keyed by user ID. + */ + function count_many_users_posts($users, $post_type = 'post', $public_only = \false) + { + } + // + // User option functions. + // + /** + * Gets the current user's ID. + * + * @since MU (3.0.0) + * + * @return int The current user's ID, or 0 if no user is logged in. + */ + function get_current_user_id() + { + } + /** + * Retrieves user option that can be either per Site or per Network. + * + * If the user ID is not given, then the current user will be used instead. If + * the user ID is given, then the user data will be retrieved. The filter for + * the result, will also pass the original option name and finally the user data + * object as the third parameter. + * + * The option will first check for the per site name and then the per Network name. + * + * @since 2.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $option User option name. + * @param int $user Optional. User ID. + * @param string $deprecated Use get_option() to check for an option in the options table. + * @return mixed User option value on success, false on failure. + */ + function get_user_option($option, $user = 0, $deprecated = '') + { + } + /** + * Updates user option with global blog capability. + * + * User options are just like user metadata except that they have support for + * global blog options. If the 'global' parameter is false, which it is by default + * it will prepend the WordPress table prefix to the option name. + * + * Deletes the user option if $newvalue is empty. + * + * @since 2.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $user_id User ID. + * @param string $option_name User option name. + * @param mixed $newvalue User option value. + * @param bool $global Optional. Whether option name is global or blog specific. + * Default false (blog specific). + * @return int|bool User meta ID if the option didn't exist, true on successful update, + * false on failure. + */ + function update_user_option($user_id, $option_name, $newvalue, $global = \false) + { + } + /** + * Deletes user option with global blog capability. + * + * User options are just like user metadata except that they have support for + * global blog options. If the 'global' parameter is false, which it is by default + * it will prepend the WordPress table prefix to the option name. + * + * @since 3.0.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $user_id User ID + * @param string $option_name User option name. + * @param bool $global Optional. Whether option name is global or blog specific. + * Default false (blog specific). + * @return bool True on success, false on failure. + */ + function delete_user_option($user_id, $option_name, $global = \false) + { + } + /** + * Retrieves list of users matching criteria. + * + * @since 3.1.0 + * + * @see WP_User_Query + * + * @param array $args Optional. Arguments to retrieve users. See WP_User_Query::prepare_query() + * for more information on accepted arguments. + * @return array List of users. + * @phpstan-param array{ + * blog_id?: int, + * role?: string|string[], + * role__in?: string[], + * role__not_in?: string[], + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * capability?: string|string[], + * capability__in?: string[], + * capability__not_in?: string[], + * include?: int[], + * exclude?: int[], + * search?: string, + * search_columns?: string[], + * orderby?: string|array, + * order?: string, + * offset?: int, + * number?: int, + * paged?: int, + * count_total?: bool, + * fields?: string|string[], + * who?: string, + * has_published_posts?: bool|string[], + * nicename?: string, + * nicename__in?: string[], + * nicename__not_in?: string[], + * login?: string, + * login__in?: string[], + * login__not_in?: string[], + * } $args See WP_User_Query::prepare_query() + */ + function get_users($args = array()) + { + } + /** + * Lists all the users of the site, with several options available. + * + * @since 5.9.0 + * + * @param string|array $args { + * Optional. Array or string of default arguments. + * + * @type string $orderby How to sort the users. Accepts 'nicename', 'email', 'url', 'registered', + * 'user_nicename', 'user_email', 'user_url', 'user_registered', 'name', + * 'display_name', 'post_count', 'ID', 'meta_value', 'user_login'. Default 'name'. + * @type string $order Sorting direction for $orderby. Accepts 'ASC', 'DESC'. Default 'ASC'. + * @type int $number Maximum users to return or display. Default empty (all users). + * @type bool $exclude_admin Whether to exclude the 'admin' account, if it exists. Default false. + * @type bool $show_fullname Whether to show the user's full name. Default false. + * @type string $feed If not empty, show a link to the user's feed and use this text as the alt + * parameter of the link. Default empty. + * @type string $feed_image If not empty, show a link to the user's feed and use this image URL as + * clickable anchor. Default empty. + * @type string $feed_type The feed type to link to, such as 'rss2'. Defaults to default feed type. + * @type bool $echo Whether to output the result or instead return it. Default true. + * @type string $style If 'list', each user is wrapped in an `<li>` element, otherwise the users + * will be separated by commas. + * @type bool $html Whether to list the items in HTML form or plaintext. Default true. + * @type string $exclude An array, comma-, or space-separated list of user IDs to exclude. Default empty. + * @type string $include An array, comma-, or space-separated list of user IDs to include. Default empty. + * } + * @return string|null The output if echo is false. Otherwise null. + * @phpstan-param array{ + * orderby?: string, + * order?: string, + * number?: int, + * exclude_admin?: bool, + * show_fullname?: bool, + * feed?: string, + * feed_image?: string, + * feed_type?: string, + * echo?: bool, + * style?: string, + * html?: bool, + * exclude?: string, + * include?: string, + * } $args + */ + function wp_list_users($args = array()) + { + } + /** + * Gets the sites a user belongs to. + * + * @since 3.0.0 + * @since 4.7.0 Converted to use `get_sites()`. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $user_id User ID + * @param bool $all Whether to retrieve all sites, or only sites that are not + * marked as deleted, archived, or spam. + * @return object[] A list of the user's sites. An empty array if the user doesn't exist + * or belongs to no sites. + */ + function get_blogs_of_user($user_id, $all = \false) + { + } + /** + * Finds out whether a user is a member of a given blog. + * + * @since MU (3.0.0) + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param int $user_id Optional. The unique ID of the user. Defaults to the current user. + * @param int $blog_id Optional. ID of the blog to check. Defaults to the current site. + * @return bool + */ + function is_user_member_of_blog($user_id = 0, $blog_id = 0) + { + } + /** + * Adds meta data to a user. + * + * @since 3.0.0 + * + * @param int $user_id User ID. + * @param string $meta_key Metadata name. + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. + * @param bool $unique Optional. Whether the same key should not be added. + * Default false. + * @return int|false Meta ID on success, false on failure. + */ + function add_user_meta($user_id, $meta_key, $meta_value, $unique = \false) + { + } + /** + * Removes metadata matching criteria from a user. + * + * You can match based on the key, or key and value. Removing based on key and + * value, will keep from removing duplicate metadata with the same key. It also + * allows removing all metadata matching key, if needed. + * + * @since 3.0.0 + * + * @link https://developer.wordpress.org/reference/functions/delete_user_meta/ + * + * @param int $user_id User ID + * @param string $meta_key Metadata name. + * @param mixed $meta_value Optional. Metadata value. If provided, + * rows will only be removed that match the value. + * Must be serializable if non-scalar. Default empty. + * @return bool True on success, false on failure. + */ + function delete_user_meta($user_id, $meta_key, $meta_value = '') + { + } + /** + * Retrieves user meta field for a user. + * + * @since 3.0.0 + * + * @link https://developer.wordpress.org/reference/functions/get_user_meta/ + * + * @param int $user_id User ID. + * @param string $key Optional. The meta key to retrieve. By default, + * returns data for all keys. + * @param bool $single Optional. Whether to return a single value. + * This parameter has no effect if `$key` is not specified. + * Default false. + * @return mixed An array of values if `$single` is false. + * The value of meta data field if `$single` is true. + * False for an invalid `$user_id` (non-numeric, zero, or negative value). + * An empty string if a valid but non-existing user ID is passed. + */ + function get_user_meta($user_id, $key = '', $single = \false) + { + } + /** + * Updates user meta field based on user ID. + * + * Use the $prev_value parameter to differentiate between meta fields with the + * same key and user ID. + * + * If the meta field for the user does not exist, it will be added. + * + * @since 3.0.0 + * + * @link https://developer.wordpress.org/reference/functions/update_user_meta/ + * + * @param int $user_id User ID. + * @param string $meta_key Metadata key. + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. + * @param mixed $prev_value Optional. Previous value to check before updating. + * If specified, only update existing metadata entries with + * this value. Otherwise, update all entries. Default empty. + * @return int|bool Meta ID if the key didn't exist, true on successful update, + * false on failure or if the value passed to the function + * is the same as the one that is already in the database. + */ + function update_user_meta($user_id, $meta_key, $meta_value, $prev_value = '') + { + } + /** + * Counts number of users who have each of the user roles. + * + * Assumes there are neither duplicated nor orphaned capabilities meta_values. + * Assumes role names are unique phrases. Same assumption made by WP_User_Query::prepare_query() + * Using $strategy = 'time' this is CPU-intensive and should handle around 10^7 users. + * Using $strategy = 'memory' this is memory-intensive and should handle around 10^5 users, but see WP Bug #12257. + * + * @since 3.0.0 + * @since 4.4.0 The number of users with no role is now included in the `none` element. + * @since 4.9.0 The `$site_id` parameter was added to support multisite. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $strategy Optional. The computational strategy to use when counting the users. + * Accepts either 'time' or 'memory'. Default 'time'. + * @param int|null $site_id Optional. The site ID to count users for. Defaults to the current site. + * @return array { + * User counts. + * + * @type int $total_users Total number of users on the site. + * @type int[] $avail_roles Array of user counts keyed by user role. + * } + * @phpstan-return array{ + * total_users: int, + * avail_roles: int[], + * } + */ + function count_users($strategy = 'time', $site_id = \null) + { + } + /** + * Returns the number of active users in your installation. + * + * Note that on a large site the count may be cached and only updated twice daily. + * + * @since MU (3.0.0) + * @since 4.8.0 The `$network_id` parameter has been added. + * @since 6.0.0 Moved to wp-includes/user.php. + * + * @param int|null $network_id ID of the network. Defaults to the current network. + * @return int Number of active users on the network. + */ + function get_user_count($network_id = \null) + { + } + /** + * Updates the total count of users on the site if live user counting is enabled. + * + * @since 6.0.0 + * + * @param int|null $network_id ID of the network. Defaults to the current network. + * @return bool Whether the update was successful. + */ + function wp_maybe_update_user_counts($network_id = \null) + { + } + /** + * Updates the total count of users on the site. + * + * @global wpdb $wpdb WordPress database abstraction object. + * @since 6.0.0 + * + * @param int|null $network_id ID of the network. Defaults to the current network. + * @return bool Whether the update was successful. + */ + function wp_update_user_counts($network_id = \null) + { + } + /** + * Schedules a recurring recalculation of the total count of users. + * + * @since 6.0.0 + */ + function wp_schedule_update_user_counts() + { + } + /** + * Determines whether the site has a large number of users. + * + * The default criteria for a large site is more than 10,000 users. + * + * @since 6.0.0 + * + * @param int|null $network_id ID of the network. Defaults to the current network. + * @return bool Whether the site has a large number of users. + */ + function wp_is_large_user_count($network_id = \null) + { + } + // + // Private helper functions. + // + /** + * Sets up global user vars. + * + * Used by wp_set_current_user() for back compat. Might be deprecated in the future. + * + * @since 2.0.4 + * + * @global string $user_login The user username for logging in + * @global WP_User $userdata User data. + * @global int $user_level The level of the user + * @global int $user_ID The ID of the user + * @global string $user_email The email address of the user + * @global string $user_url The url in the user's profile + * @global string $user_identity The display name of the user + * + * @param int $for_user_id Optional. User ID to set up global data. Default 0. + */ + function setup_userdata($for_user_id = 0) + { + } + /** + * Creates dropdown HTML content of users. + * + * The content can either be displayed, which it is by default or retrieved by + * setting the 'echo' argument. The 'include' and 'exclude' arguments do not + * need to be used; all users will be displayed in that case. Only one can be + * used, either 'include' or 'exclude', but not both. + * + * The available arguments are as follows: + * + * @since 2.3.0 + * @since 4.5.0 Added the 'display_name_with_login' value for 'show'. + * @since 4.7.0 Added the `$role`, `$role__in`, and `$role__not_in` parameters. + * + * @param array|string $args { + * Optional. Array or string of arguments to generate a drop-down of users. + * See WP_User_Query::prepare_query() for additional available arguments. + * + * @type string $show_option_all Text to show as the drop-down default (all). + * Default empty. + * @type string $show_option_none Text to show as the drop-down default when no + * users were found. Default empty. + * @type int|string $option_none_value Value to use for $show_option_non when no users + * were found. Default -1. + * @type string $hide_if_only_one_author Whether to skip generating the drop-down + * if only one user was found. Default empty. + * @type string $orderby Field to order found users by. Accepts user fields. + * Default 'display_name'. + * @type string $order Whether to order users in ascending or descending + * order. Accepts 'ASC' (ascending) or 'DESC' (descending). + * Default 'ASC'. + * @type int[]|string $include Array or comma-separated list of user IDs to include. + * Default empty. + * @type int[]|string $exclude Array or comma-separated list of user IDs to exclude. + * Default empty. + * @type bool|int $multi Whether to skip the ID attribute on the 'select' element. + * Accepts 1|true or 0|false. Default 0|false. + * @type string $show User data to display. If the selected item is empty + * then the 'user_login' will be displayed in parentheses. + * Accepts any user field, or 'display_name_with_login' to show + * the display name with user_login in parentheses. + * Default 'display_name'. + * @type int|bool $echo Whether to echo or return the drop-down. Accepts 1|true (echo) + * or 0|false (return). Default 1|true. + * @type int $selected Which user ID should be selected. Default 0. + * @type bool $include_selected Whether to always include the selected user ID in the drop- + * down. Default false. + * @type string $name Name attribute of select element. Default 'user'. + * @type string $id ID attribute of the select element. Default is the value of $name. + * @type string $class Class attribute of the select element. Default empty. + * @type int $blog_id ID of blog (Multisite only). Default is ID of the current blog. + * @type string $who Which type of users to query. Accepts only an empty string or + * 'authors'. Default empty. + * @type string|array $role An array or a comma-separated list of role names that users must + * match to be included in results. Note that this is an inclusive + * list: users must match *each* role. Default empty. + * @type string[] $role__in An array of role names. Matched users must have at least one of + * these roles. Default empty array. + * @type string[] $role__not_in An array of role names to exclude. Users matching one or more of + * these roles will not be included in results. Default empty array. + * } + * @return string HTML dropdown list of users. + * @phpstan-param array{ + * show_option_all?: string, + * show_option_none?: string, + * option_none_value?: int|string, + * hide_if_only_one_author?: string, + * orderby?: string, + * order?: string, + * include?: int[]|string, + * exclude?: int[]|string, + * multi?: bool|int, + * show?: string, + * echo?: int|bool, + * selected?: int, + * include_selected?: bool, + * name?: string, + * id?: string, + * class?: string, + * blog_id?: int, + * who?: string, + * role?: string|array, + * role__in?: string[], + * role__not_in?: string[], + * blog_id?: int, + * role?: string|string[], + * role__in?: string[], + * role__not_in?: string[], + * meta_key?: string|string[], + * meta_value?: string|string[], + * meta_compare?: string, + * meta_compare_key?: string, + * meta_type?: string, + * meta_type_key?: string, + * meta_query?: array, + * capability?: string|string[], + * capability__in?: string[], + * capability__not_in?: string[], + * include?: int[], + * exclude?: int[], + * search?: string, + * search_columns?: string[], + * orderby?: string|array, + * order?: string, + * offset?: int, + * number?: int, + * paged?: int, + * count_total?: bool, + * fields?: string|string[], + * who?: string, + * has_published_posts?: bool|string[], + * nicename?: string, + * nicename__in?: string[], + * nicename__not_in?: string[], + * login?: string, + * login__in?: string[], + * login__not_in?: string[], + * } $args + */ + function wp_dropdown_users($args = '') + { + } + /** + * Sanitizes user field based on context. + * + * Possible context values are: 'raw', 'edit', 'db', 'display', 'attribute' and 'js'. The + * 'display' context is used by default. 'attribute' and 'js' contexts are treated like 'display' + * when calling filters. + * + * @since 2.3.0 + * + * @param string $field The user Object field name. + * @param mixed $value The user Object value. + * @param int $user_id User ID. + * @param string $context How to sanitize user fields. Looks for 'raw', 'edit', 'db', 'display', + * 'attribute' and 'js'. + * @return mixed Sanitized value. + */ + function sanitize_user_field($field, $value, $user_id, $context) + { + } + /** + * Updates all user caches. + * + * @since 3.0.0 + * + * @param object|WP_User $user User object or database row to be cached + * @return void|false Void on success, false on failure. + */ + function update_user_caches($user) + { + } + /** + * Cleans all user caches. + * + * @since 3.0.0 + * @since 4.4.0 'clean_user_cache' action was added. + * + * @param WP_User|int $user User object or ID to be cleaned from the cache + */ + function clean_user_cache($user) + { + } + /** + * Determines whether the given username exists. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.0.0 + * + * @param string $username The username to check for existence. + * @return int|false The user ID on success, false on failure. + */ + function username_exists($username) + { + } + /** + * Determines whether the given email exists. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.1.0 + * + * @param string $email The email to check for existence. + * @return int|false The user ID on success, false on failure. + */ + function email_exists($email) + { + } + /** + * Checks whether a username is valid. + * + * @since 2.0.1 + * @since 4.4.0 Empty sanitized usernames are now considered invalid. + * + * @param string $username Username. + * @return bool Whether username given is valid. + */ + function validate_username($username) + { + } + /** + * Inserts a user into the database. + * + * Most of the `$userdata` array fields have filters associated with the values. Exceptions are + * 'ID', 'rich_editing', 'syntax_highlighting', 'comment_shortcuts', 'admin_color', 'use_ssl', + * 'user_registered', 'user_activation_key', 'spam', and 'role'. The filters have the prefix + * 'pre_user_' followed by the field name. An example using 'description' would have the filter + * called 'pre_user_description' that can be hooked into. + * + * @since 2.0.0 + * @since 3.6.0 The `aim`, `jabber`, and `yim` fields were removed as default user contact + * methods for new installations. See wp_get_user_contact_methods(). + * @since 4.7.0 The `locale` field can be passed to `$userdata`. + * @since 5.3.0 The `user_activation_key` field can be passed to `$userdata`. + * @since 5.3.0 The `spam` field can be passed to `$userdata` (Multisite only). + * @since 5.9.0 The `meta_input` field can be passed to `$userdata` to allow addition of user meta data. + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array|object|WP_User $userdata { + * An array, object, or WP_User object of user data arguments. + * + * @type int $ID User ID. If supplied, the user will be updated. + * @type string $user_pass The plain-text user password. + * @type string $user_login The user's login username. + * @type string $user_nicename The URL-friendly user name. + * @type string $user_url The user URL. + * @type string $user_email The user email address. + * @type string $display_name The user's display name. + * Default is the user's username. + * @type string $nickname The user's nickname. + * Default is the user's username. + * @type string $first_name The user's first name. For new users, will be used + * to build the first part of the user's display name + * if `$display_name` is not specified. + * @type string $last_name The user's last name. For new users, will be used + * to build the second part of the user's display name + * if `$display_name` is not specified. + * @type string $description The user's biographical description. + * @type string $rich_editing Whether to enable the rich-editor for the user. + * Accepts 'true' or 'false' as a string literal, + * not boolean. Default 'true'. + * @type string $syntax_highlighting Whether to enable the rich code editor for the user. + * Accepts 'true' or 'false' as a string literal, + * not boolean. Default 'true'. + * @type string $comment_shortcuts Whether to enable comment moderation keyboard + * shortcuts for the user. Accepts 'true' or 'false' + * as a string literal, not boolean. Default 'false'. + * @type string $admin_color Admin color scheme for the user. Default 'fresh'. + * @type bool $use_ssl Whether the user should always access the admin over + * https. Default false. + * @type string $user_registered Date the user registered in UTC. Format is 'Y-m-d H:i:s'. + * @type string $user_activation_key Password reset key. Default empty. + * @type bool $spam Multisite only. Whether the user is marked as spam. + * Default false. + * @type string $show_admin_bar_front Whether to display the Admin Bar for the user + * on the site's front end. Accepts 'true' or 'false' + * as a string literal, not boolean. Default 'true'. + * @type string $role User's role. + * @type string $locale User's locale. Default empty. + * @type array $meta_input Array of custom user meta values keyed by meta key. + * Default empty. + * } + * @return int|WP_Error The newly created user's ID or a WP_Error object if the user could not + * be created. + * @phpstan-param object|\WP_User|array{ + * ID?: int, + * user_pass?: string, + * user_login?: string, + * user_nicename?: string, + * user_url?: string, + * user_email?: string, + * display_name?: string, + * nickname?: string, + * first_name?: string, + * last_name?: string, + * description?: string, + * rich_editing?: string, + * syntax_highlighting?: string, + * comment_shortcuts?: string, + * admin_color?: string, + * use_ssl?: bool, + * user_registered?: string, + * user_activation_key?: string, + * spam?: bool, + * show_admin_bar_front?: string, + * role?: string, + * locale?: string, + * meta_input?: array, + * } $userdata + */ + function wp_insert_user($userdata) + { + } + /** + * Updates a user in the database. + * + * It is possible to update a user's password by specifying the 'user_pass' + * value in the $userdata parameter array. + * + * If current user's password is being updated, then the cookies will be + * cleared. + * + * @since 2.0.0 + * + * @see wp_insert_user() For what fields can be set in $userdata. + * + * @param array|object|WP_User $userdata An array of user data or a user object of type stdClass or WP_User. + * @return int|WP_Error The updated user's ID or a WP_Error object if the user could not be updated. + */ + function wp_update_user($userdata) + { + } + /** + * Provides a simpler way of inserting a user into the database. + * + * Creates a new user with just the username, password, and email. For more + * complex user creation use wp_insert_user() to specify more information. + * + * @since 2.0.0 + * + * @see wp_insert_user() More complete way to create a new user. + * + * @param string $username The user's username. + * @param string $password The user's password. + * @param string $email Optional. The user's email. Default empty. + * @return int|WP_Error The newly created user's ID or a WP_Error object if the user could not + * be created. + */ + function wp_create_user($username, $password, $email = '') + { + } + /** + * Returns a list of meta keys to be (maybe) populated in wp_update_user(). + * + * The list of keys returned via this function are dependent on the presence + * of those keys in the user meta data to be set. + * + * @since 3.3.0 + * @access private + * + * @param WP_User $user WP_User instance. + * @return string[] List of user keys to be populated in wp_update_user(). + */ + function _get_additional_user_keys($user) + { + } + /** + * Sets up the user contact methods. + * + * Default contact methods were removed in 3.6. A filter dictates contact methods. + * + * @since 3.7.0 + * + * @param WP_User|null $user Optional. WP_User object. + * @return string[] Array of contact method labels keyed by contact method. + */ + function wp_get_user_contact_methods($user = \null) + { + } + /** + * The old private function for setting up user contact methods. + * + * Use wp_get_user_contact_methods() instead. + * + * @since 2.9.0 + * @access private + * + * @param WP_User|null $user Optional. WP_User object. Default null. + * @return string[] Array of contact method labels keyed by contact method. + */ + function _wp_get_user_contactmethods($user = \null) + { + } + /** + * Gets the text suggesting how to create strong passwords. + * + * @since 4.1.0 + * + * @return string The password hint text. + */ + function wp_get_password_hint() + { + } + /** + * Creates, stores, then returns a password reset key for user. + * + * @since 4.4.0 + * + * @global PasswordHash $wp_hasher Portable PHP password hashing framework. + * + * @param WP_User $user User to retrieve password reset key for. + * @return string|WP_Error Password reset key on success. WP_Error on error. + */ + function get_password_reset_key($user) + { + } + /** + * Retrieves a user row based on password reset key and login. + * + * A key is considered 'expired' if it exactly matches the value of the + * user_activation_key field, rather than being matched after going through the + * hashing process. This field is now hashed; old values are no longer accepted + * but have a different WP_Error code so good user feedback can be provided. + * + * @since 3.1.0 + * + * @global wpdb $wpdb WordPress database object for queries. + * @global PasswordHash $wp_hasher Portable PHP password hashing framework instance. + * + * @param string $key Hash to validate sending user's password. + * @param string $login The user login. + * @return WP_User|WP_Error WP_User object on success, WP_Error object for invalid or expired keys. + */ + function check_password_reset_key($key, $login) + { + } + /** + * Handles sending a password retrieval email to a user. + * + * @since 2.5.0 + * @since 5.7.0 Added `$user_login` parameter. + * + * @global wpdb $wpdb WordPress database abstraction object. + * @global PasswordHash $wp_hasher Portable PHP password hashing framework. + * + * @param string $user_login Optional. Username to send a password retrieval email for. + * Defaults to `$_POST['user_login']` if not set. + * @return true|WP_Error True when finished, WP_Error object on error. + */ + function retrieve_password($user_login = \null) + { + } + /** + * Handles resetting the user's password. + * + * @since 2.5.0 + * + * @param WP_User $user The user + * @param string $new_pass New password for the user in plaintext + */ + function reset_password($user, $new_pass) + { + } + /** + * Handles registering a new user. + * + * @since 2.5.0 + * + * @param string $user_login User's username for logging in + * @param string $user_email User's email address to send password and add + * @return int|WP_Error Either user's ID or error on failure. + */ + function register_new_user($user_login, $user_email) + { + } + /** + * Initiates email notifications related to the creation of new users. + * + * Notifications are sent both to the site admin and to the newly created user. + * + * @since 4.4.0 + * @since 4.6.0 Converted the `$notify` parameter to accept 'user' for sending + * notifications only to the user created. + * + * @param int $user_id ID of the newly created user. + * @param string $notify Optional. Type of notification that should happen. Accepts 'admin' + * or an empty string (admin only), 'user', or 'both' (admin and user). + * Default 'both'. + */ + function wp_send_new_user_notifications($user_id, $notify = 'both') + { + } + /** + * Retrieves the current session token from the logged_in cookie. + * + * @since 4.0.0 + * + * @return string Token. + */ + function wp_get_session_token() + { + } + /** + * Retrieves a list of sessions for the current user. + * + * @since 4.0.0 + * + * @return array Array of sessions. + */ + function wp_get_all_sessions() + { + } + /** + * Removes the current session token from the database. + * + * @since 4.0.0 + */ + function wp_destroy_current_session() + { + } + /** + * Removes all but the current session token for the current user for the database. + * + * @since 4.0.0 + */ + function wp_destroy_other_sessions() + { + } + /** + * Removes all session tokens for the current user from the database. + * + * @since 4.0.0 + */ + function wp_destroy_all_sessions() + { + } + /** + * Gets the user IDs of all users with no role on this site. + * + * @since 4.4.0 + * @since 4.9.0 The `$site_id` parameter was added to support multisite. + * + * @param int|null $site_id Optional. The site ID to get users with no role for. Defaults to the current site. + * @return string[] Array of user IDs as strings. + */ + function wp_get_users_with_no_role($site_id = \null) + { + } + /** + * Retrieves the current user object. + * + * Will set the current user, if the current user is not set. The current user + * will be set to the logged-in person. If no user is logged-in, then it will + * set the current user to 0, which is invalid and won't have any permissions. + * + * This function is used by the pluggable functions wp_get_current_user() and + * get_currentuserinfo(), the latter of which is deprecated but used for backward + * compatibility. + * + * @since 4.5.0 + * @access private + * + * @see wp_get_current_user() + * @global WP_User $current_user Checks if the current user is set. + * + * @return WP_User Current WP_User instance. + */ + function _wp_get_current_user() + { + } + /** + * Sends a confirmation request email when a change of user email address is attempted. + * + * @since 3.0.0 + * @since 4.9.0 This function was moved from wp-admin/includes/ms.php so it's no longer Multisite specific. + * + * @global WP_Error $errors WP_Error object. + */ + function send_confirmation_on_profile_email() + { + } + /** + * Adds an admin notice alerting the user to check for confirmation request email + * after email address change. + * + * @since 3.0.0 + * @since 4.9.0 This function was moved from wp-admin/includes/ms.php so it's no longer Multisite specific. + * + * @global string $pagenow The filename of the current screen. + */ + function new_user_email_admin_notice() + { + } + /** + * Gets all personal data request types. + * + * @since 4.9.6 + * @access private + * + * @return string[] List of core privacy action types. + */ + function _wp_privacy_action_request_types() + { + } + /** + * Registers the personal data exporter for users. + * + * @since 4.9.6 + * + * @param array[] $exporters An array of personal data exporters. + * @return array[] An array of personal data exporters. + */ + function wp_register_user_personal_data_exporter($exporters) + { + } + /** + * Finds and exports personal data associated with an email address from the user and user_meta table. + * + * @since 4.9.6 + * @since 5.4.0 Added 'Community Events Location' group to the export data. + * @since 5.4.0 Added 'Session Tokens' group to the export data. + * + * @param string $email_address The user's email address. + * @return array An array of personal data. + */ + function wp_user_personal_data_exporter($email_address) + { + } + /** + * Updates log when privacy request is confirmed. + * + * @since 4.9.6 + * @access private + * + * @param int $request_id ID of the request. + */ + function _wp_privacy_account_request_confirmed($request_id) + { + } + /** + * Notifies the site administrator via email when a request is confirmed. + * + * Without this, the admin would have to manually check the site to see if any + * action was needed on their part yet. + * + * @since 4.9.6 + * + * @param int $request_id The ID of the request. + */ + function _wp_privacy_send_request_confirmation_notification($request_id) + { + } + /** + * Notifies the user when their erasure request is fulfilled. + * + * Without this, the user would never know if their data was actually erased. + * + * @since 4.9.6 + * + * @param int $request_id The privacy request post ID associated with this request. + */ + function _wp_privacy_send_erasure_fulfillment_notification($request_id) + { + } + /** + * Returns request confirmation message HTML. + * + * @since 4.9.6 + * @access private + * + * @param int $request_id The request ID being confirmed. + * @return string The confirmation message. + */ + function _wp_privacy_account_request_confirmed_message($request_id) + { + } + /** + * Creates and logs a user request to perform a specific action. + * + * Requests are stored inside a post type named `user_request` since they can apply to both + * users on the site, or guests without a user account. + * + * @since 4.9.6 + * @since 5.7.0 Added the `$status` parameter. + * + * @param string $email_address User email address. This can be the address of a registered + * or non-registered user. + * @param string $action_name Name of the action that is being confirmed. Required. + * @param array $request_data Misc data you want to send with the verification request and pass + * to the actions once the request is confirmed. + * @param string $status Optional request status (pending or confirmed). Default 'pending'. + * @return int|WP_Error Returns the request ID if successful, or a WP_Error object on failure. + */ + function wp_create_user_request($email_address = '', $action_name = '', $request_data = array(), $status = 'pending') + { + } + /** + * Gets action description from the name and return a string. + * + * @since 4.9.6 + * + * @param string $action_name Action name of the request. + * @return string Human readable action name. + */ + function wp_user_request_action_description($action_name) + { + } + /** + * Send a confirmation request email to confirm an action. + * + * If the request is not already pending, it will be updated. + * + * @since 4.9.6 + * + * @param string $request_id ID of the request created via wp_create_user_request(). + * @return true|WP_Error True on success, `WP_Error` on failure. + */ + function wp_send_user_request($request_id) + { + } + /** + * Returns a confirmation key for a user action and stores the hashed version for future comparison. + * + * @since 4.9.6 + * + * @param int $request_id Request ID. + * @return string Confirmation key. + */ + function wp_generate_user_request_key($request_id) + { + } + /** + * Validates a user request by comparing the key with the request's key. + * + * @since 4.9.6 + * + * @param string $request_id ID of the request being confirmed. + * @param string $key Provided key to validate. + * @return true|WP_Error True on success, WP_Error on failure. + */ + function wp_validate_user_request_key($request_id, $key) + { + } + /** + * Returns the user request object for the specified request ID. + * + * @since 4.9.6 + * + * @param int $request_id The ID of the user request. + * @return WP_User_Request|false + */ + function wp_get_user_request($request_id) + { + } + /** + * Checks if Application Passwords is supported. + * + * Application Passwords is supported only by sites using SSL or local environments + * but may be made available using the {@see 'wp_is_application_passwords_available'} filter. + * + * @since 5.9.0 + * + * @return bool + */ + function wp_is_application_passwords_supported() + { + } + /** + * Checks if Application Passwords is globally available. + * + * By default, Application Passwords is available to all sites using SSL or to local environments. + * Use the {@see 'wp_is_application_passwords_available'} filter to adjust its availability. + * + * @since 5.6.0 + * + * @return bool + */ + function wp_is_application_passwords_available() + { + } + /** + * Checks if Application Passwords is available for a specific user. + * + * By default all users can use Application Passwords. Use {@see 'wp_is_application_passwords_available_for_user'} + * to restrict availability to certain users. + * + * @since 5.6.0 + * + * @param int|WP_User $user The user to check. + * @return bool + */ + function wp_is_application_passwords_available_for_user($user) + { + } + /** + * Registers the user meta property for persisted preferences. + * + * This property is used to store user preferences across page reloads and is + * currently used by the block editor for preferences like 'fullscreenMode' and + * 'fixedToolbar'. + * + * @since 6.1.0 + * @access private + * + * @global wpdb $wpdb WordPress database abstraction object. + */ + function wp_register_persisted_preferences_meta() + { + } + /** + * Test if the current browser runs on a mobile device (smart phone, tablet, etc.) + * + * @since 3.4.0 + * + * @return bool + */ + function wp_is_mobile() + { + } + // + // Template tags & API functions. + // + /** + * Register a widget + * + * Registers a WP_Widget widget + * + * @since 2.8.0 + * @since 4.6.0 Updated the `$widget` parameter to also accept a WP_Widget instance object + * instead of simply a `WP_Widget` subclass name. + * + * @see WP_Widget + * + * @global WP_Widget_Factory $wp_widget_factory + * + * @param string|WP_Widget $widget Either the name of a `WP_Widget` subclass or an instance of a `WP_Widget` subclass. + */ + function register_widget($widget) + { + } + /** + * Unregisters a widget. + * + * Unregisters a WP_Widget widget. Useful for un-registering default widgets. + * Run within a function hooked to the {@see 'widgets_init'} action. + * + * @since 2.8.0 + * @since 4.6.0 Updated the `$widget` parameter to also accept a WP_Widget instance object + * instead of simply a `WP_Widget` subclass name. + * + * @see WP_Widget + * + * @global WP_Widget_Factory $wp_widget_factory + * + * @param string|WP_Widget $widget Either the name of a `WP_Widget` subclass or an instance of a `WP_Widget` subclass. + */ + function unregister_widget($widget) + { + } + /** + * Creates multiple sidebars. + * + * If you wanted to quickly create multiple sidebars for a theme or internally. + * This function will allow you to do so. If you don't pass the 'name' and/or + * 'id' in `$args`, then they will be built for you. + * + * @since 2.2.0 + * + * @see register_sidebar() The second parameter is documented by register_sidebar() and is the same here. + * + * @global array $wp_registered_sidebars The new sidebars are stored in this array by sidebar ID. + * + * @param int $number Optional. Number of sidebars to create. Default 1. + * @param array|string $args { + * Optional. Array or string of arguments for building a sidebar. + * + * @type string $id The base string of the unique identifier for each sidebar. If provided, and multiple + * sidebars are being defined, the ID will have "-2" appended, and so on. + * Default 'sidebar-' followed by the number the sidebar creation is currently at. + * @type string $name The name or title for the sidebars displayed in the admin dashboard. If registering + * more than one sidebar, include '%d' in the string as a placeholder for the uniquely + * assigned number for each sidebar. + * Default 'Sidebar' for the first sidebar, otherwise 'Sidebar %d'. + * } + * @phpstan-param array{ + * id?: string, + * name?: string, + * } $args + */ + function register_sidebars($number = 1, $args = array()) + { + } + /** + * Builds the definition for a single sidebar and returns the ID. + * + * Accepts either a string or an array and then parses that against a set + * of default arguments for the new sidebar. WordPress will automatically + * generate a sidebar ID and name based on the current number of registered + * sidebars if those arguments are not included. + * + * When allowing for automatic generation of the name and ID parameters, keep + * in mind that the incrementor for your sidebar can change over time depending + * on what other plugins and themes are installed. + * + * If theme support for 'widgets' has not yet been added when this function is + * called, it will be automatically enabled through the use of add_theme_support() + * + * @since 2.2.0 + * @since 5.6.0 Added the `before_sidebar` and `after_sidebar` arguments. + * @since 5.9.0 Added the `show_in_rest` argument. + * + * @global array $wp_registered_sidebars Registered sidebars. + * + * @param array|string $args { + * Optional. Array or string of arguments for the sidebar being registered. + * + * @type string $name The name or title of the sidebar displayed in the Widgets + * interface. Default 'Sidebar $instance'. + * @type string $id The unique identifier by which the sidebar will be called. + * Default 'sidebar-$instance'. + * @type string $description Description of the sidebar, displayed in the Widgets interface. + * Default empty string. + * @type string $class Extra CSS class to assign to the sidebar in the Widgets interface. + * Default empty. + * @type string $before_widget HTML content to prepend to each widget's HTML output when assigned + * to this sidebar. Receives the widget's ID attribute as `%1$s` + * and class name as `%2$s`. Default is an opening list item element. + * @type string $after_widget HTML content to append to each widget's HTML output when assigned + * to this sidebar. Default is a closing list item element. + * @type string $before_title HTML content to prepend to the sidebar title when displayed. + * Default is an opening h2 element. + * @type string $after_title HTML content to append to the sidebar title when displayed. + * Default is a closing h2 element. + * @type string $before_sidebar HTML content to prepend to the sidebar when displayed. + * Receives the `$id` argument as `%1$s` and `$class` as `%2$s`. + * Outputs after the {@see 'dynamic_sidebar_before'} action. + * Default empty string. + * @type string $after_sidebar HTML content to append to the sidebar when displayed. + * Outputs before the {@see 'dynamic_sidebar_after'} action. + * Default empty string. + * @type bool $show_in_rest Whether to show this sidebar publicly in the REST API. + * Defaults to only showing the sidebar to administrator users. + * } + * @return string Sidebar ID added to $wp_registered_sidebars global. + * @phpstan-param array{ + * name?: string, + * id?: string, + * description?: string, + * class?: string, + * before_widget?: string, + * after_widget?: string, + * before_title?: string, + * after_title?: string, + * before_sidebar?: string, + * after_sidebar?: string, + * show_in_rest?: bool, + * } $args + */ + function register_sidebar($args = array()) + { + } + /** + * Removes a sidebar from the list. + * + * @since 2.2.0 + * + * @global array $wp_registered_sidebars Registered sidebars. + * + * @param string|int $sidebar_id The ID of the sidebar when it was registered. + */ + function unregister_sidebar($sidebar_id) + { + } + /** + * Checks if a sidebar is registered. + * + * @since 4.4.0 + * + * @global array $wp_registered_sidebars Registered sidebars. + * + * @param string|int $sidebar_id The ID of the sidebar when it was registered. + * @return bool True if the sidebar is registered, false otherwise. + */ + function is_registered_sidebar($sidebar_id) + { + } + /** + * Register an instance of a widget. + * + * The default widget option is 'classname' that can be overridden. + * + * The function can also be used to un-register widgets when `$output_callback` + * parameter is an empty string. + * + * @since 2.2.0 + * @since 5.3.0 Formalized the existing and already documented `...$params` parameter + * by adding it to the function signature. + * @since 5.8.0 Added show_instance_in_rest option. + * + * @global array $wp_registered_widgets Uses stored registered widgets. + * @global array $wp_registered_widget_controls Stores the registered widget controls (options). + * @global array $wp_registered_widget_updates + * @global array $_wp_deprecated_widgets_callbacks + * + * @param int|string $id Widget ID. + * @param string $name Widget display title. + * @param callable $output_callback Run when widget is called. + * @param array $options { + * Optional. An array of supplementary widget options for the instance. + * + * @type string $classname Class name for the widget's HTML container. Default is a shortened + * version of the output callback name. + * @type string $description Widget description for display in the widget administration + * panel and/or theme. + * @type bool $show_instance_in_rest Whether to show the widget's instance settings in the REST API. + * Only available for WP_Widget based widgets. + * } + * @param mixed ...$params Optional additional parameters to pass to the callback function when it's called. + * @phpstan-param array{ + * classname?: string, + * description?: string, + * show_instance_in_rest?: bool, + * } $options + */ + function wp_register_sidebar_widget($id, $name, $output_callback, $options = array(), ...$params) + { + } + /** + * Retrieve description for widget. + * + * When registering widgets, the options can also include 'description' that + * describes the widget for display on the widget administration panel or + * in the theme. + * + * @since 2.5.0 + * + * @global array $wp_registered_widgets + * + * @param int|string $id Widget ID. + * @return string|void Widget description, if available. + */ + function wp_widget_description($id) + { + } + /** + * Retrieve description for a sidebar. + * + * When registering sidebars a 'description' parameter can be included that + * describes the sidebar for display on the widget administration panel. + * + * @since 2.9.0 + * + * @global array $wp_registered_sidebars Registered sidebars. + * + * @param string $id sidebar ID. + * @return string|void Sidebar description, if available. + */ + function wp_sidebar_description($id) + { + } + /** + * Remove widget from sidebar. + * + * @since 2.2.0 + * + * @param int|string $id Widget ID. + */ + function wp_unregister_sidebar_widget($id) + { + } + /** + * Registers widget control callback for customizing options. + * + * @since 2.2.0 + * @since 5.3.0 Formalized the existing and already documented `...$params` parameter + * by adding it to the function signature. + * + * @global array $wp_registered_widget_controls + * @global array $wp_registered_widget_updates + * @global array $wp_registered_widgets + * @global array $_wp_deprecated_widgets_callbacks + * + * @param int|string $id Sidebar ID. + * @param string $name Sidebar display name. + * @param callable $control_callback Run when sidebar is displayed. + * @param array $options { + * Optional. Array or string of control options. Default empty array. + * + * @type int $height Never used. Default 200. + * @type int $width Width of the fully expanded control form (but try hard to use the default width). + * Default 250. + * @type int|string $id_base Required for multi-widgets, i.e widgets that allow multiple instances such as the + * text widget. The widget ID will end up looking like `{$id_base}-{$unique_number}`. + * } + * @param mixed ...$params Optional additional parameters to pass to the callback function when it's called. + * @phpstan-param array{ + * height?: int, + * width?: int, + * id_base?: int|string, + * } $options + */ + function wp_register_widget_control($id, $name, $control_callback, $options = array(), ...$params) + { + } + /** + * Registers the update callback for a widget. + * + * @since 2.8.0 + * @since 5.3.0 Formalized the existing and already documented `...$params` parameter + * by adding it to the function signature. + * + * @global array $wp_registered_widget_updates + * + * @param string $id_base The base ID of a widget created by extending WP_Widget. + * @param callable $update_callback Update callback method for the widget. + * @param array $options Optional. Widget control options. See wp_register_widget_control(). + * Default empty array. + * @param mixed ...$params Optional additional parameters to pass to the callback function when it's called. + * @phpstan-param array{ + * height?: int, + * width?: int, + * id_base?: int|string, + * } $options See wp_register_widget_control() + */ + function _register_widget_update_callback($id_base, $update_callback, $options = array(), ...$params) + { + } + /** + * Registers the form callback for a widget. + * + * @since 2.8.0 + * @since 5.3.0 Formalized the existing and already documented `...$params` parameter + * by adding it to the function signature. + * + * @global array $wp_registered_widget_controls + * + * @param int|string $id Widget ID. + * @param string $name Name attribute for the widget. + * @param callable $form_callback Form callback. + * @param array $options Optional. Widget control options. See wp_register_widget_control(). + * Default empty array. + * @param mixed ...$params Optional additional parameters to pass to the callback function when it's called. + * @phpstan-param array{ + * height?: int, + * width?: int, + * id_base?: int|string, + * } $options See wp_register_widget_control() + */ + function _register_widget_form_callback($id, $name, $form_callback, $options = array(), ...$params) + { + } + /** + * Remove control callback for widget. + * + * @since 2.2.0 + * + * @param int|string $id Widget ID. + */ + function wp_unregister_widget_control($id) + { + } + /** + * Display dynamic sidebar. + * + * By default this displays the default sidebar or 'sidebar-1'. If your theme specifies the 'id' or + * 'name' parameter for its registered sidebars you can pass an ID or name as the $index parameter. + * Otherwise, you can pass in a numerical index to display the sidebar at that index. + * + * @since 2.2.0 + * + * @global array $wp_registered_sidebars Registered sidebars. + * @global array $wp_registered_widgets Registered widgets. + * + * @param int|string $index Optional. Index, name or ID of dynamic sidebar. Default 1. + * @return bool True, if widget sidebar was found and called. False if not found or not called. + */ + function dynamic_sidebar($index = 1) + { + } + /** + * Determines whether a given widget is displayed on the front end. + * + * Either $callback or $id_base can be used + * $id_base is the first argument when extending WP_Widget class + * Without the optional $widget_id parameter, returns the ID of the first sidebar + * in which the first instance of the widget with the given callback or $id_base is found. + * With the $widget_id parameter, returns the ID of the sidebar where + * the widget with that callback/$id_base AND that ID is found. + * + * NOTE: $widget_id and $id_base are the same for single widgets. To be effective + * this function has to run after widgets have initialized, at action {@see 'init'} or later. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.2.0 + * + * @global array $wp_registered_widgets + * + * @param callable|false $callback Optional. Widget callback to check. Default false. + * @param string|false $widget_id Optional. Widget ID. Optional, but needed for checking. + * Default false. + * @param string|false $id_base Optional. The base ID of a widget created by extending WP_Widget. + * Default false. + * @param bool $skip_inactive Optional. Whether to check in 'wp_inactive_widgets'. + * Default true. + * @return string|false ID of the sidebar in which the widget is active, + * false if the widget is not active. + */ + function is_active_widget($callback = \false, $widget_id = \false, $id_base = \false, $skip_inactive = \true) + { + } + /** + * Determines whether the dynamic sidebar is enabled and used by the theme. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.2.0 + * + * @global array $wp_registered_widgets Registered widgets. + * @global array $wp_registered_sidebars Registered sidebars. + * + * @return bool True if using widgets, false otherwise. + */ + function is_dynamic_sidebar() + { + } + /** + * Determines whether a sidebar contains widgets. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 2.8.0 + * + * @param string|int $index Sidebar name, id or number to check. + * @return bool True if the sidebar has widgets, false otherwise. + */ + function is_active_sidebar($index) + { + } + // + // Internal Functions. + // + /** + * Retrieve full list of sidebars and their widget instance IDs. + * + * Will upgrade sidebar widget list, if needed. Will also save updated list, if + * needed. + * + * @since 2.2.0 + * @access private + * + * @global array $_wp_sidebars_widgets + * @global array $sidebars_widgets + * + * @param bool $deprecated Not used (argument deprecated). + * @return array Upgraded list of widgets to version 3 array format when called from the admin. + */ + function wp_get_sidebars_widgets($deprecated = \true) + { + } + /** + * Retrieves the registered sidebar with the given ID. + * + * @since 5.9.0 + * + * @global array $wp_registered_sidebars The registered sidebars. + * + * @param string $id The sidebar ID. + * @return array|null The discovered sidebar, or null if it is not registered. + */ + function wp_get_sidebar($id) + { + } + /** + * Set the sidebar widget option to update sidebars. + * + * @since 2.2.0 + * @access private + * + * @global array $_wp_sidebars_widgets + * @param array $sidebars_widgets Sidebar widgets and their settings. + */ + function wp_set_sidebars_widgets($sidebars_widgets) + { + } + /** + * Retrieve default registered sidebars list. + * + * @since 2.2.0 + * @access private + * + * @global array $wp_registered_sidebars Registered sidebars. + * + * @return array + */ + function wp_get_widget_defaults() + { + } + /** + * Converts the widget settings from single to multi-widget format. + * + * @since 2.8.0 + * + * @global array $_wp_sidebars_widgets + * + * @param string $base_name Root ID for all widgets of this type. + * @param string $option_name Option name for this widget type. + * @param array $settings The array of widget instance settings. + * @return array The array of widget settings converted to multi-widget format. + */ + function wp_convert_widget_settings($base_name, $option_name, $settings) + { + } + /** + * Output an arbitrary widget as a template tag. + * + * @since 2.8.0 + * + * @global WP_Widget_Factory $wp_widget_factory + * + * @param string $widget The widget's PHP class name (see class-wp-widget.php). + * @param array $instance Optional. The widget's instance settings. Default empty array. + * @param array $args { + * Optional. Array of arguments to configure the display of the widget. + * + * @type string $before_widget HTML content that will be prepended to the widget's HTML output. + * Default `<div class="widget %s">`, where `%s` is the widget's class name. + * @type string $after_widget HTML content that will be appended to the widget's HTML output. + * Default `</div>`. + * @type string $before_title HTML content that will be prepended to the widget's title when displayed. + * Default `<h2 class="widgettitle">`. + * @type string $after_title HTML content that will be appended to the widget's title when displayed. + * Default `</h2>`. + * } + * @phpstan-param array{ + * before_widget?: string, + * after_widget?: string, + * before_title?: string, + * after_title?: string, + * } $args + */ + function the_widget($widget, $instance = array(), $args = array()) + { + } + /** + * Retrieves the widget ID base value. + * + * @since 2.8.0 + * + * @param string $id Widget ID. + * @return string Widget ID base. + */ + function _get_widget_id_base($id) + { + } + /** + * Handle sidebars config after theme change + * + * @access private + * @since 3.3.0 + * + * @global array $sidebars_widgets + */ + function _wp_sidebars_changed() + { + } + /** + * Validates and remaps any "orphaned" widgets to wp_inactive_widgets sidebar, + * and saves the widget settings. This has to run at least on each theme change. + * + * For example, let's say theme A has a "footer" sidebar, and theme B doesn't have one. + * After switching from theme A to theme B, all the widgets previously assigned + * to the footer would be inaccessible. This function detects this scenario, and + * moves all the widgets previously assigned to the footer under wp_inactive_widgets. + * + * Despite the word "retrieve" in the name, this function actually updates the database + * and the global `$sidebars_widgets`. For that reason it should not be run on front end, + * unless the `$theme_changed` value is 'customize' (to bypass the database write). + * + * @since 2.8.0 + * + * @global array $wp_registered_sidebars Registered sidebars. + * @global array $sidebars_widgets + * @global array $wp_registered_widgets Registered widgets. + * + * @param string|bool $theme_changed Whether the theme was changed as a boolean. A value + * of 'customize' defers updates for the Customizer. + * @return array Updated sidebars widgets. + */ + function retrieve_widgets($theme_changed = \false) + { + } + /** + * Compares a list of sidebars with their widgets against an allowed list. + * + * @since 4.9.0 + * @since 4.9.2 Always tries to restore widget assignments from previous data, not just if sidebars needed mapping. + * + * @param array $existing_sidebars_widgets List of sidebars and their widget instance IDs. + * @return array Mapped sidebars widgets. + */ + function wp_map_sidebars_widgets($existing_sidebars_widgets) + { + } + /** + * Compares a list of sidebars with their widgets against an allowed list. + * + * @since 4.9.0 + * + * @param array $sidebars_widgets List of sidebars and their widget instance IDs. + * @param array $allowed_widget_ids Optional. List of widget IDs to compare against. Default: Registered widgets. + * @return array Sidebars with allowed widgets. + */ + function _wp_remove_unregistered_widgets($sidebars_widgets, $allowed_widget_ids = array()) + { + } + /** + * Display the RSS entries in a list. + * + * @since 2.5.0 + * + * @param string|array|object $rss RSS url. + * @param array $args Widget arguments. + */ + function wp_widget_rss_output($rss, $args = array()) + { + } + /** + * Display RSS widget options form. + * + * The options for what fields are displayed for the RSS form are all booleans + * and are as follows: 'url', 'title', 'items', 'show_summary', 'show_author', + * 'show_date'. + * + * @since 2.5.0 + * + * @param array|string $args Values for input fields. + * @param array $inputs Override default display options. + */ + function wp_widget_rss_form($args, $inputs = \null) + { + } + /** + * Process RSS feed widget data and optionally retrieve feed items. + * + * The feed widget can not have more than 20 items or it will reset back to the + * default, which is 10. + * + * The resulting array has the feed title, feed url, feed link (from channel), + * feed items, error (if any), and whether to show summary, author, and date. + * All respectively in the order of the array elements. + * + * @since 2.5.0 + * + * @param array $widget_rss RSS widget feed data. Expects unescaped data. + * @param bool $check_feed Optional. Whether to check feed for errors. Default true. + * @return array + */ + function wp_widget_rss_process($widget_rss, $check_feed = \true) + { + } + /** + * Registers all of the default WordPress widgets on startup. + * + * Calls {@see 'widgets_init'} action after all of the WordPress widgets have been registered. + * + * @since 2.2.0 + */ + function wp_widgets_init() + { + } + /** + * Enables the widgets block editor. This is hooked into 'after_setup_theme' so + * that the block editor is enabled by default but can be disabled by themes. + * + * @since 5.8.0 + * + * @access private + */ + function wp_setup_widgets_block_editor() + { + } + /** + * Whether or not to use the block editor to manage widgets. Defaults to true + * unless a theme has removed support for widgets-block-editor or a plugin has + * filtered the return value of this function. + * + * @since 5.8.0 + * + * @return bool Whether to use the block editor to manage widgets. + */ + function wp_use_widgets_block_editor() + { + } + /** + * Converts a widget ID into its id_base and number components. + * + * @since 5.8.0 + * + * @param string $id Widget ID. + * @return array Array containing a widget's id_base and number components. + */ + function wp_parse_widget_id($id) + { + } + /** + * Finds the sidebar that a given widget belongs to. + * + * @since 5.8.0 + * + * @param string $widget_id The widget ID to look for. + * @return string|null The found sidebar's ID, or null if it was not found. + */ + function wp_find_widgets_sidebar($widget_id) + { + } + /** + * Assigns a widget to the given sidebar. + * + * @since 5.8.0 + * + * @param string $widget_id The widget ID to assign. + * @param string $sidebar_id The sidebar ID to assign to. If empty, the widget won't be added to any sidebar. + */ + function wp_assign_widget_to_sidebar($widget_id, $sidebar_id) + { + } + /** + * Calls the render callback of a widget and returns the output. + * + * @since 5.8.0 + * + * @param string $widget_id Widget ID. + * @param string $sidebar_id Sidebar ID. + * @return string + */ + function wp_render_widget($widget_id, $sidebar_id) + { + } + /** + * Calls the control callback of a widget and returns the output. + * + * @since 5.8.0 + * + * @param string $id Widget ID. + * @return string|null + */ + function wp_render_widget_control($id) + { + } + /** + * Displays a _doing_it_wrong() message for conflicting widget editor scripts. + * + * The 'wp-editor' script module is exposed as window.wp.editor. This overrides + * the legacy TinyMCE editor module which is required by the widgets editor. + * Because of that conflict, these two shouldn't be enqueued together. + * See https://core.trac.wordpress.org/ticket/53569. + * + * There is also another conflict related to styles where the block widgets + * editor is hidden if a block enqueues 'wp-edit-post' stylesheet. + * See https://core.trac.wordpress.org/ticket/53569. + * + * @since 5.8.0 + * @access private + * + * @global WP_Scripts $wp_scripts + * @global WP_Styles $wp_styles + */ + function wp_check_widget_editor_deps() + { + } + /** + * Output the login page header. + * + * @since 2.1.0 + * + * @global string $error Login error message set by deprecated pluggable wp_login() function + * or plugins replacing it. + * @global bool|string $interim_login Whether interim login modal is being displayed. String 'success' + * upon successful login. + * @global string $action The action that brought the visitor to the login page. + * + * @param string $title Optional. WordPress login Page title to display in the `<title>` element. + * Default 'Log In'. + * @param string $message Optional. Message to display in header. Default empty. + * @param WP_Error $wp_error Optional. The error to pass. Default is a WP_Error instance. + */ + function login_header($title = 'Log In', $message = '', $wp_error = \null) + { + } + // End of login_header(). + /** + * Outputs the footer for the login page. + * + * @since 3.1.0 + * + * @global bool|string $interim_login Whether interim login modal is being displayed. String 'success' + * upon successful login. + * + * @param string $input_id Which input to auto-focus. + */ + function login_footer($input_id = '') + { + } + /** + * Outputs the JavaScript to handle the form shaking on the login page. + * + * @since 3.0.0 + */ + function wp_shake_js() + { + } + /** + * Outputs the viewport meta tag for the login page. + * + * @since 3.7.0 + */ + function wp_login_viewport_meta() + { + } + /** + * Prints signup_header via wp_head. + * + * @since MU (3.0.0) + */ + function do_signup_header() + { + } + /** + * Prints styles for front-end Multisite Sign-up pages. + * + * @since MU (3.0.0) + */ + function wpmu_signup_stylesheet() + { + } + /** + * Generates and displays the Sign-up and Create Site forms. + * + * @since MU (3.0.0) + * + * @param string $blogname The new site name. + * @param string $blog_title The new site title. + * @param WP_Error|string $errors A WP_Error object containing existing errors. Defaults to empty string. + */ + function show_blog_form($blogname = '', $blog_title = '', $errors = '') + { + } + /** + * Validates the new site sign-up. + * + * @since MU (3.0.0) + * + * @return array Contains the new site data and error messages. + * See wpmu_validate_blog_signup() for details. + */ + function validate_blog_form() + { + } + /** + * Displays the fields for the new user account registration form. + * + * @since MU (3.0.0) + * + * @param string $user_name The entered username. + * @param string $user_email The entered email address. + * @param WP_Error|string $errors A WP_Error object containing existing errors. Defaults to empty string. + */ + function show_user_form($user_name = '', $user_email = '', $errors = '') + { + } + /** + * Validates user sign-up name and email. + * + * @since MU (3.0.0) + * + * @return array Contains username, email, and error messages. + * See wpmu_validate_user_signup() for details. + */ + function validate_user_form() + { + } + /** + * Shows a form for returning users to sign up for another site. + * + * @since MU (3.0.0) + * + * @param string $blogname The new site name + * @param string $blog_title The new site title. + * @param WP_Error|string $errors A WP_Error object containing existing errors. Defaults to empty string. + */ + function signup_another_blog($blogname = '', $blog_title = '', $errors = '') + { + } + /** + * Validates a new site sign-up for an existing user. + * + * @since MU (3.0.0) + * + * @global string $blogname The new site's subdomain or directory name. + * @global string $blog_title The new site's title. + * @global WP_Error $errors Existing errors in the global scope. + * @global string $domain The new site's domain. + * @global string $path The new site's path. + * + * @return null|bool True if site signup was validated, false on error. + * The function halts all execution if the user is not logged in. + */ + function validate_another_blog_signup() + { + } + /** + * Shows a message confirming that the new site has been created. + * + * @since MU (3.0.0) + * @since 4.4.0 Added the `$blog_id` parameter. + * + * @param string $domain The domain URL. + * @param string $path The site root path. + * @param string $blog_title The site title. + * @param string $user_name The username. + * @param string $user_email The user's email address. + * @param array $meta Any additional meta from the {@see 'add_signup_meta'} filter in validate_blog_signup(). + * @param int $blog_id The site ID. + */ + function confirm_another_blog_signup($domain, $path, $blog_title, $user_name, $user_email = '', $meta = array(), $blog_id = 0) + { + } + /** + * Shows a form for a visitor to sign up for a new user account. + * + * @since MU (3.0.0) + * + * @global string $active_signup String that returns registration type. The value can be + * 'all', 'none', 'blog', or 'user'. + * + * @param string $user_name The username. + * @param string $user_email The user's email. + * @param WP_Error|string $errors A WP_Error object containing existing errors. Defaults to empty string. + */ + function signup_user($user_name = '', $user_email = '', $errors = '') + { + } + /** + * Validates the new user sign-up. + * + * @since MU (3.0.0) + * + * @return bool True if new user sign-up was validated, false on error. + */ + function validate_user_signup() + { + } + /** + * Shows a message confirming that the new user has been registered and is awaiting activation. + * + * @since MU (3.0.0) + * + * @param string $user_name The username. + * @param string $user_email The user's email address. + */ + function confirm_user_signup($user_name, $user_email) + { + } + /** + * Shows a form for a user or visitor to sign up for a new site. + * + * @since MU (3.0.0) + * + * @param string $user_name The username. + * @param string $user_email The user's email address. + * @param string $blogname The site name. + * @param string $blog_title The site title. + * @param WP_Error|string $errors A WP_Error object containing existing errors. Defaults to empty string. + */ + function signup_blog($user_name = '', $user_email = '', $blogname = '', $blog_title = '', $errors = '') + { + } + /** + * Validates new site signup. + * + * @since MU (3.0.0) + * + * @return bool True if the site sign-up was validated, false on error. + */ + function validate_blog_signup() + { + } + /** + * Shows a message confirming that the new site has been registered and is awaiting activation. + * + * @since MU (3.0.0) + * + * @param string $domain The domain or subdomain of the site. + * @param string $path The path of the site. + * @param string $blog_title The title of the new site. + * @param string $user_name The user's username. + * @param string $user_email The user's email address. + * @param array $meta Any additional meta from the {@see 'add_signup_meta'} filter in validate_blog_signup(). + */ + function confirm_blog_signup($domain, $path, $blog_title, $user_name = '', $user_email = '', $meta = array()) + { + } + /** + * Retrieves languages available during the site/user sign-up process. + * + * @since 4.4.0 + * + * @see get_available_languages() + * + * @return string[] Array of available language codes. Language codes are formed by + * stripping the .mo extension from the language file names. + */ + function signup_get_available_languages() + { + } + /** + * Response to a trackback. + * + * Responds with an error or success XML message. + * + * @since 0.71 + * + * @param int|bool $error Whether there was an error. + * Default '0'. Accepts '0' or '1', true or false. + * @param string $error_message Error message if an error occurred. + */ + function trackback_response($error = 0, $error_message = '') + { + } + /** + * logIO() - Writes logging info to a file. + * + * @deprecated 3.4.0 Use error_log() + * @see error_log() + * + * @param string $io Whether input or output + * @param string $msg Information describing logging reason. + */ + function logIO($io, $msg) + { + } +} +namespace { +/** + * WordPress database abstraction object. + * @var wpdb + */ +$wpdb = \null; +} diff --git a/vendor/phpcompatibility/php-compatibility/CHANGELOG.md b/vendor/phpcompatibility/php-compatibility/CHANGELOG.md new file mode 100644 index 00000000..b92ae254 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/CHANGELOG.md @@ -0,0 +1,1488 @@ +# Change Log for the PHPCompatibility standard for PHP Codesniffer + +All notable changes to this project will be documented in this file. + +This projects adheres to [Keep a CHANGELOG](http://keepachangelog.com/). + +Up to version 8.0.0, the `major.minor` version numbers were based on the PHP version for which compatibility check support was added, with `patch` version numbers being specific to this library. +From version 8.0.0 onwards, [Semantic Versioning](http://semver.org/) is used. + +<!-- Legend to the icons used: https://github.com/PHPCompatibility/PHPCompatibility/pull/506#discussion_r131650488 --> + + +## [Unreleased] + +_Nothing yet._ + +## [9.3.5] - 2019-12-27 + +See all related issues and PRs in the [9.3.5 milestone]. + +### Added +- :star: `PHPCompatibility.Classes.NewClasses` sniff: recognize the new `FFI` extension related classes as introduced in PHP 7.4. [#949](https://github.com/PHPCompatibility/PHPCompatibility/pull/949) +- :star: `PHPCompatibility.IniDirectives.NewIniDirectives` sniff: detect use of the new `FFI` extension related ini directives as introduced in PHP 7.4. [#949](https://github.com/PHPCompatibility/PHPCompatibility/pull/949) + +### Changed +- :pencil: `PHPCompatibility.Syntax.NewShortArray`: improved clarity of the error message and made it consistent with other error messages in this standard. [#934](https://github.com/PHPCompatibility/PHPCompatibility/pull/934) +- :pencil: `PHPCompatibility.Interfaces.NewInterfaces`: updated the URL which is mentioned in select error messages. [#942](https://github.com/PHPCompatibility/PHPCompatibility/pull/942) +- :recycle: Another slew of code documentation fixes. [#937](https://github.com/PHPCompatibility/PHPCompatibility/pull/937), [#939](https://github.com/PHPCompatibility/PHPCompatibility/pull/939), [#940](https://github.com/PHPCompatibility/PHPCompatibility/pull/940), [#941](https://github.com/PHPCompatibility/PHPCompatibility/pull/941), [#943](https://github.com/PHPCompatibility/PHPCompatibility/pull/943), [#944](https://github.com/PHPCompatibility/PHPCompatibility/pull/944), [#951](https://github.com/PHPCompatibility/PHPCompatibility/pull/951), [#950](https://github.com/PHPCompatibility/PHPCompatibility/pull/950). Fixes [#734](https://github.com/PHPCompatibility/PHPCompatibility/issues/734). +- :green_heart: Travis: various tweaks. The builds against PHP 7.4 are no longer allowed to fail. [#935](https://github.com/PHPCompatibility/PHPCompatibility/pull/935), [#938](https://github.com/PHPCompatibility/PHPCompatibility/pull/938) + For running the sniffs on PHP 7.4, it is recommended to use PHP_CodeSniffer 3.5.0+ as PHP_CodeSniffer itself is + not compatible with PHP 7.4 until version 3.5.0. + +### Fixed +- :bug: `PHPCompatibility.Classes.NewClasses`: two new PHP 7.4 classes were being checked as if they were Exceptions. [#945](https://github.com/PHPCompatibility/PHPCompatibility/pull/945) + +### Credits +Thanks go out to [William Entriken] for their contribution to this version. :clap: + + +## [9.3.4] - 2019-11-15 + +See all related issues and PRs in the [9.3.4 milestone]. + +### Fixed +- :bug: `PHPCompatibility.Keywords.ForbiddenNames`: false positive for list when used in a `foreach()` condition. [#930](https://github.com/PHPCompatibility/PHPCompatibility/pull/930). Fixes [#928](https://github.com/PHPCompatibility/PHPCompatibility/issues/928), [#929](https://github.com/PHPCompatibility/PHPCompatibility/pull/929) + +### Credits +Thanks go out to [Sergii Bondarenko] for their contribution to this version. :clap: + + +## [9.3.3] - 2019-11-11 + +See all related issues and PRs in the [9.3.3 milestone]. + +### Added +- :star: `PHPCompatibility.Constants.NewConstants` sniff: detection of yet more (undocumented) PHP 7.2 Sodium constants. [#924](https://github.com/PHPCompatibility/PHPCompatibility/pull/924) +- :star: `PHPCompatibility.Keywords.ForbiddenNames` sniff: detect the use of more reserved keywords which are not allowed to be used to name certain constructs. [#923](https://github.com/PHPCompatibility/PHPCompatibility/pull/923). Fixes [#922](https://github.com/PHPCompatibility/PHPCompatibility/issues/922) + +### Fixed +- :bug: `PHPCompatibility.FunctionNameRestrictions.RemovedPHP4StyleConstructors`: false positive detecting PHP4-style constructors when declared in interfaces. The class implementing the interface will not have the same name as the interface, so the actual method would not be regarded as a PHP4 style constructor. [#921](https://github.com/PHPCompatibility/PHPCompatibility/pull/921) + +### Credits +Thanks go out to [Nikhil] for their contribution to this version. :clap: + + +## [9.3.2] - 2019-10-16 + +See all related issues and PRs in the [9.3.2 milestone]. + +### Added +- :star: `PHPCompatibility.Constants.NewConstants` sniff: detection of the PHP 7.2 `SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13` constant. [#915](https://github.com/PHPCompatibility/PHPCompatibility/pull/915) +- :books: Readme: a list of projects which are build upon or extend PHPCompatibility. [#904](https://github.com/PHPCompatibility/PHPCompatibility/pull/904) + +### Changed +- :pushpin: `PHPCompatibility.FunctionNameRestrictions.RemovedPHP4StyleConstructors`: minor efficiency fix to make the sniff faster. [#912](https://github.com/PHPCompatibility/PHPCompatibility/pull/912) +- :pushpin: `PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames`: functions marked as `@deprecated` in the function docblock will now be ignored by this sniff. [#917](https://github.com/PHPCompatibility/PHPCompatibility/pull/917). Fixes [#911](https://github.com/PHPCompatibility/PHPCompatibility/issues/911) +- :pencil: `PHPCompatibility.FunctionDeclarations.ForbiddenToStringParameters`: the `$ooScopeTokens` property is now `protected`, it should never have been `public` in the first place. [#907](https://github.com/PHPCompatibility/PHPCompatibility/pull/907) +- :recycle: More code documentation fixes. [#903](https://github.com/PHPCompatibility/PHPCompatibility/pull/903), [#916](https://github.com/PHPCompatibility/PHPCompatibility/pull/916) +- :books: Readme/Contributing: various tweaks. [#904](https://github.com/PHPCompatibility/PHPCompatibility/pull/904), [#905](https://github.com/PHPCompatibility/PHPCompatibility/pull/905) + +### Fixed +- :bug: `PHPCompatibility.FunctionUse.OptionalToRequiredFunctionParameters`: false positive when a class is instantiated which has the same name as one of the affected functions. [#914](https://github.com/PHPCompatibility/PHPCompatibility/pull/914). Fixes [#913](https://github.com/PHPCompatibility/PHPCompatibility/issues/913) +- :bug: `PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters`: false positive when a class is instantiated which has the same name as one of the affected functions. [#914](https://github.com/PHPCompatibility/PHPCompatibility/pull/914) +- :bug: `PHPCompatibility.MethodUse.NewDirectCallsToClone`: false positive on calling `__clone()` from within the class being cloned [#910](https://github.com/PHPCompatibility/PHPCompatibility/pull/910). Fixes [#629 (comment)](https://github.com/PHPCompatibility/PHPCompatibility/issues/629#issuecomment-532607809) +- :bug: `PHPCompatibility.Miscellaneous.ValidIntegers`: binary numbers using an uppercase `B` were not always recognized correctly. [#909](https://github.com/PHPCompatibility/PHPCompatibility/pull/909) + + +## [9.3.1] - 2019-09-06 + +See all related issues and PRs in the [9.3.1 milestone]. + +### Changed +- :recycle: A whole slew of code documentation fixes. [#892](https://github.com/PHPCompatibility/PHPCompatibility/pull/892), [#895](https://github.com/PHPCompatibility/PHPCompatibility/pull/895), [#896](https://github.com/PHPCompatibility/PHPCompatibility/pull/896), [#897](https://github.com/PHPCompatibility/PHPCompatibility/pull/897), [#898](https://github.com/PHPCompatibility/PHPCompatibility/pull/898), [#899](https://github.com/PHPCompatibility/PHPCompatibility/pull/899), [#900](https://github.com/PHPCompatibility/PHPCompatibility/pull/900) +- :wrench: Travis: minor tweaks to the build script. [#893](https://github.com/PHPCompatibility/PHPCompatibility/pull/893) + +### Fixed +- :bug: `PHPCompatibility.ParameterValues.RemovedImplodeFlexibleParamOrder`: false positive when an array item in the second parameter contained a ternary. [#891](https://github.com/PHPCompatibility/PHPCompatibility/pull/891). Fixes [#890](https://github.com/PHPCompatibility/PHPCompatibility/issues/890) +- :bug: `PHPCompatibility.ParameterValues.RemovedImplodeFlexibleParamOrder`: will now take array casts into account when determining which parameter is `$pieces`. [#891](https://github.com/PHPCompatibility/PHPCompatibility/pull/891). +- :bug: `PHPCompatibility.ParameterValues.RemovedImplodeFlexibleParamOrder`: hardening of the logic to not examine the second parameter when the first is just and only a text string (`$glue`). [#891](https://github.com/PHPCompatibility/PHPCompatibility/pull/891). + + +## [9.3.0] - 2019-08-29 + +See all related issues and PRs in the [9.3.0 milestone]. + +To keep informed of the progress of covering "_everything PHP 7.4_" in PHPCompatibility, please subscribe to issue [#808](https://github.com/PHPCompatibility/PHPCompatibility/issues/808). + +### Changes expected in PHPCompatibility 10.0.0 +The next version of PHPCompatibility is expected to include a new external dependency. + +In this same release, support for PHP < 5.4 and PHP_CodeSniffer < 2.6.0 will be dropped. + +The `10.0.0` release is expected around the same time as the release of PHP 7.4 - end of November/beginning of December 2019. + +### Added +- :star2: New `PHPCompatibility.Miscellaneous.NewPHPOpenTagEOF` sniff to detect a stand-alone PHP open tag at the end of a file, without trailing newline, as will be supported as of PHP 7.4. [#843](https://github.com/PHPCompatibility/PHPCompatibility/pull/846) +- :star2: New `PHPCompatibility.ParameterValues.ForbiddenStripTagsSelfClosingXHTML` sniff to detect calls to `strip_tags()` passing self-closing XHTML tags in the `$allowable_tags` parameter. This has not been supported since PHP 5.3.4. [#866](https://github.com/PHPCompatibility/PHPCompatibility/pull/866) +- :star2: New `PHPCompatibility.ParameterValues.NewHTMLEntitiesEncodingDefault` sniff to detect calls to `html_entity_decode()`, `htmlentities()` and `htmlspecialchars()` which are impacted by the change to the default value of the `$encoding` parameter in PHP 5.4. [#862](https://github.com/PHPCompatibility/PHPCompatibility/pull/862) +- :star2: New `PHPCompatibility.ParameterValues.NewIconvMbstringCharsetDefault` sniff to detect code impacted by the change in the `default_charset` value in PHP 5.6. [#864](https://github.com/PHPCompatibility/PHPCompatibility/pull/864) Fixes [#839](https://github.com/PHPCompatibility/PHPCompatibility/issues/839) +- :star2: New `PHPCompatibility.ParameterValues.NewIDNVariantDefault` sniff to detect calls to `idn_to_ascii()` and `idn_to_utf8()` impacted by the PHP 7.4 change in the default value for the `$variant` parameter. [#861](https://github.com/PHPCompatibility/PHPCompatibility/pull/861) +- :star2: New `PHPCompatibility.ParameterValues.NewPasswordAlgoConstantValues` sniff to detect calls to `password_hash()` and `password_needs_rehash()` impacted by the changed value of the `PASSWORD_DEFAULT`, `PASSWORD_BCRYPT`, `PASSWORD_ARGON2I` and `PASSWORD_ARGON2ID` constants in PHP 7.4. [#865](https://github.com/PHPCompatibility/PHPCompatibility/pull/865) +- :star2: New `PHPCompatibility.ParameterValues.NewProcOpenCmdArray` sniff to detect calls to `proc_open()` passing an array for the `$cmd` parameter as supported as of PHP 7.4. [#869](https://github.com/PHPCompatibility/PHPCompatibility/pull/869) +- :star2: New `PHPCompatibility.ParameterValues.NewStripTagsAllowableTagsArray` sniff to detect calls to `strip_tags()` passing an array for the `$allowable_tags` parameter as will be supported as of PHP 7.4. [#867](https://github.com/PHPCompatibility/PHPCompatibility/pull/867) +- :star2: New `PHPCompatibility.ParameterValues.RemovedImplodeFlexibleParamOrder` sniff to detect `implode()` being called with `$glue` and `$pieces` in reverse order from the documented argument order. This was previously allowed for historical reasons, but will be deprecated in PHP 7.4. [#846](https://github.com/PHPCompatibility/PHPCompatibility/pull/846) +- :star2: New `PHPCompatibility.ParameterValues.RemovedMbStrrposEncodingThirdParam` sniff to detect the `$encoding` being passed as the third, instead of the fourth parameter, to `mb_strrpos()` as has been soft deprecated since PHP 5.2 and will be hard deprecated as of PHP 7.4. [#860](https://github.com/PHPCompatibility/PHPCompatibility/pull/860) +- :star2: New `PHPCompatibility.Syntax.RemovedCurlyBraceArrayAccess` sniff to detect array and string offset access using curly braces as will be deprecated as of PHP 7.4. [#855](https://github.com/PHPCompatibility/PHPCompatibility/pull/855) + - In contrast to any other sniff in the PHPCompatibility standard, this sniff contains an auto-fixer. +- :star2: New `PHPCompatibility.TextStrings.NewUnicodeEscapeSequence` sniff to detect use of the PHP 7.0+ unicode codepoint escape sequences and issues with invalid sequences. [#856](https://github.com/PHPCompatibility/PHPCompatibility/pull/856) +- :star2: New `PHPCompatibility.Upgrade.LowPHP` sniff to give users of old PHP versions advance warning when support will be dropped in the near future. [#838](https://github.com/PHPCompatibility/PHPCompatibility/pull/838) + At this moment, the intention is to drop support for PHP 5.3 by the end of this year. +- :star: `PHPCompatibility.Classes.NewClasses` sniff: recognize the new `WeakReference` class as introduced in PHP 7.4. [#857](https://github.com/PHPCompatibility/PHPCompatibility/pull/857) +- :star: `PHPCompatibility.Constants.NewConstants` sniff: detection of new Curl constants as introduced in PHP 7.3.5. [#878](https://github.com/PHPCompatibility/PHPCompatibility/pull/878) +- :star: `PHPCompatibility.Constants.NewConstants` sniff: detection of the revived `T_BAD_CHARACTER` constant as re-introduced in PHP 7.4. [#882](https://github.com/PHPCompatibility/PHPCompatibility/pull/882) +- :star: `PHPCompatibility.Constants.NewConstants` sniff: detection of the new `IMG_FILTER_SCATTER` and `PASSWORD_ARGON2_PROVIDER` constants as introduced in PHP 7.4. [#887](https://github.com/PHPCompatibility/PHPCompatibility/pull/887) +- :star: `PHPCompatibility.Constants.RemovedConstants` sniff: detection of use of the `CURLPIPE_HTTP1` constant which will be deprecated in PHP 7.4. [#879](https://github.com/PHPCompatibility/PHPCompatibility/pull/879) +- :star: `PHPCompatibility.Constants.RemovedConstants` sniff: detection of use of the `FILTER_SANITIZE_MAGIC_QUOTES` constant which will be deprecated in PHP 7.4. [#845](https://github.com/PHPCompatibility/PHPCompatibility/pull/845) +- :star: `PHPCompatibility.Constants.RemovedConstants` sniff: detection of use of the `T_CHARACTER` and `T_BAD_CHARACTER` constants which were removed in PHP 7.0. [#882](https://github.com/PHPCompatibility/PHPCompatibility/pull/882) +- :star: `PHPCompatibility.FunctionDeclarations.NewMagicMethods` sniff: recognize the new `__serialize()` and `__unserialize()` magic methods as introduced in PHP 7.4. [#868](https://github.com/PHPCompatibility/PHPCompatibility/pull/868) +- :star: `PHPCompatibility.FunctionDeclarations.NewMagicMethods` sniff: recognize the PHP 5.0 `__construct()` and `__destruct()` magic methods. [#884](https://github.com/PHPCompatibility/PHPCompatibility/pull/884) +- :star: `PHPCompatibility.FunctionDeclarations.NonStaticMagicMethods` sniff: recognize the new `__serialize()` and `__unserialize()` magic methods as introduced in PHP 7.4. [#868](https://github.com/PHPCompatibility/PHPCompatibility/pull/868) +- :star: `PHPCompatibility.FunctionUse.NewFunctions` sniff: recognize the new PHP 7.4 function `imagecreatefromtga()`. [#873](https://github.com/PHPCompatibility/PHPCompatibility/pull/873) +- :star: `PHPCompatibility.FunctionUse.RemovedFunctionParameters` sniff: recognize the deprecation of the `$age` parameter of the `curl_version()` function. [#874](https://github.com/PHPCompatibility/PHPCompatibility/pull/874) +- :star: `PHPCompatibility.FunctionUse.RemovedFunctions` sniff: recognize the PHP 7.4 deprecated `convert_cyr_string()()`, `ezmlm_hash()`, `get_magic_quotes_gpc()`, `get_magic_quotes_runtime()`, `hebrevc()`, `is_real()`, `money_format()` and `restore_include_path()` functions. [#847](https://github.com/PHPCompatibility/PHPCompatibility/pull/847) +- :star: `PHPCompatibility.IniDirectives.NewIniDirectives` sniff: detect use of the new PHP 7.4 `zend.exception_ignore_args` ini directive. [#871](https://github.com/PHPCompatibility/PHPCompatibility/pull/871) +- :star: `PHPCompatibility.IniDirectives.RemovedIniDirectives` sniff: detect use of the `allow_url_include` ini directive which is deprecated as of PHP 7.4. [#870](https://github.com/PHPCompatibility/PHPCompatibility/pull/870) +- :star: `PHPCompatibility.IniDirectives.RemovedIniDirectives` sniff: detection of use of the `opcache.load_comments` directive which was removed in PHP 7.0. [#883](https://github.com/PHPCompatibility/PHPCompatibility/pull/883) +- :star: `PHPCompatibility.ParameterValues.NewHashAlgorithms`: recognize use of the new PHP 7.4 `crc32c` hash algorithm. [#872](https://github.com/PHPCompatibility/PHPCompatibility/pull/872) +- :star: `PHPCompatibility.TypeCasts.RemovedTypeCasts` sniff: detect usage of the `(real)` type cast which will be deprecated in PHP 7.4. [#844](https://github.com/PHPCompatibility/PHPCompatibility/pull/844) +- :star: Recognize the `recode` extension functionality which will be removed in PHP 7.4 (moved to PECL) in the `RemovedExtensions` and `RemovedFunctions` sniffs. [#841](https://github.com/PHPCompatibility/PHPCompatibility/pull/841) +- :star: Recognize the `OPcache` extension functionality which was be introduced in PHP 5.5, but not yet fully accounted for in the `NewFunctions` and `NewIniDirectives` sniffs. [#883](https://github.com/PHPCompatibility/PHPCompatibility/pull/883) +- :star: New `getCompleteTextString()` utility method to the `PHPCompatibility\Sniff` class. [#856](https://github.com/PHPCompatibility/PHPCompatibility/pull/856) +- :umbrella: Unit test for the `PHPCompatibility.Upgrade.LowPHPCS` sniff. +- :umbrella: Some extra unit tests for the `PHPCompatibility.ParameterValues.NewNegativeStringOffset`, `PHPCompatibility.ParameterValues.RemovedMbStringModifiers` and sniffs. [#876](https://github.com/PHPCompatibility/PHPCompatibility/pull/876), [#877](https://github.com/PHPCompatibility/PHPCompatibility/pull/877) +- :books: `CONTRIBUTING.md`: Added a list of typical sources for information about changes to PHP. [#875](https://github.com/PHPCompatibility/PHPCompatibility/pull/875) + +### Changed +- :pushpin: `PHPCompatibility.FunctionDeclarations.NewExceptionsFromToString` sniff: the sniff will now also examine the function docblock, if available, and will throw an error when a `@throws` tag is found in the docblock. [#880](https://github.com/PHPCompatibility/PHPCompatibility/pull/880). Fixes [#863](https://github.com/PHPCompatibility/PHPCompatibility/issues/863) +- :pushpin: `PHPCompatibility.FunctionDeclarations.NonStaticMagicMethods` sniff: will now also check the visibility and `static` (or not) requirements of the magic `__construct()`, `__destruct()`, `__clone()`, `__debugInfo()`, `__invoke()` and `__set_state()` methods. [#885](https://github.com/PHPCompatibility/PHPCompatibility/pull/885) +- :pushpin: `PHPCompatibility.Syntax.NewArrayStringDereferencing` sniff: the sniff will now also recognize array string dereferencing using curly braces as was (silently) supported since PHP 7.0. [#851](https://github.com/PHPCompatibility/PHPCompatibility/pull/851) + - The sniff will now also throw errors for each dereference found on the array/string, not just the first one. +- :pushpin: `PHPCompatibility.Syntax.NewClassMemberAccess` sniff: the sniff will now also recognize class member access on instantiation and cloning using curly braces as was (silently) supported since PHP 7.0. [#852](https://github.com/PHPCompatibility/PHPCompatibility/pull/852) + - The sniff will now also throw errors for each access detected, not just the first one. + - The line number on which the error is thrown in now set more precisely. +- :pushpin: `PHPCompatibility.Syntax.NewFunctionArrayDereferencing` sniff: the sniff will now also recognize function array dereferencing using curly braces as was (silently) supported since PHP 7.0. [#853](https://github.com/PHPCompatibility/PHPCompatibility/pull/853) + - The sniff will now also throw errors for each access detected, not just the first one. + - The line number on which the error is thrown in now set more precisely. +- :recycle: Various code clean-up and improvements. [#849](https://github.com/PHPCompatibility/PHPCompatibility/pull/849), [#850](https://github.com/PHPCompatibility/PHPCompatibility/pull/850) +- :recycle: Various minor inline documentation fixes. [#854](https://github.com/PHPCompatibility/PHPCompatibility/pull/854), [#886](https://github.com/PHPCompatibility/PHPCompatibility/pull/886) +- :wrench: Travis: various tweaks to the build script. [#834](https://github.com/PHPCompatibility/PHPCompatibility/pull/834), [#842](https://github.com/PHPCompatibility/PHPCompatibility/pull/842) + +### Fixed +- :bug: `PHPCompatibility.FunctionDeclarations.ForbiddenParametersWithSameName` sniff: variable names are case-sensitive, so recognition of same named parameters should be done in a case-sensitive manner. [#848](https://github.com/PHPCompatibility/PHPCompatibility/pull/848) +- :bug: `PHPCompatibility.FunctionDeclarations.NewExceptionsFromToString` sniff: Exceptions thrown within a `try` should not trigger the sniff. [#880](https://github.com/PHPCompatibility/PHPCompatibility/pull/880). Fixes [#863](https://github.com/PHPCompatibility/PHPCompatibility/issues/863) +- :bug: `PHPCompatibility.FunctionDeclarations.NewExceptionsFromToString` sniff: the `$ooScopeTokens` property should never have been a public property. [#880](https://github.com/PHPCompatibility/PHPCompatibility/pull/880). +- :umbrella: Some of the unit tests for the `PHPCompatibility.Operators.RemovedTernaryAssociativity` sniff were not being run. [#836](https://github.com/PHPCompatibility/PHPCompatibility/pull/836) + + +## [9.2.0] - 2019-06-28 + +See all related issues and PRs in the [9.2.0 milestone]. + +To keep informed of the progress of covering "_everything PHP 7.4_" in PHPCompatibility, please subscribe to issue [#808](https://github.com/PHPCompatibility/PHPCompatibility/issues/808). + +### Added +- :star2: New `PHPCompatibility.Classes.ForbiddenAbstractPrivateMethods` sniff to detect methods declared as both `private` as well as `abstract`. This was allowed between PHP 5.0.0 and 5.0.4, but disallowed in PHP 5.1 as the behaviour of `private` and `abstract` are mutually exclusive. [#822](https://github.com/PHPCompatibility/PHPCompatibility/pull/822) +- :star2: New `PHPCompatibility.Classes.NewTypedProperties` sniff to detect PHP 7.4 typed property declarations. [#801](https://github.com/PHPCompatibility/PHPCompatibility/pull/801), [#829](https://github.com/PHPCompatibility/PHPCompatibility/pull/829) +- :star2: New `PHPCompatibility.Classes.RemovedOrphanedParent` sniff to detect the use of the `parent` keyword in classes without a parent (non-extended classes). This code pattern is deprecated in PHP 7.4 and will become a compile-error in PHP 8.0. [#818](https://github.com/PHPCompatibility/PHPCompatibility/pull/818) +- :star2: New `PHPCompatibility.FunctionDeclarations.NewExceptionsFromToString` sniff to detect throwing exceptions from `__toString()` methods. This would previously result in a fatal error, but will be allowed as of PHP 7.4. [#814](https://github.com/PHPCompatibility/PHPCompatibility/pull/814) +- :star2: New `PHPCompatibility.FunctionDeclarations.ForbiddenToStringParameters` sniff to detect `__toString()` function declarations expecting parameters. This was disallowed in PHP 5.3. [#815](https://github.com/PHPCompatibility/PHPCompatibility/pull/815) +- :star2: New `PHPCompatibility.MethodUse.ForbiddenToStringParameters` sniff to detect direct calls to `__toString()` magic methods passing parameters. This was disallowed in PHP 5.3. [#830](https://github.com/PHPCompatibility/PHPCompatibility/pull/830) +- :star2: New `PHPCompatibility.Operators.ChangedConcatOperatorPrecedence` sniff to detect code affected by the upcoming change in operator precedence for the concatenation operator. The concatenation operator precedence will be lowered in PHP 8.0, with deprecation notices for code affected being thrown in PHP 7.4. [#805](https://github.com/PHPCompatibility/PHPCompatibility/pull/805) +- :star2: New `PHPCompatibility.Operators.RemovedTernaryAssociativity` sniff to detect code relying on left-associativity of the ternary operator. This behaviour will be deprecated in PHP 7.4 and removed in PHP 8.0. [#810](https://github.com/PHPCompatibility/PHPCompatibility/pull/810) +- :star2: New `PHPCompatibility.Syntax.NewArrayUnpacking` sniff to detect the use of the spread operator to unpack arrays when declaring a new array, as introduced in PHP 7.4. [#804](https://github.com/PHPCompatibility/PHPCompatibility/pull/804) +- :star: `PHPCompatibility.Classes.NewClasses` sniff: recognize the new `ReflectionReference` class as introduced in PHP 7.4. [#820](https://github.com/PHPCompatibility/PHPCompatibility/pull/820) +- :star: `PHPCompatibility.Constants.NewConstants` sniff: detection of the new PHP 7.4 Core (Standard), MBString, Socket and Tidy constants. [#821](https://github.com/PHPCompatibility/PHPCompatibility/pull/821) +- :star: `PHPCompatibility.FunctionUse.NewFunctions` sniff: detect usage of the new PHP 7.4 `get_mangled_object_vars()`, `mb_str_split()`, `openssl_x509_verify()`, `password_algos()`, `pcntl_unshare()`, `sapi_windows_set_ctrl_handler()` and `sapi_windows_generate_ctrl_event()` functions. [#811](https://github.com/PHPCompatibility/PHPCompatibility/pull/811), [#819](https://github.com/PHPCompatibility/PHPCompatibility/pull/819), [#827](https://github.com/PHPCompatibility/PHPCompatibility/pull/827) +- :star: `PHPCompatibility.FunctionUse.NewFunctions` sniff: recognize the new OCI functions as introduced in PHP 7.2.14 and PHP 7.3.1. [#786](https://github.com/PHPCompatibility/PHPCompatibility/pull/786) +- :star: `PHPCompatibility.FunctionUse.RemovedFunctions` sniff: recognize the PHP 7.4 deprecated `ldap_control_paged_result_response()` and `ldap_control_paged_result()` functions. [#831](https://github.com/PHPCompatibility/PHPCompatibility/pull/831) +- :star: `PHPCompatibility.FunctionUse.RemovedFunctions` sniff: recognize the `Payflow Pro/pfpro` functions as removed in PHP 5.1. [#823](https://github.com/PHPCompatibility/PHPCompatibility/pull/823) +- :star: `PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters` sniff: account for the parameters for `array_merge()` and `array_merge_recursive()` becoming optional in PHP 7.4. [#817](https://github.com/PHPCompatibility/PHPCompatibility/pull/817) +- :star: `PHPCompatibility.IniDirectives.RemovedIniDirectives` sniff: recognize the `Payflow Pro/pfpro` ini directives as removed in PHP 5.1. [#823](https://github.com/PHPCompatibility/PHPCompatibility/pull/823) +- :star: Recognize the `interbase/Firebird` extension functionality which will be removed in PHP 7.4 (moved to PECL) in the `RemovedConstants`, `RemovedExtensions`, `RemovedFunctions` and `RemovedIniDirectives` sniffs. [#807](https://github.com/PHPCompatibility/PHPCompatibility/pull/807) +- :star: Recognize the `wddx` extension functionality which will be removed in PHP 7.4 (moved to PECL) in the `RemovedExtensions` and `RemovedFunctions` sniffs. [#826](https://github.com/PHPCompatibility/PHPCompatibility/pull/826) +- :star: New `isShortTernary()` and `isUnaryPlusMinus()` utility methods to the `PHPCompatibility\Sniff` class. [#810](https://github.com/PHPCompatibility/PHPCompatibility/pull/810), [#805](https://github.com/PHPCompatibility/PHPCompatibility/pull/805) + +### Changed +- :pencil2: The `PHPCompatibility.Extensions.RemovedExtensions` sniff will now only report on the removed `Payflow Pro` extension when a function uses `pfpro_` as a prefix. Previously, it used the `pfpro` prefix (without underscore) for detection. [#812](https://github.com/PHPCompatibility/PHPCompatibility/pull/812) +- :pencil2: The error message thrown when the `T_ELLIPSIS` token, i.e. the spread operator, is detected. [#803](https://github.com/PHPCompatibility/PHPCompatibility/pull/803) + PHP 7.4 adds a third use-case for the spread operator. The adjusted error message accounts for this. +- :umbrella: `PHPCompatibility.FunctionDeclarations.NewParamTypeDeclarations` is now also tested with parameters using the splat operator. [#802](https://github.com/PHPCompatibility/PHPCompatibility/pull/802) +- :books: The documentation now uses the GitHub repo of `PHP_CodeSniffer` as the canonical entry point for `PHP_CodeSniffer`. Previously, it would point to the PEAR package. [#788](https://github.com/PHPCompatibility/PHPCompatibility/pull/788) +- :books: The links in the changelog now all point to the `PHPCompatibility/PHPCompatibility` repo and no longer to the (deprecated) `wimg/PHPCompatibility` repo. [#828](https://github.com/PHPCompatibility/PHPCompatibility/pull/828) +- :recycle: Various minor inline documentation improvements. [#825](https://github.com/PHPCompatibility/PHPCompatibility/pull/825) +- :wrench: Various performance optimizations and code simplifications. [#783](https://github.com/PHPCompatibility/PHPCompatibility/pull/783), [#784](https://github.com/PHPCompatibility/PHPCompatibility/pull/784), [#795](https://github.com/PHPCompatibility/PHPCompatibility/pull/795), [#813](https://github.com/PHPCompatibility/PHPCompatibility/pull/813) +- :green_heart: Travis: build tests are now being run against PHP 7.4 (unstable) as well. [#790](https://github.com/PHPCompatibility/PHPCompatibility/pull/790) + Note: the builds are currently not (yet) tested against PHP 8.0 (unstable) as there is no compatible PHPUnit version available (yet). +- :wrench: Travis: The build script has been refactored to use [stages](https://docs.travis-ci.com/user/build-stages/) to get the most relevant results faster. Additionally some more tweaks have been made to improve and/or simplify the build script. [#798](https://github.com/PHPCompatibility/PHPCompatibility/pull/798) +- :wrench: Build/PHPCS: warnings are no longer allowed for the PHPCompatibility native code. [#800](https://github.com/PHPCompatibility/PHPCompatibility/pull/800) +- :wrench: Build/PHPCS: added variable assignment alignment check and file include check to the PHPCompatibility native CS configuration. [#824](https://github.com/PHPCompatibility/PHPCompatibility/pull/824) +- :wrench: The minimum version for the recommended `DealerDirect/phpcodesniffer-composer-installer` Composer plugin has been upped to `0.5.0`. [#791](https://github.com/PHPCompatibility/PHPCompatibility/pull/791) + +### Fixed +- :bug: The `PHPCompatibility.Extensions.RemovedExtensions` sniff contained a typo in the alternative recommended for the removed `mcve` extension. [#806](https://github.com/PHPCompatibility/PHPCompatibility/pull/806) +- :bug: The `PHPCompatibility.Extensions.RemovedExtensions` sniff listed the wrong removal version number for the `Payflow Pro/pfpro` extension (PHP 5.3 instead of the correct 5.1). [#823](https://github.com/PHPCompatibility/PHPCompatibility/pull/823) + +### Credits +Thanks go out to [Yılmaz] and [Tim Millwood] for their contribution to this version. :clap: + + +## [9.1.1] - 2018-12-31 + +See all related issues and PRs in the [9.1.1 milestone]. + +### Fixed +- :bug: `ForbiddenThisUseContexts`: false positive for unsetting `$this['key']` on objects implementing `ArrayAccess`. [#781](https://github.com/PHPCompatibility/PHPCompatibility/pull/781). Fixes [#780](https://github.com/PHPCompatibility/PHPCompatibility/issues/780) + +## [9.1.0] - 2018-12-16 + +See all related issues and PRs in the [9.1.0 milestone]. + +### Added +- :star2: New `PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue` sniff to detect code which could be affected by the PHP 7.0 change in the values reported by `func_get_arg()`, `func_get_args()`, `debug_backtrace()` and exception backtraces. [#750](https://github.com/PHPCompatibility/PHPCompatibility/pull/750). Fixes [#585](https://github.com/PHPCompatibility/PHPCompatibility/pull/585). +- :star2: New `PHPCompatibility.MethodUse.NewDirectCallsToClone` sniff to detect direct call to a `__clone()` magic method which wasn't allowed prior to PHP 7.0. [#743](https://github.com/PHPCompatibility/PHPCompatibility/pull/743). Fixes [#629](https://github.com/PHPCompatibility/PHPCompatibility/issues/629). +- :star2: New `PHPCompatibility.Variables.ForbiddenThisUseContext` sniff to detect most of the inconsistencies surrounding the use of the `$this` variable, which were removed in PHP 7.1. [#762](https://github.com/PHPCompatibility/PHPCompatibility/pull/762), [#771](https://github.com/PHPCompatibility/PHPCompatibility/pull/771). Fixes [#262](https://github.com/PHPCompatibility/PHPCompatibility/issues/262) and [#740](https://github.com/PHPCompatibility/PHPCompatibility/issues/740). +- :star: `NewClasses`: detection of more native PHP Exceptions. [#743](https://github.com/PHPCompatibility/PHPCompatibility/pull/743), [#753](https://github.com/PHPCompatibility/PHPCompatibility/pull/753) +- :star: `NewConstants` : detection of the new PHP 7.3 Curl, Stream Crypto and LDAP constants and some more PHP 7.0 Tokenizer constants. [#752](https://github.com/PHPCompatibility/PHPCompatibility/pull/752), [#767](https://github.com/PHPCompatibility/PHPCompatibility/pull/767), [#778](https://github.com/PHPCompatibility/PHPCompatibility/pull/778) +- :star: `NewFunctions` sniff: recognize (more) new LDAP functions as introduced in PHP 7.3. [#768](https://github.com/PHPCompatibility/PHPCompatibility/pull/768) +- :star: `NewFunctionParameters` sniff: recognize the new `$serverctrls` parameter which was added to a number of LDAP functions in PHP 7.3. [#769](https://github.com/PHPCompatibility/PHPCompatibility/pull/769) +- :star: `NewIniDirectives` sniff: recognize the new `imap.enable_insecure_rsh` ini directive as introduced in PHP 7.1.25, 7.2.13 and 7.3.0. [#770](https://github.com/PHPCompatibility/PHPCompatibility/pull/770) +- :star: `NewInterfaces` sniff: recognize two more Session related interfaces which were introduced in PHP 5.5.1 and 7.0 respectively. [#748](https://github.com/PHPCompatibility/PHPCompatibility/pull/748) +- :star: Duplicate of upstream `findStartOfStatement()` method to the `PHPCompatibility\PHPCSHelper` class to allow for PHPCS cross-version usage of that method. [#750](https://github.com/PHPCompatibility/PHPCompatibility/pull/750) + +### Changed +- :pushpin: `RemovedPHP4StyleConstructors`: will now also detect PHP4-style constructors when declared in interfaces. [#751](https://github.com/PHPCompatibility/PHPCompatibility/pull/751) +- :pushpin: `Sniff::validDirectScope()`: the return value of this method has changed. Previously it would always be a boolean. It will stil return `false` when no valid direct scope has been found, but it will now return the `stackPtr` to the scope token if a _valid_ direct scope was encountered. [#758](https://github.com/PHPCompatibility/PHPCompatibility/pull/758) +- :rewind: `NewOperators` : updated the version number for `T_COALESCE_EQUAL`. [#746](https://github.com/PHPCompatibility/PHPCompatibility/pull/746) +- :pencil: Minor improvement to an error message in the unit test suite. [#742](https://github.com/PHPCompatibility/PHPCompatibility/pull/742) +- :recycle: Various code clean-up and improvements. [#745](https://github.com/PHPCompatibility/PHPCompatibility/pull/745), [#756](https://github.com/PHPCompatibility/PHPCompatibility/pull/756), [#774](https://github.com/PHPCompatibility/PHPCompatibility/pull/774) +- :recycle: Various minor inline documentation fixes. [#749](https://github.com/PHPCompatibility/PHPCompatibility/pull/749), [#757](https://github.com/PHPCompatibility/PHPCompatibility/pull/757) +- :umbrella: Improved code coverage recording. [#744](https://github.com/PHPCompatibility/PHPCompatibility/pull/744), [#776](https://github.com/PHPCompatibility/PHPCompatibility/pull/776) +- :green_heart: Travis: build tests are now being run against PHP 7.3 as well. [#511](https://github.com/PHPCompatibility/PHPCompatibility/pull/511) + Note: full PHP 7.3 support is only available in combination with PHP_CodeSniffer 2.9.2 or 3.3.1+ due to an incompatibility within PHP_CodeSniffer itself. + +### Fixed +- :white_check_mark: Compatibility with the upcoming release of PHPCS 3.4.0. Deal with changed behaviour of the PHPCS `Tokenizer` regarding binary type casts. [#760](https://github.com/PHPCompatibility/PHPCompatibility/pull/760) +- :bug: `InternalInterfaces`: false negative for implemented/extended interfaces prefixed with a namespace separator. [#775](https://github.com/PHPCompatibility/PHPCompatibility/pull/775) +- :bug: `NewClasses`: the introduction version of various native PHP Exceptions has been corrected. [#743](https://github.com/PHPCompatibility/PHPCompatibility/pull/743), [#753](https://github.com/PHPCompatibility/PHPCompatibility/pull/753) +- :bug: `NewInterfaces`: false negative for implemented/extended interfaces prefixed with a namespace separator. [#775](https://github.com/PHPCompatibility/PHPCompatibility/pull/775) +- :bug: `RemovedPHP4StyleConstructors`: the sniff would examine methods in nested anonymous classes as if they were methods of the higher level class. [#751](https://github.com/PHPCompatibility/PHPCompatibility/pull/751) +- :rewind: `RemovedPHP4StyleConstructors`: the sniff will no longer throw false positives for the first method in an anonymous class when used in combination with PHPCS 2.3.x. [#751](https://github.com/PHPCompatibility/PHPCompatibility/pull/751) +- :rewind: `ReservedFunctionNames`: fixed incorrect error message text for methods in anonymous classes when used in combination with PHPCS 2.3.x. [#755](https://github.com/PHPCompatibility/PHPCompatibility/pull/755) +- :bug: `ReservedFunctionNames`: prevent duplicate errors being thrown for methods in nested anonymous classes. [#755](https://github.com/PHPCompatibility/PHPCompatibility/pull/755) +- :bug: `PHPCSHelper::findEndOfStatement()`: minor bug fix. [#749](https://github.com/PHPCompatibility/PHPCompatibility/pull/749) +- :bug: `Sniff::isClassProperty()`: class properties for classes nested in conditions or function calls were not always recognized as class properties. [#758](https://github.com/PHPCompatibility/PHPCompatibility/pull/758) + +### Credits +Thanks go out to [Jonathan Champ] for his contribution to this version. :clap: + + +## [9.0.0] - 2018-10-07 + +**IMPORTANT**: This release contains **breaking changes**. Please read the below information carefully before upgrading! + +All sniffs have been placed in meaningful categories and a number of sniffs have been renamed to have more consistent, meaningful and future-proof names. + +Both the `PHPCompatibilityJoomla` [[GH](https://github.com/PHPCompatibility/PHPCompatibilityJoomla) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-joomla)] as well as the `PHPCompatibilityWP` [[GH](https://github.com/PHPCompatibility/PHPCompatibilityWP)|[Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-wp)] rulesets have already been adjusted for this change and have released a new version which is compatible with this version of PHPCompatibility. + +Aside from those CMS-based rulesets, this project now also offers a number of polyfill-library specific rulesets, such as `PHPCompatibilityPasswordCompat` [[GH](https://github.com/PHPCompatibility/PHPCompatibilityPasswordCompat) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-passwordcompat)] for @ircmaxell's [`password_compat`](https://github.com/ircmaxell/password_compat) libary, `PHPCompatibilityParagonieRandomCompat` and `PHPCompatibilityParagonieSodiumCompat` [[GH](https://github.com/PHPCompatibility/PHPCompatibilityParagonie)|[Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-paragonie)] for the [Paragonie polyfills](https://github.com/paragonie?utf8=?&q=polyfill) and a number of rulesets related to various [polyfills offered by the Symfony project](https://github.com/symfony?utf8=?&q=polyfill) [[GH](https://github.com/PHPCompatibility/PHPCompatibilitySymfony)|[Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-symfony)]. + +If your project uses one of these polyfills, please consider using these special polyfill rulesets to prevent false positives. + +Also as of this version, [Juliette Reinders Folmer] is now officially a co-maintainer of this package. + +### Upgrade instructions + +* If you have `<exclude name="..."/>` directives in your own project's custom ruleset which relate to sniffs from the PHPCompatibility library, you will need to update your ruleset to use the new sniff names. +* If you use the new [PHPCS 3.2+ inline annotations](https://github.com/squizlabs/PHP_CodeSniffer/releases/3.2.0), i.e. `// phpcs:ignore Standard.Category.SniffName`, in combination with PHPCompatibility sniff names, you will need to update these annotations. +* If you use neither of the above, you should be fine and upgrading should be painless. + +### Overview of all the sniff renames: + +Old Category.SniffName | New Category.SniffName +--- | --- +**PHP**.ArgumentFunctionsUsage | **FunctionUse**.ArgumentFunctionsUsage +**PHP**.CaseSensitiveKeywords | **Keywords**.CaseSensitiveKeywords +**PHP**.ConstantArraysUsingConst | **InitialValue**.**New**ConstantArraysUsingConst +**PHP**.ConstantArraysUsingDefine | **InitialValue**.**New**ConstantArraysUsingDefine +**PHP**.**Deprecated**Functions | **FunctionUse**.**Removed**Functions +**PHP**.**Deprecated**IniDirectives | **IniDirectives**.**Removed**IniDirectives +**PHP**.**Deprecated**MagicAutoload | **FunctionNameRestrictions**.**Removed**MagicAutoload +**PHP**.**Deprecated**NewReference | **Syntax**.**Removed**NewReference +**PHP**.**Deprecated**PHP4StyleConstructors | **FunctionNameRestrictions**.**Removed**PHP4StyleConstructors +**PHP**.**Deprecated**TypeCasts | **TypeCasts**.**Removed**TypeCasts +**PHP**.DiscouragedSwitchContinue | **ControlStructures**.DiscouragedSwitchContinue +**PHP**.DynamicAccessToStatic | **Syntax**.**New**DynamicAccessToStatic +**PHP**.EmptyNonVariable | **LanguageConstructs**.**New**EmptyNonVariable +**PHP**.ForbiddenBreakContinueOutsideLoop | **ControlStructures**.ForbiddenBreakContinueOutsideLoop +**PHP**.ForbiddenBreakContinueVariableArguments | **ControlStructures**.ForbiddenBreakContinueVariableArguments +**PHP**.ForbiddenCallTimePassByReference | **Syntax**.ForbiddenCallTimePassByReference +**PHP**.Forbidden**ClosureUseVariableNames** | **FunctionDeclarations**.Forbidden**VariableNamesInClosureUse** +**PHP**.ForbiddenEmptyListAssignment | **Lists**.ForbiddenEmptyListAssignment +**PHP**.Forbidden**Function**ParametersWithSameName | **FunctionDeclarations**.ForbiddenParametersWithSameName +**PHP**.ForbiddenGlobalVariableVariable | **Variables**.ForbiddenGlobalVariableVariable +**PHP**.ForbiddenNames | **Keywords**.ForbiddenNames +**PHP**.ForbiddenNamesAsDeclared | **Keywords**.ForbiddenNamesAsDeclared +**PHP**.ForbiddenNamesAsInvokedFunctions | **Keywords**.ForbiddenNamesAsInvokedFunctions +**PHP**.ForbiddenNegativeBitshift | **Operators**.ForbiddenNegativeBitshift +**PHP**.ForbiddenSwitchWithMultipleDefaultBlocks | **ControlStructures**.ForbiddenSwitchWithMultipleDefaultBlocks +**PHP**.InternalInterfaces | **Interfaces**.InternalInterfaces +**PHP**.LateStaticBinding | **Classes**.**New**LateStaticBinding +**PHP**.**MbstringReplaceE**Modifier | **ParameterValues**.**RemovedMbstring**Modifier**s** +**PHP**.NewAnonymousClasses | **Classes**.NewAnonymousClasses +**PHP**.NewArrayStringDereferencing | **Syntax**.NewArrayStringDereferencing +**PHP**.NewClasses | **Classes**.NewClasses +**PHP**.NewClassMemberAccess | **Syntax**.NewClassMemberAccess +**PHP**.NewClosure | **FunctionDeclarations**.NewClosure +**PHP**.NewConstants | **Constants**.NewConstants +**PHP**.NewConstantScalarExpressions | **InitialValue**.NewConstantScalarExpressions +**PHP**.NewConstVisibility | **Classes**.NewConstVisibility +**PHP**.NewExecutionDirectives | **ControlStructures**.NewExecutionDirectives +**PHP**.NewFunctionArrayDereferencing | **Syntax**.NewFunctionArrayDereferencing +**PHP**.NewFunctionParameters | **FunctionUse**.NewFunctionParameters +**PHP**.NewFunctions | **FunctionUse**.NewFunctions +**PHP**.NewGeneratorReturn | **Generators**.NewGeneratorReturn +**PHP**.NewGroupUseDeclarations | **UseDeclarations**.NewGroupUseDeclarations +**PHP**.NewHashAlgorithms | **ParameterValues**.NewHashAlgorithms +**PHP**.NewHeredoc**Initialize** | **InitialValue**.NewHeredoc +**PHP**.NewIniDirectives | **IniDirectives**.NewIniDirectives +**PHP**.NewInterfaces | **Interfaces**.NewInterfaces +**PHP**.NewKeywords | **Keywords**.NewKeywords +**PHP**.NewLanguageConstructs | **LanguageConstructs**.NewLanguageConstructs +**PHP**.NewMagicClassConstant | **Constants**.NewMagicClassConstant +**PHP**.NewMagicMethods | **FunctionNameRestrictions**.NewMagicMethods +**PHP**.NewMultiCatch | **ControlStructures**.NewMultiCatch +**PHP**.NewNullableTypes | **FunctionDeclarations**.NewNullableTypes +**PHP**.NewReturnTypeDeclarations | **FunctionDeclarations**.NewReturnTypeDeclarations +**PHP**.New**Scalar**TypeDeclarations | **FunctionDeclarations**.New**Param**TypeDeclarations +**PHP**.NewTrailingComma | **Syntax**.New**FunctionCall**TrailingComma +**PHP**.NewTypeCasts | **TypeCasts**.NewTypeCasts +**PHP**.NewUseConstFunction | **UseDeclarations**.NewUseConstFunction +**PHP**.NonStaticMagicMethods | **FunctionDeclarations**.NonStaticMagicMethods +**PHP**.OptionalRequiredFunctionParameters | **FunctionUse**.Optional**To**RequiredFunctionParameters +**PHP**.ParameterShadowSuperGlobals | **FunctionDeclarations**.**Forbidden**ParameterShadowSuperGlobals +**PHP**.**PCRENew**Modifiers | **ParameterValues**.**NewPCRE**Modifiers +**PHP**.**PregReplaceE**Modifier | **ParameterValues**.**RemovedPCRE**Modifier**s** +**PHP**.RemovedAlternativePHPTags | **Miscellaneous**.RemovedAlternativePHPTags +**PHP**.RemovedConstants | **Constants**.RemovedConstants +**PHP**.RemovedExtensions | **Extensions**.RemovedExtensions +**PHP**.RemovedFunctionParameters | **FunctionUse**.RemovedFunctionParameters +**PHP**.RemovedGlobalVariables | **Variables**.Removed**Predefined**GlobalVariables +**PHP**.RemovedHashAlgorithms | **ParameterValues**.RemovedHashAlgorithms +**PHP**.ReservedFunctionNames | **FunctionNameRestrictions**.ReservedFunctionNames +**PHP**.RequiredOptionalFunctionParameters | **FunctionUse**.Required**To**OptionalFunctionParameters +**PHP**.ShortArray | **Syntax**.**New**ShortArray +**PHP**.Ternary**Operators** | **Operators**.**NewShort**Ternary +**PHP**.ValidIntegers | **Miscellaneous**.ValidIntegers +**PHP**.**VariableVariables** | **Variables**.**NewUniformVariableSyntax** + +### Changelog for version 9.0.0 + +See all related issues and PRs in the [9.0.0 milestone]. + +### Added +- :star2: New `PHPCompatibility.ControlStructures.NewForeachExpressionReferencing` sniff to detect referencing of `$value` within a `foreach()` when the iterated array is not a variable. This was not supported prior to PHP 5.5. [#664](https://github.com/PHPCompatibility/PHPCompatibility/pull/664) +- :star2: New `PHPCompatibility.ControlStructures.NewListInForeach` sniff to detect unpacking nested arrays into separate variables via the `list()` construct in a `foreach()` statement. This was not supported prior to PHP 5.5. [#657](https://github.com/PHPCompatibility/PHPCompatibility/pull/657) +- :star2: New `PHPCompatibility.FunctionNameRestrictions.RemovedNamespacedAssert` sniff to detect declaring a function called `assert()` within a namespace. This has been deprecated as of PHP 7.3. [#735](https://github.com/PHPCompatibility/PHPCompatibility/pull/735). Partially fixes [#718](https://github.com/PHPCompatibility/PHPCompatibility/issues/718). +- :star2: New `PHPCompatibility.Lists.AssignmentOrder` sniff to detect `list()` constructs affected by the change in assignment order in PHP 7.0. [#656](https://github.com/PHPCompatibility/PHPCompatibility/pull/656) +- :star2: New `PHPCompatibility.Lists.NewKeyedList` sniff to detect usage of keys in `list()`, support for which was added in PHP 7.1. [#655](https://github.com/PHPCompatibility/PHPCompatibility/pull/655). Fixes [#252](https://github.com/PHPCompatibility/PHPCompatibility/issues/252). +- :star2: New `PHPCompatibility.Lists.NewListReferenceAssignment` sniff to detect reference assignments being used in `list()` constructs, support for which has been added in PHP 7.3. [#731](https://github.com/PHPCompatibility/PHPCompatibility/pull/731) +- :star2: New `PHPCompatibility.Lists.NewShortList` sniff to detect the shorthand array syntax `[]` being used for symmetric array destructuring as introduced in PHP 7.1. [#654](https://github.com/PHPCompatibility/PHPCompatibility/pull/654). Fixes [#248](https://github.com/PHPCompatibility/PHPCompatibility/issues/248). +- :star2: New `PHPCompatibility.Operators.NewOperators` sniff which checks for usage of the pow, pow equals, spaceship and coalesce (equals) operators. [#738](https://github.com/PHPCompatibility/PHPCompatibility/pull/738) + These checks were previously contained within the `PHPCompatibility.LanguageConstructs.NewLanguageConstructs` sniff. +- :star2: New `PHPCompatibility.ParameterValues.ForbiddenGetClassNull` sniff to detect `null` being passed to `get_class()`, support for which has been removed in PHP 7.2 [#659](https://github.com/PHPCompatibility/PHPCompatibility/pull/659). Fixes [#557](https://github.com/PHPCompatibility/PHPCompatibility/issues/557). +- :star2: New `PHPCompatibility.ParameterValues.NewArrayReduceInitialType` sniff to detect non-integers being passed as the `$initial` parameter to the `array_reduce()` function, which was not supported before PHP 5.3. [#666](https://github.com/PHPCompatibility/PHPCompatibility/pull/666). Fixes [#649](https://github.com/PHPCompatibility/PHPCompatibility/issues/649) +- :star2: New `PHPCompatibility.ParameterValues.NewFopenModes` sniff to examine the `$mode` parameter passed to `fopen()` for modes not available in older PHP versions. [#658](https://github.com/PHPCompatibility/PHPCompatibility/pull/658) +- :star2: New `PHPCompatibility.ParameterValues.NewNegativeStringOffset` sniff to detect negative string offsets being passed to string manipulation functions which was not supported before PHP 7.1. [#662](https://github.com/PHPCompatibility/PHPCompatibility/pull/662). Partially fixes [#253](https://github.com/PHPCompatibility/PHPCompatibility/issues/253). +- :star2: New `PHPCompatibility.ParameterValues.NewPackFormats` sniff to examine the `$format` parameter passed to `pack()` for formats not available in older PHP versions. [#665](https://github.com/PHPCompatibility/PHPCompatibility/pull/665) +- :star2: New `PHPCompatibility.ParameterValues.RemovedIconvEncoding` sniff to detect the PHP 5.6 deprecated encoding `$type`s being passed to `iconv_set_encoding()`. [#660](https://github.com/PHPCompatibility/PHPCompatibility/pull/660). Fixes [#475](https://github.com/PHPCompatibility/PHPCompatibility/issues/475). +- :star2: New `PHPCompatibility.ParameterValues.RemovedNonCryptoHashes` sniff to detect non-cryptographic hash algorithms being passed to various `hash_*()` functions. This is no longer accepted as of PHP 7.2. [#663](https://github.com/PHPCompatibility/PHPCompatibility/pull/663). Fixes [#559](https://github.com/PHPCompatibility/PHPCompatibility/issues/559) +- :star2: New `PHPCompatibility.ParameterValues.RemovedSetlocaleString` sniff to detect string literals being passed to the `$category` parameter of the `setlocale()` function. This behaviour was deprecated in PHP 4.2 and support has been removed in PHP 7.0. [#661](https://github.com/PHPCompatibility/PHPCompatibility/pull/661) +- :star2: New `PHPCompatibility.Syntax.NewFlexibleHeredocNowdoc` sniff to detect the new heredoc/nowdoc format as allowed as of PHP 7.3. [#736](https://github.com/PHPCompatibility/PHPCompatibility/pull/736). Fixes [#705](https://github.com/PHPCompatibility/PHPCompatibility/issues/705). + Note: This sniff is only supported in combination with PHP_CodeSniffer 2.6.0 and higher. +- :star: `PHPCompatibility.Classes.NewClasses` sniff: recognize the new `CompileError` and `JsonException` classes as introduced in PHP 7.3. [#676](https://github.com/PHPCompatibility/PHPCompatibility/pull/676) +- :star: `PHPCompatibility.Constants.NewConstants` sniff: recognize new constants which are being introduced in PHP 7.3. [#678](https://github.com/PHPCompatibility/PHPCompatibility/pull/678) +- :star: `PHPCompatibility.Constants.RemovedConstants` sniff: recognize constants which have been deprecated or removed in PHP 7.3. [#710](https://github.com/PHPCompatibility/PHPCompatibility/pull/710). Partially fixes [#718](https://github.com/PHPCompatibility/PHPCompatibility/issues/718). +- :star: `PHPCompatibility.FunctionUse.NewFunctions` sniff: recognize various new functions being introduced in PHP 7.3. [#679](https://github.com/PHPCompatibility/PHPCompatibility/pull/679) +- :star: `PHPCompatibility.FunctionUse.NewFunctions` sniff: recognize the `sapi_windows_*()`, `hash_hkdf()` and `pcntl_signal_get_handler()` functions as introduced in PHP 7.1. [#728](https://github.com/PHPCompatibility/PHPCompatibility/pull/728) +- :star: `PHPCompatibility.FunctionUse.RemovedFunctionParameters` sniff: recognize the deprecation of the `$case_insensitive` parameter for the `define()` function in PHP 7.3. [#706](https://github.com/PHPCompatibility/PHPCompatibility/pull/706) +- :star: `PHPCompatibility.FunctionUse.RemovedFunctions` sniff: recognize the PHP 7.3 deprecation of the `image2wbmp()`, `fgetss()` and `gzgetss()` functions, as well as the deprecation of undocumented Mbstring function aliases. [#681](https://github.com/PHPCompatibility/PHPCompatibility/pull/681), [#714](https://github.com/PHPCompatibility/PHPCompatibility/pull/714), [#720](https://github.com/PHPCompatibility/PHPCompatibility/pull/720). Partially fixes [#718](https://github.com/PHPCompatibility/PHPCompatibility/issues/718). +- :star: `PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters` sniff: account for the second parameter for `array_push()` and `array_unshift()` becoming optional in PHP 7.3, as well as for the `$mode` parameter for a range of `ftp_*()` functions becoming optional. [#680](https://github.com/PHPCompatibility/PHPCompatibility/pull/680) +- :star: `PHPCompatibility.IniDirectives.NewIniDirectives` sniff: recognize new `syslog` and `session` ini directives as introduced in PHP 7.3. [#702](https://github.com/PHPCompatibility/PHPCompatibility/pull/702), [#719](https://github.com/PHPCompatibility/PHPCompatibility/pull/719), [#730](https://github.com/PHPCompatibility/PHPCompatibility/pull/730) +- :star: `PHPCompatibility.IniDirectives.NewIniDirectives` sniff: recognize some more ini directives which were introduced in PHP 7.1. [#727](https://github.com/PHPCompatibility/PHPCompatibility/pull/727) +- :star: `PHPCompatibility.IniDirectives.RemovedIniDirectived` sniff: recognize ini directives removed in PHP 7.3. [#677](https://github.com/PHPCompatibility/PHPCompatibility/pull/677), [#717](https://github.com/PHPCompatibility/PHPCompatibility/pull/717). Partially fixes [#718](https://github.com/PHPCompatibility/PHPCompatibility/issues/718). +- :star: New `isNumericCalculation()` and `isVariable()` utility methods to the `PHPCompatibility\Sniff` class. [#664](https://github.com/PHPCompatibility/PHPCompatibility/pull/664), [#666](https://github.com/PHPCompatibility/PHPCompatibility/pull/666) +- :books: A section about the new sniff naming conventions to the `Contributing` file. [#738](https://github.com/PHPCompatibility/PHPCompatibility/pull/738) + +### Changed +- :fire: All sniffs have been placed in meaningful categories and a number of sniffs have been renamed to have more consistent, meaningful and future-proof names. [#738](https://github.com/PHPCompatibility/PHPCompatibility/pull/738). Fixes [#601](https://github.com/PHPCompatibility/PHPCompatibility/issues/601), [#692](https://github.com/PHPCompatibility/PHPCompatibility/issues/692) + See the table at the top of this changelog for details of all the file renames. +- :umbrella: The unit test files have been moved about as well. [#738](https://github.com/PHPCompatibility/PHPCompatibility/pull/738) + * The directory structure for these now mirrors the default directory structure used by PHPCS itself. + * The file names of the unit test files have been adjusted for the changes made in the sniffs. + * The unit test case files have been renamed and moved to the same directory as the actual test file they apply to. + * The `BaseSniffTest::sniffFile()` method has been adjusted to match. The signature of this method has changed. Where it previously expected a relative path to the unit test case file, it now expects an absolute path. + * The unit tests for the utility methods in the `PHPCompatibility\Sniff` class have been moved to a new `PHPCompatibility\Util\Tests\Core` subdirectory. + * The bootstrap file used for PHPUnit has been moved to the project root directory and renamed `phpunit-bootstrap.php`. +- :twisted_rightwards_arrows: The `PHPCompatibility.LanguageConstructs.NewLanguageConstructs` sniff has been split into two sniffs. [#738](https://github.com/PHPCompatibility/PHPCompatibility/pull/738) + The `PHPCompatibility.LanguageConstructs.NewLanguageConstructs` sniff now contains just the checks for the namespace separator and the ellipsis. + The new `PHPCompatibility.Operators.NewOperators` sniff now contains the checks regarding the pow, pow equals, spaceship and coalesce (equals) operators. +- :pushpin: The `PHPCompatibility.ParameterValues.RemovedMbstringModifiers` sniff will now also recognize removed regex modifiers when used within a function call to one of the undocumented Mbstring function aliases for the Mbstring regex functions. [#715](https://github.com/PHPCompatibility/PHPCompatibility/pull/715) +- :pushpin: The `PHPCompatibility\Sniff::getFunctionCallParameter()` utility method now allows for closures called via a variable. [#723](https://github.com/PHPCompatibility/PHPCompatibility/pull/723) +- :pencil2: `PHPCompatibility.Upgrade.LowPHPCS`: the minimum supported PHPCS version is now 2.3.0. [#699](https://github.com/PHPCompatibility/PHPCompatibility/pull/699) +- :pencil2: Minor inline documentation improvements. [#738](https://github.com/PHPCompatibility/PHPCompatibility/pull/738) +- :umbrella: Minor improvements to the unit tests for the `PHPCompatibility.FunctionNameRestrctions.RemovedMagicAutoload` sniff. [#716](https://github.com/PHPCompatibility/PHPCompatibility/pull/716) +- :recycle: Minor other optimizations. [#698](https://github.com/PHPCompatibility/PHPCompatibility/pull/698), [#697](https://github.com/PHPCompatibility/PHPCompatibility/pull/697) +- :wrench: Minor improvements to the build tools. [#701](https://github.com/PHPCompatibility/PHPCompatibility/pull/701) +- :wrench: Removed some unnecessary inline annotations. [#700](https://github.com/PHPCompatibility/PHPCompatibility/pull/700) +- :books: Replaced some of the badges in the Readme file. [#721](https://github.com/PHPCompatibility/PHPCompatibility/pull/721), [#722](https://github.com/PHPCompatibility/PHPCompatibility/pull/722) +- :books: Composer: updated the list of package authors. [#739](https://github.com/PHPCompatibility/PHPCompatibility/pull/739) + +### Removed +- :no_entry_sign: Support for PHP_CodeSniffer 1.x and low 2.x versions. The new minimum version of PHP_CodeSniffer to be able to use this library is 2.3.0. [#699](https://github.com/PHPCompatibility/PHPCompatibility/pull/699). Fixes [#691](https://github.com/PHPCompatibility/PHPCompatibility/issues/691). + The minimum _recommended_ version of PHP_CodeSniffer remains the same, i.e. 2.6.0. +- :no_entry_sign: The `\PHPCompatibility\Sniff::inUseScope()` method has been removed as it is no longer needed now support for PHPCS 1.x has been dropped. [#699](https://github.com/PHPCompatibility/PHPCompatibility/pull/699) +- :no_entry_sign: Composer: The `autoload` section has been removed from the `composer.json` file. [#738](https://github.com/PHPCompatibility/PHPCompatibility/pull/738). Fixes [#568](https://github.com/PHPCompatibility/PHPCompatibility/issues/568). + Autoloading for this library is done via the PHP_CodeSniffer default mechanism, enhanced with our own autoloader, so the Composer autoloader shouldn't be needed and was causing issues in a particular use-case. + +### Fixed +- :bug: `PHPCompatibility.FunctionUse.NewFunctionParameters` sniff: The new `$mode` parameter of the `php_uname()` function was added in PHP 4.3, not in PHP 7.0 as was previously being reported. + The previous implementation of this check was based on an error in the PHP documentation. The error in the PHP documentation has been rectified and the sniff has followed suit. [#711](https://github.com/PHPCompatibility/PHPCompatibility/pull/711) +- :bug: `PHPCompatibility.Generators.NewGeneratorReturn` sniff: The sniff would throw false positives for `return` statements in nested constructs and did not correctly detect the scope which should be examined. [#725](https://github.com/PHPCompatibility/PHPCompatibility/pull/725). Fixes [#724](https://github.com/PHPCompatibility/PHPCompatibility/pull/724). +- :bug: `PHPCompatibility.Keywords.NewKeywords` sniff: PHP magic constants are case _in_sensitive. This sniff now accounts for this. [#707](https://github.com/PHPCompatibility/PHPCompatibility/pull/707) +- :bug: Various bugs in the `PHPCompatibility.Syntax.ForbiddenCallTimePassByReference` sniff [#723](https://github.com/PHPCompatibility/PHPCompatibility/pull/723): + - Closures called via a variable will now also be examined. (false negative) + - References within arrays/closures passed as function call parameters would incorrectly trigger an error. (false positive) +- :green_heart: Compatibility with PHPUnit 7.2. [#712](https://github.com/PHPCompatibility/PHPCompatibility/pull/712) + +### Credits +Thanks go out to [Jonathan Champ] for his contribution to this version. :clap: + + +## [8.2.0] - 2018-07-17 + +See all related issues and PRs in the [8.2.0 milestone]. + +### Important changes + +#### The repository has moved +As of July 13 2018, the PHPCompatibility repository has moved from the personal account of Wim Godden `wimg` to its own organization `PHPCompatibility`. +Composer users are advised to update their `composer.json`. The dependency is now called `phpcompatibility/php-compatibility`. + +#### Framework/CMS specific PHPCompatibility rulesets +Within this new organization, hosting will be offered for framework/CMS specific PHPCompatibility rulesets. + +The first two such repositories have been created and are now available for use: +* PHPCompatibilityJoomla [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityJoomla)|[Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-joomla) +* PHPCompatibilityWP [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityWP)|[Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-wp) + +If you want to make sure you have all PHPCompatibility rulesets available at any time, you can use the PHPCompatibilityAll package [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityAll)|[Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-all). + +For more information, see the [Readme](https://github.com/PHPCompatibility/PHPCompatibility#using-a-frameworkcms-specific-ruleset) and [Contributing guidelines](https://github.com/PHPCompatibility/PHPCompatibility/blob/master/.github/CONTRIBUTING.md#frameworkcms-specific-rulesets). + +#### Changes expected in PHPCompatibility 9.0.0 +The next version of PHPCompatibility will include a major directory layout restructuring which means that the sniff codes of all sniffs will change. + +In this same release, support for PHP_CodeSniffer 1.5.x will be dropped. The new minimum supported PHPCS version will be 2.3.0. + +For more information about these upcoming changes, please read the [announcement](https://github.com/PHPCompatibility/PHPCompatibility/issues/688). + +The `9.0.0` release is expected to be ready later this summer. + + +### Added +- :star2: New `ArgumentFunctionsUsage` sniff to detect usage of the `func_get_args()`, `func_get_arg()` and `func_num_args()` functions and the changes regarding these functions introduced in PHP 5.3. [#596](https://github.com/PHPCompatibility/PHPCompatibility/pull/596). Fixes [#372](https://github.com/PHPCompatibility/PHPCompatibility/issues/372). +- :star2: New `DiscouragedSwitchContinue` sniff to detect `continue` targetting a `switch` control structure for which `E_WARNINGS` will be thrown as of PHP 7.3. [#687](https://github.com/PHPCompatibility/PHPCompatibility/pull/687) +- :star2: New `NewClassMemberAccess` sniff to detect class member access on instantiation as added in PHP 5.4 and class member access on cloning as added in PHP 7.0. [#619](https://github.com/PHPCompatibility/PHPCompatibility/pull/619). Fixes [#53](https://github.com/PHPCompatibility/PHPCompatibility/issues/53). +- :star2: New `NewConstantScalarExpressions` sniff to detect PHP 5.6 scalar expression in contexts where PHP previously only allowed static values. [#617](https://github.com/PHPCompatibility/PHPCompatibility/pull/617). Fixes [#399](https://github.com/PHPCompatibility/PHPCompatibility/issues/399). +- :star2: New `NewGeneratorReturn` sniff to detect `return` statements within generators as introduced in PHP 7.0. [#618](https://github.com/PHPCompatibility/PHPCompatibility/pull/618) +- :star2: New `PCRENewModifiers` sniff to initially detect the new `J` regex modifier as introduced in PHP 7.2. [#600](https://github.com/PHPCompatibility/PHPCompatibility/pull/600). Fixes [#556](https://github.com/PHPCompatibility/PHPCompatibility/issues/556). +- :star2: New `ReservedFunctionNames` sniff to report on double underscore prefixed functions and methods. This was previously reported via an upstream sniff. [#581](https://github.com/PHPCompatibility/PHPCompatibility/pull/581) +- :star2: New `NewTrailingComma` sniff to detect trailing comma's in function calls, method calls, `isset()` and `unset()` as will be introduced in PHP 7.3. [#632](https://github.com/PHPCompatibility/PHPCompatibility/pull/632) +- :star2: New `Upgrade/LowPHPCS` sniff to give users of old PHP_CodeSniffer versions advance warning when support will be dropped in the near future. [#693](https://github.com/PHPCompatibility/PHPCompatibility/pull/693) +- :star: `NewClasses` sniff: check for some 40+ additional PHP native classes added in various PHP versions. [#573](https://github.com/PHPCompatibility/PHPCompatibility/pull/573) +- :star: `NewClosure` sniff: check for usage of `self`/`parent`/`static::` being used within closures, support for which was only added in PHP 5.4. [#669](https://github.com/PHPCompatibility/PHPCompatibility/pull/669). Fixes [#668](https://github.com/PHPCompatibility/PHPCompatibility/pull/668). +- :star: `NewConstants` sniff: recognize constants added by the PHP 5.5+ password extension. [#626](https://github.com/PHPCompatibility/PHPCompatibility/pull/626) +- :star: `NewFunctionParameters` sniff: recognize a number of additional function parameters added in PHP 7.0, 7.1 and 7.2. [#602](https://github.com/PHPCompatibility/PHPCompatibility/pull/602) +- :star: `NewFunctions` sniff: recognize the PHP 5.1 SPL extension functions, the PHP 5.1.1 `hash_hmac()` function, the PHP 5.6 `pg_lo_truncate()` function, more PHP 7.2 Sodium functions and the new PHP 7.3 `is_countable()` function. [#606](https://github.com/PHPCompatibility/PHPCompatibility/pull/606), [#625](https://github.com/PHPCompatibility/PHPCompatibility/pull/625), [#640](https://github.com/PHPCompatibility/PHPCompatibility/pull/640), [#651](https://github.com/PHPCompatibility/PHPCompatibility/pull/651) +- :star: `NewHashAlgorithms` sniff: recognize the new hash algorithms which were added in PHP 7.1. [#599](https://github.com/PHPCompatibility/PHPCompatibility/pull/599) +- :star: `NewInterfaces` sniff: check for the PHP 5.0 `Reflector` interface. [#572](https://github.com/PHPCompatibility/PHPCompatibility/pull/572) +- :star: `OptionalRequiredFunctionParameters` sniff: detect missing `$salt` parameter in calls to the `crypt()` function (PHP 5.6+). [#605](https://github.com/PHPCompatibility/PHPCompatibility/pull/605) +- :star: `RequiredOptionalFunctionParameters` sniff: recognize that the `$varname` parameter of `getenv()` and the `$scale` parameter of `bcscale()` have become optional as of PHP 7.1 and 7.3 respectively. [#598](https://github.com/PHPCompatibility/PHPCompatibility/pull/598), [#612](https://github.com/PHPCompatibility/PHPCompatibility/pull/612) +- :star: New `AbstractFunctionCallParameterSniff` to be used as a basis for sniffs examining function call parameters. [#636](https://github.com/PHPCompatibility/PHPCompatibility/pull/636) +- :star: New `getReturnTypeHintName()` utility method to the `PHPCompatibility\Sniff` class. [#578](https://github.com/PHPCompatibility/PHPCompatibility/pull/578), [#642](https://github.com/PHPCompatibility/PHPCompatibility/pull/642) +- :star: New `isNumber()`, `isPositiveNumber()` and `isNegativeNumber()` utility methods to the `PHPCompatibility\Sniff` class. [#610](https://github.com/PHPCompatibility/PHPCompatibility/pull/610), [#650](https://github.com/PHPCompatibility/PHPCompatibility/pull/650) +- :star: New `isShortList()` utility method to the `PHPCompatibility\Sniff` class. [#635](https://github.com/PHPCompatibility/PHPCompatibility/pull/635) +- :star: New `getCommandLineData()` method to the `PHPCompatibility\PHPCSHelper` class to provide PHPCS cross-version compatible access to command line info at run time. [#693](https://github.com/PHPCompatibility/PHPCompatibility/pull/693) +- :star: Duplicate of upstream `findEndOfStatement()` method to the `PHPCompatibility\PHPCSHelper` class to allow for PHPCS cross-version usage of that method. [#614](https://github.com/PHPCompatibility/PHPCompatibility/pull/614) +- :umbrella: additional unit test to confirm that the `PHPCompatibility\Sniff::isUseOfGlobalConstant()` method handles multi-constant declarations correctly. [#587](https://github.com/PHPCompatibility/PHPCompatibility/pull/587) +- :umbrella: additional unit tests to confirm that the `PHPCompatibility\Sniff::isClassProperty()` method handles multi-property declarations correctly. [#583](https://github.com/PHPCompatibility/PHPCompatibility/pull/583) +- :books: [Readme](https://github.com/PHPCompatibility/PHPCompatibility#using-a-frameworkcms-specific-ruleset) & [Contributing](https://github.com/PHPCompatibility/PHPCompatibility/blob/master/.github/CONTRIBUTING.md#frameworkcms-specific-rulesets): add information about the framework/CMS specific rulesets. Related PRs: [#615](https://github.com/PHPCompatibility/PHPCompatibility/pull/615), [#624](https://github.com/PHPCompatibility/PHPCompatibility/pull/624), [#648](https://github.com/PHPCompatibility/PHPCompatibility/pull/648), [#674](https://github.com/PHPCompatibility/PHPCompatibility/pull/674), [#685](https://github.com/PHPCompatibility/PHPCompatibility/pull/685), [#694](https://github.com/PHPCompatibility/PHPCompatibility/pull/694). Related to issue [#530](https://github.com/PHPCompatibility/PHPCompatibility/issues/530). +- :books: Readme: information about the PHPCS 3.3.0 change which allows for a `testVersion` in a custom ruleset to be overruled by the command-line. [#607](https://github.com/PHPCompatibility/PHPCompatibility/pull/607) + +### Changed +- :books: Adjusted references to the old repository location throughout the codebase to reflect the move to a GitHub organization. [#689](https://github.com/PHPCompatibility/PHPCompatibility/pull/689) + This repository will now live in [https://github.com/PHPCompatibility/PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility) and the Packagist reference will now be `phpcompatibility/php-compatibility`. +- :white_check_mark: The `getReturnTypeHintToken()` utility method has been made compatible with the changes in the PHPCS tokenizer which were introduced in PHP_CodeSniffer 3.3.0. [#642](https://github.com/PHPCompatibility/PHPCompatibility/pull/642). Fixes [#639](https://github.com/PHPCompatibility/PHPCompatibility/issues/639). +- :pushpin: `ConstantArrayUsingConst`: improved handling of multi-constant declarations. [#593](https://github.com/PHPCompatibility/PHPCompatibility/pull/593) +- :pushpin: `NewHeredocInitialize`: improved handling of constant declarations using the `const` keyword. + The sniff will now also report on multi-declarations for variables, constants and class properties and on using heredoc as a function parameter default. [#641](https://github.com/PHPCompatibility/PHPCompatibility/pull/641) +- :pushpin: `ForbiddenEmptyListAssignment`: this sniff will now also report on empty list assignments when the PHP 7.1 short list syntax is used. [#653](https://github.com/PHPCompatibility/PHPCompatibility/pull/653) +- :pushpin: The `ForbiddenNegativeBitshift` sniff would previously only report on "bitshift right". As of this version, "bitshift left" and bitshift assignments will also be recognized. [#614](https://github.com/PHPCompatibility/PHPCompatibility/pull/614) +- :pushpin: The `NewClasses` and `NewInterfaces` sniffs will now also report on new classes/interfaces when used as _return type_ declarations. [#578](https://github.com/PHPCompatibility/PHPCompatibility/pull/578) +- :pushpin: The `NewScalarTypeDeclarations` sniff will now recognize `parent` as a valid type declaration. + The sniff will now also throw an error about using `self` and `parent` when PHP < 5.2 needs to be supported as PHP 5.1 and lower would presume these to be class names instead of keywords. [#595](https://github.com/PHPCompatibility/PHPCompatibility/pull/595) +- :pushpin: The `PregReplaceEModifier` sniff - and the `PCRENewModifiers` sniff by extension - will now correctly examine and report on modifiers in regexes passed via calls to `preg_replace_callback_array()`. [#600](https://github.com/PHPCompatibility/PHPCompatibility/pull/600), [#636](https://github.com/PHPCompatibility/PHPCompatibility/pull/636) +- :pushpin: `getReturnTypeHintToken()` utility method: improved support for interface methods and abstract function declarations. [#652](https://github.com/PHPCompatibility/PHPCompatibility/pull/652) +- :pushpin: The `findExtendedClassName()`, `findImplementedInterfaceNames()`, `getMethodParameters()` utility methods which are duplicates of upstream PHPCS methods, have been moved from the `PHPCompatibility\Sniff` class to the `PHPCompatibility\PHPCSHelper` class and have become static methods. [#613](https://github.com/PHPCompatibility/PHPCompatibility/pull/613) +- :white_check_mark: `getReturnTypeHintToken()` utility method: align returned `$stackPtr` with native PHPCS behaviour by returning the last token of the type declaration. [#575](https://github.com/PHPCompatibility/PHPCompatibility/pull/575) +- :white_check_mark: PHPCS cross-version compatibility: sync `getMethodParameters()` method with improved upstream version. [#643](https://github.com/PHPCompatibility/PHPCompatibility/pull/643) +- :pencil2: The `MbstringReplaceEModifier`, `PregReplaceEModifier` and the `PregReplaceEModifier` sniffs now `extend` the new `AbstractFunctionCallParameterSniff` class. This should yield more accurate results when checking whether one of the target PHP functions was called. [#636](https://github.com/PHPCompatibility/PHPCompatibility/pull/636) +- :pencil2: `DeprecatedNewReference` sniff: minor change to the error text and code - was `Forbidden`, now `Removed` -. Custom rulesets which explicitly excluded this error code will need to be updated. [#594](https://github.com/PHPCompatibility/PHPCompatibility/pull/594) +- :pencil2: `NewScalarTypeDeclarations` sniff: minor change to the error message text.[#644](https://github.com/PHPCompatibility/PHPCompatibility/pull/644) +- :umbrella: The unit test framework now allows for sniffs in categories other than `PHP`. [#634](https://github.com/PHPCompatibility/PHPCompatibility/pull/634) +- :umbrella: Boyscouting: fixed up some (non-relevant) parse errors in a unit test case file. [#576](https://github.com/PHPCompatibility/PHPCompatibility/pull/576) +- :green_heart: Travis: build tests are now also being run against the lowest supported PHPCS 3.x version. Previously only the highest supported PHPCS 3.x version was tested against. [#633](https://github.com/PHPCompatibility/PHPCompatibility/pull/633) +- :books: Readme: Improved Composer install instructions. [#690](https://github.com/PHPCompatibility/PHPCompatibility/pull/690) +- :books: Minor documentation fixes. [#672](https://github.com/PHPCompatibility/PHPCompatibility/pull/672) +- :wrench: Minor performance optimizations and code simplifications. [#592](https://github.com/PHPCompatibility/PHPCompatibility/pull/592), [#630](https://github.com/PHPCompatibility/PHPCompatibility/pull/630), [#671](https://github.com/PHPCompatibility/PHPCompatibility/pull/671) +- :wrench: Composer: Various improvements, including improved information about the suggested packages, suggesting `roave/security-advisories`, allowing for PHPUnit 7.x. [#604](https://github.com/PHPCompatibility/PHPCompatibility/pull/604/files), [#616](https://github.com/PHPCompatibility/PHPCompatibility/pull/616), [#622](https://github.com/PHPCompatibility/PHPCompatibility/pull/622), [#646](https://github.com/PHPCompatibility/PHPCompatibility/pull/646) +- :wrench: Various Travis build script improvements, including tweaks for faster build time, validation of the `composer.json` file, validation of the framework specific rulesets. [#570](https://github.com/PHPCompatibility/PHPCompatibility/pull/570), [#571](https://github.com/PHPCompatibility/PHPCompatibility/pull/571), [#579](https://github.com/PHPCompatibility/PHPCompatibility/pull/579), [#621](https://github.com/PHPCompatibility/PHPCompatibility/pull/621), [#631](https://github.com/PHPCompatibility/PHPCompatibility/pull/631) +- :wrench: Build/PHPCS: made some more CS conventions explicit and start using PHPCS 3.x options for the PHPCompatibility native ruleset. [#586](https://github.com/PHPCompatibility/PHPCompatibility/pull/586), [#667](https://github.com/PHPCompatibility/PHPCompatibility/pull/667), [#673](https://github.com/PHPCompatibility/PHPCompatibility/pull/673) +- :wrench: Some code style clean up and start using the new inline PHPCS 3.2+ annotations where applicable. [#586](https://github.com/PHPCompatibility/PHPCompatibility/pull/586), [#591](https://github.com/PHPCompatibility/PHPCompatibility/pull/591), [#620](https://github.com/PHPCompatibility/PHPCompatibility/pull/620), [#673](https://github.com/PHPCompatibility/PHPCompatibility/pull/673) + +### Removed +- :no_entry_sign: PHPCompatibility no longer explicitly supports PHP_CodeSniffer 2.2.0. [#687](https://github.com/PHPCompatibility/PHPCompatibility/pull/687), [#690](https://github.com/PHPCompatibility/PHPCompatibility/pull/690) +- :no_entry_sign: The PHPCompatibility ruleset no longer includes the PHPCS native `Generic.NamingConventions.CamelCapsFunctionName`. Double underscore prefixed function names are now being reported on by a new dedicated sniff. [#581](https://github.com/PHPCompatibility/PHPCompatibility/pull/581) +- :no_entry_sign: PHPCompatibility no longer explicitly supports HHVM and builds are no longer tested against HHVM. + For now, running PHPCompatibility on HHVM to test PHP code may still work for a little while, but HHVM has announced they are [dropping PHP support](https://hhvm.com/blog/2017/09/18/the-future-of-hhvm.html). [#623](https://github.com/PHPCompatibility/PHPCompatibility/pull/623). Fixes [#603](https://github.com/PHPCompatibility/PHPCompatibility/issues/603). +- :books: Readme: badges from services which are no longer supported or inaccurate. [#609](https://github.com/PHPCompatibility/PHPCompatibility/pull/609), [#628](https://github.com/PHPCompatibility/PHPCompatibility/pull/628) + +### Fixed +- :bug: Previously, the PHPCS native `Generic.NamingConventions.CamelCapsFunctionName` sniff was included in PHPCompatibility. Some error codes of this sniff were excluded, as well as some error messages changed (via the ruleset). + If/when PHPCompatibility would be used in combination with a code style-type ruleset, this could inadvertently lead to underreporting of issues which the CS-type ruleset intends to have reported - i.e. the error codes excluded by PHPCompatibility -. This has now been fixed. [#581](https://github.com/PHPCompatibility/PHPCompatibility/pull/581) +- :bug: The `ForbiddenNegativeBitshift` sniff would incorrectly throw an error when a bitshift was based on a calculation which included a negative number, but would not necessarily result in a negative number. [#614](https://github.com/PHPCompatibility/PHPCompatibility/pull/614). Fixes [#294](https://github.com/PHPCompatibility/PHPCompatibility/issues/294), [#466](https://github.com/PHPCompatibility/PHPCompatibility/issues/466). +- :bug: The `NewClosure` sniff would report the same issue twice when the issue was encountered in a nested closure. [#669](https://github.com/PHPCompatibility/PHPCompatibility/pull/669) +- :bug: The `NewKeywords` sniff would underreport on non-lowercase keywords. [#627](https://github.com/PHPCompatibility/PHPCompatibility/pull/627) +- :bug: The `NewKeywords` sniff would incorrectly report on the use of class constants and class properties using the same name as a keyword. [#627](https://github.com/PHPCompatibility/PHPCompatibility/pull/627) +- :bug: The `NewNullableTypes` sniff would potentially underreport when comments where interspersed in the (return) type declarations. [#577](https://github.com/PHPCompatibility/PHPCompatibility/pull/577) +- :bug: The `Sniff::getFunctionCallParameters()` utility method would in rare cases return incorrect results when it encountered a closure as a parameter. [#682](https://github.com/PHPCompatibility/PHPCompatibility/pull/682) +- :bug: The `Sniff::getReturnTypeHintToken()` utility method would not always return a `$stackPtr`. [#645](https://github.com/PHPCompatibility/PHPCompatibility/pull/645) +- :bug: Minor miscellanous other bugfixes. [#670](https://github.com/PHPCompatibility/PHPCompatibility/pull/670) +- :umbrella: `PHPCompatibility\Tests\BaseClass\MethodTestFrame::getTargetToken()` could potentially not find the correct token to run a test against. [#588](https://github.com/PHPCompatibility/PHPCompatibility/pull/588) + +### Credits +Thanks go out to [Michael Babker] and [Juliette Reinders Folmer] for their contributions to this version. :clap: + + +## [8.1.0] - 2017-12-27 + +See all related issues and PRs in the [8.1.0 milestone]. + +### Added +- :star2: New `NewConstants` and `RemovedConstants` sniffs to detect usage of new/removed PHP constants for all PHP versions from PHP 5 up. [#526](https://github.com/PHPCompatibility/PHPCompatibility/pull/525), [#551](https://github.com/PHPCompatibility/PHPCompatibility/pull/551), [#566](https://github.com/PHPCompatibility/PHPCompatibility/pull/566). Fixes [#263](https://github.com/PHPCompatibility/PHPCompatibility/issues/263). +- :star2: New `MagicAutoloadDeprecation` sniff to detect deprecated `__autoload()` functions as deprecated in PHP 7.2. [#540](https://github.com/PHPCompatibility/PHPCompatibility/pull/540) +- :star2: New `OptionalRequiredFunctionParameter` sniff to check for missing function call parameters which were required and only became optional in a later PHP version. [#524](https://github.com/PHPCompatibility/PHPCompatibility/pull/524) +- :star2: New `DynamicAccessToStatic` sniff to detect dynamic access to static methods and properties, as well as class constants, prior to PHP 5.3. [#535](https://github.com/PHPCompatibility/PHPCompatibility/pull/535). Fixes [#534](https://github.com/PHPCompatibility/PHPCompatibility/issues/534). +- :star: `DeprecatedFunctions` sniff: recognize yet more PHP 7.2 deprecated functions. [#561](https://github.com/PHPCompatibility/PHPCompatibility/pull/561), [#566](https://github.com/PHPCompatibility/PHPCompatibility/pull/566) +- :star: `DeprecatedIniDirectives` sniff: recognize the last of the PHP 7.2 deprecated ini directives. [#566](https://github.com/PHPCompatibility/PHPCompatibility/pull/566), [#567](https://github.com/PHPCompatibility/PHPCompatibility/pull/567) +- :star: `NewFunctions` : detection of all new PHP 7.2 functions added. [#522](https://github.com/PHPCompatibility/PHPCompatibility/pull/522), [#545](https://github.com/PHPCompatibility/PHPCompatibility/pull/545), [#551](https://github.com/PHPCompatibility/PHPCompatibility/pull/551), [#565](https://github.com/PHPCompatibility/PHPCompatibility/pull/565) +- :star: `RemovedExtensions` : report on usage of the `mcrypt` extension which has been removed in PHP 7.2. [#566](https://github.com/PHPCompatibility/PHPCompatibility/pull/566) +- :star: `RemovedGlobalVariables` : detection of the use of `$php_errormsg` with `track_errors` which has been deprecated in PHP 7.2. [#528](https://github.com/PHPCompatibility/PHPCompatibility/pull/528) +- :books: Documentation : added reporting usage instructions. [#533](https://github.com/PHPCompatibility/PHPCompatibility/pull/533), [#552](https://github.com/PHPCompatibility/PHPCompatibility/pull/552) + +### Changed +- :pushpin: `NewClosures` : downgraded "$this found in closure outside class" to warning. [#536](https://github.com/PHPCompatibility/PHPCompatibility/pull/535). Fixes [#527](https://github.com/PHPCompatibility/PHPCompatibility/issues/527). +- :pushpin: `ForbiddenGlobalVariableVariable` : the sniff will now throw an error for each variable in a `global` statement which is no longer supported and show the variable found to make it easier to fix this. Previously only one error would be thrown per `global` statement. [#564](https://github.com/PHPCompatibility/PHPCompatibility/pull/564) +- :pushpin: `ForbiddenGlobalVariableVariable` : the sniff will now throw `warning`s for non-bare variables used in a `global` statement as those are discouraged since PHP 7.0. [#564](https://github.com/PHPCompatibility/PHPCompatibility/pull/564) +- :rewind: `NewLanguageConstructs` : updated the version number for `T_COALESCE_EQUAL`. [#523](https://github.com/PHPCompatibility/PHPCompatibility/pull/523) +- :pencil2: `Sniff::getTestVersion()` : simplified regex logic. [#520](https://github.com/PHPCompatibility/PHPCompatibility/pull/520) +- :green_heart: Travis : build tests are now being run against PHP 7.2 as well. [#511](https://github.com/PHPCompatibility/PHPCompatibility/pull/511) +- :wrench: Improved check for superfluous whitespaces in files. [#542](https://github.com/PHPCompatibility/PHPCompatibility/pull/542) +- :wrench: Build/PHPCS : stabilized the exclude patterns. [#529](https://github.com/PHPCompatibility/PHPCompatibility/pull/529) +- :wrench: Build/PHPCS : added array indentation check. [#538](https://github.com/PHPCompatibility/PHPCompatibility/pull/538) +- :white_check_mark: PHPCS cross-version compatibility : sync `FindExtendedClassname()` method with upstream. [#507](https://github.com/PHPCompatibility/PHPCompatibility/pull/507) +- :wrench: The minimum version for the recommended `DealerDirect/phpcodesniffer-composer-installer` Composer plugin has been upped to `0.4.3`. [#548](https://github.com/PHPCompatibility/PHPCompatibility/pull/548) + +### Fixed +- :bug: `ForbiddenCallTimePassByReference` : a false positive was being thrown when a global constant was followed by a _bitwise and_. [#562](https://github.com/PHPCompatibility/PHPCompatibility/pull/562). Fixes [#39](https://github.com/PHPCompatibility/PHPCompatibility/issues/39). +- :bug: `ForbiddenGlobalVariableVariable` : the sniff was overzealous and would also report on `global` in combination with variable variables which are still supported. [#564](https://github.com/PHPCompatibility/PHPCompatibility/pull/564). Fixes [#537](https://github.com/PHPCompatibility/PHPCompatibility/issues/537). +- :bug: `ForbiddenGlobalVariableVariable` : variables interspersed with whitespace and/or comments were not being reported. [#564](https://github.com/PHPCompatibility/PHPCompatibility/pull/564) +- :rewind: `ForbiddenNamesAsInvokedFunctions` : improved recognition of function invocations using forbidden words and prevent warnings for keywords which are no longer forbidden as method names in PHP 7.0+. [#516](https://github.com/PHPCompatibility/PHPCompatibility/pull/516). Fixes [#515](https://github.com/PHPCompatibility/PHPCompatibility/issues/515) +- :bug: `VariableVariables` : variables interspersed with whitespace and/or comments were not being reported. [#563](https://github.com/PHPCompatibility/PHPCompatibility/pull/563) +- :umbrella: Fixed some unintentional syntax errors in test files. [#539](https://github.com/PHPCompatibility/PHPCompatibility/pull/539) +- :umbrella: Tests : fixed case numbering error. [#525](https://github.com/PHPCompatibility/PHPCompatibility/pull/525) +- :books: Tests : added missing test skip explanation. [#521](https://github.com/PHPCompatibility/PHPCompatibility/pull/521) +- :wrench: Fixed PHPCS whitespaces. [#543](https://github.com/PHPCompatibility/PHPCompatibility/pull/543) +- :wrench: Fixed code test coverage verification. [#550](https://github.com/PHPCompatibility/PHPCompatibility/pull/550). Fixes [#549](https://github.com/PHPCompatibility/PHPCompatibility/issues/549). + +### Credits +Thanks go out to [Juliette Reinders Folmer] and [Jonathan Van Belle] for their contributions to this version. :clap: + + +## [8.0.1] - 2017-08-07 + +See all related issues and PRs in the [8.0.1 milestone]. + +### Added +- :star2: New `DeprecatedTypeCasts` sniff to detect deprecated and removed type casts, such as the `(unset)` type cast as deprecated in PHP 7.2. [#498](https://github.com/PHPCompatibility/PHPCompatibility/pull/498) +- :star2: New `NewTypeCasts` sniff to detect type casts not present in older PHP versions such as the `(binary)` type cast as added in PHP 5.2.1. [#497](https://github.com/PHPCompatibility/PHPCompatibility/pull/497) +- :star: `NewGroupUseDeclaration`: Detection of PHP 7.2 trailing comma's in group use statements. [#504](https://github.com/PHPCompatibility/PHPCompatibility/pull/504) +- :star: `DeprecatedFunctions` sniff: recognize some more PHP 7.2 deprecated functions. [#501](https://github.com/PHPCompatibility/PHPCompatibility/pull/501) +- :star: `DeprecatedIniDirectives` sniff: recognize more PHP 7.2 deprecated ini directives. [#500](https://github.com/PHPCompatibility/PHPCompatibility/pull/500) +- :star: `ForbiddenNames` sniff: recognize `object` as a forbidden keyword since PHP 7.2. [#499](https://github.com/PHPCompatibility/PHPCompatibility/pull/499) +- :star: `NewReturnTypeDeclarations` sniff: recognize generic `parent`, PHP 7.1 `iterable` and PHP 7.2 `object` return type declarations. [#505](https://github.com/PHPCompatibility/PHPCompatibility/pull/505), [#499](https://github.com/PHPCompatibility/PHPCompatibility/pull/499) +- :star: `NewScalarTypeDeclarations` sniff: recognize PHP 7.2 `object` type declarion. [#499](https://github.com/PHPCompatibility/PHPCompatibility/pull/499) + +### Changed +- :pencil2: Improved clarity of the deprecated functions alternative in the error message. [#502](https://github.com/PHPCompatibility/PHPCompatibility/pull/502) + +### Fixed +- :fire_engine: Temporary hotfix for installed_paths (pending [upstream fix](https://github.com/squizlabs/PHP_CodeSniffer/issues/1591).) [#503](https://github.com/PHPCompatibility/PHPCompatibility/pull/503) + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + + +## [8.0.0] - 2017-08-03 + +**IMPORTANT**: This release contains a **breaking change**. Please read the below information carefully before upgrading! + +The directory layout of the PHPCompatibility standard has been changed for improved compatibility with Composer. +This means that the PHPCompatibility standard no longer extends from the root directory of the repository, but now lives in its own subdirectory `/PHPCompatibility`. + +This release also bring compatibility with PHPCS 3.x to the PHPCompatibility standard. + +There are two things you will need to be aware of: +* The path to the PHPCompatibility standard has changed. +* If you intend to upgrade to PHPCS 3.x, the path to the `phpcs` script has changed (upstream change). + +Please follow the below upgrade instructions carefully. This should be a one-time only action. + +### Upgrade instructions + +### Before upgrading + +If you had previously made accommodations for the old directory layout, you should remove any such _"hacks"_ (meant in the kindest of ways) now. + +By this we mean: symlinks for the PHPCompatibility install to the `PHP_CodeSniffer/CodeSniffer/Standards` directory, scripts to move the sniffs files to the PHPCS directory, scripts which made symlinks etc. + +So, please remove those first. + +> **Side-note**: +> +> If you had previously forked this repository to solve this issue, please consider reverting your fork to the official version or removing it all together. + +### Upgrading: re-registering PHPCompatibility with PHP CodeSniffer + +External PHP CodeSniffer standards need to be registered with PHP CodeSniffer. You have probably done this the first time you used PHPCompatibility or have a script or Composer plugin in place to do this for you. + +As the directory layout of PHPCompatibility has changed, the path previously registered with PHP CodeSniffer will no longer work and running `phpcs -i` will **_not_** list PHPCompatibility as one of the registered standards. + +#### Using a Composer plugin + +If you use Composer, we recommend you use a Composer plugin to sort this out. In previous install instructions we recommended the SimplyAdmin plugin for this. This plugin has since been abandoned. We now recommend the DealerDirect plugin. +```bash +composer remove --dev simplyadmire/composer-plugins +composer require --dev dealerdirect/phpcodesniffer-composer-installer:^0.4.3 +composer install +composer update phpcompatibility/php-compatibility squizlabs/php_codesniffer +vendor/bin/phpcs -i +``` +If all went well, you should now see PHPCompatibility listed again in the list of installed standards. + +#### Manually re-registering PHPCompatibility + +1. First run `phpcs --config-show` to check which path(s) are currently registered with PHP CodeSniffer for external standards. +2. Check in the below table what the new path for PHPCompatibility will be - the path should point to the root directory of your PHPCompatibility install (not to the sub-directory of the same name): + + Install type | Old path | New path + ------------ | -------- | --------- + Composer | `vendor/wimg` | `vendor/phpcompatibility/php-compatibility` + Unzipped release to arbitrary directory | `path/to/dir/abovePHPCompatibility` | `path/to/dir/abovePHPCompatibility/PHPCompatibility` + Git checkout | `path/to/dir/abovePHPCompatibility` | `path/to/dir/abovePHPCompatibility/PHPCompatibility` + PEAR | If the old install instruction has been followed, not registered. | `path/to/PHPCompatibility` + + > **Side-note**: + > + > If you used the old install instructions for a PEAR install, i.e. checking out the latest release to the `PHP/CodeSniffer/Standards/PHPCompatibility` directory, and you intend to upgrade to PHP CodeSniffer 3.x, it is recommended you move the PHPCompatibility folder out of the PEAR directory now, as the layout of the PHPCS directory has changed with PHPCS 3.x and you may otherwise lose your PHPCompatibility install when you upgrade PHP CodeSniffer via PEAR. + +3. There are two ways in which you can register the new `installed_paths` value with PHP CodeSniffer. Choose your preferred method: + * Run `phpcs --config-set installed_paths ...` and include all previously installed paths including the _adjusted_ path for the PHPCompatibility standard. + + For example, if the previous value of `installed_paths` was + + `/path/to/MyStandard,/path/to/dir/abovePHPCompatibility` + + you should now set it using + + `phpcs --config-set installed_paths /path/to/MyStandard,/path/to/PHPCompatibility` + + * If you use a custom ruleset in combination with PHPCS 2.6.0 or higher, you can pass the value to PHPCS from your custom ruleset: + ```xml + <config name="installed_paths" value="vendor/phpcompatibility/php-compatibility" /> + ``` +4. Run `phpcs -i` to verify that the PHPCompatibility standard is now listed again in the list of installed standards. + + +### Upgrading to PHPCS 3.x + +The path to the `phpcs` script has changed in PHPCS 3.x which will impact how you call PHPCS. + +Version | PHPCS 2.x | PHPCS 3.x +------- | --------- | --------- +Generic `phpcs` Command | `path/to/PHP_CodeSniffer/scripts/phpcs ....` | `path/to/PHP_CodeSniffer/bin/phpcs ....` +Composer command | `vendor/bin/phpcs ...` | `vendor/bin/phpcs ...` + +So, for Composer users, nothing changes. For everyone else, you may want to add the `path/to/PHP_CodeSniffer/bin/phpcs` path to your PATH environment variable or adjust any scripts - like build scripts - which call PHPCS. + + +### Upgrading a Travis build script + +If you run PHPCompatibility against your code as part of your Travis build: +* If you use Composer to install PHP CodeSniffer and PHPCompatibility on the travis image and you've made the above mentioned changes, your build should pass again. +* If you use `git clone` to install PHP CodeSniffer and PHPCompatibility on the travis image, your build will fail until you make the following changes: + 1. Check which branch of PHPCS is being checked out. If you previously fixed this to a pre-PHPCS 3.x branch or tag, you can now change this (back) to `master` or a PHPCS 3 tag. + 2. Check to which path PHPCompatibility is being cloned and adjust the path if necessary. + 3. Adjust the `phpcs --config-set installed_paths` command as described above to point to the root of the cloned PHPCompatibility repo. + 4. If you switched to using PHPCS 3.x, adjust the call to PHPCS. + + + +### Changelog for version 8.0.0 + +See all related issues and PRs in the [8.0.0 milestone]. + +### Added +- :two_hearts: Support for PHP CodeSniffer 3.x. [#482](https://github.com/PHPCompatibility/PHPCompatibility/pull/482), [#481](https://github.com/PHPCompatibility/PHPCompatibility/pull/481), [#480](https://github.com/PHPCompatibility/PHPCompatibility/pull/480), [#488](https://github.com/PHPCompatibility/PHPCompatibility/pull/488), [#489](https://github.com/PHPCompatibility/PHPCompatibility/pull/489), [#495](https://github.com/PHPCompatibility/PHPCompatibility/pull/495) + +### Changed +- :gift: As of this version PHPCompatibility will use semantic versioning. +- :fire: The directory structure of the repository has changed for better compatibility with installation via Composer. [#446](https://github.com/PHPCompatibility/PHPCompatibility/pull/446). Fixes [#102](https://github.com/PHPCompatibility/PHPCompatibility/issues/102), [#107](https://github.com/PHPCompatibility/PHPCompatibility/issues/107) +- :pencil2: The custom `functionWhitelist` property for the `PHPCompatibility.PHP.RemovedExtensions` sniff is now only supported in combination with PHP CodeSniffer 2.6.0 or higher (due to an upstream bug which was fixed in PHPCS 2.6.0). [#482](https://github.com/PHPCompatibility/PHPCompatibility/pull/482) +- :wrench: Improved the information provided to Composer from the `composer.json` file. [#446](https://github.com/PHPCompatibility/PHPCompatibility/pull/446), [#482](https://github.com/PHPCompatibility/PHPCompatibility/pull/482), [#486](https://github.com/PHPCompatibility/PHPCompatibility/pull/486) +- :wrench: Release archives will no longer contain the unit tests and other typical development files. You can still get these by using Composer with `--prefer-source` or by checking out a git clone of the repository. [#494](https://github.com/PHPCompatibility/PHPCompatibility/pull/494) +- :wrench: A variety of minor improvements to the build process. [#485](https://github.com/PHPCompatibility/PHPCompatibility/pull/485), [#486](https://github.com/PHPCompatibility/PHPCompatibility/pull/486), [#487](https://github.com/PHPCompatibility/PHPCompatibility/pull/487) +- :wrench: Some files for use by contributors have been renamed to use `.dist` extensions or moved for easier access. [#478](https://github.com/PHPCompatibility/PHPCompatibility/pull/478), [#479](https://github.com/PHPCompatibility/PHPCompatibility/pull/479), [#483](https://github.com/PHPCompatibility/PHPCompatibility/pull/483), [#493](https://github.com/PHPCompatibility/PHPCompatibility/pull/493) +- :books: The installation instructions in the Readme. [#496](https://github.com/PHPCompatibility/PHPCompatibility/pull/496) +- :books: The unit test instructions in the Contributing file. [#496](https://github.com/PHPCompatibility/PHPCompatibility/pull/496) +- :books: Improved the example code in the Readme. [#490](https://github.com/PHPCompatibility/PHPCompatibility/pull/490) + +### Removed +- :no_entry_sign: Support for PHP 5.1 and 5.2. + + The sniffs can now only be run on PHP 5.3 or higher in combination with PHPCS 1.5.6 or 2.x and on PHP 5.4 or higher in combination with PHPCS 3.x. [#484](https://github.com/PHPCompatibility/PHPCompatibility/pull/484), [#482](https://github.com/PHPCompatibility/PHPCompatibility/pull/482) + +### Credits +Thanks go out to [Gary Jones] and [Juliette Reinders Folmer] for their contributions to this version. :clap: + + +## [7.1.5] - 2017-07-17 + +See all related issues and PRs in the [7.1.5 milestone]. + +### Added +- :star: The `NewKeywords` sniff will now also sniff for `yield from` which was introduced in PHP 7.0. [#477](https://github.com/PHPCompatibility/PHPCompatibility/pull/477). Fixes [#476](https://github.com/PHPCompatibility/PHPCompatibility/issues/476) +- :books: The LGPL-3.0 license. [#447](https://github.com/PHPCompatibility/PHPCompatibility/pull/447) + +### Changed +- :rewind: The `NewExecutionDirectives` sniff will now also report on execution directives when used in combination with PHPCS 2.0.0-2.3.3. [#451](https://github.com/PHPCompatibility/PHPCompatibility/pull/451) +- :rewind: The `getMethodParameters()` utility method will no longer break when used with PHPCS 1.5.x < 1.5.6. This affected a number of sniffs. [#452](https://github.com/PHPCompatibility/PHPCompatibility/pull/452) +- :rewind: The `inUseScope()` utility method will no longer break when used with PHPCS 2.0.0 - 2.2.0. This affected a number of sniffs. [#454](https://github.com/PHPCompatibility/PHPCompatibility/pull/454) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#443](https://github.com/PHPCompatibility/PHPCompatibility/pull/443), [#474](https://github.com/PHPCompatibility/PHPCompatibility/pull/474) +- :pencil2: Renamed a test file for consistency. [#453](https://github.com/PHPCompatibility/PHPCompatibility/pull/453) +- :wrench: Code style clean up. [#429](https://github.com/PHPCompatibility/PHPCompatibility/pull/429) +- :wrench: Prevent Composer installing PHPCS 3.x. **_PHPCS 3.x is not (yet) supported by the PHPCompatibility standard, but will be in the near future._** [#444](https://github.com/PHPCompatibility/PHPCompatibility/pull/444) +- :green_heart: The code base will now be checked for consistent code style during build testing. [#429](https://github.com/PHPCompatibility/PHPCompatibility/pull/429) +- :green_heart: The sniffs are now also tested against HHVM for consistent results. _Note: the sniffs do not contain any HHVM specific checks nor is there any intention to add them at this time._ [#450](https://github.com/PHPCompatibility/PHPCompatibility/pull/450) +- :books: Made it explicit that - at this moment - PHPCS 3.x is not (yet) supported. [#444](https://github.com/PHPCompatibility/PHPCompatibility/pull/444) +- :books: Minor improvements to the Readme. [#448](https://github.com/PHPCompatibility/PHPCompatibility/pull/448), [#449](https://github.com/PHPCompatibility/PHPCompatibility/pull/449), [#468](https://github.com/PHPCompatibility/PHPCompatibility/pull/468) +- :books: Minor improvements to the Contributing guidelines. [#467](https://github.com/PHPCompatibility/PHPCompatibility/pull/467) + +### Removed +- :no_entry_sign: The `DefaultTimeZoneRequired` sniff. This sniff was checking server settings rather than code. [#458](https://github.com/PHPCompatibility/PHPCompatibility/pull/458). Fixes [#457](https://github.com/PHPCompatibility/PHPCompatibility/issues/457) +- :no_entry_sign: The `NewMagicClassConstant` sniff as introduced in v 7.1.4 contained two additional checks for not strictly compatibility related issues. One of these was plainly wrong, the other opinionated. Both have been removed. [#442](https://github.com/PHPCompatibility/PHPCompatibility/pull/442). Fixes [#436](https://github.com/PHPCompatibility/PHPCompatibility/issues/436) + +### Fixed +- :bug: `NewClass` sniff: was reporting an incorrect introduction version number for a few of the Exception classes. [#441](https://github.com/PHPCompatibility/PHPCompatibility/pull/441). Fixes [#440](https://github.com/PHPCompatibility/PHPCompatibility/issues/440). +- :bug: `ForbiddenBreakContinueVariableArguments` sniff: was incorrectly reporting an error if the `break` or `continue` was followed by a PHP closing tag (breaking out of PHP). [#462](https://github.com/PHPCompatibility/PHPCompatibility/pull/462). Fixes [#460](https://github.com/PHPCompatibility/PHPCompatibility/issues/460) +- :bug: `ForbiddenGlobalVariableVariable` sniff: was incorrectly reporting an error if the `global` statement was followed by a PHP closing tag (breaking out of PHP). [#463](https://github.com/PHPCompatibility/PHPCompatibility/pull/463). +- :bug: `DeprecatedFunctions` sniff: was reporting false positives for classes using the same name as a deprecated function. [#465](https://github.com/PHPCompatibility/PHPCompatibility/pull/465). Fixes [#464](https://github.com/PHPCompatibility/PHPCompatibility/issues/464) + +### Credits +Thanks go out to [Juliette Reinders Folmer] and [Mark Clements] for their contributions to this version. :clap: + + +## [7.1.4] - 2017-05-06 + +See all related issues and PRs in the [7.1.4 milestone]. + +### Added +- :star2: New `CaseSensitiveKeywords` sniff to detect use of non-lowercase `self`, `static` and `parent` keywords which could cause compatibility issues pre-PHP 5.5. [#382](https://github.com/PHPCompatibility/PHPCompatibility/pull/382) +- :star2: New `ConstantArraysUsingConst` sniff to detect constants defined using the `const` keyword being assigned an array value which was not supported prior to PHP 5.6. [#397](https://github.com/PHPCompatibility/PHPCompatibility/pull/397) +- :star2: New `ForbiddenClosureUseVariableNames` sniff to detect PHP 7.1 forbidden variable names in closure use statements. [#386](https://github.com/PHPCompatibility/PHPCompatibility/pull/386). Fixes [#374](https://github.com/PHPCompatibility/PHPCompatibility/issues/374) +- :star2: New `NewArrayStringDereferencing` sniff to detect array and string literal dereferencing as introduced in PHP 5.5. [#388](https://github.com/PHPCompatibility/PHPCompatibility/pull/388) +- :star2: New `NewHeredocInitialize` sniff to detect initialization of static variables and class properties/constants using the heredoc syntax which is supported since PHP 5.3. [#391](https://github.com/PHPCompatibility/PHPCompatibility/pull/391). Fixes [#51](https://github.com/PHPCompatibility/PHPCompatibility/issues/51) +- :star2: New `NewMagicClassConstant` sniff to detect use of the magic `::class` constant as introduced in PHP 5.5. [#403](https://github.com/PHPCompatibility/PHPCompatibility/pull/403). Fixes [#364](https://github.com/PHPCompatibility/PHPCompatibility/issues/364). +- :star2: New `NewUseConstFunction` sniff to detect use statements importing constants and functions as introduced in PHP 5.6. [#401](https://github.com/PHPCompatibility/PHPCompatibility/pull/401) +- :star: `DeprecatedFunctions` sniff: recognize PHP 7.2 deprecated GD functions. [#392](https://github.com/PHPCompatibility/PHPCompatibility/pull/392) +- :star: `DeprecatedIniDirectives` sniff: recognize PHP 7.2 deprecated `mbstring.func_overload` directive. [#377](https://github.com/PHPCompatibility/PHPCompatibility/pull/377) +- :star: `NewClasses` sniff: check for the PHP 5.1 `libXMLError` class. [#412](https://github.com/PHPCompatibility/PHPCompatibility/pull/412) +- :star: `NewClasses` sniff: recognize all native PHP Exception classes. [#418](https://github.com/PHPCompatibility/PHPCompatibility/pull/418) +- :star: `NewClosure` sniff: check for closures being declared as static and closures using `$this`. Both of which was not supported pre-PHP 5.4. [#389](https://github.com/PHPCompatibility/PHPCompatibility/pull/389). Fixes [#24](https://github.com/PHPCompatibility/PHPCompatibility/issues/24). +- :star: `NewFunctionParameters` sniff: recognize new `exclude_disabled` parameter for the `get_defined_functions()` function as introduced in PHP 7.0.15. [#375](https://github.com/PHPCompatibility/PHPCompatibility/pull/375) +- :star: `NewFunctions` sniff: recognize new PHP 7.2 socket related functions. [#376](https://github.com/PHPCompatibility/PHPCompatibility/pull/376) +- :star: `NewInterfaces` sniff: check for some more PHP native interfaces. [#411](https://github.com/PHPCompatibility/PHPCompatibility/pull/411) +- :star: New `isClassProperty()`, `isClassConstant()` and `validDirectScope()` utility methods to the `PHPCompatibility_Sniff` class. [#393](https://github.com/PHPCompatibility/PHPCompatibility/pull/393), [#391](https://github.com/PHPCompatibility/PHPCompatibility/pull/391). +- :star: New `getTypeHintsFromFunctionDeclaration()` utility method to the `PHPCompatibility_Sniff` class. [#414](https://github.com/PHPCompatibility/PHPCompatibility/pull/414). +- :umbrella: Unit tests against false positives for the `NewMagicMethods` sniff. [#381](https://github.com/PHPCompatibility/PHPCompatibility/pull/381) +- :umbrella: More unit tests for the `getTestVersion()` utility method. [#405](https://github.com/PHPCompatibility/PHPCompatibility/pull/405), [#430](https://github.com/PHPCompatibility/PHPCompatibility/pull/430) +- :green_heart: The XML of the ruleset will now be validated and checked for consistent code style during the build testing by Travis. [#433](https://github.com/PHPCompatibility/PHPCompatibility/pull/433) +- :books: Readme: information about setting `installed_paths` via a custom ruleset. [#407](https://github.com/PHPCompatibility/PHPCompatibility/pull/407) +- :books: `Changelog.md` file containing a record of notable changes since the first tagged release. [#421](https://github.com/PHPCompatibility/PHPCompatibility/pull/421) + +### Changed +- :pushpin: The `ForbiddenNamesAsDeclared` sniff will now emit `warning`s for soft reserved keywords. [#406](https://github.com/PHPCompatibility/PHPCompatibility/pull/406), [#370](https://github.com/PHPCompatibility/PHPCompatibility/pull/370). +- :pushpin: The `ForbiddenNames` sniff will now allow for the more liberal rules for usage of reserved keywords as of PHP 7.0. [#417](https://github.com/PHPCompatibility/PHPCompatibility/pull/417) +- :pushpin: The `InternalInterfaces`, `NewClasses`, `NewConstVisibility`, `NewInterfaces`, `NewMagicMethods`, `NonStaticMagicMethods` and `RemovedGlobalVariables` sniffs will now also sniff for and correctly report violations in combination with anonymous classes. [#378](https://github.com/PHPCompatibility/PHPCompatibility/pull/378), [#383](https://github.com/PHPCompatibility/PHPCompatibility/pull/383), [#393](https://github.com/PHPCompatibility/PHPCompatibility/pull/393), [#394](https://github.com/PHPCompatibility/PHPCompatibility/pull/394), [#395](https://github.com/PHPCompatibility/PHPCompatibility/pull/395), [#396](https://github.com/PHPCompatibility/PHPCompatibility/pull/396). Fixes [#351](https://github.com/PHPCompatibility/PHPCompatibility/issues/351) and [#333](https://github.com/PHPCompatibility/PHPCompatibility/issues/333). +- :pushpin: The `NewClasses` and `NewInterfaces` sniffs will now also report on new classes/interfaces when used as type hints. [#414](https://github.com/PHPCompatibility/PHPCompatibility/pull/414), [#416](https://github.com/PHPCompatibility/PHPCompatibility/pull/416). Fixes [#352](https://github.com/PHPCompatibility/PHPCompatibility/issues/352) +- :pushpin: The `NewClasses` sniff will now also report on Exception classes when used in (multi-)`catch` statements. [#418](https://github.com/PHPCompatibility/PHPCompatibility/pull/418). Fixes [#373](https://github.com/PHPCompatibility/PHPCompatibility/issues/373). +- :pushpin: The `NewScalarTypeDeclarations` sniff will now report on new type hints even when the type hint is nullable. [#379](https://github.com/PHPCompatibility/PHPCompatibility/pull/379) +- :twisted_rightwards_arrows: The `NewNowdoc` sniff has been renamed to `NewNowdocQuotedHeredoc` and will now also check for double quoted heredoc identifiers as introduced in PHP 5.3. [#390](https://github.com/PHPCompatibility/PHPCompatibility/pull/390) +- :rewind: The `NewClasses` sniff will now also report anonymous classes which `extend` a new sniff when used in combination with PHPCS 2.4.0-2.8.0. [#432](https://github.com/PHPCompatibility/PHPCompatibility/pull/432). Fixes [#334](https://github.com/PHPCompatibility/PHPCompatibility/issues/334). +- :pencil2: `NewFunctionParameter` sniff: version number precision for two parameters. [#384](https://github.com/PHPCompatibility/PHPCompatibility/pull/384), [#428](https://github.com/PHPCompatibility/PHPCompatibility/pull/428) +- :umbrella: Skipping two unit tests for the `ForbiddenClosureUseVariable` sniff when run on PHPCS 2.5.1 as these cause an infinite loop due to an upstream bug. [#408](https://github.com/PHPCompatibility/PHPCompatibility/pull/408) +- :umbrella: Skipping unit tests involving `trait`s in combination with PHP < 5.4 and PHPCS < 2.4.0 as `trait`s are not recognized in those circumstances. [#431](https://github.com/PHPCompatibility/PHPCompatibility/pull/431) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#385](https://github.com/PHPCompatibility/PHPCompatibility/pull/385), [#387](https://github.com/PHPCompatibility/PHPCompatibility/pull/387), [#415](https://github.com/PHPCompatibility/PHPCompatibility/pull/415), [#423](https://github.com/PHPCompatibility/PHPCompatibility/pull/423), [#424](https://github.com/PHPCompatibility/PHPCompatibility/pull/424) +- :recycle: Minor simplification of the PHPUnit 6 compatibility layer and other test code. [#426](https://github.com/PHPCompatibility/PHPCompatibility/pull/426), [#425](https://github.com/PHPCompatibility/PHPCompatibility/pull/425) +- General housekeeping. [#398](https://github.com/PHPCompatibility/PHPCompatibility/pull/398), [#400](https://github.com/PHPCompatibility/PHPCompatibility/pull/400) +- :wrench: Minor tweaks to the Travis build script. [#409](https://github.com/PHPCompatibility/PHPCompatibility/pull/409) +- :green_heart: The sniffs are now also tested against PHP nightly for consistent results. [#380](https://github.com/PHPCompatibility/PHPCompatibility/pull/380) + +### Fixed +- :fire: Using unbounded ranges in `testVersion` resulted in unreported errors when used with sniffs using the `supportsBelow()` method. This affected the results of approximately half the sniffs. [#430](https://github.com/PHPCompatibility/PHPCompatibility/pull/430) +- :bug: The `ForbiddenNames` sniff would throw false positives for `use` statements with the `final` modifier in traits. [#402](https://github.com/PHPCompatibility/PHPCompatibility/pull/402). +- :bug: The `ForbiddenNames` sniff would fail to report on functions declared to return by reference using a reserved keyword as the function name. [#413](https://github.com/PHPCompatibility/PHPCompatibility/pull/413) +- :bug: The `ForbiddenNames` sniff would only examine the first part of a namespace and not report on reserved keywords used in subsequent parts of a nested namespace. [#419](https://github.com/PHPCompatibility/PHPCompatibility/pull/419) +- :bug: The `ForbiddenNames` sniff would not always correctly report on use statements importing constants or functions using reserved keywords. [#420](https://github.com/PHPCompatibility/PHPCompatibility/pull/420) +- :bug: The `NewKeywords` sniff would sometimes fail to report on the `const` keyword when used in a class, but not for a class constant. [#424](https://github.com/PHPCompatibility/PHPCompatibility/pull/424) +- :green_heart: PHPCS has released version 3.0 and updated the `master` branch to reflect this. This was causing the builds to fail. [#422](https://github.com/PHPCompatibility/PHPCompatibility/pull/422) + +### Credits +Thanks go out to [Juliette Reinders Folmer] and [Mark Clements] for their contributions to this version. :clap: + + +## [7.1.3] - 2017-04-02 + +See all related issues and PRs in the [7.1.3 milestone]. + +### Added +- :zap: The `testVersion` config parameter now allows for specifying unbounded ranges. + For example: specifying `-5.6` means: check for compatibility with all PHP versions up to and including PHP 5.6; + Specifying `7.0-` means: check for compatibility with all PHP versions from PHP 7.0 upwards. + For more information about setting the `testVersion`, see [Using the compatibility sniffs](https://github.com/PHPCompatibility/PHPCompatibility#using-the-compatibility-sniffs) in the readme. +- :umbrella: Unit test for multi-line short arrays for the `ShortArray` sniff. [#347](https://github.com/PHPCompatibility/PHPCompatibility/pull/347) +- :umbrella: Various additional unit tests against false positives. [#345](https://github.com/PHPCompatibility/PHPCompatibility/pull/345), [#369](https://github.com/PHPCompatibility/PHPCompatibility/pull/369) +- :umbrella: Unit tests for the `supportsBelow()`, `supportsAbove()` and `getTestVersion()` utility methods. [#363](https://github.com/PHPCompatibility/PHPCompatibility/pull/363) +- :books: Readme: information about installation of the standard using git check-out. [#349](https://github.com/PHPCompatibility/PHPCompatibility/pull/349) +- :books: `Contributing.md` file with information about reporting bugs, requesting features, making pull requests and running the unit tests. [#350](https://github.com/PHPCompatibility/PHPCompatibility/pull/350) + +### Changed +- :pushpin: The `ForbiddenFunctionParametersWithSameName`, `NewScalarTypeDeclarations`, `ParameterShadowSuperGlobals` sniff will now also sniff for and report violations in closures. [#331](https://github.com/PHPCompatibility/PHPCompatibility/pull/331) +- :twisted_rightwards_arrows: :rewind: The check for the PHP 5.3 `nowdoc` structure has been moved from the `NewKeywords` sniff to a new stand-alone `NewNowdoc` sniff which will now also recognize this structure when the sniffs are run on PHP 5.2. [#335](https://github.com/PHPCompatibility/PHPCompatibility/pull/335) +- :rewind: The `ForbiddenNames` sniff will now also correctly recognize reserved keywords used in a declared namespace when run on PHP 5.2. [#362](https://github.com/PHPCompatibility/PHPCompatibility/pull/362) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#360](https://github.com/PHPCompatibility/PHPCompatibility/pull/360) +- :recycle: The unit tests would previously run each test case file against all PHPCompatibility sniffs. Now, they will only be tested against the sniff which the test case file is intended to test. This allows for more test cases to be tested, more precise testing in combination with `testVersion` settings and makes the unit tests run ~6 x faster. + Relevant additional unit tests have been added and others adjusted. [#369](https://github.com/PHPCompatibility/PHPCompatibility/pull/369) +- :recycle: Refactoring/tidying up of some unit test code. [#343](https://github.com/PHPCompatibility/PHPCompatibility/pull/343), [#345](https://github.com/PHPCompatibility/PHPCompatibility/pull/345), [#356](https://github.com/PHPCompatibility/PHPCompatibility/pull/356), [#355](https://github.com/PHPCompatibility/PHPCompatibility/pull/355), [#359](https://github.com/PHPCompatibility/PHPCompatibility/pull/359) +- General housekeeping. [#346](https://github.com/PHPCompatibility/PHPCompatibility/pull/346) +- :books: Readme: Clarify minimum requirements and influence on the results. [#348](https://github.com/PHPCompatibility/PHPCompatibility/pull/348) + +### Removed +- :twisted_rightwards_arrows: Removed the `LongArrays` sniff. The checks it contained have been moved into the `RemovedGlobalVariables` sniff. Both sniffs essentially did the same thing, just for different PHP native superglobals. [#354](https://github.com/PHPCompatibility/PHPCompatibility/pull/354) + +### Fixed +- :bug: The `PregReplaceEModifier` sniff would throw a false positive if a quote character was used as the regex delimiter. [#357](https://github.com/PHPCompatibility/PHPCompatibility/pull/357) +- :bug: `RemovedGlobalVariables` sniff would report false positives for class properties shadowing the removed `$HTTP_RAW_POST_DATA` variables. [#354](https://github.com/PHPCompatibility/PHPCompatibility/pull/354). +- :bug: The `getFQClassNameFromNewToken()` utility function could go into an infinite loop causing PHP to run out of memory when examining unfinished code (examination during live coding). [#338](https://github.com/PHPCompatibility/PHPCompatibility/pull/338), [#342](https://github.com/PHPCompatibility/PHPCompatibility/pull/342) +- :bug: The `determineNamespace()` utility method would in certain cases not break out a loop. [#358](https://github.com/PHPCompatibility/PHPCompatibility/pull/358) +- :wrench: Travis script: Minor tweak for PHP 5.2 compatibility. [#341](https://github.com/PHPCompatibility/PHPCompatibility/pull/341) +- :wrench: The unit test suite is now also compatible with PHPUnit 6. [#365](https://github.com/PHPCompatibility/PHPCompatibility/pull/365) +- :books: Readme: Typo in the composer instructions. [#344](https://github.com/PHPCompatibility/PHPCompatibility/pull/344) + +### Credits +Thanks go out to [Arthur Edamov], [Juliette Reinders Folmer], [Mark Clements] and [Tadas Juozapaitis] for their contributions to this version. :clap: + + +## [7.1.2] - 2017-02-17 + +See all related issues and PRs in the [7.1.2 milestone]. + +### Added +- :star2: New `VariableVariables` sniff to detect variables variables for which the behaviour has changed in PHP 7.0. [#310](https://github.com/PHPCompatibility/PHPCompatibility/pull/310) Fixes [#309](https://github.com/PHPCompatibility/PHPCompatibility/issues/309). +- :star: The `NewReturnTypeDeclarations` sniff will now also sniff for non-scalar return type declarations, i.e. `array`, `callable`, `self` or a class name. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323) +- :star: The `NewLanguageConstructs` sniff will now also sniff for the null coalesce equal operator `??=`. This operator is slated to be introduced in PHP 7.2 and PHPCS already accounts for it. [#340](https://github.com/PHPCompatibility/PHPCompatibility/pull/340) +- :star: New `getReturnTypeHintToken()` utility method to the `PHPCompatibility_Sniff` class to retrieve return type hints from function declarations in a cross-PHPCS-version compatible way. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323). +- :star: New `stripVariables()` utility method to the `PHPCompatibility_Sniff` class to strip variables from interpolated text strings. [#341](https://github.com/PHPCompatibility/PHPCompatibility/pull/314). +- :umbrella: Additional unit tests covering previously uncovered code. [#308](https://github.com/PHPCompatibility/PHPCompatibility/pull/308) + +### Changed +- :pushpin: The `MbstringReplaceEModifier`, `PregReplaceEModifier` and `NewExecutionDirectives` sniffs will now also correctly interpret double quoted text strings with interpolated variables. [#341](https://github.com/PHPCompatibility/PHPCompatibility/pull/314), [#324](https://github.com/PHPCompatibility/PHPCompatibility/pull/324). +- :pushpin: The `NewNullableTypes` sniff will now also report on nullable (return) type hints when used with closures. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323) +- :pushpin: The `NewReturnTypeDeclarations` sniff will now also report on return type hints when used with closures. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323) +- :pushpin: Allow for anonymous classes in the `inClassScope()` utility method. [#315](https://github.com/PHPCompatibility/PHPCompatibility/pull/315) +- :pushpin: The function call parameter related utility functions can now also be used to get the individual items from an array declaration. [#300](https://github.com/PHPCompatibility/PHPCompatibility/pull/300) +- :twisted_rightwards_arrows: The `NewScalarReturnTypeDeclarations` sniff has been renamed to `NewReturnTypeDeclarations`. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323) +- :rewind: The `ForbiddenNames` sniff will now also correctly ignore anonymous classes when used in combination with PHPCS < 2.3.4. [#319](https://github.com/PHPCompatibility/PHPCompatibility/pull/319) +- :rewind: The `NewAnonymousClasses` sniff will now correctly recognize and report on anonymous classes when used in combination with PHPCS < 2.5.2. [#325](https://github.com/PHPCompatibility/PHPCompatibility/pull/325) +- :rewind: The `NewGroupUseDeclarations` sniff will now correctly recognize and report on group use statements when used in combination with PHPCS < 2.6.0. [#320](https://github.com/PHPCompatibility/PHPCompatibility/pull/320) +- :rewind: The `NewNullableTypes` sniff will now correctly recognize and report on nullable return types when used in combination with PHPCS < 2.6.0. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323) +- :rewind: The `NewReturnTypeDeclarations` sniff will now correctly recognize and report on new return types when used in combination with PHPCS < 2.6.0. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#317](https://github.com/PHPCompatibility/PHPCompatibility/pull/317) +- :recycle: Defer to upstream `hasCondition()` utility method where appropriate. [#315](https://github.com/PHPCompatibility/PHPCompatibility/pull/315) +- :recycle: Minor refactoring of some unit test code. [#304](https://github.com/PHPCompatibility/PHPCompatibility/pull/304), [#303](https://github.com/PHPCompatibility/PHPCompatibility/pull/303), [#318](https://github.com/PHPCompatibility/PHPCompatibility/pull/318) +- :wrench: All unit tests now have appropriate `@group` annotations allowing for quicker/easier testing of a select group of tests/sniffs. [#305](https://github.com/PHPCompatibility/PHPCompatibility/pull/305) +- :wrench: All unit tests now have appropriate `@covers` annotations to improve code coverage reporting and remove bleed through of accidental coverage. [#307](https://github.com/PHPCompatibility/PHPCompatibility/pull/307) +- :wrench: Minor tweaks to the travis script. [#322](https://github.com/PHPCompatibility/PHPCompatibility/pull/322) +- :green_heart: The PHPCompatibility code base itself will now be checked for cross-version compatibility during build testing. [#322](https://github.com/PHPCompatibility/PHPCompatibility/pull/322) + +### Fixed +- :bug: The `ConstantArraysUsingDefine` sniff would throw false positives if the value of the `define()` was retrieved via a function call and an array parameter was passed. [#327](https://github.com/PHPCompatibility/PHPCompatibility/pull/327) +- :bug: The `ForbiddenCallTimePassByReference` sniff would throw false positives on assign by reference within function calls or conditions. [#302](https://github.com/PHPCompatibility/PHPCompatibility/pull/302) Fixes the last two cases reported in [#68](https://github.com/PHPCompatibility/PHPCompatibility/issues/68#issuecomment-231366445) +- :bug: The `ForbiddenGlobalVariableVariableSniff` sniff would only examine the first variable in a `global ...` statement causing unreported issues if subsequent variables were variable variables. [#316](https://github.com/PHPCompatibility/PHPCompatibility/pull/316) +- :bug: The `NewKeywords` sniff would throw a false positive for the `const` keyword when encountered in an interface. [#312](https://github.com/PHPCompatibility/PHPCompatibility/pull/312) +- :bug: The `NewNullableTypes` sniff would not report on nullable return types for namespaced classnames used as a type hint. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323) +- :bug: The `PregReplaceEModifier` sniff would always consider the first parameter passed as a single regex, while it could also be an array of regexes. This led to false positives and potentially unreported use of the `e` modifier when an array of regexes was passed. [#300](https://github.com/PHPCompatibility/PHPCompatibility/pull/300) +- :bug: The `PregReplaceEModifier` sniff could misidentify the regex delimiter when the regex to be examined was concatenated together from various text strings taken from a compound parameter leading to false positives. [#300](https://github.com/PHPCompatibility/PHPCompatibility/pull/300) +- :white_check_mark: Compatibility with PHPCS 2.7.x. Deal with changed behaviour of the upstream PHP tokenizer and utility function(s). [#313](https://github.com/PHPCompatibility/PHPCompatibility/pull/313), [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323), [#326](https://github.com/PHPCompatibility/PHPCompatibility/pull/326), [#340](https://github.com/PHPCompatibility/PHPCompatibility/pull/340) + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.1.1] - 2016-12-14 + +See all related issues and PRs in the [7.1.1 milestone]. + +### Added +- :star: `ForbiddenNamesAsDeclared` sniff: detection of the PHP 7.1 `iterable` and `void` reserved keywords when used to name classes, interfaces or traits. [#298](https://github.com/PHPCompatibility/PHPCompatibility/pull/298) + +### Fixed +- :bug: The `ForbiddenNamesAsInvokedFunctions` sniff would incorrectly throw an error if the `clone` keyword was used with parenthesis. [#299](https://github.com/PHPCompatibility/PHPCompatibility/pull/299). Fixes [#284](https://github.com/PHPCompatibility/PHPCompatibility/issues/284) + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.1.0] - 2016-12-14 + +See all related issues and PRs in the [7.1.0 milestone]. + +### Added +- :star: New `stringToErrorCode()`, `arrayKeysToLowercase()` and `addMessage()` utility methods to the `PHPCompatibility_Sniff` class. [#291](https://github.com/PHPCompatibility/PHPCompatibility/pull/291). + +### Changed +- :pushpin: All sniff error messages now have modular error codes allowing for selectively disabling individual checks - and even selectively disabling individual sniff for specific files - without disabling the complete sniff. [#291](https://github.com/PHPCompatibility/PHPCompatibility/pull/291) +- :pencil2: Minor changes to some of the error message texts for consistency across sniffs. [#291](https://github.com/PHPCompatibility/PHPCompatibility/pull/291) +- :recycle: Refactored the complex version sniffs to reduce code duplication. [#291](https://github.com/PHPCompatibility/PHPCompatibility/pull/291) +- :recycle: Miscellaneous other refactoring for improved performance and sniff accuracy. [#291](https://github.com/PHPCompatibility/PHPCompatibility/pull/291) +- :umbrella: The unit tests for the `RemovedExtensions` sniff now verify that the correct alternative extension is being suggested. [#291](https://github.com/PHPCompatibility/PHPCompatibility/pull/291) + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.0.8] - 2016-10-31 - :ghost: Spooky! :jack_o_lantern: + +See all related issues and PRs in the [7.0.8 milestone]. + +### Added +- :star2: New `ForbiddenNamesAsDeclared` sniff: detection of the [other reserved keywords](http://php.net/manual/en/reserved.other-reserved-words.php) which are reserved as of PHP 7.0 (or higher). [#287](https://github.com/PHPCompatibility/PHPCompatibility/pull/287). Fixes [#115](https://github.com/PHPCompatibility/PHPCompatibility/issues/115). + These were previously sniffed for by the `ForbiddenNames` and `ForbiddenNamesAsInvokedFunctions` sniffs causing false positives as the rules for their reservation are different from the rules for "normal" [reserved keywords](http://php.net/manual/en/reserved.keywords.php). +- :star: New `inUseScope()` utility method to the `PHPCompatibility_Sniff` class which handles PHPCS cross-version compatibility when determining the scope of a `use` statement. [#271](https://github.com/PHPCompatibility/PHPCompatibility/pull/271). +- :umbrella: More unit tests for the `ForbiddenNames` sniff. [#271](https://github.com/PHPCompatibility/PHPCompatibility/pull/271). + +### Changed +- :pushpin: _Deprecated_ functionality should throw a `warning`. _Removed_ or otherwise unavailable functionality should throw an `error`. This distinction was previously not consistently applied everywhere. [#286](https://github.com/PHPCompatibility/PHPCompatibility/pull/286) + This change affects the following sniffs: + * `DeprecatedPHP4StyleConstructors` will now throw a `warning` instead of an `error` for deprecated PHP4 style class constructors. + * `ForbiddenCallTimePassByReference` will now throw a `warning` if the `testVersion` is `5.3` and an `error` if the `testVersion` if `5.4` or higher. + * `MbstringReplaceEModifier` will now throw a `warning` instead of an `error` for usage of the deprecated `e` modifier. + * `PregReplaceEModifier` will now throw a `warning` if the `testVersion` is `5.5` or `5.6` and an `error` if the `testVersion` if `7.0` or higher. Fixes [#290](https://github.com/PHPCompatibility/PHPCompatibility/issues/290). + * `TernaryOperators` will now throw an `error` when the `testVersion` < `5.3` and the middle part has been omitted. + * `ValidIntegers` will now throw a `warning` when an invalid binary integer is detected. +- :pencil2: `DeprecatedFunctions` and `DeprecatedIniDirectives` sniffs: minor change in the sniff error message text. Use _"removed"_ rather than the ominous _"forbidden"_. [#285](https://github.com/PHPCompatibility/PHPCompatibility/pull/285) + Also updated relevant internal variable names and documentation to match. + +### Fixed +- :bug: `ForbiddenNames` sniff would throw false positives for `use` statements which changed the visibility of methods in traits. [#271](https://github.com/PHPCompatibility/PHPCompatibility/pull/271). +- :bug: `ForbiddenNames` sniff would not report reserved keywords when used in combination with `use function` or `use const`. [#271](https://github.com/PHPCompatibility/PHPCompatibility/pull/271). +- :bug: `ForbiddenNames` sniff would potentially - unintentionally - skip over tokens, thereby - potentially - not reporting all errors. [#271](https://github.com/PHPCompatibility/PHPCompatibility/pull/271). +- :wrench: Composer config: `prefer-stable` should be a root element of the json file. Fixes [#277](https://github.com/PHPCompatibility/PHPCompatibility/issues/277). + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.0.7] - 2016-10-20 + +See all related issues and PRs in the [7.0.7 milestone]. + +### Added +- :star2: New `ForbiddenBreakContinueOutsideLoop` sniff: verify that `break`/`continue` is not used outside of a loop structure. This will cause fatal errors since PHP 7.0. [#278](https://github.com/PHPCompatibility/PHPCompatibility/pull/278). Fixes [#275](https://github.com/PHPCompatibility/PHPCompatibility/issues/275) +- :star2: New `NewConstVisibility` sniff: detect visibility indicators for `class` and `interface` constants as introduced in PHP 7.1. [#280](https://github.com/PHPCompatibility/PHPCompatibility/pull/280). Fixes [#249](https://github.com/PHPCompatibility/PHPCompatibility/issues/249) +- :star2: New `NewHashAlgorithms` sniff to check used hash algorithms against the PHP version in which they were introduced. [#242](https://github.com/PHPCompatibility/PHPCompatibility/pull/242) +- :star2: New `NewMultiCatch` sniff: detect catch statements catching multiple Exceptions as introduced in PHP 7.1. [#281](https://github.com/PHPCompatibility/PHPCompatibility/pull/281). Fixes [#251](https://github.com/PHPCompatibility/PHPCompatibility/issues/251) +- :star2: New `NewNullableTypes` sniff: detect nullable parameter and return type hints (only supported in PHPCS >= 2.3.4) as introduced in PHP 7.1. [#282](https://github.com/PHPCompatibility/PHPCompatibility/pull/282). Fixes [#247](https://github.com/PHPCompatibility/PHPCompatibility/issues/247) +- :star: `DeprecatedIniDirectives` sniff: recognize PHP 7.1 removed `session` ini directives. [#256](https://github.com/PHPCompatibility/PHPCompatibility/pull/256) +- :star: `NewFunctions` sniff: recognize new `socket_export_stream()` function as introduced in PHP 7.0.7. [#264](https://github.com/PHPCompatibility/PHPCompatibility/pull/264) +- :star: `NewFunctions` sniff: recognize new `curl_...()`, `is_iterable()`, `pcntl_async_signals()`, `session_create_id()`, `session_gc()` functions as introduced in PHP 7.1. [#273](https://github.com/PHPCompatibility/PHPCompatibility/pull/273) +- :star: `NewFunctionParameters` sniff: recognize new OpenSSL function parameters as introduced in PHP 7.1. [#258](https://github.com/PHPCompatibility/PHPCompatibility/pull/258) +- :star: `NewIniDirectives` sniff: recognize new `session` ini directives as introduced in PHP 7.1. [#259](https://github.com/PHPCompatibility/PHPCompatibility/pull/259) +- :star: `NewScalarReturnTypeDeclarations` sniff: recognize PHP 7.1 `void` return type hint. [#250](https://github.com/PHPCompatibility/PHPCompatibility/pull/250) +- :star: `NewScalarTypeDeclarations` sniff: recognize PHP 7.1 `iterable` type hint. [#255](https://github.com/PHPCompatibility/PHPCompatibility/pull/255) +- :star: Recognize the PHP 7.1 deprecated `mcrypt` functionality in the `RemovedExtensions`, `DeprecatedFunctions` and `DeprecatedIniDirectives` sniffs. [#257](https://github.com/PHPCompatibility/PHPCompatibility/pull/257) + +### Changed +- :pushpin: `LongArrays` sniff used to only throw `warning`s. It will now throw `error`s for PHP versions in which the long superglobals have been removed. [#270](https://github.com/PHPCompatibility/PHPCompatibility/pull/270) +- :pushpin: The `NewIniDirectives` sniff used to always throw an `warning`. Now it will throw an `error` when a new ini directive is used in combination with `ini_set()`. [#246](https://github.com/PHPCompatibility/PHPCompatibility/pull/246). +- :pushpin: `RemovedHashAlgorithms` sniff: also recognize removed algorithms when used with the PHP 5.5+ `hash_pbkdf2()` function. [#240](https://github.com/PHPCompatibility/PHPCompatibility/pull/240) +- :pushpin: Properly recognize nullable type hints in the `getMethodParameters()` utility method. [#282](https://github.com/PHPCompatibility/PHPCompatibility/pull/282) +- :pencil2: `DeprecatedPHP4StyleConstructors` sniff: minor error message text fix. [#236](https://github.com/PHPCompatibility/PHPCompatibility/pull/236) +- :pencil2: `NewIniDirectives` sniff: improved precision for the introduction version numbers being reported. [#246](https://github.com/PHPCompatibility/PHPCompatibility/pull/246) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#238](https://github.com/PHPCompatibility/PHPCompatibility/pull/238), [#244](https://github.com/PHPCompatibility/PHPCompatibility/pull/244), [#240](https://github.com/PHPCompatibility/PHPCompatibility/pull/240), [#276](https://github.com/PHPCompatibility/PHPCompatibility/pull/276) +- :umbrella: Re-activate the unit tests for the `NewScalarReturnTypeDeclarations` sniff. [#250](https://github.com/PHPCompatibility/PHPCompatibility/pull/250) + +### Fixed +- :bug: The `DeprecatedPHP4StyleConstructors` sniff would not report errors when the case of the class name and the PHP4 constructor function name did not match. [#236](https://github.com/PHPCompatibility/PHPCompatibility/pull/236) +- :bug: `LongArrays` sniff would report false positives for class properties shadowing removed PHP superglobals. [#270](https://github.com/PHPCompatibility/PHPCompatibility/pull/270). Fixes [#268](https://github.com/PHPCompatibility/PHPCompatibility/issues/268). +- :bug: The `NewClasses` sniff would not report errors when the case of the class name used and "official" class name did not match. [#237](https://github.com/PHPCompatibility/PHPCompatibility/pull/237) +- :bug: The `NewIniDirectives` sniff would report violations against the PHP version in which the ini directive was introduced. This should be the version below it. [#246](https://github.com/PHPCompatibility/PHPCompatibility/pull/246) +- :bug: `PregReplaceEModifier` sniff would report false positives for compound regex parameters with different quote types. [#266](https://github.com/PHPCompatibility/PHPCompatibility/pull/266). Fixes [#265](https://github.com/PHPCompatibility/PHPCompatibility/issues/265). +- :bug: `RemovedGlobalVariables` sniff would report false positives for lowercase/mixed cased variables shadowing superglobals. [#245](https://github.com/PHPCompatibility/PHPCompatibility/pull/245). +- :bug: The `RemovedHashAlgorithms` sniff would not report errors when the case of the hash function name used and "official" class name did not match. [#240](https://github.com/PHPCompatibility/PHPCompatibility/pull/240) +- :bug: The `ShortArray` sniff would report all violations on the line of the PHP open tag, not on the lines of the short array open/close tags. [#238](https://github.com/PHPCompatibility/PHPCompatibility/pull/238) + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.0.6] - 2016-09-23 + +See all related issues and PRs in the [7.0.6 milestone]. + +### Added +- :star: New `stripQuotes()` utility method in the `PHPCompatibility_Sniff` base class to strip quotes which surround text strings in a consistent manner. [#224](https://github.com/PHPCompatibility/PHPCompatibility/pull/224) +- :books: Readme: Add _PHP Version Support_ section. [#225](https://github.com/PHPCompatibility/PHPCompatibility/pull/225) + +### Changed +- :pushpin: The `ForbiddenCallTimePassByReference` sniff will now also report the deprecation as of PHP 5.3, not just its removal as of PHP 5.4. [#203](https://github.com/PHPCompatibility/PHPCompatibility/pull/203) +- :pushpin: The `NewFunctionArrayDereferencing` sniff will now also check _method_ calls for array dereferencing, not just function calls. [#229](https://github.com/PHPCompatibility/PHPCompatibility/pull/229). Fixes [#227](https://github.com/PHPCompatibility/PHPCompatibility/issues/227). +- :pencil2: The `NewExecutionDirectives` sniff will now throw `warning`s instead of `error`s for invalid values encountered in execution directives. [#223](https://github.com/PHPCompatibility/PHPCompatibility/pull/223) +- :pencil2: Minor miscellaneous fixes. [#231](https://github.com/PHPCompatibility/PHPCompatibility/pull/231) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#219](https://github.com/PHPCompatibility/PHPCompatibility/pull/219), [#203](https://github.com/PHPCompatibility/PHPCompatibility/pull/203) +- :recycle: Defer to upstream `findImplementedInterfaceNames()` utility method when it exists. [#222](https://github.com/PHPCompatibility/PHPCompatibility/pull/222) +- :wrench: Exclude the test files from analysis by Scrutinizer CI. [#230](https://github.com/PHPCompatibility/PHPCompatibility/pull/230) + +### Removed +- :no_entry_sign: Some redundant code. [#232](https://github.com/PHPCompatibility/PHPCompatibility/pull/232) + +### Fixed +- :bug: The `EmptyNonVariable` sniff would throw false positives for variable variables and for array access with a (partially) variable array index. [#212](https://github.com/PHPCompatibility/PHPCompatibility/pull/212). Fixes [#210](https://github.com/PHPCompatibility/PHPCompatibility/issues/210). +- :bug: The `NewFunctionArrayDereferencing` sniff would throw false positives for lines of code containing both a function call as well as square brackets, even when they were unrelated. [#228](https://github.com/PHPCompatibility/PHPCompatibility/pull/228). Fixes [#226](https://github.com/PHPCompatibility/PHPCompatibility/issues/226). +- :bug: `ParameterShadowSuperGlobals` sniff would report false positives for lowercase/mixed cased variables shadowing superglobals. [#218](https://github.com/PHPCompatibility/PHPCompatibility/pull/218). Fixes [#214](https://github.com/PHPCompatibility/PHPCompatibility/issues/214). +- :bug: The `determineNamespace()` utility method now accounts properly for namespaces within scoped `declare()` statements. [#221](https://github.com/PHPCompatibility/PHPCompatibility/pull/221) +- :books: Readme: Logo alignment in the Credits section. [#233](https://github.com/PHPCompatibility/PHPCompatibility/pull/233) + +### Credits +Thanks go out to [Jason Stallings], [Juliette Reinders Folmer] and [Mark Clements] for their contributions to this version. :clap: + + +## [7.0.5] - 2016-09-08 + +See all related issues and PRs in the [7.0.5 milestone]. + +### Added +- :star2: New `MbstringReplaceEModifier` sniff to detect the use of the PHP 7.1 deprecated `e` modifier in Mbstring regex functions. [#202](https://github.com/PHPCompatibility/PHPCompatibility/pull/202) +- :star: The `ForbiddenBreakContinueVariableArguments` sniff will now also report on `break 0`/`continue 0` which is not allowed since PHP 5.4. [#209](https://github.com/PHPCompatibility/PHPCompatibility/pull/209) +- :star: New `getFunctionCallParameters()`, `getFunctionCallParameter()` utility methods in the `PHPCompatibility_Sniff` base class. [#170](https://github.com/PHPCompatibility/PHPCompatibility/pull/170) +- :star: New `tokenHasScope()` utility method in the `PHPCompatibility_Sniff` base class. [#189](https://github.com/PHPCompatibility/PHPCompatibility/pull/189) +- :umbrella: Unit test for `goto` and `callable` detection and some other miscellanous extra unit tests for the `NewKeywords` sniff. [#189](https://github.com/PHPCompatibility/PHPCompatibility/pull/189) +- :books: Readme: Information for sniff developers about running unit tests for _other_ sniff libraries using the PHPCS native test framework without running into conflicts with the PHPCompatibility specific unit test framework. [#217](https://github.com/PHPCompatibility/PHPCompatibility/pull/217) + +### Changed +- :pushpin: The `ForbiddenNames` sniff will now also check interface declarations for usage of reserved keywords. [#200](https://github.com/PHPCompatibility/PHPCompatibility/pull/200) +- :pushpin: `PregReplaceEModifier` sniff: improved handling of regexes build up of a combination of variables, function calls and/or text strings. [#201](https://github.com/PHPCompatibility/PHPCompatibility/pull/201) +- :rewind: The `NewKeywords` sniff will now also correctly recognize new keywords when used in combination with older PHPCS versions and/or run on older PHP versions. [#189](https://github.com/PHPCompatibility/PHPCompatibility/pull/189) +- :pencil2: `PregReplaceEModifier` sniff: minor improvement to the error message text. [#201](https://github.com/PHPCompatibility/PHPCompatibility/pull/201) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#170](https://github.com/PHPCompatibility/PHPCompatibility/pull/170), [#188](https://github.com/PHPCompatibility/PHPCompatibility/pull/188), [#189](https://github.com/PHPCompatibility/PHPCompatibility/pull/189), [#199](https://github.com/PHPCompatibility/PHPCompatibility/pull/199), [#200](https://github.com/PHPCompatibility/PHPCompatibility/pull/200), [#201](https://github.com/PHPCompatibility/PHPCompatibility/pull/201), [#208](https://github.com/PHPCompatibility/PHPCompatibility/pull/208) +- :wrench: The unit tests for the utility methods have been moved to their own subdirectory within `Tests`. [#215](https://github.com/PHPCompatibility/PHPCompatibility/pull/215) +- :green_heart: The sniffs are now also tested against PHP 7.1 for consistent results. [#216](https://github.com/PHPCompatibility/PHPCompatibility/pull/216) + +### Removed +- :no_entry_sign: Some redundant code. [26d0b6](https://github.com/PHPCompatibility/PHPCompatibility/commit/26d0b6cf0921f75d93a4faaf09c390f386dde9ff) and [841616](https://github.com/PHPCompatibility/PHPCompatibility/commit/8416162ea81f4067226324f5948f4a50f7958a9b) + +### Fixed +- :bug: `ConstantArraysUsingDefine` sniff: the version check logic was reversed causing the error not to be reported in certain circumstances. [#199](https://github.com/PHPCompatibility/PHPCompatibility/pull/199) +- :bug: The `DeprecatedIniDirectives` and `NewIniDirectives` sniffs could potentially trigger on the ini value instead of the ini directive name. [#170](https://github.com/PHPCompatibility/PHPCompatibility/pull/170) +- :bug: `ForbiddenNames` sniff: Reserved keywords when used as the name of a constant declared using `define()` would always be reported independently of the `testVersion` set. [#200](https://github.com/PHPCompatibility/PHPCompatibility/pull/200) +- :bug: `PregReplaceEModifier` sniff would not report errors when the function name used was not in lowercase. [#201](https://github.com/PHPCompatibility/PHPCompatibility/pull/201) +- :bug: `TernaryOperators` sniff: the version check logic was reversed causing the error not to be reported in certain circumstances. [#188](https://github.com/PHPCompatibility/PHPCompatibility/pull/188) +- :bug: The `getFQClassNameFromNewToken()` and `getFQClassNameFromDoubleColonToken()` utility methods would get confused when the class name was a variable instead of being hard-coded, resulting in a PHP warning being thown. [#206](https://github.com/PHPCompatibility/PHPCompatibility/pull/206). Fixes [#205](https://github.com/PHPCompatibility/PHPCompatibility/issues/205). +- :bug: The `getFunctionCallParameters()` utility method would incorrectly identify an extra parameter if the last parameter passed to a function would have an - unnecessary - comma after it. The `getFunctionCallParameters()` utility method also did not handle parameters passed as short arrays correctly. [#213](https://github.com/PHPCompatibility/PHPCompatibility/pull/213). Fixes [#211](https://github.com/PHPCompatibility/PHPCompatibility/issues/211). +- :umbrella: Unit tests for the `NewFunctionArrayDereferencing` sniff were not being run due to a naming error. [#208](https://github.com/PHPCompatibility/PHPCompatibility/pull/208) +- :books: Readme: Information about setting the `testVersion` from a custom ruleset was incorrect. [#204](https://github.com/PHPCompatibility/PHPCompatibility/pull/204) +- :wrench: Path to PHPCS in the unit tests breaking for non-Composer installs. [#198](https://github.com/PHPCompatibility/PHPCompatibility/pull/198) + +### Credits +Thanks go out to [Juliette Reinders Folmer] and [Yoshiaki Yoshida] for their contributions to this version. :clap: + + +## [7.0.4] - 2016-08-20 + +See all related issues and PRs in the [7.0.4 milestone]. + +### Added +- :star2: New `EmptyNonVariable` sniff: detection of empty being used on non-variables for PHP < 5.5. [#187](https://github.com/PHPCompatibility/PHPCompatibility/pull/187) +- :star2: New `NewMagicMethods` sniff: detection of declaration of magic methods before the method became "magic". Includes a check for the changed behaviour for the `__toString()` magic method in PHP 5.2. [#176](https://github.com/PHPCompatibility/PHPCompatibility/pull/176). Fixes [#64](https://github.com/PHPCompatibility/PHPCompatibility/issues/64). +- :star2: New `RemovedAlternativePHPTags` sniff: detection of ASP and script open tags for which support was removed in PHP 7.0. [#184](https://github.com/PHPCompatibility/PHPCompatibility/pull/184), [#193](https://github.com/PHPCompatibility/PHPCompatibility/pull/193). Fixes [#127](https://github.com/PHPCompatibility/PHPCompatibility/issues/127). +- :star: `NonStaticMagicMethods` sniff: detection of the `__callStatic()`, `__sleep()`, `__toString()` and `__set_state()` magic methods. +- :green_heart: Lint all non-test case files for syntax errors during the build testing by Travis. [#192](https://github.com/PHPCompatibility/PHPCompatibility/pull/192) + +### Changed +- :pushpin: `NonStaticMagicMethods` sniff: will now also sniff `trait`s for magic methods. [#174](https://github.com/PHPCompatibility/PHPCompatibility/pull/174) +- :pushpin: `NonStaticMagicMethods` sniff: will now also check for magic methods which should be declared as `static`. [#174](https://github.com/PHPCompatibility/PHPCompatibility/pull/174) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#178](https://github.com/PHPCompatibility/PHPCompatibility/pull/178), [#179](https://github.com/PHPCompatibility/PHPCompatibility/pull/179), [#174](https://github.com/PHPCompatibility/PHPCompatibility/pull/174), [#171](https://github.com/PHPCompatibility/PHPCompatibility/pull/171) +- :recycle: The unit test suite now internally caches PHPCS run results in combination with a set `testVersion` to speed up the running of the unit tests. These are now ~3 x faster. [#148](https://github.com/PHPCompatibility/PHPCompatibility/pull/148) +- :books: Readme: Minor clarification of the minimum requirements. +- :books: Readme: Advise to use the latest stable version of this repository. +- :wrench: The unit tests can now be run with PHPCS installed in an arbitrary location by passing the location through an environment option. [#191](https://github.com/PHPCompatibility/PHPCompatibility/pull/191). +- :wrench: Improved coveralls configuration and compatibility. [#194](https://github.com/PHPCompatibility/PHPCompatibility/pull/194) +- :green_heart: The sniffs are now also tested against PHP 5.2 for consistent results. Except for namespace, trait and group use related errors, most sniffs work as intended on PHP 5.2. [#196](https://github.com/PHPCompatibility/PHPCompatibility/pull/196) + +### Fixed +- :bug: The `ForbiddenBreakContinueVariableArguments` sniff would not report on `break`/`continue` with a closure as an argument. [#171](https://github.com/PHPCompatibility/PHPCompatibility/pull/171) +- :bug: The `ForbiddenNamesAsInvokedFunctions` sniff would not report on reserved keywords which were not lowercase. [#186](https://github.com/PHPCompatibility/PHPCompatibility/pull/186) +- :bug: The `ForbiddenNamesAsInvokedFunctions` sniff would not report on the `goto` and `namespace` keywords when run on PHP 5.2. [#193](https://github.com/PHPCompatibility/PHPCompatibility/pull/193) +- :bug: `NewAnonymousClasses` sniff: the version check logic was reversed causing the error not to be reported in certain circumstances. [#195](https://github.com/PHPCompatibility/PHPCompatibility/pull/195). +- :bug: `NewGroupUseDeclarations` sniff: the version check logic was reversed causing the error not to be reported in certain circumstances. [#190](https://github.com/PHPCompatibility/PHPCompatibility/pull/190). +- :bug: The `NonStaticMagicMethods` sniff would not report on magic methods when the function name as declared was not in the same case as used in the PHP manual. [#174](https://github.com/PHPCompatibility/PHPCompatibility/pull/174) +- :wrench: The unit tests would exit with `0` if PHPCS could not be found. [#191](https://github.com/PHPCompatibility/PHPCompatibility/pull/191) +- :green_heart: The PHPCompatibility library itself was not fully compatible with PHP 5.2. [#193](https://github.com/PHPCompatibility/PHPCompatibility/pull/193) + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.0.3] - 2016-08-18 + +See all related issues and PRs in the [7.0.3 milestone]. + +### Added +- :star2: New `InternalInterfaces` sniff: detection of internal PHP interfaces being which should not be implemented by user land classes. [#144](https://github.com/PHPCompatibility/PHPCompatibility/pull/144) +- :star2: New `LateStaticBinding` sniff: detection of PHP 5.3 late static binding. [#177](https://github.com/PHPCompatibility/PHPCompatibility/pull/177) +- :star2: New `NewExecutionDirectives` sniff: verify execution directives set with `declare()`. [#169](https://github.com/PHPCompatibility/PHPCompatibility/pull/169) +- :star2: New `NewInterfaces` sniff: detection of the use of newly introduced PHP native interfaces. This sniff will also detect unsupported methods when a class implements the `Serializable` interface. [#144](https://github.com/PHPCompatibility/PHPCompatibility/pull/144) +- :star2: New `RequiredOptionalFunctionParameters` sniff: detection of missing function parameters which were required in earlier PHP versions only to become optional in later versions. [#165](https://github.com/PHPCompatibility/PHPCompatibility/pull/165) +- :star2: New `ValidIntegers` sniff: detection of binary integers for PHP < 5.4, detection of hexademical numeric strings for which recognition as hex integers was removed in PHP 7.0, detection of invalid binary and octal integers. [#160](https://github.com/PHPCompatibility/PHPCompatibility/pull/160). Fixes [#55](https://github.com/PHPCompatibility/PHPCompatibility/issues/55). +- :star: `DeprecatedExtensions` sniff: detect removal of the `ereg` extension in PHP 7. [#149](https://github.com/PHPCompatibility/PHPCompatibility/pull/149) +- :star: `DeprecatedFunctions` sniff: detection of the PHP 5.0.5 deprecated `php_check_syntax()` and PHP 5.4 deprecated `mysqli_get_cache_stats()` functions. [#155](https://github.com/PHPCompatibility/PHPCompatibility/pull/155). +- :star: `DeprecatedFunctions` sniff: detect deprecation of a number of the `mysqli` functions in PHP 5.3. [#149](https://github.com/PHPCompatibility/PHPCompatibility/pull/149) +- :star: `DeprecatedFunctions` sniff: detect removal of the `call_user_method()`, `ldap_sort()`, `ereg_*()` and `mysql_*()` functions in PHP 7.0. [#149](https://github.com/PHPCompatibility/PHPCompatibility/pull/149) +- :star: `DeprecatedIniDirectives` sniff: detection of a _lot_ more deprecated/removed ini directives. [#146](https://github.com/PHPCompatibility/PHPCompatibility/pull/146) +- :star: `NewFunctionParameters` sniff: detection of a _lot_ more new function parameters. [#164](https://github.com/PHPCompatibility/PHPCompatibility/pull/164) +- :star: `NewFunctions` sniff: detection of numerous extra new functions. [#161](https://github.com/PHPCompatibility/PHPCompatibility/pull/161) +- :star: `NewIniDirectives` sniff: detection of a _lot_ more new ini directives. [#146](https://github.com/PHPCompatibility/PHPCompatibility/pull/146) +- :star: `NewLanguageConstructs` sniff: detection of the PHP 5.6 ellipsis `...` construct. [#175](https://github.com/PHPCompatibility/PHPCompatibility/pull/175) +- :star: `NewScalarTypeDeclarations` sniff: detection of PHP 5.1 `array` and PHP 5.4 `callable` type hints. [#168](https://github.com/PHPCompatibility/PHPCompatibility/pull/168) +- :star: `RemovedFunctionParameters` sniff: detection of a few extra removed function parameters. [#163](https://github.com/PHPCompatibility/PHPCompatibility/pull/163) +- :star: Detection of functions and methods with a double underscore prefix as these are reserved by PHP for future use. The existing upstream `Generic.NamingConventions.CamelCapsFunctionName` sniff is re-used for this with some customization. [#173](https://github.com/PHPCompatibility/PHPCompatibility/pull/173) +- :star: New `getFQClassNameFromNewToken()`, `getFQExtendedClassName()`, `getFQClassNameFromDoubleColonToken()`, `getFQName()`, `isNamespaced()`, `determineNamespace()` and `getDeclaredNamespaceName()` utility methods in the `PHPCompatibility_Sniff` base class for namespace determination. [#162](https://github.com/PHPCompatibility/PHPCompatibility/pull/162) +- :recycle: New `inClassScope()` utility method in the `PHPCompatibility_Sniff` base class. [#168](https://github.com/PHPCompatibility/PHPCompatibility/pull/168) +- :recycle: New `doesFunctionCallHaveParameters()` and `getFunctionCallParameterCount()` utility methods in the `PHPCompatibility_Sniff` base class. [#153](https://github.com/PHPCompatibility/PHPCompatibility/pull/153) +- :umbrella: Unit test for `__halt_compiler()` detection by the `NewKeywords` sniff. +- :umbrella: Unit tests for the `NewFunctions` sniff. [#161](https://github.com/PHPCompatibility/PHPCompatibility/pull/161) +- :umbrella: Unit tests for the `ParameterShadowSuperGlobals` sniff. [#180](https://github.com/PHPCompatibility/PHPCompatibility/pull/180) +- :wrench: Minimal config for Scrutinizer CI. [#145](https://github.com/PHPCompatibility/PHPCompatibility/pull/145). + +### Changed +- :pushpin: The `DeprecatedIniDirectives` and the `NewIniDirectives` sniffs will now indicate an alternative ini directive in case the directive has been renamed. [#146](https://github.com/PHPCompatibility/PHPCompatibility/pull/146) +- :pushpin: The `NewClasses` sniff will now also report on new classes being extended by child classes. [#140](https://github.com/PHPCompatibility/PHPCompatibility/pull/140). +- :pushpin: The `NewClasses` sniff will now also report on static use of new classes. [#162](https://github.com/PHPCompatibility/PHPCompatibility/pull/162). +- :pushpin: The `NewScalarTypeDeclarations` sniff will now throw an error on use of type hints pre-PHP 5.0. [#168](https://github.com/PHPCompatibility/PHPCompatibility/pull/168) +- :pushpin: The `NewScalarTypeDeclarations` sniff will now verify type hints used against typical mistakes. [#168](https://github.com/PHPCompatibility/PHPCompatibility/pull/168) +- :pushpin: The `ParameterShadowSuperGlobals` sniff will now do a case-insensitive variable name compare. [#180](https://github.com/PHPCompatibility/PHPCompatibility/pull/180) +- :pushpin: The `RemovedFunctionParameters` sniff will now also report `warning`s on deprecation of function parameters. [#163](https://github.com/PHPCompatibility/PHPCompatibility/pull/163) +- :twisted_rightwards_arrows: The check for `JsonSerializable` has been moved from the `NewClasses` sniff to the `NewInterfaces` sniff. [#162](https://github.com/PHPCompatibility/PHPCompatibility/pull/162) +- :rewind: The `NewLanguageConstructs` sniff will now also recognize new language constructs when used in combination with PHPCS 1.5.x. [#175](https://github.com/PHPCompatibility/PHPCompatibility/pull/175) +- :pencil2: `NewFunctionParameters` sniff: use correct name for the new parameter for the `dirname()` function. [#164](https://github.com/PHPCompatibility/PHPCompatibility/pull/164) +- :pencil2: `NewScalarTypeDeclarations` sniff: minor change in the sniff error message text. [#168](https://github.com/PHPCompatibility/PHPCompatibility/pull/168) +- :pencil2: `RemovedFunctionParameters` sniff: minor change in the sniff error message text. [#163](https://github.com/PHPCompatibility/PHPCompatibility/pull/163) +- :pencil2: The `ParameterShadowSuperGlobals` sniff now extends the `PHPCompatibility_Sniff` class. [#180](https://github.com/PHPCompatibility/PHPCompatibility/pull/180) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#181](https://github.com/PHPCompatibility/PHPCompatibility/pull/181), [#182](https://github.com/PHPCompatibility/PHPCompatibility/pull/182), [#166](https://github.com/PHPCompatibility/PHPCompatibility/pull/166), [#167](https://github.com/PHPCompatibility/PHPCompatibility/pull/167), [#172](https://github.com/PHPCompatibility/PHPCompatibility/pull/172), [#180](https://github.com/PHPCompatibility/PHPCompatibility/pull/180), [#146](https://github.com/PHPCompatibility/PHPCompatibility/pull/146), [#138](https://github.com/PHPCompatibility/PHPCompatibility/pull/138) +- :recycle: Various refactoring to remove code duplication in the unit tests and add proper test skip notifications where relevant. [#139](https://github.com/PHPCompatibility/PHPCompatibility/pull/139), [#149](https://github.com/PHPCompatibility/PHPCompatibility/pull/149) + +### Fixed +- :bug: The `DeprecatedFunctions` sniff was reporting an incorrect deprecation/removal version number for a few functions. [#149](https://github.com/PHPCompatibility/PHPCompatibility/pull/149) +- :bug: The `DeprecatedIniDirectives` sniff was in select cases reporting deprecation of an ini directive prior to removal, while the ini directive was never deprecated prior to its removal. [#146](https://github.com/PHPCompatibility/PHPCompatibility/pull/146) +- :bug: The `DeprecatedPHP4StyleConstructors` sniff would cause false positives for methods with the same name as the class in namespaced classes. [#167](https://github.com/PHPCompatibility/PHPCompatibility/pull/167) +- :bug: The `ForbiddenEmptyListAssignment` sniff did not report errors when there were only comments or parentheses between the list parentheses. [#166](https://github.com/PHPCompatibility/PHPCompatibility/pull/166) +- :bug: The `ForbiddenEmptyListAssignment` sniff will no longer cause false positives during live coding. [#166](https://github.com/PHPCompatibility/PHPCompatibility/pull/166) +- :bug: The `NewClasses` sniff would potentially misidentify namespaced classes as PHP native classes. [#161](https://github.com/PHPCompatibility/PHPCompatibility/pull/162) +- :bug: The `NewFunctions` sniff would fail to identify called functions when the function call was not lowercase. [#161](https://github.com/PHPCompatibility/PHPCompatibility/pull/161) +- :bug: The `NewFunctions` sniff would potentially misidentify namespaced userland functions as new functions. [#161](https://github.com/PHPCompatibility/PHPCompatibility/pull/161) +- :bug: The `NewIniDirectives` sniff was reporting an incorrect introduction version number for a few ini directives. [#146](https://github.com/PHPCompatibility/PHPCompatibility/pull/146) +- :bug: `NewKeywords` sniff: the use of the `const` keyword should only be reported when used outside of a class for PHP < 5.3. [#147](https://github.com/PHPCompatibility/PHPCompatibility/pull/147). Fixes [#129](https://github.com/PHPCompatibility/PHPCompatibility/issues/129). +- :bug: The `RemovedExtensions` sniff was incorrectly reporting a number of extensions as being removed in PHP 5.3 while they were actually removed in PHP 5.1. [#156](https://github.com/PHPCompatibility/PHPCompatibility/pull/156) +- :bug: :recycle: The `NewFunctionParameters` and `RemovedFunctionParameters` now use the new `doesFunctionCallHaveParameters()` and `getFunctionCallParameterCount()` utility methods for improved accuracy in identifying function parameters. This fixes several false positives. [#153](https://github.com/PHPCompatibility/PHPCompatibility/pull/153) Fixes [#120](https://github.com/PHPCompatibility/PHPCompatibility/issues/120), [#151](https://github.com/PHPCompatibility/PHPCompatibility/issues/151), [#152](https://github.com/PHPCompatibility/PHPCompatibility/issues/152). +- :bug: A number of sniffs would return `false` if the examined construct was not found. This could potentially cause race conditions/infinite sniff loops. [#138](https://github.com/PHPCompatibility/PHPCompatibility/pull/138) +- :wrench: The unit tests would fail to run when used in combination with a PEAR install of PHPCS. [#157](https://github.com/PHPCompatibility/PHPCompatibility/pull/157). +- :green_heart: Unit tests failing against PHPCS 2.6.1. [#158](https://github.com/PHPCompatibility/PHPCompatibility/pull/158) + The unit tests *will* still fail against PHPCS 2.6.2 due to a bug in PHPCS itself. This bug does not affect the running of the sniffs outside of a unit test context. + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.0.2] - 2016-08-03 + +See all related issues and PRs in the [7.0.2 milestone]. + +### Added +- :star: `RemovedExtensions` sniff: ability to whitelist userland functions for which the function prefix overlaps with a prefix of a deprecated/removed extension. [#130](https://github.com/PHPCompatibility/PHPCompatibility/pull/130). Fixes [#123](https://github.com/PHPCompatibility/PHPCompatibility/issues/123). + To use this feature, add the `functionWhitelist` property in your custom ruleset. For more information, see the [README](https://github.com/PHPCompatibility/PHPCompatibility#phpcompatibility-specific-options). + +### Changed +- :pencil2: A number of sniffs contained `public` class properties. Within PHPCS, `public` properties can be overruled via a custom ruleset. This was not the intention, so the visibility of these properties has been changed to `protected`. [#135](https://github.com/PHPCompatibility/PHPCompatibility/pull/135) +- :wrench: Composer config: Stable packages are preferred over unstable/dev. +- :pencil2: Ruleset name. [#134](https://github.com/PHPCompatibility/PHPCompatibility/pull/134) + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.0.1] - 2016-08-02 + +See all related issues and PRs in the [7.0.1 milestone]. + +### Changed +- :pushpin: The `DeprecatedIniDirectives` sniff used to throw an `error` when a deprecated ini directive was used in combination with `ini_get()`. It will now throw a `warning` instead. [#122](https://github.com/PHPCompatibility/PHPCompatibility/pull/122) Fixes [#119](https://github.com/PHPCompatibility/PHPCompatibility/issues/119). + Usage of deprecated ini directives in combination with `ini_set()` will still throw an `error`. +- :pushpin: The `PregReplaceEModifier` sniff now also detects the `e` modifier when used with the `preg_filter()` function. While this is undocumented, the `e` modifier was supported by the `preg_filter()` function as well. [#128](https://github.com/PHPCompatibility/PHPCompatibility/pull/128) +- :pencil2: The `RemovedExtensions` sniff contained superfluous deprecation information in the error message. [#131](https://github.com/PHPCompatibility/PHPCompatibility/pull/131) + +### Removed +- :wrench: Duplicate builds from the Travis CI build matrix. [#132](https://github.com/PHPCompatibility/PHPCompatibility/pull/132) + +### Fixed +- :bug: The `ForbiddenNames` sniff did not allow for the PHP 5.6 `use function ...` and `use const ...` syntax. [#126](https://github.com/PHPCompatibility/PHPCompatibility/pull/126) Fixes [#124](https://github.com/PHPCompatibility/PHPCompatibility/issues/124). +- :bug: The `NewClasses` sniff failed to detect new classes when the class was instantiated without parenthesis, i.e. `new NewClass;`. [#121](https://github.com/PHPCompatibility/PHPCompatibility/pull/121) +- :bug: The `PregReplaceEModifier` sniff failed to detect the `e` modifier when using bracket delimiters for the regex other than the `{}` brackets. [#128](https://github.com/PHPCompatibility/PHPCompatibility/pull/128) +- :green_heart: Unit tests failing against PHPCS 2.6.1. + +### Credits +Thanks go out to [Jason Stallings], [Juliette Reinders Folmer] and [Ryan Neufeld] for their contributions to this version. :clap: + + +## [7.0] - 2016-07-02 + +See all related issues and PRs in the [7.0 milestone]. + +### Added +- :zap: Ability to specify a range of PHP versions against which to test your code base for compatibility, i.e. `--runtime-set testVersion 5.0-5.4` will now test your code for compatibility with PHP 5.0 up to PHP 5.4. [#99](https://github.com/PHPCompatibility/PHPCompatibility/pull/99) +- :star2: New `NewFunctionArrayDereferencing` sniff to detect function array dereferencing as introduced in PHP 5.4. Fixes [#52](https://github.com/PHPCompatibility/PHPCompatibility/issues/52). +- :star2: New `ShortArray` sniff to detect short array syntax as introduced in PHP 5.4. [#97](https://github.com/PHPCompatibility/PHPCompatibility/pull/97). Fixes [#47](https://github.com/PHPCompatibility/PHPCompatibility/issues/47). +- :star2: New `TernaryOperators` sniff to detect ternaries without the middle part (`elvis` operator) as introduced in PHP 5.3. [#101](https://github.com/PHPCompatibility/PHPCompatibility/pull/101), [#103](https://github.com/PHPCompatibility/PHPCompatibility/pull/103). Fixes [#49](https://github.com/PHPCompatibility/PHPCompatibility/issues/49). +- :star2: New `ConstantArraysUsingDefine` sniff to detect constants declared using `define()` being assigned an `array` value which was not allowed prior to PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `DeprecatedPHP4StyleConstructors` sniff to detect PHP 4 style class constructor methods which are deprecated as of PHP 7. [#109](https://github.com/PHPCompatibility/PHPCompatibility/pull/109). +- :star2: New `ForbiddenEmptyListAssignment` sniff to detect empty list() assignments which have been removed in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `ForbiddenFunctionParametersWithSameName` sniff to detect functions declared with multiple same-named parameters which is no longer accepted since PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `ForbiddenGlobalVariableVariable` sniff to detect variable variables being made `global` which is not allowed since PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `ForbiddenNegativeBitshift` sniff to detect bitwise shifts by negative number which will throw an ArithmeticError in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `ForbiddenSwitchWithMultipleDefaultBlocks` sniff to detect switch statements with multiple default blocks which is not allowed since PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `NewAnonymousClasses` sniff to detect anonymous classes as introduced in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `NewClosure` sniff to detect anonymous functions as introduced in PHP 5.3. Fixes [#35](https://github.com/PHPCompatibility/PHPCompatibility/issues/35) +- :star2: New `NewFunctionParameters` sniff to detect use of new parameters in build-in PHP functions. Initially only sniffing for the new PHP 7.0 function parameters and the new PHP 5.3+ `before_needle` parameter for the `strstr()` function. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110), [#112](https://github.com/PHPCompatibility/PHPCompatibility/pull/112). Fixes [#27](https://github.com/PHPCompatibility/PHPCompatibility/issues/27). +- :star2: New `NewGroupUseDeclarations` sniff to detect group use declarations as introduced in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `NewScalarReturnTypeDeclarations` sniff to detect scalar return type hints as introduced in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `NewScalarTypeDeclarations` sniff to detect scalar function parameter type hints as introduced in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `RemovedFunctionParameters` sniff to detect use of removed parameters in build-in PHP functions. Initially only sniffing for the function parameters removed in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `RemovedGlobalVariables` sniff to detect the PHP 7.0 removed `$HTTP_RAW_POST_DATA` superglobal. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `DeprecatedFunctions` sniff: detection of the PHP 5.4 deprecated OCI8 functions. [#93](https://github.com/PHPCompatibility/PHPCompatibility/pull/93) +- :star: `ForbiddenNamesAsInvokedFunctions` sniff: recognize PHP 5.5 `finally` as a reserved keywords when invoked as a function. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `NewKeywords` sniff: detection of the use of the PHP 5.1+ `__halt_compiler` keyword. Fixes [#50](https://github.com/PHPCompatibility/PHPCompatibility/issues/50). +- :star: `NewKeywords` sniff: detection of the PHP 5.3+ `nowdoc` syntax. Fixes [#48](https://github.com/PHPCompatibility/PHPCompatibility/issues/48). +- :star: `NewKeywords` sniff: detection of the use of the `const` keyword outside of a class for PHP < 5.3. Fixes [#50](https://github.com/PHPCompatibility/PHPCompatibility/issues/50). +- :star: `DeprecatedFunctions` sniff: recognize PHP 7.0 deprecated and removed functions. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `DeprecatedIniDirectives` sniff: recognize PHP 7.0 removed ini directives. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `ForbiddenNamesAsInvokedFunctions` sniff: recognize new PHP 7.0 reserved keywords when invoked as functions. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `ForbiddenNames` sniff: recognize new PHP 7.0 reserved keywords. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `NewFunctions` sniff: recognize new functions as introduced in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `NewLanguageConstructs` sniff: recognize new PHP 7.0 `<=>` "spaceship" and `??` null coalescing operators. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `RemovedExtensions` sniff: recognize PHP 7.0 removed `ereg`, `mssql`, `mysql` and `sybase_ct` extensions. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :umbrella: Additional unit tests for the `NewLanguageConstructs` sniff. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :books: Readme: New section containing information about the use of the `testVersion` config variable. +- :books: Readme: Sponsor credits. + +### Changed +- :pushpin: The `DeprecatedIniDirectives` sniff used to always throw an `warning`. Now it will throw an `error` when a removed ini directive is used. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110). +- :pushpin: The `DeprecatedNewReference` sniff will now throw an error when the `testVersion` includes PHP 7.0 or higher. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :pushpin: The `ForbiddenNames` sniff now supports detection of reserved keywords when used in combination with PHP 7 anonymous classes. [#108](https://github.com/PHPCompatibility/PHPCompatibility/pull/108), [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110). +- :pushpin: The `PregReplaceEModifier` sniff will now throw an error when the `testVersion` includes PHP 7.0 or higher. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :pencil2: `NewKeywords` sniff: clarified the error message text for the `use` keyword. Fixes [#46](https://github.com/PHPCompatibility/PHPCompatibility/issues/46). +- :recycle: Minor refactor of the `testVersion` related utility functions. [#98](https://github.com/PHPCompatibility/PHPCompatibility/pull/98) +- :wrench: Add autoload to the `composer.json` file. [#96](https://github.com/PHPCompatibility/PHPCompatibility/pull/96) Fixes [#67](https://github.com/PHPCompatibility/PHPCompatibility/issues/67). +- :wrench: Minor other updates to the `composer.json` file. [#75](https://github.com/PHPCompatibility/PHPCompatibility/pull/75) +- :wrench: Improved creation of the code coverage reports needed by coveralls via Travis. +- :green_heart: The sniffs are now also tested against PHP 7.0 for consistent results. + +### Fixed +- :bug: The `ForbiddenCallTimePassByReference` sniff was throwing `Undefined index` notices when used in combination with PHPCS 2.2.0. [#100](https://github.com/PHPCompatibility/PHPCompatibility/pull/100). Fixes [#42](https://github.com/PHPCompatibility/PHPCompatibility/issues/42). +- :bug: The `ForbiddenNamesAsInvokedFunctions` sniff would incorrectly throw an error if the `throw` keyword was used with parenthesis. Fixes [#118](https://github.com/PHPCompatibility/PHPCompatibility/issues/118). +- :bug: The `PregReplaceEModifier` sniff incorrectly identified `e`'s in the pattern as the `e` modifier when using `{}` bracket delimiters for the regex. [#94](https://github.com/PHPCompatibility/PHPCompatibility/pull/94) +- :bug: The `RemovedExtensions` sniff was throwing an `error` instead of a `warning` for deprecated, but not (yet) removed extensions. Fixes [#62](https://github.com/PHPCompatibility/PHPCompatibility/issues/62). + +### Credits +Thanks go out to AlexMiroshnikov, [Chris Abernethy], [dgudgeon], [djaenecke], [Eugene Maslovich], [Ken Guest], Koen Eelen, [Komarov Alexey], [Mark Clements] and [Remko van Bezooijen] for their contributions to this version. :clap: + + +## [5.6] - 2015-09-14 + +See all related issues and PRs in the [5.6 milestone]. + +### Added +- :star2: New: `NewLanguageConstructs` sniff. The initial version of this sniff checks for the PHP 5.6 `**` power operator and the `**=` power assignment operator. [#87](https://github.com/PHPCompatibility/PHPCompatibility/pull/87). Fixes [#60](https://github.com/PHPCompatibility/PHPCompatibility/issues/60). +- :star2: New: `ParameterShadowSuperGlobals` sniff which covers the PHP 5.4 change _Parameter names that shadow super globals now cause a fatal error.`_. [#74](https://github.com/PHPCompatibility/PHPCompatibility/pull/74) +- :star2: New: `PregReplaceEModifier` sniff which detects usage of the `e` modifier in literal regular expressions used with `preg_replace()`. The `e` modifier will not (yet) be detected when the regex passed is a variable or constant. [#81](https://github.com/PHPCompatibility/PHPCompatibility/pull/81), [#84](https://github.com/PHPCompatibility/PHPCompatibility/pull/84). Fixes [#71](https://github.com/PHPCompatibility/PHPCompatibility/issues/71), [#83](https://github.com/PHPCompatibility/PHPCompatibility/issues/83). +- :star: `DeprecatedIniDirectives` sniff: PHP 5.6 deprecated ini directives. +- :star: `NewKeywords` sniff: detection of the `goto` keyword introduced in PHP 5.3 and the `callable` keyword introduced in PHP 5.4. [#57](https://github.com/PHPCompatibility/PHPCompatibility/pull/57) +- :recycle: `PHPCompatibility_Sniff` base class initially containing the `supportsAbove()` and `supportsBelow()` utility methods. (Nearly) All sniffs now extend this base class and use these methods to determine whether or not violations should be reported for a set `testVersion`. [#77](https://github.com/PHPCompatibility/PHPCompatibility/pull/77) +- :books: Readme: Composer installation instructions. [#32](https://github.com/PHPCompatibility/PHPCompatibility/pull/32), [#61](https://github.com/PHPCompatibility/PHPCompatibility/pull/61) +- :wrench: `.gitignore` to ignore vendor and IDE related directories. [#78](https://github.com/PHPCompatibility/PHPCompatibility/pull/78) +- :green_heart: Code coverage checking via coveralls. + +### Changed +- :twisted_rightwards_arrows: The check for the `\` namespace separator has been moved from the `NewKeywords` sniff to the `NewLanguageConstructs` sniff. [#88](https://github.com/PHPCompatibility/PHPCompatibility/pull/88) +- :pencil2: `DeprecatedIniDirectives` sniff: minor change in the sniff error message text. +- :pencil2: `DeprecatedFunctions` sniff: minor change in the sniff error message text. +- :wrench: Minor updates to the `composer.json` file. [#31](https://github.com/PHPCompatibility/PHPCompatibility/pull/31), [34](https://github.com/PHPCompatibility/PHPCompatibility/pull/34), [#70](https://github.com/PHPCompatibility/PHPCompatibility/pull/70) +- :wrench: Tests: The unit tests can now be run without configuration. +- :wrench: Tests: Skipped unit tests will now be annotated as such. [#85](https://github.com/PHPCompatibility/PHPCompatibility/pull/85) +- :green_heart: The sniffs are now also tested against PHP 5.6 for consistent results. +- :green_heart: The sniffs are now also tested against PHPCS 2.0+. +- :green_heart: The sniffs are now tested using the new container-based infrastructure in Travis CI. [#37](https://github.com/PHPCompatibility/PHPCompatibility/pull/37) + +### Fixed +- :bug: The `ForbiddenCallTimePassByReference` sniff was throwing false positives when a bitwise and `&` was used in combination with class constants and class properties within function calls. [#44](https://github.com/PHPCompatibility/PHPCompatibility/pull/44). Fixes [#39](https://github.com/PHPCompatibility/PHPCompatibility/issues/39). +- :bug: The `ForbiddenNamesAsInvokedFunctions` sniff was throwing false positives in certain cases when a comment separated a `try` from the `catch` block. [#29](https://github.com/PHPCompatibility/PHPCompatibility/pull/29) +- :bug: The `ForbiddenNamesAsInvokedFunctions` sniff was incorrectly reporting `instanceof` as being introduced in PHP 5.4 while it has been around since PHP 5.0. [#80](https://github.com/PHPCompatibility/PHPCompatibility/pull/80) +- :white_check_mark: Compatibility with PHPCS 2.0 - 2.3. [#63](https://github.com/PHPCompatibility/PHPCompatibility/pull/63), [#65](https://github.com/PHPCompatibility/PHPCompatibility/pull/65) + +### Credits +Thanks go out to Daniel Jänecke, [Declan Kelly], [Dominic], [Jaap van Otterdijk], [Marin Crnkovic], [Mark Clements], [Nick Pack], [Oliver Klee], [Rowan Collins] and [Sam Van der Borght] for their contributions to this version. :clap: + + +## 5.5 - 2014-04-04 + +First tagged release. + +See all related issues and PRs in the [5.5 milestone]. + + + +[Unreleased]: https://github.com/PHPCompatibility/PHPCompatibility/compare/master...HEAD +[9.3.5]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.3.4...9.3.5 +[9.3.4]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.3.3...9.3.4 +[9.3.3]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.3.2...9.3.3 +[9.3.2]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.3.1...9.3.2 +[9.3.1]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.3.0...9.3.1 +[9.3.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.2.0...9.3.0 +[9.2.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.1.1...9.2.0 +[9.1.1]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.1.0...9.1.1 +[9.1.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.0.0...9.1.0 +[9.0.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/8.2.0...9.0.0 +[8.2.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/8.1.0...8.2.0 +[8.1.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/8.0.1...8.1.0 +[8.0.1]: https://github.com/PHPCompatibility/PHPCompatibility/compare/8.0.0...8.0.1 +[8.0.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.1.5...8.0.0 +[7.1.5]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.1.4...7.1.5 +[7.1.4]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.1.3...7.1.4 +[7.1.3]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.1.2...7.1.3 +[7.1.2]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.1.1...7.1.2 +[7.1.1]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.1.0...7.1.1 +[7.1.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.8...7.1.0 +[7.0.8]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.7...7.0.8 +[7.0.7]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.6...7.0.7 +[7.0.6]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.5...7.0.6 +[7.0.5]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.4...7.0.5 +[7.0.4]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.3...7.0.4 +[7.0.3]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.2...7.0.3 +[7.0.2]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.1...7.0.2 +[7.0.1]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0...7.0.1 +[7.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/5.6...7.0 +[5.6]: https://github.com/PHPCompatibility/PHPCompatibility/compare/5.5...5.6 + +[9.3.5 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/34 +[9.3.4 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/33 +[9.3.3 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/32 +[9.3.2 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/31 +[9.3.1 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/30 +[9.3.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/29 +[9.2.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/28 +[9.1.1 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/27 +[9.1.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/25 +[9.0.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/24 +[8.2.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/22 +[8.1.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/21 +[8.0.1 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/20 +[8.0.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/19 +[7.1.5 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/17 +[7.1.4 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/15 +[7.1.3 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/14 +[7.1.2 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/13 +[7.1.1 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/12 +[7.1.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/11 +[7.0.8 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/10 +[7.0.7 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/9 +[7.0.6 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/8 +[7.0.5 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/7 +[7.0.4 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/6 +[7.0.3 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/5 +[7.0.2 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/4 +[7.0.1 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/3 +[7.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/2 +[5.6 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/1 +[5.5 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/16 + +[Arthur Edamov]: https://github.com/edamov +[Chris Abernethy]: https://github.com/cabernet-zerve +[Declan Kelly]: https://github.com/declank +[dgudgeon]: https://github.com/dgudgeon +[djaenecke]: https://github.com/djaenecke +[Dominic]: https://github.com/dol +[Eugene Maslovich]: https://github.com/ehpc +[Gary Jones]: https://github.com/GaryJones +[Jaap van Otterdijk]: https://github.com/jaapio +[Jason Stallings]: https://github.com/octalmage +[Jonathan Champ]: https://github.com/jrchamp +[Jonathan Van Belle]: https://github.com/Grummfy +[Juliette Reinders Folmer]: https://github.com/jrfnl +[Ken Guest]: https://github.com/kenguest +[Komarov Alexey]: https://github.com/erdraug +[Marin Crnkovic]: https://github.com/anorgan +[Mark Clements]: https://github.com/MarkMaldaba +[Michael Babker]: https://github.com/mbabker +[Nick Pack]: https://github.com/nickpack +[Nikhil]: https://github.com/Nikschavan +[Oliver Klee]: https://github.com/oliverklee +[Remko van Bezooijen]: https://github.com/emkookmer +[Rowan Collins]: https://github.com/IMSoP +[Ryan Neufeld]: https://github.com/ryanneufeld +[Sam Van der Borght]: https://github.com/samvdb +[Sergii Bondarenko]: https://github.com/BR0kEN- +[Tadas Juozapaitis]: https://github.com/kasp3r +[Tim Millwood]: https://github.com/timmillwood +[William Entriken]: https://github.com/fulldecent +[Yılmaz]: https://github.com/edigu +[Yoshiaki Yoshida]: https://github.com/kakakakakku diff --git a/vendor/phpcompatibility/php-compatibility/LICENSE b/vendor/phpcompatibility/php-compatibility/LICENSE new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/vendor/phpcompatibility/php-compatibility/PHPCSAliases.php b/vendor/phpcompatibility/php-compatibility/PHPCSAliases.php new file mode 100644 index 00000000..97591a3f --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCSAliases.php @@ -0,0 +1,73 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * PHPCS cross-version compatibility helper. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + * + * @since 8.0.0 + */ + +/* + * Alias a number of PHPCS 3.x classes to their PHPCS 2.x equivalents. + * + * This file is auto-loaded by PHPCS 3.x before any sniffs are loaded + * through the PHPCS 3.x `<autoload>` ruleset directive. + * + * {@internal The PHPCS file have been reorganized in PHPCS 3.x, quite + * a few "old" classes have been split and spread out over several "new" + * classes. In other words, this will only work for a limited number + * of classes.} + * + * {@internal The `class_exists` wrappers are needed to play nice with other + * external PHPCS standards creating cross-version compatibility in the same + * manner.} + */ +if (defined('PHPCOMPATIBILITY_PHPCS_ALIASES_SET') === false) { + if (interface_exists('\PHP_CodeSniffer_Sniff') === false) { + class_alias('PHP_CodeSniffer\Sniffs\Sniff', '\PHP_CodeSniffer_Sniff'); + } + if (class_exists('\PHP_CodeSniffer_File') === false) { + class_alias('PHP_CodeSniffer\Files\File', '\PHP_CodeSniffer_File'); + } + if (class_exists('\PHP_CodeSniffer_Tokens') === false) { + class_alias('PHP_CodeSniffer\Util\Tokens', '\PHP_CodeSniffer_Tokens'); + } + if (class_exists('\PHP_CodeSniffer_Exception') === false) { + class_alias('PHP_CodeSniffer\Exceptions\RuntimeException', '\PHP_CodeSniffer_Exception'); + } + if (class_exists('\PHP_CodeSniffer_Standards_AbstractScopeSniff') === false) { + class_alias('PHP_CodeSniffer\Sniffs\AbstractScopeSniff', '\PHP_CodeSniffer_Standards_AbstractScopeSniff'); + } + if (class_exists('\Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff') === false) { + class_alias('PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff', '\Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff'); + } + + define('PHPCOMPATIBILITY_PHPCS_ALIASES_SET', true); + + /* + * Register an autoloader. + * + * {@internal When `installed_paths` is set via the ruleset, this autoloader + * is needed to run the sniffs. + * Upstream issue: {@link https://github.com/squizlabs/PHP_CodeSniffer/issues/1591} } + * + * @since 8.0.0 + */ + spl_autoload_register(function ($class) { + // Only try & load our own classes. + if (stripos($class, 'PHPCompatibility') !== 0) { + return; + } + + $file = realpath(__DIR__) . DIRECTORY_SEPARATOR . strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php'; + + if (file_exists($file)) { + include_once $file; + } + }); +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/AbstractComplexVersionSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/AbstractComplexVersionSniff.php new file mode 100644 index 00000000..95245b6a --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/AbstractComplexVersionSniff.php @@ -0,0 +1,147 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility; + +use PHP_CodeSniffer_File as File; + +/** + * Abstract base class for sniffs based on complex arrays with PHP version information. + * + * @since 7.1.0 + */ +abstract class AbstractComplexVersionSniff extends Sniff implements ComplexVersionInterface +{ + + + /** + * Handle the retrieval of relevant information and - if necessary - throwing of an + * error/warning for an item. + * + * @since 7.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the relevant token in + * the stack. + * @param array $itemInfo Base information about the item. + * + * @return void + */ + public function handleFeature(File $phpcsFile, $stackPtr, array $itemInfo) + { + $itemArray = $this->getItemArray($itemInfo); + $errorInfo = $this->getErrorInfo($itemArray, $itemInfo); + + if ($this->shouldThrowError($errorInfo) === true) { + $this->addError($phpcsFile, $stackPtr, $itemInfo, $errorInfo); + } + } + + + /** + * Determine whether an error/warning should be thrown for an item based on collected information. + * + * @since 7.1.0 + * + * @param array $errorInfo Detail information about an item. + * + * @return bool + */ + abstract protected function shouldThrowError(array $errorInfo); + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array(); + } + + + /** + * Retrieve a subset of an item array containing only the array keys which + * contain PHP version information. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about an item. + * + * @return array Array with only the version information. + */ + protected function getVersionArray(array $itemArray) + { + return array_diff_key($itemArray, array_flip($this->getNonVersionArrayKeys())); + } + + + /** + * Get the item name to be used for the creation of the error code and in the error message. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Detail information about an item. + * + * @return string + */ + protected function getItemName(array $itemInfo, array $errorInfo) + { + return $itemInfo['name']; + } + + + /** + * Get the error message template for a specific sniff. + * + * @since 7.1.0 + * + * @return string + */ + abstract protected function getErrorMsgTemplate(); + + + /** + * Allow for concrete child classes to filter the error message before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param string $error The error message which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return string + */ + protected function filterErrorMsg($error, array $itemInfo, array $errorInfo) + { + return $error; + } + + + /** + * Allow for concrete child classes to filter the error data before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + return $data; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/AbstractFunctionCallParameterSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/AbstractFunctionCallParameterSniff.php new file mode 100644 index 00000000..6db8cd08 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/AbstractFunctionCallParameterSniff.php @@ -0,0 +1,193 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Abstract class to use as a base for examining the parameter values passed to function calls. + * + * @since 8.2.0 + */ +abstract class AbstractFunctionCallParameterSniff extends Sniff +{ + /** + * Is the sniff looking for a function call or a method call ? + * + * Note: the child class may need to do additional checks to make sure that + * the method called is of the right class/object. + * Checking that is outside of the scope of this abstract sniff. + * + * @since 8.2.0 + * + * @var bool False (default) if the sniff is looking for function calls. + * True if the sniff is looking for method calls. + */ + protected $isMethod = false; + + /** + * Functions the sniff is looking for. Should be defined in the child class. + * + * @since 8.2.0 + * + * @var array The only requirement for this array is that the top level + * array keys are the names of the functions you're looking for. + * Other than that, the array can have arbitrary content + * depending on your needs. + */ + protected $targetFunctions = array(); + + /** + * List of tokens which when they preceed the $stackPtr indicate that this + * is not a function call. + * + * @since 8.2.0 + * + * @var array + */ + private $ignoreTokens = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_NEW => true, + \T_CONST => true, + \T_USE => true, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.2.0 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of function names. + $this->targetFunctions = $this->arrayKeysToLowercase($this->targetFunctions); + + return array(\T_STRING); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->bowOutEarly() === true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $function = $tokens[$stackPtr]['content']; + $functionLc = strtolower($function); + + if (isset($this->targetFunctions[$functionLc]) === false) { + return; + } + + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + if ($this->isMethod === true) { + if ($tokens[$prevNonEmpty]['code'] !== \T_DOUBLE_COLON + && $tokens[$prevNonEmpty]['code'] !== \T_OBJECT_OPERATOR + ) { + // Not a call to a PHP method. + return; + } + } else { + if (isset($this->ignoreTokens[$tokens[$prevNonEmpty]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + if ($tokens[$prevNonEmpty]['code'] === \T_NS_SEPARATOR + && $tokens[$prevNonEmpty - 1]['code'] === \T_STRING + ) { + // Namespaced function. + return; + } + } + + $parameters = $this->getFunctionCallParameters($phpcsFile, $stackPtr); + + if (empty($parameters)) { + return $this->processNoParameters($phpcsFile, $stackPtr, $function); + } else { + return $this->processParameters($phpcsFile, $stackPtr, $function, $parameters); + } + } + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 8.2.0 + * + * If the check done in a child class is not specific to one PHP version, + * this function should return `false`. + * + * @return bool + */ + abstract protected function bowOutEarly(); + + + /** + * Process the parameters of a matched function. + * + * This method has to be made concrete in child classes. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + abstract public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters); + + + /** + * Process the function if no parameters were found. + * + * Defaults to doing nothing. Can be overloaded in child classes to handle functions + * were parameters are expected, but none found. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processNoParameters(File $phpcsFile, $stackPtr, $functionName) + { + return; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/AbstractNewFeatureSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/AbstractNewFeatureSniff.php new file mode 100644 index 00000000..25406fda --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/AbstractNewFeatureSniff.php @@ -0,0 +1,115 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility; + +use PHP_CodeSniffer_File as File; + +/** + * Base class for new feature sniffs. + * + * @since 7.1.0 + */ +abstract class AbstractNewFeatureSniff extends AbstractComplexVersionSniff +{ + + + /** + * Determine whether an error/warning should be thrown for an item based on collected information. + * + * @since 7.1.0 + * + * @param array $errorInfo Detail information about an item. + * + * @return bool + */ + protected function shouldThrowError(array $errorInfo) + { + return ($errorInfo['not_in_version'] !== ''); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = array( + 'not_in_version' => '', + 'error' => true, + ); + + $versionArray = $this->getVersionArray($itemArray); + + if (empty($versionArray) === false) { + foreach ($versionArray as $version => $present) { + if ($errorInfo['not_in_version'] === '' && $present === false + && $this->supportsBelow($version) === true + ) { + $errorInfo['not_in_version'] = $version; + } + } + } + + return $errorInfo; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return '%s is not present in PHP version %s or earlier'; + } + + + /** + * Generates the error or warning for this item. + * + * @since 7.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the relevant token in + * the stack. + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Array with detail (version) information + * relevant to the item. + * + * @return void + */ + public function addError(File $phpcsFile, $stackPtr, array $itemInfo, array $errorInfo) + { + $itemName = $this->getItemName($itemInfo, $errorInfo); + $error = $this->getErrorMsgTemplate(); + + $errorCode = $this->stringToErrorCode($itemName) . 'Found'; + $data = array( + $itemName, + $errorInfo['not_in_version'], + ); + + $error = $this->filterErrorMsg($error, $itemInfo, $errorInfo); + $data = $this->filterErrorData($data, $itemInfo, $errorInfo); + + $this->addMessage($phpcsFile, $error, $stackPtr, $errorInfo['error'], $errorCode, $data); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/AbstractRemovedFeatureSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/AbstractRemovedFeatureSniff.php new file mode 100644 index 00000000..94103922 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/AbstractRemovedFeatureSniff.php @@ -0,0 +1,156 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility; + +use PHP_CodeSniffer_File as File; + +/** + * Base class for removed feature sniffs. + * + * @since 7.1.0 + */ +abstract class AbstractRemovedFeatureSniff extends AbstractComplexVersionSniff +{ + + + /** + * Determine whether an error/warning should be thrown for an item based on collected information. + * + * @since 7.1.0 + * + * @param array $errorInfo Detail information about an item. + * + * @return bool + */ + protected function shouldThrowError(array $errorInfo) + { + return ($errorInfo['deprecated'] !== '' || $errorInfo['removed'] !== ''); + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * By default, removed feature version arrays, contain an additional 'alternative' array key. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('alternative'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = array( + 'deprecated' => '', + 'removed' => '', + 'alternative' => '', + 'error' => false, + ); + + $versionArray = $this->getVersionArray($itemArray); + + if (empty($versionArray) === false) { + foreach ($versionArray as $version => $removed) { + if ($this->supportsAbove($version) === true) { + if ($removed === true && $errorInfo['removed'] === '') { + $errorInfo['removed'] = $version; + $errorInfo['error'] = true; + } elseif ($errorInfo['deprecated'] === '') { + $errorInfo['deprecated'] = $version; + } + } + } + } + + if (isset($itemArray['alternative']) === true) { + $errorInfo['alternative'] = $itemArray['alternative']; + } + + return $errorInfo; + } + + + /** + * Get the error message template for suggesting an alternative for a specific sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getAlternativeOptionTemplate() + { + return '; Use %s instead'; + } + + + /** + * Generates the error or warning for this item. + * + * @since 7.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the relevant token in + * the stack. + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Array with detail (version) information + * relevant to the item. + * + * @return void + */ + public function addError(File $phpcsFile, $stackPtr, array $itemInfo, array $errorInfo) + { + $itemName = $this->getItemName($itemInfo, $errorInfo); + $error = $this->getErrorMsgTemplate(); + + $errorCode = $this->stringToErrorCode($itemName); + $data = array($itemName); + + if ($errorInfo['deprecated'] !== '') { + $error .= 'deprecated since PHP %s and '; + $errorCode .= 'Deprecated'; + $data[] = $errorInfo['deprecated']; + } + + if ($errorInfo['removed'] !== '') { + $error .= 'removed since PHP %s and '; + $errorCode .= 'Removed'; + $data[] = $errorInfo['removed']; + } + + // Remove the last 'and' from the message. + $error = substr($error, 0, (\strlen($error) - 5)); + + if ($errorInfo['alternative'] !== '') { + $error .= $this->getAlternativeOptionTemplate(); + $data[] = $errorInfo['alternative']; + } + + $error = $this->filterErrorMsg($error, $itemInfo, $errorInfo); + $data = $this->filterErrorData($data, $itemInfo, $errorInfo); + + $this->addMessage($phpcsFile, $error, $stackPtr, $errorInfo['error'], $errorCode, $data); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/ComplexVersionInterface.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/ComplexVersionInterface.php new file mode 100644 index 00000000..f5f63bbf --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/ComplexVersionInterface.php @@ -0,0 +1,84 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility; + +use PHP_CodeSniffer_File as File; + +/** + * Complex Version Interface. + * + * Interface to be implemented by sniffs using a multi-dimensional array of + * PHP features (functions, classes etc) being sniffed for with version + * information in sub-arrays. + * + * @since 7.1.0 + */ +interface ComplexVersionInterface +{ + + + /** + * Handle the retrieval of relevant information and - if necessary - throwing of an + * error/warning for an item. + * + * @since 7.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the relevant token in + * the stack. + * @param array $itemInfo Base information about the item. + * + * @return void + */ + public function handleFeature(File $phpcsFile, $stackPtr, array $itemInfo); + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo); + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo); + + + /** + * Generates the error or warning for this item. + * + * @since 7.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the relevant token in + * the stack. + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Array with detail (version) information + * relevant to the item. + * + * @return void + */ + public function addError(File $phpcsFile, $stackPtr, array $itemInfo, array $errorInfo); +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/PHPCSHelper.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/PHPCSHelper.php new file mode 100644 index 00000000..4204beaf --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/PHPCSHelper.php @@ -0,0 +1,678 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility; + +use PHP_CodeSniffer_Exception as PHPCS_Exception; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * PHPCS cross-version compatibility helper class. + * + * A number of PHPCS classes were split up into several classes in PHPCS 3.x + * Those classes cannot be aliased as they don't represent the same object. + * This class provides helper methods for functions which were contained in + * one of these classes and which are used within the PHPCompatibility library. + * + * Additionally, this class contains some duplicates of PHPCS native methods. + * These methods have received bug fixes or improved functionality between the + * lowest supported PHPCS version and the latest PHPCS stable version and + * to provide the same results cross-version, PHPCompatibility needs to use + * the up-to-date versions of these methods. + * + * @since 8.0.0 + * @since 8.2.0 The duplicate PHPCS methods have been moved from the `Sniff` + * base class to this class. + */ +class PHPCSHelper +{ + + /** + * Get the PHPCS version number. + * + * @since 8.0.0 + * + * @return string + */ + public static function getVersion() + { + if (\defined('\PHP_CodeSniffer\Config::VERSION')) { + // PHPCS 3.x. + return \PHP_CodeSniffer\Config::VERSION; + } else { + // PHPCS 2.x. + return \PHP_CodeSniffer::VERSION; + } + } + + + /** + * Pass config data to PHPCS. + * + * PHPCS cross-version compatibility helper. + * + * @since 8.0.0 + * + * @param string $key The name of the config value. + * @param string|null $value The value to set. If null, the config entry + * is deleted, reverting it to the default value. + * @param boolean $temp Set this config data temporarily for this script run. + * This will not write the config data to the config file. + * + * @return void + */ + public static function setConfigData($key, $value, $temp = false) + { + if (method_exists('\PHP_CodeSniffer\Config', 'setConfigData')) { + // PHPCS 3.x. + \PHP_CodeSniffer\Config::setConfigData($key, $value, $temp); + } else { + // PHPCS 2.x. + \PHP_CodeSniffer::setConfigData($key, $value, $temp); + } + } + + + /** + * Get the value of a single PHPCS config key. + * + * @since 8.0.0 + * + * @param string $key The name of the config value. + * + * @return string|null + */ + public static function getConfigData($key) + { + if (method_exists('\PHP_CodeSniffer\Config', 'getConfigData')) { + // PHPCS 3.x. + return \PHP_CodeSniffer\Config::getConfigData($key); + } else { + // PHPCS 2.x. + return \PHP_CodeSniffer::getConfigData($key); + } + } + + + /** + * Get the value of a single PHPCS config key. + * + * This config key can be set in the `CodeSniffer.conf` file, on the + * command-line or in a ruleset. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param string $key The name of the config value. + * + * @return string|null + */ + public static function getCommandLineData(File $phpcsFile, $key) + { + if (class_exists('\PHP_CodeSniffer\Config')) { + // PHPCS 3.x. + $config = $phpcsFile->config; + if (isset($config->{$key})) { + return $config->{$key}; + } + } else { + // PHPCS 2.x. + $config = $phpcsFile->phpcs->cli->getCommandLineValues(); + if (isset($config[$key])) { + return $config[$key]; + } + } + + return null; + } + + + /** + * Returns the position of the first non-whitespace token in a statement. + * + * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` + * class and introduced in PHPCS 2.1.0 and improved in PHPCS 2.7.1. + * + * Once the minimum supported PHPCS version for this standard goes beyond + * that, this method can be removed and calls to it replaced with + * `$phpcsFile->findStartOfStatement($start, $ignore)` calls. + * + * Last synced with PHPCS version: PHPCS 3.3.2 at commit 6ad28354c04b364c3c71a34e4a18b629cc3b231e} + * + * @since 9.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $start The position to start searching from in the token stack. + * @param int|array $ignore Token types that should not be considered stop points. + * + * @return int + */ + public static function findStartOfStatement(File $phpcsFile, $start, $ignore = null) + { + if (version_compare(self::getVersion(), '2.7.1', '>=') === true) { + return $phpcsFile->findStartOfStatement($start, $ignore); + } + + $tokens = $phpcsFile->getTokens(); + $endTokens = Tokens::$blockOpeners; + + $endTokens[\T_COLON] = true; + $endTokens[\T_COMMA] = true; + $endTokens[\T_DOUBLE_ARROW] = true; + $endTokens[\T_SEMICOLON] = true; + $endTokens[\T_OPEN_TAG] = true; + $endTokens[\T_CLOSE_TAG] = true; + $endTokens[\T_OPEN_SHORT_ARRAY] = true; + + if ($ignore !== null) { + $ignore = (array) $ignore; + foreach ($ignore as $code) { + if (isset($endTokens[$code]) === true) { + unset($endTokens[$code]); + } + } + } + + $lastNotEmpty = $start; + + for ($i = $start; $i >= 0; $i--) { + if (isset($endTokens[$tokens[$i]['code']]) === true) { + // Found the end of the previous statement. + return $lastNotEmpty; + } + + if (isset($tokens[$i]['scope_opener']) === true + && $i === $tokens[$i]['scope_closer'] + ) { + // Found the end of the previous scope block. + return $lastNotEmpty; + } + + // Skip nested statements. + if (isset($tokens[$i]['bracket_opener']) === true + && $i === $tokens[$i]['bracket_closer'] + ) { + $i = $tokens[$i]['bracket_opener']; + } elseif (isset($tokens[$i]['parenthesis_opener']) === true + && $i === $tokens[$i]['parenthesis_closer'] + ) { + $i = $tokens[$i]['parenthesis_opener']; + } + + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) { + $lastNotEmpty = $i; + } + }//end for + + return 0; + } + + + /** + * Returns the position of the last non-whitespace token in a statement. + * + * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` + * class and introduced in PHPCS 2.1.0 and improved in PHPCS 2.7.1 and 3.3.0. + * + * Once the minimum supported PHPCS version for this standard goes beyond + * that, this method can be removed and calls to it replaced with + * `$phpcsFile->findEndOfStatement($start, $ignore)` calls. + * + * Last synced with PHPCS version: PHPCS 3.3.0-alpha at commit f5d899dcb5c534a1c3cca34668624517856ba823} + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $start The position to start searching from in the token stack. + * @param int|array $ignore Token types that should not be considered stop points. + * + * @return int + */ + public static function findEndOfStatement(File $phpcsFile, $start, $ignore = null) + { + if (version_compare(self::getVersion(), '3.3.0', '>=') === true) { + return $phpcsFile->findEndOfStatement($start, $ignore); + } + + $tokens = $phpcsFile->getTokens(); + $endTokens = array( + \T_COLON => true, + \T_COMMA => true, + \T_DOUBLE_ARROW => true, + \T_SEMICOLON => true, + \T_CLOSE_PARENTHESIS => true, + \T_CLOSE_SQUARE_BRACKET => true, + \T_CLOSE_CURLY_BRACKET => true, + \T_CLOSE_SHORT_ARRAY => true, + \T_OPEN_TAG => true, + \T_CLOSE_TAG => true, + ); + + if ($ignore !== null) { + $ignore = (array) $ignore; + foreach ($ignore as $code) { + if (isset($endTokens[$code]) === true) { + unset($endTokens[$code]); + } + } + } + + $lastNotEmpty = $start; + + for ($i = $start; $i < $phpcsFile->numTokens; $i++) { + if ($i !== $start && isset($endTokens[$tokens[$i]['code']]) === true) { + // Found the end of the statement. + if ($tokens[$i]['code'] === \T_CLOSE_PARENTHESIS + || $tokens[$i]['code'] === \T_CLOSE_SQUARE_BRACKET + || $tokens[$i]['code'] === \T_CLOSE_CURLY_BRACKET + || $tokens[$i]['code'] === \T_CLOSE_SHORT_ARRAY + || $tokens[$i]['code'] === \T_OPEN_TAG + || $tokens[$i]['code'] === \T_CLOSE_TAG + ) { + return $lastNotEmpty; + } + + return $i; + } + + // Skip nested statements. + if (isset($tokens[$i]['scope_closer']) === true + && ($i === $tokens[$i]['scope_opener'] + || $i === $tokens[$i]['scope_condition']) + ) { + if ($i === $start && isset(Tokens::$scopeOpeners[$tokens[$i]['code']]) === true) { + return $tokens[$i]['scope_closer']; + } + + $i = $tokens[$i]['scope_closer']; + } elseif (isset($tokens[$i]['bracket_closer']) === true + && $i === $tokens[$i]['bracket_opener'] + ) { + $i = $tokens[$i]['bracket_closer']; + } elseif (isset($tokens[$i]['parenthesis_closer']) === true + && $i === $tokens[$i]['parenthesis_opener'] + ) { + $i = $tokens[$i]['parenthesis_closer']; + } + + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) { + $lastNotEmpty = $i; + } + }//end for + + return ($phpcsFile->numTokens - 1); + } + + + /** + * Returns the name of the class that the specified class extends + * (works for classes, anonymous classes and interfaces). + * + * Returns FALSE on error or if there is no extended class name. + * + * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` + * class, but with some improvements which have been introduced in + * PHPCS 2.8.0. + * {@link https://github.com/squizlabs/PHP_CodeSniffer/commit/0011d448119d4c568e3ac1f825ae78815bf2cc34}. + * + * Once the minimum supported PHPCS version for this standard goes beyond + * that, this method can be removed and calls to it replaced with + * `$phpcsFile->findExtendedClassName($stackPtr)` calls. + * + * Last synced with PHPCS version: PHPCS 3.1.0-alpha at commit a9efcc9b0703f3f9f4a900623d4e97128a6aafc6} + * + * @since 7.1.4 + * @since 8.2.0 Moved from the `Sniff` class to this class. + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $stackPtr The position of the class token in the stack. + * + * @return string|false + */ + public static function findExtendedClassName(File $phpcsFile, $stackPtr) + { + if (version_compare(self::getVersion(), '3.1.0', '>=') === true) { + return $phpcsFile->findExtendedClassName($stackPtr); + } + + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + if ($tokens[$stackPtr]['code'] !== \T_CLASS + && $tokens[$stackPtr]['type'] !== 'T_ANON_CLASS' + && $tokens[$stackPtr]['type'] !== 'T_INTERFACE' + ) { + return false; + } + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return false; + } + + $classCloserIndex = $tokens[$stackPtr]['scope_closer']; + $extendsIndex = $phpcsFile->findNext(\T_EXTENDS, $stackPtr, $classCloserIndex); + if ($extendsIndex === false) { + return false; + } + + $find = array( + \T_NS_SEPARATOR, + \T_STRING, + \T_WHITESPACE, + ); + + $end = $phpcsFile->findNext($find, ($extendsIndex + 1), $classCloserIndex, true); + $name = $phpcsFile->getTokensAsString(($extendsIndex + 1), ($end - $extendsIndex - 1)); + $name = trim($name); + + if ($name === '') { + return false; + } + + return $name; + } + + + /** + * Returns the name(s) of the interface(s) that the specified class implements. + * + * Returns FALSE on error or if there are no implemented interface names. + * + * {@internal Duplicate of same method as introduced in PHPCS 2.7. + * This method also includes an improvement we use which was only introduced + * in PHPCS 2.8.0, so only defer to upstream for higher versions. + * Once the minimum supported PHPCS version for this sniff library goes beyond + * that, this method can be removed and calls to it replaced with + * `$phpcsFile->findImplementedInterfaceNames($stackPtr)` calls.} + * + * @since 7.0.3 + * @since 8.2.0 Moved from the `Sniff` class to this class. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the class token. + * + * @return array|false + */ + public static function findImplementedInterfaceNames(File $phpcsFile, $stackPtr) + { + if (version_compare(self::getVersion(), '2.7.1', '>') === true) { + return $phpcsFile->findImplementedInterfaceNames($stackPtr); + } + + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + if ($tokens[$stackPtr]['code'] !== \T_CLASS + && $tokens[$stackPtr]['type'] !== 'T_ANON_CLASS' + ) { + return false; + } + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return false; + } + + $classOpenerIndex = $tokens[$stackPtr]['scope_opener']; + $implementsIndex = $phpcsFile->findNext(\T_IMPLEMENTS, $stackPtr, $classOpenerIndex); + if ($implementsIndex === false) { + return false; + } + + $find = array( + \T_NS_SEPARATOR, + \T_STRING, + \T_WHITESPACE, + \T_COMMA, + ); + + $end = $phpcsFile->findNext($find, ($implementsIndex + 1), ($classOpenerIndex + 1), true); + $name = $phpcsFile->getTokensAsString(($implementsIndex + 1), ($end - $implementsIndex - 1)); + $name = trim($name); + + if ($name === '') { + return false; + } else { + $names = explode(',', $name); + $names = array_map('trim', $names); + return $names; + } + } + + + /** + * Returns the method parameters for the specified function token. + * + * Each parameter is in the following format: + * + * <code> + * 0 => array( + * 'name' => '$var', // The variable name. + * 'token' => integer, // The stack pointer to the variable name. + * 'content' => string, // The full content of the variable definition. + * 'pass_by_reference' => boolean, // Is the variable passed by reference? + * 'variable_length' => boolean, // Is the param of variable length through use of `...` ? + * 'type_hint' => string, // The type hint for the variable. + * 'type_hint_token' => integer, // The stack pointer to the type hint + * // or false if there is no type hint. + * 'nullable_type' => boolean, // Is the variable using a nullable type? + * ) + * </code> + * + * Parameters with default values have an additional array index of + * 'default' with the value of the default as a string. + * + * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` + * class. + * + * Last synced with PHPCS version: PHPCS 3.3.0-alpha at commit 53a28408d345044c0360c2c1b4a2aaebf4a3b8c9} + * + * @since 7.0.3 + * @since 8.2.0 Moved from the `Sniff` class to this class. + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $stackPtr The position in the stack of the + * function token to acquire the + * parameters for. + * + * @return array|false + * @throws \PHP_CodeSniffer_Exception If the specified $stackPtr is not of + * type T_FUNCTION or T_CLOSURE. + */ + public static function getMethodParameters(File $phpcsFile, $stackPtr) + { + if (version_compare(self::getVersion(), '3.3.0', '>=') === true) { + return $phpcsFile->getMethodParameters($stackPtr); + } + + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + if ($tokens[$stackPtr]['code'] !== \T_FUNCTION + && $tokens[$stackPtr]['code'] !== \T_CLOSURE + ) { + throw new PHPCS_Exception('$stackPtr must be of type T_FUNCTION or T_CLOSURE'); + } + + $opener = $tokens[$stackPtr]['parenthesis_opener']; + $closer = $tokens[$stackPtr]['parenthesis_closer']; + + $vars = array(); + $currVar = null; + $paramStart = ($opener + 1); + $defaultStart = null; + $paramCount = 0; + $passByReference = false; + $variableLength = false; + $typeHint = ''; + $typeHintToken = false; + $nullableType = false; + + for ($i = $paramStart; $i <= $closer; $i++) { + // Check to see if this token has a parenthesis or bracket opener. If it does + // it's likely to be an array which might have arguments in it. This + // could cause problems in our parsing below, so lets just skip to the + // end of it. + if (isset($tokens[$i]['parenthesis_opener']) === true) { + // Don't do this if it's the close parenthesis for the method. + if ($i !== $tokens[$i]['parenthesis_closer']) { + $i = ($tokens[$i]['parenthesis_closer'] + 1); + } + } + + if (isset($tokens[$i]['bracket_opener']) === true) { + // Don't do this if it's the close parenthesis for the method. + if ($i !== $tokens[$i]['bracket_closer']) { + $i = ($tokens[$i]['bracket_closer'] + 1); + } + } + + switch ($tokens[$i]['type']) { + case 'T_BITWISE_AND': + if ($defaultStart === null) { + $passByReference = true; + } + break; + case 'T_VARIABLE': + $currVar = $i; + break; + case 'T_ELLIPSIS': + $variableLength = true; + break; + case 'T_ARRAY_HINT': // Pre-PHPCS 3.3.0. + case 'T_CALLABLE': + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $tokens[$i]['content']; + break; + case 'T_SELF': + case 'T_PARENT': + case 'T_STATIC': + // Self and parent are valid, static invalid, but was probably intended as type hint. + if (isset($defaultStart) === false) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $tokens[$i]['content']; + } + break; + case 'T_STRING': + // This is a string, so it may be a type hint, but it could + // also be a constant used as a default value. + $prevComma = false; + for ($t = $i; $t >= $opener; $t--) { + if ($tokens[$t]['code'] === \T_COMMA) { + $prevComma = $t; + break; + } + } + + if ($prevComma !== false) { + $nextEquals = false; + for ($t = $prevComma; $t < $i; $t++) { + if ($tokens[$t]['code'] === \T_EQUAL) { + $nextEquals = $t; + break; + } + } + + if ($nextEquals !== false) { + break; + } + } + + if ($defaultStart === null) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $tokens[$i]['content']; + } + break; + case 'T_NS_SEPARATOR': + // Part of a type hint or default value. + if ($defaultStart === null) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $tokens[$i]['content']; + } + break; + case 'T_NULLABLE': + case 'T_INLINE_THEN': // Pre-PHPCS 2.8.0. + if ($defaultStart === null) { + $nullableType = true; + $typeHint .= $tokens[$i]['content']; + } + break; + case 'T_CLOSE_PARENTHESIS': + case 'T_COMMA': + // If it's null, then there must be no parameters for this + // method. + if ($currVar === null) { + break; + } + + $vars[$paramCount] = array(); + $vars[$paramCount]['token'] = $currVar; + $vars[$paramCount]['name'] = $tokens[$currVar]['content']; + $vars[$paramCount]['content'] = trim($phpcsFile->getTokensAsString($paramStart, ($i - $paramStart))); + + if ($defaultStart !== null) { + $vars[$paramCount]['default'] = trim( + $phpcsFile->getTokensAsString( + $defaultStart, + ($i - $defaultStart) + ) + ); + } + + $vars[$paramCount]['pass_by_reference'] = $passByReference; + $vars[$paramCount]['variable_length'] = $variableLength; + $vars[$paramCount]['type_hint'] = $typeHint; + $vars[$paramCount]['type_hint_token'] = $typeHintToken; + $vars[$paramCount]['nullable_type'] = $nullableType; + + // Reset the vars, as we are about to process the next parameter. + $defaultStart = null; + $paramStart = ($i + 1); + $passByReference = false; + $variableLength = false; + $typeHint = ''; + $typeHintToken = false; + $nullableType = false; + + $paramCount++; + break; + case 'T_EQUAL': + $defaultStart = ($i + 1); + break; + }//end switch + }//end for + + return $vars; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniff.php new file mode 100644 index 00000000..38fb7092 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniff.php @@ -0,0 +1,2267 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility; + +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_Exception as PHPCS_Exception; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Sniff as PHPCS_Sniff; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Base class from which all PHPCompatibility sniffs extend. + * + * @since 5.6 + */ +abstract class Sniff implements PHPCS_Sniff +{ + + /** + * Regex to match variables in a double quoted string. + * + * This matches plain variables, but also more complex variables, such + * as $obj->prop, self::prop and $var[]. + * + * @since 7.1.2 + * + * @var string + */ + const REGEX_COMPLEX_VARS = '`(?:(\{)?(?<!\\\\)\$)?(\{)?(?<!\\\\)\$(\{)?(?P<varname>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)(?:->\$?(?P>varname)|\[[^\]]+\]|::\$?(?P>varname)|\([^\)]*\))*(?(3)\}|)(?(2)\}|)(?(1)\}|)`'; + + /** + * List of superglobals as an array of strings. + * + * Used by the ForbiddenParameterShadowSuperGlobals and ForbiddenClosureUseVariableNames sniffs. + * + * @since 7.0.0 + * @since 7.1.4 Moved from the `ForbiddenParameterShadowSuperGlobals` sniff to the base `Sniff` class. + * + * @var array + */ + protected $superglobals = array( + '$GLOBALS' => true, + '$_SERVER' => true, + '$_GET' => true, + '$_POST' => true, + '$_FILES' => true, + '$_COOKIE' => true, + '$_SESSION' => true, + '$_REQUEST' => true, + '$_ENV' => true, + ); + + /** + * List of functions using hash algorithm as parameter (always the first parameter). + * + * Used by the new/removed hash algorithm sniffs. + * Key is the function name, value is the 1-based parameter position in the function call. + * + * @since 5.5 + * @since 7.0.7 Moved from the `RemovedHashAlgorithms` sniff to the base `Sniff` class. + * + * @var array + */ + protected $hashAlgoFunctions = array( + 'hash_file' => 1, + 'hash_hmac_file' => 1, + 'hash_hmac' => 1, + 'hash_init' => 1, + 'hash_pbkdf2' => 1, + 'hash' => 1, + ); + + + /** + * List of functions which take an ini directive as parameter (always the first parameter). + * + * Used by the new/removed ini directives sniffs. + * Key is the function name, value is the 1-based parameter position in the function call. + * + * @since 7.1.0 + * + * @var array + */ + protected $iniFunctions = array( + 'ini_get' => 1, + 'ini_set' => 1, + ); + + + /** + * Get the testVersion configuration variable. + * + * The testVersion configuration variable may be in any of the following formats: + * 1) Omitted/empty, in which case no version is specified. This effectively + * disables all the checks for new PHP features provided by this standard. + * 2) A single PHP version number, e.g. "5.4" in which case the standard checks that + * the code will run on that version of PHP (no deprecated features or newer + * features being used). + * 3) A range, e.g. "5.0-5.5", in which case the standard checks the code will run + * on all PHP versions in that range, and that it doesn't use any features that + * were deprecated by the final version in the list, or which were not available + * for the first version in the list. + * We accept ranges where one of the components is missing, e.g. "-5.6" means + * all versions up to PHP 5.6, and "7.0-" means all versions above PHP 7.0. + * PHP version numbers should always be in Major.Minor format. Both "5", "5.3.2" + * would be treated as invalid, and ignored. + * + * @since 7.0.0 + * @since 7.1.3 Now allows for partial ranges such as `5.2-`. + * + * @return array $arrTestVersions will hold an array containing min/max version + * of PHP that we are checking against (see above). If only a + * single version number is specified, then this is used as + * both the min and max. + * + * @throws \PHP_CodeSniffer_Exception If testVersion is invalid. + */ + private function getTestVersion() + { + static $arrTestVersions = array(); + + $default = array(null, null); + $testVersion = trim(PHPCSHelper::getConfigData('testVersion')); + + if (empty($testVersion) === false && isset($arrTestVersions[$testVersion]) === false) { + + $arrTestVersions[$testVersion] = $default; + + if (preg_match('`^\d+\.\d+$`', $testVersion)) { + $arrTestVersions[$testVersion] = array($testVersion, $testVersion); + return $arrTestVersions[$testVersion]; + } + + if (preg_match('`^(\d+\.\d+)?\s*-\s*(\d+\.\d+)?$`', $testVersion, $matches)) { + if (empty($matches[1]) === false || empty($matches[2]) === false) { + // If no lower-limit is set, we set the min version to 4.0. + // Whilst development focuses on PHP 5 and above, we also accept + // sniffs for PHP 4, so we include that as the minimum. + // (It makes no sense to support PHP 3 as this was effectively a + // different language). + $min = empty($matches[1]) ? '4.0' : $matches[1]; + + // If no upper-limit is set, we set the max version to 99.9. + $max = empty($matches[2]) ? '99.9' : $matches[2]; + + if (version_compare($min, $max, '>')) { + trigger_error( + "Invalid range in testVersion setting: '" . $testVersion . "'", + \E_USER_WARNING + ); + return $default; + } else { + $arrTestVersions[$testVersion] = array($min, $max); + return $arrTestVersions[$testVersion]; + } + } + } + + trigger_error( + "Invalid testVersion setting: '" . $testVersion . "'", + \E_USER_WARNING + ); + return $default; + } + + if (isset($arrTestVersions[$testVersion])) { + return $arrTestVersions[$testVersion]; + } + + return $default; + } + + + /** + * Check whether a specific PHP version is equal to or higher than the maximum + * supported PHP version as provided by the user in `testVersion`. + * + * Should be used when sniffing for *old* PHP features (deprecated/removed). + * + * @since 5.6 + * + * @param string $phpVersion A PHP version number in 'major.minor' format. + * + * @return bool True if testVersion has not been provided or if the PHP version + * is equal to or higher than the highest supported PHP version + * in testVersion. False otherwise. + */ + public function supportsAbove($phpVersion) + { + $testVersion = $this->getTestVersion(); + $testVersion = $testVersion[1]; + + if (\is_null($testVersion) + || version_compare($testVersion, $phpVersion) >= 0 + ) { + return true; + } else { + return false; + } + } + + + /** + * Check whether a specific PHP version is equal to or lower than the minimum + * supported PHP version as provided by the user in `testVersion`. + * + * Should be used when sniffing for *new* PHP features. + * + * @since 5.6 + * + * @param string $phpVersion A PHP version number in 'major.minor' format. + * + * @return bool True if the PHP version is equal to or lower than the lowest + * supported PHP version in testVersion. + * False otherwise or if no testVersion is provided. + */ + public function supportsBelow($phpVersion) + { + $testVersion = $this->getTestVersion(); + $testVersion = $testVersion[0]; + + if (\is_null($testVersion) === false + && version_compare($testVersion, $phpVersion) <= 0 + ) { + return true; + } else { + return false; + } + } + + + /** + * Add a PHPCS message to the output stack as either a warning or an error. + * + * @since 7.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file the message applies to. + * @param string $message The message. + * @param int $stackPtr The position of the token + * the message relates to. + * @param bool $isError Whether to report the message as an + * 'error' or 'warning'. + * Defaults to true (error). + * @param string $code The error code for the message. + * Defaults to 'Found'. + * @param array $data Optional input for the data replacements. + * + * @return void + */ + public function addMessage(File $phpcsFile, $message, $stackPtr, $isError, $code = 'Found', $data = array()) + { + if ($isError === true) { + $phpcsFile->addError($message, $stackPtr, $code, $data); + } else { + $phpcsFile->addWarning($message, $stackPtr, $code, $data); + } + } + + + /** + * Convert an arbitrary string to an alphanumeric string with underscores. + * + * Pre-empt issues with arbitrary strings being used as error codes in XML and PHP. + * + * @since 7.1.0 + * + * @param string $baseString Arbitrary string. + * + * @return string + */ + public function stringToErrorCode($baseString) + { + return preg_replace('`[^a-z0-9_]`i', '_', strtolower($baseString)); + } + + + /** + * Strip quotes surrounding an arbitrary string. + * + * Intended for use with the contents of a T_CONSTANT_ENCAPSED_STRING / T_DOUBLE_QUOTED_STRING. + * + * @since 7.0.6 + * + * @param string $string The raw string. + * + * @return string String without quotes around it. + */ + public function stripQuotes($string) + { + return preg_replace('`^([\'"])(.*)\1$`Ds', '$2', $string); + } + + + /** + * Strip variables from an arbitrary double quoted string. + * + * Intended for use with the contents of a T_DOUBLE_QUOTED_STRING. + * + * @since 7.1.2 + * + * @param string $string The raw string. + * + * @return string String without variables in it. + */ + public function stripVariables($string) + { + if (strpos($string, '$') === false) { + return $string; + } + + return preg_replace(self::REGEX_COMPLEX_VARS, '', $string); + } + + + /** + * Make all top level array keys in an array lowercase. + * + * @since 7.1.0 + * + * @param array $array Initial array. + * + * @return array Same array, but with all lowercase top level keys. + */ + public function arrayKeysToLowercase($array) + { + return array_change_key_case($array, \CASE_LOWER); + } + + + /** + * Checks if a function call has parameters. + * + * Expects to be passed the T_STRING or T_VARIABLE stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Extra feature: If passed an T_ARRAY or T_OPEN_SHORT_ARRAY stack pointer, it + * will detect whether the array has values or is empty. + * + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/120 + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/152 + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the function call token. + * + * @return bool + */ + public function doesFunctionCallHaveParameters(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + // Is this one of the tokens this function handles ? + if (\in_array($tokens[$stackPtr]['code'], array(\T_STRING, \T_ARRAY, \T_OPEN_SHORT_ARRAY, \T_VARIABLE), true) === false) { + return false; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + + // Deal with short array syntax. + if ($tokens[$stackPtr]['code'] === \T_OPEN_SHORT_ARRAY) { + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + return false; + } + + if ($nextNonEmpty === $tokens[$stackPtr]['bracket_closer']) { + // No parameters. + return false; + } else { + return true; + } + } + + // Deal with function calls & long arrays. + // Next non-empty token should be the open parenthesis. + if ($nextNonEmpty === false && $tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS) { + return false; + } + + if (isset($tokens[$nextNonEmpty]['parenthesis_closer']) === false) { + return false; + } + + $closeParenthesis = $tokens[$nextNonEmpty]['parenthesis_closer']; + $nextNextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $nextNonEmpty + 1, $closeParenthesis + 1, true); + + if ($nextNextNonEmpty === $closeParenthesis) { + // No parameters. + return false; + } + + return true; + } + + + /** + * Count the number of parameters a function call has been passed. + * + * Expects to be passed the T_STRING or T_VARIABLE stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Extra feature: If passed an T_ARRAY or T_OPEN_SHORT_ARRAY stack pointer, + * it will return the number of values in the array. + * + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/111 + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/114 + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/151 + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the function call token. + * + * @return int + */ + public function getFunctionCallParameterCount(File $phpcsFile, $stackPtr) + { + if ($this->doesFunctionCallHaveParameters($phpcsFile, $stackPtr) === false) { + return 0; + } + + return \count($this->getFunctionCallParameters($phpcsFile, $stackPtr)); + } + + + /** + * Get information on all parameters passed to a function call. + * + * Expects to be passed the T_STRING or T_VARIABLE stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Will return an multi-dimentional array with the start token pointer, end token + * pointer and raw parameter value for all parameters. Index will be 1-based. + * If no parameters are found, will return an empty array. + * + * Extra feature: If passed an T_ARRAY or T_OPEN_SHORT_ARRAY stack pointer, + * it will tokenize the values / key/value pairs contained in the array call. + * + * @since 7.0.5 Split off from the `getFunctionCallParameterCount()` method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the function call token. + * + * @return array + */ + public function getFunctionCallParameters(File $phpcsFile, $stackPtr) + { + if ($this->doesFunctionCallHaveParameters($phpcsFile, $stackPtr) === false) { + return array(); + } + + // Ok, we know we have a T_STRING, T_VARIABLE, T_ARRAY or T_OPEN_SHORT_ARRAY with parameters + // and valid open & close brackets/parenthesis. + $tokens = $phpcsFile->getTokens(); + + // Mark the beginning and end tokens. + if ($tokens[$stackPtr]['code'] === \T_OPEN_SHORT_ARRAY) { + $opener = $stackPtr; + $closer = $tokens[$stackPtr]['bracket_closer']; + + $nestedParenthesisCount = 0; + + } else { + $opener = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + $closer = $tokens[$opener]['parenthesis_closer']; + + $nestedParenthesisCount = 1; + } + + // Which nesting level is the one we are interested in ? + if (isset($tokens[$opener]['nested_parenthesis'])) { + $nestedParenthesisCount += \count($tokens[$opener]['nested_parenthesis']); + } + + $parameters = array(); + $nextComma = $opener; + $paramStart = $opener + 1; + $cnt = 1; + while (($nextComma = $phpcsFile->findNext(array(\T_COMMA, $tokens[$closer]['code'], \T_OPEN_SHORT_ARRAY, \T_CLOSURE), $nextComma + 1, $closer + 1)) !== false) { + // Ignore anything within short array definition brackets. + if ($tokens[$nextComma]['type'] === 'T_OPEN_SHORT_ARRAY' + && (isset($tokens[$nextComma]['bracket_opener']) + && $tokens[$nextComma]['bracket_opener'] === $nextComma) + && isset($tokens[$nextComma]['bracket_closer']) + ) { + // Skip forward to the end of the short array definition. + $nextComma = $tokens[$nextComma]['bracket_closer']; + continue; + } + + // Skip past closures passed as function parameters. + if ($tokens[$nextComma]['type'] === 'T_CLOSURE' + && (isset($tokens[$nextComma]['scope_condition']) + && $tokens[$nextComma]['scope_condition'] === $nextComma) + && isset($tokens[$nextComma]['scope_closer']) + ) { + // Skip forward to the end of the closure declaration. + $nextComma = $tokens[$nextComma]['scope_closer']; + continue; + } + + // Ignore comma's at a lower nesting level. + if ($tokens[$nextComma]['type'] === 'T_COMMA' + && isset($tokens[$nextComma]['nested_parenthesis']) + && \count($tokens[$nextComma]['nested_parenthesis']) !== $nestedParenthesisCount + ) { + continue; + } + + // Ignore closing parenthesis/bracket if not 'ours'. + if ($tokens[$nextComma]['type'] === $tokens[$closer]['type'] && $nextComma !== $closer) { + continue; + } + + // Ok, we've reached the end of the parameter. + $parameters[$cnt]['start'] = $paramStart; + $parameters[$cnt]['end'] = $nextComma - 1; + $parameters[$cnt]['raw'] = trim($phpcsFile->getTokensAsString($paramStart, ($nextComma - $paramStart))); + + /* + * Check if there are more tokens before the closing parenthesis. + * Prevents code like the following from setting a third parameter: + * `functionCall( $param1, $param2, );`. + */ + $hasNextParam = $phpcsFile->findNext(Tokens::$emptyTokens, $nextComma + 1, $closer, true, null, true); + if ($hasNextParam === false) { + break; + } + + // Prepare for the next parameter. + $paramStart = $nextComma + 1; + $cnt++; + } + + return $parameters; + } + + + /** + * Get information on a specific parameter passed to a function call. + * + * Expects to be passed the T_STRING or T_VARIABLE stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Will return a array with the start token pointer, end token pointer and the raw value + * of the parameter at a specific offset. + * If the specified parameter is not found, will return false. + * + * @since 7.0.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the function call token. + * @param int $paramOffset The 1-based index position of the parameter to retrieve. + * + * @return array|false + */ + public function getFunctionCallParameter(File $phpcsFile, $stackPtr, $paramOffset) + { + $parameters = $this->getFunctionCallParameters($phpcsFile, $stackPtr); + + if (isset($parameters[$paramOffset]) === false) { + return false; + } else { + return $parameters[$paramOffset]; + } + } + + + /** + * Verify whether a token is within a scoped condition. + * + * If the optional $validScopes parameter has been passed, the function + * will check that the token has at least one condition which is of a + * type defined in $validScopes. + * + * @since 7.0.5 Largely split off from the `inClassScope()` method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the token. + * @param array|int $validScopes Optional. Array of valid scopes + * or int value of a valid scope. + * Pass the T_.. constant(s) for the + * desired scope to this parameter. + * + * @return bool Without the optional $scopeTypes: True if within a scope, false otherwise. + * If the $scopeTypes are set: True if *one* of the conditions is a + * valid scope, false otherwise. + */ + public function tokenHasScope(File $phpcsFile, $stackPtr, $validScopes = null) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + // No conditions = no scope. + if (empty($tokens[$stackPtr]['conditions'])) { + return false; + } + + // Ok, there are conditions, do we have to check for specific ones ? + if (isset($validScopes) === false) { + return true; + } + + return $phpcsFile->hasCondition($stackPtr, $validScopes); + } + + + /** + * Verify whether a token is within a class scope. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the token. + * @param bool $strict Whether to strictly check for the T_CLASS + * scope or also accept interfaces and traits + * as scope. + * + * @return bool True if within class scope, false otherwise. + */ + public function inClassScope(File $phpcsFile, $stackPtr, $strict = true) + { + $validScopes = array(\T_CLASS); + if (\defined('T_ANON_CLASS') === true) { + $validScopes[] = \T_ANON_CLASS; + } + + if ($strict === false) { + $validScopes[] = \T_INTERFACE; + $validScopes[] = \T_TRAIT; + } + + return $phpcsFile->hasCondition($stackPtr, $validScopes); + } + + + /** + * Returns the fully qualified class name for a new class instantiation. + * + * Returns an empty string if the class name could not be reliably inferred. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of a T_NEW token. + * + * @return string + */ + public function getFQClassNameFromNewToken(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return ''; + } + + if ($tokens[$stackPtr]['code'] !== \T_NEW) { + return ''; + } + + $start = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + if ($start === false) { + return ''; + } + + // Bow out if the next token is a variable as we don't know where it was defined. + if ($tokens[$start]['code'] === \T_VARIABLE) { + return ''; + } + + // Bow out if the next token is the class keyword. + if ($tokens[$start]['type'] === 'T_ANON_CLASS' || $tokens[$start]['code'] === \T_CLASS) { + return ''; + } + + $find = array( + \T_NS_SEPARATOR, + \T_STRING, + \T_NAMESPACE, + \T_WHITESPACE, + ); + + $end = $phpcsFile->findNext($find, ($start + 1), null, true, null, true); + $className = $phpcsFile->getTokensAsString($start, ($end - $start)); + $className = trim($className); + + return $this->getFQName($phpcsFile, $stackPtr, $className); + } + + + /** + * Returns the fully qualified name of the class that the specified class extends. + * + * Returns an empty string if the class does not extend another class or if + * the class name could not be reliably inferred. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of a T_CLASS token. + * + * @return string + */ + public function getFQExtendedClassName(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return ''; + } + + if ($tokens[$stackPtr]['code'] !== \T_CLASS + && $tokens[$stackPtr]['type'] !== 'T_ANON_CLASS' + && $tokens[$stackPtr]['type'] !== 'T_INTERFACE' + ) { + return ''; + } + + $extends = PHPCSHelper::findExtendedClassName($phpcsFile, $stackPtr); + if (empty($extends) || \is_string($extends) === false) { + return ''; + } + + return $this->getFQName($phpcsFile, $stackPtr, $extends); + } + + + /** + * Returns the class name for the static usage of a class. + * This can be a call to a method, the use of a property or constant. + * + * Returns an empty string if the class name could not be reliably inferred. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of a T_NEW token. + * + * @return string + */ + public function getFQClassNameFromDoubleColonToken(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return ''; + } + + if ($tokens[$stackPtr]['code'] !== \T_DOUBLE_COLON) { + return ''; + } + + // Nothing to do if previous token is a variable as we don't know where it was defined. + if ($tokens[$stackPtr - 1]['code'] === \T_VARIABLE) { + return ''; + } + + // Nothing to do if 'parent' or 'static' as we don't know how far the class tree extends. + if (\in_array($tokens[$stackPtr - 1]['code'], array(\T_PARENT, \T_STATIC), true)) { + return ''; + } + + // Get the classname from the class declaration if self is used. + if ($tokens[$stackPtr - 1]['code'] === \T_SELF) { + $classDeclarationPtr = $phpcsFile->findPrevious(\T_CLASS, $stackPtr - 1); + if ($classDeclarationPtr === false) { + return ''; + } + $className = $phpcsFile->getDeclarationName($classDeclarationPtr); + return $this->getFQName($phpcsFile, $classDeclarationPtr, $className); + } + + $find = array( + \T_NS_SEPARATOR, + \T_STRING, + \T_NAMESPACE, + \T_WHITESPACE, + ); + + $start = $phpcsFile->findPrevious($find, $stackPtr - 1, null, true, null, true); + if ($start === false || isset($tokens[($start + 1)]) === false) { + return ''; + } + + $start = ($start + 1); + $className = $phpcsFile->getTokensAsString($start, ($stackPtr - $start)); + $className = trim($className); + + return $this->getFQName($phpcsFile, $stackPtr, $className); + } + + + /** + * Get the Fully Qualified name for a class/function/constant etc. + * + * Checks if a class/function/constant name is already fully qualified and + * if not, enrich it with the relevant namespace information. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the token. + * @param string $name The class / function / constant name. + * + * @return string + */ + public function getFQName(File $phpcsFile, $stackPtr, $name) + { + if (strpos($name, '\\') === 0) { + // Already fully qualified. + return $name; + } + + // Remove the namespace keyword if used. + if (strpos($name, 'namespace\\') === 0) { + $name = substr($name, 10); + } + + $namespace = $this->determineNamespace($phpcsFile, $stackPtr); + + if ($namespace === '') { + return '\\' . $name; + } else { + return '\\' . $namespace . '\\' . $name; + } + } + + + /** + * Is the class/function/constant name namespaced or global ? + * + * @since 7.0.3 + * + * @param string $FQName Fully Qualified name of a class, function etc. + * I.e. should always start with a `\`. + * + * @return bool True if namespaced, false if global. + * + * @throws \PHP_CodeSniffer_Exception If the name in the passed parameter + * is not fully qualified. + */ + public function isNamespaced($FQName) + { + if (strpos($FQName, '\\') !== 0) { + throw new PHPCS_Exception('$FQName must be a fully qualified name'); + } + + return (strpos(substr($FQName, 1), '\\') !== false); + } + + + /** + * Determine the namespace name an arbitrary token lives in. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $stackPtr The token position for which to determine the namespace. + * + * @return string Namespace name or empty string if it couldn't be determined or no namespace applies. + */ + public function determineNamespace(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return ''; + } + + // Check for scoped namespace {}. + if (empty($tokens[$stackPtr]['conditions']) === false) { + $namespacePtr = $phpcsFile->getCondition($stackPtr, \T_NAMESPACE); + if ($namespacePtr !== false) { + $namespace = $this->getDeclaredNamespaceName($phpcsFile, $namespacePtr); + if ($namespace !== false) { + return $namespace; + } + + // We are in a scoped namespace, but couldn't determine the name. Searching for a global namespace is futile. + return ''; + } + } + + /* + * Not in a scoped namespace, so let's see if we can find a non-scoped namespace instead. + * Keeping in mind that: + * - there can be multiple non-scoped namespaces in a file (bad practice, but it happens). + * - the namespace keyword can also be used as part of a function/method call and such. + * - that a non-named namespace resolves to the global namespace. + */ + $previousNSToken = $stackPtr; + $namespace = false; + do { + $previousNSToken = $phpcsFile->findPrevious(\T_NAMESPACE, ($previousNSToken - 1)); + + // Stop if we encounter a scoped namespace declaration as we already know we're not in one. + if (empty($tokens[$previousNSToken]['scope_condition']) === false && $tokens[$previousNSToken]['scope_condition'] === $previousNSToken) { + break; + } + + $namespace = $this->getDeclaredNamespaceName($phpcsFile, $previousNSToken); + + } while ($namespace === false && $previousNSToken !== false); + + // If we still haven't got a namespace, return an empty string. + if ($namespace === false) { + return ''; + } else { + return $namespace; + } + } + + /** + * Get the complete namespace name for a namespace declaration. + * + * For hierarchical namespaces, the name will be composed of several tokens, + * i.e. MyProject\Sub\Level which will be returned together as one string. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int|bool $stackPtr The position of a T_NAMESPACE token. + * + * @return string|false Namespace name or false if not a namespace declaration. + * Namespace name can be an empty string for global namespace declaration. + */ + public function getDeclaredNamespaceName(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if ($stackPtr === false || isset($tokens[$stackPtr]) === false) { + return false; + } + + if ($tokens[$stackPtr]['code'] !== \T_NAMESPACE) { + return false; + } + + if ($tokens[($stackPtr + 1)]['code'] === \T_NS_SEPARATOR) { + // Not a namespace declaration, but use of, i.e. `namespace\someFunction();`. + return false; + } + + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); + if ($tokens[$nextToken]['code'] === \T_OPEN_CURLY_BRACKET) { + /* + * Declaration for global namespace when using multiple namespaces in a file. + * I.e.: `namespace {}`. + */ + return ''; + } + + // Ok, this should be a namespace declaration, so get all the parts together. + $validTokens = array( + \T_STRING => true, + \T_NS_SEPARATOR => true, + \T_WHITESPACE => true, + ); + + $namespaceName = ''; + while (isset($validTokens[$tokens[$nextToken]['code']]) === true) { + $namespaceName .= trim($tokens[$nextToken]['content']); + $nextToken++; + } + + return $namespaceName; + } + + + /** + * Get the stack pointer for a return type token for a given function. + * + * Compatible layer for older PHPCS versions which don't recognize + * return type hints correctly. + * + * Expects to be passed T_RETURN_TYPE, T_FUNCTION or T_CLOSURE token. + * + * @since 7.1.2 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the token. + * + * @return int|false Stack pointer to the return type token or false if + * no return type was found or the passed token was + * not of the correct type. + */ + public function getReturnTypeHintToken(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (\defined('T_RETURN_TYPE') && $tokens[$stackPtr]['code'] === \T_RETURN_TYPE) { + return $stackPtr; + } + + if ($tokens[$stackPtr]['code'] !== \T_FUNCTION && $tokens[$stackPtr]['code'] !== \T_CLOSURE) { + return false; + } + + if (isset($tokens[$stackPtr]['parenthesis_closer']) === false) { + return false; + } + + // Allow for interface and abstract method declarations. + $endOfFunctionDeclaration = null; + if (isset($tokens[$stackPtr]['scope_opener'])) { + $endOfFunctionDeclaration = $tokens[$stackPtr]['scope_opener']; + } else { + $nextSemiColon = $phpcsFile->findNext(\T_SEMICOLON, ($tokens[$stackPtr]['parenthesis_closer'] + 1), null, false, null, true); + if ($nextSemiColon !== false) { + $endOfFunctionDeclaration = $nextSemiColon; + } + } + + if (isset($endOfFunctionDeclaration) === false) { + return false; + } + + $hasColon = $phpcsFile->findNext( + array(\T_COLON, \T_INLINE_ELSE), + ($tokens[$stackPtr]['parenthesis_closer'] + 1), + $endOfFunctionDeclaration + ); + if ($hasColon === false) { + return false; + } + + /* + * - `self`, `parent` and `callable` are not being recognized as return types in PHPCS < 2.6.0. + * - Return types are not recognized at all in PHPCS < 2.4.0. + * - The T_RETURN_TYPE token is defined, but no longer in use since PHPCS 3.3.0+. + * The token will now be tokenized as T_STRING. + * - An `array` (return) type declaration was tokenized as `T_ARRAY_HINT` in PHPCS 2.3.3 - 3.2.3 + * to prevent confusing sniffs looking for array declarations. + * As of PHPCS 3.3.0 `array` as a type declaration will be tokenized as `T_STRING`. + */ + $unrecognizedTypes = array( + \T_CALLABLE, + \T_SELF, + \T_PARENT, + \T_ARRAY, // PHPCS < 2.4.0. + \T_STRING, + ); + + return $phpcsFile->findPrevious($unrecognizedTypes, ($endOfFunctionDeclaration - 1), $hasColon); + } + + + /** + * Get the complete return type declaration for a given function. + * + * Cross-version compatible way to retrieve the complete return type declaration. + * + * For a classname-based return type, PHPCS, as well as the Sniff::getReturnTypeHintToken() + * method will mark the classname as the return type token. + * This method will find preceeding namespaces and namespace separators and will return a + * string containing the qualified return type declaration. + * + * Expects to be passed a T_RETURN_TYPE token or the return value from a call to + * the Sniff::getReturnTypeHintToken() method. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the return type token. + * + * @return string The name of the return type token. + */ + public function getReturnTypeHintName(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // In older PHPCS versions, the nullable indicator will turn a return type colon into a T_INLINE_ELSE. + $colon = $phpcsFile->findPrevious(array(\T_COLON, \T_INLINE_ELSE, \T_FUNCTION, \T_CLOSE_PARENTHESIS), ($stackPtr - 1)); + if ($colon === false + || ($tokens[$colon]['code'] !== \T_COLON && $tokens[$colon]['code'] !== \T_INLINE_ELSE) + ) { + // Shouldn't happen, just in case. + return ''; + } + + $returnTypeHint = ''; + for ($i = ($colon + 1); $i <= $stackPtr; $i++) { + // As of PHPCS 3.3.0+, all tokens are tokenized as "normal", so T_CALLABLE, T_SELF etc are + // all possible, just exclude anything that's regarded as empty and the nullable indicator. + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']])) { + continue; + } + + if ($tokens[$i]['type'] === 'T_NULLABLE') { + continue; + } + + if (\defined('T_NULLABLE') === false && $tokens[$i]['code'] === \T_INLINE_THEN) { + // Old PHPCS. + continue; + } + + $returnTypeHint .= $tokens[$i]['content']; + } + + return $returnTypeHint; + } + + + /** + * Check whether a T_VARIABLE token is a class property declaration. + * + * Compatibility layer for PHPCS cross-version compatibility + * as PHPCS 2.4.0 - 2.7.1 does not have good enough support for + * anonymous classes. Along the same lines, the`getMemberProperties()` + * method does not support the `var` prefix. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $stackPtr The position in the stack of the + * T_VARIABLE token to verify. + * + * @return bool + */ + public function isClassProperty(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]) === false || $tokens[$stackPtr]['code'] !== \T_VARIABLE) { + return false; + } + + // Note: interfaces can not declare properties. + $validScopes = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_TRAIT' => true, + ); + + $scopePtr = $this->validDirectScope($phpcsFile, $stackPtr, $validScopes); + if ($scopePtr !== false) { + // Make sure it's not a method parameter. + if (empty($tokens[$stackPtr]['nested_parenthesis']) === true) { + return true; + } else { + $parenthesis = array_keys($tokens[$stackPtr]['nested_parenthesis']); + $deepestOpen = array_pop($parenthesis); + if ($deepestOpen < $scopePtr + || isset($tokens[$deepestOpen]['parenthesis_owner']) === false + || $tokens[$tokens[$deepestOpen]['parenthesis_owner']]['code'] !== \T_FUNCTION + ) { + return true; + } + } + } + + return false; + } + + + /** + * Check whether a T_CONST token is a class constant declaration. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $stackPtr The position in the stack of the + * T_CONST token to verify. + * + * @return bool + */ + public function isClassConstant(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]) === false || $tokens[$stackPtr]['code'] !== \T_CONST) { + return false; + } + + // Note: traits can not declare constants. + $validScopes = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_INTERFACE' => true, + ); + if ($this->validDirectScope($phpcsFile, $stackPtr, $validScopes) !== false) { + return true; + } + + return false; + } + + + /** + * Check whether the direct wrapping scope of a token is within a limited set of + * acceptable tokens. + * + * Used to check, for instance, if a T_CONST is a class constant. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $stackPtr The position in the stack of the + * token to verify. + * @param array $validScopes Array of token types. + * Keys should be the token types in string + * format to allow for newer token types. + * Value is irrelevant. + * + * @return int|bool StackPtr to the scope if valid, false otherwise. + */ + protected function validDirectScope(File $phpcsFile, $stackPtr, $validScopes) + { + $tokens = $phpcsFile->getTokens(); + + if (empty($tokens[$stackPtr]['conditions']) === true) { + return false; + } + + /* + * Check only the direct wrapping scope of the token. + */ + $conditions = array_keys($tokens[$stackPtr]['conditions']); + $ptr = array_pop($conditions); + + if (isset($tokens[$ptr]) === false) { + return false; + } + + if (isset($validScopes[$tokens[$ptr]['type']]) === true) { + return $ptr; + } + + return false; + } + + + /** + * Get an array of just the type hints from a function declaration. + * + * Expects to be passed T_FUNCTION or T_CLOSURE token. + * + * Strips potential nullable indicator and potential global namespace + * indicator from the type hints before returning them. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the token. + * + * @return array Array with type hints or an empty array if + * - the function does not have any parameters + * - no type hints were found + * - or the passed token was not of the correct type. + */ + public function getTypeHintsFromFunctionDeclaration(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] !== \T_FUNCTION && $tokens[$stackPtr]['code'] !== \T_CLOSURE) { + return array(); + } + + $parameters = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($parameters) || \is_array($parameters) === false) { + return array(); + } + + $typeHints = array(); + + foreach ($parameters as $param) { + if ($param['type_hint'] === '') { + continue; + } + + // Strip off potential nullable indication. + $typeHint = ltrim($param['type_hint'], '?'); + + // Strip off potential (global) namespace indication. + $typeHint = ltrim($typeHint, '\\'); + + if ($typeHint !== '') { + $typeHints[] = $typeHint; + } + } + + return $typeHints; + } + + + /** + * Get the hash algorithm name from the parameter in a hash function call. + * + * @since 7.0.7 Logic was originally contained in the `RemovedHashAlgorithms` sniff. + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $stackPtr The position of the T_STRING function token. + * + * @return string|false The algorithm name without quotes if this was a relevant hash + * function call or false if it was not. + */ + public function getHashAlgorithmParameter(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + if ($tokens[$stackPtr]['code'] !== \T_STRING) { + return false; + } + + $functionName = $tokens[$stackPtr]['content']; + $functionNameLc = strtolower($functionName); + + // Bow out if not one of the functions we're targetting. + if (isset($this->hashAlgoFunctions[$functionNameLc]) === false) { + return false; + } + + // Get the parameter from the function call which should contain the algorithm name. + $algoParam = $this->getFunctionCallParameter($phpcsFile, $stackPtr, $this->hashAlgoFunctions[$functionNameLc]); + if ($algoParam === false) { + return false; + } + + // Algorithm is a text string, so we need to remove the quotes. + $algo = strtolower(trim($algoParam['raw'])); + $algo = $this->stripQuotes($algo); + + return $algo; + } + + + /** + * Determine whether an arbitrary T_STRING token is the use of a global constant. + * + * @since 8.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the T_STRING token. + * + * @return bool + */ + public function isUseOfGlobalConstant(File $phpcsFile, $stackPtr) + { + static $isLowPHPCS, $isLowPHP; + + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + // Is this one of the tokens this function handles ? + if ($tokens[$stackPtr]['code'] !== \T_STRING) { + return false; + } + + // Check for older PHP, PHPCS version so we can compensate for misidentified tokens. + if (isset($isLowPHPCS, $isLowPHP) === false) { + $isLowPHP = false; + $isLowPHPCS = false; + if (version_compare(\PHP_VERSION_ID, '50400', '<')) { + $isLowPHP = true; + $isLowPHPCS = version_compare(PHPCSHelper::getVersion(), '2.4.0', '<'); + } + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next !== false + && ($tokens[$next]['code'] === \T_OPEN_PARENTHESIS + || $tokens[$next]['code'] === \T_DOUBLE_COLON) + ) { + // Function call or declaration. + return false; + } + + // Array of tokens which if found preceding the $stackPtr indicate that a T_STRING is not a global constant. + $tokensToIgnore = array( + 'T_NAMESPACE' => true, + 'T_USE' => true, + 'T_CLASS' => true, + 'T_TRAIT' => true, + 'T_INTERFACE' => true, + 'T_EXTENDS' => true, + 'T_IMPLEMENTS' => true, + 'T_NEW' => true, + 'T_FUNCTION' => true, + 'T_DOUBLE_COLON' => true, + 'T_OBJECT_OPERATOR' => true, + 'T_INSTANCEOF' => true, + 'T_INSTEADOF' => true, + 'T_GOTO' => true, + 'T_AS' => true, + 'T_PUBLIC' => true, + 'T_PROTECTED' => true, + 'T_PRIVATE' => true, + ); + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prev !== false + && (isset($tokensToIgnore[$tokens[$prev]['type']]) === true + || ($tokens[$prev]['code'] === \T_STRING + && (($isLowPHPCS === true + && $tokens[$prev]['content'] === 'trait') + || ($isLowPHP === true + && $tokens[$prev]['content'] === 'insteadof')))) + ) { + // Not the use of a constant. + return false; + } + + if ($prev !== false + && $tokens[$prev]['code'] === \T_NS_SEPARATOR + && $tokens[($prev - 1)]['code'] === \T_STRING + ) { + // Namespaced constant of the same name. + return false; + } + + if ($prev !== false + && $tokens[$prev]['code'] === \T_CONST + && $this->isClassConstant($phpcsFile, $prev) === true + ) { + // Class constant declaration of the same name. + return false; + } + + /* + * Deal with a number of variations of use statements. + */ + for ($i = $stackPtr; $i > 0; $i--) { + if ($tokens[$i]['line'] !== $tokens[$stackPtr]['line']) { + break; + } + } + + $firstOnLine = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($firstOnLine !== false && $tokens[$firstOnLine]['code'] === \T_USE) { + $nextOnLine = $phpcsFile->findNext(Tokens::$emptyTokens, ($firstOnLine + 1), null, true); + if ($nextOnLine !== false) { + if (($tokens[$nextOnLine]['code'] === \T_STRING && $tokens[$nextOnLine]['content'] === 'const') + || $tokens[$nextOnLine]['code'] === \T_CONST // Happens in some PHPCS versions. + ) { + $hasNsSep = $phpcsFile->findNext(\T_NS_SEPARATOR, ($nextOnLine + 1), $stackPtr); + if ($hasNsSep !== false) { + // Namespaced const (group) use statement. + return false; + } + } else { + // Not a const use statement. + return false; + } + } + } + + return true; + } + + + /** + * Determine whether the tokens between $start and $end together form a positive number + * as recognized by PHP. + * + * The outcome of this function is reliable for `true`, `false` should be regarded as + * "undetermined". + * + * Note: Zero is *not* regarded as a positive number. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $start Start of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * @param int $end End of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * @param bool $allowFloats Whether to only consider integers, or also floats. + * + * @return bool True if PHP would evaluate the snippet as a positive number. + * False if not or if it could not be reliably determined + * (variable or calculations and such). + */ + public function isPositiveNumber(File $phpcsFile, $start, $end, $allowFloats = false) + { + $number = $this->isNumber($phpcsFile, $start, $end, $allowFloats); + + if ($number === false) { + return false; + } + + return ($number > 0); + } + + + /** + * Determine whether the tokens between $start and $end together form a negative number + * as recognized by PHP. + * + * The outcome of this function is reliable for `true`, `false` should be regarded as + * "undetermined". + * + * Note: Zero is *not* regarded as a negative number. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $start Start of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * @param int $end End of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * @param bool $allowFloats Whether to only consider integers, or also floats. + * + * @return bool True if PHP would evaluate the snippet as a negative number. + * False if not or if it could not be reliably determined + * (variable or calculations and such). + */ + public function isNegativeNumber(File $phpcsFile, $start, $end, $allowFloats = false) + { + $number = $this->isNumber($phpcsFile, $start, $end, $allowFloats); + + if ($number === false) { + return false; + } + + return ($number < 0); + } + + /** + * Determine whether the tokens between $start and $end together form a number + * as recognized by PHP. + * + * The outcome of this function is reliable for "true-ish" values, `false` should + * be regarded as "undetermined". + * + * @link https://3v4l.org/npTeM + * + * Mainly intended for examining variable assignments, function call parameters, array values + * where the start and end of the snippet to examine is very clear. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $start Start of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * @param int $end End of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * @param bool $allowFloats Whether to only consider integers, or also floats. + * + * @return int|float|bool The number found if PHP would evaluate the snippet as a number. + * The return type will be int if $allowFloats is false, if + * $allowFloats is true, the return type will be float. + * False will be returned when the snippet does not evaluate to a + * number or if it could not be reliably determined + * (variable or calculations and such). + */ + protected function isNumber(File $phpcsFile, $start, $end, $allowFloats = false) + { + $stringTokens = Tokens::$heredocTokens + Tokens::$stringTokens; + + $validTokens = array(); + $validTokens[\T_LNUMBER] = true; + $validTokens[\T_TRUE] = true; // Evaluates to int 1. + $validTokens[\T_FALSE] = true; // Evaluates to int 0. + $validTokens[\T_NULL] = true; // Evaluates to int 0. + + if ($allowFloats === true) { + $validTokens[\T_DNUMBER] = true; + } + + $maybeValidTokens = $stringTokens + $validTokens; + + $tokens = $phpcsFile->getTokens(); + $searchEnd = ($end + 1); + $negativeNumber = false; + + if (isset($tokens[$start], $tokens[$searchEnd]) === false) { + return false; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $start, $searchEnd, true); + while ($nextNonEmpty !== false + && ($tokens[$nextNonEmpty]['code'] === \T_PLUS + || $tokens[$nextNonEmpty]['code'] === \T_MINUS) + ) { + + if ($tokens[$nextNonEmpty]['code'] === \T_MINUS) { + $negativeNumber = ($negativeNumber === false) ? true : false; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), $searchEnd, true); + } + + if ($nextNonEmpty === false || isset($maybeValidTokens[$tokens[$nextNonEmpty]['code']]) === false) { + return false; + } + + $content = false; + if ($tokens[$nextNonEmpty]['code'] === \T_LNUMBER + || $tokens[$nextNonEmpty]['code'] === \T_DNUMBER + ) { + $content = (float) $tokens[$nextNonEmpty]['content']; + } elseif ($tokens[$nextNonEmpty]['code'] === \T_TRUE) { + $content = 1.0; + } elseif ($tokens[$nextNonEmpty]['code'] === \T_FALSE + || $tokens[$nextNonEmpty]['code'] === \T_NULL + ) { + $content = 0.0; + } elseif (isset($stringTokens[$tokens[$nextNonEmpty]['code']]) === true) { + + if ($tokens[$nextNonEmpty]['code'] === \T_START_HEREDOC + || $tokens[$nextNonEmpty]['code'] === \T_START_NOWDOC + ) { + // Skip past heredoc/nowdoc opener to the first content. + $firstDocToken = $phpcsFile->findNext(array(\T_HEREDOC, \T_NOWDOC), ($nextNonEmpty + 1), $searchEnd); + if ($firstDocToken === false) { + // Live coding or parse error. + return false; + } + + $stringContent = $content = $tokens[$firstDocToken]['content']; + + // Skip forward to the end in preparation for the next part of the examination. + $nextNonEmpty = $phpcsFile->findNext(array(\T_END_HEREDOC, \T_END_NOWDOC), ($nextNonEmpty + 1), $searchEnd); + if ($nextNonEmpty === false) { + // Live coding or parse error. + return false; + } + } else { + // Gather subsequent lines for a multi-line string. + for ($i = $nextNonEmpty; $i < $searchEnd; $i++) { + if ($tokens[$i]['code'] !== $tokens[$nextNonEmpty]['code']) { + break; + } + $content .= $tokens[$i]['content']; + } + + $nextNonEmpty = --$i; + $content = $this->stripQuotes($content); + $stringContent = $content; + } + + /* + * Regexes based on the formats outlined in the manual, created by JRF. + * @link https://www.php.net/manual/en/language.types.float.php + */ + $regexInt = '`^\s*[0-9]+`'; + $regexFloat = '`^\s*(?:[+-]?(?:(?:(?P<LNUM>[0-9]+)|(?P<DNUM>([0-9]*\.(?P>LNUM)|(?P>LNUM)\.[0-9]*)))[eE][+-]?(?P>LNUM))|(?P>DNUM))`'; + + $intString = preg_match($regexInt, $content, $intMatch); + $floatString = preg_match($regexFloat, $content, $floatMatch); + + // Does the text string start with a number ? If so, PHP would juggle it and use it as a number. + if ($allowFloats === false) { + if ($intString !== 1 || $floatString === 1) { + if ($floatString === 1) { + // Found float. Only integers targetted. + return false; + } + + $content = 0.0; + } else { + $content = (float) trim($intMatch[0]); + } + } else { + if ($intString !== 1 && $floatString !== 1) { + $content = 0.0; + } else { + $content = ($floatString === 1) ? (float) trim($floatMatch[0]) : (float) trim($intMatch[0]); + } + } + + // Allow for different behaviour for hex numeric strings between PHP 5 vs PHP 7. + if ($intString === 1 && trim($intMatch[0]) === '0' + && preg_match('`^\s*(0x[A-Fa-f0-9]+)`', $stringContent, $hexNumberString) === 1 + && $this->supportsBelow('5.6') === true + ) { + // The filter extension still allows for hex numeric strings in PHP 7, so + // use that to get the numeric value if possible. + // If the filter extension is not available, the value will be zero, but so be it. + if (function_exists('filter_var')) { + $filtered = filter_var($hexNumberString[1], \FILTER_VALIDATE_INT, \FILTER_FLAG_ALLOW_HEX); + if ($filtered !== false) { + $content = $filtered; + } + } + } + } + + // OK, so we have a number, now is there still more code after it ? + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), $searchEnd, true); + if ($nextNonEmpty !== false) { + return false; + } + + if ($negativeNumber === true) { + $content = -$content; + } + + if ($allowFloats === false) { + return (int) $content; + } + + return $content; + } + + + /** + * Determine whether the tokens between $start and $end together form a numberic calculation + * as recognized by PHP. + * + * The outcome of this function is reliable for `true`, `false` should be regarded as "undetermined". + * + * Mainly intended for examining variable assignments, function call parameters, array values + * where the start and end of the snippet to examine is very clear. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $start Start of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * @param int $end End of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * + * @return bool + */ + protected function isNumericCalculation(File $phpcsFile, $start, $end) + { + $arithmeticTokens = Tokens::$arithmeticTokens; + + // phpcs:disable PHPCompatibility.Constants.NewConstants.t_powFound + if (\defined('T_POW') && isset($arithmeticTokens[\T_POW]) === false) { + // T_POW was not added to the arithmetic array until PHPCS 2.9.0. + $arithmeticTokens[\T_POW] = \T_POW; + } + // phpcs:enable + + $skipTokens = Tokens::$emptyTokens; + $skipTokens[] = \T_MINUS; + $skipTokens[] = \T_PLUS; + + // Find the first arithmetic operator, but skip past +/- signs before numbers. + $nextNonEmpty = ($start - 1); + do { + $nextNonEmpty = $phpcsFile->findNext($skipTokens, ($nextNonEmpty + 1), ($end + 1), true); + $arithmeticOperator = $phpcsFile->findNext($arithmeticTokens, ($nextNonEmpty + 1), ($end + 1)); + } while ($nextNonEmpty !== false && $arithmeticOperator !== false && $nextNonEmpty === $arithmeticOperator); + + if ($arithmeticOperator === false) { + return false; + } + + $tokens = $phpcsFile->getTokens(); + $subsetStart = $start; + $subsetEnd = ($arithmeticOperator - 1); + + while ($this->isNumber($phpcsFile, $subsetStart, $subsetEnd, true) !== false + && isset($tokens[($arithmeticOperator + 1)]) === true + ) { + // Recognize T_POW for PHPCS < 2.4.0 on low PHP versions. + if (\defined('T_POW') === false + && $tokens[$arithmeticOperator]['code'] === \T_MULTIPLY + && $tokens[($arithmeticOperator + 1)]['code'] === \T_MULTIPLY + && isset($tokens[$arithmeticOperator + 2]) === true + ) { + // Move operator one forward to the second * in T_POW. + ++$arithmeticOperator; + } + + $subsetStart = ($arithmeticOperator + 1); + $nextNonEmpty = $arithmeticOperator; + do { + $nextNonEmpty = $phpcsFile->findNext($skipTokens, ($nextNonEmpty + 1), ($end + 1), true); + $arithmeticOperator = $phpcsFile->findNext($arithmeticTokens, ($nextNonEmpty + 1), ($end + 1)); + } while ($nextNonEmpty !== false && $arithmeticOperator !== false && $nextNonEmpty === $arithmeticOperator); + + if ($arithmeticOperator === false) { + // Last calculation operator already reached. + if ($this->isNumber($phpcsFile, $subsetStart, $end, true) !== false) { + return true; + } + + return false; + } + + $subsetEnd = ($arithmeticOperator - 1); + } + + return false; + } + + + + /** + * Determine whether a ternary is a short ternary, i.e. without "middle". + * + * N.B.: This is a back-fill for a new method which is expected to go into + * PHP_CodeSniffer 3.5.0. + * Once that method has been merged into PHPCS, this one should be moved + * to the PHPCSHelper.php file. + * + * @since 9.2.0 + * + * @codeCoverageIgnore Method as pulled upstream is accompanied by unit tests. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the ternary operator + * in the stack. + * + * @return bool True if short ternary, or false otherwise. + */ + public function isShortTernary(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]) === false + || $tokens[$stackPtr]['code'] !== \T_INLINE_THEN + ) { + return false; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + // Live coding or parse error. + return false; + } + + if ($tokens[$nextNonEmpty]['code'] === \T_INLINE_ELSE) { + return true; + } + + return false; + } + + + /** + * Determine whether a T_OPEN/CLOSE_SHORT_ARRAY token is a list() construct. + * + * Note: A variety of PHPCS versions have bugs in the tokenizing of short arrays. + * In that case, the tokens are identified as T_OPEN/CLOSE_SQUARE_BRACKET. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the function call token. + * + * @return bool + */ + public function isShortList(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + // Is this one of the tokens this function handles ? + if ($tokens[$stackPtr]['code'] !== \T_OPEN_SHORT_ARRAY + && $tokens[$stackPtr]['code'] !== \T_CLOSE_SHORT_ARRAY + ) { + return false; + } + + switch ($tokens[$stackPtr]['code']) { + case \T_OPEN_SHORT_ARRAY: + if (isset($tokens[$stackPtr]['bracket_closer']) === true) { + $opener = $stackPtr; + $closer = $tokens[$stackPtr]['bracket_closer']; + } + break; + + case \T_CLOSE_SHORT_ARRAY: + if (isset($tokens[$stackPtr]['bracket_opener']) === true) { + $opener = $tokens[$stackPtr]['bracket_opener']; + $closer = $stackPtr; + } + break; + } + + if (isset($opener, $closer) === false) { + // Parse error, live coding or real square bracket. + return false; + } + + /* + * PHPCS cross-version compatibility: work around for square brackets misidentified + * as short array when preceded by a variable variable in older PHPCS versions. + */ + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($opener - 1), null, true, null, true); + + if ($prevNonEmpty !== false + && $tokens[$prevNonEmpty]['code'] === \T_CLOSE_CURLY_BRACKET + && isset($tokens[$prevNonEmpty]['bracket_opener']) === true + ) { + $maybeVariableVariable = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($tokens[$prevNonEmpty]['bracket_opener'] - 1), + null, + true, + null, + true + ); + + if ($tokens[$maybeVariableVariable]['code'] === \T_VARIABLE + || $tokens[$maybeVariableVariable]['code'] === \T_DOLLAR + ) { + return false; + } + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($closer + 1), null, true, null, true); + + if ($nextNonEmpty !== false && $tokens[$nextNonEmpty]['code'] === \T_EQUAL) { + return true; + } + + if ($prevNonEmpty !== false + && $tokens[$prevNonEmpty]['code'] === \T_AS + && isset($tokens[$prevNonEmpty]['nested_parenthesis']) === true + ) { + $parentheses = array_reverse($tokens[$prevNonEmpty]['nested_parenthesis'], true); + foreach ($parentheses as $open => $close) { + if (isset($tokens[$open]['parenthesis_owner']) + && $tokens[$tokens[$open]['parenthesis_owner']]['code'] === \T_FOREACH + ) { + return true; + } + } + } + + // Maybe this is a short list syntax nested inside another short list syntax ? + $parentOpener = $opener; + do { + $parentOpener = $phpcsFile->findPrevious( + array(\T_OPEN_SHORT_ARRAY, \T_OPEN_SQUARE_BRACKET), + ($parentOpener - 1), + null, + false, + null, + true + ); + + if ($parentOpener === false) { + return false; + } + + } while (isset($tokens[$parentOpener]['bracket_closer']) === true + && $tokens[$parentOpener]['bracket_closer'] < $opener + ); + + if (isset($tokens[$parentOpener]['bracket_closer']) === true + && $tokens[$parentOpener]['bracket_closer'] > $closer + ) { + // Work around tokenizer issue in PHPCS 2.0 - 2.7. + $phpcsVersion = PHPCSHelper::getVersion(); + if ((version_compare($phpcsVersion, '2.0', '>') === true + && version_compare($phpcsVersion, '2.8', '<') === true) + && $tokens[$parentOpener]['code'] === \T_OPEN_SQUARE_BRACKET + ) { + $nextNonEmpty = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($tokens[$parentOpener]['bracket_closer'] + 1), + null, + true, + null, + true + ); + + if ($nextNonEmpty !== false && $tokens[$nextNonEmpty]['code'] === \T_EQUAL) { + return true; + } + + return false; + } + + return $this->isShortList($phpcsFile, $parentOpener); + } + + return false; + } + + + /** + * Determine whether the tokens between $start and $end could together represent a variable. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $start Starting point stack pointer. Inclusive. + * I.e. this token should be taken into account. + * @param int $end End point stack pointer. Exclusive. + * I.e. this token should not be taken into account. + * @param int $targetNestingLevel The nesting level the variable should be at. + * + * @return bool + */ + public function isVariable(File $phpcsFile, $start, $end, $targetNestingLevel) + { + static $tokenBlackList, $bracketTokens; + + // Create the token arrays only once. + if (isset($tokenBlackList, $bracketTokens) === false) { + + $tokenBlackList = array( + \T_OPEN_PARENTHESIS => \T_OPEN_PARENTHESIS, + \T_STRING_CONCAT => \T_STRING_CONCAT, + ); + $tokenBlackList += Tokens::$assignmentTokens; + $tokenBlackList += Tokens::$equalityTokens; + $tokenBlackList += Tokens::$comparisonTokens; + $tokenBlackList += Tokens::$operators; + $tokenBlackList += Tokens::$booleanOperators; + $tokenBlackList += Tokens::$castTokens; + + /* + * List of brackets which can be part of a variable variable. + * + * Key is the open bracket token, value the close bracket token. + */ + $bracketTokens = array( + \T_OPEN_CURLY_BRACKET => \T_CLOSE_CURLY_BRACKET, + \T_OPEN_SQUARE_BRACKET => \T_CLOSE_SQUARE_BRACKET, + ); + } + + $tokens = $phpcsFile->getTokens(); + + // If no variable at all was found, then it's definitely a no-no. + $hasVariable = $phpcsFile->findNext(\T_VARIABLE, $start, $end); + if ($hasVariable === false) { + return false; + } + + // Check if the variable found is at the right level. Deeper levels are always an error. + if (isset($tokens[$hasVariable]['nested_parenthesis']) + && \count($tokens[$hasVariable]['nested_parenthesis']) !== $targetNestingLevel + ) { + return false; + } + + // Ok, so the first variable is at the right level, now are there any + // blacklisted tokens within the empty() ? + $hasBadToken = $phpcsFile->findNext($tokenBlackList, $start, $end); + if ($hasBadToken === false) { + return true; + } + + // If there are also bracket tokens, the blacklisted token might be part of a variable + // variable, but if there are no bracket tokens, we know we have an error. + $hasBrackets = $phpcsFile->findNext($bracketTokens, $start, $end); + if ($hasBrackets === false) { + return false; + } + + // Ok, we have both a blacklisted token as well as brackets, so we need to walk + // the tokens of the variable variable. + for ($i = $start; $i < $end; $i++) { + // If this is a bracket token, skip to the end of the bracketed expression. + if (isset($bracketTokens[$tokens[$i]['code']], $tokens[$i]['bracket_closer'])) { + $i = $tokens[$i]['bracket_closer']; + continue; + } + + // If it's a blacklisted token, not within brackets, we have an error. + if (isset($tokenBlackList[$tokens[$i]['code']])) { + return false; + } + } + + return true; + } + + /** + * Determine whether a T_MINUS/T_PLUS token is a unary operator. + * + * N.B.: This is a back-fill for a new method which is expected to go into + * PHP_CodeSniffer 3.5.0. + * Once that method has been merged into PHPCS, this one should be moved + * to the PHPCSHelper.php file. + * + * @since 9.2.0 + * + * @codeCoverageIgnore Method as pulled upstream is accompanied by unit tests. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the plus/minus token. + * + * @return bool True if the token passed is a unary operator. + * False otherwise or if the token is not a T_PLUS/T_MINUS token. + */ + public static function isUnaryPlusMinus(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]) === false + || ($tokens[$stackPtr]['code'] !== \T_PLUS + && $tokens[$stackPtr]['code'] !== \T_MINUS) + ) { + return false; + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next === false) { + // Live coding or parse error. + return false; + } + + if (isset(Tokens::$operators[$tokens[$next]['code']]) === true) { + // Next token is an operator, so this is not a unary. + return false; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + if ($tokens[$prev]['code'] === \T_RETURN) { + // Just returning a positive/negative value; eg. (return -1). + return true; + } + + if (isset(Tokens::$operators[$tokens[$prev]['code']]) === true) { + // Just trying to operate on a positive/negative value; eg. ($var * -1). + return true; + } + + if (isset(Tokens::$comparisonTokens[$tokens[$prev]['code']]) === true) { + // Just trying to compare a positive/negative value; eg. ($var === -1). + return true; + } + + if (isset(Tokens::$booleanOperators[$tokens[$prev]['code']]) === true) { + // Just trying to compare a positive/negative value; eg. ($var || -1 === $b). + return true; + } + + if (isset(Tokens::$assignmentTokens[$tokens[$prev]['code']]) === true) { + // Just trying to assign a positive/negative value; eg. ($var = -1). + return true; + } + + if (isset(Tokens::$castTokens[$tokens[$prev]['code']]) === true) { + // Just casting a positive/negative value; eg. (string) -$var. + return true; + } + + // Other indicators that a plus/minus sign is a unary operator. + $invalidTokens = array( + \T_COMMA => true, + \T_OPEN_PARENTHESIS => true, + \T_OPEN_SQUARE_BRACKET => true, + \T_OPEN_SHORT_ARRAY => true, + \T_COLON => true, + \T_INLINE_THEN => true, + \T_INLINE_ELSE => true, + \T_CASE => true, + \T_OPEN_CURLY_BRACKET => true, + \T_STRING_CONCAT => true, + ); + + if (isset($invalidTokens[$tokens[$prev]['code']]) === true) { + // Just trying to use a positive/negative value; eg. myFunction($var, -2). + return true; + } + + return false; + } + + /** + * Get the complete contents of a multi-line text string. + * + * N.B.: This is a back-fill for a new method which is expected to go into + * PHP_CodeSniffer 3.5.0. + * Once that method has been merged into PHPCS, this one should be moved + * to the PHPCSHelper.php file. + * + * @since 9.3.0 + * + * @codeCoverageIgnore Method as pulled upstream is accompanied by unit tests. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr Pointer to the first text string token + * of a multi-line text string or to a + * Nowdoc/Heredoc opener. + * @param bool $stripQuotes Optional. Whether to strip text delimiter + * quotes off the resulting text string. + * Defaults to true. + * + * @return string + * + * @throws \PHP_CodeSniffer_Exception If the specified position is not a + * valid text string token or if the + * token is not the first text string token. + */ + public function getCompleteTextString(File $phpcsFile, $stackPtr, $stripQuotes = true) + { + $tokens = $phpcsFile->getTokens(); + + // Must be the start of a text string token. + if ($tokens[$stackPtr]['code'] !== \T_START_HEREDOC + && $tokens[$stackPtr]['code'] !== \T_START_NOWDOC + && $tokens[$stackPtr]['code'] !== \T_CONSTANT_ENCAPSED_STRING + && $tokens[$stackPtr]['code'] !== \T_DOUBLE_QUOTED_STRING + ) { + throw new PHPCS_Exception('$stackPtr must be of type T_START_HEREDOC, T_START_NOWDOC, T_CONSTANT_ENCAPSED_STRING or T_DOUBLE_QUOTED_STRING'); + } + + if ($tokens[$stackPtr]['code'] === \T_CONSTANT_ENCAPSED_STRING + || $tokens[$stackPtr]['code'] === \T_DOUBLE_QUOTED_STRING + ) { + $prev = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$stackPtr]['code'] === $tokens[$prev]['code']) { + throw new PHPCS_Exception('$stackPtr must be the start of the text string'); + } + } + + switch ($tokens[$stackPtr]['code']) { + case \T_START_HEREDOC: + $stripQuotes = false; + $targetType = \T_HEREDOC; + $current = ($stackPtr + 1); + break; + + case \T_START_NOWDOC: + $stripQuotes = false; + $targetType = \T_NOWDOC; + $current = ($stackPtr + 1); + break; + + default: + $targetType = $tokens[$stackPtr]['code']; + $current = $stackPtr; + break; + } + + $string = ''; + do { + $string .= $tokens[$current]['content']; + ++$current; + } while ($tokens[$current]['code'] === $targetType); + + if ($stripQuotes === true) { + return $this->stripQuotes($string); + } + + return $string; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/ForbiddenAbstractPrivateMethodsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/ForbiddenAbstractPrivateMethodsSniff.php new file mode 100644 index 00000000..d0d74dfe --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/ForbiddenAbstractPrivateMethodsSniff.php @@ -0,0 +1,90 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Classes; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Abstract private methods are not allowed since PHP 5.1. + * + * Abstract private methods were supported between PHP 5.0.0 and PHP 5.0.4, but + * were then disallowed on the grounds that the behaviours of `private` and `abstract` + * are mutually exclusive. + * + * PHP version 5.1 + * + * @link https://www.php.net/manual/en/migration51.oop.php#migration51.oop-methods + * + * @since 9.2.0 + */ +class ForbiddenAbstractPrivateMethodsSniff extends Sniff +{ + + /** + * Valid scopes to check for abstract private methods. + * + * @since 9.2.0 + * + * @var array + */ + public $ooScopeTokens = array( + 'T_CLASS' => true, + 'T_TRAIT' => true, + 'T_ANON_CLASS' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + return array(\T_FUNCTION); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('5.1') === false) { + return; + } + + if ($this->validDirectScope($phpcsFile, $stackPtr, $this->ooScopeTokens) === false) { + // Function, not method. + return; + } + + $properties = $phpcsFile->getMethodProperties($stackPtr); + if ($properties['scope'] !== 'private' || $properties['is_abstract'] !== true) { + return; + } + + $phpcsFile->addError( + 'Abstract methods cannot be declared as private since PHP 5.1', + $stackPtr, + 'Found' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewAnonymousClassesSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewAnonymousClassesSniff.php new file mode 100644 index 00000000..572b6fcc --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewAnonymousClassesSniff.php @@ -0,0 +1,91 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Classes; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Anonymous classes are supported since PHP 7.0. + * + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/language.oop5.anonymous.php + * @link https://wiki.php.net/rfc/anonymous_classes + * + * @since 7.0.0 + */ +class NewAnonymousClassesSniff extends Sniff +{ + + /** + * Tokens which in various PHP versions indicate the `class` keyword. + * + * The dedicated anonymous class token is added from the `register()` + * method if the token is available. + * + * @since 7.1.2 + * + * @var array + */ + private $indicators = array( + \T_CLASS => \T_CLASS, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + if (\defined('T_ANON_CLASS')) { + $this->indicators[\T_ANON_CLASS] = \T_ANON_CLASS; + } + + return array(\T_NEW); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.6') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + if ($nextNonEmpty === false || isset($this->indicators[$tokens[$nextNonEmpty]['code']]) === false) { + return; + } + + // Still here ? In that case, it is an anonymous class. + $phpcsFile->addError( + 'Anonymous classes are not supported in PHP 5.6 or earlier', + $stackPtr, + 'Found' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewClassesSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewClassesSniff.php new file mode 100644 index 00000000..19e5e439 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewClassesSniff.php @@ -0,0 +1,913 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Classes; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect use of new PHP native classes. + * + * The sniff analyses the following constructs to find usage of new classes: + * - Class instantiation using the `new` keyword. + * - (Anonymous) Class declarations to detect new classes being extended by userland classes. + * - Static use of class properties, constants or functions using the double colon. + * - Function/closure declarations to detect new classes used as parameter type declarations. + * - Function/closure declarations to detect new classes used as return type declarations. + * - Try/catch statements to detect new exception classes being caught. + * + * PHP version All + * + * @since 5.5 + * @since 5.6 Now extends the base `Sniff` class. + * @since 7.1.0 Now extends the `AbstractNewFeatureSniff` class. + */ +class NewClassesSniff extends AbstractNewFeatureSniff +{ + + /** + * A list of new classes, not present in older versions. + * + * The array lists : version number with false (not present) or true (present). + * If's sufficient to list the first version where the class appears. + * + * @since 5.5 + * + * @var array(string => array(string => bool)) + */ + protected $newClasses = array( + 'ArrayObject' => array( + '4.4' => false, + '5.0' => true, + ), + 'ArrayIterator' => array( + '4.4' => false, + '5.0' => true, + ), + 'CachingIterator' => array( + '4.4' => false, + '5.0' => true, + ), + 'DirectoryIterator' => array( + '4.4' => false, + '5.0' => true, + ), + 'RecursiveDirectoryIterator' => array( + '4.4' => false, + '5.0' => true, + ), + 'RecursiveIteratorIterator' => array( + '4.4' => false, + '5.0' => true, + ), + 'php_user_filter' => array( + '4.4' => false, + '5.0' => true, + ), + 'tidy' => array( + '4.4' => false, + '5.0' => true, + ), + + 'SimpleXMLElement' => array( + '5.0.0' => false, + '5.0.1' => true, + ), + 'tidyNode' => array( + '5.0.0' => false, + '5.0.1' => true, + ), + + 'libXMLError' => array( + '5.0' => false, + '5.1' => true, + ), + 'PDO' => array( + '5.0' => false, + '5.1' => true, + ), + 'PDOStatement' => array( + '5.0' => false, + '5.1' => true, + ), + 'AppendIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'EmptyIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'FilterIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'InfiniteIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'IteratorIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'LimitIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'NoRewindIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'ParentIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'RecursiveArrayIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'RecursiveCachingIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'RecursiveFilterIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'SimpleXMLIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'SplFileObject' => array( + '5.0' => false, + '5.1' => true, + ), + 'XMLReader' => array( + '5.0' => false, + '5.1' => true, + ), + + 'SplFileInfo' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'SplTempFileObject' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'XMLWriter' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + + 'DateTime' => array( + '5.1' => false, + '5.2' => true, + ), + 'DateTimeZone' => array( + '5.1' => false, + '5.2' => true, + ), + 'RegexIterator' => array( + '5.1' => false, + '5.2' => true, + ), + 'RecursiveRegexIterator' => array( + '5.1' => false, + '5.2' => true, + ), + 'ReflectionFunctionAbstract' => array( + '5.1' => false, + '5.2' => true, + ), + 'ZipArchive' => array( + '5.1' => false, + '5.2' => true, + ), + + 'Closure' => array( + '5.2' => false, + '5.3' => true, + ), + 'DateInterval' => array( + '5.2' => false, + '5.3' => true, + ), + 'DatePeriod' => array( + '5.2' => false, + '5.3' => true, + ), + 'finfo' => array( + '5.2' => false, + '5.3' => true, + ), + 'Collator' => array( + '5.2' => false, + '5.3' => true, + ), + 'NumberFormatter' => array( + '5.2' => false, + '5.3' => true, + ), + 'Locale' => array( + '5.2' => false, + '5.3' => true, + ), + 'Normalizer' => array( + '5.2' => false, + '5.3' => true, + ), + 'MessageFormatter' => array( + '5.2' => false, + '5.3' => true, + ), + 'IntlDateFormatter' => array( + '5.2' => false, + '5.3' => true, + ), + 'Phar' => array( + '5.2' => false, + '5.3' => true, + ), + 'PharData' => array( + '5.2' => false, + '5.3' => true, + ), + 'PharFileInfo' => array( + '5.2' => false, + '5.3' => true, + ), + 'FilesystemIterator' => array( + '5.2' => false, + '5.3' => true, + ), + 'GlobIterator' => array( + '5.2' => false, + '5.3' => true, + ), + 'MultipleIterator' => array( + '5.2' => false, + '5.3' => true, + ), + 'RecursiveTreeIterator' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplDoublyLinkedList' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplFixedArray' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplHeap' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplMaxHeap' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplMinHeap' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplObjectStorage' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplPriorityQueue' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplQueue' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplStack' => array( + '5.2' => false, + '5.3' => true, + ), + + 'ResourceBundle' => array( + '5.3.1' => false, + '5.3.2' => true, + ), + + 'CallbackFilterIterator' => array( + '5.3' => false, + '5.4' => true, + ), + 'RecursiveCallbackFilterIterator' => array( + '5.3' => false, + '5.4' => true, + ), + 'ReflectionZendExtension' => array( + '5.3' => false, + '5.4' => true, + ), + 'SessionHandler' => array( + '5.3' => false, + '5.4' => true, + ), + 'SNMP' => array( + '5.3' => false, + '5.4' => true, + ), + 'Transliterator' => array( + '5.3' => false, + '5.4' => true, + ), + 'Spoofchecker' => array( + '5.3' => false, + '5.4' => true, + ), + + 'Generator' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLFile' => array( + '5.4' => false, + '5.5' => true, + ), + 'DateTimeImmutable' => array( + '5.4' => false, + '5.5' => true, + ), + 'IntlCalendar' => array( + '5.4' => false, + '5.5' => true, + ), + 'IntlGregorianCalendar' => array( + '5.4' => false, + '5.5' => true, + ), + 'IntlTimeZone' => array( + '5.4' => false, + '5.5' => true, + ), + 'IntlBreakIterator' => array( + '5.4' => false, + '5.5' => true, + ), + 'IntlRuleBasedBreakIterator' => array( + '5.4' => false, + '5.5' => true, + ), + 'IntlCodePointBreakIterator' => array( + '5.4' => false, + '5.5' => true, + ), + 'UConverter' => array( + '5.4' => false, + '5.5' => true, + ), + + 'GMP' => array( + '5.5' => false, + '5.6' => true, + ), + + 'IntlChar' => array( + '5.6' => false, + '7.0' => true, + ), + 'ReflectionType' => array( + '5.6' => false, + '7.0' => true, + ), + 'ReflectionGenerator' => array( + '5.6' => false, + '7.0' => true, + ), + + 'ReflectionClassConstant' => array( + '7.0' => false, + '7.1' => true, + ), + + 'FFI' => array( + '7.3' => false, + '7.4' => true, + ), + 'FFI\CData' => array( + '7.3' => false, + '7.4' => true, + ), + 'FFI\CType' => array( + '7.3' => false, + '7.4' => true, + ), + 'ReflectionReference' => array( + '7.3' => false, + '7.4' => true, + ), + 'WeakReference' => array( + '7.3' => false, + '7.4' => true, + ), + ); + + /** + * A list of new Exception classes, not present in older versions. + * + * The array lists : version number with false (not present) or true (present). + * If's sufficient to list the first version where the class appears. + * + * {@internal Classes listed here do not need to be added to the $newClasses + * property as well. + * This list is automatically added to the $newClasses property + * in the `register()` method.} + * + * {@internal Helper to update this list: https://3v4l.org/MhlUp} + * + * @since 7.1.4 + * + * @var array(string => array(string => bool)) + */ + protected $newExceptions = array( + 'com_exception' => array( + '4.4' => false, + '5.0' => true, + ), + 'DOMException' => array( + '4.4' => false, + '5.0' => true, + ), + 'Exception' => array( + // According to the docs introduced in PHP 5.1, but this appears to be. + // an error. Class was introduced with try/catch keywords in PHP 5.0. + '4.4' => false, + '5.0' => true, + ), + 'ReflectionException' => array( + '4.4' => false, + '5.0' => true, + ), + 'SoapFault' => array( + '4.4' => false, + '5.0' => true, + ), + 'SQLiteException' => array( + '4.4' => false, + '5.0' => true, + ), + + 'ErrorException' => array( + '5.0' => false, + '5.1' => true, + ), + 'BadFunctionCallException' => array( + '5.0' => false, + '5.1' => true, + ), + 'BadMethodCallException' => array( + '5.0' => false, + '5.1' => true, + ), + 'DomainException' => array( + '5.0' => false, + '5.1' => true, + ), + 'InvalidArgumentException' => array( + '5.0' => false, + '5.1' => true, + ), + 'LengthException' => array( + '5.0' => false, + '5.1' => true, + ), + 'LogicException' => array( + '5.0' => false, + '5.1' => true, + ), + 'mysqli_sql_exception' => array( + '5.0' => false, + '5.1' => true, + ), + 'OutOfBoundsException' => array( + '5.0' => false, + '5.1' => true, + ), + 'OutOfRangeException' => array( + '5.0' => false, + '5.1' => true, + ), + 'OverflowException' => array( + '5.0' => false, + '5.1' => true, + ), + 'PDOException' => array( + '5.0' => false, + '5.1' => true, + ), + 'RangeException' => array( + '5.0' => false, + '5.1' => true, + ), + 'RuntimeException' => array( + '5.0' => false, + '5.1' => true, + ), + 'UnderflowException' => array( + '5.0' => false, + '5.1' => true, + ), + 'UnexpectedValueException' => array( + '5.0' => false, + '5.1' => true, + ), + + 'PharException' => array( + '5.2' => false, + '5.3' => true, + ), + + 'SNMPException' => array( + '5.3' => false, + '5.4' => true, + ), + + 'IntlException' => array( + '5.4' => false, + '5.5' => true, + ), + + 'Error' => array( + '5.6' => false, + '7.0' => true, + ), + 'ArithmeticError' => array( + '5.6' => false, + '7.0' => true, + ), + 'AssertionError' => array( + '5.6' => false, + '7.0' => true, + ), + 'DivisionByZeroError' => array( + '5.6' => false, + '7.0' => true, + ), + 'ParseError' => array( + '5.6' => false, + '7.0' => true, + ), + 'TypeError' => array( + '5.6' => false, + '7.0' => true, + ), + 'ClosedGeneratorException' => array( + '5.6' => false, + '7.0' => true, + ), + 'UI\Exception\InvalidArgumentException' => array( + '5.6' => false, + '7.0' => true, + ), + 'UI\Exception\RuntimeException' => array( + '5.6' => false, + '7.0' => true, + ), + + 'ArgumentCountError' => array( + '7.0' => false, + '7.1' => true, + ), + + 'SodiumException' => array( + '7.1' => false, + '7.2' => true, + ), + + 'CompileError' => array( + '7.2' => false, + '7.3' => true, + ), + 'JsonException' => array( + '7.2' => false, + '7.3' => true, + ), + + 'FFI\Exception' => array( + '7.3' => false, + '7.4' => true, + ), + 'FFI\ParserException' => array( + '7.3' => false, + '7.4' => true, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * @since 7.0.3 - Now also targets the `class` keyword to detect extended classes. + * - Now also targets double colons to detect static class use. + * @since 7.1.4 - Now also targets anonymous classes to detect extended classes. + * - Now also targets functions/closures to detect new classes used + * as parameter type declarations. + * - Now also targets the `catch` control structure to detect new + * exception classes being caught. + * @since 8.2.0 Now also targets the `T_RETURN_TYPE` token to detect new classes used + * as return type declarations. + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of class names. + $this->newClasses = $this->arrayKeysToLowercase($this->newClasses); + $this->newExceptions = $this->arrayKeysToLowercase($this->newExceptions); + + // Add the Exception classes to the Classes list. + $this->newClasses = array_merge($this->newClasses, $this->newExceptions); + + $targets = array( + \T_NEW, + \T_CLASS, + \T_DOUBLE_COLON, + \T_FUNCTION, + \T_CLOSURE, + \T_CATCH, + ); + + if (\defined('T_ANON_CLASS')) { + $targets[] = \T_ANON_CLASS; + } + + if (\defined('T_RETURN_TYPE')) { + $targets[] = \T_RETURN_TYPE; + } + + return $targets; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$stackPtr]['type']) { + case 'T_FUNCTION': + case 'T_CLOSURE': + $this->processFunctionToken($phpcsFile, $stackPtr); + + // Deal with older PHPCS version which don't recognize return type hints + // as well as newer PHPCS versions (3.3.0+) where the tokenization has changed. + $returnTypeHint = $this->getReturnTypeHintToken($phpcsFile, $stackPtr); + if ($returnTypeHint !== false) { + $this->processReturnTypeToken($phpcsFile, $returnTypeHint); + } + break; + + case 'T_CATCH': + $this->processCatchToken($phpcsFile, $stackPtr); + break; + + case 'T_RETURN_TYPE': + $this->processReturnTypeToken($phpcsFile, $stackPtr); + break; + + default: + $this->processSingularToken($phpcsFile, $stackPtr); + break; + } + } + + + /** + * Processes this test for when a token resulting in a singular class name is encountered. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + private function processSingularToken(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $FQClassName = ''; + + if ($tokens[$stackPtr]['type'] === 'T_NEW') { + $FQClassName = $this->getFQClassNameFromNewToken($phpcsFile, $stackPtr); + + } elseif ($tokens[$stackPtr]['type'] === 'T_CLASS' || $tokens[$stackPtr]['type'] === 'T_ANON_CLASS') { + $FQClassName = $this->getFQExtendedClassName($phpcsFile, $stackPtr); + + } elseif ($tokens[$stackPtr]['type'] === 'T_DOUBLE_COLON') { + $FQClassName = $this->getFQClassNameFromDoubleColonToken($phpcsFile, $stackPtr); + } + + if ($FQClassName === '') { + return; + } + + $className = substr($FQClassName, 1); // Remove global namespace indicator. + $classNameLc = strtolower($className); + + if (isset($this->newClasses[$classNameLc]) === false) { + return; + } + + $itemInfo = array( + 'name' => $className, + 'nameLc' => $classNameLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Processes this test for when a function token is encountered. + * + * - Detect new classes when used as a parameter type declaration. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + private function processFunctionToken(File $phpcsFile, $stackPtr) + { + // Retrieve typehints stripped of global NS indicator and/or nullable indicator. + $typeHints = $this->getTypeHintsFromFunctionDeclaration($phpcsFile, $stackPtr); + if (empty($typeHints) || \is_array($typeHints) === false) { + return; + } + + foreach ($typeHints as $hint) { + + $typeHintLc = strtolower($hint); + + if (isset($this->newClasses[$typeHintLc]) === true) { + $itemInfo = array( + 'name' => $hint, + 'nameLc' => $typeHintLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + } + } + + + /** + * Processes this test for when a catch token is encountered. + * + * - Detect exceptions when used in a catch statement. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + private function processCatchToken(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Bow out during live coding. + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) { + return; + } + + $opener = $tokens[$stackPtr]['parenthesis_opener']; + $closer = ($tokens[$stackPtr]['parenthesis_closer'] + 1); + $name = ''; + $listen = array( + // Parts of a (namespaced) class name. + \T_STRING => true, + \T_NS_SEPARATOR => true, + // End/split tokens. + \T_VARIABLE => false, + \T_BITWISE_OR => false, + \T_CLOSE_CURLY_BRACKET => false, // Shouldn't be needed as we expect a var before this. + ); + + for ($i = ($opener + 1); $i < $closer; $i++) { + if (isset($listen[$tokens[$i]['code']]) === false) { + continue; + } + + if ($listen[$tokens[$i]['code']] === true) { + $name .= $tokens[$i]['content']; + continue; + } else { + if (empty($name) === true) { + // Weird, we should have a name by the time we encounter a variable or |. + // So this may be the closer. + continue; + } + + $name = ltrim($name, '\\'); + $nameLC = strtolower($name); + + if (isset($this->newExceptions[$nameLC]) === true) { + $itemInfo = array( + 'name' => $name, + 'nameLc' => $nameLC, + ); + $this->handleFeature($phpcsFile, $i, $itemInfo); + } + + // Reset for a potential multi-catch. + $name = ''; + } + } + } + + + /** + * Processes this test for when a return type token is encountered. + * + * - Detect new classes when used as a return type declaration. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + private function processReturnTypeToken(File $phpcsFile, $stackPtr) + { + $returnTypeHint = $this->getReturnTypeHintName($phpcsFile, $stackPtr); + if (empty($returnTypeHint)) { + return; + } + + $returnTypeHint = ltrim($returnTypeHint, '\\'); + $returnTypeHintLc = strtolower($returnTypeHint); + + if (isset($this->newClasses[$returnTypeHintLc]) === false) { + return; + } + + // Still here ? Then this is a return type declaration using a new class. + $itemInfo = array( + 'name' => $returnTypeHint, + 'nameLc' => $returnTypeHintLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newClasses[$itemInfo['nameLc']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The built-in class ' . parent::getErrorMsgTemplate(); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewConstVisibilitySniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewConstVisibilitySniff.php new file mode 100644 index 00000000..d2cb3feb --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewConstVisibilitySniff.php @@ -0,0 +1,80 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Classes; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Visibility for class constants is available since PHP 7.1. + * + * PHP version 7.1 + * + * @link https://wiki.php.net/rfc/class_const_visibility + * @link https://www.php.net/manual/en/language.oop5.constants.php#language.oop5.basic.class.this + * + * @since 7.0.7 + */ +class NewConstVisibilitySniff extends Sniff +{ + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.7 + * + * @return array + */ + public function register() + { + return array(\T_CONST); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.7 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true, null, true); + + // Is the previous token a visibility indicator ? + if ($prevToken === false || isset(Tokens::$scopeModifiers[$tokens[$prevToken]['code']]) === false) { + return; + } + + // Is this a class constant ? + if ($this->isClassConstant($phpcsFile, $stackPtr) === false) { + // This may be a constant declaration in the global namespace with visibility, + // but that would throw a parse error, i.e. not our concern. + return; + } + + $phpcsFile->addError( + 'Visibility indicators for class constants are not supported in PHP 7.0 or earlier. Found "%s const"', + $stackPtr, + 'Found', + array($tokens[$prevToken]['content']) + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewLateStaticBindingSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewLateStaticBindingSniff.php new file mode 100644 index 00000000..9658a76f --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewLateStaticBindingSniff.php @@ -0,0 +1,88 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Classes; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect use of late static binding as introduced in PHP 5.3. + * + * Checks for: + * - Late static binding as introduced in PHP 5.3. + * - Late static binding being used outside of class scope (unsupported). + * + * PHP version 5.3 + * + * @link https://www.php.net/manual/en/language.oop5.late-static-bindings.php + * @link https://wiki.php.net/rfc/lsb_parentself_forwarding + * + * @since 7.0.3 + * @since 9.0.0 Renamed from `LateStaticBindingSniff` to `NewLateStaticBindingSniff`. + */ +class NewLateStaticBindingSniff extends Sniff +{ + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.3 + * + * @return array + */ + public function register() + { + return array(\T_STATIC); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + if ($nextNonEmpty === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + if ($tokens[$nextNonEmpty]['code'] !== \T_DOUBLE_COLON) { + return; + } + + $inClass = $this->inClassScope($phpcsFile, $stackPtr, false); + + if ($inClass === true && $this->supportsBelow('5.2') === true) { + $phpcsFile->addError( + 'Late static binding is not supported in PHP 5.2 or earlier.', + $stackPtr, + 'Found' + ); + } + + if ($inClass === false) { + $phpcsFile->addError( + 'Late static binding is not supported outside of class scope.', + $stackPtr, + 'OutsideClassScope' + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewTypedPropertiesSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewTypedPropertiesSniff.php new file mode 100644 index 00000000..a609acc1 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewTypedPropertiesSniff.php @@ -0,0 +1,132 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Classes; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Typed class property declarations are available since PHP 7.4. + * + * PHP version 7.4 + * + * @link https://www.php.net/manual/en/migration74.new-features.php#migration74.new-features.core.typed-properties + * @link https://wiki.php.net/rfc/typed_properties_v2 + * + * @since 9.2.0 + */ +class NewTypedPropertiesSniff extends Sniff +{ + + /** + * Valid property modifier keywords. + * + * @since 9.2.0 + * + * @var array + */ + private $modifierKeywords = array( + \T_PRIVATE => \T_PRIVATE, + \T_PROTECTED => \T_PROTECTED, + \T_PUBLIC => \T_PUBLIC, + \T_STATIC => \T_STATIC, + \T_VAR => \T_VAR, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + return array(\T_VARIABLE); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->isClassProperty($phpcsFile, $stackPtr) === false) { + return; + } + + $find = $this->modifierKeywords; + $find += array( + \T_SEMICOLON => \T_SEMICOLON, + \T_OPEN_CURLY_BRACKET => \T_OPEN_CURLY_BRACKET, + ); + + $tokens = $phpcsFile->getTokens(); + $modifier = $phpcsFile->findPrevious($find, ($stackPtr - 1)); + if ($modifier === false + || $tokens[$modifier]['code'] === \T_SEMICOLON + || $tokens[$modifier]['code'] === \T_OPEN_CURLY_BRACKET + ) { + // Parse error. Ignore. + return; + } + + $type = $phpcsFile->findNext(Tokens::$emptyTokens, ($modifier + 1), null, true); + if ($tokens[$type]['code'] === \T_VARIABLE) { + return; + } + + // Still here ? In that case, this will be a typed property. + if ($this->supportsBelow('7.3') === true) { + $phpcsFile->addError( + 'Typed properties are not supported in PHP 7.3 or earlier', + $type, + 'Found' + ); + } + + if ($this->supportsAbove('7.4') === true) { + // Examine the type to verify it's valid. + if ($tokens[$type]['type'] === 'T_NULLABLE' + // Needed to support PHPCS < 3.5.0 which doesn't correct to the nullable token type yet. + || $tokens[$type]['code'] === \T_INLINE_THEN + ) { + $type = $phpcsFile->findNext(Tokens::$emptyTokens, ($type + 1), null, true); + } + + $content = $tokens[$type]['content']; + if ($content === 'void' || $content === 'callable') { + $phpcsFile->addError( + '%s is not supported as a type declaration for properties', + $type, + 'InvalidType', + array($content) + ); + } + } + + $endOfStatement = $phpcsFile->findNext(\T_SEMICOLON, ($stackPtr + 1)); + if ($endOfStatement !== false) { + // Don't throw the same error multiple times for multi-property declarations. + return ($endOfStatement + 1); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/RemovedOrphanedParentSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/RemovedOrphanedParentSniff.php new file mode 100644 index 00000000..7ecfd6ca --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/RemovedOrphanedParentSniff.php @@ -0,0 +1,115 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Classes; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Using `parent` inside a class without parent is deprecated since PHP 7.4. + * + * This will throw a compile-time error in the future. Currently an error will only + * be generated if/when the parent is accessed at run-time. + * + * PHP version 7.4 + * + * @link https://www.php.net/manual/en/migration74.deprecated.php#migration74.deprecated.core.parent + * + * @since 9.2.0 + */ +class RemovedOrphanedParentSniff extends Sniff +{ + + /** + * Class scopes to check the class declaration. + * + * @since 9.2.0 + * + * @var array + */ + public $classScopeTokens = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + return array(\T_PARENT); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (empty($tokens[$stackPtr]['conditions']) === true) { + // Use within the global namespace. Not our concern. + return; + } + + /* + * Find the class within which this parent keyword is used. + */ + $conditions = $tokens[$stackPtr]['conditions']; + $conditions = array_reverse($conditions, true); + $classPtr = false; + + foreach ($conditions as $ptr => $type) { + if (isset($this->classScopeTokens[$tokens[$ptr]['type']])) { + $classPtr = $ptr; + break; + } + } + + if ($classPtr === false) { + // Use outside of a class scope. Not our concern. + return; + } + + if (isset($tokens[$classPtr]['scope_opener']) === false) { + // No scope opener known. Probably a parse error. + return; + } + + $extends = $phpcsFile->findNext(\T_EXTENDS, ($classPtr + 1), $tokens[$classPtr]['scope_opener']); + if ($extends !== false) { + // Class has a parent. + return; + } + + $phpcsFile->addError( + 'Using "parent" inside a class without parent is deprecated since PHP 7.4', + $stackPtr, + 'Deprecated' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/NewConstantsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/NewConstantsSniff.php new file mode 100644 index 00000000..27ec4217 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/NewConstantsSniff.php @@ -0,0 +1,3756 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Constants; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect use of new PHP native global constants. + * + * PHP version All + * + * @since 8.1.0 + */ +class NewConstantsSniff extends AbstractNewFeatureSniff +{ + + /** + * A list of new PHP Constants, not present in older versions. + * + * The array lists : version number with false (not present) or true (present). + * If's sufficient to list the first version where the constant appears. + * + * Note: PHP constants are case-sensitive! + * + * @since 8.1.0 + * + * @var array(string => array(string => bool)) + */ + protected $newConstants = array( + 'E_STRICT' => array( + '4.4' => false, + '5.0' => true, + ), + // Curl: + 'CURLOPT_FTP_USE_EPRT' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_NOSIGNAL' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_UNRESTRICTED_AUTH' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_BUFFERSIZE' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_HTTPAUTH' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_PROXYPORT' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_PROXYTYPE' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_SSLCERTTYPE' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_HTTP200ALIASES' => array( + '4.4' => false, + '5.0' => true, + ), + // OpenSSL: + 'OPENSSL_ALGO_MD2' => array( + '4.4' => false, + '5.0' => true, + ), + 'OPENSSL_ALGO_MD4' => array( + '4.4' => false, + '5.0' => true, + ), + 'OPENSSL_ALGO_MD5' => array( + '4.4' => false, + '5.0' => true, + ), + 'OPENSSL_ALGO_SHA1' => array( + '4.4' => false, + '5.0' => true, + ), + 'OPENSSL_ALGO_DSS1' => array( + '4.4' => false, + '5.0' => true, + ), + // Tokenizer: + 'T_ABSTRACT' => array( + '4.4' => false, + '5.0' => true, + ), + 'T_CATCH' => array( + '4.4' => false, + '5.0' => true, + ), + + 'SORT_LOCALE_STRING' => array( + '5.0.1' => false, + '5.0.2' => true, + ), + 'PHP_EOL' => array( + '5.0.1' => false, + '5.0.2' => true, + ), + + 'PHP_INT_MAX' => array( + '5.0.4' => false, + '5.0.5' => true, + ), + 'PHP_INT_SIZE' => array( + '5.0.4' => false, + '5.0.5' => true, + ), + + '__COMPILER_HALT_OFFSET__' => array( + '5.0' => false, + '5.1' => true, + ), + 'GLOB_ERR' => array( + '5.0' => false, + '5.1' => true, + ), + // Curl: + 'CURLOPT_AUTOREFERER' => array( + '5.0' => false, + '5.1' => true, + ), + 'CURLOPT_BINARYTRANSFER' => array( + '5.0' => false, + '5.1' => true, + ), + 'CURLOPT_COOKIESESSION' => array( + '5.0' => false, + '5.1' => true, + ), + 'CURLOPT_FTPSSLAUTH' => array( + '5.0' => false, + '5.1' => true, + ), + 'CURLOPT_PROXYAUTH' => array( + '5.0' => false, + '5.1' => true, + ), + 'CURLOPT_TIMECONDITION' => array( + '5.0' => false, + '5.1' => true, + ), + // POSIX: + 'POSIX_F_OK' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_R_OK' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_W_OK' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_X_OK' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_S_IFBLK' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_S_IFCHR' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_S_IFIFO' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_S_IFREG' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_S_IFSOCK' => array( + '5.0' => false, + '5.1' => true, + ), + // Streams: + 'STREAM_IPPROTO_ICMP' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_IPPROTO_IP' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_IPPROTO_RAW' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_IPPROTO_TCP' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_IPPROTO_UDP' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_PF_INET' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_PF_INET6' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_PF_UNIX' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_SOCK_DGRAM' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_SOCK_RAW' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_SOCK_RDM' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_SOCK_SEQPACKET' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_SOCK_STREAM' => array( + '5.0' => false, + '5.1' => true, + ), + // Tokenizer: + 'T_HALT_COMPILER' => array( + '5.0' => false, + '5.1' => true, + ), + + // Date/Time: + 'DATE_ATOM' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_COOKIE' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_ISO8601' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_RFC822' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_RFC850' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_RFC1036' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_RFC1123' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_RFC2822' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_RFC3339' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_RSS' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_W3C' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + + // Date/Time: + 'SUNFUNCS_RET_TIMESTAMP' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'SUNFUNCS_RET_STRING' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'SUNFUNCS_RET_DOUBLE' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + // XSL: + 'LIBXSLT_VERSION' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'LIBXSLT_DOTTED_VERSION' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'LIBEXSLT_VERSION' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'LIBEXSLT_DOTTED_VERSION' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + // URL: + 'PHP_URL_SCHEME' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_URL_HOST' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_URL_PORT' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_URL_USER' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_URL_PASS' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_URL_PATH' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_URL_QUERY' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_URL_FRAGMENT' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_QUERY_RFC1738' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_QUERY_RFC3986' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + + // Curl: + 'CURLINFO_HEADER_OUT' => array( + '5.1.2' => false, + '5.1.3' => true, + ), + + // Core: + 'E_RECOVERABLE_ERROR' => array( + '5.1' => false, + '5.2' => true, + ), + // Math: + 'M_EULER' => array( + '5.1' => false, + '5.2' => true, + ), + 'M_LNPI' => array( + '5.1' => false, + '5.2' => true, + ), + 'M_SQRT3' => array( + '5.1' => false, + '5.2' => true, + ), + 'M_SQRTPI' => array( + '5.1' => false, + '5.2' => true, + ), + 'PATHINFO_FILENAME' => array( + '5.1' => false, + '5.2' => true, + ), + 'UPLOAD_ERR_EXTENSION' => array( + '5.1' => false, + '5.2' => true, + ), + // Curl: + 'CURLE_FILESIZE_EXCEEDED' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLE_FTP_SSL_FAILED' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLE_LDAP_INVALID_URL' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLFTPAUTH_DEFAULT' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLFTPAUTH_SSL' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLFTPAUTH_TLS' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLFTPSSL_ALL' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLFTPSSL_CONTROL' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLFTPSSL_NONE' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLFTPSSL_TRY' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLOPT_FTP_SSL' => array( + '5.1' => false, + '5.2' => true, + ), + // Ming: + 'SWFTEXTFIELD_USEFONT' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWFTEXTFIELD_AUTOSIZE' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_NOT_COMPRESSED' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_ADPCM_COMPRESSED' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_MP3_COMPRESSED' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_NOT_COMPRESSED_LE' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_NELLY_COMPRESSED' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_5KHZ' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_11KHZ' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_22KHZ' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_44KHZ' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_8BITS' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_16BITS' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_MONO' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_STEREO' => array( + '5.1' => false, + '5.2' => true, + ), + // OpenSSL: + 'OPENSSL_KEYTYPE_EC' => array( + '5.1' => false, + '5.2' => true, + ), + 'OPENSSL_VERSION_NUMBER' => array( + '5.1' => false, + '5.2' => true, + ), + 'OPENSSL_VERSION_TEXT' => array( + '5.1' => false, + '5.2' => true, + ), + // PCRE: + 'PREG_BACKTRACK_LIMIT_ERROR' => array( + '5.1' => false, + '5.2' => true, + ), + 'PREG_BAD_UTF8_ERROR' => array( + '5.1' => false, + '5.2' => true, + ), + 'PREG_INTERNAL_ERROR' => array( + '5.1' => false, + '5.2' => true, + ), + 'PREG_NO_ERROR' => array( + '5.1' => false, + '5.2' => true, + ), + 'PREG_RECURSION_LIMIT_ERROR' => array( + '5.1' => false, + '5.2' => true, + ), + // Snmp: + 'SNMP_OID_OUTPUT_FULL' => array( + '5.1' => false, + '5.2' => true, + ), + 'SNMP_OID_OUTPUT_NUMERIC' => array( + '5.1' => false, + '5.2' => true, + ), + // Semaphore: + 'MSG_EAGAIN' => array( + '5.1' => false, + '5.2' => true, + ), + 'MSG_ENOMSG' => array( + '5.1' => false, + '5.2' => true, + ), + + // Curl: + 'CURLOPT_TCP_NODELAY' => array( + '5.2.0' => false, + '5.2.1' => true, + ), + + // Stream: + 'STREAM_SHUT_RD' => array( + '5.2.0' => false, + '5.2.1' => true, + ), + 'STREAM_SHUT_WR' => array( + '5.2.0' => false, + '5.2.1' => true, + ), + 'STREAM_SHUT_RDWR' => array( + '5.2.0' => false, + '5.2.1' => true, + ), + + 'GMP_VERSION' => array( + '5.2.1' => false, + '5.2.2' => true, + ), + + // Curl: + 'CURLOPT_TIMEOUT_MS' => array( + '5.2.2' => false, + '5.2.3' => true, + ), + 'CURLOPT_CONNECTTIMEOUT_MS' => array( + '5.2.2' => false, + '5.2.3' => true, + ), + + // Curl: + 'CURLOPT_PRIVATE' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + 'CURLINFO_PRIVATE' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + // GD: + 'GD_VERSION' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + 'GD_MAJOR_VERSION' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + 'GD_MINOR_VERSION' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + 'GD_RELEASE_VERSION' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + 'GD_EXTRA_VERSION' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + // PCRE: + 'PCRE_VERSION' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + + 'PHP_MAJOR_VERSION' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'PHP_MINOR_VERSION' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'PHP_RELEASE_VERSION' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'PHP_VERSION_ID' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'PHP_EXTRA_VERSION' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'PHP_ZTS' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'PHP_DEBUG' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'FILE_BINARY' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'FILE_TEXT' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + // Sockets: + 'TCP_NODELAY' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + + // Curl: + 'CURLOPT_PROTOCOLS' => array( + '5.2.9' => false, + '5.2.10' => true, + ), + 'CURLOPT_REDIR_PROTOCOLS' => array( + '5.2.9' => false, + '5.2.10' => true, + ), + 'CURLPROXY_SOCKS4' => array( + '5.2.9' => false, + '5.2.10' => true, + ), + + // Libxml: + 'LIBXML_PARSEHUGE' => array( + '5.2.11' => false, + '5.2.12' => true, + ), + + // Core: + 'ENT_IGNORE' => array( + '5.2' => false, + '5.3' => true, + ), + 'E_DEPRECATED' => array( + '5.2' => false, + '5.3' => true, + ), + 'E_USER_DEPRECATED' => array( + '5.2' => false, + '5.3' => true, + ), + 'INI_SCANNER_NORMAL' => array( + '5.2' => false, + '5.3' => true, + ), + 'INI_SCANNER_RAW' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_MAXPATHLEN' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_NT_DOMAIN_CONTROLLER' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_NT_SERVER' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_NT_WORKSTATION' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_BUILD' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_MAJOR' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_MINOR' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_PLATFORM' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_PRODUCTTYPE' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_SP_MAJOR' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_SP_MINOR' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_SUITEMASK' => array( + '5.2' => false, + '5.3' => true, + ), + // Curl: + 'CURLINFO_CERTINFO' => array( + '5.2' => false, + '5.3' => true, + ), + 'CURLOPT_PROGRESSFUNCTION' => array( + '5.2' => false, + '5.3' => true, + ), + 'CURLE_SSH' => array( + '5.2' => false, + '5.3' => true, + ), + // GD: + 'IMG_FILTER_PIXELATE' => array( + '5.2' => false, + '5.3' => true, + ), + 'IMAGETYPE_ICO' => array( + '5.2' => false, + '5.3' => true, + ), + // Fileinfo: + 'FILEINFO_MIME_TYPE' => array( + '5.2' => false, + '5.3' => true, + ), + 'FILEINFO_MIME_ENCODING' => array( + '5.2' => false, + '5.3' => true, + ), + // JSON: + 'JSON_ERROR_CTRL_CHAR' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_ERROR_DEPTH' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_ERROR_NONE' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_ERROR_STATE_MISMATCH' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_ERROR_SYNTAX' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_FORCE_OBJECT' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_HEX_TAG' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_HEX_AMP' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_HEX_APOS' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_HEX_QUOT' => array( + '5.2' => false, + '5.3' => true, + ), + // LDAP: + 'LDAP_OPT_NETWORK_TIMEOUT' => array( + '5.2' => false, + '5.3' => true, + ), + // Libxml: + 'LIBXML_LOADED_VERSION' => array( + '5.2' => false, + '5.3' => true, + ), + // Math: + 'PHP_ROUND_HALF_UP' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_ROUND_HALF_DOWN' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_ROUND_HALF_EVEN' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_ROUND_HALF_ODD' => array( + '5.2' => false, + '5.3' => true, + ), + // Mysqli + 'MYSQLI_OPT_INT_AND_FLOAT_NATIVE' => array( + '5.2' => false, + '5.3' => true, + ), + 'MYSQLI_OPT_NET_CMD_BUFFER_SIZE' => array( + '5.2' => false, + '5.3' => true, + ), + 'MYSQLI_OPT_NET_READ_BUFFER_SIZE' => array( + '5.2' => false, + '5.3' => true, + ), + 'MYSQLI_OPT_SSL_VERIFY_SERVER_CERT' => array( + '5.2' => false, + '5.3' => true, + ), + // OCI8: + 'OCI_CRED_EXT' => array( + '5.2' => false, + '5.3' => true, + ), + // PCRE: + 'PREG_BAD_UTF8_OFFSET_ERROR' => array( + '5.2' => false, + '5.3' => true, + ), + // PCNTL: + 'BUS_ADRALN' => array( + '5.2' => false, + '5.3' => true, + ), + 'BUS_ADRERR' => array( + '5.2' => false, + '5.3' => true, + ), + 'BUS_OBJERR' => array( + '5.2' => false, + '5.3' => true, + ), + 'CLD_CONTIUNED' => array( + '5.2' => false, + '5.3' => true, + ), + 'CLD_DUMPED' => array( + '5.2' => false, + '5.3' => true, + ), + 'CLD_EXITED' => array( + '5.2' => false, + '5.3' => true, + ), + 'CLD_KILLED' => array( + '5.2' => false, + '5.3' => true, + ), + 'CLD_STOPPED' => array( + '5.2' => false, + '5.3' => true, + ), + 'CLD_TRAPPED' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_FLTDIV' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_FLTINV' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_FLTOVF' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_FLTRES' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_FLTSUB' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_FLTUND' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_INTDIV' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_INTOVF' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_BADSTK' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_COPROC' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_ILLADR' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_ILLOPC' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_ILLOPN' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_ILLTRP' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_PRVOPC' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_PRVREG' => array( + '5.2' => false, + '5.3' => true, + ), + 'POLL_ERR' => array( + '5.2' => false, + '5.3' => true, + ), + 'POLL_HUP' => array( + '5.2' => false, + '5.3' => true, + ), + 'POLL_IN' => array( + '5.2' => false, + '5.3' => true, + ), + 'POLL_MSG' => array( + '5.2' => false, + '5.3' => true, + ), + 'POLL_OUT' => array( + '5.2' => false, + '5.3' => true, + ), + 'POLL_PRI' => array( + '5.2' => false, + '5.3' => true, + ), + 'SEGV_ACCERR' => array( + '5.2' => false, + '5.3' => true, + ), + 'SEGV_MAPERR' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_ASYNCIO' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_KERNEL' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_MSGGQ' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_NOINFO' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_QUEUE' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_SIGIO' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_TIMER' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_TKILL' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_USER' => array( + '5.2' => false, + '5.3' => true, + ), + 'SIG_BLOCK' => array( + '5.2' => false, + '5.3' => true, + ), + 'SIG_SETMASK' => array( + '5.2' => false, + '5.3' => true, + ), + 'SIG_UNBLOCK' => array( + '5.2' => false, + '5.3' => true, + ), + 'TRAP_BRKPT' => array( + '5.2' => false, + '5.3' => true, + ), + 'TRAP_TRACE' => array( + '5.2' => false, + '5.3' => true, + ), + // Tokenizer: + 'T_DIR' => array( + '5.2' => false, + '5.3' => true, + ), + 'T_GOTO' => array( + '5.2' => false, + '5.3' => true, + ), + 'T_NAMESPACE' => array( + '5.2' => false, + '5.3' => true, + ), + 'T_NS_C' => array( + '5.2' => false, + '5.3' => true, + ), + 'T_NS_SEPARATOR' => array( + '5.2' => false, + '5.3' => true, + ), + 'T_USE' => array( + '5.2' => false, + '5.3' => true, + ), + + // OCI8: + 'OCI_NO_AUTO_COMMIT' => array( + '5.3.1' => false, + '5.3.2' => true, + ), + // OpenSSL: + 'OPENSSL_TLSEXT_SERVER_NAME' => array( + '5.3.1' => false, + '5.3.2' => true, + ), + + // JSON: + 'JSON_ERROR_UTF8' => array( + '5.3.2' => false, + '5.3.3' => true, + ), + 'JSON_NUMERIC_CHECK' => array( + '5.3.2' => false, + '5.3.3' => true, + ), + + 'DEBUG_BACKTRACE_IGNORE_ARGS' => array( + '5.3.5' => false, + '5.3.6' => true, + ), + + 'CURLINFO_REDIRECT_URL' => array( + '5.3.6' => false, + '5.3.7' => true, + ), + 'PHP_MANDIR' => array( + '5.3.6' => false, + '5.3.7' => true, + ), + + 'PHP_BINARY' => array( + '5.3' => false, + '5.4' => true, + ), + 'SORT_NATURAL' => array( + '5.3' => false, + '5.4' => true, + ), + 'SORT_FLAG_CASE' => array( + '5.3' => false, + '5.4' => true, + ), + 'ENT_HTML401' => array( + '5.3' => false, + '5.4' => true, + ), + 'ENT_XML1' => array( + '5.3' => false, + '5.4' => true, + ), + 'ENT_XHTML' => array( + '5.3' => false, + '5.4' => true, + ), + 'ENT_HTML5' => array( + '5.3' => false, + '5.4' => true, + ), + 'ENT_SUBSTITUTE' => array( + '5.3' => false, + '5.4' => true, + ), + 'ENT_DISALLOWED' => array( + '5.3' => false, + '5.4' => true, + ), + 'IPPROTO_IP' => array( + '5.3' => false, + '5.4' => true, + ), + 'IPPROTO_IPV6' => array( + '5.3' => false, + '5.4' => true, + ), + 'IPV6_MULTICAST_HOPS' => array( + '5.3' => false, + '5.4' => true, + ), + 'IPV6_MULTICAST_IF' => array( + '5.3' => false, + '5.4' => true, + ), + 'IPV6_MULTICAST_LOOP' => array( + '5.3' => false, + '5.4' => true, + ), + 'IP_MULTICAST_IF' => array( + '5.3' => false, + '5.4' => true, + ), + 'IP_MULTICAST_LOOP' => array( + '5.3' => false, + '5.4' => true, + ), + 'IP_MULTICAST_TTL' => array( + '5.3' => false, + '5.4' => true, + ), + 'MCAST_JOIN_GROUP' => array( + '5.3' => false, + '5.4' => true, + ), + 'MCAST_LEAVE_GROUP' => array( + '5.3' => false, + '5.4' => true, + ), + 'MCAST_BLOCK_SOURCE' => array( + '5.3' => false, + '5.4' => true, + ), + 'MCAST_UNBLOCK_SOURCE' => array( + '5.3' => false, + '5.4' => true, + ), + 'MCAST_JOIN_SOURCE_GROUP' => array( + '5.3' => false, + '5.4' => true, + ), + 'MCAST_LEAVE_SOURCE_GROUP' => array( + '5.3' => false, + '5.4' => true, + ), + // Curl: + 'CURLOPT_MAX_RECV_SPEED_LARGE' => array( + '5.3' => false, + '5.4' => true, + ), + 'CURLOPT_MAX_SEND_SPEED_LARGE' => array( + '5.3' => false, + '5.4' => true, + ), + // Directories: + 'SCANDIR_SORT_ASCENDING' => array( + '5.3' => false, + '5.4' => true, + ), + 'SCANDIR_SORT_DESCENDING' => array( + '5.3' => false, + '5.4' => true, + ), + 'SCANDIR_SORT_NONE' => array( + '5.3' => false, + '5.4' => true, + ), + // LibXML: + 'LIBXML_HTML_NODEFDTD' => array( + '5.3' => false, + '5.4' => true, + ), + 'LIBXML_HTML_NOIMPLIED' => array( + '5.3' => false, + '5.4' => true, + ), + 'LIBXML_PEDANTIC' => array( + '5.3' => false, + '5.4' => true, + ), + // OpenSSL: + 'OPENSSL_CIPHER_AES_128_CBC' => array( + '5.3' => false, + '5.4' => true, + ), + 'OPENSSL_CIPHER_AES_192_CBC' => array( + '5.3' => false, + '5.4' => true, + ), + 'OPENSSL_CIPHER_AES_256_CBC' => array( + '5.3' => false, + '5.4' => true, + ), + 'OPENSSL_RAW_DATA' => array( + '5.3' => false, + '5.4' => true, + ), + 'OPENSSL_ZERO_PADDING' => array( + '5.3' => false, + '5.4' => true, + ), + // Output buffering: + 'PHP_OUTPUT_HANDLER_CLEAN' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_CLEANABLE' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_DISABLED' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_FINAL' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_FLUSH' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_FLUSHABLE' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_REMOVABLE' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_STARTED' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_STDFLAGS' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_WRITE' => array( + '5.3' => false, + '5.4' => true, + ), + // Sessions: + 'PHP_SESSION_ACTIVE' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_SESSION_DISABLED' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_SESSION_NONE' => array( + '5.3' => false, + '5.4' => true, + ), + // Streams: + 'STREAM_META_ACCESS' => array( + '5.3' => false, + '5.4' => true, + ), + 'STREAM_META_GROUP' => array( + '5.3' => false, + '5.4' => true, + ), + 'STREAM_META_GROUP_NAME' => array( + '5.3' => false, + '5.4' => true, + ), + 'STREAM_META_OWNER' => array( + '5.3' => false, + '5.4' => true, + ), + 'STREAM_META_OWNER_NAME' => array( + '5.3' => false, + '5.4' => true, + ), + 'STREAM_META_TOUCH' => array( + '5.3' => false, + '5.4' => true, + ), + // Intl: + 'U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_CHECK_BIDI' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_CHECK_CONTEXTJ' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_NONTRANSITIONAL_TO_ASCII' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_NONTRANSITIONAL_TO_UNICODE' => array( + '5.3' => false, + '5.4' => true, + ), + 'INTL_IDNA_VARIANT_2003' => array( + '5.3' => false, + '5.4' => true, + ), + 'INTL_IDNA_VARIANT_UTS46' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_EMPTY_LABEL' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_LABEL_TOO_LONG' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_DOMAIN_NAME_TOO_LONG' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_LEADING_HYPHEN' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_TRAILING_HYPHEN' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_HYPHEN_3_4' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_LEADING_COMBINING_MARK' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_DISALLOWED' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_PUNYCODE' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_LABEL_HAS_DOT' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_INVALID_ACE_LABEL' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_BIDI' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_CONTEXTJ' => array( + '5.3' => false, + '5.4' => true, + ), + // Json: + 'JSON_PRETTY_PRINT' => array( + '5.3' => false, + '5.4' => true, + ), + 'JSON_UNESCAPED_SLASHES' => array( + '5.3' => false, + '5.4' => true, + ), + 'JSON_UNESCAPED_UNICODE' => array( + '5.3' => false, + '5.4' => true, + ), + 'JSON_BIGINT_AS_STRING' => array( + '5.3' => false, + '5.4' => true, + ), + 'JSON_OBJECT_AS_ARRAY' => array( + '5.3' => false, + '5.4' => true, + ), + // Snmp: + 'SNMP_OID_OUTPUT_SUFFIX' => array( + '5.3' => false, + '5.4' => true, + ), + 'SNMP_OID_OUTPUT_MODULE' => array( + '5.3' => false, + '5.4' => true, + ), + 'SNMP_OID_OUTPUT_UCD' => array( + '5.3' => false, + '5.4' => true, + ), + 'SNMP_OID_OUTPUT_NONE' => array( + '5.3' => false, + '5.4' => true, + ), + // Tokenizer: + 'T_INSTEADOF' => array( + '5.3' => false, + '5.4' => true, + ), + 'T_TRAIT' => array( + '5.3' => false, + '5.4' => true, + ), + 'T_TRAIT_C' => array( + '5.3' => false, + '5.4' => true, + ), + + // Curl: + 'CURLINFO_PRIMARY_IP' => array( + '5.4.6' => false, + '5.4.7' => true, + ), + 'CURLINFO_PRIMARY_PORT' => array( + '5.4.6' => false, + '5.4.7' => true, + ), + 'CURLINFO_LOCAL_IP' => array( + '5.4.6' => false, + '5.4.7' => true, + ), + 'CURLINFO_LOCAL_PORT' => array( + '5.4.6' => false, + '5.4.7' => true, + ), + + // OpenSSL: + 'OPENSSL_ALGO_RMD160' => array( + '5.4.7' => false, + '5.4.8' => true, + ), + 'OPENSSL_ALGO_SHA224' => array( + '5.4.7' => false, + '5.4.8' => true, + ), + 'OPENSSL_ALGO_SHA256' => array( + '5.4.7' => false, + '5.4.8' => true, + ), + 'OPENSSL_ALGO_SHA384' => array( + '5.4.7' => false, + '5.4.8' => true, + ), + 'OPENSSL_ALGO_SHA512' => array( + '5.4.7' => false, + '5.4.8' => true, + ), + + // Filter: + 'FILTER_VALIDATE_MAC' => array( + '5.4' => false, + '5.5' => true, + ), + // GD + 'IMG_AFFINE_TRANSLATE' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_AFFINE_SCALE' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_AFFINE_ROTATE' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_AFFINE_SHEAR_HORIZONTAL' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_AFFINE_SHEAR_VERTICAL' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_CROP_DEFAULT' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_CROP_TRANSPARENT' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_CROP_BLACK' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_CROP_WHITE' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_CROP_SIDES' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_FLIP_BOTH' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_FLIP_HORIZONTAL' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_FLIP_VERTICAL' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BELL' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BESSEL' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BILINEAR_FIXED' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BICUBIC' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BICUBIC_FIXED' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BLACKMAN' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BOX' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BSPLINE' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_CATMULLROM' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_GAUSSIAN' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_GENERALIZED_CUBIC' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_HERMITE' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_HAMMING' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_HANNING' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_MITCHELL' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_POWER' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_QUADRATIC' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_SINC' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_NEAREST_NEIGHBOUR' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_WEIGHTED4' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_TRIANGLE' => array( + '5.4' => false, + '5.5' => true, + ), + // JSON: + 'JSON_ERROR_RECURSION' => array( + '5.4' => false, + '5.5' => true, + ), + 'JSON_ERROR_INF_OR_NAN' => array( + '5.4' => false, + '5.5' => true, + ), + 'JSON_ERROR_UNSUPPORTED_TYPE' => array( + '5.4' => false, + '5.5' => true, + ), + 'JSON_PARTIAL_OUTPUT_ON_ERROR' => array( + '5.4' => false, + '5.5' => true, + ), + // MySQLi + 'MYSQLI_SERVER_PUBLIC_KEY' => array( + '5.4' => false, + '5.5' => true, + ), + // Curl: + 'CURLOPT_SHARE' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLOPT_SSL_OPTIONS' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLSSLOPT_ALLOW_BEAST' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLOPT_USERNAME' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_RESPONSE_CODE' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_HTTP_CONNECTCODE' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_HTTPAUTH_AVAIL' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_PROXYAUTH_AVAIL' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_OS_ERRNO' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_NUM_CONNECTS' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_SSL_ENGINES' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_COOKIELIST' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_FTP_ENTRY_PATH' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_APPCONNECT_TIME' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_CONDITION_UNMET' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_RTSP_CLIENT_CSEQ' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_RTSP_CSEQ_RECV' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_RTSP_SERVER_CSEQ' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_RTSP_SESSION_ID' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLMOPT_PIPELINING' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLMOPT_MAXCONNECTS' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLPAUSE_ALL' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLPAUSE_CONT' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLPAUSE_RECV' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLPAUSE_RECV_CONT' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLPAUSE_SEND' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLPAUSE_SEND_CONT' => array( + '5.4' => false, + '5.5' => true, + ), + // Soap: + 'SOAP_SSL_METHOD_TLS' => array( + '5.4' => false, + '5.5' => true, + ), + 'SOAP_SSL_METHOD_SSLv2' => array( + '5.4' => false, + '5.5' => true, + ), + 'SOAP_SSL_METHOD_SSLv3' => array( + '5.4' => false, + '5.5' => true, + ), + 'SOAP_SSL_METHOD_SSLv23' => array( + '5.4' => false, + '5.5' => true, + ), + // Tokenizer: + 'T_FINALLY' => array( + '5.4' => false, + '5.5' => true, + ), + 'T_YIELD' => array( + '5.4' => false, + '5.5' => true, + ), + // Core/Password Hashing: + 'PASSWORD_BCRYPT' => array( + '5.4' => false, + '5.5' => true, + ), + 'PASSWORD_DEFAULT' => array( + '5.4' => false, + '5.5' => true, + ), + 'PASSWORD_BCRYPT_DEFAULT_COST' => array( + '5.4' => false, + '5.5' => true, + ), + + + // Libxml: + 'LIBXML_SCHEMA_CREATE' => array( + '5.5.1' => false, + '5.5.2' => true, + ), + + // Curl: + 'CURL_SSLVERSION_TLSv1_0' => array( + '5.5.18' => false, + '5.5.19' => true, + ), + 'CURL_SSLVERSION_TLSv1_1' => array( + '5.5.18' => false, + '5.5.19' => true, + ), + 'CURL_SSLVERSION_TLSv1_2' => array( + '5.5.18' => false, + '5.5.19' => true, + ), + + 'CURLPROXY_SOCKS4A' => array( + '5.5.22' => false, + '5.5.23' => true, + ), + 'CURLPROXY_SOCKS5_HOSTNAME' => array( + '5.5.22' => false, + '5.5.23' => true, + ), + + 'CURL_VERSION_HTTP2' => array( + '5.5.23' => false, + '5.5.24' => true, + ), + + 'ARRAY_FILTER_USE_KEY' => array( + '5.5' => false, + '5.6' => true, + ), + 'ARRAY_FILTER_USE_BOTH' => array( + '5.5' => false, + '5.6' => true, + ), + // LDAP: + 'LDAP_ESCAPE_DN' => array( + '5.5' => false, + '5.6' => true, + ), + 'LDAP_ESCAPE_FILTER' => array( + '5.5' => false, + '5.6' => true, + ), + // OpenSSL: + 'OPENSSL_DEFAULT_STREAM_CIPHERS' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_ANY_CLIENT' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_ANY_SERVER' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_TLSv1_0_SERVER' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_TLSv1_1_SERVER' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_TLSv1_2_SERVER' => array( + '5.5' => false, + '5.6' => true, + ), + // PostgreSQL: + 'PGSQL_CONNECT_ASYNC' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_CONNECTION_AUTH_OK' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_CONNECTION_AWAITING_RESPONSE' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_CONNECTION_MADE' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_CONNECTION_SETENV' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_CONNECTION_SSL_STARTUP' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_CONNECTION_STARTED' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_DML_ESCAPE' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_POLLING_ACTIVE' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_POLLING_FAILED' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_POLLING_OK' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_POLLING_READING' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_POLLING_WRITING' => array( + '5.5' => false, + '5.6' => true, + ), + // Tokenizer: + 'T_ELLIPSIS' => array( + '5.5' => false, + '5.6' => true, + ), + 'T_POW' => array( + '5.5' => false, + '5.6' => true, + ), + 'T_POW_EQUAL' => array( + '5.5' => false, + '5.6' => true, + ), + + 'INI_SCANNER_TYPED' => array( + '5.6.0' => false, + '5.6.1' => true, + ), + + 'JSON_PRESERVE_ZERO_FRACTION' => array( + '5.6.5' => false, + '5.6.6' => true, + ), + + 'MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT' => array( + '5.6.15' => false, + '5.6.16' => true, + ), + + // GD: + // Also introduced in 7.0.10. + 'IMG_WEBP' => array( + '5.6.24' => false, + '5.6.25' => true, + ), + + + 'TOKEN_PARSE' => array( + '5.6' => false, + '7.0' => true, + ), + 'FILTER_VALIDATE_DOMAIN' => array( + '5.6' => false, + '7.0' => true, + ), + 'PHP_INT_MIN' => array( + '5.6' => false, + '7.0' => true, + ), + // Curl: + 'CURLPIPE_NOTHING' => array( + '5.6' => false, + '7.0' => true, + ), + 'CURLPIPE_HTTP1' => array( + '5.6' => false, + '7.0' => true, + ), + 'CURLPIPE_MULTIPLEX' => array( + '5.6' => false, + '7.0' => true, + ), + // JSON: + 'JSON_ERROR_INVALID_PROPERTY_NAME' => array( + '5.6' => false, + '7.0' => true, + ), + 'JSON_ERROR_UTF16' => array( + '5.6' => false, + '7.0' => true, + ), + // LibXML: + 'LIBXML_BIGLINES' => array( + '5.6' => false, + '7.0' => true, + ), + // PCRE: + 'PREG_JIT_STACKLIMIT_ERROR' => array( + '5.6' => false, + '7.0' => true, + ), + // POSIX: + 'POSIX_RLIMIT_AS' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_CORE' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_CPU' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_DATA' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_FSIZE' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_LOCKS' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_MEMLOCK' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_MSGQUEUE' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_NICE' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_NOFILE' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_NPROC' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_RSS' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_RTPRIO' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_RTTIME' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_SIGPENDING' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_STACK' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_INFINITY' => array( + '5.6' => false, + '7.0' => true, + ), + // Tokenizer: + 'T_COALESCE' => array( + '5.6' => false, + '7.0' => true, + ), + 'T_SPACESHIP' => array( + '5.6' => false, + '7.0' => true, + ), + 'T_YIELD_FROM' => array( + '5.6' => false, + '7.0' => true, + ), + + // Zlib: + // The first three are in the PHP 5.4 changelog, but the Extension constant page says 7.0. + 'ZLIB_ENCODING_RAW' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_ENCODING_DEFLATE' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_ENCODING_GZIP' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_FILTERED' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_HUFFMAN_ONLY' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_FIXED' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_RLE' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_DEFAULT_STRATEGY' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_BLOCK' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_FINISH' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_FULL_FLUSH' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_NO_FLUSH' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_PARTIAL_FLUSH' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_SYNC_FLUSH' => array( + '5.6' => false, + '7.0' => true, + ), + + 'CURL_HTTP_VERSION_2' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_HTTP_VERSION_2TLS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_REDIR_POST_301' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_REDIR_POST_302' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_REDIR_POST_303' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_REDIR_POST_ALL' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_VERSION_KERBEROS5' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_VERSION_PSL' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_VERSION_UNIX_SOCKETS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLAUTH_NEGOTIATE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLAUTH_NTLM_WB' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLFTP_CREATE_DIR' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLFTP_CREATE_DIR_NONE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLFTP_CREATE_DIR_RETRY' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLHEADER_SEPARATE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLHEADER_UNIFIED' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLMOPT_MAX_HOST_CONNECTIONS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLMOPT_MAX_PIPELINE_LENGTH' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLMOPT_MAX_TOTAL_CONNECTIONS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_CONNECT_TO' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_DEFAULT_PROTOCOL' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_DNS_INTERFACE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_DNS_LOCAL_IP4' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_DNS_LOCAL_IP6' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_EXPECT_100_TIMEOUT_MS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_HEADEROPT' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_LOGIN_OPTIONS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_PATH_AS_IS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_PINNEDPUBLICKEY' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_PIPEWAIT' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_PROXY_SERVICE_NAME' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_PROXYHEADER' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_SASL_IR' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_SERVICE_NAME' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_SSL_ENABLE_ALPN' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_SSL_ENABLE_NPN' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_SSL_FALSESTART' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_SSL_VERIFYSTATUS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_STREAM_WEIGHT' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_TCP_FASTOPEN' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_TFTP_NO_OPTIONS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_UNIX_SOCKET_PATH' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_XOAUTH2_BEARER' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLPROTO_SMB' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLPROTO_SMBS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLPROXY_HTTP_1_0' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLSSH_AUTH_AGENT' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLSSLOPT_NO_REVOKE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + + 'PHP_FD_SETSIZE' => array( + '7.0' => false, + '7.1' => true, + ), + // Curl: + 'CURLMOPT_PUSHFUNCTION' => array( + '7.0' => false, + '7.1' => true, + ), + 'CURL_PUSH_OK' => array( + '7.0' => false, + '7.1' => true, + ), + 'CURL_PUSH_DENY' => array( + '7.0' => false, + '7.1' => true, + ), + // Filter: + 'FILTER_FLAG_EMAIL_UNICODE' => array( + '7.0' => false, + '7.1' => true, + ), + // GD: + 'IMAGETYPE_WEBP' => array( + '7.0' => false, + '7.1' => true, + ), + // Json: + 'JSON_UNESCAPED_LINE_TERMINATORS' => array( + '7.0' => false, + '7.1' => true, + ), + // LDAP: + 'LDAP_OPT_X_SASL_NOCANON' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_SASL_USERNAME' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CACERTDIR' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CACERTFILE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CERTFILE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CIPHER_SUITE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_KEYFILE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_RANDOM_FILE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CRLCHECK' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CRL_NONE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CRL_PEER' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CRL_ALL' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_DHFILE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CRLFILE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_PROTOCOL_MIN' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_PROTOCOL_SSL2' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_PROTOCOL_SSL3' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_PROTOCOL_TLS1_0' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_PROTOCOL_TLS1_1' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_PROTOCOL_TLS1_2' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_PACKAGE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_KEEPALIVE_IDLE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_KEEPALIVE_PROBES' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_KEEPALIVE_INTERVAL' => array( + '7.0' => false, + '7.1' => true, + ), + // PostgreSQL: + 'PGSQL_NOTICE_LAST' => array( + '7.0' => false, + '7.1' => true, + ), + 'PGSQL_NOTICE_ALL' => array( + '7.0' => false, + '7.1' => true, + ), + 'PGSQL_NOTICE_CLEAR' => array( + '7.0' => false, + '7.1' => true, + ), + // SPL: + 'MT_RAND_PHP' => array( + '7.0' => false, + '7.1' => true, + ), + + // SQLite3: + 'SQLITE3_DETERMINISTIC' => array( + '7.1.3' => false, + '7.1.4' => true, + ), + + // Core: + 'PHP_OS_FAMILY' => array( + '7.1' => false, + '7.2' => true, + ), + 'PHP_FLOAT_DIG' => array( + '7.1' => false, + '7.2' => true, + ), + 'PHP_FLOAT_EPSILON' => array( + '7.1' => false, + '7.2' => true, + ), + 'PHP_FLOAT_MIN' => array( + '7.1' => false, + '7.2' => true, + ), + 'PHP_FLOAT_MAX' => array( + '7.1' => false, + '7.2' => true, + ), + + // Core/Password Hashing: + 'PASSWORD_ARGON2I' => array( + '7.1' => false, + '7.2' => true, + ), + 'PASSWORD_ARGON2_DEFAULT_MEMORY_COST' => array( + '7.1' => false, + '7.2' => true, + ), + 'PASSWORD_ARGON2_DEFAULT_TIME_COST' => array( + '7.1' => false, + '7.2' => true, + ), + 'PASSWORD_ARGON2_DEFAULT_THREADS' => array( + '7.1' => false, + '7.2' => true, + ), + + // Fileinfo: + 'FILEINFO_EXTENSION' => array( + '7.1' => false, + '7.2' => true, + ), + + // GD: + 'IMG_EFFECT_MULTIPLY' => array( + '7.1' => false, + '7.2' => true, + ), + 'IMG_BMP' => array( + '7.1' => false, + '7.2' => true, + ), + + // JSON: + 'JSON_INVALID_UTF8_IGNORE' => array( + '7.1' => false, + '7.2' => true, + ), + 'JSON_INVALID_UTF8_SUBSTITUTE' => array( + '7.1' => false, + '7.2' => true, + ), + + // LDAP: + 'LDAP_EXOP_START_TLS' => array( + '7.1' => false, + '7.2' => true, + ), + 'LDAP_EXOP_MODIFY_PASSWD' => array( + '7.1' => false, + '7.2' => true, + ), + 'LDAP_EXOP_REFRESH' => array( + '7.1' => false, + '7.2' => true, + ), + 'LDAP_EXOP_WHO_AM_I' => array( + '7.1' => false, + '7.2' => true, + ), + 'LDAP_EXOP_TURN' => array( + '7.1' => false, + '7.2' => true, + ), + + // PCRE: + 'PREG_UNMATCHED_AS_NULL' => array( + '7.1' => false, + '7.2' => true, + ), + + // Sodium: + 'SODIUM_LIBRARY_VERSION' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_LIBRARY_MAJOR_VERSION' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_LIBRARY_MINOR_VERSION' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_BASE64_VARIANT_ORIGINAL' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_BASE64_VARIANT_URLSAFE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_AES256GCM_NSECBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_AES256GCM_ABYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_ABYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NSECBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NSECBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AUTH_BYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AUTH_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_BOX_SEALBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_BOX_SECRETKEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_BOX_PUBLICKEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_BOX_KEYPAIRBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_BOX_MACBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_BOX_NONCEBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_BOX_SEEDBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KDF_BYTES_MIN' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KDF_BYTES_MAX' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KDF_CONTEXTBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KDF_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KX_SEEDBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KX_SESSIONKEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KX_PUBLICKEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KX_SECRETKEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KX_KEYPAIRBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_GENERICHASH_BYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_GENERICHASH_BYTES_MIN' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_GENERICHASH_BYTES_MAX' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_GENERICHASH_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_GENERICHASH_KEYBYTES_MIN' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_GENERICHASH_KEYBYTES_MAX' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_ALG_ARGON2I13' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_ALG_DEFAULT' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_SALTBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_STRPREFIX' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_OPSLIMIT_SENSITIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_MEMLIMIT_SENSITIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRPREFIX' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_SENSITIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_SENSITIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SCALARMULT_BYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SCALARMULT_SCALARBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SHORTHASH_BYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SHORTHASH_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETBOX_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETBOX_MACBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETBOX_NONCEBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SIGN_BYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SIGN_SEEDBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SIGN_SECRETKEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SIGN_KEYPAIRBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_STREAM_NONCEBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_STREAM_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + + 'CURLAUTH_BEARER' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLAUTH_GSSAPI' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLE_WEIRD_SERVER_REPLY' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_APPCONNECT_TIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_CONNECT_TIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_CONTENT_LENGTH_DOWNLOAD_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_CONTENT_LENGTH_UPLOAD_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_FILETIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_HTTP_VERSION' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_NAMELOOKUP_TIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_PRETRANSFER_TIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_PROTOCOL' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_PROXY_SSL_VERIFYRESULT' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_REDIRECT_TIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_SCHEME' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_SIZE_DOWNLOAD_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_SIZE_UPLOAD_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_SPEED_DOWNLOAD_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_SPEED_UPLOAD_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_STARTTRANSFER_TIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_TOTAL_TIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_LOCK_DATA_CONNECT' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_LOCK_DATA_PSL' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_MAX_READ_SIZE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_ABSTRACT_UNIX_SOCKET' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_DISALLOW_USERNAME_IN_URL' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_DNS_SHUFFLE_ADDRESSES' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_HAPROXYPROTOCOL' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_KEEP_SENDING_ON_ERROR' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PRE_PROXY' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_CAINFO' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_CAPATH' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_CRLFILE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_KEYPASSWD' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_PINNEDPUBLICKEY' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSLCERT' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSLCERTTYPE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSL_CIPHER_LIST' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSLKEY' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSLKEYTYPE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSL_OPTIONS' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSL_VERIFYHOST' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSL_VERIFYPEER' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSLVERSION' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_TLS13_CIPHERS' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_TLSAUTH_PASSWORD' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_TLSAUTH_TYPE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_TLSAUTH_USERNAME' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_REQUEST_TARGET' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_SOCKS5_AUTH' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_SSH_COMPRESSION' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_SUPPRESS_CONNECT_HEADERS' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_TIMEVALUE_LARGE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_TLS13_CIPHERS' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLPROXY_HTTPS' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLSSH_AUTH_GSSAPI' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_SSLVERSION_MAX_DEFAULT' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_SSLVERSION_MAX_NONE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_SSLVERSION_MAX_TLSv1_0' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_SSLVERSION_MAX_TLSv1_1' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_SSLVERSION_MAX_TLSv1_2' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_SSLVERSION_MAX_TLSv1_3' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_SSLVERSION_TLSv1_3' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_ASYNCHDNS' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_BROTLI' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_CONV' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_DEBUG' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_GSSAPI' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_GSSNEGOTIATE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_HTTPS_PROXY' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_IDN' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_LARGEFILE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_MULTI_SSL' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_NTLM' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_NTLM_WB' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_SPNEGO' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_SSPI' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_TLSAUTH_SRP' => array( + '7.2' => false, + '7.3' => true, + ), + 'FILTER_SANITIZE_ADD_SLASHES' => array( + '7.2' => false, + '7.3' => true, + ), + 'JSON_THROW_ON_ERROR' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_MANAGEDSAIT' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_PROXY_AUTHZ' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_SUBENTRIES' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_VALUESRETURNFILTER' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_ASSERT' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_PRE_READ' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_POST_READ' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_SORTREQUEST' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_SORTRESPONSE' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_PAGEDRESULTS' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_AUTHZID_REQUEST' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_AUTHZID_RESPONSE' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_SYNC' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_SYNC_STATE' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_SYNC_DONE' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_DONTUSECOPY' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_PASSWORDPOLICYREQUEST' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_PASSWORDPOLICYRESPONSE' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_X_INCREMENTAL_VALUES' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_X_DOMAIN_SCOPE' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_X_PERMISSIVE_MODIFY' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_X_SEARCH_OPTIONS' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_X_TREE_DELETE' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_X_EXTENDED_DN' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_VLVREQUEST' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_VLVRESPONSE' => array( + '7.2' => false, + '7.3' => true, + ), + 'MB_CASE_FOLD' => array( + '7.2' => false, + '7.3' => true, + ), + 'MB_CASE_UPPER_SIMPLE' => array( + '7.2' => false, + '7.3' => true, + ), + 'MB_CASE_LOWER_SIMPLE' => array( + '7.2' => false, + '7.3' => true, + ), + 'MB_CASE_TITLE_SIMPLE' => array( + '7.2' => false, + '7.3' => true, + ), + 'MB_CASE_FOLD_SIMPLE' => array( + '7.2' => false, + '7.3' => true, + ), + 'PGSQL_DIAG_SCHEMA_NAME' => array( + '7.2' => false, + '7.3' => true, + ), + 'PGSQL_DIAG_TABLE_NAME' => array( + '7.2' => false, + '7.3' => true, + ), + 'PGSQL_DIAG_COLUMN_NAME' => array( + '7.2' => false, + '7.3' => true, + ), + 'PGSQL_DIAG_DATATYPE_NAME' => array( + '7.2' => false, + '7.3' => true, + ), + 'PGSQL_DIAG_CONSTRAINT_NAME' => array( + '7.2' => false, + '7.3' => true, + ), + 'PGSQL_DIAG_SEVERITY_NONLOCALIZED' => array( + '7.2' => false, + '7.3' => true, + ), + 'PASSWORD_ARGON2ID' => array( + '7.2' => false, + '7.3' => true, + ), + 'STREAM_CRYPTO_PROTO_SSLv3' => array( + '7.2' => false, + '7.3' => true, + ), + 'STREAM_CRYPTO_PROTO_TLSv1_0' => array( + '7.2' => false, + '7.3' => true, + ), + 'STREAM_CRYPTO_PROTO_TLSv1_1' => array( + '7.2' => false, + '7.3' => true, + ), + 'STREAM_CRYPTO_PROTO_TLSv1_2' => array( + '7.2' => false, + '7.3' => true, + ), + + 'CURL_VERSION_ALTSVC' => array( + '7.3.5' => false, + '7.3.6' => true, + ), + 'CURL_VERSION_CURLDEBUG' => array( + '7.3.5' => false, + '7.3.6' => true, + ), + + 'IMG_FILTER_SCATTER' => array( + '7.3' => false, + '7.4' => true, + ), + 'MB_ONIGURUMA_VERSION' => array( + '7.3' => false, + '7.4' => true, + ), + 'SO_LABEL' => array( + '7.3' => false, + '7.4' => true, + ), + 'SO_PEERLABEL' => array( + '7.3' => false, + '7.4' => true, + ), + 'SO_LISTENQLIMIT' => array( + '7.3' => false, + '7.4' => true, + ), + 'SO_LISTENQLEN' => array( + '7.3' => false, + '7.4' => true, + ), + 'SO_USER_COOKIE' => array( + '7.3' => false, + '7.4' => true, + ), + 'PASSWORD_ARGON2_PROVIDER' => array( + '7.3' => false, + '7.4' => true, + ), + 'PHP_WINDOWS_EVENT_CTRL_C' => array( + '7.3' => false, + '7.4' => true, + ), + 'PHP_WINDOWS_EVENT_CTRL_BREAK' => array( + '7.3' => false, + '7.4' => true, + ), + 'T_BAD_CHARACTER' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_ARTICLE' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_ASIDE' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_AUDIO' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_BDI' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_CANVAS' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_COMMAND' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_DATALIST' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_DETAILS' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_DIALOG' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_FIGCAPTION' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_FIGURE' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_FOOTER' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_HEADER' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_HGROUP' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_MAIN' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_MARK' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_MENUITEM' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_METER' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_NAV' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_OUTPUT' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_PROGRESS' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_SECTION' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_SOURCE' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_SUMMARY' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_TEMPLATE' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_TIME' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_TRACK' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_VIDEO' => array( + '7.3' => false, + '7.4' => true, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.1.0 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $constantName = $tokens[$stackPtr]['content']; + + if (isset($this->newConstants[$constantName]) === false) { + return; + } + + if ($this->isUseOfGlobalConstant($phpcsFile, $stackPtr) === false) { + return; + } + + $itemInfo = array( + 'name' => $constantName, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 8.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newConstants[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 8.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The constant "%s" is not present in PHP version %s or earlier'; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/NewMagicClassConstantSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/NewMagicClassConstantSniff.php new file mode 100644 index 00000000..ccd58641 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/NewMagicClassConstantSniff.php @@ -0,0 +1,80 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Constants; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect usage of the magic `::class` constant introduced in PHP 5.5. + * + * The special `ClassName::class` constant is available as of PHP 5.5.0, and allows + * for fully qualified class name resolution at compile time. + * + * PHP version 5.5 + * + * @link https://wiki.php.net/rfc/class_name_scalars + * @link https://www.php.net/manual/en/language.oop5.constants.php#example-186 + * + * @since 7.1.4 + * @since 7.1.5 Removed the incorrect checks against invalid usage of the constant. + */ +class NewMagicClassConstantSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.1.4 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (strtolower($tokens[$stackPtr]['content']) !== 'class') { + return; + } + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true, null, true); + if ($prevToken === false || $tokens[$prevToken]['code'] !== \T_DOUBLE_COLON) { + return; + } + + $phpcsFile->addError( + 'The magic class constant ClassName::class was not available in PHP 5.4 or earlier', + $stackPtr, + 'Found' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/RemovedConstantsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/RemovedConstantsSniff.php new file mode 100644 index 00000000..b6c8f8d7 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/RemovedConstantsSniff.php @@ -0,0 +1,574 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Constants; + +use PHPCompatibility\AbstractRemovedFeatureSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect use of deprecated and/or removed PHP native global constants. + * + * PHP version All + * + * @since 8.1.0 + */ +class RemovedConstantsSniff extends AbstractRemovedFeatureSniff +{ + + /** + * A list of removed PHP Constants. + * + * The array lists : version number with false (deprecated) or true (removed). + * If's sufficient to list the first version where the constant was deprecated/removed. + * + * Optional, the array can contain an `alternative` key listing an alternative constant + * to be used instead. + * + * Note: PHP Constants are case-sensitive! + * + * @since 8.1.0 + * + * @var array(string => array(string => bool|string)) + */ + protected $removedConstants = array( + // Disabled since PHP 5.3.0 due to thread safety issues. + 'FILEINFO_COMPRESS' => array( + '5.3' => true, + ), + + 'CURLOPT_CLOSEPOLICY' => array( + '5.6' => true, + ), + 'CURLCLOSEPOLICY_LEAST_RECENTLY_USED' => array( + '5.6' => true, + ), + 'CURLCLOSEPOLICY_LEAST_TRAFFIC' => array( + '5.6' => true, + ), + 'CURLCLOSEPOLICY_SLOWEST' => array( + '5.6' => true, + ), + 'CURLCLOSEPOLICY_CALLBACK' => array( + '5.6' => true, + ), + 'CURLCLOSEPOLICY_OLDEST' => array( + '5.6' => true, + ), + + 'PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT' => array( + '7.0' => true, + ), + 'T_CHARACTER' => array( + '7.0' => true, + ), + 'T_BAD_CHARACTER' => array( + '7.0' => true, + ), + + 'INTL_IDNA_VARIANT_2003' => array( + '7.2' => false, + ), + + 'MCRYPT_MODE_ECB' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_MODE_CBC' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_MODE_CFB' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_MODE_OFB' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_MODE_NOFB' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_MODE_STREAM' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_ENCRYPT' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_DECRYPT' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_DEV_RANDOM' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_DEV_URANDOM' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RAND' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_3DES' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_ARCFOUR_IV' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_ARCFOUR' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_BLOWFISH' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_CAST_128' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_CAST_256' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_CRYPT' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_DES' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_DES_COMPAT' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_ENIGMA' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_GOST' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_IDEA' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_LOKI97' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_MARS' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_PANAMA' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RIJNDAEL_128' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RIJNDAEL_192' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RIJNDAEL_256' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RC2' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RC4' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RC6' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RC6_128' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RC6_192' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RC6_256' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SAFER64' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SAFER128' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SAFERPLUS' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SERPENT' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SERPENT_128' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SERPENT_192' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SERPENT_256' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SKIPJACK' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_TEAN' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_THREEWAY' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_TRIPLEDES' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_TWOFISH' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_TWOFISH128' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_TWOFISH192' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_TWOFISH256' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_WAKE' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_XTEA' => array( + '7.1' => false, + '7.2' => true, + ), + + 'PHPDBG_FILE' => array( + '7.3' => true, + ), + 'PHPDBG_METHOD' => array( + '7.3' => true, + ), + 'PHPDBG_LINENO' => array( + '7.3' => true, + ), + 'PHPDBG_FUNC' => array( + '7.3' => true, + ), + 'FILTER_FLAG_SCHEME_REQUIRED' => array( + '7.3' => false, + ), + 'FILTER_FLAG_HOST_REQUIRED' => array( + '7.3' => false, + ), + + 'CURLPIPE_HTTP1' => array( + '7.4' => false, + ), + 'FILTER_SANITIZE_MAGIC_QUOTES' => array( + '7.4' => false, + 'alternative' => 'FILTER_SANITIZE_ADD_SLASHES', + ), + 'IBASE_BKP_CONVERT' => array( + '7.4' => true, + ), + 'IBASE_BKP_IGNORE_CHECKSUMS' => array( + '7.4' => true, + ), + 'IBASE_BKP_IGNORE_LIMBO' => array( + '7.4' => true, + ), + 'IBASE_BKP_METADATA_ONLY' => array( + '7.4' => true, + ), + 'IBASE_BKP_NO_GARBAGE_COLLECT' => array( + '7.4' => true, + ), + 'IBASE_BKP_NON_TRANSPORTABLE' => array( + '7.4' => true, + ), + 'IBASE_BKP_OLD_DESCRIPTIONS' => array( + '7.4' => true, + ), + 'IBASE_COMMITTED' => array( + '7.4' => true, + ), + 'IBASE_CONCURRENCY' => array( + '7.4' => true, + ), + 'IBASE_CONSISTENCY' => array( + '7.4' => true, + ), + 'IBASE_DEFAULT' => array( + '7.4' => true, + ), + 'IBASE_FETCH_ARRAYS' => array( + '7.4' => true, + ), + 'IBASE_FETCH_BLOBS' => array( + '7.4' => true, + ), + 'IBASE_NOWAIT' => array( + '7.4' => true, + ), + 'IBASE_PRP_ACCESS_MODE' => array( + '7.4' => true, + ), + 'IBASE_PRP_ACTIVATE' => array( + '7.4' => true, + ), + 'IBASE_PRP_AM_READONLY' => array( + '7.4' => true, + ), + 'IBASE_PRP_AM_READWRITE' => array( + '7.4' => true, + ), + 'IBASE_PRP_DENY_NEW_ATTACHMENTS' => array( + '7.4' => true, + ), + 'IBASE_PRP_DENY_NEW_TRANSACTIONS' => array( + '7.4' => true, + ), + 'IBASE_PRP_DB_ONLINE' => array( + '7.4' => true, + ), + 'IBASE_PRP_PAGE_BUFFERS' => array( + '7.4' => true, + ), + 'IBASE_PRP_RES' => array( + '7.4' => true, + ), + 'IBASE_PRP_RES_USE_FULL' => array( + '7.4' => true, + ), + 'IBASE_PRP_RESERVE_SPACE' => array( + '7.4' => true, + ), + 'IBASE_PRP_SET_SQL_DIALECT' => array( + '7.4' => true, + ), + 'IBASE_PRP_SHUTDOWN_DB' => array( + '7.4' => true, + ), + 'IBASE_PRP_SWEEP_INTERVAL' => array( + '7.4' => true, + ), + 'IBASE_PRP_WM_ASYNC' => array( + '7.4' => true, + ), + 'IBASE_PRP_WM_SYNC' => array( + '7.4' => true, + ), + 'IBASE_PRP_WRITE_MODE' => array( + '7.4' => true, + ), + 'IBASE_READ' => array( + '7.4' => true, + ), + 'IBASE_RES_CREATE' => array( + '7.4' => true, + ), + 'IBASE_RES_DEACTIVATE_IDX' => array( + '7.4' => true, + ), + 'IBASE_RES_NO_SHADOW' => array( + '7.4' => true, + ), + 'IBASE_RES_NO_VALIDITY' => array( + '7.4' => true, + ), + 'IBASE_RES_ONE_AT_A_TIME' => array( + '7.4' => true, + ), + 'IBASE_RES_REPLACE' => array( + '7.4' => true, + ), + 'IBASE_RES_USE_ALL_SPACE' => array( + '7.4' => true, + ), + 'IBASE_RPR_CHECK_DB' => array( + '7.4' => true, + ), + 'IBASE_RPR_FULL' => array( + '7.4' => true, + ), + 'IBASE_RPR_IGNORE_CHECKSUM' => array( + '7.4' => true, + ), + 'IBASE_RPR_KILL_SHADOWS' => array( + '7.4' => true, + ), + 'IBASE_RPR_MEND_DB' => array( + '7.4' => true, + ), + 'IBASE_RPR_SWEEP_DB' => array( + '7.4' => true, + ), + 'IBASE_RPR_VALIDATE_DB' => array( + '7.4' => true, + ), + 'IBASE_STS_DATA_PAGES' => array( + '7.4' => true, + ), + 'IBASE_STS_DB_LOG' => array( + '7.4' => true, + ), + 'IBASE_STS_HDR_PAGES' => array( + '7.4' => true, + ), + 'IBASE_STS_IDX_PAGES' => array( + '7.4' => true, + ), + 'IBASE_STS_SYS_RELATIONS' => array( + '7.4' => true, + ), + 'IBASE_SVC_GET_ENV' => array( + '7.4' => true, + ), + 'IBASE_SVC_GET_ENV_LOCK' => array( + '7.4' => true, + ), + 'IBASE_SVC_GET_ENV_MSG' => array( + '7.4' => true, + ), + 'IBASE_SVC_GET_USERS' => array( + '7.4' => true, + ), + 'IBASE_SVC_IMPLEMENTATION' => array( + '7.4' => true, + ), + 'IBASE_SVC_SERVER_VERSION' => array( + '7.4' => true, + ), + 'IBASE_SVC_SVR_DB_INFO' => array( + '7.4' => true, + ), + 'IBASE_SVC_USER_DBPATH' => array( + '7.4' => true, + ), + 'IBASE_UNIXTIME' => array( + '7.4' => true, + ), + 'IBASE_WAIT' => array( + '7.4' => true, + ), + 'IBASE_WRITE' => array( + '7.4' => true, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.1.0 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $constantName = $tokens[$stackPtr]['content']; + + if (isset($this->removedConstants[$constantName]) === false) { + return; + } + + if ($this->isUseOfGlobalConstant($phpcsFile, $stackPtr) === false) { + return; + } + + $itemInfo = array( + 'name' => $constantName, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 8.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->removedConstants[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 8.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The constant "%s" is '; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/DiscouragedSwitchContinueSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/DiscouragedSwitchContinueSniff.php new file mode 100644 index 00000000..8d56b93a --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/DiscouragedSwitchContinueSniff.php @@ -0,0 +1,238 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ControlStructures; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect use of `continue` in `switch` control structures. + * + * As of PHP 7.3, PHP will throw a warning when `continue` is used to target a `switch` + * control structure. + * The sniff takes numeric arguments used with `continue` into account. + * + * PHP version 7.3 + * + * @link https://www.php.net/manual/en/migration73.incompatible.php#migration73.incompatible.core.continue-targeting-switch + * @link https://wiki.php.net/rfc/continue_on_switch_deprecation + * @link https://github.com/php/php-src/commit/04e3523b7d095341f65ed5e71a3cac82fca690e4 + * (actual implementation which is different from the RFC). + * @link https://www.php.net/manual/en/control-structures.switch.php + * + * @since 8.2.0 + */ +class DiscouragedSwitchContinueSniff extends Sniff +{ + + /** + * Token codes of control structures which can be targeted using continue. + * + * @since 8.2.0 + * + * @var array + */ + protected $loopStructures = array( + \T_FOR => \T_FOR, + \T_FOREACH => \T_FOREACH, + \T_WHILE => \T_WHILE, + \T_DO => \T_DO, + \T_SWITCH => \T_SWITCH, + ); + + /** + * Tokens which start a new case within a switch. + * + * @since 8.2.0 + * + * @var array + */ + protected $caseTokens = array( + \T_CASE => \T_CASE, + \T_DEFAULT => \T_DEFAULT, + ); + + /** + * Token codes which are accepted to determine the level for the continue. + * + * This array is enriched with the arithmetic operators in the register() method. + * + * @since 8.2.0 + * + * @var array + */ + protected $acceptedLevelTokens = array( + \T_LNUMBER => \T_LNUMBER, + \T_OPEN_PARENTHESIS => \T_OPEN_PARENTHESIS, + \T_CLOSE_PARENTHESIS => \T_CLOSE_PARENTHESIS, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.2.0 + * + * @return array + */ + public function register() + { + $this->acceptedLevelTokens += Tokens::$arithmeticTokens; + $this->acceptedLevelTokens += Tokens::$emptyTokens; + + return array(\T_SWITCH); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener'], $tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $switchOpener = $tokens[$stackPtr]['scope_opener']; + $switchCloser = $tokens[$stackPtr]['scope_closer']; + + // Quick check whether we need to bother with the more complex logic. + $hasContinue = $phpcsFile->findNext(\T_CONTINUE, ($switchOpener + 1), $switchCloser); + if ($hasContinue === false) { + return; + } + + $caseDefault = $switchOpener; + + do { + $caseDefault = $phpcsFile->findNext($this->caseTokens, ($caseDefault + 1), $switchCloser); + if ($caseDefault === false) { + break; + } + + if (isset($tokens[$caseDefault]['scope_opener']) === false) { + // Unknown start of the case, skip. + continue; + } + + $caseOpener = $tokens[$caseDefault]['scope_opener']; + $nextCaseDefault = $phpcsFile->findNext($this->caseTokens, ($caseDefault + 1), $switchCloser); + if ($nextCaseDefault === false) { + $caseCloser = $switchCloser; + } else { + $caseCloser = $nextCaseDefault; + } + + // Check for unscoped control structures within the case. + $controlStructure = $caseOpener; + $doCount = 0; + while (($controlStructure = $phpcsFile->findNext($this->loopStructures, ($controlStructure + 1), $caseCloser)) !== false) { + if ($tokens[$controlStructure]['code'] === \T_DO) { + $doCount++; + } + + if (isset($tokens[$controlStructure]['scope_opener'], $tokens[$controlStructure]['scope_closer']) === false) { + if ($tokens[$controlStructure]['code'] === \T_WHILE && $doCount > 0) { + // While in a do-while construct. + $doCount--; + continue; + } + + // Control structure without braces found within the case, ignore this case. + continue 2; + } + } + + // Examine the contents of the case. + $continue = $caseOpener; + + do { + $continue = $phpcsFile->findNext(\T_CONTINUE, ($continue + 1), $caseCloser); + if ($continue === false) { + break; + } + + $nextSemicolon = $phpcsFile->findNext(array(\T_SEMICOLON, \T_CLOSE_TAG), ($continue + 1), $caseCloser); + $codeString = ''; + for ($i = ($continue + 1); $i < $nextSemicolon; $i++) { + if (isset($this->acceptedLevelTokens[$tokens[$i]['code']]) === false) { + // Function call/variable or other token which make numeric level impossible to determine. + continue 2; + } + + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + $codeString .= $tokens[$i]['content']; + } + + $level = null; + if ($codeString !== '') { + if (is_numeric($codeString)) { + $level = (int) $codeString; + } else { + // With the above logic, the string can only contain digits and operators, eval! + $level = eval("return ( $codeString );"); + } + } + + if (isset($level) === false || $level === 0) { + $level = 1; + } + + // Examine which control structure is being targeted by the continue statement. + if (isset($tokens[$continue]['conditions']) === false) { + continue; + } + + $conditions = array_reverse($tokens[$continue]['conditions'], true); + // PHPCS adds more structures to the conditions array than we want to take into + // consideration, so clean up the array. + foreach ($conditions as $tokenPtr => $tokenCode) { + if (isset($this->loopStructures[$tokenCode]) === false) { + unset($conditions[$tokenPtr]); + } + } + + $targetCondition = \array_slice($conditions, ($level - 1), 1, true); + if (empty($targetCondition)) { + continue; + } + + $conditionToken = key($targetCondition); + if ($conditionToken === $stackPtr) { + $phpcsFile->addWarning( + "Targeting a 'switch' control structure with a 'continue' statement is strongly discouraged and will throw a warning as of PHP 7.3.", + $continue, + 'Found' + ); + } + + } while ($continue < $caseCloser); + + } while ($caseDefault < $switchCloser); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenBreakContinueOutsideLoopSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenBreakContinueOutsideLoopSniff.php new file mode 100644 index 00000000..2cfbcc53 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenBreakContinueOutsideLoopSniff.php @@ -0,0 +1,116 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ControlStructures; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect using `break` and/or `continue` statements outside of a looping structure. + * + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/migration70.incompatible.php#migration70.incompatible.other.break-continue + * @link https://www.php.net/manual/en/control-structures.break.php + * @link https://www.php.net/manual/en/control-structures.continue.php + * + * @since 7.0.7 + */ +class ForbiddenBreakContinueOutsideLoopSniff extends Sniff +{ + + /** + * Token codes of control structure in which usage of break/continue is valid. + * + * @since 7.0.7 + * + * @var array + */ + protected $validLoopStructures = array( + \T_FOR => true, + \T_FOREACH => true, + \T_WHILE => true, + \T_DO => true, + \T_SWITCH => true, + ); + + /** + * Token codes which did not correctly get a condition assigned in older PHPCS versions. + * + * @since 7.0.7 + * + * @var array + */ + protected $backCompat = array( + \T_CASE => true, + \T_DEFAULT => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.7 + * + * @return array + */ + public function register() + { + return array( + \T_BREAK, + \T_CONTINUE, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.7 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Check if the break/continue is within a valid loop structure. + if (empty($token['conditions']) === false) { + foreach ($token['conditions'] as $tokenCode) { + if (isset($this->validLoopStructures[$tokenCode]) === true) { + return; + } + } + } else { + // Deal with older PHPCS versions. + if (isset($token['scope_condition']) === true && isset($this->backCompat[$tokens[$token['scope_condition']]['code']]) === true) { + return; + } + } + + // If we're still here, no valid loop structure container has been found, so throw an error. + $error = "Using '%s' outside of a loop or switch structure is invalid"; + $isError = false; + $errorCode = 'Found'; + $data = array($token['content']); + + if ($this->supportsAbove('7.0')) { + $error .= ' and will throw a fatal error since PHP 7.0'; + $isError = true; + $errorCode = 'FatalError'; + } + + $this->addMessage($phpcsFile, $error, $stackPtr, $isError, $errorCode, $data); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenBreakContinueVariableArgumentsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenBreakContinueVariableArgumentsSniff.php new file mode 100644 index 00000000..f63c8488 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenBreakContinueVariableArgumentsSniff.php @@ -0,0 +1,110 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ControlStructures; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detects using 0 and variable numeric arguments on `break` and `continue` statements. + * + * This sniff checks for: + * - Using `break` and/or `continue` with a variable as the numeric argument. + * - Using `break` and/or `continue` with a zero - 0 - as the numeric argument. + * + * PHP version 5.4 + * + * @link https://www.php.net/manual/en/migration54.incompatible.php + * @link https://www.php.net/manual/en/control-structures.break.php + * @link https://www.php.net/manual/en/control-structures.continue.php + * + * @since 5.5 + * @since 5.6 Now extends the base `Sniff` class. + */ +class ForbiddenBreakContinueVariableArgumentsSniff extends Sniff +{ + /** + * Error types this sniff handles for forbidden break/continue arguments. + * + * Array key is the error code. Array value will be used as part of the error message. + * + * @since 7.0.5 + * @since 7.1.0 Changed from class constants to property. + * + * @var array + */ + private $errorTypes = array( + 'variableArgument' => 'a variable argument', + 'zeroArgument' => '0 as an argument', + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + return array(\T_BREAK, \T_CONTINUE); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('5.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $nextSemicolonToken = $phpcsFile->findNext(array(\T_SEMICOLON, \T_CLOSE_TAG), ($stackPtr), null, false); + $errorType = ''; + for ($curToken = $stackPtr + 1; $curToken < $nextSemicolonToken; $curToken++) { + if ($tokens[$curToken]['type'] === 'T_STRING') { + // If the next non-whitespace token after the string + // is an opening parenthesis then it's a function call. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, $curToken + 1, null, true); + if ($tokens[$openBracket]['code'] === \T_OPEN_PARENTHESIS) { + $errorType = 'variableArgument'; + break; + } + + } elseif (\in_array($tokens[$curToken]['type'], array('T_VARIABLE', 'T_FUNCTION', 'T_CLOSURE'), true)) { + $errorType = 'variableArgument'; + break; + + } elseif ($tokens[$curToken]['type'] === 'T_LNUMBER' && $tokens[$curToken]['content'] === '0') { + $errorType = 'zeroArgument'; + break; + } + } + + if ($errorType !== '') { + $error = 'Using %s on break or continue is forbidden since PHP 5.4'; + $errorCode = $errorType . 'Found'; + $data = array($this->errorTypes[$errorType]); + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenSwitchWithMultipleDefaultBlocksSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenSwitchWithMultipleDefaultBlocksSniff.php new file mode 100644 index 00000000..26f41c07 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenSwitchWithMultipleDefaultBlocksSniff.php @@ -0,0 +1,81 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ControlStructures; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Switch statements can not have multiple default blocks since PHP 7.0. + * + * PHP version 7.0 + * + * @link https://wiki.php.net/rfc/switch.default.multiple + * @link https://www.php.net/manual/en/control-structures.switch.php + * + * @since 7.0.0 + */ +class ForbiddenSwitchWithMultipleDefaultBlocksSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + return array(\T_SWITCH); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $defaultToken = $stackPtr; + $defaultCount = 0; + $targetLevel = $tokens[$stackPtr]['level'] + 1; + while ($defaultCount < 2 && ($defaultToken = $phpcsFile->findNext(array(\T_DEFAULT), $defaultToken + 1, $tokens[$stackPtr]['scope_closer'])) !== false) { + // Same level or one below (= two default cases after each other). + if ($tokens[$defaultToken]['level'] === $targetLevel || $tokens[$defaultToken]['level'] === ($targetLevel + 1)) { + $defaultCount++; + } + } + + if ($defaultCount > 1) { + $phpcsFile->addError( + 'Switch statements can not have multiple default blocks since PHP 7.0', + $stackPtr, + 'Found' + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewExecutionDirectivesSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewExecutionDirectivesSniff.php new file mode 100644 index 00000000..0e71a261 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewExecutionDirectivesSniff.php @@ -0,0 +1,378 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ControlStructures; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Check for valid execution directives set with `declare()`. + * + * The sniff contains three distinct checks: + * - Check if the execution directive used is valid. PHP currently only supports + * three execution directives. + * - Check if the execution directive used is available in the PHP versions + * for which support is being checked. + * In the case of the `encoding` directive on PHP 5.3, support is conditional + * on the `--enable-zend-multibyte` compilation option. This will be indicated as such. + * - Check whether the value for the directive is valid. + * + * PHP version All + * + * @link https://www.php.net/manual/en/control-structures.declare.php + * @link https://wiki.php.net/rfc/scalar_type_hints_v5#strict_types_declare_directive + * + * @since 7.0.3 + * @since 7.1.0 Now extends the `AbstractNewFeatureSniff` instead of the base `Sniff` class. + */ +class NewExecutionDirectivesSniff extends AbstractNewFeatureSniff +{ + + /** + * A list of new execution directives + * + * The array lists : version number with false (not present) or true (present). + * If the execution order is conditional, add the condition as a string to the version nr. + * If's sufficient to list the first version where the execution directive appears. + * + * @since 7.0.3 + * + * @var array(string => array(string => bool|string|array)) + */ + protected $newDirectives = array( + 'ticks' => array( + '3.1' => false, + '4.0' => true, + 'valid_value_callback' => 'isNumeric', + ), + 'encoding' => array( + '5.2' => false, + '5.3' => '--enable-zend-multibyte', // Directive ignored unless. + '5.4' => true, + 'valid_value_callback' => 'validEncoding', + ), + 'strict_types' => array( + '5.6' => false, + '7.0' => true, + 'valid_values' => array(1), + ), + ); + + + /** + * Tokens to ignore when trying to find the value for the directive. + * + * @since 7.0.3 + * + * @var array + */ + protected $ignoreTokens = array(); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.3 + * + * @return array + */ + public function register() + { + $this->ignoreTokens = Tokens::$emptyTokens; + $this->ignoreTokens[\T_EQUAL] = \T_EQUAL; + + return array(\T_DECLARE); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === true) { + $openParenthesis = $tokens[$stackPtr]['parenthesis_opener']; + $closeParenthesis = $tokens[$stackPtr]['parenthesis_closer']; + } else { + if (version_compare(PHPCSHelper::getVersion(), '2.3.4', '>=')) { + return; + } + + // Deal with PHPCS 2.3.0-2.3.3 which do not yet set the parenthesis properly for declare statements. + $openParenthesis = $phpcsFile->findNext(\T_OPEN_PARENTHESIS, ($stackPtr + 1), null, false, null, true); + if ($openParenthesis === false || isset($tokens[$openParenthesis]['parenthesis_closer']) === false) { + return; + } + $closeParenthesis = $tokens[$openParenthesis]['parenthesis_closer']; + } + + $directivePtr = $phpcsFile->findNext(\T_STRING, ($openParenthesis + 1), $closeParenthesis, false); + if ($directivePtr === false) { + return; + } + + $directiveContent = $tokens[$directivePtr]['content']; + + if (isset($this->newDirectives[$directiveContent]) === false) { + $error = 'Declare can only be used with the directives %s. Found: %s'; + $data = array( + implode(', ', array_keys($this->newDirectives)), + $directiveContent, + ); + + $phpcsFile->addError($error, $stackPtr, 'InvalidDirectiveFound', $data); + + } else { + // Check for valid directive for version. + $itemInfo = array( + 'name' => $directiveContent, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + + // Check for valid directive value. + $valuePtr = $phpcsFile->findNext($this->ignoreTokens, $directivePtr + 1, $closeParenthesis, true); + if ($valuePtr === false) { + return; + } + + $this->addWarningOnInvalidValue($phpcsFile, $valuePtr, $directiveContent); + } + } + + + /** + * Determine whether an error/warning should be thrown for an item based on collected information. + * + * @since 7.1.0 + * + * @param array $errorInfo Detail information about an item. + * + * @return bool + */ + protected function shouldThrowError(array $errorInfo) + { + return ($errorInfo['not_in_version'] !== '' || $errorInfo['conditional_version'] !== ''); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newDirectives[$itemInfo['name']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array( + 'valid_value_callback', + 'valid_values', + ); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['conditional_version'] = ''; + $errorInfo['condition'] = ''; + + $versionArray = $this->getVersionArray($itemArray); + + if (empty($versionArray) === false) { + foreach ($versionArray as $version => $present) { + if (\is_string($present) === true && $this->supportsBelow($version) === true) { + // We cannot test for compilation option (ok, except by scraping the output of phpinfo...). + $errorInfo['conditional_version'] = $version; + $errorInfo['condition'] = $present; + } + } + } + + return $errorInfo; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'Directive ' . parent::getErrorMsgTemplate(); + } + + + /** + * Generates the error or warning for this item. + * + * @since 7.0.3 + * @since 7.1.0 This method now overloads the method from the `AbstractNewFeatureSniff` class. + * - Renamed from `maybeAddError()` to `addError()`. + * - Changed visibility from `protected` to `public`. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the relevant token in + * the stack. + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Array with detail (version) information + * relevant to the item. + * + * @return void + */ + public function addError(File $phpcsFile, $stackPtr, array $itemInfo, array $errorInfo) + { + if ($errorInfo['not_in_version'] !== '') { + parent::addError($phpcsFile, $stackPtr, $itemInfo, $errorInfo); + } elseif ($errorInfo['conditional_version'] !== '') { + $error = 'Directive %s is present in PHP version %s but will be disregarded unless PHP is compiled with %s'; + $errorCode = $this->stringToErrorCode($itemInfo['name']) . 'WithConditionFound'; + $data = array( + $itemInfo['name'], + $errorInfo['conditional_version'], + $errorInfo['condition'], + ); + + $phpcsFile->addWarning($error, $stackPtr, $errorCode, $data); + } + } + + + /** + * Generates a error or warning for this sniff. + * + * @since 7.0.3 + * @since 7.0.6 Renamed from `addErrorOnInvalidValue()` to `addWarningOnInvalidValue()`. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the execution directive value + * in the token array. + * @param string $directive The directive. + * + * @return void + */ + protected function addWarningOnInvalidValue(File $phpcsFile, $stackPtr, $directive) + { + $tokens = $phpcsFile->getTokens(); + + $value = $tokens[$stackPtr]['content']; + if (isset(Tokens::$stringTokens[$tokens[$stackPtr]['code']]) === true) { + $value = $this->stripQuotes($value); + } + + $isError = false; + if (isset($this->newDirectives[$directive]['valid_values'])) { + if (\in_array($value, $this->newDirectives[$directive]['valid_values']) === false) { + $isError = true; + } + } elseif (isset($this->newDirectives[$directive]['valid_value_callback'])) { + $valid = \call_user_func(array($this, $this->newDirectives[$directive]['valid_value_callback']), $value); + if ($valid === false) { + $isError = true; + } + } + + if ($isError === true) { + $error = 'The execution directive %s does not seem to have a valid value. Please review. Found: %s'; + $errorCode = $this->stringToErrorCode($directive) . 'InvalidValueFound'; + $data = array( + $directive, + $value, + ); + + $phpcsFile->addWarning($error, $stackPtr, $errorCode, $data); + } + } + + + /** + * Check whether a value is numeric. + * + * Callback function to test whether the value for an execution directive is valid. + * + * @since 7.0.3 + * + * @param mixed $value The value to test. + * + * @return bool + */ + protected function isNumeric($value) + { + return is_numeric($value); + } + + + /** + * Check whether a value is a valid encoding. + * + * Callback function to test whether the value for an execution directive is valid. + * + * @since 7.0.3 + * + * @param mixed $value The value to test. + * + * @return bool + */ + protected function validEncoding($value) + { + static $encodings; + if (isset($encodings) === false && function_exists('mb_list_encodings')) { + $encodings = mb_list_encodings(); + } + + if (empty($encodings) || \is_array($encodings) === false) { + // If we can't test the encoding, let it pass through. + return true; + } + + return \in_array($value, $encodings, true); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewForeachExpressionReferencingSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewForeachExpressionReferencingSniff.php new file mode 100644 index 00000000..a2227692 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewForeachExpressionReferencingSniff.php @@ -0,0 +1,99 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ControlStructures; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect `foreach` expression referencing. + * + * Before PHP 5.5.0, referencing `$value` in a `foreach` was only possible + * if the iterated array could be referenced (i.e. if it is a variable). + * + * PHP version 5.5 + * + * @link https://www.php.net/manual/en/control-structures.foreach.php + * + * @since 9.0.0 + */ +class NewForeachExpressionReferencingSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.0.0 + * + * @return array + */ + public function register() + { + return array(\T_FOREACH); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) { + return; + } + + $opener = $tokens[$stackPtr]['parenthesis_opener']; + $closer = $tokens[$stackPtr]['parenthesis_closer']; + + $asToken = $phpcsFile->findNext(\T_AS, ($opener + 1), $closer); + if ($asToken === false) { + return; + } + + /* + * Note: referencing $key is not allowed in any version, so this should only find referenced $values. + * If it does find a referenced key, it would be a parse error anyway. + */ + $hasReference = $phpcsFile->findNext(\T_BITWISE_AND, ($asToken + 1), $closer); + if ($hasReference === false) { + return; + } + + $nestingLevel = 0; + if ($asToken !== ($opener + 1) && isset($tokens[$opener + 1]['nested_parenthesis'])) { + $nestingLevel = \count($tokens[$opener + 1]['nested_parenthesis']); + } + + if ($this->isVariable($phpcsFile, ($opener + 1), $asToken, $nestingLevel) === true) { + return; + } + + // Non-variable detected before the `as` keyword. + $phpcsFile->addError( + 'Referencing $value is only possible if the iterated array is a variable in PHP 5.4 or earlier.', + $hasReference, + 'Found' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewListInForeachSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewListInForeachSniff.php new file mode 100644 index 00000000..2398cf17 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewListInForeachSniff.php @@ -0,0 +1,84 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ControlStructures; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect unpacking nested arrays with `list()` in a `foreach()` as available since PHP 5.5. + * + * PHP version 5.5 + * + * @link https://www.php.net/manual/en/migration55.new-features.php#migration55.new-features.foreach-list + * @link https://wiki.php.net/rfc/foreachlist + * @link https://www.php.net/manual/en/control-structures.foreach.php#control-structures.foreach.list + * + * @since 9.0.0 + */ +class NewListInForeachSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.0.0 + * + * @return array + */ + public function register() + { + return array(\T_FOREACH); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) { + return; + } + + $opener = $tokens[$stackPtr]['parenthesis_opener']; + $closer = $tokens[$stackPtr]['parenthesis_closer']; + + $asToken = $phpcsFile->findNext(\T_AS, ($opener + 1), $closer); + if ($asToken === false) { + return; + } + + $hasList = $phpcsFile->findNext(array(\T_LIST, \T_OPEN_SHORT_ARRAY), ($asToken + 1), $closer); + if ($hasList === false) { + return; + } + + $phpcsFile->addError( + 'Unpacking nested arrays with list() in a foreach is not supported in PHP 5.4 or earlier.', + $hasList, + 'Found' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewMultiCatchSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewMultiCatchSniff.php new file mode 100644 index 00000000..256f37ff --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewMultiCatchSniff.php @@ -0,0 +1,78 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ControlStructures; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Catching multiple exception types in one statement is available since PHP 7.1. + * + * PHP version 7.1 + * + * @link https://www.php.net/manual/en/migration71.new-features.php#migration71.new-features.mulit-catch-exception-handling + * @link https://wiki.php.net/rfc/multiple-catch + * @link https://www.php.net/manual/en/language.exceptions.php#language.exceptions.catch + * + * @since 7.0.7 + */ +class NewMultiCatchSniff extends Sniff +{ + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.7 + * + * @return array + */ + public function register() + { + return array(\T_CATCH); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.7 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Bow out during live coding. + if (isset($token['parenthesis_opener'], $token['parenthesis_closer']) === false) { + return; + } + + $hasBitwiseOr = $phpcsFile->findNext(\T_BITWISE_OR, $token['parenthesis_opener'], $token['parenthesis_closer']); + + if ($hasBitwiseOr === false) { + return; + } + + $phpcsFile->addError( + 'Catching multiple exceptions within one statement is not supported in PHP 7.0 or earlier.', + $hasBitwiseOr, + 'Found' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Extensions/RemovedExtensionsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Extensions/RemovedExtensionsSniff.php new file mode 100644 index 00000000..13f5dfce --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Extensions/RemovedExtensionsSniff.php @@ -0,0 +1,346 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Extensions; + +use PHPCompatibility\AbstractRemovedFeatureSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect the use of deprecated and/or removed PHP extensions. + * + * This sniff examines function calls made and flags function calls to functions + * prefixed with the dedicated prefix from a deprecated/removed native PHP extension. + * + * Suggests alternative extensions if available. + * + * As userland functions may be prefixed with a prefix also used by a native + * PHP extension, the sniff offers the ability to whitelist specific functions + * from being flagged by this sniff via a property in a custom ruleset + * (since PHPCompatibility 7.0.2). + * + * {@internal This sniff is a candidate for removal once all functions from all + * deprecated/removed extensions have been added to the RemovedFunctions sniff.} + * + * PHP version All + * + * @since 5.5 + * @since 7.1.0 Now extends the `AbstractRemovedFeatureSniff` instead of the base `Sniff` class. + */ +class RemovedExtensionsSniff extends AbstractRemovedFeatureSniff +{ + /** + * A list of functions to whitelist, if any. + * + * This is intended for projects using functions which start with the same + * prefix as one of the removed extensions. + * + * This property can be set from the ruleset, like so: + * <rule ref="PHPCompatibility.Extensions.RemovedExtensions"> + * <properties> + * <property name="functionWhitelist" type="array" value="mysql_to_rfc3339,mysql_another_function" /> + * </properties> + * </rule> + * + * @since 7.0.2 + * + * @var array + */ + public $functionWhitelist; + + /** + * A list of removed extensions with their alternative, if any. + * + * The array lists : version number with false (deprecated) and true (removed). + * If's sufficient to list the first version where the extension was deprecated/removed. + * + * @since 5.5 + * + * @var array(string => array(string => bool|string|null)) + */ + protected $removedExtensions = array( + 'activescript' => array( + '5.1' => true, + 'alternative' => 'pecl/activescript', + ), + 'cpdf' => array( + '5.1' => true, + 'alternative' => 'pecl/pdflib', + ), + 'dbase' => array( + '5.3' => true, + 'alternative' => null, + ), + 'dbx' => array( + '5.1' => true, + 'alternative' => 'pecl/dbx', + ), + 'dio' => array( + '5.1' => true, + 'alternative' => 'pecl/dio', + ), + 'ereg' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'pcre', + ), + 'fam' => array( + '5.1' => true, + 'alternative' => null, + ), + 'fbsql' => array( + '5.3' => true, + 'alternative' => null, + ), + 'fdf' => array( + '5.3' => true, + 'alternative' => 'pecl/fdf', + ), + 'filepro' => array( + '5.2' => true, + 'alternative' => null, + ), + 'hw_api' => array( + '5.2' => true, + 'alternative' => null, + ), + 'ibase' => array( + '7.4' => true, + 'alternative' => 'pecl/ibase', + ), + 'ingres' => array( + '5.1' => true, + 'alternative' => 'pecl/ingres', + ), + 'ircg' => array( + '5.1' => true, + 'alternative' => null, + ), + 'mcrypt' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'openssl (preferred) or pecl/mcrypt once available', + ), + 'mcve' => array( + '5.1' => true, + 'alternative' => 'pecl/mcve', + ), + 'ming' => array( + '5.3' => true, + 'alternative' => 'pecl/ming', + ), + 'mnogosearch' => array( + '5.1' => true, + 'alternative' => null, + ), + 'msql' => array( + '5.3' => true, + 'alternative' => null, + ), + 'mssql' => array( + '7.0' => true, + 'alternative' => null, + ), + 'mysql_' => array( + '5.5' => false, + '7.0' => true, + 'alternative' => 'mysqli', + ), + 'ncurses' => array( + '5.3' => true, + 'alternative' => 'pecl/ncurses', + ), + 'oracle' => array( + '5.1' => true, + 'alternative' => 'oci8 or pdo_oci', + ), + 'ovrimos' => array( + '5.1' => true, + 'alternative' => null, + ), + 'pfpro_' => array( + '5.1' => true, + 'alternative' => null, + ), + 'recode' => array( + '7.4' => true, + 'alternative' => 'iconv or mbstring', + ), + 'sqlite' => array( + '5.4' => true, + 'alternative' => null, + ), + // Has to be before `sybase` as otherwise it will never match. + 'sybase_ct' => array( + '7.0' => true, + 'alternative' => null, + ), + 'sybase' => array( + '5.3' => true, + 'alternative' => 'sybase_ct', + ), + 'w32api' => array( + '5.1' => true, + 'alternative' => 'pecl/ffi', + ), + 'wddx' => array( + '7.4' => true, + 'alternative' => 'pecl/wddx', + ), + 'yp' => array( + '5.1' => true, + 'alternative' => null, + ), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of function names. + $this->removedExtensions = $this->arrayKeysToLowercase($this->removedExtensions); + + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Find the next non-empty token. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + if ($tokens[$openBracket]['code'] !== \T_OPEN_PARENTHESIS) { + // Not a function call. + return; + } + + if (isset($tokens[$openBracket]['parenthesis_closer']) === false) { + // Not a function call. + return; + } + + // Find the previous non-empty token. + $search = Tokens::$emptyTokens; + $search[] = \T_BITWISE_AND; + $previous = $phpcsFile->findPrevious($search, ($stackPtr - 1), null, true); + if ($tokens[$previous]['code'] === \T_FUNCTION) { + // It's a function definition, not a function call. + return; + } + + if ($tokens[$previous]['code'] === \T_NEW) { + // We are creating an object, not calling a function. + return; + } + + if ($tokens[$previous]['code'] === \T_OBJECT_OPERATOR) { + // We are calling a method of an object. + return; + } + + $function = $tokens[$stackPtr]['content']; + $functionLc = strtolower($function); + + if ($this->isWhiteListed($functionLc) === true) { + // Function is whitelisted. + return; + } + + foreach ($this->removedExtensions as $extension => $versionList) { + if (strpos($functionLc, $extension) === 0) { + $itemInfo = array( + 'name' => $extension, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + break; + } + } + } + + + /** + * Is the current function being checked whitelisted ? + * + * Parsing the list late as it may be provided as a property, but also inline. + * + * @since 7.0.2 + * + * @param string $content Content of the current token. + * + * @return bool + */ + protected function isWhiteListed($content) + { + if (isset($this->functionWhitelist) === false) { + return false; + } + + if (\is_string($this->functionWhitelist) === true) { + if (strpos($this->functionWhitelist, ',') !== false) { + $this->functionWhitelist = explode(',', $this->functionWhitelist); + } else { + $this->functionWhitelist = (array) $this->functionWhitelist; + } + } + + if (\is_array($this->functionWhitelist) === true) { + $this->functionWhitelist = array_map('strtolower', $this->functionWhitelist); + return \in_array($content, $this->functionWhitelist, true); + } + + return false; + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->removedExtensions[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return "Extension '%s' is "; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenParameterShadowSuperGlobalsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenParameterShadowSuperGlobalsSniff.php new file mode 100644 index 00000000..0f52af71 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenParameterShadowSuperGlobalsSniff.php @@ -0,0 +1,79 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionDeclarations; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; + +/** + * Detect the use of superglobals as parameters for functions, support for which was removed in PHP 5.4. + * + * {@internal List of superglobals is maintained in the parent class.} + * + * PHP version 5.4 + * + * @link https://www.php.net/manual/en/migration54.incompatible.php + * + * @since 7.0.0 + */ +class ForbiddenParameterShadowSuperGlobalsSniff extends Sniff +{ + + /** + * Register the tokens to listen for. + * + * @since 7.0.0 + * @since 7.1.3 Allows for closures. + * + * @return array + */ + public function register() + { + return array( + \T_FUNCTION, + \T_CLOSURE, + ); + } + + /** + * Processes the test. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('5.4') === false) { + return; + } + + // Get all parameters from function signature. + $parameters = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($parameters) || \is_array($parameters) === false) { + return; + } + + foreach ($parameters as $param) { + if (isset($this->superglobals[$param['name']]) === true) { + $error = 'Parameter shadowing super global (%s) causes fatal error since PHP 5.4'; + $errorCode = $this->stringToErrorCode(substr($param['name'], 1)) . 'Found'; + $data = array($param['name']); + + $phpcsFile->addError($error, $param['token'], $errorCode, $data); + } + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenParametersWithSameNameSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenParametersWithSameNameSniff.php new file mode 100644 index 00000000..e94461ca --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenParametersWithSameNameSniff.php @@ -0,0 +1,88 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionDeclarations; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; + +/** + * Functions can not have multiple parameters with the same name since PHP 7.0. + * + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/migration70.incompatible.php#migration70.incompatible.other.func-parameters + * + * @since 7.0.0 + */ +class ForbiddenParametersWithSameNameSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * @since 7.1.3 Allows for closures. + * + * @return array + */ + public function register() + { + return array( + \T_FUNCTION, + \T_CLOSURE, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + // Skip function without body. + if (isset($token['scope_opener']) === false) { + return; + } + + // Get all parameters from method signature. + $parameters = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($parameters) || \is_array($parameters) === false) { + return; + } + + $paramNames = array(); + foreach ($parameters as $param) { + $paramNames[] = $param['name']; + } + + if (\count($paramNames) !== \count(array_unique($paramNames))) { + $phpcsFile->addError( + 'Functions can not have multiple parameters with the same name since PHP 7.0', + $stackPtr, + 'Found' + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenToStringParametersSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenToStringParametersSniff.php new file mode 100644 index 00000000..1625a4fa --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenToStringParametersSniff.php @@ -0,0 +1,99 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionDeclarations; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; + +/** + * As of PHP 5.3, the __toString() magic method can no longer accept arguments. + * + * Sister-sniff to `PHPCompatibility.MethodUse.ForbiddenToStringParameters`. + * + * PHP version 5.3 + * + * @link https://www.php.net/manual/en/migration53.incompatible.php + * @link https://www.php.net/manual/en/language.oop5.magic.php#object.tostring + * + * @since 9.2.0 + */ +class ForbiddenToStringParametersSniff extends Sniff +{ + + /** + * Valid scopes for the __toString() method to live in. + * + * @since 9.2.0 + * @since 9.3.2 Visibility changed from `public` to `protected`. + * + * @var array + */ + protected $ooScopeTokens = array( + 'T_CLASS' => true, + 'T_INTERFACE' => true, + 'T_TRAIT' => true, + 'T_ANON_CLASS' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + return array(\T_FUNCTION); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('5.3') === false) { + return; + } + + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if (strtolower($functionName) !== '__tostring') { + // Not the right function. + return; + } + + if ($this->validDirectScope($phpcsFile, $stackPtr, $this->ooScopeTokens) === false) { + // Function, not method. + return; + } + + $params = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($params)) { + // Function declared without parameters. + return; + } + + $phpcsFile->addError( + 'The __toString() magic method can no longer accept arguments since PHP 5.3', + $stackPtr, + 'Declared' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenVariableNamesInClosureUseSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenVariableNamesInClosureUseSniff.php new file mode 100644 index 00000000..2e72c05e --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenVariableNamesInClosureUseSniff.php @@ -0,0 +1,122 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionDeclarations; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect variable names forbidden to be used in closure `use` statements. + * + * Variables bound to a closure via the `use` construct cannot use the same name + * as any superglobals, `$this`, or any parameter since PHP 7.1. + * + * PHP version 7.1 + * + * @link https://www.php.net/manual/en/migration71.incompatible.php#migration71.incompatible.lexical-names + * @link https://www.php.net/manual/en/functions.anonymous.php + * + * @since 7.1.4 + */ +class ForbiddenVariableNamesInClosureUseSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.1.4 + * + * @return array + */ + public function register() + { + return array(\T_USE); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.1') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + // Verify this use statement is used with a closure - if so, it has to have parenthesis before it. + $previousNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true, null, true); + if ($previousNonEmpty === false || $tokens[$previousNonEmpty]['code'] !== \T_CLOSE_PARENTHESIS + || isset($tokens[$previousNonEmpty]['parenthesis_opener']) === false + ) { + return; + } + + // ... and (a variable within) parenthesis after it. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS) { + return; + } + + if (isset($tokens[$nextNonEmpty]['parenthesis_closer']) === false) { + // Live coding. + return; + } + + $closurePtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($tokens[$previousNonEmpty]['parenthesis_opener'] - 1), null, true); + if ($closurePtr === false || $tokens[$closurePtr]['code'] !== \T_CLOSURE) { + return; + } + + // Get the parameters declared by the closure. + $closureParams = PHPCSHelper::getMethodParameters($phpcsFile, $closurePtr); + + $errorMsg = 'Variables bound to a closure via the use construct cannot use the same name as superglobals, $this, or a declared parameter since PHP 7.1. Found: %s'; + + for ($i = ($nextNonEmpty + 1); $i < $tokens[$nextNonEmpty]['parenthesis_closer']; $i++) { + if ($tokens[$i]['code'] !== \T_VARIABLE) { + continue; + } + + $variableName = $tokens[$i]['content']; + + if ($variableName === '$this') { + $phpcsFile->addError($errorMsg, $i, 'FoundThis', array($variableName)); + continue; + } + + if (isset($this->superglobals[$variableName]) === true) { + $phpcsFile->addError($errorMsg, $i, 'FoundSuperglobal', array($variableName)); + continue; + } + + // Check whether it is one of the parameters declared by the closure. + if (empty($closureParams) === false) { + foreach ($closureParams as $param) { + if ($param['name'] === $variableName) { + $phpcsFile->addError($errorMsg, $i, 'FoundShadowParam', array($variableName)); + continue 2; + } + } + } + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewClosureSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewClosureSniff.php new file mode 100644 index 00000000..b71bb320 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewClosureSniff.php @@ -0,0 +1,264 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionDeclarations; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect closures and verify that the features used are supported. + * + * Version based checks: + * - Closures are available since PHP 5.3. + * - Closures can be declared as `static` since PHP 5.4. + * - Closures can use the `$this` variable within a class context since PHP 5.4. + * - Closures can use `self`/`parent`/`static` since PHP 5.4. + * + * Version independent checks: + * - Static closures don't have access to the `$this` variable. + * - Closures declared outside of a class context don't have access to the `$this` + * variable unless bound to an object. + * + * PHP version 5.3 + * PHP version 5.4 + * + * @link https://www.php.net/manual/en/functions.anonymous.php + * @link https://wiki.php.net/rfc/closures + * @link https://wiki.php.net/rfc/closures/object-extension + * + * @since 7.0.0 + */ +class NewClosureSniff extends Sniff +{ + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + return array(\T_CLOSURE); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * @since 7.1.4 - Added check for closure being declared as static < 5.4. + * - Added check for use of `$this` variable in class context < 5.4. + * - Added check for use of `$this` variable in static closures (unsupported). + * - Added check for use of `$this` variable outside class context (unsupported). + * @since 8.2.0 Added check for use of `self`/`static`/`parent` < 5.4. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.2')) { + $phpcsFile->addError( + 'Closures / anonymous functions are not available in PHP 5.2 or earlier', + $stackPtr, + 'Found' + ); + } + + /* + * Closures can only be declared as static since PHP 5.4. + */ + $isStatic = $this->isClosureStatic($phpcsFile, $stackPtr); + if ($this->supportsBelow('5.3') && $isStatic === true) { + $phpcsFile->addError( + 'Closures / anonymous functions could not be declared as static in PHP 5.3 or earlier', + $stackPtr, + 'StaticFound' + ); + } + + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener'], $tokens[$stackPtr]['scope_closer']) === false) { + // Live coding or parse error. + return; + } + + $scopeStart = ($tokens[$stackPtr]['scope_opener'] + 1); + $scopeEnd = $tokens[$stackPtr]['scope_closer']; + $usesThis = $this->findThisUsageInClosure($phpcsFile, $scopeStart, $scopeEnd); + + if ($this->supportsBelow('5.3')) { + /* + * Closures declared within classes only have access to $this since PHP 5.4. + */ + if ($usesThis !== false) { + $thisFound = $usesThis; + do { + $phpcsFile->addError( + 'Closures / anonymous functions did not have access to $this in PHP 5.3 or earlier', + $thisFound, + 'ThisFound' + ); + + $thisFound = $this->findThisUsageInClosure($phpcsFile, ($thisFound + 1), $scopeEnd); + + } while ($thisFound !== false); + } + + /* + * Closures declared within classes only have access to self/parent/static since PHP 5.4. + */ + $usesClassRef = $this->findClassRefUsageInClosure($phpcsFile, $scopeStart, $scopeEnd); + + if ($usesClassRef !== false) { + do { + $phpcsFile->addError( + 'Closures / anonymous functions could not use "%s::" in PHP 5.3 or earlier', + $usesClassRef, + 'ClassRefFound', + array(strtolower($tokens[$usesClassRef]['content'])) + ); + + $usesClassRef = $this->findClassRefUsageInClosure($phpcsFile, ($usesClassRef + 1), $scopeEnd); + + } while ($usesClassRef !== false); + } + } + + /* + * Check for correct usage. + */ + if ($this->supportsAbove('5.4') && $usesThis !== false) { + + $thisFound = $usesThis; + + do { + /* + * Closures only have access to $this if not declared as static. + */ + if ($isStatic === true) { + $phpcsFile->addError( + 'Closures / anonymous functions declared as static do not have access to $this', + $thisFound, + 'ThisFoundInStatic' + ); + } + + /* + * Closures only have access to $this if used within a class context. + */ + elseif ($this->inClassScope($phpcsFile, $stackPtr, false) === false) { + $phpcsFile->addWarning( + 'Closures / anonymous functions only have access to $this if used within a class or when bound to an object using bindTo(). Please verify.', + $thisFound, + 'ThisFoundOutsideClass' + ); + } + + $thisFound = $this->findThisUsageInClosure($phpcsFile, ($thisFound + 1), $scopeEnd); + + } while ($thisFound !== false); + } + + // Prevent double reporting for nested closures. + return $scopeEnd; + } + + + /** + * Check whether the closure is declared as static. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return bool + */ + protected function isClosureStatic(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true, null, true); + + return ($prevToken !== false && $tokens[$prevToken]['code'] === \T_STATIC); + } + + + /** + * Check if the code within a closure uses the $this variable. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $startToken The position within the closure to continue searching from. + * @param int $endToken The closure scope closer to stop searching at. + * + * @return int|false The stackPtr to the first $this usage if found or false if + * $this is not used. + */ + protected function findThisUsageInClosure(File $phpcsFile, $startToken, $endToken) + { + // Make sure the $startToken is valid. + if ($startToken >= $endToken) { + return false; + } + + return $phpcsFile->findNext( + \T_VARIABLE, + $startToken, + $endToken, + false, + '$this' + ); + } + + /** + * Check if the code within a closure uses "self/parent/static". + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $startToken The position within the closure to continue searching from. + * @param int $endToken The closure scope closer to stop searching at. + * + * @return int|false The stackPtr to the first classRef usage if found or false if + * they are not used. + */ + protected function findClassRefUsageInClosure(File $phpcsFile, $startToken, $endToken) + { + // Make sure the $startToken is valid. + if ($startToken >= $endToken) { + return false; + } + + $tokens = $phpcsFile->getTokens(); + $classRef = $phpcsFile->findNext(array(\T_SELF, \T_PARENT, \T_STATIC), $startToken, $endToken); + + if ($classRef === false || $tokens[$classRef]['code'] !== \T_STATIC) { + return $classRef; + } + + // T_STATIC, make sure it is used as a class reference. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($classRef + 1), $endToken, true); + if ($next === false || $tokens[$next]['code'] !== \T_DOUBLE_COLON) { + return false; + } + + return $classRef; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewExceptionsFromToStringSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewExceptionsFromToStringSniff.php new file mode 100644 index 00000000..05648961 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewExceptionsFromToStringSniff.php @@ -0,0 +1,171 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionDeclarations; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * As of PHP 7.4, throwing exceptions from a `__toString()` method is allowed. + * + * PHP version 7.4 + * + * @link https://wiki.php.net/rfc/tostring_exceptions + * @link https://www.php.net/manual/en/language.oop5.magic.php#object.tostring + * + * @since 9.2.0 + */ +class NewExceptionsFromToStringSniff extends Sniff +{ + + /** + * Valid scopes for the __toString() method to live in. + * + * @since 9.2.0 + * @since 9.3.0 Visibility changed from `public` to `protected`. + * + * @var array + */ + protected $ooScopeTokens = array( + 'T_CLASS' => true, + 'T_TRAIT' => true, + 'T_ANON_CLASS' => true, + ); + + /** + * Tokens which should be ignored when they preface a function declaration + * when trying to find the docblock (if any). + * + * Array will be added to in the register() method. + * + * @since 9.3.0 + * + * @var array + */ + private $docblockIgnoreTokens = array( + \T_WHITESPACE => \T_WHITESPACE, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + // Enhance the array of tokens to ignore for finding the docblock. + $this->docblockIgnoreTokens += Tokens::$methodPrefixes; + if (isset(Tokens::$phpcsCommentTokens)) { + $this->docblockIgnoreTokens += Tokens::$phpcsCommentTokens; + } + + return array(\T_FUNCTION); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('7.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_opener'], $tokens[$stackPtr]['scope_closer']) === false) { + // Abstract function, interface function, live coding or parse error. + return; + } + + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if (strtolower($functionName) !== '__tostring') { + // Not the right function. + return; + } + + if ($this->validDirectScope($phpcsFile, $stackPtr, $this->ooScopeTokens) === false) { + // Function, not method. + return; + } + + /* + * Examine the content of the function. + */ + $error = 'Throwing exceptions from __toString() was not allowed prior to PHP 7.4'; + $throwPtr = $tokens[$stackPtr]['scope_opener']; + $errorThrown = false; + + do { + $throwPtr = $phpcsFile->findNext(\T_THROW, ($throwPtr + 1), $tokens[$stackPtr]['scope_closer']); + if ($throwPtr === false) { + break; + } + + $conditions = $tokens[$throwPtr]['conditions']; + $conditions = array_reverse($conditions, true); + $inTryCatch = false; + foreach ($conditions as $ptr => $type) { + if ($type === \T_TRY) { + $inTryCatch = true; + break; + } + + if ($ptr === $stackPtr) { + // Don't check the conditions outside the function scope. + break; + } + } + + if ($inTryCatch === false) { + $phpcsFile->addError($error, $throwPtr, 'Found'); + $errorThrown = true; + } + } while (true); + + if ($errorThrown === true) { + // We've already thrown an error for this method, no need to examine the docblock. + return; + } + + /* + * Check whether the function has a docblock and if so, whether it contains a @throws tag. + * + * {@internal This can be partially replaced by the findCommentAboveFunction() + * utility function in due time.} + */ + $commentEnd = $phpcsFile->findPrevious($this->docblockIgnoreTokens, ($stackPtr - 1), null, true); + if ($commentEnd === false || $tokens[$commentEnd]['code'] !== \T_DOC_COMMENT_CLOSE_TAG) { + return; + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] !== '@throws') { + continue; + } + + // Found a throws tag. + $phpcsFile->addError($error, $stackPtr, 'ThrowsTagFoundInDocblock'); + break; + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewNullableTypesSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewNullableTypesSniff.php new file mode 100644 index 00000000..8dc0c416 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewNullableTypesSniff.php @@ -0,0 +1,169 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionDeclarations; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Nullable parameter type declarations and return types are available since PHP 7.1. + * + * PHP version 7.1 + * + * @link https://www.php.net/manual/en/migration71.new-features.php#migration71.new-features.nullable-types + * @link https://wiki.php.net/rfc/nullable_types + * @link https://www.php.net/manual/en/functions.arguments.php#example-146 + * + * @since 7.0.7 + */ +class NewNullableTypesSniff extends Sniff +{ + /** + * Returns an array of tokens this test wants to listen for. + * + * {@internal Not sniffing for T_NULLABLE which was introduced in PHPCS 2.7.2 + * as in that case we can't distinguish between parameter type hints and + * return type hints for the error message.} + * + * @since 7.0.7 + * + * @return array + */ + public function register() + { + $tokens = array( + \T_FUNCTION, + \T_CLOSURE, + ); + + if (\defined('T_RETURN_TYPE')) { + $tokens[] = \T_RETURN_TYPE; + } + + return $tokens; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.7 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $tokenCode = $tokens[$stackPtr]['code']; + + if ($tokenCode === \T_FUNCTION || $tokenCode === \T_CLOSURE) { + $this->processFunctionDeclaration($phpcsFile, $stackPtr); + + // Deal with older PHPCS version which don't recognize return type hints + // as well as newer PHPCS versions (3.3.0+) where the tokenization has changed. + $returnTypeHint = $this->getReturnTypeHintToken($phpcsFile, $stackPtr); + if ($returnTypeHint !== false) { + $this->processReturnType($phpcsFile, $returnTypeHint); + } + } else { + $this->processReturnType($phpcsFile, $stackPtr); + } + } + + + /** + * Process this test for function tokens. + * + * @since 7.0.7 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + protected function processFunctionDeclaration(File $phpcsFile, $stackPtr) + { + $params = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + + if (empty($params) === false && \is_array($params)) { + foreach ($params as $param) { + if ($param['nullable_type'] === true) { + $phpcsFile->addError( + 'Nullable type declarations are not supported in PHP 7.0 or earlier. Found: %s', + $param['token'], + 'typeDeclarationFound', + array($param['type_hint']) + ); + } + } + } + } + + + /** + * Process this test for return type tokens. + * + * @since 7.0.7 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + protected function processReturnType(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[($stackPtr - 1)]['code']) === false) { + return; + } + + $previous = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + // Deal with namespaced class names. + if ($tokens[$previous]['code'] === \T_NS_SEPARATOR) { + $validTokens = Tokens::$emptyTokens; + $validTokens[\T_STRING] = true; + $validTokens[\T_NS_SEPARATOR] = true; + + $stackPtr--; + + while (isset($validTokens[$tokens[($stackPtr - 1)]['code']]) === true) { + $stackPtr--; + } + + $previous = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + } + + // T_NULLABLE token was introduced in PHPCS 2.7.2. Before that it identified as T_INLINE_THEN. + if ((\defined('T_NULLABLE') === true && $tokens[$previous]['type'] === 'T_NULLABLE') + || (\defined('T_NULLABLE') === false && $tokens[$previous]['code'] === \T_INLINE_THEN) + ) { + $phpcsFile->addError( + 'Nullable return types are not supported in PHP 7.0 or earlier.', + $stackPtr, + 'returnTypeFound' + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewParamTypeDeclarationsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewParamTypeDeclarationsSniff.php new file mode 100644 index 00000000..6ad98b6a --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewParamTypeDeclarationsSniff.php @@ -0,0 +1,237 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionDeclarations; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; + +/** + * Detect and verify the use of parameter type declarations in function declarations. + * + * Parameter type declarations - class/interface names only - is available since PHP 5.0. + * - Since PHP 5.1, the `array` keyword can be used. + * - Since PHP 5.2, `self` and `parent` can be used. Previously, those were interpreted as + * class names. + * - Since PHP 5.4, the `callable` keyword. + * - Since PHP 7.0, scalar type declarations are available. + * - Since PHP 7.1, the `iterable` pseudo-type is available. + * - Since PHP 7.2, the generic `object` type is available. + * + * Additionally, this sniff does a cursory check for typical invalid type declarations, + * such as: + * - `boolean` (should be `bool`), `integer` (should be `int`) and `static`. + * - `self`/`parent` as type declaration used outside class context throws a fatal error since PHP 7.0. + * + * PHP version 5.0+ + * + * @link https://www.php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration + * @link https://wiki.php.net/rfc/callable + * @link https://wiki.php.net/rfc/scalar_type_hints_v5 + * @link https://wiki.php.net/rfc/iterable + * @link https://wiki.php.net/rfc/object-typehint + * + * @since 7.0.0 + * @since 7.1.0 Now extends the `AbstractNewFeatureSniff` instead of the base `Sniff` class. + * @since 9.0.0 Renamed from `NewScalarTypeDeclarationsSniff` to `NewParamTypeDeclarationsSniff`. + */ +class NewParamTypeDeclarationsSniff extends AbstractNewFeatureSniff +{ + + /** + * A list of new types. + * + * The array lists : version number with false (not present) or true (present). + * If's sufficient to list the first version where the keyword appears. + * + * @since 7.0.0 + * @since 7.0.3 Now lists all param type declarations, not just the PHP 7+ scalar ones. + * + * @var array(string => array(string => bool)) + */ + protected $newTypes = array( + 'array' => array( + '5.0' => false, + '5.1' => true, + ), + 'self' => array( + '5.1' => false, + '5.2' => true, + ), + 'parent' => array( + '5.1' => false, + '5.2' => true, + ), + 'callable' => array( + '5.3' => false, + '5.4' => true, + ), + 'int' => array( + '5.6' => false, + '7.0' => true, + ), + 'float' => array( + '5.6' => false, + '7.0' => true, + ), + 'bool' => array( + '5.6' => false, + '7.0' => true, + ), + 'string' => array( + '5.6' => false, + '7.0' => true, + ), + 'iterable' => array( + '7.0' => false, + '7.1' => true, + ), + 'object' => array( + '7.1' => false, + '7.2' => true, + ), + ); + + + /** + * Invalid types + * + * The array lists : the invalid type hint => what was probably intended/alternative. + * + * @since 7.0.3 + * + * @var array(string => string) + */ + protected $invalidTypes = array( + 'static' => 'self', + 'boolean' => 'bool', + 'integer' => 'int', + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * @since 7.1.3 Now also checks closures. + * + * @return array + */ + public function register() + { + return array( + \T_FUNCTION, + \T_CLOSURE, + ); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * @since 7.0.3 - Added check for non-scalar type declarations. + * - Added check for invalid type declarations. + * - Added check for usage of `self` type declaration outside + * class scope. + * @since 8.2.0 Added check for `parent` type declaration outside class scope. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Get all parameters from method signature. + $paramNames = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($paramNames)) { + return; + } + + $supportsPHP4 = $this->supportsBelow('4.4'); + + foreach ($paramNames as $param) { + if ($param['type_hint'] === '') { + continue; + } + + // Strip off potential nullable indication. + $typeHint = ltrim($param['type_hint'], '?'); + + if ($supportsPHP4 === true) { + $phpcsFile->addError( + 'Type declarations were not present in PHP 4.4 or earlier.', + $param['token'], + 'TypeHintFound' + ); + + } elseif (isset($this->newTypes[$typeHint])) { + $itemInfo = array( + 'name' => $typeHint, + ); + $this->handleFeature($phpcsFile, $param['token'], $itemInfo); + + // As of PHP 7.0, using `self` or `parent` outside class scope throws a fatal error. + // Only throw this error for PHP 5.2+ as before that the "type hint not supported" error + // will be thrown. + if (($typeHint === 'self' || $typeHint === 'parent') + && $this->inClassScope($phpcsFile, $stackPtr, false) === false + && $this->supportsAbove('5.2') !== false + ) { + $phpcsFile->addError( + "'%s' type cannot be used outside of class scope", + $param['token'], + ucfirst($typeHint) . 'OutsideClassScopeFound', + array($typeHint) + ); + } + } elseif (isset($this->invalidTypes[$typeHint])) { + $error = "'%s' is not a valid type declaration. Did you mean %s ?"; + $data = array( + $typeHint, + $this->invalidTypes[$typeHint], + ); + + $phpcsFile->addError($error, $param['token'], 'InvalidTypeHintFound', $data); + } + } + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newTypes[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return "'%s' type declaration is not present in PHP version %s or earlier"; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewReturnTypeDeclarationsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewReturnTypeDeclarationsSniff.php new file mode 100644 index 00000000..3e225616 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewReturnTypeDeclarationsSniff.php @@ -0,0 +1,194 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionDeclarations; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect and verify the use of return type declarations in function declarations. + * + * Return type declarations are available since PHP 7.0. + * - Since PHP 7.1, the `iterable` and `void` pseudo-types are available. + * - Since PHP 7.2, the generic `object` type is available. + * + * PHP version 7.0+ + * + * @link https://www.php.net/manual/en/migration70.new-features.php#migration70.new-features.return-type-declarations + * @link https://www.php.net/manual/en/functions.returning-values.php#functions.returning-values.type-declaration + * @link https://wiki.php.net/rfc/return_types + * @link https://wiki.php.net/rfc/iterable + * @link https://wiki.php.net/rfc/void_return_type + * @link https://wiki.php.net/rfc/object-typehint + * + * @since 7.0.0 + * @since 7.1.0 Now extends the `AbstractNewFeatureSniff` instead of the base `Sniff` class. + * @since 7.1.2 Renamed from `NewScalarReturnTypeDeclarationsSniff` to `NewReturnTypeDeclarationsSniff`. + */ +class NewReturnTypeDeclarationsSniff extends AbstractNewFeatureSniff +{ + + /** + * A list of new types + * + * The array lists : version number with false (not present) or true (present). + * If's sufficient to list the first version where the keyword appears. + * + * @since 7.0.0 + * + * @var array(string => array(string => bool)) + */ + protected $newTypes = array( + 'int' => array( + '5.6' => false, + '7.0' => true, + ), + 'float' => array( + '5.6' => false, + '7.0' => true, + ), + 'bool' => array( + '5.6' => false, + '7.0' => true, + ), + 'string' => array( + '5.6' => false, + '7.0' => true, + ), + 'array' => array( + '5.6' => false, + '7.0' => true, + ), + 'callable' => array( + '5.6' => false, + '7.0' => true, + ), + 'parent' => array( + '5.6' => false, + '7.0' => true, + ), + 'self' => array( + '5.6' => false, + '7.0' => true, + ), + 'Class name' => array( + '5.6' => false, + '7.0' => true, + ), + + 'iterable' => array( + '7.0' => false, + '7.1' => true, + ), + 'void' => array( + '7.0' => false, + '7.1' => true, + ), + + 'object' => array( + '7.1' => false, + '7.2' => true, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * @since 7.1.2 Now also checks based on the function and closure keywords. + * + * @return array + */ + public function register() + { + $tokens = array( + \T_FUNCTION, + \T_CLOSURE, + ); + + if (\defined('T_RETURN_TYPE')) { + $tokens[] = \T_RETURN_TYPE; + } + + return $tokens; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Deal with older PHPCS version which don't recognize return type hints + // as well as newer PHPCS versions (3.3.0+) where the tokenization has changed. + if ($tokens[$stackPtr]['code'] === \T_FUNCTION || $tokens[$stackPtr]['code'] === \T_CLOSURE) { + $returnTypeHint = $this->getReturnTypeHintToken($phpcsFile, $stackPtr); + if ($returnTypeHint !== false) { + $stackPtr = $returnTypeHint; + } + } + + if (isset($this->newTypes[$tokens[$stackPtr]['content']]) === true) { + $itemInfo = array( + 'name' => $tokens[$stackPtr]['content'], + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + // Handle class name based return types. + elseif ($tokens[$stackPtr]['code'] === \T_STRING + || (\defined('T_RETURN_TYPE') && $tokens[$stackPtr]['code'] === \T_RETURN_TYPE) + ) { + $itemInfo = array( + 'name' => 'Class name', + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newTypes[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return '%s return type is not present in PHP version %s or earlier'; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NonStaticMagicMethodsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NonStaticMagicMethodsSniff.php new file mode 100644 index 00000000..a86d56ef --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NonStaticMagicMethodsSniff.php @@ -0,0 +1,216 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionDeclarations; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Verifies the use of the correct visibility and static properties of magic methods. + * + * The requirements have always existed, but as of PHP 5.3, a warning will be thrown + * when magic methods have the wrong modifiers. + * + * PHP version 5.3 + * + * @link https://www.php.net/manual/en/language.oop5.magic.php + * + * @since 5.5 + * @since 5.6 Now extends the base `Sniff` class. + */ +class NonStaticMagicMethodsSniff extends Sniff +{ + + /** + * A list of PHP magic methods and their visibility and static requirements. + * + * Method names in the array should be all *lowercase*. + * Visibility can be either 'public', 'protected' or 'private'. + * Static can be either 'true' - *must* be static, or 'false' - *must* be non-static. + * When a method does not have a specific requirement for either visibility or static, + * do *not* add the key. + * + * @since 5.5 + * @since 5.6 The array format has changed to allow the sniff to also verify the + * use of the correct visibility for a magic method. + * + * @var array(string) + */ + protected $magicMethods = array( + '__construct' => array( + 'static' => false, + ), + '__destruct' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__clone' => array( + 'static' => false, + ), + '__get' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__set' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__isset' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__unset' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__call' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__callstatic' => array( + 'visibility' => 'public', + 'static' => true, + ), + '__sleep' => array( + 'visibility' => 'public', + ), + '__tostring' => array( + 'visibility' => 'public', + ), + '__set_state' => array( + 'visibility' => 'public', + 'static' => true, + ), + '__debuginfo' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__invoke' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__serialize' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__unserialize' => array( + 'visibility' => 'public', + 'static' => false, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * @since 5.6 Now also checks traits. + * @since 7.1.4 Now also checks anonymous classes. + * + * @return array + */ + public function register() + { + $targets = array( + \T_CLASS, + \T_INTERFACE, + \T_TRAIT, + ); + + if (\defined('T_ANON_CLASS')) { + $targets[] = \T_ANON_CLASS; + } + + return $targets; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Should be removed, the requirement was previously also there, 5.3 just started throwing a warning about it. + if ($this->supportsAbove('5.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $classScopeCloser = $tokens[$stackPtr]['scope_closer']; + $functionPtr = $stackPtr; + + // Find all the functions in this class or interface. + while (($functionToken = $phpcsFile->findNext(\T_FUNCTION, $functionPtr, $classScopeCloser)) !== false) { + /* + * Get the scope closer for this function in order to know how + * to advance to the next function. + * If no body of function (e.g. for interfaces), there is + * no closing curly brace; advance the pointer differently. + */ + if (isset($tokens[$functionToken]['scope_closer'])) { + $scopeCloser = $tokens[$functionToken]['scope_closer']; + } else { + $scopeCloser = ($functionToken + 1); + } + + $methodName = $phpcsFile->getDeclarationName($functionToken); + $methodNameLc = strtolower($methodName); + if (isset($this->magicMethods[$methodNameLc]) === false) { + $functionPtr = $scopeCloser; + continue; + } + + $methodProperties = $phpcsFile->getMethodProperties($functionToken); + $errorCodeBase = $this->stringToErrorCode($methodNameLc); + + if (isset($this->magicMethods[$methodNameLc]['visibility']) && $this->magicMethods[$methodNameLc]['visibility'] !== $methodProperties['scope']) { + $error = 'Visibility for magic method %s must be %s. Found: %s'; + $errorCode = $errorCodeBase . 'MethodVisibility'; + $data = array( + $methodName, + $this->magicMethods[$methodNameLc]['visibility'], + $methodProperties['scope'], + ); + + $phpcsFile->addError($error, $functionToken, $errorCode, $data); + } + + if (isset($this->magicMethods[$methodNameLc]['static']) && $this->magicMethods[$methodNameLc]['static'] !== $methodProperties['is_static']) { + $error = 'Magic method %s cannot be defined as static.'; + $errorCode = $errorCodeBase . 'MethodStatic'; + $data = array($methodName); + + if ($this->magicMethods[$methodNameLc]['static'] === true) { + $error = 'Magic method %s must be defined as static.'; + $errorCode = $errorCodeBase . 'MethodNonStatic'; + } + + $phpcsFile->addError($error, $functionToken, $errorCode, $data); + } + + // Advance to next function. + $functionPtr = $scopeCloser; + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/NewMagicMethodsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/NewMagicMethodsSniff.php new file mode 100644 index 00000000..4dc08f88 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/NewMagicMethodsSniff.php @@ -0,0 +1,231 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionNameRestrictions; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHP_CodeSniffer_File as File; + +/** + * Warns for non-magic behaviour of magic methods prior to becoming magic. + * + * PHP version 5.0+ + * + * @link https://www.php.net/manual/en/language.oop5.magic.php + * @link https://wiki.php.net/rfc/closures#additional_goodyinvoke + * @link https://wiki.php.net/rfc/debug-info + * + * @since 7.0.4 + * @since 7.1.0 Now extends the `AbstractNewFeatureSniff` instead of the base `Sniff` class. + */ +class NewMagicMethodsSniff extends AbstractNewFeatureSniff +{ + + /** + * A list of new magic methods, not considered magic in older versions. + * + * Method names in the array should be all *lowercase*. + * The array lists : version number with false (not magic) or true (magic). + * If's sufficient to list the first version where the method became magic. + * + * @since 7.0.4 + * + * @var array(string => array(string => bool|string)) + */ + protected $newMagicMethods = array( + '__construct' => array( + '4.4' => false, + '5.0' => true, + ), + '__destruct' => array( + '4.4' => false, + '5.0' => true, + ), + '__get' => array( + '4.4' => false, + '5.0' => true, + ), + + '__isset' => array( + '5.0' => false, + '5.1' => true, + ), + '__unset' => array( + '5.0' => false, + '5.1' => true, + ), + '__set_state' => array( + '5.0' => false, + '5.1' => true, + ), + + '__callstatic' => array( + '5.2' => false, + '5.3' => true, + ), + '__invoke' => array( + '5.2' => false, + '5.3' => true, + ), + + '__debuginfo' => array( + '5.5' => false, + '5.6' => true, + ), + + // Special case - only became properly magical in 5.2.0, + // before that it was only called for echo and print. + '__tostring' => array( + '5.1' => false, + '5.2' => true, + 'message' => 'The method %s() was not truly magical in PHP version %s and earlier. The associated magic functionality will only be called when directly combined with echo or print.', + ), + + '__serialize' => array( + '7.3' => false, + '7.4' => true, + ), + '__unserialize' => array( + '7.3' => false, + '7.4' => true, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.4 + * + * @return array + */ + public function register() + { + return array(\T_FUNCTION); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $functionName = $phpcsFile->getDeclarationName($stackPtr); + $functionNameLc = strtolower($functionName); + + if (isset($this->newMagicMethods[$functionNameLc]) === false) { + return; + } + + if ($this->inClassScope($phpcsFile, $stackPtr, false) === false) { + return; + } + + $itemInfo = array( + 'name' => $functionName, + 'nameLc' => $functionNameLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newMagicMethods[$itemInfo['nameLc']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('message'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['error'] = false; // Warning, not error. + $errorInfo['message'] = ''; + + if (empty($itemArray['message']) === false) { + $errorInfo['message'] = $itemArray['message']; + } + + return $errorInfo; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The method %s() was not magical in PHP version %s and earlier. The associated magic functionality will not be invoked.'; + } + + + /** + * Allow for concrete child classes to filter the error message before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param string $error The error message which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return string + */ + protected function filterErrorMsg($error, array $itemInfo, array $errorInfo) + { + if ($errorInfo['message'] !== '') { + $error = $errorInfo['message']; + } + + return $error; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedMagicAutoloadSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedMagicAutoloadSniff.php new file mode 100644 index 00000000..0ea5b0d6 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedMagicAutoloadSniff.php @@ -0,0 +1,92 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionNameRestrictions; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect declaration of the magic `__autoload()` method. + * + * This method has been deprecated in PHP 7.2 in favour of `spl_autoload_register()`. + * + * PHP version 7.2 + * + * @link https://www.php.net/manual/en/migration72.deprecated.php#migration72.deprecated.__autoload-method + * @link https://wiki.php.net/rfc/deprecations_php_7_2#autoload + * @link https://www.php.net/manual/en/function.autoload.php + * + * @since 8.1.0 + * @since 9.0.0 Renamed from `DeprecatedMagicAutoloadSniff` to `RemovedMagicAutoloadSniff`. + */ +class RemovedMagicAutoloadSniff extends Sniff +{ + /** + * Scopes to look for when testing using validDirectScope. + * + * @since 8.1.0 + * + * @var array + */ + private $checkForScopes = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_INTERFACE' => true, + 'T_TRAIT' => true, + 'T_NAMESPACE' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.1.0 + * + * @return array + */ + public function register() + { + return array(\T_FUNCTION); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.2') === false) { + return; + } + + $funcName = $phpcsFile->getDeclarationName($stackPtr); + + if (strtolower($funcName) !== '__autoload') { + return; + } + + if ($this->validDirectScope($phpcsFile, $stackPtr, $this->checkForScopes) !== false) { + return; + } + + if ($this->determineNamespace($phpcsFile, $stackPtr) !== '') { + return; + } + + $phpcsFile->addWarning('Use of __autoload() function is deprecated since PHP 7.2', $stackPtr, 'Found'); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedNamespacedAssertSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedNamespacedAssertSniff.php new file mode 100644 index 00000000..3c3feadc --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedNamespacedAssertSniff.php @@ -0,0 +1,101 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionNameRestrictions; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect declaration of a namespaced function called `assert()`. + * + * As of PHP 7.3, a compile-time deprecation warning will be thrown when a function + * called `assert()` is declared. In PHP 8 this will become a compile-error. + * + * Methods are unaffected. + * Global, non-namespaced, `assert()` function declarations were always a fatal + * "function already declared" error, so not the concern of this sniff. + * + * PHP version 7.3 + * + * @link https://www.php.net/manual/en/migration73.deprecated.php#migration73.deprecated.core.assert + * @link https://wiki.php.net/rfc/deprecations_php_7_3#defining_a_free-standing_assert_function + * @link https://www.php.net/manual/en/function.assert.php + * + * @since 9.0.0 + */ +class RemovedNamespacedAssertSniff extends Sniff +{ + /** + * Scopes in which an `assert` function can be declared without issue. + * + * @since 9.0.0 + * + * @var array + */ + private $scopes = array( + \T_CLASS, + \T_INTERFACE, + \T_TRAIT, + \T_CLOSURE, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.0.0 + * + * @return array + */ + public function register() + { + // Enrich the scopes list. + if (\defined('T_ANON_CLASS')) { + $this->scopes[] = \T_ANON_CLASS; + } + + return array(\T_FUNCTION); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.3') === false) { + return; + } + + $funcName = $phpcsFile->getDeclarationName($stackPtr); + + if (strtolower($funcName) !== 'assert') { + return; + } + + if ($phpcsFile->hasCondition($stackPtr, $this->scopes) === true) { + return; + } + + if ($this->determineNamespace($phpcsFile, $stackPtr) === '') { + // Not a namespaced function declaration. This may be a parse error, but not our concern. + return; + } + + $phpcsFile->addWarning('Declaring a free-standing function called assert() is deprecated since PHP 7.3.', $stackPtr, 'Found'); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedPHP4StyleConstructorsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedPHP4StyleConstructorsSniff.php new file mode 100644 index 00000000..a888f51d --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedPHP4StyleConstructorsSniff.php @@ -0,0 +1,158 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionNameRestrictions; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect declarations of PHP 4 style constructors which are deprecated as of PHP 7.0.0. + * + * PHP 4 style constructors - methods that have the same name as the class they are defined in - + * are deprecated as of PHP 7.0.0, and will be removed in the future. + * PHP 7 will emit `E_DEPRECATED` if a PHP 4 constructor is the only constructor defined + * within a class. Classes that implement a `__construct()` method are unaffected. + * + * Note: Methods with the same name as the class they are defined in _within a namespace_ + * are not recognized as constructors anyway and therefore outside the scope of this sniff. + * + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/migration70.deprecated.php#migration70.deprecated.php4-constructors + * @link https://wiki.php.net/rfc/remove_php4_constructors + * @link https://www.php.net/manual/en/language.oop5.decon.php + * + * @since 7.0.0 + * @since 7.0.8 This sniff now throws a warning instead of an error as the functionality is + * only deprecated (for now). + * @since 9.0.0 Renamed from `DeprecatedPHP4StyleConstructorsSniff` to `RemovedPHP4StyleConstructorsSniff`. + */ +class RemovedPHP4StyleConstructorsSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + return array( + \T_CLASS, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * @since 7.0.8 The message is downgraded from error to warning as - for now - support + * for PHP4-style constructors is just deprecated, not yet removed. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + if ($this->determineNamespace($phpcsFile, $stackPtr) !== '') { + /* + * Namespaced methods with the same name as the class are treated as + * regular methods, so we can bow out if we're in a namespace. + * + * Note: the exception to this is PHP 5.3.0-5.3.2. This is currently + * not dealt with. + */ + return; + } + + $tokens = $phpcsFile->getTokens(); + + $class = $tokens[$stackPtr]; + + if (isset($class['scope_closer']) === false) { + return; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_STRING) { + // Anonymous class in combination with PHPCS 2.3.x. + return; + } + + $scopeCloser = $class['scope_closer']; + $className = $tokens[$nextNonEmpty]['content']; + + if (empty($className) || \is_string($className) === false) { + return; + } + + $nextFunc = $stackPtr; + $classNameLc = strtolower($className); + $newConstructorFound = false; + $oldConstructorFound = false; + $oldConstructorPos = -1; + while (($nextFunc = $phpcsFile->findNext(array(\T_FUNCTION, \T_DOC_COMMENT_OPEN_TAG), ($nextFunc + 1), $scopeCloser)) !== false) { + // Skip over docblocks. + if ($tokens[$nextFunc]['code'] === \T_DOC_COMMENT_OPEN_TAG) { + $nextFunc = $tokens[$nextFunc]['comment_closer']; + continue; + } + + $functionScopeCloser = $nextFunc; + if (isset($tokens[$nextFunc]['scope_closer'])) { + // Normal (non-interface, non-abstract) method. + $functionScopeCloser = $tokens[$nextFunc]['scope_closer']; + } + + $funcName = $phpcsFile->getDeclarationName($nextFunc); + if (empty($funcName) || \is_string($funcName) === false) { + $nextFunc = $functionScopeCloser; + continue; + } + + $funcNameLc = strtolower($funcName); + + if ($funcNameLc === '__construct') { + $newConstructorFound = true; + } + + if ($funcNameLc === $classNameLc) { + $oldConstructorFound = true; + $oldConstructorPos = $nextFunc; + } + + // If both have been found, no need to continue looping through the functions. + if ($newConstructorFound === true && $oldConstructorFound === true) { + break; + } + + $nextFunc = $functionScopeCloser; + } + + if ($newConstructorFound === false && $oldConstructorFound === true) { + $phpcsFile->addWarning( + 'Use of deprecated PHP4 style class constructor is not supported since PHP 7.', + $oldConstructorPos, + 'Found' + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/ReservedFunctionNamesSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/ReservedFunctionNamesSniff.php new file mode 100644 index 00000000..9ddb9e96 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/ReservedFunctionNamesSniff.php @@ -0,0 +1,205 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionNameRestrictions; + +use Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff as PHPCS_CamelCapsFunctionNameSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Standards_AbstractScopeSniff as PHPCS_AbstractScopeSniff; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * All function and method names starting with double underscore are reserved by PHP. + * + * PHP version All + * + * {@internal Extends an upstream sniff to benefit from the properties contained therein. + * The properties are lists of valid PHP magic function and method names, which + * should be ignored for the purposes of this sniff. + * As this sniff is not PHP version specific, we don't need access to the utility + * methods in the PHPCompatibility\Sniff, so extending the upstream sniff is fine. + * As the upstream sniff checks the same (and more, but we don't need the rest), + * the logic in this sniff is largely the same as used upstream. + * Extending the upstream sniff instead of including it via the ruleset, however, + * prevents hard to debug issues of errors not being reported from the upstream sniff + * if this library is used in combination with other rulesets.} + * + * @link https://www.php.net/manual/en/language.oop5.magic.php + * + * @since 8.2.0 This was previously, since 7.0.3, checked by the upstream sniff. + * @since 9.3.2 The sniff will now ignore functions marked as `@deprecated` by design. + */ +class ReservedFunctionNamesSniff extends PHPCS_CamelCapsFunctionNameSniff +{ + + /** + * Overload the constructor to work round various PHPCS cross-version compatibility issues. + * + * @since 8.2.0 + */ + public function __construct() + { + $scopeTokens = array(\T_CLASS, \T_INTERFACE, \T_TRAIT); + if (\defined('T_ANON_CLASS')) { + $scopeTokens[] = \T_ANON_CLASS; + } + + // Call the grand-parent constructor directly. + PHPCS_AbstractScopeSniff::__construct($scopeTokens, array(\T_FUNCTION), true); + + // Make sure debuginfo is included in the array. Upstream only includes it since 2.5.1. + $this->magicMethods['debuginfo'] = true; + } + + + /** + * Processes the tokens within the scope. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * @param int $currScope The position of the current scope. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + /* + * Determine if this is a function which needs to be examined. + * The `processTokenWithinScope()` is called for each valid scope a method is in, + * so for nested classes, we need to make sure we only examine the token for + * the lowest level valid scope. + */ + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + if ($this->isFunctionDeprecated($phpcsFile, $stackPtr) === true) { + /* + * Deprecated functions don't have to comply with the naming conventions, + * otherwise functions deprecated in favour of a function with a compliant + * name would still trigger an error. + */ + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + // Is this a magic method. i.e., is prefixed with "__" ? + if (preg_match('|^__[^_]|', $methodName) > 0) { + $magicPart = strtolower(substr($methodName, 2)); + if (isset($this->magicMethods[$magicPart]) === false + && isset($this->methodsDoubleUnderscore[$magicPart]) === false + ) { + $className = '[anonymous class]'; + $scopeNextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($currScope + 1), null, true); + if ($scopeNextNonEmpty !== false && $tokens[$scopeNextNonEmpty]['code'] === \T_STRING) { + $className = $tokens[$scopeNextNonEmpty]['content']; + } + + $phpcsFile->addWarning( + 'Method name "%s" is discouraged; PHP has reserved all method names with a double underscore prefix for future use.', + $stackPtr, + 'MethodDoubleUnderscore', + array($className . '::' . $methodName) + ); + } + } + } + + + /** + * Processes the tokens outside the scope. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + if ($this->isFunctionDeprecated($phpcsFile, $stackPtr) === true) { + /* + * Deprecated functions don't have to comply with the naming conventions, + * otherwise functions deprecated in favour of a function with a compliant + * name would still trigger an error. + */ + return; + } + + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if ($functionName === null) { + // Ignore closures. + return; + } + + // Is this a magic function. i.e., it is prefixed with "__". + if (preg_match('|^__[^_]|', $functionName) > 0) { + $magicPart = strtolower(substr($functionName, 2)); + if (isset($this->magicFunctions[$magicPart]) === false) { + $phpcsFile->addWarning( + 'Function name "%s" is discouraged; PHP has reserved all method names with a double underscore prefix for future use.', + $stackPtr, + 'FunctionDoubleUnderscore', + array($functionName) + ); + } + } + } + + + /** + * Check whether a function has been marked as deprecated via a @deprecated tag + * in the function docblock. + * + * @since 9.3.2 + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of a T_FUNCTION + * token in the stack. + * + * @return bool + */ + private function isFunctionDeprecated(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $find = Tokens::$methodPrefixes; + $find[] = \T_WHITESPACE; + + $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true); + if ($tokens[$commentEnd]['code'] !== \T_DOC_COMMENT_CLOSE_TAG) { + // Function doesn't have a doc comment or is using the wrong type of comment. + return false; + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@deprecated') { + return true; + } + } + + return false; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/ArgumentFunctionsReportCurrentValueSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/ArgumentFunctionsReportCurrentValueSniff.php new file mode 100644 index 00000000..4e904dea --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/ArgumentFunctionsReportCurrentValueSniff.php @@ -0,0 +1,455 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionUse; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Functions inspecting function arguments report the current parameter value + * instead of the original since PHP 7.0. + * + * `func_get_arg()`, `func_get_args()`, `debug_backtrace()` and exception backtraces + * will no longer report the original parameter value as was passed to the function, + * but will instead provide the current value (which might have been modified). + * + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/migration70.incompatible.php#migration70.incompatible.other.func-parameter-modified + * + * @since 9.1.0 + */ +class ArgumentFunctionsReportCurrentValueSniff extends Sniff +{ + + /** + * A list of functions that, when called, can behave differently in PHP 7 + * when dealing with parameters of the function they're called in. + * + * @since 9.1.0 + * + * @var array + */ + protected $changedFunctions = array( + 'func_get_arg' => true, + 'func_get_args' => true, + 'debug_backtrace' => true, + 'debug_print_backtrace' => true, + ); + + /** + * Tokens to look out for to allow us to skip past nested scoped structures. + * + * @since 9.1.0 + * + * @var array + */ + private $skipPastNested = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_INTERFACE' => true, + 'T_TRAIT' => true, + 'T_FUNCTION' => true, + 'T_CLOSURE' => true, + ); + + /** + * List of tokens which when they preceed a T_STRING *within a function* indicate + * this is not a call to a PHP native function. + * + * This list already takes into account that nested scoped structures are being + * skipped over, so doesn't check for those again. + * Similarly, as constants won't have parentheses, those don't need to be checked + * for either. + * + * @since 9.1.0 + * + * @var array + */ + private $noneFunctionCallIndicators = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + ); + + /** + * The tokens for variable incrementing/decrementing. + * + * @since 9.1.0 + * + * @var array + */ + private $plusPlusMinusMinus = array( + \T_DEC => true, + \T_INC => true, + ); + + /** + * Tokens to ignore when determining the start of a statement. + * + * @since 9.1.0 + * + * @var array + */ + private $ignoreForStartOfStatement = array( + \T_COMMA, + \T_DOUBLE_ARROW, + \T_OPEN_SQUARE_BRACKET, + \T_OPEN_PARENTHESIS, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.1.0 + * + * @return array + */ + public function register() + { + return array( + \T_FUNCTION, + \T_CLOSURE, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener'], $tokens[$stackPtr]['scope_closer']) === false) { + // Abstract function, interface function, live coding or parse error. + return; + } + + $scopeOpener = $tokens[$stackPtr]['scope_opener']; + $scopeCloser = $tokens[$stackPtr]['scope_closer']; + + // Does the function declaration have parameters ? + $params = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($params)) { + // No named arguments found, so no risk of them being changed. + return; + } + + $paramNames = array(); + foreach ($params as $param) { + $paramNames[] = $param['name']; + } + + for ($i = ($scopeOpener + 1); $i < $scopeCloser; $i++) { + if (isset($this->skipPastNested[$tokens[$i]['type']]) && isset($tokens[$i]['scope_closer'])) { + // Skip past nested structures. + $i = $tokens[$i]['scope_closer']; + continue; + } + + if ($tokens[$i]['code'] !== \T_STRING) { + continue; + } + + $foundFunctionName = strtolower($tokens[$i]['content']); + + if (isset($this->changedFunctions[$foundFunctionName]) === false) { + // Not one of the target functions. + continue; + } + + /* + * Ok, so is this really a function call to one of the PHP native functions ? + */ + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($next === false || $tokens[$next]['code'] !== \T_OPEN_PARENTHESIS) { + // Live coding, parse error or not a function call. + continue; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), null, true); + if ($prev !== false) { + if (isset($this->noneFunctionCallIndicators[$tokens[$prev]['code']])) { + continue; + } + + // Check for namespaced functions, ie: \foo\bar() not \bar(). + if ($tokens[ $prev ]['code'] === \T_NS_SEPARATOR) { + $pprev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + if ($pprev !== false && $tokens[ $pprev ]['code'] === \T_STRING) { + continue; + } + } + } + + /* + * Address some special cases. + */ + if ($foundFunctionName !== 'func_get_args') { + $paramOne = $this->getFunctionCallParameter($phpcsFile, $i, 1); + if ($paramOne !== false) { + switch ($foundFunctionName) { + /* + * Check if `debug_(print_)backtrace()` is called with the + * `DEBUG_BACKTRACE_IGNORE_ARGS` option. + */ + case 'debug_backtrace': + case 'debug_print_backtrace': + $hasIgnoreArgs = $phpcsFile->findNext( + \T_STRING, + $paramOne['start'], + ($paramOne['end'] + 1), + false, + 'DEBUG_BACKTRACE_IGNORE_ARGS' + ); + + if ($hasIgnoreArgs !== false) { + // Debug_backtrace() called with ignore args option. + continue 2; + } + break; + + /* + * Collect the necessary information to only throw a notice if the argument + * touched/changed is in line with the passed $arg_num. + * + * Also, we can ignore `func_get_arg()` if the argument offset passed is + * higher than the number of named parameters. + * + * {@internal Note: This does not take calculations into account! + * Should be exceptionally rare and can - if needs be - be addressed at a later stage.} + */ + case 'func_get_arg': + $number = $phpcsFile->findNext(\T_LNUMBER, $paramOne['start'], ($paramOne['end'] + 1)); + if ($number !== false) { + $argNumber = $tokens[$number]['content']; + + if (isset($paramNames[$argNumber]) === false) { + // Requesting a non-named additional parameter. Ignore. + continue 2; + } + } + break; + } + } + } else { + /* + * Check if the call to func_get_args() happens to be in an array_slice() or + * array_splice() with an $offset higher than the number of named parameters. + * In that case, we can ignore it. + * + * {@internal Note: This does not take offset calculations into account! + * Should be exceptionally rare and can - if needs be - be addressed at a later stage.} + */ + if ($prev !== false && $tokens[$prev]['code'] === \T_OPEN_PARENTHESIS) { + + $maybeFunctionCall = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + if ($maybeFunctionCall !== false + && $tokens[$maybeFunctionCall]['code'] === \T_STRING + && ($tokens[$maybeFunctionCall]['content'] === 'array_slice' + || $tokens[$maybeFunctionCall]['content'] === 'array_splice') + ) { + $parentFuncParamTwo = $this->getFunctionCallParameter($phpcsFile, $maybeFunctionCall, 2); + $number = $phpcsFile->findNext( + \T_LNUMBER, + $parentFuncParamTwo['start'], + ($parentFuncParamTwo['end'] + 1) + ); + + if ($number !== false && isset($paramNames[$tokens[$number]['content']]) === false) { + // Requesting non-named additional parameters. Ignore. + continue ; + } + + // Slice starts at a named argument, but we know which params are being accessed. + $paramNamesSubset = \array_slice($paramNames, $tokens[$number]['content']); + } + } + } + + /* + * For debug_backtrace(), check if the result is being dereferenced and if so, + * whether the `args` index is used. + * I.e. whether `$index` in `debug_backtrace()[$stackFrame][$index]` is a string + * with the content `args`. + * + * Note: We already know that $next is the open parenthesis of the function call. + */ + if ($foundFunctionName === 'debug_backtrace' && isset($tokens[$next]['parenthesis_closer'])) { + $afterParenthesis = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($tokens[$next]['parenthesis_closer'] + 1), + null, + true + ); + + if ($tokens[$afterParenthesis]['code'] === \T_OPEN_SQUARE_BRACKET + && isset($tokens[$afterParenthesis]['bracket_closer']) + ) { + $afterStackFrame = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($tokens[$afterParenthesis]['bracket_closer'] + 1), + null, + true + ); + + if ($tokens[$afterStackFrame]['code'] === \T_OPEN_SQUARE_BRACKET + && isset($tokens[$afterStackFrame]['bracket_closer']) + ) { + $arrayIndex = $phpcsFile->findNext( + \T_CONSTANT_ENCAPSED_STRING, + ($afterStackFrame + 1), + $tokens[$afterStackFrame]['bracket_closer'] + ); + + if ($arrayIndex !== false && $this->stripQuotes($tokens[$arrayIndex]['content']) !== 'args') { + continue; + } + } + } + } + + /* + * Only check for variables before the start of the statement to + * prevent false positives on the return value of the function call + * being assigned to one of the parameters, i.e.: + * `$param = func_get_args();`. + */ + $startOfStatement = PHPCSHelper::findStartOfStatement($phpcsFile, $i, $this->ignoreForStartOfStatement); + + /* + * Ok, so we've found one of the target functions in the right scope. + * Now, let's check if any of the passed parameters were touched. + */ + $scanResult = 'clean'; + for ($j = ($scopeOpener + 1); $j < $startOfStatement; $j++) { + if (isset($this->skipPastNested[$tokens[$j]['type']]) + && isset($tokens[$j]['scope_closer']) + ) { + // Skip past nested structures. + $j = $tokens[$j]['scope_closer']; + continue; + } + + if ($tokens[$j]['code'] !== \T_VARIABLE) { + continue; + } + + if ($foundFunctionName === 'func_get_arg' && isset($argNumber)) { + if (isset($paramNames[$argNumber]) + && $tokens[$j]['content'] !== $paramNames[$argNumber] + ) { + // Different param than the one requested by func_get_arg(). + continue; + } + } elseif ($foundFunctionName === 'func_get_args' && isset($paramNamesSubset)) { + if (\in_array($tokens[$j]['content'], $paramNamesSubset, true) === false) { + // Different param than the ones requested by func_get_args(). + continue; + } + } elseif (\in_array($tokens[$j]['content'], $paramNames, true) === false) { + // Variable is not one of the function parameters. + continue; + } + + /* + * Ok, so we've found a variable which was passed as one of the parameters. + * Now, is this variable being changed, i.e. incremented, decremented or + * assigned something ? + */ + $scanResult = 'warning'; + if (isset($variableToken) === false) { + $variableToken = $j; + } + + $beforeVar = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($j - 1), null, true); + if ($beforeVar !== false && isset($this->plusPlusMinusMinus[$tokens[$beforeVar]['code']])) { + // Variable is being (pre-)incremented/decremented. + $scanResult = 'error'; + $variableToken = $j; + break; + } + + $afterVar = $phpcsFile->findNext(Tokens::$emptyTokens, ($j + 1), null, true); + if ($afterVar === false) { + // Shouldn't be possible, but just in case. + continue; + } + + if (isset($this->plusPlusMinusMinus[$tokens[$afterVar]['code']])) { + // Variable is being (post-)incremented/decremented. + $scanResult = 'error'; + $variableToken = $j; + break; + } + + if ($tokens[$afterVar]['code'] === \T_OPEN_SQUARE_BRACKET + && isset($tokens[$afterVar]['bracket_closer']) + ) { + // Skip past array access on the variable. + while (($afterVar = $phpcsFile->findNext(Tokens::$emptyTokens, ($tokens[$afterVar]['bracket_closer'] + 1), null, true)) !== false) { + if ($tokens[$afterVar]['code'] !== \T_OPEN_SQUARE_BRACKET + || isset($tokens[$afterVar]['bracket_closer']) === false + ) { + break; + } + } + } + + if ($afterVar !== false + && isset(Tokens::$assignmentTokens[$tokens[$afterVar]['code']]) + ) { + // Variable is being assigned something. + $scanResult = 'error'; + $variableToken = $j; + break; + } + } + + unset($argNumber, $paramNamesSubset); + + if ($scanResult === 'clean') { + continue; + } + + $error = 'Since PHP 7.0, functions inspecting arguments, like %1$s(), no longer report the original value as passed to a parameter, but will instead provide the current value. The parameter "%2$s" was %4$s on line %3$s.'; + $data = array( + $foundFunctionName, + $tokens[$variableToken]['content'], + $tokens[$variableToken]['line'], + ); + + if ($scanResult === 'error') { + $data[] = 'changed'; + $phpcsFile->addError($error, $i, 'Changed', $data); + + } elseif ($scanResult === 'warning') { + $data[] = 'used, and possibly changed (by reference),'; + $phpcsFile->addWarning($error, $i, 'NeedsInspection', $data); + } + + unset($variableToken); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/ArgumentFunctionsUsageSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/ArgumentFunctionsUsageSniff.php new file mode 100644 index 00000000..7c251119 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/ArgumentFunctionsUsageSniff.php @@ -0,0 +1,169 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionUse; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect usage of `func_get_args()`, `func_get_arg()` and `func_num_args()` in invalid context. + * + * Checks for: + * - Prior to PHP 5.3, these functions could not be used as a function call parameter. + * - Calling these functions from the outermost scope of a file which has been included by + * calling `include` or `require` from within a function in the calling file, worked + * prior to PHP 5.3. As of PHP 5.3, this will generate a warning and will always return false/-1. + * If the file was called directly or included in the global scope, calls to these + * functions would already generate a warning prior to PHP 5.3. + * + * PHP version 5.3 + * + * @link https://www.php.net/manual/en/migration53.incompatible.php + * + * @since 8.2.0 + */ +class ArgumentFunctionsUsageSniff extends Sniff +{ + + /** + * The target functions for this sniff. + * + * @since 8.2.0 + * + * @var array + */ + protected $targetFunctions = array( + 'func_get_args' => true, + 'func_get_arg' => true, + 'func_num_args' => true, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.2.0 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $functionLc = strtolower($tokens[$stackPtr]['content']); + if (isset($this->targetFunctions[$functionLc]) === false) { + return; + } + + // Next non-empty token should be the open parenthesis. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS) { + return; + } + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_NEW => true, + ); + + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevNonEmpty]['code']]) === true) { + // Not a call to a PHP function. + return; + } elseif ($tokens[$prevNonEmpty]['code'] === \T_NS_SEPARATOR && $tokens[$prevNonEmpty - 1]['code'] === \T_STRING) { + // Namespaced function. + return; + } + + $data = $tokens[$stackPtr]['content']; + + /* + * Check for use of the functions in the global scope. + * + * As PHPCS can not determine whether a file is included from within a function in + * another file, so always throw a warning/error. + */ + if ($phpcsFile->hasCondition($stackPtr, array(\T_FUNCTION, \T_CLOSURE)) === false) { + $isError = false; + $message = 'Use of %s() outside of a user-defined function is only supported if the file is included from within a user-defined function in another file prior to PHP 5.3.'; + + if ($this->supportsAbove('5.3') === true) { + $isError = true; + $message .= ' As of PHP 5.3, it is no longer supported at all.'; + } + + $this->addMessage($phpcsFile, $message, $stackPtr, $isError, 'OutsideFunctionScope', $data); + } + + /* + * Check for use of the functions as a parameter in a function call. + */ + if ($this->supportsBelow('5.2') === false) { + return; + } + + if (isset($tokens[$stackPtr]['nested_parenthesis']) === false) { + return; + } + + $throwError = false; + + $closer = end($tokens[$stackPtr]['nested_parenthesis']); + if (isset($tokens[$closer]['parenthesis_owner']) + && $tokens[$tokens[$closer]['parenthesis_owner']]['type'] === 'T_CLOSURE' + ) { + $throwError = true; + } else { + $opener = key($tokens[$stackPtr]['nested_parenthesis']); + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($opener - 1), null, true); + if ($tokens[$prevNonEmpty]['code'] !== \T_STRING) { + return; + } + + $prevPrevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevNonEmpty - 1), null, true); + if ($tokens[$prevPrevNonEmpty]['code'] === \T_FUNCTION) { + return; + } + + $throwError = true; + } + + if ($throwError === false) { + return; + } + + $phpcsFile->addError( + '%s() could not be used in parameter lists prior to PHP 5.3.', + $stackPtr, + 'InParameterList', + $data + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/NewFunctionParametersSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/NewFunctionParametersSniff.php new file mode 100644 index 00000000..7b0d60bd --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/NewFunctionParametersSniff.php @@ -0,0 +1,1109 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionUse; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect use of new function parameters in calls to native PHP functions. + * + * PHP version All + * + * @link https://www.php.net/manual/en/doc.changelog.php + * + * @since 7.0.0 + * @since 7.1.0 Now extends the `AbstractNewFeatureSniff` instead of the base `Sniff` class.. + */ +class NewFunctionParametersSniff extends AbstractNewFeatureSniff +{ + /** + * A list of functions which have new parameters, not present in older versions. + * + * The array lists : version number with false (not present) or true (present). + * The index is the location of the parameter in the parameter list, starting at 0 ! + * If's sufficient to list the first version where the function appears. + * + * @since 7.0.0 + * @since 7.0.2 Visibility changed from `public` to `protected`. + * + * @var array + */ + protected $newFunctionParameters = array( + 'array_filter' => array( + 2 => array( + 'name' => 'flag', + '5.5' => false, + '5.6' => true, + ), + ), + 'array_slice' => array( + 1 => array( + 'name' => 'preserve_keys', + '5.0.1' => false, + '5.0.2' => true, + ), + ), + 'array_unique' => array( + 1 => array( + 'name' => 'sort_flags', + '5.2.8' => false, + '5.2.9' => true, + ), + ), + 'assert' => array( + 1 => array( + 'name' => 'description', + '5.4.7' => false, + '5.4.8' => true, + ), + ), + 'base64_decode' => array( + 1 => array( + 'name' => 'strict', + '5.1' => false, + '5.2' => true, + ), + ), + 'bcmod' => array( + 2 => array( + 'name' => 'scale', + '7.1' => false, + '7.2' => true, + ), + ), + 'class_implements' => array( + 1 => array( + 'name' => 'autoload', + '5.0' => false, + '5.1' => true, + ), + ), + 'class_parents' => array( + 1 => array( + 'name' => 'autoload', + '5.0' => false, + '5.1' => true, + ), + ), + 'clearstatcache' => array( + 0 => array( + 'name' => 'clear_realpath_cache', + '5.2' => false, + '5.3' => true, + ), + 1 => array( + 'name' => 'filename', + '5.2' => false, + '5.3' => true, + ), + ), + 'copy' => array( + 2 => array( + 'name' => 'context', + '5.2' => false, + '5.3' => true, + ), + ), + 'curl_multi_info_read' => array( + 1 => array( + 'name' => 'msgs_in_queue', + '5.1' => false, + '5.2' => true, + ), + ), + 'debug_backtrace' => array( + 0 => array( + 'name' => 'options', + '5.2.4' => false, + '5.2.5' => true, + ), + 1 => array( + 'name' => 'limit', + '5.3' => false, + '5.4' => true, + ), + ), + 'debug_print_backtrace' => array( + 0 => array( + 'name' => 'options', + '5.3.5' => false, + '5.3.6' => true, + ), + 1 => array( + 'name' => 'limit', + '5.3' => false, + '5.4' => true, + ), + ), + 'dirname' => array( + 1 => array( + 'name' => 'levels', + '5.6' => false, + '7.0' => true, + ), + ), + 'dns_get_record' => array( + 4 => array( + 'name' => 'raw', + '5.3' => false, + '5.4' => true, + ), + ), + 'fgetcsv' => array( + 4 => array( + 'name' => 'escape', + '5.2' => false, + '5.3' => true, + ), + ), + 'fputcsv' => array( + 4 => array( + 'name' => 'escape_char', + '5.5.3' => false, + '5.5.4' => true, + ), + ), + 'file_get_contents' => array( + 3 => array( + 'name' => 'offset', + '5.0' => false, + '5.1' => true, + ), + 4 => array( + 'name' => 'maxlen', + '5.0' => false, + '5.1' => true, + ), + ), + 'filter_input_array' => array( + 2 => array( + 'name' => 'add_empty', + '5.3' => false, + '5.4' => true, + ), + ), + 'filter_var_array' => array( + 2 => array( + 'name' => 'add_empty', + '5.3' => false, + '5.4' => true, + ), + ), + 'getenv' => array( + 1 => array( + 'name' => 'local_only', + '5.5.37' => false, + '5.5.38' => true, // Also introduced in PHP 5.6.24 and 7.0.9. + ), + ), + 'getopt' => array( + 2 => array( + 'name' => 'optind', + '7.0' => false, + '7.1' => true, + ), + ), + 'gettimeofday' => array( + 0 => array( + 'name' => 'return_float', + '5.0' => false, + '5.1' => true, + ), + ), + 'get_defined_functions' => array( + 0 => array( + 'name' => 'exclude_disabled', + '7.0.14' => false, + '7.0.15' => true, + ), + ), + 'get_headers' => array( + 2 => array( + 'name' => 'context', + '7.0' => false, + '7.1' => true, + ), + ), + 'get_html_translation_table' => array( + 2 => array( + 'name' => 'encoding', + '5.3.3' => false, + '5.3.4' => true, + ), + ), + 'get_loaded_extensions' => array( + 0 => array( + 'name' => 'zend_extensions', + '5.2.3' => false, + '5.2.4' => true, + ), + ), + 'gzcompress' => array( + 2 => array( + 'name' => 'encoding', + '5.3' => false, + '5.4' => true, + ), + ), + 'gzdeflate' => array( + 2 => array( + 'name' => 'encoding', + '5.3' => false, + '5.4' => true, + ), + ), + 'htmlentities' => array( + 3 => array( + 'name' => 'double_encode', + '5.2.2' => false, + '5.2.3' => true, + ), + ), + 'htmlspecialchars' => array( + 3 => array( + 'name' => 'double_encode', + '5.2.2' => false, + '5.2.3' => true, + ), + ), + 'http_build_query' => array( + 2 => array( + 'name' => 'arg_separator', + '5.1.1' => false, + '5.1.2' => true, + ), + 3 => array( + 'name' => 'enc_type', + '5.3' => false, + '5.4' => true, + ), + ), + 'idn_to_ascii' => array( + 2 => array( + 'name' => 'variant', + '5.3' => false, + '5.4' => true, + ), + 3 => array( + 'name' => 'idna_info', + '5.3' => false, + '5.4' => true, + ), + ), + 'idn_to_utf8' => array( + 2 => array( + 'name' => 'variant', + '5.3' => false, + '5.4' => true, + ), + 3 => array( + 'name' => 'idna_info', + '5.3' => false, + '5.4' => true, + ), + ), + 'imagecolorset' => array( + 5 => array( + 'name' => 'alpha', + '5.3' => false, + '5.4' => true, + ), + ), + 'imagepng' => array( + 2 => array( + 'name' => 'quality', + '5.1.1' => false, + '5.1.2' => true, + ), + 3 => array( + 'name' => 'filters', + '5.1.2' => false, + '5.1.3' => true, + ), + ), + 'imagerotate' => array( + 3 => array( + 'name' => 'ignore_transparent', + '5.0' => false, + '5.1' => true, + ), + ), + 'imap_open' => array( + 4 => array( + 'name' => 'n_retries', + '5.1' => false, + '5.2' => true, + ), + 5 => array( + 'name' => 'params', + '5.3.1' => false, + '5.3.2' => true, + ), + ), + 'imap_reopen' => array( + 3 => array( + 'name' => 'n_retries', + '5.1' => false, + '5.2' => true, + ), + ), + 'ini_get_all' => array( + 1 => array( + 'name' => 'details', + '5.2' => false, + '5.3' => true, + ), + ), + 'is_a' => array( + 2 => array( + 'name' => 'allow_string', + '5.3.8' => false, + '5.3.9' => true, + ), + ), + 'is_subclass_of' => array( + 2 => array( + 'name' => 'allow_string', + '5.3.8' => false, + '5.3.9' => true, + ), + ), + 'iterator_to_array' => array( + 1 => array( + 'name' => 'use_keys', + '5.2.0' => false, + '5.2.1' => true, + ), + ), + 'json_decode' => array( + 2 => array( + 'name' => 'depth', + '5.2' => false, + '5.3' => true, + ), + 3 => array( + 'name' => 'options', + '5.3' => false, + '5.4' => true, + ), + ), + 'json_encode' => array( + 1 => array( + 'name' => 'options', + '5.2' => false, + '5.3' => true, + ), + 2 => array( + 'name' => 'depth', + '5.4' => false, + '5.5' => true, + ), + ), + 'ldap_add' => array( + 3 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_compare' => array( + 4 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_delete' => array( + 2 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_list' => array( + 8 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_mod_add' => array( + 3 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_mod_del' => array( + 3 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_mod_replace' => array( + 3 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_modify_batch' => array( + 3 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_parse_result' => array( + 6 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_read' => array( + 8 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_rename' => array( + 5 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_search' => array( + 8 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'memory_get_peak_usage' => array( + 0 => array( + 'name' => 'real_usage', + '5.1' => false, + '5.2' => true, + ), + ), + 'memory_get_usage' => array( + 0 => array( + 'name' => 'real_usage', + '5.1' => false, + '5.2' => true, + ), + ), + 'mb_encode_numericentity' => array( + 3 => array( + 'name' => 'is_hex', + '5.3' => false, + '5.4' => true, + ), + ), + 'mb_strrpos' => array( + /* + * Note: the actual position is 2, but the original 3rd + * parameter 'encoding' was moved to the 4th position. + * So the only way to detect if offset is used is when + * both offset and encoding are set. + */ + 3 => array( + 'name' => 'offset', + '5.1' => false, + '5.2' => true, + ), + ), + 'mssql_connect' => array( + 3 => array( + 'name' => 'new_link', + '5.0' => false, + '5.1' => true, + ), + ), + 'mysqli_commit' => array( + 1 => array( + 'name' => 'flags', + '5.4' => false, + '5.5' => true, + ), + 2 => array( + 'name' => 'name', + '5.4' => false, + '5.5' => true, + ), + ), + 'mysqli_rollback' => array( + 1 => array( + 'name' => 'flags', + '5.4' => false, + '5.5' => true, + ), + 2 => array( + 'name' => 'name', + '5.4' => false, + '5.5' => true, + ), + ), + 'nl2br' => array( + 1 => array( + 'name' => 'is_xhtml', + '5.2' => false, + '5.3' => true, + ), + ), + 'openssl_decrypt' => array( + 4 => array( + 'name' => 'iv', + '5.3.2' => false, + '5.3.3' => true, + ), + 5 => array( + 'name' => 'tag', + '7.0' => false, + '7.1' => true, + ), + 6 => array( + 'name' => 'aad', + '7.0' => false, + '7.1' => true, + ), + ), + 'openssl_encrypt' => array( + 4 => array( + 'name' => 'iv', + '5.3.2' => false, + '5.3.3' => true, + ), + 5 => array( + 'name' => 'tag', + '7.0' => false, + '7.1' => true, + ), + 6 => array( + 'name' => 'aad', + '7.0' => false, + '7.1' => true, + ), + 7 => array( + 'name' => 'tag_length', + '7.0' => false, + '7.1' => true, + ), + ), + 'openssl_open' => array( + 4 => array( + 'name' => 'method', + '5.2' => false, + '5.3' => true, + ), + 5 => array( + 'name' => 'iv', + '5.6' => false, + '7.0' => true, + ), + ), + 'openssl_pkcs7_verify' => array( + 5 => array( + 'name' => 'content', + '5.0' => false, + '5.1' => true, + ), + 6 => array( + 'name' => 'p7bfilename', + '7.1' => false, + '7.2' => true, + ), + ), + 'openssl_seal' => array( + 4 => array( + 'name' => 'method', + '5.2' => false, + '5.3' => true, + ), + 5 => array( + 'name' => 'iv', + '5.6' => false, + '7.0' => true, + ), + ), + 'openssl_verify' => array( + 3 => array( + 'name' => 'signature_alg', + '5.1' => false, + '5.2' => true, + ), + ), + 'parse_ini_file' => array( + 2 => array( + 'name' => 'scanner_mode', + '5.2' => false, + '5.3' => true, + ), + ), + 'parse_url' => array( + 1 => array( + 'name' => 'component', + '5.1.1' => false, + '5.1.2' => true, + ), + ), + 'pg_fetch_all' => array( + 1 => array( + 'name' => 'result_type', + '7.0' => false, + '7.1' => true, + ), + ), + 'pg_last_notice' => array( + 1 => array( + 'name' => 'option', + '7.0' => false, + '7.1' => true, + ), + ), + 'pg_lo_create' => array( + 1 => array( + 'name' => 'object_id', + '5.2' => false, + '5.3' => true, + ), + ), + 'pg_lo_import' => array( + 2 => array( + 'name' => 'object_id', + '5.2' => false, + '5.3' => true, + ), + ), + 'pg_select' => array( + 4 => array( + 'name' => 'result_type', + '7.0' => false, + '7.1' => true, + ), + ), + 'php_uname' => array( + 0 => array( + 'name' => 'mode', + '4.2' => false, + '4.3' => true, + ), + ), + 'preg_replace' => array( + 4 => array( + 'name' => 'count', + '5.0' => false, + '5.1' => true, + ), + ), + 'preg_replace_callback' => array( + 4 => array( + 'name' => 'count', + '5.0' => false, + '5.1' => true, + ), + 5 => array( + 'name' => 'flags', + '7.3' => false, + '7.4' => true, + ), + ), + 'preg_replace_callback_array' => array( + 4 => array( + 'name' => 'flags', + '7.3' => false, + '7.4' => true, + ), + ), + 'round' => array( + 2 => array( + 'name' => 'mode', + '5.2' => false, + '5.3' => true, + ), + ), + 'sem_acquire' => array( + 1 => array( + 'name' => 'nowait', + '5.6' => false, + '5.6.1' => true, + ), + ), + 'session_regenerate_id' => array( + 0 => array( + 'name' => 'delete_old_session', + '5.0' => false, + '5.1' => true, + ), + ), + 'session_set_cookie_params' => array( + 4 => array( + 'name' => 'httponly', + '5.1' => false, + '5.2' => true, + ), + ), + 'session_set_save_handler' => array( + 6 => array( + 'name' => 'create_sid', + '5.5.0' => false, + '5.5.1' => true, + ), + 7 => array( + 'name' => 'validate_sid', + '5.6' => false, + '7.0' => true, + ), + 8 => array( + 'name' => 'update_timestamp', + '5.6' => false, + '7.0' => true, + ), + ), + 'session_start' => array( + 0 => array( + 'name' => 'options', + '5.6' => false, + '7.0' => true, + ), + ), + 'setcookie' => array( + 6 => array( + 'name' => 'httponly', + '5.1' => false, + '5.2' => true, + ), + ), + 'setrawcookie' => array( + 6 => array( + 'name' => 'httponly', + '5.1' => false, + '5.2' => true, + ), + ), + 'simplexml_load_file' => array( + 4 => array( + 'name' => 'is_prefix', + '5.1' => false, + '5.2' => true, + ), + ), + 'simplexml_load_string' => array( + 4 => array( + 'name' => 'is_prefix', + '5.1' => false, + '5.2' => true, + ), + ), + 'spl_autoload_register' => array( + 2 => array( + 'name' => 'prepend', + '5.2' => false, + '5.3' => true, + ), + ), + 'stream_context_create' => array( + 1 => array( + 'name' => 'params', + '5.2' => false, + '5.3' => true, + ), + ), + 'stream_copy_to_stream' => array( + 3 => array( + 'name' => 'offset', + '5.0' => false, + '5.1' => true, + ), + ), + 'stream_get_contents' => array( + 2 => array( + 'name' => 'offset', + '5.0' => false, + '5.1' => true, + ), + ), + 'stream_wrapper_register' => array( + 2 => array( + 'name' => 'flags', + '5.2.3' => false, + '5.2.4' => true, + ), + ), + 'stristr' => array( + 2 => array( + 'name' => 'before_needle', + '5.2' => false, + '5.3' => true, + ), + ), + 'strstr' => array( + 2 => array( + 'name' => 'before_needle', + '5.2' => false, + '5.3' => true, + ), + ), + 'str_word_count' => array( + 2 => array( + 'name' => 'charlist', + '5.0' => false, + '5.1' => true, + ), + ), + 'substr_count' => array( + 2 => array( + 'name' => 'offset', + '5.0' => false, + '5.1' => true, + ), + 3 => array( + 'name' => 'length', + '5.0' => false, + '5.1' => true, + ), + ), + 'sybase_connect' => array( + 5 => array( + 'name' => 'new', + '5.2' => false, + '5.3' => true, + ), + ), + 'timezone_transitions_get' => array( + 1 => array( + 'name' => 'timestamp_begin', + '5.2' => false, + '5.3' => true, + ), + 2 => array( + 'name' => 'timestamp_end', + '5.2' => false, + '5.3' => true, + ), + ), + 'timezone_identifiers_list' => array( + 0 => array( + 'name' => 'what', + '5.2' => false, + '5.3' => true, + ), + 1 => array( + 'name' => 'country', + '5.2' => false, + '5.3' => true, + ), + ), + 'token_get_all' => array( + 1 => array( + 'name' => 'flags', + '5.6' => false, + '7.0' => true, + ), + ), + 'ucwords' => array( + 1 => array( + 'name' => 'delimiters', + '5.4.31' => false, + '5.5.15' => false, + '5.4.32' => true, + '5.5.16' => true, + ), + ), + 'unpack' => array( + 2 => array( + 'name' => 'offset', + '7.0' => false, + '7.1' => true, + ), + ), + 'unserialize' => array( + 1 => array( + 'name' => 'options', + '5.6' => false, + '7.0' => true, + ), + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of function names. + $this->newFunctionParameters = $this->arrayKeysToLowercase($this->newFunctionParameters); + + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CONST => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + $function = $tokens[$stackPtr]['content']; + $functionLc = strtolower($function); + + if (isset($this->newFunctionParameters[$functionLc]) === false) { + return; + } + + $parameterCount = $this->getFunctionCallParameterCount($phpcsFile, $stackPtr); + if ($parameterCount === 0) { + return; + } + + // If the parameter count returned > 0, we know there will be valid open parenthesis. + $openParenthesis = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + $parameterOffsetFound = $parameterCount - 1; + + foreach ($this->newFunctionParameters[$functionLc] as $offset => $parameterDetails) { + if ($offset <= $parameterOffsetFound) { + $itemInfo = array( + 'name' => $function, + 'nameLc' => $functionLc, + 'offset' => $offset, + ); + $this->handleFeature($phpcsFile, $openParenthesis, $itemInfo); + } + } + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newFunctionParameters[$itemInfo['nameLc']][$itemInfo['offset']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('name'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['paramName'] = $itemArray['name']; + + return $errorInfo; + } + + + /** + * Get the item name to be used for the creation of the error code. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Detail information about an item. + * + * @return string + */ + protected function getItemName(array $itemInfo, array $errorInfo) + { + return $itemInfo['name'] . '_' . $errorInfo['paramName']; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The function %s() does not have a parameter "%s" in PHP version %s or earlier'; + } + + + /** + * Allow for concrete child classes to filter the error data before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + array_shift($data); + array_unshift($data, $itemInfo['name'], $errorInfo['paramName']); + return $data; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/NewFunctionsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/NewFunctionsSniff.php new file mode 100644 index 00000000..c1a0ec4e --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/NewFunctionsSniff.php @@ -0,0 +1,2008 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionUse; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect calls to new native PHP functions. + * + * PHP version All + * + * @since 5.5 + * @since 5.6 Now extends the base `Sniff` class instead of the upstream + * `Generic.PHP.ForbiddenFunctions` sniff. + * @since 7.1.0 Now extends the `AbstractNewFeatureSniff` instead of the base `Sniff` class.. + */ +class NewFunctionsSniff extends AbstractNewFeatureSniff +{ + /** + * A list of new functions, not present in older versions. + * + * The array lists : version number with false (not present) or true (present). + * If's sufficient to list the first version where the function appears. + * + * @since 5.5 + * @since 5.6 Visibility changed from `protected` to `public`. + * @since 7.0.2 Visibility changed back from `public` to `protected`. + * The earlier change was made to be in line with the upstream sniff, + * but that sniff is no longer being extended. + * @since 7.0.8 Renamed from `$forbiddenFunctions` to the more descriptive `$newFunctions`. + * + * @var array(string => array(string => bool)) + */ + protected $newFunctions = array( + 'iterator_count' => array( + '5.0' => false, + '5.1' => true, + ), + 'iterator_to_array' => array( + '5.0' => false, + '5.1' => true, + ), + 'spl_autoload_call' => array( + '5.0' => false, + '5.1' => true, + ), + 'spl_autoload_extensions' => array( + '5.0' => false, + '5.1' => true, + ), + 'spl_autoload_functions' => array( + '5.0' => false, + '5.1' => true, + ), + 'spl_autoload_register' => array( + '5.0' => false, + '5.1' => true, + ), + 'spl_autoload_unregister' => array( + '5.0' => false, + '5.1' => true, + ), + 'spl_autoload' => array( + '5.0' => false, + '5.1' => true, + ), + 'hash_hmac' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'array_fill_keys' => array( + '5.1' => false, + '5.2' => true, + ), + 'error_get_last' => array( + '5.1' => false, + '5.2' => true, + ), + 'image_type_to_extension' => array( + '5.1' => false, + '5.2' => true, + ), + 'memory_get_peak_usage' => array( + '5.1' => false, + '5.2' => true, + ), + 'sys_get_temp_dir' => array( + '5.1' => false, + '5.2' => true, + ), + 'timezone_abbreviations_list' => array( + '5.1' => false, + '5.2' => true, + ), + 'timezone_identifiers_list' => array( + '5.1' => false, + '5.2' => true, + ), + 'timezone_name_from_abbr' => array( + '5.1' => false, + '5.2' => true, + ), + 'stream_socket_shutdown' => array( + '5.1' => false, + '5.2' => true, + ), + 'imagegrabscreen' => array( + '5.1' => false, + '5.2' => true, + ), + 'imagegrabwindow' => array( + '5.1' => false, + '5.2' => true, + ), + 'libxml_disable_entity_loader' => array( + '5.1' => false, + '5.2' => true, + ), + 'mb_stripos' => array( + '5.1' => false, + '5.2' => true, + ), + 'mb_stristr' => array( + '5.1' => false, + '5.2' => true, + ), + 'mb_strrchr' => array( + '5.1' => false, + '5.2' => true, + ), + 'mb_strrichr' => array( + '5.1' => false, + '5.2' => true, + ), + 'mb_strripos' => array( + '5.1' => false, + '5.2' => true, + ), + 'ming_setSWFCompression' => array( + '5.1' => false, + '5.2' => true, + ), + 'openssl_csr_get_public_key' => array( + '5.1' => false, + '5.2' => true, + ), + 'openssl_csr_get_subject' => array( + '5.1' => false, + '5.2' => true, + ), + 'openssl_pkey_get_details' => array( + '5.1' => false, + '5.2' => true, + ), + 'spl_object_hash' => array( + '5.1' => false, + '5.2' => true, + ), + 'iterator_apply' => array( + '5.1' => false, + '5.2' => true, + ), + 'preg_last_error' => array( + '5.1' => false, + '5.2' => true, + ), + 'pg_field_table' => array( + '5.1' => false, + '5.2' => true, + ), + 'posix_initgroups' => array( + '5.1' => false, + '5.2' => true, + ), + 'gmp_nextprime' => array( + '5.1' => false, + '5.2' => true, + ), + 'xmlwriter_full_end_element' => array( + '5.1' => false, + '5.2' => true, + ), + 'xmlwriter_write_raw' => array( + '5.1' => false, + '5.2' => true, + ), + 'xmlwriter_start_dtd_entity' => array( + '5.1' => false, + '5.2' => true, + ), + 'xmlwriter_end_dtd_entity' => array( + '5.1' => false, + '5.2' => true, + ), + 'xmlwriter_write_dtd_entity' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter_has_var' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter_id' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter_input_array' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter_input' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter_list' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter_var_array' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter_var' => array( + '5.1' => false, + '5.2' => true, + ), + 'json_decode' => array( + '5.1' => false, + '5.2' => true, + ), + 'json_encode' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_close' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_entry_close' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_entry_compressedsize' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_entry_compressionmethod' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_entry_filesize' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_entry_name' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_entry_open' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_entry_read' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_open' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_read' => array( + '5.1' => false, + '5.2' => true, + ), + + 'array_replace' => array( + '5.2' => false, + '5.3' => true, + ), + 'array_replace_recursive' => array( + '5.2' => false, + '5.3' => true, + ), + 'class_alias' => array( + '5.2' => false, + '5.3' => true, + ), + 'forward_static_call' => array( + '5.2' => false, + '5.3' => true, + ), + 'forward_static_call_array' => array( + '5.2' => false, + '5.3' => true, + ), + 'gc_collect_cycles' => array( + '5.2' => false, + '5.3' => true, + ), + 'gc_disable' => array( + '5.2' => false, + '5.3' => true, + ), + 'gc_enable' => array( + '5.2' => false, + '5.3' => true, + ), + 'gc_enabled' => array( + '5.2' => false, + '5.3' => true, + ), + 'get_called_class' => array( + '5.2' => false, + '5.3' => true, + ), + 'gethostname' => array( + '5.2' => false, + '5.3' => true, + ), + 'header_remove' => array( + '5.2' => false, + '5.3' => true, + ), + 'lcfirst' => array( + '5.2' => false, + '5.3' => true, + ), + 'parse_ini_string' => array( + '5.2' => false, + '5.3' => true, + ), + 'quoted_printable_encode' => array( + '5.2' => false, + '5.3' => true, + ), + 'str_getcsv' => array( + '5.2' => false, + '5.3' => true, + ), + 'stream_context_set_default' => array( + '5.2' => false, + '5.3' => true, + ), + 'stream_supports_lock' => array( + '5.2' => false, + '5.3' => true, + ), + 'stream_context_get_params' => array( + '5.2' => false, + '5.3' => true, + ), + 'date_add' => array( + '5.2' => false, + '5.3' => true, + ), + 'date_create_from_format' => array( + '5.2' => false, + '5.3' => true, + ), + 'date_diff' => array( + '5.2' => false, + '5.3' => true, + ), + 'date_get_last_errors' => array( + '5.2' => false, + '5.3' => true, + ), + 'date_parse_from_format' => array( + '5.2' => false, + '5.3' => true, + ), + 'date_sub' => array( + '5.2' => false, + '5.3' => true, + ), + 'timezone_version_get' => array( + '5.2' => false, + '5.3' => true, + ), + 'gmp_testbit' => array( + '5.2' => false, + '5.3' => true, + ), + 'hash_copy' => array( + '5.2' => false, + '5.3' => true, + ), + 'imap_gc' => array( + '5.2' => false, + '5.3' => true, + ), + 'imap_utf8_to_mutf7' => array( + '5.2' => false, + '5.3' => true, + ), + 'imap_mutf7_to_utf8' => array( + '5.2' => false, + '5.3' => true, + ), + 'json_last_error' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli_get_cache_stats' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli_fetch_all' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli_get_connection_status' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli_poll' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli_read_async_query' => array( + '5.2' => false, + '5.3' => true, + ), + 'openssl_random_pseudo_bytes' => array( + '5.2' => false, + '5.3' => true, + ), + 'pcntl_signal_dispatch' => array( + '5.2' => false, + '5.3' => true, + ), + 'pcntl_sigprocmask' => array( + '5.2' => false, + '5.3' => true, + ), + 'pcntl_sigtimedwait' => array( + '5.2' => false, + '5.3' => true, + ), + 'pcntl_sigwaitinfo' => array( + '5.2' => false, + '5.3' => true, + ), + 'preg_filter' => array( + '5.2' => false, + '5.3' => true, + ), + 'msg_queue_exists' => array( + '5.2' => false, + '5.3' => true, + ), + 'shm_has_vars' => array( + '5.2' => false, + '5.3' => true, + ), + 'acosh' => array( + '5.2' => false, + '5.3' => true, + ), + 'asinh' => array( + '5.2' => false, + '5.3' => true, + ), + 'atanh' => array( + '5.2' => false, + '5.3' => true, + ), + 'expm1' => array( + '5.2' => false, + '5.3' => true, + ), + 'log1p' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_describe' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_dict_exists' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_free_dict' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_free' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_get_error' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_init' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_list_dicts' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_request_dict' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_request_pwl_dict' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_set_ordering' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_add_to_personal' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_add_to_session' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_check' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_describe' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_get_error' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_is_in_session' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_quick_check' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_store_replacement' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_suggest' => array( + '5.2' => false, + '5.3' => true, + ), + 'finfo_buffer' => array( + '5.2' => false, + '5.3' => true, + ), + 'finfo_close' => array( + '5.2' => false, + '5.3' => true, + ), + 'finfo_file' => array( + '5.2' => false, + '5.3' => true, + ), + 'finfo_open' => array( + '5.2' => false, + '5.3' => true, + ), + 'finfo_set_flags' => array( + '5.2' => false, + '5.3' => true, + ), + 'intl_error_name' => array( + '5.2' => false, + '5.3' => true, + ), + 'intl_get_error_code' => array( + '5.2' => false, + '5.3' => true, + ), + 'intl_get_error_message' => array( + '5.2' => false, + '5.3' => true, + ), + 'intl_is_failure' => array( + '5.2' => false, + '5.3' => true, + ), + + 'hex2bin' => array( + '5.3' => false, + '5.4' => true, + ), + 'http_response_code' => array( + '5.3' => false, + '5.4' => true, + ), + 'get_declared_traits' => array( + '5.3' => false, + '5.4' => true, + ), + 'getimagesizefromstring' => array( + '5.3' => false, + '5.4' => true, + ), + 'stream_set_chunk_size' => array( + '5.3' => false, + '5.4' => true, + ), + 'socket_import_stream' => array( + '5.3' => false, + '5.4' => true, + ), + 'trait_exists' => array( + '5.3' => false, + '5.4' => true, + ), + 'header_register_callback' => array( + '5.3' => false, + '5.4' => true, + ), + 'class_uses' => array( + '5.3' => false, + '5.4' => true, + ), + 'session_status' => array( + '5.3' => false, + '5.4' => true, + ), + 'session_register_shutdown' => array( + '5.3' => false, + '5.4' => true, + ), + 'mysqli_error_list' => array( + '5.3' => false, + '5.4' => true, + ), + 'mysqli_stmt_error_list' => array( + '5.3' => false, + '5.4' => true, + ), + 'libxml_set_external_entity_loader' => array( + '5.3' => false, + '5.4' => true, + ), + 'ldap_control_paged_result' => array( + '5.3' => false, + '5.4' => true, + ), + 'ldap_control_paged_result_response' => array( + '5.3' => false, + '5.4' => true, + ), + 'transliteral_create' => array( + '5.3' => false, + '5.4' => true, + ), + 'transliteral_create_from_rules' => array( + '5.3' => false, + '5.4' => true, + ), + 'transliteral_create_inverse' => array( + '5.3' => false, + '5.4' => true, + ), + 'transliteral_get_error_code' => array( + '5.3' => false, + '5.4' => true, + ), + 'transliteral_get_error_message' => array( + '5.3' => false, + '5.4' => true, + ), + 'transliteral_list_ids' => array( + '5.3' => false, + '5.4' => true, + ), + 'transliteral_transliterate' => array( + '5.3' => false, + '5.4' => true, + ), + 'zlib_decode' => array( + '5.3' => false, + '5.4' => true, + ), + 'zlib_encode' => array( + '5.3' => false, + '5.4' => true, + ), + + 'array_column' => array( + '5.4' => false, + '5.5' => true, + ), + 'boolval' => array( + '5.4' => false, + '5.5' => true, + ), + 'json_last_error_msg' => array( + '5.4' => false, + '5.5' => true, + ), + 'password_get_info' => array( + '5.4' => false, + '5.5' => true, + ), + 'password_hash' => array( + '5.4' => false, + '5.5' => true, + ), + 'password_needs_rehash' => array( + '5.4' => false, + '5.5' => true, + ), + 'password_verify' => array( + '5.4' => false, + '5.5' => true, + ), + 'hash_pbkdf2' => array( + '5.4' => false, + '5.5' => true, + ), + 'openssl_pbkdf2' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_escape' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_file_create' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_multi_setopt' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_multi_strerror' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_pause' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_reset' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_share_close' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_share_init' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_share_setopt' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_strerror' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_unescape' => array( + '5.4' => false, + '5.5' => true, + ), + 'imageaffinematrixconcat' => array( + '5.4' => false, + '5.5' => true, + ), + 'imageaffinematrixget' => array( + '5.4' => false, + '5.5' => true, + ), + 'imagecrop' => array( + '5.4' => false, + '5.5' => true, + ), + 'imagecropauto' => array( + '5.4' => false, + '5.5' => true, + ), + 'imageflip' => array( + '5.4' => false, + '5.5' => true, + ), + 'imagepalettetotruecolor' => array( + '5.4' => false, + '5.5' => true, + ), + 'imagescale' => array( + '5.4' => false, + '5.5' => true, + ), + 'mysqli_begin_transaction' => array( + '5.4' => false, + '5.5' => true, + ), + 'mysqli_release_savepoint' => array( + '5.4' => false, + '5.5' => true, + ), + 'mysqli_savepoint' => array( + '5.4' => false, + '5.5' => true, + ), + 'pg_escape_literal' => array( + '5.4' => false, + '5.5' => true, + ), + 'pg_escape_identifier' => array( + '5.4' => false, + '5.5' => true, + ), + 'socket_sendmsg' => array( + '5.4' => false, + '5.5' => true, + ), + 'socket_recvmsg' => array( + '5.4' => false, + '5.5' => true, + ), + 'socket_cmsg_space' => array( + '5.4' => false, + '5.5' => true, + ), + 'cli_get_process_title' => array( + '5.4' => false, + '5.5' => true, + ), + 'cli_set_process_title' => array( + '5.4' => false, + '5.5' => true, + ), + 'datefmt_format_object' => array( + '5.4' => false, + '5.5' => true, + ), + 'datefmt_get_calendar_object' => array( + '5.4' => false, + '5.5' => true, + ), + 'datefmt_get_timezone' => array( + '5.4' => false, + '5.5' => true, + ), + 'datefmt_set_timezone' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_create_instance' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_keyword_values_for_locale' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_now' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_available_locales' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_time' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_set_time' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_add' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_set_time_zone' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_after' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_before' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_set' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_roll' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_clear' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_field_difference' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_actual_maximum' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_actual_minumum' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_day_of_week_type' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_first_day_of_week' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_greatest_minimum' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_least_maximum' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_locale' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_maximum' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_minimal_days_in_first_week' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_minimum' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_time_zone' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_type' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_weekend_transition' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_in_daylight_time' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_is_equivalent_to' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_is_lenient' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_equals' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_repeated_wall_time_option' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_skipped_wall_time_option' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_set_repeated_wall_time_option' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_set_skipped_wall_time_option' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_from_date_time' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_to_date_time' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_error_code' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_error_message' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlgregcal_create_instance' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlgregcal_set_gregorian_change' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlgregcal_get_gregorian_change' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlgregcal_is_leap_year' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_create_time_zone' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_create_default' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_id' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_gmt' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_unknown' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_create_enumeration' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_count_equivalent_ids' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_create_time_zone_id_enumeration' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_canonical_id' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_region' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_tz_data_version' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_equivalent_id' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_use_daylight_time' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_offset' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_raw_offset' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_has_same_rules' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_display_name' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_dst_savings' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_from_date_time_zone' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_to_date_time_zone' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_error_code' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_error_message' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache_compile_file' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache_get_configuration' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache_get_status' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache_invalidate' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache_reset' => array( + '5.4' => false, + '5.5' => true, + ), + + 'opcache_is_script_cached' => array( + '5.5.10' => false, + '5.5.11' => true, + ), + + 'gmp_root' => array( + '5.5' => false, + '5.6' => true, + ), + 'gmp_rootrem' => array( + '5.5' => false, + '5.6' => true, + ), + 'hash_equals' => array( + '5.5' => false, + '5.6' => true, + ), + 'ldap_escape' => array( + '5.5' => false, + '5.6' => true, + ), + 'ldap_modify_batch' => array( + '5.4.25' => false, + '5.5.9' => false, + '5.4.26' => true, + '5.5.10' => true, + '5.6.0' => true, + ), + 'mysqli_get_links_stats' => array( + '5.5' => false, + '5.6' => true, + ), + 'openssl_get_cert_locations' => array( + '5.5' => false, + '5.6' => true, + ), + 'openssl_x509_fingerprint' => array( + '5.5' => false, + '5.6' => true, + ), + 'openssl_spki_new' => array( + '5.5' => false, + '5.6' => true, + ), + 'openssl_spki_verify' => array( + '5.5' => false, + '5.6' => true, + ), + 'openssl_spki_export_challenge' => array( + '5.5' => false, + '5.6' => true, + ), + 'openssl_spki_export' => array( + '5.5' => false, + '5.6' => true, + ), + 'pg_connect_poll' => array( + '5.5' => false, + '5.6' => true, + ), + 'pg_consume_input' => array( + '5.5' => false, + '5.6' => true, + ), + 'pg_flush' => array( + '5.5' => false, + '5.6' => true, + ), + 'pg_lo_truncate' => array( + '5.5' => false, + '5.6' => true, + ), + 'pg_socket' => array( + '5.5' => false, + '5.6' => true, + ), + 'session_abort' => array( + '5.5' => false, + '5.6' => true, + ), + 'session_reset' => array( + '5.5' => false, + '5.6' => true, + ), + + 'random_bytes' => array( + '5.6' => false, + '7.0' => true, + ), + 'random_int' => array( + '5.6' => false, + '7.0' => true, + ), + 'error_clear_last' => array( + '5.6' => false, + '7.0' => true, + ), + 'gmp_random_seed' => array( + '5.6' => false, + '7.0' => true, + ), + 'intdiv' => array( + '5.6' => false, + '7.0' => true, + ), + 'preg_replace_callback_array' => array( + '5.6' => false, + '7.0' => true, + ), + 'gc_mem_caches' => array( + '5.6' => false, + '7.0' => true, + ), + 'get_resources' => array( + '5.6' => false, + '7.0' => true, + ), + 'posix_setrlimit' => array( + '5.6' => false, + '7.0' => true, + ), + 'inflate_add' => array( + '5.6' => false, + '7.0' => true, + ), + 'deflate_add' => array( + '5.6' => false, + '7.0' => true, + ), + 'inflate_init' => array( + '5.6' => false, + '7.0' => true, + ), + 'deflate_init' => array( + '5.6' => false, + '7.0' => true, + ), + + 'socket_export_stream' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + + 'curl_multi_errno' => array( + '7.0' => false, + '7.1' => true, + ), + 'curl_share_errno' => array( + '7.0' => false, + '7.1' => true, + ), + 'curl_share_strerror' => array( + '7.0' => false, + '7.1' => true, + ), + 'is_iterable' => array( + '7.0' => false, + '7.1' => true, + ), + 'pcntl_async_signals' => array( + '7.0' => false, + '7.1' => true, + ), + 'pcntl_signal_get_handler' => array( + '7.0' => false, + '7.1' => true, + ), + 'session_create_id' => array( + '7.0' => false, + '7.1' => true, + ), + 'session_gc' => array( + '7.0' => false, + '7.1' => true, + ), + 'sapi_windows_cp_set' => array( + '7.0' => false, + '7.1' => true, + ), + 'sapi_windows_cp_get' => array( + '7.0' => false, + '7.1' => true, + ), + 'sapi_windows_cp_is_utf8' => array( + '7.0' => false, + '7.1' => true, + ), + 'sapi_windows_cp_conv' => array( + '7.0' => false, + '7.1' => true, + ), + + 'hash_hkdf' => array( + '7.1.1' => false, + '7.1.2' => true, + ), + 'oci_register_taf_callback' => array( + '7.1.6' => false, + '7.1.7' => true, + ), + 'oci_unregister_taf_callback' => array( + '7.1.8' => false, + '7.1.9' => true, + ), + + 'stream_isatty' => array( + '7.1' => false, + '7.2' => true, + ), + 'sapi_windows_vt100_support' => array( + '7.1' => false, + '7.2' => true, + ), + 'ftp_append' => array( + '7.1' => false, + '7.2' => true, + ), + 'hash_hmac_algos' => array( + '7.1' => false, + '7.2' => true, + ), + 'imagebmp' => array( + '7.1' => false, + '7.2' => true, + ), + 'imagecreatefrombmp' => array( + '7.1' => false, + '7.2' => true, + ), + 'imagegetclip' => array( + '7.1' => false, + '7.2' => true, + ), + 'imageopenpolygon' => array( + '7.1' => false, + '7.2' => true, + ), + 'imageresolution' => array( + '7.1' => false, + '7.2' => true, + ), + 'imagesetclip' => array( + '7.1' => false, + '7.2' => true, + ), + 'ldap_exop' => array( + '7.1' => false, + '7.2' => true, + ), + 'ldap_exop_passwd' => array( + '7.1' => false, + '7.2' => true, + ), + 'ldap_exop_whoami' => array( + '7.1' => false, + '7.2' => true, + ), + 'ldap_parse_exop' => array( + '7.1' => false, + '7.2' => true, + ), + 'mb_chr' => array( + '7.1' => false, + '7.2' => true, + ), + 'mb_ord' => array( + '7.1' => false, + '7.2' => true, + ), + 'mb_scrub' => array( + '7.1' => false, + '7.2' => true, + ), + 'socket_addrinfo_lookup' => array( + '7.1' => false, + '7.2' => true, + ), + 'socket_addrinfo_connect' => array( + '7.1' => false, + '7.2' => true, + ), + 'socket_addrinfo_bind' => array( + '7.1' => false, + '7.2' => true, + ), + 'socket_addrinfo_explain' => array( + '7.1' => false, + '7.2' => true, + ), + 'spl_object_id' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_add' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_base642bin' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_bin2base64' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_bin2hex' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_compare' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_aes256gcm_decrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_aes256gcm_encrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_aes256gcm_is_available' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_aes256gcm_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_chacha20poly1305_decrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_chacha20poly1305_encrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_chacha20poly1305_ietf_decrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_chacha20poly1305_ietf_encrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_chacha20poly1305_ietf_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_chacha20poly1305_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_xchacha20poly1305_ietf_decrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_xchacha20poly1305_ietf_encrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_xchacha20poly1305_ietf_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_auth_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_auth_verify' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_auth' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_keypair_from_secretkey_and_publickey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_keypair' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_open' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_publickey_from_secretkey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_publickey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_seal_open' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_seal' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_secretkey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_seed_keypair' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_generichash_final' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_generichash_init' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_generichash_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_generichash_update' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_generichash' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kdf_derive_from_key' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kdf_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kx_client_session_keys' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kx_keypair' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kx_publickey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kx_secretkey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kx_seed_keypair' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kx_server_session_keys' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_pwhash_scryptsalsa208sha256_str_verify' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_pwhash_scryptsalsa208sha256_str' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_pwhash_scryptsalsa208sha256' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_pwhash_str_needs_rehash' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_pwhash_str_verify' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_pwhash_str' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_pwhash' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_scalarmult_base' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_scalarmult' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretbox_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretbox_open' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretbox' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretstream_xchacha20poly1305_init_pull' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretstream_xchacha20poly1305_init_push' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretstream_xchacha20poly1305_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretstream_xchacha20poly1305_pull' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretstream_xchacha20poly1305_push' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretstream_xchacha20poly1305_rekey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_shorthash_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_shorthash' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_detached' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_ed25519_pk_to_curve25519' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_ed25519_sk_to_curve25519' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_keypair_from_secretkey_and_publickey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_keypair' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_open' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_publickey_from_secretkey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_publickey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_secretkey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_seed_keypair' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_verify_detached' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_stream_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_stream_xor' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_stream' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_hex2bin' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_increment' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_memcmp' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_memzero' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_pad' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_unpad' => array( + '7.1' => false, + '7.2' => true, + ), + // Introduced in 7.2.14 and 7.3.1 simultanously. + 'oci_set_call_timeout' => array( + '7.2.13' => false, + '7.2.14' => true, + ), + // Introduced in 7.2.14 and 7.3.1 simultanously. + 'oci_set_db_operation' => array( + '7.2.13' => false, + '7.2.14' => true, + ), + + 'hrtime' => array( + '7.2' => false, + '7.3' => true, + ), + 'is_countable' => array( + '7.2' => false, + '7.3' => true, + ), + 'array_key_first' => array( + '7.2' => false, + '7.3' => true, + ), + 'array_key_last' => array( + '7.2' => false, + '7.3' => true, + ), + 'fpm_get_status' => array( + '7.2' => false, + '7.3' => true, + ), + 'net_get_interfaces' => array( + '7.2' => false, + '7.3' => true, + ), + 'gmp_binomial' => array( + '7.2' => false, + '7.3' => true, + ), + 'gmp_lcm' => array( + '7.2' => false, + '7.3' => true, + ), + 'gmp_perfect_power' => array( + '7.2' => false, + '7.3' => true, + ), + 'gmp_kronecker' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_add_ext' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_bind_ext' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_delete_ext' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_exop_refresh' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_mod_add_ext' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_mod_replace_ext' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_mod_del_ext' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_rename_ext' => array( + '7.2' => false, + '7.3' => true, + ), + 'normalizer_get_raw_decomposition' => array( + '7.2' => false, + '7.3' => true, + ), + 'openssl_pkey_derive' => array( + '7.2' => false, + '7.3' => true, + ), + 'socket_wsaprotocol_info_export' => array( + '7.2' => false, + '7.3' => true, + ), + 'socket_wsaprotocol_info_import' => array( + '7.2' => false, + '7.3' => true, + ), + 'socket_wsaprotocol_info_release' => array( + '7.2' => false, + '7.3' => true, + ), + + 'get_mangled_object_vars' => array( + '7.3' => false, + '7.4' => true, + ), + 'imagecreatefromtga' => array( + '7.3' => false, + '7.4' => true, + ), + 'mb_str_split' => array( + '7.3' => false, + '7.4' => true, + ), + 'openssl_x509_verify' => array( + '7.3' => false, + '7.4' => true, + ), + 'password_algos' => array( + '7.3' => false, + '7.4' => true, + ), + 'pcntl_unshare' => array( + '7.3' => false, + '7.4' => true, + ), + 'sapi_windows_set_ctrl_handler' => array( + '7.3' => false, + '7.4' => true, + ), + 'sapi_windows_generate_ctrl_event' => array( + '7.3' => false, + '7.4' => true, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.6 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of function names. + $this->newFunctions = $this->arrayKeysToLowercase($this->newFunctions); + + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CONST => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + + } elseif ($tokens[$prevToken]['code'] === \T_NS_SEPARATOR && $tokens[$prevToken - 1]['code'] === \T_STRING) { + // Namespaced function. + return; + } + + $function = $tokens[$stackPtr]['content']; + $functionLc = strtolower($function); + + if (isset($this->newFunctions[$functionLc]) === false) { + return; + } + + $itemInfo = array( + 'name' => $function, + 'nameLc' => $functionLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newFunctions[$itemInfo['nameLc']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The function %s() is not present in PHP version %s or earlier'; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/OptionalToRequiredFunctionParametersSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/OptionalToRequiredFunctionParametersSniff.php new file mode 100644 index 00000000..301e5e07 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/OptionalToRequiredFunctionParametersSniff.php @@ -0,0 +1,173 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionUse; + +use PHPCompatibility\Sniffs\FunctionUse\RequiredToOptionalFunctionParametersSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect missing required function parameters in calls to native PHP functions. + * + * Specifically when those function parameters used to be optional in older PHP versions. + * + * PHP version All + * + * @link https://www.php.net/manual/en/doc.changelog.php + * + * @since 8.1.0 + * @since 9.0.0 Renamed from `OptionalRequiredFunctionParametersSniff` to `OptionalToRequiredFunctionParametersSniff`. + */ +class OptionalToRequiredFunctionParametersSniff extends RequiredToOptionalFunctionParametersSniff +{ + + /** + * A list of function parameters, which were optional in older versions and became required later on. + * + * The array lists : version number with true (required) and false (optional use deprecated). + * + * The index is the location of the parameter in the parameter list, starting at 0 ! + * If's sufficient to list the last version in which the parameter was not yet required. + * + * @since 8.1.0 + * + * @var array + */ + protected $functionParameters = array( + // Special case, the optional nature is not deprecated, but usage is recommended + // and leaving the parameter out will throw an E_NOTICE. + 'crypt' => array( + 1 => array( + 'name' => 'salt', + '5.6' => 'recommended', + ), + ), + 'parse_str' => array( + 1 => array( + 'name' => 'result', + '7.2' => false, + ), + ), + ); + + + /** + * Determine whether an error/warning should be thrown for an item based on collected information. + * + * @since 8.1.0 + * + * @param array $errorInfo Detail information about an item. + * + * @return bool + */ + protected function shouldThrowError(array $errorInfo) + { + return ($errorInfo['optionalDeprecated'] !== '' + || $errorInfo['optionalRemoved'] !== '' + || $errorInfo['optionalRecommended'] !== ''); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 8.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = array( + 'paramName' => '', + 'optionalRecommended' => '', + 'optionalDeprecated' => '', + 'optionalRemoved' => '', + 'error' => false, + ); + + $versionArray = $this->getVersionArray($itemArray); + + if (empty($versionArray) === false) { + foreach ($versionArray as $version => $required) { + if ($this->supportsAbove($version) === true) { + if ($required === true && $errorInfo['optionalRemoved'] === '') { + $errorInfo['optionalRemoved'] = $version; + $errorInfo['error'] = true; + } elseif ($required === 'recommended' && $errorInfo['optionalRecommended'] === '') { + $errorInfo['optionalRecommended'] = $version; + } elseif ($errorInfo['optionalDeprecated'] === '') { + $errorInfo['optionalDeprecated'] = $version; + } + } + } + } + + $errorInfo['paramName'] = $itemArray['name']; + + return $errorInfo; + } + + + /** + * Generates the error or warning for this item. + * + * @since 8.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the relevant token in + * the stack. + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Array with detail (version) information + * relevant to the item. + * + * @return void + */ + public function addError(File $phpcsFile, $stackPtr, array $itemInfo, array $errorInfo) + { + $error = 'The "%s" parameter for function %s() is missing. Passing this parameter is '; + if ($errorInfo['optionalRecommended'] === '') { + $error .= 'no longer optional. The optional nature of the parameter is '; + } else { + $error .= 'strongly recommended '; + } + + $errorCode = $this->stringToErrorCode($itemInfo['name'] . '_' . $errorInfo['paramName']); + $data = array( + $errorInfo['paramName'], + $itemInfo['name'], + ); + + if ($errorInfo['optionalRecommended'] !== '') { + $error .= 'since PHP %s '; + $errorCode .= 'SoftRecommended'; + $data[] = $errorInfo['optionalRecommended']; + } else { + if ($errorInfo['optionalDeprecated'] !== '') { + $error .= 'deprecated since PHP %s and '; + $errorCode .= 'SoftRequired'; + $data[] = $errorInfo['optionalDeprecated']; + } + + if ($errorInfo['optionalRemoved'] !== '') { + $error .= 'removed since PHP %s and '; + $errorCode .= 'HardRequired'; + $data[] = $errorInfo['optionalRemoved']; + } + + // Remove the last 'and' from the message. + $error = substr($error, 0, (\strlen($error) - 5)); + } + + $this->addMessage($phpcsFile, $error, $stackPtr, $errorInfo['error'], $errorCode, $data); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RemovedFunctionParametersSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RemovedFunctionParametersSniff.php new file mode 100644 index 00000000..b4cad10b --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RemovedFunctionParametersSniff.php @@ -0,0 +1,292 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionUse; + +use PHPCompatibility\AbstractRemovedFeatureSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect use of deprecated/removed function parameters in calls to native PHP functions. + * + * PHP version All + * + * @link https://www.php.net/manual/en/doc.changelog.php + * + * @since 7.0.0 + * @since 7.1.0 Now extends the `AbstractRemovedFeatureSniff` instead of the base `Sniff` class. + */ +class RemovedFunctionParametersSniff extends AbstractRemovedFeatureSniff +{ + /** + * A list of removed function parameters, which were present in older versions. + * + * The array lists : version number with false (deprecated) and true (removed). + * The index is the location of the parameter in the parameter list, starting at 0 ! + * If's sufficient to list the first version where the function parameter was deprecated/removed. + * + * The optional `callback` key can be used to pass a method name which should be called for an + * additional check. The method will be passed the parameter info and should return true + * if the notice should be thrown or false otherwise. + * + * @since 7.0.0 + * @since 7.0.2 Visibility changed from `public` to `protected`. + * @since 9.3.0 Optional `callback` key. + * + * @var array + */ + protected $removedFunctionParameters = array( + 'curl_version' => array( + 0 => array( + 'name' => 'age', + '7.4' => false, + 'callback' => 'curlVersionInvalidValue', + ), + ), + 'define' => array( + 2 => array( + 'name' => 'case_insensitive', + '7.3' => false, // Slated for removal in PHP 8.0.0. + ), + ), + 'gmmktime' => array( + 6 => array( + 'name' => 'is_dst', + '5.1' => false, + '7.0' => true, + ), + ), + 'ldap_first_attribute' => array( + 2 => array( + 'name' => 'ber_identifier', + '5.2.4' => true, + ), + ), + 'ldap_next_attribute' => array( + 2 => array( + 'name' => 'ber_identifier', + '5.2.4' => true, + ), + ), + 'mktime' => array( + 6 => array( + 'name' => 'is_dst', + '5.1' => false, + '7.0' => true, + ), + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of function names. + $this->removedFunctionParameters = $this->arrayKeysToLowercase($this->removedFunctionParameters); + + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CONST => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + $function = $tokens[$stackPtr]['content']; + $functionLc = strtolower($function); + + if (isset($this->removedFunctionParameters[$functionLc]) === false) { + return; + } + + $parameters = $this->getFunctionCallParameters($phpcsFile, $stackPtr); + $parameterCount = \count($parameters); + if ($parameterCount === 0) { + return; + } + + // If the parameter count returned > 0, we know there will be valid open parenthesis. + $openParenthesis = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + $parameterOffsetFound = $parameterCount - 1; + + foreach ($this->removedFunctionParameters[$functionLc] as $offset => $parameterDetails) { + if ($offset <= $parameterOffsetFound) { + if (isset($parameterDetails['callback']) && method_exists($this, $parameterDetails['callback'])) { + if ($this->{$parameterDetails['callback']}($phpcsFile, $parameters[($offset + 1)]) === false) { + continue; + } + } + + $itemInfo = array( + 'name' => $function, + 'nameLc' => $functionLc, + 'offset' => $offset, + ); + $this->handleFeature($phpcsFile, $openParenthesis, $itemInfo); + } + } + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->removedFunctionParameters[$itemInfo['nameLc']][$itemInfo['offset']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('name', 'callback'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['paramName'] = $itemArray['name']; + + return $errorInfo; + } + + + /** + * Get the item name to be used for the creation of the error code. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Detail information about an item. + * + * @return string + */ + protected function getItemName(array $itemInfo, array $errorInfo) + { + return $itemInfo['name'] . '_' . $errorInfo['paramName']; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The "%s" parameter for function %s() is '; + } + + + /** + * Filter the error data before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + array_shift($data); + array_unshift($data, $errorInfo['paramName'], $itemInfo['name']); + return $data; + } + + /** + * Check whether curl_version() was passed the default CURLVERSION_NOW. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param array $parameter Parameter info array. + * + * @return bool True if the value was not CURLVERSION_NOW, false otherwise. + */ + protected function curlVersionInvalidValue(File $phpcsFile, array $parameter) + { + $tokens = $phpcsFile->getTokens(); + $raw = ''; + for ($i = $parameter['start']; $i <= $parameter['end']; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']])) { + continue; + } + + $raw .= $tokens[$i]['content']; + } + + if ($raw !== 'CURLVERSION_NOW' + && $raw !== (string) \CURLVERSION_NOW + ) { + return true; + } + + return false; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RemovedFunctionsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RemovedFunctionsSniff.php new file mode 100644 index 00000000..33f3d393 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RemovedFunctionsSniff.php @@ -0,0 +1,1104 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionUse; + +use PHPCompatibility\AbstractRemovedFeatureSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect calls to deprecated/removed native PHP functions. + * + * Suggests alternative if available. + * + * PHP version All + * + * @since 5.5 + * @since 5.6 Now extends the base `Sniff` class instead of the upstream + * `Generic.PHP.ForbiddenFunctions` sniff. + * @since 7.1.0 Now extends the `AbstractRemovedFeatureSniff` instead of the base `Sniff` class. + * @since 9.0.0 Renamed from `DeprecatedFunctionsSniff` to `RemovedFunctionsSniff`. + */ +class RemovedFunctionsSniff extends AbstractRemovedFeatureSniff +{ + /** + * A list of deprecated and removed functions with their alternatives. + * + * The array lists : version number with false (deprecated) or true (removed) and an alternative function. + * If no alternative exists, it is NULL, i.e, the function should just not be used. + * + * @since 5.5 + * @since 5.6 Visibility changed from `protected` to `public`. + * @since 7.0.2 Visibility changed back from `public` to `protected`. + * The earlier change was made to be in line with the upstream sniff, + * but that sniff is no longer being extended. + * @since 7.0.8 Property renamed from `$forbiddenFunctions` to `$removedFunctions`. + * + * @var array(string => array(string => bool|string|null)) + */ + protected $removedFunctions = array( + 'php_check_syntax' => array( + '5.0.5' => true, + 'alternative' => null, + ), + + 'pfpro_cleanup' => array( + '5.1' => true, + 'alternative' => null, + ), + 'pfpro_init' => array( + '5.1' => true, + 'alternative' => null, + ), + 'pfpro_process_raw' => array( + '5.1' => true, + 'alternative' => null, + ), + 'pfpro_process' => array( + '5.1' => true, + 'alternative' => null, + ), + 'pfpro_version' => array( + '5.1' => true, + 'alternative' => null, + ), + + 'call_user_method' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'call_user_func()', + ), + 'call_user_method_array' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'call_user_func_array()', + ), + 'define_syslog_variables' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => null, + ), + 'dl' => array( + '5.3' => false, + 'alternative' => null, + ), + 'ereg' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'preg_match()', + ), + 'ereg_replace' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'preg_replace()', + ), + 'eregi' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'preg_match()', + ), + 'eregi_replace' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'preg_replace()', + ), + 'imagepsbbox' => array( + '7.0' => true, + 'alternative' => null, + ), + 'imagepsencodefont' => array( + '7.0' => true, + 'alternative' => null, + ), + 'imagepsextendfont' => array( + '7.0' => true, + 'alternative' => null, + ), + 'imagepsfreefont' => array( + '7.0' => true, + 'alternative' => null, + ), + 'imagepsloadfont' => array( + '7.0' => true, + 'alternative' => null, + ), + 'imagepsslantfont' => array( + '7.0' => true, + 'alternative' => null, + ), + 'imagepstext' => array( + '7.0' => true, + 'alternative' => null, + ), + 'import_request_variables' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => null, + ), + 'ldap_sort' => array( + '7.0' => false, + 'alternative' => null, + ), + 'mcrypt_generic_end' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'mcrypt_generic_deinit()', + ), + 'mysql_db_query' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'mysqli::select_db() and mysqli::query()', + ), + 'mysql_escape_string' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'mysqli::real_escape_string()', + ), + 'mysql_list_dbs' => array( + '5.4' => false, + '7.0' => true, + 'alternative' => null, + ), + 'mysqli_bind_param' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'mysqli_stmt::bind_param()', + ), + 'mysqli_bind_result' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'mysqli_stmt::bind_result()', + ), + 'mysqli_client_encoding' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'mysqli::character_set_name()', + ), + 'mysqli_fetch' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'mysqli_stmt::fetch()', + ), + 'mysqli_param_count' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'mysqli_stmt_param_count()', + ), + 'mysqli_get_metadata' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'mysqli_stmt::result_metadata()', + ), + 'mysqli_send_long_data' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'mysqli_stmt::send_long_data()', + ), + 'magic_quotes_runtime' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => null, + ), + 'session_register' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_SESSION', + ), + 'session_unregister' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_SESSION', + ), + 'session_is_registered' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_SESSION', + ), + 'set_magic_quotes_runtime' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => null, + ), + 'set_socket_blocking' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'stream_set_blocking()', + ), + 'split' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'preg_split()', + ), + 'spliti' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'preg_split()', + ), + 'sql_regcase' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => null, + ), + 'php_logo_guid' => array( + '5.5' => true, + 'alternative' => null, + ), + 'php_egg_logo_guid' => array( + '5.5' => true, + 'alternative' => null, + ), + 'php_real_logo_guid' => array( + '5.5' => true, + 'alternative' => null, + ), + 'zend_logo_guid' => array( + '5.5' => true, + 'alternative' => null, + ), + 'datefmt_set_timezone_id' => array( + '5.5' => false, + '7.0' => true, + 'alternative' => 'IntlDateFormatter::setTimeZone()', + ), + 'mcrypt_ecb' => array( + '5.5' => false, + '7.0' => true, + 'alternative' => null, + ), + 'mcrypt_cbc' => array( + '5.5' => false, + '7.0' => true, + 'alternative' => null, + ), + 'mcrypt_cfb' => array( + '5.5' => false, + '7.0' => true, + 'alternative' => null, + ), + 'mcrypt_ofb' => array( + '5.5' => false, + '7.0' => true, + 'alternative' => null, + ), + 'ocibindbyname' => array( + '5.4' => false, + 'alternative' => 'oci_bind_by_name()', + ), + 'ocicancel' => array( + '5.4' => false, + 'alternative' => 'oci_cancel()', + ), + 'ocicloselob' => array( + '5.4' => false, + 'alternative' => 'OCI-Lob::close()', + ), + 'ocicollappend' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::append()', + ), + 'ocicollassign' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::assign()', + ), + 'ocicollassignelem' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::assignElem()', + ), + 'ocicollgetelem' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::getElem()', + ), + 'ocicollmax' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::max()', + ), + 'ocicollsize' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::size()', + ), + 'ocicolltrim' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::trim()', + ), + 'ocicolumnisnull' => array( + '5.4' => false, + 'alternative' => 'oci_field_is_null()', + ), + 'ocicolumnname' => array( + '5.4' => false, + 'alternative' => 'oci_field_name()', + ), + 'ocicolumnprecision' => array( + '5.4' => false, + 'alternative' => 'oci_field_precision()', + ), + 'ocicolumnscale' => array( + '5.4' => false, + 'alternative' => 'oci_field_scale()', + ), + 'ocicolumnsize' => array( + '5.4' => false, + 'alternative' => 'oci_field_size()', + ), + 'ocicolumntype' => array( + '5.4' => false, + 'alternative' => 'oci_field_type()', + ), + 'ocicolumntyperaw' => array( + '5.4' => false, + 'alternative' => 'oci_field_type_raw()', + ), + 'ocicommit' => array( + '5.4' => false, + 'alternative' => 'oci_commit()', + ), + 'ocidefinebyname' => array( + '5.4' => false, + 'alternative' => 'oci_define_by_name()', + ), + 'ocierror' => array( + '5.4' => false, + 'alternative' => 'oci_error()', + ), + 'ociexecute' => array( + '5.4' => false, + 'alternative' => 'oci_execute()', + ), + 'ocifetch' => array( + '5.4' => false, + 'alternative' => 'oci_fetch()', + ), + 'ocifetchinto' => array( + '5.4' => false, + 'alternative' => null, + ), + 'ocifetchstatement' => array( + '5.4' => false, + 'alternative' => 'oci_fetch_all()', + ), + 'ocifreecollection' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::free()', + ), + 'ocifreecursor' => array( + '5.4' => false, + 'alternative' => 'oci_free_statement()', + ), + 'ocifreedesc' => array( + '5.4' => false, + 'alternative' => 'OCI-Lob::free()', + ), + 'ocifreestatement' => array( + '5.4' => false, + 'alternative' => 'oci_free_statement()', + ), + 'ociinternaldebug' => array( + '5.4' => false, + 'alternative' => 'oci_internal_debug()', + ), + 'ociloadlob' => array( + '5.4' => false, + 'alternative' => 'OCI-Lob::load()', + ), + 'ocilogoff' => array( + '5.4' => false, + 'alternative' => 'oci_close()', + ), + 'ocilogon' => array( + '5.4' => false, + 'alternative' => 'oci_connect()', + ), + 'ocinewcollection' => array( + '5.4' => false, + 'alternative' => 'oci_new_collection()', + ), + 'ocinewcursor' => array( + '5.4' => false, + 'alternative' => 'oci_new_cursor()', + ), + 'ocinewdescriptor' => array( + '5.4' => false, + 'alternative' => 'oci_new_descriptor()', + ), + 'ocinlogon' => array( + '5.4' => false, + 'alternative' => 'oci_new_connect()', + ), + 'ocinumcols' => array( + '5.4' => false, + 'alternative' => 'oci_num_fields()', + ), + 'ociparse' => array( + '5.4' => false, + 'alternative' => 'oci_parse()', + ), + 'ociplogon' => array( + '5.4' => false, + 'alternative' => 'oci_pconnect()', + ), + 'ociresult' => array( + '5.4' => false, + 'alternative' => 'oci_result()', + ), + 'ocirollback' => array( + '5.4' => false, + 'alternative' => 'oci_rollback()', + ), + 'ocirowcount' => array( + '5.4' => false, + 'alternative' => 'oci_num_rows()', + ), + 'ocisavelob' => array( + '5.4' => false, + 'alternative' => 'OCI-Lob::save()', + ), + 'ocisavelobfile' => array( + '5.4' => false, + 'alternative' => 'OCI-Lob::import()', + ), + 'ociserverversion' => array( + '5.4' => false, + 'alternative' => 'oci_server_version()', + ), + 'ocisetprefetch' => array( + '5.4' => false, + 'alternative' => 'oci_set_prefetch()', + ), + 'ocistatementtype' => array( + '5.4' => false, + 'alternative' => 'oci_statement_type()', + ), + 'ociwritelobtofile' => array( + '5.4' => false, + 'alternative' => 'OCI-Lob::export()', + ), + 'ociwritetemporarylob' => array( + '5.4' => false, + 'alternative' => 'OCI-Lob::writeTemporary()', + ), + 'mysqli_get_cache_stats' => array( + '5.4' => true, + 'alternative' => null, + ), + + 'mcrypt_create_iv' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'random_bytes() or OpenSSL', + ), + 'mcrypt_decrypt' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_get_algorithms_name' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_get_block_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_get_iv_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_get_key_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_get_modes_name' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_get_supported_key_sizes' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_is_block_algorithm_mode' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_is_block_algorithm' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_is_block_mode' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_self_test' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_encrypt' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_generic_deinit' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_generic_init' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_generic' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_get_block_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_get_cipher_name' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_get_iv_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_get_key_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_list_algorithms' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_list_modes' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_close' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_get_algo_block_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_get_algo_key_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_get_supported_key_sizes' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_is_block_algorithm_mode' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_is_block_algorithm' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_is_block_mode' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_open' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_self_test' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mdecrypt_generic' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'jpeg2wbmp' => array( + '7.2' => false, + 'alternative' => 'imagecreatefromjpeg() and imagewbmp()', + ), + 'png2wbmp' => array( + '7.2' => false, + 'alternative' => 'imagecreatefrompng() or imagewbmp()', + ), + 'create_function' => array( + '7.2' => false, + 'alternative' => 'an anonymous function', + ), + 'each' => array( + '7.2' => false, + 'alternative' => 'a foreach loop', + ), + 'gmp_random' => array( + '7.2' => false, + 'alternative' => 'gmp_random_bits() or gmp_random_range()', + ), + 'read_exif_data' => array( + '7.2' => false, + 'alternative' => 'exif_read_data()', + ), + + 'image2wbmp' => array( + '7.3' => false, + 'alternative' => 'imagewbmp()', + ), + 'mbregex_encoding' => array( + '7.3' => false, + 'alternative' => 'mb_regex_encoding()', + ), + 'mbereg' => array( + '7.3' => false, + 'alternative' => 'mb_ereg()', + ), + 'mberegi' => array( + '7.3' => false, + 'alternative' => 'mb_eregi()', + ), + 'mbereg_replace' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_replace()', + ), + 'mberegi_replace' => array( + '7.3' => false, + 'alternative' => 'mb_eregi_replace()', + ), + 'mbsplit' => array( + '7.3' => false, + 'alternative' => 'mb_split()', + ), + 'mbereg_match' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_match()', + ), + 'mbereg_search' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_search()', + ), + 'mbereg_search_pos' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_search_pos()', + ), + 'mbereg_search_regs' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_search_regs()', + ), + 'mbereg_search_init' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_search_init()', + ), + 'mbereg_search_getregs' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_search_getregs()', + ), + 'mbereg_search_getpos' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_search_getpos()', + ), + 'mbereg_search_setpos' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_search_setpos()', + ), + 'fgetss' => array( + '7.3' => false, + 'alternative' => null, + ), + 'gzgetss' => array( + '7.3' => false, + 'alternative' => null, + ), + + 'convert_cyr_string' => array( + '7.4' => false, + 'alternative' => 'mb_convert_encoding(), iconv() or UConverter', + ), + 'ezmlm_hash' => array( + '7.4' => false, + 'alternative' => null, + ), + 'get_magic_quotes_gpc' => array( + '7.4' => false, + 'alternative' => null, + ), + 'get_magic_quotes_runtime' => array( + '7.4' => false, + 'alternative' => null, + ), + 'hebrevc' => array( + '7.4' => false, + 'alternative' => null, + ), + 'is_real' => array( + '7.4' => false, + 'alternative' => 'is_float()', + ), + 'money_format' => array( + '7.4' => false, + 'alternative' => 'NumberFormatter::formatCurrency()', + ), + 'restore_include_path' => array( + '7.4' => false, + 'alternative' => "ini_restore('include_path')", + ), + 'ibase_add_user' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_affected_rows' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_backup' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_add' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_cancel' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_close' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_create' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_echo' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_get' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_import' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_info' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_open' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_close' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_commit_ret' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_commit' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_connect' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_db_info' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_delete_user' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_drop_db' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_errcode' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_errmsg' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_execute' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_fetch_assoc' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_fetch_object' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_fetch_row' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_field_info' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_free_event_handler' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_free_query' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_free_result' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_gen_id' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_maintain_db' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_modify_user' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_name_result' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_num_fields' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_num_params' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_param_info' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_pconnect' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_prepare' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_query' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_restore' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_rollback_ret' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_rollback' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_server_info' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_service_attach' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_service_detach' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_set_event_handler' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_trans' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_wait_event' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ldap_control_paged_result_response' => array( + '7.4' => false, + 'alternative' => 'ldap_search()', + ), + 'ldap_control_paged_result' => array( + '7.4' => false, + 'alternative' => 'ldap_search()', + ), + 'recode_file' => array( + '7.4' => true, + 'alternative' => 'the iconv or mbstring extension', + ), + 'recode_string' => array( + '7.4' => true, + 'alternative' => 'the iconv or mbstring extension', + ), + 'recode' => array( + '7.4' => true, + 'alternative' => 'the iconv or mbstring extension', + ), + 'wddx_add_vars' => array( + '7.4' => true, + 'alternative' => null, + ), + 'wddx_deserialize' => array( + '7.4' => true, + 'alternative' => null, + ), + 'wddx_packet_end' => array( + '7.4' => true, + 'alternative' => null, + ), + 'wddx_packet_start' => array( + '7.4' => true, + 'alternative' => null, + ), + 'wddx_serialize_value' => array( + '7.4' => true, + 'alternative' => null, + ), + 'wddx_serialize_vars' => array( + '7.4' => true, + 'alternative' => null, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.6 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of function names. + $this->removedFunctions = $this->arrayKeysToLowercase($this->removedFunctions); + + return array(\T_STRING); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CLASS => true, + \T_CONST => true, + \T_USE => true, + \T_NS_SEPARATOR => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + $function = $tokens[$stackPtr]['content']; + $functionLc = strtolower($function); + + if (isset($this->removedFunctions[$functionLc]) === false) { + return; + } + + $itemInfo = array( + 'name' => $function, + 'nameLc' => $functionLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->removedFunctions[$itemInfo['nameLc']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'Function %s() is '; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RequiredToOptionalFunctionParametersSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RequiredToOptionalFunctionParametersSniff.php new file mode 100644 index 00000000..9c32ccca --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RequiredToOptionalFunctionParametersSniff.php @@ -0,0 +1,350 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\FunctionUse; + +use PHPCompatibility\AbstractComplexVersionSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect missing required function parameters in calls to native PHP functions. + * + * Specifically when those function parameters are no longer required in more recent PHP versions. + * + * PHP version All + * + * @link https://www.php.net/manual/en/doc.changelog.php + * + * @since 7.0.3 + * @since 7.1.0 Now extends the `AbstractComplexVersionSniff` instead of the base `Sniff` class. + * @since 9.0.0 Renamed from `RequiredOptionalFunctionParametersSniff` to `RequiredToOptionalFunctionParametersSniff`. + */ +class RequiredToOptionalFunctionParametersSniff extends AbstractComplexVersionSniff +{ + + /** + * A list of function parameters, which were required in older versions and became optional later on. + * + * The array lists : version number with true (required) and false (optional). + * + * The index is the location of the parameter in the parameter list, starting at 0 ! + * If's sufficient to list the last version in which the parameter was still required. + * + * @since 7.0.3 + * + * @var array + */ + protected $functionParameters = array( + 'array_merge' => array( + 0 => array( + 'name' => 'array(s) to merge', + '7.3' => true, + '7.4' => false, + ), + ), + 'array_merge_recursive' => array( + 0 => array( + 'name' => 'array(s) to merge', + '7.3' => true, + '7.4' => false, + ), + ), + 'array_push' => array( + 1 => array( + 'name' => 'element to push', + '7.2' => true, + '7.3' => false, + ), + ), + 'array_unshift' => array( + 1 => array( + 'name' => 'element to prepend', + '7.2' => true, + '7.3' => false, + ), + ), + 'bcscale' => array( + 0 => array( + 'name' => 'scale', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_fget' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_fput' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_get' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_nb_fget' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_nb_fput' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_nb_get' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_nb_put' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_put' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'getenv' => array( + 0 => array( + 'name' => 'varname', + '7.0' => true, + '7.1' => false, + ), + ), + 'preg_match_all' => array( + 2 => array( + 'name' => 'matches', + '5.3' => true, + '5.4' => false, + ), + ), + 'stream_socket_enable_crypto' => array( + 2 => array( + 'name' => 'crypto_type', + '5.5' => true, + '5.6' => false, + ), + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.3 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of function names. + $this->functionParameters = $this->arrayKeysToLowercase($this->functionParameters); + + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CONST => true, + \T_NEW => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + $function = $tokens[$stackPtr]['content']; + $functionLc = strtolower($function); + + if (isset($this->functionParameters[$functionLc]) === false) { + return; + } + + $parameterCount = $this->getFunctionCallParameterCount($phpcsFile, $stackPtr); + $openParenthesis = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + + // If the parameter count returned > 0, we know there will be valid open parenthesis. + if ($parameterCount === 0 && $tokens[$openParenthesis]['code'] !== \T_OPEN_PARENTHESIS) { + return; + } + + $parameterOffsetFound = $parameterCount - 1; + + foreach ($this->functionParameters[$functionLc] as $offset => $parameterDetails) { + if ($offset > $parameterOffsetFound) { + $itemInfo = array( + 'name' => $function, + 'nameLc' => $functionLc, + 'offset' => $offset, + ); + $this->handleFeature($phpcsFile, $openParenthesis, $itemInfo); + } + } + } + + + /** + * Determine whether an error/warning should be thrown for an item based on collected information. + * + * @since 7.1.0 + * + * @param array $errorInfo Detail information about an item. + * + * @return bool + */ + protected function shouldThrowError(array $errorInfo) + { + return ($errorInfo['requiredVersion'] !== ''); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->functionParameters[$itemInfo['nameLc']][$itemInfo['offset']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('name'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = array( + 'paramName' => '', + 'requiredVersion' => '', + ); + + $versionArray = $this->getVersionArray($itemArray); + + if (empty($versionArray) === false) { + foreach ($versionArray as $version => $required) { + if ($required === true && $this->supportsBelow($version) === true) { + $errorInfo['requiredVersion'] = $version; + } + } + } + + $errorInfo['paramName'] = $itemArray['name']; + + return $errorInfo; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The "%s" parameter for function %s() is missing, but was required for PHP version %s and lower'; + } + + + /** + * Generates the error or warning for this item. + * + * @since 7.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the relevant token in + * the stack. + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Array with detail (version) information + * relevant to the item. + * + * @return void + */ + public function addError(File $phpcsFile, $stackPtr, array $itemInfo, array $errorInfo) + { + $error = $this->getErrorMsgTemplate(); + $errorCode = $this->stringToErrorCode($itemInfo['name'] . '_' . $errorInfo['paramName']) . 'Missing'; + $data = array( + $errorInfo['paramName'], + $itemInfo['name'], + $errorInfo['requiredVersion'], + ); + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Generators/NewGeneratorReturnSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Generators/NewGeneratorReturnSniff.php new file mode 100644 index 00000000..98ca2461 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Generators/NewGeneratorReturnSniff.php @@ -0,0 +1,158 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Generators; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; + +/** + * As of PHP 7.0, a `return` statement can be used within a generator for a final expression to be returned. + * + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/migration70.new-features.php#migration70.new-features.generator-return-expressions + * @link https://wiki.php.net/rfc/generator-return-expressions + * @link https://www.php.net/manual/en/language.generators.syntax.php + * + * @since 8.2.0 + */ +class NewGeneratorReturnSniff extends Sniff +{ + /** + * Scope conditions within which a yield can exist. + * + * @since 9.0.0 + * + * @var array + */ + private $validConditions = array( + \T_FUNCTION => \T_FUNCTION, + \T_CLOSURE => \T_CLOSURE, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.2.0 + * + * @return array + */ + public function register() + { + $targets = array( + \T_YIELD, + ); + + /* + * The `yield` keyword was introduced in PHP 5.5 with the token T_YIELD. + * The `yield from` keyword was introduced in PHP 7.0 and tokenizes as + * "T_YIELD T_WHITESPACE T_STRING". + * + * Pre-PHPCS 3.1.0, the T_YIELD token was not correctly back-filled for PHP < 5.5. + * Also, as of PHPCS 3.1.0, the PHPCS tokenizer adds a new T_YIELD_FROM + * token. + * + * So for PHP 5.3-5.4 icw PHPCS < 3.1.0, we need to look for T_STRING with content "yield". + * For PHP 5.5+ we need to look for T_YIELD. + * For PHPCS 3.1.0+, we also need to look for T_YIELD_FROM. + */ + if (version_compare(\PHP_VERSION_ID, '50500', '<') === true + && version_compare(PHPCSHelper::getVersion(), '3.1.0', '<') === true + ) { + $targets[] = \T_STRING; + } + + if (\defined('T_YIELD_FROM')) { + $targets[] = \T_YIELD_FROM; + } + + return $targets; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void|int Void or a stack pointer to skip forward. + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.6') !== true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === \T_STRING + && $tokens[$stackPtr]['content'] !== 'yield' + ) { + return; + } + + if (empty($tokens[$stackPtr]['conditions']) === true) { + return; + } + + // Walk the condition from inner to outer to see if we can find a valid function/closure scope. + $conditions = array_reverse($tokens[$stackPtr]['conditions'], true); + foreach ($conditions as $ptr => $type) { + if (isset($this->validConditions[$type]) === true) { + $function = $ptr; + break; + } + } + + if (isset($function) === false) { + // Yield outside function scope, fatal error, but not our concern. + return; + } + + if (isset($tokens[$function]['scope_opener'], $tokens[$function]['scope_closer']) === false) { + // Can't reliably determine start/end of function scope. + return; + } + + $targets = array(\T_RETURN, \T_CLOSURE, \T_FUNCTION, \T_CLASS); + if (\defined('T_ANON_CLASS')) { + $targets[] = \T_ANON_CLASS; + } + + $current = $tokens[$function]['scope_opener']; + + while (($current = $phpcsFile->findNext($targets, ($current + 1), $tokens[$function]['scope_closer'])) !== false) { + if ($tokens[$current]['code'] === \T_RETURN) { + $phpcsFile->addError( + 'Returning a final expression from a generator was not supported in PHP 5.6 or earlier', + $current, + 'ReturnFound' + ); + + return $tokens[$function]['scope_closer']; + } + + // Found a nested scope in which return can exist without problems. + if (isset($tokens[$current]['scope_closer'])) { + // Skip past the nested scope. + $current = $tokens[$current]['scope_closer']; + } + } + + // Don't examine this function again. + return $tokens[$function]['scope_closer']; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/IniDirectives/NewIniDirectivesSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/IniDirectives/NewIniDirectivesSniff.php new file mode 100644 index 00000000..cd40fa68 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/IniDirectives/NewIniDirectivesSniff.php @@ -0,0 +1,855 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\IniDirectives; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect the use of new INI directives through `ini_set()` or `ini_get()`. + * + * PHP version All + * + * @link https://www.php.net/manual/en/ini.list.php + * @link https://www.php.net/manual/en/ini.core.php + * + * @since 5.5 + * @since 7.0.7 When a new directive is used with `ini_set()`, the sniff will now throw an error + * instead of a warning. + * @since 7.1.0 Now extends the `AbstractNewFeatureSniff` instead of the base `Sniff` class.. + */ +class NewIniDirectivesSniff extends AbstractNewFeatureSniff +{ + /** + * A list of new INI directives + * + * The array lists : version number with false (not present) or true (present). + * If's sufficient to list the first version where the ini directive appears. + * + * @since 5.5 + * @since 7.0.3 Support for 'alternative' has been added. + * + * @var array(string) + */ + protected $newIniDirectives = array( + 'auto_globals_jit' => array( + '4.4' => false, + '5.0' => true, + ), + 'com.code_page' => array( + '4.4' => false, + '5.0' => true, + ), + 'date.default_latitude' => array( + '4.4' => false, + '5.0' => true, + ), + 'date.default_longitude' => array( + '4.4' => false, + '5.0' => true, + ), + 'date.sunrise_zenith' => array( + '4.4' => false, + '5.0' => true, + ), + 'date.sunset_zenith' => array( + '4.4' => false, + '5.0' => true, + ), + 'ibase.default_charset' => array( + '4.4' => false, + '5.0' => true, + ), + 'ibase.default_db' => array( + '4.4' => false, + '5.0' => true, + ), + 'mail.force_extra_parameters' => array( + '4.4' => false, + '5.0' => true, + ), + 'mime_magic.debug' => array( + '4.4' => false, + '5.0' => true, + ), + 'mysqli.max_links' => array( + '4.4' => false, + '5.0' => true, + ), + 'mysqli.default_port' => array( + '4.4' => false, + '5.0' => true, + ), + 'mysqli.default_socket' => array( + '4.4' => false, + '5.0' => true, + ), + 'mysqli.default_host' => array( + '4.4' => false, + '5.0' => true, + ), + 'mysqli.default_user' => array( + '4.4' => false, + '5.0' => true, + ), + 'mysqli.default_pw' => array( + '4.4' => false, + '5.0' => true, + ), + 'report_zend_debug' => array( + '4.4' => false, + '5.0' => true, + ), + 'session.hash_bits_per_character' => array( + '4.4' => false, + '5.0' => true, + ), + 'session.hash_function' => array( + '4.4' => false, + '5.0' => true, + ), + 'soap.wsdl_cache_dir' => array( + '4.4' => false, + '5.0' => true, + ), + 'soap.wsdl_cache_enabled' => array( + '4.4' => false, + '5.0' => true, + ), + 'soap.wsdl_cache_ttl' => array( + '4.4' => false, + '5.0' => true, + ), + 'sqlite.assoc_case' => array( + '4.4' => false, + '5.0' => true, + ), + 'tidy.clean_output' => array( + '4.4' => false, + '5.0' => true, + ), + 'tidy.default_config' => array( + '4.4' => false, + '5.0' => true, + ), + 'zend.ze1_compatibility_mode' => array( + '4.4' => false, + '5.0' => true, + ), + + 'date.timezone' => array( + '5.0' => false, + '5.1' => true, + ), + 'detect_unicode' => array( + '5.0' => false, + '5.1' => true, + ), + 'fbsql.batchsize' => array( + '5.0' => false, + '5.1' => true, + 'alternative' => 'fbsql.batchSize', + ), + 'realpath_cache_size' => array( + '5.0' => false, + '5.1' => true, + ), + 'realpath_cache_ttl' => array( + '5.0' => false, + '5.1' => true, + ), + + 'mbstring.strict_detection' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'mssql.charset' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + + 'gd.jpeg_ignore_warning' => array( + '5.1.2' => false, + '5.1.3' => true, + ), + + 'fbsql.show_timestamp_decimals' => array( + '5.1.4' => false, + '5.1.5' => true, + ), + 'soap.wsdl_cache' => array( + '5.1.4' => false, + '5.1.5' => true, + ), + 'soap.wsdl_cache_limit' => array( + '5.1.4' => false, + '5.1.5' => true, + ), + + 'allow_url_include' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter.default' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter.default_flags' => array( + '5.1' => false, + '5.2' => true, + ), + 'pcre.backtrack_limit' => array( + '5.1' => false, + '5.2' => true, + ), + 'pcre.recursion_limit' => array( + '5.1' => false, + '5.2' => true, + ), + 'session.cookie_httponly' => array( + '5.1' => false, + '5.2' => true, + ), + + 'cgi.check_shebang_line' => array( + '5.2.0' => false, + '5.2.1' => true, + ), + + 'max_input_nesting_level' => array( + '5.2.2' => false, + '5.2.3' => true, + ), + + 'mysqli.allow_local_infile' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + + 'max_file_uploads' => array( + '5.2.11' => false, + '5.2.12' => true, + ), + + 'cgi.discard_path' => array( + '5.2' => false, + '5.3' => true, + ), + 'exit_on_timeout' => array( + '5.2' => false, + '5.3' => true, + ), + 'intl.default_locale' => array( + '5.2' => false, + '5.3' => true, + ), + 'intl.error_level' => array( + '5.2' => false, + '5.3' => true, + ), + 'mail.add_x_header' => array( + '5.2' => false, + '5.3' => true, + ), + 'mail.log' => array( + '5.2' => false, + '5.3' => true, + ), + 'mbstring.http_output_conv_mimetype' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli.allow_persistent' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli.cache_size' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli.max_persistent' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqlnd.collect_memory_statistics' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqlnd.collect_statistics' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqlnd.debug' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqlnd.net_read_buffer_size' => array( + '5.2' => false, + '5.3' => true, + ), + 'odbc.default_cursortype' => array( + '5.2' => false, + '5.3' => true, + ), + 'request_order' => array( + '5.2' => false, + '5.3' => true, + ), + 'user_ini.cache_ttl' => array( + '5.2' => false, + '5.3' => true, + ), + 'user_ini.filename' => array( + '5.2' => false, + '5.3' => true, + ), + 'zend.enable_gc' => array( + '5.2' => false, + '5.3' => true, + ), + + 'curl.cainfo' => array( + '5.3.6' => false, + '5.3.7' => true, + ), + + 'max_input_vars' => array( + '5.3.8' => false, + '5.3.9' => true, + ), + + 'sqlite3.extension_dir' => array( + '5.3.10' => false, + '5.3.11' => true, + ), + + 'cli.pager' => array( + '5.3' => false, + '5.4' => true, + ), + 'cli.prompt' => array( + '5.3' => false, + '5.4' => true, + ), + 'cli_server.color' => array( + '5.3' => false, + '5.4' => true, + ), + 'enable_post_data_reading' => array( + '5.3' => false, + '5.4' => true, + ), + 'mysqlnd.mempool_default_size' => array( + '5.3' => false, + '5.4' => true, + ), + 'mysqlnd.net_cmd_buffer_size' => array( + '5.3' => false, + '5.4' => true, + ), + 'mysqlnd.net_read_timeout' => array( + '5.3' => false, + '5.4' => true, + ), + 'phar.cache_list' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.upload_progress.enabled' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.upload_progress.cleanup' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.upload_progress.name' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.upload_progress.freq' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.upload_progress.min_freq' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.upload_progress.prefix' => array( + '5.3' => false, + '5.4' => true, + ), + 'windows_show_crt_warning' => array( + '5.3' => false, + '5.4' => true, + ), + 'zend.detect_unicode' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'detect_unicode', + ), + 'zend.multibyte' => array( + '5.3' => false, + '5.4' => true, + ), + 'zend.script_encoding' => array( + '5.3' => false, + '5.4' => true, + ), + 'zend.signal_check' => array( + '5.3' => false, + '5.4' => true, + ), + 'mysqlnd.log_mask' => array( + '5.3' => false, + '5.4' => true, + ), + + 'intl.use_exceptions' => array( + '5.4' => false, + '5.5' => true, + ), + 'mysqlnd.sha256_server_public_key' => array( + '5.4' => false, + '5.5' => true, + ), + 'mysqlnd.trace_alloc' => array( + '5.4' => false, + '5.5' => true, + ), + 'sys_temp_dir' => array( + '5.4' => false, + '5.5' => true, + ), + 'xsl.security_prefs' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.enable' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.enable_cli' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.memory_consumption' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.interned_strings_buffer' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.max_accelerated_files' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.max_wasted_percentage' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.use_cwd' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.validate_timestamps' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.revalidate_freq' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.revalidate_path' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.save_comments' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.load_comments' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.fast_shutdown' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.enable_file_override' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.optimization_level' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.inherited_hack' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.dups_fix' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.blacklist_filename' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.max_file_size' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.consistency_checks' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.force_restart_timeout' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.error_log' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.log_verbosity_level' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.preferred_memory_model' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.protect_memory' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.mmap_base' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.restrict_api' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.file_update_protection' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.huge_code_pages' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.lockfile_path' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.opt_debug_level' => array( + '5.4' => false, + '5.5' => true, + ), + + 'session.use_strict_mode' => array( + '5.5.1' => false, + '5.5.2' => true, + ), + + 'mysqli.rollback_on_cached_plink' => array( + '5.5' => false, + '5.6' => true, + ), + + 'assert.exception' => array( + '5.6' => false, + '7.0' => true, + ), + 'pcre.jit' => array( + '5.6' => false, + '7.0' => true, + ), + 'session.lazy_write' => array( + '5.6' => false, + '7.0' => true, + ), + 'zend.assertions' => array( + '5.6' => false, + '7.0' => true, + ), + 'opcache.file_cache' => array( + '5.6' => false, + '7.0' => true, + ), + 'opcache.file_cache_only' => array( + '5.6' => false, + '7.0' => true, + ), + 'opcache.file_cache_consistency_checks' => array( + '5.6' => false, + '7.0' => true, + ), + 'opcache.file_cache_fallback' => array( + '5.6' => false, + '7.0' => true, + ), // Windows only. + + 'opcache.validate_permission' => array( + '7.0.13' => false, + '7.0.14' => true, + ), + 'opcache.validate_root' => array( + '7.0.13' => false, + '7.0.14' => true, + ), + + 'hard_timeout' => array( + '7.0' => false, + '7.1' => true, + ), + 'session.sid_length' => array( + '7.0' => false, + '7.1' => true, + ), + 'session.sid_bits_per_character' => array( + '7.0' => false, + '7.1' => true, + ), + 'session.trans_sid_hosts' => array( + '7.0' => false, + '7.1' => true, + ), + 'session.trans_sid_tags' => array( + '7.0' => false, + '7.1' => true, + ), + 'url_rewriter.hosts' => array( + '7.0' => false, + '7.1' => true, + ), + + // Introduced in PHP 7.1.25, 7.2.13, 7.3.0. + 'imap.enable_insecure_rsh' => array( + '7.1.24' => false, + '7.1.25' => true, + ), + + 'syslog.facility' => array( + '7.2' => false, + '7.3' => true, + ), + 'syslog.filter' => array( + '7.2' => false, + '7.3' => true, + ), + 'syslog.ident' => array( + '7.2' => false, + '7.3' => true, + ), + 'session.cookie_samesite' => array( + '7.2' => false, + '7.3' => true, + ), + + 'ffi.enable' => array( + '7.3' => false, + '7.4' => true, + ), + 'ffi.preload' => array( + '7.3' => false, + '7.4' => true, + ), + 'opcache.cache_id' => array( + '7.3' => false, + '7.4' => true, + ), + 'opcache.preload' => array( + '7.3' => false, + '7.4' => true, + ), + 'zend.exception_ignore_args' => array( + '7.3' => false, + '7.4' => true, + ), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CONST => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + $functionLc = strtolower($tokens[$stackPtr]['content']); + if (isset($this->iniFunctions[$functionLc]) === false) { + return; + } + + $iniToken = $this->getFunctionCallParameter($phpcsFile, $stackPtr, $this->iniFunctions[$functionLc]); + if ($iniToken === false) { + return; + } + + $filteredToken = $this->stripQuotes($iniToken['raw']); + if (isset($this->newIniDirectives[$filteredToken]) === false) { + return; + } + + $itemInfo = array( + 'name' => $filteredToken, + 'functionLc' => $functionLc, + ); + $this->handleFeature($phpcsFile, $iniToken['end'], $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newIniDirectives[$itemInfo['name']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('alternative'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['alternative'] = ''; + + if (isset($itemArray['alternative']) === true) { + $errorInfo['alternative'] = $itemArray['alternative']; + } + + // Lower error level to warning if the function used was ini_get. + if ($errorInfo['error'] === true && $itemInfo['functionLc'] === 'ini_get') { + $errorInfo['error'] = false; + } + + return $errorInfo; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return "INI directive '%s' is not present in PHP version %s or earlier"; + } + + + /** + * Allow for concrete child classes to filter the error message before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param string $error The error message which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return string + */ + protected function filterErrorMsg($error, array $itemInfo, array $errorInfo) + { + if ($errorInfo['alternative'] !== '') { + $error .= ". This directive was previously called '%s'."; + } + + return $error; + } + + + /** + * Allow for concrete child classes to filter the error data before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + if ($errorInfo['alternative'] !== '') { + $data[] = $errorInfo['alternative']; + } + + return $data; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/IniDirectives/RemovedIniDirectivesSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/IniDirectives/RemovedIniDirectivesSniff.php new file mode 100644 index 00000000..a6928ae0 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/IniDirectives/RemovedIniDirectivesSniff.php @@ -0,0 +1,424 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\IniDirectives; + +use PHPCompatibility\AbstractRemovedFeatureSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect the use of deprecated and removed INI directives through `ini_set()` or `ini_get()`. + * + * PHP version All + * + * @link https://www.php.net/manual/en/ini.list.php + * @link https://www.php.net/manual/en/ini.core.php + * + * @since 5.5 + * @since 7.0.0 This sniff now throws a warning (deprecated) or an error (removed) depending + * on the `testVersion` set. Previously it would always throw a warning. + * @since 7.0.1 The sniff will now only throw warnings for `ini_get()`. + * @since 7.1.0 Now extends the `AbstractRemovedFeatureSniff` instead of the base `Sniff` class. + * @since 9.0.0 Renamed from `DeprecatedIniDirectivesSniff` to `RemovedIniDirectivesSniff`. + */ +class RemovedIniDirectivesSniff extends AbstractRemovedFeatureSniff +{ + /** + * A list of deprecated/removed INI directives. + * + * The array lists : version number with false (deprecated) and true (removed). + * If's sufficient to list the first version where the ini directive was deprecated/removed. + * + * @since 5.5 + * @since 7.0.3 Support for 'alternative' has been added. + * + * @var array(string) + */ + protected $deprecatedIniDirectives = array( + 'fbsql.batchSize' => array( + '5.1' => true, + 'alternative' => 'fbsql.batchsize', + ), + 'pfpro.defaulthost' => array( + '5.1' => true, + ), + 'pfpro.defaultport' => array( + '5.1' => true, + ), + 'pfpro.defaulttimeout' => array( + '5.1' => true, + ), + 'pfpro.proxyaddress' => array( + '5.1' => true, + ), + 'pfpro.proxyport' => array( + '5.1' => true, + ), + 'pfpro.proxylogon' => array( + '5.1' => true, + ), + 'pfpro.proxypassword' => array( + '5.1' => true, + ), + + 'ifx.allow_persistent' => array( + '5.2.1' => true, + ), + 'ifx.blobinfile' => array( + '5.2.1' => true, + ), + 'ifx.byteasvarchar' => array( + '5.2.1' => true, + ), + 'ifx.charasvarchar' => array( + '5.2.1' => true, + ), + 'ifx.default_host' => array( + '5.2.1' => true, + ), + 'ifx.default_password' => array( + '5.2.1' => true, + ), + 'ifx.default_user' => array( + '5.2.1' => true, + ), + 'ifx.max_links' => array( + '5.2.1' => true, + ), + 'ifx.max_persistent' => array( + '5.2.1' => true, + ), + 'ifx.nullformat' => array( + '5.2.1' => true, + ), + 'ifx.textasvarchar' => array( + '5.2.1' => true, + ), + + 'zend.ze1_compatibility_mode' => array( + '5.3' => true, + ), + + 'allow_call_time_pass_reference' => array( + '5.3' => false, + '5.4' => true, + ), + 'define_syslog_variables' => array( + '5.3' => false, + '5.4' => true, + ), + 'detect_unicode' => array( + '5.4' => true, + 'alternative' => 'zend.detect_unicode', + ), + 'highlight.bg' => array( + '5.3' => false, + '5.4' => true, + ), + 'magic_quotes_gpc' => array( + '5.3' => false, + '5.4' => true, + ), + 'magic_quotes_runtime' => array( + '5.3' => false, + '5.4' => true, + ), + 'magic_quotes_sybase' => array( + '5.3' => false, + '5.4' => true, + ), + 'mbstring.script_encoding' => array( + '5.4' => true, + 'alternative' => 'zend.script_encoding', + ), + 'register_globals' => array( + '5.3' => false, + '5.4' => true, + ), + 'register_long_arrays' => array( + '5.3' => false, + '5.4' => true, + ), + 'safe_mode' => array( + '5.3' => false, + '5.4' => true, + ), + 'safe_mode_allowed_env_vars' => array( + '5.3' => false, + '5.4' => true, + ), + 'safe_mode_exec_dir' => array( + '5.3' => false, + '5.4' => true, + ), + 'safe_mode_gid' => array( + '5.3' => false, + '5.4' => true, + ), + 'safe_mode_include_dir' => array( + '5.3' => false, + '5.4' => true, + ), + 'safe_mode_protected_env_vars' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.bug_compat_42' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.bug_compat_warn' => array( + '5.3' => false, + '5.4' => true, + ), + 'y2k_compliance' => array( + '5.3' => false, + '5.4' => true, + ), + + 'always_populate_raw_post_data' => array( + '5.6' => false, + '7.0' => true, + ), + 'iconv.input_encoding' => array( + '5.6' => false, + ), + 'iconv.output_encoding' => array( + '5.6' => false, + ), + 'iconv.internal_encoding' => array( + '5.6' => false, + ), + 'mbstring.http_input' => array( + '5.6' => false, + ), + 'mbstring.http_output' => array( + '5.6' => false, + ), + 'mbstring.internal_encoding' => array( + '5.6' => false, + ), + + 'asp_tags' => array( + '7.0' => true, + ), + 'xsl.security_prefs' => array( + '7.0' => true, + ), + 'opcache.load_comments' => array( + '7.0' => true, + ), + + 'mcrypt.algorithms_dir' => array( + '7.1' => false, + '7.2' => true, + ), + 'mcrypt.modes_dir' => array( + '7.1' => false, + '7.2' => true, + ), + 'session.entropy_file' => array( + '7.1' => true, + ), + 'session.entropy_length' => array( + '7.1' => true, + ), + 'session.hash_function' => array( + '7.1' => true, + ), + 'session.hash_bits_per_character' => array( + '7.1' => true, + ), + + 'mbstring.func_overload' => array( + '7.2' => false, + ), + 'sql.safe_mode' => array( + '7.2' => true, + ), + 'track_errors' => array( + '7.2' => false, + ), + 'opcache.fast_shutdown' => array( + '7.2' => true, + ), + + 'birdstep.max_links' => array( + '7.3' => true, + ), + 'opcache.inherited_hack' => array( + '5.3' => false, // Soft deprecated, i.e. ignored. + '7.3' => true, + ), + 'pdo_odbc.db2_instance_name' => array( + '7.3' => false, // Has been marked as deprecated in the manual from before this time. Now hard-deprecated. + ), + + 'allow_url_include' => array( + '7.4' => false, + ), + 'ibase.allow_persistent' => array( + '7.4' => true, + ), + 'ibase.max_persistent' => array( + '7.4' => true, + ), + 'ibase.max_links' => array( + '7.4' => true, + ), + 'ibase.default_db' => array( + '7.4' => true, + ), + 'ibase.default_user' => array( + '7.4' => true, + ), + 'ibase.default_password' => array( + '7.4' => true, + ), + 'ibase.default_charset' => array( + '7.4' => true, + ), + 'ibase.timestampformat' => array( + '7.4' => true, + ), + 'ibase.dateformat' => array( + '7.4' => true, + ), + 'ibase.timeformat' => array( + '7.4' => true, + ), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CONST => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + $functionLc = strtolower($tokens[$stackPtr]['content']); + if (isset($this->iniFunctions[$functionLc]) === false) { + return; + } + + $iniToken = $this->getFunctionCallParameter($phpcsFile, $stackPtr, $this->iniFunctions[$functionLc]); + if ($iniToken === false) { + return; + } + + $filteredToken = $this->stripQuotes($iniToken['raw']); + if (isset($this->deprecatedIniDirectives[$filteredToken]) === false) { + return; + } + + $itemInfo = array( + 'name' => $filteredToken, + 'functionLc' => $functionLc, + ); + $this->handleFeature($phpcsFile, $iniToken['end'], $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->deprecatedIniDirectives[$itemInfo['name']]; + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + + // Lower error level to warning if the function used was ini_get. + if ($errorInfo['error'] === true && $itemInfo['functionLc'] === 'ini_get') { + $errorInfo['error'] = false; + } + + return $errorInfo; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return "INI directive '%s' is "; + } + + + /** + * Get the error message template for suggesting an alternative for a specific sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getAlternativeOptionTemplate() + { + return str_replace('%s', "'%s'", parent::getAlternativeOptionTemplate()); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantArraysUsingConstSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantArraysUsingConstSniff.php new file mode 100644 index 00000000..c9c2225f --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantArraysUsingConstSniff.php @@ -0,0 +1,82 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\InitialValue; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect declaration of constants using the `const` keyword with a (constant) array value + * as supported since PHP 5.6. + * + * PHP version 5.6 + * + * @link https://wiki.php.net/rfc/const_scalar_exprs + * @link https://www.php.net/manual/en/language.constants.syntax.php + * + * @since 7.1.4 + * @since 9.0.0 Renamed from `ConstantArraysUsingConstSniff` to `NewConstantArraysUsingConstSniff`. + */ +class NewConstantArraysUsingConstSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.1.4 + * + * @return array + */ + public function register() + { + return array(\T_CONST); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.5') !== true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $find = array( + \T_ARRAY => \T_ARRAY, + \T_OPEN_SHORT_ARRAY => \T_OPEN_SHORT_ARRAY, + ); + + while (($hasArray = $phpcsFile->findNext($find, ($stackPtr + 1), null, false, null, true)) !== false) { + $phpcsFile->addError( + 'Constant arrays using the "const" keyword are not allowed in PHP 5.5 or earlier', + $hasArray, + 'Found' + ); + + // Skip past the content of the array. + $stackPtr = $hasArray; + if ($tokens[$hasArray]['code'] === \T_OPEN_SHORT_ARRAY && isset($tokens[$hasArray]['bracket_closer'])) { + $stackPtr = $tokens[$hasArray]['bracket_closer']; + } elseif ($tokens[$hasArray]['code'] === \T_ARRAY && isset($tokens[$hasArray]['parenthesis_closer'])) { + $stackPtr = $tokens[$hasArray]['parenthesis_closer']; + } + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantArraysUsingDefineSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantArraysUsingDefineSniff.php new file mode 100644 index 00000000..7b996728 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantArraysUsingDefineSniff.php @@ -0,0 +1,101 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\InitialValue; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect declaration of constants using `define()` with a (constant) array value + * as supported since PHP 7.0. + * + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/migration70.new-features.php#migration70.new-features.define-array + * @link https://www.php.net/manual/en/language.constants.syntax.php + * + * @since 7.0.0 + * @since 9.0.0 Renamed from `ConstantArraysUsingDefineSniff` to `NewConstantArraysUsingDefineSniff`. + */ +class NewConstantArraysUsingDefineSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.6') !== true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CONST => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + $functionLc = strtolower($tokens[$stackPtr]['content']); + if ($functionLc !== 'define') { + return; + } + + $secondParam = $this->getFunctionCallParameter($phpcsFile, $stackPtr, 2); + if (isset($secondParam['start'], $secondParam['end']) === false) { + return; + } + + $targetNestingLevel = 0; + if (isset($tokens[$secondParam['start']]['nested_parenthesis'])) { + $targetNestingLevel = \count($tokens[$secondParam['start']]['nested_parenthesis']); + } + + $array = $phpcsFile->findNext(array(\T_ARRAY, \T_OPEN_SHORT_ARRAY), $secondParam['start'], ($secondParam['end'] + 1)); + if ($array !== false) { + if ((isset($tokens[$array]['nested_parenthesis']) === false && $targetNestingLevel === 0) || \count($tokens[$array]['nested_parenthesis']) === $targetNestingLevel) { + $phpcsFile->addError( + 'Constant arrays using define are not allowed in PHP 5.6 or earlier', + $array, + 'Found' + ); + } + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantScalarExpressionsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantScalarExpressionsSniff.php new file mode 100644 index 00000000..8e1cddca --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantScalarExpressionsSniff.php @@ -0,0 +1,556 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\InitialValue; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect constant scalar expressions being used to set an initial value. + * + * Since PHP 5.6, it is now possible to provide a scalar expression involving + * numeric and string literals and/or constants in contexts where PHP previously + * expected a static value, such as constant and property declarations and + * default values for function parameters. + * + * PHP version 5.6 + * + * @link https://www.php.net/manual/en/migration56.new-features.php#migration56.new-features.const-scalar-exprs + * @link https://wiki.php.net/rfc/const_scalar_exprs + * + * @since 8.2.0 + */ +class NewConstantScalarExpressionsSniff extends Sniff +{ + + /** + * Error message. + * + * @since 8.2.0 + * + * @var string + */ + const ERROR_PHRASE = 'Constant scalar expressions are not allowed %s in PHP 5.5 or earlier.'; + + /** + * Partial error phrases to be used in combination with the error message constant. + * + * @since 8.2.0 + * + * @var array + */ + protected $errorPhrases = array( + 'const' => 'when defining constants using the const keyword', + 'property' => 'in property declarations', + 'staticvar' => 'in static variable declarations', + 'default' => 'in default function arguments', + ); + + /** + * Tokens which were allowed to be used in these declarations prior to PHP 5.6. + * + * This list will be enriched in the setProperties() method. + * + * @since 8.2.0 + * + * @var array + */ + protected $safeOperands = array( + \T_LNUMBER => \T_LNUMBER, + \T_DNUMBER => \T_DNUMBER, + \T_CONSTANT_ENCAPSED_STRING => \T_CONSTANT_ENCAPSED_STRING, + \T_TRUE => \T_TRUE, + \T_FALSE => \T_FALSE, + \T_NULL => \T_NULL, + + \T_LINE => \T_LINE, + \T_FILE => \T_FILE, + \T_DIR => \T_DIR, + \T_FUNC_C => \T_FUNC_C, + \T_CLASS_C => \T_CLASS_C, + \T_TRAIT_C => \T_TRAIT_C, + \T_METHOD_C => \T_METHOD_C, + \T_NS_C => \T_NS_C, + + // Special cases: + \T_NS_SEPARATOR => \T_NS_SEPARATOR, + /* + * This can be neigh anything, but for any usage except constants, + * the T_STRING will be combined with non-allowed tokens, so we should be good. + */ + \T_STRING => \T_STRING, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.2.0 + * + * @return array + */ + public function register() + { + // Set the properties up only once. + $this->setProperties(); + + return array( + \T_CONST, + \T_VARIABLE, + \T_FUNCTION, + \T_CLOSURE, + \T_STATIC, + ); + } + + + /** + * Make some adjustments to the $safeOperands property. + * + * @since 8.2.0 + * + * @return void + */ + public function setProperties() + { + $this->safeOperands += Tokens::$heredocTokens; + $this->safeOperands += Tokens::$emptyTokens; + } + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 8.2.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('5.5') !== true); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void|int Null or integer stack pointer to skip forward. + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->bowOutEarly() === true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$stackPtr]['type']) { + case 'T_FUNCTION': + case 'T_CLOSURE': + $params = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($params)) { + // No parameters. + return; + } + + $funcToken = $tokens[$stackPtr]; + + if (isset($funcToken['parenthesis_owner'], $funcToken['parenthesis_opener'], $funcToken['parenthesis_closer']) === false + || $funcToken['parenthesis_owner'] !== $stackPtr + || isset($tokens[$funcToken['parenthesis_opener']], $tokens[$funcToken['parenthesis_closer']]) === false + ) { + // Hmm.. something is going wrong as these should all be available & valid. + return; + } + + $opener = $funcToken['parenthesis_opener']; + $closer = $funcToken['parenthesis_closer']; + + // Which nesting level is the one we are interested in ? + $nestedParenthesisCount = 1; + if (isset($tokens[$opener]['nested_parenthesis'])) { + $nestedParenthesisCount += \count($tokens[$opener]['nested_parenthesis']); + } + + foreach ($params as $param) { + if (isset($param['default']) === false) { + continue; + } + + $end = $param['token']; + while (($end = $phpcsFile->findNext(array(\T_COMMA, \T_CLOSE_PARENTHESIS), ($end + 1), ($closer + 1))) !== false) { + $maybeSkipTo = $this->isRealEndOfDeclaration($tokens, $end, $nestedParenthesisCount); + if ($maybeSkipTo !== true) { + $end = $maybeSkipTo; + continue; + } + + // Ignore closing parenthesis/bracket if not 'ours'. + if ($tokens[$end]['code'] === \T_CLOSE_PARENTHESIS && $end !== $closer) { + continue; + } + + // Ok, we've found the end of the param default value declaration. + break; + } + + if ($this->isValidAssignment($phpcsFile, $param['token'], $end) === false) { + $this->throwError($phpcsFile, $param['token'], 'default', $param['content']); + } + } + + /* + * No need for the sniff to be triggered by the T_VARIABLEs in the function + * definition as we've already examined them above, so let's skip over them. + */ + return $closer; + + case 'T_VARIABLE': + case 'T_STATIC': + case 'T_CONST': + $type = 'const'; + + // Filter out non-property declarations. + if ($tokens[$stackPtr]['code'] === \T_VARIABLE) { + if ($this->isClassProperty($phpcsFile, $stackPtr) === false) { + return; + } + + $type = 'property'; + + // Move back one token to have the same starting point as the others. + $stackPtr = ($stackPtr - 1); + } + + // Filter out late static binding and class properties. + if ($tokens[$stackPtr]['code'] === \T_STATIC) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); + if ($next === false || $tokens[$next]['code'] !== \T_VARIABLE) { + // Late static binding. + return; + } + + if ($this->isClassProperty($phpcsFile, $next) === true) { + // Class properties are examined based on the T_VARIABLE token. + return; + } + unset($next); + + $type = 'staticvar'; + } + + $endOfStatement = $phpcsFile->findNext(array(\T_SEMICOLON, \T_CLOSE_TAG), ($stackPtr + 1)); + if ($endOfStatement === false) { + // No semi-colon - live coding. + return; + } + + $targetNestingLevel = 0; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $targetNestingLevel = \count($tokens[$stackPtr]['nested_parenthesis']); + } + + // Examine each variable/constant in multi-declarations. + $start = $stackPtr; + $end = $stackPtr; + while (($end = $phpcsFile->findNext(array(\T_COMMA, \T_SEMICOLON, \T_OPEN_SHORT_ARRAY, \T_CLOSE_TAG), ($end + 1), ($endOfStatement + 1))) !== false) { + + $maybeSkipTo = $this->isRealEndOfDeclaration($tokens, $end, $targetNestingLevel); + if ($maybeSkipTo !== true) { + $end = $maybeSkipTo; + continue; + } + + $start = $phpcsFile->findNext(Tokens::$emptyTokens, ($start + 1), $end, true); + if ($start === false + || ($tokens[$stackPtr]['code'] === \T_CONST && $tokens[$start]['code'] !== \T_STRING) + || ($tokens[$stackPtr]['code'] !== \T_CONST && $tokens[$start]['code'] !== \T_VARIABLE) + ) { + // Shouldn't be possible. + continue; + } + + if ($this->isValidAssignment($phpcsFile, $start, $end) === false) { + // Create the "found" snippet. + $content = ''; + $tokenCount = ($end - $start); + if ($tokenCount < 20) { + // Prevent large arrays from being added to the error message. + $content = $phpcsFile->getTokensAsString($start, ($tokenCount + 1)); + } + + $this->throwError($phpcsFile, $start, $type, $content); + } + + $start = $end; + } + + // Skip to the end of the statement to prevent duplicate messages for multi-declarations. + return $endOfStatement; + } + } + + + /** + * Is a value declared and is the value declared valid pre-PHP 5.6 ? + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param int $end The end of the value definition. + * This will normally be a comma or semi-colon. + * + * @return bool + */ + protected function isValidAssignment(File $phpcsFile, $stackPtr, $end) + { + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), $end, true); + if ($next === false || $tokens[$next]['code'] !== \T_EQUAL) { + // No value assigned. + return true; + } + + return $this->isStaticValue($phpcsFile, $tokens, ($next + 1), ($end - 1)); + } + + + /** + * Is a value declared and is the value declared constant as accepted in PHP 5.5 and lower ? + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param array $tokens The token stack of the current file. + * @param int $start The stackPtr from which to start examining. + * @param int $end The end of the value definition (inclusive), + * i.e. this token will be examined as part of + * the snippet. + * @param int $nestedArrays Optional. Array nesting level when examining + * the content of an array. + * + * @return bool + */ + protected function isStaticValue(File $phpcsFile, $tokens, $start, $end, $nestedArrays = 0) + { + $nextNonSimple = $phpcsFile->findNext($this->safeOperands, $start, ($end + 1), true); + if ($nextNonSimple === false) { + return true; + } + + /* + * OK, so we have at least one token which needs extra examination. + */ + switch ($tokens[$nextNonSimple]['code']) { + case \T_MINUS: + case \T_PLUS: + if ($this->isNumber($phpcsFile, $start, $end, true) !== false) { + // Int or float with sign. + return true; + } + + return false; + + case \T_NAMESPACE: + case \T_PARENT: + case \T_SELF: + case \T_DOUBLE_COLON: + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonSimple + 1), ($end + 1), true); + + if ($tokens[$nextNonSimple]['code'] === \T_NAMESPACE) { + // Allow only `namespace\...`. + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_NS_SEPARATOR) { + return false; + } + } elseif ($tokens[$nextNonSimple]['code'] === \T_PARENT + || $tokens[$nextNonSimple]['code'] === \T_SELF + ) { + // Allow only `parent::` and `self::`. + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_DOUBLE_COLON) { + return false; + } + } elseif ($tokens[$nextNonSimple]['code'] === \T_DOUBLE_COLON) { + // Allow only `T_STRING::T_STRING`. + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_STRING) { + return false; + } + + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($nextNonSimple - 1), null, true); + // No need to worry about parent/self, that's handled above and + // the double colon is skipped over in that case. + if ($prevNonEmpty === false || $tokens[$prevNonEmpty]['code'] !== \T_STRING) { + return false; + } + } + + // Examine what comes after the namespace/parent/self/double colon, if anything. + return $this->isStaticValue($phpcsFile, $tokens, ($nextNonEmpty + 1), $end, $nestedArrays); + + case \T_ARRAY: + case \T_OPEN_SHORT_ARRAY: + ++$nestedArrays; + + $arrayItems = $this->getFunctionCallParameters($phpcsFile, $nextNonSimple); + if (empty($arrayItems) === false) { + foreach ($arrayItems as $item) { + // Check for a double arrow, but only if it's for this array item, not for a nested array. + $doubleArrow = false; + + $maybeDoubleArrow = $phpcsFile->findNext( + array(\T_DOUBLE_ARROW, \T_ARRAY, \T_OPEN_SHORT_ARRAY), + $item['start'], + ($item['end'] + 1) + ); + if ($maybeDoubleArrow !== false && $tokens[$maybeDoubleArrow]['code'] === \T_DOUBLE_ARROW) { + // Double arrow is for this nesting level. + $doubleArrow = $maybeDoubleArrow; + } + + if ($doubleArrow === false) { + if ($this->isStaticValue($phpcsFile, $tokens, $item['start'], $item['end'], $nestedArrays) === false) { + return false; + } + + } else { + // Examine array key. + if ($this->isStaticValue($phpcsFile, $tokens, $item['start'], ($doubleArrow - 1), $nestedArrays) === false) { + return false; + } + + // Examine array value. + if ($this->isStaticValue($phpcsFile, $tokens, ($doubleArrow + 1), $item['end'], $nestedArrays) === false) { + return false; + } + } + } + } + + --$nestedArrays; + + /* + * Find the end of the array. + * We already know we will have a valid closer as otherwise we wouldn't have been + * able to get the array items. + */ + $closer = ($nextNonSimple + 1); + if ($tokens[$nextNonSimple]['code'] === \T_OPEN_SHORT_ARRAY + && isset($tokens[$nextNonSimple]['bracket_closer']) === true + ) { + $closer = $tokens[$nextNonSimple]['bracket_closer']; + } else { + $maybeOpener = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonSimple + 1), ($end + 1), true); + if ($tokens[$maybeOpener]['code'] === \T_OPEN_PARENTHESIS) { + $opener = $maybeOpener; + if (isset($tokens[$opener]['parenthesis_closer']) === true) { + $closer = $tokens[$opener]['parenthesis_closer']; + } + } + } + + if ($closer === $end) { + return true; + } + + // Examine what comes after the array, if anything. + return $this->isStaticValue($phpcsFile, $tokens, ($closer + 1), $end, $nestedArrays); + + } + + // Ok, so this unsafe token was not one of the exceptions, i.e. this is a PHP 5.6+ syntax. + return false; + } + + + /** + * Throw an error if a scalar expression is found. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the token to link the error to. + * @param string $type Type of usage found. + * @param string $content Optional. The value for the declaration as found. + * + * @return void + */ + protected function throwError(File $phpcsFile, $stackPtr, $type, $content = '') + { + $error = static::ERROR_PHRASE; + $phrase = ''; + $errorCode = 'Found'; + + if (isset($this->errorPhrases[$type]) === true) { + $errorCode = $this->stringToErrorCode($type) . 'Found'; + $phrase = $this->errorPhrases[$type]; + } + + $data = array($phrase); + + if (empty($content) === false) { + $error .= ' Found: %s'; + $data[] = $content; + } + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } + + + /** + * Helper function to find the end of multi variable/constant declarations. + * + * Checks whether a certain part of a declaration needs to be skipped over or + * if it is the real end of the declaration. + * + * @since 8.2.0 + * + * @param array $tokens Token stack of the current file. + * @param int $endPtr The token to examine as a candidate end pointer. + * @param int $targetLevel Target nesting level. + * + * @return bool|int True if this is the real end. Int stackPtr to skip to if not. + */ + private function isRealEndOfDeclaration($tokens, $endPtr, $targetLevel) + { + // Ignore anything within short array definition brackets for now. + if ($tokens[$endPtr]['code'] === \T_OPEN_SHORT_ARRAY + && (isset($tokens[$endPtr]['bracket_opener']) + && $tokens[$endPtr]['bracket_opener'] === $endPtr) + && isset($tokens[$endPtr]['bracket_closer']) + ) { + // Skip forward to the end of the short array definition. + return $tokens[$endPtr]['bracket_closer']; + } + + // Skip past comma's at a lower nesting level. + if ($tokens[$endPtr]['code'] === \T_COMMA) { + // Check if a comma is at the nesting level we're targetting. + $nestingLevel = 0; + if (isset($tokens[$endPtr]['nested_parenthesis']) === true) { + $nestingLevel = \count($tokens[$endPtr]['nested_parenthesis']); + } + if ($nestingLevel > $targetLevel) { + return $endPtr; + } + } + + return true; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewHeredocSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewHeredocSniff.php new file mode 100644 index 00000000..406237a5 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewHeredocSniff.php @@ -0,0 +1,100 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\InitialValue; + +use PHPCompatibility\Sniffs\InitialValue\NewConstantScalarExpressionsSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect a heredoc being used to set an initial value. + * + * As of PHP 5.3.0, it's possible to initialize static variables, class properties + * and constants declared using the `const` keyword, using the Heredoc syntax. + * And while not documented, heredoc initialization can now also be used for function param defaults. + * See: https://3v4l.org/JVH8W + * + * These heredocs (still) cannot contain variables. That's, however, outside the scope of the + * PHPCompatibility library until such time as there is a PHP version in which this would be accepted. + * + * PHP version 5.3 + * + * @link https://www.php.net/manual/en/migration53.new-features.php + * @link https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc + * + * @since 7.1.4 + * @since 8.2.0 Now extends the NewConstantScalarExpressionsSniff instead of the base Sniff class. + * @since 9.0.0 Renamed from `NewHeredocInitializeSniff` to `NewHeredocSniff`. + */ +class NewHeredocSniff extends NewConstantScalarExpressionsSniff +{ + + /** + * Error message. + * + * @since 8.2.0 + * + * @var string + */ + const ERROR_PHRASE = 'Initializing %s using the Heredoc syntax was not supported in PHP 5.2 or earlier'; + + /** + * Partial error phrases to be used in combination with the error message constant. + * + * @since 8.2.0 + * + * @var array + */ + protected $errorPhrases = array( + 'const' => 'constants', + 'property' => 'class properties', + 'staticvar' => 'static variables', + 'default' => 'default parameter values', + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 8.2.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('5.2') !== true); + } + + + /** + * Is a value declared and does the declared value not contain an heredoc ? + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param int $end The end of the value definition. + * + * @return bool True if no heredoc (or assignment) is found, false otherwise. + */ + protected function isValidAssignment(File $phpcsFile, $stackPtr, $end) + { + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), $end, true); + if ($next === false || $tokens[$next]['code'] !== \T_EQUAL) { + // No value assigned. + return true; + } + + return ($phpcsFile->findNext(\T_START_HEREDOC, ($next + 1), $end, false, null, true) === false); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Interfaces/InternalInterfacesSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Interfaces/InternalInterfacesSniff.php new file mode 100644 index 00000000..e154a603 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Interfaces/InternalInterfacesSniff.php @@ -0,0 +1,103 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Interfaces; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; + +/** + * Detect classes which implement PHP native interfaces intended only for PHP internal use. + * + * PHP version 5.0+ + * + * @link https://www.php.net/manual/en/class.traversable.php + * @link https://www.php.net/manual/en/class.throwable.php + * @link https://www.php.net/manual/en/class.datetimeinterface.php + * + * @since 7.0.3 + */ +class InternalInterfacesSniff extends Sniff +{ + + /** + * A list of PHP internal interfaces, not intended to be implemented by userland classes. + * + * The array lists : the error message to use. + * + * @since 7.0.3 + * + * @var array(string => string) + */ + protected $internalInterfaces = array( + 'Traversable' => 'shouldn\'t be implemented directly, implement the Iterator or IteratorAggregate interface instead.', + 'DateTimeInterface' => 'is intended for type hints only and is not implementable.', + 'Throwable' => 'cannot be implemented directly, extend the Exception class instead.', + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.3 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of interface names. + $this->internalInterfaces = $this->arrayKeysToLowercase($this->internalInterfaces); + + $targets = array(\T_CLASS); + + if (\defined('T_ANON_CLASS')) { + $targets[] = \T_ANON_CLASS; + } + + return $targets; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $interfaces = PHPCSHelper::findImplementedInterfaceNames($phpcsFile, $stackPtr); + + if (\is_array($interfaces) === false || $interfaces === array()) { + return; + } + + foreach ($interfaces as $interface) { + $interface = ltrim($interface, '\\'); + $interfaceLc = strtolower($interface); + if (isset($this->internalInterfaces[$interfaceLc]) === true) { + $error = 'The interface %s %s'; + $errorCode = $this->stringToErrorCode($interfaceLc) . 'Found'; + $data = array( + $interface, + $this->internalInterfaces[$interfaceLc], + ); + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Interfaces/NewInterfacesSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Interfaces/NewInterfacesSniff.php new file mode 100644 index 00000000..35c5939b --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Interfaces/NewInterfacesSniff.php @@ -0,0 +1,362 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Interfaces; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; + +/** + * Detect use of new PHP native interfaces and unsupported interface methods. + * + * PHP version 5.0+ + * + * @since 7.0.3 + * @since 7.1.0 Now extends the `AbstractNewFeatureSniff` instead of the base `Sniff` class.. + * @since 7.1.4 Now also detects new interfaces when used as parameter type declarations. + * @since 8.2.0 Now also detects new interfaces when used as return type declarations. + */ +class NewInterfacesSniff extends AbstractNewFeatureSniff +{ + + /** + * A list of new interfaces, not present in older versions. + * + * The array lists : version number with false (not present) or true (present). + * If's sufficient to list the first version where the interface appears. + * + * @since 7.0.3 + * + * @var array(string => array(string => bool)) + */ + protected $newInterfaces = array( + 'Traversable' => array( + '4.4' => false, + '5.0' => true, + ), + 'Reflector' => array( + '4.4' => false, + '5.0' => true, + ), + + 'Countable' => array( + '5.0' => false, + '5.1' => true, + ), + 'OuterIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'RecursiveIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'SeekableIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'Serializable' => array( + '5.0' => false, + '5.1' => true, + ), + 'SplObserver' => array( + '5.0' => false, + '5.1' => true, + ), + 'SplSubject' => array( + '5.0' => false, + '5.1' => true, + ), + + 'JsonSerializable' => array( + '5.3' => false, + '5.4' => true, + ), + 'SessionHandlerInterface' => array( + '5.3' => false, + '5.4' => true, + ), + + 'DateTimeInterface' => array( + '5.4' => false, + '5.5' => true, + ), + + 'SessionIdInterface' => array( + '5.5.0' => false, + '5.5.1' => true, + ), + + 'Throwable' => array( + '5.6' => false, + '7.0' => true, + ), + 'SessionUpdateTimestampHandlerInterface' => array( + '5.6' => false, + '7.0' => true, + ), + ); + + /** + * A list of methods which cannot be used in combination with particular interfaces. + * + * @since 7.0.3 + * + * @var array(string => array(string => string)) + */ + protected $unsupportedMethods = array( + 'Serializable' => array( + '__sleep' => 'https://www.php.net/serializable', + '__wakeup' => 'https://www.php.net/serializable', + ), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.3 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of interface names. + $this->newInterfaces = $this->arrayKeysToLowercase($this->newInterfaces); + $this->unsupportedMethods = $this->arrayKeysToLowercase($this->unsupportedMethods); + + $targets = array( + \T_CLASS, + \T_FUNCTION, + \T_CLOSURE, + ); + + if (\defined('T_ANON_CLASS')) { + $targets[] = \T_ANON_CLASS; + } + + if (\defined('T_RETURN_TYPE')) { + $targets[] = \T_RETURN_TYPE; + } + + return $targets; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$stackPtr]['type']) { + case 'T_CLASS': + case 'T_ANON_CLASS': + $this->processClassToken($phpcsFile, $stackPtr); + break; + + case 'T_FUNCTION': + case 'T_CLOSURE': + $this->processFunctionToken($phpcsFile, $stackPtr); + + // Deal with older PHPCS versions which don't recognize return type hints + // as well as newer PHPCS versions (3.3.0+) where the tokenization has changed. + $returnTypeHint = $this->getReturnTypeHintToken($phpcsFile, $stackPtr); + if ($returnTypeHint !== false) { + $this->processReturnTypeToken($phpcsFile, $returnTypeHint); + } + break; + + case 'T_RETURN_TYPE': + $this->processReturnTypeToken($phpcsFile, $stackPtr); + break; + + default: + // Deliberately left empty. + break; + } + } + + + /** + * Processes this test for when a class token is encountered. + * + * - Detect classes implementing the new interfaces. + * - Detect classes implementing the new interfaces with unsupported functions. + * + * @since 7.1.4 Split off from the `process()` method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + private function processClassToken(File $phpcsFile, $stackPtr) + { + $interfaces = PHPCSHelper::findImplementedInterfaceNames($phpcsFile, $stackPtr); + + if (\is_array($interfaces) === false || $interfaces === array()) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $checkMethods = false; + + if (isset($tokens[$stackPtr]['scope_closer'])) { + $checkMethods = true; + $scopeCloser = $tokens[$stackPtr]['scope_closer']; + } + + foreach ($interfaces as $interface) { + $interface = ltrim($interface, '\\'); + $interfaceLc = strtolower($interface); + + if (isset($this->newInterfaces[$interfaceLc]) === true) { + $itemInfo = array( + 'name' => $interface, + 'nameLc' => $interfaceLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + if ($checkMethods === true && isset($this->unsupportedMethods[$interfaceLc]) === true) { + $nextFunc = $stackPtr; + while (($nextFunc = $phpcsFile->findNext(\T_FUNCTION, ($nextFunc + 1), $scopeCloser)) !== false) { + $funcName = $phpcsFile->getDeclarationName($nextFunc); + $funcNameLc = strtolower($funcName); + if ($funcNameLc === '') { + continue; + } + + if (isset($this->unsupportedMethods[$interfaceLc][$funcNameLc]) === true) { + $error = 'Classes that implement interface %s do not support the method %s(). See %s'; + $errorCode = $this->stringToErrorCode($interface) . 'UnsupportedMethod'; + $data = array( + $interface, + $funcName, + $this->unsupportedMethods[$interfaceLc][$funcNameLc], + ); + + $phpcsFile->addError($error, $nextFunc, $errorCode, $data); + } + } + } + } + } + + + /** + * Processes this test for when a function token is encountered. + * + * - Detect new interfaces when used as a type hint. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + private function processFunctionToken(File $phpcsFile, $stackPtr) + { + $typeHints = $this->getTypeHintsFromFunctionDeclaration($phpcsFile, $stackPtr); + if (empty($typeHints) || \is_array($typeHints) === false) { + return; + } + + foreach ($typeHints as $hint) { + + $typeHintLc = strtolower($hint); + + if (isset($this->newInterfaces[$typeHintLc]) === true) { + $itemInfo = array( + 'name' => $hint, + 'nameLc' => $typeHintLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + } + } + + + /** + * Processes this test for when a return type token is encountered. + * + * - Detect new interfaces when used as a return type declaration. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + private function processReturnTypeToken(File $phpcsFile, $stackPtr) + { + $returnTypeHint = $this->getReturnTypeHintName($phpcsFile, $stackPtr); + if (empty($returnTypeHint)) { + return; + } + + $returnTypeHint = ltrim($returnTypeHint, '\\'); + $returnTypeHintLc = strtolower($returnTypeHint); + + if (isset($this->newInterfaces[$returnTypeHintLc]) === false) { + return; + } + + // Still here ? Then this is a return type declaration using a new interface. + $itemInfo = array( + 'name' => $returnTypeHint, + 'nameLc' => $returnTypeHintLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newInterfaces[$itemInfo['nameLc']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The built-in interface ' . parent::getErrorMsgTemplate(); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/CaseSensitiveKeywordsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/CaseSensitiveKeywordsSniff.php new file mode 100644 index 00000000..64002b4d --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/CaseSensitiveKeywordsSniff.php @@ -0,0 +1,76 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Keywords; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect usage of `self`, `parent` and `static` and verify they are lowercase. + * + * Prior to PHP 5.5, cases existed where the `self`, `parent`, and `static` keywords + * were treated in a case sensitive fashion. + * + * PHP version 5.5 + * + * @link https://www.php.net/manual/en/migration55.incompatible.php#migration55.incompatible.self-parent-static + * + * @since 7.1.4 + */ +class CaseSensitiveKeywordsSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.1.4 + * + * @return array + */ + public function register() + { + return array( + \T_SELF, + \T_STATIC, + \T_PARENT, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $tokenContentLC = strtolower($tokens[$stackPtr]['content']); + + if ($tokenContentLC !== $tokens[$stackPtr]['content']) { + $phpcsFile->addError( + 'The keyword \'%s\' was treated in a case-sensitive fashion in certain cases in PHP 5.4 or earlier. Use the lowercase version for consistent support.', + $stackPtr, + 'NonLowercaseFound', + array($tokenContentLC) + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesAsDeclaredSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesAsDeclaredSniff.php new file mode 100644 index 00000000..7f4411bc --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesAsDeclaredSniff.php @@ -0,0 +1,259 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Keywords; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detects the use of some reserved keywords to name a class, interface, trait or namespace. + * + * Emits errors for reserved words and warnings for soft-reserved words. + * + * PHP version 7.0+ + * + * @link https://www.php.net/manual/en/reserved.other-reserved-words.php + * @link https://wiki.php.net/rfc/reserve_more_types_in_php_7 + * + * @since 7.0.8 + * @since 7.1.4 This sniff now throws a warning (soft reserved) or an error (reserved) depending + * on the `testVersion` set. Previously it would always throw an error. + */ +class ForbiddenNamesAsDeclaredSniff extends Sniff +{ + + /** + * List of tokens which can not be used as class, interface, trait names or as part of a namespace. + * + * @since 7.0.8 + * + * @var array + */ + protected $forbiddenTokens = array( + \T_NULL => '7.0', + \T_TRUE => '7.0', + \T_FALSE => '7.0', + ); + + /** + * T_STRING keywords to recognize as forbidden names. + * + * @since 7.0.8 + * + * @var array + */ + protected $forbiddenNames = array( + 'null' => '7.0', + 'true' => '7.0', + 'false' => '7.0', + 'bool' => '7.0', + 'int' => '7.0', + 'float' => '7.0', + 'string' => '7.0', + 'iterable' => '7.1', + 'void' => '7.1', + 'object' => '7.2', + ); + + /** + * T_STRING keywords to recognize as soft reserved names. + * + * Using any of these keywords to name a class, interface, trait or namespace + * is highly discouraged since they may be used in future versions of PHP. + * + * @since 7.0.8 + * + * @var array + */ + protected $softReservedNames = array( + 'resource' => '7.0', + 'object' => '7.0', + 'mixed' => '7.0', + 'numeric' => '7.0', + ); + + /** + * Combined list of the two lists above. + * + * Used for quick check whether or not something is a reserved + * word. + * Set from the `register()` method. + * + * @since 7.0.8 + * + * @var array + */ + private $allForbiddenNames = array(); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.8 + * + * @return array + */ + public function register() + { + // Do the list merge only once. + $this->allForbiddenNames = array_merge($this->forbiddenNames, $this->softReservedNames); + + $targets = array( + \T_CLASS, + \T_INTERFACE, + \T_TRAIT, + \T_NAMESPACE, + \T_STRING, // Compat for PHPCS < 2.4.0 and PHP < 5.3. + ); + + return $targets; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.8 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $tokenCode = $tokens[$stackPtr]['code']; + $tokenType = $tokens[$stackPtr]['type']; + $tokenContentLc = strtolower($tokens[$stackPtr]['content']); + + // For string tokens we only care about 'trait' as that is the only one + // which may not be correctly recognized as it's own token. + // This only happens in older versions of PHP where the token doesn't exist yet as a keyword. + if ($tokenCode === \T_STRING && $tokenContentLc !== 'trait') { + return; + } + + if (\in_array($tokenType, array('T_CLASS', 'T_INTERFACE', 'T_TRAIT'), true)) { + // Check for the declared name being a name which is not tokenized as T_STRING. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty !== false && isset($this->forbiddenTokens[$tokens[$nextNonEmpty]['code']]) === true) { + $name = $tokens[$nextNonEmpty]['content']; + } else { + // Get the declared name if it's a T_STRING. + $name = $phpcsFile->getDeclarationName($stackPtr); + } + unset($nextNonEmpty); + + if (isset($name) === false || \is_string($name) === false || $name === '') { + return; + } + + $nameLc = strtolower($name); + if (isset($this->allForbiddenNames[$nameLc]) === false) { + return; + } + + } elseif ($tokenCode === \T_NAMESPACE) { + $namespaceName = $this->getDeclaredNamespaceName($phpcsFile, $stackPtr); + + if ($namespaceName === false || $namespaceName === '') { + return; + } + + $namespaceParts = explode('\\', $namespaceName); + foreach ($namespaceParts as $namespacePart) { + $partLc = strtolower($namespacePart); + if (isset($this->allForbiddenNames[$partLc]) === true) { + $name = $namespacePart; + $nameLc = $partLc; + break; + } + } + } elseif ($tokenCode === \T_STRING) { + // Traits which are not yet tokenized as T_TRAIT. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + $nextNonEmptyCode = $tokens[$nextNonEmpty]['code']; + + if ($nextNonEmptyCode !== \T_STRING && isset($this->forbiddenTokens[$nextNonEmptyCode]) === true) { + $name = $tokens[$nextNonEmpty]['content']; + $nameLc = strtolower($tokens[$nextNonEmpty]['content']); + } elseif ($nextNonEmptyCode === \T_STRING) { + $endOfStatement = $phpcsFile->findNext(array(\T_SEMICOLON, \T_OPEN_CURLY_BRACKET), ($stackPtr + 1)); + if ($endOfStatement === false) { + return; + } + + do { + $nextNonEmptyLc = strtolower($tokens[$nextNonEmpty]['content']); + + if (isset($this->allForbiddenNames[$nextNonEmptyLc]) === true) { + $name = $tokens[$nextNonEmpty]['content']; + $nameLc = $nextNonEmptyLc; + break; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), $endOfStatement, true); + } while ($nextNonEmpty !== false); + } + unset($nextNonEmptyCode, $nextNonEmptyLc, $endOfStatement); + } + + if (isset($name, $nameLc) === false) { + return; + } + + // Still here, so this is one of the reserved words. + // Build up the error message. + $error = "'%s' is a"; + $isError = null; + $errorCode = $this->stringToErrorCode($nameLc) . 'Found'; + $data = array( + $nameLc, + ); + + if (isset($this->softReservedNames[$nameLc]) === true + && $this->supportsAbove($this->softReservedNames[$nameLc]) === true + ) { + $error .= ' soft reserved keyword as of PHP version %s'; + $isError = false; + $data[] = $this->softReservedNames[$nameLc]; + } + + if (isset($this->forbiddenNames[$nameLc]) === true + && $this->supportsAbove($this->forbiddenNames[$nameLc]) === true + ) { + if (isset($isError) === true) { + $error .= ' and a'; + } + $error .= ' reserved keyword as of PHP version %s'; + $isError = true; + $data[] = $this->forbiddenNames[$nameLc]; + } + + if (isset($isError) === true) { + $error .= ' and should not be used to name a class, interface or trait or as part of a namespace (%s)'; + $data[] = $tokens[$stackPtr]['type']; + + $this->addMessage($phpcsFile, $error, $stackPtr, $isError, $errorCode, $data); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesAsInvokedFunctionsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesAsInvokedFunctionsSniff.php new file mode 100644 index 00000000..c1c38281 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesAsInvokedFunctionsSniff.php @@ -0,0 +1,188 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Keywords; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Prohibits the use of reserved keywords invoked as functions. + * + * PHP version All + * + * @link https://www.php.net/manual/en/reserved.keywords.php + * + * @since 5.5 + */ +class ForbiddenNamesAsInvokedFunctionsSniff extends Sniff +{ + + /** + * List of tokens to register. + * + * @since 5.5 + * + * @var array + */ + protected $targetedTokens = array( + \T_ABSTRACT => '5.0', + \T_CALLABLE => '5.4', + \T_CATCH => '5.0', + \T_FINAL => '5.0', + \T_FINALLY => '5.5', + \T_GOTO => '5.3', + \T_IMPLEMENTS => '5.0', + \T_INTERFACE => '5.0', + \T_INSTANCEOF => '5.0', + \T_INSTEADOF => '5.4', + \T_NAMESPACE => '5.3', + \T_PRIVATE => '5.0', + \T_PROTECTED => '5.0', + \T_PUBLIC => '5.0', + \T_TRAIT => '5.4', + \T_TRY => '5.0', + + ); + + /** + * T_STRING keywords to recognize as targetted tokens. + * + * Compatibility for PHP versions where the keyword is not yet recognized + * as its own token and for PHPCS versions which change the token to + * T_STRING when used in a method call. + * + * @since 5.5 + * + * @var array + */ + protected $targetedStringTokens = array( + 'abstract' => '5.0', + 'callable' => '5.4', + 'catch' => '5.0', + 'final' => '5.0', + 'finally' => '5.5', + 'goto' => '5.3', + 'implements' => '5.0', + 'interface' => '5.0', + 'instanceof' => '5.0', + 'insteadof' => '5.4', + 'namespace' => '5.3', + 'private' => '5.0', + 'protected' => '5.0', + 'public' => '5.0', + 'trait' => '5.4', + 'try' => '5.0', + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + $tokens = array_keys($this->targetedTokens); + $tokens[] = \T_STRING; + + return $tokens; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenCode = $tokens[$stackPtr]['code']; + $tokenContentLc = strtolower($tokens[$stackPtr]['content']); + $isString = false; + + /* + * For string tokens we only care if the string is a reserved word used + * as a function. This only happens in older versions of PHP where the + * token doesn't exist yet for that keyword or in later versions when the + * token is used in a method invocation. + */ + if ($tokenCode === \T_STRING + && (isset($this->targetedStringTokens[$tokenContentLc]) === false) + ) { + return; + } + + if ($tokenCode === \T_STRING) { + $isString = true; + } + + // Make sure this is a function call. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next === false || $tokens[$next]['code'] !== \T_OPEN_PARENTHESIS) { + // Not a function call. + return; + } + + // This sniff isn't concerned about function declarations. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prev !== false && $tokens[$prev]['code'] === \T_FUNCTION) { + return; + } + + /* + * Deal with PHP 7 relaxing the rules. + * "As of PHP 7.0.0 these keywords are allowed as property, constant, and method names + * of classes, interfaces and traits...", i.e. they can be invoked as a method call. + * + * Only needed for those keywords which we sniff out via T_STRING. + */ + if (($tokens[$prev]['code'] === \T_OBJECT_OPERATOR || $tokens[$prev]['code'] === \T_DOUBLE_COLON) + && $this->supportsBelow('5.6') === false + ) { + return; + } + + // For the word catch, it is valid to have an open parenthesis + // after it, but only if it is preceded by a right curly brace. + if ($tokenCode === \T_CATCH) { + if ($prev !== false && $tokens[$prev]['code'] === \T_CLOSE_CURLY_BRACKET) { + // Ok, it's fine. + return; + } + } + + if ($isString === true) { + $version = $this->targetedStringTokens[$tokenContentLc]; + } else { + $version = $this->targetedTokens[$tokenCode]; + } + + if ($this->supportsAbove($version)) { + $error = "'%s' is a reserved keyword introduced in PHP version %s and cannot be invoked as a function (%s)"; + $errorCode = $this->stringToErrorCode($tokenContentLc) . 'Found'; + $data = array( + $tokenContentLc, + $version, + $tokens[$stackPtr]['type'], + ); + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesSniff.php new file mode 100644 index 00000000..6be1de4f --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesSniff.php @@ -0,0 +1,442 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Keywords; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detects the use of reserved keywords as class, function, namespace or constant names. + * + * PHP version All + * + * @link https://www.php.net/manual/en/reserved.keywords.php + * + * @since 5.5 + */ +class ForbiddenNamesSniff extends Sniff +{ + + /** + * A list of keywords that can not be used as function, class and namespace name or constant name. + * Mentions since which version it's not allowed. + * + * @since 5.5 + * + * @var array(string => string) + */ + protected $invalidNames = array( + 'abstract' => '5.0', + 'and' => 'all', + 'array' => 'all', + 'as' => 'all', + 'break' => 'all', + 'callable' => '5.4', + 'case' => 'all', + 'catch' => '5.0', + 'class' => 'all', + 'clone' => '5.0', + 'const' => 'all', + 'continue' => 'all', + 'declare' => 'all', + 'default' => 'all', + 'die' => 'all', + 'do' => 'all', + 'echo' => 'all', + 'else' => 'all', + 'elseif' => 'all', + 'empty' => 'all', + 'enddeclare' => 'all', + 'endfor' => 'all', + 'endforeach' => 'all', + 'endif' => 'all', + 'endswitch' => 'all', + 'endwhile' => 'all', + 'eval' => 'all', + 'exit' => 'all', + 'extends' => 'all', + 'final' => '5.0', + 'finally' => '5.5', + 'for' => 'all', + 'foreach' => 'all', + 'function' => 'all', + 'global' => 'all', + 'goto' => '5.3', + 'if' => 'all', + 'implements' => '5.0', + 'include' => 'all', + 'include_once' => 'all', + 'instanceof' => '5.0', + 'insteadof' => '5.4', + 'interface' => '5.0', + 'isset' => 'all', + 'list' => 'all', + 'namespace' => '5.3', + 'new' => 'all', + 'or' => 'all', + 'print' => 'all', + 'private' => '5.0', + 'protected' => '5.0', + 'public' => '5.0', + 'require' => 'all', + 'require_once' => 'all', + 'return' => 'all', + 'static' => 'all', + 'switch' => 'all', + 'throw' => '5.0', + 'trait' => '5.4', + 'try' => '5.0', + 'unset' => 'all', + 'use' => 'all', + 'var' => 'all', + 'while' => 'all', + 'xor' => 'all', + 'yield' => '5.5', + '__class__' => 'all', + '__dir__' => '5.3', + '__file__' => 'all', + '__function__' => 'all', + '__method__' => 'all', + '__namespace__' => '5.3', + ); + + /** + * A list of keywords that can follow use statements. + * + * @since 7.0.1 + * + * @var array(string => string) + */ + protected $validUseNames = array( + 'const' => true, + 'function' => true, + ); + + /** + * Scope modifiers and other keywords allowed in trait use statements. + * + * @since 7.1.4 + * + * @var array + */ + private $allowedModifiers = array(); + + /** + * Targeted tokens. + * + * @since 5.5 + * + * @var array + */ + protected $targetedTokens = array( + \T_CLASS, + \T_FUNCTION, + \T_NAMESPACE, + \T_STRING, + \T_CONST, + \T_USE, + \T_AS, + \T_EXTENDS, + \T_INTERFACE, + \T_TRAIT, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + $this->allowedModifiers = Tokens::$scopeModifiers; + $this->allowedModifiers[\T_FINAL] = \T_FINAL; + + $tokens = $this->targetedTokens; + + if (\defined('T_ANON_CLASS')) { + $tokens[] = \T_ANON_CLASS; + } + + return $tokens; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + /* + * We distinguish between the class, function and namespace names vs the define statements. + */ + if ($tokens[$stackPtr]['type'] === 'T_STRING') { + $this->processString($phpcsFile, $stackPtr, $tokens); + } else { + $this->processNonString($phpcsFile, $stackPtr, $tokens); + } + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processNonString(File $phpcsFile, $stackPtr, $tokens) + { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + /* + * Deal with anonymous classes - `class` before a reserved keyword is sometimes + * misidentified as `T_ANON_CLASS`. + * In PHPCS < 2.3.4 these were tokenized as T_CLASS no matter what. + */ + if ($tokens[$stackPtr]['type'] === 'T_ANON_CLASS' || $tokens[$stackPtr]['type'] === 'T_CLASS') { + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prevNonEmpty !== false && $tokens[$prevNonEmpty]['type'] === 'T_NEW') { + return; + } + } + + /* + * PHP 5.6 allows for use const and use function, but only if followed by the function/constant name. + * - `use function HelloWorld` => move to the next token (HelloWorld) to verify. + * - `use const HelloWorld` => move to the next token (HelloWorld) to verify. + */ + elseif ($tokens[$stackPtr]['type'] === 'T_USE' + && isset($this->validUseNames[strtolower($tokens[$nextNonEmpty]['content'])]) === true + ) { + $maybeUseNext = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), null, true, null, true); + if ($maybeUseNext !== false && $this->isEndOfUseStatement($tokens[$maybeUseNext]) === false) { + $nextNonEmpty = $maybeUseNext; + } + } + + /* + * Deal with visibility modifiers. + * - `use HelloWorld { sayHello as protected; }` => valid, bow out. + * - `use HelloWorld { sayHello as private myPrivateHello; }` => move to the next token to verify. + */ + elseif ($tokens[$stackPtr]['type'] === 'T_AS' + && isset($this->allowedModifiers[$tokens[$nextNonEmpty]['code']]) === true + && $phpcsFile->hasCondition($stackPtr, \T_USE) === true + ) { + $maybeUseNext = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), null, true, null, true); + if ($maybeUseNext === false || $this->isEndOfUseStatement($tokens[$maybeUseNext]) === true) { + return; + } + + $nextNonEmpty = $maybeUseNext; + } + + /* + * Deal with foreach ( ... as list() ). + */ + elseif ($tokens[$stackPtr]['type'] === 'T_AS' + && isset($tokens[$stackPtr]['nested_parenthesis']) === true + && $tokens[$nextNonEmpty]['code'] === \T_LIST + ) { + $parentheses = array_reverse($tokens[$stackPtr]['nested_parenthesis'], true); + foreach ($parentheses as $open => $close) { + if (isset($tokens[$open]['parenthesis_owner']) + && $tokens[$tokens[$open]['parenthesis_owner']]['code'] === \T_FOREACH + ) { + return; + } + } + } + + /* + * Deal with functions declared to return by reference. + */ + elseif ($tokens[$stackPtr]['type'] === 'T_FUNCTION' + && $tokens[$nextNonEmpty]['type'] === 'T_BITWISE_AND' + ) { + $maybeUseNext = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), null, true, null, true); + if ($maybeUseNext === false) { + // Live coding. + return; + } + + $nextNonEmpty = $maybeUseNext; + } + + /* + * Deal with nested namespaces. + */ + elseif ($tokens[$stackPtr]['type'] === 'T_NAMESPACE') { + if ($tokens[$stackPtr + 1]['code'] === \T_NS_SEPARATOR) { + // Not a namespace declaration, but use of, i.e. `namespace\someFunction();`. + return; + } + + $endToken = $phpcsFile->findNext(array(\T_SEMICOLON, \T_OPEN_CURLY_BRACKET), ($stackPtr + 1), null, false, null, true); + $namespaceName = trim($phpcsFile->getTokensAsString(($stackPtr + 1), ($endToken - $stackPtr - 1))); + if (empty($namespaceName) === true) { + return; + } + + $namespaceParts = explode('\\', $namespaceName); + foreach ($namespaceParts as $namespacePart) { + $partLc = strtolower($namespacePart); + if (isset($this->invalidNames[$partLc]) === false) { + continue; + } + + // Find the token position of the part which matched. + for ($i = ($stackPtr + 1); $i < $endToken; $i++) { + if ($tokens[$i]['content'] === $namespacePart) { + $nextNonEmpty = $i; + break; + } + } + } + unset($i, $namespacePart, $partLc); + } + + $nextContentLc = strtolower($tokens[$nextNonEmpty]['content']); + if (isset($this->invalidNames[$nextContentLc]) === false) { + return; + } + + /* + * Deal with PHP 7 relaxing the rules. + * "As of PHP 7.0.0 these keywords are allowed as property, constant, and method names + * of classes, interfaces and traits, except that class may not be used as constant name." + */ + if ((($tokens[$stackPtr]['type'] === 'T_FUNCTION' + && $this->inClassScope($phpcsFile, $stackPtr, false) === true) + || ($tokens[$stackPtr]['type'] === 'T_CONST' + && $this->isClassConstant($phpcsFile, $stackPtr) === true + && $nextContentLc !== 'class')) + && $this->supportsBelow('5.6') === false + ) { + return; + } + + if ($this->supportsAbove($this->invalidNames[$nextContentLc])) { + $data = array( + $tokens[$nextNonEmpty]['content'], + $this->invalidNames[$nextContentLc], + ); + $this->addError($phpcsFile, $stackPtr, $tokens[$nextNonEmpty]['content'], $data); + } + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processString(File $phpcsFile, $stackPtr, $tokens) + { + $tokenContentLc = strtolower($tokens[$stackPtr]['content']); + + /* + * Special case for PHP versions where the target is not yet identified as + * its own token, but presents as T_STRING. + * - trait keyword in PHP < 5.4 + */ + if (version_compare(\PHP_VERSION_ID, '50400', '<') && $tokenContentLc === 'trait') { + $this->processNonString($phpcsFile, $stackPtr, $tokens); + return; + } + + // Look for any define/defined tokens (both T_STRING ones, blame Tokenizer). + if ($tokenContentLc !== 'define' && $tokenContentLc !== 'defined') { + return; + } + + // Retrieve the define(d) constant name. + $firstParam = $this->getFunctionCallParameter($phpcsFile, $stackPtr, 1); + if ($firstParam === false) { + return; + } + + $defineName = $this->stripQuotes($firstParam['raw']); + $defineNameLc = strtolower($defineName); + + if (isset($this->invalidNames[$defineNameLc]) && $this->supportsAbove($this->invalidNames[$defineNameLc])) { + $data = array( + $defineName, + $this->invalidNames[$defineNameLc], + ); + $this->addError($phpcsFile, $stackPtr, $defineNameLc, $data); + } + } + + + /** + * Add the error message. + * + * @since 7.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param string $content The token content found. + * @param array $data The data to pass into the error message. + * + * @return void + */ + protected function addError(File $phpcsFile, $stackPtr, $content, $data) + { + $error = "Function name, class name, namespace name or constant name can not be reserved keyword '%s' (since version %s)"; + $errorCode = $this->stringToErrorCode($content) . 'Found'; + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } + + + /** + * Check if the current token code is for a token which can be considered + * the end of a (partial) use statement. + * + * @since 7.0.8 + * + * @param int $token The current token information. + * + * @return bool + */ + protected function isEndOfUseStatement($token) + { + return \in_array($token['code'], array(\T_CLOSE_CURLY_BRACKET, \T_SEMICOLON, \T_COMMA), true); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/NewKeywordsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/NewKeywordsSniff.php new file mode 100644 index 00000000..61f79aa5 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/NewKeywordsSniff.php @@ -0,0 +1,391 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Keywords; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect use of new PHP keywords. + * + * PHP version All + * + * @link https://wiki.php.net/rfc/heredoc-with-double-quotes + * @link https://wiki.php.net/rfc/horizontalreuse (traits) + * @link https://wiki.php.net/rfc/generators + * @link https://wiki.php.net/rfc/finally + * @link https://wiki.php.net/rfc/generator-delegation + * + * @since 5.5 + * @since 7.1.0 Now extends the `AbstractNewFeatureSniff` instead of the base `Sniff` class.. + */ +class NewKeywordsSniff extends AbstractNewFeatureSniff +{ + + /** + * A list of new keywords, not present in older versions. + * + * The array lists : version number with false (not present) or true (present). + * If's sufficient to list the last version which did not contain the keyword. + * + * Description will be used as part of the error message. + * Condition is the name of a callback method within this class or the parent class + * which checks whether the token complies with a certain condition. + * The callback function will be passed the $phpcsFile and the $stackPtr. + * The callback function should return `true` if the condition is met and the + * error should *not* be thrown. + * + * @since 5.5 + * @since 7.0.3 Support for 'condition' has been added. + * + * @var array(string => array(string => bool|string)) + */ + protected $newKeywords = array( + 'T_HALT_COMPILER' => array( + '5.0' => false, + '5.1' => true, + 'description' => '"__halt_compiler" keyword', + ), + 'T_CONST' => array( + '5.2' => false, + '5.3' => true, + 'description' => '"const" keyword', + 'condition' => 'isClassConstant', // Keyword is only new when not in class context. + ), + 'T_CALLABLE' => array( + '5.3' => false, + '5.4' => true, + 'description' => '"callable" keyword', + 'content' => 'callable', + ), + 'T_DIR' => array( + '5.2' => false, + '5.3' => true, + 'description' => '__DIR__ magic constant', + 'content' => '__DIR__', + ), + 'T_GOTO' => array( + '5.2' => false, + '5.3' => true, + 'description' => '"goto" keyword', + 'content' => 'goto', + ), + 'T_INSTEADOF' => array( + '5.3' => false, + '5.4' => true, + 'description' => '"insteadof" keyword (for traits)', + 'content' => 'insteadof', + ), + 'T_NAMESPACE' => array( + '5.2' => false, + '5.3' => true, + 'description' => '"namespace" keyword', + 'content' => 'namespace', + ), + 'T_NS_C' => array( + '5.2' => false, + '5.3' => true, + 'description' => '__NAMESPACE__ magic constant', + 'content' => '__NAMESPACE__', + ), + 'T_USE' => array( + '5.2' => false, + '5.3' => true, + 'description' => '"use" keyword (for traits/namespaces/anonymous functions)', + ), + 'T_START_NOWDOC' => array( + '5.2' => false, + '5.3' => true, + 'description' => 'nowdoc functionality', + ), + 'T_END_NOWDOC' => array( + '5.2' => false, + '5.3' => true, + 'description' => 'nowdoc functionality', + ), + 'T_START_HEREDOC' => array( + '5.2' => false, + '5.3' => true, + 'description' => '(Double) quoted Heredoc identifier', + 'condition' => 'isNotQuoted', // Heredoc is only new with quoted identifier. + ), + 'T_TRAIT' => array( + '5.3' => false, + '5.4' => true, + 'description' => '"trait" keyword', + 'content' => 'trait', + ), + 'T_TRAIT_C' => array( + '5.3' => false, + '5.4' => true, + 'description' => '__TRAIT__ magic constant', + 'content' => '__TRAIT__', + ), + // The specifics for distinguishing between 'yield' and 'yield from' are dealt + // with in the translation logic. + // This token has to be placed above the `T_YIELD` token in this array to allow for this. + 'T_YIELD_FROM' => array( + '5.6' => false, + '7.0' => true, + 'description' => '"yield from" keyword (for generators)', + 'content' => 'yield', + ), + 'T_YIELD' => array( + '5.4' => false, + '5.5' => true, + 'description' => '"yield" keyword (for generators)', + 'content' => 'yield', + ), + 'T_FINALLY' => array( + '5.4' => false, + '5.5' => true, + 'description' => '"finally" keyword (in exception handling)', + 'content' => 'finally', + ), + ); + + /** + * Translation table for T_STRING tokens. + * + * Will be set up from the register() method. + * + * @since 7.0.5 + * + * @var array(string => string) + */ + protected $translateContentToToken = array(); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + $tokens = array(); + $translate = array(); + foreach ($this->newKeywords as $token => $versions) { + if (\defined($token)) { + $tokens[] = constant($token); + } + if (isset($versions['content'])) { + $translate[strtolower($versions['content'])] = $token; + } + } + + /* + * Deal with tokens not recognized by the PHP version the sniffer is run + * under and (not correctly) compensated for by PHPCS. + */ + if (empty($translate) === false) { + $this->translateContentToToken = $translate; + $tokens[] = \T_STRING; + } + + return $tokens; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenType = $tokens[$stackPtr]['type']; + + // Allow for dealing with multi-token keywords, like "yield from". + $end = $stackPtr; + + // Translate T_STRING token if necessary. + if ($tokens[$stackPtr]['type'] === 'T_STRING') { + $content = strtolower($tokens[$stackPtr]['content']); + + if (isset($this->translateContentToToken[$content]) === false) { + // Not one of the tokens we're looking for. + return; + } + + $tokenType = $this->translateContentToToken[$content]; + } + + /* + * Special case: distinguish between `yield` and `yield from`. + * + * PHPCS currently (at least up to v 3.0.1) does not backfill for the + * `yield` nor the `yield from` keywords. + * See: https://github.com/squizlabs/PHP_CodeSniffer/issues/1524 + * + * In PHP < 5.5, both `yield` as well as `from` are tokenized as T_STRING. + * In PHP 5.5 - 5.6, `yield` is tokenized as T_YIELD and `from` as T_STRING, + * but the `T_YIELD_FROM` token *is* defined in PHP. + * In PHP 7.0+ both are tokenized as their respective token, however, + * a multi-line "yield from" is tokenized as two tokens. + */ + if ($tokenType === 'T_YIELD') { + $nextToken = $phpcsFile->findNext(\T_WHITESPACE, ($end + 1), null, true); + if ($tokens[$nextToken]['code'] === \T_STRING + && $tokens[$nextToken]['content'] === 'from' + ) { + $tokenType = 'T_YIELD_FROM'; + $end = $nextToken; + } + unset($nextToken); + } + + if ($tokenType === 'T_YIELD_FROM' && $tokens[($stackPtr - 1)]['type'] === 'T_YIELD_FROM') { + // Multi-line "yield from", no need to report it twice. + return; + } + + if (isset($this->newKeywords[$tokenType]) === false) { + return; + } + + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + if ($prevToken !== false + && ($tokens[$prevToken]['code'] === \T_DOUBLE_COLON + || $tokens[$prevToken]['code'] === \T_OBJECT_OPERATOR) + ) { + // Class property of the same name as one of the keywords. Ignore. + return; + } + + // Skip attempts to use keywords as functions or class names - the former + // will be reported by ForbiddenNamesAsInvokedFunctionsSniff, whilst the + // latter will be (partially) reported by the ForbiddenNames sniff. + // Either type will result in false-positives when targetting lower versions + // of PHP where the name was not reserved, unless we explicitly check for + // them. + if (($nextToken === false + || $tokens[$nextToken]['type'] !== 'T_OPEN_PARENTHESIS') + && ($prevToken === false + || $tokens[$prevToken]['type'] !== 'T_CLASS' + || $tokens[$prevToken]['type'] !== 'T_INTERFACE') + ) { + // Skip based on token scope condition. + if (isset($this->newKeywords[$tokenType]['condition']) + && \call_user_func(array($this, $this->newKeywords[$tokenType]['condition']), $phpcsFile, $stackPtr) === true + ) { + return; + } + + $itemInfo = array( + 'name' => $tokenType, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newKeywords[$itemInfo['name']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array( + 'description', + 'condition', + 'content', + ); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['description'] = $itemArray['description']; + + return $errorInfo; + } + + + /** + * Allow for concrete child classes to filter the error data before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + $data[0] = $errorInfo['description']; + return $data; + } + + + /** + * Callback for the quoted heredoc identifier condition. + * + * A double quoted identifier will have the opening quote on position 3 + * in the string: `<<<"ID"`. + * + * @since 8.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return bool + */ + public function isNotQuoted(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + return ($tokens[$stackPtr]['content'][3] !== '"'); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/LanguageConstructs/NewEmptyNonVariableSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/LanguageConstructs/NewEmptyNonVariableSniff.php new file mode 100644 index 00000000..ffb9ef28 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/LanguageConstructs/NewEmptyNonVariableSniff.php @@ -0,0 +1,91 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\LanguageConstructs; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Verify that nothing but variables are passed to empty(). + * + * Prior to PHP 5.5, `empty()` only supported variables; anything else resulted in a parse error. + * + * PHP version 5.5 + * + * @link https://wiki.php.net/rfc/empty_isset_exprs + * @link https://www.php.net/manual/en/function.empty.php + * + * @since 7.0.4 + * @since 9.0.0 The "is the parameter a variable" determination has been abstracted out + * and moved to a separate method `Sniff::isVariable()`. + * @since 9.0.0 Renamed from `EmptyNonVariableSniff` to `NewEmptyNonVariableSniff`. + */ +class NewEmptyNonVariableSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.4 + * + * @return array + */ + public function register() + { + return array(\T_EMPTY); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $open = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); + if ($open === false + || $tokens[$open]['code'] !== \T_OPEN_PARENTHESIS + || isset($tokens[$open]['parenthesis_closer']) === false + ) { + return; + } + + $close = $tokens[$open]['parenthesis_closer']; + + $nestingLevel = 0; + if ($close !== ($open + 1) && isset($tokens[$open + 1]['nested_parenthesis'])) { + $nestingLevel = \count($tokens[$open + 1]['nested_parenthesis']); + } + + if ($this->isVariable($phpcsFile, ($open + 1), $close, $nestingLevel) === true) { + return; + } + + $phpcsFile->addError( + 'Only variables can be passed to empty() prior to PHP 5.5.', + $stackPtr, + 'Found' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/LanguageConstructs/NewLanguageConstructsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/LanguageConstructs/NewLanguageConstructsSniff.php new file mode 100644 index 00000000..44488ed0 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/LanguageConstructs/NewLanguageConstructsSniff.php @@ -0,0 +1,159 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\LanguageConstructs; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect use of new PHP language constructs. + * + * PHP version All + * + * @link https://wiki.php.net/rfc/namespaceseparator + * @link https://wiki.php.net/rfc/variadics + * @link https://wiki.php.net/rfc/argument_unpacking + * + * @since 5.6 + * @since 7.1.0 Now extends the `AbstractNewFeatureSniff` instead of the base `Sniff` class.. + * @since 9.0.0 Detection for new operator tokens has been moved to the `NewOperators` sniff. + */ +class NewLanguageConstructsSniff extends AbstractNewFeatureSniff +{ + + /** + * A list of new language constructs, not present in older versions. + * + * The array lists : version number with false (not present) or true (present). + * If's sufficient to list the first version where the keyword appears. + * + * @since 5.6 + * + * @var array(string => array(string => bool|string)) + */ + protected $newConstructs = array( + 'T_NS_SEPARATOR' => array( + '5.2' => false, + '5.3' => true, + 'description' => 'the \ operator (for namespaces)', + ), + 'T_ELLIPSIS' => array( + '5.5' => false, + '5.6' => true, + 'description' => 'the ... spread operator', + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.6 + * + * @return array + */ + public function register() + { + $tokens = array(); + foreach ($this->newConstructs as $token => $versions) { + $tokens[] = constant($token); + } + return $tokens; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.6 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenType = $tokens[$stackPtr]['type']; + + $itemInfo = array( + 'name' => $tokenType, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newConstructs[$itemInfo['name']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('description'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['description'] = $itemArray['description']; + + return $errorInfo; + } + + + /** + * Allow for concrete child classes to filter the error data before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + $data[0] = $errorInfo['description']; + return $data; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/AssignmentOrderSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/AssignmentOrderSniff.php new file mode 100644 index 00000000..f5ba4772 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/AssignmentOrderSniff.php @@ -0,0 +1,188 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Lists; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect code affected by the changed list assignment order in PHP 7.0+. + * + * The `list()` construct no longer assigns variables in reverse order. + * This affects all list constructs where non-unique variables are used. + * + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/migration70.incompatible.php#migration70.incompatible.variable-handling.list.order + * @link https://wiki.php.net/rfc/abstract_syntax_tree#changes_to_list + * @link https://www.php.net/manual/en/function.list.php + * + * @since 9.0.0 + */ +class AssignmentOrderSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.0.0 + * + * @return array + */ + public function register() + { + return array( + \T_LIST, + \T_OPEN_SHORT_ARRAY, + ); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void|int Void if not a valid list. If a list construct has been + * examined, the stack pointer to the list closer to skip + * passed any nested lists which don't need to be examined again. + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === \T_OPEN_SHORT_ARRAY + && $this->isShortList($phpcsFile, $stackPtr) === false + ) { + // Short array, not short list. + return; + } + + if ($tokens[$stackPtr]['code'] === \T_LIST) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false + || $tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS + || isset($tokens[$nextNonEmpty]['parenthesis_closer']) === false + ) { + // Parse error or live coding. + return; + } + + $opener = $nextNonEmpty; + $closer = $tokens[$nextNonEmpty]['parenthesis_closer']; + } else { + // Short list syntax. + $opener = $stackPtr; + + if (isset($tokens[$stackPtr]['bracket_closer'])) { + $closer = $tokens[$stackPtr]['bracket_closer']; + } + } + + if (isset($opener, $closer) === false) { + return; + } + + /* + * OK, so we have the opener & closer, now we need to check all the variables in the + * list() to see if there are duplicates as that's the problem. + */ + $hasVars = $phpcsFile->findNext(array(\T_VARIABLE, \T_DOLLAR), ($opener + 1), $closer); + if ($hasVars === false) { + // Empty list, not our concern. + return ($closer + 1); + } + + // Set the variable delimiters based on the list type being examined. + $stopPoints = array(\T_COMMA); + if ($tokens[$stackPtr]['code'] === \T_OPEN_SHORT_ARRAY) { + $stopPoints[] = \T_CLOSE_SHORT_ARRAY; + } else { + $stopPoints[] = \T_CLOSE_PARENTHESIS; + } + + $listVars = array(); + $lastStopPoint = $opener; + + /* + * Create a list of all variables used within the `list()` construct. + * We're not concerned with whether these are nested or not, as any duplicate + * variable name used will be problematic, independent of nesting. + */ + do { + $nextStopPoint = $phpcsFile->findNext($stopPoints, ($lastStopPoint + 1), $closer); + if ($nextStopPoint === false) { + $nextStopPoint = $closer; + } + + // Also detect this in PHP 7.1 keyed lists. + $hasDoubleArrow = $phpcsFile->findNext(\T_DOUBLE_ARROW, ($lastStopPoint + 1), $nextStopPoint); + if ($hasDoubleArrow !== false) { + $lastStopPoint = $hasDoubleArrow; + } + + // Find the start of the variable, allowing for variable variables. + $nextStartPoint = $phpcsFile->findNext(array(\T_VARIABLE, \T_DOLLAR), ($lastStopPoint + 1), $nextStopPoint); + if ($nextStartPoint === false) { + // Skip past empty bits in the list, i.e. `list( $a, , ,)`. + $lastStopPoint = $nextStopPoint; + continue; + } + + /* + * Gather the content of all non-empty tokens to determine the "variable name". + * Variable name in this context includes array or object property syntaxes, such + * as `$a['name']` and `$b->property`. + */ + $varContent = ''; + + for ($i = $nextStartPoint; $i < $nextStopPoint; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']])) { + continue; + } + + $varContent .= $tokens[$i]['content']; + } + + if ($varContent !== '') { + $listVars[] = $varContent; + } + + $lastStopPoint = $nextStopPoint; + + } while ($lastStopPoint < $closer); + + if (empty($listVars)) { + // Shouldn't be possible, but just in case. + return ($closer + 1); + } + + // Verify that all variables used in the list() construct are unique. + if (\count($listVars) !== \count(array_unique($listVars))) { + $phpcsFile->addError( + 'list() will assign variable from left-to-right since PHP 7.0. Ensure all variables in list() are unique to prevent unexpected results.', + $stackPtr, + 'Affected' + ); + } + + return ($closer + 1); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/ForbiddenEmptyListAssignmentSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/ForbiddenEmptyListAssignmentSniff.php new file mode 100644 index 00000000..b9d4b7b0 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/ForbiddenEmptyListAssignmentSniff.php @@ -0,0 +1,116 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Lists; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Support for empty `list()` expressions has been removed in PHP 7.0. + * + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/migration70.incompatible.php#migration70.incompatible.variable-handling.list.empty + * @link https://wiki.php.net/rfc/abstract_syntax_tree#changes_to_list + * @link https://www.php.net/manual/en/function.list.php + * + * @since 7.0.0 + */ +class ForbiddenEmptyListAssignmentSniff extends Sniff +{ + + /** + * List of tokens to disregard when determining whether the list() is empty. + * + * @since 7.0.3 + * + * @var array + */ + protected $ignoreTokens = array(); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + // Set up a list of tokens to disregard when determining whether the list() is empty. + // Only needs to be set up once. + $this->ignoreTokens = Tokens::$emptyTokens; + $this->ignoreTokens[\T_COMMA] = \T_COMMA; + $this->ignoreTokens[\T_OPEN_PARENTHESIS] = \T_OPEN_PARENTHESIS; + $this->ignoreTokens[\T_CLOSE_PARENTHESIS] = \T_CLOSE_PARENTHESIS; + + return array( + \T_LIST, + \T_OPEN_SHORT_ARRAY, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === \T_OPEN_SHORT_ARRAY) { + if ($this->isShortList($phpcsFile, $stackPtr) === false) { + return; + } + + $open = $stackPtr; + $close = $tokens[$stackPtr]['bracket_closer']; + } else { + // T_LIST. + $open = $phpcsFile->findNext(\T_OPEN_PARENTHESIS, $stackPtr, null, false, null, true); + if ($open === false || isset($tokens[$open]['parenthesis_closer']) === false) { + return; + } + + $close = $tokens[$open]['parenthesis_closer']; + } + + $error = true; + if (($close - $open) > 1) { + for ($cnt = $open + 1; $cnt < $close; $cnt++) { + if (isset($this->ignoreTokens[$tokens[$cnt]['code']]) === false) { + $error = false; + break; + } + } + } + + if ($error === true) { + $phpcsFile->addError( + 'Empty list() assignments are not allowed since PHP 7.0', + $stackPtr, + 'Found' + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewKeyedListSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewKeyedListSniff.php new file mode 100644 index 00000000..7111b125 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewKeyedListSniff.php @@ -0,0 +1,227 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Lists; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Since PHP 7.1, you can specify keys in `list()`, or its new shorthand `[]` syntax. + * + * PHP version 7.1 + * + * @link https://wiki.php.net/rfc/list_keys + * @link https://www.php.net/manual/en/function.list.php + * + * @since 9.0.0 + */ +class NewKeyedListSniff extends Sniff +{ + /** + * Tokens which represent the start of a list construct. + * + * @since 9.0.0 + * + * @var array + */ + protected $sniffTargets = array( + \T_LIST => \T_LIST, + \T_OPEN_SHORT_ARRAY => \T_OPEN_SHORT_ARRAY, + ); + + /** + * The token(s) within the list construct which is being targeted. + * + * @since 9.0.0 + * + * @var array + */ + protected $targetsInList = array( + \T_DOUBLE_ARROW => \T_DOUBLE_ARROW, + ); + + /** + * All tokens needed to walk through the list construct and + * determine whether the target token is contained within. + * + * Set by the setUpAllTargets() method which is called from within register(). + * + * @since 9.0.0 + * + * @var array + */ + protected $allTargets; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.0.0 + * + * @return array + */ + public function register() + { + $this->setUpAllTargets(); + + return $this->sniffTargets; + } + + /** + * Prepare the $allTargets array only once. + * + * @since 9.0.0 + * + * @return void + */ + public function setUpAllTargets() + { + $this->allTargets = $this->sniffTargets + $this->targetsInList; + } + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('7.0') === false); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->bowOutEarly() === true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === \T_OPEN_SHORT_ARRAY + && $this->isShortList($phpcsFile, $stackPtr) === false + ) { + // Short array, not short list. + return; + } + + if ($tokens[$stackPtr]['code'] === \T_LIST) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false + || $tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS + || isset($tokens[$nextNonEmpty]['parenthesis_closer']) === false + ) { + // Parse error or live coding. + return; + } + + $opener = $nextNonEmpty; + $closer = $tokens[$nextNonEmpty]['parenthesis_closer']; + } else { + // Short list syntax. + $opener = $stackPtr; + + if (isset($tokens[$stackPtr]['bracket_closer'])) { + $closer = $tokens[$stackPtr]['bracket_closer']; + } + } + + if (isset($opener, $closer) === false) { + return; + } + + $this->examineList($phpcsFile, $opener, $closer); + } + + + /** + * Examine the contents of a list construct to determine whether an error needs to be thrown. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $opener The position of the list open token. + * @param int $closer The position of the list close token. + * + * @return void + */ + protected function examineList(File $phpcsFile, $opener, $closer) + { + $start = $opener; + while (($start = $this->hasTargetInList($phpcsFile, $start, $closer)) !== false) { + $phpcsFile->addError( + 'Specifying keys in list constructs is not supported in PHP 7.0 or earlier.', + $start, + 'Found' + ); + } + } + + + /** + * Check whether a certain target token exists within a list construct. + * + * Skips past nested list constructs, so these can be examined based on their own token. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $start The position of the list open token or a token + * within the list to start (resume) the examination from. + * @param int $closer The position of the list close token. + * + * @return int|bool Stack pointer to the target token if encountered. False otherwise. + */ + protected function hasTargetInList(File $phpcsFile, $start, $closer) + { + $tokens = $phpcsFile->getTokens(); + + for ($i = ($start + 1); $i < $closer; $i++) { + if (isset($this->allTargets[$tokens[$i]['code']]) === false) { + continue; + } + + if (isset($this->targetsInList[$tokens[$i]['code']]) === true) { + return $i; + } + + // Skip past nested list constructs. + if ($tokens[$i]['code'] === \T_LIST) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($nextNonEmpty !== false + && $tokens[$nextNonEmpty]['code'] === \T_OPEN_PARENTHESIS + && isset($tokens[$nextNonEmpty]['parenthesis_closer']) === true + ) { + $i = $tokens[$nextNonEmpty]['parenthesis_closer']; + } + } elseif ($tokens[$i]['code'] === \T_OPEN_SHORT_ARRAY + && isset($tokens[$i]['bracket_closer']) + ) { + $i = $tokens[$i]['bracket_closer']; + } + } + + return false; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewListReferenceAssignmentSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewListReferenceAssignmentSniff.php new file mode 100644 index 00000000..ebcd7c8e --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewListReferenceAssignmentSniff.php @@ -0,0 +1,74 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Lists; + +use PHPCompatibility\Sniffs\Lists\NewKeyedListSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect reference assignments in array destructuring using (short) list. + * + * PHP version 7.3 + * + * @link https://www.php.net/manual/en/migration73.new-features.php#migration73.new-features.core.destruct-reference + * @link https://wiki.php.net/rfc/list_reference_assignment + * @link https://www.php.net/manual/en/function.list.php + * + * @since 9.0.0 + */ +class NewListReferenceAssignmentSniff extends NewKeyedListSniff +{ + /** + * The token(s) within the list construct which is being targeted. + * + * @since 9.0.0 + * + * @var array + */ + protected $targetsInList = array( + \T_BITWISE_AND => \T_BITWISE_AND, + ); + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('7.2') === false); + } + + /** + * Examine the contents of a list construct to determine whether an error needs to be thrown. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $opener The position of the list open token. + * @param int $closer The position of the list close token. + * + * @return void + */ + protected function examineList(File $phpcsFile, $opener, $closer) + { + $start = $opener; + while (($start = $this->hasTargetInList($phpcsFile, $start, $closer)) !== false) { + $phpcsFile->addError( + 'Reference assignments within list constructs are not supported in PHP 7.2 or earlier.', + $start, + 'Found' + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewShortListSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewShortListSniff.php new file mode 100644 index 00000000..ee100fbe --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewShortListSniff.php @@ -0,0 +1,84 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Lists; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect short list syntax for symmetric array destructuring. + * + * "The shorthand array syntax (`[]`) may now be used to destructure arrays for + * assignments (including within `foreach`), as an alternative to the existing + * `list()` syntax, which is still supported." + * + * PHP version 7.1 + * + * @link https://www.php.net/manual/en/migration71.new-features.php#migration71.new-features.symmetric-array-destructuring + * @link https://wiki.php.net/rfc/short_list_syntax + * + * @since 9.0.0 + */ +class NewShortListSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.0.0 + * + * @return array + */ + public function register() + { + return array(\T_OPEN_SHORT_ARRAY); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('7.0') === false) { + return; + } + + if ($this->isShortList($phpcsFile, $stackPtr) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $closer = $tokens[$stackPtr]['bracket_closer']; + + $hasVariable = $phpcsFile->findNext(\T_VARIABLE, ($stackPtr + 1), $closer); + if ($hasVariable === false) { + // List syntax is only valid if there are variables in it. + return; + } + + $phpcsFile->addError( + 'The shorthand list syntax "[]" to destructure arrays is not available in PHP 7.0 or earlier.', + $stackPtr, + 'Found' + ); + + return ($closer + 1); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/MethodUse/ForbiddenToStringParametersSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/MethodUse/ForbiddenToStringParametersSniff.php new file mode 100644 index 00000000..d580bac7 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/MethodUse/ForbiddenToStringParametersSniff.php @@ -0,0 +1,103 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\MethodUse; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * As of PHP 5.3, the `__toString()` magic method can no longer be passed arguments. + * + * Sister-sniff to `PHPCompatibility.FunctionDeclarations.ForbiddenToStringParameters`. + * + * PHP version 5.3 + * + * @link https://www.php.net/manual/en/migration53.incompatible.php + * @link https://www.php.net/manual/en/language.oop5.magic.php#object.tostring + * + * @since 9.2.0 + */ +class ForbiddenToStringParametersSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + return array( + \T_DOUBLE_COLON, + \T_OBJECT_OPERATOR, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('5.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_STRING) { + /* + * Not a method call. + * + * Note: This disregards method calls with the method name in a variable, like: + * $method = '__toString'; + * $obj->$method(); + * However, that would be very hard to examine reliably anyway. + */ + return; + } + + if (strtolower($tokens[$nextNonEmpty]['content']) !== '__tostring') { + // Not a call to the __toString() method. + return; + } + + $openParens = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), null, true); + if ($openParens === false || $tokens[$openParens]['code'] !== \T_OPEN_PARENTHESIS) { + // Not a method call. + return; + } + + $closeParens = $phpcsFile->findNext(Tokens::$emptyTokens, ($openParens + 1), null, true); + if ($closeParens === false || $tokens[$closeParens]['code'] === \T_CLOSE_PARENTHESIS) { + // Not a method call. + return; + } + + // If we're still here, then this is a call to the __toString() magic method passing parameters. + $phpcsFile->addError( + 'The __toString() magic method will no longer accept passed arguments since PHP 5.3', + $stackPtr, + 'Passed' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/MethodUse/NewDirectCallsToCloneSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/MethodUse/NewDirectCallsToCloneSniff.php new file mode 100644 index 00000000..873ef1d2 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/MethodUse/NewDirectCallsToCloneSniff.php @@ -0,0 +1,117 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\MethodUse; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect direct calls to the `__clone()` magic method, which is allowed since PHP 7.0. + * + * "Doing calls like `$obj->__clone()` is now allowed. This was the only magic method + * that had a compile-time check preventing some calls to it, which doesn't make sense. + * If we allow all other magic methods to be called, there's no reason to forbid this one." + * + * PHP version 7.0 + * + * @link https://wiki.php.net/rfc/abstract_syntax_tree#directly_calling_clone_is_allowed + * @link https://www.php.net/manual/en/language.oop5.cloning.php + * + * @since 9.1.0 + */ +class NewDirectCallsToCloneSniff extends Sniff +{ + + /** + * Tokens which indicate class internal use. + * + * @since 9.3.2 + * + * @var array + */ + protected $classInternal = array( + \T_PARENT => true, + \T_SELF => true, + \T_STATIC => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.1.0 + * + * @return array + */ + public function register() + { + return array( + \T_DOUBLE_COLON, + \T_OBJECT_OPERATOR, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.6') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_STRING) { + /* + * Not a method call. + * + * Note: This disregards method calls with the method name in a variable, like: + * $method = '__clone'; + * $obj->$method(); + * However, that would be very hard to examine reliably anyway. + */ + return; + } + + if (strtolower($tokens[$nextNonEmpty]['content']) !== '__clone') { + // Not a call to the __clone() method. + return; + } + + $nextNextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), null, true); + if ($nextNextNonEmpty === false || $tokens[$nextNextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS) { + // Not a method call. + return; + } + + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prevNonEmpty === false || isset($this->classInternal[$tokens[$prevNonEmpty]['code']])) { + // Class internal call to __clone(). + return; + } + + $phpcsFile->addError( + 'Direct calls to the __clone() magic method are not allowed in PHP 5.6 or earlier.', + $nextNonEmpty, + 'Found' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/NewPHPOpenTagEOFSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/NewPHPOpenTagEOFSniff.php new file mode 100644 index 00000000..85e10bcf --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/NewPHPOpenTagEOFSniff.php @@ -0,0 +1,147 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Miscellaneous; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * PHP 7.4 now supports stand-alone PHP tags at the end of a file (without new line). + * + * > `<?php` at the end of the file (without trailing newline) will now be + * > interpreted as an opening PHP tag. Previously it was interpreted either as + * > `<? php` and resulted in a syntax error (with short_open_tag=1) or was + * > interpreted as a literal `<?php` string (with short_open_tag=0). + * + * {@internal Due to an issue with the Tokenizer, this sniff will not work correctly + * on PHP 5.3 in combination with PHPCS < 2.6.0 when short_open_tag is `On`. + * As this is causing "Undefined offset" notices, there is nothing we can + * do to work-around this.} + * + * PHP version 7.4 + * + * @link https://www.php.net/manual/en/migration74.incompatible.php#migration74.incompatible.core.php-tag + * @link https://github.com/php/php-src/blob/30de357fa14480468132bbc22a272aeb91789ba8/UPGRADING#L37-L40 + * + * @since 9.3.0 + */ +class NewPHPOpenTagEOFSniff extends Sniff +{ + + /** + * Whether or not short open tags is enabled on the install running the sniffs. + * + * @since 9.3.0 + * + * @var bool + */ + protected $shortOpenTags; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.3.0 + * + * @return array + */ + public function register() + { + $targets = array( + \T_OPEN_TAG_WITH_ECHO, + ); + + $this->shortOpenTags = (bool) ini_get('short_open_tag'); + if ($this->shortOpenTags === false) { + $targets[] = \T_INLINE_HTML; + } else { + $targets[] = \T_STRING; + } + + if (version_compare(\PHP_VERSION_ID, '70399', '>')) { + $targets[] = \T_OPEN_TAG; + } + + return $targets; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('7.3') === false) { + return; + } + + if ($stackPtr !== ($phpcsFile->numTokens - 1)) { + // We're only interested in the last token in the file. + return; + } + + $tokens = $phpcsFile->getTokens(); + $contents = $tokens[$stackPtr]['content']; + $error = false; + + switch ($tokens[$stackPtr]['code']) { + case \T_INLINE_HTML: + // PHP < 7.4 with short open tags off. + if ($contents === '<?php') { + $error = true; + } elseif ($contents === '<?=') { + // Also cover short open echo tags in PHP 5.3 with short open tags off. + $error = true; + } + break; + + case \T_STRING: + // PHP < 7.4 with short open tags on. + if ($contents === 'php' + && $tokens[($stackPtr - 1)]['code'] === \T_OPEN_TAG + && $tokens[($stackPtr - 1)]['content'] === '<?' + ) { + $error = true; + } + break; + + case \T_OPEN_TAG_WITH_ECHO: + // PHP 5.4+. + if (rtrim($contents) === '<?=') { + $error = true; + } + break; + + case \T_OPEN_TAG: + // PHP 7.4+. + if ($contents === '<?php') { + $error = true; + } + break; + } + + if ($error === true) { + $phpcsFile->addError( + 'A PHP open tag at the end of a file, without trailing newline, was not supported in PHP 7.3 or earlier and would result in a syntax error or be interpreted as a literal string', + $stackPtr, + 'Found' + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/RemovedAlternativePHPTagsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/RemovedAlternativePHPTagsSniff.php new file mode 100644 index 00000000..47143a3d --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/RemovedAlternativePHPTagsSniff.php @@ -0,0 +1,172 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Miscellaneous; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Check for use of alternative PHP tags, support for which was removed in PHP 7.0. + * + * {@internal Based on `Generic.PHP.DisallowAlternativePHPTags` by Juliette Reinders Folmer + * (with permission) which was merged into PHPCS 2.7.0.} + * + * PHP version 7.0 + * + * @link https://wiki.php.net/rfc/remove_alternative_php_tags + * @link https://www.php.net/manual/en/language.basic-syntax.phptags.php + * + * @since 7.0.4 + */ +class RemovedAlternativePHPTagsSniff extends Sniff +{ + + /** + * Whether ASP tags are enabled or not. + * + * @since 7.0.4 + * + * @var bool + */ + private $aspTags = false; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.4 + * + * @return array + */ + public function register() + { + if (version_compare(\PHP_VERSION_ID, '70000', '<') === true) { + // phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.asp_tagsRemoved + $this->aspTags = (bool) ini_get('asp_tags'); + } + + return array( + \T_OPEN_TAG, + \T_OPEN_TAG_WITH_ECHO, + \T_INLINE_HTML, + ); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $openTag = $tokens[$stackPtr]; + $content = trim($openTag['content']); + + if ($content === '' || $content === '<?php') { + return; + } + + if ($openTag['code'] === \T_OPEN_TAG || $openTag['code'] === \T_OPEN_TAG_WITH_ECHO) { + + if ($content === '<%' || $content === '<%=') { + $data = array( + 'ASP', + $content, + ); + $errorCode = 'ASPOpenTagFound'; + + } elseif (strpos($content, '<script ') !== false) { + $data = array( + 'Script', + $content, + ); + $errorCode = 'ScriptOpenTagFound'; + } else { + return; + } + } + // Account for incorrect script open tags. + // The "(?:<s)?" in the regex is to work-around a bug in the tokenizer in PHP 5.2. + elseif ($openTag['code'] === \T_INLINE_HTML + && preg_match('`((?:<s)?cript (?:[^>]+)?language=[\'"]?php[\'"]?(?:[^>]+)?>)`i', $content, $match) === 1 + ) { + $found = $match[1]; + $data = array( + 'Script', + $found, + ); + $errorCode = 'ScriptOpenTagFound'; + } + + if (isset($errorCode, $data)) { + $phpcsFile->addError( + '%s style opening tags have been removed in PHP 7.0. Found "%s"', + $stackPtr, + $errorCode, + $data + ); + return; + } + + // If we're still here, we can't be sure if what we found was really intended as ASP open tags. + if ($openTag['code'] === \T_INLINE_HTML && $this->aspTags === false) { + if (strpos($content, '<%') !== false) { + $error = 'Possible use of ASP style opening tags detected. ASP style opening tags have been removed in PHP 7.0. Found: %s'; + $snippet = $this->getSnippet($content, '<%'); + $data = array('<%' . $snippet); + + $phpcsFile->addWarning($error, $stackPtr, 'MaybeASPOpenTagFound', $data); + } + } + } + + + /** + * Get a snippet from a HTML token. + * + * @since 7.0.4 + * + * @param string $content The content of the HTML token. + * @param string $startAt Partial string to use as a starting point for the snippet. + * @param int $length The target length of the snippet to get. Defaults to 25. + * + * @return string + */ + protected function getSnippet($content, $startAt = '', $length = 25) + { + $startPos = 0; + + if ($startAt !== '') { + $startPos = strpos($content, $startAt); + if ($startPos !== false) { + $startPos += \strlen($startAt); + } + } + + $snippet = substr($content, $startPos, $length); + if ((\strlen($content) - $startPos) > $length) { + $snippet .= '...'; + } + + return $snippet; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/ValidIntegersSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/ValidIntegersSniff.php new file mode 100644 index 00000000..53dce438 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/ValidIntegersSniff.php @@ -0,0 +1,250 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Miscellaneous; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Check for valid integer types and values. + * + * Checks: + * - PHP 5.4 introduced binary integers. + * - PHP 7.0 removed tolerance for invalid octals. These were truncated prior to PHP 7 + * and give a parse error since PHP 7. + * - PHP 7.0 removed support for recognizing hexadecimal numeric strings as numeric. + * Type juggling and recognition was inconsistent prior to PHP 7. As of PHP 7, they + * are no longer treated as numeric. + * + * PHP version 5.4+ + * + * @link https://wiki.php.net/rfc/binnotation4ints + * @link https://wiki.php.net/rfc/remove_hex_support_in_numeric_strings + * @link https://www.php.net/manual/en/language.types.integer.php + * + * @since 7.0.3 + * @since 7.0.8 This sniff now throws a warning instead of an error for invalid binary integers. + */ +class ValidIntegersSniff extends Sniff +{ + + /** + * Whether PHPCS is run on a PHP < 5.4. + * + * @since 7.0.3 + * + * @var bool + */ + protected $isLowPHPVersion = false; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.3 + * + * @return array + */ + public function register() + { + $this->isLowPHPVersion = version_compare(\PHP_VERSION_ID, '50400', '<'); + + return array( + \T_LNUMBER, // Binary, octal integers. + \T_CONSTANT_ENCAPSED_STRING, // Hex numeric string. + ); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + if ($this->couldBeBinaryInteger($tokens, $stackPtr) === true) { + if ($this->supportsBelow('5.3')) { + $error = 'Binary integer literals were not present in PHP version 5.3 or earlier. Found: %s'; + if ($this->isLowPHPVersion === false) { + $data = array($token['content']); + } else { + $data = array($this->getBinaryInteger($phpcsFile, $tokens, $stackPtr)); + } + $phpcsFile->addError($error, $stackPtr, 'BinaryIntegerFound', $data); + } + + if ($this->isInvalidBinaryInteger($tokens, $stackPtr) === true) { + $error = 'Invalid binary integer detected. Found: %s'; + $data = array($this->getBinaryInteger($phpcsFile, $tokens, $stackPtr)); + $phpcsFile->addWarning($error, $stackPtr, 'InvalidBinaryIntegerFound', $data); + } + return; + } + + $isError = $this->supportsAbove('7.0'); + $data = array( $token['content'] ); + + if ($this->isInvalidOctalInteger($tokens, $stackPtr) === true) { + $this->addMessage( + $phpcsFile, + 'Invalid octal integer detected. Prior to PHP 7 this would lead to a truncated number. From PHP 7 onwards this causes a parse error. Found: %s', + $stackPtr, + $isError, + 'InvalidOctalIntegerFound', + $data + ); + return; + } + + if ($this->isHexidecimalNumericString($tokens, $stackPtr) === true) { + $this->addMessage( + $phpcsFile, + 'The behaviour of hexadecimal numeric strings was inconsistent prior to PHP 7 and support has been removed in PHP 7. Found: %s', + $stackPtr, + $isError, + 'HexNumericStringFound', + $data + ); + return; + } + } + + + /** + * Could the current token potentially be a binary integer ? + * + * @since 7.0.3 + * + * @param array $tokens Token stack. + * @param int $stackPtr The current position in the token stack. + * + * @return bool + */ + private function couldBeBinaryInteger($tokens, $stackPtr) + { + $token = $tokens[$stackPtr]; + + if ($token['code'] !== \T_LNUMBER) { + return false; + } + + if ($this->isLowPHPVersion === false) { + return (preg_match('`^0b[0-1]+$`iD', $token['content']) === 1); + } + // Pre-5.4, binary strings are tokenized as T_LNUMBER (0) + T_STRING ("b01010101"). + // At this point, we don't yet care whether it's a valid binary int, that's a separate check. + else { + return($token['content'] === '0' && $tokens[$stackPtr + 1]['code'] === \T_STRING && preg_match('`^b[0-9]+$`iD', $tokens[$stackPtr + 1]['content']) === 1); + } + } + + /** + * Is the current token an invalid binary integer ? + * + * @since 7.0.3 + * + * @param array $tokens Token stack. + * @param int $stackPtr The current position in the token stack. + * + * @return bool + */ + private function isInvalidBinaryInteger($tokens, $stackPtr) + { + if ($this->couldBeBinaryInteger($tokens, $stackPtr) === false) { + return false; + } + + if ($this->isLowPHPVersion === false) { + // If it's an invalid binary int, the token will be split into two T_LNUMBER tokens. + return ($tokens[$stackPtr + 1]['code'] === \T_LNUMBER); + } else { + return (preg_match('`^b[0-1]+$`iD', $tokens[$stackPtr + 1]['content']) === 0); + } + } + + /** + * Retrieve the content of the tokens which together look like a binary integer. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param array $tokens Token stack. + * @param int $stackPtr The position of the current token in + * the stack. + * + * @return string + */ + private function getBinaryInteger(File $phpcsFile, $tokens, $stackPtr) + { + $length = 2; // PHP < 5.4 T_LNUMBER + T_STRING. + + if ($this->isLowPHPVersion === false) { + $i = $stackPtr; + while ($tokens[$i]['code'] === \T_LNUMBER) { + $i++; + } + $length = ($i - $stackPtr); + } + + return $phpcsFile->getTokensAsString($stackPtr, $length); + } + + /** + * Is the current token an invalid octal integer ? + * + * @since 7.0.3 + * + * @param array $tokens Token stack. + * @param int $stackPtr The current position in the token stack. + * + * @return bool + */ + private function isInvalidOctalInteger($tokens, $stackPtr) + { + $token = $tokens[$stackPtr]; + + if ($token['code'] === \T_LNUMBER && preg_match('`^0[0-7]*[8-9]+[0-9]*$`D', $token['content']) === 1) { + return true; + } + + return false; + } + + /** + * Is the current token a hexidecimal numeric string ? + * + * @since 7.0.3 + * + * @param array $tokens Token stack. + * @param int $stackPtr The current position in the token stack. + * + * @return bool + */ + private function isHexidecimalNumericString($tokens, $stackPtr) + { + $token = $tokens[$stackPtr]; + + if ($token['code'] === \T_CONSTANT_ENCAPSED_STRING && preg_match('`^0x[a-f0-9]+$`iD', $this->stripQuotes($token['content'])) === 1) { + return true; + } + + return false; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/ChangedConcatOperatorPrecedenceSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/ChangedConcatOperatorPrecedenceSniff.php new file mode 100644 index 00000000..3dfe738c --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/ChangedConcatOperatorPrecedenceSniff.php @@ -0,0 +1,199 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Operators; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect code affected by the change in operator precedence of concatenation in PHP 8.0. + * + * In PHP < 8.0 the operator precedence of `.`, `+` and `-` are the same. + * As of PHP 8.0, the operator precedence of the concatenation operator will be + * lowered to be right below the `<<` and `>>` operators. + * + * As of PHP 7.4, a deprecation warning will be thrown upon encountering an + * unparenthesized expression containing an `.` before a `+` or `-`. + * + * PHP version 7.4 + * PHP version 8.0 + * + * @link https://wiki.php.net/rfc/concatenation_precedence + * @link https://www.php.net/manual/en/language.operators.precedence.php + * + * @since 9.2.0 + */ +class ChangedConcatOperatorPrecedenceSniff extends Sniff +{ + + /** + * List of tokens with a lower operator precedence than concatenation in PHP >= 8.0. + * + * @since 9.2.0 + * + * @var array + */ + private $tokensWithLowerPrecedence = array( + 'T_BITWISE_AND' => true, + 'T_BITWISE_XOR' => true, + 'T_BITWISE_OR' => true, + 'T_COALESCE' => true, + 'T_INLINE_THEN' => true, + 'T_INLINE_ELSE' => true, + 'T_YIELD_FROM' => true, + 'T_YIELD' => true, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + return array( + \T_PLUS, + \T_MINUS, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.4') === false) { + return; + } + + if ($this->isUnaryPlusMinus($phpcsFile, $stackPtr) === true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + for ($i = ($stackPtr - 1); $stackPtr >= 0; $i--) { + if ($tokens[$i]['code'] === \T_STRING_CONCAT) { + // Found one. + break; + } + + if ($tokens[$i]['code'] === \T_SEMICOLON + || $tokens[$i]['code'] === \T_OPEN_CURLY_BRACKET + || $tokens[$i]['code'] === \T_OPEN_TAG + || $tokens[$i]['code'] === \T_OPEN_TAG_WITH_ECHO + || $tokens[$i]['code'] === \T_COMMA + || $tokens[$i]['code'] === \T_COLON + || $tokens[$i]['code'] === \T_CASE + ) { + // If we reached any of the above tokens, we've reached the end of + // the statement without encountering a concatenation operator. + return; + } + + if ($tokens[$i]['code'] === \T_OPEN_CURLY_BRACKET + && isset($tokens[$i]['bracket_closer']) + && $tokens[$i]['bracket_closer'] > $stackPtr + ) { + // No need to look any further, this is plus/minus within curly braces + // and we've reached the open curly. + return; + } + + if ($tokens[$i]['code'] === \T_OPEN_PARENTHESIS + && isset($tokens[$i]['parenthesis_closer']) + && $tokens[$i]['parenthesis_closer'] > $stackPtr + ) { + // No need to look any further, this is plus/minus within parenthesis + // and we've reached the open parenthesis. + return; + } + + if (($tokens[$i]['code'] === \T_OPEN_SHORT_ARRAY + || $tokens[$i]['code'] === \T_OPEN_SQUARE_BRACKET) + && isset($tokens[$i]['bracket_closer']) + && $tokens[$i]['bracket_closer'] > $stackPtr + ) { + // No need to look any further, this is plus/minus within a short array + // or array key square brackets and we've reached the opener. + return; + } + + if ($tokens[$i]['code'] === \T_CLOSE_CURLY_BRACKET) { + if (isset($tokens[$i]['scope_owner'])) { + // Different scope, we've passed the start of the statement. + return; + } + + if (isset($tokens[$i]['bracket_opener'])) { + $i = $tokens[$i]['bracket_opener']; + } + + continue; + } + + if ($tokens[$i]['code'] === \T_CLOSE_PARENTHESIS + && isset($tokens[$i]['parenthesis_opener']) + ) { + // Skip over statements in parenthesis, including long arrays. + $i = $tokens[$i]['parenthesis_opener']; + continue; + } + + if (($tokens[$i]['code'] === \T_CLOSE_SQUARE_BRACKET + || $tokens[$i]['code'] === \T_CLOSE_SHORT_ARRAY) + && isset($tokens[$i]['bracket_opener']) + ) { + // Skip over array keys and short arrays. + $i = $tokens[$i]['bracket_opener']; + continue; + } + + // Check for chain being broken by a token with a lower precedence. + if (isset(Tokens::$booleanOperators[$tokens[$i]['code']]) === true + || isset(Tokens::$assignmentTokens[$tokens[$i]['code']]) === true + ) { + return; + } + + if (isset($this->tokensWithLowerPrecedence[$tokens[$i]['type']]) === true) { + if ($tokens[$i]['code'] === \T_BITWISE_AND + && $phpcsFile->isReference($i) === true + ) { + continue; + } + + return; + } + } + + $message = 'Using an unparenthesized expression containing a "." before a "+" or "-" has been deprecated in PHP 7.4'; + $isError = false; + if ($this->supportsAbove('8.0') === true) { + $message .= ' and removed in PHP 8.0'; + $isError = true; + } + + $this->addMessage($phpcsFile, $message, $i, $isError); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/ForbiddenNegativeBitshiftSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/ForbiddenNegativeBitshiftSniff.php new file mode 100644 index 00000000..740e7dfd --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/ForbiddenNegativeBitshiftSniff.php @@ -0,0 +1,109 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Operators; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Bitwise shifts by negative number will throw an ArithmeticError since PHP 7.0. + * + * PHP version 7.0 + * + * @link https://wiki.php.net/rfc/integer_semantics + * @link https://www.php.net/manual/en/migration70.incompatible.php#migration70.incompatible.integers.negative-bitshift + * + * @since 7.0.0 + */ +class ForbiddenNegativeBitshiftSniff extends Sniff +{ + /** + * Potential end tokens for which the end pointer has to be set back by one. + * + * {@internal The PHPCS `findEndOfStatement()` method is not completely consistent + * in how it returns the statement end. This is just a simple way to bypass + * the inconsistency for our purposes.} + * + * @since 8.2.0 + * + * @var array + */ + private $inclusiveStopPoints = array( + \T_COLON => true, + \T_COMMA => true, + \T_DOUBLE_ARROW => true, + \T_SEMICOLON => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * @since 8.2.0 Now registers all bitshift tokens, not just bitshift right (`T_SR`). + * + * @return array + */ + public function register() + { + return array( + \T_SL, + \T_SL_EQUAL, + \T_SR, + \T_SR_EQUAL, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + // Determine the start and end of the part of the statement we need to examine. + $start = ($stackPtr + 1); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $start, null, true); + if ($next !== false && $tokens[$next]['code'] === \T_OPEN_PARENTHESIS) { + $start = ($next + 1); + } + + $end = PHPCSHelper::findEndOfStatement($phpcsFile, $start); + if (isset($this->inclusiveStopPoints[$tokens[$end]['code']]) === true) { + --$end; + } + + if ($this->isNegativeNumber($phpcsFile, $start, $end, true) !== true) { + // Not a negative number or undetermined. + return; + } + + $phpcsFile->addError( + 'Bitwise shifts by negative number will throw an ArithmeticError in PHP 7.0. Found: %s', + $stackPtr, + 'Found', + array($phpcsFile->getTokensAsString($start, ($end - $start + 1))) + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/NewOperatorsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/NewOperatorsSniff.php new file mode 100644 index 00000000..7c50ad86 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/NewOperatorsSniff.php @@ -0,0 +1,317 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Operators; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect use of new PHP operators. + * + * PHP version All + * + * @link https://wiki.php.net/rfc/pow-operator + * @link https://wiki.php.net/rfc/combined-comparison-operator + * @link https://wiki.php.net/rfc/isset_ternary + * @link https://wiki.php.net/rfc/null_coalesce_equal_operator + * + * @since 9.0.0 Detection of new operators was originally included in the + * `NewLanguageConstruct` sniff (since 5.6). + */ +class NewOperatorsSniff extends AbstractNewFeatureSniff +{ + + /** + * A list of new operators, not present in older versions. + * + * The array lists : version number with false (not present) or true (present). + * If's sufficient to list the first version where the operator appears. + * + * @since 5.6 + * + * @var array(string => array(string => bool|string)) + */ + protected $newOperators = array( + 'T_POW' => array( + '5.5' => false, + '5.6' => true, + 'description' => 'power operator (**)', + ), // Identified in PHP < 5.6 icw PHPCS < 2.4.0 as T_MULTIPLY + T_MULTIPLY. + 'T_POW_EQUAL' => array( + '5.5' => false, + '5.6' => true, + 'description' => 'power assignment operator (**=)', + ), // Identified in PHP < 5.6 icw PHPCS < 2.6.0 as T_MULTIPLY + T_MUL_EQUAL. + 'T_SPACESHIP' => array( + '5.6' => false, + '7.0' => true, + 'description' => 'spaceship operator (<=>)', + ), // Identified in PHP < 7.0 icw PHPCS < 2.5.1 as T_IS_SMALLER_OR_EQUAL + T_GREATER_THAN. + 'T_COALESCE' => array( + '5.6' => false, + '7.0' => true, + 'description' => 'null coalescing operator (??)', + ), // Identified in PHP < 7.0 icw PHPCS < 2.6.2 as T_INLINE_THEN + T_INLINE_THEN. + 'T_COALESCE_EQUAL' => array( + '7.3' => false, + '7.4' => true, + 'description' => 'null coalesce equal operator (??=)', + ), // Identified in PHP < 7.0 icw PHPCS < 2.6.2 as T_INLINE_THEN + T_INLINE_THEN + T_EQUAL and between PHPCS 2.6.2 and PHPCS 2.8.1 as T_COALESCE + T_EQUAL. + ); + + + /** + * A list of new operators which are not recognized in older PHPCS versions. + * + * The array lists an alternative token to listen for. + * + * @since 7.0.3 + * + * @var array(string => int) + */ + protected $newOperatorsPHPCSCompat = array( + 'T_POW' => \T_MULTIPLY, + 'T_POW_EQUAL' => \T_MUL_EQUAL, + 'T_SPACESHIP' => \T_GREATER_THAN, + 'T_COALESCE' => \T_INLINE_THEN, + 'T_COALESCE_EQUAL' => \T_EQUAL, + ); + + /** + * Token translation table for older PHPCS versions. + * + * The 'before' index lists the token which would have to be directly before the + * token found for it to be one of the new operators. + * The 'real_token' index indicates which operator was found in that case. + * + * If the token combination has multi-layer complexity, such as is the case + * with T_COALESCE(_EQUAL), a 'callback' index is added instead pointing to a + * separate function which can determine whether this is the targetted token across + * PHP and PHPCS versions. + * + * {@internal 'before' was chosen rather than 'after' as that allowed for a 1-on-1 + * translation list with the current tokens.} + * + * @since 7.0.3 + * + * @var array(string => array(string => string)) + */ + protected $PHPCSCompatTranslate = array( + 'T_MULTIPLY' => array( + 'before' => 'T_MULTIPLY', + 'real_token' => 'T_POW', + ), + 'T_MUL_EQUAL' => array( + 'before' => 'T_MULTIPLY', + 'real_token' => 'T_POW_EQUAL', + ), + 'T_GREATER_THAN' => array( + 'before' => 'T_IS_SMALLER_OR_EQUAL', + 'real_token' => 'T_SPACESHIP', + ), + 'T_INLINE_THEN' => array( + 'callback' => 'isTCoalesce', + 'real_token' => 'T_COALESCE', + ), + 'T_EQUAL' => array( + 'callback' => 'isTCoalesceEqual', + 'real_token' => 'T_COALESCE_EQUAL', + ), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.6 + * + * @return array + */ + public function register() + { + $tokens = array(); + foreach ($this->newOperators as $token => $versions) { + if (\defined($token)) { + $tokens[] = constant($token); + } elseif (isset($this->newOperatorsPHPCSCompat[$token])) { + $tokens[] = $this->newOperatorsPHPCSCompat[$token]; + } + } + return $tokens; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.6 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenType = $tokens[$stackPtr]['type']; + + // Translate older PHPCS token combis for new operators to the actual operator. + if (isset($this->newOperators[$tokenType]) === false) { + if (isset($this->PHPCSCompatTranslate[$tokenType]) + && ((isset($this->PHPCSCompatTranslate[$tokenType]['before'], $tokens[$stackPtr - 1]) === true + && $tokens[$stackPtr - 1]['type'] === $this->PHPCSCompatTranslate[$tokenType]['before']) + || (isset($this->PHPCSCompatTranslate[$tokenType]['callback']) === true + && \call_user_func(array($this, $this->PHPCSCompatTranslate[$tokenType]['callback']), $tokens, $stackPtr) === true)) + ) { + $tokenType = $this->PHPCSCompatTranslate[$tokenType]['real_token']; + } + } elseif ($tokenType === 'T_COALESCE') { + // Make sure that T_COALESCE is not confused with T_COALESCE_EQUAL. + if (isset($tokens[($stackPtr + 1)]) !== false && $tokens[($stackPtr + 1)]['code'] === \T_EQUAL) { + // Ignore as will be dealt with via the T_EQUAL token. + return; + } + } + + // If the translation did not yield one of the tokens we are looking for, bow out. + if (isset($this->newOperators[$tokenType]) === false) { + return; + } + + $itemInfo = array( + 'name' => $tokenType, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newOperators[$itemInfo['name']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('description'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['description'] = $itemArray['description']; + + return $errorInfo; + } + + + /** + * Filter the error data before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + $data[0] = $errorInfo['description']; + return $data; + } + + + /** + * Callback function to determine whether a T_EQUAL token is really a T_COALESCE_EQUAL token. + * + * @since 7.1.2 + * + * @param array $tokens The token stack. + * @param int $stackPtr The current position in the token stack. + * + * @return bool + */ + private function isTCoalesceEqual($tokens, $stackPtr) + { + if ($tokens[$stackPtr]['code'] !== \T_EQUAL || isset($tokens[($stackPtr - 1)]) === false) { + // Function called for wrong token or token has no predecessor. + return false; + } + + if ($tokens[($stackPtr - 1)]['type'] === 'T_COALESCE') { + return true; + } + if ($tokens[($stackPtr - 1)]['type'] === 'T_INLINE_THEN' + && (isset($tokens[($stackPtr - 2)]) && $tokens[($stackPtr - 2)]['type'] === 'T_INLINE_THEN') + ) { + return true; + } + + return false; + } + + /** + * Callback function to determine whether a T_INLINE_THEN token is really a T_COALESCE token. + * + * @since 7.1.2 + * + * @param array $tokens The token stack. + * @param int $stackPtr The current position in the token stack. + * + * @return bool + */ + private function isTCoalesce($tokens, $stackPtr) + { + if ($tokens[$stackPtr]['code'] !== \T_INLINE_THEN || isset($tokens[($stackPtr - 1)]) === false) { + // Function called for wrong token or token has no predecessor. + return false; + } + + if ($tokens[($stackPtr - 1)]['code'] === \T_INLINE_THEN) { + // Make sure not to confuse it with the T_COALESCE_EQUAL token. + if (isset($tokens[($stackPtr + 1)]) === false || $tokens[($stackPtr + 1)]['code'] !== \T_EQUAL) { + return true; + } + } + + return false; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/NewShortTernarySniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/NewShortTernarySniff.php new file mode 100644 index 00000000..b65da597 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/NewShortTernarySniff.php @@ -0,0 +1,73 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Operators; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect usage of the short ternary (elvis) operator as introduced in PHP 5.3. + * + * Performs checks on ternary operators, specifically that the middle expression + * is not omitted for versions that don't support this. + * + * PHP version 5.3 + * + * @link https://www.php.net/manual/en/migration53.new-features.php + * @link https://www.php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary + * + * @since 7.0.0 + * @since 7.0.8 This sniff now throws an error instead of a warning. + * @since 9.0.0 Renamed from `TernaryOperatorsSniff` to `NewShortTernarySniff`. + */ +class NewShortTernarySniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + return array(\T_INLINE_THEN); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.2') === false) { + return; + } + + if ($this->isShortTernary($phpcsFile, $stackPtr) === false) { + return; + } + + $phpcsFile->addError( + 'Middle may not be omitted from ternary operators in PHP < 5.3', + $stackPtr, + 'MiddleMissing' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/RemovedTernaryAssociativitySniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/RemovedTernaryAssociativitySniff.php new file mode 100644 index 00000000..21eca02b --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/RemovedTernaryAssociativitySniff.php @@ -0,0 +1,157 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Operators; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * The left-associativity of the ternary operator is deprecated in PHP 7.4 and + * removed in PHP 8.0. + * + * PHP version 7.4 + * PHP version 8.0 + * + * @link https://www.php.net/manual/en/migration74.deprecated.php#migration74.deprecated.core.nested-ternary + * @link https://wiki.php.net/rfc/ternary_associativity + * @link https://github.com/php/php-src/pull/4017 + * + * @since 9.2.0 + */ +class RemovedTernaryAssociativitySniff extends Sniff +{ + + /** + * List of tokens with a lower operator precedence than ternary. + * + * @since 9.2.0 + * + * @var array + */ + private $tokensWithLowerPrecedence = array( + 'T_YIELD_FROM' => true, + 'T_YIELD' => true, + 'T_LOGICAL_AND' => true, + 'T_LOGICAL_OR' => true, + 'T_LOGICAL_XOR' => true, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + return array(\T_INLINE_THEN); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $endOfStatement = PHPCSHelper::findEndOfStatement($phpcsFile, $stackPtr); + if ($tokens[$endOfStatement]['code'] !== \T_SEMICOLON + && $tokens[$endOfStatement]['code'] !== \T_COLON + && $tokens[$endOfStatement]['code'] !== \T_COMMA + && $tokens[$endOfStatement]['code'] !== \T_DOUBLE_ARROW + && $tokens[$endOfStatement]['code'] !== \T_OPEN_TAG + && $tokens[$endOfStatement]['code'] !== \T_CLOSE_TAG + ) { + // End of statement is last non-empty before close brace, so make sure we examine that token too. + ++$endOfStatement; + } + + $ternaryCount = 0; + $elseCount = 0; + $shortTernaryCount = 0; + + // Start at $stackPtr so we don't need duplicate code for short ternary determination. + for ($i = $stackPtr; $i < $endOfStatement; $i++) { + if (($tokens[$i]['code'] === \T_OPEN_SHORT_ARRAY + || $tokens[$i]['code'] === \T_OPEN_SQUARE_BRACKET + || $tokens[$i]['code'] === \T_OPEN_CURLY_BRACKET) + && isset($tokens[$i]['bracket_closer']) + ) { + // Skip over short arrays, array access keys and curlies. + $i = $tokens[$i]['bracket_closer']; + continue; + } + + if ($tokens[$i]['code'] === \T_OPEN_PARENTHESIS + && isset($tokens[$i]['parenthesis_closer']) + ) { + // Skip over anything between parentheses. + $i = $tokens[$i]['parenthesis_closer']; + continue; + } + + // Check for operators with lower operator precedence. + if (isset(Tokens::$assignmentTokens[$tokens[$i]['code']]) + || isset($this->tokensWithLowerPrecedence[$tokens[$i]['code']]) + ) { + break; + } + + if ($tokens[$i]['code'] === \T_INLINE_THEN) { + ++$ternaryCount; + + if ($this->isShortTernary($phpcsFile, $i) === true) { + ++$shortTernaryCount; + } + + continue; + } + + if ($tokens[$i]['code'] === \T_INLINE_ELSE) { + if (($ternaryCount - $elseCount) >= 2) { + // This is the `else` for a ternary in the middle part of a previous ternary. + --$ternaryCount; + } else { + ++$elseCount; + } + continue; + } + } + + if ($ternaryCount > 1 && $ternaryCount === $elseCount && $ternaryCount > $shortTernaryCount) { + $message = 'The left-associativity of the ternary operator has been deprecated in PHP 7.4'; + $isError = false; + if ($this->supportsAbove('8.0') === true) { + $message .= ' and removed in PHP 8.0'; + $isError = true; + } + + $message .= '. Multiple consecutive ternaries detected. Use parenthesis to clarify the order in which the operations should be executed'; + + $this->addMessage($phpcsFile, $message, $stackPtr, $isError); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/ForbiddenGetClassNullSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/ForbiddenGetClassNullSniff.php new file mode 100644 index 00000000..30452a09 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/ForbiddenGetClassNullSniff.php @@ -0,0 +1,84 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect: Passing `null` to `get_class()` is no longer allowed as of PHP 7.2. + * This will now result in an `E_WARNING` being thrown. + * + * PHP version 7.2 + * + * @link https://wiki.php.net/rfc/get_class_disallow_null_parameter + * @link https://www.php.net/manual/en/function.get-class.php#refsect1-function.get-class-changelog + * + * @since 9.0.0 + */ +class ForbiddenGetClassNullSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * @since 9.0.0 + * + * @var array + */ + protected $targetFunctions = array( + 'get_class' => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('7.2') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[1]) === false) { + return; + } + + if ($parameters[1]['raw'] !== 'null') { + return; + } + + $phpcsFile->addError( + 'Passing "null" as the $object to get_class() is not allowed since PHP 7.2.', + $parameters[1]['start'], + 'Found' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/ForbiddenStripTagsSelfClosingXHTMLSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/ForbiddenStripTagsSelfClosingXHTMLSniff.php new file mode 100644 index 00000000..9ecae5c8 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/ForbiddenStripTagsSelfClosingXHTMLSniff.php @@ -0,0 +1,113 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; + +/** + * Since PHP 5.3.4, `strip_tags()` ignores self-closing XHTML tags in allowable_tags + * + * PHP version 5.3.4 + * + * @link https://www.php.net/manual/en/function.strip-tags.php#refsect1-function.strip-tags-changelog + * + * @since 9.3.0 + */ +class ForbiddenStripTagsSelfClosingXHTMLSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * @since 9.3.0 + * + * @var array + */ + protected $targetFunctions = array( + 'strip_tags' => true, + ); + + /** + * Text string tokens to examine. + * + * @since 9.3.0 + * + * @var array + */ + private $textStringTokens = array( + \T_CONSTANT_ENCAPSED_STRING => true, + \T_DOUBLE_QUOTED_STRING => true, + \T_INLINE_HTML => true, + \T_HEREDOC => true, + \T_NOWDOC => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('5.4') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[2]) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $targetParam = $parameters[2]; + for ($i = $targetParam['start']; $i <= $targetParam['end']; $i++) { + if ($tokens[$i]['code'] === \T_STRING + || $tokens[$i]['code'] === \T_VARIABLE + ) { + // Variable, constant, function call. Ignore as undetermined. + return; + } + + if (isset($this->textStringTokens[$tokens[$i]['code']]) === true + && strpos($tokens[$i]['content'], '/>') !== false + ) { + + $phpcsFile->addError( + 'Self-closing XHTML tags are ignored. Only non-self-closing tags should be used in the strip_tags() $allowable_tags parameter since PHP 5.3.4. Found: %s', + $i, + 'Found', + array($targetParam['raw']) + ); + + // Only throw one error per function call. + return; + } + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewArrayReduceInitialTypeSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewArrayReduceInitialTypeSniff.php new file mode 100644 index 00000000..8045ac8a --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewArrayReduceInitialTypeSniff.php @@ -0,0 +1,116 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; + +/** + * In PHP 5.2 and lower, the `$initial` parameter for `array_reduce()` had to be an integer. + * + * PHP version 5.3 + * + * @link https://www.php.net/manual/en/migration53.other.php#migration53.other + * @link https://www.php.net/manual/en/function.array-reduce.php#refsect1-function.array-reduce-changelog + * + * @since 9.0.0 + */ +class NewArrayReduceInitialTypeSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * @since 9.0.0 + * + * @var array + */ + protected $targetFunctions = array( + 'array_reduce' => true, + ); + + /** + * Tokens which, for the purposes of this sniff, indicate that there is + * a variable element to the value passed. + * + * @since 9.0.0 + * + * @var array + */ + private $variableValueTokens = array( + \T_VARIABLE, + \T_STRING, + \T_SELF, + \T_PARENT, + \T_STATIC, + \T_DOUBLE_QUOTED_STRING, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('5.2') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[3]) === false) { + return; + } + + $targetParam = $parameters[3]; + if ($this->isNumber($phpcsFile, $targetParam['start'], $targetParam['end'], true) !== false) { + return; + } + + if ($this->isNumericCalculation($phpcsFile, $targetParam['start'], $targetParam['end']) === true) { + return; + } + + $error = 'Passing a non-integer as the value for $initial to array_reduce() is not supported in PHP 5.2 or lower.'; + if ($phpcsFile->findNext($this->variableValueTokens, $targetParam['start'], ($targetParam['end'] + 1)) === false) { + $phpcsFile->addError( + $error . ' Found %s', + $targetParam['start'], + 'InvalidTypeFound', + array($targetParam['raw']) + ); + } else { + $phpcsFile->addWarning( + $error . ' Variable value found. Found %s', + $targetParam['start'], + 'VariableFound', + array($targetParam['raw']) + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewFopenModesSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewFopenModesSniff.php new file mode 100644 index 00000000..83299822 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewFopenModesSniff.php @@ -0,0 +1,119 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; + +/** + * Check for valid values for the `fopen()` `$mode` parameter. + * + * PHP version 5.2+ + * + * @link https://www.php.net/manual/en/function.fopen.php#refsect1-function.fopen-changelog + * + * @since 9.0.0 + */ +class NewFopenModesSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * @since 9.0.0 + * + * @var array + */ + protected $targetFunctions = array( + 'fopen' => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + // Version used here should be (above) the highest version from the `newModes` control, + // structure below, i.e. the last PHP version in which a new mode was introduced. + return ($this->supportsBelow('7.1') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[2]) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $targetParam = $parameters[2]; + $errors = array(); + + for ($i = $targetParam['start']; $i <= $targetParam['end']; $i++) { + if ($tokens[$i]['code'] !== \T_CONSTANT_ENCAPSED_STRING) { + continue; + } + + if (strpos($tokens[$i]['content'], 'c+') !== false && $this->supportsBelow('5.2.5')) { + $errors['cplusFound'] = array( + 'c+', + '5.2.5', + $targetParam['raw'], + ); + } elseif (strpos($tokens[$i]['content'], 'c') !== false && $this->supportsBelow('5.2.5')) { + $errors['cFound'] = array( + 'c', + '5.2.5', + $targetParam['raw'], + ); + } + + if (strpos($tokens[$i]['content'], 'e') !== false && $this->supportsBelow('7.0.15')) { + $errors['eFound'] = array( + 'e', + '7.0.15', + $targetParam['raw'], + ); + } + } + + if (empty($errors) === true) { + return; + } + + foreach ($errors as $errorCode => $errorData) { + $phpcsFile->addError( + 'Passing "%s" as the $mode to fopen() is not supported in PHP %s or lower. Found %s', + $targetParam['start'], + $errorCode, + $errorData + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewHTMLEntitiesEncodingDefaultSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewHTMLEntitiesEncodingDefaultSniff.php new file mode 100644 index 00000000..18895565 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewHTMLEntitiesEncodingDefaultSniff.php @@ -0,0 +1,92 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; + +/** + * As of PHP 5.4, the default character set for `htmlspecialchars()`, `htmlentities()` + * and `html_entity_decode()` is now `UTF-8`, instead of `ISO-8859-1`. + * + * PHP version 5.4 + * + * @link https://www.php.net/manual/en/migration54.other.php + * @link https://www.php.net/manual/en/function.html-entity-decode.php#refsect1-function.html-entity-decode-changelog + * @link https://www.php.net/manual/en/function.htmlentities.php#refsect1-function.htmlentities-changelog + * @link https://www.php.net/manual/en/function.htmlspecialchars.php#refsect1-function.htmlspecialchars-changelog + * + * @since 9.3.0 + */ +class NewHTMLEntitiesEncodingDefaultSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * Key is the function name, value the 1-based parameter position of + * the $encoding parameter. + * + * @since 9.3.0 + * + * @var array + */ + protected $targetFunctions = array( + 'html_entity_decode' => 3, + 'htmlentities' => 3, + 'htmlspecialchars' => 3, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * Note: This sniff should only trigger errors when both PHP 5.3 or lower, + * as well as PHP 5.4 or higher need to be supported within the application. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('5.3') === false || $this->supportsAbove('5.4') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + $functionLC = strtolower($functionName); + if (isset($parameters[$this->targetFunctions[$functionLC]]) === true) { + return; + } + + $phpcsFile->addError( + 'The default value of the $encoding parameter for %s() was changed from ISO-8859-1 to UTF-8 in PHP 5.4. For cross-version compatibility, the $encoding parameter should be explicitly set.', + $stackPtr, + 'NotSet', + array($functionName) + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewHashAlgorithmsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewHashAlgorithmsSniff.php new file mode 100644 index 00000000..297f84ec --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewHashAlgorithmsSniff.php @@ -0,0 +1,185 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect the use of newly introduced hash algorithms. + * + * PHP version 5.2+ + * + * @link https://www.php.net/manual/en/function.hash-algos.php#refsect1-function.hash-algos-changelog + * + * @since 7.0.7 + * @since 7.1.0 Now extends the `AbstractNewFeatureSniff` instead of the base `Sniff` class.. + */ +class NewHashAlgorithmsSniff extends AbstractNewFeatureSniff +{ + /** + * A list of new hash algorithms, not present in older versions. + * + * The array lists : version number with false (not present) or true (present). + * If's sufficient to list the first version where the hash algorithm appears. + * + * @since 7.0.7 + * + * @var array(string => array(string => bool)) + */ + protected $newAlgorithms = array( + 'md2' => array( + '5.2' => false, + '5.3' => true, + ), + 'ripemd256' => array( + '5.2' => false, + '5.3' => true, + ), + 'ripemd320' => array( + '5.2' => false, + '5.3' => true, + ), + 'salsa10' => array( + '5.2' => false, + '5.3' => true, + ), + 'salsa20' => array( + '5.2' => false, + '5.3' => true, + ), + 'snefru256' => array( + '5.2' => false, + '5.3' => true, + ), + 'sha224' => array( + '5.2' => false, + '5.3' => true, + ), + 'joaat' => array( + '5.3' => false, + '5.4' => true, + ), + 'fnv132' => array( + '5.3' => false, + '5.4' => true, + ), + 'fnv164' => array( + '5.3' => false, + '5.4' => true, + ), + 'gost-crypto' => array( + '5.5' => false, + '5.6' => true, + ), + + 'sha512/224' => array( + '7.0' => false, + '7.1' => true, + ), + 'sha512/256' => array( + '7.0' => false, + '7.1' => true, + ), + 'sha3-224' => array( + '7.0' => false, + '7.1' => true, + ), + 'sha3-256' => array( + '7.0' => false, + '7.1' => true, + ), + 'sha3-384' => array( + '7.0' => false, + '7.1' => true, + ), + 'sha3-512' => array( + '7.0' => false, + '7.1' => true, + ), + 'crc32c' => array( + '7.3' => false, + '7.4' => true, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.7 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.7 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $algo = $this->getHashAlgorithmParameter($phpcsFile, $stackPtr); + if (empty($algo) || \is_string($algo) === false) { + return; + } + + // Bow out if not one of the algorithms we're targetting. + if (isset($this->newAlgorithms[$algo]) === false) { + return; + } + + // Check if the algorithm used is new. + $itemInfo = array( + 'name' => $algo, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newAlgorithms[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The %s hash algorithm is not present in PHP version %s or earlier'; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewIDNVariantDefaultSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewIDNVariantDefaultSniff.php new file mode 100644 index 00000000..2c9748ca --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewIDNVariantDefaultSniff.php @@ -0,0 +1,91 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; + +/** + * The default value for the `$variant` parameter has changed from `INTL_IDNA_VARIANT_2003` + * to `INTL_IDNA_VARIANT_UTS46` in PHP 7.4. + * + * PHP version 7.4 + * + * @link https://www.php.net/manual/en/migration74.incompatible.php#migration74.incompatible.intl + * @link https://wiki.php.net/rfc/deprecate-and-remove-intl_idna_variant_2003 + * @link https://www.php.net/manual/en/function.idn-to-ascii.php + * @link https://www.php.net/manual/en/function.idn-to-utf8.php + * + * @since 9.3.0 + */ +class NewIDNVariantDefaultSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * Key is the function name, value the 1-based parameter position of + * the $variant parameter. + * + * @since 9.3.0 + * + * @var array + */ + protected $targetFunctions = array( + 'idn_to_ascii' => 3, + 'idn_to_utf8' => 3, + ); + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * Note: This sniff should only trigger errors when both PHP 7.3 or lower, + * as well as PHP 7.4 or higher need to be supported within the application. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('7.3') === false || $this->supportsAbove('7.4') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + $functionLC = strtolower($functionName); + if (isset($parameters[$this->targetFunctions[$functionLC]]) === true) { + return; + } + + $error = 'The default value of the %s() $variant parameter has changed from INTL_IDNA_VARIANT_2003 to INTL_IDNA_VARIANT_UTS46 in PHP 7.4. For optimal cross-version compatibility, the $variant parameter should be explicitly set.'; + $phpcsFile->addError( + $error, + $stackPtr, + 'NotSet', + array($functionName) + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewIconvMbstringCharsetDefaultSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewIconvMbstringCharsetDefaultSniff.php new file mode 100644 index 00000000..51cc894e --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewIconvMbstringCharsetDefaultSniff.php @@ -0,0 +1,231 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect calls to Iconv and Mbstring functions with the optional `$charset`/`$encoding` parameter not set. + * + * The default value for the iconv `$charset` and the MbString $encoding` parameters was changed + * in PHP 5.6 to the value of `default_charset`, which defaults to `UTF-8`. + * + * Previously, the iconv functions would default to the value of `iconv.internal_encoding`; + * The Mbstring functions would default to the return value of `mb_internal_encoding()`. + * In both case, this would normally come down to `ISO-8859-1`. + * + * PHP version 5.6 + * + * @link https://www.php.net/manual/en/migration56.new-features.php#migration56.new-features.default-encoding + * @link https://www.php.net/manual/en/migration56.deprecated.php#migration56.deprecated.iconv-mbstring-encoding + * @link https://wiki.php.net/rfc/default_encoding + * + * @since 9.3.0 + */ +class NewIconvMbstringCharsetDefaultSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * Only those functions where the charset/encoding parameter is optional need to be listed. + * + * Key is the function name, value the 1-based parameter position of + * the $charset/$encoding parameter. + * + * @since 9.3.0 + * + * @var array + */ + protected $targetFunctions = array( + 'iconv_mime_decode_headers' => 3, + 'iconv_mime_decode' => 3, + 'iconv_mime_encode' => 3, // Special case. + 'iconv_strlen' => 2, + 'iconv_strpos' => 4, + 'iconv_strrpos' => 3, + 'iconv_substr' => 4, + + 'mb_check_encoding' => 2, + 'mb_chr' => 2, + 'mb_convert_case' => 3, + 'mb_convert_encoding' => 3, + 'mb_convert_kana' => 3, + 'mb_decode_numericentity' => 3, + 'mb_encode_numericentity' => 3, + 'mb_ord' => 2, + 'mb_scrub' => 2, + 'mb_strcut' => 4, + 'mb_stripos' => 4, + 'mb_stristr' => 4, + 'mb_strlen' => 2, + 'mb_strpos' => 4, + 'mb_strrchr' => 4, + 'mb_strrichr' => 4, + 'mb_strripos' => 4, + 'mb_strrpos' => 4, + 'mb_strstr' => 4, + 'mb_strtolower' => 2, + 'mb_strtoupper' => 2, + 'mb_strwidth' => 2, + 'mb_substr_count' => 3, + 'mb_substr' => 4, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * Note: This sniff should only trigger errors when both PHP 5.5 or lower, + * as well as PHP 5.6 or higher need to be supported within the application. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('5.5') === false || $this->supportsAbove('5.6') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + $functionLC = strtolower($functionName); + if ($functionLC === 'iconv_mime_encode') { + // Special case the iconv_mime_encode() function. + return $this->processIconvMimeEncode($phpcsFile, $stackPtr, $functionName, $parameters); + } + + if (isset($parameters[$this->targetFunctions[$functionLC]]) === true) { + return; + } + + $paramName = '$encoding'; + if (strpos($functionLC, 'iconv_') === 0) { + $paramName = '$charset'; + } elseif ($functionLC === 'mb_convert_encoding') { + $paramName = '$from_encoding'; + } + + $error = 'The default value of the %1$s parameter for %2$s() was changed from ISO-8859-1 to UTF-8 in PHP 5.6. For cross-version compatibility, the %1$s parameter should be explicitly set.'; + $data = array( + $paramName, + $functionName, + ); + + $phpcsFile->addError($error, $stackPtr, 'NotSet', $data); + } + + /** + * Process the parameters of a matched call to the iconv_mime_encode() function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processIconvMimeEncode(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + $error = 'The default value of the %s parameter index for iconv_mime_encode() was changed from ISO-8859-1 to UTF-8 in PHP 5.6. For cross-version compatibility, the %s should be explicitly set.'; + + $functionLC = strtolower($functionName); + if (isset($parameters[$this->targetFunctions[$functionLC]]) === false) { + $phpcsFile->addError( + $error, + $stackPtr, + 'PreferencesNotSet', + array( + '$preferences[\'input/output-charset\']', + '$preferences[\'input-charset\'] and $preferences[\'output-charset\'] indexes', + ) + ); + + return; + } + + $tokens = $phpcsFile->getTokens(); + $targetParam = $parameters[$this->targetFunctions[$functionLC]]; + $firstNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $targetParam['start'], ($targetParam['end'] + 1), true); + if ($firstNonEmpty === false) { + // Parse error or live coding. + return; + } + + if ($tokens[$firstNonEmpty]['code'] === \T_ARRAY + || $tokens[$firstNonEmpty]['code'] === \T_OPEN_SHORT_ARRAY + ) { + $hasInputCharset = preg_match('`([\'"])input-charset\1\s*=>`', $targetParam['raw']); + $hasOutputCharset = preg_match('`([\'"])output-charset\1\s*=>`', $targetParam['raw']); + if ($hasInputCharset === 1 && $hasOutputCharset === 1) { + // Both input as well as output charset are set. + return; + } + + if ($hasInputCharset !== 1) { + $phpcsFile->addError( + $error, + $firstNonEmpty, + 'InputPreferenceNotSet', + array( + '$preferences[\'input-charset\']', + '$preferences[\'input-charset\'] index', + ) + ); + } + + if ($hasOutputCharset !== 1) { + $phpcsFile->addError( + $error, + $firstNonEmpty, + 'OutputPreferenceNotSet', + array( + '$preferences[\'output-charset\']', + '$preferences[\'output-charset\'] index', + ) + ); + } + + return; + } + + // The $preferences parameter was passed, but it was a variable/constant/output of a function call. + $phpcsFile->addWarning( + $error, + $firstNonEmpty, + 'Undetermined', + array( + '$preferences[\'input/output-charset\']', + '$preferences[\'input-charset\'] and $preferences[\'output-charset\'] indexes', + ) + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewNegativeStringOffsetSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewNegativeStringOffsetSniff.php new file mode 100644 index 00000000..f2aea60e --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewNegativeStringOffsetSniff.php @@ -0,0 +1,129 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect negative string offsets as parameters passed to functions where this + * was not allowed prior to PHP 7.1. + * + * PHP version 7.1 + * + * @link https://wiki.php.net/rfc/negative-string-offsets + * + * @since 9.0.0 + */ +class NewNegativeStringOffsetSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * @since 9.0.0 + * + * @var array Function name => 1-based parameter offset of the affected parameters => parameter name. + */ + protected $targetFunctions = array( + 'file_get_contents' => array( + 4 => 'offset', + ), + 'grapheme_extract' => array( + 4 => 'start', + ), + 'grapheme_stripos' => array( + 3 => 'offset', + ), + 'grapheme_strpos' => array( + 3 => 'offset', + ), + 'iconv_strpos' => array( + 3 => 'offset', + ), + 'mb_ereg_search_setpos' => array( + 1 => 'position', + ), + 'mb_strimwidth' => array( + 2 => 'start', + 3 => 'width', + ), + 'mb_stripos' => array( + 3 => 'offset', + ), + 'mb_strpos' => array( + 3 => 'offset', + ), + 'stripos' => array( + 3 => 'offset', + ), + 'strpos' => array( + 3 => 'offset', + ), + 'substr_count' => array( + 3 => 'offset', + 4 => 'length', + ), + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('7.0') === false); + } + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + $functionLC = strtolower($functionName); + foreach ($this->targetFunctions[$functionLC] as $pos => $name) { + if (isset($parameters[$pos]) === false) { + continue; + } + + $targetParam = $parameters[$pos]; + + if ($this->isNegativeNumber($phpcsFile, $targetParam['start'], $targetParam['end']) === false) { + continue; + } + + $phpcsFile->addError( + 'Negative string offsets were not supported for the $%s parameter in %s() in PHP 7.0 or lower. Found %s', + $targetParam['start'], + 'Found', + array( + $name, + $functionName, + $targetParam['raw'], + ) + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPCREModifiersSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPCREModifiersSniff.php new file mode 100644 index 00000000..65339e50 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPCREModifiersSniff.php @@ -0,0 +1,127 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\Sniffs\ParameterValues\RemovedPCREModifiersSniff; +use PHP_CodeSniffer_File as File; + +/** + * Check for the use of newly added regex modifiers for PCRE functions. + * + * Initially just checks for the PHP 7.2 new `J` modifier. + * + * PHP version 7.2+ + * + * @link https://www.php.net/manual/en/reference.pcre.pattern.modifiers.php + * @link https://www.php.net/manual/en/migration72.new-features.php#migration72.new-features.pcre + * + * @since 8.2.0 + * @since 9.0.0 Renamed from `PCRENewModifiersSniff` to `NewPCREModifiersSniff`. + */ +class NewPCREModifiersSniff extends RemovedPCREModifiersSniff +{ + + /** + * Functions to check for. + * + * @since 8.2.0 + * + * @var array + */ + protected $targetFunctions = array( + 'preg_filter' => true, + 'preg_grep' => true, + 'preg_match_all' => true, + 'preg_match' => true, + 'preg_replace_callback_array' => true, + 'preg_replace_callback' => true, + 'preg_replace' => true, + 'preg_split' => true, + ); + + /** + * Array listing newly introduced regex modifiers. + * + * The key should be the modifier (case-sensitive!). + * The value should be the PHP version in which the modifier was introduced. + * + * @since 8.2.0 + * + * @var array + */ + protected $newModifiers = array( + 'J' => array( + '7.1' => false, + '7.2' => true, + ), + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 8.2.0 + * + * @return bool + */ + protected function bowOutEarly() + { + // Version used here should be the highest version from the `$newModifiers` array, + // i.e. the last PHP version in which a new modifier was introduced. + return ($this->supportsBelow('7.2') === false); + } + + + /** + * Examine the regex modifier string. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param string $functionName The function which contained the pattern. + * @param string $modifiers The regex modifiers found. + * + * @return void + */ + protected function examineModifiers(File $phpcsFile, $stackPtr, $functionName, $modifiers) + { + $error = 'The PCRE regex modifier "%s" is not present in PHP version %s or earlier'; + + foreach ($this->newModifiers as $modifier => $versionArray) { + if (strpos($modifiers, $modifier) === false) { + continue; + } + + $notInVersion = ''; + foreach ($versionArray as $version => $present) { + if ($notInVersion === '' && $present === false + && $this->supportsBelow($version) === true + ) { + $notInVersion = $version; + } + } + + if ($notInVersion === '') { + continue; + } + + $errorCode = $modifier . 'ModifierFound'; + $data = array( + $modifier, + $notInVersion, + ); + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPackFormatSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPackFormatSniff.php new file mode 100644 index 00000000..7e42f3e9 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPackFormatSniff.php @@ -0,0 +1,132 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; + +/** + * Check for valid values for the `$format` passed to `pack()`. + * + * PHP version 5.4+ + * + * @link https://www.php.net/manual/en/function.pack.php#refsect1-function.pack-changelog + * + * @since 9.0.0 + */ +class NewPackFormatSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * @since 9.0.0 + * + * @var array + */ + protected $targetFunctions = array( + 'pack' => true, + ); + + /** + * List of new format character codes added to pack(). + * + * @since 9.0.0 + * + * @var array Regex pattern => Version array. + */ + protected $newFormats = array( + '`([Z])`' => array( + '5.4' => false, + '5.5' => true, + ), + '`([qQJP])`' => array( + '5.6.2' => false, + '5.6.3' => true, + ), + '`([eEgG])`' => array( + '7.0.14' => false, + '7.0.15' => true, // And 7.1.1. + ), + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('7.1') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[1]) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $targetParam = $parameters[1]; + + for ($i = $targetParam['start']; $i <= $targetParam['end']; $i++) { + if ($tokens[$i]['code'] !== \T_CONSTANT_ENCAPSED_STRING + && $tokens[$i]['code'] !== \T_DOUBLE_QUOTED_STRING + ) { + continue; + } + + $content = $tokens[$i]['content']; + if ($tokens[$i]['code'] === \T_DOUBLE_QUOTED_STRING) { + $content = $this->stripVariables($content); + } + + foreach ($this->newFormats as $pattern => $versionArray) { + if (preg_match($pattern, $content, $matches) !== 1) { + continue; + } + + foreach ($versionArray as $version => $present) { + if ($present === false && $this->supportsBelow($version) === true) { + $phpcsFile->addError( + 'Passing the $format(s) "%s" to pack() is not supported in PHP %s or lower. Found %s', + $targetParam['start'], + 'NewFormatFound', + array( + $matches[1], + $version, + $targetParam['raw'], + ) + ); + continue 2; + } + } + } + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPasswordAlgoConstantValuesSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPasswordAlgoConstantValuesSniff.php new file mode 100644 index 00000000..94a1360d --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPasswordAlgoConstantValuesSniff.php @@ -0,0 +1,125 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * The constant value of the password hash algorithm constants has changed in PHP 7.4. + * + * Applications using the constants `PASSWORD_DEFAULT`, `PASSWORD_BCRYPT`, + * `PASSWORD_ARGON2I`, and `PASSWORD_ARGON2ID` will continue to function correctly. + * Using an integer will still work, but will produce a deprecation warning. + * + * PHP version 7.4 + * + * @link https://www.php.net/manual/en/migration74.incompatible.php#migration74.incompatible.core.password-algorithm-constants + * @link https://wiki.php.net/rfc/password_registry + * + * @since 9.3.0 + */ +class NewPasswordAlgoConstantValuesSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * Key is the function name, value the 1-based parameter position of + * the $algo parameter. + * + * @since 9.3.0 + * + * @var array + */ + protected $targetFunctions = array( + 'password_hash' => 2, + 'password_needs_rehash' => 2, + ); + + /** + * Tokens types which indicate that the parameter passed is not the PHP native constant. + * + * @since 9.3.0 + * + * @var array + */ + private $invalidTokenTypes = array( + \T_NULL => true, + \T_TRUE => true, + \T_FALSE => true, + \T_LNUMBER => true, + \T_DNUMBER => true, + \T_CONSTANT_ENCAPSED_STRING => true, + \T_DOUBLE_QUOTED_STRING => true, + \T_HEREDOC => true, + \T_NOWDOC => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('7.4') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + $functionLC = strtolower($functionName); + if (isset($parameters[$this->targetFunctions[$functionLC]]) === false) { + return; + } + + $targetParam = $parameters[$this->targetFunctions[$functionLC]]; + $tokens = $phpcsFile->getTokens(); + + for ($i = $targetParam['start']; $i <= $targetParam['end']; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + if (isset($this->invalidTokenTypes[$tokens[$i]['code']]) === true) { + $phpcsFile->addWarning( + 'The value of the password hash algorithm constants has changed in PHP 7.4. Pass a PHP native constant to the %s() function instead of using the value of the constant. Found: %s', + $stackPtr, + 'NotAlgoConstant', + array( + $functionName, + $targetParam['raw'], + ) + ); + + break; + } + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewProcOpenCmdArraySniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewProcOpenCmdArraySniff.php new file mode 100644 index 00000000..4e9f1500 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewProcOpenCmdArraySniff.php @@ -0,0 +1,136 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * As of PHP 7.4, `proc_open()` now also accepts an array instead of a string for the command. + * + * In that case, the process will be opened directly (without going through a shell) and + * PHP will take care of any necessary argument escaping. + * + * PHP version 7.4 + * + * @link https://www.php.net/manual/en/migration74.new-features.php#migration74.new-features.standard.proc-open + * @link https://www.php.net/manual/en/function.proc-open.php + * + * @since 9.3.0 + */ +class NewProcOpenCmdArraySniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * @since 9.3.0 + * + * @var array + */ + protected $targetFunctions = array( + 'proc_open' => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return false; + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[1]) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $targetParam = $parameters[1]; + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $targetParam['start'], $targetParam['end'], true); + + if ($nextNonEmpty === false) { + // Shouldn't be possible. + return; + } + + if ($tokens[$nextNonEmpty]['code'] !== \T_ARRAY + && $tokens[$nextNonEmpty]['code'] !== \T_OPEN_SHORT_ARRAY + ) { + // Not passed as an array. + return; + } + + if ($this->supportsBelow('7.3') === true) { + $phpcsFile->addError( + 'The proc_open() function did not accept $cmd to be passed in array format in PHP 7.3 and earlier.', + $nextNonEmpty, + 'Found' + ); + } + + if ($this->supportsAbove('7.4') === true) { + if (strpos($targetParam['raw'], 'escapeshellarg(') === false) { + // Efficiency: prevent needlessly walking the array. + return; + } + + $items = $this->getFunctionCallParameters($phpcsFile, $nextNonEmpty); + + if (empty($items)) { + return; + } + + foreach ($items as $item) { + for ($i = $item['start']; $i <= $item['end']; $i++) { + if ($tokens[$i]['code'] !== \T_STRING + || $tokens[$i]['content'] !== 'escapeshellarg' + ) { + continue; + } + + // @todo Potential future enhancement: check if it's a call to the PHP native function. + + $phpcsFile->addWarning( + 'When passing proc_open() the $cmd parameter as an array, PHP will take care of any necessary argument escaping. Found: %s', + $i, + 'Invalid', + array($item['raw']) + ); + + // Only throw one error per array item. + break; + } + } + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewStripTagsAllowableTagsArraySniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewStripTagsAllowableTagsArraySniff.php new file mode 100644 index 00000000..9d9ede05 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewStripTagsAllowableTagsArraySniff.php @@ -0,0 +1,152 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * As of PHP 7.4, `strip_tags()` now also accepts an array of `$allowable_tags`. + * + * PHP version 7.4 + * + * @link https://www.php.net/manual/en/migration74.new-features.php#migration74.new-features.standard.strip-tags + * @link https://www.php.net/manual/en/function.strip-tags.php + * + * @since 9.3.0 + */ +class NewStripTagsAllowableTagsArraySniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * @since 9.3.0 + * + * @var array + */ + protected $targetFunctions = array( + 'strip_tags' => true, + ); + + /** + * Text string tokens to examine. + * + * @since 9.3.0 + * + * @var array + */ + private $textStringTokens = array( + \T_CONSTANT_ENCAPSED_STRING => true, + \T_DOUBLE_QUOTED_STRING => true, + \T_INLINE_HTML => true, + \T_HEREDOC => true, + \T_NOWDOC => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return false; + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[2]) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $targetParam = $parameters[2]; + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $targetParam['start'], $targetParam['end'], true); + + if ($nextNonEmpty === false) { + // Shouldn't be possible. + return; + } + + if ($tokens[$nextNonEmpty]['code'] !== \T_ARRAY + && $tokens[$nextNonEmpty]['code'] !== \T_OPEN_SHORT_ARRAY + ) { + // Not passed as a hard-coded array. + return; + } + + if ($this->supportsBelow('7.3') === true) { + $phpcsFile->addError( + 'The strip_tags() function did not accept $allowable_tags to be passed in array format in PHP 7.3 and earlier.', + $nextNonEmpty, + 'Found' + ); + } + + if ($this->supportsAbove('7.4') === true) { + if (strpos($targetParam['raw'], '>') === false) { + // Efficiency: prevent needlessly walking the array. + return; + } + + $items = $this->getFunctionCallParameters($phpcsFile, $nextNonEmpty); + + if (empty($items)) { + return; + } + + foreach ($items as $item) { + for ($i = $item['start']; $i <= $item['end']; $i++) { + if ($tokens[$i]['code'] === \T_STRING + || $tokens[$i]['code'] === \T_VARIABLE + ) { + // Variable, constant, function call. Ignore complete item as undetermined. + break; + } + + if (isset($this->textStringTokens[$tokens[$i]['code']]) === true + && strpos($tokens[$i]['content'], '>') !== false + ) { + + $phpcsFile->addWarning( + 'When passing strip_tags() the $allowable_tags parameter as an array, the tags should not be enclosed in <> brackets. Found: %s', + $i, + 'Invalid', + array($item['raw']) + ); + + // Only throw one error per array item. + break; + } + } + } + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedHashAlgorithmsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedHashAlgorithmsSniff.php new file mode 100644 index 00000000..83d4b8b3 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedHashAlgorithmsSniff.php @@ -0,0 +1,117 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractRemovedFeatureSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect the use of deprecated and removed hash algorithms. + * + * PHP version 5.4 + * + * @link https://www.php.net/manual/en/function.hash-algos.php#refsect1-function.hash-algos-changelog + * + * @since 5.5 + * @since 7.1.0 Now extends the `AbstractRemovedFeatureSniff` instead of the base `Sniff` class. + */ +class RemovedHashAlgorithmsSniff extends AbstractRemovedFeatureSniff +{ + + /** + * A list of removed hash algorithms, which were present in older versions. + * + * The array lists : version number with false (deprecated) and true (removed). + * If's sufficient to list the first version where the hash algorithm was deprecated/removed. + * + * @since 7.0.7 + * + * @var array(string => array(string => bool)) + */ + protected $removedAlgorithms = array( + 'salsa10' => array( + '5.4' => true, + ), + 'salsa20' => array( + '5.4' => true, + ), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $algo = $this->getHashAlgorithmParameter($phpcsFile, $stackPtr); + if (empty($algo) || \is_string($algo) === false) { + return; + } + + // Bow out if not one of the algorithms we're targetting. + if (isset($this->removedAlgorithms[$algo]) === false) { + return; + } + + $itemInfo = array( + 'name' => $algo, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->removedAlgorithms[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The %s hash algorithm is '; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedIconvEncodingSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedIconvEncodingSniff.php new file mode 100644 index 00000000..d7c7c663 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedIconvEncodingSniff.php @@ -0,0 +1,86 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect passing deprecated `$type` values to `iconv_get_encoding()`. + * + * "The iconv and mbstring configuration options related to encoding have been + * deprecated in favour of default_charset." + * + * {@internal It is unclear which mbstring functions should be targetted, so for now, + * only the iconv function is handled.} + * + * PHP version 5.6 + * + * @link https://www.php.net/manual/en/migration56.deprecated.php#migration56.deprecated.iconv-mbstring-encoding + * @link https://wiki.php.net/rfc/default_encoding + * + * @since 9.0.0 + */ +class RemovedIconvEncodingSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * @since 9.0.0 + * + * @var array + */ + protected $targetFunctions = array( + 'iconv_set_encoding' => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('5.6') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[1]) === false) { + return; + } + + $phpcsFile->addWarning( + 'All previously accepted values for the $type parameter of iconv_set_encoding() have been deprecated since PHP 5.6. Found %s', + $parameters[1]['start'], + 'DeprecatedValueFound', + $parameters[1]['raw'] + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedImplodeFlexibleParamOrderSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedImplodeFlexibleParamOrderSniff.php new file mode 100644 index 00000000..1ff0f90f --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedImplodeFlexibleParamOrderSniff.php @@ -0,0 +1,323 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Passing the `$glue` and `$pieces` parameters to `implode()` in reverse order has + * been deprecated in PHP 7.4. + * + * PHP version 7.4 + * + * @link https://www.php.net/manual/en/migration74.deprecated.php#migration74.deprecated.core.implode-reverse-parameters + * @link https://wiki.php.net/rfc/deprecations_php_7_4#implode_parameter_order_mix + * @link https://php.net/manual/en/function.implode.php + * + * @since 9.3.0 + */ +class RemovedImplodeFlexibleParamOrderSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * @since 9.3.0 + * + * @var array + */ + protected $targetFunctions = array( + 'implode' => true, + 'join' => true, + ); + + /** + * List of PHP native constants which should be recognized as text strings. + * + * @since 9.3.0 + * + * @var array + */ + private $constantStrings = array( + 'DIRECTORY_SEPARATOR' => true, + 'PHP_EOL' => true, + ); + + /** + * List of PHP native functions which should be recognized as returning an array. + * + * Note: The array_*() functions will always be taken into account. + * + * @since 9.3.0 + * + * @var array + */ + private $arrayFunctions = array( + 'compact' => true, + 'explode' => true, + 'range' => true, + ); + + /** + * List of PHP native array functions which should *not* be recognized as returning an array. + * + * @since 9.3.0 + * + * @var array + */ + private $arrayFunctionExceptions = array( + 'array_key_exists' => true, + 'array_key_first' => true, + 'array_key_last' => true, + 'array_multisort' => true, + 'array_pop' => true, + 'array_product' => true, + 'array_push' => true, + 'array_search' => true, + 'array_shift' => true, + 'array_sum' => true, + 'array_unshift' => true, + 'array_walk_recursive' => true, + 'array_walk' => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('7.4') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[2]) === false) { + // Only one parameter, this must be $pieces. Bow out. + return; + } + + $tokens = $phpcsFile->getTokens(); + + /* + * Examine the first parameter. + * If there is any indication that this is an array declaration, we have an error. + */ + + $targetParam = $parameters[1]; + $start = $targetParam['start']; + $end = ($targetParam['end'] + 1); + $isOnlyText = true; + + $firstNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $start, $end, true); + if ($firstNonEmpty === false) { + // Parse error. Shouldn't be possible. + return; + } + + if ($tokens[$firstNonEmpty]['code'] === \T_OPEN_PARENTHESIS) { + $start = ($firstNonEmpty + 1); + $end = $tokens[$firstNonEmpty]['parenthesis_closer']; + } + + $hasTernary = $phpcsFile->findNext(\T_INLINE_THEN, $start, $end); + if ($hasTernary !== false + && isset($tokens[$start]['nested_parenthesis'], $tokens[$hasTernary]['nested_parenthesis']) + && count($tokens[$start]['nested_parenthesis']) === count($tokens[$hasTernary]['nested_parenthesis']) + ) { + $start = ($hasTernary + 1); + } + + for ($i = $start; $i < $end; $i++) { + $tokenCode = $tokens[$i]['code']; + + if (isset(Tokens::$emptyTokens[$tokenCode])) { + continue; + } + + if ($tokenCode === \T_STRING && isset($this->constantStrings[$tokens[$i]['content']])) { + continue; + } + + if ($hasTernary !== false && $tokenCode === \T_INLINE_ELSE) { + continue; + } + + if (isset(Tokens::$stringTokens[$tokenCode]) === false) { + $isOnlyText = false; + } + + if ($tokenCode === \T_ARRAY || $tokenCode === \T_OPEN_SHORT_ARRAY || $tokenCode === \T_ARRAY_CAST) { + $this->throwNotice($phpcsFile, $stackPtr, $functionName); + return; + } + + if ($tokenCode === \T_STRING) { + /* + * Check for specific functions which return an array (i.e. $pieces). + */ + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), $end, true); + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS) { + continue; + } + + $nameLc = strtolower($tokens[$i]['content']); + if (isset($this->arrayFunctions[$nameLc]) === false + && (strpos($nameLc, 'array_') !== 0 + || isset($this->arrayFunctionExceptions[$nameLc]) === true) + ) { + continue; + } + + // Now make sure it's the PHP native function being called. + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), $start, true); + if ($tokens[$prevNonEmpty]['code'] === \T_DOUBLE_COLON + || $tokens[$prevNonEmpty]['code'] === \T_OBJECT_OPERATOR + ) { + // Method call, not a call to the PHP native function. + continue; + } + + if ($tokens[$prevNonEmpty]['code'] === \T_NS_SEPARATOR + && $tokens[$prevNonEmpty - 1]['code'] === \T_STRING + ) { + // Namespaced function. + continue; + } + + // Ok, so we know that there is an array function in the first param. + // 99.9% chance that this is $pieces, not $glue. + $this->throwNotice($phpcsFile, $stackPtr, $functionName); + return; + } + } + + if ($isOnlyText === true) { + // First parameter only contained text string tokens, i.e. glue. + return; + } + + /* + * Examine the second parameter. + */ + + $targetParam = $parameters[2]; + $start = $targetParam['start']; + $end = ($targetParam['end'] + 1); + + $firstNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $start, $end, true); + if ($firstNonEmpty === false) { + // Parse error. Shouldn't be possible. + return; + } + + if ($tokens[$firstNonEmpty]['code'] === \T_OPEN_PARENTHESIS) { + $start = ($firstNonEmpty + 1); + $end = $tokens[$firstNonEmpty]['parenthesis_closer']; + } + + $hasTernary = $phpcsFile->findNext(\T_INLINE_THEN, $start, $end); + if ($hasTernary !== false + && isset($tokens[$start]['nested_parenthesis'], $tokens[$hasTernary]['nested_parenthesis']) + && count($tokens[$start]['nested_parenthesis']) === count($tokens[$hasTernary]['nested_parenthesis']) + ) { + $start = ($hasTernary + 1); + } + + for ($i = $start; $i < $end; $i++) { + $tokenCode = $tokens[$i]['code']; + + if (isset(Tokens::$emptyTokens[$tokenCode])) { + continue; + } + + if ($tokenCode === \T_ARRAY || $tokenCode === \T_OPEN_SHORT_ARRAY || $tokenCode === \T_ARRAY_CAST) { + // Found an array, $pieces is second. + return; + } + + if ($tokenCode === \T_STRING && isset($this->constantStrings[$tokens[$i]['content']])) { + // One of the special cased, PHP native string constants found. + $this->throwNotice($phpcsFile, $stackPtr, $functionName); + return; + } + + if ($tokenCode === \T_STRING || $tokenCode === \T_VARIABLE) { + // Function call, constant or variable encountered. + // No matter what this is combined with, we won't be able to reliably determine the value. + return; + } + + if ($tokenCode === \T_CONSTANT_ENCAPSED_STRING + || $tokenCode === \T_DOUBLE_QUOTED_STRING + || $tokenCode === \T_HEREDOC + || $tokenCode === \T_NOWDOC + ) { + $this->throwNotice($phpcsFile, $stackPtr, $functionName); + return; + } + } + } + + + /** + * Throw the error/warning. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * + * @return void + */ + protected function throwNotice(File $phpcsFile, $stackPtr, $functionName) + { + $message = 'Passing the $glue and $pieces parameters in reverse order to %s has been deprecated since PHP 7.4'; + $isError = false; + $errorCode = 'Deprecated'; + $data = array($functionName); + + /* + Support for the deprecated behaviour is expected to be removed in PHP 8.0. + Once this has been implemented, this section should be uncommented. + if ($this->supportsAbove('8.0') === true) { + $message .= ' and is removed since PHP 8.0'; + $isError = true; + $errorCode = 'Removed'; + } + */ + + $message .= '; $glue should be the first parameter and $pieces the second'; + + $this->addMessage($phpcsFile, $message, $stackPtr, $isError, $errorCode, $data); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedMbStrrposEncodingThirdParamSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedMbStrrposEncodingThirdParamSniff.php new file mode 100644 index 00000000..7406d9a8 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedMbStrrposEncodingThirdParamSniff.php @@ -0,0 +1,149 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect passing `$encoding` to `mb_strrpos()` as 3rd argument. + * + * The `$encoding` parameter was moved from the third position to the fourth in PHP 5.2.0. + * For backward compatibility, `$encoding` could be specified as the third parameter, but doing + * so is deprecated and will be removed in the future. + * + * Between PHP 5.2 and PHP 7.3, this was a deprecation in documentation only. + * As of PHP 7.4, a deprecation warning will be thrown if an encoding is passed as the 3rd + * argument. + * As of PHP 8, the argument is expected to change to accept an integer only. + * + * PHP version 5.2 + * PHP version 7.4 + * + * @link https://www.php.net/manual/en/migration74.deprecated.php#migration74.deprecated.mbstring + * @link https://wiki.php.net/rfc/deprecations_php_7_4#mb_strrpos_with_encoding_as_3rd_argument + * @link https://www.php.net/manual/en/function.mb-strrpos.php + * + * @since 9.3.0 + */ +class RemovedMbStrrposEncodingThirdParamSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * @since 9.3.0 + * + * @var array + */ + protected $targetFunctions = array( + 'mb_strrpos' => true, + ); + + /** + * Tokens which should be recognized as text. + * + * @since 9.3.0 + * + * @var array + */ + private $textStringTokens = array( + \T_CONSTANT_ENCAPSED_STRING, + \T_DOUBLE_QUOTED_STRING, + \T_HEREDOC, + \T_NOWDOC, + ); + + /** + * Tokens which should be recognized as numbers. + * + * @since 9.3.0 + * + * @var array + */ + private $numberTokens = array( + \T_LNUMBER => \T_LNUMBER, + \T_DNUMBER => \T_DNUMBER, + \T_MINUS => \T_MINUS, + \T_PLUS => \T_PLUS, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return $this->supportsAbove('5.2') === false; + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[3]) === false) { + // Optional third parameter not set. + return; + } + + if (isset($parameters[4]) === true) { + // Encoding set as fourth parameter. + return; + } + + $targetParam = $parameters[3]; + $targets = $this->numberTokens + Tokens::$emptyTokens; + $nonNumber = $phpcsFile->findNext($targets, $targetParam['start'], ($targetParam['end'] + 1), true); + if ($nonNumber === false) { + return; + } + + if ($this->isNumericCalculation($phpcsFile, $targetParam['start'], $targetParam['end']) === true) { + return; + } + + $hasString = $phpcsFile->findNext($this->textStringTokens, $targetParam['start'], ($targetParam['end'] + 1)); + if ($hasString === false) { + // No text strings found. Undetermined. + return; + } + + $error = 'Passing the encoding to mb_strrpos() as third parameter is soft deprecated since PHP 5.2'; + if ($this->supportsAbove('7.4') === true) { + $error .= ' and hard deprecated since PHP 7.4'; + } + + $error .= '. Use an explicit 0 as the offset in the third parameter.'; + + $phpcsFile->addWarning( + $error, + $targetParam['start'], + 'Deprecated' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedMbstringModifiersSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedMbstringModifiersSniff.php new file mode 100644 index 00000000..83e4de97 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedMbstringModifiersSniff.php @@ -0,0 +1,135 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Check for use of deprecated and removed regex modifiers for MbString regex functions. + * + * Initially just checks for the PHP 7.1 deprecated `e` modifier. + * + * PHP version 7.1 + * + * @link https://wiki.php.net/rfc/deprecate_mb_ereg_replace_eval_option + * @link https://www.php.net/manual/en/function.mb-regex-set-options.php + * + * @since 7.0.5 + * @since 7.0.8 This sniff now throws a warning instead of an error as the functionality is + * only deprecated (for now). + * @since 8.2.0 Now extends the `AbstractFunctionCallParameterSniff` instead of the base `Sniff` class. + * @since 9.0.0 Renamed from `MbstringReplaceEModifierSniff` to `RemovedMbstringModifiersSniff`. + */ +class RemovedMbstringModifiersSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * Key is the function name, value the parameter position of the options parameter. + * + * @since 7.0.5 + * @since 8.2.0 Renamed from `$functions` to `$targetFunctions`. + * + * @var array + */ + protected $targetFunctions = array( + 'mb_ereg_replace' => 4, + 'mb_eregi_replace' => 4, + 'mb_regex_set_options' => 1, + 'mbereg_replace' => 4, // Undocumented, but valid function alias. + 'mberegi_replace' => 4, // Undocumented, but valid function alias. + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 8.2.0 + * + * @return bool + */ + protected function bowOutEarly() + { + // Version used here should be the highest version from the `$newModifiers` array, + // i.e. the last PHP version in which a new modifier was introduced. + return ($this->supportsAbove('7.1') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 7.0.5 + * @since 8.2.0 Renamed from `process()` to `processParameters()` and removed + * logic superfluous now the sniff extends the abstract. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + $tokens = $phpcsFile->getTokens(); + $functionNameLc = strtolower($functionName); + + // Check whether the options parameter in the function call is passed. + if (isset($parameters[$this->targetFunctions[$functionNameLc]]) === false) { + return; + } + + $optionsParam = $parameters[$this->targetFunctions[$functionNameLc]]; + + $stringToken = $phpcsFile->findNext(Tokens::$stringTokens, $optionsParam['start'], $optionsParam['end'] + 1); + if ($stringToken === false) { + // No string token found in the options parameter, so skip it (e.g. variable passed in). + return; + } + + $options = ''; + + /* + * Get the content of any string tokens in the options parameter and remove the quotes and variables. + */ + for ($i = $stringToken; $i <= $optionsParam['end']; $i++) { + if (isset(Tokens::$stringTokens[$tokens[$i]['code']]) === false) { + continue; + } + + $content = $this->stripQuotes($tokens[$i]['content']); + if ($tokens[$i]['code'] === \T_DOUBLE_QUOTED_STRING) { + $content = $this->stripVariables($content); + } + $content = trim($content); + + if (empty($content) === false) { + $options .= $content; + } + } + + if (strpos($options, 'e') !== false) { + $error = 'The Mbstring regex "e" modifier is deprecated since PHP 7.1.'; + + // The alternative mb_ereg_replace_callback() function is only available since 5.4.1. + if ($this->supportsBelow('5.4.1') === false) { + $error .= ' Use mb_ereg_replace_callback() instead (PHP 5.4.1+).'; + } + + $phpcsFile->addWarning($error, $stackPtr, 'Deprecated'); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedNonCryptoHashSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedNonCryptoHashSniff.php new file mode 100644 index 00000000..832a1f62 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedNonCryptoHashSniff.php @@ -0,0 +1,121 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect usage of non-cryptographic hashes. + * + * "The `hash_hmac()`, `hash_hmac_file()`, `hash_pbkdf2()`, and `hash_init()` + * (with `HASH_HMAC`) functions no longer accept non-cryptographic hashes." + * + * PHP version 7.2 + * + * @link https://www.php.net/manual/en/migration72.incompatible.php#migration72.incompatible.hash-functions + * + * @since 9.0.0 + */ +class RemovedNonCryptoHashSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * @since 9.0.0 + * + * @var array + */ + protected $targetFunctions = array( + 'hash_hmac' => true, + 'hash_hmac_file' => true, + 'hash_init' => true, + 'hash_pbkdf2' => true, + ); + + /** + * List of the non-cryptographic hashes. + * + * @since 9.0.0 + * + * @var array + */ + protected $disabledCryptos = array( + 'adler32' => true, + 'crc32' => true, + 'crc32b' => true, + 'fnv132' => true, + 'fnv1a32' => true, + 'fnv164' => true, + 'fnv1a64' => true, + 'joaat' => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('7.2') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[1]) === false) { + return; + } + + $targetParam = $parameters[1]; + + if (isset($this->disabledCryptos[$this->stripQuotes($targetParam['raw'])]) === false) { + return; + } + + if (strtolower($functionName) === 'hash_init' + && (isset($parameters[2]) === false + || ($parameters[2]['raw'] !== 'HASH_HMAC' + && $parameters[2]['raw'] !== (string) \HASH_HMAC)) + ) { + // For hash_init(), these hashes are only disabled with HASH_HMAC set. + return; + } + + $phpcsFile->addError( + 'Non-cryptographic hashes are no longer accepted by function %s() since PHP 7.2. Found: %s', + $targetParam['start'], + $this->stringToErrorCode($functionName), + array( + $functionName, + $targetParam['raw'], + ) + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedPCREModifiersSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedPCREModifiersSniff.php new file mode 100644 index 00000000..377ed79f --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedPCREModifiersSniff.php @@ -0,0 +1,241 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Check for the use of deprecated and removed regex modifiers for PCRE regex functions. + * + * Initially just checks for the `e` modifier, which was deprecated since PHP 5.5 + * and removed as of PHP 7.0. + * + * {@internal If and when this sniff would need to start checking for other modifiers, a minor + * refactor will be needed as all references to the `e` modifier are currently hard-coded.} + * + * PHP version 5.5 + * PHP version 7.0 + * + * @link https://wiki.php.net/rfc/remove_preg_replace_eval_modifier + * @link https://wiki.php.net/rfc/remove_deprecated_functionality_in_php7 + * @link https://www.php.net/manual/en/reference.pcre.pattern.modifiers.php + * + * @since 5.6 + * @since 7.0.8 This sniff now throws a warning (deprecated) or an error (removed) depending + * on the `testVersion` set. Previously it would always throw an error. + * @since 8.2.0 Now extends the `AbstractFunctionCallParameterSniff` instead of the base `Sniff` class. + * @since 9.0.0 Renamed from `PregReplaceEModifierSniff` to `RemovedPCREModifiersSniff`. + */ +class RemovedPCREModifiersSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * @since 7.0.1 + * @since 8.2.0 Renamed from `$functions` to `$targetFunctions`. + * + * @var array + */ + protected $targetFunctions = array( + 'preg_replace' => true, + 'preg_filter' => true, + ); + + /** + * Regex bracket delimiters. + * + * @since 7.0.5 This array was originally contained within the `process()` method. + * + * @var array + */ + protected $doublesSeparators = array( + '{' => '}', + '[' => ']', + '(' => ')', + '<' => '>', + ); + + + /** + * Process the parameters of a matched function. + * + * @since 5.6 + * @since 8.2.0 Renamed from `process()` to `processParameters()` and removed + * logic superfluous now the sniff extends the abstract. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + // Check the first parameter in the function call as that should contain the regex(es). + if (isset($parameters[1]) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $functionNameLc = strtolower($functionName); + $firstParam = $parameters[1]; + + // Differentiate between an array of patterns passed and a single pattern. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $firstParam['start'], ($firstParam['end'] + 1), true); + if ($nextNonEmpty !== false && ($tokens[$nextNonEmpty]['code'] === \T_ARRAY || $tokens[$nextNonEmpty]['code'] === \T_OPEN_SHORT_ARRAY)) { + $arrayValues = $this->getFunctionCallParameters($phpcsFile, $nextNonEmpty); + if ($functionNameLc === 'preg_replace_callback_array') { + // For preg_replace_callback_array(), the patterns will be in the array keys. + foreach ($arrayValues as $value) { + $hasKey = $phpcsFile->findNext(\T_DOUBLE_ARROW, $value['start'], ($value['end'] + 1)); + if ($hasKey === false) { + continue; + } + + $value['end'] = ($hasKey - 1); + $value['raw'] = trim($phpcsFile->getTokensAsString($value['start'], ($hasKey - $value['start']))); + $this->processRegexPattern($value, $phpcsFile, $value['end'], $functionName); + } + + } else { + // Otherwise, the patterns will be in the array values. + foreach ($arrayValues as $value) { + $hasKey = $phpcsFile->findNext(\T_DOUBLE_ARROW, $value['start'], ($value['end'] + 1)); + if ($hasKey !== false) { + $value['start'] = ($hasKey + 1); + $value['raw'] = trim($phpcsFile->getTokensAsString($value['start'], (($value['end'] + 1) - $value['start']))); + } + + $this->processRegexPattern($value, $phpcsFile, $value['end'], $functionName); + } + } + + } else { + $this->processRegexPattern($firstParam, $phpcsFile, $stackPtr, $functionName); + } + } + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 8.2.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('5.5') === false); + } + + + /** + * Analyse a potential regex pattern for use of the /e modifier. + * + * @since 7.1.2 This logic was originally contained within the `process()` method. + * + * @param array $pattern Array containing the start and end token + * pointer of the potential regex pattern and + * the raw string value of the pattern. + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param string $functionName The function which contained the pattern. + * + * @return void + */ + protected function processRegexPattern($pattern, File $phpcsFile, $stackPtr, $functionName) + { + $tokens = $phpcsFile->getTokens(); + + /* + * The pattern might be build up of a combination of strings, variables + * and function calls. We are only concerned with the strings. + */ + $regex = ''; + for ($i = $pattern['start']; $i <= $pattern['end']; $i++) { + if (isset(Tokens::$stringTokens[$tokens[$i]['code']]) === true) { + $content = $this->stripQuotes($tokens[$i]['content']); + if ($tokens[$i]['code'] === \T_DOUBLE_QUOTED_STRING) { + $content = $this->stripVariables($content); + } + + $regex .= trim($content); + } + } + + // Deal with multi-line regexes which were broken up in several string tokens. + if ($tokens[$pattern['start']]['line'] !== $tokens[$pattern['end']]['line']) { + $regex = $this->stripQuotes($regex); + } + + if ($regex === '') { + // No string token found in the first parameter, so skip it (e.g. if variable passed in). + return; + } + + $regexFirstChar = substr($regex, 0, 1); + + // Make sure that the character identified as the delimiter is valid. + // Otherwise, it is a false positive caused by the string concatenation. + if (preg_match('`[a-z0-9\\\\ ]`i', $regexFirstChar) === 1) { + return; + } + + if (isset($this->doublesSeparators[$regexFirstChar])) { + $regexEndPos = strrpos($regex, $this->doublesSeparators[$regexFirstChar]); + } else { + $regexEndPos = strrpos($regex, $regexFirstChar); + } + + if ($regexEndPos !== false) { + $modifiers = substr($regex, $regexEndPos + 1); + $this->examineModifiers($phpcsFile, $stackPtr, $functionName, $modifiers); + } + } + + + /** + * Examine the regex modifier string. + * + * @since 8.2.0 Split off from the `processRegexPattern()` method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param string $functionName The function which contained the pattern. + * @param string $modifiers The regex modifiers found. + * + * @return void + */ + protected function examineModifiers(File $phpcsFile, $stackPtr, $functionName, $modifiers) + { + if (strpos($modifiers, 'e') !== false) { + $error = '%s() - /e modifier is deprecated since PHP 5.5'; + $isError = false; + $errorCode = 'Deprecated'; + $data = array($functionName); + + if ($this->supportsAbove('7.0')) { + $error .= ' and removed since PHP 7.0'; + $isError = true; + $errorCode = 'Removed'; + } + + $this->addMessage($phpcsFile, $error, $stackPtr, $isError, $errorCode, $data); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedSetlocaleStringSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedSetlocaleStringSniff.php new file mode 100644 index 00000000..6f1eced1 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedSetlocaleStringSniff.php @@ -0,0 +1,104 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\ParameterValues; + +use PHPCompatibility\AbstractFunctionCallParameterSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect passing a string literal as `$category` to `setlocale()`. + * + * Support for the category parameter passed as a string has been removed. + * Only `LC_*` constants can be used as of PHP 7.0.0. + * + * PHP version 4.2 + * PHP version 7.0 + * + * @link https://wiki.php.net/rfc/remove_deprecated_functionality_in_php7 + * @link https://www.php.net/manual/en/function.setlocale.php#refsect1-function.setlocale-changelog + * + * @since 9.0.0 + */ +class RemovedSetlocaleStringSniff extends AbstractFunctionCallParameterSniff +{ + + /** + * Functions to check for. + * + * @since 9.0.0 + * + * @var array + */ + protected $targetFunctions = array( + 'setlocale' => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('4.2') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[1]) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $targetParam = $parameters[1]; + + for ($i = $targetParam['start']; $i <= $targetParam['end']; $i++) { + if ($tokens[$i]['code'] !== \T_CONSTANT_ENCAPSED_STRING + && $tokens[$i]['code'] !== \T_DOUBLE_QUOTED_STRING + ) { + continue; + } + + $message = 'Passing the $category as a string to setlocale() has been deprecated since PHP 4.2'; + $isError = false; + $errorCode = 'Deprecated'; + $data = array($targetParam['raw']); + + if ($this->supportsAbove('7.0') === true) { + $message .= ' and is removed since PHP 7.0'; + $isError = true; + $errorCode = 'Removed'; + } + + $message .= '; Pass one of the LC_* constants instead. Found: %s'; + + $this->addMessage($phpcsFile, $message, $i, $isError, $errorCode, $data); + break; + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/ForbiddenCallTimePassByReferenceSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/ForbiddenCallTimePassByReferenceSniff.php new file mode 100644 index 00000000..96b49827 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/ForbiddenCallTimePassByReferenceSniff.php @@ -0,0 +1,259 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2009-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Syntax; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect the use of call time pass by reference. + * + * This behaviour has been deprecated in PHP 5.3 and removed in PHP 5.4. + * + * PHP version 5.4 + * + * @link https://wiki.php.net/rfc/calltimebyref + * @link https://www.php.net/manual/en/language.references.pass.php + * + * @since 5.5 + * @since 7.0.8 This sniff now throws a warning (deprecated) or an error (removed) depending + * on the `testVersion` set. Previously it would always throw an error. + */ +class ForbiddenCallTimePassByReferenceSniff extends Sniff +{ + + /** + * Tokens that represent assignments or equality comparisons. + * + * Near duplicate of Tokens::$assignmentTokens + Tokens::$equalityTokens. + * Copied in for PHPCS cross-version compatibility. + * + * @since 8.1.0 + * + * @var array + */ + private $assignOrCompare = array( + // Equality tokens. + 'T_IS_EQUAL' => true, + 'T_IS_NOT_EQUAL' => true, + 'T_IS_IDENTICAL' => true, + 'T_IS_NOT_IDENTICAL' => true, + 'T_IS_SMALLER_OR_EQUAL' => true, + 'T_IS_GREATER_OR_EQUAL' => true, + + // Assignment tokens. + 'T_EQUAL' => true, + 'T_AND_EQUAL' => true, + 'T_OR_EQUAL' => true, + 'T_CONCAT_EQUAL' => true, + 'T_DIV_EQUAL' => true, + 'T_MINUS_EQUAL' => true, + 'T_POW_EQUAL' => true, + 'T_MOD_EQUAL' => true, + 'T_MUL_EQUAL' => true, + 'T_PLUS_EQUAL' => true, + 'T_XOR_EQUAL' => true, + 'T_DOUBLE_ARROW' => true, + 'T_SL_EQUAL' => true, + 'T_SR_EQUAL' => true, + 'T_COALESCE_EQUAL' => true, + 'T_ZSR_EQUAL' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + return array( + \T_STRING, + \T_VARIABLE, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('5.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + // Skip tokens that are the names of functions or classes + // within their definitions. For example: function myFunction... + // "myFunction" is T_STRING but we should skip because it is not a + // function or method *call*. + $findTokens = Tokens::$emptyTokens; + $findTokens[] = \T_BITWISE_AND; + + $prevNonEmpty = $phpcsFile->findPrevious( + $findTokens, + ($stackPtr - 1), + null, + true + ); + + if ($prevNonEmpty !== false && \in_array($tokens[$prevNonEmpty]['type'], array('T_FUNCTION', 'T_CLASS', 'T_INTERFACE', 'T_TRAIT'), true)) { + return; + } + + // If the next non-whitespace token after the function or method call + // is not an opening parenthesis then it can't really be a *call*. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + if ($openBracket === false || $tokens[$openBracket]['code'] !== \T_OPEN_PARENTHESIS + || isset($tokens[$openBracket]['parenthesis_closer']) === false + ) { + return; + } + + // Get the function call parameters. + $parameters = $this->getFunctionCallParameters($phpcsFile, $stackPtr); + if (\count($parameters) === 0) { + return; + } + + // Which nesting level is the one we are interested in ? + $nestedParenthesisCount = 1; + if (isset($tokens[$openBracket]['nested_parenthesis'])) { + $nestedParenthesisCount = \count($tokens[$openBracket]['nested_parenthesis']) + 1; + } + + foreach ($parameters as $parameter) { + if ($this->isCallTimePassByReferenceParam($phpcsFile, $parameter, $nestedParenthesisCount) === true) { + // T_BITWISE_AND represents a pass-by-reference. + $error = 'Using a call-time pass-by-reference is deprecated since PHP 5.3'; + $isError = false; + $errorCode = 'Deprecated'; + + if ($this->supportsAbove('5.4')) { + $error .= ' and prohibited since PHP 5.4'; + $isError = true; + $errorCode = 'NotAllowed'; + } + + $this->addMessage($phpcsFile, $error, $parameter['start'], $isError, $errorCode); + } + } + } + + + /** + * Determine whether a parameter is passed by reference. + * + * @since 7.0.6 Split off from the `process()` method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param array $parameter Information on the current parameter + * to be examined. + * @param int $nestingLevel Target nesting level. + * + * @return bool + */ + protected function isCallTimePassByReferenceParam(File $phpcsFile, $parameter, $nestingLevel) + { + $tokens = $phpcsFile->getTokens(); + + $searchStartToken = $parameter['start'] - 1; + $searchEndToken = $parameter['end'] + 1; + $nextVariable = $searchStartToken; + do { + $nextVariable = $phpcsFile->findNext(array(\T_VARIABLE, \T_OPEN_SHORT_ARRAY, \T_CLOSURE), ($nextVariable + 1), $searchEndToken); + if ($nextVariable === false) { + return false; + } + + // Ignore anything within short array definition brackets. + if ($tokens[$nextVariable]['type'] === 'T_OPEN_SHORT_ARRAY' + && (isset($tokens[$nextVariable]['bracket_opener']) + && $tokens[$nextVariable]['bracket_opener'] === $nextVariable) + && isset($tokens[$nextVariable]['bracket_closer']) + ) { + // Skip forward to the end of the short array definition. + $nextVariable = $tokens[$nextVariable]['bracket_closer']; + continue; + } + + // Skip past closures passed as function parameters. + if ($tokens[$nextVariable]['type'] === 'T_CLOSURE' + && (isset($tokens[$nextVariable]['scope_condition']) + && $tokens[$nextVariable]['scope_condition'] === $nextVariable) + && isset($tokens[$nextVariable]['scope_closer']) + ) { + // Skip forward to the end of the closure declaration. + $nextVariable = $tokens[$nextVariable]['scope_closer']; + continue; + } + + // Make sure the variable belongs directly to this function call + // and is not inside a nested function call or array. + if (isset($tokens[$nextVariable]['nested_parenthesis']) === false + || (\count($tokens[$nextVariable]['nested_parenthesis']) !== $nestingLevel) + ) { + continue; + } + + // Checking this: $value = my_function(...[*]$arg...). + $tokenBefore = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($nextVariable - 1), + $searchStartToken, + true + ); + + if ($tokenBefore === false || $tokens[$tokenBefore]['code'] !== \T_BITWISE_AND) { + // Nothing before the token or no &. + continue; + } + + if ($phpcsFile->isReference($tokenBefore) === false) { + continue; + } + + // Checking this: $value = my_function(...[*]&$arg...). + $tokenBefore = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($tokenBefore - 1), + $searchStartToken, + true + ); + + // Prevent false positive on assign by reference and compare with reference + // within function call parameters. + if (isset($this->assignOrCompare[$tokens[$tokenBefore]['type']])) { + continue; + } + + // The found T_BITWISE_AND represents a pass-by-reference. + return true; + + } while ($nextVariable < $searchEndToken); + + // This code should never be reached, but here in case of weird bugs. + return false; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayStringDereferencingSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayStringDereferencingSniff.php new file mode 100644 index 00000000..2cc1e551 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayStringDereferencingSniff.php @@ -0,0 +1,199 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Syntax; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect array and string literal dereferencing. + * + * As of PHP 5.5, array and string literals can now be dereferenced directly to + * access individual elements and characters. + * + * As of PHP 7.0, this also works when using curly braces for the dereferencing. + * While unclear, this most likely has to do with the Uniform Variable Syntax changes. + * + * PHP version 5.5 + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/migration55.new-features.php#migration55.new-features.const-dereferencing + * @link https://wiki.php.net/rfc/constdereference + * @link https://wiki.php.net/rfc/uniform_variable_syntax + * @link https://www.php.net/manual/en/language.types.array.php#example-63 + * + * {@internal The reason for splitting the logic of this sniff into different methods is + * to allow re-use of the logic by the PHP 7.4 `RemovedCurlyBraceArrayAccess` sniff.} + * + * @since 7.1.4 + * @since 9.3.0 Now also detects dereferencing using curly braces. + */ +class NewArrayStringDereferencingSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.1.4 + * + * @return array + */ + public function register() + { + return array( + \T_ARRAY, + \T_OPEN_SHORT_ARRAY, + \T_CONSTANT_ENCAPSED_STRING, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.6') === false) { + return; + } + + $dereferencing = $this->isArrayStringDereferencing($phpcsFile, $stackPtr); + if (empty($dereferencing)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $supports54 = $this->supportsBelow('5.4'); + + foreach ($dereferencing['braces'] as $openBrace => $closeBrace) { + if ($supports54 === true + && ($tokens[$openBrace]['type'] === 'T_OPEN_SQUARE_BRACKET' + || $tokens[$openBrace]['type'] === 'T_OPEN_SHORT_ARRAY') // Work around bug #1381 in PHPCS 2.8.1 and lower. + ) { + $phpcsFile->addError( + 'Direct array dereferencing of %s is not present in PHP version 5.4 or earlier', + $openBrace, + 'Found', + array($dereferencing['type']) + ); + + continue; + } + + // PHP 7.0 Array/string dereferencing using curly braces. + if ($tokens[$openBrace]['type'] === 'T_OPEN_CURLY_BRACKET') { + $phpcsFile->addError( + 'Direct array dereferencing of %s using curly braces is not present in PHP version 5.6 or earlier', + $openBrace, + 'FoundUsingCurlies', + array($dereferencing['type']) + ); + } + } + } + + + /** + * Check if this string/array is being dereferenced. + * + * @since 9.3.0 Logic split off from the process method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return array Array containing the type of access and stack pointers to the + * open/close braces involved in the array/string dereferencing; + * or an empty array if no array/string dereferencing was detected. + */ + public function isArrayStringDereferencing(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$stackPtr]['code']) { + case \T_CONSTANT_ENCAPSED_STRING: + $type = 'string literals'; + $end = $stackPtr; + break; + + case \T_ARRAY: + if (isset($tokens[$stackPtr]['parenthesis_closer']) === false) { + // Live coding. + return array(); + } else { + $type = 'arrays'; + $end = $tokens[$stackPtr]['parenthesis_closer']; + } + break; + + case \T_OPEN_SHORT_ARRAY: + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + // Live coding. + return array(); + } else { + $type = 'arrays'; + $end = $tokens[$stackPtr]['bracket_closer']; + } + break; + } + + if (isset($type, $end) === false) { + // Shouldn't happen, but for some reason did. + return array(); + } + + $braces = array(); + + do { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true, null, true); + if ($nextNonEmpty === false) { + break; + } + + if ($tokens[$nextNonEmpty]['type'] === 'T_OPEN_SQUARE_BRACKET' + || $tokens[$nextNonEmpty]['type'] === 'T_OPEN_CURLY_BRACKET' // PHP 7.0+. + || $tokens[$nextNonEmpty]['type'] === 'T_OPEN_SHORT_ARRAY' // Work around bug #1381 in PHPCS 2.8.1 and lower. + ) { + if (isset($tokens[$nextNonEmpty]['bracket_closer']) === false) { + // Live coding or parse error. + break; + } + + $braces[$nextNonEmpty] = $tokens[$nextNonEmpty]['bracket_closer']; + + // Continue, just in case there is nested array access, i.e. `array(1, 2, 3)[$i][$j];`. + $end = $tokens[$nextNonEmpty]['bracket_closer']; + continue; + } + + // If we're still here, we've reached the end of the variable. + break; + + } while (true); + + if (empty($braces)) { + return array(); + } + + return array( + 'type' => $type, + 'braces' => $braces, + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayUnpackingSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayUnpackingSniff.php new file mode 100644 index 00000000..f0f66b86 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayUnpackingSniff.php @@ -0,0 +1,142 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Syntax; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Using the spread operator for unpacking arrays in array expressions is available since PHP 7.4. + * + * PHP version 7.4 + * + * @link https://www.php.net/manual/en/migration74.new-features.php#migration74.new-features.core.unpack-inside-array + * @link https://wiki.php.net/rfc/spread_operator_for_array + * + * @since 9.2.0 + */ +class NewArrayUnpackingSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + return array( + \T_ARRAY, + \T_OPEN_SHORT_ARRAY, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('7.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + /* + * Determine the array opener & closer. + */ + $closer = $phpcsFile->numTokens; + if ($tokens[$stackPtr]['code'] === \T_ARRAY) { + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false) { + return; + } + + $opener = $tokens[$stackPtr]['parenthesis_opener']; + + if (isset($tokens[$opener]['parenthesis_closer'])) { + $closer = $tokens[$opener]['parenthesis_closer']; + } + } else { + // Short array syntax. + $opener = $stackPtr; + + if (isset($tokens[$stackPtr]['bracket_closer'])) { + $closer = $tokens[$stackPtr]['bracket_closer']; + } + } + + $nestingLevel = 0; + if (isset($tokens[($opener + 1)]['nested_parenthesis'])) { + $nestingLevel = count($tokens[($opener + 1)]['nested_parenthesis']); + } + + for ($i = $opener; $i < $closer;) { + $i = $phpcsFile->findNext(array(\T_ELLIPSIS, \T_OPEN_SHORT_ARRAY, \T_ARRAY), ($i + 1), $closer); + if ($i === false) { + return; + } + + if ($tokens[$i]['code'] === \T_OPEN_SHORT_ARRAY) { + if (isset($tokens[$i]['bracket_closer']) === false) { + // Live coding, unfinished nested array, handle this when the array opener + // of the nested array is passed. + return; + } + + // Skip over nested short arrays. These will be handled when the array opener + // of the nested array is passed. + $i = $tokens[$i]['bracket_closer']; + continue; + } + + if ($tokens[$i]['code'] === \T_ARRAY) { + if (isset($tokens[$i]['parenthesis_closer']) === false) { + // Live coding, unfinished nested array, handle this when the array opener + // of the nested array is passed. + return; + } + + // Skip over nested long arrays. These will be handled when the array opener + // of the nested array is passed. + $i = $tokens[$i]['parenthesis_closer']; + continue; + } + + // Ensure this is not function call variable unpacking. + if (isset($tokens[$i]['nested_parenthesis']) + && count($tokens[$i]['nested_parenthesis']) > $nestingLevel + ) { + continue; + } + + // Ok, found one. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + $snippet = trim($phpcsFile->getTokensAsString($i, (($nextNonEmpty - $i) + 1))); + $phpcsFile->addError( + 'Array unpacking within array declarations using the spread operator is not supported in PHP 7.3 or earlier. Found: %s', + $i, + 'Found', + array($snippet) + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewClassMemberAccessSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewClassMemberAccessSniff.php new file mode 100644 index 00000000..218f0c9f --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewClassMemberAccessSniff.php @@ -0,0 +1,192 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Syntax; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect class member access on object instantiation/cloning. + * + * PHP 5.4: Class member access on instantiation has been added, e.g. `(new Foo)->bar()`. + * PHP 7.0: Class member access on cloning has been added, e.g. `(clone $foo)->bar()`. + * + * As of PHP 7.0, class member access on instantiation also works when using curly braces. + * While unclear, this most likely has to do with the Uniform Variable Syntax changes. + * + * PHP version 5.4 + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/language.oop5.basic.php#example-177 + * @link https://www.php.net/manual/en/language.oop5.cloning.php#language.oop5.traits.properties.example + * @link https://www.php.net/manual/en/migration54.new-features.php + * @link https://wiki.php.net/rfc/instance-method-call + * @link https://wiki.php.net/rfc/uniform_variable_syntax + * + * {@internal The reason for splitting the logic of this sniff into different methods is + * to allow re-use of the logic by the PHP 7.4 `RemovedCurlyBraceArrayAccess` sniff.} + * + * @since 8.2.0 + * @since 9.3.0 Now also detects class member access on instantiation using curly braces. + */ +class NewClassMemberAccessSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.2.0 + * + * @return array + */ + public function register() + { + return array( + \T_NEW, + \T_CLONE, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.6') === false) { + return; + } + + $pointers = $this->isClassMemberAccess($phpcsFile, $stackPtr); + if (empty($pointers)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $supports53 = $this->supportsBelow('5.3'); + + $error = 'Class member access on object %s was not supported in PHP %s or earlier'; + $data = array('instantiation', '5.3'); + $errorCode = 'OnNewFound'; + + if ($tokens[$stackPtr]['code'] === \T_CLONE) { + $data = array('cloning', '5.6'); + $errorCode = 'OnCloneFound'; + } + + foreach ($pointers as $open => $close) { + $itemData = $data; + $itemErrorCode = $errorCode; + + if ($tokens[$stackPtr]['code'] === \T_NEW + && $tokens[$open]['code'] !== \T_OPEN_CURLY_BRACKET + ) { + if ($supports53 === true) { + $phpcsFile->addError($error, $open, $itemErrorCode, $itemData); + } + continue; + } + + if ($tokens[$stackPtr]['code'] === \T_NEW + && $tokens[$open]['code'] === \T_OPEN_CURLY_BRACKET + ) { + // Non-curlies was already handled above. + $itemData = array('instantiation using curly braces', '5.6'); + $itemErrorCode = 'OnNewFoundUsingCurlies'; + } + + $phpcsFile->addError($error, $open, $itemErrorCode, $itemData); + } + } + + + /** + * Check if the class being instantiated/cloned is being dereferenced. + * + * @since 9.3.0 Logic split off from the process method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return array Array containing the stack pointers to the object operator or + * the open/close braces involved in the class member access; + * or an empty array if no class member access was detected. + */ + public function isClassMemberAccess(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['nested_parenthesis']) === false) { + // The `new className/clone $a` has to be in parentheses, without is not supported. + return array(); + } + + $parenthesisCloser = end($tokens[$stackPtr]['nested_parenthesis']); + $parenthesisOpener = key($tokens[$stackPtr]['nested_parenthesis']); + + if (isset($tokens[$parenthesisOpener]['parenthesis_owner']) === true) { + // If there is an owner, these parentheses are for a different purpose. + return array(); + } + + $prevBeforeParenthesis = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($parenthesisOpener - 1), null, true); + if ($prevBeforeParenthesis !== false && $tokens[$prevBeforeParenthesis]['code'] === \T_STRING) { + // This is most likely a function call with the new/cloned object as a parameter. + return array(); + } + + $braces = array(); + $end = $parenthesisCloser; + + do { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true, null, true); + if ($nextNonEmpty === false) { + break; + } + + if ($tokens[$nextNonEmpty]['code'] === \T_OBJECT_OPERATOR) { + // No need to walk any further if this is object access. + $braces[$nextNonEmpty] = true; + break; + } + + if ($tokens[$nextNonEmpty]['code'] === \T_OPEN_SQUARE_BRACKET + || $tokens[$nextNonEmpty]['code'] === \T_OPEN_CURLY_BRACKET // PHP 7.0+. + ) { + if (isset($tokens[$nextNonEmpty]['bracket_closer']) === false) { + // Live coding or parse error. + break; + } + + $braces[$nextNonEmpty] = $tokens[$nextNonEmpty]['bracket_closer']; + + // Continue, just in case there is nested array access, i.e. `(new Foo())[1][0];`. + $end = $tokens[$nextNonEmpty]['bracket_closer']; + continue; + } + + // If we're still here, we've reached the end. + break; + + } while (true); + + return $braces; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewDynamicAccessToStaticSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewDynamicAccessToStaticSniff.php new file mode 100644 index 00000000..4fd3b2fa --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewDynamicAccessToStaticSniff.php @@ -0,0 +1,89 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Syntax; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect dynamic access to static methods and properties, as well as class constants. + * + * As of PHP 5.3, static properties and methods as well as class constants + * can be accessed using a dynamic (variable) class name. + * + * PHP version 5.3 + * + * @link https://www.php.net/manual/en/migration53.new-features.php + * + * @since 8.1.0 + * @since 9.0.0 Renamed from `DynamicAccessToStaticSniff` to `NewDynamicAccessToStaticSniff`. + */ +class NewDynamicAccessToStaticSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.1.0 + * + * @return array + */ + public function register() + { + return array( + \T_DOUBLE_COLON, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.2') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + // Disregard `static::` as well. Late static binding is reported by another sniff. + if ($tokens[$prevNonEmpty]['code'] === \T_SELF + || $tokens[$prevNonEmpty]['code'] === \T_PARENT + || $tokens[$prevNonEmpty]['code'] === \T_STATIC + ) { + return; + } + + if ($tokens[$prevNonEmpty]['code'] === \T_STRING) { + $prevPrevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevNonEmpty - 1), null, true); + + if ($tokens[$prevPrevNonEmpty]['code'] !== \T_OBJECT_OPERATOR) { + return; + } + } + + $phpcsFile->addError( + 'Static class properties and methods, as well as class constants, could not be accessed using a dynamic (variable) classname in PHP 5.2 or earlier.', + $stackPtr, + 'Found' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFlexibleHeredocNowdocSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFlexibleHeredocNowdocSniff.php new file mode 100644 index 00000000..b24590a6 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFlexibleHeredocNowdocSniff.php @@ -0,0 +1,255 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Syntax; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; + +/** + * Detect usage of flexible heredoc/nowdoc and related cross-version incompatibilities. + * + * As of PHP 7.3: + * - The body and the closing marker of a heredoc/nowdoc can be indented; + * - The closing marker no longer needs to be on a line by itself; + * - The heredoc/nowdoc body may no longer contain the closing marker at the + * start of any of its lines. + * + * PHP version 7.3 + * + * @link https://www.php.net/manual/en/migration73.new-features.php#migration73.new-features.core.heredoc + * @link https://wiki.php.net/rfc/flexible_heredoc_nowdoc_syntaxes + * + * @since 9.0.0 + */ +class NewFlexibleHeredocNowdocSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.0.0 + * + * @return array + */ + public function register() + { + $targets = array( + \T_END_HEREDOC, + \T_END_NOWDOC, + ); + + if (version_compare(\PHP_VERSION_ID, '70299', '>') === false) { + // Start identifier of a PHP 7.3 flexible heredoc/nowdoc. + $targets[] = \T_STRING; + } + + return $targets; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + /* + * Due to a tokenizer bug which gets hit when the PHP 7.3 heredoc/nowdoc syntax + * is used, this part of the sniff cannot possibly work on PHPCS < 2.6.0. + * See upstream issue #928. + */ + if ($this->supportsBelow('7.2') === true && version_compare(PHPCSHelper::getVersion(), '2.6.0', '>=')) { + $this->detectIndentedNonStandAloneClosingMarker($phpcsFile, $stackPtr); + } + + $tokens = $phpcsFile->getTokens(); + if ($this->supportsAbove('7.3') === true && $tokens[$stackPtr]['code'] !== \T_STRING) { + $this->detectClosingMarkerInBody($phpcsFile, $stackPtr); + } + } + + + /** + * Detect indented and/or non-stand alone closing markers. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function detectIndentedNonStandAloneClosingMarker(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $indentError = 'Heredoc/nowdoc with an indented closing marker is not supported in PHP 7.2 or earlier.'; + $indentErrorCode = 'IndentedClosingMarker'; + $trailingError = 'Having code - other than a semi-colon or new line - after the closing marker of a heredoc/nowdoc is not supported in PHP 7.2 or earlier.'; + $trailingErrorCode = 'ClosingMarkerNoNewLine'; + + if (version_compare(\PHP_VERSION_ID, '70299', '>') === true) { + + /* + * Check for indented closing marker. + */ + if (ltrim($tokens[$stackPtr]['content']) !== $tokens[$stackPtr]['content']) { + $phpcsFile->addError($indentError, $stackPtr, $indentErrorCode); + } + + /* + * Check for tokens after the closing marker. + */ + $nextNonWhitespace = $phpcsFile->findNext(array(\T_WHITESPACE, \T_SEMICOLON), ($stackPtr + 1), null, true); + if ($tokens[$stackPtr]['line'] === $tokens[$nextNonWhitespace]['line']) { + $phpcsFile->addError($trailingError, $stackPtr, $trailingErrorCode); + } + } else { + // For PHP < 7.3, we're only interested in T_STRING tokens. + if ($tokens[$stackPtr]['code'] !== \T_STRING) { + return; + } + + if (preg_match('`^<<<([\'"]?)([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\1[\r\n]+`', $tokens[$stackPtr]['content'], $matches) !== 1) { + // Not the start of a PHP 7.3 flexible heredoc/nowdoc. + return; + } + + $identifier = $matches[2]; + + for ($i = ($stackPtr + 1); $i <= $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['code'] !== \T_ENCAPSED_AND_WHITESPACE) { + continue; + } + + $trimmed = ltrim($tokens[$i]['content']); + + if (strpos($trimmed, $identifier) !== 0) { + continue; + } + + // OK, we've found the PHP 7.3 flexible heredoc/nowdoc closing marker. + + /* + * Check for indented closing marker. + */ + if ($trimmed !== $tokens[$i]['content']) { + // Indent found before closing marker. + $phpcsFile->addError($indentError, $i, $indentErrorCode); + } + + /* + * Check for tokens after the closing marker. + */ + // Remove the identifier. + $afterMarker = substr($trimmed, \strlen($identifier)); + // Remove a potential semi-colon at the beginning of what's left of the string. + $afterMarker = ltrim($afterMarker, ';'); + // Remove new line characters at the end of the string. + $afterMarker = rtrim($afterMarker, "\r\n"); + + if ($afterMarker !== '') { + $phpcsFile->addError($trailingError, $i, $trailingErrorCode); + } + + break; + } + } + } + + + /** + * Detect heredoc/nowdoc identifiers at the start of lines in the heredoc/nowdoc body. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function detectClosingMarkerInBody(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $error = 'The body of a heredoc/nowdoc can not contain the heredoc/nowdoc closing marker as text at the start of a line since PHP 7.3.'; + $errorCode = 'ClosingMarkerNoNewLine'; + + if (version_compare(\PHP_VERSION_ID, '70299', '>') === true) { + $nextNonWhitespace = $phpcsFile->findNext(\T_WHITESPACE, ($stackPtr + 1), null, true, null, true); + if ($nextNonWhitespace === false + || $tokens[$nextNonWhitespace]['code'] === \T_SEMICOLON + || (($tokens[$nextNonWhitespace]['code'] === \T_COMMA + || $tokens[$nextNonWhitespace]['code'] === \T_STRING_CONCAT) + && $tokens[$nextNonWhitespace]['line'] !== $tokens[$stackPtr]['line']) + ) { + // This is most likely a correctly identified closing marker. + return; + } + + // The real closing tag has to be before the next heredoc/nowdoc. + $nextHereNowDoc = $phpcsFile->findNext(array(\T_START_HEREDOC, \T_START_NOWDOC), ($stackPtr + 1)); + if ($nextHereNowDoc === false) { + $nextHereNowDoc = null; + } + + $identifier = trim($tokens[$stackPtr]['content']); + $realClosingMarker = $stackPtr; + + while (($realClosingMarker = $phpcsFile->findNext(\T_STRING, ($realClosingMarker + 1), $nextHereNowDoc, false, $identifier)) !== false) { + + $prevNonWhitespace = $phpcsFile->findPrevious(\T_WHITESPACE, ($realClosingMarker - 1), null, true); + if ($prevNonWhitespace === false + || $tokens[$prevNonWhitespace]['line'] === $tokens[$realClosingMarker]['line'] + ) { + // Marker text found, but not at the start of the line. + continue; + } + + // The original T_END_HEREDOC/T_END_NOWDOC was most likely incorrect as we've found + // a possible alternative closing marker. + $phpcsFile->addError($error, $stackPtr, $errorCode); + + break; + } + + } else { + if (isset($tokens[$stackPtr]['scope_closer'], $tokens[$stackPtr]['scope_opener']) === true + && $tokens[$stackPtr]['scope_closer'] === $stackPtr + ) { + $opener = $tokens[$stackPtr]['scope_opener']; + } else { + // PHPCS < 3.0.2 did not add scope_* values for Nowdocs. + $opener = $phpcsFile->findPrevious(\T_START_NOWDOC, ($stackPtr - 1)); + if ($opener === false) { + return; + } + } + + $quotedIdentifier = preg_quote($tokens[$stackPtr]['content'], '`'); + + // Throw an error for each line in the body which starts with the identifier. + for ($i = ($opener + 1); $i < $stackPtr; $i++) { + if (preg_match('`^[ \t]*' . $quotedIdentifier . '\b`', $tokens[$i]['content']) === 1) { + $phpcsFile->addError($error, $i, $errorCode); + } + } + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFunctionArrayDereferencingSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFunctionArrayDereferencingSniff.php new file mode 100644 index 00000000..ac5e6b72 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFunctionArrayDereferencingSniff.php @@ -0,0 +1,187 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Syntax; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect function array dereferencing as introduced in PHP 5.4. + * + * PHP 5.4 supports direct array dereferencing on the return of a method/function call. + * + * As of PHP 7.0, this also works when using curly braces for the dereferencing. + * While unclear, this most likely has to do with the Uniform Variable Syntax changes. + * + * PHP version 5.4 + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/language.types.array.php#example-63 + * @link https://www.php.net/manual/en/migration54.new-features.php + * @link https://wiki.php.net/rfc/functionarraydereferencing + * @link https://wiki.php.net/rfc/uniform_variable_syntax + * + * {@internal The reason for splitting the logic of this sniff into different methods is + * to allow re-use of the logic by the PHP 7.4 RemovedCurlyBraceArrayAccess sniff.} + * + * @since 7.0.0 + * @since 9.3.0 Now also detects dereferencing using curly braces. + */ +class NewFunctionArrayDereferencingSniff extends Sniff +{ + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.6') === false) { + return; + } + + $dereferencing = $this->isFunctionArrayDereferencing($phpcsFile, $stackPtr); + if (empty($dereferencing)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $supports53 = $this->supportsBelow('5.3'); + + foreach ($dereferencing as $openBrace => $closeBrace) { + if ($supports53 === true + && $tokens[$openBrace]['type'] === 'T_OPEN_SQUARE_BRACKET' + ) { + $phpcsFile->addError( + 'Function array dereferencing is not present in PHP version 5.3 or earlier', + $openBrace, + 'Found' + ); + + continue; + } + + // PHP 7.0 function array dereferencing using curly braces. + if ($tokens[$openBrace]['type'] === 'T_OPEN_CURLY_BRACKET') { + $phpcsFile->addError( + 'Function array dereferencing using curly braces is not present in PHP version 5.6 or earlier', + $openBrace, + 'FoundUsingCurlies' + ); + } + } + } + + + /** + * Check if the return of a function/method call is being dereferenced. + * + * @since 9.3.0 Logic split off from the process method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return array Array containing stack pointers to the open/close braces + * involved in the function dereferencing; + * or an empty array if no function dereferencing was detected. + */ + public function isFunctionArrayDereferencing(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Next non-empty token should be the open parenthesis. + $openParenthesis = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); + if ($openParenthesis === false || $tokens[$openParenthesis]['code'] !== \T_OPEN_PARENTHESIS) { + return array(); + } + + // Don't throw errors during live coding. + if (isset($tokens[$openParenthesis]['parenthesis_closer']) === false) { + return array(); + } + + // Is this T_STRING really a function or method call ? + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prevToken !== false + && \in_array($tokens[$prevToken]['code'], array(\T_DOUBLE_COLON, \T_OBJECT_OPERATOR), true) === false + ) { + if ($tokens[$prevToken]['code'] === \T_BITWISE_AND) { + // This may be a function declared by reference. + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), null, true); + } + + $ignore = array( + \T_FUNCTION => true, + \T_CONST => true, + \T_USE => true, + \T_NEW => true, + \T_CLASS => true, + \T_INTERFACE => true, + ); + + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function or method. + return array(); + } + } + + $current = $tokens[$openParenthesis]['parenthesis_closer']; + $braces = array(); + + do { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($current + 1), null, true, null, true); + if ($nextNonEmpty === false) { + break; + } + + if ($tokens[$nextNonEmpty]['type'] === 'T_OPEN_SQUARE_BRACKET' + || $tokens[$nextNonEmpty]['type'] === 'T_OPEN_CURLY_BRACKET' // PHP 7.0+. + ) { + if (isset($tokens[$nextNonEmpty]['bracket_closer']) === false) { + // Live coding or parse error. + break; + } + + $braces[$nextNonEmpty] = $tokens[$nextNonEmpty]['bracket_closer']; + + // Continue, just in case there is nested array access, i.e. `echo $foo->bar()[0][2];`. + $current = $tokens[$nextNonEmpty]['bracket_closer']; + continue; + } + + // If we're still here, we've reached the end of the function call. + break; + + } while (true); + + return $braces; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFunctionCallTrailingCommaSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFunctionCallTrailingCommaSniff.php new file mode 100644 index 00000000..39208b35 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFunctionCallTrailingCommaSniff.php @@ -0,0 +1,120 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Syntax; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect trailing comma's in function calls, `isset()` and `unset()` as allowed since PHP 7.3. + * + * PHP version 7.3 + * + * @link https://www.php.net/manual/en/migration73.new-features.php#migration73.new-features.core.trailing-commas + * @link https://wiki.php.net/rfc/trailing-comma-function-calls + * + * @since 8.2.0 + * @since 9.0.0 Renamed from `NewTrailingCommaSniff` to `NewFunctionCallTrailingCommaSniff`. + */ +class NewFunctionCallTrailingCommaSniff extends Sniff +{ + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.2.0 + * + * @return array + */ + public function register() + { + return array( + \T_STRING, + \T_VARIABLE, + \T_ISSET, + \T_UNSET, + ); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('7.2') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS + || isset($tokens[$nextNonEmpty]['parenthesis_closer']) === false + ) { + return; + } + + if ($tokens[$stackPtr]['code'] === \T_STRING) { + $ignore = array( + \T_FUNCTION => true, + \T_CONST => true, + \T_USE => true, + ); + + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevNonEmpty]['code']]) === true) { + // Not a function call. + return; + } + } + + $closer = $tokens[$nextNonEmpty]['parenthesis_closer']; + $lastInParenthesis = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($closer - 1), $nextNonEmpty, true); + + if ($tokens[$lastInParenthesis]['code'] !== \T_COMMA) { + return; + } + + $data = array(); + switch ($tokens[$stackPtr]['code']) { + case \T_ISSET: + $data[] = 'calls to isset()'; + $errorCode = 'FoundInIsset'; + break; + + case \T_UNSET: + $data[] = 'calls to unset()'; + $errorCode = 'FoundInUnset'; + break; + + default: + $data[] = 'function calls'; + $errorCode = 'FoundInFunctionCall'; + break; + } + + $phpcsFile->addError( + 'Trailing comma\'s are not allowed in %s in PHP 7.2 or earlier', + $lastInParenthesis, + $errorCode, + $data + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewShortArraySniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewShortArraySniff.php new file mode 100644 index 00000000..c60ba5c3 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewShortArraySniff.php @@ -0,0 +1,77 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Syntax; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect use of short array syntax which is available since PHP 5.4. + * + * PHP version 5.4 + * + * @link https://wiki.php.net/rfc/shortsyntaxforarrays + * @link https://www.php.net/manual/en/language.types.array.php#language.types.array.syntax + * + * @since 7.0.0 + * @since 9.0.0 Renamed from `ShortArraySniff` to `NewShortArraySniff`. + */ +class NewShortArraySniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + return array( + \T_OPEN_SHORT_ARRAY, + \T_CLOSE_SHORT_ARRAY, + ); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + $error = '%s is not supported in PHP 5.3 or lower'; + $data = array(); + + if ($token['type'] === 'T_OPEN_SHORT_ARRAY') { + $data[] = 'Short array syntax (open)'; + } elseif ($token['type'] === 'T_CLOSE_SHORT_ARRAY') { + $data[] = 'Short array syntax (close)'; + } + + $phpcsFile->addError($error, $stackPtr, 'Found', $data); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/RemovedCurlyBraceArrayAccessSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/RemovedCurlyBraceArrayAccessSniff.php new file mode 100644 index 00000000..b2c29e5f --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/RemovedCurlyBraceArrayAccessSniff.php @@ -0,0 +1,362 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Syntax; + +use PHPCompatibility\Sniff; +use PHPCompatibility\Sniffs\Syntax\NewArrayStringDereferencingSniff; +use PHPCompatibility\Sniffs\Syntax\NewClassMemberAccessSniff; +use PHPCompatibility\Sniffs\Syntax\NewFunctionArrayDereferencingSniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Using the curly brace syntax to access array or string offsets has been deprecated in PHP 7.4. + * + * PHP version 7.4 + * + * @link https://www.php.net/manual/en/migration74.deprecated.php#migration74.deprecated.core.array-string-access-curly-brace + * @link https://wiki.php.net/rfc/deprecate_curly_braces_array_access + * + * @since 9.3.0 + */ +class RemovedCurlyBraceArrayAccessSniff extends Sniff +{ + + /** + * Instance of the NewArrayStringDereferencing sniff. + * + * @since 9.3.0 + * + * @var \PHPCompatibility\Sniffs\Syntax\NewArrayStringDereferencingSniff + */ + private $newArrayStringDereferencing; + + /** + * Target tokens as register by the NewArrayStringDereferencing sniff. + * + * @since 9.3.0 + * + * @var array + */ + private $newArrayStringDereferencingTargets; + + /** + * Instance of the NewClassMemberAccess sniff. + * + * @since 9.3.0 + * + * @var \PHPCompatibility\Sniffs\Syntax\NewClassMemberAccessSniff + */ + private $newClassMemberAccess; + + /** + * Target tokens as register by the NewClassMemberAccess sniff. + * + * @since 9.3.0 + * + * @var array + */ + private $newClassMemberAccessTargets; + + /** + * Instance of the NewFunctionArrayDereferencing sniff. + * + * @since 9.3.0 + * + * @var \PHPCompatibility\Sniffs\Syntax\NewFunctionArrayDereferencingSniff + */ + private $newFunctionArrayDereferencing; + + /** + * Target tokens as register by the NewFunctionArrayDereferencing sniff. + * + * @since 9.3.0 + * + * @var array + */ + private $newFunctionArrayDereferencingTargets; + + + /** + * Constructor. + * + * @since 9.3.0 + */ + public function __construct() + { + $this->newArrayStringDereferencing = new NewArrayStringDereferencingSniff(); + $this->newClassMemberAccess = new NewClassMemberAccessSniff(); + $this->newFunctionArrayDereferencing = new NewFunctionArrayDereferencingSniff(); + } + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.3.0 + * + * @return array + */ + public function register() + { + $targets = array( + array( + \T_VARIABLE, + \T_STRING, // Constants. + ), + ); + + // Registers T_ARRAY, T_OPEN_SHORT_ARRAY and T_CONSTANT_ENCAPSED_STRING. + $additionalTargets = $this->newArrayStringDereferencing->register(); + $this->newArrayStringDereferencingTargets = array_flip($additionalTargets); + $targets[] = $additionalTargets; + + // Registers T_NEW and T_CLONE. + $additionalTargets = $this->newClassMemberAccess->register(); + $this->newClassMemberAccessTargets = array_flip($additionalTargets); + $targets[] = $additionalTargets; + + // Registers T_STRING. + $additionalTargets = $this->newFunctionArrayDereferencing->register(); + $this->newFunctionArrayDereferencingTargets = array_flip($additionalTargets); + $targets[] = $additionalTargets; + + return call_user_func_array('array_merge', $targets); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $braces = array(); + + // Note: Overwriting braces in each `if` is fine as only one will match anyway. + if ($tokens[$stackPtr]['code'] === \T_VARIABLE) { + $braces = $this->isVariableArrayAccess($phpcsFile, $stackPtr); + } + + if (isset($this->newArrayStringDereferencingTargets[$tokens[$stackPtr]['code']])) { + $dereferencing = $this->newArrayStringDereferencing->isArrayStringDereferencing($phpcsFile, $stackPtr); + if (isset($dereferencing['braces'])) { + $braces = $dereferencing['braces']; + } + } + + if (isset($this->newClassMemberAccessTargets[$tokens[$stackPtr]['code']])) { + $braces = $this->newClassMemberAccess->isClassMemberAccess($phpcsFile, $stackPtr); + } + + if (isset($this->newFunctionArrayDereferencingTargets[$tokens[$stackPtr]['code']])) { + $braces = $this->newFunctionArrayDereferencing->isFunctionArrayDereferencing($phpcsFile, $stackPtr); + } + + if (empty($braces) && $tokens[$stackPtr]['code'] === \T_STRING) { + $braces = $this->isConstantArrayAccess($phpcsFile, $stackPtr); + } + + if (empty($braces)) { + return; + } + + foreach ($braces as $open => $close) { + // Some of the functions will sniff for both curlies as well as square braces. + if ($tokens[$open]['code'] !== \T_OPEN_CURLY_BRACKET) { + continue; + } + + // Make sure there is something between the braces, otherwise it's still not curly brace array access. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($open + 1), $close, true); + if ($nextNonEmpty === false) { + // Nothing between the brackets. Parse error. Ignore. + continue; + } + + // OK, so we've found curly brace array access. + $snippet = $phpcsFile->getTokensAsString($stackPtr, (($close - $stackPtr) + 1)); + $fix = $phpcsFile->addFixableWarning( + 'Curly brace syntax for accessing array elements and string offsets has been deprecated in PHP 7.4. Found: %s', + $open, + 'Found', + array($snippet) + ); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($open, '['); + $phpcsFile->fixer->replaceToken($close, ']'); + $phpcsFile->fixer->endChangeset(); + } + } + } + + + /** + * Determine whether a variable is being dereferenced using curly brace syntax. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return array An array with the stack pointers to the open/close braces of + * the curly brace array access, or an empty array if no curly + * brace array access was detected. + */ + protected function isVariableArrayAccess(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $current = $stackPtr; + $braces = array(); + + do { + $current = $phpcsFile->findNext(Tokens::$emptyTokens, ($current + 1), null, true); + if ($current === false) { + break; + } + + // Skip over square bracket array access. Bracket styles can be mixed. + if ($tokens[$current]['code'] === \T_OPEN_SQUARE_BRACKET + && isset($tokens[$current]['bracket_closer']) === true + && $current === $tokens[$current]['bracket_opener'] + ) { + $current = $tokens[$current]['bracket_closer']; + continue; + } + + // Handle property access. + if ($tokens[$current]['code'] === \T_OBJECT_OPERATOR) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($current + 1), null, true); + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_STRING) { + // Live coding or parse error. + break; + } + + $current = $nextNonEmpty; + continue; + } + + if ($tokens[$current]['code'] === \T_OPEN_CURLY_BRACKET) { + if (isset($tokens[$current]['bracket_closer']) === false) { + // Live coding or parse error. + break; + } + + $braces[$current] = $tokens[$current]['bracket_closer']; + + // Continue, just in case there is nested access using curly braces, i.e. `$a{$i}{$j};`. + $current = $tokens[$current]['bracket_closer']; + continue; + } + + // If we're still here, we've reached the end of the variable. + break; + + } while (true); + + return $braces; + } + + + /** + * Determine whether a T_STRING is a constant being dereferenced using curly brace syntax. + * + * {@internal Note: the first braces for array access to a constant, for some unknown reason, + * can never be curlies, but have to be square brackets. + * Subsequent braces can be curlies.} + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return array An array with the stack pointers to the open/close braces of + * the curly brace array access, or an empty array if no curly + * brace array access was detected. + */ + protected function isConstantArrayAccess(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + if ($this->isUseOfGlobalConstant($phpcsFile, $stackPtr) === false + && $tokens[$prevNonEmpty]['code'] !== \T_DOUBLE_COLON // Class constant access. + ) { + return array(); + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return array(); + } + + if ($tokens[$nextNonEmpty]['code'] !== \T_OPEN_SQUARE_BRACKET + || isset($tokens[$nextNonEmpty]['bracket_closer']) === false + ) { + // Array access for constants must start with square brackets. + return array(); + } + + $current = $tokens[$nextNonEmpty]['bracket_closer']; + $braces = array(); + + do { + $current = $phpcsFile->findNext(Tokens::$emptyTokens, ($current + 1), null, true); + if ($current === false) { + break; + } + + // Skip over square bracket array access. Bracket styles can be mixed. + if ($tokens[$current]['code'] === \T_OPEN_SQUARE_BRACKET + && isset($tokens[$current]['bracket_closer']) === true + && $current === $tokens[$current]['bracket_opener'] + ) { + $current = $tokens[$current]['bracket_closer']; + continue; + } + + if ($tokens[$current]['code'] === \T_OPEN_CURLY_BRACKET) { + if (isset($tokens[$current]['bracket_closer']) === false) { + // Live coding or parse error. + break; + } + + $braces[$current] = $tokens[$current]['bracket_closer']; + + // Continue, just in case there is nested access using curly braces, i.e. `$a{$i}{$j};`. + $current = $tokens[$current]['bracket_closer']; + continue; + } + + // If we're still here, we've reached the end of the variable. + break; + + } while (true); + + return $braces; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/RemovedNewReferenceSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/RemovedNewReferenceSniff.php new file mode 100644 index 00000000..ad76828c --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/RemovedNewReferenceSniff.php @@ -0,0 +1,80 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Syntax; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect the use of assigning the return value of `new` by reference. + * + * This syntax has been deprecated since PHP 5.3 and removed in PHP 7.0. + * + * PHP version 5.3 + * PHP version 7.0 + * + * @link https://wiki.php.net/rfc/remove_deprecated_functionality_in_php7 + * + * @since 5.5 + * @since 9.0.0 Renamed from `DeprecatedNewReferenceSniff` to `RemovedNewReferenceSniff`. + */ +class RemovedNewReferenceSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + return array(\T_NEW); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('5.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prevNonEmpty === false || $tokens[$prevNonEmpty]['type'] !== 'T_BITWISE_AND') { + return; + } + + $error = 'Assigning the return value of new by reference is deprecated in PHP 5.3'; + $isError = false; + $errorCode = 'Deprecated'; + + if ($this->supportsAbove('7.0') === true) { + $error .= ' and has been removed in PHP 7.0'; + $isError = true; + $errorCode = 'Removed'; + } + + $this->addMessage($phpcsFile, $error, $stackPtr, $isError, $errorCode); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TextStrings/NewUnicodeEscapeSequenceSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TextStrings/NewUnicodeEscapeSequenceSniff.php new file mode 100644 index 00000000..aa5a39a3 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TextStrings/NewUnicodeEscapeSequenceSniff.php @@ -0,0 +1,162 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\TextStrings; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_Exception as PHPCS_Exception; +use PHP_CodeSniffer_File as File; + +/** + * PHP 7.0 introduced a Unicode codepoint escape sequence. + * + * Strings containing a literal `\u{` followed by an invalid sequence will cause a + * fatal error as of PHP 7.0. + * + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/migration70.new-features.php#migration70.new-features.unicode-codepoint-escape-syntax + * @link https://www.php.net/manual/en/migration70.incompatible.php#migration70.incompatible.strings.unicode-escapes + * @link https://wiki.php.net/rfc/unicode_escape + * @link https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.double + * + * @since 9.3.0 + */ +class NewUnicodeEscapeSequenceSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.3.0 + * + * @return array + */ + public function register() + { + return array( + \T_CONSTANT_ENCAPSED_STRING, + \T_DOUBLE_QUOTED_STRING, + \T_HEREDOC, + ); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check whether this is a single quoted or double quoted string. + if ($tokens[$stackPtr]['code'] === \T_CONSTANT_ENCAPSED_STRING) { + + // Find the start of the - potentially multi-line - text string. + $start = $stackPtr; + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + if ($tokens[$i]['code'] === \T_WHITESPACE) { + continue; + } + + if ($tokens[$i]['code'] === \T_CONSTANT_ENCAPSED_STRING) { + $start = $i; + continue; + } + + break; + } + + try { + $textString = $this->getCompleteTextString($phpcsFile, $start, false); + } catch (PHPCS_Exception $e) { + // Something went wrong determining the start of the text string. + return; + } + + $startQuote = $textString[0]; + $endQuote = substr($textString, -1); + if (($startQuote === "'" && $endQuote === "'") + || $startQuote !== $endQuote + ) { + // Single quoted string, not our concern. + return; + } + } + + $content = $this->stripQuotes($tokens[$stackPtr]['content']); + $count = preg_match_all('`(?<!\\\\)\\\\u\{([^}\n\r]*)(\})?`', $content, $matches, \PREG_SET_ORDER); + if ($count === false || $count === 0) { + return; + } + + foreach ($matches as $match) { + $valid = false; // If the close curly is missing, we have an incomplete escape sequence. + if (isset($match[2])) { + $valid = $this->isValidUnicodeEscapeSequence($match[1]); + } + + if ($this->supportsBelow('5.6') === true && $valid === true) { + $phpcsFile->addError( + 'Unicode codepoint escape sequences are not supported in PHP 5.6 or earlier. Found: %s', + $stackPtr, + 'Found', + array($match[0]) + ); + } + + if ($this->supportsAbove('7.0') === true && $valid === false) { + $phpcsFile->addError( + 'Strings containing a literal \u{ followed by an invalid unicode codepoint escape sequence will cause a fatal error in PHP 7.0 and above. Escape the leading backslash to prevent this. Found: %s', + $stackPtr, + 'Invalid', + array($match[0]) + ); + } + } + } + + + /** + * Verify if the codepoint in a unicode escape sequence is valid. + * + * @since 9.3.0 + * + * @param string $codepoint The codepoint as a string. + * + * @return bool + */ + protected function isValidUnicodeEscapeSequence($codepoint) + { + if (trim($codepoint) === '') { + return false; + } + + // Check if it's a valid hex codepoint. + if (preg_match('`^[0-9A-F]+$`iD', $codepoint, $match) !== 1) { + return false; + } + + if (hexdec($codepoint) > 1114111) { + // Outside of the maximum permissable range. + return false; + } + + return true; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TypeCasts/NewTypeCastsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TypeCasts/NewTypeCastsSniff.php new file mode 100644 index 00000000..12e47318 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TypeCasts/NewTypeCastsSniff.php @@ -0,0 +1,222 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\TypeCasts; + +use PHPCompatibility\AbstractNewFeatureSniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; + +/** + * Detect use of newly introduced type casts. + * + * PHP version All + * + * @link https://www.php.net/manual/en/language.types.type-juggling.php#language.types.typecasting + * + * @since 8.0.1 + */ +class NewTypeCastsSniff extends AbstractNewFeatureSniff +{ + + /** + * A list of new type casts, not present in older versions. + * + * The array lists : version number with false (not present) or true (present). + * If's sufficient to list the first version where the keyword appears. + * + * @since 8.0.1 + * + * @var array(string => array(string => bool|string)) + */ + protected $newTypeCasts = array( + 'T_UNSET_CAST' => array( + '4.4' => false, + '5.0' => true, + 'description' => 'The unset cast', + ), + 'T_BINARY_CAST' => array( + '5.2.0' => false, + '5.2.1' => true, + 'description' => 'The binary cast', + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.0.1 + * + * @return array + */ + public function register() + { + $tokens = array(); + foreach ($this->newTypeCasts as $token => $versions) { + if (\defined($token)) { + $tokens[] = constant($token); + } + } + + /* + * Work around tokenizer issues. + * + * - (binary) cast is incorrectly tokenized as T_STRING_CAST by PHP and PHPCS. + * - b"something" binary cast is incorrectly tokenized as T_CONSTANT_ENCAPSED_STRING by PHP and PHPCS. + * - Since PHPCS 3.4.0, PHPCS *will* tokenize these correctly. + * + * @link https://github.com/squizlabs/PHP_CodeSniffer/issues/1574 + */ + if (version_compare(PHPCSHelper::getVersion(), '3.4.0', '<') === true) { + $tokens[] = \T_STRING_CAST; + $tokens[] = \T_CONSTANT_ENCAPSED_STRING; + } + + return $tokens; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.0.1 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenType = $tokens[$stackPtr]['type']; + + // Detect incorrectly tokenized binary casts. + if (isset($this->newTypeCasts[$tokenType]) === false) { + $tokenContent = $tokens[$stackPtr]['content']; + switch ($tokenType) { + case 'T_STRING_CAST': + if (preg_match('`^\(\s*binary\s*\)$`i', $tokenContent) !== 1) { + return; + } + + $tokenType = 'T_BINARY_CAST'; + break; + + case 'T_CONSTANT_ENCAPSED_STRING': + if ((strpos($tokenContent, 'b"') === 0 && substr($tokenContent, -1) === '"') + || (strpos($tokenContent, "b'") === 0 && substr($tokenContent, -1) === "'") + ) { + $tokenType = 'T_BINARY_CAST'; + } else { + return; + } + break; + + } + } + + // If the translation did not yield one of the tokens we are looking for, bow out. + if (isset($this->newTypeCasts[$tokenType]) === false) { + return; + } + + $itemInfo = array( + 'name' => $tokenType, + 'content' => $tokens[$stackPtr]['content'], + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 8.0.1 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newTypeCasts[$itemInfo['name']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 8.0.1 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('description'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 8.0.1 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['description'] = $itemArray['description']; + + return $errorInfo; + } + + + /** + * Filter the error message before it's passed to PHPCS. + * + * @since 8.0.1 + * + * @param string $error The error message which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return string + */ + protected function filterErrorMsg($error, array $itemInfo, array $errorInfo) + { + return $error . '. Found: %s'; + } + + + /** + * Filter the error data before it's passed to PHPCS. + * + * @since 8.0.1 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + $data[0] = $errorInfo['description']; + $data[] = $itemInfo['content']; + return $data; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TypeCasts/RemovedTypeCastsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TypeCasts/RemovedTypeCastsSniff.php new file mode 100644 index 00000000..3791f0b5 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TypeCasts/RemovedTypeCastsSniff.php @@ -0,0 +1,158 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\TypeCasts; + +use PHPCompatibility\AbstractRemovedFeatureSniff; +use PHP_CodeSniffer_File as File; + +/** + * Detect use of deprecated/removed type casts. + * + * PHP version All + * + * @link https://www.php.net/manual/en/language.types.type-juggling.php#language.types.typecasting + * @link https://wiki.php.net/rfc/deprecations_php_7_2#unset_cast + * @link https://wiki.php.net/rfc/deprecations_php_7_4#the_real_type + * + * @since 8.0.1 + * @since 9.0.0 Renamed from `DeprecatedTypeCastsSniff` to `RemovedTypeCastsSniff`. + */ +class RemovedTypeCastsSniff extends AbstractRemovedFeatureSniff +{ + /** + * A list of deprecated and removed type casts with their alternatives. + * + * The array lists : version number with false (deprecated) or true (removed) and an alternative function. + * If no alternative exists, it is NULL, i.e, the function should just not be used. + * + * @since 8.0.1 + * + * @var array(string => array(string => bool|string)) + */ + protected $deprecatedTypeCasts = array( + 'T_UNSET_CAST' => array( + '7.2' => false, + 'alternative' => 'unset()', + 'description' => 'unset', + ), + 'T_DOUBLE_CAST' => array( + '7.4' => false, + 'alternative' => '(float)', + 'description' => 'real', + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.0.1 + * + * @return array + */ + public function register() + { + $tokens = array(); + foreach ($this->deprecatedTypeCasts as $token => $versions) { + $tokens[] = constant($token); + } + + return $tokens; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.0.1 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenType = $tokens[$stackPtr]['type']; + + // Special case `T_DOUBLE_CAST` as the same token is used for (float) and (double) casts. + if ($tokenType === 'T_DOUBLE_CAST' && strpos($tokens[$stackPtr]['content'], 'real') === false) { + // Float/double casts, not (real) cast. + return; + } + + $itemInfo = array( + 'name' => $tokenType, + 'description' => $this->deprecatedTypeCasts[$tokenType]['description'], + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 8.0.1 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('description', 'alternative'); + } + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 8.0.1 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->deprecatedTypeCasts[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 8.0.1 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The %s cast is '; + } + + + /** + * Filter the error data before it's passed to PHPCS. + * + * @since 8.0.1 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + $data[0] = $itemInfo['description']; + return $data; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPCSSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPCSSniff.php new file mode 100644 index 00000000..1e79873c --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPCSSniff.php @@ -0,0 +1,187 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Upgrade; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; + +/** + * Add a notification for users of low PHPCS versions. + * + * Originally PHPCompatibility supported PHPCS 1.5.x, 2.x and since PHPCompatibility 8.0.0, 3.x. + * Support for PHPCS < 2.3.0 has been dropped in PHPCompatibility 9.0.0. + * + * The standard will - up to a point - still work for users of lower + * PHPCS versions, but will give less accurate results and may throw + * notices and warnings (or even fatal out). + * + * This sniff adds an explicit error/warning for users of the standard + * using a PHPCS version below the recommended version. + * + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/688 + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/835 + * + * @since 8.2.0 + */ +class LowPHPCSSniff extends Sniff +{ + /** + * The minimum supported PHPCS version. + * + * Users on PHPCS versions below this will see an ERROR message. + * + * @since 8.2.0 + * @since 9.3.0 Changed from $minSupportedVersion property to a constant. + * + * @var string + */ + const MIN_SUPPORTED_VERSION = '2.3.0'; + + /** + * The minimum recommended PHPCS version. + * + * Users on PHPCS versions below this will see a WARNING. + * + * @since 8.2.0 + * @since 9.3.0 Changed from $minRecommendedVersion property to a constant. + * + * @var string + */ + const MIN_RECOMMENDED_VERSION = '2.6.0'; + + /** + * Keep track of whether this sniff needs to actually run. + * + * This will be set to `false` when either a high enough PHPCS + * version is detected or once the error/warning has been thrown, + * to make sure that the notice will only be thrown once per run. + * + * @since 8.2.0 + * + * @var bool + */ + private $examine = true; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.2.0 + * + * @return array + */ + public function register() + { + return array( + \T_OPEN_TAG, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process(File $phpcsFile, $stackPtr) + { + // Don't do anything if the warning has already been thrown or is not necessary. + if ($this->examine === false) { + return ($phpcsFile->numTokens + 1); + } + + $phpcsVersion = PHPCSHelper::getVersion(); + + // Don't do anything if the PHPCS version used is above the minimum recommended version. + if (version_compare($phpcsVersion, self::MIN_RECOMMENDED_VERSION, '>=')) { + $this->examine = false; + return ($phpcsFile->numTokens + 1); + } + + if (version_compare($phpcsVersion, self::MIN_SUPPORTED_VERSION, '<')) { + $isError = true; + $message = 'IMPORTANT: Please be advised that the minimum PHP_CodeSniffer version the PHPCompatibility standard supports is %s. You are currently using PHP_CodeSniffer %s. Please upgrade your PHP_CodeSniffer installation. The recommended version of PHP_CodeSniffer for PHPCompatibility is %s or higher.'; + $errorCode = 'Unsupported_' . $this->stringToErrorCode(self::MIN_SUPPORTED_VERSION); + $replacements = array( + self::MIN_SUPPORTED_VERSION, + $phpcsVersion, + self::MIN_RECOMMENDED_VERSION, + $errorCode, + ); + } else { + $isError = false; + $message = 'IMPORTANT: Please be advised that for the most reliable PHPCompatibility results, PHP_CodeSniffer %s or higher should be used. Support for lower versions will be dropped in the foreseeable future. You are currently using PHP_CodeSniffer %s. Please upgrade your PHP_CodeSniffer installation to version %s or higher.'; + $errorCode = 'BelowRecommended_' . $this->stringToErrorCode(self::MIN_RECOMMENDED_VERSION); + $replacements = array( + self::MIN_RECOMMENDED_VERSION, + $phpcsVersion, + self::MIN_RECOMMENDED_VERSION, + $errorCode, + ); + } + + /* + * Figure out the report width to determine how long the delimiter lines should be. + * + * This is not an exact calculation as there are a number of unknowns at the time the + * notice is thrown (whether there are other notices for the file, whether those are + * warnings or errors, whether there are auto-fixable issues etc). + * + * In other words, this is just an approximation to get a reasonably stable and + * readable message layout format. + * + * {@internal + * PHPCS has had some changes as to how the messages display over the years. + * Most significantly in 2.4.0 it was attempted to solve an issue with messages + * containing new lines. Unfortunately, that solution is buggy. + * An improved version has been pulled upstream and will hopefully make it + * into PHPCS 3.3.1/3.4.0. + * + * Anyway, this means that instead of new lines, delimiter lines will be used to improved + * the readability of the (long) message. + * + * Also, as of PHPCS 2.2.0, the report width when using the `-s` option is 8 wider than + * it should be. A patch for that is included in the same upstream PR. + * + * If/when the upstream PR has been merged and the minimum supported/recommended version + * of PHPCompatibility would go beyond that, the below code should be adjusted.} + */ + $reportWidth = PHPCSHelper::getCommandLineData($phpcsFile, 'reportWidth'); + if (empty($reportWidth)) { + $reportWidth = 80; + } + $showSources = PHPCSHelper::getCommandLineData($phpcsFile, 'showSources'); + if ($showSources === true) { + $reportWidth += 6; + } + + $messageWidth = ($reportWidth - 15); // 15 is length of " # | WARNING | ". + $delimiterLine = str_repeat('-', ($messageWidth)); + $disableNotice = 'To disable this notice, add --exclude=PHPCompatibility.Upgrade.LowPHPCS to your command or add <exclude name="PHPCompatibility.Upgrade.LowPHPCS.%s"/> to your custom ruleset. '; + $thankYou = 'Thank you for using PHPCompatibility!'; + + $message .= ' ' . $delimiterLine; + $message .= ' ' . $disableNotice; + $message .= ' ' . $delimiterLine; + $message .= ' ' . $thankYou; + + $this->addMessage($phpcsFile, $message, 0, $isError, $errorCode, $replacements); + + $this->examine = false; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPSniff.php new file mode 100644 index 00000000..7a171633 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPSniff.php @@ -0,0 +1,182 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Upgrade; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; + +/** + * Add a notification for users of low PHP versions. + * + * Originally PHPCompatibility supported PHP 5.1 and higher. + * As of PHPCompatibility 8.0.0, support for PHP < 5.3 has been dropped. + * + * The intention is to drop support for PHP 5.3 in the (near) future. + * + * This sniff adds an explicit error/warning for users of the standard + * using a PHP version below the recommended version. + * + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/835 + * + * @since 9.3.0 + */ +class LowPHPSniff extends Sniff +{ + /** + * The minimum supported PHP version. + * + * Users on PHP versions below this will see an ERROR message. + * + * @since 9.3.0 + * + * @var string + */ + const MIN_SUPPORTED_VERSION = '5.3'; + + /** + * The minimum recommended PHP version. + * + * Users on PHP versions below this will see a WARNING. + * + * @since 9.3.0 + * + * @var string + */ + const MIN_RECOMMENDED_VERSION = '5.4'; + + /** + * Keep track of whether this sniff needs to actually run. + * + * This will be set to `false` when either a high enough PHP + * version is detected or once the error/warning has been thrown, + * to make sure that the notice will only be thrown once per run. + * + * @since 9.3.0 + * + * @var bool + */ + private $examine = true; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.3.0 + * + * @return array + */ + public function register() + { + return array( + \T_OPEN_TAG, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process(File $phpcsFile, $stackPtr) + { + // Don't do anything if the warning has already been thrown or is not necessary. + if ($this->examine === false) { + return ($phpcsFile->numTokens + 1); + } + + $phpVersion = phpversion(); + + // Don't do anything if the PHPCS version used is above the minimum recommended version. + if (version_compare($phpVersion, self::MIN_RECOMMENDED_VERSION, '>=')) { + $this->examine = false; + return ($phpcsFile->numTokens + 1); + } + + if (version_compare($phpVersion, self::MIN_SUPPORTED_VERSION, '<')) { + $isError = true; + $message = 'IMPORTANT: Please be advised that the minimum PHP version the PHPCompatibility standard supports is %s. You are currently using PHP %s. Please upgrade your PHP installation. The recommended version of PHP for PHPCompatibility is %s or higher.'; + $errorCode = 'Unsupported_' . $this->stringToErrorCode(self::MIN_SUPPORTED_VERSION); + $replacements = array( + self::MIN_SUPPORTED_VERSION, + $phpVersion, + self::MIN_RECOMMENDED_VERSION, + $errorCode, + ); + } else { + $isError = false; + $message = 'IMPORTANT: Please be advised that for the most reliable PHPCompatibility results, PHP %s or higher should be used. Support for lower versions will be dropped in the foreseeable future. You are currently using PHP %s. Please upgrade your PHP installation to version %s or higher.'; + $errorCode = 'BelowRecommended_' . $this->stringToErrorCode(self::MIN_RECOMMENDED_VERSION); + $replacements = array( + self::MIN_RECOMMENDED_VERSION, + $phpVersion, + self::MIN_RECOMMENDED_VERSION, + $errorCode, + ); + } + + /* + * Figure out the report width to determine how long the delimiter lines should be. + * + * This is not an exact calculation as there are a number of unknowns at the time the + * notice is thrown (whether there are other notices for the file, whether those are + * warnings or errors, whether there are auto-fixable issues etc). + * + * In other words, this is just an approximation to get a reasonably stable and + * readable message layout format. + * + * {@internal + * PHPCS has had some changes as to how the messages display over the years. + * Most significantly in 2.4.0 it was attempted to solve an issue with messages + * containing new lines. Unfortunately, that solution is buggy. + * An improved version has been pulled upstream and will hopefully make it + * into PHPCS 3.3.1/3.4.0. + * + * Anyway, this means that instead of new lines, delimiter lines will be used to improved + * the readability of the (long) message. + * + * Also, as of PHPCS 2.2.0, the report width when using the `-s` option is 8 wider than + * it should be. A patch for that is included in the same upstream PR. + * + * If/when the upstream PR has been merged and the minimum supported/recommended version + * of PHPCompatibility would go beyond that, the below code should be adjusted.} + */ + $reportWidth = PHPCSHelper::getCommandLineData($phpcsFile, 'reportWidth'); + if (empty($reportWidth)) { + $reportWidth = 80; + } + $showSources = PHPCSHelper::getCommandLineData($phpcsFile, 'showSources'); + if ($showSources === true) { + $reportWidth += 6; + } + + $messageWidth = ($reportWidth - 15); // 15 is length of " # | WARNING | ". + $delimiterLine = str_repeat('-', ($messageWidth)); + $disableNotice = 'To disable this notice, add --exclude=PHPCompatibility.Upgrade.LowPHP to your command or add <exclude name="PHPCompatibility.Upgrade.LowPHP.%s"/> to your custom ruleset. '; + $thankYou = 'Thank you for using PHPCompatibility!'; + + $message .= ' ' . $delimiterLine; + $message .= ' ' . $disableNotice; + $message .= ' ' . $delimiterLine; + $message .= ' ' . $thankYou; + + $this->addMessage($phpcsFile, $message, 0, $isError, $errorCode, $replacements); + + $this->examine = false; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/UseDeclarations/NewGroupUseDeclarationsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/UseDeclarations/NewGroupUseDeclarationsSniff.php new file mode 100644 index 00000000..a681a4a3 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/UseDeclarations/NewGroupUseDeclarationsSniff.php @@ -0,0 +1,118 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\UseDeclarations; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect group use declarations as introduced in PHP 7.0. + * + * Checks for: + * - Group use statements as introduced in PHP 7.0. + * - Trailing comma's in group use statements as allowed since PHP 7.2. + * + * PHP version 7.0 + * PHP version 7.2 + * + * @link https://www.php.net/manual/en/migration70.new-features.php#migration70.new-features.group-use-declarations + * @link https://www.php.net/manual/en/migration72.new-features.php#migration72.new-features.trailing-comma-in-grouped-namespaces + * @link https://wiki.php.net/rfc/group_use_declarations + * @link https://wiki.php.net/rfc/list-syntax-trailing-commas + * @link https://www.php.net/manual/en/language.namespaces.importing.php#language.namespaces.importing.group + * + * @since 7.0.0 + * @since 8.0.1 Now also checks for trailing comma's in group `use` declarations. + */ +class NewGroupUseDeclarationsSniff extends Sniff +{ + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + if (\defined('T_OPEN_USE_GROUP')) { + return array(\T_OPEN_USE_GROUP); + } else { + return array(\T_USE); + } + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('7.1') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Deal with PHPCS pre-2.6.0. + if ($token['code'] === \T_USE) { + $hasCurlyBrace = $phpcsFile->findNext(\T_OPEN_CURLY_BRACKET, ($stackPtr + 1), null, false, null, true); + if ($hasCurlyBrace === false) { + return; + } + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($hasCurlyBrace - 1), null, true); + if ($prevToken === false || $tokens[$prevToken]['code'] !== \T_NS_SEPARATOR) { + return; + } + + $stackPtr = $hasCurlyBrace; + } + + // Still here ? In that case, it is a group use statement. + if ($this->supportsBelow('5.6') === true) { + $phpcsFile->addError( + 'Group use declarations are not allowed in PHP 5.6 or earlier', + $stackPtr, + 'Found' + ); + } + + $closers = array(\T_CLOSE_CURLY_BRACKET); + if (\defined('T_CLOSE_USE_GROUP')) { + $closers[] = \T_CLOSE_USE_GROUP; + } + + $closeCurly = $phpcsFile->findNext($closers, ($stackPtr + 1), null, false, null, true); + if ($closeCurly === false) { + return; + } + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($closeCurly - 1), null, true); + if ($tokens[$prevToken]['code'] === \T_COMMA) { + $phpcsFile->addError( + 'Trailing comma\'s are not allowed in group use statements in PHP 7.1 or earlier', + $prevToken, + 'TrailingCommaFound' + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/UseDeclarations/NewUseConstFunctionSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/UseDeclarations/NewUseConstFunctionSniff.php new file mode 100644 index 00000000..2d166fb5 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/UseDeclarations/NewUseConstFunctionSniff.php @@ -0,0 +1,109 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\UseDeclarations; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect importing constants and functions via a `use` statement. + * + * The `use` operator has been extended to support importing functions and + * constants in addition to classes. This is achieved via the `use function` + * and `use const` constructs, respectively. + * + * PHP version 5.6 + * + * @link https://www.php.net/manual/en/migration56.new-features.php#migration56.new-features.use + * @link https://wiki.php.net/rfc/use_function + * @link https://www.php.net/manual/en/language.namespaces.importing.php + * + * @since 7.1.4 + */ +class NewUseConstFunctionSniff extends Sniff +{ + + /** + * A list of keywords that can follow use statements. + * + * @since 7.1.4 + * + * @var array(string => string) + */ + protected $validUseNames = array( + 'const' => true, + 'function' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.1.4 + * + * @return array + */ + public function register() + { + return array(\T_USE); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.5') !== true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + // Live coding. + return; + } + + if (isset($this->validUseNames[strtolower($tokens[$nextNonEmpty]['content'])]) === false) { + // Not a `use const` or `use function` statement. + return; + } + + // `use const` and `use function` have to be followed by the function/constant name. + $functionOrConstName = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), null, true); + if ($functionOrConstName === false + // Identifies as T_AS or T_STRING, this covers both. + || ($tokens[$functionOrConstName]['content'] === 'as' + || $tokens[$functionOrConstName]['code'] === \T_COMMA) + ) { + // Live coding or incorrect use of reserved keyword, but that is + // covered by the ForbiddenNames sniff. + return; + } + + // Still here ? In that case we have encountered a `use const` or `use function` statement. + $phpcsFile->addError( + 'Importing functions and constants through a "use" statement is not supported in PHP 5.5 or lower.', + $nextNonEmpty, + 'Found' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/ForbiddenGlobalVariableVariableSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/ForbiddenGlobalVariableVariableSniff.php new file mode 100644 index 00000000..c7f715d2 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/ForbiddenGlobalVariableVariableSniff.php @@ -0,0 +1,125 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Variables; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect use of `global` with variable variables, support for which has been removed in PHP 7.0. + * + * PHP version 7.0 + * + * @link https://wiki.php.net/rfc/uniform_variable_syntax#global_keyword_takes_only_simple_variables + * + * @since 7.0.0 + */ +class ForbiddenGlobalVariableVariableSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + return array(\T_GLOBAL); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $endOfStatement = $phpcsFile->findNext(array(\T_SEMICOLON, \T_CLOSE_TAG), ($stackPtr + 1)); + if ($endOfStatement === false) { + // No semi-colon - live coding. + return; + } + + for ($ptr = ($stackPtr + 1); $ptr <= $endOfStatement; $ptr++) { + $errorThrown = false; + $nextComma = $phpcsFile->findNext(\T_COMMA, $ptr, $endOfStatement, false, null, true); + $varEnd = ($nextComma === false) ? $endOfStatement : $nextComma; + $variable = $phpcsFile->findNext(\T_VARIABLE, $ptr, $varEnd); + $varString = trim($phpcsFile->getTokensAsString($ptr, ($varEnd - $ptr))); + $data = array($varString); + + if ($variable !== false) { + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($variable - 1), $ptr, true); + + if ($prev !== false && $tokens[$prev]['type'] === 'T_DOLLAR') { + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($variable + 1), $varEnd, true); + + if ($next !== false + && \in_array($tokens[$next]['code'], array(\T_OPEN_SQUARE_BRACKET, \T_OBJECT_OPERATOR, \T_DOUBLE_COLON), true) === true + ) { + $phpcsFile->addError( + 'Global with variable variables is not allowed since PHP 7.0. Found %s', + $variable, + 'Found', + $data + ); + $errorThrown = true; + } else { + $phpcsFile->addWarning( + 'Global with anything other than bare variables is discouraged since PHP 7.0. Found %s', + $variable, + 'NonBareVariableFound', + $data + ); + $errorThrown = true; + } + } + } + + if ($errorThrown === false) { + $dollar = $phpcsFile->findNext(\T_DOLLAR, $ptr, $varEnd); + if ($dollar !== false) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($dollar + 1), $varEnd, true); + if ($tokens[$next]['code'] === \T_OPEN_CURLY_BRACKET) { + $phpcsFile->addWarning( + 'Global with anything other than bare variables is discouraged since PHP 7.0. Found %s', + $dollar, + 'NonBareVariableFound', + $data + ); + } + } + } + + // Move the stack pointer forward to the next variable for multi-variable statements. + if ($nextComma === false) { + break; + } + $ptr = $nextComma; + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/ForbiddenThisUseContextsSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/ForbiddenThisUseContextsSniff.php new file mode 100644 index 00000000..fc0ddc65 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/ForbiddenThisUseContextsSniff.php @@ -0,0 +1,425 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Variables; + +use PHPCompatibility\Sniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect using `$this` in incompatible contexts. + * + * "Whilst `$this` is considered a special variable in PHP, it lacked proper checks + * to ensure it wasn't used as a variable name or reassigned. This has now been + * rectified to ensure that `$this` cannot be a user-defined variable, reassigned + * to a different value, or be globalised." + * + * This sniff only addresses those situations which did *not* throw an error prior + * to PHP 7.1, either at all or only in PHP 7.0. + * In other words, the following situation, while mentioned in the RFC, will NOT + * be sniffed for: + * - Using $this as static variable. (error _message_ change only). + * + * Also, the changes with relation to assigning `$this` dynamically can not be + * sniffed for reliably, so are not covered by this sniff. + * - Disable ability to re-assign `$this` indirectly through `$$`. + * - Disable ability to re-assign `$this` indirectly through reference. + * - Disable ability to re-assign `$this` indirectly through `extract()` and `parse_str()`. + * + * Other changes not (yet) covered: + * - `get_defined_vars()` always doesn't show value of variable `$this`. + * - Always show true `$this` value in magic method `__call()`. + * {@internal This could possibly be covered. Similar logic as "outside object context", + * but with function name check and supportsBelow('7.0').} + * + * PHP version 7.1 + * + * @link https://www.php.net/manual/en/migration71.other-changes.php#migration71.other-changes.inconsistency-fixes-to-this + * @link https://wiki.php.net/rfc/this_var + * + * @since 9.1.0 + */ +class ForbiddenThisUseContextsSniff extends Sniff +{ + + /** + * OO scope tokens. + * + * Duplicate of Tokens::$ooScopeTokens array in PHPCS which was added in 3.1.0. + * + * @since 9.1.0 + * + * @var array + */ + private $ooScopeTokens = array( + 'T_CLASS' => \T_CLASS, + 'T_INTERFACE' => \T_INTERFACE, + 'T_TRAIT' => \T_TRAIT, + ); + + /** + * Scopes to skip over when examining the contents of functions. + * + * @since 9.1.0 + * + * @var array + */ + private $skipOverScopes = array( + 'T_FUNCTION' => true, + 'T_CLOSURE' => true, + ); + + /** + * Valid uses of $this in plain functions or methods outside object context. + * + * @since 9.1.0 + * + * @var array + */ + private $validUseOutsideObject = array( + \T_ISSET => true, + \T_EMPTY => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.1.0 + * + * @return array + */ + public function register() + { + if (\defined('T_ANON_CLASS')) { + $this->ooScopeTokens['T_ANON_CLASS'] = \T_ANON_CLASS; + } + + $this->skipOverScopes += $this->ooScopeTokens; + + return array( + \T_FUNCTION, + \T_CLOSURE, + \T_GLOBAL, + \T_CATCH, + \T_FOREACH, + \T_UNSET, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.1') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$stackPtr]['code']) { + case \T_FUNCTION: + $this->isThisUsedAsParameter($phpcsFile, $stackPtr); + $this->isThisUsedOutsideObjectContext($phpcsFile, $stackPtr); + break; + + case \T_CLOSURE: + $this->isThisUsedAsParameter($phpcsFile, $stackPtr); + break; + + case \T_GLOBAL: + /* + * $this can no longer be imported using the `global` keyword. + * This worked in PHP 7.0, though in PHP 5.x, it would throw a + * fatal "Cannot re-assign $this" error. + */ + $endOfStatement = $phpcsFile->findNext(array(\T_SEMICOLON, \T_CLOSE_TAG), ($stackPtr + 1)); + if ($endOfStatement === false) { + // No semi-colon - live coding. + return; + } + + for ($i = ($stackPtr + 1); $i < $endOfStatement; $i++) { + if ($tokens[$i]['code'] !== \T_VARIABLE || $tokens[$i]['content'] !== '$this') { + continue; + } + + $phpcsFile->addError( + '"$this" can no longer be used with the "global" keyword since PHP 7.1.', + $i, + 'Global' + ); + } + + break; + + case \T_CATCH: + /* + * $this can no longer be used as a catch variable. + */ + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) { + return; + } + + $varPtr = $phpcsFile->findNext( + \T_VARIABLE, + ($tokens[$stackPtr]['parenthesis_opener'] + 1), + $tokens[$stackPtr]['parenthesis_closer'] + ); + + if ($varPtr === false || $tokens[$varPtr]['content'] !== '$this') { + return; + } + + $phpcsFile->addError( + '"$this" can no longer be used as a catch variable since PHP 7.1.', + $varPtr, + 'Catch' + ); + + break; + + case \T_FOREACH: + /* + * $this can no longer be used as a foreach *value* variable. + * This worked in PHP 7.0, though in PHP 5.x, it would throw a + * fatal "Cannot re-assign $this" error. + */ + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) { + return; + } + + $stopPtr = $phpcsFile->findPrevious( + array(\T_AS, \T_DOUBLE_ARROW), + ($tokens[$stackPtr]['parenthesis_closer'] - 1), + $tokens[$stackPtr]['parenthesis_opener'] + ); + if ($stopPtr === false) { + return; + } + + $valueVarPtr = $phpcsFile->findNext( + \T_VARIABLE, + ($stopPtr + 1), + $tokens[$stackPtr]['parenthesis_closer'] + ); + if ($valueVarPtr === false || $tokens[$valueVarPtr]['content'] !== '$this') { + return; + } + + $afterThis = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($valueVarPtr + 1), + $tokens[$stackPtr]['parenthesis_closer'], + true + ); + + if ($afterThis !== false + && ($tokens[$afterThis]['code'] === \T_OBJECT_OPERATOR + || $tokens[$afterThis]['code'] === \T_DOUBLE_COLON) + ) { + return; + } + + $phpcsFile->addError( + '"$this" can no longer be used as value variable in a foreach control structure since PHP 7.1.', + $valueVarPtr, + 'ForeachValueVar' + ); + + break; + + case \T_UNSET: + /* + * $this can no longer be unset. + */ + $openParenthesis = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($openParenthesis === false + || $tokens[$openParenthesis]['code'] !== \T_OPEN_PARENTHESIS + || isset($tokens[$openParenthesis]['parenthesis_closer']) === false + ) { + return; + } + + for ($i = ($openParenthesis + 1); $i < $tokens[$openParenthesis]['parenthesis_closer']; $i++) { + if ($tokens[$i]['code'] !== \T_VARIABLE || $tokens[$i]['content'] !== '$this') { + continue; + } + + $afterThis = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($i + 1), + $tokens[$openParenthesis]['parenthesis_closer'], + true + ); + + if ($afterThis !== false + && ($tokens[$afterThis]['code'] === \T_OBJECT_OPERATOR + || $tokens[$afterThis]['code'] === \T_DOUBLE_COLON + || $tokens[$afterThis]['code'] === \T_OPEN_SQUARE_BRACKET) + ) { + $i = $afterThis; + continue; + } + + $phpcsFile->addError( + '"$this" can no longer be unset since PHP 7.1.', + $i, + 'Unset' + ); + } + + break; + } + } + + /** + * Check if $this is used as a parameter in a function declaration. + * + * $this can no longer be used as a parameter in a *global* function. + * Use as a parameter in a method was already an error prior to PHP 7.1. + * + * @since 9.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + protected function isThisUsedAsParameter(File $phpcsFile, $stackPtr) + { + if ($this->validDirectScope($phpcsFile, $stackPtr, $this->ooScopeTokens) !== false) { + return; + } + + $params = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($params)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + foreach ($params as $param) { + if ($param['name'] !== '$this') { + continue; + } + + if ($tokens[$stackPtr]['code'] === \T_FUNCTION) { + $phpcsFile->addError( + '"$this" can no longer be used as a parameter since PHP 7.1.', + $param['token'], + 'FunctionParam' + ); + } else { + $phpcsFile->addError( + '"$this" can no longer be used as a closure parameter since PHP 7.0.7.', + $param['token'], + 'ClosureParam' + ); + } + } + } + + /** + * Check if $this is used in a plain function or method. + * + * Prior to PHP 7.1, this would result in an "undefined variable" notice + * and execution would continue with $this regarded as `null`. + * As of PHP 7.1, this throws an exception. + * + * Note: use within isset() and empty() to check object context is still allowed. + * Note: $this can still be used within a closure. + * + * @since 9.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + protected function isThisUsedOutsideObjectContext(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener'], $tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + if ($this->validDirectScope($phpcsFile, $stackPtr, $this->ooScopeTokens) !== false) { + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + if ($methodProps['is_static'] === false) { + return; + } else { + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === '__call') { + /* + * This is an exception. + * @link https://wiki.php.net/rfc/this_var#always_show_true_this_value_in_magic_method_call + */ + return; + } + } + } + + for ($i = ($tokens[$stackPtr]['scope_opener'] + 1); $i < $tokens[$stackPtr]['scope_closer']; $i++) { + if (isset($this->skipOverScopes[$tokens[$i]['type']])) { + if (isset($tokens[$i]['scope_closer']) === false) { + // Live coding or parse error, will only lead to inaccurate results. + return; + } + + // Skip over nested structures. + $i = $tokens[$i]['scope_closer']; + continue; + } + + if ($tokens[$i]['code'] !== \T_VARIABLE || $tokens[$i]['content'] !== '$this') { + continue; + } + + if (isset($tokens[$i]['nested_parenthesis']) === true) { + $nestedParenthesis = $tokens[$i]['nested_parenthesis']; + $nestedOpenParenthesis = array_keys($nestedParenthesis); + $lastOpenParenthesis = array_pop($nestedOpenParenthesis); + + $previousNonEmpty = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($lastOpenParenthesis - 1), + null, + true, + null, + true + ); + + if (isset($this->validUseOutsideObject[$tokens[$previousNonEmpty]['code']])) { + continue; + } + } + + $phpcsFile->addError( + '"$this" can no longer be used in a plain function or method since PHP 7.1.', + $i, + 'OutsideObjectContext' + ); + } + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/NewUniformVariableSyntaxSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/NewUniformVariableSyntaxSniff.php new file mode 100644 index 00000000..f7948079 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/NewUniformVariableSyntaxSniff.php @@ -0,0 +1,114 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Variables; + +use PHPCompatibility\Sniff; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * The interpretation of variable variables has changed in PHP 7.0. + * + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/migration70.incompatible.php#migration70.incompatible.variable-handling.indirect + * @link https://wiki.php.net/rfc/uniform_variable_syntax + * + * @since 7.1.2 + * @since 9.0.0 Renamed from `VariableVariablesSniff` to `NewUniformVariableSyntaxSniff`. + */ +class NewUniformVariableSyntaxSniff extends Sniff +{ + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.1.2 + * + * @return array + */ + public function register() + { + return array(\T_VARIABLE); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.1.2 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + // Verify that the next token is a square open bracket. If not, bow out. + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); + + if ($nextToken === false || $tokens[$nextToken]['code'] !== \T_OPEN_SQUARE_BRACKET || isset($tokens[$nextToken]['bracket_closer']) === false) { + return; + } + + // The previous non-empty token has to be a $, -> or ::. + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true, null, true); + if ($prevToken === false || \in_array($tokens[$prevToken]['code'], array(\T_DOLLAR, \T_OBJECT_OPERATOR, \T_DOUBLE_COLON), true) === false) { + return; + } + + // For static object calls, it only applies when this is a function call. + if ($tokens[$prevToken]['code'] === \T_DOUBLE_COLON) { + $hasBrackets = $tokens[$nextToken]['bracket_closer']; + while (($hasBrackets = $phpcsFile->findNext(Tokens::$emptyTokens, ($hasBrackets + 1), null, true, null, true)) !== false) { + if ($tokens[$hasBrackets]['code'] === \T_OPEN_SQUARE_BRACKET) { + if (isset($tokens[$hasBrackets]['bracket_closer'])) { + $hasBrackets = $tokens[$hasBrackets]['bracket_closer']; + continue; + } else { + // Live coding. + return; + } + + } elseif ($tokens[$hasBrackets]['code'] === \T_OPEN_PARENTHESIS) { + // Caught! + break; + + } else { + // Not a function call, so bow out. + return; + } + } + + // Now let's also prevent false positives when used with self and static which still work fine. + $classToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), null, true, null, true); + if ($classToken !== false) { + if ($tokens[$classToken]['code'] === \T_STATIC || $tokens[$classToken]['code'] === \T_SELF) { + return; + } elseif ($tokens[$classToken]['code'] === \T_STRING && $tokens[$classToken]['content'] === 'self') { + return; + } + } + } + + $phpcsFile->addError( + 'Indirect access to variables, properties and methods will be evaluated strictly in left-to-right order since PHP 7.0. Use curly braces to remove ambiguity.', + $stackPtr, + 'Found' + ); + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/RemovedPredefinedGlobalVariablesSniff.php b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/RemovedPredefinedGlobalVariablesSniff.php new file mode 100644 index 00000000..c814e7dc --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/RemovedPredefinedGlobalVariablesSniff.php @@ -0,0 +1,318 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + */ + +namespace PHPCompatibility\Sniffs\Variables; + +use PHPCompatibility\AbstractRemovedFeatureSniff; +use PHPCompatibility\PHPCSHelper; +use PHP_CodeSniffer_File as File; +use PHP_CodeSniffer_Tokens as Tokens; + +/** + * Detect the use of removed global variables. Suggests alternatives if available. + * + * PHP version 5.3+ + * + * @link https://wiki.php.net/rfc/deprecations_php_7_2#php_errormsg + * + * @since 5.5 Introduced `LongArrays` sniff. + * @since 7.0 Introduced `RemovedGlobalVariables` sniff. + * @since 7.0.7 The `LongArrays` sniff now throws a warning for deprecated and an error for removed. + * Previously the `LongArrays` sniff would always throw a warning. + * @since 7.1.0 The `RemovedGlobalVariables` sniff now extends the `AbstractNewFeatureSniff` + * instead of the base `Sniff` class. + * @since 7.1.3 Merged the `LongArrays` sniff into the `RemovedGlobalVariables` sniff. + * @since 9.0.0 Renamed from `RemovedGlobalVariablesSniff` to `RemovedPredefinedGlobalVariablesSniff`. + */ +class RemovedPredefinedGlobalVariablesSniff extends AbstractRemovedFeatureSniff +{ + + /** + * A list of removed global variables with their alternative, if any. + * + * The array lists : version number with false (deprecated) and true (removed). + * If's sufficient to list the first version where the variable was deprecated/removed. + * + * @since 5.5 + * @since 7.0 + * + * @var array(string => array(string => bool|string)) + */ + protected $removedGlobalVariables = array( + 'HTTP_POST_VARS' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_POST', + ), + 'HTTP_GET_VARS' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_GET', + ), + 'HTTP_ENV_VARS' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_ENV', + ), + 'HTTP_SERVER_VARS' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_SERVER', + ), + 'HTTP_COOKIE_VARS' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_COOKIE', + ), + 'HTTP_SESSION_VARS' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_SESSION', + ), + 'HTTP_POST_FILES' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_FILES', + ), + + 'HTTP_RAW_POST_DATA' => array( + '5.6' => false, + '7.0' => true, + 'alternative' => 'php://input', + ), + + 'php_errormsg' => array( + '7.2' => false, + 'alternative' => 'error_get_last()', + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * @since 7.0 + * + * @return array + */ + public function register() + { + return array(\T_VARIABLE); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * @since 7.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('5.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $varName = substr($tokens[$stackPtr]['content'], 1); + + if (isset($this->removedGlobalVariables[$varName]) === false) { + return; + } + + if ($this->isClassProperty($phpcsFile, $stackPtr) === true) { + // Ok, so this was a class property declaration, not our concern. + return; + } + + // Check for static usage of class properties shadowing the removed global variables. + if ($this->inClassScope($phpcsFile, $stackPtr, false) === true) { + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true, null, true); + if ($prevToken !== false && $tokens[$prevToken]['code'] === \T_DOUBLE_COLON) { + return; + } + } + + // Do some additional checks for the $php_errormsg variable. + if ($varName === 'php_errormsg' + && $this->isTargetPHPErrormsgVar($phpcsFile, $stackPtr, $tokens) === false + ) { + return; + } + + // Still here, so throw an error/warning. + $itemInfo = array( + 'name' => $varName, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->removedGlobalVariables[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return "Global variable '\$%s' is "; + } + + + /** + * Filter the error message before it's passed to PHPCS. + * + * @since 8.1.0 + * + * @param string $error The error message which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return string + */ + protected function filterErrorMsg($error, array $itemInfo, array $errorInfo) + { + if ($itemInfo['name'] === 'php_errormsg') { + $error = str_replace('Global', 'The', $error); + } + return $error; + } + + /** + * Run some additional checks for the `$php_errormsg` variable. + * + * @since 8.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param array $tokens Token array of the current file. + * + * @return bool + */ + private function isTargetPHPErrormsgVar(File $phpcsFile, $stackPtr, array $tokens) + { + $scopeStart = 0; + + /* + * If the variable is detected within the scope of a function/closure, limit the checking. + */ + $function = $phpcsFile->getCondition($stackPtr, \T_CLOSURE); + if ($function === false) { + $function = $phpcsFile->getCondition($stackPtr, \T_FUNCTION); + } + + // It could also be a function param, which is not in the function scope. + if ($function === false && isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nestedParentheses = $tokens[$stackPtr]['nested_parenthesis']; + $parenthesisCloser = end($nestedParentheses); + if (isset($tokens[$parenthesisCloser]['parenthesis_owner']) + && ($tokens[$tokens[$parenthesisCloser]['parenthesis_owner']]['code'] === \T_FUNCTION + || $tokens[$tokens[$parenthesisCloser]['parenthesis_owner']]['code'] === \T_CLOSURE) + ) { + $function = $tokens[$parenthesisCloser]['parenthesis_owner']; + } + } + + if ($function !== false) { + $scopeStart = $tokens[$function]['scope_opener']; + } + + /* + * Now, let's do some additional checks. + */ + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + // Is the variable being used as an array ? + if ($nextNonEmpty !== false && $tokens[$nextNonEmpty]['code'] === \T_OPEN_SQUARE_BRACKET) { + // The PHP native variable is a string, so this is probably not it + // (except for array access to string, but why would you in this case ?). + return false; + } + + // Is this a variable assignment ? + if ($nextNonEmpty !== false + && isset(Tokens::$assignmentTokens[$tokens[$nextNonEmpty]['code']]) === true + ) { + return false; + } + + // Is this a function param shadowing the PHP native one ? + if ($function !== false) { + $parameters = PHPCSHelper::getMethodParameters($phpcsFile, $function); + if (\is_array($parameters) === true && empty($parameters) === false) { + foreach ($parameters as $param) { + if ($param['name'] === '$php_errormsg') { + return false; + } + } + } + } + + $skipPast = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_INTERFACE' => true, + 'T_TRAIT' => true, + 'T_FUNCTION' => true, + 'T_CLOSURE' => true, + ); + + // Walk back and see if there is an assignment to the variable within the same scope. + for ($i = ($stackPtr - 1); $i >= $scopeStart; $i--) { + if ($tokens[$i]['code'] === \T_CLOSE_CURLY_BRACKET + && isset($tokens[$i]['scope_condition']) + && isset($skipPast[$tokens[$tokens[$i]['scope_condition']]['type']]) + ) { + // Skip past functions, classes etc. + $i = $tokens[$i]['scope_condition']; + continue; + } + + if ($tokens[$i]['code'] !== \T_VARIABLE || $tokens[$i]['content'] !== '$php_errormsg') { + continue; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + + if ($nextNonEmpty !== false + && isset(Tokens::$assignmentTokens[$tokens[$nextNonEmpty]['code']]) === true + ) { + return false; + } + } + + return true; + } +} diff --git a/vendor/phpcompatibility/php-compatibility/PHPCompatibility/ruleset.xml b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/ruleset.xml new file mode 100644 index 00000000..3eb0b673 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/PHPCompatibility/ruleset.xml @@ -0,0 +1,7 @@ +<?xml version="1.0"?> +<ruleset name="PHPCompatibility"> + <description>Coding Standard that checks for PHP version compatibility.</description> + + <autoload>./../PHPCSAliases.php</autoload> + +</ruleset> diff --git a/vendor/phpcompatibility/php-compatibility/README.md b/vendor/phpcompatibility/php-compatibility/README.md new file mode 100644 index 00000000..9b1fd51b --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/README.md @@ -0,0 +1,250 @@ +PHP Compatibility Coding Standard for PHP CodeSniffer +===================================================== +[![Latest Stable Version](https://poser.pugx.org/phpcompatibility/php-compatibility/v/stable.png)](https://packagist.org/packages/phpcompatibility/php-compatibility) +[![Latest Unstable Version](https://poser.pugx.org/phpcompatibility/php-compatibility/v/unstable.png)](https://packagist.org/packages/phpcompatibility/php-compatibility) +![Awesome](https://img.shields.io/badge/awesome%3F-yes!-brightgreen.svg) +[![License](https://poser.pugx.org/phpcompatibility/php-compatibility/license.png)](https://github.com/PHPCompatibility/PHPCompatibility/blob/master/LICENSE) +[![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=wimg&url=https://github.com/PHPCompatibility/PHPCompatibility&title=PHPCompatibility&language=&tags=github&category=software) + +[![Build Status](https://travis-ci.org/PHPCompatibility/PHPCompatibility.svg?branch=develop)](https://travis-ci.org/PHPCompatibility/PHPCompatibility) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/PHPCompatibility/PHPCompatibility/badges/quality-score.png?b=develop)](https://scrutinizer-ci.com/g/PHPCompatibility/PHPCompatibility/) +[![Coverage Status](https://coveralls.io/repos/github/PHPCompatibility/PHPCompatibility/badge.svg?branch=develop)](https://coveralls.io/github/PHPCompatibility/PHPCompatibility?branch=develop) + +[![Minimum PHP Version](https://img.shields.io/packagist/php-v/phpcompatibility/php-compatibility.svg?maxAge=3600)](https://packagist.org/packages/phpcompatibility/php-compatibility) +[![Tested on PHP 5.3 to nightly](https://img.shields.io/badge/tested%20on-PHP%205.3%20|%205.4%20|%205.5%20|%205.6%20|%207.0%20|%207.1%20|%207.2%20|%207.3%20|%207.4%20-brightgreen.svg?maxAge=2419200)](https://travis-ci.org/PHPCompatibility/PHPCompatibility) + + +This is a set of sniffs for [PHP CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) that checks for PHP cross-version compatibility. +It will allow you to analyse your code for compatibility with higher and lower versions of PHP. + +* [PHP Version Support](#php-version-support) +* [Requirements](#requirements) +* [Thank you](#thank-you) +* [Upgrading to PHPCompatibility 9.0.0](#warning-upgrading-to-phpcompatibility-900-warning) +* [Installation in a Composer project (method 1)](#installation-in-a-composer-project-method-1) +* [Installation via a git check-out to an arbitrary directory (method 2)](#installation-via-a-git-check-out-to-an-arbitrary-directory-method-2) +* [Sniffing your code for compatibility with specific PHP version(s)](#sniffing-your-code-for-compatibility-with-specific-php-versions) + + [Using a framework/CMS/polyfill specific ruleset](#using-a-frameworkcmspolyfill-specific-ruleset) +* [Using a custom ruleset](#using-a-custom-ruleset) + + [`testVersion` in the ruleset versus command-line](#testversion-in-the-ruleset-versus-command-line) + + [PHPCompatibility specific options](#phpcompatibility-specific-options) +* [Projects extending PHPCompatibility](#projects-extending-phpcompatibility) +* [Contributing](#contributing) +* [License](#license) + +PHP Version Support +------- + +The project aims to cover all PHP compatibility changes introduced since PHP 5.0 up to the latest PHP release. This is an ongoing process and coverage is not yet 100% (if, indeed, it ever could be). Progress is tracked on [our GitHub issue tracker](https://github.com/PHPCompatibility/PHPCompatibility/issues). + +Pull requests that check for compatibility issues in PHP 4 code - in particular between PHP 4 and PHP 5.0 - are very welcome as there are still situations where people need help upgrading legacy systems. However, coverage for changes introduced before PHP 5.1 will remain patchy as sniffs for this are not actively being developed at this time. + +Requirements +------- + +* PHP 5.3+ for use with PHP CodeSniffer 2.x. +* PHP 5.4+ for use with PHP CodeSniffer 3.x. + +PHP CodeSniffer: 2.3.0+ or 3.0.2+. + +The sniffs are designed to give the same results regardless of which PHP version you are using to run PHP CodeSniffer. You should get reasonably consistent results independently of the PHP version used in your test environment, though for the best results it is recommended to run the sniffs on PHP 5.4 or higher. + +PHP CodeSniffer 2.3.0 is required for 90% of the sniffs, PHP CodeSniffer 2.6.0 or later is required for full support, notices may be thrown on older versions. + +For running the sniffs on PHP 7.3, it is recommended to use PHP_CodeSniffer 3.3.1+, or, if needs be, PHP_CodeSniffer 2.9.2. +PHP_CodeSniffer < 2.9.2/3.3.1 is not fully compatible with PHP 7.3, which effectively means that PHPCompatibility can't be either. +While the sniffs will still work in _most_ cases, you can expect PHP warnings to be thrown. + +For running the sniffs on PHP 7.4, it is recommended to use PHP_CodeSniffer 3.5.0+. + +As of version 8.0.0, the PHPCompatibility standard can also be used with PHP CodeSniffer 3.x. + +As of version 9.0.0, support for PHP CodeSniffer 1.5.x and low 2.x versions < 2.3.0 has been dropped. + + +Thank you +--------- +Thanks to all [contributors](https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors) for their valuable contributions. + +Thanks to [WP Engine](https://wpengine.com) for their support on the PHP 7.0 sniffs. + + +:warning: Upgrading to PHPCompatibility 9.0.0 :warning: +-------- +This library has been reorganized. All sniffs have been placed in categories and a significant number of sniffs have been renamed. + +If you use the complete `PHPCompatibility` standard without `exclude` directives in a custom ruleset and do not (yet) use the new-style PHP_CodeSniffer annotation as introduced in [PHP_CodeSniffer 3.2.0](https://github.com/squizlabs/PHP_CodeSniffer/releases/tag/3.2.0), this will have no noticeable effect and everything should work as before. + +However, if you do use `exclude` directives for PHPCompatibility sniffs in a custom ruleset or if you use the [new-style PHP_CodeSniffer inline annotations](https://github.com/squizlabs/PHP_CodeSniffer/releases/3.2.0), you will need to update these when upgrading. This should be a one-time only change. +The changelog contains detailed information about all the sniff renames. + +Please read the changelog for version [9.0.0](https://github.com/PHPCompatibility/PHPCompatibility/releases/tag/9.0.0) carefully before upgrading. + + +Installation in a Composer project (method 1) +------------------------------------------- + +* Add the following lines to the `require-dev` section of your `composer.json` file. + ```json + "require-dev": { + "phpcompatibility/php-compatibility": "*" + }, + "prefer-stable" : true + ``` +* Next, PHP CodeSniffer has to be informed of the location of the standard. + - If PHPCompatibility is the **_only_** external PHP CodeSniffer standard you use, you can add the following to your `composer.json` file to automatically run the necessary command: + ```json + "scripts": { + "post-install-cmd": "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility", + "post-update-cmd" : "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility" + } + ``` + - Alternatively - and **_strongly recommended_** if you use more than one external PHP CodeSniffer standard - you can use any of the following Composer plugins to handle this for you. + + Just add the Composer plugin you prefer to the `require-dev` section of your `composer.json` file. + + * [DealerDirect/phpcodesniffer-composer-installer](https://github.com/DealerDirect/phpcodesniffer-composer-installer):"^0.5.0" + * [higidi/composer-phpcodesniffer-standards-plugin](https://github.com/higidi/composer-phpcodesniffer-standards-plugin) + * [SimplyAdmire/ComposerPlugins](https://github.com/SimplyAdmire/ComposerPlugins). This plugin *might* still work, but appears to be abandoned. + - As a last alternative in case you use a custom ruleset, _and only if you use PHP CodeSniffer version 2.6.0 or higher_, you can tell PHP CodeSniffer the path to the PHPCompatibility standard by adding the following snippet to your custom ruleset: + ```xml + <config name="installed_paths" value="vendor/phpcompatibility/php-compatibility" /> + ``` +* Run `composer update --lock` to install both PHP CodeSniffer, the PHPCompatibility coding standard and - optionally - the Composer plugin. +* Verify that the PHPCompatibility standard is registered correctly by running `./vendor/bin/phpcs -i` on the command line. PHPCompatibility should be listed as one of the available standards. +* Now you can use the following command to inspect your code: + ```bash + ./vendor/bin/phpcs -p . --standard=PHPCompatibility + ``` + +Installation via a git check-out to an arbitrary directory (method 2) +----------------------- + +* Install [PHP CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) via [your preferred method](https://github.com/squizlabs/PHP_CodeSniffer#installation). + + PHP CodeSniffer offers a variety of installation methods to suit your work-flow: Composer, [PEAR](http://pear.php.net/PHP_CodeSniffer), a Phar file, zipped/tarred release archives or checking the repository out using Git. + + **Pro-tip:** Register the path to PHPCS in your system `$PATH` environment variable to make the `phpcs` command available from anywhere in your file system. +* Download the [latest PHPCompatibility release](https://github.com/PHPCompatibility/PHPCompatibility/releases) and unzip/untar it into an arbitrary directory. + + You can also choose to clone the repository using git to easily update your install regularly. +* Add the path to the directory in which you placed your copy of the PHPCompatibility repo to the PHP CodeSniffer configuration using the below command from the command line: + ```bash + phpcs --config-set installed_paths /path/to/PHPCompatibility + ``` + I.e. if you placed the `PHPCompatibility` repository in the `/my/custom/standards/PHPCompatibility` directory, you will need to add that directory to the PHP CodeSniffer [`installed_paths` configuration variable](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options#setting-the-installed-standard-paths). + + **Warning**: :warning: The `installed_paths` command overwrites any previously set `installed_paths`. If you have previously set `installed_paths` for other external standards, run `phpcs --config-show` first and then run the `installed_paths` command with all the paths you need separated by comma's, i.e.: + ```bash + phpcs --config-set installed_paths /path/1,/path/2,/path/3 + ``` + + **Pro-tip:** Alternatively, in case you use a custom ruleset _and only if you use PHP CodeSniffer version 2.6.0 or higher_, you can tell PHP CodeSniffer the path to the PHPCompatibility standard(s) by adding the following snippet to your custom ruleset: + ```xml + <config name="installed_paths" value="/path/to/PHPCompatibility" /> + ``` +* Verify that the PHPCompatibility standard is registered correctly by running `phpcs -i` on the command line. PHPCompatibility should be listed as one of the available standards. +* Now you can use the following command to inspect your code: + ```bash + phpcs -p . --standard=PHPCompatibility + ``` + +Sniffing your code for compatibility with specific PHP version(s) +------------------------------ +* Run the coding standard from the command-line with `phpcs -p . --standard=PHPCompatibility`. +* By default, you will only receive notifications about deprecated and/or removed PHP features. +* To get the most out of the PHPCompatibility standard, you should specify a `testVersion` to check against. That will enable the checks for both deprecated/removed PHP features as well as the detection of code using new PHP features. + - You can run the checks for just one specific PHP version by adding `--runtime-set testVersion 5.5` to your command line command. + - You can also specify a range of PHP versions that your code needs to support. In this situation, compatibility issues that affect any of the PHP versions in that range will be reported: `--runtime-set testVersion 5.3-5.5`. + - As of PHPCompatibility 7.1.3, you can omit one part of the range if you want to support everything above or below a particular version, i.e. use `--runtime-set testVersion 7.0-` to run all the checks for PHP 7.0 and above. +* By default the report will be sent to the console, if you want to save the report to a file, add the following to the command line command: `--report-full=path/to/report-file`. + For more information and other reporting options, check the [PHP CodeSniffer wiki](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Reporting). + + +### Using a framework/CMS/polyfill specific ruleset + +As of mid 2018, a limited set of framework/CMS specific rulesets is available. These rulesets are hosted in their own repositories. +* `PHPCompatibilityJoomla` [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityJoomla) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-joomla) +* `PHPCompatibilityWP` [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityWP) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-wp) + +Since the autumn of 2018, there are also a number of PHP polyfill specific rulesets available: +* `PHPCompatibilityPasswordCompat` [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityPasswordCompat) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-passwordcompat): accounts for @ircmaxell's [`password_compat`](https://github.com/ircmaxell/password_compat) polyfill library. +* `PHPCompatibilityParagonie` [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityParagonie) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-paragonie): contains two rulesets which account for the Paragonie [`random_compat`](https://github.com/paragonie/random_compat) and [`sodium_compat`](https://github.com/paragonie/sodium_compat) polyfill libraries respectively. +* `PHPCompatibilitySymfony` [GitHub](https://github.com/PHPCompatibility/PHPCompatibilitySymfony) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-symfony): contains a number of rulesets which account for various PHP polyfill libraries offered by the Symfony project. For more details about the available rulesets, please check out the [README of the PHPCompatibilitySymfony](https://github.com/PHPCompatibility/PHPCompatibilitySymfony/blob/master/README.md) repository. + +If you want to make sure you have all PHPCompatibility rulesets available at any time, you can use the `PHPCompatibilityAll` package [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityAll) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-all). + +**IMPORTANT:** Framework/CMS/Polyfill specific rulesets do not set the minimum PHP version for your project, so you will still need to pass a `testVersion` to get the most accurate results. + + +Using a custom ruleset +------------------------------ +Like with any PHP CodeSniffer standard, you can add PHPCompatibility to a custom PHP CodeSniffer ruleset. + +```xml +<?xml version="1.0"?> +<ruleset name="Custom ruleset"> + <description>My rules for PHP CodeSniffer</description> + + <!-- Run against the PHPCompatibility ruleset --> + <rule ref="PHPCompatibility"/> + + <!-- Run against a second ruleset --> + <rule ref="PSR2"/> + +</ruleset> +``` + +You can also set the `testVersion` from within the ruleset: +```xml + <!-- Check for cross-version support for PHP 5.6 and higher. --> + <config name="testVersion" value="5.6-"/> +``` + +Other advanced options, such as changing the message type or severity of select sniffs, as described in the [PHPCS Annotated ruleset](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml) wiki page are, of course, also supported. + +### `testVersion` in the ruleset versus command-line + +In PHPCS 3.2.0 and lower, once you set the `testVersion` in the ruleset, you could not overrule it from the command-line anymore. +Starting with PHPCS 3.3.0, a `testVersion` set via the command-line will overrule the `testVersion` in the ruleset. + +This allows for more flexibility when, for instance, your project needs to comply with PHP `5.5-`, but you have a bootstrap file which needs to be compatible with PHP `5.2-`. + + +### PHPCompatibility specific options + +At this moment, there is one sniff which has a property which can be set via the ruleset. More custom properties may become available in the future. + +The `PHPCompatibility.Extensions.RemovedExtensions` sniff checks for removed extensions based on the function prefix used for these extensions. +This might clash with userland functions using the same function prefix. + +To whitelist userland functions, you can pass a comma-delimited list of function names to the sniff. +```xml + <!-- Whitelist the mysql_to_rfc3339() and mysql_another_function() functions. --> + <rule ref="PHPCompatibility.Extensions.RemovedExtensions"> + <properties> + <property name="functionWhitelist" type="array" value="mysql_to_rfc3339,mysql_another_function"/> + </properties> + </rule> +``` + +This property was added in PHPCompatibility version 7.0.1. +As of PHPCompatibility version 8.0.0, this custom property is only supported in combination with PHP CodeSniffer > 2.6.0 due to an upstream bug (which was fixed in PHPCS 2.6.0). + +Projects extending PHPCompatibility +-------------------------------------- +There are hundreds of public projects using PHPCompatibility or extending on top of it. A short list of some that you might know or have a look at : +* [adamculp/php-code-quality](https://github.com/adamculp/php-code-quality) - a Docker image doing a lot of code quality checks +* [VFAC/PHP7Compatibility](https://vfac.fr/projects/php7compatibility) - a Docker container to check PHP7 Compatibility +* [grumphp-php-compatibility](https://github.com/wunderio/grumphp-php-compatibility) - A plugin for [GrumPHP](https://github.com/phpro/grumphp) +* PHPCompatibility Checker WordPress plugin : [Wordpress site](https://wordpress.org/plugins/php-compatibility-checker/) and [Github](https://github.com/wpengine/phpcompat/) +* [WordPress Tide project](https://wptide.org/) +* [PHPStorm has built-in support for PHPCompatibility](https://www.jetbrains.com/help/phpstorm/using-php-code-sniffer.html#788c81b6) + +Contributing +------- +Contributions are very welcome. Please read the [CONTRIBUTING](.github/CONTRIBUTING.md) documentation to get started. + +License +------- +This code is released under the GNU Lesser General Public License (LGPL). For more information, visit http://www.gnu.org/copyleft/lesser.html diff --git a/vendor/phpcompatibility/php-compatibility/composer.json b/vendor/phpcompatibility/php-compatibility/composer.json new file mode 100644 index 00000000..38fbe637 --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/composer.json @@ -0,0 +1,44 @@ +{ + "name" : "phpcompatibility/php-compatibility", + "description" : "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", + "type" : "phpcodesniffer-standard", + "keywords" : [ "compatibility", "phpcs", "standards" ], + "homepage" : "http://techblog.wimgodden.be/tag/codesniffer/", + "license" : "LGPL-3.0-or-later", + "authors" : [ { + "name" : "Wim Godden", + "role" : "lead", + "homepage" : "https://github.com/wimg" + }, + { + "name" : "Juliette Reinders Folmer", + "role" : "lead", + "homepage" : "https://github.com/jrfnl" + }, + { + "name" : "Contributors", + "homepage" : "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" + } ], + "support" : { + "issues" : "https://github.com/PHPCompatibility/PHPCompatibility/issues", + "source" : "https://github.com/PHPCompatibility/PHPCompatibility" + }, + "require" : { + "php" : ">=5.3", + "squizlabs/php_codesniffer" : "^2.3 || ^3.0.2" + }, + "require-dev" : { + "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" + }, + "conflict": { + "squizlabs/php_codesniffer": "2.6.2" + }, + "suggest" : { + "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "scripts" : { + "post-install-cmd": "\"vendor/bin/phpcs\" --config-set installed_paths ../../..", + "post-update-cmd" : "\"vendor/bin/phpcs\" --config-set installed_paths ../../.." + } +} diff --git a/vendor/phpcompatibility/php-compatibility/phpunit-bootstrap.php b/vendor/phpcompatibility/php-compatibility/phpunit-bootstrap.php new file mode 100644 index 00000000..f66ec0cf --- /dev/null +++ b/vendor/phpcompatibility/php-compatibility/phpunit-bootstrap.php @@ -0,0 +1,86 @@ +<?php +/** + * PHPCompatibility, an external standard for PHP_CodeSniffer. + * + * Bootstrap file for tests. + * + * @package PHPCompatibility + * @copyright 2012-2019 PHPCompatibility Contributors + * @license https://opensource.org/licenses/LGPL-3.0 LGPL3 + * @link https://github.com/PHPCompatibility/PHPCompatibility + * + * @since 5.5 + */ + +if (defined('PHP_CODESNIFFER_IN_TESTS') === false) { + define('PHP_CODESNIFFER_IN_TESTS', true); +} + +// The below two defines are needed for PHPCS 3.x. +if (defined('PHP_CODESNIFFER_CBF') === false) { + define('PHP_CODESNIFFER_CBF', false); +} + +if (defined('PHP_CODESNIFFER_VERBOSITY') === false) { + define('PHP_CODESNIFFER_VERBOSITY', 0); +} + +$ds = DIRECTORY_SEPARATOR; + +// Get the PHPCS dir from an environment variable. +$phpcsDir = getenv('PHPCS_DIR'); + +// This may be a Composer install. +if ($phpcsDir === false && is_dir(__DIR__ . $ds . 'vendor' . $ds . 'squizlabs' . $ds . 'php_codesniffer')) { + $vendorDir = __DIR__ . $ds . 'vendor'; + $phpcsDir = $vendorDir . $ds . 'squizlabs' . $ds . 'php_codesniffer'; +} elseif ($phpcsDir !== false) { + $phpcsDir = realpath($phpcsDir); +} + +// Try and load the PHPCS autoloader. +if ($phpcsDir !== false && file_exists($phpcsDir . $ds . 'autoload.php')) { + // PHPCS 3.x. + require_once $phpcsDir . $ds . 'autoload.php'; + + /* + * Alias the PHPCS 3.x classes to their PHPCS 2.x equivalent if necessary. + * Also provide a custom autoloader for our abstract base classes as the PHPCS native autoloader + * has trouble with them in combination with the PHPCompatibility custom unit test suite. + */ + require_once __DIR__ . $ds . 'PHPCSAliases.php'; + +} elseif ($phpcsDir !== false && file_exists($phpcsDir . $ds . 'CodeSniffer.php')) { + // PHPCS 2.x. + require_once $phpcsDir . $ds . 'CodeSniffer.php'; + + if (isset($vendorDir) && file_exists($vendorDir . $ds . 'autoload.php')) { + require_once $vendorDir . $ds . 'autoload.php'; + } + +} else { + echo 'Uh oh... can\'t find PHPCS. + +If you use Composer, please run `composer install --prefer-source`. +Otherwise, make sure you set a `PHPCS_DIR` environment variable in your phpunit.xml file +pointing to the PHPCS directory. + +Please read the contributors guidelines for more information: +https://is.gd/PHPCompatibilityContrib +'; + + die(1); +} + + +// PHPUnit cross version compatibility. +if (class_exists('PHPUnit\Runner\Version') + && version_compare(PHPUnit\Runner\Version::id(), '6.0', '>=') + && class_exists('PHPUnit_Framework_TestCase') === false +) { + class_alias('PHPUnit\Framework\TestCase', 'PHPUnit_Framework_TestCase'); +} + +require_once __DIR__ . $ds . 'PHPCompatibility' . $ds . 'Tests' . $ds . 'BaseSniffTest.php'; +require_once __DIR__ . $ds . 'PHPCompatibility' . $ds . 'Util' . $ds . 'Tests' . $ds . 'CoreMethodTestFrame.php'; +unset($ds, $phpcsDir, $vendorDir); diff --git a/vendor/phpcompatibility/phpcompatibility-paragonie/LICENSE b/vendor/phpcompatibility/phpcompatibility-paragonie/LICENSE new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/vendor/phpcompatibility/phpcompatibility-paragonie/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/vendor/phpcompatibility/phpcompatibility-paragonie/PHPCompatibilityParagonieRandomCompat/ruleset.xml b/vendor/phpcompatibility/phpcompatibility-paragonie/PHPCompatibilityParagonieRandomCompat/ruleset.xml new file mode 100644 index 00000000..e67a12e0 --- /dev/null +++ b/vendor/phpcompatibility/phpcompatibility-paragonie/PHPCompatibilityParagonieRandomCompat/ruleset.xml @@ -0,0 +1,40 @@ +<?xml version="1.0"?> +<ruleset name="PHPCompatibilityParagonieRandomCompat"> + <description>PHPCompatibility ruleset for PHP_CodeSniffer which accounts for polyfills provided by the Paragonie random_compat library.</description> + + <rule ref="PHPCompatibility"> + <!-- https://github.com/paragonie/random_compat/blob/master/lib/random.php --> + <exclude name="PHPCompatibility.Constants.NewConstants.php_version_idFound"/> + + <!-- https://github.com/paragonie/random_compat/blob/master/lib/random_bytes_*.php --> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.random_bytesFound"/> + + <!-- https://github.com/paragonie/random_compat/blob/master/lib/random_int.php --> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.random_intFound"/> + + <!-- https://github.com/paragonie/random_compat/blob/master/lib/error_polyfill.php --> + <exclude name="PHPCompatibility.Classes.NewClasses.errorFound"/> + <exclude name="PHPCompatibility.Classes.NewClasses.typeerrorFound"/> + </rule> + + <!-- Prevent false positives being thrown when run over the code of random_compat itself. --> + <rule ref="PHPCompatibility.IniDirectives.RemovedIniDirectives.mbstring_func_overloadDeprecated"> + <exclude-pattern>/random_compat/lib/byte_safe_strings\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.FunctionUse.NewFunctions.stream_set_chunk_sizeFound"> + <exclude-pattern>/random_compat/lib/random_bytes_dev_urandom\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.Constants.RemovedConstants.mcrypt_dev_urandomDeprecatedRemoved"> + <exclude-pattern>/random_compat/lib/random_bytes_mcrypt\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.Extensions.RemovedExtensions.mcryptDeprecatedRemoved"> + <exclude-pattern>/random_compat/lib/random_bytes_mcrypt\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.FunctionUse.RemovedFunctions.mcrypt_create_ivDeprecatedRemoved"> + <exclude-pattern>/random_compat/lib/random_bytes_mcrypt\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.LanguageConstructs.NewLanguageConstructs.t_ns_separatorFound"> + <exclude-pattern>/random_compat/lib/random_bytes_libsodium\.php$</exclude-pattern> + </rule> + +</ruleset> diff --git a/vendor/phpcompatibility/phpcompatibility-paragonie/PHPCompatibilityParagonieSodiumCompat/ruleset.xml b/vendor/phpcompatibility/phpcompatibility-paragonie/PHPCompatibilityParagonieSodiumCompat/ruleset.xml new file mode 100644 index 00000000..e08fea53 --- /dev/null +++ b/vendor/phpcompatibility/phpcompatibility-paragonie/PHPCompatibilityParagonieSodiumCompat/ruleset.xml @@ -0,0 +1,244 @@ +<?xml version="1.0"?> +<ruleset name="PHPCompatibilityParagonieSodiumCompat"> + <description>PHPCompatibility ruleset for PHP_CodeSniffer which accounts for polyfills provided by the Paragonie sodium_compat library.</description> + + <!-- + Note: this ruleset does **not** contain excludes for the `sodium_pwhash()` and + the sodium_memzero() functions as, while those functions do exist in the polyfill, + they do not work and are explicitly excluded features. + See: https://github.com/paragonie/sodium_compat#features-excluded-from-this-polyfill + + With that in mind, these functions should not be used in code which intends to be + PHP cross-version compatible. + --> + + <!-- https://github.com/paragonie/sodium_compat/blob/master/composer.json --> + <rule ref="PHPCompatibilityParagonieRandomCompat"/> + + <rule ref="PHPCompatibility"> + <!-- https://github.com/paragonie/sodium_compat/blob/master/src/SodiumException.php --> + <exclude name="PHPCompatibility.Classes.NewClasses.sodiumexceptionFound"/> + + <!-- https://github.com/paragonie/sodium_compat/blob/master/lib/php72compat.php --> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_base64_variant_originalFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_base64_variant_original_no_paddingFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_base64_variant_urlsafeFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_base64_variant_urlsafe_no_paddingFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_aes256gcm_keybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_aes256gcm_nsecbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_aes256gcm_npubbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_aes256gcm_abytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_chacha20poly1305_keybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_chacha20poly1305_nsecbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_chacha20poly1305_npubbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_chacha20poly1305_abytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_chacha20poly1305_ietf_keybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_chacha20poly1305_ietf_nsecbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_chacha20poly1305_ietf_npubbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_chacha20poly1305_ietf_abytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_xchacha20poly1305_ietf_keybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_xchacha20poly1305_ietf_nsecbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_xchacha20poly1305_ietf_npubbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_aead_xchacha20poly1305_ietf_abytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_auth_bytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_auth_keybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_box_sealbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_box_secretkeybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_box_publickeybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_box_keypairbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_box_macbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_box_noncebytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_box_seedbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_kdf_bytes_minFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_kdf_bytes_maxFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_kdf_contextbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_kdf_keybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_kx_bytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_kx_keypairbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_kx_publickeybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_kx_secretkeybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_kx_seedbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_kx_sessionkeybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_generichash_bytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_generichash_bytes_minFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_generichash_bytes_maxFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_generichash_keybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_generichash_keybytes_minFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_generichash_keybytes_maxFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_saltbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_strprefixFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_alg_argon2i13Found"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_alg_argon2id13Found"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_memlimit_interactiveFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_opslimit_interactiveFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_memlimit_moderateFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_opslimit_moderateFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_memlimit_sensitiveFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_opslimit_sensitiveFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_scryptsalsa208sha256_saltbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_scryptsalsa208sha256_strprefixFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_scryptsalsa208sha256_opslimit_interactiveFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_scryptsalsa208sha256_memlimit_interactiveFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_scryptsalsa208sha256_opslimit_sensitiveFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_pwhash_scryptsalsa208sha256_memlimit_sensitiveFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_scalarmult_bytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_scalarmult_scalarbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_secretstream_xchacha20poly1305_abytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_secretstream_xchacha20poly1305_headerbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_secretstream_xchacha20poly1305_keybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_secretstream_xchacha20poly1305_messagebytes_maxFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_secretstream_xchacha20poly1305_tag_pushFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_secretstream_xchacha20poly1305_tag_rekeyFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_secretstream_xchacha20poly1305_tag_finalFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_shorthash_bytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_shorthash_keybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_secretbox_keybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_secretbox_macbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_secretbox_noncebytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_sign_bytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_sign_seedbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_sign_publickeybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_sign_secretkeybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_sign_keypairbytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_stream_keybytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_crypto_stream_noncebytesFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_library_versionFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_library_major_versionFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.sodium_library_minor_versionFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_addFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_base642binFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_bin2base64Found"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_bin2hexFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_compareFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_aead_aes256gcm_decryptFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_aead_aes256gcm_encryptFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_aead_aes256gcm_is_availableFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_aead_chacha20poly1305_decryptFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_aead_chacha20poly1305_encryptFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_aead_chacha20poly1305_keygenFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_aead_chacha20poly1305_ietf_decryptFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_aead_chacha20poly1305_ietf_encryptFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_aead_chacha20poly1305_ietf_keygenFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_aead_xchacha20poly1305_ietf_decryptFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_aead_xchacha20poly1305_ietf_encryptFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_aead_xchacha20poly1305_ietf_keygenFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_authFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_auth_keygenFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_auth_verifyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_boxFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_box_keypairFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_box_keypair_from_secretkey_and_publickeyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_box_openFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_box_publickeyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_box_publickey_from_secretkeyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_box_sealFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_box_seal_openFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_box_secretkeyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_box_seed_keypairFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_generichashFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_generichash_finalFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_generichash_initFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_generichash_keygenFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_generichash_updateFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_kdf_derive_from_keyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_kdf_keygenFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_kxFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_kx_client_session_keysFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_kx_keypairFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_kx_publickeyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_kx_secretkeyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_kx_seed_keypairFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_kx_server_session_keysFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_pwhash_strFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_pwhash_str_needs_rehashFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_pwhash_str_verifyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_pwhash_scryptsalsa208sha256Found"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_pwhash_scryptsalsa208sha256_strFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_pwhash_scryptsalsa208sha256_str_verifyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_scalarmultFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_scalarmult_baseFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_secretboxFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_secretbox_keygenFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_secretbox_openFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_secretstream_xchacha20poly1305_keygenFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_secretstream_xchacha20poly1305_init_pullFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_secretstream_xchacha20poly1305_init_pushFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_secretstream_xchacha20poly1305_pullFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_secretstream_xchacha20poly1305_pushFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_secretstream_xchacha20poly1305_rekeyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_shorthashFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_shorthash_keygenFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_signFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_sign_detachedFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_sign_keypairFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_sign_keypair_from_secretkey_and_publickeyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_sign_openFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_sign_publickeyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_sign_publickey_from_secretkeyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_sign_secretkeyFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_sign_seed_keypairFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_sign_verify_detachedFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_sign_ed25519_pk_to_curve25519Found"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_sign_ed25519_sk_to_curve25519Found"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_streamFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_stream_keygenFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_stream_xorFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_hex2binFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_incrementFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_library_versionFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_library_version_majorFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_library_version_minorFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_version_stringFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_memcmpFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_padFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_randombytes_bufFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_randombytes_uniformFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_randombytes_random16Found"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.sodium_unpadFound"/> + </rule> + + <!-- Prevent false positives being thrown when run over the code of sodium_compat itself. --> + <rule ref="PHPCompatibility.FunctionUse.NewFunctionParameters.assert_descriptionFound"> + <exclude-pattern>/sodium_compat/autoload\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.FunctionNameRestrictions.NewMagicMethods.__debuginfoFound"> + <exclude-pattern>/sodium_compat/src/Core(32)?/Curve25519/Fe\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.FunctionUse.NewFunctions.hash_equalsFound"> + <exclude-pattern>/sodium_compat/src/Core/Util\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.ParameterValues.NewPackFormat.NewFormatFound"> + <exclude-pattern>/sodium_compat/src/Core/Util\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.FunctionUse.NewFunctionParameters.openssl_decrypt_ivFound"> + <exclude-pattern>/sodium_compat/src/Compat\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.FunctionUse.NewFunctionParameters.openssl_decrypt_tagFound"> + <exclude-pattern>/sodium_compat/src/Compat\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.FunctionUse.NewFunctionParameters.openssl_decrypt_aadFound"> + <exclude-pattern>/sodium_compat/src/Compat\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.FunctionUse.NewFunctionParameters.openssl_encrypt_ivFound"> + <exclude-pattern>/sodium_compat/src/Compat\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.FunctionUse.NewFunctionParameters.openssl_encrypt_tagFound"> + <exclude-pattern>/sodium_compat/src/Compat\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.FunctionUse.NewFunctionParameters.openssl_encrypt_aadFound"> + <exclude-pattern>/sodium_compat/src/Compat\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.Constants.NewConstants.openssl_raw_dataFound"> + <exclude-pattern>/sodium_compat/src/Compat\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_pwhashFound"> + <exclude-pattern>/sodium_compat/src/Compat\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.FunctionUse.NewFunctions.sodium_memzeroFound"> + <exclude-pattern>/sodium_compat/src/Compat\.php$</exclude-pattern> + </rule> + <rule ref="PHPCompatibility.IniDirectives.RemovedIniDirectives.mbstring_func_overloadDeprecated"> + <exclude-pattern>/sodium_compat/src/Core/Util\.php$</exclude-pattern> + </rule> + +</ruleset> diff --git a/vendor/phpcompatibility/phpcompatibility-paragonie/README.md b/vendor/phpcompatibility/phpcompatibility-paragonie/README.md new file mode 100644 index 00000000..ed3e4d75 --- /dev/null +++ b/vendor/phpcompatibility/phpcompatibility-paragonie/README.md @@ -0,0 +1,143 @@ +[![Latest Stable Version](https://poser.pugx.org/phpcompatibility/phpcompatibility-paragonie/v/stable.png)](https://packagist.org/packages/phpcompatibility/phpcompatibility-paragonie) +[![Latest Unstable Version](https://poser.pugx.org/phpcompatibility/phpcompatibility-paragonie/v/unstable.png)](https://packagist.org/packages/phpcompatibility/phpcompatibility-paragonie) +[![License](https://poser.pugx.org/phpcompatibility/phpcompatibility-paragonie/license.png)](https://github.com/PHPCompatibility/PHPCompatibilityParagonie/blob/master/LICENSE) +[![Build Status](https://github.com/PHPCompatibility/PHPCompatibilityParagonie/workflows/CI/badge.svg?branch=master)](https://github.com/PHPCompatibility/PHPCompatibilityParagonie/actions) + +# PHPCompatibilityParagonie + +Using PHPCompatibilityParagonie, you can analyse the codebase of a project using either of the Paragonie polyfills, for PHP cross-version compatibility. + + +## What's in this repo ? + +Two rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries. + +These rulesets prevent false positives from the [PHPCompatibility standard](https://github.com/PHPCompatibility/PHPCompatibility) by excluding back-fills and poly-fills which are provided by those libraries. + +Paragonie Polyfill Library | Corresponding PHPCompatibility Ruleset | Includes +--- | --- | --- +[`random_compat`](https://github.com/paragonie/random_compat) | `PHPCompatibilityParagonieRandomCompat` +[`sodium_compat`](https://github.com/paragonie/sodium_compat) | `PHPCompatibilityParagonieSodiumCompat` | `PHPCompatibilityParagonieRandomCompat` + +> Note: +> As the `sodium_compat` library has `random_compat` [as a dependency](https://github.com/paragonie/sodium_compat/blob/master/composer.json), the `PHPCompatibilityParagonieSodiumCompat` ruleset includes the `PHPCompatibilityParagonieRandomCompat` ruleset. +> +> In practice, this means that if your project uses both libraries, you just need to use the `PHPCompatibilityParagonieSodiumCompat` ruleset to prevent false positives from both. + + +## Requirements + +* [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer). + * PHP 5.3+ for use with [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) 2.3.0+. + * PHP 5.4+ for use with [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) 3.0.2+. + + Use the latest stable release of PHP_CodeSniffer for the best results. + The minimum _recommended_ version of PHP_CodeSniffer is version 2.6.0. +* [PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility) 9.0.0+. + + +## Installation instructions + +The only supported installation method is via [Composer](https://getcomposer.org/). + +If you don't have a Composer plugin installed to manage the `installed_paths` setting for PHP_CodeSniffer, run the following from the command-line: +```bash +composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true +composer require --dev dealerdirect/phpcodesniffer-composer-installer:"^0.7" phpcompatibility/phpcompatibility-paragonie:"*" +``` + +If you already have a Composer PHP_CodeSniffer plugin installed, run: +```bash +composer require --dev phpcompatibility/phpcompatibility-paragonie:"*" +``` + +Next, run: +```bash +vendor/bin/phpcs -i +``` +If all went well, you will now see that the `PHPCompatibility`, `PHPCompatibilityParagonieRandomCompat` and `PHPCompatibilityParagonieSodiumCompat` standards are installed for PHP_CodeSniffer. + + +## How to use + +Now you can use the following commands to inspect the code in your project for PHP cross-version compatibility: +```bash +./vendor/bin/phpcs -p . --standard=PHPCompatibilityParagonieRandomCompat + +./vendor/bin/phpcs -p . --standard=PHPCompatibilityParagonieSodiumCompat +``` + +By default, you will only receive notifications about deprecated and/or removed PHP features. + +To get the most out of the PHPCompatibilityParagonie rulesets, you should specify a `testVersion` to check against. That will enable the checks for both deprecated/removed PHP features as well as the detection of code using new PHP features. + +For example: +```bash +# For a project which should be compatible with PHP 5.3 up to and including PHP 7.0: +./vendor/bin/phpcs -p . --standard=PHPCompatibilityParagonieRandomCompat --runtime-set testVersion 5.3-7.0 + +# For a project which should be compatible with PHP 5.4 and higher: +./vendor/bin/phpcs -p . --standard=PHPCompatibilityParagonieSodiumCompat --runtime-set testVersion 5.4- +``` + +For more detailed information about setting the `testVersion`, see the README of the generic [PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility#sniffing-your-code-for-compatibility-with-specific-php-versions) standard. + + +### Testing PHP files only + +By default PHP_CodeSniffer will analyse PHP, JavaScript and CSS files. As the PHPCompatibility sniffs only target PHP code, you can make the run slightly faster by telling PHP_CodeSniffer to only check PHP files, like so: +```bash +./vendor/bin/phpcs -p . --standard=PHPCompatibilityParagonieRandomCompat --extensions=php --runtime-set testVersion 5.3- +``` + +## License + +All code within the PHPCompatibility organisation is released under the GNU Lesser General Public License (LGPL). For more information, visit https://www.gnu.org/copyleft/lesser.html + + +## Changelog + +### 1.3.2 - 2022-10-25 + +- README: Updated the installation instructions for [compatibility with Composer >= 2.2][composer22announce]. +- Composer: The package will now identify itself as a static analysis tool. Thanks [@GaryJones]! +- Other housekeeping and minor documentation updates. + +[composer22announce]: https://blog.packagist.com/composer-2-2/#more-secure-plugin-execution + +### 1.3.1 - 2021-02-15 + +- The recommended version of the [Composer PHPCS plugin] is now `^0.7.0`, which offers compatibility with Composer 2.0. +- The rulesets are now also tested against PHP 7.4 and 8.0. + Note: full PHP 7.4 support is only available in combination with PHP_CodeSniffer >= 3.5.6. + Note: runtime PHP 8.0 support is only available in combination with PHP_CodeSniffer >= 3.5.7, full support is expected in PHP_CodeSniffer 3.6.0. + +### 1.3.0 - 2019-11-04 + +* Ruleset update for full compatibility with version [`1.12.0` of `sodium_compat`](https://github.com/paragonie/sodium_compat/releases/tag/v1.12.0). + +### 1.2.0 - 2019-10-16 + +* Ruleset update for full compatibility with version [`1.11.0` of `sodium_compat`](https://github.com/paragonie/sodium_compat/releases/tag/v1.11.0). + +### 1.1.0 - 2019-08-29 + +* The `PHPCompatibilityParagonieSodiumCompat` ruleset has been updated to account for the latest changes in the `sodium_compat` polyfill. +* Prevent false positives when the ruleset is run over the code of the `sodium_compat` polyfill itself. +* Composer: The recommended version of the [Composer PHPCS plugin] has been upped to `^0.5.0`. +* CI: Improved integration test for the `SodiumCompat` ruleset. +* CI: Added early warning system for false positives due to changes in the polyfill libraries themselves. + +### 1.0.1 - 2018-12-16 + +* Prevent false positives when the ruleset is run over the code of the `random_compat` polyfill itself. +* The rulesets are now also tested against PHP 7.3. + Note: full PHP 7.3 support is only available in combination with PHP_CodeSniffer 2.9.2 or 3.3.1+ due to an incompatibility within PHP_CodeSniffer itself. + +### 1.0.0 - 2018-10-07 + +Initial release of PHPCompatibilityParagonie containing rulesets covering the `random_compat` and `sodium_compat` polyfill libraries. + +[Composer PHPCS plugin]: https://github.com/PHPCSStandards/composer-installer/ + +[@GaryJones]: https://github.com/GaryJones diff --git a/vendor/phpcompatibility/phpcompatibility-paragonie/composer.json b/vendor/phpcompatibility/phpcompatibility-paragonie/composer.json new file mode 100644 index 00000000..27a96521 --- /dev/null +++ b/vendor/phpcompatibility/phpcompatibility-paragonie/composer.json @@ -0,0 +1,38 @@ +{ + "name" : "phpcompatibility/phpcompatibility-paragonie", + "description" : "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.", + "type" : "phpcodesniffer-standard", + "keywords" : [ "compatibility", "phpcs", "standards", "static analysis", "paragonie", "polyfill" ], + "homepage" : "http://phpcompatibility.com/", + "license" : "LGPL-3.0-or-later", + "authors" : [ { + "name" : "Wim Godden", + "role" : "lead" + }, + { + "name" : "Juliette Reinders Folmer", + "role" : "lead" + } ], + "support" : { + "issues" : "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", + "source" : "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + }, + "require" : { + "phpcompatibility/php-compatibility" : "^9.0" + }, + "require-dev" : { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7", + "paragonie/random_compat": "dev-master", + "paragonie/sodium_compat": "dev-master" + }, + "suggest" : { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "prefer-stable" : true +} diff --git a/vendor/phpcompatibility/phpcompatibility-wp/LICENSE b/vendor/phpcompatibility/phpcompatibility-wp/LICENSE new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/vendor/phpcompatibility/phpcompatibility-wp/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/vendor/phpcompatibility/phpcompatibility-wp/PHPCompatibilityWP/ruleset.xml b/vendor/phpcompatibility/phpcompatibility-wp/PHPCompatibilityWP/ruleset.xml new file mode 100644 index 00000000..4d92d8b2 --- /dev/null +++ b/vendor/phpcompatibility/phpcompatibility-wp/PHPCompatibilityWP/ruleset.xml @@ -0,0 +1,82 @@ +<?xml version="1.0"?> +<ruleset name="PHPCompatibilityWP"> + <description>WordPress specific ruleset which checks for PHP cross version compatibility.</description> + + <!-- + The WordPress minimum PHP requirement was 5.2.4 up to WP 5.1. + As of WP 5.2, the new minimum PHP requirement is PHP 5.6.20. + Add the following in your project PHP_CodeSniffer ruleset to enforce this: + <config name="testVersion" value="5.6-"/> + + This directive is not included in this ruleset as individual projects may use + a different (higher) minimum PHP version. + --> + + <rule ref="PHPCompatibility"> + <!-- + Contained in /wp-includes/compat.php. + + History of the polyfills in WP: + * hash_hmac(): since WP 3.2.0. + * json_encode() and json_decode(): since unknown. + * hash_equals(): since WP 3.9.2. + * JSON_PRETTY_PRINT: since WP 4.1.0. + * json_last_error_msg(): since WP 4.4.0. + * JsonSerializable: since WP 4.4.0. + * array_replace_recursive(): since WP 4.5.3 up to 5.2.x. The polyfill was removed in WP 5.3. + * is_iterable(): since WP 4.9.6 + * is_countable(): since WP 4.9.6 + * IMAGETYPE_WEBP and IMG_WEBP: since WP 5.8.0. + * array_key_first(): since WP 5.9.0 + * array_key_last(): since WP 5.9.0 + * str_contains(): since WP 5.9.0 + * str_starts_with(): since WP 5.9.0 + * str_ends_with(): since WP 5.9.0 + --> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.hash_hmacFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.json_encodeFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.json_decodeFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.hash_equalsFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.json_pretty_printFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.json_last_error_msgFound"/> + <exclude name="PHPCompatibility.Interfaces.NewInterfaces.jsonserializableFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.array_replace_recursiveFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.is_iterableFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.is_countableFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.imagetype_webpFound"/> + <exclude name="PHPCompatibility.Constants.NewConstants.img_webpFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.array_key_firstFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.array_key_lastFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.str_containsFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.str_starts_withFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.str_ends_withFound"/> + + <!-- + Contained in /wp-includes/spl-autoload-compat.php. + + History of the polyfills in WP: + * spl_autoload_register(), spl_autoload_unregister() and spl_autoload_functions() were + introduced in WP 4.6.0 and available up to WP 5.2.x. The polyfills were removed in WP 5.3. + --> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.spl_autoload_registerFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.spl_autoload_unregisterFound"/> + <exclude name="PHPCompatibility.FunctionUse.NewFunctions.spl_autoload_functionsFound"/> + </rule> + + <!-- + The ParagonieSodiumCompat ruleset includes the ParagonieRandomCompat ruleset. + + RancomCompat is contained in /wp-includes/random_compat/ since WP 4.4.0 + SodiumCompat is contained in /wp-includes/sodium_compat/ since WP 5.2.0 + --> + <rule ref="PHPCompatibilityParagonieSodiumCompat"/> + + <!-- Whitelist the WP Core mysql_to_rfc3339() function. --> + <rule ref="PHPCompatibility.Extensions.RemovedExtensions"> + <properties> + <!-- Contained in /wp-includes/functions.php. --> + <property name="functionWhitelist" type="array" value="mysql_to_rfc3339"/> + </properties> + </rule> + +</ruleset> diff --git a/vendor/phpcompatibility/phpcompatibility-wp/README.md b/vendor/phpcompatibility/phpcompatibility-wp/README.md new file mode 100644 index 00000000..55d66b91 --- /dev/null +++ b/vendor/phpcompatibility/phpcompatibility-wp/README.md @@ -0,0 +1,135 @@ +[![Latest Stable Version](https://poser.pugx.org/phpcompatibility/phpcompatibility-wp/v/stable.png)](https://packagist.org/packages/phpcompatibility/phpcompatibility-wp) +[![Latest Unstable Version](https://poser.pugx.org/phpcompatibility/phpcompatibility-wp/v/unstable.png)](https://packagist.org/packages/phpcompatibility/phpcompatibility-wp) +[![License](https://poser.pugx.org/phpcompatibility/phpcompatibility-wp/license.png)](https://github.com/PHPCompatibility/PHPCompatibilityWP/blob/master/LICENSE) +[![Build Status](https://github.com/PHPCompatibility/PHPCompatibilityWP/workflows/CI/badge.svg?branch=master)](https://github.com/PHPCompatibility/PHPCompatibilityWP/actions) + +# PHPCompatibilityWP + +Using PHPCompatibilityWP, you can analyse the codebase of a WordPress-based project for PHP cross-version compatibility. + + +## What's in this repo ? + +A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects based on the WordPress CMS. + +This WordPress specific ruleset prevents false positives from the [PHPCompatibility standard](https://github.com/PHPCompatibility/PHPCompatibility) by excluding back-fills and poly-fills which are provided by WordPress. + + +## Requirements + +* [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer). + * PHP 5.3+ for use with [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) 2.3.0+. + * PHP 5.4+ for use with [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) 3.0.2+. + + Use the latest stable release of PHP_CodeSniffer for the best results. + The minimum _recommended_ version of PHP_CodeSniffer is version 2.6.0. +* [PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility) 9.0.0+. +* [PHPCompatibilityParagonie](https://github.com/PHPCompatibility/PHPCompatibilityParagonie) 1.0.0+. + + +## Installation instructions + +The only supported installation method is via [Composer](https://getcomposer.org/). + +If you don't have a Composer plugin installed to manage the `installed_paths` setting for PHP_CodeSniffer, run the following from the command-line: +```bash +composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true +composer require --dev dealerdirect/phpcodesniffer-composer-installer:"^0.7" phpcompatibility/phpcompatibility-wp:"*" +``` + +If you already have a Composer PHP_CodeSniffer plugin installed, run: +```bash +composer require --dev phpcompatibility/phpcompatibility-wp:"*" +``` + +Next, run: +```bash +vendor/bin/phpcs -i +``` +If all went well, you will now see that the `PHPCompatibility`, `PHPCompatibilityWP` and some more PHPCompatibility standards are installed for PHP_CodeSniffer. + + +## How to use + +Now you can use the following command to inspect your code: +```bash +./vendor/bin/phpcs -p . --standard=PHPCompatibilityWP +``` + +By default, you will only receive notifications about deprecated and/or removed PHP features. + +To get the most out of the PHPCompatibilityWP standard, you should specify a `testVersion` to check against. That will enable the checks for both deprecated/removed PHP features as well as the detection of code using new PHP features. + +The minimum PHP requirement of the WordPress project up to WP 5.1 was 5.2.4. As of WP 5.2 it will be PHP 5.6.20. If you want to enforce this, either add `--runtime-set testVersion 5.6-` to your command-line command or add `<config name="testVersion" value="5.6-"/>` to your [custom ruleset](https://github.com/PHPCompatibility/PHPCompatibility#using-a-custom-ruleset). + +For example: +```bash +# For a project which should be compatible with PHP 5.6 and higher: +./vendor/bin/phpcs -p . --standard=PHPCompatibilityWP --runtime-set testVersion 5.6- +``` + +For more detailed information about setting the `testVersion`, see the README of the generic [PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility#sniffing-your-code-for-compatibility-with-specific-php-versions) standard. + + +### Testing PHP files only + +By default PHP_CodeSniffer will analyse PHP, JavaScript and CSS files. As the PHPCompatibility sniffs only target PHP code, you can make the run slightly faster by telling PHP_CodeSniffer to only check PHP files, like so: +```bash +./vendor/bin/phpcs -p . --standard=PHPCompatibilityWP --extensions=php --runtime-set testVersion 5.6- +``` + +## License + +All code within the PHPCompatibility organisation is released under the GNU Lesser General Public License (LGPL). For more information, visit https://www.gnu.org/copyleft/lesser.html + + +## Changelog + +### 2.1.4 - 2022-10-24 + +- Composer: The package will now identify itself as a static analysis tool. Thanks [@GaryJones]! +- Other housekeeping and minor documentation updates. + +### 2.1.3 - 2021-12-31 + +- Ruleset: Updated for compatibility with WordPress 5.9. +- README: Updated the installation instructions for [compatibility with Composer >= 2.2][composer22announce]. +- Minor housekeeping. + +[composer22announce]: https://blog.packagist.com/composer-2-2/#more-secure-plugin-execution + +### 2.1.2 - 2021-07-21 + +- Ruleset: Updated for compatibility with WordPress 5.8. +- Documentation: improved installation instructions. Props [Andy Fragen](https://github.com/afragen). + +### 2.1.1 - 2021-02-15 + +- The recommended version of the [Composer PHPCS plugin] is now `^0.7.0`, which offers compatibility with Composer 2.0. +- The ruleset is now also tested against PHP 7.4 and 8.0. + Note: full PHP 7.4 support is only available in combination with PHP_CodeSniffer >= 3.5.6. + Note: runtime PHP 8.0 support is only available in combination with PHP_CodeSniffer >= 3.5.7, full support is expected in PHP_CodeSniffer 3.6.0. + +### 2.1.0 - 2019-08-29 + +- Ruleset: Updated for the Sodium_Compat polyfill which is included in WordPress 5.2. +- Composer: The recommended version of the [Composer PHPCS plugin] has been upped to `^0.5.0`. +- Documentation: Updated the ruleset inline documentation and the Readme to reflect the change in minimum PHP requirements for WordPress as of WP 5.2. +- Documentation: Updated the ruleset inline documentation to include information on when each polyfill was added to/removed from WordPress. +- CI: The rulesets are now also tested against PHP 7.3. + Note: full PHP 7.3 support is only available in combination with PHP_CodeSniffer 2.9.2 or 3.3.1+ due to an incompatibility within PHP_CodeSniffer itself. + +### 2.0.0 - 2018-10-07 + +- Ruleset: Updated for compatibility with PHPCompatibility 9.0+. +- Composer: Added dependency for a dedicated polyfill-based PHPCompatibility ruleset. +- CI: Added a test for the ruleset. +- Readme: Removed the installation instructions for a non-Composer based install. + +### 1.0.0 - 2018-07-17 + +Initial release of the PHPCompatibilityWP ruleset. + +[Composer PHPCS plugin]: https://github.com/PHPCSStandards/composer-installer/ + +[@GaryJones]: https://github.com/GaryJones diff --git a/vendor/phpcompatibility/phpcompatibility-wp/composer.json b/vendor/phpcompatibility/phpcompatibility-wp/composer.json new file mode 100644 index 00000000..2132398a --- /dev/null +++ b/vendor/phpcompatibility/phpcompatibility-wp/composer.json @@ -0,0 +1,37 @@ +{ + "name" : "phpcompatibility/phpcompatibility-wp", + "description" : "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.", + "type" : "phpcodesniffer-standard", + "keywords" : [ "compatibility", "phpcs", "standards", "static analysis", "wordpress" ], + "homepage" : "http://phpcompatibility.com/", + "license" : "LGPL-3.0-or-later", + "authors" : [ { + "name" : "Wim Godden", + "role" : "lead" + }, + { + "name" : "Juliette Reinders Folmer", + "role" : "lead" + } ], + "support" : { + "issues" : "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues", + "source" : "https://github.com/PHPCompatibility/PHPCompatibilityWP" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + }, + "require" : { + "phpcompatibility/php-compatibility" : "^9.0", + "phpcompatibility/phpcompatibility-paragonie" : "^1.0" + }, + "require-dev" : { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7" + }, + "suggest" : { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "prefer-stable" : true +} diff --git a/vendor/phpunit/php-code-coverage/ChangeLog.md b/vendor/phpunit/php-code-coverage/ChangeLog.md new file mode 100644 index 00000000..cdf28e0a --- /dev/null +++ b/vendor/phpunit/php-code-coverage/ChangeLog.md @@ -0,0 +1,523 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [9.2.24] - 2023-01-26 + +### Changed + +* [#970](https://github.com/sebastianbergmann/php-code-coverage/issues/970): CSS and JavaScript assets are now referenced using `?v=%s` URLs in the HTML report to avoid cache issues + +## [9.2.23] - 2022-12-28 + +### Fixed + +* [#971](https://github.com/sebastianbergmann/php-code-coverage/issues/971): PHP report does not handle serialized code coverage data larger than 2 GB +* [#974](https://github.com/sebastianbergmann/php-code-coverage/issues/974): Executable line analysis fails for declarations with enumerations and unions + +## [9.2.22] - 2022-12-18 + +### Fixed + +* [#969](https://github.com/sebastianbergmann/php-code-coverage/pull/969): Fixed identifying line with `throw` as executable + +## [9.2.21] - 2022-12-14 + +### Changed + +* [#964](https://github.com/sebastianbergmann/php-code-coverage/pull/964): Changed how executable lines are identified + +## [9.2.20] - 2022-12-13 + +### Fixed + +* [#960](https://github.com/sebastianbergmann/php-code-coverage/issues/960): New body font-size is way too big + +## [9.2.19] - 2022-11-18 + +### Fixed + +* [#949](https://github.com/sebastianbergmann/php-code-coverage/pull/949): Various issues related to identifying executable lines + +### Changed + +* Tweaked CSS for HTML report +* Updated bundled CSS/JavaScript components used for HTML report: Bootstrap 4.6.2 and jQuery 3.6.1 + +## [9.2.18] - 2022-10-27 + +### Fixed + +* [#935](https://github.com/sebastianbergmann/php-code-coverage/pull/935): Cobertura package name attribute is always empty +* [#946](https://github.com/sebastianbergmann/php-code-coverage/issues/946): `return` with multiline constant expression must only contain the last line + +## [9.2.17] - 2022-08-30 + +### Changed + +* [#928](https://github.com/sebastianbergmann/php-code-coverage/pull/928): Avoid unnecessary `is_file()` calls +* [#931](https://github.com/sebastianbergmann/php-code-coverage/pull/931): Use MD5 instead of CRC32 for static analysis cache file identifier + +### Fixed + +* [#926](https://github.com/sebastianbergmann/php-code-coverage/pull/926): Static Analysis cache does not work with `open_basedir` + +## [9.2.16] - 2022-08-20 + +### Fixed + +* [#926](https://github.com/sebastianbergmann/php-code-coverage/issues/926): File view has wrong colouring for the first column + +## [9.2.15] - 2022-03-07 + +### Fixed + +* [#885](https://github.com/sebastianbergmann/php-code-coverage/issues/885): Files that have only `\r` (CR, 0x0d) EOL characters are not handled correctly +* [#907](https://github.com/sebastianbergmann/php-code-coverage/issues/907): Line with only `return [` is not recognized as executable + +## [9.2.14] - 2022-02-28 + +### Fixed + +* [#904](https://github.com/sebastianbergmann/php-code-coverage/issues/904): Lines of code containing the `match` keyword were not recognized as executable correctly +* [#905](https://github.com/sebastianbergmann/php-code-coverage/issues/905): Lines of code in constructors were not recognized as executable correctly when constructor property promotion is used + +## [9.2.13] - 2022-02-23 + +### Changed + +* The contents of the static analysis sourcecode files is now used to generate the static analysis cache version identifier + +### Fixed + +* Reverted rename of `SebastianBergmann\CodeCoverage\ProcessedCodeCoverageData` to `SebastianBergmann\CodeCoverage\Data\ProcessedCodeCoverageData` (this class is marked as `@internal` and not covered by the backward compatibility promise, but it is (still) used directly by PHPUnit) +* Reverted rename of `SebastianBergmann\CodeCoverage\RawCodeCoverageData` to `SebastianBergmann\CodeCoverage\Data\RawCodeCoverageData` (this class is marked as `@internal` and not covered by the backward compatibility promise, but it is (still) used directly by PHPUnit) +* The `ArrayDim`, `Cast`, and `MethodCall` nodes are now considered when determining whether a line of code is executable or not + +## [9.2.12] - 2022-02-23 [YANKED] + +### Changed + +* [#898](https://github.com/sebastianbergmann/php-code-coverage/pull/898): Use content hash instead of `filemtime()` to determine cache hit/miss + +### Fixed + +* [#736](https://github.com/sebastianbergmann/php-code-coverage/issues/736): HTML report generator allows invalid values for low upper bound and high lower bound +* [#854](https://github.com/sebastianbergmann/php-code-coverage/issues/854): "Class Coverage Distribution" and "Class Complexity" graphs are not displayed at full width +* [#897](https://github.com/sebastianbergmann/php-code-coverage/issues/897): `declare(strict_types=1)` marked as uncovered + +## [9.2.11] - 2022-02-18 + +### Changed + +* `CoveredFileAnalyser` and `UncoveredFileAnalyser` have been combined to `FileAnalyser` +* Updated bundled CSS/JavaScript components used for HTML report: Bootstrap 4.6.1, jQuery 3.6.0, and popper.js 1.16.1 + +### Fixed + +* [#889](https://github.com/sebastianbergmann/php-code-coverage/issues/889): Code Coverage depends on autoload order + +## [9.2.10] - 2021-12-05 + +### Fixed + +* [#887](https://github.com/sebastianbergmann/php-code-coverage/issues/887): Document return type of `CodeUnitFindingVisitor::enterNode()` so that Symfony's DebugClassLoader does not trigger a deprecation warning + +## [9.2.9] - 2021-11-19 + +### Fixed + +* [#882](https://github.com/sebastianbergmann/php-code-coverage/issues/882): PHPUnit 9.2.8 has wrong version number + +## [9.2.8] - 2021-10-30 + +### Fixed + +* [#866](https://github.com/sebastianbergmann/php-code-coverage/issues/866): `CodeUnitFindingVisitor` does not handle `enum` type introduced in PHP 8.1 +* [#868](https://github.com/sebastianbergmann/php-code-coverage/pull/868): Uncovered files should be ignored unless requested +* [#876](https://github.com/sebastianbergmann/php-code-coverage/issues/876): PCOV driver causes 2x slowdown after upgrade to PHPUnit 9.5 + +## [9.2.7] - 2021-09-17 + +### Fixed + +* [#860](https://github.com/sebastianbergmann/php-code-coverage/pull/860): Empty value for `XDEBUG_MODE` environment variable is not handled correctly + +## [9.2.6] - 2021-03-28 + +### Fixed + +* [#846](https://github.com/sebastianbergmann/php-code-coverage/issues/846): Method name should not appear in the method signature attribute of Cobertura XML + +## [9.2.5] - 2020-11-28 + +### Fixed + +* [#831](https://github.com/sebastianbergmann/php-code-coverage/issues/831): Files that do not contain a newline are not handled correctly + +## [9.2.4] - 2020-11-27 + +### Added + +* [#834](https://github.com/sebastianbergmann/php-code-coverage/issues/834): Support `XDEBUG_MODE` environment variable + +## [9.2.3] - 2020-10-30 + +### Changed + +* Bumped required version of `nikic/php-parser` + +## [9.2.2] - 2020-10-28 + +### Fixed + +* [#820](https://github.com/sebastianbergmann/php-code-coverage/issues/820): Hidden dependency on PHPUnit + +## [9.2.1] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\CodeCoverage\Exception` now correctly extends `\Throwable` + +## [9.2.0] - 2020-10-02 + +### Added + +* [#812](https://github.com/sebastianbergmann/php-code-coverage/pull/812): Support for Cobertura XML report format + +### Changed + +* Reduced the number of I/O operations performed by the static analysis cache + +## [9.1.11] - 2020-09-19 + +### Fixed + +* [#811](https://github.com/sebastianbergmann/php-code-coverage/issues/811): `T_FN` constant is used on PHP 7.3 where it is not available + +## [9.1.10] - 2020-09-18 + +### Added + +* `SebastianBergmann\CodeCoverage\Driver\Selector::forLineCoverage()` and `SebastianBergmann\CodeCoverage\Driver\Selector::forLineAndPathCoverage()` have been added + +### Fixed + +* [#810](https://github.com/sebastianbergmann/php-code-coverage/issues/810): `SebastianBergmann\CodeCoverage\Driver\Driver::forLineCoverage()` and `SebastianBergmann\CodeCoverage\Driver\Driver::forLineAndPathCoverage()` are marked as internal + +### Removed + +* `SebastianBergmann\CodeCoverage\Driver\Driver::forLineCoverage()` and `SebastianBergmann\CodeCoverage\Driver\Driver::forLineAndPathCoverage()` are now deprecated + +## [9.1.9] - 2020-09-15 + +### Fixed + +* [#808](https://github.com/sebastianbergmann/php-code-coverage/issues/808): `PHP Warning: Use of undefined constant T_MATCH` + +## [9.1.8] - 2020-09-07 + +### Changed + +* [#800](https://github.com/sebastianbergmann/php-code-coverage/pull/800): All files on the inclusion list are no longer loaded when `SebastianBergmann\CodeCoverage::start()` is called for the first time and `processUncoveredFiles` is set to `true` + +### Fixed + +* [#799](https://github.com/sebastianbergmann/php-code-coverage/issues/799): Uncovered new line at end of file + +## [9.1.7] - 2020-09-03 + +### Fixed + +* Fixed regressions introduced in versions 9.1.5 and 9.1.6 + +## [9.1.6] - 2020-08-31 + +### Fixed + +* [#799](https://github.com/sebastianbergmann/php-code-coverage/issues/799): Uncovered new line at end of file +* [#803](https://github.com/sebastianbergmann/php-code-coverage/issues/803): HTML report does not sort directories and files anymore + +## [9.1.5] - 2020-08-27 + +### Changed + +* [#800](https://github.com/sebastianbergmann/php-code-coverage/pull/800): All files on the inclusion list are no longer loaded when `SebastianBergmann\CodeCoverage::start()` is called for the first time and `processUncoveredFiles` is set to `true` + +### Fixed + +* [#797](https://github.com/sebastianbergmann/php-code-coverage/pull/797): Class name is wrongly removed from namespace name + +## [9.1.4] - 2020-08-13 + +### Fixed + +* [#793](https://github.com/sebastianbergmann/php-code-coverage/issues/793): Lines with `::class` constant are not covered + +## [9.1.3] - 2020-08-10 + +### Changed + +* Changed PHP-Parser usage to parse sourcecode according to the PHP version we are currently running on instead of using emulative lexing + +## [9.1.2] - 2020-08-10 + +### Fixed + +* [#791](https://github.com/sebastianbergmann/php-code-coverage/pull/791): Cache Warmer does not warm all caches + +## [9.1.1] - 2020-08-10 + +### Added + +* Added `SebastianBergmann\CodeCoverage::cacheDirectory()` method for querying where the cache writes its files + +## [9.1.0] - 2020-08-10 + +### Added + +* Implemented a persistent cache for information gathered using PHP-Parser based static analysis (hereinafter referred to as "cache") +* Added `SebastianBergmann\CodeCoverage::cacheStaticAnalysis(string $cacheDirectory)` method for enabling the cache; it will write its files to `$directory` +* Added `SebastianBergmann\CodeCoverage::doNotCacheStaticAnalysis` method for disabling the cache +* Added `SebastianBergmann\CodeCoverage::cachesStaticAnalysis()` method for querying whether the cache is enabled +* Added `SebastianBergmann\CodeCoverage\StaticAnalysis\CacheWarmer::warmCache()` method for warming the cache + +## [9.0.0] - 2020-08-07 + +### Added + +* [#761](https://github.com/sebastianbergmann/php-code-coverage/pull/761): Support for Branch Coverage and Path Coverage +* Added `SebastianBergmann\CodeCoverage\Driver\Driver::forLineCoverage()` for selecting the best available driver for line coverage +* Added `SebastianBergmann\CodeCoverage\Driver\Driver::forLineAndPathCoverage()` for selecting the best available driver for path coverage +* This component is now supported on PHP 8 +* This component now supports Xdebug 3 + +### Changed + +* [#746](https://github.com/sebastianbergmann/php-code-coverage/pull/746): Remove some ancient workarounds for very old Xdebug versions +* [#747](https://github.com/sebastianbergmann/php-code-coverage/pull/747): Use native filtering in PCOV and Xdebug drivers +* [#748](https://github.com/sebastianbergmann/php-code-coverage/pull/748): Store raw code coverage in value objects instead of arrays +* [#749](https://github.com/sebastianbergmann/php-code-coverage/pull/749): Store processed code coverage in value objects instead of arrays +* [#752](https://github.com/sebastianbergmann/php-code-coverage/pull/752): Rework how code coverage settings are propagated to the driver +* [#754](https://github.com/sebastianbergmann/php-code-coverage/pull/754): Implement collection of raw branch and path coverage +* [#755](https://github.com/sebastianbergmann/php-code-coverage/pull/755): Implement processing of raw branch and path coverage +* [#756](https://github.com/sebastianbergmann/php-code-coverage/pull/756): Improve handling of uncovered files +* `SebastianBergmann\CodeCoverage\Filter::addDirectoryToWhitelist()` has been renamed to `SebastianBergmann\CodeCoverage\Filter::includeDirectory()` +* `SebastianBergmann\CodeCoverage\Filter::addFilesToWhitelist()` has been renamed to `SebastianBergmann\CodeCoverage\Filter::includeFiles()` +* `SebastianBergmann\CodeCoverage\Filter::addFileToWhitelist()` has been renamed to `SebastianBergmann\CodeCoverage\Filter::includeFile()` +* `SebastianBergmann\CodeCoverage\Filter::removeDirectoryFromWhitelist()` has been renamed to `SebastianBergmann\CodeCoverage\Filter::excludeDirectory()` +* `SebastianBergmann\CodeCoverage\Filter::removeFileFromWhitelist()` has been renamed to `SebastianBergmann\CodeCoverage\Filter::excludeFile()` +* `SebastianBergmann\CodeCoverage\Filter::isFiltered()` has been renamed to `SebastianBergmann\CodeCoverage\Filter::isExcluded()` +* `SebastianBergmann\CodeCoverage\Filter::getWhitelist()` has been renamed to `SebastianBergmann\CodeCoverage\Filter::files()` +* The arguments for `CodeCoverage::__construct()` are no longer optional + +### Fixed + +* [#700](https://github.com/sebastianbergmann/php-code-coverage/pull/700): Throw an exception if code coverage fails to write to disk + +### Removed + +* `SebastianBergmann\CodeCoverage\CodeCoverage::setCacheTokens()` and `SebastianBergmann\CodeCoverage\CodeCoverage::getCacheTokens()` have been removed +* `SebastianBergmann\CodeCoverage\CodeCoverage::setCheckForUnintentionallyCoveredCode()` has been removed, please use `SebastianBergmann\CodeCoverage\CodeCoverage::enableCheckForUnintentionallyCoveredCode()` or `SebastianBergmann\CodeCoverage\CodeCoverage::disableCheckForUnintentionallyCoveredCode()` instead +* `SebastianBergmann\CodeCoverage\CodeCoverage::setSubclassesExcludedFromUnintentionallyCoveredCodeCheck()` has been removed, please use `SebastianBergmann\CodeCoverage\CodeCoverage::excludeSubclassesOfThisClassFromUnintentionallyCoveredCodeCheck()` instead +* `SebastianBergmann\CodeCoverage\CodeCoverage::setAddUncoveredFilesFromWhitelist()` has been removed, please use `SebastianBergmann\CodeCoverage\CodeCoverage::includeUncoveredFiles()` or `SebastianBergmann\CodeCoverage\CodeCoverage::excludeUncoveredFiles()` instead +* `SebastianBergmann\CodeCoverage\CodeCoverage::setProcessUncoveredFiles()` has been removed, please use `SebastianBergmann\CodeCoverage\CodeCoverage::processUncoveredFiles()` or `SebastianBergmann\CodeCoverage\CodeCoverage::doNotProcessUncoveredFiles()` instead +* `SebastianBergmann\CodeCoverage\CodeCoverage::setIgnoreDeprecatedCode()` has been removed, please use `SebastianBergmann\CodeCoverage\CodeCoverage::ignoreDeprecatedCode()` or `SebastianBergmann\CodeCoverage\CodeCoverage::doNotIgnoreDeprecatedCode()` instead +* `SebastianBergmann\CodeCoverage\CodeCoverage::setDisableIgnoredLines()` has been removed, please use `SebastianBergmann\CodeCoverage\CodeCoverage::enableAnnotationsForIgnoringCode()` or `SebastianBergmann\CodeCoverage\CodeCoverage::disableAnnotationsForIgnoringCode()` instead +* `SebastianBergmann\CodeCoverage\CodeCoverage::setCheckForMissingCoversAnnotation()` has been removed +* `SebastianBergmann\CodeCoverage\CodeCoverage::setCheckForUnexecutedCoveredCode()` has been removed +* `SebastianBergmann\CodeCoverage\CodeCoverage::setForceCoversAnnotation()` has been removed +* `SebastianBergmann\CodeCoverage\Filter::hasWhitelist()` has been removed, please use `SebastianBergmann\CodeCoverage\Filter::isEmpty()` instead +* `SebastianBergmann\CodeCoverage\Filter::getWhitelistedFiles()` has been removed +* `SebastianBergmann\CodeCoverage\Filter::setWhitelistedFiles()` has been removed + +## [8.0.2] - 2020-05-23 + +### Fixed + +* [#750](https://github.com/sebastianbergmann/php-code-coverage/pull/750): Inconsistent handling of namespaces +* [#751](https://github.com/sebastianbergmann/php-code-coverage/pull/751): Dead code is not highlighted correctly +* [#753](https://github.com/sebastianbergmann/php-code-coverage/issues/753): Do not use `$_SERVER['REQUEST_TIME']` because the test(ed) code might unset it + +## [8.0.1] - 2020-02-19 + +### Fixed + +* [#731](https://github.com/sebastianbergmann/php-code-coverage/pull/731): Confusing footer in the HTML report + +## [8.0.0] - 2020-02-07 + +### Fixed + +* [#721](https://github.com/sebastianbergmann/php-code-coverage/pull/721): Workaround for PHP bug [#79191](https://bugs.php.net/bug.php?id=79191) + +### Removed + +* This component is no longer supported on PHP 7.2 + +## [7.0.15] - 2021-07-26 + +### Changed + +* Bumped required version of php-token-stream + +## [7.0.14] - 2020-12-02 + +### Changed + +* [#837](https://github.com/sebastianbergmann/php-code-coverage/issues/837): Allow version 4 of php-token-stream + +## [7.0.13] - 2020-11-30 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.2` to `>=7.2` to allow installation of this version of this library on PHP 8. However, this version of this library does not work on PHP 8. PHPUnit 8.5, which uses this version of this library, does not call into this library and instead shows a message that code coverage functionality is not available for PHPUnit 8.5 on PHP 8. + +## [7.0.12] - 2020-11-27 + +### Added + +* [#834](https://github.com/sebastianbergmann/php-code-coverage/issues/834): Support `XDEBUG_MODE` environment variable + +## [7.0.11] - 2020-11-27 + +### Added + +* Support for Xdebug 3 + +## [7.0.10] - 2019-11-20 + +### Fixed + +* [#710](https://github.com/sebastianbergmann/php-code-coverage/pull/710): Code Coverage does not work in PhpStorm + +## [7.0.9] - 2019-11-20 + +### Changed + +* [#709](https://github.com/sebastianbergmann/php-code-coverage/pull/709): Prioritize PCOV over Xdebug + +## [7.0.8] - 2019-09-17 + +### Changed + +* Updated bundled CSS/JavaScript components used for HTML report: Bootstrap 4.3.1, jQuery 3.4.1, and popper.js 1.15.0 + +## [7.0.7] - 2019-07-25 + +### Changed + +* Bumped required version of php-token-stream + +## [7.0.6] - 2019-07-08 + +### Changed + +* Bumped required version of php-token-stream + +## [7.0.5] - 2019-06-06 + +### Fixed + +* [#681](https://github.com/sebastianbergmann/php-code-coverage/pull/681): `use function` statements are not ignored + +## [7.0.4] - 2019-05-29 + +### Fixed + +* [#682](https://github.com/sebastianbergmann/php-code-coverage/pull/682): Code that is not executed is reported as being executed when using PCOV + +## [7.0.3] - 2019-02-26 + +### Fixed + +* [#671](https://github.com/sebastianbergmann/php-code-coverage/issues/671): `TypeError` when directory name is a number + +## [7.0.2] - 2019-02-15 + +### Changed + +* Updated bundled CSS/JavaScript components used for HTML report: Bootstrap 4.3.0 + +### Fixed + +* [#667](https://github.com/sebastianbergmann/php-code-coverage/pull/667): `TypeError` in PHP reporter + +## [7.0.1] - 2019-02-01 + +### Fixed + +* [#664](https://github.com/sebastianbergmann/php-code-coverage/issues/664): `TypeError` when whitelisted file does not exist + +## [7.0.0] - 2019-02-01 + +### Added + +* [#663](https://github.com/sebastianbergmann/php-code-coverage/pull/663): Support for PCOV + +### Fixed + +* [#654](https://github.com/sebastianbergmann/php-code-coverage/issues/654): HTML report fails to load assets +* [#655](https://github.com/sebastianbergmann/php-code-coverage/issues/655): Popin pops in outside of screen + +### Removed + +* This component is no longer supported on PHP 7.1 + +[9.2.24]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.23...9.2.24 +[9.2.23]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.22...9.2.23 +[9.2.22]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.21...9.2.22 +[9.2.21]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.20...9.2.21 +[9.2.20]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.19...9.2.20 +[9.2.19]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.18...9.2.19 +[9.2.18]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.17...9.2.18 +[9.2.17]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.16...9.2.17 +[9.2.16]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.15...9.2.16 +[9.2.15]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.14...9.2.15 +[9.2.14]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.13...9.2.14 +[9.2.13]: https://github.com/sebastianbergmann/php-code-coverage/compare/c011a0b6aaa4acd2f39b7f51fb4ad4442b6ec631...9.2.13 +[9.2.12]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.11...c011a0b6aaa4acd2f39b7f51fb4ad4442b6ec631 +[9.2.11]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.10...9.2.11 +[9.2.10]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.9...9.2.10 +[9.2.9]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.8...9.2.9 +[9.2.8]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.7...9.2.8 +[9.2.7]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.6...9.2.7 +[9.2.6]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.5...9.2.6 +[9.2.5]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.4...9.2.5 +[9.2.4]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.3...9.2.4 +[9.2.3]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.2...9.2.3 +[9.2.2]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.1...9.2.2 +[9.2.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.0...9.2.1 +[9.2.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.11...9.2.0 +[9.1.11]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.10...9.1.11 +[9.1.10]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.9...9.1.10 +[9.1.9]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.8...9.1.9 +[9.1.8]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.7...9.1.8 +[9.1.7]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.6...9.1.7 +[9.1.6]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.5...9.1.6 +[9.1.5]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.4...9.1.5 +[9.1.4]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.3...9.1.4 +[9.1.3]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.2...9.1.3 +[9.1.2]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.1...9.1.2 +[9.1.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.1.0...9.1.1 +[9.1.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.0.0...9.1.0 +[9.0.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/8.0...9.0.0 +[8.0.2]: https://github.com/sebastianbergmann/php-code-coverage/compare/8.0.1...8.0.2 +[8.0.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/8.0.0...8.0.1 +[8.0.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.10...8.0.0 +[7.0.15]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.14...7.0.15 +[7.0.14]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.13...7.0.14 +[7.0.13]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.12...7.0.13 +[7.0.12]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.11...7.0.12 +[7.0.11]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.10...7.0.11 +[7.0.10]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.9...7.0.10 +[7.0.9]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.8...7.0.9 +[7.0.8]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.7...7.0.8 +[7.0.7]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.6...7.0.7 +[7.0.6]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.5...7.0.6 +[7.0.5]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.4...7.0.5 +[7.0.4]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.3...7.0.4 +[7.0.3]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.2...7.0.3 +[7.0.2]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.1...7.0.2 +[7.0.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/7.0.0...7.0.1 +[7.0.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/6.1.4...7.0.0 diff --git a/vendor/phpunit/php-code-coverage/LICENSE b/vendor/phpunit/php-code-coverage/LICENSE new file mode 100644 index 00000000..80e09f7b --- /dev/null +++ b/vendor/phpunit/php-code-coverage/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2009-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/phpunit/php-code-coverage/README.md b/vendor/phpunit/php-code-coverage/README.md new file mode 100644 index 00000000..53ce9b33 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/README.md @@ -0,0 +1,48 @@ +# phpunit/php-code-coverage + +[![Latest Stable Version](https://poser.pugx.org/phpunit/php-code-coverage/v/stable.png)](https://packagist.org/packages/phpunit/php-code-coverage) +[![CI Status](https://github.com/sebastianbergmann/php-code-coverage/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/php-code-coverage/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/php-code-coverage/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/php-code-coverage) + +Provides collection, processing, and rendering functionality for PHP code coverage information. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require phpunit/php-code-coverage +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev phpunit/php-code-coverage +``` + +## Usage + +```php +<?php declare(strict_types=1); +use SebastianBergmann\CodeCoverage\Filter; +use SebastianBergmann\CodeCoverage\Driver\Selector; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Report\Html\Facade as HtmlReport; + +$filter = new Filter; +$filter->includeDirectory('/path/to/directory'); + +$coverage = new CodeCoverage( + (new Selector)->forLineCoverage($filter), + $filter +); + +$coverage->start('<name of test>'); + +// ... + +$coverage->stop(); + + +(new HtmlReport)->process($coverage, '/tmp/code-coverage-report'); +``` diff --git a/vendor/phpunit/php-code-coverage/composer.json b/vendor/phpunit/php-code-coverage/composer.json new file mode 100644 index 00000000..b09bd647 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/composer.json @@ -0,0 +1,68 @@ +{ + "name": "phpunit/php-code-coverage", + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "type": "library", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues" + }, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "prefer-stable": true, + "require": { + "php": ">=7.3", + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.14", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcov": "*", + "ext-xdebug": "*" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "files": [ + "tests/TestCase.php", + "tests/_files/BankAccountTest.php" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "9.2-dev" + } + } +} diff --git a/vendor/phpunit/php-code-coverage/src/CodeCoverage.php b/vendor/phpunit/php-code-coverage/src/CodeCoverage.php new file mode 100644 index 00000000..c35f27c8 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/CodeCoverage.php @@ -0,0 +1,682 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use function array_diff; +use function array_diff_key; +use function array_flip; +use function array_keys; +use function array_merge; +use function array_unique; +use function array_values; +use function count; +use function explode; +use function get_class; +use function is_array; +use function sort; +use PHPUnit\Framework\TestCase; +use PHPUnit\Runner\PhptTestCase; +use PHPUnit\Util\Test; +use ReflectionClass; +use SebastianBergmann\CodeCoverage\Driver\Driver; +use SebastianBergmann\CodeCoverage\Node\Builder; +use SebastianBergmann\CodeCoverage\Node\Directory; +use SebastianBergmann\CodeCoverage\StaticAnalysis\CachingFileAnalyser; +use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser; +use SebastianBergmann\CodeCoverage\StaticAnalysis\ParsingFileAnalyser; +use SebastianBergmann\CodeUnitReverseLookup\Wizard; + +/** + * Provides collection functionality for PHP code coverage information. + */ +final class CodeCoverage +{ + private const UNCOVERED_FILES = 'UNCOVERED_FILES'; + + /** + * @var Driver + */ + private $driver; + + /** + * @var Filter + */ + private $filter; + + /** + * @var Wizard + */ + private $wizard; + + /** + * @var bool + */ + private $checkForUnintentionallyCoveredCode = false; + + /** + * @var bool + */ + private $includeUncoveredFiles = true; + + /** + * @var bool + */ + private $processUncoveredFiles = false; + + /** + * @var bool + */ + private $ignoreDeprecatedCode = false; + + /** + * @var null|PhptTestCase|string|TestCase + */ + private $currentId; + + /** + * Code coverage data. + * + * @var ProcessedCodeCoverageData + */ + private $data; + + /** + * @var bool + */ + private $useAnnotationsForIgnoringCode = true; + + /** + * Test data. + * + * @var array + */ + private $tests = []; + + /** + * @psalm-var list<class-string> + */ + private $parentClassesExcludedFromUnintentionallyCoveredCodeCheck = []; + + /** + * @var ?FileAnalyser + */ + private $analyser; + + /** + * @var ?string + */ + private $cacheDirectory; + + public function __construct(Driver $driver, Filter $filter) + { + $this->driver = $driver; + $this->filter = $filter; + $this->data = new ProcessedCodeCoverageData; + $this->wizard = new Wizard; + } + + /** + * Returns the code coverage information as a graph of node objects. + */ + public function getReport(): Directory + { + return (new Builder($this->analyser()))->build($this); + } + + /** + * Clears collected code coverage data. + */ + public function clear(): void + { + $this->currentId = null; + $this->data = new ProcessedCodeCoverageData; + $this->tests = []; + } + + /** + * Returns the filter object used. + */ + public function filter(): Filter + { + return $this->filter; + } + + /** + * Returns the collected code coverage data. + */ + public function getData(bool $raw = false): ProcessedCodeCoverageData + { + if (!$raw) { + if ($this->processUncoveredFiles) { + $this->processUncoveredFilesFromFilter(); + } elseif ($this->includeUncoveredFiles) { + $this->addUncoveredFilesFromFilter(); + } + } + + return $this->data; + } + + /** + * Sets the coverage data. + */ + public function setData(ProcessedCodeCoverageData $data): void + { + $this->data = $data; + } + + /** + * Returns the test data. + */ + public function getTests(): array + { + return $this->tests; + } + + /** + * Sets the test data. + */ + public function setTests(array $tests): void + { + $this->tests = $tests; + } + + /** + * Start collection of code coverage information. + * + * @param PhptTestCase|string|TestCase $id + */ + public function start($id, bool $clear = false): void + { + if ($clear) { + $this->clear(); + } + + $this->currentId = $id; + + $this->driver->start(); + } + + /** + * Stop collection of code coverage information. + * + * @param array|false $linesToBeCovered + */ + public function stop(bool $append = true, $linesToBeCovered = [], array $linesToBeUsed = []): RawCodeCoverageData + { + if (!is_array($linesToBeCovered) && $linesToBeCovered !== false) { + throw new InvalidArgumentException( + '$linesToBeCovered must be an array or false' + ); + } + + $data = $this->driver->stop(); + $this->append($data, null, $append, $linesToBeCovered, $linesToBeUsed); + + $this->currentId = null; + + return $data; + } + + /** + * Appends code coverage data. + * + * @param PhptTestCase|string|TestCase $id + * @param array|false $linesToBeCovered + * + * @throws ReflectionException + * @throws TestIdMissingException + * @throws UnintentionallyCoveredCodeException + */ + public function append(RawCodeCoverageData $rawData, $id = null, bool $append = true, $linesToBeCovered = [], array $linesToBeUsed = []): void + { + if ($id === null) { + $id = $this->currentId; + } + + if ($id === null) { + throw new TestIdMissingException; + } + + $this->applyFilter($rawData); + + $this->applyExecutableLinesFilter($rawData); + + if ($this->useAnnotationsForIgnoringCode) { + $this->applyIgnoredLinesFilter($rawData); + } + + $this->data->initializeUnseenData($rawData); + + if (!$append) { + return; + } + + if ($id !== self::UNCOVERED_FILES) { + $this->applyCoversAnnotationFilter( + $rawData, + $linesToBeCovered, + $linesToBeUsed + ); + + if (empty($rawData->lineCoverage())) { + return; + } + + $size = 'unknown'; + $status = -1; + $fromTestcase = false; + + if ($id instanceof TestCase) { + $fromTestcase = true; + $_size = $id->getSize(); + + if ($_size === Test::SMALL) { + $size = 'small'; + } elseif ($_size === Test::MEDIUM) { + $size = 'medium'; + } elseif ($_size === Test::LARGE) { + $size = 'large'; + } + + $status = $id->getStatus(); + $id = get_class($id) . '::' . $id->getName(); + } elseif ($id instanceof PhptTestCase) { + $fromTestcase = true; + $size = 'large'; + $id = $id->getName(); + } + + $this->tests[$id] = ['size' => $size, 'status' => $status, 'fromTestcase' => $fromTestcase]; + + $this->data->markCodeAsExecutedByTestCase($id, $rawData); + } + } + + /** + * Merges the data from another instance. + */ + public function merge(self $that): void + { + $this->filter->includeFiles( + $that->filter()->files() + ); + + $this->data->merge($that->data); + + $this->tests = array_merge($this->tests, $that->getTests()); + } + + public function enableCheckForUnintentionallyCoveredCode(): void + { + $this->checkForUnintentionallyCoveredCode = true; + } + + public function disableCheckForUnintentionallyCoveredCode(): void + { + $this->checkForUnintentionallyCoveredCode = false; + } + + public function includeUncoveredFiles(): void + { + $this->includeUncoveredFiles = true; + } + + public function excludeUncoveredFiles(): void + { + $this->includeUncoveredFiles = false; + } + + public function processUncoveredFiles(): void + { + $this->processUncoveredFiles = true; + } + + public function doNotProcessUncoveredFiles(): void + { + $this->processUncoveredFiles = false; + } + + public function enableAnnotationsForIgnoringCode(): void + { + $this->useAnnotationsForIgnoringCode = true; + } + + public function disableAnnotationsForIgnoringCode(): void + { + $this->useAnnotationsForIgnoringCode = false; + } + + public function ignoreDeprecatedCode(): void + { + $this->ignoreDeprecatedCode = true; + } + + public function doNotIgnoreDeprecatedCode(): void + { + $this->ignoreDeprecatedCode = false; + } + + /** + * @psalm-assert-if-true !null $this->cacheDirectory + */ + public function cachesStaticAnalysis(): bool + { + return $this->cacheDirectory !== null; + } + + public function cacheStaticAnalysis(string $directory): void + { + $this->cacheDirectory = $directory; + } + + public function doNotCacheStaticAnalysis(): void + { + $this->cacheDirectory = null; + } + + /** + * @throws StaticAnalysisCacheNotConfiguredException + */ + public function cacheDirectory(): string + { + if (!$this->cachesStaticAnalysis()) { + throw new StaticAnalysisCacheNotConfiguredException( + 'The static analysis cache is not configured' + ); + } + + return $this->cacheDirectory; + } + + /** + * @psalm-param class-string $className + */ + public function excludeSubclassesOfThisClassFromUnintentionallyCoveredCodeCheck(string $className): void + { + $this->parentClassesExcludedFromUnintentionallyCoveredCodeCheck[] = $className; + } + + public function enableBranchAndPathCoverage(): void + { + $this->driver->enableBranchAndPathCoverage(); + } + + public function disableBranchAndPathCoverage(): void + { + $this->driver->disableBranchAndPathCoverage(); + } + + public function collectsBranchAndPathCoverage(): bool + { + return $this->driver->collectsBranchAndPathCoverage(); + } + + public function detectsDeadCode(): bool + { + return $this->driver->detectsDeadCode(); + } + + /** + * Applies the @covers annotation filtering. + * + * @param array|false $linesToBeCovered + * + * @throws ReflectionException + * @throws UnintentionallyCoveredCodeException + */ + private function applyCoversAnnotationFilter(RawCodeCoverageData $rawData, $linesToBeCovered, array $linesToBeUsed): void + { + if ($linesToBeCovered === false) { + $rawData->clear(); + + return; + } + + if (empty($linesToBeCovered)) { + return; + } + + if ($this->checkForUnintentionallyCoveredCode && + (!$this->currentId instanceof TestCase || + (!$this->currentId->isMedium() && !$this->currentId->isLarge()))) { + $this->performUnintentionallyCoveredCodeCheck($rawData, $linesToBeCovered, $linesToBeUsed); + } + + $rawLineData = $rawData->lineCoverage(); + $filesWithNoCoverage = array_diff_key($rawLineData, $linesToBeCovered); + + foreach (array_keys($filesWithNoCoverage) as $fileWithNoCoverage) { + $rawData->removeCoverageDataForFile($fileWithNoCoverage); + } + + if (is_array($linesToBeCovered)) { + foreach ($linesToBeCovered as $fileToBeCovered => $includedLines) { + $rawData->keepLineCoverageDataOnlyForLines($fileToBeCovered, $includedLines); + $rawData->keepFunctionCoverageDataOnlyForLines($fileToBeCovered, $includedLines); + } + } + } + + private function applyFilter(RawCodeCoverageData $data): void + { + if ($this->filter->isEmpty()) { + return; + } + + foreach (array_keys($data->lineCoverage()) as $filename) { + if ($this->filter->isExcluded($filename)) { + $data->removeCoverageDataForFile($filename); + } + } + } + + private function applyExecutableLinesFilter(RawCodeCoverageData $data): void + { + foreach (array_keys($data->lineCoverage()) as $filename) { + if (!$this->filter->isFile($filename)) { + continue; + } + + $linesToBranchMap = $this->analyser()->executableLinesIn($filename); + + $data->keepLineCoverageDataOnlyForLines( + $filename, + array_keys($linesToBranchMap) + ); + + $data->markExecutableLineByBranch( + $filename, + $linesToBranchMap + ); + } + } + + private function applyIgnoredLinesFilter(RawCodeCoverageData $data): void + { + foreach (array_keys($data->lineCoverage()) as $filename) { + if (!$this->filter->isFile($filename)) { + continue; + } + + $data->removeCoverageDataForLines( + $filename, + $this->analyser()->ignoredLinesFor($filename) + ); + } + } + + /** + * @throws UnintentionallyCoveredCodeException + */ + private function addUncoveredFilesFromFilter(): void + { + $uncoveredFiles = array_diff( + $this->filter->files(), + $this->data->coveredFiles() + ); + + foreach ($uncoveredFiles as $uncoveredFile) { + if ($this->filter->isFile($uncoveredFile)) { + $this->append( + RawCodeCoverageData::fromUncoveredFile( + $uncoveredFile, + $this->analyser() + ), + self::UNCOVERED_FILES + ); + } + } + } + + /** + * @throws UnintentionallyCoveredCodeException + */ + private function processUncoveredFilesFromFilter(): void + { + $uncoveredFiles = array_diff( + $this->filter->files(), + $this->data->coveredFiles() + ); + + $this->driver->start(); + + foreach ($uncoveredFiles as $uncoveredFile) { + if ($this->filter->isFile($uncoveredFile)) { + include_once $uncoveredFile; + } + } + + $this->append($this->driver->stop(), self::UNCOVERED_FILES); + } + + /** + * @throws ReflectionException + * @throws UnintentionallyCoveredCodeException + */ + private function performUnintentionallyCoveredCodeCheck(RawCodeCoverageData $data, array $linesToBeCovered, array $linesToBeUsed): void + { + $allowedLines = $this->getAllowedLines( + $linesToBeCovered, + $linesToBeUsed + ); + + $unintentionallyCoveredUnits = []; + + foreach ($data->lineCoverage() as $file => $_data) { + foreach ($_data as $line => $flag) { + if ($flag === 1 && !isset($allowedLines[$file][$line])) { + $unintentionallyCoveredUnits[] = $this->wizard->lookup($file, $line); + } + } + } + + $unintentionallyCoveredUnits = $this->processUnintentionallyCoveredUnits($unintentionallyCoveredUnits); + + if (!empty($unintentionallyCoveredUnits)) { + throw new UnintentionallyCoveredCodeException( + $unintentionallyCoveredUnits + ); + } + } + + private function getAllowedLines(array $linesToBeCovered, array $linesToBeUsed): array + { + $allowedLines = []; + + foreach (array_keys($linesToBeCovered) as $file) { + if (!isset($allowedLines[$file])) { + $allowedLines[$file] = []; + } + + $allowedLines[$file] = array_merge( + $allowedLines[$file], + $linesToBeCovered[$file] + ); + } + + foreach (array_keys($linesToBeUsed) as $file) { + if (!isset($allowedLines[$file])) { + $allowedLines[$file] = []; + } + + $allowedLines[$file] = array_merge( + $allowedLines[$file], + $linesToBeUsed[$file] + ); + } + + foreach (array_keys($allowedLines) as $file) { + $allowedLines[$file] = array_flip( + array_unique($allowedLines[$file]) + ); + } + + return $allowedLines; + } + + /** + * @throws ReflectionException + */ + private function processUnintentionallyCoveredUnits(array $unintentionallyCoveredUnits): array + { + $unintentionallyCoveredUnits = array_unique($unintentionallyCoveredUnits); + sort($unintentionallyCoveredUnits); + + foreach (array_keys($unintentionallyCoveredUnits) as $k => $v) { + $unit = explode('::', $unintentionallyCoveredUnits[$k]); + + if (count($unit) !== 2) { + continue; + } + + try { + $class = new ReflectionClass($unit[0]); + + foreach ($this->parentClassesExcludedFromUnintentionallyCoveredCodeCheck as $parentClass) { + if ($class->isSubclassOf($parentClass)) { + unset($unintentionallyCoveredUnits[$k]); + + break; + } + } + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + } + + return array_values($unintentionallyCoveredUnits); + } + + private function analyser(): FileAnalyser + { + if ($this->analyser !== null) { + return $this->analyser; + } + + $this->analyser = new ParsingFileAnalyser( + $this->useAnnotationsForIgnoringCode, + $this->ignoreDeprecatedCode + ); + + if ($this->cachesStaticAnalysis()) { + $this->analyser = new CachingFileAnalyser( + $this->cacheDirectory, + $this->analyser + ); + } + + return $this->analyser; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Driver/Driver.php b/vendor/phpunit/php-code-coverage/src/Driver/Driver.php new file mode 100644 index 00000000..dc2de68f --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Driver/Driver.php @@ -0,0 +1,167 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use function sprintf; +use SebastianBergmann\CodeCoverage\BranchAndPathCoverageNotSupportedException; +use SebastianBergmann\CodeCoverage\DeadCodeDetectionNotSupportedException; +use SebastianBergmann\CodeCoverage\Filter; +use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverAvailableException; +use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverWithPathCoverageSupportAvailableException; +use SebastianBergmann\CodeCoverage\RawCodeCoverageData; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +abstract class Driver +{ + /** + * @var int + * + * @see http://xdebug.org/docs/code_coverage + */ + public const LINE_NOT_EXECUTABLE = -2; + + /** + * @var int + * + * @see http://xdebug.org/docs/code_coverage + */ + public const LINE_NOT_EXECUTED = -1; + + /** + * @var int + * + * @see http://xdebug.org/docs/code_coverage + */ + public const LINE_EXECUTED = 1; + + /** + * @var int + * + * @see http://xdebug.org/docs/code_coverage + */ + public const BRANCH_NOT_HIT = 0; + + /** + * @var int + * + * @see http://xdebug.org/docs/code_coverage + */ + public const BRANCH_HIT = 1; + + /** + * @var bool + */ + private $collectBranchAndPathCoverage = false; + + /** + * @var bool + */ + private $detectDeadCode = false; + + /** + * @throws NoCodeCoverageDriverAvailableException + * @throws PcovNotAvailableException + * @throws PhpdbgNotAvailableException + * @throws Xdebug2NotEnabledException + * @throws Xdebug3NotEnabledException + * @throws XdebugNotAvailableException + * + * @deprecated Use DriverSelector::forLineCoverage() instead + */ + public static function forLineCoverage(Filter $filter): self + { + return (new Selector)->forLineCoverage($filter); + } + + /** + * @throws NoCodeCoverageDriverWithPathCoverageSupportAvailableException + * @throws Xdebug2NotEnabledException + * @throws Xdebug3NotEnabledException + * @throws XdebugNotAvailableException + * + * @deprecated Use DriverSelector::forLineAndPathCoverage() instead + */ + public static function forLineAndPathCoverage(Filter $filter): self + { + return (new Selector)->forLineAndPathCoverage($filter); + } + + public function canCollectBranchAndPathCoverage(): bool + { + return false; + } + + public function collectsBranchAndPathCoverage(): bool + { + return $this->collectBranchAndPathCoverage; + } + + /** + * @throws BranchAndPathCoverageNotSupportedException + */ + public function enableBranchAndPathCoverage(): void + { + if (!$this->canCollectBranchAndPathCoverage()) { + throw new BranchAndPathCoverageNotSupportedException( + sprintf( + '%s does not support branch and path coverage', + $this->nameAndVersion() + ) + ); + } + + $this->collectBranchAndPathCoverage = true; + } + + public function disableBranchAndPathCoverage(): void + { + $this->collectBranchAndPathCoverage = false; + } + + public function canDetectDeadCode(): bool + { + return false; + } + + public function detectsDeadCode(): bool + { + return $this->detectDeadCode; + } + + /** + * @throws DeadCodeDetectionNotSupportedException + */ + public function enableDeadCodeDetection(): void + { + if (!$this->canDetectDeadCode()) { + throw new DeadCodeDetectionNotSupportedException( + sprintf( + '%s does not support dead code detection', + $this->nameAndVersion() + ) + ); + } + + $this->detectDeadCode = true; + } + + public function disableDeadCodeDetection(): void + { + $this->detectDeadCode = false; + } + + abstract public function nameAndVersion(): string; + + abstract public function start(): void; + + abstract public function stop(): RawCodeCoverageData; +} diff --git a/vendor/phpunit/php-code-coverage/src/Driver/PcovDriver.php b/vendor/phpunit/php-code-coverage/src/Driver/PcovDriver.php new file mode 100644 index 00000000..c30b30c4 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Driver/PcovDriver.php @@ -0,0 +1,75 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use const pcov\inclusive; +use function array_intersect; +use function extension_loaded; +use function pcov\clear; +use function pcov\collect; +use function pcov\start; +use function pcov\stop; +use function pcov\waiting; +use function phpversion; +use SebastianBergmann\CodeCoverage\Filter; +use SebastianBergmann\CodeCoverage\RawCodeCoverageData; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class PcovDriver extends Driver +{ + /** + * @var Filter + */ + private $filter; + + /** + * @throws PcovNotAvailableException + */ + public function __construct(Filter $filter) + { + if (!extension_loaded('pcov')) { + throw new PcovNotAvailableException; + } + + $this->filter = $filter; + } + + public function start(): void + { + start(); + } + + public function stop(): RawCodeCoverageData + { + stop(); + + $filesToCollectCoverageFor = waiting(); + $collected = []; + + if ($filesToCollectCoverageFor) { + if (!$this->filter->isEmpty()) { + $filesToCollectCoverageFor = array_intersect($filesToCollectCoverageFor, $this->filter->files()); + } + + $collected = collect(inclusive, $filesToCollectCoverageFor); + + clear(); + } + + return RawCodeCoverageData::fromXdebugWithoutPathCoverage($collected); + } + + public function nameAndVersion(): string + { + return 'PCOV ' . phpversion('pcov'); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Driver/PhpdbgDriver.php b/vendor/phpunit/php-code-coverage/src/Driver/PhpdbgDriver.php new file mode 100644 index 00000000..7ee13b00 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Driver/PhpdbgDriver.php @@ -0,0 +1,93 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use const PHP_SAPI; +use const PHP_VERSION; +use function array_diff; +use function array_keys; +use function array_merge; +use function get_included_files; +use function phpdbg_end_oplog; +use function phpdbg_get_executable; +use function phpdbg_start_oplog; +use SebastianBergmann\CodeCoverage\RawCodeCoverageData; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class PhpdbgDriver extends Driver +{ + /** + * @throws PhpdbgNotAvailableException + */ + public function __construct() + { + if (PHP_SAPI !== 'phpdbg') { + throw new PhpdbgNotAvailableException; + } + } + + public function start(): void + { + phpdbg_start_oplog(); + } + + public function stop(): RawCodeCoverageData + { + static $fetchedLines = []; + + $dbgData = phpdbg_end_oplog(); + + if ($fetchedLines === []) { + $sourceLines = phpdbg_get_executable(); + } else { + $newFiles = array_diff(get_included_files(), array_keys($fetchedLines)); + + $sourceLines = []; + + if ($newFiles) { + $sourceLines = phpdbg_get_executable(['files' => $newFiles]); + } + } + + foreach ($sourceLines as $file => $lines) { + foreach ($lines as $lineNo => $numExecuted) { + $sourceLines[$file][$lineNo] = self::LINE_NOT_EXECUTED; + } + } + + $fetchedLines = array_merge($fetchedLines, $sourceLines); + + return RawCodeCoverageData::fromXdebugWithoutPathCoverage( + $this->detectExecutedLines($fetchedLines, $dbgData) + ); + } + + public function nameAndVersion(): string + { + return 'PHPDBG ' . PHP_VERSION; + } + + private function detectExecutedLines(array $sourceLines, array $dbgData): array + { + foreach ($dbgData as $file => $coveredLines) { + foreach ($coveredLines as $lineNo => $numExecuted) { + // phpdbg also reports $lineNo=0 when e.g. exceptions get thrown. + // make sure we only mark lines executed which are actually executable. + if (isset($sourceLines[$file][$lineNo])) { + $sourceLines[$file][$lineNo] = self::LINE_EXECUTED; + } + } + } + + return $sourceLines; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Driver/Selector.php b/vendor/phpunit/php-code-coverage/src/Driver/Selector.php new file mode 100644 index 00000000..936ee898 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Driver/Selector.php @@ -0,0 +1,79 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use function phpversion; +use function version_compare; +use SebastianBergmann\CodeCoverage\Filter; +use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverAvailableException; +use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverWithPathCoverageSupportAvailableException; +use SebastianBergmann\Environment\Runtime; + +final class Selector +{ + /** + * @throws NoCodeCoverageDriverAvailableException + * @throws PcovNotAvailableException + * @throws PhpdbgNotAvailableException + * @throws Xdebug2NotEnabledException + * @throws Xdebug3NotEnabledException + * @throws XdebugNotAvailableException + */ + public function forLineCoverage(Filter $filter): Driver + { + $runtime = new Runtime; + + if ($runtime->hasPHPDBGCodeCoverage()) { + return new PhpdbgDriver; + } + + if ($runtime->hasPCOV()) { + return new PcovDriver($filter); + } + + if ($runtime->hasXdebug()) { + if (version_compare(phpversion('xdebug'), '3', '>=')) { + $driver = new Xdebug3Driver($filter); + } else { + $driver = new Xdebug2Driver($filter); + } + + $driver->enableDeadCodeDetection(); + + return $driver; + } + + throw new NoCodeCoverageDriverAvailableException; + } + + /** + * @throws NoCodeCoverageDriverWithPathCoverageSupportAvailableException + * @throws Xdebug2NotEnabledException + * @throws Xdebug3NotEnabledException + * @throws XdebugNotAvailableException + */ + public function forLineAndPathCoverage(Filter $filter): Driver + { + if ((new Runtime)->hasXdebug()) { + if (version_compare(phpversion('xdebug'), '3', '>=')) { + $driver = new Xdebug3Driver($filter); + } else { + $driver = new Xdebug2Driver($filter); + } + + $driver->enableDeadCodeDetection(); + $driver->enableBranchAndPathCoverage(); + + return $driver; + } + + throw new NoCodeCoverageDriverWithPathCoverageSupportAvailableException; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Driver/Xdebug2Driver.php b/vendor/phpunit/php-code-coverage/src/Driver/Xdebug2Driver.php new file mode 100644 index 00000000..74cbbfbc --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Driver/Xdebug2Driver.php @@ -0,0 +1,128 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use const XDEBUG_CC_BRANCH_CHECK; +use const XDEBUG_CC_DEAD_CODE; +use const XDEBUG_CC_UNUSED; +use const XDEBUG_FILTER_CODE_COVERAGE; +use const XDEBUG_PATH_INCLUDE; +use const XDEBUG_PATH_WHITELIST; +use function defined; +use function extension_loaded; +use function ini_get; +use function phpversion; +use function sprintf; +use function version_compare; +use function xdebug_get_code_coverage; +use function xdebug_set_filter; +use function xdebug_start_code_coverage; +use function xdebug_stop_code_coverage; +use SebastianBergmann\CodeCoverage\Filter; +use SebastianBergmann\CodeCoverage\RawCodeCoverageData; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Xdebug2Driver extends Driver +{ + /** + * @var bool + */ + private $pathCoverageIsMixedCoverage; + + /** + * @throws WrongXdebugVersionException + * @throws Xdebug2NotEnabledException + * @throws XdebugNotAvailableException + */ + public function __construct(Filter $filter) + { + if (!extension_loaded('xdebug')) { + throw new XdebugNotAvailableException; + } + + if (version_compare(phpversion('xdebug'), '3', '>=')) { + throw new WrongXdebugVersionException( + sprintf( + 'This driver requires Xdebug 2 but version %s is loaded', + phpversion('xdebug') + ) + ); + } + + if (!ini_get('xdebug.coverage_enable')) { + throw new Xdebug2NotEnabledException; + } + + if (!$filter->isEmpty()) { + if (defined('XDEBUG_PATH_WHITELIST')) { + $listType = XDEBUG_PATH_WHITELIST; + } else { + $listType = XDEBUG_PATH_INCLUDE; + } + + xdebug_set_filter( + XDEBUG_FILTER_CODE_COVERAGE, + $listType, + $filter->files() + ); + } + + $this->pathCoverageIsMixedCoverage = version_compare(phpversion('xdebug'), '2.9.6', '<'); + } + + public function canCollectBranchAndPathCoverage(): bool + { + return true; + } + + public function canDetectDeadCode(): bool + { + return true; + } + + public function start(): void + { + $flags = XDEBUG_CC_UNUSED; + + if ($this->detectsDeadCode() || $this->collectsBranchAndPathCoverage()) { + $flags |= XDEBUG_CC_DEAD_CODE; + } + + if ($this->collectsBranchAndPathCoverage()) { + $flags |= XDEBUG_CC_BRANCH_CHECK; + } + + xdebug_start_code_coverage($flags); + } + + public function stop(): RawCodeCoverageData + { + $data = xdebug_get_code_coverage(); + + xdebug_stop_code_coverage(); + + if ($this->collectsBranchAndPathCoverage()) { + if ($this->pathCoverageIsMixedCoverage) { + return RawCodeCoverageData::fromXdebugWithMixedCoverage($data); + } + + return RawCodeCoverageData::fromXdebugWithPathCoverage($data); + } + + return RawCodeCoverageData::fromXdebugWithoutPathCoverage($data); + } + + public function nameAndVersion(): string + { + return 'Xdebug ' . phpversion('xdebug'); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Driver/Xdebug3Driver.php b/vendor/phpunit/php-code-coverage/src/Driver/Xdebug3Driver.php new file mode 100644 index 00000000..b85db403 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Driver/Xdebug3Driver.php @@ -0,0 +1,119 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use const XDEBUG_CC_BRANCH_CHECK; +use const XDEBUG_CC_DEAD_CODE; +use const XDEBUG_CC_UNUSED; +use const XDEBUG_FILTER_CODE_COVERAGE; +use const XDEBUG_PATH_INCLUDE; +use function explode; +use function extension_loaded; +use function getenv; +use function in_array; +use function ini_get; +use function phpversion; +use function sprintf; +use function version_compare; +use function xdebug_get_code_coverage; +use function xdebug_set_filter; +use function xdebug_start_code_coverage; +use function xdebug_stop_code_coverage; +use SebastianBergmann\CodeCoverage\Filter; +use SebastianBergmann\CodeCoverage\RawCodeCoverageData; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Xdebug3Driver extends Driver +{ + /** + * @throws WrongXdebugVersionException + * @throws Xdebug3NotEnabledException + * @throws XdebugNotAvailableException + */ + public function __construct(Filter $filter) + { + if (!extension_loaded('xdebug')) { + throw new XdebugNotAvailableException; + } + + if (version_compare(phpversion('xdebug'), '3', '<')) { + throw new WrongXdebugVersionException( + sprintf( + 'This driver requires Xdebug 3 but version %s is loaded', + phpversion('xdebug') + ) + ); + } + + $mode = getenv('XDEBUG_MODE'); + + if ($mode === false || $mode === '') { + $mode = ini_get('xdebug.mode'); + } + + if ($mode === false || + !in_array('coverage', explode(',', $mode), true)) { + throw new Xdebug3NotEnabledException; + } + + if (!$filter->isEmpty()) { + xdebug_set_filter( + XDEBUG_FILTER_CODE_COVERAGE, + XDEBUG_PATH_INCLUDE, + $filter->files() + ); + } + } + + public function canCollectBranchAndPathCoverage(): bool + { + return true; + } + + public function canDetectDeadCode(): bool + { + return true; + } + + public function start(): void + { + $flags = XDEBUG_CC_UNUSED; + + if ($this->detectsDeadCode() || $this->collectsBranchAndPathCoverage()) { + $flags |= XDEBUG_CC_DEAD_CODE; + } + + if ($this->collectsBranchAndPathCoverage()) { + $flags |= XDEBUG_CC_BRANCH_CHECK; + } + + xdebug_start_code_coverage($flags); + } + + public function stop(): RawCodeCoverageData + { + $data = xdebug_get_code_coverage(); + + xdebug_stop_code_coverage(); + + if ($this->collectsBranchAndPathCoverage()) { + return RawCodeCoverageData::fromXdebugWithPathCoverage($data); + } + + return RawCodeCoverageData::fromXdebugWithoutPathCoverage($data); + } + + public function nameAndVersion(): string + { + return 'Xdebug ' . phpversion('xdebug'); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php b/vendor/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php new file mode 100644 index 00000000..ab208919 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php @@ -0,0 +1,16 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class BranchAndPathCoverageNotSupportedException extends RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php b/vendor/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php new file mode 100644 index 00000000..d3600648 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php @@ -0,0 +1,16 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class DeadCodeDetectionNotSupportedException extends RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php b/vendor/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php new file mode 100644 index 00000000..fdd9bfdf --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php @@ -0,0 +1,17 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Util; + +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class DirectoryCouldNotBeCreatedException extends RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/Exception.php b/vendor/phpunit/php-code-coverage/src/Exception/Exception.php new file mode 100644 index 00000000..28dc48b8 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/Exception.php @@ -0,0 +1,16 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php b/vendor/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php new file mode 100644 index 00000000..17e4b707 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php @@ -0,0 +1,14 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +final class InvalidArgumentException extends \InvalidArgumentException implements Exception +{ +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php b/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php new file mode 100644 index 00000000..b1494e26 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php @@ -0,0 +1,20 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class NoCodeCoverageDriverAvailableException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('No code coverage driver available'); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php b/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php new file mode 100644 index 00000000..0065b740 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php @@ -0,0 +1,20 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class NoCodeCoverageDriverWithPathCoverageSupportAvailableException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('No code coverage driver with path coverage support available'); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/ParserException.php b/vendor/phpunit/php-code-coverage/src/Exception/ParserException.php new file mode 100644 index 00000000..a907e34e --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/ParserException.php @@ -0,0 +1,16 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class ParserException extends RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php b/vendor/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php new file mode 100644 index 00000000..54bd73f5 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php @@ -0,0 +1,22 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use function sprintf; +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class PathExistsButIsNotDirectoryException extends RuntimeException implements Exception +{ + public function __construct(string $path) + { + parent::__construct(sprintf('"%s" exists but is not a directory', $path)); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php b/vendor/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php new file mode 100644 index 00000000..2f0a66e5 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php @@ -0,0 +1,21 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class PcovNotAvailableException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('The PCOV extension is not available'); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/PhpdbgNotAvailableException.php b/vendor/phpunit/php-code-coverage/src/Exception/PhpdbgNotAvailableException.php new file mode 100644 index 00000000..bfb183d5 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/PhpdbgNotAvailableException.php @@ -0,0 +1,21 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class PhpdbgNotAvailableException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('The PHPDBG SAPI is not available'); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/ReflectionException.php b/vendor/phpunit/php-code-coverage/src/Exception/ReflectionException.php new file mode 100644 index 00000000..78db430b --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/ReflectionException.php @@ -0,0 +1,16 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class ReflectionException extends RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php b/vendor/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php new file mode 100644 index 00000000..0481f161 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php @@ -0,0 +1,20 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class ReportAlreadyFinalizedException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('The code coverage report has already been finalized'); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php b/vendor/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php new file mode 100644 index 00000000..fd58fd6b --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php @@ -0,0 +1,16 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class StaticAnalysisCacheNotConfiguredException extends RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php b/vendor/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php new file mode 100644 index 00000000..4cc3e0c2 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php @@ -0,0 +1,20 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class TestIdMissingException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('Test ID is missing'); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php b/vendor/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php new file mode 100644 index 00000000..cb7a975f --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php @@ -0,0 +1,43 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class UnintentionallyCoveredCodeException extends RuntimeException implements Exception +{ + /** + * @var array + */ + private $unintentionallyCoveredUnits; + + public function __construct(array $unintentionallyCoveredUnits) + { + $this->unintentionallyCoveredUnits = $unintentionallyCoveredUnits; + + parent::__construct($this->toString()); + } + + public function getUnintentionallyCoveredUnits(): array + { + return $this->unintentionallyCoveredUnits; + } + + private function toString(): string + { + $message = ''; + + foreach ($this->unintentionallyCoveredUnits as $unit) { + $message .= '- ' . $unit . "\n"; + } + + return $message; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php b/vendor/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php new file mode 100644 index 00000000..be549e17 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php @@ -0,0 +1,22 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use function sprintf; +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class WriteOperationFailedException extends RuntimeException implements Exception +{ + public function __construct(string $path) + { + parent::__construct(sprintf('Cannot write to "%s"', $path)); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/WrongXdebugVersionException.php b/vendor/phpunit/php-code-coverage/src/Exception/WrongXdebugVersionException.php new file mode 100644 index 00000000..6e8f10a9 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/WrongXdebugVersionException.php @@ -0,0 +1,17 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class WrongXdebugVersionException extends RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/Xdebug2NotEnabledException.php b/vendor/phpunit/php-code-coverage/src/Exception/Xdebug2NotEnabledException.php new file mode 100644 index 00000000..3039e77c --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/Xdebug2NotEnabledException.php @@ -0,0 +1,21 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class Xdebug2NotEnabledException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('xdebug.coverage_enable=On has to be set'); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/Xdebug3NotEnabledException.php b/vendor/phpunit/php-code-coverage/src/Exception/Xdebug3NotEnabledException.php new file mode 100644 index 00000000..5d3b106c --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/Xdebug3NotEnabledException.php @@ -0,0 +1,21 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class Xdebug3NotEnabledException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('XDEBUG_MODE=coverage or xdebug.mode=coverage has to be set'); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php b/vendor/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php new file mode 100644 index 00000000..1622c5a6 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php @@ -0,0 +1,21 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class XdebugNotAvailableException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('The Xdebug extension is not available'); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Exception/XmlException.php b/vendor/phpunit/php-code-coverage/src/Exception/XmlException.php new file mode 100644 index 00000000..31e4623d --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Exception/XmlException.php @@ -0,0 +1,16 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class XmlException extends RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/php-code-coverage/src/Filter.php b/vendor/phpunit/php-code-coverage/src/Filter.php new file mode 100644 index 00000000..5a0a142a --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Filter.php @@ -0,0 +1,118 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use function array_keys; +use function is_file; +use function realpath; +use function strpos; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; + +final class Filter +{ + /** + * @psalm-var array<string,true> + */ + private $files = []; + + /** + * @psalm-var array<string,bool> + */ + private $isFileCache = []; + + public function includeDirectory(string $directory, string $suffix = '.php', string $prefix = ''): void + { + foreach ((new FileIteratorFacade)->getFilesAsArray($directory, $suffix, $prefix) as $file) { + $this->includeFile($file); + } + } + + /** + * @psalm-param list<string> $files + */ + public function includeFiles(array $filenames): void + { + foreach ($filenames as $filename) { + $this->includeFile($filename); + } + } + + public function includeFile(string $filename): void + { + $filename = realpath($filename); + + if (!$filename) { + return; + } + + $this->files[$filename] = true; + } + + public function excludeDirectory(string $directory, string $suffix = '.php', string $prefix = ''): void + { + foreach ((new FileIteratorFacade)->getFilesAsArray($directory, $suffix, $prefix) as $file) { + $this->excludeFile($file); + } + } + + public function excludeFile(string $filename): void + { + $filename = realpath($filename); + + if (!$filename || !isset($this->files[$filename])) { + return; + } + + unset($this->files[$filename]); + } + + public function isFile(string $filename): bool + { + if (isset($this->isFileCache[$filename])) { + return $this->isFileCache[$filename]; + } + + if ($filename === '-' || + strpos($filename, 'vfs://') === 0 || + strpos($filename, 'xdebug://debug-eval') !== false || + strpos($filename, 'eval()\'d code') !== false || + strpos($filename, 'runtime-created function') !== false || + strpos($filename, 'runkit created function') !== false || + strpos($filename, 'assert code') !== false || + strpos($filename, 'regexp code') !== false || + strpos($filename, 'Standard input code') !== false) { + $isFile = false; + } else { + $isFile = is_file($filename); + } + + $this->isFileCache[$filename] = $isFile; + + return $isFile; + } + + public function isExcluded(string $filename): bool + { + return !isset($this->files[$filename]) || !$this->isFile($filename); + } + + /** + * @psalm-return list<string> + */ + public function files(): array + { + return array_keys($this->files); + } + + public function isEmpty(): bool + { + return empty($this->files); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Node/AbstractNode.php b/vendor/phpunit/php-code-coverage/src/Node/AbstractNode.php new file mode 100644 index 00000000..60d6391d --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Node/AbstractNode.php @@ -0,0 +1,253 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Node; + +use const DIRECTORY_SEPARATOR; +use function array_merge; +use function str_replace; +use function substr; +use Countable; +use SebastianBergmann\CodeCoverage\Util\Percentage; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +abstract class AbstractNode implements Countable +{ + /** + * @var string + */ + private $name; + + /** + * @var string + */ + private $pathAsString; + + /** + * @var array + */ + private $pathAsArray; + + /** + * @var AbstractNode + */ + private $parent; + + /** + * @var string + */ + private $id; + + public function __construct(string $name, self $parent = null) + { + if (substr($name, -1) === DIRECTORY_SEPARATOR) { + $name = substr($name, 0, -1); + } + + $this->name = $name; + $this->parent = $parent; + } + + public function name(): string + { + return $this->name; + } + + public function id(): string + { + if ($this->id === null) { + $parent = $this->parent(); + + if ($parent === null) { + $this->id = 'index'; + } else { + $parentId = $parent->id(); + + if ($parentId === 'index') { + $this->id = str_replace(':', '_', $this->name); + } else { + $this->id = $parentId . '/' . $this->name; + } + } + } + + return $this->id; + } + + public function pathAsString(): string + { + if ($this->pathAsString === null) { + if ($this->parent === null) { + $this->pathAsString = $this->name; + } else { + $this->pathAsString = $this->parent->pathAsString() . DIRECTORY_SEPARATOR . $this->name; + } + } + + return $this->pathAsString; + } + + public function pathAsArray(): array + { + if ($this->pathAsArray === null) { + if ($this->parent === null) { + $this->pathAsArray = []; + } else { + $this->pathAsArray = $this->parent->pathAsArray(); + } + + $this->pathAsArray[] = $this; + } + + return $this->pathAsArray; + } + + public function parent(): ?self + { + return $this->parent; + } + + public function percentageOfTestedClasses(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfTestedClasses(), + $this->numberOfClasses(), + ); + } + + public function percentageOfTestedTraits(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfTestedTraits(), + $this->numberOfTraits(), + ); + } + + public function percentageOfTestedClassesAndTraits(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfTestedClassesAndTraits(), + $this->numberOfClassesAndTraits(), + ); + } + + public function percentageOfTestedFunctions(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfTestedFunctions(), + $this->numberOfFunctions(), + ); + } + + public function percentageOfTestedMethods(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfTestedMethods(), + $this->numberOfMethods(), + ); + } + + public function percentageOfTestedFunctionsAndMethods(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfTestedFunctionsAndMethods(), + $this->numberOfFunctionsAndMethods(), + ); + } + + public function percentageOfExecutedLines(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfExecutedLines(), + $this->numberOfExecutableLines(), + ); + } + + public function percentageOfExecutedBranches(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfExecutedBranches(), + $this->numberOfExecutableBranches() + ); + } + + public function percentageOfExecutedPaths(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfExecutedPaths(), + $this->numberOfExecutablePaths() + ); + } + + public function numberOfClassesAndTraits(): int + { + return $this->numberOfClasses() + $this->numberOfTraits(); + } + + public function numberOfTestedClassesAndTraits(): int + { + return $this->numberOfTestedClasses() + $this->numberOfTestedTraits(); + } + + public function classesAndTraits(): array + { + return array_merge($this->classes(), $this->traits()); + } + + public function numberOfFunctionsAndMethods(): int + { + return $this->numberOfFunctions() + $this->numberOfMethods(); + } + + public function numberOfTestedFunctionsAndMethods(): int + { + return $this->numberOfTestedFunctions() + $this->numberOfTestedMethods(); + } + + abstract public function classes(): array; + + abstract public function traits(): array; + + abstract public function functions(): array; + + /** + * @psalm-return array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} + */ + abstract public function linesOfCode(): array; + + abstract public function numberOfExecutableLines(): int; + + abstract public function numberOfExecutedLines(): int; + + abstract public function numberOfExecutableBranches(): int; + + abstract public function numberOfExecutedBranches(): int; + + abstract public function numberOfExecutablePaths(): int; + + abstract public function numberOfExecutedPaths(): int; + + abstract public function numberOfClasses(): int; + + abstract public function numberOfTestedClasses(): int; + + abstract public function numberOfTraits(): int; + + abstract public function numberOfTestedTraits(): int; + + abstract public function numberOfMethods(): int; + + abstract public function numberOfTestedMethods(): int; + + abstract public function numberOfFunctions(): int; + + abstract public function numberOfTestedFunctions(): int; +} diff --git a/vendor/phpunit/php-code-coverage/src/Node/Builder.php b/vendor/phpunit/php-code-coverage/src/Node/Builder.php new file mode 100644 index 00000000..6d11c779 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Node/Builder.php @@ -0,0 +1,264 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Node; + +use const DIRECTORY_SEPARATOR; +use function array_shift; +use function basename; +use function count; +use function dirname; +use function explode; +use function implode; +use function is_file; +use function str_replace; +use function strpos; +use function substr; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\ProcessedCodeCoverageData; +use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Builder +{ + /** + * @var FileAnalyser + */ + private $analyser; + + public function __construct(FileAnalyser $analyser) + { + $this->analyser = $analyser; + } + + public function build(CodeCoverage $coverage): Directory + { + $data = clone $coverage->getData(); // clone because path munging is destructive to the original data + $commonPath = $this->reducePaths($data); + $root = new Directory( + $commonPath, + null + ); + + $this->addItems( + $root, + $this->buildDirectoryStructure($data), + $coverage->getTests() + ); + + return $root; + } + + private function addItems(Directory $root, array $items, array $tests): void + { + foreach ($items as $key => $value) { + $key = (string) $key; + + if (substr($key, -2) === '/f') { + $key = substr($key, 0, -2); + $filename = $root->pathAsString() . DIRECTORY_SEPARATOR . $key; + + if (is_file($filename)) { + $root->addFile( + new File( + $key, + $root, + $value['lineCoverage'], + $value['functionCoverage'], + $tests, + $this->analyser->classesIn($filename), + $this->analyser->traitsIn($filename), + $this->analyser->functionsIn($filename), + $this->analyser->linesOfCodeFor($filename) + ) + ); + } + } else { + $child = $root->addDirectory($key); + + $this->addItems($child, $value, $tests); + } + } + } + + /** + * Builds an array representation of the directory structure. + * + * For instance, + * + * <code> + * Array + * ( + * [Money.php] => Array + * ( + * ... + * ) + * + * [MoneyBag.php] => Array + * ( + * ... + * ) + * ) + * </code> + * + * is transformed into + * + * <code> + * Array + * ( + * [.] => Array + * ( + * [Money.php] => Array + * ( + * ... + * ) + * + * [MoneyBag.php] => Array + * ( + * ... + * ) + * ) + * ) + * </code> + */ + private function buildDirectoryStructure(ProcessedCodeCoverageData $data): array + { + $result = []; + + foreach ($data->coveredFiles() as $originalPath) { + $path = explode(DIRECTORY_SEPARATOR, $originalPath); + $pointer = &$result; + $max = count($path); + + for ($i = 0; $i < $max; $i++) { + $type = ''; + + if ($i === ($max - 1)) { + $type = '/f'; + } + + $pointer = &$pointer[$path[$i] . $type]; + } + + $pointer = [ + 'lineCoverage' => $data->lineCoverage()[$originalPath] ?? [], + 'functionCoverage' => $data->functionCoverage()[$originalPath] ?? [], + ]; + } + + return $result; + } + + /** + * Reduces the paths by cutting the longest common start path. + * + * For instance, + * + * <code> + * Array + * ( + * [/home/sb/Money/Money.php] => Array + * ( + * ... + * ) + * + * [/home/sb/Money/MoneyBag.php] => Array + * ( + * ... + * ) + * ) + * </code> + * + * is reduced to + * + * <code> + * Array + * ( + * [Money.php] => Array + * ( + * ... + * ) + * + * [MoneyBag.php] => Array + * ( + * ... + * ) + * ) + * </code> + */ + private function reducePaths(ProcessedCodeCoverageData $coverage): string + { + if (empty($coverage->coveredFiles())) { + return '.'; + } + + $commonPath = ''; + $paths = $coverage->coveredFiles(); + + if (count($paths) === 1) { + $commonPath = dirname($paths[0]) . DIRECTORY_SEPARATOR; + $coverage->renameFile($paths[0], basename($paths[0])); + + return $commonPath; + } + + $max = count($paths); + + for ($i = 0; $i < $max; $i++) { + // strip phar:// prefixes + if (strpos($paths[$i], 'phar://') === 0) { + $paths[$i] = substr($paths[$i], 7); + $paths[$i] = str_replace('/', DIRECTORY_SEPARATOR, $paths[$i]); + } + $paths[$i] = explode(DIRECTORY_SEPARATOR, $paths[$i]); + + if (empty($paths[$i][0])) { + $paths[$i][0] = DIRECTORY_SEPARATOR; + } + } + + $done = false; + $max = count($paths); + + while (!$done) { + for ($i = 0; $i < $max - 1; $i++) { + if (!isset($paths[$i][0]) || + !isset($paths[$i + 1][0]) || + $paths[$i][0] !== $paths[$i + 1][0]) { + $done = true; + + break; + } + } + + if (!$done) { + $commonPath .= $paths[0][0]; + + if ($paths[0][0] !== DIRECTORY_SEPARATOR) { + $commonPath .= DIRECTORY_SEPARATOR; + } + + for ($i = 0; $i < $max; $i++) { + array_shift($paths[$i]); + } + } + } + + $original = $coverage->coveredFiles(); + $max = count($original); + + for ($i = 0; $i < $max; $i++) { + $coverage->renameFile($original[$i], implode(DIRECTORY_SEPARATOR, $paths[$i])); + } + + return substr($commonPath, 0, -1); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Node/CrapIndex.php b/vendor/phpunit/php-code-coverage/src/Node/CrapIndex.php new file mode 100644 index 00000000..30b86b7d --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Node/CrapIndex.php @@ -0,0 +1,50 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Node; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class CrapIndex +{ + /** + * @var int + */ + private $cyclomaticComplexity; + + /** + * @var float + */ + private $codeCoverage; + + public function __construct(int $cyclomaticComplexity, float $codeCoverage) + { + $this->cyclomaticComplexity = $cyclomaticComplexity; + $this->codeCoverage = $codeCoverage; + } + + public function asString(): string + { + if ($this->codeCoverage === 0.0) { + return (string) ($this->cyclomaticComplexity ** 2 + $this->cyclomaticComplexity); + } + + if ($this->codeCoverage >= 95) { + return (string) $this->cyclomaticComplexity; + } + + return sprintf( + '%01.2F', + $this->cyclomaticComplexity ** 2 * (1 - $this->codeCoverage / 100) ** 3 + $this->cyclomaticComplexity + ); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Node/Directory.php b/vendor/phpunit/php-code-coverage/src/Node/Directory.php new file mode 100644 index 00000000..d6ee07e4 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Node/Directory.php @@ -0,0 +1,440 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Node; + +use function array_merge; +use function count; +use IteratorAggregate; +use RecursiveIteratorIterator; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Directory extends AbstractNode implements IteratorAggregate +{ + /** + * @var AbstractNode[] + */ + private $children = []; + + /** + * @var Directory[] + */ + private $directories = []; + + /** + * @var File[] + */ + private $files = []; + + /** + * @var array + */ + private $classes; + + /** + * @var array + */ + private $traits; + + /** + * @var array + */ + private $functions; + + /** + * @psalm-var null|array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} + */ + private $linesOfCode; + + /** + * @var int + */ + private $numFiles = -1; + + /** + * @var int + */ + private $numExecutableLines = -1; + + /** + * @var int + */ + private $numExecutedLines = -1; + + /** + * @var int + */ + private $numExecutableBranches = -1; + + /** + * @var int + */ + private $numExecutedBranches = -1; + + /** + * @var int + */ + private $numExecutablePaths = -1; + + /** + * @var int + */ + private $numExecutedPaths = -1; + + /** + * @var int + */ + private $numClasses = -1; + + /** + * @var int + */ + private $numTestedClasses = -1; + + /** + * @var int + */ + private $numTraits = -1; + + /** + * @var int + */ + private $numTestedTraits = -1; + + /** + * @var int + */ + private $numMethods = -1; + + /** + * @var int + */ + private $numTestedMethods = -1; + + /** + * @var int + */ + private $numFunctions = -1; + + /** + * @var int + */ + private $numTestedFunctions = -1; + + public function count(): int + { + if ($this->numFiles === -1) { + $this->numFiles = 0; + + foreach ($this->children as $child) { + $this->numFiles += count($child); + } + } + + return $this->numFiles; + } + + public function getIterator(): RecursiveIteratorIterator + { + return new RecursiveIteratorIterator( + new Iterator($this), + RecursiveIteratorIterator::SELF_FIRST + ); + } + + public function addDirectory(string $name): self + { + $directory = new self($name, $this); + + $this->children[] = $directory; + $this->directories[] = &$this->children[count($this->children) - 1]; + + return $directory; + } + + public function addFile(File $file): void + { + $this->children[] = $file; + $this->files[] = &$this->children[count($this->children) - 1]; + + $this->numExecutableLines = -1; + $this->numExecutedLines = -1; + } + + public function directories(): array + { + return $this->directories; + } + + public function files(): array + { + return $this->files; + } + + public function children(): array + { + return $this->children; + } + + public function classes(): array + { + if ($this->classes === null) { + $this->classes = []; + + foreach ($this->children as $child) { + $this->classes = array_merge( + $this->classes, + $child->classes() + ); + } + } + + return $this->classes; + } + + public function traits(): array + { + if ($this->traits === null) { + $this->traits = []; + + foreach ($this->children as $child) { + $this->traits = array_merge( + $this->traits, + $child->traits() + ); + } + } + + return $this->traits; + } + + public function functions(): array + { + if ($this->functions === null) { + $this->functions = []; + + foreach ($this->children as $child) { + $this->functions = array_merge( + $this->functions, + $child->functions() + ); + } + } + + return $this->functions; + } + + /** + * @psalm-return array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} + */ + public function linesOfCode(): array + { + if ($this->linesOfCode === null) { + $this->linesOfCode = [ + 'linesOfCode' => 0, + 'commentLinesOfCode' => 0, + 'nonCommentLinesOfCode' => 0, + ]; + + foreach ($this->children as $child) { + $childLinesOfCode = $child->linesOfCode(); + + $this->linesOfCode['linesOfCode'] += $childLinesOfCode['linesOfCode']; + $this->linesOfCode['commentLinesOfCode'] += $childLinesOfCode['commentLinesOfCode']; + $this->linesOfCode['nonCommentLinesOfCode'] += $childLinesOfCode['nonCommentLinesOfCode']; + } + } + + return $this->linesOfCode; + } + + public function numberOfExecutableLines(): int + { + if ($this->numExecutableLines === -1) { + $this->numExecutableLines = 0; + + foreach ($this->children as $child) { + $this->numExecutableLines += $child->numberOfExecutableLines(); + } + } + + return $this->numExecutableLines; + } + + public function numberOfExecutedLines(): int + { + if ($this->numExecutedLines === -1) { + $this->numExecutedLines = 0; + + foreach ($this->children as $child) { + $this->numExecutedLines += $child->numberOfExecutedLines(); + } + } + + return $this->numExecutedLines; + } + + public function numberOfExecutableBranches(): int + { + if ($this->numExecutableBranches === -1) { + $this->numExecutableBranches = 0; + + foreach ($this->children as $child) { + $this->numExecutableBranches += $child->numberOfExecutableBranches(); + } + } + + return $this->numExecutableBranches; + } + + public function numberOfExecutedBranches(): int + { + if ($this->numExecutedBranches === -1) { + $this->numExecutedBranches = 0; + + foreach ($this->children as $child) { + $this->numExecutedBranches += $child->numberOfExecutedBranches(); + } + } + + return $this->numExecutedBranches; + } + + public function numberOfExecutablePaths(): int + { + if ($this->numExecutablePaths === -1) { + $this->numExecutablePaths = 0; + + foreach ($this->children as $child) { + $this->numExecutablePaths += $child->numberOfExecutablePaths(); + } + } + + return $this->numExecutablePaths; + } + + public function numberOfExecutedPaths(): int + { + if ($this->numExecutedPaths === -1) { + $this->numExecutedPaths = 0; + + foreach ($this->children as $child) { + $this->numExecutedPaths += $child->numberOfExecutedPaths(); + } + } + + return $this->numExecutedPaths; + } + + public function numberOfClasses(): int + { + if ($this->numClasses === -1) { + $this->numClasses = 0; + + foreach ($this->children as $child) { + $this->numClasses += $child->numberOfClasses(); + } + } + + return $this->numClasses; + } + + public function numberOfTestedClasses(): int + { + if ($this->numTestedClasses === -1) { + $this->numTestedClasses = 0; + + foreach ($this->children as $child) { + $this->numTestedClasses += $child->numberOfTestedClasses(); + } + } + + return $this->numTestedClasses; + } + + public function numberOfTraits(): int + { + if ($this->numTraits === -1) { + $this->numTraits = 0; + + foreach ($this->children as $child) { + $this->numTraits += $child->numberOfTraits(); + } + } + + return $this->numTraits; + } + + public function numberOfTestedTraits(): int + { + if ($this->numTestedTraits === -1) { + $this->numTestedTraits = 0; + + foreach ($this->children as $child) { + $this->numTestedTraits += $child->numberOfTestedTraits(); + } + } + + return $this->numTestedTraits; + } + + public function numberOfMethods(): int + { + if ($this->numMethods === -1) { + $this->numMethods = 0; + + foreach ($this->children as $child) { + $this->numMethods += $child->numberOfMethods(); + } + } + + return $this->numMethods; + } + + public function numberOfTestedMethods(): int + { + if ($this->numTestedMethods === -1) { + $this->numTestedMethods = 0; + + foreach ($this->children as $child) { + $this->numTestedMethods += $child->numberOfTestedMethods(); + } + } + + return $this->numTestedMethods; + } + + public function numberOfFunctions(): int + { + if ($this->numFunctions === -1) { + $this->numFunctions = 0; + + foreach ($this->children as $child) { + $this->numFunctions += $child->numberOfFunctions(); + } + } + + return $this->numFunctions; + } + + public function numberOfTestedFunctions(): int + { + if ($this->numTestedFunctions === -1) { + $this->numTestedFunctions = 0; + + foreach ($this->children as $child) { + $this->numTestedFunctions += $child->numberOfTestedFunctions(); + } + } + + return $this->numTestedFunctions; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Node/File.php b/vendor/phpunit/php-code-coverage/src/Node/File.php new file mode 100644 index 00000000..af3764e4 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Node/File.php @@ -0,0 +1,651 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Node; + +use function array_filter; +use function count; +use function range; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class File extends AbstractNode +{ + /** + * @var array + */ + private $lineCoverageData; + + /** + * @var array + */ + private $functionCoverageData; + + /** + * @var array + */ + private $testData; + + /** + * @var int + */ + private $numExecutableLines = 0; + + /** + * @var int + */ + private $numExecutedLines = 0; + + /** + * @var int + */ + private $numExecutableBranches = 0; + + /** + * @var int + */ + private $numExecutedBranches = 0; + + /** + * @var int + */ + private $numExecutablePaths = 0; + + /** + * @var int + */ + private $numExecutedPaths = 0; + + /** + * @var array + */ + private $classes = []; + + /** + * @var array + */ + private $traits = []; + + /** + * @var array + */ + private $functions = []; + + /** + * @psalm-var array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} + */ + private $linesOfCode; + + /** + * @var int + */ + private $numClasses; + + /** + * @var int + */ + private $numTestedClasses = 0; + + /** + * @var int + */ + private $numTraits; + + /** + * @var int + */ + private $numTestedTraits = 0; + + /** + * @var int + */ + private $numMethods; + + /** + * @var int + */ + private $numTestedMethods; + + /** + * @var int + */ + private $numTestedFunctions; + + /** + * @var array + */ + private $codeUnitsByLine = []; + + /** + * @psalm-param array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} $linesOfCode + */ + public function __construct(string $name, AbstractNode $parent, array $lineCoverageData, array $functionCoverageData, array $testData, array $classes, array $traits, array $functions, array $linesOfCode) + { + parent::__construct($name, $parent); + + $this->lineCoverageData = $lineCoverageData; + $this->functionCoverageData = $functionCoverageData; + $this->testData = $testData; + $this->linesOfCode = $linesOfCode; + + $this->calculateStatistics($classes, $traits, $functions); + } + + public function count(): int + { + return 1; + } + + public function lineCoverageData(): array + { + return $this->lineCoverageData; + } + + public function functionCoverageData(): array + { + return $this->functionCoverageData; + } + + public function testData(): array + { + return $this->testData; + } + + public function classes(): array + { + return $this->classes; + } + + public function traits(): array + { + return $this->traits; + } + + public function functions(): array + { + return $this->functions; + } + + /** + * @psalm-return array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} + */ + public function linesOfCode(): array + { + return $this->linesOfCode; + } + + public function numberOfExecutableLines(): int + { + return $this->numExecutableLines; + } + + public function numberOfExecutedLines(): int + { + return $this->numExecutedLines; + } + + public function numberOfExecutableBranches(): int + { + return $this->numExecutableBranches; + } + + public function numberOfExecutedBranches(): int + { + return $this->numExecutedBranches; + } + + public function numberOfExecutablePaths(): int + { + return $this->numExecutablePaths; + } + + public function numberOfExecutedPaths(): int + { + return $this->numExecutedPaths; + } + + public function numberOfClasses(): int + { + if ($this->numClasses === null) { + $this->numClasses = 0; + + foreach ($this->classes as $class) { + foreach ($class['methods'] as $method) { + if ($method['executableLines'] > 0) { + $this->numClasses++; + + continue 2; + } + } + } + } + + return $this->numClasses; + } + + public function numberOfTestedClasses(): int + { + return $this->numTestedClasses; + } + + public function numberOfTraits(): int + { + if ($this->numTraits === null) { + $this->numTraits = 0; + + foreach ($this->traits as $trait) { + foreach ($trait['methods'] as $method) { + if ($method['executableLines'] > 0) { + $this->numTraits++; + + continue 2; + } + } + } + } + + return $this->numTraits; + } + + public function numberOfTestedTraits(): int + { + return $this->numTestedTraits; + } + + public function numberOfMethods(): int + { + if ($this->numMethods === null) { + $this->numMethods = 0; + + foreach ($this->classes as $class) { + foreach ($class['methods'] as $method) { + if ($method['executableLines'] > 0) { + $this->numMethods++; + } + } + } + + foreach ($this->traits as $trait) { + foreach ($trait['methods'] as $method) { + if ($method['executableLines'] > 0) { + $this->numMethods++; + } + } + } + } + + return $this->numMethods; + } + + public function numberOfTestedMethods(): int + { + if ($this->numTestedMethods === null) { + $this->numTestedMethods = 0; + + foreach ($this->classes as $class) { + foreach ($class['methods'] as $method) { + if ($method['executableLines'] > 0 && + $method['coverage'] === 100) { + $this->numTestedMethods++; + } + } + } + + foreach ($this->traits as $trait) { + foreach ($trait['methods'] as $method) { + if ($method['executableLines'] > 0 && + $method['coverage'] === 100) { + $this->numTestedMethods++; + } + } + } + } + + return $this->numTestedMethods; + } + + public function numberOfFunctions(): int + { + return count($this->functions); + } + + public function numberOfTestedFunctions(): int + { + if ($this->numTestedFunctions === null) { + $this->numTestedFunctions = 0; + + foreach ($this->functions as $function) { + if ($function['executableLines'] > 0 && + $function['coverage'] === 100) { + $this->numTestedFunctions++; + } + } + } + + return $this->numTestedFunctions; + } + + private function calculateStatistics(array $classes, array $traits, array $functions): void + { + foreach (range(1, $this->linesOfCode['linesOfCode']) as $lineNumber) { + $this->codeUnitsByLine[$lineNumber] = []; + } + + $this->processClasses($classes); + $this->processTraits($traits); + $this->processFunctions($functions); + + foreach (range(1, $this->linesOfCode['linesOfCode']) as $lineNumber) { + if (isset($this->lineCoverageData[$lineNumber])) { + foreach ($this->codeUnitsByLine[$lineNumber] as &$codeUnit) { + $codeUnit['executableLines']++; + } + + unset($codeUnit); + + $this->numExecutableLines++; + + if (count($this->lineCoverageData[$lineNumber]) > 0) { + foreach ($this->codeUnitsByLine[$lineNumber] as &$codeUnit) { + $codeUnit['executedLines']++; + } + + unset($codeUnit); + + $this->numExecutedLines++; + } + } + } + + foreach ($this->traits as &$trait) { + foreach ($trait['methods'] as &$method) { + $methodLineCoverage = $method['executableLines'] ? ($method['executedLines'] / $method['executableLines']) * 100 : 100; + $methodBranchCoverage = $method['executableBranches'] ? ($method['executedBranches'] / $method['executableBranches']) * 100 : 0; + $methodPathCoverage = $method['executablePaths'] ? ($method['executedPaths'] / $method['executablePaths']) * 100 : 0; + + $method['coverage'] = $methodBranchCoverage ?: $methodLineCoverage; + $method['crap'] = (new CrapIndex($method['ccn'], $methodPathCoverage ?: $methodLineCoverage))->asString(); + + $trait['ccn'] += $method['ccn']; + } + + unset($method); + + $traitLineCoverage = $trait['executableLines'] ? ($trait['executedLines'] / $trait['executableLines']) * 100 : 100; + $traitBranchCoverage = $trait['executableBranches'] ? ($trait['executedBranches'] / $trait['executableBranches']) * 100 : 0; + $traitPathCoverage = $trait['executablePaths'] ? ($trait['executedPaths'] / $trait['executablePaths']) * 100 : 0; + + $trait['coverage'] = $traitBranchCoverage ?: $traitLineCoverage; + $trait['crap'] = (new CrapIndex($trait['ccn'], $traitPathCoverage ?: $traitLineCoverage))->asString(); + + if ($trait['executableLines'] > 0 && $trait['coverage'] === 100) { + $this->numTestedClasses++; + } + } + + unset($trait); + + foreach ($this->classes as &$class) { + foreach ($class['methods'] as &$method) { + $methodLineCoverage = $method['executableLines'] ? ($method['executedLines'] / $method['executableLines']) * 100 : 100; + $methodBranchCoverage = $method['executableBranches'] ? ($method['executedBranches'] / $method['executableBranches']) * 100 : 0; + $methodPathCoverage = $method['executablePaths'] ? ($method['executedPaths'] / $method['executablePaths']) * 100 : 0; + + $method['coverage'] = $methodBranchCoverage ?: $methodLineCoverage; + $method['crap'] = (new CrapIndex($method['ccn'], $methodPathCoverage ?: $methodLineCoverage))->asString(); + + $class['ccn'] += $method['ccn']; + } + + unset($method); + + $classLineCoverage = $class['executableLines'] ? ($class['executedLines'] / $class['executableLines']) * 100 : 100; + $classBranchCoverage = $class['executableBranches'] ? ($class['executedBranches'] / $class['executableBranches']) * 100 : 0; + $classPathCoverage = $class['executablePaths'] ? ($class['executedPaths'] / $class['executablePaths']) * 100 : 0; + + $class['coverage'] = $classBranchCoverage ?: $classLineCoverage; + $class['crap'] = (new CrapIndex($class['ccn'], $classPathCoverage ?: $classLineCoverage))->asString(); + + if ($class['executableLines'] > 0 && $class['coverage'] === 100) { + $this->numTestedClasses++; + } + } + + unset($class); + + foreach ($this->functions as &$function) { + $functionLineCoverage = $function['executableLines'] ? ($function['executedLines'] / $function['executableLines']) * 100 : 100; + $functionBranchCoverage = $function['executableBranches'] ? ($function['executedBranches'] / $function['executableBranches']) * 100 : 0; + $functionPathCoverage = $function['executablePaths'] ? ($function['executedPaths'] / $function['executablePaths']) * 100 : 0; + + $function['coverage'] = $functionBranchCoverage ?: $functionLineCoverage; + $function['crap'] = (new CrapIndex($function['ccn'], $functionPathCoverage ?: $functionLineCoverage))->asString(); + + if ($function['coverage'] === 100) { + $this->numTestedFunctions++; + } + } + } + + private function processClasses(array $classes): void + { + $link = $this->id() . '.html#'; + + foreach ($classes as $className => $class) { + $this->classes[$className] = [ + 'className' => $className, + 'namespace' => $class['namespace'], + 'methods' => [], + 'startLine' => $class['startLine'], + 'executableLines' => 0, + 'executedLines' => 0, + 'executableBranches' => 0, + 'executedBranches' => 0, + 'executablePaths' => 0, + 'executedPaths' => 0, + 'ccn' => 0, + 'coverage' => 0, + 'crap' => 0, + 'link' => $link . $class['startLine'], + ]; + + foreach ($class['methods'] as $methodName => $method) { + $methodData = $this->newMethod($className, $methodName, $method, $link); + $this->classes[$className]['methods'][$methodName] = $methodData; + + $this->classes[$className]['executableBranches'] += $methodData['executableBranches']; + $this->classes[$className]['executedBranches'] += $methodData['executedBranches']; + $this->classes[$className]['executablePaths'] += $methodData['executablePaths']; + $this->classes[$className]['executedPaths'] += $methodData['executedPaths']; + + $this->numExecutableBranches += $methodData['executableBranches']; + $this->numExecutedBranches += $methodData['executedBranches']; + $this->numExecutablePaths += $methodData['executablePaths']; + $this->numExecutedPaths += $methodData['executedPaths']; + + foreach (range($method['startLine'], $method['endLine']) as $lineNumber) { + $this->codeUnitsByLine[$lineNumber] = [ + &$this->classes[$className], + &$this->classes[$className]['methods'][$methodName], + ]; + } + } + } + } + + private function processTraits(array $traits): void + { + $link = $this->id() . '.html#'; + + foreach ($traits as $traitName => $trait) { + $this->traits[$traitName] = [ + 'traitName' => $traitName, + 'namespace' => $trait['namespace'], + 'methods' => [], + 'startLine' => $trait['startLine'], + 'executableLines' => 0, + 'executedLines' => 0, + 'executableBranches' => 0, + 'executedBranches' => 0, + 'executablePaths' => 0, + 'executedPaths' => 0, + 'ccn' => 0, + 'coverage' => 0, + 'crap' => 0, + 'link' => $link . $trait['startLine'], + ]; + + foreach ($trait['methods'] as $methodName => $method) { + $methodData = $this->newMethod($traitName, $methodName, $method, $link); + $this->traits[$traitName]['methods'][$methodName] = $methodData; + + $this->traits[$traitName]['executableBranches'] += $methodData['executableBranches']; + $this->traits[$traitName]['executedBranches'] += $methodData['executedBranches']; + $this->traits[$traitName]['executablePaths'] += $methodData['executablePaths']; + $this->traits[$traitName]['executedPaths'] += $methodData['executedPaths']; + + $this->numExecutableBranches += $methodData['executableBranches']; + $this->numExecutedBranches += $methodData['executedBranches']; + $this->numExecutablePaths += $methodData['executablePaths']; + $this->numExecutedPaths += $methodData['executedPaths']; + + foreach (range($method['startLine'], $method['endLine']) as $lineNumber) { + $this->codeUnitsByLine[$lineNumber] = [ + &$this->traits[$traitName], + &$this->traits[$traitName]['methods'][$methodName], + ]; + } + } + } + } + + private function processFunctions(array $functions): void + { + $link = $this->id() . '.html#'; + + foreach ($functions as $functionName => $function) { + $this->functions[$functionName] = [ + 'functionName' => $functionName, + 'namespace' => $function['namespace'], + 'signature' => $function['signature'], + 'startLine' => $function['startLine'], + 'endLine' => $function['endLine'], + 'executableLines' => 0, + 'executedLines' => 0, + 'executableBranches' => 0, + 'executedBranches' => 0, + 'executablePaths' => 0, + 'executedPaths' => 0, + 'ccn' => $function['ccn'], + 'coverage' => 0, + 'crap' => 0, + 'link' => $link . $function['startLine'], + ]; + + foreach (range($function['startLine'], $function['endLine']) as $lineNumber) { + $this->codeUnitsByLine[$lineNumber] = [&$this->functions[$functionName]]; + } + + if (isset($this->functionCoverageData[$functionName]['branches'])) { + $this->functions[$functionName]['executableBranches'] = count( + $this->functionCoverageData[$functionName]['branches'] + ); + + $this->functions[$functionName]['executedBranches'] = count( + array_filter( + $this->functionCoverageData[$functionName]['branches'], + static function (array $branch) + { + return (bool) $branch['hit']; + } + ) + ); + } + + if (isset($this->functionCoverageData[$functionName]['paths'])) { + $this->functions[$functionName]['executablePaths'] = count( + $this->functionCoverageData[$functionName]['paths'] + ); + + $this->functions[$functionName]['executedPaths'] = count( + array_filter( + $this->functionCoverageData[$functionName]['paths'], + static function (array $path) + { + return (bool) $path['hit']; + } + ) + ); + } + + $this->numExecutableBranches += $this->functions[$functionName]['executableBranches']; + $this->numExecutedBranches += $this->functions[$functionName]['executedBranches']; + $this->numExecutablePaths += $this->functions[$functionName]['executablePaths']; + $this->numExecutedPaths += $this->functions[$functionName]['executedPaths']; + } + } + + private function newMethod(string $className, string $methodName, array $method, string $link): array + { + $methodData = [ + 'methodName' => $methodName, + 'visibility' => $method['visibility'], + 'signature' => $method['signature'], + 'startLine' => $method['startLine'], + 'endLine' => $method['endLine'], + 'executableLines' => 0, + 'executedLines' => 0, + 'executableBranches' => 0, + 'executedBranches' => 0, + 'executablePaths' => 0, + 'executedPaths' => 0, + 'ccn' => $method['ccn'], + 'coverage' => 0, + 'crap' => 0, + 'link' => $link . $method['startLine'], + ]; + + $key = $className . '->' . $methodName; + + if (isset($this->functionCoverageData[$key]['branches'])) { + $methodData['executableBranches'] = count( + $this->functionCoverageData[$key]['branches'] + ); + + $methodData['executedBranches'] = count( + array_filter( + $this->functionCoverageData[$key]['branches'], + static function (array $branch) + { + return (bool) $branch['hit']; + } + ) + ); + } + + if (isset($this->functionCoverageData[$key]['paths'])) { + $methodData['executablePaths'] = count( + $this->functionCoverageData[$key]['paths'] + ); + + $methodData['executedPaths'] = count( + array_filter( + $this->functionCoverageData[$key]['paths'], + static function (array $path) + { + return (bool) $path['hit']; + } + ) + ); + } + + return $methodData; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Node/Iterator.php b/vendor/phpunit/php-code-coverage/src/Node/Iterator.php new file mode 100644 index 00000000..0d1c7354 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Node/Iterator.php @@ -0,0 +1,90 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Node; + +use function count; +use RecursiveIterator; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Iterator implements RecursiveIterator +{ + /** + * @var int + */ + private $position; + + /** + * @var AbstractNode[] + */ + private $nodes; + + public function __construct(Directory $node) + { + $this->nodes = $node->children(); + } + + /** + * Rewinds the Iterator to the first element. + */ + public function rewind(): void + { + $this->position = 0; + } + + /** + * Checks if there is a current element after calls to rewind() or next(). + */ + public function valid(): bool + { + return $this->position < count($this->nodes); + } + + /** + * Returns the key of the current element. + */ + public function key(): int + { + return $this->position; + } + + /** + * Returns the current element. + */ + public function current(): ?AbstractNode + { + return $this->valid() ? $this->nodes[$this->position] : null; + } + + /** + * Moves forward to next element. + */ + public function next(): void + { + $this->position++; + } + + /** + * Returns the sub iterator for the current element. + */ + public function getChildren(): self + { + return new self($this->nodes[$this->position]); + } + + /** + * Checks whether the current element has children. + */ + public function hasChildren(): bool + { + return $this->nodes[$this->position] instanceof Directory; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/ProcessedCodeCoverageData.php b/vendor/phpunit/php-code-coverage/src/ProcessedCodeCoverageData.php new file mode 100644 index 00000000..1ed29ad5 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/ProcessedCodeCoverageData.php @@ -0,0 +1,255 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use function array_key_exists; +use function array_keys; +use function array_merge; +use function array_unique; +use function count; +use function is_array; +use function ksort; +use SebastianBergmann\CodeCoverage\Driver\Driver; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class ProcessedCodeCoverageData +{ + /** + * Line coverage data. + * An array of filenames, each having an array of linenumbers, each executable line having an array of testcase ids. + * + * @var array + */ + private $lineCoverage = []; + + /** + * Function coverage data. + * Maintains base format of raw data (@see https://xdebug.org/docs/code_coverage), but each 'hit' entry is an array + * of testcase ids. + * + * @var array + */ + private $functionCoverage = []; + + public function initializeUnseenData(RawCodeCoverageData $rawData): void + { + foreach ($rawData->lineCoverage() as $file => $lines) { + if (!isset($this->lineCoverage[$file])) { + $this->lineCoverage[$file] = []; + + foreach ($lines as $k => $v) { + $this->lineCoverage[$file][$k] = $v === Driver::LINE_NOT_EXECUTABLE ? null : []; + } + } + } + + foreach ($rawData->functionCoverage() as $file => $functions) { + foreach ($functions as $functionName => $functionData) { + if (isset($this->functionCoverage[$file][$functionName])) { + $this->initPreviouslySeenFunction($file, $functionName, $functionData); + } else { + $this->initPreviouslyUnseenFunction($file, $functionName, $functionData); + } + } + } + } + + public function markCodeAsExecutedByTestCase(string $testCaseId, RawCodeCoverageData $executedCode): void + { + foreach ($executedCode->lineCoverage() as $file => $lines) { + foreach ($lines as $k => $v) { + if ($v === Driver::LINE_EXECUTED) { + $this->lineCoverage[$file][$k][] = $testCaseId; + } + } + } + + foreach ($executedCode->functionCoverage() as $file => $functions) { + foreach ($functions as $functionName => $functionData) { + foreach ($functionData['branches'] as $branchId => $branchData) { + if ($branchData['hit'] === Driver::BRANCH_HIT) { + $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'][] = $testCaseId; + } + } + + foreach ($functionData['paths'] as $pathId => $pathData) { + if ($pathData['hit'] === Driver::BRANCH_HIT) { + $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'][] = $testCaseId; + } + } + } + } + } + + public function setLineCoverage(array $lineCoverage): void + { + $this->lineCoverage = $lineCoverage; + } + + public function lineCoverage(): array + { + ksort($this->lineCoverage); + + return $this->lineCoverage; + } + + public function setFunctionCoverage(array $functionCoverage): void + { + $this->functionCoverage = $functionCoverage; + } + + public function functionCoverage(): array + { + ksort($this->functionCoverage); + + return $this->functionCoverage; + } + + public function coveredFiles(): array + { + ksort($this->lineCoverage); + + return array_keys($this->lineCoverage); + } + + public function renameFile(string $oldFile, string $newFile): void + { + $this->lineCoverage[$newFile] = $this->lineCoverage[$oldFile]; + + if (isset($this->functionCoverage[$oldFile])) { + $this->functionCoverage[$newFile] = $this->functionCoverage[$oldFile]; + } + + unset($this->lineCoverage[$oldFile], $this->functionCoverage[$oldFile]); + } + + public function merge(self $newData): void + { + foreach ($newData->lineCoverage as $file => $lines) { + if (!isset($this->lineCoverage[$file])) { + $this->lineCoverage[$file] = $lines; + + continue; + } + + // we should compare the lines if any of two contains data + $compareLineNumbers = array_unique( + array_merge( + array_keys($this->lineCoverage[$file]), + array_keys($newData->lineCoverage[$file]) + ) + ); + + foreach ($compareLineNumbers as $line) { + $thatPriority = $this->priorityForLine($newData->lineCoverage[$file], $line); + $thisPriority = $this->priorityForLine($this->lineCoverage[$file], $line); + + if ($thatPriority > $thisPriority) { + $this->lineCoverage[$file][$line] = $newData->lineCoverage[$file][$line]; + } elseif ($thatPriority === $thisPriority && is_array($this->lineCoverage[$file][$line])) { + $this->lineCoverage[$file][$line] = array_unique( + array_merge($this->lineCoverage[$file][$line], $newData->lineCoverage[$file][$line]) + ); + } + } + } + + foreach ($newData->functionCoverage as $file => $functions) { + if (!isset($this->functionCoverage[$file])) { + $this->functionCoverage[$file] = $functions; + + continue; + } + + foreach ($functions as $functionName => $functionData) { + if (isset($this->functionCoverage[$file][$functionName])) { + $this->initPreviouslySeenFunction($file, $functionName, $functionData); + } else { + $this->initPreviouslyUnseenFunction($file, $functionName, $functionData); + } + + foreach ($functionData['branches'] as $branchId => $branchData) { + $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = array_unique(array_merge($this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'], $branchData['hit'])); + } + + foreach ($functionData['paths'] as $pathId => $pathData) { + $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = array_unique(array_merge($this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'], $pathData['hit'])); + } + } + } + } + + /** + * Determine the priority for a line. + * + * 1 = the line is not set + * 2 = the line has not been tested + * 3 = the line is dead code + * 4 = the line has been tested + * + * During a merge, a higher number is better. + */ + private function priorityForLine(array $data, int $line): int + { + if (!array_key_exists($line, $data)) { + return 1; + } + + if (is_array($data[$line]) && count($data[$line]) === 0) { + return 2; + } + + if ($data[$line] === null) { + return 3; + } + + return 4; + } + + /** + * For a function we have never seen before, copy all data over and simply init the 'hit' array. + */ + private function initPreviouslyUnseenFunction(string $file, string $functionName, array $functionData): void + { + $this->functionCoverage[$file][$functionName] = $functionData; + + foreach (array_keys($functionData['branches']) as $branchId) { + $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = []; + } + + foreach (array_keys($functionData['paths']) as $pathId) { + $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = []; + } + } + + /** + * For a function we have seen before, only copy over and init the 'hit' array for any unseen branches and paths. + * Techniques such as mocking and where the contents of a file are different vary during tests (e.g. compiling + * containers) mean that the functions inside a file cannot be relied upon to be static. + */ + private function initPreviouslySeenFunction(string $file, string $functionName, array $functionData): void + { + foreach ($functionData['branches'] as $branchId => $branchData) { + if (!isset($this->functionCoverage[$file][$functionName]['branches'][$branchId])) { + $this->functionCoverage[$file][$functionName]['branches'][$branchId] = $branchData; + $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = []; + } + } + + foreach ($functionData['paths'] as $pathId => $pathData) { + if (!isset($this->functionCoverage[$file][$functionName]['paths'][$pathId])) { + $this->functionCoverage[$file][$functionName]['paths'][$pathId] = $pathData; + $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = []; + } + } + } +} diff --git a/vendor/phpunit/php-code-coverage/src/RawCodeCoverageData.php b/vendor/phpunit/php-code-coverage/src/RawCodeCoverageData.php new file mode 100644 index 00000000..9cb20e73 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/RawCodeCoverageData.php @@ -0,0 +1,274 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use function array_diff; +use function array_diff_key; +use function array_flip; +use function array_intersect; +use function array_intersect_key; +use function count; +use function explode; +use function file_get_contents; +use function in_array; +use function is_file; +use function range; +use function trim; +use SebastianBergmann\CodeCoverage\Driver\Driver; +use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class RawCodeCoverageData +{ + /** + * @var array<string, array<int>> + */ + private static $emptyLineCache = []; + + /** + * @var array + * + * @see https://xdebug.org/docs/code_coverage for format + */ + private $lineCoverage; + + /** + * @var array + * + * @see https://xdebug.org/docs/code_coverage for format + */ + private $functionCoverage; + + public static function fromXdebugWithoutPathCoverage(array $rawCoverage): self + { + return new self($rawCoverage, []); + } + + public static function fromXdebugWithPathCoverage(array $rawCoverage): self + { + $lineCoverage = []; + $functionCoverage = []; + + foreach ($rawCoverage as $file => $fileCoverageData) { + $lineCoverage[$file] = $fileCoverageData['lines']; + $functionCoverage[$file] = $fileCoverageData['functions']; + } + + return new self($lineCoverage, $functionCoverage); + } + + public static function fromXdebugWithMixedCoverage(array $rawCoverage): self + { + $lineCoverage = []; + $functionCoverage = []; + + foreach ($rawCoverage as $file => $fileCoverageData) { + if (!isset($fileCoverageData['functions'])) { + // Current file does not have functions, so line coverage + // is stored in $fileCoverageData, not in $fileCoverageData['lines'] + $lineCoverage[$file] = $fileCoverageData; + + continue; + } + + $lineCoverage[$file] = $fileCoverageData['lines']; + $functionCoverage[$file] = $fileCoverageData['functions']; + } + + return new self($lineCoverage, $functionCoverage); + } + + public static function fromUncoveredFile(string $filename, FileAnalyser $analyser): self + { + $lineCoverage = []; + + foreach ($analyser->executableLinesIn($filename) as $line => $branch) { + $lineCoverage[$line] = Driver::LINE_NOT_EXECUTED; + } + + return new self([$filename => $lineCoverage], []); + } + + private function __construct(array $lineCoverage, array $functionCoverage) + { + $this->lineCoverage = $lineCoverage; + $this->functionCoverage = $functionCoverage; + + $this->skipEmptyLines(); + } + + public function clear(): void + { + $this->lineCoverage = $this->functionCoverage = []; + } + + public function lineCoverage(): array + { + return $this->lineCoverage; + } + + public function functionCoverage(): array + { + return $this->functionCoverage; + } + + public function removeCoverageDataForFile(string $filename): void + { + unset($this->lineCoverage[$filename], $this->functionCoverage[$filename]); + } + + /** + * @param int[] $lines + */ + public function keepLineCoverageDataOnlyForLines(string $filename, array $lines): void + { + if (!isset($this->lineCoverage[$filename])) { + return; + } + + $this->lineCoverage[$filename] = array_intersect_key( + $this->lineCoverage[$filename], + array_flip($lines) + ); + } + + /** + * @param int[] $linesToBranchMap + */ + public function markExecutableLineByBranch(string $filename, array $linesToBranchMap): void + { + if (!isset($this->lineCoverage[$filename])) { + return; + } + + $linesByBranch = []; + + foreach ($linesToBranchMap as $line => $branch) { + $linesByBranch[$branch][] = $line; + } + + foreach ($this->lineCoverage[$filename] as $line => $lineStatus) { + if (!isset($linesToBranchMap[$line])) { + continue; + } + + $branch = $linesToBranchMap[$line]; + + if (!isset($linesByBranch[$branch])) { + continue; + } + + foreach ($linesByBranch[$branch] as $lineInBranch) { + $this->lineCoverage[$filename][$lineInBranch] = $lineStatus; + } + + if (Driver::LINE_EXECUTED === $lineStatus) { + unset($linesByBranch[$branch]); + } + } + } + + /** + * @param int[] $lines + */ + public function keepFunctionCoverageDataOnlyForLines(string $filename, array $lines): void + { + if (!isset($this->functionCoverage[$filename])) { + return; + } + + foreach ($this->functionCoverage[$filename] as $functionName => $functionData) { + foreach ($functionData['branches'] as $branchId => $branch) { + if (count(array_diff(range($branch['line_start'], $branch['line_end']), $lines)) > 0) { + unset($this->functionCoverage[$filename][$functionName]['branches'][$branchId]); + + foreach ($functionData['paths'] as $pathId => $path) { + if (in_array($branchId, $path['path'], true)) { + unset($this->functionCoverage[$filename][$functionName]['paths'][$pathId]); + } + } + } + } + } + } + + /** + * @param int[] $lines + */ + public function removeCoverageDataForLines(string $filename, array $lines): void + { + if (empty($lines)) { + return; + } + + if (!isset($this->lineCoverage[$filename])) { + return; + } + + $this->lineCoverage[$filename] = array_diff_key( + $this->lineCoverage[$filename], + array_flip($lines) + ); + + if (isset($this->functionCoverage[$filename])) { + foreach ($this->functionCoverage[$filename] as $functionName => $functionData) { + foreach ($functionData['branches'] as $branchId => $branch) { + if (count(array_intersect($lines, range($branch['line_start'], $branch['line_end']))) > 0) { + unset($this->functionCoverage[$filename][$functionName]['branches'][$branchId]); + + foreach ($functionData['paths'] as $pathId => $path) { + if (in_array($branchId, $path['path'], true)) { + unset($this->functionCoverage[$filename][$functionName]['paths'][$pathId]); + } + } + } + } + } + } + } + + /** + * At the end of a file, the PHP interpreter always sees an implicit return. Where this occurs in a file that has + * e.g. a class definition, that line cannot be invoked from a test and results in confusing coverage. This engine + * implementation detail therefore needs to be masked which is done here by simply ensuring that all empty lines + * are skipped over for coverage purposes. + * + * @see https://github.com/sebastianbergmann/php-code-coverage/issues/799 + */ + private function skipEmptyLines(): void + { + foreach ($this->lineCoverage as $filename => $coverage) { + foreach ($this->getEmptyLinesForFile($filename) as $emptyLine) { + unset($this->lineCoverage[$filename][$emptyLine]); + } + } + } + + private function getEmptyLinesForFile(string $filename): array + { + if (!isset(self::$emptyLineCache[$filename])) { + self::$emptyLineCache[$filename] = []; + + if (is_file($filename)) { + $sourceLines = explode("\n", file_get_contents($filename)); + + foreach ($sourceLines as $line => $source) { + if (trim($source) === '') { + self::$emptyLineCache[$filename][] = ($line + 1); + } + } + } + } + + return self::$emptyLineCache[$filename]; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Clover.php b/vendor/phpunit/php-code-coverage/src/Report/Clover.php new file mode 100644 index 00000000..75c731bb --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Clover.php @@ -0,0 +1,255 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report; + +use function count; +use function dirname; +use function file_put_contents; +use function is_string; +use function ksort; +use function max; +use function range; +use function time; +use DOMDocument; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; +use SebastianBergmann\CodeCoverage\Node\File; +use SebastianBergmann\CodeCoverage\Util\Filesystem; + +final class Clover +{ + /** + * @throws WriteOperationFailedException + */ + public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string + { + $time = (string) time(); + + $xmlDocument = new DOMDocument('1.0', 'UTF-8'); + $xmlDocument->formatOutput = true; + + $xmlCoverage = $xmlDocument->createElement('coverage'); + $xmlCoverage->setAttribute('generated', $time); + $xmlDocument->appendChild($xmlCoverage); + + $xmlProject = $xmlDocument->createElement('project'); + $xmlProject->setAttribute('timestamp', $time); + + if (is_string($name)) { + $xmlProject->setAttribute('name', $name); + } + + $xmlCoverage->appendChild($xmlProject); + + $packages = []; + $report = $coverage->getReport(); + + foreach ($report as $item) { + if (!$item instanceof File) { + continue; + } + + /* @var File $item */ + + $xmlFile = $xmlDocument->createElement('file'); + $xmlFile->setAttribute('name', $item->pathAsString()); + + $classes = $item->classesAndTraits(); + $coverageData = $item->lineCoverageData(); + $lines = []; + $namespace = 'global'; + + foreach ($classes as $className => $class) { + $classStatements = 0; + $coveredClassStatements = 0; + $coveredMethods = 0; + $classMethods = 0; + + foreach ($class['methods'] as $methodName => $method) { + if ($method['executableLines'] == 0) { + continue; + } + + $classMethods++; + $classStatements += $method['executableLines']; + $coveredClassStatements += $method['executedLines']; + + if ($method['coverage'] == 100) { + $coveredMethods++; + } + + $methodCount = 0; + + foreach (range($method['startLine'], $method['endLine']) as $line) { + if (isset($coverageData[$line]) && ($coverageData[$line] !== null)) { + $methodCount = max($methodCount, count($coverageData[$line])); + } + } + + $lines[$method['startLine']] = [ + 'ccn' => $method['ccn'], + 'count' => $methodCount, + 'crap' => $method['crap'], + 'type' => 'method', + 'visibility' => $method['visibility'], + 'name' => $methodName, + ]; + } + + if (!empty($class['package']['namespace'])) { + $namespace = $class['package']['namespace']; + } + + $xmlClass = $xmlDocument->createElement('class'); + $xmlClass->setAttribute('name', $className); + $xmlClass->setAttribute('namespace', $namespace); + + if (!empty($class['package']['fullPackage'])) { + $xmlClass->setAttribute( + 'fullPackage', + $class['package']['fullPackage'] + ); + } + + if (!empty($class['package']['category'])) { + $xmlClass->setAttribute( + 'category', + $class['package']['category'] + ); + } + + if (!empty($class['package']['package'])) { + $xmlClass->setAttribute( + 'package', + $class['package']['package'] + ); + } + + if (!empty($class['package']['subpackage'])) { + $xmlClass->setAttribute( + 'subpackage', + $class['package']['subpackage'] + ); + } + + $xmlFile->appendChild($xmlClass); + + $xmlMetrics = $xmlDocument->createElement('metrics'); + $xmlMetrics->setAttribute('complexity', (string) $class['ccn']); + $xmlMetrics->setAttribute('methods', (string) $classMethods); + $xmlMetrics->setAttribute('coveredmethods', (string) $coveredMethods); + $xmlMetrics->setAttribute('conditionals', (string) $class['executableBranches']); + $xmlMetrics->setAttribute('coveredconditionals', (string) $class['executedBranches']); + $xmlMetrics->setAttribute('statements', (string) $classStatements); + $xmlMetrics->setAttribute('coveredstatements', (string) $coveredClassStatements); + $xmlMetrics->setAttribute('elements', (string) ($classMethods + $classStatements + $class['executableBranches'])); + $xmlMetrics->setAttribute('coveredelements', (string) ($coveredMethods + $coveredClassStatements + $class['executedBranches'])); + $xmlClass->appendChild($xmlMetrics); + } + + foreach ($coverageData as $line => $data) { + if ($data === null || isset($lines[$line])) { + continue; + } + + $lines[$line] = [ + 'count' => count($data), 'type' => 'stmt', + ]; + } + + ksort($lines); + + foreach ($lines as $line => $data) { + $xmlLine = $xmlDocument->createElement('line'); + $xmlLine->setAttribute('num', (string) $line); + $xmlLine->setAttribute('type', $data['type']); + + if (isset($data['name'])) { + $xmlLine->setAttribute('name', $data['name']); + } + + if (isset($data['visibility'])) { + $xmlLine->setAttribute('visibility', $data['visibility']); + } + + if (isset($data['ccn'])) { + $xmlLine->setAttribute('complexity', (string) $data['ccn']); + } + + if (isset($data['crap'])) { + $xmlLine->setAttribute('crap', (string) $data['crap']); + } + + $xmlLine->setAttribute('count', (string) $data['count']); + $xmlFile->appendChild($xmlLine); + } + + $linesOfCode = $item->linesOfCode(); + + $xmlMetrics = $xmlDocument->createElement('metrics'); + $xmlMetrics->setAttribute('loc', (string) $linesOfCode['linesOfCode']); + $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode['nonCommentLinesOfCode']); + $xmlMetrics->setAttribute('classes', (string) $item->numberOfClassesAndTraits()); + $xmlMetrics->setAttribute('methods', (string) $item->numberOfMethods()); + $xmlMetrics->setAttribute('coveredmethods', (string) $item->numberOfTestedMethods()); + $xmlMetrics->setAttribute('conditionals', (string) $item->numberOfExecutableBranches()); + $xmlMetrics->setAttribute('coveredconditionals', (string) $item->numberOfExecutedBranches()); + $xmlMetrics->setAttribute('statements', (string) $item->numberOfExecutableLines()); + $xmlMetrics->setAttribute('coveredstatements', (string) $item->numberOfExecutedLines()); + $xmlMetrics->setAttribute('elements', (string) ($item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches())); + $xmlMetrics->setAttribute('coveredelements', (string) ($item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches())); + $xmlFile->appendChild($xmlMetrics); + + if ($namespace === 'global') { + $xmlProject->appendChild($xmlFile); + } else { + if (!isset($packages[$namespace])) { + $packages[$namespace] = $xmlDocument->createElement( + 'package' + ); + + $packages[$namespace]->setAttribute('name', $namespace); + $xmlProject->appendChild($packages[$namespace]); + } + + $packages[$namespace]->appendChild($xmlFile); + } + } + + $linesOfCode = $report->linesOfCode(); + + $xmlMetrics = $xmlDocument->createElement('metrics'); + $xmlMetrics->setAttribute('files', (string) count($report)); + $xmlMetrics->setAttribute('loc', (string) $linesOfCode['linesOfCode']); + $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode['nonCommentLinesOfCode']); + $xmlMetrics->setAttribute('classes', (string) $report->numberOfClassesAndTraits()); + $xmlMetrics->setAttribute('methods', (string) $report->numberOfMethods()); + $xmlMetrics->setAttribute('coveredmethods', (string) $report->numberOfTestedMethods()); + $xmlMetrics->setAttribute('conditionals', (string) $report->numberOfExecutableBranches()); + $xmlMetrics->setAttribute('coveredconditionals', (string) $report->numberOfExecutedBranches()); + $xmlMetrics->setAttribute('statements', (string) $report->numberOfExecutableLines()); + $xmlMetrics->setAttribute('coveredstatements', (string) $report->numberOfExecutedLines()); + $xmlMetrics->setAttribute('elements', (string) ($report->numberOfMethods() + $report->numberOfExecutableLines() + $report->numberOfExecutableBranches())); + $xmlMetrics->setAttribute('coveredelements', (string) ($report->numberOfTestedMethods() + $report->numberOfExecutedLines() + $report->numberOfExecutedBranches())); + $xmlProject->appendChild($xmlMetrics); + + $buffer = $xmlDocument->saveXML(); + + if ($target !== null) { + Filesystem::createDirectory(dirname($target)); + + if (@file_put_contents($target, $buffer) === false) { + throw new WriteOperationFailedException($target); + } + } + + return $buffer; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Cobertura.php b/vendor/phpunit/php-code-coverage/src/Report/Cobertura.php new file mode 100644 index 00000000..0d1dde76 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Cobertura.php @@ -0,0 +1,306 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report; + +use function basename; +use function count; +use function dirname; +use function file_put_contents; +use function preg_match; +use function range; +use function str_replace; +use function time; +use DOMImplementation; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; +use SebastianBergmann\CodeCoverage\Node\File; +use SebastianBergmann\CodeCoverage\Util\Filesystem; + +final class Cobertura +{ + /** + * @throws WriteOperationFailedException + */ + public function process(CodeCoverage $coverage, ?string $target = null): string + { + $time = (string) time(); + + $report = $coverage->getReport(); + + $implementation = new DOMImplementation; + + $documentType = $implementation->createDocumentType( + 'coverage', + '', + 'http://cobertura.sourceforge.net/xml/coverage-04.dtd' + ); + + $document = $implementation->createDocument('', '', $documentType); + $document->xmlVersion = '1.0'; + $document->encoding = 'UTF-8'; + $document->formatOutput = true; + + $coverageElement = $document->createElement('coverage'); + + $linesValid = $report->numberOfExecutableLines(); + $linesCovered = $report->numberOfExecutedLines(); + $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); + $coverageElement->setAttribute('line-rate', (string) $lineRate); + + $branchesValid = $report->numberOfExecutableBranches(); + $branchesCovered = $report->numberOfExecutedBranches(); + $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); + $coverageElement->setAttribute('branch-rate', (string) $branchRate); + + $coverageElement->setAttribute('lines-covered', (string) $report->numberOfExecutedLines()); + $coverageElement->setAttribute('lines-valid', (string) $report->numberOfExecutableLines()); + $coverageElement->setAttribute('branches-covered', (string) $report->numberOfExecutedBranches()); + $coverageElement->setAttribute('branches-valid', (string) $report->numberOfExecutableBranches()); + $coverageElement->setAttribute('complexity', ''); + $coverageElement->setAttribute('version', '0.4'); + $coverageElement->setAttribute('timestamp', $time); + + $document->appendChild($coverageElement); + + $sourcesElement = $document->createElement('sources'); + $coverageElement->appendChild($sourcesElement); + + $sourceElement = $document->createElement('source', $report->pathAsString()); + $sourcesElement->appendChild($sourceElement); + + $packagesElement = $document->createElement('packages'); + $coverageElement->appendChild($packagesElement); + + $complexity = 0; + + foreach ($report as $item) { + if (!$item instanceof File) { + continue; + } + + $packageElement = $document->createElement('package'); + $packageComplexity = 0; + + $packageElement->setAttribute('name', str_replace($report->pathAsString() . DIRECTORY_SEPARATOR, '', $item->pathAsString())); + + $linesValid = $item->numberOfExecutableLines(); + $linesCovered = $item->numberOfExecutedLines(); + $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); + + $packageElement->setAttribute('line-rate', (string) $lineRate); + + $branchesValid = $item->numberOfExecutableBranches(); + $branchesCovered = $item->numberOfExecutedBranches(); + $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); + + $packageElement->setAttribute('branch-rate', (string) $branchRate); + + $packageElement->setAttribute('complexity', ''); + $packagesElement->appendChild($packageElement); + + $classesElement = $document->createElement('classes'); + + $packageElement->appendChild($classesElement); + + $classes = $item->classesAndTraits(); + $coverageData = $item->lineCoverageData(); + + foreach ($classes as $className => $class) { + $complexity += $class['ccn']; + $packageComplexity += $class['ccn']; + + if (!empty($class['package']['namespace'])) { + $className = $class['package']['namespace'] . '\\' . $className; + } + + $linesValid = $class['executableLines']; + $linesCovered = $class['executedLines']; + $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); + + $branchesValid = $class['executableBranches']; + $branchesCovered = $class['executedBranches']; + $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); + + $classElement = $document->createElement('class'); + + $classElement->setAttribute('name', $className); + $classElement->setAttribute('filename', str_replace($report->pathAsString() . DIRECTORY_SEPARATOR, '', $item->pathAsString())); + $classElement->setAttribute('line-rate', (string) $lineRate); + $classElement->setAttribute('branch-rate', (string) $branchRate); + $classElement->setAttribute('complexity', (string) $class['ccn']); + + $classesElement->appendChild($classElement); + + $methodsElement = $document->createElement('methods'); + + $classElement->appendChild($methodsElement); + + $classLinesElement = $document->createElement('lines'); + + $classElement->appendChild($classLinesElement); + + foreach ($class['methods'] as $methodName => $method) { + if ($method['executableLines'] === 0) { + continue; + } + + preg_match("/\((.*?)\)/", $method['signature'], $signature); + + $linesValid = $method['executableLines']; + $linesCovered = $method['executedLines']; + $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); + + $branchesValid = $method['executableBranches']; + $branchesCovered = $method['executedBranches']; + $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); + + $methodElement = $document->createElement('method'); + + $methodElement->setAttribute('name', $methodName); + $methodElement->setAttribute('signature', $signature[1]); + $methodElement->setAttribute('line-rate', (string) $lineRate); + $methodElement->setAttribute('branch-rate', (string) $branchRate); + $methodElement->setAttribute('complexity', (string) $method['ccn']); + + $methodLinesElement = $document->createElement('lines'); + + $methodElement->appendChild($methodLinesElement); + + foreach (range($method['startLine'], $method['endLine']) as $line) { + if (!isset($coverageData[$line]) || $coverageData[$line] === null) { + continue; + } + $methodLineElement = $document->createElement('line'); + + $methodLineElement->setAttribute('number', (string) $line); + $methodLineElement->setAttribute('hits', (string) count($coverageData[$line])); + + $methodLinesElement->appendChild($methodLineElement); + + $classLineElement = $methodLineElement->cloneNode(); + + $classLinesElement->appendChild($classLineElement); + } + + $methodsElement->appendChild($methodElement); + } + } + + if ($report->numberOfFunctions() === 0) { + $packageElement->setAttribute('complexity', (string) $packageComplexity); + + continue; + } + + $functionsComplexity = 0; + $functionsLinesValid = 0; + $functionsLinesCovered = 0; + $functionsBranchesValid = 0; + $functionsBranchesCovered = 0; + + $classElement = $document->createElement('class'); + $classElement->setAttribute('name', basename($item->pathAsString())); + $classElement->setAttribute('filename', str_replace($report->pathAsString() . DIRECTORY_SEPARATOR, '', $item->pathAsString())); + + $methodsElement = $document->createElement('methods'); + + $classElement->appendChild($methodsElement); + + $classLinesElement = $document->createElement('lines'); + + $classElement->appendChild($classLinesElement); + + $functions = $report->functions(); + + foreach ($functions as $functionName => $function) { + if ($function['executableLines'] === 0) { + continue; + } + + $complexity += $function['ccn']; + $packageComplexity += $function['ccn']; + $functionsComplexity += $function['ccn']; + + $linesValid = $function['executableLines']; + $linesCovered = $function['executedLines']; + $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); + + $functionsLinesValid += $linesValid; + $functionsLinesCovered += $linesCovered; + + $branchesValid = $function['executableBranches']; + $branchesCovered = $function['executedBranches']; + $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); + + $functionsBranchesValid += $branchesValid; + $functionsBranchesCovered += $branchesValid; + + $methodElement = $document->createElement('method'); + + $methodElement->setAttribute('name', $functionName); + $methodElement->setAttribute('signature', $function['signature']); + $methodElement->setAttribute('line-rate', (string) $lineRate); + $methodElement->setAttribute('branch-rate', (string) $branchRate); + $methodElement->setAttribute('complexity', (string) $function['ccn']); + + $methodLinesElement = $document->createElement('lines'); + + $methodElement->appendChild($methodLinesElement); + + foreach (range($function['startLine'], $function['endLine']) as $line) { + if (!isset($coverageData[$line]) || $coverageData[$line] === null) { + continue; + } + $methodLineElement = $document->createElement('line'); + + $methodLineElement->setAttribute('number', (string) $line); + $methodLineElement->setAttribute('hits', (string) count($coverageData[$line])); + + $methodLinesElement->appendChild($methodLineElement); + + $classLineElement = $methodLineElement->cloneNode(); + + $classLinesElement->appendChild($classLineElement); + } + + $methodsElement->appendChild($methodElement); + } + + $packageElement->setAttribute('complexity', (string) $packageComplexity); + + if ($functionsLinesValid === 0) { + continue; + } + + $lineRate = $functionsLinesCovered / $functionsLinesValid; + $branchRate = $functionsBranchesValid === 0 ? 0 : ($functionsBranchesCovered / $functionsBranchesValid); + + $classElement->setAttribute('line-rate', (string) $lineRate); + $classElement->setAttribute('branch-rate', (string) $branchRate); + $classElement->setAttribute('complexity', (string) $functionsComplexity); + + $classesElement->appendChild($classElement); + } + + $coverageElement->setAttribute('complexity', (string) $complexity); + + $buffer = $document->saveXML(); + + if ($target !== null) { + Filesystem::createDirectory(dirname($target)); + + if (@file_put_contents($target, $buffer) === false) { + throw new WriteOperationFailedException($target); + } + } + + return $buffer; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Crap4j.php b/vendor/phpunit/php-code-coverage/src/Report/Crap4j.php new file mode 100644 index 00000000..91f8ed59 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Crap4j.php @@ -0,0 +1,153 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report; + +use function date; +use function dirname; +use function file_put_contents; +use function htmlspecialchars; +use function is_string; +use function round; +use DOMDocument; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; +use SebastianBergmann\CodeCoverage\Node\File; +use SebastianBergmann\CodeCoverage\Util\Filesystem; + +final class Crap4j +{ + /** + * @var int + */ + private $threshold; + + public function __construct(int $threshold = 30) + { + $this->threshold = $threshold; + } + + /** + * @throws WriteOperationFailedException + */ + public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string + { + $document = new DOMDocument('1.0', 'UTF-8'); + $document->formatOutput = true; + + $root = $document->createElement('crap_result'); + $document->appendChild($root); + + $project = $document->createElement('project', is_string($name) ? $name : ''); + $root->appendChild($project); + $root->appendChild($document->createElement('timestamp', date('Y-m-d H:i:s'))); + + $stats = $document->createElement('stats'); + $methodsNode = $document->createElement('methods'); + + $report = $coverage->getReport(); + unset($coverage); + + $fullMethodCount = 0; + $fullCrapMethodCount = 0; + $fullCrapLoad = 0; + $fullCrap = 0; + + foreach ($report as $item) { + $namespace = 'global'; + + if (!$item instanceof File) { + continue; + } + + $file = $document->createElement('file'); + $file->setAttribute('name', $item->pathAsString()); + + $classes = $item->classesAndTraits(); + + foreach ($classes as $className => $class) { + foreach ($class['methods'] as $methodName => $method) { + $crapLoad = $this->crapLoad((float) $method['crap'], $method['ccn'], $method['coverage']); + + $fullCrap += $method['crap']; + $fullCrapLoad += $crapLoad; + $fullMethodCount++; + + if ($method['crap'] >= $this->threshold) { + $fullCrapMethodCount++; + } + + $methodNode = $document->createElement('method'); + + if (!empty($class['namespace'])) { + $namespace = $class['namespace']; + } + + $methodNode->appendChild($document->createElement('package', $namespace)); + $methodNode->appendChild($document->createElement('className', $className)); + $methodNode->appendChild($document->createElement('methodName', $methodName)); + $methodNode->appendChild($document->createElement('methodSignature', htmlspecialchars($method['signature']))); + $methodNode->appendChild($document->createElement('fullMethod', htmlspecialchars($method['signature']))); + $methodNode->appendChild($document->createElement('crap', (string) $this->roundValue((float) $method['crap']))); + $methodNode->appendChild($document->createElement('complexity', (string) $method['ccn'])); + $methodNode->appendChild($document->createElement('coverage', (string) $this->roundValue($method['coverage']))); + $methodNode->appendChild($document->createElement('crapLoad', (string) round($crapLoad))); + + $methodsNode->appendChild($methodNode); + } + } + } + + $stats->appendChild($document->createElement('name', 'Method Crap Stats')); + $stats->appendChild($document->createElement('methodCount', (string) $fullMethodCount)); + $stats->appendChild($document->createElement('crapMethodCount', (string) $fullCrapMethodCount)); + $stats->appendChild($document->createElement('crapLoad', (string) round($fullCrapLoad))); + $stats->appendChild($document->createElement('totalCrap', (string) $fullCrap)); + + $crapMethodPercent = 0; + + if ($fullMethodCount > 0) { + $crapMethodPercent = $this->roundValue((100 * $fullCrapMethodCount) / $fullMethodCount); + } + + $stats->appendChild($document->createElement('crapMethodPercent', (string) $crapMethodPercent)); + + $root->appendChild($stats); + $root->appendChild($methodsNode); + + $buffer = $document->saveXML(); + + if ($target !== null) { + Filesystem::createDirectory(dirname($target)); + + if (@file_put_contents($target, $buffer) === false) { + throw new WriteOperationFailedException($target); + } + } + + return $buffer; + } + + private function crapLoad(float $crapValue, int $cyclomaticComplexity, float $coveragePercent): float + { + $crapLoad = 0; + + if ($crapValue >= $this->threshold) { + $crapLoad += $cyclomaticComplexity * (1.0 - $coveragePercent / 100); + $crapLoad += $cyclomaticComplexity / $this->threshold; + } + + return $crapLoad; + } + + private function roundValue(float $value): float + { + return round($value, 2); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Facade.php b/vendor/phpunit/php-code-coverage/src/Report/Html/Facade.php new file mode 100644 index 00000000..69935d73 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Facade.php @@ -0,0 +1,147 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use const DIRECTORY_SEPARATOR; +use function copy; +use function date; +use function dirname; +use function substr; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\InvalidArgumentException; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; +use SebastianBergmann\CodeCoverage\Util\Filesystem; + +final class Facade +{ + /** + * @var string + */ + private $templatePath; + + /** + * @var string + */ + private $generator; + + /** + * @var int + */ + private $lowUpperBound; + + /** + * @var int + */ + private $highLowerBound; + + public function __construct(int $lowUpperBound = 50, int $highLowerBound = 90, string $generator = '') + { + if ($lowUpperBound > $highLowerBound) { + throw new InvalidArgumentException( + '$lowUpperBound must not be larger than $highLowerBound' + ); + } + + $this->generator = $generator; + $this->highLowerBound = $highLowerBound; + $this->lowUpperBound = $lowUpperBound; + $this->templatePath = __DIR__ . '/Renderer/Template/'; + } + + public function process(CodeCoverage $coverage, string $target): void + { + $target = $this->directory($target); + $report = $coverage->getReport(); + $date = date('D M j G:i:s T Y'); + + $dashboard = new Dashboard( + $this->templatePath, + $this->generator, + $date, + $this->lowUpperBound, + $this->highLowerBound, + $coverage->collectsBranchAndPathCoverage() + ); + + $directory = new Directory( + $this->templatePath, + $this->generator, + $date, + $this->lowUpperBound, + $this->highLowerBound, + $coverage->collectsBranchAndPathCoverage() + ); + + $file = new File( + $this->templatePath, + $this->generator, + $date, + $this->lowUpperBound, + $this->highLowerBound, + $coverage->collectsBranchAndPathCoverage() + ); + + $directory->render($report, $target . 'index.html'); + $dashboard->render($report, $target . 'dashboard.html'); + + foreach ($report as $node) { + $id = $node->id(); + + if ($node instanceof DirectoryNode) { + Filesystem::createDirectory($target . $id); + + $directory->render($node, $target . $id . '/index.html'); + $dashboard->render($node, $target . $id . '/dashboard.html'); + } else { + $dir = dirname($target . $id); + + Filesystem::createDirectory($dir); + + $file->render($node, $target . $id); + } + } + + $this->copyFiles($target); + } + + private function copyFiles(string $target): void + { + $dir = $this->directory($target . '_css'); + + copy($this->templatePath . 'css/bootstrap.min.css', $dir . 'bootstrap.min.css'); + copy($this->templatePath . 'css/nv.d3.min.css', $dir . 'nv.d3.min.css'); + copy($this->templatePath . 'css/style.css', $dir . 'style.css'); + copy($this->templatePath . 'css/custom.css', $dir . 'custom.css'); + copy($this->templatePath . 'css/octicons.css', $dir . 'octicons.css'); + + $dir = $this->directory($target . '_icons'); + copy($this->templatePath . 'icons/file-code.svg', $dir . 'file-code.svg'); + copy($this->templatePath . 'icons/file-directory.svg', $dir . 'file-directory.svg'); + + $dir = $this->directory($target . '_js'); + copy($this->templatePath . 'js/bootstrap.min.js', $dir . 'bootstrap.min.js'); + copy($this->templatePath . 'js/popper.min.js', $dir . 'popper.min.js'); + copy($this->templatePath . 'js/d3.min.js', $dir . 'd3.min.js'); + copy($this->templatePath . 'js/jquery.min.js', $dir . 'jquery.min.js'); + copy($this->templatePath . 'js/nv.d3.min.js', $dir . 'nv.d3.min.js'); + copy($this->templatePath . 'js/file.js', $dir . 'file.js'); + } + + private function directory(string $directory): string + { + if (substr($directory, -1, 1) != DIRECTORY_SEPARATOR) { + $directory .= DIRECTORY_SEPARATOR; + } + + Filesystem::createDirectory($directory); + + return $directory; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer.php b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer.php new file mode 100644 index 00000000..fe285b18 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer.php @@ -0,0 +1,314 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use function array_pop; +use function count; +use function sprintf; +use function str_repeat; +use function substr_count; +use SebastianBergmann\CodeCoverage\Node\AbstractNode; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; +use SebastianBergmann\CodeCoverage\Node\File as FileNode; +use SebastianBergmann\CodeCoverage\Version; +use SebastianBergmann\Environment\Runtime; +use SebastianBergmann\Template\Template; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +abstract class Renderer +{ + /** + * @var string + */ + protected $templatePath; + + /** + * @var string + */ + protected $generator; + + /** + * @var string + */ + protected $date; + + /** + * @var int + */ + protected $lowUpperBound; + + /** + * @var int + */ + protected $highLowerBound; + + /** + * @var bool + */ + protected $hasBranchCoverage; + + /** + * @var string + */ + protected $version; + + public function __construct(string $templatePath, string $generator, string $date, int $lowUpperBound, int $highLowerBound, bool $hasBranchCoverage) + { + $this->templatePath = $templatePath; + $this->generator = $generator; + $this->date = $date; + $this->lowUpperBound = $lowUpperBound; + $this->highLowerBound = $highLowerBound; + $this->version = Version::id(); + $this->hasBranchCoverage = $hasBranchCoverage; + } + + protected function renderItemTemplate(Template $template, array $data): string + { + $numSeparator = ' / '; + + if (isset($data['numClasses']) && $data['numClasses'] > 0) { + $classesLevel = $this->colorLevel($data['testedClassesPercent']); + + $classesNumber = $data['numTestedClasses'] . $numSeparator . + $data['numClasses']; + + $classesBar = $this->coverageBar( + $data['testedClassesPercent'] + ); + } else { + $classesLevel = ''; + $classesNumber = '0' . $numSeparator . '0'; + $classesBar = ''; + $data['testedClassesPercentAsString'] = 'n/a'; + } + + if ($data['numMethods'] > 0) { + $methodsLevel = $this->colorLevel($data['testedMethodsPercent']); + + $methodsNumber = $data['numTestedMethods'] . $numSeparator . + $data['numMethods']; + + $methodsBar = $this->coverageBar( + $data['testedMethodsPercent'] + ); + } else { + $methodsLevel = ''; + $methodsNumber = '0' . $numSeparator . '0'; + $methodsBar = ''; + $data['testedMethodsPercentAsString'] = 'n/a'; + } + + if ($data['numExecutableLines'] > 0) { + $linesLevel = $this->colorLevel($data['linesExecutedPercent']); + + $linesNumber = $data['numExecutedLines'] . $numSeparator . + $data['numExecutableLines']; + + $linesBar = $this->coverageBar( + $data['linesExecutedPercent'] + ); + } else { + $linesLevel = ''; + $linesNumber = '0' . $numSeparator . '0'; + $linesBar = ''; + $data['linesExecutedPercentAsString'] = 'n/a'; + } + + if ($data['numExecutablePaths'] > 0) { + $pathsLevel = $this->colorLevel($data['pathsExecutedPercent']); + + $pathsNumber = $data['numExecutedPaths'] . $numSeparator . + $data['numExecutablePaths']; + + $pathsBar = $this->coverageBar( + $data['pathsExecutedPercent'] + ); + } else { + $pathsLevel = ''; + $pathsNumber = '0' . $numSeparator . '0'; + $pathsBar = ''; + $data['pathsExecutedPercentAsString'] = 'n/a'; + } + + if ($data['numExecutableBranches'] > 0) { + $branchesLevel = $this->colorLevel($data['branchesExecutedPercent']); + + $branchesNumber = $data['numExecutedBranches'] . $numSeparator . + $data['numExecutableBranches']; + + $branchesBar = $this->coverageBar( + $data['branchesExecutedPercent'] + ); + } else { + $branchesLevel = ''; + $branchesNumber = '0' . $numSeparator . '0'; + $branchesBar = ''; + $data['branchesExecutedPercentAsString'] = 'n/a'; + } + + $template->setVar( + [ + 'icon' => $data['icon'] ?? '', + 'crap' => $data['crap'] ?? '', + 'name' => $data['name'], + 'lines_bar' => $linesBar, + 'lines_executed_percent' => $data['linesExecutedPercentAsString'], + 'lines_level' => $linesLevel, + 'lines_number' => $linesNumber, + 'paths_bar' => $pathsBar, + 'paths_executed_percent' => $data['pathsExecutedPercentAsString'], + 'paths_level' => $pathsLevel, + 'paths_number' => $pathsNumber, + 'branches_bar' => $branchesBar, + 'branches_executed_percent' => $data['branchesExecutedPercentAsString'], + 'branches_level' => $branchesLevel, + 'branches_number' => $branchesNumber, + 'methods_bar' => $methodsBar, + 'methods_tested_percent' => $data['testedMethodsPercentAsString'], + 'methods_level' => $methodsLevel, + 'methods_number' => $methodsNumber, + 'classes_bar' => $classesBar, + 'classes_tested_percent' => $data['testedClassesPercentAsString'] ?? '', + 'classes_level' => $classesLevel, + 'classes_number' => $classesNumber, + ] + ); + + return $template->render(); + } + + protected function setCommonTemplateVariables(Template $template, AbstractNode $node): void + { + $template->setVar( + [ + 'id' => $node->id(), + 'full_path' => $node->pathAsString(), + 'path_to_root' => $this->pathToRoot($node), + 'breadcrumbs' => $this->breadcrumbs($node), + 'date' => $this->date, + 'version' => $this->version, + 'runtime' => $this->runtimeString(), + 'generator' => $this->generator, + 'low_upper_bound' => $this->lowUpperBound, + 'high_lower_bound' => $this->highLowerBound, + ] + ); + } + + protected function breadcrumbs(AbstractNode $node): string + { + $breadcrumbs = ''; + $path = $node->pathAsArray(); + $pathToRoot = []; + $max = count($path); + + if ($node instanceof FileNode) { + $max--; + } + + for ($i = 0; $i < $max; $i++) { + $pathToRoot[] = str_repeat('../', $i); + } + + foreach ($path as $step) { + if ($step !== $node) { + $breadcrumbs .= $this->inactiveBreadcrumb( + $step, + array_pop($pathToRoot) + ); + } else { + $breadcrumbs .= $this->activeBreadcrumb($step); + } + } + + return $breadcrumbs; + } + + protected function activeBreadcrumb(AbstractNode $node): string + { + $buffer = sprintf( + ' <li class="breadcrumb-item active">%s</li>' . "\n", + $node->name() + ); + + if ($node instanceof DirectoryNode) { + $buffer .= ' <li class="breadcrumb-item">(<a href="dashboard.html">Dashboard</a>)</li>' . "\n"; + } + + return $buffer; + } + + protected function inactiveBreadcrumb(AbstractNode $node, string $pathToRoot): string + { + return sprintf( + ' <li class="breadcrumb-item"><a href="%sindex.html">%s</a></li>' . "\n", + $pathToRoot, + $node->name() + ); + } + + protected function pathToRoot(AbstractNode $node): string + { + $id = $node->id(); + $depth = substr_count($id, '/'); + + if ($id !== 'index' && + $node instanceof DirectoryNode) { + $depth++; + } + + return str_repeat('../', $depth); + } + + protected function coverageBar(float $percent): string + { + $level = $this->colorLevel($percent); + + $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'coverage_bar_branch.html' : 'coverage_bar.html'); + $template = new Template( + $templateName, + '{{', + '}}' + ); + + $template->setVar(['level' => $level, 'percent' => sprintf('%.2F', $percent)]); + + return $template->render(); + } + + protected function colorLevel(float $percent): string + { + if ($percent <= $this->lowUpperBound) { + return 'danger'; + } + + if ($percent > $this->lowUpperBound && + $percent < $this->highLowerBound) { + return 'warning'; + } + + return 'success'; + } + + private function runtimeString(): string + { + $runtime = new Runtime; + + return sprintf( + '<a href="%s" target="_top">%s %s</a>', + $runtime->getVendorUrl(), + $runtime->getName(), + $runtime->getVersion() + ); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php new file mode 100644 index 00000000..6672a6ea --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php @@ -0,0 +1,288 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use function array_values; +use function arsort; +use function asort; +use function count; +use function explode; +use function floor; +use function json_encode; +use function sprintf; +use function str_replace; +use SebastianBergmann\CodeCoverage\Node\AbstractNode; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; +use SebastianBergmann\Template\Template; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Dashboard extends Renderer +{ + public function render(DirectoryNode $node, string $file): void + { + $classes = $node->classesAndTraits(); + $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'dashboard_branch.html' : 'dashboard.html'); + $template = new Template( + $templateName, + '{{', + '}}' + ); + + $this->setCommonTemplateVariables($template, $node); + + $baseLink = $node->id() . '/'; + $complexity = $this->complexity($classes, $baseLink); + $coverageDistribution = $this->coverageDistribution($classes); + $insufficientCoverage = $this->insufficientCoverage($classes, $baseLink); + $projectRisks = $this->projectRisks($classes, $baseLink); + + $template->setVar( + [ + 'insufficient_coverage_classes' => $insufficientCoverage['class'], + 'insufficient_coverage_methods' => $insufficientCoverage['method'], + 'project_risks_classes' => $projectRisks['class'], + 'project_risks_methods' => $projectRisks['method'], + 'complexity_class' => $complexity['class'], + 'complexity_method' => $complexity['method'], + 'class_coverage_distribution' => $coverageDistribution['class'], + 'method_coverage_distribution' => $coverageDistribution['method'], + ] + ); + + $template->renderTo($file); + } + + protected function activeBreadcrumb(AbstractNode $node): string + { + return sprintf( + ' <li class="breadcrumb-item"><a href="index.html">%s</a></li>' . "\n" . + ' <li class="breadcrumb-item active">(Dashboard)</li>' . "\n", + $node->name() + ); + } + + /** + * Returns the data for the Class/Method Complexity charts. + */ + private function complexity(array $classes, string $baseLink): array + { + $result = ['class' => [], 'method' => []]; + + foreach ($classes as $className => $class) { + foreach ($class['methods'] as $methodName => $method) { + if ($className !== '*') { + $methodName = $className . '::' . $methodName; + } + + $result['method'][] = [ + $method['coverage'], + $method['ccn'], + sprintf( + '<a href="%s">%s</a>', + str_replace($baseLink, '', $method['link']), + $methodName + ), + ]; + } + + $result['class'][] = [ + $class['coverage'], + $class['ccn'], + sprintf( + '<a href="%s">%s</a>', + str_replace($baseLink, '', $class['link']), + $className + ), + ]; + } + + return [ + 'class' => json_encode($result['class']), + 'method' => json_encode($result['method']), + ]; + } + + /** + * Returns the data for the Class / Method Coverage Distribution chart. + */ + private function coverageDistribution(array $classes): array + { + $result = [ + 'class' => [ + '0%' => 0, + '0-10%' => 0, + '10-20%' => 0, + '20-30%' => 0, + '30-40%' => 0, + '40-50%' => 0, + '50-60%' => 0, + '60-70%' => 0, + '70-80%' => 0, + '80-90%' => 0, + '90-100%' => 0, + '100%' => 0, + ], + 'method' => [ + '0%' => 0, + '0-10%' => 0, + '10-20%' => 0, + '20-30%' => 0, + '30-40%' => 0, + '40-50%' => 0, + '50-60%' => 0, + '60-70%' => 0, + '70-80%' => 0, + '80-90%' => 0, + '90-100%' => 0, + '100%' => 0, + ], + ]; + + foreach ($classes as $class) { + foreach ($class['methods'] as $methodName => $method) { + if ($method['coverage'] === 0) { + $result['method']['0%']++; + } elseif ($method['coverage'] === 100) { + $result['method']['100%']++; + } else { + $key = floor($method['coverage'] / 10) * 10; + $key = $key . '-' . ($key + 10) . '%'; + $result['method'][$key]++; + } + } + + if ($class['coverage'] === 0) { + $result['class']['0%']++; + } elseif ($class['coverage'] === 100) { + $result['class']['100%']++; + } else { + $key = floor($class['coverage'] / 10) * 10; + $key = $key . '-' . ($key + 10) . '%'; + $result['class'][$key]++; + } + } + + return [ + 'class' => json_encode(array_values($result['class'])), + 'method' => json_encode(array_values($result['method'])), + ]; + } + + /** + * Returns the classes / methods with insufficient coverage. + */ + private function insufficientCoverage(array $classes, string $baseLink): array + { + $leastTestedClasses = []; + $leastTestedMethods = []; + $result = ['class' => '', 'method' => '']; + + foreach ($classes as $className => $class) { + foreach ($class['methods'] as $methodName => $method) { + if ($method['coverage'] < $this->highLowerBound) { + $key = $methodName; + + if ($className !== '*') { + $key = $className . '::' . $methodName; + } + + $leastTestedMethods[$key] = $method['coverage']; + } + } + + if ($class['coverage'] < $this->highLowerBound) { + $leastTestedClasses[$className] = $class['coverage']; + } + } + + asort($leastTestedClasses); + asort($leastTestedMethods); + + foreach ($leastTestedClasses as $className => $coverage) { + $result['class'] .= sprintf( + ' <tr><td><a href="%s">%s</a></td><td class="text-right">%d%%</td></tr>' . "\n", + str_replace($baseLink, '', $classes[$className]['link']), + $className, + $coverage + ); + } + + foreach ($leastTestedMethods as $methodName => $coverage) { + [$class, $method] = explode('::', $methodName); + + $result['method'] .= sprintf( + ' <tr><td><a href="%s"><abbr title="%s">%s</abbr></a></td><td class="text-right">%d%%</td></tr>' . "\n", + str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']), + $methodName, + $method, + $coverage + ); + } + + return $result; + } + + /** + * Returns the project risks according to the CRAP index. + */ + private function projectRisks(array $classes, string $baseLink): array + { + $classRisks = []; + $methodRisks = []; + $result = ['class' => '', 'method' => '']; + + foreach ($classes as $className => $class) { + foreach ($class['methods'] as $methodName => $method) { + if ($method['coverage'] < $this->highLowerBound && $method['ccn'] > 1) { + $key = $methodName; + + if ($className !== '*') { + $key = $className . '::' . $methodName; + } + + $methodRisks[$key] = $method['crap']; + } + } + + if ($class['coverage'] < $this->highLowerBound && + $class['ccn'] > count($class['methods'])) { + $classRisks[$className] = $class['crap']; + } + } + + arsort($classRisks); + arsort($methodRisks); + + foreach ($classRisks as $className => $crap) { + $result['class'] .= sprintf( + ' <tr><td><a href="%s">%s</a></td><td class="text-right">%d</td></tr>' . "\n", + str_replace($baseLink, '', $classes[$className]['link']), + $className, + $crap + ); + } + + foreach ($methodRisks as $methodName => $crap) { + [$class, $method] = explode('::', $methodName); + + $result['method'] .= sprintf( + ' <tr><td><a href="%s"><abbr title="%s">%s</abbr></a></td><td class="text-right">%d</td></tr>' . "\n", + str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']), + $methodName, + $method, + $crap + ); + } + + return $result; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php new file mode 100644 index 00000000..faacbc31 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php @@ -0,0 +1,113 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use function count; +use function sprintf; +use function str_repeat; +use SebastianBergmann\CodeCoverage\Node\AbstractNode as Node; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; +use SebastianBergmann\Template\Template; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Directory extends Renderer +{ + public function render(DirectoryNode $node, string $file): void + { + $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'directory_branch.html' : 'directory.html'); + $template = new Template($templateName, '{{', '}}'); + + $this->setCommonTemplateVariables($template, $node); + + $items = $this->renderItem($node, true); + + foreach ($node->directories() as $item) { + $items .= $this->renderItem($item); + } + + foreach ($node->files() as $item) { + $items .= $this->renderItem($item); + } + + $template->setVar( + [ + 'id' => $node->id(), + 'items' => $items, + ] + ); + + $template->renderTo($file); + } + + private function renderItem(Node $node, bool $total = false): string + { + $data = [ + 'numClasses' => $node->numberOfClassesAndTraits(), + 'numTestedClasses' => $node->numberOfTestedClassesAndTraits(), + 'numMethods' => $node->numberOfFunctionsAndMethods(), + 'numTestedMethods' => $node->numberOfTestedFunctionsAndMethods(), + 'linesExecutedPercent' => $node->percentageOfExecutedLines()->asFloat(), + 'linesExecutedPercentAsString' => $node->percentageOfExecutedLines()->asString(), + 'numExecutedLines' => $node->numberOfExecutedLines(), + 'numExecutableLines' => $node->numberOfExecutableLines(), + 'branchesExecutedPercent' => $node->percentageOfExecutedBranches()->asFloat(), + 'branchesExecutedPercentAsString' => $node->percentageOfExecutedBranches()->asString(), + 'numExecutedBranches' => $node->numberOfExecutedBranches(), + 'numExecutableBranches' => $node->numberOfExecutableBranches(), + 'pathsExecutedPercent' => $node->percentageOfExecutedPaths()->asFloat(), + 'pathsExecutedPercentAsString' => $node->percentageOfExecutedPaths()->asString(), + 'numExecutedPaths' => $node->numberOfExecutedPaths(), + 'numExecutablePaths' => $node->numberOfExecutablePaths(), + 'testedMethodsPercent' => $node->percentageOfTestedFunctionsAndMethods()->asFloat(), + 'testedMethodsPercentAsString' => $node->percentageOfTestedFunctionsAndMethods()->asString(), + 'testedClassesPercent' => $node->percentageOfTestedClassesAndTraits()->asFloat(), + 'testedClassesPercentAsString' => $node->percentageOfTestedClassesAndTraits()->asString(), + ]; + + if ($total) { + $data['name'] = 'Total'; + } else { + $up = str_repeat('../', count($node->pathAsArray()) - 2); + $data['icon'] = sprintf('<img src="%s_icons/file-code.svg" class="octicon" />', $up); + + if ($node instanceof DirectoryNode) { + $data['name'] = sprintf( + '<a href="%s/index.html">%s</a>', + $node->name(), + $node->name() + ); + $data['icon'] = sprintf('<img src="%s_icons/file-directory.svg" class="octicon" />', $up); + } elseif ($this->hasBranchCoverage) { + $data['name'] = sprintf( + '%s <a class="small" href="%s.html">[line]</a> <a class="small" href="%s_branch.html">[branch]</a> <a class="small" href="%s_path.html">[path]</a>', + $node->name(), + $node->name(), + $node->name(), + $node->name() + ); + } else { + $data['name'] = sprintf( + '<a href="%s.html">%s</a>', + $node->name(), + $node->name() + ); + } + } + + $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'directory_item_branch.html' : 'directory_item.html'); + + return $this->renderItemTemplate( + new Template($templateName, '{{', '}}'), + $data + ); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php new file mode 100644 index 00000000..69fd8b1d --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php @@ -0,0 +1,1162 @@ +<?php declare(strict_types=1); +/* + * This file is part of phpunit/php-code-coverage. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use const ENT_COMPAT; +use const ENT_HTML401; +use const ENT_SUBSTITUTE; +use const T_ABSTRACT; +use const T_ARRAY; +use const T_AS; +use const T_BREAK; +use const T_CALLABLE; +use const T_CASE; +use const T_CATCH; +use const T_CLASS; +use const T_CLONE; +use const T_COMMENT; +use const T_CONST; +use const T_CONTINUE; +use const T_DECLARE; +use const T_DEFAULT; +use const T_DO; +use const T_DOC_COMMENT; +use const T_ECHO; +use const T_ELSE; +use const T_ELSEIF; +use const T_EMPTY; +use const T_ENDDECLARE; +use const T_ENDFOR; +use const T_ENDFOREACH; +use const T_ENDIF; +use const T_ENDSWITCH; +use const T_ENDWHILE; +use const T_EVAL; +use const T_EXIT; +use const T_EXTENDS; +use const T_FINAL; +use const T_FINALLY; +use const T_FOR; +use const T_FOREACH; +use const T_FUNCTION; +use const T_GLOBAL; +use const T_GOTO; +use const T_HALT_COMPILER; +use const T_IF; +use const T_IMPLEMENTS; +use const T_INCLUDE; +use const T_INCLUDE_ONCE; +use const T_INLINE_HTML; +use const T_INSTANCEOF; +use const T_INSTEADOF; +use const T_INTERFACE; +use const T_ISSET; +use const T_LIST; +use const T_NAMESPACE; +use const T_NEW; +use const T_PRINT; +use const T_PRIVATE; +use const T_PROTECTED; +use const T_PUBLIC; +use const T_REQUIRE; +use const T_REQUIRE_ONCE; +use const T_RETURN; +use const T_STATIC; +use const T_SWITCH; +use const T_THROW; +use const T_TRAIT; +use const T_TRY; +use const T_UNSET; +use const T_USE; +use const T_VAR; +use const T_WHILE; +use const T_YIELD; +use const T_YIELD_FROM; +use function array_key_exists; +use function array_keys; +use function array_merge; +use function array_pop; +use function array_unique; +use function constant; +use function count; +use function defined; +use function explode; +use function file_get_contents; +use function htmlspecialchars; +use function is_string; +use function ksort; +use function range; +use function sort; +use function sprintf; +use function str_replace; +use function substr; +use function token_get_all; +use function trim; +use PHPUnit\Runner\BaseTestRunner; +use SebastianBergmann\CodeCoverage\Node\File as FileNode; +use SebastianBergmann\CodeCoverage\Util\Percentage; +use SebastianBergmann\Template\Template; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class File extends Renderer +{ + /** + * @psalm-var array<int,true> + */ + private static $keywordTokens = []; + + /** + * @var array + */ + private static $formattedSourceCache = []; + + /** + * @var int + */ + private $htmlSpecialCharsFlags = ENT_COMPAT | ENT_HTML401 | ENT_SUBSTITUTE; + + public function render(FileNode $node, string $file): void + { + $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'file_branch.html' : 'file.html'); + $template = new Template($templateName, '{{', '}}'); + $this->setCommonTemplateVariables($template, $node); + + $template->setVar( + [ + 'items' => $this->renderItems($node), + 'lines' => $this->renderSourceWithLineCoverage($node), + 'legend' => '<p><span class="success"><strong>Executed</strong></span><span class="danger"><strong>Not Executed</strong></span><span class="warning"><strong>Dead Code</strong></span></p>', + 'structure' => '', + ] + ); + + $template->renderTo($file . '.html'); + + if ($this->hasBranchCoverage) { + $template->setVar( + [ + 'items' => $this->renderItems($node), + 'lines' => $this->renderSourceWithBranchCoverage($node), + 'legend' => '<p><span class="success"><strong>Fully covered</strong></span><span class="warning"><strong>Partially covered</strong></span><span class="danger"><strong>Not covered</strong></span></p>', + 'structure' => $this->renderBranchStructure($node), + ] + ); + + $template->renderTo($file . '_branch.html'); + + $template->setVar( + [ + 'items' => $this->renderItems($node), + 'lines' => $this->renderSourceWithPathCoverage($node), + 'legend' => '<p><span class="success"><strong>Fully covered</strong></span><span class="warning"><strong>Partially covered</strong></span><span class="danger"><strong>Not covered</strong></span></p>', + 'structure' => $this->renderPathStructure($node), + ] + ); + + $template->renderTo($file . '_path.html'); + } + } + + private function renderItems(FileNode $node): string + { + $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'file_item_branch.html' : 'file_item.html'); + $template = new Template($templateName, '{{', '}}'); + + $methodTemplateName = $this->templatePath . ($this->hasBranchCoverage ? 'method_item_branch.html' : 'method_item.html'); + $methodItemTemplate = new Template( + $methodTemplateName, + '{{', + '}}' + ); + + $items = $this->renderItemTemplate( + $template, + [ + 'name' => 'Total', + 'numClasses' => $node->numberOfClassesAndTraits(), + 'numTestedClasses' => $node->numberOfTestedClassesAndTraits(), + 'numMethods' => $node->numberOfFunctionsAndMethods(), + 'numTestedMethods' => $node->numberOfTestedFunctionsAndMethods(), + 'linesExecutedPercent' => $node->percentageOfExecutedLines()->asFloat(), + 'linesExecutedPercentAsString' => $node->percentageOfExecutedLines()->asString(), + 'numExecutedLines' => $node->numberOfExecutedLines(), + 'numExecutableLines' => $node->numberOfExecutableLines(), + 'branchesExecutedPercent' => $node->percentageOfExecutedBranches()->asFloat(), + 'branchesExecutedPercentAsString' => $node->percentageOfExecutedBranches()->asString(), + 'numExecutedBranches' => $node->numberOfExecutedBranches(), + 'numExecutableBranches' => $node->numberOfExecutableBranches(), + 'pathsExecutedPercent' => $node->percentageOfExecutedPaths()->asFloat(), + 'pathsExecutedPercentAsString' => $node->percentageOfExecutedPaths()->asString(), + 'numExecutedPaths' => $node->numberOfExecutedPaths(), + 'numExecutablePaths' => $node->numberOfExecutablePaths(), + 'testedMethodsPercent' => $node->percentageOfTestedFunctionsAndMethods()->asFloat(), + 'testedMethodsPercentAsString' => $node->percentageOfTestedFunctionsAndMethods()->asString(), + 'testedClassesPercent' => $node->percentageOfTestedClassesAndTraits()->asFloat(), + 'testedClassesPercentAsString' => $node->percentageOfTestedClassesAndTraits()->asString(), + 'crap' => '<abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr>', + ] + ); + + $items .= $this->renderFunctionItems( + $node->functions(), + $methodItemTemplate + ); + + $items .= $this->renderTraitOrClassItems( + $node->traits(), + $template, + $methodItemTemplate + ); + + $items .= $this->renderTraitOrClassItems( + $node->classes(), + $template, + $methodItemTemplate + ); + + return $items; + } + + private function renderTraitOrClassItems(array $items, Template $template, Template $methodItemTemplate): string + { + $buffer = ''; + + if (empty($items)) { + return $buffer; + } + + foreach ($items as $name => $item) { + $numMethods = 0; + $numTestedMethods = 0; + + foreach ($item['methods'] as $method) { + if ($method['executableLines'] > 0) { + $numMethods++; + + if ($method['executedLines'] === $method['executableLines']) { + $numTestedMethods++; + } + } + } + + if ($item['executableLines'] > 0) { + $numClasses = 1; + $numTestedClasses = $numTestedMethods === $numMethods ? 1 : 0; + $linesExecutedPercentAsString = Percentage::fromFractionAndTotal( + $item['executedLines'], + $item['executableLines'] + )->asString(); + $branchesExecutedPercentAsString = Percentage::fromFractionAndTotal( + $item['executedBranches'], + $item['executableBranches'] + )->asString(); + $pathsExecutedPercentAsString = Percentage::fromFractionAndTotal( + $item['executedPaths'], + $item['executablePaths'] + )->asString(); + } else { + $numClasses = 0; + $numTestedClasses = 0; + $linesExecutedPercentAsString = 'n/a'; + $branchesExecutedPercentAsString = 'n/a'; + $pathsExecutedPercentAsString = 'n/a'; + } + + $testedMethodsPercentage = Percentage::fromFractionAndTotal( + $numTestedMethods, + $numMethods + ); + + $testedClassesPercentage = Percentage::fromFractionAndTotal( + $numTestedMethods === $numMethods ? 1 : 0, + 1 + ); + + $buffer .= $this->renderItemTemplate( + $template, + [ + 'name' => $this->abbreviateClassName($name), + 'numClasses' => $numClasses, + 'numTestedClasses' => $numTestedClasses, + 'numMethods' => $numMethods, + 'numTestedMethods' => $numTestedMethods, + 'linesExecutedPercent' => Percentage::fromFractionAndTotal( + $item['executedLines'], + $item['executableLines'], + )->asFloat(), + 'linesExecutedPercentAsString' => $linesExecutedPercentAsString, + 'numExecutedLines' => $item['executedLines'], + 'numExecutableLines' => $item['executableLines'], + 'branchesExecutedPercent' => Percentage::fromFractionAndTotal( + $item['executedBranches'], + $item['executableBranches'], + )->asFloat(), + 'branchesExecutedPercentAsString' => $branchesExecutedPercentAsString, + 'numExecutedBranches' => $item['executedBranches'], + 'numExecutableBranches' => $item['executableBranches'], + 'pathsExecutedPercent' => Percentage::fromFractionAndTotal( + $item['executedPaths'], + $item['executablePaths'] + )->asFloat(), + 'pathsExecutedPercentAsString' => $pathsExecutedPercentAsString, + 'numExecutedPaths' => $item['executedPaths'], + 'numExecutablePaths' => $item['executablePaths'], + 'testedMethodsPercent' => $testedMethodsPercentage->asFloat(), + 'testedMethodsPercentAsString' => $testedMethodsPercentage->asString(), + 'testedClassesPercent' => $testedClassesPercentage->asFloat(), + 'testedClassesPercentAsString' => $testedClassesPercentage->asString(), + 'crap' => $item['crap'], + ] + ); + + foreach ($item['methods'] as $method) { + $buffer .= $this->renderFunctionOrMethodItem( + $methodItemTemplate, + $method, + ' ' + ); + } + } + + return $buffer; + } + + private function renderFunctionItems(array $functions, Template $template): string + { + if (empty($functions)) { + return ''; + } + + $buffer = ''; + + foreach ($functions as $function) { + $buffer .= $this->renderFunctionOrMethodItem( + $template, + $function + ); + } + + return $buffer; + } + + private function renderFunctionOrMethodItem(Template $template, array $item, string $indent = ''): string + { + $numMethods = 0; + $numTestedMethods = 0; + + if ($item['executableLines'] > 0) { + $numMethods = 1; + + if ($item['executedLines'] === $item['executableLines']) { + $numTestedMethods = 1; + } + } + + $executedLinesPercentage = Percentage::fromFractionAndTotal( + $item['executedLines'], + $item['executableLines'] + ); + + $executedBranchesPercentage = Percentage::fromFractionAndTotal( + $item['executedBranches'], + $item['executableBranches'] + ); + + $executedPathsPercentage = Percentage::fromFractionAndTotal( + $item['executedPaths'], + $item['executablePaths'] + ); + + $testedMethodsPercentage = Percentage::fromFractionAndTotal( + $numTestedMethods, + 1 + ); + + return $this->renderItemTemplate( + $template, + [ + 'name' => sprintf( + '%s<a href="#%d"><abbr title="%s">%s</abbr></a>', + $indent, + $item['startLine'], + htmlspecialchars($item['signature'], $this->htmlSpecialCharsFlags), + $item['functionName'] ?? $item['methodName'] + ), + 'numMethods' => $numMethods, + 'numTestedMethods' => $numTestedMethods, + 'linesExecutedPercent' => $executedLinesPercentage->asFloat(), + 'linesExecutedPercentAsString' => $executedLinesPercentage->asString(), + 'numExecutedLines' => $item['executedLines'], + 'numExecutableLines' => $item['executableLines'], + 'branchesExecutedPercent' => $executedBranchesPercentage->asFloat(), + 'branchesExecutedPercentAsString' => $executedBranchesPercentage->asString(), + 'numExecutedBranches' => $item['executedBranches'], + 'numExecutableBranches' => $item['executableBranches'], + 'pathsExecutedPercent' => $executedPathsPercentage->asFloat(), + 'pathsExecutedPercentAsString' => $executedPathsPercentage->asString(), + 'numExecutedPaths' => $item['executedPaths'], + 'numExecutablePaths' => $item['executablePaths'], + 'testedMethodsPercent' => $testedMethodsPercentage->asFloat(), + 'testedMethodsPercentAsString' => $testedMethodsPercentage->asString(), + 'crap' => $item['crap'], + ] + ); + } + + private function renderSourceWithLineCoverage(FileNode $node): string + { + $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); + $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); + + $coverageData = $node->lineCoverageData(); + $testData = $node->testData(); + $codeLines = $this->loadFile($node->pathAsString()); + $lines = ''; + $i = 1; + + foreach ($codeLines as $line) { + $trClass = ''; + $popoverContent = ''; + $popoverTitle = ''; + + if (array_key_exists($i, $coverageData)) { + $numTests = ($coverageData[$i] ? count($coverageData[$i]) : 0); + + if ($coverageData[$i] === null) { + $trClass = 'warning'; + } elseif ($numTests === 0) { + $trClass = 'danger'; + } else { + if ($numTests > 1) { + $popoverTitle = $numTests . ' tests cover line ' . $i; + } else { + $popoverTitle = '1 test covers line ' . $i; + } + + $lineCss = 'covered-by-large-tests'; + $popoverContent = '<ul>'; + + foreach ($coverageData[$i] as $test) { + if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') { + $lineCss = 'covered-by-medium-tests'; + } elseif ($testData[$test]['size'] === 'small') { + $lineCss = 'covered-by-small-tests'; + } + + $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); + } + + $popoverContent .= '</ul>'; + $trClass = $lineCss . ' popin'; + } + } + + $popover = ''; + + if (!empty($popoverTitle)) { + $popover = sprintf( + ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', + $popoverTitle, + htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags) + ); + } + + $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover); + + $i++; + } + + $linesTemplate->setVar(['lines' => $lines]); + + return $linesTemplate->render(); + } + + private function renderSourceWithBranchCoverage(FileNode $node): string + { + $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); + $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); + + $functionCoverageData = $node->functionCoverageData(); + $testData = $node->testData(); + $codeLines = $this->loadFile($node->pathAsString()); + + $lineData = []; + + /** @var int $line */ + foreach (array_keys($codeLines) as $line) { + $lineData[$line + 1] = [ + 'includedInBranches' => 0, + 'includedInHitBranches' => 0, + 'tests' => [], + ]; + } + + foreach ($functionCoverageData as $method) { + foreach ($method['branches'] as $branch) { + foreach (range($branch['line_start'], $branch['line_end']) as $line) { + if (!isset($lineData[$line])) { // blank line at end of file is sometimes included here + continue; + } + + $lineData[$line]['includedInBranches']++; + + if ($branch['hit']) { + $lineData[$line]['includedInHitBranches']++; + $lineData[$line]['tests'] = array_unique(array_merge($lineData[$line]['tests'], $branch['hit'])); + } + } + } + } + + $lines = ''; + $i = 1; + + /** @var string $line */ + foreach ($codeLines as $line) { + $trClass = ''; + $popover = ''; + + if ($lineData[$i]['includedInBranches'] > 0) { + $lineCss = 'success'; + + if ($lineData[$i]['includedInHitBranches'] === 0) { + $lineCss = 'danger'; + } elseif ($lineData[$i]['includedInHitBranches'] !== $lineData[$i]['includedInBranches']) { + $lineCss = 'warning'; + } + + $popoverContent = '<ul>'; + + if (count($lineData[$i]['tests']) === 1) { + $popoverTitle = '1 test covers line ' . $i; + } else { + $popoverTitle = count($lineData[$i]['tests']) . ' tests cover line ' . $i; + } + $popoverTitle .= '. These are covering ' . $lineData[$i]['includedInHitBranches'] . ' out of the ' . $lineData[$i]['includedInBranches'] . ' code branches.'; + + foreach ($lineData[$i]['tests'] as $test) { + $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); + } + + $popoverContent .= '</ul>'; + $trClass = $lineCss . ' popin'; + + $popover = sprintf( + ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', + $popoverTitle, + htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags) + ); + } + + $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover); + + $i++; + } + + $linesTemplate->setVar(['lines' => $lines]); + + return $linesTemplate->render(); + } + + private function renderSourceWithPathCoverage(FileNode $node): string + { + $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); + $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); + + $functionCoverageData = $node->functionCoverageData(); + $testData = $node->testData(); + $codeLines = $this->loadFile($node->pathAsString()); + + $lineData = []; + + /** @var int $line */ + foreach (array_keys($codeLines) as $line) { + $lineData[$line + 1] = [ + 'includedInPaths' => [], + 'includedInHitPaths' => [], + 'tests' => [], + ]; + } + + foreach ($functionCoverageData as $method) { + foreach ($method['paths'] as $pathId => $path) { + foreach ($path['path'] as $branchTaken) { + foreach (range($method['branches'][$branchTaken]['line_start'], $method['branches'][$branchTaken]['line_end']) as $line) { + if (!isset($lineData[$line])) { + continue; + } + $lineData[$line]['includedInPaths'][] = $pathId; + + if ($path['hit']) { + $lineData[$line]['includedInHitPaths'][] = $pathId; + $lineData[$line]['tests'] = array_unique(array_merge($lineData[$line]['tests'], $path['hit'])); + } + } + } + } + } + + $lines = ''; + $i = 1; + + /** @var string $line */ + foreach ($codeLines as $line) { + $trClass = ''; + $popover = ''; + $includedInPathsCount = count(array_unique($lineData[$i]['includedInPaths'])); + $includedInHitPathsCount = count(array_unique($lineData[$i]['includedInHitPaths'])); + + if ($includedInPathsCount > 0) { + $lineCss = 'success'; + + if ($includedInHitPathsCount === 0) { + $lineCss = 'danger'; + } elseif ($includedInHitPathsCount !== $includedInPathsCount) { + $lineCss = 'warning'; + } + + $popoverContent = '<ul>'; + + if (count($lineData[$i]['tests']) === 1) { + $popoverTitle = '1 test covers line ' . $i; + } else { + $popoverTitle = count($lineData[$i]['tests']) . ' tests cover line ' . $i; + } + $popoverTitle .= '. These are covering ' . $includedInHitPathsCount . ' out of the ' . $includedInPathsCount . ' code paths.'; + + foreach ($lineData[$i]['tests'] as $test) { + $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); + } + + $popoverContent .= '</ul>'; + $trClass = $lineCss . ' popin'; + + $popover = sprintf( + ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', + $popoverTitle, + htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags) + ); + } + + $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover); + + $i++; + } + + $linesTemplate->setVar(['lines' => $lines]); + + return $linesTemplate->render(); + } + + private function renderBranchStructure(FileNode $node): string + { + $branchesTemplate = new Template($this->templatePath . 'branches.html.dist', '{{', '}}'); + + $coverageData = $node->functionCoverageData(); + $testData = $node->testData(); + $codeLines = $this->loadFile($node->pathAsString()); + $branches = ''; + + ksort($coverageData); + + foreach ($coverageData as $methodName => $methodData) { + if (!$methodData['branches']) { + continue; + } + + $branchStructure = ''; + + foreach ($methodData['branches'] as $branch) { + $branchStructure .= $this->renderBranchLines($branch, $codeLines, $testData); + } + + if ($branchStructure !== '') { // don't show empty branches + $branches .= '<h5 class="structure-heading"><a name="' . htmlspecialchars($methodName, $this->htmlSpecialCharsFlags) . '">' . $this->abbreviateMethodName($methodName) . '</a></h5>' . "\n"; + $branches .= $branchStructure; + } + } + + $branchesTemplate->setVar(['branches' => $branches]); + + return $branchesTemplate->render(); + } + + private function renderBranchLines(array $branch, array $codeLines, array $testData): string + { + $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); + $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); + + $lines = ''; + + $branchLines = range($branch['line_start'], $branch['line_end']); + sort($branchLines); // sometimes end_line < start_line + + /** @var int $line */ + foreach ($branchLines as $line) { + if (!isset($codeLines[$line])) { // blank line at end of file is sometimes included here + continue; + } + + $popoverContent = ''; + $popoverTitle = ''; + + $numTests = count($branch['hit']); + + if ($numTests === 0) { + $trClass = 'danger'; + } else { + $lineCss = 'covered-by-large-tests'; + $popoverContent = '<ul>'; + + if ($numTests > 1) { + $popoverTitle = $numTests . ' tests cover this branch'; + } else { + $popoverTitle = '1 test covers this branch'; + } + + foreach ($branch['hit'] as $test) { + if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') { + $lineCss = 'covered-by-medium-tests'; + } elseif ($testData[$test]['size'] === 'small') { + $lineCss = 'covered-by-small-tests'; + } + + $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); + } + $trClass = $lineCss . ' popin'; + } + + $popover = ''; + + if (!empty($popoverTitle)) { + $popover = sprintf( + ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', + $popoverTitle, + htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags) + ); + } + + $lines .= $this->renderLine($singleLineTemplate, $line, $codeLines[$line - 1], $trClass, $popover); + } + + if ($lines === '') { + return ''; + } + + $linesTemplate->setVar(['lines' => $lines]); + + return $linesTemplate->render(); + } + + private function renderPathStructure(FileNode $node): string + { + $pathsTemplate = new Template($this->templatePath . 'paths.html.dist', '{{', '}}'); + + $coverageData = $node->functionCoverageData(); + $testData = $node->testData(); + $codeLines = $this->loadFile($node->pathAsString()); + $paths = ''; + + ksort($coverageData); + + foreach ($coverageData as $methodName => $methodData) { + if (!$methodData['paths']) { + continue; + } + + $pathStructure = ''; + + if (count($methodData['paths']) > 100) { + $pathStructure .= '<p>' . count($methodData['paths']) . ' is too many paths to sensibly render, consider refactoring your code to bring this number down.</p>'; + + continue; + } + + foreach ($methodData['paths'] as $path) { + $pathStructure .= $this->renderPathLines($path, $methodData['branches'], $codeLines, $testData); + } + + if ($pathStructure !== '') { + $paths .= '<h5 class="structure-heading"><a name="' . htmlspecialchars($methodName, $this->htmlSpecialCharsFlags) . '">' . $this->abbreviateMethodName($methodName) . '</a></h5>' . "\n"; + $paths .= $pathStructure; + } + } + + $pathsTemplate->setVar(['paths' => $paths]); + + return $pathsTemplate->render(); + } + + private function renderPathLines(array $path, array $branches, array $codeLines, array $testData): string + { + $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); + $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); + + $lines = ''; + $first = true; + + foreach ($path['path'] as $branchId) { + if ($first) { + $first = false; + } else { + $lines .= ' <tr><td colspan="2"> </td></tr>' . "\n"; + } + + $branchLines = range($branches[$branchId]['line_start'], $branches[$branchId]['line_end']); + sort($branchLines); // sometimes end_line < start_line + + /** @var int $line */ + foreach ($branchLines as $line) { + if (!isset($codeLines[$line])) { // blank line at end of file is sometimes included here + continue; + } + + $popoverContent = ''; + $popoverTitle = ''; + + $numTests = count($path['hit']); + + if ($numTests === 0) { + $trClass = 'danger'; + } else { + $lineCss = 'covered-by-large-tests'; + $popoverContent = '<ul>'; + + if ($numTests > 1) { + $popoverTitle = $numTests . ' tests cover this path'; + } else { + $popoverTitle = '1 test covers this path'; + } + + foreach ($path['hit'] as $test) { + if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') { + $lineCss = 'covered-by-medium-tests'; + } elseif ($testData[$test]['size'] === 'small') { + $lineCss = 'covered-by-small-tests'; + } + + $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); + } + + $trClass = $lineCss . ' popin'; + } + + $popover = ''; + + if (!empty($popoverTitle)) { + $popover = sprintf( + ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', + $popoverTitle, + htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags) + ); + } + + $lines .= $this->renderLine($singleLineTemplate, $line, $codeLines[$line - 1], $trClass, $popover); + } + } + + if ($lines === '') { + return ''; + } + + $linesTemplate->setVar(['lines' => $lines]); + + return $linesTemplate->render(); + } + + private function renderLine(Template $template, int $lineNumber, string $lineContent, string $class, string $popover): string + { + $template->setVar( + [ + 'lineNumber' => $lineNumber, + 'lineContent' => $lineContent, + 'class' => $class, + 'popover' => $popover, + ] + ); + + return $template->render(); + } + + private function loadFile(string $file): array + { + if (isset(self::$formattedSourceCache[$file])) { + return self::$formattedSourceCache[$file]; + } + + $buffer = file_get_contents($file); + $tokens = token_get_all($buffer); + $result = ['']; + $i = 0; + $stringFlag = false; + $fileEndsWithNewLine = substr($buffer, -1) === "\n"; + + unset($buffer); + + foreach ($tokens as $j => $token) { + if (is_string($token)) { + if ($token === '"' && $tokens[$j - 1] !== '\\') { + $result[$i] .= sprintf( + '<span class="string">%s</span>', + htmlspecialchars($token, $this->htmlSpecialCharsFlags) + ); + + $stringFlag = !$stringFlag; + } else { + $result[$i] .= sprintf( + '<span class="keyword">%s</span>', + htmlspecialchars($token, $this->htmlSpecialCharsFlags) + ); + } + + continue; + } + + [$token, $value] = $token; + + $value = str_replace( + ["\t", ' '], + ['    ', ' '], + htmlspecialchars($value, $this->htmlSpecialCharsFlags) + ); + + if ($value === "\n") { + $result[++$i] = ''; + } else { + $lines = explode("\n", $value); + + foreach ($lines as $jj => $line) { + $line = trim($line); + + if ($line !== '') { + if ($stringFlag) { + $colour = 'string'; + } else { + $colour = 'default'; + + if ($this->isInlineHtml($token)) { + $colour = 'html'; + } elseif ($this->isComment($token)) { + $colour = 'comment'; + } elseif ($this->isKeyword($token)) { + $colour = 'keyword'; + } + } + + $result[$i] .= sprintf( + '<span class="%s">%s</span>', + $colour, + $line + ); + } + + if (isset($lines[$jj + 1])) { + $result[++$i] = ''; + } + } + } + } + + if ($fileEndsWithNewLine) { + unset($result[count($result) - 1]); + } + + self::$formattedSourceCache[$file] = $result; + + return $result; + } + + private function abbreviateClassName(string $className): string + { + $tmp = explode('\\', $className); + + if (count($tmp) > 1) { + $className = sprintf( + '<abbr title="%s">%s</abbr>', + $className, + array_pop($tmp) + ); + } + + return $className; + } + + private function abbreviateMethodName(string $methodName): string + { + $parts = explode('->', $methodName); + + if (count($parts) === 2) { + return $this->abbreviateClassName($parts[0]) . '->' . $parts[1]; + } + + return $methodName; + } + + private function createPopoverContentForTest(string $test, array $testData): string + { + $testCSS = ''; + + if ($testData['fromTestcase']) { + switch ($testData['status']) { + case BaseTestRunner::STATUS_PASSED: + switch ($testData['size']) { + case 'small': + $testCSS = ' class="covered-by-small-tests"'; + + break; + + case 'medium': + $testCSS = ' class="covered-by-medium-tests"'; + + break; + + default: + $testCSS = ' class="covered-by-large-tests"'; + + break; + } + + break; + + case BaseTestRunner::STATUS_SKIPPED: + case BaseTestRunner::STATUS_INCOMPLETE: + case BaseTestRunner::STATUS_RISKY: + case BaseTestRunner::STATUS_WARNING: + $testCSS = ' class="warning"'; + + break; + + case BaseTestRunner::STATUS_FAILURE: + case BaseTestRunner::STATUS_ERROR: + $testCSS = ' class="danger"'; + + break; + } + } + + return sprintf( + '<li%s>%s</li>', + $testCSS, + htmlspecialchars($test, $this->htmlSpecialCharsFlags) + ); + } + + private function isComment(int $token): bool + { + return $token === T_COMMENT || $token === T_DOC_COMMENT; + } + + private function isInlineHtml(int $token): bool + { + return $token === T_INLINE_HTML; + } + + private function isKeyword(int $token): bool + { + return isset(self::keywordTokens()[$token]); + } + + /** + * @psalm-return array<int,true> + */ + private static function keywordTokens(): array + { + if (self::$keywordTokens !== []) { + return self::$keywordTokens; + } + + self::$keywordTokens = [ + T_ABSTRACT => true, + T_ARRAY => true, + T_AS => true, + T_BREAK => true, + T_CALLABLE => true, + T_CASE => true, + T_CATCH => true, + T_CLASS => true, + T_CLONE => true, + T_CONST => true, + T_CONTINUE => true, + T_DECLARE => true, + T_DEFAULT => true, + T_DO => true, + T_ECHO => true, + T_ELSE => true, + T_ELSEIF => true, + T_EMPTY => true, + T_ENDDECLARE => true, + T_ENDFOR => true, + T_ENDFOREACH => true, + T_ENDIF => true, + T_ENDSWITCH => true, + T_ENDWHILE => true, + T_EVAL => true, + T_EXIT => true, + T_EXTENDS => true, + T_FINAL => true, + T_FINALLY => true, + T_FOR => true, + T_FOREACH => true, + T_FUNCTION => true, + T_GLOBAL => true, + T_GOTO => true, + T_HALT_COMPILER => true, + T_IF => true, + T_IMPLEMENTS => true, + T_INCLUDE => true, + T_INCLUDE_ONCE => true, + T_INSTANCEOF => true, + T_INSTEADOF => true, + T_INTERFACE => true, + T_ISSET => true, + T_LIST => true, + T_NAMESPACE => true, + T_NEW => true, + T_PRINT => true, + T_PRIVATE => true, + T_PROTECTED => true, + T_PUBLIC => true, + T_REQUIRE => true, + T_REQUIRE_ONCE => true, + T_RETURN => true, + T_STATIC => true, + T_SWITCH => true, + T_THROW => true, + T_TRAIT => true, + T_TRY => true, + T_UNSET => true, + T_USE => true, + T_VAR => true, + T_WHILE => true, + T_YIELD => true, + T_YIELD_FROM => true, + ]; + + if (defined('T_FN')) { + self::$keywordTokens[constant('T_FN')] = true; + } + + if (defined('T_MATCH')) { + self::$keywordTokens[constant('T_MATCH')] = true; + } + + if (defined('T_ENUM')) { + self::$keywordTokens[constant('T_ENUM')] = true; + } + + if (defined('T_READONLY')) { + self::$keywordTokens[constant('T_READONLY')] = true; + } + + return self::$keywordTokens; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/branches.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/branches.html.dist new file mode 100644 index 00000000..54770262 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/branches.html.dist @@ -0,0 +1,9 @@ +<hr/> +<h4>Branches</h4> +<p> + Below are the source code lines that represent each code branch as identified by Xdebug. Please note a branch is not + necessarily coterminous with a line, a line may contain multiple branches and therefore show up more than once. + Please also be aware that some branches may be implicit rather than explicit, e.g. an <code>if</code> statement + <i>always</i> has an <code>else</code> as part of its logical flow even if you didn't write one. +</p> +{{branches}} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar.html.dist new file mode 100644 index 00000000..7fcf6f49 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar.html.dist @@ -0,0 +1,5 @@ + <div class="progress"> + <div class="progress-bar bg-{{level}}" role="progressbar" aria-valuenow="{{percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{percent}}%"> + <span class="sr-only">{{percent}}% covered ({{level}})</span> + </div> + </div> diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar_branch.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar_branch.html.dist new file mode 100644 index 00000000..7fcf6f49 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar_branch.html.dist @@ -0,0 +1,5 @@ + <div class="progress"> + <div class="progress-bar bg-{{level}}" role="progressbar" aria-valuenow="{{percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{percent}}%"> + <span class="sr-only">{{percent}}% covered ({{level}})</span> + </div> + </div> diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/bootstrap.min.css b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/bootstrap.min.css new file mode 100644 index 00000000..83a71b1f --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/bootstrap.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap v4.6.2 (https://getbootstrap.com/) + * Copyright 2011-2022 The Bootstrap Authors + * Copyright 2011-2022 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:.875em;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-sm-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-sm-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-md-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-md-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-lg-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-lg-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-xl-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-xl-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#28a745}.valid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.form-row>.col>.valid-tooltip,.form-row>[class*=col-]>.valid-tooltip{left:5px}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem)!important;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated select.form-control:valid,select.form-control.is-valid{padding-right:3rem!important;background-position:right 1.5rem center}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem)!important;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.form-row>.col>.invalid-tooltip,.form-row>[class*=col-]>.invalid-tooltip{left:5px}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem)!important;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated select.form-control:invalid,select.form-control.is-invalid{padding-right:3rem!important;background-position:right 1.5rem center}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem)!important;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#0069d9;border-color:#0062cc;box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{color:#fff;background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#218838;border-color:#1e7e34;box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{color:#212529;background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{color:#fff;background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.width{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion:reduce){.collapsing.width{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#e9ecef}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#adb5bd;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;min-width:0;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label,.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label::after,.input-group:not(.has-validation)>.custom-select:not(:last-child),.input-group:not(.has-validation)>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label,.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label::after,.input-group.has-validation>.custom-select:nth-last-child(n+3),.input-group.has-validation>.form-control:nth-last-child(n+3){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.btn,.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.input-group-text,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;z-index:1;display:block;min-height:1.5rem;padding-left:1.5rem;-webkit-print-color-adjust:exact;color-adjust:exact;print-color-adjust:exact}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before,.custom-control-input[disabled]~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:1px solid #adb5bd}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:50%/50% 50% no-repeat}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;overflow:hidden;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;overflow:hidden;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{margin-bottom:-1px;background-color:transparent;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{isolation:isolate;border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{background:0 0;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item,.nav-fill>.nav-link{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:50%/100% 100% no-repeat}.navbar-nav-scroll{max-height:75vh;overflow-y:auto}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem;border-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom,.card-img-top{-ms-flex-negative:0;flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;z-index:2;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;line-height:0;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:1s linear infinite progress-bar-stripes;animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0}a.close.disabled{pointer-events:none}.toast{-ms-flex-preferred-size:350px;flex-basis:350px;max-width:350px;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal.modal-static .modal-dialog{-webkit-transform:scale(1.02);transform:scale(1.02)}.modal-dialog-scrollable{display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);height:-webkit-min-content;height:-moz-min-content;height:min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem);height:-webkit-min-content;height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow::before,.bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow::after,.bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow::before,.bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow::after,.bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow::before,.bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow::after,.bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow::before,.bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow::after,.bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:50%/100% 100% no-repeat}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;border:.25em solid currentcolor;border-right-color:transparent;border-radius:50%;-webkit-animation:.75s linear infinite spinner-border;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;background-color:currentcolor;border-radius:50%;opacity:0;-webkit-animation:.75s linear infinite spinner-grow;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{-webkit-animation-duration:1.5s;animation-duration:1.5s}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-break:break-word!important;word-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/custom.css b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/custom.css new file mode 100644 index 00000000..e69de29b diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/nv.d3.min.css b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/nv.d3.min.css new file mode 100644 index 00000000..7a6f7fe9 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/nv.d3.min.css @@ -0,0 +1 @@ +.nvd3 .nv-axis{pointer-events:none;opacity:1}.nvd3 .nv-axis path{fill:none;stroke:#000;stroke-opacity:.75;shape-rendering:crispEdges}.nvd3 .nv-axis path.domain{stroke-opacity:.75}.nvd3 .nv-axis.nv-x path.domain{stroke-opacity:0}.nvd3 .nv-axis line{fill:none;stroke:#e5e5e5;shape-rendering:crispEdges}.nvd3 .nv-axis .zero line,.nvd3 .nv-axis line.zero{stroke-opacity:.75}.nvd3 .nv-axis .nv-axisMaxMin text{font-weight:700}.nvd3 .x .nv-axis .nv-axisMaxMin text,.nvd3 .x2 .nv-axis .nv-axisMaxMin text,.nvd3 .x3 .nv-axis .nv-axisMaxMin text{text-anchor:middle}.nvd3 .nv-axis.nv-disabled{opacity:0}.nvd3 .nv-bars rect{fill-opacity:.75;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-bars rect.hover{fill-opacity:1}.nvd3 .nv-bars .hover rect{fill:#add8e6}.nvd3 .nv-bars text{fill:rgba(0,0,0,0)}.nvd3 .nv-bars .hover text{fill:rgba(0,0,0,1)}.nvd3 .nv-multibar .nv-groups rect,.nvd3 .nv-multibarHorizontal .nv-groups rect,.nvd3 .nv-discretebar .nv-groups rect{stroke-opacity:0;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-multibar .nv-groups rect:hover,.nvd3 .nv-multibarHorizontal .nv-groups rect:hover,.nvd3 .nv-candlestickBar .nv-ticks rect:hover,.nvd3 .nv-discretebar .nv-groups rect:hover{fill-opacity:1}.nvd3 .nv-discretebar .nv-groups text,.nvd3 .nv-multibarHorizontal .nv-groups text{font-weight:700;fill:rgba(0,0,0,1);stroke:rgba(0,0,0,0)}.nvd3 .nv-boxplot circle{fill-opacity:.5}.nvd3 .nv-boxplot circle:hover{fill-opacity:1}.nvd3 .nv-boxplot rect:hover{fill-opacity:1}.nvd3 line.nv-boxplot-median{stroke:#000}.nv-boxplot-tick:hover{stroke-width:2.5px}.nvd3.nv-bullet{font:10px sans-serif}.nvd3.nv-bullet .nv-measure{fill-opacity:.8}.nvd3.nv-bullet .nv-measure:hover{fill-opacity:1}.nvd3.nv-bullet .nv-marker{stroke:#000;stroke-width:2px}.nvd3.nv-bullet .nv-markerTriangle{stroke:#000;fill:#fff;stroke-width:1.5px}.nvd3.nv-bullet .nv-tick line{stroke:#666;stroke-width:.5px}.nvd3.nv-bullet .nv-range.nv-s0{fill:#eee}.nvd3.nv-bullet .nv-range.nv-s1{fill:#ddd}.nvd3.nv-bullet .nv-range.nv-s2{fill:#ccc}.nvd3.nv-bullet .nv-title{font-size:14px;font-weight:700}.nvd3.nv-bullet .nv-subtitle{fill:#999}.nvd3.nv-bullet .nv-range{fill:#bababa;fill-opacity:.4}.nvd3.nv-bullet .nv-range:hover{fill-opacity:.7}.nvd3.nv-candlestickBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect{stroke:#d62728;fill:#d62728}.with-transitions .nv-candlestickBar .nv-ticks .nv-tick{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-candlestickBar .nv-ticks line{stroke:#333}.nvd3 .nv-legend .nv-disabled rect{}.nvd3 .nv-check-box .nv-box{fill-opacity:0;stroke-width:2}.nvd3 .nv-check-box .nv-check{fill-opacity:0;stroke-width:4}.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check{opacity:0}.nvd3.nv-linePlusBar .nv-bar rect{fill-opacity:.75}.nvd3.nv-linePlusBar .nv-bar rect:hover{fill-opacity:1}.nvd3 .nv-groups path.nv-line{fill:none}.nvd3 .nv-groups path.nv-area{stroke:none}.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point{fill-opacity:0;stroke-opacity:0}.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point{fill-opacity:.5!important;stroke-opacity:.5!important}.with-transitions .nvd3 .nv-groups .nv-point{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-scatter .nv-groups .nv-point.hover,.nvd3 .nv-groups .nv-point.hover{stroke-width:7px;fill-opacity:.95!important;stroke-opacity:.95!important}.nvd3 .nv-point-paths path{stroke:#aaa;stroke-opacity:0;fill:#eee;fill-opacity:0}.nvd3 .nv-indexLine{cursor:ew-resize}svg.nvd3-svg{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-ms-user-select:none;-moz-user-select:none;user-select:none;display:block;width:100%;height:100%}.nvtooltip.with-3d-shadow,.with-3d-shadow .nvtooltip{-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nvd3 text{font:400 12px Arial}.nvd3 .title{font:700 14px Arial}.nvd3 .nv-background{fill:#fff;fill-opacity:0}.nvd3.nv-noData{font-size:18px;font-weight:700}.nv-brush .extent{fill-opacity:.125;shape-rendering:crispEdges}.nv-brush .resize path{fill:#eee;stroke:#666}.nvd3 .nv-legend .nv-series{cursor:pointer}.nvd3 .nv-legend .nv-disabled circle{fill-opacity:0}.nvd3 .nv-brush .extent{fill-opacity:0!important}.nvd3 .nv-brushBackground rect{stroke:#000;stroke-width:.4;fill:#fff;fill-opacity:.7}.nvd3.nv-ohlcBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive{stroke:#2ca02c}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative{stroke:#d62728}.nvd3 .background path{fill:none;stroke:#EEE;stroke-opacity:.4;shape-rendering:crispEdges}.nvd3 .foreground path{fill:none;stroke-opacity:.7}.nvd3 .nv-parallelCoordinates-brush .extent{fill:#fff;fill-opacity:.6;stroke:gray;shape-rendering:crispEdges}.nvd3 .nv-parallelCoordinates .hover{fill-opacity:1;stroke-width:3px}.nvd3 .missingValuesline line{fill:none;stroke:#000;stroke-width:1;stroke-opacity:1;stroke-dasharray:5,5}.nvd3.nv-pie path{stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-pie .nv-pie-title{font-size:24px;fill:rgba(19,196,249,.59)}.nvd3.nv-pie .nv-slice text{stroke:#000;stroke-width:0}.nvd3.nv-pie path{stroke:#fff;stroke-width:1px;stroke-opacity:1}.nvd3.nv-pie .hover path{fill-opacity:.7}.nvd3.nv-pie .nv-label{pointer-events:none}.nvd3.nv-pie .nv-label rect{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-groups .nv-point.hover{stroke-width:20px;stroke-opacity:.5}.nvd3 .nv-scatter .nv-point.hover{fill-opacity:1}.nv-noninteractive{pointer-events:none}.nv-distx,.nv-disty{pointer-events:none}.nvd3.nv-sparkline path{fill:none}.nvd3.nv-sparklineplus g.nv-hoverValue{pointer-events:none}.nvd3.nv-sparklineplus .nv-hoverValue line{stroke:#333;stroke-width:1.5px}.nvd3.nv-sparklineplus,.nvd3.nv-sparklineplus g{pointer-events:all}.nvd3 .nv-hoverArea{fill-opacity:0;stroke-opacity:0}.nvd3.nv-sparklineplus .nv-xValue,.nvd3.nv-sparklineplus .nv-yValue{stroke-width:0;font-size:.9em;font-weight:400}.nvd3.nv-sparklineplus .nv-yValue{stroke:#f66}.nvd3.nv-sparklineplus .nv-maxValue{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-sparklineplus .nv-minValue{stroke:#d62728;fill:#d62728}.nvd3.nv-sparklineplus .nv-currentValue{font-weight:700;font-size:1.1em}.nvd3.nv-stackedarea path.nv-area{fill-opacity:.7;stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-stackedarea path.nv-area.hover{fill-opacity:.9}.nvd3.nv-stackedarea .nv-groups .nv-point{stroke-opacity:0;fill-opacity:0}.nvtooltip{position:absolute;background-color:rgba(255,255,255,1);color:rgba(0,0,0,1);padding:1px;border:1px solid rgba(0,0,0,.2);z-index:10000;display:block;font-family:Arial;font-size:13px;text-align:left;pointer-events:none;white-space:nowrap;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.nvtooltip{background:rgba(255,255,255,.8);border:1px solid rgba(0,0,0,.5);border-radius:4px}.nvtooltip.with-transitions,.with-transitions .nvtooltip{transition:opacity 50ms linear;-moz-transition:opacity 50ms linear;-webkit-transition:opacity 50ms linear;transition-delay:200ms;-moz-transition-delay:200ms;-webkit-transition-delay:200ms}.nvtooltip.x-nvtooltip,.nvtooltip.y-nvtooltip{padding:8px}.nvtooltip h3{margin:0;padding:4px 14px;line-height:18px;font-weight:400;background-color:rgba(247,247,247,.75);color:rgba(0,0,0,1);text-align:center;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.nvtooltip p{margin:0;padding:5px 14px;text-align:center}.nvtooltip span{display:inline-block;margin:2px 0}.nvtooltip table{margin:6px;border-spacing:0}.nvtooltip table td{padding:2px 9px 2px 0;vertical-align:middle}.nvtooltip table td.key{font-weight:400}.nvtooltip table td.value{text-align:right;font-weight:700}.nvtooltip table tr.highlight td{padding:1px 9px 1px 0;border-bottom-style:solid;border-bottom-width:1px;border-top-style:solid;border-top-width:1px}.nvtooltip table td.legend-color-guide div{width:8px;height:8px;vertical-align:middle}.nvtooltip table td.legend-color-guide div{width:12px;height:12px;border:1px solid #999}.nvtooltip .footer{padding:3px;text-align:center}.nvtooltip-pending-removal{pointer-events:none;display:none}.nvd3 .nv-interactiveGuideLine{pointer-events:none}.nvd3 line.nv-guideline{stroke:#ccc} \ No newline at end of file diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/octicons.css b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/octicons.css new file mode 100644 index 00000000..31d97867 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/octicons.css @@ -0,0 +1,5 @@ +.octicon { + display: inline-block; + vertical-align: text-top; + fill: currentColor; +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/style.css b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/style.css new file mode 100644 index 00000000..5dc62ccf --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/style.css @@ -0,0 +1,130 @@ +body { + font-family: sans-serif; + font-size: 1em; + font-kerning: normal; + font-variant-ligatures: common-ligatures; + text-rendering: optimizeLegibility; + padding-top: 10px; +} + +.popover { + max-width: none; +} + +.octicon { + margin-right:.25em; + vertical-align: baseline; + width: 0.75em; +} + +.table-bordered>thead>tr>td { + border-bottom-width: 1px; +} + +.table tbody>tr>td, .table thead>tr>td { + padding-top: 3px; + padding-bottom: 3px; +} + +.table-condensed tbody>tr>td { + padding-top: 0; + padding-bottom: 0; +} + +.table .progress { + margin-bottom: inherit; +} + +.table-borderless th, .table-borderless td { + border: 0 !important; +} + +.table tbody tr.covered-by-large-tests, li.covered-by-large-tests, tr.success, td.success, li.success, span.success { + background-color: #dff0d8; +} + +.table tbody tr.covered-by-medium-tests, li.covered-by-medium-tests { + background-color: #c3e3b5; +} + +.table tbody tr.covered-by-small-tests, li.covered-by-small-tests { + background-color: #99cb84; +} + +.table tbody tr.danger, .table tbody td.danger, li.danger, span.danger { + background-color: #f2dede; +} + +.table tbody tr.warning, .table tbody td.warning, li.warning, span.warning { + background-color: #fcf8e3; +} + +.table tbody td.info { + background-color: #d9edf7; +} + +td.big { + vertical-align: middle; + width: 117px; +} + +td.small { +} + +td.codeLine { + font-family: "Source Code Pro", "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + white-space: pre-wrap; +} + +td span.comment { + color: #888a85; +} + +td span.default { + color: #2e3436; +} + +td span.html { + color: #888a85; +} + +td span.keyword { + color: #2e3436; + font-weight: bold; +} + +pre span.string { + color: #2e3436; +} + +span.success, span.warning, span.danger { + margin-right: 2px; + padding-left: 10px; + padding-right: 10px; + text-align: center; +} + +#toplink { + position: fixed; + left: 5px; + bottom: 5px; + outline: 0; +} + +svg text { + font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif; + font-size: 11px; + color: #666; + fill: #666; +} + +.scrollbox { + height:245px; + overflow-x:hidden; + overflow-y:scroll; +} + +table + .structure-heading { + border-top: 1px solid lightgrey; + padding-top: 0.5em; +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard.html.dist new file mode 100644 index 00000000..60e66d5b --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard.html.dist @@ -0,0 +1,281 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8"> + <title>Dashboard for {{full_path}} + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +
    +
    +

    Coverage Distribution

    +
    + +
    +
    +
    +

    Complexity

    +
    + +
    +
    +
    +
    +
    +

    Insufficient Coverage

    +
    + + + + + + + + +{{insufficient_coverage_classes}} + +
    ClassCoverage
    +
    +
    +
    +

    Project Risks

    +
    + + + + + + + + +{{project_risks_classes}} + +
    ClassCRAP
    +
    +
    +
    +
    +
    +

    Methods

    +
    +
    +
    +
    +

    Coverage Distribution

    +
    + +
    +
    +
    +

    Complexity

    +
    + +
    +
    +
    +
    +
    +

    Insufficient Coverage

    +
    + + + + + + + + +{{insufficient_coverage_methods}} + +
    MethodCoverage
    +
    +
    +
    +

    Project Risks

    +
    + + + + + + + + +{{project_risks_methods}} + +
    MethodCRAP
    +
    +
    +
    + +
    + + + + + + diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard_branch.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard_branch.html.dist new file mode 100644 index 00000000..60e66d5b --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard_branch.html.dist @@ -0,0 +1,281 @@ + + + + + Dashboard for {{full_path}} + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +
    +
    +

    Coverage Distribution

    +
    + +
    +
    +
    +

    Complexity

    +
    + +
    +
    +
    +
    +
    +

    Insufficient Coverage

    +
    + + + + + + + + +{{insufficient_coverage_classes}} + +
    ClassCoverage
    +
    +
    +
    +

    Project Risks

    +
    + + + + + + + + +{{project_risks_classes}} + +
    ClassCRAP
    +
    +
    +
    +
    +
    +

    Methods

    +
    +
    +
    +
    +

    Coverage Distribution

    +
    + +
    +
    +
    +

    Complexity

    +
    + +
    +
    +
    +
    +
    +

    Insufficient Coverage

    +
    + + + + + + + + +{{insufficient_coverage_methods}} + +
    MethodCoverage
    +
    +
    +
    +

    Project Risks

    +
    + + + + + + + + +{{project_risks_methods}} + +
    MethodCRAP
    +
    +
    +
    + +
    + + + + + + diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory.html.dist new file mode 100644 index 00000000..f769d2ca --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory.html.dist @@ -0,0 +1,60 @@ + + + + + Code Coverage for {{full_path}} + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + +{{items}} + +
     
    Code Coverage
     
    Lines
    Functions and Methods
    Classes and Traits
    +
    +
    +
    +

    Legend

    +

    + Low: 0% to {{low_upper_bound}}% + Medium: {{low_upper_bound}}% to {{high_lower_bound}}% + High: {{high_lower_bound}}% to 100% +

    +

    + Generated by php-code-coverage {{version}} using {{runtime}}{{generator}} at {{date}}. +

    +
    +
    + + diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_branch.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_branch.html.dist new file mode 100644 index 00000000..a40c2e12 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_branch.html.dist @@ -0,0 +1,62 @@ + + + + + Code Coverage for {{full_path}} + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + +{{items}} + +
     
    Code Coverage
     
    Lines
    Branches
    Paths
    Functions and Methods
    Classes and Traits
    +
    +
    +
    +

    Legend

    +

    + Low: 0% to {{low_upper_bound}}% + Medium: {{low_upper_bound}}% to {{high_lower_bound}}% + High: {{high_lower_bound}}% to 100% +

    +

    + Generated by php-code-coverage {{version}} using {{runtime}}{{generator}} at {{date}}. +

    +
    +
    + + diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item.html.dist new file mode 100644 index 00000000..f6941a43 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item.html.dist @@ -0,0 +1,13 @@ + + {{icon}}{{name}} + {{lines_bar}} +
    {{lines_executed_percent}}
    +
    {{lines_number}}
    + {{methods_bar}} +
    {{methods_tested_percent}}
    +
    {{methods_number}}
    + {{classes_bar}} +
    {{classes_tested_percent}}
    +
    {{classes_number}}
    + + diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item_branch.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item_branch.html.dist new file mode 100644 index 00000000..532a436c --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item_branch.html.dist @@ -0,0 +1,19 @@ + + {{icon}}{{name}} + {{lines_bar}} +
    {{lines_executed_percent}}
    +
    {{lines_number}}
    + {{branches_bar}} +
    {{branches_executed_percent}}
    +
    {{branches_number}}
    + {{paths_bar}} +
    {{paths_executed_percent}}
    +
    {{paths_number}}
    + {{methods_bar}} +
    {{methods_tested_percent}}
    +
    {{methods_number}}
    + {{classes_bar}} +
    {{classes_tested_percent}}
    +
    {{classes_number}}
    + + diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file.html.dist new file mode 100644 index 00000000..a022f5c2 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file.html.dist @@ -0,0 +1,65 @@ + + + + + Code Coverage for {{full_path}} + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + +{{items}} + +
     
    Code Coverage
     
    Lines
    Functions and Methods
    Classes and Traits
    +
    +{{lines}} +{{structure}} + +
    + + + + + + diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_branch.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_branch.html.dist new file mode 100644 index 00000000..f48ebf12 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_branch.html.dist @@ -0,0 +1,67 @@ + + + + + Code Coverage for {{full_path}} + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + +{{items}} + +
     
    Code Coverage
     
    Lines
    Branches
    Paths
    Functions and Methods
    Classes and Traits
    +
    +{{lines}} +{{structure}} + +
    + + + + + + diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item.html.dist new file mode 100644 index 00000000..b1c0fca4 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item.html.dist @@ -0,0 +1,14 @@ + + {{name}} + {{lines_bar}} +
    {{lines_executed_percent}}
    +
    {{lines_number}}
    + {{methods_bar}} +
    {{methods_tested_percent}}
    +
    {{methods_number}}
    + {{crap}} + {{classes_bar}} +
    {{classes_tested_percent}}
    +
    {{classes_number}}
    + + diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item_branch.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item_branch.html.dist new file mode 100644 index 00000000..50502517 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item_branch.html.dist @@ -0,0 +1,20 @@ + + {{name}} + {{lines_bar}} +
    {{lines_executed_percent}}
    +
    {{lines_number}}
    + {{branches_bar}} +
    {{branches_executed_percent}}
    +
    {{branches_number}}
    + {{paths_bar}} +
    {{paths_executed_percent}}
    +
    {{paths_number}}
    + {{methods_bar}} +
    {{methods_tested_percent}}
    +
    {{methods_number}}
    + {{crap}} + {{classes_bar}} +
    {{classes_tested_percent}}
    +
    {{classes_number}}
    + + diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-code.svg b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-code.svg new file mode 100644 index 00000000..5b4b1995 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-directory.svg b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-directory.svg new file mode 100644 index 00000000..4bf1f1ca --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-directory.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/bootstrap.min.js b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/bootstrap.min.js new file mode 100644 index 00000000..97206dcd --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v4.6.2 (https://getbootstrap.com/) + * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap={},t.jQuery,t.Popper)}(this,(function(t,e,n){"use strict";function i(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var o=i(e),a=i(n);function s(t,e){for(var n=0;n=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};d.jQueryDetection(),o.default.fn.emulateTransitionEnd=function(t){var e=this,n=!1;return o.default(this).one(d.TRANSITION_END,(function(){n=!0})),setTimeout((function(){n||d.triggerTransitionEnd(e)}),t),this},o.default.event.special[d.TRANSITION_END]={bindType:f,delegateType:f,handle:function(t){if(o.default(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var c="bs.alert",h=o.default.fn.alert,g=function(){function t(t){this._element=t}var e=t.prototype;return e.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},e.dispose=function(){o.default.removeData(this._element,c),this._element=null},e._getRootElement=function(t){var e=d.getSelectorFromElement(t),n=!1;return e&&(n=document.querySelector(e)),n||(n=o.default(t).closest(".alert")[0]),n},e._triggerCloseEvent=function(t){var e=o.default.Event("close.bs.alert");return o.default(t).trigger(e),e},e._removeElement=function(t){var e=this;if(o.default(t).removeClass("show"),o.default(t).hasClass("fade")){var n=d.getTransitionDurationFromElement(t);o.default(t).one(d.TRANSITION_END,(function(n){return e._destroyElement(t,n)})).emulateTransitionEnd(n)}else this._destroyElement(t)},e._destroyElement=function(t){o.default(t).detach().trigger("closed.bs.alert").remove()},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(c);i||(i=new t(this),n.data(c,i)),"close"===e&&i[e](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}}]),t}();o.default(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',g._handleDismiss(new g)),o.default.fn.alert=g._jQueryInterface,o.default.fn.alert.Constructor=g,o.default.fn.alert.noConflict=function(){return o.default.fn.alert=h,g._jQueryInterface};var m="bs.button",p=o.default.fn.button,_="active",v='[data-toggle^="button"]',y='input:not([type="hidden"])',b=".btn",E=function(){function t(t){this._element=t,this.shouldAvoidTriggerChange=!1}var e=t.prototype;return e.toggle=function(){var t=!0,e=!0,n=o.default(this._element).closest('[data-toggle="buttons"]')[0];if(n){var i=this._element.querySelector(y);if(i){if("radio"===i.type)if(i.checked&&this._element.classList.contains(_))t=!1;else{var a=n.querySelector(".active");a&&o.default(a).removeClass(_)}t&&("checkbox"!==i.type&&"radio"!==i.type||(i.checked=!this._element.classList.contains(_)),this.shouldAvoidTriggerChange||o.default(i).trigger("change")),i.focus(),e=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(e&&this._element.setAttribute("aria-pressed",!this._element.classList.contains(_)),t&&o.default(this._element).toggleClass(_))},e.dispose=function(){o.default.removeData(this._element,m),this._element=null},t._jQueryInterface=function(e,n){return this.each((function(){var i=o.default(this),a=i.data(m);a||(a=new t(this),i.data(m,a)),a.shouldAvoidTriggerChange=n,"toggle"===e&&a[e]()}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}}]),t}();o.default(document).on("click.bs.button.data-api",v,(function(t){var e=t.target,n=e;if(o.default(e).hasClass("btn")||(e=o.default(e).closest(b)[0]),!e||e.hasAttribute("disabled")||e.classList.contains("disabled"))t.preventDefault();else{var i=e.querySelector(y);if(i&&(i.hasAttribute("disabled")||i.classList.contains("disabled")))return void t.preventDefault();"INPUT"!==n.tagName&&"LABEL"===e.tagName||E._jQueryInterface.call(o.default(e),"toggle","INPUT"===n.tagName)}})).on("focus.bs.button.data-api blur.bs.button.data-api",v,(function(t){var e=o.default(t.target).closest(b)[0];o.default(e).toggleClass("focus",/^focus(in)?$/.test(t.type))})),o.default(window).on("load.bs.button.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-toggle="buttons"] .btn')),e=0,n=t.length;e0,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var e=t.prototype;return e.next=function(){this._isSliding||this._slide(N)},e.nextWhenVisible=function(){var t=o.default(this._element);!document.hidden&&t.is(":visible")&&"hidden"!==t.css("visibility")&&this.next()},e.prev=function(){this._isSliding||this._slide(D)},e.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(".carousel-item-next, .carousel-item-prev")&&(d.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},e.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},e.to=function(t){var e=this;this._activeElement=this._element.querySelector(I);var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)o.default(this._element).one(A,(function(){return e.to(t)}));else{if(n===t)return this.pause(),void this.cycle();var i=t>n?N:D;this._slide(i,this._items[t])}},e.dispose=function(){o.default(this._element).off(".bs.carousel"),o.default.removeData(this._element,w),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},e._getConfig=function(t){return t=r({},k,t),d.typeCheckConfig(T,t,O),t},e._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&this.prev(),e<0&&this.next()}},e._addEventListeners=function(){var t=this;this._config.keyboard&&o.default(this._element).on("keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&o.default(this._element).on("mouseenter.bs.carousel",(function(e){return t.pause(e)})).on("mouseleave.bs.carousel",(function(e){return t.cycle(e)})),this._config.touch&&this._addTouchEventListeners()},e._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var e=function(e){t._pointerEvent&&j[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},n=function(e){t._pointerEvent&&j[e.originalEvent.pointerType.toUpperCase()]&&(t.touchDeltaX=e.originalEvent.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),500+t._config.interval))};o.default(this._element.querySelectorAll(".carousel-item img")).on("dragstart.bs.carousel",(function(t){return t.preventDefault()})),this._pointerEvent?(o.default(this._element).on("pointerdown.bs.carousel",(function(t){return e(t)})),o.default(this._element).on("pointerup.bs.carousel",(function(t){return n(t)})),this._element.classList.add("pointer-event")):(o.default(this._element).on("touchstart.bs.carousel",(function(t){return e(t)})),o.default(this._element).on("touchmove.bs.carousel",(function(e){return function(e){t.touchDeltaX=e.originalEvent.touches&&e.originalEvent.touches.length>1?0:e.originalEvent.touches[0].clientX-t.touchStartX}(e)})),o.default(this._element).on("touchend.bs.carousel",(function(t){return n(t)})))}},e._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},e._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(".carousel-item")):[],this._items.indexOf(t)},e._getItemByDirection=function(t,e){var n=t===N,i=t===D,o=this._getItemIndex(e),a=this._items.length-1;if((i&&0===o||n&&o===a)&&!this._config.wrap)return e;var s=(o+(t===D?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},e._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),i=this._getItemIndex(this._element.querySelector(I)),a=o.default.Event("slide.bs.carousel",{relatedTarget:t,direction:e,from:i,to:n});return o.default(this._element).trigger(a),a},e._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=[].slice.call(this._indicatorsElement.querySelectorAll(".active"));o.default(e).removeClass(S);var n=this._indicatorsElement.children[this._getItemIndex(t)];n&&o.default(n).addClass(S)}},e._updateInterval=function(){var t=this._activeElement||this._element.querySelector(I);if(t){var e=parseInt(t.getAttribute("data-interval"),10);e?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=e):this._config.interval=this._config.defaultInterval||this._config.interval}},e._slide=function(t,e){var n,i,a,s=this,l=this._element.querySelector(I),r=this._getItemIndex(l),u=e||l&&this._getItemByDirection(t,l),f=this._getItemIndex(u),c=Boolean(this._interval);if(t===N?(n="carousel-item-left",i="carousel-item-next",a="left"):(n="carousel-item-right",i="carousel-item-prev",a="right"),u&&o.default(u).hasClass(S))this._isSliding=!1;else if(!this._triggerSlideEvent(u,a).isDefaultPrevented()&&l&&u){this._isSliding=!0,c&&this.pause(),this._setActiveIndicatorElement(u),this._activeElement=u;var h=o.default.Event(A,{relatedTarget:u,direction:a,from:r,to:f});if(o.default(this._element).hasClass("slide")){o.default(u).addClass(i),d.reflow(u),o.default(l).addClass(n),o.default(u).addClass(n);var g=d.getTransitionDurationFromElement(l);o.default(l).one(d.TRANSITION_END,(function(){o.default(u).removeClass(n+" "+i).addClass(S),o.default(l).removeClass("active "+i+" "+n),s._isSliding=!1,setTimeout((function(){return o.default(s._element).trigger(h)}),0)})).emulateTransitionEnd(g)}else o.default(l).removeClass(S),o.default(u).addClass(S),this._isSliding=!1,o.default(this._element).trigger(h);c&&this.cycle()}},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this).data(w),i=r({},k,o.default(this).data());"object"==typeof e&&(i=r({},i,e));var a="string"==typeof e?e:i.slide;if(n||(n=new t(this,i),o.default(this).data(w,n)),"number"==typeof e)n.to(e);else if("string"==typeof a){if("undefined"==typeof n[a])throw new TypeError('No method named "'+a+'"');n[a]()}else i.interval&&i.ride&&(n.pause(),n.cycle())}))},t._dataApiClickHandler=function(e){var n=d.getSelectorFromElement(this);if(n){var i=o.default(n)[0];if(i&&o.default(i).hasClass("carousel")){var a=r({},o.default(i).data(),o.default(this).data()),s=this.getAttribute("data-slide-to");s&&(a.interval=!1),t._jQueryInterface.call(o.default(i),a),s&&o.default(i).data(w).to(s),e.preventDefault()}}},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"Default",get:function(){return k}}]),t}();o.default(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",P._dataApiClickHandler),o.default(window).on("load.bs.carousel.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-ride="carousel"]')),e=0,n=t.length;e0&&(this._selector=s,this._triggerArray.push(a))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var e=t.prototype;return e.toggle=function(){o.default(this._element).hasClass(q)?this.hide():this.show()},e.show=function(){var e,n,i=this;if(!(this._isTransitioning||o.default(this._element).hasClass(q)||(this._parent&&0===(e=[].slice.call(this._parent.querySelectorAll(".show, .collapsing")).filter((function(t){return"string"==typeof i._config.parent?t.getAttribute("data-parent")===i._config.parent:t.classList.contains(F)}))).length&&(e=null),e&&(n=o.default(e).not(this._selector).data(R))&&n._isTransitioning))){var a=o.default.Event("show.bs.collapse");if(o.default(this._element).trigger(a),!a.isDefaultPrevented()){e&&(t._jQueryInterface.call(o.default(e).not(this._selector),"hide"),n||o.default(e).data(R,null));var s=this._getDimension();o.default(this._element).removeClass(F).addClass(Q),this._element.style[s]=0,this._triggerArray.length&&o.default(this._triggerArray).removeClass(B).attr("aria-expanded",!0),this.setTransitioning(!0);var l="scroll"+(s[0].toUpperCase()+s.slice(1)),r=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,(function(){o.default(i._element).removeClass(Q).addClass("collapse show"),i._element.style[s]="",i.setTransitioning(!1),o.default(i._element).trigger("shown.bs.collapse")})).emulateTransitionEnd(r),this._element.style[s]=this._element[l]+"px"}}},e.hide=function(){var t=this;if(!this._isTransitioning&&o.default(this._element).hasClass(q)){var e=o.default.Event("hide.bs.collapse");if(o.default(this._element).trigger(e),!e.isDefaultPrevented()){var n=this._getDimension();this._element.style[n]=this._element.getBoundingClientRect()[n]+"px",d.reflow(this._element),o.default(this._element).addClass(Q).removeClass("collapse show");var i=this._triggerArray.length;if(i>0)for(var a=0;a0},e._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=r({},e.offsets,t._config.offset(e.offsets,t._element)),e}:e.offset=this._config.offset,e},e._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),r({},t,this._config.popperConfig)},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this).data(K);if(n||(n=new t(this,"object"==typeof e?e:null),o.default(this).data(K,n)),"string"==typeof e){if("undefined"==typeof n[e])throw new TypeError('No method named "'+e+'"');n[e]()}}))},t._clearMenus=function(e){if(!e||3!==e.which&&("keyup"!==e.type||9===e.which))for(var n=[].slice.call(document.querySelectorAll(it)),i=0,a=n.length;i0&&s--,40===e.which&&sdocument.documentElement.clientHeight;n||(this._element.style.overflowY="hidden"),this._element.classList.add(ht);var i=d.getTransitionDurationFromElement(this._dialog);o.default(this._element).off(d.TRANSITION_END),o.default(this._element).one(d.TRANSITION_END,(function(){t._element.classList.remove(ht),n||o.default(t._element).one(d.TRANSITION_END,(function(){t._element.style.overflowY=""})).emulateTransitionEnd(t._element,i)})).emulateTransitionEnd(i),this._element.focus()}},e._showElement=function(t){var e=this,n=o.default(this._element).hasClass(dt),i=this._dialog?this._dialog.querySelector(".modal-body"):null;this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),o.default(this._dialog).hasClass("modal-dialog-scrollable")&&i?i.scrollTop=0:this._element.scrollTop=0,n&&d.reflow(this._element),o.default(this._element).addClass(ct),this._config.focus&&this._enforceFocus();var a=o.default.Event("shown.bs.modal",{relatedTarget:t}),s=function(){e._config.focus&&e._element.focus(),e._isTransitioning=!1,o.default(e._element).trigger(a)};if(n){var l=d.getTransitionDurationFromElement(this._dialog);o.default(this._dialog).one(d.TRANSITION_END,s).emulateTransitionEnd(l)}else s()},e._enforceFocus=function(){var t=this;o.default(document).off(pt).on(pt,(function(e){document!==e.target&&t._element!==e.target&&0===o.default(t._element).has(e.target).length&&t._element.focus()}))},e._setEscapeEvent=function(){var t=this;this._isShown?o.default(this._element).on(yt,(function(e){t._config.keyboard&&27===e.which?(e.preventDefault(),t.hide()):t._config.keyboard||27!==e.which||t._triggerBackdropTransition()})):this._isShown||o.default(this._element).off(yt)},e._setResizeEvent=function(){var t=this;this._isShown?o.default(window).on(_t,(function(e){return t.handleUpdate(e)})):o.default(window).off(_t)},e._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._showBackdrop((function(){o.default(document.body).removeClass(ft),t._resetAdjustments(),t._resetScrollbar(),o.default(t._element).trigger(gt)}))},e._removeBackdrop=function(){this._backdrop&&(o.default(this._backdrop).remove(),this._backdrop=null)},e._showBackdrop=function(t){var e=this,n=o.default(this._element).hasClass(dt)?dt:"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className="modal-backdrop",n&&this._backdrop.classList.add(n),o.default(this._backdrop).appendTo(document.body),o.default(this._element).on(vt,(function(t){e._ignoreBackdropClick?e._ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"===e._config.backdrop?e._triggerBackdropTransition():e.hide())})),n&&d.reflow(this._backdrop),o.default(this._backdrop).addClass(ct),!t)return;if(!n)return void t();var i=d.getTransitionDurationFromElement(this._backdrop);o.default(this._backdrop).one(d.TRANSITION_END,t).emulateTransitionEnd(i)}else if(!this._isShown&&this._backdrop){o.default(this._backdrop).removeClass(ct);var a=function(){e._removeBackdrop(),t&&t()};if(o.default(this._element).hasClass(dt)){var s=d.getTransitionDurationFromElement(this._backdrop);o.default(this._backdrop).one(d.TRANSITION_END,a).emulateTransitionEnd(s)}else a()}else t&&t()},e._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},e._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},e._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)
    ',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",customClass:"",sanitize:!0,sanitizeFn:null,whiteList:{"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},popperConfig:null},Ut={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",customClass:"(string|function)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},Mt={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},Wt=function(){function t(t,e){if("undefined"==typeof a.default)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var e=t.prototype;return e.enable=function(){this._isEnabled=!0},e.disable=function(){this._isEnabled=!1},e.toggleEnabled=function(){this._isEnabled=!this._isEnabled},e.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=o.default(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(o.default(this.getTipElement()).hasClass(Rt))return void this._leave(null,this);this._enter(null,this)}},e.dispose=function(){clearTimeout(this._timeout),o.default.removeData(this.element,this.constructor.DATA_KEY),o.default(this.element).off(this.constructor.EVENT_KEY),o.default(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&o.default(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},e.show=function(){var t=this;if("none"===o.default(this.element).css("display"))throw new Error("Please use show on visible elements");var e=o.default.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){o.default(this.element).trigger(e);var n=d.findShadowRoot(this.element),i=o.default.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(e.isDefaultPrevented()||!i)return;var s=this.getTipElement(),l=d.getUID(this.constructor.NAME);s.setAttribute("id",l),this.element.setAttribute("aria-describedby",l),this.setContent(),this.config.animation&&o.default(s).addClass(Lt);var r="function"==typeof this.config.placement?this.config.placement.call(this,s,this.element):this.config.placement,u=this._getAttachment(r);this.addAttachmentClass(u);var f=this._getContainer();o.default(s).data(this.constructor.DATA_KEY,this),o.default.contains(this.element.ownerDocument.documentElement,this.tip)||o.default(s).appendTo(f),o.default(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new a.default(this.element,s,this._getPopperConfig(u)),o.default(s).addClass(Rt),o.default(s).addClass(this.config.customClass),"ontouchstart"in document.documentElement&&o.default(document.body).children().on("mouseover",null,o.default.noop);var c=function(){t.config.animation&&t._fixTransition();var e=t._hoverState;t._hoverState=null,o.default(t.element).trigger(t.constructor.Event.SHOWN),e===qt&&t._leave(null,t)};if(o.default(this.tip).hasClass(Lt)){var h=d.getTransitionDurationFromElement(this.tip);o.default(this.tip).one(d.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},e.hide=function(t){var e=this,n=this.getTipElement(),i=o.default.Event(this.constructor.Event.HIDE),a=function(){e._hoverState!==xt&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),o.default(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(o.default(this.element).trigger(i),!i.isDefaultPrevented()){if(o.default(n).removeClass(Rt),"ontouchstart"in document.documentElement&&o.default(document.body).children().off("mouseover",null,o.default.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,o.default(this.tip).hasClass(Lt)){var s=d.getTransitionDurationFromElement(n);o.default(n).one(d.TRANSITION_END,a).emulateTransitionEnd(s)}else a();this._hoverState=""}},e.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},e.isWithContent=function(){return Boolean(this.getTitle())},e.addAttachmentClass=function(t){o.default(this.getTipElement()).addClass("bs-tooltip-"+t)},e.getTipElement=function(){return this.tip=this.tip||o.default(this.config.template)[0],this.tip},e.setContent=function(){var t=this.getTipElement();this.setElementContent(o.default(t.querySelectorAll(".tooltip-inner")),this.getTitle()),o.default(t).removeClass("fade show")},e.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=At(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?o.default(e).parent().is(t)||t.empty().append(e):t.text(o.default(e).text())},e.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},e._getPopperConfig=function(t){var e=this;return r({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:".arrow"},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}},this.config.popperConfig)},e._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=r({},e.offsets,t.config.offset(e.offsets,t.element)),e}:e.offset=this.config.offset,e},e._getContainer=function(){return!1===this.config.container?document.body:d.isElement(this.config.container)?o.default(this.config.container):o.default(document).find(this.config.container)},e._getAttachment=function(t){return Bt[t.toUpperCase()]},e._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(e){if("click"===e)o.default(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==e){var n=e===Ft?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,i=e===Ft?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;o.default(t.element).on(n,t.config.selector,(function(e){return t._enter(e)})).on(i,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},o.default(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=r({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},e._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},e._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||o.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Qt:Ft]=!0),o.default(e.getTipElement()).hasClass(Rt)||e._hoverState===xt?e._hoverState=xt:(clearTimeout(e._timeout),e._hoverState=xt,e.config.delay&&e.config.delay.show?e._timeout=setTimeout((function(){e._hoverState===xt&&e.show()}),e.config.delay.show):e.show())},e._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||o.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Qt:Ft]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=qt,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout((function(){e._hoverState===qt&&e.hide()}),e.config.delay.hide):e.hide())},e._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},e._getConfig=function(t){var e=o.default(this.element).data();return Object.keys(e).forEach((function(t){-1!==Pt.indexOf(t)&&delete e[t]})),"number"==typeof(t=r({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),d.typeCheckConfig(It,t,this.constructor.DefaultType),t.sanitize&&(t.template=At(t.template,t.whiteList,t.sanitizeFn)),t},e._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},e._cleanTipClass=function(){var t=o.default(this.getTipElement()),e=t.attr("class").match(jt);null!==e&&e.length&&t.removeClass(e.join(""))},e._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},e._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(o.default(t).removeClass(Lt),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(kt),a="object"==typeof e&&e;if((i||!/dispose|hide/.test(e))&&(i||(i=new t(this,a),n.data(kt,i)),"string"==typeof e)){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e]()}}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"Default",get:function(){return Ht}},{key:"NAME",get:function(){return It}},{key:"DATA_KEY",get:function(){return kt}},{key:"Event",get:function(){return Mt}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return Ut}}]),t}();o.default.fn.tooltip=Wt._jQueryInterface,o.default.fn.tooltip.Constructor=Wt,o.default.fn.tooltip.noConflict=function(){return o.default.fn.tooltip=Ot,Wt._jQueryInterface};var Vt="bs.popover",zt=o.default.fn.popover,Kt=new RegExp("(^|\\s)bs-popover\\S+","g"),Xt=r({},Wt.Default,{placement:"right",trigger:"click",content:"",template:''}),Yt=r({},Wt.DefaultType,{content:"(string|element|function)"}),$t={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},Jt=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),e.prototype.constructor=e,u(e,n);var a=i.prototype;return a.isWithContent=function(){return this.getTitle()||this._getContent()},a.addAttachmentClass=function(t){o.default(this.getTipElement()).addClass("bs-popover-"+t)},a.getTipElement=function(){return this.tip=this.tip||o.default(this.config.template)[0],this.tip},a.setContent=function(){var t=o.default(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(".popover-body"),e),t.removeClass("fade show")},a._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},a._cleanTipClass=function(){var t=o.default(this.getTipElement()),e=t.attr("class").match(Kt);null!==e&&e.length>0&&t.removeClass(e.join(""))},i._jQueryInterface=function(t){return this.each((function(){var e=o.default(this).data(Vt),n="object"==typeof t?t:null;if((e||!/dispose|hide/.test(t))&&(e||(e=new i(this,n),o.default(this).data(Vt,e)),"string"==typeof t)){if("undefined"==typeof e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},l(i,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"Default",get:function(){return Xt}},{key:"NAME",get:function(){return"popover"}},{key:"DATA_KEY",get:function(){return Vt}},{key:"Event",get:function(){return $t}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return Yt}}]),i}(Wt);o.default.fn.popover=Jt._jQueryInterface,o.default.fn.popover.Constructor=Jt,o.default.fn.popover.noConflict=function(){return o.default.fn.popover=zt,Jt._jQueryInterface};var Gt="scrollspy",Zt="bs.scrollspy",te=o.default.fn[Gt],ee="active",ne="position",ie=".nav, .list-group",oe={offset:10,method:"auto",target:""},ae={offset:"number",method:"string",target:"(string|element)"},se=function(){function t(t,e){var n=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),this._selector=this._config.target+" .nav-link,"+this._config.target+" .list-group-item,"+this._config.target+" .dropdown-item",this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,o.default(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return n._process(t)})),this.refresh(),this._process()}var e=t.prototype;return e.refresh=function(){var t=this,e=this._scrollElement===this._scrollElement.window?"offset":ne,n="auto"===this._config.method?e:this._config.method,i=n===ne?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var e,a=d.getSelectorFromElement(t);if(a&&(e=document.querySelector(a)),e){var s=e.getBoundingClientRect();if(s.width||s.height)return[o.default(e)[n]().top+i,a]}return null})).filter(Boolean).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},e.dispose=function(){o.default.removeData(this._element,Zt),o.default(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},e._getConfig=function(t){if("string"!=typeof(t=r({},oe,"object"==typeof t&&t?t:{})).target&&d.isElement(t.target)){var e=o.default(t.target).attr("id");e||(e=d.getUID(Gt),o.default(t.target).attr("id",e)),t.target="#"+e}return d.typeCheckConfig(Gt,t,ae),t},e._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},e._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},e._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},e._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;)this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t li > .active",ge=function(){function t(t){this._element=t}var e=t.prototype;return e.show=function(){var t=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&o.default(this._element).hasClass(ue)||o.default(this._element).hasClass("disabled")||this._element.hasAttribute("disabled"))){var e,n,i=o.default(this._element).closest(".nav, .list-group")[0],a=d.getSelectorFromElement(this._element);if(i){var s="UL"===i.nodeName||"OL"===i.nodeName?he:ce;n=(n=o.default.makeArray(o.default(i).find(s)))[n.length-1]}var l=o.default.Event("hide.bs.tab",{relatedTarget:this._element}),r=o.default.Event("show.bs.tab",{relatedTarget:n});if(n&&o.default(n).trigger(l),o.default(this._element).trigger(r),!r.isDefaultPrevented()&&!l.isDefaultPrevented()){a&&(e=document.querySelector(a)),this._activate(this._element,i);var u=function(){var e=o.default.Event("hidden.bs.tab",{relatedTarget:t._element}),i=o.default.Event("shown.bs.tab",{relatedTarget:n});o.default(n).trigger(e),o.default(t._element).trigger(i)};e?this._activate(e,e.parentNode,u):u()}}},e.dispose=function(){o.default.removeData(this._element,le),this._element=null},e._activate=function(t,e,n){var i=this,a=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?o.default(e).children(ce):o.default(e).find(he))[0],s=n&&a&&o.default(a).hasClass(fe),l=function(){return i._transitionComplete(t,a,n)};if(a&&s){var r=d.getTransitionDurationFromElement(a);o.default(a).removeClass(de).one(d.TRANSITION_END,l).emulateTransitionEnd(r)}else l()},e._transitionComplete=function(t,e,n){if(e){o.default(e).removeClass(ue);var i=o.default(e.parentNode).find("> .dropdown-menu .active")[0];i&&o.default(i).removeClass(ue),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}o.default(t).addClass(ue),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),d.reflow(t),t.classList.contains(fe)&&t.classList.add(de);var a=t.parentNode;if(a&&"LI"===a.nodeName&&(a=a.parentNode),a&&o.default(a).hasClass("dropdown-menu")){var s=o.default(t).closest(".dropdown")[0];if(s){var l=[].slice.call(s.querySelectorAll(".dropdown-toggle"));o.default(l).addClass(ue)}t.setAttribute("aria-expanded",!0)}n&&n()},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(le);if(i||(i=new t(this),n.data(le,i)),"string"==typeof e){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e]()}}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}}]),t}();o.default(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',(function(t){t.preventDefault(),ge._jQueryInterface.call(o.default(this),"show")})),o.default.fn.tab=ge._jQueryInterface,o.default.fn.tab.Constructor=ge,o.default.fn.tab.noConflict=function(){return o.default.fn.tab=re,ge._jQueryInterface};var me="bs.toast",pe=o.default.fn.toast,_e="hide",ve="show",ye="showing",be="click.dismiss.bs.toast",Ee={animation:!0,autohide:!0,delay:500},Te={animation:"boolean",autohide:"boolean",delay:"number"},we=function(){function t(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var e=t.prototype;return e.show=function(){var t=this,e=o.default.Event("show.bs.toast");if(o.default(this._element).trigger(e),!e.isDefaultPrevented()){this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");var n=function(){t._element.classList.remove(ye),t._element.classList.add(ve),o.default(t._element).trigger("shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove(_e),d.reflow(this._element),this._element.classList.add(ye),this._config.animation){var i=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,n).emulateTransitionEnd(i)}else n()}},e.hide=function(){if(this._element.classList.contains(ve)){var t=o.default.Event("hide.bs.toast");o.default(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},e.dispose=function(){this._clearTimeout(),this._element.classList.contains(ve)&&this._element.classList.remove(ve),o.default(this._element).off(be),o.default.removeData(this._element,me),this._element=null,this._config=null},e._getConfig=function(t){return t=r({},Ee,o.default(this._element).data(),"object"==typeof t&&t?t:{}),d.typeCheckConfig("toast",t,this.constructor.DefaultType),t},e._setListeners=function(){var t=this;o.default(this._element).on(be,'[data-dismiss="toast"]',(function(){return t.hide()}))},e._close=function(){var t=this,e=function(){t._element.classList.add(_e),o.default(t._element).trigger("hidden.bs.toast")};if(this._element.classList.remove(ve),this._config.animation){var n=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},e._clearTimeout=function(){clearTimeout(this._timeout),this._timeout=null},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(me);if(i||(i=new t(this,"object"==typeof e&&e),n.data(me,i)),"string"==typeof e){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e](this)}}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"DefaultType",get:function(){return Te}},{key:"Default",get:function(){return Ee}}]),t}();o.default.fn.toast=we._jQueryInterface,o.default.fn.toast.Constructor=we,o.default.fn.toast.noConflict=function(){return o.default.fn.toast=pe,we._jQueryInterface},t.Alert=g,t.Button=E,t.Carousel=P,t.Collapse=V,t.Dropdown=lt,t.Modal=Ct,t.Popover=Jt,t.Scrollspy=se,t.Tab=ge,t.Toast=we,t.Tooltip=Wt,t.Util=d,Object.defineProperty(t,"__esModule",{value:!0})})); +//# sourceMappingURL=bootstrap.min.js.map \ No newline at end of file diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/d3.min.js b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/d3.min.js new file mode 100644 index 00000000..16648730 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/d3.min.js @@ -0,0 +1,5 @@ +!function(){function n(n){return n&&(n.ownerDocument||n.document||n).documentElement}function t(n){return n&&(n.ownerDocument&&n.ownerDocument.defaultView||n.document&&n||n.defaultView)}function e(n,t){return t>n?-1:n>t?1:n>=t?0:NaN}function r(n){return null===n?NaN:+n}function i(n){return!isNaN(n)}function u(n){return{left:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)<0?r=u+1:i=u}return r},right:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)>0?i=u:r=u+1}return r}}}function o(n){return n.length}function a(n){for(var t=1;n*t%1;)t*=10;return t}function l(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function c(){this._=Object.create(null)}function f(n){return(n+="")===bo||n[0]===_o?_o+n:n}function s(n){return(n+="")[0]===_o?n.slice(1):n}function h(n){return f(n)in this._}function p(n){return(n=f(n))in this._&&delete this._[n]}function g(){var n=[];for(var t in this._)n.push(s(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function y(){this._=Object.create(null)}function m(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=wo.length;r>e;++e){var i=wo[e]+t;if(i in n)return i}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,i=-1,u=r.length;++ie;e++)for(var i,u=n[e],o=0,a=u.length;a>o;o++)(i=u[o])&&t(i,o,e);return n}function Z(n){return ko(n,qo),n}function V(n){var t,e;return function(r,i,u){var o,a=n[u].update,l=a.length;for(u!=e&&(e=u,t=0),i>=t&&(t=i+1);!(o=a[t])&&++t0&&(n=n.slice(0,a));var c=To.get(n);return c&&(n=c,l=B),a?t?i:r:t?b:u}function $(n,t){return function(e){var r=ao.event;ao.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ao.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=".dragsuppress-"+ ++Do,i="click"+r,u=ao.select(t(e)).on("touchmove"+r,S).on("dragstart"+r,S).on("selectstart"+r,S);if(null==Ro&&(Ro="onselectstart"in e?!1:x(e.style,"userSelect")),Ro){var o=n(e).style,a=o[Ro];o[Ro]="none"}return function(n){if(u.on(r,null),Ro&&(o[Ro]=a),n){var t=function(){u.on(i,null)};u.on(i,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var i=r.createSVGPoint();if(0>Po){var u=t(n);if(u.scrollX||u.scrollY){r=ao.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var o=r[0][0].getScreenCTM();Po=!(o.f||o.e),r.remove()}}return Po?(i.x=e.pageX,i.y=e.pageY):(i.x=e.clientX,i.y=e.clientY),i=i.matrixTransform(n.getScreenCTM().inverse()),[i.x,i.y]}var a=n.getBoundingClientRect();return[e.clientX-a.left-n.clientLeft,e.clientY-a.top-n.clientTop]}function G(){return ao.event.changedTouches[0].identifier}function K(n){return n>0?1:0>n?-1:0}function Q(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function nn(n){return n>1?0:-1>n?Fo:Math.acos(n)}function tn(n){return n>1?Io:-1>n?-Io:Math.asin(n)}function en(n){return((n=Math.exp(n))-1/n)/2}function rn(n){return((n=Math.exp(n))+1/n)/2}function un(n){return((n=Math.exp(2*n))-1)/(n+1)}function on(n){return(n=Math.sin(n/2))*n}function an(){}function ln(n,t,e){return this instanceof ln?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof ln?new ln(n.h,n.s,n.l):_n(""+n,wn,ln):new ln(n,t,e)}function cn(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?u+(o-u)*n/60:180>n?o:240>n?u+(o-u)*(240-n)/60:u}function i(n){return Math.round(255*r(n))}var u,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,u=2*e-o,new mn(i(n+120),i(n),i(n-120))}function fn(n,t,e){return this instanceof fn?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof fn?new fn(n.h,n.c,n.l):n instanceof hn?gn(n.l,n.a,n.b):gn((n=Sn((n=ao.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new fn(n,t,e)}function sn(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new hn(e,Math.cos(n*=Yo)*t,Math.sin(n)*t)}function hn(n,t,e){return this instanceof hn?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof hn?new hn(n.l,n.a,n.b):n instanceof fn?sn(n.h,n.c,n.l):Sn((n=mn(n)).r,n.g,n.b):new hn(n,t,e)}function pn(n,t,e){var r=(n+16)/116,i=r+t/500,u=r-e/200;return i=vn(i)*na,r=vn(r)*ta,u=vn(u)*ea,new mn(yn(3.2404542*i-1.5371385*r-.4985314*u),yn(-.969266*i+1.8760108*r+.041556*u),yn(.0556434*i-.2040259*r+1.0572252*u))}function gn(n,t,e){return n>0?new fn(Math.atan2(e,t)*Zo,Math.sqrt(t*t+e*e),n):new fn(NaN,NaN,n)}function vn(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function dn(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function yn(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function mn(n,t,e){return this instanceof mn?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof mn?new mn(n.r,n.g,n.b):_n(""+n,mn,cn):new mn(n,t,e)}function Mn(n){return new mn(n>>16,n>>8&255,255&n)}function xn(n){return Mn(n)+""}function bn(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function _n(n,t,e){var r,i,u,o=0,a=0,l=0;if(r=/([a-z]+)\((.*)\)/.exec(n=n.toLowerCase()))switch(i=r[2].split(","),r[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return t(Nn(i[0]),Nn(i[1]),Nn(i[2]))}return(u=ua.get(n))?t(u.r,u.g,u.b):(null==n||"#"!==n.charAt(0)||isNaN(u=parseInt(n.slice(1),16))||(4===n.length?(o=(3840&u)>>4,o=o>>4|o,a=240&u,a=a>>4|a,l=15&u,l=l<<4|l):7===n.length&&(o=(16711680&u)>>16,a=(65280&u)>>8,l=255&u)),t(o,a,l))}function wn(n,t,e){var r,i,u=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-u,l=(o+u)/2;return a?(i=.5>l?a/(o+u):a/(2-o-u),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=NaN,i=l>0&&1>l?0:r),new ln(r,i,l)}function Sn(n,t,e){n=kn(n),t=kn(t),e=kn(e);var r=dn((.4124564*n+.3575761*t+.1804375*e)/na),i=dn((.2126729*n+.7151522*t+.072175*e)/ta),u=dn((.0193339*n+.119192*t+.9503041*e)/ea);return hn(116*i-16,500*(r-i),200*(i-u))}function kn(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Nn(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function En(n){return"function"==typeof n?n:function(){return n}}function An(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Cn(t,e,n,r)}}function Cn(n,t,e,r){function i(){var n,t=l.status;if(!t&&Ln(l)||t>=200&&300>t||304===t){try{n=e.call(u,l)}catch(r){return void o.error.call(u,r)}o.load.call(u,n)}else o.error.call(u,l)}var u={},o=ao.dispatch("beforesend","progress","load","error"),a={},l=new XMLHttpRequest,c=null;return!this.XDomainRequest||"withCredentials"in l||!/^(http(s)?:)?\/\//.test(n)||(l=new XDomainRequest),"onload"in l?l.onload=l.onerror=i:l.onreadystatechange=function(){l.readyState>3&&i()},l.onprogress=function(n){var t=ao.event;ao.event=n;try{o.progress.call(u,l)}finally{ao.event=t}},u.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",u)},u.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",u):t},u.responseType=function(n){return arguments.length?(c=n,u):c},u.response=function(n){return e=n,u},["get","post"].forEach(function(n){u[n]=function(){return u.send.apply(u,[n].concat(co(arguments)))}}),u.send=function(e,r,i){if(2===arguments.length&&"function"==typeof r&&(i=r,r=null),l.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),l.setRequestHeader)for(var f in a)l.setRequestHeader(f,a[f]);return null!=t&&l.overrideMimeType&&l.overrideMimeType(t),null!=c&&(l.responseType=c),null!=i&&u.on("error",i).on("load",function(n){i(null,n)}),o.beforesend.call(u,l),l.send(null==r?null:r),u},u.abort=function(){return l.abort(),u},ao.rebind(u,o,"on"),null==r?u:u.get(zn(r))}function zn(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Ln(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qn(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var i=e+t,u={c:n,t:i,n:null};return aa?aa.n=u:oa=u,aa=u,la||(ca=clearTimeout(ca),la=1,fa(Tn)),u}function Tn(){var n=Rn(),t=Dn()-n;t>24?(isFinite(t)&&(clearTimeout(ca),ca=setTimeout(Tn,t)),la=0):(la=1,fa(Tn))}function Rn(){for(var n=Date.now(),t=oa;t;)n>=t.t&&t.c(n-t.t)&&(t.c=null),t=t.n;return n}function Dn(){for(var n,t=oa,e=1/0;t;)t.c?(t.t8?function(n){return n/e}:function(n){return n*e},symbol:n}}function jn(n){var t=n.decimal,e=n.thousands,r=n.grouping,i=n.currency,u=r&&e?function(n,t){for(var i=n.length,u=[],o=0,a=r[0],l=0;i>0&&a>0&&(l+a+1>t&&(a=Math.max(1,t-l)),u.push(n.substring(i-=a,i+a)),!((l+=a+1)>t));)a=r[o=(o+1)%r.length];return u.reverse().join(e)}:m;return function(n){var e=ha.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"-",l=e[4]||"",c=e[5],f=+e[6],s=e[7],h=e[8],p=e[9],g=1,v="",d="",y=!1,m=!0;switch(h&&(h=+h.substring(1)),(c||"0"===r&&"="===o)&&(c=r="0",o="="),p){case"n":s=!0,p="g";break;case"%":g=100,d="%",p="f";break;case"p":g=100,d="%",p="r";break;case"b":case"o":case"x":case"X":"#"===l&&(v="0"+p.toLowerCase());case"c":m=!1;case"d":y=!0,h=0;break;case"s":g=-1,p="r"}"$"===l&&(v=i[0],d=i[1]),"r"!=p||h||(p="g"),null!=h&&("g"==p?h=Math.max(1,Math.min(21,h)):"e"!=p&&"f"!=p||(h=Math.max(0,Math.min(20,h)))),p=pa.get(p)||Fn;var M=c&&s;return function(n){var e=d;if(y&&n%1)return"";var i=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===a?"":a;if(0>g){var l=ao.formatPrefix(n,h);n=l.scale(n),e=l.symbol+d}else n*=g;n=p(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=m?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!c&&s&&(x=u(x,1/0));var S=v.length+x.length+b.length+(M?0:i.length),k=f>S?new Array(S=f-S+1).join(r):"";return M&&(x=u(k+x,k.length?f-b.length:1/0)),i+=v,n=x+b,("<"===o?i+n+k:">"===o?k+i+n:"^"===o?k.substring(0,S>>=1)+i+n+k.substring(S):i+(M?n:k+n))+e}}}function Fn(n){return n+""}function Hn(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function On(n,t,e){function r(t){var e=n(t),r=u(e,1);return r-t>t-e?e:r}function i(e){return t(e=n(new va(e-1)),1),e}function u(n,e){return t(n=new va(+n),e),n}function o(n,r,u){var o=i(n),a=[];if(u>1)for(;r>o;)e(o)%u||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{va=Hn;var r=new Hn;return r._=n,o(r,t,e)}finally{va=Date}}n.floor=n,n.round=r,n.ceil=i,n.offset=u,n.range=o;var l=n.utc=In(n);return l.floor=l,l.round=In(r),l.ceil=In(i),l.offset=In(u),l.range=a,n}function In(n){return function(t,e){try{va=Hn;var r=new Hn;return r._=t,n(r,e)._}finally{va=Date}}}function Yn(n){function t(n){function t(t){for(var e,i,u,o=[],a=-1,l=0;++aa;){if(r>=c)return-1;if(i=t.charCodeAt(a++),37===i){if(o=t.charAt(a++),u=C[o in ya?t.charAt(a++):o],!u||(r=u(n,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){N.lastIndex=0;var r=N.exec(t.slice(e));return r?(n.m=E.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,A.c.toString(),t,r)}function l(n,t,r){return e(n,A.x.toString(),t,r)}function c(n,t,r){return e(n,A.X.toString(),t,r)}function f(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var s=n.dateTime,h=n.date,p=n.time,g=n.periods,v=n.days,d=n.shortDays,y=n.months,m=n.shortMonths;t.utc=function(n){function e(n){try{va=Hn;var t=new va;return t._=n,r(t)}finally{va=Date}}var r=t(n);return e.parse=function(n){try{va=Hn;var t=r.parse(n);return t&&t._}finally{va=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ct;var M=ao.map(),x=Vn(v),b=Xn(v),_=Vn(d),w=Xn(d),S=Vn(y),k=Xn(y),N=Vn(m),E=Xn(m);g.forEach(function(n,t){M.set(n.toLowerCase(),t)});var A={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return m[n.getMonth()]},B:function(n){return y[n.getMonth()]},c:t(s),d:function(n,t){return Zn(n.getDate(),t,2)},e:function(n,t){return Zn(n.getDate(),t,2)},H:function(n,t){return Zn(n.getHours(),t,2)},I:function(n,t){return Zn(n.getHours()%12||12,t,2)},j:function(n,t){return Zn(1+ga.dayOfYear(n),t,3)},L:function(n,t){return Zn(n.getMilliseconds(),t,3)},m:function(n,t){return Zn(n.getMonth()+1,t,2)},M:function(n,t){return Zn(n.getMinutes(),t,2)},p:function(n){return g[+(n.getHours()>=12)]},S:function(n,t){return Zn(n.getSeconds(),t,2)},U:function(n,t){return Zn(ga.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Zn(ga.mondayOfYear(n),t,2)},x:t(h),X:t(p),y:function(n,t){return Zn(n.getFullYear()%100,t,2)},Y:function(n,t){return Zn(n.getFullYear()%1e4,t,4)},Z:at,"%":function(){return"%"}},C={a:r,A:i,b:u,B:o,c:a,d:tt,e:tt,H:rt,I:rt,j:et,L:ot,m:nt,M:it,p:f,S:ut,U:Bn,w:$n,W:Wn,x:l,X:c,y:Gn,Y:Jn,Z:Kn,"%":lt};return t}function Zn(n,t,e){var r=0>n?"-":"",i=(r?-n:n)+"",u=i.length;return r+(e>u?new Array(e-u+1).join(t)+i:i)}function Vn(n){return new RegExp("^(?:"+n.map(ao.requote).join("|")+")","i")}function Xn(n){for(var t=new c,e=-1,r=n.length;++e68?1900:2e3)}function nt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function tt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function et(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function rt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function it(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function ut(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ot(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function at(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=xo(t)/60|0,i=xo(t)%60;return e+Zn(r,"0",2)+Zn(i,"0",2)}function lt(n,t,e){Ma.lastIndex=0;var r=Ma.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ct(n){for(var t=n.length,e=-1;++e=0?1:-1,a=o*e,l=Math.cos(t),c=Math.sin(t),f=u*c,s=i*l+f*Math.cos(a),h=f*o*Math.sin(a);ka.add(Math.atan2(h,s)),r=n,i=l,u=c}var t,e,r,i,u;Na.point=function(o,a){Na.point=n,r=(t=o)*Yo,i=Math.cos(a=(e=a)*Yo/2+Fo/4),u=Math.sin(a)},Na.lineEnd=function(){n(t,e)}}function dt(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function yt(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function mt(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function Mt(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function xt(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function bt(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function _t(n){return[Math.atan2(n[1],n[0]),tn(n[2])]}function wt(n,t){return xo(n[0]-t[0])a;++a)i.point((e=n[a])[0],e[1]);return void i.lineEnd()}var l=new Tt(e,n,null,!0),c=new Tt(e,null,l,!1);l.o=c,u.push(l),o.push(c),l=new Tt(r,n,null,!1),c=new Tt(r,null,l,!0),l.o=c,u.push(l),o.push(c)}}),o.sort(t),qt(u),qt(o),u.length){for(var a=0,l=e,c=o.length;c>a;++a)o[a].e=l=!l;for(var f,s,h=u[0];;){for(var p=h,g=!0;p.v;)if((p=p.n)===h)return;f=p.z,i.lineStart();do{if(p.v=p.o.v=!0,p.e){if(g)for(var a=0,c=f.length;c>a;++a)i.point((s=f[a])[0],s[1]);else r(p.x,p.n.x,1,i);p=p.n}else{if(g){f=p.p.z;for(var a=f.length-1;a>=0;--a)i.point((s=f[a])[0],s[1])}else r(p.x,p.p.x,-1,i);p=p.p}p=p.o,f=p.z,g=!g}while(!p.v);i.lineEnd()}}}function qt(n){if(t=n.length){for(var t,e,r=0,i=n[0];++r0){for(b||(u.polygonStart(),b=!0),u.lineStart();++o1&&2&t&&e.push(e.pop().concat(e.shift())),p.push(e.filter(Dt))}var p,g,v,d=t(u),y=i.invert(r[0],r[1]),m={point:o,lineStart:l,lineEnd:c,polygonStart:function(){m.point=f,m.lineStart=s,m.lineEnd=h,p=[],g=[]},polygonEnd:function(){m.point=o,m.lineStart=l,m.lineEnd=c,p=ao.merge(p);var n=Ot(y,g);p.length?(b||(u.polygonStart(),b=!0),Lt(p,Ut,n,e,u)):n&&(b||(u.polygonStart(),b=!0),u.lineStart(),e(null,null,1,u),u.lineEnd()),b&&(u.polygonEnd(),b=!1),p=g=null},sphere:function(){u.polygonStart(),u.lineStart(),e(null,null,1,u),u.lineEnd(),u.polygonEnd()}},M=Pt(),x=t(M),b=!1;return m}}function Dt(n){return n.length>1}function Pt(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:b,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ut(n,t){return((n=n.x)[0]<0?n[1]-Io-Uo:Io-n[1])-((t=t.x)[0]<0?t[1]-Io-Uo:Io-t[1])}function jt(n){var t,e=NaN,r=NaN,i=NaN;return{lineStart:function(){n.lineStart(),t=1},point:function(u,o){var a=u>0?Fo:-Fo,l=xo(u-e);xo(l-Fo)0?Io:-Io),n.point(i,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(u,r),t=0):i!==a&&l>=Fo&&(xo(e-i)Uo?Math.atan((Math.sin(t)*(u=Math.cos(r))*Math.sin(e)-Math.sin(r)*(i=Math.cos(t))*Math.sin(n))/(i*u*o)):(t+r)/2}function Ht(n,t,e,r){var i;if(null==n)i=e*Io,r.point(-Fo,i),r.point(0,i),r.point(Fo,i),r.point(Fo,0),r.point(Fo,-i),r.point(0,-i),r.point(-Fo,-i),r.point(-Fo,0),r.point(-Fo,i);else if(xo(n[0]-t[0])>Uo){var u=n[0]a;++a){var c=t[a],f=c.length;if(f)for(var s=c[0],h=s[0],p=s[1]/2+Fo/4,g=Math.sin(p),v=Math.cos(p),d=1;;){d===f&&(d=0),n=c[d];var y=n[0],m=n[1]/2+Fo/4,M=Math.sin(m),x=Math.cos(m),b=y-h,_=b>=0?1:-1,w=_*b,S=w>Fo,k=g*M;if(ka.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),u+=S?b+_*Ho:b,S^h>=e^y>=e){var N=mt(dt(s),dt(n));bt(N);var E=mt(i,N);bt(E);var A=(S^b>=0?-1:1)*tn(E[2]);(r>A||r===A&&(N[0]||N[1]))&&(o+=S^b>=0?1:-1)}if(!d++)break;h=y,g=M,v=x,s=n}}return(-Uo>u||Uo>u&&-Uo>ka)^1&o}function It(n){function t(n,t){return Math.cos(n)*Math.cos(t)>u}function e(n){var e,u,l,c,f;return{lineStart:function(){c=l=!1,f=1},point:function(s,h){var p,g=[s,h],v=t(s,h),d=o?v?0:i(s,h):v?i(s+(0>s?Fo:-Fo),h):0;if(!e&&(c=l=v)&&n.lineStart(),v!==l&&(p=r(e,g),(wt(e,p)||wt(g,p))&&(g[0]+=Uo,g[1]+=Uo,v=t(g[0],g[1]))),v!==l)f=0,v?(n.lineStart(),p=r(g,e),n.point(p[0],p[1])):(p=r(e,g),n.point(p[0],p[1]),n.lineEnd()),e=p;else if(a&&e&&o^v){var y;d&u||!(y=r(g,e,!0))||(f=0,o?(n.lineStart(),n.point(y[0][0],y[0][1]),n.point(y[1][0],y[1][1]),n.lineEnd()):(n.point(y[1][0],y[1][1]),n.lineEnd(),n.lineStart(),n.point(y[0][0],y[0][1])))}!v||e&&wt(e,g)||n.point(g[0],g[1]),e=g,l=v,u=d},lineEnd:function(){l&&n.lineEnd(),e=null},clean:function(){return f|(c&&l)<<1}}}function r(n,t,e){var r=dt(n),i=dt(t),o=[1,0,0],a=mt(r,i),l=yt(a,a),c=a[0],f=l-c*c;if(!f)return!e&&n;var s=u*l/f,h=-u*c/f,p=mt(o,a),g=xt(o,s),v=xt(a,h);Mt(g,v);var d=p,y=yt(g,d),m=yt(d,d),M=y*y-m*(yt(g,g)-1);if(!(0>M)){var x=Math.sqrt(M),b=xt(d,(-y-x)/m);if(Mt(b,g),b=_t(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],N=t[1];w>S&&(_=w,w=S,S=_);var E=S-w,A=xo(E-Fo)E;if(!A&&k>N&&(_=k,k=N,N=_),C?A?k+N>0^b[1]<(xo(b[0]-w)Fo^(w<=b[0]&&b[0]<=S)){var z=xt(d,(-y+x)/m);return Mt(z,g),[b,_t(z)]}}}function i(t,e){var r=o?n:Fo-n,i=0;return-r>t?i|=1:t>r&&(i|=2),-r>e?i|=4:e>r&&(i|=8),i}var u=Math.cos(n),o=u>0,a=xo(u)>Uo,l=ve(n,6*Yo);return Rt(t,e,l,o?[0,-n]:[-Fo,n-Fo])}function Yt(n,t,e,r){return function(i){var u,o=i.a,a=i.b,l=o.x,c=o.y,f=a.x,s=a.y,h=0,p=1,g=f-l,v=s-c;if(u=n-l,g||!(u>0)){if(u/=g,0>g){if(h>u)return;p>u&&(p=u)}else if(g>0){if(u>p)return;u>h&&(h=u)}if(u=e-l,g||!(0>u)){if(u/=g,0>g){if(u>p)return;u>h&&(h=u)}else if(g>0){if(h>u)return;p>u&&(p=u)}if(u=t-c,v||!(u>0)){if(u/=v,0>v){if(h>u)return;p>u&&(p=u)}else if(v>0){if(u>p)return;u>h&&(h=u)}if(u=r-c,v||!(0>u)){if(u/=v,0>v){if(u>p)return;u>h&&(h=u)}else if(v>0){if(h>u)return;p>u&&(p=u)}return h>0&&(i.a={x:l+h*g,y:c+h*v}),1>p&&(i.b={x:l+p*g,y:c+p*v}),i}}}}}}function Zt(n,t,e,r){function i(r,i){return xo(r[0]-n)0?0:3:xo(r[0]-e)0?2:1:xo(r[1]-t)0?1:0:i>0?3:2}function u(n,t){return o(n.x,t.x)}function o(n,t){var e=i(n,1),r=i(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function l(n){for(var t=0,e=d.length,r=n[1],i=0;e>i;++i)for(var u,o=1,a=d[i],l=a.length,c=a[0];l>o;++o)u=a[o],c[1]<=r?u[1]>r&&Q(c,u,n)>0&&++t:u[1]<=r&&Q(c,u,n)<0&&--t,c=u;return 0!==t}function c(u,a,l,c){var f=0,s=0;if(null==u||(f=i(u,l))!==(s=i(a,l))||o(u,a)<0^l>0){do c.point(0===f||3===f?n:e,f>1?r:t);while((f=(f+l+4)%4)!==s)}else c.point(a[0],a[1])}function f(i,u){return i>=n&&e>=i&&u>=t&&r>=u}function s(n,t){f(n,t)&&a.point(n,t)}function h(){C.point=g,d&&d.push(y=[]),S=!0,w=!1,b=_=NaN}function p(){v&&(g(m,M),x&&w&&E.rejoin(),v.push(E.buffer())),C.point=s,w&&a.lineEnd()}function g(n,t){n=Math.max(-Ha,Math.min(Ha,n)),t=Math.max(-Ha,Math.min(Ha,t));var e=f(n,t);if(d&&y.push([n,t]),S)m=n,M=t,x=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};A(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,y,m,M,x,b,_,w,S,k,N=a,E=Pt(),A=Yt(n,t,e,r),C={point:s,lineStart:h,lineEnd:p,polygonStart:function(){a=E,v=[],d=[],k=!0},polygonEnd:function(){a=N,v=ao.merge(v);var t=l([n,r]),e=k&&t,i=v.length;(e||i)&&(a.polygonStart(),e&&(a.lineStart(),c(null,null,1,a),a.lineEnd()),i&&Lt(v,u,t,c,a),a.polygonEnd()),v=d=y=null}};return C}}function Vt(n){var t=0,e=Fo/3,r=ae(n),i=r(t,e);return i.parallels=function(n){return arguments.length?r(t=n[0]*Fo/180,e=n[1]*Fo/180):[t/Fo*180,e/Fo*180]},i}function Xt(n,t){function e(n,t){var e=Math.sqrt(u-2*i*Math.sin(t))/i;return[e*Math.sin(n*=i),o-e*Math.cos(n)]}var r=Math.sin(n),i=(r+Math.sin(t))/2,u=1+r*(2*i-r),o=Math.sqrt(u)/i;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/i,tn((u-(n*n+e*e)*i*i)/(2*i))]},e}function $t(){function n(n,t){Ia+=i*n-r*t,r=n,i=t}var t,e,r,i;$a.point=function(u,o){$a.point=n,t=r=u,e=i=o},$a.lineEnd=function(){n(t,e)}}function Bt(n,t){Ya>n&&(Ya=n),n>Va&&(Va=n),Za>t&&(Za=t),t>Xa&&(Xa=t)}function Wt(){function n(n,t){o.push("M",n,",",t,u)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function i(){o.push("Z")}var u=Jt(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return u=Jt(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Jt(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Gt(n,t){Ca+=n,za+=t,++La}function Kt(){function n(n,r){var i=n-t,u=r-e,o=Math.sqrt(i*i+u*u);qa+=o*(t+n)/2,Ta+=o*(e+r)/2,Ra+=o,Gt(t=n,e=r)}var t,e;Wa.point=function(r,i){Wa.point=n,Gt(t=r,e=i)}}function Qt(){Wa.point=Gt}function ne(){function n(n,t){var e=n-r,u=t-i,o=Math.sqrt(e*e+u*u);qa+=o*(r+n)/2,Ta+=o*(i+t)/2,Ra+=o,o=i*n-r*t,Da+=o*(r+n),Pa+=o*(i+t),Ua+=3*o,Gt(r=n,i=t)}var t,e,r,i;Wa.point=function(u,o){Wa.point=n,Gt(t=r=u,e=i=o)},Wa.lineEnd=function(){n(t,e)}}function te(n){function t(t,e){n.moveTo(t+o,e),n.arc(t,e,o,0,Ho)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function i(){a.point=t}function u(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:i,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=i,a.point=t},pointRadius:function(n){return o=n,a},result:b};return a}function ee(n){function t(n){return(a?r:e)(n)}function e(t){return ue(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=NaN,S.point=u,t.lineStart()}function u(e,r){var u=dt([e,r]),o=n(e,r);i(M,x,m,b,_,w,M=o[0],x=o[1],m=e,b=u[0],_=u[1],w=u[2],a,t),t.point(M,x)}function o(){S.point=e,t.lineEnd()}function l(){ +r(),S.point=c,S.lineEnd=f}function c(n,t){u(s=n,h=t),p=M,g=x,v=b,d=_,y=w,S.point=u}function f(){i(M,x,m,b,_,w,p,g,s,v,d,y,a,t),S.lineEnd=o,o()}var s,h,p,g,v,d,y,m,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=l},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function i(t,e,r,a,l,c,f,s,h,p,g,v,d,y){var m=f-t,M=s-e,x=m*m+M*M;if(x>4*u&&d--){var b=a+p,_=l+g,w=c+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),N=xo(xo(w)-1)u||xo((m*z+M*L)/x-.5)>.3||o>a*p+l*g+c*v)&&(i(t,e,r,a,l,c,A,C,N,b/=S,_/=S,w,d,y),y.point(A,C),i(A,C,N,b,_,w,f,s,h,p,g,v,d,y))}}var u=.5,o=Math.cos(30*Yo),a=16;return t.precision=function(n){return arguments.length?(a=(u=n*n)>0&&16,t):Math.sqrt(u)},t}function re(n){var t=ee(function(t,e){return n([t*Zo,e*Zo])});return function(n){return le(t(n))}}function ie(n){this.stream=n}function ue(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function oe(n){return ae(function(){return n})()}function ae(n){function t(n){return n=a(n[0]*Yo,n[1]*Yo),[n[0]*h+l,c-n[1]*h]}function e(n){return n=a.invert((n[0]-l)/h,(c-n[1])/h),n&&[n[0]*Zo,n[1]*Zo]}function r(){a=Ct(o=se(y,M,x),u);var n=u(v,d);return l=p-n[0]*h,c=g+n[1]*h,i()}function i(){return f&&(f.valid=!1,f=null),t}var u,o,a,l,c,f,s=ee(function(n,t){return n=u(n,t),[n[0]*h+l,c-n[1]*h]}),h=150,p=480,g=250,v=0,d=0,y=0,M=0,x=0,b=Fa,_=m,w=null,S=null;return t.stream=function(n){return f&&(f.valid=!1),f=le(b(o,s(_(n)))),f.valid=!0,f},t.clipAngle=function(n){return arguments.length?(b=null==n?(w=n,Fa):It((w=+n)*Yo),i()):w},t.clipExtent=function(n){return arguments.length?(S=n,_=n?Zt(n[0][0],n[0][1],n[1][0],n[1][1]):m,i()):S},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(p=+n[0],g=+n[1],r()):[p,g]},t.center=function(n){return arguments.length?(v=n[0]%360*Yo,d=n[1]%360*Yo,r()):[v*Zo,d*Zo]},t.rotate=function(n){return arguments.length?(y=n[0]%360*Yo,M=n[1]%360*Yo,x=n.length>2?n[2]%360*Yo:0,r()):[y*Zo,M*Zo,x*Zo]},ao.rebind(t,s,"precision"),function(){return u=n.apply(this,arguments),t.invert=u.invert&&e,r()}}function le(n){return ue(n,function(t,e){n.point(t*Yo,e*Yo)})}function ce(n,t){return[n,t]}function fe(n,t){return[n>Fo?n-Ho:-Fo>n?n+Ho:n,t]}function se(n,t,e){return n?t||e?Ct(pe(n),ge(t,e)):pe(n):t||e?ge(t,e):fe}function he(n){return function(t,e){return t+=n,[t>Fo?t-Ho:-Fo>t?t+Ho:t,e]}}function pe(n){var t=he(n);return t.invert=he(-n),t}function ge(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),f=c*r+a*i;return[Math.atan2(l*u-f*o,a*r-c*i),tn(f*u+l*o)]}var r=Math.cos(n),i=Math.sin(n),u=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),f=c*u-l*o;return[Math.atan2(l*u+c*o,a*r+f*i),tn(f*r-a*i)]},e}function ve(n,t){var e=Math.cos(n),r=Math.sin(n);return function(i,u,o,a){var l=o*t;null!=i?(i=de(e,i),u=de(e,u),(o>0?u>i:i>u)&&(i+=o*Ho)):(i=n+o*Ho,u=n-.5*l);for(var c,f=i;o>0?f>u:u>f;f-=l)a.point((c=_t([e,-r*Math.cos(f),-r*Math.sin(f)]))[0],c[1])}}function de(n,t){var e=dt(t);e[0]-=n,bt(e);var r=nn(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Uo)%(2*Math.PI)}function ye(n,t,e){var r=ao.range(n,t-Uo,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function me(n,t,e){var r=ao.range(n,t-Uo,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function Me(n){return n.source}function xe(n){return n.target}function be(n,t,e,r){var i=Math.cos(t),u=Math.sin(t),o=Math.cos(r),a=Math.sin(r),l=i*Math.cos(n),c=i*Math.sin(n),f=o*Math.cos(e),s=o*Math.sin(e),h=2*Math.asin(Math.sqrt(on(r-t)+i*o*on(e-n))),p=1/Math.sin(h),g=h?function(n){var t=Math.sin(n*=h)*p,e=Math.sin(h-n)*p,r=e*l+t*f,i=e*c+t*s,o=e*u+t*a;return[Math.atan2(i,r)*Zo,Math.atan2(o,Math.sqrt(r*r+i*i))*Zo]}:function(){return[n*Zo,t*Zo]};return g.distance=h,g}function _e(){function n(n,i){var u=Math.sin(i*=Yo),o=Math.cos(i),a=xo((n*=Yo)-t),l=Math.cos(a);Ja+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*u-e*o*l)*a),e*u+r*o*l),t=n,e=u,r=o}var t,e,r;Ga.point=function(i,u){t=i*Yo,e=Math.sin(u*=Yo),r=Math.cos(u),Ga.point=n},Ga.lineEnd=function(){Ga.point=Ga.lineEnd=b}}function we(n,t){function e(t,e){var r=Math.cos(t),i=Math.cos(e),u=n(r*i);return[u*i*Math.sin(t),u*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),i=t(r),u=Math.sin(i),o=Math.cos(i);return[Math.atan2(n*u,r*o),Math.asin(r&&e*u/r)]},e}function Se(n,t){function e(n,t){o>0?-Io+Uo>t&&(t=-Io+Uo):t>Io-Uo&&(t=Io-Uo);var e=o/Math.pow(i(t),u);return[e*Math.sin(u*n),o-e*Math.cos(u*n)]}var r=Math.cos(n),i=function(n){return Math.tan(Fo/4+n/2)},u=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(i(t)/i(n)),o=r*Math.pow(i(n),u)/u;return u?(e.invert=function(n,t){var e=o-t,r=K(u)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/u,2*Math.atan(Math.pow(o/r,1/u))-Io]},e):Ne}function ke(n,t){function e(n,t){var e=u-t;return[e*Math.sin(i*n),u-e*Math.cos(i*n)]}var r=Math.cos(n),i=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),u=r/i+n;return xo(i)i;i++){for(;r>1&&Q(n[e[r-2]],n[e[r-1]],n[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function qe(n,t){return n[0]-t[0]||n[1]-t[1]}function Te(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Re(n,t,e,r){var i=n[0],u=e[0],o=t[0]-i,a=r[0]-u,l=n[1],c=e[1],f=t[1]-l,s=r[1]-c,h=(a*(l-c)-s*(i-u))/(s*o-a*f);return[i+h*o,l+h*f]}function De(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Pe(){rr(this),this.edge=this.site=this.circle=null}function Ue(n){var t=cl.pop()||new Pe;return t.site=n,t}function je(n){Be(n),ol.remove(n),cl.push(n),rr(n)}function Fe(n){var t=n.circle,e=t.x,r=t.cy,i={x:e,y:r},u=n.P,o=n.N,a=[n];je(n);for(var l=u;l.circle&&xo(e-l.circle.x)f;++f)c=a[f],l=a[f-1],nr(c.edge,l.site,c.site,i);l=a[0],c=a[s-1],c.edge=Ke(l.site,c.site,null,i),$e(l),$e(c)}function He(n){for(var t,e,r,i,u=n.x,o=n.y,a=ol._;a;)if(r=Oe(a,o)-u,r>Uo)a=a.L;else{if(i=u-Ie(a,o),!(i>Uo)){r>-Uo?(t=a.P,e=a):i>-Uo?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var l=Ue(n);if(ol.insert(t,l),t||e){if(t===e)return Be(t),e=Ue(t.site),ol.insert(l,e),l.edge=e.edge=Ke(t.site,l.site),$e(t),void $e(e);if(!e)return void(l.edge=Ke(t.site,l.site));Be(t),Be(e);var c=t.site,f=c.x,s=c.y,h=n.x-f,p=n.y-s,g=e.site,v=g.x-f,d=g.y-s,y=2*(h*d-p*v),m=h*h+p*p,M=v*v+d*d,x={x:(d*m-p*M)/y+f,y:(h*M-v*m)/y+s};nr(e.edge,c,g,x),l.edge=Ke(c,n,null,x),e.edge=Ke(n,g,null,x),$e(t),$e(e)}}function Oe(n,t){var e=n.site,r=e.x,i=e.y,u=i-t;if(!u)return r;var o=n.P;if(!o)return-(1/0);e=o.site;var a=e.x,l=e.y,c=l-t;if(!c)return a;var f=a-r,s=1/u-1/c,h=f/c;return s?(-h+Math.sqrt(h*h-2*s*(f*f/(-2*c)-l+c/2+i-u/2)))/s+r:(r+a)/2}function Ie(n,t){var e=n.N;if(e)return Oe(e,t);var r=n.site;return r.y===t?r.x:1/0}function Ye(n){this.site=n,this.edges=[]}function Ze(n){for(var t,e,r,i,u,o,a,l,c,f,s=n[0][0],h=n[1][0],p=n[0][1],g=n[1][1],v=ul,d=v.length;d--;)if(u=v[d],u&&u.prepare())for(a=u.edges,l=a.length,o=0;l>o;)f=a[o].end(),r=f.x,i=f.y,c=a[++o%l].start(),t=c.x,e=c.y,(xo(r-t)>Uo||xo(i-e)>Uo)&&(a.splice(o,0,new tr(Qe(u.site,f,xo(r-s)Uo?{x:s,y:xo(t-s)Uo?{x:xo(e-g)Uo?{x:h,y:xo(t-h)Uo?{x:xo(e-p)=-jo)){var p=l*l+c*c,g=f*f+s*s,v=(s*p-c*g)/h,d=(l*g-f*p)/h,s=d+a,y=fl.pop()||new Xe;y.arc=n,y.site=i,y.x=v+o,y.y=s+Math.sqrt(v*v+d*d),y.cy=s,n.circle=y;for(var m=null,M=ll._;M;)if(y.yd||d>=a)return;if(h>g){if(u){if(u.y>=c)return}else u={x:d,y:l};e={x:d,y:c}}else{if(u){if(u.yr||r>1)if(h>g){if(u){if(u.y>=c)return}else u={x:(l-i)/r,y:l};e={x:(c-i)/r,y:c}}else{if(u){if(u.yp){if(u){if(u.x>=a)return}else u={x:o,y:r*o+i};e={x:a,y:r*a+i}}else{if(u){if(u.xu||s>o||r>h||i>p)){if(g=n.point){var g,v=t-n.x,d=e-n.y,y=v*v+d*d;if(l>y){var m=Math.sqrt(l=y);r=t-m,i=e-m,u=t+m,o=e+m,a=g}}for(var M=n.nodes,x=.5*(f+h),b=.5*(s+p),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:c(n,f,s,x,b);break;case 1:c(n,x,s,h,b);break;case 2:c(n,f,b,x,p);break;case 3:c(n,x,b,h,p)}}}(n,r,i,u,o),a}function vr(n,t){n=ao.rgb(n),t=ao.rgb(t);var e=n.r,r=n.g,i=n.b,u=t.r-e,o=t.g-r,a=t.b-i;return function(n){return"#"+bn(Math.round(e+u*n))+bn(Math.round(r+o*n))+bn(Math.round(i+a*n))}}function dr(n,t){var e,r={},i={};for(e in n)e in t?r[e]=Mr(n[e],t[e]):i[e]=n[e];for(e in t)e in n||(i[e]=t[e]);return function(n){for(e in r)i[e]=r[e](n);return i}}function yr(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function mr(n,t){var e,r,i,u=hl.lastIndex=pl.lastIndex=0,o=-1,a=[],l=[];for(n+="",t+="";(e=hl.exec(n))&&(r=pl.exec(t));)(i=r.index)>u&&(i=t.slice(u,i),a[o]?a[o]+=i:a[++o]=i),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,l.push({i:o,x:yr(e,r)})),u=pl.lastIndex;return ur;++r)a[(e=l[r]).i]=e.x(n);return a.join("")})}function Mr(n,t){for(var e,r=ao.interpolators.length;--r>=0&&!(e=ao.interpolators[r](n,t)););return e}function xr(n,t){var e,r=[],i=[],u=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(Mr(n[e],t[e]));for(;u>e;++e)i[e]=n[e];for(;o>e;++e)i[e]=t[e];return function(n){for(e=0;a>e;++e)i[e]=r[e](n);return i}}function br(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function _r(n){return function(t){return 1-n(1-t)}}function wr(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function Sr(n){return n*n}function kr(n){return n*n*n}function Nr(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Er(n){return function(t){return Math.pow(t,n)}}function Ar(n){return 1-Math.cos(n*Io)}function Cr(n){return Math.pow(2,10*(n-1))}function zr(n){return 1-Math.sqrt(1-n*n)}function Lr(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/Ho*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*Ho/t)}}function qr(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Tr(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Rr(n,t){n=ao.hcl(n),t=ao.hcl(t);var e=n.h,r=n.c,i=n.l,u=t.h-e,o=t.c-r,a=t.l-i;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return sn(e+u*n,r+o*n,i+a*n)+""}}function Dr(n,t){n=ao.hsl(n),t=ao.hsl(t);var e=n.h,r=n.s,i=n.l,u=t.h-e,o=t.s-r,a=t.l-i;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return cn(e+u*n,r+o*n,i+a*n)+""}}function Pr(n,t){n=ao.lab(n),t=ao.lab(t);var e=n.l,r=n.a,i=n.b,u=t.l-e,o=t.a-r,a=t.b-i;return function(n){return pn(e+u*n,r+o*n,i+a*n)+""}}function Ur(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function jr(n){var t=[n.a,n.b],e=[n.c,n.d],r=Hr(t),i=Fr(t,e),u=Hr(Or(e,t,-i))||0;t[0]*e[1]180?t+=360:t-n>180&&(n+=360),r.push({i:e.push(Ir(e)+"rotate(",null,")")-2,x:yr(n,t)})):t&&e.push(Ir(e)+"rotate("+t+")")}function Vr(n,t,e,r){n!==t?r.push({i:e.push(Ir(e)+"skewX(",null,")")-2,x:yr(n,t)}):t&&e.push(Ir(e)+"skewX("+t+")")}function Xr(n,t,e,r){if(n[0]!==t[0]||n[1]!==t[1]){var i=e.push(Ir(e)+"scale(",null,",",null,")");r.push({i:i-4,x:yr(n[0],t[0])},{i:i-2,x:yr(n[1],t[1])})}else 1===t[0]&&1===t[1]||e.push(Ir(e)+"scale("+t+")")}function $r(n,t){var e=[],r=[];return n=ao.transform(n),t=ao.transform(t),Yr(n.translate,t.translate,e,r),Zr(n.rotate,t.rotate,e,r),Vr(n.skew,t.skew,e,r),Xr(n.scale,t.scale,e,r),n=t=null,function(n){for(var t,i=-1,u=r.length;++i=0;)e.push(i[r])}function oi(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(u=n.children)&&(i=u.length))for(var i,u,o=-1;++oe;++e)(t=n[e][1])>i&&(r=e,i=t);return r}function yi(n){return n.reduce(mi,0)}function mi(n,t){return n+t[1]}function Mi(n,t){return xi(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function xi(n,t){for(var e=-1,r=+n[0],i=(n[1]-r)/t,u=[];++e<=t;)u[e]=i*e+r;return u}function bi(n){return[ao.min(n),ao.max(n)]}function _i(n,t){return n.value-t.value}function wi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Si(n,t){n._pack_next=t,t._pack_prev=n}function ki(n,t){var e=t.x-n.x,r=t.y-n.y,i=n.r+t.r;return.999*i*i>e*e+r*r}function Ni(n){function t(n){f=Math.min(n.x-n.r,f),s=Math.max(n.x+n.r,s),h=Math.min(n.y-n.r,h),p=Math.max(n.y+n.r,p)}if((e=n.children)&&(c=e.length)){var e,r,i,u,o,a,l,c,f=1/0,s=-(1/0),h=1/0,p=-(1/0);if(e.forEach(Ei),r=e[0],r.x=-r.r,r.y=0,t(r),c>1&&(i=e[1],i.x=i.r,i.y=0,t(i),c>2))for(u=e[2],zi(r,i,u),t(u),wi(r,u),r._pack_prev=u,wi(u,i),i=r._pack_next,o=3;c>o;o++){zi(r,i,u=e[o]);var g=0,v=1,d=1;for(a=i._pack_next;a!==i;a=a._pack_next,v++)if(ki(a,u)){g=1;break}if(1==g)for(l=r._pack_prev;l!==a._pack_prev&&!ki(l,u);l=l._pack_prev,d++);g?(d>v||v==d&&i.ro;o++)u=e[o],u.x-=y,u.y-=m,M=Math.max(M,u.r+Math.sqrt(u.x*u.x+u.y*u.y));n.r=M,e.forEach(Ai)}}function Ei(n){n._pack_next=n._pack_prev=n}function Ai(n){delete n._pack_next,delete n._pack_prev}function Ci(n,t,e,r){var i=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,i)for(var u=-1,o=i.length;++u=0;)t=i[u],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Pi(n,t,e){return n.a.parent===t.parent?n.a:e}function Ui(n){return 1+ao.max(n,function(n){return n.y})}function ji(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Fi(n){var t=n.children;return t&&t.length?Fi(t[0]):n}function Hi(n){var t,e=n.children;return e&&(t=e.length)?Hi(e[t-1]):n}function Oi(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Ii(n,t){var e=n.x+t[3],r=n.y+t[0],i=n.dx-t[1]-t[3],u=n.dy-t[0]-t[2];return 0>i&&(e+=i/2,i=0),0>u&&(r+=u/2,u=0),{x:e,y:r,dx:i,dy:u}}function Yi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Zi(n){return n.rangeExtent?n.rangeExtent():Yi(n.range())}function Vi(n,t,e,r){var i=e(n[0],n[1]),u=r(t[0],t[1]);return function(n){return u(i(n))}}function Xi(n,t){var e,r=0,i=n.length-1,u=n[r],o=n[i];return u>o&&(e=r,r=i,i=e,e=u,u=o,o=e),n[r]=t.floor(u),n[i]=t.ceil(o),n}function $i(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:Sl}function Bi(n,t,e,r){var i=[],u=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]2?Bi:Vi,l=r?Wr:Br;return o=i(n,t,l,e),a=i(t,n,l,Mr),u}function u(n){return o(n)}var o,a;return u.invert=function(n){return a(n)},u.domain=function(t){return arguments.length?(n=t.map(Number),i()):n},u.range=function(n){return arguments.length?(t=n,i()):t},u.rangeRound=function(n){return u.range(n).interpolate(Ur)},u.clamp=function(n){return arguments.length?(r=n,i()):r},u.interpolate=function(n){return arguments.length?(e=n,i()):e},u.ticks=function(t){return Qi(n,t)},u.tickFormat=function(t,e){return nu(n,t,e)},u.nice=function(t){return Gi(n,t),i()},u.copy=function(){return Wi(n,t,e,r)},i()}function Ji(n,t){return ao.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Gi(n,t){return Xi(n,$i(Ki(n,t)[2])),Xi(n,$i(Ki(n,t)[2])),n}function Ki(n,t){null==t&&(t=10);var e=Yi(n),r=e[1]-e[0],i=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),u=t/r*i;return.15>=u?i*=10:.35>=u?i*=5:.75>=u&&(i*=2),e[0]=Math.ceil(e[0]/i)*i,e[1]=Math.floor(e[1]/i)*i+.5*i,e[2]=i,e}function Qi(n,t){return ao.range.apply(ao,Ki(n,t))}function nu(n,t,e){var r=Ki(n,t);if(e){var i=ha.exec(e);if(i.shift(),"s"===i[8]){var u=ao.formatPrefix(Math.max(xo(r[0]),xo(r[1])));return i[7]||(i[7]="."+tu(u.scale(r[2]))),i[8]="f",e=ao.format(i.join("")),function(n){return e(u.scale(n))+u.symbol}}i[7]||(i[7]="."+eu(i[8],r)),e=i.join("")}else e=",."+tu(r[2])+"f";return ao.format(e)}function tu(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function eu(n,t){var e=tu(t[2]);return n in kl?Math.abs(e-tu(Math.max(xo(t[0]),xo(t[1]))))+ +("e"!==n):e-2*("%"===n)}function ru(n,t,e,r){function i(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function u(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(i(t))}return o.invert=function(t){return u(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(i)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(i)),o):t},o.nice=function(){var t=Xi(r.map(i),e?Math:El);return n.domain(t),r=t.map(u),o},o.ticks=function(){var n=Yi(r),o=[],a=n[0],l=n[1],c=Math.floor(i(a)),f=Math.ceil(i(l)),s=t%1?2:t;if(isFinite(f-c)){if(e){for(;f>c;c++)for(var h=1;s>h;h++)o.push(u(c)*h);o.push(u(c))}else for(o.push(u(c));c++0;h--)o.push(u(c)*h);for(c=0;o[c]l;f--);o=o.slice(c,f)}return o},o.tickFormat=function(n,e){if(!arguments.length)return Nl;arguments.length<2?e=Nl:"function"!=typeof e&&(e=ao.format(e));var r=Math.max(1,t*n/o.ticks().length);return function(n){var o=n/u(Math.round(i(n)));return t-.5>o*t&&(o*=t),r>=o?e(n):""}},o.copy=function(){return ru(n.copy(),t,e,r)},Ji(o,n)}function iu(n,t,e){function r(t){return n(i(t))}var i=uu(t),u=uu(1/t);return r.invert=function(t){return u(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(i)),r):e},r.ticks=function(n){return Qi(e,n)},r.tickFormat=function(n,t){return nu(e,n,t)},r.nice=function(n){return r.domain(Gi(e,n))},r.exponent=function(o){return arguments.length?(i=uu(t=o),u=uu(1/t),n.domain(e.map(i)),r):t},r.copy=function(){return iu(n.copy(),t,e)},Ji(r,n)}function uu(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function ou(n,t){function e(e){return u[((i.get(e)||("range"===t.t?i.set(e,n.push(e)):NaN))-1)%u.length]}function r(t,e){return ao.range(n.length).map(function(n){return t+e*n})}var i,u,o;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new c;for(var u,o=-1,a=r.length;++oe?[NaN,NaN]:[e>0?a[e-1]:n[0],et?NaN:t/u+n,[t,t+1/u]},r.copy=function(){return lu(n,t,e)},i()}function cu(n,t){function e(e){return e>=e?t[ao.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return cu(n,t)},e}function fu(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Qi(n,t)},t.tickFormat=function(t,e){return nu(n,t,e)},t.copy=function(){return fu(n)},t}function su(){return 0}function hu(n){return n.innerRadius}function pu(n){return n.outerRadius}function gu(n){return n.startAngle}function vu(n){return n.endAngle}function du(n){return n&&n.padAngle}function yu(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function mu(n,t,e,r,i){var u=n[0]-t[0],o=n[1]-t[1],a=(i?r:-r)/Math.sqrt(u*u+o*o),l=a*o,c=-a*u,f=n[0]+l,s=n[1]+c,h=t[0]+l,p=t[1]+c,g=(f+h)/2,v=(s+p)/2,d=h-f,y=p-s,m=d*d+y*y,M=e-r,x=f*p-h*s,b=(0>y?-1:1)*Math.sqrt(Math.max(0,M*M*m-x*x)),_=(x*y-d*b)/m,w=(-x*d-y*b)/m,S=(x*y+d*b)/m,k=(-x*d+y*b)/m,N=_-g,E=w-v,A=S-g,C=k-v;return N*N+E*E>A*A+C*C&&(_=S,w=k),[[_-l,w-c],[_*e/M,w*e/M]]}function Mu(n){function t(t){function o(){c.push("M",u(n(f),a))}for(var l,c=[],f=[],s=-1,h=t.length,p=En(e),g=En(r);++s1?n.join("L"):n+"Z"}function bu(n){return n.join("L")+"Z"}function _u(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t1&&i.push("H",r[0]),i.join("")}function wu(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t1){a=t[1],u=n[l],l++,r+="C"+(i[0]+o[0])+","+(i[1]+o[1])+","+(u[0]-a[0])+","+(u[1]-a[1])+","+u[0]+","+u[1];for(var c=2;c9&&(i=3*t/Math.sqrt(i),o[a]=i*e,o[a+1]=i*r));for(a=-1;++a<=l;)i=(n[Math.min(l,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),u.push([i||0,o[a]*i||0]);return u}function Fu(n){return n.length<3?xu(n):n[0]+Au(n,ju(n))}function Hu(n){for(var t,e,r,i=-1,u=n.length;++i=t?o(n-t):void(f.c=o)}function o(e){var i=g.active,u=g[i];u&&(u.timer.c=null,u.timer.t=NaN,--g.count,delete g[i],u.event&&u.event.interrupt.call(n,n.__data__,u.index));for(var o in g)if(r>+o){var c=g[o];c.timer.c=null,c.timer.t=NaN,--g.count,delete g[o]}f.c=a,qn(function(){return f.c&&a(e||1)&&(f.c=null,f.t=NaN),1},0,l),g.active=r,v.event&&v.event.start.call(n,n.__data__,t),p=[],v.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&p.push(r)}),h=v.ease,s=v.duration}function a(i){for(var u=i/s,o=h(u),a=p.length;a>0;)p[--a].call(n,o);return u>=1?(v.event&&v.event.end.call(n,n.__data__,t),--g.count?delete g[r]:delete n[e],1):void 0}var l,f,s,h,p,g=n[e]||(n[e]={active:0,count:0}),v=g[r];v||(l=i.time,f=qn(u,0,l),v=g[r]={tween:new c,time:l,timer:f,delay:i.delay,duration:i.duration,ease:i.ease,index:t},i=null,++g.count)}function no(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function to(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function eo(n){return n.toISOString()}function ro(n,t,e){function r(t){return n(t)}function i(n,e){var r=n[1]-n[0],i=r/e,u=ao.bisect(Kl,i);return u==Kl.length?[t.year,Ki(n.map(function(n){return n/31536e6}),e)[2]]:u?t[i/Kl[u-1]1?{floor:function(t){for(;e(t=n.floor(t));)t=io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Yi(r.domain()),u=null==n?i(e,10):"number"==typeof n?i(e,n):!n.range&&[{range:n},t];return u&&(n=u[0],t=u[1]),n.range(e[0],io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return ro(n.copy(),t,e)},Ji(r,n)}function io(n){return new Date(n)}function uo(n){return JSON.parse(n.responseText)}function oo(n){var t=fo.createRange();return t.selectNode(fo.body),t.createContextualFragment(n.responseText)}var ao={version:"3.5.17"},lo=[].slice,co=function(n){return lo.call(n)},fo=this.document;if(fo)try{co(fo.documentElement.childNodes)[0].nodeType}catch(so){co=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}if(Date.now||(Date.now=function(){return+new Date}),fo)try{fo.createElement("DIV").style.setProperty("opacity",0,"")}catch(ho){var po=this.Element.prototype,go=po.setAttribute,vo=po.setAttributeNS,yo=this.CSSStyleDeclaration.prototype,mo=yo.setProperty;po.setAttribute=function(n,t){go.call(this,n,t+"")},po.setAttributeNS=function(n,t,e){vo.call(this,n,t,e+"")},yo.setProperty=function(n,t,e){mo.call(this,n,t+"",e)}}ao.ascending=e,ao.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:NaN},ao.min=function(n,t){var e,r,i=-1,u=n.length;if(1===arguments.length){for(;++i=r){e=r;break}for(;++ir&&(e=r)}else{for(;++i=r){e=r;break}for(;++ir&&(e=r)}return e},ao.max=function(n,t){var e,r,i=-1,u=n.length;if(1===arguments.length){for(;++i=r){e=r;break}for(;++ie&&(e=r)}else{for(;++i=r){e=r;break}for(;++ie&&(e=r)}return e},ao.extent=function(n,t){var e,r,i,u=-1,o=n.length;if(1===arguments.length){for(;++u=r){e=i=r;break}for(;++ur&&(e=r),r>i&&(i=r))}else{for(;++u=r){e=i=r;break}for(;++ur&&(e=r),r>i&&(i=r))}return[e,i]},ao.sum=function(n,t){var e,r=0,u=n.length,o=-1;if(1===arguments.length)for(;++o1?l/(f-1):void 0},ao.deviation=function(){var n=ao.variance.apply(this,arguments);return n?Math.sqrt(n):n};var Mo=u(e);ao.bisectLeft=Mo.left,ao.bisect=ao.bisectRight=Mo.right,ao.bisector=function(n){return u(1===n.length?function(t,r){return e(n(t),r)}:n)},ao.shuffle=function(n,t,e){(u=arguments.length)<3&&(e=n.length,2>u&&(t=0));for(var r,i,u=e-t;u;)i=Math.random()*u--|0,r=n[u+t],n[u+t]=n[i+t],n[i+t]=r;return n},ao.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ao.pairs=function(n){for(var t,e=0,r=n.length-1,i=n[0],u=new Array(0>r?0:r);r>e;)u[e]=[t=i,i=n[++e]];return u},ao.transpose=function(n){if(!(i=n.length))return[];for(var t=-1,e=ao.min(n,o),r=new Array(e);++t=0;)for(r=n[i],t=r.length;--t>=0;)e[--o]=r[t];return e};var xo=Math.abs;ao.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error("infinite range");var r,i=[],u=a(xo(e)),o=-1;if(n*=u,t*=u,e*=u,0>e)for(;(r=n+e*++o)>t;)i.push(r/u);else for(;(r=n+e*++o)=u.length)return r?r.call(i,o):e?o.sort(e):o;for(var l,f,s,h,p=-1,g=o.length,v=u[a++],d=new c;++p=u.length)return n;var r=[],i=o[e++];return n.forEach(function(n,i){r.push({key:n,values:t(i,e)})}),i?r.sort(function(n,t){return i(n.key,t.key)}):r}var e,r,i={},u=[],o=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(ao.map,e,0),0)},i.key=function(n){return u.push(n),i},i.sortKeys=function(n){return o[u.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},ao.set=function(n){var t=new y;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},l(y,{has:h,add:function(n){return this._[f(n+="")]=!0,n},remove:p,values:g,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,s(t))}}),ao.behavior={},ao.rebind=function(n,t){for(var e,r=1,i=arguments.length;++r=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ao.event=null,ao.requote=function(n){return n.replace(So,"\\$&")};var So=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,ko={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},No=function(n,t){return t.querySelector(n)},Eo=function(n,t){return t.querySelectorAll(n)},Ao=function(n,t){var e=n.matches||n[x(n,"matchesSelector")];return(Ao=function(n,t){return e.call(n,t)})(n,t)};"function"==typeof Sizzle&&(No=function(n,t){return Sizzle(n,t)[0]||null},Eo=Sizzle,Ao=Sizzle.matchesSelector),ao.selection=function(){return ao.select(fo.documentElement)};var Co=ao.selection.prototype=[];Co.select=function(n){var t,e,r,i,u=[];n=A(n);for(var o=-1,a=this.length;++o=0&&"xmlns"!==(e=n.slice(0,t))&&(n=n.slice(t+1)),Lo.hasOwnProperty(e)?{space:Lo[e],local:n}:n}},Co.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ao.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},Co.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=T(n)).length,i=-1;if(t=e.classList){for(;++ii){if("string"!=typeof n){2>i&&(e="");for(r in n)this.each(P(r,n[r],e));return this}if(2>i){var u=this.node();return t(u).getComputedStyle(u,null).getPropertyValue(n)}r=""}return this.each(P(n,e,r))},Co.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(U(t,n[t]));return this}return this.each(U(n,t))},Co.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},Co.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},Co.append=function(n){return n=j(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},Co.insert=function(n,t){return n=j(n),t=A(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},Co.remove=function(){return this.each(F)},Co.data=function(n,t){function e(n,e){var r,i,u,o=n.length,s=e.length,h=Math.min(o,s),p=new Array(s),g=new Array(s),v=new Array(o);if(t){var d,y=new c,m=new Array(o);for(r=-1;++rr;++r)g[r]=H(e[r]);for(;o>r;++r)v[r]=n[r]}g.update=p,g.parentNode=p.parentNode=v.parentNode=n.parentNode,a.push(g),l.push(p),f.push(v)}var r,i,u=-1,o=this.length;if(!arguments.length){for(n=new Array(o=(r=this[0]).length);++uu;u++){i.push(t=[]),t.parentNode=(e=this[u]).parentNode;for(var a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return E(i)},Co.order=function(){for(var n=-1,t=this.length;++n=0;)(e=r[i])&&(u&&u!==e.nextSibling&&u.parentNode.insertBefore(e,u),u=e);return this},Co.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++tn;n++)for(var e=this[n],r=0,i=e.length;i>r;r++){var u=e[r];if(u)return u}return null},Co.size=function(){var n=0;return Y(this,function(){++n}),n};var qo=[];ao.selection.enter=Z,ao.selection.enter.prototype=qo,qo.append=Co.append,qo.empty=Co.empty,qo.node=Co.node,qo.call=Co.call,qo.size=Co.size,qo.select=function(n){for(var t,e,r,i,u,o=[],a=-1,l=this.length;++ar){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(X(n,t,e))};var To=ao.map({mouseenter:"mouseover",mouseleave:"mouseout"});fo&&To.forEach(function(n){"on"+n in fo&&To.remove(n)});var Ro,Do=0;ao.mouse=function(n){return J(n,k())};var Po=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;ao.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,i=0,u=t.length;u>i;++i)if((r=t[i]).identifier===e)return J(n,r)},ao.behavior.drag=function(){function n(){this.on("mousedown.drag",u).on("touchstart.drag",o)}function e(n,t,e,u,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],g|=n|e,M=r,p({type:"drag",x:r[0]+c[0],y:r[1]+c[1],dx:n,dy:e}))}function l(){t(h,v)&&(y.on(u+d,null).on(o+d,null),m(g),p({type:"dragend"}))}var c,f=this,s=ao.event.target.correspondingElement||ao.event.target,h=f.parentNode,p=r.of(f,arguments),g=0,v=n(),d=".drag"+(null==v?"":"-"+v),y=ao.select(e(s)).on(u+d,a).on(o+d,l),m=W(s),M=t(h,v);i?(c=i.apply(f,arguments),c=[c.x-M[0],c.y-M[1]]):c=[0,0],p({type:"dragstart"})}}var r=N(n,"drag","dragstart","dragend"),i=null,u=e(b,ao.mouse,t,"mousemove","mouseup"),o=e(G,ao.touch,m,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},ao.rebind(n,r,"on")},ao.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?co(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Uo=1e-6,jo=Uo*Uo,Fo=Math.PI,Ho=2*Fo,Oo=Ho-Uo,Io=Fo/2,Yo=Fo/180,Zo=180/Fo,Vo=Math.SQRT2,Xo=2,$o=4;ao.interpolateZoom=function(n,t){var e,r,i=n[0],u=n[1],o=n[2],a=t[0],l=t[1],c=t[2],f=a-i,s=l-u,h=f*f+s*s;if(jo>h)r=Math.log(c/o)/Vo,e=function(n){return[i+n*f,u+n*s,o*Math.exp(Vo*n*r)]};else{var p=Math.sqrt(h),g=(c*c-o*o+$o*h)/(2*o*Xo*p),v=(c*c-o*o-$o*h)/(2*c*Xo*p),d=Math.log(Math.sqrt(g*g+1)-g),y=Math.log(Math.sqrt(v*v+1)-v);r=(y-d)/Vo,e=function(n){var t=n*r,e=rn(d),a=o/(Xo*p)*(e*un(Vo*t+d)-en(d));return[i+a*f,u+a*s,o*e/rn(Vo*t+d)]}}return e.duration=1e3*r,e},ao.behavior.zoom=function(){function n(n){n.on(L,s).on(Wo+".zoom",p).on("dblclick.zoom",g).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,n[1]*k.k+k.y]}function i(n){k.k=Math.max(A[0],Math.min(A[1],n))}function u(n,t){t=r(t),k.x+=n[0]-t[0],k.y+=n[1]-t[1]}function o(t,e,r,o){t.__chart__={x:k.x,y:k.y,k:k.k},i(Math.pow(2,o)),u(d=e,r),t=ao.select(t),C>0&&(t=t.transition().duration(C)),t.call(n.event)}function a(){b&&b.domain(x.range().map(function(n){return(n-k.x)/k.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-k.y)/k.k}).map(_.invert))}function l(n){z++||n({type:"zoomstart"})}function c(n){a(),n({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function f(n){--z||(n({type:"zoomend"}),d=null)}function s(){function n(){a=1,u(ao.mouse(i),h),c(o)}function r(){s.on(q,null).on(T,null),p(a),f(o)}var i=this,o=D.of(i,arguments),a=0,s=ao.select(t(i)).on(q,n).on(T,r),h=e(ao.mouse(i)),p=W(i);Il.call(i),l(o)}function h(){function n(){var n=ao.touches(g);return p=k.k,n.forEach(function(n){n.identifier in d&&(d[n.identifier]=e(n))}),n}function t(){var t=ao.event.target;ao.select(t).on(x,r).on(b,a),_.push(t);for(var e=ao.event.changedTouches,i=0,u=e.length;u>i;++i)d[e[i].identifier]=null;var l=n(),c=Date.now();if(1===l.length){if(500>c-M){var f=l[0];o(g,f,d[f.identifier],Math.floor(Math.log(k.k)/Math.LN2)+1),S()}M=c}else if(l.length>1){var f=l[0],s=l[1],h=f[0]-s[0],p=f[1]-s[1];y=h*h+p*p}}function r(){var n,t,e,r,o=ao.touches(g);Il.call(g);for(var a=0,l=o.length;l>a;++a,r=null)if(e=o[a],r=d[e.identifier]){if(t)break;n=e,t=r}if(r){var f=(f=e[0]-n[0])*f+(f=e[1]-n[1])*f,s=y&&Math.sqrt(f/y);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+r[0])/2,(t[1]+r[1])/2],i(s*p)}M=null,u(n,t),c(v)}function a(){if(ao.event.touches.length){for(var t=ao.event.changedTouches,e=0,r=t.length;r>e;++e)delete d[t[e].identifier];for(var i in d)return void n()}ao.selectAll(_).on(m,null),w.on(L,s).on(R,h),N(),f(v)}var p,g=this,v=D.of(g,arguments),d={},y=0,m=".zoom-"+ao.event.changedTouches[0].identifier,x="touchmove"+m,b="touchend"+m,_=[],w=ao.select(g),N=W(g);t(),l(v),w.on(L,null).on(R,t)}function p(){var n=D.of(this,arguments);m?clearTimeout(m):(Il.call(this),v=e(d=y||ao.mouse(this)),l(n)),m=setTimeout(function(){m=null,f(n)},50),S(),i(Math.pow(2,.002*Bo())*k.k),u(d,v),c(n)}function g(){var n=ao.mouse(this),t=Math.log(k.k)/Math.LN2;o(this,n,e(n),ao.event.shiftKey?Math.ceil(t)-1:Math.floor(t)+1)}var v,d,y,m,M,x,b,_,w,k={x:0,y:0,k:1},E=[960,500],A=Jo,C=250,z=0,L="mousedown.zoom",q="mousemove.zoom",T="mouseup.zoom",R="touchstart.zoom",D=N(n,"zoomstart","zoom","zoomend");return Wo||(Wo="onwheel"in fo?(Bo=function(){return-ao.event.deltaY*(ao.event.deltaMode?120:1)},"wheel"):"onmousewheel"in fo?(Bo=function(){return ao.event.wheelDelta},"mousewheel"):(Bo=function(){return-ao.event.detail},"MozMousePixelScroll")),n.event=function(n){n.each(function(){var n=D.of(this,arguments),t=k;Hl?ao.select(this).transition().each("start.zoom",function(){k=this.__chart__||{x:0,y:0,k:1},l(n)}).tween("zoom:zoom",function(){var e=E[0],r=E[1],i=d?d[0]:e/2,u=d?d[1]:r/2,o=ao.interpolateZoom([(i-k.x)/k.k,(u-k.y)/k.k,e/k.k],[(i-t.x)/t.k,(u-t.y)/t.k,e/t.k]);return function(t){var r=o(t),a=e/r[2];this.__chart__=k={x:i-r[0]*a,y:u-r[1]*a,k:a},c(n)}}).each("interrupt.zoom",function(){f(n)}).each("end.zoom",function(){f(n)}):(this.__chart__=k,l(n),c(n),f(n))})},n.translate=function(t){return arguments.length?(k={x:+t[0],y:+t[1],k:k.k},a(),n):[k.x,k.y]},n.scale=function(t){return arguments.length?(k={x:k.x,y:k.y,k:null},i(+t),a(),n):k.k},n.scaleExtent=function(t){return arguments.length?(A=null==t?Jo:[+t[0],+t[1]],n):A},n.center=function(t){return arguments.length?(y=t&&[+t[0],+t[1]],n):y},n.size=function(t){return arguments.length?(E=t&&[+t[0],+t[1]],n):E},n.duration=function(t){return arguments.length?(C=+t,n):C},n.x=function(t){return arguments.length?(b=t,x=t.copy(),k={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),k={x:0,y:0,k:1},n):w},ao.rebind(n,D,"on")};var Bo,Wo,Jo=[0,1/0];ao.color=an,an.prototype.toString=function(){return this.rgb()+""},ao.hsl=ln;var Go=ln.prototype=new an;Go.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,this.l/n)},Go.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,n*this.l)},Go.rgb=function(){return cn(this.h,this.s,this.l)},ao.hcl=fn;var Ko=fn.prototype=new an;Ko.brighter=function(n){return new fn(this.h,this.c,Math.min(100,this.l+Qo*(arguments.length?n:1)))},Ko.darker=function(n){return new fn(this.h,this.c,Math.max(0,this.l-Qo*(arguments.length?n:1)))},Ko.rgb=function(){return sn(this.h,this.c,this.l).rgb()},ao.lab=hn;var Qo=18,na=.95047,ta=1,ea=1.08883,ra=hn.prototype=new an;ra.brighter=function(n){return new hn(Math.min(100,this.l+Qo*(arguments.length?n:1)),this.a,this.b)},ra.darker=function(n){return new hn(Math.max(0,this.l-Qo*(arguments.length?n:1)),this.a,this.b)},ra.rgb=function(){return pn(this.l,this.a,this.b)},ao.rgb=mn;var ia=mn.prototype=new an;ia.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,i=30;return t||e||r?(t&&i>t&&(t=i),e&&i>e&&(e=i),r&&i>r&&(r=i),new mn(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new mn(i,i,i)},ia.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new mn(n*this.r,n*this.g,n*this.b)},ia.hsl=function(){return wn(this.r,this.g,this.b)},ia.toString=function(){return"#"+bn(this.r)+bn(this.g)+bn(this.b)};var ua=ao.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});ua.forEach(function(n,t){ua.set(n,Mn(t))}),ao.functor=En,ao.xhr=An(m),ao.dsv=function(n,t){function e(n,e,u){arguments.length<3&&(u=e,e=null);var o=Cn(n,t,null==e?r:i(e),u);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:i(n)):e},o}function r(n){return e.parse(n.responseText)}function i(n){return function(t){return e.parse(t.responseText,n)}}function u(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),l=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var i=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(i(n),e)}:i})},e.parseRows=function(n,t){function e(){if(f>=c)return o;if(i)return i=!1,u;var t=f;if(34===n.charCodeAt(t)){for(var e=t;e++f;){var r=n.charCodeAt(f++),a=1;if(10===r)i=!0;else if(13===r)i=!0,10===n.charCodeAt(f)&&(++f,++a);else if(r!==l)continue;return n.slice(t,f-a)}return n.slice(t)}for(var r,i,u={},o={},a=[],c=n.length,f=0,s=0;(r=e())!==o;){for(var h=[];r!==u&&r!==o;)h.push(r),r=e();t&&null==(h=t(h,s++))||a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new y,i=[];return t.forEach(function(n){for(var t in n)r.has(t)||i.push(r.add(t))}),[i.map(o).join(n)].concat(t.map(function(t){return i.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(u).join("\n")},e},ao.csv=ao.dsv(",","text/csv"),ao.tsv=ao.dsv(" ","text/tab-separated-values");var oa,aa,la,ca,fa=this[x(this,"requestAnimationFrame")]||function(n){setTimeout(n,17)};ao.timer=function(){qn.apply(this,arguments)},ao.timer.flush=function(){Rn(),Dn()},ao.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var sa=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Un);ao.formatPrefix=function(n,t){var e=0;return(n=+n)&&(0>n&&(n*=-1),t&&(n=ao.round(n,Pn(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),sa[8+e/3]};var ha=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,pa=ao.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=ao.round(n,Pn(n,t))).toFixed(Math.max(0,Math.min(20,Pn(n*(1+1e-15),t))))}}),ga=ao.time={},va=Date;Hn.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){da.setUTCDate.apply(this._,arguments)},setDay:function(){da.setUTCDay.apply(this._,arguments)},setFullYear:function(){da.setUTCFullYear.apply(this._,arguments)},setHours:function(){da.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){da.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){da.setUTCMinutes.apply(this._,arguments)},setMonth:function(){da.setUTCMonth.apply(this._,arguments)},setSeconds:function(){da.setUTCSeconds.apply(this._,arguments)},setTime:function(){da.setTime.apply(this._,arguments)}};var da=Date.prototype;ga.year=On(function(n){return n=ga.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ga.years=ga.year.range,ga.years.utc=ga.year.utc.range,ga.day=On(function(n){var t=new va(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ga.days=ga.day.range,ga.days.utc=ga.day.utc.range,ga.dayOfYear=function(n){var t=ga.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=ga[n]=On(function(n){return(n=ga.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=ga.year(n).getDay();return Math.floor((ga.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ga[n+"s"]=e.range,ga[n+"s"].utc=e.utc.range,ga[n+"OfYear"]=function(n){var e=ga.year(n).getDay();return Math.floor((ga.dayOfYear(n)+(e+t)%7)/7)}}),ga.week=ga.sunday,ga.weeks=ga.sunday.range,ga.weeks.utc=ga.sunday.utc.range,ga.weekOfYear=ga.sundayOfYear;var ya={"-":"",_:" ",0:"0"},ma=/^\s*\d+/,Ma=/^%/;ao.locale=function(n){return{numberFormat:jn(n),timeFormat:Yn(n)}};var xa=ao.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"], +shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});ao.format=xa.numberFormat,ao.geo={},ft.prototype={s:0,t:0,add:function(n){st(n,this.t,ba),st(ba.s,this.s,this),this.s?this.t+=ba.t:this.s=ba.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var ba=new ft;ao.geo.stream=function(n,t){n&&_a.hasOwnProperty(n.type)?_a[n.type](n,t):ht(n,t)};var _a={Feature:function(n,t){ht(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,i=e.length;++rn?4*Fo+n:n,Na.lineStart=Na.lineEnd=Na.point=b}};ao.geo.bounds=function(){function n(n,t){M.push(x=[f=n,h=n]),s>t&&(s=t),t>p&&(p=t)}function t(t,e){var r=dt([t*Yo,e*Yo]);if(y){var i=mt(y,r),u=[i[1],-i[0],0],o=mt(u,i);bt(o),o=_t(o);var l=t-g,c=l>0?1:-1,v=o[0]*Zo*c,d=xo(l)>180;if(d^(v>c*g&&c*t>v)){var m=o[1]*Zo;m>p&&(p=m)}else if(v=(v+360)%360-180,d^(v>c*g&&c*t>v)){var m=-o[1]*Zo;s>m&&(s=m)}else s>e&&(s=e),e>p&&(p=e);d?g>t?a(f,t)>a(f,h)&&(h=t):a(t,h)>a(f,h)&&(f=t):h>=f?(f>t&&(f=t),t>h&&(h=t)):t>g?a(f,t)>a(f,h)&&(h=t):a(t,h)>a(f,h)&&(f=t)}else n(t,e);y=r,g=t}function e(){b.point=t}function r(){x[0]=f,x[1]=h,b.point=n,y=null}function i(n,e){if(y){var r=n-g;m+=xo(r)>180?r+(r>0?360:-360):r}else v=n,d=e;Na.point(n,e),t(n,e)}function u(){Na.lineStart()}function o(){i(v,d),Na.lineEnd(),xo(m)>Uo&&(f=-(h=180)),x[0]=f,x[1]=h,y=null}function a(n,t){return(t-=n)<0?t+360:t}function l(n,t){return n[0]-t[0]}function c(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:nka?(f=-(h=180),s=-(p=90)):m>Uo?p=90:-Uo>m&&(s=-90),x[0]=f,x[1]=h}};return function(n){p=h=-(f=s=1/0),M=[],ao.geo.stream(n,b);var t=M.length;if(t){M.sort(l);for(var e,r=1,i=M[0],u=[i];t>r;++r)e=M[r],c(e[0],i)||c(e[1],i)?(a(i[0],e[1])>a(i[0],i[1])&&(i[1]=e[1]),a(e[0],i[1])>a(i[0],i[1])&&(i[0]=e[0])):u.push(i=e);for(var o,e,g=-(1/0),t=u.length-1,r=0,i=u[t];t>=r;i=e,++r)e=u[r],(o=a(i[1],e[0]))>g&&(g=o,f=e[0],h=i[1])}return M=x=null,f===1/0||s===1/0?[[NaN,NaN],[NaN,NaN]]:[[f,s],[h,p]]}}(),ao.geo.centroid=function(n){Ea=Aa=Ca=za=La=qa=Ta=Ra=Da=Pa=Ua=0,ao.geo.stream(n,ja);var t=Da,e=Pa,r=Ua,i=t*t+e*e+r*r;return jo>i&&(t=qa,e=Ta,r=Ra,Uo>Aa&&(t=Ca,e=za,r=La),i=t*t+e*e+r*r,jo>i)?[NaN,NaN]:[Math.atan2(e,t)*Zo,tn(r/Math.sqrt(i))*Zo]};var Ea,Aa,Ca,za,La,qa,Ta,Ra,Da,Pa,Ua,ja={sphere:b,point:St,lineStart:Nt,lineEnd:Et,polygonStart:function(){ja.lineStart=At},polygonEnd:function(){ja.lineStart=Nt}},Fa=Rt(zt,jt,Ht,[-Fo,-Fo/2]),Ha=1e9;ao.geo.clipExtent=function(){var n,t,e,r,i,u,o={stream:function(n){return i&&(i.valid=!1),i=u(n),i.valid=!0,i},extent:function(a){return arguments.length?(u=Zt(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),i&&(i.valid=!1,i=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(ao.geo.conicEqualArea=function(){return Vt(Xt)}).raw=Xt,ao.geo.albers=function(){return ao.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},ao.geo.albersUsa=function(){function n(n){var u=n[0],o=n[1];return t=null,e(u,o),t||(r(u,o),t)||i(u,o),t}var t,e,r,i,u=ao.geo.albers(),o=ao.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=ao.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=u.scale(),e=u.translate(),r=(n[0]-e[0])/t,i=(n[1]-e[1])/t;return(i>=.12&&.234>i&&r>=-.425&&-.214>r?o:i>=.166&&.234>i&&r>=-.214&&-.115>r?a:u).invert(n)},n.stream=function(n){var t=u.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,i){t.point(n,i),e.point(n,i),r.point(n,i)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(u.precision(t),o.precision(t),a.precision(t),n):u.precision()},n.scale=function(t){return arguments.length?(u.scale(t),o.scale(.35*t),a.scale(t),n.translate(u.translate())):u.scale()},n.translate=function(t){if(!arguments.length)return u.translate();var c=u.scale(),f=+t[0],s=+t[1];return e=u.translate(t).clipExtent([[f-.455*c,s-.238*c],[f+.455*c,s+.238*c]]).stream(l).point,r=o.translate([f-.307*c,s+.201*c]).clipExtent([[f-.425*c+Uo,s+.12*c+Uo],[f-.214*c-Uo,s+.234*c-Uo]]).stream(l).point,i=a.translate([f-.205*c,s+.212*c]).clipExtent([[f-.214*c+Uo,s+.166*c+Uo],[f-.115*c-Uo,s+.234*c-Uo]]).stream(l).point,n},n.scale(1070)};var Oa,Ia,Ya,Za,Va,Xa,$a={point:b,lineStart:b,lineEnd:b,polygonStart:function(){Ia=0,$a.lineStart=$t},polygonEnd:function(){$a.lineStart=$a.lineEnd=$a.point=b,Oa+=xo(Ia/2)}},Ba={point:Bt,lineStart:b,lineEnd:b,polygonStart:b,polygonEnd:b},Wa={point:Gt,lineStart:Kt,lineEnd:Qt,polygonStart:function(){Wa.lineStart=ne},polygonEnd:function(){Wa.point=Gt,Wa.lineStart=Kt,Wa.lineEnd=Qt}};ao.geo.path=function(){function n(n){return n&&("function"==typeof a&&u.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=i(u)),ao.geo.stream(n,o)),u.result()}function t(){return o=null,n}var e,r,i,u,o,a=4.5;return n.area=function(n){return Oa=0,ao.geo.stream(n,i($a)),Oa},n.centroid=function(n){return Ca=za=La=qa=Ta=Ra=Da=Pa=Ua=0,ao.geo.stream(n,i(Wa)),Ua?[Da/Ua,Pa/Ua]:Ra?[qa/Ra,Ta/Ra]:La?[Ca/La,za/La]:[NaN,NaN]},n.bounds=function(n){return Va=Xa=-(Ya=Za=1/0),ao.geo.stream(n,i(Ba)),[[Ya,Za],[Va,Xa]]},n.projection=function(n){return arguments.length?(i=(e=n)?n.stream||re(n):m,t()):e},n.context=function(n){return arguments.length?(u=null==(r=n)?new Wt:new te(n),"function"!=typeof a&&u.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(u.pointRadius(+t),+t),n):a},n.projection(ao.geo.albersUsa()).context(null)},ao.geo.transform=function(n){return{stream:function(t){var e=new ie(t);for(var r in n)e[r]=n[r];return e}}},ie.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},ao.geo.projection=oe,ao.geo.projectionMutator=ae,(ao.geo.equirectangular=function(){return oe(ce)}).raw=ce.invert=ce,ao.geo.rotation=function(n){function t(t){return t=n(t[0]*Yo,t[1]*Yo),t[0]*=Zo,t[1]*=Zo,t}return n=se(n[0]%360*Yo,n[1]*Yo,n.length>2?n[2]*Yo:0),t.invert=function(t){return t=n.invert(t[0]*Yo,t[1]*Yo),t[0]*=Zo,t[1]*=Zo,t},t},fe.invert=ce,ao.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=se(-n[0]*Yo,-n[1]*Yo,0).invert,i=[];return e(null,null,1,{point:function(n,e){i.push(n=t(n,e)),n[0]*=Zo,n[1]*=Zo}}),{type:"Polygon",coordinates:[i]}}var t,e,r=[0,0],i=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=ve((t=+r)*Yo,i*Yo),n):t},n.precision=function(r){return arguments.length?(e=ve(t*Yo,(i=+r)*Yo),n):i},n.angle(90)},ao.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Yo,i=n[1]*Yo,u=t[1]*Yo,o=Math.sin(r),a=Math.cos(r),l=Math.sin(i),c=Math.cos(i),f=Math.sin(u),s=Math.cos(u);return Math.atan2(Math.sqrt((e=s*o)*e+(e=c*f-l*s*a)*e),l*f+c*s*a)},ao.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return ao.range(Math.ceil(u/d)*d,i,d).map(h).concat(ao.range(Math.ceil(c/y)*y,l,y).map(p)).concat(ao.range(Math.ceil(r/g)*g,e,g).filter(function(n){return xo(n%d)>Uo}).map(f)).concat(ao.range(Math.ceil(a/v)*v,o,v).filter(function(n){return xo(n%y)>Uo}).map(s))}var e,r,i,u,o,a,l,c,f,s,h,p,g=10,v=g,d=90,y=360,m=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(u).concat(p(l).slice(1),h(i).reverse().slice(1),p(c).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(u=+t[0][0],i=+t[1][0],c=+t[0][1],l=+t[1][1],u>i&&(t=u,u=i,i=t),c>l&&(t=c,c=l,l=t),n.precision(m)):[[u,c],[i,l]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(m)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],y=+t[1],n):[d,y]},n.minorStep=function(t){return arguments.length?(g=+t[0],v=+t[1],n):[g,v]},n.precision=function(t){return arguments.length?(m=+t,f=ye(a,o,90),s=me(r,e,m),h=ye(c,l,90),p=me(u,i,m),n):m},n.majorExtent([[-180,-90+Uo],[180,90-Uo]]).minorExtent([[-180,-80-Uo],[180,80+Uo]])},ao.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||i.apply(this,arguments)]}}var t,e,r=Me,i=xe;return n.distance=function(){return ao.geo.distance(t||r.apply(this,arguments),e||i.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(i=t,e="function"==typeof t?null:t,n):i},n.precision=function(){return arguments.length?n:0},n},ao.geo.interpolate=function(n,t){return be(n[0]*Yo,n[1]*Yo,t[0]*Yo,t[1]*Yo)},ao.geo.length=function(n){return Ja=0,ao.geo.stream(n,Ga),Ja};var Ja,Ga={sphere:b,point:b,lineStart:_e,lineEnd:b,polygonStart:b,polygonEnd:b},Ka=we(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(ao.geo.azimuthalEqualArea=function(){return oe(Ka)}).raw=Ka;var Qa=we(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},m);(ao.geo.azimuthalEquidistant=function(){return oe(Qa)}).raw=Qa,(ao.geo.conicConformal=function(){return Vt(Se)}).raw=Se,(ao.geo.conicEquidistant=function(){return Vt(ke)}).raw=ke;var nl=we(function(n){return 1/n},Math.atan);(ao.geo.gnomonic=function(){return oe(nl)}).raw=nl,Ne.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Io]},(ao.geo.mercator=function(){return Ee(Ne)}).raw=Ne;var tl=we(function(){return 1},Math.asin);(ao.geo.orthographic=function(){return oe(tl)}).raw=tl;var el=we(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(ao.geo.stereographic=function(){return oe(el)}).raw=el,Ae.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Io]},(ao.geo.transverseMercator=function(){var n=Ee(Ae),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=Ae,ao.geom={},ao.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,i=En(e),u=En(r),o=n.length,a=[],l=[];for(t=0;o>t;t++)a.push([+i.call(this,n[t],t),+u.call(this,n[t],t),t]);for(a.sort(qe),t=0;o>t;t++)l.push([a[t][0],-a[t][1]]);var c=Le(a),f=Le(l),s=f[0]===c[0],h=f[f.length-1]===c[c.length-1],p=[];for(t=c.length-1;t>=0;--t)p.push(n[a[c[t]][2]]);for(t=+s;t=r&&c.x<=u&&c.y>=i&&c.y<=o?[[r,o],[u,o],[u,i],[r,i]]:[];f.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(u(n,t)/Uo)*Uo,y:Math.round(o(n,t)/Uo)*Uo,i:t}})}var r=Ce,i=ze,u=r,o=i,a=sl;return n?t(n):(t.links=function(n){return ar(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return ar(e(n)).cells.forEach(function(e,r){for(var i,u,o=e.site,a=e.edges.sort(Ve),l=-1,c=a.length,f=a[c-1].edge,s=f.l===o?f.r:f.l;++l=c,h=r>=f,p=h<<1|s;n.leaf=!1,n=n.nodes[p]||(n.nodes[p]=hr()),s?i=c:a=c,h?o=f:l=f,u(n,t,e,r,i,o,a,l)}var f,s,h,p,g,v,d,y,m,M=En(a),x=En(l);if(null!=t)v=t,d=e,y=r,m=i;else if(y=m=-(v=d=1/0),s=[],h=[],g=n.length,o)for(p=0;g>p;++p)f=n[p],f.xy&&(y=f.x),f.y>m&&(m=f.y),s.push(f.x),h.push(f.y);else for(p=0;g>p;++p){var b=+M(f=n[p],p),_=+x(f,p);v>b&&(v=b),d>_&&(d=_),b>y&&(y=b),_>m&&(m=_),s.push(b),h.push(_)}var w=y-v,S=m-d;w>S?m=d+w:y=v+S;var k=hr();if(k.add=function(n){u(k,n,+M(n,++p),+x(n,p),v,d,y,m)},k.visit=function(n){pr(n,k,v,d,y,m)},k.find=function(n){return gr(k,n[0],n[1],v,d,y,m)},p=-1,null==t){for(;++p=0?n.slice(0,t):n,r=t>=0?n.slice(t+1):"in";return e=vl.get(e)||gl,r=dl.get(r)||m,br(r(e.apply(null,lo.call(arguments,1))))},ao.interpolateHcl=Rr,ao.interpolateHsl=Dr,ao.interpolateLab=Pr,ao.interpolateRound=Ur,ao.transform=function(n){var t=fo.createElementNS(ao.ns.prefix.svg,"g");return(ao.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new jr(e?e.matrix:yl)})(n)},jr.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var yl={a:1,b:0,c:0,d:1,e:0,f:0};ao.interpolateTransform=$r,ao.layout={},ao.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++ea*a/y){if(v>l){var c=t.charge/l;n.px-=u*c,n.py-=o*c}return!0}if(t.point&&l&&v>l){var c=t.pointCharge/l;n.px-=u*c,n.py-=o*c}}return!t.charge}}function t(n){n.px=ao.event.x,n.py=ao.event.y,l.resume()}var e,r,i,u,o,a,l={},c=ao.dispatch("start","tick","end"),f=[1,1],s=.9,h=ml,p=Ml,g=-30,v=xl,d=.1,y=.64,M=[],x=[];return l.tick=function(){if((i*=.99)<.005)return e=null,c.end({type:"end",alpha:i=0}),!0;var t,r,l,h,p,v,y,m,b,_=M.length,w=x.length;for(r=0;w>r;++r)l=x[r],h=l.source,p=l.target,m=p.x-h.x,b=p.y-h.y,(v=m*m+b*b)&&(v=i*o[r]*((v=Math.sqrt(v))-u[r])/v,m*=v,b*=v,p.x-=m*(y=h.weight+p.weight?h.weight/(h.weight+p.weight):.5),p.y-=b*y,h.x+=m*(y=1-y),h.y+=b*y);if((y=i*d)&&(m=f[0]/2,b=f[1]/2,r=-1,y))for(;++r<_;)l=M[r],l.x+=(m-l.x)*y,l.y+=(b-l.y)*y;if(g)for(ri(t=ao.geom.quadtree(M),i,a),r=-1;++r<_;)(l=M[r]).fixed||t.visit(n(l));for(r=-1;++r<_;)l=M[r],l.fixed?(l.x=l.px,l.y=l.py):(l.x-=(l.px-(l.px=l.x))*s,l.y-=(l.py-(l.py=l.y))*s);c.tick({type:"tick",alpha:i})},l.nodes=function(n){return arguments.length?(M=n,l):M},l.links=function(n){return arguments.length?(x=n,l):x},l.size=function(n){return arguments.length?(f=n,l):f},l.linkDistance=function(n){return arguments.length?(h="function"==typeof n?n:+n,l):h},l.distance=l.linkDistance,l.linkStrength=function(n){return arguments.length?(p="function"==typeof n?n:+n,l):p},l.friction=function(n){return arguments.length?(s=+n,l):s},l.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,l):g},l.chargeDistance=function(n){return arguments.length?(v=n*n,l):Math.sqrt(v)},l.gravity=function(n){return arguments.length?(d=+n,l):d},l.theta=function(n){return arguments.length?(y=n*n,l):Math.sqrt(y)},l.alpha=function(n){return arguments.length?(n=+n,i?n>0?i=n:(e.c=null,e.t=NaN,e=null,c.end({type:"end",alpha:i=0})):n>0&&(c.start({type:"start",alpha:i=n}),e=qn(l.tick)),l):i},l.start=function(){function n(n,r){if(!e){for(e=new Array(i),l=0;i>l;++l)e[l]=[];for(l=0;c>l;++l){var u=x[l];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var o,a=e[t],l=-1,f=a.length;++lt;++t)(r=M[t]).index=t,r.weight=0;for(t=0;c>t;++t)r=x[t],"number"==typeof r.source&&(r.source=M[r.source]),"number"==typeof r.target&&(r.target=M[r.target]),++r.source.weight,++r.target.weight;for(t=0;i>t;++t)r=M[t],isNaN(r.x)&&(r.x=n("x",s)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof h)for(t=0;c>t;++t)u[t]=+h.call(this,x[t],t);else for(t=0;c>t;++t)u[t]=h;if(o=[],"function"==typeof p)for(t=0;c>t;++t)o[t]=+p.call(this,x[t],t);else for(t=0;c>t;++t)o[t]=p;if(a=[],"function"==typeof g)for(t=0;i>t;++t)a[t]=+g.call(this,M[t],t);else for(t=0;i>t;++t)a[t]=g;return l.resume()},l.resume=function(){return l.alpha(.1)},l.stop=function(){return l.alpha(0)},l.drag=function(){return r||(r=ao.behavior.drag().origin(m).on("dragstart.force",Qr).on("drag.force",t).on("dragend.force",ni)),arguments.length?void this.on("mouseover.force",ti).on("mouseout.force",ei).call(r):r},ao.rebind(l,c,"on")};var ml=20,Ml=1,xl=1/0;ao.layout.hierarchy=function(){function n(i){var u,o=[i],a=[];for(i.depth=0;null!=(u=o.pop());)if(a.push(u),(c=e.call(n,u,u.depth))&&(l=c.length)){for(var l,c,f;--l>=0;)o.push(f=c[l]),f.parent=u,f.depth=u.depth+1;r&&(u.value=0),u.children=c}else r&&(u.value=+r.call(n,u,u.depth)||0),delete u.children;return oi(i,function(n){var e,i;t&&(e=n.children)&&e.sort(t),r&&(i=n.parent)&&(i.value+=n.value)}),a}var t=ci,e=ai,r=li;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(ui(t,function(n){n.children&&(n.value=0)}),oi(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},ao.layout.partition=function(){function n(t,e,r,i){var u=t.children;if(t.x=e,t.y=t.depth*i,t.dx=r,t.dy=i,u&&(o=u.length)){var o,a,l,c=-1;for(r=t.value?r/t.value:0;++cs?-1:1),g=ao.sum(c),v=g?(s-l*p)/g:0,d=ao.range(l),y=[];return null!=e&&d.sort(e===bl?function(n,t){return c[t]-c[n]}:function(n,t){return e(o[n],o[t])}),d.forEach(function(n){y[n]={data:o[n],value:a=c[n],startAngle:f,endAngle:f+=a*v+p,padAngle:h}}),y}var t=Number,e=bl,r=0,i=Ho,u=0;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(i=t,n):i},n.padAngle=function(t){return arguments.length?(u=t,n):u},n};var bl={};ao.layout.stack=function(){function n(a,l){if(!(h=a.length))return a;var c=a.map(function(e,r){return t.call(n,e,r)}),f=c.map(function(t){return t.map(function(t,e){return[u.call(n,t,e),o.call(n,t,e)]})}),s=e.call(n,f,l);c=ao.permute(c,s),f=ao.permute(f,s);var h,p,g,v,d=r.call(n,f,l),y=c[0].length;for(g=0;y>g;++g)for(i.call(n,c[0][g],v=d[g],f[0][g][1]),p=1;h>p;++p)i.call(n,c[p][g],v+=f[p-1][g][1],f[p][g][1]);return a}var t=m,e=gi,r=vi,i=pi,u=si,o=hi;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:_l.get(t)||gi,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:wl.get(t)||vi,n):r},n.x=function(t){return arguments.length?(u=t,n):u},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(i=t,n):i},n};var _l=ao.map({"inside-out":function(n){var t,e,r=n.length,i=n.map(di),u=n.map(yi),o=ao.range(r).sort(function(n,t){return i[n]-i[t]}),a=0,l=0,c=[],f=[];for(t=0;r>t;++t)e=o[t],l>a?(a+=u[e],c.push(e)):(l+=u[e],f.push(e));return f.reverse().concat(c)},reverse:function(n){return ao.range(n.length).reverse()},"default":gi}),wl=ao.map({silhouette:function(n){var t,e,r,i=n.length,u=n[0].length,o=[],a=0,l=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;u>e;++e)l[e]=(a-o[e])/2;return l},wiggle:function(n){var t,e,r,i,u,o,a,l,c,f=n.length,s=n[0],h=s.length,p=[];for(p[0]=l=c=0,e=1;h>e;++e){for(t=0,i=0;f>t;++t)i+=n[t][e][1];for(t=0,u=0,a=s[e][0]-s[e-1][0];f>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;u+=o*n[t][e][1]}p[e]=l-=i?u/i*a:0,c>l&&(c=l)}for(e=0;h>e;++e)p[e]-=c;return p},expand:function(n){var t,e,r,i=n.length,u=n[0].length,o=1/i,a=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];if(r)for(t=0;i>t;t++)n[t][e][1]/=r;else for(t=0;i>t;t++)n[t][e][1]=o}for(e=0;u>e;++e)a[e]=0;return a},zero:vi});ao.layout.histogram=function(){function n(n,u){for(var o,a,l=[],c=n.map(e,this),f=r.call(this,c,u),s=i.call(this,f,c,u),u=-1,h=c.length,p=s.length-1,g=t?1:1/h;++u0)for(u=-1;++u=f[0]&&a<=f[1]&&(o=l[ao.bisect(s,a,1,p)-1],o.y+=g,o.push(n[u]));return l}var t=!0,e=Number,r=bi,i=Mi;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=En(t),n):r},n.bins=function(t){return arguments.length?(i="number"==typeof t?function(n){return xi(n,t)}:En(t),n):i},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},ao.layout.pack=function(){function n(n,u){var o=e.call(this,n,u),a=o[0],l=i[0],c=i[1],f=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,oi(a,function(n){n.r=+f(n.value)}),oi(a,Ni),r){var s=r*(t?1:Math.max(2*a.r/l,2*a.r/c))/2;oi(a,function(n){n.r+=s}),oi(a,Ni),oi(a,function(n){n.r-=s})}return Ci(a,l/2,c/2,t?1:1/Math.max(2*a.r/l,2*a.r/c)),o}var t,e=ao.layout.hierarchy().sort(_i),r=0,i=[1,1];return n.size=function(t){return arguments.length?(i=t,n):i},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},ii(n,e)},ao.layout.tree=function(){function n(n,i){var f=o.call(this,n,i),s=f[0],h=t(s);if(oi(h,e),h.parent.m=-h.z,ui(h,r),c)ui(s,u);else{var p=s,g=s,v=s;ui(s,function(n){n.xg.x&&(g=n),n.depth>v.depth&&(v=n)});var d=a(p,g)/2-p.x,y=l[0]/(g.x+a(g,p)/2+d),m=l[1]/(v.depth||1);ui(s,function(n){n.x=(n.x+d)*y,n.y=n.depth*m})}return f}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var i,u=t.children,o=0,a=u.length;a>o;++o)r.push((u[o]=i={_:u[o],parent:t,children:(i=u[o].children)&&i.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=i);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){Di(n);var u=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-u):n.z=u}else r&&(n.z=r.z+a(n._,r._));n.parent.A=i(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function i(n,t,e){if(t){for(var r,i=n,u=n,o=t,l=i.parent.children[0],c=i.m,f=u.m,s=o.m,h=l.m;o=Ti(o),i=qi(i),o&&i;)l=qi(l),u=Ti(u),u.a=n,r=o.z+s-i.z-c+a(o._,i._),r>0&&(Ri(Pi(o,n,e),n,r),c+=r,f+=r),s+=o.m,c+=i.m,h+=l.m,f+=u.m;o&&!Ti(u)&&(u.t=o,u.m+=s-f),i&&!qi(l)&&(l.t=i,l.m+=c-h,e=n)}return e}function u(n){n.x*=l[0],n.y=n.depth*l[1]}var o=ao.layout.hierarchy().sort(null).value(null),a=Li,l=[1,1],c=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(c=null==(l=t)?u:null,n):c?null:l},n.nodeSize=function(t){return arguments.length?(c=null==(l=t)?null:u,n):c?l:null},ii(n,o)},ao.layout.cluster=function(){function n(n,u){var o,a=t.call(this,n,u),l=a[0],c=0;oi(l,function(n){var t=n.children;t&&t.length?(n.x=ji(t),n.y=Ui(t)):(n.x=o?c+=e(n,o):0,n.y=0,o=n)});var f=Fi(l),s=Hi(l),h=f.x-e(f,s)/2,p=s.x+e(s,f)/2;return oi(l,i?function(n){n.x=(n.x-l.x)*r[0],n.y=(l.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(p-h)*r[0],n.y=(1-(l.y?n.y/l.y:1))*r[1]}),a}var t=ao.layout.hierarchy().sort(null).value(null),e=Li,r=[1,1],i=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(i=null==(r=t),n):i?null:r},n.nodeSize=function(t){return arguments.length?(i=null!=(r=t),n):i?r:null},ii(n,t)},ao.layout.treemap=function(){function n(n,t){for(var e,r,i=-1,u=n.length;++it?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var u=e.children;if(u&&u.length){var o,a,l,c=s(e),f=[],h=u.slice(),g=1/0,v="slice"===p?c.dx:"dice"===p?c.dy:"slice-dice"===p?1&e.depth?c.dy:c.dx:Math.min(c.dx,c.dy);for(n(h,c.dx*c.dy/e.value),f.area=0;(l=h.length)>0;)f.push(o=h[l-1]),f.area+=o.area,"squarify"!==p||(a=r(f,v))<=g?(h.pop(),g=a):(f.area-=f.pop().area,i(f,v,c,!1),v=Math.min(c.dx,c.dy),f.length=f.area=0,g=1/0);f.length&&(i(f,v,c,!0),f.length=f.area=0),u.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var u,o=s(t),a=r.slice(),l=[];for(n(a,o.dx*o.dy/t.value),l.area=0;u=a.pop();)l.push(u),l.area+=u.area,null!=u.z&&(i(l,u.z?o.dx:o.dy,o,!a.length),l.length=l.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,i=0,u=1/0,o=-1,a=n.length;++oe&&(u=e),e>i&&(i=e));return r*=r,t*=t,r?Math.max(t*i*g/r,r/(t*u*g)):1/0}function i(n,t,e,r){var i,u=-1,o=n.length,a=e.x,c=e.y,f=t?l(n.area/t):0; +if(t==e.dx){for((r||f>e.dy)&&(f=e.dy);++ue.dx)&&(f=e.dx);++ue&&(t=1),1>e&&(n=0),function(){var e,r,i;do e=2*Math.random()-1,r=2*Math.random()-1,i=e*e+r*r;while(!i||i>1);return n+t*e*Math.sqrt(-2*Math.log(i)/i)}},logNormal:function(){var n=ao.random.normal.apply(ao,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=ao.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},ao.scale={};var Sl={floor:m,ceil:m};ao.scale.linear=function(){return Wi([0,1],[0,1],Mr,!1)};var kl={s:1,g:1,p:1,r:1,e:1};ao.scale.log=function(){return ru(ao.scale.linear().domain([0,1]),10,!0,[1,10])};var Nl=ao.format(".0e"),El={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};ao.scale.pow=function(){return iu(ao.scale.linear(),1,[0,1])},ao.scale.sqrt=function(){return ao.scale.pow().exponent(.5)},ao.scale.ordinal=function(){return ou([],{t:"range",a:[[]]})},ao.scale.category10=function(){return ao.scale.ordinal().range(Al)},ao.scale.category20=function(){return ao.scale.ordinal().range(Cl)},ao.scale.category20b=function(){return ao.scale.ordinal().range(zl)},ao.scale.category20c=function(){return ao.scale.ordinal().range(Ll)};var Al=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(xn),Cl=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(xn),zl=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(xn),Ll=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(xn);ao.scale.quantile=function(){return au([],[])},ao.scale.quantize=function(){return lu(0,1,[0,1])},ao.scale.threshold=function(){return cu([.5],[0,1])},ao.scale.identity=function(){return fu([0,1])},ao.svg={},ao.svg.arc=function(){function n(){var n=Math.max(0,+e.apply(this,arguments)),c=Math.max(0,+r.apply(this,arguments)),f=o.apply(this,arguments)-Io,s=a.apply(this,arguments)-Io,h=Math.abs(s-f),p=f>s?0:1;if(n>c&&(g=c,c=n,n=g),h>=Oo)return t(c,p)+(n?t(n,1-p):"")+"Z";var g,v,d,y,m,M,x,b,_,w,S,k,N=0,E=0,A=[];if((y=(+l.apply(this,arguments)||0)/2)&&(d=u===ql?Math.sqrt(n*n+c*c):+u.apply(this,arguments),p||(E*=-1),c&&(E=tn(d/c*Math.sin(y))),n&&(N=tn(d/n*Math.sin(y)))),c){m=c*Math.cos(f+E),M=c*Math.sin(f+E),x=c*Math.cos(s-E),b=c*Math.sin(s-E);var C=Math.abs(s-f-2*E)<=Fo?0:1;if(E&&yu(m,M,x,b)===p^C){var z=(f+s)/2;m=c*Math.cos(z),M=c*Math.sin(z),x=b=null}}else m=M=0;if(n){_=n*Math.cos(s-N),w=n*Math.sin(s-N),S=n*Math.cos(f+N),k=n*Math.sin(f+N);var L=Math.abs(f-s+2*N)<=Fo?0:1;if(N&&yu(_,w,S,k)===1-p^L){var q=(f+s)/2;_=n*Math.cos(q),w=n*Math.sin(q),S=k=null}}else _=w=0;if(h>Uo&&(g=Math.min(Math.abs(c-n)/2,+i.apply(this,arguments)))>.001){v=c>n^p?0:1;var T=g,R=g;if(Fo>h){var D=null==S?[_,w]:null==x?[m,M]:Re([m,M],[S,k],[x,b],[_,w]),P=m-D[0],U=M-D[1],j=x-D[0],F=b-D[1],H=1/Math.sin(Math.acos((P*j+U*F)/(Math.sqrt(P*P+U*U)*Math.sqrt(j*j+F*F)))/2),O=Math.sqrt(D[0]*D[0]+D[1]*D[1]);R=Math.min(g,(n-O)/(H-1)),T=Math.min(g,(c-O)/(H+1))}if(null!=x){var I=mu(null==S?[_,w]:[S,k],[m,M],c,T,p),Y=mu([x,b],[_,w],c,T,p);g===T?A.push("M",I[0],"A",T,",",T," 0 0,",v," ",I[1],"A",c,",",c," 0 ",1-p^yu(I[1][0],I[1][1],Y[1][0],Y[1][1]),",",p," ",Y[1],"A",T,",",T," 0 0,",v," ",Y[0]):A.push("M",I[0],"A",T,",",T," 0 1,",v," ",Y[0])}else A.push("M",m,",",M);if(null!=S){var Z=mu([m,M],[S,k],n,-R,p),V=mu([_,w],null==x?[m,M]:[x,b],n,-R,p);g===R?A.push("L",V[0],"A",R,",",R," 0 0,",v," ",V[1],"A",n,",",n," 0 ",p^yu(V[1][0],V[1][1],Z[1][0],Z[1][1]),",",1-p," ",Z[1],"A",R,",",R," 0 0,",v," ",Z[0]):A.push("L",V[0],"A",R,",",R," 0 0,",v," ",Z[0])}else A.push("L",_,",",w)}else A.push("M",m,",",M),null!=x&&A.push("A",c,",",c," 0 ",C,",",p," ",x,",",b),A.push("L",_,",",w),null!=S&&A.push("A",n,",",n," 0 ",L,",",1-p," ",S,",",k);return A.push("Z"),A.join("")}function t(n,t){return"M0,"+n+"A"+n+","+n+" 0 1,"+t+" 0,"+-n+"A"+n+","+n+" 0 1,"+t+" 0,"+n}var e=hu,r=pu,i=su,u=ql,o=gu,a=vu,l=du;return n.innerRadius=function(t){return arguments.length?(e=En(t),n):e},n.outerRadius=function(t){return arguments.length?(r=En(t),n):r},n.cornerRadius=function(t){return arguments.length?(i=En(t),n):i},n.padRadius=function(t){return arguments.length?(u=t==ql?ql:En(t),n):u},n.startAngle=function(t){return arguments.length?(o=En(t),n):o},n.endAngle=function(t){return arguments.length?(a=En(t),n):a},n.padAngle=function(t){return arguments.length?(l=En(t),n):l},n.centroid=function(){var n=(+e.apply(this,arguments)+ +r.apply(this,arguments))/2,t=(+o.apply(this,arguments)+ +a.apply(this,arguments))/2-Io;return[Math.cos(t)*n,Math.sin(t)*n]},n};var ql="auto";ao.svg.line=function(){return Mu(m)};var Tl=ao.map({linear:xu,"linear-closed":bu,step:_u,"step-before":wu,"step-after":Su,basis:zu,"basis-open":Lu,"basis-closed":qu,bundle:Tu,cardinal:Eu,"cardinal-open":ku,"cardinal-closed":Nu,monotone:Fu});Tl.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Rl=[0,2/3,1/3,0],Dl=[0,1/3,2/3,0],Pl=[0,1/6,2/3,1/6];ao.svg.line.radial=function(){var n=Mu(Hu);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},wu.reverse=Su,Su.reverse=wu,ao.svg.area=function(){return Ou(m)},ao.svg.area.radial=function(){var n=Ou(Hu);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},ao.svg.chord=function(){function n(n,a){var l=t(this,u,n,a),c=t(this,o,n,a);return"M"+l.p0+r(l.r,l.p1,l.a1-l.a0)+(e(l,c)?i(l.r,l.p1,l.r,l.p0):i(l.r,l.p1,c.r,c.p0)+r(c.r,c.p1,c.a1-c.a0)+i(c.r,c.p1,l.r,l.p0))+"Z"}function t(n,t,e,r){var i=t.call(n,e,r),u=a.call(n,i,r),o=l.call(n,i,r)-Io,f=c.call(n,i,r)-Io;return{r:u,a0:o,a1:f,p0:[u*Math.cos(o),u*Math.sin(o)],p1:[u*Math.cos(f),u*Math.sin(f)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Fo)+",1 "+t}function i(n,t,e,r){return"Q 0,0 "+r}var u=Me,o=xe,a=Iu,l=gu,c=vu;return n.radius=function(t){return arguments.length?(a=En(t),n):a},n.source=function(t){return arguments.length?(u=En(t),n):u},n.target=function(t){return arguments.length?(o=En(t),n):o},n.startAngle=function(t){return arguments.length?(l=En(t),n):l},n.endAngle=function(t){return arguments.length?(c=En(t),n):c},n},ao.svg.diagonal=function(){function n(n,i){var u=t.call(this,n,i),o=e.call(this,n,i),a=(u.y+o.y)/2,l=[u,{x:u.x,y:a},{x:o.x,y:a},o];return l=l.map(r),"M"+l[0]+"C"+l[1]+" "+l[2]+" "+l[3]}var t=Me,e=xe,r=Yu;return n.source=function(e){return arguments.length?(t=En(e),n):t},n.target=function(t){return arguments.length?(e=En(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},ao.svg.diagonal.radial=function(){var n=ao.svg.diagonal(),t=Yu,e=n.projection;return n.projection=function(n){return arguments.length?e(Zu(t=n)):t},n},ao.svg.symbol=function(){function n(n,r){return(Ul.get(t.call(this,n,r))||$u)(e.call(this,n,r))}var t=Xu,e=Vu;return n.type=function(e){return arguments.length?(t=En(e),n):t},n.size=function(t){return arguments.length?(e=En(t),n):e},n};var Ul=ao.map({circle:$u,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Fl)),e=t*Fl;return"M0,"+-t+"L"+e+",0 0,"+t+" "+-e+",0Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});ao.svg.symbolTypes=Ul.keys();var jl=Math.sqrt(3),Fl=Math.tan(30*Yo);Co.transition=function(n){for(var t,e,r=Hl||++Zl,i=Ku(n),u=[],o=Ol||{time:Date.now(),ease:Nr,delay:0,duration:250},a=-1,l=this.length;++au;u++){i.push(t=[]);for(var e=this[u],a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return Wu(i,this.namespace,this.id)},Yl.tween=function(n,t){var e=this.id,r=this.namespace;return arguments.length<2?this.node()[r][e].tween.get(n):Y(this,null==t?function(t){t[r][e].tween.remove(n)}:function(i){i[r][e].tween.set(n,t)})},Yl.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function i(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function u(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?$r:Mr,a=ao.ns.qualify(n);return Ju(this,"attr."+n,t,a.local?u:i)},Yl.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(i));return r&&function(n){this.setAttribute(i,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(i.space,i.local));return r&&function(n){this.setAttributeNS(i.space,i.local,r(n))}}var i=ao.ns.qualify(n);return this.tween("attr."+n,i.local?r:e)},Yl.style=function(n,e,r){function i(){this.style.removeProperty(n)}function u(e){return null==e?i:(e+="",function(){var i,u=t(this).getComputedStyle(this,null).getPropertyValue(n);return u!==e&&(i=Mr(u,e),function(t){this.style.setProperty(n,i(t),r)})})}var o=arguments.length;if(3>o){if("string"!=typeof n){2>o&&(e="");for(r in n)this.style(r,n[r],e);return this}r=""}return Ju(this,"style."+n,e,u)},Yl.styleTween=function(n,e,r){function i(i,u){var o=e.call(this,i,u,t(this).getComputedStyle(this,null).getPropertyValue(n));return o&&function(t){this.style.setProperty(n,o(t),r)}}return arguments.length<3&&(r=""),this.tween("style."+n,i)},Yl.text=function(n){return Ju(this,"text",n,Gu)},Yl.remove=function(){var n=this.namespace;return this.each("end.transition",function(){var t;this[n].count<2&&(t=this.parentNode)&&t.removeChild(this)})},Yl.ease=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].ease:("function"!=typeof n&&(n=ao.ease.apply(ao,arguments)),Y(this,function(r){r[e][t].ease=n}))},Yl.delay=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].delay:Y(this,"function"==typeof n?function(r,i,u){r[e][t].delay=+n.call(r,r.__data__,i,u)}:(n=+n,function(r){r[e][t].delay=n}))},Yl.duration=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].duration:Y(this,"function"==typeof n?function(r,i,u){r[e][t].duration=Math.max(1,n.call(r,r.__data__,i,u))}:(n=Math.max(1,n),function(r){r[e][t].duration=n}))},Yl.each=function(n,t){var e=this.id,r=this.namespace;if(arguments.length<2){var i=Ol,u=Hl;try{Hl=e,Y(this,function(t,i,u){Ol=t[r][e],n.call(t,t.__data__,i,u)})}finally{Ol=i,Hl=u}}else Y(this,function(i){var u=i[r][e];(u.event||(u.event=ao.dispatch("start","end","interrupt"))).on(n,t)});return this},Yl.transition=function(){for(var n,t,e,r,i=this.id,u=++Zl,o=this.namespace,a=[],l=0,c=this.length;c>l;l++){a.push(n=[]);for(var t=this[l],f=0,s=t.length;s>f;f++)(e=t[f])&&(r=e[o][i],Qu(e,f,o,u,{time:r.time,ease:r.ease,delay:r.delay+r.duration,duration:r.duration})),n.push(e)}return Wu(a,o,u)},ao.svg.axis=function(){function n(n){n.each(function(){var n,c=ao.select(this),f=this.__chart__||e,s=this.__chart__=e.copy(),h=null==l?s.ticks?s.ticks.apply(s,a):s.domain():l,p=null==t?s.tickFormat?s.tickFormat.apply(s,a):m:t,g=c.selectAll(".tick").data(h,s),v=g.enter().insert("g",".domain").attr("class","tick").style("opacity",Uo),d=ao.transition(g.exit()).style("opacity",Uo).remove(),y=ao.transition(g.order()).style("opacity",1),M=Math.max(i,0)+o,x=Zi(s),b=c.selectAll(".domain").data([0]),_=(b.enter().append("path").attr("class","domain"),ao.transition(b));v.append("line"),v.append("text");var w,S,k,N,E=v.select("line"),A=y.select("line"),C=g.select("text").text(p),z=v.select("text"),L=y.select("text"),q="top"===r||"left"===r?-1:1;if("bottom"===r||"top"===r?(n=no,w="x",k="y",S="x2",N="y2",C.attr("dy",0>q?"0em":".71em").style("text-anchor","middle"),_.attr("d","M"+x[0]+","+q*u+"V0H"+x[1]+"V"+q*u)):(n=to,w="y",k="x",S="y2",N="x2",C.attr("dy",".32em").style("text-anchor",0>q?"end":"start"),_.attr("d","M"+q*u+","+x[0]+"H0V"+x[1]+"H"+q*u)),E.attr(N,q*i),z.attr(k,q*M),A.attr(S,0).attr(N,q*i),L.attr(w,0).attr(k,q*M),s.rangeBand){var T=s,R=T.rangeBand()/2;f=s=function(n){return T(n)+R}}else f.rangeBand?f=s:d.call(n,s,f);v.call(n,f,s),y.call(n,s,s)})}var t,e=ao.scale.linear(),r=Vl,i=6,u=6,o=3,a=[10],l=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Xl?t+"":Vl,n):r},n.ticks=function(){return arguments.length?(a=co(arguments),n):a},n.tickValues=function(t){return arguments.length?(l=t,n):l},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(i=+t,u=+arguments[e-1],n):i},n.innerTickSize=function(t){return arguments.length?(i=+t,n):i},n.outerTickSize=function(t){return arguments.length?(u=+t,n):u},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Vl="bottom",Xl={top:1,right:1,bottom:1,left:1};ao.svg.brush=function(){function n(t){t.each(function(){var t=ao.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=t.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),t.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=t.selectAll(".resize").data(v,m);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return $l[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,s=ao.transition(t),h=ao.transition(o);c&&(l=Zi(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),r(s)),f&&(l=Zi(f),h.attr("y",l[0]).attr("height",l[1]-l[0]),i(s)),e(s)})}function e(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+s[+/e$/.test(n)]+","+h[+/^s/.test(n)]+")"})}function r(n){n.select(".extent").attr("x",s[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",s[1]-s[0])}function i(n){n.select(".extent").attr("y",h[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",h[1]-h[0])}function u(){function u(){32==ao.event.keyCode&&(C||(M=null,L[0]-=s[1],L[1]-=h[1],C=2),S())}function v(){32==ao.event.keyCode&&2==C&&(L[0]+=s[1],L[1]+=h[1],C=0,S())}function d(){var n=ao.mouse(b),t=!1;x&&(n[0]+=x[0],n[1]+=x[1]),C||(ao.event.altKey?(M||(M=[(s[0]+s[1])/2,(h[0]+h[1])/2]),L[0]=s[+(n[0]f?(i=r,r=f):i=f),v[0]!=r||v[1]!=i?(e?a=null:o=null,v[0]=r,v[1]=i,!0):void 0}function m(){d(),k.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),ao.select("body").style("cursor",null),q.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),z(),w({type:"brushend"})}var M,x,b=this,_=ao.select(ao.event.target),w=l.of(b,arguments),k=ao.select(b),N=_.datum(),E=!/^(n|s)$/.test(N)&&c,A=!/^(e|w)$/.test(N)&&f,C=_.classed("extent"),z=W(b),L=ao.mouse(b),q=ao.select(t(b)).on("keydown.brush",u).on("keyup.brush",v);if(ao.event.changedTouches?q.on("touchmove.brush",d).on("touchend.brush",m):q.on("mousemove.brush",d).on("mouseup.brush",m),k.interrupt().selectAll("*").interrupt(),C)L[0]=s[0]-L[0],L[1]=h[0]-L[1];else if(N){var T=+/w$/.test(N),R=+/^n/.test(N);x=[s[1-T]-L[0],h[1-R]-L[1]],L[0]=s[T],L[1]=h[R]}else ao.event.altKey&&(M=L.slice());k.style("pointer-events","none").selectAll(".resize").style("display",null),ao.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),d()}var o,a,l=N(n,"brushstart","brush","brushend"),c=null,f=null,s=[0,0],h=[0,0],p=!0,g=!0,v=Bl[0];return n.event=function(n){n.each(function(){var n=l.of(this,arguments),t={x:s,y:h,i:o,j:a},e=this.__chart__||t;this.__chart__=t,Hl?ao.select(this).transition().each("start.brush",function(){o=e.i,a=e.j,s=e.x,h=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=xr(s,t.x),r=xr(h,t.y);return o=a=null,function(i){s=t.x=e(i),h=t.y=r(i),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){o=t.i,a=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,v=Bl[!c<<1|!f],n):c},n.y=function(t){return arguments.length?(f=t,v=Bl[!c<<1|!f],n):f},n.clamp=function(t){return arguments.length?(c&&f?(p=!!t[0],g=!!t[1]):c?p=!!t:f&&(g=!!t),n):c&&f?[p,g]:c?p:f?g:null},n.extent=function(t){var e,r,i,u,l;return arguments.length?(c&&(e=t[0],r=t[1],f&&(e=e[0],r=r[0]),o=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(l=e,e=r,r=l),e==s[0]&&r==s[1]||(s=[e,r])),f&&(i=t[0],u=t[1],c&&(i=i[1],u=u[1]),a=[i,u],f.invert&&(i=f(i),u=f(u)),i>u&&(l=i,i=u,u=l),i==h[0]&&u==h[1]||(h=[i,u])),n):(c&&(o?(e=o[0],r=o[1]):(e=s[0],r=s[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(l=e,e=r,r=l))),f&&(a?(i=a[0],u=a[1]):(i=h[0],u=h[1],f.invert&&(i=f.invert(i),u=f.invert(u)),i>u&&(l=i,i=u,u=l))),c&&f?[[e,i],[r,u]]:c?[e,r]:f&&[i,u])},n.clear=function(){return n.empty()||(s=[0,0],h=[0,0],o=a=null),n},n.empty=function(){return!!c&&s[0]==s[1]||!!f&&h[0]==h[1]},ao.rebind(n,l,"on")};var $l={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Bl=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Wl=ga.format=xa.timeFormat,Jl=Wl.utc,Gl=Jl("%Y-%m-%dT%H:%M:%S.%LZ");Wl.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?eo:Gl,eo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},eo.toString=Gl.toString,ga.second=On(function(n){return new va(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ga.seconds=ga.second.range,ga.seconds.utc=ga.second.utc.range,ga.minute=On(function(n){return new va(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ga.minutes=ga.minute.range,ga.minutes.utc=ga.minute.utc.range,ga.hour=On(function(n){var t=n.getTimezoneOffset()/60;return new va(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ga.hours=ga.hour.range,ga.hours.utc=ga.hour.utc.range,ga.month=On(function(n){return n=ga.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ga.months=ga.month.range,ga.months.utc=ga.month.utc.range;var Kl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Ql=[[ga.second,1],[ga.second,5],[ga.second,15],[ga.second,30],[ga.minute,1],[ga.minute,5],[ga.minute,15],[ga.minute,30],[ga.hour,1],[ga.hour,3],[ga.hour,6],[ga.hour,12],[ga.day,1],[ga.day,2],[ga.week,1],[ga.month,1],[ga.month,3],[ga.year,1]],nc=Wl.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",zt]]),tc={range:function(n,t,e){return ao.range(Math.ceil(n/e)*e,+t,e).map(io)},floor:m,ceil:m};Ql.year=ga.year,ga.scale=function(){return ro(ao.scale.linear(),Ql,nc)};var ec=Ql.map(function(n){return[n[0].utc,n[1]]}),rc=Jl.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",zt]]);ec.year=ga.year.utc,ga.scale.utc=function(){return ro(ao.scale.linear(),ec,rc)},ao.text=An(function(n){return n.responseText}),ao.json=function(n,t){return Cn(n,"application/json",uo,t)},ao.html=function(n,t){return Cn(n,"text/html",oo,t)},ao.xml=An(function(n){return n.responseXML}),"function"==typeof define&&define.amd?(this.d3=ao,define(ao)):"object"==typeof module&&module.exports?module.exports=ao:this.d3=ao}(); \ No newline at end of file diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/file.js b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/file.js new file mode 100644 index 00000000..29cacd4d --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/file.js @@ -0,0 +1,62 @@ + $(function() { + var $window = $(window) + , $top_link = $('#toplink') + , $body = $('body, html') + , offset = $('#code').offset().top + , hidePopover = function ($target) { + $target.data('popover-hover', false); + + setTimeout(function () { + if (!$target.data('popover-hover')) { + $target.popover('hide'); + } + }, 300); + }; + + $top_link.hide().click(function(event) { + event.preventDefault(); + $body.animate({scrollTop:0}, 800); + }); + + $window.scroll(function() { + if($window.scrollTop() > offset) { + $top_link.fadeIn(); + } else { + $top_link.fadeOut(); + } + }).scroll(); + + $('.popin') + .popover({trigger: 'manual'}) + .on({ + 'mouseenter.popover': function () { + var $target = $(this); + var $container = $target.children().first(); + + $target.data('popover-hover', true); + + // popover already displayed + if ($target.next('.popover').length) { + return; + } + + // show the popover + $container.popover('show'); + + // register mouse events on the popover + $target.next('.popover:not(.popover-initialized)') + .on({ + 'mouseenter': function () { + $target.data('popover-hover', true); + }, + 'mouseleave': function () { + hidePopover($container); + } + }) + .addClass('popover-initialized'); + }, + 'mouseleave.popover': function () { + hidePopover($(this).children().first()); + } + }); + }); diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/jquery.min.js b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/jquery.min.js new file mode 100644 index 00000000..2c69bc90 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/jquery.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&v(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!y||!y.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ve(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ye(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ve(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],y=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||y.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||y.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||y.push(".#.+[+~]"),e.querySelectorAll("\\\f"),y.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),y=y.length&&new RegExp(y.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),v=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&v(p,e)?-1:t==C||t.ownerDocument==p&&v(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!y||!y.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),v.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",v.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",v.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),v.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0f&&(e=a.render.queue[f]);f++)d=e.generate(),typeof e.callback==typeof Function&&e.callback(d);a.render.queue.splice(0,f),a.render.queue.length?setTimeout(c):(a.dispatch.render_end(),a.render.active=!1)};setTimeout(c)},a.render.active=!1,a.render.queue=[],a.addGraph=function(b){typeof arguments[0]==typeof Function&&(b={generate:arguments[0],callback:arguments[1]}),a.render.queue.push(b),a.render.active||a.render()},"undefined"!=typeof module&&"undefined"!=typeof exports&&(module.exports=a),"undefined"!=typeof window&&(window.nv=a),a.dom.write=function(a){return void 0!==window.fastdom?fastdom.write(a):a()},a.dom.read=function(a){return void 0!==window.fastdom?fastdom.read(a):a()},a.interactiveGuideline=function(){"use strict";function b(l){l.each(function(l){function m(){var a=d3.mouse(this),d=a[0],e=a[1],i=!0,j=!1;if(k&&(d=d3.event.offsetX,e=d3.event.offsetY,"svg"!==d3.event.target.tagName&&(i=!1),d3.event.target.className.baseVal.match("nv-legend")&&(j=!0)),i&&(d-=f.left,e-=f.top),0>d||0>e||d>o||e>p||d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement||j){if(k&&d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement&&(void 0===d3.event.relatedTarget.className||d3.event.relatedTarget.className.match(c.nvPointerEventsClass)))return;return h.elementMouseout({mouseX:d,mouseY:e}),b.renderGuideLine(null),void c.hidden(!0)}c.hidden(!1);var l=g.invert(d);h.elementMousemove({mouseX:d,mouseY:e,pointXValue:l}),"dblclick"===d3.event.type&&h.elementDblclick({mouseX:d,mouseY:e,pointXValue:l}),"click"===d3.event.type&&h.elementClick({mouseX:d,mouseY:e,pointXValue:l})}var n=d3.select(this),o=d||960,p=e||400,q=n.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([l]),r=q.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");r.append("g").attr("class","nv-interactiveGuideLine"),j&&(j.on("touchmove",m).on("mousemove",m,!0).on("mouseout",m,!0).on("dblclick",m).on("click",m),b.guideLine=null,b.renderGuideLine=function(c){i&&(b.guideLine&&b.guideLine.attr("x1")===c||a.dom.write(function(){var b=q.select(".nv-interactiveGuideLine").selectAll("line").data(null!=c?[a.utils.NaNtoZero(c)]:[],String);b.enter().append("line").attr("class","nv-guideline").attr("x1",function(a){return a}).attr("x2",function(a){return a}).attr("y1",p).attr("y2",0),b.exit().remove()}))})})}var c=a.models.tooltip();c.duration(0).hideDelay(0)._isInteractiveLayer(!0).hidden(!1);var d=null,e=null,f={left:0,top:0},g=d3.scale.linear(),h=d3.dispatch("elementMousemove","elementMouseout","elementClick","elementDblclick"),i=!0,j=null,k="ActiveXObject"in window;return b.dispatch=h,b.tooltip=c,b.margin=function(a){return arguments.length?(f.top="undefined"!=typeof a.top?a.top:f.top,f.left="undefined"!=typeof a.left?a.left:f.left,b):f},b.width=function(a){return arguments.length?(d=a,b):d},b.height=function(a){return arguments.length?(e=a,b):e},b.xScale=function(a){return arguments.length?(g=a,b):g},b.showGuideLine=function(a){return arguments.length?(i=a,b):i},b.svgContainer=function(a){return arguments.length?(j=a,b):j},b},a.interactiveBisect=function(a,b,c){"use strict";if(!(a instanceof Array))return null;var d;d="function"!=typeof c?function(a){return a.x}:c;var e=function(a,b){return d(a)-b},f=d3.bisector(e).left,g=d3.max([0,f(a,b)-1]),h=d(a[g]);if("undefined"==typeof h&&(h=g),h===b)return g;var i=d3.min([g+1,a.length-1]),j=d(a[i]);return"undefined"==typeof j&&(j=i),Math.abs(j-b)>=Math.abs(h-b)?g:i},a.nearestValueIndex=function(a,b,c){"use strict";var d=1/0,e=null;return a.forEach(function(a,f){var g=Math.abs(b-a);null!=a&&d>=g&&c>g&&(d=g,e=f)}),e},function(){"use strict";a.models.tooltip=function(){function b(){if(k){var a=d3.select(k);"svg"!==a.node().tagName&&(a=a.select("svg"));var b=a.node()?a.attr("viewBox"):null;if(b){b=b.split(" ");var c=parseInt(a.style("width"),10)/b[2];p.left=p.left*c,p.top=p.top*c}}}function c(){if(!n){var a;a=k?k:document.body,n=d3.select(a).append("div").attr("class","nvtooltip "+(j?j:"xy-tooltip")).attr("id",v),n.style("top",0).style("left",0),n.style("opacity",0),n.selectAll("div, table, td, tr").classed(w,!0),n.classed(w,!0),o=n.node()}}function d(){if(r&&B(e)){b();var f=p.left,g=null!==i?i:p.top;return a.dom.write(function(){c();var b=A(e);b&&(o.innerHTML=b),k&&u?a.dom.read(function(){var a=k.getElementsByTagName("svg")[0],b={left:0,top:0};if(a){var c=a.getBoundingClientRect(),d=k.getBoundingClientRect(),e=c.top;if(0>e){var i=k.getBoundingClientRect();e=Math.abs(e)>i.height?0:e}b.top=Math.abs(e-d.top),b.left=Math.abs(c.left-d.left)}f+=k.offsetLeft+b.left-2*k.scrollLeft,g+=k.offsetTop+b.top-2*k.scrollTop,h&&h>0&&(g=Math.floor(g/h)*h),C([f,g])}):C([f,g])}),d}}var e=null,f="w",g=25,h=0,i=null,j=null,k=null,l=!0,m=400,n=null,o=null,p={left:null,top:null},q={left:0,top:0},r=!0,s=100,t=!0,u=!1,v="nvtooltip-"+Math.floor(1e5*Math.random()),w="nv-pointer-events-none",x=function(a){return a},y=function(a){return a},z=function(a){return a},A=function(a){if(null===a)return"";var b=d3.select(document.createElement("table"));if(t){var c=b.selectAll("thead").data([a]).enter().append("thead");c.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(y(a.value))}var d=b.selectAll("tbody").data([a]).enter().append("tbody"),e=d.selectAll("tr").data(function(a){return a.series}).enter().append("tr").classed("highlight",function(a){return a.highlight});e.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(a){return a.color}),e.append("td").classed("key",!0).html(function(a,b){return z(a.key,b)}),e.append("td").classed("value",!0).html(function(a,b){return x(a.value,b)}),e.selectAll("td").each(function(a){if(a.highlight){var b=d3.scale.linear().domain([0,1]).range(["#fff",a.color]),c=.6;d3.select(this).style("border-bottom-color",b(c)).style("border-top-color",b(c))}});var f=b.node().outerHTML;return void 0!==a.footer&&(f+=""),f},B=function(a){if(a&&a.series){if(a.series instanceof Array)return!!a.series.length;if(a.series instanceof Object)return a.series=[a.series],!0}return!1},C=function(b){o&&a.dom.read(function(){var c,d,e=parseInt(o.offsetHeight,10),h=parseInt(o.offsetWidth,10),i=a.utils.windowSize().width,j=a.utils.windowSize().height,k=window.pageYOffset,p=window.pageXOffset;j=window.innerWidth>=document.body.scrollWidth?j:j-16,i=window.innerHeight>=document.body.scrollHeight?i:i-16;var r,t,u=function(a){var b=d;do isNaN(a.offsetTop)||(b+=a.offsetTop),a=a.offsetParent;while(a);return b},v=function(a){var b=c;do isNaN(a.offsetLeft)||(b+=a.offsetLeft),a=a.offsetParent;while(a);return b};switch(f){case"e":c=b[0]-h-g,d=b[1]-e/2,r=v(o),t=u(o),p>r&&(c=b[0]+g>p?b[0]+g:p-r+c),k>t&&(d=k-t+d),t+e>k+j&&(d=k+j-t+d-e);break;case"w":c=b[0]+g,d=b[1]-e/2,r=v(o),t=u(o),r+h>i&&(c=b[0]-h-g),k>t&&(d=k+5),t+e>k+j&&(d=k+j-t+d-e);break;case"n":c=b[0]-h/2-5,d=b[1]+g,r=v(o),t=u(o),p>r&&(c=p+5),r+h>i&&(c=c-h/2+5),t+e>k+j&&(d=k+j-t+d-e);break;case"s":c=b[0]-h/2,d=b[1]-e-g,r=v(o),t=u(o),p>r&&(c=p+5),r+h>i&&(c=c-h/2+5),k>t&&(d=k);break;case"none":c=b[0],d=b[1]-g,r=v(o),t=u(o)}c-=q.left,d-=q.top;var w=o.getBoundingClientRect(),k=window.pageYOffset||document.documentElement.scrollTop,p=window.pageXOffset||document.documentElement.scrollLeft,x="translate("+(w.left+p)+"px, "+(w.top+k)+"px)",y="translate("+c+"px, "+d+"px)",z=d3.interpolateString(x,y),A=n.style("opacity")<.1;l?n.transition().delay(m).duration(0).style("opacity",0):n.interrupt().transition().duration(A?0:s).styleTween("transform",function(){return z},"important").style("-webkit-transform",y).style("opacity",1)})};return d.nvPointerEventsClass=w,d.options=a.utils.optionsFunc.bind(d),d._options=Object.create({},{duration:{get:function(){return s},set:function(a){s=a}},gravity:{get:function(){return f},set:function(a){f=a}},distance:{get:function(){return g},set:function(a){g=a}},snapDistance:{get:function(){return h},set:function(a){h=a}},classes:{get:function(){return j},set:function(a){j=a}},chartContainer:{get:function(){return k},set:function(a){k=a}},fixedTop:{get:function(){return i},set:function(a){i=a}},enabled:{get:function(){return r},set:function(a){r=a}},hideDelay:{get:function(){return m},set:function(a){m=a}},contentGenerator:{get:function(){return A},set:function(a){A=a}},valueFormatter:{get:function(){return x},set:function(a){x=a}},headerFormatter:{get:function(){return y},set:function(a){y=a}},keyFormatter:{get:function(){return z},set:function(a){z=a}},headerEnabled:{get:function(){return t},set:function(a){t=a}},_isInteractiveLayer:{get:function(){return u},set:function(a){u=!!a}},position:{get:function(){return p},set:function(a){p.left=void 0!==a.left?a.left:p.left,p.top=void 0!==a.top?a.top:p.top}},offset:{get:function(){return q},set:function(a){q.left=void 0!==a.left?a.left:q.left,q.top=void 0!==a.top?a.top:q.top}},hidden:{get:function(){return l},set:function(a){l!=a&&(l=!!a,d())}},data:{get:function(){return e},set:function(a){a.point&&(a.value=a.point.x,a.series=a.series||{},a.series.value=a.point.y,a.series.color=a.point.color||a.series.color),e=a}},tooltipElem:{get:function(){return o},set:function(){}},id:{get:function(){return v},set:function(){}}}),a.utils.initOptions(d),d}}(),a.utils.windowSize=function(){var a={width:640,height:480};return window.innerWidth&&window.innerHeight?(a.width=window.innerWidth,a.height=window.innerHeight,a):"CSS1Compat"==document.compatMode&&document.documentElement&&document.documentElement.offsetWidth?(a.width=document.documentElement.offsetWidth,a.height=document.documentElement.offsetHeight,a):document.body&&document.body.offsetWidth?(a.width=document.body.offsetWidth,a.height=document.body.offsetHeight,a):a},a.utils.windowResize=function(b){return window.addEventListener?window.addEventListener("resize",b):a.log("ERROR: Failed to bind to window.resize with: ",b),{callback:b,clear:function(){window.removeEventListener("resize",b)}}},a.utils.getColor=function(b){if(void 0===b)return a.utils.defaultColor();if(Array.isArray(b)){var c=d3.scale.ordinal().range(b);return function(a,b){var d=void 0===b?a:b;return a.color||c(d)}}return b},a.utils.defaultColor=function(){return a.utils.getColor(d3.scale.category20().range())},a.utils.customTheme=function(a,b,c){b=b||function(a){return a.key},c=c||d3.scale.category20().range();var d=c.length;return function(e){var f=b(e);return"function"==typeof a[f]?a[f]():void 0!==a[f]?a[f]:(d||(d=c.length),d-=1,c[d])}},a.utils.pjax=function(b,c){var d=function(d){d3.html(d,function(d){var e=d3.select(c).node();e.parentNode.replaceChild(d3.select(d).select(c).node(),e),a.utils.pjax(b,c)})};d3.selectAll(b).on("click",function(){history.pushState(this.href,this.textContent,this.href),d(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&d(d3.event.state)})},a.utils.calcApproxTextWidth=function(a){if("function"==typeof a.style&&"function"==typeof a.text){var b=parseInt(a.style("font-size").replace("px",""),10),c=a.text().length;return c*b*.5}return 0},a.utils.NaNtoZero=function(a){return"number"!=typeof a||isNaN(a)||null===a||1/0===a||a===-1/0?0:a},d3.selection.prototype.watchTransition=function(a){var b=[this].concat([].slice.call(arguments,1));return a.transition.apply(a,b)},a.utils.renderWatch=function(b,c){if(!(this instanceof a.utils.renderWatch))return new a.utils.renderWatch(b,c);var d=void 0!==c?c:250,e=[],f=this;this.models=function(a){return a=[].slice.call(arguments,0),a.forEach(function(a){a.__rendered=!1,function(a){a.dispatch.on("renderEnd",function(){a.__rendered=!0,f.renderEnd("model")})}(a),e.indexOf(a)<0&&e.push(a)}),this},this.reset=function(a){void 0!==a&&(d=a),e=[]},this.transition=function(a,b,c){if(b=arguments.length>1?[].slice.call(arguments,1):[],c=b.length>1?b.pop():void 0!==d?d:250,a.__rendered=!1,e.indexOf(a)<0&&e.push(a),0===c)return a.__rendered=!0,a.delay=function(){return this},a.duration=function(){return this},a;a.__rendered=0===a.length?!0:a.every(function(a){return!a.length})?!0:!1;var g=0;return a.transition().duration(c).each(function(){++g}).each("end",function(){0===--g&&(a.__rendered=!0,f.renderEnd.apply(this,b))})},this.renderEnd=function(){e.every(function(a){return a.__rendered})&&(e.forEach(function(a){a.__rendered=!1}),b.renderEnd.apply(this,arguments))}},a.utils.deepExtend=function(b){var c=arguments.length>1?[].slice.call(arguments,1):[];c.forEach(function(c){for(var d in c){var e=b[d]instanceof Array,f="object"==typeof b[d],g="object"==typeof c[d];f&&!e&&g?a.utils.deepExtend(b[d],c[d]):b[d]=c[d]}})},a.utils.state=function(){if(!(this instanceof a.utils.state))return new a.utils.state;var b={},c=function(){},d=function(){return{}},e=null,f=null;this.dispatch=d3.dispatch("change","set"),this.dispatch.on("set",function(a){c(a,!0)}),this.getter=function(a){return d=a,this},this.setter=function(a,b){return b||(b=function(){}),c=function(c,d){a(c),d&&b()},this},this.init=function(b){e=e||{},a.utils.deepExtend(e,b)};var g=function(){var a=d();if(JSON.stringify(a)===JSON.stringify(b))return!1;for(var c in a)void 0===b[c]&&(b[c]={}),b[c]=a[c],f=!0;return!0};this.update=function(){e&&(c(e,!1),e=null),g.call(this)&&this.dispatch.change(b)}},a.utils.optionsFunc=function(a){return a&&d3.map(a).forEach(function(a,b){"function"==typeof this[a]&&this[a](b)}.bind(this)),this},a.utils.calcTicksX=function(b,c){var d=1,e=0;for(e;ed?f:d}return a.log("Requested number of ticks: ",b),a.log("Calculated max values to be: ",d),b=b>d?b=d-1:b,b=1>b?1:b,b=Math.floor(b),a.log("Calculating tick count as: ",b),b},a.utils.calcTicksY=function(b,c){return a.utils.calcTicksX(b,c)},a.utils.initOption=function(a,b){a._calls&&a._calls[b]?a[b]=a._calls[b]:(a[b]=function(c){return arguments.length?(a._overrides[b]=!0,a._options[b]=c,a):a._options[b]},a["_"+b]=function(c){return arguments.length?(a._overrides[b]||(a._options[b]=c),a):a._options[b]})},a.utils.initOptions=function(b){b._overrides=b._overrides||{};var c=Object.getOwnPropertyNames(b._options||{}),d=Object.getOwnPropertyNames(b._calls||{});c=c.concat(d);for(var e in c)a.utils.initOption(b,c[e])},a.utils.inheritOptionsD3=function(a,b,c){a._d3options=c.concat(a._d3options||[]),c.unshift(b),c.unshift(a),d3.rebind.apply(this,c)},a.utils.arrayUnique=function(a){return a.sort().filter(function(b,c){return!c||b!=a[c-1]})},a.utils.symbolMap=d3.map(),a.utils.symbol=function(){function b(b,e){var f=c.call(this,b,e),g=d.call(this,b,e);return-1!==d3.svg.symbolTypes.indexOf(f)?d3.svg.symbol().type(f).size(g)():a.utils.symbolMap.get(f)(g)}var c,d=64;return b.type=function(a){return arguments.length?(c=d3.functor(a),b):c},b.size=function(a){return arguments.length?(d=d3.functor(a),b):d},b},a.utils.inheritOptions=function(b,c){var d=Object.getOwnPropertyNames(c._options||{}),e=Object.getOwnPropertyNames(c._calls||{}),f=c._inherited||[],g=c._d3options||[],h=d.concat(e).concat(f).concat(g);h.unshift(c),h.unshift(b),d3.rebind.apply(this,h),b._inherited=a.utils.arrayUnique(d.concat(e).concat(f).concat(d).concat(b._inherited||[])),b._d3options=a.utils.arrayUnique(g.concat(b._d3options||[]))},a.utils.initSVG=function(a){a.classed({"nvd3-svg":!0})},a.utils.sanitizeHeight=function(a,b){return a||parseInt(b.style("height"),10)||400},a.utils.sanitizeWidth=function(a,b){return a||parseInt(b.style("width"),10)||960},a.utils.availableHeight=function(b,c,d){return a.utils.sanitizeHeight(b,c)-d.top-d.bottom},a.utils.availableWidth=function(b,c,d){return a.utils.sanitizeWidth(b,c)-d.left-d.right},a.utils.noData=function(b,c){var d=b.options(),e=d.margin(),f=d.noData(),g=null==f?["No Data Available."]:[f],h=a.utils.availableHeight(d.height(),c,e),i=a.utils.availableWidth(d.width(),c,e),j=e.left+i/2,k=e.top+h/2;c.selectAll("g").remove();var l=c.selectAll(".nv-noData").data(g);l.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),l.attr("x",j).attr("y",k).text(function(a){return a})},a.models.axis=function(){"use strict";function b(g){return s.reset(),g.each(function(b){var g=d3.select(this);a.utils.initSVG(g);var p=g.selectAll("g.nv-wrap.nv-axis").data([b]),q=p.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),t=(q.append("g"),p.select("g"));null!==n?c.ticks(n):("top"==c.orient()||"bottom"==c.orient())&&c.ticks(Math.abs(d.range()[1]-d.range()[0])/100),t.watchTransition(s,"axis").call(c),r=r||c.scale();var u=c.tickFormat();null==u&&(u=r.tickFormat());var v=t.selectAll("text.nv-axislabel").data([h||null]);v.exit().remove();var w,x,y;switch(c.orient()){case"top":v.enter().append("text").attr("class","nv-axislabel"),y=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),v.attr("text-anchor","middle").attr("y",0).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b))+",0)"}).select("text").attr("dy","-0.5em").attr("y",-c.tickPadding()).attr("text-anchor","middle").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max top").attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d.range()[c])+",0)"}));break;case"bottom":w=o+36;var z=30,A=0,B=t.selectAll("g").select("text"),C="";if(j%360){B.each(function(){var a=this.getBoundingClientRect(),b=a.width;A=a.height,b>z&&(z=b)}),C="rotate("+j+" 0,"+(A/2+c.tickPadding())+")";var D=Math.abs(Math.sin(j*Math.PI/180));w=(D?D*z:z)+30,B.attr("transform",C).style("text-anchor",j%360>0?"start":"end")}v.enter().append("text").attr("class","nv-axislabel"),y=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),v.attr("text-anchor","middle").attr("y",w).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data([d.domain()[0],d.domain()[d.domain().length-1]]),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",c.tickPadding()).attr("transform",C).style("text-anchor",j?j%360>0?"start":"end":"middle").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max bottom").attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"})),l&&B.attr("transform",function(a,b){return"translate(0,"+(b%2==0?"0":"12")+")"});break;case"right":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"begin").attr("transform",k?"rotate(90)":"").attr("y",k?-Math.max(e.right,f)+12:-10).attr("x",k?d3.max(d.range())/2:c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b){return"translate(0,"+a.utils.NaNtoZero(d(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",c.tickPadding()).style("text-anchor","start").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1));break;case"left":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"end").attr("transform",k?"rotate(-90)":"").attr("y",k?-Math.max(e.left,f)+25-(o||0):-10).attr("x",k?-d3.max(d.range())/2:-c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b){return"translate(0,"+a.utils.NaNtoZero(r(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-c.tickPadding()).attr("text-anchor","end").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1))}if(v.text(function(a){return a}),!i||"left"!==c.orient()&&"right"!==c.orient()||(t.selectAll("g").each(function(a){d3.select(this).select("text").attr("opacity",1),(d(a)d.range()[0]-10)&&((a>1e-10||-1e-10>a)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0))}),d.domain()[0]==d.domain()[1]&&0==d.domain()[0]&&p.selectAll("g.nv-axisMaxMin").style("opacity",function(a,b){return b?0:1})),i&&("top"===c.orient()||"bottom"===c.orient())){var E=[];p.selectAll("g.nv-axisMaxMin").each(function(a,b){try{E.push(b?d(a)-this.getBoundingClientRect().width-4:d(a)+this.getBoundingClientRect().width+4)}catch(c){E.push(b?d(a)-4:d(a)+4)}}),t.selectAll("g").each(function(a){(d(a)E[1])&&(a>1e-10||-1e-10>a?d3.select(this).remove():d3.select(this).select("text").remove())})}t.selectAll(".tick").filter(function(a){return!parseFloat(Math.round(1e5*a)/1e6)&&void 0!==a}).classed("zero",!0),r=d.copy()}),s.renderEnd("axis immediate"),b}var c=d3.svg.axis(),d=d3.scale.linear(),e={top:0,right:0,bottom:0,left:0},f=75,g=60,h=null,i=!0,j=0,k=!0,l=!1,m=!1,n=null,o=0,p=250,q=d3.dispatch("renderEnd");c.scale(d).orient("bottom").tickFormat(function(a){return a});var r,s=a.utils.renderWatch(q,p);return b.axis=c,b.dispatch=q,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{axisLabelDistance:{get:function(){return o},set:function(a){o=a}},staggerLabels:{get:function(){return l},set:function(a){l=a}},rotateLabels:{get:function(){return j},set:function(a){j=a}},rotateYLabel:{get:function(){return k},set:function(a){k=a}},showMaxMin:{get:function(){return i},set:function(a){i=a}},axisLabel:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return g},set:function(a){g=a}},ticks:{get:function(){return n},set:function(a){n=a}},width:{get:function(){return f},set:function(a){f=a}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},duration:{get:function(){return p},set:function(a){p=a,s.reset(p)}},scale:{get:function(){return d},set:function(e){d=e,c.scale(d),m="function"==typeof d.rangeBands,a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"])}}}),a.utils.initOptions(b),a.utils.inheritOptionsD3(b,c,["orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"]),a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"]),b},a.models.boxPlot=function(){"use strict";function b(l){return v.reset(),l.each(function(b){var l=j-i.left-i.right,p=k-i.top-i.bottom;r=d3.select(this),a.utils.initSVG(r),m.domain(c||b.map(function(a,b){return o(a,b)})).rangeBands(e||[0,l],.1);var w=[];if(!d){var x=d3.min(b.map(function(a){var b=[];return b.push(a.values.Q1),a.values.hasOwnProperty("whisker_low")&&null!==a.values.whisker_low&&b.push(a.values.whisker_low),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.min(b)})),y=d3.max(b.map(function(a){var b=[];return b.push(a.values.Q3),a.values.hasOwnProperty("whisker_high")&&null!==a.values.whisker_high&&b.push(a.values.whisker_high),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.max(b)}));w=[x,y]}n.domain(d||w),n.range(f||[p,0]),g=g||m,h=h||n.copy().range([n(0),n(0)]);{var z=r.selectAll("g.nv-wrap").data([b]);z.enter().append("g").attr("class","nvd3 nv-wrap")}z.attr("transform","translate("+i.left+","+i.top+")");var A=z.selectAll(".nv-boxplot").data(function(a){return a}),B=A.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);A.attr("class","nv-boxplot").attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}).classed("hover",function(a){return a.hover}),A.watchTransition(v,"nv-boxplot: boxplots").style("stroke-opacity",1).style("fill-opacity",.75).delay(function(a,c){return c*t/b.length}).attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}),A.exit().remove(),B.each(function(a,b){var c=d3.select(this);["low","high"].forEach(function(d){a.values.hasOwnProperty("whisker_"+d)&&null!==a.values["whisker_"+d]&&(c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-whisker nv-boxplot-"+d),c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-tick nv-boxplot-"+d))})});var C=A.selectAll(".nv-boxplot-outlier").data(function(a){return a.values.hasOwnProperty("outliers")&&null!==a.values.outliers?a.values.outliers:[]});C.enter().append("circle").style("fill",function(a,b,c){return q(a,c)}).style("stroke",function(a,b,c){return q(a,c)}).on("mouseover",function(a,b,c){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:a,color:q(a,c)},e:d3.event})}).on("mouseout",function(a,b,c){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:a,color:q(a,c)},e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})}),C.attr("class","nv-boxplot-outlier"),C.watchTransition(v,"nv-boxplot: nv-boxplot-outlier").attr("cx",.45*m.rangeBand()).attr("cy",function(a){return n(a)}).attr("r","3"),C.exit().remove();var D=function(){return null===u?.9*m.rangeBand():Math.min(75,.9*m.rangeBand())},E=function(){return.45*m.rangeBand()-D()/2},F=function(){return.45*m.rangeBand()+D()/2};["low","high"].forEach(function(a){var b="low"===a?"Q1":"Q3";A.select("line.nv-boxplot-whisker.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",.45*m.rangeBand()).attr("y1",function(b){return n(b.values["whisker_"+a])}).attr("x2",.45*m.rangeBand()).attr("y2",function(a){return n(a.values[b])}),A.select("line.nv-boxplot-tick.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",E).attr("y1",function(b){return n(b.values["whisker_"+a])}).attr("x2",F).attr("y2",function(b){return n(b.values["whisker_"+a])})}),["low","high"].forEach(function(a){B.selectAll(".nv-boxplot-"+a).on("mouseover",function(b,c,d){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mouseout",function(b,c,d){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})})}),B.append("rect").attr("class","nv-boxplot-box").on("mouseover",function(a,b){d3.select(this).classed("hover",!0),s.elementMouseover({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),s.elementMouseout({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})}),A.select("rect.nv-boxplot-box").watchTransition(v,"nv-boxplot: boxes").attr("y",function(a){return n(a.values.Q3)}).attr("width",D).attr("x",E).attr("height",function(a){return Math.abs(n(a.values.Q3)-n(a.values.Q1))||1}).style("fill",function(a,b){return a.color||q(a,b)}).style("stroke",function(a,b){return a.color||q(a,b)}),B.append("line").attr("class","nv-boxplot-median"),A.select("line.nv-boxplot-median").watchTransition(v,"nv-boxplot: boxplots line").attr("x1",E).attr("y1",function(a){return n(a.values.Q2)}).attr("x2",F).attr("y2",function(a){return n(a.values.Q2)}),g=m.copy(),h=n.copy()}),v.renderEnd("nv-boxplot immediate"),b}var c,d,e,f,g,h,i={top:0,right:0,bottom:0,left:0},j=960,k=500,l=Math.floor(1e4*Math.random()),m=d3.scale.ordinal(),n=d3.scale.linear(),o=function(a){return a.x},p=function(a){return a.y},q=a.utils.defaultColor(),r=null,s=d3.dispatch("elementMouseover","elementMouseout","elementMousemove","renderEnd"),t=250,u=null,v=a.utils.renderWatch(s,t);return b.dispatch=s,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},maxBoxWidth:{get:function(){return u},set:function(a){u=a}},x:{get:function(){return o},set:function(a){o=a}},y:{get:function(){return p},set:function(a){p=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return l},set:function(a){l=a}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}},duration:{get:function(){return t},set:function(a){t=a,v.reset(t)}}}),a.utils.initOptions(b),b},a.models.boxPlotChart=function(){"use strict";function b(k){return t.reset(),t.models(e),l&&t.models(f),m&&t.models(g),k.each(function(k){var p=d3.select(this);a.utils.initSVG(p);var t=(i||parseInt(p.style("width"))||960)-h.left-h.right,u=(j||parseInt(p.style("height"))||400)-h.top-h.bottom;if(b.update=function(){r.beforeUpdate(),p.transition().duration(s).call(b)},b.container=this,!(k&&k.length&&k.filter(function(a){return a.values.hasOwnProperty("Q1")&&a.values.hasOwnProperty("Q2")&&a.values.hasOwnProperty("Q3")}).length)){var v=p.selectAll(".nv-noData").data([q]);return v.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),v.attr("x",h.left+t/2).attr("y",h.top+u/2).text(function(a){return a}),b}p.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var w=p.selectAll("g.nv-wrap.nv-boxPlotWithAxes").data([k]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-boxPlotWithAxes").append("g"),y=x.append("defs"),z=w.select("g"); +x.append("g").attr("class","nv-x nv-axis"),x.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),x.append("g").attr("class","nv-barsWrap"),z.attr("transform","translate("+h.left+","+h.top+")"),n&&z.select(".nv-y.nv-axis").attr("transform","translate("+t+",0)"),e.width(t).height(u);var A=z.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));if(A.transition().call(e),y.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),z.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(o?2:1)).attr("height",16).attr("x",-c.rangeBand()/(o?1:2)),l){f.scale(c).ticks(a.utils.calcTicksX(t/100,k)).tickSize(-u,0),z.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),z.select(".nv-x.nv-axis").call(f);var B=z.select(".nv-x.nv-axis").selectAll("g");o&&B.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}m&&(g.scale(d).ticks(Math.floor(u/36)).tickSize(-t,0),z.select(".nv-y.nv-axis").call(g)),z.select(".nv-zeroLine line").attr("x1",0).attr("x2",t).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("nv-boxplot chart immediate"),b}var c,d,e=a.models.boxPlot(),f=a.models.axis(),g=a.models.axis(),h={top:15,right:10,bottom:50,left:60},i=null,j=null,k=a.utils.getColor(),l=!0,m=!0,n=!1,o=!1,p=a.models.tooltip(),q="No Data Available.",r=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(n?"right":"left").tickFormat(d3.format(",.1f")),p.duration(0);var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){p.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){p.data(a).hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){p.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=r,b.boxplot=e,b.xAxis=f,b.yAxis=g,b.tooltip=p,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},staggerLabels:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return l},set:function(a){l=a}},showYAxis:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return tooltips},set:function(a){tooltips=a}},tooltipContent:{get:function(){return p},set:function(a){p=a}},noData:{get:function(){return q},set:function(a){q=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!==a.top?a.top:h.top,h.right=void 0!==a.right?a.right:h.right,h.bottom=void 0!==a.bottom?a.bottom:h.bottom,h.left=void 0!==a.left?a.left:h.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}},rightAlignYAxis:{get:function(){return n},set:function(a){n=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.bullet=function(){"use strict";function b(d){return d.each(function(b,d){var p=m-c.left-c.right,s=n-c.top-c.bottom;o=d3.select(this),a.utils.initSVG(o);{var t=f.call(this,b,d).slice().sort(d3.descending),u=g.call(this,b,d).slice().sort(d3.descending),v=h.call(this,b,d).slice().sort(d3.descending),w=i.call(this,b,d).slice(),x=j.call(this,b,d).slice(),y=k.call(this,b,d).slice(),z=d3.scale.linear().domain(d3.extent(d3.merge([l,t]))).range(e?[p,0]:[0,p]);this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range())}this.__chart__=z;var A=d3.min(t),B=d3.max(t),C=t[1],D=o.selectAll("g.nv-wrap.nv-bullet").data([b]),E=D.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),F=E.append("g"),G=D.select("g");F.append("rect").attr("class","nv-range nv-rangeMax"),F.append("rect").attr("class","nv-range nv-rangeAvg"),F.append("rect").attr("class","nv-range nv-rangeMin"),F.append("rect").attr("class","nv-measure"),D.attr("transform","translate("+c.left+","+c.top+")");var H=function(a){return Math.abs(z(a)-z(0))},I=function(a){return z(0>a?a:0)};G.select("rect.nv-rangeMax").attr("height",s).attr("width",H(B>0?B:A)).attr("x",I(B>0?B:A)).datum(B>0?B:A),G.select("rect.nv-rangeAvg").attr("height",s).attr("width",H(C)).attr("x",I(C)).datum(C),G.select("rect.nv-rangeMin").attr("height",s).attr("width",H(B)).attr("x",I(B)).attr("width",H(B>0?A:B)).attr("x",I(B>0?A:B)).datum(B>0?A:B),G.select("rect.nv-measure").style("fill",q).attr("height",s/3).attr("y",s/3).attr("width",0>v?z(0)-z(v[0]):z(v[0])-z(0)).attr("x",I(v)).on("mouseover",function(){r.elementMouseover({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mouseout",function(){r.elementMouseout({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})});var J=s/6,K=u.map(function(a,b){return{value:a,label:x[b]}});F.selectAll("path.nv-markerTriangle").data(K).enter().append("path").attr("class","nv-markerTriangle").attr("transform",function(a){return"translate("+z(a.value)+","+s/2+")"}).attr("d","M0,"+J+"L"+J+","+-J+" "+-J+","+-J+"Z").on("mouseover",function(a){r.elementMouseover({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill"),pos:[z(a.value),s/2]})}).on("mousemove",function(a){r.elementMousemove({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a){r.elementMouseout({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}),D.selectAll(".nv-range").on("mouseover",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseover({value:a,label:c,color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseout({value:a,label:c,color:d3.select(this).style("fill")})})}),b}var c={top:0,right:0,bottom:0,left:0},d="left",e=!1,f=function(a){return a.ranges},g=function(a){return a.markers?a.markers:[0]},h=function(a){return a.measures},i=function(a){return a.rangeLabels?a.rangeLabels:[]},j=function(a){return a.markerLabels?a.markerLabels:[]},k=function(a){return a.measureLabels?a.measureLabels:[]},l=[0],m=380,n=30,o=null,p=null,q=a.utils.getColor(["#1f77b4"]),r=d3.dispatch("elementMouseover","elementMouseout","elementMousemove");return b.dispatch=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return f},set:function(a){f=a}},markers:{get:function(){return g},set:function(a){g=a}},measures:{get:function(){return h},set:function(a){h=a}},forceX:{get:function(){return l},set:function(a){l=a}},width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},tickFormat:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},orient:{get:function(){return d},set:function(a){d=a,e="right"==d||"bottom"==d}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.bulletChart=function(){"use strict";function b(d){return d.each(function(e,o){var p=d3.select(this);a.utils.initSVG(p);var q=a.utils.availableWidth(k,p,g),r=l-g.top-g.bottom;if(b.update=function(){b(d)},b.container=this,!e||!h.call(this,e,o))return a.utils.noData(b,p),b;p.selectAll(".nv-noData").remove();var s=h.call(this,e,o).slice().sort(d3.descending),t=i.call(this,e,o).slice().sort(d3.descending),u=j.call(this,e,o).slice().sort(d3.descending),v=p.selectAll("g.nv-wrap.nv-bulletChart").data([e]),w=v.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),x=w.append("g"),y=v.select("g");x.append("g").attr("class","nv-bulletWrap"),x.append("g").attr("class","nv-titles"),v.attr("transform","translate("+g.left+","+g.top+")");var z=d3.scale.linear().domain([0,Math.max(s[0],t[0],u[0])]).range(f?[q,0]:[0,q]),A=this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range());this.__chart__=z;var B=x.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(l-g.top-g.bottom)/2+")");B.append("text").attr("class","nv-title").text(function(a){return a.title}),B.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(a){return a.subtitle}),c.width(q).height(r);var C=y.select(".nv-bulletWrap");d3.transition(C).call(c);var D=m||z.tickFormat(q/100),E=y.selectAll("g.nv-tick").data(z.ticks(n?n:q/50),function(a){return this.textContent||D(a)}),F=E.enter().append("g").attr("class","nv-tick").attr("transform",function(a){return"translate("+A(a)+",0)"}).style("opacity",1e-6);F.append("line").attr("y1",r).attr("y2",7*r/6),F.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",7*r/6).text(D);var G=d3.transition(E).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1);G.select("line").attr("y1",r).attr("y2",7*r/6),G.select("text").attr("y",7*r/6),d3.transition(E.exit()).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1e-6).remove()}),d3.timer.flush(),b}var c=a.models.bullet(),d=a.models.tooltip(),e="left",f=!1,g={top:5,right:40,bottom:20,left:120},h=function(a){return a.ranges},i=function(a){return a.markers?a.markers:[0]},j=function(a){return a.measures},k=null,l=55,m=null,n=null,o=null,p=d3.dispatch("tooltipShow","tooltipHide");return d.duration(0).headerEnabled(!1),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.label,value:a.value,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){d.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.bullet=c,b.dispatch=p,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return h},set:function(a){h=a}},markers:{get:function(){return i},set:function(a){i=a}},measures:{get:function(){return j},set:function(a){j=a}},width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},tickFormat:{get:function(){return m},set:function(a){m=a}},ticks:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return o},set:function(a){o=a}},tooltips:{get:function(){return d.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),d.enabled(!!b)}},tooltipContent:{get:function(){return d.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),d.contentGenerator(b)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},orient:{get:function(){return e},set:function(a){e=a,f="right"==e||"bottom"==e}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.candlestickBar=function(){"use strict";function b(x){return x.each(function(b){c=d3.select(this);var x=a.utils.availableWidth(i,c,h),y=a.utils.availableHeight(j,c,h);a.utils.initSVG(c);var A=x/b[0].values.length*.45;l.domain(d||d3.extent(b[0].values.map(n).concat(t))),l.range(v?f||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:f||[5+A/2,x-A/2-5]),m.domain(e||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(g||[y,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var B=d3.select(this).selectAll("g.nv-wrap.nv-candlestickBar").data([b[0].values]),C=B.enter().append("g").attr("class","nvd3 nv-wrap nv-candlestickBar"),D=C.append("defs"),E=C.append("g"),F=B.select("g");E.append("g").attr("class","nv-ticks"),B.attr("transform","translate("+h.left+","+h.top+")"),c.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:k})}),D.append("clipPath").attr("id","nv-chart-clip-path-"+k).append("rect"),B.select("#nv-chart-clip-path-"+k+" rect").attr("width",x).attr("height",y),F.attr("clip-path",w?"url(#nv-chart-clip-path-"+k+")":"");var G=B.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});G.exit().remove();{var H=G.enter().append("g").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b});H.append("line").attr("class","nv-candlestick-lines").attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),H.append("rect").attr("class","nv-candlestick-rects nv-bars").attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}c.selectAll(".nv-candlestick-lines").transition().attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),c.selectAll(".nv-candlestick-rects").transition().attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}),b}var c,d,e,f,g,h={top:0,right:0,bottom:0,left:0},i=null,j=null,k=Math.floor(1e4*Math.random()),l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,d){b.clearHighlights(),c.select(".nv-candlestickBar .nv-tick-0-"+a).classed("hover",d)},b.clearHighlights=function(){c.select(".nv-candlestickBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return k},set:function(a){k=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!=a.top?a.top:h.top,h.right=void 0!=a.right?a.right:h.right,h.bottom=void 0!=a.bottom?a.bottom:h.bottom,h.left=void 0!=a.left?a.left:h.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.cumulativeLineChart=function(){"use strict";function b(l){return H.reset(),H.models(f),r&&H.models(g),s&&H.models(h),l.each(function(l){function A(){d3.select(b.container).style("cursor","ew-resize")}function E(){G.x=d3.event.x,G.i=Math.round(F.invert(G.x)),K()}function H(){d3.select(b.container).style("cursor","auto"),y.index=G.i,C.stateChange(y)}function K(){bb.data([G]);var a=b.duration();b.duration(0),b.update(),b.duration(a)}var L=d3.select(this);a.utils.initSVG(L),L.classed("nv-chart-"+x,!0);var M=this,N=a.utils.availableWidth(o,L,m),O=a.utils.availableHeight(p,L,m);if(b.update=function(){0===D?L.call(b):L.transition().duration(D).call(b)},b.container=this,y.setter(J(l),b.update).getter(I(l)).update(),y.disabled=l.map(function(a){return!!a.disabled}),!z){var P;z={};for(P in y)z[P]=y[P]instanceof Array?y[P].slice(0):y[P]}var Q=d3.behavior.drag().on("dragstart",A).on("drag",E).on("dragend",H);if(!(l&&l.length&&l.filter(function(a){return a.values.length}).length))return a.utils.noData(b,L),b;if(L.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale(),w)f.yDomain(null);else{var R=l.filter(function(a){return!a.disabled}).map(function(a){var b=d3.extent(a.values,f.y());return b[0]<-.95&&(b[0]=-.95),[(b[0]-b[1])/(1+b[1]),(b[1]-b[0])/(1+b[0])]}),S=[d3.min(R,function(a){return a[0]}),d3.max(R,function(a){return a[1]})];f.yDomain(S)}F.domain([0,l[0].values.length-1]).range([0,N]).clamp(!0);var l=c(G.i,l),T=v?"none":"all",U=L.selectAll("g.nv-wrap.nv-cumulativeLine").data([l]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),W=U.select("g");if(V.append("g").attr("class","nv-interactive"),V.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),V.append("g").attr("class","nv-y nv-axis"),V.append("g").attr("class","nv-background"),V.append("g").attr("class","nv-linesWrap").style("pointer-events",T),V.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),V.append("g").attr("class","nv-legendWrap"),V.append("g").attr("class","nv-controlsWrap"),q&&(i.width(N),W.select(".nv-legendWrap").datum(l).call(i),m.top!=i.height()&&(m.top=i.height(),O=a.utils.availableHeight(p,L,m)),W.select(".nv-legendWrap").attr("transform","translate(0,"+-m.top+")")),u){var X=[{key:"Re-scale y-axis",disabled:!w}];j.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),W.select(".nv-controlsWrap").datum(X).attr("transform","translate(0,"+-m.top+")").call(j)}U.attr("transform","translate("+m.left+","+m.top+")"),t&&W.select(".nv-y.nv-axis").attr("transform","translate("+N+",0)");var Y=l.filter(function(a){return a.tempDisabled});U.select(".tempDisabled").remove(),Y.length&&U.append("text").attr("class","tempDisabled").attr("x",N/2).attr("y","-.71em").style("text-anchor","end").text(Y.map(function(a){return a.key}).join(", ")+" values cannot be calculated for this time period."),v&&(k.width(N).height(O).margin({left:m.left,top:m.top}).svgContainer(L).xScale(d),U.select(".nv-interactive").call(k)),V.select(".nv-background").append("rect"),W.select(".nv-background rect").attr("width",N).attr("height",O),f.y(function(a){return a.display.y}).width(N).height(O).color(l.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!l[b].disabled&&!l[b].tempDisabled}));var Z=W.select(".nv-linesWrap").datum(l.filter(function(a){return!a.disabled&&!a.tempDisabled}));Z.call(f),l.forEach(function(a,b){a.seriesIndex=b});var $=l.filter(function(a){return!a.disabled&&!!B(a)}),_=W.select(".nv-avgLinesWrap").selectAll("line").data($,function(a){return a.key}),ab=function(a){var b=e(B(a));return 0>b?0:b>O?O:b};_.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(a){return f.color()(a,a.seriesIndex)}).attr("x1",0).attr("x2",N).attr("y1",ab).attr("y2",ab),_.style("stroke-opacity",function(a){var b=e(B(a));return 0>b||b>O?0:1}).attr("x1",0).attr("x2",N).attr("y1",ab).attr("y2",ab),_.exit().remove();var bb=Z.selectAll(".nv-indexLine").data([G]);bb.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(Q),bb.attr("transform",function(a){return"translate("+F(a.i)+",0)"}).attr("height",O),r&&(g.scale(d)._ticks(a.utils.calcTicksX(N/70,l)).tickSize(-O,0),W.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),W.select(".nv-x.nv-axis").call(g)),s&&(h.scale(e)._ticks(a.utils.calcTicksY(O/36,l)).tickSize(-N,0),W.select(".nv-y.nv-axis").call(h)),W.select(".nv-background rect").on("click",function(){G.x=d3.mouse(this)[0],G.i=Math.round(F.invert(G.x)),y.index=G.i,C.stateChange(y),K()}),f.dispatch.on("elementClick",function(a){G.i=a.pointIndex,G.x=F(G.i),y.index=G.i,C.stateChange(y),K()}),j.dispatch.on("legendClick",function(a){a.disabled=!a.disabled,w=!a.disabled,y.rescaleY=w,C.stateChange(y),b.update()}),i.dispatch.on("stateChange",function(a){for(var c in a)y[c]=a[c];C.stateChange(y),b.update()}),k.dispatch.on("elementMousemove",function(c){f.clearHighlights();var d,e,i,j=[];if(l.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,c.pointXValue,b.x()),f.highlightPoint(h,e,!0);var k=g.values[e];"undefined"!=typeof k&&("undefined"==typeof d&&(d=k),"undefined"==typeof i&&(i=b.xScale()(b.x()(k,e))),j.push({key:g.key,value:b.y()(k,e),color:n(g,g.seriesIndex)}))}),j.length>2){var o=b.yScale().invert(c.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(j.map(function(a){return a.value}),o,q);null!==r&&(j[r].highlight=!0)}var s=g.tickFormat()(b.x()(d,e),e);k.tooltip.position({left:i+m.left,top:c.mouseY+m.top}).chartContainer(M.parentNode).valueFormatter(function(a){return h.tickFormat()(a)}).data({value:s,series:j})(),k.renderGuideLine(i)}),k.dispatch.on("elementMouseout",function(){f.clearHighlights()}),C.on("changeState",function(a){"undefined"!=typeof a.disabled&&(l.forEach(function(b,c){b.disabled=a.disabled[c]}),y.disabled=a.disabled),"undefined"!=typeof a.index&&(G.i=a.index,G.x=F(G.i),y.index=a.index,bb.data([G])),"undefined"!=typeof a.rescaleY&&(w=a.rescaleY),b.update()})}),H.renderEnd("cumulativeLineChart immediate"),b}function c(a,b){return K||(K=f.y()),b.map(function(b){if(!b.values)return b;var c=b.values[a];if(null==c)return b;var d=K(c,a);return-.95>d&&!E?(b.tempDisabled=!0,b):(b.tempDisabled=!1,b.values=b.values.map(function(a,b){return a.display={y:(K(a,b)-d)/(1+d)},a}),b)})}var d,e,f=a.models.line(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.models.legend(),k=a.interactiveGuideline(),l=a.models.tooltip(),m={top:30,right:30,bottom:50,left:60},n=a.utils.defaultColor(),o=null,p=null,q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=!0,x=f.id(),y=a.utils.state(),z=null,A=null,B=function(a){return a.average},C=d3.dispatch("stateChange","changeState","renderEnd"),D=250,E=!1;y.index=0,y.rescaleY=w,g.orient("bottom").tickPadding(7),h.orient(t?"right":"left"),l.valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)}),j.updateState(!1);var F=d3.scale.linear(),G={i:0,x:0},H=a.utils.renderWatch(C,D),I=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),index:G.i,rescaleY:w}}},J=function(a){return function(b){void 0!==b.index&&(G.i=b.index),void 0!==b.rescaleY&&(w=b.rescaleY),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};f.dispatch.on("elementMouseover.tooltip",function(a){var c={x:b.x()(a.point),y:b.y()(a.point),color:a.point.color};a.point=c,l.data(a).position(a.pos).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(){l.hidden(!0)});var K=null;return b.dispatch=C,b.lines=f,b.legend=i,b.controls=j,b.xAxis=g,b.yAxis=h,b.interactiveLayer=k,b.state=y,b.tooltip=l,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return o},set:function(a){o=a}},height:{get:function(){return p},set:function(a){p=a}},rescaleY:{get:function(){return w},set:function(a){w=a}},showControls:{get:function(){return u},set:function(a){u=a}},showLegend:{get:function(){return q},set:function(a){q=a}},average:{get:function(){return B},set:function(a){B=a}},defaultState:{get:function(){return z},set:function(a){z=a}},noData:{get:function(){return A},set:function(a){A=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},noErrorCheck:{get:function(){return E},set:function(a){E=a}},tooltips:{get:function(){return l.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),l.enabled(!!b)}},tooltipContent:{get:function(){return l.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),l.contentGenerator(b)}},margin:{get:function(){return m},set:function(a){m.top=void 0!==a.top?a.top:m.top,m.right=void 0!==a.right?a.right:m.right,m.bottom=void 0!==a.bottom?a.bottom:m.bottom,m.left=void 0!==a.left?a.left:m.left}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),i.color(n)}},useInteractiveGuideline:{get:function(){return v},set:function(a){v=a,a===!0&&(b.interactive(!1),b.useVoronoi(!1))}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,h.orient(a?"right":"left")}},duration:{get:function(){return D},set:function(a){D=a,f.duration(D),g.duration(D),h.duration(D),H.reset(D)}}}),a.utils.inheritOptions(b,f),a.utils.initOptions(b),b},a.models.discreteBar=function(){"use strict";function b(m){return y.reset(),m.each(function(b){var m=k-j.left-j.right,x=l-j.top-j.bottom;c=d3.select(this),a.utils.initSVG(c),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var z=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),y0:a.y0}})});n.domain(d||d3.merge(z).map(function(a){return a.x})).rangeBands(f||[0,m],.1),o.domain(e||d3.extent(d3.merge(z).map(function(a){return a.y}).concat(r))),o.range(t?g||[x-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]:g||[x,0]),h=h||n,i=i||o.copy().range([o(0),o(0)]);{var A=c.selectAll("g.nv-wrap.nv-discretebar").data([b]),B=A.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),C=B.append("g");A.select("g")}C.append("g").attr("class","nv-groups"),A.attr("transform","translate("+j.left+","+j.top+")");var D=A.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().watchTransition(y,"discreteBar: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),D.watchTransition(y,"discreteBar: groups").style("stroke-opacity",1).style("fill-opacity",.75);var E=D.selectAll("g.nv-bar").data(function(a){return a.values});E.exit().remove();var F=E.enter().append("g").attr("transform",function(a,b){return"translate("+(n(p(a,b))+.05*n.rangeBand())+", "+o(0)+")"}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),v.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),v.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){v.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){v.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()});F.append("rect").attr("height",0).attr("width",.9*n.rangeBand()/b.length),t?(F.append("text").attr("text-anchor","middle"),E.select("text").text(function(a,b){return u(q(a,b))}).watchTransition(y,"discreteBar: bars text").attr("x",.9*n.rangeBand()/2).attr("y",function(a,b){return q(a,b)<0?o(q(a,b))-o(0)+12:-4})):E.selectAll("text").remove(),E.attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(a,b){return a.color||s(a,b)}).style("stroke",function(a,b){return a.color||s(a,b)}).select("rect").attr("class",w).watchTransition(y,"discreteBar: bars rect").attr("width",.9*n.rangeBand()/b.length),E.watchTransition(y,"discreteBar: bars").attr("transform",function(a,b){var c=n(p(a,b))+.05*n.rangeBand(),d=q(a,b)<0?o(0):o(0)-o(q(a,b))<1?o(0)-1:o(q(a,b));return"translate("+c+", "+d+")"}).select("rect").attr("height",function(a,b){return Math.max(Math.abs(o(q(a,b))-o(e&&e[0]||0))||1)}),h=n.copy(),i=o.copy()}),y.renderEnd("discreteBar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=d3.scale.ordinal(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=[0],s=a.utils.defaultColor(),t=!1,u=d3.format(",.2f"),v=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),w="discreteBar",x=250,y=a.utils.renderWatch(v,x);return b.dispatch=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},forceY:{get:function(){return r},set:function(a){r=a}},showValues:{get:function(){return t},set:function(a){t=a}},x:{get:function(){return p},set:function(a){p=a}},y:{get:function(){return q},set:function(a){q=a}},xScale:{get:function(){return n},set:function(a){n=a}},yScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},valueFormat:{get:function(){return u},set:function(a){u=a}},id:{get:function(){return m},set:function(a){m=a}},rectClass:{get:function(){return w},set:function(a){w=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b)}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x)}}}),a.utils.initOptions(b),b},a.models.discreteBarChart=function(){"use strict";function b(h){return t.reset(),t.models(e),m&&t.models(f),n&&t.models(g),h.each(function(h){var l=d3.select(this);a.utils.initSVG(l);var q=a.utils.availableWidth(j,l,i),t=a.utils.availableHeight(k,l,i);if(b.update=function(){r.beforeUpdate(),l.transition().duration(s).call(b)},b.container=this,!(h&&h.length&&h.filter(function(a){return a.values.length}).length))return a.utils.noData(b,l),b;l.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var u=l.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([h]),v=u.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),w=v.append("defs"),x=u.select("g");v.append("g").attr("class","nv-x nv-axis"),v.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),v.append("g").attr("class","nv-barsWrap"),x.attr("transform","translate("+i.left+","+i.top+")"),o&&x.select(".nv-y.nv-axis").attr("transform","translate("+q+",0)"),e.width(q).height(t);var y=x.select(".nv-barsWrap").datum(h.filter(function(a){return!a.disabled}));if(y.transition().call(e),w.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),x.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(p?2:1)).attr("height",16).attr("x",-c.rangeBand()/(p?1:2)),m){f.scale(c)._ticks(a.utils.calcTicksX(q/100,h)).tickSize(-t,0),x.select(".nv-x.nv-axis").attr("transform","translate(0,"+(d.range()[0]+(e.showValues()&&d.domain()[0]<0?16:0))+")"),x.select(".nv-x.nv-axis").call(f); +var z=x.select(".nv-x.nv-axis").selectAll("g");p&&z.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}n&&(g.scale(d)._ticks(a.utils.calcTicksY(t/36,h)).tickSize(-q,0),x.select(".nv-y.nv-axis").call(g)),x.select(".nv-zeroLine line").attr("x1",0).attr("x2",q).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("discreteBar chart immediate"),b}var c,d,e=a.models.discreteBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.tooltip(),i={top:15,right:10,bottom:50,left:60},j=null,k=null,l=a.utils.getColor(),m=!0,n=!0,o=!1,p=!1,q=null,r=d3.dispatch("beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(o?"right":"left").tickFormat(d3.format(",.1f")),h.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).keyFormatter(function(a,b){return f.tickFormat()(a,b)});var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},h.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){h.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){h.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=r,b.discretebar=e,b.xAxis=f,b.yAxis=g,b.tooltip=h,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},staggerLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return m},set:function(a){m=a}},showYAxis:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return q},set:function(a){q=a}},tooltips:{get:function(){return h.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),h.enabled(!!b)}},tooltipContent:{get:function(){return h.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),h.contentGenerator(b)}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),e.color(l)}},rightAlignYAxis:{get:function(){return o},set:function(a){o=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.distribution=function(){"use strict";function b(k){return m.reset(),k.each(function(b){var k=(e-("x"===g?d.left+d.right:d.top+d.bottom),"x"==g?"y":"x"),l=d3.select(this);a.utils.initSVG(l),c=c||j;var n=l.selectAll("g.nv-distribution").data([b]),o=n.enter().append("g").attr("class","nvd3 nv-distribution"),p=(o.append("g"),n.select("g"));n.attr("transform","translate("+d.left+","+d.top+")");var q=p.selectAll("g.nv-dist").data(function(a){return a},function(a){return a.key});q.enter().append("g"),q.attr("class",function(a,b){return"nv-dist nv-series-"+b}).style("stroke",function(a,b){return i(a,b)});var r=q.selectAll("line.nv-dist"+g).data(function(a){return a.values});r.enter().append("line").attr(g+"1",function(a,b){return c(h(a,b))}).attr(g+"2",function(a,b){return c(h(a,b))}),m.transition(q.exit().selectAll("line.nv-dist"+g),"dist exit").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}).style("stroke-opacity",0).remove(),r.attr("class",function(a,b){return"nv-dist"+g+" nv-dist"+g+"-"+b}).attr(k+"1",0).attr(k+"2",f),m.transition(r,"dist").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}),c=j.copy()}),m.renderEnd("distribution immediate"),b}var c,d={top:0,right:0,bottom:0,left:0},e=400,f=8,g="x",h=function(a){return a[g]},i=a.utils.defaultColor(),j=d3.scale.linear(),k=250,l=d3.dispatch("renderEnd"),m=a.utils.renderWatch(l,k);return b.options=a.utils.optionsFunc.bind(b),b.dispatch=l,b.margin=function(a){return arguments.length?(d.top="undefined"!=typeof a.top?a.top:d.top,d.right="undefined"!=typeof a.right?a.right:d.right,d.bottom="undefined"!=typeof a.bottom?a.bottom:d.bottom,d.left="undefined"!=typeof a.left?a.left:d.left,b):d},b.width=function(a){return arguments.length?(e=a,b):e},b.axis=function(a){return arguments.length?(g=a,b):g},b.size=function(a){return arguments.length?(f=a,b):f},b.getData=function(a){return arguments.length?(h=d3.functor(a),b):h},b.scale=function(a){return arguments.length?(j=a,b):j},b.color=function(c){return arguments.length?(i=a.utils.getColor(c),b):i},b.duration=function(a){return arguments.length?(k=a,m.reset(k),b):k},b},a.models.furiousLegend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?g(a,b):"#fff":m?void 0:a.disabled?g(a,b):"#fff"}function r(a,b){return m&&"furious"==o?a.disengaged?"#fff":g(a,b):a.disabled?"#fff":g(a,b)}return p.each(function(b){var p=d-c.left-c.right,s=d3.select(this);a.utils.initSVG(s);var t=s.selectAll("g.nv-legend").data([b]),u=(t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),t.select("g"));t.attr("transform","translate("+c.left+","+c.top+")");var v,w=u.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),x=w.enter().append("g").attr("class","nv-series");if("classic"==o)x.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),v=w.select("circle");else if("furious"==o){x.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),v=w.select("rect"),x.append("g").attr("class","nv-check-box").property("innerHTML",'').attr("transform","translate(-10,-8)scale(0.5)");var y=w.select(".nv-check-box");y.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",q(a,b))})}x.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var z=w.select("text.nv-legend-text");w.on("mouseover",function(a,b){n.legendMouseover(a,b)}).on("mouseout",function(a,b){n.legendMouseout(a,b)}).on("click",function(a,b){n.legendClick(a,b);var c=w.data();if(k){if("classic"==o)l?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==o)if(m)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!m){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}n.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=o||!m)&&(n.legendDblclick(a,b),k)){var c=w.data();c.forEach(function(a){a.disabled=!0,"furious"==o&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==o&&(a.userDisabled=a.disabled),n.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),w.classed("nv-disabled",function(a){return a.userDisabled}),w.exit().remove(),z.attr("fill",q).text(f);var A;switch(o){case"furious":A=23;break;case"classic":A=20}if(h){var B=[];w.each(function(){var b,c=d3.select(this).select("text");try{if(b=c.node().getComputedTextLength(),0>=b)throw Error()}catch(d){b=a.utils.calcApproxTextWidth(c)}B.push(b+i)});for(var C=0,D=0,E=[];p>D&&Cp&&C>1;){E=[],C--;for(var F=0;F(E[F%C]||0)&&(E[F%C]=B[F]);D=E.reduce(function(a,b){return a+b})}for(var G=[],H=0,I=0;C>H;H++)G[H]=I,I+=E[H];w.attr("transform",function(a,b){return"translate("+G[b%C]+","+(5+Math.floor(b/C)*A)+")"}),j?u.attr("transform","translate("+(d-c.right-D)+","+c.top+")"):u.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(B.length/C)*A}else{var J,K=5,L=5,M=0;w.attr("transform",function(){var a=d3.select(this).select("text").node().getComputedTextLength()+i;return J=L,dM&&(M=L),"translate("+J+","+K+")"}),u.attr("transform","translate("+(d-c.right-M)+","+c.top+")"),e=c.top+c.bottom+K+15}"furious"==o&&v.attr("width",function(a,b){return z[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),v.style("fill",r).style("stroke",function(a,b){return a.color||g(a,b)})}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=!0,i=28,j=!0,k=!0,l=!1,m=!1,n=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),o="classic";return b.dispatch=n,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return j},set:function(a){j=a}},padding:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return k},set:function(a){k=a}},radioButtonMode:{get:function(){return l},set:function(a){l=a}},expanded:{get:function(){return m},set:function(a){m=a}},vers:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBar=function(){"use strict";function b(x){return x.each(function(b){w.reset(),k=d3.select(this);var x=a.utils.availableWidth(h,k,g),y=a.utils.availableHeight(i,k,g);a.utils.initSVG(k),l.domain(c||d3.extent(b[0].values.map(n).concat(p))),l.range(r?e||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:e||[0,x]),m.domain(d||d3.extent(b[0].values.map(o).concat(q))).range(f||[y,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var z=k.selectAll("g.nv-wrap.nv-historicalBar-"+j).data([b[0].values]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+j),B=A.append("defs"),C=A.append("g"),D=z.select("g");C.append("g").attr("class","nv-bars"),z.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){u.chartClick({data:a,index:b,pos:d3.event,id:j})}),B.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),z.select("#nv-chart-clip-path-"+j+" rect").attr("width",x).attr("height",y),D.attr("clip-path",s?"url(#nv-chart-clip-path-"+j+")":"");var E=z.select(".nv-bars").selectAll(".nv-bar").data(function(a){return a},function(a,b){return n(a,b)});E.exit().remove(),E.enter().append("rect").attr("x",0).attr("y",function(b,c){return a.utils.NaNtoZero(m(Math.max(0,o(b,c))))}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.abs(m(o(b,c))-m(0)))}).attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).on("mouseover",function(a,b){v&&(d3.select(this).classed("hover",!0),u.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mouseout",function(a,b){v&&(d3.select(this).classed("hover",!1),u.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mousemove",function(a,b){v&&u.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v&&(u.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}).on("dblclick",function(a,b){v&&(u.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}),E.attr("fill",function(a,b){return t(a,b)}).attr("class",function(a,b,c){return(o(a,b)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+c+"-"+b}).watchTransition(w,"bars").attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).attr("width",x/b[0].values.length*.9),E.watchTransition(w,"bars").attr("y",function(b,c){var d=o(b,c)<0?m(0):m(0)-m(o(b,c))<1?m(0)-1:m(o(b,c));return a.utils.NaNtoZero(d)}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.max(Math.abs(m(o(b,c))-m(0)),1))})}),w.renderEnd("historicalBar immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=[],q=[0],r=!1,s=!0,t=a.utils.defaultColor(),u=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),v=!0,w=a.utils.renderWatch(u,0);return b.highlightPoint=function(a,b){k.select(".nv-bars .nv-bar-0-"+a).classed("hover",b)},b.clearHighlights=function(){k.select(".nv-bars .nv-bar.hover").classed("hover",!1)},b.dispatch=u,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},forceX:{get:function(){return p},set:function(a){p=a}},forceY:{get:function(){return q},set:function(a){q=a}},padData:{get:function(){return r},set:function(a){r=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},clipEdge:{get:function(){return s},set:function(a){s=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return v},set:function(a){v=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return t},set:function(b){t=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBarChart=function(b){"use strict";function c(b){return b.each(function(k){z.reset(),z.models(f),q&&z.models(g),r&&z.models(h);var w=d3.select(this),A=this;a.utils.initSVG(w);var B=a.utils.availableWidth(n,w,l),C=a.utils.availableHeight(o,w,l);if(c.update=function(){w.transition().duration(y).call(c)},c.container=this,u.disabled=k.map(function(a){return!!a.disabled}),!v){var D;v={};for(D in u)v[D]=u[D]instanceof Array?u[D].slice(0):u[D]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(c,w),c;w.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale();var E=w.selectAll("g.nv-wrap.nv-historicalBarChart").data([k]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),G=E.select("g");F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-barsWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),p&&(i.width(B),G.select(".nv-legendWrap").datum(k).call(i),l.top!=i.height()&&(l.top=i.height(),C=a.utils.availableHeight(o,w,l)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-l.top+")")),E.attr("transform","translate("+l.left+","+l.top+")"),s&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),t&&(j.width(B).height(C).margin({left:l.left,top:l.top}).svgContainer(w).xScale(d),E.select(".nv-interactive").call(j)),f.width(B).height(C).color(k.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!k[b].disabled}));var H=G.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));H.transition().call(f),q&&(g.scale(d)._ticks(a.utils.calcTicksX(B/100,k)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),G.select(".nv-x.nv-axis").transition().call(g)),r&&(h.scale(e)._ticks(a.utils.calcTicksY(C/36,k)).tickSize(-B,0),G.select(".nv-y.nv-axis").transition().call(h)),j.dispatch.on("elementMousemove",function(b){f.clearHighlights();var d,e,i,n=[];k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g){e=a.interactiveBisect(g.values,b.pointXValue,c.x()),f.highlightPoint(e,!0);var h=g.values[e];void 0!==h&&(void 0===d&&(d=h),void 0===i&&(i=c.xScale()(c.x()(h,e))),n.push({key:g.key,value:c.y()(h,e),color:m(g,g.seriesIndex),data:g.values[e]}))});var o=g.tickFormat()(c.x()(d,e));j.tooltip.position({left:i+l.left,top:b.mouseY+l.top}).chartContainer(A.parentNode).valueFormatter(function(a){return h.tickFormat()(a)}).data({value:o,index:e,series:n})(),j.renderGuideLine(i)}),j.dispatch.on("elementMouseout",function(){x.tooltipHide(),f.clearHighlights()}),i.dispatch.on("legendClick",function(a){a.disabled=!a.disabled,k.filter(function(a){return!a.disabled}).length||k.map(function(a){return a.disabled=!1,E.selectAll(".nv-series").classed("disabled",!1),a}),u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),b.transition().call(c)}),i.dispatch.on("legendDblclick",function(a){k.forEach(function(a){a.disabled=!0}),a.disabled=!1,u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),c.update()}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),c.update()})}),z.renderEnd("historicalBarChart immediate"),c}var d,e,f=b||a.models.historicalBar(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:90,bottom:50,left:90},m=a.utils.defaultColor(),n=null,o=null,p=!1,q=!0,r=!0,s=!1,t=!1,u={},v=null,w=null,x=d3.dispatch("tooltipHide","stateChange","changeState","renderEnd"),y=250;g.orient("bottom").tickPadding(7),h.orient(s?"right":"left"),k.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)});var z=a.utils.renderWatch(x,0);return f.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:c.x()(a.data),value:c.y()(a.data),color:a.color},k.data(a).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(){k.hidden(!0)}),f.dispatch.on("elementMousemove.tooltip",function(){k.position({top:d3.event.pageY,left:d3.event.pageX})()}),c.dispatch=x,c.bars=f,c.legend=i,c.xAxis=g,c.yAxis=h,c.interactiveLayer=j,c.tooltip=k,c.options=a.utils.optionsFunc.bind(c),c._options=Object.create({},{width:{get:function(){return n},set:function(a){n=a}},height:{get:function(){return o},set:function(a){o=a}},showLegend:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return q},set:function(a){q=a}},showYAxis:{get:function(){return r},set:function(a){r=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},tooltips:{get:function(){return k.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),k.enabled(!!b)}},tooltipContent:{get:function(){return k.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),k.contentGenerator(b)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b),i.color(m),f.color(m)}},duration:{get:function(){return y},set:function(a){y=a,z.reset(y),h.duration(y),g.duration(y)}},rightAlignYAxis:{get:function(){return s},set:function(a){s=a,h.orient(a?"right":"left")}},useInteractiveGuideline:{get:function(){return t},set:function(a){t=a,a===!0&&c.interactive(!1)}}}),a.utils.inheritOptions(c,f),a.utils.initOptions(c),c},a.models.ohlcBarChart=function(){var b=a.models.historicalBarChart(a.models.ohlcBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open'+a.value+"
    open:"+b.yAxis.tickFormat()(c.open)+"
    close:"+b.yAxis.tickFormat()(c.close)+"
    high"+b.yAxis.tickFormat()(c.high)+"
    low:"+b.yAxis.tickFormat()(c.low)+"
    "}),b},a.models.candlestickBarChart=function(){var b=a.models.historicalBarChart(a.models.candlestickBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open'+a.value+"
    open:"+b.yAxis.tickFormat()(c.open)+"
    close:"+b.yAxis.tickFormat()(c.close)+"
    high"+b.yAxis.tickFormat()(c.high)+"
    low:"+b.yAxis.tickFormat()(c.low)+"
    "}),b},a.models.legend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?"#000":"#fff":m?void 0:(a.color||(a.color=g(a,b)),a.disabled?a.color:"#fff")}function r(a,b){return m&&"furious"==o&&a.disengaged?"#eee":a.color||g(a,b)}function s(a){return m&&"furious"==o?1:a.disabled?0:1}return p.each(function(b){var g=d-c.left-c.right,p=d3.select(this);a.utils.initSVG(p);var t=p.selectAll("g.nv-legend").data([b]),u=t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),v=t.select("g");t.attr("transform","translate("+c.left+","+c.top+")");var w,x,y=v.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),z=y.enter().append("g").attr("class","nv-series");switch(o){case"furious":x=23;break;case"classic":x=20}if("classic"==o)z.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),w=y.select("circle");else if("furious"==o){z.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),w=y.select(".nv-legend-symbol"),z.append("g").attr("class","nv-check-box").property("innerHTML",'').attr("transform","translate(-10,-8)scale(0.5)");var A=y.select(".nv-check-box");A.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",q(a,b))})}z.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var B=y.select("text.nv-legend-text");y.on("mouseover",function(a,b){n.legendMouseover(a,b)}).on("mouseout",function(a,b){n.legendMouseout(a,b)}).on("click",function(a,b){n.legendClick(a,b);var c=y.data();if(k){if("classic"==o)l?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==o)if(m)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!m){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}n.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=o||!m)&&(n.legendDblclick(a,b),k)){var c=y.data();c.forEach(function(a){a.disabled=!0,"furious"==o&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==o&&(a.userDisabled=a.disabled),n.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),y.classed("nv-disabled",function(a){return a.userDisabled}),y.exit().remove(),B.attr("fill",q).text(f);var C=0;if(h){var D=[];y.each(function(){var b,c=d3.select(this).select("text");try{if(b=c.node().getComputedTextLength(),0>=b)throw Error()}catch(d){b=a.utils.calcApproxTextWidth(c)}D.push(b+i)});var E=0,F=[];for(C=0;g>C&&Eg&&E>1;){F=[],E--;for(var G=0;G(F[G%E]||0)&&(F[G%E]=D[G]);C=F.reduce(function(a,b){return a+b})}for(var H=[],I=0,J=0;E>I;I++)H[I]=J,J+=F[I];y.attr("transform",function(a,b){return"translate("+H[b%E]+","+(5+Math.floor(b/E)*x)+")"}),j?v.attr("transform","translate("+(d-c.right-C)+","+c.top+")"):v.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(D.length/E)*x}else{var K,L=5,M=5,N=0;y.attr("transform",function(){var a=d3.select(this).select("text").node().getComputedTextLength()+i;return K=M,dN&&(N=M),K+N>C&&(C=K+N),"translate("+K+","+L+")"}),v.attr("transform","translate("+(d-c.right-N)+","+c.top+")"),e=c.top+c.bottom+L+15}if("furious"==o){w.attr("width",function(a,b){return B[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),u.insert("rect",":first-child").attr("class","nv-legend-bg").attr("fill","#eee").attr("opacity",0);var O=v.select(".nv-legend-bg");O.transition().duration(300).attr("x",-x).attr("width",C+x-12).attr("height",e+10).attr("y",-c.top-10).attr("opacity",m?1:0)}w.style("fill",r).style("fill-opacity",s).style("stroke",r)}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=!0,i=32,j=!0,k=!0,l=!1,m=!1,n=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),o="classic";return b.dispatch=n,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return j},set:function(a){j=a}},padding:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return k},set:function(a){k=a}},radioButtonMode:{get:function(){return l},set:function(a){l=a}},expanded:{get:function(){return m},set:function(a){m=a}},vers:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.line=function(){"use strict";function b(r){return v.reset(),v.models(e),r.each(function(b){i=d3.select(this);var r=a.utils.availableWidth(g,i,f),s=a.utils.availableHeight(h,i,f);a.utils.initSVG(i),c=e.xScale(),d=e.yScale(),t=t||c,u=u||d;var w=i.selectAll("g.nv-wrap.nv-line").data([b]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),y=x.append("defs"),z=x.append("g"),A=w.select("g");z.append("g").attr("class","nv-groups"),z.append("g").attr("class","nv-scatterWrap"),w.attr("transform","translate("+f.left+","+f.top+")"),e.width(r).height(s);var B=w.select(".nv-scatterWrap");B.call(e),y.append("clipPath").attr("id","nv-edge-clip-"+e.id()).append("rect"),w.select("#nv-edge-clip-"+e.id()+" rect").attr("width",r).attr("height",s>0?s:0),A.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":""),B.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":"");var C=w.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});C.enter().append("g").style("stroke-opacity",1e-6).style("stroke-width",function(a){return a.strokeWidth||j}).style("fill-opacity",1e-6),C.exit().remove(),C.attr("class",function(a,b){return(a.classed||"")+" nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return k(a,b)}).style("stroke",function(a,b){return k(a,b)}),C.watchTransition(v,"line: groups").style("stroke-opacity",1).style("fill-opacity",function(a){return a.fillOpacity||.5});var D=C.selectAll("path.nv-area").data(function(a){return o(a)?[a]:[]});D.enter().append("path").attr("class","nv-area").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y0(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))}).y1(function(){return u(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])}),C.exit().selectAll("path.nv-area").remove(),D.watchTransition(v,"line: areaPaths").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y0(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))}).y1(function(){return d(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])});var E=C.selectAll("path.nv-line").data(function(a){return[a.values]});E.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))})),E.watchTransition(v,"line: linePaths").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))})),t=c.copy(),u=d.copy()}),v.renderEnd("line immediate"),b}var c,d,e=a.models.scatter(),f={top:0,right:0,bottom:0,left:0},g=960,h=500,i=null,j=1.5,k=a.utils.defaultColor(),l=function(a){return a.x},m=function(a){return a.y},n=function(a,b){return!isNaN(m(a,b))&&null!==m(a,b)},o=function(a){return a.area},p=!1,q="linear",r=250,s=d3.dispatch("elementClick","elementMouseover","elementMouseout","renderEnd");e.pointSize(16).pointDomain([16,256]);var t,u,v=a.utils.renderWatch(s,r);return b.dispatch=s,b.scatter=e,e.dispatch.on("elementClick",function(){s.elementClick.apply(this,arguments)}),e.dispatch.on("elementMouseover",function(){s.elementMouseover.apply(this,arguments)}),e.dispatch.on("elementMouseout",function(){s.elementMouseout.apply(this,arguments)}),b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},defined:{get:function(){return n},set:function(a){n=a}},interpolate:{get:function(){return q},set:function(a){q=a}},clipEdge:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},duration:{get:function(){return r},set:function(a){r=a,v.reset(r),e.duration(r)}},isArea:{get:function(){return o},set:function(a){o=d3.functor(a)}},x:{get:function(){return l},set:function(a){l=a,e.x(a)}},y:{get:function(){return m},set:function(a){m=a,e.y(a)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.lineChart=function(){"use strict";function b(j){return y.reset(),y.models(e),p&&y.models(f),q&&y.models(g),j.each(function(j){var v=d3.select(this),y=this;a.utils.initSVG(v);var B=a.utils.availableWidth(m,v,k),C=a.utils.availableHeight(n,v,k);if(b.update=function(){0===x?v.call(b):v.transition().duration(x).call(b)},b.container=this,t.setter(A(j),b.update).getter(z(j)).update(),t.disabled=j.map(function(a){return!!a.disabled}),!u){var D;u={};for(D in t)u[D]=t[D]instanceof Array?t[D].slice(0):t[D] +}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,v),b;v.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var E=v.selectAll("g.nv-wrap.nv-lineChart").data([j]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),G=E.select("g");F.append("rect").style("opacity",0),F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-linesWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),G.select("rect").attr("width",B).attr("height",C>0?C:0),o&&(h.width(B),G.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),C=a.utils.availableHeight(n,v,k)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-k.top+")")),E.attr("transform","translate("+k.left+","+k.top+")"),r&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),s&&(i.width(B).height(C).margin({left:k.left,top:k.top}).svgContainer(v).xScale(c),E.select(".nv-interactive").call(i)),e.width(B).height(C).color(j.map(function(a,b){return a.color||l(a,b)}).filter(function(a,b){return!j[b].disabled}));var H=G.select(".nv-linesWrap").datum(j.filter(function(a){return!a.disabled}));H.call(e),p&&(f.scale(c)._ticks(a.utils.calcTicksX(B/100,j)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),G.select(".nv-x.nv-axis").call(f)),q&&(g.scale(d)._ticks(a.utils.calcTicksY(C/36,j)).tickSize(-B,0),G.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)t[c]=a[c];w.stateChange(t),b.update()}),i.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,h,m,n=[];if(j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,g){h=a.interactiveBisect(f.values,c.pointXValue,b.x());var i=f.values[h],j=b.y()(i,h);null!=j&&e.highlightPoint(g,h,!0),void 0!==i&&(void 0===d&&(d=i),void 0===m&&(m=b.xScale()(b.x()(i,h))),n.push({key:f.key,value:j,color:l(f,f.seriesIndex)}))}),n.length>2){var o=b.yScale().invert(c.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(n.map(function(a){return a.value}),o,q);null!==r&&(n[r].highlight=!0)}var s=f.tickFormat()(b.x()(d,h));i.tooltip.position({left:c.mouseX+k.left,top:c.mouseY+k.top}).chartContainer(y.parentNode).valueFormatter(function(a){return null==a?"N/A":g.tickFormat()(a)}).data({value:s,index:h,series:n})(),i.renderGuideLine(m)}),i.dispatch.on("elementClick",function(c){var d,f=[];j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(e){var g=a.interactiveBisect(e.values,c.pointXValue,b.x()),h=e.values[g];if("undefined"!=typeof h){"undefined"==typeof d&&(d=b.xScale()(b.x()(h,g)));var i=b.yScale()(b.y()(h,g));f.push({point:h,pointIndex:g,pos:[d,i],seriesIndex:e.seriesIndex,series:e})}}),e.dispatch.elementClick(f)}),i.dispatch.on("elementMouseout",function(){e.clearHighlights()}),w.on("changeState",function(a){"undefined"!=typeof a.disabled&&j.length===a.disabled.length&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),t.disabled=a.disabled),b.update()})}),y.renderEnd("lineChart immediate"),b}var c,d,e=a.models.line(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.interactiveGuideline(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=a.utils.defaultColor(),m=null,n=null,o=!0,p=!0,q=!0,r=!1,s=!1,t=a.utils.state(),u=null,v=null,w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),x=250;f.orient("bottom").tickPadding(7),g.orient(r?"right":"left"),j.valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)});var y=a.utils.renderWatch(w,x),z=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},A=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){j.data(a).position(a.pos).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),b.dispatch=w,b.lines=e,b.legend=h,b.xAxis=f,b.yAxis=g,b.interactiveLayer=i,b.tooltip=j,b.dispatch=w,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return p},set:function(a){p=a}},showYAxis:{get:function(){return q},set:function(a){q=a}},defaultState:{get:function(){return u},set:function(a){u=a}},noData:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x),e.duration(x),f.duration(x),g.duration(x)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),h.color(l),e.color(l)}},rightAlignYAxis:{get:function(){return r},set:function(a){r=a,g.orient(r?"right":"left")}},useInteractiveGuideline:{get:function(){return s},set:function(a){s=a,s&&(e.interactive(!1),e.useVoronoi(!1))}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.linePlusBarChart=function(){"use strict";function b(v){return v.each(function(v){function J(a){var b=+("e"==a),c=b?1:-1,d=X/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function S(){u.empty()||u.extent(I),kb.data([u.empty()?e.domain():I]).each(function(a){var b=e(a[0])-e.range()[0],c=e.range()[1]-e(a[1]);d3.select(this).select(".left").attr("width",0>b?0:b),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>c?0:c)})}function T(){I=u.empty()?null:u.extent(),c=u.empty()?e.domain():u.extent(),K.brush({extent:c,brush:u}),S(),l.width(V).height(W).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),j.width(V).height(W).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var b=db.select(".nv-focus .nv-barsWrap").datum(Z.length?Z.map(function(a){return{key:a.key,values:a.values.filter(function(a,b){return l.x()(a,b)>=c[0]&&l.x()(a,b)<=c[1]})}}):[{values:[]}]),h=db.select(".nv-focus .nv-linesWrap").datum($[0].disabled?[{values:[]}]:$.map(function(a){return{area:a.area,fillOpacity:a.fillOpacity,key:a.key,values:a.values.filter(function(a,b){return j.x()(a,b)>=c[0]&&j.x()(a,b)<=c[1]})}}));d=Z.length?l.xScale():j.xScale(),n.scale(d)._ticks(a.utils.calcTicksX(V/100,v)).tickSize(-W,0),n.domain([Math.ceil(c[0]),Math.floor(c[1])]),db.select(".nv-x.nv-axis").transition().duration(L).call(n),b.transition().duration(L).call(l),h.transition().duration(L).call(j),db.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),p.scale(f)._ticks(a.utils.calcTicksY(W/36,v)).tickSize(-V,0),q.scale(g)._ticks(a.utils.calcTicksY(W/36,v)).tickSize(Z.length?0:-V,0),db.select(".nv-focus .nv-y1.nv-axis").style("opacity",Z.length?1:0),db.select(".nv-focus .nv-y2.nv-axis").style("opacity",$.length&&!$[0].disabled?1:0).attr("transform","translate("+d.range()[1]+",0)"),db.select(".nv-focus .nv-y1.nv-axis").transition().duration(L).call(p),db.select(".nv-focus .nv-y2.nv-axis").transition().duration(L).call(q)}var U=d3.select(this);a.utils.initSVG(U);var V=a.utils.availableWidth(y,U,w),W=a.utils.availableHeight(z,U,w)-(E?H:0),X=H-x.top-x.bottom;if(b.update=function(){U.transition().duration(L).call(b)},b.container=this,M.setter(R(v),b.update).getter(Q(v)).update(),M.disabled=v.map(function(a){return!!a.disabled}),!N){var Y;N={};for(Y in M)N[Y]=M[Y]instanceof Array?M[Y].slice(0):M[Y]}if(!(v&&v.length&&v.filter(function(a){return a.values.length}).length))return a.utils.noData(b,U),b;U.selectAll(".nv-noData").remove();var Z=v.filter(function(a){return!a.disabled&&a.bar}),$=v.filter(function(a){return!a.bar});d=l.xScale(),e=o.scale(),f=l.yScale(),g=j.yScale(),h=m.yScale(),i=k.yScale();var _=v.filter(function(a){return!a.disabled&&a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})}),ab=v.filter(function(a){return!a.disabled&&!a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})});d.range([0,V]),e.domain(d3.extent(d3.merge(_.concat(ab)),function(a){return a.x})).range([0,V]);var bb=U.selectAll("g.nv-wrap.nv-linePlusBar").data([v]),cb=bb.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),db=bb.select("g");cb.append("g").attr("class","nv-legendWrap");var eb=cb.append("g").attr("class","nv-focus");eb.append("g").attr("class","nv-x nv-axis"),eb.append("g").attr("class","nv-y1 nv-axis"),eb.append("g").attr("class","nv-y2 nv-axis"),eb.append("g").attr("class","nv-barsWrap"),eb.append("g").attr("class","nv-linesWrap");var fb=cb.append("g").attr("class","nv-context");if(fb.append("g").attr("class","nv-x nv-axis"),fb.append("g").attr("class","nv-y1 nv-axis"),fb.append("g").attr("class","nv-y2 nv-axis"),fb.append("g").attr("class","nv-barsWrap"),fb.append("g").attr("class","nv-linesWrap"),fb.append("g").attr("class","nv-brushBackground"),fb.append("g").attr("class","nv-x nv-brush"),D){var gb=t.align()?V/2:V,hb=t.align()?gb:0;t.width(gb),db.select(".nv-legendWrap").datum(v.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(a.bar?O:P),a})).call(t),w.top!=t.height()&&(w.top=t.height(),W=a.utils.availableHeight(z,U,w)-H),db.select(".nv-legendWrap").attr("transform","translate("+hb+","+-w.top+")")}bb.attr("transform","translate("+w.left+","+w.top+")"),db.select(".nv-context").style("display",E?"initial":"none"),m.width(V).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),k.width(V).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var ib=db.select(".nv-context .nv-barsWrap").datum(Z.length?Z:[{values:[]}]),jb=db.select(".nv-context .nv-linesWrap").datum($[0].disabled?[{values:[]}]:$);db.select(".nv-context").attr("transform","translate(0,"+(W+w.bottom+x.top)+")"),ib.transition().call(m),jb.transition().call(k),G&&(o._ticks(a.utils.calcTicksX(V/100,v)).tickSize(-X,0),db.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+h.range()[0]+")"),db.select(".nv-context .nv-x.nv-axis").transition().call(o)),F&&(r.scale(h)._ticks(X/36).tickSize(-V,0),s.scale(i)._ticks(X/36).tickSize(Z.length?0:-V,0),db.select(".nv-context .nv-y3.nv-axis").style("opacity",Z.length?1:0).attr("transform","translate(0,"+e.range()[0]+")"),db.select(".nv-context .nv-y2.nv-axis").style("opacity",$.length?1:0).attr("transform","translate("+e.range()[1]+",0)"),db.select(".nv-context .nv-y1.nv-axis").transition().call(r),db.select(".nv-context .nv-y2.nv-axis").transition().call(s)),u.x(e).on("brush",T),I&&u.extent(I);var kb=db.select(".nv-brushBackground").selectAll("g").data([I||u.extent()]),lb=kb.enter().append("g");lb.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",X),lb.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",X);var mb=db.select(".nv-x.nv-brush").call(u);mb.selectAll("rect").attr("height",X),mb.selectAll(".resize").append("path").attr("d",J),t.dispatch.on("stateChange",function(a){for(var c in a)M[c]=a[c];K.stateChange(M),b.update()}),K.on("changeState",function(a){"undefined"!=typeof a.disabled&&(v.forEach(function(b,c){b.disabled=a.disabled[c]}),M.disabled=a.disabled),b.update()}),T()}),b}var c,d,e,f,g,h,i,j=a.models.line(),k=a.models.line(),l=a.models.historicalBar(),m=a.models.historicalBar(),n=a.models.axis(),o=a.models.axis(),p=a.models.axis(),q=a.models.axis(),r=a.models.axis(),s=a.models.axis(),t=a.models.legend(),u=d3.svg.brush(),v=a.models.tooltip(),w={top:30,right:30,bottom:30,left:60},x={top:0,right:30,bottom:20,left:60},y=null,z=null,A=function(a){return a.x},B=function(a){return a.y},C=a.utils.defaultColor(),D=!0,E=!0,F=!1,G=!0,H=50,I=null,J=null,K=d3.dispatch("brush","stateChange","changeState"),L=0,M=a.utils.state(),N=null,O=" (left axis)",P=" (right axis)";j.clipEdge(!0),k.interactive(!1),n.orient("bottom").tickPadding(5),p.orient("left"),q.orient("right"),o.orient("bottom").tickPadding(5),r.orient("left"),s.orient("right"),v.headerEnabled(!0).headerFormatter(function(a,b){return n.tickFormat()(a,b)});var Q=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},R=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return j.dispatch.on("elementMouseover.tooltip",function(a){v.duration(100).valueFormatter(function(a,b){return q.tickFormat()(a,b)}).data(a).position(a.pos).hidden(!1)}),j.dispatch.on("elementMouseout.tooltip",function(){v.hidden(!0)}),l.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={value:b.y()(a.data),color:a.color},v.duration(0).valueFormatter(function(a,b){return p.tickFormat()(a,b)}).data(a).hidden(!1)}),l.dispatch.on("elementMouseout.tooltip",function(){v.hidden(!0)}),l.dispatch.on("elementMousemove.tooltip",function(){v.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=K,b.legend=t,b.lines=j,b.lines2=k,b.bars=l,b.bars2=m,b.xAxis=n,b.x2Axis=o,b.y1Axis=p,b.y2Axis=q,b.y3Axis=r,b.y4Axis=s,b.tooltip=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return y},set:function(a){y=a}},height:{get:function(){return z},set:function(a){z=a}},showLegend:{get:function(){return D},set:function(a){D=a}},brushExtent:{get:function(){return I},set:function(a){I=a}},noData:{get:function(){return J},set:function(a){J=a}},focusEnable:{get:function(){return E},set:function(a){E=a}},focusHeight:{get:function(){return H},set:function(a){H=a}},focusShowAxisX:{get:function(){return G},set:function(a){G=a}},focusShowAxisY:{get:function(){return F},set:function(a){F=a}},legendLeftAxisHint:{get:function(){return O},set:function(a){O=a}},legendRightAxisHint:{get:function(){return P},set:function(a){P=a}},tooltips:{get:function(){return v.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),v.enabled(!!b)}},tooltipContent:{get:function(){return v.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),v.contentGenerator(b)}},margin:{get:function(){return w},set:function(a){w.top=void 0!==a.top?a.top:w.top,w.right=void 0!==a.right?a.right:w.right,w.bottom=void 0!==a.bottom?a.bottom:w.bottom,w.left=void 0!==a.left?a.left:w.left}},duration:{get:function(){return L},set:function(a){L=a}},color:{get:function(){return C},set:function(b){C=a.utils.getColor(b),t.color(C)}},x:{get:function(){return A},set:function(a){A=a,j.x(a),k.x(a),l.x(a),m.x(a)}},y:{get:function(){return B},set:function(a){B=a,j.y(a),k.y(a),l.y(a),m.y(a)}}}),a.utils.inheritOptions(b,j),a.utils.initOptions(b),b},a.models.lineWithFocusChart=function(){"use strict";function b(o){return o.each(function(o){function z(a){var b=+("e"==a),c=b?1:-1,d=M/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function G(){n.empty()||n.extent(y),U.data([n.empty()?e.domain():y]).each(function(a){var b=e(a[0])-c.range()[0],d=K-e(a[1]);d3.select(this).select(".left").attr("width",0>b?0:b),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>d?0:d)})}function H(){y=n.empty()?null:n.extent();var a=n.empty()?e.domain():n.extent();if(!(Math.abs(a[0]-a[1])<=1)){A.brush({extent:a,brush:n}),G();var b=Q.select(".nv-focus .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}).map(function(b){return{key:b.key,area:b.area,values:b.values.filter(function(b,c){return g.x()(b,c)>=a[0]&&g.x()(b,c)<=a[1]})}}));b.transition().duration(B).call(g),Q.select(".nv-focus .nv-x.nv-axis").transition().duration(B).call(i),Q.select(".nv-focus .nv-y.nv-axis").transition().duration(B).call(j)}}var I=d3.select(this),J=this;a.utils.initSVG(I);var K=a.utils.availableWidth(t,I,q),L=a.utils.availableHeight(u,I,q)-v,M=v-r.top-r.bottom;if(b.update=function(){I.transition().duration(B).call(b)},b.container=this,C.setter(F(o),b.update).getter(E(o)).update(),C.disabled=o.map(function(a){return!!a.disabled}),!D){var N;D={};for(N in C)D[N]=C[N]instanceof Array?C[N].slice(0):C[N]}if(!(o&&o.length&&o.filter(function(a){return a.values.length}).length))return a.utils.noData(b,I),b;I.selectAll(".nv-noData").remove(),c=g.xScale(),d=g.yScale(),e=h.xScale(),f=h.yScale();var O=I.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([o]),P=O.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),Q=O.select("g");P.append("g").attr("class","nv-legendWrap");var R=P.append("g").attr("class","nv-focus");R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-linesWrap"),R.append("g").attr("class","nv-interactive");var S=P.append("g").attr("class","nv-context");S.append("g").attr("class","nv-x nv-axis"),S.append("g").attr("class","nv-y nv-axis"),S.append("g").attr("class","nv-linesWrap"),S.append("g").attr("class","nv-brushBackground"),S.append("g").attr("class","nv-x nv-brush"),x&&(m.width(K),Q.select(".nv-legendWrap").datum(o).call(m),q.top!=m.height()&&(q.top=m.height(),L=a.utils.availableHeight(u,I,q)-v),Q.select(".nv-legendWrap").attr("transform","translate(0,"+-q.top+")")),O.attr("transform","translate("+q.left+","+q.top+")"),w&&(p.width(K).height(L).margin({left:q.left,top:q.top}).svgContainer(I).xScale(c),O.select(".nv-interactive").call(p)),g.width(K).height(L).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),h.defined(g.defined()).width(K).height(M).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),Q.select(".nv-context").attr("transform","translate(0,"+(L+q.bottom+r.top)+")");var T=Q.select(".nv-context .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}));d3.transition(T).call(h),i.scale(c)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-L,0),j.scale(d)._ticks(a.utils.calcTicksY(L/36,o)).tickSize(-K,0),Q.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L+")"),n.x(e).on("brush",function(){H()}),y&&n.extent(y);var U=Q.select(".nv-brushBackground").selectAll("g").data([y||n.extent()]),V=U.enter().append("g");V.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",M),V.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",M);var W=Q.select(".nv-x.nv-brush").call(n);W.selectAll("rect").attr("height",M),W.selectAll(".resize").append("path").attr("d",z),H(),k.scale(e)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-M,0),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),d3.transition(Q.select(".nv-context .nv-x.nv-axis")).call(k),l.scale(f)._ticks(a.utils.calcTicksY(M/36,o)).tickSize(-K,0),d3.transition(Q.select(".nv-context .nv-y.nv-axis")).call(l),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),m.dispatch.on("stateChange",function(a){for(var c in a)C[c]=a[c];A.stateChange(C),b.update()}),p.dispatch.on("elementMousemove",function(c){g.clearHighlights();var d,f,h,k=[];if(o.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(i,j){var l=n.empty()?e.domain():n.extent(),m=i.values.filter(function(a,b){return g.x()(a,b)>=l[0]&&g.x()(a,b)<=l[1]});f=a.interactiveBisect(m,c.pointXValue,g.x());var o=m[f],p=b.y()(o,f);null!=p&&g.highlightPoint(j,f,!0),void 0!==o&&(void 0===d&&(d=o),void 0===h&&(h=b.xScale()(b.x()(o,f))),k.push({key:i.key,value:b.y()(o,f),color:s(i,i.seriesIndex)}))}),k.length>2){var l=b.yScale().invert(c.mouseY),m=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),r=.03*m,t=a.nearestValueIndex(k.map(function(a){return a.value}),l,r);null!==t&&(k[t].highlight=!0)}var u=i.tickFormat()(b.x()(d,f));p.tooltip.position({left:c.mouseX+q.left,top:c.mouseY+q.top}).chartContainer(J.parentNode).valueFormatter(function(a){return null==a?"N/A":j.tickFormat()(a)}).data({value:u,index:f,series:k})(),p.renderGuideLine(h)}),p.dispatch.on("elementMouseout",function(){g.clearHighlights()}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&o.forEach(function(b,c){b.disabled=a.disabled[c]}),b.update()})}),b}var c,d,e,f,g=a.models.line(),h=a.models.line(),i=a.models.axis(),j=a.models.axis(),k=a.models.axis(),l=a.models.axis(),m=a.models.legend(),n=d3.svg.brush(),o=a.models.tooltip(),p=a.interactiveGuideline(),q={top:30,right:30,bottom:30,left:60},r={top:0,right:30,bottom:20,left:60},s=a.utils.defaultColor(),t=null,u=null,v=50,w=!1,x=!0,y=null,z=null,A=d3.dispatch("brush","stateChange","changeState"),B=250,C=a.utils.state(),D=null;g.clipEdge(!0).duration(0),h.interactive(!1),i.orient("bottom").tickPadding(5),j.orient("left"),k.orient("bottom").tickPadding(5),l.orient("left"),o.valueFormatter(function(a,b){return j.tickFormat()(a,b)}).headerFormatter(function(a,b){return i.tickFormat()(a,b)});var E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return g.dispatch.on("elementMouseover.tooltip",function(a){o.data(a).position(a.pos).hidden(!1)}),g.dispatch.on("elementMouseout.tooltip",function(){o.hidden(!0)}),b.dispatch=A,b.legend=m,b.lines=g,b.lines2=h,b.xAxis=i,b.yAxis=j,b.x2Axis=k,b.y2Axis=l,b.interactiveLayer=p,b.tooltip=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return t},set:function(a){t=a}},height:{get:function(){return u},set:function(a){u=a}},focusHeight:{get:function(){return v},set:function(a){v=a}},showLegend:{get:function(){return x},set:function(a){x=a}},brushExtent:{get:function(){return y},set:function(a){y=a}},defaultState:{get:function(){return D},set:function(a){D=a}},noData:{get:function(){return z},set:function(a){z=a}},tooltips:{get:function(){return o.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),o.enabled(!!b)}},tooltipContent:{get:function(){return o.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),o.contentGenerator(b)}},margin:{get:function(){return q},set:function(a){q.top=void 0!==a.top?a.top:q.top,q.right=void 0!==a.right?a.right:q.right,q.bottom=void 0!==a.bottom?a.bottom:q.bottom,q.left=void 0!==a.left?a.left:q.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b),m.color(s)}},interpolate:{get:function(){return g.interpolate()},set:function(a){g.interpolate(a),h.interpolate(a)}},xTickFormat:{get:function(){return i.tickFormat()},set:function(a){i.tickFormat(a),k.tickFormat(a)}},yTickFormat:{get:function(){return j.tickFormat()},set:function(a){j.tickFormat(a),l.tickFormat(a)}},duration:{get:function(){return B},set:function(a){B=a,j.duration(B),l.duration(B),i.duration(B),k.duration(B)}},x:{get:function(){return g.x()},set:function(a){g.x(a),h.x(a)}},y:{get:function(){return g.y()},set:function(a){g.y(a),h.y(a)}},useInteractiveGuideline:{get:function(){return w},set:function(a){w=a,w&&(g.interactive(!1),g.useVoronoi(!1))}}}),a.utils.inheritOptions(b,g),a.utils.initOptions(b),b},a.models.multiBar=function(){"use strict";function b(E){return C.reset(),E.each(function(b){var E=k-j.left-j.right,F=l-j.top-j.bottom;p=d3.select(this),a.utils.initSVG(p);var G=0;if(x&&b.length&&(x=[{values:b[0].values.map(function(a){return{x:a.x,y:0,series:a.series,size:.01}})}]),u){var H=d3.layout.stack().offset(v).values(function(a){return a.values}).y(r)(!b.length&&x?x:b);H.forEach(function(a,c){a.nonStackable?(b[c].nonStackableSeries=G++,H[c]=b[c]):c>0&&H[c-1].nonStackable&&H[c].values.map(function(a,b){a.y0-=H[c-1].values[b].y,a.y1=a.y0+a.y})}),b=H}b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),u&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a,f){if(!b[f].nonStackable){var g=a.values[c];g.size=Math.abs(g.y),g.y<0?(g.y1=e,e-=g.size):(g.y1=g.size+d,d+=g.size)}})});var I=d&&e?[]:b.map(function(a,b){return a.values.map(function(a,c){return{x:q(a,c),y:r(a,c),y0:a.y0,y1:a.y1,idx:b}})});m.domain(d||d3.merge(I).map(function(a){return a.x})).rangeBands(f||[0,E],A),n.domain(e||d3.extent(d3.merge(I).map(function(a){var c=a.y;return u&&!b[a.idx].nonStackable&&(c=a.y>0?a.y1:a.y1+a.y),c}).concat(s))).range(g||[F,0]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]+.01*n.domain()[0],n.domain()[1]-.01*n.domain()[1]]:[-1,1]),h=h||m,i=i||n;var J=p.selectAll("g.nv-wrap.nv-multibar").data([b]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),L=K.append("defs"),M=K.append("g"),N=J.select("g");M.append("g").attr("class","nv-groups"),J.attr("transform","translate("+j.left+","+j.top+")"),L.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),J.select("#nv-edge-clip-"+o+" rect").attr("width",E).attr("height",F),N.attr("clip-path",t?"url(#nv-edge-clip-"+o+")":"");var O=J.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});O.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);var P=C.transition(O.exit().selectAll("rect.nv-bar"),"multibarExit",Math.min(100,z)).attr("y",function(a){var c=i(0)||0;return u&&b[a.series]&&!b[a.series].nonStackable&&(c=i(a.y0)),c}).attr("height",0).remove();P.delay&&P.delay(function(a,b){var c=b*(z/(D+1))-b;return c}),O.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return w(a,b)}).style("stroke",function(a,b){return w(a,b)}),O.style("stroke-opacity",1).style("fill-opacity",.75);var Q=O.selectAll("rect.nv-bar").data(function(a){return x&&!b.length?x.values:a.values});Q.exit().remove();Q.enter().append("rect").attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(a,c,d){return u&&!b[d].nonStackable?0:d*m.rangeBand()/b.length}).attr("y",function(a,c,d){return i(u&&!b[d].nonStackable?a.y0:0)||0}).attr("height",0).attr("width",function(a,c,d){return m.rangeBand()/(u&&!b[d].nonStackable?1:b.length)}).attr("transform",function(a,b){return"translate("+m(q(a,b))+",0)"});Q.style("fill",function(a,b,c){return w(a,c,b)}).style("stroke",function(a,b,c){return w(a,c,b)}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),B.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),B.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){B.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){B.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){B.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),Q.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("transform",function(a,b){return"translate("+m(q(a,b))+",0)"}),y&&(c||(c=b.map(function(){return!0})),Q.style("fill",function(a,b,d){return d3.rgb(y(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(y(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}));var R=Q.watchTransition(C,"multibar",Math.min(250,z)).delay(function(a,c){return c*z/b[0].values.length});u?R.attr("y",function(a,c,d){var e=0;return e=b[d].nonStackable?r(a,c)<0?n(0):n(0)-n(r(a,c))<-1?n(0)-1:n(r(a,c))||0:n(a.y1)}).attr("height",function(a,c,d){return b[d].nonStackable?Math.max(Math.abs(n(r(a,c))-n(0)),1)||0:Math.max(Math.abs(n(a.y+a.y0)-n(a.y0)),1)}).attr("x",function(a,c,d){var e=0;return b[d].nonStackable&&(e=a.series*m.rangeBand()/b.length,b.length!==G&&(e=b[d].nonStackableSeries*m.rangeBand()/(2*G))),e}).attr("width",function(a,c,d){if(b[d].nonStackable){var e=m.rangeBand()/G;return b.length!==G&&(e=m.rangeBand()/(2*G)),e}return m.rangeBand()}):R.attr("x",function(a){return a.series*m.rangeBand()/b.length}).attr("width",m.rangeBand()/b.length).attr("y",function(a,b){return r(a,b)<0?n(0):n(0)-n(r(a,b))<1?n(0)-1:n(r(a,b))||0}).attr("height",function(a,b){return Math.max(Math.abs(n(r(a,b))-n(0)),1)||0}),h=m.copy(),i=n.copy(),b[0]&&b[0].values&&(D=b[0].values.length)}),C.renderEnd("multibar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=d3.scale.ordinal(),n=d3.scale.linear(),o=Math.floor(1e4*Math.random()),p=null,q=function(a){return a.x},r=function(a){return a.y},s=[0],t=!0,u=!1,v="zero",w=a.utils.defaultColor(),x=!1,y=null,z=500,A=.1,B=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),C=a.utils.renderWatch(B,z),D=0;return b.dispatch=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return s},set:function(a){s=a}},stacked:{get:function(){return u},set:function(a){u=a}},stackOffset:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return t},set:function(a){t=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return o},set:function(a){o=a}},hideable:{get:function(){return x},set:function(a){x=a}},groupSpacing:{get:function(){return A},set:function(a){A=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return z},set:function(a){z=a,C.reset(z)}},color:{get:function(){return w},set:function(b){w=a.utils.getColor(b)}},barColor:{get:function(){return y},set:function(b){y=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarChart=function(){"use strict";function b(j){return D.reset(),D.models(e),r&&D.models(f),s&&D.models(g),j.each(function(j){var z=d3.select(this);a.utils.initSVG(z);var D=a.utils.availableWidth(l,z,k),H=a.utils.availableHeight(m,z,k);if(b.update=function(){0===C?z.call(b):z.transition().duration(C).call(b)},b.container=this,x.setter(G(j),b.update).getter(F(j)).update(),x.disabled=j.map(function(a){return!!a.disabled}),!y){var I;y={};for(I in x)y[I]=x[I]instanceof Array?x[I].slice(0):x[I]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,z),b;z.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale(); +var J=z.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([j]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),L=J.select("g");if(K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-legendWrap"),K.append("g").attr("class","nv-controlsWrap"),q&&(h.width(D-B()),L.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),H=a.utils.availableHeight(m,z,k)),L.select(".nv-legendWrap").attr("transform","translate("+B()+","+-k.top+")")),o){var M=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(B()).color(["#444","#444","#444"]),L.select(".nv-controlsWrap").datum(M).attr("transform","translate(0,"+-k.top+")").call(i)}J.attr("transform","translate("+k.left+","+k.top+")"),t&&L.select(".nv-y.nv-axis").attr("transform","translate("+D+",0)"),e.disabled(j.map(function(a){return a.disabled})).width(D).height(H).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var N=L.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(N.call(e),r){f.scale(c)._ticks(a.utils.calcTicksX(D/100,j)).tickSize(-H,0),L.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),L.select(".nv-x.nv-axis").call(f);var O=L.select(".nv-x.nv-axis > g").selectAll("g");if(O.selectAll("line, text").style("opacity",1),v){var P=function(a,b){return"translate("+a+","+b+")"},Q=5,R=17;O.selectAll("text").attr("transform",function(a,b,c){return P(0,c%2==0?Q:R)});var S=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;L.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(a,b){return P(0,0===b||S%2!==0?R:Q)})}u&&O.filter(function(a,b){return b%Math.ceil(j[0].values.length/(D/100))!==0}).selectAll("text, line").style("opacity",0),w&&O.selectAll(".tick text").attr("transform","rotate("+w+" 0,0)").style("text-anchor",w>0?"start":"end"),L.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}s&&(g.scale(d)._ticks(a.utils.calcTicksY(H/36,j)).tickSize(-D,0),L.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)x[c]=a[c];A.stateChange(x),b.update()}),i.dispatch.on("legendClick",function(a){if(a.disabled){switch(M=M.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":case p.grouped:e.stacked(!1);break;case"Stacked":case p.stacked:e.stacked(!0)}x.stacked=e.stacked(),A.stateChange(x),b.update()}}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),x.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),x.stacked=a.stacked,E=a.stacked),b.update()})}),D.renderEnd("multibarchart immediate"),b}var c,d,e=a.models.multiBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=0,x=a.utils.state(),y=null,z=null,A=d3.dispatch("stateChange","changeState","renderEnd"),B=function(){return o?180:0},C=250;x.stacked=!1,e.stacked(!1),f.orient("bottom").tickPadding(7).showMaxMin(!1).tickFormat(function(a){return a}),g.orient(t?"right":"left").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var D=a.utils.renderWatch(A),E=!1,F=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:E}}},G=function(a){return function(b){void 0!==b.stacked&&(E=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){j.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=A,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=x,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return y},set:function(a){y=a}},noData:{get:function(){return z},set:function(a){z=a}},reduceXTicks:{get:function(){return u},set:function(a){u=a}},rotateLabels:{get:function(){return w},set:function(a){w=a}},staggerLabels:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return C},set:function(a){C=a,e.duration(C),f.duration(C),g.duration(C),D.reset(C)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiBarHorizontal=function(){"use strict";function b(m){return E.reset(),m.each(function(b){var m=k-j.left-j.right,C=l-j.top-j.bottom;n=d3.select(this),a.utils.initSVG(n),w&&(b=d3.layout.stack().offset("zero").values(function(a){return a.values}).y(r)(b)),b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),w&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a){var b=a.values[c];b.size=Math.abs(b.y),b.y<0?(b.y1=e-b.size,e-=b.size):(b.y1=d,d+=b.size)})});var F=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:q(a,b),y:r(a,b),y0:a.y0,y1:a.y1}})});o.domain(d||d3.merge(F).map(function(a){return a.x})).rangeBands(f||[0,C],A),p.domain(e||d3.extent(d3.merge(F).map(function(a){return w?a.y>0?a.y1+a.y:a.y1:a.y}).concat(t))),p.range(x&&!w?g||[p.domain()[0]<0?z:0,m-(p.domain()[1]>0?z:0)]:g||[0,m]),h=h||o,i=i||d3.scale.linear().domain(p.domain()).range([p(0),p(0)]);{var G=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([b]),H=G.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),I=(H.append("defs"),H.append("g"));G.select("g")}I.append("g").attr("class","nv-groups"),G.attr("transform","translate("+j.left+","+j.top+")");var J=G.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});J.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),J.exit().watchTransition(E,"multibarhorizontal: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),J.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return u(a,b)}).style("stroke",function(a,b){return u(a,b)}),J.watchTransition(E,"multibarhorizontal: groups").style("stroke-opacity",1).style("fill-opacity",.75);var K=J.selectAll("g.nv-bar").data(function(a){return a.values});K.exit().remove();var L=K.enter().append("g").attr("transform",function(a,c,d){return"translate("+i(w?a.y0:0)+","+(w?0:d*o.rangeBand()/b.length+o(q(a,c)))+")"});L.append("rect").attr("width",0).attr("height",o.rangeBand()/(w?1:b.length)),K.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),D.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),D.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){D.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){D.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){D.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){D.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),s(b[0],0)&&(L.append("polyline"),K.select("polyline").attr("fill","none").attr("points",function(a,c){var d=s(a,c),e=.8*o.rangeBand()/(2*(w?1:b.length));d=d.length?d:[-Math.abs(d),Math.abs(d)],d=d.map(function(a){return p(a)-p(0)});var f=[[d[0],-e],[d[0],e],[d[0],0],[d[1],0],[d[1],-e],[d[1],e]];return f.map(function(a){return a.join(",")}).join(" ")}).attr("transform",function(a,c){var d=o.rangeBand()/(2*(w?1:b.length));return"translate("+(r(a,c)<0?0:p(r(a,c))-p(0))+", "+d+")"})),L.append("text"),x&&!w?(K.select("text").attr("text-anchor",function(a,b){return r(a,b)<0?"end":"start"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){var c=B(r(a,b)),d=s(a,b);return void 0===d?c:d.length?c+"+"+B(Math.abs(d[1]))+"-"+B(Math.abs(d[0])):c+"±"+B(Math.abs(d))}),K.watchTransition(E,"multibarhorizontal: bars").select("text").attr("x",function(a,b){return r(a,b)<0?-4:p(r(a,b))-p(0)+4})):K.selectAll("text").text(""),y&&!w?(L.append("text").classed("nv-bar-label",!0),K.select("text.nv-bar-label").attr("text-anchor",function(a,b){return r(a,b)<0?"start":"end"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){return q(a,b)}),K.watchTransition(E,"multibarhorizontal: bars").select("text.nv-bar-label").attr("x",function(a,b){return r(a,b)<0?p(0)-p(r(a,b))+4:-4})):K.selectAll("text.nv-bar-label").text(""),K.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}),v&&(c||(c=b.map(function(){return!0})),K.style("fill",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()})),w?K.watchTransition(E,"multibarhorizontal: bars").attr("transform",function(a,b){return"translate("+p(a.y1)+","+o(q(a,b))+")"}).select("rect").attr("width",function(a,b){return Math.abs(p(r(a,b)+a.y0)-p(a.y0))}).attr("height",o.rangeBand()):K.watchTransition(E,"multibarhorizontal: bars").attr("transform",function(a,c){return"translate("+p(r(a,c)<0?r(a,c):0)+","+(a.series*o.rangeBand()/b.length+o(q(a,c)))+")"}).select("rect").attr("height",o.rangeBand()/b.length).attr("width",function(a,b){return Math.max(Math.abs(p(r(a,b))-p(0)),1)}),h=o.copy(),i=p.copy()}),E.renderEnd("multibarHorizontal immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=null,o=d3.scale.ordinal(),p=d3.scale.linear(),q=function(a){return a.x},r=function(a){return a.y},s=function(a){return a.yErr},t=[0],u=a.utils.defaultColor(),v=null,w=!1,x=!1,y=!1,z=60,A=.1,B=d3.format(",.2f"),C=250,D=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),E=a.utils.renderWatch(D,C);return b.dispatch=D,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},yErr:{get:function(){return s},set:function(a){s=a}},xScale:{get:function(){return o},set:function(a){o=a}},yScale:{get:function(){return p},set:function(a){p=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return t},set:function(a){t=a}},stacked:{get:function(){return w},set:function(a){w=a}},showValues:{get:function(){return x},set:function(a){x=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return m},set:function(a){m=a}},valueFormat:{get:function(){return B},set:function(a){B=a}},valuePadding:{get:function(){return z},set:function(a){z=a}},groupSpacing:{get:function(){return A},set:function(a){A=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return C},set:function(a){C=a,E.reset(C)}},color:{get:function(){return u},set:function(b){u=a.utils.getColor(b)}},barColor:{get:function(){return v},set:function(b){v=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarHorizontalChart=function(){"use strict";function b(j){return C.reset(),C.models(e),r&&C.models(f),s&&C.models(g),j.each(function(j){var w=d3.select(this);a.utils.initSVG(w);var C=a.utils.availableWidth(l,w,k),D=a.utils.availableHeight(m,w,k);if(b.update=function(){w.transition().duration(z).call(b)},b.container=this,t=e.stacked(),u.setter(B(j),b.update).getter(A(j)).update(),u.disabled=j.map(function(a){return!!a.disabled}),!v){var E;v={};for(E in u)v[E]=u[E]instanceof Array?u[E].slice(0):u[E]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,w),b;w.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var F=w.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([j]),G=F.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),H=F.select("g");if(G.append("g").attr("class","nv-x nv-axis"),G.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),G.append("g").attr("class","nv-barsWrap"),G.append("g").attr("class","nv-legendWrap"),G.append("g").attr("class","nv-controlsWrap"),q&&(h.width(C-y()),H.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),D=a.utils.availableHeight(m,w,k)),H.select(".nv-legendWrap").attr("transform","translate("+y()+","+-k.top+")")),o){var I=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(y()).color(["#444","#444","#444"]),H.select(".nv-controlsWrap").datum(I).attr("transform","translate(0,"+-k.top+")").call(i)}F.attr("transform","translate("+k.left+","+k.top+")"),e.disabled(j.map(function(a){return a.disabled})).width(C).height(D).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var J=H.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(J.transition().call(e),r){f.scale(c)._ticks(a.utils.calcTicksY(D/24,j)).tickSize(-C,0),H.select(".nv-x.nv-axis").call(f);var K=H.select(".nv-x.nv-axis").selectAll("g");K.selectAll("line, text")}s&&(g.scale(d)._ticks(a.utils.calcTicksX(C/100,j)).tickSize(-D,0),H.select(".nv-y.nv-axis").attr("transform","translate(0,"+D+")"),H.select(".nv-y.nv-axis").call(g)),H.select(".nv-zeroLine line").attr("x1",d(0)).attr("x2",d(0)).attr("y1",0).attr("y2",-D),h.dispatch.on("stateChange",function(a){for(var c in a)u[c]=a[c];x.stateChange(u),b.update()}),i.dispatch.on("legendClick",function(a){if(a.disabled){switch(I=I.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":e.stacked(!1);break;case"Stacked":e.stacked(!0)}u.stacked=e.stacked(),x.stateChange(u),t=e.stacked(),b.update()}}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),u.stacked=a.stacked,t=a.stacked),b.update()})}),C.renderEnd("multibar horizontal chart immediate"),b}var c,d,e=a.models.multiBarHorizontal(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend().height(30),i=a.models.legend().height(30),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=a.utils.state(),v=null,w=null,x=d3.dispatch("stateChange","changeState","renderEnd"),y=function(){return o?180:0},z=250;u.stacked=!1,e.stacked(t),f.orient("left").tickPadding(5).showMaxMin(!1).tickFormat(function(a){return a}),g.orient("bottom").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var A=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:t}}},B=function(a){return function(b){void 0!==b.stacked&&(t=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},C=a.utils.renderWatch(x,z);return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){j.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=x,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=u,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return z},set:function(a){z=a,C.reset(z),e.duration(z),f.duration(z),g.duration(z)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiChart=function(){"use strict";function b(j){return j.each(function(j){function k(a){var b=2===j[a.seriesIndex].yAxis?z:y;a.value=a.point.x,a.series={value:a.point.y,color:a.point.color},B.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function l(a){var b=2===j[a.seriesIndex].yAxis?z:y;a.point.x=v.x()(a.point),a.point.y=v.y()(a.point),B.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function n(a){var b=2===j[a.data.series].yAxis?z:y;a.value=t.x()(a.data),a.series={value:t.y()(a.data),color:a.color},B.duration(0).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}var C=d3.select(this);a.utils.initSVG(C),b.update=function(){C.transition().call(b)},b.container=this;var D=a.utils.availableWidth(g,C,e),E=a.utils.availableHeight(h,C,e),F=j.filter(function(a){return"line"==a.type&&1==a.yAxis}),G=j.filter(function(a){return"line"==a.type&&2==a.yAxis}),H=j.filter(function(a){return"bar"==a.type&&1==a.yAxis}),I=j.filter(function(a){return"bar"==a.type&&2==a.yAxis}),J=j.filter(function(a){return"area"==a.type&&1==a.yAxis}),K=j.filter(function(a){return"area"==a.type&&2==a.yAxis});if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,C),b;C.selectAll(".nv-noData").remove();var L=j.filter(function(a){return!a.disabled&&1==a.yAxis}).map(function(a){return a.values.map(function(a){return{x:a.x,y:a.y}})}),M=j.filter(function(a){return!a.disabled&&2==a.yAxis}).map(function(a){return a.values.map(function(a){return{x:a.x,y:a.y}})});o.domain(d3.extent(d3.merge(L.concat(M)),function(a){return a.x})).range([0,D]);var N=C.selectAll("g.wrap.multiChart").data([j]),O=N.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y1 nv-axis"),O.append("g").attr("class","nv-y2 nv-axis"),O.append("g").attr("class","lines1Wrap"),O.append("g").attr("class","lines2Wrap"),O.append("g").attr("class","bars1Wrap"),O.append("g").attr("class","bars2Wrap"),O.append("g").attr("class","stack1Wrap"),O.append("g").attr("class","stack2Wrap"),O.append("g").attr("class","legendWrap");var P=N.select("g"),Q=j.map(function(a,b){return j[b].color||f(a,b)});if(i){var R=A.align()?D/2:D,S=A.align()?R:0;A.width(R),A.color(Q),P.select(".legendWrap").datum(j.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(1==a.yAxis?"":" (right axis)"),a})).call(A),e.top!=A.height()&&(e.top=A.height(),E=a.utils.availableHeight(h,C,e)),P.select(".legendWrap").attr("transform","translate("+S+","+-e.top+")")}r.width(D).height(E).interpolate(m).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"line"==j[b].type})),s.width(D).height(E).interpolate(m).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"line"==j[b].type})),t.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"bar"==j[b].type})),u.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"bar"==j[b].type})),v.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"area"==j[b].type})),w.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"area"==j[b].type})),P.attr("transform","translate("+e.left+","+e.top+")");var T=P.select(".lines1Wrap").datum(F.filter(function(a){return!a.disabled})),U=P.select(".bars1Wrap").datum(H.filter(function(a){return!a.disabled})),V=P.select(".stack1Wrap").datum(J.filter(function(a){return!a.disabled})),W=P.select(".lines2Wrap").datum(G.filter(function(a){return!a.disabled})),X=P.select(".bars2Wrap").datum(I.filter(function(a){return!a.disabled})),Y=P.select(".stack2Wrap").datum(K.filter(function(a){return!a.disabled})),Z=J.length?J.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[],$=K.length?K.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[];p.domain(c||d3.extent(d3.merge(L).concat(Z),function(a){return a.y})).range([0,E]),q.domain(d||d3.extent(d3.merge(M).concat($),function(a){return a.y})).range([0,E]),r.yDomain(p.domain()),t.yDomain(p.domain()),v.yDomain(p.domain()),s.yDomain(q.domain()),u.yDomain(q.domain()),w.yDomain(q.domain()),J.length&&d3.transition(V).call(v),K.length&&d3.transition(Y).call(w),H.length&&d3.transition(U).call(t),I.length&&d3.transition(X).call(u),F.length&&d3.transition(T).call(r),G.length&&d3.transition(W).call(s),x._ticks(a.utils.calcTicksX(D/100,j)).tickSize(-E,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+E+")"),d3.transition(P.select(".nv-x.nv-axis")).call(x),y._ticks(a.utils.calcTicksY(E/36,j)).tickSize(-D,0),d3.transition(P.select(".nv-y1.nv-axis")).call(y),z._ticks(a.utils.calcTicksY(E/36,j)).tickSize(-D,0),d3.transition(P.select(".nv-y2.nv-axis")).call(z),P.select(".nv-y1.nv-axis").classed("nv-disabled",L.length?!1:!0).attr("transform","translate("+o.range()[0]+",0)"),P.select(".nv-y2.nv-axis").classed("nv-disabled",M.length?!1:!0).attr("transform","translate("+o.range()[1]+",0)"),A.dispatch.on("stateChange",function(){b.update()}),r.dispatch.on("elementMouseover.tooltip",k),s.dispatch.on("elementMouseover.tooltip",k),r.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),s.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),v.dispatch.on("elementMouseover.tooltip",l),w.dispatch.on("elementMouseover.tooltip",l),v.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),w.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),t.dispatch.on("elementMouseover.tooltip",n),u.dispatch.on("elementMouseover.tooltip",n),t.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),u.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),t.dispatch.on("elementMousemove.tooltip",function(){B.position({top:d3.event.pageY,left:d3.event.pageX})()}),u.dispatch.on("elementMousemove.tooltip",function(){B.position({top:d3.event.pageY,left:d3.event.pageX})()})}),b}var c,d,e={top:30,right:20,bottom:50,left:60},f=a.utils.defaultColor(),g=null,h=null,i=!0,j=null,k=function(a){return a.x},l=function(a){return a.y},m="monotone",n=!0,o=d3.scale.linear(),p=d3.scale.linear(),q=d3.scale.linear(),r=a.models.line().yScale(p),s=a.models.line().yScale(q),t=a.models.multiBar().stacked(!1).yScale(p),u=a.models.multiBar().stacked(!1).yScale(q),v=a.models.stackedArea().yScale(p),w=a.models.stackedArea().yScale(q),x=a.models.axis().scale(o).orient("bottom").tickPadding(5),y=a.models.axis().scale(p).orient("left"),z=a.models.axis().scale(q).orient("right"),A=a.models.legend().height(30),B=a.models.tooltip(),C=d3.dispatch();return b.dispatch=C,b.lines1=r,b.lines2=s,b.bars1=t,b.bars2=u,b.stack1=v,b.stack2=w,b.xAxis=x,b.yAxis1=y,b.yAxis2=z,b.tooltip=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},showLegend:{get:function(){return i},set:function(a){i=a}},yDomain1:{get:function(){return c},set:function(a){c=a}},yDomain2:{get:function(){return d},set:function(a){d=a}},noData:{get:function(){return j},set:function(a){j=a}},interpolate:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return B.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),B.enabled(!!b)}},tooltipContent:{get:function(){return B.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),B.contentGenerator(b)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return f},set:function(b){f=a.utils.getColor(b)}},x:{get:function(){return k},set:function(a){k=a,r.x(a),s.x(a),t.x(a),u.x(a),v.x(a),w.x(a)}},y:{get:function(){return l},set:function(a){l=a,r.y(a),s.y(a),v.y(a),w.y(a),t.y(a),u.y(a)}},useVoronoi:{get:function(){return n},set:function(a){n=a,r.useVoronoi(a),s.useVoronoi(a),v.useVoronoi(a),w.useVoronoi(a)}}}),a.utils.initOptions(b),b},a.models.ohlcBar=function(){"use strict";function b(y){return y.each(function(b){k=d3.select(this);var y=a.utils.availableWidth(h,k,g),A=a.utils.availableHeight(i,k,g);a.utils.initSVG(k);var B=y/b[0].values.length*.9;l.domain(c||d3.extent(b[0].values.map(n).concat(t))),l.range(v?e||[.5*y/b[0].values.length,y*(b[0].values.length-.5)/b[0].values.length]:e||[5+B/2,y-B/2-5]),m.domain(d||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(f||[A,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var C=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([b[0].values]),D=C.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),E=D.append("defs"),F=D.append("g"),G=C.select("g");F.append("g").attr("class","nv-ticks"),C.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:j})}),E.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),C.select("#nv-chart-clip-path-"+j+" rect").attr("width",y).attr("height",A),G.attr("clip-path",w?"url(#nv-chart-clip-path-"+j+")":"");var H=C.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});H.exit().remove(),H.enter().append("path").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}).attr("d",function(a,b){return"m0,0l0,"+(m(p(a,b))-m(r(a,b)))+"l"+-B/2+",0l"+B/2+",0l0,"+(m(s(a,b))-m(p(a,b)))+"l0,"+(m(q(a,b))-m(s(a,b)))+"l"+B/2+",0l"+-B/2+",0z"}).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("fill",function(){return x[0]}).attr("stroke",function(){return x[0]}).attr("x",0).attr("y",function(a,b){return m(Math.max(0,o(a,b)))}).attr("height",function(a,b){return Math.abs(m(o(a,b))-m(0))}),H.attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}),d3.transition(H).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("d",function(a,c){var d=y/b[0].values.length*.9;return"m0,0l0,"+(m(p(a,c))-m(r(a,c)))+"l"+-d/2+",0l"+d/2+",0l0,"+(m(s(a,c))-m(p(a,c)))+"l0,"+(m(q(a,c))-m(s(a,c)))+"l"+d/2+",0l"+-d/2+",0z"})}),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,c){b.clearHighlights(),k.select(".nv-ohlcBar .nv-tick-0-"+a).classed("hover",c)},b.clearHighlights=function(){k.select(".nv-ohlcBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!=a.top?a.top:g.top,g.right=void 0!=a.right?a.right:g.right,g.bottom=void 0!=a.bottom?a.bottom:g.bottom,g.left=void 0!=a.left?a.left:g.left +}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.parallelCoordinates=function(){"use strict";function b(p){return p.each(function(b){function p(a){return F(h.map(function(b){if(isNaN(a[b])||isNaN(parseFloat(a[b]))){var c=g[b].domain(),d=g[b].range(),e=c[0]-(c[1]-c[0])/9;if(J.indexOf(b)<0){var h=d3.scale.linear().domain([e,c[1]]).range([x-12,d[1]]);g[b].brush.y(h),J.push(b)}return[f(b),g[b](e)]}return J.length>0?(D.style("display","inline"),E.style("display","inline")):(D.style("display","none"),E.style("display","none")),[f(b),g[b](a[b])]}))}function q(){var a=h.filter(function(a){return!g[a].brush.empty()}),b=a.map(function(a){return g[a].brush.extent()});k=[],a.forEach(function(a,c){k[c]={dimension:a,extent:b[c]}}),l=[],M.style("display",function(c){var d=a.every(function(a,d){return isNaN(c[a])&&b[d][0]==g[a].brush.y().domain()[0]?!0:b[d][0]<=c[a]&&c[a]<=b[d][1]});return d&&l.push(c),d?null:"none"}),o.brush({filters:k,active:l})}function r(a){m[a]=this.parentNode.__origin__=f(a),L.attr("visibility","hidden")}function s(a){m[a]=Math.min(w,Math.max(0,this.parentNode.__origin__+=d3.event.x)),M.attr("d",p),h.sort(function(a,b){return u(a)-u(b)}),f.domain(h),N.attr("transform",function(a){return"translate("+u(a)+")"})}function t(a){delete this.parentNode.__origin__,delete m[a],d3.select(this.parentNode).attr("transform","translate("+f(a)+")"),M.attr("d",p),L.attr("d",p).attr("visibility",null)}function u(a){var b=m[a];return null==b?f(a):b}var v=d3.select(this),w=a.utils.availableWidth(d,v,c),x=a.utils.availableHeight(e,v,c);a.utils.initSVG(v),l=b,f.rangePoints([0,w],1).domain(h);var y={};h.forEach(function(a){var c=d3.extent(b,function(b){return+b[a]});return y[a]=!1,void 0===c[0]&&(y[a]=!0,c[0]=0,c[1]=0),c[0]===c[1]&&(c[0]=c[0]-1,c[1]=c[1]+1),g[a]=d3.scale.linear().domain(c).range([.9*(x-12),0]),g[a].brush=d3.svg.brush().y(g[a]).on("brush",q),"name"!=a});var z=v.selectAll("g.nv-wrap.nv-parallelCoordinates").data([b]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-parallelCoordinates"),B=A.append("g"),C=z.select("g");B.append("g").attr("class","nv-parallelCoordinates background"),B.append("g").attr("class","nv-parallelCoordinates foreground"),B.append("g").attr("class","nv-parallelCoordinates missingValuesline"),z.attr("transform","translate("+c.left+","+c.top+")");var D,E,F=d3.svg.line().interpolate("cardinal").tension(n),G=d3.svg.axis().orient("left"),H=d3.behavior.drag().on("dragstart",r).on("drag",s).on("dragend",t),I=f.range()[1]-f.range()[0],J=[],K=[0+I/2,x-12,w-I/2,x-12];D=z.select(".missingValuesline").selectAll("line").data([K]),D.enter().append("line"),D.exit().remove(),D.attr("x1",function(a){return a[0]}).attr("y1",function(a){return a[1]}).attr("x2",function(a){return a[2]}).attr("y2",function(a){return a[3]}),E=z.select(".missingValuesline").selectAll("text").data(["undefined values"]),E.append("text").data(["undefined values"]),E.enter().append("text"),E.exit().remove(),E.attr("y",x).attr("x",w-92-I/2).text(function(a){return a});var L=z.select(".background").selectAll("path").data(b);L.enter().append("path"),L.exit().remove(),L.attr("d",p);var M=z.select(".foreground").selectAll("path").data(b);M.enter().append("path"),M.exit().remove(),M.attr("d",p).attr("stroke",j),M.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),o.elementMouseover({label:a.name,data:a.data,index:b,pos:[d3.mouse(this.parentNode)[0],d3.mouse(this.parentNode)[1]]})}),M.on("mouseout",function(a,b){d3.select(this).classed("hover",!1),o.elementMouseout({label:a.name,data:a.data,index:b})});var N=C.selectAll(".dimension").data(h),O=N.enter().append("g").attr("class","nv-parallelCoordinates dimension");O.append("g").attr("class","nv-parallelCoordinates nv-axis"),O.append("g").attr("class","nv-parallelCoordinates-brush"),O.append("text").attr("class","nv-parallelCoordinates nv-label"),N.attr("transform",function(a){return"translate("+f(a)+",0)"}),N.exit().remove(),N.select(".nv-label").style("cursor","move").attr("dy","-1em").attr("text-anchor","middle").text(String).on("mouseover",function(a){o.elementMouseover({dim:a,pos:[d3.mouse(this.parentNode.parentNode)[0],d3.mouse(this.parentNode.parentNode)[1]]})}).on("mouseout",function(a){o.elementMouseout({dim:a})}).call(H),N.select(".nv-axis").each(function(a,b){d3.select(this).call(G.scale(g[a]).tickFormat(d3.format(i[b])))}),N.select(".nv-parallelCoordinates-brush").each(function(a){d3.select(this).call(g[a].brush)}).selectAll("rect").attr("x",-8).attr("width",16)}),b}var c={top:30,right:0,bottom:10,left:0},d=null,e=null,f=d3.scale.ordinal(),g={},h=[],i=[],j=a.utils.defaultColor(),k=[],l=[],m=[],n=1,o=d3.dispatch("brush","elementMouseover","elementMouseout");return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},dimensionNames:{get:function(){return h},set:function(a){h=a}},dimensionFormats:{get:function(){return i},set:function(a){i=a}},lineTension:{get:function(){return n},set:function(a){n=a}},dimensions:{get:function(){return h},set:function(b){a.deprecated("dimensions","use dimensionNames instead"),h=b}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.pie=function(){"use strict";function b(E){return D.reset(),E.each(function(b){function E(a,b){a.endAngle=isNaN(a.endAngle)?0:a.endAngle,a.startAngle=isNaN(a.startAngle)?0:a.startAngle,p||(a.innerRadius=0);var c=d3.interpolate(this._current,a);return this._current=c(0),function(a){return B[b](c(a))}}var F=d-c.left-c.right,G=e-c.top-c.bottom,H=Math.min(F,G)/2,I=[],J=[];if(i=d3.select(this),0===z.length)for(var K=H-H/5,L=y*H,M=0;Mc)return"";if("function"==typeof n)d=n(a,b,{key:f(a.data),value:g(a.data),percent:k(c)});else switch(n){case"key":d=f(a.data);break;case"value":d=k(g(a.data));break;case"percent":d=d3.format("%")(c)}return d})}}),D.renderEnd("pie immediate"),b}var c={top:0,right:0,bottom:0,left:0},d=500,e=500,f=function(a){return a.x},g=function(a){return a.y},h=Math.floor(1e4*Math.random()),i=null,j=a.utils.defaultColor(),k=d3.format(",.2f"),l=!0,m=!1,n="key",o=.02,p=!1,q=!1,r=!0,s=0,t=!1,u=!1,v=!1,w=!1,x=0,y=.5,z=[],A=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),B=[],C=[],D=a.utils.renderWatch(A);return b.dispatch=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{arcsRadius:{get:function(){return z},set:function(a){z=a}},width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},showLabels:{get:function(){return l},set:function(a){l=a}},title:{get:function(){return q},set:function(a){q=a}},titleOffset:{get:function(){return s},set:function(a){s=a}},labelThreshold:{get:function(){return o},set:function(a){o=a}},valueFormat:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return h},set:function(a){h=a}},endAngle:{get:function(){return w},set:function(a){w=a}},startAngle:{get:function(){return u},set:function(a){u=a}},padAngle:{get:function(){return v},set:function(a){v=a}},cornerRadius:{get:function(){return x},set:function(a){x=a}},donutRatio:{get:function(){return y},set:function(a){y=a}},labelsOutside:{get:function(){return m},set:function(a){m=a}},labelSunbeamLayout:{get:function(){return t},set:function(a){t=a}},donut:{get:function(){return p},set:function(a){p=a}},growOnHover:{get:function(){return r},set:function(a){r=a}},pieLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("pieLabelsOutside","use labelsOutside instead")}},donutLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("donutLabelsOutside","use labelsOutside instead")}},labelFormat:{get:function(){return k},set:function(b){k=b,a.deprecated("labelFormat","use valueFormat instead")}},margin:{get:function(){return c},set:function(a){c.top="undefined"!=typeof a.top?a.top:c.top,c.right="undefined"!=typeof a.right?a.right:c.right,c.bottom="undefined"!=typeof a.bottom?a.bottom:c.bottom,c.left="undefined"!=typeof a.left?a.left:c.left}},y:{get:function(){return g},set:function(a){g=d3.functor(a)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},labelType:{get:function(){return n},set:function(a){n=a||"key"}}}),a.utils.initOptions(b),b},a.models.pieChart=function(){"use strict";function b(e){return q.reset(),q.models(c),e.each(function(e){var k=d3.select(this);a.utils.initSVG(k);var n=a.utils.availableWidth(g,k,f),o=a.utils.availableHeight(h,k,f);if(b.update=function(){k.transition().call(b)},b.container=this,l.setter(s(e),b.update).getter(r(e)).update(),l.disabled=e.map(function(a){return!!a.disabled}),!m){var q;m={};for(q in l)m[q]=l[q]instanceof Array?l[q].slice(0):l[q]}if(!e||!e.length)return a.utils.noData(b,k),b;k.selectAll(".nv-noData").remove();var t=k.selectAll("g.nv-wrap.nv-pieChart").data([e]),u=t.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),v=t.select("g");if(u.append("g").attr("class","nv-pieWrap"),u.append("g").attr("class","nv-legendWrap"),i)if("top"===j)d.width(n).key(c.x()),t.select(".nv-legendWrap").datum(e).call(d),f.top!=d.height()&&(f.top=d.height(),o=a.utils.availableHeight(h,k,f)),t.select(".nv-legendWrap").attr("transform","translate(0,"+-f.top+")");else if("right"===j){var w=a.models.legend().width();w>n/2&&(w=n/2),d.height(o).key(c.x()),d.width(w),n-=d.width(),t.select(".nv-legendWrap").datum(e).call(d).attr("transform","translate("+n+",0)")}t.attr("transform","translate("+f.left+","+f.top+")"),c.width(n).height(o);var x=v.select(".nv-pieWrap").datum([e]);d3.transition(x).call(c),d.dispatch.on("stateChange",function(a){for(var c in a)l[c]=a[c];p.stateChange(l),b.update()}),p.on("changeState",function(a){"undefined"!=typeof a.disabled&&(e.forEach(function(b,c){b.disabled=a.disabled[c]}),l.disabled=a.disabled),b.update()})}),q.renderEnd("pieChart immediate"),b}var c=a.models.pie(),d=a.models.legend(),e=a.models.tooltip(),f={top:30,right:20,bottom:20,left:20},g=null,h=null,i=!0,j="top",k=a.utils.defaultColor(),l=a.utils.state(),m=null,n=null,o=250,p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd");e.headerEnabled(!1).duration(0).valueFormatter(function(a,b){return c.valueFormat()(a,b)});var q=a.utils.renderWatch(p),r=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},s=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},e.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){e.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){e.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.legend=d,b.dispatch=p,b.pie=c,b.tooltip=e,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return i},set:function(a){i=a}},legendPosition:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return e.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),e.enabled(!!b)}},tooltipContent:{get:function(){return e.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),e.contentGenerator(b)}},color:{get:function(){return k},set:function(a){k=a,d.color(k),c.color(k)}},duration:{get:function(){return o},set:function(a){o=a,q.reset(o)}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.scatter=function(){"use strict";function b(N){return P.reset(),N.each(function(b){function N(){if(O=!1,!w)return!1;if(M===!0){var a=d3.merge(b.map(function(a,b){return a.values.map(function(a,c){var d=p(a,c),e=q(a,c);return[m(d)+1e-4*Math.random(),n(e)+1e-4*Math.random(),b,c,a]}).filter(function(a,b){return x(a[4],b)})}));if(0==a.length)return!1;a.length<3&&(a.push([m.range()[0]-20,n.range()[0]-20,null,null]),a.push([m.range()[1]+20,n.range()[1]+20,null,null]),a.push([m.range()[0]-20,n.range()[0]+20,null,null]),a.push([m.range()[1]+20,n.range()[1]-20,null,null]));var c=d3.geom.polygon([[-10,-10],[-10,i+10],[h+10,i+10],[h+10,-10]]),d=d3.geom.voronoi(a).map(function(b,d){return{data:c.clip(b),series:a[d][2],point:a[d][3]}});U.select(".nv-point-paths").selectAll("path").remove();var e=U.select(".nv-point-paths").selectAll("path").data(d),f=e.enter().append("svg:path").attr("d",function(a){return a&&a.data&&0!==a.data.length?"M"+a.data.join(",")+"Z":"M 0 0"}).attr("id",function(a,b){return"nv-path-"+b}).attr("clip-path",function(a,b){return"url(#nv-clip-"+b+")"});C&&f.style("fill",d3.rgb(230,230,230)).style("fill-opacity",.4).style("stroke-opacity",1).style("stroke",d3.rgb(200,200,200)),B&&(U.select(".nv-point-clips").selectAll("clipPath").remove(),U.select(".nv-point-clips").selectAll("clipPath").data(a).enter().append("svg:clipPath").attr("id",function(a,b){return"nv-clip-"+b}).append("svg:circle").attr("cx",function(a){return a[0]}).attr("cy",function(a){return a[1]}).attr("r",D));var k=function(a,c){if(O)return 0;var d=b[a.series];if(void 0!==d){var e=d.values[a.point];e.color=j(d,a.series),e.x=p(e),e.y=q(e);var f=l.node().getBoundingClientRect(),h=window.pageYOffset||document.documentElement.scrollTop,i=window.pageXOffset||document.documentElement.scrollLeft,k={left:m(p(e,a.point))+f.left+i+g.left+10,top:n(q(e,a.point))+f.top+h+g.top+10};c({point:e,series:d,pos:k,seriesIndex:a.series,pointIndex:a.point})}};e.on("click",function(a){k(a,L.elementClick)}).on("dblclick",function(a){k(a,L.elementDblClick)}).on("mouseover",function(a){k(a,L.elementMouseover)}).on("mouseout",function(a){k(a,L.elementMouseout)})}else U.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("dblclick",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementDblClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("mouseover",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseover({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c,color:j(a,c)})}).on("mouseout",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseout({point:e,series:d,seriesIndex:a.series,pointIndex:c,color:j(a,c)})})}l=d3.select(this);var R=a.utils.availableWidth(h,l,g),S=a.utils.availableHeight(i,l,g);a.utils.initSVG(l),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var T=E&&F&&I?[]:d3.merge(b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),size:r(a,b)}})}));m.domain(E||d3.extent(T.map(function(a){return a.x}).concat(t))),m.range(y&&b[0]?G||[(R*z+R)/(2*b[0].values.length),R-R*(1+z)/(2*b[0].values.length)]:G||[0,R]),n.domain(F||d3.extent(T.map(function(a){return a.y}).concat(u))).range(H||[S,0]),o.domain(I||d3.extent(T.map(function(a){return a.size}).concat(v))).range(J||Q),K=m.domain()[0]===m.domain()[1]||n.domain()[0]===n.domain()[1],m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]-.01*n.domain()[0],n.domain()[1]+.01*n.domain()[1]]:[-1,1]),isNaN(m.domain()[0])&&m.domain([-1,1]),isNaN(n.domain()[0])&&n.domain([-1,1]),c=c||m,d=d||n,e=e||o;var U=l.selectAll("g.nv-wrap.nv-scatter").data([b]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+k),W=V.append("defs"),X=V.append("g"),Y=U.select("g");U.classed("nv-single-point",K),X.append("g").attr("class","nv-groups"),X.append("g").attr("class","nv-point-paths"),V.append("g").attr("class","nv-point-clips"),U.attr("transform","translate("+g.left+","+g.top+")"),W.append("clipPath").attr("id","nv-edge-clip-"+k).append("rect"),U.select("#nv-edge-clip-"+k+" rect").attr("width",R).attr("height",S>0?S:0),Y.attr("clip-path",A?"url(#nv-edge-clip-"+k+")":""),O=!0;var Z=U.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});Z.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),Z.exit().remove(),Z.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),Z.watchTransition(P,"scatter: groups").style("fill",function(a,b){return j(a,b)}).style("stroke",function(a,b){return j(a,b)}).style("stroke-opacity",1).style("fill-opacity",.5);var $=Z.selectAll("path.nv-point").data(function(a){return a.values.map(function(a,b){return[a,b]}).filter(function(a,b){return x(a[0],b)})});$.enter().append("path").style("fill",function(a){return a.color}).style("stroke",function(a){return a.color}).attr("transform",function(a){return"translate("+c(p(a[0],a[1]))+","+d(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),$.exit().remove(),Z.exit().selectAll("path.nv-point").watchTransition(P,"scatter exit").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).remove(),$.each(function(a){d3.select(this).classed("nv-point",!0).classed("nv-point-"+a[1],!0).classed("nv-noninteractive",!w).classed("hover",!1)}),$.watchTransition(P,"scatter points").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),clearTimeout(f),f=setTimeout(N,300),c=m.copy(),d=n.copy(),e=o.copy()}),P.renderEnd("scatter immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=a.utils.defaultColor(),k=Math.floor(1e5*Math.random()),l=null,m=d3.scale.linear(),n=d3.scale.linear(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=function(a){return a.size||1},s=function(a){return a.shape||"circle"},t=[],u=[],v=[],w=!0,x=function(a){return!a.notActive},y=!1,z=.1,A=!1,B=!0,C=!1,D=function(){return 25},E=null,F=null,G=null,H=null,I=null,J=null,K=!1,L=d3.dispatch("elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),M=!0,N=250,O=!1,P=a.utils.renderWatch(L,N),Q=[16,256];return b.dispatch=L,b.options=a.utils.optionsFunc.bind(b),b._calls=new function(){this.clearHighlights=function(){return a.dom.write(function(){l.selectAll(".nv-point.hover").classed("hover",!1)}),null},this.highlightPoint=function(b,c,d){a.dom.write(function(){l.select(" .nv-series-"+b+" .nv-point-"+c).classed("hover",d)})}},L.on("elementMouseover.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!0)}),L.on("elementMouseout.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!1)}),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},pointScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return E},set:function(a){E=a}},yDomain:{get:function(){return F},set:function(a){F=a}},pointDomain:{get:function(){return I},set:function(a){I=a}},xRange:{get:function(){return G},set:function(a){G=a}},yRange:{get:function(){return H},set:function(a){H=a}},pointRange:{get:function(){return J},set:function(a){J=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},forcePoint:{get:function(){return v},set:function(a){v=a}},interactive:{get:function(){return w},set:function(a){w=a}},pointActive:{get:function(){return x},set:function(a){x=a}},padDataOuter:{get:function(){return z},set:function(a){z=a}},padData:{get:function(){return y},set:function(a){y=a}},clipEdge:{get:function(){return A},set:function(a){A=a}},clipVoronoi:{get:function(){return B},set:function(a){B=a}},clipRadius:{get:function(){return D},set:function(a){D=a}},showVoronoi:{get:function(){return C},set:function(a){C=a}},id:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return p},set:function(a){p=d3.functor(a)}},y:{get:function(){return q},set:function(a){q=d3.functor(a)}},pointSize:{get:function(){return r},set:function(a){r=d3.functor(a)}},pointShape:{get:function(){return s},set:function(a){s=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},duration:{get:function(){return N},set:function(a){N=a,P.reset(N)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},useVoronoi:{get:function(){return M},set:function(a){M=a,M===!1&&(B=!1)}}}),a.utils.initOptions(b),b},a.models.scatterChart=function(){"use strict";function b(z){return D.reset(),D.models(c),t&&D.models(d),u&&D.models(e),q&&D.models(g),r&&D.models(h),z.each(function(z){m=d3.select(this),a.utils.initSVG(m);var G=a.utils.availableWidth(k,m,j),H=a.utils.availableHeight(l,m,j);if(b.update=function(){0===A?m.call(b):m.transition().duration(A).call(b)},b.container=this,w.setter(F(z),b.update).getter(E(z)).update(),w.disabled=z.map(function(a){return!!a.disabled}),!x){var I;x={};for(I in w)x[I]=w[I]instanceof Array?w[I].slice(0):w[I]}if(!(z&&z.length&&z.filter(function(a){return a.values.length}).length))return a.utils.noData(b,m),D.renderEnd("scatter immediate"),b;m.selectAll(".nv-noData").remove(),o=c.xScale(),p=c.yScale();var J=m.selectAll("g.nv-wrap.nv-scatterChart").data([z]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+c.id()),L=K.append("g"),M=J.select("g");if(L.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),L.append("g").attr("class","nv-x nv-axis"),L.append("g").attr("class","nv-y nv-axis"),L.append("g").attr("class","nv-scatterWrap"),L.append("g").attr("class","nv-regressionLinesWrap"),L.append("g").attr("class","nv-distWrap"),L.append("g").attr("class","nv-legendWrap"),v&&M.select(".nv-y.nv-axis").attr("transform","translate("+G+",0)"),s){var N=G;f.width(N),J.select(".nv-legendWrap").datum(z).call(f),j.top!=f.height()&&(j.top=f.height(),H=a.utils.availableHeight(l,m,j)),J.select(".nv-legendWrap").attr("transform","translate(0,"+-j.top+")")}J.attr("transform","translate("+j.left+","+j.top+")"),c.width(G).height(H).color(z.map(function(a,b){return a.color=a.color||n(a,b),a.color}).filter(function(a,b){return!z[b].disabled})),J.select(".nv-scatterWrap").datum(z.filter(function(a){return!a.disabled})).call(c),J.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+c.id()+")");var O=J.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(a){return a});O.enter().append("g").attr("class","nv-regLines");var P=O.selectAll(".nv-regLine").data(function(a){return[a]});P.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0),P.filter(function(a){return a.intercept&&a.slope}).watchTransition(D,"scatterPlusLineChart: regline").attr("x1",o.range()[0]).attr("x2",o.range()[1]).attr("y1",function(a){return p(o.domain()[0]*a.slope+a.intercept)}).attr("y2",function(a){return p(o.domain()[1]*a.slope+a.intercept)}).style("stroke",function(a,b,c){return n(a,c)}).style("stroke-opacity",function(a){return a.disabled||"undefined"==typeof a.slope||"undefined"==typeof a.intercept?0:1}),t&&(d.scale(o)._ticks(a.utils.calcTicksX(G/100,z)).tickSize(-H,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(d)),u&&(e.scale(p)._ticks(a.utils.calcTicksY(H/36,z)).tickSize(-G,0),M.select(".nv-y.nv-axis").call(e)),q&&(g.getData(c.x()).scale(o).width(G).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),M.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(z.filter(function(a){return!a.disabled})).call(g)),r&&(h.getData(c.y()).scale(p).width(H).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),M.select(".nv-distributionY").attr("transform","translate("+(v?G:-h.size())+",0)").datum(z.filter(function(a){return!a.disabled})).call(h)),f.dispatch.on("stateChange",function(a){for(var c in a)w[c]=a[c];y.stateChange(w),b.update()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&(z.forEach(function(b,c){b.disabled=a.disabled[c]}),w.disabled=a.disabled),b.update()}),c.dispatch.on("elementMouseout.tooltip",function(a){i.hidden(!0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",h.size())}),c.dispatch.on("elementMouseover.tooltip",function(a){m.select(".nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",a.pos.top-H-j.top),m.select(".nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",a.pos.left+g.size()-j.left),i.position(a.pos).data(a).hidden(!1)}),B=o.copy(),C=p.copy()}),D.renderEnd("scatter with line immediate"),b}var c=a.models.scatter(),d=a.models.axis(),e=a.models.axis(),f=a.models.legend(),g=a.models.distribution(),h=a.models.distribution(),i=a.models.tooltip(),j={top:30,right:20,bottom:50,left:75},k=null,l=null,m=null,n=a.utils.defaultColor(),o=c.xScale(),p=c.yScale(),q=!1,r=!1,s=!0,t=!0,u=!0,v=!1,w=a.utils.state(),x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=null,A=250;c.xScale(o).yScale(p),d.orient("bottom").tickPadding(10),e.orient(v?"right":"left").tickPadding(10),g.axis("x"),h.axis("y"),i.headerFormatter(function(a,b){return d.tickFormat()(a,b)}).valueFormatter(function(a,b){return e.tickFormat()(a,b)});var B,C,D=a.utils.renderWatch(y,A),E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return b.dispatch=y,b.scatter=c,b.legend=f,b.xAxis=d,b.yAxis=e,b.distX=g,b.distY=h,b.tooltip=i,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},container:{get:function(){return m},set:function(a){m=a}},showDistX:{get:function(){return q},set:function(a){q=a}},showDistY:{get:function(){return r},set:function(a){r=a}},showLegend:{get:function(){return s},set:function(a){s=a}},showXAxis:{get:function(){return t},set:function(a){t=a}},showYAxis:{get:function(){return u},set:function(a){u=a}},defaultState:{get:function(){return x},set:function(a){x=a}},noData:{get:function(){return z},set:function(a){z=a}},duration:{get:function(){return A},set:function(a){A=a}},tooltips:{get:function(){return i.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),i.enabled(!!b) +}},tooltipContent:{get:function(){return i.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),i.contentGenerator(b)}},tooltipXContent:{get:function(){return i.contentGenerator()},set:function(){a.deprecated("tooltipContent","This option is removed, put values into main tooltip.")}},tooltipYContent:{get:function(){return i.contentGenerator()},set:function(){a.deprecated("tooltipContent","This option is removed, put values into main tooltip.")}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},rightAlignYAxis:{get:function(){return v},set:function(a){v=a,e.orient(a?"right":"left")}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),f.color(n),g.color(n),h.color(n)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.sparkline=function(){"use strict";function b(k){return k.each(function(b){var k=h-g.left-g.right,q=i-g.top-g.bottom;j=d3.select(this),a.utils.initSVG(j),l.domain(c||d3.extent(b,n)).range(e||[0,k]),m.domain(d||d3.extent(b,o)).range(f||[q,0]);{var r=j.selectAll("g.nv-wrap.nv-sparkline").data([b]),s=r.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline");s.append("g"),r.select("g")}r.attr("transform","translate("+g.left+","+g.top+")");var t=r.selectAll("path").data(function(a){return[a]});t.enter().append("path"),t.exit().remove(),t.style("stroke",function(a,b){return a.color||p(a,b)}).attr("d",d3.svg.line().x(function(a,b){return l(n(a,b))}).y(function(a,b){return m(o(a,b))}));var u=r.selectAll("circle.nv-point").data(function(a){function b(b){if(-1!=b){var c=a[b];return c.pointIndex=b,c}return null}var c=a.map(function(a,b){return o(a,b)}),d=b(c.lastIndexOf(m.domain()[1])),e=b(c.indexOf(m.domain()[0])),f=b(c.length-1);return[e,d,f].filter(function(a){return null!=a})});u.enter().append("circle"),u.exit().remove(),u.attr("cx",function(a){return l(n(a,a.pointIndex))}).attr("cy",function(a){return m(o(a,a.pointIndex))}).attr("r",2).attr("class",function(a){return n(a,a.pointIndex)==l.domain()[1]?"nv-point nv-currentValue":o(a,a.pointIndex)==m.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),b}var c,d,e,f,g={top:2,right:0,bottom:2,left:0},h=400,i=32,j=null,k=!0,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=a.utils.getColor(["#000"]);return b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},animate:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return n},set:function(a){n=d3.functor(a)}},y:{get:function(){return o},set:function(a){o=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return p},set:function(b){p=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sparklinePlus=function(){"use strict";function b(p){return p.each(function(p){function q(){if(!j){var a=z.selectAll(".nv-hoverValue").data(i),b=a.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);a.exit().transition().duration(250).style("stroke-opacity",0).style("fill-opacity",0).remove(),a.attr("transform",function(a){return"translate("+c(e.x()(p[a],a))+",0)"}).transition().duration(250).style("stroke-opacity",1).style("fill-opacity",1),i.length&&(b.append("line").attr("x1",0).attr("y1",-f.top).attr("x2",0).attr("y2",u),b.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-f.top).attr("text-anchor","end").attr("dy",".9em"),z.select(".nv-hoverValue .nv-xValue").text(k(e.x()(p[i[0]],i[0]))),b.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-f.top).attr("text-anchor","start").attr("dy",".9em"),z.select(".nv-hoverValue .nv-yValue").text(l(e.y()(p[i[0]],i[0]))))}}function r(){function a(a,b){for(var c=Math.abs(e.x()(a[0],0)-b),d=0,f=0;fc;++c){for(b=0,d=0;bb;b++)a[b][c][1]/=d;else for(b=0;e>b;b++)a[b][c][1]=0}for(c=0;f>c;++c)g[c]=0;return g}}),u.renderEnd("stackedArea immediate"),b}var c,d,e={top:0,right:0,bottom:0,left:0},f=960,g=500,h=a.utils.defaultColor(),i=Math.floor(1e5*Math.random()),j=null,k=function(a){return a.x},l=function(a){return a.y},m="stack",n="zero",o="default",p="linear",q=!1,r=a.models.scatter(),s=250,t=d3.dispatch("areaClick","areaMouseover","areaMouseout","renderEnd","elementClick","elementMouseover","elementMouseout");r.pointSize(2.2).pointDomain([2.2,2.2]);var u=a.utils.renderWatch(t,s);return b.dispatch=t,b.scatter=r,r.dispatch.on("elementClick",function(){t.elementClick.apply(this,arguments)}),r.dispatch.on("elementMouseover",function(){t.elementMouseover.apply(this,arguments)}),r.dispatch.on("elementMouseout",function(){t.elementMouseout.apply(this,arguments)}),b.interpolate=function(a){return arguments.length?(p=a,b):p},b.duration=function(a){return arguments.length?(s=a,u.reset(s),r.duration(s),b):s},b.dispatch=t,b.scatter=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return f},set:function(a){f=a}},height:{get:function(){return g},set:function(a){g=a}},clipEdge:{get:function(){return q},set:function(a){q=a}},offset:{get:function(){return n},set:function(a){n=a}},order:{get:function(){return o},set:function(a){o=a}},interpolate:{get:function(){return p},set:function(a){p=a}},x:{get:function(){return k},set:function(a){k=d3.functor(a)}},y:{get:function(){return l},set:function(a){l=d3.functor(a)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return h},set:function(b){h=a.utils.getColor(b)}},style:{get:function(){return m},set:function(a){switch(m=a){case"stack":b.offset("zero"),b.order("default");break;case"stream":b.offset("wiggle"),b.order("inside-out");break;case"stream-center":b.offset("silhouette"),b.order("inside-out");break;case"expand":b.offset("expand"),b.order("default");break;case"stack_percent":b.offset(b.d3_stackedOffset_stackPercent),b.order("default")}}},duration:{get:function(){return s},set:function(a){s=a,u.reset(s),r.duration(s)}}}),a.utils.inheritOptions(b,r),a.utils.initOptions(b),b},a.models.stackedAreaChart=function(){"use strict";function b(k){return F.reset(),F.models(e),r&&F.models(f),s&&F.models(g),k.each(function(k){var x=d3.select(this),F=this;a.utils.initSVG(x);var K=a.utils.availableWidth(m,x,l),L=a.utils.availableHeight(n,x,l);if(b.update=function(){x.transition().duration(C).call(b)},b.container=this,v.setter(I(k),b.update).getter(H(k)).update(),v.disabled=k.map(function(a){return!!a.disabled}),!w){var M;w={};for(M in v)w[M]=v[M]instanceof Array?v[M].slice(0):v[M]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(b,x),b;x.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var N=x.selectAll("g.nv-wrap.nv-stackedAreaChart").data([k]),O=N.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),P=N.select("g");if(O.append("rect").style("opacity",0),O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-stackedWrap"),O.append("g").attr("class","nv-legendWrap"),O.append("g").attr("class","nv-controlsWrap"),O.append("g").attr("class","nv-interactive"),P.select("rect").attr("width",K).attr("height",L),q){var Q=p?K-z:K;h.width(Q),P.select(".nv-legendWrap").datum(k).call(h),l.top!=h.height()&&(l.top=h.height(),L=a.utils.availableHeight(n,x,l)),P.select(".nv-legendWrap").attr("transform","translate("+(K-Q)+","+-l.top+")")}if(p){var R=[{key:B.stacked||"Stacked",metaKey:"Stacked",disabled:"stack"!=e.style(),style:"stack"},{key:B.stream||"Stream",metaKey:"Stream",disabled:"stream"!=e.style(),style:"stream"},{key:B.expanded||"Expanded",metaKey:"Expanded",disabled:"expand"!=e.style(),style:"expand"},{key:B.stack_percent||"Stack %",metaKey:"Stack_Percent",disabled:"stack_percent"!=e.style(),style:"stack_percent"}];z=A.length/3*260,R=R.filter(function(a){return-1!==A.indexOf(a.metaKey)}),i.width(z).color(["#444","#444","#444"]),P.select(".nv-controlsWrap").datum(R).call(i),l.top!=Math.max(i.height(),h.height())&&(l.top=Math.max(i.height(),h.height()),L=a.utils.availableHeight(n,x,l)),P.select(".nv-controlsWrap").attr("transform","translate(0,"+-l.top+")")}N.attr("transform","translate("+l.left+","+l.top+")"),t&&P.select(".nv-y.nv-axis").attr("transform","translate("+K+",0)"),u&&(j.width(K).height(L).margin({left:l.left,top:l.top}).svgContainer(x).xScale(c),N.select(".nv-interactive").call(j)),e.width(K).height(L);var S=P.select(".nv-stackedWrap").datum(k);if(S.transition().call(e),r&&(f.scale(c)._ticks(a.utils.calcTicksX(K/100,k)).tickSize(-L,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+L+")"),P.select(".nv-x.nv-axis").transition().duration(0).call(f)),s){var T;if(T="wiggle"===e.offset()?0:a.utils.calcTicksY(L/36,k),g.scale(d)._ticks(T).tickSize(-K,0),"expand"===e.style()||"stack_percent"===e.style()){var U=g.tickFormat();D&&U===J||(D=U),g.tickFormat(J)}else D&&(g.tickFormat(D),D=null);P.select(".nv-y.nv-axis").transition().duration(0).call(g)}e.dispatch.on("areaClick.toggle",function(a){k.forEach(1===k.filter(function(a){return!a.disabled}).length?function(a){a.disabled=!1}:function(b,c){b.disabled=c!=a.seriesIndex}),v.disabled=k.map(function(a){return!!a.disabled}),y.stateChange(v),b.update()}),h.dispatch.on("stateChange",function(a){for(var c in a)v[c]=a[c];y.stateChange(v),b.update()}),i.dispatch.on("legendClick",function(a){a.disabled&&(R=R.map(function(a){return a.disabled=!0,a}),a.disabled=!1,e.style(a.style),v.style=e.style(),y.stateChange(v),b.update())}),j.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,g,h,i=[];if(k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,j){g=a.interactiveBisect(f.values,c.pointXValue,b.x());var k=f.values[g],l=b.y()(k,g);if(null!=l&&e.highlightPoint(j,g,!0),"undefined"!=typeof k){"undefined"==typeof d&&(d=k),"undefined"==typeof h&&(h=b.xScale()(b.x()(k,g)));var m="expand"==e.style()?k.display.y:b.y()(k,g);i.push({key:f.key,value:m,color:o(f,f.seriesIndex),stackedValue:k.display})}}),i.reverse(),i.length>2){var m=b.yScale().invert(c.mouseY),n=null;i.forEach(function(a,b){m=Math.abs(m);var c=Math.abs(a.stackedValue.y0),d=Math.abs(a.stackedValue.y);return m>=c&&d+c>=m?void(n=b):void 0}),null!=n&&(i[n].highlight=!0)}var p=f.tickFormat()(b.x()(d,g)),q=j.tooltip.valueFormatter();"expand"===e.style()||"stack_percent"===e.style()?(E||(E=q),q=d3.format(".1%")):E&&(q=E,E=null),j.tooltip.position({left:h+l.left,top:c.mouseY+l.top}).chartContainer(F.parentNode).valueFormatter(q).data({value:p,series:i})(),j.renderGuideLine(h)}),j.dispatch.on("elementMouseout",function(){e.clearHighlights()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&k.length===a.disabled.length&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),v.disabled=a.disabled),"undefined"!=typeof a.style&&(e.style(a.style),G=a.style),b.update()})}),F.renderEnd("stacked Area chart immediate"),b}var c,d,e=a.models.stackedArea(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:25,bottom:50,left:60},m=null,n=null,o=a.utils.defaultColor(),p=!0,q=!0,r=!0,s=!0,t=!1,u=!1,v=a.utils.state(),w=null,x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=250,A=["Stacked","Stream","Expanded"],B={},C=250;v.style=e.style(),f.orient("bottom").tickPadding(7),g.orient(t?"right":"left"),k.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)}),j.tooltip.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)});var D=null,E=null;i.updateState(!1);var F=a.utils.renderWatch(y),G=e.style(),H=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),style:e.style()}}},I=function(a){return function(b){void 0!==b.style&&(G=b.style),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},J=d3.format("%");return e.dispatch.on("elementMouseover.tooltip",function(a){a.point.x=e.x()(a.point),a.point.y=e.y()(a.point),k.data(a).position(a.pos).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){k.hidden(!0)}),b.dispatch=y,b.stacked=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.interactiveLayer=j,b.tooltip=k,b.dispatch=y,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return w},set:function(a){w=a}},noData:{get:function(){return x},set:function(a){x=a}},showControls:{get:function(){return p},set:function(a){p=a}},controlLabels:{get:function(){return B},set:function(a){B=a}},controlOptions:{get:function(){return A},set:function(a){A=a}},tooltips:{get:function(){return k.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),k.enabled(!!b)}},tooltipContent:{get:function(){return k.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),k.contentGenerator(b)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},duration:{get:function(){return C},set:function(a){C=a,F.reset(C),e.duration(C),f.duration(C),g.duration(C)}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b),h.color(o),e.color(o)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},useInteractiveGuideline:{get:function(){return u},set:function(a){u=!!a,b.interactive(!a),b.useVoronoi(!a),e.scatter.interactive(!a)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.sunburst=function(){"use strict";function b(u){return t.reset(),u.each(function(b){function t(a){a.x0=a.x,a.dx0=a.dx}function u(a){var b=d3.interpolate(p.domain(),[a.x,a.x+a.dx]),c=d3.interpolate(q.domain(),[a.y,1]),d=d3.interpolate(q.range(),[a.y?20:0,y]);return function(a,e){return e?function(){return s(a)}:function(e){return p.domain(b(e)),q.domain(c(e)).range(d(e)),s(a)}}}l=d3.select(this);var v,w=a.utils.availableWidth(g,l,f),x=a.utils.availableHeight(h,l,f),y=Math.min(w,x)/2;a.utils.initSVG(l);var z=l.selectAll(".nv-wrap.nv-sunburst").data(b),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburst nv-chart-"+k),B=A.selectAll("nv-sunburst");z.attr("transform","translate("+w/2+","+x/2+")"),l.on("click",function(a,b){o.chartClick({data:a,index:b,pos:d3.event,id:k})}),q.range([0,y]),c=c||b,e=b[0],r.value(j[i]||j.count),v=B.data(r.nodes).enter().append("path").attr("d",s).style("fill",function(a){return m((a.children?a:a.parent).name)}).style("stroke","#FFF").on("click",function(a){d!==c&&c!==a&&(d=c),c=a,v.transition().duration(n).attrTween("d",u(a))}).each(t).on("dblclick",function(a){d.parent==a&&v.transition().duration(n).attrTween("d",u(e))}).each(t).on("mouseover",function(a){d3.select(this).classed("hover",!0).style("opacity",.8),o.elementMouseover({data:a,color:d3.select(this).style("fill")})}).on("mouseout",function(a){d3.select(this).classed("hover",!1).style("opacity",1),o.elementMouseout({data:a})}).on("mousemove",function(a){o.elementMousemove({data:a})})}),t.renderEnd("sunburst immediate"),b}var c,d,e,f={top:0,right:0,bottom:0,left:0},g=null,h=null,i="count",j={count:function(){return 1},size:function(a){return a.size}},k=Math.floor(1e4*Math.random()),l=null,m=a.utils.defaultColor(),n=500,o=d3.dispatch("chartClick","elementClick","elementDblClick","elementMousemove","elementMouseover","elementMouseout","renderEnd"),p=d3.scale.linear().range([0,2*Math.PI]),q=d3.scale.sqrt(),r=d3.layout.partition().sort(null).value(function(){return 1}),s=d3.svg.arc().startAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x)))}).endAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x+a.dx)))}).innerRadius(function(a){return Math.max(0,q(a.y))}).outerRadius(function(a){return Math.max(0,q(a.y+a.dy))}),t=a.utils.renderWatch(o);return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},mode:{get:function(){return i},set:function(a){i=a}},id:{get:function(){return k},set:function(a){k=a}},duration:{get:function(){return n},set:function(a){n=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!=a.top?a.top:f.top,f.right=void 0!=a.right?a.right:f.right,f.bottom=void 0!=a.bottom?a.bottom:f.bottom,f.left=void 0!=a.left?a.left:f.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sunburstChart=function(){"use strict";function b(d){return m.reset(),m.models(c),d.each(function(d){var h=d3.select(this);a.utils.initSVG(h);var i=a.utils.availableWidth(f,h,e),j=a.utils.availableHeight(g,h,e);if(b.update=function(){0===k?h.call(b):h.transition().duration(k).call(b)},b.container=this,!d||!d.length)return a.utils.noData(b,h),b;h.selectAll(".nv-noData").remove();var l=h.selectAll("g.nv-wrap.nv-sunburstChart").data(d),m=l.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburstChart").append("g"),n=l.select("g");m.append("g").attr("class","nv-sunburstWrap"),l.attr("transform","translate("+e.left+","+e.top+")"),c.width(i).height(j);var o=n.select(".nv-sunburstWrap").datum(d);d3.transition(o).call(c)}),m.renderEnd("sunburstChart immediate"),b}var c=a.models.sunburst(),d=a.models.tooltip(),e={top:30,right:20,bottom:20,left:20},f=null,g=null,h=a.utils.defaultColor(),i=(Math.round(1e5*Math.random()),null),j=null,k=250,l=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),m=a.utils.renderWatch(l);return d.headerEnabled(!1).duration(0).valueFormatter(function(a){return a}),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.data.name,value:a.data.size,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){d.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=l,b.sunburst=c,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return i},set:function(a){i=a}},color:{get:function(){return h},set:function(a){h=a,c.color(h)}},duration:{get:function(){return k},set:function(a){k=a,m.reset(k),c.duration(k)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.version="1.8.1"}(); \ No newline at end of file diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/popper.min.js b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/popper.min.js new file mode 100644 index 00000000..bb1aaae3 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/popper.min.js @@ -0,0 +1,5 @@ +/* + Copyright (C) Federico Zivolo 2020 + Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT). + */(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?module.exports=t():'function'==typeof define&&define.amd?define(t):e.Popper=t()})(this,function(){'use strict';function e(e){return e&&'[object Function]'==={}.toString.call(e)}function t(e,t){if(1!==e.nodeType)return[];var o=e.ownerDocument.defaultView,n=o.getComputedStyle(e,null);return t?n[t]:n}function o(e){return'HTML'===e.nodeName?e:e.parentNode||e.host}function n(e){if(!e)return document.body;switch(e.nodeName){case'HTML':case'BODY':return e.ownerDocument.body;case'#document':return e.body;}var i=t(e),r=i.overflow,p=i.overflowX,s=i.overflowY;return /(auto|scroll|overlay)/.test(r+s+p)?e:n(o(e))}function i(e){return e&&e.referenceNode?e.referenceNode:e}function r(e){return 11===e?re:10===e?pe:re||pe}function p(e){if(!e)return document.documentElement;for(var o=r(10)?document.body:null,n=e.offsetParent||null;n===o&&e.nextElementSibling;)n=(e=e.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&'BODY'!==i&&'HTML'!==i?-1!==['TH','TD','TABLE'].indexOf(n.nodeName)&&'static'===t(n,'position')?p(n):n:e?e.ownerDocument.documentElement:document.documentElement}function s(e){var t=e.nodeName;return'BODY'!==t&&('HTML'===t||p(e.firstElementChild)===e)}function d(e){return null===e.parentNode?e:d(e.parentNode)}function a(e,t){if(!e||!e.nodeType||!t||!t.nodeType)return document.documentElement;var o=e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_FOLLOWING,n=o?e:t,i=o?t:e,r=document.createRange();r.setStart(n,0),r.setEnd(i,0);var l=r.commonAncestorContainer;if(e!==l&&t!==l||n.contains(i))return s(l)?l:p(l);var f=d(e);return f.host?a(f.host,t):a(e,d(t).host)}function l(e){var t=1=o.clientWidth&&n>=o.clientHeight}),l=0a[e]&&!t.escapeWithReference&&(n=Q(f[o],a[e]-('right'===e?f.width:f.height))),ae({},o,n)}};return l.forEach(function(e){var t=-1===['left','top'].indexOf(e)?'secondary':'primary';f=le({},f,m[t](e))}),e.offsets.popper=f,e},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,o=t.popper,n=t.reference,i=e.placement.split('-')[0],r=Z,p=-1!==['top','bottom'].indexOf(i),s=p?'right':'bottom',d=p?'left':'top',a=p?'width':'height';return o[s]r(n[s])&&(e.offsets.popper[d]=r(n[s])),e}},arrow:{order:500,enabled:!0,fn:function(e,o){var n;if(!K(e.instance.modifiers,'arrow','keepTogether'))return e;var i=o.element;if('string'==typeof i){if(i=e.instance.popper.querySelector(i),!i)return e;}else if(!e.instance.popper.contains(i))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),e;var r=e.placement.split('-')[0],p=e.offsets,s=p.popper,d=p.reference,a=-1!==['left','right'].indexOf(r),l=a?'height':'width',f=a?'Top':'Left',m=f.toLowerCase(),h=a?'left':'top',c=a?'bottom':'right',u=S(i)[l];d[c]-us[c]&&(e.offsets.popper[m]+=d[m]+u-s[c]),e.offsets.popper=g(e.offsets.popper);var b=d[m]+d[l]/2-u/2,w=t(e.instance.popper),y=parseFloat(w['margin'+f]),E=parseFloat(w['border'+f+'Width']),v=b-e.offsets.popper[m]-y-E;return v=ee(Q(s[l]-u,v),0),e.arrowElement=i,e.offsets.arrow=(n={},ae(n,m,$(v)),ae(n,h,''),n),e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=v(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement,e.positionFixed),n=e.placement.split('-')[0],i=T(n),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case ce.FLIP:p=[n,i];break;case ce.CLOCKWISE:p=G(n);break;case ce.COUNTERCLOCKWISE:p=G(n,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(n!==s||p.length===d+1)return e;n=e.placement.split('-')[0],i=T(n);var a=e.offsets.popper,l=e.offsets.reference,f=Z,m='left'===n&&f(a.right)>f(l.left)||'right'===n&&f(a.left)f(l.top)||'bottom'===n&&f(a.top)f(o.right),g=f(a.top)f(o.bottom),b='left'===n&&h||'right'===n&&c||'top'===n&&g||'bottom'===n&&u,w=-1!==['top','bottom'].indexOf(n),y=!!t.flipVariations&&(w&&'start'===r&&h||w&&'end'===r&&c||!w&&'start'===r&&g||!w&&'end'===r&&u),E=!!t.flipVariationsByContent&&(w&&'start'===r&&c||w&&'end'===r&&h||!w&&'start'===r&&u||!w&&'end'===r&&g),v=y||E;(m||b||v)&&(e.flipped=!0,(m||b)&&(n=p[d+1]),v&&(r=z(r)),e.placement=n+(r?'-'+r:''),e.offsets.popper=le({},e.offsets.popper,C(e.instance.popper,e.offsets.reference,e.placement)),e=P(e.instance.modifiers,e,'flip'))}),e},behavior:'flip',padding:5,boundariesElement:'viewport',flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,o=t.split('-')[0],n=e.offsets,i=n.popper,r=n.reference,p=-1!==['left','right'].indexOf(o),s=-1===['top','left'].indexOf(o);return i[p?'left':'top']=r[o]-(s?i[p?'width':'height']:0),e.placement=T(t),e.offsets.popper=g(i),e}},hide:{order:800,enabled:!0,fn:function(e){if(!K(e.instance.modifiers,'hide','preventOverflow'))return e;var t=e.offsets.reference,o=D(e.instance.modifiers,function(e){return'preventOverflow'===e.name}).boundaries;if(t.bottomo.right||t.top>o.bottom||t.rightwindow.devicePixelRatio||!fe),c='bottom'===o?'top':'bottom',g='right'===n?'left':'right',b=B('transform');if(d='bottom'==c?'HTML'===l.nodeName?-l.clientHeight+h.bottom:-f.height+h.bottom:h.top,s='right'==g?'HTML'===l.nodeName?-l.clientWidth+h.right:-f.width+h.right:h.left,a&&b)m[b]='translate3d('+s+'px, '+d+'px, 0)',m[c]=0,m[g]=0,m.willChange='transform';else{var w='bottom'==c?-1:1,y='right'==g?-1:1;m[c]=d*w,m[g]=s*y,m.willChange=c+', '+g}var E={"x-placement":e.placement};return e.attributes=le({},E,e.attributes),e.styles=le({},m,e.styles),e.arrowStyles=le({},e.offsets.arrow,e.arrowStyles),e},gpuAcceleration:!0,x:'bottom',y:'right'},applyStyle:{order:900,enabled:!0,fn:function(e){return V(e.instance.popper,e.styles),j(e.instance.popper,e.attributes),e.arrowElement&&Object.keys(e.arrowStyles).length&&V(e.arrowElement,e.arrowStyles),e},onLoad:function(e,t,o,n,i){var r=L(i,t,e,o.positionFixed),p=O(o.placement,r,t,e,o.modifiers.flip.boundariesElement,o.modifiers.flip.padding);return t.setAttribute('x-placement',p),V(t,{position:o.positionFixed?'fixed':'absolute'}),o},gpuAcceleration:void 0}}},ge}); +//# sourceMappingURL=popper.min.js.map diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/line.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/line.html.dist new file mode 100644 index 00000000..89810d15 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/line.html.dist @@ -0,0 +1 @@ + {{lineNumber}}{{lineContent}} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/lines.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/lines.html.dist new file mode 100644 index 00000000..add40e4e --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/lines.html.dist @@ -0,0 +1,5 @@ + + +{{lines}} + +
    diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item.html.dist new file mode 100644 index 00000000..2311d456 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item.html.dist @@ -0,0 +1,12 @@ + + {{name}} + {{lines_bar}} +
    {{lines_executed_percent}}
    +
    {{lines_number}}
    + {{methods_bar}} +
    {{methods_tested_percent}}
    +
    {{methods_number}}
    + {{crap}} + + + diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item_branch.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item_branch.html.dist new file mode 100644 index 00000000..36d6cb74 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item_branch.html.dist @@ -0,0 +1,18 @@ + + {{name}} + {{lines_bar}} +
    {{lines_executed_percent}}
    +
    {{lines_number}}
    + {{branches_bar}} +
    {{branches_executed_percent}}
    +
    {{branches_number}}
    + {{paths_bar}} +
    {{paths_executed_percent}}
    +
    {{paths_number}}
    + {{methods_bar}} +
    {{methods_tested_percent}}
    +
    {{methods_number}}
    + {{crap}} + + + diff --git a/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/paths.html.dist b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/paths.html.dist new file mode 100644 index 00000000..d14b8ad9 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/paths.html.dist @@ -0,0 +1,9 @@ +
    +

    Paths

    +

    + Below are the source code lines that represent each code path as identified by Xdebug. Please note a path is not + necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once. + Please also be aware that some paths may include implicit rather than explicit branches, e.g. an if statement + always has an else as part of its logical flow even if you didn't write one. +

    +{{paths}} diff --git a/vendor/phpunit/php-code-coverage/src/Report/PHP.php b/vendor/phpunit/php-code-coverage/src/Report/PHP.php new file mode 100644 index 00000000..ccb104ce --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/PHP.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report; + +use function dirname; +use function file_put_contents; +use function serialize; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; +use SebastianBergmann\CodeCoverage\Util\Filesystem; + +final class PHP +{ + public function process(CodeCoverage $coverage, ?string $target = null): string + { + $buffer = " + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report; + +use const PHP_EOL; +use function array_map; +use function date; +use function ksort; +use function max; +use function sprintf; +use function str_pad; +use function strlen; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Node\File; +use SebastianBergmann\CodeCoverage\Util\Percentage; + +final class Text +{ + /** + * @var string + */ + private const COLOR_GREEN = "\x1b[30;42m"; + + /** + * @var string + */ + private const COLOR_YELLOW = "\x1b[30;43m"; + + /** + * @var string + */ + private const COLOR_RED = "\x1b[37;41m"; + + /** + * @var string + */ + private const COLOR_HEADER = "\x1b[1;37;40m"; + + /** + * @var string + */ + private const COLOR_RESET = "\x1b[0m"; + + /** + * @var string + */ + private const COLOR_EOL = "\x1b[2K"; + + /** + * @var int + */ + private $lowUpperBound; + + /** + * @var int + */ + private $highLowerBound; + + /** + * @var bool + */ + private $showUncoveredFiles; + + /** + * @var bool + */ + private $showOnlySummary; + + public function __construct(int $lowUpperBound = 50, int $highLowerBound = 90, bool $showUncoveredFiles = false, bool $showOnlySummary = false) + { + $this->lowUpperBound = $lowUpperBound; + $this->highLowerBound = $highLowerBound; + $this->showUncoveredFiles = $showUncoveredFiles; + $this->showOnlySummary = $showOnlySummary; + } + + public function process(CodeCoverage $coverage, bool $showColors = false): string + { + $hasBranchCoverage = !empty($coverage->getData(true)->functionCoverage()); + + $output = PHP_EOL . PHP_EOL; + $report = $coverage->getReport(); + + $colors = [ + 'header' => '', + 'classes' => '', + 'methods' => '', + 'lines' => '', + 'branches' => '', + 'paths' => '', + 'reset' => '', + 'eol' => '', + ]; + + if ($showColors) { + $colors['classes'] = $this->coverageColor( + $report->numberOfTestedClassesAndTraits(), + $report->numberOfClassesAndTraits() + ); + + $colors['methods'] = $this->coverageColor( + $report->numberOfTestedMethods(), + $report->numberOfMethods() + ); + + $colors['lines'] = $this->coverageColor( + $report->numberOfExecutedLines(), + $report->numberOfExecutableLines() + ); + + $colors['branches'] = $this->coverageColor( + $report->numberOfExecutedBranches(), + $report->numberOfExecutableBranches() + ); + + $colors['paths'] = $this->coverageColor( + $report->numberOfExecutedPaths(), + $report->numberOfExecutablePaths() + ); + + $colors['reset'] = self::COLOR_RESET; + $colors['header'] = self::COLOR_HEADER; + $colors['eol'] = self::COLOR_EOL; + } + + $classes = sprintf( + ' Classes: %6s (%d/%d)', + Percentage::fromFractionAndTotal( + $report->numberOfTestedClassesAndTraits(), + $report->numberOfClassesAndTraits() + )->asString(), + $report->numberOfTestedClassesAndTraits(), + $report->numberOfClassesAndTraits() + ); + + $methods = sprintf( + ' Methods: %6s (%d/%d)', + Percentage::fromFractionAndTotal( + $report->numberOfTestedMethods(), + $report->numberOfMethods(), + )->asString(), + $report->numberOfTestedMethods(), + $report->numberOfMethods() + ); + + $paths = ''; + $branches = ''; + + if ($hasBranchCoverage) { + $paths = sprintf( + ' Paths: %6s (%d/%d)', + Percentage::fromFractionAndTotal( + $report->numberOfExecutedPaths(), + $report->numberOfExecutablePaths(), + )->asString(), + $report->numberOfExecutedPaths(), + $report->numberOfExecutablePaths() + ); + + $branches = sprintf( + ' Branches: %6s (%d/%d)', + Percentage::fromFractionAndTotal( + $report->numberOfExecutedBranches(), + $report->numberOfExecutableBranches(), + )->asString(), + $report->numberOfExecutedBranches(), + $report->numberOfExecutableBranches() + ); + } + + $lines = sprintf( + ' Lines: %6s (%d/%d)', + Percentage::fromFractionAndTotal( + $report->numberOfExecutedLines(), + $report->numberOfExecutableLines(), + )->asString(), + $report->numberOfExecutedLines(), + $report->numberOfExecutableLines() + ); + + $padding = max(array_map('strlen', [$classes, $methods, $lines])); + + if ($this->showOnlySummary) { + $title = 'Code Coverage Report Summary:'; + $padding = max($padding, strlen($title)); + + $output .= $this->format($colors['header'], $padding, $title); + } else { + $date = date(' Y-m-d H:i:s'); + $title = 'Code Coverage Report:'; + + $output .= $this->format($colors['header'], $padding, $title); + $output .= $this->format($colors['header'], $padding, $date); + $output .= $this->format($colors['header'], $padding, ''); + $output .= $this->format($colors['header'], $padding, ' Summary:'); + } + + $output .= $this->format($colors['classes'], $padding, $classes); + $output .= $this->format($colors['methods'], $padding, $methods); + + if ($hasBranchCoverage) { + $output .= $this->format($colors['paths'], $padding, $paths); + $output .= $this->format($colors['branches'], $padding, $branches); + } + $output .= $this->format($colors['lines'], $padding, $lines); + + if ($this->showOnlySummary) { + return $output . PHP_EOL; + } + + $classCoverage = []; + + foreach ($report as $item) { + if (!$item instanceof File) { + continue; + } + + $classes = $item->classesAndTraits(); + + foreach ($classes as $className => $class) { + $classExecutableLines = 0; + $classExecutedLines = 0; + $classExecutableBranches = 0; + $classExecutedBranches = 0; + $classExecutablePaths = 0; + $classExecutedPaths = 0; + $coveredMethods = 0; + $classMethods = 0; + + foreach ($class['methods'] as $method) { + if ($method['executableLines'] == 0) { + continue; + } + + $classMethods++; + $classExecutableLines += $method['executableLines']; + $classExecutedLines += $method['executedLines']; + $classExecutableBranches += $method['executableBranches']; + $classExecutedBranches += $method['executedBranches']; + $classExecutablePaths += $method['executablePaths']; + $classExecutedPaths += $method['executedPaths']; + + if ($method['coverage'] == 100) { + $coveredMethods++; + } + } + + $classCoverage[$className] = [ + 'namespace' => $class['namespace'], + 'className' => $className, + 'methodsCovered' => $coveredMethods, + 'methodCount' => $classMethods, + 'statementsCovered' => $classExecutedLines, + 'statementCount' => $classExecutableLines, + 'branchesCovered' => $classExecutedBranches, + 'branchesCount' => $classExecutableBranches, + 'pathsCovered' => $classExecutedPaths, + 'pathsCount' => $classExecutablePaths, + ]; + } + } + + ksort($classCoverage); + + $methodColor = ''; + $pathsColor = ''; + $branchesColor = ''; + $linesColor = ''; + $resetColor = ''; + + foreach ($classCoverage as $fullQualifiedPath => $classInfo) { + if ($this->showUncoveredFiles || $classInfo['statementsCovered'] != 0) { + if ($showColors) { + $methodColor = $this->coverageColor($classInfo['methodsCovered'], $classInfo['methodCount']); + $pathsColor = $this->coverageColor($classInfo['pathsCovered'], $classInfo['pathsCount']); + $branchesColor = $this->coverageColor($classInfo['branchesCovered'], $classInfo['branchesCount']); + $linesColor = $this->coverageColor($classInfo['statementsCovered'], $classInfo['statementCount']); + $resetColor = $colors['reset']; + } + + $output .= PHP_EOL . $fullQualifiedPath . PHP_EOL + . ' ' . $methodColor . 'Methods: ' . $this->printCoverageCounts($classInfo['methodsCovered'], $classInfo['methodCount'], 2) . $resetColor . ' '; + + if ($hasBranchCoverage) { + $output .= ' ' . $pathsColor . 'Paths: ' . $this->printCoverageCounts($classInfo['pathsCovered'], $classInfo['pathsCount'], 3) . $resetColor . ' ' + . ' ' . $branchesColor . 'Branches: ' . $this->printCoverageCounts($classInfo['branchesCovered'], $classInfo['branchesCount'], 3) . $resetColor . ' '; + } + $output .= ' ' . $linesColor . 'Lines: ' . $this->printCoverageCounts($classInfo['statementsCovered'], $classInfo['statementCount'], 3) . $resetColor; + } + } + + return $output . PHP_EOL; + } + + private function coverageColor(int $numberOfCoveredElements, int $totalNumberOfElements): string + { + $coverage = Percentage::fromFractionAndTotal( + $numberOfCoveredElements, + $totalNumberOfElements + ); + + if ($coverage->asFloat() >= $this->highLowerBound) { + return self::COLOR_GREEN; + } + + if ($coverage->asFloat() > $this->lowUpperBound) { + return self::COLOR_YELLOW; + } + + return self::COLOR_RED; + } + + private function printCoverageCounts(int $numberOfCoveredElements, int $totalNumberOfElements, int $precision): string + { + $format = '%' . $precision . 's'; + + return Percentage::fromFractionAndTotal( + $numberOfCoveredElements, + $totalNumberOfElements + )->asFixedWidthString() . + ' (' . sprintf($format, $numberOfCoveredElements) . '/' . + sprintf($format, $totalNumberOfElements) . ')'; + } + + /** + * @param false|string $string + */ + private function format(string $color, int $padding, $string): string + { + $reset = $color ? self::COLOR_RESET : ''; + + return $color . str_pad((string) $string, $padding) . $reset . PHP_EOL; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php new file mode 100644 index 00000000..ebdbae61 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use function constant; +use function phpversion; +use DateTimeImmutable; +use DOMElement; +use SebastianBergmann\Environment\Runtime; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class BuildInformation +{ + /** + * @var DOMElement + */ + private $contextNode; + + public function __construct(DOMElement $contextNode) + { + $this->contextNode = $contextNode; + } + + public function setRuntimeInformation(Runtime $runtime): void + { + $runtimeNode = $this->nodeByName('runtime'); + + $runtimeNode->setAttribute('name', $runtime->getName()); + $runtimeNode->setAttribute('version', $runtime->getVersion()); + $runtimeNode->setAttribute('url', $runtime->getVendorUrl()); + + $driverNode = $this->nodeByName('driver'); + + if ($runtime->hasPHPDBGCodeCoverage()) { + $driverNode->setAttribute('name', 'phpdbg'); + $driverNode->setAttribute('version', constant('PHPDBG_VERSION')); + } + + if ($runtime->hasXdebug()) { + $driverNode->setAttribute('name', 'xdebug'); + $driverNode->setAttribute('version', phpversion('xdebug')); + } + + if ($runtime->hasPCOV()) { + $driverNode->setAttribute('name', 'pcov'); + $driverNode->setAttribute('version', phpversion('pcov')); + } + } + + public function setBuildTime(DateTimeImmutable $date): void + { + $this->contextNode->setAttribute('time', $date->format('D M j G:i:s T Y')); + } + + public function setGeneratorVersions(string $phpUnitVersion, string $coverageVersion): void + { + $this->contextNode->setAttribute('phpunit', $phpUnitVersion); + $this->contextNode->setAttribute('coverage', $coverageVersion); + } + + private function nodeByName(string $name): DOMElement + { + $node = $this->contextNode->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + $name + )->item(0); + + if (!$node) { + $node = $this->contextNode->appendChild( + $this->contextNode->ownerDocument->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + $name + ) + ); + } + + return $node; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php new file mode 100644 index 00000000..b556d820 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMElement; +use SebastianBergmann\CodeCoverage\ReportAlreadyFinalizedException; +use XMLWriter; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Coverage +{ + /** + * @var XMLWriter + */ + private $writer; + + /** + * @var DOMElement + */ + private $contextNode; + + /** + * @var bool + */ + private $finalized = false; + + public function __construct(DOMElement $context, string $line) + { + $this->contextNode = $context; + + $this->writer = new XMLWriter; + $this->writer->openMemory(); + $this->writer->startElementNS(null, $context->nodeName, 'https://schema.phpunit.de/coverage/1.0'); + $this->writer->writeAttribute('nr', $line); + } + + /** + * @throws ReportAlreadyFinalizedException + */ + public function addTest(string $test): void + { + if ($this->finalized) { + throw new ReportAlreadyFinalizedException; + } + + $this->writer->startElement('covered'); + $this->writer->writeAttribute('by', $test); + $this->writer->endElement(); + } + + public function finalize(): void + { + $this->writer->endElement(); + + $fragment = $this->contextNode->ownerDocument->createDocumentFragment(); + $fragment->appendXML($this->writer->outputMemory()); + + $this->contextNode->parentNode->replaceChild( + $fragment, + $this->contextNode + ); + + $this->finalized = true; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php new file mode 100644 index 00000000..b712953a --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Directory extends Node +{ +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php new file mode 100644 index 00000000..3ecc7506 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php @@ -0,0 +1,315 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use const DIRECTORY_SEPARATOR; +use const PHP_EOL; +use function count; +use function dirname; +use function file_get_contents; +use function file_put_contents; +use function is_array; +use function is_dir; +use function is_file; +use function is_writable; +use function libxml_clear_errors; +use function libxml_get_errors; +use function libxml_use_internal_errors; +use function sprintf; +use function strlen; +use function substr; +use DateTimeImmutable; +use DOMDocument; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Driver\PathExistsButIsNotDirectoryException; +use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; +use SebastianBergmann\CodeCoverage\Node\AbstractNode; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; +use SebastianBergmann\CodeCoverage\Node\File as FileNode; +use SebastianBergmann\CodeCoverage\Util\Filesystem as DirectoryUtil; +use SebastianBergmann\CodeCoverage\Version; +use SebastianBergmann\CodeCoverage\XmlException; +use SebastianBergmann\Environment\Runtime; + +final class Facade +{ + /** + * @var string + */ + private $target; + + /** + * @var Project + */ + private $project; + + /** + * @var string + */ + private $phpUnitVersion; + + public function __construct(string $version) + { + $this->phpUnitVersion = $version; + } + + /** + * @throws XmlException + */ + public function process(CodeCoverage $coverage, string $target): void + { + if (substr($target, -1, 1) !== DIRECTORY_SEPARATOR) { + $target .= DIRECTORY_SEPARATOR; + } + + $this->target = $target; + $this->initTargetDirectory($target); + + $report = $coverage->getReport(); + + $this->project = new Project( + $coverage->getReport()->name() + ); + + $this->setBuildInformation(); + $this->processTests($coverage->getTests()); + $this->processDirectory($report, $this->project); + + $this->saveDocument($this->project->asDom(), 'index'); + } + + private function setBuildInformation(): void + { + $buildNode = $this->project->buildInformation(); + $buildNode->setRuntimeInformation(new Runtime); + $buildNode->setBuildTime(new DateTimeImmutable); + $buildNode->setGeneratorVersions($this->phpUnitVersion, Version::id()); + } + + /** + * @throws PathExistsButIsNotDirectoryException + * @throws WriteOperationFailedException + */ + private function initTargetDirectory(string $directory): void + { + if (is_file($directory)) { + if (!is_dir($directory)) { + throw new PathExistsButIsNotDirectoryException($directory); + } + + if (!is_writable($directory)) { + throw new WriteOperationFailedException($directory); + } + } + + DirectoryUtil::createDirectory($directory); + } + + /** + * @throws XmlException + */ + private function processDirectory(DirectoryNode $directory, Node $context): void + { + $directoryName = $directory->name(); + + if ($this->project->projectSourceDirectory() === $directoryName) { + $directoryName = '/'; + } + + $directoryObject = $context->addDirectory($directoryName); + + $this->setTotals($directory, $directoryObject->totals()); + + foreach ($directory->directories() as $node) { + $this->processDirectory($node, $directoryObject); + } + + foreach ($directory->files() as $node) { + $this->processFile($node, $directoryObject); + } + } + + /** + * @throws XmlException + */ + private function processFile(FileNode $file, Directory $context): void + { + $fileObject = $context->addFile( + $file->name(), + $file->id() . '.xml' + ); + + $this->setTotals($file, $fileObject->totals()); + + $path = substr( + $file->pathAsString(), + strlen($this->project->projectSourceDirectory()) + ); + + $fileReport = new Report($path); + + $this->setTotals($file, $fileReport->totals()); + + foreach ($file->classesAndTraits() as $unit) { + $this->processUnit($unit, $fileReport); + } + + foreach ($file->functions() as $function) { + $this->processFunction($function, $fileReport); + } + + foreach ($file->lineCoverageData() as $line => $tests) { + if (!is_array($tests) || count($tests) === 0) { + continue; + } + + $coverage = $fileReport->lineCoverage((string) $line); + + foreach ($tests as $test) { + $coverage->addTest($test); + } + + $coverage->finalize(); + } + + $fileReport->source()->setSourceCode( + file_get_contents($file->pathAsString()) + ); + + $this->saveDocument($fileReport->asDom(), $file->id()); + } + + private function processUnit(array $unit, Report $report): void + { + if (isset($unit['className'])) { + $unitObject = $report->classObject($unit['className']); + } else { + $unitObject = $report->traitObject($unit['traitName']); + } + + $unitObject->setLines( + $unit['startLine'], + $unit['executableLines'], + $unit['executedLines'] + ); + + $unitObject->setCrap((float) $unit['crap']); + $unitObject->setNamespace($unit['namespace']); + + foreach ($unit['methods'] as $method) { + $methodObject = $unitObject->addMethod($method['methodName']); + $methodObject->setSignature($method['signature']); + $methodObject->setLines((string) $method['startLine'], (string) $method['endLine']); + $methodObject->setCrap($method['crap']); + $methodObject->setTotals( + (string) $method['executableLines'], + (string) $method['executedLines'], + (string) $method['coverage'] + ); + } + } + + private function processFunction(array $function, Report $report): void + { + $functionObject = $report->functionObject($function['functionName']); + + $functionObject->setSignature($function['signature']); + $functionObject->setLines((string) $function['startLine']); + $functionObject->setCrap($function['crap']); + $functionObject->setTotals((string) $function['executableLines'], (string) $function['executedLines'], (string) $function['coverage']); + } + + private function processTests(array $tests): void + { + $testsObject = $this->project->tests(); + + foreach ($tests as $test => $result) { + $testsObject->addTest($test, $result); + } + } + + private function setTotals(AbstractNode $node, Totals $totals): void + { + $loc = $node->linesOfCode(); + + $totals->setNumLines( + $loc['linesOfCode'], + $loc['commentLinesOfCode'], + $loc['nonCommentLinesOfCode'], + $node->numberOfExecutableLines(), + $node->numberOfExecutedLines() + ); + + $totals->setNumClasses( + $node->numberOfClasses(), + $node->numberOfTestedClasses() + ); + + $totals->setNumTraits( + $node->numberOfTraits(), + $node->numberOfTestedTraits() + ); + + $totals->setNumMethods( + $node->numberOfMethods(), + $node->numberOfTestedMethods() + ); + + $totals->setNumFunctions( + $node->numberOfFunctions(), + $node->numberOfTestedFunctions() + ); + } + + private function targetDirectory(): string + { + return $this->target; + } + + /** + * @throws XmlException + */ + private function saveDocument(DOMDocument $document, string $name): void + { + $filename = sprintf('%s/%s.xml', $this->targetDirectory(), $name); + + $document->formatOutput = true; + $document->preserveWhiteSpace = false; + $this->initTargetDirectory(dirname($filename)); + + file_put_contents($filename, $this->documentAsString($document)); + } + + /** + * @throws XmlException + * + * @see https://bugs.php.net/bug.php?id=79191 + */ + private function documentAsString(DOMDocument $document): string + { + $xmlErrorHandling = libxml_use_internal_errors(true); + $xml = $document->saveXML(); + + if ($xml === false) { + $message = 'Unable to generate the XML'; + + foreach (libxml_get_errors() as $error) { + $message .= PHP_EOL . $error->message; + } + + throw new XmlException($message); + } + + libxml_clear_errors(); + libxml_use_internal_errors($xmlErrorHandling); + + return $xml; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/File.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/File.php new file mode 100644 index 00000000..245c5cee --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/File.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMDocument; +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +class File +{ + /** + * @var DOMDocument + */ + private $dom; + + /** + * @var DOMElement + */ + private $contextNode; + + public function __construct(DOMElement $context) + { + $this->dom = $context->ownerDocument; + $this->contextNode = $context; + } + + public function totals(): Totals + { + $totalsContainer = $this->contextNode->firstChild; + + if (!$totalsContainer) { + $totalsContainer = $this->contextNode->appendChild( + $this->dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'totals' + ) + ); + } + + return new Totals($totalsContainer); + } + + public function lineCoverage(string $line): Coverage + { + $coverage = $this->contextNode->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + 'coverage' + )->item(0); + + if (!$coverage) { + $coverage = $this->contextNode->appendChild( + $this->dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'coverage' + ) + ); + } + + $lineNode = $coverage->appendChild( + $this->dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'line' + ) + ); + + return new Coverage($lineNode, $line); + } + + protected function contextNode(): DOMElement + { + return $this->contextNode; + } + + protected function dom(): DOMDocument + { + return $this->dom; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php new file mode 100644 index 00000000..7e300999 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Method +{ + /** + * @var DOMElement + */ + private $contextNode; + + public function __construct(DOMElement $context, string $name) + { + $this->contextNode = $context; + + $this->setName($name); + } + + public function setSignature(string $signature): void + { + $this->contextNode->setAttribute('signature', $signature); + } + + public function setLines(string $start, ?string $end = null): void + { + $this->contextNode->setAttribute('start', $start); + + if ($end !== null) { + $this->contextNode->setAttribute('end', $end); + } + } + + public function setTotals(string $executable, string $executed, string $coverage): void + { + $this->contextNode->setAttribute('executable', $executable); + $this->contextNode->setAttribute('executed', $executed); + $this->contextNode->setAttribute('coverage', $coverage); + } + + public function setCrap(string $crap): void + { + $this->contextNode->setAttribute('crap', $crap); + } + + private function setName(string $name): void + { + $this->contextNode->setAttribute('name', $name); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php new file mode 100644 index 00000000..15992309 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMDocument; +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +abstract class Node +{ + /** + * @var DOMDocument + */ + private $dom; + + /** + * @var DOMElement + */ + private $contextNode; + + public function __construct(DOMElement $context) + { + $this->setContextNode($context); + } + + public function dom(): DOMDocument + { + return $this->dom; + } + + public function totals(): Totals + { + $totalsContainer = $this->contextNode()->firstChild; + + if (!$totalsContainer) { + $totalsContainer = $this->contextNode()->appendChild( + $this->dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'totals' + ) + ); + } + + return new Totals($totalsContainer); + } + + public function addDirectory(string $name): Directory + { + $dirNode = $this->dom()->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'directory' + ); + + $dirNode->setAttribute('name', $name); + $this->contextNode()->appendChild($dirNode); + + return new Directory($dirNode); + } + + public function addFile(string $name, string $href): File + { + $fileNode = $this->dom()->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'file' + ); + + $fileNode->setAttribute('name', $name); + $fileNode->setAttribute('href', $href); + $this->contextNode()->appendChild($fileNode); + + return new File($fileNode); + } + + protected function setContextNode(DOMElement $context): void + { + $this->dom = $context->ownerDocument; + $this->contextNode = $context; + } + + protected function contextNode(): DOMElement + { + return $this->contextNode; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php new file mode 100644 index 00000000..b566bce0 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMDocument; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Project extends Node +{ + public function __construct(string $directory) + { + $this->init(); + $this->setProjectSourceDirectory($directory); + } + + public function projectSourceDirectory(): string + { + return $this->contextNode()->getAttribute('source'); + } + + public function buildInformation(): BuildInformation + { + $buildNode = $this->dom()->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + 'build' + )->item(0); + + if (!$buildNode) { + $buildNode = $this->dom()->documentElement->appendChild( + $this->dom()->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'build' + ) + ); + } + + return new BuildInformation($buildNode); + } + + public function tests(): Tests + { + $testsNode = $this->contextNode()->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + 'tests' + )->item(0); + + if (!$testsNode) { + $testsNode = $this->contextNode()->appendChild( + $this->dom()->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'tests' + ) + ); + } + + return new Tests($testsNode); + } + + public function asDom(): DOMDocument + { + return $this->dom(); + } + + private function init(): void + { + $dom = new DOMDocument; + $dom->loadXML(''); + + $this->setContextNode( + $dom->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + 'project' + )->item(0) + ); + } + + private function setProjectSourceDirectory(string $name): void + { + $this->contextNode()->setAttribute('source', $name); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php new file mode 100644 index 00000000..7f2badae --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use function basename; +use function dirname; +use DOMDocument; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Report extends File +{ + public function __construct(string $name) + { + $dom = new DOMDocument; + $dom->loadXML(''); + + $contextNode = $dom->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + 'file' + )->item(0); + + parent::__construct($contextNode); + + $this->setName($name); + } + + public function asDom(): DOMDocument + { + return $this->dom(); + } + + public function functionObject($name): Method + { + $node = $this->contextNode()->appendChild( + $this->dom()->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'function' + ) + ); + + return new Method($node, $name); + } + + public function classObject($name): Unit + { + return $this->unitObject('class', $name); + } + + public function traitObject($name): Unit + { + return $this->unitObject('trait', $name); + } + + public function source(): Source + { + $source = $this->contextNode()->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + 'source' + )->item(0); + + if (!$source) { + $source = $this->contextNode()->appendChild( + $this->dom()->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'source' + ) + ); + } + + return new Source($source); + } + + private function setName(string $name): void + { + $this->contextNode()->setAttribute('name', basename($name)); + $this->contextNode()->setAttribute('path', dirname($name)); + } + + private function unitObject(string $tagName, $name): Unit + { + $node = $this->contextNode()->appendChild( + $this->dom()->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + $tagName + ) + ); + + return new Unit($node, $name); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php new file mode 100644 index 00000000..2b67ce1d --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMElement; +use TheSeer\Tokenizer\NamespaceUri; +use TheSeer\Tokenizer\Tokenizer; +use TheSeer\Tokenizer\XMLSerializer; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Source +{ + /** @var DOMElement */ + private $context; + + public function __construct(DOMElement $context) + { + $this->context = $context; + } + + public function setSourceCode(string $source): void + { + $context = $this->context; + + $tokens = (new Tokenizer)->parse($source); + $srcDom = (new XMLSerializer(new NamespaceUri($context->namespaceURI)))->toDom($tokens); + + $context->parentNode->replaceChild( + $context->ownerDocument->importNode($srcDom->documentElement, true), + $context + ); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php new file mode 100644 index 00000000..c2e56268 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Tests +{ + private $contextNode; + + private $codeMap = [ + -1 => 'UNKNOWN', // PHPUnit_Runner_BaseTestRunner::STATUS_UNKNOWN + 0 => 'PASSED', // PHPUnit_Runner_BaseTestRunner::STATUS_PASSED + 1 => 'SKIPPED', // PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED + 2 => 'INCOMPLETE', // PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE + 3 => 'FAILURE', // PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE + 4 => 'ERROR', // PHPUnit_Runner_BaseTestRunner::STATUS_ERROR + 5 => 'RISKY', // PHPUnit_Runner_BaseTestRunner::STATUS_RISKY + 6 => 'WARNING', // PHPUnit_Runner_BaseTestRunner::STATUS_WARNING + ]; + + public function __construct(DOMElement $context) + { + $this->contextNode = $context; + } + + public function addTest(string $test, array $result): void + { + $node = $this->contextNode->appendChild( + $this->contextNode->ownerDocument->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'test' + ) + ); + + $node->setAttribute('name', $test); + $node->setAttribute('size', $result['size']); + $node->setAttribute('result', (string) $result['status']); + $node->setAttribute('status', $this->codeMap[(int) $result['status']]); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php new file mode 100644 index 00000000..37081318 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php @@ -0,0 +1,146 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use function sprintf; +use DOMElement; +use DOMNode; +use SebastianBergmann\CodeCoverage\Util\Percentage; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Totals +{ + /** + * @var DOMNode + */ + private $container; + + /** + * @var DOMElement + */ + private $linesNode; + + /** + * @var DOMElement + */ + private $methodsNode; + + /** + * @var DOMElement + */ + private $functionsNode; + + /** + * @var DOMElement + */ + private $classesNode; + + /** + * @var DOMElement + */ + private $traitsNode; + + public function __construct(DOMElement $container) + { + $this->container = $container; + $dom = $container->ownerDocument; + + $this->linesNode = $dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'lines' + ); + + $this->methodsNode = $dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'methods' + ); + + $this->functionsNode = $dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'functions' + ); + + $this->classesNode = $dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'classes' + ); + + $this->traitsNode = $dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'traits' + ); + + $container->appendChild($this->linesNode); + $container->appendChild($this->methodsNode); + $container->appendChild($this->functionsNode); + $container->appendChild($this->classesNode); + $container->appendChild($this->traitsNode); + } + + public function container(): DOMNode + { + return $this->container; + } + + public function setNumLines(int $loc, int $cloc, int $ncloc, int $executable, int $executed): void + { + $this->linesNode->setAttribute('total', (string) $loc); + $this->linesNode->setAttribute('comments', (string) $cloc); + $this->linesNode->setAttribute('code', (string) $ncloc); + $this->linesNode->setAttribute('executable', (string) $executable); + $this->linesNode->setAttribute('executed', (string) $executed); + $this->linesNode->setAttribute( + 'percent', + $executable === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($executed, $executable)->asFloat()) + ); + } + + public function setNumClasses(int $count, int $tested): void + { + $this->classesNode->setAttribute('count', (string) $count); + $this->classesNode->setAttribute('tested', (string) $tested); + $this->classesNode->setAttribute( + 'percent', + $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()) + ); + } + + public function setNumTraits(int $count, int $tested): void + { + $this->traitsNode->setAttribute('count', (string) $count); + $this->traitsNode->setAttribute('tested', (string) $tested); + $this->traitsNode->setAttribute( + 'percent', + $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()) + ); + } + + public function setNumMethods(int $count, int $tested): void + { + $this->methodsNode->setAttribute('count', (string) $count); + $this->methodsNode->setAttribute('tested', (string) $tested); + $this->methodsNode->setAttribute( + 'percent', + $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()) + ); + } + + public function setNumFunctions(int $count, int $tested): void + { + $this->functionsNode->setAttribute('count', (string) $count); + $this->functionsNode->setAttribute('tested', (string) $tested); + $this->functionsNode->setAttribute( + 'percent', + $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()) + ); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php b/vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php new file mode 100644 index 00000000..d84dc481 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Unit +{ + /** + * @var DOMElement + */ + private $contextNode; + + public function __construct(DOMElement $context, string $name) + { + $this->contextNode = $context; + + $this->setName($name); + } + + public function setLines(int $start, int $executable, int $executed): void + { + $this->contextNode->setAttribute('start', (string) $start); + $this->contextNode->setAttribute('executable', (string) $executable); + $this->contextNode->setAttribute('executed', (string) $executed); + } + + public function setCrap(float $crap): void + { + $this->contextNode->setAttribute('crap', (string) $crap); + } + + public function setNamespace(string $namespace): void + { + $node = $this->contextNode->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + 'namespace' + )->item(0); + + if (!$node) { + $node = $this->contextNode->appendChild( + $this->contextNode->ownerDocument->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'namespace' + ) + ); + } + + $node->setAttribute('name', $namespace); + } + + public function addMethod(string $name): Method + { + $node = $this->contextNode->appendChild( + $this->contextNode->ownerDocument->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'method' + ) + ); + + return new Method($node, $name); + } + + private function setName(string $name): void + { + $this->contextNode->setAttribute('name', $name); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php new file mode 100644 index 00000000..00a6d8df --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\StaticAnalysis; + +use SebastianBergmann\CodeCoverage\Filter; + +final class CacheWarmer +{ + public function warmCache(string $cacheDirectory, bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecatedCode, Filter $filter): void + { + $analyser = new CachingFileAnalyser( + $cacheDirectory, + new ParsingFileAnalyser( + $useAnnotationsForIgnoringCode, + $ignoreDeprecatedCode + ) + ); + + foreach ($filter->files() as $file) { + $analyser->process($file); + } + } +} diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php new file mode 100644 index 00000000..f53da078 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php @@ -0,0 +1,184 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\StaticAnalysis; + +use function file_get_contents; +use function file_put_contents; +use function implode; +use function is_file; +use function md5; +use function serialize; +use function unserialize; +use SebastianBergmann\CodeCoverage\Util\Filesystem; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class CachingFileAnalyser implements FileAnalyser +{ + /** + * @var ?string + */ + private static $cacheVersion; + + /** + * @var FileAnalyser + */ + private $analyser; + + /** + * @var array + */ + private $cache = []; + + /** + * @var string + */ + private $directory; + + public function __construct(string $directory, FileAnalyser $analyser) + { + Filesystem::createDirectory($directory); + + $this->analyser = $analyser; + $this->directory = $directory; + } + + public function classesIn(string $filename): array + { + if (!isset($this->cache[$filename])) { + $this->process($filename); + } + + return $this->cache[$filename]['classesIn']; + } + + public function traitsIn(string $filename): array + { + if (!isset($this->cache[$filename])) { + $this->process($filename); + } + + return $this->cache[$filename]['traitsIn']; + } + + public function functionsIn(string $filename): array + { + if (!isset($this->cache[$filename])) { + $this->process($filename); + } + + return $this->cache[$filename]['functionsIn']; + } + + /** + * @psalm-return array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} + */ + public function linesOfCodeFor(string $filename): array + { + if (!isset($this->cache[$filename])) { + $this->process($filename); + } + + return $this->cache[$filename]['linesOfCodeFor']; + } + + public function executableLinesIn(string $filename): array + { + if (!isset($this->cache[$filename])) { + $this->process($filename); + } + + return $this->cache[$filename]['executableLinesIn']; + } + + public function ignoredLinesFor(string $filename): array + { + if (!isset($this->cache[$filename])) { + $this->process($filename); + } + + return $this->cache[$filename]['ignoredLinesFor']; + } + + public function process(string $filename): void + { + $cache = $this->read($filename); + + if ($cache !== false) { + $this->cache[$filename] = $cache; + + return; + } + + $this->cache[$filename] = [ + 'classesIn' => $this->analyser->classesIn($filename), + 'traitsIn' => $this->analyser->traitsIn($filename), + 'functionsIn' => $this->analyser->functionsIn($filename), + 'linesOfCodeFor' => $this->analyser->linesOfCodeFor($filename), + 'ignoredLinesFor' => $this->analyser->ignoredLinesFor($filename), + 'executableLinesIn' => $this->analyser->executableLinesIn($filename), + ]; + + $this->write($filename, $this->cache[$filename]); + } + + /** + * @return mixed + */ + private function read(string $filename) + { + $cacheFile = $this->cacheFile($filename); + + if (!is_file($cacheFile)) { + return false; + } + + return unserialize( + file_get_contents($cacheFile), + ['allowed_classes' => false] + ); + } + + /** + * @param mixed $data + */ + private function write(string $filename, $data): void + { + file_put_contents( + $this->cacheFile($filename), + serialize($data) + ); + } + + private function cacheFile(string $filename): string + { + return $this->directory . DIRECTORY_SEPARATOR . md5($filename . "\0" . file_get_contents($filename) . "\0" . self::cacheVersion()); + } + + private static function cacheVersion(): string + { + if (self::$cacheVersion !== null) { + return self::$cacheVersion; + } + + $buffer = []; + + foreach ((new FileIteratorFacade)->getFilesAsArray(__DIR__, '.php') as $file) { + $buffer[] = $file; + $buffer[] = file_get_contents($file); + } + + self::$cacheVersion = md5(implode("\0", $buffer)); + + return self::$cacheVersion; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php new file mode 100644 index 00000000..8a2003fa --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php @@ -0,0 +1,326 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\StaticAnalysis; + +use function assert; +use function implode; +use function rtrim; +use function trim; +use PhpParser\Node; +use PhpParser\Node\ComplexType; +use PhpParser\Node\Identifier; +use PhpParser\Node\IntersectionType; +use PhpParser\Node\Name; +use PhpParser\Node\NullableType; +use PhpParser\Node\Stmt\Class_; +use PhpParser\Node\Stmt\ClassMethod; +use PhpParser\Node\Stmt\Enum_; +use PhpParser\Node\Stmt\Function_; +use PhpParser\Node\Stmt\Interface_; +use PhpParser\Node\Stmt\Trait_; +use PhpParser\Node\UnionType; +use PhpParser\NodeTraverser; +use PhpParser\NodeVisitorAbstract; +use SebastianBergmann\Complexity\CyclomaticComplexityCalculatingVisitor; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class CodeUnitFindingVisitor extends NodeVisitorAbstract +{ + /** + * @psalm-var array}> + */ + private $classes = []; + + /** + * @psalm-var array}> + */ + private $traits = []; + + /** + * @psalm-var array + */ + private $functions = []; + + public function enterNode(Node $node): void + { + if ($node instanceof Class_) { + if ($node->isAnonymous()) { + return; + } + + $this->processClass($node); + } + + if ($node instanceof Trait_) { + $this->processTrait($node); + } + + if (!$node instanceof ClassMethod && !$node instanceof Function_) { + return; + } + + if ($node instanceof ClassMethod) { + $parentNode = $node->getAttribute('parent'); + + if ($parentNode instanceof Class_ && $parentNode->isAnonymous()) { + return; + } + + $this->processMethod($node); + + return; + } + + $this->processFunction($node); + } + + /** + * @psalm-return array}> + */ + public function classes(): array + { + return $this->classes; + } + + /** + * @psalm-return array}> + */ + public function traits(): array + { + return $this->traits; + } + + /** + * @psalm-return array + */ + public function functions(): array + { + return $this->functions; + } + + /** + * @psalm-param ClassMethod|Function_ $node + */ + private function cyclomaticComplexity(Node $node): int + { + assert($node instanceof ClassMethod || $node instanceof Function_); + + $nodes = $node->getStmts(); + + if ($nodes === null) { + return 0; + } + + $traverser = new NodeTraverser; + + $cyclomaticComplexityCalculatingVisitor = new CyclomaticComplexityCalculatingVisitor; + + $traverser->addVisitor($cyclomaticComplexityCalculatingVisitor); + + /* @noinspection UnusedFunctionResultInspection */ + $traverser->traverse($nodes); + + return $cyclomaticComplexityCalculatingVisitor->cyclomaticComplexity(); + } + + /** + * @psalm-param ClassMethod|Function_ $node + */ + private function signature(Node $node): string + { + assert($node instanceof ClassMethod || $node instanceof Function_); + + $signature = ($node->returnsByRef() ? '&' : '') . $node->name->toString() . '('; + $parameters = []; + + foreach ($node->getParams() as $parameter) { + assert(isset($parameter->var->name)); + + $parameterAsString = ''; + + if ($parameter->type !== null) { + $parameterAsString = $this->type($parameter->type) . ' '; + } + + $parameterAsString .= '$' . $parameter->var->name; + + /* @todo Handle default values */ + + $parameters[] = $parameterAsString; + } + + $signature .= implode(', ', $parameters) . ')'; + + $returnType = $node->getReturnType(); + + if ($returnType !== null) { + $signature .= ': ' . $this->type($returnType); + } + + return $signature; + } + + /** + * @psalm-param Identifier|Name|ComplexType $type + */ + private function type(Node $type): string + { + assert($type instanceof Identifier || $type instanceof Name || $type instanceof ComplexType); + + if ($type instanceof NullableType) { + return '?' . $type->type; + } + + if ($type instanceof UnionType || $type instanceof IntersectionType) { + return $this->unionOrIntersectionAsString($type); + } + + return $type->toString(); + } + + private function visibility(ClassMethod $node): string + { + if ($node->isPrivate()) { + return 'private'; + } + + if ($node->isProtected()) { + return 'protected'; + } + + return 'public'; + } + + private function processClass(Class_ $node): void + { + $name = $node->name->toString(); + $namespacedName = $node->namespacedName->toString(); + + $this->classes[$namespacedName] = [ + 'name' => $name, + 'namespacedName' => $namespacedName, + 'namespace' => $this->namespace($namespacedName, $name), + 'startLine' => $node->getStartLine(), + 'endLine' => $node->getEndLine(), + 'methods' => [], + ]; + } + + private function processTrait(Trait_ $node): void + { + $name = $node->name->toString(); + $namespacedName = $node->namespacedName->toString(); + + $this->traits[$namespacedName] = [ + 'name' => $name, + 'namespacedName' => $namespacedName, + 'namespace' => $this->namespace($namespacedName, $name), + 'startLine' => $node->getStartLine(), + 'endLine' => $node->getEndLine(), + 'methods' => [], + ]; + } + + private function processMethod(ClassMethod $node): void + { + $parentNode = $node->getAttribute('parent'); + + if ($parentNode instanceof Interface_) { + return; + } + + assert($parentNode instanceof Class_ || $parentNode instanceof Trait_ || $parentNode instanceof Enum_); + assert(isset($parentNode->name)); + assert(isset($parentNode->namespacedName)); + assert($parentNode->namespacedName instanceof Name); + + $parentName = $parentNode->name->toString(); + $parentNamespacedName = $parentNode->namespacedName->toString(); + + if ($parentNode instanceof Class_) { + $storage = &$this->classes; + } else { + $storage = &$this->traits; + } + + if (!isset($storage[$parentNamespacedName])) { + $storage[$parentNamespacedName] = [ + 'name' => $parentName, + 'namespacedName' => $parentNamespacedName, + 'namespace' => $this->namespace($parentNamespacedName, $parentName), + 'startLine' => $parentNode->getStartLine(), + 'endLine' => $parentNode->getEndLine(), + 'methods' => [], + ]; + } + + $storage[$parentNamespacedName]['methods'][$node->name->toString()] = [ + 'methodName' => $node->name->toString(), + 'signature' => $this->signature($node), + 'visibility' => $this->visibility($node), + 'startLine' => $node->getStartLine(), + 'endLine' => $node->getEndLine(), + 'ccn' => $this->cyclomaticComplexity($node), + ]; + } + + private function processFunction(Function_ $node): void + { + assert(isset($node->name)); + assert(isset($node->namespacedName)); + assert($node->namespacedName instanceof Name); + + $name = $node->name->toString(); + $namespacedName = $node->namespacedName->toString(); + + $this->functions[$namespacedName] = [ + 'name' => $name, + 'namespacedName' => $namespacedName, + 'namespace' => $this->namespace($namespacedName, $name), + 'signature' => $this->signature($node), + 'startLine' => $node->getStartLine(), + 'endLine' => $node->getEndLine(), + 'ccn' => $this->cyclomaticComplexity($node), + ]; + } + + private function namespace(string $namespacedName, string $name): string + { + return trim(rtrim($namespacedName, $name), '\\'); + } + + /** + * @psalm-param UnionType|IntersectionType $type + */ + private function unionOrIntersectionAsString(ComplexType $type): string + { + if ($type instanceof UnionType) { + $separator = '|'; + } else { + $separator = '&'; + } + + $types = []; + + foreach ($type->types as $_type) { + if ($_type instanceof Name) { + $types[] = $_type->toCodeString(); + } else { + assert($_type instanceof Identifier); + + $types[] = $_type->toString(); + } + } + + return implode($separator, $types); + } +} diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php new file mode 100644 index 00000000..506f2752 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php @@ -0,0 +1,366 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\StaticAnalysis; + +use function array_diff_key; +use function assert; +use function count; +use function current; +use function end; +use function explode; +use function max; +use function preg_match; +use function preg_quote; +use function range; +use function reset; +use function sprintf; +use PhpParser\Node; +use PhpParser\NodeVisitorAbstract; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class ExecutableLinesFindingVisitor extends NodeVisitorAbstract +{ + /** + * @var int + */ + private $nextBranch = 0; + + /** + * @var string + */ + private $source; + + /** + * @var array + */ + private $executableLinesGroupedByBranch = []; + + /** + * @var array + */ + private $unsets = []; + + /** + * @var array + */ + private $commentsToCheckForUnset = []; + + public function __construct(string $source) + { + $this->source = $source; + } + + public function enterNode(Node $node): void + { + foreach ($node->getComments() as $comment) { + $commentLine = $comment->getStartLine(); + + if (!isset($this->executableLinesGroupedByBranch[$commentLine])) { + continue; + } + + foreach (explode("\n", $comment->getText()) as $text) { + $this->commentsToCheckForUnset[$commentLine] = $text; + $commentLine++; + } + } + + if ($node instanceof Node\Scalar\String_ || + $node instanceof Node\Scalar\EncapsedStringPart) { + $startLine = $node->getStartLine() + 1; + $endLine = $node->getEndLine() - 1; + + if ($startLine <= $endLine) { + foreach (range($startLine, $endLine) as $line) { + unset($this->executableLinesGroupedByBranch[$line]); + } + } + + return; + } + + if ($node instanceof Node\Stmt\Declare_ || + $node instanceof Node\Stmt\DeclareDeclare || + $node instanceof Node\Stmt\Else_ || + $node instanceof Node\Stmt\EnumCase || + $node instanceof Node\Stmt\Finally_ || + $node instanceof Node\Stmt\Interface_ || + $node instanceof Node\Stmt\Label || + $node instanceof Node\Stmt\Namespace_ || + $node instanceof Node\Stmt\Nop || + $node instanceof Node\Stmt\Switch_ || + $node instanceof Node\Stmt\TryCatch || + $node instanceof Node\Stmt\Use_ || + $node instanceof Node\Stmt\UseUse || + $node instanceof Node\Expr\ConstFetch || + $node instanceof Node\Expr\Match_ || + $node instanceof Node\Expr\Variable || + $node instanceof Node\ComplexType || + $node instanceof Node\Const_ || + $node instanceof Node\Identifier || + $node instanceof Node\Name || + $node instanceof Node\Param || + $node instanceof Node\Scalar) { + return; + } + + if ($node instanceof Node\Stmt\Throw_) { + $this->setLineBranch($node->expr->getEndLine(), $node->expr->getEndLine(), ++$this->nextBranch); + + return; + } + + if ($node instanceof Node\Stmt\Enum_ || + $node instanceof Node\Stmt\Function_ || + $node instanceof Node\Stmt\Class_ || + $node instanceof Node\Stmt\ClassMethod || + $node instanceof Node\Expr\Closure || + $node instanceof Node\Stmt\Trait_) { + $isConcreteClassLike = $node instanceof Node\Stmt\Enum_ || $node instanceof Node\Stmt\Class_ || $node instanceof Node\Stmt\Trait_; + + if (null !== $node->stmts) { + foreach ($node->stmts as $stmt) { + if ($stmt instanceof Node\Stmt\Nop) { + continue; + } + + foreach (range($stmt->getStartLine(), $stmt->getEndLine()) as $line) { + unset($this->executableLinesGroupedByBranch[$line]); + + if ( + $isConcreteClassLike && + !$stmt instanceof Node\Stmt\ClassMethod + ) { + $this->unsets[$line] = true; + } + } + } + } + + if ($isConcreteClassLike) { + return; + } + + $hasEmptyBody = [] === $node->stmts || + null === $node->stmts || + ( + 1 === count($node->stmts) && + $node->stmts[0] instanceof Node\Stmt\Nop + ); + + if ($hasEmptyBody) { + if ($node->getEndLine() === $node->getStartLine()) { + return; + } + + $this->setLineBranch($node->getEndLine(), $node->getEndLine(), ++$this->nextBranch); + + return; + } + + return; + } + + if ($node instanceof Node\Expr\ArrowFunction) { + $startLine = max( + $node->getStartLine() + 1, + $node->expr->getStartLine() + ); + + $endLine = $node->expr->getEndLine(); + + if ($endLine < $startLine) { + return; + } + + $this->setLineBranch($startLine, $endLine, ++$this->nextBranch); + + return; + } + + if ($node instanceof Node\Expr\Ternary) { + if (null !== $node->if && + $node->getStartLine() !== $node->if->getEndLine()) { + $this->setLineBranch($node->if->getStartLine(), $node->if->getEndLine(), ++$this->nextBranch); + } + + if ($node->getStartLine() !== $node->else->getEndLine()) { + $this->setLineBranch($node->else->getStartLine(), $node->else->getEndLine(), ++$this->nextBranch); + } + + return; + } + + if ($node instanceof Node\Expr\BinaryOp\Coalesce) { + if ($node->getStartLine() !== $node->getEndLine()) { + $this->setLineBranch($node->getEndLine(), $node->getEndLine(), ++$this->nextBranch); + } + + return; + } + + if ($node instanceof Node\Stmt\If_ || + $node instanceof Node\Stmt\ElseIf_ || + $node instanceof Node\Stmt\Case_) { + if (null === $node->cond) { + return; + } + + $this->setLineBranch( + $node->cond->getStartLine(), + $node->cond->getStartLine(), + ++$this->nextBranch + ); + + return; + } + + if ($node instanceof Node\Stmt\For_) { + $startLine = null; + $endLine = null; + + if ([] !== $node->init) { + $startLine = $node->init[0]->getStartLine(); + + end($node->init); + + $endLine = current($node->init)->getEndLine(); + + reset($node->init); + } + + if ([] !== $node->cond) { + if (null === $startLine) { + $startLine = $node->cond[0]->getStartLine(); + } + + end($node->cond); + + $endLine = current($node->cond)->getEndLine(); + + reset($node->cond); + } + + if ([] !== $node->loop) { + if (null === $startLine) { + $startLine = $node->loop[0]->getStartLine(); + } + + end($node->loop); + + $endLine = current($node->loop)->getEndLine(); + + reset($node->loop); + } + + if (null === $startLine || null === $endLine) { + return; + } + + $this->setLineBranch( + $startLine, + $endLine, + ++$this->nextBranch + ); + + return; + } + + if ($node instanceof Node\Stmt\Foreach_) { + $this->setLineBranch( + $node->expr->getStartLine(), + $node->valueVar->getEndLine(), + ++$this->nextBranch + ); + + return; + } + + if ($node instanceof Node\Stmt\While_ || + $node instanceof Node\Stmt\Do_) { + $this->setLineBranch( + $node->cond->getStartLine(), + $node->cond->getEndLine(), + ++$this->nextBranch + ); + + return; + } + + if ($node instanceof Node\Stmt\Catch_) { + assert([] !== $node->types); + $startLine = $node->types[0]->getStartLine(); + end($node->types); + $endLine = current($node->types)->getEndLine(); + + $this->setLineBranch( + $startLine, + $endLine, + ++$this->nextBranch + ); + + return; + } + + if ($node instanceof Node\Expr\CallLike) { + if (isset($this->executableLinesGroupedByBranch[$node->getStartLine()])) { + $branch = $this->executableLinesGroupedByBranch[$node->getStartLine()]; + } else { + $branch = ++$this->nextBranch; + } + + $this->setLineBranch($node->getStartLine(), $node->getEndLine(), $branch); + + return; + } + + if (isset($this->executableLinesGroupedByBranch[$node->getStartLine()])) { + return; + } + + $this->setLineBranch($node->getStartLine(), $node->getEndLine(), ++$this->nextBranch); + } + + public function afterTraverse(array $nodes): void + { + $lines = explode("\n", $this->source); + + foreach ($lines as $lineNumber => $line) { + $lineNumber++; + + if (1 === preg_match('/^\s*$/', $line) || + ( + isset($this->commentsToCheckForUnset[$lineNumber]) && + 1 === preg_match(sprintf('/^\s*%s\s*$/', preg_quote($this->commentsToCheckForUnset[$lineNumber], '/')), $line) + )) { + unset($this->executableLinesGroupedByBranch[$lineNumber]); + } + } + + $this->executableLinesGroupedByBranch = array_diff_key( + $this->executableLinesGroupedByBranch, + $this->unsets + ); + } + + public function executableLinesGroupedByBranch(): array + { + return $this->executableLinesGroupedByBranch; + } + + private function setLineBranch(int $start, int $end, int $branch): void + { + foreach (range($start, $end) as $line) { + $this->executableLinesGroupedByBranch[$line] = $branch; + } + } +} diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.php new file mode 100644 index 00000000..3dbcf68f --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\StaticAnalysis; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +interface FileAnalyser +{ + public function classesIn(string $filename): array; + + public function traitsIn(string $filename): array; + + public function functionsIn(string $filename): array; + + /** + * @psalm-return array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} + */ + public function linesOfCodeFor(string $filename): array; + + public function executableLinesIn(string $filename): array; + + public function ignoredLinesFor(string $filename): array; +} diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php new file mode 100644 index 00000000..3c0b2373 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\StaticAnalysis; + +use function array_merge; +use function assert; +use function range; +use function strpos; +use PhpParser\Node; +use PhpParser\Node\Attribute; +use PhpParser\Node\Stmt\Class_; +use PhpParser\Node\Stmt\ClassMethod; +use PhpParser\Node\Stmt\Function_; +use PhpParser\Node\Stmt\Interface_; +use PhpParser\Node\Stmt\Trait_; +use PhpParser\NodeVisitorAbstract; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class IgnoredLinesFindingVisitor extends NodeVisitorAbstract +{ + /** + * @psalm-var list + */ + private $ignoredLines = []; + + /** + * @var bool + */ + private $useAnnotationsForIgnoringCode; + + /** + * @var bool + */ + private $ignoreDeprecated; + + public function __construct(bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecated) + { + $this->useAnnotationsForIgnoringCode = $useAnnotationsForIgnoringCode; + $this->ignoreDeprecated = $ignoreDeprecated; + } + + public function enterNode(Node $node): void + { + if (!$node instanceof Class_ && + !$node instanceof Trait_ && + !$node instanceof Interface_ && + !$node instanceof ClassMethod && + !$node instanceof Function_ && + !$node instanceof Attribute) { + return; + } + + if ($node instanceof Class_ && $node->isAnonymous()) { + return; + } + + if ($node instanceof Class_ || + $node instanceof Trait_ || + $node instanceof Interface_ || + $node instanceof Attribute) { + $this->ignoredLines[] = $node->getStartLine(); + + assert($node->name !== null); + + // Workaround for https://github.com/nikic/PHP-Parser/issues/886 + $this->ignoredLines[] = $node->name->getStartLine(); + } + + if (!$this->useAnnotationsForIgnoringCode) { + return; + } + + if ($node instanceof Interface_) { + return; + } + + $this->processDocComment($node); + } + + /** + * @psalm-return list + */ + public function ignoredLines(): array + { + return $this->ignoredLines; + } + + private function processDocComment(Node $node): void + { + $docComment = $node->getDocComment(); + + if ($docComment === null) { + return; + } + + if (strpos($docComment->getText(), '@codeCoverageIgnore') !== false) { + $this->ignoredLines = array_merge( + $this->ignoredLines, + range($node->getStartLine(), $node->getEndLine()) + ); + } + + if ($this->ignoreDeprecated && strpos($docComment->getText(), '@deprecated') !== false) { + $this->ignoredLines = array_merge( + $this->ignoredLines, + range($node->getStartLine(), $node->getEndLine()) + ); + } + } +} diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php new file mode 100644 index 00000000..e6863821 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php @@ -0,0 +1,253 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\StaticAnalysis; + +use function array_merge; +use function array_unique; +use function assert; +use function file_get_contents; +use function is_array; +use function max; +use function range; +use function sort; +use function sprintf; +use function substr_count; +use function token_get_all; +use function trim; +use PhpParser\Error; +use PhpParser\Lexer; +use PhpParser\NodeTraverser; +use PhpParser\NodeVisitor\NameResolver; +use PhpParser\NodeVisitor\ParentConnectingVisitor; +use PhpParser\ParserFactory; +use SebastianBergmann\CodeCoverage\ParserException; +use SebastianBergmann\LinesOfCode\LineCountingVisitor; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class ParsingFileAnalyser implements FileAnalyser +{ + /** + * @var array + */ + private $classes = []; + + /** + * @var array + */ + private $traits = []; + + /** + * @var array + */ + private $functions = []; + + /** + * @var array + */ + private $linesOfCode = []; + + /** + * @var array + */ + private $ignoredLines = []; + + /** + * @var array + */ + private $executableLines = []; + + /** + * @var bool + */ + private $useAnnotationsForIgnoringCode; + + /** + * @var bool + */ + private $ignoreDeprecatedCode; + + public function __construct(bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecatedCode) + { + $this->useAnnotationsForIgnoringCode = $useAnnotationsForIgnoringCode; + $this->ignoreDeprecatedCode = $ignoreDeprecatedCode; + } + + public function classesIn(string $filename): array + { + $this->analyse($filename); + + return $this->classes[$filename]; + } + + public function traitsIn(string $filename): array + { + $this->analyse($filename); + + return $this->traits[$filename]; + } + + public function functionsIn(string $filename): array + { + $this->analyse($filename); + + return $this->functions[$filename]; + } + + /** + * @psalm-return array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} + */ + public function linesOfCodeFor(string $filename): array + { + $this->analyse($filename); + + return $this->linesOfCode[$filename]; + } + + public function executableLinesIn(string $filename): array + { + $this->analyse($filename); + + return $this->executableLines[$filename]; + } + + public function ignoredLinesFor(string $filename): array + { + $this->analyse($filename); + + return $this->ignoredLines[$filename]; + } + + /** + * @throws ParserException + */ + private function analyse(string $filename): void + { + if (isset($this->classes[$filename])) { + return; + } + + $source = file_get_contents($filename); + $linesOfCode = max(substr_count($source, "\n") + 1, substr_count($source, "\r") + 1); + + if ($linesOfCode === 0 && !empty($source)) { + $linesOfCode = 1; + } + + $parser = (new ParserFactory)->create( + ParserFactory::PREFER_PHP7, + new Lexer + ); + + try { + $nodes = $parser->parse($source); + + assert($nodes !== null); + + $traverser = new NodeTraverser; + $codeUnitFindingVisitor = new CodeUnitFindingVisitor; + $lineCountingVisitor = new LineCountingVisitor($linesOfCode); + $ignoredLinesFindingVisitor = new IgnoredLinesFindingVisitor($this->useAnnotationsForIgnoringCode, $this->ignoreDeprecatedCode); + $executableLinesFindingVisitor = new ExecutableLinesFindingVisitor($source); + + $traverser->addVisitor(new NameResolver); + $traverser->addVisitor(new ParentConnectingVisitor); + $traverser->addVisitor($codeUnitFindingVisitor); + $traverser->addVisitor($lineCountingVisitor); + $traverser->addVisitor($ignoredLinesFindingVisitor); + $traverser->addVisitor($executableLinesFindingVisitor); + + /* @noinspection UnusedFunctionResultInspection */ + $traverser->traverse($nodes); + // @codeCoverageIgnoreStart + } catch (Error $error) { + throw new ParserException( + sprintf( + 'Cannot parse %s: %s', + $filename, + $error->getMessage() + ), + $error->getCode(), + $error + ); + } + // @codeCoverageIgnoreEnd + + $this->classes[$filename] = $codeUnitFindingVisitor->classes(); + $this->traits[$filename] = $codeUnitFindingVisitor->traits(); + $this->functions[$filename] = $codeUnitFindingVisitor->functions(); + $this->executableLines[$filename] = $executableLinesFindingVisitor->executableLinesGroupedByBranch(); + $this->ignoredLines[$filename] = []; + + $this->findLinesIgnoredByLineBasedAnnotations($filename, $source, $this->useAnnotationsForIgnoringCode); + + $this->ignoredLines[$filename] = array_unique( + array_merge( + $this->ignoredLines[$filename], + $ignoredLinesFindingVisitor->ignoredLines() + ) + ); + + sort($this->ignoredLines[$filename]); + + $result = $lineCountingVisitor->result(); + + $this->linesOfCode[$filename] = [ + 'linesOfCode' => $result->linesOfCode(), + 'commentLinesOfCode' => $result->commentLinesOfCode(), + 'nonCommentLinesOfCode' => $result->nonCommentLinesOfCode(), + ]; + } + + private function findLinesIgnoredByLineBasedAnnotations(string $filename, string $source, bool $useAnnotationsForIgnoringCode): void + { + if (!$useAnnotationsForIgnoringCode) { + return; + } + + $start = false; + + foreach (token_get_all($source) as $token) { + if (!is_array($token) || + !(T_COMMENT === $token[0] || T_DOC_COMMENT === $token[0])) { + continue; + } + + $comment = trim($token[1]); + + if ($comment === '// @codeCoverageIgnore' || + $comment === '//@codeCoverageIgnore') { + $this->ignoredLines[$filename][] = $token[2]; + + continue; + } + + if ($comment === '// @codeCoverageIgnoreStart' || + $comment === '//@codeCoverageIgnoreStart') { + $start = $token[2]; + + continue; + } + + if ($comment === '// @codeCoverageIgnoreEnd' || + $comment === '//@codeCoverageIgnoreEnd') { + if (false === $start) { + $start = $token[2]; + } + + $this->ignoredLines[$filename] = array_merge( + $this->ignoredLines[$filename], + range($start, $token[2]) + ); + } + } + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Util/Filesystem.php b/vendor/phpunit/php-code-coverage/src/Util/Filesystem.php new file mode 100644 index 00000000..ff0e16ae --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Util/Filesystem.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Util; + +use function is_dir; +use function mkdir; +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Filesystem +{ + /** + * @throws DirectoryCouldNotBeCreatedException + */ + public static function createDirectory(string $directory): void + { + $success = !(!is_dir($directory) && !@mkdir($directory, 0777, true) && !is_dir($directory)); + + if (!$success) { + throw new DirectoryCouldNotBeCreatedException( + sprintf( + 'Directory "%s" could not be created', + $directory + ) + ); + } + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Util/Percentage.php b/vendor/phpunit/php-code-coverage/src/Util/Percentage.php new file mode 100644 index 00000000..0f7a3fec --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Util/Percentage.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Util; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Percentage +{ + /** + * @var float + */ + private $fraction; + + /** + * @var float + */ + private $total; + + public static function fromFractionAndTotal(float $fraction, float $total): self + { + return new self($fraction, $total); + } + + private function __construct(float $fraction, float $total) + { + $this->fraction = $fraction; + $this->total = $total; + } + + public function asFloat(): float + { + if ($this->total > 0) { + return ($this->fraction / $this->total) * 100; + } + + return 100.0; + } + + public function asString(): string + { + if ($this->total > 0) { + return sprintf('%01.2F%%', $this->asFloat()); + } + + return ''; + } + + public function asFixedWidthString(): string + { + if ($this->total > 0) { + return sprintf('%6.2F%%', $this->asFloat()); + } + + return ''; + } +} diff --git a/vendor/phpunit/php-code-coverage/src/Version.php b/vendor/phpunit/php-code-coverage/src/Version.php new file mode 100644 index 00000000..8d45b6c6 --- /dev/null +++ b/vendor/phpunit/php-code-coverage/src/Version.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use function dirname; +use SebastianBergmann\Version as VersionId; + +final class Version +{ + /** + * @var string + */ + private static $version; + + public static function id(): string + { + if (self::$version === null) { + self::$version = (new VersionId('9.2.24', dirname(__DIR__)))->getVersion(); + } + + return self::$version; + } +} diff --git a/vendor/phpunit/php-file-iterator/.psalm/baseline.xml b/vendor/phpunit/php-file-iterator/.psalm/baseline.xml new file mode 100644 index 00000000..8b6cdc24 --- /dev/null +++ b/vendor/phpunit/php-file-iterator/.psalm/baseline.xml @@ -0,0 +1,8 @@ + + + + + current + + + diff --git a/vendor/phpunit/php-file-iterator/.psalm/config.xml b/vendor/phpunit/php-file-iterator/.psalm/config.xml new file mode 100644 index 00000000..2a4b16f2 --- /dev/null +++ b/vendor/phpunit/php-file-iterator/.psalm/config.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/vendor/phpunit/php-file-iterator/ChangeLog.md b/vendor/phpunit/php-file-iterator/ChangeLog.md new file mode 100644 index 00000000..44833762 --- /dev/null +++ b/vendor/phpunit/php-file-iterator/ChangeLog.md @@ -0,0 +1,144 @@ +# Change Log + +All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). + +## [3.0.6] - 2021-12-02 + +### Changed + +* [#73](https://github.com/sebastianbergmann/php-file-iterator/pull/73): Micro performance improvements on parsing paths + +## [3.0.5] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [3.0.4] - 2020-07-11 + +### Fixed + +* [#67](https://github.com/sebastianbergmann/php-file-iterator/issues/67): `TypeError` in `SebastianBergmann\FileIterator\Iterator::accept()` + +## [3.0.3] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [3.0.2] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [3.0.1] - 2020-04-18 + +### Fixed + +* [#64](https://github.com/sebastianbergmann/php-file-iterator/issues/64): Release tarball contains Composer PHAR + +## [3.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.1 and PHP 7.2 + +## [2.0.5] - 2021-12-02 + +### Changed + +* [#73](https://github.com/sebastianbergmann/php-file-iterator/pull/73): Micro performance improvements on parsing paths + +### Fixed + +* [#74](https://github.com/sebastianbergmann/php-file-iterator/pull/74): Document return type of `SebastianBergmann\FileIterator\Iterator::accept()` so that Symfony's `DebugClassLoader` does not trigger a deprecation warning + +## [2.0.4] - 2021-07-19 + +### Changed + +* Added `ReturnTypeWillChange` attribute to `SebastianBergmann\FileIterator\Iterator::accept()` because the return type of `\FilterIterator::accept()` will change in PHP 8.1 + +## [2.0.3] - 2020-11-30 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.1` to `>=7.1` + +## [2.0.2] - 2018-09-13 + +### Fixed + +* [#48](https://github.com/sebastianbergmann/php-file-iterator/issues/48): Excluding an array that contains false ends up excluding the current working directory + +## [2.0.1] - 2018-06-11 + +### Fixed + +* [#46](https://github.com/sebastianbergmann/php-file-iterator/issues/46): Regression with hidden parent directory + +## [2.0.0] - 2018-05-28 + +### Fixed + +* [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30): Exclude is not considered if it is a parent of the base path + +### Changed + +* This component now uses namespaces + +### Removed + +* This component is no longer supported on PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, and PHP 7.0 + +## [1.4.5] - 2017-11-27 + +### Fixed + +* [#37](https://github.com/sebastianbergmann/php-file-iterator/issues/37): Regression caused by fix for [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30) + +## [1.4.4] - 2017-11-27 + +### Fixed + +* [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30): Exclude is not considered if it is a parent of the base path + +## [1.4.3] - 2017-11-25 + +### Fixed + +* [#34](https://github.com/sebastianbergmann/php-file-iterator/issues/34): Factory should use canonical directory names + +## [1.4.2] - 2016-11-26 + +No changes + +## [1.4.1] - 2015-07-26 + +No changes + +## 1.4.0 - 2015-04-02 + +### Added + +* [#23](https://github.com/sebastianbergmann/php-file-iterator/pull/23): Added support for wildcards (glob) in exclude + +[3.0.6]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.5...3.0.6 +[3.0.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.4...3.0.5 +[3.0.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.3...3.0.4 +[3.0.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.2...3.0.3 +[3.0.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.5...3.0.0 +[2.0.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.4...2.0.5 +[2.0.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.3...2.0.4 +[2.0.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.2...2.0.3 +[2.0.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.5...2.0.0 +[1.4.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.4...1.4.5 +[1.4.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.3...1.4.4 +[1.4.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.2...1.4.3 +[1.4.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.1...1.4.2 +[1.4.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.0...1.4.1 diff --git a/vendor/phpunit/php-file-iterator/LICENSE b/vendor/phpunit/php-file-iterator/LICENSE new file mode 100644 index 00000000..51db9163 --- /dev/null +++ b/vendor/phpunit/php-file-iterator/LICENSE @@ -0,0 +1,33 @@ +php-file-iterator + +Copyright (c) 2009-2021, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/phpunit/php-file-iterator/README.md b/vendor/phpunit/php-file-iterator/README.md new file mode 100644 index 00000000..3cbfdaae --- /dev/null +++ b/vendor/phpunit/php-file-iterator/README.md @@ -0,0 +1,14 @@ +[![Build Status](https://travis-ci.org/sebastianbergmann/php-file-iterator.svg?branch=master)](https://travis-ci.org/sebastianbergmann/php-file-iterator) + +# php-file-iterator + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + + composer require phpunit/php-file-iterator + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + + composer require --dev phpunit/php-file-iterator + diff --git a/vendor/phpunit/php-file-iterator/composer.json b/vendor/phpunit/php-file-iterator/composer.json new file mode 100644 index 00000000..f1b95b3f --- /dev/null +++ b/vendor/phpunit/php-file-iterator/composer.json @@ -0,0 +1,45 @@ +{ + "name": "phpunit/php-file-iterator", + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "type": "library", + "keywords": [ + "iterator", + "filesystem" + ], + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues" + }, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "prefer-stable": true, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + } +} diff --git a/vendor/phpunit/php-file-iterator/src/Facade.php b/vendor/phpunit/php-file-iterator/src/Facade.php new file mode 100644 index 00000000..87b6588d --- /dev/null +++ b/vendor/phpunit/php-file-iterator/src/Facade.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\FileIterator; + +use const DIRECTORY_SEPARATOR; +use function array_unique; +use function count; +use function dirname; +use function explode; +use function is_file; +use function is_string; +use function realpath; +use function sort; + +class Facade +{ + /** + * @param array|string $paths + * @param array|string $suffixes + * @param array|string $prefixes + */ + public function getFilesAsArray($paths, $suffixes = '', $prefixes = '', array $exclude = [], bool $commonPath = false): array + { + if (is_string($paths)) { + $paths = [$paths]; + } + + $iterator = (new Factory)->getFileIterator($paths, $suffixes, $prefixes, $exclude); + + $files = []; + + foreach ($iterator as $file) { + $file = $file->getRealPath(); + + if ($file) { + $files[] = $file; + } + } + + foreach ($paths as $path) { + if (is_file($path)) { + $files[] = realpath($path); + } + } + + $files = array_unique($files); + sort($files); + + if ($commonPath) { + return [ + 'commonPath' => $this->getCommonPath($files), + 'files' => $files, + ]; + } + + return $files; + } + + protected function getCommonPath(array $files): string + { + $count = count($files); + + if ($count === 0) { + return ''; + } + + if ($count === 1) { + return dirname($files[0]) . DIRECTORY_SEPARATOR; + } + + $_files = []; + + foreach ($files as $file) { + $_files[] = $_fileParts = explode(DIRECTORY_SEPARATOR, $file); + + if (empty($_fileParts[0])) { + $_fileParts[0] = DIRECTORY_SEPARATOR; + } + } + + $common = ''; + $done = false; + $j = 0; + $count--; + + while (!$done) { + for ($i = 0; $i < $count; $i++) { + if ($_files[$i][$j] != $_files[$i + 1][$j]) { + $done = true; + + break; + } + } + + if (!$done) { + $common .= $_files[0][$j]; + + if ($j > 0) { + $common .= DIRECTORY_SEPARATOR; + } + } + + $j++; + } + + return DIRECTORY_SEPARATOR . $common; + } +} diff --git a/vendor/phpunit/php-file-iterator/src/Factory.php b/vendor/phpunit/php-file-iterator/src/Factory.php new file mode 100644 index 00000000..08f8de99 --- /dev/null +++ b/vendor/phpunit/php-file-iterator/src/Factory.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\FileIterator; + +use const GLOB_ONLYDIR; +use function array_filter; +use function array_map; +use function array_merge; +use function glob; +use function is_dir; +use function is_string; +use function realpath; +use AppendIterator; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; + +class Factory +{ + /** + * @param array|string $paths + * @param array|string $suffixes + * @param array|string $prefixes + */ + public function getFileIterator($paths, $suffixes = '', $prefixes = '', array $exclude = []): AppendIterator + { + if (is_string($paths)) { + $paths = [$paths]; + } + + $paths = $this->getPathsAfterResolvingWildcards($paths); + $exclude = $this->getPathsAfterResolvingWildcards($exclude); + + if (is_string($prefixes)) { + if ($prefixes !== '') { + $prefixes = [$prefixes]; + } else { + $prefixes = []; + } + } + + if (is_string($suffixes)) { + if ($suffixes !== '') { + $suffixes = [$suffixes]; + } else { + $suffixes = []; + } + } + + $iterator = new AppendIterator; + + foreach ($paths as $path) { + if (is_dir($path)) { + $iterator->append( + new Iterator( + $path, + new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::FOLLOW_SYMLINKS | RecursiveDirectoryIterator::SKIP_DOTS) + ), + $suffixes, + $prefixes, + $exclude + ) + ); + } + } + + return $iterator; + } + + protected function getPathsAfterResolvingWildcards(array $paths): array + { + $_paths = [[]]; + + foreach ($paths as $path) { + if ($locals = glob($path, GLOB_ONLYDIR)) { + $_paths[] = array_map('\realpath', $locals); + } else { + $_paths[] = [realpath($path)]; + } + } + + return array_filter(array_merge(...$_paths)); + } +} diff --git a/vendor/phpunit/php-file-iterator/src/Iterator.php b/vendor/phpunit/php-file-iterator/src/Iterator.php new file mode 100644 index 00000000..7eb82ad6 --- /dev/null +++ b/vendor/phpunit/php-file-iterator/src/Iterator.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\FileIterator; + +use function array_filter; +use function array_map; +use function preg_match; +use function realpath; +use function str_replace; +use function strlen; +use function strpos; +use function substr; +use FilterIterator; + +class Iterator extends FilterIterator +{ + public const PREFIX = 0; + + public const SUFFIX = 1; + + /** + * @var string + */ + private $basePath; + + /** + * @var array + */ + private $suffixes = []; + + /** + * @var array + */ + private $prefixes = []; + + /** + * @var array + */ + private $exclude = []; + + public function __construct(string $basePath, \Iterator $iterator, array $suffixes = [], array $prefixes = [], array $exclude = []) + { + $this->basePath = realpath($basePath); + $this->prefixes = $prefixes; + $this->suffixes = $suffixes; + $this->exclude = array_filter(array_map('realpath', $exclude)); + + parent::__construct($iterator); + } + + public function accept(): bool + { + $current = $this->getInnerIterator()->current(); + $filename = $current->getFilename(); + $realPath = $current->getRealPath(); + + if ($realPath === false) { + return false; + } + + return $this->acceptPath($realPath) && + $this->acceptPrefix($filename) && + $this->acceptSuffix($filename); + } + + private function acceptPath(string $path): bool + { + // Filter files in hidden directories by checking path that is relative to the base path. + if (preg_match('=/\.[^/]*/=', str_replace($this->basePath, '', $path))) { + return false; + } + + foreach ($this->exclude as $exclude) { + if (strpos($path, $exclude) === 0) { + return false; + } + } + + return true; + } + + private function acceptPrefix(string $filename): bool + { + return $this->acceptSubString($filename, $this->prefixes, self::PREFIX); + } + + private function acceptSuffix(string $filename): bool + { + return $this->acceptSubString($filename, $this->suffixes, self::SUFFIX); + } + + private function acceptSubString(string $filename, array $subStrings, int $type): bool + { + if (empty($subStrings)) { + return true; + } + + $matched = false; + + foreach ($subStrings as $string) { + if (($type === self::PREFIX && strpos($filename, $string) === 0) || + ($type === self::SUFFIX && + substr($filename, -1 * strlen($string)) === $string)) { + $matched = true; + + break; + } + } + + return $matched; + } +} diff --git a/vendor/phpunit/php-invoker/ChangeLog.md b/vendor/phpunit/php-invoker/ChangeLog.md new file mode 100644 index 00000000..15cff1f1 --- /dev/null +++ b/vendor/phpunit/php-invoker/ChangeLog.md @@ -0,0 +1,48 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [3.1.1] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [3.1.0] - 2020-08-06 + +### Changed + +* [#14](https://github.com/sebastianbergmann/php-invoker/pull/14): Clear alarm in `finally` block + +## [3.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [3.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [3.0.0] - 2020-02-07 + +### Added + +* Added `canInvokeWithTimeout()` method to check requirements for the functionality provided by this component to work + +### Changed + +* Moved `"ext-pcntl": "*"` requirement from `require` to `suggest` so that this component can be installed even if `ext/pcntl` is not available +* `invoke()` now raises an exception when the requirements for the functionality provided by this component to work are not met + +### Removed + +* This component is no longer supported on PHP 7.1 and PHP 7.2 + +[3.1.1]: https://github.com/sebastianbergmann/php-invoker/compare/3.1.0...3.1.1 +[3.1.0]: https://github.com/sebastianbergmann/php-invoker/compare/3.0.2...3.1.0 +[3.0.2]: https://github.com/sebastianbergmann/php-invoker/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/php-invoker/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/php-invoker/compare/2.0.0...3.0.0 diff --git a/vendor/phpunit/php-invoker/LICENSE b/vendor/phpunit/php-invoker/LICENSE new file mode 100644 index 00000000..4620776e --- /dev/null +++ b/vendor/phpunit/php-invoker/LICENSE @@ -0,0 +1,33 @@ +php-invoker + +Copyright (c) 2011-2020, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/phpunit/php-invoker/README.md b/vendor/phpunit/php-invoker/README.md new file mode 100644 index 00000000..ace07e5f --- /dev/null +++ b/vendor/phpunit/php-invoker/README.md @@ -0,0 +1,18 @@ +# phpunit/php-invoker + +[![CI Status](https://github.com/sebastianbergmann/php-invoker/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/php-invoker/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/php-invoker/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/php-invoker) + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require phpunit/php-invoker +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev phpunit/php-invoker +``` diff --git a/vendor/phpunit/php-invoker/composer.json b/vendor/phpunit/php-invoker/composer.json new file mode 100644 index 00000000..6c007cd8 --- /dev/null +++ b/vendor/phpunit/php-invoker/composer.json @@ -0,0 +1,54 @@ +{ + "name": "phpunit/php-invoker", + "description": "Invoke callables with a timeout", + "type": "library", + "keywords": [ + "process" + ], + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues" + }, + "prefer-stable": true, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture/" + ] + }, + "suggest": { + "ext-pcntl": "*" + }, + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + } +} + diff --git a/vendor/phpunit/php-invoker/src/Invoker.php b/vendor/phpunit/php-invoker/src/Invoker.php new file mode 100644 index 00000000..656f4180 --- /dev/null +++ b/vendor/phpunit/php-invoker/src/Invoker.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Invoker; + +use const SIGALRM; +use function call_user_func_array; +use function function_exists; +use function pcntl_alarm; +use function pcntl_async_signals; +use function pcntl_signal; +use function sprintf; +use Throwable; + +final class Invoker +{ + /** + * @var int + */ + private $timeout; + + /** + * @throws Throwable + */ + public function invoke(callable $callable, array $arguments, int $timeout) + { + if (!$this->canInvokeWithTimeout()) { + throw new ProcessControlExtensionNotLoadedException( + 'The pcntl (process control) extension for PHP is required' + ); + } + + pcntl_signal( + SIGALRM, + function (): void { + throw new TimeoutException( + sprintf( + 'Execution aborted after %d second%s', + $this->timeout, + $this->timeout === 1 ? '' : 's' + ) + ); + }, + true + ); + + $this->timeout = $timeout; + + pcntl_async_signals(true); + pcntl_alarm($timeout); + + try { + return call_user_func_array($callable, $arguments); + } finally { + pcntl_alarm(0); + } + } + + public function canInvokeWithTimeout(): bool + { + return function_exists('pcntl_signal') && function_exists('pcntl_async_signals') && function_exists('pcntl_alarm'); + } +} diff --git a/vendor/phpunit/php-invoker/src/exceptions/Exception.php b/vendor/phpunit/php-invoker/src/exceptions/Exception.php new file mode 100644 index 00000000..6ecbf5dd --- /dev/null +++ b/vendor/phpunit/php-invoker/src/exceptions/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Invoker; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php b/vendor/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php new file mode 100644 index 00000000..ef42fd19 --- /dev/null +++ b/vendor/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Invoker; + +use RuntimeException; + +final class ProcessControlExtensionNotLoadedException extends RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/php-invoker/src/exceptions/TimeoutException.php b/vendor/phpunit/php-invoker/src/exceptions/TimeoutException.php new file mode 100644 index 00000000..2f7631c0 --- /dev/null +++ b/vendor/phpunit/php-invoker/src/exceptions/TimeoutException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Invoker; + +use RuntimeException; + +final class TimeoutException extends RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/php-text-template/.psalm/baseline.xml b/vendor/phpunit/php-text-template/.psalm/baseline.xml new file mode 100644 index 00000000..77e688e0 --- /dev/null +++ b/vendor/phpunit/php-text-template/.psalm/baseline.xml @@ -0,0 +1,2 @@ + + diff --git a/vendor/phpunit/php-text-template/.psalm/config.xml b/vendor/phpunit/php-text-template/.psalm/config.xml new file mode 100644 index 00000000..2a4b16f2 --- /dev/null +++ b/vendor/phpunit/php-text-template/.psalm/config.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/vendor/phpunit/php-text-template/ChangeLog.md b/vendor/phpunit/php-text-template/ChangeLog.md new file mode 100644 index 00000000..32a48a7a --- /dev/null +++ b/vendor/phpunit/php-text-template/ChangeLog.md @@ -0,0 +1,43 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [2.0.4] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\Template\Exception` now correctly extends `\Throwable` + +## [2.0.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [2.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [2.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [2.0.0] - 2020-02-07 + +### Changed + +* The `Text_Template` class was renamed to `SebastianBergmann\Template\Template` + +### Removed + +* Removed support for PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, PHP 7.0, PHP 7.1, and PHP 7.2 + +[2.0.4]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.3...2.0.4 +[2.0.3]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.2...2.0.3 +[2.0.2]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/php-text-template/compare/1.2.1...2.0.0 diff --git a/vendor/phpunit/php-text-template/LICENSE b/vendor/phpunit/php-text-template/LICENSE new file mode 100644 index 00000000..6db5566c --- /dev/null +++ b/vendor/phpunit/php-text-template/LICENSE @@ -0,0 +1,33 @@ +phpunit/php-text-template + +Copyright (c) 2009-2020, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/phpunit/php-text-template/README.md b/vendor/phpunit/php-text-template/README.md new file mode 100644 index 00000000..b2865935 --- /dev/null +++ b/vendor/phpunit/php-text-template/README.md @@ -0,0 +1,12 @@ +# Text_Template + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + + composer require phpunit/php-text-template + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + + composer require --dev phpunit/php-text-template + diff --git a/vendor/phpunit/php-text-template/composer.json b/vendor/phpunit/php-text-template/composer.json new file mode 100644 index 00000000..a51b34b9 --- /dev/null +++ b/vendor/phpunit/php-text-template/composer.json @@ -0,0 +1,43 @@ +{ + "name": "phpunit/php-text-template", + "description": "Simple template engine.", + "type": "library", + "keywords": [ + "template" + ], + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues" + }, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + } +} diff --git a/vendor/phpunit/php-text-template/src/Template.php b/vendor/phpunit/php-text-template/src/Template.php new file mode 100644 index 00000000..25e29ea9 --- /dev/null +++ b/vendor/phpunit/php-text-template/src/Template.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Template; + +use function array_merge; +use function file_exists; +use function file_get_contents; +use function file_put_contents; +use function sprintf; +use function str_replace; + +final class Template +{ + /** + * @var string + */ + private $template = ''; + + /** + * @var string + */ + private $openDelimiter; + + /** + * @var string + */ + private $closeDelimiter; + + /** + * @var array + */ + private $values = []; + + /** + * @throws InvalidArgumentException + */ + public function __construct(string $file = '', string $openDelimiter = '{', string $closeDelimiter = '}') + { + $this->setFile($file); + + $this->openDelimiter = $openDelimiter; + $this->closeDelimiter = $closeDelimiter; + } + + /** + * @throws InvalidArgumentException + */ + public function setFile(string $file): void + { + $distFile = $file . '.dist'; + + if (file_exists($file)) { + $this->template = file_get_contents($file); + } elseif (file_exists($distFile)) { + $this->template = file_get_contents($distFile); + } else { + throw new InvalidArgumentException( + sprintf( + 'Failed to load template "%s"', + $file + ) + ); + } + } + + public function setVar(array $values, bool $merge = true): void + { + if (!$merge || empty($this->values)) { + $this->values = $values; + } else { + $this->values = array_merge($this->values, $values); + } + } + + public function render(): string + { + $keys = []; + + foreach ($this->values as $key => $value) { + $keys[] = $this->openDelimiter . $key . $this->closeDelimiter; + } + + return str_replace($keys, $this->values, $this->template); + } + + /** + * @codeCoverageIgnore + */ + public function renderTo(string $target): void + { + if (!file_put_contents($target, $this->render())) { + throw new RuntimeException( + sprintf( + 'Writing rendered result to "%s" failed', + $target + ) + ); + } + } +} diff --git a/vendor/phpunit/php-text-template/src/exceptions/Exception.php b/vendor/phpunit/php-text-template/src/exceptions/Exception.php new file mode 100644 index 00000000..d7dc5cbe --- /dev/null +++ b/vendor/phpunit/php-text-template/src/exceptions/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Template; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php b/vendor/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php new file mode 100644 index 00000000..10e1cd11 --- /dev/null +++ b/vendor/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Template; + +final class InvalidArgumentException extends \InvalidArgumentException implements Exception +{ +} diff --git a/vendor/phpunit/php-text-template/src/exceptions/RuntimeException.php b/vendor/phpunit/php-text-template/src/exceptions/RuntimeException.php new file mode 100644 index 00000000..131498e6 --- /dev/null +++ b/vendor/phpunit/php-text-template/src/exceptions/RuntimeException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Template; + +use InvalidArgumentException; + +final class RuntimeException extends InvalidArgumentException implements Exception +{ +} diff --git a/vendor/phpunit/php-timer/.psalm/baseline.xml b/vendor/phpunit/php-timer/.psalm/baseline.xml new file mode 100644 index 00000000..77e688e0 --- /dev/null +++ b/vendor/phpunit/php-timer/.psalm/baseline.xml @@ -0,0 +1,2 @@ + + diff --git a/vendor/phpunit/php-timer/.psalm/config.xml b/vendor/phpunit/php-timer/.psalm/config.xml new file mode 100644 index 00000000..15abef05 --- /dev/null +++ b/vendor/phpunit/php-timer/.psalm/config.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/vendor/phpunit/php-timer/ChangeLog.md b/vendor/phpunit/php-timer/ChangeLog.md new file mode 100644 index 00000000..34ef7d1d --- /dev/null +++ b/vendor/phpunit/php-timer/ChangeLog.md @@ -0,0 +1,138 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [5.0.3] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\Timer\Exception` now correctly extends `\Throwable` + +## [5.0.2] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [5.0.1] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [5.0.0] - 2020-06-07 + +### Changed + +* Parameter type for `SebastianBergmann\Timer\Duration::fromMicroseconds()` was changed from `int` to `float` +* Parameter type for `SebastianBergmann\Timer\Duration::fromNanoseconds()` was changed from `int` to `float` +* Return type for `SebastianBergmann\Timer\Duration::asNanoseconds()` was changed from `int` to `float` + +### Fixed + +* [#31](https://github.com/sebastianbergmann/php-timer/issues/31): Type Error on 32-bit systems (where `hrtime()` returns `float` instead of `int`) + +## [4.0.0] - 2020-06-01 + +### Added + +* Introduced `Duration` value object for encapsulating a duration with nanosecond granularity +* Introduced `ResourceUsageFormatter` object for formatting resource usage with option to explicitly pass a duration (instead of looking at the unreliable `$_SERVER['REQUEST_TIME_FLOAT']` variable) + +### Changed + +* The methods of `Timer` are no longer static +* `Timer::stop()` now returns a `Duration` value object + +### Removed + +* Functionality that is now implemented in `Duration` and `ResourceUsageFormatter` has been removed from `Timer` + +## [3.1.4] - 2020-04-20 + +### Changed + +* `Timer::timeSinceStartOfRequest()` no longer tries `$_SERVER['REQUEST_TIME']` when `$_SERVER['REQUEST_TIME_FLOAT']` is not available (`$_SERVER['REQUEST_TIME_FLOAT']` was added in PHP 5.4 and this library requires PHP 7.3) +* Improved exception messages when `$_SERVER['REQUEST_TIME_FLOAT']` is not set or is not of type `float` + +### Changed + +## [3.1.3] - 2020-04-20 + +### Changed + +* `Timer::timeSinceStartOfRequest()` now raises an exception if `$_SERVER['REQUEST_TIME_FLOAT']` does not contain a `float` (or `$_SERVER['REQUEST_TIME']` does not contain an `int`) + +## [3.1.2] - 2020-04-17 + +### Changed + +* Improved the fix for [#30](https://github.com/sebastianbergmann/php-timer/issues/30) and restored usage of `hrtime()` + +## [3.1.1] - 2020-04-17 + +### Fixed + +* [#30](https://github.com/sebastianbergmann/php-timer/issues/30): Resolution of time returned by `Timer::stop()` is different than before (this reverts using `hrtime()` instead of `microtime()`) + +## [3.1.0] - 2020-04-17 + +### Added + +* `Timer::secondsToShortTimeString()` as alternative to `Timer::secondsToTimeString()` + +### Changed + +* `Timer::start()` and `Timer::stop()` now use `hrtime()` (high resolution monotonic timer) instead of `microtime()` +* `Timer::timeSinceStartOfRequest()` now uses `Timer::secondsToShortTimeString()` for time formatting +* Improved formatting of `Timer::secondsToTimeString()` result + +## [3.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.1 and PHP 7.2 + +## [2.1.2] - 2019-06-07 + +### Fixed + +* [#21](https://github.com/sebastianbergmann/php-timer/pull/21): Formatting of memory consumption does not work on 32bit systems + +## [2.1.1] - 2019-02-20 + +### Changed + +* Improved formatting of memory consumption for `resourceUsage()` + +## [2.1.0] - 2019-02-20 + +### Changed + +* Improved formatting of memory consumption for `resourceUsage()` + +## [2.0.0] - 2018-02-01 + +### Changed + +* This component now uses namespaces + +### Removed + +* This component is no longer supported on PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, and PHP 7.0 + +[5.0.3]: https://github.com/sebastianbergmann/php-timer/compare/5.0.2...5.0.3 +[5.0.2]: https://github.com/sebastianbergmann/php-timer/compare/5.0.1...5.0.2 +[5.0.1]: https://github.com/sebastianbergmann/php-timer/compare/5.0.0...5.0.1 +[5.0.0]: https://github.com/sebastianbergmann/php-timer/compare/4.0.0...5.0.0 +[4.0.0]: https://github.com/sebastianbergmann/php-timer/compare/3.1.4...4.0.0 +[3.1.4]: https://github.com/sebastianbergmann/php-timer/compare/3.1.3...3.1.4 +[3.1.3]: https://github.com/sebastianbergmann/php-timer/compare/3.1.2...3.1.3 +[3.1.2]: https://github.com/sebastianbergmann/php-timer/compare/3.1.1...3.1.2 +[3.1.1]: https://github.com/sebastianbergmann/php-timer/compare/3.1.0...3.1.1 +[3.1.0]: https://github.com/sebastianbergmann/php-timer/compare/3.0.0...3.1.0 +[3.0.0]: https://github.com/sebastianbergmann/php-timer/compare/2.1.2...3.0.0 +[2.1.2]: https://github.com/sebastianbergmann/php-timer/compare/2.1.1...2.1.2 +[2.1.1]: https://github.com/sebastianbergmann/php-timer/compare/2.1.0...2.1.1 +[2.1.0]: https://github.com/sebastianbergmann/php-timer/compare/2.0.0...2.1.0 +[2.0.0]: https://github.com/sebastianbergmann/php-timer/compare/1.0.9...2.0.0 diff --git a/vendor/phpunit/php-timer/LICENSE b/vendor/phpunit/php-timer/LICENSE new file mode 100644 index 00000000..4193d8ae --- /dev/null +++ b/vendor/phpunit/php-timer/LICENSE @@ -0,0 +1,33 @@ +phpunit/php-timer + +Copyright (c) 2010-2020, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/phpunit/php-timer/README.md b/vendor/phpunit/php-timer/README.md new file mode 100644 index 00000000..a7d1e70d --- /dev/null +++ b/vendor/phpunit/php-timer/README.md @@ -0,0 +1,104 @@ +# phpunit/php-timer + +[![CI Status](https://github.com/sebastianbergmann/php-timer/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/php-timer/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/php-timer/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/php-timer) + +Utility class for timing things, factored out of PHPUnit into a stand-alone component. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require phpunit/php-timer +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev phpunit/php-timer +``` + +## Usage + +### Basic Timing + +```php +require __DIR__ . '/vendor/autoload.php'; + +use SebastianBergmann\Timer\Timer; + +$timer = new Timer; + +$timer->start(); + +foreach (\range(0, 100000) as $i) { + // ... +} + +$duration = $timer->stop(); + +var_dump(get_class($duration)); +var_dump($duration->asString()); +var_dump($duration->asSeconds()); +var_dump($duration->asMilliseconds()); +var_dump($duration->asMicroseconds()); +var_dump($duration->asNanoseconds()); +``` + +The code above yields the output below: + +``` +string(32) "SebastianBergmann\Timer\Duration" +string(9) "00:00.002" +float(0.002851062) +float(2.851062) +float(2851.062) +int(2851062) +``` + +### Resource Consumption + +#### Explicit duration + +```php +require __DIR__ . '/vendor/autoload.php'; + +use SebastianBergmann\Timer\ResourceUsageFormatter; +use SebastianBergmann\Timer\Timer; + +$timer = new Timer; +$timer->start(); + +foreach (\range(0, 100000) as $i) { + // ... +} + +print (new ResourceUsageFormatter)->resourceUsage($timer->stop()); +``` + +The code above yields the output below: + +``` +Time: 00:00.002, Memory: 6.00 MB +``` + +#### Duration since PHP Startup (using unreliable `$_SERVER['REQUEST_TIME_FLOAT']`) + +```php +require __DIR__ . '/vendor/autoload.php'; + +use SebastianBergmann\Timer\ResourceUsageFormatter; + +foreach (\range(0, 100000) as $i) { + // ... +} + +print (new ResourceUsageFormatter)->resourceUsageSinceStartOfRequest(); +``` + +The code above yields the output below: + +``` +Time: 00:00.002, Memory: 6.00 MB +``` diff --git a/vendor/phpunit/php-timer/composer.json b/vendor/phpunit/php-timer/composer.json new file mode 100644 index 00000000..001701c2 --- /dev/null +++ b/vendor/phpunit/php-timer/composer.json @@ -0,0 +1,45 @@ +{ + "name": "phpunit/php-timer", + "description": "Utility class for timing", + "type": "library", + "keywords": [ + "timer" + ], + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues" + }, + "prefer-stable": true, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} + diff --git a/vendor/phpunit/php-timer/src/Duration.php b/vendor/phpunit/php-timer/src/Duration.php new file mode 100644 index 00000000..e52bf018 --- /dev/null +++ b/vendor/phpunit/php-timer/src/Duration.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Timer; + +use function floor; +use function sprintf; + +/** + * @psalm-immutable + */ +final class Duration +{ + /** + * @var float + */ + private $nanoseconds; + + /** + * @var int + */ + private $hours; + + /** + * @var int + */ + private $minutes; + + /** + * @var int + */ + private $seconds; + + /** + * @var int + */ + private $milliseconds; + + public static function fromMicroseconds(float $microseconds): self + { + return new self($microseconds * 1000); + } + + public static function fromNanoseconds(float $nanoseconds): self + { + return new self($nanoseconds); + } + + private function __construct(float $nanoseconds) + { + $this->nanoseconds = $nanoseconds; + $timeInMilliseconds = $nanoseconds / 1000000; + $hours = floor($timeInMilliseconds / 60 / 60 / 1000); + $hoursInMilliseconds = $hours * 60 * 60 * 1000; + $minutes = floor($timeInMilliseconds / 60 / 1000) % 60; + $minutesInMilliseconds = $minutes * 60 * 1000; + $seconds = floor(($timeInMilliseconds - $hoursInMilliseconds - $minutesInMilliseconds) / 1000); + $secondsInMilliseconds = $seconds * 1000; + $milliseconds = $timeInMilliseconds - $hoursInMilliseconds - $minutesInMilliseconds - $secondsInMilliseconds; + $this->hours = (int) $hours; + $this->minutes = $minutes; + $this->seconds = (int) $seconds; + $this->milliseconds = (int) $milliseconds; + } + + public function asNanoseconds(): float + { + return $this->nanoseconds; + } + + public function asMicroseconds(): float + { + return $this->nanoseconds / 1000; + } + + public function asMilliseconds(): float + { + return $this->nanoseconds / 1000000; + } + + public function asSeconds(): float + { + return $this->nanoseconds / 1000000000; + } + + public function asString(): string + { + $result = ''; + + if ($this->hours > 0) { + $result = sprintf('%02d', $this->hours) . ':'; + } + + $result .= sprintf('%02d', $this->minutes) . ':'; + $result .= sprintf('%02d', $this->seconds); + + if ($this->milliseconds > 0) { + $result .= '.' . sprintf('%03d', $this->milliseconds); + } + + return $result; + } +} diff --git a/vendor/phpunit/php-timer/src/ResourceUsageFormatter.php b/vendor/phpunit/php-timer/src/ResourceUsageFormatter.php new file mode 100644 index 00000000..ad792627 --- /dev/null +++ b/vendor/phpunit/php-timer/src/ResourceUsageFormatter.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Timer; + +use function is_float; +use function memory_get_peak_usage; +use function microtime; +use function sprintf; + +final class ResourceUsageFormatter +{ + /** + * @psalm-var array + */ + private const SIZES = [ + 'GB' => 1073741824, + 'MB' => 1048576, + 'KB' => 1024, + ]; + + public function resourceUsage(Duration $duration): string + { + return sprintf( + 'Time: %s, Memory: %s', + $duration->asString(), + $this->bytesToString(memory_get_peak_usage(true)) + ); + } + + /** + * @throws TimeSinceStartOfRequestNotAvailableException + */ + public function resourceUsageSinceStartOfRequest(): string + { + if (!isset($_SERVER['REQUEST_TIME_FLOAT'])) { + throw new TimeSinceStartOfRequestNotAvailableException( + 'Cannot determine time at which the request started because $_SERVER[\'REQUEST_TIME_FLOAT\'] is not available' + ); + } + + if (!is_float($_SERVER['REQUEST_TIME_FLOAT'])) { + throw new TimeSinceStartOfRequestNotAvailableException( + 'Cannot determine time at which the request started because $_SERVER[\'REQUEST_TIME_FLOAT\'] is not of type float' + ); + } + + return $this->resourceUsage( + Duration::fromMicroseconds( + (1000000 * (microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'])) + ) + ); + } + + private function bytesToString(int $bytes): string + { + foreach (self::SIZES as $unit => $value) { + if ($bytes >= $value) { + return sprintf('%.2f %s', $bytes >= 1024 ? $bytes / $value : $bytes, $unit); + } + } + + // @codeCoverageIgnoreStart + return $bytes . ' byte' . ($bytes !== 1 ? 's' : ''); + // @codeCoverageIgnoreEnd + } +} diff --git a/vendor/phpunit/php-timer/src/Timer.php b/vendor/phpunit/php-timer/src/Timer.php new file mode 100644 index 00000000..0917109b --- /dev/null +++ b/vendor/phpunit/php-timer/src/Timer.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Timer; + +use function array_pop; +use function hrtime; + +final class Timer +{ + /** + * @psalm-var list + */ + private $startTimes = []; + + public function start(): void + { + $this->startTimes[] = (float) hrtime(true); + } + + /** + * @throws NoActiveTimerException + */ + public function stop(): Duration + { + if (empty($this->startTimes)) { + throw new NoActiveTimerException( + 'Timer::start() has to be called before Timer::stop()' + ); + } + + return Duration::fromNanoseconds((float) hrtime(true) - array_pop($this->startTimes)); + } +} diff --git a/vendor/phpunit/php-timer/src/exceptions/Exception.php b/vendor/phpunit/php-timer/src/exceptions/Exception.php new file mode 100644 index 00000000..996da086 --- /dev/null +++ b/vendor/phpunit/php-timer/src/exceptions/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Timer; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/phpunit/php-timer/src/exceptions/NoActiveTimerException.php b/vendor/phpunit/php-timer/src/exceptions/NoActiveTimerException.php new file mode 100644 index 00000000..40fe45e8 --- /dev/null +++ b/vendor/phpunit/php-timer/src/exceptions/NoActiveTimerException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Timer; + +use LogicException; + +final class NoActiveTimerException extends LogicException implements Exception +{ +} diff --git a/vendor/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php b/vendor/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php new file mode 100644 index 00000000..a2d94ce8 --- /dev/null +++ b/vendor/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Timer; + +use RuntimeException; + +final class TimeSinceStartOfRequestNotAvailableException extends RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/phpunit/.phpstorm.meta.php b/vendor/phpunit/phpunit/.phpstorm.meta.php new file mode 100644 index 00000000..b69ff789 --- /dev/null +++ b/vendor/phpunit/phpunit/.phpstorm.meta.php @@ -0,0 +1,33 @@ +"$0"]) + ); + + override( + \PHPUnit\Framework\TestCase::createStub(0), + map([""=>"$0"]) + ); + + override( + \PHPUnit\Framework\TestCase::createConfiguredMock(0), + map([""=>"$0"]) + ); + + override( + \PHPUnit\Framework\TestCase::createPartialMock(0), + map([""=>"$0"]) + ); + + override( + \PHPUnit\Framework\TestCase::createTestProxy(0), + map([""=>"$0"]) + ); + + override( + \PHPUnit\Framework\TestCase::getMockForAbstractClass(0), + map([""=>"$0"]) + ); +} diff --git a/vendor/phpunit/phpunit/ChangeLog-8.5.md b/vendor/phpunit/phpunit/ChangeLog-8.5.md new file mode 100644 index 00000000..6485b8e5 --- /dev/null +++ b/vendor/phpunit/phpunit/ChangeLog-8.5.md @@ -0,0 +1,297 @@ +# Changes in PHPUnit 8.5 + +All notable changes of the PHPUnit 8.5 release series are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [8.5.32] - 2023-01-26 + +### Fixed + +* [#5120](https://github.com/sebastianbergmann/phpunit/issues/5120): Test Runner incorrectly treats `--testsuite` and `--list-tests` as not combinable options + +## [8.5.31] - 2022-10-28 + +### Fixed + +* [#5076](https://github.com/sebastianbergmann/phpunit/issues/5076): Test Runner does not warn about conflicting options + +## [8.5.30] - 2022-09-25 + +### Changed + +* The configuration generator now asks for a cache directory + +### Fixed + +* [#4913](https://github.com/sebastianbergmann/phpunit/issues/4913): Failed `assert()` should show a backtrace +* [#4966](https://github.com/sebastianbergmann/phpunit/issues/4966): `TestCase::assertSame()` (and related exact comparisons) must compare `float` exactly + +## [8.5.29] - 2022-08-22 + +### Changed + +* [#5033](https://github.com/sebastianbergmann/phpunit/issues/5033): Do not depend on phpspec/prophecy + +## [8.5.28] - 2022-07-29 + +### Fixed + +* [#5015](https://github.com/sebastianbergmann/phpunit/pull/5015): Ukraine banner unreadable on black background +* [#5016](https://github.com/sebastianbergmann/phpunit/issues/5016): PHPUnit 8.5.27 does not work on PHP 7.2.0-7.2.18 and PHP 7.3.0-7.3.5 + +## [8.5.27] - 2022-06-19 + +### Fixed + +* [#4950](https://github.com/sebastianbergmann/phpunit/issues/4950): False error on `atMost()` invocation rule without call +* [#4962](https://github.com/sebastianbergmann/phpunit/issues/4962): Ukraine banner unreadable on white background + +## [8.5.26] - 2022-04-01 + +### Fixed + +* [#4938](https://github.com/sebastianbergmann/phpunit/issues/4938): Test Double code generator does not handle `void` return type declaration on `__clone()` methods + +## [8.5.25] - 2022-03-16 + +### Fixed + +* [#4934](https://github.com/sebastianbergmann/phpunit/issues/4934): Code Coverage does not work with PHPUnit 8.5.24 PHAR on PHP 7 + +## [8.5.24] - 2022-03-05 - #StandWithUkraine + +### Changed + +* [#4874](https://github.com/sebastianbergmann/phpunit/pull/4874): `PHP_FLOAT_EPSILON` is now used instead of hardcoded `0.0000000001` in `PHPUnit\Framework\Constraint\IsIdentical` + +### Fixed + +* When the HTML code coverage report's configured low upper bound is larger than the high lower bound then the default values are used instead + +## [8.5.23] - 2022-01-21 + +### Fixed + +* [#4799](https://github.com/sebastianbergmann/phpunit/pull/4799): Memory leaks in `PHPUnit\Framework\TestSuite` class +* [#4857](https://github.com/sebastianbergmann/phpunit/pull/4857): Result of `debug_backtrace()` is not used correctly + +## [8.5.22] - 2021-12-25 + +### Changed + +* [#4812](https://github.com/sebastianbergmann/phpunit/issues/4812): Do not enforce time limits when a debugging session through DBGp is active +* [#4835](https://github.com/sebastianbergmann/phpunit/issues/4835): Support for `$GLOBALS['_composer_autoload_path']` introduced in Composer 2.2 + +### Fixed + +* [#4840](https://github.com/sebastianbergmann/phpunit/pull/4840): TestDox prettifying for class names does not correctly handle diacritics +* [#4846](https://github.com/sebastianbergmann/phpunit/pull/4846): Composer proxy script is not ignored + +## [8.5.21] - 2021-09-25 + +### Changed + +* PHPUnit no longer converts PHP deprecations to exceptions by default (configure `convertDeprecationsToExceptions="true"` to enable this) +* The PHPUnit XML configuration file generator now configures `convertDeprecationsToExceptions="true"` + +### Fixed + +* [#4772](https://github.com/sebastianbergmann/phpunit/pull/4772): TestDox HTML report not displayed correctly when browser has custom colour settings + +## [8.5.20] - 2021-08-31 + +### Fixed + +* [#4751](https://github.com/sebastianbergmann/phpunit/issues/4751): Configuration validation fails when using brackets in glob pattern + +## [8.5.19] - 2021-07-31 + +### Fixed + +* [#4740](https://github.com/sebastianbergmann/phpunit/issues/4740): `phpunit.phar` does not work with PHP 8.1 + +## [8.5.18] - 2021-07-19 + +### Fixed + +* [#4720](https://github.com/sebastianbergmann/phpunit/issues/4720): PHPUnit does not verify its own PHP extension requirements + +## [8.5.17] - 2021-06-23 + +### Changed + +* PHPUnit now errors out on startup when `PHP_VERSION` contains a value that is not compatible with `version_compare()`, for instance `X.Y.Z-(to be removed in future macOS)` + +## [8.5.16] - 2021-06-05 + +### Changed + +* The test result cache (the storage for which is implemented in `PHPUnit\Runner\DefaultTestResultCache`) no longer uses PHP's `serialize()` and `unserialize()` functions for persistence. It now uses a versioned JSON format instead that is independent of PHP implementation details (see [#3581](https://github.com/sebastianbergmann/phpunit/issues/3581) and [#4662](https://github.com/sebastianbergmann/phpunit/pull/4662) for examples why this is a problem). When PHPUnit tries to load the test result cache from a file that does not exist, or from a file that does not contain data in JSON format, or from a file that contains data in a JSON format version other than the one used by the currently running PHPUnit version, then this is considered to be a "cache miss". An empty `DefaultTestResultCache` object is created in this case. This should also prevent PHPUnit from crashing when trying to load a test result cache file created by a different version of PHPUnit (see [#4580](https://github.com/sebastianbergmann/phpunit/issues/4580) for example). + +### Fixed + +* [#4663](https://github.com/sebastianbergmann/phpunit/issues/4663): `TestCase::expectError()` works on PHP 7.3, but not on PHP >= 7.4 +* [#4678](https://github.com/sebastianbergmann/phpunit/pull/4678): Stubbed methods with `iterable` return types should return empty array by default +* [#4692](https://github.com/sebastianbergmann/phpunit/issues/4692): Annotations in single-line doc-comments are not handled correctly +* [#4694](https://github.com/sebastianbergmann/phpunit/issues/4694): `TestCase::getMockFromWsdl()` does not work with PHP 8.1-dev + +## [8.5.15] - 2021-03-17 + +### Fixed + +* [#4591](https://github.com/sebastianbergmann/phpunit/issues/4591): TeamCity logger logs warnings as test failures + +## [8.5.14] - 2021-01-17 + +### Fixed + +* [#4535](https://github.com/sebastianbergmann/phpunit/issues/4535): `getMockFromWsdl()` does not handle methods that do not have parameters correctly +* [#4572](https://github.com/sebastianbergmann/phpunit/issues/4572): Schema validation does not work with `%xx` sequences in path to `phpunit.xsd` +* [#4575](https://github.com/sebastianbergmann/phpunit/issues/4575): PHPUnit 8.5 incompatibility with PHP 8.1 + +## [8.5.13] - 2020-12-01 + +### Fixed + +* Running tests in isolated processes did not work with PHP 8 on Windows + +## [8.5.12] - 2020-11-30 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.2` to `>=7.2` to allow the installation of PHPUnit 8.5 on PHP 8. Please note that the code coverage functionality is not available for PHPUnit 8.5 on PHP 8. + +### Fixed + +* [#4529](https://github.com/sebastianbergmann/phpunit/issues/4529): Debug mode of Xdebug 2 is not disabled for PHPT tests + +## [8.5.11] - 2020-11-27 + +### Changed + +* Bumped required version of `phpunit/php-code-coverage` + +## [8.5.10] - 2020-11-27 + +### Added + +* Support for Xdebug 3 + +### Fixed + +* [#4516](https://github.com/sebastianbergmann/phpunit/issues/4516): `phpunit/phpunit-selenium` does not work with PHPUnit 8.5.9 + +## [8.5.9] - 2020-11-10 + +### Fixed + +* [#3965](https://github.com/sebastianbergmann/phpunit/issues/3965): Process Isolation throws exceptions when PHPDBG is used +* [#4470](https://github.com/sebastianbergmann/phpunit/pull/4470): Infinite recursion when `--static-backup --strict-global-state` is used + +## [8.5.8] - 2020-06-22 + +### Fixed + +* [#4312](https://github.com/sebastianbergmann/phpunit/issues/4312): Fix for [#4299](https://github.com/sebastianbergmann/phpunit/issues/4299) breaks backward compatibility + +## [8.5.7] - 2020-06-21 + +### Fixed + +* [#4299](https://github.com/sebastianbergmann/phpunit/issues/4299): "No tests executed" does not always result in exit code `1` +* [#4306](https://github.com/sebastianbergmann/phpunit/issues/4306): Exceptions during code coverage driver initialization are not handled correctly + +## [8.5.6] - 2020-06-15 + +### Fixed + +* [#4211](https://github.com/sebastianbergmann/phpunit/issues/4211): `phpdbg_*()` functions are scoped to `PHPUnit\phpdbg_*()` + +## [8.5.5] - 2020-05-22 + +### Fixed + +* [#4033](https://github.com/sebastianbergmann/phpunit/issues/4033): Unexpected behaviour when `$GLOBALS` is deleted + +## [8.5.4] - 2020-04-23 + +### Changed + +* Changed how `PHPUnit\TextUI\Command` passes warnings to `PHPUnit\TextUI\TestRunner` + +## [8.5.3] - 2020-03-31 + +### Fixed + +* [#4017](https://github.com/sebastianbergmann/phpunit/issues/4017): Do not suggest refactoring to something that is also deprecated +* [#4133](https://github.com/sebastianbergmann/phpunit/issues/4133): `expectExceptionMessageRegExp()` has been removed in PHPUnit 9 without a deprecation warning being given in PHPUnit 8 +* [#4139](https://github.com/sebastianbergmann/phpunit/issues/4139): Cannot double interfaces that declare a constructor with PHP 8 +* [#4144](https://github.com/sebastianbergmann/phpunit/issues/4144): Empty objects are converted to empty arrays in JSON comparison failure diff + +## [8.5.2] - 2020-01-08 + +### Removed + +* `eval-stdin.php` has been removed, it was not used anymore since PHPUnit 7.2.7 + +## [8.5.1] - 2019-12-25 + +### Changed + +* `eval-stdin.php` can now only be executed with `cli` and `phpdbg` + +### Fixed + +* [#3983](https://github.com/sebastianbergmann/phpunit/issues/3983): Deprecation warning given too eagerly + +## [8.5.0] - 2019-12-06 + +### Added + +* [#3911](https://github.com/sebastianbergmann/phpunit/issues/3911): Support combined use of `addMethods()` and `onlyMethods()` +* [#3949](https://github.com/sebastianbergmann/phpunit/issues/3949): Introduce specialized assertions `assertFileEqualsCanonicalizing()`, `assertFileEqualsIgnoringCase()`, `assertStringEqualsFileCanonicalizing()`, `assertStringEqualsFileIgnoringCase()`, `assertFileNotEqualsCanonicalizing()`, `assertFileNotEqualsIgnoringCase()`, `assertStringNotEqualsFileCanonicalizing()`, and `assertStringNotEqualsFileIgnoringCase()` as alternative to using `assertFileEquals()` etc. with optional parameters + +### Changed + +* [#3860](https://github.com/sebastianbergmann/phpunit/pull/3860): Deprecate invoking PHPUnit commandline test runner with just a class name +* [#3950](https://github.com/sebastianbergmann/phpunit/issues/3950): Deprecate optional parameters of `assertFileEquals()` etc. +* [#3955](https://github.com/sebastianbergmann/phpunit/issues/3955): Deprecate support for doubling multiple interfaces + +### Fixed + +* [#3953](https://github.com/sebastianbergmann/phpunit/issues/3953): Code Coverage for test executed in isolation does not work when the PHAR is used +* [#3967](https://github.com/sebastianbergmann/phpunit/issues/3967): Cannot double interface that extends interface that extends `\Throwable` +* [#3968](https://github.com/sebastianbergmann/phpunit/pull/3968): Test class run in a separate PHP process are passing when `exit` called inside + +[8.5.32]: https://github.com/sebastianbergmann/phpunit/compare/8.5.31...8.5.32 +[8.5.31]: https://github.com/sebastianbergmann/phpunit/compare/8.5.30...8.5.31 +[8.5.30]: https://github.com/sebastianbergmann/phpunit/compare/8.5.29...8.5.30 +[8.5.29]: https://github.com/sebastianbergmann/phpunit/compare/8.5.28...8.5.29 +[8.5.28]: https://github.com/sebastianbergmann/phpunit/compare/8.5.27...8.5.28 +[8.5.27]: https://github.com/sebastianbergmann/phpunit/compare/8.5.26...8.5.27 +[8.5.26]: https://github.com/sebastianbergmann/phpunit/compare/8.5.25...8.5.26 +[8.5.25]: https://github.com/sebastianbergmann/phpunit/compare/8.5.24...8.5.25 +[8.5.24]: https://github.com/sebastianbergmann/phpunit/compare/8.5.23...8.5.24 +[8.5.23]: https://github.com/sebastianbergmann/phpunit/compare/8.5.22...8.5.23 +[8.5.22]: https://github.com/sebastianbergmann/phpunit/compare/8.5.21...8.5.22 +[8.5.21]: https://github.com/sebastianbergmann/phpunit/compare/8.5.20...8.5.21 +[8.5.20]: https://github.com/sebastianbergmann/phpunit/compare/8.5.19...8.5.20 +[8.5.19]: https://github.com/sebastianbergmann/phpunit/compare/8.5.18...8.5.19 +[8.5.18]: https://github.com/sebastianbergmann/phpunit/compare/8.5.17...8.5.18 +[8.5.17]: https://github.com/sebastianbergmann/phpunit/compare/8.5.16...8.5.17 +[8.5.16]: https://github.com/sebastianbergmann/phpunit/compare/8.5.15...8.5.16 +[8.5.15]: https://github.com/sebastianbergmann/phpunit/compare/8.5.14...8.5.15 +[8.5.14]: https://github.com/sebastianbergmann/phpunit/compare/8.5.13...8.5.14 +[8.5.13]: https://github.com/sebastianbergmann/phpunit/compare/8.5.12...8.5.13 +[8.5.12]: https://github.com/sebastianbergmann/phpunit/compare/8.5.11...8.5.12 +[8.5.11]: https://github.com/sebastianbergmann/phpunit/compare/8.5.10...8.5.11 +[8.5.10]: https://github.com/sebastianbergmann/phpunit/compare/8.5.9...8.5.10 +[8.5.9]: https://github.com/sebastianbergmann/phpunit/compare/8.5.8...8.5.9 +[8.5.8]: https://github.com/sebastianbergmann/phpunit/compare/8.5.7...8.5.8 +[8.5.7]: https://github.com/sebastianbergmann/phpunit/compare/8.5.6...8.5.7 +[8.5.6]: https://github.com/sebastianbergmann/phpunit/compare/8.5.5...8.5.6 +[8.5.5]: https://github.com/sebastianbergmann/phpunit/compare/8.5.4...8.5.5 +[8.5.4]: https://github.com/sebastianbergmann/phpunit/compare/8.5.3...8.5.4 +[8.5.3]: https://github.com/sebastianbergmann/phpunit/compare/8.5.2...8.5.3 +[8.5.2]: https://github.com/sebastianbergmann/phpunit/compare/8.5.1...8.5.2 +[8.5.1]: https://github.com/sebastianbergmann/phpunit/compare/8.5.0...8.5.1 +[8.5.0]: https://github.com/sebastianbergmann/phpunit/compare/8.4.3...8.5.0 diff --git a/vendor/phpunit/phpunit/ChangeLog-9.6.md b/vendor/phpunit/phpunit/ChangeLog-9.6.md new file mode 100644 index 00000000..2491e303 --- /dev/null +++ b/vendor/phpunit/phpunit/ChangeLog-9.6.md @@ -0,0 +1,36 @@ +# Changes in PHPUnit 9.6 + +All notable changes of the PHPUnit 9.6 release series are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [9.6.3] - 2023-02-04 + +### Fixed + +* [#5164](https://github.com/sebastianbergmann/phpunit/issues/5164): `markTestSkipped()` not handled correctly when called in "before first test" method + +## [9.6.2] - 2023-02-04 + +### Fixed + +* [#4618](https://github.com/sebastianbergmann/phpunit/issues/4618): Support for generators in `assertCount()` etc. is not marked as deprecated in PHPUnit 9.6 + +## [9.6.1] - 2023-02-03 + +### Fixed + +* [#5073](https://github.com/sebastianbergmann/phpunit/issues/5073): `--no-extensions` CLI option only prevents extension PHARs from being loaded +* [#5160](https://github.com/sebastianbergmann/phpunit/issues/5160): PHPUnit 9.6 misses deprecations for assertions and constraints removed in PHPUnit 10 + +## [9.6.0] - 2023-02-03 + +### Changed + +* [#5062](https://github.com/sebastianbergmann/phpunit/issues/5062): Deprecate `expectDeprecation()`, `expectDeprecationMessage()`, `expectDeprecationMessageMatches()`, `expectError()`, `expectErrorMessage()`, `expectErrorMessageMatches()`, `expectNotice()`, `expectNoticeMessage()`, `expectNoticeMessageMatches()`, `expectWarning()`, `expectWarningMessage()`, and `expectWarningMessageMatches()` +* [#5063](https://github.com/sebastianbergmann/phpunit/issues/5063): Deprecate `withConsecutive()` +* [#5064](https://github.com/sebastianbergmann/phpunit/issues/5064): Deprecate `PHPUnit\Framework\TestCase::getMockClass()` +* [#5132](https://github.com/sebastianbergmann/phpunit/issues/5132): Deprecate `Test` suffix for abstract test case classes + +[9.6.3]: https://github.com/sebastianbergmann/phpunit/compare/9.6.2...9.6.3 +[9.6.2]: https://github.com/sebastianbergmann/phpunit/compare/9.6.1...9.6.2 +[9.6.1]: https://github.com/sebastianbergmann/phpunit/compare/9.6.0...9.6.1 +[9.6.0]: https://github.com/sebastianbergmann/phpunit/compare/9.5.28...9.6.0 diff --git a/vendor/phpunit/phpunit/LICENSE b/vendor/phpunit/phpunit/LICENSE new file mode 100644 index 00000000..73e95512 --- /dev/null +++ b/vendor/phpunit/phpunit/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2001-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/phpunit/phpunit/README.md b/vendor/phpunit/phpunit/README.md new file mode 100644 index 00000000..ffc8bf32 --- /dev/null +++ b/vendor/phpunit/phpunit/README.md @@ -0,0 +1,38 @@ +

    🇺🇦 UKRAINE NEEDS YOUR HELP NOW!

    + +# PHPUnit + +[![Latest Stable Version](https://poser.pugx.org/phpunit/phpunit/v/stable.png)](https://packagist.org/packages/phpunit/phpunit) +[![CI Status](https://github.com/sebastianbergmann/phpunit/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/phpunit/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/phpunit/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/phpunit) +[![codecov](https://codecov.io/gh/sebastianbergmann/phpunit/branch/9.6/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/phpunit) + +PHPUnit is a programmer-oriented testing framework for PHP. It is an instance of the xUnit architecture for unit testing frameworks. + +## Installation + +We distribute a [PHP Archive (PHAR)](https://php.net/phar) that has all required (as well as some optional) dependencies of PHPUnit bundled in a single file: + +```bash +$ wget https://phar.phpunit.de/phpunit-X.Y.phar + +$ php phpunit-X.Y.phar --version +``` + +Please replace `X.Y` with the version of PHPUnit you are interested in. + +Alternatively, you may use [Composer](https://getcomposer.org/) to download and install PHPUnit as well as its dependencies. Please refer to the "[Getting Started](https://phpunit.de/getting-started-with-phpunit.html)" guide for details on how to install PHPUnit. + +## Contribute + +Please refer to [CONTRIBUTING.md](https://github.com/sebastianbergmann/phpunit/blob/master/.github/CONTRIBUTING.md) for information on how to contribute to PHPUnit and its related projects. + +## List of Contributors + +Thanks to everyone who has contributed to PHPUnit! You can find a detailed list of contributors on every PHPUnit related package on GitHub. This list shows only the major components: + +* [PHPUnit](https://github.com/sebastianbergmann/phpunit/graphs/contributors) +* [php-code-coverage](https://github.com/sebastianbergmann/php-code-coverage/graphs/contributors) + +A very special thanks to everyone who has contributed to the [documentation](https://github.com/sebastianbergmann/phpunit-documentation-english/graphs/contributors). + diff --git a/vendor/phpunit/phpunit/SECURITY.md b/vendor/phpunit/phpunit/SECURITY.md new file mode 100644 index 00000000..dcc15385 --- /dev/null +++ b/vendor/phpunit/phpunit/SECURITY.md @@ -0,0 +1,11 @@ +# Security Policy + +PHPUnit is a framework for writing as well as a commandline tool for running tests. Writing and running tests is a development-time activity. There is no reason why PHPUnit should be installed on a webserver. + +**If you upload PHPUnit to a webserver then your deployment process is broken. On a more general note, if your `vendor` directory is publicly accessible on your webserver then your deployment process is also broken.** + +Please note that if you upload PHPUnit to a webserver "bad things" may happen. [You have been warned.](https://thephp.cc/articles/phpunit-a-security-risk) + +## Security Contact Information + +After the above, if you still would like to report a security vulnerability, please email `sebastian@phpunit.de`. diff --git a/vendor/phpunit/phpunit/composer.json b/vendor/phpunit/phpunit/composer.json new file mode 100644 index 00000000..38117ea1 --- /dev/null +++ b/vendor/phpunit/phpunit/composer.json @@ -0,0 +1,89 @@ +{ + "name": "phpunit/phpunit", + "description": "The PHP Unit Testing framework.", + "type": "library", + "keywords": [ + "phpunit", + "xunit", + "testing" + ], + "homepage": "https://phpunit.de/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues" + }, + "prefer-stable": true, + "require": { + "php": ">=7.3", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "doctrine/instantiator": "^1.3.1 || ^2", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" + }, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*" + }, + "bin": [ + "phpunit" + ], + "autoload": { + "classmap": [ + "src/" + ], + "files": [ + "src/Framework/Assert/Functions.php" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/" + ], + "files": [ + "tests/_files/CoverageNamespacedFunctionTest.php", + "tests/_files/CoveredFunction.php", + "tests/_files/NamespaceCoveredFunction.php" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "9.6-dev" + } + } +} diff --git a/vendor/phpunit/phpunit/phpunit b/vendor/phpunit/phpunit/phpunit new file mode 100755 index 00000000..c8029566 --- /dev/null +++ b/vendor/phpunit/phpunit/phpunit @@ -0,0 +1,98 @@ +#!/usr/bin/env php + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (!version_compare(PHP_VERSION, PHP_VERSION, '=')) { + fwrite( + STDERR, + sprintf( + '%s declares an invalid value for PHP_VERSION.' . PHP_EOL . + 'This breaks fundamental functionality such as version_compare().' . PHP_EOL . + 'Please use a different PHP interpreter.' . PHP_EOL, + + PHP_BINARY + ) + ); + + die(1); +} + +if (version_compare('7.3.0', PHP_VERSION, '>')) { + fwrite( + STDERR, + sprintf( + 'This version of PHPUnit requires PHP >= 7.3.' . PHP_EOL . + 'You are using PHP %s (%s).' . PHP_EOL, + PHP_VERSION, + PHP_BINARY + ) + ); + + die(1); +} + +foreach (['dom', 'json', 'libxml', 'mbstring', 'tokenizer', 'xml', 'xmlwriter'] as $extension) { + if (extension_loaded($extension)) { + continue; + } + + fwrite( + STDERR, + sprintf( + 'PHPUnit requires the "%s" extension.' . PHP_EOL, + $extension + ) + ); + + die(1); +} + +if (!ini_get('date.timezone')) { + ini_set('date.timezone', 'UTC'); +} + +if (isset($GLOBALS['_composer_autoload_path'])) { + define('PHPUNIT_COMPOSER_INSTALL', $GLOBALS['_composer_autoload_path']); + + unset($GLOBALS['_composer_autoload_path']); +} else { + foreach (array(__DIR__ . '/../../autoload.php', __DIR__ . '/../vendor/autoload.php', __DIR__ . '/vendor/autoload.php') as $file) { + if (file_exists($file)) { + define('PHPUNIT_COMPOSER_INSTALL', $file); + + break; + } + } + + unset($file); +} + +if (!defined('PHPUNIT_COMPOSER_INSTALL')) { + fwrite( + STDERR, + 'You need to set up the project dependencies using Composer:' . PHP_EOL . PHP_EOL . + ' composer install' . PHP_EOL . PHP_EOL . + 'You can learn all about Composer on https://getcomposer.org/.' . PHP_EOL + ); + + die(1); +} + +$options = getopt('', array('prepend:')); + +if (isset($options['prepend'])) { + require $options['prepend']; +} + +unset($options); + +require PHPUNIT_COMPOSER_INSTALL; + +PHPUnit\TextUI\Command::main(); diff --git a/vendor/phpunit/phpunit/phpunit.xsd b/vendor/phpunit/phpunit/phpunit.xsd new file mode 100644 index 00000000..7fa2f6b6 --- /dev/null +++ b/vendor/phpunit/phpunit/phpunit.xsd @@ -0,0 +1,330 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 9.6 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/phpunit/phpunit/schema/8.5.xsd b/vendor/phpunit/phpunit/schema/8.5.xsd new file mode 100644 index 00000000..5881bafe --- /dev/null +++ b/vendor/phpunit/phpunit/schema/8.5.xsd @@ -0,0 +1,317 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 8.5 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/phpunit/phpunit/schema/9.2.xsd b/vendor/phpunit/phpunit/schema/9.2.xsd new file mode 100644 index 00000000..883f21bc --- /dev/null +++ b/vendor/phpunit/phpunit/schema/9.2.xsd @@ -0,0 +1,317 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 9.2 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/phpunit/phpunit/src/Exception.php b/vendor/phpunit/phpunit/src/Exception.php new file mode 100644 index 00000000..4e7c3335 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Exception.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit; + +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Exception extends Throwable +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Assert.php b/vendor/phpunit/phpunit/src/Framework/Assert.php new file mode 100644 index 00000000..156220a5 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Assert.php @@ -0,0 +1,2932 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use const DEBUG_BACKTRACE_IGNORE_ARGS; +use const PHP_EOL; +use function array_shift; +use function array_unshift; +use function assert; +use function class_exists; +use function count; +use function debug_backtrace; +use function explode; +use function file_get_contents; +use function func_get_args; +use function implode; +use function interface_exists; +use function is_array; +use function is_bool; +use function is_int; +use function is_iterable; +use function is_object; +use function is_string; +use function preg_match; +use function preg_split; +use function sprintf; +use function strpos; +use ArrayAccess; +use Countable; +use DOMAttr; +use DOMDocument; +use DOMElement; +use Generator; +use PHPUnit\Framework\Constraint\ArrayHasKey; +use PHPUnit\Framework\Constraint\Callback; +use PHPUnit\Framework\Constraint\ClassHasAttribute; +use PHPUnit\Framework\Constraint\ClassHasStaticAttribute; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\Constraint\Count; +use PHPUnit\Framework\Constraint\DirectoryExists; +use PHPUnit\Framework\Constraint\FileExists; +use PHPUnit\Framework\Constraint\GreaterThan; +use PHPUnit\Framework\Constraint\IsAnything; +use PHPUnit\Framework\Constraint\IsEmpty; +use PHPUnit\Framework\Constraint\IsEqual; +use PHPUnit\Framework\Constraint\IsEqualCanonicalizing; +use PHPUnit\Framework\Constraint\IsEqualIgnoringCase; +use PHPUnit\Framework\Constraint\IsEqualWithDelta; +use PHPUnit\Framework\Constraint\IsFalse; +use PHPUnit\Framework\Constraint\IsFinite; +use PHPUnit\Framework\Constraint\IsIdentical; +use PHPUnit\Framework\Constraint\IsInfinite; +use PHPUnit\Framework\Constraint\IsInstanceOf; +use PHPUnit\Framework\Constraint\IsJson; +use PHPUnit\Framework\Constraint\IsNan; +use PHPUnit\Framework\Constraint\IsNull; +use PHPUnit\Framework\Constraint\IsReadable; +use PHPUnit\Framework\Constraint\IsTrue; +use PHPUnit\Framework\Constraint\IsType; +use PHPUnit\Framework\Constraint\IsWritable; +use PHPUnit\Framework\Constraint\JsonMatches; +use PHPUnit\Framework\Constraint\LessThan; +use PHPUnit\Framework\Constraint\LogicalAnd; +use PHPUnit\Framework\Constraint\LogicalNot; +use PHPUnit\Framework\Constraint\LogicalOr; +use PHPUnit\Framework\Constraint\LogicalXor; +use PHPUnit\Framework\Constraint\ObjectEquals; +use PHPUnit\Framework\Constraint\ObjectHasAttribute; +use PHPUnit\Framework\Constraint\RegularExpression; +use PHPUnit\Framework\Constraint\SameSize; +use PHPUnit\Framework\Constraint\StringContains; +use PHPUnit\Framework\Constraint\StringEndsWith; +use PHPUnit\Framework\Constraint\StringMatchesFormatDescription; +use PHPUnit\Framework\Constraint\StringStartsWith; +use PHPUnit\Framework\Constraint\TraversableContainsEqual; +use PHPUnit\Framework\Constraint\TraversableContainsIdentical; +use PHPUnit\Framework\Constraint\TraversableContainsOnly; +use PHPUnit\Util\Type; +use PHPUnit\Util\Xml; +use PHPUnit\Util\Xml\Loader as XmlLoader; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class Assert +{ + /** + * @var int + */ + private static $count = 0; + + /** + * Asserts that an array has a specified key. + * + * @param int|string $key + * @param array|ArrayAccess $array + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + */ + public static function assertArrayHasKey($key, $array, string $message = ''): void + { + if (!(is_int($key) || is_string($key))) { + throw InvalidArgumentException::create( + 1, + 'integer or string' + ); + } + + if (!(is_array($array) || $array instanceof ArrayAccess)) { + throw InvalidArgumentException::create( + 2, + 'array or ArrayAccess' + ); + } + + $constraint = new ArrayHasKey($key); + + static::assertThat($array, $constraint, $message); + } + + /** + * Asserts that an array does not have a specified key. + * + * @param int|string $key + * @param array|ArrayAccess $array + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + */ + public static function assertArrayNotHasKey($key, $array, string $message = ''): void + { + if (!(is_int($key) || is_string($key))) { + throw InvalidArgumentException::create( + 1, + 'integer or string' + ); + } + + if (!(is_array($array) || $array instanceof ArrayAccess)) { + throw InvalidArgumentException::create( + 2, + 'array or ArrayAccess' + ); + } + + $constraint = new LogicalNot( + new ArrayHasKey($key) + ); + + static::assertThat($array, $constraint, $message); + } + + /** + * Asserts that a haystack contains a needle. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + */ + public static function assertContains($needle, iterable $haystack, string $message = ''): void + { + $constraint = new TraversableContainsIdentical($needle); + + static::assertThat($haystack, $constraint, $message); + } + + public static function assertContainsEquals($needle, iterable $haystack, string $message = ''): void + { + $constraint = new TraversableContainsEqual($needle); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * Asserts that a haystack does not contain a needle. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + */ + public static function assertNotContains($needle, iterable $haystack, string $message = ''): void + { + $constraint = new LogicalNot( + new TraversableContainsIdentical($needle) + ); + + static::assertThat($haystack, $constraint, $message); + } + + public static function assertNotContainsEquals($needle, iterable $haystack, string $message = ''): void + { + $constraint = new LogicalNot(new TraversableContainsEqual($needle)); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * Asserts that a haystack contains only values of a given type. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void + { + if ($isNativeType === null) { + $isNativeType = Type::isType($type); + } + + static::assertThat( + $haystack, + new TraversableContainsOnly( + $type, + $isNativeType + ), + $message + ); + } + + /** + * Asserts that a haystack contains only instances of a given class name. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = ''): void + { + static::assertThat( + $haystack, + new TraversableContainsOnly( + $className, + false + ), + $message + ); + } + + /** + * Asserts that a haystack does not contain only values of a given type. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void + { + if ($isNativeType === null) { + $isNativeType = Type::isType($type); + } + + static::assertThat( + $haystack, + new LogicalNot( + new TraversableContainsOnly( + $type, + $isNativeType + ) + ), + $message + ); + } + + /** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @param Countable|iterable $haystack + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + */ + public static function assertCount(int $expectedCount, $haystack, string $message = ''): void + { + if ($haystack instanceof Generator) { + self::createWarning('Passing an argument of type Generator for the $haystack parameter is deprecated. Support for this will be removed in PHPUnit 10.'); + } + + if (!$haystack instanceof Countable && !is_iterable($haystack)) { + throw InvalidArgumentException::create(2, 'countable or iterable'); + } + + static::assertThat( + $haystack, + new Count($expectedCount), + $message + ); + } + + /** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @param Countable|iterable $haystack + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + */ + public static function assertNotCount(int $expectedCount, $haystack, string $message = ''): void + { + if ($haystack instanceof Generator) { + self::createWarning('Passing an argument of type Generator for the $haystack parameter is deprecated. Support for this will be removed in PHPUnit 10.'); + } + + if (!$haystack instanceof Countable && !is_iterable($haystack)) { + throw InvalidArgumentException::create(2, 'countable or iterable'); + } + + $constraint = new LogicalNot( + new Count($expectedCount) + ); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * Asserts that two variables are equal. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertEquals($expected, $actual, string $message = ''): void + { + $constraint = new IsEqual($expected); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are equal (canonicalizing). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertEqualsCanonicalizing($expected, $actual, string $message = ''): void + { + $constraint = new IsEqualCanonicalizing($expected); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are equal (ignoring case). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertEqualsIgnoringCase($expected, $actual, string $message = ''): void + { + $constraint = new IsEqualIgnoringCase($expected); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are equal (with delta). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertEqualsWithDelta($expected, $actual, float $delta, string $message = ''): void + { + $constraint = new IsEqualWithDelta( + $expected, + $delta + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are not equal. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertNotEquals($expected, $actual, string $message = ''): void + { + $constraint = new LogicalNot( + new IsEqual($expected) + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are not equal (canonicalizing). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertNotEqualsCanonicalizing($expected, $actual, string $message = ''): void + { + $constraint = new LogicalNot( + new IsEqualCanonicalizing($expected) + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are not equal (ignoring case). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertNotEqualsIgnoringCase($expected, $actual, string $message = ''): void + { + $constraint = new LogicalNot( + new IsEqualIgnoringCase($expected) + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are not equal (with delta). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertNotEqualsWithDelta($expected, $actual, float $delta, string $message = ''): void + { + $constraint = new LogicalNot( + new IsEqualWithDelta( + $expected, + $delta + ) + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * @throws ExpectationFailedException + */ + public static function assertObjectEquals(object $expected, object $actual, string $method = 'equals', string $message = ''): void + { + static::assertThat( + $actual, + static::objectEquals($expected, $method), + $message + ); + } + + /** + * Asserts that a variable is empty. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert empty $actual + */ + public static function assertEmpty($actual, string $message = ''): void + { + if ($actual instanceof Generator) { + self::createWarning('Passing an argument of type Generator for the $actual parameter is deprecated. Support for this will be removed in PHPUnit 10.'); + } + + static::assertThat($actual, static::isEmpty(), $message); + } + + /** + * Asserts that a variable is not empty. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !empty $actual + */ + public static function assertNotEmpty($actual, string $message = ''): void + { + if ($actual instanceof Generator) { + self::createWarning('Passing an argument of type Generator for the $actual parameter is deprecated. Support for this will be removed in PHPUnit 10.'); + } + + static::assertThat($actual, static::logicalNot(static::isEmpty()), $message); + } + + /** + * Asserts that a value is greater than another value. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertGreaterThan($expected, $actual, string $message = ''): void + { + static::assertThat($actual, static::greaterThan($expected), $message); + } + + /** + * Asserts that a value is greater than or equal to another value. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertGreaterThanOrEqual($expected, $actual, string $message = ''): void + { + static::assertThat( + $actual, + static::greaterThanOrEqual($expected), + $message + ); + } + + /** + * Asserts that a value is smaller than another value. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertLessThan($expected, $actual, string $message = ''): void + { + static::assertThat($actual, static::lessThan($expected), $message); + } + + /** + * Asserts that a value is smaller than or equal to another value. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertLessThanOrEqual($expected, $actual, string $message = ''): void + { + static::assertThat($actual, static::lessThanOrEqual($expected), $message); + } + + /** + * Asserts that the contents of one file is equal to the contents of another + * file. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertFileEquals(string $expected, string $actual, string $message = ''): void + { + static::assertFileExists($expected, $message); + static::assertFileExists($actual, $message); + + $constraint = new IsEqual(file_get_contents($expected)); + + static::assertThat(file_get_contents($actual), $constraint, $message); + } + + /** + * Asserts that the contents of one file is equal to the contents of another + * file (canonicalizing). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertFileEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void + { + static::assertFileExists($expected, $message); + static::assertFileExists($actual, $message); + + $constraint = new IsEqualCanonicalizing( + file_get_contents($expected) + ); + + static::assertThat(file_get_contents($actual), $constraint, $message); + } + + /** + * Asserts that the contents of one file is equal to the contents of another + * file (ignoring case). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertFileEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void + { + static::assertFileExists($expected, $message); + static::assertFileExists($actual, $message); + + $constraint = new IsEqualIgnoringCase(file_get_contents($expected)); + + static::assertThat(file_get_contents($actual), $constraint, $message); + } + + /** + * Asserts that the contents of one file is not equal to the contents of + * another file. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertFileNotEquals(string $expected, string $actual, string $message = ''): void + { + static::assertFileExists($expected, $message); + static::assertFileExists($actual, $message); + + $constraint = new LogicalNot( + new IsEqual(file_get_contents($expected)) + ); + + static::assertThat(file_get_contents($actual), $constraint, $message); + } + + /** + * Asserts that the contents of one file is not equal to the contents of another + * file (canonicalizing). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertFileNotEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void + { + static::assertFileExists($expected, $message); + static::assertFileExists($actual, $message); + + $constraint = new LogicalNot( + new IsEqualCanonicalizing(file_get_contents($expected)) + ); + + static::assertThat(file_get_contents($actual), $constraint, $message); + } + + /** + * Asserts that the contents of one file is not equal to the contents of another + * file (ignoring case). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertFileNotEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void + { + static::assertFileExists($expected, $message); + static::assertFileExists($actual, $message); + + $constraint = new LogicalNot( + new IsEqualIgnoringCase(file_get_contents($expected)) + ); + + static::assertThat(file_get_contents($actual), $constraint, $message); + } + + /** + * Asserts that the contents of a string is equal + * to the contents of a file. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + + $constraint = new IsEqual(file_get_contents($expectedFile)); + + static::assertThat($actualString, $constraint, $message); + } + + /** + * Asserts that the contents of a string is equal + * to the contents of a file (canonicalizing). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + + $constraint = new IsEqualCanonicalizing(file_get_contents($expectedFile)); + + static::assertThat($actualString, $constraint, $message); + } + + /** + * Asserts that the contents of a string is equal + * to the contents of a file (ignoring case). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + + $constraint = new IsEqualIgnoringCase(file_get_contents($expectedFile)); + + static::assertThat($actualString, $constraint, $message); + } + + /** + * Asserts that the contents of a string is not equal + * to the contents of a file. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + + $constraint = new LogicalNot( + new IsEqual(file_get_contents($expectedFile)) + ); + + static::assertThat($actualString, $constraint, $message); + } + + /** + * Asserts that the contents of a string is not equal + * to the contents of a file (canonicalizing). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringNotEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + + $constraint = new LogicalNot( + new IsEqualCanonicalizing(file_get_contents($expectedFile)) + ); + + static::assertThat($actualString, $constraint, $message); + } + + /** + * Asserts that the contents of a string is not equal + * to the contents of a file (ignoring case). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringNotEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + + $constraint = new LogicalNot( + new IsEqualIgnoringCase(file_get_contents($expectedFile)) + ); + + static::assertThat($actualString, $constraint, $message); + } + + /** + * Asserts that a file/dir is readable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertIsReadable(string $filename, string $message = ''): void + { + static::assertThat($filename, new IsReadable, $message); + } + + /** + * Asserts that a file/dir exists and is not readable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertIsNotReadable(string $filename, string $message = ''): void + { + static::assertThat($filename, new LogicalNot(new IsReadable), $message); + } + + /** + * Asserts that a file/dir exists and is not readable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4062 + */ + public static function assertNotIsReadable(string $filename, string $message = ''): void + { + self::createWarning('assertNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertIsNotReadable() instead.'); + + static::assertThat($filename, new LogicalNot(new IsReadable), $message); + } + + /** + * Asserts that a file/dir exists and is writable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertIsWritable(string $filename, string $message = ''): void + { + static::assertThat($filename, new IsWritable, $message); + } + + /** + * Asserts that a file/dir exists and is not writable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertIsNotWritable(string $filename, string $message = ''): void + { + static::assertThat($filename, new LogicalNot(new IsWritable), $message); + } + + /** + * Asserts that a file/dir exists and is not writable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4065 + */ + public static function assertNotIsWritable(string $filename, string $message = ''): void + { + self::createWarning('assertNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertIsNotWritable() instead.'); + + static::assertThat($filename, new LogicalNot(new IsWritable), $message); + } + + /** + * Asserts that a directory exists. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertDirectoryExists(string $directory, string $message = ''): void + { + static::assertThat($directory, new DirectoryExists, $message); + } + + /** + * Asserts that a directory does not exist. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertDirectoryDoesNotExist(string $directory, string $message = ''): void + { + static::assertThat($directory, new LogicalNot(new DirectoryExists), $message); + } + + /** + * Asserts that a directory does not exist. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4068 + */ + public static function assertDirectoryNotExists(string $directory, string $message = ''): void + { + self::createWarning('assertDirectoryNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryDoesNotExist() instead.'); + + static::assertThat($directory, new LogicalNot(new DirectoryExists), $message); + } + + /** + * Asserts that a directory exists and is readable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertDirectoryIsReadable(string $directory, string $message = ''): void + { + self::assertDirectoryExists($directory, $message); + self::assertIsReadable($directory, $message); + } + + /** + * Asserts that a directory exists and is not readable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertDirectoryIsNotReadable(string $directory, string $message = ''): void + { + self::assertDirectoryExists($directory, $message); + self::assertIsNotReadable($directory, $message); + } + + /** + * Asserts that a directory exists and is not readable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4071 + */ + public static function assertDirectoryNotIsReadable(string $directory, string $message = ''): void + { + self::createWarning('assertDirectoryNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryIsNotReadable() instead.'); + + self::assertDirectoryExists($directory, $message); + self::assertIsNotReadable($directory, $message); + } + + /** + * Asserts that a directory exists and is writable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertDirectoryIsWritable(string $directory, string $message = ''): void + { + self::assertDirectoryExists($directory, $message); + self::assertIsWritable($directory, $message); + } + + /** + * Asserts that a directory exists and is not writable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertDirectoryIsNotWritable(string $directory, string $message = ''): void + { + self::assertDirectoryExists($directory, $message); + self::assertIsNotWritable($directory, $message); + } + + /** + * Asserts that a directory exists and is not writable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4074 + */ + public static function assertDirectoryNotIsWritable(string $directory, string $message = ''): void + { + self::createWarning('assertDirectoryNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryIsNotWritable() instead.'); + + self::assertDirectoryExists($directory, $message); + self::assertIsNotWritable($directory, $message); + } + + /** + * Asserts that a file exists. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertFileExists(string $filename, string $message = ''): void + { + static::assertThat($filename, new FileExists, $message); + } + + /** + * Asserts that a file does not exist. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertFileDoesNotExist(string $filename, string $message = ''): void + { + static::assertThat($filename, new LogicalNot(new FileExists), $message); + } + + /** + * Asserts that a file does not exist. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4077 + */ + public static function assertFileNotExists(string $filename, string $message = ''): void + { + self::createWarning('assertFileNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileDoesNotExist() instead.'); + + static::assertThat($filename, new LogicalNot(new FileExists), $message); + } + + /** + * Asserts that a file exists and is readable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertFileIsReadable(string $file, string $message = ''): void + { + self::assertFileExists($file, $message); + self::assertIsReadable($file, $message); + } + + /** + * Asserts that a file exists and is not readable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertFileIsNotReadable(string $file, string $message = ''): void + { + self::assertFileExists($file, $message); + self::assertIsNotReadable($file, $message); + } + + /** + * Asserts that a file exists and is not readable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4080 + */ + public static function assertFileNotIsReadable(string $file, string $message = ''): void + { + self::createWarning('assertFileNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileIsNotReadable() instead.'); + + self::assertFileExists($file, $message); + self::assertIsNotReadable($file, $message); + } + + /** + * Asserts that a file exists and is writable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertFileIsWritable(string $file, string $message = ''): void + { + self::assertFileExists($file, $message); + self::assertIsWritable($file, $message); + } + + /** + * Asserts that a file exists and is not writable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertFileIsNotWritable(string $file, string $message = ''): void + { + self::assertFileExists($file, $message); + self::assertIsNotWritable($file, $message); + } + + /** + * Asserts that a file exists and is not writable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4083 + */ + public static function assertFileNotIsWritable(string $file, string $message = ''): void + { + self::createWarning('assertFileNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileIsNotWritable() instead.'); + + self::assertFileExists($file, $message); + self::assertIsNotWritable($file, $message); + } + + /** + * Asserts that a condition is true. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert true $condition + */ + public static function assertTrue($condition, string $message = ''): void + { + static::assertThat($condition, static::isTrue(), $message); + } + + /** + * Asserts that a condition is not true. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !true $condition + */ + public static function assertNotTrue($condition, string $message = ''): void + { + static::assertThat($condition, static::logicalNot(static::isTrue()), $message); + } + + /** + * Asserts that a condition is false. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert false $condition + */ + public static function assertFalse($condition, string $message = ''): void + { + static::assertThat($condition, static::isFalse(), $message); + } + + /** + * Asserts that a condition is not false. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !false $condition + */ + public static function assertNotFalse($condition, string $message = ''): void + { + static::assertThat($condition, static::logicalNot(static::isFalse()), $message); + } + + /** + * Asserts that a variable is null. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert null $actual + */ + public static function assertNull($actual, string $message = ''): void + { + static::assertThat($actual, static::isNull(), $message); + } + + /** + * Asserts that a variable is not null. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !null $actual + */ + public static function assertNotNull($actual, string $message = ''): void + { + static::assertThat($actual, static::logicalNot(static::isNull()), $message); + } + + /** + * Asserts that a variable is finite. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertFinite($actual, string $message = ''): void + { + static::assertThat($actual, static::isFinite(), $message); + } + + /** + * Asserts that a variable is infinite. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertInfinite($actual, string $message = ''): void + { + static::assertThat($actual, static::isInfinite(), $message); + } + + /** + * Asserts that a variable is nan. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertNan($actual, string $message = ''): void + { + static::assertThat($actual, static::isNan(), $message); + } + + /** + * Asserts that a class has a specified attribute. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4601 + */ + public static function assertClassHasAttribute(string $attributeName, string $className, string $message = ''): void + { + self::createWarning('assertClassHasAttribute() is deprecated and will be removed in PHPUnit 10.'); + + if (!self::isValidClassAttributeName($attributeName)) { + throw InvalidArgumentException::create(1, 'valid attribute name'); + } + + if (!class_exists($className)) { + throw InvalidArgumentException::create(2, 'class name'); + } + + static::assertThat($className, new ClassHasAttribute($attributeName), $message); + } + + /** + * Asserts that a class does not have a specified attribute. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4601 + */ + public static function assertClassNotHasAttribute(string $attributeName, string $className, string $message = ''): void + { + self::createWarning('assertClassNotHasAttribute() is deprecated and will be removed in PHPUnit 10.'); + + if (!self::isValidClassAttributeName($attributeName)) { + throw InvalidArgumentException::create(1, 'valid attribute name'); + } + + if (!class_exists($className)) { + throw InvalidArgumentException::create(2, 'class name'); + } + + static::assertThat( + $className, + new LogicalNot( + new ClassHasAttribute($attributeName) + ), + $message + ); + } + + /** + * Asserts that a class has a specified static attribute. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4601 + */ + public static function assertClassHasStaticAttribute(string $attributeName, string $className, string $message = ''): void + { + self::createWarning('assertClassHasStaticAttribute() is deprecated and will be removed in PHPUnit 10.'); + + if (!self::isValidClassAttributeName($attributeName)) { + throw InvalidArgumentException::create(1, 'valid attribute name'); + } + + if (!class_exists($className)) { + throw InvalidArgumentException::create(2, 'class name'); + } + + static::assertThat( + $className, + new ClassHasStaticAttribute($attributeName), + $message + ); + } + + /** + * Asserts that a class does not have a specified static attribute. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4601 + */ + public static function assertClassNotHasStaticAttribute(string $attributeName, string $className, string $message = ''): void + { + self::createWarning('assertClassNotHasStaticAttribute() is deprecated and will be removed in PHPUnit 10.'); + + if (!self::isValidClassAttributeName($attributeName)) { + throw InvalidArgumentException::create(1, 'valid attribute name'); + } + + if (!class_exists($className)) { + throw InvalidArgumentException::create(2, 'class name'); + } + + static::assertThat( + $className, + new LogicalNot( + new ClassHasStaticAttribute($attributeName) + ), + $message + ); + } + + /** + * Asserts that an object has a specified attribute. + * + * @param object $object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4601 + */ + public static function assertObjectHasAttribute(string $attributeName, $object, string $message = ''): void + { + self::createWarning('assertObjectHasAttribute() is deprecated and will be removed in PHPUnit 10.'); + + if (!self::isValidObjectAttributeName($attributeName)) { + throw InvalidArgumentException::create(1, 'valid attribute name'); + } + + if (!is_object($object)) { + throw InvalidArgumentException::create(2, 'object'); + } + + static::assertThat( + $object, + new ObjectHasAttribute($attributeName), + $message + ); + } + + /** + * Asserts that an object does not have a specified attribute. + * + * @param object $object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4601 + */ + public static function assertObjectNotHasAttribute(string $attributeName, $object, string $message = ''): void + { + self::createWarning('assertObjectNotHasAttribute() is deprecated and will be removed in PHPUnit 10.'); + + if (!self::isValidObjectAttributeName($attributeName)) { + throw InvalidArgumentException::create(1, 'valid attribute name'); + } + + if (!is_object($object)) { + throw InvalidArgumentException::create(2, 'object'); + } + + static::assertThat( + $object, + new LogicalNot( + new ObjectHasAttribute($attributeName) + ), + $message + ); + } + + /** + * Asserts that two variables have the same type and value. + * Used on objects, it asserts that two variables reference + * the same object. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-template ExpectedType + * + * @psalm-param ExpectedType $expected + * + * @psalm-assert =ExpectedType $actual + */ + public static function assertSame($expected, $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsIdentical($expected), + $message + ); + } + + /** + * Asserts that two variables do not have the same type and value. + * Used on objects, it asserts that two variables do not reference + * the same object. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertNotSame($expected, $actual, string $message = ''): void + { + if (is_bool($expected) && is_bool($actual)) { + static::assertNotEquals($expected, $actual, $message); + } + + static::assertThat( + $actual, + new LogicalNot( + new IsIdentical($expected) + ), + $message + ); + } + + /** + * Asserts that a variable is of a given type. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-template ExpectedType of object + * + * @psalm-param class-string $expected + * + * @psalm-assert =ExpectedType $actual + */ + public static function assertInstanceOf(string $expected, $actual, string $message = ''): void + { + if (!class_exists($expected) && !interface_exists($expected)) { + throw InvalidArgumentException::create(1, 'class or interface name'); + } + + static::assertThat( + $actual, + new IsInstanceOf($expected), + $message + ); + } + + /** + * Asserts that a variable is not of a given type. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-template ExpectedType of object + * + * @psalm-param class-string $expected + * + * @psalm-assert !ExpectedType $actual + */ + public static function assertNotInstanceOf(string $expected, $actual, string $message = ''): void + { + if (!class_exists($expected) && !interface_exists($expected)) { + throw InvalidArgumentException::create(1, 'class or interface name'); + } + + static::assertThat( + $actual, + new LogicalNot( + new IsInstanceOf($expected) + ), + $message + ); + } + + /** + * Asserts that a variable is of type array. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert array $actual + */ + public static function assertIsArray($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_ARRAY), + $message + ); + } + + /** + * Asserts that a variable is of type bool. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert bool $actual + */ + public static function assertIsBool($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_BOOL), + $message + ); + } + + /** + * Asserts that a variable is of type float. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert float $actual + */ + public static function assertIsFloat($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_FLOAT), + $message + ); + } + + /** + * Asserts that a variable is of type int. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert int $actual + */ + public static function assertIsInt($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_INT), + $message + ); + } + + /** + * Asserts that a variable is of type numeric. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert numeric $actual + */ + public static function assertIsNumeric($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_NUMERIC), + $message + ); + } + + /** + * Asserts that a variable is of type object. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert object $actual + */ + public static function assertIsObject($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_OBJECT), + $message + ); + } + + /** + * Asserts that a variable is of type resource. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert resource $actual + */ + public static function assertIsResource($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_RESOURCE), + $message + ); + } + + /** + * Asserts that a variable is of type resource and is closed. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert resource $actual + */ + public static function assertIsClosedResource($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_CLOSED_RESOURCE), + $message + ); + } + + /** + * Asserts that a variable is of type string. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert string $actual + */ + public static function assertIsString($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_STRING), + $message + ); + } + + /** + * Asserts that a variable is of type scalar. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert scalar $actual + */ + public static function assertIsScalar($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_SCALAR), + $message + ); + } + + /** + * Asserts that a variable is of type callable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert callable $actual + */ + public static function assertIsCallable($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_CALLABLE), + $message + ); + } + + /** + * Asserts that a variable is of type iterable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert iterable $actual + */ + public static function assertIsIterable($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_ITERABLE), + $message + ); + } + + /** + * Asserts that a variable is not of type array. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !array $actual + */ + public static function assertIsNotArray($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_ARRAY)), + $message + ); + } + + /** + * Asserts that a variable is not of type bool. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !bool $actual + */ + public static function assertIsNotBool($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_BOOL)), + $message + ); + } + + /** + * Asserts that a variable is not of type float. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !float $actual + */ + public static function assertIsNotFloat($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_FLOAT)), + $message + ); + } + + /** + * Asserts that a variable is not of type int. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !int $actual + */ + public static function assertIsNotInt($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_INT)), + $message + ); + } + + /** + * Asserts that a variable is not of type numeric. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !numeric $actual + */ + public static function assertIsNotNumeric($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_NUMERIC)), + $message + ); + } + + /** + * Asserts that a variable is not of type object. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !object $actual + */ + public static function assertIsNotObject($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_OBJECT)), + $message + ); + } + + /** + * Asserts that a variable is not of type resource. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !resource $actual + */ + public static function assertIsNotResource($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_RESOURCE)), + $message + ); + } + + /** + * Asserts that a variable is not of type resource. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !resource $actual + */ + public static function assertIsNotClosedResource($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_CLOSED_RESOURCE)), + $message + ); + } + + /** + * Asserts that a variable is not of type string. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !string $actual + */ + public static function assertIsNotString($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_STRING)), + $message + ); + } + + /** + * Asserts that a variable is not of type scalar. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !scalar $actual + */ + public static function assertIsNotScalar($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_SCALAR)), + $message + ); + } + + /** + * Asserts that a variable is not of type callable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !callable $actual + */ + public static function assertIsNotCallable($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_CALLABLE)), + $message + ); + } + + /** + * Asserts that a variable is not of type iterable. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-assert !iterable $actual + */ + public static function assertIsNotIterable($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_ITERABLE)), + $message + ); + } + + /** + * Asserts that a string matches a given regular expression. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertMatchesRegularExpression(string $pattern, string $string, string $message = ''): void + { + static::assertThat($string, new RegularExpression($pattern), $message); + } + + /** + * Asserts that a string matches a given regular expression. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4086 + */ + public static function assertRegExp(string $pattern, string $string, string $message = ''): void + { + self::createWarning('assertRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertMatchesRegularExpression() instead.'); + + static::assertThat($string, new RegularExpression($pattern), $message); + } + + /** + * Asserts that a string does not match a given regular expression. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertDoesNotMatchRegularExpression(string $pattern, string $string, string $message = ''): void + { + static::assertThat( + $string, + new LogicalNot( + new RegularExpression($pattern) + ), + $message + ); + } + + /** + * Asserts that a string does not match a given regular expression. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4089 + */ + public static function assertNotRegExp(string $pattern, string $string, string $message = ''): void + { + self::createWarning('assertNotRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDoesNotMatchRegularExpression() instead.'); + + static::assertThat( + $string, + new LogicalNot( + new RegularExpression($pattern) + ), + $message + ); + } + + /** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is the same. + * + * @param Countable|iterable $expected + * @param Countable|iterable $actual + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + */ + public static function assertSameSize($expected, $actual, string $message = ''): void + { + if ($expected instanceof Generator) { + self::createWarning('Passing an argument of type Generator for the $expected parameter is deprecated. Support for this will be removed in PHPUnit 10.'); + } + + if ($actual instanceof Generator) { + self::createWarning('Passing an argument of type Generator for the $actual parameter is deprecated. Support for this will be removed in PHPUnit 10.'); + } + + if (!$expected instanceof Countable && !is_iterable($expected)) { + throw InvalidArgumentException::create(1, 'countable or iterable'); + } + + if (!$actual instanceof Countable && !is_iterable($actual)) { + throw InvalidArgumentException::create(2, 'countable or iterable'); + } + + static::assertThat( + $actual, + new SameSize($expected), + $message + ); + } + + /** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is not the same. + * + * @param Countable|iterable $expected + * @param Countable|iterable $actual + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + */ + public static function assertNotSameSize($expected, $actual, string $message = ''): void + { + if ($expected instanceof Generator) { + self::createWarning('Passing an argument of type Generator for the $expected parameter is deprecated. Support for this will be removed in PHPUnit 10.'); + } + + if ($actual instanceof Generator) { + self::createWarning('Passing an argument of type Generator for the $actual parameter is deprecated. Support for this will be removed in PHPUnit 10.'); + } + + if (!$expected instanceof Countable && !is_iterable($expected)) { + throw InvalidArgumentException::create(1, 'countable or iterable'); + } + + if (!$actual instanceof Countable && !is_iterable($actual)) { + throw InvalidArgumentException::create(2, 'countable or iterable'); + } + + static::assertThat( + $actual, + new LogicalNot( + new SameSize($expected) + ), + $message + ); + } + + /** + * Asserts that a string matches a given format string. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringMatchesFormat(string $format, string $string, string $message = ''): void + { + static::assertThat($string, new StringMatchesFormatDescription($format), $message); + } + + /** + * Asserts that a string does not match a given format string. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringNotMatchesFormat(string $format, string $string, string $message = ''): void + { + static::assertThat( + $string, + new LogicalNot( + new StringMatchesFormatDescription($format) + ), + $message + ); + } + + /** + * Asserts that a string matches a given format file. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringMatchesFormatFile(string $formatFile, string $string, string $message = ''): void + { + static::assertFileExists($formatFile, $message); + + static::assertThat( + $string, + new StringMatchesFormatDescription( + file_get_contents($formatFile) + ), + $message + ); + } + + /** + * Asserts that a string does not match a given format string. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringNotMatchesFormatFile(string $formatFile, string $string, string $message = ''): void + { + static::assertFileExists($formatFile, $message); + + static::assertThat( + $string, + new LogicalNot( + new StringMatchesFormatDescription( + file_get_contents($formatFile) + ) + ), + $message + ); + } + + /** + * Asserts that a string starts with a given prefix. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringStartsWith(string $prefix, string $string, string $message = ''): void + { + static::assertThat($string, new StringStartsWith($prefix), $message); + } + + /** + * Asserts that a string starts not with a given prefix. + * + * @param string $prefix + * @param string $string + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringStartsNotWith($prefix, $string, string $message = ''): void + { + static::assertThat( + $string, + new LogicalNot( + new StringStartsWith($prefix) + ), + $message + ); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringContainsString(string $needle, string $haystack, string $message = ''): void + { + $constraint = new StringContains($needle, false); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void + { + $constraint = new StringContains($needle, true); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringNotContainsString(string $needle, string $haystack, string $message = ''): void + { + $constraint = new LogicalNot(new StringContains($needle)); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringNotContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void + { + $constraint = new LogicalNot(new StringContains($needle, true)); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * Asserts that a string ends with a given suffix. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringEndsWith(string $suffix, string $string, string $message = ''): void + { + static::assertThat($string, new StringEndsWith($suffix), $message); + } + + /** + * Asserts that a string ends not with a given suffix. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertStringEndsNotWith(string $suffix, string $string, string $message = ''): void + { + static::assertThat( + $string, + new LogicalNot( + new StringEndsWith($suffix) + ), + $message + ); + } + + /** + * Asserts that two XML files are equal. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + */ + public static function assertXmlFileEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void + { + $expected = (new XmlLoader)->loadFile($expectedFile); + $actual = (new XmlLoader)->loadFile($actualFile); + + static::assertEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML files are not equal. + * + * @throws \PHPUnit\Util\Exception + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void + { + $expected = (new XmlLoader)->loadFile($expectedFile); + $actual = (new XmlLoader)->loadFile($actualFile); + + static::assertNotEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are equal. + * + * @param DOMDocument|string $actualXml + * + * @throws \PHPUnit\Util\Xml\Exception + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertXmlStringEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void + { + if (!is_string($actualXml)) { + self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.'); + + $actual = $actualXml; + } else { + $actual = (new XmlLoader)->load($actualXml); + } + + $expected = (new XmlLoader)->loadFile($expectedFile); + + static::assertEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are not equal. + * + * @param DOMDocument|string $actualXml + * + * @throws \PHPUnit\Util\Xml\Exception + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertXmlStringNotEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void + { + if (!is_string($actualXml)) { + self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.'); + + $actual = $actualXml; + } else { + $actual = (new XmlLoader)->load($actualXml); + } + + $expected = (new XmlLoader)->loadFile($expectedFile); + + static::assertNotEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are equal. + * + * @param DOMDocument|string $expectedXml + * @param DOMDocument|string $actualXml + * + * @throws \PHPUnit\Util\Xml\Exception + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertXmlStringEqualsXmlString($expectedXml, $actualXml, string $message = ''): void + { + if (!is_string($expectedXml)) { + self::createWarning('Passing an argument of type DOMDocument for the $expectedXml parameter is deprecated. Support for this will be removed in PHPUnit 10.'); + + $expected = $expectedXml; + } else { + $expected = (new XmlLoader)->load($expectedXml); + } + + if (!is_string($actualXml)) { + self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.'); + + $actual = $actualXml; + } else { + $actual = (new XmlLoader)->load($actualXml); + } + + static::assertEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are not equal. + * + * @param DOMDocument|string $expectedXml + * @param DOMDocument|string $actualXml + * + * @throws \PHPUnit\Util\Xml\Exception + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, string $message = ''): void + { + if (!is_string($expectedXml)) { + self::createWarning('Passing an argument of type DOMDocument for the $expectedXml parameter is deprecated. Support for this will be removed in PHPUnit 10.'); + + $expected = $expectedXml; + } else { + $expected = (new XmlLoader)->load($expectedXml); + } + + if (!is_string($actualXml)) { + self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.'); + + $actual = $actualXml; + } else { + $actual = (new XmlLoader)->load($actualXml); + } + + static::assertNotEquals($expected, $actual, $message); + } + + /** + * Asserts that a hierarchy of DOMElements matches. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws AssertionFailedError + * @throws ExpectationFailedException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4091 + */ + public static function assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, bool $checkAttributes = false, string $message = ''): void + { + self::createWarning('assertEqualXMLStructure() is deprecated and will be removed in PHPUnit 10.'); + + $expectedElement = Xml::import($expectedElement); + $actualElement = Xml::import($actualElement); + + static::assertSame( + $expectedElement->tagName, + $actualElement->tagName, + $message + ); + + if ($checkAttributes) { + static::assertSame( + $expectedElement->attributes->length, + $actualElement->attributes->length, + sprintf( + '%s%sNumber of attributes on node "%s" does not match', + $message, + !empty($message) ? "\n" : '', + $expectedElement->tagName + ) + ); + + for ($i = 0; $i < $expectedElement->attributes->length; $i++) { + $expectedAttribute = $expectedElement->attributes->item($i); + $actualAttribute = $actualElement->attributes->getNamedItem($expectedAttribute->name); + + assert($expectedAttribute instanceof DOMAttr); + + if (!$actualAttribute) { + static::fail( + sprintf( + '%s%sCould not find attribute "%s" on node "%s"', + $message, + !empty($message) ? "\n" : '', + $expectedAttribute->name, + $expectedElement->tagName + ) + ); + } + } + } + + Xml::removeCharacterDataNodes($expectedElement); + Xml::removeCharacterDataNodes($actualElement); + + static::assertSame( + $expectedElement->childNodes->length, + $actualElement->childNodes->length, + sprintf( + '%s%sNumber of child nodes of "%s" differs', + $message, + !empty($message) ? "\n" : '', + $expectedElement->tagName + ) + ); + + for ($i = 0; $i < $expectedElement->childNodes->length; $i++) { + static::assertEqualXMLStructure( + $expectedElement->childNodes->item($i), + $actualElement->childNodes->item($i), + $checkAttributes, + $message + ); + } + } + + /** + * Evaluates a PHPUnit\Framework\Constraint matcher object. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertThat($value, Constraint $constraint, string $message = ''): void + { + self::$count += count($constraint); + + $constraint->evaluate($value, $message); + } + + /** + * Asserts that a string is a valid JSON string. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertJson(string $actualJson, string $message = ''): void + { + static::assertThat($actualJson, static::isJson(), $message); + } + + /** + * Asserts that two given JSON encoded objects or arrays are equal. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void + { + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + static::assertThat($actualJson, new JsonMatches($expectedJson), $message); + } + + /** + * Asserts that two given JSON encoded objects or arrays are not equal. + * + * @param string $expectedJson + * @param string $actualJson + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, string $message = ''): void + { + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + static::assertThat( + $actualJson, + new LogicalNot( + new JsonMatches($expectedJson) + ), + $message + ); + } + + /** + * Asserts that the generated JSON encoded object and the content of the given file are equal. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertJsonStringEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + $expectedJson = file_get_contents($expectedFile); + + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + static::assertThat($actualJson, new JsonMatches($expectedJson), $message); + } + + /** + * Asserts that the generated JSON encoded object and the content of the given file are not equal. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertJsonStringNotEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + $expectedJson = file_get_contents($expectedFile); + + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + static::assertThat( + $actualJson, + new LogicalNot( + new JsonMatches($expectedJson) + ), + $message + ); + } + + /** + * Asserts that two JSON files are equal. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertJsonFileEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + static::assertFileExists($actualFile, $message); + + $actualJson = file_get_contents($actualFile); + $expectedJson = file_get_contents($expectedFile); + + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + $constraintExpected = new JsonMatches( + $expectedJson + ); + + $constraintActual = new JsonMatches($actualJson); + + static::assertThat($expectedJson, $constraintActual, $message); + static::assertThat($actualJson, $constraintExpected, $message); + } + + /** + * Asserts that two JSON files are not equal. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public static function assertJsonFileNotEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + static::assertFileExists($actualFile, $message); + + $actualJson = file_get_contents($actualFile); + $expectedJson = file_get_contents($expectedFile); + + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + $constraintExpected = new JsonMatches( + $expectedJson + ); + + $constraintActual = new JsonMatches($actualJson); + + static::assertThat($expectedJson, new LogicalNot($constraintActual), $message); + static::assertThat($actualJson, new LogicalNot($constraintExpected), $message); + } + + /** + * @throws Exception + */ + public static function logicalAnd(): LogicalAnd + { + $constraints = func_get_args(); + + $constraint = new LogicalAnd; + $constraint->setConstraints($constraints); + + return $constraint; + } + + public static function logicalOr(): LogicalOr + { + $constraints = func_get_args(); + + $constraint = new LogicalOr; + $constraint->setConstraints($constraints); + + return $constraint; + } + + public static function logicalNot(Constraint $constraint): LogicalNot + { + return new LogicalNot($constraint); + } + + public static function logicalXor(): LogicalXor + { + $constraints = func_get_args(); + + $constraint = new LogicalXor; + $constraint->setConstraints($constraints); + + return $constraint; + } + + public static function anything(): IsAnything + { + return new IsAnything; + } + + public static function isTrue(): IsTrue + { + return new IsTrue; + } + + /** + * @psalm-template CallbackInput of mixed + * + * @psalm-param callable(CallbackInput $callback): bool $callback + * + * @psalm-return Callback + */ + public static function callback(callable $callback): Callback + { + return new Callback($callback); + } + + public static function isFalse(): IsFalse + { + return new IsFalse; + } + + public static function isJson(): IsJson + { + return new IsJson; + } + + public static function isNull(): IsNull + { + return new IsNull; + } + + public static function isFinite(): IsFinite + { + return new IsFinite; + } + + public static function isInfinite(): IsInfinite + { + return new IsInfinite; + } + + public static function isNan(): IsNan + { + return new IsNan; + } + + public static function containsEqual($value): TraversableContainsEqual + { + return new TraversableContainsEqual($value); + } + + public static function containsIdentical($value): TraversableContainsIdentical + { + return new TraversableContainsIdentical($value); + } + + public static function containsOnly(string $type): TraversableContainsOnly + { + return new TraversableContainsOnly($type); + } + + public static function containsOnlyInstancesOf(string $className): TraversableContainsOnly + { + return new TraversableContainsOnly($className, false); + } + + /** + * @param int|string $key + */ + public static function arrayHasKey($key): ArrayHasKey + { + return new ArrayHasKey($key); + } + + public static function equalTo($value): IsEqual + { + return new IsEqual($value, 0.0, false, false); + } + + public static function equalToCanonicalizing($value): IsEqualCanonicalizing + { + return new IsEqualCanonicalizing($value); + } + + public static function equalToIgnoringCase($value): IsEqualIgnoringCase + { + return new IsEqualIgnoringCase($value); + } + + public static function equalToWithDelta($value, float $delta): IsEqualWithDelta + { + return new IsEqualWithDelta($value, $delta); + } + + public static function isEmpty(): IsEmpty + { + return new IsEmpty; + } + + public static function isWritable(): IsWritable + { + return new IsWritable; + } + + public static function isReadable(): IsReadable + { + return new IsReadable; + } + + public static function directoryExists(): DirectoryExists + { + return new DirectoryExists; + } + + public static function fileExists(): FileExists + { + return new FileExists; + } + + public static function greaterThan($value): GreaterThan + { + return new GreaterThan($value); + } + + public static function greaterThanOrEqual($value): LogicalOr + { + return static::logicalOr( + new IsEqual($value), + new GreaterThan($value) + ); + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4601 + */ + public static function classHasAttribute(string $attributeName): ClassHasAttribute + { + self::createWarning('classHasAttribute() is deprecated and will be removed in PHPUnit 10.'); + + return new ClassHasAttribute($attributeName); + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4601 + */ + public static function classHasStaticAttribute(string $attributeName): ClassHasStaticAttribute + { + self::createWarning('classHasStaticAttribute() is deprecated and will be removed in PHPUnit 10.'); + + return new ClassHasStaticAttribute($attributeName); + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4601 + */ + public static function objectHasAttribute($attributeName): ObjectHasAttribute + { + self::createWarning('objectHasAttribute() is deprecated and will be removed in PHPUnit 10.'); + + return new ObjectHasAttribute($attributeName); + } + + public static function identicalTo($value): IsIdentical + { + return new IsIdentical($value); + } + + public static function isInstanceOf(string $className): IsInstanceOf + { + return new IsInstanceOf($className); + } + + public static function isType(string $type): IsType + { + return new IsType($type); + } + + public static function lessThan($value): LessThan + { + return new LessThan($value); + } + + public static function lessThanOrEqual($value): LogicalOr + { + return static::logicalOr( + new IsEqual($value), + new LessThan($value) + ); + } + + public static function matchesRegularExpression(string $pattern): RegularExpression + { + return new RegularExpression($pattern); + } + + public static function matches(string $string): StringMatchesFormatDescription + { + return new StringMatchesFormatDescription($string); + } + + public static function stringStartsWith($prefix): StringStartsWith + { + return new StringStartsWith($prefix); + } + + public static function stringContains(string $string, bool $case = true): StringContains + { + return new StringContains($string, $case); + } + + public static function stringEndsWith(string $suffix): StringEndsWith + { + return new StringEndsWith($suffix); + } + + public static function countOf(int $count): Count + { + return new Count($count); + } + + public static function objectEquals(object $object, string $method = 'equals'): ObjectEquals + { + return new ObjectEquals($object, $method); + } + + /** + * Fails a test with the given message. + * + * @throws AssertionFailedError + * + * @psalm-return never-return + */ + public static function fail(string $message = ''): void + { + self::$count++; + + throw new AssertionFailedError($message); + } + + /** + * Mark the test as incomplete. + * + * @throws IncompleteTestError + * + * @psalm-return never-return + */ + public static function markTestIncomplete(string $message = ''): void + { + throw new IncompleteTestError($message); + } + + /** + * Mark the test as skipped. + * + * @throws SkippedTestError + * @throws SyntheticSkippedError + * + * @psalm-return never-return + */ + public static function markTestSkipped(string $message = ''): void + { + if ($hint = self::detectLocationHint($message)) { + $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + array_unshift($trace, $hint); + + throw new SyntheticSkippedError($hint['message'], 0, $hint['file'], (int) $hint['line'], $trace); + } + + throw new SkippedTestError($message); + } + + /** + * Return the current assertion count. + */ + public static function getCount(): int + { + return self::$count; + } + + /** + * Reset the assertion counter. + */ + public static function resetCount(): void + { + self::$count = 0; + } + + private static function detectLocationHint(string $message): ?array + { + $hint = null; + $lines = preg_split('/\r\n|\r|\n/', $message); + + while (strpos($lines[0], '__OFFSET') !== false) { + $offset = explode('=', array_shift($lines)); + + if ($offset[0] === '__OFFSET_FILE') { + $hint['file'] = $offset[1]; + } + + if ($offset[0] === '__OFFSET_LINE') { + $hint['line'] = $offset[1]; + } + } + + if ($hint) { + $hint['message'] = implode(PHP_EOL, $lines); + } + + return $hint; + } + + private static function isValidObjectAttributeName(string $attributeName): bool + { + return (bool) preg_match('/[^\x00-\x1f\x7f-\x9f]+/', $attributeName); + } + + private static function isValidClassAttributeName(string $attributeName): bool + { + return (bool) preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName); + } + + /** + * @codeCoverageIgnore + */ + private static function createWarning(string $warning): void + { + foreach (debug_backtrace() as $step) { + if (isset($step['object']) && $step['object'] instanceof TestCase) { + assert($step['object'] instanceof TestCase); + + $step['object']->addWarning($warning); + + break; + } + } + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Assert/Functions.php b/vendor/phpunit/phpunit/src/Framework/Assert/Functions.php new file mode 100644 index 00000000..5b8c50ed --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Assert/Functions.php @@ -0,0 +1,3042 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function func_get_args; +use function function_exists; +use ArrayAccess; +use Countable; +use DOMDocument; +use DOMElement; +use PHPUnit\Framework\Constraint\ArrayHasKey; +use PHPUnit\Framework\Constraint\Callback; +use PHPUnit\Framework\Constraint\ClassHasAttribute; +use PHPUnit\Framework\Constraint\ClassHasStaticAttribute; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\Constraint\Count; +use PHPUnit\Framework\Constraint\DirectoryExists; +use PHPUnit\Framework\Constraint\FileExists; +use PHPUnit\Framework\Constraint\GreaterThan; +use PHPUnit\Framework\Constraint\IsAnything; +use PHPUnit\Framework\Constraint\IsEmpty; +use PHPUnit\Framework\Constraint\IsEqual; +use PHPUnit\Framework\Constraint\IsEqualCanonicalizing; +use PHPUnit\Framework\Constraint\IsEqualIgnoringCase; +use PHPUnit\Framework\Constraint\IsEqualWithDelta; +use PHPUnit\Framework\Constraint\IsFalse; +use PHPUnit\Framework\Constraint\IsFinite; +use PHPUnit\Framework\Constraint\IsIdentical; +use PHPUnit\Framework\Constraint\IsInfinite; +use PHPUnit\Framework\Constraint\IsInstanceOf; +use PHPUnit\Framework\Constraint\IsJson; +use PHPUnit\Framework\Constraint\IsNan; +use PHPUnit\Framework\Constraint\IsNull; +use PHPUnit\Framework\Constraint\IsReadable; +use PHPUnit\Framework\Constraint\IsTrue; +use PHPUnit\Framework\Constraint\IsType; +use PHPUnit\Framework\Constraint\IsWritable; +use PHPUnit\Framework\Constraint\LessThan; +use PHPUnit\Framework\Constraint\LogicalAnd; +use PHPUnit\Framework\Constraint\LogicalNot; +use PHPUnit\Framework\Constraint\LogicalOr; +use PHPUnit\Framework\Constraint\LogicalXor; +use PHPUnit\Framework\Constraint\ObjectEquals; +use PHPUnit\Framework\Constraint\ObjectHasAttribute; +use PHPUnit\Framework\Constraint\RegularExpression; +use PHPUnit\Framework\Constraint\StringContains; +use PHPUnit\Framework\Constraint\StringEndsWith; +use PHPUnit\Framework\Constraint\StringMatchesFormatDescription; +use PHPUnit\Framework\Constraint\StringStartsWith; +use PHPUnit\Framework\Constraint\TraversableContainsEqual; +use PHPUnit\Framework\Constraint\TraversableContainsIdentical; +use PHPUnit\Framework\Constraint\TraversableContainsOnly; +use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount as AnyInvokedCountMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedAtIndex as InvokedAtIndexMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastCount as InvokedAtLeastCountMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce as InvokedAtLeastOnceMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount as InvokedAtMostCountMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedCount as InvokedCountMatcher; +use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls as ConsecutiveCallsStub; +use PHPUnit\Framework\MockObject\Stub\Exception as ExceptionStub; +use PHPUnit\Framework\MockObject\Stub\ReturnArgument as ReturnArgumentStub; +use PHPUnit\Framework\MockObject\Stub\ReturnCallback as ReturnCallbackStub; +use PHPUnit\Framework\MockObject\Stub\ReturnSelf as ReturnSelfStub; +use PHPUnit\Framework\MockObject\Stub\ReturnStub; +use PHPUnit\Framework\MockObject\Stub\ReturnValueMap as ReturnValueMapStub; +use Throwable; + +if (!function_exists('PHPUnit\Framework\assertArrayHasKey')) { + /** + * Asserts that an array has a specified key. + * + * @param int|string $key + * @param array|ArrayAccess $array + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertArrayHasKey + */ + function assertArrayHasKey($key, $array, string $message = ''): void + { + Assert::assertArrayHasKey(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertArrayNotHasKey')) { + /** + * Asserts that an array does not have a specified key. + * + * @param int|string $key + * @param array|ArrayAccess $array + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertArrayNotHasKey + */ + function assertArrayNotHasKey($key, $array, string $message = ''): void + { + Assert::assertArrayNotHasKey(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertContains')) { + /** + * Asserts that a haystack contains a needle. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertContains + */ + function assertContains($needle, iterable $haystack, string $message = ''): void + { + Assert::assertContains(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertContainsEquals')) { + function assertContainsEquals($needle, iterable $haystack, string $message = ''): void + { + Assert::assertContainsEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotContains')) { + /** + * Asserts that a haystack does not contain a needle. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotContains + */ + function assertNotContains($needle, iterable $haystack, string $message = ''): void + { + Assert::assertNotContains(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotContainsEquals')) { + function assertNotContainsEquals($needle, iterable $haystack, string $message = ''): void + { + Assert::assertNotContainsEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertContainsOnly')) { + /** + * Asserts that a haystack contains only values of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertContainsOnly + */ + function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void + { + Assert::assertContainsOnly(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertContainsOnlyInstancesOf')) { + /** + * Asserts that a haystack contains only instances of a given class name. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertContainsOnlyInstancesOf + */ + function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = ''): void + { + Assert::assertContainsOnlyInstancesOf(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotContainsOnly')) { + /** + * Asserts that a haystack does not contain only values of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotContainsOnly + */ + function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void + { + Assert::assertNotContainsOnly(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertCount')) { + /** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @param Countable|iterable $haystack + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertCount + */ + function assertCount(int $expectedCount, $haystack, string $message = ''): void + { + Assert::assertCount(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotCount')) { + /** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @param Countable|iterable $haystack + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotCount + */ + function assertNotCount(int $expectedCount, $haystack, string $message = ''): void + { + Assert::assertNotCount(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertEquals')) { + /** + * Asserts that two variables are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertEquals + */ + function assertEquals($expected, $actual, string $message = ''): void + { + Assert::assertEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertEqualsCanonicalizing')) { + /** + * Asserts that two variables are equal (canonicalizing). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertEqualsCanonicalizing + */ + function assertEqualsCanonicalizing($expected, $actual, string $message = ''): void + { + Assert::assertEqualsCanonicalizing(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertEqualsIgnoringCase')) { + /** + * Asserts that two variables are equal (ignoring case). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertEqualsIgnoringCase + */ + function assertEqualsIgnoringCase($expected, $actual, string $message = ''): void + { + Assert::assertEqualsIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertEqualsWithDelta')) { + /** + * Asserts that two variables are equal (with delta). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertEqualsWithDelta + */ + function assertEqualsWithDelta($expected, $actual, float $delta, string $message = ''): void + { + Assert::assertEqualsWithDelta(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotEquals')) { + /** + * Asserts that two variables are not equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotEquals + */ + function assertNotEquals($expected, $actual, string $message = ''): void + { + Assert::assertNotEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotEqualsCanonicalizing')) { + /** + * Asserts that two variables are not equal (canonicalizing). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotEqualsCanonicalizing + */ + function assertNotEqualsCanonicalizing($expected, $actual, string $message = ''): void + { + Assert::assertNotEqualsCanonicalizing(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotEqualsIgnoringCase')) { + /** + * Asserts that two variables are not equal (ignoring case). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotEqualsIgnoringCase + */ + function assertNotEqualsIgnoringCase($expected, $actual, string $message = ''): void + { + Assert::assertNotEqualsIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotEqualsWithDelta')) { + /** + * Asserts that two variables are not equal (with delta). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotEqualsWithDelta + */ + function assertNotEqualsWithDelta($expected, $actual, float $delta, string $message = ''): void + { + Assert::assertNotEqualsWithDelta(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertObjectEquals')) { + /** + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertObjectEquals + */ + function assertObjectEquals(object $expected, object $actual, string $method = 'equals', string $message = ''): void + { + Assert::assertObjectEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertEmpty')) { + /** + * Asserts that a variable is empty. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert empty $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertEmpty + */ + function assertEmpty($actual, string $message = ''): void + { + Assert::assertEmpty(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotEmpty')) { + /** + * Asserts that a variable is not empty. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !empty $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotEmpty + */ + function assertNotEmpty($actual, string $message = ''): void + { + Assert::assertNotEmpty(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertGreaterThan')) { + /** + * Asserts that a value is greater than another value. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertGreaterThan + */ + function assertGreaterThan($expected, $actual, string $message = ''): void + { + Assert::assertGreaterThan(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertGreaterThanOrEqual')) { + /** + * Asserts that a value is greater than or equal to another value. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertGreaterThanOrEqual + */ + function assertGreaterThanOrEqual($expected, $actual, string $message = ''): void + { + Assert::assertGreaterThanOrEqual(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertLessThan')) { + /** + * Asserts that a value is smaller than another value. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertLessThan + */ + function assertLessThan($expected, $actual, string $message = ''): void + { + Assert::assertLessThan(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertLessThanOrEqual')) { + /** + * Asserts that a value is smaller than or equal to another value. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertLessThanOrEqual + */ + function assertLessThanOrEqual($expected, $actual, string $message = ''): void + { + Assert::assertLessThanOrEqual(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileEquals')) { + /** + * Asserts that the contents of one file is equal to the contents of another + * file. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileEquals + */ + function assertFileEquals(string $expected, string $actual, string $message = ''): void + { + Assert::assertFileEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileEqualsCanonicalizing')) { + /** + * Asserts that the contents of one file is equal to the contents of another + * file (canonicalizing). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileEqualsCanonicalizing + */ + function assertFileEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void + { + Assert::assertFileEqualsCanonicalizing(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileEqualsIgnoringCase')) { + /** + * Asserts that the contents of one file is equal to the contents of another + * file (ignoring case). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileEqualsIgnoringCase + */ + function assertFileEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void + { + Assert::assertFileEqualsIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileNotEquals')) { + /** + * Asserts that the contents of one file is not equal to the contents of + * another file. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileNotEquals + */ + function assertFileNotEquals(string $expected, string $actual, string $message = ''): void + { + Assert::assertFileNotEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileNotEqualsCanonicalizing')) { + /** + * Asserts that the contents of one file is not equal to the contents of another + * file (canonicalizing). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileNotEqualsCanonicalizing + */ + function assertFileNotEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void + { + Assert::assertFileNotEqualsCanonicalizing(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileNotEqualsIgnoringCase')) { + /** + * Asserts that the contents of one file is not equal to the contents of another + * file (ignoring case). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileNotEqualsIgnoringCase + */ + function assertFileNotEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void + { + Assert::assertFileNotEqualsIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringEqualsFile')) { + /** + * Asserts that the contents of a string is equal + * to the contents of a file. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringEqualsFile + */ + function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = ''): void + { + Assert::assertStringEqualsFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringEqualsFileCanonicalizing')) { + /** + * Asserts that the contents of a string is equal + * to the contents of a file (canonicalizing). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringEqualsFileCanonicalizing + */ + function assertStringEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void + { + Assert::assertStringEqualsFileCanonicalizing(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringEqualsFileIgnoringCase')) { + /** + * Asserts that the contents of a string is equal + * to the contents of a file (ignoring case). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringEqualsFileIgnoringCase + */ + function assertStringEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void + { + Assert::assertStringEqualsFileIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringNotEqualsFile')) { + /** + * Asserts that the contents of a string is not equal + * to the contents of a file. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringNotEqualsFile + */ + function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = ''): void + { + Assert::assertStringNotEqualsFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringNotEqualsFileCanonicalizing')) { + /** + * Asserts that the contents of a string is not equal + * to the contents of a file (canonicalizing). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringNotEqualsFileCanonicalizing + */ + function assertStringNotEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void + { + Assert::assertStringNotEqualsFileCanonicalizing(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringNotEqualsFileIgnoringCase')) { + /** + * Asserts that the contents of a string is not equal + * to the contents of a file (ignoring case). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringNotEqualsFileIgnoringCase + */ + function assertStringNotEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void + { + Assert::assertStringNotEqualsFileIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsReadable')) { + /** + * Asserts that a file/dir is readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsReadable + */ + function assertIsReadable(string $filename, string $message = ''): void + { + Assert::assertIsReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotReadable')) { + /** + * Asserts that a file/dir exists and is not readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotReadable + */ + function assertIsNotReadable(string $filename, string $message = ''): void + { + Assert::assertIsNotReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotIsReadable')) { + /** + * Asserts that a file/dir exists and is not readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4062 + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotIsReadable + */ + function assertNotIsReadable(string $filename, string $message = ''): void + { + Assert::assertNotIsReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsWritable')) { + /** + * Asserts that a file/dir exists and is writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsWritable + */ + function assertIsWritable(string $filename, string $message = ''): void + { + Assert::assertIsWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotWritable')) { + /** + * Asserts that a file/dir exists and is not writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotWritable + */ + function assertIsNotWritable(string $filename, string $message = ''): void + { + Assert::assertIsNotWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotIsWritable')) { + /** + * Asserts that a file/dir exists and is not writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4065 + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotIsWritable + */ + function assertNotIsWritable(string $filename, string $message = ''): void + { + Assert::assertNotIsWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryExists')) { + /** + * Asserts that a directory exists. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryExists + */ + function assertDirectoryExists(string $directory, string $message = ''): void + { + Assert::assertDirectoryExists(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryDoesNotExist')) { + /** + * Asserts that a directory does not exist. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryDoesNotExist + */ + function assertDirectoryDoesNotExist(string $directory, string $message = ''): void + { + Assert::assertDirectoryDoesNotExist(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryNotExists')) { + /** + * Asserts that a directory does not exist. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4068 + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryNotExists + */ + function assertDirectoryNotExists(string $directory, string $message = ''): void + { + Assert::assertDirectoryNotExists(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryIsReadable')) { + /** + * Asserts that a directory exists and is readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryIsReadable + */ + function assertDirectoryIsReadable(string $directory, string $message = ''): void + { + Assert::assertDirectoryIsReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryIsNotReadable')) { + /** + * Asserts that a directory exists and is not readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryIsNotReadable + */ + function assertDirectoryIsNotReadable(string $directory, string $message = ''): void + { + Assert::assertDirectoryIsNotReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryNotIsReadable')) { + /** + * Asserts that a directory exists and is not readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4071 + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryNotIsReadable + */ + function assertDirectoryNotIsReadable(string $directory, string $message = ''): void + { + Assert::assertDirectoryNotIsReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryIsWritable')) { + /** + * Asserts that a directory exists and is writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryIsWritable + */ + function assertDirectoryIsWritable(string $directory, string $message = ''): void + { + Assert::assertDirectoryIsWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryIsNotWritable')) { + /** + * Asserts that a directory exists and is not writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryIsNotWritable + */ + function assertDirectoryIsNotWritable(string $directory, string $message = ''): void + { + Assert::assertDirectoryIsNotWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryNotIsWritable')) { + /** + * Asserts that a directory exists and is not writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4074 + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryNotIsWritable + */ + function assertDirectoryNotIsWritable(string $directory, string $message = ''): void + { + Assert::assertDirectoryNotIsWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileExists')) { + /** + * Asserts that a file exists. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileExists + */ + function assertFileExists(string $filename, string $message = ''): void + { + Assert::assertFileExists(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileDoesNotExist')) { + /** + * Asserts that a file does not exist. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileDoesNotExist + */ + function assertFileDoesNotExist(string $filename, string $message = ''): void + { + Assert::assertFileDoesNotExist(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileNotExists')) { + /** + * Asserts that a file does not exist. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4077 + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileNotExists + */ + function assertFileNotExists(string $filename, string $message = ''): void + { + Assert::assertFileNotExists(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileIsReadable')) { + /** + * Asserts that a file exists and is readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileIsReadable + */ + function assertFileIsReadable(string $file, string $message = ''): void + { + Assert::assertFileIsReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileIsNotReadable')) { + /** + * Asserts that a file exists and is not readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileIsNotReadable + */ + function assertFileIsNotReadable(string $file, string $message = ''): void + { + Assert::assertFileIsNotReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileNotIsReadable')) { + /** + * Asserts that a file exists and is not readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4080 + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileNotIsReadable + */ + function assertFileNotIsReadable(string $file, string $message = ''): void + { + Assert::assertFileNotIsReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileIsWritable')) { + /** + * Asserts that a file exists and is writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileIsWritable + */ + function assertFileIsWritable(string $file, string $message = ''): void + { + Assert::assertFileIsWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileIsNotWritable')) { + /** + * Asserts that a file exists and is not writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileIsNotWritable + */ + function assertFileIsNotWritable(string $file, string $message = ''): void + { + Assert::assertFileIsNotWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileNotIsWritable')) { + /** + * Asserts that a file exists and is not writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4083 + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileNotIsWritable + */ + function assertFileNotIsWritable(string $file, string $message = ''): void + { + Assert::assertFileNotIsWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertTrue')) { + /** + * Asserts that a condition is true. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert true $condition + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertTrue + */ + function assertTrue($condition, string $message = ''): void + { + Assert::assertTrue(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotTrue')) { + /** + * Asserts that a condition is not true. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !true $condition + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotTrue + */ + function assertNotTrue($condition, string $message = ''): void + { + Assert::assertNotTrue(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFalse')) { + /** + * Asserts that a condition is false. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert false $condition + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFalse + */ + function assertFalse($condition, string $message = ''): void + { + Assert::assertFalse(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotFalse')) { + /** + * Asserts that a condition is not false. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !false $condition + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotFalse + */ + function assertNotFalse($condition, string $message = ''): void + { + Assert::assertNotFalse(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNull')) { + /** + * Asserts that a variable is null. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert null $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNull + */ + function assertNull($actual, string $message = ''): void + { + Assert::assertNull(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotNull')) { + /** + * Asserts that a variable is not null. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !null $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotNull + */ + function assertNotNull($actual, string $message = ''): void + { + Assert::assertNotNull(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFinite')) { + /** + * Asserts that a variable is finite. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFinite + */ + function assertFinite($actual, string $message = ''): void + { + Assert::assertFinite(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertInfinite')) { + /** + * Asserts that a variable is infinite. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertInfinite + */ + function assertInfinite($actual, string $message = ''): void + { + Assert::assertInfinite(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNan')) { + /** + * Asserts that a variable is nan. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNan + */ + function assertNan($actual, string $message = ''): void + { + Assert::assertNan(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertClassHasAttribute')) { + /** + * Asserts that a class has a specified attribute. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertClassHasAttribute + */ + function assertClassHasAttribute(string $attributeName, string $className, string $message = ''): void + { + Assert::assertClassHasAttribute(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertClassNotHasAttribute')) { + /** + * Asserts that a class does not have a specified attribute. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertClassNotHasAttribute + */ + function assertClassNotHasAttribute(string $attributeName, string $className, string $message = ''): void + { + Assert::assertClassNotHasAttribute(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertClassHasStaticAttribute')) { + /** + * Asserts that a class has a specified static attribute. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertClassHasStaticAttribute + */ + function assertClassHasStaticAttribute(string $attributeName, string $className, string $message = ''): void + { + Assert::assertClassHasStaticAttribute(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertClassNotHasStaticAttribute')) { + /** + * Asserts that a class does not have a specified static attribute. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertClassNotHasStaticAttribute + */ + function assertClassNotHasStaticAttribute(string $attributeName, string $className, string $message = ''): void + { + Assert::assertClassNotHasStaticAttribute(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertObjectHasAttribute')) { + /** + * Asserts that an object has a specified attribute. + * + * @param object $object + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertObjectHasAttribute + */ + function assertObjectHasAttribute(string $attributeName, $object, string $message = ''): void + { + Assert::assertObjectHasAttribute(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertObjectNotHasAttribute')) { + /** + * Asserts that an object does not have a specified attribute. + * + * @param object $object + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertObjectNotHasAttribute + */ + function assertObjectNotHasAttribute(string $attributeName, $object, string $message = ''): void + { + Assert::assertObjectNotHasAttribute(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertSame')) { + /** + * Asserts that two variables have the same type and value. + * Used on objects, it asserts that two variables reference + * the same object. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-template ExpectedType + * + * @psalm-param ExpectedType $expected + * + * @psalm-assert =ExpectedType $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertSame + */ + function assertSame($expected, $actual, string $message = ''): void + { + Assert::assertSame(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotSame')) { + /** + * Asserts that two variables do not have the same type and value. + * Used on objects, it asserts that two variables do not reference + * the same object. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotSame + */ + function assertNotSame($expected, $actual, string $message = ''): void + { + Assert::assertNotSame(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertInstanceOf')) { + /** + * Asserts that a variable is of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @psalm-template ExpectedType of object + * + * @psalm-param class-string $expected + * + * @psalm-assert =ExpectedType $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertInstanceOf + */ + function assertInstanceOf(string $expected, $actual, string $message = ''): void + { + Assert::assertInstanceOf(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotInstanceOf')) { + /** + * Asserts that a variable is not of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @psalm-template ExpectedType of object + * + * @psalm-param class-string $expected + * + * @psalm-assert !ExpectedType $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotInstanceOf + */ + function assertNotInstanceOf(string $expected, $actual, string $message = ''): void + { + Assert::assertNotInstanceOf(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsArray')) { + /** + * Asserts that a variable is of type array. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert array $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsArray + */ + function assertIsArray($actual, string $message = ''): void + { + Assert::assertIsArray(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsBool')) { + /** + * Asserts that a variable is of type bool. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert bool $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsBool + */ + function assertIsBool($actual, string $message = ''): void + { + Assert::assertIsBool(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsFloat')) { + /** + * Asserts that a variable is of type float. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert float $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsFloat + */ + function assertIsFloat($actual, string $message = ''): void + { + Assert::assertIsFloat(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsInt')) { + /** + * Asserts that a variable is of type int. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert int $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsInt + */ + function assertIsInt($actual, string $message = ''): void + { + Assert::assertIsInt(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNumeric')) { + /** + * Asserts that a variable is of type numeric. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert numeric $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNumeric + */ + function assertIsNumeric($actual, string $message = ''): void + { + Assert::assertIsNumeric(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsObject')) { + /** + * Asserts that a variable is of type object. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert object $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsObject + */ + function assertIsObject($actual, string $message = ''): void + { + Assert::assertIsObject(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsResource')) { + /** + * Asserts that a variable is of type resource. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert resource $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsResource + */ + function assertIsResource($actual, string $message = ''): void + { + Assert::assertIsResource(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsClosedResource')) { + /** + * Asserts that a variable is of type resource and is closed. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert resource $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsClosedResource + */ + function assertIsClosedResource($actual, string $message = ''): void + { + Assert::assertIsClosedResource(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsString')) { + /** + * Asserts that a variable is of type string. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert string $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsString + */ + function assertIsString($actual, string $message = ''): void + { + Assert::assertIsString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsScalar')) { + /** + * Asserts that a variable is of type scalar. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert scalar $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsScalar + */ + function assertIsScalar($actual, string $message = ''): void + { + Assert::assertIsScalar(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsCallable')) { + /** + * Asserts that a variable is of type callable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert callable $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsCallable + */ + function assertIsCallable($actual, string $message = ''): void + { + Assert::assertIsCallable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsIterable')) { + /** + * Asserts that a variable is of type iterable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert iterable $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsIterable + */ + function assertIsIterable($actual, string $message = ''): void + { + Assert::assertIsIterable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotArray')) { + /** + * Asserts that a variable is not of type array. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !array $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotArray + */ + function assertIsNotArray($actual, string $message = ''): void + { + Assert::assertIsNotArray(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotBool')) { + /** + * Asserts that a variable is not of type bool. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !bool $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotBool + */ + function assertIsNotBool($actual, string $message = ''): void + { + Assert::assertIsNotBool(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotFloat')) { + /** + * Asserts that a variable is not of type float. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !float $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotFloat + */ + function assertIsNotFloat($actual, string $message = ''): void + { + Assert::assertIsNotFloat(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotInt')) { + /** + * Asserts that a variable is not of type int. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !int $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotInt + */ + function assertIsNotInt($actual, string $message = ''): void + { + Assert::assertIsNotInt(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotNumeric')) { + /** + * Asserts that a variable is not of type numeric. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !numeric $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotNumeric + */ + function assertIsNotNumeric($actual, string $message = ''): void + { + Assert::assertIsNotNumeric(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotObject')) { + /** + * Asserts that a variable is not of type object. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !object $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotObject + */ + function assertIsNotObject($actual, string $message = ''): void + { + Assert::assertIsNotObject(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotResource')) { + /** + * Asserts that a variable is not of type resource. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !resource $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotResource + */ + function assertIsNotResource($actual, string $message = ''): void + { + Assert::assertIsNotResource(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotClosedResource')) { + /** + * Asserts that a variable is not of type resource. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !resource $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotClosedResource + */ + function assertIsNotClosedResource($actual, string $message = ''): void + { + Assert::assertIsNotClosedResource(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotString')) { + /** + * Asserts that a variable is not of type string. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !string $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotString + */ + function assertIsNotString($actual, string $message = ''): void + { + Assert::assertIsNotString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotScalar')) { + /** + * Asserts that a variable is not of type scalar. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !scalar $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotScalar + */ + function assertIsNotScalar($actual, string $message = ''): void + { + Assert::assertIsNotScalar(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotCallable')) { + /** + * Asserts that a variable is not of type callable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !callable $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotCallable + */ + function assertIsNotCallable($actual, string $message = ''): void + { + Assert::assertIsNotCallable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotIterable')) { + /** + * Asserts that a variable is not of type iterable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @psalm-assert !iterable $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotIterable + */ + function assertIsNotIterable($actual, string $message = ''): void + { + Assert::assertIsNotIterable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertMatchesRegularExpression')) { + /** + * Asserts that a string matches a given regular expression. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertMatchesRegularExpression + */ + function assertMatchesRegularExpression(string $pattern, string $string, string $message = ''): void + { + Assert::assertMatchesRegularExpression(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertRegExp')) { + /** + * Asserts that a string matches a given regular expression. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4086 + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertRegExp + */ + function assertRegExp(string $pattern, string $string, string $message = ''): void + { + Assert::assertRegExp(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDoesNotMatchRegularExpression')) { + /** + * Asserts that a string does not match a given regular expression. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDoesNotMatchRegularExpression + */ + function assertDoesNotMatchRegularExpression(string $pattern, string $string, string $message = ''): void + { + Assert::assertDoesNotMatchRegularExpression(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotRegExp')) { + /** + * Asserts that a string does not match a given regular expression. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4089 + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotRegExp + */ + function assertNotRegExp(string $pattern, string $string, string $message = ''): void + { + Assert::assertNotRegExp(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertSameSize')) { + /** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is the same. + * + * @param Countable|iterable $expected + * @param Countable|iterable $actual + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertSameSize + */ + function assertSameSize($expected, $actual, string $message = ''): void + { + Assert::assertSameSize(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotSameSize')) { + /** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is not the same. + * + * @param Countable|iterable $expected + * @param Countable|iterable $actual + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotSameSize + */ + function assertNotSameSize($expected, $actual, string $message = ''): void + { + Assert::assertNotSameSize(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringMatchesFormat')) { + /** + * Asserts that a string matches a given format string. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringMatchesFormat + */ + function assertStringMatchesFormat(string $format, string $string, string $message = ''): void + { + Assert::assertStringMatchesFormat(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringNotMatchesFormat')) { + /** + * Asserts that a string does not match a given format string. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringNotMatchesFormat + */ + function assertStringNotMatchesFormat(string $format, string $string, string $message = ''): void + { + Assert::assertStringNotMatchesFormat(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringMatchesFormatFile')) { + /** + * Asserts that a string matches a given format file. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringMatchesFormatFile + */ + function assertStringMatchesFormatFile(string $formatFile, string $string, string $message = ''): void + { + Assert::assertStringMatchesFormatFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringNotMatchesFormatFile')) { + /** + * Asserts that a string does not match a given format string. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringNotMatchesFormatFile + */ + function assertStringNotMatchesFormatFile(string $formatFile, string $string, string $message = ''): void + { + Assert::assertStringNotMatchesFormatFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringStartsWith')) { + /** + * Asserts that a string starts with a given prefix. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringStartsWith + */ + function assertStringStartsWith(string $prefix, string $string, string $message = ''): void + { + Assert::assertStringStartsWith(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringStartsNotWith')) { + /** + * Asserts that a string starts not with a given prefix. + * + * @param string $prefix + * @param string $string + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringStartsNotWith + */ + function assertStringStartsNotWith($prefix, $string, string $message = ''): void + { + Assert::assertStringStartsNotWith(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringContainsString')) { + /** + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringContainsString + */ + function assertStringContainsString(string $needle, string $haystack, string $message = ''): void + { + Assert::assertStringContainsString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringContainsStringIgnoringCase')) { + /** + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringContainsStringIgnoringCase + */ + function assertStringContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void + { + Assert::assertStringContainsStringIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringNotContainsString')) { + /** + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringNotContainsString + */ + function assertStringNotContainsString(string $needle, string $haystack, string $message = ''): void + { + Assert::assertStringNotContainsString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringNotContainsStringIgnoringCase')) { + /** + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringNotContainsStringIgnoringCase + */ + function assertStringNotContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void + { + Assert::assertStringNotContainsStringIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringEndsWith')) { + /** + * Asserts that a string ends with a given suffix. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringEndsWith + */ + function assertStringEndsWith(string $suffix, string $string, string $message = ''): void + { + Assert::assertStringEndsWith(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringEndsNotWith')) { + /** + * Asserts that a string ends not with a given suffix. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringEndsNotWith + */ + function assertStringEndsNotWith(string $suffix, string $string, string $message = ''): void + { + Assert::assertStringEndsNotWith(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertXmlFileEqualsXmlFile')) { + /** + * Asserts that two XML files are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertXmlFileEqualsXmlFile + */ + function assertXmlFileEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void + { + Assert::assertXmlFileEqualsXmlFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertXmlFileNotEqualsXmlFile')) { + /** + * Asserts that two XML files are not equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws \PHPUnit\Util\Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertXmlFileNotEqualsXmlFile + */ + function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void + { + Assert::assertXmlFileNotEqualsXmlFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertXmlStringEqualsXmlFile')) { + /** + * Asserts that two XML documents are equal. + * + * @param DOMDocument|string $actualXml + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws \PHPUnit\Util\Xml\Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertXmlStringEqualsXmlFile + */ + function assertXmlStringEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void + { + Assert::assertXmlStringEqualsXmlFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertXmlStringNotEqualsXmlFile')) { + /** + * Asserts that two XML documents are not equal. + * + * @param DOMDocument|string $actualXml + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws \PHPUnit\Util\Xml\Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertXmlStringNotEqualsXmlFile + */ + function assertXmlStringNotEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void + { + Assert::assertXmlStringNotEqualsXmlFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertXmlStringEqualsXmlString')) { + /** + * Asserts that two XML documents are equal. + * + * @param DOMDocument|string $expectedXml + * @param DOMDocument|string $actualXml + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws \PHPUnit\Util\Xml\Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertXmlStringEqualsXmlString + */ + function assertXmlStringEqualsXmlString($expectedXml, $actualXml, string $message = ''): void + { + Assert::assertXmlStringEqualsXmlString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertXmlStringNotEqualsXmlString')) { + /** + * Asserts that two XML documents are not equal. + * + * @param DOMDocument|string $expectedXml + * @param DOMDocument|string $actualXml + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws \PHPUnit\Util\Xml\Exception + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertXmlStringNotEqualsXmlString + */ + function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, string $message = ''): void + { + Assert::assertXmlStringNotEqualsXmlString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertEqualXMLStructure')) { + /** + * Asserts that a hierarchy of DOMElements matches. + * + * @throws AssertionFailedError + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @codeCoverageIgnore + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4091 + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertEqualXMLStructure + */ + function assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, bool $checkAttributes = false, string $message = ''): void + { + Assert::assertEqualXMLStructure(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertThat')) { + /** + * Evaluates a PHPUnit\Framework\Constraint matcher object. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertThat + */ + function assertThat($value, Constraint $constraint, string $message = ''): void + { + Assert::assertThat(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertJson')) { + /** + * Asserts that a string is a valid JSON string. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertJson + */ + function assertJson(string $actualJson, string $message = ''): void + { + Assert::assertJson(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertJsonStringEqualsJsonString')) { + /** + * Asserts that two given JSON encoded objects or arrays are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertJsonStringEqualsJsonString + */ + function assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void + { + Assert::assertJsonStringEqualsJsonString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertJsonStringNotEqualsJsonString')) { + /** + * Asserts that two given JSON encoded objects or arrays are not equal. + * + * @param string $expectedJson + * @param string $actualJson + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertJsonStringNotEqualsJsonString + */ + function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, string $message = ''): void + { + Assert::assertJsonStringNotEqualsJsonString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertJsonStringEqualsJsonFile')) { + /** + * Asserts that the generated JSON encoded object and the content of the given file are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertJsonStringEqualsJsonFile + */ + function assertJsonStringEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void + { + Assert::assertJsonStringEqualsJsonFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertJsonStringNotEqualsJsonFile')) { + /** + * Asserts that the generated JSON encoded object and the content of the given file are not equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertJsonStringNotEqualsJsonFile + */ + function assertJsonStringNotEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void + { + Assert::assertJsonStringNotEqualsJsonFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertJsonFileEqualsJsonFile')) { + /** + * Asserts that two JSON files are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertJsonFileEqualsJsonFile + */ + function assertJsonFileEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void + { + Assert::assertJsonFileEqualsJsonFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertJsonFileNotEqualsJsonFile')) { + /** + * Asserts that two JSON files are not equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertJsonFileNotEqualsJsonFile + */ + function assertJsonFileNotEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void + { + Assert::assertJsonFileNotEqualsJsonFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\logicalAnd')) { + function logicalAnd(): LogicalAnd + { + return Assert::logicalAnd(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\logicalOr')) { + function logicalOr(): LogicalOr + { + return Assert::logicalOr(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\logicalNot')) { + function logicalNot(Constraint $constraint): LogicalNot + { + return Assert::logicalNot(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\logicalXor')) { + function logicalXor(): LogicalXor + { + return Assert::logicalXor(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\anything')) { + function anything(): IsAnything + { + return Assert::anything(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isTrue')) { + function isTrue(): IsTrue + { + return Assert::isTrue(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\callback')) { + function callback(callable $callback): Callback + { + return Assert::callback(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isFalse')) { + function isFalse(): IsFalse + { + return Assert::isFalse(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isJson')) { + function isJson(): IsJson + { + return Assert::isJson(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isNull')) { + function isNull(): IsNull + { + return Assert::isNull(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isFinite')) { + function isFinite(): IsFinite + { + return Assert::isFinite(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isInfinite')) { + function isInfinite(): IsInfinite + { + return Assert::isInfinite(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isNan')) { + function isNan(): IsNan + { + return Assert::isNan(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\containsEqual')) { + function containsEqual($value): TraversableContainsEqual + { + return Assert::containsEqual(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\containsIdentical')) { + function containsIdentical($value): TraversableContainsIdentical + { + return Assert::containsIdentical(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\containsOnly')) { + function containsOnly(string $type): TraversableContainsOnly + { + return Assert::containsOnly(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\containsOnlyInstancesOf')) { + function containsOnlyInstancesOf(string $className): TraversableContainsOnly + { + return Assert::containsOnlyInstancesOf(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\arrayHasKey')) { + function arrayHasKey($key): ArrayHasKey + { + return Assert::arrayHasKey(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\equalTo')) { + function equalTo($value): IsEqual + { + return Assert::equalTo(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\equalToCanonicalizing')) { + function equalToCanonicalizing($value): IsEqualCanonicalizing + { + return Assert::equalToCanonicalizing(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\equalToIgnoringCase')) { + function equalToIgnoringCase($value): IsEqualIgnoringCase + { + return Assert::equalToIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\equalToWithDelta')) { + function equalToWithDelta($value, float $delta): IsEqualWithDelta + { + return Assert::equalToWithDelta(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isEmpty')) { + function isEmpty(): IsEmpty + { + return Assert::isEmpty(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isWritable')) { + function isWritable(): IsWritable + { + return Assert::isWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isReadable')) { + function isReadable(): IsReadable + { + return Assert::isReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\directoryExists')) { + function directoryExists(): DirectoryExists + { + return Assert::directoryExists(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\fileExists')) { + function fileExists(): FileExists + { + return Assert::fileExists(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\greaterThan')) { + function greaterThan($value): GreaterThan + { + return Assert::greaterThan(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\greaterThanOrEqual')) { + function greaterThanOrEqual($value): LogicalOr + { + return Assert::greaterThanOrEqual(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\classHasAttribute')) { + function classHasAttribute(string $attributeName): ClassHasAttribute + { + return Assert::classHasAttribute(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\classHasStaticAttribute')) { + function classHasStaticAttribute(string $attributeName): ClassHasStaticAttribute + { + return Assert::classHasStaticAttribute(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\objectHasAttribute')) { + function objectHasAttribute($attributeName): ObjectHasAttribute + { + return Assert::objectHasAttribute(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\identicalTo')) { + function identicalTo($value): IsIdentical + { + return Assert::identicalTo(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isInstanceOf')) { + function isInstanceOf(string $className): IsInstanceOf + { + return Assert::isInstanceOf(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isType')) { + function isType(string $type): IsType + { + return Assert::isType(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\lessThan')) { + function lessThan($value): LessThan + { + return Assert::lessThan(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\lessThanOrEqual')) { + function lessThanOrEqual($value): LogicalOr + { + return Assert::lessThanOrEqual(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\matchesRegularExpression')) { + function matchesRegularExpression(string $pattern): RegularExpression + { + return Assert::matchesRegularExpression(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\matches')) { + function matches(string $string): StringMatchesFormatDescription + { + return Assert::matches(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\stringStartsWith')) { + function stringStartsWith($prefix): StringStartsWith + { + return Assert::stringStartsWith(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\stringContains')) { + function stringContains(string $string, bool $case = true): StringContains + { + return Assert::stringContains(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\stringEndsWith')) { + function stringEndsWith(string $suffix): StringEndsWith + { + return Assert::stringEndsWith(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\countOf')) { + function countOf(int $count): Count + { + return Assert::countOf(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\objectEquals')) { + function objectEquals(object $object, string $method = 'equals'): ObjectEquals + { + return Assert::objectEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\any')) { + /** + * Returns a matcher that matches when the method is executed + * zero or more times. + */ + function any(): AnyInvokedCountMatcher + { + return new AnyInvokedCountMatcher; + } +} + +if (!function_exists('PHPUnit\Framework\never')) { + /** + * Returns a matcher that matches when the method is never executed. + */ + function never(): InvokedCountMatcher + { + return new InvokedCountMatcher(0); + } +} + +if (!function_exists('PHPUnit\Framework\atLeast')) { + /** + * Returns a matcher that matches when the method is executed + * at least N times. + */ + function atLeast(int $requiredInvocations): InvokedAtLeastCountMatcher + { + return new InvokedAtLeastCountMatcher( + $requiredInvocations + ); + } +} + +if (!function_exists('PHPUnit\Framework\atLeastOnce')) { + /** + * Returns a matcher that matches when the method is executed at least once. + */ + function atLeastOnce(): InvokedAtLeastOnceMatcher + { + return new InvokedAtLeastOnceMatcher; + } +} + +if (!function_exists('PHPUnit\Framework\once')) { + /** + * Returns a matcher that matches when the method is executed exactly once. + */ + function once(): InvokedCountMatcher + { + return new InvokedCountMatcher(1); + } +} + +if (!function_exists('PHPUnit\Framework\exactly')) { + /** + * Returns a matcher that matches when the method is executed + * exactly $count times. + */ + function exactly(int $count): InvokedCountMatcher + { + return new InvokedCountMatcher($count); + } +} + +if (!function_exists('PHPUnit\Framework\atMost')) { + /** + * Returns a matcher that matches when the method is executed + * at most N times. + */ + function atMost(int $allowedInvocations): InvokedAtMostCountMatcher + { + return new InvokedAtMostCountMatcher($allowedInvocations); + } +} + +if (!function_exists('PHPUnit\Framework\at')) { + /** + * Returns a matcher that matches when the method is executed + * at the given index. + */ + function at(int $index): InvokedAtIndexMatcher + { + return new InvokedAtIndexMatcher($index); + } +} + +if (!function_exists('PHPUnit\Framework\returnValue')) { + function returnValue($value): ReturnStub + { + return new ReturnStub($value); + } +} + +if (!function_exists('PHPUnit\Framework\returnValueMap')) { + function returnValueMap(array $valueMap): ReturnValueMapStub + { + return new ReturnValueMapStub($valueMap); + } +} + +if (!function_exists('PHPUnit\Framework\returnArgument')) { + function returnArgument(int $argumentIndex): ReturnArgumentStub + { + return new ReturnArgumentStub($argumentIndex); + } +} + +if (!function_exists('PHPUnit\Framework\returnCallback')) { + function returnCallback($callback): ReturnCallbackStub + { + return new ReturnCallbackStub($callback); + } +} + +if (!function_exists('PHPUnit\Framework\returnSelf')) { + /** + * Returns the current object. + * + * This method is useful when mocking a fluent interface. + */ + function returnSelf(): ReturnSelfStub + { + return new ReturnSelfStub; + } +} + +if (!function_exists('PHPUnit\Framework\throwException')) { + function throwException(Throwable $exception): ExceptionStub + { + return new ExceptionStub($exception); + } +} + +if (!function_exists('PHPUnit\Framework\onConsecutiveCalls')) { + function onConsecutiveCalls(): ConsecutiveCallsStub + { + $args = func_get_args(); + + return new ConsecutiveCallsStub($args); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php new file mode 100644 index 00000000..212e2bcb --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsFalse extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is false'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return $other === false; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php new file mode 100644 index 00000000..e1d6b269 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsTrue extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is true'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return $other === true; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Callback.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Callback.php new file mode 100644 index 00000000..b7cf95a1 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Callback.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @psalm-template CallbackInput of mixed + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Callback extends Constraint +{ + /** + * @var callable + * + * @psalm-var callable(CallbackInput $input): bool + */ + private $callback; + + /** @psalm-param callable(CallbackInput $input): bool $callback */ + public function __construct(callable $callback) + { + $this->callback = $callback; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is accepted by specified callback'; + } + + /** + * Evaluates the constraint for parameter $value. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + * + * @psalm-param CallbackInput $other + */ + protected function matches($other): bool + { + return ($this->callback)($other); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php new file mode 100644 index 00000000..8e27fbfd --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function count; +use function is_array; +use function iterator_count; +use function sprintf; +use Countable; +use EmptyIterator; +use Generator; +use Iterator; +use IteratorAggregate; +use PHPUnit\Framework\Exception; +use Traversable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +class Count extends Constraint +{ + /** + * @var int + */ + private $expectedCount; + + public function __construct(int $expected) + { + $this->expectedCount = $expected; + } + + public function toString(): string + { + return sprintf( + 'count matches %d', + $this->expectedCount + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @throws Exception + */ + protected function matches($other): bool + { + return $this->expectedCount === $this->getCountOf($other); + } + + /** + * @throws Exception + */ + protected function getCountOf($other): ?int + { + if ($other instanceof Countable || is_array($other)) { + return count($other); + } + + if ($other instanceof EmptyIterator) { + return 0; + } + + if ($other instanceof Traversable) { + while ($other instanceof IteratorAggregate) { + try { + $other = $other->getIterator(); + } catch (\Exception $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + } + + $iterator = $other; + + if ($iterator instanceof Generator) { + return $this->getCountOfGenerator($iterator); + } + + if (!$iterator instanceof Iterator) { + return iterator_count($iterator); + } + + $key = $iterator->key(); + $count = iterator_count($iterator); + + // Manually rewind $iterator to previous key, since iterator_count + // moves pointer. + if ($key !== null) { + $iterator->rewind(); + + while ($iterator->valid() && $key !== $iterator->key()) { + $iterator->next(); + } + } + + return $count; + } + + return null; + } + + /** + * Returns the total number of iterations from a generator. + * This will fully exhaust the generator. + */ + protected function getCountOfGenerator(Generator $generator): int + { + for ($count = 0; $generator->valid(); $generator->next()) { + $count++; + } + + return $count; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + return sprintf( + 'actual size %d matches expected size %d', + (int) $this->getCountOf($other), + $this->expectedCount + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php new file mode 100644 index 00000000..31df5020 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class GreaterThan extends Constraint +{ + /** + * @var float|int + */ + private $value; + + /** + * @param float|int $value + */ + public function __construct($value) + { + $this->value = $value; + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + return 'is greater than ' . $this->exporter()->export($this->value); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return $this->value < $other; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php new file mode 100644 index 00000000..e6371d53 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function count; +use function gettype; +use function sprintf; +use function strpos; +use Countable; +use EmptyIterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsEmpty extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is empty'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + if ($other instanceof EmptyIterator) { + return true; + } + + if ($other instanceof Countable) { + return count($other) === 0; + } + + return empty($other); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + $type = gettype($other); + + return sprintf( + '%s %s %s', + strpos($type, 'a') === 0 || strpos($type, 'o') === 0 ? 'an' : 'a', + $type, + $this->toString() + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php new file mode 100644 index 00000000..c7884ba1 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class LessThan extends Constraint +{ + /** + * @var float|int + */ + private $value; + + /** + * @param float|int $value + */ + public function __construct($value) + { + $this->value = $value; + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + return 'is less than ' . $this->exporter()->export($this->value); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return $this->value > $other; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php new file mode 100644 index 00000000..a5467942 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class SameSize extends Count +{ + public function __construct(iterable $expected) + { + parent::__construct((int) $this->getCountOf($expected)); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php new file mode 100644 index 00000000..5f772b4d --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php @@ -0,0 +1,270 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function sprintf; +use Countable; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\SelfDescribing; +use SebastianBergmann\Comparator\ComparisonFailure; +use SebastianBergmann\Exporter\Exporter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class Constraint implements Countable, SelfDescribing +{ + /** + * @var ?Exporter + */ + private $exporter; + + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public function evaluate($other, string $description = '', bool $returnResult = false): ?bool + { + $success = false; + + if ($this->matches($other)) { + $success = true; + } + + if ($returnResult) { + return $success; + } + + if (!$success) { + $this->fail($other, $description); + } + + return null; + } + + /** + * Counts the number of constraint elements. + */ + public function count(): int + { + return 1; + } + + protected function exporter(): Exporter + { + if ($this->exporter === null) { + $this->exporter = new Exporter; + } + + return $this->exporter; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * This method can be overridden to implement the evaluation algorithm. + * + * @param mixed $other value or object to evaluate + * + * @codeCoverageIgnore + */ + protected function matches($other): bool + { + return false; + } + + /** + * Throws an exception for the given compared value and test description. + * + * @param mixed $other evaluated value or object + * @param string $description Additional information about the test + * @param ComparisonFailure $comparisonFailure + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-return never-return + */ + protected function fail($other, $description, ComparisonFailure $comparisonFailure = null): void + { + $failureDescription = sprintf( + 'Failed asserting that %s.', + $this->failureDescription($other) + ); + + $additionalFailureDescription = $this->additionalFailureDescription($other); + + if ($additionalFailureDescription) { + $failureDescription .= "\n" . $additionalFailureDescription; + } + + if (!empty($description)) { + $failureDescription = $description . "\n" . $failureDescription; + } + + throw new ExpectationFailedException( + $failureDescription, + $comparisonFailure + ); + } + + /** + * Return additional failure description where needed. + * + * The function can be overridden to provide additional failure + * information like a diff + * + * @param mixed $other evaluated value or object + */ + protected function additionalFailureDescription($other): string + { + return ''; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * To provide additional failure information additionalFailureDescription + * can be used. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + return $this->exporter()->export($other) . ' ' . $this->toString(); + } + + /** + * Returns a custom string representation of the constraint object when it + * appears in context of an $operator expression. + * + * The purpose of this method is to provide meaningful descriptive string + * in context of operators such as LogicalNot. Native PHPUnit constraints + * are supported out of the box by LogicalNot, but externally developed + * ones had no way to provide correct strings in this context. + * + * The method shall return empty string, when it does not handle + * customization by itself. + * + * @param Operator $operator the $operator of the expression + * @param mixed $role role of $this constraint in the $operator expression + */ + protected function toStringInContext(Operator $operator, $role): string + { + return ''; + } + + /** + * Returns the description of the failure when this constraint appears in + * context of an $operator expression. + * + * The purpose of this method is to provide meaningful failure description + * in context of operators such as LogicalNot. Native PHPUnit constraints + * are supported out of the box by LogicalNot, but externally developed + * ones had no way to provide correct messages in this context. + * + * The method shall return empty string, when it does not handle + * customization by itself. + * + * @param Operator $operator the $operator of the expression + * @param mixed $role role of $this constraint in the $operator expression + * @param mixed $other evaluated value or object + */ + protected function failureDescriptionInContext(Operator $operator, $role, $other): string + { + $string = $this->toStringInContext($operator, $role); + + if ($string === '') { + return ''; + } + + return $this->exporter()->export($other) . ' ' . $string; + } + + /** + * Reduces the sub-expression starting at $this by skipping degenerate + * sub-expression and returns first descendant constraint that starts + * a non-reducible sub-expression. + * + * Returns $this for terminal constraints and for operators that start + * non-reducible sub-expression, or the nearest descendant of $this that + * starts a non-reducible sub-expression. + * + * A constraint expression may be modelled as a tree with non-terminal + * nodes (operators) and terminal nodes. For example: + * + * LogicalOr (operator, non-terminal) + * + LogicalAnd (operator, non-terminal) + * | + IsType('int') (terminal) + * | + GreaterThan(10) (terminal) + * + LogicalNot (operator, non-terminal) + * + IsType('array') (terminal) + * + * A degenerate sub-expression is a part of the tree, that effectively does + * not contribute to the evaluation of the expression it appears in. An example + * of degenerate sub-expression is a BinaryOperator constructed with single + * operand or nested BinaryOperators, each with single operand. An + * expression involving a degenerate sub-expression is equivalent to a + * reduced expression with the degenerate sub-expression removed, for example + * + * LogicalAnd (operator) + * + LogicalOr (degenerate operator) + * | + LogicalAnd (degenerate operator) + * | + IsType('int') (terminal) + * + GreaterThan(10) (terminal) + * + * is equivalent to + * + * LogicalAnd (operator) + * + IsType('int') (terminal) + * + GreaterThan(10) (terminal) + * + * because the subexpression + * + * + LogicalOr + * + LogicalAnd + * + - + * + * is degenerate. Calling reduce() on the LogicalOr object above, as well + * as on LogicalAnd, shall return the IsType('int') instance. + * + * Other specific reductions can be implemented, for example cascade of + * LogicalNot operators + * + * + LogicalNot + * + LogicalNot + * +LogicalNot + * + IsTrue + * + * can be reduced to + * + * LogicalNot + * + IsTrue + */ + protected function reduce(): self + { + return $this; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php new file mode 100644 index 00000000..6a61ebfb --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_string; +use function sprintf; +use function strpos; +use function trim; +use PHPUnit\Framework\ExpectationFailedException; +use SebastianBergmann\Comparator\ComparisonFailure; +use SebastianBergmann\Comparator\Factory as ComparatorFactory; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsEqual extends Constraint +{ + /** + * @var mixed + */ + private $value; + + /** + * @var float + */ + private $delta; + + /** + * @var bool + */ + private $canonicalize; + + /** + * @var bool + */ + private $ignoreCase; + + public function __construct($value, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false) + { + $this->value = $value; + $this->delta = $delta; + $this->canonicalize = $canonicalize; + $this->ignoreCase = $ignoreCase; + } + + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws ExpectationFailedException + * + * @return bool + */ + public function evaluate($other, string $description = '', bool $returnResult = false): ?bool + { + // If $this->value and $other are identical, they are also equal. + // This is the most common path and will allow us to skip + // initialization of all the comparators. + if ($this->value === $other) { + return true; + } + + $comparatorFactory = ComparatorFactory::getInstance(); + + try { + $comparator = $comparatorFactory->getComparatorFor( + $this->value, + $other + ); + + $comparator->assertEquals( + $this->value, + $other, + $this->delta, + $this->canonicalize, + $this->ignoreCase + ); + } catch (ComparisonFailure $f) { + if ($returnResult) { + return false; + } + + throw new ExpectationFailedException( + trim($description . "\n" . $f->getMessage()), + $f + ); + } + + return true; + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + $delta = ''; + + if (is_string($this->value)) { + if (strpos($this->value, "\n") !== false) { + return 'is equal to '; + } + + return sprintf( + "is equal to '%s'", + $this->value + ); + } + + if ($this->delta != 0) { + $delta = sprintf( + ' with delta <%F>', + $this->delta + ); + } + + return sprintf( + 'is equal to %s%s', + $this->exporter()->export($this->value), + $delta + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php new file mode 100644 index 00000000..57bb91ca --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_string; +use function sprintf; +use function strpos; +use function trim; +use PHPUnit\Framework\ExpectationFailedException; +use SebastianBergmann\Comparator\ComparisonFailure; +use SebastianBergmann\Comparator\Factory as ComparatorFactory; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsEqualCanonicalizing extends Constraint +{ + /** + * @var mixed + */ + private $value; + + public function __construct($value) + { + $this->value = $value; + } + + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws ExpectationFailedException + */ + public function evaluate($other, string $description = '', bool $returnResult = false): ?bool + { + // If $this->value and $other are identical, they are also equal. + // This is the most common path and will allow us to skip + // initialization of all the comparators. + if ($this->value === $other) { + return true; + } + + $comparatorFactory = ComparatorFactory::getInstance(); + + try { + $comparator = $comparatorFactory->getComparatorFor( + $this->value, + $other + ); + + $comparator->assertEquals( + $this->value, + $other, + 0.0, + true, + false + ); + } catch (ComparisonFailure $f) { + if ($returnResult) { + return false; + } + + throw new ExpectationFailedException( + trim($description . "\n" . $f->getMessage()), + $f + ); + } + + return true; + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + if (is_string($this->value)) { + if (strpos($this->value, "\n") !== false) { + return 'is equal to '; + } + + return sprintf( + "is equal to '%s'", + $this->value + ); + } + + return sprintf( + 'is equal to %s', + $this->exporter()->export($this->value) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php new file mode 100644 index 00000000..d657e96a --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_string; +use function sprintf; +use function strpos; +use function trim; +use PHPUnit\Framework\ExpectationFailedException; +use SebastianBergmann\Comparator\ComparisonFailure; +use SebastianBergmann\Comparator\Factory as ComparatorFactory; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsEqualIgnoringCase extends Constraint +{ + /** + * @var mixed + */ + private $value; + + public function __construct($value) + { + $this->value = $value; + } + + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws ExpectationFailedException + */ + public function evaluate($other, string $description = '', bool $returnResult = false): ?bool + { + // If $this->value and $other are identical, they are also equal. + // This is the most common path and will allow us to skip + // initialization of all the comparators. + if ($this->value === $other) { + return true; + } + + $comparatorFactory = ComparatorFactory::getInstance(); + + try { + $comparator = $comparatorFactory->getComparatorFor( + $this->value, + $other + ); + + $comparator->assertEquals( + $this->value, + $other, + 0.0, + false, + true + ); + } catch (ComparisonFailure $f) { + if ($returnResult) { + return false; + } + + throw new ExpectationFailedException( + trim($description . "\n" . $f->getMessage()), + $f + ); + } + + return true; + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + if (is_string($this->value)) { + if (strpos($this->value, "\n") !== false) { + return 'is equal to '; + } + + return sprintf( + "is equal to '%s'", + $this->value + ); + } + + return sprintf( + 'is equal to %s', + $this->exporter()->export($this->value) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php new file mode 100644 index 00000000..0370b511 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function sprintf; +use function trim; +use PHPUnit\Framework\ExpectationFailedException; +use SebastianBergmann\Comparator\ComparisonFailure; +use SebastianBergmann\Comparator\Factory as ComparatorFactory; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsEqualWithDelta extends Constraint +{ + /** + * @var mixed + */ + private $value; + + /** + * @var float + */ + private $delta; + + public function __construct($value, float $delta) + { + $this->value = $value; + $this->delta = $delta; + } + + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws ExpectationFailedException + */ + public function evaluate($other, string $description = '', bool $returnResult = false): ?bool + { + // If $this->value and $other are identical, they are also equal. + // This is the most common path and will allow us to skip + // initialization of all the comparators. + if ($this->value === $other) { + return true; + } + + $comparatorFactory = ComparatorFactory::getInstance(); + + try { + $comparator = $comparatorFactory->getComparatorFor( + $this->value, + $other + ); + + $comparator->assertEquals( + $this->value, + $other, + $this->delta + ); + } catch (ComparisonFailure $f) { + if ($returnResult) { + return false; + } + + throw new ExpectationFailedException( + trim($description . "\n" . $f->getMessage()), + $f + ); + } + + return true; + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + return sprintf( + 'is equal to %s with delta <%F>>', + $this->exporter()->export($this->value), + $this->delta + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php new file mode 100644 index 00000000..860c0030 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function get_class; +use function sprintf; +use PHPUnit\Util\Filter; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Exception extends Constraint +{ + /** + * @var string + */ + private $className; + + public function __construct(string $className) + { + $this->className = $className; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return sprintf( + 'exception of type "%s"', + $this->className + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return $other instanceof $this->className; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + if ($other !== null) { + $message = ''; + + if ($other instanceof Throwable) { + $message = '. Message was: "' . $other->getMessage() . '" at' + . "\n" . Filter::getFilteredStacktrace($other); + } + + return sprintf( + 'exception of type "%s" matches expected exception "%s"%s', + get_class($other), + $this->className, + $message + ); + } + + return sprintf( + 'exception of type "%s" is thrown', + $this->className + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php new file mode 100644 index 00000000..b8054a94 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function sprintf; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ExceptionCode extends Constraint +{ + /** + * @var int|string + */ + private $expectedCode; + + /** + * @param int|string $expected + */ + public function __construct($expected) + { + $this->expectedCode = $expected; + } + + public function toString(): string + { + return 'exception code is '; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param Throwable $other + */ + protected function matches($other): bool + { + return (string) $other->getCode() === (string) $this->expectedCode; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + return sprintf( + '%s is equal to expected exception code %s', + $this->exporter()->export($other->getCode()), + $this->exporter()->export($this->expectedCode) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessage.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessage.php new file mode 100644 index 00000000..030beff9 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessage.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function sprintf; +use function strpos; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ExceptionMessage extends Constraint +{ + /** + * @var string + */ + private $expectedMessage; + + public function __construct(string $expected) + { + $this->expectedMessage = $expected; + } + + public function toString(): string + { + if ($this->expectedMessage === '') { + return 'exception message is empty'; + } + + return 'exception message contains '; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param Throwable $other + */ + protected function matches($other): bool + { + if ($this->expectedMessage === '') { + return $other->getMessage() === ''; + } + + return strpos((string) $other->getMessage(), $this->expectedMessage) !== false; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + if ($this->expectedMessage === '') { + return sprintf( + "exception message is empty but is '%s'", + $other->getMessage() + ); + } + + return sprintf( + "exception message '%s' contains '%s'", + $other->getMessage(), + $this->expectedMessage + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageRegularExpression.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageRegularExpression.php new file mode 100644 index 00000000..fd0db1c8 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageRegularExpression.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function sprintf; +use Exception; +use PHPUnit\Util\RegularExpression as RegularExpressionUtil; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ExceptionMessageRegularExpression extends Constraint +{ + /** + * @var string + */ + private $expectedMessageRegExp; + + public function __construct(string $expected) + { + $this->expectedMessageRegExp = $expected; + } + + public function toString(): string + { + return 'exception message matches '; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param \PHPUnit\Framework\Exception $other + * + * @throws \PHPUnit\Framework\Exception + * @throws Exception + */ + protected function matches($other): bool + { + $match = RegularExpressionUtil::safeMatch($this->expectedMessageRegExp, $other->getMessage()); + + if ($match === false) { + throw new \PHPUnit\Framework\Exception( + "Invalid expected exception message regex given: '{$this->expectedMessageRegExp}'" + ); + } + + return $match === 1; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + return sprintf( + "exception message '%s' matches '%s'", + $other->getMessage(), + $this->expectedMessageRegExp + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php new file mode 100644 index 00000000..ef4b2baf --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_dir; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class DirectoryExists extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'directory exists'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return is_dir($other); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + return sprintf( + 'directory "%s" exists', + $other + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php new file mode 100644 index 00000000..41b3136e --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function file_exists; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class FileExists extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'file exists'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return file_exists($other); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + return sprintf( + 'file "%s" exists', + $other + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php new file mode 100644 index 00000000..e33d7e04 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_readable; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsReadable extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is readable'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return is_readable($other); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + return sprintf( + '"%s" is readable', + $other + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php new file mode 100644 index 00000000..93981224 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_writable; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsWritable extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is writable'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return is_writable($other); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + return sprintf( + '"%s" is writable', + $other + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/IsAnything.php b/vendor/phpunit/phpunit/src/Framework/Constraint/IsAnything.php new file mode 100644 index 00000000..db84a743 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/IsAnything.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use PHPUnit\Framework\ExpectationFailedException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsAnything extends Constraint +{ + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws ExpectationFailedException + */ + public function evaluate($other, string $description = '', bool $returnResult = false): ?bool + { + return $returnResult ? true : null; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is anything'; + } + + /** + * Counts the number of constraint elements. + */ + public function count(): int + { + return 0; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php b/vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php new file mode 100644 index 00000000..fde43d9e --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function get_class; +use function is_array; +use function is_object; +use function is_string; +use function sprintf; +use PHPUnit\Framework\ExpectationFailedException; +use SebastianBergmann\Comparator\ComparisonFailure; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsIdentical extends Constraint +{ + /** + * @var mixed + */ + private $value; + + public function __construct($value) + { + $this->value = $value; + } + + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public function evaluate($other, string $description = '', bool $returnResult = false): ?bool + { + $success = $this->value === $other; + + if ($returnResult) { + return $success; + } + + if (!$success) { + $f = null; + + // if both values are strings, make sure a diff is generated + if (is_string($this->value) && is_string($other)) { + $f = new ComparisonFailure( + $this->value, + $other, + sprintf("'%s'", $this->value), + sprintf("'%s'", $other) + ); + } + + // if both values are array, make sure a diff is generated + if (is_array($this->value) && is_array($other)) { + $f = new ComparisonFailure( + $this->value, + $other, + $this->exporter()->export($this->value), + $this->exporter()->export($other) + ); + } + + $this->fail($other, $description, $f); + } + + return null; + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + if (is_object($this->value)) { + return 'is identical to an object of class "' . + get_class($this->value) . '"'; + } + + return 'is identical to ' . $this->exporter()->export($this->value); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + if (is_object($this->value) && is_object($other)) { + return 'two variables reference the same object'; + } + + if (is_string($this->value) && is_string($other)) { + return 'two strings are identical'; + } + + if (is_array($this->value) && is_array($other)) { + return 'two arrays are identical'; + } + + return parent::failureDescription($other); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php b/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php new file mode 100644 index 00000000..23a4de7e --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function json_decode; +use function sprintf; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Util\Json; +use SebastianBergmann\Comparator\ComparisonFailure; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class JsonMatches extends Constraint +{ + /** + * @var string + */ + private $value; + + public function __construct(string $value) + { + $this->value = $value; + } + + /** + * Returns a string representation of the object. + */ + public function toString(): string + { + return sprintf( + 'matches JSON string "%s"', + $this->value + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * This method can be overridden to implement the evaluation algorithm. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + [$error, $recodedOther] = Json::canonicalize($other); + + if ($error) { + return false; + } + + [$error, $recodedValue] = Json::canonicalize($this->value); + + if ($error) { + return false; + } + + return $recodedOther == $recodedValue; + } + + /** + * Throws an exception for the given compared value and test description. + * + * @param mixed $other evaluated value or object + * @param string $description Additional information about the test + * @param ComparisonFailure $comparisonFailure + * + * @throws \PHPUnit\Framework\Exception + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * + * @psalm-return never-return + */ + protected function fail($other, $description, ComparisonFailure $comparisonFailure = null): void + { + if ($comparisonFailure === null) { + [$error, $recodedOther] = Json::canonicalize($other); + + if ($error) { + parent::fail($other, $description); + } + + [$error, $recodedValue] = Json::canonicalize($this->value); + + if ($error) { + parent::fail($other, $description); + } + + $comparisonFailure = new ComparisonFailure( + json_decode($this->value), + json_decode($other), + Json::prettify($recodedValue), + Json::prettify($recodedOther), + false, + 'Failed asserting that two json values are equal.' + ); + } + + parent::fail($other, $description, $comparisonFailure); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php b/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php new file mode 100644 index 00000000..4bf19e27 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use const JSON_ERROR_CTRL_CHAR; +use const JSON_ERROR_DEPTH; +use const JSON_ERROR_NONE; +use const JSON_ERROR_STATE_MISMATCH; +use const JSON_ERROR_SYNTAX; +use const JSON_ERROR_UTF8; +use function strtolower; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class JsonMatchesErrorMessageProvider +{ + /** + * Translates JSON error to a human readable string. + */ + public static function determineJsonError(string $error, string $prefix = ''): ?string + { + switch ($error) { + case JSON_ERROR_NONE: + return null; + + case JSON_ERROR_DEPTH: + return $prefix . 'Maximum stack depth exceeded'; + + case JSON_ERROR_STATE_MISMATCH: + return $prefix . 'Underflow or the modes mismatch'; + + case JSON_ERROR_CTRL_CHAR: + return $prefix . 'Unexpected control character found'; + + case JSON_ERROR_SYNTAX: + return $prefix . 'Syntax error, malformed JSON'; + + case JSON_ERROR_UTF8: + return $prefix . 'Malformed UTF-8 characters, possibly incorrectly encoded'; + + default: + return $prefix . 'Unknown error'; + } + } + + /** + * Translates a given type to a human readable message prefix. + */ + public static function translateTypeToPrefix(string $type): string + { + switch (strtolower($type)) { + case 'expected': + $prefix = 'Expected value JSON decode error - '; + + break; + + case 'actual': + $prefix = 'Actual value JSON decode error - '; + + break; + + default: + $prefix = ''; + + break; + } + + return $prefix; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php new file mode 100644 index 00000000..9a2f3286 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_finite; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsFinite extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is finite'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return is_finite($other); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php new file mode 100644 index 00000000..c718514c --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_infinite; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsInfinite extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is infinite'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return is_infinite($other); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php new file mode 100644 index 00000000..0062c5b5 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_nan; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsNan extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is nan'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return is_nan($other); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasAttribute.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasAttribute.php new file mode 100644 index 00000000..a873ceae --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasAttribute.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function get_class; +use function is_object; +use function sprintf; +use PHPUnit\Framework\Exception; +use ReflectionClass; +use ReflectionException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4601 + */ +class ClassHasAttribute extends Constraint +{ + /** + * @var string + */ + private $attributeName; + + public function __construct(string $attributeName) + { + $this->attributeName = $attributeName; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return sprintf( + 'has attribute "%s"', + $this->attributeName + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + try { + return (new ReflectionClass($other))->hasProperty($this->attributeName); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + return sprintf( + '%sclass "%s" %s', + is_object($other) ? 'object of ' : '', + is_object($other) ? get_class($other) : $other, + $this->toString() + ); + } + + protected function attributeName(): string + { + return $this->attributeName; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasStaticAttribute.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasStaticAttribute.php new file mode 100644 index 00000000..538cbf08 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ClassHasStaticAttribute.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function sprintf; +use PHPUnit\Framework\Exception; +use ReflectionClass; +use ReflectionException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4601 + */ +final class ClassHasStaticAttribute extends ClassHasAttribute +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return sprintf( + 'has static attribute "%s"', + $this->attributeName() + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + try { + $class = new ReflectionClass($other); + + if ($class->hasProperty($this->attributeName())) { + return $class->getProperty($this->attributeName())->isStatic(); + } + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + return false; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php new file mode 100644 index 00000000..30f3a330 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php @@ -0,0 +1,151 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function get_class; +use function is_object; +use PHPUnit\Framework\ActualValueIsNotAnObjectException; +use PHPUnit\Framework\ComparisonMethodDoesNotAcceptParameterTypeException; +use PHPUnit\Framework\ComparisonMethodDoesNotDeclareBoolReturnTypeException; +use PHPUnit\Framework\ComparisonMethodDoesNotDeclareExactlyOneParameterException; +use PHPUnit\Framework\ComparisonMethodDoesNotDeclareParameterTypeException; +use PHPUnit\Framework\ComparisonMethodDoesNotExistException; +use ReflectionNamedType; +use ReflectionObject; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ObjectEquals extends Constraint +{ + /** + * @var object + */ + private $expected; + + /** + * @var string + */ + private $method; + + public function __construct(object $object, string $method = 'equals') + { + $this->expected = $object; + $this->method = $method; + } + + public function toString(): string + { + return 'two objects are equal'; + } + + /** + * @throws ActualValueIsNotAnObjectException + * @throws ComparisonMethodDoesNotAcceptParameterTypeException + * @throws ComparisonMethodDoesNotDeclareBoolReturnTypeException + * @throws ComparisonMethodDoesNotDeclareExactlyOneParameterException + * @throws ComparisonMethodDoesNotDeclareParameterTypeException + * @throws ComparisonMethodDoesNotExistException + */ + protected function matches($other): bool + { + if (!is_object($other)) { + throw new ActualValueIsNotAnObjectException; + } + + $object = new ReflectionObject($other); + + if (!$object->hasMethod($this->method)) { + throw new ComparisonMethodDoesNotExistException( + get_class($other), + $this->method + ); + } + + /** @noinspection PhpUnhandledExceptionInspection */ + $method = $object->getMethod($this->method); + + if (!$method->hasReturnType()) { + throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException( + get_class($other), + $this->method + ); + } + + $returnType = $method->getReturnType(); + + if (!$returnType instanceof ReflectionNamedType) { + throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException( + get_class($other), + $this->method + ); + } + + if ($returnType->allowsNull()) { + throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException( + get_class($other), + $this->method + ); + } + + if ($returnType->getName() !== 'bool') { + throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException( + get_class($other), + $this->method + ); + } + + if ($method->getNumberOfParameters() !== 1 || $method->getNumberOfRequiredParameters() !== 1) { + throw new ComparisonMethodDoesNotDeclareExactlyOneParameterException( + get_class($other), + $this->method + ); + } + + $parameter = $method->getParameters()[0]; + + if (!$parameter->hasType()) { + throw new ComparisonMethodDoesNotDeclareParameterTypeException( + get_class($other), + $this->method + ); + } + + $type = $parameter->getType(); + + if (!$type instanceof ReflectionNamedType) { + throw new ComparisonMethodDoesNotDeclareParameterTypeException( + get_class($other), + $this->method + ); + } + + $typeName = $type->getName(); + + if ($typeName === 'self') { + $typeName = get_class($other); + } + + if (!$this->expected instanceof $typeName) { + throw new ComparisonMethodDoesNotAcceptParameterTypeException( + get_class($other), + $this->method, + get_class($this->expected) + ); + } + + return $other->{$this->method}($this->expected); + } + + protected function failureDescription($other): string + { + return $this->toString(); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasAttribute.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasAttribute.php new file mode 100644 index 00000000..602cb05d --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasAttribute.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use ReflectionObject; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4601 + */ +final class ObjectHasAttribute extends ClassHasAttribute +{ + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return (new ReflectionObject($other))->hasProperty($this->attributeName()); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php new file mode 100644 index 00000000..11c86b52 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php @@ -0,0 +1,148 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function array_map; +use function array_values; +use function count; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class BinaryOperator extends Operator +{ + /** + * @var Constraint[] + */ + private $constraints = []; + + public static function fromConstraints(Constraint ...$constraints): self + { + $constraint = new static; + + $constraint->constraints = $constraints; + + return $constraint; + } + + /** + * @param mixed[] $constraints + */ + public function setConstraints(array $constraints): void + { + $this->constraints = array_map(function ($constraint): Constraint + { + return $this->checkConstraint($constraint); + }, array_values($constraints)); + } + + /** + * Returns the number of operands (constraints). + */ + final public function arity(): int + { + return count($this->constraints); + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + $reduced = $this->reduce(); + + if ($reduced !== $this) { + return $reduced->toString(); + } + + $text = ''; + + foreach ($this->constraints as $key => $constraint) { + $constraint = $constraint->reduce(); + + $text .= $this->constraintToString($constraint, $key); + } + + return $text; + } + + /** + * Counts the number of constraint elements. + */ + public function count(): int + { + $count = 0; + + foreach ($this->constraints as $constraint) { + $count += count($constraint); + } + + return $count; + } + + /** + * Returns the nested constraints. + */ + final protected function constraints(): array + { + return $this->constraints; + } + + /** + * Returns true if the $constraint needs to be wrapped with braces. + */ + final protected function constraintNeedsParentheses(Constraint $constraint): bool + { + return $this->arity() > 1 && parent::constraintNeedsParentheses($constraint); + } + + /** + * Reduces the sub-expression starting at $this by skipping degenerate + * sub-expression and returns first descendant constraint that starts + * a non-reducible sub-expression. + * + * See Constraint::reduce() for more. + */ + protected function reduce(): Constraint + { + if ($this->arity() === 1 && $this->constraints[0] instanceof Operator) { + return $this->constraints[0]->reduce(); + } + + return parent::reduce(); + } + + /** + * Returns string representation of given operand in context of this operator. + * + * @param Constraint $constraint operand constraint + * @param int $position position of $constraint in this expression + */ + private function constraintToString(Constraint $constraint, int $position): string + { + $prefix = ''; + + if ($position > 0) { + $prefix = (' ' . $this->operator() . ' '); + } + + if ($this->constraintNeedsParentheses($constraint)) { + return $prefix . '( ' . $constraint->toString() . ' )'; + } + + $string = $constraint->toStringInContext($this, $position); + + if ($string === '') { + $string = $constraint->toString(); + } + + return $prefix . $string; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php new file mode 100644 index 00000000..a1af4dd3 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class LogicalAnd extends BinaryOperator +{ + /** + * Returns the name of this operator. + */ + public function operator(): string + { + return 'and'; + } + + /** + * Returns this operator's precedence. + * + * @see https://www.php.net/manual/en/language.operators.precedence.php + */ + public function precedence(): int + { + return 22; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + foreach ($this->constraints() as $constraint) { + if (!$constraint->evaluate($other, '', true)) { + return false; + } + } + + return [] !== $this->constraints(); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php new file mode 100644 index 00000000..7560ce2a --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function array_map; +use function count; +use function preg_match; +use function preg_quote; +use function preg_replace; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class LogicalNot extends UnaryOperator +{ + public static function negate(string $string): string + { + $positives = [ + 'contains ', + 'exists', + 'has ', + 'is ', + 'are ', + 'matches ', + 'starts with ', + 'ends with ', + 'reference ', + 'not not ', + ]; + + $negatives = [ + 'does not contain ', + 'does not exist', + 'does not have ', + 'is not ', + 'are not ', + 'does not match ', + 'starts not with ', + 'ends not with ', + 'don\'t reference ', + 'not ', + ]; + + preg_match('/(\'[\w\W]*\')([\w\W]*)("[\w\W]*")/i', $string, $matches); + + $positives = array_map(static function (string $s) + { + return '/\\b' . preg_quote($s, '/') . '/'; + }, $positives); + + if (count($matches) > 0) { + $nonInput = $matches[2]; + + $negatedString = preg_replace( + '/' . preg_quote($nonInput, '/') . '/', + preg_replace( + $positives, + $negatives, + $nonInput + ), + $string + ); + } else { + $negatedString = preg_replace( + $positives, + $negatives, + $string + ); + } + + return $negatedString; + } + + /** + * Returns the name of this operator. + */ + public function operator(): string + { + return 'not'; + } + + /** + * Returns this operator's precedence. + * + * @see https://www.php.net/manual/en/language.operators.precedence.php + */ + public function precedence(): int + { + return 5; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return !$this->constraint()->evaluate($other, '', true); + } + + /** + * Applies additional transformation to strings returned by toString() or + * failureDescription(). + */ + protected function transformString(string $string): string + { + return self::negate($string); + } + + /** + * Reduces the sub-expression starting at $this by skipping degenerate + * sub-expression and returns first descendant constraint that starts + * a non-reducible sub-expression. + * + * See Constraint::reduce() for more. + */ + protected function reduce(): Constraint + { + $constraint = $this->constraint(); + + if ($constraint instanceof self) { + return $constraint->constraint()->reduce(); + } + + return parent::reduce(); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php new file mode 100644 index 00000000..2932de67 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class LogicalOr extends BinaryOperator +{ + /** + * Returns the name of this operator. + */ + public function operator(): string + { + return 'or'; + } + + /** + * Returns this operator's precedence. + * + * @see https://www.php.net/manual/en/language.operators.precedence.php + */ + public function precedence(): int + { + return 24; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + public function matches($other): bool + { + foreach ($this->constraints() as $constraint) { + if ($constraint->evaluate($other, '', true)) { + return true; + } + } + + return false; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php new file mode 100644 index 00000000..fbdb479b --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function array_reduce; +use function array_shift; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class LogicalXor extends BinaryOperator +{ + /** + * Returns the name of this operator. + */ + public function operator(): string + { + return 'xor'; + } + + /** + * Returns this operator's precedence. + * + * @see https://www.php.net/manual/en/language.operators.precedence.php. + */ + public function precedence(): int + { + return 23; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + public function matches($other): bool + { + $constraints = $this->constraints(); + + $initial = array_shift($constraints); + + if ($initial === null) { + return false; + } + + return array_reduce( + $constraints, + static function (bool $matches, Constraint $constraint) use ($other): bool + { + return $matches xor $constraint->evaluate($other, '', true); + }, + $initial->evaluate($other, '', true) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php new file mode 100644 index 00000000..3f51a0f4 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class Operator extends Constraint +{ + /** + * Returns the name of this operator. + */ + abstract public function operator(): string; + + /** + * Returns this operator's precedence. + * + * @see https://www.php.net/manual/en/language.operators.precedence.php + */ + abstract public function precedence(): int; + + /** + * Returns the number of operands. + */ + abstract public function arity(): int; + + /** + * Validates $constraint argument. + */ + protected function checkConstraint($constraint): Constraint + { + if (!$constraint instanceof Constraint) { + return new IsEqual($constraint); + } + + return $constraint; + } + + /** + * Returns true if the $constraint needs to be wrapped with braces. + */ + protected function constraintNeedsParentheses(Constraint $constraint): bool + { + return $constraint instanceof self && + $constraint->arity() > 1 && + $this->precedence() <= $constraint->precedence(); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php new file mode 100644 index 00000000..0a7a5fa2 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function count; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class UnaryOperator extends Operator +{ + /** + * @var Constraint + */ + private $constraint; + + /** + * @param Constraint|mixed $constraint + */ + public function __construct($constraint) + { + $this->constraint = $this->checkConstraint($constraint); + } + + /** + * Returns the number of operands (constraints). + */ + public function arity(): int + { + return 1; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + $reduced = $this->reduce(); + + if ($reduced !== $this) { + return $reduced->toString(); + } + + $constraint = $this->constraint->reduce(); + + if ($this->constraintNeedsParentheses($constraint)) { + return $this->operator() . '( ' . $constraint->toString() . ' )'; + } + + $string = $constraint->toStringInContext($this, 0); + + if ($string === '') { + return $this->transformString($constraint->toString()); + } + + return $string; + } + + /** + * Counts the number of constraint elements. + */ + public function count(): int + { + return count($this->constraint); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + $reduced = $this->reduce(); + + if ($reduced !== $this) { + return $reduced->failureDescription($other); + } + + $constraint = $this->constraint->reduce(); + + if ($this->constraintNeedsParentheses($constraint)) { + return $this->operator() . '( ' . $constraint->failureDescription($other) . ' )'; + } + + $string = $constraint->failureDescriptionInContext($this, 0, $other); + + if ($string === '') { + return $this->transformString($constraint->failureDescription($other)); + } + + return $string; + } + + /** + * Transforms string returned by the memeber constraint's toString() or + * failureDescription() such that it reflects constraint's participation in + * this expression. + * + * The method may be overwritten in a subclass to apply default + * transformation in case the operand constraint does not provide its own + * custom strings via toStringInContext() or failureDescriptionInContext(). + * + * @param string $string the string to be transformed + */ + protected function transformString(string $string): string + { + return $string; + } + + /** + * Provides access to $this->constraint for subclasses. + */ + final protected function constraint(): Constraint + { + return $this->constraint; + } + + /** + * Returns true if the $constraint needs to be wrapped with parentheses. + */ + protected function constraintNeedsParentheses(Constraint $constraint): bool + { + $constraint = $constraint->reduce(); + + return $constraint instanceof self || parent::constraintNeedsParentheses($constraint); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php b/vendor/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php new file mode 100644 index 00000000..97b29461 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function json_decode; +use function json_last_error; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsJson extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is valid JSON'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + if ($other === '') { + return false; + } + + json_decode($other); + + if (json_last_error()) { + return false; + } + + return true; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + if ($other === '') { + return 'an empty string is valid JSON'; + } + + json_decode($other); + $error = (string) JsonMatchesErrorMessageProvider::determineJsonError( + (string) json_last_error() + ); + + return sprintf( + '%s is valid JSON (%s)', + $this->exporter()->shortenedExport($other), + $error + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php b/vendor/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php new file mode 100644 index 00000000..8e609e79 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function preg_match; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +class RegularExpression extends Constraint +{ + /** + * @var string + */ + private $pattern; + + public function __construct(string $pattern) + { + $this->pattern = $pattern; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return sprintf( + 'matches PCRE pattern "%s"', + $this->pattern + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return preg_match($this->pattern, $other) > 0; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php new file mode 100644 index 00000000..6279f37b --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function mb_stripos; +use function mb_strtolower; +use function sprintf; +use function strpos; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class StringContains extends Constraint +{ + /** + * @var string + */ + private $string; + + /** + * @var bool + */ + private $ignoreCase; + + public function __construct(string $string, bool $ignoreCase = false) + { + $this->string = $string; + $this->ignoreCase = $ignoreCase; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + if ($this->ignoreCase) { + $string = mb_strtolower($this->string, 'UTF-8'); + } else { + $string = $this->string; + } + + return sprintf( + 'contains "%s"', + $string + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + if ('' === $this->string) { + return true; + } + + if ($this->ignoreCase) { + /* + * We must use the multi byte safe version so we can accurately compare non latin upper characters with + * their lowercase equivalents. + */ + return mb_stripos($other, $this->string, 0, 'UTF-8') !== false; + } + + /* + * Use the non multi byte safe functions to see if the string is contained in $other. + * + * This function is very fast and we don't care about the character position in the string. + * + * Additionally, we want this method to be binary safe so we can check if some binary data is in other binary + * data. + */ + return strpos($other, $this->string) !== false; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php new file mode 100644 index 00000000..bb4ce23b --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function strlen; +use function substr; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class StringEndsWith extends Constraint +{ + /** + * @var string + */ + private $suffix; + + public function __construct(string $suffix) + { + $this->suffix = $suffix; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'ends with "' . $this->suffix . '"'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return substr($other, 0 - strlen($this->suffix)) === $this->suffix; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php new file mode 100644 index 00000000..c4f7324e --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use const DIRECTORY_SEPARATOR; +use function explode; +use function implode; +use function preg_match; +use function preg_quote; +use function preg_replace; +use function strtr; +use SebastianBergmann\Diff\Differ; +use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class StringMatchesFormatDescription extends RegularExpression +{ + /** + * @var string + */ + private $string; + + public function __construct(string $string) + { + parent::__construct( + $this->createPatternFromFormat( + $this->convertNewlines($string) + ) + ); + + $this->string = $string; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return parent::matches( + $this->convertNewlines($other) + ); + } + + protected function failureDescription($other): string + { + return 'string matches format description'; + } + + protected function additionalFailureDescription($other): string + { + $from = explode("\n", $this->string); + $to = explode("\n", $this->convertNewlines($other)); + + foreach ($from as $index => $line) { + if (isset($to[$index]) && $line !== $to[$index]) { + $line = $this->createPatternFromFormat($line); + + if (preg_match($line, $to[$index]) > 0) { + $from[$index] = $to[$index]; + } + } + } + + $this->string = implode("\n", $from); + $other = implode("\n", $to); + + return (new Differ(new UnifiedDiffOutputBuilder("--- Expected\n+++ Actual\n")))->diff($this->string, $other); + } + + private function createPatternFromFormat(string $string): string + { + $string = strtr( + preg_quote($string, '/'), + [ + '%%' => '%', + '%e' => '\\' . DIRECTORY_SEPARATOR, + '%s' => '[^\r\n]+', + '%S' => '[^\r\n]*', + '%a' => '.+', + '%A' => '.*', + '%w' => '\s*', + '%i' => '[+-]?\d+', + '%d' => '\d+', + '%x' => '[0-9a-fA-F]+', + '%f' => '[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?', + '%c' => '.', + ] + ); + + return '/^' . $string . '$/s'; + } + + private function convertNewlines(string $text): string + { + return preg_replace('/\r\n/', "\n", $text); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php new file mode 100644 index 00000000..089545c1 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function strlen; +use function strpos; +use PHPUnit\Framework\InvalidArgumentException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class StringStartsWith extends Constraint +{ + /** + * @var string + */ + private $prefix; + + public function __construct(string $prefix) + { + if (strlen($prefix) === 0) { + throw InvalidArgumentException::create(1, 'non-empty string'); + } + + $this->prefix = $prefix; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'starts with "' . $this->prefix . '"'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return strpos((string) $other, $this->prefix) === 0; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php new file mode 100644 index 00000000..44cada3a --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function array_key_exists; +use function is_array; +use ArrayAccess; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ArrayHasKey extends Constraint +{ + /** + * @var int|string + */ + private $key; + + /** + * @param int|string $key + */ + public function __construct($key) + { + $this->key = $key; + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + return 'has the key ' . $this->exporter()->export($this->key); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + if (is_array($other)) { + return array_key_exists($this->key, $other); + } + + if ($other instanceof ArrayAccess) { + return $other->offsetExists($this->key); + } + + return false; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + return 'an array ' . $this->toString(); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php new file mode 100644 index 00000000..39660a98 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_array; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class TraversableContains extends Constraint +{ + /** + * @var mixed + */ + private $value; + + public function __construct($value) + { + $this->value = $value; + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + return 'contains ' . $this->exporter()->export($this->value); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + return sprintf( + '%s %s', + is_array($other) ? 'an array' : 'a traversable', + $this->toString() + ); + } + + protected function value() + { + return $this->value; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php new file mode 100644 index 00000000..c315e709 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use SplObjectStorage; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TraversableContainsEqual extends TraversableContains +{ + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + if ($other instanceof SplObjectStorage) { + return $other->contains($this->value()); + } + + foreach ($other as $element) { + /* @noinspection TypeUnsafeComparisonInspection */ + if ($this->value() == $element) { + return true; + } + } + + return false; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php new file mode 100644 index 00000000..a3437dbc --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use SplObjectStorage; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TraversableContainsIdentical extends TraversableContains +{ + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + if ($other instanceof SplObjectStorage) { + return $other->contains($this->value()); + } + + foreach ($other as $element) { + if ($this->value() === $element) { + return true; + } + } + + return false; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php new file mode 100644 index 00000000..cf4a46b4 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use PHPUnit\Framework\ExpectationFailedException; +use Traversable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TraversableContainsOnly extends Constraint +{ + /** + * @var Constraint + */ + private $constraint; + + /** + * @var string + */ + private $type; + + /** + * @throws \PHPUnit\Framework\Exception + */ + public function __construct(string $type, bool $isNativeType = true) + { + if ($isNativeType) { + $this->constraint = new IsType($type); + } else { + $this->constraint = new IsInstanceOf( + $type + ); + } + + $this->type = $type; + } + + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param mixed|Traversable $other + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public function evaluate($other, string $description = '', bool $returnResult = false): ?bool + { + $success = true; + + foreach ($other as $item) { + if (!$this->constraint->evaluate($item, '', true)) { + $success = false; + + break; + } + } + + if ($returnResult) { + return $success; + } + + if (!$success) { + $this->fail($other, $description); + } + + return null; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'contains only values of type "' . $this->type . '"'; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php new file mode 100644 index 00000000..f0fa02b9 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function sprintf; +use ReflectionClass; +use ReflectionException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsInstanceOf extends Constraint +{ + /** + * @var string + */ + private $className; + + public function __construct(string $className) + { + $this->className = $className; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return sprintf( + 'is instance of %s "%s"', + $this->getType(), + $this->className + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return $other instanceof $this->className; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + return sprintf( + '%s is an instance of %s "%s"', + $this->exporter()->shortenedExport($other), + $this->getType(), + $this->className + ); + } + + private function getType(): string + { + try { + $reflection = new ReflectionClass($this->className); + + if ($reflection->isInterface()) { + return 'interface'; + } + } catch (ReflectionException $e) { + } + + return 'class'; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php new file mode 100644 index 00000000..b9fcdd7a --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsNull extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is null'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return $other === null; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php b/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php new file mode 100644 index 00000000..5bc691d7 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php @@ -0,0 +1,210 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function gettype; +use function is_array; +use function is_bool; +use function is_callable; +use function is_float; +use function is_int; +use function is_iterable; +use function is_numeric; +use function is_object; +use function is_scalar; +use function is_string; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsType extends Constraint +{ + /** + * @var string + */ + public const TYPE_ARRAY = 'array'; + + /** + * @var string + */ + public const TYPE_BOOL = 'bool'; + + /** + * @var string + */ + public const TYPE_FLOAT = 'float'; + + /** + * @var string + */ + public const TYPE_INT = 'int'; + + /** + * @var string + */ + public const TYPE_NULL = 'null'; + + /** + * @var string + */ + public const TYPE_NUMERIC = 'numeric'; + + /** + * @var string + */ + public const TYPE_OBJECT = 'object'; + + /** + * @var string + */ + public const TYPE_RESOURCE = 'resource'; + + /** + * @var string + */ + public const TYPE_CLOSED_RESOURCE = 'resource (closed)'; + + /** + * @var string + */ + public const TYPE_STRING = 'string'; + + /** + * @var string + */ + public const TYPE_SCALAR = 'scalar'; + + /** + * @var string + */ + public const TYPE_CALLABLE = 'callable'; + + /** + * @var string + */ + public const TYPE_ITERABLE = 'iterable'; + + /** + * @var array + */ + private const KNOWN_TYPES = [ + 'array' => true, + 'boolean' => true, + 'bool' => true, + 'double' => true, + 'float' => true, + 'integer' => true, + 'int' => true, + 'null' => true, + 'numeric' => true, + 'object' => true, + 'real' => true, + 'resource' => true, + 'resource (closed)' => true, + 'string' => true, + 'scalar' => true, + 'callable' => true, + 'iterable' => true, + ]; + + /** + * @var string + */ + private $type; + + /** + * @throws \PHPUnit\Framework\Exception + */ + public function __construct(string $type) + { + if (!isset(self::KNOWN_TYPES[$type])) { + throw new \PHPUnit\Framework\Exception( + sprintf( + 'Type specified for PHPUnit\Framework\Constraint\IsType <%s> ' . + 'is not a valid type.', + $type + ) + ); + } + + $this->type = $type; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return sprintf( + 'is of type "%s"', + $this->type + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + switch ($this->type) { + case 'numeric': + return is_numeric($other); + + case 'integer': + case 'int': + return is_int($other); + + case 'double': + case 'float': + case 'real': + return is_float($other); + + case 'string': + return is_string($other); + + case 'boolean': + case 'bool': + return is_bool($other); + + case 'null': + return null === $other; + + case 'array': + return is_array($other); + + case 'object': + return is_object($other); + + case 'resource': + $type = gettype($other); + + return $type === 'resource' || $type === 'resource (closed)'; + + case 'resource (closed)': + return gettype($other) === 'resource (closed)'; + + case 'scalar': + return is_scalar($other); + + case 'callable': + return is_callable($other); + + case 'iterable': + return is_iterable($other); + + default: + return false; + } + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/DataProviderTestSuite.php b/vendor/phpunit/phpunit/src/Framework/DataProviderTestSuite.php new file mode 100644 index 00000000..18b54999 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/DataProviderTestSuite.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function explode; +use PHPUnit\Util\Test as TestUtil; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DataProviderTestSuite extends TestSuite +{ + /** + * @var list + */ + private $dependencies = []; + + /** + * @param list $dependencies + */ + public function setDependencies(array $dependencies): void + { + $this->dependencies = $dependencies; + + foreach ($this->tests as $test) { + if (!$test instanceof TestCase) { + // @codeCoverageIgnoreStart + continue; + // @codeCoverageIgnoreStart + } + $test->setDependencies($dependencies); + } + } + + /** + * @return list + */ + public function provides(): array + { + if ($this->providedTests === null) { + $this->providedTests = [new ExecutionOrderDependency($this->getName())]; + } + + return $this->providedTests; + } + + /** + * @return list + */ + public function requires(): array + { + // A DataProviderTestSuite does not have to traverse its child tests + // as these are inherited and cannot reference dataProvider rows directly + return $this->dependencies; + } + + /** + * Returns the size of the each test created using the data provider(s). + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function getSize(): int + { + [$className, $methodName] = explode('::', $this->getName()); + + return TestUtil::getSize($className, $methodName); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Error/Deprecated.php b/vendor/phpunit/phpunit/src/Framework/Error/Deprecated.php new file mode 100644 index 00000000..db62195f --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Error/Deprecated.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Error; + +/** + * @internal + */ +final class Deprecated extends Error +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Error/Error.php b/vendor/phpunit/phpunit/src/Framework/Error/Error.php new file mode 100644 index 00000000..2990b360 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Error/Error.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Error; + +use PHPUnit\Framework\Exception; + +/** + * @internal + */ +class Error extends Exception +{ + public function __construct(string $message, int $code, string $file, int $line, \Exception $previous = null) + { + parent::__construct($message, $code, $previous); + + $this->file = $file; + $this->line = $line; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Error/Notice.php b/vendor/phpunit/phpunit/src/Framework/Error/Notice.php new file mode 100644 index 00000000..54e5e31e --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Error/Notice.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Error; + +/** + * @internal + */ +final class Notice extends Error +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Error/Warning.php b/vendor/phpunit/phpunit/src/Framework/Error/Warning.php new file mode 100644 index 00000000..0c0c0064 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Error/Warning.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Error; + +/** + * @internal + */ +final class Warning extends Error +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/ErrorTestCase.php b/vendor/phpunit/phpunit/src/Framework/ErrorTestCase.php new file mode 100644 index 00000000..841247d7 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/ErrorTestCase.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ErrorTestCase extends TestCase +{ + /** + * @var bool + */ + protected $backupGlobals = false; + + /** + * @var bool + */ + protected $backupStaticAttributes = false; + + /** + * @var bool + */ + protected $runTestInSeparateProcess = false; + + /** + * @var string + */ + private $message; + + public function __construct(string $message = '') + { + $this->message = $message; + + parent::__construct('Error'); + } + + public function getMessage(): string + { + return $this->message; + } + + /** + * Returns a string representation of the test case. + */ + public function toString(): string + { + return 'Error'; + } + + /** + * @throws Exception + * + * @psalm-return never-return + */ + protected function runTest(): void + { + throw new Error($this->message); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php b/vendor/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php new file mode 100644 index 00000000..adae2829 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/ActualValueIsNotAnObjectException.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use const PHP_EOL; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ActualValueIsNotAnObjectException extends Exception +{ + public function __construct() + { + parent::__construct( + 'Actual value is not an object', + 0, + null + ); + } + + public function __toString(): string + { + return $this->getMessage() . PHP_EOL; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php b/vendor/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php new file mode 100644 index 00000000..0ba25286 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class AssertionFailedError extends Exception implements SelfDescribing +{ + /** + * Wrapper for getMessage() which is declared as final. + */ + public function toString(): string + { + return $this->getMessage(); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php b/vendor/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php new file mode 100644 index 00000000..36b07231 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class CodeCoverageException extends Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotAcceptParameterTypeException.php b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotAcceptParameterTypeException.php new file mode 100644 index 00000000..ebd68f34 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotAcceptParameterTypeException.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use const PHP_EOL; +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ComparisonMethodDoesNotAcceptParameterTypeException extends Exception +{ + public function __construct(string $className, string $methodName, string $type) + { + parent::__construct( + sprintf( + '%s is not an accepted argument type for comparison method %s::%s().', + $type, + $className, + $methodName + ), + 0, + null + ); + } + + public function __toString(): string + { + return $this->getMessage() . PHP_EOL; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php new file mode 100644 index 00000000..20189cde --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use const PHP_EOL; +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ComparisonMethodDoesNotDeclareBoolReturnTypeException extends Exception +{ + public function __construct(string $className, string $methodName) + { + parent::__construct( + sprintf( + 'Comparison method %s::%s() does not declare bool return type.', + $className, + $methodName + ), + 0, + null + ); + } + + public function __toString(): string + { + return $this->getMessage() . PHP_EOL; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php new file mode 100644 index 00000000..bd09d87c --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use const PHP_EOL; +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ComparisonMethodDoesNotDeclareExactlyOneParameterException extends Exception +{ + public function __construct(string $className, string $methodName) + { + parent::__construct( + sprintf( + 'Comparison method %s::%s() does not declare exactly one parameter.', + $className, + $methodName + ), + 0, + null + ); + } + + public function __toString(): string + { + return $this->getMessage() . PHP_EOL; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareParameterTypeException.php b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareParameterTypeException.php new file mode 100644 index 00000000..9bbb112e --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotDeclareParameterTypeException.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use const PHP_EOL; +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ComparisonMethodDoesNotDeclareParameterTypeException extends Exception +{ + public function __construct(string $className, string $methodName) + { + parent::__construct( + sprintf( + 'Parameter of comparison method %s::%s() does not have a declared type.', + $className, + $methodName + ), + 0, + null + ); + } + + public function __toString(): string + { + return $this->getMessage() . PHP_EOL; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotExistException.php b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotExistException.php new file mode 100644 index 00000000..ad0e2d08 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/ComparisonMethodDoesNotExistException.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use const PHP_EOL; +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ComparisonMethodDoesNotExistException extends Exception +{ + public function __construct(string $className, string $methodName) + { + parent::__construct( + sprintf( + 'Comparison method %s::%s() does not exist.', + $className, + $methodName + ), + 0, + null + ); + } + + public function __toString(): string + { + return $this->getMessage() . PHP_EOL; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/CoveredCodeNotExecutedException.php b/vendor/phpunit/phpunit/src/Framework/Exception/CoveredCodeNotExecutedException.php new file mode 100644 index 00000000..78f89bc3 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/CoveredCodeNotExecutedException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CoveredCodeNotExecutedException extends RiskyTestError +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/Error.php b/vendor/phpunit/phpunit/src/Framework/Exception/Error.php new file mode 100644 index 00000000..d43e4218 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/Error.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Error extends Exception implements SelfDescribing +{ + /** + * Wrapper for getMessage() which is declared as final. + */ + public function toString(): string + { + return $this->getMessage(); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/Exception.php b/vendor/phpunit/phpunit/src/Framework/Exception/Exception.php new file mode 100644 index 00000000..0b21e6de --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/Exception.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function array_keys; +use function get_object_vars; +use PHPUnit\Util\Filter; +use RuntimeException; +use Throwable; + +/** + * Base class for all PHPUnit Framework exceptions. + * + * Ensures that exceptions thrown during a test run do not leave stray + * references behind. + * + * Every Exception contains a stack trace. Each stack frame contains the 'args' + * of the called function. The function arguments can contain references to + * instantiated objects. The references prevent the objects from being + * destructed (until test results are eventually printed), so memory cannot be + * freed up. + * + * With enabled process isolation, test results are serialized in the child + * process and unserialized in the parent process. The stack trace of Exceptions + * may contain objects that cannot be serialized or unserialized (e.g., PDO + * connections). Unserializing user-space objects from the child process into + * the parent would break the intended encapsulation of process isolation. + * + * @see http://fabien.potencier.org/article/9/php-serialization-stack-traces-and-exceptions + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class Exception extends RuntimeException implements \PHPUnit\Exception +{ + /** + * @var array + */ + protected $serializableTrace; + + public function __construct($message = '', $code = 0, Throwable $previous = null) + { + parent::__construct($message, $code, $previous); + + $this->serializableTrace = $this->getTrace(); + + foreach (array_keys($this->serializableTrace) as $key) { + unset($this->serializableTrace[$key]['args']); + } + } + + public function __toString(): string + { + $string = TestFailure::exceptionToString($this); + + if ($trace = Filter::getFilteredStacktrace($this)) { + $string .= "\n" . $trace; + } + + return $string; + } + + public function __sleep(): array + { + return array_keys(get_object_vars($this)); + } + + /** + * Returns the serializable trace (without 'args'). + */ + public function getSerializableTrace(): array + { + return $this->serializableTrace; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php b/vendor/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php new file mode 100644 index 00000000..b9a595a8 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use Exception; +use SebastianBergmann\Comparator\ComparisonFailure; + +/** + * Exception for expectations which failed their check. + * + * The exception contains the error message and optionally a + * SebastianBergmann\Comparator\ComparisonFailure which is used to + * generate diff output of the failed expectations. + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExpectationFailedException extends AssertionFailedError +{ + /** + * @var ComparisonFailure + */ + protected $comparisonFailure; + + public function __construct(string $message, ComparisonFailure $comparisonFailure = null, Exception $previous = null) + { + $this->comparisonFailure = $comparisonFailure; + + parent::__construct($message, 0, $previous); + } + + public function getComparisonFailure(): ?ComparisonFailure + { + return $this->comparisonFailure; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/IncompleteTestError.php b/vendor/phpunit/phpunit/src/Framework/Exception/IncompleteTestError.php new file mode 100644 index 00000000..65f9c8bc --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/IncompleteTestError.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class IncompleteTestError extends AssertionFailedError implements IncompleteTest +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php b/vendor/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php new file mode 100644 index 00000000..77f58079 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function debug_backtrace; +use function in_array; +use function lcfirst; +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidArgumentException extends Exception +{ + public static function create(int $argument, string $type): self + { + $stack = debug_backtrace(); + $function = $stack[1]['function']; + + if (isset($stack[1]['class'])) { + $function = sprintf('%s::%s', $stack[1]['class'], $stack[1]['function']); + } + + return new self( + sprintf( + 'Argument #%d of %s() must be %s %s', + $argument, + $function, + in_array(lcfirst($type)[0], ['a', 'e', 'i', 'o', 'u'], true) ? 'an' : 'a', + $type + ) + ); + } + + private function __construct(string $message = '', int $code = 0, \Exception $previous = null) + { + parent::__construct($message, $code, $previous); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php b/vendor/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php new file mode 100644 index 00000000..ebf2994a --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidCoversTargetException extends CodeCoverageException +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php b/vendor/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php new file mode 100644 index 00000000..7e2ef24c --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidDataProviderException extends Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/MissingCoversAnnotationException.php b/vendor/phpunit/phpunit/src/Framework/Exception/MissingCoversAnnotationException.php new file mode 100644 index 00000000..567a6c4c --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/MissingCoversAnnotationException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MissingCoversAnnotationException extends RiskyTestError +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php b/vendor/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php new file mode 100644 index 00000000..7ef4153b --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NoChildTestSuiteException extends Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/OutputError.php b/vendor/phpunit/phpunit/src/Framework/Exception/OutputError.php new file mode 100644 index 00000000..1c8b37e5 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/OutputError.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class OutputError extends AssertionFailedError +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/PHPTAssertionFailedError.php b/vendor/phpunit/phpunit/src/Framework/Exception/PHPTAssertionFailedError.php new file mode 100644 index 00000000..17126139 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/PHPTAssertionFailedError.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class PHPTAssertionFailedError extends SyntheticError +{ + /** + * @var string + */ + private $diff; + + public function __construct(string $message, int $code, string $file, int $line, array $trace, string $diff) + { + parent::__construct($message, $code, $file, $line, $trace); + $this->diff = $diff; + } + + public function getDiff(): string + { + return $this->diff; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/RiskyTestError.php b/vendor/phpunit/phpunit/src/Framework/Exception/RiskyTestError.php new file mode 100644 index 00000000..a66552c0 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/RiskyTestError.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class RiskyTestError extends AssertionFailedError +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/SkippedTestError.php b/vendor/phpunit/phpunit/src/Framework/Exception/SkippedTestError.php new file mode 100644 index 00000000..7d553dcf --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/SkippedTestError.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SkippedTestError extends AssertionFailedError implements SkippedTest +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/SkippedTestSuiteError.php b/vendor/phpunit/phpunit/src/Framework/Exception/SkippedTestSuiteError.php new file mode 100644 index 00000000..5448508a --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/SkippedTestSuiteError.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SkippedTestSuiteError extends AssertionFailedError implements SkippedTest +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/SyntheticError.php b/vendor/phpunit/phpunit/src/Framework/Exception/SyntheticError.php new file mode 100644 index 00000000..c3124ba0 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/SyntheticError.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class SyntheticError extends AssertionFailedError +{ + /** + * The synthetic file. + * + * @var string + */ + protected $syntheticFile = ''; + + /** + * The synthetic line number. + * + * @var int + */ + protected $syntheticLine = 0; + + /** + * The synthetic trace. + * + * @var array + */ + protected $syntheticTrace = []; + + public function __construct(string $message, int $code, string $file, int $line, array $trace) + { + parent::__construct($message, $code); + + $this->syntheticFile = $file; + $this->syntheticLine = $line; + $this->syntheticTrace = $trace; + } + + public function getSyntheticFile(): string + { + return $this->syntheticFile; + } + + public function getSyntheticLine(): int + { + return $this->syntheticLine; + } + + public function getSyntheticTrace(): array + { + return $this->syntheticTrace; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/SyntheticSkippedError.php b/vendor/phpunit/phpunit/src/Framework/Exception/SyntheticSkippedError.php new file mode 100644 index 00000000..f6e155d7 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/SyntheticSkippedError.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SyntheticSkippedError extends SyntheticError implements SkippedTest +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/UnintentionallyCoveredCodeError.php b/vendor/phpunit/phpunit/src/Framework/Exception/UnintentionallyCoveredCodeError.php new file mode 100644 index 00000000..fcd1d824 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/UnintentionallyCoveredCodeError.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class UnintentionallyCoveredCodeError extends RiskyTestError +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/Exception/Warning.php b/vendor/phpunit/phpunit/src/Framework/Exception/Warning.php new file mode 100644 index 00000000..35e94493 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Exception/Warning.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Warning extends Exception implements SelfDescribing +{ + /** + * Wrapper for getMessage() which is declared as final. + */ + public function toString(): string + { + return $this->getMessage(); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/ExceptionWrapper.php b/vendor/phpunit/phpunit/src/Framework/ExceptionWrapper.php new file mode 100644 index 00000000..00d40353 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/ExceptionWrapper.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use const PHP_VERSION_ID; +use function array_keys; +use function get_class; +use function spl_object_hash; +use PHPUnit\Util\Filter; +use Throwable; +use WeakReference; + +/** + * Wraps Exceptions thrown by code under test. + * + * Re-instantiates Exceptions thrown by user-space code to retain their original + * class names, properties, and stack traces (but without arguments). + * + * Unlike PHPUnit\Framework\Exception, the complete stack of previous Exceptions + * is processed. + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExceptionWrapper extends Exception +{ + /** + * @var string + */ + protected $className; + + /** + * @var null|ExceptionWrapper + */ + protected $previous; + + /** + * @var null|WeakReference + */ + private $originalException; + + public function __construct(Throwable $t) + { + // PDOException::getCode() is a string. + // @see https://php.net/manual/en/class.pdoexception.php#95812 + parent::__construct($t->getMessage(), (int) $t->getCode()); + + $this->setOriginalException($t); + } + + public function __toString(): string + { + $string = TestFailure::exceptionToString($this); + + if ($trace = Filter::getFilteredStacktrace($this)) { + $string .= "\n" . $trace; + } + + if ($this->previous) { + $string .= "\nCaused by\n" . $this->previous; + } + + return $string; + } + + public function getClassName(): string + { + return $this->className; + } + + public function getPreviousWrapped(): ?self + { + return $this->previous; + } + + public function setClassName(string $className): void + { + $this->className = $className; + } + + public function setOriginalException(Throwable $t): void + { + $this->originalException($t); + + $this->className = get_class($t); + $this->file = $t->getFile(); + $this->line = $t->getLine(); + + $this->serializableTrace = $t->getTrace(); + + foreach (array_keys($this->serializableTrace) as $key) { + unset($this->serializableTrace[$key]['args']); + } + + if ($t->getPrevious()) { + $this->previous = new self($t->getPrevious()); + } + } + + public function getOriginalException(): ?Throwable + { + return $this->originalException(); + } + + /** + * Method to contain static originalException to exclude it from stacktrace to prevent the stacktrace contents, + * which can be quite big, from being garbage-collected, thus blocking memory until shutdown. + * + * Approach works both for var_dump() and var_export() and print_r(). + */ + private function originalException(Throwable $exceptionToStore = null): ?Throwable + { + // drop once PHP 7.3 support is removed + if (PHP_VERSION_ID < 70400) { + static $originalExceptions; + + $instanceId = spl_object_hash($this); + + if ($exceptionToStore) { + $originalExceptions[$instanceId] = $exceptionToStore; + } + + return $originalExceptions[$instanceId] ?? null; + } + + if ($exceptionToStore) { + $this->originalException = WeakReference::create($exceptionToStore); + } + + return $this->originalException !== null ? $this->originalException->get() : null; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php b/vendor/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php new file mode 100644 index 00000000..09c343c1 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php @@ -0,0 +1,206 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function array_filter; +use function array_map; +use function array_values; +use function count; +use function explode; +use function in_array; +use function strpos; +use function trim; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExecutionOrderDependency +{ + /** + * @var string + */ + private $className = ''; + + /** + * @var string + */ + private $methodName = ''; + + /** + * @var bool + */ + private $useShallowClone = false; + + /** + * @var bool + */ + private $useDeepClone = false; + + public static function createFromDependsAnnotation(string $className, string $annotation): self + { + // Split clone option and target + $parts = explode(' ', trim($annotation), 2); + + if (count($parts) === 1) { + $cloneOption = ''; + $target = $parts[0]; + } else { + $cloneOption = $parts[0]; + $target = $parts[1]; + } + + // Prefix provided class for targets assumed to be in scope + if ($target !== '' && strpos($target, '::') === false) { + $target = $className . '::' . $target; + } + + return new self($target, null, $cloneOption); + } + + /** + * @psalm-param list $dependencies + * + * @psalm-return list + */ + public static function filterInvalid(array $dependencies): array + { + return array_values( + array_filter( + $dependencies, + static function (self $d) + { + return $d->isValid(); + } + ) + ); + } + + /** + * @psalm-param list $existing + * @psalm-param list $additional + * + * @psalm-return list + */ + public static function mergeUnique(array $existing, array $additional): array + { + $existingTargets = array_map( + static function ($dependency) + { + return $dependency->getTarget(); + }, + $existing + ); + + foreach ($additional as $dependency) { + if (in_array($dependency->getTarget(), $existingTargets, true)) { + continue; + } + + $existingTargets[] = $dependency->getTarget(); + $existing[] = $dependency; + } + + return $existing; + } + + /** + * @psalm-param list $left + * @psalm-param list $right + * + * @psalm-return list + */ + public static function diff(array $left, array $right): array + { + if ($right === []) { + return $left; + } + + if ($left === []) { + return []; + } + + $diff = []; + $rightTargets = array_map( + static function ($dependency) + { + return $dependency->getTarget(); + }, + $right + ); + + foreach ($left as $dependency) { + if (in_array($dependency->getTarget(), $rightTargets, true)) { + continue; + } + + $diff[] = $dependency; + } + + return $diff; + } + + public function __construct(string $classOrCallableName, ?string $methodName = null, ?string $option = null) + { + if ($classOrCallableName === '') { + return; + } + + if (strpos($classOrCallableName, '::') !== false) { + [$this->className, $this->methodName] = explode('::', $classOrCallableName); + } else { + $this->className = $classOrCallableName; + $this->methodName = !empty($methodName) ? $methodName : 'class'; + } + + if ($option === 'clone') { + $this->useDeepClone = true; + } elseif ($option === 'shallowClone') { + $this->useShallowClone = true; + } + } + + public function __toString(): string + { + return $this->getTarget(); + } + + public function isValid(): bool + { + // Invalid dependencies can be declared and are skipped by the runner + return $this->className !== '' && $this->methodName !== ''; + } + + public function useShallowClone(): bool + { + return $this->useShallowClone; + } + + public function useDeepClone(): bool + { + return $this->useDeepClone; + } + + public function targetIsClass(): bool + { + return $this->methodName === 'class'; + } + + public function getTarget(): string + { + return $this->isValid() + ? $this->className . '::' . $this->methodName + : ''; + } + + public function getTargetClassName(): string + { + return $this->className; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/IncompleteTest.php b/vendor/phpunit/phpunit/src/Framework/IncompleteTest.php new file mode 100644 index 00000000..b77b1aff --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/IncompleteTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface IncompleteTest extends Throwable +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/IncompleteTestCase.php b/vendor/phpunit/phpunit/src/Framework/IncompleteTestCase.php new file mode 100644 index 00000000..ee1e3e9f --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/IncompleteTestCase.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class IncompleteTestCase extends TestCase +{ + /** + * @var bool + */ + protected $backupGlobals = false; + + /** + * @var bool + */ + protected $backupStaticAttributes = false; + + /** + * @var bool + */ + protected $runTestInSeparateProcess = false; + + /** + * @var string + */ + private $message; + + public function __construct(string $className, string $methodName, string $message = '') + { + parent::__construct($className . '::' . $methodName); + + $this->message = $message; + } + + public function getMessage(): string + { + return $this->message; + } + + /** + * Returns a string representation of the test case. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + return $this->getName(); + } + + /** + * @throws Exception + */ + protected function runTest(): void + { + $this->markTestIncomplete($this->message); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/InvalidParameterGroupException.php b/vendor/phpunit/phpunit/src/Framework/InvalidParameterGroupException.php new file mode 100644 index 00000000..feb9cc98 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/InvalidParameterGroupException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidParameterGroupException extends Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Api/Api.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Api/Api.php new file mode 100644 index 00000000..e2f0a280 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Api/Api.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use PHPUnit\Framework\MockObject\Builder\InvocationMocker as InvocationMockerBuilder; +use PHPUnit\Framework\MockObject\Rule\InvocationOrder; + +/** + * @internal This trait is not covered by the backward compatibility promise for PHPUnit + */ +trait Api +{ + /** + * @var ConfigurableMethod[] + */ + private static $__phpunit_configurableMethods; + + /** + * @var object + */ + private $__phpunit_originalObject; + + /** + * @var bool + */ + private $__phpunit_returnValueGeneration = true; + + /** + * @var InvocationHandler + */ + private $__phpunit_invocationMocker; + + /** @noinspection MagicMethodsValidityInspection */ + public static function __phpunit_initConfigurableMethods(ConfigurableMethod ...$configurableMethods): void + { + if (isset(static::$__phpunit_configurableMethods)) { + throw new ConfigurableMethodsAlreadyInitializedException( + 'Configurable methods is already initialized and can not be reinitialized' + ); + } + + static::$__phpunit_configurableMethods = $configurableMethods; + } + + /** @noinspection MagicMethodsValidityInspection */ + public function __phpunit_setOriginalObject($originalObject): void + { + $this->__phpunit_originalObject = $originalObject; + } + + /** @noinspection MagicMethodsValidityInspection */ + public function __phpunit_setReturnValueGeneration(bool $returnValueGeneration): void + { + $this->__phpunit_returnValueGeneration = $returnValueGeneration; + } + + /** @noinspection MagicMethodsValidityInspection */ + public function __phpunit_getInvocationHandler(): InvocationHandler + { + if ($this->__phpunit_invocationMocker === null) { + $this->__phpunit_invocationMocker = new InvocationHandler( + static::$__phpunit_configurableMethods, + $this->__phpunit_returnValueGeneration + ); + } + + return $this->__phpunit_invocationMocker; + } + + /** @noinspection MagicMethodsValidityInspection */ + public function __phpunit_hasMatchers(): bool + { + return $this->__phpunit_getInvocationHandler()->hasMatchers(); + } + + /** @noinspection MagicMethodsValidityInspection */ + public function __phpunit_verify(bool $unsetInvocationMocker = true): void + { + $this->__phpunit_getInvocationHandler()->verify(); + + if ($unsetInvocationMocker) { + $this->__phpunit_invocationMocker = null; + } + } + + public function expects(InvocationOrder $matcher): InvocationMockerBuilder + { + return $this->__phpunit_getInvocationHandler()->expects($matcher); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Api/Method.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Api/Method.php new file mode 100644 index 00000000..f6df7533 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Api/Method.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function call_user_func_array; +use function func_get_args; +use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount; + +/** + * @internal This trait is not covered by the backward compatibility promise for PHPUnit + */ +trait Method +{ + public function method() + { + $expects = $this->expects(new AnyInvokedCount); + + return call_user_func_array( + [$expects, 'method'], + func_get_args() + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/Identity.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/Identity.php new file mode 100644 index 00000000..a68bfadf --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/Identity.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Identity +{ + /** + * Sets the identification of the expectation to $id. + * + * @note The identifier is unique per mock object. + * + * @param string $id unique identification of expectation + */ + public function id($id); +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationMocker.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationMocker.php new file mode 100644 index 00000000..bc3c9236 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationMocker.php @@ -0,0 +1,308 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +use function array_map; +use function array_merge; +use function count; +use function in_array; +use function is_string; +use function strtolower; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\MockObject\ConfigurableMethod; +use PHPUnit\Framework\MockObject\IncompatibleReturnValueException; +use PHPUnit\Framework\MockObject\InvocationHandler; +use PHPUnit\Framework\MockObject\Matcher; +use PHPUnit\Framework\MockObject\MatcherAlreadyRegisteredException; +use PHPUnit\Framework\MockObject\MethodCannotBeConfiguredException; +use PHPUnit\Framework\MockObject\MethodNameAlreadyConfiguredException; +use PHPUnit\Framework\MockObject\MethodNameNotConfiguredException; +use PHPUnit\Framework\MockObject\MethodParametersAlreadyConfiguredException; +use PHPUnit\Framework\MockObject\Rule; +use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls; +use PHPUnit\Framework\MockObject\Stub\Exception; +use PHPUnit\Framework\MockObject\Stub\ReturnArgument; +use PHPUnit\Framework\MockObject\Stub\ReturnCallback; +use PHPUnit\Framework\MockObject\Stub\ReturnReference; +use PHPUnit\Framework\MockObject\Stub\ReturnSelf; +use PHPUnit\Framework\MockObject\Stub\ReturnStub; +use PHPUnit\Framework\MockObject\Stub\ReturnValueMap; +use PHPUnit\Framework\MockObject\Stub\Stub; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class InvocationMocker implements InvocationStubber, MethodNameMatch +{ + /** + * @var InvocationHandler + */ + private $invocationHandler; + + /** + * @var Matcher + */ + private $matcher; + + /** + * @var ConfigurableMethod[] + */ + private $configurableMethods; + + public function __construct(InvocationHandler $handler, Matcher $matcher, ConfigurableMethod ...$configurableMethods) + { + $this->invocationHandler = $handler; + $this->matcher = $matcher; + $this->configurableMethods = $configurableMethods; + } + + /** + * @throws MatcherAlreadyRegisteredException + * + * @return $this + */ + public function id($id): self + { + $this->invocationHandler->registerMatcher($id, $this->matcher); + + return $this; + } + + /** + * @return $this + */ + public function will(Stub $stub): Identity + { + $this->matcher->setStub($stub); + + return $this; + } + + /** + * @param mixed $value + * @param mixed[] $nextValues + * + * @throws IncompatibleReturnValueException + */ + public function willReturn($value, ...$nextValues): self + { + if (count($nextValues) === 0) { + $this->ensureTypeOfReturnValues([$value]); + + $stub = $value instanceof Stub ? $value : new ReturnStub($value); + } else { + $values = array_merge([$value], $nextValues); + + $this->ensureTypeOfReturnValues($values); + + $stub = new ConsecutiveCalls($values); + } + + return $this->will($stub); + } + + public function willReturnReference(&$reference): self + { + $stub = new ReturnReference($reference); + + return $this->will($stub); + } + + public function willReturnMap(array $valueMap): self + { + $stub = new ReturnValueMap($valueMap); + + return $this->will($stub); + } + + public function willReturnArgument($argumentIndex): self + { + $stub = new ReturnArgument($argumentIndex); + + return $this->will($stub); + } + + public function willReturnCallback($callback): self + { + $stub = new ReturnCallback($callback); + + return $this->will($stub); + } + + public function willReturnSelf(): self + { + $stub = new ReturnSelf; + + return $this->will($stub); + } + + public function willReturnOnConsecutiveCalls(...$values): self + { + $stub = new ConsecutiveCalls($values); + + return $this->will($stub); + } + + public function willThrowException(Throwable $exception): self + { + $stub = new Exception($exception); + + return $this->will($stub); + } + + /** + * @return $this + */ + public function after($id): self + { + $this->matcher->setAfterMatchBuilderId($id); + + return $this; + } + + /** + * @param mixed[] $arguments + * + * @throws \PHPUnit\Framework\Exception + * @throws MethodNameNotConfiguredException + * @throws MethodParametersAlreadyConfiguredException + * + * @return $this + */ + public function with(...$arguments): self + { + $this->ensureParametersCanBeConfigured(); + + $this->matcher->setParametersRule(new Rule\Parameters($arguments)); + + return $this; + } + + /** + * @param array ...$arguments + * + * @throws \PHPUnit\Framework\Exception + * @throws MethodNameNotConfiguredException + * @throws MethodParametersAlreadyConfiguredException + * + * @return $this + * + * @deprecated + */ + public function withConsecutive(...$arguments): self + { + $this->ensureParametersCanBeConfigured(); + + $this->matcher->setParametersRule(new Rule\ConsecutiveParameters($arguments)); + + return $this; + } + + /** + * @throws MethodNameNotConfiguredException + * @throws MethodParametersAlreadyConfiguredException + * + * @return $this + */ + public function withAnyParameters(): self + { + $this->ensureParametersCanBeConfigured(); + + $this->matcher->setParametersRule(new Rule\AnyParameters); + + return $this; + } + + /** + * @param Constraint|string $constraint + * + * @throws \PHPUnit\Framework\InvalidArgumentException + * @throws MethodCannotBeConfiguredException + * @throws MethodNameAlreadyConfiguredException + * + * @return $this + */ + public function method($constraint): self + { + if ($this->matcher->hasMethodNameRule()) { + throw new MethodNameAlreadyConfiguredException; + } + + $configurableMethodNames = array_map( + static function (ConfigurableMethod $configurable) + { + return strtolower($configurable->getName()); + }, + $this->configurableMethods + ); + + if (is_string($constraint) && !in_array(strtolower($constraint), $configurableMethodNames, true)) { + throw new MethodCannotBeConfiguredException($constraint); + } + + $this->matcher->setMethodNameRule(new Rule\MethodName($constraint)); + + return $this; + } + + /** + * @throws MethodNameNotConfiguredException + * @throws MethodParametersAlreadyConfiguredException + */ + private function ensureParametersCanBeConfigured(): void + { + if (!$this->matcher->hasMethodNameRule()) { + throw new MethodNameNotConfiguredException; + } + + if ($this->matcher->hasParametersRule()) { + throw new MethodParametersAlreadyConfiguredException; + } + } + + private function getConfiguredMethod(): ?ConfigurableMethod + { + $configuredMethod = null; + + foreach ($this->configurableMethods as $configurableMethod) { + if ($this->matcher->getMethodNameRule()->matchesName($configurableMethod->getName())) { + if ($configuredMethod !== null) { + return null; + } + + $configuredMethod = $configurableMethod; + } + } + + return $configuredMethod; + } + + /** + * @throws IncompatibleReturnValueException + */ + private function ensureTypeOfReturnValues(array $values): void + { + $configuredMethod = $this->getConfiguredMethod(); + + if ($configuredMethod === null) { + return; + } + + foreach ($values as $value) { + if (!$configuredMethod->mayReturn($value)) { + throw new IncompatibleReturnValueException( + $configuredMethod, + $value + ); + } + } + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationStubber.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationStubber.php new file mode 100644 index 00000000..f32ff0e7 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/InvocationStubber.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +use PHPUnit\Framework\MockObject\Stub\Stub; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface InvocationStubber +{ + public function will(Stub $stub): Identity; + + /** @return self */ + public function willReturn($value, ...$nextValues)/*: self */; + + /** + * @param mixed $reference + * + * @return self + */ + public function willReturnReference(&$reference)/*: self */; + + /** + * @param array> $valueMap + * + * @return self + */ + public function willReturnMap(array $valueMap)/*: self */; + + /** + * @param int $argumentIndex + * + * @return self + */ + public function willReturnArgument($argumentIndex)/*: self */; + + /** + * @param callable $callback + * + * @return self + */ + public function willReturnCallback($callback)/*: self */; + + /** @return self */ + public function willReturnSelf()/*: self */; + + /** + * @param mixed $values + * + * @return self + */ + public function willReturnOnConsecutiveCalls(...$values)/*: self */; + + /** @return self */ + public function willThrowException(Throwable $exception)/*: self */; +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/MethodNameMatch.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/MethodNameMatch.php new file mode 100644 index 00000000..543d596c --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/MethodNameMatch.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface MethodNameMatch extends ParametersMatch +{ + /** + * Adds a new method name match and returns the parameter match object for + * further matching possibilities. + * + * @param \PHPUnit\Framework\Constraint\Constraint $constraint Constraint for matching method, if a string is passed it will use the PHPUnit_Framework_Constraint_IsEqual + * + * @return ParametersMatch + */ + public function method($constraint); +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/ParametersMatch.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/ParametersMatch.php new file mode 100644 index 00000000..707d8255 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/ParametersMatch.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface ParametersMatch extends Stub +{ + /** + * Defines the expectation which must occur before the current is valid. + * + * @param string $id the identification of the expectation that should + * occur before this one + * + * @return Stub + */ + public function after($id); + + /** + * Sets the parameters to match for, each parameter to this function will + * be part of match. To perform specific matches or constraints create a + * new PHPUnit\Framework\Constraint\Constraint and use it for the parameter. + * If the parameter value is not a constraint it will use the + * PHPUnit\Framework\Constraint\IsEqual for the value. + * + * Some examples: + * + * // match first parameter with value 2 + * $b->with(2); + * // match first parameter with value 'smock' and second identical to 42 + * $b->with('smock', new PHPUnit\Framework\Constraint\IsEqual(42)); + * + * + * @return ParametersMatch + */ + public function with(...$arguments); + + /** + * Sets a rule which allows any kind of parameters. + * + * Some examples: + * + * // match any number of parameters + * $b->withAnyParameters(); + * + * + * @return ParametersMatch + */ + public function withAnyParameters(); +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/Stub.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/Stub.php new file mode 100644 index 00000000..d7cb78fc --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Builder/Stub.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +use PHPUnit\Framework\MockObject\Stub\Stub as BaseStub; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Stub extends Identity +{ + /** + * Stubs the matching method with the stub object $stub. Any invocations of + * the matched method will now be handled by the stub instead. + */ + public function will(BaseStub $stub): Identity; +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php b/vendor/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php new file mode 100644 index 00000000..4757dc63 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use SebastianBergmann\Type\Type; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ConfigurableMethod +{ + /** + * @var string + */ + private $name; + + /** + * @var Type + */ + private $returnType; + + public function __construct(string $name, Type $returnType) + { + $this->name = $name; + $this->returnType = $returnType; + } + + public function getName(): string + { + return $this->name; + } + + public function mayReturn($value): bool + { + if ($value === null && $this->returnType->allowsNull()) { + return true; + } + + return $this->returnType->isAssignable(Type::fromValue($value, false)); + } + + public function getReturnTypeDeclaration(): string + { + return $this->returnType->asString(); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php new file mode 100644 index 00000000..7e655e23 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class BadMethodCallException extends \BadMethodCallException implements Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseAddMethodsException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseAddMethodsException.php new file mode 100644 index 00000000..0698870b --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseAddMethodsException.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CannotUseAddMethodsException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $type, string $methodName) + { + parent::__construct( + sprintf( + 'Trying to configure method "%s" with addMethods(), but it exists in class "%s". Use onlyMethods() for methods that exist in the class', + $methodName, + $type + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php new file mode 100644 index 00000000..35a29b73 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CannotUseOnlyMethodsException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $type, string $methodName) + { + parent::__construct( + sprintf( + 'Trying to configure method "%s" with onlyMethods(), but it does not exist in class "%s". Use addMethods() for methods that do not exist in the class', + $methodName, + $type + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassAlreadyExistsException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassAlreadyExistsException.php new file mode 100644 index 00000000..0ba9a187 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassAlreadyExistsException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ClassAlreadyExistsException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $className) + { + parent::__construct( + sprintf( + 'Class "%s" already exists', + $className + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsFinalException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsFinalException.php new file mode 100644 index 00000000..e648f026 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsFinalException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ClassIsFinalException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $className) + { + parent::__construct( + sprintf( + 'Class "%s" is declared "final" and cannot be doubled', + $className + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsReadonlyException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsReadonlyException.php new file mode 100644 index 00000000..aa1a7451 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ClassIsReadonlyException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ClassIsReadonlyException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $className) + { + parent::__construct( + sprintf( + 'Class "%s" is declared "readonly" and cannot be doubled', + $className + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ConfigurableMethodsAlreadyInitializedException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ConfigurableMethodsAlreadyInitializedException.php new file mode 100644 index 00000000..d12ac997 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ConfigurableMethodsAlreadyInitializedException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ConfigurableMethodsAlreadyInitializedException extends \PHPUnit\Framework\Exception implements Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/DuplicateMethodException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/DuplicateMethodException.php new file mode 100644 index 00000000..1216b45d --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/DuplicateMethodException.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function array_diff_assoc; +use function array_unique; +use function implode; +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DuplicateMethodException extends \PHPUnit\Framework\Exception implements Exception +{ + /** + * @psalm-param list $methods + */ + public function __construct(array $methods) + { + parent::__construct( + sprintf( + 'Cannot double using a method list that contains duplicates: "%s" (duplicate: "%s")', + implode(', ', $methods), + implode(', ', array_unique(array_diff_assoc($methods, array_unique($methods)))) + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php new file mode 100644 index 00000000..5880bc03 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Exception extends Throwable +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php new file mode 100644 index 00000000..eec79213 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function get_class; +use function gettype; +use function is_object; +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class IncompatibleReturnValueException extends \PHPUnit\Framework\Exception implements Exception +{ + /** + * @param mixed $value + */ + public function __construct(ConfigurableMethod $method, $value) + { + parent::__construct( + sprintf( + 'Method %s may not return value of type %s, its declared return type is "%s"', + $method->getName(), + is_object($value) ? get_class($value) : gettype($value), + $method->getReturnTypeDeclaration() + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/InvalidMethodNameException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/InvalidMethodNameException.php new file mode 100644 index 00000000..d2444cf1 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/InvalidMethodNameException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidMethodNameException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $method) + { + parent::__construct( + sprintf( + 'Cannot double method with invalid name "%s"', + $method + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php new file mode 100644 index 00000000..c05b2bce --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MatchBuilderNotFoundException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $id) + { + parent::__construct( + sprintf( + 'No builder found for match builder identification <%s>', + $id + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php new file mode 100644 index 00000000..efcc13ed --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MatcherAlreadyRegisteredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $id) + { + parent::__construct( + sprintf( + 'Matcher with id <%s> is already registered', + $id + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php new file mode 100644 index 00000000..70729043 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MethodCannotBeConfiguredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $method) + { + parent::__construct( + sprintf( + 'Trying to configure method "%s" which cannot be configured because it does not exist, has not been specified, is final, or is static', + $method + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php new file mode 100644 index 00000000..1e9f2c04 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MethodNameAlreadyConfiguredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct() + { + parent::__construct('Method name is already configured'); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php new file mode 100644 index 00000000..89565b77 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MethodNameNotConfiguredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct() + { + parent::__construct('Method name is not configured'); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php new file mode 100644 index 00000000..1609c6ff --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MethodParametersAlreadyConfiguredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct() + { + parent::__construct('Method parameters already configured'); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/OriginalConstructorInvocationRequiredException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/OriginalConstructorInvocationRequiredException.php new file mode 100644 index 00000000..ecb9b63c --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/OriginalConstructorInvocationRequiredException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class OriginalConstructorInvocationRequiredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct() + { + parent::__construct('Proxying to original methods requires invoking the original constructor'); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReflectionException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReflectionException.php new file mode 100644 index 00000000..d6319c69 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReflectionException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use RuntimeException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReflectionException extends RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php new file mode 100644 index 00000000..2c16c1dc --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnValueNotConfiguredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(Invocation $invocation) + { + parent::__construct( + sprintf( + 'Return value inference disabled and no expectation set up for %s::%s()', + $invocation->getClassName(), + $invocation->getMethodName() + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php new file mode 100644 index 00000000..33b6a5be --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/SoapExtensionNotAvailableException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/SoapExtensionNotAvailableException.php new file mode 100644 index 00000000..98837c95 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/SoapExtensionNotAvailableException.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SoapExtensionNotAvailableException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct() + { + parent::__construct( + 'The SOAP extension is required to generate a test double from WSDL' + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownClassException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownClassException.php new file mode 100644 index 00000000..e124f9b1 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownClassException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class UnknownClassException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $className) + { + parent::__construct( + sprintf( + 'Class "%s" does not exist', + $className + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTraitException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTraitException.php new file mode 100644 index 00000000..90fc8d84 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTraitException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class UnknownTraitException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $traitName) + { + parent::__construct( + sprintf( + 'Trait "%s" does not exist', + $traitName + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTypeException.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTypeException.php new file mode 100644 index 00000000..b1a70edd --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/UnknownTypeException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class UnknownTypeException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $type) + { + parent::__construct( + sprintf( + 'Class or interface "%s" does not exist', + $type + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator.php new file mode 100644 index 00000000..17e3312c --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator.php @@ -0,0 +1,1163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use const DIRECTORY_SEPARATOR; +use const PHP_EOL; +use const PHP_MAJOR_VERSION; +use const PREG_OFFSET_CAPTURE; +use const WSDL_CACHE_NONE; +use function array_merge; +use function array_pop; +use function array_unique; +use function class_exists; +use function count; +use function explode; +use function extension_loaded; +use function implode; +use function in_array; +use function interface_exists; +use function is_array; +use function is_object; +use function md5; +use function method_exists; +use function mt_rand; +use function preg_match; +use function preg_match_all; +use function range; +use function serialize; +use function sort; +use function sprintf; +use function str_replace; +use function strlen; +use function strpos; +use function strtolower; +use function substr; +use function trait_exists; +use Doctrine\Instantiator\Exception\ExceptionInterface as InstantiatorException; +use Doctrine\Instantiator\Instantiator; +use Exception; +use Iterator; +use IteratorAggregate; +use PHPUnit\Framework\InvalidArgumentException; +use ReflectionClass; +use ReflectionMethod; +use SebastianBergmann\Template\Exception as TemplateException; +use SebastianBergmann\Template\Template; +use SoapClient; +use SoapFault; +use Throwable; +use Traversable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Generator +{ + private const MOCKED_CLONE_METHOD_WITH_VOID_RETURN_TYPE_TRAIT = <<<'EOT' +namespace PHPUnit\Framework\MockObject; + +trait MockedCloneMethodWithVoidReturnType +{ + public function __clone(): void + { + $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationHandler(); + } +} +EOT; + + private const MOCKED_CLONE_METHOD_WITHOUT_RETURN_TYPE_TRAIT = <<<'EOT' +namespace PHPUnit\Framework\MockObject; + +trait MockedCloneMethodWithoutReturnType +{ + public function __clone() + { + $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationHandler(); + } +} +EOT; + + private const UNMOCKED_CLONE_METHOD_WITH_VOID_RETURN_TYPE_TRAIT = <<<'EOT' +namespace PHPUnit\Framework\MockObject; + +trait UnmockedCloneMethodWithVoidReturnType +{ + public function __clone(): void + { + $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationHandler(); + + parent::__clone(); + } +} +EOT; + + private const UNMOCKED_CLONE_METHOD_WITHOUT_RETURN_TYPE_TRAIT = <<<'EOT' +namespace PHPUnit\Framework\MockObject; + +trait UnmockedCloneMethodWithoutReturnType +{ + public function __clone() + { + $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationHandler(); + + parent::__clone(); + } +} +EOT; + + /** + * @var array + */ + private const EXCLUDED_METHOD_NAMES = [ + '__CLASS__' => true, + '__DIR__' => true, + '__FILE__' => true, + '__FUNCTION__' => true, + '__LINE__' => true, + '__METHOD__' => true, + '__NAMESPACE__' => true, + '__TRAIT__' => true, + '__clone' => true, + '__halt_compiler' => true, + ]; + + /** + * @var array + */ + private static $cache = []; + + /** + * @var Template[] + */ + private static $templates = []; + + /** + * Returns a mock object for the specified class. + * + * @param null|array $methods + * + * @throws \PHPUnit\Framework\InvalidArgumentException + * @throws ClassAlreadyExistsException + * @throws ClassIsFinalException + * @throws ClassIsReadonlyException + * @throws DuplicateMethodException + * @throws InvalidMethodNameException + * @throws OriginalConstructorInvocationRequiredException + * @throws ReflectionException + * @throws RuntimeException + * @throws UnknownTypeException + */ + public function getMock(string $type, $methods = [], array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, bool $cloneArguments = true, bool $callOriginalMethods = false, object $proxyTarget = null, bool $allowMockingUnknownTypes = true, bool $returnValueGeneration = true): MockObject + { + if (!is_array($methods) && null !== $methods) { + throw InvalidArgumentException::create(2, 'array'); + } + + if ($type === 'Traversable' || $type === '\\Traversable') { + $type = 'Iterator'; + } + + if (!$allowMockingUnknownTypes && !class_exists($type, $callAutoload) && !interface_exists($type, $callAutoload)) { + throw new UnknownTypeException($type); + } + + if (null !== $methods) { + foreach ($methods as $method) { + if (!preg_match('~[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*~', (string) $method)) { + throw new InvalidMethodNameException((string) $method); + } + } + + if ($methods !== array_unique($methods)) { + throw new DuplicateMethodException($methods); + } + } + + if ($mockClassName !== '' && class_exists($mockClassName, false)) { + try { + $reflector = new ReflectionClass($mockClassName); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + if (!$reflector->implementsInterface(MockObject::class)) { + throw new ClassAlreadyExistsException($mockClassName); + } + } + + if (!$callOriginalConstructor && $callOriginalMethods) { + throw new OriginalConstructorInvocationRequiredException; + } + + $mock = $this->generate( + $type, + $methods, + $mockClassName, + $callOriginalClone, + $callAutoload, + $cloneArguments, + $callOriginalMethods + ); + + return $this->getObject( + $mock, + $type, + $callOriginalConstructor, + $callAutoload, + $arguments, + $callOriginalMethods, + $proxyTarget, + $returnValueGeneration + ); + } + + /** + * @psalm-param list $interfaces + * + * @throws RuntimeException + * @throws UnknownTypeException + */ + public function getMockForInterfaces(array $interfaces, bool $callAutoload = true): MockObject + { + if (count($interfaces) < 2) { + throw new RuntimeException('At least two interfaces must be specified'); + } + + foreach ($interfaces as $interface) { + if (!interface_exists($interface, $callAutoload)) { + throw new UnknownTypeException($interface); + } + } + + sort($interfaces); + + $methods = []; + + foreach ($interfaces as $interface) { + $methods = array_merge($methods, $this->getClassMethods($interface)); + } + + if (count(array_unique($methods)) < count($methods)) { + throw new RuntimeException('Interfaces must not declare the same method'); + } + + $unqualifiedNames = []; + + foreach ($interfaces as $interface) { + $parts = explode('\\', $interface); + $unqualifiedNames[] = array_pop($parts); + } + + sort($unqualifiedNames); + + do { + $intersectionName = sprintf( + 'Intersection_%s_%s', + implode('_', $unqualifiedNames), + substr(md5((string) mt_rand()), 0, 8) + ); + } while (interface_exists($intersectionName, false)); + + $template = $this->getTemplate('intersection.tpl'); + + $template->setVar( + [ + 'intersection' => $intersectionName, + 'interfaces' => implode(', ', $interfaces), + ] + ); + + eval($template->render()); + + return $this->getMock($intersectionName); + } + + /** + * Returns a mock object for the specified abstract class with all abstract + * methods of the class mocked. + * + * Concrete methods to mock can be specified with the $mockedMethods parameter. + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return MockObject&RealInstanceType + * + * @throws \PHPUnit\Framework\InvalidArgumentException + * @throws ClassAlreadyExistsException + * @throws ClassIsFinalException + * @throws ClassIsReadonlyException + * @throws DuplicateMethodException + * @throws InvalidMethodNameException + * @throws OriginalConstructorInvocationRequiredException + * @throws ReflectionException + * @throws RuntimeException + * @throws UnknownClassException + * @throws UnknownTypeException + */ + public function getMockForAbstractClass(string $originalClassName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, array $mockedMethods = null, bool $cloneArguments = true): MockObject + { + if (class_exists($originalClassName, $callAutoload) || + interface_exists($originalClassName, $callAutoload)) { + try { + $reflector = new ReflectionClass($originalClassName); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + $methods = $mockedMethods; + + foreach ($reflector->getMethods() as $method) { + if ($method->isAbstract() && !in_array($method->getName(), $methods ?? [], true)) { + $methods[] = $method->getName(); + } + } + + if (empty($methods)) { + $methods = null; + } + + return $this->getMock( + $originalClassName, + $methods, + $arguments, + $mockClassName, + $callOriginalConstructor, + $callOriginalClone, + $callAutoload, + $cloneArguments + ); + } + + throw new UnknownClassException($originalClassName); + } + + /** + * Returns a mock object for the specified trait with all abstract methods + * of the trait mocked. Concrete methods to mock can be specified with the + * `$mockedMethods` parameter. + * + * @psalm-param trait-string $traitName + * + * @throws \PHPUnit\Framework\InvalidArgumentException + * @throws ClassAlreadyExistsException + * @throws ClassIsFinalException + * @throws ClassIsReadonlyException + * @throws DuplicateMethodException + * @throws InvalidMethodNameException + * @throws OriginalConstructorInvocationRequiredException + * @throws ReflectionException + * @throws RuntimeException + * @throws UnknownClassException + * @throws UnknownTraitException + * @throws UnknownTypeException + */ + public function getMockForTrait(string $traitName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, array $mockedMethods = null, bool $cloneArguments = true): MockObject + { + if (!trait_exists($traitName, $callAutoload)) { + throw new UnknownTraitException($traitName); + } + + $className = $this->generateClassName( + $traitName, + '', + 'Trait_' + ); + + $classTemplate = $this->getTemplate('trait_class.tpl'); + + $classTemplate->setVar( + [ + 'prologue' => 'abstract ', + 'class_name' => $className['className'], + 'trait_name' => $traitName, + ] + ); + + $mockTrait = new MockTrait($classTemplate->render(), $className['className']); + $mockTrait->generate(); + + return $this->getMockForAbstractClass($className['className'], $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $mockedMethods, $cloneArguments); + } + + /** + * Returns an object for the specified trait. + * + * @psalm-param trait-string $traitName + * + * @throws ReflectionException + * @throws RuntimeException + * @throws UnknownTraitException + */ + public function getObjectForTrait(string $traitName, string $traitClassName = '', bool $callAutoload = true, bool $callOriginalConstructor = false, array $arguments = []): object + { + if (!trait_exists($traitName, $callAutoload)) { + throw new UnknownTraitException($traitName); + } + + $className = $this->generateClassName( + $traitName, + $traitClassName, + 'Trait_' + ); + + $classTemplate = $this->getTemplate('trait_class.tpl'); + + $classTemplate->setVar( + [ + 'prologue' => '', + 'class_name' => $className['className'], + 'trait_name' => $traitName, + ] + ); + + return $this->getObject( + new MockTrait( + $classTemplate->render(), + $className['className'] + ), + '', + $callOriginalConstructor, + $callAutoload, + $arguments + ); + } + + /** + * @throws ClassIsFinalException + * @throws ClassIsReadonlyException + * @throws ReflectionException + * @throws RuntimeException + */ + public function generate(string $type, array $methods = null, string $mockClassName = '', bool $callOriginalClone = true, bool $callAutoload = true, bool $cloneArguments = true, bool $callOriginalMethods = false): MockClass + { + if ($mockClassName !== '') { + return $this->generateMock( + $type, + $methods, + $mockClassName, + $callOriginalClone, + $callAutoload, + $cloneArguments, + $callOriginalMethods + ); + } + + $key = md5( + $type . + serialize($methods) . + serialize($callOriginalClone) . + serialize($cloneArguments) . + serialize($callOriginalMethods) + ); + + if (!isset(self::$cache[$key])) { + self::$cache[$key] = $this->generateMock( + $type, + $methods, + $mockClassName, + $callOriginalClone, + $callAutoload, + $cloneArguments, + $callOriginalMethods + ); + } + + return self::$cache[$key]; + } + + /** + * @throws RuntimeException + * @throws SoapExtensionNotAvailableException + */ + public function generateClassFromWsdl(string $wsdlFile, string $className, array $methods = [], array $options = []): string + { + if (!extension_loaded('soap')) { + throw new SoapExtensionNotAvailableException; + } + + $options = array_merge($options, ['cache_wsdl' => WSDL_CACHE_NONE]); + + try { + $client = new SoapClient($wsdlFile, $options); + $_methods = array_unique($client->__getFunctions()); + unset($client); + } catch (SoapFault $e) { + throw new RuntimeException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + + sort($_methods); + + $methodTemplate = $this->getTemplate('wsdl_method.tpl'); + $methodsBuffer = ''; + + foreach ($_methods as $method) { + preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\(/', $method, $matches, PREG_OFFSET_CAPTURE); + $lastFunction = array_pop($matches[0]); + $nameStart = $lastFunction[1]; + $nameEnd = $nameStart + strlen($lastFunction[0]) - 1; + $name = str_replace('(', '', $lastFunction[0]); + + if (empty($methods) || in_array($name, $methods, true)) { + $args = explode( + ',', + str_replace(')', '', substr($method, $nameEnd + 1)) + ); + + foreach (range(0, count($args) - 1) as $i) { + $parameterStart = strpos($args[$i], '$'); + + if (!$parameterStart) { + continue; + } + + $args[$i] = substr($args[$i], $parameterStart); + } + + $methodTemplate->setVar( + [ + 'method_name' => $name, + 'arguments' => implode(', ', $args), + ] + ); + + $methodsBuffer .= $methodTemplate->render(); + } + } + + $optionsBuffer = '['; + + foreach ($options as $key => $value) { + $optionsBuffer .= $key . ' => ' . $value; + } + + $optionsBuffer .= ']'; + + $classTemplate = $this->getTemplate('wsdl_class.tpl'); + $namespace = ''; + + if (strpos($className, '\\') !== false) { + $parts = explode('\\', $className); + $className = array_pop($parts); + $namespace = 'namespace ' . implode('\\', $parts) . ';' . "\n\n"; + } + + $classTemplate->setVar( + [ + 'namespace' => $namespace, + 'class_name' => $className, + 'wsdl' => $wsdlFile, + 'options' => $optionsBuffer, + 'methods' => $methodsBuffer, + ] + ); + + return $classTemplate->render(); + } + + /** + * @throws ReflectionException + * + * @return string[] + */ + public function getClassMethods(string $className): array + { + try { + $class = new ReflectionClass($className); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + $methods = []; + + foreach ($class->getMethods() as $method) { + if ($method->isPublic() || $method->isAbstract()) { + $methods[] = $method->getName(); + } + } + + return $methods; + } + + /** + * @throws ReflectionException + * + * @return MockMethod[] + */ + public function mockClassMethods(string $className, bool $callOriginalMethods, bool $cloneArguments): array + { + try { + $class = new ReflectionClass($className); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + $methods = []; + + foreach ($class->getMethods() as $method) { + if (($method->isPublic() || $method->isAbstract()) && $this->canMockMethod($method)) { + $methods[] = MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments); + } + } + + return $methods; + } + + /** + * @throws ReflectionException + * + * @return MockMethod[] + */ + public function mockInterfaceMethods(string $interfaceName, bool $cloneArguments): array + { + try { + $class = new ReflectionClass($interfaceName); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + $methods = []; + + foreach ($class->getMethods() as $method) { + $methods[] = MockMethod::fromReflection($method, false, $cloneArguments); + } + + return $methods; + } + + /** + * @psalm-param class-string $interfaceName + * + * @throws ReflectionException + * + * @return ReflectionMethod[] + */ + private function userDefinedInterfaceMethods(string $interfaceName): array + { + try { + // @codeCoverageIgnoreStart + $interface = new ReflectionClass($interfaceName); + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + $methods = []; + + foreach ($interface->getMethods() as $method) { + if (!$method->isUserDefined()) { + continue; + } + + $methods[] = $method; + } + + return $methods; + } + + /** + * @throws ReflectionException + * @throws RuntimeException + */ + private function getObject(MockType $mockClass, $type = '', bool $callOriginalConstructor = false, bool $callAutoload = false, array $arguments = [], bool $callOriginalMethods = false, object $proxyTarget = null, bool $returnValueGeneration = true) + { + $className = $mockClass->generate(); + + if ($callOriginalConstructor) { + if (count($arguments) === 0) { + $object = new $className; + } else { + try { + $class = new ReflectionClass($className); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + $object = $class->newInstanceArgs($arguments); + } + } else { + try { + $object = (new Instantiator)->instantiate($className); + } catch (InstantiatorException $e) { + throw new RuntimeException($e->getMessage()); + } + } + + if ($callOriginalMethods) { + if (!is_object($proxyTarget)) { + if (count($arguments) === 0) { + $proxyTarget = new $type; + } else { + try { + $class = new ReflectionClass($type); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + $proxyTarget = $class->newInstanceArgs($arguments); + } + } + + $object->__phpunit_setOriginalObject($proxyTarget); + } + + if ($object instanceof MockObject) { + $object->__phpunit_setReturnValueGeneration($returnValueGeneration); + } + + return $object; + } + + /** + * @throws ClassIsFinalException + * @throws ClassIsReadonlyException + * @throws ReflectionException + * @throws RuntimeException + */ + private function generateMock(string $type, ?array $explicitMethods, string $mockClassName, bool $callOriginalClone, bool $callAutoload, bool $cloneArguments, bool $callOriginalMethods): MockClass + { + $classTemplate = $this->getTemplate('mocked_class.tpl'); + $additionalInterfaces = []; + $mockedCloneMethod = false; + $unmockedCloneMethod = false; + $isClass = false; + $isInterface = false; + $class = null; + $mockMethods = new MockMethodSet; + + $_mockClassName = $this->generateClassName( + $type, + $mockClassName, + 'Mock_' + ); + + if (class_exists($_mockClassName['fullClassName'], $callAutoload)) { + $isClass = true; + } elseif (interface_exists($_mockClassName['fullClassName'], $callAutoload)) { + $isInterface = true; + } + + if (!$isClass && !$isInterface) { + $prologue = 'class ' . $_mockClassName['originalClassName'] . "\n{\n}\n\n"; + + if (!empty($_mockClassName['namespaceName'])) { + $prologue = 'namespace ' . $_mockClassName['namespaceName'] . + " {\n\n" . $prologue . "}\n\n" . + "namespace {\n\n"; + + $epilogue = "\n\n}"; + } + + $mockedCloneMethod = true; + } else { + try { + $class = new ReflectionClass($_mockClassName['fullClassName']); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + if ($class->isFinal()) { + throw new ClassIsFinalException($_mockClassName['fullClassName']); + } + + if (method_exists($class, 'isReadOnly') && $class->isReadOnly()) { + throw new ClassIsReadonlyException($_mockClassName['fullClassName']); + } + + // @see https://github.com/sebastianbergmann/phpunit/issues/2995 + if ($isInterface && $class->implementsInterface(Throwable::class)) { + $actualClassName = Exception::class; + $additionalInterfaces[] = $class->getName(); + $isInterface = false; + + try { + $class = new ReflectionClass($actualClassName); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + foreach ($this->userDefinedInterfaceMethods($_mockClassName['fullClassName']) as $method) { + $methodName = $method->getName(); + + if ($class->hasMethod($methodName)) { + try { + $classMethod = $class->getMethod($methodName); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + if (!$this->canMockMethod($classMethod)) { + continue; + } + } + + $mockMethods->addMethods( + MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments) + ); + } + + $_mockClassName = $this->generateClassName( + $actualClassName, + $_mockClassName['className'], + 'Mock_' + ); + } + + // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/103 + if ($isInterface && $class->implementsInterface(Traversable::class) && + !$class->implementsInterface(Iterator::class) && + !$class->implementsInterface(IteratorAggregate::class)) { + $additionalInterfaces[] = Iterator::class; + + $mockMethods->addMethods( + ...$this->mockClassMethods(Iterator::class, $callOriginalMethods, $cloneArguments) + ); + } + + if ($class->hasMethod('__clone')) { + try { + $cloneMethod = $class->getMethod('__clone'); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + if (!$cloneMethod->isFinal()) { + if ($callOriginalClone && !$isInterface) { + $unmockedCloneMethod = true; + } else { + $mockedCloneMethod = true; + } + } + } else { + $mockedCloneMethod = true; + } + } + + if ($isClass && $explicitMethods === []) { + $mockMethods->addMethods( + ...$this->mockClassMethods($_mockClassName['fullClassName'], $callOriginalMethods, $cloneArguments) + ); + } + + if ($isInterface && ($explicitMethods === [] || $explicitMethods === null)) { + $mockMethods->addMethods( + ...$this->mockInterfaceMethods($_mockClassName['fullClassName'], $cloneArguments) + ); + } + + if (is_array($explicitMethods)) { + foreach ($explicitMethods as $methodName) { + if ($class !== null && $class->hasMethod($methodName)) { + try { + $method = $class->getMethod($methodName); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + if ($this->canMockMethod($method)) { + $mockMethods->addMethods( + MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments) + ); + } + } else { + $mockMethods->addMethods( + MockMethod::fromName( + $_mockClassName['fullClassName'], + $methodName, + $cloneArguments + ) + ); + } + } + } + + $mockedMethods = ''; + $configurable = []; + + foreach ($mockMethods->asArray() as $mockMethod) { + $mockedMethods .= $mockMethod->generateCode(); + $configurable[] = new ConfigurableMethod($mockMethod->getName(), $mockMethod->getReturnType()); + } + + $method = ''; + + if (!$mockMethods->hasMethod('method') && (!isset($class) || !$class->hasMethod('method'))) { + $method = PHP_EOL . ' use \PHPUnit\Framework\MockObject\Method;'; + } + + $cloneTrait = ''; + + if ($mockedCloneMethod) { + $cloneTrait = $this->mockedCloneMethod(); + } + + if ($unmockedCloneMethod) { + $cloneTrait = $this->unmockedCloneMethod(); + } + + $classTemplate->setVar( + [ + 'prologue' => $prologue ?? '', + 'epilogue' => $epilogue ?? '', + 'class_declaration' => $this->generateMockClassDeclaration( + $_mockClassName, + $isInterface, + $additionalInterfaces + ), + 'clone' => $cloneTrait, + 'mock_class_name' => $_mockClassName['className'], + 'mocked_methods' => $mockedMethods, + 'method' => $method, + ] + ); + + return new MockClass( + $classTemplate->render(), + $_mockClassName['className'], + $configurable + ); + } + + private function generateClassName(string $type, string $className, string $prefix): array + { + if ($type[0] === '\\') { + $type = substr($type, 1); + } + + $classNameParts = explode('\\', $type); + + if (count($classNameParts) > 1) { + $type = array_pop($classNameParts); + $namespaceName = implode('\\', $classNameParts); + $fullClassName = $namespaceName . '\\' . $type; + } else { + $namespaceName = ''; + $fullClassName = $type; + } + + if ($className === '') { + do { + $className = $prefix . $type . '_' . + substr(md5((string) mt_rand()), 0, 8); + } while (class_exists($className, false)); + } + + return [ + 'className' => $className, + 'originalClassName' => $type, + 'fullClassName' => $fullClassName, + 'namespaceName' => $namespaceName, + ]; + } + + private function generateMockClassDeclaration(array $mockClassName, bool $isInterface, array $additionalInterfaces = []): string + { + $buffer = 'class '; + + $additionalInterfaces[] = MockObject::class; + $interfaces = implode(', ', $additionalInterfaces); + + if ($isInterface) { + $buffer .= sprintf( + '%s implements %s', + $mockClassName['className'], + $interfaces + ); + + if (!in_array($mockClassName['originalClassName'], $additionalInterfaces, true)) { + $buffer .= ', '; + + if (!empty($mockClassName['namespaceName'])) { + $buffer .= $mockClassName['namespaceName'] . '\\'; + } + + $buffer .= $mockClassName['originalClassName']; + } + } else { + $buffer .= sprintf( + '%s extends %s%s implements %s', + $mockClassName['className'], + !empty($mockClassName['namespaceName']) ? $mockClassName['namespaceName'] . '\\' : '', + $mockClassName['originalClassName'], + $interfaces + ); + } + + return $buffer; + } + + private function canMockMethod(ReflectionMethod $method): bool + { + return !($this->isConstructor($method) || $method->isFinal() || $method->isPrivate() || $this->isMethodNameExcluded($method->getName())); + } + + private function isMethodNameExcluded(string $name): bool + { + return isset(self::EXCLUDED_METHOD_NAMES[$name]); + } + + /** + * @throws RuntimeException + */ + private function getTemplate(string $template): Template + { + $filename = __DIR__ . DIRECTORY_SEPARATOR . 'Generator' . DIRECTORY_SEPARATOR . $template; + + if (!isset(self::$templates[$filename])) { + try { + self::$templates[$filename] = new Template($filename); + } catch (TemplateException $e) { + throw new RuntimeException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + } + + return self::$templates[$filename]; + } + + /** + * @see https://github.com/sebastianbergmann/phpunit/issues/4139#issuecomment-605409765 + */ + private function isConstructor(ReflectionMethod $method): bool + { + $methodName = strtolower($method->getName()); + + if ($methodName === '__construct') { + return true; + } + + if (PHP_MAJOR_VERSION >= 8) { + return false; + } + + $className = strtolower($method->getDeclaringClass()->getName()); + + return $methodName === $className; + } + + private function mockedCloneMethod(): string + { + if (PHP_MAJOR_VERSION >= 8) { + if (!trait_exists('\PHPUnit\Framework\MockObject\MockedCloneMethodWithVoidReturnType')) { + eval(self::MOCKED_CLONE_METHOD_WITH_VOID_RETURN_TYPE_TRAIT); + } + + return PHP_EOL . ' use \PHPUnit\Framework\MockObject\MockedCloneMethodWithVoidReturnType;'; + } + + if (!trait_exists('\PHPUnit\Framework\MockObject\MockedCloneMethodWithoutReturnType')) { + eval(self::MOCKED_CLONE_METHOD_WITHOUT_RETURN_TYPE_TRAIT); + } + + return PHP_EOL . ' use \PHPUnit\Framework\MockObject\MockedCloneMethodWithoutReturnType;'; + } + + private function unmockedCloneMethod(): string + { + if (PHP_MAJOR_VERSION >= 8) { + if (!trait_exists('\PHPUnit\Framework\MockObject\UnmockedCloneMethodWithVoidReturnType')) { + eval(self::UNMOCKED_CLONE_METHOD_WITH_VOID_RETURN_TYPE_TRAIT); + } + + return PHP_EOL . ' use \PHPUnit\Framework\MockObject\UnmockedCloneMethodWithVoidReturnType;'; + } + + if (!trait_exists('\PHPUnit\Framework\MockObject\UnmockedCloneMethodWithoutReturnType')) { + eval(self::UNMOCKED_CLONE_METHOD_WITHOUT_RETURN_TYPE_TRAIT); + } + + return PHP_EOL . ' use \PHPUnit\Framework\MockObject\UnmockedCloneMethodWithoutReturnType;'; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/deprecation.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/deprecation.tpl new file mode 100644 index 00000000..5bf06f52 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/deprecation.tpl @@ -0,0 +1,2 @@ + + @trigger_error({deprecation}, E_USER_DEPRECATED); diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/intersection.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/intersection.tpl new file mode 100644 index 00000000..75cd27a6 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/intersection.tpl @@ -0,0 +1,5 @@ +declare(strict_types=1); + +interface {intersection} extends {interfaces} +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_class.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_class.tpl new file mode 100644 index 00000000..593119fb --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_class.tpl @@ -0,0 +1,6 @@ +declare(strict_types=1); + +{prologue}{class_declaration} +{ + use \PHPUnit\Framework\MockObject\Api;{method}{clone} +{mocked_methods}}{epilogue} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_method.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_method.tpl new file mode 100644 index 00000000..114ff8d0 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_method.tpl @@ -0,0 +1,22 @@ + + {modifier} function {reference}{method_name}({arguments_decl}){return_declaration} + {{deprecation} + $__phpunit_arguments = [{arguments_call}]; + $__phpunit_count = func_num_args(); + + if ($__phpunit_count > {arguments_count}) { + $__phpunit_arguments_tmp = func_get_args(); + + for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) { + $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i]; + } + } + + $__phpunit_result = $this->__phpunit_getInvocationHandler()->invoke( + new \PHPUnit\Framework\MockObject\Invocation( + '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments} + ) + ); + + return $__phpunit_result; + } diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_method_never_or_void.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_method_never_or_void.tpl new file mode 100644 index 00000000..39020220 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_method_never_or_void.tpl @@ -0,0 +1,20 @@ + + {modifier} function {reference}{method_name}({arguments_decl}){return_declaration} + {{deprecation} + $__phpunit_arguments = [{arguments_call}]; + $__phpunit_count = func_num_args(); + + if ($__phpunit_count > {arguments_count}) { + $__phpunit_arguments_tmp = func_get_args(); + + for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) { + $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i]; + } + } + + $this->__phpunit_getInvocationHandler()->invoke( + new \PHPUnit\Framework\MockObject\Invocation( + '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments} + ) + ); + } diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_static_method.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_static_method.tpl new file mode 100644 index 00000000..5e5cf23c --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/mocked_static_method.tpl @@ -0,0 +1,5 @@ + + {modifier} function {reference}{method_name}({arguments_decl}){return_declaration} + { + throw new \PHPUnit\Framework\MockObject\BadMethodCallException('Static method "{method_name}" cannot be invoked on mock object'); + } diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/proxied_method.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/proxied_method.tpl new file mode 100644 index 00000000..91bef463 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/proxied_method.tpl @@ -0,0 +1,22 @@ + + {modifier} function {reference}{method_name}({arguments_decl}){return_declaration} + { + $__phpunit_arguments = [{arguments_call}]; + $__phpunit_count = func_num_args(); + + if ($__phpunit_count > {arguments_count}) { + $__phpunit_arguments_tmp = func_get_args(); + + for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) { + $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i]; + } + } + + $this->__phpunit_getInvocationHandler()->invoke( + new \PHPUnit\Framework\MockObject\Invocation( + '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}, true + ) + ); + + return call_user_func_array(array($this->__phpunit_originalObject, "{method_name}"), $__phpunit_arguments); + } diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/proxied_method_never_or_void.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/proxied_method_never_or_void.tpl new file mode 100644 index 00000000..cce19882 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/proxied_method_never_or_void.tpl @@ -0,0 +1,22 @@ + + {modifier} function {reference}{method_name}({arguments_decl}){return_declaration} + { + $__phpunit_arguments = [{arguments_call}]; + $__phpunit_count = func_num_args(); + + if ($__phpunit_count > {arguments_count}) { + $__phpunit_arguments_tmp = func_get_args(); + + for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) { + $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i]; + } + } + + $this->__phpunit_getInvocationHandler()->invoke( + new \PHPUnit\Framework\MockObject\Invocation( + '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}, true + ) + ); + + call_user_func_array(array($this->__phpunit_originalObject, "{method_name}"), $__phpunit_arguments); + } diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/trait_class.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/trait_class.tpl new file mode 100644 index 00000000..a8fe470f --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/trait_class.tpl @@ -0,0 +1,6 @@ +declare(strict_types=1); + +{prologue}class {class_name} +{ + use {trait_name}; +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/wsdl_class.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/wsdl_class.tpl new file mode 100644 index 00000000..b3100b41 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/wsdl_class.tpl @@ -0,0 +1,9 @@ +declare(strict_types=1); + +{namespace}class {class_name} extends \SoapClient +{ + public function __construct($wsdl, array $options) + { + parent::__construct('{wsdl}', $options); + } +{methods}} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/wsdl_method.tpl b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/wsdl_method.tpl new file mode 100644 index 00000000..bb16e763 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/wsdl_method.tpl @@ -0,0 +1,4 @@ + + public function {method_name}({arguments}) + { + } diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Invocation.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Invocation.php new file mode 100644 index 00000000..418d6a07 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Invocation.php @@ -0,0 +1,301 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function array_map; +use function explode; +use function get_class; +use function implode; +use function in_array; +use function interface_exists; +use function is_object; +use function sprintf; +use function strpos; +use function strtolower; +use function substr; +use Doctrine\Instantiator\Instantiator; +use PHPUnit\Framework\SelfDescribing; +use PHPUnit\Util\Cloner; +use SebastianBergmann\Exporter\Exporter; +use stdClass; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Invocation implements SelfDescribing +{ + /** + * @var string + */ + private $className; + + /** + * @var string + */ + private $methodName; + + /** + * @var array + */ + private $parameters; + + /** + * @var string + */ + private $returnType; + + /** + * @var bool + */ + private $isReturnTypeNullable = false; + + /** + * @var bool + */ + private $proxiedCall; + + /** + * @var object + */ + private $object; + + public function __construct(string $className, string $methodName, array $parameters, string $returnType, object $object, bool $cloneObjects = false, bool $proxiedCall = false) + { + $this->className = $className; + $this->methodName = $methodName; + $this->parameters = $parameters; + $this->object = $object; + $this->proxiedCall = $proxiedCall; + + if (strtolower($methodName) === '__tostring') { + $returnType = 'string'; + } + + if (strpos($returnType, '?') === 0) { + $returnType = substr($returnType, 1); + $this->isReturnTypeNullable = true; + } + + $this->returnType = $returnType; + + if (!$cloneObjects) { + return; + } + + foreach ($this->parameters as $key => $value) { + if (is_object($value)) { + $this->parameters[$key] = Cloner::clone($value); + } + } + } + + public function getClassName(): string + { + return $this->className; + } + + public function getMethodName(): string + { + return $this->methodName; + } + + public function getParameters(): array + { + return $this->parameters; + } + + /** + * @throws RuntimeException + * + * @return mixed Mocked return value + */ + public function generateReturnValue() + { + if ($this->isReturnTypeNullable || $this->proxiedCall) { + return null; + } + + $intersection = false; + $union = false; + $unionContainsIntersections = false; + + if (strpos($this->returnType, '|') !== false) { + $types = explode('|', $this->returnType); + $union = true; + + if (strpos($this->returnType, '(') !== false) { + $unionContainsIntersections = true; + } + } elseif (strpos($this->returnType, '&') !== false) { + $types = explode('&', $this->returnType); + $intersection = true; + } else { + $types = [$this->returnType]; + } + + $types = array_map('strtolower', $types); + + if (!$intersection && !$unionContainsIntersections) { + if (in_array('', $types, true) || + in_array('null', $types, true) || + in_array('mixed', $types, true) || + in_array('void', $types, true)) { + return null; + } + + if (in_array('true', $types, true)) { + return true; + } + + if (in_array('false', $types, true) || + in_array('bool', $types, true)) { + return false; + } + + if (in_array('float', $types, true)) { + return 0.0; + } + + if (in_array('int', $types, true)) { + return 0; + } + + if (in_array('string', $types, true)) { + return ''; + } + + if (in_array('array', $types, true)) { + return []; + } + + if (in_array('static', $types, true)) { + try { + return (new Instantiator)->instantiate(get_class($this->object)); + } catch (Throwable $t) { + throw new RuntimeException( + $t->getMessage(), + (int) $t->getCode(), + $t + ); + } + } + + if (in_array('object', $types, true)) { + return new stdClass; + } + + if (in_array('callable', $types, true) || + in_array('closure', $types, true)) { + return static function (): void + { + }; + } + + if (in_array('traversable', $types, true) || + in_array('generator', $types, true) || + in_array('iterable', $types, true)) { + $generator = static function (): \Generator + { + yield from []; + }; + + return $generator(); + } + + if (!$union) { + try { + return (new Generator)->getMock($this->returnType, [], [], '', false); + } catch (Throwable $t) { + if ($t instanceof Exception) { + throw $t; + } + + throw new RuntimeException( + $t->getMessage(), + (int) $t->getCode(), + $t + ); + } + } + } + + if ($intersection && $this->onlyInterfaces($types)) { + try { + return (new Generator)->getMockForInterfaces($types); + } catch (Throwable $t) { + throw new RuntimeException( + sprintf( + 'Return value for %s::%s() cannot be generated: %s', + $this->className, + $this->methodName, + $t->getMessage(), + ), + (int) $t->getCode(), + ); + } + } + + $reason = ''; + + if ($union) { + $reason = ' because the declared return type is a union'; + } elseif ($intersection) { + $reason = ' because the declared return type is an intersection'; + } + + throw new RuntimeException( + sprintf( + 'Return value for %s::%s() cannot be generated%s, please configure a return value for this method', + $this->className, + $this->methodName, + $reason + ) + ); + } + + public function toString(): string + { + $exporter = new Exporter; + + return sprintf( + '%s::%s(%s)%s', + $this->className, + $this->methodName, + implode( + ', ', + array_map( + [$exporter, 'shortenedExport'], + $this->parameters + ) + ), + $this->returnType ? sprintf(': %s', $this->returnType) : '' + ); + } + + public function getObject(): object + { + return $this->object; + } + + /** + * @psalm-param non-empty-list $types + */ + private function onlyInterfaces(array $types): bool + { + foreach ($types as $type) { + if (!interface_exists($type)) { + return false; + } + } + + return true; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/InvocationHandler.php b/vendor/phpunit/phpunit/src/Framework/MockObject/InvocationHandler.php new file mode 100644 index 00000000..b9d62610 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/InvocationHandler.php @@ -0,0 +1,186 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function strtolower; +use Exception; +use PHPUnit\Framework\MockObject\Builder\InvocationMocker; +use PHPUnit\Framework\MockObject\Rule\InvocationOrder; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvocationHandler +{ + /** + * @var Matcher[] + */ + private $matchers = []; + + /** + * @var Matcher[] + */ + private $matcherMap = []; + + /** + * @var ConfigurableMethod[] + */ + private $configurableMethods; + + /** + * @var bool + */ + private $returnValueGeneration; + + /** + * @var Throwable + */ + private $deferredError; + + public function __construct(array $configurableMethods, bool $returnValueGeneration) + { + $this->configurableMethods = $configurableMethods; + $this->returnValueGeneration = $returnValueGeneration; + } + + public function hasMatchers(): bool + { + foreach ($this->matchers as $matcher) { + if ($matcher->hasMatchers()) { + return true; + } + } + + return false; + } + + /** + * Looks up the match builder with identification $id and returns it. + * + * @param string $id The identification of the match builder + */ + public function lookupMatcher(string $id): ?Matcher + { + if (isset($this->matcherMap[$id])) { + return $this->matcherMap[$id]; + } + + return null; + } + + /** + * Registers a matcher with the identification $id. The matcher can later be + * looked up using lookupMatcher() to figure out if it has been invoked. + * + * @param string $id The identification of the matcher + * @param Matcher $matcher The builder which is being registered + * + * @throws MatcherAlreadyRegisteredException + */ + public function registerMatcher(string $id, Matcher $matcher): void + { + if (isset($this->matcherMap[$id])) { + throw new MatcherAlreadyRegisteredException($id); + } + + $this->matcherMap[$id] = $matcher; + } + + public function expects(InvocationOrder $rule): InvocationMocker + { + $matcher = new Matcher($rule); + $this->addMatcher($matcher); + + return new InvocationMocker( + $this, + $matcher, + ...$this->configurableMethods + ); + } + + /** + * @throws Exception + * @throws RuntimeException + */ + public function invoke(Invocation $invocation) + { + $exception = null; + $hasReturnValue = false; + $returnValue = null; + + foreach ($this->matchers as $match) { + try { + if ($match->matches($invocation)) { + $value = $match->invoked($invocation); + + if (!$hasReturnValue) { + $returnValue = $value; + $hasReturnValue = true; + } + } + } catch (Exception $e) { + $exception = $e; + } + } + + if ($exception !== null) { + throw $exception; + } + + if ($hasReturnValue) { + return $returnValue; + } + + if (!$this->returnValueGeneration) { + $exception = new ReturnValueNotConfiguredException($invocation); + + if (strtolower($invocation->getMethodName()) === '__tostring') { + $this->deferredError = $exception; + + return ''; + } + + throw $exception; + } + + return $invocation->generateReturnValue(); + } + + public function matches(Invocation $invocation): bool + { + foreach ($this->matchers as $matcher) { + if (!$matcher->matches($invocation)) { + return false; + } + } + + return true; + } + + /** + * @throws Throwable + */ + public function verify(): void + { + foreach ($this->matchers as $matcher) { + $matcher->verify(); + } + + if ($this->deferredError) { + throw $this->deferredError; + } + } + + private function addMatcher(Matcher $matcher): void + { + $this->matchers[] = $matcher; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Matcher.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Matcher.php new file mode 100644 index 00000000..7c81a0ea --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Matcher.php @@ -0,0 +1,274 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function assert; +use function implode; +use function sprintf; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount; +use PHPUnit\Framework\MockObject\Rule\AnyParameters; +use PHPUnit\Framework\MockObject\Rule\InvocationOrder; +use PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount; +use PHPUnit\Framework\MockObject\Rule\InvokedCount; +use PHPUnit\Framework\MockObject\Rule\MethodName; +use PHPUnit\Framework\MockObject\Rule\ParametersRule; +use PHPUnit\Framework\MockObject\Stub\Stub; +use PHPUnit\Framework\TestFailure; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Matcher +{ + /** + * @var InvocationOrder + */ + private $invocationRule; + + /** + * @var mixed + */ + private $afterMatchBuilderId; + + /** + * @var bool + */ + private $afterMatchBuilderIsInvoked = false; + + /** + * @var MethodName + */ + private $methodNameRule; + + /** + * @var ParametersRule + */ + private $parametersRule; + + /** + * @var Stub + */ + private $stub; + + public function __construct(InvocationOrder $rule) + { + $this->invocationRule = $rule; + } + + public function hasMatchers(): bool + { + return !$this->invocationRule instanceof AnyInvokedCount; + } + + public function hasMethodNameRule(): bool + { + return $this->methodNameRule !== null; + } + + public function getMethodNameRule(): MethodName + { + return $this->methodNameRule; + } + + public function setMethodNameRule(MethodName $rule): void + { + $this->methodNameRule = $rule; + } + + public function hasParametersRule(): bool + { + return $this->parametersRule !== null; + } + + public function setParametersRule(ParametersRule $rule): void + { + $this->parametersRule = $rule; + } + + public function setStub(Stub $stub): void + { + $this->stub = $stub; + } + + public function setAfterMatchBuilderId(string $id): void + { + $this->afterMatchBuilderId = $id; + } + + /** + * @throws ExpectationFailedException + * @throws MatchBuilderNotFoundException + * @throws MethodNameNotConfiguredException + * @throws RuntimeException + */ + public function invoked(Invocation $invocation) + { + if ($this->methodNameRule === null) { + throw new MethodNameNotConfiguredException; + } + + if ($this->afterMatchBuilderId !== null) { + $matcher = $invocation->getObject() + ->__phpunit_getInvocationHandler() + ->lookupMatcher($this->afterMatchBuilderId); + + if (!$matcher) { + throw new MatchBuilderNotFoundException($this->afterMatchBuilderId); + } + + assert($matcher instanceof self); + + if ($matcher->invocationRule->hasBeenInvoked()) { + $this->afterMatchBuilderIsInvoked = true; + } + } + + $this->invocationRule->invoked($invocation); + + try { + if ($this->parametersRule !== null) { + $this->parametersRule->apply($invocation); + } + } catch (ExpectationFailedException $e) { + throw new ExpectationFailedException( + sprintf( + "Expectation failed for %s when %s\n%s", + $this->methodNameRule->toString(), + $this->invocationRule->toString(), + $e->getMessage() + ), + $e->getComparisonFailure() + ); + } + + if ($this->stub) { + return $this->stub->invoke($invocation); + } + + return $invocation->generateReturnValue(); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * @throws MatchBuilderNotFoundException + * @throws MethodNameNotConfiguredException + * @throws RuntimeException + */ + public function matches(Invocation $invocation): bool + { + if ($this->afterMatchBuilderId !== null) { + $matcher = $invocation->getObject() + ->__phpunit_getInvocationHandler() + ->lookupMatcher($this->afterMatchBuilderId); + + if (!$matcher) { + throw new MatchBuilderNotFoundException($this->afterMatchBuilderId); + } + + assert($matcher instanceof self); + + if (!$matcher->invocationRule->hasBeenInvoked()) { + return false; + } + } + + if ($this->methodNameRule === null) { + throw new MethodNameNotConfiguredException; + } + + if (!$this->invocationRule->matches($invocation)) { + return false; + } + + try { + if (!$this->methodNameRule->matches($invocation)) { + return false; + } + } catch (ExpectationFailedException $e) { + throw new ExpectationFailedException( + sprintf( + "Expectation failed for %s when %s\n%s", + $this->methodNameRule->toString(), + $this->invocationRule->toString(), + $e->getMessage() + ), + $e->getComparisonFailure() + ); + } + + return true; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + * @throws MethodNameNotConfiguredException + */ + public function verify(): void + { + if ($this->methodNameRule === null) { + throw new MethodNameNotConfiguredException; + } + + try { + $this->invocationRule->verify(); + + if ($this->parametersRule === null) { + $this->parametersRule = new AnyParameters; + } + + $invocationIsAny = $this->invocationRule instanceof AnyInvokedCount; + $invocationIsNever = $this->invocationRule instanceof InvokedCount && $this->invocationRule->isNever(); + $invocationIsAtMost = $this->invocationRule instanceof InvokedAtMostCount; + + if (!$invocationIsAny && !$invocationIsNever && !$invocationIsAtMost) { + $this->parametersRule->verify(); + } + } catch (ExpectationFailedException $e) { + throw new ExpectationFailedException( + sprintf( + "Expectation failed for %s when %s.\n%s", + $this->methodNameRule->toString(), + $this->invocationRule->toString(), + TestFailure::exceptionToString($e) + ) + ); + } + } + + public function toString(): string + { + $list = []; + + if ($this->invocationRule !== null) { + $list[] = $this->invocationRule->toString(); + } + + if ($this->methodNameRule !== null) { + $list[] = 'where ' . $this->methodNameRule->toString(); + } + + if ($this->parametersRule !== null) { + $list[] = 'and ' . $this->parametersRule->toString(); + } + + if ($this->afterMatchBuilderId !== null) { + $list[] = 'after ' . $this->afterMatchBuilderId; + } + + if ($this->stub !== null) { + $list[] = 'will ' . $this->stub->toString(); + } + + return implode(' ', $list); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MethodNameConstraint.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MethodNameConstraint.php new file mode 100644 index 00000000..3082ab38 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MethodNameConstraint.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function is_string; +use function sprintf; +use function strtolower; +use PHPUnit\Framework\Constraint\Constraint; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MethodNameConstraint extends Constraint +{ + /** + * @var string + */ + private $methodName; + + public function __construct(string $methodName) + { + $this->methodName = $methodName; + } + + public function toString(): string + { + return sprintf( + 'is "%s"', + $this->methodName + ); + } + + protected function matches($other): bool + { + if (!is_string($other)) { + return false; + } + + return strtolower($this->methodName) === strtolower($other); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php new file mode 100644 index 00000000..4007a9f1 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php @@ -0,0 +1,517 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function array_diff; +use function array_merge; +use PHPUnit\Framework\TestCase; +use ReflectionClass; + +/** + * @psalm-template MockedType + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class MockBuilder +{ + /** + * @var TestCase + */ + private $testCase; + + /** + * @var string + */ + private $type; + + /** + * @var null|string[] + */ + private $methods = []; + + /** + * @var bool + */ + private $emptyMethodsArray = false; + + /** + * @var string + */ + private $mockClassName = ''; + + /** + * @var array + */ + private $constructorArgs = []; + + /** + * @var bool + */ + private $originalConstructor = true; + + /** + * @var bool + */ + private $originalClone = true; + + /** + * @var bool + */ + private $autoload = true; + + /** + * @var bool + */ + private $cloneArguments = false; + + /** + * @var bool + */ + private $callOriginalMethods = false; + + /** + * @var ?object + */ + private $proxyTarget; + + /** + * @var bool + */ + private $allowMockingUnknownTypes = true; + + /** + * @var bool + */ + private $returnValueGeneration = true; + + /** + * @var Generator + */ + private $generator; + + /** + * @param string|string[] $type + * + * @psalm-param class-string|string|string[] $type + */ + public function __construct(TestCase $testCase, $type) + { + $this->testCase = $testCase; + $this->type = $type; + $this->generator = new Generator; + } + + /** + * Creates a mock object using a fluent interface. + * + * @throws \PHPUnit\Framework\InvalidArgumentException + * @throws ClassAlreadyExistsException + * @throws ClassIsFinalException + * @throws ClassIsReadonlyException + * @throws DuplicateMethodException + * @throws InvalidMethodNameException + * @throws OriginalConstructorInvocationRequiredException + * @throws ReflectionException + * @throws RuntimeException + * @throws UnknownTypeException + * + * @psalm-return MockObject&MockedType + */ + public function getMock(): MockObject + { + $object = $this->generator->getMock( + $this->type, + !$this->emptyMethodsArray ? $this->methods : null, + $this->constructorArgs, + $this->mockClassName, + $this->originalConstructor, + $this->originalClone, + $this->autoload, + $this->cloneArguments, + $this->callOriginalMethods, + $this->proxyTarget, + $this->allowMockingUnknownTypes, + $this->returnValueGeneration + ); + + $this->testCase->registerMockObject($object); + + return $object; + } + + /** + * Creates a mock object for an abstract class using a fluent interface. + * + * @psalm-return MockObject&MockedType + * + * @throws \PHPUnit\Framework\Exception + * @throws ReflectionException + * @throws RuntimeException + */ + public function getMockForAbstractClass(): MockObject + { + $object = $this->generator->getMockForAbstractClass( + $this->type, + $this->constructorArgs, + $this->mockClassName, + $this->originalConstructor, + $this->originalClone, + $this->autoload, + $this->methods, + $this->cloneArguments + ); + + $this->testCase->registerMockObject($object); + + return $object; + } + + /** + * Creates a mock object for a trait using a fluent interface. + * + * @psalm-return MockObject&MockedType + * + * @throws \PHPUnit\Framework\Exception + * @throws ReflectionException + * @throws RuntimeException + */ + public function getMockForTrait(): MockObject + { + $object = $this->generator->getMockForTrait( + $this->type, + $this->constructorArgs, + $this->mockClassName, + $this->originalConstructor, + $this->originalClone, + $this->autoload, + $this->methods, + $this->cloneArguments + ); + + $this->testCase->registerMockObject($object); + + return $object; + } + + /** + * Specifies the subset of methods to mock. Default is to mock none of them. + * + * @deprecated https://github.com/sebastianbergmann/phpunit/pull/3687 + * + * @return $this + */ + public function setMethods(?array $methods = null): self + { + if ($methods === null) { + $this->methods = $methods; + } else { + $this->methods = array_merge($this->methods ?? [], $methods); + } + + return $this; + } + + /** + * Specifies the subset of methods to mock, requiring each to exist in the class. + * + * @param string[] $methods + * + * @throws CannotUseOnlyMethodsException + * @throws ReflectionException + * + * @return $this + */ + public function onlyMethods(array $methods): self + { + if (empty($methods)) { + $this->emptyMethodsArray = true; + + return $this; + } + + try { + $reflector = new ReflectionClass($this->type); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + foreach ($methods as $method) { + if (!$reflector->hasMethod($method)) { + throw new CannotUseOnlyMethodsException($this->type, $method); + } + } + + $this->methods = array_merge($this->methods ?? [], $methods); + + return $this; + } + + /** + * Specifies methods that don't exist in the class which you want to mock. + * + * @param string[] $methods + * + * @throws CannotUseAddMethodsException + * @throws ReflectionException + * @throws RuntimeException + * + * @return $this + */ + public function addMethods(array $methods): self + { + if (empty($methods)) { + $this->emptyMethodsArray = true; + + return $this; + } + + try { + $reflector = new ReflectionClass($this->type); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + foreach ($methods as $method) { + if ($reflector->hasMethod($method)) { + throw new CannotUseAddMethodsException($this->type, $method); + } + } + + $this->methods = array_merge($this->methods ?? [], $methods); + + return $this; + } + + /** + * Specifies the subset of methods to not mock. Default is to mock all of them. + * + * @deprecated https://github.com/sebastianbergmann/phpunit/pull/3687 + * + * @throws ReflectionException + */ + public function setMethodsExcept(array $methods = []): self + { + return $this->setMethods( + array_diff( + $this->generator->getClassMethods($this->type), + $methods + ) + ); + } + + /** + * Specifies the arguments for the constructor. + * + * @return $this + */ + public function setConstructorArgs(array $args): self + { + $this->constructorArgs = $args; + + return $this; + } + + /** + * Specifies the name for the mock class. + * + * @return $this + */ + public function setMockClassName(string $name): self + { + $this->mockClassName = $name; + + return $this; + } + + /** + * Disables the invocation of the original constructor. + * + * @return $this + */ + public function disableOriginalConstructor(): self + { + $this->originalConstructor = false; + + return $this; + } + + /** + * Enables the invocation of the original constructor. + * + * @return $this + */ + public function enableOriginalConstructor(): self + { + $this->originalConstructor = true; + + return $this; + } + + /** + * Disables the invocation of the original clone constructor. + * + * @return $this + */ + public function disableOriginalClone(): self + { + $this->originalClone = false; + + return $this; + } + + /** + * Enables the invocation of the original clone constructor. + * + * @return $this + */ + public function enableOriginalClone(): self + { + $this->originalClone = true; + + return $this; + } + + /** + * Disables the use of class autoloading while creating the mock object. + * + * @return $this + */ + public function disableAutoload(): self + { + $this->autoload = false; + + return $this; + } + + /** + * Enables the use of class autoloading while creating the mock object. + * + * @return $this + */ + public function enableAutoload(): self + { + $this->autoload = true; + + return $this; + } + + /** + * Disables the cloning of arguments passed to mocked methods. + * + * @return $this + */ + public function disableArgumentCloning(): self + { + $this->cloneArguments = false; + + return $this; + } + + /** + * Enables the cloning of arguments passed to mocked methods. + * + * @return $this + */ + public function enableArgumentCloning(): self + { + $this->cloneArguments = true; + + return $this; + } + + /** + * Enables the invocation of the original methods. + * + * @return $this + */ + public function enableProxyingToOriginalMethods(): self + { + $this->callOriginalMethods = true; + + return $this; + } + + /** + * Disables the invocation of the original methods. + * + * @return $this + */ + public function disableProxyingToOriginalMethods(): self + { + $this->callOriginalMethods = false; + $this->proxyTarget = null; + + return $this; + } + + /** + * Sets the proxy target. + * + * @return $this + */ + public function setProxyTarget(object $object): self + { + $this->proxyTarget = $object; + + return $this; + } + + /** + * @return $this + */ + public function allowMockingUnknownTypes(): self + { + $this->allowMockingUnknownTypes = true; + + return $this; + } + + /** + * @return $this + */ + public function disallowMockingUnknownTypes(): self + { + $this->allowMockingUnknownTypes = false; + + return $this; + } + + /** + * @return $this + */ + public function enableAutoReturnValueGeneration(): self + { + $this->returnValueGeneration = true; + + return $this; + } + + /** + * @return $this + */ + public function disableAutoReturnValueGeneration(): self + { + $this->returnValueGeneration = false; + + return $this; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MockClass.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MockClass.php new file mode 100644 index 00000000..253d7846 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MockClass.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function call_user_func; +use function class_exists; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MockClass implements MockType +{ + /** + * @var string + */ + private $classCode; + + /** + * @var class-string + */ + private $mockName; + + /** + * @var ConfigurableMethod[] + */ + private $configurableMethods; + + /** + * @psalm-param class-string $mockName + */ + public function __construct(string $classCode, string $mockName, array $configurableMethods) + { + $this->classCode = $classCode; + $this->mockName = $mockName; + $this->configurableMethods = $configurableMethods; + } + + /** + * @psalm-return class-string + */ + public function generate(): string + { + if (!class_exists($this->mockName, false)) { + eval($this->classCode); + + call_user_func( + [ + $this->mockName, + '__phpunit_initConfigurableMethods', + ], + ...$this->configurableMethods + ); + } + + return $this->mockName; + } + + public function getClassCode(): string + { + return $this->classCode; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MockMethod.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MockMethod.php new file mode 100644 index 00000000..2cf149ad --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MockMethod.php @@ -0,0 +1,380 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use const DIRECTORY_SEPARATOR; +use function explode; +use function implode; +use function is_object; +use function is_string; +use function preg_match; +use function preg_replace; +use function sprintf; +use function strlen; +use function strpos; +use function substr; +use function substr_count; +use function trim; +use function var_export; +use ReflectionMethod; +use ReflectionParameter; +use SebastianBergmann\Template\Exception as TemplateException; +use SebastianBergmann\Template\Template; +use SebastianBergmann\Type\ReflectionMapper; +use SebastianBergmann\Type\Type; +use SebastianBergmann\Type\UnknownType; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MockMethod +{ + /** + * @var Template[] + */ + private static $templates = []; + + /** + * @var string + */ + private $className; + + /** + * @var string + */ + private $methodName; + + /** + * @var bool + */ + private $cloneArguments; + + /** + * @var string string + */ + private $modifier; + + /** + * @var string + */ + private $argumentsForDeclaration; + + /** + * @var string + */ + private $argumentsForCall; + + /** + * @var Type + */ + private $returnType; + + /** + * @var string + */ + private $reference; + + /** + * @var bool + */ + private $callOriginalMethod; + + /** + * @var bool + */ + private $static; + + /** + * @var ?string + */ + private $deprecation; + + /** + * @throws ReflectionException + * @throws RuntimeException + */ + public static function fromReflection(ReflectionMethod $method, bool $callOriginalMethod, bool $cloneArguments): self + { + if ($method->isPrivate()) { + $modifier = 'private'; + } elseif ($method->isProtected()) { + $modifier = 'protected'; + } else { + $modifier = 'public'; + } + + if ($method->isStatic()) { + $modifier .= ' static'; + } + + if ($method->returnsReference()) { + $reference = '&'; + } else { + $reference = ''; + } + + $docComment = $method->getDocComment(); + + if (is_string($docComment) && + preg_match('#\*[ \t]*+@deprecated[ \t]*+(.*?)\r?+\n[ \t]*+\*(?:[ \t]*+@|/$)#s', $docComment, $deprecation)) { + $deprecation = trim(preg_replace('#[ \t]*\r?\n[ \t]*+\*[ \t]*+#', ' ', $deprecation[1])); + } else { + $deprecation = null; + } + + return new self( + $method->getDeclaringClass()->getName(), + $method->getName(), + $cloneArguments, + $modifier, + self::getMethodParametersForDeclaration($method), + self::getMethodParametersForCall($method), + (new ReflectionMapper)->fromReturnType($method), + $reference, + $callOriginalMethod, + $method->isStatic(), + $deprecation + ); + } + + public static function fromName(string $fullClassName, string $methodName, bool $cloneArguments): self + { + return new self( + $fullClassName, + $methodName, + $cloneArguments, + 'public', + '', + '', + new UnknownType, + '', + false, + false, + null + ); + } + + public function __construct(string $className, string $methodName, bool $cloneArguments, string $modifier, string $argumentsForDeclaration, string $argumentsForCall, Type $returnType, string $reference, bool $callOriginalMethod, bool $static, ?string $deprecation) + { + $this->className = $className; + $this->methodName = $methodName; + $this->cloneArguments = $cloneArguments; + $this->modifier = $modifier; + $this->argumentsForDeclaration = $argumentsForDeclaration; + $this->argumentsForCall = $argumentsForCall; + $this->returnType = $returnType; + $this->reference = $reference; + $this->callOriginalMethod = $callOriginalMethod; + $this->static = $static; + $this->deprecation = $deprecation; + } + + public function getName(): string + { + return $this->methodName; + } + + /** + * @throws RuntimeException + */ + public function generateCode(): string + { + if ($this->static) { + $templateFile = 'mocked_static_method.tpl'; + } elseif ($this->returnType->isNever() || $this->returnType->isVoid()) { + $templateFile = sprintf( + '%s_method_never_or_void.tpl', + $this->callOriginalMethod ? 'proxied' : 'mocked' + ); + } else { + $templateFile = sprintf( + '%s_method.tpl', + $this->callOriginalMethod ? 'proxied' : 'mocked' + ); + } + + $deprecation = $this->deprecation; + + if (null !== $this->deprecation) { + $deprecation = "The {$this->className}::{$this->methodName} method is deprecated ({$this->deprecation})."; + $deprecationTemplate = $this->getTemplate('deprecation.tpl'); + + $deprecationTemplate->setVar( + [ + 'deprecation' => var_export($deprecation, true), + ] + ); + + $deprecation = $deprecationTemplate->render(); + } + + $template = $this->getTemplate($templateFile); + + $template->setVar( + [ + 'arguments_decl' => $this->argumentsForDeclaration, + 'arguments_call' => $this->argumentsForCall, + 'return_declaration' => !empty($this->returnType->asString()) ? (': ' . $this->returnType->asString()) : '', + 'return_type' => $this->returnType->asString(), + 'arguments_count' => !empty($this->argumentsForCall) ? substr_count($this->argumentsForCall, ',') + 1 : 0, + 'class_name' => $this->className, + 'method_name' => $this->methodName, + 'modifier' => $this->modifier, + 'reference' => $this->reference, + 'clone_arguments' => $this->cloneArguments ? 'true' : 'false', + 'deprecation' => $deprecation, + ] + ); + + return $template->render(); + } + + public function getReturnType(): Type + { + return $this->returnType; + } + + /** + * @throws RuntimeException + */ + private function getTemplate(string $template): Template + { + $filename = __DIR__ . DIRECTORY_SEPARATOR . 'Generator' . DIRECTORY_SEPARATOR . $template; + + if (!isset(self::$templates[$filename])) { + try { + self::$templates[$filename] = new Template($filename); + } catch (TemplateException $e) { + throw new RuntimeException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + } + + return self::$templates[$filename]; + } + + /** + * Returns the parameters of a function or method. + * + * @throws RuntimeException + */ + private static function getMethodParametersForDeclaration(ReflectionMethod $method): string + { + $parameters = []; + $types = (new ReflectionMapper)->fromParameterTypes($method); + + foreach ($method->getParameters() as $i => $parameter) { + $name = '$' . $parameter->getName(); + + /* Note: PHP extensions may use empty names for reference arguments + * or "..." for methods taking a variable number of arguments. + */ + if ($name === '$' || $name === '$...') { + $name = '$arg' . $i; + } + + $default = ''; + $reference = ''; + $typeDeclaration = ''; + + if (!$types[$i]->type()->isUnknown()) { + $typeDeclaration = $types[$i]->type()->asString() . ' '; + } + + if ($parameter->isPassedByReference()) { + $reference = '&'; + } + + if ($parameter->isVariadic()) { + $name = '...' . $name; + } elseif ($parameter->isDefaultValueAvailable()) { + $default = ' = ' . self::exportDefaultValue($parameter); + } elseif ($parameter->isOptional()) { + $default = ' = null'; + } + + $parameters[] = $typeDeclaration . $reference . $name . $default; + } + + return implode(', ', $parameters); + } + + /** + * Returns the parameters of a function or method. + * + * @throws ReflectionException + */ + private static function getMethodParametersForCall(ReflectionMethod $method): string + { + $parameters = []; + + foreach ($method->getParameters() as $i => $parameter) { + $name = '$' . $parameter->getName(); + + /* Note: PHP extensions may use empty names for reference arguments + * or "..." for methods taking a variable number of arguments. + */ + if ($name === '$' || $name === '$...') { + $name = '$arg' . $i; + } + + if ($parameter->isVariadic()) { + continue; + } + + if ($parameter->isPassedByReference()) { + $parameters[] = '&' . $name; + } else { + $parameters[] = $name; + } + } + + return implode(', ', $parameters); + } + + /** + * @throws ReflectionException + */ + private static function exportDefaultValue(ReflectionParameter $parameter): string + { + try { + $defaultValue = $parameter->getDefaultValue(); + + if (!is_object($defaultValue)) { + return (string) var_export($defaultValue, true); + } + + $parameterAsString = $parameter->__toString(); + + return (string) explode( + ' = ', + substr( + substr( + $parameterAsString, + strpos($parameterAsString, ' ') + strlen(' ') + ), + 0, + -2 + ) + )[1]; + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MockMethodSet.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MockMethodSet.php new file mode 100644 index 00000000..1c78963c --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MockMethodSet.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function array_key_exists; +use function array_values; +use function strtolower; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MockMethodSet +{ + /** + * @var MockMethod[] + */ + private $methods = []; + + public function addMethods(MockMethod ...$methods): void + { + foreach ($methods as $method) { + $this->methods[strtolower($method->getName())] = $method; + } + } + + /** + * @return MockMethod[] + */ + public function asArray(): array + { + return array_values($this->methods); + } + + public function hasMethod(string $methodName): bool + { + return array_key_exists(strtolower($methodName), $this->methods); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MockObject.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MockObject.php new file mode 100644 index 00000000..094decf4 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MockObject.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use PHPUnit\Framework\MockObject\Builder\InvocationMocker as BuilderInvocationMocker; +use PHPUnit\Framework\MockObject\Rule\InvocationOrder; + +/** + * @method BuilderInvocationMocker method($constraint) + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface MockObject extends Stub +{ + public function __phpunit_setOriginalObject($originalObject): void; + + public function __phpunit_verify(bool $unsetInvocationMocker = true): void; + + public function expects(InvocationOrder $invocationRule): BuilderInvocationMocker; +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MockTrait.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MockTrait.php new file mode 100644 index 00000000..7c326988 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MockTrait.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function class_exists; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MockTrait implements MockType +{ + /** + * @var string + */ + private $classCode; + + /** + * @var class-string + */ + private $mockName; + + /** + * @psalm-param class-string $mockName + */ + public function __construct(string $classCode, string $mockName) + { + $this->classCode = $classCode; + $this->mockName = $mockName; + } + + /** + * @psalm-return class-string + */ + public function generate(): string + { + if (!class_exists($this->mockName, false)) { + eval($this->classCode); + } + + return $this->mockName; + } + + public function getClassCode(): string + { + return $this->classCode; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/MockType.php b/vendor/phpunit/phpunit/src/Framework/MockObject/MockType.php new file mode 100644 index 00000000..6a03fb51 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/MockType.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface MockType +{ + /** + * @psalm-return class-string + */ + public function generate(): string; +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/AnyInvokedCount.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/AnyInvokedCount.php new file mode 100644 index 00000000..f93e5686 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/AnyInvokedCount.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class AnyInvokedCount extends InvocationOrder +{ + public function toString(): string + { + return 'invoked zero or more times'; + } + + public function verify(): void + { + } + + public function matches(BaseInvocation $invocation): bool + { + return true; + } + + protected function invokedDo(BaseInvocation $invocation): void + { + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/AnyParameters.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/AnyParameters.php new file mode 100644 index 00000000..61de7887 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/AnyParameters.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class AnyParameters implements ParametersRule +{ + public function toString(): string + { + return 'with any parameters'; + } + + public function apply(BaseInvocation $invocation): void + { + } + + public function verify(): void + { + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/ConsecutiveParameters.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/ConsecutiveParameters.php new file mode 100644 index 00000000..2188ea0f --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/ConsecutiveParameters.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use function count; +use function gettype; +use function is_iterable; +use function sprintf; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\Constraint\IsEqual; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\InvalidParameterGroupException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @deprecated + */ +final class ConsecutiveParameters implements ParametersRule +{ + /** + * @var array + */ + private $parameterGroups = []; + + /** + * @var array + */ + private $invocations = []; + + /** + * @throws \PHPUnit\Framework\Exception + */ + public function __construct(array $parameterGroups) + { + foreach ($parameterGroups as $index => $parameters) { + if (!is_iterable($parameters)) { + throw new InvalidParameterGroupException( + sprintf( + 'Parameter group #%d must be an array or Traversable, got %s', + $index, + gettype($parameters) + ) + ); + } + + foreach ($parameters as $parameter) { + if (!$parameter instanceof Constraint) { + $parameter = new IsEqual($parameter); + } + + $this->parameterGroups[$index][] = $parameter; + } + } + } + + public function toString(): string + { + return 'with consecutive parameters'; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public function apply(BaseInvocation $invocation): void + { + $this->invocations[] = $invocation; + $callIndex = count($this->invocations) - 1; + + $this->verifyInvocation($invocation, $callIndex); + } + + /** + * @throws \PHPUnit\Framework\ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function verify(): void + { + foreach ($this->invocations as $callIndex => $invocation) { + $this->verifyInvocation($invocation, $callIndex); + } + } + + /** + * Verify a single invocation. + * + * @param int $callIndex + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + private function verifyInvocation(BaseInvocation $invocation, $callIndex): void + { + if (!isset($this->parameterGroups[$callIndex])) { + // no parameter assertion for this call index + return; + } + + $parameters = $this->parameterGroups[$callIndex]; + + if (count($invocation->getParameters()) < count($parameters)) { + throw new ExpectationFailedException( + sprintf( + 'Parameter count for invocation %s is too low.', + $invocation->toString() + ) + ); + } + + foreach ($parameters as $i => $parameter) { + $parameter->evaluate( + $invocation->getParameters()[$i], + sprintf( + 'Parameter %s for invocation #%d %s does not match expected ' . + 'value.', + $i, + $callIndex, + $invocation->toString() + ) + ); + } + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvocationOrder.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvocationOrder.php new file mode 100644 index 00000000..90aa4935 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvocationOrder.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use function count; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; +use PHPUnit\Framework\MockObject\Verifiable; +use PHPUnit\Framework\SelfDescribing; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class InvocationOrder implements SelfDescribing, Verifiable +{ + /** + * @var BaseInvocation[] + */ + private $invocations = []; + + public function getInvocationCount(): int + { + return count($this->invocations); + } + + public function hasBeenInvoked(): bool + { + return count($this->invocations) > 0; + } + + final public function invoked(BaseInvocation $invocation) + { + $this->invocations[] = $invocation; + + return $this->invokedDo($invocation); + } + + abstract public function matches(BaseInvocation $invocation): bool; + + abstract protected function invokedDo(BaseInvocation $invocation); +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtIndex.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtIndex.php new file mode 100644 index 00000000..9b51f4ef --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtIndex.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use function sprintf; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4297 + * + * @codeCoverageIgnore + */ +final class InvokedAtIndex extends InvocationOrder +{ + /** + * @var int + */ + private $sequenceIndex; + + /** + * @var int + */ + private $currentIndex = -1; + + /** + * @param int $sequenceIndex + */ + public function __construct($sequenceIndex) + { + $this->sequenceIndex = $sequenceIndex; + } + + public function toString(): string + { + return 'invoked at sequence index ' . $this->sequenceIndex; + } + + public function matches(BaseInvocation $invocation): bool + { + $this->currentIndex++; + + return $this->currentIndex == $this->sequenceIndex; + } + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + if ($this->currentIndex < $this->sequenceIndex) { + throw new ExpectationFailedException( + sprintf( + 'The expected invocation at index %s was never reached.', + $this->sequenceIndex + ) + ); + } + } + + protected function invokedDo(BaseInvocation $invocation): void + { + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastCount.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastCount.php new file mode 100644 index 00000000..a84aa655 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastCount.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvokedAtLeastCount extends InvocationOrder +{ + /** + * @var int + */ + private $requiredInvocations; + + /** + * @param int $requiredInvocations + */ + public function __construct($requiredInvocations) + { + $this->requiredInvocations = $requiredInvocations; + } + + public function toString(): string + { + return 'invoked at least ' . $this->requiredInvocations . ' times'; + } + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + $count = $this->getInvocationCount(); + + if ($count < $this->requiredInvocations) { + throw new ExpectationFailedException( + 'Expected invocation at least ' . $this->requiredInvocations . + ' times but it occurred ' . $count . ' time(s).' + ); + } + } + + public function matches(BaseInvocation $invocation): bool + { + return true; + } + + protected function invokedDo(BaseInvocation $invocation): void + { + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastOnce.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastOnce.php new file mode 100644 index 00000000..d0ad1f80 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtLeastOnce.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvokedAtLeastOnce extends InvocationOrder +{ + public function toString(): string + { + return 'invoked at least once'; + } + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + $count = $this->getInvocationCount(); + + if ($count < 1) { + throw new ExpectationFailedException( + 'Expected invocation at least once but it never occurred.' + ); + } + } + + public function matches(BaseInvocation $invocation): bool + { + return true; + } + + protected function invokedDo(BaseInvocation $invocation): void + { + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtMostCount.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtMostCount.php new file mode 100644 index 00000000..c3b815aa --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedAtMostCount.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvokedAtMostCount extends InvocationOrder +{ + /** + * @var int + */ + private $allowedInvocations; + + /** + * @param int $allowedInvocations + */ + public function __construct($allowedInvocations) + { + $this->allowedInvocations = $allowedInvocations; + } + + public function toString(): string + { + return 'invoked at most ' . $this->allowedInvocations . ' times'; + } + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + $count = $this->getInvocationCount(); + + if ($count > $this->allowedInvocations) { + throw new ExpectationFailedException( + 'Expected invocation at most ' . $this->allowedInvocations . + ' times but it occurred ' . $count . ' time(s).' + ); + } + } + + public function matches(BaseInvocation $invocation): bool + { + return true; + } + + protected function invokedDo(BaseInvocation $invocation): void + { + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedCount.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedCount.php new file mode 100644 index 00000000..188326c9 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/InvokedCount.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use function sprintf; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvokedCount extends InvocationOrder +{ + /** + * @var int + */ + private $expectedCount; + + /** + * @param int $expectedCount + */ + public function __construct($expectedCount) + { + $this->expectedCount = $expectedCount; + } + + public function isNever(): bool + { + return $this->expectedCount === 0; + } + + public function toString(): string + { + return 'invoked ' . $this->expectedCount . ' time(s)'; + } + + public function matches(BaseInvocation $invocation): bool + { + return true; + } + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + $count = $this->getInvocationCount(); + + if ($count !== $this->expectedCount) { + throw new ExpectationFailedException( + sprintf( + 'Method was expected to be called %d times, ' . + 'actually called %d times.', + $this->expectedCount, + $count + ) + ); + } + } + + /** + * @throws ExpectationFailedException + */ + protected function invokedDo(BaseInvocation $invocation): void + { + $count = $this->getInvocationCount(); + + if ($count > $this->expectedCount) { + $message = $invocation->toString() . ' '; + + switch ($this->expectedCount) { + case 0: + $message .= 'was not expected to be called.'; + + break; + + case 1: + $message .= 'was not expected to be called more than once.'; + + break; + + default: + $message .= sprintf( + 'was not expected to be called more than %d times.', + $this->expectedCount + ); + } + + throw new ExpectationFailedException($message); + } + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/MethodName.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/MethodName.php new file mode 100644 index 00000000..83ba3b8d --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/MethodName.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use function is_string; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\InvalidArgumentException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; +use PHPUnit\Framework\MockObject\MethodNameConstraint; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MethodName +{ + /** + * @var Constraint + */ + private $constraint; + + /** + * @param Constraint|string $constraint + * + * @throws InvalidArgumentException + */ + public function __construct($constraint) + { + if (is_string($constraint)) { + $constraint = new MethodNameConstraint($constraint); + } + + if (!$constraint instanceof Constraint) { + throw InvalidArgumentException::create(1, 'PHPUnit\Framework\Constraint\Constraint object or string'); + } + + $this->constraint = $constraint; + } + + public function toString(): string + { + return 'method name ' . $this->constraint->toString(); + } + + /** + * @throws \PHPUnit\Framework\ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function matches(BaseInvocation $invocation): bool + { + return $this->matchesName($invocation->getMethodName()); + } + + /** + * @throws \PHPUnit\Framework\ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function matchesName(string $methodName): bool + { + return (bool) $this->constraint->evaluate($methodName, '', true); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/Parameters.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/Parameters.php new file mode 100644 index 00000000..3f1cc53a --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/Parameters.php @@ -0,0 +1,160 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use function count; +use function get_class; +use function sprintf; +use Exception; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\Constraint\IsAnything; +use PHPUnit\Framework\Constraint\IsEqual; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Parameters implements ParametersRule +{ + /** + * @var Constraint[] + */ + private $parameters = []; + + /** + * @var BaseInvocation + */ + private $invocation; + + /** + * @var bool|ExpectationFailedException + */ + private $parameterVerificationResult; + + /** + * @throws \PHPUnit\Framework\Exception + */ + public function __construct(array $parameters) + { + foreach ($parameters as $parameter) { + if (!($parameter instanceof Constraint)) { + $parameter = new IsEqual( + $parameter + ); + } + + $this->parameters[] = $parameter; + } + } + + public function toString(): string + { + $text = 'with parameter'; + + foreach ($this->parameters as $index => $parameter) { + if ($index > 0) { + $text .= ' and'; + } + + $text .= ' ' . $index . ' ' . $parameter->toString(); + } + + return $text; + } + + /** + * @throws Exception + */ + public function apply(BaseInvocation $invocation): void + { + $this->invocation = $invocation; + $this->parameterVerificationResult = null; + + try { + $this->parameterVerificationResult = $this->doVerify(); + } catch (ExpectationFailedException $e) { + $this->parameterVerificationResult = $e; + + throw $this->parameterVerificationResult; + } + } + + /** + * Checks if the invocation $invocation matches the current rules. If it + * does the rule will get the invoked() method called which should check + * if an expectation is met. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + public function verify(): void + { + $this->doVerify(); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ExpectationFailedException + */ + private function doVerify(): bool + { + if (isset($this->parameterVerificationResult)) { + return $this->guardAgainstDuplicateEvaluationOfParameterConstraints(); + } + + if ($this->invocation === null) { + throw new ExpectationFailedException('Mocked method does not exist.'); + } + + if (count($this->invocation->getParameters()) < count($this->parameters)) { + $message = 'Parameter count for invocation %s is too low.'; + + // The user called `->with($this->anything())`, but may have meant + // `->withAnyParameters()`. + // + // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/199 + if (count($this->parameters) === 1 && + get_class($this->parameters[0]) === IsAnything::class) { + $message .= "\nTo allow 0 or more parameters with any value, omit ->with() or use ->withAnyParameters() instead."; + } + + throw new ExpectationFailedException( + sprintf($message, $this->invocation->toString()) + ); + } + + foreach ($this->parameters as $i => $parameter) { + $parameter->evaluate( + $this->invocation->getParameters()[$i], + sprintf( + 'Parameter %s for invocation %s does not match expected ' . + 'value.', + $i, + $this->invocation->toString() + ) + ); + } + + return true; + } + + /** + * @throws ExpectationFailedException + */ + private function guardAgainstDuplicateEvaluationOfParameterConstraints(): bool + { + if ($this->parameterVerificationResult instanceof ExpectationFailedException) { + throw $this->parameterVerificationResult; + } + + return (bool) $this->parameterVerificationResult; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/ParametersRule.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/ParametersRule.php new file mode 100644 index 00000000..70c47fe3 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Rule/ParametersRule.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; +use PHPUnit\Framework\MockObject\Verifiable; +use PHPUnit\Framework\SelfDescribing; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface ParametersRule extends SelfDescribing, Verifiable +{ + /** + * @throws ExpectationFailedException if the invocation violates the rule + */ + public function apply(BaseInvocation $invocation): void; + + public function verify(): void; +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub.php new file mode 100644 index 00000000..2b032e2d --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use PHPUnit\Framework\MockObject\Builder\InvocationStubber; + +/** + * @method InvocationStubber method($constraint) + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface Stub +{ + public function __phpunit_getInvocationHandler(): InvocationHandler; + + public function __phpunit_hasMatchers(): bool; + + public function __phpunit_setReturnValueGeneration(bool $returnValueGeneration): void; +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ConsecutiveCalls.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ConsecutiveCalls.php new file mode 100644 index 00000000..0dcf386b --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ConsecutiveCalls.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use function array_shift; +use function sprintf; +use PHPUnit\Framework\MockObject\Invocation; +use SebastianBergmann\Exporter\Exporter; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ConsecutiveCalls implements Stub +{ + /** + * @var array + */ + private $stack; + + /** + * @var mixed + */ + private $value; + + public function __construct(array $stack) + { + $this->stack = $stack; + } + + public function invoke(Invocation $invocation) + { + $this->value = array_shift($this->stack); + + if ($this->value instanceof Stub) { + $this->value = $this->value->invoke($invocation); + } + + return $this->value; + } + + public function toString(): string + { + $exporter = new Exporter; + + return sprintf( + 'return user-specified value %s', + $exporter->export($this->value) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/Exception.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/Exception.php new file mode 100644 index 00000000..5d64c96a --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/Exception.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use function sprintf; +use PHPUnit\Framework\MockObject\Invocation; +use SebastianBergmann\Exporter\Exporter; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Exception implements Stub +{ + private $exception; + + public function __construct(Throwable $exception) + { + $this->exception = $exception; + } + + /** + * @throws Throwable + */ + public function invoke(Invocation $invocation): void + { + throw $this->exception; + } + + public function toString(): string + { + $exporter = new Exporter; + + return sprintf( + 'raise user-specified exception %s', + $exporter->export($this->exception) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnArgument.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnArgument.php new file mode 100644 index 00000000..c7b3f8f4 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnArgument.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use function sprintf; +use PHPUnit\Framework\MockObject\Invocation; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnArgument implements Stub +{ + /** + * @var int + */ + private $argumentIndex; + + public function __construct($argumentIndex) + { + $this->argumentIndex = $argumentIndex; + } + + public function invoke(Invocation $invocation) + { + if (isset($invocation->getParameters()[$this->argumentIndex])) { + return $invocation->getParameters()[$this->argumentIndex]; + } + } + + public function toString(): string + { + return sprintf('return argument #%d', $this->argumentIndex); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnCallback.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnCallback.php new file mode 100644 index 00000000..e02181e9 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnCallback.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use function call_user_func_array; +use function get_class; +use function is_array; +use function is_object; +use function sprintf; +use PHPUnit\Framework\MockObject\Invocation; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnCallback implements Stub +{ + private $callback; + + public function __construct($callback) + { + $this->callback = $callback; + } + + public function invoke(Invocation $invocation) + { + return call_user_func_array($this->callback, $invocation->getParameters()); + } + + public function toString(): string + { + if (is_array($this->callback)) { + if (is_object($this->callback[0])) { + $class = get_class($this->callback[0]); + $type = '->'; + } else { + $class = $this->callback[0]; + $type = '::'; + } + + return sprintf( + 'return result of user defined callback %s%s%s() with the ' . + 'passed arguments', + $class, + $type, + $this->callback[1] + ); + } + + return 'return result of user defined callback ' . $this->callback . + ' with the passed arguments'; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnReference.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnReference.php new file mode 100644 index 00000000..0d288ceb --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnReference.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use function sprintf; +use PHPUnit\Framework\MockObject\Invocation; +use SebastianBergmann\Exporter\Exporter; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnReference implements Stub +{ + /** + * @var mixed + */ + private $reference; + + public function __construct(&$reference) + { + $this->reference = &$reference; + } + + public function invoke(Invocation $invocation) + { + return $this->reference; + } + + public function toString(): string + { + $exporter = new Exporter; + + return sprintf( + 'return user-specified reference %s', + $exporter->export($this->reference) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnSelf.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnSelf.php new file mode 100644 index 00000000..6d2137bf --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnSelf.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; +use PHPUnit\Framework\MockObject\RuntimeException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnSelf implements Stub +{ + /** + * @throws RuntimeException + */ + public function invoke(Invocation $invocation) + { + return $invocation->getObject(); + } + + public function toString(): string + { + return 'return the current object'; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnStub.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnStub.php new file mode 100644 index 00000000..fbcd0a07 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnStub.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use function sprintf; +use PHPUnit\Framework\MockObject\Invocation; +use SebastianBergmann\Exporter\Exporter; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnStub implements Stub +{ + /** + * @var mixed + */ + private $value; + + public function __construct($value) + { + $this->value = $value; + } + + public function invoke(Invocation $invocation) + { + return $this->value; + } + + public function toString(): string + { + $exporter = new Exporter; + + return sprintf( + 'return user-specified value %s', + $exporter->export($this->value) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnValueMap.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnValueMap.php new file mode 100644 index 00000000..5fcd3a09 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnValueMap.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use function array_pop; +use function count; +use function is_array; +use PHPUnit\Framework\MockObject\Invocation; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnValueMap implements Stub +{ + /** + * @var array + */ + private $valueMap; + + public function __construct(array $valueMap) + { + $this->valueMap = $valueMap; + } + + public function invoke(Invocation $invocation) + { + $parameterCount = count($invocation->getParameters()); + + foreach ($this->valueMap as $map) { + if (!is_array($map) || $parameterCount !== (count($map) - 1)) { + continue; + } + + $return = array_pop($map); + + if ($invocation->getParameters() === $map) { + return $return; + } + } + } + + public function toString(): string + { + return 'return value from a map'; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/Stub.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/Stub.php new file mode 100644 index 00000000..15cfce5c --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/Stub.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; +use PHPUnit\Framework\SelfDescribing; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Stub extends SelfDescribing +{ + /** + * Fakes the processing of the invocation $invocation by returning a + * specific value. + * + * @param Invocation $invocation The invocation which was mocked and matched by the current method and argument matchers + */ + public function invoke(Invocation $invocation); +} diff --git a/vendor/phpunit/phpunit/src/Framework/MockObject/Verifiable.php b/vendor/phpunit/phpunit/src/Framework/MockObject/Verifiable.php new file mode 100644 index 00000000..8c9a82c5 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/MockObject/Verifiable.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use PHPUnit\Framework\ExpectationFailedException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Verifiable +{ + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void; +} diff --git a/vendor/phpunit/phpunit/src/Framework/Reorderable.php b/vendor/phpunit/phpunit/src/Framework/Reorderable.php new file mode 100644 index 00000000..34951f8d --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Reorderable.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Reorderable +{ + public function sortId(): string; + + /** + * @return list + */ + public function provides(): array; + + /** + * @return list + */ + public function requires(): array; +} diff --git a/vendor/phpunit/phpunit/src/Framework/SelfDescribing.php b/vendor/phpunit/phpunit/src/Framework/SelfDescribing.php new file mode 100644 index 00000000..73034f65 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/SelfDescribing.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface SelfDescribing +{ + /** + * Returns a string representation of the object. + */ + public function toString(): string; +} diff --git a/vendor/phpunit/phpunit/src/Framework/SkippedTest.php b/vendor/phpunit/phpunit/src/Framework/SkippedTest.php new file mode 100644 index 00000000..a12aa402 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/SkippedTest.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface SkippedTest extends Throwable +{ +} diff --git a/vendor/phpunit/phpunit/src/Framework/SkippedTestCase.php b/vendor/phpunit/phpunit/src/Framework/SkippedTestCase.php new file mode 100644 index 00000000..51c00619 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/SkippedTestCase.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SkippedTestCase extends TestCase +{ + /** + * @var bool + */ + protected $backupGlobals = false; + + /** + * @var bool + */ + protected $backupStaticAttributes = false; + + /** + * @var bool + */ + protected $runTestInSeparateProcess = false; + + /** + * @var string + */ + private $message; + + public function __construct(string $className, string $methodName, string $message = '') + { + parent::__construct($className . '::' . $methodName); + + $this->message = $message; + } + + public function getMessage(): string + { + return $this->message; + } + + /** + * Returns a string representation of the test case. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + return $this->getName(); + } + + /** + * @throws Exception + */ + protected function runTest(): void + { + $this->markTestSkipped($this->message); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/Test.php b/vendor/phpunit/phpunit/src/Framework/Test.php new file mode 100644 index 00000000..be0dcd0e --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/Test.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use Countable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface Test extends Countable +{ + /** + * Runs a test and collects its result in a TestResult instance. + */ + public function run(TestResult $result = null): TestResult; +} diff --git a/vendor/phpunit/phpunit/src/Framework/TestBuilder.php b/vendor/phpunit/phpunit/src/Framework/TestBuilder.php new file mode 100644 index 00000000..5dd91e21 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/TestBuilder.php @@ -0,0 +1,239 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function assert; +use function count; +use function get_class; +use function sprintf; +use function trim; +use PHPUnit\Util\Filter; +use PHPUnit\Util\InvalidDataSetException; +use PHPUnit\Util\Test as TestUtil; +use ReflectionClass; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestBuilder +{ + public function build(ReflectionClass $theClass, string $methodName): Test + { + $className = $theClass->getName(); + + if (!$theClass->isInstantiable()) { + return new ErrorTestCase( + sprintf('Cannot instantiate class "%s".', $className) + ); + } + + $backupSettings = TestUtil::getBackupSettings( + $className, + $methodName + ); + + $preserveGlobalState = TestUtil::getPreserveGlobalStateSettings( + $className, + $methodName + ); + + $runTestInSeparateProcess = TestUtil::getProcessIsolationSettings( + $className, + $methodName + ); + + $runClassInSeparateProcess = TestUtil::getClassProcessIsolationSettings( + $className, + $methodName + ); + + $constructor = $theClass->getConstructor(); + + if ($constructor === null) { + throw new Exception('No valid test provided.'); + } + + $parameters = $constructor->getParameters(); + + // TestCase() or TestCase($name) + if (count($parameters) < 2) { + $test = $this->buildTestWithoutData($className); + } // TestCase($name, $data) + else { + try { + $data = TestUtil::getProvidedData( + $className, + $methodName + ); + } catch (IncompleteTestError $e) { + $message = sprintf( + "Test for %s::%s marked incomplete by data provider\n%s", + $className, + $methodName, + $this->throwableToString($e) + ); + + $data = new IncompleteTestCase($className, $methodName, $message); + } catch (SkippedTestError $e) { + $message = sprintf( + "Test for %s::%s skipped by data provider\n%s", + $className, + $methodName, + $this->throwableToString($e) + ); + + $data = new SkippedTestCase($className, $methodName, $message); + } catch (Throwable $t) { + $message = sprintf( + "The data provider specified for %s::%s is invalid.\n%s", + $className, + $methodName, + $this->throwableToString($t) + ); + + $data = new ErrorTestCase($message); + } + + // Test method with @dataProvider. + if (isset($data)) { + $test = $this->buildDataProviderTestSuite( + $methodName, + $className, + $data, + $runTestInSeparateProcess, + $preserveGlobalState, + $runClassInSeparateProcess, + $backupSettings + ); + } else { + $test = $this->buildTestWithoutData($className); + } + } + + if ($test instanceof TestCase) { + $test->setName($methodName); + $this->configureTestCase( + $test, + $runTestInSeparateProcess, + $preserveGlobalState, + $runClassInSeparateProcess, + $backupSettings + ); + } + + return $test; + } + + /** @psalm-param class-string $className */ + private function buildTestWithoutData(string $className) + { + return new $className; + } + + /** @psalm-param class-string $className */ + private function buildDataProviderTestSuite( + string $methodName, + string $className, + $data, + bool $runTestInSeparateProcess, + ?bool $preserveGlobalState, + bool $runClassInSeparateProcess, + array $backupSettings + ): DataProviderTestSuite { + $dataProviderTestSuite = new DataProviderTestSuite( + $className . '::' . $methodName + ); + + $groups = TestUtil::getGroups($className, $methodName); + + if ($data instanceof ErrorTestCase || + $data instanceof SkippedTestCase || + $data instanceof IncompleteTestCase) { + $dataProviderTestSuite->addTest($data, $groups); + } else { + foreach ($data as $_dataName => $_data) { + $_test = new $className($methodName, $_data, $_dataName); + + assert($_test instanceof TestCase); + + $this->configureTestCase( + $_test, + $runTestInSeparateProcess, + $preserveGlobalState, + $runClassInSeparateProcess, + $backupSettings + ); + + $dataProviderTestSuite->addTest($_test, $groups); + } + } + + return $dataProviderTestSuite; + } + + private function configureTestCase( + TestCase $test, + bool $runTestInSeparateProcess, + ?bool $preserveGlobalState, + bool $runClassInSeparateProcess, + array $backupSettings + ): void { + if ($runTestInSeparateProcess) { + $test->setRunTestInSeparateProcess(true); + + if ($preserveGlobalState !== null) { + $test->setPreserveGlobalState($preserveGlobalState); + } + } + + if ($runClassInSeparateProcess) { + $test->setRunClassInSeparateProcess(true); + + if ($preserveGlobalState !== null) { + $test->setPreserveGlobalState($preserveGlobalState); + } + } + + if ($backupSettings['backupGlobals'] !== null) { + $test->setBackupGlobals($backupSettings['backupGlobals']); + } + + if ($backupSettings['backupStaticAttributes'] !== null) { + $test->setBackupStaticAttributes( + $backupSettings['backupStaticAttributes'] + ); + } + } + + private function throwableToString(Throwable $t): string + { + $message = $t->getMessage(); + + if (empty(trim($message))) { + $message = ''; + } + + if ($t instanceof InvalidDataSetException) { + return sprintf( + "%s\n%s", + $message, + Filter::getFilteredStacktrace($t) + ); + } + + return sprintf( + "%s: %s\n%s", + get_class($t), + $message, + Filter::getFilteredStacktrace($t) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/TestCase.php b/vendor/phpunit/phpunit/src/Framework/TestCase.php new file mode 100644 index 00000000..2d83fe01 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/TestCase.php @@ -0,0 +1,2669 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use const LC_ALL; +use const LC_COLLATE; +use const LC_CTYPE; +use const LC_MONETARY; +use const LC_NUMERIC; +use const LC_TIME; +use const PATHINFO_FILENAME; +use const PHP_EOL; +use const PHP_URL_PATH; +use function array_filter; +use function array_flip; +use function array_keys; +use function array_merge; +use function array_pop; +use function array_search; +use function array_unique; +use function array_values; +use function basename; +use function call_user_func; +use function chdir; +use function class_exists; +use function clearstatcache; +use function count; +use function debug_backtrace; +use function defined; +use function explode; +use function get_class; +use function get_include_path; +use function getcwd; +use function implode; +use function in_array; +use function ini_set; +use function is_array; +use function is_callable; +use function is_int; +use function is_object; +use function is_string; +use function libxml_clear_errors; +use function method_exists; +use function ob_end_clean; +use function ob_get_contents; +use function ob_get_level; +use function ob_start; +use function parse_url; +use function pathinfo; +use function preg_replace; +use function serialize; +use function setlocale; +use function sprintf; +use function strpos; +use function substr; +use function trim; +use function var_export; +use DeepCopy\DeepCopy; +use PHPUnit\Framework\Constraint\Exception as ExceptionConstraint; +use PHPUnit\Framework\Constraint\ExceptionCode; +use PHPUnit\Framework\Constraint\ExceptionMessage; +use PHPUnit\Framework\Constraint\ExceptionMessageRegularExpression; +use PHPUnit\Framework\Constraint\LogicalOr; +use PHPUnit\Framework\Error\Deprecated; +use PHPUnit\Framework\Error\Error; +use PHPUnit\Framework\Error\Notice; +use PHPUnit\Framework\Error\Warning as WarningError; +use PHPUnit\Framework\MockObject\Generator as MockGenerator; +use PHPUnit\Framework\MockObject\MockBuilder; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount as AnyInvokedCountMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedAtIndex as InvokedAtIndexMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastCount as InvokedAtLeastCountMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce as InvokedAtLeastOnceMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount as InvokedAtMostCountMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedCount as InvokedCountMatcher; +use PHPUnit\Framework\MockObject\Stub; +use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls as ConsecutiveCallsStub; +use PHPUnit\Framework\MockObject\Stub\Exception as ExceptionStub; +use PHPUnit\Framework\MockObject\Stub\ReturnArgument as ReturnArgumentStub; +use PHPUnit\Framework\MockObject\Stub\ReturnCallback as ReturnCallbackStub; +use PHPUnit\Framework\MockObject\Stub\ReturnSelf as ReturnSelfStub; +use PHPUnit\Framework\MockObject\Stub\ReturnStub; +use PHPUnit\Framework\MockObject\Stub\ReturnValueMap as ReturnValueMapStub; +use PHPUnit\Runner\BaseTestRunner; +use PHPUnit\Runner\PhptTestCase; +use PHPUnit\Util\Cloner; +use PHPUnit\Util\Exception as UtilException; +use PHPUnit\Util\GlobalState; +use PHPUnit\Util\PHP\AbstractPhpProcess; +use PHPUnit\Util\Test as TestUtil; +use Prophecy\Exception\Prediction\PredictionException; +use Prophecy\Prophecy\MethodProphecy; +use Prophecy\Prophecy\ObjectProphecy; +use Prophecy\Prophet; +use ReflectionClass; +use ReflectionException; +use SebastianBergmann\Comparator\Comparator; +use SebastianBergmann\Comparator\Factory as ComparatorFactory; +use SebastianBergmann\Diff\Differ; +use SebastianBergmann\Exporter\Exporter; +use SebastianBergmann\GlobalState\ExcludeList; +use SebastianBergmann\GlobalState\Restorer; +use SebastianBergmann\GlobalState\Snapshot; +use SebastianBergmann\ObjectEnumerator\Enumerator; +use SebastianBergmann\Template\Template; +use SoapClient; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class TestCase extends Assert implements Reorderable, SelfDescribing, Test +{ + private const LOCALE_CATEGORIES = [LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME]; + + /** + * @var ?bool + */ + protected $backupGlobals; + + /** + * @var string[] + */ + protected $backupGlobalsExcludeList = []; + + /** + * @var string[] + * + * @deprecated Use $backupGlobalsExcludeList instead + */ + protected $backupGlobalsBlacklist = []; + + /** + * @var bool + */ + protected $backupStaticAttributes; + + /** + * @var array> + */ + protected $backupStaticAttributesExcludeList = []; + + /** + * @var array> + * + * @deprecated Use $backupStaticAttributesExcludeList instead + */ + protected $backupStaticAttributesBlacklist = []; + + /** + * @var bool + */ + protected $runTestInSeparateProcess; + + /** + * @var bool + */ + protected $preserveGlobalState = true; + + /** + * @var list + */ + protected $providedTests = []; + + /** + * @var bool + */ + private $runClassInSeparateProcess; + + /** + * @var bool + */ + private $inIsolation = false; + + /** + * @var array + */ + private $data; + + /** + * @var int|string + */ + private $dataName; + + /** + * @var null|string + */ + private $expectedException; + + /** + * @var null|string + */ + private $expectedExceptionMessage; + + /** + * @var null|string + */ + private $expectedExceptionMessageRegExp; + + /** + * @var null|int|string + */ + private $expectedExceptionCode; + + /** + * @var string + */ + private $name = ''; + + /** + * @var list + */ + private $dependencies = []; + + /** + * @var array + */ + private $dependencyInput = []; + + /** + * @var array + */ + private $iniSettings = []; + + /** + * @var array + */ + private $locale = []; + + /** + * @var MockObject[] + */ + private $mockObjects = []; + + /** + * @var MockGenerator + */ + private $mockObjectGenerator; + + /** + * @var int + */ + private $status = BaseTestRunner::STATUS_UNKNOWN; + + /** + * @var string + */ + private $statusMessage = ''; + + /** + * @var int + */ + private $numAssertions = 0; + + /** + * @var TestResult + */ + private $result; + + /** + * @var mixed + */ + private $testResult; + + /** + * @var string + */ + private $output = ''; + + /** + * @var ?string + */ + private $outputExpectedRegex; + + /** + * @var ?string + */ + private $outputExpectedString; + + /** + * @var mixed + */ + private $outputCallback = false; + + /** + * @var bool + */ + private $outputBufferingActive = false; + + /** + * @var int + */ + private $outputBufferingLevel; + + /** + * @var bool + */ + private $outputRetrievedForAssertion = false; + + /** + * @var ?Snapshot + */ + private $snapshot; + + /** + * @var \Prophecy\Prophet + */ + private $prophet; + + /** + * @var bool + */ + private $beStrictAboutChangesToGlobalState = false; + + /** + * @var bool + */ + private $registerMockObjectsFromTestArgumentsRecursively = false; + + /** + * @var string[] + */ + private $warnings = []; + + /** + * @var string[] + */ + private $groups = []; + + /** + * @var bool + */ + private $doesNotPerformAssertions = false; + + /** + * @var Comparator[] + */ + private $customComparators = []; + + /** + * @var string[] + */ + private $doubledTypes = []; + + /** + * Returns a matcher that matches when the method is executed + * zero or more times. + */ + public static function any(): AnyInvokedCountMatcher + { + return new AnyInvokedCountMatcher; + } + + /** + * Returns a matcher that matches when the method is never executed. + */ + public static function never(): InvokedCountMatcher + { + return new InvokedCountMatcher(0); + } + + /** + * Returns a matcher that matches when the method is executed + * at least N times. + */ + public static function atLeast(int $requiredInvocations): InvokedAtLeastCountMatcher + { + return new InvokedAtLeastCountMatcher( + $requiredInvocations + ); + } + + /** + * Returns a matcher that matches when the method is executed at least once. + */ + public static function atLeastOnce(): InvokedAtLeastOnceMatcher + { + return new InvokedAtLeastOnceMatcher; + } + + /** + * Returns a matcher that matches when the method is executed exactly once. + */ + public static function once(): InvokedCountMatcher + { + return new InvokedCountMatcher(1); + } + + /** + * Returns a matcher that matches when the method is executed + * exactly $count times. + */ + public static function exactly(int $count): InvokedCountMatcher + { + return new InvokedCountMatcher($count); + } + + /** + * Returns a matcher that matches when the method is executed + * at most N times. + */ + public static function atMost(int $allowedInvocations): InvokedAtMostCountMatcher + { + return new InvokedAtMostCountMatcher($allowedInvocations); + } + + /** + * Returns a matcher that matches when the method is executed + * at the given index. + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4297 + * + * @codeCoverageIgnore + */ + public static function at(int $index): InvokedAtIndexMatcher + { + $stack = debug_backtrace(); + + while (!empty($stack)) { + $frame = array_pop($stack); + + if (isset($frame['object']) && $frame['object'] instanceof self) { + $frame['object']->addWarning( + 'The at() matcher has been deprecated. It will be removed in PHPUnit 10. Please refactor your test to not rely on the order in which methods are invoked.' + ); + + break; + } + } + + return new InvokedAtIndexMatcher($index); + } + + public static function returnValue($value): ReturnStub + { + return new ReturnStub($value); + } + + public static function returnValueMap(array $valueMap): ReturnValueMapStub + { + return new ReturnValueMapStub($valueMap); + } + + public static function returnArgument(int $argumentIndex): ReturnArgumentStub + { + return new ReturnArgumentStub($argumentIndex); + } + + public static function returnCallback($callback): ReturnCallbackStub + { + return new ReturnCallbackStub($callback); + } + + /** + * Returns the current object. + * + * This method is useful when mocking a fluent interface. + */ + public static function returnSelf(): ReturnSelfStub + { + return new ReturnSelfStub; + } + + public static function throwException(Throwable $exception): ExceptionStub + { + return new ExceptionStub($exception); + } + + public static function onConsecutiveCalls(...$args): ConsecutiveCallsStub + { + return new ConsecutiveCallsStub($args); + } + + /** + * @param int|string $dataName + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function __construct(?string $name = null, array $data = [], $dataName = '') + { + if ($name !== null) { + $this->setName($name); + } + + $this->data = $data; + $this->dataName = $dataName; + } + + /** + * This method is called before the first test of this test class is run. + */ + public static function setUpBeforeClass(): void + { + } + + /** + * This method is called after the last test of this test class is run. + */ + public static function tearDownAfterClass(): void + { + } + + /** + * This method is called before each test. + */ + protected function setUp(): void + { + } + + /** + * Performs assertions shared by all tests of a test case. + * + * This method is called between setUp() and test. + */ + protected function assertPreConditions(): void + { + } + + /** + * Performs assertions shared by all tests of a test case. + * + * This method is called between test and tearDown(). + */ + protected function assertPostConditions(): void + { + } + + /** + * This method is called after each test. + */ + protected function tearDown(): void + { + } + + /** + * Returns a string representation of the test case. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + */ + public function toString(): string + { + try { + $class = new ReflectionClass($this); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + $buffer = sprintf( + '%s::%s', + $class->name, + $this->getName(false) + ); + + return $buffer . $this->getDataSetAsString(); + } + + public function count(): int + { + return 1; + } + + public function getActualOutputForAssertion(): string + { + $this->outputRetrievedForAssertion = true; + + return $this->getActualOutput(); + } + + public function expectOutputRegex(string $expectedRegex): void + { + $this->outputExpectedRegex = $expectedRegex; + } + + public function expectOutputString(string $expectedString): void + { + $this->outputExpectedString = $expectedString; + } + + /** + * @psalm-param class-string<\Throwable> $exception + */ + public function expectException(string $exception): void + { + // @codeCoverageIgnoreStart + switch ($exception) { + case Deprecated::class: + $this->addWarning('Expecting E_DEPRECATED and E_USER_DEPRECATED is deprecated and will no longer be possible in PHPUnit 10.'); + + break; + + case Error::class: + $this->addWarning('Expecting E_ERROR and E_USER_ERROR is deprecated and will no longer be possible in PHPUnit 10.'); + + break; + + case Notice::class: + $this->addWarning('Expecting E_STRICT, E_NOTICE, and E_USER_NOTICE is deprecated and will no longer be possible in PHPUnit 10.'); + + break; + + case WarningError::class: + $this->addWarning('Expecting E_WARNING and E_USER_WARNING is deprecated and will no longer be possible in PHPUnit 10.'); + + break; + } + // @codeCoverageIgnoreEnd + + $this->expectedException = $exception; + } + + /** + * @param int|string $code + */ + public function expectExceptionCode($code): void + { + $this->expectedExceptionCode = $code; + } + + public function expectExceptionMessage(string $message): void + { + $this->expectedExceptionMessage = $message; + } + + public function expectExceptionMessageMatches(string $regularExpression): void + { + $this->expectedExceptionMessageRegExp = $regularExpression; + } + + /** + * Sets up an expectation for an exception to be raised by the code under test. + * Information for expected exception class, expected exception message, and + * expected exception code are retrieved from a given Exception object. + */ + public function expectExceptionObject(\Exception $exception): void + { + $this->expectException(get_class($exception)); + $this->expectExceptionMessage($exception->getMessage()); + $this->expectExceptionCode($exception->getCode()); + } + + public function expectNotToPerformAssertions(): void + { + $this->doesNotPerformAssertions = true; + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5062 + */ + public function expectDeprecation(): void + { + $this->addWarning('Expecting E_DEPRECATED and E_USER_DEPRECATED is deprecated and will no longer be possible in PHPUnit 10.'); + + $this->expectedException = Deprecated::class; + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5062 + */ + public function expectDeprecationMessage(string $message): void + { + $this->addWarning('Expecting E_DEPRECATED and E_USER_DEPRECATED is deprecated and will no longer be possible in PHPUnit 10.'); + + $this->expectExceptionMessage($message); + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5062 + */ + public function expectDeprecationMessageMatches(string $regularExpression): void + { + $this->addWarning('Expecting E_DEPRECATED and E_USER_DEPRECATED is deprecated and will no longer be possible in PHPUnit 10.'); + + $this->expectExceptionMessageMatches($regularExpression); + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5062 + */ + public function expectNotice(): void + { + $this->addWarning('Expecting E_STRICT, E_NOTICE, and E_USER_NOTICE is deprecated and will no longer be possible in PHPUnit 10.'); + + $this->expectedException = Notice::class; + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5062 + */ + public function expectNoticeMessage(string $message): void + { + $this->addWarning('Expecting E_STRICT, E_NOTICE, and E_USER_NOTICE is deprecated and will no longer be possible in PHPUnit 10.'); + + $this->expectExceptionMessage($message); + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5062 + */ + public function expectNoticeMessageMatches(string $regularExpression): void + { + $this->addWarning('Expecting E_STRICT, E_NOTICE, and E_USER_NOTICE is deprecated and will no longer be possible in PHPUnit 10.'); + + $this->expectExceptionMessageMatches($regularExpression); + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5062 + */ + public function expectWarning(): void + { + $this->addWarning('Expecting E_WARNING and E_USER_WARNING is deprecated and will no longer be possible in PHPUnit 10.'); + + $this->expectedException = WarningError::class; + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5062 + */ + public function expectWarningMessage(string $message): void + { + $this->addWarning('Expecting E_WARNING and E_USER_WARNING is deprecated and will no longer be possible in PHPUnit 10.'); + + $this->expectExceptionMessage($message); + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5062 + */ + public function expectWarningMessageMatches(string $regularExpression): void + { + $this->addWarning('Expecting E_WARNING and E_USER_WARNING is deprecated and will no longer be possible in PHPUnit 10.'); + + $this->expectExceptionMessageMatches($regularExpression); + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5062 + */ + public function expectError(): void + { + $this->addWarning('Expecting E_ERROR and E_USER_ERROR is deprecated and will no longer be possible in PHPUnit 10.'); + + $this->expectedException = Error::class; + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5062 + */ + public function expectErrorMessage(string $message): void + { + $this->addWarning('Expecting E_ERROR and E_USER_ERROR is deprecated and will no longer be possible in PHPUnit 10.'); + + $this->expectExceptionMessage($message); + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5062 + */ + public function expectErrorMessageMatches(string $regularExpression): void + { + $this->addWarning('Expecting E_ERROR and E_USER_ERROR is deprecated and will no longer be possible in PHPUnit 10.'); + + $this->expectExceptionMessageMatches($regularExpression); + } + + public function getStatus(): int + { + return $this->status; + } + + public function markAsRisky(): void + { + $this->status = BaseTestRunner::STATUS_RISKY; + } + + public function getStatusMessage(): string + { + return $this->statusMessage; + } + + public function hasFailed(): bool + { + $status = $this->getStatus(); + + return $status === BaseTestRunner::STATUS_FAILURE || $status === BaseTestRunner::STATUS_ERROR; + } + + /** + * Runs the test case and collects the results in a TestResult object. + * If no TestResult object is passed a new one will be created. + * + * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException + * @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws CodeCoverageException + * @throws UtilException + */ + public function run(TestResult $result = null): TestResult + { + if ($result === null) { + $result = $this->createResult(); + } + + if (!$this instanceof ErrorTestCase && !$this instanceof WarningTestCase) { + $this->setTestResultObject($result); + } + + if (!$this instanceof ErrorTestCase && + !$this instanceof WarningTestCase && + !$this instanceof SkippedTestCase && + !$this->handleDependencies()) { + return $result; + } + + if ($this->runInSeparateProcess()) { + $runEntireClass = $this->runClassInSeparateProcess && !$this->runTestInSeparateProcess; + + try { + $class = new ReflectionClass($this); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + if ($runEntireClass) { + $template = new Template( + __DIR__ . '/../Util/PHP/Template/TestCaseClass.tpl' + ); + } else { + $template = new Template( + __DIR__ . '/../Util/PHP/Template/TestCaseMethod.tpl' + ); + } + + if ($this->preserveGlobalState) { + $constants = GlobalState::getConstantsAsString(); + $globals = GlobalState::getGlobalsAsString(); + $includedFiles = GlobalState::getIncludedFilesAsString(); + $iniSettings = GlobalState::getIniSettingsAsString(); + } else { + $constants = ''; + + if (!empty($GLOBALS['__PHPUNIT_BOOTSTRAP'])) { + $globals = '$GLOBALS[\'__PHPUNIT_BOOTSTRAP\'] = ' . var_export($GLOBALS['__PHPUNIT_BOOTSTRAP'], true) . ";\n"; + } else { + $globals = ''; + } + + $includedFiles = ''; + $iniSettings = ''; + } + + $coverage = $result->getCollectCodeCoverageInformation() ? 'true' : 'false'; + $isStrictAboutTestsThatDoNotTestAnything = $result->isStrictAboutTestsThatDoNotTestAnything() ? 'true' : 'false'; + $isStrictAboutOutputDuringTests = $result->isStrictAboutOutputDuringTests() ? 'true' : 'false'; + $enforcesTimeLimit = $result->enforcesTimeLimit() ? 'true' : 'false'; + $isStrictAboutTodoAnnotatedTests = $result->isStrictAboutTodoAnnotatedTests() ? 'true' : 'false'; + $isStrictAboutResourceUsageDuringSmallTests = $result->isStrictAboutResourceUsageDuringSmallTests() ? 'true' : 'false'; + + if (defined('PHPUNIT_COMPOSER_INSTALL')) { + $composerAutoload = var_export(PHPUNIT_COMPOSER_INSTALL, true); + } else { + $composerAutoload = '\'\''; + } + + if (defined('__PHPUNIT_PHAR__')) { + $phar = var_export(__PHPUNIT_PHAR__, true); + } else { + $phar = '\'\''; + } + + $codeCoverage = $result->getCodeCoverage(); + $codeCoverageFilter = null; + $cachesStaticAnalysis = 'false'; + $codeCoverageCacheDirectory = null; + $driverMethod = 'forLineCoverage'; + + if ($codeCoverage) { + $codeCoverageFilter = $codeCoverage->filter(); + + if ($codeCoverage->collectsBranchAndPathCoverage()) { + $driverMethod = 'forLineAndPathCoverage'; + } + + if ($codeCoverage->cachesStaticAnalysis()) { + $cachesStaticAnalysis = 'true'; + $codeCoverageCacheDirectory = $codeCoverage->cacheDirectory(); + } + } + + $data = var_export(serialize($this->data), true); + $dataName = var_export($this->dataName, true); + $dependencyInput = var_export(serialize($this->dependencyInput), true); + $includePath = var_export(get_include_path(), true); + $codeCoverageFilter = var_export(serialize($codeCoverageFilter), true); + $codeCoverageCacheDirectory = var_export(serialize($codeCoverageCacheDirectory), true); + // must do these fixes because TestCaseMethod.tpl has unserialize('{data}') in it, and we can't break BC + // the lines above used to use addcslashes() rather than var_export(), which breaks null byte escape sequences + $data = "'." . $data . ".'"; + $dataName = "'.(" . $dataName . ").'"; + $dependencyInput = "'." . $dependencyInput . ".'"; + $includePath = "'." . $includePath . ".'"; + $codeCoverageFilter = "'." . $codeCoverageFilter . ".'"; + $codeCoverageCacheDirectory = "'." . $codeCoverageCacheDirectory . ".'"; + + $configurationFilePath = $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] ?? ''; + + $var = [ + 'composerAutoload' => $composerAutoload, + 'phar' => $phar, + 'filename' => $class->getFileName(), + 'className' => $class->getName(), + 'collectCodeCoverageInformation' => $coverage, + 'cachesStaticAnalysis' => $cachesStaticAnalysis, + 'codeCoverageCacheDirectory' => $codeCoverageCacheDirectory, + 'driverMethod' => $driverMethod, + 'data' => $data, + 'dataName' => $dataName, + 'dependencyInput' => $dependencyInput, + 'constants' => $constants, + 'globals' => $globals, + 'include_path' => $includePath, + 'included_files' => $includedFiles, + 'iniSettings' => $iniSettings, + 'isStrictAboutTestsThatDoNotTestAnything' => $isStrictAboutTestsThatDoNotTestAnything, + 'isStrictAboutOutputDuringTests' => $isStrictAboutOutputDuringTests, + 'enforcesTimeLimit' => $enforcesTimeLimit, + 'isStrictAboutTodoAnnotatedTests' => $isStrictAboutTodoAnnotatedTests, + 'isStrictAboutResourceUsageDuringSmallTests' => $isStrictAboutResourceUsageDuringSmallTests, + 'codeCoverageFilter' => $codeCoverageFilter, + 'configurationFilePath' => $configurationFilePath, + 'name' => $this->getName(false), + ]; + + if (!$runEntireClass) { + $var['methodName'] = $this->name; + } + + $template->setVar($var); + + $php = AbstractPhpProcess::factory(); + $php->runTestJob($template->render(), $this, $result); + } else { + $result->run($this); + } + + $this->result = null; + + return $result; + } + + /** + * Returns a builder object to create mock objects using a fluent interface. + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $className + * + * @psalm-return MockBuilder + */ + public function getMockBuilder(string $className): MockBuilder + { + $this->recordDoubledType($className); + + return new MockBuilder($this, $className); + } + + public function registerComparator(Comparator $comparator): void + { + ComparatorFactory::getInstance()->register($comparator); + + $this->customComparators[] = $comparator; + } + + /** + * @return string[] + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function doubledTypes(): array + { + return array_unique($this->doubledTypes); + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function getGroups(): array + { + return $this->groups; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setGroups(array $groups): void + { + $this->groups = $groups; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function getName(bool $withDataSet = true): string + { + if ($withDataSet) { + return $this->name . $this->getDataSetAsString(false); + } + + return $this->name; + } + + /** + * Returns the size of the test. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function getSize(): int + { + return TestUtil::getSize( + static::class, + $this->getName(false) + ); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function hasSize(): bool + { + return $this->getSize() !== TestUtil::UNKNOWN; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function isSmall(): bool + { + return $this->getSize() === TestUtil::SMALL; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function isMedium(): bool + { + return $this->getSize() === TestUtil::MEDIUM; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function isLarge(): bool + { + return $this->getSize() === TestUtil::LARGE; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function getActualOutput(): string + { + if (!$this->outputBufferingActive) { + return $this->output; + } + + return (string) ob_get_contents(); + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function hasOutput(): bool + { + if ($this->output === '') { + return false; + } + + if ($this->hasExpectationOnOutput()) { + return false; + } + + return true; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function doesNotPerformAssertions(): bool + { + return $this->doesNotPerformAssertions; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function hasExpectationOnOutput(): bool + { + return is_string($this->outputExpectedString) || is_string($this->outputExpectedRegex) || $this->outputRetrievedForAssertion; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function getExpectedException(): ?string + { + return $this->expectedException; + } + + /** + * @return null|int|string + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function getExpectedExceptionCode() + { + return $this->expectedExceptionCode; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function getExpectedExceptionMessage(): ?string + { + return $this->expectedExceptionMessage; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function getExpectedExceptionMessageRegExp(): ?string + { + return $this->expectedExceptionMessageRegExp; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setRegisterMockObjectsFromTestArgumentsRecursively(bool $flag): void + { + $this->registerMockObjectsFromTestArgumentsRecursively = $flag; + } + + /** + * @throws Throwable + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function runBare(): void + { + $this->numAssertions = 0; + + $this->snapshotGlobalState(); + $this->startOutputBuffering(); + clearstatcache(); + $currentWorkingDirectory = getcwd(); + + $hookMethods = TestUtil::getHookMethods(static::class); + + $hasMetRequirements = false; + + try { + $this->checkRequirements(); + $hasMetRequirements = true; + + if ($this->inIsolation) { + foreach ($hookMethods['beforeClass'] as $method) { + $this->{$method}(); + } + } + + $this->setDoesNotPerformAssertionsFromAnnotation(); + + foreach ($hookMethods['before'] as $method) { + $this->{$method}(); + } + + foreach ($hookMethods['preCondition'] as $method) { + $this->{$method}(); + } + + $this->testResult = $this->runTest(); + $this->verifyMockObjects(); + + foreach ($hookMethods['postCondition'] as $method) { + $this->{$method}(); + } + + if (!empty($this->warnings)) { + throw new Warning( + implode( + "\n", + array_unique($this->warnings) + ) + ); + } + + $this->status = BaseTestRunner::STATUS_PASSED; + } catch (IncompleteTest $e) { + $this->status = BaseTestRunner::STATUS_INCOMPLETE; + $this->statusMessage = $e->getMessage(); + } catch (SkippedTest $e) { + $this->status = BaseTestRunner::STATUS_SKIPPED; + $this->statusMessage = $e->getMessage(); + } catch (Warning $e) { + $this->status = BaseTestRunner::STATUS_WARNING; + $this->statusMessage = $e->getMessage(); + } catch (AssertionFailedError $e) { + $this->status = BaseTestRunner::STATUS_FAILURE; + $this->statusMessage = $e->getMessage(); + } catch (PredictionException $e) { + $this->status = BaseTestRunner::STATUS_FAILURE; + $this->statusMessage = $e->getMessage(); + } catch (Throwable $_e) { + $e = $_e; + $this->status = BaseTestRunner::STATUS_ERROR; + $this->statusMessage = $_e->getMessage(); + } + + $this->mockObjects = []; + $this->prophet = null; + + // Tear down the fixture. An exception raised in tearDown() will be + // caught and passed on when no exception was raised before. + try { + if ($hasMetRequirements) { + foreach ($hookMethods['after'] as $method) { + $this->{$method}(); + } + + if ($this->inIsolation) { + foreach ($hookMethods['afterClass'] as $method) { + $this->{$method}(); + } + } + } + } catch (Throwable $_e) { + $e = $e ?? $_e; + } + + try { + $this->stopOutputBuffering(); + } catch (RiskyTestError $_e) { + $e = $e ?? $_e; + } + + if (isset($_e)) { + $this->status = BaseTestRunner::STATUS_ERROR; + $this->statusMessage = $_e->getMessage(); + } + + clearstatcache(); + + if ($currentWorkingDirectory !== getcwd()) { + chdir($currentWorkingDirectory); + } + + $this->restoreGlobalState(); + $this->unregisterCustomComparators(); + $this->cleanupIniSettings(); + $this->cleanupLocaleSettings(); + libxml_clear_errors(); + + // Perform assertion on output. + if (!isset($e)) { + try { + if ($this->outputExpectedRegex !== null) { + $this->assertMatchesRegularExpression($this->outputExpectedRegex, $this->output); + } elseif ($this->outputExpectedString !== null) { + $this->assertEquals($this->outputExpectedString, $this->output); + } + } catch (Throwable $_e) { + $e = $_e; + } + } + + // Workaround for missing "finally". + if (isset($e)) { + if ($e instanceof PredictionException) { + $e = new AssertionFailedError($e->getMessage()); + } + + $this->onNotSuccessfulTest($e); + } + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setName(string $name): void + { + $this->name = $name; + + if (is_callable($this->sortId(), true)) { + $this->providedTests = [new ExecutionOrderDependency($this->sortId())]; + } + } + + /** + * @param list $dependencies + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setDependencies(array $dependencies): void + { + $this->dependencies = $dependencies; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setDependencyInput(array $dependencyInput): void + { + $this->dependencyInput = $dependencyInput; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setBeStrictAboutChangesToGlobalState(?bool $beStrictAboutChangesToGlobalState): void + { + $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setBackupGlobals(?bool $backupGlobals): void + { + if ($this->backupGlobals === null && $backupGlobals !== null) { + $this->backupGlobals = $backupGlobals; + } + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setBackupStaticAttributes(?bool $backupStaticAttributes): void + { + if ($this->backupStaticAttributes === null && $backupStaticAttributes !== null) { + $this->backupStaticAttributes = $backupStaticAttributes; + } + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setRunTestInSeparateProcess(bool $runTestInSeparateProcess): void + { + if ($this->runTestInSeparateProcess === null) { + $this->runTestInSeparateProcess = $runTestInSeparateProcess; + } + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setRunClassInSeparateProcess(bool $runClassInSeparateProcess): void + { + if ($this->runClassInSeparateProcess === null) { + $this->runClassInSeparateProcess = $runClassInSeparateProcess; + } + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setPreserveGlobalState(bool $preserveGlobalState): void + { + $this->preserveGlobalState = $preserveGlobalState; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setInIsolation(bool $inIsolation): void + { + $this->inIsolation = $inIsolation; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function isInIsolation(): bool + { + return $this->inIsolation; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function getResult() + { + return $this->testResult; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setResult($result): void + { + $this->testResult = $result; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setOutputCallback(callable $callback): void + { + $this->outputCallback = $callback; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function getTestResultObject(): ?TestResult + { + return $this->result; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function setTestResultObject(TestResult $result): void + { + $this->result = $result; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function registerMockObject(MockObject $mockObject): void + { + $this->mockObjects[] = $mockObject; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function addToAssertionCount(int $count): void + { + $this->numAssertions += $count; + } + + /** + * Returns the number of assertions performed by this test. + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function getNumAssertions(): int + { + return $this->numAssertions; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function usesDataProvider(): bool + { + return !empty($this->data); + } + + /** + * @return int|string + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function dataName() + { + return $this->dataName; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function getDataSetAsString(bool $includeData = true): string + { + $buffer = ''; + + if (!empty($this->data)) { + if (is_int($this->dataName)) { + $buffer .= sprintf(' with data set #%d', $this->dataName); + } else { + $buffer .= sprintf(' with data set "%s"', $this->dataName); + } + + if ($includeData) { + $exporter = new Exporter; + + $buffer .= sprintf(' (%s)', $exporter->shortenedRecursiveExport($this->data)); + } + } + + return $buffer; + } + + /** + * Gets the data set of a TestCase. + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function getProvidedData(): array + { + return $this->data; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function addWarning(string $warning): void + { + $this->warnings[] = $warning; + } + + public function sortId(): string + { + $id = $this->name; + + if (strpos($id, '::') === false) { + $id = static::class . '::' . $id; + } + + if ($this->usesDataProvider()) { + $id .= $this->getDataSetAsString(false); + } + + return $id; + } + + /** + * Returns the normalized test name as class::method. + * + * @return list + */ + public function provides(): array + { + return $this->providedTests; + } + + /** + * Returns a list of normalized dependency names, class::method. + * + * This list can differ from the raw dependencies as the resolver has + * no need for the [!][shallow]clone prefix that is filtered out + * during normalization. + * + * @return list + */ + public function requires(): array + { + return $this->dependencies; + } + + /** + * Override to run the test and assert its state. + * + * @throws \SebastianBergmann\ObjectEnumerator\InvalidArgumentException + * @throws AssertionFailedError + * @throws Exception + * @throws ExpectationFailedException + * @throws Throwable + */ + protected function runTest() + { + if (trim($this->name) === '') { + throw new Exception( + 'PHPUnit\Framework\TestCase::$name must be a non-blank string.' + ); + } + + $testArguments = array_merge($this->data, $this->dependencyInput); + + $this->registerMockObjectsFromTestArguments($testArguments); + + try { + $testResult = $this->{$this->name}(...array_values($testArguments)); + } catch (Throwable $exception) { + if (!$this->checkExceptionExpectations($exception)) { + throw $exception; + } + + if ($this->expectedException !== null) { + if ($this->expectedException === Error::class) { + $this->assertThat( + $exception, + LogicalOr::fromConstraints( + new ExceptionConstraint(Error::class), + new ExceptionConstraint(\Error::class) + ) + ); + } else { + $this->assertThat( + $exception, + new ExceptionConstraint( + $this->expectedException + ) + ); + } + } + + if ($this->expectedExceptionMessage !== null) { + $this->assertThat( + $exception, + new ExceptionMessage( + $this->expectedExceptionMessage + ) + ); + } + + if ($this->expectedExceptionMessageRegExp !== null) { + $this->assertThat( + $exception, + new ExceptionMessageRegularExpression( + $this->expectedExceptionMessageRegExp + ) + ); + } + + if ($this->expectedExceptionCode !== null) { + $this->assertThat( + $exception, + new ExceptionCode( + $this->expectedExceptionCode + ) + ); + } + + return; + } + + if ($this->expectedException !== null) { + $this->assertThat( + null, + new ExceptionConstraint( + $this->expectedException + ) + ); + } elseif ($this->expectedExceptionMessage !== null) { + $this->numAssertions++; + + throw new AssertionFailedError( + sprintf( + 'Failed asserting that exception with message "%s" is thrown', + $this->expectedExceptionMessage + ) + ); + } elseif ($this->expectedExceptionMessageRegExp !== null) { + $this->numAssertions++; + + throw new AssertionFailedError( + sprintf( + 'Failed asserting that exception with message matching "%s" is thrown', + $this->expectedExceptionMessageRegExp + ) + ); + } elseif ($this->expectedExceptionCode !== null) { + $this->numAssertions++; + + throw new AssertionFailedError( + sprintf( + 'Failed asserting that exception with code "%s" is thrown', + $this->expectedExceptionCode + ) + ); + } + + return $testResult; + } + + /** + * This method is a wrapper for the ini_set() function that automatically + * resets the modified php.ini setting to its original value after the + * test is run. + * + * @throws Exception + */ + protected function iniSet(string $varName, string $newValue): void + { + $currentValue = ini_set($varName, $newValue); + + if ($currentValue !== false) { + $this->iniSettings[$varName] = $currentValue; + } else { + throw new Exception( + sprintf( + 'INI setting "%s" could not be set to "%s".', + $varName, + $newValue + ) + ); + } + } + + /** + * This method is a wrapper for the setlocale() function that automatically + * resets the locale to its original value after the test is run. + * + * @throws Exception + */ + protected function setLocale(...$args): void + { + if (count($args) < 2) { + throw new Exception; + } + + [$category, $locale] = $args; + + if (!in_array($category, self::LOCALE_CATEGORIES, true)) { + throw new Exception; + } + + if (!is_array($locale) && !is_string($locale)) { + throw new Exception; + } + + $this->locale[$category] = setlocale($category, 0); + + $result = setlocale(...$args); + + if ($result === false) { + throw new Exception( + 'The locale functionality is not implemented on your platform, ' . + 'the specified locale does not exist or the category name is ' . + 'invalid.' + ); + } + } + + /** + * Makes configurable stub for the specified class. + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return Stub&RealInstanceType + */ + protected function createStub(string $originalClassName): Stub + { + return $this->createMockObject($originalClassName); + } + + /** + * Returns a mock object for the specified class. + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return MockObject&RealInstanceType + */ + protected function createMock(string $originalClassName): MockObject + { + return $this->createMockObject($originalClassName); + } + + /** + * Returns a configured mock object for the specified class. + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return MockObject&RealInstanceType + */ + protected function createConfiguredMock(string $originalClassName, array $configuration): MockObject + { + $o = $this->createMockObject($originalClassName); + + foreach ($configuration as $method => $return) { + $o->method($method)->willReturn($return); + } + + return $o; + } + + /** + * Returns a partial mock object for the specified class. + * + * @param string[] $methods + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return MockObject&RealInstanceType + */ + protected function createPartialMock(string $originalClassName, array $methods): MockObject + { + try { + $reflector = new ReflectionClass($originalClassName); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + $mockedMethodsThatDontExist = array_filter( + $methods, + static function (string $method) use ($reflector) + { + return !$reflector->hasMethod($method); + } + ); + + if ($mockedMethodsThatDontExist) { + $this->addWarning( + sprintf( + 'createPartialMock() called with method(s) %s that do not exist in %s. This will not be allowed in future versions of PHPUnit.', + implode(', ', $mockedMethodsThatDontExist), + $originalClassName + ) + ); + } + + return $this->getMockBuilder($originalClassName) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->disableArgumentCloning() + ->disallowMockingUnknownTypes() + ->setMethods(empty($methods) ? null : $methods) + ->getMock(); + } + + /** + * Returns a test proxy for the specified class. + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return MockObject&RealInstanceType + */ + protected function createTestProxy(string $originalClassName, array $constructorArguments = []): MockObject + { + return $this->getMockBuilder($originalClassName) + ->setConstructorArgs($constructorArguments) + ->enableProxyingToOriginalMethods() + ->getMock(); + } + + /** + * Mocks the specified class and returns the name of the mocked class. + * + * @param null|array $methods $methods + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string|string $originalClassName + * + * @psalm-return class-string + * + * @deprecated + */ + protected function getMockClass(string $originalClassName, $methods = [], array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = false, bool $callOriginalClone = true, bool $callAutoload = true, bool $cloneArguments = false): string + { + $this->addWarning('PHPUnit\Framework\TestCase::getMockClass() is deprecated and will be removed in PHPUnit 10.'); + + $this->recordDoubledType($originalClassName); + + $mock = $this->getMockObjectGenerator()->getMock( + $originalClassName, + $methods, + $arguments, + $mockClassName, + $callOriginalConstructor, + $callOriginalClone, + $callAutoload, + $cloneArguments + ); + + return get_class($mock); + } + + /** + * Returns a mock object for the specified abstract class with all abstract + * methods of the class mocked. Concrete methods are not mocked by default. + * To mock concrete methods, use the 7th parameter ($mockedMethods). + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return MockObject&RealInstanceType + */ + protected function getMockForAbstractClass(string $originalClassName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, array $mockedMethods = [], bool $cloneArguments = false): MockObject + { + $this->recordDoubledType($originalClassName); + + $mockObject = $this->getMockObjectGenerator()->getMockForAbstractClass( + $originalClassName, + $arguments, + $mockClassName, + $callOriginalConstructor, + $callOriginalClone, + $callAutoload, + $mockedMethods, + $cloneArguments + ); + + $this->registerMockObject($mockObject); + + return $mockObject; + } + + /** + * Returns a mock object based on the given WSDL file. + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string|string $originalClassName + * + * @psalm-return MockObject&RealInstanceType + */ + protected function getMockFromWsdl(string $wsdlFile, string $originalClassName = '', string $mockClassName = '', array $methods = [], bool $callOriginalConstructor = true, array $options = []): MockObject + { + $this->recordDoubledType(SoapClient::class); + + if ($originalClassName === '') { + $fileName = pathinfo(basename(parse_url($wsdlFile, PHP_URL_PATH)), PATHINFO_FILENAME); + $originalClassName = preg_replace('/\W/', '', $fileName); + } + + if (!class_exists($originalClassName)) { + eval( + $this->getMockObjectGenerator()->generateClassFromWsdl( + $wsdlFile, + $originalClassName, + $methods, + $options + ) + ); + } + + $mockObject = $this->getMockObjectGenerator()->getMock( + $originalClassName, + $methods, + ['', $options], + $mockClassName, + $callOriginalConstructor, + false, + false + ); + + $this->registerMockObject($mockObject); + + return $mockObject; + } + + /** + * Returns a mock object for the specified trait with all abstract methods + * of the trait mocked. Concrete methods to mock can be specified with the + * `$mockedMethods` parameter. + * + * @psalm-param trait-string $traitName + */ + protected function getMockForTrait(string $traitName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, array $mockedMethods = [], bool $cloneArguments = false): MockObject + { + $this->recordDoubledType($traitName); + + $mockObject = $this->getMockObjectGenerator()->getMockForTrait( + $traitName, + $arguments, + $mockClassName, + $callOriginalConstructor, + $callOriginalClone, + $callAutoload, + $mockedMethods, + $cloneArguments + ); + + $this->registerMockObject($mockObject); + + return $mockObject; + } + + /** + * Returns an object for the specified trait. + * + * @psalm-param trait-string $traitName + */ + protected function getObjectForTrait(string $traitName, array $arguments = [], string $traitClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true): object + { + $this->recordDoubledType($traitName); + + return $this->getMockObjectGenerator()->getObjectForTrait( + $traitName, + $traitClassName, + $callAutoload, + $callOriginalConstructor, + $arguments + ); + } + + /** + * @throws \Prophecy\Exception\Doubler\ClassNotFoundException + * @throws \Prophecy\Exception\Doubler\DoubleException + * @throws \Prophecy\Exception\Doubler\InterfaceNotFoundException + * + * @psalm-param class-string|null $classOrInterface + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/4141 + */ + protected function prophesize(?string $classOrInterface = null): ObjectProphecy + { + if (!class_exists(Prophet::class)) { + throw new Exception('This test uses TestCase::prophesize(), but phpspec/prophecy is not installed. Please run "composer require --dev phpspec/prophecy".'); + } + + $this->addWarning('PHPUnit\Framework\TestCase::prophesize() is deprecated and will be removed in PHPUnit 10. Please use the trait provided by phpspec/prophecy-phpunit.'); + + if (is_string($classOrInterface)) { + $this->recordDoubledType($classOrInterface); + } + + return $this->getProphet()->prophesize($classOrInterface); + } + + /** + * Creates a default TestResult object. + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + protected function createResult(): TestResult + { + return new TestResult; + } + + /** + * This method is called when a test method did not execute successfully. + * + * @throws Throwable + */ + protected function onNotSuccessfulTest(Throwable $t): void + { + throw $t; + } + + protected function recordDoubledType(string $originalClassName): void + { + $this->doubledTypes[] = $originalClassName; + } + + /** + * @throws Throwable + */ + private function verifyMockObjects(): void + { + foreach ($this->mockObjects as $mockObject) { + if ($mockObject->__phpunit_hasMatchers()) { + $this->numAssertions++; + } + + $mockObject->__phpunit_verify( + $this->shouldInvocationMockerBeReset($mockObject) + ); + } + + if ($this->prophet !== null) { + try { + $this->prophet->checkPredictions(); + } finally { + foreach ($this->prophet->getProphecies() as $objectProphecy) { + foreach ($objectProphecy->getMethodProphecies() as $methodProphecies) { + foreach ($methodProphecies as $methodProphecy) { + /* @var MethodProphecy $methodProphecy */ + $this->numAssertions += count($methodProphecy->getCheckedPredictions()); + } + } + } + } + } + } + + /** + * @throws SkippedTestError + * @throws SyntheticSkippedError + * @throws Warning + */ + private function checkRequirements(): void + { + if (!$this->name || !method_exists($this, $this->name)) { + return; + } + + $missingRequirements = TestUtil::getMissingRequirements( + static::class, + $this->name + ); + + if (!empty($missingRequirements)) { + $this->markTestSkipped(implode(PHP_EOL, $missingRequirements)); + } + } + + private function handleDependencies(): bool + { + if ([] === $this->dependencies || $this->inIsolation) { + return true; + } + + $passed = $this->result->passed(); + $passedKeys = array_keys($passed); + $numKeys = count($passedKeys); + + for ($i = 0; $i < $numKeys; $i++) { + $pos = strpos($passedKeys[$i], ' with data set'); + + if ($pos !== false) { + $passedKeys[$i] = substr($passedKeys[$i], 0, $pos); + } + } + + $passedKeys = array_flip(array_unique($passedKeys)); + + foreach ($this->dependencies as $dependency) { + if (!$dependency->isValid()) { + $this->markSkippedForNotSpecifyingDependency(); + + return false; + } + + if ($dependency->targetIsClass()) { + $dependencyClassName = $dependency->getTargetClassName(); + + if (array_search($dependencyClassName, $this->result->passedClasses(), true) === false) { + $this->markSkippedForMissingDependency($dependency); + + return false; + } + + continue; + } + + $dependencyTarget = $dependency->getTarget(); + + if (!isset($passedKeys[$dependencyTarget])) { + if (!$this->isCallableTestMethod($dependencyTarget)) { + $this->markWarningForUncallableDependency($dependency); + } else { + $this->markSkippedForMissingDependency($dependency); + } + + return false; + } + + if (isset($passed[$dependencyTarget])) { + if ($passed[$dependencyTarget]['size'] != \PHPUnit\Util\Test::UNKNOWN && + $this->getSize() != \PHPUnit\Util\Test::UNKNOWN && + $passed[$dependencyTarget]['size'] > $this->getSize()) { + $this->result->addError( + $this, + new SkippedTestError( + 'This test depends on a test that is larger than itself.' + ), + 0 + ); + + return false; + } + + if ($dependency->useDeepClone()) { + $deepCopy = new DeepCopy; + $deepCopy->skipUncloneable(false); + + $this->dependencyInput[$dependencyTarget] = $deepCopy->copy($passed[$dependencyTarget]['result']); + } elseif ($dependency->useShallowClone()) { + $this->dependencyInput[$dependencyTarget] = clone $passed[$dependencyTarget]['result']; + } else { + $this->dependencyInput[$dependencyTarget] = $passed[$dependencyTarget]['result']; + } + } else { + $this->dependencyInput[$dependencyTarget] = null; + } + } + + return true; + } + + private function markSkippedForNotSpecifyingDependency(): void + { + $this->status = BaseTestRunner::STATUS_SKIPPED; + + $this->result->startTest($this); + + $this->result->addError( + $this, + new SkippedTestError( + 'This method has an invalid @depends annotation.' + ), + 0 + ); + + $this->result->endTest($this, 0); + } + + private function markSkippedForMissingDependency(ExecutionOrderDependency $dependency): void + { + $this->status = BaseTestRunner::STATUS_SKIPPED; + + $this->result->startTest($this); + + $this->result->addError( + $this, + new SkippedTestError( + sprintf( + 'This test depends on "%s" to pass.', + $dependency->getTarget() + ) + ), + 0 + ); + + $this->result->endTest($this, 0); + } + + private function markWarningForUncallableDependency(ExecutionOrderDependency $dependency): void + { + $this->status = BaseTestRunner::STATUS_WARNING; + + $this->result->startTest($this); + + $this->result->addWarning( + $this, + new Warning( + sprintf( + 'This test depends on "%s" which does not exist.', + $dependency->getTarget() + ) + ), + 0 + ); + + $this->result->endTest($this, 0); + } + + /** + * Get the mock object generator, creating it if it doesn't exist. + */ + private function getMockObjectGenerator(): MockGenerator + { + if ($this->mockObjectGenerator === null) { + $this->mockObjectGenerator = new MockGenerator; + } + + return $this->mockObjectGenerator; + } + + private function startOutputBuffering(): void + { + ob_start(); + + $this->outputBufferingActive = true; + $this->outputBufferingLevel = ob_get_level(); + } + + /** + * @throws RiskyTestError + */ + private function stopOutputBuffering(): void + { + if (ob_get_level() !== $this->outputBufferingLevel) { + while (ob_get_level() >= $this->outputBufferingLevel) { + ob_end_clean(); + } + + throw new RiskyTestError( + 'Test code or tested code did not (only) close its own output buffers' + ); + } + + $this->output = ob_get_contents(); + + if ($this->outputCallback !== false) { + $this->output = (string) call_user_func($this->outputCallback, $this->output); + } + + ob_end_clean(); + + $this->outputBufferingActive = false; + $this->outputBufferingLevel = ob_get_level(); + } + + private function snapshotGlobalState(): void + { + if ($this->runTestInSeparateProcess || $this->inIsolation || + (!$this->backupGlobals && !$this->backupStaticAttributes)) { + return; + } + + $this->snapshot = $this->createGlobalStateSnapshot($this->backupGlobals === true); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws RiskyTestError + */ + private function restoreGlobalState(): void + { + if (!$this->snapshot instanceof Snapshot) { + return; + } + + if ($this->beStrictAboutChangesToGlobalState) { + try { + $this->compareGlobalStateSnapshots( + $this->snapshot, + $this->createGlobalStateSnapshot($this->backupGlobals === true) + ); + } catch (RiskyTestError $rte) { + // Intentionally left empty + } + } + + $restorer = new Restorer; + + if ($this->backupGlobals) { + $restorer->restoreGlobalVariables($this->snapshot); + } + + if ($this->backupStaticAttributes) { + $restorer->restoreStaticAttributes($this->snapshot); + } + + $this->snapshot = null; + + if (isset($rte)) { + throw $rte; + } + } + + private function createGlobalStateSnapshot(bool $backupGlobals): Snapshot + { + $excludeList = new ExcludeList; + + foreach ($this->backupGlobalsExcludeList as $globalVariable) { + $excludeList->addGlobalVariable($globalVariable); + } + + if (!empty($this->backupGlobalsBlacklist)) { + $this->addWarning('PHPUnit\Framework\TestCase::$backupGlobalsBlacklist is deprecated and will be removed in PHPUnit 10. Please use PHPUnit\Framework\TestCase::$backupGlobalsExcludeList instead.'); + + foreach ($this->backupGlobalsBlacklist as $globalVariable) { + $excludeList->addGlobalVariable($globalVariable); + } + } + + if (!defined('PHPUNIT_TESTSUITE')) { + $excludeList->addClassNamePrefix('PHPUnit'); + $excludeList->addClassNamePrefix('SebastianBergmann\CodeCoverage'); + $excludeList->addClassNamePrefix('SebastianBergmann\FileIterator'); + $excludeList->addClassNamePrefix('SebastianBergmann\Invoker'); + $excludeList->addClassNamePrefix('SebastianBergmann\Template'); + $excludeList->addClassNamePrefix('SebastianBergmann\Timer'); + $excludeList->addClassNamePrefix('Doctrine\Instantiator'); + $excludeList->addClassNamePrefix('Prophecy'); + $excludeList->addStaticAttribute(ComparatorFactory::class, 'instance'); + + foreach ($this->backupStaticAttributesExcludeList as $class => $attributes) { + foreach ($attributes as $attribute) { + $excludeList->addStaticAttribute($class, $attribute); + } + } + + if (!empty($this->backupStaticAttributesBlacklist)) { + $this->addWarning('PHPUnit\Framework\TestCase::$backupStaticAttributesBlacklist is deprecated and will be removed in PHPUnit 10. Please use PHPUnit\Framework\TestCase::$backupStaticAttributesExcludeList instead.'); + + foreach ($this->backupStaticAttributesBlacklist as $class => $attributes) { + foreach ($attributes as $attribute) { + $excludeList->addStaticAttribute($class, $attribute); + } + } + } + } + + return new Snapshot( + $excludeList, + $backupGlobals, + (bool) $this->backupStaticAttributes, + false, + false, + false, + false, + false, + false, + false + ); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws RiskyTestError + */ + private function compareGlobalStateSnapshots(Snapshot $before, Snapshot $after): void + { + $backupGlobals = $this->backupGlobals === null || $this->backupGlobals; + + if ($backupGlobals) { + $this->compareGlobalStateSnapshotPart( + $before->globalVariables(), + $after->globalVariables(), + "--- Global variables before the test\n+++ Global variables after the test\n" + ); + + $this->compareGlobalStateSnapshotPart( + $before->superGlobalVariables(), + $after->superGlobalVariables(), + "--- Super-global variables before the test\n+++ Super-global variables after the test\n" + ); + } + + if ($this->backupStaticAttributes) { + $this->compareGlobalStateSnapshotPart( + $before->staticAttributes(), + $after->staticAttributes(), + "--- Static attributes before the test\n+++ Static attributes after the test\n" + ); + } + } + + /** + * @throws RiskyTestError + */ + private function compareGlobalStateSnapshotPart(array $before, array $after, string $header): void + { + if ($before != $after) { + $differ = new Differ($header); + $exporter = new Exporter; + + $diff = $differ->diff( + $exporter->export($before), + $exporter->export($after) + ); + + throw new RiskyTestError( + $diff + ); + } + } + + private function getProphet(): Prophet + { + if ($this->prophet === null) { + $this->prophet = new Prophet; + } + + return $this->prophet; + } + + /** + * @throws \SebastianBergmann\ObjectEnumerator\InvalidArgumentException + */ + private function shouldInvocationMockerBeReset(MockObject $mock): bool + { + $enumerator = new Enumerator; + + foreach ($enumerator->enumerate($this->dependencyInput) as $object) { + if ($mock === $object) { + return false; + } + } + + if (!is_array($this->testResult) && !is_object($this->testResult)) { + return true; + } + + return !in_array($mock, $enumerator->enumerate($this->testResult), true); + } + + /** + * @throws \SebastianBergmann\ObjectEnumerator\InvalidArgumentException + * @throws \SebastianBergmann\ObjectReflector\InvalidArgumentException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + private function registerMockObjectsFromTestArguments(array $testArguments, array &$visited = []): void + { + if ($this->registerMockObjectsFromTestArgumentsRecursively) { + foreach ((new Enumerator)->enumerate($testArguments) as $object) { + if ($object instanceof MockObject) { + $this->registerMockObject($object); + } + } + } else { + foreach ($testArguments as $testArgument) { + if ($testArgument instanceof MockObject) { + $testArgument = Cloner::clone($testArgument); + + $this->registerMockObject($testArgument); + } elseif (is_array($testArgument) && !in_array($testArgument, $visited, true)) { + $visited[] = $testArgument; + + $this->registerMockObjectsFromTestArguments( + $testArgument, + $visited + ); + } + } + } + } + + private function setDoesNotPerformAssertionsFromAnnotation(): void + { + $annotations = TestUtil::parseTestMethodAnnotations( + static::class, + $this->name + ); + + if (isset($annotations['method']['doesNotPerformAssertions'])) { + $this->doesNotPerformAssertions = true; + } + } + + private function unregisterCustomComparators(): void + { + $factory = ComparatorFactory::getInstance(); + + foreach ($this->customComparators as $comparator) { + $factory->unregister($comparator); + } + + $this->customComparators = []; + } + + private function cleanupIniSettings(): void + { + foreach ($this->iniSettings as $varName => $oldValue) { + ini_set($varName, $oldValue); + } + + $this->iniSettings = []; + } + + private function cleanupLocaleSettings(): void + { + foreach ($this->locale as $category => $locale) { + setlocale($category, $locale); + } + + $this->locale = []; + } + + /** + * @throws Exception + */ + private function checkExceptionExpectations(Throwable $throwable): bool + { + $result = false; + + if ($this->expectedException !== null || $this->expectedExceptionCode !== null || $this->expectedExceptionMessage !== null || $this->expectedExceptionMessageRegExp !== null) { + $result = true; + } + + if ($throwable instanceof Exception) { + $result = false; + } + + if (is_string($this->expectedException)) { + try { + $reflector = new ReflectionClass($this->expectedException); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + if ($this->expectedException === 'PHPUnit\Framework\Exception' || + $this->expectedException === '\PHPUnit\Framework\Exception' || + $reflector->isSubclassOf(Exception::class)) { + $result = true; + } + } + + return $result; + } + + private function runInSeparateProcess(): bool + { + return ($this->runTestInSeparateProcess || $this->runClassInSeparateProcess) && + !$this->inIsolation && !$this instanceof PhptTestCase; + } + + private function isCallableTestMethod(string $dependency): bool + { + [$className, $methodName] = explode('::', $dependency); + + if (!class_exists($className)) { + return false; + } + + try { + $class = new ReflectionClass($className); + } catch (ReflectionException $e) { + return false; + } + + if (!$class->isSubclassOf(__CLASS__)) { + return false; + } + + if (!$class->hasMethod($methodName)) { + return false; + } + + try { + $method = $class->getMethod($methodName); + } catch (ReflectionException $e) { + return false; + } + + return TestUtil::isTestMethod($method); + } + + /** + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return MockObject&RealInstanceType + */ + private function createMockObject(string $originalClassName): MockObject + { + return $this->getMockBuilder($originalClassName) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->disableArgumentCloning() + ->disallowMockingUnknownTypes() + ->getMock(); + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/TestFailure.php b/vendor/phpunit/phpunit/src/Framework/TestFailure.php new file mode 100644 index 00000000..0764bc78 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/TestFailure.php @@ -0,0 +1,155 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function get_class; +use function sprintf; +use function trim; +use PHPUnit\Framework\Error\Error; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFailure +{ + /** + * @var null|Test + */ + private $failedTest; + + /** + * @var Throwable + */ + private $thrownException; + + /** + * @var string + */ + private $testName; + + /** + * Returns a description for an exception. + */ + public static function exceptionToString(Throwable $e): string + { + if ($e instanceof SelfDescribing) { + $buffer = $e->toString(); + + if ($e instanceof ExpectationFailedException && $e->getComparisonFailure()) { + $buffer .= $e->getComparisonFailure()->getDiff(); + } + + if ($e instanceof PHPTAssertionFailedError) { + $buffer .= $e->getDiff(); + } + + if (!empty($buffer)) { + $buffer = trim($buffer) . "\n"; + } + + return $buffer; + } + + if ($e instanceof Error) { + return $e->getMessage() . "\n"; + } + + if ($e instanceof ExceptionWrapper) { + return $e->getClassName() . ': ' . $e->getMessage() . "\n"; + } + + return get_class($e) . ': ' . $e->getMessage() . "\n"; + } + + /** + * Constructs a TestFailure with the given test and exception. + */ + public function __construct(Test $failedTest, Throwable $t) + { + if ($failedTest instanceof SelfDescribing) { + $this->testName = $failedTest->toString(); + } else { + $this->testName = get_class($failedTest); + } + + if (!$failedTest instanceof TestCase || !$failedTest->isInIsolation()) { + $this->failedTest = $failedTest; + } + + $this->thrownException = $t; + } + + /** + * Returns a short description of the failure. + */ + public function toString(): string + { + return sprintf( + '%s: %s', + $this->testName, + $this->thrownException->getMessage() + ); + } + + /** + * Returns a description for the thrown exception. + */ + public function getExceptionAsString(): string + { + return self::exceptionToString($this->thrownException); + } + + /** + * Returns the name of the failing test (including data set, if any). + */ + public function getTestName(): string + { + return $this->testName; + } + + /** + * Returns the failing test. + * + * Note: The test object is not set when the test is executed in process + * isolation. + * + * @see Exception + */ + public function failedTest(): ?Test + { + return $this->failedTest; + } + + /** + * Gets the thrown exception. + */ + public function thrownException(): Throwable + { + return $this->thrownException; + } + + /** + * Returns the exception's message. + */ + public function exceptionMessage(): string + { + return $this->thrownException()->getMessage(); + } + + /** + * Returns true if the thrown exception + * is of type AssertionFailedError. + */ + public function isFailure(): bool + { + return $this->thrownException() instanceof AssertionFailedError; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/TestListener.php b/vendor/phpunit/phpunit/src/Framework/TestListener.php new file mode 100644 index 00000000..eade600f --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/TestListener.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use Throwable; + +/** + * This interface, as well as the associated mechanism for extending PHPUnit, + * will be removed in PHPUnit 10. There is no alternative available in this + * version of PHPUnit. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated + * @see https://github.com/sebastianbergmann/phpunit/issues/4676 + */ +interface TestListener +{ + public function addError(Test $test, Throwable $t, float $time): void; + + public function addWarning(Test $test, Warning $e, float $time): void; + + public function addFailure(Test $test, AssertionFailedError $e, float $time): void; + + public function addIncompleteTest(Test $test, Throwable $t, float $time): void; + + public function addRiskyTest(Test $test, Throwable $t, float $time): void; + + public function addSkippedTest(Test $test, Throwable $t, float $time): void; + + public function startTestSuite(TestSuite $suite): void; + + public function endTestSuite(TestSuite $suite): void; + + public function startTest(Test $test): void; + + public function endTest(Test $test, float $time): void; +} diff --git a/vendor/phpunit/phpunit/src/Framework/TestListenerDefaultImplementation.php b/vendor/phpunit/phpunit/src/Framework/TestListenerDefaultImplementation.php new file mode 100644 index 00000000..5731d98d --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/TestListenerDefaultImplementation.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use Throwable; + +/** + * @deprecated The `TestListener` interface is deprecated + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +trait TestListenerDefaultImplementation +{ + public function addError(Test $test, Throwable $t, float $time): void + { + } + + public function addWarning(Test $test, Warning $e, float $time): void + { + } + + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + } + + public function addIncompleteTest(Test $test, Throwable $t, float $time): void + { + } + + public function addRiskyTest(Test $test, Throwable $t, float $time): void + { + } + + public function addSkippedTest(Test $test, Throwable $t, float $time): void + { + } + + public function startTestSuite(TestSuite $suite): void + { + } + + public function endTestSuite(TestSuite $suite): void + { + } + + public function startTest(Test $test): void + { + } + + public function endTest(Test $test, float $time): void + { + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/TestResult.php b/vendor/phpunit/phpunit/src/Framework/TestResult.php new file mode 100644 index 00000000..4fde29fa --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/TestResult.php @@ -0,0 +1,1322 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use const PHP_EOL; +use function class_exists; +use function count; +use function extension_loaded; +use function function_exists; +use function get_class; +use function sprintf; +use function xdebug_get_monitored_functions; +use function xdebug_is_debugger_active; +use function xdebug_start_function_monitor; +use function xdebug_stop_function_monitor; +use AssertionError; +use Countable; +use Error; +use PHPUnit\Util\ErrorHandler; +use PHPUnit\Util\ExcludeList; +use PHPUnit\Util\Printer; +use PHPUnit\Util\Test as TestUtil; +use ReflectionClass; +use ReflectionException; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Exception as OriginalCodeCoverageException; +use SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException; +use SebastianBergmann\Invoker\Invoker; +use SebastianBergmann\Invoker\TimeoutException; +use SebastianBergmann\ResourceOperations\ResourceOperations; +use SebastianBergmann\Timer\Timer; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestResult implements Countable +{ + /** + * @var array + */ + private $passed = []; + + /** + * @var array + */ + private $passedTestClasses = []; + + /** + * @var bool + */ + private $currentTestSuiteFailed = false; + + /** + * @var TestFailure[] + */ + private $errors = []; + + /** + * @var TestFailure[] + */ + private $failures = []; + + /** + * @var TestFailure[] + */ + private $warnings = []; + + /** + * @var TestFailure[] + */ + private $notImplemented = []; + + /** + * @var TestFailure[] + */ + private $risky = []; + + /** + * @var TestFailure[] + */ + private $skipped = []; + + /** + * @deprecated Use the `TestHook` interfaces instead + * + * @var TestListener[] + */ + private $listeners = []; + + /** + * @var int + */ + private $runTests = 0; + + /** + * @var float + */ + private $time = 0; + + /** + * Code Coverage information. + * + * @var CodeCoverage + */ + private $codeCoverage; + + /** + * @var bool + */ + private $convertDeprecationsToExceptions = false; + + /** + * @var bool + */ + private $convertErrorsToExceptions = true; + + /** + * @var bool + */ + private $convertNoticesToExceptions = true; + + /** + * @var bool + */ + private $convertWarningsToExceptions = true; + + /** + * @var bool + */ + private $stop = false; + + /** + * @var bool + */ + private $stopOnError = false; + + /** + * @var bool + */ + private $stopOnFailure = false; + + /** + * @var bool + */ + private $stopOnWarning = false; + + /** + * @var bool + */ + private $beStrictAboutTestsThatDoNotTestAnything = true; + + /** + * @var bool + */ + private $beStrictAboutOutputDuringTests = false; + + /** + * @var bool + */ + private $beStrictAboutTodoAnnotatedTests = false; + + /** + * @var bool + */ + private $beStrictAboutResourceUsageDuringSmallTests = false; + + /** + * @var bool + */ + private $enforceTimeLimit = false; + + /** + * @var bool + */ + private $forceCoversAnnotation = false; + + /** + * @var int + */ + private $timeoutForSmallTests = 1; + + /** + * @var int + */ + private $timeoutForMediumTests = 10; + + /** + * @var int + */ + private $timeoutForLargeTests = 60; + + /** + * @var bool + */ + private $stopOnRisky = false; + + /** + * @var bool + */ + private $stopOnIncomplete = false; + + /** + * @var bool + */ + private $stopOnSkipped = false; + + /** + * @var bool + */ + private $lastTestFailed = false; + + /** + * @var int + */ + private $defaultTimeLimit = 0; + + /** + * @var bool + */ + private $stopOnDefect = false; + + /** + * @var bool + */ + private $registerMockObjectsFromTestArgumentsRecursively = false; + + /** + * @deprecated Use the `TestHook` interfaces instead + * + * @codeCoverageIgnore + * + * Registers a TestListener. + */ + public function addListener(TestListener $listener): void + { + $this->listeners[] = $listener; + } + + /** + * @deprecated Use the `TestHook` interfaces instead + * + * @codeCoverageIgnore + * + * Unregisters a TestListener. + */ + public function removeListener(TestListener $listener): void + { + foreach ($this->listeners as $key => $_listener) { + if ($listener === $_listener) { + unset($this->listeners[$key]); + } + } + } + + /** + * @deprecated Use the `TestHook` interfaces instead + * + * @codeCoverageIgnore + * + * Flushes all flushable TestListeners. + */ + public function flushListeners(): void + { + foreach ($this->listeners as $listener) { + if ($listener instanceof Printer) { + $listener->flush(); + } + } + } + + /** + * Adds an error to the list of errors. + */ + public function addError(Test $test, Throwable $t, float $time): void + { + if ($t instanceof RiskyTestError) { + $this->recordRisky($test, $t); + + $notifyMethod = 'addRiskyTest'; + + if ($test instanceof TestCase) { + $test->markAsRisky(); + } + + if ($this->stopOnRisky || $this->stopOnDefect) { + $this->stop(); + } + } elseif ($t instanceof IncompleteTest) { + $this->recordNotImplemented($test, $t); + + $notifyMethod = 'addIncompleteTest'; + + if ($this->stopOnIncomplete) { + $this->stop(); + } + } elseif ($t instanceof SkippedTest) { + $this->recordSkipped($test, $t); + + $notifyMethod = 'addSkippedTest'; + + if ($this->stopOnSkipped) { + $this->stop(); + } + } else { + $this->recordError($test, $t); + + $notifyMethod = 'addError'; + + if ($this->stopOnError || $this->stopOnFailure) { + $this->stop(); + } + } + + // @see https://github.com/sebastianbergmann/phpunit/issues/1953 + if ($t instanceof Error) { + $t = new ExceptionWrapper($t); + } + + foreach ($this->listeners as $listener) { + $listener->{$notifyMethod}($test, $t, $time); + } + + $this->lastTestFailed = true; + $this->time += $time; + } + + /** + * Adds a warning to the list of warnings. + * The passed in exception caused the warning. + */ + public function addWarning(Test $test, Warning $e, float $time): void + { + if ($this->stopOnWarning || $this->stopOnDefect) { + $this->stop(); + } + + $this->recordWarning($test, $e); + + foreach ($this->listeners as $listener) { + $listener->addWarning($test, $e, $time); + } + + $this->time += $time; + } + + /** + * Adds a failure to the list of failures. + * The passed in exception caused the failure. + */ + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + if ($e instanceof RiskyTestError || $e instanceof OutputError) { + $this->recordRisky($test, $e); + + $notifyMethod = 'addRiskyTest'; + + if ($test instanceof TestCase) { + $test->markAsRisky(); + } + + if ($this->stopOnRisky || $this->stopOnDefect) { + $this->stop(); + } + } elseif ($e instanceof IncompleteTest) { + $this->recordNotImplemented($test, $e); + + $notifyMethod = 'addIncompleteTest'; + + if ($this->stopOnIncomplete) { + $this->stop(); + } + } elseif ($e instanceof SkippedTest) { + $this->recordSkipped($test, $e); + + $notifyMethod = 'addSkippedTest'; + + if ($this->stopOnSkipped) { + $this->stop(); + } + } else { + $this->failures[] = new TestFailure($test, $e); + $notifyMethod = 'addFailure'; + + if ($this->stopOnFailure || $this->stopOnDefect) { + $this->stop(); + } + } + + foreach ($this->listeners as $listener) { + $listener->{$notifyMethod}($test, $e, $time); + } + + $this->lastTestFailed = true; + $this->time += $time; + } + + /** + * Informs the result that a test suite will be started. + */ + public function startTestSuite(TestSuite $suite): void + { + $this->currentTestSuiteFailed = false; + + foreach ($this->listeners as $listener) { + $listener->startTestSuite($suite); + } + } + + /** + * Informs the result that a test suite was completed. + */ + public function endTestSuite(TestSuite $suite): void + { + if (!$this->currentTestSuiteFailed) { + $this->passedTestClasses[] = $suite->getName(); + } + + foreach ($this->listeners as $listener) { + $listener->endTestSuite($suite); + } + } + + /** + * Informs the result that a test will be started. + */ + public function startTest(Test $test): void + { + $this->lastTestFailed = false; + $this->runTests += count($test); + + foreach ($this->listeners as $listener) { + $listener->startTest($test); + } + } + + /** + * Informs the result that a test was completed. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function endTest(Test $test, float $time): void + { + foreach ($this->listeners as $listener) { + $listener->endTest($test, $time); + } + + if (!$this->lastTestFailed && $test instanceof TestCase) { + $class = get_class($test); + $key = $class . '::' . $test->getName(); + + $this->passed[$key] = [ + 'result' => $test->getResult(), + 'size' => TestUtil::getSize( + $class, + $test->getName(false) + ), + ]; + + $this->time += $time; + } + + if ($this->lastTestFailed && $test instanceof TestCase) { + $this->currentTestSuiteFailed = true; + } + } + + /** + * Returns true if no risky test occurred. + */ + public function allHarmless(): bool + { + return $this->riskyCount() === 0; + } + + /** + * Gets the number of risky tests. + */ + public function riskyCount(): int + { + return count($this->risky); + } + + /** + * Returns true if no incomplete test occurred. + */ + public function allCompletelyImplemented(): bool + { + return $this->notImplementedCount() === 0; + } + + /** + * Gets the number of incomplete tests. + */ + public function notImplementedCount(): int + { + return count($this->notImplemented); + } + + /** + * Returns an array of TestFailure objects for the risky tests. + * + * @return TestFailure[] + */ + public function risky(): array + { + return $this->risky; + } + + /** + * Returns an array of TestFailure objects for the incomplete tests. + * + * @return TestFailure[] + */ + public function notImplemented(): array + { + return $this->notImplemented; + } + + /** + * Returns true if no test has been skipped. + */ + public function noneSkipped(): bool + { + return $this->skippedCount() === 0; + } + + /** + * Gets the number of skipped tests. + */ + public function skippedCount(): int + { + return count($this->skipped); + } + + /** + * Returns an array of TestFailure objects for the skipped tests. + * + * @return TestFailure[] + */ + public function skipped(): array + { + return $this->skipped; + } + + /** + * Gets the number of detected errors. + */ + public function errorCount(): int + { + return count($this->errors); + } + + /** + * Returns an array of TestFailure objects for the errors. + * + * @return TestFailure[] + */ + public function errors(): array + { + return $this->errors; + } + + /** + * Gets the number of detected failures. + */ + public function failureCount(): int + { + return count($this->failures); + } + + /** + * Returns an array of TestFailure objects for the failures. + * + * @return TestFailure[] + */ + public function failures(): array + { + return $this->failures; + } + + /** + * Gets the number of detected warnings. + */ + public function warningCount(): int + { + return count($this->warnings); + } + + /** + * Returns an array of TestFailure objects for the warnings. + * + * @return TestFailure[] + */ + public function warnings(): array + { + return $this->warnings; + } + + /** + * Returns the names of the tests that have passed. + */ + public function passed(): array + { + return $this->passed; + } + + /** + * Returns the names of the TestSuites that have passed. + * + * This enables @depends-annotations for TestClassName::class + */ + public function passedClasses(): array + { + return $this->passedTestClasses; + } + + /** + * Returns whether code coverage information should be collected. + */ + public function getCollectCodeCoverageInformation(): bool + { + return $this->codeCoverage !== null; + } + + /** + * Runs a TestCase. + * + * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws CodeCoverageException + * @throws UnintentionallyCoveredCodeException + */ + public function run(Test $test): void + { + Assert::resetCount(); + + $size = TestUtil::UNKNOWN; + + if ($test instanceof TestCase) { + $test->setRegisterMockObjectsFromTestArgumentsRecursively( + $this->registerMockObjectsFromTestArgumentsRecursively + ); + + $isAnyCoverageRequired = TestUtil::requiresCodeCoverageDataCollection($test); + $size = $test->getSize(); + } + + $error = false; + $failure = false; + $warning = false; + $incomplete = false; + $risky = false; + $skipped = false; + + $this->startTest($test); + + if ($this->convertDeprecationsToExceptions || $this->convertErrorsToExceptions || $this->convertNoticesToExceptions || $this->convertWarningsToExceptions) { + $errorHandler = new ErrorHandler( + $this->convertDeprecationsToExceptions, + $this->convertErrorsToExceptions, + $this->convertNoticesToExceptions, + $this->convertWarningsToExceptions + ); + + $errorHandler->register(); + } + + $collectCodeCoverage = $this->codeCoverage !== null && + !$test instanceof ErrorTestCase && + !$test instanceof WarningTestCase && + $isAnyCoverageRequired; + + if ($collectCodeCoverage) { + $this->codeCoverage->start($test); + } + + $monitorFunctions = $this->beStrictAboutResourceUsageDuringSmallTests && + !$test instanceof ErrorTestCase && + !$test instanceof WarningTestCase && + $size === TestUtil::SMALL && + function_exists('xdebug_start_function_monitor'); + + if ($monitorFunctions) { + /* @noinspection ForgottenDebugOutputInspection */ + xdebug_start_function_monitor(ResourceOperations::getFunctions()); + } + + $timer = new Timer; + $timer->start(); + + try { + $invoker = new Invoker; + + if (!$test instanceof ErrorTestCase && + !$test instanceof WarningTestCase && + $this->shouldTimeLimitBeEnforced($size) && + $invoker->canInvokeWithTimeout()) { + switch ($size) { + case TestUtil::SMALL: + $_timeout = $this->timeoutForSmallTests; + + break; + + case TestUtil::MEDIUM: + $_timeout = $this->timeoutForMediumTests; + + break; + + case TestUtil::LARGE: + $_timeout = $this->timeoutForLargeTests; + + break; + + default: + $_timeout = $this->defaultTimeLimit; + } + + $invoker->invoke([$test, 'runBare'], [], $_timeout); + } else { + $test->runBare(); + } + } catch (TimeoutException $e) { + $this->addFailure( + $test, + new RiskyTestError( + $e->getMessage() + ), + $_timeout + ); + + $risky = true; + } catch (AssertionFailedError $e) { + $failure = true; + + if ($e instanceof RiskyTestError) { + $risky = true; + } elseif ($e instanceof IncompleteTestError) { + $incomplete = true; + } elseif ($e instanceof SkippedTestError) { + $skipped = true; + } + } catch (AssertionError $e) { + $test->addToAssertionCount(1); + + $failure = true; + $frame = $e->getTrace()[0]; + + $e = new AssertionFailedError( + sprintf( + '%s in %s:%s', + $e->getMessage(), + $frame['file'] ?? $e->getFile(), + $frame['line'] ?? $e->getLine() + ), + 0, + $e + ); + } catch (Warning $e) { + $warning = true; + } catch (Exception $e) { + $error = true; + } catch (Throwable $e) { + $e = new ExceptionWrapper($e); + $error = true; + } + + $time = $timer->stop()->asSeconds(); + + $test->addToAssertionCount(Assert::getCount()); + + if ($monitorFunctions) { + $excludeList = new ExcludeList; + + /** @noinspection ForgottenDebugOutputInspection */ + $functions = xdebug_get_monitored_functions(); + + /* @noinspection ForgottenDebugOutputInspection */ + xdebug_stop_function_monitor(); + + foreach ($functions as $function) { + if (!$excludeList->isExcluded($function['filename'])) { + $this->addFailure( + $test, + new RiskyTestError( + sprintf( + '%s() used in %s:%s', + $function['function'], + $function['filename'], + $function['lineno'] + ) + ), + $time + ); + } + } + } + + if ($this->beStrictAboutTestsThatDoNotTestAnything && + $test->getNumAssertions() === 0) { + $risky = true; + } + + if ($this->forceCoversAnnotation && !$error && !$failure && !$warning && !$incomplete && !$skipped && !$risky) { + $annotations = TestUtil::parseTestMethodAnnotations( + get_class($test), + $test->getName(false) + ); + + if (!isset($annotations['class']['covers']) && + !isset($annotations['method']['covers']) && + !isset($annotations['class']['coversNothing']) && + !isset($annotations['method']['coversNothing'])) { + $this->addFailure( + $test, + new MissingCoversAnnotationException( + 'This test does not have a @covers annotation but is expected to have one' + ), + $time + ); + + $risky = true; + } + } + + if ($collectCodeCoverage) { + $append = !$risky && !$incomplete && !$skipped; + $linesToBeCovered = []; + $linesToBeUsed = []; + + if ($append && $test instanceof TestCase) { + try { + $linesToBeCovered = TestUtil::getLinesToBeCovered( + get_class($test), + $test->getName(false) + ); + + $linesToBeUsed = TestUtil::getLinesToBeUsed( + get_class($test), + $test->getName(false) + ); + } catch (InvalidCoversTargetException $cce) { + $this->addWarning( + $test, + new Warning( + $cce->getMessage() + ), + $time + ); + } + } + + try { + $this->codeCoverage->stop( + $append, + $linesToBeCovered, + $linesToBeUsed + ); + } catch (UnintentionallyCoveredCodeException $cce) { + $unintentionallyCoveredCodeError = new UnintentionallyCoveredCodeError( + 'This test executed code that is not listed as code to be covered or used:' . + PHP_EOL . $cce->getMessage() + ); + } catch (OriginalCodeCoverageException $cce) { + $error = true; + + $e = $e ?? $cce; + } + } + + if (isset($errorHandler)) { + $errorHandler->unregister(); + + unset($errorHandler); + } + + if ($error) { + $this->addError($test, $e, $time); + } elseif ($failure) { + $this->addFailure($test, $e, $time); + } elseif ($warning) { + $this->addWarning($test, $e, $time); + } elseif (isset($unintentionallyCoveredCodeError)) { + $this->addFailure( + $test, + $unintentionallyCoveredCodeError, + $time + ); + } elseif ($this->beStrictAboutTestsThatDoNotTestAnything && + !$test->doesNotPerformAssertions() && + $test->getNumAssertions() === 0) { + try { + $reflected = new ReflectionClass($test); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + $name = $test->getName(false); + + if ($name && $reflected->hasMethod($name)) { + try { + $reflected = $reflected->getMethod($name); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + $this->addFailure( + $test, + new RiskyTestError( + sprintf( + "This test did not perform any assertions\n\n%s:%d", + $reflected->getFileName(), + $reflected->getStartLine() + ) + ), + $time + ); + } elseif ($this->beStrictAboutTestsThatDoNotTestAnything && + $test->doesNotPerformAssertions() && + $test->getNumAssertions() > 0) { + $this->addFailure( + $test, + new RiskyTestError( + sprintf( + 'This test is annotated with "@doesNotPerformAssertions" but performed %d assertions', + $test->getNumAssertions() + ) + ), + $time + ); + } elseif ($this->beStrictAboutOutputDuringTests && $test->hasOutput()) { + $this->addFailure( + $test, + new OutputError( + sprintf( + 'This test printed output: %s', + $test->getActualOutput() + ) + ), + $time + ); + } elseif ($this->beStrictAboutTodoAnnotatedTests && $test instanceof TestCase) { + $annotations = TestUtil::parseTestMethodAnnotations( + get_class($test), + $test->getName(false) + ); + + if (isset($annotations['method']['todo'])) { + $this->addFailure( + $test, + new RiskyTestError( + 'Test method is annotated with @todo' + ), + $time + ); + } + } + + $this->endTest($test, $time); + } + + /** + * Gets the number of run tests. + */ + public function count(): int + { + return $this->runTests; + } + + /** + * Checks whether the test run should stop. + */ + public function shouldStop(): bool + { + return $this->stop; + } + + /** + * Marks that the test run should stop. + */ + public function stop(): void + { + $this->stop = true; + } + + /** + * Returns the code coverage object. + */ + public function getCodeCoverage(): ?CodeCoverage + { + return $this->codeCoverage; + } + + /** + * Sets the code coverage object. + */ + public function setCodeCoverage(CodeCoverage $codeCoverage): void + { + $this->codeCoverage = $codeCoverage; + } + + /** + * Enables or disables the deprecation-to-exception conversion. + */ + public function convertDeprecationsToExceptions(bool $flag): void + { + $this->convertDeprecationsToExceptions = $flag; + } + + /** + * Returns the deprecation-to-exception conversion setting. + */ + public function getConvertDeprecationsToExceptions(): bool + { + return $this->convertDeprecationsToExceptions; + } + + /** + * Enables or disables the error-to-exception conversion. + */ + public function convertErrorsToExceptions(bool $flag): void + { + $this->convertErrorsToExceptions = $flag; + } + + /** + * Returns the error-to-exception conversion setting. + */ + public function getConvertErrorsToExceptions(): bool + { + return $this->convertErrorsToExceptions; + } + + /** + * Enables or disables the notice-to-exception conversion. + */ + public function convertNoticesToExceptions(bool $flag): void + { + $this->convertNoticesToExceptions = $flag; + } + + /** + * Returns the notice-to-exception conversion setting. + */ + public function getConvertNoticesToExceptions(): bool + { + return $this->convertNoticesToExceptions; + } + + /** + * Enables or disables the warning-to-exception conversion. + */ + public function convertWarningsToExceptions(bool $flag): void + { + $this->convertWarningsToExceptions = $flag; + } + + /** + * Returns the warning-to-exception conversion setting. + */ + public function getConvertWarningsToExceptions(): bool + { + return $this->convertWarningsToExceptions; + } + + /** + * Enables or disables the stopping when an error occurs. + */ + public function stopOnError(bool $flag): void + { + $this->stopOnError = $flag; + } + + /** + * Enables or disables the stopping when a failure occurs. + */ + public function stopOnFailure(bool $flag): void + { + $this->stopOnFailure = $flag; + } + + /** + * Enables or disables the stopping when a warning occurs. + */ + public function stopOnWarning(bool $flag): void + { + $this->stopOnWarning = $flag; + } + + public function beStrictAboutTestsThatDoNotTestAnything(bool $flag): void + { + $this->beStrictAboutTestsThatDoNotTestAnything = $flag; + } + + public function isStrictAboutTestsThatDoNotTestAnything(): bool + { + return $this->beStrictAboutTestsThatDoNotTestAnything; + } + + public function beStrictAboutOutputDuringTests(bool $flag): void + { + $this->beStrictAboutOutputDuringTests = $flag; + } + + public function isStrictAboutOutputDuringTests(): bool + { + return $this->beStrictAboutOutputDuringTests; + } + + public function beStrictAboutResourceUsageDuringSmallTests(bool $flag): void + { + $this->beStrictAboutResourceUsageDuringSmallTests = $flag; + } + + public function isStrictAboutResourceUsageDuringSmallTests(): bool + { + return $this->beStrictAboutResourceUsageDuringSmallTests; + } + + public function enforceTimeLimit(bool $flag): void + { + $this->enforceTimeLimit = $flag; + } + + public function enforcesTimeLimit(): bool + { + return $this->enforceTimeLimit; + } + + public function beStrictAboutTodoAnnotatedTests(bool $flag): void + { + $this->beStrictAboutTodoAnnotatedTests = $flag; + } + + public function isStrictAboutTodoAnnotatedTests(): bool + { + return $this->beStrictAboutTodoAnnotatedTests; + } + + public function forceCoversAnnotation(): void + { + $this->forceCoversAnnotation = true; + } + + public function forcesCoversAnnotation(): bool + { + return $this->forceCoversAnnotation; + } + + /** + * Enables or disables the stopping for risky tests. + */ + public function stopOnRisky(bool $flag): void + { + $this->stopOnRisky = $flag; + } + + /** + * Enables or disables the stopping for incomplete tests. + */ + public function stopOnIncomplete(bool $flag): void + { + $this->stopOnIncomplete = $flag; + } + + /** + * Enables or disables the stopping for skipped tests. + */ + public function stopOnSkipped(bool $flag): void + { + $this->stopOnSkipped = $flag; + } + + /** + * Enables or disables the stopping for defects: error, failure, warning. + */ + public function stopOnDefect(bool $flag): void + { + $this->stopOnDefect = $flag; + } + + /** + * Returns the time spent running the tests. + */ + public function time(): float + { + return $this->time; + } + + /** + * Returns whether the entire test was successful or not. + */ + public function wasSuccessful(): bool + { + return $this->wasSuccessfulIgnoringWarnings() && empty($this->warnings); + } + + public function wasSuccessfulIgnoringWarnings(): bool + { + return empty($this->errors) && empty($this->failures); + } + + public function wasSuccessfulAndNoTestIsRiskyOrSkippedOrIncomplete(): bool + { + return $this->wasSuccessful() && $this->allHarmless() && $this->allCompletelyImplemented() && $this->noneSkipped(); + } + + /** + * Sets the default timeout for tests. + */ + public function setDefaultTimeLimit(int $timeout): void + { + $this->defaultTimeLimit = $timeout; + } + + /** + * Sets the timeout for small tests. + */ + public function setTimeoutForSmallTests(int $timeout): void + { + $this->timeoutForSmallTests = $timeout; + } + + /** + * Sets the timeout for medium tests. + */ + public function setTimeoutForMediumTests(int $timeout): void + { + $this->timeoutForMediumTests = $timeout; + } + + /** + * Sets the timeout for large tests. + */ + public function setTimeoutForLargeTests(int $timeout): void + { + $this->timeoutForLargeTests = $timeout; + } + + /** + * Returns the set timeout for large tests. + */ + public function getTimeoutForLargeTests(): int + { + return $this->timeoutForLargeTests; + } + + public function setRegisterMockObjectsFromTestArgumentsRecursively(bool $flag): void + { + $this->registerMockObjectsFromTestArgumentsRecursively = $flag; + } + + private function recordError(Test $test, Throwable $t): void + { + $this->errors[] = new TestFailure($test, $t); + } + + private function recordNotImplemented(Test $test, Throwable $t): void + { + $this->notImplemented[] = new TestFailure($test, $t); + } + + private function recordRisky(Test $test, Throwable $t): void + { + $this->risky[] = new TestFailure($test, $t); + } + + private function recordSkipped(Test $test, Throwable $t): void + { + $this->skipped[] = new TestFailure($test, $t); + } + + private function recordWarning(Test $test, Throwable $t): void + { + $this->warnings[] = new TestFailure($test, $t); + } + + private function shouldTimeLimitBeEnforced(int $size): bool + { + if (!$this->enforceTimeLimit) { + return false; + } + + if (!(($this->defaultTimeLimit || $size !== TestUtil::UNKNOWN))) { + return false; + } + + if (!extension_loaded('pcntl')) { + return false; + } + + if (!class_exists(Invoker::class)) { + return false; + } + + if (extension_loaded('xdebug') && xdebug_is_debugger_active()) { + return false; + } + + return true; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/TestSuite.php b/vendor/phpunit/phpunit/src/Framework/TestSuite.php new file mode 100644 index 00000000..e7cef62e --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/TestSuite.php @@ -0,0 +1,921 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use const PHP_EOL; +use function array_keys; +use function array_map; +use function array_merge; +use function array_slice; +use function array_unique; +use function basename; +use function call_user_func; +use function class_exists; +use function count; +use function dirname; +use function get_declared_classes; +use function implode; +use function is_bool; +use function is_callable; +use function is_file; +use function is_object; +use function is_string; +use function method_exists; +use function preg_match; +use function preg_quote; +use function sprintf; +use function strpos; +use function substr; +use Iterator; +use IteratorAggregate; +use PHPUnit\Runner\BaseTestRunner; +use PHPUnit\Runner\Filter\Factory; +use PHPUnit\Runner\PhptTestCase; +use PHPUnit\Util\FileLoader; +use PHPUnit\Util\Reflection; +use PHPUnit\Util\Test as TestUtil; +use ReflectionClass; +use ReflectionException; +use ReflectionMethod; +use Throwable; + +/** + * @template-implements IteratorAggregate + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class TestSuite implements IteratorAggregate, Reorderable, SelfDescribing, Test +{ + /** + * Enable or disable the backup and restoration of the $GLOBALS array. + * + * @var bool + */ + protected $backupGlobals; + + /** + * Enable or disable the backup and restoration of static attributes. + * + * @var bool + */ + protected $backupStaticAttributes; + + /** + * @var bool + */ + protected $runTestInSeparateProcess = false; + + /** + * The name of the test suite. + * + * @var string + */ + protected $name = ''; + + /** + * The test groups of the test suite. + * + * @psalm-var array> + */ + protected $groups = []; + + /** + * The tests in the test suite. + * + * @var Test[] + */ + protected $tests = []; + + /** + * The number of tests in the test suite. + * + * @var int + */ + protected $numTests = -1; + + /** + * @var bool + */ + protected $testCase = false; + + /** + * @var string[] + */ + protected $foundClasses = []; + + /** + * @var null|list + */ + protected $providedTests; + + /** + * @var null|list + */ + protected $requiredTests; + + /** + * @var bool + */ + private $beStrictAboutChangesToGlobalState; + + /** + * @var Factory + */ + private $iteratorFilter; + + /** + * @var int + */ + private $declaredClassesPointer; + + /** + * @psalm-var array + */ + private $warnings = []; + + /** + * Constructs a new TestSuite. + * + * - PHPUnit\Framework\TestSuite() constructs an empty TestSuite. + * + * - PHPUnit\Framework\TestSuite(ReflectionClass) constructs a + * TestSuite from the given class. + * + * - PHPUnit\Framework\TestSuite(ReflectionClass, String) + * constructs a TestSuite from the given class with the given + * name. + * + * - PHPUnit\Framework\TestSuite(String) either constructs a + * TestSuite from the given class (if the passed string is the + * name of an existing class) or constructs an empty TestSuite + * with the given name. + * + * @param ReflectionClass|string $theClass + * + * @throws Exception + */ + public function __construct($theClass = '', string $name = '') + { + if (!is_string($theClass) && !$theClass instanceof ReflectionClass) { + throw InvalidArgumentException::create( + 1, + 'ReflectionClass object or string' + ); + } + + $this->declaredClassesPointer = count(get_declared_classes()); + + if (!$theClass instanceof ReflectionClass) { + if (class_exists($theClass, true)) { + if ($name === '') { + $name = $theClass; + } + + try { + $theClass = new ReflectionClass($theClass); + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } else { + $this->setName($theClass); + + return; + } + } + + if (!$theClass->isSubclassOf(TestCase::class)) { + $this->setName((string) $theClass); + + return; + } + + if ($name !== '') { + $this->setName($name); + } else { + $this->setName($theClass->getName()); + } + + $constructor = $theClass->getConstructor(); + + if ($constructor !== null && + !$constructor->isPublic()) { + $this->addTest( + new WarningTestCase( + sprintf( + 'Class "%s" has no public constructor.', + $theClass->getName() + ) + ) + ); + + return; + } + + foreach ((new Reflection)->publicMethodsInTestClass($theClass) as $method) { + if (!TestUtil::isTestMethod($method)) { + continue; + } + + $this->addTestMethod($theClass, $method); + } + + if (empty($this->tests)) { + $this->addTest( + new WarningTestCase( + sprintf( + 'No tests found in class "%s".', + $theClass->getName() + ) + ) + ); + } + + $this->testCase = true; + } + + /** + * Returns a string representation of the test suite. + */ + public function toString(): string + { + return $this->getName(); + } + + /** + * Adds a test to the suite. + * + * @param array $groups + */ + public function addTest(Test $test, $groups = []): void + { + try { + $class = new ReflectionClass($test); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + if (!$class->isAbstract()) { + $this->tests[] = $test; + $this->clearCaches(); + + if ($test instanceof self && empty($groups)) { + $groups = $test->getGroups(); + } + + if ($this->containsOnlyVirtualGroups($groups)) { + $groups[] = 'default'; + } + + foreach ($groups as $group) { + if (!isset($this->groups[$group])) { + $this->groups[$group] = [$test]; + } else { + $this->groups[$group][] = $test; + } + } + + if ($test instanceof TestCase) { + $test->setGroups($groups); + } + } + } + + /** + * Adds the tests from the given class to the suite. + * + * @psalm-param object|class-string $testClass + * + * @throws Exception + */ + public function addTestSuite($testClass): void + { + if (!(is_object($testClass) || (is_string($testClass) && class_exists($testClass)))) { + throw InvalidArgumentException::create( + 1, + 'class name or object' + ); + } + + if (!is_object($testClass)) { + try { + $testClass = new ReflectionClass($testClass); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + if ($testClass instanceof self) { + $this->addTest($testClass); + } elseif ($testClass instanceof ReflectionClass) { + $suiteMethod = false; + + if (!$testClass->isAbstract() && $testClass->hasMethod(BaseTestRunner::SUITE_METHODNAME)) { + try { + $method = $testClass->getMethod( + BaseTestRunner::SUITE_METHODNAME + ); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + if ($method->isStatic()) { + $this->addTest( + $method->invoke(null, $testClass->getName()) + ); + + $suiteMethod = true; + } + } + + if (!$suiteMethod && !$testClass->isAbstract() && $testClass->isSubclassOf(TestCase::class)) { + $this->addTest(new self($testClass)); + } + } else { + throw new Exception; + } + } + + public function addWarning(string $warning): void + { + $this->warnings[] = $warning; + } + + /** + * Wraps both addTest() and addTestSuite + * as well as the separate import statements for the user's convenience. + * + * If the named file cannot be read or there are no new tests that can be + * added, a PHPUnit\Framework\WarningTestCase will be created instead, + * leaving the current test run untouched. + * + * @throws Exception + */ + public function addTestFile(string $filename): void + { + if (is_file($filename) && substr($filename, -5) === '.phpt') { + $this->addTest(new PhptTestCase($filename)); + + $this->declaredClassesPointer = count(get_declared_classes()); + + return; + } + + $numTests = count($this->tests); + + // The given file may contain further stub classes in addition to the + // test class itself. Figure out the actual test class. + $filename = FileLoader::checkAndLoad($filename); + $newClasses = array_slice(get_declared_classes(), $this->declaredClassesPointer); + + // The diff is empty in case a parent class (with test methods) is added + // AFTER a child class that inherited from it. To account for that case, + // accumulate all discovered classes, so the parent class may be found in + // a later invocation. + if (!empty($newClasses)) { + // On the assumption that test classes are defined first in files, + // process discovered classes in approximate LIFO order, so as to + // avoid unnecessary reflection. + $this->foundClasses = array_merge($newClasses, $this->foundClasses); + $this->declaredClassesPointer = count(get_declared_classes()); + } + + // The test class's name must match the filename, either in full, or as + // a PEAR/PSR-0 prefixed short name ('NameSpace_ShortName'), or as a + // PSR-1 local short name ('NameSpace\ShortName'). The comparison must be + // anchored to prevent false-positive matches (e.g., 'OtherShortName'). + $shortName = basename($filename, '.php'); + $shortNameRegEx = '/(?:^|_|\\\\)' . preg_quote($shortName, '/') . '$/'; + + foreach ($this->foundClasses as $i => $className) { + if (preg_match($shortNameRegEx, $className)) { + try { + $class = new ReflectionClass($className); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + if ($class->getFileName() == $filename) { + $newClasses = [$className]; + unset($this->foundClasses[$i]); + + break; + } + } + } + + foreach ($newClasses as $className) { + try { + $class = new ReflectionClass($className); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + if (dirname($class->getFileName()) === __DIR__) { + continue; + } + + if ($class->isAbstract() && $class->isSubclassOf(TestCase::class)) { + $this->addWarning( + sprintf( + 'Abstract test case classes with "Test" suffix are deprecated (%s)', + $class->getName() + ) + ); + } + + if (!$class->isAbstract()) { + if ($class->hasMethod(BaseTestRunner::SUITE_METHODNAME)) { + try { + $method = $class->getMethod( + BaseTestRunner::SUITE_METHODNAME + ); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + if ($method->isStatic()) { + $this->addTest($method->invoke(null, $className)); + } + } elseif ($class->implementsInterface(Test::class)) { + // Do we have modern namespacing ('Foo\Bar\WhizBangTest') or old-school namespacing ('Foo_Bar_WhizBangTest')? + $isPsr0 = (!$class->inNamespace()) && (strpos($class->getName(), '_') !== false); + $expectedClassName = $isPsr0 ? $className : $shortName; + + if (($pos = strpos($expectedClassName, '.')) !== false) { + $expectedClassName = substr( + $expectedClassName, + 0, + $pos + ); + } + + if ($class->getShortName() !== $expectedClassName) { + $this->addWarning( + sprintf( + "Test case class not matching filename is deprecated\n in %s\n Class name was '%s', expected '%s'", + $filename, + $class->getShortName(), + $expectedClassName + ) + ); + } + + $this->addTestSuite($class); + } + } + } + + if (count($this->tests) > ++$numTests) { + $this->addWarning( + sprintf( + "Multiple test case classes per file is deprecated\n in %s", + $filename + ) + ); + } + + $this->numTests = -1; + } + + /** + * Wrapper for addTestFile() that adds multiple test files. + * + * @throws Exception + */ + public function addTestFiles(iterable $fileNames): void + { + foreach ($fileNames as $filename) { + $this->addTestFile((string) $filename); + } + } + + /** + * Counts the number of test cases that will be run by this test. + * + * @todo refactor usage of numTests in DefaultResultPrinter + */ + public function count(): int + { + $this->numTests = 0; + + foreach ($this as $test) { + $this->numTests += count($test); + } + + return $this->numTests; + } + + /** + * Returns the name of the suite. + */ + public function getName(): string + { + return $this->name; + } + + /** + * Returns the test groups of the suite. + * + * @psalm-return list + */ + public function getGroups(): array + { + return array_map( + static function ($key): string + { + return (string) $key; + }, + array_keys($this->groups) + ); + } + + public function getGroupDetails(): array + { + return $this->groups; + } + + /** + * Set tests groups of the test case. + */ + public function setGroupDetails(array $groups): void + { + $this->groups = $groups; + } + + /** + * Runs the tests and collects their result in a TestResult. + * + * @throws \PHPUnit\Framework\CodeCoverageException + * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException + * @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Warning + */ + public function run(TestResult $result = null): TestResult + { + if ($result === null) { + $result = $this->createResult(); + } + + if (count($this) === 0) { + return $result; + } + + /** @psalm-var class-string $className */ + $className = $this->name; + $hookMethods = TestUtil::getHookMethods($className); + + $result->startTestSuite($this); + + $test = null; + + if ($this->testCase && class_exists($this->name, false)) { + try { + foreach ($hookMethods['beforeClass'] as $beforeClassMethod) { + if (method_exists($this->name, $beforeClassMethod)) { + if ($missingRequirements = TestUtil::getMissingRequirements($this->name, $beforeClassMethod)) { + $this->markTestSuiteSkipped(implode(PHP_EOL, $missingRequirements)); + } + + call_user_func([$this->name, $beforeClassMethod]); + } + } + } catch (SkippedTestSuiteError|SkippedTestError $error) { + foreach ($this->tests() as $test) { + $result->startTest($test); + $result->addFailure($test, $error, 0); + $result->endTest($test, 0); + } + + $result->endTestSuite($this); + + return $result; + } catch (Throwable $t) { + $errorAdded = false; + + foreach ($this->tests() as $test) { + if ($result->shouldStop()) { + break; + } + + $result->startTest($test); + + if (!$errorAdded) { + $result->addError($test, $t, 0); + + $errorAdded = true; + } else { + $result->addFailure( + $test, + new SkippedTestError('Test skipped because of an error in hook method'), + 0 + ); + } + + $result->endTest($test, 0); + } + + $result->endTestSuite($this); + + return $result; + } + } + + foreach ($this as $test) { + if ($result->shouldStop()) { + break; + } + + if ($test instanceof TestCase || $test instanceof self) { + $test->setBeStrictAboutChangesToGlobalState($this->beStrictAboutChangesToGlobalState); + $test->setBackupGlobals($this->backupGlobals); + $test->setBackupStaticAttributes($this->backupStaticAttributes); + $test->setRunTestInSeparateProcess($this->runTestInSeparateProcess); + } + + $test->run($result); + } + + if ($this->testCase && class_exists($this->name, false)) { + foreach ($hookMethods['afterClass'] as $afterClassMethod) { + if (method_exists($this->name, $afterClassMethod)) { + try { + call_user_func([$this->name, $afterClassMethod]); + } catch (Throwable $t) { + $message = "Exception in {$this->name}::{$afterClassMethod}" . PHP_EOL . $t->getMessage(); + $error = new SyntheticError($message, 0, $t->getFile(), $t->getLine(), $t->getTrace()); + + $placeholderTest = clone $test; + $placeholderTest->setName($afterClassMethod); + + $result->startTest($placeholderTest); + $result->addFailure($placeholderTest, $error, 0); + $result->endTest($placeholderTest, 0); + } + } + } + } + + $result->endTestSuite($this); + + return $result; + } + + public function setRunTestInSeparateProcess(bool $runTestInSeparateProcess): void + { + $this->runTestInSeparateProcess = $runTestInSeparateProcess; + } + + public function setName(string $name): void + { + $this->name = $name; + } + + /** + * Returns the tests as an enumeration. + * + * @return Test[] + */ + public function tests(): array + { + return $this->tests; + } + + /** + * Set tests of the test suite. + * + * @param Test[] $tests + */ + public function setTests(array $tests): void + { + $this->tests = $tests; + } + + /** + * Mark the test suite as skipped. + * + * @param string $message + * + * @throws SkippedTestSuiteError + * + * @psalm-return never-return + */ + public function markTestSuiteSkipped($message = ''): void + { + throw new SkippedTestSuiteError($message); + } + + /** + * @param bool $beStrictAboutChangesToGlobalState + */ + public function setBeStrictAboutChangesToGlobalState($beStrictAboutChangesToGlobalState): void + { + if (null === $this->beStrictAboutChangesToGlobalState && is_bool($beStrictAboutChangesToGlobalState)) { + $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; + } + } + + /** + * @param bool $backupGlobals + */ + public function setBackupGlobals($backupGlobals): void + { + if (null === $this->backupGlobals && is_bool($backupGlobals)) { + $this->backupGlobals = $backupGlobals; + } + } + + /** + * @param bool $backupStaticAttributes + */ + public function setBackupStaticAttributes($backupStaticAttributes): void + { + if (null === $this->backupStaticAttributes && is_bool($backupStaticAttributes)) { + $this->backupStaticAttributes = $backupStaticAttributes; + } + } + + /** + * Returns an iterator for this test suite. + */ + public function getIterator(): Iterator + { + $iterator = new TestSuiteIterator($this); + + if ($this->iteratorFilter !== null) { + $iterator = $this->iteratorFilter->factory($iterator, $this); + } + + return $iterator; + } + + public function injectFilter(Factory $filter): void + { + $this->iteratorFilter = $filter; + + foreach ($this as $test) { + if ($test instanceof self) { + $test->injectFilter($filter); + } + } + } + + /** + * @psalm-return array + */ + public function warnings(): array + { + return array_unique($this->warnings); + } + + /** + * @return list + */ + public function provides(): array + { + if ($this->providedTests === null) { + $this->providedTests = []; + + if (is_callable($this->sortId(), true)) { + $this->providedTests[] = new ExecutionOrderDependency($this->sortId()); + } + + foreach ($this->tests as $test) { + if (!($test instanceof Reorderable)) { + // @codeCoverageIgnoreStart + continue; + // @codeCoverageIgnoreEnd + } + $this->providedTests = ExecutionOrderDependency::mergeUnique($this->providedTests, $test->provides()); + } + } + + return $this->providedTests; + } + + /** + * @return list + */ + public function requires(): array + { + if ($this->requiredTests === null) { + $this->requiredTests = []; + + foreach ($this->tests as $test) { + if (!($test instanceof Reorderable)) { + // @codeCoverageIgnoreStart + continue; + // @codeCoverageIgnoreEnd + } + $this->requiredTests = ExecutionOrderDependency::mergeUnique( + ExecutionOrderDependency::filterInvalid($this->requiredTests), + $test->requires() + ); + } + + $this->requiredTests = ExecutionOrderDependency::diff($this->requiredTests, $this->provides()); + } + + return $this->requiredTests; + } + + public function sortId(): string + { + return $this->getName() . '::class'; + } + + /** + * Creates a default TestResult object. + */ + protected function createResult(): TestResult + { + return new TestResult; + } + + /** + * @throws Exception + */ + protected function addTestMethod(ReflectionClass $class, ReflectionMethod $method): void + { + $methodName = $method->getName(); + + $test = (new TestBuilder)->build($class, $methodName); + + if ($test instanceof TestCase || $test instanceof DataProviderTestSuite) { + $test->setDependencies( + TestUtil::getDependencies($class->getName(), $methodName) + ); + } + + $this->addTest( + $test, + TestUtil::getGroups($class->getName(), $methodName) + ); + } + + private function clearCaches(): void + { + $this->numTests = -1; + $this->providedTests = null; + $this->requiredTests = null; + } + + private function containsOnlyVirtualGroups(array $groups): bool + { + foreach ($groups as $group) { + if (strpos($group, '__phpunit_') !== 0) { + return false; + } + } + + return true; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/TestSuiteIterator.php b/vendor/phpunit/phpunit/src/Framework/TestSuiteIterator.php new file mode 100644 index 00000000..76b12fcf --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/TestSuiteIterator.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function assert; +use function count; +use RecursiveIterator; + +/** + * @template-implements RecursiveIterator + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteIterator implements RecursiveIterator +{ + /** + * @var int + */ + private $position = 0; + + /** + * @var Test[] + */ + private $tests; + + public function __construct(TestSuite $testSuite) + { + $this->tests = $testSuite->tests(); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->tests); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Test + { + return $this->tests[$this->position]; + } + + public function next(): void + { + $this->position++; + } + + /** + * @throws NoChildTestSuiteException + */ + public function getChildren(): self + { + if (!$this->hasChildren()) { + throw new NoChildTestSuiteException( + 'The current item is not a TestSuite instance and therefore does not have any children.' + ); + } + + $current = $this->current(); + + assert($current instanceof TestSuite); + + return new self($current); + } + + public function hasChildren(): bool + { + return $this->valid() && $this->current() instanceof TestSuite; + } +} diff --git a/vendor/phpunit/phpunit/src/Framework/WarningTestCase.php b/vendor/phpunit/phpunit/src/Framework/WarningTestCase.php new file mode 100644 index 00000000..e1e41bc4 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Framework/WarningTestCase.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class WarningTestCase extends TestCase +{ + /** + * @var bool + */ + protected $backupGlobals = false; + + /** + * @var bool + */ + protected $backupStaticAttributes = false; + + /** + * @var bool + */ + protected $runTestInSeparateProcess = false; + + /** + * @var string + */ + private $message; + + public function __construct(string $message = '') + { + $this->message = $message; + + parent::__construct('Warning'); + } + + public function getMessage(): string + { + return $this->message; + } + + /** + * Returns a string representation of the test case. + */ + public function toString(): string + { + return 'Warning'; + } + + /** + * @throws Exception + * + * @psalm-return never-return + */ + protected function runTest(): void + { + throw new Warning($this->message); + } +} diff --git a/vendor/phpunit/phpunit/src/Runner/BaseTestRunner.php b/vendor/phpunit/phpunit/src/Runner/BaseTestRunner.php new file mode 100644 index 00000000..75a70ca5 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/BaseTestRunner.php @@ -0,0 +1,161 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function is_dir; +use function is_file; +use function substr; +use PHPUnit\Framework\Exception; +use PHPUnit\Framework\TestSuite; +use ReflectionClass; +use ReflectionException; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class BaseTestRunner +{ + /** + * @var int + */ + public const STATUS_UNKNOWN = -1; + + /** + * @var int + */ + public const STATUS_PASSED = 0; + + /** + * @var int + */ + public const STATUS_SKIPPED = 1; + + /** + * @var int + */ + public const STATUS_INCOMPLETE = 2; + + /** + * @var int + */ + public const STATUS_FAILURE = 3; + + /** + * @var int + */ + public const STATUS_ERROR = 4; + + /** + * @var int + */ + public const STATUS_RISKY = 5; + + /** + * @var int + */ + public const STATUS_WARNING = 6; + + /** + * @var string + */ + public const SUITE_METHODNAME = 'suite'; + + /** + * Returns the loader to be used. + */ + public function getLoader(): TestSuiteLoader + { + return new StandardTestSuiteLoader; + } + + /** + * Returns the Test corresponding to the given suite. + * This is a template method, subclasses override + * the runFailed() and clearStatus() methods. + * + * @param string|string[] $suffixes + * + * @throws Exception + */ + public function getTest(string $suiteClassFile, $suffixes = ''): ?TestSuite + { + if (is_dir($suiteClassFile)) { + /** @var string[] $files */ + $files = (new FileIteratorFacade)->getFilesAsArray( + $suiteClassFile, + $suffixes + ); + + $suite = new TestSuite($suiteClassFile); + $suite->addTestFiles($files); + + return $suite; + } + + if (is_file($suiteClassFile) && substr($suiteClassFile, -5, 5) === '.phpt') { + $suite = new TestSuite; + $suite->addTestFile($suiteClassFile); + + return $suite; + } + + try { + $testClass = $this->loadSuiteClass( + $suiteClassFile + ); + } catch (\PHPUnit\Exception $e) { + $this->runFailed($e->getMessage()); + + return null; + } + + try { + $suiteMethod = $testClass->getMethod(self::SUITE_METHODNAME); + + if (!$suiteMethod->isStatic()) { + $this->runFailed( + 'suite() method must be static.' + ); + + return null; + } + + $test = $suiteMethod->invoke(null, $testClass->getName()); + } catch (ReflectionException $e) { + $test = new TestSuite($testClass); + } + + $this->clearStatus(); + + return $test; + } + + /** + * Returns the loaded ReflectionClass for a suite name. + */ + protected function loadSuiteClass(string $suiteClassFile): ReflectionClass + { + return $this->getLoader()->load($suiteClassFile); + } + + /** + * Clears the status message. + */ + protected function clearStatus(): void + { + } + + /** + * Override to define how to handle a failed loading of + * a test suite. + */ + abstract protected function runFailed(string $message): void; +} diff --git a/vendor/phpunit/phpunit/src/Runner/DefaultTestResultCache.php b/vendor/phpunit/phpunit/src/Runner/DefaultTestResultCache.php new file mode 100644 index 00000000..cc22b250 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/DefaultTestResultCache.php @@ -0,0 +1,158 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use const DIRECTORY_SEPARATOR; +use const LOCK_EX; +use function assert; +use function dirname; +use function file_get_contents; +use function file_put_contents; +use function in_array; +use function is_array; +use function is_dir; +use function is_file; +use function json_decode; +use function json_encode; +use function sprintf; +use PHPUnit\Util\Filesystem; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DefaultTestResultCache implements TestResultCache +{ + /** + * @var int + */ + private const VERSION = 1; + + /** + * @psalm-var list + */ + private const ALLOWED_TEST_STATUSES = [ + BaseTestRunner::STATUS_SKIPPED, + BaseTestRunner::STATUS_INCOMPLETE, + BaseTestRunner::STATUS_FAILURE, + BaseTestRunner::STATUS_ERROR, + BaseTestRunner::STATUS_RISKY, + BaseTestRunner::STATUS_WARNING, + ]; + + /** + * @var string + */ + private const DEFAULT_RESULT_CACHE_FILENAME = '.phpunit.result.cache'; + + /** + * @var string + */ + private $cacheFilename; + + /** + * @psalm-var array + */ + private $defects = []; + + /** + * @psalm-var array + */ + private $times = []; + + public function __construct(?string $filepath = null) + { + if ($filepath !== null && is_dir($filepath)) { + $filepath .= DIRECTORY_SEPARATOR . self::DEFAULT_RESULT_CACHE_FILENAME; + } + + $this->cacheFilename = $filepath ?? $_ENV['PHPUNIT_RESULT_CACHE'] ?? self::DEFAULT_RESULT_CACHE_FILENAME; + } + + public function setState(string $testName, int $state): void + { + if (!in_array($state, self::ALLOWED_TEST_STATUSES, true)) { + return; + } + + $this->defects[$testName] = $state; + } + + public function getState(string $testName): int + { + return $this->defects[$testName] ?? BaseTestRunner::STATUS_UNKNOWN; + } + + public function setTime(string $testName, float $time): void + { + $this->times[$testName] = $time; + } + + public function getTime(string $testName): float + { + return $this->times[$testName] ?? 0.0; + } + + public function load(): void + { + if (!is_file($this->cacheFilename)) { + return; + } + + $data = json_decode( + file_get_contents($this->cacheFilename), + true + ); + + if ($data === null) { + return; + } + + if (!isset($data['version'])) { + return; + } + + if ($data['version'] !== self::VERSION) { + return; + } + + assert(isset($data['defects']) && is_array($data['defects'])); + assert(isset($data['times']) && is_array($data['times'])); + + $this->defects = $data['defects']; + $this->times = $data['times']; + } + + /** + * @throws Exception + */ + public function persist(): void + { + if (!Filesystem::createDirectory(dirname($this->cacheFilename))) { + throw new Exception( + sprintf( + 'Cannot create directory "%s" for result cache file', + $this->cacheFilename + ) + ); + } + + file_put_contents( + $this->cacheFilename, + json_encode( + [ + 'version' => self::VERSION, + 'defects' => $this->defects, + 'times' => $this->times, + ] + ), + LOCK_EX + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Runner/Exception.php b/vendor/phpunit/phpunit/src/Runner/Exception.php new file mode 100644 index 00000000..adcd1155 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Exception.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use RuntimeException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Exception extends RuntimeException implements \PHPUnit\Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/Runner/Extension/ExtensionHandler.php b/vendor/phpunit/phpunit/src/Runner/Extension/ExtensionHandler.php new file mode 100644 index 00000000..88f7ccad --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Extension/ExtensionHandler.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Extension; + +use function class_exists; +use function sprintf; +use PHPUnit\Framework\TestListener; +use PHPUnit\Runner\Exception; +use PHPUnit\Runner\Hook; +use PHPUnit\TextUI\TestRunner; +use PHPUnit\TextUI\XmlConfiguration\Extension; +use ReflectionClass; +use ReflectionException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExtensionHandler +{ + /** + * @throws Exception + */ + public function registerExtension(Extension $extensionConfiguration, TestRunner $runner): void + { + $extension = $this->createInstance($extensionConfiguration); + + if (!$extension instanceof Hook) { + throw new Exception( + sprintf( + 'Class "%s" does not implement a PHPUnit\Runner\Hook interface', + $extensionConfiguration->className() + ) + ); + } + + $runner->addExtension($extension); + } + + /** + * @throws Exception + * + * @deprecated + */ + public function createTestListenerInstance(Extension $listenerConfiguration): TestListener + { + $listener = $this->createInstance($listenerConfiguration); + + if (!$listener instanceof TestListener) { + throw new Exception( + sprintf( + 'Class "%s" does not implement the PHPUnit\Framework\TestListener interface', + $listenerConfiguration->className() + ) + ); + } + + return $listener; + } + + /** + * @throws Exception + */ + private function createInstance(Extension $extensionConfiguration): object + { + $this->ensureClassExists($extensionConfiguration); + + try { + $reflector = new ReflectionClass($extensionConfiguration->className()); + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + + if (!$extensionConfiguration->hasArguments()) { + return $reflector->newInstance(); + } + + return $reflector->newInstanceArgs($extensionConfiguration->arguments()); + } + + /** + * @throws Exception + */ + private function ensureClassExists(Extension $extensionConfiguration): void + { + if (class_exists($extensionConfiguration->className(), false)) { + return; + } + + if ($extensionConfiguration->hasSourceFile()) { + /** + * @noinspection PhpIncludeInspection + * + * @psalm-suppress UnresolvableInclude + */ + require_once $extensionConfiguration->sourceFile(); + } + + if (!class_exists($extensionConfiguration->className())) { + throw new Exception( + sprintf( + 'Class "%s" does not exist', + $extensionConfiguration->className() + ) + ); + } + } +} diff --git a/vendor/phpunit/phpunit/src/Runner/Extension/PharLoader.php b/vendor/phpunit/phpunit/src/Runner/Extension/PharLoader.php new file mode 100644 index 00000000..e76e12ce --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Extension/PharLoader.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Extension; + +use function is_file; +use PharIo\Manifest\ApplicationName; +use PharIo\Manifest\Exception as ManifestException; +use PharIo\Manifest\ManifestLoader; +use PharIo\Version\Version as PharIoVersion; +use PHPUnit\Runner\Version; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class PharLoader +{ + /** + * @psalm-return array{loadedExtensions: list, notLoadedExtensions: list} + */ + public function loadPharExtensionsInDirectory(string $directory): array + { + $loadedExtensions = []; + $notLoadedExtensions = []; + + foreach ((new FileIteratorFacade)->getFilesAsArray($directory, '.phar') as $file) { + if (!is_file('phar://' . $file . '/manifest.xml')) { + $notLoadedExtensions[] = $file . ' is not an extension for PHPUnit'; + + continue; + } + + try { + $applicationName = new ApplicationName('phpunit/phpunit'); + $version = new PharIoVersion(Version::series()); + $manifest = ManifestLoader::fromFile('phar://' . $file . '/manifest.xml'); + + if (!$manifest->isExtensionFor($applicationName)) { + $notLoadedExtensions[] = $file . ' is not an extension for PHPUnit'; + + continue; + } + + if (!$manifest->isExtensionFor($applicationName, $version)) { + $notLoadedExtensions[] = $file . ' is not compatible with this version of PHPUnit'; + + continue; + } + } catch (ManifestException $e) { + $notLoadedExtensions[] = $file . ': ' . $e->getMessage(); + + continue; + } + + /** + * @noinspection PhpIncludeInspection + * + * @psalm-suppress UnresolvableInclude + */ + require $file; + + $loadedExtensions[] = $manifest->getName()->asString() . ' ' . $manifest->getVersion()->getVersionString(); + } + + return [ + 'loadedExtensions' => $loadedExtensions, + 'notLoadedExtensions' => $notLoadedExtensions, + ]; + } +} diff --git a/vendor/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php b/vendor/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php new file mode 100644 index 00000000..4b26e571 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Filter; + +use function in_array; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExcludeGroupFilterIterator extends GroupFilterIterator +{ + protected function doAccept(string $hash): bool + { + return !in_array($hash, $this->groupTests, true); + } +} diff --git a/vendor/phpunit/phpunit/src/Runner/Filter/Factory.php b/vendor/phpunit/phpunit/src/Runner/Filter/Factory.php new file mode 100644 index 00000000..3f79da54 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Filter/Factory.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Filter; + +use function assert; +use function sprintf; +use FilterIterator; +use Iterator; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\Exception; +use RecursiveFilterIterator; +use ReflectionClass; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Factory +{ + /** + * @psalm-var array + */ + private $filters = []; + + /** + * @param array|string $args + * + * @throws Exception + */ + public function addFilter(ReflectionClass $filter, $args): void + { + if (!$filter->isSubclassOf(RecursiveFilterIterator::class)) { + throw new Exception( + sprintf( + 'Class "%s" does not extend RecursiveFilterIterator', + $filter->name + ) + ); + } + + $this->filters[] = [$filter, $args]; + } + + public function factory(Iterator $iterator, TestSuite $suite): FilterIterator + { + foreach ($this->filters as $filter) { + [$class, $args] = $filter; + $iterator = $class->newInstance($iterator, $args, $suite); + } + + assert($iterator instanceof FilterIterator); + + return $iterator; + } +} diff --git a/vendor/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php b/vendor/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php new file mode 100644 index 00000000..42ca77a3 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Filter; + +use function array_map; +use function array_merge; +use function in_array; +use function spl_object_hash; +use PHPUnit\Framework\TestSuite; +use RecursiveFilterIterator; +use RecursiveIterator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class GroupFilterIterator extends RecursiveFilterIterator +{ + /** + * @var string[] + */ + protected $groupTests = []; + + public function __construct(RecursiveIterator $iterator, array $groups, TestSuite $suite) + { + parent::__construct($iterator); + + foreach ($suite->getGroupDetails() as $group => $tests) { + if (in_array((string) $group, $groups, true)) { + $testHashes = array_map( + 'spl_object_hash', + $tests + ); + + $this->groupTests = array_merge($this->groupTests, $testHashes); + } + } + } + + public function accept(): bool + { + $test = $this->getInnerIterator()->current(); + + if ($test instanceof TestSuite) { + return true; + } + + return $this->doAccept(spl_object_hash($test)); + } + + abstract protected function doAccept(string $hash); +} diff --git a/vendor/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php b/vendor/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php new file mode 100644 index 00000000..0346c601 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Filter; + +use function in_array; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class IncludeGroupFilterIterator extends GroupFilterIterator +{ + protected function doAccept(string $hash): bool + { + return in_array($hash, $this->groupTests, true); + } +} diff --git a/vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php b/vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php new file mode 100644 index 00000000..7057e1c4 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Filter; + +use function end; +use function implode; +use function preg_match; +use function sprintf; +use function str_replace; +use Exception; +use PHPUnit\Framework\ErrorTestCase; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Framework\WarningTestCase; +use PHPUnit\Util\RegularExpression; +use RecursiveFilterIterator; +use RecursiveIterator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NameFilterIterator extends RecursiveFilterIterator +{ + /** + * @var string + */ + private $filter; + + /** + * @var int + */ + private $filterMin; + + /** + * @var int + */ + private $filterMax; + + /** + * @throws Exception + */ + public function __construct(RecursiveIterator $iterator, string $filter) + { + parent::__construct($iterator); + + $this->setFilter($filter); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function accept(): bool + { + $test = $this->getInnerIterator()->current(); + + if ($test instanceof TestSuite) { + return true; + } + + $tmp = \PHPUnit\Util\Test::describe($test); + + if ($test instanceof ErrorTestCase || $test instanceof WarningTestCase) { + $name = $test->getMessage(); + } elseif ($tmp[0] !== '') { + $name = implode('::', $tmp); + } else { + $name = $tmp[1]; + } + + $accepted = @preg_match($this->filter, $name, $matches); + + if ($accepted && isset($this->filterMax)) { + $set = end($matches); + $accepted = $set >= $this->filterMin && $set <= $this->filterMax; + } + + return (bool) $accepted; + } + + /** + * @throws Exception + */ + private function setFilter(string $filter): void + { + if (RegularExpression::safeMatch($filter, '') === false) { + // Handles: + // * testAssertEqualsSucceeds#4 + // * testAssertEqualsSucceeds#4-8 + if (preg_match('/^(.*?)#(\d+)(?:-(\d+))?$/', $filter, $matches)) { + if (isset($matches[3]) && $matches[2] < $matches[3]) { + $filter = sprintf( + '%s.*with data set #(\d+)$', + $matches[1] + ); + + $this->filterMin = (int) $matches[2]; + $this->filterMax = (int) $matches[3]; + } else { + $filter = sprintf( + '%s.*with data set #%s$', + $matches[1], + $matches[2] + ); + } + } // Handles: + // * testDetermineJsonError@JSON_ERROR_NONE + // * testDetermineJsonError@JSON.* + elseif (preg_match('/^(.*?)@(.+)$/', $filter, $matches)) { + $filter = sprintf( + '%s.*with data set "%s"$', + $matches[1], + $matches[2] + ); + } + + // Escape delimiters in regular expression. Do NOT use preg_quote, + // to keep magic characters. + $filter = sprintf( + '/%s/i', + str_replace( + '/', + '\\/', + $filter + ) + ); + } + + $this->filter = $filter; + } +} diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterIncompleteTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterIncompleteTestHook.php new file mode 100644 index 00000000..432be9a9 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterIncompleteTestHook.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * This interface, as well as the associated mechanism for extending PHPUnit, + * will be removed in PHPUnit 10. There is no alternative available in this + * version of PHPUnit. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see https://github.com/sebastianbergmann/phpunit/issues/4676 + */ +interface AfterIncompleteTestHook extends TestHook +{ + public function executeAfterIncompleteTest(string $test, string $message, float $time): void; +} diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterLastTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterLastTestHook.php new file mode 100644 index 00000000..eb789f26 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterLastTestHook.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * This interface, as well as the associated mechanism for extending PHPUnit, + * will be removed in PHPUnit 10. There is no alternative available in this + * version of PHPUnit. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see https://github.com/sebastianbergmann/phpunit/issues/4676 + */ +interface AfterLastTestHook extends Hook +{ + public function executeAfterLastTest(): void; +} diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterRiskyTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterRiskyTestHook.php new file mode 100644 index 00000000..31cc91ab --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterRiskyTestHook.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * This interface, as well as the associated mechanism for extending PHPUnit, + * will be removed in PHPUnit 10. There is no alternative available in this + * version of PHPUnit. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see https://github.com/sebastianbergmann/phpunit/issues/4676 + */ +interface AfterRiskyTestHook extends TestHook +{ + public function executeAfterRiskyTest(string $test, string $message, float $time): void; +} diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterSkippedTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterSkippedTestHook.php new file mode 100644 index 00000000..76980b3f --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterSkippedTestHook.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * This interface, as well as the associated mechanism for extending PHPUnit, + * will be removed in PHPUnit 10. There is no alternative available in this + * version of PHPUnit. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see https://github.com/sebastianbergmann/phpunit/issues/4676 + */ +interface AfterSkippedTestHook extends TestHook +{ + public function executeAfterSkippedTest(string $test, string $message, float $time): void; +} diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterSuccessfulTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterSuccessfulTestHook.php new file mode 100644 index 00000000..d0a10dd1 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterSuccessfulTestHook.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * This interface, as well as the associated mechanism for extending PHPUnit, + * will be removed in PHPUnit 10. There is no alternative available in this + * version of PHPUnit. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see https://github.com/sebastianbergmann/phpunit/issues/4676 + */ +interface AfterSuccessfulTestHook extends TestHook +{ + public function executeAfterSuccessfulTest(string $test, float $time): void; +} diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestErrorHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestErrorHook.php new file mode 100644 index 00000000..12ecebd3 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestErrorHook.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * This interface, as well as the associated mechanism for extending PHPUnit, + * will be removed in PHPUnit 10. There is no alternative available in this + * version of PHPUnit. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see https://github.com/sebastianbergmann/phpunit/issues/4676 + */ +interface AfterTestErrorHook extends TestHook +{ + public function executeAfterTestError(string $test, string $message, float $time): void; +} diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestFailureHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestFailureHook.php new file mode 100644 index 00000000..94b2f300 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestFailureHook.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * This interface, as well as the associated mechanism for extending PHPUnit, + * will be removed in PHPUnit 10. There is no alternative available in this + * version of PHPUnit. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see https://github.com/sebastianbergmann/phpunit/issues/4676 + */ +interface AfterTestFailureHook extends TestHook +{ + public function executeAfterTestFailure(string $test, string $message, float $time): void; +} diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestHook.php new file mode 100644 index 00000000..3d5bcaa9 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestHook.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * This interface, as well as the associated mechanism for extending PHPUnit, + * will be removed in PHPUnit 10. There is no alternative available in this + * version of PHPUnit. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see https://github.com/sebastianbergmann/phpunit/issues/4676 + */ +interface AfterTestHook extends TestHook +{ + /** + * This hook will fire after any test, regardless of the result. + * + * For more fine grained control, have a look at the other hooks + * that extend PHPUnit\Runner\Hook. + */ + public function executeAfterTest(string $test, float $time): void; +} diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestWarningHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestWarningHook.php new file mode 100644 index 00000000..860fccee --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Hook/AfterTestWarningHook.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * This interface, as well as the associated mechanism for extending PHPUnit, + * will be removed in PHPUnit 10. There is no alternative available in this + * version of PHPUnit. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see https://github.com/sebastianbergmann/phpunit/issues/4676 + */ +interface AfterTestWarningHook extends TestHook +{ + public function executeAfterTestWarning(string $test, string $message, float $time): void; +} diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/BeforeFirstTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/BeforeFirstTestHook.php new file mode 100644 index 00000000..feeb90fb --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Hook/BeforeFirstTestHook.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * This interface, as well as the associated mechanism for extending PHPUnit, + * will be removed in PHPUnit 10. There is no alternative available in this + * version of PHPUnit. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see https://github.com/sebastianbergmann/phpunit/issues/4676 + */ +interface BeforeFirstTestHook extends Hook +{ + public function executeBeforeFirstTest(): void; +} diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/BeforeTestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/BeforeTestHook.php new file mode 100644 index 00000000..b7e0827d --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Hook/BeforeTestHook.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * This interface, as well as the associated mechanism for extending PHPUnit, + * will be removed in PHPUnit 10. There is no alternative available in this + * version of PHPUnit. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see https://github.com/sebastianbergmann/phpunit/issues/4676 + */ +interface BeforeTestHook extends TestHook +{ + public function executeBeforeTest(string $test): void; +} diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/Hook.php b/vendor/phpunit/phpunit/src/Runner/Hook/Hook.php new file mode 100644 index 00000000..a08dc72b --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Hook/Hook.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * This interface, as well as the associated mechanism for extending PHPUnit, + * will be removed in PHPUnit 10. There is no alternative available in this + * version of PHPUnit. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see https://github.com/sebastianbergmann/phpunit/issues/4676 + */ +interface Hook +{ +} diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/TestHook.php b/vendor/phpunit/phpunit/src/Runner/Hook/TestHook.php new file mode 100644 index 00000000..31e880e2 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Hook/TestHook.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * This interface, as well as the associated mechanism for extending PHPUnit, + * will be removed in PHPUnit 10. There is no alternative available in this + * version of PHPUnit. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see https://github.com/sebastianbergmann/phpunit/issues/4676 + */ +interface TestHook extends Hook +{ +} diff --git a/vendor/phpunit/phpunit/src/Runner/Hook/TestListenerAdapter.php b/vendor/phpunit/phpunit/src/Runner/Hook/TestListenerAdapter.php new file mode 100644 index 00000000..60fbfba3 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Hook/TestListenerAdapter.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestListener; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Framework\Warning; +use PHPUnit\Util\Test as TestUtil; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestListenerAdapter implements TestListener +{ + /** + * @var TestHook[] + */ + private $hooks = []; + + /** + * @var bool + */ + private $lastTestWasNotSuccessful; + + public function add(TestHook $hook): void + { + $this->hooks[] = $hook; + } + + public function startTest(Test $test): void + { + foreach ($this->hooks as $hook) { + if ($hook instanceof BeforeTestHook) { + $hook->executeBeforeTest(TestUtil::describeAsString($test)); + } + } + + $this->lastTestWasNotSuccessful = false; + } + + public function addError(Test $test, Throwable $t, float $time): void + { + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterTestErrorHook) { + $hook->executeAfterTestError(TestUtil::describeAsString($test), $t->getMessage(), $time); + } + } + + $this->lastTestWasNotSuccessful = true; + } + + public function addWarning(Test $test, Warning $e, float $time): void + { + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterTestWarningHook) { + $hook->executeAfterTestWarning(TestUtil::describeAsString($test), $e->getMessage(), $time); + } + } + + $this->lastTestWasNotSuccessful = true; + } + + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterTestFailureHook) { + $hook->executeAfterTestFailure(TestUtil::describeAsString($test), $e->getMessage(), $time); + } + } + + $this->lastTestWasNotSuccessful = true; + } + + public function addIncompleteTest(Test $test, Throwable $t, float $time): void + { + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterIncompleteTestHook) { + $hook->executeAfterIncompleteTest(TestUtil::describeAsString($test), $t->getMessage(), $time); + } + } + + $this->lastTestWasNotSuccessful = true; + } + + public function addRiskyTest(Test $test, Throwable $t, float $time): void + { + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterRiskyTestHook) { + $hook->executeAfterRiskyTest(TestUtil::describeAsString($test), $t->getMessage(), $time); + } + } + + $this->lastTestWasNotSuccessful = true; + } + + public function addSkippedTest(Test $test, Throwable $t, float $time): void + { + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterSkippedTestHook) { + $hook->executeAfterSkippedTest(TestUtil::describeAsString($test), $t->getMessage(), $time); + } + } + + $this->lastTestWasNotSuccessful = true; + } + + public function endTest(Test $test, float $time): void + { + if (!$this->lastTestWasNotSuccessful) { + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterSuccessfulTestHook) { + $hook->executeAfterSuccessfulTest(TestUtil::describeAsString($test), $time); + } + } + } + + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterTestHook) { + $hook->executeAfterTest(TestUtil::describeAsString($test), $time); + } + } + } + + public function startTestSuite(TestSuite $suite): void + { + } + + public function endTestSuite(TestSuite $suite): void + { + } +} diff --git a/vendor/phpunit/phpunit/src/Runner/NullTestResultCache.php b/vendor/phpunit/phpunit/src/Runner/NullTestResultCache.php new file mode 100644 index 00000000..2aa86534 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/NullTestResultCache.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NullTestResultCache implements TestResultCache +{ + public function setState(string $testName, int $state): void + { + } + + public function getState(string $testName): int + { + return BaseTestRunner::STATUS_UNKNOWN; + } + + public function setTime(string $testName, float $time): void + { + } + + public function getTime(string $testName): float + { + return 0; + } + + public function load(): void + { + } + + public function persist(): void + { + } +} diff --git a/vendor/phpunit/phpunit/src/Runner/PhptTestCase.php b/vendor/phpunit/phpunit/src/Runner/PhptTestCase.php new file mode 100644 index 00000000..6590102d --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/PhptTestCase.php @@ -0,0 +1,864 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use const DEBUG_BACKTRACE_IGNORE_ARGS; +use const DIRECTORY_SEPARATOR; +use function array_merge; +use function basename; +use function debug_backtrace; +use function defined; +use function dirname; +use function explode; +use function extension_loaded; +use function file; +use function file_get_contents; +use function file_put_contents; +use function is_array; +use function is_file; +use function is_readable; +use function is_string; +use function ltrim; +use function phpversion; +use function preg_match; +use function preg_replace; +use function preg_split; +use function realpath; +use function rtrim; +use function sprintf; +use function str_replace; +use function strncasecmp; +use function strpos; +use function substr; +use function trim; +use function unlink; +use function unserialize; +use function var_export; +use function version_compare; +use PHPUnit\Framework\Assert; +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\ExecutionOrderDependency; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\IncompleteTestError; +use PHPUnit\Framework\PHPTAssertionFailedError; +use PHPUnit\Framework\Reorderable; +use PHPUnit\Framework\SelfDescribing; +use PHPUnit\Framework\SkippedTestError; +use PHPUnit\Framework\SyntheticSkippedError; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestResult; +use PHPUnit\Util\PHP\AbstractPhpProcess; +use SebastianBergmann\CodeCoverage\RawCodeCoverageData; +use SebastianBergmann\Template\Template; +use SebastianBergmann\Timer\Timer; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class PhptTestCase implements Reorderable, SelfDescribing, Test +{ + /** + * @var string + */ + private $filename; + + /** + * @var AbstractPhpProcess + */ + private $phpUtil; + + /** + * @var string + */ + private $output = ''; + + /** + * Constructs a test case with the given filename. + * + * @throws Exception + */ + public function __construct(string $filename, AbstractPhpProcess $phpUtil = null) + { + if (!is_file($filename)) { + throw new Exception( + sprintf( + 'File "%s" does not exist.', + $filename + ) + ); + } + + $this->filename = $filename; + $this->phpUtil = $phpUtil ?: AbstractPhpProcess::factory(); + } + + /** + * Counts the number of test cases executed by run(TestResult result). + */ + public function count(): int + { + return 1; + } + + /** + * Runs a test and collects its result in a TestResult instance. + * + * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException + * @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + */ + public function run(TestResult $result = null): TestResult + { + if ($result === null) { + $result = new TestResult; + } + + try { + $sections = $this->parse(); + } catch (Exception $e) { + $result->startTest($this); + $result->addFailure($this, new SkippedTestError($e->getMessage()), 0); + $result->endTest($this, 0); + + return $result; + } + + $code = $this->render($sections['FILE']); + $xfail = false; + $settings = $this->parseIniSection($this->settings($result->getCollectCodeCoverageInformation())); + + $result->startTest($this); + + if (isset($sections['INI'])) { + $settings = $this->parseIniSection($sections['INI'], $settings); + } + + if (isset($sections['ENV'])) { + $env = $this->parseEnvSection($sections['ENV']); + $this->phpUtil->setEnv($env); + } + + $this->phpUtil->setUseStderrRedirection(true); + + if ($result->enforcesTimeLimit()) { + $this->phpUtil->setTimeout($result->getTimeoutForLargeTests()); + } + + $skip = $this->runSkip($sections, $result, $settings); + + if ($skip) { + return $result; + } + + if (isset($sections['XFAIL'])) { + $xfail = trim($sections['XFAIL']); + } + + if (isset($sections['STDIN'])) { + $this->phpUtil->setStdin($sections['STDIN']); + } + + if (isset($sections['ARGS'])) { + $this->phpUtil->setArgs($sections['ARGS']); + } + + if ($result->getCollectCodeCoverageInformation()) { + $codeCoverageCacheDirectory = null; + $pathCoverage = false; + + $codeCoverage = $result->getCodeCoverage(); + + if ($codeCoverage) { + if ($codeCoverage->cachesStaticAnalysis()) { + $codeCoverageCacheDirectory = $codeCoverage->cacheDirectory(); + } + + $pathCoverage = $codeCoverage->collectsBranchAndPathCoverage(); + } + + $this->renderForCoverage($code, $pathCoverage, $codeCoverageCacheDirectory); + } + + $timer = new Timer; + $timer->start(); + + $jobResult = $this->phpUtil->runJob($code, $this->stringifyIni($settings)); + $time = $timer->stop()->asSeconds(); + $this->output = $jobResult['stdout'] ?? ''; + + if (isset($codeCoverage) && ($coverage = $this->cleanupForCoverage())) { + $codeCoverage->append($coverage, $this, true, [], []); + } + + try { + $this->assertPhptExpectation($sections, $this->output); + } catch (AssertionFailedError $e) { + $failure = $e; + + if ($xfail !== false) { + $failure = new IncompleteTestError($xfail, 0, $e); + } elseif ($e instanceof ExpectationFailedException) { + $comparisonFailure = $e->getComparisonFailure(); + + if ($comparisonFailure) { + $diff = $comparisonFailure->getDiff(); + } else { + $diff = $e->getMessage(); + } + + $hint = $this->getLocationHintFromDiff($diff, $sections); + $trace = array_merge($hint, debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)); + $failure = new PHPTAssertionFailedError( + $e->getMessage(), + 0, + $trace[0]['file'], + $trace[0]['line'], + $trace, + $comparisonFailure ? $diff : '' + ); + } + + $result->addFailure($this, $failure, $time); + } catch (Throwable $t) { + $result->addError($this, $t, $time); + } + + if ($xfail !== false && $result->allCompletelyImplemented()) { + $result->addFailure($this, new IncompleteTestError('XFAIL section but test passes'), $time); + } + + $this->runClean($sections, $result->getCollectCodeCoverageInformation()); + + $result->endTest($this, $time); + + return $result; + } + + /** + * Returns the name of the test case. + */ + public function getName(): string + { + return $this->toString(); + } + + /** + * Returns a string representation of the test case. + */ + public function toString(): string + { + return $this->filename; + } + + public function usesDataProvider(): bool + { + return false; + } + + public function getNumAssertions(): int + { + return 1; + } + + public function getActualOutput(): string + { + return $this->output; + } + + public function hasOutput(): bool + { + return !empty($this->output); + } + + public function sortId(): string + { + return $this->filename; + } + + /** + * @return list + */ + public function provides(): array + { + return []; + } + + /** + * @return list + */ + public function requires(): array + { + return []; + } + + /** + * Parse --INI-- section key value pairs and return as array. + * + * @param array|string $content + */ + private function parseIniSection($content, array $ini = []): array + { + if (is_string($content)) { + $content = explode("\n", trim($content)); + } + + foreach ($content as $setting) { + if (strpos($setting, '=') === false) { + continue; + } + + $setting = explode('=', $setting, 2); + $name = trim($setting[0]); + $value = trim($setting[1]); + + if ($name === 'extension' || $name === 'zend_extension') { + if (!isset($ini[$name])) { + $ini[$name] = []; + } + + $ini[$name][] = $value; + + continue; + } + + $ini[$name] = $value; + } + + return $ini; + } + + private function parseEnvSection(string $content): array + { + $env = []; + + foreach (explode("\n", trim($content)) as $e) { + $e = explode('=', trim($e), 2); + + if (!empty($e[0]) && isset($e[1])) { + $env[$e[0]] = $e[1]; + } + } + + return $env; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + * @throws ExpectationFailedException + */ + private function assertPhptExpectation(array $sections, string $output): void + { + $assertions = [ + 'EXPECT' => 'assertEquals', + 'EXPECTF' => 'assertStringMatchesFormat', + 'EXPECTREGEX' => 'assertMatchesRegularExpression', + ]; + + $actual = preg_replace('/\r\n/', "\n", trim($output)); + + foreach ($assertions as $sectionName => $sectionAssertion) { + if (isset($sections[$sectionName])) { + $sectionContent = preg_replace('/\r\n/', "\n", trim($sections[$sectionName])); + $expected = $sectionName === 'EXPECTREGEX' ? "/{$sectionContent}/" : $sectionContent; + + if ($expected === '') { + throw new Exception('No PHPT expectation found'); + } + + Assert::$sectionAssertion($expected, $actual); + + return; + } + } + + throw new Exception('No PHPT assertion found'); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + private function runSkip(array &$sections, TestResult $result, array $settings): bool + { + if (!isset($sections['SKIPIF'])) { + return false; + } + + $skipif = $this->render($sections['SKIPIF']); + $jobResult = $this->phpUtil->runJob($skipif, $this->stringifyIni($settings)); + + if (!strncasecmp('skip', ltrim($jobResult['stdout']), 4)) { + $message = ''; + + if (preg_match('/^\s*skip\s*(.+)\s*/i', $jobResult['stdout'], $skipMatch)) { + $message = substr($skipMatch[1], 2); + } + + $hint = $this->getLocationHint($message, $sections, 'SKIPIF'); + $trace = array_merge($hint, debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)); + $result->addFailure( + $this, + new SyntheticSkippedError($message, 0, $trace[0]['file'], $trace[0]['line'], $trace), + 0 + ); + $result->endTest($this, 0); + + return true; + } + + return false; + } + + private function runClean(array &$sections, bool $collectCoverage): void + { + $this->phpUtil->setStdin(''); + $this->phpUtil->setArgs(''); + + if (isset($sections['CLEAN'])) { + $cleanCode = $this->render($sections['CLEAN']); + + $this->phpUtil->runJob($cleanCode, $this->settings($collectCoverage)); + } + } + + /** + * @throws Exception + */ + private function parse(): array + { + $sections = []; + $section = ''; + + $unsupportedSections = [ + 'CGI', + 'COOKIE', + 'DEFLATE_POST', + 'EXPECTHEADERS', + 'EXTENSIONS', + 'GET', + 'GZIP_POST', + 'HEADERS', + 'PHPDBG', + 'POST', + 'POST_RAW', + 'PUT', + 'REDIRECTTEST', + 'REQUEST', + ]; + + $lineNr = 0; + + foreach (file($this->filename) as $line) { + $lineNr++; + + if (preg_match('/^--([_A-Z]+)--/', $line, $result)) { + $section = $result[1]; + $sections[$section] = ''; + $sections[$section . '_offset'] = $lineNr; + + continue; + } + + if (empty($section)) { + throw new Exception('Invalid PHPT file: empty section header'); + } + + $sections[$section] .= $line; + } + + if (isset($sections['FILEEOF'])) { + $sections['FILE'] = rtrim($sections['FILEEOF'], "\r\n"); + unset($sections['FILEEOF']); + } + + $this->parseExternal($sections); + + if (!$this->validate($sections)) { + throw new Exception('Invalid PHPT file'); + } + + foreach ($unsupportedSections as $section) { + if (isset($sections[$section])) { + throw new Exception( + "PHPUnit does not support PHPT {$section} sections" + ); + } + } + + return $sections; + } + + /** + * @throws Exception + */ + private function parseExternal(array &$sections): void + { + $allowSections = [ + 'FILE', + 'EXPECT', + 'EXPECTF', + 'EXPECTREGEX', + ]; + $testDirectory = dirname($this->filename) . DIRECTORY_SEPARATOR; + + foreach ($allowSections as $section) { + if (isset($sections[$section . '_EXTERNAL'])) { + $externalFilename = trim($sections[$section . '_EXTERNAL']); + + if (!is_file($testDirectory . $externalFilename) || + !is_readable($testDirectory . $externalFilename)) { + throw new Exception( + sprintf( + 'Could not load --%s-- %s for PHPT file', + $section . '_EXTERNAL', + $testDirectory . $externalFilename + ) + ); + } + + $sections[$section] = file_get_contents($testDirectory . $externalFilename); + } + } + } + + private function validate(array &$sections): bool + { + $requiredSections = [ + 'FILE', + [ + 'EXPECT', + 'EXPECTF', + 'EXPECTREGEX', + ], + ]; + + foreach ($requiredSections as $section) { + if (is_array($section)) { + $foundSection = false; + + foreach ($section as $anySection) { + if (isset($sections[$anySection])) { + $foundSection = true; + + break; + } + } + + if (!$foundSection) { + return false; + } + + continue; + } + + if (!isset($sections[$section])) { + return false; + } + } + + return true; + } + + private function render(string $code): string + { + return str_replace( + [ + '__DIR__', + '__FILE__', + ], + [ + "'" . dirname($this->filename) . "'", + "'" . $this->filename . "'", + ], + $code + ); + } + + private function getCoverageFiles(): array + { + $baseDir = dirname(realpath($this->filename)) . DIRECTORY_SEPARATOR; + $basename = basename($this->filename, 'phpt'); + + return [ + 'coverage' => $baseDir . $basename . 'coverage', + 'job' => $baseDir . $basename . 'php', + ]; + } + + private function renderForCoverage(string &$job, bool $pathCoverage, ?string $codeCoverageCacheDirectory): void + { + $files = $this->getCoverageFiles(); + + $template = new Template( + __DIR__ . '/../Util/PHP/Template/PhptTestCase.tpl' + ); + + $composerAutoload = '\'\''; + + if (defined('PHPUNIT_COMPOSER_INSTALL')) { + $composerAutoload = var_export(PHPUNIT_COMPOSER_INSTALL, true); + } + + $phar = '\'\''; + + if (defined('__PHPUNIT_PHAR__')) { + $phar = var_export(__PHPUNIT_PHAR__, true); + } + + $globals = ''; + + if (!empty($GLOBALS['__PHPUNIT_BOOTSTRAP'])) { + $globals = '$GLOBALS[\'__PHPUNIT_BOOTSTRAP\'] = ' . var_export( + $GLOBALS['__PHPUNIT_BOOTSTRAP'], + true + ) . ";\n"; + } + + if ($codeCoverageCacheDirectory === null) { + $codeCoverageCacheDirectory = 'null'; + } else { + $codeCoverageCacheDirectory = "'" . $codeCoverageCacheDirectory . "'"; + } + + $template->setVar( + [ + 'composerAutoload' => $composerAutoload, + 'phar' => $phar, + 'globals' => $globals, + 'job' => $files['job'], + 'coverageFile' => $files['coverage'], + 'driverMethod' => $pathCoverage ? 'forLineAndPathCoverage' : 'forLineCoverage', + 'codeCoverageCacheDirectory' => $codeCoverageCacheDirectory, + ] + ); + + file_put_contents($files['job'], $job); + + $job = $template->render(); + } + + private function cleanupForCoverage(): RawCodeCoverageData + { + $coverage = RawCodeCoverageData::fromXdebugWithoutPathCoverage([]); + $files = $this->getCoverageFiles(); + + if (is_file($files['coverage'])) { + $buffer = @file_get_contents($files['coverage']); + + if ($buffer !== false) { + $coverage = @unserialize($buffer); + + if ($coverage === false) { + $coverage = RawCodeCoverageData::fromXdebugWithoutPathCoverage([]); + } + } + } + + foreach ($files as $file) { + @unlink($file); + } + + return $coverage; + } + + private function stringifyIni(array $ini): array + { + $settings = []; + + foreach ($ini as $key => $value) { + if (is_array($value)) { + foreach ($value as $val) { + $settings[] = $key . '=' . $val; + } + + continue; + } + + $settings[] = $key . '=' . $value; + } + + return $settings; + } + + private function getLocationHintFromDiff(string $message, array $sections): array + { + $needle = ''; + $previousLine = ''; + $block = 'message'; + + foreach (preg_split('/\r\n|\r|\n/', $message) as $line) { + $line = trim($line); + + if ($block === 'message' && $line === '--- Expected') { + $block = 'expected'; + } + + if ($block === 'expected' && $line === '@@ @@') { + $block = 'diff'; + } + + if ($block === 'diff') { + if (strpos($line, '+') === 0) { + $needle = $this->getCleanDiffLine($previousLine); + + break; + } + + if (strpos($line, '-') === 0) { + $needle = $this->getCleanDiffLine($line); + + break; + } + } + + if (!empty($line)) { + $previousLine = $line; + } + } + + return $this->getLocationHint($needle, $sections); + } + + private function getCleanDiffLine(string $line): string + { + if (preg_match('/^[\-+]([\'\"]?)(.*)\1$/', $line, $matches)) { + $line = $matches[2]; + } + + return $line; + } + + private function getLocationHint(string $needle, array $sections, ?string $sectionName = null): array + { + $needle = trim($needle); + + if (empty($needle)) { + return [[ + 'file' => realpath($this->filename), + 'line' => 1, + ]]; + } + + if ($sectionName) { + $search = [$sectionName]; + } else { + $search = [ + // 'FILE', + 'EXPECT', + 'EXPECTF', + 'EXPECTREGEX', + ]; + } + + $sectionOffset = null; + + foreach ($search as $section) { + if (!isset($sections[$section])) { + continue; + } + + if (isset($sections[$section . '_EXTERNAL'])) { + $externalFile = trim($sections[$section . '_EXTERNAL']); + + return [ + [ + 'file' => realpath(dirname($this->filename) . DIRECTORY_SEPARATOR . $externalFile), + 'line' => 1, + ], + [ + 'file' => realpath($this->filename), + 'line' => ($sections[$section . '_EXTERNAL_offset'] ?? 0) + 1, + ], + ]; + } + + $sectionOffset = $sections[$section . '_offset'] ?? 0; + $offset = $sectionOffset + 1; + + foreach (preg_split('/\r\n|\r|\n/', $sections[$section]) as $line) { + if (strpos($line, $needle) !== false) { + return [[ + 'file' => realpath($this->filename), + 'line' => $offset, + ]]; + } + $offset++; + } + } + + if ($sectionName) { + // String not found in specified section, show user the start of the named section + return [[ + 'file' => realpath($this->filename), + 'line' => $sectionOffset, + ]]; + } + + // No section specified, show user start of code + return [[ + 'file' => realpath($this->filename), + 'line' => 1, + ]]; + } + + /** + * @psalm-return list + */ + private function settings(bool $collectCoverage): array + { + $settings = [ + 'allow_url_fopen=1', + 'auto_append_file=', + 'auto_prepend_file=', + 'disable_functions=', + 'display_errors=1', + 'docref_ext=.html', + 'docref_root=', + 'error_append_string=', + 'error_prepend_string=', + 'error_reporting=-1', + 'html_errors=0', + 'log_errors=0', + 'open_basedir=', + 'output_buffering=Off', + 'output_handler=', + 'report_memleaks=0', + 'report_zend_debug=0', + ]; + + if (extension_loaded('pcov')) { + if ($collectCoverage) { + $settings[] = 'pcov.enabled=1'; + } else { + $settings[] = 'pcov.enabled=0'; + } + } + + if (extension_loaded('xdebug')) { + if (version_compare(phpversion('xdebug'), '3', '>=')) { + if ($collectCoverage) { + $settings[] = 'xdebug.mode=coverage'; + } else { + $settings[] = 'xdebug.mode=off'; + } + } else { + $settings[] = 'xdebug.default_enable=0'; + + if ($collectCoverage) { + $settings[] = 'xdebug.coverage_enable=1'; + } + } + } + + return $settings; + } +} diff --git a/vendor/phpunit/phpunit/src/Runner/ResultCacheExtension.php b/vendor/phpunit/phpunit/src/Runner/ResultCacheExtension.php new file mode 100644 index 00000000..31d7610e --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/ResultCacheExtension.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function preg_match; +use function round; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ResultCacheExtension implements AfterIncompleteTestHook, AfterLastTestHook, AfterRiskyTestHook, AfterSkippedTestHook, AfterSuccessfulTestHook, AfterTestErrorHook, AfterTestFailureHook, AfterTestWarningHook +{ + /** + * @var TestResultCache + */ + private $cache; + + public function __construct(TestResultCache $cache) + { + $this->cache = $cache; + } + + public function flush(): void + { + $this->cache->persist(); + } + + public function executeAfterSuccessfulTest(string $test, float $time): void + { + $testName = $this->getTestName($test); + + $this->cache->setTime($testName, round($time, 3)); + } + + public function executeAfterIncompleteTest(string $test, string $message, float $time): void + { + $testName = $this->getTestName($test); + + $this->cache->setTime($testName, round($time, 3)); + $this->cache->setState($testName, BaseTestRunner::STATUS_INCOMPLETE); + } + + public function executeAfterRiskyTest(string $test, string $message, float $time): void + { + $testName = $this->getTestName($test); + + $this->cache->setTime($testName, round($time, 3)); + $this->cache->setState($testName, BaseTestRunner::STATUS_RISKY); + } + + public function executeAfterSkippedTest(string $test, string $message, float $time): void + { + $testName = $this->getTestName($test); + + $this->cache->setTime($testName, round($time, 3)); + $this->cache->setState($testName, BaseTestRunner::STATUS_SKIPPED); + } + + public function executeAfterTestError(string $test, string $message, float $time): void + { + $testName = $this->getTestName($test); + + $this->cache->setTime($testName, round($time, 3)); + $this->cache->setState($testName, BaseTestRunner::STATUS_ERROR); + } + + public function executeAfterTestFailure(string $test, string $message, float $time): void + { + $testName = $this->getTestName($test); + + $this->cache->setTime($testName, round($time, 3)); + $this->cache->setState($testName, BaseTestRunner::STATUS_FAILURE); + } + + public function executeAfterTestWarning(string $test, string $message, float $time): void + { + $testName = $this->getTestName($test); + + $this->cache->setTime($testName, round($time, 3)); + $this->cache->setState($testName, BaseTestRunner::STATUS_WARNING); + } + + public function executeAfterLastTest(): void + { + $this->flush(); + } + + /** + * @param string $test A long description format of the current test + * + * @return string The test name without TestSuiteClassName:: and @dataprovider details + */ + private function getTestName(string $test): string + { + $matches = []; + + if (preg_match('/^(?\S+::\S+)(?:(? with data set (?:#\d+|"[^"]+"))\s\()?/', $test, $matches)) { + $test = $matches['name'] . ($matches['dataname'] ?? ''); + } + + return $test; + } +} diff --git a/vendor/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php b/vendor/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php new file mode 100644 index 00000000..0ed8330e --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php @@ -0,0 +1,152 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function array_diff; +use function array_values; +use function basename; +use function class_exists; +use function get_declared_classes; +use function sprintf; +use function stripos; +use function strlen; +use function substr; +use PHPUnit\Framework\TestCase; +use PHPUnit\Util\FileLoader; +use ReflectionClass; +use ReflectionException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039 + */ +final class StandardTestSuiteLoader implements TestSuiteLoader +{ + /** + * @throws Exception + */ + public function load(string $suiteClassFile): ReflectionClass + { + $suiteClassName = basename($suiteClassFile, '.php'); + $loadedClasses = get_declared_classes(); + + if (!class_exists($suiteClassName, false)) { + /* @noinspection UnusedFunctionResultInspection */ + FileLoader::checkAndLoad($suiteClassFile); + + $loadedClasses = array_values( + array_diff(get_declared_classes(), $loadedClasses) + ); + + if (empty($loadedClasses)) { + throw new Exception( + sprintf( + 'Class %s could not be found in %s', + $suiteClassName, + $suiteClassFile + ) + ); + } + } + + if (!class_exists($suiteClassName, false)) { + $offset = 0 - strlen($suiteClassName); + + foreach ($loadedClasses as $loadedClass) { + // @see https://github.com/sebastianbergmann/phpunit/issues/5020 + if (stripos(substr($loadedClass, $offset - 1), '\\' . $suiteClassName) === 0 || + stripos(substr($loadedClass, $offset - 1), '_' . $suiteClassName) === 0) { + $suiteClassName = $loadedClass; + + break; + } + } + } + + if (!class_exists($suiteClassName, false)) { + throw new Exception( + sprintf( + 'Class %s could not be found in %s', + $suiteClassName, + $suiteClassFile + ) + ); + } + + try { + $class = new ReflectionClass($suiteClassName); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + if ($class->isSubclassOf(TestCase::class)) { + if ($class->isAbstract()) { + throw new Exception( + sprintf( + 'Class %s declared in %s is abstract', + $suiteClassName, + $suiteClassFile + ) + ); + } + + return $class; + } + + if ($class->hasMethod('suite')) { + try { + $method = $class->getMethod('suite'); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + sprintf( + 'Method %s::suite() declared in %s is abstract', + $suiteClassName, + $suiteClassFile + ) + ); + } + + if (!$method->isPublic()) { + throw new Exception( + sprintf( + 'Method %s::suite() declared in %s is not public', + $suiteClassName, + $suiteClassFile + ) + ); + } + + if (!$method->isStatic()) { + throw new Exception( + sprintf( + 'Method %s::suite() declared in %s is not static', + $suiteClassName, + $suiteClassFile + ) + ); + } + } + + return $class; + } + + public function reload(ReflectionClass $aClass): ReflectionClass + { + return $aClass; + } +} diff --git a/vendor/phpunit/phpunit/src/Runner/TestResultCache.php b/vendor/phpunit/phpunit/src/Runner/TestResultCache.php new file mode 100644 index 00000000..69e62828 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/TestResultCache.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface TestResultCache +{ + public function setState(string $testName, int $state): void; + + public function getState(string $testName): int; + + public function setTime(string $testName, float $time): void; + + public function getTime(string $testName): float; + + public function load(): void; + + public function persist(): void; +} diff --git a/vendor/phpunit/phpunit/src/Runner/TestSuiteLoader.php b/vendor/phpunit/phpunit/src/Runner/TestSuiteLoader.php new file mode 100644 index 00000000..c9d8e01b --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/TestSuiteLoader.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use ReflectionClass; + +/** + * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039 + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface TestSuiteLoader +{ + public function load(string $suiteClassFile): ReflectionClass; + + public function reload(ReflectionClass $aClass): ReflectionClass; +} diff --git a/vendor/phpunit/phpunit/src/Runner/TestSuiteSorter.php b/vendor/phpunit/phpunit/src/Runner/TestSuiteSorter.php new file mode 100644 index 00000000..64ad845c --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/TestSuiteSorter.php @@ -0,0 +1,394 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function array_diff; +use function array_merge; +use function array_reverse; +use function array_splice; +use function count; +use function in_array; +use function max; +use function shuffle; +use function usort; +use PHPUnit\Framework\DataProviderTestSuite; +use PHPUnit\Framework\Reorderable; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Util\Test as TestUtil; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteSorter +{ + /** + * @var int + */ + public const ORDER_DEFAULT = 0; + + /** + * @var int + */ + public const ORDER_RANDOMIZED = 1; + + /** + * @var int + */ + public const ORDER_REVERSED = 2; + + /** + * @var int + */ + public const ORDER_DEFECTS_FIRST = 3; + + /** + * @var int + */ + public const ORDER_DURATION = 4; + + /** + * Order tests by @size annotation 'small', 'medium', 'large'. + * + * @var int + */ + public const ORDER_SIZE = 5; + + /** + * List of sorting weights for all test result codes. A higher number gives higher priority. + */ + private const DEFECT_SORT_WEIGHT = [ + BaseTestRunner::STATUS_ERROR => 6, + BaseTestRunner::STATUS_FAILURE => 5, + BaseTestRunner::STATUS_WARNING => 4, + BaseTestRunner::STATUS_INCOMPLETE => 3, + BaseTestRunner::STATUS_RISKY => 2, + BaseTestRunner::STATUS_SKIPPED => 1, + BaseTestRunner::STATUS_UNKNOWN => 0, + ]; + + private const SIZE_SORT_WEIGHT = [ + TestUtil::SMALL => 1, + TestUtil::MEDIUM => 2, + TestUtil::LARGE => 3, + TestUtil::UNKNOWN => 4, + ]; + + /** + * @var array Associative array of (string => DEFECT_SORT_WEIGHT) elements + */ + private $defectSortOrder = []; + + /** + * @var TestResultCache + */ + private $cache; + + /** + * @var array A list of normalized names of tests before reordering + */ + private $originalExecutionOrder = []; + + /** + * @var array A list of normalized names of tests affected by reordering + */ + private $executionOrder = []; + + public function __construct(?TestResultCache $cache = null) + { + $this->cache = $cache ?? new NullTestResultCache; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + */ + public function reorderTestsInSuite(Test $suite, int $order, bool $resolveDependencies, int $orderDefects, bool $isRootTestSuite = true): void + { + $allowedOrders = [ + self::ORDER_DEFAULT, + self::ORDER_REVERSED, + self::ORDER_RANDOMIZED, + self::ORDER_DURATION, + self::ORDER_SIZE, + ]; + + if (!in_array($order, $allowedOrders, true)) { + throw new Exception( + '$order must be one of TestSuiteSorter::ORDER_[DEFAULT|REVERSED|RANDOMIZED|DURATION|SIZE]' + ); + } + + $allowedOrderDefects = [ + self::ORDER_DEFAULT, + self::ORDER_DEFECTS_FIRST, + ]; + + if (!in_array($orderDefects, $allowedOrderDefects, true)) { + throw new Exception( + '$orderDefects must be one of TestSuiteSorter::ORDER_DEFAULT, TestSuiteSorter::ORDER_DEFECTS_FIRST' + ); + } + + if ($isRootTestSuite) { + $this->originalExecutionOrder = $this->calculateTestExecutionOrder($suite); + } + + if ($suite instanceof TestSuite) { + foreach ($suite as $_suite) { + $this->reorderTestsInSuite($_suite, $order, $resolveDependencies, $orderDefects, false); + } + + if ($orderDefects === self::ORDER_DEFECTS_FIRST) { + $this->addSuiteToDefectSortOrder($suite); + } + + $this->sort($suite, $order, $resolveDependencies, $orderDefects); + } + + if ($isRootTestSuite) { + $this->executionOrder = $this->calculateTestExecutionOrder($suite); + } + } + + public function getOriginalExecutionOrder(): array + { + return $this->originalExecutionOrder; + } + + public function getExecutionOrder(): array + { + return $this->executionOrder; + } + + private function sort(TestSuite $suite, int $order, bool $resolveDependencies, int $orderDefects): void + { + if (empty($suite->tests())) { + return; + } + + if ($order === self::ORDER_REVERSED) { + $suite->setTests($this->reverse($suite->tests())); + } elseif ($order === self::ORDER_RANDOMIZED) { + $suite->setTests($this->randomize($suite->tests())); + } elseif ($order === self::ORDER_DURATION && $this->cache !== null) { + $suite->setTests($this->sortByDuration($suite->tests())); + } elseif ($order === self::ORDER_SIZE) { + $suite->setTests($this->sortBySize($suite->tests())); + } + + if ($orderDefects === self::ORDER_DEFECTS_FIRST && $this->cache !== null) { + $suite->setTests($this->sortDefectsFirst($suite->tests())); + } + + if ($resolveDependencies && !($suite instanceof DataProviderTestSuite)) { + /** @var TestCase[] $tests */ + $tests = $suite->tests(); + + $suite->setTests($this->resolveDependencies($tests)); + } + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + private function addSuiteToDefectSortOrder(TestSuite $suite): void + { + $max = 0; + + foreach ($suite->tests() as $test) { + if (!$test instanceof Reorderable) { + continue; + } + + if (!isset($this->defectSortOrder[$test->sortId()])) { + $this->defectSortOrder[$test->sortId()] = self::DEFECT_SORT_WEIGHT[$this->cache->getState($test->sortId())]; + $max = max($max, $this->defectSortOrder[$test->sortId()]); + } + } + + $this->defectSortOrder[$suite->sortId()] = $max; + } + + private function reverse(array $tests): array + { + return array_reverse($tests); + } + + private function randomize(array $tests): array + { + shuffle($tests); + + return $tests; + } + + private function sortDefectsFirst(array $tests): array + { + usort( + $tests, + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + function ($left, $right) + { + return $this->cmpDefectPriorityAndTime($left, $right); + } + ); + + return $tests; + } + + private function sortByDuration(array $tests): array + { + usort( + $tests, + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + function ($left, $right) + { + return $this->cmpDuration($left, $right); + } + ); + + return $tests; + } + + private function sortBySize(array $tests): array + { + usort( + $tests, + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + function ($left, $right) + { + return $this->cmpSize($left, $right); + } + ); + + return $tests; + } + + /** + * Comparator callback function to sort tests for "reach failure as fast as possible". + * + * 1. sort tests by defect weight defined in self::DEFECT_SORT_WEIGHT + * 2. when tests are equally defective, sort the fastest to the front + * 3. do not reorder successful tests + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + private function cmpDefectPriorityAndTime(Test $a, Test $b): int + { + if (!($a instanceof Reorderable && $b instanceof Reorderable)) { + return 0; + } + + $priorityA = $this->defectSortOrder[$a->sortId()] ?? 0; + $priorityB = $this->defectSortOrder[$b->sortId()] ?? 0; + + if ($priorityB <=> $priorityA) { + // Sort defect weight descending + return $priorityB <=> $priorityA; + } + + if ($priorityA || $priorityB) { + return $this->cmpDuration($a, $b); + } + + // do not change execution order + return 0; + } + + /** + * Compares test duration for sorting tests by duration ascending. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + private function cmpDuration(Test $a, Test $b): int + { + if (!($a instanceof Reorderable && $b instanceof Reorderable)) { + return 0; + } + + return $this->cache->getTime($a->sortId()) <=> $this->cache->getTime($b->sortId()); + } + + /** + * Compares test size for sorting tests small->medium->large->unknown. + */ + private function cmpSize(Test $a, Test $b): int + { + $sizeA = ($a instanceof TestCase || $a instanceof DataProviderTestSuite) + ? $a->getSize() + : TestUtil::UNKNOWN; + $sizeB = ($b instanceof TestCase || $b instanceof DataProviderTestSuite) + ? $b->getSize() + : TestUtil::UNKNOWN; + + return self::SIZE_SORT_WEIGHT[$sizeA] <=> self::SIZE_SORT_WEIGHT[$sizeB]; + } + + /** + * Reorder Tests within a TestCase in such a way as to resolve as many dependencies as possible. + * The algorithm will leave the tests in original running order when it can. + * For more details see the documentation for test dependencies. + * + * Short description of algorithm: + * 1. Pick the next Test from remaining tests to be checked for dependencies. + * 2. If the test has no dependencies: mark done, start again from the top + * 3. If the test has dependencies but none left to do: mark done, start again from the top + * 4. When we reach the end add any leftover tests to the end. These will be marked 'skipped' during execution. + * + * @param array $tests + * + * @return array + */ + private function resolveDependencies(array $tests): array + { + $newTestOrder = []; + $i = 0; + $provided = []; + + do { + if ([] === array_diff($tests[$i]->requires(), $provided)) { + $provided = array_merge($provided, $tests[$i]->provides()); + $newTestOrder = array_merge($newTestOrder, array_splice($tests, $i, 1)); + $i = 0; + } else { + $i++; + } + } while (!empty($tests) && ($i < count($tests))); + + return array_merge($newTestOrder, $tests); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + private function calculateTestExecutionOrder(Test $suite): array + { + $tests = []; + + if ($suite instanceof TestSuite) { + foreach ($suite->tests() as $test) { + if (!$test instanceof TestSuite && $test instanceof Reorderable) { + $tests[] = $test->sortId(); + } else { + $tests = array_merge($tests, $this->calculateTestExecutionOrder($test)); + } + } + } + + return $tests; + } +} diff --git a/vendor/phpunit/phpunit/src/Runner/Version.php b/vendor/phpunit/phpunit/src/Runner/Version.php new file mode 100644 index 00000000..70de3024 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Runner/Version.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function array_slice; +use function dirname; +use function explode; +use function implode; +use function strpos; +use SebastianBergmann\Version as VersionId; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Version +{ + /** + * @var string + */ + private static $pharVersion = ''; + + /** + * @var string + */ + private static $version = ''; + + /** + * Returns the current version of PHPUnit. + */ + public static function id(): string + { + if (self::$pharVersion !== '') { + return self::$pharVersion; + } + + if (self::$version === '') { + self::$version = (new VersionId('9.6.3', dirname(__DIR__, 2)))->getVersion(); + } + + return self::$version; + } + + public static function series(): string + { + if (strpos(self::id(), '-')) { + $version = explode('-', self::id())[0]; + } else { + $version = self::id(); + } + + return implode('.', array_slice(explode('.', $version), 0, 2)); + } + + public static function getVersionString(): string + { + return 'PHPUnit ' . self::id() . ' by Sebastian Bergmann and contributors.'; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/CliArguments/Builder.php b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Builder.php new file mode 100644 index 00000000..9030b1db --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Builder.php @@ -0,0 +1,887 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\CliArguments; + +use function array_map; +use function array_merge; +use function class_exists; +use function explode; +use function is_numeric; +use function str_replace; +use PHPUnit\Runner\TestSuiteSorter; +use PHPUnit\TextUI\DefaultResultPrinter; +use PHPUnit\TextUI\XmlConfiguration\Extension; +use PHPUnit\Util\Log\TeamCity; +use PHPUnit\Util\TestDox\CliTestDoxPrinter; +use SebastianBergmann\CliParser\Exception as CliParserException; +use SebastianBergmann\CliParser\Parser as CliParser; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Builder +{ + private const LONG_OPTIONS = [ + 'atleast-version=', + 'prepend=', + 'bootstrap=', + 'cache-result', + 'do-not-cache-result', + 'cache-result-file=', + 'check-version', + 'colors==', + 'columns=', + 'configuration=', + 'coverage-cache=', + 'warm-coverage-cache', + 'coverage-filter=', + 'coverage-clover=', + 'coverage-cobertura=', + 'coverage-crap4j=', + 'coverage-html=', + 'coverage-php=', + 'coverage-text==', + 'coverage-xml=', + 'path-coverage', + 'debug', + 'disallow-test-output', + 'disallow-resource-usage', + 'disallow-todo-tests', + 'default-time-limit=', + 'enforce-time-limit', + 'exclude-group=', + 'extensions=', + 'filter=', + 'generate-configuration', + 'globals-backup', + 'group=', + 'covers=', + 'uses=', + 'help', + 'resolve-dependencies', + 'ignore-dependencies', + 'include-path=', + 'list-groups', + 'list-suites', + 'list-tests', + 'list-tests-xml=', + 'loader=', + 'log-junit=', + 'log-teamcity=', + 'migrate-configuration', + 'no-configuration', + 'no-coverage', + 'no-logging', + 'no-interaction', + 'no-extensions', + 'order-by=', + 'printer=', + 'process-isolation', + 'repeat=', + 'dont-report-useless-tests', + 'random-order', + 'random-order-seed=', + 'reverse-order', + 'reverse-list', + 'static-backup', + 'stderr', + 'stop-on-defect', + 'stop-on-error', + 'stop-on-failure', + 'stop-on-warning', + 'stop-on-incomplete', + 'stop-on-risky', + 'stop-on-skipped', + 'fail-on-empty-test-suite', + 'fail-on-incomplete', + 'fail-on-risky', + 'fail-on-skipped', + 'fail-on-warning', + 'strict-coverage', + 'disable-coverage-ignore', + 'strict-global-state', + 'teamcity', + 'testdox', + 'testdox-group=', + 'testdox-exclude-group=', + 'testdox-html=', + 'testdox-text=', + 'testdox-xml=', + 'test-suffix=', + 'testsuite=', + 'verbose', + 'version', + 'whitelist=', + 'dump-xdebug-filter=', + ]; + + private const SHORT_OPTIONS = 'd:c:hv'; + + public function fromParameters(array $parameters, array $additionalLongOptions): Configuration + { + try { + $options = (new CliParser)->parse( + $parameters, + self::SHORT_OPTIONS, + array_merge(self::LONG_OPTIONS, $additionalLongOptions) + ); + } catch (CliParserException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + + $argument = null; + $atLeastVersion = null; + $backupGlobals = null; + $backupStaticAttributes = null; + $beStrictAboutChangesToGlobalState = null; + $beStrictAboutResourceUsageDuringSmallTests = null; + $bootstrap = null; + $cacheResult = null; + $cacheResultFile = null; + $checkVersion = null; + $colors = null; + $columns = null; + $configuration = null; + $coverageCacheDirectory = null; + $warmCoverageCache = null; + $coverageFilter = null; + $coverageClover = null; + $coverageCobertura = null; + $coverageCrap4J = null; + $coverageHtml = null; + $coveragePhp = null; + $coverageText = null; + $coverageTextShowUncoveredFiles = null; + $coverageTextShowOnlySummary = null; + $coverageXml = null; + $pathCoverage = null; + $debug = null; + $defaultTimeLimit = null; + $disableCodeCoverageIgnore = null; + $disallowTestOutput = null; + $disallowTodoAnnotatedTests = null; + $enforceTimeLimit = null; + $excludeGroups = null; + $executionOrder = null; + $executionOrderDefects = null; + $extensions = []; + $unavailableExtensions = []; + $failOnEmptyTestSuite = null; + $failOnIncomplete = null; + $failOnRisky = null; + $failOnSkipped = null; + $failOnWarning = null; + $filter = null; + $generateConfiguration = null; + $migrateConfiguration = null; + $groups = null; + $testsCovering = null; + $testsUsing = null; + $help = null; + $includePath = null; + $iniSettings = []; + $junitLogfile = null; + $listGroups = null; + $listSuites = null; + $listTests = null; + $listTestsXml = null; + $loader = null; + $noCoverage = null; + $noExtensions = null; + $noInteraction = null; + $noLogging = null; + $printer = null; + $processIsolation = null; + $randomOrderSeed = null; + $repeat = null; + $reportUselessTests = null; + $resolveDependencies = null; + $reverseList = null; + $stderr = null; + $strictCoverage = null; + $stopOnDefect = null; + $stopOnError = null; + $stopOnFailure = null; + $stopOnIncomplete = null; + $stopOnRisky = null; + $stopOnSkipped = null; + $stopOnWarning = null; + $teamcityLogfile = null; + $testdoxExcludeGroups = null; + $testdoxGroups = null; + $testdoxHtmlFile = null; + $testdoxTextFile = null; + $testdoxXmlFile = null; + $testSuffixes = null; + $testSuite = null; + $unrecognizedOptions = []; + $unrecognizedOrderBy = null; + $useDefaultConfiguration = null; + $verbose = null; + $version = null; + $xdebugFilterFile = null; + + if (isset($options[1][0])) { + $argument = $options[1][0]; + } + + foreach ($options[0] as $option) { + switch ($option[0]) { + case '--colors': + $colors = $option[1] ?: DefaultResultPrinter::COLOR_AUTO; + + break; + + case '--bootstrap': + $bootstrap = $option[1]; + + break; + + case '--cache-result': + $cacheResult = true; + + break; + + case '--do-not-cache-result': + $cacheResult = false; + + break; + + case '--cache-result-file': + $cacheResultFile = $option[1]; + + break; + + case '--columns': + if (is_numeric($option[1])) { + $columns = (int) $option[1]; + } elseif ($option[1] === 'max') { + $columns = 'max'; + } + + break; + + case 'c': + case '--configuration': + $configuration = $option[1]; + + break; + + case '--coverage-cache': + $coverageCacheDirectory = $option[1]; + + break; + + case '--warm-coverage-cache': + $warmCoverageCache = true; + + break; + + case '--coverage-clover': + $coverageClover = $option[1]; + + break; + + case '--coverage-cobertura': + $coverageCobertura = $option[1]; + + break; + + case '--coverage-crap4j': + $coverageCrap4J = $option[1]; + + break; + + case '--coverage-html': + $coverageHtml = $option[1]; + + break; + + case '--coverage-php': + $coveragePhp = $option[1]; + + break; + + case '--coverage-text': + if ($option[1] === null) { + $option[1] = 'php://stdout'; + } + + $coverageText = $option[1]; + $coverageTextShowUncoveredFiles = false; + $coverageTextShowOnlySummary = false; + + break; + + case '--coverage-xml': + $coverageXml = $option[1]; + + break; + + case '--path-coverage': + $pathCoverage = true; + + break; + + case 'd': + $tmp = explode('=', $option[1]); + + if (isset($tmp[0])) { + if (isset($tmp[1])) { + $iniSettings[$tmp[0]] = $tmp[1]; + } else { + $iniSettings[$tmp[0]] = '1'; + } + } + + break; + + case '--debug': + $debug = true; + + break; + + case 'h': + case '--help': + $help = true; + + break; + + case '--filter': + $filter = $option[1]; + + break; + + case '--testsuite': + $testSuite = $option[1]; + + break; + + case '--generate-configuration': + $generateConfiguration = true; + + break; + + case '--migrate-configuration': + $migrateConfiguration = true; + + break; + + case '--group': + $groups = explode(',', $option[1]); + + break; + + case '--exclude-group': + $excludeGroups = explode(',', $option[1]); + + break; + + case '--covers': + $testsCovering = array_map('strtolower', explode(',', $option[1])); + + break; + + case '--uses': + $testsUsing = array_map('strtolower', explode(',', $option[1])); + + break; + + case '--test-suffix': + $testSuffixes = explode(',', $option[1]); + + break; + + case '--include-path': + $includePath = $option[1]; + + break; + + case '--list-groups': + $listGroups = true; + + break; + + case '--list-suites': + $listSuites = true; + + break; + + case '--list-tests': + $listTests = true; + + break; + + case '--list-tests-xml': + $listTestsXml = $option[1]; + + break; + + case '--printer': + $printer = $option[1]; + + break; + + case '--loader': + $loader = $option[1]; + + break; + + case '--log-junit': + $junitLogfile = $option[1]; + + break; + + case '--log-teamcity': + $teamcityLogfile = $option[1]; + + break; + + case '--order-by': + foreach (explode(',', $option[1]) as $order) { + switch ($order) { + case 'default': + $executionOrder = TestSuiteSorter::ORDER_DEFAULT; + $executionOrderDefects = TestSuiteSorter::ORDER_DEFAULT; + $resolveDependencies = true; + + break; + + case 'defects': + $executionOrderDefects = TestSuiteSorter::ORDER_DEFECTS_FIRST; + + break; + + case 'depends': + $resolveDependencies = true; + + break; + + case 'duration': + $executionOrder = TestSuiteSorter::ORDER_DURATION; + + break; + + case 'no-depends': + $resolveDependencies = false; + + break; + + case 'random': + $executionOrder = TestSuiteSorter::ORDER_RANDOMIZED; + + break; + + case 'reverse': + $executionOrder = TestSuiteSorter::ORDER_REVERSED; + + break; + + case 'size': + $executionOrder = TestSuiteSorter::ORDER_SIZE; + + break; + + default: + $unrecognizedOrderBy = $order; + } + } + + break; + + case '--process-isolation': + $processIsolation = true; + + break; + + case '--repeat': + $repeat = (int) $option[1]; + + break; + + case '--stderr': + $stderr = true; + + break; + + case '--stop-on-defect': + $stopOnDefect = true; + + break; + + case '--stop-on-error': + $stopOnError = true; + + break; + + case '--stop-on-failure': + $stopOnFailure = true; + + break; + + case '--stop-on-warning': + $stopOnWarning = true; + + break; + + case '--stop-on-incomplete': + $stopOnIncomplete = true; + + break; + + case '--stop-on-risky': + $stopOnRisky = true; + + break; + + case '--stop-on-skipped': + $stopOnSkipped = true; + + break; + + case '--fail-on-empty-test-suite': + $failOnEmptyTestSuite = true; + + break; + + case '--fail-on-incomplete': + $failOnIncomplete = true; + + break; + + case '--fail-on-risky': + $failOnRisky = true; + + break; + + case '--fail-on-skipped': + $failOnSkipped = true; + + break; + + case '--fail-on-warning': + $failOnWarning = true; + + break; + + case '--teamcity': + $printer = TeamCity::class; + + break; + + case '--testdox': + $printer = CliTestDoxPrinter::class; + + break; + + case '--testdox-group': + $testdoxGroups = explode(',', $option[1]); + + break; + + case '--testdox-exclude-group': + $testdoxExcludeGroups = explode(',', $option[1]); + + break; + + case '--testdox-html': + $testdoxHtmlFile = $option[1]; + + break; + + case '--testdox-text': + $testdoxTextFile = $option[1]; + + break; + + case '--testdox-xml': + $testdoxXmlFile = $option[1]; + + break; + + case '--no-configuration': + $useDefaultConfiguration = false; + + break; + + case '--extensions': + foreach (explode(',', $option[1]) as $extensionClass) { + if (!class_exists($extensionClass)) { + $unavailableExtensions[] = $extensionClass; + + continue; + } + + $extensions[] = new Extension($extensionClass, '', []); + } + + break; + + case '--no-extensions': + $noExtensions = true; + + break; + + case '--no-coverage': + $noCoverage = true; + + break; + + case '--no-logging': + $noLogging = true; + + break; + + case '--no-interaction': + $noInteraction = true; + + break; + + case '--globals-backup': + $backupGlobals = true; + + break; + + case '--static-backup': + $backupStaticAttributes = true; + + break; + + case 'v': + case '--verbose': + $verbose = true; + + break; + + case '--atleast-version': + $atLeastVersion = $option[1]; + + break; + + case '--version': + $version = true; + + break; + + case '--dont-report-useless-tests': + $reportUselessTests = false; + + break; + + case '--strict-coverage': + $strictCoverage = true; + + break; + + case '--disable-coverage-ignore': + $disableCodeCoverageIgnore = true; + + break; + + case '--strict-global-state': + $beStrictAboutChangesToGlobalState = true; + + break; + + case '--disallow-test-output': + $disallowTestOutput = true; + + break; + + case '--disallow-resource-usage': + $beStrictAboutResourceUsageDuringSmallTests = true; + + break; + + case '--default-time-limit': + $defaultTimeLimit = (int) $option[1]; + + break; + + case '--enforce-time-limit': + $enforceTimeLimit = true; + + break; + + case '--disallow-todo-tests': + $disallowTodoAnnotatedTests = true; + + break; + + case '--reverse-list': + $reverseList = true; + + break; + + case '--check-version': + $checkVersion = true; + + break; + + case '--coverage-filter': + case '--whitelist': + if ($coverageFilter === null) { + $coverageFilter = []; + } + + $coverageFilter[] = $option[1]; + + break; + + case '--random-order': + $executionOrder = TestSuiteSorter::ORDER_RANDOMIZED; + + break; + + case '--random-order-seed': + $randomOrderSeed = (int) $option[1]; + + break; + + case '--resolve-dependencies': + $resolveDependencies = true; + + break; + + case '--ignore-dependencies': + $resolveDependencies = false; + + break; + + case '--reverse-order': + $executionOrder = TestSuiteSorter::ORDER_REVERSED; + + break; + + case '--dump-xdebug-filter': + $xdebugFilterFile = $option[1]; + + break; + + default: + $unrecognizedOptions[str_replace('--', '', $option[0])] = $option[1]; + } + } + + if (empty($extensions)) { + $extensions = null; + } + + if (empty($unavailableExtensions)) { + $unavailableExtensions = null; + } + + if (empty($iniSettings)) { + $iniSettings = null; + } + + if (empty($coverageFilter)) { + $coverageFilter = null; + } + + return new Configuration( + $argument, + $atLeastVersion, + $backupGlobals, + $backupStaticAttributes, + $beStrictAboutChangesToGlobalState, + $beStrictAboutResourceUsageDuringSmallTests, + $bootstrap, + $cacheResult, + $cacheResultFile, + $checkVersion, + $colors, + $columns, + $configuration, + $coverageClover, + $coverageCobertura, + $coverageCrap4J, + $coverageHtml, + $coveragePhp, + $coverageText, + $coverageTextShowUncoveredFiles, + $coverageTextShowOnlySummary, + $coverageXml, + $pathCoverage, + $coverageCacheDirectory, + $warmCoverageCache, + $debug, + $defaultTimeLimit, + $disableCodeCoverageIgnore, + $disallowTestOutput, + $disallowTodoAnnotatedTests, + $enforceTimeLimit, + $excludeGroups, + $executionOrder, + $executionOrderDefects, + $extensions, + $unavailableExtensions, + $failOnEmptyTestSuite, + $failOnIncomplete, + $failOnRisky, + $failOnSkipped, + $failOnWarning, + $filter, + $generateConfiguration, + $migrateConfiguration, + $groups, + $testsCovering, + $testsUsing, + $help, + $includePath, + $iniSettings, + $junitLogfile, + $listGroups, + $listSuites, + $listTests, + $listTestsXml, + $loader, + $noCoverage, + $noExtensions, + $noInteraction, + $noLogging, + $printer, + $processIsolation, + $randomOrderSeed, + $repeat, + $reportUselessTests, + $resolveDependencies, + $reverseList, + $stderr, + $strictCoverage, + $stopOnDefect, + $stopOnError, + $stopOnFailure, + $stopOnIncomplete, + $stopOnRisky, + $stopOnSkipped, + $stopOnWarning, + $teamcityLogfile, + $testdoxExcludeGroups, + $testdoxGroups, + $testdoxHtmlFile, + $testdoxTextFile, + $testdoxXmlFile, + $testSuffixes, + $testSuite, + $unrecognizedOptions, + $unrecognizedOrderBy, + $useDefaultConfiguration, + $verbose, + $version, + $coverageFilter, + $xdebugFilterFile + ); + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/CliArguments/Configuration.php b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Configuration.php new file mode 100644 index 00000000..51bf5cb8 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Configuration.php @@ -0,0 +1,2108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\CliArguments; + +use PHPUnit\TextUI\XmlConfiguration\Extension; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Configuration +{ + /** + * @var ?string + */ + private $argument; + + /** + * @var ?string + */ + private $atLeastVersion; + + /** + * @var ?bool + */ + private $backupGlobals; + + /** + * @var ?bool + */ + private $backupStaticAttributes; + + /** + * @var ?bool + */ + private $beStrictAboutChangesToGlobalState; + + /** + * @var ?bool + */ + private $beStrictAboutResourceUsageDuringSmallTests; + + /** + * @var ?string + */ + private $bootstrap; + + /** + * @var ?bool + */ + private $cacheResult; + + /** + * @var ?string + */ + private $cacheResultFile; + + /** + * @var ?bool + */ + private $checkVersion; + + /** + * @var ?string + */ + private $colors; + + /** + * @var null|int|string + */ + private $columns; + + /** + * @var ?string + */ + private $configuration; + + /** + * @var null|string[] + */ + private $coverageFilter; + + /** + * @var ?string + */ + private $coverageClover; + + /** + * @var ?string + */ + private $coverageCobertura; + + /** + * @var ?string + */ + private $coverageCrap4J; + + /** + * @var ?string + */ + private $coverageHtml; + + /** + * @var ?string + */ + private $coveragePhp; + + /** + * @var ?string + */ + private $coverageText; + + /** + * @var ?bool + */ + private $coverageTextShowUncoveredFiles; + + /** + * @var ?bool + */ + private $coverageTextShowOnlySummary; + + /** + * @var ?string + */ + private $coverageXml; + + /** + * @var ?bool + */ + private $pathCoverage; + + /** + * @var ?string + */ + private $coverageCacheDirectory; + + /** + * @var ?bool + */ + private $warmCoverageCache; + + /** + * @var ?bool + */ + private $debug; + + /** + * @var ?int + */ + private $defaultTimeLimit; + + /** + * @var ?bool + */ + private $disableCodeCoverageIgnore; + + /** + * @var ?bool + */ + private $disallowTestOutput; + + /** + * @var ?bool + */ + private $disallowTodoAnnotatedTests; + + /** + * @var ?bool + */ + private $enforceTimeLimit; + + /** + * @var null|string[] + */ + private $excludeGroups; + + /** + * @var ?int + */ + private $executionOrder; + + /** + * @var ?int + */ + private $executionOrderDefects; + + /** + * @var null|Extension[] + */ + private $extensions; + + /** + * @var null|string[] + */ + private $unavailableExtensions; + + /** + * @var ?bool + */ + private $failOnEmptyTestSuite; + + /** + * @var ?bool + */ + private $failOnIncomplete; + + /** + * @var ?bool + */ + private $failOnRisky; + + /** + * @var ?bool + */ + private $failOnSkipped; + + /** + * @var ?bool + */ + private $failOnWarning; + + /** + * @var ?string + */ + private $filter; + + /** + * @var ?bool + */ + private $generateConfiguration; + + /** + * @var ?bool + */ + private $migrateConfiguration; + + /** + * @var null|string[] + */ + private $groups; + + /** + * @var null|string[] + */ + private $testsCovering; + + /** + * @var null|string[] + */ + private $testsUsing; + + /** + * @var ?bool + */ + private $help; + + /** + * @var ?string + */ + private $includePath; + + /** + * @var null|string[] + */ + private $iniSettings; + + /** + * @var ?string + */ + private $junitLogfile; + + /** + * @var ?bool + */ + private $listGroups; + + /** + * @var ?bool + */ + private $listSuites; + + /** + * @var ?bool + */ + private $listTests; + + /** + * @var ?string + */ + private $listTestsXml; + + /** + * @var ?string + */ + private $loader; + + /** + * @var ?bool + */ + private $noCoverage; + + /** + * @var ?bool + */ + private $noExtensions; + + /** + * @var ?bool + */ + private $noInteraction; + + /** + * @var ?bool + */ + private $noLogging; + + /** + * @var ?string + */ + private $printer; + + /** + * @var ?bool + */ + private $processIsolation; + + /** + * @var ?int + */ + private $randomOrderSeed; + + /** + * @var ?int + */ + private $repeat; + + /** + * @var ?bool + */ + private $reportUselessTests; + + /** + * @var ?bool + */ + private $resolveDependencies; + + /** + * @var ?bool + */ + private $reverseList; + + /** + * @var ?bool + */ + private $stderr; + + /** + * @var ?bool + */ + private $strictCoverage; + + /** + * @var ?bool + */ + private $stopOnDefect; + + /** + * @var ?bool + */ + private $stopOnError; + + /** + * @var ?bool + */ + private $stopOnFailure; + + /** + * @var ?bool + */ + private $stopOnIncomplete; + + /** + * @var ?bool + */ + private $stopOnRisky; + + /** + * @var ?bool + */ + private $stopOnSkipped; + + /** + * @var ?bool + */ + private $stopOnWarning; + + /** + * @var ?string + */ + private $teamcityLogfile; + + /** + * @var null|string[] + */ + private $testdoxExcludeGroups; + + /** + * @var null|string[] + */ + private $testdoxGroups; + + /** + * @var ?string + */ + private $testdoxHtmlFile; + + /** + * @var ?string + */ + private $testdoxTextFile; + + /** + * @var ?string + */ + private $testdoxXmlFile; + + /** + * @var null|string[] + */ + private $testSuffixes; + + /** + * @var ?string + */ + private $testSuite; + + /** + * @var string[] + */ + private $unrecognizedOptions; + + /** + * @var ?string + */ + private $unrecognizedOrderBy; + + /** + * @var ?bool + */ + private $useDefaultConfiguration; + + /** + * @var ?bool + */ + private $verbose; + + /** + * @var ?bool + */ + private $version; + + /** + * @var ?string + */ + private $xdebugFilterFile; + + /** + * @param null|int|string $columns + */ + public function __construct(?string $argument, ?string $atLeastVersion, ?bool $backupGlobals, ?bool $backupStaticAttributes, ?bool $beStrictAboutChangesToGlobalState, ?bool $beStrictAboutResourceUsageDuringSmallTests, ?string $bootstrap, ?bool $cacheResult, ?string $cacheResultFile, ?bool $checkVersion, ?string $colors, $columns, ?string $configuration, ?string $coverageClover, ?string $coverageCobertura, ?string $coverageCrap4J, ?string $coverageHtml, ?string $coveragePhp, ?string $coverageText, ?bool $coverageTextShowUncoveredFiles, ?bool $coverageTextShowOnlySummary, ?string $coverageXml, ?bool $pathCoverage, ?string $coverageCacheDirectory, ?bool $warmCoverageCache, ?bool $debug, ?int $defaultTimeLimit, ?bool $disableCodeCoverageIgnore, ?bool $disallowTestOutput, ?bool $disallowTodoAnnotatedTests, ?bool $enforceTimeLimit, ?array $excludeGroups, ?int $executionOrder, ?int $executionOrderDefects, ?array $extensions, ?array $unavailableExtensions, ?bool $failOnEmptyTestSuite, ?bool $failOnIncomplete, ?bool $failOnRisky, ?bool $failOnSkipped, ?bool $failOnWarning, ?string $filter, ?bool $generateConfiguration, ?bool $migrateConfiguration, ?array $groups, ?array $testsCovering, ?array $testsUsing, ?bool $help, ?string $includePath, ?array $iniSettings, ?string $junitLogfile, ?bool $listGroups, ?bool $listSuites, ?bool $listTests, ?string $listTestsXml, ?string $loader, ?bool $noCoverage, ?bool $noExtensions, ?bool $noInteraction, ?bool $noLogging, ?string $printer, ?bool $processIsolation, ?int $randomOrderSeed, ?int $repeat, ?bool $reportUselessTests, ?bool $resolveDependencies, ?bool $reverseList, ?bool $stderr, ?bool $strictCoverage, ?bool $stopOnDefect, ?bool $stopOnError, ?bool $stopOnFailure, ?bool $stopOnIncomplete, ?bool $stopOnRisky, ?bool $stopOnSkipped, ?bool $stopOnWarning, ?string $teamcityLogfile, ?array $testdoxExcludeGroups, ?array $testdoxGroups, ?string $testdoxHtmlFile, ?string $testdoxTextFile, ?string $testdoxXmlFile, ?array $testSuffixes, ?string $testSuite, array $unrecognizedOptions, ?string $unrecognizedOrderBy, ?bool $useDefaultConfiguration, ?bool $verbose, ?bool $version, ?array $coverageFilter, ?string $xdebugFilterFile) + { + $this->argument = $argument; + $this->atLeastVersion = $atLeastVersion; + $this->backupGlobals = $backupGlobals; + $this->backupStaticAttributes = $backupStaticAttributes; + $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; + $this->beStrictAboutResourceUsageDuringSmallTests = $beStrictAboutResourceUsageDuringSmallTests; + $this->bootstrap = $bootstrap; + $this->cacheResult = $cacheResult; + $this->cacheResultFile = $cacheResultFile; + $this->checkVersion = $checkVersion; + $this->colors = $colors; + $this->columns = $columns; + $this->configuration = $configuration; + $this->coverageFilter = $coverageFilter; + $this->coverageClover = $coverageClover; + $this->coverageCobertura = $coverageCobertura; + $this->coverageCrap4J = $coverageCrap4J; + $this->coverageHtml = $coverageHtml; + $this->coveragePhp = $coveragePhp; + $this->coverageText = $coverageText; + $this->coverageTextShowUncoveredFiles = $coverageTextShowUncoveredFiles; + $this->coverageTextShowOnlySummary = $coverageTextShowOnlySummary; + $this->coverageXml = $coverageXml; + $this->pathCoverage = $pathCoverage; + $this->coverageCacheDirectory = $coverageCacheDirectory; + $this->warmCoverageCache = $warmCoverageCache; + $this->debug = $debug; + $this->defaultTimeLimit = $defaultTimeLimit; + $this->disableCodeCoverageIgnore = $disableCodeCoverageIgnore; + $this->disallowTestOutput = $disallowTestOutput; + $this->disallowTodoAnnotatedTests = $disallowTodoAnnotatedTests; + $this->enforceTimeLimit = $enforceTimeLimit; + $this->excludeGroups = $excludeGroups; + $this->executionOrder = $executionOrder; + $this->executionOrderDefects = $executionOrderDefects; + $this->extensions = $extensions; + $this->unavailableExtensions = $unavailableExtensions; + $this->failOnEmptyTestSuite = $failOnEmptyTestSuite; + $this->failOnIncomplete = $failOnIncomplete; + $this->failOnRisky = $failOnRisky; + $this->failOnSkipped = $failOnSkipped; + $this->failOnWarning = $failOnWarning; + $this->filter = $filter; + $this->generateConfiguration = $generateConfiguration; + $this->migrateConfiguration = $migrateConfiguration; + $this->groups = $groups; + $this->testsCovering = $testsCovering; + $this->testsUsing = $testsUsing; + $this->help = $help; + $this->includePath = $includePath; + $this->iniSettings = $iniSettings; + $this->junitLogfile = $junitLogfile; + $this->listGroups = $listGroups; + $this->listSuites = $listSuites; + $this->listTests = $listTests; + $this->listTestsXml = $listTestsXml; + $this->loader = $loader; + $this->noCoverage = $noCoverage; + $this->noExtensions = $noExtensions; + $this->noInteraction = $noInteraction; + $this->noLogging = $noLogging; + $this->printer = $printer; + $this->processIsolation = $processIsolation; + $this->randomOrderSeed = $randomOrderSeed; + $this->repeat = $repeat; + $this->reportUselessTests = $reportUselessTests; + $this->resolveDependencies = $resolveDependencies; + $this->reverseList = $reverseList; + $this->stderr = $stderr; + $this->strictCoverage = $strictCoverage; + $this->stopOnDefect = $stopOnDefect; + $this->stopOnError = $stopOnError; + $this->stopOnFailure = $stopOnFailure; + $this->stopOnIncomplete = $stopOnIncomplete; + $this->stopOnRisky = $stopOnRisky; + $this->stopOnSkipped = $stopOnSkipped; + $this->stopOnWarning = $stopOnWarning; + $this->teamcityLogfile = $teamcityLogfile; + $this->testdoxExcludeGroups = $testdoxExcludeGroups; + $this->testdoxGroups = $testdoxGroups; + $this->testdoxHtmlFile = $testdoxHtmlFile; + $this->testdoxTextFile = $testdoxTextFile; + $this->testdoxXmlFile = $testdoxXmlFile; + $this->testSuffixes = $testSuffixes; + $this->testSuite = $testSuite; + $this->unrecognizedOptions = $unrecognizedOptions; + $this->unrecognizedOrderBy = $unrecognizedOrderBy; + $this->useDefaultConfiguration = $useDefaultConfiguration; + $this->verbose = $verbose; + $this->version = $version; + $this->xdebugFilterFile = $xdebugFilterFile; + } + + public function hasArgument(): bool + { + return $this->argument !== null; + } + + /** + * @throws Exception + */ + public function argument(): string + { + if ($this->argument === null) { + throw new Exception; + } + + return $this->argument; + } + + public function hasAtLeastVersion(): bool + { + return $this->atLeastVersion !== null; + } + + /** + * @throws Exception + */ + public function atLeastVersion(): string + { + if ($this->atLeastVersion === null) { + throw new Exception; + } + + return $this->atLeastVersion; + } + + public function hasBackupGlobals(): bool + { + return $this->backupGlobals !== null; + } + + /** + * @throws Exception + */ + public function backupGlobals(): bool + { + if ($this->backupGlobals === null) { + throw new Exception; + } + + return $this->backupGlobals; + } + + public function hasBackupStaticAttributes(): bool + { + return $this->backupStaticAttributes !== null; + } + + /** + * @throws Exception + */ + public function backupStaticAttributes(): bool + { + if ($this->backupStaticAttributes === null) { + throw new Exception; + } + + return $this->backupStaticAttributes; + } + + public function hasBeStrictAboutChangesToGlobalState(): bool + { + return $this->beStrictAboutChangesToGlobalState !== null; + } + + /** + * @throws Exception + */ + public function beStrictAboutChangesToGlobalState(): bool + { + if ($this->beStrictAboutChangesToGlobalState === null) { + throw new Exception; + } + + return $this->beStrictAboutChangesToGlobalState; + } + + public function hasBeStrictAboutResourceUsageDuringSmallTests(): bool + { + return $this->beStrictAboutResourceUsageDuringSmallTests !== null; + } + + /** + * @throws Exception + */ + public function beStrictAboutResourceUsageDuringSmallTests(): bool + { + if ($this->beStrictAboutResourceUsageDuringSmallTests === null) { + throw new Exception; + } + + return $this->beStrictAboutResourceUsageDuringSmallTests; + } + + public function hasBootstrap(): bool + { + return $this->bootstrap !== null; + } + + /** + * @throws Exception + */ + public function bootstrap(): string + { + if ($this->bootstrap === null) { + throw new Exception; + } + + return $this->bootstrap; + } + + public function hasCacheResult(): bool + { + return $this->cacheResult !== null; + } + + /** + * @throws Exception + */ + public function cacheResult(): bool + { + if ($this->cacheResult === null) { + throw new Exception; + } + + return $this->cacheResult; + } + + public function hasCacheResultFile(): bool + { + return $this->cacheResultFile !== null; + } + + /** + * @throws Exception + */ + public function cacheResultFile(): string + { + if ($this->cacheResultFile === null) { + throw new Exception; + } + + return $this->cacheResultFile; + } + + public function hasCheckVersion(): bool + { + return $this->checkVersion !== null; + } + + /** + * @throws Exception + */ + public function checkVersion(): bool + { + if ($this->checkVersion === null) { + throw new Exception; + } + + return $this->checkVersion; + } + + public function hasColors(): bool + { + return $this->colors !== null; + } + + /** + * @throws Exception + */ + public function colors(): string + { + if ($this->colors === null) { + throw new Exception; + } + + return $this->colors; + } + + public function hasColumns(): bool + { + return $this->columns !== null; + } + + /** + * @throws Exception + */ + public function columns() + { + if ($this->columns === null) { + throw new Exception; + } + + return $this->columns; + } + + public function hasConfiguration(): bool + { + return $this->configuration !== null; + } + + /** + * @throws Exception + */ + public function configuration(): string + { + if ($this->configuration === null) { + throw new Exception; + } + + return $this->configuration; + } + + public function hasCoverageFilter(): bool + { + return $this->coverageFilter !== null; + } + + /** + * @throws Exception + */ + public function coverageFilter(): array + { + if ($this->coverageFilter === null) { + throw new Exception; + } + + return $this->coverageFilter; + } + + public function hasCoverageClover(): bool + { + return $this->coverageClover !== null; + } + + /** + * @throws Exception + */ + public function coverageClover(): string + { + if ($this->coverageClover === null) { + throw new Exception; + } + + return $this->coverageClover; + } + + public function hasCoverageCobertura(): bool + { + return $this->coverageCobertura !== null; + } + + /** + * @throws Exception + */ + public function coverageCobertura(): string + { + if ($this->coverageCobertura === null) { + throw new Exception; + } + + return $this->coverageCobertura; + } + + public function hasCoverageCrap4J(): bool + { + return $this->coverageCrap4J !== null; + } + + /** + * @throws Exception + */ + public function coverageCrap4J(): string + { + if ($this->coverageCrap4J === null) { + throw new Exception; + } + + return $this->coverageCrap4J; + } + + public function hasCoverageHtml(): bool + { + return $this->coverageHtml !== null; + } + + /** + * @throws Exception + */ + public function coverageHtml(): string + { + if ($this->coverageHtml === null) { + throw new Exception; + } + + return $this->coverageHtml; + } + + public function hasCoveragePhp(): bool + { + return $this->coveragePhp !== null; + } + + /** + * @throws Exception + */ + public function coveragePhp(): string + { + if ($this->coveragePhp === null) { + throw new Exception; + } + + return $this->coveragePhp; + } + + public function hasCoverageText(): bool + { + return $this->coverageText !== null; + } + + /** + * @throws Exception + */ + public function coverageText(): string + { + if ($this->coverageText === null) { + throw new Exception; + } + + return $this->coverageText; + } + + public function hasCoverageTextShowUncoveredFiles(): bool + { + return $this->coverageTextShowUncoveredFiles !== null; + } + + /** + * @throws Exception + */ + public function coverageTextShowUncoveredFiles(): bool + { + if ($this->coverageTextShowUncoveredFiles === null) { + throw new Exception; + } + + return $this->coverageTextShowUncoveredFiles; + } + + public function hasCoverageTextShowOnlySummary(): bool + { + return $this->coverageTextShowOnlySummary !== null; + } + + /** + * @throws Exception + */ + public function coverageTextShowOnlySummary(): bool + { + if ($this->coverageTextShowOnlySummary === null) { + throw new Exception; + } + + return $this->coverageTextShowOnlySummary; + } + + public function hasCoverageXml(): bool + { + return $this->coverageXml !== null; + } + + /** + * @throws Exception + */ + public function coverageXml(): string + { + if ($this->coverageXml === null) { + throw new Exception; + } + + return $this->coverageXml; + } + + public function hasPathCoverage(): bool + { + return $this->pathCoverage !== null; + } + + /** + * @throws Exception + */ + public function pathCoverage(): bool + { + if ($this->pathCoverage === null) { + throw new Exception; + } + + return $this->pathCoverage; + } + + public function hasCoverageCacheDirectory(): bool + { + return $this->coverageCacheDirectory !== null; + } + + /** + * @throws Exception + */ + public function coverageCacheDirectory(): string + { + if ($this->coverageCacheDirectory === null) { + throw new Exception; + } + + return $this->coverageCacheDirectory; + } + + public function hasWarmCoverageCache(): bool + { + return $this->warmCoverageCache !== null; + } + + /** + * @throws Exception + */ + public function warmCoverageCache(): bool + { + if ($this->warmCoverageCache === null) { + throw new Exception; + } + + return $this->warmCoverageCache; + } + + public function hasDebug(): bool + { + return $this->debug !== null; + } + + /** + * @throws Exception + */ + public function debug(): bool + { + if ($this->debug === null) { + throw new Exception; + } + + return $this->debug; + } + + public function hasDefaultTimeLimit(): bool + { + return $this->defaultTimeLimit !== null; + } + + /** + * @throws Exception + */ + public function defaultTimeLimit(): int + { + if ($this->defaultTimeLimit === null) { + throw new Exception; + } + + return $this->defaultTimeLimit; + } + + public function hasDisableCodeCoverageIgnore(): bool + { + return $this->disableCodeCoverageIgnore !== null; + } + + /** + * @throws Exception + */ + public function disableCodeCoverageIgnore(): bool + { + if ($this->disableCodeCoverageIgnore === null) { + throw new Exception; + } + + return $this->disableCodeCoverageIgnore; + } + + public function hasDisallowTestOutput(): bool + { + return $this->disallowTestOutput !== null; + } + + /** + * @throws Exception + */ + public function disallowTestOutput(): bool + { + if ($this->disallowTestOutput === null) { + throw new Exception; + } + + return $this->disallowTestOutput; + } + + public function hasDisallowTodoAnnotatedTests(): bool + { + return $this->disallowTodoAnnotatedTests !== null; + } + + /** + * @throws Exception + */ + public function disallowTodoAnnotatedTests(): bool + { + if ($this->disallowTodoAnnotatedTests === null) { + throw new Exception; + } + + return $this->disallowTodoAnnotatedTests; + } + + public function hasEnforceTimeLimit(): bool + { + return $this->enforceTimeLimit !== null; + } + + /** + * @throws Exception + */ + public function enforceTimeLimit(): bool + { + if ($this->enforceTimeLimit === null) { + throw new Exception; + } + + return $this->enforceTimeLimit; + } + + public function hasExcludeGroups(): bool + { + return $this->excludeGroups !== null; + } + + /** + * @throws Exception + */ + public function excludeGroups(): array + { + if ($this->excludeGroups === null) { + throw new Exception; + } + + return $this->excludeGroups; + } + + public function hasExecutionOrder(): bool + { + return $this->executionOrder !== null; + } + + /** + * @throws Exception + */ + public function executionOrder(): int + { + if ($this->executionOrder === null) { + throw new Exception; + } + + return $this->executionOrder; + } + + public function hasExecutionOrderDefects(): bool + { + return $this->executionOrderDefects !== null; + } + + /** + * @throws Exception + */ + public function executionOrderDefects(): int + { + if ($this->executionOrderDefects === null) { + throw new Exception; + } + + return $this->executionOrderDefects; + } + + public function hasFailOnEmptyTestSuite(): bool + { + return $this->failOnEmptyTestSuite !== null; + } + + /** + * @throws Exception + */ + public function failOnEmptyTestSuite(): bool + { + if ($this->failOnEmptyTestSuite === null) { + throw new Exception; + } + + return $this->failOnEmptyTestSuite; + } + + public function hasFailOnIncomplete(): bool + { + return $this->failOnIncomplete !== null; + } + + /** + * @throws Exception + */ + public function failOnIncomplete(): bool + { + if ($this->failOnIncomplete === null) { + throw new Exception; + } + + return $this->failOnIncomplete; + } + + public function hasFailOnRisky(): bool + { + return $this->failOnRisky !== null; + } + + /** + * @throws Exception + */ + public function failOnRisky(): bool + { + if ($this->failOnRisky === null) { + throw new Exception; + } + + return $this->failOnRisky; + } + + public function hasFailOnSkipped(): bool + { + return $this->failOnSkipped !== null; + } + + /** + * @throws Exception + */ + public function failOnSkipped(): bool + { + if ($this->failOnSkipped === null) { + throw new Exception; + } + + return $this->failOnSkipped; + } + + public function hasFailOnWarning(): bool + { + return $this->failOnWarning !== null; + } + + /** + * @throws Exception + */ + public function failOnWarning(): bool + { + if ($this->failOnWarning === null) { + throw new Exception; + } + + return $this->failOnWarning; + } + + public function hasFilter(): bool + { + return $this->filter !== null; + } + + /** + * @throws Exception + */ + public function filter(): string + { + if ($this->filter === null) { + throw new Exception; + } + + return $this->filter; + } + + public function hasGenerateConfiguration(): bool + { + return $this->generateConfiguration !== null; + } + + /** + * @throws Exception + */ + public function generateConfiguration(): bool + { + if ($this->generateConfiguration === null) { + throw new Exception; + } + + return $this->generateConfiguration; + } + + public function hasMigrateConfiguration(): bool + { + return $this->migrateConfiguration !== null; + } + + /** + * @throws Exception + */ + public function migrateConfiguration(): bool + { + if ($this->migrateConfiguration === null) { + throw new Exception; + } + + return $this->migrateConfiguration; + } + + public function hasGroups(): bool + { + return $this->groups !== null; + } + + /** + * @throws Exception + */ + public function groups(): array + { + if ($this->groups === null) { + throw new Exception; + } + + return $this->groups; + } + + public function hasTestsCovering(): bool + { + return $this->testsCovering !== null; + } + + /** + * @throws Exception + */ + public function testsCovering(): array + { + if ($this->testsCovering === null) { + throw new Exception; + } + + return $this->testsCovering; + } + + public function hasTestsUsing(): bool + { + return $this->testsUsing !== null; + } + + /** + * @throws Exception + */ + public function testsUsing(): array + { + if ($this->testsUsing === null) { + throw new Exception; + } + + return $this->testsUsing; + } + + public function hasHelp(): bool + { + return $this->help !== null; + } + + /** + * @throws Exception + */ + public function help(): bool + { + if ($this->help === null) { + throw new Exception; + } + + return $this->help; + } + + public function hasIncludePath(): bool + { + return $this->includePath !== null; + } + + /** + * @throws Exception + */ + public function includePath(): string + { + if ($this->includePath === null) { + throw new Exception; + } + + return $this->includePath; + } + + public function hasIniSettings(): bool + { + return $this->iniSettings !== null; + } + + /** + * @throws Exception + */ + public function iniSettings(): array + { + if ($this->iniSettings === null) { + throw new Exception; + } + + return $this->iniSettings; + } + + public function hasJunitLogfile(): bool + { + return $this->junitLogfile !== null; + } + + /** + * @throws Exception + */ + public function junitLogfile(): string + { + if ($this->junitLogfile === null) { + throw new Exception; + } + + return $this->junitLogfile; + } + + public function hasListGroups(): bool + { + return $this->listGroups !== null; + } + + /** + * @throws Exception + */ + public function listGroups(): bool + { + if ($this->listGroups === null) { + throw new Exception; + } + + return $this->listGroups; + } + + public function hasListSuites(): bool + { + return $this->listSuites !== null; + } + + /** + * @throws Exception + */ + public function listSuites(): bool + { + if ($this->listSuites === null) { + throw new Exception; + } + + return $this->listSuites; + } + + public function hasListTests(): bool + { + return $this->listTests !== null; + } + + /** + * @throws Exception + */ + public function listTests(): bool + { + if ($this->listTests === null) { + throw new Exception; + } + + return $this->listTests; + } + + public function hasListTestsXml(): bool + { + return $this->listTestsXml !== null; + } + + /** + * @throws Exception + */ + public function listTestsXml(): string + { + if ($this->listTestsXml === null) { + throw new Exception; + } + + return $this->listTestsXml; + } + + public function hasLoader(): bool + { + return $this->loader !== null; + } + + /** + * @throws Exception + */ + public function loader(): string + { + if ($this->loader === null) { + throw new Exception; + } + + return $this->loader; + } + + public function hasNoCoverage(): bool + { + return $this->noCoverage !== null; + } + + /** + * @throws Exception + */ + public function noCoverage(): bool + { + if ($this->noCoverage === null) { + throw new Exception; + } + + return $this->noCoverage; + } + + public function hasNoExtensions(): bool + { + return $this->noExtensions !== null; + } + + /** + * @throws Exception + */ + public function noExtensions(): bool + { + if ($this->noExtensions === null) { + throw new Exception; + } + + return $this->noExtensions; + } + + public function hasExtensions(): bool + { + return $this->extensions !== null; + } + + /** + * @throws Exception + */ + public function extensions(): array + { + if ($this->extensions === null) { + throw new Exception; + } + + return $this->extensions; + } + + public function hasUnavailableExtensions(): bool + { + return $this->unavailableExtensions !== null; + } + + /** + * @throws Exception + */ + public function unavailableExtensions(): array + { + if ($this->unavailableExtensions === null) { + throw new Exception; + } + + return $this->unavailableExtensions; + } + + public function hasNoInteraction(): bool + { + return $this->noInteraction !== null; + } + + /** + * @throws Exception + */ + public function noInteraction(): bool + { + if ($this->noInteraction === null) { + throw new Exception; + } + + return $this->noInteraction; + } + + public function hasNoLogging(): bool + { + return $this->noLogging !== null; + } + + /** + * @throws Exception + */ + public function noLogging(): bool + { + if ($this->noLogging === null) { + throw new Exception; + } + + return $this->noLogging; + } + + public function hasPrinter(): bool + { + return $this->printer !== null; + } + + /** + * @throws Exception + */ + public function printer(): string + { + if ($this->printer === null) { + throw new Exception; + } + + return $this->printer; + } + + public function hasProcessIsolation(): bool + { + return $this->processIsolation !== null; + } + + /** + * @throws Exception + */ + public function processIsolation(): bool + { + if ($this->processIsolation === null) { + throw new Exception; + } + + return $this->processIsolation; + } + + public function hasRandomOrderSeed(): bool + { + return $this->randomOrderSeed !== null; + } + + /** + * @throws Exception + */ + public function randomOrderSeed(): int + { + if ($this->randomOrderSeed === null) { + throw new Exception; + } + + return $this->randomOrderSeed; + } + + public function hasRepeat(): bool + { + return $this->repeat !== null; + } + + /** + * @throws Exception + */ + public function repeat(): int + { + if ($this->repeat === null) { + throw new Exception; + } + + return $this->repeat; + } + + public function hasReportUselessTests(): bool + { + return $this->reportUselessTests !== null; + } + + /** + * @throws Exception + */ + public function reportUselessTests(): bool + { + if ($this->reportUselessTests === null) { + throw new Exception; + } + + return $this->reportUselessTests; + } + + public function hasResolveDependencies(): bool + { + return $this->resolveDependencies !== null; + } + + /** + * @throws Exception + */ + public function resolveDependencies(): bool + { + if ($this->resolveDependencies === null) { + throw new Exception; + } + + return $this->resolveDependencies; + } + + public function hasReverseList(): bool + { + return $this->reverseList !== null; + } + + /** + * @throws Exception + */ + public function reverseList(): bool + { + if ($this->reverseList === null) { + throw new Exception; + } + + return $this->reverseList; + } + + public function hasStderr(): bool + { + return $this->stderr !== null; + } + + /** + * @throws Exception + */ + public function stderr(): bool + { + if ($this->stderr === null) { + throw new Exception; + } + + return $this->stderr; + } + + public function hasStrictCoverage(): bool + { + return $this->strictCoverage !== null; + } + + /** + * @throws Exception + */ + public function strictCoverage(): bool + { + if ($this->strictCoverage === null) { + throw new Exception; + } + + return $this->strictCoverage; + } + + public function hasStopOnDefect(): bool + { + return $this->stopOnDefect !== null; + } + + /** + * @throws Exception + */ + public function stopOnDefect(): bool + { + if ($this->stopOnDefect === null) { + throw new Exception; + } + + return $this->stopOnDefect; + } + + public function hasStopOnError(): bool + { + return $this->stopOnError !== null; + } + + /** + * @throws Exception + */ + public function stopOnError(): bool + { + if ($this->stopOnError === null) { + throw new Exception; + } + + return $this->stopOnError; + } + + public function hasStopOnFailure(): bool + { + return $this->stopOnFailure !== null; + } + + /** + * @throws Exception + */ + public function stopOnFailure(): bool + { + if ($this->stopOnFailure === null) { + throw new Exception; + } + + return $this->stopOnFailure; + } + + public function hasStopOnIncomplete(): bool + { + return $this->stopOnIncomplete !== null; + } + + /** + * @throws Exception + */ + public function stopOnIncomplete(): bool + { + if ($this->stopOnIncomplete === null) { + throw new Exception; + } + + return $this->stopOnIncomplete; + } + + public function hasStopOnRisky(): bool + { + return $this->stopOnRisky !== null; + } + + /** + * @throws Exception + */ + public function stopOnRisky(): bool + { + if ($this->stopOnRisky === null) { + throw new Exception; + } + + return $this->stopOnRisky; + } + + public function hasStopOnSkipped(): bool + { + return $this->stopOnSkipped !== null; + } + + /** + * @throws Exception + */ + public function stopOnSkipped(): bool + { + if ($this->stopOnSkipped === null) { + throw new Exception; + } + + return $this->stopOnSkipped; + } + + public function hasStopOnWarning(): bool + { + return $this->stopOnWarning !== null; + } + + /** + * @throws Exception + */ + public function stopOnWarning(): bool + { + if ($this->stopOnWarning === null) { + throw new Exception; + } + + return $this->stopOnWarning; + } + + public function hasTeamcityLogfile(): bool + { + return $this->teamcityLogfile !== null; + } + + /** + * @throws Exception + */ + public function teamcityLogfile(): string + { + if ($this->teamcityLogfile === null) { + throw new Exception; + } + + return $this->teamcityLogfile; + } + + public function hasTestdoxExcludeGroups(): bool + { + return $this->testdoxExcludeGroups !== null; + } + + /** + * @throws Exception + */ + public function testdoxExcludeGroups(): array + { + if ($this->testdoxExcludeGroups === null) { + throw new Exception; + } + + return $this->testdoxExcludeGroups; + } + + public function hasTestdoxGroups(): bool + { + return $this->testdoxGroups !== null; + } + + /** + * @throws Exception + */ + public function testdoxGroups(): array + { + if ($this->testdoxGroups === null) { + throw new Exception; + } + + return $this->testdoxGroups; + } + + public function hasTestdoxHtmlFile(): bool + { + return $this->testdoxHtmlFile !== null; + } + + /** + * @throws Exception + */ + public function testdoxHtmlFile(): string + { + if ($this->testdoxHtmlFile === null) { + throw new Exception; + } + + return $this->testdoxHtmlFile; + } + + public function hasTestdoxTextFile(): bool + { + return $this->testdoxTextFile !== null; + } + + /** + * @throws Exception + */ + public function testdoxTextFile(): string + { + if ($this->testdoxTextFile === null) { + throw new Exception; + } + + return $this->testdoxTextFile; + } + + public function hasTestdoxXmlFile(): bool + { + return $this->testdoxXmlFile !== null; + } + + /** + * @throws Exception + */ + public function testdoxXmlFile(): string + { + if ($this->testdoxXmlFile === null) { + throw new Exception; + } + + return $this->testdoxXmlFile; + } + + public function hasTestSuffixes(): bool + { + return $this->testSuffixes !== null; + } + + /** + * @throws Exception + */ + public function testSuffixes(): array + { + if ($this->testSuffixes === null) { + throw new Exception; + } + + return $this->testSuffixes; + } + + public function hasTestSuite(): bool + { + return $this->testSuite !== null; + } + + /** + * @throws Exception + */ + public function testSuite(): string + { + if ($this->testSuite === null) { + throw new Exception; + } + + return $this->testSuite; + } + + public function unrecognizedOptions(): array + { + return $this->unrecognizedOptions; + } + + public function hasUnrecognizedOrderBy(): bool + { + return $this->unrecognizedOrderBy !== null; + } + + /** + * @throws Exception + */ + public function unrecognizedOrderBy(): string + { + if ($this->unrecognizedOrderBy === null) { + throw new Exception; + } + + return $this->unrecognizedOrderBy; + } + + public function hasUseDefaultConfiguration(): bool + { + return $this->useDefaultConfiguration !== null; + } + + /** + * @throws Exception + */ + public function useDefaultConfiguration(): bool + { + if ($this->useDefaultConfiguration === null) { + throw new Exception; + } + + return $this->useDefaultConfiguration; + } + + public function hasVerbose(): bool + { + return $this->verbose !== null; + } + + /** + * @throws Exception + */ + public function verbose(): bool + { + if ($this->verbose === null) { + throw new Exception; + } + + return $this->verbose; + } + + public function hasVersion(): bool + { + return $this->version !== null; + } + + /** + * @throws Exception + */ + public function version(): bool + { + if ($this->version === null) { + throw new Exception; + } + + return $this->version; + } + + public function hasXdebugFilterFile(): bool + { + return $this->xdebugFilterFile !== null; + } + + /** + * @throws Exception + */ + public function xdebugFilterFile(): string + { + if ($this->xdebugFilterFile === null) { + throw new Exception; + } + + return $this->xdebugFilterFile; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/CliArguments/Exception.php b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Exception.php new file mode 100644 index 00000000..dd5536ea --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Exception.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\CliArguments; + +use RuntimeException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Exception extends RuntimeException implements \PHPUnit\Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/TextUI/CliArguments/Mapper.php b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Mapper.php new file mode 100644 index 00000000..9ceb8ab4 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/CliArguments/Mapper.php @@ -0,0 +1,365 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\CliArguments; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Mapper +{ + /** + * @throws Exception + */ + public function mapToLegacyArray(Configuration $arguments): array + { + $result = [ + 'extensions' => [], + 'listGroups' => false, + 'listSuites' => false, + 'listTests' => false, + 'listTestsXml' => false, + 'loader' => null, + 'useDefaultConfiguration' => true, + 'loadedExtensions' => [], + 'unavailableExtensions' => [], + 'notLoadedExtensions' => [], + ]; + + if ($arguments->hasColors()) { + $result['colors'] = $arguments->colors(); + } + + if ($arguments->hasBootstrap()) { + $result['bootstrap'] = $arguments->bootstrap(); + } + + if ($arguments->hasCacheResult()) { + $result['cacheResult'] = $arguments->cacheResult(); + } + + if ($arguments->hasCacheResultFile()) { + $result['cacheResultFile'] = $arguments->cacheResultFile(); + } + + if ($arguments->hasColumns()) { + $result['columns'] = $arguments->columns(); + } + + if ($arguments->hasConfiguration()) { + $result['configuration'] = $arguments->configuration(); + } + + if ($arguments->hasCoverageCacheDirectory()) { + $result['coverageCacheDirectory'] = $arguments->coverageCacheDirectory(); + } + + if ($arguments->hasWarmCoverageCache()) { + $result['warmCoverageCache'] = $arguments->warmCoverageCache(); + } + + if ($arguments->hasCoverageClover()) { + $result['coverageClover'] = $arguments->coverageClover(); + } + + if ($arguments->hasCoverageCobertura()) { + $result['coverageCobertura'] = $arguments->coverageCobertura(); + } + + if ($arguments->hasCoverageCrap4J()) { + $result['coverageCrap4J'] = $arguments->coverageCrap4J(); + } + + if ($arguments->hasCoverageHtml()) { + $result['coverageHtml'] = $arguments->coverageHtml(); + } + + if ($arguments->hasCoveragePhp()) { + $result['coveragePHP'] = $arguments->coveragePhp(); + } + + if ($arguments->hasCoverageText()) { + $result['coverageText'] = $arguments->coverageText(); + } + + if ($arguments->hasCoverageTextShowUncoveredFiles()) { + $result['coverageTextShowUncoveredFiles'] = $arguments->hasCoverageTextShowUncoveredFiles(); + } + + if ($arguments->hasCoverageTextShowOnlySummary()) { + $result['coverageTextShowOnlySummary'] = $arguments->coverageTextShowOnlySummary(); + } + + if ($arguments->hasCoverageXml()) { + $result['coverageXml'] = $arguments->coverageXml(); + } + + if ($arguments->hasPathCoverage()) { + $result['pathCoverage'] = $arguments->pathCoverage(); + } + + if ($arguments->hasDebug()) { + $result['debug'] = $arguments->debug(); + } + + if ($arguments->hasHelp()) { + $result['help'] = $arguments->help(); + } + + if ($arguments->hasFilter()) { + $result['filter'] = $arguments->filter(); + } + + if ($arguments->hasTestSuite()) { + $result['testsuite'] = $arguments->testSuite(); + } + + if ($arguments->hasGroups()) { + $result['groups'] = $arguments->groups(); + } + + if ($arguments->hasExcludeGroups()) { + $result['excludeGroups'] = $arguments->excludeGroups(); + } + + if ($arguments->hasTestsCovering()) { + $result['testsCovering'] = $arguments->testsCovering(); + } + + if ($arguments->hasTestsUsing()) { + $result['testsUsing'] = $arguments->testsUsing(); + } + + if ($arguments->hasTestSuffixes()) { + $result['testSuffixes'] = $arguments->testSuffixes(); + } + + if ($arguments->hasIncludePath()) { + $result['includePath'] = $arguments->includePath(); + } + + if ($arguments->hasListGroups()) { + $result['listGroups'] = $arguments->listGroups(); + } + + if ($arguments->hasListSuites()) { + $result['listSuites'] = $arguments->listSuites(); + } + + if ($arguments->hasListTests()) { + $result['listTests'] = $arguments->listTests(); + } + + if ($arguments->hasListTestsXml()) { + $result['listTestsXml'] = $arguments->listTestsXml(); + } + + if ($arguments->hasPrinter()) { + $result['printer'] = $arguments->printer(); + } + + if ($arguments->hasLoader()) { + $result['loader'] = $arguments->loader(); + } + + if ($arguments->hasJunitLogfile()) { + $result['junitLogfile'] = $arguments->junitLogfile(); + } + + if ($arguments->hasTeamcityLogfile()) { + $result['teamcityLogfile'] = $arguments->teamcityLogfile(); + } + + if ($arguments->hasExecutionOrder()) { + $result['executionOrder'] = $arguments->executionOrder(); + } + + if ($arguments->hasExecutionOrderDefects()) { + $result['executionOrderDefects'] = $arguments->executionOrderDefects(); + } + + if ($arguments->hasExtensions()) { + $result['extensions'] = $arguments->extensions(); + } + + if ($arguments->hasUnavailableExtensions()) { + $result['unavailableExtensions'] = $arguments->unavailableExtensions(); + } + + if ($arguments->hasResolveDependencies()) { + $result['resolveDependencies'] = $arguments->resolveDependencies(); + } + + if ($arguments->hasProcessIsolation()) { + $result['processIsolation'] = $arguments->processIsolation(); + } + + if ($arguments->hasRepeat()) { + $result['repeat'] = $arguments->repeat(); + } + + if ($arguments->hasStderr()) { + $result['stderr'] = $arguments->stderr(); + } + + if ($arguments->hasStopOnDefect()) { + $result['stopOnDefect'] = $arguments->stopOnDefect(); + } + + if ($arguments->hasStopOnError()) { + $result['stopOnError'] = $arguments->stopOnError(); + } + + if ($arguments->hasStopOnFailure()) { + $result['stopOnFailure'] = $arguments->stopOnFailure(); + } + + if ($arguments->hasStopOnWarning()) { + $result['stopOnWarning'] = $arguments->stopOnWarning(); + } + + if ($arguments->hasStopOnIncomplete()) { + $result['stopOnIncomplete'] = $arguments->stopOnIncomplete(); + } + + if ($arguments->hasStopOnRisky()) { + $result['stopOnRisky'] = $arguments->stopOnRisky(); + } + + if ($arguments->hasStopOnSkipped()) { + $result['stopOnSkipped'] = $arguments->stopOnSkipped(); + } + + if ($arguments->hasFailOnEmptyTestSuite()) { + $result['failOnEmptyTestSuite'] = $arguments->failOnEmptyTestSuite(); + } + + if ($arguments->hasFailOnIncomplete()) { + $result['failOnIncomplete'] = $arguments->failOnIncomplete(); + } + + if ($arguments->hasFailOnRisky()) { + $result['failOnRisky'] = $arguments->failOnRisky(); + } + + if ($arguments->hasFailOnSkipped()) { + $result['failOnSkipped'] = $arguments->failOnSkipped(); + } + + if ($arguments->hasFailOnWarning()) { + $result['failOnWarning'] = $arguments->failOnWarning(); + } + + if ($arguments->hasTestdoxGroups()) { + $result['testdoxGroups'] = $arguments->testdoxGroups(); + } + + if ($arguments->hasTestdoxExcludeGroups()) { + $result['testdoxExcludeGroups'] = $arguments->testdoxExcludeGroups(); + } + + if ($arguments->hasTestdoxHtmlFile()) { + $result['testdoxHTMLFile'] = $arguments->testdoxHtmlFile(); + } + + if ($arguments->hasTestdoxTextFile()) { + $result['testdoxTextFile'] = $arguments->testdoxTextFile(); + } + + if ($arguments->hasTestdoxXmlFile()) { + $result['testdoxXMLFile'] = $arguments->testdoxXmlFile(); + } + + if ($arguments->hasUseDefaultConfiguration()) { + $result['useDefaultConfiguration'] = $arguments->useDefaultConfiguration(); + } + + if ($arguments->hasNoExtensions()) { + $result['noExtensions'] = $arguments->noExtensions(); + } + + if ($arguments->hasNoCoverage()) { + $result['noCoverage'] = $arguments->noCoverage(); + } + + if ($arguments->hasNoLogging()) { + $result['noLogging'] = $arguments->noLogging(); + } + + if ($arguments->hasNoInteraction()) { + $result['noInteraction'] = $arguments->noInteraction(); + } + + if ($arguments->hasBackupGlobals()) { + $result['backupGlobals'] = $arguments->backupGlobals(); + } + + if ($arguments->hasBackupStaticAttributes()) { + $result['backupStaticAttributes'] = $arguments->backupStaticAttributes(); + } + + if ($arguments->hasVerbose()) { + $result['verbose'] = $arguments->verbose(); + } + + if ($arguments->hasReportUselessTests()) { + $result['reportUselessTests'] = $arguments->reportUselessTests(); + } + + if ($arguments->hasStrictCoverage()) { + $result['strictCoverage'] = $arguments->strictCoverage(); + } + + if ($arguments->hasDisableCodeCoverageIgnore()) { + $result['disableCodeCoverageIgnore'] = $arguments->disableCodeCoverageIgnore(); + } + + if ($arguments->hasBeStrictAboutChangesToGlobalState()) { + $result['beStrictAboutChangesToGlobalState'] = $arguments->beStrictAboutChangesToGlobalState(); + } + + if ($arguments->hasDisallowTestOutput()) { + $result['disallowTestOutput'] = $arguments->disallowTestOutput(); + } + + if ($arguments->hasBeStrictAboutResourceUsageDuringSmallTests()) { + $result['beStrictAboutResourceUsageDuringSmallTests'] = $arguments->beStrictAboutResourceUsageDuringSmallTests(); + } + + if ($arguments->hasDefaultTimeLimit()) { + $result['defaultTimeLimit'] = $arguments->defaultTimeLimit(); + } + + if ($arguments->hasEnforceTimeLimit()) { + $result['enforceTimeLimit'] = $arguments->enforceTimeLimit(); + } + + if ($arguments->hasDisallowTodoAnnotatedTests()) { + $result['disallowTodoAnnotatedTests'] = $arguments->disallowTodoAnnotatedTests(); + } + + if ($arguments->hasReverseList()) { + $result['reverseList'] = $arguments->reverseList(); + } + + if ($arguments->hasCoverageFilter()) { + $result['coverageFilter'] = $arguments->coverageFilter(); + } + + if ($arguments->hasRandomOrderSeed()) { + $result['randomOrderSeed'] = $arguments->randomOrderSeed(); + } + + if ($arguments->hasXdebugFilterFile()) { + $result['xdebugFilterFile'] = $arguments->xdebugFilterFile(); + } + + return $result; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/Command.php b/vendor/phpunit/phpunit/src/TextUI/Command.php new file mode 100644 index 00000000..48243caa --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/Command.php @@ -0,0 +1,1004 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use const PATH_SEPARATOR; +use const PHP_EOL; +use const STDIN; +use function array_keys; +use function assert; +use function class_exists; +use function copy; +use function extension_loaded; +use function fgets; +use function file_get_contents; +use function file_put_contents; +use function get_class; +use function getcwd; +use function ini_get; +use function ini_set; +use function is_array; +use function is_callable; +use function is_dir; +use function is_file; +use function is_string; +use function printf; +use function realpath; +use function sort; +use function sprintf; +use function stream_resolve_include_path; +use function strpos; +use function trim; +use function version_compare; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\Extension\PharLoader; +use PHPUnit\Runner\StandardTestSuiteLoader; +use PHPUnit\Runner\TestSuiteLoader; +use PHPUnit\Runner\Version; +use PHPUnit\TextUI\CliArguments\Builder; +use PHPUnit\TextUI\CliArguments\Configuration; +use PHPUnit\TextUI\CliArguments\Exception as ArgumentsException; +use PHPUnit\TextUI\CliArguments\Mapper; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\FilterMapper; +use PHPUnit\TextUI\XmlConfiguration\Generator; +use PHPUnit\TextUI\XmlConfiguration\Loader; +use PHPUnit\TextUI\XmlConfiguration\Migrator; +use PHPUnit\TextUI\XmlConfiguration\PhpHandler; +use PHPUnit\Util\FileLoader; +use PHPUnit\Util\Filesystem; +use PHPUnit\Util\Printer; +use PHPUnit\Util\TextTestListRenderer; +use PHPUnit\Util\Xml\SchemaDetector; +use PHPUnit\Util\XmlTestListRenderer; +use ReflectionClass; +use SebastianBergmann\CodeCoverage\Filter; +use SebastianBergmann\CodeCoverage\StaticAnalysis\CacheWarmer; +use SebastianBergmann\Timer\Timer; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +class Command +{ + /** + * @var array + */ + protected $arguments = []; + + /** + * @var array + */ + protected $longOptions = []; + + /** + * @var bool + */ + private $versionStringPrinted = false; + + /** + * @psalm-var list + */ + private $warnings = []; + + /** + * @throws Exception + */ + public static function main(bool $exit = true): int + { + try { + return (new static)->run($_SERVER['argv'], $exit); + } catch (Throwable $t) { + throw new RuntimeException( + $t->getMessage(), + (int) $t->getCode(), + $t + ); + } + } + + /** + * @throws Exception + */ + public function run(array $argv, bool $exit = true): int + { + $this->handleArguments($argv); + + $runner = $this->createRunner(); + + if ($this->arguments['test'] instanceof TestSuite) { + $suite = $this->arguments['test']; + } else { + $suite = $runner->getTest( + $this->arguments['test'], + $this->arguments['testSuffixes'] + ); + } + + if ($this->arguments['listGroups']) { + return $this->handleListGroups($suite, $exit); + } + + if ($this->arguments['listSuites']) { + return $this->handleListSuites($exit); + } + + if ($this->arguments['listTests']) { + return $this->handleListTests($suite, $exit); + } + + if ($this->arguments['listTestsXml']) { + return $this->handleListTestsXml($suite, $this->arguments['listTestsXml'], $exit); + } + + unset($this->arguments['test'], $this->arguments['testFile']); + + try { + $result = $runner->run($suite, $this->arguments, $this->warnings, $exit); + } catch (Throwable $t) { + print $t->getMessage() . PHP_EOL; + } + + $return = TestRunner::FAILURE_EXIT; + + if (isset($result) && $result->wasSuccessful()) { + $return = TestRunner::SUCCESS_EXIT; + } elseif (!isset($result) || $result->errorCount() > 0) { + $return = TestRunner::EXCEPTION_EXIT; + } + + if ($exit) { + exit($return); + } + + return $return; + } + + /** + * Create a TestRunner, override in subclasses. + */ + protected function createRunner(): TestRunner + { + return new TestRunner($this->arguments['loader']); + } + + /** + * Handles the command-line arguments. + * + * A child class of PHPUnit\TextUI\Command can hook into the argument + * parsing by adding the switch(es) to the $longOptions array and point to a + * callback method that handles the switch(es) in the child class like this + * + * + * longOptions['my-switch'] = 'myHandler'; + * // my-secondswitch will accept a value - note the equals sign + * $this->longOptions['my-secondswitch='] = 'myOtherHandler'; + * } + * + * // --my-switch -> myHandler() + * protected function myHandler() + * { + * } + * + * // --my-secondswitch foo -> myOtherHandler('foo') + * protected function myOtherHandler ($value) + * { + * } + * + * // You will also need this - the static keyword in the + * // PHPUnit\TextUI\Command will mean that it'll be + * // PHPUnit\TextUI\Command that gets instantiated, + * // not MyCommand + * public static function main($exit = true) + * { + * $command = new static; + * + * return $command->run($_SERVER['argv'], $exit); + * } + * + * } + * + * + * @throws Exception + */ + protected function handleArguments(array $argv): void + { + try { + $arguments = (new Builder)->fromParameters($argv, array_keys($this->longOptions)); + } catch (ArgumentsException $e) { + $this->exitWithErrorMessage($e->getMessage()); + } + + assert(isset($arguments) && $arguments instanceof Configuration); + + if ($arguments->hasGenerateConfiguration() && $arguments->generateConfiguration()) { + $this->generateConfiguration(); + } + + if ($arguments->hasAtLeastVersion()) { + if (version_compare(Version::id(), $arguments->atLeastVersion(), '>=')) { + exit(TestRunner::SUCCESS_EXIT); + } + + exit(TestRunner::FAILURE_EXIT); + } + + if ($arguments->hasVersion() && $arguments->version()) { + $this->printVersionString(); + + exit(TestRunner::SUCCESS_EXIT); + } + + if ($arguments->hasCheckVersion() && $arguments->checkVersion()) { + $this->handleVersionCheck(); + } + + if ($arguments->hasHelp()) { + $this->showHelp(); + + exit(TestRunner::SUCCESS_EXIT); + } + + if ($arguments->hasUnrecognizedOrderBy()) { + $this->exitWithErrorMessage( + sprintf( + 'unrecognized --order-by option: %s', + $arguments->unrecognizedOrderBy() + ) + ); + } + + if ($arguments->hasIniSettings()) { + foreach ($arguments->iniSettings() as $name => $value) { + ini_set($name, $value); + } + } + + if ($arguments->hasIncludePath()) { + ini_set( + 'include_path', + $arguments->includePath() . PATH_SEPARATOR . ini_get('include_path') + ); + } + + $this->arguments = (new Mapper)->mapToLegacyArray($arguments); + + $this->handleCustomOptions($arguments->unrecognizedOptions()); + $this->handleCustomTestSuite(); + + if (!isset($this->arguments['testSuffixes'])) { + $this->arguments['testSuffixes'] = ['Test.php', '.phpt']; + } + + if (!isset($this->arguments['test']) && $arguments->hasArgument()) { + $this->arguments['test'] = realpath($arguments->argument()); + + if ($this->arguments['test'] === false) { + $this->exitWithErrorMessage( + sprintf( + 'Cannot open file "%s".', + $arguments->argument() + ) + ); + } + } + + if ($this->arguments['loader'] !== null) { + $this->arguments['loader'] = $this->handleLoader($this->arguments['loader']); + } + + if (isset($this->arguments['configuration'])) { + if (is_dir($this->arguments['configuration'])) { + $candidate = $this->configurationFileInDirectory($this->arguments['configuration']); + + if ($candidate !== null) { + $this->arguments['configuration'] = $candidate; + } + } + } elseif ($this->arguments['useDefaultConfiguration']) { + $candidate = $this->configurationFileInDirectory(getcwd()); + + if ($candidate !== null) { + $this->arguments['configuration'] = $candidate; + } + } + + if ($arguments->hasMigrateConfiguration() && $arguments->migrateConfiguration()) { + if (!isset($this->arguments['configuration'])) { + print 'No configuration file found to migrate.' . PHP_EOL; + + exit(TestRunner::EXCEPTION_EXIT); + } + + $this->migrateConfiguration(realpath($this->arguments['configuration'])); + } + + if (isset($this->arguments['configuration'])) { + try { + $this->arguments['configurationObject'] = (new Loader)->load($this->arguments['configuration']); + } catch (Throwable $e) { + print $e->getMessage() . PHP_EOL; + + exit(TestRunner::FAILURE_EXIT); + } + + $phpunitConfiguration = $this->arguments['configurationObject']->phpunit(); + + (new PhpHandler)->handle($this->arguments['configurationObject']->php()); + + if (isset($this->arguments['bootstrap'])) { + $this->handleBootstrap($this->arguments['bootstrap']); + } elseif ($phpunitConfiguration->hasBootstrap()) { + $this->handleBootstrap($phpunitConfiguration->bootstrap()); + } + + if (!isset($this->arguments['stderr'])) { + $this->arguments['stderr'] = $phpunitConfiguration->stderr(); + } + + if (!isset($this->arguments['noExtensions']) && $phpunitConfiguration->hasExtensionsDirectory() && extension_loaded('phar')) { + $result = (new PharLoader)->loadPharExtensionsInDirectory($phpunitConfiguration->extensionsDirectory()); + + $this->arguments['loadedExtensions'] = $result['loadedExtensions']; + $this->arguments['notLoadedExtensions'] = $result['notLoadedExtensions']; + + unset($result); + } + + if (!isset($this->arguments['columns'])) { + $this->arguments['columns'] = $phpunitConfiguration->columns(); + } + + if (!isset($this->arguments['printer']) && $phpunitConfiguration->hasPrinterClass()) { + $file = $phpunitConfiguration->hasPrinterFile() ? $phpunitConfiguration->printerFile() : ''; + + $this->arguments['printer'] = $this->handlePrinter( + $phpunitConfiguration->printerClass(), + $file + ); + } + + if ($phpunitConfiguration->hasTestSuiteLoaderClass()) { + $file = $phpunitConfiguration->hasTestSuiteLoaderFile() ? $phpunitConfiguration->testSuiteLoaderFile() : ''; + + $this->arguments['loader'] = $this->handleLoader( + $phpunitConfiguration->testSuiteLoaderClass(), + $file + ); + } + + if (!isset($this->arguments['testsuite']) && $phpunitConfiguration->hasDefaultTestSuite()) { + $this->arguments['testsuite'] = $phpunitConfiguration->defaultTestSuite(); + } + + if (!isset($this->arguments['test'])) { + try { + $this->arguments['test'] = (new TestSuiteMapper)->map( + $this->arguments['configurationObject']->testSuite(), + $this->arguments['testsuite'] ?? '' + ); + } catch (Exception $e) { + $this->printVersionString(); + + print $e->getMessage() . PHP_EOL; + + exit(TestRunner::EXCEPTION_EXIT); + } + } + } elseif (isset($this->arguments['bootstrap'])) { + $this->handleBootstrap($this->arguments['bootstrap']); + } + + if (isset($this->arguments['printer']) && is_string($this->arguments['printer'])) { + $this->arguments['printer'] = $this->handlePrinter($this->arguments['printer']); + } + + if (isset($this->arguments['configurationObject'], $this->arguments['warmCoverageCache'])) { + $this->handleWarmCoverageCache($this->arguments['configurationObject']); + } + + if (!isset($this->arguments['test'])) { + $this->showHelp(); + + exit(TestRunner::EXCEPTION_EXIT); + } + } + + /** + * Handles the loading of the PHPUnit\Runner\TestSuiteLoader implementation. + * + * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039 + */ + protected function handleLoader(string $loaderClass, string $loaderFile = ''): ?TestSuiteLoader + { + $this->warnings[] = 'Using a custom test suite loader is deprecated'; + + if (!class_exists($loaderClass, false)) { + if ($loaderFile == '') { + $loaderFile = Filesystem::classNameToFilename( + $loaderClass + ); + } + + $loaderFile = stream_resolve_include_path($loaderFile); + + if ($loaderFile) { + /** + * @noinspection PhpIncludeInspection + * + * @psalm-suppress UnresolvableInclude + */ + require $loaderFile; + } + } + + if (class_exists($loaderClass, false)) { + try { + $class = new ReflectionClass($loaderClass); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + if ($class->implementsInterface(TestSuiteLoader::class) && $class->isInstantiable()) { + $object = $class->newInstance(); + + assert($object instanceof TestSuiteLoader); + + return $object; + } + } + + if ($loaderClass == StandardTestSuiteLoader::class) { + return null; + } + + $this->exitWithErrorMessage( + sprintf( + 'Could not use "%s" as loader.', + $loaderClass + ) + ); + + return null; + } + + /** + * Handles the loading of the PHPUnit\Util\Printer implementation. + * + * @return null|Printer|string + */ + protected function handlePrinter(string $printerClass, string $printerFile = '') + { + if (!class_exists($printerClass, false)) { + if ($printerFile === '') { + $printerFile = Filesystem::classNameToFilename( + $printerClass + ); + } + + $printerFile = stream_resolve_include_path($printerFile); + + if ($printerFile) { + /** + * @noinspection PhpIncludeInspection + * + * @psalm-suppress UnresolvableInclude + */ + require $printerFile; + } + } + + if (!class_exists($printerClass)) { + $this->exitWithErrorMessage( + sprintf( + 'Could not use "%s" as printer: class does not exist', + $printerClass + ) + ); + } + + try { + $class = new ReflectionClass($printerClass); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + // @codeCoverageIgnoreEnd + } + + if (!$class->implementsInterface(ResultPrinter::class)) { + $this->exitWithErrorMessage( + sprintf( + 'Could not use "%s" as printer: class does not implement %s', + $printerClass, + ResultPrinter::class + ) + ); + } + + if (!$class->isInstantiable()) { + $this->exitWithErrorMessage( + sprintf( + 'Could not use "%s" as printer: class cannot be instantiated', + $printerClass + ) + ); + } + + if ($class->isSubclassOf(ResultPrinter::class)) { + return $printerClass; + } + + $outputStream = isset($this->arguments['stderr']) ? 'php://stderr' : null; + + return $class->newInstance($outputStream); + } + + /** + * Loads a bootstrap file. + */ + protected function handleBootstrap(string $filename): void + { + try { + FileLoader::checkAndLoad($filename); + } catch (Throwable $t) { + if ($t instanceof \PHPUnit\Exception) { + $this->exitWithErrorMessage($t->getMessage()); + } + + $this->exitWithErrorMessage( + sprintf( + 'Error in bootstrap script: %s:%s%s%s%s', + get_class($t), + PHP_EOL, + $t->getMessage(), + PHP_EOL, + $t->getTraceAsString() + ) + ); + } + } + + protected function handleVersionCheck(): void + { + $this->printVersionString(); + + $latestVersion = file_get_contents('https://phar.phpunit.de/latest-version-of/phpunit'); + $isOutdated = version_compare($latestVersion, Version::id(), '>'); + + if ($isOutdated) { + printf( + 'You are not using the latest version of PHPUnit.' . PHP_EOL . + 'The latest version is PHPUnit %s.' . PHP_EOL, + $latestVersion + ); + } else { + print 'You are using the latest version of PHPUnit.' . PHP_EOL; + } + + exit(TestRunner::SUCCESS_EXIT); + } + + /** + * Show the help message. + */ + protected function showHelp(): void + { + $this->printVersionString(); + (new Help)->writeToConsole(); + } + + /** + * Custom callback for test suite discovery. + */ + protected function handleCustomTestSuite(): void + { + } + + private function printVersionString(): void + { + if ($this->versionStringPrinted) { + return; + } + + print Version::getVersionString() . PHP_EOL . PHP_EOL; + + $this->versionStringPrinted = true; + } + + private function exitWithErrorMessage(string $message): void + { + $this->printVersionString(); + + print $message . PHP_EOL; + + exit(TestRunner::FAILURE_EXIT); + } + + private function handleListGroups(TestSuite $suite, bool $exit): int + { + $this->printVersionString(); + + $this->warnAboutConflictingOptions( + 'listGroups', + [ + 'filter', + 'groups', + 'excludeGroups', + 'testsuite', + ] + ); + + print 'Available test group(s):' . PHP_EOL; + + $groups = $suite->getGroups(); + sort($groups); + + foreach ($groups as $group) { + if (strpos($group, '__phpunit_') === 0) { + continue; + } + + printf( + ' - %s' . PHP_EOL, + $group + ); + } + + if ($exit) { + exit(TestRunner::SUCCESS_EXIT); + } + + return TestRunner::SUCCESS_EXIT; + } + + /** + * @throws \PHPUnit\Framework\Exception + * @throws \PHPUnit\TextUI\XmlConfiguration\Exception + */ + private function handleListSuites(bool $exit): int + { + $this->printVersionString(); + + $this->warnAboutConflictingOptions( + 'listSuites', + [ + 'filter', + 'groups', + 'excludeGroups', + 'testsuite', + ] + ); + + print 'Available test suite(s):' . PHP_EOL; + + foreach ($this->arguments['configurationObject']->testSuite() as $testSuite) { + printf( + ' - %s' . PHP_EOL, + $testSuite->name() + ); + } + + if ($exit) { + exit(TestRunner::SUCCESS_EXIT); + } + + return TestRunner::SUCCESS_EXIT; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + private function handleListTests(TestSuite $suite, bool $exit): int + { + $this->printVersionString(); + + $this->warnAboutConflictingOptions( + 'listTests', + [ + 'filter', + 'groups', + 'excludeGroups', + ] + ); + + $renderer = new TextTestListRenderer; + + print $renderer->render($suite); + + if ($exit) { + exit(TestRunner::SUCCESS_EXIT); + } + + return TestRunner::SUCCESS_EXIT; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + private function handleListTestsXml(TestSuite $suite, string $target, bool $exit): int + { + $this->printVersionString(); + + $this->warnAboutConflictingOptions( + 'listTestsXml', + [ + 'filter', + 'groups', + 'excludeGroups', + ] + ); + + $renderer = new XmlTestListRenderer; + + file_put_contents($target, $renderer->render($suite)); + + printf( + 'Wrote list of tests that would have been run to %s' . PHP_EOL, + $target + ); + + if ($exit) { + exit(TestRunner::SUCCESS_EXIT); + } + + return TestRunner::SUCCESS_EXIT; + } + + private function generateConfiguration(): void + { + $this->printVersionString(); + + print 'Generating phpunit.xml in ' . getcwd() . PHP_EOL . PHP_EOL; + print 'Bootstrap script (relative to path shown above; default: vendor/autoload.php): '; + + $bootstrapScript = trim(fgets(STDIN)); + + print 'Tests directory (relative to path shown above; default: tests): '; + + $testsDirectory = trim(fgets(STDIN)); + + print 'Source directory (relative to path shown above; default: src): '; + + $src = trim(fgets(STDIN)); + + print 'Cache directory (relative to path shown above; default: .phpunit.cache): '; + + $cacheDirectory = trim(fgets(STDIN)); + + if ($bootstrapScript === '') { + $bootstrapScript = 'vendor/autoload.php'; + } + + if ($testsDirectory === '') { + $testsDirectory = 'tests'; + } + + if ($src === '') { + $src = 'src'; + } + + if ($cacheDirectory === '') { + $cacheDirectory = '.phpunit.cache'; + } + + $generator = new Generator; + + file_put_contents( + 'phpunit.xml', + $generator->generateDefaultConfiguration( + Version::series(), + $bootstrapScript, + $testsDirectory, + $src, + $cacheDirectory + ) + ); + + print PHP_EOL . 'Generated phpunit.xml in ' . getcwd() . '.' . PHP_EOL; + print 'Make sure to exclude the ' . $cacheDirectory . ' directory from version control.' . PHP_EOL; + + exit(TestRunner::SUCCESS_EXIT); + } + + private function migrateConfiguration(string $filename): void + { + $this->printVersionString(); + + if (!(new SchemaDetector)->detect($filename)->detected()) { + print $filename . ' does not need to be migrated.' . PHP_EOL; + + exit(TestRunner::EXCEPTION_EXIT); + } + + copy($filename, $filename . '.bak'); + + print 'Created backup: ' . $filename . '.bak' . PHP_EOL; + + try { + file_put_contents( + $filename, + (new Migrator)->migrate($filename) + ); + + print 'Migrated configuration: ' . $filename . PHP_EOL; + } catch (Throwable $t) { + print 'Migration failed: ' . $t->getMessage() . PHP_EOL; + + exit(TestRunner::EXCEPTION_EXIT); + } + + exit(TestRunner::SUCCESS_EXIT); + } + + private function handleCustomOptions(array $unrecognizedOptions): void + { + foreach ($unrecognizedOptions as $name => $value) { + if (isset($this->longOptions[$name])) { + $handler = $this->longOptions[$name]; + } + + $name .= '='; + + if (isset($this->longOptions[$name])) { + $handler = $this->longOptions[$name]; + } + + if (isset($handler) && is_callable([$this, $handler])) { + $this->{$handler}($value); + + unset($handler); + } + } + } + + private function handleWarmCoverageCache(XmlConfiguration\Configuration $configuration): void + { + $this->printVersionString(); + + if (isset($this->arguments['coverageCacheDirectory'])) { + $cacheDirectory = $this->arguments['coverageCacheDirectory']; + } elseif ($configuration->codeCoverage()->hasCacheDirectory()) { + $cacheDirectory = $configuration->codeCoverage()->cacheDirectory()->path(); + } else { + print 'Cache for static analysis has not been configured' . PHP_EOL; + + exit(TestRunner::EXCEPTION_EXIT); + } + + $filter = new Filter; + + if ($configuration->codeCoverage()->hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport()) { + (new FilterMapper)->map( + $filter, + $configuration->codeCoverage() + ); + } elseif (isset($this->arguments['coverageFilter'])) { + if (!is_array($this->arguments['coverageFilter'])) { + $coverageFilterDirectories = [$this->arguments['coverageFilter']]; + } else { + $coverageFilterDirectories = $this->arguments['coverageFilter']; + } + + foreach ($coverageFilterDirectories as $coverageFilterDirectory) { + $filter->includeDirectory($coverageFilterDirectory); + } + } else { + print 'Filter for code coverage has not been configured' . PHP_EOL; + + exit(TestRunner::EXCEPTION_EXIT); + } + + $timer = new Timer; + $timer->start(); + + print 'Warming cache for static analysis ... '; + + (new CacheWarmer)->warmCache( + $cacheDirectory, + !$configuration->codeCoverage()->disableCodeCoverageIgnore(), + $configuration->codeCoverage()->ignoreDeprecatedCodeUnits(), + $filter + ); + + print 'done [' . $timer->stop()->asString() . ']' . PHP_EOL; + + exit(TestRunner::SUCCESS_EXIT); + } + + private function configurationFileInDirectory(string $directory): ?string + { + $candidates = [ + $directory . '/phpunit.xml', + $directory . '/phpunit.xml.dist', + ]; + + foreach ($candidates as $candidate) { + if (is_file($candidate)) { + return realpath($candidate); + } + } + + return null; + } + + /** + * @psalm-param "listGroups"|"listSuites"|"listTests"|"listTestsXml"|"filter"|"groups"|"excludeGroups"|"testsuite" $key + * @psalm-param list<"listGroups"|"listSuites"|"listTests"|"listTestsXml"|"filter"|"groups"|"excludeGroups"|"testsuite"> $keys + */ + private function warnAboutConflictingOptions(string $key, array $keys): void + { + $warningPrinted = false; + + foreach ($keys as $_key) { + if (!empty($this->arguments[$_key])) { + printf( + 'The %s and %s options cannot be combined, %s is ignored' . PHP_EOL, + $this->mapKeyToOptionForWarning($_key), + $this->mapKeyToOptionForWarning($key), + $this->mapKeyToOptionForWarning($_key) + ); + + $warningPrinted = true; + } + } + + if ($warningPrinted) { + print PHP_EOL; + } + } + + /** + * @psalm-param "listGroups"|"listSuites"|"listTests"|"listTestsXml"|"filter"|"groups"|"excludeGroups"|"testsuite" $key + */ + private function mapKeyToOptionForWarning(string $key): string + { + switch ($key) { + case 'listGroups': + return '--list-groups'; + + case 'listSuites': + return '--list-suites'; + + case 'listTests': + return '--list-tests'; + + case 'listTestsXml': + return '--list-tests-xml'; + + case 'filter': + return '--filter'; + + case 'groups': + return '--group'; + + case 'excludeGroups': + return '--exclude-group'; + + case 'testsuite': + return '--testsuite'; + } + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/DefaultResultPrinter.php b/vendor/phpunit/phpunit/src/TextUI/DefaultResultPrinter.php new file mode 100644 index 00000000..99f0fa9d --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/DefaultResultPrinter.php @@ -0,0 +1,593 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use const PHP_EOL; +use function array_map; +use function array_reverse; +use function count; +use function floor; +use function implode; +use function in_array; +use function is_int; +use function max; +use function preg_split; +use function sprintf; +use function str_pad; +use function str_repeat; +use function strlen; +use function trim; +use function vsprintf; +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\Exception; +use PHPUnit\Framework\InvalidArgumentException; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestFailure; +use PHPUnit\Framework\TestResult; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Framework\Warning; +use PHPUnit\Runner\PhptTestCase; +use PHPUnit\Util\Color; +use PHPUnit\Util\Printer; +use SebastianBergmann\Environment\Console; +use SebastianBergmann\Timer\ResourceUsageFormatter; +use SebastianBergmann\Timer\Timer; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class DefaultResultPrinter extends Printer implements ResultPrinter +{ + public const EVENT_TEST_START = 0; + + public const EVENT_TEST_END = 1; + + public const EVENT_TESTSUITE_START = 2; + + public const EVENT_TESTSUITE_END = 3; + + public const COLOR_NEVER = 'never'; + + public const COLOR_AUTO = 'auto'; + + public const COLOR_ALWAYS = 'always'; + + public const COLOR_DEFAULT = self::COLOR_NEVER; + + private const AVAILABLE_COLORS = [self::COLOR_NEVER, self::COLOR_AUTO, self::COLOR_ALWAYS]; + + /** + * @var int + */ + protected $column = 0; + + /** + * @var int + */ + protected $maxColumn; + + /** + * @var bool + */ + protected $lastTestFailed = false; + + /** + * @var int + */ + protected $numAssertions = 0; + + /** + * @var int + */ + protected $numTests = -1; + + /** + * @var int + */ + protected $numTestsRun = 0; + + /** + * @var int + */ + protected $numTestsWidth; + + /** + * @var bool + */ + protected $colors = false; + + /** + * @var bool + */ + protected $debug = false; + + /** + * @var bool + */ + protected $verbose = false; + + /** + * @var int + */ + private $numberOfColumns; + + /** + * @var bool + */ + private $reverse; + + /** + * @var bool + */ + private $defectListPrinted = false; + + /** + * @var Timer + */ + private $timer; + + /** + * Constructor. + * + * @param null|resource|string $out + * @param int|string $numberOfColumns + * + * @throws Exception + */ + public function __construct($out = null, bool $verbose = false, string $colors = self::COLOR_DEFAULT, bool $debug = false, $numberOfColumns = 80, bool $reverse = false) + { + parent::__construct($out); + + if (!in_array($colors, self::AVAILABLE_COLORS, true)) { + throw InvalidArgumentException::create( + 3, + vsprintf('value from "%s", "%s" or "%s"', self::AVAILABLE_COLORS) + ); + } + + if (!is_int($numberOfColumns) && $numberOfColumns !== 'max') { + throw InvalidArgumentException::create(5, 'integer or "max"'); + } + + $console = new Console; + $maxNumberOfColumns = $console->getNumberOfColumns(); + + if ($numberOfColumns === 'max' || ($numberOfColumns !== 80 && $numberOfColumns > $maxNumberOfColumns)) { + $numberOfColumns = $maxNumberOfColumns; + } + + $this->numberOfColumns = $numberOfColumns; + $this->verbose = $verbose; + $this->debug = $debug; + $this->reverse = $reverse; + + if ($colors === self::COLOR_AUTO && $console->hasColorSupport()) { + $this->colors = true; + } else { + $this->colors = (self::COLOR_ALWAYS === $colors); + } + + $this->timer = new Timer; + + $this->timer->start(); + } + + public function printResult(TestResult $result): void + { + $this->printHeader($result); + $this->printErrors($result); + $this->printWarnings($result); + $this->printFailures($result); + $this->printRisky($result); + + if ($this->verbose) { + $this->printIncompletes($result); + $this->printSkipped($result); + } + + $this->printFooter($result); + } + + /** + * An error occurred. + */ + public function addError(Test $test, Throwable $t, float $time): void + { + $this->writeProgressWithColor('fg-red, bold', 'E'); + $this->lastTestFailed = true; + } + + /** + * A failure occurred. + */ + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + $this->writeProgressWithColor('bg-red, fg-white', 'F'); + $this->lastTestFailed = true; + } + + /** + * A warning occurred. + */ + public function addWarning(Test $test, Warning $e, float $time): void + { + $this->writeProgressWithColor('fg-yellow, bold', 'W'); + $this->lastTestFailed = true; + } + + /** + * Incomplete test. + */ + public function addIncompleteTest(Test $test, Throwable $t, float $time): void + { + $this->writeProgressWithColor('fg-yellow, bold', 'I'); + $this->lastTestFailed = true; + } + + /** + * Risky test. + */ + public function addRiskyTest(Test $test, Throwable $t, float $time): void + { + $this->writeProgressWithColor('fg-yellow, bold', 'R'); + $this->lastTestFailed = true; + } + + /** + * Skipped test. + */ + public function addSkippedTest(Test $test, Throwable $t, float $time): void + { + $this->writeProgressWithColor('fg-cyan, bold', 'S'); + $this->lastTestFailed = true; + } + + /** + * A testsuite started. + */ + public function startTestSuite(TestSuite $suite): void + { + if ($this->numTests == -1) { + $this->numTests = count($suite); + $this->numTestsWidth = strlen((string) $this->numTests); + $this->maxColumn = $this->numberOfColumns - strlen(' / (XXX%)') - (2 * $this->numTestsWidth); + } + } + + /** + * A testsuite ended. + */ + public function endTestSuite(TestSuite $suite): void + { + } + + /** + * A test started. + */ + public function startTest(Test $test): void + { + if ($this->debug) { + $this->write( + sprintf( + "Test '%s' started\n", + \PHPUnit\Util\Test::describeAsString($test) + ) + ); + } + } + + /** + * A test ended. + */ + public function endTest(Test $test, float $time): void + { + if ($this->debug) { + $this->write( + sprintf( + "Test '%s' ended\n", + \PHPUnit\Util\Test::describeAsString($test) + ) + ); + } + + if (!$this->lastTestFailed) { + $this->writeProgress('.'); + } + + if ($test instanceof TestCase) { + $this->numAssertions += $test->getNumAssertions(); + } elseif ($test instanceof PhptTestCase) { + $this->numAssertions++; + } + + $this->lastTestFailed = false; + + if ($test instanceof TestCase && !$test->hasExpectationOnOutput()) { + $this->write($test->getActualOutput()); + } + } + + protected function printDefects(array $defects, string $type): void + { + $count = count($defects); + + if ($count == 0) { + return; + } + + if ($this->defectListPrinted) { + $this->write("\n--\n\n"); + } + + $this->write( + sprintf( + "There %s %d %s%s:\n", + ($count == 1) ? 'was' : 'were', + $count, + $type, + ($count == 1) ? '' : 's' + ) + ); + + $i = 1; + + if ($this->reverse) { + $defects = array_reverse($defects); + } + + foreach ($defects as $defect) { + $this->printDefect($defect, $i++); + } + + $this->defectListPrinted = true; + } + + protected function printDefect(TestFailure $defect, int $count): void + { + $this->printDefectHeader($defect, $count); + $this->printDefectTrace($defect); + } + + protected function printDefectHeader(TestFailure $defect, int $count): void + { + $this->write( + sprintf( + "\n%d) %s\n", + $count, + $defect->getTestName() + ) + ); + } + + protected function printDefectTrace(TestFailure $defect): void + { + $e = $defect->thrownException(); + + $this->write((string) $e); + + while ($e = $e->getPrevious()) { + $this->write("\nCaused by\n" . trim((string) $e) . "\n"); + } + } + + protected function printErrors(TestResult $result): void + { + $this->printDefects($result->errors(), 'error'); + } + + protected function printFailures(TestResult $result): void + { + $this->printDefects($result->failures(), 'failure'); + } + + protected function printWarnings(TestResult $result): void + { + $this->printDefects($result->warnings(), 'warning'); + } + + protected function printIncompletes(TestResult $result): void + { + $this->printDefects($result->notImplemented(), 'incomplete test'); + } + + protected function printRisky(TestResult $result): void + { + $this->printDefects($result->risky(), 'risky test'); + } + + protected function printSkipped(TestResult $result): void + { + $this->printDefects($result->skipped(), 'skipped test'); + } + + protected function printHeader(TestResult $result): void + { + if (count($result) > 0) { + $this->write(PHP_EOL . PHP_EOL . (new ResourceUsageFormatter)->resourceUsage($this->timer->stop()) . PHP_EOL . PHP_EOL); + } + } + + protected function printFooter(TestResult $result): void + { + if (count($result) === 0) { + $this->writeWithColor( + 'fg-black, bg-yellow', + 'No tests executed!' + ); + + return; + } + + if ($result->wasSuccessfulAndNoTestIsRiskyOrSkippedOrIncomplete()) { + $this->writeWithColor( + 'fg-black, bg-green', + sprintf( + 'OK (%d test%s, %d assertion%s)', + count($result), + (count($result) === 1) ? '' : 's', + $this->numAssertions, + ($this->numAssertions === 1) ? '' : 's' + ) + ); + + return; + } + + $color = 'fg-black, bg-yellow'; + + if ($result->wasSuccessful()) { + if ($this->verbose || !$result->allHarmless()) { + $this->write("\n"); + } + + $this->writeWithColor( + $color, + 'OK, but incomplete, skipped, or risky tests!' + ); + } else { + $this->write("\n"); + + if ($result->errorCount()) { + $color = 'fg-white, bg-red'; + + $this->writeWithColor( + $color, + 'ERRORS!' + ); + } elseif ($result->failureCount()) { + $color = 'fg-white, bg-red'; + + $this->writeWithColor( + $color, + 'FAILURES!' + ); + } elseif ($result->warningCount()) { + $color = 'fg-black, bg-yellow'; + + $this->writeWithColor( + $color, + 'WARNINGS!' + ); + } + } + + $this->writeCountString(count($result), 'Tests', $color, true); + $this->writeCountString($this->numAssertions, 'Assertions', $color, true); + $this->writeCountString($result->errorCount(), 'Errors', $color); + $this->writeCountString($result->failureCount(), 'Failures', $color); + $this->writeCountString($result->warningCount(), 'Warnings', $color); + $this->writeCountString($result->skippedCount(), 'Skipped', $color); + $this->writeCountString($result->notImplementedCount(), 'Incomplete', $color); + $this->writeCountString($result->riskyCount(), 'Risky', $color); + $this->writeWithColor($color, '.'); + } + + protected function writeProgress(string $progress): void + { + if ($this->debug) { + return; + } + + $this->write($progress); + $this->column++; + $this->numTestsRun++; + + if ($this->column == $this->maxColumn || $this->numTestsRun == $this->numTests) { + if ($this->numTestsRun == $this->numTests) { + $this->write(str_repeat(' ', $this->maxColumn - $this->column)); + } + + $this->write( + sprintf( + ' %' . $this->numTestsWidth . 'd / %' . + $this->numTestsWidth . 'd (%3s%%)', + $this->numTestsRun, + $this->numTests, + floor(($this->numTestsRun / $this->numTests) * 100) + ) + ); + + if ($this->column == $this->maxColumn) { + $this->writeNewLine(); + } + } + } + + protected function writeNewLine(): void + { + $this->column = 0; + $this->write("\n"); + } + + /** + * Formats a buffer with a specified ANSI color sequence if colors are + * enabled. + */ + protected function colorizeTextBox(string $color, string $buffer): string + { + if (!$this->colors) { + return $buffer; + } + + $lines = preg_split('/\r\n|\r|\n/', $buffer); + $padding = max(array_map('\strlen', $lines)); + + $styledLines = []; + + foreach ($lines as $line) { + $styledLines[] = Color::colorize($color, str_pad($line, $padding)); + } + + return implode(PHP_EOL, $styledLines); + } + + /** + * Writes a buffer out with a color sequence if colors are enabled. + */ + protected function writeWithColor(string $color, string $buffer, bool $lf = true): void + { + $this->write($this->colorizeTextBox($color, $buffer)); + + if ($lf) { + $this->write(PHP_EOL); + } + } + + /** + * Writes progress with a color sequence if colors are enabled. + */ + protected function writeProgressWithColor(string $color, string $buffer): void + { + $buffer = $this->colorizeTextBox($color, $buffer); + $this->writeProgress($buffer); + } + + private function writeCountString(int $count, string $name, string $color, bool $always = false): void + { + static $first = true; + + if ($always || $count > 0) { + $this->writeWithColor( + $color, + sprintf( + '%s%s: %d', + !$first ? ', ' : '', + $name, + $count + ), + false + ); + + $first = false; + } + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/Exception/Exception.php b/vendor/phpunit/phpunit/src/TextUI/Exception/Exception.php new file mode 100644 index 00000000..ee2ae4ff --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/Exception/Exception.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use Throwable; + +/** + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +interface Exception extends Throwable +{ +} diff --git a/vendor/phpunit/phpunit/src/TextUI/Exception/ReflectionException.php b/vendor/phpunit/phpunit/src/TextUI/Exception/ReflectionException.php new file mode 100644 index 00000000..74e9d25d --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/Exception/ReflectionException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use RuntimeException; + +/** + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +final class ReflectionException extends RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php b/vendor/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php new file mode 100644 index 00000000..790a8463 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +/** + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php b/vendor/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php new file mode 100644 index 00000000..770ad874 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use function sprintf; +use RuntimeException; + +/** + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +final class TestDirectoryNotFoundException extends RuntimeException implements Exception +{ + public function __construct(string $path) + { + parent::__construct( + sprintf( + 'Test directory "%s" not found', + $path + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php b/vendor/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php new file mode 100644 index 00000000..7ffd2c78 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use function sprintf; +use RuntimeException; + +/** + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFileNotFoundException extends RuntimeException implements Exception +{ + public function __construct(string $path) + { + parent::__construct( + sprintf( + 'Test file "%s" not found', + $path + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/Help.php b/vendor/phpunit/phpunit/src/TextUI/Help.php new file mode 100644 index 00000000..084f2a21 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/Help.php @@ -0,0 +1,265 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use const PHP_EOL; +use function count; +use function explode; +use function max; +use function preg_replace_callback; +use function str_pad; +use function str_repeat; +use function strlen; +use function wordwrap; +use PHPUnit\Util\Color; +use SebastianBergmann\Environment\Console; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Help +{ + private const LEFT_MARGIN = ' '; + + private const HELP_TEXT = [ + 'Usage' => [ + ['text' => 'phpunit [options] UnitTest.php'], + ['text' => 'phpunit [options] '], + ], + + 'Code Coverage Options' => [ + ['arg' => '--coverage-clover ', 'desc' => 'Generate code coverage report in Clover XML format'], + ['arg' => '--coverage-cobertura ', 'desc' => 'Generate code coverage report in Cobertura XML format'], + ['arg' => '--coverage-crap4j ', 'desc' => 'Generate code coverage report in Crap4J XML format'], + ['arg' => '--coverage-html ', 'desc' => 'Generate code coverage report in HTML format'], + ['arg' => '--coverage-php ', 'desc' => 'Export PHP_CodeCoverage object to file'], + ['arg' => '--coverage-text=', 'desc' => 'Generate code coverage report in text format [default: standard output]'], + ['arg' => '--coverage-xml ', 'desc' => 'Generate code coverage report in PHPUnit XML format'], + ['arg' => '--coverage-cache ', 'desc' => 'Cache static analysis results'], + ['arg' => '--warm-coverage-cache', 'desc' => 'Warm static analysis cache'], + ['arg' => '--coverage-filter ', 'desc' => 'Include in code coverage analysis'], + ['arg' => '--path-coverage', 'desc' => 'Perform path coverage analysis'], + ['arg' => '--disable-coverage-ignore', 'desc' => 'Disable annotations for ignoring code coverage'], + ['arg' => '--no-coverage', 'desc' => 'Ignore code coverage configuration'], + ], + + 'Logging Options' => [ + ['arg' => '--log-junit ', 'desc' => 'Log test execution in JUnit XML format to file'], + ['arg' => '--log-teamcity ', 'desc' => 'Log test execution in TeamCity format to file'], + ['arg' => '--testdox-html ', 'desc' => 'Write agile documentation in HTML format to file'], + ['arg' => '--testdox-text ', 'desc' => 'Write agile documentation in Text format to file'], + ['arg' => '--testdox-xml ', 'desc' => 'Write agile documentation in XML format to file'], + ['arg' => '--reverse-list', 'desc' => 'Print defects in reverse order'], + ['arg' => '--no-logging', 'desc' => 'Ignore logging configuration'], + ], + + 'Test Selection Options' => [ + ['arg' => '--list-suites', 'desc' => 'List available test suites'], + ['arg' => '--testsuite ', 'desc' => 'Filter which testsuite to run'], + ['arg' => '--list-groups', 'desc' => 'List available test groups'], + ['arg' => '--group ', 'desc' => 'Only runs tests from the specified group(s)'], + ['arg' => '--exclude-group ', 'desc' => 'Exclude tests from the specified group(s)'], + ['arg' => '--covers ', 'desc' => 'Only runs tests annotated with "@covers "'], + ['arg' => '--uses ', 'desc' => 'Only runs tests annotated with "@uses "'], + ['arg' => '--list-tests', 'desc' => 'List available tests'], + ['arg' => '--list-tests-xml ', 'desc' => 'List available tests in XML format'], + ['arg' => '--filter ', 'desc' => 'Filter which tests to run'], + ['arg' => '--test-suffix ', 'desc' => 'Only search for test in files with specified suffix(es). Default: Test.php,.phpt'], + ], + + 'Test Execution Options' => [ + ['arg' => '--dont-report-useless-tests', 'desc' => 'Do not report tests that do not test anything'], + ['arg' => '--strict-coverage', 'desc' => 'Be strict about @covers annotation usage'], + ['arg' => '--strict-global-state', 'desc' => 'Be strict about changes to global state'], + ['arg' => '--disallow-test-output', 'desc' => 'Be strict about output during tests'], + ['arg' => '--disallow-resource-usage', 'desc' => 'Be strict about resource usage during small tests'], + ['arg' => '--enforce-time-limit', 'desc' => 'Enforce time limit based on test size'], + ['arg' => '--default-time-limit ', 'desc' => 'Timeout in seconds for tests without @small, @medium or @large'], + ['arg' => '--disallow-todo-tests', 'desc' => 'Disallow @todo-annotated tests'], + ['spacer' => ''], + + ['arg' => '--process-isolation', 'desc' => 'Run each test in a separate PHP process'], + ['arg' => '--globals-backup', 'desc' => 'Backup and restore $GLOBALS for each test'], + ['arg' => '--static-backup', 'desc' => 'Backup and restore static attributes for each test'], + ['spacer' => ''], + + ['arg' => '--colors ', 'desc' => 'Use colors in output ("never", "auto" or "always")'], + ['arg' => '--columns ', 'desc' => 'Number of columns to use for progress output'], + ['arg' => '--columns max', 'desc' => 'Use maximum number of columns for progress output'], + ['arg' => '--stderr', 'desc' => 'Write to STDERR instead of STDOUT'], + ['arg' => '--stop-on-defect', 'desc' => 'Stop execution upon first not-passed test'], + ['arg' => '--stop-on-error', 'desc' => 'Stop execution upon first error'], + ['arg' => '--stop-on-failure', 'desc' => 'Stop execution upon first error or failure'], + ['arg' => '--stop-on-warning', 'desc' => 'Stop execution upon first warning'], + ['arg' => '--stop-on-risky', 'desc' => 'Stop execution upon first risky test'], + ['arg' => '--stop-on-skipped', 'desc' => 'Stop execution upon first skipped test'], + ['arg' => '--stop-on-incomplete', 'desc' => 'Stop execution upon first incomplete test'], + ['arg' => '--fail-on-incomplete', 'desc' => 'Treat incomplete tests as failures'], + ['arg' => '--fail-on-risky', 'desc' => 'Treat risky tests as failures'], + ['arg' => '--fail-on-skipped', 'desc' => 'Treat skipped tests as failures'], + ['arg' => '--fail-on-warning', 'desc' => 'Treat tests with warnings as failures'], + ['arg' => '-v|--verbose', 'desc' => 'Output more verbose information'], + ['arg' => '--debug', 'desc' => 'Display debugging information'], + ['spacer' => ''], + + ['arg' => '--repeat ', 'desc' => 'Runs the test(s) repeatedly'], + ['arg' => '--teamcity', 'desc' => 'Report test execution progress in TeamCity format'], + ['arg' => '--testdox', 'desc' => 'Report test execution progress in TestDox format'], + ['arg' => '--testdox-group', 'desc' => 'Only include tests from the specified group(s)'], + ['arg' => '--testdox-exclude-group', 'desc' => 'Exclude tests from the specified group(s)'], + ['arg' => '--no-interaction', 'desc' => 'Disable TestDox progress animation'], + ['arg' => '--printer ', 'desc' => 'TestListener implementation to use'], + ['spacer' => ''], + + ['arg' => '--order-by ', 'desc' => 'Run tests in order: default|defects|duration|no-depends|random|reverse|size'], + ['arg' => '--random-order-seed ', 'desc' => 'Use a specific random seed for random order'], + ['arg' => '--cache-result', 'desc' => 'Write test results to cache file'], + ['arg' => '--do-not-cache-result', 'desc' => 'Do not write test results to cache file'], + ], + + 'Configuration Options' => [ + ['arg' => '--prepend ', 'desc' => 'A PHP script that is included as early as possible'], + ['arg' => '--bootstrap ', 'desc' => 'A PHP script that is included before the tests run'], + ['arg' => '-c|--configuration ', 'desc' => 'Read configuration from XML file'], + ['arg' => '--no-configuration', 'desc' => 'Ignore default configuration file (phpunit.xml)'], + ['arg' => '--extensions ', 'desc' => 'A comma separated list of PHPUnit extensions to load'], + ['arg' => '--no-extensions', 'desc' => 'Do not load PHPUnit extensions'], + ['arg' => '--include-path ', 'desc' => 'Prepend PHP\'s include_path with given path(s)'], + ['arg' => '-d ', 'desc' => 'Sets a php.ini value'], + ['arg' => '--cache-result-file ', 'desc' => 'Specify result cache path and filename'], + ['arg' => '--generate-configuration', 'desc' => 'Generate configuration file with suggested settings'], + ['arg' => '--migrate-configuration', 'desc' => 'Migrate configuration file to current format'], + ], + + 'Miscellaneous Options' => [ + ['arg' => '-h|--help', 'desc' => 'Prints this usage information'], + ['arg' => '--version', 'desc' => 'Prints the version and exits'], + ['arg' => '--atleast-version ', 'desc' => 'Checks that version is greater than min and exits'], + ['arg' => '--check-version', 'desc' => 'Check whether PHPUnit is the latest version'], + ], + + ]; + + /** + * @var int Number of columns required to write the longest option name to the console + */ + private $maxArgLength = 0; + + /** + * @var int Number of columns left for the description field after padding and option + */ + private $maxDescLength; + + /** + * @var bool Use color highlights for sections, options and parameters + */ + private $hasColor = false; + + public function __construct(?int $width = null, ?bool $withColor = null) + { + if ($width === null) { + $width = (new Console)->getNumberOfColumns(); + } + + if ($withColor === null) { + $this->hasColor = (new Console)->hasColorSupport(); + } else { + $this->hasColor = $withColor; + } + + foreach (self::HELP_TEXT as $options) { + foreach ($options as $option) { + if (isset($option['arg'])) { + $this->maxArgLength = max($this->maxArgLength, isset($option['arg']) ? strlen($option['arg']) : 0); + } + } + } + + $this->maxDescLength = $width - $this->maxArgLength - 4; + } + + /** + * Write the help file to the CLI, adapting width and colors to the console. + */ + public function writeToConsole(): void + { + if ($this->hasColor) { + $this->writeWithColor(); + } else { + $this->writePlaintext(); + } + } + + private function writePlaintext(): void + { + foreach (self::HELP_TEXT as $section => $options) { + print "{$section}:" . PHP_EOL; + + if ($section !== 'Usage') { + print PHP_EOL; + } + + foreach ($options as $option) { + if (isset($option['spacer'])) { + print PHP_EOL; + } + + if (isset($option['text'])) { + print self::LEFT_MARGIN . $option['text'] . PHP_EOL; + } + + if (isset($option['arg'])) { + $arg = str_pad($option['arg'], $this->maxArgLength); + print self::LEFT_MARGIN . $arg . ' ' . $option['desc'] . PHP_EOL; + } + } + + print PHP_EOL; + } + } + + private function writeWithColor(): void + { + foreach (self::HELP_TEXT as $section => $options) { + print Color::colorize('fg-yellow', "{$section}:") . PHP_EOL; + + foreach ($options as $option) { + if (isset($option['spacer'])) { + print PHP_EOL; + } + + if (isset($option['text'])) { + print self::LEFT_MARGIN . $option['text'] . PHP_EOL; + } + + if (isset($option['arg'])) { + $arg = Color::colorize('fg-green', str_pad($option['arg'], $this->maxArgLength)); + $arg = preg_replace_callback( + '/(<[^>]+>)/', + static function ($matches) + { + return Color::colorize('fg-cyan', $matches[0]); + }, + $arg + ); + $desc = explode(PHP_EOL, wordwrap($option['desc'], $this->maxDescLength, PHP_EOL)); + + print self::LEFT_MARGIN . $arg . ' ' . $desc[0] . PHP_EOL; + + for ($i = 1; $i < count($desc); $i++) { + print str_repeat(' ', $this->maxArgLength + 3) . $desc[$i] . PHP_EOL; + } + } + } + + print PHP_EOL; + } + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/ResultPrinter.php b/vendor/phpunit/phpunit/src/TextUI/ResultPrinter.php new file mode 100644 index 00000000..ec89f600 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/ResultPrinter.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use PHPUnit\Framework\TestListener; +use PHPUnit\Framework\TestResult; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface ResultPrinter extends TestListener +{ + public function printResult(TestResult $result): void; + + public function write(string $buffer): void; +} diff --git a/vendor/phpunit/phpunit/src/TextUI/TestRunner.php b/vendor/phpunit/phpunit/src/TextUI/TestRunner.php new file mode 100644 index 00000000..c1362f3a --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/TestRunner.php @@ -0,0 +1,1264 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use const PHP_EOL; +use const PHP_SAPI; +use const PHP_VERSION; +use function array_diff; +use function array_map; +use function array_merge; +use function assert; +use function class_exists; +use function count; +use function dirname; +use function file_put_contents; +use function htmlspecialchars; +use function is_array; +use function is_int; +use function is_string; +use function mt_srand; +use function range; +use function realpath; +use function sort; +use function sprintf; +use function time; +use PHPUnit\Framework\Exception; +use PHPUnit\Framework\TestResult; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\AfterLastTestHook; +use PHPUnit\Runner\BaseTestRunner; +use PHPUnit\Runner\BeforeFirstTestHook; +use PHPUnit\Runner\DefaultTestResultCache; +use PHPUnit\Runner\Extension\ExtensionHandler; +use PHPUnit\Runner\Filter\ExcludeGroupFilterIterator; +use PHPUnit\Runner\Filter\Factory; +use PHPUnit\Runner\Filter\IncludeGroupFilterIterator; +use PHPUnit\Runner\Filter\NameFilterIterator; +use PHPUnit\Runner\Hook; +use PHPUnit\Runner\NullTestResultCache; +use PHPUnit\Runner\ResultCacheExtension; +use PHPUnit\Runner\StandardTestSuiteLoader; +use PHPUnit\Runner\TestHook; +use PHPUnit\Runner\TestListenerAdapter; +use PHPUnit\Runner\TestSuiteLoader; +use PHPUnit\Runner\TestSuiteSorter; +use PHPUnit\Runner\Version; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\FilterMapper; +use PHPUnit\TextUI\XmlConfiguration\Configuration; +use PHPUnit\TextUI\XmlConfiguration\Loader; +use PHPUnit\TextUI\XmlConfiguration\PhpHandler; +use PHPUnit\Util\Filesystem; +use PHPUnit\Util\Log\JUnit; +use PHPUnit\Util\Log\TeamCity; +use PHPUnit\Util\Printer; +use PHPUnit\Util\TestDox\CliTestDoxPrinter; +use PHPUnit\Util\TestDox\HtmlResultPrinter; +use PHPUnit\Util\TestDox\TextResultPrinter; +use PHPUnit\Util\TestDox\XmlResultPrinter; +use PHPUnit\Util\XdebugFilterScriptGenerator; +use PHPUnit\Util\Xml\SchemaDetector; +use ReflectionClass; +use ReflectionException; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Driver\Selector; +use SebastianBergmann\CodeCoverage\Exception as CodeCoverageException; +use SebastianBergmann\CodeCoverage\Filter as CodeCoverageFilter; +use SebastianBergmann\CodeCoverage\Report\Clover as CloverReport; +use SebastianBergmann\CodeCoverage\Report\Cobertura as CoberturaReport; +use SebastianBergmann\CodeCoverage\Report\Crap4j as Crap4jReport; +use SebastianBergmann\CodeCoverage\Report\Html\Facade as HtmlReport; +use SebastianBergmann\CodeCoverage\Report\PHP as PhpReport; +use SebastianBergmann\CodeCoverage\Report\Text as TextReport; +use SebastianBergmann\CodeCoverage\Report\Xml\Facade as XmlReport; +use SebastianBergmann\Comparator\Comparator; +use SebastianBergmann\Environment\Runtime; +use SebastianBergmann\Invoker\Invoker; +use SebastianBergmann\Timer\Timer; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestRunner extends BaseTestRunner +{ + public const SUCCESS_EXIT = 0; + + public const FAILURE_EXIT = 1; + + public const EXCEPTION_EXIT = 2; + + /** + * @var CodeCoverageFilter + */ + private $codeCoverageFilter; + + /** + * @var TestSuiteLoader + */ + private $loader; + + /** + * @var ResultPrinter + */ + private $printer; + + /** + * @var bool + */ + private $messagePrinted = false; + + /** + * @var Hook[] + */ + private $extensions = []; + + /** + * @var Timer + */ + private $timer; + + public function __construct(TestSuiteLoader $loader = null, CodeCoverageFilter $filter = null) + { + if ($filter === null) { + $filter = new CodeCoverageFilter; + } + + $this->codeCoverageFilter = $filter; + $this->loader = $loader; + $this->timer = new Timer; + } + + /** + * @throws \PHPUnit\Runner\Exception + * @throws \PHPUnit\TextUI\XmlConfiguration\Exception + * @throws Exception + */ + public function run(TestSuite $suite, array $arguments = [], array $warnings = [], bool $exit = true): TestResult + { + if (isset($arguments['configuration'])) { + $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] = $arguments['configuration']; + } + + $this->handleConfiguration($arguments); + + $warnings = array_merge($warnings, $arguments['warnings']); + + if (is_int($arguments['columns']) && $arguments['columns'] < 16) { + $arguments['columns'] = 16; + $tooFewColumnsRequested = true; + } + + if (isset($arguments['bootstrap'])) { + $GLOBALS['__PHPUNIT_BOOTSTRAP'] = $arguments['bootstrap']; + } + + if ($arguments['backupGlobals'] === true) { + $suite->setBackupGlobals(true); + } + + if ($arguments['backupStaticAttributes'] === true) { + $suite->setBackupStaticAttributes(true); + } + + if ($arguments['beStrictAboutChangesToGlobalState'] === true) { + $suite->setBeStrictAboutChangesToGlobalState(true); + } + + if ($arguments['executionOrder'] === TestSuiteSorter::ORDER_RANDOMIZED) { + mt_srand($arguments['randomOrderSeed']); + } + + if ($arguments['cacheResult']) { + if (!isset($arguments['cacheResultFile'])) { + if (isset($arguments['configurationObject'])) { + assert($arguments['configurationObject'] instanceof Configuration); + + $cacheLocation = $arguments['configurationObject']->filename(); + } else { + $cacheLocation = $_SERVER['PHP_SELF']; + } + + $arguments['cacheResultFile'] = null; + + $cacheResultFile = realpath($cacheLocation); + + if ($cacheResultFile !== false) { + $arguments['cacheResultFile'] = dirname($cacheResultFile); + } + } + + $cache = new DefaultTestResultCache($arguments['cacheResultFile']); + + $this->addExtension(new ResultCacheExtension($cache)); + } + + if ($arguments['executionOrder'] !== TestSuiteSorter::ORDER_DEFAULT || $arguments['executionOrderDefects'] !== TestSuiteSorter::ORDER_DEFAULT || $arguments['resolveDependencies']) { + $cache = $cache ?? new NullTestResultCache; + + $cache->load(); + + $sorter = new TestSuiteSorter($cache); + + $sorter->reorderTestsInSuite($suite, $arguments['executionOrder'], $arguments['resolveDependencies'], $arguments['executionOrderDefects']); + $originalExecutionOrder = $sorter->getOriginalExecutionOrder(); + + unset($sorter); + } + + if (is_int($arguments['repeat']) && $arguments['repeat'] > 0) { + $_suite = new TestSuite; + + /* @noinspection PhpUnusedLocalVariableInspection */ + foreach (range(1, $arguments['repeat']) as $step) { + $_suite->addTest($suite); + } + + $suite = $_suite; + + unset($_suite); + } + + $result = $this->createTestResult(); + + $listener = new TestListenerAdapter; + $listenerNeeded = false; + + foreach ($this->extensions as $extension) { + if ($extension instanceof TestHook) { + $listener->add($extension); + + $listenerNeeded = true; + } + } + + if ($listenerNeeded) { + $result->addListener($listener); + } + + unset($listener, $listenerNeeded); + + if ($arguments['convertDeprecationsToExceptions']) { + $result->convertDeprecationsToExceptions(true); + } + + if (!$arguments['convertErrorsToExceptions']) { + $result->convertErrorsToExceptions(false); + } + + if (!$arguments['convertNoticesToExceptions']) { + $result->convertNoticesToExceptions(false); + } + + if (!$arguments['convertWarningsToExceptions']) { + $result->convertWarningsToExceptions(false); + } + + if ($arguments['stopOnError']) { + $result->stopOnError(true); + } + + if ($arguments['stopOnFailure']) { + $result->stopOnFailure(true); + } + + if ($arguments['stopOnWarning']) { + $result->stopOnWarning(true); + } + + if ($arguments['stopOnIncomplete']) { + $result->stopOnIncomplete(true); + } + + if ($arguments['stopOnRisky']) { + $result->stopOnRisky(true); + } + + if ($arguments['stopOnSkipped']) { + $result->stopOnSkipped(true); + } + + if ($arguments['stopOnDefect']) { + $result->stopOnDefect(true); + } + + if ($arguments['registerMockObjectsFromTestArgumentsRecursively']) { + $result->setRegisterMockObjectsFromTestArgumentsRecursively(true); + } + + if ($this->printer === null) { + if (isset($arguments['printer'])) { + if ($arguments['printer'] instanceof ResultPrinter) { + $this->printer = $arguments['printer']; + } elseif (is_string($arguments['printer']) && class_exists($arguments['printer'], false)) { + try { + $reflector = new ReflectionClass($arguments['printer']); + + if ($reflector->implementsInterface(ResultPrinter::class)) { + $this->printer = $this->createPrinter($arguments['printer'], $arguments); + } + + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + } else { + $this->printer = $this->createPrinter(DefaultResultPrinter::class, $arguments); + } + } + + if (isset($originalExecutionOrder) && $this->printer instanceof CliTestDoxPrinter) { + assert($this->printer instanceof CliTestDoxPrinter); + + $this->printer->setOriginalExecutionOrder($originalExecutionOrder); + $this->printer->setShowProgressAnimation(!$arguments['noInteraction']); + } + + $this->write(Version::getVersionString() . "\n"); + + foreach ($arguments['listeners'] as $listener) { + $result->addListener($listener); + } + + $result->addListener($this->printer); + + $coverageFilterFromConfigurationFile = false; + $coverageFilterFromOption = false; + $codeCoverageReports = 0; + + if (isset($arguments['testdoxHTMLFile'])) { + $result->addListener( + new HtmlResultPrinter( + $arguments['testdoxHTMLFile'], + $arguments['testdoxGroups'], + $arguments['testdoxExcludeGroups'] + ) + ); + } + + if (isset($arguments['testdoxTextFile'])) { + $result->addListener( + new TextResultPrinter( + $arguments['testdoxTextFile'], + $arguments['testdoxGroups'], + $arguments['testdoxExcludeGroups'] + ) + ); + } + + if (isset($arguments['testdoxXMLFile'])) { + $result->addListener( + new XmlResultPrinter( + $arguments['testdoxXMLFile'] + ) + ); + } + + if (isset($arguments['teamcityLogfile'])) { + $result->addListener( + new TeamCity($arguments['teamcityLogfile']) + ); + } + + if (isset($arguments['junitLogfile'])) { + $result->addListener( + new JUnit( + $arguments['junitLogfile'], + $arguments['reportUselessTests'] + ) + ); + } + + if (isset($arguments['coverageClover'])) { + $codeCoverageReports++; + } + + if (isset($arguments['coverageCobertura'])) { + $codeCoverageReports++; + } + + if (isset($arguments['coverageCrap4J'])) { + $codeCoverageReports++; + } + + if (isset($arguments['coverageHtml'])) { + $codeCoverageReports++; + } + + if (isset($arguments['coveragePHP'])) { + $codeCoverageReports++; + } + + if (isset($arguments['coverageText'])) { + $codeCoverageReports++; + } + + if (isset($arguments['coverageXml'])) { + $codeCoverageReports++; + } + + if ($codeCoverageReports > 0 || isset($arguments['xdebugFilterFile'])) { + if (isset($arguments['coverageFilter'])) { + if (!is_array($arguments['coverageFilter'])) { + $coverageFilterDirectories = [$arguments['coverageFilter']]; + } else { + $coverageFilterDirectories = $arguments['coverageFilter']; + } + + foreach ($coverageFilterDirectories as $coverageFilterDirectory) { + $this->codeCoverageFilter->includeDirectory($coverageFilterDirectory); + } + + $coverageFilterFromOption = true; + } + + if (isset($arguments['configurationObject'])) { + assert($arguments['configurationObject'] instanceof Configuration); + + $codeCoverageConfiguration = $arguments['configurationObject']->codeCoverage(); + + if ($codeCoverageConfiguration->hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport()) { + $coverageFilterFromConfigurationFile = true; + + (new FilterMapper)->map( + $this->codeCoverageFilter, + $codeCoverageConfiguration + ); + } + } + } + + if ($codeCoverageReports > 0) { + try { + if (isset($codeCoverageConfiguration) && + ($codeCoverageConfiguration->pathCoverage() || (isset($arguments['pathCoverage']) && $arguments['pathCoverage'] === true))) { + $codeCoverageDriver = (new Selector)->forLineAndPathCoverage($this->codeCoverageFilter); + } else { + $codeCoverageDriver = (new Selector)->forLineCoverage($this->codeCoverageFilter); + } + + $codeCoverage = new CodeCoverage( + $codeCoverageDriver, + $this->codeCoverageFilter + ); + + if (isset($codeCoverageConfiguration) && $codeCoverageConfiguration->hasCacheDirectory()) { + $codeCoverage->cacheStaticAnalysis($codeCoverageConfiguration->cacheDirectory()->path()); + } + + if (isset($arguments['coverageCacheDirectory'])) { + $codeCoverage->cacheStaticAnalysis($arguments['coverageCacheDirectory']); + } + + $codeCoverage->excludeSubclassesOfThisClassFromUnintentionallyCoveredCodeCheck(Comparator::class); + + if ($arguments['strictCoverage']) { + $codeCoverage->enableCheckForUnintentionallyCoveredCode(); + } + + if (isset($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'])) { + if ($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage']) { + $codeCoverage->ignoreDeprecatedCode(); + } else { + $codeCoverage->doNotIgnoreDeprecatedCode(); + } + } + + if (isset($arguments['disableCodeCoverageIgnore'])) { + if ($arguments['disableCodeCoverageIgnore']) { + $codeCoverage->disableAnnotationsForIgnoringCode(); + } else { + $codeCoverage->enableAnnotationsForIgnoringCode(); + } + } + + if (isset($arguments['configurationObject'])) { + $codeCoverageConfiguration = $arguments['configurationObject']->codeCoverage(); + + if ($codeCoverageConfiguration->hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport()) { + if ($codeCoverageConfiguration->includeUncoveredFiles()) { + $codeCoverage->includeUncoveredFiles(); + } else { + $codeCoverage->excludeUncoveredFiles(); + } + + if ($codeCoverageConfiguration->processUncoveredFiles()) { + $codeCoverage->processUncoveredFiles(); + } else { + $codeCoverage->doNotProcessUncoveredFiles(); + } + } + } + + if ($this->codeCoverageFilter->isEmpty()) { + if (!$coverageFilterFromConfigurationFile && !$coverageFilterFromOption) { + $warnings[] = 'No filter is configured, code coverage will not be processed'; + } else { + $warnings[] = 'Incorrect filter configuration, code coverage will not be processed'; + } + + unset($codeCoverage); + } + } catch (CodeCoverageException $e) { + $warnings[] = $e->getMessage(); + } + } + + if ($arguments['verbose']) { + if (PHP_SAPI === 'phpdbg') { + $this->writeMessage('Runtime', 'PHPDBG ' . PHP_VERSION); + } else { + $runtime = 'PHP ' . PHP_VERSION; + + if (isset($codeCoverageDriver)) { + $runtime .= ' with ' . $codeCoverageDriver->nameAndVersion(); + } + + $this->writeMessage('Runtime', $runtime); + } + + if (isset($arguments['configurationObject'])) { + assert($arguments['configurationObject'] instanceof Configuration); + + $this->writeMessage( + 'Configuration', + $arguments['configurationObject']->filename() + ); + } + + foreach ($arguments['loadedExtensions'] as $extension) { + $this->writeMessage( + 'Extension', + $extension + ); + } + + foreach ($arguments['notLoadedExtensions'] as $extension) { + $this->writeMessage( + 'Extension', + $extension + ); + } + } + + if ($arguments['executionOrder'] === TestSuiteSorter::ORDER_RANDOMIZED) { + $this->writeMessage( + 'Random Seed', + (string) $arguments['randomOrderSeed'] + ); + } + + if (isset($tooFewColumnsRequested)) { + $warnings[] = 'Less than 16 columns requested, number of columns set to 16'; + } + + if ((new Runtime)->discardsComments()) { + $warnings[] = 'opcache.save_comments=0 set; annotations will not work'; + } + + if (isset($arguments['conflictBetweenPrinterClassAndTestdox'])) { + $warnings[] = 'Directives printerClass and testdox are mutually exclusive'; + } + + $warnings = array_merge($warnings, $suite->warnings()); + sort($warnings); + + foreach ($warnings as $warning) { + $this->writeMessage('Warning', $warning); + } + + if (isset($arguments['configurationObject'])) { + assert($arguments['configurationObject'] instanceof Configuration); + + if ($arguments['configurationObject']->hasValidationErrors()) { + if ((new SchemaDetector)->detect($arguments['configurationObject']->filename())->detected()) { + $this->writeMessage('Warning', 'Your XML configuration validates against a deprecated schema.'); + $this->writeMessage('Suggestion', 'Migrate your XML configuration using "--migrate-configuration"!'); + } else { + $this->write( + "\n Warning - The configuration file did not pass validation!\n The following problems have been detected:\n" + ); + + $this->write($arguments['configurationObject']->validationErrors()); + + $this->write("\n Test results may not be as expected.\n\n"); + } + } + } + + if (isset($arguments['xdebugFilterFile'], $codeCoverageConfiguration)) { + $this->write(PHP_EOL . 'Please note that --dump-xdebug-filter and --prepend are deprecated and will be removed in PHPUnit 10.' . PHP_EOL); + + $script = (new XdebugFilterScriptGenerator)->generate($codeCoverageConfiguration); + + if ($arguments['xdebugFilterFile'] !== 'php://stdout' && $arguments['xdebugFilterFile'] !== 'php://stderr' && !Filesystem::createDirectory(dirname($arguments['xdebugFilterFile']))) { + $this->write(sprintf('Cannot write Xdebug filter script to %s ' . PHP_EOL, $arguments['xdebugFilterFile'])); + + exit(self::EXCEPTION_EXIT); + } + + file_put_contents($arguments['xdebugFilterFile'], $script); + + $this->write(sprintf('Wrote Xdebug filter script to %s ' . PHP_EOL . PHP_EOL, $arguments['xdebugFilterFile'])); + + exit(self::SUCCESS_EXIT); + } + + $this->write("\n"); + + if (isset($codeCoverage)) { + $result->setCodeCoverage($codeCoverage); + } + + $result->beStrictAboutTestsThatDoNotTestAnything($arguments['reportUselessTests']); + $result->beStrictAboutOutputDuringTests($arguments['disallowTestOutput']); + $result->beStrictAboutTodoAnnotatedTests($arguments['disallowTodoAnnotatedTests']); + $result->beStrictAboutResourceUsageDuringSmallTests($arguments['beStrictAboutResourceUsageDuringSmallTests']); + + if ($arguments['enforceTimeLimit'] === true && !(new Invoker)->canInvokeWithTimeout()) { + $this->writeMessage('Error', 'PHP extension pcntl is required for enforcing time limits'); + } + + $result->enforceTimeLimit($arguments['enforceTimeLimit']); + $result->setDefaultTimeLimit($arguments['defaultTimeLimit']); + $result->setTimeoutForSmallTests($arguments['timeoutForSmallTests']); + $result->setTimeoutForMediumTests($arguments['timeoutForMediumTests']); + $result->setTimeoutForLargeTests($arguments['timeoutForLargeTests']); + + if (isset($arguments['forceCoversAnnotation']) && $arguments['forceCoversAnnotation'] === true) { + $result->forceCoversAnnotation(); + } + + $this->processSuiteFilters($suite, $arguments); + $suite->setRunTestInSeparateProcess($arguments['processIsolation']); + + foreach ($this->extensions as $extension) { + if ($extension instanceof BeforeFirstTestHook) { + $extension->executeBeforeFirstTest(); + } + } + + $suite->run($result); + + foreach ($this->extensions as $extension) { + if ($extension instanceof AfterLastTestHook) { + $extension->executeAfterLastTest(); + } + } + + $result->flushListeners(); + $this->printer->printResult($result); + + if (isset($codeCoverage)) { + if (isset($arguments['coverageClover'])) { + $this->codeCoverageGenerationStart('Clover XML'); + + try { + $writer = new CloverReport; + $writer->process($codeCoverage, $arguments['coverageClover']); + + $this->codeCoverageGenerationSucceeded(); + + unset($writer); + } catch (CodeCoverageException $e) { + $this->codeCoverageGenerationFailed($e); + } + } + + if (isset($arguments['coverageCobertura'])) { + $this->codeCoverageGenerationStart('Cobertura XML'); + + try { + $writer = new CoberturaReport; + $writer->process($codeCoverage, $arguments['coverageCobertura']); + + $this->codeCoverageGenerationSucceeded(); + + unset($writer); + } catch (CodeCoverageException $e) { + $this->codeCoverageGenerationFailed($e); + } + } + + if (isset($arguments['coverageCrap4J'])) { + $this->codeCoverageGenerationStart('Crap4J XML'); + + try { + $writer = new Crap4jReport($arguments['crap4jThreshold']); + $writer->process($codeCoverage, $arguments['coverageCrap4J']); + + $this->codeCoverageGenerationSucceeded(); + + unset($writer); + } catch (CodeCoverageException $e) { + $this->codeCoverageGenerationFailed($e); + } + } + + if (isset($arguments['coverageHtml'])) { + $this->codeCoverageGenerationStart('HTML'); + + try { + $writer = new HtmlReport( + $arguments['reportLowUpperBound'], + $arguments['reportHighLowerBound'], + sprintf( + ' and PHPUnit %s', + Version::id() + ) + ); + + $writer->process($codeCoverage, $arguments['coverageHtml']); + + $this->codeCoverageGenerationSucceeded(); + + unset($writer); + } catch (CodeCoverageException $e) { + $this->codeCoverageGenerationFailed($e); + } + } + + if (isset($arguments['coveragePHP'])) { + $this->codeCoverageGenerationStart('PHP'); + + try { + $writer = new PhpReport; + $writer->process($codeCoverage, $arguments['coveragePHP']); + + $this->codeCoverageGenerationSucceeded(); + + unset($writer); + } catch (CodeCoverageException $e) { + $this->codeCoverageGenerationFailed($e); + } + } + + if (isset($arguments['coverageText'])) { + if ($arguments['coverageText'] === 'php://stdout') { + $outputStream = $this->printer; + $colors = $arguments['colors'] && $arguments['colors'] !== DefaultResultPrinter::COLOR_NEVER; + } else { + $outputStream = new Printer($arguments['coverageText']); + $colors = false; + } + + $processor = new TextReport( + $arguments['reportLowUpperBound'], + $arguments['reportHighLowerBound'], + $arguments['coverageTextShowUncoveredFiles'], + $arguments['coverageTextShowOnlySummary'] + ); + + $outputStream->write( + $processor->process($codeCoverage, $colors) + ); + } + + if (isset($arguments['coverageXml'])) { + $this->codeCoverageGenerationStart('PHPUnit XML'); + + try { + $writer = new XmlReport(Version::id()); + $writer->process($codeCoverage, $arguments['coverageXml']); + + $this->codeCoverageGenerationSucceeded(); + + unset($writer); + } catch (CodeCoverageException $e) { + $this->codeCoverageGenerationFailed($e); + } + } + } + + if ($exit) { + if (isset($arguments['failOnEmptyTestSuite']) && $arguments['failOnEmptyTestSuite'] === true && count($result) === 0) { + exit(self::FAILURE_EXIT); + } + + if ($result->wasSuccessfulIgnoringWarnings()) { + if ($arguments['failOnRisky'] && !$result->allHarmless()) { + exit(self::FAILURE_EXIT); + } + + if ($arguments['failOnWarning'] && $result->warningCount() > 0) { + exit(self::FAILURE_EXIT); + } + + if ($arguments['failOnIncomplete'] && $result->notImplementedCount() > 0) { + exit(self::FAILURE_EXIT); + } + + if ($arguments['failOnSkipped'] && $result->skippedCount() > 0) { + exit(self::FAILURE_EXIT); + } + + exit(self::SUCCESS_EXIT); + } + + if ($result->errorCount() > 0) { + exit(self::EXCEPTION_EXIT); + } + + if ($result->failureCount() > 0) { + exit(self::FAILURE_EXIT); + } + } + + return $result; + } + + /** + * Returns the loader to be used. + */ + public function getLoader(): TestSuiteLoader + { + if ($this->loader === null) { + $this->loader = new StandardTestSuiteLoader; + } + + return $this->loader; + } + + public function addExtension(Hook $extension): void + { + $this->extensions[] = $extension; + } + + /** + * Override to define how to handle a failed loading of + * a test suite. + */ + protected function runFailed(string $message): void + { + $this->write($message . PHP_EOL); + + exit(self::FAILURE_EXIT); + } + + private function createTestResult(): TestResult + { + return new TestResult; + } + + private function write(string $buffer): void + { + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') { + $buffer = htmlspecialchars($buffer); + } + + if ($this->printer !== null) { + $this->printer->write($buffer); + } else { + print $buffer; + } + } + + /** + * @throws \PHPUnit\TextUI\XmlConfiguration\Exception + * @throws Exception + */ + private function handleConfiguration(array &$arguments): void + { + if (!isset($arguments['configurationObject']) && isset($arguments['configuration'])) { + $arguments['configurationObject'] = (new Loader)->load($arguments['configuration']); + } + + if (!isset($arguments['warnings'])) { + $arguments['warnings'] = []; + } + + $arguments['debug'] = $arguments['debug'] ?? false; + $arguments['filter'] = $arguments['filter'] ?? false; + $arguments['listeners'] = $arguments['listeners'] ?? []; + + if (isset($arguments['configurationObject'])) { + (new PhpHandler)->handle($arguments['configurationObject']->php()); + + $codeCoverageConfiguration = $arguments['configurationObject']->codeCoverage(); + + if (!isset($arguments['noCoverage'])) { + if (!isset($arguments['coverageClover']) && $codeCoverageConfiguration->hasClover()) { + $arguments['coverageClover'] = $codeCoverageConfiguration->clover()->target()->path(); + } + + if (!isset($arguments['coverageCobertura']) && $codeCoverageConfiguration->hasCobertura()) { + $arguments['coverageCobertura'] = $codeCoverageConfiguration->cobertura()->target()->path(); + } + + if (!isset($arguments['coverageCrap4J']) && $codeCoverageConfiguration->hasCrap4j()) { + $arguments['coverageCrap4J'] = $codeCoverageConfiguration->crap4j()->target()->path(); + + if (!isset($arguments['crap4jThreshold'])) { + $arguments['crap4jThreshold'] = $codeCoverageConfiguration->crap4j()->threshold(); + } + } + + if (!isset($arguments['coverageHtml']) && $codeCoverageConfiguration->hasHtml()) { + $arguments['coverageHtml'] = $codeCoverageConfiguration->html()->target()->path(); + + if (!isset($arguments['reportLowUpperBound'])) { + $arguments['reportLowUpperBound'] = $codeCoverageConfiguration->html()->lowUpperBound(); + } + + if (!isset($arguments['reportHighLowerBound'])) { + $arguments['reportHighLowerBound'] = $codeCoverageConfiguration->html()->highLowerBound(); + } + } + + if (!isset($arguments['coveragePHP']) && $codeCoverageConfiguration->hasPhp()) { + $arguments['coveragePHP'] = $codeCoverageConfiguration->php()->target()->path(); + } + + if (!isset($arguments['coverageText']) && $codeCoverageConfiguration->hasText()) { + $arguments['coverageText'] = $codeCoverageConfiguration->text()->target()->path(); + $arguments['coverageTextShowUncoveredFiles'] = $codeCoverageConfiguration->text()->showUncoveredFiles(); + $arguments['coverageTextShowOnlySummary'] = $codeCoverageConfiguration->text()->showOnlySummary(); + } + + if (!isset($arguments['coverageXml']) && $codeCoverageConfiguration->hasXml()) { + $arguments['coverageXml'] = $codeCoverageConfiguration->xml()->target()->path(); + } + } + + $phpunitConfiguration = $arguments['configurationObject']->phpunit(); + + $arguments['backupGlobals'] = $arguments['backupGlobals'] ?? $phpunitConfiguration->backupGlobals(); + $arguments['backupStaticAttributes'] = $arguments['backupStaticAttributes'] ?? $phpunitConfiguration->backupStaticAttributes(); + $arguments['beStrictAboutChangesToGlobalState'] = $arguments['beStrictAboutChangesToGlobalState'] ?? $phpunitConfiguration->beStrictAboutChangesToGlobalState(); + $arguments['cacheResult'] = $arguments['cacheResult'] ?? $phpunitConfiguration->cacheResult(); + $arguments['colors'] = $arguments['colors'] ?? $phpunitConfiguration->colors(); + $arguments['convertDeprecationsToExceptions'] = $arguments['convertDeprecationsToExceptions'] ?? $phpunitConfiguration->convertDeprecationsToExceptions(); + $arguments['convertErrorsToExceptions'] = $arguments['convertErrorsToExceptions'] ?? $phpunitConfiguration->convertErrorsToExceptions(); + $arguments['convertNoticesToExceptions'] = $arguments['convertNoticesToExceptions'] ?? $phpunitConfiguration->convertNoticesToExceptions(); + $arguments['convertWarningsToExceptions'] = $arguments['convertWarningsToExceptions'] ?? $phpunitConfiguration->convertWarningsToExceptions(); + $arguments['processIsolation'] = $arguments['processIsolation'] ?? $phpunitConfiguration->processIsolation(); + $arguments['stopOnDefect'] = $arguments['stopOnDefect'] ?? $phpunitConfiguration->stopOnDefect(); + $arguments['stopOnError'] = $arguments['stopOnError'] ?? $phpunitConfiguration->stopOnError(); + $arguments['stopOnFailure'] = $arguments['stopOnFailure'] ?? $phpunitConfiguration->stopOnFailure(); + $arguments['stopOnWarning'] = $arguments['stopOnWarning'] ?? $phpunitConfiguration->stopOnWarning(); + $arguments['stopOnIncomplete'] = $arguments['stopOnIncomplete'] ?? $phpunitConfiguration->stopOnIncomplete(); + $arguments['stopOnRisky'] = $arguments['stopOnRisky'] ?? $phpunitConfiguration->stopOnRisky(); + $arguments['stopOnSkipped'] = $arguments['stopOnSkipped'] ?? $phpunitConfiguration->stopOnSkipped(); + $arguments['failOnEmptyTestSuite'] = $arguments['failOnEmptyTestSuite'] ?? $phpunitConfiguration->failOnEmptyTestSuite(); + $arguments['failOnIncomplete'] = $arguments['failOnIncomplete'] ?? $phpunitConfiguration->failOnIncomplete(); + $arguments['failOnRisky'] = $arguments['failOnRisky'] ?? $phpunitConfiguration->failOnRisky(); + $arguments['failOnSkipped'] = $arguments['failOnSkipped'] ?? $phpunitConfiguration->failOnSkipped(); + $arguments['failOnWarning'] = $arguments['failOnWarning'] ?? $phpunitConfiguration->failOnWarning(); + $arguments['enforceTimeLimit'] = $arguments['enforceTimeLimit'] ?? $phpunitConfiguration->enforceTimeLimit(); + $arguments['defaultTimeLimit'] = $arguments['defaultTimeLimit'] ?? $phpunitConfiguration->defaultTimeLimit(); + $arguments['timeoutForSmallTests'] = $arguments['timeoutForSmallTests'] ?? $phpunitConfiguration->timeoutForSmallTests(); + $arguments['timeoutForMediumTests'] = $arguments['timeoutForMediumTests'] ?? $phpunitConfiguration->timeoutForMediumTests(); + $arguments['timeoutForLargeTests'] = $arguments['timeoutForLargeTests'] ?? $phpunitConfiguration->timeoutForLargeTests(); + $arguments['reportUselessTests'] = $arguments['reportUselessTests'] ?? $phpunitConfiguration->beStrictAboutTestsThatDoNotTestAnything(); + $arguments['strictCoverage'] = $arguments['strictCoverage'] ?? $phpunitConfiguration->beStrictAboutCoversAnnotation(); + $arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'] = $arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'] ?? $codeCoverageConfiguration->ignoreDeprecatedCodeUnits(); + $arguments['disallowTestOutput'] = $arguments['disallowTestOutput'] ?? $phpunitConfiguration->beStrictAboutOutputDuringTests(); + $arguments['disallowTodoAnnotatedTests'] = $arguments['disallowTodoAnnotatedTests'] ?? $phpunitConfiguration->beStrictAboutTodoAnnotatedTests(); + $arguments['beStrictAboutResourceUsageDuringSmallTests'] = $arguments['beStrictAboutResourceUsageDuringSmallTests'] ?? $phpunitConfiguration->beStrictAboutResourceUsageDuringSmallTests(); + $arguments['verbose'] = $arguments['verbose'] ?? $phpunitConfiguration->verbose(); + $arguments['reverseDefectList'] = $arguments['reverseDefectList'] ?? $phpunitConfiguration->reverseDefectList(); + $arguments['forceCoversAnnotation'] = $arguments['forceCoversAnnotation'] ?? $phpunitConfiguration->forceCoversAnnotation(); + $arguments['disableCodeCoverageIgnore'] = $arguments['disableCodeCoverageIgnore'] ?? $codeCoverageConfiguration->disableCodeCoverageIgnore(); + $arguments['registerMockObjectsFromTestArgumentsRecursively'] = $arguments['registerMockObjectsFromTestArgumentsRecursively'] ?? $phpunitConfiguration->registerMockObjectsFromTestArgumentsRecursively(); + $arguments['noInteraction'] = $arguments['noInteraction'] ?? $phpunitConfiguration->noInteraction(); + $arguments['executionOrder'] = $arguments['executionOrder'] ?? $phpunitConfiguration->executionOrder(); + $arguments['resolveDependencies'] = $arguments['resolveDependencies'] ?? $phpunitConfiguration->resolveDependencies(); + + if (!isset($arguments['bootstrap']) && $phpunitConfiguration->hasBootstrap()) { + $arguments['bootstrap'] = $phpunitConfiguration->bootstrap(); + } + + if (!isset($arguments['cacheResultFile']) && $phpunitConfiguration->hasCacheResultFile()) { + $arguments['cacheResultFile'] = $phpunitConfiguration->cacheResultFile(); + } + + if (!isset($arguments['executionOrderDefects'])) { + $arguments['executionOrderDefects'] = $phpunitConfiguration->defectsFirst() ? TestSuiteSorter::ORDER_DEFECTS_FIRST : TestSuiteSorter::ORDER_DEFAULT; + } + + if ($phpunitConfiguration->conflictBetweenPrinterClassAndTestdox()) { + $arguments['conflictBetweenPrinterClassAndTestdox'] = true; + } + + $groupCliArgs = []; + + if (!empty($arguments['groups'])) { + $groupCliArgs = $arguments['groups']; + } + + $groupConfiguration = $arguments['configurationObject']->groups(); + + if (!isset($arguments['groups']) && $groupConfiguration->hasInclude()) { + $arguments['groups'] = $groupConfiguration->include()->asArrayOfStrings(); + } + + if (!isset($arguments['excludeGroups']) && $groupConfiguration->hasExclude()) { + $arguments['excludeGroups'] = array_diff($groupConfiguration->exclude()->asArrayOfStrings(), $groupCliArgs); + } + + if (!isset($this->arguments['noExtensions'])) { + $extensionHandler = new ExtensionHandler; + + foreach ($arguments['configurationObject']->extensions() as $extension) { + $extensionHandler->registerExtension($extension, $this); + } + + foreach ($arguments['configurationObject']->listeners() as $listener) { + $arguments['listeners'][] = $extensionHandler->createTestListenerInstance($listener); + } + + unset($extensionHandler); + } + + foreach ($arguments['unavailableExtensions'] as $extension) { + $arguments['warnings'][] = sprintf( + 'Extension "%s" is not available', + $extension + ); + } + + $loggingConfiguration = $arguments['configurationObject']->logging(); + + if (!isset($arguments['noLogging'])) { + if ($loggingConfiguration->hasText()) { + $arguments['listeners'][] = new DefaultResultPrinter( + $loggingConfiguration->text()->target()->path(), + true + ); + } + + if (!isset($arguments['teamcityLogfile']) && $loggingConfiguration->hasTeamCity()) { + $arguments['teamcityLogfile'] = $loggingConfiguration->teamCity()->target()->path(); + } + + if (!isset($arguments['junitLogfile']) && $loggingConfiguration->hasJunit()) { + $arguments['junitLogfile'] = $loggingConfiguration->junit()->target()->path(); + } + + if (!isset($arguments['testdoxHTMLFile']) && $loggingConfiguration->hasTestDoxHtml()) { + $arguments['testdoxHTMLFile'] = $loggingConfiguration->testDoxHtml()->target()->path(); + } + + if (!isset($arguments['testdoxTextFile']) && $loggingConfiguration->hasTestDoxText()) { + $arguments['testdoxTextFile'] = $loggingConfiguration->testDoxText()->target()->path(); + } + + if (!isset($arguments['testdoxXMLFile']) && $loggingConfiguration->hasTestDoxXml()) { + $arguments['testdoxXMLFile'] = $loggingConfiguration->testDoxXml()->target()->path(); + } + } + + $testdoxGroupConfiguration = $arguments['configurationObject']->testdoxGroups(); + + if (!isset($arguments['testdoxGroups']) && $testdoxGroupConfiguration->hasInclude()) { + $arguments['testdoxGroups'] = $testdoxGroupConfiguration->include()->asArrayOfStrings(); + } + + if (!isset($arguments['testdoxExcludeGroups']) && $testdoxGroupConfiguration->hasExclude()) { + $arguments['testdoxExcludeGroups'] = $testdoxGroupConfiguration->exclude()->asArrayOfStrings(); + } + } + + $extensionHandler = new ExtensionHandler; + + foreach ($arguments['extensions'] as $extension) { + $extensionHandler->registerExtension($extension, $this); + } + + unset($extensionHandler); + + $arguments['backupGlobals'] = $arguments['backupGlobals'] ?? null; + $arguments['backupStaticAttributes'] = $arguments['backupStaticAttributes'] ?? null; + $arguments['beStrictAboutChangesToGlobalState'] = $arguments['beStrictAboutChangesToGlobalState'] ?? null; + $arguments['beStrictAboutResourceUsageDuringSmallTests'] = $arguments['beStrictAboutResourceUsageDuringSmallTests'] ?? false; + $arguments['cacheResult'] = $arguments['cacheResult'] ?? true; + $arguments['colors'] = $arguments['colors'] ?? DefaultResultPrinter::COLOR_DEFAULT; + $arguments['columns'] = $arguments['columns'] ?? 80; + $arguments['convertDeprecationsToExceptions'] = $arguments['convertDeprecationsToExceptions'] ?? false; + $arguments['convertErrorsToExceptions'] = $arguments['convertErrorsToExceptions'] ?? true; + $arguments['convertNoticesToExceptions'] = $arguments['convertNoticesToExceptions'] ?? true; + $arguments['convertWarningsToExceptions'] = $arguments['convertWarningsToExceptions'] ?? true; + $arguments['crap4jThreshold'] = $arguments['crap4jThreshold'] ?? 30; + $arguments['disallowTestOutput'] = $arguments['disallowTestOutput'] ?? false; + $arguments['disallowTodoAnnotatedTests'] = $arguments['disallowTodoAnnotatedTests'] ?? false; + $arguments['defaultTimeLimit'] = $arguments['defaultTimeLimit'] ?? 0; + $arguments['enforceTimeLimit'] = $arguments['enforceTimeLimit'] ?? false; + $arguments['excludeGroups'] = $arguments['excludeGroups'] ?? []; + $arguments['executionOrder'] = $arguments['executionOrder'] ?? TestSuiteSorter::ORDER_DEFAULT; + $arguments['executionOrderDefects'] = $arguments['executionOrderDefects'] ?? TestSuiteSorter::ORDER_DEFAULT; + $arguments['failOnIncomplete'] = $arguments['failOnIncomplete'] ?? false; + $arguments['failOnRisky'] = $arguments['failOnRisky'] ?? false; + $arguments['failOnSkipped'] = $arguments['failOnSkipped'] ?? false; + $arguments['failOnWarning'] = $arguments['failOnWarning'] ?? false; + $arguments['groups'] = $arguments['groups'] ?? []; + $arguments['noInteraction'] = $arguments['noInteraction'] ?? false; + $arguments['processIsolation'] = $arguments['processIsolation'] ?? false; + $arguments['randomOrderSeed'] = $arguments['randomOrderSeed'] ?? time(); + $arguments['registerMockObjectsFromTestArgumentsRecursively'] = $arguments['registerMockObjectsFromTestArgumentsRecursively'] ?? false; + $arguments['repeat'] = $arguments['repeat'] ?? false; + $arguments['reportHighLowerBound'] = $arguments['reportHighLowerBound'] ?? 90; + $arguments['reportLowUpperBound'] = $arguments['reportLowUpperBound'] ?? 50; + $arguments['reportUselessTests'] = $arguments['reportUselessTests'] ?? true; + $arguments['reverseList'] = $arguments['reverseList'] ?? false; + $arguments['resolveDependencies'] = $arguments['resolveDependencies'] ?? true; + $arguments['stopOnError'] = $arguments['stopOnError'] ?? false; + $arguments['stopOnFailure'] = $arguments['stopOnFailure'] ?? false; + $arguments['stopOnIncomplete'] = $arguments['stopOnIncomplete'] ?? false; + $arguments['stopOnRisky'] = $arguments['stopOnRisky'] ?? false; + $arguments['stopOnSkipped'] = $arguments['stopOnSkipped'] ?? false; + $arguments['stopOnWarning'] = $arguments['stopOnWarning'] ?? false; + $arguments['stopOnDefect'] = $arguments['stopOnDefect'] ?? false; + $arguments['strictCoverage'] = $arguments['strictCoverage'] ?? false; + $arguments['testdoxExcludeGroups'] = $arguments['testdoxExcludeGroups'] ?? []; + $arguments['testdoxGroups'] = $arguments['testdoxGroups'] ?? []; + $arguments['timeoutForLargeTests'] = $arguments['timeoutForLargeTests'] ?? 60; + $arguments['timeoutForMediumTests'] = $arguments['timeoutForMediumTests'] ?? 10; + $arguments['timeoutForSmallTests'] = $arguments['timeoutForSmallTests'] ?? 1; + $arguments['verbose'] = $arguments['verbose'] ?? false; + + if ($arguments['reportLowUpperBound'] > $arguments['reportHighLowerBound']) { + $arguments['reportLowUpperBound'] = 50; + $arguments['reportHighLowerBound'] = 90; + } + } + + private function processSuiteFilters(TestSuite $suite, array $arguments): void + { + if (!$arguments['filter'] && + empty($arguments['groups']) && + empty($arguments['excludeGroups']) && + empty($arguments['testsCovering']) && + empty($arguments['testsUsing'])) { + return; + } + + $filterFactory = new Factory; + + if (!empty($arguments['excludeGroups'])) { + $filterFactory->addFilter( + new ReflectionClass(ExcludeGroupFilterIterator::class), + $arguments['excludeGroups'] + ); + } + + if (!empty($arguments['groups'])) { + $filterFactory->addFilter( + new ReflectionClass(IncludeGroupFilterIterator::class), + $arguments['groups'] + ); + } + + if (!empty($arguments['testsCovering'])) { + $filterFactory->addFilter( + new ReflectionClass(IncludeGroupFilterIterator::class), + array_map( + static function (string $name): string + { + return '__phpunit_covers_' . $name; + }, + $arguments['testsCovering'] + ) + ); + } + + if (!empty($arguments['testsUsing'])) { + $filterFactory->addFilter( + new ReflectionClass(IncludeGroupFilterIterator::class), + array_map( + static function (string $name): string + { + return '__phpunit_uses_' . $name; + }, + $arguments['testsUsing'] + ) + ); + } + + if ($arguments['filter']) { + $filterFactory->addFilter( + new ReflectionClass(NameFilterIterator::class), + $arguments['filter'] + ); + } + + $suite->injectFilter($filterFactory); + } + + private function writeMessage(string $type, string $message): void + { + if (!$this->messagePrinted) { + $this->write("\n"); + } + + $this->write( + sprintf( + "%-15s%s\n", + $type . ':', + $message + ) + ); + + $this->messagePrinted = true; + } + + private function createPrinter(string $class, array $arguments): ResultPrinter + { + $object = new $class( + (isset($arguments['stderr']) && $arguments['stderr'] === true) ? 'php://stderr' : null, + $arguments['verbose'], + $arguments['colors'], + $arguments['debug'], + $arguments['columns'], + $arguments['reverseList'] + ); + + assert($object instanceof ResultPrinter); + + return $object; + } + + private function codeCoverageGenerationStart(string $format): void + { + $this->write( + sprintf( + "\nGenerating code coverage report in %s format ... ", + $format + ) + ); + + $this->timer->start(); + } + + private function codeCoverageGenerationSucceeded(): void + { + $this->write( + sprintf( + "done [%s]\n", + $this->timer->stop()->asString() + ) + ); + } + + private function codeCoverageGenerationFailed(\Exception $e): void + { + $this->write( + sprintf( + "failed [%s]\n%s\n", + $this->timer->stop()->asString(), + $e->getMessage() + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/TestSuiteMapper.php b/vendor/phpunit/phpunit/src/TextUI/TestSuiteMapper.php new file mode 100644 index 00000000..170e6602 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/TestSuiteMapper.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use const PHP_VERSION; +use function explode; +use function in_array; +use function is_dir; +use function is_file; +use function strpos; +use function version_compare; +use PHPUnit\Framework\Exception as FrameworkException; +use PHPUnit\Framework\TestSuite as TestSuiteObject; +use PHPUnit\TextUI\XmlConfiguration\TestSuiteCollection; +use SebastianBergmann\FileIterator\Facade; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteMapper +{ + /** + * @throws RuntimeException + * @throws TestDirectoryNotFoundException + * @throws TestFileNotFoundException + */ + public function map(TestSuiteCollection $configuration, string $filter): TestSuiteObject + { + try { + $filterAsArray = $filter ? explode(',', $filter) : []; + $result = new TestSuiteObject; + + foreach ($configuration as $testSuiteConfiguration) { + if (!empty($filterAsArray) && !in_array($testSuiteConfiguration->name(), $filterAsArray, true)) { + continue; + } + + $testSuite = new TestSuiteObject($testSuiteConfiguration->name()); + $testSuiteEmpty = true; + + $exclude = []; + + foreach ($testSuiteConfiguration->exclude()->asArray() as $file) { + $exclude[] = $file->path(); + } + + foreach ($testSuiteConfiguration->directories() as $directory) { + if (!version_compare(PHP_VERSION, $directory->phpVersion(), $directory->phpVersionOperator()->asString())) { + continue; + } + + $files = (new Facade)->getFilesAsArray( + $directory->path(), + $directory->suffix(), + $directory->prefix(), + $exclude + ); + + if (!empty($files)) { + $testSuite->addTestFiles($files); + + $testSuiteEmpty = false; + } elseif (strpos($directory->path(), '*') === false && !is_dir($directory->path())) { + throw new TestDirectoryNotFoundException($directory->path()); + } + } + + foreach ($testSuiteConfiguration->files() as $file) { + if (!is_file($file->path())) { + throw new TestFileNotFoundException($file->path()); + } + + if (!version_compare(PHP_VERSION, $file->phpVersion(), $file->phpVersionOperator()->asString())) { + continue; + } + + $testSuite->addTestFile($file->path()); + + $testSuiteEmpty = false; + } + + if (!$testSuiteEmpty) { + $result->addTest($testSuite); + } + } + + return $result; + } catch (FrameworkException $e) { + throw new RuntimeException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/CodeCoverage.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/CodeCoverage.php new file mode 100644 index 00000000..80abfac7 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/CodeCoverage.php @@ -0,0 +1,363 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage; + +use function count; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Filter\DirectoryCollection; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Clover; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Cobertura; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Crap4j; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Html; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Php; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Text; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Xml; +use PHPUnit\TextUI\XmlConfiguration\Directory; +use PHPUnit\TextUI\XmlConfiguration\Exception; +use PHPUnit\TextUI\XmlConfiguration\FileCollection; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class CodeCoverage +{ + /** + * @var ?Directory + */ + private $cacheDirectory; + + /** + * @var DirectoryCollection + */ + private $directories; + + /** + * @var FileCollection + */ + private $files; + + /** + * @var DirectoryCollection + */ + private $excludeDirectories; + + /** + * @var FileCollection + */ + private $excludeFiles; + + /** + * @var bool + */ + private $pathCoverage; + + /** + * @var bool + */ + private $includeUncoveredFiles; + + /** + * @var bool + */ + private $processUncoveredFiles; + + /** + * @var bool + */ + private $ignoreDeprecatedCodeUnits; + + /** + * @var bool + */ + private $disableCodeCoverageIgnore; + + /** + * @var ?Clover + */ + private $clover; + + /** + * @var ?Cobertura + */ + private $cobertura; + + /** + * @var ?Crap4j + */ + private $crap4j; + + /** + * @var ?Html + */ + private $html; + + /** + * @var ?Php + */ + private $php; + + /** + * @var ?Text + */ + private $text; + + /** + * @var ?Xml + */ + private $xml; + + public function __construct(?Directory $cacheDirectory, DirectoryCollection $directories, FileCollection $files, DirectoryCollection $excludeDirectories, FileCollection $excludeFiles, bool $pathCoverage, bool $includeUncoveredFiles, bool $processUncoveredFiles, bool $ignoreDeprecatedCodeUnits, bool $disableCodeCoverageIgnore, ?Clover $clover, ?Cobertura $cobertura, ?Crap4j $crap4j, ?Html $html, ?Php $php, ?Text $text, ?Xml $xml) + { + $this->cacheDirectory = $cacheDirectory; + $this->directories = $directories; + $this->files = $files; + $this->excludeDirectories = $excludeDirectories; + $this->excludeFiles = $excludeFiles; + $this->pathCoverage = $pathCoverage; + $this->includeUncoveredFiles = $includeUncoveredFiles; + $this->processUncoveredFiles = $processUncoveredFiles; + $this->ignoreDeprecatedCodeUnits = $ignoreDeprecatedCodeUnits; + $this->disableCodeCoverageIgnore = $disableCodeCoverageIgnore; + $this->clover = $clover; + $this->cobertura = $cobertura; + $this->crap4j = $crap4j; + $this->html = $html; + $this->php = $php; + $this->text = $text; + $this->xml = $xml; + } + + /** + * @psalm-assert-if-true !null $this->cacheDirectory + */ + public function hasCacheDirectory(): bool + { + return $this->cacheDirectory !== null; + } + + /** + * @throws Exception + */ + public function cacheDirectory(): Directory + { + if (!$this->hasCacheDirectory()) { + throw new Exception( + 'No cache directory has been configured' + ); + } + + return $this->cacheDirectory; + } + + public function hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport(): bool + { + return count($this->directories) > 0 || count($this->files) > 0; + } + + public function directories(): DirectoryCollection + { + return $this->directories; + } + + public function files(): FileCollection + { + return $this->files; + } + + public function excludeDirectories(): DirectoryCollection + { + return $this->excludeDirectories; + } + + public function excludeFiles(): FileCollection + { + return $this->excludeFiles; + } + + public function pathCoverage(): bool + { + return $this->pathCoverage; + } + + public function includeUncoveredFiles(): bool + { + return $this->includeUncoveredFiles; + } + + public function ignoreDeprecatedCodeUnits(): bool + { + return $this->ignoreDeprecatedCodeUnits; + } + + public function disableCodeCoverageIgnore(): bool + { + return $this->disableCodeCoverageIgnore; + } + + public function processUncoveredFiles(): bool + { + return $this->processUncoveredFiles; + } + + /** + * @psalm-assert-if-true !null $this->clover + */ + public function hasClover(): bool + { + return $this->clover !== null; + } + + /** + * @throws Exception + */ + public function clover(): Clover + { + if (!$this->hasClover()) { + throw new Exception( + 'Code Coverage report "Clover XML" has not been configured' + ); + } + + return $this->clover; + } + + /** + * @psalm-assert-if-true !null $this->cobertura + */ + public function hasCobertura(): bool + { + return $this->cobertura !== null; + } + + /** + * @throws Exception + */ + public function cobertura(): Cobertura + { + if (!$this->hasCobertura()) { + throw new Exception( + 'Code Coverage report "Cobertura XML" has not been configured' + ); + } + + return $this->cobertura; + } + + /** + * @psalm-assert-if-true !null $this->crap4j + */ + public function hasCrap4j(): bool + { + return $this->crap4j !== null; + } + + /** + * @throws Exception + */ + public function crap4j(): Crap4j + { + if (!$this->hasCrap4j()) { + throw new Exception( + 'Code Coverage report "Crap4J" has not been configured' + ); + } + + return $this->crap4j; + } + + /** + * @psalm-assert-if-true !null $this->html + */ + public function hasHtml(): bool + { + return $this->html !== null; + } + + /** + * @throws Exception + */ + public function html(): Html + { + if (!$this->hasHtml()) { + throw new Exception( + 'Code Coverage report "HTML" has not been configured' + ); + } + + return $this->html; + } + + /** + * @psalm-assert-if-true !null $this->php + */ + public function hasPhp(): bool + { + return $this->php !== null; + } + + /** + * @throws Exception + */ + public function php(): Php + { + if (!$this->hasPhp()) { + throw new Exception( + 'Code Coverage report "PHP" has not been configured' + ); + } + + return $this->php; + } + + /** + * @psalm-assert-if-true !null $this->text + */ + public function hasText(): bool + { + return $this->text !== null; + } + + /** + * @throws Exception + */ + public function text(): Text + { + if (!$this->hasText()) { + throw new Exception( + 'Code Coverage report "Text" has not been configured' + ); + } + + return $this->text; + } + + /** + * @psalm-assert-if-true !null $this->xml + */ + public function hasXml(): bool + { + return $this->xml !== null; + } + + /** + * @throws Exception + */ + public function xml(): Xml + { + if (!$this->hasXml()) { + throw new Exception( + 'Code Coverage report "XML" has not been configured' + ); + } + + return $this->xml; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/Directory.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/Directory.php new file mode 100644 index 00000000..91659f4d --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/Directory.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Filter; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Directory +{ + /** + * @var string + */ + private $path; + + /** + * @var string + */ + private $prefix; + + /** + * @var string + */ + private $suffix; + + /** + * @var string + */ + private $group; + + public function __construct(string $path, string $prefix, string $suffix, string $group) + { + $this->path = $path; + $this->prefix = $prefix; + $this->suffix = $suffix; + $this->group = $group; + } + + public function path(): string + { + return $this->path; + } + + public function prefix(): string + { + return $this->prefix; + } + + public function suffix(): string + { + return $this->suffix; + } + + public function group(): string + { + return $this->group; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollection.php new file mode 100644 index 00000000..88ec1e38 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollection.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Filter; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class DirectoryCollection implements Countable, IteratorAggregate +{ + /** + * @var Directory[] + */ + private $directories; + + /** + * @param Directory[] $directories + */ + public static function fromArray(array $directories): self + { + return new self(...$directories); + } + + private function __construct(Directory ...$directories) + { + $this->directories = $directories; + } + + /** + * @return Directory[] + */ + public function asArray(): array + { + return $this->directories; + } + + public function count(): int + { + return count($this->directories); + } + + public function getIterator(): DirectoryCollectionIterator + { + return new DirectoryCollectionIterator($this); + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollectionIterator.php new file mode 100644 index 00000000..f2fee25d --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Filter/DirectoryCollectionIterator.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Filter; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class DirectoryCollectionIterator implements Countable, Iterator +{ + /** + * @var Directory[] + */ + private $directories; + + /** + * @var int + */ + private $position; + + public function __construct(DirectoryCollection $directories) + { + $this->directories = $directories->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->directories); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Directory + { + return $this->directories[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/FilterMapper.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/FilterMapper.php new file mode 100644 index 00000000..102c96eb --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/FilterMapper.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage; + +use SebastianBergmann\CodeCoverage\Filter; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class FilterMapper +{ + public function map(Filter $filter, CodeCoverage $configuration): void + { + foreach ($configuration->directories() as $directory) { + $filter->includeDirectory( + $directory->path(), + $directory->suffix(), + $directory->prefix() + ); + } + + foreach ($configuration->files() as $file) { + $filter->includeFile($file->path()); + } + + foreach ($configuration->excludeDirectories() as $directory) { + $filter->excludeDirectory( + $directory->path(), + $directory->suffix(), + $directory->prefix() + ); + } + + foreach ($configuration->excludeFiles() as $file) { + $filter->excludeFile($file->path()); + } + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Clover.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Clover.php new file mode 100644 index 00000000..b1094ec3 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Clover.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; + +use PHPUnit\TextUI\XmlConfiguration\File; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Clover +{ + /** + * @var File + */ + private $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Cobertura.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Cobertura.php new file mode 100644 index 00000000..f831ac09 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Cobertura.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; + +use PHPUnit\TextUI\XmlConfiguration\File; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Cobertura +{ + /** + * @var File + */ + private $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Crap4j.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Crap4j.php new file mode 100644 index 00000000..4904775d --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Crap4j.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; + +use PHPUnit\TextUI\XmlConfiguration\File; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Crap4j +{ + /** + * @var File + */ + private $target; + + /** + * @var int + */ + private $threshold; + + public function __construct(File $target, int $threshold) + { + $this->target = $target; + $this->threshold = $threshold; + } + + public function target(): File + { + return $this->target; + } + + public function threshold(): int + { + return $this->threshold; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Html.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Html.php new file mode 100644 index 00000000..ce3d0284 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Html.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; + +use PHPUnit\TextUI\XmlConfiguration\Directory; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Html +{ + /** + * @var Directory + */ + private $target; + + /** + * @var int + */ + private $lowUpperBound; + + /** + * @var int + */ + private $highLowerBound; + + public function __construct(Directory $target, int $lowUpperBound, int $highLowerBound) + { + $this->target = $target; + $this->lowUpperBound = $lowUpperBound; + $this->highLowerBound = $highLowerBound; + } + + public function target(): Directory + { + return $this->target; + } + + public function lowUpperBound(): int + { + return $this->lowUpperBound; + } + + public function highLowerBound(): int + { + return $this->highLowerBound; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Php.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Php.php new file mode 100644 index 00000000..dc5d32ea --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Php.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; + +use PHPUnit\TextUI\XmlConfiguration\File; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Php +{ + /** + * @var File + */ + private $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Text.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Text.php new file mode 100644 index 00000000..cb7470d3 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Text.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; + +use PHPUnit\TextUI\XmlConfiguration\File; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Text +{ + /** + * @var File + */ + private $target; + + /** + * @var bool + */ + private $showUncoveredFiles; + + /** + * @var bool + */ + private $showOnlySummary; + + public function __construct(File $target, bool $showUncoveredFiles, bool $showOnlySummary) + { + $this->target = $target; + $this->showUncoveredFiles = $showUncoveredFiles; + $this->showOnlySummary = $showOnlySummary; + } + + public function target(): File + { + return $this->target; + } + + public function showUncoveredFiles(): bool + { + return $this->showUncoveredFiles; + } + + public function showOnlySummary(): bool + { + return $this->showOnlySummary; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Xml.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Xml.php new file mode 100644 index 00000000..34073bd5 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/CodeCoverage/Report/Xml.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; + +use PHPUnit\TextUI\XmlConfiguration\Directory; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Xml +{ + /** + * @var Directory + */ + private $target; + + public function __construct(Directory $target) + { + $this->target = $target; + } + + public function target(): Directory + { + return $this->target; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Configuration.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Configuration.php new file mode 100644 index 00000000..4067e2f8 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Configuration.php @@ -0,0 +1,152 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\CodeCoverage; +use PHPUnit\TextUI\XmlConfiguration\Logging\Logging; +use PHPUnit\Util\Xml\ValidationResult; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Configuration +{ + /** + * @var string + */ + private $filename; + + /** + * @var ValidationResult + */ + private $validationResult; + + /** + * @var ExtensionCollection + */ + private $extensions; + + /** + * @var CodeCoverage + */ + private $codeCoverage; + + /** + * @var Groups + */ + private $groups; + + /** + * @var Groups + */ + private $testdoxGroups; + + /** + * @var ExtensionCollection + */ + private $listeners; + + /** + * @var Logging + */ + private $logging; + + /** + * @var Php + */ + private $php; + + /** + * @var PHPUnit + */ + private $phpunit; + + /** + * @var TestSuiteCollection + */ + private $testSuite; + + public function __construct(string $filename, ValidationResult $validationResult, ExtensionCollection $extensions, CodeCoverage $codeCoverage, Groups $groups, Groups $testdoxGroups, ExtensionCollection $listeners, Logging $logging, Php $php, PHPUnit $phpunit, TestSuiteCollection $testSuite) + { + $this->filename = $filename; + $this->validationResult = $validationResult; + $this->extensions = $extensions; + $this->codeCoverage = $codeCoverage; + $this->groups = $groups; + $this->testdoxGroups = $testdoxGroups; + $this->listeners = $listeners; + $this->logging = $logging; + $this->php = $php; + $this->phpunit = $phpunit; + $this->testSuite = $testSuite; + } + + public function filename(): string + { + return $this->filename; + } + + public function hasValidationErrors(): bool + { + return $this->validationResult->hasValidationErrors(); + } + + public function validationErrors(): string + { + return $this->validationResult->asString(); + } + + public function extensions(): ExtensionCollection + { + return $this->extensions; + } + + public function codeCoverage(): CodeCoverage + { + return $this->codeCoverage; + } + + public function groups(): Groups + { + return $this->groups; + } + + public function testdoxGroups(): Groups + { + return $this->testdoxGroups; + } + + public function listeners(): ExtensionCollection + { + return $this->listeners; + } + + public function logging(): Logging + { + return $this->logging; + } + + public function php(): Php + { + return $this->php; + } + + public function phpunit(): PHPUnit + { + return $this->phpunit; + } + + public function testSuite(): TestSuiteCollection + { + return $this->testSuite; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Exception.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Exception.php new file mode 100644 index 00000000..162b37e8 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Exception.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use RuntimeException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Exception extends RuntimeException implements \PHPUnit\Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/Directory.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/Directory.php new file mode 100644 index 00000000..b0fdf64f --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/Directory.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Directory +{ + /** + * @var string + */ + private $path; + + public function __construct(string $path) + { + $this->path = $path; + } + + public function path(): string + { + return $this->path; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollection.php new file mode 100644 index 00000000..cb840892 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollection.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class DirectoryCollection implements Countable, IteratorAggregate +{ + /** + * @var Directory[] + */ + private $directories; + + /** + * @param Directory[] $directories + */ + public static function fromArray(array $directories): self + { + return new self(...$directories); + } + + private function __construct(Directory ...$directories) + { + $this->directories = $directories; + } + + /** + * @return Directory[] + */ + public function asArray(): array + { + return $this->directories; + } + + public function count(): int + { + return count($this->directories); + } + + public function getIterator(): DirectoryCollectionIterator + { + return new DirectoryCollectionIterator($this); + } + + public function isEmpty(): bool + { + return $this->count() === 0; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollectionIterator.php new file mode 100644 index 00000000..4b092744 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/DirectoryCollectionIterator.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class DirectoryCollectionIterator implements Countable, Iterator +{ + /** + * @var Directory[] + */ + private $directories; + + /** + * @var int + */ + private $position; + + public function __construct(DirectoryCollection $directories) + { + $this->directories = $directories->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->directories); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Directory + { + return $this->directories[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/File.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/File.php new file mode 100644 index 00000000..6bdd1c24 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/File.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class File +{ + /** + * @var string + */ + private $path; + + public function __construct(string $path) + { + $this->path = $path; + } + + public function path(): string + { + return $this->path; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollection.php new file mode 100644 index 00000000..60e7e401 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollection.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class FileCollection implements Countable, IteratorAggregate +{ + /** + * @var File[] + */ + private $files; + + /** + * @param File[] $files + */ + public static function fromArray(array $files): self + { + return new self(...$files); + } + + private function __construct(File ...$files) + { + $this->files = $files; + } + + /** + * @return File[] + */ + public function asArray(): array + { + return $this->files; + } + + public function count(): int + { + return count($this->files); + } + + public function getIterator(): FileCollectionIterator + { + return new FileCollectionIterator($this); + } + + public function isEmpty(): bool + { + return $this->count() === 0; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollectionIterator.php new file mode 100644 index 00000000..0ce4273d --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Filesystem/FileCollectionIterator.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class FileCollectionIterator implements Countable, Iterator +{ + /** + * @var File[] + */ + private $files; + + /** + * @var int + */ + private $position; + + public function __construct(FileCollection $files) + { + $this->files = $files->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->files); + } + + public function key(): int + { + return $this->position; + } + + public function current(): File + { + return $this->files[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Generator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Generator.php new file mode 100644 index 00000000..cc77b1a3 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Generator.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function str_replace; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Generator +{ + /** + * @var string + */ + private const TEMPLATE = <<<'EOT' + + + + + {tests_directory} + + + + + + {src_directory} + + + + +EOT; + + public function generateDefaultConfiguration(string $phpunitVersion, string $bootstrapScript, string $testsDirectory, string $srcDirectory, string $cacheDirectory): string + { + return str_replace( + [ + '{phpunit_version}', + '{bootstrap_script}', + '{tests_directory}', + '{src_directory}', + '{cache_directory}', + ], + [ + $phpunitVersion, + $bootstrapScript, + $testsDirectory, + $srcDirectory, + $cacheDirectory, + ], + self::TEMPLATE + ); + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Group.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Group.php new file mode 100644 index 00000000..bb0d9252 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Group.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Group +{ + /** + * @var string + */ + private $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function name(): string + { + return $this->name; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollection.php new file mode 100644 index 00000000..735d8af1 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollection.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use IteratorAggregate; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class GroupCollection implements IteratorAggregate +{ + /** + * @var Group[] + */ + private $groups; + + /** + * @param Group[] $groups + */ + public static function fromArray(array $groups): self + { + return new self(...$groups); + } + + private function __construct(Group ...$groups) + { + $this->groups = $groups; + } + + /** + * @return Group[] + */ + public function asArray(): array + { + return $this->groups; + } + + /** + * @return string[] + */ + public function asArrayOfStrings(): array + { + $result = []; + + foreach ($this->groups as $group) { + $result[] = $group->name(); + } + + return $result; + } + + public function isEmpty(): bool + { + return empty($this->groups); + } + + public function getIterator(): GroupCollectionIterator + { + return new GroupCollectionIterator($this); + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollectionIterator.php new file mode 100644 index 00000000..843a708e --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/GroupCollectionIterator.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class GroupCollectionIterator implements Countable, Iterator +{ + /** + * @var Group[] + */ + private $groups; + + /** + * @var int + */ + private $position; + + public function __construct(GroupCollection $groups) + { + $this->groups = $groups->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->groups); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Group + { + return $this->groups[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Groups.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Groups.php new file mode 100644 index 00000000..0604ce32 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Group/Groups.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Groups +{ + /** + * @var GroupCollection + */ + private $include; + + /** + * @var GroupCollection + */ + private $exclude; + + public function __construct(GroupCollection $include, GroupCollection $exclude) + { + $this->include = $include; + $this->exclude = $exclude; + } + + public function hasInclude(): bool + { + return !$this->include->isEmpty(); + } + + public function include(): GroupCollection + { + return $this->include; + } + + public function hasExclude(): bool + { + return !$this->exclude->isEmpty(); + } + + public function exclude(): GroupCollection + { + return $this->exclude; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Loader.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Loader.php new file mode 100644 index 00000000..c1877317 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Loader.php @@ -0,0 +1,1264 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use const DIRECTORY_SEPARATOR; +use const PHP_VERSION; +use function assert; +use function defined; +use function dirname; +use function explode; +use function is_file; +use function is_numeric; +use function preg_match; +use function stream_resolve_include_path; +use function strlen; +use function strpos; +use function strtolower; +use function substr; +use function trim; +use DOMDocument; +use DOMElement; +use DOMNodeList; +use DOMXPath; +use PHPUnit\Runner\TestSuiteSorter; +use PHPUnit\Runner\Version; +use PHPUnit\TextUI\DefaultResultPrinter; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\CodeCoverage; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Filter\Directory as FilterDirectory; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Filter\DirectoryCollection as FilterDirectoryCollection; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Clover; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Cobertura; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Crap4j; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Html as CodeCoverageHtml; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Php as CodeCoveragePhp; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Text as CodeCoverageText; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Xml as CodeCoverageXml; +use PHPUnit\TextUI\XmlConfiguration\Logging\Junit; +use PHPUnit\TextUI\XmlConfiguration\Logging\Logging; +use PHPUnit\TextUI\XmlConfiguration\Logging\TeamCity; +use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Html as TestDoxHtml; +use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Text as TestDoxText; +use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Xml as TestDoxXml; +use PHPUnit\TextUI\XmlConfiguration\Logging\Text; +use PHPUnit\TextUI\XmlConfiguration\TestSuite as TestSuiteConfiguration; +use PHPUnit\Util\TestDox\CliTestDoxPrinter; +use PHPUnit\Util\VersionComparisonOperator; +use PHPUnit\Util\Xml; +use PHPUnit\Util\Xml\Exception as XmlException; +use PHPUnit\Util\Xml\Loader as XmlLoader; +use PHPUnit\Util\Xml\SchemaFinder; +use PHPUnit\Util\Xml\Validator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Loader +{ + /** + * @throws Exception + */ + public function load(string $filename): Configuration + { + try { + $document = (new XmlLoader)->loadFile($filename, false, true, true); + } catch (XmlException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + + $xpath = new DOMXPath($document); + + try { + $xsdFilename = (new SchemaFinder)->find(Version::series()); + } catch (XmlException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + + return new Configuration( + $filename, + (new Validator)->validate($document, $xsdFilename), + $this->extensions($filename, $xpath), + $this->codeCoverage($filename, $xpath, $document), + $this->groups($xpath), + $this->testdoxGroups($xpath), + $this->listeners($filename, $xpath), + $this->logging($filename, $xpath), + $this->php($filename, $xpath), + $this->phpunit($filename, $document), + $this->testSuite($filename, $xpath) + ); + } + + public function logging(string $filename, DOMXPath $xpath): Logging + { + if ($xpath->query('logging/log')->length !== 0) { + return $this->legacyLogging($filename, $xpath); + } + + $junit = null; + $element = $this->element($xpath, 'logging/junit'); + + if ($element) { + $junit = new Junit( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile') + ) + ) + ); + } + + $text = null; + $element = $this->element($xpath, 'logging/text'); + + if ($element) { + $text = new Text( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile') + ) + ) + ); + } + + $teamCity = null; + $element = $this->element($xpath, 'logging/teamcity'); + + if ($element) { + $teamCity = new TeamCity( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile') + ) + ) + ); + } + + $testDoxHtml = null; + $element = $this->element($xpath, 'logging/testdoxHtml'); + + if ($element) { + $testDoxHtml = new TestDoxHtml( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile') + ) + ) + ); + } + + $testDoxText = null; + $element = $this->element($xpath, 'logging/testdoxText'); + + if ($element) { + $testDoxText = new TestDoxText( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile') + ) + ) + ); + } + + $testDoxXml = null; + $element = $this->element($xpath, 'logging/testdoxXml'); + + if ($element) { + $testDoxXml = new TestDoxXml( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile') + ) + ) + ); + } + + return new Logging( + $junit, + $text, + $teamCity, + $testDoxHtml, + $testDoxText, + $testDoxXml + ); + } + + public function legacyLogging(string $filename, DOMXPath $xpath): Logging + { + $junit = null; + $teamCity = null; + $testDoxHtml = null; + $testDoxText = null; + $testDoxXml = null; + $text = null; + + foreach ($xpath->query('logging/log') as $log) { + assert($log instanceof DOMElement); + + $type = (string) $log->getAttribute('type'); + $target = (string) $log->getAttribute('target'); + + if (!$target) { + continue; + } + + $target = $this->toAbsolutePath($filename, $target); + + switch ($type) { + case 'plain': + $text = new Text( + new File($target) + ); + + break; + + case 'junit': + $junit = new Junit( + new File($target) + ); + + break; + + case 'teamcity': + $teamCity = new TeamCity( + new File($target) + ); + + break; + + case 'testdox-html': + $testDoxHtml = new TestDoxHtml( + new File($target) + ); + + break; + + case 'testdox-text': + $testDoxText = new TestDoxText( + new File($target) + ); + + break; + + case 'testdox-xml': + $testDoxXml = new TestDoxXml( + new File($target) + ); + + break; + } + } + + return new Logging( + $junit, + $text, + $teamCity, + $testDoxHtml, + $testDoxText, + $testDoxXml + ); + } + + private function extensions(string $filename, DOMXPath $xpath): ExtensionCollection + { + $extensions = []; + + foreach ($xpath->query('extensions/extension') as $extension) { + assert($extension instanceof DOMElement); + + $extensions[] = $this->getElementConfigurationParameters($filename, $extension); + } + + return ExtensionCollection::fromArray($extensions); + } + + private function getElementConfigurationParameters(string $filename, DOMElement $element): Extension + { + /** @psalm-var class-string $class */ + $class = (string) $element->getAttribute('class'); + $file = ''; + $arguments = $this->getConfigurationArguments($filename, $element->childNodes); + + if ($element->getAttribute('file')) { + $file = $this->toAbsolutePath( + $filename, + (string) $element->getAttribute('file'), + true + ); + } + + return new Extension($class, $file, $arguments); + } + + private function toAbsolutePath(string $filename, string $path, bool $useIncludePath = false): string + { + $path = trim($path); + + if (strpos($path, '/') === 0) { + return $path; + } + + // Matches the following on Windows: + // - \\NetworkComputer\Path + // - \\.\D: + // - \\.\c: + // - C:\Windows + // - C:\windows + // - C:/windows + // - c:/windows + if (defined('PHP_WINDOWS_VERSION_BUILD') && + ($path[0] === '\\' || (strlen($path) >= 3 && preg_match('#^[A-Z]\:[/\\\]#i', substr($path, 0, 3))))) { + return $path; + } + + if (strpos($path, '://') !== false) { + return $path; + } + + $file = dirname($filename) . DIRECTORY_SEPARATOR . $path; + + if ($useIncludePath && !is_file($file)) { + $includePathFile = stream_resolve_include_path($path); + + if ($includePathFile) { + $file = $includePathFile; + } + } + + return $file; + } + + private function getConfigurationArguments(string $filename, DOMNodeList $nodes): array + { + $arguments = []; + + if ($nodes->length === 0) { + return $arguments; + } + + foreach ($nodes as $node) { + if (!$node instanceof DOMElement) { + continue; + } + + if ($node->tagName !== 'arguments') { + continue; + } + + foreach ($node->childNodes as $argument) { + if (!$argument instanceof DOMElement) { + continue; + } + + if ($argument->tagName === 'file' || $argument->tagName === 'directory') { + $arguments[] = $this->toAbsolutePath($filename, (string) $argument->textContent); + } else { + $arguments[] = Xml::xmlToVariable($argument); + } + } + } + + return $arguments; + } + + private function codeCoverage(string $filename, DOMXPath $xpath, DOMDocument $document): CodeCoverage + { + if ($xpath->query('filter/whitelist')->length !== 0) { + return $this->legacyCodeCoverage($filename, $xpath, $document); + } + + $cacheDirectory = null; + $pathCoverage = false; + $includeUncoveredFiles = true; + $processUncoveredFiles = false; + $ignoreDeprecatedCodeUnits = false; + $disableCodeCoverageIgnore = false; + + $element = $this->element($xpath, 'coverage'); + + if ($element) { + $cacheDirectory = $this->getStringAttribute($element, 'cacheDirectory'); + + if ($cacheDirectory !== null) { + $cacheDirectory = new Directory( + $this->toAbsolutePath($filename, $cacheDirectory) + ); + } + + $pathCoverage = $this->getBooleanAttribute( + $element, + 'pathCoverage', + false + ); + + $includeUncoveredFiles = $this->getBooleanAttribute( + $element, + 'includeUncoveredFiles', + true + ); + + $processUncoveredFiles = $this->getBooleanAttribute( + $element, + 'processUncoveredFiles', + false + ); + + $ignoreDeprecatedCodeUnits = $this->getBooleanAttribute( + $element, + 'ignoreDeprecatedCodeUnits', + false + ); + + $disableCodeCoverageIgnore = $this->getBooleanAttribute( + $element, + 'disableCodeCoverageIgnore', + false + ); + } + + $clover = null; + $element = $this->element($xpath, 'coverage/report/clover'); + + if ($element) { + $clover = new Clover( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile') + ) + ) + ); + } + + $cobertura = null; + $element = $this->element($xpath, 'coverage/report/cobertura'); + + if ($element) { + $cobertura = new Cobertura( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile') + ) + ) + ); + } + + $crap4j = null; + $element = $this->element($xpath, 'coverage/report/crap4j'); + + if ($element) { + $crap4j = new Crap4j( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile') + ) + ), + $this->getIntegerAttribute($element, 'threshold', 30) + ); + } + + $html = null; + $element = $this->element($xpath, 'coverage/report/html'); + + if ($element) { + $html = new CodeCoverageHtml( + new Directory( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputDirectory') + ) + ), + $this->getIntegerAttribute($element, 'lowUpperBound', 50), + $this->getIntegerAttribute($element, 'highLowerBound', 90) + ); + } + + $php = null; + $element = $this->element($xpath, 'coverage/report/php'); + + if ($element) { + $php = new CodeCoveragePhp( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile') + ) + ) + ); + } + + $text = null; + $element = $this->element($xpath, 'coverage/report/text'); + + if ($element) { + $text = new CodeCoverageText( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile') + ) + ), + $this->getBooleanAttribute($element, 'showUncoveredFiles', false), + $this->getBooleanAttribute($element, 'showOnlySummary', false) + ); + } + + $xml = null; + $element = $this->element($xpath, 'coverage/report/xml'); + + if ($element) { + $xml = new CodeCoverageXml( + new Directory( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputDirectory') + ) + ) + ); + } + + return new CodeCoverage( + $cacheDirectory, + $this->readFilterDirectories($filename, $xpath, 'coverage/include/directory'), + $this->readFilterFiles($filename, $xpath, 'coverage/include/file'), + $this->readFilterDirectories($filename, $xpath, 'coverage/exclude/directory'), + $this->readFilterFiles($filename, $xpath, 'coverage/exclude/file'), + $pathCoverage, + $includeUncoveredFiles, + $processUncoveredFiles, + $ignoreDeprecatedCodeUnits, + $disableCodeCoverageIgnore, + $clover, + $cobertura, + $crap4j, + $html, + $php, + $text, + $xml + ); + } + + /** + * @deprecated + */ + private function legacyCodeCoverage(string $filename, DOMXPath $xpath, DOMDocument $document): CodeCoverage + { + $ignoreDeprecatedCodeUnits = $this->getBooleanAttribute( + $document->documentElement, + 'ignoreDeprecatedCodeUnitsFromCodeCoverage', + false + ); + + $disableCodeCoverageIgnore = $this->getBooleanAttribute( + $document->documentElement, + 'disableCodeCoverageIgnore', + false + ); + + $includeUncoveredFiles = true; + $processUncoveredFiles = false; + + $element = $this->element($xpath, 'filter/whitelist'); + + if ($element) { + if ($element->hasAttribute('addUncoveredFilesFromWhitelist')) { + $includeUncoveredFiles = (bool) $this->getBoolean( + (string) $element->getAttribute('addUncoveredFilesFromWhitelist'), + true + ); + } + + if ($element->hasAttribute('processUncoveredFilesFromWhitelist')) { + $processUncoveredFiles = (bool) $this->getBoolean( + (string) $element->getAttribute('processUncoveredFilesFromWhitelist'), + false + ); + } + } + + $clover = null; + $cobertura = null; + $crap4j = null; + $html = null; + $php = null; + $text = null; + $xml = null; + + foreach ($xpath->query('logging/log') as $log) { + assert($log instanceof DOMElement); + + $type = (string) $log->getAttribute('type'); + $target = (string) $log->getAttribute('target'); + + if (!$target) { + continue; + } + + $target = $this->toAbsolutePath($filename, $target); + + switch ($type) { + case 'coverage-clover': + $clover = new Clover( + new File($target) + ); + + break; + + case 'coverage-cobertura': + $cobertura = new Cobertura( + new File($target) + ); + + break; + + case 'coverage-crap4j': + $crap4j = new Crap4j( + new File($target), + $this->getIntegerAttribute($log, 'threshold', 30) + ); + + break; + + case 'coverage-html': + $html = new CodeCoverageHtml( + new Directory($target), + $this->getIntegerAttribute($log, 'lowUpperBound', 50), + $this->getIntegerAttribute($log, 'highLowerBound', 90) + ); + + break; + + case 'coverage-php': + $php = new CodeCoveragePhp( + new File($target) + ); + + break; + + case 'coverage-text': + $text = new CodeCoverageText( + new File($target), + $this->getBooleanAttribute($log, 'showUncoveredFiles', false), + $this->getBooleanAttribute($log, 'showOnlySummary', false) + ); + + break; + + case 'coverage-xml': + $xml = new CodeCoverageXml( + new Directory($target) + ); + + break; + } + } + + return new CodeCoverage( + null, + $this->readFilterDirectories($filename, $xpath, 'filter/whitelist/directory'), + $this->readFilterFiles($filename, $xpath, 'filter/whitelist/file'), + $this->readFilterDirectories($filename, $xpath, 'filter/whitelist/exclude/directory'), + $this->readFilterFiles($filename, $xpath, 'filter/whitelist/exclude/file'), + false, + $includeUncoveredFiles, + $processUncoveredFiles, + $ignoreDeprecatedCodeUnits, + $disableCodeCoverageIgnore, + $clover, + $cobertura, + $crap4j, + $html, + $php, + $text, + $xml + ); + } + + /** + * If $value is 'false' or 'true', this returns the value that $value represents. + * Otherwise, returns $default, which may be a string in rare cases. + * + * @see \PHPUnit\TextUI\XmlConfigurationTest::testPHPConfigurationIsReadCorrectly + * + * @param bool|string $default + * + * @return bool|string + */ + private function getBoolean(string $value, $default) + { + if (strtolower($value) === 'false') { + return false; + } + + if (strtolower($value) === 'true') { + return true; + } + + return $default; + } + + private function readFilterDirectories(string $filename, DOMXPath $xpath, string $query): FilterDirectoryCollection + { + $directories = []; + + foreach ($xpath->query($query) as $directoryNode) { + assert($directoryNode instanceof DOMElement); + + $directoryPath = (string) $directoryNode->textContent; + + if (!$directoryPath) { + continue; + } + + $directories[] = new FilterDirectory( + $this->toAbsolutePath($filename, $directoryPath), + $directoryNode->hasAttribute('prefix') ? (string) $directoryNode->getAttribute('prefix') : '', + $directoryNode->hasAttribute('suffix') ? (string) $directoryNode->getAttribute('suffix') : '.php', + $directoryNode->hasAttribute('group') ? (string) $directoryNode->getAttribute('group') : 'DEFAULT' + ); + } + + return FilterDirectoryCollection::fromArray($directories); + } + + private function readFilterFiles(string $filename, DOMXPath $xpath, string $query): FileCollection + { + $files = []; + + foreach ($xpath->query($query) as $file) { + $filePath = (string) $file->textContent; + + if ($filePath) { + $files[] = new File($this->toAbsolutePath($filename, $filePath)); + } + } + + return FileCollection::fromArray($files); + } + + private function groups(DOMXPath $xpath): Groups + { + return $this->parseGroupConfiguration($xpath, 'groups'); + } + + private function testdoxGroups(DOMXPath $xpath): Groups + { + return $this->parseGroupConfiguration($xpath, 'testdoxGroups'); + } + + private function parseGroupConfiguration(DOMXPath $xpath, string $root): Groups + { + $include = []; + $exclude = []; + + foreach ($xpath->query($root . '/include/group') as $group) { + $include[] = new Group((string) $group->textContent); + } + + foreach ($xpath->query($root . '/exclude/group') as $group) { + $exclude[] = new Group((string) $group->textContent); + } + + return new Groups( + GroupCollection::fromArray($include), + GroupCollection::fromArray($exclude) + ); + } + + private function listeners(string $filename, DOMXPath $xpath): ExtensionCollection + { + $listeners = []; + + foreach ($xpath->query('listeners/listener') as $listener) { + assert($listener instanceof DOMElement); + + $listeners[] = $this->getElementConfigurationParameters($filename, $listener); + } + + return ExtensionCollection::fromArray($listeners); + } + + private function getBooleanAttribute(DOMElement $element, string $attribute, bool $default): bool + { + if (!$element->hasAttribute($attribute)) { + return $default; + } + + return (bool) $this->getBoolean( + (string) $element->getAttribute($attribute), + false + ); + } + + private function getIntegerAttribute(DOMElement $element, string $attribute, int $default): int + { + if (!$element->hasAttribute($attribute)) { + return $default; + } + + return $this->getInteger( + (string) $element->getAttribute($attribute), + $default + ); + } + + private function getStringAttribute(DOMElement $element, string $attribute): ?string + { + if (!$element->hasAttribute($attribute)) { + return null; + } + + return (string) $element->getAttribute($attribute); + } + + private function getInteger(string $value, int $default): int + { + if (is_numeric($value)) { + return (int) $value; + } + + return $default; + } + + private function php(string $filename, DOMXPath $xpath): Php + { + $includePaths = []; + + foreach ($xpath->query('php/includePath') as $includePath) { + $path = (string) $includePath->textContent; + + if ($path) { + $includePaths[] = new Directory($this->toAbsolutePath($filename, $path)); + } + } + + $iniSettings = []; + + foreach ($xpath->query('php/ini') as $ini) { + assert($ini instanceof DOMElement); + + $iniSettings[] = new IniSetting( + (string) $ini->getAttribute('name'), + (string) $ini->getAttribute('value') + ); + } + + $constants = []; + + foreach ($xpath->query('php/const') as $const) { + assert($const instanceof DOMElement); + + $value = (string) $const->getAttribute('value'); + + $constants[] = new Constant( + (string) $const->getAttribute('name'), + $this->getBoolean($value, $value) + ); + } + + $variables = [ + 'var' => [], + 'env' => [], + 'post' => [], + 'get' => [], + 'cookie' => [], + 'server' => [], + 'files' => [], + 'request' => [], + ]; + + foreach (['var', 'env', 'post', 'get', 'cookie', 'server', 'files', 'request'] as $array) { + foreach ($xpath->query('php/' . $array) as $var) { + assert($var instanceof DOMElement); + + $name = (string) $var->getAttribute('name'); + $value = (string) $var->getAttribute('value'); + $force = false; + $verbatim = false; + + if ($var->hasAttribute('force')) { + $force = (bool) $this->getBoolean($var->getAttribute('force'), false); + } + + if ($var->hasAttribute('verbatim')) { + $verbatim = $this->getBoolean($var->getAttribute('verbatim'), false); + } + + if (!$verbatim) { + $value = $this->getBoolean($value, $value); + } + + $variables[$array][] = new Variable($name, $value, $force); + } + } + + return new Php( + DirectoryCollection::fromArray($includePaths), + IniSettingCollection::fromArray($iniSettings), + ConstantCollection::fromArray($constants), + VariableCollection::fromArray($variables['var']), + VariableCollection::fromArray($variables['env']), + VariableCollection::fromArray($variables['post']), + VariableCollection::fromArray($variables['get']), + VariableCollection::fromArray($variables['cookie']), + VariableCollection::fromArray($variables['server']), + VariableCollection::fromArray($variables['files']), + VariableCollection::fromArray($variables['request']), + ); + } + + private function phpunit(string $filename, DOMDocument $document): PHPUnit + { + $executionOrder = TestSuiteSorter::ORDER_DEFAULT; + $defectsFirst = false; + $resolveDependencies = $this->getBooleanAttribute($document->documentElement, 'resolveDependencies', true); + + if ($document->documentElement->hasAttribute('executionOrder')) { + foreach (explode(',', $document->documentElement->getAttribute('executionOrder')) as $order) { + switch ($order) { + case 'default': + $executionOrder = TestSuiteSorter::ORDER_DEFAULT; + $defectsFirst = false; + $resolveDependencies = true; + + break; + + case 'depends': + $resolveDependencies = true; + + break; + + case 'no-depends': + $resolveDependencies = false; + + break; + + case 'defects': + $defectsFirst = true; + + break; + + case 'duration': + $executionOrder = TestSuiteSorter::ORDER_DURATION; + + break; + + case 'random': + $executionOrder = TestSuiteSorter::ORDER_RANDOMIZED; + + break; + + case 'reverse': + $executionOrder = TestSuiteSorter::ORDER_REVERSED; + + break; + + case 'size': + $executionOrder = TestSuiteSorter::ORDER_SIZE; + + break; + } + } + } + + $printerClass = $this->getStringAttribute($document->documentElement, 'printerClass'); + $testdox = $this->getBooleanAttribute($document->documentElement, 'testdox', false); + $conflictBetweenPrinterClassAndTestdox = false; + + if ($testdox) { + if ($printerClass !== null) { + $conflictBetweenPrinterClassAndTestdox = true; + } + + $printerClass = CliTestDoxPrinter::class; + } + + $cacheResultFile = $this->getStringAttribute($document->documentElement, 'cacheResultFile'); + + if ($cacheResultFile !== null) { + $cacheResultFile = $this->toAbsolutePath($filename, $cacheResultFile); + } + + $bootstrap = $this->getStringAttribute($document->documentElement, 'bootstrap'); + + if ($bootstrap !== null) { + $bootstrap = $this->toAbsolutePath($filename, $bootstrap); + } + + $extensionsDirectory = $this->getStringAttribute($document->documentElement, 'extensionsDirectory'); + + if ($extensionsDirectory !== null) { + $extensionsDirectory = $this->toAbsolutePath($filename, $extensionsDirectory); + } + + $testSuiteLoaderFile = $this->getStringAttribute($document->documentElement, 'testSuiteLoaderFile'); + + if ($testSuiteLoaderFile !== null) { + $testSuiteLoaderFile = $this->toAbsolutePath($filename, $testSuiteLoaderFile); + } + + $printerFile = $this->getStringAttribute($document->documentElement, 'printerFile'); + + if ($printerFile !== null) { + $printerFile = $this->toAbsolutePath($filename, $printerFile); + } + + return new PHPUnit( + $this->getBooleanAttribute($document->documentElement, 'cacheResult', true), + $cacheResultFile, + $this->getColumns($document), + $this->getColors($document), + $this->getBooleanAttribute($document->documentElement, 'stderr', false), + $this->getBooleanAttribute($document->documentElement, 'noInteraction', false), + $this->getBooleanAttribute($document->documentElement, 'verbose', false), + $this->getBooleanAttribute($document->documentElement, 'reverseDefectList', false), + $this->getBooleanAttribute($document->documentElement, 'convertDeprecationsToExceptions', false), + $this->getBooleanAttribute($document->documentElement, 'convertErrorsToExceptions', true), + $this->getBooleanAttribute($document->documentElement, 'convertNoticesToExceptions', true), + $this->getBooleanAttribute($document->documentElement, 'convertWarningsToExceptions', true), + $this->getBooleanAttribute($document->documentElement, 'forceCoversAnnotation', false), + $bootstrap, + $this->getBooleanAttribute($document->documentElement, 'processIsolation', false), + $this->getBooleanAttribute($document->documentElement, 'failOnEmptyTestSuite', false), + $this->getBooleanAttribute($document->documentElement, 'failOnIncomplete', false), + $this->getBooleanAttribute($document->documentElement, 'failOnRisky', false), + $this->getBooleanAttribute($document->documentElement, 'failOnSkipped', false), + $this->getBooleanAttribute($document->documentElement, 'failOnWarning', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnDefect', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnError', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnFailure', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnWarning', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnIncomplete', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnRisky', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnSkipped', false), + $extensionsDirectory, + $this->getStringAttribute($document->documentElement, 'testSuiteLoaderClass'), + $testSuiteLoaderFile, + $printerClass, + $printerFile, + $this->getBooleanAttribute($document->documentElement, 'beStrictAboutChangesToGlobalState', false), + $this->getBooleanAttribute($document->documentElement, 'beStrictAboutOutputDuringTests', false), + $this->getBooleanAttribute($document->documentElement, 'beStrictAboutResourceUsageDuringSmallTests', false), + $this->getBooleanAttribute($document->documentElement, 'beStrictAboutTestsThatDoNotTestAnything', true), + $this->getBooleanAttribute($document->documentElement, 'beStrictAboutTodoAnnotatedTests', false), + $this->getBooleanAttribute($document->documentElement, 'beStrictAboutCoversAnnotation', false), + $this->getBooleanAttribute($document->documentElement, 'enforceTimeLimit', false), + $this->getIntegerAttribute($document->documentElement, 'defaultTimeLimit', 1), + $this->getIntegerAttribute($document->documentElement, 'timeoutForSmallTests', 1), + $this->getIntegerAttribute($document->documentElement, 'timeoutForMediumTests', 10), + $this->getIntegerAttribute($document->documentElement, 'timeoutForLargeTests', 60), + $this->getStringAttribute($document->documentElement, 'defaultTestSuite'), + $executionOrder, + $resolveDependencies, + $defectsFirst, + $this->getBooleanAttribute($document->documentElement, 'backupGlobals', false), + $this->getBooleanAttribute($document->documentElement, 'backupStaticAttributes', false), + $this->getBooleanAttribute($document->documentElement, 'registerMockObjectsFromTestArgumentsRecursively', false), + $conflictBetweenPrinterClassAndTestdox + ); + } + + private function getColors(DOMDocument $document): string + { + $colors = DefaultResultPrinter::COLOR_DEFAULT; + + if ($document->documentElement->hasAttribute('colors')) { + /* only allow boolean for compatibility with previous versions + 'always' only allowed from command line */ + if ($this->getBoolean($document->documentElement->getAttribute('colors'), false)) { + $colors = DefaultResultPrinter::COLOR_AUTO; + } else { + $colors = DefaultResultPrinter::COLOR_NEVER; + } + } + + return $colors; + } + + /** + * @return int|string + */ + private function getColumns(DOMDocument $document) + { + $columns = 80; + + if ($document->documentElement->hasAttribute('columns')) { + $columns = (string) $document->documentElement->getAttribute('columns'); + + if ($columns !== 'max') { + $columns = $this->getInteger($columns, 80); + } + } + + return $columns; + } + + private function testSuite(string $filename, DOMXPath $xpath): TestSuiteCollection + { + $testSuites = []; + + foreach ($this->getTestSuiteElements($xpath) as $element) { + $exclude = []; + + foreach ($element->getElementsByTagName('exclude') as $excludeNode) { + $excludeFile = (string) $excludeNode->textContent; + + if ($excludeFile) { + $exclude[] = new File($this->toAbsolutePath($filename, $excludeFile)); + } + } + + $directories = []; + + foreach ($element->getElementsByTagName('directory') as $directoryNode) { + assert($directoryNode instanceof DOMElement); + + $directory = (string) $directoryNode->textContent; + + if (empty($directory)) { + continue; + } + + $prefix = ''; + + if ($directoryNode->hasAttribute('prefix')) { + $prefix = (string) $directoryNode->getAttribute('prefix'); + } + + $suffix = 'Test.php'; + + if ($directoryNode->hasAttribute('suffix')) { + $suffix = (string) $directoryNode->getAttribute('suffix'); + } + + $phpVersion = PHP_VERSION; + + if ($directoryNode->hasAttribute('phpVersion')) { + $phpVersion = (string) $directoryNode->getAttribute('phpVersion'); + } + + $phpVersionOperator = new VersionComparisonOperator('>='); + + if ($directoryNode->hasAttribute('phpVersionOperator')) { + $phpVersionOperator = new VersionComparisonOperator((string) $directoryNode->getAttribute('phpVersionOperator')); + } + + $directories[] = new TestDirectory( + $this->toAbsolutePath($filename, $directory), + $prefix, + $suffix, + $phpVersion, + $phpVersionOperator + ); + } + + $files = []; + + foreach ($element->getElementsByTagName('file') as $fileNode) { + assert($fileNode instanceof DOMElement); + + $file = (string) $fileNode->textContent; + + if (empty($file)) { + continue; + } + + $phpVersion = PHP_VERSION; + + if ($fileNode->hasAttribute('phpVersion')) { + $phpVersion = (string) $fileNode->getAttribute('phpVersion'); + } + + $phpVersionOperator = new VersionComparisonOperator('>='); + + if ($fileNode->hasAttribute('phpVersionOperator')) { + $phpVersionOperator = new VersionComparisonOperator((string) $fileNode->getAttribute('phpVersionOperator')); + } + + $files[] = new TestFile( + $this->toAbsolutePath($filename, $file), + $phpVersion, + $phpVersionOperator + ); + } + + $testSuites[] = new TestSuiteConfiguration( + (string) $element->getAttribute('name'), + TestDirectoryCollection::fromArray($directories), + TestFileCollection::fromArray($files), + FileCollection::fromArray($exclude) + ); + } + + return TestSuiteCollection::fromArray($testSuites); + } + + /** + * @return DOMElement[] + */ + private function getTestSuiteElements(DOMXPath $xpath): array + { + /** @var DOMElement[] $elements */ + $elements = []; + + $testSuiteNodes = $xpath->query('testsuites/testsuite'); + + if ($testSuiteNodes->length === 0) { + $testSuiteNodes = $xpath->query('testsuite'); + } + + if ($testSuiteNodes->length === 1) { + $element = $testSuiteNodes->item(0); + + assert($element instanceof DOMElement); + + $elements[] = $element; + } else { + foreach ($testSuiteNodes as $testSuiteNode) { + assert($testSuiteNode instanceof DOMElement); + + $elements[] = $testSuiteNode; + } + } + + return $elements; + } + + private function element(DOMXPath $xpath, string $element): ?DOMElement + { + $nodes = $xpath->query($element); + + if ($nodes->length === 1) { + $node = $nodes->item(0); + + assert($node instanceof DOMElement); + + return $node; + } + + return null; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Junit.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Junit.php new file mode 100644 index 00000000..9fca1852 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Junit.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\Logging; + +use PHPUnit\TextUI\XmlConfiguration\File; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Junit +{ + /** + * @var File + */ + private $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Logging.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Logging.php new file mode 100644 index 00000000..bce03019 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Logging.php @@ -0,0 +1,147 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\Logging; + +use PHPUnit\TextUI\XmlConfiguration\Exception; +use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Html as TestDoxHtml; +use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Text as TestDoxText; +use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Xml as TestDoxXml; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Logging +{ + /** + * @var ?Junit + */ + private $junit; + + /** + * @var ?Text + */ + private $text; + + /** + * @var ?TeamCity + */ + private $teamCity; + + /** + * @var ?TestDoxHtml + */ + private $testDoxHtml; + + /** + * @var ?TestDoxText + */ + private $testDoxText; + + /** + * @var ?TestDoxXml + */ + private $testDoxXml; + + public function __construct(?Junit $junit, ?Text $text, ?TeamCity $teamCity, ?TestDoxHtml $testDoxHtml, ?TestDoxText $testDoxText, ?TestDoxXml $testDoxXml) + { + $this->junit = $junit; + $this->text = $text; + $this->teamCity = $teamCity; + $this->testDoxHtml = $testDoxHtml; + $this->testDoxText = $testDoxText; + $this->testDoxXml = $testDoxXml; + } + + public function hasJunit(): bool + { + return $this->junit !== null; + } + + public function junit(): Junit + { + if ($this->junit === null) { + throw new Exception('Logger "JUnit XML" is not configured'); + } + + return $this->junit; + } + + public function hasText(): bool + { + return $this->text !== null; + } + + public function text(): Text + { + if ($this->text === null) { + throw new Exception('Logger "Text" is not configured'); + } + + return $this->text; + } + + public function hasTeamCity(): bool + { + return $this->teamCity !== null; + } + + public function teamCity(): TeamCity + { + if ($this->teamCity === null) { + throw new Exception('Logger "Team City" is not configured'); + } + + return $this->teamCity; + } + + public function hasTestDoxHtml(): bool + { + return $this->testDoxHtml !== null; + } + + public function testDoxHtml(): TestDoxHtml + { + if ($this->testDoxHtml === null) { + throw new Exception('Logger "TestDox HTML" is not configured'); + } + + return $this->testDoxHtml; + } + + public function hasTestDoxText(): bool + { + return $this->testDoxText !== null; + } + + public function testDoxText(): TestDoxText + { + if ($this->testDoxText === null) { + throw new Exception('Logger "TestDox Text" is not configured'); + } + + return $this->testDoxText; + } + + public function hasTestDoxXml(): bool + { + return $this->testDoxXml !== null; + } + + public function testDoxXml(): TestDoxXml + { + if ($this->testDoxXml === null) { + throw new Exception('Logger "TestDox XML" is not configured'); + } + + return $this->testDoxXml; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TeamCity.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TeamCity.php new file mode 100644 index 00000000..804a7ea6 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TeamCity.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\Logging; + +use PHPUnit\TextUI\XmlConfiguration\File; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class TeamCity +{ + /** + * @var File + */ + private $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Html.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Html.php new file mode 100644 index 00000000..5b198352 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Html.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\Logging\TestDox; + +use PHPUnit\TextUI\XmlConfiguration\File; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Html +{ + /** + * @var File + */ + private $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Text.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Text.php new file mode 100644 index 00000000..5c742d3a --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Text.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\Logging\TestDox; + +use PHPUnit\TextUI\XmlConfiguration\File; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Text +{ + /** + * @var File + */ + private $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Xml.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Xml.php new file mode 100644 index 00000000..92dd3b7b --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/TestDox/Xml.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\Logging\TestDox; + +use PHPUnit\TextUI\XmlConfiguration\File; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Xml +{ + /** + * @var File + */ + private $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Text.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Text.php new file mode 100644 index 00000000..fd37942f --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Logging/Text.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\Logging; + +use PHPUnit\TextUI\XmlConfiguration\File; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Text +{ + /** + * @var File + */ + private $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilder.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilder.php new file mode 100644 index 00000000..abef49f1 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilder.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function array_key_exists; +use function sprintf; +use function version_compare; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MigrationBuilder +{ + private const AVAILABLE_MIGRATIONS = [ + '8.5' => [ + RemoveLogTypes::class, + ], + + '9.2' => [ + RemoveCacheTokensAttribute::class, + IntroduceCoverageElement::class, + MoveAttributesFromRootToCoverage::class, + MoveAttributesFromFilterWhitelistToCoverage::class, + MoveWhitelistDirectoriesToCoverage::class, + MoveWhitelistExcludesToCoverage::class, + RemoveEmptyFilter::class, + CoverageCloverToReport::class, + CoverageCrap4jToReport::class, + CoverageHtmlToReport::class, + CoveragePhpToReport::class, + CoverageTextToReport::class, + CoverageXmlToReport::class, + ConvertLogTypes::class, + UpdateSchemaLocationTo93::class, + ], + ]; + + /** + * @throws MigrationBuilderException + */ + public function build(string $fromVersion): array + { + if (!array_key_exists($fromVersion, self::AVAILABLE_MIGRATIONS)) { + throw new MigrationBuilderException( + sprintf( + 'Migration from schema version %s is not supported', + $fromVersion + ) + ); + } + + $stack = []; + + foreach (self::AVAILABLE_MIGRATIONS as $version => $migrations) { + if (version_compare($version, $fromVersion, '<')) { + continue; + } + + foreach ($migrations as $migration) { + $stack[] = new $migration; + } + } + + return $stack; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilderException.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilderException.php new file mode 100644 index 00000000..3d3c767a --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationBuilderException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use RuntimeException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MigrationBuilderException extends RuntimeException implements \PHPUnit\Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationException.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationException.php new file mode 100644 index 00000000..f92b2db3 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/MigrationException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use RuntimeException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MigrationException extends RuntimeException implements \PHPUnit\Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/ConvertLogTypes.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/ConvertLogTypes.php new file mode 100644 index 00000000..697bbe08 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/ConvertLogTypes.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ConvertLogTypes implements Migration +{ + public function migrate(DOMDocument $document): void + { + $logging = $document->getElementsByTagName('logging')->item(0); + + if (!$logging instanceof DOMElement) { + return; + } + $types = [ + 'junit' => 'junit', + 'teamcity' => 'teamcity', + 'testdox-html' => 'testdoxHtml', + 'testdox-text' => 'testdoxText', + 'testdox-xml' => 'testdoxXml', + 'plain' => 'text', + ]; + + $logNodes = []; + + foreach ($logging->getElementsByTagName('log') as $logNode) { + if (!isset($types[$logNode->getAttribute('type')])) { + continue; + } + + $logNodes[] = $logNode; + } + + foreach ($logNodes as $oldNode) { + $newLogNode = $document->createElement($types[$oldNode->getAttribute('type')]); + $newLogNode->setAttribute('outputFile', $oldNode->getAttribute('target')); + + $logging->replaceChild($newLogNode, $oldNode); + } + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCloverToReport.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCloverToReport.php new file mode 100644 index 00000000..5f1522b9 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCloverToReport.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CoverageCloverToReport extends LogToReportMigration +{ + protected function forType(): string + { + return 'coverage-clover'; + } + + protected function toReportFormat(DOMElement $logNode): DOMElement + { + $clover = $logNode->ownerDocument->createElement('clover'); + $clover->setAttribute('outputFile', $logNode->getAttribute('target')); + + return $clover; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCrap4jToReport.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCrap4jToReport.php new file mode 100644 index 00000000..afbaaec1 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageCrap4jToReport.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CoverageCrap4jToReport extends LogToReportMigration +{ + protected function forType(): string + { + return 'coverage-crap4j'; + } + + protected function toReportFormat(DOMElement $logNode): DOMElement + { + $crap4j = $logNode->ownerDocument->createElement('crap4j'); + $crap4j->setAttribute('outputFile', $logNode->getAttribute('target')); + + $this->migrateAttributes($logNode, $crap4j, ['threshold']); + + return $crap4j; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageHtmlToReport.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageHtmlToReport.php new file mode 100644 index 00000000..7e12095b --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageHtmlToReport.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CoverageHtmlToReport extends LogToReportMigration +{ + protected function forType(): string + { + return 'coverage-html'; + } + + protected function toReportFormat(DOMElement $logNode): DOMElement + { + $html = $logNode->ownerDocument->createElement('html'); + $html->setAttribute('outputDirectory', $logNode->getAttribute('target')); + + $this->migrateAttributes($logNode, $html, ['lowUpperBound', 'highLowerBound']); + + return $html; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoveragePhpToReport.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoveragePhpToReport.php new file mode 100644 index 00000000..bfa10030 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoveragePhpToReport.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CoveragePhpToReport extends LogToReportMigration +{ + protected function forType(): string + { + return 'coverage-php'; + } + + protected function toReportFormat(DOMElement $logNode): DOMElement + { + $php = $logNode->ownerDocument->createElement('php'); + $php->setAttribute('outputFile', $logNode->getAttribute('target')); + + return $php; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageTextToReport.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageTextToReport.php new file mode 100644 index 00000000..063d8df0 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageTextToReport.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CoverageTextToReport extends LogToReportMigration +{ + protected function forType(): string + { + return 'coverage-text'; + } + + protected function toReportFormat(DOMElement $logNode): DOMElement + { + $text = $logNode->ownerDocument->createElement('text'); + $text->setAttribute('outputFile', $logNode->getAttribute('target')); + + $this->migrateAttributes($logNode, $text, ['showUncoveredFiles', 'showOnlySummary']); + + return $text; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageXmlToReport.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageXmlToReport.php new file mode 100644 index 00000000..480d7777 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/CoverageXmlToReport.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CoverageXmlToReport extends LogToReportMigration +{ + protected function forType(): string + { + return 'coverage-xml'; + } + + protected function toReportFormat(DOMElement $logNode): DOMElement + { + $xml = $logNode->ownerDocument->createElement('xml'); + $xml->setAttribute('outputDirectory', $logNode->getAttribute('target')); + + return $xml; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/IntroduceCoverageElement.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/IntroduceCoverageElement.php new file mode 100644 index 00000000..867a8441 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/IntroduceCoverageElement.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class IntroduceCoverageElement implements Migration +{ + public function migrate(DOMDocument $document): void + { + $coverage = $document->createElement('coverage'); + + $document->documentElement->insertBefore( + $coverage, + $document->documentElement->firstChild + ); + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/LogToReportMigration.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/LogToReportMigration.php new file mode 100644 index 00000000..e987308b --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/LogToReportMigration.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function sprintf; +use DOMDocument; +use DOMElement; +use DOMXPath; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class LogToReportMigration implements Migration +{ + /** + * @throws MigrationException + */ + public function migrate(DOMDocument $document): void + { + $coverage = $document->getElementsByTagName('coverage')->item(0); + + if (!$coverage instanceof DOMElement) { + throw new MigrationException('Unexpected state - No coverage element'); + } + + $logNode = $this->findLogNode($document); + + if ($logNode === null) { + return; + } + + $reportChild = $this->toReportFormat($logNode); + + $report = $coverage->getElementsByTagName('report')->item(0); + + if ($report === null) { + $report = $coverage->appendChild($document->createElement('report')); + } + + $report->appendChild($reportChild); + $logNode->parentNode->removeChild($logNode); + } + + protected function migrateAttributes(DOMElement $src, DOMElement $dest, array $attributes): void + { + foreach ($attributes as $attr) { + if (!$src->hasAttribute($attr)) { + continue; + } + + $dest->setAttribute($attr, $src->getAttribute($attr)); + $src->removeAttribute($attr); + } + } + + abstract protected function forType(): string; + + abstract protected function toReportFormat(DOMElement $logNode): DOMElement; + + private function findLogNode(DOMDocument $document): ?DOMElement + { + $logNode = (new DOMXPath($document))->query( + sprintf('//logging/log[@type="%s"]', $this->forType()) + )->item(0); + + if (!$logNode instanceof DOMElement) { + return null; + } + + return $logNode; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/Migration.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/Migration.php new file mode 100644 index 00000000..fa4092a9 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/Migration.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Migration +{ + public function migrate(DOMDocument $document): void; +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php new file mode 100644 index 00000000..a7aab5e5 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MoveAttributesFromFilterWhitelistToCoverage implements Migration +{ + /** + * @throws MigrationException + */ + public function migrate(DOMDocument $document): void + { + $whitelist = $document->getElementsByTagName('whitelist')->item(0); + + if (!$whitelist) { + return; + } + + $coverage = $document->getElementsByTagName('coverage')->item(0); + + if (!$coverage instanceof DOMElement) { + throw new MigrationException('Unexpected state - No coverage element'); + } + + $map = [ + 'addUncoveredFilesFromWhitelist' => 'includeUncoveredFiles', + 'processUncoveredFilesFromWhitelist' => 'processUncoveredFiles', + ]; + + foreach ($map as $old => $new) { + if (!$whitelist->hasAttribute($old)) { + continue; + } + + $coverage->setAttribute($new, $whitelist->getAttribute($old)); + $whitelist->removeAttribute($old); + } + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromRootToCoverage.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromRootToCoverage.php new file mode 100644 index 00000000..b86b259c --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveAttributesFromRootToCoverage.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MoveAttributesFromRootToCoverage implements Migration +{ + /** + * @throws MigrationException + */ + public function migrate(DOMDocument $document): void + { + $map = [ + 'disableCodeCoverageIgnore' => 'disableCodeCoverageIgnore', + 'ignoreDeprecatedCodeUnitsFromCodeCoverage' => 'ignoreDeprecatedCodeUnits', + ]; + + $root = $document->documentElement; + + $coverage = $document->getElementsByTagName('coverage')->item(0); + + if (!$coverage instanceof DOMElement) { + throw new MigrationException('Unexpected state - No coverage element'); + } + + foreach ($map as $old => $new) { + if (!$root->hasAttribute($old)) { + continue; + } + + $coverage->setAttribute($new, $root->getAttribute($old)); + $root->removeAttribute($old); + } + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistDirectoriesToCoverage.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistDirectoriesToCoverage.php new file mode 100644 index 00000000..14e6cec8 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistDirectoriesToCoverage.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; +use DOMElement; +use PHPUnit\Util\Xml\SnapshotNodeList; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MoveWhitelistDirectoriesToCoverage implements Migration +{ + /** + * @throws MigrationException + */ + public function migrate(DOMDocument $document): void + { + $whitelist = $document->getElementsByTagName('whitelist')->item(0); + + if ($whitelist === null) { + return; + } + + $coverage = $document->getElementsByTagName('coverage')->item(0); + + if (!$coverage instanceof DOMElement) { + throw new MigrationException('Unexpected state - No coverage element'); + } + + $include = $document->createElement('include'); + $coverage->appendChild($include); + + foreach (SnapshotNodeList::fromNodeList($whitelist->childNodes) as $child) { + if (!$child instanceof DOMElement || $child->nodeName !== 'directory') { + continue; + } + + $include->appendChild($child); + } + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistExcludesToCoverage.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistExcludesToCoverage.php new file mode 100644 index 00000000..c55315fa --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/MoveWhitelistExcludesToCoverage.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use function in_array; +use DOMDocument; +use DOMElement; +use PHPUnit\Util\Xml\SnapshotNodeList; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MoveWhitelistExcludesToCoverage implements Migration +{ + /** + * @throws MigrationException + */ + public function migrate(DOMDocument $document): void + { + $whitelist = $document->getElementsByTagName('whitelist')->item(0); + + if ($whitelist === null) { + return; + } + + $excludeNodes = SnapshotNodeList::fromNodeList($whitelist->getElementsByTagName('exclude')); + + if ($excludeNodes->count() === 0) { + return; + } + + $coverage = $document->getElementsByTagName('coverage')->item(0); + + if (!$coverage instanceof DOMElement) { + throw new MigrationException('Unexpected state - No coverage element'); + } + + $targetExclude = $coverage->getElementsByTagName('exclude')->item(0); + + if ($targetExclude === null) { + $targetExclude = $coverage->appendChild( + $document->createElement('exclude') + ); + } + + foreach ($excludeNodes as $excludeNode) { + assert($excludeNode instanceof DOMElement); + + foreach (SnapshotNodeList::fromNodeList($excludeNode->childNodes) as $child) { + if (!$child instanceof DOMElement || !in_array($child->nodeName, ['directory', 'file'], true)) { + continue; + } + + $targetExclude->appendChild($child); + } + + if ($excludeNode->getElementsByTagName('*')->count() !== 0) { + throw new MigrationException('Dangling child elements in exclude found.'); + } + + $whitelist->removeChild($excludeNode); + } + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveCacheTokensAttribute.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveCacheTokensAttribute.php new file mode 100644 index 00000000..0eec12ac --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveCacheTokensAttribute.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveCacheTokensAttribute implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + if ($root->hasAttribute('cacheTokens')) { + $root->removeAttribute('cacheTokens'); + } + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveEmptyFilter.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveEmptyFilter.php new file mode 100644 index 00000000..8f1a6d54 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveEmptyFilter.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function sprintf; +use DOMDocument; +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveEmptyFilter implements Migration +{ + /** + * @throws MigrationException + */ + public function migrate(DOMDocument $document): void + { + $whitelist = $document->getElementsByTagName('whitelist')->item(0); + + if ($whitelist instanceof DOMElement) { + $this->ensureEmpty($whitelist); + $whitelist->parentNode->removeChild($whitelist); + } + + $filter = $document->getElementsByTagName('filter')->item(0); + + if ($filter instanceof DOMElement) { + $this->ensureEmpty($filter); + $filter->parentNode->removeChild($filter); + } + } + + /** + * @throws MigrationException + */ + private function ensureEmpty(DOMElement $element): void + { + if ($element->attributes->length > 0) { + throw new MigrationException(sprintf('%s element has unexpected attributes', $element->nodeName)); + } + + if ($element->getElementsByTagName('*')->length > 0) { + throw new MigrationException(sprintf('%s element has unexpected children', $element->nodeName)); + } + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveLogTypes.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveLogTypes.php new file mode 100644 index 00000000..962ff13c --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/RemoveLogTypes.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; +use PHPUnit\Util\Xml\SnapshotNodeList; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveLogTypes implements Migration +{ + public function migrate(DOMDocument $document): void + { + $logging = $document->getElementsByTagName('logging')->item(0); + + if (!$logging instanceof DOMElement) { + return; + } + + foreach (SnapshotNodeList::fromNodeList($logging->getElementsByTagName('log')) as $logNode) { + assert($logNode instanceof DOMElement); + + switch ($logNode->getAttribute('type')) { + case 'json': + case 'tap': + $logging->removeChild($logNode); + } + } + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/UpdateSchemaLocationTo93.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/UpdateSchemaLocationTo93.php new file mode 100644 index 00000000..2e86ab6e --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrations/UpdateSchemaLocationTo93.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class UpdateSchemaLocationTo93 implements Migration +{ + public function migrate(DOMDocument $document): void + { + $document->documentElement->setAttributeNS( + 'http://www.w3.org/2001/XMLSchema-instance', + 'xsi:noNamespaceSchemaLocation', + 'https://schema.phpunit.de/9.3/phpunit.xsd' + ); + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrator.php new file mode 100644 index 00000000..d173e7af --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/Migration/Migrator.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function sprintf; +use PHPUnit\Util\Xml\Exception as XmlException; +use PHPUnit\Util\Xml\Loader as XmlLoader; +use PHPUnit\Util\Xml\SchemaDetector; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Migrator +{ + /** + * @throws Exception + * @throws MigrationBuilderException + * @throws MigrationException + * @throws XmlException + */ + public function migrate(string $filename): string + { + $origin = (new SchemaDetector)->detect($filename); + + if (!$origin->detected()) { + throw new Exception( + sprintf( + '"%s" is not a valid PHPUnit XML configuration file that can be migrated', + $filename, + ) + ); + } + + $configurationDocument = (new XmlLoader)->loadFile( + $filename, + false, + true, + true + ); + + foreach ((new MigrationBuilder)->build($origin->version()) as $migration) { + $migration->migrate($configurationDocument); + } + + $configurationDocument->formatOutput = true; + $configurationDocument->preserveWhiteSpace = false; + + return $configurationDocument->saveXML(); + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Constant.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Constant.php new file mode 100644 index 00000000..6d4bc94c --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Constant.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Constant +{ + /** + * @var string + */ + private $name; + + /** + * @var mixed + */ + private $value; + + public function __construct(string $name, $value) + { + $this->name = $name; + $this->value = $value; + } + + public function name(): string + { + return $this->name; + } + + public function value() + { + return $this->value; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollection.php new file mode 100644 index 00000000..440b0b0b --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollection.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class ConstantCollection implements Countable, IteratorAggregate +{ + /** + * @var Constant[] + */ + private $constants; + + /** + * @param Constant[] $constants + */ + public static function fromArray(array $constants): self + { + return new self(...$constants); + } + + private function __construct(Constant ...$constants) + { + $this->constants = $constants; + } + + /** + * @return Constant[] + */ + public function asArray(): array + { + return $this->constants; + } + + public function count(): int + { + return count($this->constants); + } + + public function getIterator(): ConstantCollectionIterator + { + return new ConstantCollectionIterator($this); + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollectionIterator.php new file mode 100644 index 00000000..623de961 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/ConstantCollectionIterator.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class ConstantCollectionIterator implements Countable, Iterator +{ + /** + * @var Constant[] + */ + private $constants; + + /** + * @var int + */ + private $position; + + public function __construct(ConstantCollection $constants) + { + $this->constants = $constants->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->constants); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Constant + { + return $this->constants[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSetting.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSetting.php new file mode 100644 index 00000000..4786618d --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSetting.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class IniSetting +{ + /** + * @var string + */ + private $name; + + /** + * @var string + */ + private $value; + + public function __construct(string $name, string $value) + { + $this->name = $name; + $this->value = $value; + } + + public function name(): string + { + return $this->name; + } + + public function value(): string + { + return $this->value; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollection.php new file mode 100644 index 00000000..28e40d93 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollection.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class IniSettingCollection implements Countable, IteratorAggregate +{ + /** + * @var IniSetting[] + */ + private $iniSettings; + + /** + * @param IniSetting[] $iniSettings + */ + public static function fromArray(array $iniSettings): self + { + return new self(...$iniSettings); + } + + private function __construct(IniSetting ...$iniSettings) + { + $this->iniSettings = $iniSettings; + } + + /** + * @return IniSetting[] + */ + public function asArray(): array + { + return $this->iniSettings; + } + + public function count(): int + { + return count($this->iniSettings); + } + + public function getIterator(): IniSettingCollectionIterator + { + return new IniSettingCollectionIterator($this); + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollectionIterator.php new file mode 100644 index 00000000..6c348b48 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/IniSettingCollectionIterator.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class IniSettingCollectionIterator implements Countable, Iterator +{ + /** + * @var IniSetting[] + */ + private $iniSettings; + + /** + * @var int + */ + private $position; + + public function __construct(IniSettingCollection $iniSettings) + { + $this->iniSettings = $iniSettings->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->iniSettings); + } + + public function key(): int + { + return $this->position; + } + + public function current(): IniSetting + { + return $this->iniSettings[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Php.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Php.php new file mode 100644 index 00000000..c1e9c6fd --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Php.php @@ -0,0 +1,143 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Php +{ + /** + * @var DirectoryCollection + */ + private $includePaths; + + /** + * @var IniSettingCollection + */ + private $iniSettings; + + /** + * @var ConstantCollection + */ + private $constants; + + /** + * @var VariableCollection + */ + private $globalVariables; + + /** + * @var VariableCollection + */ + private $envVariables; + + /** + * @var VariableCollection + */ + private $postVariables; + + /** + * @var VariableCollection + */ + private $getVariables; + + /** + * @var VariableCollection + */ + private $cookieVariables; + + /** + * @var VariableCollection + */ + private $serverVariables; + + /** + * @var VariableCollection + */ + private $filesVariables; + + /** + * @var VariableCollection + */ + private $requestVariables; + + public function __construct(DirectoryCollection $includePaths, IniSettingCollection $iniSettings, ConstantCollection $constants, VariableCollection $globalVariables, VariableCollection $envVariables, VariableCollection $postVariables, VariableCollection $getVariables, VariableCollection $cookieVariables, VariableCollection $serverVariables, VariableCollection $filesVariables, VariableCollection $requestVariables) + { + $this->includePaths = $includePaths; + $this->iniSettings = $iniSettings; + $this->constants = $constants; + $this->globalVariables = $globalVariables; + $this->envVariables = $envVariables; + $this->postVariables = $postVariables; + $this->getVariables = $getVariables; + $this->cookieVariables = $cookieVariables; + $this->serverVariables = $serverVariables; + $this->filesVariables = $filesVariables; + $this->requestVariables = $requestVariables; + } + + public function includePaths(): DirectoryCollection + { + return $this->includePaths; + } + + public function iniSettings(): IniSettingCollection + { + return $this->iniSettings; + } + + public function constants(): ConstantCollection + { + return $this->constants; + } + + public function globalVariables(): VariableCollection + { + return $this->globalVariables; + } + + public function envVariables(): VariableCollection + { + return $this->envVariables; + } + + public function postVariables(): VariableCollection + { + return $this->postVariables; + } + + public function getVariables(): VariableCollection + { + return $this->getVariables; + } + + public function cookieVariables(): VariableCollection + { + return $this->cookieVariables; + } + + public function serverVariables(): VariableCollection + { + return $this->serverVariables; + } + + public function filesVariables(): VariableCollection + { + return $this->filesVariables; + } + + public function requestVariables(): VariableCollection + { + return $this->requestVariables; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/PhpHandler.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/PhpHandler.php new file mode 100644 index 00000000..5fb0c72b --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/PhpHandler.php @@ -0,0 +1,121 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use const PATH_SEPARATOR; +use function constant; +use function define; +use function defined; +use function getenv; +use function implode; +use function ini_get; +use function ini_set; +use function putenv; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class PhpHandler +{ + public function handle(Php $configuration): void + { + $this->handleIncludePaths($configuration->includePaths()); + $this->handleIniSettings($configuration->iniSettings()); + $this->handleConstants($configuration->constants()); + $this->handleGlobalVariables($configuration->globalVariables()); + $this->handleServerVariables($configuration->serverVariables()); + $this->handleEnvVariables($configuration->envVariables()); + $this->handleVariables('_POST', $configuration->postVariables()); + $this->handleVariables('_GET', $configuration->getVariables()); + $this->handleVariables('_COOKIE', $configuration->cookieVariables()); + $this->handleVariables('_FILES', $configuration->filesVariables()); + $this->handleVariables('_REQUEST', $configuration->requestVariables()); + } + + private function handleIncludePaths(DirectoryCollection $includePaths): void + { + if (!$includePaths->isEmpty()) { + $includePathsAsStrings = []; + + foreach ($includePaths as $includePath) { + $includePathsAsStrings[] = $includePath->path(); + } + + ini_set( + 'include_path', + implode(PATH_SEPARATOR, $includePathsAsStrings) . + PATH_SEPARATOR . + ini_get('include_path') + ); + } + } + + private function handleIniSettings(IniSettingCollection $iniSettings): void + { + foreach ($iniSettings as $iniSetting) { + $value = $iniSetting->value(); + + if (defined($value)) { + $value = (string) constant($value); + } + + ini_set($iniSetting->name(), $value); + } + } + + private function handleConstants(ConstantCollection $constants): void + { + foreach ($constants as $constant) { + if (!defined($constant->name())) { + define($constant->name(), $constant->value()); + } + } + } + + private function handleGlobalVariables(VariableCollection $variables): void + { + foreach ($variables as $variable) { + $GLOBALS[$variable->name()] = $variable->value(); + } + } + + private function handleServerVariables(VariableCollection $variables): void + { + foreach ($variables as $variable) { + $_SERVER[$variable->name()] = $variable->value(); + } + } + + private function handleVariables(string $target, VariableCollection $variables): void + { + foreach ($variables as $variable) { + $GLOBALS[$target][$variable->name()] = $variable->value(); + } + } + + private function handleEnvVariables(VariableCollection $variables): void + { + foreach ($variables as $variable) { + $name = $variable->name(); + $value = $variable->value(); + $force = $variable->force(); + + if ($force || getenv($name) === false) { + putenv("{$name}={$value}"); + } + + $value = getenv($name); + + if ($force || !isset($_ENV[$name])) { + $_ENV[$name] = $value; + } + } + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Variable.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Variable.php new file mode 100644 index 00000000..37c572ae --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/Variable.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Variable +{ + /** + * @var string + */ + private $name; + + /** + * @var mixed + */ + private $value; + + /** + * @var bool + */ + private $force; + + public function __construct(string $name, $value, bool $force) + { + $this->name = $name; + $this->value = $value; + $this->force = $force; + } + + public function name(): string + { + return $this->name; + } + + public function value() + { + return $this->value; + } + + public function force(): bool + { + return $this->force; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollection.php new file mode 100644 index 00000000..6662db64 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollection.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class VariableCollection implements Countable, IteratorAggregate +{ + /** + * @var Variable[] + */ + private $variables; + + /** + * @param Variable[] $variables + */ + public static function fromArray(array $variables): self + { + return new self(...$variables); + } + + private function __construct(Variable ...$variables) + { + $this->variables = $variables; + } + + /** + * @return Variable[] + */ + public function asArray(): array + { + return $this->variables; + } + + public function count(): int + { + return count($this->variables); + } + + public function getIterator(): VariableCollectionIterator + { + return new VariableCollectionIterator($this); + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollectionIterator.php new file mode 100644 index 00000000..032d0be1 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHP/VariableCollectionIterator.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class VariableCollectionIterator implements Countable, Iterator +{ + /** + * @var Variable[] + */ + private $variables; + + /** + * @var int + */ + private $position; + + public function __construct(VariableCollection $variables) + { + $this->variables = $variables->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->variables); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Variable + { + return $this->variables[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/Extension.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/Extension.php new file mode 100644 index 00000000..09fe8cc9 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/Extension.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Extension +{ + /** + * @var string + * + * @psalm-var class-string + */ + private $className; + + /** + * @var string + */ + private $sourceFile; + + /** + * @var array + */ + private $arguments; + + /** + * @psalm-param class-string $className + */ + public function __construct(string $className, string $sourceFile, array $arguments) + { + $this->className = $className; + $this->sourceFile = $sourceFile; + $this->arguments = $arguments; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + public function hasSourceFile(): bool + { + return $this->sourceFile !== ''; + } + + public function sourceFile(): string + { + return $this->sourceFile; + } + + public function hasArguments(): bool + { + return !empty($this->arguments); + } + + public function arguments(): array + { + return $this->arguments; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollection.php new file mode 100644 index 00000000..76d07ebc --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollection.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use IteratorAggregate; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class ExtensionCollection implements IteratorAggregate +{ + /** + * @var Extension[] + */ + private $extensions; + + /** + * @param Extension[] $extensions + */ + public static function fromArray(array $extensions): self + { + return new self(...$extensions); + } + + private function __construct(Extension ...$extensions) + { + $this->extensions = $extensions; + } + + /** + * @return Extension[] + */ + public function asArray(): array + { + return $this->extensions; + } + + public function getIterator(): ExtensionCollectionIterator + { + return new ExtensionCollectionIterator($this); + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollectionIterator.php new file mode 100644 index 00000000..a9fc1af8 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/ExtensionCollectionIterator.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class ExtensionCollectionIterator implements Countable, Iterator +{ + /** + * @var Extension[] + */ + private $extensions; + + /** + * @var int + */ + private $position; + + public function __construct(ExtensionCollection $extensions) + { + $this->extensions = $extensions->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->extensions); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Extension + { + return $this->extensions[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/PHPUnit.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/PHPUnit.php new file mode 100644 index 00000000..5b3ce9b8 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/PHPUnit/PHPUnit.php @@ -0,0 +1,715 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class PHPUnit +{ + /** + * @var bool + */ + private $cacheResult; + + /** + * @var ?string + */ + private $cacheResultFile; + + /** + * @var int|string + */ + private $columns; + + /** + * @var string + */ + private $colors; + + /** + * @var bool + */ + private $stderr; + + /** + * @var bool + */ + private $noInteraction; + + /** + * @var bool + */ + private $verbose; + + /** + * @var bool + */ + private $reverseDefectList; + + /** + * @var bool + */ + private $convertDeprecationsToExceptions; + + /** + * @var bool + */ + private $convertErrorsToExceptions; + + /** + * @var bool + */ + private $convertNoticesToExceptions; + + /** + * @var bool + */ + private $convertWarningsToExceptions; + + /** + * @var bool + */ + private $forceCoversAnnotation; + + /** + * @var ?string + */ + private $bootstrap; + + /** + * @var bool + */ + private $processIsolation; + + /** + * @var bool + */ + private $failOnEmptyTestSuite; + + /** + * @var bool + */ + private $failOnIncomplete; + + /** + * @var bool + */ + private $failOnRisky; + + /** + * @var bool + */ + private $failOnSkipped; + + /** + * @var bool + */ + private $failOnWarning; + + /** + * @var bool + */ + private $stopOnDefect; + + /** + * @var bool + */ + private $stopOnError; + + /** + * @var bool + */ + private $stopOnFailure; + + /** + * @var bool + */ + private $stopOnWarning; + + /** + * @var bool + */ + private $stopOnIncomplete; + + /** + * @var bool + */ + private $stopOnRisky; + + /** + * @var bool + */ + private $stopOnSkipped; + + /** + * @var ?string + */ + private $extensionsDirectory; + + /** + * @var ?string + * + * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039 + */ + private $testSuiteLoaderClass; + + /** + * @var ?string + * + * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039 + */ + private $testSuiteLoaderFile; + + /** + * @var ?string + */ + private $printerClass; + + /** + * @var ?string + */ + private $printerFile; + + /** + * @var bool + */ + private $beStrictAboutChangesToGlobalState; + + /** + * @var bool + */ + private $beStrictAboutOutputDuringTests; + + /** + * @var bool + */ + private $beStrictAboutResourceUsageDuringSmallTests; + + /** + * @var bool + */ + private $beStrictAboutTestsThatDoNotTestAnything; + + /** + * @var bool + */ + private $beStrictAboutTodoAnnotatedTests; + + /** + * @var bool + */ + private $beStrictAboutCoversAnnotation; + + /** + * @var bool + */ + private $enforceTimeLimit; + + /** + * @var int + */ + private $defaultTimeLimit; + + /** + * @var int + */ + private $timeoutForSmallTests; + + /** + * @var int + */ + private $timeoutForMediumTests; + + /** + * @var int + */ + private $timeoutForLargeTests; + + /** + * @var ?string + */ + private $defaultTestSuite; + + /** + * @var int + */ + private $executionOrder; + + /** + * @var bool + */ + private $resolveDependencies; + + /** + * @var bool + */ + private $defectsFirst; + + /** + * @var bool + */ + private $backupGlobals; + + /** + * @var bool + */ + private $backupStaticAttributes; + + /** + * @var bool + */ + private $registerMockObjectsFromTestArgumentsRecursively; + + /** + * @var bool + */ + private $conflictBetweenPrinterClassAndTestdox; + + public function __construct(bool $cacheResult, ?string $cacheResultFile, $columns, string $colors, bool $stderr, bool $noInteraction, bool $verbose, bool $reverseDefectList, bool $convertDeprecationsToExceptions, bool $convertErrorsToExceptions, bool $convertNoticesToExceptions, bool $convertWarningsToExceptions, bool $forceCoversAnnotation, ?string $bootstrap, bool $processIsolation, bool $failOnEmptyTestSuite, bool $failOnIncomplete, bool $failOnRisky, bool $failOnSkipped, bool $failOnWarning, bool $stopOnDefect, bool $stopOnError, bool $stopOnFailure, bool $stopOnWarning, bool $stopOnIncomplete, bool $stopOnRisky, bool $stopOnSkipped, ?string $extensionsDirectory, ?string $testSuiteLoaderClass, ?string $testSuiteLoaderFile, ?string $printerClass, ?string $printerFile, bool $beStrictAboutChangesToGlobalState, bool $beStrictAboutOutputDuringTests, bool $beStrictAboutResourceUsageDuringSmallTests, bool $beStrictAboutTestsThatDoNotTestAnything, bool $beStrictAboutTodoAnnotatedTests, bool $beStrictAboutCoversAnnotation, bool $enforceTimeLimit, int $defaultTimeLimit, int $timeoutForSmallTests, int $timeoutForMediumTests, int $timeoutForLargeTests, ?string $defaultTestSuite, int $executionOrder, bool $resolveDependencies, bool $defectsFirst, bool $backupGlobals, bool $backupStaticAttributes, bool $registerMockObjectsFromTestArgumentsRecursively, bool $conflictBetweenPrinterClassAndTestdox) + { + $this->cacheResult = $cacheResult; + $this->cacheResultFile = $cacheResultFile; + $this->columns = $columns; + $this->colors = $colors; + $this->stderr = $stderr; + $this->noInteraction = $noInteraction; + $this->verbose = $verbose; + $this->reverseDefectList = $reverseDefectList; + $this->convertDeprecationsToExceptions = $convertDeprecationsToExceptions; + $this->convertErrorsToExceptions = $convertErrorsToExceptions; + $this->convertNoticesToExceptions = $convertNoticesToExceptions; + $this->convertWarningsToExceptions = $convertWarningsToExceptions; + $this->forceCoversAnnotation = $forceCoversAnnotation; + $this->bootstrap = $bootstrap; + $this->processIsolation = $processIsolation; + $this->failOnEmptyTestSuite = $failOnEmptyTestSuite; + $this->failOnIncomplete = $failOnIncomplete; + $this->failOnRisky = $failOnRisky; + $this->failOnSkipped = $failOnSkipped; + $this->failOnWarning = $failOnWarning; + $this->stopOnDefect = $stopOnDefect; + $this->stopOnError = $stopOnError; + $this->stopOnFailure = $stopOnFailure; + $this->stopOnWarning = $stopOnWarning; + $this->stopOnIncomplete = $stopOnIncomplete; + $this->stopOnRisky = $stopOnRisky; + $this->stopOnSkipped = $stopOnSkipped; + $this->extensionsDirectory = $extensionsDirectory; + $this->testSuiteLoaderClass = $testSuiteLoaderClass; + $this->testSuiteLoaderFile = $testSuiteLoaderFile; + $this->printerClass = $printerClass; + $this->printerFile = $printerFile; + $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; + $this->beStrictAboutOutputDuringTests = $beStrictAboutOutputDuringTests; + $this->beStrictAboutResourceUsageDuringSmallTests = $beStrictAboutResourceUsageDuringSmallTests; + $this->beStrictAboutTestsThatDoNotTestAnything = $beStrictAboutTestsThatDoNotTestAnything; + $this->beStrictAboutTodoAnnotatedTests = $beStrictAboutTodoAnnotatedTests; + $this->beStrictAboutCoversAnnotation = $beStrictAboutCoversAnnotation; + $this->enforceTimeLimit = $enforceTimeLimit; + $this->defaultTimeLimit = $defaultTimeLimit; + $this->timeoutForSmallTests = $timeoutForSmallTests; + $this->timeoutForMediumTests = $timeoutForMediumTests; + $this->timeoutForLargeTests = $timeoutForLargeTests; + $this->defaultTestSuite = $defaultTestSuite; + $this->executionOrder = $executionOrder; + $this->resolveDependencies = $resolveDependencies; + $this->defectsFirst = $defectsFirst; + $this->backupGlobals = $backupGlobals; + $this->backupStaticAttributes = $backupStaticAttributes; + $this->registerMockObjectsFromTestArgumentsRecursively = $registerMockObjectsFromTestArgumentsRecursively; + $this->conflictBetweenPrinterClassAndTestdox = $conflictBetweenPrinterClassAndTestdox; + } + + public function cacheResult(): bool + { + return $this->cacheResult; + } + + /** + * @psalm-assert-if-true !null $this->cacheResultFile + */ + public function hasCacheResultFile(): bool + { + return $this->cacheResultFile !== null; + } + + /** + * @throws Exception + */ + public function cacheResultFile(): string + { + if (!$this->hasCacheResultFile()) { + throw new Exception('Cache result file is not configured'); + } + + return (string) $this->cacheResultFile; + } + + public function columns() + { + return $this->columns; + } + + public function colors(): string + { + return $this->colors; + } + + public function stderr(): bool + { + return $this->stderr; + } + + public function noInteraction(): bool + { + return $this->noInteraction; + } + + public function verbose(): bool + { + return $this->verbose; + } + + public function reverseDefectList(): bool + { + return $this->reverseDefectList; + } + + public function convertDeprecationsToExceptions(): bool + { + return $this->convertDeprecationsToExceptions; + } + + public function convertErrorsToExceptions(): bool + { + return $this->convertErrorsToExceptions; + } + + public function convertNoticesToExceptions(): bool + { + return $this->convertNoticesToExceptions; + } + + public function convertWarningsToExceptions(): bool + { + return $this->convertWarningsToExceptions; + } + + public function forceCoversAnnotation(): bool + { + return $this->forceCoversAnnotation; + } + + /** + * @psalm-assert-if-true !null $this->bootstrap + */ + public function hasBootstrap(): bool + { + return $this->bootstrap !== null; + } + + /** + * @throws Exception + */ + public function bootstrap(): string + { + if (!$this->hasBootstrap()) { + throw new Exception('Bootstrap script is not configured'); + } + + return (string) $this->bootstrap; + } + + public function processIsolation(): bool + { + return $this->processIsolation; + } + + public function failOnEmptyTestSuite(): bool + { + return $this->failOnEmptyTestSuite; + } + + public function failOnIncomplete(): bool + { + return $this->failOnIncomplete; + } + + public function failOnRisky(): bool + { + return $this->failOnRisky; + } + + public function failOnSkipped(): bool + { + return $this->failOnSkipped; + } + + public function failOnWarning(): bool + { + return $this->failOnWarning; + } + + public function stopOnDefect(): bool + { + return $this->stopOnDefect; + } + + public function stopOnError(): bool + { + return $this->stopOnError; + } + + public function stopOnFailure(): bool + { + return $this->stopOnFailure; + } + + public function stopOnWarning(): bool + { + return $this->stopOnWarning; + } + + public function stopOnIncomplete(): bool + { + return $this->stopOnIncomplete; + } + + public function stopOnRisky(): bool + { + return $this->stopOnRisky; + } + + public function stopOnSkipped(): bool + { + return $this->stopOnSkipped; + } + + /** + * @psalm-assert-if-true !null $this->extensionsDirectory + */ + public function hasExtensionsDirectory(): bool + { + return $this->extensionsDirectory !== null; + } + + /** + * @throws Exception + */ + public function extensionsDirectory(): string + { + if (!$this->hasExtensionsDirectory()) { + throw new Exception('Extensions directory is not configured'); + } + + return (string) $this->extensionsDirectory; + } + + /** + * @psalm-assert-if-true !null $this->testSuiteLoaderClass + * + * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039 + */ + public function hasTestSuiteLoaderClass(): bool + { + return $this->testSuiteLoaderClass !== null; + } + + /** + * @throws Exception + * + * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039 + */ + public function testSuiteLoaderClass(): string + { + if (!$this->hasTestSuiteLoaderClass()) { + throw new Exception('TestSuiteLoader class is not configured'); + } + + return (string) $this->testSuiteLoaderClass; + } + + /** + * @psalm-assert-if-true !null $this->testSuiteLoaderFile + * + * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039 + */ + public function hasTestSuiteLoaderFile(): bool + { + return $this->testSuiteLoaderFile !== null; + } + + /** + * @throws Exception + * + * @deprecated see https://github.com/sebastianbergmann/phpunit/issues/4039 + */ + public function testSuiteLoaderFile(): string + { + if (!$this->hasTestSuiteLoaderFile()) { + throw new Exception('TestSuiteLoader sourcecode file is not configured'); + } + + return (string) $this->testSuiteLoaderFile; + } + + /** + * @psalm-assert-if-true !null $this->printerClass + */ + public function hasPrinterClass(): bool + { + return $this->printerClass !== null; + } + + /** + * @throws Exception + */ + public function printerClass(): string + { + if (!$this->hasPrinterClass()) { + throw new Exception('ResultPrinter class is not configured'); + } + + return (string) $this->printerClass; + } + + /** + * @psalm-assert-if-true !null $this->printerFile + */ + public function hasPrinterFile(): bool + { + return $this->printerFile !== null; + } + + /** + * @throws Exception + */ + public function printerFile(): string + { + if (!$this->hasPrinterFile()) { + throw new Exception('ResultPrinter sourcecode file is not configured'); + } + + return (string) $this->printerFile; + } + + public function beStrictAboutChangesToGlobalState(): bool + { + return $this->beStrictAboutChangesToGlobalState; + } + + public function beStrictAboutOutputDuringTests(): bool + { + return $this->beStrictAboutOutputDuringTests; + } + + public function beStrictAboutResourceUsageDuringSmallTests(): bool + { + return $this->beStrictAboutResourceUsageDuringSmallTests; + } + + public function beStrictAboutTestsThatDoNotTestAnything(): bool + { + return $this->beStrictAboutTestsThatDoNotTestAnything; + } + + public function beStrictAboutTodoAnnotatedTests(): bool + { + return $this->beStrictAboutTodoAnnotatedTests; + } + + public function beStrictAboutCoversAnnotation(): bool + { + return $this->beStrictAboutCoversAnnotation; + } + + public function enforceTimeLimit(): bool + { + return $this->enforceTimeLimit; + } + + public function defaultTimeLimit(): int + { + return $this->defaultTimeLimit; + } + + public function timeoutForSmallTests(): int + { + return $this->timeoutForSmallTests; + } + + public function timeoutForMediumTests(): int + { + return $this->timeoutForMediumTests; + } + + public function timeoutForLargeTests(): int + { + return $this->timeoutForLargeTests; + } + + /** + * @psalm-assert-if-true !null $this->defaultTestSuite + */ + public function hasDefaultTestSuite(): bool + { + return $this->defaultTestSuite !== null; + } + + /** + * @throws Exception + */ + public function defaultTestSuite(): string + { + if (!$this->hasDefaultTestSuite()) { + throw new Exception('Default test suite is not configured'); + } + + return (string) $this->defaultTestSuite; + } + + public function executionOrder(): int + { + return $this->executionOrder; + } + + public function resolveDependencies(): bool + { + return $this->resolveDependencies; + } + + public function defectsFirst(): bool + { + return $this->defectsFirst; + } + + public function backupGlobals(): bool + { + return $this->backupGlobals; + } + + public function backupStaticAttributes(): bool + { + return $this->backupStaticAttributes; + } + + public function registerMockObjectsFromTestArgumentsRecursively(): bool + { + return $this->registerMockObjectsFromTestArgumentsRecursively; + } + + public function conflictBetweenPrinterClassAndTestdox(): bool + { + return $this->conflictBetweenPrinterClassAndTestdox; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectory.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectory.php new file mode 100644 index 00000000..ecefbb7c --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectory.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use PHPUnit\Util\VersionComparisonOperator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class TestDirectory +{ + /** + * @var string + */ + private $path; + + /** + * @var string + */ + private $prefix; + + /** + * @var string + */ + private $suffix; + + /** + * @var string + */ + private $phpVersion; + + /** + * @var VersionComparisonOperator + */ + private $phpVersionOperator; + + public function __construct(string $path, string $prefix, string $suffix, string $phpVersion, VersionComparisonOperator $phpVersionOperator) + { + $this->path = $path; + $this->prefix = $prefix; + $this->suffix = $suffix; + $this->phpVersion = $phpVersion; + $this->phpVersionOperator = $phpVersionOperator; + } + + public function path(): string + { + return $this->path; + } + + public function prefix(): string + { + return $this->prefix; + } + + public function suffix(): string + { + return $this->suffix; + } + + public function phpVersion(): string + { + return $this->phpVersion; + } + + public function phpVersionOperator(): VersionComparisonOperator + { + return $this->phpVersionOperator; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollection.php new file mode 100644 index 00000000..5f581c21 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollection.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class TestDirectoryCollection implements Countable, IteratorAggregate +{ + /** + * @var TestDirectory[] + */ + private $directories; + + /** + * @param TestDirectory[] $directories + */ + public static function fromArray(array $directories): self + { + return new self(...$directories); + } + + private function __construct(TestDirectory ...$directories) + { + $this->directories = $directories; + } + + /** + * @return TestDirectory[] + */ + public function asArray(): array + { + return $this->directories; + } + + public function count(): int + { + return count($this->directories); + } + + public function getIterator(): TestDirectoryCollectionIterator + { + return new TestDirectoryCollectionIterator($this); + } + + public function isEmpty(): bool + { + return $this->count() === 0; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollectionIterator.php new file mode 100644 index 00000000..b2312a38 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestDirectoryCollectionIterator.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class TestDirectoryCollectionIterator implements Countable, Iterator +{ + /** + * @var TestDirectory[] + */ + private $directories; + + /** + * @var int + */ + private $position; + + public function __construct(TestDirectoryCollection $directories) + { + $this->directories = $directories->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->directories); + } + + public function key(): int + { + return $this->position; + } + + public function current(): TestDirectory + { + return $this->directories[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFile.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFile.php new file mode 100644 index 00000000..21d1cf7b --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFile.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use PHPUnit\Util\VersionComparisonOperator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class TestFile +{ + /** + * @var string + */ + private $path; + + /** + * @var string + */ + private $phpVersion; + + /** + * @var VersionComparisonOperator + */ + private $phpVersionOperator; + + public function __construct(string $path, string $phpVersion, VersionComparisonOperator $phpVersionOperator) + { + $this->path = $path; + $this->phpVersion = $phpVersion; + $this->phpVersionOperator = $phpVersionOperator; + } + + public function path(): string + { + return $this->path; + } + + public function phpVersion(): string + { + return $this->phpVersion; + } + + public function phpVersionOperator(): VersionComparisonOperator + { + return $this->phpVersionOperator; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollection.php new file mode 100644 index 00000000..27ba9bd2 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollection.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class TestFileCollection implements Countable, IteratorAggregate +{ + /** + * @var TestFile[] + */ + private $files; + + /** + * @param TestFile[] $files + */ + public static function fromArray(array $files): self + { + return new self(...$files); + } + + private function __construct(TestFile ...$files) + { + $this->files = $files; + } + + /** + * @return TestFile[] + */ + public function asArray(): array + { + return $this->files; + } + + public function count(): int + { + return count($this->files); + } + + public function getIterator(): TestFileCollectionIterator + { + return new TestFileCollectionIterator($this); + } + + public function isEmpty(): bool + { + return $this->count() === 0; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollectionIterator.php new file mode 100644 index 00000000..45a5f160 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestFileCollectionIterator.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class TestFileCollectionIterator implements Countable, Iterator +{ + /** + * @var TestFile[] + */ + private $files; + + /** + * @var int + */ + private $position; + + public function __construct(TestFileCollection $files) + { + $this->files = $files->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->files); + } + + public function key(): int + { + return $this->position; + } + + public function current(): TestFile + { + return $this->files[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuite.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuite.php new file mode 100644 index 00000000..035376cb --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuite.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class TestSuite +{ + /** + * @var string + */ + private $name; + + /** + * @var TestDirectoryCollection + */ + private $directories; + + /** + * @var TestFileCollection + */ + private $files; + + /** + * @var FileCollection + */ + private $exclude; + + public function __construct(string $name, TestDirectoryCollection $directories, TestFileCollection $files, FileCollection $exclude) + { + $this->name = $name; + $this->directories = $directories; + $this->files = $files; + $this->exclude = $exclude; + } + + public function name(): string + { + return $this->name; + } + + public function directories(): TestDirectoryCollection + { + return $this->directories; + } + + public function files(): TestFileCollection + { + return $this->files; + } + + public function exclude(): FileCollection + { + return $this->exclude; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollection.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollection.php new file mode 100644 index 00000000..f632e519 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollection.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class TestSuiteCollection implements Countable, IteratorAggregate +{ + /** + * @var TestSuite[] + */ + private $testSuites; + + /** + * @param TestSuite[] $testSuites + */ + public static function fromArray(array $testSuites): self + { + return new self(...$testSuites); + } + + private function __construct(TestSuite ...$testSuites) + { + $this->testSuites = $testSuites; + } + + /** + * @return TestSuite[] + */ + public function asArray(): array + { + return $this->testSuites; + } + + public function count(): int + { + return count($this->testSuites); + } + + public function getIterator(): TestSuiteCollectionIterator + { + return new TestSuiteCollectionIterator($this); + } + + public function isEmpty(): bool + { + return $this->count() === 0; + } +} diff --git a/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollectionIterator.php b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollectionIterator.php new file mode 100644 index 00000000..42d03db0 --- /dev/null +++ b/vendor/phpunit/phpunit/src/TextUI/XmlConfiguration/TestSuite/TestSuiteCollectionIterator.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class TestSuiteCollectionIterator implements Countable, Iterator +{ + /** + * @var TestSuite[] + */ + private $testSuites; + + /** + * @var int + */ + private $position; + + public function __construct(TestSuiteCollection $testSuites) + { + $this->testSuites = $testSuites->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->testSuites); + } + + public function key(): int + { + return $this->position; + } + + public function current(): TestSuite + { + return $this->testSuites[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Annotation/DocBlock.php b/vendor/phpunit/phpunit/src/Util/Annotation/DocBlock.php new file mode 100644 index 00000000..648f9edc --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Annotation/DocBlock.php @@ -0,0 +1,551 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Annotation; + +use const JSON_ERROR_NONE; +use const PREG_OFFSET_CAPTURE; +use function array_filter; +use function array_key_exists; +use function array_map; +use function array_merge; +use function array_pop; +use function array_slice; +use function array_values; +use function count; +use function explode; +use function file; +use function implode; +use function is_array; +use function is_int; +use function json_decode; +use function json_last_error; +use function json_last_error_msg; +use function preg_match; +use function preg_match_all; +use function preg_replace; +use function preg_split; +use function realpath; +use function rtrim; +use function sprintf; +use function str_replace; +use function strlen; +use function strpos; +use function strtolower; +use function substr; +use function trim; +use PharIo\Version\VersionConstraintParser; +use PHPUnit\Framework\InvalidDataProviderException; +use PHPUnit\Framework\SkippedTestError; +use PHPUnit\Framework\Warning; +use PHPUnit\Util\Exception; +use PHPUnit\Util\InvalidDataSetException; +use ReflectionClass; +use ReflectionException; +use ReflectionFunctionAbstract; +use ReflectionMethod; +use Reflector; +use Traversable; + +/** + * This is an abstraction around a PHPUnit-specific docBlock, + * allowing us to ask meaningful questions about a specific + * reflection symbol. + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DocBlock +{ + /** + * @todo This constant should be private (it's public because of TestTest::testGetProvidedDataRegEx) + */ + public const REGEX_DATA_PROVIDER = '/@dataProvider\s+([a-zA-Z0-9._:-\\\\x7f-\xff]+)/'; + + private const REGEX_REQUIRES_VERSION = '/@requires\s+(?PPHP(?:Unit)?)\s+(?P[<>=!]{0,2})\s*(?P[\d\.-]+(dev|(RC|alpha|beta)[\d\.])?)[ \t]*\r?$/m'; + + private const REGEX_REQUIRES_VERSION_CONSTRAINT = '/@requires\s+(?PPHP(?:Unit)?)\s+(?P[\d\t \-.|~^]+)[ \t]*\r?$/m'; + + private const REGEX_REQUIRES_OS = '/@requires\s+(?POS(?:FAMILY)?)\s+(?P.+?)[ \t]*\r?$/m'; + + private const REGEX_REQUIRES_SETTING = '/@requires\s+(?Psetting)\s+(?P([^ ]+?))\s*(?P[\w\.-]+[\w\.]?)?[ \t]*\r?$/m'; + + private const REGEX_REQUIRES = '/@requires\s+(?Pfunction|extension)\s+(?P([^\s<>=!]+))\s*(?P[<>=!]{0,2})\s*(?P[\d\.-]+[\d\.]?)?[ \t]*\r?$/m'; + + private const REGEX_TEST_WITH = '/@testWith\s+/'; + + /** @var string */ + private $docComment; + + /** @var bool */ + private $isMethod; + + /** @var array> pre-parsed annotations indexed by name and occurrence index */ + private $symbolAnnotations; + + /** + * @var null|array + * + * @psalm-var null|(array{ + * __OFFSET: array&array{__FILE: string}, + * setting?: array, + * extension_versions?: array + * }&array< + * string, + * string|array{version: string, operator: string}|array{constraint: string}|array + * >) + */ + private $parsedRequirements; + + /** @var int */ + private $startLine; + + /** @var int */ + private $endLine; + + /** @var string */ + private $fileName; + + /** @var string */ + private $name; + + /** + * @var string + * + * @psalm-var class-string + */ + private $className; + + public static function ofClass(ReflectionClass $class): self + { + $className = $class->getName(); + + return new self( + (string) $class->getDocComment(), + false, + self::extractAnnotationsFromReflector($class), + $class->getStartLine(), + $class->getEndLine(), + $class->getFileName(), + $className, + $className + ); + } + + /** + * @psalm-param class-string $classNameInHierarchy + */ + public static function ofMethod(ReflectionMethod $method, string $classNameInHierarchy): self + { + return new self( + (string) $method->getDocComment(), + true, + self::extractAnnotationsFromReflector($method), + $method->getStartLine(), + $method->getEndLine(), + $method->getFileName(), + $method->getName(), + $classNameInHierarchy + ); + } + + /** + * Note: we do not preserve an instance of the reflection object, since it cannot be safely (de-)serialized. + * + * @param array> $symbolAnnotations + * + * @psalm-param class-string $className + */ + private function __construct(string $docComment, bool $isMethod, array $symbolAnnotations, int $startLine, int $endLine, string $fileName, string $name, string $className) + { + $this->docComment = $docComment; + $this->isMethod = $isMethod; + $this->symbolAnnotations = $symbolAnnotations; + $this->startLine = $startLine; + $this->endLine = $endLine; + $this->fileName = $fileName; + $this->name = $name; + $this->className = $className; + } + + /** + * @psalm-return array{ + * __OFFSET: array&array{__FILE: string}, + * setting?: array, + * extension_versions?: array + * }&array< + * string, + * string|array{version: string, operator: string}|array{constraint: string}|array + * > + * + * @throws Warning if the requirements version constraint is not well-formed + */ + public function requirements(): array + { + if ($this->parsedRequirements !== null) { + return $this->parsedRequirements; + } + + $offset = $this->startLine; + $requires = []; + $recordedSettings = []; + $extensionVersions = []; + $recordedOffsets = [ + '__FILE' => realpath($this->fileName), + ]; + + // Trim docblock markers, split it into lines and rewind offset to start of docblock + $lines = preg_replace(['#^/\*{2}#', '#\*/$#'], '', preg_split('/\r\n|\r|\n/', $this->docComment)); + $offset -= count($lines); + + foreach ($lines as $line) { + if (preg_match(self::REGEX_REQUIRES_OS, $line, $matches)) { + $requires[$matches['name']] = $matches['value']; + $recordedOffsets[$matches['name']] = $offset; + } + + if (preg_match(self::REGEX_REQUIRES_VERSION, $line, $matches)) { + $requires[$matches['name']] = [ + 'version' => $matches['version'], + 'operator' => $matches['operator'], + ]; + $recordedOffsets[$matches['name']] = $offset; + } + + if (preg_match(self::REGEX_REQUIRES_VERSION_CONSTRAINT, $line, $matches)) { + if (!empty($requires[$matches['name']])) { + $offset++; + + continue; + } + + try { + $versionConstraintParser = new VersionConstraintParser; + + $requires[$matches['name'] . '_constraint'] = [ + 'constraint' => $versionConstraintParser->parse(trim($matches['constraint'])), + ]; + $recordedOffsets[$matches['name'] . '_constraint'] = $offset; + } catch (\PharIo\Version\Exception $e) { + throw new Warning($e->getMessage(), $e->getCode(), $e); + } + } + + if (preg_match(self::REGEX_REQUIRES_SETTING, $line, $matches)) { + $recordedSettings[$matches['setting']] = $matches['value']; + $recordedOffsets['__SETTING_' . $matches['setting']] = $offset; + } + + if (preg_match(self::REGEX_REQUIRES, $line, $matches)) { + $name = $matches['name'] . 's'; + + if (!isset($requires[$name])) { + $requires[$name] = []; + } + + $requires[$name][] = $matches['value']; + $recordedOffsets[$matches['name'] . '_' . $matches['value']] = $offset; + + if ($name === 'extensions' && !empty($matches['version'])) { + $extensionVersions[$matches['value']] = [ + 'version' => $matches['version'], + 'operator' => $matches['operator'], + ]; + } + } + + $offset++; + } + + return $this->parsedRequirements = array_merge( + $requires, + ['__OFFSET' => $recordedOffsets], + array_filter([ + 'setting' => $recordedSettings, + 'extension_versions' => $extensionVersions, + ]) + ); + } + + /** + * Returns the provided data for a method. + * + * @throws Exception + */ + public function getProvidedData(): ?array + { + /** @noinspection SuspiciousBinaryOperationInspection */ + $data = $this->getDataFromDataProviderAnnotation($this->docComment) ?? $this->getDataFromTestWithAnnotation($this->docComment); + + if ($data === null) { + return null; + } + + if ($data === []) { + throw new SkippedTestError; + } + + foreach ($data as $key => $value) { + if (!is_array($value)) { + throw new InvalidDataSetException( + sprintf( + 'Data set %s is invalid.', + is_int($key) ? '#' . $key : '"' . $key . '"' + ) + ); + } + } + + return $data; + } + + /** + * @psalm-return array + */ + public function getInlineAnnotations(): array + { + $code = file($this->fileName); + $lineNumber = $this->startLine; + $startLine = $this->startLine - 1; + $endLine = $this->endLine - 1; + $codeLines = array_slice($code, $startLine, $endLine - $startLine + 1); + $annotations = []; + + foreach ($codeLines as $line) { + if (preg_match('#/\*\*?\s*@(?P[A-Za-z_-]+)(?:[ \t]+(?P.*?))?[ \t]*\r?\*/$#m', $line, $matches)) { + $annotations[strtolower($matches['name'])] = [ + 'line' => $lineNumber, + 'value' => $matches['value'], + ]; + } + + $lineNumber++; + } + + return $annotations; + } + + public function symbolAnnotations(): array + { + return $this->symbolAnnotations; + } + + public function isHookToBeExecutedBeforeClass(): bool + { + return $this->isMethod && + false !== strpos($this->docComment, '@beforeClass'); + } + + public function isHookToBeExecutedAfterClass(): bool + { + return $this->isMethod && + false !== strpos($this->docComment, '@afterClass'); + } + + public function isToBeExecutedBeforeTest(): bool + { + return 1 === preg_match('/@before\b/', $this->docComment); + } + + public function isToBeExecutedAfterTest(): bool + { + return 1 === preg_match('/@after\b/', $this->docComment); + } + + public function isToBeExecutedAsPreCondition(): bool + { + return 1 === preg_match('/@preCondition\b/', $this->docComment); + } + + public function isToBeExecutedAsPostCondition(): bool + { + return 1 === preg_match('/@postCondition\b/', $this->docComment); + } + + private function getDataFromDataProviderAnnotation(string $docComment): ?array + { + $methodName = null; + $className = $this->className; + + if ($this->isMethod) { + $methodName = $this->name; + } + + if (!preg_match_all(self::REGEX_DATA_PROVIDER, $docComment, $matches)) { + return null; + } + + $result = []; + + foreach ($matches[1] as $match) { + $dataProviderMethodNameNamespace = explode('\\', $match); + $leaf = explode('::', array_pop($dataProviderMethodNameNamespace)); + $dataProviderMethodName = array_pop($leaf); + + if (empty($dataProviderMethodNameNamespace)) { + $dataProviderMethodNameNamespace = ''; + } else { + $dataProviderMethodNameNamespace = implode('\\', $dataProviderMethodNameNamespace) . '\\'; + } + + if (empty($leaf)) { + $dataProviderClassName = $className; + } else { + /** @psalm-var class-string $dataProviderClassName */ + $dataProviderClassName = $dataProviderMethodNameNamespace . array_pop($leaf); + } + + try { + $dataProviderClass = new ReflectionClass($dataProviderClassName); + + $dataProviderMethod = $dataProviderClass->getMethod( + $dataProviderMethodName + ); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + // @codeCoverageIgnoreEnd + } + + if ($dataProviderMethod->isStatic()) { + $object = null; + } else { + $object = $dataProviderClass->newInstance(); + } + + if ($dataProviderMethod->getNumberOfParameters() === 0) { + $data = $dataProviderMethod->invoke($object); + } else { + $data = $dataProviderMethod->invoke($object, $methodName); + } + + if ($data instanceof Traversable) { + $origData = $data; + $data = []; + + foreach ($origData as $key => $value) { + if (is_int($key)) { + $data[] = $value; + } elseif (array_key_exists($key, $data)) { + throw new InvalidDataProviderException( + sprintf( + 'The key "%s" has already been defined in the data provider "%s".', + $key, + $match + ) + ); + } else { + $data[$key] = $value; + } + } + } + + if (is_array($data)) { + $result = array_merge($result, $data); + } + } + + return $result; + } + + /** + * @throws Exception + */ + private function getDataFromTestWithAnnotation(string $docComment): ?array + { + $docComment = $this->cleanUpMultiLineAnnotation($docComment); + + if (!preg_match(self::REGEX_TEST_WITH, $docComment, $matches, PREG_OFFSET_CAPTURE)) { + return null; + } + + $offset = strlen($matches[0][0]) + $matches[0][1]; + $annotationContent = substr($docComment, $offset); + $data = []; + + foreach (explode("\n", $annotationContent) as $candidateRow) { + $candidateRow = trim($candidateRow); + + if ($candidateRow[0] !== '[') { + break; + } + + $dataSet = json_decode($candidateRow, true); + + if (json_last_error() !== JSON_ERROR_NONE) { + throw new Exception( + 'The data set for the @testWith annotation cannot be parsed: ' . json_last_error_msg() + ); + } + + $data[] = $dataSet; + } + + if (!$data) { + throw new Exception('The data set for the @testWith annotation cannot be parsed.'); + } + + return $data; + } + + private function cleanUpMultiLineAnnotation(string $docComment): string + { + //removing initial ' * ' for docComment + $docComment = str_replace("\r\n", "\n", $docComment); + $docComment = preg_replace('/' . '\n' . '\s*' . '\*' . '\s?' . '/', "\n", $docComment); + $docComment = (string) substr($docComment, 0, -1); + + return rtrim($docComment, "\n"); + } + + /** @return array> */ + private static function parseDocBlock(string $docBlock): array + { + // Strip away the docblock header and footer to ease parsing of one line annotations + $docBlock = (string) substr($docBlock, 3, -2); + $annotations = []; + + if (preg_match_all('/@(?P[A-Za-z_-]+)(?:[ \t]+(?P.*?))?[ \t]*\r?$/m', $docBlock, $matches)) { + $numMatches = count($matches[0]); + + for ($i = 0; $i < $numMatches; $i++) { + $annotations[$matches['name'][$i]][] = (string) $matches['value'][$i]; + } + } + + return $annotations; + } + + /** @param ReflectionClass|ReflectionFunctionAbstract $reflector */ + private static function extractAnnotationsFromReflector(Reflector $reflector): array + { + $annotations = []; + + if ($reflector instanceof ReflectionClass) { + $annotations = array_merge( + $annotations, + ...array_map( + static function (ReflectionClass $trait): array + { + return self::parseDocBlock((string) $trait->getDocComment()); + }, + array_values($reflector->getTraits()) + ) + ); + } + + return array_merge( + $annotations, + self::parseDocBlock((string) $reflector->getDocComment()) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Annotation/Registry.php b/vendor/phpunit/phpunit/src/Util/Annotation/Registry.php new file mode 100644 index 00000000..8ee6c839 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Annotation/Registry.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Annotation; + +use function array_key_exists; +use PHPUnit\Util\Exception; +use ReflectionClass; +use ReflectionException; +use ReflectionMethod; + +/** + * Reflection information, and therefore DocBlock information, is static within + * a single PHP process. It is therefore okay to use a Singleton registry here. + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Registry +{ + /** @var null|self */ + private static $instance; + + /** @var array indexed by class name */ + private $classDocBlocks = []; + + /** @var array> indexed by class name and method name */ + private $methodDocBlocks = []; + + public static function getInstance(): self + { + return self::$instance ?? self::$instance = new self; + } + + private function __construct() + { + } + + /** + * @throws Exception + * + * @psalm-param class-string $class + */ + public function forClassName(string $class): DocBlock + { + if (array_key_exists($class, $this->classDocBlocks)) { + return $this->classDocBlocks[$class]; + } + + try { + $reflection = new ReflectionClass($class); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + return $this->classDocBlocks[$class] = DocBlock::ofClass($reflection); + } + + /** + * @throws Exception + * + * @psalm-param class-string $classInHierarchy + */ + public function forMethod(string $classInHierarchy, string $method): DocBlock + { + if (isset($this->methodDocBlocks[$classInHierarchy][$method])) { + return $this->methodDocBlocks[$classInHierarchy][$method]; + } + + try { + $reflection = new ReflectionMethod($classInHierarchy, $method); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + return $this->methodDocBlocks[$classInHierarchy][$method] = DocBlock::ofMethod($reflection, $classInHierarchy); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Blacklist.php b/vendor/phpunit/phpunit/src/Util/Blacklist.php new file mode 100644 index 00000000..3b416e14 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Blacklist.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +/** + * @deprecated Use ExcludeList instead + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Blacklist +{ + public static function addDirectory(string $directory): void + { + ExcludeList::addDirectory($directory); + } + + /** + * @throws Exception + * + * @return string[] + */ + public function getBlacklistedDirectories(): array + { + return (new ExcludeList)->getExcludedDirectories(); + } + + /** + * @throws Exception + */ + public function isBlacklisted(string $file): bool + { + return (new ExcludeList)->isExcluded($file); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Cloner.php b/vendor/phpunit/phpunit/src/Util/Cloner.php new file mode 100644 index 00000000..38bd59ff --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Cloner.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Cloner +{ + /** + * @psalm-template OriginalType + * + * @psalm-param OriginalType $original + * + * @psalm-return OriginalType + */ + public static function clone(object $original): object + { + try { + return clone $original; + } catch (Throwable $t) { + return $original; + } + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Color.php b/vendor/phpunit/phpunit/src/Util/Color.php new file mode 100644 index 00000000..b96eb474 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Color.php @@ -0,0 +1,159 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const DIRECTORY_SEPARATOR; +use function array_keys; +use function array_map; +use function array_values; +use function count; +use function explode; +use function implode; +use function min; +use function preg_replace; +use function preg_replace_callback; +use function sprintf; +use function strtr; +use function trim; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Color +{ + /** + * @var array + */ + private const WHITESPACE_MAP = [ + ' ' => '·', + "\t" => '⇥', + ]; + + /** + * @var array + */ + private const WHITESPACE_EOL_MAP = [ + ' ' => '·', + "\t" => '⇥', + "\n" => '↵', + "\r" => '⟵', + ]; + + /** + * @var array + */ + private static $ansiCodes = [ + 'reset' => '0', + 'bold' => '1', + 'dim' => '2', + 'dim-reset' => '22', + 'underlined' => '4', + 'fg-default' => '39', + 'fg-black' => '30', + 'fg-red' => '31', + 'fg-green' => '32', + 'fg-yellow' => '33', + 'fg-blue' => '34', + 'fg-magenta' => '35', + 'fg-cyan' => '36', + 'fg-white' => '37', + 'bg-default' => '49', + 'bg-black' => '40', + 'bg-red' => '41', + 'bg-green' => '42', + 'bg-yellow' => '43', + 'bg-blue' => '44', + 'bg-magenta' => '45', + 'bg-cyan' => '46', + 'bg-white' => '47', + ]; + + public static function colorize(string $color, string $buffer): string + { + if (trim($buffer) === '') { + return $buffer; + } + + $codes = array_map('\trim', explode(',', $color)); + $styles = []; + + foreach ($codes as $code) { + if (isset(self::$ansiCodes[$code])) { + $styles[] = self::$ansiCodes[$code] ?? ''; + } + } + + if (empty($styles)) { + return $buffer; + } + + return self::optimizeColor(sprintf("\x1b[%sm", implode(';', $styles)) . $buffer . "\x1b[0m"); + } + + public static function colorizePath(string $path, ?string $prevPath = null, bool $colorizeFilename = false): string + { + if ($prevPath === null) { + $prevPath = ''; + } + + $path = explode(DIRECTORY_SEPARATOR, $path); + $prevPath = explode(DIRECTORY_SEPARATOR, $prevPath); + + for ($i = 0; $i < min(count($path), count($prevPath)); $i++) { + if ($path[$i] == $prevPath[$i]) { + $path[$i] = self::dim($path[$i]); + } + } + + if ($colorizeFilename) { + $last = count($path) - 1; + $path[$last] = preg_replace_callback( + '/([\-_\.]+|phpt$)/', + static function ($matches) + { + return self::dim($matches[0]); + }, + $path[$last] + ); + } + + return self::optimizeColor(implode(self::dim(DIRECTORY_SEPARATOR), $path)); + } + + public static function dim(string $buffer): string + { + if (trim($buffer) === '') { + return $buffer; + } + + return "\e[2m{$buffer}\e[22m"; + } + + public static function visualizeWhitespace(string $buffer, bool $visualizeEOL = false): string + { + $replaceMap = $visualizeEOL ? self::WHITESPACE_EOL_MAP : self::WHITESPACE_MAP; + + return preg_replace_callback('/\s+/', static function ($matches) use ($replaceMap) + { + return self::dim(strtr($matches[0], $replaceMap)); + }, $buffer); + } + + private static function optimizeColor(string $buffer): string + { + $patterns = [ + "/\e\\[22m\e\\[2m/" => '', + "/\e\\[([^m]*)m\e\\[([1-9][0-9;]*)m/" => "\e[$1;$2m", + "/(\e\\[[^m]*m)+(\e\\[0m)/" => '$2', + ]; + + return preg_replace(array_keys($patterns), array_values($patterns), $buffer); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/ErrorHandler.php b/vendor/phpunit/phpunit/src/Util/ErrorHandler.php new file mode 100644 index 00000000..f8566347 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/ErrorHandler.php @@ -0,0 +1,156 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const E_DEPRECATED; +use const E_NOTICE; +use const E_STRICT; +use const E_USER_DEPRECATED; +use const E_USER_NOTICE; +use const E_USER_WARNING; +use const E_WARNING; +use function error_reporting; +use function restore_error_handler; +use function set_error_handler; +use PHPUnit\Framework\Error\Deprecated; +use PHPUnit\Framework\Error\Error; +use PHPUnit\Framework\Error\Notice; +use PHPUnit\Framework\Error\Warning; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ErrorHandler +{ + /** + * @var bool + */ + private $convertDeprecationsToExceptions; + + /** + * @var bool + */ + private $convertErrorsToExceptions; + + /** + * @var bool + */ + private $convertNoticesToExceptions; + + /** + * @var bool + */ + private $convertWarningsToExceptions; + + /** + * @var bool + */ + private $registered = false; + + public static function invokeIgnoringWarnings(callable $callable) + { + set_error_handler( + static function ($errorNumber, $errorString) + { + if ($errorNumber === E_WARNING) { + return; + } + + return false; + } + ); + + $result = $callable(); + + restore_error_handler(); + + return $result; + } + + public function __construct(bool $convertDeprecationsToExceptions, bool $convertErrorsToExceptions, bool $convertNoticesToExceptions, bool $convertWarningsToExceptions) + { + $this->convertDeprecationsToExceptions = $convertDeprecationsToExceptions; + $this->convertErrorsToExceptions = $convertErrorsToExceptions; + $this->convertNoticesToExceptions = $convertNoticesToExceptions; + $this->convertWarningsToExceptions = $convertWarningsToExceptions; + } + + public function __invoke(int $errorNumber, string $errorString, string $errorFile, int $errorLine): bool + { + /* + * Do not raise an exception when the error suppression operator (@) was used. + * + * @see https://github.com/sebastianbergmann/phpunit/issues/3739 + */ + if (!($errorNumber & error_reporting())) { + return false; + } + + switch ($errorNumber) { + case E_NOTICE: + case E_USER_NOTICE: + case E_STRICT: + if (!$this->convertNoticesToExceptions) { + return false; + } + + throw new Notice($errorString, $errorNumber, $errorFile, $errorLine); + + case E_WARNING: + case E_USER_WARNING: + if (!$this->convertWarningsToExceptions) { + return false; + } + + throw new Warning($errorString, $errorNumber, $errorFile, $errorLine); + + case E_DEPRECATED: + case E_USER_DEPRECATED: + if (!$this->convertDeprecationsToExceptions) { + return false; + } + + throw new Deprecated($errorString, $errorNumber, $errorFile, $errorLine); + + default: + if (!$this->convertErrorsToExceptions) { + return false; + } + + throw new Error($errorString, $errorNumber, $errorFile, $errorLine); + } + } + + public function register(): void + { + if ($this->registered) { + return; + } + + $oldErrorHandler = set_error_handler($this); + + if ($oldErrorHandler !== null) { + restore_error_handler(); + + return; + } + + $this->registered = true; + } + + public function unregister(): void + { + if (!$this->registered) { + return; + } + + restore_error_handler(); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Exception.php b/vendor/phpunit/phpunit/src/Util/Exception.php new file mode 100644 index 00000000..6bcb3d14 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Exception.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use RuntimeException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Exception extends RuntimeException implements \PHPUnit\Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/Util/ExcludeList.php b/vendor/phpunit/phpunit/src/Util/ExcludeList.php new file mode 100644 index 00000000..778eb309 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/ExcludeList.php @@ -0,0 +1,236 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const DIRECTORY_SEPARATOR; +use function class_exists; +use function defined; +use function dirname; +use function is_dir; +use function realpath; +use function sprintf; +use function strpos; +use function sys_get_temp_dir; +use Composer\Autoload\ClassLoader; +use DeepCopy\DeepCopy; +use Doctrine\Instantiator\Instantiator; +use PharIo\Manifest\Manifest; +use PharIo\Version\Version as PharIoVersion; +use PhpParser\Parser; +use PHPUnit\Framework\TestCase; +use ReflectionClass; +use SebastianBergmann\CliParser\Parser as CliParser; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeUnit\CodeUnit; +use SebastianBergmann\CodeUnitReverseLookup\Wizard; +use SebastianBergmann\Comparator\Comparator; +use SebastianBergmann\Complexity\Calculator; +use SebastianBergmann\Diff\Diff; +use SebastianBergmann\Environment\Runtime; +use SebastianBergmann\Exporter\Exporter; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; +use SebastianBergmann\GlobalState\Snapshot; +use SebastianBergmann\Invoker\Invoker; +use SebastianBergmann\LinesOfCode\Counter; +use SebastianBergmann\ObjectEnumerator\Enumerator; +use SebastianBergmann\RecursionContext\Context; +use SebastianBergmann\ResourceOperations\ResourceOperations; +use SebastianBergmann\Template\Template; +use SebastianBergmann\Timer\Timer; +use SebastianBergmann\Type\TypeName; +use SebastianBergmann\Version; +use TheSeer\Tokenizer\Tokenizer; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ExcludeList +{ + /** + * @var array + */ + private const EXCLUDED_CLASS_NAMES = [ + // composer + ClassLoader::class => 1, + + // doctrine/instantiator + Instantiator::class => 1, + + // myclabs/deepcopy + DeepCopy::class => 1, + + // nikic/php-parser + Parser::class => 1, + + // phar-io/manifest + Manifest::class => 1, + + // phar-io/version + PharIoVersion::class => 1, + + // phpdocumentor/type-resolver + Type::class => 1, + + // phpunit/phpunit + TestCase::class => 2, + + // phpunit/php-code-coverage + CodeCoverage::class => 1, + + // phpunit/php-file-iterator + FileIteratorFacade::class => 1, + + // phpunit/php-invoker + Invoker::class => 1, + + // phpunit/php-text-template + Template::class => 1, + + // phpunit/php-timer + Timer::class => 1, + + // sebastian/cli-parser + CliParser::class => 1, + + // sebastian/code-unit + CodeUnit::class => 1, + + // sebastian/code-unit-reverse-lookup + Wizard::class => 1, + + // sebastian/comparator + Comparator::class => 1, + + // sebastian/complexity + Calculator::class => 1, + + // sebastian/diff + Diff::class => 1, + + // sebastian/environment + Runtime::class => 1, + + // sebastian/exporter + Exporter::class => 1, + + // sebastian/global-state + Snapshot::class => 1, + + // sebastian/lines-of-code + Counter::class => 1, + + // sebastian/object-enumerator + Enumerator::class => 1, + + // sebastian/recursion-context + Context::class => 1, + + // sebastian/resource-operations + ResourceOperations::class => 1, + + // sebastian/type + TypeName::class => 1, + + // sebastian/version + Version::class => 1, + + // theseer/tokenizer + Tokenizer::class => 1, + ]; + + /** + * @var string[] + */ + private static $directories = []; + + /** + * @var bool + */ + private static $initialized = false; + + public static function addDirectory(string $directory): void + { + if (!is_dir($directory)) { + throw new Exception( + sprintf( + '"%s" is not a directory', + $directory + ) + ); + } + + self::$directories[] = realpath($directory); + } + + /** + * @throws Exception + * + * @return string[] + */ + public function getExcludedDirectories(): array + { + $this->initialize(); + + return self::$directories; + } + + /** + * @throws Exception + */ + public function isExcluded(string $file): bool + { + if (defined('PHPUNIT_TESTSUITE')) { + return false; + } + + $this->initialize(); + + foreach (self::$directories as $directory) { + if (strpos($file, $directory) === 0) { + return true; + } + } + + return false; + } + + /** + * @throws Exception + */ + private function initialize(): void + { + if (self::$initialized) { + return; + } + + foreach (self::EXCLUDED_CLASS_NAMES as $className => $parent) { + if (!class_exists($className)) { + continue; + } + + $directory = (new ReflectionClass($className))->getFileName(); + + for ($i = 0; $i < $parent; $i++) { + $directory = dirname($directory); + } + + self::$directories[] = $directory; + } + + // Hide process isolation workaround on Windows. + if (DIRECTORY_SEPARATOR === '\\') { + // tempnam() prefix is limited to first 3 chars. + // @see https://php.net/manual/en/function.tempnam.php + self::$directories[] = sys_get_temp_dir() . '\\PHP'; + } + + self::$initialized = true; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/FileLoader.php b/vendor/phpunit/phpunit/src/Util/FileLoader.php new file mode 100644 index 00000000..8abdc91c --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/FileLoader.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const DIRECTORY_SEPARATOR; +use function array_diff; +use function array_keys; +use function fopen; +use function get_defined_vars; +use function sprintf; +use function stream_resolve_include_path; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class FileLoader +{ + /** + * Checks if a PHP sourcecode file is readable. The sourcecode file is loaded through the load() method. + * + * As a fallback, PHP looks in the directory of the file executing the stream_resolve_include_path function. + * We do not want to load the Test.php file here, so skip it if it found that. + * PHP prioritizes the include_path setting, so if the current directory is in there, it will first look in the + * current working directory. + * + * @throws Exception + */ + public static function checkAndLoad(string $filename): string + { + $includePathFilename = stream_resolve_include_path($filename); + + $localFile = __DIR__ . DIRECTORY_SEPARATOR . $filename; + + if (!$includePathFilename || + $includePathFilename === $localFile || + !self::isReadable($includePathFilename)) { + throw new Exception( + sprintf('Cannot open file "%s".' . "\n", $filename) + ); + } + + self::load($includePathFilename); + + return $includePathFilename; + } + + /** + * Loads a PHP sourcefile. + */ + public static function load(string $filename): void + { + $oldVariableNames = array_keys(get_defined_vars()); + + /** + * @noinspection PhpIncludeInspection + * + * @psalm-suppress UnresolvableInclude + */ + include_once $filename; + + $newVariables = get_defined_vars(); + + foreach (array_diff(array_keys($newVariables), $oldVariableNames) as $variableName) { + if ($variableName !== 'oldVariableNames') { + $GLOBALS[$variableName] = $newVariables[$variableName]; + } + } + } + + /** + * @see https://github.com/sebastianbergmann/phpunit/pull/2751 + */ + private static function isReadable(string $filename): bool + { + return @fopen($filename, 'r') !== false; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Filesystem.php b/vendor/phpunit/phpunit/src/Util/Filesystem.php new file mode 100644 index 00000000..35b2690b --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Filesystem.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const DIRECTORY_SEPARATOR; +use function is_dir; +use function mkdir; +use function str_replace; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Filesystem +{ + /** + * Maps class names to source file names. + * + * - PEAR CS: Foo_Bar_Baz -> Foo/Bar/Baz.php + * - Namespace: Foo\Bar\Baz -> Foo/Bar/Baz.php + */ + public static function classNameToFilename(string $className): string + { + return str_replace( + ['_', '\\'], + DIRECTORY_SEPARATOR, + $className + ) . '.php'; + } + + public static function createDirectory(string $directory): bool + { + return !(!is_dir($directory) && !@mkdir($directory, 0777, true) && !is_dir($directory)); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Filter.php b/vendor/phpunit/phpunit/src/Util/Filter.php new file mode 100644 index 00000000..42563937 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Filter.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use function array_unshift; +use function defined; +use function in_array; +use function is_file; +use function realpath; +use function sprintf; +use function strpos; +use PHPUnit\Framework\Exception; +use PHPUnit\Framework\SyntheticError; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Filter +{ + /** + * @throws Exception + */ + public static function getFilteredStacktrace(Throwable $t): string + { + $filteredStacktrace = ''; + + if ($t instanceof SyntheticError) { + $eTrace = $t->getSyntheticTrace(); + $eFile = $t->getSyntheticFile(); + $eLine = $t->getSyntheticLine(); + } elseif ($t instanceof Exception) { + $eTrace = $t->getSerializableTrace(); + $eFile = $t->getFile(); + $eLine = $t->getLine(); + } else { + if ($t->getPrevious()) { + $t = $t->getPrevious(); + } + + $eTrace = $t->getTrace(); + $eFile = $t->getFile(); + $eLine = $t->getLine(); + } + + if (!self::frameExists($eTrace, $eFile, $eLine)) { + array_unshift( + $eTrace, + ['file' => $eFile, 'line' => $eLine] + ); + } + + $prefix = defined('__PHPUNIT_PHAR_ROOT__') ? __PHPUNIT_PHAR_ROOT__ : false; + $excludeList = new ExcludeList; + + foreach ($eTrace as $frame) { + if (self::shouldPrintFrame($frame, $prefix, $excludeList)) { + $filteredStacktrace .= sprintf( + "%s:%s\n", + $frame['file'], + $frame['line'] ?? '?' + ); + } + } + + return $filteredStacktrace; + } + + private static function shouldPrintFrame(array $frame, $prefix, ExcludeList $excludeList): bool + { + if (!isset($frame['file'])) { + return false; + } + + $file = $frame['file']; + $fileIsNotPrefixed = $prefix === false || strpos($file, $prefix) !== 0; + + // @see https://github.com/sebastianbergmann/phpunit/issues/4033 + if (isset($GLOBALS['_SERVER']['SCRIPT_NAME'])) { + $script = realpath($GLOBALS['_SERVER']['SCRIPT_NAME']); + } else { + $script = ''; + } + + return is_file($file) && + self::fileIsExcluded($file, $excludeList) && + $fileIsNotPrefixed && + $file !== $script; + } + + private static function fileIsExcluded(string $file, ExcludeList $excludeList): bool + { + return (empty($GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST']) || + !in_array($file, $GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST'], true)) && + !$excludeList->isExcluded($file); + } + + private static function frameExists(array $trace, string $file, int $line): bool + { + foreach ($trace as $frame) { + if (isset($frame['file'], $frame['line']) && $frame['file'] === $file && $frame['line'] === $line) { + return true; + } + } + + return false; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/GlobalState.php b/vendor/phpunit/phpunit/src/Util/GlobalState.php new file mode 100644 index 00000000..cc5c2228 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/GlobalState.php @@ -0,0 +1,203 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use function array_keys; +use function array_reverse; +use function array_shift; +use function defined; +use function get_defined_constants; +use function get_included_files; +use function in_array; +use function ini_get_all; +use function is_array; +use function is_file; +use function is_scalar; +use function preg_match; +use function serialize; +use function sprintf; +use function strpos; +use function strtr; +use function substr; +use function var_export; +use Closure; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class GlobalState +{ + /** + * @var string[] + */ + private const SUPER_GLOBAL_ARRAYS = [ + '_ENV', + '_POST', + '_GET', + '_COOKIE', + '_SERVER', + '_FILES', + '_REQUEST', + ]; + + /** + * @throws Exception + */ + public static function getIncludedFilesAsString(): string + { + return self::processIncludedFilesAsString(get_included_files()); + } + + /** + * @param string[] $files + * + * @throws Exception + */ + public static function processIncludedFilesAsString(array $files): string + { + $excludeList = new ExcludeList; + $prefix = false; + $result = ''; + + if (defined('__PHPUNIT_PHAR__')) { + $prefix = 'phar://' . __PHPUNIT_PHAR__ . '/'; + } + + // Do not process bootstrap script + array_shift($files); + + // If bootstrap script was a Composer bin proxy, skip the second entry as well + if (substr(strtr($files[0], '\\', '/'), -24) === '/phpunit/phpunit/phpunit') { + array_shift($files); + } + + foreach (array_reverse($files) as $file) { + if (!empty($GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST']) && + in_array($file, $GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST'], true)) { + continue; + } + + if ($prefix !== false && strpos($file, $prefix) === 0) { + continue; + } + + // Skip virtual file system protocols + if (preg_match('/^(vfs|phpvfs[a-z0-9]+):/', $file)) { + continue; + } + + if (!$excludeList->isExcluded($file) && is_file($file)) { + $result = 'require_once \'' . $file . "';\n" . $result; + } + } + + return $result; + } + + public static function getIniSettingsAsString(): string + { + $result = ''; + + foreach (ini_get_all(null, false) as $key => $value) { + $result .= sprintf( + '@ini_set(%s, %s);' . "\n", + self::exportVariable($key), + self::exportVariable((string) $value) + ); + } + + return $result; + } + + public static function getConstantsAsString(): string + { + $constants = get_defined_constants(true); + $result = ''; + + if (isset($constants['user'])) { + foreach ($constants['user'] as $name => $value) { + $result .= sprintf( + 'if (!defined(\'%s\')) define(\'%s\', %s);' . "\n", + $name, + $name, + self::exportVariable($value) + ); + } + } + + return $result; + } + + public static function getGlobalsAsString(): string + { + $result = ''; + + foreach (self::SUPER_GLOBAL_ARRAYS as $superGlobalArray) { + if (isset($GLOBALS[$superGlobalArray]) && is_array($GLOBALS[$superGlobalArray])) { + foreach (array_keys($GLOBALS[$superGlobalArray]) as $key) { + if ($GLOBALS[$superGlobalArray][$key] instanceof Closure) { + continue; + } + + $result .= sprintf( + '$GLOBALS[\'%s\'][\'%s\'] = %s;' . "\n", + $superGlobalArray, + $key, + self::exportVariable($GLOBALS[$superGlobalArray][$key]) + ); + } + } + } + + $excludeList = self::SUPER_GLOBAL_ARRAYS; + $excludeList[] = 'GLOBALS'; + + foreach (array_keys($GLOBALS) as $key) { + if (!$GLOBALS[$key] instanceof Closure && !in_array($key, $excludeList, true)) { + $result .= sprintf( + '$GLOBALS[\'%s\'] = %s;' . "\n", + $key, + self::exportVariable($GLOBALS[$key]) + ); + } + } + + return $result; + } + + private static function exportVariable($variable): string + { + if (is_scalar($variable) || $variable === null || + (is_array($variable) && self::arrayOnlyContainsScalars($variable))) { + return var_export($variable, true); + } + + return 'unserialize(' . var_export(serialize($variable), true) . ')'; + } + + private static function arrayOnlyContainsScalars(array $array): bool + { + $result = true; + + foreach ($array as $element) { + if (is_array($element)) { + $result = self::arrayOnlyContainsScalars($element); + } elseif (!is_scalar($element) && $element !== null) { + $result = false; + } + + if (!$result) { + break; + } + } + + return $result; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/InvalidDataSetException.php b/vendor/phpunit/phpunit/src/Util/InvalidDataSetException.php new file mode 100644 index 00000000..3493d113 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/InvalidDataSetException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use RuntimeException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidDataSetException extends RuntimeException implements \PHPUnit\Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/Util/Json.php b/vendor/phpunit/phpunit/src/Util/Json.php new file mode 100644 index 00000000..752c1fd6 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Json.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const JSON_PRETTY_PRINT; +use const JSON_UNESCAPED_SLASHES; +use const JSON_UNESCAPED_UNICODE; +use function count; +use function is_array; +use function is_object; +use function json_decode; +use function json_encode; +use function json_last_error; +use function ksort; +use PHPUnit\Framework\Exception; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Json +{ + /** + * Prettify json string. + * + * @throws \PHPUnit\Framework\Exception + */ + public static function prettify(string $json): string + { + $decodedJson = json_decode($json, false); + + if (json_last_error()) { + throw new Exception( + 'Cannot prettify invalid json' + ); + } + + return json_encode($decodedJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } + + /** + * To allow comparison of JSON strings, first process them into a consistent + * format so that they can be compared as strings. + * + * @return array ($error, $canonicalized_json) The $error parameter is used + * to indicate an error decoding the json. This is used to avoid ambiguity + * with JSON strings consisting entirely of 'null' or 'false'. + */ + public static function canonicalize(string $json): array + { + $decodedJson = json_decode($json); + + if (json_last_error()) { + return [true, null]; + } + + self::recursiveSort($decodedJson); + + $reencodedJson = json_encode($decodedJson); + + return [false, $reencodedJson]; + } + + /** + * JSON object keys are unordered while PHP array keys are ordered. + * + * Sort all array keys to ensure both the expected and actual values have + * their keys in the same order. + */ + private static function recursiveSort(&$json): void + { + if (!is_array($json)) { + // If the object is not empty, change it to an associative array + // so we can sort the keys (and we will still re-encode it + // correctly, since PHP encodes associative arrays as JSON objects.) + // But EMPTY objects MUST remain empty objects. (Otherwise we will + // re-encode it as a JSON array rather than a JSON object.) + // See #2919. + if (is_object($json) && count((array) $json) > 0) { + $json = (array) $json; + } else { + return; + } + } + + ksort($json); + + foreach ($json as $key => &$value) { + self::recursiveSort($value); + } + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Log/JUnit.php b/vendor/phpunit/phpunit/src/Util/Log/JUnit.php new file mode 100644 index 00000000..3ceb5e84 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Log/JUnit.php @@ -0,0 +1,424 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Log; + +use function class_exists; +use function get_class; +use function method_exists; +use function sprintf; +use function str_replace; +use function trim; +use DOMDocument; +use DOMElement; +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\ExceptionWrapper; +use PHPUnit\Framework\SelfDescribing; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestFailure; +use PHPUnit\Framework\TestListener; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Framework\Warning; +use PHPUnit\Util\Exception; +use PHPUnit\Util\Filter; +use PHPUnit\Util\Printer; +use PHPUnit\Util\Xml; +use ReflectionClass; +use ReflectionException; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class JUnit extends Printer implements TestListener +{ + /** + * @var DOMDocument + */ + private $document; + + /** + * @var DOMElement + */ + private $root; + + /** + * @var bool + */ + private $reportRiskyTests = false; + + /** + * @var DOMElement[] + */ + private $testSuites = []; + + /** + * @var int[] + */ + private $testSuiteTests = [0]; + + /** + * @var int[] + */ + private $testSuiteAssertions = [0]; + + /** + * @var int[] + */ + private $testSuiteErrors = [0]; + + /** + * @var int[] + */ + private $testSuiteWarnings = [0]; + + /** + * @var int[] + */ + private $testSuiteFailures = [0]; + + /** + * @var int[] + */ + private $testSuiteSkipped = [0]; + + /** + * @var int[] + */ + private $testSuiteTimes = [0]; + + /** + * @var int + */ + private $testSuiteLevel = 0; + + /** + * @var DOMElement + */ + private $currentTestCase; + + /** + * @param null|mixed $out + */ + public function __construct($out = null, bool $reportRiskyTests = false) + { + $this->document = new DOMDocument('1.0', 'UTF-8'); + $this->document->formatOutput = true; + + $this->root = $this->document->createElement('testsuites'); + $this->document->appendChild($this->root); + + parent::__construct($out); + + $this->reportRiskyTests = $reportRiskyTests; + } + + /** + * Flush buffer and close output. + */ + public function flush(): void + { + $this->write($this->getXML()); + + parent::flush(); + } + + /** + * An error occurred. + */ + public function addError(Test $test, Throwable $t, float $time): void + { + $this->doAddFault($test, $t, 'error'); + $this->testSuiteErrors[$this->testSuiteLevel]++; + } + + /** + * A warning occurred. + */ + public function addWarning(Test $test, Warning $e, float $time): void + { + $this->doAddFault($test, $e, 'warning'); + $this->testSuiteWarnings[$this->testSuiteLevel]++; + } + + /** + * A failure occurred. + */ + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + $this->doAddFault($test, $e, 'failure'); + $this->testSuiteFailures[$this->testSuiteLevel]++; + } + + /** + * Incomplete test. + */ + public function addIncompleteTest(Test $test, Throwable $t, float $time): void + { + $this->doAddSkipped(); + } + + /** + * Risky test. + */ + public function addRiskyTest(Test $test, Throwable $t, float $time): void + { + if (!$this->reportRiskyTests) { + return; + } + + $this->doAddFault($test, $t, 'error'); + $this->testSuiteErrors[$this->testSuiteLevel]++; + } + + /** + * Skipped test. + */ + public function addSkippedTest(Test $test, Throwable $t, float $time): void + { + $this->doAddSkipped(); + } + + /** + * A testsuite started. + */ + public function startTestSuite(TestSuite $suite): void + { + $testSuite = $this->document->createElement('testsuite'); + $testSuite->setAttribute('name', $suite->getName()); + + if (class_exists($suite->getName(), false)) { + try { + $class = new ReflectionClass($suite->getName()); + + $testSuite->setAttribute('file', $class->getFileName()); + } catch (ReflectionException $e) { + } + } + + if ($this->testSuiteLevel > 0) { + $this->testSuites[$this->testSuiteLevel]->appendChild($testSuite); + } else { + $this->root->appendChild($testSuite); + } + + $this->testSuiteLevel++; + $this->testSuites[$this->testSuiteLevel] = $testSuite; + $this->testSuiteTests[$this->testSuiteLevel] = 0; + $this->testSuiteAssertions[$this->testSuiteLevel] = 0; + $this->testSuiteErrors[$this->testSuiteLevel] = 0; + $this->testSuiteWarnings[$this->testSuiteLevel] = 0; + $this->testSuiteFailures[$this->testSuiteLevel] = 0; + $this->testSuiteSkipped[$this->testSuiteLevel] = 0; + $this->testSuiteTimes[$this->testSuiteLevel] = 0; + } + + /** + * A testsuite ended. + */ + public function endTestSuite(TestSuite $suite): void + { + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'tests', + (string) $this->testSuiteTests[$this->testSuiteLevel] + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'assertions', + (string) $this->testSuiteAssertions[$this->testSuiteLevel] + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'errors', + (string) $this->testSuiteErrors[$this->testSuiteLevel] + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'warnings', + (string) $this->testSuiteWarnings[$this->testSuiteLevel] + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'failures', + (string) $this->testSuiteFailures[$this->testSuiteLevel] + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'skipped', + (string) $this->testSuiteSkipped[$this->testSuiteLevel] + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'time', + sprintf('%F', $this->testSuiteTimes[$this->testSuiteLevel]) + ); + + if ($this->testSuiteLevel > 1) { + $this->testSuiteTests[$this->testSuiteLevel - 1] += $this->testSuiteTests[$this->testSuiteLevel]; + $this->testSuiteAssertions[$this->testSuiteLevel - 1] += $this->testSuiteAssertions[$this->testSuiteLevel]; + $this->testSuiteErrors[$this->testSuiteLevel - 1] += $this->testSuiteErrors[$this->testSuiteLevel]; + $this->testSuiteWarnings[$this->testSuiteLevel - 1] += $this->testSuiteWarnings[$this->testSuiteLevel]; + $this->testSuiteFailures[$this->testSuiteLevel - 1] += $this->testSuiteFailures[$this->testSuiteLevel]; + $this->testSuiteSkipped[$this->testSuiteLevel - 1] += $this->testSuiteSkipped[$this->testSuiteLevel]; + $this->testSuiteTimes[$this->testSuiteLevel - 1] += $this->testSuiteTimes[$this->testSuiteLevel]; + } + + $this->testSuiteLevel--; + } + + /** + * A test started. + */ + public function startTest(Test $test): void + { + $usesDataprovider = false; + + if (method_exists($test, 'usesDataProvider')) { + $usesDataprovider = $test->usesDataProvider(); + } + + $testCase = $this->document->createElement('testcase'); + $testCase->setAttribute('name', $test->getName()); + + try { + $class = new ReflectionClass($test); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + $methodName = $test->getName(!$usesDataprovider); + + if ($class->hasMethod($methodName)) { + try { + $method = $class->getMethod($methodName); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + $testCase->setAttribute('class', $class->getName()); + $testCase->setAttribute('classname', str_replace('\\', '.', $class->getName())); + $testCase->setAttribute('file', $class->getFileName()); + $testCase->setAttribute('line', (string) $method->getStartLine()); + } + + $this->currentTestCase = $testCase; + } + + /** + * A test ended. + */ + public function endTest(Test $test, float $time): void + { + $numAssertions = 0; + + if (method_exists($test, 'getNumAssertions')) { + $numAssertions = $test->getNumAssertions(); + } + + $this->testSuiteAssertions[$this->testSuiteLevel] += $numAssertions; + + $this->currentTestCase->setAttribute( + 'assertions', + (string) $numAssertions + ); + + $this->currentTestCase->setAttribute( + 'time', + sprintf('%F', $time) + ); + + $this->testSuites[$this->testSuiteLevel]->appendChild( + $this->currentTestCase + ); + + $this->testSuiteTests[$this->testSuiteLevel]++; + $this->testSuiteTimes[$this->testSuiteLevel] += $time; + + $testOutput = ''; + + if (method_exists($test, 'hasOutput') && method_exists($test, 'getActualOutput')) { + $testOutput = $test->hasOutput() ? $test->getActualOutput() : ''; + } + + if (!empty($testOutput)) { + $systemOut = $this->document->createElement( + 'system-out', + Xml::prepareString($testOutput) + ); + + $this->currentTestCase->appendChild($systemOut); + } + + $this->currentTestCase = null; + } + + /** + * Returns the XML as a string. + */ + public function getXML(): string + { + return $this->document->saveXML(); + } + + private function doAddFault(Test $test, Throwable $t, string $type): void + { + if ($this->currentTestCase === null) { + return; + } + + if ($test instanceof SelfDescribing) { + $buffer = $test->toString() . "\n"; + } else { + $buffer = ''; + } + + $buffer .= trim( + TestFailure::exceptionToString($t) . "\n" . + Filter::getFilteredStacktrace($t) + ); + + $fault = $this->document->createElement( + $type, + Xml::prepareString($buffer) + ); + + if ($t instanceof ExceptionWrapper) { + $fault->setAttribute('type', $t->getClassName()); + } else { + $fault->setAttribute('type', get_class($t)); + } + + $this->currentTestCase->appendChild($fault); + } + + private function doAddSkipped(): void + { + if ($this->currentTestCase === null) { + return; + } + + $skipped = $this->document->createElement('skipped'); + + $this->currentTestCase->appendChild($skipped); + + $this->testSuiteSkipped[$this->testSuiteLevel]++; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Log/TeamCity.php b/vendor/phpunit/phpunit/src/Util/Log/TeamCity.php new file mode 100644 index 00000000..0efe3438 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Log/TeamCity.php @@ -0,0 +1,383 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Log; + +use function class_exists; +use function count; +use function explode; +use function get_class; +use function getmypid; +use function ini_get; +use function is_bool; +use function is_scalar; +use function method_exists; +use function print_r; +use function round; +use function str_replace; +use function stripos; +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\ExceptionWrapper; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestFailure; +use PHPUnit\Framework\TestResult; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Framework\Warning; +use PHPUnit\TextUI\DefaultResultPrinter; +use PHPUnit\Util\Exception; +use PHPUnit\Util\Filter; +use ReflectionClass; +use ReflectionException; +use SebastianBergmann\Comparator\ComparisonFailure; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TeamCity extends DefaultResultPrinter +{ + /** + * @var bool + */ + private $isSummaryTestCountPrinted = false; + + /** + * @var string + */ + private $startedTestName; + + /** + * @var false|int + */ + private $flowId; + + public function printResult(TestResult $result): void + { + $this->printHeader($result); + $this->printFooter($result); + } + + /** + * An error occurred. + */ + public function addError(Test $test, Throwable $t, float $time): void + { + $this->printEvent( + 'testFailed', + [ + 'name' => $test->getName(), + 'message' => self::getMessage($t), + 'details' => self::getDetails($t), + 'duration' => self::toMilliseconds($time), + ] + ); + } + + /** + * A warning occurred. + */ + public function addWarning(Test $test, Warning $e, float $time): void + { + $this->write(self::getMessage($e) . PHP_EOL); + } + + /** + * A failure occurred. + */ + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + $parameters = [ + 'name' => $test->getName(), + 'message' => self::getMessage($e), + 'details' => self::getDetails($e), + 'duration' => self::toMilliseconds($time), + ]; + + if ($e instanceof ExpectationFailedException) { + $comparisonFailure = $e->getComparisonFailure(); + + if ($comparisonFailure instanceof ComparisonFailure) { + $expectedString = $comparisonFailure->getExpectedAsString(); + + if ($expectedString === null || empty($expectedString)) { + $expectedString = self::getPrimitiveValueAsString($comparisonFailure->getExpected()); + } + + $actualString = $comparisonFailure->getActualAsString(); + + if ($actualString === null || empty($actualString)) { + $actualString = self::getPrimitiveValueAsString($comparisonFailure->getActual()); + } + + if ($actualString !== null && $expectedString !== null) { + $parameters['type'] = 'comparisonFailure'; + $parameters['actual'] = $actualString; + $parameters['expected'] = $expectedString; + } + } + } + + $this->printEvent('testFailed', $parameters); + } + + /** + * Incomplete test. + */ + public function addIncompleteTest(Test $test, Throwable $t, float $time): void + { + $this->printIgnoredTest($test->getName(), $t, $time); + } + + /** + * Risky test. + */ + public function addRiskyTest(Test $test, Throwable $t, float $time): void + { + $this->addError($test, $t, $time); + } + + /** + * Skipped test. + */ + public function addSkippedTest(Test $test, Throwable $t, float $time): void + { + $testName = $test->getName(); + + if ($this->startedTestName !== $testName) { + $this->startTest($test); + $this->printIgnoredTest($testName, $t, $time); + $this->endTest($test, $time); + } else { + $this->printIgnoredTest($testName, $t, $time); + } + } + + public function printIgnoredTest(string $testName, Throwable $t, float $time): void + { + $this->printEvent( + 'testIgnored', + [ + 'name' => $testName, + 'message' => self::getMessage($t), + 'details' => self::getDetails($t), + 'duration' => self::toMilliseconds($time), + ] + ); + } + + /** + * A testsuite started. + */ + public function startTestSuite(TestSuite $suite): void + { + if (stripos(ini_get('disable_functions'), 'getmypid') === false) { + $this->flowId = getmypid(); + } else { + $this->flowId = false; + } + + if (!$this->isSummaryTestCountPrinted) { + $this->isSummaryTestCountPrinted = true; + + $this->printEvent( + 'testCount', + ['count' => count($suite)] + ); + } + + $suiteName = $suite->getName(); + + if (empty($suiteName)) { + return; + } + + $parameters = ['name' => $suiteName]; + + if (class_exists($suiteName, false)) { + $fileName = self::getFileName($suiteName); + $parameters['locationHint'] = "php_qn://{$fileName}::\\{$suiteName}"; + } else { + $split = explode('::', $suiteName); + + if (count($split) === 2 && class_exists($split[0]) && method_exists($split[0], $split[1])) { + $fileName = self::getFileName($split[0]); + $parameters['locationHint'] = "php_qn://{$fileName}::\\{$suiteName}"; + $parameters['name'] = $split[1]; + } + } + + $this->printEvent('testSuiteStarted', $parameters); + } + + /** + * A testsuite ended. + */ + public function endTestSuite(TestSuite $suite): void + { + $suiteName = $suite->getName(); + + if (empty($suiteName)) { + return; + } + + $parameters = ['name' => $suiteName]; + + if (!class_exists($suiteName, false)) { + $split = explode('::', $suiteName); + + if (count($split) === 2 && class_exists($split[0]) && method_exists($split[0], $split[1])) { + $parameters['name'] = $split[1]; + } + } + + $this->printEvent('testSuiteFinished', $parameters); + } + + /** + * A test started. + */ + public function startTest(Test $test): void + { + $testName = $test->getName(); + $this->startedTestName = $testName; + $params = ['name' => $testName]; + + if ($test instanceof TestCase) { + $className = get_class($test); + $fileName = self::getFileName($className); + $params['locationHint'] = "php_qn://{$fileName}::\\{$className}::{$testName}"; + } + + $this->printEvent('testStarted', $params); + } + + /** + * A test ended. + */ + public function endTest(Test $test, float $time): void + { + parent::endTest($test, $time); + + $this->printEvent( + 'testFinished', + [ + 'name' => $test->getName(), + 'duration' => self::toMilliseconds($time), + ] + ); + } + + protected function writeProgress(string $progress): void + { + } + + private function printEvent(string $eventName, array $params = []): void + { + $this->write("\n##teamcity[{$eventName}"); + + if ($this->flowId) { + $params['flowId'] = $this->flowId; + } + + foreach ($params as $key => $value) { + $escapedValue = self::escapeValue((string) $value); + $this->write(" {$key}='{$escapedValue}'"); + } + + $this->write("]\n"); + } + + private static function getMessage(Throwable $t): string + { + $message = ''; + + if ($t instanceof ExceptionWrapper) { + if ($t->getClassName() !== '') { + $message .= $t->getClassName(); + } + + if ($message !== '' && $t->getMessage() !== '') { + $message .= ' : '; + } + } + + return $message . $t->getMessage(); + } + + private static function getDetails(Throwable $t): string + { + $stackTrace = Filter::getFilteredStacktrace($t); + $previous = $t instanceof ExceptionWrapper ? $t->getPreviousWrapped() : $t->getPrevious(); + + while ($previous) { + $stackTrace .= "\nCaused by\n" . + TestFailure::exceptionToString($previous) . "\n" . + Filter::getFilteredStacktrace($previous); + + $previous = $previous instanceof ExceptionWrapper ? + $previous->getPreviousWrapped() : $previous->getPrevious(); + } + + return ' ' . str_replace("\n", "\n ", $stackTrace); + } + + private static function getPrimitiveValueAsString($value): ?string + { + if ($value === null) { + return 'null'; + } + + if (is_bool($value)) { + return $value ? 'true' : 'false'; + } + + if (is_scalar($value)) { + return print_r($value, true); + } + + return null; + } + + private static function escapeValue(string $text): string + { + return str_replace( + ['|', "'", "\n", "\r", ']', '['], + ['||', "|'", '|n', '|r', '|]', '|['], + $text + ); + } + + /** + * @param string $className + */ + private static function getFileName($className): string + { + try { + return (new ReflectionClass($className))->getFileName(); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @param float $time microseconds + */ + private static function toMilliseconds(float $time): int + { + return (int) round($time * 1000); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php b/vendor/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php new file mode 100644 index 00000000..8706ae1a --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php @@ -0,0 +1,416 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\PHP; + +use const DIRECTORY_SEPARATOR; +use const PHP_SAPI; +use function array_keys; +use function array_merge; +use function assert; +use function escapeshellarg; +use function ini_get_all; +use function restore_error_handler; +use function set_error_handler; +use function sprintf; +use function str_replace; +use function strpos; +use function strrpos; +use function substr; +use function trim; +use function unserialize; +use __PHP_Incomplete_Class; +use ErrorException; +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\Exception; +use PHPUnit\Framework\SyntheticError; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestFailure; +use PHPUnit\Framework\TestResult; +use SebastianBergmann\Environment\Runtime; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class AbstractPhpProcess +{ + /** + * @var Runtime + */ + protected $runtime; + + /** + * @var bool + */ + protected $stderrRedirection = false; + + /** + * @var string + */ + protected $stdin = ''; + + /** + * @var string + */ + protected $args = ''; + + /** + * @var array + */ + protected $env = []; + + /** + * @var int + */ + protected $timeout = 0; + + public static function factory(): self + { + if (DIRECTORY_SEPARATOR === '\\') { + return new WindowsPhpProcess; + } + + return new DefaultPhpProcess; + } + + public function __construct() + { + $this->runtime = new Runtime; + } + + /** + * Defines if should use STDERR redirection or not. + * + * Then $stderrRedirection is TRUE, STDERR is redirected to STDOUT. + */ + public function setUseStderrRedirection(bool $stderrRedirection): void + { + $this->stderrRedirection = $stderrRedirection; + } + + /** + * Returns TRUE if uses STDERR redirection or FALSE if not. + */ + public function useStderrRedirection(): bool + { + return $this->stderrRedirection; + } + + /** + * Sets the input string to be sent via STDIN. + */ + public function setStdin(string $stdin): void + { + $this->stdin = $stdin; + } + + /** + * Returns the input string to be sent via STDIN. + */ + public function getStdin(): string + { + return $this->stdin; + } + + /** + * Sets the string of arguments to pass to the php job. + */ + public function setArgs(string $args): void + { + $this->args = $args; + } + + /** + * Returns the string of arguments to pass to the php job. + */ + public function getArgs(): string + { + return $this->args; + } + + /** + * Sets the array of environment variables to start the child process with. + * + * @param array $env + */ + public function setEnv(array $env): void + { + $this->env = $env; + } + + /** + * Returns the array of environment variables to start the child process with. + */ + public function getEnv(): array + { + return $this->env; + } + + /** + * Sets the amount of seconds to wait before timing out. + */ + public function setTimeout(int $timeout): void + { + $this->timeout = $timeout; + } + + /** + * Returns the amount of seconds to wait before timing out. + */ + public function getTimeout(): int + { + return $this->timeout; + } + + /** + * Runs a single test in a separate PHP process. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function runTestJob(string $job, Test $test, TestResult $result): void + { + $result->startTest($test); + + $_result = $this->runJob($job); + + $this->processChildResult( + $test, + $result, + $_result['stdout'], + $_result['stderr'] + ); + } + + /** + * Returns the command based into the configurations. + */ + public function getCommand(array $settings, string $file = null): string + { + $command = $this->runtime->getBinary(); + + if ($this->runtime->hasPCOV()) { + $settings = array_merge( + $settings, + $this->runtime->getCurrentSettings( + array_keys(ini_get_all('pcov')) + ) + ); + } elseif ($this->runtime->hasXdebug()) { + $settings = array_merge( + $settings, + $this->runtime->getCurrentSettings( + array_keys(ini_get_all('xdebug')) + ) + ); + } + + $command .= $this->settingsToParameters($settings); + + if (PHP_SAPI === 'phpdbg') { + $command .= ' -qrr'; + + if (!$file) { + $command .= 's='; + } + } + + if ($file) { + $command .= ' ' . escapeshellarg($file); + } + + if ($this->args) { + if (!$file) { + $command .= ' --'; + } + $command .= ' ' . $this->args; + } + + if ($this->stderrRedirection) { + $command .= ' 2>&1'; + } + + return $command; + } + + /** + * Runs a single job (PHP code) using a separate PHP process. + */ + abstract public function runJob(string $job, array $settings = []): array; + + protected function settingsToParameters(array $settings): string + { + $buffer = ''; + + foreach ($settings as $setting) { + $buffer .= ' -d ' . escapeshellarg($setting); + } + + return $buffer; + } + + /** + * Processes the TestResult object from an isolated process. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + private function processChildResult(Test $test, TestResult $result, string $stdout, string $stderr): void + { + $time = 0; + + if (!empty($stderr)) { + $result->addError( + $test, + new Exception(trim($stderr)), + $time + ); + } else { + set_error_handler( + /** + * @throws ErrorException + */ + static function ($errno, $errstr, $errfile, $errline): void + { + throw new ErrorException($errstr, $errno, $errno, $errfile, $errline); + } + ); + + try { + if (strpos($stdout, "#!/usr/bin/env php\n") === 0) { + $stdout = substr($stdout, 19); + } + + $childResult = unserialize(str_replace("#!/usr/bin/env php\n", '', $stdout)); + restore_error_handler(); + + if ($childResult === false) { + $result->addFailure( + $test, + new AssertionFailedError('Test was run in child process and ended unexpectedly'), + $time + ); + } + } catch (ErrorException $e) { + restore_error_handler(); + $childResult = false; + + $result->addError( + $test, + new Exception(trim($stdout), 0, $e), + $time + ); + } + + if ($childResult !== false) { + if (!empty($childResult['output'])) { + $output = $childResult['output']; + } + + /* @var TestCase $test */ + + $test->setResult($childResult['testResult']); + $test->addToAssertionCount($childResult['numAssertions']); + + $childResult = $childResult['result']; + assert($childResult instanceof TestResult); + + if ($result->getCollectCodeCoverageInformation()) { + $result->getCodeCoverage()->merge( + $childResult->getCodeCoverage() + ); + } + + $time = $childResult->time(); + $notImplemented = $childResult->notImplemented(); + $risky = $childResult->risky(); + $skipped = $childResult->skipped(); + $errors = $childResult->errors(); + $warnings = $childResult->warnings(); + $failures = $childResult->failures(); + + if (!empty($notImplemented)) { + $result->addError( + $test, + $this->getException($notImplemented[0]), + $time + ); + } elseif (!empty($risky)) { + $result->addError( + $test, + $this->getException($risky[0]), + $time + ); + } elseif (!empty($skipped)) { + $result->addError( + $test, + $this->getException($skipped[0]), + $time + ); + } elseif (!empty($errors)) { + $result->addError( + $test, + $this->getException($errors[0]), + $time + ); + } elseif (!empty($warnings)) { + $result->addWarning( + $test, + $this->getException($warnings[0]), + $time + ); + } elseif (!empty($failures)) { + $result->addFailure( + $test, + $this->getException($failures[0]), + $time + ); + } + } + } + + $result->endTest($test, $time); + + if (!empty($output)) { + print $output; + } + } + + /** + * Gets the thrown exception from a PHPUnit\Framework\TestFailure. + * + * @see https://github.com/sebastianbergmann/phpunit/issues/74 + */ + private function getException(TestFailure $error): Exception + { + $exception = $error->thrownException(); + + if ($exception instanceof __PHP_Incomplete_Class) { + $exceptionArray = []; + + foreach ((array) $exception as $key => $value) { + $key = substr($key, strrpos($key, "\0") + 1); + $exceptionArray[$key] = $value; + } + + $exception = new SyntheticError( + sprintf( + '%s: %s', + $exceptionArray['_PHP_Incomplete_Class_Name'], + $exceptionArray['message'] + ), + $exceptionArray['code'], + $exceptionArray['file'], + $exceptionArray['line'], + $exceptionArray['trace'] + ); + } + + return $exception; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php b/vendor/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php new file mode 100644 index 00000000..c4dc1114 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php @@ -0,0 +1,236 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\PHP; + +use function array_merge; +use function fclose; +use function file_put_contents; +use function fread; +use function fwrite; +use function is_array; +use function is_resource; +use function proc_close; +use function proc_open; +use function proc_terminate; +use function rewind; +use function sprintf; +use function stream_get_contents; +use function stream_select; +use function sys_get_temp_dir; +use function tempnam; +use function unlink; +use PHPUnit\Framework\Exception; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class DefaultPhpProcess extends AbstractPhpProcess +{ + /** + * @var string + */ + protected $tempFile; + + /** + * Runs a single job (PHP code) using a separate PHP process. + * + * @throws Exception + */ + public function runJob(string $job, array $settings = []): array + { + if ($this->stdin || $this->useTemporaryFile()) { + if (!($this->tempFile = tempnam(sys_get_temp_dir(), 'PHPUnit')) || + file_put_contents($this->tempFile, $job) === false) { + throw new Exception( + 'Unable to write temporary file' + ); + } + + $job = $this->stdin; + } + + return $this->runProcess($job, $settings); + } + + /** + * Returns an array of file handles to be used in place of pipes. + */ + protected function getHandles(): array + { + return []; + } + + /** + * Handles creating the child process and returning the STDOUT and STDERR. + * + * @throws Exception + */ + protected function runProcess(string $job, array $settings): array + { + $handles = $this->getHandles(); + + $env = null; + + if ($this->env) { + $env = $_SERVER ?? []; + unset($env['argv'], $env['argc']); + $env = array_merge($env, $this->env); + + foreach ($env as $envKey => $envVar) { + if (is_array($envVar)) { + unset($env[$envKey]); + } + } + } + + $pipeSpec = [ + 0 => $handles[0] ?? ['pipe', 'r'], + 1 => $handles[1] ?? ['pipe', 'w'], + 2 => $handles[2] ?? ['pipe', 'w'], + ]; + + $process = proc_open( + $this->getCommand($settings, $this->tempFile), + $pipeSpec, + $pipes, + null, + $env + ); + + if (!is_resource($process)) { + throw new Exception( + 'Unable to spawn worker process' + ); + } + + if ($job) { + $this->process($pipes[0], $job); + } + + fclose($pipes[0]); + + $stderr = $stdout = ''; + + if ($this->timeout) { + unset($pipes[0]); + + while (true) { + $r = $pipes; + $w = null; + $e = null; + + $n = @stream_select($r, $w, $e, $this->timeout); + + if ($n === false) { + break; + } + + if ($n === 0) { + proc_terminate($process, 9); + + throw new Exception( + sprintf( + 'Job execution aborted after %d seconds', + $this->timeout + ) + ); + } + + if ($n > 0) { + foreach ($r as $pipe) { + $pipeOffset = 0; + + foreach ($pipes as $i => $origPipe) { + if ($pipe === $origPipe) { + $pipeOffset = $i; + + break; + } + } + + if (!$pipeOffset) { + break; + } + + $line = fread($pipe, 8192); + + if ($line === '' || $line === false) { + fclose($pipes[$pipeOffset]); + + unset($pipes[$pipeOffset]); + } elseif ($pipeOffset === 1) { + $stdout .= $line; + } else { + $stderr .= $line; + } + } + + if (empty($pipes)) { + break; + } + } + } + } else { + if (isset($pipes[1])) { + $stdout = stream_get_contents($pipes[1]); + + fclose($pipes[1]); + } + + if (isset($pipes[2])) { + $stderr = stream_get_contents($pipes[2]); + + fclose($pipes[2]); + } + } + + if (isset($handles[1])) { + rewind($handles[1]); + + $stdout = stream_get_contents($handles[1]); + + fclose($handles[1]); + } + + if (isset($handles[2])) { + rewind($handles[2]); + + $stderr = stream_get_contents($handles[2]); + + fclose($handles[2]); + } + + proc_close($process); + + $this->cleanup(); + + return ['stdout' => $stdout, 'stderr' => $stderr]; + } + + /** + * @param resource $pipe + */ + protected function process($pipe, string $job): void + { + fwrite($pipe, $job); + } + + protected function cleanup(): void + { + if ($this->tempFile) { + unlink($this->tempFile); + } + } + + protected function useTemporaryFile(): bool + { + return false; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/PHP/Template/PhptTestCase.tpl b/vendor/phpunit/phpunit/src/Util/PHP/Template/PhptTestCase.tpl new file mode 100644 index 00000000..f23a0d1a --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/PHP/Template/PhptTestCase.tpl @@ -0,0 +1,57 @@ +{driverMethod}($filter), + $filter + ); + + if ({codeCoverageCacheDirectory}) { + $coverage->cacheStaticAnalysis({codeCoverageCacheDirectory}); + } + + $coverage->start(__FILE__); +} + +register_shutdown_function( + function() use ($coverage) { + $output = null; + + if ($coverage) { + $output = $coverage->stop(); + } + + file_put_contents('{coverageFile}', serialize($output)); + } +); + +ob_end_clean(); + +require '{job}'; diff --git a/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseClass.tpl b/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseClass.tpl new file mode 100644 index 00000000..95035e50 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseClass.tpl @@ -0,0 +1,119 @@ +{driverMethod}($filter), + $filter + ); + + if ({cachesStaticAnalysis}) { + $codeCoverage->cacheStaticAnalysis(unserialize('{codeCoverageCacheDirectory}')); + } + + $result->setCodeCoverage($codeCoverage); + } + + $result->beStrictAboutTestsThatDoNotTestAnything({isStrictAboutTestsThatDoNotTestAnything}); + $result->beStrictAboutOutputDuringTests({isStrictAboutOutputDuringTests}); + $result->enforceTimeLimit({enforcesTimeLimit}); + $result->beStrictAboutTodoAnnotatedTests({isStrictAboutTodoAnnotatedTests}); + $result->beStrictAboutResourceUsageDuringSmallTests({isStrictAboutResourceUsageDuringSmallTests}); + + $test = new {className}('{name}', unserialize('{data}'), '{dataName}'); + $test->setDependencyInput(unserialize('{dependencyInput}')); + $test->setInIsolation(TRUE); + + ob_end_clean(); + $test->run($result); + $output = ''; + if (!$test->hasExpectationOnOutput()) { + $output = $test->getActualOutput(); + } + + ini_set('xdebug.scream', '0'); + @rewind(STDOUT); /* @ as not every STDOUT target stream is rewindable */ + if ($stdout = @stream_get_contents(STDOUT)) { + $output = $stdout . $output; + $streamMetaData = stream_get_meta_data(STDOUT); + if (!empty($streamMetaData['stream_type']) && 'STDIO' === $streamMetaData['stream_type']) { + @ftruncate(STDOUT, 0); + @rewind(STDOUT); + } + } + + print serialize( + [ + 'testResult' => $test->getResult(), + 'numAssertions' => $test->getNumAssertions(), + 'result' => $result, + 'output' => $output + ] + ); +} + +$configurationFilePath = '{configurationFilePath}'; + +if ('' !== $configurationFilePath) { + $configuration = (new Loader)->load($configurationFilePath); + + (new PhpHandler)->handle($configuration->php()); + + unset($configuration); +} + +function __phpunit_error_handler($errno, $errstr, $errfile, $errline) +{ + return true; +} + +set_error_handler('__phpunit_error_handler'); + +{constants} +{included_files} +{globals} + +restore_error_handler(); + +if (isset($GLOBALS['__PHPUNIT_BOOTSTRAP'])) { + require_once $GLOBALS['__PHPUNIT_BOOTSTRAP']; + unset($GLOBALS['__PHPUNIT_BOOTSTRAP']); +} + +__phpunit_run_isolated_test(); diff --git a/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseMethod.tpl b/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseMethod.tpl new file mode 100644 index 00000000..da824e72 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseMethod.tpl @@ -0,0 +1,122 @@ +{driverMethod}($filter), + $filter + ); + + if ({cachesStaticAnalysis}) { + $codeCoverage->cacheStaticAnalysis(unserialize('{codeCoverageCacheDirectory}')); + } + + $result->setCodeCoverage($codeCoverage); + } + + $result->beStrictAboutTestsThatDoNotTestAnything({isStrictAboutTestsThatDoNotTestAnything}); + $result->beStrictAboutOutputDuringTests({isStrictAboutOutputDuringTests}); + $result->enforceTimeLimit({enforcesTimeLimit}); + $result->beStrictAboutTodoAnnotatedTests({isStrictAboutTodoAnnotatedTests}); + $result->beStrictAboutResourceUsageDuringSmallTests({isStrictAboutResourceUsageDuringSmallTests}); + + $test = new {className}('{methodName}', unserialize('{data}'), '{dataName}'); + \assert($test instanceof TestCase); + + $test->setDependencyInput(unserialize('{dependencyInput}')); + $test->setInIsolation(true); + + ob_end_clean(); + $test->run($result); + $output = ''; + if (!$test->hasExpectationOnOutput()) { + $output = $test->getActualOutput(); + } + + ini_set('xdebug.scream', '0'); + @rewind(STDOUT); /* @ as not every STDOUT target stream is rewindable */ + if ($stdout = @stream_get_contents(STDOUT)) { + $output = $stdout . $output; + $streamMetaData = stream_get_meta_data(STDOUT); + if (!empty($streamMetaData['stream_type']) && 'STDIO' === $streamMetaData['stream_type']) { + @ftruncate(STDOUT, 0); + @rewind(STDOUT); + } + } + + print serialize( + [ + 'testResult' => $test->getResult(), + 'numAssertions' => $test->getNumAssertions(), + 'result' => $result, + 'output' => $output + ] + ); +} + +$configurationFilePath = '{configurationFilePath}'; + +if ('' !== $configurationFilePath) { + $configuration = (new Loader)->load($configurationFilePath); + + (new PhpHandler)->handle($configuration->php()); + + unset($configuration); +} + +function __phpunit_error_handler($errno, $errstr, $errfile, $errline) +{ + return true; +} + +set_error_handler('__phpunit_error_handler'); + +{constants} +{included_files} +{globals} + +restore_error_handler(); + +if (isset($GLOBALS['__PHPUNIT_BOOTSTRAP'])) { + require_once $GLOBALS['__PHPUNIT_BOOTSTRAP']; + unset($GLOBALS['__PHPUNIT_BOOTSTRAP']); +} + +__phpunit_run_isolated_test(); diff --git a/vendor/phpunit/phpunit/src/Util/PHP/WindowsPhpProcess.php b/vendor/phpunit/phpunit/src/Util/PHP/WindowsPhpProcess.php new file mode 100644 index 00000000..9ef92555 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/PHP/WindowsPhpProcess.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\PHP; + +use const PHP_MAJOR_VERSION; +use function tmpfile; +use PHPUnit\Framework\Exception; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @see https://bugs.php.net/bug.php?id=51800 + */ +final class WindowsPhpProcess extends DefaultPhpProcess +{ + public function getCommand(array $settings, string $file = null): string + { + if (PHP_MAJOR_VERSION < 8) { + return '"' . parent::getCommand($settings, $file) . '"'; + } + + return parent::getCommand($settings, $file); + } + + /** + * @throws Exception + */ + protected function getHandles(): array + { + if (false === $stdout_handle = tmpfile()) { + throw new Exception( + 'A temporary file could not be created; verify that your TEMP environment variable is writable' + ); + } + + return [ + 1 => $stdout_handle, + ]; + } + + protected function useTemporaryFile(): bool + { + return true; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Printer.php b/vendor/phpunit/phpunit/src/Util/Printer.php new file mode 100644 index 00000000..77b5745a --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Printer.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const ENT_COMPAT; +use const ENT_SUBSTITUTE; +use const PHP_SAPI; +use function assert; +use function count; +use function dirname; +use function explode; +use function fclose; +use function fopen; +use function fsockopen; +use function fwrite; +use function htmlspecialchars; +use function is_resource; +use function is_string; +use function sprintf; +use function str_replace; +use function strncmp; +use function strpos; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class Printer +{ + /** + * @psalm-var closed-resource|resource + */ + private $stream; + + /** + * @var bool + */ + private $isPhpStream; + + /** + * @param null|resource|string $out + * + * @throws Exception + */ + public function __construct($out = null) + { + if (is_resource($out)) { + $this->stream = $out; + + return; + } + + if (!is_string($out)) { + return; + } + + if (strpos($out, 'socket://') === 0) { + $tmp = explode(':', str_replace('socket://', '', $out)); + + if (count($tmp) !== 2) { + throw new Exception( + sprintf( + '"%s" does not match "socket://hostname:port" format', + $out + ) + ); + } + + $this->stream = fsockopen($tmp[0], (int) $tmp[1]); + + return; + } + + if (strpos($out, 'php://') === false && !Filesystem::createDirectory(dirname($out))) { + throw new Exception( + sprintf( + 'Directory "%s" was not created', + dirname($out) + ) + ); + } + + $this->stream = fopen($out, 'wb'); + $this->isPhpStream = strncmp($out, 'php://', 6) !== 0; + } + + public function write(string $buffer): void + { + if ($this->stream) { + assert(is_resource($this->stream)); + + fwrite($this->stream, $buffer); + } else { + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') { + $buffer = htmlspecialchars($buffer, ENT_COMPAT | ENT_SUBSTITUTE); + } + + print $buffer; + } + } + + public function flush(): void + { + if ($this->stream && $this->isPhpStream) { + assert(is_resource($this->stream)); + + fclose($this->stream); + } + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Reflection.php b/vendor/phpunit/phpunit/src/Util/Reflection.php new file mode 100644 index 00000000..3ffc2d5e --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Reflection.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use PHPUnit\Framework\Assert; +use PHPUnit\Framework\TestCase; +use ReflectionClass; +use ReflectionMethod; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Reflection +{ + /** + * @psalm-return list + */ + public function publicMethodsInTestClass(ReflectionClass $class): array + { + return $this->filterMethods($class, ReflectionMethod::IS_PUBLIC); + } + + /** + * @psalm-return list + */ + public function methodsInTestClass(ReflectionClass $class): array + { + return $this->filterMethods($class, null); + } + + /** + * @psalm-return list + */ + private function filterMethods(ReflectionClass $class, ?int $filter): array + { + $methods = []; + + // PHP <7.3.5 throw error when null is passed + // to ReflectionClass::getMethods() when strict_types is enabled. + $classMethods = $filter === null ? $class->getMethods() : $class->getMethods($filter); + + foreach ($classMethods as $method) { + if ($method->getDeclaringClass()->getName() === TestCase::class) { + continue; + } + + if ($method->getDeclaringClass()->getName() === Assert::class) { + continue; + } + + $methods[] = $method; + } + + return $methods; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/RegularExpression.php b/vendor/phpunit/phpunit/src/Util/RegularExpression.php new file mode 100644 index 00000000..db1dae92 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/RegularExpression.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use function preg_match; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RegularExpression +{ + /** + * @return false|int + */ + public static function safeMatch(string $pattern, string $subject) + { + return ErrorHandler::invokeIgnoringWarnings( + static function () use ($pattern, $subject) + { + return preg_match($pattern, $subject); + } + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Test.php b/vendor/phpunit/phpunit/src/Util/Test.php new file mode 100644 index 00000000..f089f6d4 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Test.php @@ -0,0 +1,783 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const PHP_OS; +use const PHP_VERSION; +use function addcslashes; +use function array_flip; +use function array_key_exists; +use function array_merge; +use function array_unique; +use function array_unshift; +use function class_exists; +use function count; +use function explode; +use function extension_loaded; +use function function_exists; +use function get_class; +use function ini_get; +use function interface_exists; +use function is_array; +use function is_int; +use function method_exists; +use function phpversion; +use function preg_match; +use function preg_replace; +use function sprintf; +use function strncmp; +use function strpos; +use function strtolower; +use function trim; +use function version_compare; +use PHPUnit\Framework\CodeCoverageException; +use PHPUnit\Framework\ExecutionOrderDependency; +use PHPUnit\Framework\InvalidCoversTargetException; +use PHPUnit\Framework\SelfDescribing; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Warning; +use PHPUnit\Runner\Version; +use PHPUnit\Util\Annotation\Registry; +use ReflectionClass; +use ReflectionException; +use ReflectionMethod; +use SebastianBergmann\CodeUnit\CodeUnitCollection; +use SebastianBergmann\CodeUnit\InvalidCodeUnitException; +use SebastianBergmann\CodeUnit\Mapper; +use SebastianBergmann\Environment\OperatingSystem; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Test +{ + /** + * @var int + */ + public const UNKNOWN = -1; + + /** + * @var int + */ + public const SMALL = 0; + + /** + * @var int + */ + public const MEDIUM = 1; + + /** + * @var int + */ + public const LARGE = 2; + + /** + * @var array + */ + private static $hookMethods = []; + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function describe(\PHPUnit\Framework\Test $test): array + { + if ($test instanceof TestCase) { + return [get_class($test), $test->getName()]; + } + + if ($test instanceof SelfDescribing) { + return ['', $test->toString()]; + } + + return ['', get_class($test)]; + } + + public static function describeAsString(\PHPUnit\Framework\Test $test): string + { + if ($test instanceof SelfDescribing) { + return $test->toString(); + } + + return get_class($test); + } + + /** + * @throws CodeCoverageException + * + * @return array|bool + * + * @psalm-param class-string $className + */ + public static function getLinesToBeCovered(string $className, string $methodName) + { + $annotations = self::parseTestMethodAnnotations( + $className, + $methodName + ); + + if (!self::shouldCoversAnnotationBeUsed($annotations)) { + return false; + } + + return self::getLinesToBeCoveredOrUsed($className, $methodName, 'covers'); + } + + /** + * Returns lines of code specified with the @uses annotation. + * + * @throws CodeCoverageException + * + * @psalm-param class-string $className + */ + public static function getLinesToBeUsed(string $className, string $methodName): array + { + return self::getLinesToBeCoveredOrUsed($className, $methodName, 'uses'); + } + + public static function requiresCodeCoverageDataCollection(TestCase $test): bool + { + $annotations = self::parseTestMethodAnnotations( + get_class($test), + $test->getName(false) + ); + + // If there is no @covers annotation but a @coversNothing annotation on + // the test method then code coverage data does not need to be collected + if (isset($annotations['method']['coversNothing'])) { + // @see https://github.com/sebastianbergmann/phpunit/issues/4947#issuecomment-1084480950 + // return false; + } + + // If there is at least one @covers annotation then + // code coverage data needs to be collected + if (isset($annotations['method']['covers'])) { + return true; + } + + // If there is no @covers annotation but a @coversNothing annotation + // then code coverage data does not need to be collected + if (isset($annotations['class']['coversNothing'])) { + // @see https://github.com/sebastianbergmann/phpunit/issues/4947#issuecomment-1084480950 + // return false; + } + + // If there is no @coversNothing annotation then + // code coverage data may be collected + return true; + } + + /** + * @throws Exception + * + * @psalm-param class-string $className + */ + public static function getRequirements(string $className, string $methodName): array + { + return self::mergeArraysRecursively( + Registry::getInstance()->forClassName($className)->requirements(), + Registry::getInstance()->forMethod($className, $methodName)->requirements() + ); + } + + /** + * Returns the missing requirements for a test. + * + * @throws Exception + * @throws Warning + * + * @psalm-param class-string $className + */ + public static function getMissingRequirements(string $className, string $methodName): array + { + $required = self::getRequirements($className, $methodName); + $missing = []; + $hint = null; + + if (!empty($required['PHP'])) { + $operator = new VersionComparisonOperator(empty($required['PHP']['operator']) ? '>=' : $required['PHP']['operator']); + + if (!version_compare(PHP_VERSION, $required['PHP']['version'], $operator->asString())) { + $missing[] = sprintf('PHP %s %s is required.', $operator->asString(), $required['PHP']['version']); + $hint = 'PHP'; + } + } elseif (!empty($required['PHP_constraint'])) { + $version = new \PharIo\Version\Version(self::sanitizeVersionNumber(PHP_VERSION)); + + if (!$required['PHP_constraint']['constraint']->complies($version)) { + $missing[] = sprintf( + 'PHP version does not match the required constraint %s.', + $required['PHP_constraint']['constraint']->asString() + ); + + $hint = 'PHP_constraint'; + } + } + + if (!empty($required['PHPUnit'])) { + $phpunitVersion = Version::id(); + + $operator = new VersionComparisonOperator(empty($required['PHPUnit']['operator']) ? '>=' : $required['PHPUnit']['operator']); + + if (!version_compare($phpunitVersion, $required['PHPUnit']['version'], $operator->asString())) { + $missing[] = sprintf('PHPUnit %s %s is required.', $operator->asString(), $required['PHPUnit']['version']); + $hint = $hint ?? 'PHPUnit'; + } + } elseif (!empty($required['PHPUnit_constraint'])) { + $phpunitVersion = new \PharIo\Version\Version(self::sanitizeVersionNumber(Version::id())); + + if (!$required['PHPUnit_constraint']['constraint']->complies($phpunitVersion)) { + $missing[] = sprintf( + 'PHPUnit version does not match the required constraint %s.', + $required['PHPUnit_constraint']['constraint']->asString() + ); + + $hint = $hint ?? 'PHPUnit_constraint'; + } + } + + if (!empty($required['OSFAMILY']) && $required['OSFAMILY'] !== (new OperatingSystem)->getFamily()) { + $missing[] = sprintf('Operating system %s is required.', $required['OSFAMILY']); + $hint = $hint ?? 'OSFAMILY'; + } + + if (!empty($required['OS'])) { + $requiredOsPattern = sprintf('/%s/i', addcslashes($required['OS'], '/')); + + if (!preg_match($requiredOsPattern, PHP_OS)) { + $missing[] = sprintf('Operating system matching %s is required.', $requiredOsPattern); + $hint = $hint ?? 'OS'; + } + } + + if (!empty($required['functions'])) { + foreach ($required['functions'] as $function) { + $pieces = explode('::', $function); + + if (count($pieces) === 2 && class_exists($pieces[0]) && method_exists($pieces[0], $pieces[1])) { + continue; + } + + if (function_exists($function)) { + continue; + } + + $missing[] = sprintf('Function %s is required.', $function); + $hint = $hint ?? 'function_' . $function; + } + } + + if (!empty($required['setting'])) { + foreach ($required['setting'] as $setting => $value) { + if (ini_get($setting) !== $value) { + $missing[] = sprintf('Setting "%s" must be "%s".', $setting, $value); + $hint = $hint ?? '__SETTING_' . $setting; + } + } + } + + if (!empty($required['extensions'])) { + foreach ($required['extensions'] as $extension) { + if (isset($required['extension_versions'][$extension])) { + continue; + } + + if (!extension_loaded($extension)) { + $missing[] = sprintf('Extension %s is required.', $extension); + $hint = $hint ?? 'extension_' . $extension; + } + } + } + + if (!empty($required['extension_versions'])) { + foreach ($required['extension_versions'] as $extension => $req) { + $actualVersion = phpversion($extension); + + $operator = new VersionComparisonOperator(empty($req['operator']) ? '>=' : $req['operator']); + + if ($actualVersion === false || !version_compare($actualVersion, $req['version'], $operator->asString())) { + $missing[] = sprintf('Extension %s %s %s is required.', $extension, $operator->asString(), $req['version']); + $hint = $hint ?? 'extension_' . $extension; + } + } + } + + if ($hint && isset($required['__OFFSET'])) { + array_unshift($missing, '__OFFSET_FILE=' . $required['__OFFSET']['__FILE']); + array_unshift($missing, '__OFFSET_LINE=' . ($required['__OFFSET'][$hint] ?? 1)); + } + + return $missing; + } + + /** + * Returns the provided data for a method. + * + * @throws Exception + * + * @psalm-param class-string $className + */ + public static function getProvidedData(string $className, string $methodName): ?array + { + return Registry::getInstance()->forMethod($className, $methodName)->getProvidedData(); + } + + /** + * @psalm-param class-string $className + */ + public static function parseTestMethodAnnotations(string $className, ?string $methodName = ''): array + { + $registry = Registry::getInstance(); + + if ($methodName !== null) { + try { + return [ + 'method' => $registry->forMethod($className, $methodName)->symbolAnnotations(), + 'class' => $registry->forClassName($className)->symbolAnnotations(), + ]; + } catch (Exception $methodNotFound) { + // ignored + } + } + + return [ + 'method' => null, + 'class' => $registry->forClassName($className)->symbolAnnotations(), + ]; + } + + /** + * @psalm-param class-string $className + */ + public static function getInlineAnnotations(string $className, string $methodName): array + { + return Registry::getInstance()->forMethod($className, $methodName)->getInlineAnnotations(); + } + + /** @psalm-param class-string $className */ + public static function getBackupSettings(string $className, string $methodName): array + { + return [ + 'backupGlobals' => self::getBooleanAnnotationSetting( + $className, + $methodName, + 'backupGlobals' + ), + 'backupStaticAttributes' => self::getBooleanAnnotationSetting( + $className, + $methodName, + 'backupStaticAttributes' + ), + ]; + } + + /** + * @psalm-param class-string $className + * + * @return ExecutionOrderDependency[] + */ + public static function getDependencies(string $className, string $methodName): array + { + $annotations = self::parseTestMethodAnnotations( + $className, + $methodName + ); + + $dependsAnnotations = $annotations['class']['depends'] ?? []; + + if (isset($annotations['method']['depends'])) { + $dependsAnnotations = array_merge( + $dependsAnnotations, + $annotations['method']['depends'] + ); + } + + // Normalize dependency name to className::methodName + $dependencies = []; + + foreach ($dependsAnnotations as $value) { + $dependencies[] = ExecutionOrderDependency::createFromDependsAnnotation($className, $value); + } + + return array_unique($dependencies); + } + + /** @psalm-param class-string $className */ + public static function getGroups(string $className, ?string $methodName = ''): array + { + $annotations = self::parseTestMethodAnnotations( + $className, + $methodName + ); + + $groups = []; + + if (isset($annotations['method']['author'])) { + $groups[] = $annotations['method']['author']; + } elseif (isset($annotations['class']['author'])) { + $groups[] = $annotations['class']['author']; + } + + if (isset($annotations['class']['group'])) { + $groups[] = $annotations['class']['group']; + } + + if (isset($annotations['method']['group'])) { + $groups[] = $annotations['method']['group']; + } + + if (isset($annotations['class']['ticket'])) { + $groups[] = $annotations['class']['ticket']; + } + + if (isset($annotations['method']['ticket'])) { + $groups[] = $annotations['method']['ticket']; + } + + foreach (['method', 'class'] as $element) { + foreach (['small', 'medium', 'large'] as $size) { + if (isset($annotations[$element][$size])) { + $groups[] = [$size]; + + break 2; + } + } + } + + foreach (['method', 'class'] as $element) { + if (isset($annotations[$element]['covers'])) { + foreach ($annotations[$element]['covers'] as $coversTarget) { + $groups[] = ['__phpunit_covers_' . self::canonicalizeName($coversTarget)]; + } + } + + if (isset($annotations[$element]['uses'])) { + foreach ($annotations[$element]['uses'] as $usesTarget) { + $groups[] = ['__phpunit_uses_' . self::canonicalizeName($usesTarget)]; + } + } + } + + return array_unique(array_merge([], ...$groups)); + } + + /** @psalm-param class-string $className */ + public static function getSize(string $className, ?string $methodName): int + { + $groups = array_flip(self::getGroups($className, $methodName)); + + if (isset($groups['large'])) { + return self::LARGE; + } + + if (isset($groups['medium'])) { + return self::MEDIUM; + } + + if (isset($groups['small'])) { + return self::SMALL; + } + + return self::UNKNOWN; + } + + /** @psalm-param class-string $className */ + public static function getProcessIsolationSettings(string $className, string $methodName): bool + { + $annotations = self::parseTestMethodAnnotations( + $className, + $methodName + ); + + return isset($annotations['class']['runTestsInSeparateProcesses']) || isset($annotations['method']['runInSeparateProcess']); + } + + /** @psalm-param class-string $className */ + public static function getClassProcessIsolationSettings(string $className, string $methodName): bool + { + $annotations = self::parseTestMethodAnnotations( + $className, + $methodName + ); + + return isset($annotations['class']['runClassInSeparateProcess']); + } + + /** @psalm-param class-string $className */ + public static function getPreserveGlobalStateSettings(string $className, string $methodName): ?bool + { + return self::getBooleanAnnotationSetting( + $className, + $methodName, + 'preserveGlobalState' + ); + } + + /** @psalm-param class-string $className */ + public static function getHookMethods(string $className): array + { + if (!class_exists($className, false)) { + return self::emptyHookMethodsArray(); + } + + if (!isset(self::$hookMethods[$className])) { + self::$hookMethods[$className] = self::emptyHookMethodsArray(); + + try { + foreach ((new Reflection)->methodsInTestClass(new ReflectionClass($className)) as $method) { + $docBlock = Registry::getInstance()->forMethod($className, $method->getName()); + + if ($method->isStatic()) { + if ($docBlock->isHookToBeExecutedBeforeClass()) { + array_unshift( + self::$hookMethods[$className]['beforeClass'], + $method->getName() + ); + } + + if ($docBlock->isHookToBeExecutedAfterClass()) { + self::$hookMethods[$className]['afterClass'][] = $method->getName(); + } + } + + if ($docBlock->isToBeExecutedBeforeTest()) { + array_unshift( + self::$hookMethods[$className]['before'], + $method->getName() + ); + } + + if ($docBlock->isToBeExecutedAsPreCondition()) { + array_unshift( + self::$hookMethods[$className]['preCondition'], + $method->getName() + ); + } + + if ($docBlock->isToBeExecutedAsPostCondition()) { + self::$hookMethods[$className]['postCondition'][] = $method->getName(); + } + + if ($docBlock->isToBeExecutedAfterTest()) { + self::$hookMethods[$className]['after'][] = $method->getName(); + } + } + } catch (ReflectionException $e) { + } + } + + return self::$hookMethods[$className]; + } + + public static function isTestMethod(ReflectionMethod $method): bool + { + if (!$method->isPublic()) { + return false; + } + + if (strpos($method->getName(), 'test') === 0) { + return true; + } + + return array_key_exists( + 'test', + Registry::getInstance()->forMethod( + $method->getDeclaringClass()->getName(), + $method->getName() + ) + ->symbolAnnotations() + ); + } + + /** + * @throws CodeCoverageException + * + * @psalm-param class-string $className + */ + private static function getLinesToBeCoveredOrUsed(string $className, string $methodName, string $mode): array + { + $annotations = self::parseTestMethodAnnotations( + $className, + $methodName + ); + + $classShortcut = null; + + if (!empty($annotations['class'][$mode . 'DefaultClass'])) { + if (count($annotations['class'][$mode . 'DefaultClass']) > 1) { + throw new CodeCoverageException( + sprintf( + 'More than one @%sClass annotation in class or interface "%s".', + $mode, + $className + ) + ); + } + + $classShortcut = $annotations['class'][$mode . 'DefaultClass'][0]; + } + + $list = $annotations['class'][$mode] ?? []; + + if (isset($annotations['method'][$mode])) { + $list = array_merge($list, $annotations['method'][$mode]); + } + + $codeUnits = CodeUnitCollection::fromArray([]); + $mapper = new Mapper; + + foreach (array_unique($list) as $element) { + if ($classShortcut && strncmp($element, '::', 2) === 0) { + $element = $classShortcut . $element; + } + + $element = preg_replace('/[\s()]+$/', '', $element); + $element = explode(' ', $element); + $element = $element[0]; + + if ($mode === 'covers' && interface_exists($element)) { + throw new InvalidCoversTargetException( + sprintf( + 'Trying to @cover interface "%s".', + $element + ) + ); + } + + try { + $codeUnits = $codeUnits->mergeWith($mapper->stringToCodeUnits($element)); + } catch (InvalidCodeUnitException $e) { + throw new InvalidCoversTargetException( + sprintf( + '"@%s %s" is invalid', + $mode, + $element + ), + $e->getCode(), + $e + ); + } + } + + return $mapper->codeUnitsToSourceLines($codeUnits); + } + + private static function emptyHookMethodsArray(): array + { + return [ + 'beforeClass' => ['setUpBeforeClass'], + 'before' => ['setUp'], + 'preCondition' => ['assertPreConditions'], + 'postCondition' => ['assertPostConditions'], + 'after' => ['tearDown'], + 'afterClass' => ['tearDownAfterClass'], + ]; + } + + /** @psalm-param class-string $className */ + private static function getBooleanAnnotationSetting(string $className, ?string $methodName, string $settingName): ?bool + { + $annotations = self::parseTestMethodAnnotations( + $className, + $methodName + ); + + if (isset($annotations['method'][$settingName])) { + if ($annotations['method'][$settingName][0] === 'enabled') { + return true; + } + + if ($annotations['method'][$settingName][0] === 'disabled') { + return false; + } + } + + if (isset($annotations['class'][$settingName])) { + if ($annotations['class'][$settingName][0] === 'enabled') { + return true; + } + + if ($annotations['class'][$settingName][0] === 'disabled') { + return false; + } + } + + return null; + } + + /** + * Trims any extensions from version string that follows after + * the .[.] format. + */ + private static function sanitizeVersionNumber(string $version) + { + return preg_replace( + '/^(\d+\.\d+(?:.\d+)?).*$/', + '$1', + $version + ); + } + + private static function shouldCoversAnnotationBeUsed(array $annotations): bool + { + if (isset($annotations['method']['coversNothing'])) { + return false; + } + + if (isset($annotations['method']['covers'])) { + return true; + } + + if (isset($annotations['class']['coversNothing'])) { + return false; + } + + return true; + } + + /** + * Merge two arrays together. + * + * If an integer key exists in both arrays and preserveNumericKeys is false, the value + * from the second array will be appended to the first array. If both values are arrays, they + * are merged together, else the value of the second array overwrites the one of the first array. + * + * This implementation is copied from https://github.com/zendframework/zend-stdlib/blob/76b653c5e99b40eccf5966e3122c90615134ae46/src/ArrayUtils.php + * + * Zend Framework (http://framework.zend.com/) + * + * @see http://github.com/zendframework/zf2 for the canonical source repository + * + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + private static function mergeArraysRecursively(array $a, array $b): array + { + foreach ($b as $key => $value) { + if (array_key_exists($key, $a)) { + if (is_int($key)) { + $a[] = $value; + } elseif (is_array($value) && is_array($a[$key])) { + $a[$key] = self::mergeArraysRecursively($a[$key], $value); + } else { + $a[$key] = $value; + } + } else { + $a[$key] = $value; + } + } + + return $a; + } + + private static function canonicalizeName(string $name): string + { + return strtolower(trim($name, '\\')); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/TestDox/CliTestDoxPrinter.php b/vendor/phpunit/phpunit/src/Util/TestDox/CliTestDoxPrinter.php new file mode 100644 index 00000000..def16c39 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/TestDox/CliTestDoxPrinter.php @@ -0,0 +1,381 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\TestDox; + +use const PHP_EOL; +use function array_map; +use function ceil; +use function count; +use function explode; +use function get_class; +use function implode; +use function preg_match; +use function sprintf; +use function strlen; +use function strpos; +use function trim; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestResult; +use PHPUnit\Runner\BaseTestRunner; +use PHPUnit\Runner\PhptTestCase; +use PHPUnit\Util\Color; +use SebastianBergmann\Timer\ResourceUsageFormatter; +use SebastianBergmann\Timer\Timer; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class CliTestDoxPrinter extends TestDoxPrinter +{ + /** + * The default Testdox left margin for messages is a vertical line. + */ + private const PREFIX_SIMPLE = [ + 'default' => '│', + 'start' => '│', + 'message' => '│', + 'diff' => '│', + 'trace' => '│', + 'last' => '│', + ]; + + /** + * Colored Testdox use box-drawing for a more textured map of the message. + */ + private const PREFIX_DECORATED = [ + 'default' => '│', + 'start' => '┐', + 'message' => '├', + 'diff' => '┊', + 'trace' => '╵', + 'last' => '┴', + ]; + + private const SPINNER_ICONS = [ + " \e[36m◐\e[0m running tests", + " \e[36m◓\e[0m running tests", + " \e[36m◑\e[0m running tests", + " \e[36m◒\e[0m running tests", + ]; + + private const STATUS_STYLES = [ + BaseTestRunner::STATUS_PASSED => [ + 'symbol' => '✔', + 'color' => 'fg-green', + ], + BaseTestRunner::STATUS_ERROR => [ + 'symbol' => '✘', + 'color' => 'fg-yellow', + 'message' => 'bg-yellow,fg-black', + ], + BaseTestRunner::STATUS_FAILURE => [ + 'symbol' => '✘', + 'color' => 'fg-red', + 'message' => 'bg-red,fg-white', + ], + BaseTestRunner::STATUS_SKIPPED => [ + 'symbol' => '↩', + 'color' => 'fg-cyan', + 'message' => 'fg-cyan', + ], + BaseTestRunner::STATUS_RISKY => [ + 'symbol' => '☢', + 'color' => 'fg-yellow', + 'message' => 'fg-yellow', + ], + BaseTestRunner::STATUS_INCOMPLETE => [ + 'symbol' => '∅', + 'color' => 'fg-yellow', + 'message' => 'fg-yellow', + ], + BaseTestRunner::STATUS_WARNING => [ + 'symbol' => '⚠', + 'color' => 'fg-yellow', + 'message' => 'fg-yellow', + ], + BaseTestRunner::STATUS_UNKNOWN => [ + 'symbol' => '?', + 'color' => 'fg-blue', + 'message' => 'fg-white,bg-blue', + ], + ]; + + /** + * @var int[] + */ + private $nonSuccessfulTestResults = []; + + /** + * @var Timer + */ + private $timer; + + /** + * @param null|resource|string $out + * @param int|string $numberOfColumns + * + * @throws \PHPUnit\Framework\Exception + */ + public function __construct($out = null, bool $verbose = false, string $colors = self::COLOR_DEFAULT, bool $debug = false, $numberOfColumns = 80, bool $reverse = false) + { + parent::__construct($out, $verbose, $colors, $debug, $numberOfColumns, $reverse); + + $this->timer = new Timer; + + $this->timer->start(); + } + + public function printResult(TestResult $result): void + { + $this->printHeader($result); + + $this->printNonSuccessfulTestsSummary($result->count()); + + $this->printFooter($result); + } + + protected function printHeader(TestResult $result): void + { + $this->write("\n" . (new ResourceUsageFormatter)->resourceUsage($this->timer->stop()) . "\n\n"); + } + + protected function formatClassName(Test $test): string + { + if ($test instanceof TestCase) { + return $this->prettifier->prettifyTestClass(get_class($test)); + } + + return get_class($test); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function registerTestResult(Test $test, ?Throwable $t, int $status, float $time, bool $verbose): void + { + if ($status !== BaseTestRunner::STATUS_PASSED) { + $this->nonSuccessfulTestResults[] = $this->testIndex; + } + + parent::registerTestResult($test, $t, $status, $time, $verbose); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function formatTestName(Test $test): string + { + if ($test instanceof TestCase) { + return $this->prettifier->prettifyTestCase($test); + } + + return parent::formatTestName($test); + } + + protected function writeTestResult(array $prevResult, array $result): void + { + // spacer line for new suite headers and after verbose messages + if ($prevResult['testName'] !== '' && + (!empty($prevResult['message']) || $prevResult['className'] !== $result['className'])) { + $this->write(PHP_EOL); + } + + // suite header + if ($prevResult['className'] !== $result['className']) { + $this->write($this->colorizeTextBox('underlined', $result['className']) . PHP_EOL); + } + + // test result line + if ($this->colors && $result['className'] === PhptTestCase::class) { + $testName = Color::colorizePath($result['testName'], $prevResult['testName'], true); + } else { + $testName = $result['testMethod']; + } + + $style = self::STATUS_STYLES[$result['status']]; + $line = sprintf( + ' %s %s%s' . PHP_EOL, + $this->colorizeTextBox($style['color'], $style['symbol']), + $testName, + $this->verbose ? ' ' . $this->formatRuntime($result['time'], $style['color']) : '' + ); + + $this->write($line); + + // additional information when verbose + $this->write($result['message']); + } + + protected function formatThrowable(Throwable $t, ?int $status = null): string + { + return trim(\PHPUnit\Framework\TestFailure::exceptionToString($t)); + } + + protected function colorizeMessageAndDiff(string $style, string $buffer): array + { + $lines = $buffer ? array_map('\rtrim', explode(PHP_EOL, $buffer)) : []; + $message = []; + $diff = []; + $insideDiff = false; + + foreach ($lines as $line) { + if ($line === '--- Expected') { + $insideDiff = true; + } + + if (!$insideDiff) { + $message[] = $line; + } else { + if (strpos($line, '-') === 0) { + $line = Color::colorize('fg-red', Color::visualizeWhitespace($line, true)); + } elseif (strpos($line, '+') === 0) { + $line = Color::colorize('fg-green', Color::visualizeWhitespace($line, true)); + } elseif ($line === '@@ @@') { + $line = Color::colorize('fg-cyan', $line); + } + $diff[] = $line; + } + } + $diff = implode(PHP_EOL, $diff); + + if (!empty($message)) { + $message = $this->colorizeTextBox($style, implode(PHP_EOL, $message)); + } + + return [$message, $diff]; + } + + protected function formatStacktrace(Throwable $t): string + { + $trace = \PHPUnit\Util\Filter::getFilteredStacktrace($t); + + if (!$this->colors) { + return $trace; + } + + $lines = []; + $prevPath = ''; + + foreach (explode(PHP_EOL, $trace) as $line) { + if (preg_match('/^(.*):(\d+)$/', $line, $matches)) { + $lines[] = Color::colorizePath($matches[1], $prevPath) . + Color::dim(':') . + Color::colorize('fg-blue', $matches[2]) . + "\n"; + $prevPath = $matches[1]; + } else { + $lines[] = $line; + $prevPath = ''; + } + } + + return implode('', $lines); + } + + protected function formatTestResultMessage(Throwable $t, array $result, ?string $prefix = null): string + { + $message = $this->formatThrowable($t, $result['status']); + $diff = ''; + + if (!($this->verbose || $result['verbose'])) { + return ''; + } + + if ($message && $this->colors) { + $style = self::STATUS_STYLES[$result['status']]['message'] ?? ''; + [$message, $diff] = $this->colorizeMessageAndDiff($style, $message); + } + + if ($prefix === null || !$this->colors) { + $prefix = self::PREFIX_SIMPLE; + } + + if ($this->colors) { + $color = self::STATUS_STYLES[$result['status']]['color'] ?? ''; + $prefix = array_map(static function ($p) use ($color) + { + return Color::colorize($color, $p); + }, self::PREFIX_DECORATED); + } + + $trace = $this->formatStacktrace($t); + $out = $this->prefixLines($prefix['start'], PHP_EOL) . PHP_EOL; + + if ($message) { + $out .= $this->prefixLines($prefix['message'], $message . PHP_EOL) . PHP_EOL; + } + + if ($diff) { + $out .= $this->prefixLines($prefix['diff'], $diff . PHP_EOL) . PHP_EOL; + } + + if ($trace) { + if ($message || $diff) { + $out .= $this->prefixLines($prefix['default'], PHP_EOL) . PHP_EOL; + } + $out .= $this->prefixLines($prefix['trace'], $trace . PHP_EOL) . PHP_EOL; + } + $out .= $this->prefixLines($prefix['last'], PHP_EOL) . PHP_EOL; + + return $out; + } + + protected function drawSpinner(): void + { + if ($this->colors) { + $id = $this->spinState % count(self::SPINNER_ICONS); + $this->write(self::SPINNER_ICONS[$id]); + } + } + + protected function undrawSpinner(): void + { + if ($this->colors) { + $id = $this->spinState % count(self::SPINNER_ICONS); + $this->write("\e[1K\e[" . strlen(self::SPINNER_ICONS[$id]) . 'D'); + } + } + + private function formatRuntime(float $time, string $color = ''): string + { + if (!$this->colors) { + return sprintf('[%.2f ms]', $time * 1000); + } + + if ($time > 1) { + $color = 'fg-magenta'; + } + + return Color::colorize($color, ' ' . (int) ceil($time * 1000) . ' ' . Color::dim('ms')); + } + + private function printNonSuccessfulTestsSummary(int $numberOfExecutedTests): void + { + if (empty($this->nonSuccessfulTestResults)) { + return; + } + + if ((count($this->nonSuccessfulTestResults) / $numberOfExecutedTests) >= 0.7) { + return; + } + + $this->write("Summary of non-successful tests:\n\n"); + + $prevResult = $this->getEmptyTestResult(); + + foreach ($this->nonSuccessfulTestResults as $testIndex) { + $result = $this->testResults[$testIndex]; + $this->writeTestResult($prevResult, $result); + $prevResult = $result; + } + } +} diff --git a/vendor/phpunit/phpunit/src/Util/TestDox/HtmlResultPrinter.php b/vendor/phpunit/phpunit/src/Util/TestDox/HtmlResultPrinter.php new file mode 100644 index 00000000..013d1de8 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/TestDox/HtmlResultPrinter.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\TestDox; + +use function sprintf; +use PHPUnit\Framework\TestResult; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class HtmlResultPrinter extends ResultPrinter +{ + /** + * @var string + */ + private const PAGE_HEADER = <<<'EOT' + + + + + Test Documentation + + + +EOT; + + /** + * @var string + */ + private const CLASS_HEADER = <<<'EOT' + +

    %s

    +
      + +EOT; + + /** + * @var string + */ + private const CLASS_FOOTER = <<<'EOT' +
    +EOT; + + /** + * @var string + */ + private const PAGE_FOOTER = <<<'EOT' + + + +EOT; + + public function printResult(TestResult $result): void + { + } + + /** + * Handler for 'start run' event. + */ + protected function startRun(): void + { + $this->write(self::PAGE_HEADER); + } + + /** + * Handler for 'start class' event. + */ + protected function startClass(string $name): void + { + $this->write( + sprintf( + self::CLASS_HEADER, + $name, + $this->currentTestClassPrettified + ) + ); + } + + /** + * Handler for 'on test' event. + */ + protected function onTest(string $name, bool $success = true): void + { + $this->write( + sprintf( + "
  • %s %s
  • \n", + $success ? '#555753' : '#ef2929', + $success ? '✓' : '❌', + $name + ) + ); + } + + /** + * Handler for 'end class' event. + */ + protected function endClass(string $name): void + { + $this->write(self::CLASS_FOOTER); + } + + /** + * Handler for 'end run' event. + */ + protected function endRun(): void + { + $this->write(self::PAGE_FOOTER); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php b/vendor/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php new file mode 100644 index 00000000..74207149 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php @@ -0,0 +1,312 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\TestDox; + +use function array_key_exists; +use function array_keys; +use function array_map; +use function array_pop; +use function array_values; +use function explode; +use function get_class; +use function gettype; +use function implode; +use function in_array; +use function is_bool; +use function is_float; +use function is_int; +use function is_numeric; +use function is_object; +use function is_scalar; +use function is_string; +use function ord; +use function preg_quote; +use function preg_replace; +use function range; +use function sprintf; +use function str_replace; +use function strlen; +use function strpos; +use function strtolower; +use function strtoupper; +use function substr; +use function trim; +use PHPUnit\Framework\TestCase; +use PHPUnit\Util\Color; +use PHPUnit\Util\Exception as UtilException; +use PHPUnit\Util\Test; +use ReflectionException; +use ReflectionMethod; +use ReflectionObject; +use SebastianBergmann\Exporter\Exporter; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NamePrettifier +{ + /** + * @var string[] + */ + private $strings = []; + + /** + * @var bool + */ + private $useColor; + + public function __construct(bool $useColor = false) + { + $this->useColor = $useColor; + } + + /** + * Prettifies the name of a test class. + * + * @psalm-param class-string $className + */ + public function prettifyTestClass(string $className): string + { + try { + $annotations = Test::parseTestMethodAnnotations($className); + + if (isset($annotations['class']['testdox'][0])) { + return $annotations['class']['testdox'][0]; + } + } catch (UtilException $e) { + // ignore, determine className by parsing the provided name + } + + $parts = explode('\\', $className); + $className = array_pop($parts); + + if (substr($className, -1 * strlen('Test')) === 'Test') { + $className = substr($className, 0, strlen($className) - strlen('Test')); + } + + if (strpos($className, 'Tests') === 0) { + $className = substr($className, strlen('Tests')); + } elseif (strpos($className, 'Test') === 0) { + $className = substr($className, strlen('Test')); + } + + if (empty($className)) { + $className = 'UnnamedTests'; + } + + if (!empty($parts)) { + $parts[] = $className; + $fullyQualifiedName = implode('\\', $parts); + } else { + $fullyQualifiedName = $className; + } + + $result = preg_replace('/(?<=[[:lower:]])(?=[[:upper:]])/u', ' ', $className); + + if ($fullyQualifiedName !== $className) { + return $result . ' (' . $fullyQualifiedName . ')'; + } + + return $result; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function prettifyTestCase(TestCase $test): string + { + $annotations = Test::parseTestMethodAnnotations( + get_class($test), + $test->getName(false) + ); + + $annotationWithPlaceholders = false; + + $callback = static function (string $variable): string + { + return sprintf('/%s(?=\b)/', preg_quote($variable, '/')); + }; + + if (isset($annotations['method']['testdox'][0])) { + $result = $annotations['method']['testdox'][0]; + + if (strpos($result, '$') !== false) { + $annotation = $annotations['method']['testdox'][0]; + $providedData = $this->mapTestMethodParameterNamesToProvidedDataValues($test); + $variables = array_map($callback, array_keys($providedData)); + + $result = trim(preg_replace($variables, $providedData, $annotation)); + + $annotationWithPlaceholders = true; + } + } else { + $result = $this->prettifyTestMethod($test->getName(false)); + } + + if (!$annotationWithPlaceholders && $test->usesDataProvider()) { + $result .= $this->prettifyDataSet($test); + } + + return $result; + } + + public function prettifyDataSet(TestCase $test): string + { + if (!$this->useColor) { + return $test->getDataSetAsString(false); + } + + if (is_int($test->dataName())) { + $data = Color::dim(' with data set ') . Color::colorize('fg-cyan', (string) $test->dataName()); + } else { + $data = Color::dim(' with ') . Color::colorize('fg-cyan', Color::visualizeWhitespace((string) $test->dataName())); + } + + return $data; + } + + /** + * Prettifies the name of a test method. + */ + public function prettifyTestMethod(string $name): string + { + $buffer = ''; + + if ($name === '') { + return $buffer; + } + + $string = (string) preg_replace('#\d+$#', '', $name, -1, $count); + + if (in_array($string, $this->strings, true)) { + $name = $string; + } elseif ($count === 0) { + $this->strings[] = $string; + } + + if (strpos($name, 'test_') === 0) { + $name = substr($name, 5); + } elseif (strpos($name, 'test') === 0) { + $name = substr($name, 4); + } + + if ($name === '') { + return $buffer; + } + + $name[0] = strtoupper($name[0]); + + if (strpos($name, '_') !== false) { + return trim(str_replace('_', ' ', $name)); + } + + $wasNumeric = false; + + foreach (range(0, strlen($name) - 1) as $i) { + if ($i > 0 && ord($name[$i]) >= 65 && ord($name[$i]) <= 90) { + $buffer .= ' ' . strtolower($name[$i]); + } else { + $isNumeric = is_numeric($name[$i]); + + if (!$wasNumeric && $isNumeric) { + $buffer .= ' '; + $wasNumeric = true; + } + + if ($wasNumeric && !$isNumeric) { + $wasNumeric = false; + } + + $buffer .= $name[$i]; + } + } + + return $buffer; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + private function mapTestMethodParameterNamesToProvidedDataValues(TestCase $test): array + { + try { + $reflector = new ReflectionMethod(get_class($test), $test->getName(false)); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new UtilException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + $providedData = []; + $providedDataValues = array_values($test->getProvidedData()); + $i = 0; + + $providedData['$_dataName'] = $test->dataName(); + + foreach ($reflector->getParameters() as $parameter) { + if (!array_key_exists($i, $providedDataValues) && $parameter->isDefaultValueAvailable()) { + try { + $providedDataValues[$i] = $parameter->getDefaultValue(); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new UtilException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + $value = $providedDataValues[$i++] ?? null; + + if (is_object($value)) { + $reflector = new ReflectionObject($value); + + if ($reflector->hasMethod('__toString')) { + $value = (string) $value; + } else { + $value = get_class($value); + } + } + + if (!is_scalar($value)) { + $value = gettype($value); + } + + if (is_bool($value) || is_int($value) || is_float($value)) { + $value = (new Exporter)->export($value); + } + + if (is_string($value) && $value === '') { + if ($this->useColor) { + $value = Color::colorize('dim,underlined', 'empty'); + } else { + $value = "''"; + } + } + + $providedData['$' . $parameter->getName()] = $value; + } + + if ($this->useColor) { + $providedData = array_map(static function ($value) + { + return Color::colorize('fg-cyan', Color::visualizeWhitespace((string) $value, true)); + }, $providedData); + } + + return $providedData; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php b/vendor/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php new file mode 100644 index 00000000..c4b63644 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php @@ -0,0 +1,343 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\TestDox; + +use function get_class; +use function in_array; +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\ErrorTestCase; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Framework\Warning; +use PHPUnit\Framework\WarningTestCase; +use PHPUnit\Runner\BaseTestRunner; +use PHPUnit\TextUI\ResultPrinter as ResultPrinterInterface; +use PHPUnit\Util\Printer; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class ResultPrinter extends Printer implements ResultPrinterInterface +{ + /** + * @var NamePrettifier + */ + protected $prettifier; + + /** + * @var string + */ + protected $testClass = ''; + + /** + * @var int + */ + protected $testStatus; + + /** + * @var array + */ + protected $tests = []; + + /** + * @var int + */ + protected $successful = 0; + + /** + * @var int + */ + protected $warned = 0; + + /** + * @var int + */ + protected $failed = 0; + + /** + * @var int + */ + protected $risky = 0; + + /** + * @var int + */ + protected $skipped = 0; + + /** + * @var int + */ + protected $incomplete = 0; + + /** + * @var null|string + */ + protected $currentTestClassPrettified; + + /** + * @var null|string + */ + protected $currentTestMethodPrettified; + + /** + * @var array + */ + private $groups; + + /** + * @var array + */ + private $excludeGroups; + + /** + * @param resource $out + * + * @throws \PHPUnit\Framework\Exception + */ + public function __construct($out = null, array $groups = [], array $excludeGroups = []) + { + parent::__construct($out); + + $this->groups = $groups; + $this->excludeGroups = $excludeGroups; + + $this->prettifier = new NamePrettifier; + $this->startRun(); + } + + /** + * Flush buffer and close output. + */ + public function flush(): void + { + $this->doEndClass(); + $this->endRun(); + + parent::flush(); + } + + /** + * An error occurred. + */ + public function addError(Test $test, Throwable $t, float $time): void + { + if (!$this->isOfInterest($test)) { + return; + } + + $this->testStatus = BaseTestRunner::STATUS_ERROR; + $this->failed++; + } + + /** + * A warning occurred. + */ + public function addWarning(Test $test, Warning $e, float $time): void + { + if (!$this->isOfInterest($test)) { + return; + } + + $this->testStatus = BaseTestRunner::STATUS_WARNING; + $this->warned++; + } + + /** + * A failure occurred. + */ + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + if (!$this->isOfInterest($test)) { + return; + } + + $this->testStatus = BaseTestRunner::STATUS_FAILURE; + $this->failed++; + } + + /** + * Incomplete test. + */ + public function addIncompleteTest(Test $test, Throwable $t, float $time): void + { + if (!$this->isOfInterest($test)) { + return; + } + + $this->testStatus = BaseTestRunner::STATUS_INCOMPLETE; + $this->incomplete++; + } + + /** + * Risky test. + */ + public function addRiskyTest(Test $test, Throwable $t, float $time): void + { + if (!$this->isOfInterest($test)) { + return; + } + + $this->testStatus = BaseTestRunner::STATUS_RISKY; + $this->risky++; + } + + /** + * Skipped test. + */ + public function addSkippedTest(Test $test, Throwable $t, float $time): void + { + if (!$this->isOfInterest($test)) { + return; + } + + $this->testStatus = BaseTestRunner::STATUS_SKIPPED; + $this->skipped++; + } + + /** + * A testsuite started. + */ + public function startTestSuite(TestSuite $suite): void + { + } + + /** + * A testsuite ended. + */ + public function endTestSuite(TestSuite $suite): void + { + } + + /** + * A test started. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function startTest(Test $test): void + { + if (!$this->isOfInterest($test)) { + return; + } + + $class = get_class($test); + + if ($this->testClass !== $class) { + if ($this->testClass !== '') { + $this->doEndClass(); + } + + $this->currentTestClassPrettified = $this->prettifier->prettifyTestClass($class); + $this->testClass = $class; + $this->tests = []; + + $this->startClass($class); + } + + if ($test instanceof TestCase) { + $this->currentTestMethodPrettified = $this->prettifier->prettifyTestCase($test); + } + + $this->testStatus = BaseTestRunner::STATUS_PASSED; + } + + /** + * A test ended. + */ + public function endTest(Test $test, float $time): void + { + if (!$this->isOfInterest($test)) { + return; + } + + $this->tests[] = [$this->currentTestMethodPrettified, $this->testStatus]; + + $this->currentTestClassPrettified = null; + $this->currentTestMethodPrettified = null; + } + + protected function doEndClass(): void + { + foreach ($this->tests as $test) { + $this->onTest($test[0], $test[1] === BaseTestRunner::STATUS_PASSED); + } + + $this->endClass($this->testClass); + } + + /** + * Handler for 'start run' event. + */ + protected function startRun(): void + { + } + + /** + * Handler for 'start class' event. + */ + protected function startClass(string $name): void + { + } + + /** + * Handler for 'on test' event. + */ + protected function onTest(string $name, bool $success = true): void + { + } + + /** + * Handler for 'end class' event. + */ + protected function endClass(string $name): void + { + } + + /** + * Handler for 'end run' event. + */ + protected function endRun(): void + { + } + + private function isOfInterest(Test $test): bool + { + if (!$test instanceof TestCase) { + return false; + } + + if ($test instanceof ErrorTestCase || $test instanceof WarningTestCase) { + return false; + } + + if (!empty($this->groups)) { + foreach ($test->getGroups() as $group) { + if (in_array($group, $this->groups, true)) { + return true; + } + } + + return false; + } + + if (!empty($this->excludeGroups)) { + foreach ($test->getGroups() as $group) { + if (in_array($group, $this->excludeGroups, true)) { + return false; + } + } + + return true; + } + + return true; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/TestDox/TestDoxPrinter.php b/vendor/phpunit/phpunit/src/Util/TestDox/TestDoxPrinter.php new file mode 100644 index 00000000..bd64785c --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/TestDox/TestDoxPrinter.php @@ -0,0 +1,388 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\TestDox; + +use const PHP_EOL; +use function array_map; +use function get_class; +use function implode; +use function method_exists; +use function preg_split; +use function trim; +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\Reorderable; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestResult; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Framework\Warning; +use PHPUnit\Runner\BaseTestRunner; +use PHPUnit\Runner\PhptTestCase; +use PHPUnit\TextUI\DefaultResultPrinter; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class TestDoxPrinter extends DefaultResultPrinter +{ + /** + * @var NamePrettifier + */ + protected $prettifier; + + /** + * @var int The number of test results received from the TestRunner + */ + protected $testIndex = 0; + + /** + * @var int The number of test results already sent to the output + */ + protected $testFlushIndex = 0; + + /** + * @var array Buffer for test results + */ + protected $testResults = []; + + /** + * @var array Lookup table for testname to testResults[index] + */ + protected $testNameResultIndex = []; + + /** + * @var bool + */ + protected $enableOutputBuffer = false; + + /** + * @var array array + */ + protected $originalExecutionOrder = []; + + /** + * @var int + */ + protected $spinState = 0; + + /** + * @var bool + */ + protected $showProgress = true; + + /** + * @param null|resource|string $out + * @param int|string $numberOfColumns + * + * @throws \PHPUnit\Framework\Exception + */ + public function __construct($out = null, bool $verbose = false, string $colors = self::COLOR_DEFAULT, bool $debug = false, $numberOfColumns = 80, bool $reverse = false) + { + parent::__construct($out, $verbose, $colors, $debug, $numberOfColumns, $reverse); + + $this->prettifier = new NamePrettifier($this->colors); + } + + public function setOriginalExecutionOrder(array $order): void + { + $this->originalExecutionOrder = $order; + $this->enableOutputBuffer = !empty($order); + } + + public function setShowProgressAnimation(bool $showProgress): void + { + $this->showProgress = $showProgress; + } + + public function printResult(TestResult $result): void + { + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function endTest(Test $test, float $time): void + { + if (!$test instanceof TestCase && !$test instanceof PhptTestCase && !$test instanceof TestSuite) { + return; + } + + if ($this->testHasPassed()) { + $this->registerTestResult($test, null, BaseTestRunner::STATUS_PASSED, $time, false); + } + + if ($test instanceof TestCase || $test instanceof PhptTestCase) { + $this->testIndex++; + } + + parent::endTest($test, $time); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function addError(Test $test, Throwable $t, float $time): void + { + $this->registerTestResult($test, $t, BaseTestRunner::STATUS_ERROR, $time, true); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function addWarning(Test $test, Warning $e, float $time): void + { + $this->registerTestResult($test, $e, BaseTestRunner::STATUS_WARNING, $time, true); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + $this->registerTestResult($test, $e, BaseTestRunner::STATUS_FAILURE, $time, true); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function addIncompleteTest(Test $test, Throwable $t, float $time): void + { + $this->registerTestResult($test, $t, BaseTestRunner::STATUS_INCOMPLETE, $time, false); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function addRiskyTest(Test $test, Throwable $t, float $time): void + { + $this->registerTestResult($test, $t, BaseTestRunner::STATUS_RISKY, $time, false); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function addSkippedTest(Test $test, Throwable $t, float $time): void + { + $this->registerTestResult($test, $t, BaseTestRunner::STATUS_SKIPPED, $time, false); + } + + public function writeProgress(string $progress): void + { + $this->flushOutputBuffer(); + } + + public function flush(): void + { + $this->flushOutputBuffer(true); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function registerTestResult(Test $test, ?Throwable $t, int $status, float $time, bool $verbose): void + { + $testName = $test instanceof Reorderable ? $test->sortId() : $test->getName(); + + $result = [ + 'className' => $this->formatClassName($test), + 'testName' => $testName, + 'testMethod' => $this->formatTestName($test), + 'message' => '', + 'status' => $status, + 'time' => $time, + 'verbose' => $verbose, + ]; + + if ($t !== null) { + $result['message'] = $this->formatTestResultMessage($t, $result); + } + + $this->testResults[$this->testIndex] = $result; + $this->testNameResultIndex[$testName] = $this->testIndex; + } + + protected function formatTestName(Test $test): string + { + return method_exists($test, 'getName') ? $test->getName() : ''; + } + + protected function formatClassName(Test $test): string + { + return get_class($test); + } + + protected function testHasPassed(): bool + { + if (!isset($this->testResults[$this->testIndex]['status'])) { + return true; + } + + if ($this->testResults[$this->testIndex]['status'] === BaseTestRunner::STATUS_PASSED) { + return true; + } + + return false; + } + + protected function flushOutputBuffer(bool $forceFlush = false): void + { + if ($this->testFlushIndex === $this->testIndex) { + return; + } + + if ($this->testFlushIndex > 0) { + if ($this->enableOutputBuffer && + isset($this->originalExecutionOrder[$this->testFlushIndex - 1])) { + $prevResult = $this->getTestResultByName($this->originalExecutionOrder[$this->testFlushIndex - 1]); + } else { + $prevResult = $this->testResults[$this->testFlushIndex - 1]; + } + } else { + $prevResult = $this->getEmptyTestResult(); + } + + if (!$this->enableOutputBuffer) { + $this->writeTestResult($prevResult, $this->testResults[$this->testFlushIndex++]); + } else { + do { + $flushed = false; + + if (!$forceFlush && isset($this->originalExecutionOrder[$this->testFlushIndex])) { + $result = $this->getTestResultByName($this->originalExecutionOrder[$this->testFlushIndex]); + } else { + // This test(name) cannot found in original execution order, + // flush result to output stream right away + $result = $this->testResults[$this->testFlushIndex]; + } + + if (!empty($result)) { + $this->hideSpinner(); + $this->writeTestResult($prevResult, $result); + $this->testFlushIndex++; + $prevResult = $result; + $flushed = true; + } else { + $this->showSpinner(); + } + } while ($flushed && $this->testFlushIndex < $this->testIndex); + } + } + + protected function showSpinner(): void + { + if (!$this->showProgress) { + return; + } + + if ($this->spinState) { + $this->undrawSpinner(); + } + + $this->spinState++; + $this->drawSpinner(); + } + + protected function hideSpinner(): void + { + if (!$this->showProgress) { + return; + } + + if ($this->spinState) { + $this->undrawSpinner(); + } + + $this->spinState = 0; + } + + protected function drawSpinner(): void + { + // optional for CLI printers: show the user a 'buffering output' spinner + } + + protected function undrawSpinner(): void + { + // remove the spinner from the current line + } + + protected function writeTestResult(array $prevResult, array $result): void + { + } + + protected function getEmptyTestResult(): array + { + return [ + 'className' => '', + 'testName' => '', + 'message' => '', + 'failed' => '', + 'verbose' => '', + ]; + } + + protected function getTestResultByName(?string $testName): array + { + if (isset($this->testNameResultIndex[$testName])) { + return $this->testResults[$this->testNameResultIndex[$testName]]; + } + + return []; + } + + protected function formatThrowable(Throwable $t, ?int $status = null): string + { + $message = trim(\PHPUnit\Framework\TestFailure::exceptionToString($t)); + + if ($message) { + $message .= PHP_EOL . PHP_EOL . $this->formatStacktrace($t); + } else { + $message = $this->formatStacktrace($t); + } + + return $message; + } + + protected function formatStacktrace(Throwable $t): string + { + return \PHPUnit\Util\Filter::getFilteredStacktrace($t); + } + + protected function formatTestResultMessage(Throwable $t, array $result, string $prefix = '│'): string + { + $message = $this->formatThrowable($t, $result['status']); + + if ($message === '') { + return ''; + } + + if (!($this->verbose || $result['verbose'])) { + return ''; + } + + return $this->prefixLines($prefix, $message); + } + + protected function prefixLines(string $prefix, string $message): string + { + $message = trim($message); + + return implode( + PHP_EOL, + array_map( + static function (string $text) use ($prefix) + { + return ' ' . $prefix . ($text ? ' ' . $text : ''); + }, + preg_split('/\r\n|\r|\n/', $message) + ) + ); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/TestDox/TextResultPrinter.php b/vendor/phpunit/phpunit/src/Util/TestDox/TextResultPrinter.php new file mode 100644 index 00000000..8a1893e5 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/TestDox/TextResultPrinter.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\TestDox; + +use PHPUnit\Framework\TestResult; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TextResultPrinter extends ResultPrinter +{ + public function printResult(TestResult $result): void + { + } + + /** + * Handler for 'start class' event. + */ + protected function startClass(string $name): void + { + $this->write($this->currentTestClassPrettified . "\n"); + } + + /** + * Handler for 'on test' event. + */ + protected function onTest(string $name, bool $success = true): void + { + if ($success) { + $this->write(' [x] '); + } else { + $this->write(' [ ] '); + } + + $this->write($name . "\n"); + } + + /** + * Handler for 'end class' event. + */ + protected function endClass(string $name): void + { + $this->write("\n"); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/TestDox/XmlResultPrinter.php b/vendor/phpunit/phpunit/src/Util/TestDox/XmlResultPrinter.php new file mode 100644 index 00000000..265fe41f --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/TestDox/XmlResultPrinter.php @@ -0,0 +1,261 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\TestDox; + +use function array_filter; +use function get_class; +use function implode; +use function strpos; +use DOMDocument; +use DOMElement; +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\Exception; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestListener; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Framework\Warning; +use PHPUnit\Framework\WarningTestCase; +use PHPUnit\Util\Printer; +use PHPUnit\Util\Test as TestUtil; +use ReflectionClass; +use ReflectionException; +use Throwable; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class XmlResultPrinter extends Printer implements TestListener +{ + /** + * @var DOMDocument + */ + private $document; + + /** + * @var DOMElement + */ + private $root; + + /** + * @var NamePrettifier + */ + private $prettifier; + + /** + * @var null|Throwable + */ + private $exception; + + /** + * @param resource|string $out + * + * @throws Exception + */ + public function __construct($out = null) + { + $this->document = new DOMDocument('1.0', 'UTF-8'); + $this->document->formatOutput = true; + + $this->root = $this->document->createElement('tests'); + $this->document->appendChild($this->root); + + $this->prettifier = new NamePrettifier; + + parent::__construct($out); + } + + /** + * Flush buffer and close output. + */ + public function flush(): void + { + $this->write($this->document->saveXML()); + + parent::flush(); + } + + /** + * An error occurred. + */ + public function addError(Test $test, Throwable $t, float $time): void + { + $this->exception = $t; + } + + /** + * A warning occurred. + */ + public function addWarning(Test $test, Warning $e, float $time): void + { + } + + /** + * A failure occurred. + */ + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + $this->exception = $e; + } + + /** + * Incomplete test. + */ + public function addIncompleteTest(Test $test, Throwable $t, float $time): void + { + } + + /** + * Risky test. + */ + public function addRiskyTest(Test $test, Throwable $t, float $time): void + { + } + + /** + * Skipped test. + */ + public function addSkippedTest(Test $test, Throwable $t, float $time): void + { + } + + /** + * A test suite started. + */ + public function startTestSuite(TestSuite $suite): void + { + } + + /** + * A test suite ended. + */ + public function endTestSuite(TestSuite $suite): void + { + } + + /** + * A test started. + */ + public function startTest(Test $test): void + { + $this->exception = null; + } + + /** + * A test ended. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function endTest(Test $test, float $time): void + { + if (!$test instanceof TestCase || $test instanceof WarningTestCase) { + return; + } + + $groups = array_filter( + $test->getGroups(), + static function ($group) + { + return !($group === 'small' || $group === 'medium' || $group === 'large' || strpos($group, '__phpunit_') === 0); + } + ); + + $testNode = $this->document->createElement('test'); + + $testNode->setAttribute('className', get_class($test)); + $testNode->setAttribute('methodName', $test->getName()); + $testNode->setAttribute('prettifiedClassName', $this->prettifier->prettifyTestClass(get_class($test))); + $testNode->setAttribute('prettifiedMethodName', $this->prettifier->prettifyTestCase($test)); + $testNode->setAttribute('status', (string) $test->getStatus()); + $testNode->setAttribute('time', (string) $time); + $testNode->setAttribute('size', (string) $test->getSize()); + $testNode->setAttribute('groups', implode(',', $groups)); + + foreach ($groups as $group) { + $groupNode = $this->document->createElement('group'); + + $groupNode->setAttribute('name', $group); + + $testNode->appendChild($groupNode); + } + + $annotations = TestUtil::parseTestMethodAnnotations( + get_class($test), + $test->getName(false) + ); + + foreach (['class', 'method'] as $type) { + foreach ($annotations[$type] as $annotation => $values) { + if ($annotation !== 'covers' && $annotation !== 'uses') { + continue; + } + + foreach ($values as $value) { + $coversNode = $this->document->createElement($annotation); + + $coversNode->setAttribute('target', $value); + + $testNode->appendChild($coversNode); + } + } + } + + foreach ($test->doubledTypes() as $doubledType) { + $testDoubleNode = $this->document->createElement('testDouble'); + + $testDoubleNode->setAttribute('type', $doubledType); + + $testNode->appendChild($testDoubleNode); + } + + $inlineAnnotations = \PHPUnit\Util\Test::getInlineAnnotations(get_class($test), $test->getName(false)); + + if (isset($inlineAnnotations['given'], $inlineAnnotations['when'], $inlineAnnotations['then'])) { + $testNode->setAttribute('given', $inlineAnnotations['given']['value']); + $testNode->setAttribute('givenStartLine', (string) $inlineAnnotations['given']['line']); + $testNode->setAttribute('when', $inlineAnnotations['when']['value']); + $testNode->setAttribute('whenStartLine', (string) $inlineAnnotations['when']['line']); + $testNode->setAttribute('then', $inlineAnnotations['then']['value']); + $testNode->setAttribute('thenStartLine', (string) $inlineAnnotations['then']['line']); + } + + if ($this->exception !== null) { + if ($this->exception instanceof Exception) { + $steps = $this->exception->getSerializableTrace(); + } else { + $steps = $this->exception->getTrace(); + } + + try { + $file = (new ReflectionClass($test))->getFileName(); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + + foreach ($steps as $step) { + if (isset($step['file']) && $step['file'] === $file) { + $testNode->setAttribute('exceptionLine', (string) $step['line']); + + break; + } + } + + $testNode->setAttribute('exceptionMessage', $this->exception->getMessage()); + } + + $this->root->appendChild($testNode); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/TextTestListRenderer.php b/vendor/phpunit/phpunit/src/Util/TextTestListRenderer.php new file mode 100644 index 00000000..67168a67 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/TextTestListRenderer.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const PHP_EOL; +use function get_class; +use function sprintf; +use function str_replace; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\PhptTestCase; +use RecursiveIteratorIterator; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TextTestListRenderer +{ + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function render(TestSuite $suite): string + { + $buffer = 'Available test(s):' . PHP_EOL; + + foreach (new RecursiveIteratorIterator($suite->getIterator()) as $test) { + if ($test instanceof TestCase) { + $name = sprintf( + '%s::%s', + get_class($test), + str_replace(' with data set ', '', $test->getName()) + ); + } elseif ($test instanceof PhptTestCase) { + $name = $test->getName(); + } else { + continue; + } + + $buffer .= sprintf( + ' - %s' . PHP_EOL, + $name + ); + } + + return $buffer; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Type.php b/vendor/phpunit/phpunit/src/Util/Type.php new file mode 100644 index 00000000..ec6a1d78 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Type.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Type +{ + public static function isType(string $type): bool + { + switch ($type) { + case 'numeric': + case 'integer': + case 'int': + case 'iterable': + case 'float': + case 'string': + case 'boolean': + case 'bool': + case 'null': + case 'array': + case 'object': + case 'resource': + case 'scalar': + return true; + + default: + return false; + } + } +} diff --git a/vendor/phpunit/phpunit/src/Util/VersionComparisonOperator.php b/vendor/phpunit/phpunit/src/Util/VersionComparisonOperator.php new file mode 100644 index 00000000..77e67470 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/VersionComparisonOperator.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use function in_array; +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class VersionComparisonOperator +{ + /** + * @psalm-var '<'|'lt'|'<='|'le'|'>'|'gt'|'>='|'ge'|'=='|'='|'eq'|'!='|'<>'|'ne' + */ + private $operator; + + public function __construct(string $operator) + { + $this->ensureOperatorIsValid($operator); + + $this->operator = $operator; + } + + /** + * @return '!='|'<'|'<='|'<>'|'='|'=='|'>'|'>='|'eq'|'ge'|'gt'|'le'|'lt'|'ne' + */ + public function asString(): string + { + return $this->operator; + } + + /** + * @throws Exception + * + * @psalm-assert '<'|'lt'|'<='|'le'|'>'|'gt'|'>='|'ge'|'=='|'='|'eq'|'!='|'<>'|'ne' $operator + */ + private function ensureOperatorIsValid(string $operator): void + { + if (!in_array($operator, ['<', 'lt', '<=', 'le', '>', 'gt', '>=', 'ge', '==', '=', 'eq', '!=', '<>', 'ne'], true)) { + throw new Exception( + sprintf( + '"%s" is not a valid version_compare() operator', + $operator + ) + ); + } + } +} diff --git a/vendor/phpunit/phpunit/src/Util/XdebugFilterScriptGenerator.php b/vendor/phpunit/phpunit/src/Util/XdebugFilterScriptGenerator.php new file mode 100644 index 00000000..8b10d415 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/XdebugFilterScriptGenerator.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const DIRECTORY_SEPARATOR; +use function addslashes; +use function array_map; +use function implode; +use function is_string; +use function realpath; +use function sprintf; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\CodeCoverage as FilterConfiguration; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @deprecated + */ +final class XdebugFilterScriptGenerator +{ + public function generate(FilterConfiguration $filter): string + { + $files = array_map( + static function ($item) + { + return sprintf( + " '%s'", + $item + ); + }, + $this->getItems($filter) + ); + + $files = implode(",\n", $files); + + return <<directories() as $directory) { + $path = realpath($directory->path()); + + if (is_string($path)) { + $files[] = sprintf( + addslashes('%s' . DIRECTORY_SEPARATOR), + $path + ); + } + } + + foreach ($filter->files() as $file) { + $files[] = $file->path(); + } + + return $files; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Xml.php b/vendor/phpunit/phpunit/src/Util/Xml.php new file mode 100644 index 00000000..54d72156 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Xml.php @@ -0,0 +1,193 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const ENT_QUOTES; +use function assert; +use function class_exists; +use function htmlspecialchars; +use function mb_convert_encoding; +use function ord; +use function preg_replace; +use function settype; +use function strlen; +use DOMCharacterData; +use DOMDocument; +use DOMElement; +use DOMNode; +use DOMText; +use ReflectionClass; +use ReflectionException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Xml +{ + /** + * @deprecated Only used by assertEqualXMLStructure() + */ + public static function import(DOMElement $element): DOMElement + { + return (new DOMDocument)->importNode($element, true); + } + + /** + * @deprecated Only used by assertEqualXMLStructure() + */ + public static function removeCharacterDataNodes(DOMNode $node): void + { + if ($node->hasChildNodes()) { + for ($i = $node->childNodes->length - 1; $i >= 0; $i--) { + if (($child = $node->childNodes->item($i)) instanceof DOMCharacterData) { + $node->removeChild($child); + } + } + } + } + + /** + * Escapes a string for the use in XML documents. + * + * Any Unicode character is allowed, excluding the surrogate blocks, FFFE, + * and FFFF (not even as character reference). + * + * @see https://www.w3.org/TR/xml/#charsets + */ + public static function prepareString(string $string): string + { + return preg_replace( + '/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/', + '', + htmlspecialchars( + self::convertToUtf8($string), + ENT_QUOTES + ) + ); + } + + /** + * "Convert" a DOMElement object into a PHP variable. + */ + public static function xmlToVariable(DOMElement $element) + { + $variable = null; + + switch ($element->tagName) { + case 'array': + $variable = []; + + foreach ($element->childNodes as $entry) { + if (!$entry instanceof DOMElement || $entry->tagName !== 'element') { + continue; + } + $item = $entry->childNodes->item(0); + + if ($item instanceof DOMText) { + $item = $entry->childNodes->item(1); + } + + $value = self::xmlToVariable($item); + + if ($entry->hasAttribute('key')) { + $variable[(string) $entry->getAttribute('key')] = $value; + } else { + $variable[] = $value; + } + } + + break; + + case 'object': + $className = $element->getAttribute('class'); + + if ($element->hasChildNodes()) { + $arguments = $element->childNodes->item(0)->childNodes; + $constructorArgs = []; + + foreach ($arguments as $argument) { + if ($argument instanceof DOMElement) { + $constructorArgs[] = self::xmlToVariable($argument); + } + } + + try { + assert(class_exists($className)); + + $variable = (new ReflectionClass($className))->newInstanceArgs($constructorArgs); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } else { + $variable = new $className; + } + + break; + + case 'boolean': + $variable = $element->textContent === 'true'; + + break; + + case 'integer': + case 'double': + case 'string': + $variable = $element->textContent; + + settype($variable, $element->tagName); + + break; + } + + return $variable; + } + + private static function convertToUtf8(string $string): string + { + if (!self::isUtf8($string)) { + $string = mb_convert_encoding($string, 'UTF-8'); + } + + return $string; + } + + private static function isUtf8(string $string): bool + { + $length = strlen($string); + + for ($i = 0; $i < $length; $i++) { + if (ord($string[$i]) < 0x80) { + $n = 0; + } elseif ((ord($string[$i]) & 0xE0) === 0xC0) { + $n = 1; + } elseif ((ord($string[$i]) & 0xF0) === 0xE0) { + $n = 2; + } elseif ((ord($string[$i]) & 0xF0) === 0xF0) { + $n = 3; + } else { + return false; + } + + for ($j = 0; $j < $n; $j++) { + if ((++$i === $length) || ((ord($string[$i]) & 0xC0) !== 0x80)) { + return false; + } + } + } + + return true; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Xml/Exception.php b/vendor/phpunit/phpunit/src/Util/Xml/Exception.php new file mode 100644 index 00000000..09b73d8f --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Xml/Exception.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Xml; + +use RuntimeException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Exception extends RuntimeException implements \PHPUnit\Exception +{ +} diff --git a/vendor/phpunit/phpunit/src/Util/Xml/FailedSchemaDetectionResult.php b/vendor/phpunit/phpunit/src/Util/Xml/FailedSchemaDetectionResult.php new file mode 100644 index 00000000..0949f568 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Xml/FailedSchemaDetectionResult.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Xml; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class FailedSchemaDetectionResult extends SchemaDetectionResult +{ +} diff --git a/vendor/phpunit/phpunit/src/Util/Xml/Loader.php b/vendor/phpunit/phpunit/src/Util/Xml/Loader.php new file mode 100644 index 00000000..8d43d327 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Xml/Loader.php @@ -0,0 +1,117 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Xml; + +use function chdir; +use function dirname; +use function error_reporting; +use function file_get_contents; +use function getcwd; +use function libxml_get_errors; +use function libxml_use_internal_errors; +use function sprintf; +use DOMDocument; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Loader +{ + /** + * @throws Exception + */ + public function loadFile(string $filename, bool $isHtml = false, bool $xinclude = false, bool $strict = false): DOMDocument + { + $reporting = error_reporting(0); + $contents = file_get_contents($filename); + + error_reporting($reporting); + + if ($contents === false) { + throw new Exception( + sprintf( + 'Could not read "%s".', + $filename + ) + ); + } + + return $this->load($contents, $isHtml, $filename, $xinclude, $strict); + } + + /** + * @throws Exception + */ + public function load(string $actual, bool $isHtml = false, string $filename = '', bool $xinclude = false, bool $strict = false): DOMDocument + { + if ($actual === '') { + throw new Exception('Could not load XML from empty string'); + } + + // Required for XInclude on Windows. + if ($xinclude) { + $cwd = getcwd(); + @chdir(dirname($filename)); + } + + $document = new DOMDocument; + $document->preserveWhiteSpace = false; + + $internal = libxml_use_internal_errors(true); + $message = ''; + $reporting = error_reporting(0); + + if ($filename !== '') { + // Required for XInclude + $document->documentURI = $filename; + } + + if ($isHtml) { + $loaded = $document->loadHTML($actual); + } else { + $loaded = $document->loadXML($actual); + } + + if (!$isHtml && $xinclude) { + $document->xinclude(); + } + + foreach (libxml_get_errors() as $error) { + $message .= "\n" . $error->message; + } + + libxml_use_internal_errors($internal); + error_reporting($reporting); + + if (isset($cwd)) { + @chdir($cwd); + } + + if ($loaded === false || ($strict && $message !== '')) { + if ($filename !== '') { + throw new Exception( + sprintf( + 'Could not load "%s".%s', + $filename, + $message !== '' ? "\n" . $message : '' + ) + ); + } + + if ($message === '') { + $message = 'Could not load XML for unknown reason'; + } + + throw new Exception($message); + } + + return $document; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Xml/SchemaDetectionResult.php b/vendor/phpunit/phpunit/src/Util/Xml/SchemaDetectionResult.php new file mode 100644 index 00000000..442aae49 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Xml/SchemaDetectionResult.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Xml; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +abstract class SchemaDetectionResult +{ + public function detected(): bool + { + return false; + } + + /** + * @throws Exception + */ + public function version(): string + { + throw new Exception('No supported schema was detected'); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Xml/SchemaDetector.php b/vendor/phpunit/phpunit/src/Util/Xml/SchemaDetector.php new file mode 100644 index 00000000..5864695b --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Xml/SchemaDetector.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Xml; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SchemaDetector +{ + /** + * @throws Exception + */ + public function detect(string $filename): SchemaDetectionResult + { + $document = (new Loader)->loadFile( + $filename, + false, + true, + true + ); + + foreach (['9.2', '8.5'] as $candidate) { + $schema = (new SchemaFinder)->find($candidate); + + if (!(new Validator)->validate($document, $schema)->hasValidationErrors()) { + return new SuccessfulSchemaDetectionResult($candidate); + } + } + + return new FailedSchemaDetectionResult; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Xml/SchemaFinder.php b/vendor/phpunit/phpunit/src/Util/Xml/SchemaFinder.php new file mode 100644 index 00000000..1e7b73c5 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Xml/SchemaFinder.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Xml; + +use function defined; +use function is_file; +use function sprintf; +use PHPUnit\Runner\Version; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SchemaFinder +{ + /** + * @throws Exception + */ + public function find(string $version): string + { + if ($version === Version::series()) { + $filename = $this->path() . 'phpunit.xsd'; + } else { + $filename = $this->path() . 'schema/' . $version . '.xsd'; + } + + if (!is_file($filename)) { + throw new Exception( + sprintf( + 'Schema for PHPUnit %s is not available', + $version + ) + ); + } + + return $filename; + } + + private function path(): string + { + if (defined('__PHPUNIT_PHAR_ROOT__')) { + return __PHPUNIT_PHAR_ROOT__ . '/'; + } + + return __DIR__ . '/../../../'; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Xml/SnapshotNodeList.php b/vendor/phpunit/phpunit/src/Util/Xml/SnapshotNodeList.php new file mode 100644 index 00000000..e383678d --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Xml/SnapshotNodeList.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Xml; + +use function count; +use ArrayIterator; +use Countable; +use DOMNode; +use DOMNodeList; +use IteratorAggregate; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @template-implements IteratorAggregate + */ +final class SnapshotNodeList implements Countable, IteratorAggregate +{ + /** + * @var DOMNode[] + */ + private $nodes = []; + + public static function fromNodeList(DOMNodeList $list): self + { + $snapshot = new self; + + foreach ($list as $node) { + $snapshot->nodes[] = $node; + } + + return $snapshot; + } + + public function count(): int + { + return count($this->nodes); + } + + public function getIterator(): ArrayIterator + { + return new ArrayIterator($this->nodes); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Xml/SuccessfulSchemaDetectionResult.php b/vendor/phpunit/phpunit/src/Util/Xml/SuccessfulSchemaDetectionResult.php new file mode 100644 index 00000000..8b517e29 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Xml/SuccessfulSchemaDetectionResult.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Xml; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class SuccessfulSchemaDetectionResult extends SchemaDetectionResult +{ + /** + * @var string + */ + private $version; + + public function __construct(string $version) + { + $this->version = $version; + } + + public function detected(): bool + { + return true; + } + + public function version(): string + { + return $this->version; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Xml/ValidationResult.php b/vendor/phpunit/phpunit/src/Util/Xml/ValidationResult.php new file mode 100644 index 00000000..3292267b --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Xml/ValidationResult.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Xml; + +use function sprintf; +use function trim; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class ValidationResult +{ + /** + * @psalm-var array> + */ + private $validationErrors = []; + + /** + * @psalm-param array $errors + */ + public static function fromArray(array $errors): self + { + $validationErrors = []; + + foreach ($errors as $error) { + if (!isset($validationErrors[$error->line])) { + $validationErrors[$error->line] = []; + } + + $validationErrors[$error->line][] = trim($error->message); + } + + return new self($validationErrors); + } + + private function __construct(array $validationErrors) + { + $this->validationErrors = $validationErrors; + } + + public function hasValidationErrors(): bool + { + return !empty($this->validationErrors); + } + + public function asString(): string + { + $buffer = ''; + + foreach ($this->validationErrors as $line => $validationErrorsOnLine) { + $buffer .= sprintf(PHP_EOL . ' Line %d:' . PHP_EOL, $line); + + foreach ($validationErrorsOnLine as $validationError) { + $buffer .= sprintf(' - %s' . PHP_EOL, $validationError); + } + } + + return $buffer; + } +} diff --git a/vendor/phpunit/phpunit/src/Util/Xml/Validator.php b/vendor/phpunit/phpunit/src/Util/Xml/Validator.php new file mode 100644 index 00000000..b3c4e05b --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/Xml/Validator.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Xml; + +use function file_get_contents; +use function libxml_clear_errors; +use function libxml_get_errors; +use function libxml_use_internal_errors; +use DOMDocument; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Validator +{ + public function validate(DOMDocument $document, string $xsdFilename): ValidationResult + { + $originalErrorHandling = libxml_use_internal_errors(true); + + $document->schemaValidateSource(file_get_contents($xsdFilename)); + + $errors = libxml_get_errors(); + libxml_clear_errors(); + libxml_use_internal_errors($originalErrorHandling); + + return ValidationResult::fromArray($errors); + } +} diff --git a/vendor/phpunit/phpunit/src/Util/XmlTestListRenderer.php b/vendor/phpunit/phpunit/src/Util/XmlTestListRenderer.php new file mode 100644 index 00000000..b16ef0b7 --- /dev/null +++ b/vendor/phpunit/phpunit/src/Util/XmlTestListRenderer.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use function get_class; +use function implode; +use function str_replace; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\PhptTestCase; +use RecursiveIteratorIterator; +use XMLWriter; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class XmlTestListRenderer +{ + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function render(TestSuite $suite): string + { + $writer = new XMLWriter; + + $writer->openMemory(); + $writer->setIndent(true); + $writer->startDocument('1.0', 'UTF-8'); + $writer->startElement('tests'); + + $currentTestCase = null; + + foreach (new RecursiveIteratorIterator($suite->getIterator()) as $test) { + if ($test instanceof TestCase) { + if (get_class($test) !== $currentTestCase) { + if ($currentTestCase !== null) { + $writer->endElement(); + } + + $writer->startElement('testCaseClass'); + $writer->writeAttribute('name', get_class($test)); + + $currentTestCase = get_class($test); + } + + $writer->startElement('testCaseMethod'); + $writer->writeAttribute('name', $test->getName(false)); + $writer->writeAttribute('groups', implode(',', $test->getGroups())); + + if (!empty($test->getDataSetAsString(false))) { + $writer->writeAttribute( + 'dataSet', + str_replace( + ' with data set ', + '', + $test->getDataSetAsString(false) + ) + ); + } + + $writer->endElement(); + } elseif ($test instanceof PhptTestCase) { + if ($currentTestCase !== null) { + $writer->endElement(); + + $currentTestCase = null; + } + + $writer->startElement('phptFile'); + $writer->writeAttribute('path', $test->getName()); + $writer->endElement(); + } + } + + if ($currentTestCase !== null) { + $writer->endElement(); + } + + $writer->endElement(); + $writer->endDocument(); + + return $writer->outputMemory(); + } +} diff --git a/vendor/sebastian/cli-parser/ChangeLog.md b/vendor/sebastian/cli-parser/ChangeLog.md new file mode 100644 index 00000000..9431ec59 --- /dev/null +++ b/vendor/sebastian/cli-parser/ChangeLog.md @@ -0,0 +1,15 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [1.0.1] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [1.0.0] - 2020-08-12 + +* Initial release + +[1.0.0]: https://github.com/sebastianbergmann/cli-parser/compare/bb7bb3297957927962b0a3335befe7b66f7462e9...1.0.0 diff --git a/vendor/sebastian/cli-parser/LICENSE b/vendor/sebastian/cli-parser/LICENSE new file mode 100644 index 00000000..0e33c059 --- /dev/null +++ b/vendor/sebastian/cli-parser/LICENSE @@ -0,0 +1,33 @@ +sebastian/cli-parser + +Copyright (c) 2020, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/cli-parser/README.md b/vendor/sebastian/cli-parser/README.md new file mode 100644 index 00000000..39c17a72 --- /dev/null +++ b/vendor/sebastian/cli-parser/README.md @@ -0,0 +1,17 @@ +# sebastian/cli-parser + +Library for parsing `$_SERVER['argv']`, extracted from `phpunit/phpunit`. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/cli-parser +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/cli-parser +``` diff --git a/vendor/sebastian/cli-parser/composer.json b/vendor/sebastian/cli-parser/composer.json new file mode 100644 index 00000000..34c376f9 --- /dev/null +++ b/vendor/sebastian/cli-parser/composer.json @@ -0,0 +1,41 @@ +{ + "name": "sebastian/cli-parser", + "description": "Library for parsing CLI options", + "type": "library", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues" + }, + "prefer-stable": true, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + } +} diff --git a/vendor/sebastian/cli-parser/infection.json b/vendor/sebastian/cli-parser/infection.json new file mode 100644 index 00000000..09546514 --- /dev/null +++ b/vendor/sebastian/cli-parser/infection.json @@ -0,0 +1,12 @@ +{ + "source": { + "directories": [ + "src" + ] + }, + "mutators": { + "@default": true + }, + "minMsi": 100, + "minCoveredMsi": 100 +} diff --git a/vendor/sebastian/cli-parser/src/Parser.php b/vendor/sebastian/cli-parser/src/Parser.php new file mode 100644 index 00000000..a4f728bc --- /dev/null +++ b/vendor/sebastian/cli-parser/src/Parser.php @@ -0,0 +1,204 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CliParser; + +use function array_map; +use function array_merge; +use function array_shift; +use function array_slice; +use function assert; +use function count; +use function current; +use function explode; +use function is_array; +use function is_int; +use function is_string; +use function key; +use function next; +use function preg_replace; +use function reset; +use function sort; +use function strlen; +use function strpos; +use function strstr; +use function substr; + +final class Parser +{ + /** + * @psalm-param list $argv + * @psalm-param list $longOptions + * + * @throws AmbiguousOptionException + * @throws RequiredOptionArgumentMissingException + * @throws OptionDoesNotAllowArgumentException + * @throws UnknownOptionException + */ + public function parse(array $argv, string $shortOptions, array $longOptions = null): array + { + if (empty($argv)) { + return [[], []]; + } + + $options = []; + $nonOptions = []; + + if ($longOptions) { + sort($longOptions); + } + + if (isset($argv[0][0]) && $argv[0][0] !== '-') { + array_shift($argv); + } + + reset($argv); + + $argv = array_map('trim', $argv); + + while (false !== $arg = current($argv)) { + $i = key($argv); + + assert(is_int($i)); + + next($argv); + + if ($arg === '') { + continue; + } + + if ($arg === '--') { + $nonOptions = array_merge($nonOptions, array_slice($argv, $i + 1)); + + break; + } + + if ($arg[0] !== '-' || (strlen($arg) > 1 && $arg[1] === '-' && !$longOptions)) { + $nonOptions[] = $arg; + + continue; + } + + if (strlen($arg) > 1 && $arg[1] === '-' && is_array($longOptions)) { + $this->parseLongOption( + substr($arg, 2), + $longOptions, + $options, + $argv + ); + } else { + $this->parseShortOption( + substr($arg, 1), + $shortOptions, + $options, + $argv + ); + } + } + + return [$options, $nonOptions]; + } + + /** + * @throws RequiredOptionArgumentMissingException + */ + private function parseShortOption(string $arg, string $shortOptions, array &$opts, array &$args): void + { + $argLength = strlen($arg); + + for ($i = 0; $i < $argLength; $i++) { + $option = $arg[$i]; + $optionArgument = null; + + if ($arg[$i] === ':' || ($spec = strstr($shortOptions, $option)) === false) { + throw new UnknownOptionException('-' . $option); + } + + assert(is_string($spec)); + + if (strlen($spec) > 1 && $spec[1] === ':') { + if ($i + 1 < $argLength) { + $opts[] = [$option, substr($arg, $i + 1)]; + + break; + } + + if (!(strlen($spec) > 2 && $spec[2] === ':')) { + $optionArgument = current($args); + + if (!$optionArgument) { + throw new RequiredOptionArgumentMissingException('-' . $option); + } + + assert(is_string($optionArgument)); + + next($args); + } + } + + $opts[] = [$option, $optionArgument]; + } + } + + /** + * @psalm-param list $longOptions + * + * @throws AmbiguousOptionException + * @throws RequiredOptionArgumentMissingException + * @throws OptionDoesNotAllowArgumentException + * @throws UnknownOptionException + */ + private function parseLongOption(string $arg, array $longOptions, array &$opts, array &$args): void + { + $count = count($longOptions); + $list = explode('=', $arg); + $option = $list[0]; + $optionArgument = null; + + if (count($list) > 1) { + $optionArgument = $list[1]; + } + + $optionLength = strlen($option); + + foreach ($longOptions as $i => $longOption) { + $opt_start = substr($longOption, 0, $optionLength); + + if ($opt_start !== $option) { + continue; + } + + $opt_rest = substr($longOption, $optionLength); + + if ($opt_rest !== '' && $i + 1 < $count && $option[0] !== '=' && strpos($longOptions[$i + 1], $option) === 0) { + throw new AmbiguousOptionException('--' . $option); + } + + if (substr($longOption, -1) === '=') { + /* @noinspection StrlenInEmptyStringCheckContextInspection */ + if (substr($longOption, -2) !== '==' && !strlen((string) $optionArgument)) { + if (false === $optionArgument = current($args)) { + throw new RequiredOptionArgumentMissingException('--' . $option); + } + + next($args); + } + } elseif ($optionArgument) { + throw new OptionDoesNotAllowArgumentException('--' . $option); + } + + $fullOption = '--' . preg_replace('/={1,2}$/', '', $longOption); + $opts[] = [$fullOption, $optionArgument]; + + return; + } + + throw new UnknownOptionException('--' . $option); + } +} diff --git a/vendor/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php b/vendor/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php new file mode 100644 index 00000000..a99f6369 --- /dev/null +++ b/vendor/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CliParser; + +use function sprintf; +use RuntimeException; + +final class AmbiguousOptionException extends RuntimeException implements Exception +{ + public function __construct(string $option) + { + parent::__construct( + sprintf( + 'Option "%s" is ambiguous', + $option + ) + ); + } +} diff --git a/vendor/sebastian/cli-parser/src/exceptions/Exception.php b/vendor/sebastian/cli-parser/src/exceptions/Exception.php new file mode 100644 index 00000000..f35ad245 --- /dev/null +++ b/vendor/sebastian/cli-parser/src/exceptions/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CliParser; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php b/vendor/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php new file mode 100644 index 00000000..0aad29ac --- /dev/null +++ b/vendor/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CliParser; + +use function sprintf; +use RuntimeException; + +final class OptionDoesNotAllowArgumentException extends RuntimeException implements Exception +{ + public function __construct(string $option) + { + parent::__construct( + sprintf( + 'Option "%s" does not allow an argument', + $option + ) + ); + } +} diff --git a/vendor/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php b/vendor/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php new file mode 100644 index 00000000..d2a930b6 --- /dev/null +++ b/vendor/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CliParser; + +use function sprintf; +use RuntimeException; + +final class RequiredOptionArgumentMissingException extends RuntimeException implements Exception +{ + public function __construct(string $option) + { + parent::__construct( + sprintf( + 'Required argument for option "%s" is missing', + $option + ) + ); + } +} diff --git a/vendor/sebastian/cli-parser/src/exceptions/UnknownOptionException.php b/vendor/sebastian/cli-parser/src/exceptions/UnknownOptionException.php new file mode 100644 index 00000000..e98d9fd0 --- /dev/null +++ b/vendor/sebastian/cli-parser/src/exceptions/UnknownOptionException.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CliParser; + +use function sprintf; +use RuntimeException; + +final class UnknownOptionException extends RuntimeException implements Exception +{ + public function __construct(string $option) + { + parent::__construct( + sprintf( + 'Unknown option "%s"', + $option + ) + ); + } +} diff --git a/vendor/sebastian/code-unit-reverse-lookup/ChangeLog.md b/vendor/sebastian/code-unit-reverse-lookup/ChangeLog.md new file mode 100644 index 00000000..43a5db90 --- /dev/null +++ b/vendor/sebastian/code-unit-reverse-lookup/ChangeLog.md @@ -0,0 +1,38 @@ +# Change Log + +All notable changes to `sebastianbergmann/code-unit-reverse-lookup` are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [2.0.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [2.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [2.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## 2.0.0 - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 5.6, PHP 7.0, PHP 7.1, and PHP 7.2 + +## 1.0.0 - 2016-02-13 + +### Added + +* Initial release + +[2.0.3]: https://github.com/sebastianbergmann/code-unit-reverse-lookup/compare/2.0.2...2.0.3 +[2.0.2]: https://github.com/sebastianbergmann/code-unit-reverse-lookup/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/sebastianbergmann/code-unit-reverse-lookup/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/code-unit-reverse-lookup/compare/1.0.0...2.0.0 diff --git a/vendor/sebastian/code-unit-reverse-lookup/LICENSE b/vendor/sebastian/code-unit-reverse-lookup/LICENSE new file mode 100644 index 00000000..dc4bf701 --- /dev/null +++ b/vendor/sebastian/code-unit-reverse-lookup/LICENSE @@ -0,0 +1,33 @@ +code-unit-reverse-lookup + +Copyright (c) 2016-2020, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/code-unit-reverse-lookup/README.md b/vendor/sebastian/code-unit-reverse-lookup/README.md new file mode 100644 index 00000000..1c0ca235 --- /dev/null +++ b/vendor/sebastian/code-unit-reverse-lookup/README.md @@ -0,0 +1,20 @@ +# sebastian/code-unit-reverse-lookup + +[![CI Status](https://github.com/sebastianbergmann/code-unit-reverse-lookup/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/code-unit-reverse-lookup/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/code-unit-reverse-lookup/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/code-unit-reverse-lookup) + +Looks up which function or method a line of code belongs to. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/code-unit-reverse-lookup +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/code-unit-reverse-lookup +``` diff --git a/vendor/sebastian/code-unit-reverse-lookup/composer.json b/vendor/sebastian/code-unit-reverse-lookup/composer.json new file mode 100644 index 00000000..cff96167 --- /dev/null +++ b/vendor/sebastian/code-unit-reverse-lookup/composer.json @@ -0,0 +1,36 @@ +{ + "name": "sebastian/code-unit-reverse-lookup", + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "prefer-stable": true, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + } +} diff --git a/vendor/sebastian/code-unit-reverse-lookup/src/Wizard.php b/vendor/sebastian/code-unit-reverse-lookup/src/Wizard.php new file mode 100644 index 00000000..35de5398 --- /dev/null +++ b/vendor/sebastian/code-unit-reverse-lookup/src/Wizard.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnitReverseLookup; + +use function array_merge; +use function assert; +use function get_declared_classes; +use function get_declared_traits; +use function get_defined_functions; +use function is_array; +use function range; +use ReflectionClass; +use ReflectionFunction; +use ReflectionFunctionAbstract; +use ReflectionMethod; + +/** + * @since Class available since Release 1.0.0 + */ +class Wizard +{ + /** + * @var array + */ + private $lookupTable = []; + + /** + * @var array + */ + private $processedClasses = []; + + /** + * @var array + */ + private $processedFunctions = []; + + /** + * @param string $filename + * @param int $lineNumber + * + * @return string + */ + public function lookup($filename, $lineNumber) + { + if (!isset($this->lookupTable[$filename][$lineNumber])) { + $this->updateLookupTable(); + } + + if (isset($this->lookupTable[$filename][$lineNumber])) { + return $this->lookupTable[$filename][$lineNumber]; + } + + return $filename . ':' . $lineNumber; + } + + private function updateLookupTable(): void + { + $this->processClassesAndTraits(); + $this->processFunctions(); + } + + private function processClassesAndTraits(): void + { + $classes = get_declared_classes(); + $traits = get_declared_traits(); + + assert(is_array($classes)); + assert(is_array($traits)); + + foreach (array_merge($classes, $traits) as $classOrTrait) { + if (isset($this->processedClasses[$classOrTrait])) { + continue; + } + + $reflector = new ReflectionClass($classOrTrait); + + foreach ($reflector->getMethods() as $method) { + $this->processFunctionOrMethod($method); + } + + $this->processedClasses[$classOrTrait] = true; + } + } + + private function processFunctions(): void + { + foreach (get_defined_functions()['user'] as $function) { + if (isset($this->processedFunctions[$function])) { + continue; + } + + $this->processFunctionOrMethod(new ReflectionFunction($function)); + + $this->processedFunctions[$function] = true; + } + } + + private function processFunctionOrMethod(ReflectionFunctionAbstract $functionOrMethod): void + { + if ($functionOrMethod->isInternal()) { + return; + } + + $name = $functionOrMethod->getName(); + + if ($functionOrMethod instanceof ReflectionMethod) { + $name = $functionOrMethod->getDeclaringClass()->getName() . '::' . $name; + } + + if (!isset($this->lookupTable[$functionOrMethod->getFileName()])) { + $this->lookupTable[$functionOrMethod->getFileName()] = []; + } + + foreach (range($functionOrMethod->getStartLine(), $functionOrMethod->getEndLine()) as $line) { + $this->lookupTable[$functionOrMethod->getFileName()][$line] = $name; + } + } +} diff --git a/vendor/sebastian/code-unit/.psalm/baseline.xml b/vendor/sebastian/code-unit/.psalm/baseline.xml new file mode 100644 index 00000000..e4488919 --- /dev/null +++ b/vendor/sebastian/code-unit/.psalm/baseline.xml @@ -0,0 +1,23 @@ + + + + + $firstPart + $firstPart + $firstPart + $firstPart + $firstPart + $firstPart + $firstPart + $firstPart + $firstPart + $secondPart + $unit + $unit + $unit + $unit + $unit + $unit + + + diff --git a/vendor/sebastian/code-unit/.psalm/config.xml b/vendor/sebastian/code-unit/.psalm/config.xml new file mode 100644 index 00000000..a39e9a4c --- /dev/null +++ b/vendor/sebastian/code-unit/.psalm/config.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/vendor/sebastian/code-unit/ChangeLog.md b/vendor/sebastian/code-unit/ChangeLog.md new file mode 100644 index 00000000..0978e651 --- /dev/null +++ b/vendor/sebastian/code-unit/ChangeLog.md @@ -0,0 +1,65 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [1.0.8] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\CodeUnit\Exception` now correctly extends `\Throwable` + +## [1.0.7] - 2020-10-02 + +### Fixed + +* `SebastianBergmann\CodeUnit\Mapper::stringToCodeUnits()` no longer attempts to create `CodeUnit` objects for code units that are not declared in userland + +## [1.0.6] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [1.0.5] - 2020-06-26 + +### Fixed + +* [#3](https://github.com/sebastianbergmann/code-unit/issues/3): Regression in 1.0.4 + +## [1.0.4] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [1.0.3] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [1.0.2] - 2020-04-30 + +### Fixed + +* `Mapper::stringToCodeUnits()` raised the wrong exception for `Class::method` when a class named `Class` exists but does not have a method named `method` + +## [1.0.1] - 2020-04-27 + +### Fixed + +* [#2](https://github.com/sebastianbergmann/code-unit/issues/2): `Mapper::stringToCodeUnits()` breaks when `ClassName` is used for class that extends built-in class + +## [1.0.0] - 2020-03-30 + +* Initial release + +[1.0.8]: https://github.com/sebastianbergmann/code-unit/compare/1.0.7...1.0.8 +[1.0.7]: https://github.com/sebastianbergmann/code-unit/compare/1.0.6...1.0.7 +[1.0.6]: https://github.com/sebastianbergmann/code-unit/compare/1.0.5...1.0.6 +[1.0.5]: https://github.com/sebastianbergmann/code-unit/compare/1.0.4...1.0.5 +[1.0.4]: https://github.com/sebastianbergmann/code-unit/compare/1.0.3...1.0.4 +[1.0.3]: https://github.com/sebastianbergmann/code-unit/compare/1.0.2...1.0.3 +[1.0.2]: https://github.com/sebastianbergmann/code-unit/compare/1.0.1...1.0.2 +[1.0.1]: https://github.com/sebastianbergmann/code-unit/compare/1.0.0...1.0.1 +[1.0.0]: https://github.com/sebastianbergmann/code-unit/compare/530c3900e5db9bcb8516da545bef0d62536cedaa...1.0.0 diff --git a/vendor/sebastian/code-unit/LICENSE b/vendor/sebastian/code-unit/LICENSE new file mode 100644 index 00000000..b99bc8ac --- /dev/null +++ b/vendor/sebastian/code-unit/LICENSE @@ -0,0 +1,33 @@ +sebastian/code-unit + +Copyright (c) 2020, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/code-unit/README.md b/vendor/sebastian/code-unit/README.md new file mode 100644 index 00000000..d20227a9 --- /dev/null +++ b/vendor/sebastian/code-unit/README.md @@ -0,0 +1,17 @@ +# sebastian/code-unit + +Collection of value objects that represent the PHP code units. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/code-unit +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/code-unit +``` diff --git a/vendor/sebastian/code-unit/composer.json b/vendor/sebastian/code-unit/composer.json new file mode 100644 index 00000000..5b86ec58 --- /dev/null +++ b/vendor/sebastian/code-unit/composer.json @@ -0,0 +1,50 @@ +{ + "name": "sebastian/code-unit", + "description": "Collection of value objects that represent the PHP code units", + "type": "library", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues" + }, + "prefer-stable": true, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture" + ], + "files": [ + "tests/_fixture/file_with_multiple_code_units.php", + "tests/_fixture/function.php" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + } +} diff --git a/vendor/sebastian/code-unit/src/ClassMethodUnit.php b/vendor/sebastian/code-unit/src/ClassMethodUnit.php new file mode 100644 index 00000000..f9ddac29 --- /dev/null +++ b/vendor/sebastian/code-unit/src/ClassMethodUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class ClassMethodUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true ClassMethodUnit $this + */ + public function isClassMethod(): bool + { + return true; + } +} diff --git a/vendor/sebastian/code-unit/src/ClassUnit.php b/vendor/sebastian/code-unit/src/ClassUnit.php new file mode 100644 index 00000000..3ba0ee66 --- /dev/null +++ b/vendor/sebastian/code-unit/src/ClassUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class ClassUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true ClassUnit $this + */ + public function isClass(): bool + { + return true; + } +} diff --git a/vendor/sebastian/code-unit/src/CodeUnit.php b/vendor/sebastian/code-unit/src/CodeUnit.php new file mode 100644 index 00000000..9e5cceb3 --- /dev/null +++ b/vendor/sebastian/code-unit/src/CodeUnit.php @@ -0,0 +1,445 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use function range; +use function sprintf; +use ReflectionClass; +use ReflectionFunction; +use ReflectionMethod; + +/** + * @psalm-immutable + */ +abstract class CodeUnit +{ + /** + * @var string + */ + private $name; + + /** + * @var string + */ + private $sourceFileName; + + /** + * @var array + * @psalm-var list + */ + private $sourceLines; + + /** + * @psalm-param class-string $className + * + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public static function forClass(string $className): ClassUnit + { + self::ensureUserDefinedClass($className); + + $reflector = self::reflectorForClass($className); + + return new ClassUnit( + $className, + $reflector->getFileName(), + range( + $reflector->getStartLine(), + $reflector->getEndLine() + ) + ); + } + + /** + * @psalm-param class-string $className + * + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public static function forClassMethod(string $className, string $methodName): ClassMethodUnit + { + self::ensureUserDefinedClass($className); + + $reflector = self::reflectorForClassMethod($className, $methodName); + + return new ClassMethodUnit( + $className . '::' . $methodName, + $reflector->getFileName(), + range( + $reflector->getStartLine(), + $reflector->getEndLine() + ) + ); + } + + /** + * @psalm-param class-string $interfaceName + * + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public static function forInterface(string $interfaceName): InterfaceUnit + { + self::ensureUserDefinedInterface($interfaceName); + + $reflector = self::reflectorForClass($interfaceName); + + return new InterfaceUnit( + $interfaceName, + $reflector->getFileName(), + range( + $reflector->getStartLine(), + $reflector->getEndLine() + ) + ); + } + + /** + * @psalm-param class-string $interfaceName + * + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public static function forInterfaceMethod(string $interfaceName, string $methodName): InterfaceMethodUnit + { + self::ensureUserDefinedInterface($interfaceName); + + $reflector = self::reflectorForClassMethod($interfaceName, $methodName); + + return new InterfaceMethodUnit( + $interfaceName . '::' . $methodName, + $reflector->getFileName(), + range( + $reflector->getStartLine(), + $reflector->getEndLine() + ) + ); + } + + /** + * @psalm-param class-string $traitName + * + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public static function forTrait(string $traitName): TraitUnit + { + self::ensureUserDefinedTrait($traitName); + + $reflector = self::reflectorForClass($traitName); + + return new TraitUnit( + $traitName, + $reflector->getFileName(), + range( + $reflector->getStartLine(), + $reflector->getEndLine() + ) + ); + } + + /** + * @psalm-param class-string $traitName + * + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public static function forTraitMethod(string $traitName, string $methodName): TraitMethodUnit + { + self::ensureUserDefinedTrait($traitName); + + $reflector = self::reflectorForClassMethod($traitName, $methodName); + + return new TraitMethodUnit( + $traitName . '::' . $methodName, + $reflector->getFileName(), + range( + $reflector->getStartLine(), + $reflector->getEndLine() + ) + ); + } + + /** + * @psalm-param callable-string $functionName + * + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public static function forFunction(string $functionName): FunctionUnit + { + $reflector = self::reflectorForFunction($functionName); + + if (!$reflector->isUserDefined()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is not a user-defined function', + $functionName + ) + ); + } + + return new FunctionUnit( + $functionName, + $reflector->getFileName(), + range( + $reflector->getStartLine(), + $reflector->getEndLine() + ) + ); + } + + /** + * @psalm-param list $sourceLines + */ + private function __construct(string $name, string $sourceFileName, array $sourceLines) + { + $this->name = $name; + $this->sourceFileName = $sourceFileName; + $this->sourceLines = $sourceLines; + } + + public function name(): string + { + return $this->name; + } + + public function sourceFileName(): string + { + return $this->sourceFileName; + } + + /** + * @psalm-return list + */ + public function sourceLines(): array + { + return $this->sourceLines; + } + + public function isClass(): bool + { + return false; + } + + public function isClassMethod(): bool + { + return false; + } + + public function isInterface(): bool + { + return false; + } + + public function isInterfaceMethod(): bool + { + return false; + } + + public function isTrait(): bool + { + return false; + } + + public function isTraitMethod(): bool + { + return false; + } + + public function isFunction(): bool + { + return false; + } + + /** + * @psalm-param class-string $className + * + * @throws InvalidCodeUnitException + */ + private static function ensureUserDefinedClass(string $className): void + { + try { + $reflector = new ReflectionClass($className); + + if ($reflector->isInterface()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is an interface and not a class', + $className + ) + ); + } + + if ($reflector->isTrait()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is a trait and not a class', + $className + ) + ); + } + + if (!$reflector->isUserDefined()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is not a user-defined class', + $className + ) + ); + } + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @psalm-param class-string $interfaceName + * + * @throws InvalidCodeUnitException + */ + private static function ensureUserDefinedInterface(string $interfaceName): void + { + try { + $reflector = new ReflectionClass($interfaceName); + + if (!$reflector->isInterface()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is not an interface', + $interfaceName + ) + ); + } + + if (!$reflector->isUserDefined()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is not a user-defined interface', + $interfaceName + ) + ); + } + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @psalm-param class-string $traitName + * + * @throws InvalidCodeUnitException + */ + private static function ensureUserDefinedTrait(string $traitName): void + { + try { + $reflector = new ReflectionClass($traitName); + + if (!$reflector->isTrait()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is not a trait', + $traitName + ) + ); + } + + // @codeCoverageIgnoreStart + if (!$reflector->isUserDefined()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is not a user-defined trait', + $traitName + ) + ); + } + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private static function reflectorForClass(string $className): ReflectionClass + { + try { + return new ReflectionClass($className); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private static function reflectorForClassMethod(string $className, string $methodName): ReflectionMethod + { + try { + return new ReflectionMethod($className, $methodName); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @psalm-param callable-string $functionName + * + * @throws ReflectionException + */ + private static function reflectorForFunction(string $functionName): ReflectionFunction + { + try { + return new ReflectionFunction($functionName); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } +} diff --git a/vendor/sebastian/code-unit/src/CodeUnitCollection.php b/vendor/sebastian/code-unit/src/CodeUnitCollection.php new file mode 100644 index 00000000..f53db8a1 --- /dev/null +++ b/vendor/sebastian/code-unit/src/CodeUnitCollection.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use function array_merge; +use function count; +use Countable; +use IteratorAggregate; + +final class CodeUnitCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private $codeUnits = []; + + /** + * @psalm-param list $items + */ + public static function fromArray(array $items): self + { + $collection = new self; + + foreach ($items as $item) { + $collection->add($item); + } + + return $collection; + } + + public static function fromList(CodeUnit ...$items): self + { + return self::fromArray($items); + } + + private function __construct() + { + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->codeUnits; + } + + public function getIterator(): CodeUnitCollectionIterator + { + return new CodeUnitCollectionIterator($this); + } + + public function count(): int + { + return count($this->codeUnits); + } + + public function isEmpty(): bool + { + return empty($this->codeUnits); + } + + public function mergeWith(self $other): self + { + return self::fromArray( + array_merge( + $this->asArray(), + $other->asArray() + ) + ); + } + + private function add(CodeUnit $item): void + { + $this->codeUnits[] = $item; + } +} diff --git a/vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.php b/vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.php new file mode 100644 index 00000000..bdc86d88 --- /dev/null +++ b/vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use Iterator; + +final class CodeUnitCollectionIterator implements Iterator +{ + /** + * @psalm-var list + */ + private $codeUnits; + + /** + * @var int + */ + private $position = 0; + + public function __construct(CodeUnitCollection $collection) + { + $this->codeUnits = $collection->asArray(); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return isset($this->codeUnits[$this->position]); + } + + public function key(): int + { + return $this->position; + } + + public function current(): CodeUnit + { + return $this->codeUnits[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/vendor/sebastian/code-unit/src/FunctionUnit.php b/vendor/sebastian/code-unit/src/FunctionUnit.php new file mode 100644 index 00000000..df76cf19 --- /dev/null +++ b/vendor/sebastian/code-unit/src/FunctionUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class FunctionUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true FunctionUnit $this + */ + public function isFunction(): bool + { + return true; + } +} diff --git a/vendor/sebastian/code-unit/src/InterfaceMethodUnit.php b/vendor/sebastian/code-unit/src/InterfaceMethodUnit.php new file mode 100644 index 00000000..fcd44f41 --- /dev/null +++ b/vendor/sebastian/code-unit/src/InterfaceMethodUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class InterfaceMethodUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true InterfaceMethod $this + */ + public function isInterfaceMethod(): bool + { + return true; + } +} diff --git a/vendor/sebastian/code-unit/src/InterfaceUnit.php b/vendor/sebastian/code-unit/src/InterfaceUnit.php new file mode 100644 index 00000000..5cf585bf --- /dev/null +++ b/vendor/sebastian/code-unit/src/InterfaceUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class InterfaceUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true InterfaceUnit $this + */ + public function isInterface(): bool + { + return true; + } +} diff --git a/vendor/sebastian/code-unit/src/Mapper.php b/vendor/sebastian/code-unit/src/Mapper.php new file mode 100644 index 00000000..a72b3b0d --- /dev/null +++ b/vendor/sebastian/code-unit/src/Mapper.php @@ -0,0 +1,414 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use function array_keys; +use function array_merge; +use function array_unique; +use function array_values; +use function class_exists; +use function explode; +use function function_exists; +use function interface_exists; +use function ksort; +use function method_exists; +use function sort; +use function sprintf; +use function str_replace; +use function strpos; +use function trait_exists; +use ReflectionClass; +use ReflectionFunction; +use ReflectionMethod; + +final class Mapper +{ + /** + * @psalm-return array> + */ + public function codeUnitsToSourceLines(CodeUnitCollection $codeUnits): array + { + $result = []; + + foreach ($codeUnits as $codeUnit) { + $sourceFileName = $codeUnit->sourceFileName(); + + if (!isset($result[$sourceFileName])) { + $result[$sourceFileName] = []; + } + + $result[$sourceFileName] = array_merge($result[$sourceFileName], $codeUnit->sourceLines()); + } + + foreach (array_keys($result) as $sourceFileName) { + $result[$sourceFileName] = array_values(array_unique($result[$sourceFileName])); + + sort($result[$sourceFileName]); + } + + ksort($result); + + return $result; + } + + /** + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public function stringToCodeUnits(string $unit): CodeUnitCollection + { + if (strpos($unit, '::') !== false) { + [$firstPart, $secondPart] = explode('::', $unit); + + if (empty($firstPart) && $this->isUserDefinedFunction($secondPart)) { + return CodeUnitCollection::fromList(CodeUnit::forFunction($secondPart)); + } + + if ($this->isUserDefinedClass($firstPart)) { + if ($secondPart === '') { + return $this->publicMethodsOfClass($firstPart); + } + + if ($secondPart === '') { + return $this->protectedAndPrivateMethodsOfClass($firstPart); + } + + if ($secondPart === '') { + return $this->protectedMethodsOfClass($firstPart); + } + + if ($secondPart === '') { + return $this->publicAndPrivateMethodsOfClass($firstPart); + } + + if ($secondPart === '') { + return $this->privateMethodsOfClass($firstPart); + } + + if ($secondPart === '') { + return $this->publicAndProtectedMethodsOfClass($firstPart); + } + + if ($this->isUserDefinedMethod($firstPart, $secondPart)) { + return CodeUnitCollection::fromList(CodeUnit::forClassMethod($firstPart, $secondPart)); + } + } + + if ($this->isUserDefinedInterface($firstPart)) { + return CodeUnitCollection::fromList(CodeUnit::forInterfaceMethod($firstPart, $secondPart)); + } + + if ($this->isUserDefinedTrait($firstPart)) { + return CodeUnitCollection::fromList(CodeUnit::forTraitMethod($firstPart, $secondPart)); + } + } else { + if ($this->isUserDefinedClass($unit)) { + $units = [CodeUnit::forClass($unit)]; + + foreach ($this->reflectorForClass($unit)->getTraits() as $trait) { + if (!$trait->isUserDefined()) { + // @codeCoverageIgnoreStart + continue; + // @codeCoverageIgnoreEnd + } + + $units[] = CodeUnit::forTrait($trait->getName()); + } + + return CodeUnitCollection::fromArray($units); + } + + if ($this->isUserDefinedInterface($unit)) { + return CodeUnitCollection::fromList(CodeUnit::forInterface($unit)); + } + + if ($this->isUserDefinedTrait($unit)) { + return CodeUnitCollection::fromList(CodeUnit::forTrait($unit)); + } + + if ($this->isUserDefinedFunction($unit)) { + return CodeUnitCollection::fromList(CodeUnit::forFunction($unit)); + } + + $unit = str_replace('', '', $unit); + + if ($this->isUserDefinedClass($unit)) { + return $this->classAndParentClassesAndTraits($unit); + } + } + + throw new InvalidCodeUnitException( + sprintf( + '"%s" is not a valid code unit', + $unit + ) + ); + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private function publicMethodsOfClass(string $className): CodeUnitCollection + { + return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC); + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private function publicAndProtectedMethodsOfClass(string $className): CodeUnitCollection + { + return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED); + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private function publicAndPrivateMethodsOfClass(string $className): CodeUnitCollection + { + return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PRIVATE); + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private function protectedMethodsOfClass(string $className): CodeUnitCollection + { + return $this->methodsOfClass($className, ReflectionMethod::IS_PROTECTED); + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private function protectedAndPrivateMethodsOfClass(string $className): CodeUnitCollection + { + return $this->methodsOfClass($className, ReflectionMethod::IS_PROTECTED | ReflectionMethod::IS_PRIVATE); + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private function privateMethodsOfClass(string $className): CodeUnitCollection + { + return $this->methodsOfClass($className, ReflectionMethod::IS_PRIVATE); + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private function methodsOfClass(string $className, int $filter): CodeUnitCollection + { + $units = []; + + foreach ($this->reflectorForClass($className)->getMethods($filter) as $method) { + if (!$method->isUserDefined()) { + continue; + } + + $units[] = CodeUnit::forClassMethod($className, $method->getName()); + } + + return CodeUnitCollection::fromArray($units); + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private function classAndParentClassesAndTraits(string $className): CodeUnitCollection + { + $units = [CodeUnit::forClass($className)]; + + $reflector = $this->reflectorForClass($className); + + foreach ($this->reflectorForClass($className)->getTraits() as $trait) { + if (!$trait->isUserDefined()) { + // @codeCoverageIgnoreStart + continue; + // @codeCoverageIgnoreEnd + } + + $units[] = CodeUnit::forTrait($trait->getName()); + } + + while ($reflector = $reflector->getParentClass()) { + if (!$reflector->isUserDefined()) { + break; + } + + $units[] = CodeUnit::forClass($reflector->getName()); + + foreach ($reflector->getTraits() as $trait) { + if (!$trait->isUserDefined()) { + // @codeCoverageIgnoreStart + continue; + // @codeCoverageIgnoreEnd + } + + $units[] = CodeUnit::forTrait($trait->getName()); + } + } + + return CodeUnitCollection::fromArray($units); + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private function reflectorForClass(string $className): ReflectionClass + { + try { + return new ReflectionClass($className); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @throws ReflectionException + */ + private function isUserDefinedFunction(string $functionName): bool + { + if (!function_exists($functionName)) { + return false; + } + + try { + return (new ReflectionFunction($functionName))->isUserDefined(); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @throws ReflectionException + */ + private function isUserDefinedClass(string $className): bool + { + if (!class_exists($className)) { + return false; + } + + try { + return (new ReflectionClass($className))->isUserDefined(); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @throws ReflectionException + */ + private function isUserDefinedInterface(string $interfaceName): bool + { + if (!interface_exists($interfaceName)) { + return false; + } + + try { + return (new ReflectionClass($interfaceName))->isUserDefined(); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @throws ReflectionException + */ + private function isUserDefinedTrait(string $traitName): bool + { + if (!trait_exists($traitName)) { + return false; + } + + try { + return (new ReflectionClass($traitName))->isUserDefined(); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @throws ReflectionException + */ + private function isUserDefinedMethod(string $className, string $methodName): bool + { + if (!class_exists($className)) { + // @codeCoverageIgnoreStart + return false; + // @codeCoverageIgnoreEnd + } + + if (!method_exists($className, $methodName)) { + // @codeCoverageIgnoreStart + return false; + // @codeCoverageIgnoreEnd + } + + try { + return (new ReflectionMethod($className, $methodName))->isUserDefined(); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } +} diff --git a/vendor/sebastian/code-unit/src/TraitMethodUnit.php b/vendor/sebastian/code-unit/src/TraitMethodUnit.php new file mode 100644 index 00000000..a58f7249 --- /dev/null +++ b/vendor/sebastian/code-unit/src/TraitMethodUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class TraitMethodUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true TraitMethodUnit $this + */ + public function isTraitMethod(): bool + { + return true; + } +} diff --git a/vendor/sebastian/code-unit/src/TraitUnit.php b/vendor/sebastian/code-unit/src/TraitUnit.php new file mode 100644 index 00000000..abddfc11 --- /dev/null +++ b/vendor/sebastian/code-unit/src/TraitUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class TraitUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true TraitUnit $this + */ + public function isTrait(): bool + { + return true; + } +} diff --git a/vendor/sebastian/code-unit/src/exceptions/Exception.php b/vendor/sebastian/code-unit/src/exceptions/Exception.php new file mode 100644 index 00000000..74d0eeef --- /dev/null +++ b/vendor/sebastian/code-unit/src/exceptions/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php b/vendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php new file mode 100644 index 00000000..60a3da82 --- /dev/null +++ b/vendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use RuntimeException; + +final class InvalidCodeUnitException extends RuntimeException implements Exception +{ +} diff --git a/vendor/sebastian/code-unit/src/exceptions/NoTraitException.php b/vendor/sebastian/code-unit/src/exceptions/NoTraitException.php new file mode 100644 index 00000000..e9b9b9c7 --- /dev/null +++ b/vendor/sebastian/code-unit/src/exceptions/NoTraitException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use RuntimeException; + +final class NoTraitException extends RuntimeException implements Exception +{ +} diff --git a/vendor/sebastian/code-unit/src/exceptions/ReflectionException.php b/vendor/sebastian/code-unit/src/exceptions/ReflectionException.php new file mode 100644 index 00000000..23201278 --- /dev/null +++ b/vendor/sebastian/code-unit/src/exceptions/ReflectionException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use RuntimeException; + +final class ReflectionException extends RuntimeException implements Exception +{ +} diff --git a/vendor/sebastian/comparator/ChangeLog.md b/vendor/sebastian/comparator/ChangeLog.md new file mode 100644 index 00000000..17557536 --- /dev/null +++ b/vendor/sebastian/comparator/ChangeLog.md @@ -0,0 +1,143 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [4.0.8] - 2022-09-14 + +### Fixed + +* [#102](https://github.com/sebastianbergmann/comparator/pull/102): Fix `float` comparison precision + +## [4.0.7] - 2022-09-14 + +### Fixed + +* [#99](https://github.com/sebastianbergmann/comparator/pull/99): Fix weak comparison between `'0'` and `false` + +## [4.0.6] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\Comparator\Exception` now correctly extends `\Throwable` + +## [4.0.5] - 2020-09-30 + +### Fixed + +* [#89](https://github.com/sebastianbergmann/comparator/pull/89): Handle PHP 8 `ValueError` + +## [4.0.4] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [4.0.3] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [4.0.2] - 2020-06-15 + +### Fixed + +* [#85](https://github.com/sebastianbergmann/comparator/issues/85): Version 4.0.1 breaks backward compatibility + +## [4.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [4.0.0] - 2020-02-07 + +### Removed + +* Removed support for PHP 7.1 and PHP 7.2 + +## [3.0.5] - 2022-09-14 + +### Fixed + +* [#102](https://github.com/sebastianbergmann/comparator/pull/102): Fix `float` comparison precision + +## [3.0.4] - 2022-09-14 + +### Fixed + +* [#99](https://github.com/sebastianbergmann/comparator/pull/99): Fix weak comparison between `'0'` and `false` + +## [3.0.3] - 2020-11-30 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.1` to `>=7.1` + +## [3.0.2] - 2018-07-12 + +### Changed + +* By default, `MockObjectComparator` is now tried before all other (default) comparators + +## [3.0.1] - 2018-06-14 + +### Fixed + +* [#53](https://github.com/sebastianbergmann/comparator/pull/53): `DOMNodeComparator` ignores `$ignoreCase` parameter +* [#58](https://github.com/sebastianbergmann/comparator/pull/58): `ScalarComparator` does not handle extremely ugly string comparison edge cases + +## [3.0.0] - 2018-04-18 + +### Fixed + +* [#48](https://github.com/sebastianbergmann/comparator/issues/48): `DateTimeComparator` does not support fractional second deltas + +### Removed + +* Removed support for PHP 7.0 + +## [2.1.3] - 2018-02-01 + +### Changed + +* This component is now compatible with version 3 of `sebastian/diff` + +## [2.1.2] - 2018-01-12 + +### Fixed + +* Fix comparison of `DateTimeImmutable` objects + +## [2.1.1] - 2017-12-22 + +### Fixed + +* [phpunit/#2923](https://github.com/sebastianbergmann/phpunit/issues/2923): Unexpected failed date matching + +## [2.1.0] - 2017-11-03 + +### Added + +* Added `SebastianBergmann\Comparator\Factory::reset()` to unregister all non-default comparators +* Added support for `phpunit/phpunit-mock-objects` version `^5.0` + +[4.0.8]: https://github.com/sebastianbergmann/comparator/compare/4.0.7...4.0.8 +[4.0.7]: https://github.com/sebastianbergmann/comparator/compare/4.0.6...4.0.7 +[4.0.6]: https://github.com/sebastianbergmann/comparator/compare/4.0.5...4.0.6 +[4.0.5]: https://github.com/sebastianbergmann/comparator/compare/4.0.4...4.0.5 +[4.0.4]: https://github.com/sebastianbergmann/comparator/compare/4.0.3...4.0.4 +[4.0.3]: https://github.com/sebastianbergmann/comparator/compare/4.0.2...4.0.3 +[4.0.2]: https://github.com/sebastianbergmann/comparator/compare/4.0.1...4.0.2 +[4.0.1]: https://github.com/sebastianbergmann/comparator/compare/4.0.0...4.0.1 +[4.0.0]: https://github.com/sebastianbergmann/comparator/compare/3.0.5...4.0.0 +[3.0.5]: https://github.com/sebastianbergmann/comparator/compare/3.0.4...3.0.5 +[3.0.4]: https://github.com/sebastianbergmann/comparator/compare/3.0.3...3.0.4 +[3.0.3]: https://github.com/sebastianbergmann/comparator/compare/3.0.2...3.0.3 +[3.0.2]: https://github.com/sebastianbergmann/comparator/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/comparator/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/comparator/compare/2.1.3...3.0.0 +[2.1.3]: https://github.com/sebastianbergmann/comparator/compare/2.1.2...2.1.3 +[2.1.2]: https://github.com/sebastianbergmann/comparator/compare/2.1.1...2.1.2 +[2.1.1]: https://github.com/sebastianbergmann/comparator/compare/2.1.0...2.1.1 +[2.1.0]: https://github.com/sebastianbergmann/comparator/compare/2.0.2...2.1.0 diff --git a/vendor/sebastian/comparator/LICENSE b/vendor/sebastian/comparator/LICENSE new file mode 100644 index 00000000..6ad70cba --- /dev/null +++ b/vendor/sebastian/comparator/LICENSE @@ -0,0 +1,33 @@ +Comparator + +Copyright (c) 2002-2020, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/comparator/README.md b/vendor/sebastian/comparator/README.md new file mode 100644 index 00000000..f6002db6 --- /dev/null +++ b/vendor/sebastian/comparator/README.md @@ -0,0 +1,41 @@ +# sebastian/comparator + +[![CI Status](https://github.com/sebastianbergmann/comparator/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/comparator/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/comparator/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/comparator) + +This component provides the functionality to compare PHP values for equality. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/comparator +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/comparator +``` + +## Usage + +```php +getComparatorFor($date1, $date2); + +try { + $comparator->assertEquals($date1, $date2); + print "Dates match"; +} catch (ComparisonFailure $failure) { + print "Dates don't match"; +} +``` diff --git a/vendor/sebastian/comparator/composer.json b/vendor/sebastian/comparator/composer.json new file mode 100644 index 00000000..b758e03c --- /dev/null +++ b/vendor/sebastian/comparator/composer.json @@ -0,0 +1,57 @@ +{ + "name": "sebastian/comparator", + "description": "Provides the functionality to compare PHP values for equality", + "keywords": ["comparator","compare","equality"], + "homepage": "https://github.com/sebastianbergmann/comparator", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "prefer-stable": true, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + } +} + diff --git a/vendor/sebastian/comparator/src/ArrayComparator.php b/vendor/sebastian/comparator/src/ArrayComparator.php new file mode 100644 index 00000000..5d9fbce6 --- /dev/null +++ b/vendor/sebastian/comparator/src/ArrayComparator.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function array_key_exists; +use function is_array; +use function sort; +use function sprintf; +use function str_replace; +use function trim; + +/** + * Compares arrays for equality. + * + * Arrays are equal if they contain the same key-value pairs. + * The order of the keys does not matter. + * The types of key-value pairs do not matter. + */ +class ArrayComparator extends Comparator +{ + /** + * Returns whether the comparator can compare two values. + * + * @param mixed $expected The first value to compare + * @param mixed $actual The second value to compare + * + * @return bool + */ + public function accepts($expected, $actual) + { + return is_array($expected) && is_array($actual); + } + + /** + * Asserts that two arrays are equal. + * + * @param mixed $expected First value to compare + * @param mixed $actual Second value to compare + * @param float $delta Allowed numerical distance between two values to consider them equal + * @param bool $canonicalize Arrays are sorted before comparison when set to true + * @param bool $ignoreCase Case is ignored when set to true + * @param array $processed List of already processed elements (used to prevent infinite recursion) + * + * @throws ComparisonFailure + */ + public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = [])/*: void*/ + { + if ($canonicalize) { + sort($expected); + sort($actual); + } + + $remaining = $actual; + $actualAsString = "Array (\n"; + $expectedAsString = "Array (\n"; + $equal = true; + + foreach ($expected as $key => $value) { + unset($remaining[$key]); + + if (!array_key_exists($key, $actual)) { + $expectedAsString .= sprintf( + " %s => %s\n", + $this->exporter->export($key), + $this->exporter->shortenedExport($value) + ); + + $equal = false; + + continue; + } + + try { + $comparator = $this->factory->getComparatorFor($value, $actual[$key]); + $comparator->assertEquals($value, $actual[$key], $delta, $canonicalize, $ignoreCase, $processed); + + $expectedAsString .= sprintf( + " %s => %s\n", + $this->exporter->export($key), + $this->exporter->shortenedExport($value) + ); + + $actualAsString .= sprintf( + " %s => %s\n", + $this->exporter->export($key), + $this->exporter->shortenedExport($actual[$key]) + ); + } catch (ComparisonFailure $e) { + $expectedAsString .= sprintf( + " %s => %s\n", + $this->exporter->export($key), + $e->getExpectedAsString() ? $this->indent($e->getExpectedAsString()) : $this->exporter->shortenedExport($e->getExpected()) + ); + + $actualAsString .= sprintf( + " %s => %s\n", + $this->exporter->export($key), + $e->getActualAsString() ? $this->indent($e->getActualAsString()) : $this->exporter->shortenedExport($e->getActual()) + ); + + $equal = false; + } + } + + foreach ($remaining as $key => $value) { + $actualAsString .= sprintf( + " %s => %s\n", + $this->exporter->export($key), + $this->exporter->shortenedExport($value) + ); + + $equal = false; + } + + $expectedAsString .= ')'; + $actualAsString .= ')'; + + if (!$equal) { + throw new ComparisonFailure( + $expected, + $actual, + $expectedAsString, + $actualAsString, + false, + 'Failed asserting that two arrays are equal.' + ); + } + } + + protected function indent($lines) + { + return trim(str_replace("\n", "\n ", $lines)); + } +} diff --git a/vendor/sebastian/comparator/src/Comparator.php b/vendor/sebastian/comparator/src/Comparator.php new file mode 100644 index 00000000..e1906c16 --- /dev/null +++ b/vendor/sebastian/comparator/src/Comparator.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use SebastianBergmann\Exporter\Exporter; + +/** + * Abstract base class for comparators which compare values for equality. + */ +abstract class Comparator +{ + /** + * @var Factory + */ + protected $factory; + + /** + * @var Exporter + */ + protected $exporter; + + public function __construct() + { + $this->exporter = new Exporter; + } + + public function setFactory(Factory $factory)/*: void*/ + { + $this->factory = $factory; + } + + /** + * Returns whether the comparator can compare two values. + * + * @param mixed $expected The first value to compare + * @param mixed $actual The second value to compare + * + * @return bool + */ + abstract public function accepts($expected, $actual); + + /** + * Asserts that two values are equal. + * + * @param mixed $expected First value to compare + * @param mixed $actual Second value to compare + * @param float $delta Allowed numerical distance between two values to consider them equal + * @param bool $canonicalize Arrays are sorted before comparison when set to true + * @param bool $ignoreCase Case is ignored when set to true + * + * @throws ComparisonFailure + */ + abstract public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false); +} diff --git a/vendor/sebastian/comparator/src/ComparisonFailure.php b/vendor/sebastian/comparator/src/ComparisonFailure.php new file mode 100644 index 00000000..857314da --- /dev/null +++ b/vendor/sebastian/comparator/src/ComparisonFailure.php @@ -0,0 +1,129 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use RuntimeException; +use SebastianBergmann\Diff\Differ; +use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder; + +/** + * Thrown when an assertion for string equality failed. + */ +class ComparisonFailure extends RuntimeException +{ + /** + * Expected value of the retrieval which does not match $actual. + * + * @var mixed + */ + protected $expected; + + /** + * Actually retrieved value which does not match $expected. + * + * @var mixed + */ + protected $actual; + + /** + * The string representation of the expected value. + * + * @var string + */ + protected $expectedAsString; + + /** + * The string representation of the actual value. + * + * @var string + */ + protected $actualAsString; + + /** + * @var bool + */ + protected $identical; + + /** + * Optional message which is placed in front of the first line + * returned by toString(). + * + * @var string + */ + protected $message; + + /** + * Initialises with the expected value and the actual value. + * + * @param mixed $expected expected value retrieved + * @param mixed $actual actual value retrieved + * @param string $expectedAsString + * @param string $actualAsString + * @param bool $identical + * @param string $message a string which is prefixed on all returned lines + * in the difference output + */ + public function __construct($expected, $actual, $expectedAsString, $actualAsString, $identical = false, $message = '') + { + $this->expected = $expected; + $this->actual = $actual; + $this->expectedAsString = $expectedAsString; + $this->actualAsString = $actualAsString; + $this->message = $message; + } + + public function getActual() + { + return $this->actual; + } + + public function getExpected() + { + return $this->expected; + } + + /** + * @return string + */ + public function getActualAsString() + { + return $this->actualAsString; + } + + /** + * @return string + */ + public function getExpectedAsString() + { + return $this->expectedAsString; + } + + /** + * @return string + */ + public function getDiff() + { + if (!$this->actualAsString && !$this->expectedAsString) { + return ''; + } + + $differ = new Differ(new UnifiedDiffOutputBuilder("\n--- Expected\n+++ Actual\n")); + + return $differ->diff($this->expectedAsString, $this->actualAsString); + } + + /** + * @return string + */ + public function toString() + { + return $this->message . $this->getDiff(); + } +} diff --git a/vendor/sebastian/comparator/src/DOMNodeComparator.php b/vendor/sebastian/comparator/src/DOMNodeComparator.php new file mode 100644 index 00000000..5bf854ea --- /dev/null +++ b/vendor/sebastian/comparator/src/DOMNodeComparator.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function sprintf; +use function strtolower; +use DOMDocument; +use DOMNode; +use ValueError; + +/** + * Compares DOMNode instances for equality. + */ +class DOMNodeComparator extends ObjectComparator +{ + /** + * Returns whether the comparator can compare two values. + * + * @param mixed $expected The first value to compare + * @param mixed $actual The second value to compare + * + * @return bool + */ + public function accepts($expected, $actual) + { + return $expected instanceof DOMNode && $actual instanceof DOMNode; + } + + /** + * Asserts that two values are equal. + * + * @param mixed $expected First value to compare + * @param mixed $actual Second value to compare + * @param float $delta Allowed numerical distance between two values to consider them equal + * @param bool $canonicalize Arrays are sorted before comparison when set to true + * @param bool $ignoreCase Case is ignored when set to true + * @param array $processed List of already processed elements (used to prevent infinite recursion) + * + * @throws ComparisonFailure + */ + public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = [])/*: void*/ + { + $expectedAsString = $this->nodeToText($expected, true, $ignoreCase); + $actualAsString = $this->nodeToText($actual, true, $ignoreCase); + + if ($expectedAsString !== $actualAsString) { + $type = $expected instanceof DOMDocument ? 'documents' : 'nodes'; + + throw new ComparisonFailure( + $expected, + $actual, + $expectedAsString, + $actualAsString, + false, + sprintf("Failed asserting that two DOM %s are equal.\n", $type) + ); + } + } + + /** + * Returns the normalized, whitespace-cleaned, and indented textual + * representation of a DOMNode. + */ + private function nodeToText(DOMNode $node, bool $canonicalize, bool $ignoreCase): string + { + if ($canonicalize) { + $document = new DOMDocument; + + try { + @$document->loadXML($node->C14N()); + } catch (ValueError $e) { + } + + $node = $document; + } + + $document = $node instanceof DOMDocument ? $node : $node->ownerDocument; + + $document->formatOutput = true; + $document->normalizeDocument(); + + $text = $node instanceof DOMDocument ? $node->saveXML() : $document->saveXML($node); + + return $ignoreCase ? strtolower($text) : $text; + } +} diff --git a/vendor/sebastian/comparator/src/DateTimeComparator.php b/vendor/sebastian/comparator/src/DateTimeComparator.php new file mode 100644 index 00000000..0a303b62 --- /dev/null +++ b/vendor/sebastian/comparator/src/DateTimeComparator.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function abs; +use function floor; +use function sprintf; +use DateInterval; +use DateTime; +use DateTimeInterface; +use DateTimeZone; +use Exception; + +/** + * Compares DateTimeInterface instances for equality. + */ +class DateTimeComparator extends ObjectComparator +{ + /** + * Returns whether the comparator can compare two values. + * + * @param mixed $expected The first value to compare + * @param mixed $actual The second value to compare + * + * @return bool + */ + public function accepts($expected, $actual) + { + return ($expected instanceof DateTime || $expected instanceof DateTimeInterface) && + ($actual instanceof DateTime || $actual instanceof DateTimeInterface); + } + + /** + * Asserts that two values are equal. + * + * @param mixed $expected First value to compare + * @param mixed $actual Second value to compare + * @param float $delta Allowed numerical distance between two values to consider them equal + * @param bool $canonicalize Arrays are sorted before comparison when set to true + * @param bool $ignoreCase Case is ignored when set to true + * @param array $processed List of already processed elements (used to prevent infinite recursion) + * + * @throws Exception + * @throws ComparisonFailure + */ + public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = [])/*: void*/ + { + /** @var DateTimeInterface $expected */ + /** @var DateTimeInterface $actual */ + $absDelta = abs($delta); + $delta = new DateInterval(sprintf('PT%dS', $absDelta)); + $delta->f = $absDelta - floor($absDelta); + + $actualClone = (clone $actual) + ->setTimezone(new DateTimeZone('UTC')); + + $expectedLower = (clone $expected) + ->setTimezone(new DateTimeZone('UTC')) + ->sub($delta); + + $expectedUpper = (clone $expected) + ->setTimezone(new DateTimeZone('UTC')) + ->add($delta); + + if ($actualClone < $expectedLower || $actualClone > $expectedUpper) { + throw new ComparisonFailure( + $expected, + $actual, + $this->dateTimeToString($expected), + $this->dateTimeToString($actual), + false, + 'Failed asserting that two DateTime objects are equal.' + ); + } + } + + /** + * Returns an ISO 8601 formatted string representation of a datetime or + * 'Invalid DateTimeInterface object' if the provided DateTimeInterface was not properly + * initialized. + */ + private function dateTimeToString(DateTimeInterface $datetime): string + { + $string = $datetime->format('Y-m-d\TH:i:s.uO'); + + return $string ?: 'Invalid DateTimeInterface object'; + } +} diff --git a/vendor/sebastian/comparator/src/DoubleComparator.php b/vendor/sebastian/comparator/src/DoubleComparator.php new file mode 100644 index 00000000..42352219 --- /dev/null +++ b/vendor/sebastian/comparator/src/DoubleComparator.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function is_float; +use function is_numeric; + +/** + * Compares doubles for equality. + * + * @deprecated since v3.0.5 and v4.0.8 + */ +class DoubleComparator extends NumericComparator +{ + /** + * Smallest value available in PHP. + * + * @var float + */ + public const EPSILON = 0.0000000001; + + /** + * Returns whether the comparator can compare two values. + * + * @param mixed $expected The first value to compare + * @param mixed $actual The second value to compare + * + * @return bool + */ + public function accepts($expected, $actual) + { + return (is_float($expected) || is_float($actual)) && is_numeric($expected) && is_numeric($actual); + } + + /** + * Asserts that two values are equal. + * + * @param mixed $expected First value to compare + * @param mixed $actual Second value to compare + * @param float $delta Allowed numerical distance between two values to consider them equal + * @param bool $canonicalize Arrays are sorted before comparison when set to true + * @param bool $ignoreCase Case is ignored when set to true + * + * @throws ComparisonFailure + */ + public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/ + { + if ($delta == 0) { + $delta = self::EPSILON; + } + + parent::assertEquals($expected, $actual, $delta, $canonicalize, $ignoreCase); + } +} diff --git a/vendor/sebastian/comparator/src/ExceptionComparator.php b/vendor/sebastian/comparator/src/ExceptionComparator.php new file mode 100644 index 00000000..1fc0174e --- /dev/null +++ b/vendor/sebastian/comparator/src/ExceptionComparator.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use Exception; + +/** + * Compares Exception instances for equality. + */ +class ExceptionComparator extends ObjectComparator +{ + /** + * Returns whether the comparator can compare two values. + * + * @param mixed $expected The first value to compare + * @param mixed $actual The second value to compare + * + * @return bool + */ + public function accepts($expected, $actual) + { + return $expected instanceof Exception && $actual instanceof Exception; + } + + /** + * Converts an object to an array containing all of its private, protected + * and public properties. + * + * @param object $object + * + * @return array + */ + protected function toArray($object) + { + $array = parent::toArray($object); + + unset( + $array['file'], + $array['line'], + $array['trace'], + $array['string'], + $array['xdebug_message'] + ); + + return $array; + } +} diff --git a/vendor/sebastian/comparator/src/Factory.php b/vendor/sebastian/comparator/src/Factory.php new file mode 100644 index 00000000..6a8b5b44 --- /dev/null +++ b/vendor/sebastian/comparator/src/Factory.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function array_unshift; + +/** + * Factory for comparators which compare values for equality. + */ +class Factory +{ + /** + * @var Factory + */ + private static $instance; + + /** + * @var Comparator[] + */ + private $customComparators = []; + + /** + * @var Comparator[] + */ + private $defaultComparators = []; + + /** + * @return Factory + */ + public static function getInstance() + { + if (self::$instance === null) { + self::$instance = new self; // @codeCoverageIgnore + } + + return self::$instance; + } + + /** + * Constructs a new factory. + */ + public function __construct() + { + $this->registerDefaultComparators(); + } + + /** + * Returns the correct comparator for comparing two values. + * + * @param mixed $expected The first value to compare + * @param mixed $actual The second value to compare + * + * @return Comparator + */ + public function getComparatorFor($expected, $actual) + { + foreach ($this->customComparators as $comparator) { + if ($comparator->accepts($expected, $actual)) { + return $comparator; + } + } + + foreach ($this->defaultComparators as $comparator) { + if ($comparator->accepts($expected, $actual)) { + return $comparator; + } + } + + throw new RuntimeException('No suitable Comparator implementation found'); + } + + /** + * Registers a new comparator. + * + * This comparator will be returned by getComparatorFor() if its accept() method + * returns TRUE for the compared values. It has higher priority than the + * existing comparators, meaning that its accept() method will be invoked + * before those of the other comparators. + * + * @param Comparator $comparator The comparator to be registered + */ + public function register(Comparator $comparator)/*: void*/ + { + array_unshift($this->customComparators, $comparator); + + $comparator->setFactory($this); + } + + /** + * Unregisters a comparator. + * + * This comparator will no longer be considered by getComparatorFor(). + * + * @param Comparator $comparator The comparator to be unregistered + */ + public function unregister(Comparator $comparator)/*: void*/ + { + foreach ($this->customComparators as $key => $_comparator) { + if ($comparator === $_comparator) { + unset($this->customComparators[$key]); + } + } + } + + /** + * Unregisters all non-default comparators. + */ + public function reset()/*: void*/ + { + $this->customComparators = []; + } + + private function registerDefaultComparators(): void + { + $this->registerDefaultComparator(new MockObjectComparator); + $this->registerDefaultComparator(new DateTimeComparator); + $this->registerDefaultComparator(new DOMNodeComparator); + $this->registerDefaultComparator(new SplObjectStorageComparator); + $this->registerDefaultComparator(new ExceptionComparator); + $this->registerDefaultComparator(new ObjectComparator); + $this->registerDefaultComparator(new ResourceComparator); + $this->registerDefaultComparator(new ArrayComparator); + $this->registerDefaultComparator(new NumericComparator); + $this->registerDefaultComparator(new ScalarComparator); + $this->registerDefaultComparator(new TypeComparator); + } + + private function registerDefaultComparator(Comparator $comparator): void + { + $this->defaultComparators[] = $comparator; + + $comparator->setFactory($this); + } +} diff --git a/vendor/sebastian/comparator/src/MockObjectComparator.php b/vendor/sebastian/comparator/src/MockObjectComparator.php new file mode 100644 index 00000000..cb670316 --- /dev/null +++ b/vendor/sebastian/comparator/src/MockObjectComparator.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use PHPUnit\Framework\MockObject\MockObject; + +/** + * Compares PHPUnit\Framework\MockObject\MockObject instances for equality. + */ +class MockObjectComparator extends ObjectComparator +{ + /** + * Returns whether the comparator can compare two values. + * + * @param mixed $expected The first value to compare + * @param mixed $actual The second value to compare + * + * @return bool + */ + public function accepts($expected, $actual) + { + return $expected instanceof MockObject && $actual instanceof MockObject; + } + + /** + * Converts an object to an array containing all of its private, protected + * and public properties. + * + * @param object $object + * + * @return array + */ + protected function toArray($object) + { + $array = parent::toArray($object); + + unset($array['__phpunit_invocationMocker']); + + return $array; + } +} diff --git a/vendor/sebastian/comparator/src/NumericComparator.php b/vendor/sebastian/comparator/src/NumericComparator.php new file mode 100644 index 00000000..841881c9 --- /dev/null +++ b/vendor/sebastian/comparator/src/NumericComparator.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function abs; +use function is_float; +use function is_infinite; +use function is_nan; +use function is_numeric; +use function is_string; +use function sprintf; + +/** + * Compares numerical values for equality. + */ +class NumericComparator extends ScalarComparator +{ + /** + * Returns whether the comparator can compare two values. + * + * @param mixed $expected The first value to compare + * @param mixed $actual The second value to compare + * + * @return bool + */ + public function accepts($expected, $actual) + { + // all numerical values, but not if both of them are strings + return is_numeric($expected) && is_numeric($actual) && + !(is_string($expected) && is_string($actual)); + } + + /** + * Asserts that two values are equal. + * + * @param mixed $expected First value to compare + * @param mixed $actual Second value to compare + * @param float $delta Allowed numerical distance between two values to consider them equal + * @param bool $canonicalize Arrays are sorted before comparison when set to true + * @param bool $ignoreCase Case is ignored when set to true + * + * @throws ComparisonFailure + */ + public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/ + { + if ($this->isInfinite($actual) && $this->isInfinite($expected)) { + return; + } + + if (($this->isInfinite($actual) xor $this->isInfinite($expected)) || + ($this->isNan($actual) || $this->isNan($expected)) || + abs($actual - $expected) > $delta) { + throw new ComparisonFailure( + $expected, + $actual, + '', + '', + false, + sprintf( + 'Failed asserting that %s matches expected %s.', + $this->exporter->export($actual), + $this->exporter->export($expected) + ) + ); + } + } + + private function isInfinite($value): bool + { + return is_float($value) && is_infinite($value); + } + + private function isNan($value): bool + { + return is_float($value) && is_nan($value); + } +} diff --git a/vendor/sebastian/comparator/src/ObjectComparator.php b/vendor/sebastian/comparator/src/ObjectComparator.php new file mode 100644 index 00000000..9380ba15 --- /dev/null +++ b/vendor/sebastian/comparator/src/ObjectComparator.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function get_class; +use function in_array; +use function is_object; +use function sprintf; +use function substr_replace; + +/** + * Compares objects for equality. + */ +class ObjectComparator extends ArrayComparator +{ + /** + * Returns whether the comparator can compare two values. + * + * @param mixed $expected The first value to compare + * @param mixed $actual The second value to compare + * + * @return bool + */ + public function accepts($expected, $actual) + { + return is_object($expected) && is_object($actual); + } + + /** + * Asserts that two values are equal. + * + * @param mixed $expected First value to compare + * @param mixed $actual Second value to compare + * @param float $delta Allowed numerical distance between two values to consider them equal + * @param bool $canonicalize Arrays are sorted before comparison when set to true + * @param bool $ignoreCase Case is ignored when set to true + * @param array $processed List of already processed elements (used to prevent infinite recursion) + * + * @throws ComparisonFailure + */ + public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = [])/*: void*/ + { + if (get_class($actual) !== get_class($expected)) { + throw new ComparisonFailure( + $expected, + $actual, + $this->exporter->export($expected), + $this->exporter->export($actual), + false, + sprintf( + '%s is not instance of expected class "%s".', + $this->exporter->export($actual), + get_class($expected) + ) + ); + } + + // don't compare twice to allow for cyclic dependencies + if (in_array([$actual, $expected], $processed, true) || + in_array([$expected, $actual], $processed, true)) { + return; + } + + $processed[] = [$actual, $expected]; + + // don't compare objects if they are identical + // this helps to avoid the error "maximum function nesting level reached" + // CAUTION: this conditional clause is not tested + if ($actual !== $expected) { + try { + parent::assertEquals( + $this->toArray($expected), + $this->toArray($actual), + $delta, + $canonicalize, + $ignoreCase, + $processed + ); + } catch (ComparisonFailure $e) { + throw new ComparisonFailure( + $expected, + $actual, + // replace "Array" with "MyClass object" + substr_replace($e->getExpectedAsString(), get_class($expected) . ' Object', 0, 5), + substr_replace($e->getActualAsString(), get_class($actual) . ' Object', 0, 5), + false, + 'Failed asserting that two objects are equal.' + ); + } + } + } + + /** + * Converts an object to an array containing all of its private, protected + * and public properties. + * + * @param object $object + * + * @return array + */ + protected function toArray($object) + { + return $this->exporter->toArray($object); + } +} diff --git a/vendor/sebastian/comparator/src/ResourceComparator.php b/vendor/sebastian/comparator/src/ResourceComparator.php new file mode 100644 index 00000000..7822598b --- /dev/null +++ b/vendor/sebastian/comparator/src/ResourceComparator.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function is_resource; + +/** + * Compares resources for equality. + */ +class ResourceComparator extends Comparator +{ + /** + * Returns whether the comparator can compare two values. + * + * @param mixed $expected The first value to compare + * @param mixed $actual The second value to compare + * + * @return bool + */ + public function accepts($expected, $actual) + { + return is_resource($expected) && is_resource($actual); + } + + /** + * Asserts that two values are equal. + * + * @param mixed $expected First value to compare + * @param mixed $actual Second value to compare + * @param float $delta Allowed numerical distance between two values to consider them equal + * @param bool $canonicalize Arrays are sorted before comparison when set to true + * @param bool $ignoreCase Case is ignored when set to true + * + * @throws ComparisonFailure + */ + public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/ + { + if ($actual != $expected) { + throw new ComparisonFailure( + $expected, + $actual, + $this->exporter->export($expected), + $this->exporter->export($actual) + ); + } + } +} diff --git a/vendor/sebastian/comparator/src/ScalarComparator.php b/vendor/sebastian/comparator/src/ScalarComparator.php new file mode 100644 index 00000000..7f131229 --- /dev/null +++ b/vendor/sebastian/comparator/src/ScalarComparator.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function is_bool; +use function is_object; +use function is_scalar; +use function is_string; +use function method_exists; +use function sprintf; +use function strtolower; + +/** + * Compares scalar or NULL values for equality. + */ +class ScalarComparator extends Comparator +{ + /** + * Returns whether the comparator can compare two values. + * + * @param mixed $expected The first value to compare + * @param mixed $actual The second value to compare + * + * @return bool + * + * @since Method available since Release 3.6.0 + */ + public function accepts($expected, $actual) + { + return ((is_scalar($expected) xor null === $expected) && + (is_scalar($actual) xor null === $actual)) + // allow comparison between strings and objects featuring __toString() + || (is_string($expected) && is_object($actual) && method_exists($actual, '__toString')) + || (is_object($expected) && method_exists($expected, '__toString') && is_string($actual)); + } + + /** + * Asserts that two values are equal. + * + * @param mixed $expected First value to compare + * @param mixed $actual Second value to compare + * @param float $delta Allowed numerical distance between two values to consider them equal + * @param bool $canonicalize Arrays are sorted before comparison when set to true + * @param bool $ignoreCase Case is ignored when set to true + * + * @throws ComparisonFailure + */ + public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/ + { + $expectedToCompare = $expected; + $actualToCompare = $actual; + + // always compare as strings to avoid strange behaviour + // otherwise 0 == 'Foobar' + if ((is_string($expected) && !is_bool($actual)) || (is_string($actual) && !is_bool($expected))) { + $expectedToCompare = (string) $expectedToCompare; + $actualToCompare = (string) $actualToCompare; + + if ($ignoreCase) { + $expectedToCompare = strtolower($expectedToCompare); + $actualToCompare = strtolower($actualToCompare); + } + } + + if ($expectedToCompare !== $actualToCompare && is_string($expected) && is_string($actual)) { + throw new ComparisonFailure( + $expected, + $actual, + $this->exporter->export($expected), + $this->exporter->export($actual), + false, + 'Failed asserting that two strings are equal.' + ); + } + + if ($expectedToCompare != $actualToCompare) { + throw new ComparisonFailure( + $expected, + $actual, + // no diff is required + '', + '', + false, + sprintf( + 'Failed asserting that %s matches expected %s.', + $this->exporter->export($actual), + $this->exporter->export($expected) + ) + ); + } + } +} diff --git a/vendor/sebastian/comparator/src/SplObjectStorageComparator.php b/vendor/sebastian/comparator/src/SplObjectStorageComparator.php new file mode 100644 index 00000000..d9b6f541 --- /dev/null +++ b/vendor/sebastian/comparator/src/SplObjectStorageComparator.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use SplObjectStorage; + +/** + * Compares \SplObjectStorage instances for equality. + */ +class SplObjectStorageComparator extends Comparator +{ + /** + * Returns whether the comparator can compare two values. + * + * @param mixed $expected The first value to compare + * @param mixed $actual The second value to compare + * + * @return bool + */ + public function accepts($expected, $actual) + { + return $expected instanceof SplObjectStorage && $actual instanceof SplObjectStorage; + } + + /** + * Asserts that two values are equal. + * + * @param mixed $expected First value to compare + * @param mixed $actual Second value to compare + * @param float $delta Allowed numerical distance between two values to consider them equal + * @param bool $canonicalize Arrays are sorted before comparison when set to true + * @param bool $ignoreCase Case is ignored when set to true + * + * @throws ComparisonFailure + */ + public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/ + { + foreach ($actual as $object) { + if (!$expected->contains($object)) { + throw new ComparisonFailure( + $expected, + $actual, + $this->exporter->export($expected), + $this->exporter->export($actual), + false, + 'Failed asserting that two objects are equal.' + ); + } + } + + foreach ($expected as $object) { + if (!$actual->contains($object)) { + throw new ComparisonFailure( + $expected, + $actual, + $this->exporter->export($expected), + $this->exporter->export($actual), + false, + 'Failed asserting that two objects are equal.' + ); + } + } + } +} diff --git a/vendor/sebastian/comparator/src/TypeComparator.php b/vendor/sebastian/comparator/src/TypeComparator.php new file mode 100644 index 00000000..b0d38d72 --- /dev/null +++ b/vendor/sebastian/comparator/src/TypeComparator.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function gettype; +use function sprintf; + +/** + * Compares values for type equality. + */ +class TypeComparator extends Comparator +{ + /** + * Returns whether the comparator can compare two values. + * + * @param mixed $expected The first value to compare + * @param mixed $actual The second value to compare + * + * @return bool + */ + public function accepts($expected, $actual) + { + return true; + } + + /** + * Asserts that two values are equal. + * + * @param mixed $expected First value to compare + * @param mixed $actual Second value to compare + * @param float $delta Allowed numerical distance between two values to consider them equal + * @param bool $canonicalize Arrays are sorted before comparison when set to true + * @param bool $ignoreCase Case is ignored when set to true + * + * @throws ComparisonFailure + */ + public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/ + { + if (gettype($expected) != gettype($actual)) { + throw new ComparisonFailure( + $expected, + $actual, + // we don't need a diff + '', + '', + false, + sprintf( + '%s does not match expected type "%s".', + $this->exporter->shortenedExport($actual), + gettype($expected) + ) + ); + } + } +} diff --git a/vendor/sebastian/comparator/src/exceptions/Exception.php b/vendor/sebastian/comparator/src/exceptions/Exception.php new file mode 100644 index 00000000..8975aaf1 --- /dev/null +++ b/vendor/sebastian/comparator/src/exceptions/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/sebastian/comparator/src/exceptions/RuntimeException.php b/vendor/sebastian/comparator/src/exceptions/RuntimeException.php new file mode 100644 index 00000000..ca726084 --- /dev/null +++ b/vendor/sebastian/comparator/src/exceptions/RuntimeException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/vendor/sebastian/complexity/.psalm/baseline.xml b/vendor/sebastian/complexity/.psalm/baseline.xml new file mode 100644 index 00000000..77e688e0 --- /dev/null +++ b/vendor/sebastian/complexity/.psalm/baseline.xml @@ -0,0 +1,2 @@ + + diff --git a/vendor/sebastian/complexity/.psalm/config.xml b/vendor/sebastian/complexity/.psalm/config.xml new file mode 100644 index 00000000..8172fe15 --- /dev/null +++ b/vendor/sebastian/complexity/.psalm/config.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/vendor/sebastian/complexity/ChangeLog.md b/vendor/sebastian/complexity/ChangeLog.md new file mode 100644 index 00000000..cb93ff62 --- /dev/null +++ b/vendor/sebastian/complexity/ChangeLog.md @@ -0,0 +1,30 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [2.0.2] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\Complexity\Exception` now correctly extends `\Throwable` + +## [2.0.1] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [2.0.0] - 2020-07-25 + +### Removed + +* The `ParentConnectingVisitor` has been removed (it should have been marked as `@internal`) + +## [1.0.0] - 2020-07-22 + +* Initial release + +[2.0.2]: https://github.com/sebastianbergmann/complexity/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/sebastianbergmann/complexity/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/complexity/compare/1.0.0...2.0.0 +[1.0.0]: https://github.com/sebastianbergmann/complexity/compare/70ee0ad32d9e2be3f85beffa3e2eb474193f2487...1.0.0 diff --git a/vendor/sebastian/complexity/LICENSE b/vendor/sebastian/complexity/LICENSE new file mode 100644 index 00000000..5f818df6 --- /dev/null +++ b/vendor/sebastian/complexity/LICENSE @@ -0,0 +1,33 @@ +sebastian/complexity + +Copyright (c) 2020, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/complexity/README.md b/vendor/sebastian/complexity/README.md new file mode 100644 index 00000000..5f53b0b5 --- /dev/null +++ b/vendor/sebastian/complexity/README.md @@ -0,0 +1,22 @@ +# sebastian/complexity + +Library for calculating the complexity of PHP code units. + +[![Latest Stable Version](https://img.shields.io/packagist/v/sebastian/complexity.svg?style=flat-square)](https://packagist.org/packages/sebastian/complexity) +[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.3-8892BF.svg?style=flat-square)](https://php.net/) +[![CI Status](https://github.com/sebastianbergmann/complexity/workflows/CI/badge.svg?branch=master&event=push)](https://phpunit.de/build-status.html) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/complexity/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/complexity) + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/complexity +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/complexity +``` diff --git a/vendor/sebastian/complexity/composer.json b/vendor/sebastian/complexity/composer.json new file mode 100644 index 00000000..7aa38314 --- /dev/null +++ b/vendor/sebastian/complexity/composer.json @@ -0,0 +1,41 @@ +{ + "name": "sebastian/complexity", + "description": "Library for calculating the complexity of PHP code units", + "type": "library", + "homepage": "https://github.com/sebastianbergmann/complexity", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues" + }, + "require": { + "php": ">=7.3", + "nikic/php-parser": "^4.7" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + } +} diff --git a/vendor/sebastian/complexity/src/Calculator.php b/vendor/sebastian/complexity/src/Calculator.php new file mode 100644 index 00000000..9abdcd16 --- /dev/null +++ b/vendor/sebastian/complexity/src/Calculator.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Complexity; + +use PhpParser\Error; +use PhpParser\Lexer; +use PhpParser\Node; +use PhpParser\NodeTraverser; +use PhpParser\NodeVisitor\NameResolver; +use PhpParser\NodeVisitor\ParentConnectingVisitor; +use PhpParser\Parser; +use PhpParser\ParserFactory; + +final class Calculator +{ + /** + * @throws RuntimeException + */ + public function calculateForSourceFile(string $sourceFile): ComplexityCollection + { + return $this->calculateForSourceString(file_get_contents($sourceFile)); + } + + /** + * @throws RuntimeException + */ + public function calculateForSourceString(string $source): ComplexityCollection + { + try { + $nodes = $this->parser()->parse($source); + + assert($nodes !== null); + + return $this->calculateForAbstractSyntaxTree($nodes); + + // @codeCoverageIgnoreStart + } catch (Error $error) { + throw new RuntimeException( + $error->getMessage(), + (int) $error->getCode(), + $error + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @param Node[] $nodes + * + * @throws RuntimeException + */ + public function calculateForAbstractSyntaxTree(array $nodes): ComplexityCollection + { + $traverser = new NodeTraverser; + $complexityCalculatingVisitor = new ComplexityCalculatingVisitor(true); + + $traverser->addVisitor(new NameResolver); + $traverser->addVisitor(new ParentConnectingVisitor); + $traverser->addVisitor($complexityCalculatingVisitor); + + try { + /* @noinspection UnusedFunctionResultInspection */ + $traverser->traverse($nodes); + // @codeCoverageIgnoreStart + } catch (Error $error) { + throw new RuntimeException( + $error->getMessage(), + (int) $error->getCode(), + $error + ); + } + // @codeCoverageIgnoreEnd + + return $complexityCalculatingVisitor->result(); + } + + private function parser(): Parser + { + return (new ParserFactory)->create(ParserFactory::PREFER_PHP7, new Lexer); + } +} diff --git a/vendor/sebastian/complexity/src/Complexity/Complexity.php b/vendor/sebastian/complexity/src/Complexity/Complexity.php new file mode 100644 index 00000000..dc6708dd --- /dev/null +++ b/vendor/sebastian/complexity/src/Complexity/Complexity.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Complexity; + +/** + * @psalm-immutable + */ +final class Complexity +{ + /** + * @var string + */ + private $name; + + /** + * @var int + */ + private $cyclomaticComplexity; + + public function __construct(string $name, int $cyclomaticComplexity) + { + $this->name = $name; + $this->cyclomaticComplexity = $cyclomaticComplexity; + } + + public function name(): string + { + return $this->name; + } + + public function cyclomaticComplexity(): int + { + return $this->cyclomaticComplexity; + } +} diff --git a/vendor/sebastian/complexity/src/Complexity/ComplexityCollection.php b/vendor/sebastian/complexity/src/Complexity/ComplexityCollection.php new file mode 100644 index 00000000..ccbddbf7 --- /dev/null +++ b/vendor/sebastian/complexity/src/Complexity/ComplexityCollection.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Complexity; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @psalm-immutable + */ +final class ComplexityCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private $items = []; + + public static function fromList(Complexity ...$items): self + { + return new self($items); + } + + /** + * @psalm-param list $items + */ + private function __construct(array $items) + { + $this->items = $items; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->items; + } + + public function getIterator(): ComplexityCollectionIterator + { + return new ComplexityCollectionIterator($this); + } + + public function count(): int + { + return count($this->items); + } + + public function isEmpty(): bool + { + return empty($this->items); + } + + public function cyclomaticComplexity(): int + { + $cyclomaticComplexity = 0; + + foreach ($this as $item) { + $cyclomaticComplexity += $item->cyclomaticComplexity(); + } + + return $cyclomaticComplexity; + } +} diff --git a/vendor/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php b/vendor/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php new file mode 100644 index 00000000..ec39e199 --- /dev/null +++ b/vendor/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Complexity; + +use Iterator; + +final class ComplexityCollectionIterator implements Iterator +{ + /** + * @psalm-var list + */ + private $items; + + /** + * @var int + */ + private $position = 0; + + public function __construct(ComplexityCollection $items) + { + $this->items = $items->asArray(); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return isset($this->items[$this->position]); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Complexity + { + return $this->items[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/vendor/sebastian/complexity/src/Exception/Exception.php b/vendor/sebastian/complexity/src/Exception/Exception.php new file mode 100644 index 00000000..897ecdcf --- /dev/null +++ b/vendor/sebastian/complexity/src/Exception/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Complexity; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/sebastian/complexity/src/Exception/RuntimeException.php b/vendor/sebastian/complexity/src/Exception/RuntimeException.php new file mode 100644 index 00000000..6c68a6f0 --- /dev/null +++ b/vendor/sebastian/complexity/src/Exception/RuntimeException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Complexity; + +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/vendor/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php b/vendor/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php new file mode 100644 index 00000000..b69f2b09 --- /dev/null +++ b/vendor/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Complexity; + +use function assert; +use function is_array; +use PhpParser\Node; +use PhpParser\Node\Name; +use PhpParser\Node\Stmt; +use PhpParser\Node\Stmt\Class_; +use PhpParser\Node\Stmt\ClassMethod; +use PhpParser\Node\Stmt\Function_; +use PhpParser\Node\Stmt\Trait_; +use PhpParser\NodeTraverser; +use PhpParser\NodeVisitorAbstract; + +final class ComplexityCalculatingVisitor extends NodeVisitorAbstract +{ + /** + * @psalm-var list + */ + private $result = []; + + /** + * @var bool + */ + private $shortCircuitTraversal; + + public function __construct(bool $shortCircuitTraversal) + { + $this->shortCircuitTraversal = $shortCircuitTraversal; + } + + public function enterNode(Node $node): ?int + { + if (!$node instanceof ClassMethod && !$node instanceof Function_) { + return null; + } + + if ($node instanceof ClassMethod) { + $name = $this->classMethodName($node); + } else { + $name = $this->functionName($node); + } + + $statements = $node->getStmts(); + + assert(is_array($statements)); + + $this->result[] = new Complexity( + $name, + $this->cyclomaticComplexity($statements) + ); + + if ($this->shortCircuitTraversal) { + return NodeTraverser::DONT_TRAVERSE_CHILDREN; + } + + return null; + } + + public function result(): ComplexityCollection + { + return ComplexityCollection::fromList(...$this->result); + } + + /** + * @param Stmt[] $statements + */ + private function cyclomaticComplexity(array $statements): int + { + $traverser = new NodeTraverser; + + $cyclomaticComplexityCalculatingVisitor = new CyclomaticComplexityCalculatingVisitor; + + $traverser->addVisitor($cyclomaticComplexityCalculatingVisitor); + + /* @noinspection UnusedFunctionResultInspection */ + $traverser->traverse($statements); + + return $cyclomaticComplexityCalculatingVisitor->cyclomaticComplexity(); + } + + private function classMethodName(ClassMethod $node): string + { + $parent = $node->getAttribute('parent'); + + assert($parent instanceof Class_ || $parent instanceof Trait_); + assert(isset($parent->namespacedName)); + assert($parent->namespacedName instanceof Name); + + return $parent->namespacedName->toString() . '::' . $node->name->toString(); + } + + private function functionName(Function_ $node): string + { + assert(isset($node->namespacedName)); + assert($node->namespacedName instanceof Name); + + return $node->namespacedName->toString(); + } +} diff --git a/vendor/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php b/vendor/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php new file mode 100644 index 00000000..d4430876 --- /dev/null +++ b/vendor/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Complexity; + +use function get_class; +use PhpParser\Node; +use PhpParser\Node\Expr\BinaryOp\BooleanAnd; +use PhpParser\Node\Expr\BinaryOp\BooleanOr; +use PhpParser\Node\Expr\BinaryOp\LogicalAnd; +use PhpParser\Node\Expr\BinaryOp\LogicalOr; +use PhpParser\Node\Expr\Ternary; +use PhpParser\Node\Stmt\Case_; +use PhpParser\Node\Stmt\Catch_; +use PhpParser\Node\Stmt\ElseIf_; +use PhpParser\Node\Stmt\For_; +use PhpParser\Node\Stmt\Foreach_; +use PhpParser\Node\Stmt\If_; +use PhpParser\Node\Stmt\While_; +use PhpParser\NodeVisitorAbstract; + +final class CyclomaticComplexityCalculatingVisitor extends NodeVisitorAbstract +{ + /** + * @var int + */ + private $cyclomaticComplexity = 1; + + public function enterNode(Node $node): void + { + /* @noinspection GetClassMissUseInspection */ + switch (get_class($node)) { + case BooleanAnd::class: + case BooleanOr::class: + case Case_::class: + case Catch_::class: + case ElseIf_::class: + case For_::class: + case Foreach_::class: + case If_::class: + case LogicalAnd::class: + case LogicalOr::class: + case Ternary::class: + case While_::class: + $this->cyclomaticComplexity++; + } + } + + public function cyclomaticComplexity(): int + { + return $this->cyclomaticComplexity; + } +} diff --git a/vendor/sebastian/diff/ChangeLog.md b/vendor/sebastian/diff/ChangeLog.md new file mode 100644 index 00000000..9bdcc5b6 --- /dev/null +++ b/vendor/sebastian/diff/ChangeLog.md @@ -0,0 +1,88 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [4.0.4] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\Diff\Exception` now correctly extends `\Throwable` + +## [4.0.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [4.0.2] - 2020-06-30 + +### Added + +* This component is now supported on PHP 8 + +## [4.0.1] - 2020-05-08 + +### Fixed + +* [#99](https://github.com/sebastianbergmann/diff/pull/99): Regression in unified diff output of identical strings + +## [4.0.0] - 2020-02-07 + +### Removed + +* Removed support for PHP 7.1 and PHP 7.2 + +## [3.0.2] - 2019-02-04 + +### Changed + +* `Chunk::setLines()` now ensures that the `$lines` array only contains `Line` objects + +## [3.0.1] - 2018-06-10 + +### Fixed + +* Removed `"minimum-stability": "dev",` from `composer.json` + +## [3.0.0] - 2018-02-01 + +* The `StrictUnifiedDiffOutputBuilder` implementation of the `DiffOutputBuilderInterface` was added + +### Changed + +* The default `DiffOutputBuilderInterface` implementation now generates context lines (unchanged lines) + +### Removed + +* Removed support for PHP 7.0 + +### Fixed + +* [#70](https://github.com/sebastianbergmann/diff/issues/70): Diffing of arrays no longer works + +## [2.0.1] - 2017-08-03 + +### Fixed + +* [#66](https://github.com/sebastianbergmann/diff/pull/66): Restored backwards compatibility for PHPUnit 6.1.4, 6.2.0, 6.2.1, 6.2.2, and 6.2.3 + +## [2.0.0] - 2017-07-11 [YANKED] + +### Added + +* [#64](https://github.com/sebastianbergmann/diff/pull/64): Show line numbers for chunks of a diff + +### Removed + +* This component is no longer supported on PHP 5.6 + +[4.0.4]: https://github.com/sebastianbergmann/diff/compare/4.0.3...4.0.4 +[4.0.3]: https://github.com/sebastianbergmann/diff/compare/4.0.2...4.0.3 +[4.0.2]: https://github.com/sebastianbergmann/diff/compare/4.0.1...4.0.2 +[4.0.1]: https://github.com/sebastianbergmann/diff/compare/4.0.0...4.0.1 +[4.0.0]: https://github.com/sebastianbergmann/diff/compare/3.0.2...4.0.0 +[3.0.2]: https://github.com/sebastianbergmann/diff/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/diff/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/diff/compare/2.0...3.0.0 +[2.0.1]: https://github.com/sebastianbergmann/diff/compare/c341c98ce083db77f896a0aa64f5ee7652915970...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/diff/compare/1.4...c341c98ce083db77f896a0aa64f5ee7652915970 diff --git a/vendor/sebastian/diff/LICENSE b/vendor/sebastian/diff/LICENSE new file mode 100644 index 00000000..f22f31cf --- /dev/null +++ b/vendor/sebastian/diff/LICENSE @@ -0,0 +1,33 @@ +sebastian/diff + +Copyright (c) 2002-2020, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/diff/README.md b/vendor/sebastian/diff/README.md new file mode 100644 index 00000000..734b852d --- /dev/null +++ b/vendor/sebastian/diff/README.md @@ -0,0 +1,202 @@ +# sebastian/diff + +[![CI Status](https://github.com/sebastianbergmann/diff/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/diff/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/diff/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/diff) + +Diff implementation for PHP, factored out of PHPUnit into a stand-alone component. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/diff +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/diff +``` + +### Usage + +#### Generating diff + +The `Differ` class can be used to generate a textual representation of the difference between two strings: + +```php +diff('foo', 'bar'); +``` + +The code above yields the output below: +```diff +--- Original ++++ New +@@ @@ +-foo ++bar +``` + +There are three output builders available in this package: + +#### UnifiedDiffOutputBuilder + +This is default builder, which generates the output close to udiff and is used by PHPUnit. + +```php +diff('foo', 'bar'); +``` + +#### StrictUnifiedDiffOutputBuilder + +Generates (strict) Unified diff's (unidiffs) with hunks, +similar to `diff -u` and compatible with `patch` and `git apply`. + +```php + true, // ranges of length one are rendered with the trailing `,1` + 'commonLineThreshold' => 6, // number of same lines before ending a new hunk and creating a new one (if needed) + 'contextLines' => 3, // like `diff: -u, -U NUM, --unified[=NUM]`, for patch/git apply compatibility best to keep at least @ 3 + 'fromFile' => null, + 'fromFileDate' => null, + 'toFile' => null, + 'toFileDate' => null, +]); + +$differ = new Differ($builder); +print $differ->diff('foo', 'bar'); +``` + +#### DiffOnlyOutputBuilder + +Output only the lines that differ. + +```php +diff('foo', 'bar'); +``` + +#### DiffOutputBuilderInterface + +You can pass any output builder to the `Differ` class as longs as it implements the `DiffOutputBuilderInterface`. + +#### Parsing diff + +The `Parser` class can be used to parse a unified diff into an object graph: + +```php +use SebastianBergmann\Diff\Parser; +use SebastianBergmann\Git; + +$git = new Git('/usr/local/src/money'); + +$diff = $git->getDiff( + '948a1a07768d8edd10dcefa8315c1cbeffb31833', + 'c07a373d2399f3e686234c4f7f088d635eb9641b' +); + +$parser = new Parser; + +print_r($parser->parse($diff)); +``` + +The code above yields the output below: + + Array + ( + [0] => SebastianBergmann\Diff\Diff Object + ( + [from:SebastianBergmann\Diff\Diff:private] => a/tests/MoneyTest.php + [to:SebastianBergmann\Diff\Diff:private] => b/tests/MoneyTest.php + [chunks:SebastianBergmann\Diff\Diff:private] => Array + ( + [0] => SebastianBergmann\Diff\Chunk Object + ( + [start:SebastianBergmann\Diff\Chunk:private] => 87 + [startRange:SebastianBergmann\Diff\Chunk:private] => 7 + [end:SebastianBergmann\Diff\Chunk:private] => 87 + [endRange:SebastianBergmann\Diff\Chunk:private] => 7 + [lines:SebastianBergmann\Diff\Chunk:private] => Array + ( + [0] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 3 + [content:SebastianBergmann\Diff\Line:private] => * @covers SebastianBergmann\Money\Money::add + ) + + [1] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 3 + [content:SebastianBergmann\Diff\Line:private] => * @covers SebastianBergmann\Money\Money::newMoney + ) + + [2] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 3 + [content:SebastianBergmann\Diff\Line:private] => */ + ) + + [3] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 2 + [content:SebastianBergmann\Diff\Line:private] => public function testAnotherMoneyWithSameCurrencyObjectCanBeAdded() + ) + + [4] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 1 + [content:SebastianBergmann\Diff\Line:private] => public function testAnotherMoneyObjectWithSameCurrencyCanBeAdded() + ) + + [5] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 3 + [content:SebastianBergmann\Diff\Line:private] => { + ) + + [6] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 3 + [content:SebastianBergmann\Diff\Line:private] => $a = new Money(1, new Currency('EUR')); + ) + + [7] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 3 + [content:SebastianBergmann\Diff\Line:private] => $b = new Money(2, new Currency('EUR')); + ) + ) + ) + ) + ) + ) diff --git a/vendor/sebastian/diff/composer.json b/vendor/sebastian/diff/composer.json new file mode 100644 index 00000000..cf92202b --- /dev/null +++ b/vendor/sebastian/diff/composer.json @@ -0,0 +1,47 @@ +{ + "name": "sebastian/diff", + "description": "Diff implementation", + "keywords": ["diff", "udiff", "unidiff", "unified diff"], + "homepage": "https://github.com/sebastianbergmann/diff", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "prefer-stable": true, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + } +} diff --git a/vendor/sebastian/diff/src/Chunk.php b/vendor/sebastian/diff/src/Chunk.php new file mode 100644 index 00000000..16ae34f4 --- /dev/null +++ b/vendor/sebastian/diff/src/Chunk.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +final class Chunk +{ + /** + * @var int + */ + private $start; + + /** + * @var int + */ + private $startRange; + + /** + * @var int + */ + private $end; + + /** + * @var int + */ + private $endRange; + + /** + * @var Line[] + */ + private $lines; + + public function __construct(int $start = 0, int $startRange = 1, int $end = 0, int $endRange = 1, array $lines = []) + { + $this->start = $start; + $this->startRange = $startRange; + $this->end = $end; + $this->endRange = $endRange; + $this->lines = $lines; + } + + public function getStart(): int + { + return $this->start; + } + + public function getStartRange(): int + { + return $this->startRange; + } + + public function getEnd(): int + { + return $this->end; + } + + public function getEndRange(): int + { + return $this->endRange; + } + + /** + * @return Line[] + */ + public function getLines(): array + { + return $this->lines; + } + + /** + * @param Line[] $lines + */ + public function setLines(array $lines): void + { + foreach ($lines as $line) { + if (!$line instanceof Line) { + throw new InvalidArgumentException; + } + } + + $this->lines = $lines; + } +} diff --git a/vendor/sebastian/diff/src/Diff.php b/vendor/sebastian/diff/src/Diff.php new file mode 100644 index 00000000..17b2084f --- /dev/null +++ b/vendor/sebastian/diff/src/Diff.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +final class Diff +{ + /** + * @var string + */ + private $from; + + /** + * @var string + */ + private $to; + + /** + * @var Chunk[] + */ + private $chunks; + + /** + * @param Chunk[] $chunks + */ + public function __construct(string $from, string $to, array $chunks = []) + { + $this->from = $from; + $this->to = $to; + $this->chunks = $chunks; + } + + public function getFrom(): string + { + return $this->from; + } + + public function getTo(): string + { + return $this->to; + } + + /** + * @return Chunk[] + */ + public function getChunks(): array + { + return $this->chunks; + } + + /** + * @param Chunk[] $chunks + */ + public function setChunks(array $chunks): void + { + $this->chunks = $chunks; + } +} diff --git a/vendor/sebastian/diff/src/Differ.php b/vendor/sebastian/diff/src/Differ.php new file mode 100644 index 00000000..5a4d9d10 --- /dev/null +++ b/vendor/sebastian/diff/src/Differ.php @@ -0,0 +1,327 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +use const PHP_INT_SIZE; +use const PREG_SPLIT_DELIM_CAPTURE; +use const PREG_SPLIT_NO_EMPTY; +use function array_shift; +use function array_unshift; +use function array_values; +use function count; +use function current; +use function end; +use function get_class; +use function gettype; +use function is_array; +use function is_object; +use function is_string; +use function key; +use function min; +use function preg_split; +use function prev; +use function reset; +use function sprintf; +use function substr; +use SebastianBergmann\Diff\Output\DiffOutputBuilderInterface; +use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder; + +final class Differ +{ + public const OLD = 0; + + public const ADDED = 1; + + public const REMOVED = 2; + + public const DIFF_LINE_END_WARNING = 3; + + public const NO_LINE_END_EOF_WARNING = 4; + + /** + * @var DiffOutputBuilderInterface + */ + private $outputBuilder; + + /** + * @param DiffOutputBuilderInterface $outputBuilder + * + * @throws InvalidArgumentException + */ + public function __construct($outputBuilder = null) + { + if ($outputBuilder instanceof DiffOutputBuilderInterface) { + $this->outputBuilder = $outputBuilder; + } elseif (null === $outputBuilder) { + $this->outputBuilder = new UnifiedDiffOutputBuilder; + } elseif (is_string($outputBuilder)) { + // PHPUnit 6.1.4, 6.2.0, 6.2.1, 6.2.2, and 6.2.3 support + // @see https://github.com/sebastianbergmann/phpunit/issues/2734#issuecomment-314514056 + // @deprecated + $this->outputBuilder = new UnifiedDiffOutputBuilder($outputBuilder); + } else { + throw new InvalidArgumentException( + sprintf( + 'Expected builder to be an instance of DiffOutputBuilderInterface, or a string, got %s.', + is_object($outputBuilder) ? 'instance of "' . get_class($outputBuilder) . '"' : gettype($outputBuilder) . ' "' . $outputBuilder . '"' + ) + ); + } + } + + /** + * Returns the diff between two arrays or strings as string. + * + * @param array|string $from + * @param array|string $to + */ + public function diff($from, $to, LongestCommonSubsequenceCalculator $lcs = null): string + { + $diff = $this->diffToArray( + $this->normalizeDiffInput($from), + $this->normalizeDiffInput($to), + $lcs + ); + + return $this->outputBuilder->getDiff($diff); + } + + /** + * Returns the diff between two arrays or strings as array. + * + * Each array element contains two elements: + * - [0] => mixed $token + * - [1] => 2|1|0 + * + * - 2: REMOVED: $token was removed from $from + * - 1: ADDED: $token was added to $from + * - 0: OLD: $token is not changed in $to + * + * @param array|string $from + * @param array|string $to + * @param LongestCommonSubsequenceCalculator $lcs + */ + public function diffToArray($from, $to, LongestCommonSubsequenceCalculator $lcs = null): array + { + if (is_string($from)) { + $from = $this->splitStringByLines($from); + } elseif (!is_array($from)) { + throw new InvalidArgumentException('"from" must be an array or string.'); + } + + if (is_string($to)) { + $to = $this->splitStringByLines($to); + } elseif (!is_array($to)) { + throw new InvalidArgumentException('"to" must be an array or string.'); + } + + [$from, $to, $start, $end] = self::getArrayDiffParted($from, $to); + + if ($lcs === null) { + $lcs = $this->selectLcsImplementation($from, $to); + } + + $common = $lcs->calculate(array_values($from), array_values($to)); + $diff = []; + + foreach ($start as $token) { + $diff[] = [$token, self::OLD]; + } + + reset($from); + reset($to); + + foreach ($common as $token) { + while (($fromToken = reset($from)) !== $token) { + $diff[] = [array_shift($from), self::REMOVED]; + } + + while (($toToken = reset($to)) !== $token) { + $diff[] = [array_shift($to), self::ADDED]; + } + + $diff[] = [$token, self::OLD]; + + array_shift($from); + array_shift($to); + } + + while (($token = array_shift($from)) !== null) { + $diff[] = [$token, self::REMOVED]; + } + + while (($token = array_shift($to)) !== null) { + $diff[] = [$token, self::ADDED]; + } + + foreach ($end as $token) { + $diff[] = [$token, self::OLD]; + } + + if ($this->detectUnmatchedLineEndings($diff)) { + array_unshift($diff, ["#Warning: Strings contain different line endings!\n", self::DIFF_LINE_END_WARNING]); + } + + return $diff; + } + + /** + * Casts variable to string if it is not a string or array. + * + * @return array|string + */ + private function normalizeDiffInput($input) + { + if (!is_array($input) && !is_string($input)) { + return (string) $input; + } + + return $input; + } + + /** + * Checks if input is string, if so it will split it line-by-line. + */ + private function splitStringByLines(string $input): array + { + return preg_split('/(.*\R)/', $input, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + } + + private function selectLcsImplementation(array $from, array $to): LongestCommonSubsequenceCalculator + { + // We do not want to use the time-efficient implementation if its memory + // footprint will probably exceed this value. Note that the footprint + // calculation is only an estimation for the matrix and the LCS method + // will typically allocate a bit more memory than this. + $memoryLimit = 100 * 1024 * 1024; + + if ($this->calculateEstimatedFootprint($from, $to) > $memoryLimit) { + return new MemoryEfficientLongestCommonSubsequenceCalculator; + } + + return new TimeEfficientLongestCommonSubsequenceCalculator; + } + + /** + * Calculates the estimated memory footprint for the DP-based method. + * + * @return float|int + */ + private function calculateEstimatedFootprint(array $from, array $to) + { + $itemSize = PHP_INT_SIZE === 4 ? 76 : 144; + + return $itemSize * min(count($from), count($to)) ** 2; + } + + /** + * Returns true if line ends don't match in a diff. + */ + private function detectUnmatchedLineEndings(array $diff): bool + { + $newLineBreaks = ['' => true]; + $oldLineBreaks = ['' => true]; + + foreach ($diff as $entry) { + if (self::OLD === $entry[1]) { + $ln = $this->getLinebreak($entry[0]); + $oldLineBreaks[$ln] = true; + $newLineBreaks[$ln] = true; + } elseif (self::ADDED === $entry[1]) { + $newLineBreaks[$this->getLinebreak($entry[0])] = true; + } elseif (self::REMOVED === $entry[1]) { + $oldLineBreaks[$this->getLinebreak($entry[0])] = true; + } + } + + // if either input or output is a single line without breaks than no warning should be raised + if (['' => true] === $newLineBreaks || ['' => true] === $oldLineBreaks) { + return false; + } + + // two way compare + foreach ($newLineBreaks as $break => $set) { + if (!isset($oldLineBreaks[$break])) { + return true; + } + } + + foreach ($oldLineBreaks as $break => $set) { + if (!isset($newLineBreaks[$break])) { + return true; + } + } + + return false; + } + + private function getLinebreak($line): string + { + if (!is_string($line)) { + return ''; + } + + $lc = substr($line, -1); + + if ("\r" === $lc) { + return "\r"; + } + + if ("\n" !== $lc) { + return ''; + } + + if ("\r\n" === substr($line, -2)) { + return "\r\n"; + } + + return "\n"; + } + + private static function getArrayDiffParted(array &$from, array &$to): array + { + $start = []; + $end = []; + + reset($to); + + foreach ($from as $k => $v) { + $toK = key($to); + + if ($toK === $k && $v === $to[$k]) { + $start[$k] = $v; + + unset($from[$k], $to[$k]); + } else { + break; + } + } + + end($from); + end($to); + + do { + $fromK = key($from); + $toK = key($to); + + if (null === $fromK || null === $toK || current($from) !== current($to)) { + break; + } + + prev($from); + prev($to); + + $end = [$fromK => $from[$fromK]] + $end; + unset($from[$fromK], $to[$toK]); + } while (true); + + return [$from, $to, $start, $end]; + } +} diff --git a/vendor/sebastian/diff/src/Exception/ConfigurationException.php b/vendor/sebastian/diff/src/Exception/ConfigurationException.php new file mode 100644 index 00000000..b767b219 --- /dev/null +++ b/vendor/sebastian/diff/src/Exception/ConfigurationException.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +use function get_class; +use function gettype; +use function is_object; +use function sprintf; +use Exception; + +final class ConfigurationException extends InvalidArgumentException +{ + public function __construct( + string $option, + string $expected, + $value, + int $code = 0, + Exception $previous = null + ) { + parent::__construct( + sprintf( + 'Option "%s" must be %s, got "%s".', + $option, + $expected, + is_object($value) ? get_class($value) : (null === $value ? '' : gettype($value) . '#' . $value) + ), + $code, + $previous + ); + } +} diff --git a/vendor/sebastian/diff/src/Exception/Exception.php b/vendor/sebastian/diff/src/Exception/Exception.php new file mode 100644 index 00000000..e20d3203 --- /dev/null +++ b/vendor/sebastian/diff/src/Exception/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/sebastian/diff/src/Exception/InvalidArgumentException.php b/vendor/sebastian/diff/src/Exception/InvalidArgumentException.php new file mode 100644 index 00000000..846ac3fb --- /dev/null +++ b/vendor/sebastian/diff/src/Exception/InvalidArgumentException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +class InvalidArgumentException extends \InvalidArgumentException implements Exception +{ +} diff --git a/vendor/sebastian/diff/src/Line.php b/vendor/sebastian/diff/src/Line.php new file mode 100644 index 00000000..3596ed26 --- /dev/null +++ b/vendor/sebastian/diff/src/Line.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +final class Line +{ + public const ADDED = 1; + + public const REMOVED = 2; + + public const UNCHANGED = 3; + + /** + * @var int + */ + private $type; + + /** + * @var string + */ + private $content; + + public function __construct(int $type = self::UNCHANGED, string $content = '') + { + $this->type = $type; + $this->content = $content; + } + + public function getContent(): string + { + return $this->content; + } + + public function getType(): int + { + return $this->type; + } +} diff --git a/vendor/sebastian/diff/src/LongestCommonSubsequenceCalculator.php b/vendor/sebastian/diff/src/LongestCommonSubsequenceCalculator.php new file mode 100644 index 00000000..dea8fe1c --- /dev/null +++ b/vendor/sebastian/diff/src/LongestCommonSubsequenceCalculator.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +interface LongestCommonSubsequenceCalculator +{ + /** + * Calculates the longest common subsequence of two arrays. + */ + public function calculate(array $from, array $to): array; +} diff --git a/vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php b/vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php new file mode 100644 index 00000000..0b626eaf --- /dev/null +++ b/vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +use function array_fill; +use function array_merge; +use function array_reverse; +use function array_slice; +use function count; +use function in_array; +use function max; + +final class MemoryEfficientLongestCommonSubsequenceCalculator implements LongestCommonSubsequenceCalculator +{ + /** + * {@inheritdoc} + */ + public function calculate(array $from, array $to): array + { + $cFrom = count($from); + $cTo = count($to); + + if ($cFrom === 0) { + return []; + } + + if ($cFrom === 1) { + if (in_array($from[0], $to, true)) { + return [$from[0]]; + } + + return []; + } + + $i = (int) ($cFrom / 2); + $fromStart = array_slice($from, 0, $i); + $fromEnd = array_slice($from, $i); + $llB = $this->length($fromStart, $to); + $llE = $this->length(array_reverse($fromEnd), array_reverse($to)); + $jMax = 0; + $max = 0; + + for ($j = 0; $j <= $cTo; $j++) { + $m = $llB[$j] + $llE[$cTo - $j]; + + if ($m >= $max) { + $max = $m; + $jMax = $j; + } + } + + $toStart = array_slice($to, 0, $jMax); + $toEnd = array_slice($to, $jMax); + + return array_merge( + $this->calculate($fromStart, $toStart), + $this->calculate($fromEnd, $toEnd) + ); + } + + private function length(array $from, array $to): array + { + $current = array_fill(0, count($to) + 1, 0); + $cFrom = count($from); + $cTo = count($to); + + for ($i = 0; $i < $cFrom; $i++) { + $prev = $current; + + for ($j = 0; $j < $cTo; $j++) { + if ($from[$i] === $to[$j]) { + $current[$j + 1] = $prev[$j] + 1; + } else { + $current[$j + 1] = max($current[$j], $prev[$j + 1]); + } + } + } + + return $current; + } +} diff --git a/vendor/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php b/vendor/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php new file mode 100644 index 00000000..e55757c3 --- /dev/null +++ b/vendor/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff\Output; + +use function count; + +abstract class AbstractChunkOutputBuilder implements DiffOutputBuilderInterface +{ + /** + * Takes input of the diff array and returns the common parts. + * Iterates through diff line by line. + */ + protected function getCommonChunks(array $diff, int $lineThreshold = 5): array + { + $diffSize = count($diff); + $capturing = false; + $chunkStart = 0; + $chunkSize = 0; + $commonChunks = []; + + for ($i = 0; $i < $diffSize; ++$i) { + if ($diff[$i][1] === 0 /* OLD */) { + if ($capturing === false) { + $capturing = true; + $chunkStart = $i; + $chunkSize = 0; + } else { + ++$chunkSize; + } + } elseif ($capturing !== false) { + if ($chunkSize >= $lineThreshold) { + $commonChunks[$chunkStart] = $chunkStart + $chunkSize; + } + + $capturing = false; + } + } + + if ($capturing !== false && $chunkSize >= $lineThreshold) { + $commonChunks[$chunkStart] = $chunkStart + $chunkSize; + } + + return $commonChunks; + } +} diff --git a/vendor/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php b/vendor/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php new file mode 100644 index 00000000..f79a935c --- /dev/null +++ b/vendor/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff\Output; + +use function fclose; +use function fopen; +use function fwrite; +use function stream_get_contents; +use function substr; +use SebastianBergmann\Diff\Differ; + +/** + * Builds a diff string representation in a loose unified diff format + * listing only changes lines. Does not include line numbers. + */ +final class DiffOnlyOutputBuilder implements DiffOutputBuilderInterface +{ + /** + * @var string + */ + private $header; + + public function __construct(string $header = "--- Original\n+++ New\n") + { + $this->header = $header; + } + + public function getDiff(array $diff): string + { + $buffer = fopen('php://memory', 'r+b'); + + if ('' !== $this->header) { + fwrite($buffer, $this->header); + + if ("\n" !== substr($this->header, -1, 1)) { + fwrite($buffer, "\n"); + } + } + + foreach ($diff as $diffEntry) { + if ($diffEntry[1] === Differ::ADDED) { + fwrite($buffer, '+' . $diffEntry[0]); + } elseif ($diffEntry[1] === Differ::REMOVED) { + fwrite($buffer, '-' . $diffEntry[0]); + } elseif ($diffEntry[1] === Differ::DIFF_LINE_END_WARNING) { + fwrite($buffer, ' ' . $diffEntry[0]); + + continue; // Warnings should not be tested for line break, it will always be there + } else { /* Not changed (old) 0 */ + continue; // we didn't write the non changs line, so do not add a line break either + } + + $lc = substr($diffEntry[0], -1); + + if ($lc !== "\n" && $lc !== "\r") { + fwrite($buffer, "\n"); // \No newline at end of file + } + } + + $diff = stream_get_contents($buffer, -1, 0); + fclose($buffer); + + return $diff; + } +} diff --git a/vendor/sebastian/diff/src/Output/DiffOutputBuilderInterface.php b/vendor/sebastian/diff/src/Output/DiffOutputBuilderInterface.php new file mode 100644 index 00000000..0e18f9f2 --- /dev/null +++ b/vendor/sebastian/diff/src/Output/DiffOutputBuilderInterface.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff\Output; + +/** + * Defines how an output builder should take a generated + * diff array and return a string representation of that diff. + */ +interface DiffOutputBuilderInterface +{ + public function getDiff(array $diff): string; +} diff --git a/vendor/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php b/vendor/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php new file mode 100644 index 00000000..9c55ab2a --- /dev/null +++ b/vendor/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php @@ -0,0 +1,338 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff\Output; + +use function array_merge; +use function array_splice; +use function count; +use function fclose; +use function fopen; +use function fwrite; +use function is_bool; +use function is_int; +use function is_string; +use function max; +use function min; +use function sprintf; +use function stream_get_contents; +use function substr; +use SebastianBergmann\Diff\ConfigurationException; +use SebastianBergmann\Diff\Differ; + +/** + * Strict Unified diff output builder. + * + * Generates (strict) Unified diff's (unidiffs) with hunks. + */ +final class StrictUnifiedDiffOutputBuilder implements DiffOutputBuilderInterface +{ + private static $default = [ + 'collapseRanges' => true, // ranges of length one are rendered with the trailing `,1` + 'commonLineThreshold' => 6, // number of same lines before ending a new hunk and creating a new one (if needed) + 'contextLines' => 3, // like `diff: -u, -U NUM, --unified[=NUM]`, for patch/git apply compatibility best to keep at least @ 3 + 'fromFile' => null, + 'fromFileDate' => null, + 'toFile' => null, + 'toFileDate' => null, + ]; + + /** + * @var bool + */ + private $changed; + + /** + * @var bool + */ + private $collapseRanges; + + /** + * @var int >= 0 + */ + private $commonLineThreshold; + + /** + * @var string + */ + private $header; + + /** + * @var int >= 0 + */ + private $contextLines; + + public function __construct(array $options = []) + { + $options = array_merge(self::$default, $options); + + if (!is_bool($options['collapseRanges'])) { + throw new ConfigurationException('collapseRanges', 'a bool', $options['collapseRanges']); + } + + if (!is_int($options['contextLines']) || $options['contextLines'] < 0) { + throw new ConfigurationException('contextLines', 'an int >= 0', $options['contextLines']); + } + + if (!is_int($options['commonLineThreshold']) || $options['commonLineThreshold'] <= 0) { + throw new ConfigurationException('commonLineThreshold', 'an int > 0', $options['commonLineThreshold']); + } + + $this->assertString($options, 'fromFile'); + $this->assertString($options, 'toFile'); + $this->assertStringOrNull($options, 'fromFileDate'); + $this->assertStringOrNull($options, 'toFileDate'); + + $this->header = sprintf( + "--- %s%s\n+++ %s%s\n", + $options['fromFile'], + null === $options['fromFileDate'] ? '' : "\t" . $options['fromFileDate'], + $options['toFile'], + null === $options['toFileDate'] ? '' : "\t" . $options['toFileDate'] + ); + + $this->collapseRanges = $options['collapseRanges']; + $this->commonLineThreshold = $options['commonLineThreshold']; + $this->contextLines = $options['contextLines']; + } + + public function getDiff(array $diff): string + { + if (0 === count($diff)) { + return ''; + } + + $this->changed = false; + + $buffer = fopen('php://memory', 'r+b'); + fwrite($buffer, $this->header); + + $this->writeDiffHunks($buffer, $diff); + + if (!$this->changed) { + fclose($buffer); + + return ''; + } + + $diff = stream_get_contents($buffer, -1, 0); + + fclose($buffer); + + // If the last char is not a linebreak: add it. + // This might happen when both the `from` and `to` do not have a trailing linebreak + $last = substr($diff, -1); + + return "\n" !== $last && "\r" !== $last + ? $diff . "\n" + : $diff; + } + + private function writeDiffHunks($output, array $diff): void + { + // detect "No newline at end of file" and insert into `$diff` if needed + + $upperLimit = count($diff); + + if (0 === $diff[$upperLimit - 1][1]) { + $lc = substr($diff[$upperLimit - 1][0], -1); + + if ("\n" !== $lc) { + array_splice($diff, $upperLimit, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]); + } + } else { + // search back for the last `+` and `-` line, + // check if has trailing linebreak, else add under it warning under it + $toFind = [1 => true, 2 => true]; + + for ($i = $upperLimit - 1; $i >= 0; --$i) { + if (isset($toFind[$diff[$i][1]])) { + unset($toFind[$diff[$i][1]]); + $lc = substr($diff[$i][0], -1); + + if ("\n" !== $lc) { + array_splice($diff, $i + 1, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]); + } + + if (!count($toFind)) { + break; + } + } + } + } + + // write hunks to output buffer + + $cutOff = max($this->commonLineThreshold, $this->contextLines); + $hunkCapture = false; + $sameCount = $toRange = $fromRange = 0; + $toStart = $fromStart = 1; + $i = 0; + + /** @var int $i */ + foreach ($diff as $i => $entry) { + if (0 === $entry[1]) { // same + if (false === $hunkCapture) { + ++$fromStart; + ++$toStart; + + continue; + } + + ++$sameCount; + ++$toRange; + ++$fromRange; + + if ($sameCount === $cutOff) { + $contextStartOffset = ($hunkCapture - $this->contextLines) < 0 + ? $hunkCapture + : $this->contextLines; + + // note: $contextEndOffset = $this->contextLines; + // + // because we never go beyond the end of the diff. + // with the cutoff/contextlines here the follow is never true; + // + // if ($i - $cutOff + $this->contextLines + 1 > \count($diff)) { + // $contextEndOffset = count($diff) - 1; + // } + // + // ; that would be true for a trailing incomplete hunk case which is dealt with after this loop + + $this->writeHunk( + $diff, + $hunkCapture - $contextStartOffset, + $i - $cutOff + $this->contextLines + 1, + $fromStart - $contextStartOffset, + $fromRange - $cutOff + $contextStartOffset + $this->contextLines, + $toStart - $contextStartOffset, + $toRange - $cutOff + $contextStartOffset + $this->contextLines, + $output + ); + + $fromStart += $fromRange; + $toStart += $toRange; + + $hunkCapture = false; + $sameCount = $toRange = $fromRange = 0; + } + + continue; + } + + $sameCount = 0; + + if ($entry[1] === Differ::NO_LINE_END_EOF_WARNING) { + continue; + } + + $this->changed = true; + + if (false === $hunkCapture) { + $hunkCapture = $i; + } + + if (Differ::ADDED === $entry[1]) { // added + ++$toRange; + } + + if (Differ::REMOVED === $entry[1]) { // removed + ++$fromRange; + } + } + + if (false === $hunkCapture) { + return; + } + + // we end here when cutoff (commonLineThreshold) was not reached, but we where capturing a hunk, + // do not render hunk till end automatically because the number of context lines might be less than the commonLineThreshold + + $contextStartOffset = $hunkCapture - $this->contextLines < 0 + ? $hunkCapture + : $this->contextLines; + + // prevent trying to write out more common lines than there are in the diff _and_ + // do not write more than configured through the context lines + $contextEndOffset = min($sameCount, $this->contextLines); + + $fromRange -= $sameCount; + $toRange -= $sameCount; + + $this->writeHunk( + $diff, + $hunkCapture - $contextStartOffset, + $i - $sameCount + $contextEndOffset + 1, + $fromStart - $contextStartOffset, + $fromRange + $contextStartOffset + $contextEndOffset, + $toStart - $contextStartOffset, + $toRange + $contextStartOffset + $contextEndOffset, + $output + ); + } + + private function writeHunk( + array $diff, + int $diffStartIndex, + int $diffEndIndex, + int $fromStart, + int $fromRange, + int $toStart, + int $toRange, + $output + ): void { + fwrite($output, '@@ -' . $fromStart); + + if (!$this->collapseRanges || 1 !== $fromRange) { + fwrite($output, ',' . $fromRange); + } + + fwrite($output, ' +' . $toStart); + + if (!$this->collapseRanges || 1 !== $toRange) { + fwrite($output, ',' . $toRange); + } + + fwrite($output, " @@\n"); + + for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) { + if ($diff[$i][1] === Differ::ADDED) { + $this->changed = true; + fwrite($output, '+' . $diff[$i][0]); + } elseif ($diff[$i][1] === Differ::REMOVED) { + $this->changed = true; + fwrite($output, '-' . $diff[$i][0]); + } elseif ($diff[$i][1] === Differ::OLD) { + fwrite($output, ' ' . $diff[$i][0]); + } elseif ($diff[$i][1] === Differ::NO_LINE_END_EOF_WARNING) { + $this->changed = true; + fwrite($output, $diff[$i][0]); + } + //} elseif ($diff[$i][1] === Differ::DIFF_LINE_END_WARNING) { // custom comment inserted by PHPUnit/diff package + // skip + //} else { + // unknown/invalid + //} + } + } + + private function assertString(array $options, string $option): void + { + if (!is_string($options[$option])) { + throw new ConfigurationException($option, 'a string', $options[$option]); + } + } + + private function assertStringOrNull(array $options, string $option): void + { + if (null !== $options[$option] && !is_string($options[$option])) { + throw new ConfigurationException($option, 'a string or ', $options[$option]); + } + } +} diff --git a/vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php b/vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php new file mode 100644 index 00000000..8aae6450 --- /dev/null +++ b/vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php @@ -0,0 +1,272 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff\Output; + +use function array_splice; +use function count; +use function fclose; +use function fopen; +use function fwrite; +use function max; +use function min; +use function stream_get_contents; +use function strlen; +use function substr; +use SebastianBergmann\Diff\Differ; + +/** + * Builds a diff string representation in unified diff format in chunks. + */ +final class UnifiedDiffOutputBuilder extends AbstractChunkOutputBuilder +{ + /** + * @var bool + */ + private $collapseRanges = true; + + /** + * @var int >= 0 + */ + private $commonLineThreshold = 6; + + /** + * @var int >= 0 + */ + private $contextLines = 3; + + /** + * @var string + */ + private $header; + + /** + * @var bool + */ + private $addLineNumbers; + + public function __construct(string $header = "--- Original\n+++ New\n", bool $addLineNumbers = false) + { + $this->header = $header; + $this->addLineNumbers = $addLineNumbers; + } + + public function getDiff(array $diff): string + { + $buffer = fopen('php://memory', 'r+b'); + + if ('' !== $this->header) { + fwrite($buffer, $this->header); + + if ("\n" !== substr($this->header, -1, 1)) { + fwrite($buffer, "\n"); + } + } + + if (0 !== count($diff)) { + $this->writeDiffHunks($buffer, $diff); + } + + $diff = stream_get_contents($buffer, -1, 0); + + fclose($buffer); + + // If the diff is non-empty and last char is not a linebreak: add it. + // This might happen when both the `from` and `to` do not have a trailing linebreak + $last = substr($diff, -1); + + return 0 !== strlen($diff) && "\n" !== $last && "\r" !== $last + ? $diff . "\n" + : $diff; + } + + private function writeDiffHunks($output, array $diff): void + { + // detect "No newline at end of file" and insert into `$diff` if needed + + $upperLimit = count($diff); + + if (0 === $diff[$upperLimit - 1][1]) { + $lc = substr($diff[$upperLimit - 1][0], -1); + + if ("\n" !== $lc) { + array_splice($diff, $upperLimit, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]); + } + } else { + // search back for the last `+` and `-` line, + // check if has trailing linebreak, else add under it warning under it + $toFind = [1 => true, 2 => true]; + + for ($i = $upperLimit - 1; $i >= 0; --$i) { + if (isset($toFind[$diff[$i][1]])) { + unset($toFind[$diff[$i][1]]); + $lc = substr($diff[$i][0], -1); + + if ("\n" !== $lc) { + array_splice($diff, $i + 1, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]); + } + + if (!count($toFind)) { + break; + } + } + } + } + + // write hunks to output buffer + + $cutOff = max($this->commonLineThreshold, $this->contextLines); + $hunkCapture = false; + $sameCount = $toRange = $fromRange = 0; + $toStart = $fromStart = 1; + $i = 0; + + /** @var int $i */ + foreach ($diff as $i => $entry) { + if (0 === $entry[1]) { // same + if (false === $hunkCapture) { + ++$fromStart; + ++$toStart; + + continue; + } + + ++$sameCount; + ++$toRange; + ++$fromRange; + + if ($sameCount === $cutOff) { + $contextStartOffset = ($hunkCapture - $this->contextLines) < 0 + ? $hunkCapture + : $this->contextLines; + + // note: $contextEndOffset = $this->contextLines; + // + // because we never go beyond the end of the diff. + // with the cutoff/contextlines here the follow is never true; + // + // if ($i - $cutOff + $this->contextLines + 1 > \count($diff)) { + // $contextEndOffset = count($diff) - 1; + // } + // + // ; that would be true for a trailing incomplete hunk case which is dealt with after this loop + + $this->writeHunk( + $diff, + $hunkCapture - $contextStartOffset, + $i - $cutOff + $this->contextLines + 1, + $fromStart - $contextStartOffset, + $fromRange - $cutOff + $contextStartOffset + $this->contextLines, + $toStart - $contextStartOffset, + $toRange - $cutOff + $contextStartOffset + $this->contextLines, + $output + ); + + $fromStart += $fromRange; + $toStart += $toRange; + + $hunkCapture = false; + $sameCount = $toRange = $fromRange = 0; + } + + continue; + } + + $sameCount = 0; + + if ($entry[1] === Differ::NO_LINE_END_EOF_WARNING) { + continue; + } + + if (false === $hunkCapture) { + $hunkCapture = $i; + } + + if (Differ::ADDED === $entry[1]) { + ++$toRange; + } + + if (Differ::REMOVED === $entry[1]) { + ++$fromRange; + } + } + + if (false === $hunkCapture) { + return; + } + + // we end here when cutoff (commonLineThreshold) was not reached, but we where capturing a hunk, + // do not render hunk till end automatically because the number of context lines might be less than the commonLineThreshold + + $contextStartOffset = $hunkCapture - $this->contextLines < 0 + ? $hunkCapture + : $this->contextLines; + + // prevent trying to write out more common lines than there are in the diff _and_ + // do not write more than configured through the context lines + $contextEndOffset = min($sameCount, $this->contextLines); + + $fromRange -= $sameCount; + $toRange -= $sameCount; + + $this->writeHunk( + $diff, + $hunkCapture - $contextStartOffset, + $i - $sameCount + $contextEndOffset + 1, + $fromStart - $contextStartOffset, + $fromRange + $contextStartOffset + $contextEndOffset, + $toStart - $contextStartOffset, + $toRange + $contextStartOffset + $contextEndOffset, + $output + ); + } + + private function writeHunk( + array $diff, + int $diffStartIndex, + int $diffEndIndex, + int $fromStart, + int $fromRange, + int $toStart, + int $toRange, + $output + ): void { + if ($this->addLineNumbers) { + fwrite($output, '@@ -' . $fromStart); + + if (!$this->collapseRanges || 1 !== $fromRange) { + fwrite($output, ',' . $fromRange); + } + + fwrite($output, ' +' . $toStart); + + if (!$this->collapseRanges || 1 !== $toRange) { + fwrite($output, ',' . $toRange); + } + + fwrite($output, " @@\n"); + } else { + fwrite($output, "@@ @@\n"); + } + + for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) { + if ($diff[$i][1] === Differ::ADDED) { + fwrite($output, '+' . $diff[$i][0]); + } elseif ($diff[$i][1] === Differ::REMOVED) { + fwrite($output, '-' . $diff[$i][0]); + } elseif ($diff[$i][1] === Differ::OLD) { + fwrite($output, ' ' . $diff[$i][0]); + } elseif ($diff[$i][1] === Differ::NO_LINE_END_EOF_WARNING) { + fwrite($output, "\n"); // $diff[$i][0] + } else { /* Not changed (old) Differ::OLD or Warning Differ::DIFF_LINE_END_WARNING */ + fwrite($output, ' ' . $diff[$i][0]); + } + } + } +} diff --git a/vendor/sebastian/diff/src/Parser.php b/vendor/sebastian/diff/src/Parser.php new file mode 100644 index 00000000..cc9e3887 --- /dev/null +++ b/vendor/sebastian/diff/src/Parser.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +use function array_pop; +use function count; +use function max; +use function preg_match; +use function preg_split; + +/** + * Unified diff parser. + */ +final class Parser +{ + /** + * @return Diff[] + */ + public function parse(string $string): array + { + $lines = preg_split('(\r\n|\r|\n)', $string); + + if (!empty($lines) && $lines[count($lines) - 1] === '') { + array_pop($lines); + } + + $lineCount = count($lines); + $diffs = []; + $diff = null; + $collected = []; + + for ($i = 0; $i < $lineCount; ++$i) { + if (preg_match('#^---\h+"?(?P[^\\v\\t"]+)#', $lines[$i], $fromMatch) && + preg_match('#^\\+\\+\\+\\h+"?(?P[^\\v\\t"]+)#', $lines[$i + 1], $toMatch)) { + if ($diff !== null) { + $this->parseFileDiff($diff, $collected); + + $diffs[] = $diff; + $collected = []; + } + + $diff = new Diff($fromMatch['file'], $toMatch['file']); + + ++$i; + } else { + if (preg_match('/^(?:diff --git |index [\da-f\.]+|[+-]{3} [ab])/', $lines[$i])) { + continue; + } + + $collected[] = $lines[$i]; + } + } + + if ($diff !== null && count($collected)) { + $this->parseFileDiff($diff, $collected); + + $diffs[] = $diff; + } + + return $diffs; + } + + private function parseFileDiff(Diff $diff, array $lines): void + { + $chunks = []; + $chunk = null; + $diffLines = []; + + foreach ($lines as $line) { + if (preg_match('/^@@\s+-(?P\d+)(?:,\s*(?P\d+))?\s+\+(?P\d+)(?:,\s*(?P\d+))?\s+@@/', $line, $match)) { + $chunk = new Chunk( + (int) $match['start'], + isset($match['startrange']) ? max(1, (int) $match['startrange']) : 1, + (int) $match['end'], + isset($match['endrange']) ? max(1, (int) $match['endrange']) : 1 + ); + + $chunks[] = $chunk; + $diffLines = []; + + continue; + } + + if (preg_match('/^(?P[+ -])?(?P.*)/', $line, $match)) { + $type = Line::UNCHANGED; + + if ($match['type'] === '+') { + $type = Line::ADDED; + } elseif ($match['type'] === '-') { + $type = Line::REMOVED; + } + + $diffLines[] = new Line($type, $match['line']); + + if (null !== $chunk) { + $chunk->setLines($diffLines); + } + } + } + + $diff->setChunks($chunks); + } +} diff --git a/vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php b/vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php new file mode 100644 index 00000000..fd19cac7 --- /dev/null +++ b/vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +use function array_reverse; +use function count; +use function max; +use SplFixedArray; + +final class TimeEfficientLongestCommonSubsequenceCalculator implements LongestCommonSubsequenceCalculator +{ + /** + * {@inheritdoc} + */ + public function calculate(array $from, array $to): array + { + $common = []; + $fromLength = count($from); + $toLength = count($to); + $width = $fromLength + 1; + $matrix = new SplFixedArray($width * ($toLength + 1)); + + for ($i = 0; $i <= $fromLength; ++$i) { + $matrix[$i] = 0; + } + + for ($j = 0; $j <= $toLength; ++$j) { + $matrix[$j * $width] = 0; + } + + for ($i = 1; $i <= $fromLength; ++$i) { + for ($j = 1; $j <= $toLength; ++$j) { + $o = ($j * $width) + $i; + $matrix[$o] = max( + $matrix[$o - 1], + $matrix[$o - $width], + $from[$i - 1] === $to[$j - 1] ? $matrix[$o - $width - 1] + 1 : 0 + ); + } + } + + $i = $fromLength; + $j = $toLength; + + while ($i > 0 && $j > 0) { + if ($from[$i - 1] === $to[$j - 1]) { + $common[] = $from[$i - 1]; + --$i; + --$j; + } else { + $o = ($j * $width) + $i; + + if ($matrix[$o - $width] > $matrix[$o - 1]) { + --$j; + } else { + --$i; + } + } + } + + return array_reverse($common); + } +} diff --git a/vendor/sebastian/environment/ChangeLog.md b/vendor/sebastian/environment/ChangeLog.md new file mode 100644 index 00000000..07365951 --- /dev/null +++ b/vendor/sebastian/environment/ChangeLog.md @@ -0,0 +1,183 @@ +# Changes in sebastianbergmann/environment + +All notable changes in `sebastianbergmann/environment` are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [5.1.5] - 2023-02-03 + +### Fixed + +* [#59](https://github.com/sebastianbergmann/environment/issues/59): Wrong usage of `stream_isatty()`, `fstat()` used without checking whether the function is available + +## [5.1.4] - 2022-04-03 + +### Fixed + +* [#63](https://github.com/sebastianbergmann/environment/pull/63): `Runtime::getCurrentSettings()` does not correctly process INI settings + +## [5.1.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [5.1.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [5.1.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [5.1.0] - 2020-04-14 + +### Added + +* `Runtime::performsJustInTimeCompilation()` returns `true` if PHP 8's JIT is active, `false` otherwise + +## [5.0.2] - 2020-03-31 + +### Fixed + +* [#55](https://github.com/sebastianbergmann/environment/issues/55): `stty` command is executed even if no tty is available + +## [5.0.1] - 2020-02-19 + +### Changed + +* `Runtime::getNameWithVersionAndCodeCoverageDriver()` now prioritizes PCOV over Xdebug when both extensions are loaded (just like php-code-coverage does) + +## [5.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.1 and PHP 7.2 + +## [4.2.3] - 2019-11-20 + +### Changed + +* [#50](https://github.com/sebastianbergmann/environment/pull/50): Windows improvements to console capabilities + +### Fixed + +* [#49](https://github.com/sebastianbergmann/environment/issues/49): Detection how OpCache handles docblocks does not work correctly when PHPDBG is used + +## [4.2.2] - 2019-05-05 + +### Fixed + +* [#44](https://github.com/sebastianbergmann/environment/pull/44): `TypeError` in `Console::getNumberOfColumnsInteractive()` + +## [4.2.1] - 2019-04-25 + +### Fixed + +* Fixed an issue in `Runtime::getCurrentSettings()` + +## [4.2.0] - 2019-04-25 + +### Added + +* [#36](https://github.com/sebastianbergmann/environment/pull/36): `Runtime::getCurrentSettings()` + +## [4.1.0] - 2019-02-01 + +### Added + +* Implemented `Runtime::getNameWithVersionAndCodeCoverageDriver()` method +* [#34](https://github.com/sebastianbergmann/environment/pull/34): Support for PCOV extension + +## [4.0.2] - 2019-01-28 + +### Fixed + +* [#33](https://github.com/sebastianbergmann/environment/issues/33): `Runtime::discardsComments()` returns true too eagerly + +### Removed + +* Removed support for Zend Optimizer+ in `Runtime::discardsComments()` + +## [4.0.1] - 2018-11-25 + +### Fixed + +* [#31](https://github.com/sebastianbergmann/environment/issues/31): Regressions in `Console` class + +## [4.0.0] - 2018-10-23 [YANKED] + +### Fixed + +* [#25](https://github.com/sebastianbergmann/environment/pull/25): `Console::hasColorSupport()` does not work on Windows + +### Removed + +* This component is no longer supported on PHP 7.0 + +## [3.1.0] - 2017-07-01 + +### Added + +* [#21](https://github.com/sebastianbergmann/environment/issues/21): Equivalent of `PHP_OS_FAMILY` (for PHP < 7.2) + +## [3.0.4] - 2017-06-20 + +### Fixed + +* [#20](https://github.com/sebastianbergmann/environment/pull/20): PHP 7 mode of HHVM not forced + +## [3.0.3] - 2017-05-18 + +### Fixed + +* [#18](https://github.com/sebastianbergmann/environment/issues/18): `Uncaught TypeError: preg_match() expects parameter 2 to be string, null given` + +## [3.0.2] - 2017-04-21 + +### Fixed + +* [#17](https://github.com/sebastianbergmann/environment/issues/17): `Uncaught TypeError: trim() expects parameter 1 to be string, boolean given` + +## [3.0.1] - 2017-04-21 + +### Fixed + +* Fixed inverted logic in `Runtime::discardsComments()` + +## [3.0.0] - 2017-04-21 + +### Added + +* Implemented `Runtime::discardsComments()` for querying whether the PHP runtime discards annotations + +### Removed + +* This component is no longer supported on PHP 5.6 + +[5.1.5]: https://github.com/sebastianbergmann/environment/compare/5.1.4...5.1.5 +[5.1.4]: https://github.com/sebastianbergmann/environment/compare/5.1.3...5.1.4 +[5.1.3]: https://github.com/sebastianbergmann/environment/compare/5.1.2...5.1.3 +[5.1.2]: https://github.com/sebastianbergmann/environment/compare/5.1.1...5.1.2 +[5.1.1]: https://github.com/sebastianbergmann/environment/compare/5.1.0...5.1.1 +[5.1.0]: https://github.com/sebastianbergmann/environment/compare/5.0.2...5.1.0 +[5.0.2]: https://github.com/sebastianbergmann/environment/compare/5.0.1...5.0.2 +[5.0.1]: https://github.com/sebastianbergmann/environment/compare/5.0.0...5.0.1 +[5.0.0]: https://github.com/sebastianbergmann/environment/compare/4.2.3...5.0.0 +[4.2.3]: https://github.com/sebastianbergmann/environment/compare/4.2.2...4.2.3 +[4.2.2]: https://github.com/sebastianbergmann/environment/compare/4.2.1...4.2.2 +[4.2.1]: https://github.com/sebastianbergmann/environment/compare/4.2.0...4.2.1 +[4.2.0]: https://github.com/sebastianbergmann/environment/compare/4.1.0...4.2.0 +[4.1.0]: https://github.com/sebastianbergmann/environment/compare/4.0.2...4.1.0 +[4.0.2]: https://github.com/sebastianbergmann/environment/compare/4.0.1...4.0.2 +[4.0.1]: https://github.com/sebastianbergmann/environment/compare/66691f8e2dc4641909166b275a9a4f45c0e89092...4.0.1 +[4.0.0]: https://github.com/sebastianbergmann/environment/compare/3.1.0...66691f8e2dc4641909166b275a9a4f45c0e89092 +[3.1.0]: https://github.com/sebastianbergmann/environment/compare/3.0...3.1.0 +[3.0.4]: https://github.com/sebastianbergmann/environment/compare/3.0.3...3.0.4 +[3.0.3]: https://github.com/sebastianbergmann/environment/compare/3.0.2...3.0.3 +[3.0.2]: https://github.com/sebastianbergmann/environment/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/environment/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/environment/compare/2.0...3.0.0 + diff --git a/vendor/sebastian/environment/LICENSE b/vendor/sebastian/environment/LICENSE new file mode 100644 index 00000000..42546339 --- /dev/null +++ b/vendor/sebastian/environment/LICENSE @@ -0,0 +1,33 @@ +sebastian/environment + +Copyright (c) 2014-2022, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/environment/README.md b/vendor/sebastian/environment/README.md new file mode 100644 index 00000000..1fead13e --- /dev/null +++ b/vendor/sebastian/environment/README.md @@ -0,0 +1,21 @@ +# sebastian/environment + +[![Latest Stable Version](https://img.shields.io/packagist/v/sebastian/environment.svg?style=flat-square)](https://packagist.org/packages/sebastian/environment) +[![CI Status](https://github.com/sebastianbergmann/environment/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/environment/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/environment/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/environment) + +This component provides functionality that helps writing PHP code that has runtime-specific (PHP / HHVM) execution paths. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/environment +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/environment +``` diff --git a/vendor/sebastian/environment/composer.json b/vendor/sebastian/environment/composer.json new file mode 100644 index 00000000..d50dcfd7 --- /dev/null +++ b/vendor/sebastian/environment/composer.json @@ -0,0 +1,40 @@ +{ + "name": "sebastian/environment", + "description": "Provides functionality to handle HHVM/PHP environments", + "keywords": ["environment","hhvm","xdebug"], + "homepage": "http://www.github.com/sebastianbergmann/environment", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "prefer-stable": true, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + } +} diff --git a/vendor/sebastian/environment/src/Console.php b/vendor/sebastian/environment/src/Console.php new file mode 100644 index 00000000..180eb60b --- /dev/null +++ b/vendor/sebastian/environment/src/Console.php @@ -0,0 +1,187 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Environment; + +use const DIRECTORY_SEPARATOR; +use const STDIN; +use const STDOUT; +use function defined; +use function fclose; +use function fstat; +use function function_exists; +use function getenv; +use function is_resource; +use function is_string; +use function posix_isatty; +use function preg_match; +use function proc_close; +use function proc_open; +use function sapi_windows_vt100_support; +use function shell_exec; +use function stream_get_contents; +use function stream_isatty; +use function trim; + +final class Console +{ + /** + * @var int + */ + public const STDIN = 0; + + /** + * @var int + */ + public const STDOUT = 1; + + /** + * @var int + */ + public const STDERR = 2; + + /** + * Returns true if STDOUT supports colorization. + * + * This code has been copied and adapted from + * Symfony\Component\Console\Output\StreamOutput. + */ + public function hasColorSupport(): bool + { + if ('Hyper' === getenv('TERM_PROGRAM')) { + return true; + } + + if ($this->isWindows()) { + // @codeCoverageIgnoreStart + return (defined('STDOUT') && function_exists('sapi_windows_vt100_support') && @sapi_windows_vt100_support(STDOUT)) || + false !== getenv('ANSICON') || + 'ON' === getenv('ConEmuANSI') || + 'xterm' === getenv('TERM'); + // @codeCoverageIgnoreEnd + } + + if (!defined('STDOUT')) { + // @codeCoverageIgnoreStart + return false; + // @codeCoverageIgnoreEnd + } + + return $this->isInteractive(STDOUT); + } + + /** + * Returns the number of columns of the terminal. + * + * @codeCoverageIgnore + */ + public function getNumberOfColumns(): int + { + if (!$this->isInteractive(defined('STDIN') ? STDIN : self::STDIN)) { + return 80; + } + + if ($this->isWindows()) { + return $this->getNumberOfColumnsWindows(); + } + + return $this->getNumberOfColumnsInteractive(); + } + + /** + * Returns if the file descriptor is an interactive terminal or not. + * + * Normally, we want to use a resource as a parameter, yet sadly it's not always awailable, + * eg when running code in interactive console (`php -a`), STDIN/STDOUT/STDERR constants are not defined. + * + * @param int|resource $fileDescriptor + */ + public function isInteractive($fileDescriptor = self::STDOUT): bool + { + if (is_resource($fileDescriptor)) { + if (function_exists('stream_isatty') && @stream_isatty($fileDescriptor)) { + return true; + } + + if (function_exists('fstat')) { + $stat = @fstat(STDOUT); + + return $stat && 0020000 === ($stat['mode'] & 0170000); + } + + return false; + } + + return function_exists('posix_isatty') && @posix_isatty($fileDescriptor); + } + + private function isWindows(): bool + { + return DIRECTORY_SEPARATOR === '\\'; + } + + /** + * @codeCoverageIgnore + */ + private function getNumberOfColumnsInteractive(): int + { + if (function_exists('shell_exec') && preg_match('#\d+ (\d+)#', shell_exec('stty size') ?: '', $match) === 1) { + if ((int) $match[1] > 0) { + return (int) $match[1]; + } + } + + if (function_exists('shell_exec') && preg_match('#columns = (\d+);#', shell_exec('stty') ?: '', $match) === 1) { + if ((int) $match[1] > 0) { + return (int) $match[1]; + } + } + + return 80; + } + + /** + * @codeCoverageIgnore + */ + private function getNumberOfColumnsWindows(): int + { + $ansicon = getenv('ANSICON'); + $columns = 80; + + if (is_string($ansicon) && preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim($ansicon), $matches)) { + $columns = (int) $matches[1]; + } elseif (function_exists('proc_open')) { + $process = proc_open( + 'mode CON', + [ + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ], + $pipes, + null, + null, + ['suppress_errors' => true] + ); + + if (is_resource($process)) { + $info = stream_get_contents($pipes[1]); + + fclose($pipes[1]); + fclose($pipes[2]); + proc_close($process); + + if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { + $columns = (int) $matches[2]; + } + } + } + + return $columns - 1; + } +} diff --git a/vendor/sebastian/environment/src/OperatingSystem.php b/vendor/sebastian/environment/src/OperatingSystem.php new file mode 100644 index 00000000..1f3ebca7 --- /dev/null +++ b/vendor/sebastian/environment/src/OperatingSystem.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Environment; + +use const DIRECTORY_SEPARATOR; +use const PHP_OS; +use const PHP_OS_FAMILY; +use function defined; + +final class OperatingSystem +{ + /** + * Returns PHP_OS_FAMILY (if defined (which it is on PHP >= 7.2)). + * Returns a string (compatible with PHP_OS_FAMILY) derived from PHP_OS otherwise. + */ + public function getFamily(): string + { + if (defined('PHP_OS_FAMILY')) { + return PHP_OS_FAMILY; + } + + if (DIRECTORY_SEPARATOR === '\\') { + return 'Windows'; + } + + switch (PHP_OS) { + case 'Darwin': + return 'Darwin'; + + case 'DragonFly': + case 'FreeBSD': + case 'NetBSD': + case 'OpenBSD': + return 'BSD'; + + case 'Linux': + return 'Linux'; + + case 'SunOS': + return 'Solaris'; + + default: + return 'Unknown'; + } + } +} diff --git a/vendor/sebastian/environment/src/Runtime.php b/vendor/sebastian/environment/src/Runtime.php new file mode 100644 index 00000000..d1b92d62 --- /dev/null +++ b/vendor/sebastian/environment/src/Runtime.php @@ -0,0 +1,321 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Environment; + +use const PHP_BINARY; +use const PHP_BINDIR; +use const PHP_MAJOR_VERSION; +use const PHP_SAPI; +use const PHP_VERSION; +use function array_map; +use function array_merge; +use function defined; +use function escapeshellarg; +use function explode; +use function extension_loaded; +use function getenv; +use function ini_get; +use function is_readable; +use function parse_ini_file; +use function php_ini_loaded_file; +use function php_ini_scanned_files; +use function phpversion; +use function sprintf; +use function strpos; + +/** + * Utility class for HHVM/PHP environment handling. + */ +final class Runtime +{ + /** + * @var string + */ + private static $binary; + + /** + * Returns true when Xdebug or PCOV is available or + * the runtime used is PHPDBG. + */ + public function canCollectCodeCoverage(): bool + { + return $this->hasXdebug() || $this->hasPCOV() || $this->hasPHPDBGCodeCoverage(); + } + + /** + * Returns true when Zend OPcache is loaded, enabled, + * and is configured to discard comments. + */ + public function discardsComments(): bool + { + if (!$this->isOpcacheActive()) { + return false; + } + + if (ini_get('opcache.save_comments') !== '0') { + return false; + } + + return true; + } + + /** + * Returns true when Zend OPcache is loaded, enabled, + * and is configured to perform just-in-time compilation. + */ + public function performsJustInTimeCompilation(): bool + { + if (PHP_MAJOR_VERSION < 8) { + return false; + } + + if (!$this->isOpcacheActive()) { + return false; + } + + if (strpos(ini_get('opcache.jit'), '0') === 0) { + return false; + } + + return true; + } + + /** + * Returns the path to the binary of the current runtime. + * Appends ' --php' to the path when the runtime is HHVM. + */ + public function getBinary(): string + { + // HHVM + if (self::$binary === null && $this->isHHVM()) { + // @codeCoverageIgnoreStart + if ((self::$binary = getenv('PHP_BINARY')) === false) { + self::$binary = PHP_BINARY; + } + + self::$binary = escapeshellarg(self::$binary) . ' --php' . + ' -d hhvm.php7.all=1'; + // @codeCoverageIgnoreEnd + } + + if (self::$binary === null && PHP_BINARY !== '') { + self::$binary = escapeshellarg(PHP_BINARY); + } + + if (self::$binary === null) { + // @codeCoverageIgnoreStart + $possibleBinaryLocations = [ + PHP_BINDIR . '/php', + PHP_BINDIR . '/php-cli.exe', + PHP_BINDIR . '/php.exe', + ]; + + foreach ($possibleBinaryLocations as $binary) { + if (is_readable($binary)) { + self::$binary = escapeshellarg($binary); + + break; + } + } + // @codeCoverageIgnoreEnd + } + + if (self::$binary === null) { + // @codeCoverageIgnoreStart + self::$binary = 'php'; + // @codeCoverageIgnoreEnd + } + + return self::$binary; + } + + public function getNameWithVersion(): string + { + return $this->getName() . ' ' . $this->getVersion(); + } + + public function getNameWithVersionAndCodeCoverageDriver(): string + { + if (!$this->canCollectCodeCoverage() || $this->hasPHPDBGCodeCoverage()) { + return $this->getNameWithVersion(); + } + + if ($this->hasPCOV()) { + return sprintf( + '%s with PCOV %s', + $this->getNameWithVersion(), + phpversion('pcov') + ); + } + + if ($this->hasXdebug()) { + return sprintf( + '%s with Xdebug %s', + $this->getNameWithVersion(), + phpversion('xdebug') + ); + } + } + + public function getName(): string + { + if ($this->isHHVM()) { + // @codeCoverageIgnoreStart + return 'HHVM'; + // @codeCoverageIgnoreEnd + } + + if ($this->isPHPDBG()) { + // @codeCoverageIgnoreStart + return 'PHPDBG'; + // @codeCoverageIgnoreEnd + } + + return 'PHP'; + } + + public function getVendorUrl(): string + { + if ($this->isHHVM()) { + // @codeCoverageIgnoreStart + return 'http://hhvm.com/'; + // @codeCoverageIgnoreEnd + } + + return 'https://secure.php.net/'; + } + + public function getVersion(): string + { + if ($this->isHHVM()) { + // @codeCoverageIgnoreStart + return HHVM_VERSION; + // @codeCoverageIgnoreEnd + } + + return PHP_VERSION; + } + + /** + * Returns true when the runtime used is PHP and Xdebug is loaded. + */ + public function hasXdebug(): bool + { + return ($this->isPHP() || $this->isHHVM()) && extension_loaded('xdebug'); + } + + /** + * Returns true when the runtime used is HHVM. + */ + public function isHHVM(): bool + { + return defined('HHVM_VERSION'); + } + + /** + * Returns true when the runtime used is PHP without the PHPDBG SAPI. + */ + public function isPHP(): bool + { + return !$this->isHHVM() && !$this->isPHPDBG(); + } + + /** + * Returns true when the runtime used is PHP with the PHPDBG SAPI. + */ + public function isPHPDBG(): bool + { + return PHP_SAPI === 'phpdbg' && !$this->isHHVM(); + } + + /** + * Returns true when the runtime used is PHP with the PHPDBG SAPI + * and the phpdbg_*_oplog() functions are available (PHP >= 7.0). + */ + public function hasPHPDBGCodeCoverage(): bool + { + return $this->isPHPDBG(); + } + + /** + * Returns true when the runtime used is PHP with PCOV loaded and enabled. + */ + public function hasPCOV(): bool + { + return $this->isPHP() && extension_loaded('pcov') && ini_get('pcov.enabled'); + } + + /** + * Parses the loaded php.ini file (if any) as well as all + * additional php.ini files from the additional ini dir for + * a list of all configuration settings loaded from files + * at startup. Then checks for each php.ini setting passed + * via the `$values` parameter whether this setting has + * been changed at runtime. Returns an array of strings + * where each string has the format `key=value` denoting + * the name of a changed php.ini setting with its new value. + * + * @return string[] + */ + public function getCurrentSettings(array $values): array + { + $diff = []; + $files = []; + + if ($file = php_ini_loaded_file()) { + $files[] = $file; + } + + if ($scanned = php_ini_scanned_files()) { + $files = array_merge( + $files, + array_map( + 'trim', + explode(",\n", $scanned) + ) + ); + } + + foreach ($files as $ini) { + $config = parse_ini_file($ini, true); + + foreach ($values as $value) { + $set = ini_get($value); + + if (empty($set)) { + continue; + } + + if ((!isset($config[$value]) || ($set !== $config[$value]))) { + $diff[$value] = sprintf('%s=%s', $value, $set); + } + } + } + + return $diff; + } + + private function isOpcacheActive(): bool + { + if (!extension_loaded('Zend OPcache')) { + return false; + } + + if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && ini_get('opcache.enable_cli') === '1') { + return true; + } + + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' && ini_get('opcache.enable') === '1') { + return true; + } + + return false; + } +} diff --git a/vendor/sebastian/exporter/ChangeLog.md b/vendor/sebastian/exporter/ChangeLog.md new file mode 100644 index 00000000..91a4220d --- /dev/null +++ b/vendor/sebastian/exporter/ChangeLog.md @@ -0,0 +1,78 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [4.0.5] - 2022-09-14 + +### Fixed + +* [#47](https://github.com/sebastianbergmann/exporter/pull/47): Fix `float` export precision + +## [4.0.4] - 2021-11-11 + +### Changed + +* [#37](https://github.com/sebastianbergmann/exporter/pull/37): Improve export of closed resources + +## [4.0.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [4.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [4.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [4.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.0, PHP 7.1, and PHP 7.2 + +## [3.1.5] - 2022-09-14 + +### Fixed + +* [#47](https://github.com/sebastianbergmann/exporter/pull/47): Fix `float` export precision + +## [3.1.4] - 2021-11-11 + +### Changed + +* [#38](https://github.com/sebastianbergmann/exporter/pull/38): Improve export of closed resources + +## [3.1.3] - 2020-11-30 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.0` to `>=7.0` + +## [3.1.2] - 2019-09-14 + +### Fixed + +* [#29](https://github.com/sebastianbergmann/exporter/pull/29): Second parameter for `str_repeat()` must be an integer + +### Removed + +* Remove HHVM-specific code that is no longer needed + +[4.0.5]: https://github.com/sebastianbergmann/exporter/compare/4.0.4...4.0.5 +[4.0.4]: https://github.com/sebastianbergmann/exporter/compare/4.0.3...4.0.4 +[4.0.3]: https://github.com/sebastianbergmann/exporter/compare/4.0.2...4.0.3 +[4.0.2]: https://github.com/sebastianbergmann/exporter/compare/4.0.1...4.0.2 +[4.0.1]: https://github.com/sebastianbergmann/exporter/compare/4.0.0...4.0.1 +[4.0.0]: https://github.com/sebastianbergmann/exporter/compare/3.1.2...4.0.0 +[3.1.5]: https://github.com/sebastianbergmann/exporter/compare/3.1.4...3.1.5 +[3.1.4]: https://github.com/sebastianbergmann/exporter/compare/3.1.3...3.1.4 +[3.1.3]: https://github.com/sebastianbergmann/exporter/compare/3.1.2...3.1.3 +[3.1.2]: https://github.com/sebastianbergmann/exporter/compare/3.1.1...3.1.2 diff --git a/vendor/sebastian/exporter/LICENSE b/vendor/sebastian/exporter/LICENSE new file mode 100644 index 00000000..26dc7fec --- /dev/null +++ b/vendor/sebastian/exporter/LICENSE @@ -0,0 +1,33 @@ +Exporter + +Copyright (c) 2002-2021, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/exporter/README.md b/vendor/sebastian/exporter/README.md new file mode 100644 index 00000000..ed8719f5 --- /dev/null +++ b/vendor/sebastian/exporter/README.md @@ -0,0 +1,174 @@ +# sebastian/exporter + +[![CI Status](https://github.com/sebastianbergmann/exporter/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/exporter/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/exporter/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/exporter) + +This component provides the functionality to export PHP variables for visualization. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/exporter +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/exporter +``` + +## Usage + +Exporting: + +```php + '' + 'string' => '' + 'code' => 0 + 'file' => '/home/sebastianbergmann/test.php' + 'line' => 34 + 'previous' => null +) +*/ + +print $exporter->export(new Exception); +``` + +## Data Types + +Exporting simple types: + +```php +export(46); + +// 4.0 +print $exporter->export(4.0); + +// 'hello, world!' +print $exporter->export('hello, world!'); + +// false +print $exporter->export(false); + +// NAN +print $exporter->export(acos(8)); + +// -INF +print $exporter->export(log(0)); + +// null +print $exporter->export(null); + +// resource(13) of type (stream) +print $exporter->export(fopen('php://stderr', 'w')); + +// Binary String: 0x000102030405 +print $exporter->export(chr(0) . chr(1) . chr(2) . chr(3) . chr(4) . chr(5)); +``` + +Exporting complex types: + +```php + Array &1 ( + 0 => 1 + 1 => 2 + 2 => 3 + ) + 1 => Array &2 ( + 0 => '' + 1 => 0 + 2 => false + ) +) +*/ + +print $exporter->export(array(array(1,2,3), array("",0,FALSE))); + +/* +Array &0 ( + 'self' => Array &1 ( + 'self' => Array &1 + ) +) +*/ + +$array = array(); +$array['self'] = &$array; +print $exporter->export($array); + +/* +stdClass Object &0000000003a66dcc0000000025e723e2 ( + 'self' => stdClass Object &0000000003a66dcc0000000025e723e2 +) +*/ + +$obj = new stdClass(); +$obj->self = $obj; +print $exporter->export($obj); +``` + +Compact exports: + +```php +shortenedExport(array()); + +// Array (...) +print $exporter->shortenedExport(array(1,2,3,4,5)); + +// stdClass Object () +print $exporter->shortenedExport(new stdClass); + +// Exception Object (...) +print $exporter->shortenedExport(new Exception); + +// this\nis\na\nsuper\nlong\nstring\nt...\nspace +print $exporter->shortenedExport( +<<=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "ext-mbstring": "*" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + } +} + diff --git a/vendor/sebastian/exporter/src/Exporter.php b/vendor/sebastian/exporter/src/Exporter.php new file mode 100644 index 00000000..ca006ad6 --- /dev/null +++ b/vendor/sebastian/exporter/src/Exporter.php @@ -0,0 +1,346 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Exporter; + +use function bin2hex; +use function count; +use function function_exists; +use function get_class; +use function get_resource_type; +use function gettype; +use function implode; +use function ini_get; +use function ini_set; +use function is_array; +use function is_float; +use function is_object; +use function is_resource; +use function is_string; +use function mb_strlen; +use function mb_substr; +use function preg_match; +use function spl_object_hash; +use function sprintf; +use function str_repeat; +use function str_replace; +use function strlen; +use function substr; +use function var_export; +use SebastianBergmann\RecursionContext\Context; +use SplObjectStorage; + +/** + * A nifty utility for visualizing PHP variables. + * + * + * export(new Exception); + * + */ +class Exporter +{ + /** + * Exports a value as a string. + * + * The output of this method is similar to the output of print_r(), but + * improved in various aspects: + * + * - NULL is rendered as "null" (instead of "") + * - TRUE is rendered as "true" (instead of "1") + * - FALSE is rendered as "false" (instead of "") + * - Strings are always quoted with single quotes + * - Carriage returns and newlines are normalized to \n + * - Recursion and repeated rendering is treated properly + * + * @param int $indentation The indentation level of the 2nd+ line + * + * @return string + */ + public function export($value, $indentation = 0) + { + return $this->recursiveExport($value, $indentation); + } + + /** + * @param array $data + * @param Context $context + * + * @return string + */ + public function shortenedRecursiveExport(&$data, Context $context = null) + { + $result = []; + $exporter = new self(); + + if (!$context) { + $context = new Context; + } + + $array = $data; + $context->add($data); + + foreach ($array as $key => $value) { + if (is_array($value)) { + if ($context->contains($data[$key]) !== false) { + $result[] = '*RECURSION*'; + } else { + $result[] = sprintf( + 'array(%s)', + $this->shortenedRecursiveExport($data[$key], $context) + ); + } + } else { + $result[] = $exporter->shortenedExport($value); + } + } + + return implode(', ', $result); + } + + /** + * Exports a value into a single-line string. + * + * The output of this method is similar to the output of + * SebastianBergmann\Exporter\Exporter::export(). + * + * Newlines are replaced by the visible string '\n'. + * Contents of arrays and objects (if any) are replaced by '...'. + * + * @return string + * + * @see SebastianBergmann\Exporter\Exporter::export + */ + public function shortenedExport($value) + { + if (is_string($value)) { + $string = str_replace("\n", '', $this->export($value)); + + if (function_exists('mb_strlen')) { + if (mb_strlen($string) > 40) { + $string = mb_substr($string, 0, 30) . '...' . mb_substr($string, -7); + } + } else { + if (strlen($string) > 40) { + $string = substr($string, 0, 30) . '...' . substr($string, -7); + } + } + + return $string; + } + + if (is_object($value)) { + return sprintf( + '%s Object (%s)', + get_class($value), + count($this->toArray($value)) > 0 ? '...' : '' + ); + } + + if (is_array($value)) { + return sprintf( + 'Array (%s)', + count($value) > 0 ? '...' : '' + ); + } + + return $this->export($value); + } + + /** + * Converts an object to an array containing all of its private, protected + * and public properties. + * + * @return array + */ + public function toArray($value) + { + if (!is_object($value)) { + return (array) $value; + } + + $array = []; + + foreach ((array) $value as $key => $val) { + // Exception traces commonly reference hundreds to thousands of + // objects currently loaded in memory. Including them in the result + // has a severe negative performance impact. + if ("\0Error\0trace" === $key || "\0Exception\0trace" === $key) { + continue; + } + + // properties are transformed to keys in the following way: + // private $property => "\0Classname\0property" + // protected $property => "\0*\0property" + // public $property => "property" + if (preg_match('/^\0.+\0(.+)$/', (string) $key, $matches)) { + $key = $matches[1]; + } + + // See https://github.com/php/php-src/commit/5721132 + if ($key === "\0gcdata") { + continue; + } + + $array[$key] = $val; + } + + // Some internal classes like SplObjectStorage don't work with the + // above (fast) mechanism nor with reflection in Zend. + // Format the output similarly to print_r() in this case + if ($value instanceof SplObjectStorage) { + foreach ($value as $key => $val) { + $array[spl_object_hash($val)] = [ + 'obj' => $val, + 'inf' => $value->getInfo(), + ]; + } + } + + return $array; + } + + /** + * Recursive implementation of export. + * + * @param mixed $value The value to export + * @param int $indentation The indentation level of the 2nd+ line + * @param \SebastianBergmann\RecursionContext\Context $processed Previously processed objects + * + * @return string + * + * @see SebastianBergmann\Exporter\Exporter::export + */ + protected function recursiveExport(&$value, $indentation, $processed = null) + { + if ($value === null) { + return 'null'; + } + + if ($value === true) { + return 'true'; + } + + if ($value === false) { + return 'false'; + } + + if (is_float($value)) { + $precisionBackup = ini_get('precision'); + + ini_set('precision', '-1'); + + try { + $valueStr = (string) $value; + + if ((string) (int) $value === $valueStr) { + return $valueStr . '.0'; + } + + return $valueStr; + } finally { + ini_set('precision', $precisionBackup); + } + } + + if (gettype($value) === 'resource (closed)') { + return 'resource (closed)'; + } + + if (is_resource($value)) { + return sprintf( + 'resource(%d) of type (%s)', + $value, + get_resource_type($value) + ); + } + + if (is_string($value)) { + // Match for most non printable chars somewhat taking multibyte chars into account + if (preg_match('/[^\x09-\x0d\x1b\x20-\xff]/', $value)) { + return 'Binary String: 0x' . bin2hex($value); + } + + return "'" . + str_replace( + '', + "\n", + str_replace( + ["\r\n", "\n\r", "\r", "\n"], + ['\r\n', '\n\r', '\r', '\n'], + $value + ) + ) . + "'"; + } + + $whitespace = str_repeat(' ', 4 * $indentation); + + if (!$processed) { + $processed = new Context; + } + + if (is_array($value)) { + if (($key = $processed->contains($value)) !== false) { + return 'Array &' . $key; + } + + $array = $value; + $key = $processed->add($value); + $values = ''; + + if (count($array) > 0) { + foreach ($array as $k => $v) { + $values .= sprintf( + '%s %s => %s' . "\n", + $whitespace, + $this->recursiveExport($k, $indentation), + $this->recursiveExport($value[$k], $indentation + 1, $processed) + ); + } + + $values = "\n" . $values . $whitespace; + } + + return sprintf('Array &%s (%s)', $key, $values); + } + + if (is_object($value)) { + $class = get_class($value); + + if ($hash = $processed->contains($value)) { + return sprintf('%s Object &%s', $class, $hash); + } + + $hash = $processed->add($value); + $values = ''; + $array = $this->toArray($value); + + if (count($array) > 0) { + foreach ($array as $k => $v) { + $values .= sprintf( + '%s %s => %s' . "\n", + $whitespace, + $this->recursiveExport($k, $indentation), + $this->recursiveExport($v, $indentation + 1, $processed) + ); + } + + $values = "\n" . $values . $whitespace; + } + + return sprintf('%s Object &%s (%s)', $class, $hash, $values); + } + + return var_export($value, true); + } +} diff --git a/vendor/sebastian/global-state/ChangeLog.md b/vendor/sebastian/global-state/ChangeLog.md new file mode 100644 index 00000000..a27a5cf1 --- /dev/null +++ b/vendor/sebastian/global-state/ChangeLog.md @@ -0,0 +1,79 @@ +# Changes in sebastian/global-state + +All notable changes in `sebastian/global-state` are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [5.0.5] - 2022-02-14 + +### Fixed + +* [#34](https://github.com/sebastianbergmann/global-state/pull/34): Uninitialised typed static properties are not handled correctly + +## [5.0.4] - 2022-02-10 + +### Fixed + +* The `$includeTraits` parameter of `SebastianBergmann\GlobalState\Snapshot::__construct()` is not respected + +## [5.0.3] - 2021-06-11 + +### Changed + +* `SebastianBergmann\GlobalState\CodeExporter::globalVariables()` now generates code that is compatible with PHP 8.1 + +## [5.0.2] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\GlobalState\Exception` now correctly extends `\Throwable` + +## [5.0.1] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [5.0.0] - 2020-08-07 + +### Changed + +* The `SebastianBergmann\GlobalState\Blacklist` class has been renamed to `SebastianBergmann\GlobalState\ExcludeList` + +## [4.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.2 + +## [3.0.2] - 2022-02-10 + +### Fixed + +* The `$includeTraits` parameter of `SebastianBergmann\GlobalState\Snapshot::__construct()` is not respected + +## [3.0.1] - 2020-11-30 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.2` to `>=7.2` + +## [3.0.0] - 2019-02-01 + +### Changed + +* `Snapshot::canBeSerialized()` now recursively checks arrays and object graphs for variables that cannot be serialized + +### Removed + +* This component is no longer supported on PHP 7.0 and PHP 7.1 + +[5.0.5]: https://github.com/sebastianbergmann/global-state/compare/5.0.4...5.0.5 +[5.0.4]: https://github.com/sebastianbergmann/global-state/compare/5.0.3...5.0.4 +[5.0.3]: https://github.com/sebastianbergmann/global-state/compare/5.0.2...5.0.3 +[5.0.2]: https://github.com/sebastianbergmann/global-state/compare/5.0.1...5.0.2 +[5.0.1]: https://github.com/sebastianbergmann/global-state/compare/5.0.0...5.0.1 +[5.0.0]: https://github.com/sebastianbergmann/global-state/compare/4.0.0...5.0.0 +[4.0.0]: https://github.com/sebastianbergmann/global-state/compare/3.0.2...4.0.0 +[3.0.2]: https://github.com/sebastianbergmann/phpunit/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/phpunit/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/phpunit/compare/2.0.0...3.0.0 + diff --git a/vendor/sebastian/global-state/LICENSE b/vendor/sebastian/global-state/LICENSE new file mode 100644 index 00000000..240190bd --- /dev/null +++ b/vendor/sebastian/global-state/LICENSE @@ -0,0 +1,33 @@ +sebastian/global-state + +Copyright (c) 2001-2022, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/global-state/README.md b/vendor/sebastian/global-state/README.md new file mode 100644 index 00000000..af15bedd --- /dev/null +++ b/vendor/sebastian/global-state/README.md @@ -0,0 +1,20 @@ +# sebastian/global-state + +[![CI Status](https://github.com/sebastianbergmann/global-state/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/global-state/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/global-state/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/global-state) + +Snapshotting of global state, factored out of PHPUnit into a stand-alone component. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/global-state +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/global-state +``` diff --git a/vendor/sebastian/global-state/composer.json b/vendor/sebastian/global-state/composer.json new file mode 100644 index 00000000..0fef446a --- /dev/null +++ b/vendor/sebastian/global-state/composer.json @@ -0,0 +1,51 @@ +{ + "name": "sebastian/global-state", + "description": "Snapshotting of global state", + "keywords": ["global state"], + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "prefer-stable": true, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture/" + ], + "files": [ + "tests/_fixture/SnapshotFunctions.php" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/sebastian/global-state/src/CodeExporter.php b/vendor/sebastian/global-state/src/CodeExporter.php new file mode 100644 index 00000000..71cdbf50 --- /dev/null +++ b/vendor/sebastian/global-state/src/CodeExporter.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\GlobalState; + +use const PHP_EOL; +use function is_array; +use function is_scalar; +use function serialize; +use function sprintf; +use function var_export; + +/** + * Exports parts of a Snapshot as PHP code. + */ +final class CodeExporter +{ + public function constants(Snapshot $snapshot): string + { + $result = ''; + + foreach ($snapshot->constants() as $name => $value) { + $result .= sprintf( + 'if (!defined(\'%s\')) define(\'%s\', %s);' . "\n", + $name, + $name, + $this->exportVariable($value) + ); + } + + return $result; + } + + public function globalVariables(Snapshot $snapshot): string + { + $result = <<<'EOT' +call_user_func( + function () + { + foreach (array_keys($GLOBALS) as $key) { + unset($GLOBALS[$key]); + } + } +); + + +EOT; + + foreach ($snapshot->globalVariables() as $name => $value) { + $result .= sprintf( + '$GLOBALS[%s] = %s;' . PHP_EOL, + $this->exportVariable($name), + $this->exportVariable($value) + ); + } + + return $result; + } + + public function iniSettings(Snapshot $snapshot): string + { + $result = ''; + + foreach ($snapshot->iniSettings() as $key => $value) { + $result .= sprintf( + '@ini_set(%s, %s);' . "\n", + $this->exportVariable($key), + $this->exportVariable($value) + ); + } + + return $result; + } + + private function exportVariable($variable): string + { + if (is_scalar($variable) || null === $variable || + (is_array($variable) && $this->arrayOnlyContainsScalars($variable))) { + return var_export($variable, true); + } + + return 'unserialize(' . var_export(serialize($variable), true) . ')'; + } + + private function arrayOnlyContainsScalars(array $array): bool + { + $result = true; + + foreach ($array as $element) { + if (is_array($element)) { + $result = $this->arrayOnlyContainsScalars($element); + } elseif (!is_scalar($element) && null !== $element) { + $result = false; + } + + if ($result === false) { + break; + } + } + + return $result; + } +} diff --git a/vendor/sebastian/global-state/src/ExcludeList.php b/vendor/sebastian/global-state/src/ExcludeList.php new file mode 100644 index 00000000..5631f118 --- /dev/null +++ b/vendor/sebastian/global-state/src/ExcludeList.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\GlobalState; + +use function in_array; +use function strpos; +use ReflectionClass; + +final class ExcludeList +{ + /** + * @var array + */ + private $globalVariables = []; + + /** + * @var string[] + */ + private $classes = []; + + /** + * @var string[] + */ + private $classNamePrefixes = []; + + /** + * @var string[] + */ + private $parentClasses = []; + + /** + * @var string[] + */ + private $interfaces = []; + + /** + * @var array + */ + private $staticAttributes = []; + + public function addGlobalVariable(string $variableName): void + { + $this->globalVariables[$variableName] = true; + } + + public function addClass(string $className): void + { + $this->classes[] = $className; + } + + public function addSubclassesOf(string $className): void + { + $this->parentClasses[] = $className; + } + + public function addImplementorsOf(string $interfaceName): void + { + $this->interfaces[] = $interfaceName; + } + + public function addClassNamePrefix(string $classNamePrefix): void + { + $this->classNamePrefixes[] = $classNamePrefix; + } + + public function addStaticAttribute(string $className, string $attributeName): void + { + if (!isset($this->staticAttributes[$className])) { + $this->staticAttributes[$className] = []; + } + + $this->staticAttributes[$className][$attributeName] = true; + } + + public function isGlobalVariableExcluded(string $variableName): bool + { + return isset($this->globalVariables[$variableName]); + } + + public function isStaticAttributeExcluded(string $className, string $attributeName): bool + { + if (in_array($className, $this->classes, true)) { + return true; + } + + foreach ($this->classNamePrefixes as $prefix) { + if (strpos($className, $prefix) === 0) { + return true; + } + } + + $class = new ReflectionClass($className); + + foreach ($this->parentClasses as $type) { + if ($class->isSubclassOf($type)) { + return true; + } + } + + foreach ($this->interfaces as $type) { + if ($class->implementsInterface($type)) { + return true; + } + } + + if (isset($this->staticAttributes[$className][$attributeName])) { + return true; + } + + return false; + } +} diff --git a/vendor/sebastian/global-state/src/Restorer.php b/vendor/sebastian/global-state/src/Restorer.php new file mode 100644 index 00000000..1633fcc1 --- /dev/null +++ b/vendor/sebastian/global-state/src/Restorer.php @@ -0,0 +1,143 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\GlobalState; + +use function array_diff; +use function array_key_exists; +use function array_keys; +use function array_merge; +use function function_exists; +use function get_defined_functions; +use function in_array; +use function is_array; +use ReflectionClass; +use ReflectionProperty; + +/** + * Restorer of snapshots of global state. + */ +class Restorer +{ + /** + * Deletes function definitions that are not defined in a snapshot. + * + * @throws RuntimeException when the uopz_delete() function is not available + * + * @see https://github.com/krakjoe/uopz + */ + public function restoreFunctions(Snapshot $snapshot): void + { + if (!function_exists('uopz_delete')) { + throw new RuntimeException('The uopz_delete() function is required for this operation'); + } + + $functions = get_defined_functions(); + + foreach (array_diff($functions['user'], $snapshot->functions()) as $function) { + uopz_delete($function); + } + } + + /** + * Restores all global and super-global variables from a snapshot. + */ + public function restoreGlobalVariables(Snapshot $snapshot): void + { + $superGlobalArrays = $snapshot->superGlobalArrays(); + + foreach ($superGlobalArrays as $superGlobalArray) { + $this->restoreSuperGlobalArray($snapshot, $superGlobalArray); + } + + $globalVariables = $snapshot->globalVariables(); + + foreach (array_keys($GLOBALS) as $key) { + if ($key !== 'GLOBALS' && + !in_array($key, $superGlobalArrays, true) && + !$snapshot->excludeList()->isGlobalVariableExcluded($key)) { + if (array_key_exists($key, $globalVariables)) { + $GLOBALS[$key] = $globalVariables[$key]; + } else { + unset($GLOBALS[$key]); + } + } + } + } + + /** + * Restores all static attributes in user-defined classes from this snapshot. + */ + public function restoreStaticAttributes(Snapshot $snapshot): void + { + $current = new Snapshot($snapshot->excludeList(), false, false, false, false, true, false, false, false, false); + $newClasses = array_diff($current->classes(), $snapshot->classes()); + + unset($current); + + foreach ($snapshot->staticAttributes() as $className => $staticAttributes) { + foreach ($staticAttributes as $name => $value) { + $reflector = new ReflectionProperty($className, $name); + $reflector->setAccessible(true); + $reflector->setValue($value); + } + } + + foreach ($newClasses as $className) { + $class = new ReflectionClass($className); + $defaults = $class->getDefaultProperties(); + + foreach ($class->getProperties() as $attribute) { + if (!$attribute->isStatic()) { + continue; + } + + $name = $attribute->getName(); + + if ($snapshot->excludeList()->isStaticAttributeExcluded($className, $name)) { + continue; + } + + if (!isset($defaults[$name])) { + continue; + } + + $attribute->setAccessible(true); + $attribute->setValue($defaults[$name]); + } + } + } + + /** + * Restores a super-global variable array from this snapshot. + */ + private function restoreSuperGlobalArray(Snapshot $snapshot, string $superGlobalArray): void + { + $superGlobalVariables = $snapshot->superGlobalVariables(); + + if (isset($GLOBALS[$superGlobalArray]) && + is_array($GLOBALS[$superGlobalArray]) && + isset($superGlobalVariables[$superGlobalArray])) { + $keys = array_keys( + array_merge( + $GLOBALS[$superGlobalArray], + $superGlobalVariables[$superGlobalArray] + ) + ); + + foreach ($keys as $key) { + if (isset($superGlobalVariables[$superGlobalArray][$key])) { + $GLOBALS[$superGlobalArray][$key] = $superGlobalVariables[$superGlobalArray][$key]; + } else { + unset($GLOBALS[$superGlobalArray][$key]); + } + } + } + } +} diff --git a/vendor/sebastian/global-state/src/Snapshot.php b/vendor/sebastian/global-state/src/Snapshot.php new file mode 100644 index 00000000..e33264eb --- /dev/null +++ b/vendor/sebastian/global-state/src/Snapshot.php @@ -0,0 +1,443 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\GlobalState; + +use const PHP_VERSION_ID; +use function array_keys; +use function array_merge; +use function array_reverse; +use function func_get_args; +use function get_declared_classes; +use function get_declared_interfaces; +use function get_declared_traits; +use function get_defined_constants; +use function get_defined_functions; +use function get_included_files; +use function in_array; +use function ini_get_all; +use function is_array; +use function is_object; +use function is_resource; +use function is_scalar; +use function serialize; +use function unserialize; +use ReflectionClass; +use SebastianBergmann\ObjectReflector\ObjectReflector; +use SebastianBergmann\RecursionContext\Context; +use Throwable; + +/** + * A snapshot of global state. + */ +class Snapshot +{ + /** + * @var ExcludeList + */ + private $excludeList; + + /** + * @var array + */ + private $globalVariables = []; + + /** + * @var array + */ + private $superGlobalArrays = []; + + /** + * @var array + */ + private $superGlobalVariables = []; + + /** + * @var array + */ + private $staticAttributes = []; + + /** + * @var array + */ + private $iniSettings = []; + + /** + * @var array + */ + private $includedFiles = []; + + /** + * @var array + */ + private $constants = []; + + /** + * @var array + */ + private $functions = []; + + /** + * @var array + */ + private $interfaces = []; + + /** + * @var array + */ + private $classes = []; + + /** + * @var array + */ + private $traits = []; + + /** + * Creates a snapshot of the current global state. + */ + public function __construct(ExcludeList $excludeList = null, bool $includeGlobalVariables = true, bool $includeStaticAttributes = true, bool $includeConstants = true, bool $includeFunctions = true, bool $includeClasses = true, bool $includeInterfaces = true, bool $includeTraits = true, bool $includeIniSettings = true, bool $includeIncludedFiles = true) + { + $this->excludeList = $excludeList ?: new ExcludeList; + + if ($includeConstants) { + $this->snapshotConstants(); + } + + if ($includeFunctions) { + $this->snapshotFunctions(); + } + + if ($includeClasses || $includeStaticAttributes) { + $this->snapshotClasses(); + } + + if ($includeInterfaces) { + $this->snapshotInterfaces(); + } + + if ($includeGlobalVariables) { + $this->setupSuperGlobalArrays(); + $this->snapshotGlobals(); + } + + if ($includeStaticAttributes) { + $this->snapshotStaticAttributes(); + } + + if ($includeIniSettings) { + $this->iniSettings = ini_get_all(null, false); + } + + if ($includeIncludedFiles) { + $this->includedFiles = get_included_files(); + } + + if ($includeTraits) { + $this->traits = get_declared_traits(); + } + } + + public function excludeList(): ExcludeList + { + return $this->excludeList; + } + + public function globalVariables(): array + { + return $this->globalVariables; + } + + public function superGlobalVariables(): array + { + return $this->superGlobalVariables; + } + + public function superGlobalArrays(): array + { + return $this->superGlobalArrays; + } + + public function staticAttributes(): array + { + return $this->staticAttributes; + } + + public function iniSettings(): array + { + return $this->iniSettings; + } + + public function includedFiles(): array + { + return $this->includedFiles; + } + + public function constants(): array + { + return $this->constants; + } + + public function functions(): array + { + return $this->functions; + } + + public function interfaces(): array + { + return $this->interfaces; + } + + public function classes(): array + { + return $this->classes; + } + + public function traits(): array + { + return $this->traits; + } + + /** + * Creates a snapshot user-defined constants. + */ + private function snapshotConstants(): void + { + $constants = get_defined_constants(true); + + if (isset($constants['user'])) { + $this->constants = $constants['user']; + } + } + + /** + * Creates a snapshot user-defined functions. + */ + private function snapshotFunctions(): void + { + $functions = get_defined_functions(); + + $this->functions = $functions['user']; + } + + /** + * Creates a snapshot user-defined classes. + */ + private function snapshotClasses(): void + { + foreach (array_reverse(get_declared_classes()) as $className) { + $class = new ReflectionClass($className); + + if (!$class->isUserDefined()) { + break; + } + + $this->classes[] = $className; + } + + $this->classes = array_reverse($this->classes); + } + + /** + * Creates a snapshot user-defined interfaces. + */ + private function snapshotInterfaces(): void + { + foreach (array_reverse(get_declared_interfaces()) as $interfaceName) { + $class = new ReflectionClass($interfaceName); + + if (!$class->isUserDefined()) { + break; + } + + $this->interfaces[] = $interfaceName; + } + + $this->interfaces = array_reverse($this->interfaces); + } + + /** + * Creates a snapshot of all global and super-global variables. + */ + private function snapshotGlobals(): void + { + $superGlobalArrays = $this->superGlobalArrays(); + + foreach ($superGlobalArrays as $superGlobalArray) { + $this->snapshotSuperGlobalArray($superGlobalArray); + } + + foreach (array_keys($GLOBALS) as $key) { + if ($key !== 'GLOBALS' && + !in_array($key, $superGlobalArrays, true) && + $this->canBeSerialized($GLOBALS[$key]) && + !$this->excludeList->isGlobalVariableExcluded($key)) { + /* @noinspection UnserializeExploitsInspection */ + $this->globalVariables[$key] = unserialize(serialize($GLOBALS[$key])); + } + } + } + + /** + * Creates a snapshot a super-global variable array. + */ + private function snapshotSuperGlobalArray(string $superGlobalArray): void + { + $this->superGlobalVariables[$superGlobalArray] = []; + + if (isset($GLOBALS[$superGlobalArray]) && is_array($GLOBALS[$superGlobalArray])) { + foreach ($GLOBALS[$superGlobalArray] as $key => $value) { + /* @noinspection UnserializeExploitsInspection */ + $this->superGlobalVariables[$superGlobalArray][$key] = unserialize(serialize($value)); + } + } + } + + /** + * Creates a snapshot of all static attributes in user-defined classes. + */ + private function snapshotStaticAttributes(): void + { + foreach ($this->classes as $className) { + $class = new ReflectionClass($className); + $snapshot = []; + + foreach ($class->getProperties() as $attribute) { + if ($attribute->isStatic()) { + $name = $attribute->getName(); + + if ($this->excludeList->isStaticAttributeExcluded($className, $name)) { + continue; + } + + $attribute->setAccessible(true); + + if (PHP_VERSION_ID >= 70400 && !$attribute->isInitialized()) { + continue; + } + + $value = $attribute->getValue(); + + if ($this->canBeSerialized($value)) { + /* @noinspection UnserializeExploitsInspection */ + $snapshot[$name] = unserialize(serialize($value)); + } + } + } + + if (!empty($snapshot)) { + $this->staticAttributes[$className] = $snapshot; + } + } + } + + /** + * Returns a list of all super-global variable arrays. + */ + private function setupSuperGlobalArrays(): void + { + $this->superGlobalArrays = [ + '_ENV', + '_POST', + '_GET', + '_COOKIE', + '_SERVER', + '_FILES', + '_REQUEST', + ]; + } + + private function canBeSerialized($variable): bool + { + if (is_scalar($variable) || $variable === null) { + return true; + } + + if (is_resource($variable)) { + return false; + } + + foreach ($this->enumerateObjectsAndResources($variable) as $value) { + if (is_resource($value)) { + return false; + } + + if (is_object($value)) { + $class = new ReflectionClass($value); + + if ($class->isAnonymous()) { + return false; + } + + try { + @serialize($value); + } catch (Throwable $t) { + return false; + } + } + } + + return true; + } + + private function enumerateObjectsAndResources($variable): array + { + if (isset(func_get_args()[1])) { + $processed = func_get_args()[1]; + } else { + $processed = new Context; + } + + $result = []; + + if ($processed->contains($variable)) { + return $result; + } + + $array = $variable; + $processed->add($variable); + + if (is_array($variable)) { + foreach ($array as $element) { + if (!is_array($element) && !is_object($element) && !is_resource($element)) { + continue; + } + + if (!is_resource($element)) { + /** @noinspection SlowArrayOperationsInLoopInspection */ + $result = array_merge( + $result, + $this->enumerateObjectsAndResources($element, $processed) + ); + } else { + $result[] = $element; + } + } + } else { + $result[] = $variable; + + foreach ((new ObjectReflector)->getAttributes($variable) as $value) { + if (!is_array($value) && !is_object($value) && !is_resource($value)) { + continue; + } + + if (!is_resource($value)) { + /** @noinspection SlowArrayOperationsInLoopInspection */ + $result = array_merge( + $result, + $this->enumerateObjectsAndResources($value, $processed) + ); + } else { + $result[] = $value; + } + } + } + + return $result; + } +} diff --git a/vendor/sebastian/global-state/src/exceptions/Exception.php b/vendor/sebastian/global-state/src/exceptions/Exception.php new file mode 100644 index 00000000..94432008 --- /dev/null +++ b/vendor/sebastian/global-state/src/exceptions/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\GlobalState; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/sebastian/global-state/src/exceptions/RuntimeException.php b/vendor/sebastian/global-state/src/exceptions/RuntimeException.php new file mode 100644 index 00000000..79f02a11 --- /dev/null +++ b/vendor/sebastian/global-state/src/exceptions/RuntimeException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\GlobalState; + +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/vendor/sebastian/lines-of-code/.psalm/baseline.xml b/vendor/sebastian/lines-of-code/.psalm/baseline.xml new file mode 100644 index 00000000..77e688e0 --- /dev/null +++ b/vendor/sebastian/lines-of-code/.psalm/baseline.xml @@ -0,0 +1,2 @@ + + diff --git a/vendor/sebastian/lines-of-code/.psalm/config.xml b/vendor/sebastian/lines-of-code/.psalm/config.xml new file mode 100644 index 00000000..15abef05 --- /dev/null +++ b/vendor/sebastian/lines-of-code/.psalm/config.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/vendor/sebastian/lines-of-code/ChangeLog.md b/vendor/sebastian/lines-of-code/ChangeLog.md new file mode 100644 index 00000000..39bcaad4 --- /dev/null +++ b/vendor/sebastian/lines-of-code/ChangeLog.md @@ -0,0 +1,34 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [1.0.3] - 2020-11-28 + +### Fixed + +* Files that do not contain a newline were not handled correctly + +### Changed + +* A line of code is no longer considered to be a Logical Line of Code if it does not contain an `Expr` node + +## [1.0.2] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\LinesOfCode\Exception` now correctly extends `\Throwable` + +## [1.0.1] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [1.0.0] - 2020-07-22 + +* Initial release + +[1.0.3]: https://github.com/sebastianbergmann/lines-of-code/compare/1.0.2...1.0.3 +[1.0.2]: https://github.com/sebastianbergmann/lines-of-code/compare/1.0.1...1.0.2 +[1.0.1]: https://github.com/sebastianbergmann/lines-of-code/compare/1.0.0...1.0.1 +[1.0.0]: https://github.com/sebastianbergmann/lines-of-code/compare/f959e71f00e591288acc024afe9cb966c6cf9bd6...1.0.0 diff --git a/vendor/sebastian/lines-of-code/LICENSE b/vendor/sebastian/lines-of-code/LICENSE new file mode 100644 index 00000000..d170181f --- /dev/null +++ b/vendor/sebastian/lines-of-code/LICENSE @@ -0,0 +1,33 @@ +sebastian/lines-of-code + +Copyright (c) 2020, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/lines-of-code/README.md b/vendor/sebastian/lines-of-code/README.md new file mode 100644 index 00000000..9457ef5a --- /dev/null +++ b/vendor/sebastian/lines-of-code/README.md @@ -0,0 +1,22 @@ +# sebastian/lines-of-code + +Library for counting the lines of code in PHP source code. + +[![Latest Stable Version](https://img.shields.io/packagist/v/sebastian/lines-of-code.svg?style=flat-square)](https://packagist.org/packages/sebastian/lines-of-code) +[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.3-8892BF.svg?style=flat-square)](https://php.net/) +[![CI Status](https://github.com/sebastianbergmann/lines-of-code/workflows/CI/badge.svg?branch=master&event=push)](https://phpunit.de/build-status.html) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/lines-of-code/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/lines-of-code) + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/lines-of-code +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/lines-of-code +``` diff --git a/vendor/sebastian/lines-of-code/composer.json b/vendor/sebastian/lines-of-code/composer.json new file mode 100644 index 00000000..95bb9e36 --- /dev/null +++ b/vendor/sebastian/lines-of-code/composer.json @@ -0,0 +1,42 @@ +{ + "name": "sebastian/lines-of-code", + "description": "Library for counting the lines of code in PHP source code", + "type": "library", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues" + }, + "prefer-stable": true, + "require": { + "php": ">=7.3", + "nikic/php-parser": "^4.6" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + } +} diff --git a/vendor/sebastian/lines-of-code/src/Counter.php b/vendor/sebastian/lines-of-code/src/Counter.php new file mode 100644 index 00000000..cfe5e20a --- /dev/null +++ b/vendor/sebastian/lines-of-code/src/Counter.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\LinesOfCode; + +use function substr_count; +use PhpParser\Error; +use PhpParser\Lexer; +use PhpParser\Node; +use PhpParser\NodeTraverser; +use PhpParser\Parser; +use PhpParser\ParserFactory; + +final class Counter +{ + /** + * @throws RuntimeException + */ + public function countInSourceFile(string $sourceFile): LinesOfCode + { + return $this->countInSourceString(file_get_contents($sourceFile)); + } + + /** + * @throws RuntimeException + */ + public function countInSourceString(string $source): LinesOfCode + { + $linesOfCode = substr_count($source, "\n"); + + if ($linesOfCode === 0 && !empty($source)) { + $linesOfCode = 1; + } + + try { + $nodes = $this->parser()->parse($source); + + assert($nodes !== null); + + return $this->countInAbstractSyntaxTree($linesOfCode, $nodes); + + // @codeCoverageIgnoreStart + } catch (Error $error) { + throw new RuntimeException( + $error->getMessage(), + (int) $error->getCode(), + $error + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @param Node[] $nodes + * + * @throws RuntimeException + */ + public function countInAbstractSyntaxTree(int $linesOfCode, array $nodes): LinesOfCode + { + $traverser = new NodeTraverser; + $visitor = new LineCountingVisitor($linesOfCode); + + $traverser->addVisitor($visitor); + + try { + /* @noinspection UnusedFunctionResultInspection */ + $traverser->traverse($nodes); + // @codeCoverageIgnoreStart + } catch (Error $error) { + throw new RuntimeException( + $error->getMessage(), + (int) $error->getCode(), + $error + ); + } + // @codeCoverageIgnoreEnd + + return $visitor->result(); + } + + private function parser(): Parser + { + return (new ParserFactory)->create(ParserFactory::PREFER_PHP7, new Lexer); + } +} diff --git a/vendor/sebastian/lines-of-code/src/Exception/Exception.php b/vendor/sebastian/lines-of-code/src/Exception/Exception.php new file mode 100644 index 00000000..11d543aa --- /dev/null +++ b/vendor/sebastian/lines-of-code/src/Exception/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\LinesOfCode; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php b/vendor/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php new file mode 100644 index 00000000..46a5c1b1 --- /dev/null +++ b/vendor/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\LinesOfCode; + +use LogicException; + +final class IllogicalValuesException extends LogicException implements Exception +{ +} diff --git a/vendor/sebastian/lines-of-code/src/Exception/NegativeValueException.php b/vendor/sebastian/lines-of-code/src/Exception/NegativeValueException.php new file mode 100644 index 00000000..40d27e1f --- /dev/null +++ b/vendor/sebastian/lines-of-code/src/Exception/NegativeValueException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\LinesOfCode; + +use InvalidArgumentException; + +final class NegativeValueException extends InvalidArgumentException implements Exception +{ +} diff --git a/vendor/sebastian/lines-of-code/src/Exception/RuntimeException.php b/vendor/sebastian/lines-of-code/src/Exception/RuntimeException.php new file mode 100644 index 00000000..4e6d66d0 --- /dev/null +++ b/vendor/sebastian/lines-of-code/src/Exception/RuntimeException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\LinesOfCode; + +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/vendor/sebastian/lines-of-code/src/LineCountingVisitor.php b/vendor/sebastian/lines-of-code/src/LineCountingVisitor.php new file mode 100644 index 00000000..ff433b2f --- /dev/null +++ b/vendor/sebastian/lines-of-code/src/LineCountingVisitor.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\LinesOfCode; + +use function array_merge; +use function array_unique; +use function count; +use PhpParser\Comment; +use PhpParser\Node; +use PhpParser\Node\Expr; +use PhpParser\NodeVisitorAbstract; + +final class LineCountingVisitor extends NodeVisitorAbstract +{ + /** + * @var int + */ + private $linesOfCode; + + /** + * @var Comment[] + */ + private $comments = []; + + /** + * @var int[] + */ + private $linesWithStatements = []; + + public function __construct(int $linesOfCode) + { + $this->linesOfCode = $linesOfCode; + } + + public function enterNode(Node $node): void + { + $this->comments = array_merge($this->comments, $node->getComments()); + + if (!$node instanceof Expr) { + return; + } + + $this->linesWithStatements[] = $node->getStartLine(); + } + + public function result(): LinesOfCode + { + $commentLinesOfCode = 0; + + foreach ($this->comments() as $comment) { + $commentLinesOfCode += ($comment->getEndLine() - $comment->getStartLine() + 1); + } + + return new LinesOfCode( + $this->linesOfCode, + $commentLinesOfCode, + $this->linesOfCode - $commentLinesOfCode, + count(array_unique($this->linesWithStatements)) + ); + } + + /** + * @return Comment[] + */ + private function comments(): array + { + $comments = []; + + foreach ($this->comments as $comment) { + $comments[$comment->getStartLine() . '_' . $comment->getStartTokenPos() . '_' . $comment->getEndLine() . '_' . $comment->getEndTokenPos()] = $comment; + } + + return $comments; + } +} diff --git a/vendor/sebastian/lines-of-code/src/LinesOfCode.php b/vendor/sebastian/lines-of-code/src/LinesOfCode.php new file mode 100644 index 00000000..41829981 --- /dev/null +++ b/vendor/sebastian/lines-of-code/src/LinesOfCode.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\LinesOfCode; + +/** + * @psalm-immutable + */ +final class LinesOfCode +{ + /** + * @var int + */ + private $linesOfCode; + + /** + * @var int + */ + private $commentLinesOfCode; + + /** + * @var int + */ + private $nonCommentLinesOfCode; + + /** + * @var int + */ + private $logicalLinesOfCode; + + /** + * @throws IllogicalValuesException + * @throws NegativeValueException + */ + public function __construct(int $linesOfCode, int $commentLinesOfCode, int $nonCommentLinesOfCode, int $logicalLinesOfCode) + { + if ($linesOfCode < 0) { + throw new NegativeValueException('$linesOfCode must not be negative'); + } + + if ($commentLinesOfCode < 0) { + throw new NegativeValueException('$commentLinesOfCode must not be negative'); + } + + if ($nonCommentLinesOfCode < 0) { + throw new NegativeValueException('$nonCommentLinesOfCode must not be negative'); + } + + if ($logicalLinesOfCode < 0) { + throw new NegativeValueException('$logicalLinesOfCode must not be negative'); + } + + if ($linesOfCode - $commentLinesOfCode !== $nonCommentLinesOfCode) { + throw new IllogicalValuesException('$linesOfCode !== $commentLinesOfCode + $nonCommentLinesOfCode'); + } + + $this->linesOfCode = $linesOfCode; + $this->commentLinesOfCode = $commentLinesOfCode; + $this->nonCommentLinesOfCode = $nonCommentLinesOfCode; + $this->logicalLinesOfCode = $logicalLinesOfCode; + } + + public function linesOfCode(): int + { + return $this->linesOfCode; + } + + public function commentLinesOfCode(): int + { + return $this->commentLinesOfCode; + } + + public function nonCommentLinesOfCode(): int + { + return $this->nonCommentLinesOfCode; + } + + public function logicalLinesOfCode(): int + { + return $this->logicalLinesOfCode; + } + + public function plus(self $other): self + { + return new self( + $this->linesOfCode() + $other->linesOfCode(), + $this->commentLinesOfCode() + $other->commentLinesOfCode(), + $this->nonCommentLinesOfCode() + $other->nonCommentLinesOfCode(), + $this->logicalLinesOfCode() + $other->logicalLinesOfCode(), + ); + } +} diff --git a/vendor/sebastian/object-enumerator/.psalm/baseline.xml b/vendor/sebastian/object-enumerator/.psalm/baseline.xml new file mode 100644 index 00000000..180b3f80 --- /dev/null +++ b/vendor/sebastian/object-enumerator/.psalm/baseline.xml @@ -0,0 +1,9 @@ + + + + + !is_array($variable) && !is_object($variable) + is_object($variable) + + + diff --git a/vendor/sebastian/object-enumerator/.psalm/config.xml b/vendor/sebastian/object-enumerator/.psalm/config.xml new file mode 100644 index 00000000..2a4b16f2 --- /dev/null +++ b/vendor/sebastian/object-enumerator/.psalm/config.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/vendor/sebastian/object-enumerator/ChangeLog.md b/vendor/sebastian/object-enumerator/ChangeLog.md new file mode 100644 index 00000000..88655418 --- /dev/null +++ b/vendor/sebastian/object-enumerator/ChangeLog.md @@ -0,0 +1,88 @@ +# Change Log + +All notable changes to `sebastianbergmann/object-enumerator` are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [4.0.4] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\ObjectEnumerator\Exception` now correctly extends `\Throwable` + +## [4.0.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [4.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [4.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [4.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.0, PHP 7.1, and PHP 7.2 + +## [3.0.3] - 2017-08-03 + +### Changed + +* Bumped required version of `sebastian/object-reflector` + +## [3.0.2] - 2017-03-12 + +### Changed + +* `sebastian/object-reflector` is now a dependency + +## [3.0.1] - 2017-03-12 + +### Fixed + +* Objects aggregated in inherited attributes are not enumerated + +## [3.0.0] - 2017-03-03 + +### Removed + +* This component is no longer supported on PHP 5.6 + +## [2.0.1] - 2017-02-18 + +### Fixed + +* Fixed [#2](https://github.com/sebastianbergmann/phpunit/pull/2): Exceptions in `ReflectionProperty::getValue()` are not handled + +## [2.0.0] - 2016-11-19 + +### Changed + +* This component is now compatible with `sebastian/recursion-context: ~1.0.4` + +## 1.0.0 - 2016-02-04 + +### Added + +* Initial release + +[4.0.4]: https://github.com/sebastianbergmann/object-enumerator/compare/4.0.3...4.0.4 +[4.0.3]: https://github.com/sebastianbergmann/object-enumerator/compare/4.0.2...4.0.3 +[4.0.2]: https://github.com/sebastianbergmann/object-enumerator/compare/4.0.1...4.0.2 +[4.0.1]: https://github.com/sebastianbergmann/object-enumerator/compare/4.0.0...4.0.1 +[4.0.0]: https://github.com/sebastianbergmann/object-enumerator/compare/3.0.3...4.0.0 +[3.0.3]: https://github.com/sebastianbergmann/object-enumerator/compare/3.0.2...3.0.3 +[3.0.2]: https://github.com/sebastianbergmann/object-enumerator/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/object-enumerator/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/object-enumerator/compare/2.0...3.0.0 +[2.0.1]: https://github.com/sebastianbergmann/object-enumerator/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/object-enumerator/compare/1.0...2.0.0 + diff --git a/vendor/sebastian/object-enumerator/LICENSE b/vendor/sebastian/object-enumerator/LICENSE new file mode 100644 index 00000000..1389ad39 --- /dev/null +++ b/vendor/sebastian/object-enumerator/LICENSE @@ -0,0 +1,33 @@ +Object Enumerator + +Copyright (c) 2016-2020, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/object-enumerator/README.md b/vendor/sebastian/object-enumerator/README.md new file mode 100644 index 00000000..afca0177 --- /dev/null +++ b/vendor/sebastian/object-enumerator/README.md @@ -0,0 +1,20 @@ +# sebastian/object-enumerator + +[![CI Status](https://github.com/sebastianbergmann/object-enumerator/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/object-enumerator/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/object-enumerator/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/object-enumerator) + +Traverses array structures and object graphs to enumerate all referenced objects. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/object-enumerator +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/object-enumerator +``` diff --git a/vendor/sebastian/object-enumerator/composer.json b/vendor/sebastian/object-enumerator/composer.json new file mode 100644 index 00000000..d68a2133 --- /dev/null +++ b/vendor/sebastian/object-enumerator/composer.json @@ -0,0 +1,43 @@ +{ + "name": "sebastian/object-enumerator", + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "prefer-stable": true, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + } +} diff --git a/vendor/sebastian/object-enumerator/phpunit.xml b/vendor/sebastian/object-enumerator/phpunit.xml new file mode 100644 index 00000000..7be976b1 --- /dev/null +++ b/vendor/sebastian/object-enumerator/phpunit.xml @@ -0,0 +1,24 @@ + + + + + tests + + + + + + src + + + diff --git a/vendor/sebastian/object-enumerator/src/Enumerator.php b/vendor/sebastian/object-enumerator/src/Enumerator.php new file mode 100644 index 00000000..de75d17c --- /dev/null +++ b/vendor/sebastian/object-enumerator/src/Enumerator.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\ObjectEnumerator; + +use function array_merge; +use function func_get_args; +use function is_array; +use function is_object; +use SebastianBergmann\ObjectReflector\ObjectReflector; +use SebastianBergmann\RecursionContext\Context; + +/** + * Traverses array structures and object graphs + * to enumerate all referenced objects. + */ +class Enumerator +{ + /** + * Returns an array of all objects referenced either + * directly or indirectly by a variable. + * + * @param array|object $variable + * + * @return object[] + */ + public function enumerate($variable) + { + if (!is_array($variable) && !is_object($variable)) { + throw new InvalidArgumentException; + } + + if (isset(func_get_args()[1])) { + if (!func_get_args()[1] instanceof Context) { + throw new InvalidArgumentException; + } + + $processed = func_get_args()[1]; + } else { + $processed = new Context; + } + + $objects = []; + + if ($processed->contains($variable)) { + return $objects; + } + + $array = $variable; + $processed->add($variable); + + if (is_array($variable)) { + foreach ($array as $element) { + if (!is_array($element) && !is_object($element)) { + continue; + } + + $objects = array_merge( + $objects, + $this->enumerate($element, $processed) + ); + } + } else { + $objects[] = $variable; + + $reflector = new ObjectReflector; + + foreach ($reflector->getAttributes($variable) as $value) { + if (!is_array($value) && !is_object($value)) { + continue; + } + + $objects = array_merge( + $objects, + $this->enumerate($value, $processed) + ); + } + } + + return $objects; + } +} diff --git a/vendor/sebastian/object-enumerator/src/Exception.php b/vendor/sebastian/object-enumerator/src/Exception.php new file mode 100644 index 00000000..2f09d70a --- /dev/null +++ b/vendor/sebastian/object-enumerator/src/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\ObjectEnumerator; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/sebastian/object-enumerator/src/InvalidArgumentException.php b/vendor/sebastian/object-enumerator/src/InvalidArgumentException.php new file mode 100644 index 00000000..ce2037cd --- /dev/null +++ b/vendor/sebastian/object-enumerator/src/InvalidArgumentException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\ObjectEnumerator; + +class InvalidArgumentException extends \InvalidArgumentException implements Exception +{ +} diff --git a/vendor/sebastian/object-reflector/.psalm/baseline.xml b/vendor/sebastian/object-reflector/.psalm/baseline.xml new file mode 100644 index 00000000..965c1275 --- /dev/null +++ b/vendor/sebastian/object-reflector/.psalm/baseline.xml @@ -0,0 +1,8 @@ + + + + + is_object($object) + + + diff --git a/vendor/sebastian/object-reflector/.psalm/config.xml b/vendor/sebastian/object-reflector/.psalm/config.xml new file mode 100644 index 00000000..2a4b16f2 --- /dev/null +++ b/vendor/sebastian/object-reflector/.psalm/config.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/vendor/sebastian/object-reflector/ChangeLog.md b/vendor/sebastian/object-reflector/ChangeLog.md new file mode 100644 index 00000000..7fa62e90 --- /dev/null +++ b/vendor/sebastian/object-reflector/ChangeLog.md @@ -0,0 +1,55 @@ +# Change Log + +All notable changes to `sebastianbergmann/object-reflector` are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [2.0.4] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\ObjectReflector\Exception` now correctly extends `\Throwable` + +## [2.0.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [2.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [2.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [2.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.0, PHP 7.1, and PHP 7.2 + +## [1.1.1] - 2017-03-29 + +* Fixed [#1](https://github.com/sebastianbergmann/object-reflector/issues/1): Attributes with non-string names are not handled correctly + +## [1.1.0] - 2017-03-16 + +### Changed + +* Changed implementation of `ObjectReflector::getattributes()` to use `(array)` cast instead of `ReflectionObject` + +## 1.0.0 - 2017-03-12 + +* Initial release + +[2.0.4]: https://github.com/sebastianbergmann/object-reflector/compare/2.0.3...2.0.4 +[2.0.3]: https://github.com/sebastianbergmann/object-reflector/compare/2.0.2...2.0.3 +[2.0.2]: https://github.com/sebastianbergmann/object-reflector/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/sebastianbergmann/object-reflector/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/object-reflector/compare/1.1.1...2.0.0 +[1.1.1]: https://github.com/sebastianbergmann/object-reflector/compare/1.1.0...1.1.1 +[1.1.0]: https://github.com/sebastianbergmann/object-reflector/compare/1.0.0...1.1.0 diff --git a/vendor/sebastian/object-reflector/LICENSE b/vendor/sebastian/object-reflector/LICENSE new file mode 100644 index 00000000..a80c1619 --- /dev/null +++ b/vendor/sebastian/object-reflector/LICENSE @@ -0,0 +1,33 @@ +Object Reflector + +Copyright (c) 2017-2020, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/object-reflector/README.md b/vendor/sebastian/object-reflector/README.md new file mode 100644 index 00000000..b7d5ae95 --- /dev/null +++ b/vendor/sebastian/object-reflector/README.md @@ -0,0 +1,20 @@ +# sebastian/object-reflector + +[![CI Status](https://github.com/sebastianbergmann/object-reflector/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/object-reflector/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/object-reflector/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/object-reflector) + +Allows reflection of object attributes, including inherited and non-public ones. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/object-reflector +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/object-reflector +``` diff --git a/vendor/sebastian/object-reflector/composer.json b/vendor/sebastian/object-reflector/composer.json new file mode 100644 index 00000000..36a33788 --- /dev/null +++ b/vendor/sebastian/object-reflector/composer.json @@ -0,0 +1,41 @@ +{ + "name": "sebastian/object-reflector", + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "prefer-stable": true, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + } +} diff --git a/vendor/sebastian/object-reflector/src/Exception.php b/vendor/sebastian/object-reflector/src/Exception.php new file mode 100644 index 00000000..36f8efec --- /dev/null +++ b/vendor/sebastian/object-reflector/src/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\ObjectReflector; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/sebastian/object-reflector/src/InvalidArgumentException.php b/vendor/sebastian/object-reflector/src/InvalidArgumentException.php new file mode 100644 index 00000000..34b4cca1 --- /dev/null +++ b/vendor/sebastian/object-reflector/src/InvalidArgumentException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\ObjectReflector; + +class InvalidArgumentException extends \InvalidArgumentException implements Exception +{ +} diff --git a/vendor/sebastian/object-reflector/src/ObjectReflector.php b/vendor/sebastian/object-reflector/src/ObjectReflector.php new file mode 100644 index 00000000..4abb5f55 --- /dev/null +++ b/vendor/sebastian/object-reflector/src/ObjectReflector.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\ObjectReflector; + +use function count; +use function explode; +use function get_class; +use function is_object; + +class ObjectReflector +{ + /** + * @param object $object + * + * @throws InvalidArgumentException + */ + public function getAttributes($object): array + { + if (!is_object($object)) { + throw new InvalidArgumentException; + } + + $attributes = []; + $className = get_class($object); + + foreach ((array) $object as $name => $value) { + $name = explode("\0", (string) $name); + + if (count($name) === 1) { + $name = $name[0]; + } else { + if ($name[1] !== $className) { + $name = $name[1] . '::' . $name[2]; + } else { + $name = $name[2]; + } + } + + $attributes[$name] = $value; + } + + return $attributes; + } +} diff --git a/vendor/sebastian/recursion-context/ChangeLog.md b/vendor/sebastian/recursion-context/ChangeLog.md new file mode 100644 index 00000000..c1a76516 --- /dev/null +++ b/vendor/sebastian/recursion-context/ChangeLog.md @@ -0,0 +1,40 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [4.0.5] - 2023-02-03 + +### Fixed + +* [#26](https://github.com/sebastianbergmann/recursion-context/pull/26): Don't clobber `null` values if `array_key_exists(PHP_INT_MAX, $array)` + +## [4.0.4] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\RecursionContext\Exception` now correctly extends `\Throwable` + +## [4.0.3] - 2020-09-28 + +### Changed + +* [#21](https://github.com/sebastianbergmann/recursion-context/pull/21): Add type annotations for in/out parameters +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [4.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [4.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +[4.0.5]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.4...4.0.5 +[4.0.4]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.3...4.0.4 +[4.0.3]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.2...4.0.3 +[4.0.2]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.1...4.0.2 +[4.0.1]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.0...4.0.1 diff --git a/vendor/sebastian/recursion-context/LICENSE b/vendor/sebastian/recursion-context/LICENSE new file mode 100644 index 00000000..4e9b6371 --- /dev/null +++ b/vendor/sebastian/recursion-context/LICENSE @@ -0,0 +1,33 @@ +Recursion Context + +Copyright (c) 2002-2022, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/recursion-context/README.md b/vendor/sebastian/recursion-context/README.md new file mode 100644 index 00000000..8e4d2a08 --- /dev/null +++ b/vendor/sebastian/recursion-context/README.md @@ -0,0 +1,18 @@ +# sebastian/recursion-context + +[![CI Status](https://github.com/sebastianbergmann/recursion-context/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/recursion-context/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/recursion-context/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/recursion-context) + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/recursion-context +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/recursion-context +``` diff --git a/vendor/sebastian/recursion-context/composer.json b/vendor/sebastian/recursion-context/composer.json new file mode 100644 index 00000000..cbd39f76 --- /dev/null +++ b/vendor/sebastian/recursion-context/composer.json @@ -0,0 +1,44 @@ +{ + "name": "sebastian/recursion-context", + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "prefer-stable": true, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + } +} diff --git a/vendor/sebastian/recursion-context/src/Context.php b/vendor/sebastian/recursion-context/src/Context.php new file mode 100644 index 00000000..a647938c --- /dev/null +++ b/vendor/sebastian/recursion-context/src/Context.php @@ -0,0 +1,191 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\RecursionContext; + +use const PHP_INT_MAX; +use const PHP_INT_MIN; +use function array_key_exists; +use function array_pop; +use function array_slice; +use function count; +use function is_array; +use function is_object; +use function random_int; +use function spl_object_hash; +use SplObjectStorage; + +/** + * A context containing previously processed arrays and objects + * when recursively processing a value. + */ +final class Context +{ + /** + * @var array[] + */ + private $arrays; + + /** + * @var SplObjectStorage + */ + private $objects; + + /** + * Initialises the context. + */ + public function __construct() + { + $this->arrays = []; + $this->objects = new SplObjectStorage; + } + + /** + * @codeCoverageIgnore + */ + public function __destruct() + { + foreach ($this->arrays as &$array) { + if (is_array($array)) { + array_pop($array); + array_pop($array); + } + } + } + + /** + * Adds a value to the context. + * + * @param array|object $value the value to add + * + * @throws InvalidArgumentException Thrown if $value is not an array or object + * + * @return bool|int|string the ID of the stored value, either as a string or integer + * + * @psalm-template T + * @psalm-param T $value + * @param-out T $value + */ + public function add(&$value) + { + if (is_array($value)) { + return $this->addArray($value); + } + + if (is_object($value)) { + return $this->addObject($value); + } + + throw new InvalidArgumentException( + 'Only arrays and objects are supported' + ); + } + + /** + * Checks if the given value exists within the context. + * + * @param array|object $value the value to check + * + * @throws InvalidArgumentException Thrown if $value is not an array or object + * + * @return false|int|string the string or integer ID of the stored value if it has already been seen, or false if the value is not stored + * + * @psalm-template T + * @psalm-param T $value + * @param-out T $value + */ + public function contains(&$value) + { + if (is_array($value)) { + return $this->containsArray($value); + } + + if (is_object($value)) { + return $this->containsObject($value); + } + + throw new InvalidArgumentException( + 'Only arrays and objects are supported' + ); + } + + /** + * @return bool|int + */ + private function addArray(array &$array) + { + $key = $this->containsArray($array); + + if ($key !== false) { + return $key; + } + + $key = count($this->arrays); + $this->arrays[] = &$array; + + if (!array_key_exists(PHP_INT_MAX, $array) && !array_key_exists(PHP_INT_MAX - 1, $array)) { + $array[] = $key; + $array[] = $this->objects; + } else { /* cover the improbable case too */ + /* Note that array_slice (used in containsArray) will return the + * last two values added *not necessarily* the highest integer + * keys in the array, so the order of these writes to $array + * is important, but the actual keys used is not. */ + do { + $key = random_int(PHP_INT_MIN, PHP_INT_MAX); + } while (array_key_exists($key, $array)); + + $array[$key] = $key; + + do { + $key = random_int(PHP_INT_MIN, PHP_INT_MAX); + } while (array_key_exists($key, $array)); + + $array[$key] = $this->objects; + } + + return $key; + } + + /** + * @param object $object + */ + private function addObject($object): string + { + if (!$this->objects->contains($object)) { + $this->objects->attach($object); + } + + return spl_object_hash($object); + } + + /** + * @return false|int + */ + private function containsArray(array &$array) + { + $end = array_slice($array, -2); + + return isset($end[1]) && $end[1] === $this->objects ? $end[0] : false; + } + + /** + * @param object $value + * + * @return false|string + */ + private function containsObject($value) + { + if ($this->objects->contains($value)) { + return spl_object_hash($value); + } + + return false; + } +} diff --git a/vendor/sebastian/recursion-context/src/Exception.php b/vendor/sebastian/recursion-context/src/Exception.php new file mode 100644 index 00000000..9389a271 --- /dev/null +++ b/vendor/sebastian/recursion-context/src/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\RecursionContext; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/sebastian/recursion-context/src/InvalidArgumentException.php b/vendor/sebastian/recursion-context/src/InvalidArgumentException.php new file mode 100644 index 00000000..93d150bc --- /dev/null +++ b/vendor/sebastian/recursion-context/src/InvalidArgumentException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\RecursionContext; + +final class InvalidArgumentException extends \InvalidArgumentException implements Exception +{ +} diff --git a/vendor/sebastian/resource-operations/.gitattributes b/vendor/sebastian/resource-operations/.gitattributes new file mode 100644 index 00000000..85e55ebc --- /dev/null +++ b/vendor/sebastian/resource-operations/.gitattributes @@ -0,0 +1,7 @@ +/.github export-ignore +/.php_cs.dist export-ignore +/build.xml export-ignore +/phpunit.xml export-ignore +/tests export-ignore + +*.php diff=php diff --git a/vendor/sebastian/resource-operations/.gitignore b/vendor/sebastian/resource-operations/.gitignore new file mode 100644 index 00000000..a086c781 --- /dev/null +++ b/vendor/sebastian/resource-operations/.gitignore @@ -0,0 +1,6 @@ +/.idea +/.php_cs.cache +/build/FunctionSignatureMap.php +/composer.lock +/vendor +/.phpunit.result.cache diff --git a/vendor/sebastian/resource-operations/ChangeLog.md b/vendor/sebastian/resource-operations/ChangeLog.md new file mode 100644 index 00000000..e6dc7392 --- /dev/null +++ b/vendor/sebastian/resource-operations/ChangeLog.md @@ -0,0 +1,54 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [3.0.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [3.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [3.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [3.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.1 and PHP 7.2 + +## [2.0.1] - 2018-10-04 + +### Fixed + +* Functions and methods with nullable parameters of type `resource` are now also considered + +## [2.0.0] - 2018-09-27 + +### Changed + +* [FunctionSignatureMap.php](https://raw.githubusercontent.com/phan/phan/master/src/Phan/Language/Internal/FunctionSignatureMap.php) from `phan/phan` is now used instead of [arginfo.php](https://raw.githubusercontent.com/rlerdorf/phan/master/includes/arginfo.php) from `rlerdorf/phan` + +### Removed + +* This component is no longer supported on PHP 5.6 and PHP 7.0 + +## 1.0.0 - 2015-07-28 + +* Initial release + +[3.0.3]: https://github.com/sebastianbergmann/comparator/resource-operations/3.0.2...3.0.3 +[3.0.2]: https://github.com/sebastianbergmann/comparator/resource-operations/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/comparator/resource-operations/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/comparator/resource-operations/2.0.1...3.0.0 +[2.0.1]: https://github.com/sebastianbergmann/comparator/resource-operations/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/comparator/resource-operations/1.0.0...2.0.0 diff --git a/vendor/sebastian/resource-operations/LICENSE b/vendor/sebastian/resource-operations/LICENSE new file mode 100644 index 00000000..dccd6b07 --- /dev/null +++ b/vendor/sebastian/resource-operations/LICENSE @@ -0,0 +1,33 @@ +Resource Operations + +Copyright (c) 2015-2020, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/resource-operations/README.md b/vendor/sebastian/resource-operations/README.md new file mode 100644 index 00000000..88b05ccb --- /dev/null +++ b/vendor/sebastian/resource-operations/README.md @@ -0,0 +1,14 @@ +# Resource Operations + +Provides a list of PHP built-in functions that operate on resources. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + + composer require sebastian/resource-operations + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + + composer require --dev sebastian/resource-operations + diff --git a/vendor/sebastian/resource-operations/build/generate.php b/vendor/sebastian/resource-operations/build/generate.php new file mode 100755 index 00000000..0354dc45 --- /dev/null +++ b/vendor/sebastian/resource-operations/build/generate.php @@ -0,0 +1,65 @@ +#!/usr/bin/env php + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +$functions = require __DIR__ . '/FunctionSignatureMap.php'; +$resourceFunctions = []; + +foreach ($functions as $function => $arguments) { + foreach ($arguments as $argument) { + if (strpos($argument, '?') === 0) { + $argument = substr($argument, 1); + } + + if ($argument === 'resource') { + $resourceFunctions[] = explode('\'', $function)[0]; + } + } +} + +$resourceFunctions = array_unique($resourceFunctions); +sort($resourceFunctions); + +$buffer = << + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\ResourceOperations; + +final class ResourceOperations +{ + /** + * @return string[] + */ + public static function getFunctions(): array + { + return [ + +EOT; + +foreach ($resourceFunctions as $function) { + $buffer .= sprintf(" '%s',\n", $function); +} + +$buffer .= <<< EOT + ]; + } +} + +EOT; + +file_put_contents(__DIR__ . '/../src/ResourceOperations.php', $buffer); + diff --git a/vendor/sebastian/resource-operations/composer.json b/vendor/sebastian/resource-operations/composer.json new file mode 100644 index 00000000..870be3c1 --- /dev/null +++ b/vendor/sebastian/resource-operations/composer.json @@ -0,0 +1,37 @@ +{ + "name": "sebastian/resource-operations", + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "prefer-stable": true, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + } +} + diff --git a/vendor/sebastian/resource-operations/src/ResourceOperations.php b/vendor/sebastian/resource-operations/src/ResourceOperations.php new file mode 100644 index 00000000..f3911f36 --- /dev/null +++ b/vendor/sebastian/resource-operations/src/ResourceOperations.php @@ -0,0 +1,2232 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\ResourceOperations; + +final class ResourceOperations +{ + /** + * @return string[] + */ + public static function getFunctions(): array + { + return [ + 'Directory::close', + 'Directory::read', + 'Directory::rewind', + 'DirectoryIterator::openFile', + 'FilesystemIterator::openFile', + 'Gmagick::readimagefile', + 'HttpResponse::getRequestBodyStream', + 'HttpResponse::getStream', + 'HttpResponse::setStream', + 'Imagick::pingImageFile', + 'Imagick::readImageFile', + 'Imagick::writeImageFile', + 'Imagick::writeImagesFile', + 'MongoGridFSCursor::__construct', + 'MongoGridFSFile::getResource', + 'MysqlndUhConnection::stmtInit', + 'MysqlndUhConnection::storeResult', + 'MysqlndUhConnection::useResult', + 'PDF_activate_item', + 'PDF_add_launchlink', + 'PDF_add_locallink', + 'PDF_add_nameddest', + 'PDF_add_note', + 'PDF_add_pdflink', + 'PDF_add_table_cell', + 'PDF_add_textflow', + 'PDF_add_thumbnail', + 'PDF_add_weblink', + 'PDF_arc', + 'PDF_arcn', + 'PDF_attach_file', + 'PDF_begin_document', + 'PDF_begin_font', + 'PDF_begin_glyph', + 'PDF_begin_item', + 'PDF_begin_layer', + 'PDF_begin_page', + 'PDF_begin_page_ext', + 'PDF_begin_pattern', + 'PDF_begin_template', + 'PDF_begin_template_ext', + 'PDF_circle', + 'PDF_clip', + 'PDF_close', + 'PDF_close_image', + 'PDF_close_pdi', + 'PDF_close_pdi_page', + 'PDF_closepath', + 'PDF_closepath_fill_stroke', + 'PDF_closepath_stroke', + 'PDF_concat', + 'PDF_continue_text', + 'PDF_create_3dview', + 'PDF_create_action', + 'PDF_create_annotation', + 'PDF_create_bookmark', + 'PDF_create_field', + 'PDF_create_fieldgroup', + 'PDF_create_gstate', + 'PDF_create_pvf', + 'PDF_create_textflow', + 'PDF_curveto', + 'PDF_define_layer', + 'PDF_delete', + 'PDF_delete_pvf', + 'PDF_delete_table', + 'PDF_delete_textflow', + 'PDF_encoding_set_char', + 'PDF_end_document', + 'PDF_end_font', + 'PDF_end_glyph', + 'PDF_end_item', + 'PDF_end_layer', + 'PDF_end_page', + 'PDF_end_page_ext', + 'PDF_end_pattern', + 'PDF_end_template', + 'PDF_endpath', + 'PDF_fill', + 'PDF_fill_imageblock', + 'PDF_fill_pdfblock', + 'PDF_fill_stroke', + 'PDF_fill_textblock', + 'PDF_findfont', + 'PDF_fit_image', + 'PDF_fit_pdi_page', + 'PDF_fit_table', + 'PDF_fit_textflow', + 'PDF_fit_textline', + 'PDF_get_apiname', + 'PDF_get_buffer', + 'PDF_get_errmsg', + 'PDF_get_errnum', + 'PDF_get_parameter', + 'PDF_get_pdi_parameter', + 'PDF_get_pdi_value', + 'PDF_get_value', + 'PDF_info_font', + 'PDF_info_matchbox', + 'PDF_info_table', + 'PDF_info_textflow', + 'PDF_info_textline', + 'PDF_initgraphics', + 'PDF_lineto', + 'PDF_load_3ddata', + 'PDF_load_font', + 'PDF_load_iccprofile', + 'PDF_load_image', + 'PDF_makespotcolor', + 'PDF_moveto', + 'PDF_new', + 'PDF_open_ccitt', + 'PDF_open_file', + 'PDF_open_image', + 'PDF_open_image_file', + 'PDF_open_memory_image', + 'PDF_open_pdi', + 'PDF_open_pdi_document', + 'PDF_open_pdi_page', + 'PDF_pcos_get_number', + 'PDF_pcos_get_stream', + 'PDF_pcos_get_string', + 'PDF_place_image', + 'PDF_place_pdi_page', + 'PDF_process_pdi', + 'PDF_rect', + 'PDF_restore', + 'PDF_resume_page', + 'PDF_rotate', + 'PDF_save', + 'PDF_scale', + 'PDF_set_border_color', + 'PDF_set_border_dash', + 'PDF_set_border_style', + 'PDF_set_gstate', + 'PDF_set_info', + 'PDF_set_layer_dependency', + 'PDF_set_parameter', + 'PDF_set_text_pos', + 'PDF_set_value', + 'PDF_setcolor', + 'PDF_setdash', + 'PDF_setdashpattern', + 'PDF_setflat', + 'PDF_setfont', + 'PDF_setgray', + 'PDF_setgray_fill', + 'PDF_setgray_stroke', + 'PDF_setlinecap', + 'PDF_setlinejoin', + 'PDF_setlinewidth', + 'PDF_setmatrix', + 'PDF_setmiterlimit', + 'PDF_setrgbcolor', + 'PDF_setrgbcolor_fill', + 'PDF_setrgbcolor_stroke', + 'PDF_shading', + 'PDF_shading_pattern', + 'PDF_shfill', + 'PDF_show', + 'PDF_show_boxed', + 'PDF_show_xy', + 'PDF_skew', + 'PDF_stringwidth', + 'PDF_stroke', + 'PDF_suspend_page', + 'PDF_translate', + 'PDF_utf16_to_utf8', + 'PDF_utf32_to_utf16', + 'PDF_utf8_to_utf16', + 'PDO::pgsqlLOBOpen', + 'RarEntry::getStream', + 'SQLite3::openBlob', + 'SWFMovie::saveToFile', + 'SplFileInfo::openFile', + 'SplFileObject::openFile', + 'SplTempFileObject::openFile', + 'V8Js::compileString', + 'V8Js::executeScript', + 'Vtiful\Kernel\Excel::setColumn', + 'Vtiful\Kernel\Excel::setRow', + 'Vtiful\Kernel\Format::align', + 'Vtiful\Kernel\Format::bold', + 'Vtiful\Kernel\Format::italic', + 'Vtiful\Kernel\Format::underline', + 'XMLWriter::openMemory', + 'XMLWriter::openURI', + 'ZipArchive::getStream', + 'Zookeeper::setLogStream', + 'apc_bin_dumpfile', + 'apc_bin_loadfile', + 'bbcode_add_element', + 'bbcode_add_smiley', + 'bbcode_create', + 'bbcode_destroy', + 'bbcode_parse', + 'bbcode_set_arg_parser', + 'bbcode_set_flags', + 'bcompiler_read', + 'bcompiler_write_class', + 'bcompiler_write_constant', + 'bcompiler_write_exe_footer', + 'bcompiler_write_file', + 'bcompiler_write_footer', + 'bcompiler_write_function', + 'bcompiler_write_functions_from_file', + 'bcompiler_write_header', + 'bcompiler_write_included_filename', + 'bzclose', + 'bzerrno', + 'bzerror', + 'bzerrstr', + 'bzflush', + 'bzopen', + 'bzread', + 'bzwrite', + 'cairo_surface_write_to_png', + 'closedir', + 'copy', + 'crack_closedict', + 'crack_opendict', + 'cubrid_bind', + 'cubrid_close_prepare', + 'cubrid_close_request', + 'cubrid_col_get', + 'cubrid_col_size', + 'cubrid_column_names', + 'cubrid_column_types', + 'cubrid_commit', + 'cubrid_connect', + 'cubrid_connect_with_url', + 'cubrid_current_oid', + 'cubrid_db_parameter', + 'cubrid_disconnect', + 'cubrid_drop', + 'cubrid_fetch', + 'cubrid_free_result', + 'cubrid_get', + 'cubrid_get_autocommit', + 'cubrid_get_charset', + 'cubrid_get_class_name', + 'cubrid_get_db_parameter', + 'cubrid_get_query_timeout', + 'cubrid_get_server_info', + 'cubrid_insert_id', + 'cubrid_is_instance', + 'cubrid_lob2_bind', + 'cubrid_lob2_close', + 'cubrid_lob2_export', + 'cubrid_lob2_import', + 'cubrid_lob2_new', + 'cubrid_lob2_read', + 'cubrid_lob2_seek', + 'cubrid_lob2_seek64', + 'cubrid_lob2_size', + 'cubrid_lob2_size64', + 'cubrid_lob2_tell', + 'cubrid_lob2_tell64', + 'cubrid_lob2_write', + 'cubrid_lob_export', + 'cubrid_lob_get', + 'cubrid_lob_send', + 'cubrid_lob_size', + 'cubrid_lock_read', + 'cubrid_lock_write', + 'cubrid_move_cursor', + 'cubrid_next_result', + 'cubrid_num_cols', + 'cubrid_num_rows', + 'cubrid_pconnect', + 'cubrid_pconnect_with_url', + 'cubrid_prepare', + 'cubrid_put', + 'cubrid_query', + 'cubrid_rollback', + 'cubrid_schema', + 'cubrid_seq_add', + 'cubrid_seq_drop', + 'cubrid_seq_insert', + 'cubrid_seq_put', + 'cubrid_set_add', + 'cubrid_set_autocommit', + 'cubrid_set_db_parameter', + 'cubrid_set_drop', + 'cubrid_set_query_timeout', + 'cubrid_unbuffered_query', + 'curl_close', + 'curl_copy_handle', + 'curl_errno', + 'curl_error', + 'curl_escape', + 'curl_exec', + 'curl_getinfo', + 'curl_multi_add_handle', + 'curl_multi_close', + 'curl_multi_errno', + 'curl_multi_exec', + 'curl_multi_getcontent', + 'curl_multi_info_read', + 'curl_multi_remove_handle', + 'curl_multi_select', + 'curl_multi_setopt', + 'curl_pause', + 'curl_reset', + 'curl_setopt', + 'curl_setopt_array', + 'curl_share_close', + 'curl_share_errno', + 'curl_share_init', + 'curl_share_setopt', + 'curl_unescape', + 'cyrus_authenticate', + 'cyrus_bind', + 'cyrus_close', + 'cyrus_connect', + 'cyrus_query', + 'cyrus_unbind', + 'db2_autocommit', + 'db2_bind_param', + 'db2_client_info', + 'db2_close', + 'db2_column_privileges', + 'db2_columns', + 'db2_commit', + 'db2_conn_error', + 'db2_conn_errormsg', + 'db2_connect', + 'db2_cursor_type', + 'db2_exec', + 'db2_execute', + 'db2_fetch_array', + 'db2_fetch_assoc', + 'db2_fetch_both', + 'db2_fetch_object', + 'db2_fetch_row', + 'db2_field_display_size', + 'db2_field_name', + 'db2_field_num', + 'db2_field_precision', + 'db2_field_scale', + 'db2_field_type', + 'db2_field_width', + 'db2_foreign_keys', + 'db2_free_result', + 'db2_free_stmt', + 'db2_get_option', + 'db2_last_insert_id', + 'db2_lob_read', + 'db2_next_result', + 'db2_num_fields', + 'db2_num_rows', + 'db2_pclose', + 'db2_pconnect', + 'db2_prepare', + 'db2_primary_keys', + 'db2_procedure_columns', + 'db2_procedures', + 'db2_result', + 'db2_rollback', + 'db2_server_info', + 'db2_set_option', + 'db2_special_columns', + 'db2_statistics', + 'db2_stmt_error', + 'db2_stmt_errormsg', + 'db2_table_privileges', + 'db2_tables', + 'dba_close', + 'dba_delete', + 'dba_exists', + 'dba_fetch', + 'dba_firstkey', + 'dba_insert', + 'dba_nextkey', + 'dba_open', + 'dba_optimize', + 'dba_popen', + 'dba_replace', + 'dba_sync', + 'dbplus_add', + 'dbplus_aql', + 'dbplus_close', + 'dbplus_curr', + 'dbplus_find', + 'dbplus_first', + 'dbplus_flush', + 'dbplus_freelock', + 'dbplus_freerlocks', + 'dbplus_getlock', + 'dbplus_getunique', + 'dbplus_info', + 'dbplus_last', + 'dbplus_lockrel', + 'dbplus_next', + 'dbplus_open', + 'dbplus_prev', + 'dbplus_rchperm', + 'dbplus_rcreate', + 'dbplus_rcrtexact', + 'dbplus_rcrtlike', + 'dbplus_restorepos', + 'dbplus_rkeys', + 'dbplus_ropen', + 'dbplus_rquery', + 'dbplus_rrename', + 'dbplus_rsecindex', + 'dbplus_runlink', + 'dbplus_rzap', + 'dbplus_savepos', + 'dbplus_setindex', + 'dbplus_setindexbynumber', + 'dbplus_sql', + 'dbplus_tremove', + 'dbplus_undo', + 'dbplus_undoprepare', + 'dbplus_unlockrel', + 'dbplus_unselect', + 'dbplus_update', + 'dbplus_xlockrel', + 'dbplus_xunlockrel', + 'deflate_add', + 'dio_close', + 'dio_fcntl', + 'dio_open', + 'dio_read', + 'dio_seek', + 'dio_stat', + 'dio_tcsetattr', + 'dio_truncate', + 'dio_write', + 'dir', + 'eio_busy', + 'eio_cancel', + 'eio_chmod', + 'eio_chown', + 'eio_close', + 'eio_custom', + 'eio_dup2', + 'eio_fallocate', + 'eio_fchmod', + 'eio_fchown', + 'eio_fdatasync', + 'eio_fstat', + 'eio_fstatvfs', + 'eio_fsync', + 'eio_ftruncate', + 'eio_futime', + 'eio_get_last_error', + 'eio_grp', + 'eio_grp_add', + 'eio_grp_cancel', + 'eio_grp_limit', + 'eio_link', + 'eio_lstat', + 'eio_mkdir', + 'eio_mknod', + 'eio_nop', + 'eio_open', + 'eio_read', + 'eio_readahead', + 'eio_readdir', + 'eio_readlink', + 'eio_realpath', + 'eio_rename', + 'eio_rmdir', + 'eio_seek', + 'eio_sendfile', + 'eio_stat', + 'eio_statvfs', + 'eio_symlink', + 'eio_sync', + 'eio_sync_file_range', + 'eio_syncfs', + 'eio_truncate', + 'eio_unlink', + 'eio_utime', + 'eio_write', + 'enchant_broker_describe', + 'enchant_broker_dict_exists', + 'enchant_broker_free', + 'enchant_broker_free_dict', + 'enchant_broker_get_dict_path', + 'enchant_broker_get_error', + 'enchant_broker_init', + 'enchant_broker_list_dicts', + 'enchant_broker_request_dict', + 'enchant_broker_request_pwl_dict', + 'enchant_broker_set_dict_path', + 'enchant_broker_set_ordering', + 'enchant_dict_add_to_personal', + 'enchant_dict_add_to_session', + 'enchant_dict_check', + 'enchant_dict_describe', + 'enchant_dict_get_error', + 'enchant_dict_is_in_session', + 'enchant_dict_quick_check', + 'enchant_dict_store_replacement', + 'enchant_dict_suggest', + 'event_add', + 'event_base_free', + 'event_base_loop', + 'event_base_loopbreak', + 'event_base_loopexit', + 'event_base_new', + 'event_base_priority_init', + 'event_base_reinit', + 'event_base_set', + 'event_buffer_base_set', + 'event_buffer_disable', + 'event_buffer_enable', + 'event_buffer_fd_set', + 'event_buffer_free', + 'event_buffer_new', + 'event_buffer_priority_set', + 'event_buffer_read', + 'event_buffer_set_callback', + 'event_buffer_timeout_set', + 'event_buffer_watermark_set', + 'event_buffer_write', + 'event_del', + 'event_free', + 'event_new', + 'event_priority_set', + 'event_set', + 'event_timer_add', + 'event_timer_del', + 'event_timer_pending', + 'event_timer_set', + 'expect_expectl', + 'expect_popen', + 'fam_cancel_monitor', + 'fam_close', + 'fam_monitor_collection', + 'fam_monitor_directory', + 'fam_monitor_file', + 'fam_next_event', + 'fam_open', + 'fam_pending', + 'fam_resume_monitor', + 'fam_suspend_monitor', + 'fann_cascadetrain_on_data', + 'fann_cascadetrain_on_file', + 'fann_clear_scaling_params', + 'fann_copy', + 'fann_create_from_file', + 'fann_create_shortcut_array', + 'fann_create_standard', + 'fann_create_standard_array', + 'fann_create_train', + 'fann_create_train_from_callback', + 'fann_descale_input', + 'fann_descale_output', + 'fann_descale_train', + 'fann_destroy', + 'fann_destroy_train', + 'fann_duplicate_train_data', + 'fann_get_MSE', + 'fann_get_activation_function', + 'fann_get_activation_steepness', + 'fann_get_bias_array', + 'fann_get_bit_fail', + 'fann_get_bit_fail_limit', + 'fann_get_cascade_activation_functions', + 'fann_get_cascade_activation_functions_count', + 'fann_get_cascade_activation_steepnesses', + 'fann_get_cascade_activation_steepnesses_count', + 'fann_get_cascade_candidate_change_fraction', + 'fann_get_cascade_candidate_limit', + 'fann_get_cascade_candidate_stagnation_epochs', + 'fann_get_cascade_max_cand_epochs', + 'fann_get_cascade_max_out_epochs', + 'fann_get_cascade_min_cand_epochs', + 'fann_get_cascade_min_out_epochs', + 'fann_get_cascade_num_candidate_groups', + 'fann_get_cascade_num_candidates', + 'fann_get_cascade_output_change_fraction', + 'fann_get_cascade_output_stagnation_epochs', + 'fann_get_cascade_weight_multiplier', + 'fann_get_connection_array', + 'fann_get_connection_rate', + 'fann_get_errno', + 'fann_get_errstr', + 'fann_get_layer_array', + 'fann_get_learning_momentum', + 'fann_get_learning_rate', + 'fann_get_network_type', + 'fann_get_num_input', + 'fann_get_num_layers', + 'fann_get_num_output', + 'fann_get_quickprop_decay', + 'fann_get_quickprop_mu', + 'fann_get_rprop_decrease_factor', + 'fann_get_rprop_delta_max', + 'fann_get_rprop_delta_min', + 'fann_get_rprop_delta_zero', + 'fann_get_rprop_increase_factor', + 'fann_get_sarprop_step_error_shift', + 'fann_get_sarprop_step_error_threshold_factor', + 'fann_get_sarprop_temperature', + 'fann_get_sarprop_weight_decay_shift', + 'fann_get_total_connections', + 'fann_get_total_neurons', + 'fann_get_train_error_function', + 'fann_get_train_stop_function', + 'fann_get_training_algorithm', + 'fann_init_weights', + 'fann_length_train_data', + 'fann_merge_train_data', + 'fann_num_input_train_data', + 'fann_num_output_train_data', + 'fann_randomize_weights', + 'fann_read_train_from_file', + 'fann_reset_errno', + 'fann_reset_errstr', + 'fann_run', + 'fann_save', + 'fann_save_train', + 'fann_scale_input', + 'fann_scale_input_train_data', + 'fann_scale_output', + 'fann_scale_output_train_data', + 'fann_scale_train', + 'fann_scale_train_data', + 'fann_set_activation_function', + 'fann_set_activation_function_hidden', + 'fann_set_activation_function_layer', + 'fann_set_activation_function_output', + 'fann_set_activation_steepness', + 'fann_set_activation_steepness_hidden', + 'fann_set_activation_steepness_layer', + 'fann_set_activation_steepness_output', + 'fann_set_bit_fail_limit', + 'fann_set_callback', + 'fann_set_cascade_activation_functions', + 'fann_set_cascade_activation_steepnesses', + 'fann_set_cascade_candidate_change_fraction', + 'fann_set_cascade_candidate_limit', + 'fann_set_cascade_candidate_stagnation_epochs', + 'fann_set_cascade_max_cand_epochs', + 'fann_set_cascade_max_out_epochs', + 'fann_set_cascade_min_cand_epochs', + 'fann_set_cascade_min_out_epochs', + 'fann_set_cascade_num_candidate_groups', + 'fann_set_cascade_output_change_fraction', + 'fann_set_cascade_output_stagnation_epochs', + 'fann_set_cascade_weight_multiplier', + 'fann_set_error_log', + 'fann_set_input_scaling_params', + 'fann_set_learning_momentum', + 'fann_set_learning_rate', + 'fann_set_output_scaling_params', + 'fann_set_quickprop_decay', + 'fann_set_quickprop_mu', + 'fann_set_rprop_decrease_factor', + 'fann_set_rprop_delta_max', + 'fann_set_rprop_delta_min', + 'fann_set_rprop_delta_zero', + 'fann_set_rprop_increase_factor', + 'fann_set_sarprop_step_error_shift', + 'fann_set_sarprop_step_error_threshold_factor', + 'fann_set_sarprop_temperature', + 'fann_set_sarprop_weight_decay_shift', + 'fann_set_scaling_params', + 'fann_set_train_error_function', + 'fann_set_train_stop_function', + 'fann_set_training_algorithm', + 'fann_set_weight', + 'fann_set_weight_array', + 'fann_shuffle_train_data', + 'fann_subset_train_data', + 'fann_test', + 'fann_test_data', + 'fann_train', + 'fann_train_epoch', + 'fann_train_on_data', + 'fann_train_on_file', + 'fbsql_affected_rows', + 'fbsql_autocommit', + 'fbsql_blob_size', + 'fbsql_change_user', + 'fbsql_clob_size', + 'fbsql_close', + 'fbsql_commit', + 'fbsql_connect', + 'fbsql_create_blob', + 'fbsql_create_clob', + 'fbsql_create_db', + 'fbsql_data_seek', + 'fbsql_database', + 'fbsql_database_password', + 'fbsql_db_query', + 'fbsql_db_status', + 'fbsql_drop_db', + 'fbsql_errno', + 'fbsql_error', + 'fbsql_fetch_array', + 'fbsql_fetch_assoc', + 'fbsql_fetch_field', + 'fbsql_fetch_lengths', + 'fbsql_fetch_object', + 'fbsql_fetch_row', + 'fbsql_field_flags', + 'fbsql_field_len', + 'fbsql_field_name', + 'fbsql_field_seek', + 'fbsql_field_table', + 'fbsql_field_type', + 'fbsql_free_result', + 'fbsql_get_autostart_info', + 'fbsql_hostname', + 'fbsql_insert_id', + 'fbsql_list_dbs', + 'fbsql_list_fields', + 'fbsql_list_tables', + 'fbsql_next_result', + 'fbsql_num_fields', + 'fbsql_num_rows', + 'fbsql_password', + 'fbsql_pconnect', + 'fbsql_query', + 'fbsql_read_blob', + 'fbsql_read_clob', + 'fbsql_result', + 'fbsql_rollback', + 'fbsql_rows_fetched', + 'fbsql_select_db', + 'fbsql_set_characterset', + 'fbsql_set_lob_mode', + 'fbsql_set_password', + 'fbsql_set_transaction', + 'fbsql_start_db', + 'fbsql_stop_db', + 'fbsql_table_name', + 'fbsql_username', + 'fclose', + 'fdf_add_doc_javascript', + 'fdf_add_template', + 'fdf_close', + 'fdf_create', + 'fdf_enum_values', + 'fdf_get_ap', + 'fdf_get_attachment', + 'fdf_get_encoding', + 'fdf_get_file', + 'fdf_get_flags', + 'fdf_get_opt', + 'fdf_get_status', + 'fdf_get_value', + 'fdf_get_version', + 'fdf_next_field_name', + 'fdf_open', + 'fdf_open_string', + 'fdf_remove_item', + 'fdf_save', + 'fdf_save_string', + 'fdf_set_ap', + 'fdf_set_encoding', + 'fdf_set_file', + 'fdf_set_flags', + 'fdf_set_javascript_action', + 'fdf_set_on_import_javascript', + 'fdf_set_opt', + 'fdf_set_status', + 'fdf_set_submit_form_action', + 'fdf_set_target_frame', + 'fdf_set_value', + 'fdf_set_version', + 'feof', + 'fflush', + 'ffmpeg_frame::__construct', + 'ffmpeg_frame::toGDImage', + 'fgetc', + 'fgetcsv', + 'fgets', + 'fgetss', + 'file', + 'file_get_contents', + 'file_put_contents', + 'finfo::buffer', + 'finfo::file', + 'finfo_buffer', + 'finfo_close', + 'finfo_file', + 'finfo_open', + 'finfo_set_flags', + 'flock', + 'fopen', + 'fpassthru', + 'fprintf', + 'fputcsv', + 'fputs', + 'fread', + 'fscanf', + 'fseek', + 'fstat', + 'ftell', + 'ftp_alloc', + 'ftp_append', + 'ftp_cdup', + 'ftp_chdir', + 'ftp_chmod', + 'ftp_close', + 'ftp_delete', + 'ftp_exec', + 'ftp_fget', + 'ftp_fput', + 'ftp_get', + 'ftp_get_option', + 'ftp_login', + 'ftp_mdtm', + 'ftp_mkdir', + 'ftp_mlsd', + 'ftp_nb_continue', + 'ftp_nb_fget', + 'ftp_nb_fput', + 'ftp_nb_get', + 'ftp_nb_put', + 'ftp_nlist', + 'ftp_pasv', + 'ftp_put', + 'ftp_pwd', + 'ftp_quit', + 'ftp_raw', + 'ftp_rawlist', + 'ftp_rename', + 'ftp_rmdir', + 'ftp_set_option', + 'ftp_site', + 'ftp_size', + 'ftp_systype', + 'ftruncate', + 'fwrite', + 'get_resource_type', + 'gmp_div', + 'gnupg::init', + 'gnupg_adddecryptkey', + 'gnupg_addencryptkey', + 'gnupg_addsignkey', + 'gnupg_cleardecryptkeys', + 'gnupg_clearencryptkeys', + 'gnupg_clearsignkeys', + 'gnupg_decrypt', + 'gnupg_decryptverify', + 'gnupg_encrypt', + 'gnupg_encryptsign', + 'gnupg_export', + 'gnupg_geterror', + 'gnupg_getprotocol', + 'gnupg_import', + 'gnupg_init', + 'gnupg_keyinfo', + 'gnupg_setarmor', + 'gnupg_seterrormode', + 'gnupg_setsignmode', + 'gnupg_sign', + 'gnupg_verify', + 'gupnp_context_get_host_ip', + 'gupnp_context_get_port', + 'gupnp_context_get_subscription_timeout', + 'gupnp_context_host_path', + 'gupnp_context_new', + 'gupnp_context_set_subscription_timeout', + 'gupnp_context_timeout_add', + 'gupnp_context_unhost_path', + 'gupnp_control_point_browse_start', + 'gupnp_control_point_browse_stop', + 'gupnp_control_point_callback_set', + 'gupnp_control_point_new', + 'gupnp_device_action_callback_set', + 'gupnp_device_info_get', + 'gupnp_device_info_get_service', + 'gupnp_root_device_get_available', + 'gupnp_root_device_get_relative_location', + 'gupnp_root_device_new', + 'gupnp_root_device_set_available', + 'gupnp_root_device_start', + 'gupnp_root_device_stop', + 'gupnp_service_action_get', + 'gupnp_service_action_return', + 'gupnp_service_action_return_error', + 'gupnp_service_action_set', + 'gupnp_service_freeze_notify', + 'gupnp_service_info_get', + 'gupnp_service_info_get_introspection', + 'gupnp_service_introspection_get_state_variable', + 'gupnp_service_notify', + 'gupnp_service_proxy_action_get', + 'gupnp_service_proxy_action_set', + 'gupnp_service_proxy_add_notify', + 'gupnp_service_proxy_callback_set', + 'gupnp_service_proxy_get_subscribed', + 'gupnp_service_proxy_remove_notify', + 'gupnp_service_proxy_send_action', + 'gupnp_service_proxy_set_subscribed', + 'gupnp_service_thaw_notify', + 'gzclose', + 'gzeof', + 'gzgetc', + 'gzgets', + 'gzgetss', + 'gzpassthru', + 'gzputs', + 'gzread', + 'gzrewind', + 'gzseek', + 'gztell', + 'gzwrite', + 'hash_update_stream', + 'http\Env\Response::send', + 'http_get_request_body_stream', + 'ibase_add_user', + 'ibase_affected_rows', + 'ibase_backup', + 'ibase_blob_add', + 'ibase_blob_cancel', + 'ibase_blob_close', + 'ibase_blob_create', + 'ibase_blob_get', + 'ibase_blob_open', + 'ibase_close', + 'ibase_commit', + 'ibase_commit_ret', + 'ibase_connect', + 'ibase_db_info', + 'ibase_delete_user', + 'ibase_drop_db', + 'ibase_execute', + 'ibase_fetch_assoc', + 'ibase_fetch_object', + 'ibase_fetch_row', + 'ibase_field_info', + 'ibase_free_event_handler', + 'ibase_free_query', + 'ibase_free_result', + 'ibase_gen_id', + 'ibase_maintain_db', + 'ibase_modify_user', + 'ibase_name_result', + 'ibase_num_fields', + 'ibase_num_params', + 'ibase_param_info', + 'ibase_pconnect', + 'ibase_prepare', + 'ibase_query', + 'ibase_restore', + 'ibase_rollback', + 'ibase_rollback_ret', + 'ibase_server_info', + 'ibase_service_attach', + 'ibase_service_detach', + 'ibase_set_event_handler', + 'ibase_trans', + 'ifx_affected_rows', + 'ifx_close', + 'ifx_connect', + 'ifx_do', + 'ifx_error', + 'ifx_fetch_row', + 'ifx_fieldproperties', + 'ifx_fieldtypes', + 'ifx_free_result', + 'ifx_getsqlca', + 'ifx_htmltbl_result', + 'ifx_num_fields', + 'ifx_num_rows', + 'ifx_pconnect', + 'ifx_prepare', + 'ifx_query', + 'image2wbmp', + 'imageaffine', + 'imagealphablending', + 'imageantialias', + 'imagearc', + 'imagebmp', + 'imagechar', + 'imagecharup', + 'imagecolorallocate', + 'imagecolorallocatealpha', + 'imagecolorat', + 'imagecolorclosest', + 'imagecolorclosestalpha', + 'imagecolorclosesthwb', + 'imagecolordeallocate', + 'imagecolorexact', + 'imagecolorexactalpha', + 'imagecolormatch', + 'imagecolorresolve', + 'imagecolorresolvealpha', + 'imagecolorset', + 'imagecolorsforindex', + 'imagecolorstotal', + 'imagecolortransparent', + 'imageconvolution', + 'imagecopy', + 'imagecopymerge', + 'imagecopymergegray', + 'imagecopyresampled', + 'imagecopyresized', + 'imagecrop', + 'imagecropauto', + 'imagedashedline', + 'imagedestroy', + 'imageellipse', + 'imagefill', + 'imagefilledarc', + 'imagefilledellipse', + 'imagefilledpolygon', + 'imagefilledrectangle', + 'imagefilltoborder', + 'imagefilter', + 'imageflip', + 'imagefttext', + 'imagegammacorrect', + 'imagegd', + 'imagegd2', + 'imagegetclip', + 'imagegif', + 'imagegrabscreen', + 'imagegrabwindow', + 'imageinterlace', + 'imageistruecolor', + 'imagejpeg', + 'imagelayereffect', + 'imageline', + 'imageopenpolygon', + 'imagepalettecopy', + 'imagepalettetotruecolor', + 'imagepng', + 'imagepolygon', + 'imagepsencodefont', + 'imagepsextendfont', + 'imagepsfreefont', + 'imagepsloadfont', + 'imagepsslantfont', + 'imagepstext', + 'imagerectangle', + 'imageresolution', + 'imagerotate', + 'imagesavealpha', + 'imagescale', + 'imagesetbrush', + 'imagesetclip', + 'imagesetinterpolation', + 'imagesetpixel', + 'imagesetstyle', + 'imagesetthickness', + 'imagesettile', + 'imagestring', + 'imagestringup', + 'imagesx', + 'imagesy', + 'imagetruecolortopalette', + 'imagettftext', + 'imagewbmp', + 'imagewebp', + 'imagexbm', + 'imap_append', + 'imap_body', + 'imap_bodystruct', + 'imap_check', + 'imap_clearflag_full', + 'imap_close', + 'imap_create', + 'imap_createmailbox', + 'imap_delete', + 'imap_deletemailbox', + 'imap_expunge', + 'imap_fetch_overview', + 'imap_fetchbody', + 'imap_fetchheader', + 'imap_fetchmime', + 'imap_fetchstructure', + 'imap_fetchtext', + 'imap_gc', + 'imap_get_quota', + 'imap_get_quotaroot', + 'imap_getacl', + 'imap_getmailboxes', + 'imap_getsubscribed', + 'imap_header', + 'imap_headerinfo', + 'imap_headers', + 'imap_list', + 'imap_listmailbox', + 'imap_listscan', + 'imap_listsubscribed', + 'imap_lsub', + 'imap_mail_copy', + 'imap_mail_move', + 'imap_mailboxmsginfo', + 'imap_msgno', + 'imap_num_msg', + 'imap_num_recent', + 'imap_ping', + 'imap_rename', + 'imap_renamemailbox', + 'imap_reopen', + 'imap_savebody', + 'imap_scan', + 'imap_scanmailbox', + 'imap_search', + 'imap_set_quota', + 'imap_setacl', + 'imap_setflag_full', + 'imap_sort', + 'imap_status', + 'imap_subscribe', + 'imap_thread', + 'imap_uid', + 'imap_undelete', + 'imap_unsubscribe', + 'inflate_add', + 'inflate_get_read_len', + 'inflate_get_status', + 'ingres_autocommit', + 'ingres_autocommit_state', + 'ingres_charset', + 'ingres_close', + 'ingres_commit', + 'ingres_connect', + 'ingres_cursor', + 'ingres_errno', + 'ingres_error', + 'ingres_errsqlstate', + 'ingres_escape_string', + 'ingres_execute', + 'ingres_fetch_array', + 'ingres_fetch_assoc', + 'ingres_fetch_object', + 'ingres_fetch_proc_return', + 'ingres_fetch_row', + 'ingres_field_length', + 'ingres_field_name', + 'ingres_field_nullable', + 'ingres_field_precision', + 'ingres_field_scale', + 'ingres_field_type', + 'ingres_free_result', + 'ingres_next_error', + 'ingres_num_fields', + 'ingres_num_rows', + 'ingres_pconnect', + 'ingres_prepare', + 'ingres_query', + 'ingres_result_seek', + 'ingres_rollback', + 'ingres_set_environment', + 'ingres_unbuffered_query', + 'inotify_add_watch', + 'inotify_init', + 'inotify_queue_len', + 'inotify_read', + 'inotify_rm_watch', + 'kadm5_chpass_principal', + 'kadm5_create_principal', + 'kadm5_delete_principal', + 'kadm5_destroy', + 'kadm5_flush', + 'kadm5_get_policies', + 'kadm5_get_principal', + 'kadm5_get_principals', + 'kadm5_init_with_password', + 'kadm5_modify_principal', + 'ldap_add', + 'ldap_bind', + 'ldap_close', + 'ldap_compare', + 'ldap_control_paged_result', + 'ldap_control_paged_result_response', + 'ldap_count_entries', + 'ldap_delete', + 'ldap_errno', + 'ldap_error', + 'ldap_exop', + 'ldap_exop_passwd', + 'ldap_exop_refresh', + 'ldap_exop_whoami', + 'ldap_first_attribute', + 'ldap_first_entry', + 'ldap_first_reference', + 'ldap_free_result', + 'ldap_get_attributes', + 'ldap_get_dn', + 'ldap_get_entries', + 'ldap_get_option', + 'ldap_get_values', + 'ldap_get_values_len', + 'ldap_mod_add', + 'ldap_mod_del', + 'ldap_mod_replace', + 'ldap_modify', + 'ldap_modify_batch', + 'ldap_next_attribute', + 'ldap_next_entry', + 'ldap_next_reference', + 'ldap_parse_exop', + 'ldap_parse_reference', + 'ldap_parse_result', + 'ldap_rename', + 'ldap_sasl_bind', + 'ldap_set_option', + 'ldap_set_rebind_proc', + 'ldap_sort', + 'ldap_start_tls', + 'ldap_unbind', + 'libxml_set_streams_context', + 'm_checkstatus', + 'm_completeauthorizations', + 'm_connect', + 'm_connectionerror', + 'm_deletetrans', + 'm_destroyconn', + 'm_getcell', + 'm_getcellbynum', + 'm_getcommadelimited', + 'm_getheader', + 'm_initconn', + 'm_iscommadelimited', + 'm_maxconntimeout', + 'm_monitor', + 'm_numcolumns', + 'm_numrows', + 'm_parsecommadelimited', + 'm_responsekeys', + 'm_responseparam', + 'm_returnstatus', + 'm_setblocking', + 'm_setdropfile', + 'm_setip', + 'm_setssl', + 'm_setssl_cafile', + 'm_setssl_files', + 'm_settimeout', + 'm_transactionssent', + 'm_transinqueue', + 'm_transkeyval', + 'm_transnew', + 'm_transsend', + 'm_validateidentifier', + 'm_verifyconnection', + 'm_verifysslcert', + 'mailparse_determine_best_xfer_encoding', + 'mailparse_msg_create', + 'mailparse_msg_extract_part', + 'mailparse_msg_extract_part_file', + 'mailparse_msg_extract_whole_part_file', + 'mailparse_msg_free', + 'mailparse_msg_get_part', + 'mailparse_msg_get_part_data', + 'mailparse_msg_get_structure', + 'mailparse_msg_parse', + 'mailparse_msg_parse_file', + 'mailparse_stream_encode', + 'mailparse_uudecode_all', + 'maxdb::use_result', + 'maxdb_affected_rows', + 'maxdb_connect', + 'maxdb_disable_rpl_parse', + 'maxdb_dump_debug_info', + 'maxdb_embedded_connect', + 'maxdb_enable_reads_from_master', + 'maxdb_enable_rpl_parse', + 'maxdb_errno', + 'maxdb_error', + 'maxdb_fetch_lengths', + 'maxdb_field_tell', + 'maxdb_get_host_info', + 'maxdb_get_proto_info', + 'maxdb_get_server_info', + 'maxdb_get_server_version', + 'maxdb_info', + 'maxdb_init', + 'maxdb_insert_id', + 'maxdb_master_query', + 'maxdb_more_results', + 'maxdb_next_result', + 'maxdb_num_fields', + 'maxdb_num_rows', + 'maxdb_rpl_parse_enabled', + 'maxdb_rpl_probe', + 'maxdb_select_db', + 'maxdb_sqlstate', + 'maxdb_stmt::result_metadata', + 'maxdb_stmt_affected_rows', + 'maxdb_stmt_errno', + 'maxdb_stmt_error', + 'maxdb_stmt_num_rows', + 'maxdb_stmt_param_count', + 'maxdb_stmt_result_metadata', + 'maxdb_stmt_sqlstate', + 'maxdb_thread_id', + 'maxdb_use_result', + 'maxdb_warning_count', + 'mcrypt_enc_get_algorithms_name', + 'mcrypt_enc_get_block_size', + 'mcrypt_enc_get_iv_size', + 'mcrypt_enc_get_key_size', + 'mcrypt_enc_get_modes_name', + 'mcrypt_enc_get_supported_key_sizes', + 'mcrypt_enc_is_block_algorithm', + 'mcrypt_enc_is_block_algorithm_mode', + 'mcrypt_enc_is_block_mode', + 'mcrypt_enc_self_test', + 'mcrypt_generic', + 'mcrypt_generic_deinit', + 'mcrypt_generic_end', + 'mcrypt_generic_init', + 'mcrypt_module_close', + 'mcrypt_module_open', + 'mdecrypt_generic', + 'mkdir', + 'mqseries_back', + 'mqseries_begin', + 'mqseries_close', + 'mqseries_cmit', + 'mqseries_conn', + 'mqseries_connx', + 'mqseries_disc', + 'mqseries_get', + 'mqseries_inq', + 'mqseries_open', + 'mqseries_put', + 'mqseries_put1', + 'mqseries_set', + 'msg_get_queue', + 'msg_receive', + 'msg_remove_queue', + 'msg_send', + 'msg_set_queue', + 'msg_stat_queue', + 'msql_affected_rows', + 'msql_close', + 'msql_connect', + 'msql_create_db', + 'msql_data_seek', + 'msql_db_query', + 'msql_drop_db', + 'msql_fetch_array', + 'msql_fetch_field', + 'msql_fetch_object', + 'msql_fetch_row', + 'msql_field_flags', + 'msql_field_len', + 'msql_field_name', + 'msql_field_seek', + 'msql_field_table', + 'msql_field_type', + 'msql_free_result', + 'msql_list_dbs', + 'msql_list_fields', + 'msql_list_tables', + 'msql_num_fields', + 'msql_num_rows', + 'msql_pconnect', + 'msql_query', + 'msql_result', + 'msql_select_db', + 'mssql_bind', + 'mssql_close', + 'mssql_connect', + 'mssql_data_seek', + 'mssql_execute', + 'mssql_fetch_array', + 'mssql_fetch_assoc', + 'mssql_fetch_batch', + 'mssql_fetch_field', + 'mssql_fetch_object', + 'mssql_fetch_row', + 'mssql_field_length', + 'mssql_field_name', + 'mssql_field_seek', + 'mssql_field_type', + 'mssql_free_result', + 'mssql_free_statement', + 'mssql_init', + 'mssql_next_result', + 'mssql_num_fields', + 'mssql_num_rows', + 'mssql_pconnect', + 'mssql_query', + 'mssql_result', + 'mssql_rows_affected', + 'mssql_select_db', + 'mysql_affected_rows', + 'mysql_client_encoding', + 'mysql_close', + 'mysql_connect', + 'mysql_create_db', + 'mysql_data_seek', + 'mysql_db_name', + 'mysql_db_query', + 'mysql_drop_db', + 'mysql_errno', + 'mysql_error', + 'mysql_fetch_array', + 'mysql_fetch_assoc', + 'mysql_fetch_field', + 'mysql_fetch_lengths', + 'mysql_fetch_object', + 'mysql_fetch_row', + 'mysql_field_flags', + 'mysql_field_len', + 'mysql_field_name', + 'mysql_field_seek', + 'mysql_field_table', + 'mysql_field_type', + 'mysql_free_result', + 'mysql_get_host_info', + 'mysql_get_proto_info', + 'mysql_get_server_info', + 'mysql_info', + 'mysql_insert_id', + 'mysql_list_dbs', + 'mysql_list_fields', + 'mysql_list_processes', + 'mysql_list_tables', + 'mysql_num_fields', + 'mysql_num_rows', + 'mysql_pconnect', + 'mysql_ping', + 'mysql_query', + 'mysql_real_escape_string', + 'mysql_result', + 'mysql_select_db', + 'mysql_set_charset', + 'mysql_stat', + 'mysql_tablename', + 'mysql_thread_id', + 'mysql_unbuffered_query', + 'mysqlnd_uh_convert_to_mysqlnd', + 'ncurses_bottom_panel', + 'ncurses_del_panel', + 'ncurses_delwin', + 'ncurses_getmaxyx', + 'ncurses_getyx', + 'ncurses_hide_panel', + 'ncurses_keypad', + 'ncurses_meta', + 'ncurses_move_panel', + 'ncurses_mvwaddstr', + 'ncurses_new_panel', + 'ncurses_newpad', + 'ncurses_newwin', + 'ncurses_panel_above', + 'ncurses_panel_below', + 'ncurses_panel_window', + 'ncurses_pnoutrefresh', + 'ncurses_prefresh', + 'ncurses_replace_panel', + 'ncurses_show_panel', + 'ncurses_top_panel', + 'ncurses_waddch', + 'ncurses_waddstr', + 'ncurses_wattroff', + 'ncurses_wattron', + 'ncurses_wattrset', + 'ncurses_wborder', + 'ncurses_wclear', + 'ncurses_wcolor_set', + 'ncurses_werase', + 'ncurses_wgetch', + 'ncurses_whline', + 'ncurses_wmouse_trafo', + 'ncurses_wmove', + 'ncurses_wnoutrefresh', + 'ncurses_wrefresh', + 'ncurses_wstandend', + 'ncurses_wstandout', + 'ncurses_wvline', + 'newt_button', + 'newt_button_bar', + 'newt_checkbox', + 'newt_checkbox_get_value', + 'newt_checkbox_set_flags', + 'newt_checkbox_set_value', + 'newt_checkbox_tree', + 'newt_checkbox_tree_add_item', + 'newt_checkbox_tree_find_item', + 'newt_checkbox_tree_get_current', + 'newt_checkbox_tree_get_entry_value', + 'newt_checkbox_tree_get_multi_selection', + 'newt_checkbox_tree_get_selection', + 'newt_checkbox_tree_multi', + 'newt_checkbox_tree_set_current', + 'newt_checkbox_tree_set_entry', + 'newt_checkbox_tree_set_entry_value', + 'newt_checkbox_tree_set_width', + 'newt_compact_button', + 'newt_component_add_callback', + 'newt_component_takes_focus', + 'newt_create_grid', + 'newt_draw_form', + 'newt_entry', + 'newt_entry_get_value', + 'newt_entry_set', + 'newt_entry_set_filter', + 'newt_entry_set_flags', + 'newt_form', + 'newt_form_add_component', + 'newt_form_add_components', + 'newt_form_add_hot_key', + 'newt_form_destroy', + 'newt_form_get_current', + 'newt_form_run', + 'newt_form_set_background', + 'newt_form_set_height', + 'newt_form_set_size', + 'newt_form_set_timer', + 'newt_form_set_width', + 'newt_form_watch_fd', + 'newt_grid_add_components_to_form', + 'newt_grid_basic_window', + 'newt_grid_free', + 'newt_grid_get_size', + 'newt_grid_h_close_stacked', + 'newt_grid_h_stacked', + 'newt_grid_place', + 'newt_grid_set_field', + 'newt_grid_simple_window', + 'newt_grid_v_close_stacked', + 'newt_grid_v_stacked', + 'newt_grid_wrapped_window', + 'newt_grid_wrapped_window_at', + 'newt_label', + 'newt_label_set_text', + 'newt_listbox', + 'newt_listbox_append_entry', + 'newt_listbox_clear', + 'newt_listbox_clear_selection', + 'newt_listbox_delete_entry', + 'newt_listbox_get_current', + 'newt_listbox_get_selection', + 'newt_listbox_insert_entry', + 'newt_listbox_item_count', + 'newt_listbox_select_item', + 'newt_listbox_set_current', + 'newt_listbox_set_current_by_key', + 'newt_listbox_set_data', + 'newt_listbox_set_entry', + 'newt_listbox_set_width', + 'newt_listitem', + 'newt_listitem_get_data', + 'newt_listitem_set', + 'newt_radio_get_current', + 'newt_radiobutton', + 'newt_run_form', + 'newt_scale', + 'newt_scale_set', + 'newt_scrollbar_set', + 'newt_textbox', + 'newt_textbox_get_num_lines', + 'newt_textbox_reflowed', + 'newt_textbox_set_height', + 'newt_textbox_set_text', + 'newt_vertical_scrollbar', + 'oci_bind_array_by_name', + 'oci_bind_by_name', + 'oci_cancel', + 'oci_close', + 'oci_commit', + 'oci_connect', + 'oci_define_by_name', + 'oci_error', + 'oci_execute', + 'oci_fetch', + 'oci_fetch_all', + 'oci_fetch_array', + 'oci_fetch_assoc', + 'oci_fetch_object', + 'oci_fetch_row', + 'oci_field_is_null', + 'oci_field_name', + 'oci_field_precision', + 'oci_field_scale', + 'oci_field_size', + 'oci_field_type', + 'oci_field_type_raw', + 'oci_free_cursor', + 'oci_free_statement', + 'oci_get_implicit_resultset', + 'oci_new_collection', + 'oci_new_connect', + 'oci_new_cursor', + 'oci_new_descriptor', + 'oci_num_fields', + 'oci_num_rows', + 'oci_parse', + 'oci_pconnect', + 'oci_register_taf_callback', + 'oci_result', + 'oci_rollback', + 'oci_server_version', + 'oci_set_action', + 'oci_set_client_identifier', + 'oci_set_client_info', + 'oci_set_module_name', + 'oci_set_prefetch', + 'oci_statement_type', + 'oci_unregister_taf_callback', + 'odbc_autocommit', + 'odbc_close', + 'odbc_columnprivileges', + 'odbc_columns', + 'odbc_commit', + 'odbc_connect', + 'odbc_cursor', + 'odbc_data_source', + 'odbc_do', + 'odbc_error', + 'odbc_errormsg', + 'odbc_exec', + 'odbc_execute', + 'odbc_fetch_array', + 'odbc_fetch_into', + 'odbc_fetch_row', + 'odbc_field_len', + 'odbc_field_name', + 'odbc_field_num', + 'odbc_field_precision', + 'odbc_field_scale', + 'odbc_field_type', + 'odbc_foreignkeys', + 'odbc_free_result', + 'odbc_gettypeinfo', + 'odbc_next_result', + 'odbc_num_fields', + 'odbc_num_rows', + 'odbc_pconnect', + 'odbc_prepare', + 'odbc_primarykeys', + 'odbc_procedurecolumns', + 'odbc_procedures', + 'odbc_result', + 'odbc_result_all', + 'odbc_rollback', + 'odbc_setoption', + 'odbc_specialcolumns', + 'odbc_statistics', + 'odbc_tableprivileges', + 'odbc_tables', + 'openal_buffer_create', + 'openal_buffer_data', + 'openal_buffer_destroy', + 'openal_buffer_get', + 'openal_buffer_loadwav', + 'openal_context_create', + 'openal_context_current', + 'openal_context_destroy', + 'openal_context_process', + 'openal_context_suspend', + 'openal_device_close', + 'openal_device_open', + 'openal_source_create', + 'openal_source_destroy', + 'openal_source_get', + 'openal_source_pause', + 'openal_source_play', + 'openal_source_rewind', + 'openal_source_set', + 'openal_source_stop', + 'openal_stream', + 'opendir', + 'openssl_csr_new', + 'openssl_dh_compute_key', + 'openssl_free_key', + 'openssl_pkey_export', + 'openssl_pkey_free', + 'openssl_pkey_get_details', + 'openssl_spki_new', + 'openssl_x509_free', + 'pclose', + 'pfsockopen', + 'pg_affected_rows', + 'pg_cancel_query', + 'pg_client_encoding', + 'pg_close', + 'pg_connect_poll', + 'pg_connection_busy', + 'pg_connection_reset', + 'pg_connection_status', + 'pg_consume_input', + 'pg_convert', + 'pg_copy_from', + 'pg_copy_to', + 'pg_dbname', + 'pg_delete', + 'pg_end_copy', + 'pg_escape_bytea', + 'pg_escape_identifier', + 'pg_escape_literal', + 'pg_escape_string', + 'pg_execute', + 'pg_fetch_all', + 'pg_fetch_all_columns', + 'pg_fetch_array', + 'pg_fetch_assoc', + 'pg_fetch_row', + 'pg_field_name', + 'pg_field_num', + 'pg_field_size', + 'pg_field_table', + 'pg_field_type', + 'pg_field_type_oid', + 'pg_flush', + 'pg_free_result', + 'pg_get_notify', + 'pg_get_pid', + 'pg_get_result', + 'pg_host', + 'pg_insert', + 'pg_last_error', + 'pg_last_notice', + 'pg_last_oid', + 'pg_lo_close', + 'pg_lo_create', + 'pg_lo_export', + 'pg_lo_import', + 'pg_lo_open', + 'pg_lo_read', + 'pg_lo_read_all', + 'pg_lo_seek', + 'pg_lo_tell', + 'pg_lo_truncate', + 'pg_lo_unlink', + 'pg_lo_write', + 'pg_meta_data', + 'pg_num_fields', + 'pg_num_rows', + 'pg_options', + 'pg_parameter_status', + 'pg_ping', + 'pg_port', + 'pg_prepare', + 'pg_put_line', + 'pg_query', + 'pg_query_params', + 'pg_result_error', + 'pg_result_error_field', + 'pg_result_seek', + 'pg_result_status', + 'pg_select', + 'pg_send_execute', + 'pg_send_prepare', + 'pg_send_query', + 'pg_send_query_params', + 'pg_set_client_encoding', + 'pg_set_error_verbosity', + 'pg_socket', + 'pg_trace', + 'pg_transaction_status', + 'pg_tty', + 'pg_untrace', + 'pg_update', + 'pg_version', + 'php_user_filter::filter', + 'proc_close', + 'proc_get_status', + 'proc_terminate', + 'ps_add_bookmark', + 'ps_add_launchlink', + 'ps_add_locallink', + 'ps_add_note', + 'ps_add_pdflink', + 'ps_add_weblink', + 'ps_arc', + 'ps_arcn', + 'ps_begin_page', + 'ps_begin_pattern', + 'ps_begin_template', + 'ps_circle', + 'ps_clip', + 'ps_close', + 'ps_close_image', + 'ps_closepath', + 'ps_closepath_stroke', + 'ps_continue_text', + 'ps_curveto', + 'ps_delete', + 'ps_end_page', + 'ps_end_pattern', + 'ps_end_template', + 'ps_fill', + 'ps_fill_stroke', + 'ps_findfont', + 'ps_get_buffer', + 'ps_get_parameter', + 'ps_get_value', + 'ps_hyphenate', + 'ps_include_file', + 'ps_lineto', + 'ps_makespotcolor', + 'ps_moveto', + 'ps_new', + 'ps_open_file', + 'ps_open_image', + 'ps_open_image_file', + 'ps_open_memory_image', + 'ps_place_image', + 'ps_rect', + 'ps_restore', + 'ps_rotate', + 'ps_save', + 'ps_scale', + 'ps_set_border_color', + 'ps_set_border_dash', + 'ps_set_border_style', + 'ps_set_info', + 'ps_set_parameter', + 'ps_set_text_pos', + 'ps_set_value', + 'ps_setcolor', + 'ps_setdash', + 'ps_setflat', + 'ps_setfont', + 'ps_setgray', + 'ps_setlinecap', + 'ps_setlinejoin', + 'ps_setlinewidth', + 'ps_setmiterlimit', + 'ps_setoverprintmode', + 'ps_setpolydash', + 'ps_shading', + 'ps_shading_pattern', + 'ps_shfill', + 'ps_show', + 'ps_show2', + 'ps_show_boxed', + 'ps_show_xy', + 'ps_show_xy2', + 'ps_string_geometry', + 'ps_stringwidth', + 'ps_stroke', + 'ps_symbol', + 'ps_symbol_name', + 'ps_symbol_width', + 'ps_translate', + 'px_close', + 'px_create_fp', + 'px_date2string', + 'px_delete', + 'px_delete_record', + 'px_get_field', + 'px_get_info', + 'px_get_parameter', + 'px_get_record', + 'px_get_schema', + 'px_get_value', + 'px_insert_record', + 'px_new', + 'px_numfields', + 'px_numrecords', + 'px_open_fp', + 'px_put_record', + 'px_retrieve_record', + 'px_set_blob_file', + 'px_set_parameter', + 'px_set_tablename', + 'px_set_targetencoding', + 'px_set_value', + 'px_timestamp2string', + 'px_update_record', + 'radius_acct_open', + 'radius_add_server', + 'radius_auth_open', + 'radius_close', + 'radius_config', + 'radius_create_request', + 'radius_demangle', + 'radius_demangle_mppe_key', + 'radius_get_attr', + 'radius_put_addr', + 'radius_put_attr', + 'radius_put_int', + 'radius_put_string', + 'radius_put_vendor_addr', + 'radius_put_vendor_attr', + 'radius_put_vendor_int', + 'radius_put_vendor_string', + 'radius_request_authenticator', + 'radius_salt_encrypt_attr', + 'radius_send_request', + 'radius_server_secret', + 'radius_strerror', + 'readdir', + 'readfile', + 'recode_file', + 'rename', + 'rewind', + 'rewinddir', + 'rmdir', + 'rpm_close', + 'rpm_get_tag', + 'rpm_open', + 'sapi_windows_vt100_support', + 'scandir', + 'sem_acquire', + 'sem_get', + 'sem_release', + 'sem_remove', + 'set_file_buffer', + 'shm_attach', + 'shm_detach', + 'shm_get_var', + 'shm_has_var', + 'shm_put_var', + 'shm_remove', + 'shm_remove_var', + 'shmop_close', + 'shmop_delete', + 'shmop_open', + 'shmop_read', + 'shmop_size', + 'shmop_write', + 'socket_accept', + 'socket_addrinfo_bind', + 'socket_addrinfo_connect', + 'socket_addrinfo_explain', + 'socket_bind', + 'socket_clear_error', + 'socket_close', + 'socket_connect', + 'socket_export_stream', + 'socket_get_option', + 'socket_get_status', + 'socket_getopt', + 'socket_getpeername', + 'socket_getsockname', + 'socket_import_stream', + 'socket_last_error', + 'socket_listen', + 'socket_read', + 'socket_recv', + 'socket_recvfrom', + 'socket_recvmsg', + 'socket_send', + 'socket_sendmsg', + 'socket_sendto', + 'socket_set_block', + 'socket_set_blocking', + 'socket_set_nonblock', + 'socket_set_option', + 'socket_set_timeout', + 'socket_shutdown', + 'socket_write', + 'sqlite_close', + 'sqlite_fetch_string', + 'sqlite_has_more', + 'sqlite_open', + 'sqlite_popen', + 'sqlsrv_begin_transaction', + 'sqlsrv_cancel', + 'sqlsrv_client_info', + 'sqlsrv_close', + 'sqlsrv_commit', + 'sqlsrv_connect', + 'sqlsrv_execute', + 'sqlsrv_fetch', + 'sqlsrv_fetch_array', + 'sqlsrv_fetch_object', + 'sqlsrv_field_metadata', + 'sqlsrv_free_stmt', + 'sqlsrv_get_field', + 'sqlsrv_has_rows', + 'sqlsrv_next_result', + 'sqlsrv_num_fields', + 'sqlsrv_num_rows', + 'sqlsrv_prepare', + 'sqlsrv_query', + 'sqlsrv_rollback', + 'sqlsrv_rows_affected', + 'sqlsrv_send_stream_data', + 'sqlsrv_server_info', + 'ssh2_auth_agent', + 'ssh2_auth_hostbased_file', + 'ssh2_auth_none', + 'ssh2_auth_password', + 'ssh2_auth_pubkey_file', + 'ssh2_disconnect', + 'ssh2_exec', + 'ssh2_fetch_stream', + 'ssh2_fingerprint', + 'ssh2_methods_negotiated', + 'ssh2_publickey_add', + 'ssh2_publickey_init', + 'ssh2_publickey_list', + 'ssh2_publickey_remove', + 'ssh2_scp_recv', + 'ssh2_scp_send', + 'ssh2_sftp', + 'ssh2_sftp_chmod', + 'ssh2_sftp_lstat', + 'ssh2_sftp_mkdir', + 'ssh2_sftp_readlink', + 'ssh2_sftp_realpath', + 'ssh2_sftp_rename', + 'ssh2_sftp_rmdir', + 'ssh2_sftp_stat', + 'ssh2_sftp_symlink', + 'ssh2_sftp_unlink', + 'ssh2_shell', + 'ssh2_tunnel', + 'stomp_connect', + 'streamWrapper::stream_cast', + 'stream_bucket_append', + 'stream_bucket_make_writeable', + 'stream_bucket_new', + 'stream_bucket_prepend', + 'stream_context_create', + 'stream_context_get_default', + 'stream_context_get_options', + 'stream_context_get_params', + 'stream_context_set_default', + 'stream_context_set_params', + 'stream_copy_to_stream', + 'stream_encoding', + 'stream_filter_append', + 'stream_filter_prepend', + 'stream_filter_remove', + 'stream_get_contents', + 'stream_get_line', + 'stream_get_meta_data', + 'stream_isatty', + 'stream_set_blocking', + 'stream_set_chunk_size', + 'stream_set_read_buffer', + 'stream_set_timeout', + 'stream_set_write_buffer', + 'stream_socket_accept', + 'stream_socket_client', + 'stream_socket_enable_crypto', + 'stream_socket_get_name', + 'stream_socket_recvfrom', + 'stream_socket_sendto', + 'stream_socket_server', + 'stream_socket_shutdown', + 'stream_supports_lock', + 'svn_fs_abort_txn', + 'svn_fs_apply_text', + 'svn_fs_begin_txn2', + 'svn_fs_change_node_prop', + 'svn_fs_check_path', + 'svn_fs_contents_changed', + 'svn_fs_copy', + 'svn_fs_delete', + 'svn_fs_dir_entries', + 'svn_fs_file_contents', + 'svn_fs_file_length', + 'svn_fs_is_dir', + 'svn_fs_is_file', + 'svn_fs_make_dir', + 'svn_fs_make_file', + 'svn_fs_node_created_rev', + 'svn_fs_node_prop', + 'svn_fs_props_changed', + 'svn_fs_revision_prop', + 'svn_fs_revision_root', + 'svn_fs_txn_root', + 'svn_fs_youngest_rev', + 'svn_repos_create', + 'svn_repos_fs', + 'svn_repos_fs_begin_txn_for_commit', + 'svn_repos_fs_commit_txn', + 'svn_repos_open', + 'sybase_affected_rows', + 'sybase_close', + 'sybase_connect', + 'sybase_data_seek', + 'sybase_fetch_array', + 'sybase_fetch_assoc', + 'sybase_fetch_field', + 'sybase_fetch_object', + 'sybase_fetch_row', + 'sybase_field_seek', + 'sybase_free_result', + 'sybase_num_fields', + 'sybase_num_rows', + 'sybase_pconnect', + 'sybase_query', + 'sybase_result', + 'sybase_select_db', + 'sybase_set_message_handler', + 'sybase_unbuffered_query', + 'tmpfile', + 'udm_add_search_limit', + 'udm_alloc_agent', + 'udm_alloc_agent_array', + 'udm_cat_list', + 'udm_cat_path', + 'udm_check_charset', + 'udm_clear_search_limits', + 'udm_crc32', + 'udm_errno', + 'udm_error', + 'udm_find', + 'udm_free_agent', + 'udm_free_res', + 'udm_get_doc_count', + 'udm_get_res_field', + 'udm_get_res_param', + 'udm_hash32', + 'udm_load_ispell_data', + 'udm_set_agent_param', + 'unlink', + 'vfprintf', + 'w32api_init_dtype', + 'wddx_add_vars', + 'wddx_packet_end', + 'wddx_packet_start', + 'xml_get_current_byte_index', + 'xml_get_current_column_number', + 'xml_get_current_line_number', + 'xml_get_error_code', + 'xml_parse', + 'xml_parse_into_struct', + 'xml_parser_create', + 'xml_parser_create_ns', + 'xml_parser_free', + 'xml_parser_get_option', + 'xml_parser_set_option', + 'xml_set_character_data_handler', + 'xml_set_default_handler', + 'xml_set_element_handler', + 'xml_set_end_namespace_decl_handler', + 'xml_set_external_entity_ref_handler', + 'xml_set_notation_decl_handler', + 'xml_set_object', + 'xml_set_processing_instruction_handler', + 'xml_set_start_namespace_decl_handler', + 'xml_set_unparsed_entity_decl_handler', + 'xmlrpc_server_add_introspection_data', + 'xmlrpc_server_call_method', + 'xmlrpc_server_create', + 'xmlrpc_server_destroy', + 'xmlrpc_server_register_introspection_callback', + 'xmlrpc_server_register_method', + 'xmlwriter_end_attribute', + 'xmlwriter_end_cdata', + 'xmlwriter_end_comment', + 'xmlwriter_end_document', + 'xmlwriter_end_dtd', + 'xmlwriter_end_dtd_attlist', + 'xmlwriter_end_dtd_element', + 'xmlwriter_end_dtd_entity', + 'xmlwriter_end_element', + 'xmlwriter_end_pi', + 'xmlwriter_flush', + 'xmlwriter_full_end_element', + 'xmlwriter_open_memory', + 'xmlwriter_open_uri', + 'xmlwriter_output_memory', + 'xmlwriter_set_indent', + 'xmlwriter_set_indent_string', + 'xmlwriter_start_attribute', + 'xmlwriter_start_attribute_ns', + 'xmlwriter_start_cdata', + 'xmlwriter_start_comment', + 'xmlwriter_start_document', + 'xmlwriter_start_dtd', + 'xmlwriter_start_dtd_attlist', + 'xmlwriter_start_dtd_element', + 'xmlwriter_start_dtd_entity', + 'xmlwriter_start_element', + 'xmlwriter_start_element_ns', + 'xmlwriter_start_pi', + 'xmlwriter_text', + 'xmlwriter_write_attribute', + 'xmlwriter_write_attribute_ns', + 'xmlwriter_write_cdata', + 'xmlwriter_write_comment', + 'xmlwriter_write_dtd', + 'xmlwriter_write_dtd_attlist', + 'xmlwriter_write_dtd_element', + 'xmlwriter_write_dtd_entity', + 'xmlwriter_write_element', + 'xmlwriter_write_element_ns', + 'xmlwriter_write_pi', + 'xmlwriter_write_raw', + 'xslt_create', + 'yaz_addinfo', + 'yaz_ccl_conf', + 'yaz_ccl_parse', + 'yaz_close', + 'yaz_database', + 'yaz_element', + 'yaz_errno', + 'yaz_error', + 'yaz_es', + 'yaz_es_result', + 'yaz_get_option', + 'yaz_hits', + 'yaz_itemorder', + 'yaz_present', + 'yaz_range', + 'yaz_record', + 'yaz_scan', + 'yaz_scan_result', + 'yaz_schema', + 'yaz_search', + 'yaz_sort', + 'yaz_syntax', + 'zip_close', + 'zip_entry_close', + 'zip_entry_compressedsize', + 'zip_entry_compressionmethod', + 'zip_entry_filesize', + 'zip_entry_name', + 'zip_entry_open', + 'zip_entry_read', + 'zip_open', + 'zip_read', + ]; + } +} diff --git a/vendor/sebastian/type/ChangeLog.md b/vendor/sebastian/type/ChangeLog.md new file mode 100644 index 00000000..0691a9b1 --- /dev/null +++ b/vendor/sebastian/type/ChangeLog.md @@ -0,0 +1,169 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [3.2.1] - 2023-02-03 + +### Fixed + +* [#28](https://github.com/sebastianbergmann/type/pull/28): Potential undefined offset warning/notice + +## [3.2.0] - 2022-09-12 + +### Added + +* [#25](https://github.com/sebastianbergmann/type/issues/25): Support Disjunctive Normal Form types +* Added `ReflectionMapper::fromParameterTypes()` +* Added `IntersectionType::types()` and `UnionType::types()` +* Added `UnionType::containsIntersectionTypes()` + +## [3.1.0] - 2022-08-29 + +### Added + +* [#21](https://github.com/sebastianbergmann/type/issues/21): Support `true` as stand-alone type + +## [3.0.0] - 2022-03-15 + +### Added + +* Support for intersection types introduced in PHP 8.1 +* Support for the `never` return type introduced in PHP 8.1 +* Added `Type::isCallable()`, `Type::isGenericObject()`, `Type::isIterable()`, `Type::isMixed()`, `Type::isNever()`, `Type::isNull()`, `Type::isObject()`, `Type::isSimple()`, `Type::isStatic()`, `Type::isUnion()`, `Type::isUnknown()`, and `Type::isVoid()` + +### Changed + +* Renamed `ReflectionMapper::fromMethodReturnType(ReflectionMethod $method)` to `ReflectionMapper::fromReturnType(ReflectionFunctionAbstract $functionOrMethod)` + +### Removed + +* Removed `Type::getReturnTypeDeclaration()` (use `Type::asString()` instead and prefix its result with `': '`) +* Removed `TypeName::getNamespaceName()` (use `TypeName::namespaceName()` instead) +* Removed `TypeName::getSimpleName()` (use `TypeName::simpleName()` instead) +* Removed `TypeName::getQualifiedName()` (use `TypeName::qualifiedName()` instead) + +## [2.3.4] - 2021-06-15 + +### Fixed + +* Fixed regression introduced in 2.3.3 + +## [2.3.3] - 2021-06-15 [YANKED] + +### Fixed + +* [#15](https://github.com/sebastianbergmann/type/issues/15): "false" pseudo type is not handled properly + +## [2.3.2] - 2021-06-04 + +### Fixed + +* Fixed handling of tentatively declared return types + +## [2.3.1] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\Type\Exception` now correctly extends `\Throwable` + +## [2.3.0] - 2020-10-06 + +### Added + +* [#14](https://github.com/sebastianbergmann/type/issues/14): Support for `static` return type that is introduced in PHP 8 + +## [2.2.2] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [2.2.1] - 2020-07-05 + +### Fixed + +* Fixed handling of `mixed` type in `ReflectionMapper::fromMethodReturnType()` + +## [2.2.0] - 2020-07-05 + +### Added + +* Added `MixedType` object for representing PHP 8's `mixed` type + +## [2.1.1] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [2.1.0] - 2020-06-01 + +### Added + +* Added `UnionType` object for representing PHP 8's Union Types +* Added `ReflectionMapper::fromMethodReturnType()` for mapping `\ReflectionMethod::getReturnType()` to a `Type` object +* Added `Type::name()` for retrieving the name of a type +* Added `Type::asString()` for retrieving a textual representation of a type + +### Changed + +* Deprecated `Type::getReturnTypeDeclaration()` (use `Type::asString()` instead and prefix its result with `': '`) +* Deprecated `TypeName::getNamespaceName()` (use `TypeName::namespaceName()` instead) +* Deprecated `TypeName::getSimpleName()` (use `TypeName::simpleName()` instead) +* Deprecated `TypeName::getQualifiedName()` (use `TypeName::qualifiedName()` instead) + +## [2.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.2 + +## [1.1.3] - 2019-07-02 + +### Fixed + +* Fixed class name comparison in `ObjectType` to be case-insensitive + +## [1.1.2] - 2019-06-19 + +### Fixed + +* Fixed handling of `object` type + +## [1.1.1] - 2019-06-08 + +### Fixed + +* Fixed autoloading of `callback_function.php` fixture file + +## [1.1.0] - 2019-06-07 + +### Added + +* Added support for `callable` type +* Added support for `iterable` type + +## [1.0.0] - 2019-06-06 + +* Initial release based on [code contributed by Michel Hartmann to PHPUnit](https://github.com/sebastianbergmann/phpunit/pull/3673) + +[3.2.1]: https://github.com/sebastianbergmann/type/compare/3.2.0...3.2.1 +[3.2.0]: https://github.com/sebastianbergmann/type/compare/3.1.0...3.2.0 +[3.1.0]: https://github.com/sebastianbergmann/type/compare/3.0.0...3.1.0 +[3.0.0]: https://github.com/sebastianbergmann/type/compare/2.3.4...3.0.0 +[2.3.4]: https://github.com/sebastianbergmann/type/compare/ca39369c41313ed12c071ed38ecda8fcdb248859...2.3.4 +[2.3.3]: https://github.com/sebastianbergmann/type/compare/2.3.2...ca39369c41313ed12c071ed38ecda8fcdb248859 +[2.3.2]: https://github.com/sebastianbergmann/type/compare/2.3.1...2.3.2 +[2.3.1]: https://github.com/sebastianbergmann/type/compare/2.3.0...2.3.1 +[2.3.0]: https://github.com/sebastianbergmann/type/compare/2.2.2...2.3.0 +[2.2.2]: https://github.com/sebastianbergmann/type/compare/2.2.1...2.2.2 +[2.2.1]: https://github.com/sebastianbergmann/type/compare/2.2.0...2.2.1 +[2.2.0]: https://github.com/sebastianbergmann/type/compare/2.1.1...2.2.0 +[2.1.1]: https://github.com/sebastianbergmann/type/compare/2.1.0...2.1.1 +[2.1.0]: https://github.com/sebastianbergmann/type/compare/2.0.0...2.1.0 +[2.0.0]: https://github.com/sebastianbergmann/type/compare/1.1.3...2.0.0 +[1.1.3]: https://github.com/sebastianbergmann/type/compare/1.1.2...1.1.3 +[1.1.2]: https://github.com/sebastianbergmann/type/compare/1.1.1...1.1.2 +[1.1.1]: https://github.com/sebastianbergmann/type/compare/1.1.0...1.1.1 +[1.1.0]: https://github.com/sebastianbergmann/type/compare/1.0.0...1.1.0 +[1.0.0]: https://github.com/sebastianbergmann/type/compare/ff74aa41746bd8d10e931843ebf37d42da513ede...1.0.0 diff --git a/vendor/sebastian/type/LICENSE b/vendor/sebastian/type/LICENSE new file mode 100644 index 00000000..f4e4a328 --- /dev/null +++ b/vendor/sebastian/type/LICENSE @@ -0,0 +1,33 @@ +sebastian/type + +Copyright (c) 2019-2022, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/type/README.md b/vendor/sebastian/type/README.md new file mode 100644 index 00000000..1036ce7a --- /dev/null +++ b/vendor/sebastian/type/README.md @@ -0,0 +1,20 @@ +# sebastian/type + +[![CI Status](https://github.com/sebastianbergmann/type/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/type/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/type/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/type) + +Collection of value objects that represent the types of the PHP type system. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/type +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/type +``` diff --git a/vendor/sebastian/type/composer.json b/vendor/sebastian/type/composer.json new file mode 100644 index 00000000..a0865c93 --- /dev/null +++ b/vendor/sebastian/type/composer.json @@ -0,0 +1,50 @@ +{ + "name": "sebastian/type", + "description": "Collection of value objects that represent the types of the PHP type system", + "type": "library", + "homepage": "https://github.com/sebastianbergmann/type", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues" + }, + "prefer-stable": true, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture" + ], + "files": [ + "tests/_fixture/callback_function.php", + "tests/_fixture/functions_that_declare_return_types.php" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + } +} diff --git a/vendor/sebastian/type/src/Parameter.php b/vendor/sebastian/type/src/Parameter.php new file mode 100644 index 00000000..1adb061e --- /dev/null +++ b/vendor/sebastian/type/src/Parameter.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class Parameter +{ + /** + * @psalm-var non-empty-string + */ + private $name; + + /** + * @var Type + */ + private $type; + + /** + * @psalm-param non-empty-string $name + */ + public function __construct(string $name, Type $type) + { + $this->name = $name; + $this->type = $type; + } + + public function name(): string + { + return $this->name; + } + + public function type(): Type + { + return $this->type; + } +} diff --git a/vendor/sebastian/type/src/ReflectionMapper.php b/vendor/sebastian/type/src/ReflectionMapper.php new file mode 100644 index 00000000..32099b4b --- /dev/null +++ b/vendor/sebastian/type/src/ReflectionMapper.php @@ -0,0 +1,184 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function assert; +use ReflectionFunctionAbstract; +use ReflectionIntersectionType; +use ReflectionMethod; +use ReflectionNamedType; +use ReflectionType; +use ReflectionUnionType; + +final class ReflectionMapper +{ + /** + * @psalm-return list + */ + public function fromParameterTypes(ReflectionFunctionAbstract $functionOrMethod): array + { + $parameters = []; + + foreach ($functionOrMethod->getParameters() as $parameter) { + $name = $parameter->getName(); + + assert($name !== ''); + + if (!$parameter->hasType()) { + $parameters[] = new Parameter($name, new UnknownType); + + continue; + } + + $type = $parameter->getType(); + + if ($type instanceof ReflectionNamedType) { + $parameters[] = new Parameter( + $name, + $this->mapNamedType($type, $functionOrMethod) + ); + + continue; + } + + if ($type instanceof ReflectionUnionType) { + $parameters[] = new Parameter( + $name, + $this->mapUnionType($type, $functionOrMethod) + ); + + continue; + } + + if ($type instanceof ReflectionIntersectionType) { + $parameters[] = new Parameter( + $name, + $this->mapIntersectionType($type, $functionOrMethod) + ); + } + } + + return $parameters; + } + + public function fromReturnType(ReflectionFunctionAbstract $functionOrMethod): Type + { + if (!$this->hasReturnType($functionOrMethod)) { + return new UnknownType; + } + + $returnType = $this->returnType($functionOrMethod); + + assert($returnType instanceof ReflectionNamedType || $returnType instanceof ReflectionUnionType || $returnType instanceof ReflectionIntersectionType); + + if ($returnType instanceof ReflectionNamedType) { + return $this->mapNamedType($returnType, $functionOrMethod); + } + + if ($returnType instanceof ReflectionUnionType) { + return $this->mapUnionType($returnType, $functionOrMethod); + } + + if ($returnType instanceof ReflectionIntersectionType) { + return $this->mapIntersectionType($returnType, $functionOrMethod); + } + } + + private function mapNamedType(ReflectionNamedType $type, ReflectionFunctionAbstract $functionOrMethod): Type + { + if ($functionOrMethod instanceof ReflectionMethod && $type->getName() === 'self') { + return ObjectType::fromName( + $functionOrMethod->getDeclaringClass()->getName(), + $type->allowsNull() + ); + } + + if ($functionOrMethod instanceof ReflectionMethod && $type->getName() === 'static') { + return new StaticType( + TypeName::fromReflection($functionOrMethod->getDeclaringClass()), + $type->allowsNull() + ); + } + + if ($type->getName() === 'mixed') { + return new MixedType; + } + + if ($functionOrMethod instanceof ReflectionMethod && $type->getName() === 'parent') { + return ObjectType::fromName( + $functionOrMethod->getDeclaringClass()->getParentClass()->getName(), + $type->allowsNull() + ); + } + + return Type::fromName( + $type->getName(), + $type->allowsNull() + ); + } + + private function mapUnionType(ReflectionUnionType $type, ReflectionFunctionAbstract $functionOrMethod): Type + { + $types = []; + + foreach ($type->getTypes() as $_type) { + assert($_type instanceof ReflectionNamedType || $_type instanceof ReflectionIntersectionType); + + if ($_type instanceof ReflectionNamedType) { + $types[] = $this->mapNamedType($_type, $functionOrMethod); + + continue; + } + + $types[] = $this->mapIntersectionType($_type, $functionOrMethod); + } + + return new UnionType(...$types); + } + + private function mapIntersectionType(ReflectionIntersectionType $type, ReflectionFunctionAbstract $functionOrMethod): Type + { + $types = []; + + foreach ($type->getTypes() as $_type) { + assert($_type instanceof ReflectionNamedType); + + $types[] = $this->mapNamedType($_type, $functionOrMethod); + } + + return new IntersectionType(...$types); + } + + private function hasReturnType(ReflectionFunctionAbstract $functionOrMethod): bool + { + if ($functionOrMethod->hasReturnType()) { + return true; + } + + if (!method_exists($functionOrMethod, 'hasTentativeReturnType')) { + return false; + } + + return $functionOrMethod->hasTentativeReturnType(); + } + + private function returnType(ReflectionFunctionAbstract $functionOrMethod): ?ReflectionType + { + if ($functionOrMethod->hasReturnType()) { + return $functionOrMethod->getReturnType(); + } + + if (!method_exists($functionOrMethod, 'getTentativeReturnType')) { + return null; + } + + return $functionOrMethod->getTentativeReturnType(); + } +} diff --git a/vendor/sebastian/type/src/TypeName.php b/vendor/sebastian/type/src/TypeName.php new file mode 100644 index 00000000..17d477cf --- /dev/null +++ b/vendor/sebastian/type/src/TypeName.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function array_pop; +use function explode; +use function implode; +use function substr; +use ReflectionClass; + +final class TypeName +{ + /** + * @var ?string + */ + private $namespaceName; + + /** + * @var string + */ + private $simpleName; + + public static function fromQualifiedName(string $fullClassName): self + { + if ($fullClassName[0] === '\\') { + $fullClassName = substr($fullClassName, 1); + } + + $classNameParts = explode('\\', $fullClassName); + + $simpleName = array_pop($classNameParts); + $namespaceName = implode('\\', $classNameParts); + + return new self($namespaceName, $simpleName); + } + + public static function fromReflection(ReflectionClass $type): self + { + return new self( + $type->getNamespaceName(), + $type->getShortName() + ); + } + + public function __construct(?string $namespaceName, string $simpleName) + { + if ($namespaceName === '') { + $namespaceName = null; + } + + $this->namespaceName = $namespaceName; + $this->simpleName = $simpleName; + } + + public function namespaceName(): ?string + { + return $this->namespaceName; + } + + public function simpleName(): string + { + return $this->simpleName; + } + + public function qualifiedName(): string + { + return $this->namespaceName === null + ? $this->simpleName + : $this->namespaceName . '\\' . $this->simpleName; + } + + public function isNamespaced(): bool + { + return $this->namespaceName !== null; + } +} diff --git a/vendor/sebastian/type/src/exception/Exception.php b/vendor/sebastian/type/src/exception/Exception.php new file mode 100644 index 00000000..e0e7ee57 --- /dev/null +++ b/vendor/sebastian/type/src/exception/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/vendor/sebastian/type/src/exception/RuntimeException.php b/vendor/sebastian/type/src/exception/RuntimeException.php new file mode 100644 index 00000000..4dfea6a6 --- /dev/null +++ b/vendor/sebastian/type/src/exception/RuntimeException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/vendor/sebastian/type/src/type/CallableType.php b/vendor/sebastian/type/src/type/CallableType.php new file mode 100644 index 00000000..d44fb0ca --- /dev/null +++ b/vendor/sebastian/type/src/type/CallableType.php @@ -0,0 +1,212 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function assert; +use function class_exists; +use function count; +use function explode; +use function function_exists; +use function is_array; +use function is_object; +use function is_string; +use Closure; +use ReflectionClass; +use ReflectionException; +use ReflectionObject; + +final class CallableType extends Type +{ + /** + * @var bool + */ + private $allowsNull; + + public function __construct(bool $nullable) + { + $this->allowsNull = $nullable; + } + + /** + * @throws RuntimeException + */ + public function isAssignable(Type $other): bool + { + if ($this->allowsNull && $other instanceof NullType) { + return true; + } + + if ($other instanceof self) { + return true; + } + + if ($other instanceof ObjectType) { + if ($this->isClosure($other)) { + return true; + } + + if ($this->hasInvokeMethod($other)) { + return true; + } + } + + if ($other instanceof SimpleType) { + if ($this->isFunction($other)) { + return true; + } + + if ($this->isClassCallback($other)) { + return true; + } + + if ($this->isObjectCallback($other)) { + return true; + } + } + + return false; + } + + public function name(): string + { + return 'callable'; + } + + public function allowsNull(): bool + { + return $this->allowsNull; + } + + /** + * @psalm-assert-if-true CallableType $this + */ + public function isCallable(): bool + { + return true; + } + + private function isClosure(ObjectType $type): bool + { + return !$type->className()->isNamespaced() && $type->className()->simpleName() === Closure::class; + } + + /** + * @throws RuntimeException + */ + private function hasInvokeMethod(ObjectType $type): bool + { + $className = $type->className()->qualifiedName(); + assert(class_exists($className)); + + try { + $class = new ReflectionClass($className); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new RuntimeException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + // @codeCoverageIgnoreEnd + } + + if ($class->hasMethod('__invoke')) { + return true; + } + + return false; + } + + private function isFunction(SimpleType $type): bool + { + if (!is_string($type->value())) { + return false; + } + + return function_exists($type->value()); + } + + private function isObjectCallback(SimpleType $type): bool + { + if (!is_array($type->value())) { + return false; + } + + if (count($type->value()) !== 2) { + return false; + } + + if (!isset($type->value()[0], $type->value()[1])) { + return false; + } + + if (!is_object($type->value()[0]) || !is_string($type->value()[1])) { + return false; + } + + [$object, $methodName] = $type->value(); + + return (new ReflectionObject($object))->hasMethod($methodName); + } + + private function isClassCallback(SimpleType $type): bool + { + if (!is_string($type->value()) && !is_array($type->value())) { + return false; + } + + if (is_string($type->value())) { + if (strpos($type->value(), '::') === false) { + return false; + } + + [$className, $methodName] = explode('::', $type->value()); + } + + if (is_array($type->value())) { + if (count($type->value()) !== 2) { + return false; + } + + if (!isset($type->value()[0], $type->value()[1])) { + return false; + } + + if (!is_string($type->value()[0]) || !is_string($type->value()[1])) { + return false; + } + + [$className, $methodName] = $type->value(); + } + + assert(isset($className) && is_string($className) && class_exists($className)); + assert(isset($methodName) && is_string($methodName)); + + try { + $class = new ReflectionClass($className); + + if ($class->hasMethod($methodName)) { + $method = $class->getMethod($methodName); + + return $method->isPublic() && $method->isStatic(); + } + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new RuntimeException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + // @codeCoverageIgnoreEnd + } + + return false; + } +} diff --git a/vendor/sebastian/type/src/type/FalseType.php b/vendor/sebastian/type/src/type/FalseType.php new file mode 100644 index 00000000..f417fb69 --- /dev/null +++ b/vendor/sebastian/type/src/type/FalseType.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class FalseType extends Type +{ + public function isAssignable(Type $other): bool + { + if ($other instanceof self) { + return true; + } + + return $other instanceof SimpleType && + $other->name() === 'bool' && + $other->value() === false; + } + + public function name(): string + { + return 'false'; + } + + public function allowsNull(): bool + { + return false; + } + + /** + * @psalm-assert-if-true FalseType $this + */ + public function isFalse(): bool + { + return true; + } +} diff --git a/vendor/sebastian/type/src/type/GenericObjectType.php b/vendor/sebastian/type/src/type/GenericObjectType.php new file mode 100644 index 00000000..d06963f0 --- /dev/null +++ b/vendor/sebastian/type/src/type/GenericObjectType.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class GenericObjectType extends Type +{ + /** + * @var bool + */ + private $allowsNull; + + public function __construct(bool $nullable) + { + $this->allowsNull = $nullable; + } + + public function isAssignable(Type $other): bool + { + if ($this->allowsNull && $other instanceof NullType) { + return true; + } + + if (!$other instanceof ObjectType) { + return false; + } + + return true; + } + + public function name(): string + { + return 'object'; + } + + public function allowsNull(): bool + { + return $this->allowsNull; + } + + /** + * @psalm-assert-if-true GenericObjectType $this + */ + public function isGenericObject(): bool + { + return true; + } +} diff --git a/vendor/sebastian/type/src/type/IntersectionType.php b/vendor/sebastian/type/src/type/IntersectionType.php new file mode 100644 index 00000000..2e133940 --- /dev/null +++ b/vendor/sebastian/type/src/type/IntersectionType.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function assert; +use function count; +use function implode; +use function in_array; +use function sort; + +final class IntersectionType extends Type +{ + /** + * @psalm-var non-empty-list + */ + private $types; + + /** + * @throws RuntimeException + */ + public function __construct(Type ...$types) + { + $this->ensureMinimumOfTwoTypes(...$types); + $this->ensureOnlyValidTypes(...$types); + $this->ensureNoDuplicateTypes(...$types); + + $this->types = $types; + } + + public function isAssignable(Type $other): bool + { + return $other->isObject(); + } + + public function asString(): string + { + return $this->name(); + } + + public function name(): string + { + $types = []; + + foreach ($this->types as $type) { + $types[] = $type->name(); + } + + sort($types); + + return implode('&', $types); + } + + public function allowsNull(): bool + { + return false; + } + + /** + * @psalm-assert-if-true IntersectionType $this + */ + public function isIntersection(): bool + { + return true; + } + + /** + * @psalm-return non-empty-list + */ + public function types(): array + { + return $this->types; + } + + /** + * @throws RuntimeException + */ + private function ensureMinimumOfTwoTypes(Type ...$types): void + { + if (count($types) < 2) { + throw new RuntimeException( + 'An intersection type must be composed of at least two types' + ); + } + } + + /** + * @throws RuntimeException + */ + private function ensureOnlyValidTypes(Type ...$types): void + { + foreach ($types as $type) { + if (!$type->isObject()) { + throw new RuntimeException( + 'An intersection type can only be composed of interfaces and classes' + ); + } + } + } + + /** + * @throws RuntimeException + */ + private function ensureNoDuplicateTypes(Type ...$types): void + { + $names = []; + + foreach ($types as $type) { + assert($type instanceof ObjectType); + + $classQualifiedName = $type->className()->qualifiedName(); + + if (in_array($classQualifiedName, $names, true)) { + throw new RuntimeException('An intersection type must not contain duplicate types'); + } + + $names[] = $classQualifiedName; + } + } +} diff --git a/vendor/sebastian/type/src/type/IterableType.php b/vendor/sebastian/type/src/type/IterableType.php new file mode 100644 index 00000000..7b2a58fa --- /dev/null +++ b/vendor/sebastian/type/src/type/IterableType.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function assert; +use function class_exists; +use function is_iterable; +use ReflectionClass; +use ReflectionException; + +final class IterableType extends Type +{ + /** + * @var bool + */ + private $allowsNull; + + public function __construct(bool $nullable) + { + $this->allowsNull = $nullable; + } + + /** + * @throws RuntimeException + */ + public function isAssignable(Type $other): bool + { + if ($this->allowsNull && $other instanceof NullType) { + return true; + } + + if ($other instanceof self) { + return true; + } + + if ($other instanceof SimpleType) { + return is_iterable($other->value()); + } + + if ($other instanceof ObjectType) { + $className = $other->className()->qualifiedName(); + assert(class_exists($className)); + + try { + return (new ReflectionClass($className))->isIterable(); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new RuntimeException( + $e->getMessage(), + (int) $e->getCode(), + $e + ); + // @codeCoverageIgnoreEnd + } + } + + return false; + } + + public function name(): string + { + return 'iterable'; + } + + public function allowsNull(): bool + { + return $this->allowsNull; + } + + /** + * @psalm-assert-if-true IterableType $this + */ + public function isIterable(): bool + { + return true; + } +} diff --git a/vendor/sebastian/type/src/type/MixedType.php b/vendor/sebastian/type/src/type/MixedType.php new file mode 100644 index 00000000..a1412e45 --- /dev/null +++ b/vendor/sebastian/type/src/type/MixedType.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class MixedType extends Type +{ + public function isAssignable(Type $other): bool + { + return !$other instanceof VoidType; + } + + public function asString(): string + { + return 'mixed'; + } + + public function name(): string + { + return 'mixed'; + } + + public function allowsNull(): bool + { + return true; + } + + /** + * @psalm-assert-if-true MixedType $this + */ + public function isMixed(): bool + { + return true; + } +} diff --git a/vendor/sebastian/type/src/type/NeverType.php b/vendor/sebastian/type/src/type/NeverType.php new file mode 100644 index 00000000..6c144743 --- /dev/null +++ b/vendor/sebastian/type/src/type/NeverType.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class NeverType extends Type +{ + public function isAssignable(Type $other): bool + { + return $other instanceof self; + } + + public function name(): string + { + return 'never'; + } + + public function allowsNull(): bool + { + return false; + } + + /** + * @psalm-assert-if-true NeverType $this + */ + public function isNever(): bool + { + return true; + } +} diff --git a/vendor/sebastian/type/src/type/NullType.php b/vendor/sebastian/type/src/type/NullType.php new file mode 100644 index 00000000..93834eab --- /dev/null +++ b/vendor/sebastian/type/src/type/NullType.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class NullType extends Type +{ + public function isAssignable(Type $other): bool + { + return !($other instanceof VoidType); + } + + public function name(): string + { + return 'null'; + } + + public function asString(): string + { + return 'null'; + } + + public function allowsNull(): bool + { + return true; + } + + /** + * @psalm-assert-if-true NullType $this + */ + public function isNull(): bool + { + return true; + } +} diff --git a/vendor/sebastian/type/src/type/ObjectType.php b/vendor/sebastian/type/src/type/ObjectType.php new file mode 100644 index 00000000..44febb27 --- /dev/null +++ b/vendor/sebastian/type/src/type/ObjectType.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function is_subclass_of; +use function strcasecmp; + +final class ObjectType extends Type +{ + /** + * @var TypeName + */ + private $className; + + /** + * @var bool + */ + private $allowsNull; + + public function __construct(TypeName $className, bool $allowsNull) + { + $this->className = $className; + $this->allowsNull = $allowsNull; + } + + public function isAssignable(Type $other): bool + { + if ($this->allowsNull && $other instanceof NullType) { + return true; + } + + if ($other instanceof self) { + if (0 === strcasecmp($this->className->qualifiedName(), $other->className->qualifiedName())) { + return true; + } + + if (is_subclass_of($other->className->qualifiedName(), $this->className->qualifiedName(), true)) { + return true; + } + } + + return false; + } + + public function name(): string + { + return $this->className->qualifiedName(); + } + + public function allowsNull(): bool + { + return $this->allowsNull; + } + + public function className(): TypeName + { + return $this->className; + } + + /** + * @psalm-assert-if-true ObjectType $this + */ + public function isObject(): bool + { + return true; + } +} diff --git a/vendor/sebastian/type/src/type/SimpleType.php b/vendor/sebastian/type/src/type/SimpleType.php new file mode 100644 index 00000000..4dce75da --- /dev/null +++ b/vendor/sebastian/type/src/type/SimpleType.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function strtolower; + +final class SimpleType extends Type +{ + /** + * @var string + */ + private $name; + + /** + * @var bool + */ + private $allowsNull; + + /** + * @var mixed + */ + private $value; + + public function __construct(string $name, bool $nullable, $value = null) + { + $this->name = $this->normalize($name); + $this->allowsNull = $nullable; + $this->value = $value; + } + + public function isAssignable(Type $other): bool + { + if ($this->allowsNull && $other instanceof NullType) { + return true; + } + + if ($this->name === 'bool' && $other->name() === 'true') { + return true; + } + + if ($this->name === 'bool' && $other->name() === 'false') { + return true; + } + + if ($other instanceof self) { + return $this->name === $other->name; + } + + return false; + } + + public function name(): string + { + return $this->name; + } + + public function allowsNull(): bool + { + return $this->allowsNull; + } + + public function value() + { + return $this->value; + } + + /** + * @psalm-assert-if-true SimpleType $this + */ + public function isSimple(): bool + { + return true; + } + + private function normalize(string $name): string + { + $name = strtolower($name); + + switch ($name) { + case 'boolean': + return 'bool'; + + case 'real': + case 'double': + return 'float'; + + case 'integer': + return 'int'; + + case '[]': + return 'array'; + + default: + return $name; + } + } +} diff --git a/vendor/sebastian/type/src/type/StaticType.php b/vendor/sebastian/type/src/type/StaticType.php new file mode 100644 index 00000000..cbc13f5f --- /dev/null +++ b/vendor/sebastian/type/src/type/StaticType.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class StaticType extends Type +{ + /** + * @var TypeName + */ + private $className; + + /** + * @var bool + */ + private $allowsNull; + + public function __construct(TypeName $className, bool $allowsNull) + { + $this->className = $className; + $this->allowsNull = $allowsNull; + } + + public function isAssignable(Type $other): bool + { + if ($this->allowsNull && $other instanceof NullType) { + return true; + } + + if (!$other instanceof ObjectType) { + return false; + } + + if (0 === strcasecmp($this->className->qualifiedName(), $other->className()->qualifiedName())) { + return true; + } + + if (is_subclass_of($other->className()->qualifiedName(), $this->className->qualifiedName(), true)) { + return true; + } + + return false; + } + + public function name(): string + { + return 'static'; + } + + public function allowsNull(): bool + { + return $this->allowsNull; + } + + /** + * @psalm-assert-if-true StaticType $this + */ + public function isStatic(): bool + { + return true; + } +} diff --git a/vendor/sebastian/type/src/type/TrueType.php b/vendor/sebastian/type/src/type/TrueType.php new file mode 100644 index 00000000..94e5be99 --- /dev/null +++ b/vendor/sebastian/type/src/type/TrueType.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class TrueType extends Type +{ + public function isAssignable(Type $other): bool + { + if ($other instanceof self) { + return true; + } + + return $other instanceof SimpleType && + $other->name() === 'bool' && + $other->value() === true; + } + + public function name(): string + { + return 'true'; + } + + public function allowsNull(): bool + { + return false; + } + + /** + * @psalm-assert-if-true TrueType $this + */ + public function isTrue(): bool + { + return true; + } +} diff --git a/vendor/sebastian/type/src/type/Type.php b/vendor/sebastian/type/src/type/Type.php new file mode 100644 index 00000000..e7536683 --- /dev/null +++ b/vendor/sebastian/type/src/type/Type.php @@ -0,0 +1,226 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use const PHP_VERSION; +use function get_class; +use function gettype; +use function strtolower; +use function version_compare; + +abstract class Type +{ + public static function fromValue($value, bool $allowsNull): self + { + if ($allowsNull === false) { + if ($value === true) { + return new TrueType; + } + + if ($value === false) { + return new FalseType; + } + } + + $typeName = gettype($value); + + if ($typeName === 'object') { + return new ObjectType(TypeName::fromQualifiedName(get_class($value)), $allowsNull); + } + + $type = self::fromName($typeName, $allowsNull); + + if ($type instanceof SimpleType) { + $type = new SimpleType($typeName, $allowsNull, $value); + } + + return $type; + } + + public static function fromName(string $typeName, bool $allowsNull): self + { + if (version_compare(PHP_VERSION, '8.1.0-dev', '>=') && strtolower($typeName) === 'never') { + return new NeverType; + } + + switch (strtolower($typeName)) { + case 'callable': + return new CallableType($allowsNull); + + case 'true': + return new TrueType; + + case 'false': + return new FalseType; + + case 'iterable': + return new IterableType($allowsNull); + + case 'null': + return new NullType; + + case 'object': + return new GenericObjectType($allowsNull); + + case 'unknown type': + return new UnknownType; + + case 'void': + return new VoidType; + + case 'array': + case 'bool': + case 'boolean': + case 'double': + case 'float': + case 'int': + case 'integer': + case 'real': + case 'resource': + case 'resource (closed)': + case 'string': + return new SimpleType($typeName, $allowsNull); + + default: + return new ObjectType(TypeName::fromQualifiedName($typeName), $allowsNull); + } + } + + public function asString(): string + { + return ($this->allowsNull() ? '?' : '') . $this->name(); + } + + /** + * @psalm-assert-if-true CallableType $this + */ + public function isCallable(): bool + { + return false; + } + + /** + * @psalm-assert-if-true TrueType $this + */ + public function isTrue(): bool + { + return false; + } + + /** + * @psalm-assert-if-true FalseType $this + */ + public function isFalse(): bool + { + return false; + } + + /** + * @psalm-assert-if-true GenericObjectType $this + */ + public function isGenericObject(): bool + { + return false; + } + + /** + * @psalm-assert-if-true IntersectionType $this + */ + public function isIntersection(): bool + { + return false; + } + + /** + * @psalm-assert-if-true IterableType $this + */ + public function isIterable(): bool + { + return false; + } + + /** + * @psalm-assert-if-true MixedType $this + */ + public function isMixed(): bool + { + return false; + } + + /** + * @psalm-assert-if-true NeverType $this + */ + public function isNever(): bool + { + return false; + } + + /** + * @psalm-assert-if-true NullType $this + */ + public function isNull(): bool + { + return false; + } + + /** + * @psalm-assert-if-true ObjectType $this + */ + public function isObject(): bool + { + return false; + } + + /** + * @psalm-assert-if-true SimpleType $this + */ + public function isSimple(): bool + { + return false; + } + + /** + * @psalm-assert-if-true StaticType $this + */ + public function isStatic(): bool + { + return false; + } + + /** + * @psalm-assert-if-true UnionType $this + */ + public function isUnion(): bool + { + return false; + } + + /** + * @psalm-assert-if-true UnknownType $this + */ + public function isUnknown(): bool + { + return false; + } + + /** + * @psalm-assert-if-true VoidType $this + */ + public function isVoid(): bool + { + return false; + } + + abstract public function isAssignable(self $other): bool; + + abstract public function name(): string; + + abstract public function allowsNull(): bool; +} diff --git a/vendor/sebastian/type/src/type/UnionType.php b/vendor/sebastian/type/src/type/UnionType.php new file mode 100644 index 00000000..427729c5 --- /dev/null +++ b/vendor/sebastian/type/src/type/UnionType.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function count; +use function implode; +use function sort; + +final class UnionType extends Type +{ + /** + * @psalm-var non-empty-list + */ + private $types; + + /** + * @throws RuntimeException + */ + public function __construct(Type ...$types) + { + $this->ensureMinimumOfTwoTypes(...$types); + $this->ensureOnlyValidTypes(...$types); + + $this->types = $types; + } + + public function isAssignable(Type $other): bool + { + foreach ($this->types as $type) { + if ($type->isAssignable($other)) { + return true; + } + } + + return false; + } + + public function asString(): string + { + return $this->name(); + } + + public function name(): string + { + $types = []; + + foreach ($this->types as $type) { + if ($type->isIntersection()) { + $types[] = '(' . $type->name() . ')'; + + continue; + } + + $types[] = $type->name(); + } + + sort($types); + + return implode('|', $types); + } + + public function allowsNull(): bool + { + foreach ($this->types as $type) { + if ($type instanceof NullType) { + return true; + } + } + + return false; + } + + /** + * @psalm-assert-if-true UnionType $this + */ + public function isUnion(): bool + { + return true; + } + + public function containsIntersectionTypes(): bool + { + foreach ($this->types as $type) { + if ($type->isIntersection()) { + return true; + } + } + + return false; + } + + /** + * @psalm-return non-empty-list + */ + public function types(): array + { + return $this->types; + } + + /** + * @throws RuntimeException + */ + private function ensureMinimumOfTwoTypes(Type ...$types): void + { + if (count($types) < 2) { + throw new RuntimeException( + 'A union type must be composed of at least two types' + ); + } + } + + /** + * @throws RuntimeException + */ + private function ensureOnlyValidTypes(Type ...$types): void + { + foreach ($types as $type) { + if ($type instanceof UnknownType) { + throw new RuntimeException( + 'A union type must not be composed of an unknown type' + ); + } + + if ($type instanceof VoidType) { + throw new RuntimeException( + 'A union type must not be composed of a void type' + ); + } + } + } +} diff --git a/vendor/sebastian/type/src/type/UnknownType.php b/vendor/sebastian/type/src/type/UnknownType.php new file mode 100644 index 00000000..dc274407 --- /dev/null +++ b/vendor/sebastian/type/src/type/UnknownType.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class UnknownType extends Type +{ + public function isAssignable(Type $other): bool + { + return true; + } + + public function name(): string + { + return 'unknown type'; + } + + public function asString(): string + { + return ''; + } + + public function allowsNull(): bool + { + return true; + } + + /** + * @psalm-assert-if-true UnknownType $this + */ + public function isUnknown(): bool + { + return true; + } +} diff --git a/vendor/sebastian/type/src/type/VoidType.php b/vendor/sebastian/type/src/type/VoidType.php new file mode 100644 index 00000000..f740fe29 --- /dev/null +++ b/vendor/sebastian/type/src/type/VoidType.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class VoidType extends Type +{ + public function isAssignable(Type $other): bool + { + return $other instanceof self; + } + + public function name(): string + { + return 'void'; + } + + public function allowsNull(): bool + { + return false; + } + + /** + * @psalm-assert-if-true VoidType $this + */ + public function isVoid(): bool + { + return true; + } +} diff --git a/vendor/sebastian/version/.gitattributes b/vendor/sebastian/version/.gitattributes new file mode 100644 index 00000000..54b89530 --- /dev/null +++ b/vendor/sebastian/version/.gitattributes @@ -0,0 +1,4 @@ +/.github export-ignore +/.php_cs.dist export-ignore + +*.php diff=php diff --git a/vendor/sebastian/version/.gitignore b/vendor/sebastian/version/.gitignore new file mode 100644 index 00000000..ff5ec9a0 --- /dev/null +++ b/vendor/sebastian/version/.gitignore @@ -0,0 +1,2 @@ +/.php_cs.cache +/.idea diff --git a/vendor/sebastian/version/ChangeLog.md b/vendor/sebastian/version/ChangeLog.md new file mode 100644 index 00000000..10fd9a1a --- /dev/null +++ b/vendor/sebastian/version/ChangeLog.md @@ -0,0 +1,25 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [3.0.2] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [3.0.1] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [3.0.0] - 2020-01-21 + +### Removed + +* This component is no longer supported on PHP 7.1 and PHP 7.2 + +[3.0.2]: https://github.com/sebastianbergmann/version/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/version/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/version/compare/2.0.1...3.0.0 diff --git a/vendor/sebastian/version/LICENSE b/vendor/sebastian/version/LICENSE new file mode 100644 index 00000000..aa6bca29 --- /dev/null +++ b/vendor/sebastian/version/LICENSE @@ -0,0 +1,33 @@ +Version + +Copyright (c) 2013-2020, Sebastian Bergmann . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sebastian/version/README.md b/vendor/sebastian/version/README.md new file mode 100644 index 00000000..2864c812 --- /dev/null +++ b/vendor/sebastian/version/README.md @@ -0,0 +1,43 @@ +# Version + +**Version** is a library that helps with managing the version number of Git-hosted PHP projects. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + + composer require sebastian/version + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + + composer require --dev sebastian/version + +## Usage + +The constructor of the `SebastianBergmann\Version` class expects two parameters: + +* `$release` is the version number of the latest release (`X.Y.Z`, for instance) or the name of the release series (`X.Y`) when no release has been made from that branch / for that release series yet. +* `$path` is the path to the directory (or a subdirectory thereof) where the sourcecode of the project can be found. Simply passing `__DIR__` here usually suffices. + +Apart from the constructor, the `SebastianBergmann\Version` class has a single public method: `getVersion()`. + +Here is a contrived example that shows the basic usage: + + getVersion()); + ?> + + string(18) "3.7.10-17-g00f3408" + +When a new release is prepared, the string that is passed to the constructor as the first argument needs to be updated. + +### How SebastianBergmann\Version::getVersion() works + +* If `$path` is not (part of) a Git repository and `$release` is in `X.Y.Z` format then `$release` is returned as-is. +* If `$path` is not (part of) a Git repository and `$release` is in `X.Y` format then `$release` is returned suffixed with `-dev`. +* If `$path` is (part of) a Git repository and `$release` is in `X.Y.Z` format then the output of `git describe --tags` is returned as-is. +* If `$path` is (part of) a Git repository and `$release` is in `X.Y` format then a string is returned that begins with `X.Y` and ends with information from `git describe --tags`. diff --git a/vendor/sebastian/version/composer.json b/vendor/sebastian/version/composer.json new file mode 100644 index 00000000..e76dbf41 --- /dev/null +++ b/vendor/sebastian/version/composer.json @@ -0,0 +1,37 @@ +{ + "name": "sebastian/version", + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues" + }, + "config": { + "platform": { + "php": "7.3.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "prefer-stable": true, + "require": { + "php": ">=7.3" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + } +} diff --git a/vendor/sebastian/version/src/Version.php b/vendor/sebastian/version/src/Version.php new file mode 100644 index 00000000..53ae7894 --- /dev/null +++ b/vendor/sebastian/version/src/Version.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann; + +final class Version +{ + /** + * @var string + */ + private $path; + + /** + * @var string + */ + private $release; + + /** + * @var string + */ + private $version; + + public function __construct(string $release, string $path) + { + $this->release = $release; + $this->path = $path; + } + + public function getVersion(): string + { + if ($this->version === null) { + if (\substr_count($this->release, '.') + 1 === 3) { + $this->version = $this->release; + } else { + $this->version = $this->release . '-dev'; + } + + $git = $this->getGitInformation($this->path); + + if ($git) { + if (\substr_count($this->release, '.') + 1 === 3) { + $this->version = $git; + } else { + $git = \explode('-', $git); + + $this->version = $this->release . '-' . \end($git); + } + } + } + + return $this->version; + } + + /** + * @return bool|string + */ + private function getGitInformation(string $path) + { + if (!\is_dir($path . DIRECTORY_SEPARATOR . '.git')) { + return false; + } + + $process = \proc_open( + 'git describe --tags', + [ + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ], + $pipes, + $path + ); + + if (!\is_resource($process)) { + return false; + } + + $result = \trim(\stream_get_contents($pipes[1])); + + \fclose($pipes[1]); + \fclose($pipes[2]); + + $returnCode = \proc_close($process); + + if ($returnCode !== 0) { + return false; + } + + return $result; + } +} diff --git a/vendor/sirbrillig/phpcs-variable-analysis/LICENSE b/vendor/sirbrillig/phpcs-variable-analysis/LICENSE new file mode 100644 index 00000000..ba156525 --- /dev/null +++ b/vendor/sirbrillig/phpcs-variable-analysis/LICENSE @@ -0,0 +1,71 @@ +BSD Licence Agreement +----------------------------------------------------------------------- + +This software is available to you under the BSD license, +available in the LICENSE file accompanying this software. +You may obtain a copy of the License at + +http://www.opensource.org/licenses/bsd-license.php + +----------------------------------------------------------------------- + +Copyright (c) 2011, Sam Graham +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +----------------------------------------------------------------------- + +Portions of this sofware derived from work Copyright (c) 2010, Monotek d.o.o, +released under a BSD License available at: + +http://www.opensource.org/licenses/bsd-license.php + +----------------------------------------------------------------------- + +Portions of this software derived from work Copyright (c), 2006 Squiz +Pty Ltd (ABN 77 084 670 600), available under the following license: + +BSD Licence Agreement +----------------------------------------------------------------------- + +This software is available to you under the BSD license, +available in the LICENSE file accompanying this software. +You may obtain a copy of the License at + +http://matrix.squiz.net/developer/tools/php_cs/licence + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Copyright (c), 2006 Squiz Pty Ltd (ABN 77 084 670 600). +All rights reserved. diff --git a/vendor/sirbrillig/phpcs-variable-analysis/README.md b/vendor/sirbrillig/phpcs-variable-analysis/README.md new file mode 100644 index 00000000..25964559 --- /dev/null +++ b/vendor/sirbrillig/phpcs-variable-analysis/README.md @@ -0,0 +1,123 @@ +# PHP_CodeSniffer VariableAnalysis + +[![CS and QA Build Status](https://github.com/sirbrillig/phpcs-variable-analysis/actions/workflows/csqa.yml/badge.svg)](https://github.com/sirbrillig/phpcs-variable-analysis/actions/workflows/csqa.yml) +[![Test Build Status](https://github.com/sirbrillig/phpcs-variable-analysis/actions/workflows/test.yml/badge.svg)](https://github.com/sirbrillig/phpcs-variable-analysis/actions/workflows/test.yml) +[![Coverage Status](https://coveralls.io/repos/github/sirbrillig/phpcs-variable-analysis/badge.svg)](https://coveralls.io/github/sirbrillig/phpcs-variable-analysis) + +Plugin for PHP_CodeSniffer static analysis tool that adds analysis of problematic variable use. + +- Warns if variables are used without being defined. (Sniff code: `VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable`) +- Warns if variables are used inside `unset()` without being defined. (Sniff code: `VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedUnsetVariable`) +- Warns if variables are set or declared but never used. (Sniff code: `VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable`) +- Warns if `$this`, `self::$static_member`, `static::$static_member` is used outside class scope. (Sniff codes: `VariableAnalysis.CodeAnalysis.VariableAnalysis.SelfOutsideClass` or `VariableAnalysis.CodeAnalysis.VariableAnalysis.StaticOutsideClass`) + +## Installation + +### Requirements + +VariableAnalysis requires PHP 5.4 or higher and [PHP CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) version 3.5.6 or higher. + +### With PHPCS Composer Installer + +This is the easiest method. + +First, install [phpcodesniffer-composer-installer](https://github.com/PHPCSStandards/composer-installer) for your project if you have not already. This will also install PHPCS. + +``` +composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true +composer require --dev dealerdirect/phpcodesniffer-composer-installer +``` + +Then install these standards. + +``` +composer require --dev sirbrillig/phpcs-variable-analysis +``` + +You can then include the sniffs by adding a line like the following to [your phpcs.xml file](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#using-a-default-configuration-file). + +``` + +``` + +It should just work after that! + +### Standalone + +1. Install PHP_CodeSniffer (PHPCS) by following its [installation instructions](https://github.com/squizlabs/PHP_CodeSniffer#installation) (via Composer, Phar file, PEAR, or Git checkout). + + Do ensure that PHP_CodeSniffer's version matches our [requirements](#requirements). + +2. Install VariableAnalysis. Download either the zip or tar.gz file from [the VariableAnalysis latest release page](https://github.com/sirbrillig/phpcs-variable-analysis/releases/latest). Expand the file and rename the resulting directory to `phpcs-variable-analysis`. Move the directory to a place where you'd like to keep all your PHPCS standards. + +3. Add the paths of the newly installed standards to the [PHP_CodeSniffer installed_paths configuration](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options#setting-the-installed-standard-paths). The following command should append the new standards to your existing standards (be sure to supply the actual paths to the directories you created above). + + phpcs --config-set installed_paths "$(phpcs --config-show|grep installed_paths|awk '{ print $2 }'),/path/to/phpcs-variable-analysis" + + If you do not have any other standards installed, you can do this more easily (again, be sure to supply the actual paths): + + phpcs --config-set installed_paths /path/to/phpcs-variable-analysis + +## Customization + +There's a variety of options to customize the behaviour of VariableAnalysis, take a look at the included ruleset.xml.example for commented examples of a configuration. + +The available options are as follows: + +- `allowUnusedFunctionParameters` (bool, default `false`): if set to true, function arguments will never be marked as unused. +- `allowUnusedCaughtExceptions` (bool, default `true`): if set to true, caught Exception variables will never be marked as unused. +- `allowUnusedParametersBeforeUsed` (bool, default `true`): if set to true, unused function arguments will be ignored if they are followed by used function arguments. +- `allowUnusedVariablesBeforeRequire` (bool, default `false`): if set to true, variables defined before a `require`, `require_once`, `include`, or `include_once` will not be marked as unused. They may be intended for the required file. +- `allowUndefinedVariablesInFileScope` (bool, default `false`): if set to true, undefined variables in the file's top-level scope will never be marked as undefined. This can be useful for template files which use many global variables defined elsewhere. +- `allowUnusedVariablesInFileScope` (bool, default `false`): if set to true, unused variables in the file's top-level scope will never be marked as unused. This can be helpful when defining a lot of global variables to be used elsewhere. +- `validUnusedVariableNames` (string, default `null`): a space-separated list of names of placeholder variables that you want to ignore from unused variable warnings. For example, to ignore the variables `$junk` and `$unused`, this could be set to `'junk unused'`. +- `ignoreUnusedRegexp` (string, default `null`): a PHP regexp string (note that this requires explicit delimiters) for variables that you want to ignore from unused variable warnings. For example, to ignore the variables `$_junk` and `$_unused`, this could be set to `'/^_/'`. +- `validUndefinedVariableNames` (string, default `null`): a space-separated list of names of placeholder variables that you want to ignore from undefined variable warnings. For example, to ignore the variables `$post` and `$undefined`, this could be set to `'post undefined'`. This can be used in combination with `validUndefinedVariableRegexp`. +- `validUndefinedVariableRegexp` (string, default `null`): a PHP regexp string (note that this requires explicit delimiters) for variables that you want to ignore from undefined variable warnings. For example, to ignore the variables `$post` and `$undefined`, this could be set to `'/^(post|undefined)$/'`. This can be used in combination with `validUndefinedVariableNames`. +- `allowUnusedForeachVariables` (bool, default `true`): if set to true, unused values from the `key => value` syntax in a `foreach` loop will never be marked as unused. +- `sitePassByRefFunctions` (string, default `null`): a list of custom functions which pass in variables to be initialized by reference (eg `preg_match()`) and therefore should not require those variables to be defined ahead of time. The list is space separated and each entry is of the form `functionName:1,2`. The function name comes first followed by a colon and a comma-separated list of argument numbers (starting from 1) which should be considered variable definitions. The special value `...` in the arguments list will cause all arguments after the last number to be considered variable definitions. +- `allowWordPressPassByRefFunctions` (bool, default `false`): if set to true, a list of common WordPress pass-by-reference functions will be added to the list of PHP ones so that passing undefined variables to these functions (to be initialized by reference) will be allowed. + +To set these these options, you must use XML in your ruleset. For details, see the [phpcs customizable sniff properties page](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Customisable-Sniff-Properties). Here is an example that ignores all variables that start with an underscore: + +```xml + + + + + +``` + +## See Also + +- [ImportDetection](https://github.com/sirbrillig/phpcs-import-detection): A set of phpcs sniffs to look for unused or unimported symbols. +- [phpcs-changed](https://github.com/sirbrillig/phpcs-changed): Run phpcs on files, but only report warnings/errors from lines which were changed. + +## Original + +This was forked from the excellent work in https://github.com/illusori/PHP_Codesniffer-VariableAnalysis + +## Contributing + +Please open issues or PRs on this repository. + +Any changes should be accompanied by tests and should pass linting and static analysis. Please use phpdoc (rather than actual types) for declaring types since this must run in PHP 5.4. + +To run tests, make sure composer is installed, then run: + +``` +composer install # you only need to do this once +composer test +``` + +To run linting, use: + +``` +composer lint +``` + +To run static analysis, use: + +``` +composer phpstan +``` diff --git a/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/Constants.php b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/Constants.php new file mode 100644 index 00000000..95580c08 --- /dev/null +++ b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/Constants.php @@ -0,0 +1,260 @@ +> + */ + public static function getPassByReferenceFunctions() + { + return [ + '__soapCall' => [5], + 'addFunction' => [3], + 'addTask' => [3], + 'addTaskBackground' => [3], + 'addTaskHigh' => [3], + 'addTaskHighBackground' => [3], + 'addTaskLow' => [3], + 'addTaskLowBackground' => [3], + 'addTaskStatus' => [2], + 'apc_dec' => [3], + 'apc_fetch' => [2], + 'apc_inc' => [3], + 'apcu_dec' => [3], + 'apcu_fetch' => [2], + 'apcu_inc' => [3], + 'areConfusable' => [3], + 'arsort' => [1], + 'asort' => [1], + 'bindColumn' => [2], + 'bindParam' => [2], + 'bind_param' => [2, 3, '...'], + 'bind_result' => [1, 2, '...'], + 'call_user_method' => [2], + 'call_user_method_array' => [2], + 'curl_multi_exec' => [2], + 'curl_multi_info_read' => [2], + 'current' => [1], + 'dbplus_curr' => [2], + 'dbplus_first' => [2], + 'dbplus_info' => [3], + 'dbplus_last' => [2], + 'dbplus_next' => [2], + 'dbplus_prev' => [2], + 'dbplus_tremove' => [3], + 'dns_get_record' => [3, 4], + 'domxml_open_file' => [3], + 'domxml_open_mem' => [3], + 'each' => [1], + 'enchant_dict_quick_check' => [3], + 'end' => [1], + 'ereg' => [3], + 'eregi' => [3], + 'exec' => [2, 3], + 'exif_thumbnail' => [1, 2, 3], + 'expect_expectl' => [3], + 'extract' => [1], + 'filter' => [3], + 'flock' => [2,3], + 'fscanf' => [2, 3, '...'], + 'fsockopen' => [3, 4], + 'ftp_alloc' => [3], + 'get' => [2, 3], + 'getByKey' => [4], + 'getMulti' => [2], + 'getMultiByKey' => [3], + 'getimagesize' => [2], + 'getmxrr' => [2, 3], + 'gnupg_decryptverify' => [3], + 'gnupg_verify' => [4], + 'grapheme_extract' => [5], + 'headers_sent' => [1, 2], + 'http_build_url' => [4], + 'http_get' => [3], + 'http_head' => [3], + 'http_negotiate_charset' => [2], + 'http_negotiate_content_type' => [2], + 'http_negotiate_language' => [2], + 'http_post_data' => [4], + 'http_post_fields' => [5], + 'http_put_data' => [4], + 'http_put_file' => [4], + 'http_put_stream' => [4], + 'http_request' => [5], + 'isSuspicious' => [2], + 'is_callable' => [3], + 'key' => [1], + 'krsort' => [1], + 'ksort' => [1], + 'ldap_get_option' => [3], + 'ldap_parse_reference' => [3], + 'ldap_parse_result' => [3, 4, 5, 6], + 'localtime' => [2], + 'm_completeauthorizations' => [2], + 'maxdb_stmt_bind_param' => [3, 4, '...'], + 'maxdb_stmt_bind_result' => [2, 3, '...'], + 'mb_convert_variables' => [3, 4, '...'], + 'mb_parse_str' => [2], + 'mqseries_back' => [2, 3], + 'mqseries_begin' => [3, 4], + 'mqseries_close' => [4, 5], + 'mqseries_cmit' => [2, 3], + 'mqseries_conn' => [2, 3, 4], + 'mqseries_connx' => [2, 3, 4, 5], + 'mqseries_disc' => [2, 3], + 'mqseries_get' => [3, 4, 5, 6, 7, 8, 9], + 'mqseries_inq' => [6, 8, 9, 10], + 'mqseries_open' => [2, 4, 5, 6], + 'mqseries_put' => [3, 4, 6, 7], + 'mqseries_put1' => [2, 3, 4, 6, 7], + 'mqseries_set' => [9, 10], + 'msg_receive' => [3, 5, 8], + 'msg_send' => [6], + 'mssql_bind' => [3], + 'natcasesort' => [1], + 'natsort' => [1], + 'ncurses_color_content' => [2, 3, 4], + 'ncurses_getmaxyx' => [2, 3], + 'ncurses_getmouse' => [1], + 'ncurses_getyx' => [2, 3], + 'ncurses_instr' => [1], + 'ncurses_mouse_trafo' => [1, 2], + 'ncurses_mousemask' => [2], + 'ncurses_pair_content' => [2, 3], + 'ncurses_wmouse_trafo' => [2, 3], + 'newt_button_bar' => [1], + 'newt_form_run' => [2], + 'newt_get_screen_size' => [1, 2], + 'newt_grid_get_size' => [2, 3], + 'newt_reflow_text' => [5, 6], + 'newt_win_entries' => [7], + 'newt_win_menu' => [8], + 'next' => [1], + 'oci_bind_array_by_name' => [3], + 'oci_bind_by_name' => [3], + 'oci_define_by_name' => [3], + 'oci_fetch_all' => [2], + 'ocifetchinto' => [2], + 'odbc_fetch_into' => [2], + 'openssl_csr_export' => [2], + 'openssl_csr_new' => [2], + 'openssl_open' => [2], + 'openssl_pkcs12_export' => [2], + 'openssl_pkcs12_read' => [2], + 'openssl_pkey_export' => [2], + 'openssl_private_decrypt' => [2], + 'openssl_private_encrypt' => [2], + 'openssl_public_decrypt' => [2], + 'openssl_public_encrypt' => [2], + 'openssl_random_pseudo_bytes' => [2], + 'openssl_seal' => [2, 3], + 'openssl_sign' => [2], + 'openssl_x509_export' => [2], + 'ovrimos_fetch_into' => [2], + 'parse' => [2,3], + 'parseCurrency' => [2, 3], + 'parse_str' => [2], + 'parsekit_compile_file' => [2], + 'parsekit_compile_string' => [2], + 'passthru' => [2], + 'pcntl_sigprocmask' => [3], + 'pcntl_sigtimedwait' => [2], + 'pcntl_sigwaitinfo' => [2], + 'pcntl_wait' => [1], + 'pcntl_waitpid' => [2], + 'pfsockopen' => [3, 4], + 'php_check_syntax' => [2], + 'poll' => [1, 2, 3], + 'preg_filter' => [5], + 'preg_match' => [3], + 'preg_match_all' => [3], + 'preg_replace' => [5], + 'preg_replace_callback' => [5], + 'prev' => [1], + 'proc_open' => [3], + 'query' => [3], + 'queryExec' => [2], + 'reset' => [1], + 'rsort' => [1], + 'settype' => [1], + 'shuffle' => [1], + 'similar_text' => [3], + 'socket_create_pair' => [4], + 'socket_getpeername' => [2, 3], + 'socket_getsockname' => [2, 3], + 'socket_recv' => [2], + 'socket_recvfrom' => [2, 5, 6], + 'socket_select' => [1, 2, 3], + 'sort' => [1], + 'sortWithSortKeys' => [1], + 'sqlite_exec' => [3], + 'sqlite_factory' => [3], + 'sqlite_open' => [3], + 'sqlite_popen' => [3], + 'sqlite_query' => [4], + 'sqlite_unbuffered_query' => [4], + 'sscanf' => [3, '...'], + 'str_ireplace' => [4], + 'str_replace' => [4], + 'stream_open' => [4], + 'stream_select' => [1, 2, 3], + 'stream_socket_accept' => [3], + 'stream_socket_client' => [2, 3], + 'stream_socket_recvfrom' => [4], + 'stream_socket_server' => [2, 3], + 'system' => [2], + 'uasort' => [1], + 'uksort' => [1], + 'unbufferedQuery' => [3], + 'usort' => [1], + 'wincache_ucache_dec' => [3], + 'wincache_ucache_get' => [2], + 'wincache_ucache_inc' => [3], + 'xdiff_string_merge3' => [4], + 'xdiff_string_patch' => [4], + 'xml_parse_into_struct' => [3, 4], + 'xml_set_object' => [2], + 'xmlrpc_decode_request' => [2], + 'xmlrpc_set_type' => [1], + 'xslt_set_object' => [2], + 'yaml_parse' => [3], + 'yaml_parse_file' => [3], + 'yaml_parse_url' => [3], + 'yaz_ccl_parse' => [3], + 'yaz_hits' => [2], + 'yaz_scan_result' => [2], + 'yaz_wait' => [1], + ]; + } + + /** + * @return array> + */ + public static function getWordPressPassByReferenceFunctions() + { + return [ + 'wp_parse_str' => [2], + 'wp_cache_get' => [4], + ]; + } + + /** + * A regexp for matching variable names in double-quoted strings. + * + * @return string + */ + public static function getDoubleQuotedVarRegexp() + { + return '|(? + */ + public $incrementVariables = []; + + /** + * @param int $forIndex + * @param int $blockStart + * @param int $blockEnd + * @param int $initStart + * @param int $initEnd + * @param int $conditionStart + * @param int $conditionEnd + * @param int $incrementStart + * @param int $incrementEnd + */ + public function __construct( + $forIndex, + $blockStart, + $blockEnd, + $initStart, + $initEnd, + $conditionStart, + $conditionEnd, + $incrementStart, + $incrementEnd + ) { + $this->forIndex = $forIndex; + $this->blockStart = $blockStart; + $this->blockEnd = $blockEnd; + $this->initStart = $initStart; + $this->initEnd = $initEnd; + $this->conditionStart = $conditionStart; + $this->conditionEnd = $conditionEnd; + $this->incrementStart = $incrementStart; + $this->incrementEnd = $incrementEnd; + } +} diff --git a/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/Helpers.php b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/Helpers.php new file mode 100644 index 00000000..b05917ed --- /dev/null +++ b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/Helpers.php @@ -0,0 +1,1478 @@ + + */ + public static function getPossibleEndOfFileTokens() + { + return array_merge( + array_values(Tokens::$emptyTokens), + [ + T_INLINE_HTML, + T_CLOSE_TAG, + ] + ); + } + + /** + * @param int|bool $value + * + * @return ?int + */ + public static function getIntOrNull($value) + { + return is_int($value) ? $value : null; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return ?int + */ + public static function findContainingOpeningSquareBracket(File $phpcsFile, $stackPtr) + { + $previousStatementPtr = self::getPreviousStatementPtr($phpcsFile, $stackPtr); + return self::getIntOrNull($phpcsFile->findPrevious([T_OPEN_SHORT_ARRAY, T_OPEN_SQUARE_BRACKET], $stackPtr - 1, $previousStatementPtr)); + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return int + */ + public static function getPreviousStatementPtr(File $phpcsFile, $stackPtr) + { + $result = $phpcsFile->findPrevious([T_SEMICOLON, T_CLOSE_CURLY_BRACKET], $stackPtr - 1); + return is_bool($result) ? 1 : $result; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return ?int + */ + public static function findContainingOpeningBracket(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['nested_parenthesis'])) { + /** + * @var array + */ + $openPtrs = array_keys($tokens[$stackPtr]['nested_parenthesis']); + return (int)end($openPtrs); + } + return null; + } + + /** + * @param (int|string)[] $conditions + * + * @return bool + */ + public static function areAnyConditionsAClass(array $conditions) + { + foreach (array_reverse($conditions, true) as $scopeCode) { + if ($scopeCode === T_CLASS || $scopeCode === T_ANON_CLASS || $scopeCode === T_TRAIT) { + return true; + } + } + return false; + } + + /** + * Return true if the token conditions are within a function before they are + * within a class. + * + * @param (int|string)[] $conditions + * + * @return bool + */ + public static function areConditionsWithinFunctionBeforeClass(array $conditions) + { + $classTypes = [T_CLASS, T_ANON_CLASS, T_TRAIT]; + foreach (array_reverse($conditions, true) as $scopeCode) { + if (in_array($scopeCode, $classTypes)) { + return false; + } + if ($scopeCode === T_FUNCTION) { + return true; + } + } + return false; + } + + /** + * Return true if the token conditions are within an if block before they are + * within a class or function. + * + * @param (int|string)[] $conditions + * + * @return int|string|null + */ + public static function getClosestIfPositionIfBeforeOtherConditions(array $conditions) + { + $conditionsInsideOut = array_reverse($conditions, true); + if (empty($conditions)) { + return null; + } + $scopeCode = reset($conditionsInsideOut); + if ($scopeCode === T_IF) { + return key($conditionsInsideOut); + } + return null; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isTokenFunctionParameter(File $phpcsFile, $stackPtr) + { + return is_int(self::getFunctionIndexForFunctionParameter($phpcsFile, $stackPtr)); + } + + /** + * Return true if the token is inside the arguments of a function call. + * + * For example, the variable `$foo` in `doSomething($foo)` is inside the + * arguments to the call to `doSomething()`. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isTokenInsideFunctionCallArgument(File $phpcsFile, $stackPtr) + { + return is_int(self::getFunctionIndexForFunctionCallArgument($phpcsFile, $stackPtr)); + } + + /** + * Find the index of the function keyword for a token in a function + * definition's parameters. + * + * Does not work for tokens inside the "use". + * + * Will also work for the parenthesis that make up the function definition's + * parameters list. + * + * For arguments inside a function call, rather than a definition, use + * `getFunctionIndexForFunctionCallArgument`. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return ?int + */ + public static function getFunctionIndexForFunctionParameter(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + if ($token['code'] === 'PHPCS_T_OPEN_PARENTHESIS') { + $startOfArguments = $stackPtr; + } elseif ($token['code'] === 'PHPCS_T_CLOSE_PARENTHESIS') { + if (empty($token['parenthesis_opener'])) { + return null; + } + $startOfArguments = $token['parenthesis_opener']; + } else { + if (empty($token['nested_parenthesis'])) { + return null; + } + $startingParenthesis = array_keys($token['nested_parenthesis']); + $startOfArguments = end($startingParenthesis); + } + + if (! is_int($startOfArguments)) { + return null; + } + + $nonFunctionTokenTypes = Tokens::$emptyTokens; + $nonFunctionTokenTypes[] = T_STRING; + $nonFunctionTokenTypes[] = T_BITWISE_AND; + $functionPtr = self::getIntOrNull($phpcsFile->findPrevious($nonFunctionTokenTypes, $startOfArguments - 1, null, true, null, true)); + if (! is_int($functionPtr)) { + return null; + } + $functionToken = $tokens[$functionPtr]; + + $functionTokenTypes = [ + T_FUNCTION, + T_CLOSURE, + ]; + if (!in_array($functionToken['code'], $functionTokenTypes, true) && ! self::isArrowFunction($phpcsFile, $functionPtr)) { + return null; + } + return $functionPtr; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isTokenInsideFunctionUseImport(File $phpcsFile, $stackPtr) + { + return is_int(self::getUseIndexForUseImport($phpcsFile, $stackPtr)); + } + + /** + * Find the token index of the "use" for a token inside a function use import + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return ?int + */ + public static function getUseIndexForUseImport(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nonUseTokenTypes = Tokens::$emptyTokens; + $nonUseTokenTypes[] = T_VARIABLE; + $nonUseTokenTypes[] = T_ELLIPSIS; + $nonUseTokenTypes[] = T_COMMA; + $nonUseTokenTypes[] = T_BITWISE_AND; + $openParenPtr = self::getIntOrNull($phpcsFile->findPrevious($nonUseTokenTypes, $stackPtr - 1, null, true, null, true)); + if (! is_int($openParenPtr) || $tokens[$openParenPtr]['code'] !== T_OPEN_PARENTHESIS) { + return null; + } + + $usePtr = self::getIntOrNull($phpcsFile->findPrevious(array_values($nonUseTokenTypes), $openParenPtr - 1, null, true, null, true)); + if (! is_int($usePtr) || $tokens[$usePtr]['code'] !== T_USE) { + return null; + } + return $usePtr; + } + + /** + * Return the index of a function's name token from inside the function. + * + * $stackPtr must be inside the function body or parameters for this to work. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return ?int + */ + public static function findFunctionCall(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $openPtr = self::findContainingOpeningBracket($phpcsFile, $stackPtr); + if (is_int($openPtr)) { + // First non-whitespace thing and see if it's a T_STRING function name + $functionPtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $openPtr - 1, null, true, null, true); + if (is_int($functionPtr) && $tokens[$functionPtr]['code'] === T_STRING) { + return $functionPtr; + } + } + return null; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return array> + */ + public static function findFunctionCallArguments(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Slight hack: also allow this to find args for array constructor. + if (($tokens[$stackPtr]['code'] !== T_STRING) && ($tokens[$stackPtr]['code'] !== T_ARRAY)) { + // Assume $stackPtr is something within the brackets, find our function call + $stackPtr = self::findFunctionCall($phpcsFile, $stackPtr); + if ($stackPtr === null) { + return []; + } + } + + // $stackPtr is the function name, find our brackets after it + $openPtr = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + if (($openPtr === false) || ($tokens[$openPtr]['code'] !== T_OPEN_PARENTHESIS)) { + return []; + } + + if (!isset($tokens[$openPtr]['parenthesis_closer'])) { + return []; + } + $closePtr = $tokens[$openPtr]['parenthesis_closer']; + + $argPtrs = []; + $lastPtr = $openPtr; + $lastArgComma = $openPtr; + $nextPtr = $phpcsFile->findNext([T_COMMA], $lastPtr + 1, $closePtr); + while (is_int($nextPtr)) { + if (self::findContainingOpeningBracket($phpcsFile, $nextPtr) === $openPtr) { + // Comma is at our level of brackets, it's an argument delimiter. + $range = range($lastArgComma + 1, $nextPtr - 1); + $range = array_filter($range, function ($element) { + return is_int($element); + }); + array_push($argPtrs, $range); + $lastArgComma = $nextPtr; + } + $lastPtr = $nextPtr; + $nextPtr = $phpcsFile->findNext([T_COMMA], $lastPtr + 1, $closePtr); + } + $range = range($lastArgComma + 1, $closePtr - 1); + $range = array_filter($range, function ($element) { + return is_int($element); + }); + array_push($argPtrs, $range); + + return $argPtrs; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return ?int + */ + public static function getNextAssignPointer(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Is the next non-whitespace an assignment? + $nextPtr = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + if (is_int($nextPtr) + && isset(Tokens::$assignmentTokens[$tokens[$nextPtr]['code']]) + // Ignore double arrow to prevent triggering on `foreach ( $array as $k => $v )`. + && $tokens[$nextPtr]['code'] !== T_DOUBLE_ARROW + ) { + return $nextPtr; + } + return null; + } + + /** + * @param string $varName + * + * @return string + */ + public static function normalizeVarName($varName) + { + $result = preg_replace('/[{}$]/', '', $varName); + return $result ? $result : $varName; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName (optional) if it differs from the normalized 'content' of the token at $stackPtr + * + * @return ?int + */ + public static function findVariableScope(File $phpcsFile, $stackPtr, $varName = null) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + $varName = isset($varName) ? $varName : self::normalizeVarName($token['content']); + + $arrowFunctionIndex = self::getContainingArrowFunctionIndex($phpcsFile, $stackPtr); + $isTokenInsideArrowFunctionBody = is_int($arrowFunctionIndex); + if ($isTokenInsideArrowFunctionBody) { + // Get the list of variables defined by the arrow function + // If this matches any of them, the scope is the arrow function, + // otherwise, it uses the enclosing scope. + if ($arrowFunctionIndex) { + $variableNames = self::getVariablesDefinedByArrowFunction($phpcsFile, $arrowFunctionIndex); + self::debug('findVariableScope: looking for', $varName, 'in arrow function variables', $variableNames); + if (in_array($varName, $variableNames, true)) { + return $arrowFunctionIndex; + } + } + } + + return self::findVariableScopeExceptArrowFunctions($phpcsFile, $stackPtr); + } + + /** + * Return the token index of the scope start for a token + * + * For a variable within a function body, or a variable within a function + * definition argument list, this will return the function keyword's index. + * + * For a variable within a "use" import list within a function definition, + * this will return the enclosing scope, not the function keyword. This is + * important to note because the "use" keyword performs double-duty, defining + * variables for the function's scope, and consuming the variables in the + * enclosing scope. Use `getUseIndexForUseImport` to determine if this + * token needs to be treated as a "use". + * + * For a variable within an arrow function definition argument list, + * this will return the arrow function's keyword index. + * + * For a variable in an arrow function body, this will return the enclosing + * function's index, which may be incorrect. + * + * Since a variable in an arrow function's body may be imported from the + * enclosing scope, it's important to test to see if the variable is in an + * arrow function and also check its enclosing scope separately. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return ?int + */ + public static function findVariableScopeExceptArrowFunctions(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $allowedTypes = [ + T_VARIABLE, + T_DOUBLE_QUOTED_STRING, + T_HEREDOC, + T_STRING, + ]; + if (! in_array($tokens[$stackPtr]['code'], $allowedTypes, true)) { + throw new \Exception("Cannot find variable scope for non-variable {$tokens[$stackPtr]['type']}"); + } + + $startOfTokenScope = self::getStartOfTokenScope($phpcsFile, $stackPtr); + if (is_int($startOfTokenScope) && $startOfTokenScope > 0) { + return $startOfTokenScope; + } + + // If there is no "conditions" array, this is a function definition argument. + if (self::isTokenFunctionParameter($phpcsFile, $stackPtr)) { + $functionPtr = self::getFunctionIndexForFunctionParameter($phpcsFile, $stackPtr); + if (! is_int($functionPtr)) { + throw new \Exception("Function index not found for function argument index {$stackPtr}"); + } + return $functionPtr; + } + + self::debug('Cannot find function scope for variable at', $stackPtr); + return $startOfTokenScope; + } + + /** + * Return the token index of the scope start for a variable token + * + * This will only work for a variable within a function's body. Otherwise, + * see `findVariableScope`, which is more complex. + * + * Note that if used on a variable in an arrow function, it will return the + * enclosing function's scope, which may be incorrect. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return ?int + */ + private static function getStartOfTokenScope(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + $inClass = false; + $conditions = isset($token['conditions']) ? $token['conditions'] : []; + $functionTokenTypes = [ + T_FUNCTION, + T_CLOSURE, + ]; + foreach (array_reverse($conditions, true) as $scopePtr => $scopeCode) { + if (in_array($scopeCode, $functionTokenTypes, true) || self::isArrowFunction($phpcsFile, $scopePtr)) { + return $scopePtr; + } + if (isset(Tokens::$ooScopeTokens[$scopeCode]) === true) { + $inClass = true; + } + } + + if ($inClass) { + // If this is inside a class and not inside a function, this is either a + // class member variable definition, or a function argument. If it is a + // variable definition, it has no scope on its own (it can only be used + // with an object reference). If it is a function argument, we need to do + // more work (see `findVariableScopeExceptArrowFunctions`). + return null; + } + + // If we can't find a scope, let's use the first token of the file. + return 0; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isTokenInsideArrowFunctionDefinition(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + $openParenIndices = isset($token['nested_parenthesis']) ? $token['nested_parenthesis'] : []; + if (empty($openParenIndices)) { + return false; + } + $openParenPtr = $openParenIndices[0]; + return self::isArrowFunction($phpcsFile, $openParenPtr - 1); + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return ?int + */ + public static function getContainingArrowFunctionIndex(File $phpcsFile, $stackPtr) + { + $arrowFunctionIndex = self::getPreviousArrowFunctionIndex($phpcsFile, $stackPtr); + if (! is_int($arrowFunctionIndex)) { + return null; + } + $arrowFunctionInfo = self::getArrowFunctionOpenClose($phpcsFile, $arrowFunctionIndex); + if (! $arrowFunctionInfo) { + return null; + } + $arrowFunctionScopeStart = $arrowFunctionInfo['scope_opener']; + $arrowFunctionScopeEnd = $arrowFunctionInfo['scope_closer']; + if ($stackPtr > $arrowFunctionScopeStart && $stackPtr < $arrowFunctionScopeEnd) { + return $arrowFunctionIndex; + } + return null; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return ?int + */ + private static function getPreviousArrowFunctionIndex(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $enclosingScopeIndex = self::findVariableScopeExceptArrowFunctions($phpcsFile, $stackPtr); + for ($index = $stackPtr - 1; $index > $enclosingScopeIndex; $index--) { + $token = $tokens[$index]; + if ($token['content'] === 'fn' && self::isArrowFunction($phpcsFile, $index)) { + return $index; + } + } + return null; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isArrowFunction(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (defined('T_FN') && $tokens[$stackPtr]['code'] === T_FN) { + return true; + } + if ($tokens[$stackPtr]['content'] !== 'fn') { + return false; + } + // Make sure next non-space token is an open parenthesis + $openParenIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); + if (! is_int($openParenIndex) || $tokens[$openParenIndex]['code'] !== T_OPEN_PARENTHESIS) { + return false; + } + // Find the associated close parenthesis + $closeParenIndex = $tokens[$openParenIndex]['parenthesis_closer']; + // Make sure the next token is a fat arrow + $fatArrowIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $closeParenIndex + 1, null, true); + if (! is_int($fatArrowIndex)) { + return false; + } + if ($tokens[$fatArrowIndex]['code'] !== T_DOUBLE_ARROW && $tokens[$fatArrowIndex]['type'] !== 'T_FN_ARROW') { + return false; + } + return true; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return ?array + */ + public static function getArrowFunctionOpenClose(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (defined('T_FN') && $tokens[$stackPtr]['code'] === T_FN) { + return [ + 'scope_opener' => $tokens[$stackPtr]['scope_opener'], + 'scope_closer' => $tokens[$stackPtr]['scope_closer'], + ]; + } + if ($tokens[$stackPtr]['content'] !== 'fn') { + return null; + } + // Make sure next non-space token is an open parenthesis + $openParenIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); + if (! is_int($openParenIndex) || $tokens[$openParenIndex]['code'] !== T_OPEN_PARENTHESIS) { + return null; + } + // Find the associated close parenthesis + $closeParenIndex = $tokens[$openParenIndex]['parenthesis_closer']; + // Make sure the next token is a fat arrow + $fatArrowIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $closeParenIndex + 1, null, true); + if (! is_int($fatArrowIndex)) { + return null; + } + if ($tokens[$fatArrowIndex]['code'] !== T_DOUBLE_ARROW && $tokens[$fatArrowIndex]['type'] !== 'T_FN_ARROW') { + return null; + } + // Find the scope closer + $endScopeTokens = [ + T_COMMA, + T_SEMICOLON, + T_CLOSE_PARENTHESIS, + T_CLOSE_CURLY_BRACKET, + T_CLOSE_SHORT_ARRAY, + ]; + $scopeCloserIndex = $phpcsFile->findNext($endScopeTokens, $fatArrowIndex + 1); + if (! is_int($scopeCloserIndex)) { + return null; + } + return [ + 'scope_opener' => $stackPtr, + 'scope_closer' => $scopeCloserIndex, + ]; + } + + /** + * Determine if a token is a list opener for list assignment/destructuring. + * + * The index provided can be either the opening square brace of a short list + * assignment like the first character of `[$a] = $b;` or the `list` token of + * an expression like `list($a) = $b;` or the opening parenthesis of that + * expression. + * + * @param File $phpcsFile + * @param int $listOpenerIndex + * + * @return bool + */ + private static function isListAssignment(File $phpcsFile, $listOpenerIndex) + { + $tokens = $phpcsFile->getTokens(); + // Match `[$a] = $b;` except for when the previous token is a parenthesis. + if ($tokens[$listOpenerIndex]['code'] === T_OPEN_SHORT_ARRAY) { + return true; + } + // Match `list($a) = $b;` + if ($tokens[$listOpenerIndex]['code'] === T_LIST) { + return true; + } + + // If $listOpenerIndex is the open parenthesis of `list($a) = $b;`, then + // match that too. + if ($tokens[$listOpenerIndex]['code'] === T_OPEN_PARENTHESIS) { + $previousTokenPtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $listOpenerIndex - 1, null, true); + if ( + isset($tokens[$previousTokenPtr]) + && $tokens[$previousTokenPtr]['code'] === T_LIST + ) { + return true; + } + return true; + } + + // If the list opener token is a square bracket that is preceeded by a + // close parenthesis that has an owner which is a scope opener, then this + // is a list assignment and not an array access. + // + // Match `if (true) [$a] = $b;` + if ($tokens[$listOpenerIndex]['code'] === T_OPEN_SQUARE_BRACKET) { + $previousTokenPtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $listOpenerIndex - 1, null, true); + if ( + isset($tokens[$previousTokenPtr]) + && $tokens[$previousTokenPtr]['code'] === T_CLOSE_PARENTHESIS + && isset($tokens[$previousTokenPtr]['parenthesis_owner']) + && isset(Tokens::$scopeOpeners[$tokens[$tokens[$previousTokenPtr]['parenthesis_owner']]['code']]) + ) { + return true; + } + } + + return false; + } + + /** + * Return a list of indices for variables assigned within a list assignment. + * + * The index provided can be either the opening square brace of a short list + * assignment like the first character of `[$a] = $b;` or the `list` token of + * an expression like `list($a) = $b;` or the opening parenthesis of that + * expression. + * + * @param File $phpcsFile + * @param int $listOpenerIndex + * + * @return ?array + */ + public static function getListAssignments(File $phpcsFile, $listOpenerIndex) + { + $tokens = $phpcsFile->getTokens(); + self::debug('getListAssignments', $listOpenerIndex, $tokens[$listOpenerIndex]); + + // First find the end of the list + $closePtr = null; + if (isset($tokens[$listOpenerIndex]['parenthesis_closer'])) { + $closePtr = $tokens[$listOpenerIndex]['parenthesis_closer']; + } + if (isset($tokens[$listOpenerIndex]['bracket_closer'])) { + $closePtr = $tokens[$listOpenerIndex]['bracket_closer']; + } + if (! $closePtr) { + return null; + } + + // Find the assignment (equals sign) which, if this is a list assignment, should be the next non-space token + $assignPtr = $phpcsFile->findNext(Tokens::$emptyTokens, $closePtr + 1, null, true); + + // If the next token isn't an assignment, check for nested brackets because we might be a nested assignment + if (! is_int($assignPtr) || $tokens[$assignPtr]['code'] !== T_EQUAL) { + // Collect the enclosing list open/close tokens ($parents is an assoc array keyed by opener index and the value is the closer index) + $parents = isset($tokens[$listOpenerIndex]['nested_parenthesis']) ? $tokens[$listOpenerIndex]['nested_parenthesis'] : []; + // There's no record of nested brackets for short lists; we'll have to find the parent ourselves + if (empty($parents)) { + $parentSquareBracket = self::findContainingOpeningSquareBracket($phpcsFile, $listOpenerIndex); + if (is_int($parentSquareBracket)) { + // Collect the opening index, but we don't actually need the closing paren index so just make that 0 + $parents = [$parentSquareBracket => 0]; + } + } + // If we have no parents, this is not a nested assignment and therefore is not an assignment + if (empty($parents)) { + return null; + } + + // Recursively check to see if the parent is a list assignment (we only need to check one level due to the recursion) + $isNestedAssignment = null; + $parentListOpener = array_keys(array_reverse($parents, true))[0]; + $isNestedAssignment = self::getListAssignments($phpcsFile, $parentListOpener); + if ($isNestedAssignment === null) { + return null; + } + } + + $variablePtrs = []; + + $currentPtr = $listOpenerIndex; + $variablePtr = 0; + while ($currentPtr < $closePtr && is_int($variablePtr)) { + $variablePtr = $phpcsFile->findNext([T_VARIABLE], $currentPtr + 1, $closePtr); + if (is_int($variablePtr)) { + $variablePtrs[] = $variablePtr; + } + ++$currentPtr; + } + + if (! self::isListAssignment($phpcsFile, $listOpenerIndex)) { + return null; + } + + return $variablePtrs; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return string[] + */ + public static function getVariablesDefinedByArrowFunction(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $arrowFunctionToken = $tokens[$stackPtr]; + $variableNames = []; + self::debug('looking for variables in arrow function token', $arrowFunctionToken); + for ($index = $arrowFunctionToken['parenthesis_opener']; $index < $arrowFunctionToken['parenthesis_closer']; $index++) { + $token = $tokens[$index]; + if ($token['code'] === T_VARIABLE) { + $variableNames[] = self::normalizeVarName($token['content']); + } + } + self::debug('found these variables in arrow function token', $variableNames); + return $variableNames; + } + + /** + * @return void + */ + public static function debug() + { + $messages = func_get_args(); + if (! defined('PHP_CODESNIFFER_VERBOSITY')) { + return; + } + if (PHP_CODESNIFFER_VERBOSITY <= 3) { + return; + } + $output = PHP_EOL . 'VariableAnalysisSniff: DEBUG:'; + foreach ($messages as $message) { + if (is_string($message) || is_numeric($message)) { + $output .= ' "' . $message . '"'; + continue; + } + $output .= PHP_EOL . var_export($message, true) . PHP_EOL; + } + $output .= PHP_EOL; + echo $output; + } + + /** + * @param string $pattern + * @param string $value + * + * @return string[] + */ + public static function splitStringToArray($pattern, $value) + { + $result = preg_split($pattern, $value); + return is_array($result) ? $result : []; + } + + /** + * @param string $varName + * + * @return bool + */ + public static function isVariableANumericVariable($varName) + { + return is_numeric(substr($varName, 0, 1)); + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isVariableInsideElseCondition(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $nonFunctionTokenTypes = Tokens::$emptyTokens; + $nonFunctionTokenTypes[] = T_OPEN_PARENTHESIS; + $nonFunctionTokenTypes[] = T_INLINE_HTML; + $nonFunctionTokenTypes[] = T_CLOSE_TAG; + $nonFunctionTokenTypes[] = T_VARIABLE; + $nonFunctionTokenTypes[] = T_ELLIPSIS; + $nonFunctionTokenTypes[] = T_COMMA; + $nonFunctionTokenTypes[] = T_STRING; + $nonFunctionTokenTypes[] = T_BITWISE_AND; + $elsePtr = self::getIntOrNull($phpcsFile->findPrevious($nonFunctionTokenTypes, $stackPtr - 1, null, true, null, true)); + $elseTokenTypes = [ + T_ELSE, + T_ELSEIF, + ]; + if (is_int($elsePtr) && in_array($tokens[$elsePtr]['code'], $elseTokenTypes, true)) { + return true; + } + return false; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isVariableInsideElseBody(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + $conditions = isset($token['conditions']) ? $token['conditions'] : []; + $elseTokenTypes = [ + T_ELSE, + T_ELSEIF, + ]; + foreach (array_reverse($conditions, true) as $scopeCode) { + if (in_array($scopeCode, $elseTokenTypes, true)) { + return true; + } + } + + // Some else body code will not have conditions because it is inline (no + // curly braces) so we have to look in other ways. + $previousSemicolonPtr = $phpcsFile->findPrevious([T_SEMICOLON], $stackPtr - 1); + if (! is_int($previousSemicolonPtr)) { + $previousSemicolonPtr = 0; + } + $elsePtr = $phpcsFile->findPrevious([T_ELSE, T_ELSEIF], $stackPtr - 1, $previousSemicolonPtr); + if (is_int($elsePtr)) { + return true; + } + + return false; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return int[] + */ + public static function getAttachedBlockIndicesForElse(File $phpcsFile, $stackPtr) + { + $currentElsePtr = $phpcsFile->findPrevious([T_ELSE, T_ELSEIF], $stackPtr - 1); + if (! is_int($currentElsePtr)) { + throw new \Exception("Cannot find expected else at {$stackPtr}"); + } + + $ifPtr = $phpcsFile->findPrevious([T_IF], $currentElsePtr - 1); + if (! is_int($ifPtr)) { + throw new \Exception("Cannot find if for else at {$stackPtr}"); + } + $blockIndices = [$ifPtr]; + + $previousElseIfPtr = $currentElsePtr; + do { + $elseIfPtr = $phpcsFile->findPrevious([T_ELSEIF], $previousElseIfPtr - 1, $ifPtr); + if (is_int($elseIfPtr)) { + $blockIndices[] = $elseIfPtr; + $previousElseIfPtr = $elseIfPtr; + } + } while (is_int($elseIfPtr)); + + return $blockIndices; + } + + /** + * @param int $needle + * @param int $scopeStart + * @param int $scopeEnd + * + * @return bool + */ + public static function isIndexInsideScope($needle, $scopeStart, $scopeEnd) + { + return ($needle > $scopeStart && $needle < $scopeEnd); + } + + /** + * @param File $phpcsFile + * @param int $scopeStartIndex + * + * @return int + */ + public static function getScopeCloseForScopeOpen(File $phpcsFile, $scopeStartIndex) + { + $tokens = $phpcsFile->getTokens(); + $scopeCloserIndex = isset($tokens[$scopeStartIndex]['scope_closer']) ? $tokens[$scopeStartIndex]['scope_closer'] : 0; + + if (self::isArrowFunction($phpcsFile, $scopeStartIndex)) { + $arrowFunctionInfo = self::getArrowFunctionOpenClose($phpcsFile, $scopeStartIndex); + $scopeCloserIndex = $arrowFunctionInfo ? $arrowFunctionInfo['scope_closer'] : $scopeCloserIndex; + } + + if ($scopeStartIndex === 0) { + $scopeCloserIndex = self::getLastNonEmptyTokenIndexInFile($phpcsFile); + } + return $scopeCloserIndex; + } + + /** + * @param File $phpcsFile + * + * @return int + */ + public static function getLastNonEmptyTokenIndexInFile(File $phpcsFile) + { + $tokens = $phpcsFile->getTokens(); + foreach (array_reverse($tokens, true) as $index => $token) { + if (! in_array($token['code'], self::getPossibleEndOfFileTokens(), true)) { + return $index; + } + } + self::debug('no non-empty token found for end of file'); + return 0; + } + + /** + * @param VariableInfo $varInfo + * @param ScopeInfo $scopeInfo + * + * @return bool + */ + public static function areFollowingArgumentsUsed(VariableInfo $varInfo, ScopeInfo $scopeInfo) + { + $foundVarPosition = false; + foreach ($scopeInfo->variables as $variable) { + if ($variable === $varInfo) { + $foundVarPosition = true; + continue; + } + if (! $foundVarPosition) { + continue; + } + if ($variable->scopeType !== ScopeType::PARAM) { + continue; + } + if ($variable->firstRead) { + return true; + } + } + return false; + } + + /** + * @param File $phpcsFile + * @param VariableInfo $varInfo + * @param ScopeInfo $scopeInfo + * + * @return bool + */ + public static function isRequireInScopeAfter(File $phpcsFile, VariableInfo $varInfo, ScopeInfo $scopeInfo) + { + $requireTokens = [ + T_REQUIRE, + T_REQUIRE_ONCE, + T_INCLUDE, + T_INCLUDE_ONCE, + ]; + $indexToStartSearch = $varInfo->firstDeclared; + if (! empty($varInfo->firstInitialized)) { + $indexToStartSearch = $varInfo->firstInitialized; + } + $tokens = $phpcsFile->getTokens(); + $indexToStopSearch = isset($tokens[$scopeInfo->scopeStartIndex]['scope_closer']) ? $tokens[$scopeInfo->scopeStartIndex]['scope_closer'] : null; + if (! is_int($indexToStartSearch) || ! is_int($indexToStopSearch)) { + return false; + } + $requireTokenIndex = $phpcsFile->findNext($requireTokens, $indexToStartSearch + 1, $indexToStopSearch); + if (is_int($requireTokenIndex)) { + return true; + } + return false; + } + + /** + * Find the index of the function keyword for a token in a function call's arguments + * + * For the variable `$foo` in the expression `doSomething($foo)`, this will + * return the index of the `doSomething` token. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return ?int + */ + public static function getFunctionIndexForFunctionCallArgument(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + if (empty($token['nested_parenthesis'])) { + return null; + } + /** + * @var array + */ + $startingParenthesis = array_keys($token['nested_parenthesis']); + $startOfArguments = end($startingParenthesis); + if (! is_int($startOfArguments)) { + return null; + } + + $nonFunctionTokenTypes = Tokens::$emptyTokens; + $functionPtr = self::getIntOrNull($phpcsFile->findPrevious($nonFunctionTokenTypes, $startOfArguments - 1, null, true, null, true)); + if (! is_int($functionPtr) || ! isset($tokens[$functionPtr]['code'])) { + return null; + } + if ( + $tokens[$functionPtr]['content'] === 'function' + || ($tokens[$functionPtr]['content'] === 'fn' && self::isArrowFunction($phpcsFile, $functionPtr)) + ) { + // If there is a function/fn keyword before the beginning of the parens, + // this is a function definition and not a function call. + return null; + } + if (! empty($tokens[$functionPtr]['scope_opener'])) { + // If the alleged function name has a scope, this is not a function call. + return null; + } + + $functionNameType = $tokens[$functionPtr]['code']; + if (! in_array($functionNameType, Tokens::$functionNameTokens, true)) { + // If the alleged function name is not a variable or a string, this is + // not a function call. + return null; + } + + if ($tokens[$functionPtr]['level'] !== $tokens[$stackPtr]['level']) { + // If the variable is inside a different scope than the function name, + // the function call doesn't apply to the variable. + return null; + } + + return $functionPtr; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isVariableInsideIssetOrEmpty(File $phpcsFile, $stackPtr) + { + $functionIndex = self::getFunctionIndexForFunctionCallArgument($phpcsFile, $stackPtr); + if (! is_int($functionIndex)) { + return false; + } + $tokens = $phpcsFile->getTokens(); + if (! isset($tokens[$functionIndex])) { + return false; + } + $allowedFunctionNames = [ + 'isset', + 'empty', + ]; + if (in_array($tokens[$functionIndex]['content'], $allowedFunctionNames, true)) { + return true; + } + return false; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isVariableArrayPushShortcut(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $nonFunctionTokenTypes = Tokens::$emptyTokens; + + $arrayPushOperatorIndex1 = self::getIntOrNull($phpcsFile->findNext($nonFunctionTokenTypes, $stackPtr + 1, null, true, null, true)); + if (! is_int($arrayPushOperatorIndex1)) { + return false; + } + if (! isset($tokens[$arrayPushOperatorIndex1]['content']) || $tokens[$arrayPushOperatorIndex1]['content'] !== '[') { + return false; + } + + $arrayPushOperatorIndex2 = self::getIntOrNull($phpcsFile->findNext($nonFunctionTokenTypes, $arrayPushOperatorIndex1 + 1, null, true, null, true)); + if (! is_int($arrayPushOperatorIndex2)) { + return false; + } + if (! isset($tokens[$arrayPushOperatorIndex2]['content']) || $tokens[$arrayPushOperatorIndex2]['content'] !== ']') { + return false; + } + + $arrayPushOperatorIndex3 = self::getIntOrNull($phpcsFile->findNext($nonFunctionTokenTypes, $arrayPushOperatorIndex2 + 1, null, true, null, true)); + if (! is_int($arrayPushOperatorIndex3)) { + return false; + } + if (! isset($tokens[$arrayPushOperatorIndex3]['content']) || $tokens[$arrayPushOperatorIndex3]['content'] !== '=') { + return false; + } + + return true; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isVariableInsideUnset(File $phpcsFile, $stackPtr) + { + $functionIndex = self::getFunctionIndexForFunctionCallArgument($phpcsFile, $stackPtr); + if (! is_int($functionIndex)) { + return false; + } + $tokens = $phpcsFile->getTokens(); + if (! isset($tokens[$functionIndex])) { + return false; + } + if ($tokens[$functionIndex]['content'] === 'unset') { + return true; + } + return false; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isTokenInsideAssignmentRHS(File $phpcsFile, $stackPtr) + { + $previousStatementPtr = $phpcsFile->findPrevious([T_SEMICOLON, T_CLOSE_CURLY_BRACKET, T_OPEN_CURLY_BRACKET, T_COMMA], $stackPtr - 1); + if (! is_int($previousStatementPtr)) { + $previousStatementPtr = 1; + } + $previousTokenPtr = $phpcsFile->findPrevious([T_EQUAL], $stackPtr - 1, $previousStatementPtr); + if (is_int($previousTokenPtr)) { + return true; + } + return false; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isTokenInsideAssignmentLHS(File $phpcsFile, $stackPtr) + { + // Is the next non-whitespace an assignment? + $assignPtr = self::getNextAssignPointer($phpcsFile, $stackPtr); + if (! is_int($assignPtr)) { + return false; + } + + // Is this a variable variable? If so, it's not an assignment to the current variable. + if (self::isTokenVariableVariable($phpcsFile, $stackPtr)) { + self::debug('found variable variable'); + return false; + } + return true; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isTokenVariableVariable(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prev === false) { + return false; + } + if ($tokens[$prev]['code'] === T_DOLLAR) { + return true; + } + if ($tokens[$prev]['code'] !== T_OPEN_CURLY_BRACKET) { + return false; + } + + $prevPrev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + if ($prevPrev !== false && $tokens[$prevPrev]['code'] === T_DOLLAR) { + return true; + } + return false; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * + * @return ForLoopInfo + */ + public static function makeForLoopInfo(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + $forIndex = $stackPtr; + $blockStart = $token['parenthesis_closer']; + if (isset($token['scope_opener'])) { + $blockStart = $token['scope_opener']; + $blockEnd = $token['scope_closer']; + } else { + // Some for loop blocks will not have scope positions because it they are + // inline (no curly braces) so we have to find the end of their scope by + // looking for the end of the next statement. + $nextSemicolonIndex = $phpcsFile->findNext([T_SEMICOLON], $token['parenthesis_closer']); + if (! is_int($nextSemicolonIndex)) { + $nextSemicolonIndex = $token['parenthesis_closer'] + 1; + } + $blockEnd = $nextSemicolonIndex; + } + $initStart = intval($token['parenthesis_opener']) + 1; + $initEnd = null; + $conditionStart = null; + $conditionEnd = null; + $incrementStart = null; + $incrementEnd = $token['parenthesis_closer'] - 1; + + $semicolonCount = 0; + $forLoopLevel = $tokens[$forIndex]['level']; + $forLoopNestedParensCount = 1; + + if (isset($tokens[$forIndex]['nested_parenthesis'])) { + $forLoopNestedParensCount = count($tokens[$forIndex]['nested_parenthesis']) + 1; + } + + for ($i = $initStart; ($i <= $incrementEnd && $semicolonCount < 2); $i++) { + if ($tokens[$i]['code'] !== T_SEMICOLON) { + continue; + } + + if ($tokens[$i]['level'] !== $forLoopLevel) { + continue; + } + + if (count($tokens[$i]['nested_parenthesis']) !== $forLoopNestedParensCount) { + continue; + } + + switch ($semicolonCount) { + case 0: + $initEnd = $i; + $conditionStart = $initEnd + 1; + break; + case 1: + $conditionEnd = $i; + $incrementStart = $conditionEnd + 1; + break; + } + $semicolonCount += 1; + } + + if ($initEnd === null || $conditionStart === null || $conditionEnd === null || $incrementStart === null) { + throw new \Exception("Cannot parse for loop at position {$forIndex}"); + } + + return new ForLoopInfo( + $forIndex, + $blockStart, + $blockEnd, + $initStart, + $initEnd, + $conditionStart, + $conditionEnd, + $incrementStart, + $incrementEnd + ); + } + + /** + * @param int $stackPtr + * @param array $forLoops + * @return ForLoopInfo|null + */ + public static function getForLoopForIncrementVariable($stackPtr, $forLoops) + { + foreach ($forLoops as $forLoop) { + if ($stackPtr > $forLoop->incrementStart && $stackPtr < $forLoop->incrementEnd) { + return $forLoop; + } + } + return null; + } + + /** + * Return true if the token looks like constructor promotion. + * + * Call on a parameter variable token only. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isConstructorPromotion(File $phpcsFile, $stackPtr) + { + $functionIndex = self::getFunctionIndexForFunctionParameter($phpcsFile, $stackPtr); + if (! $functionIndex) { + return false; + } + + $tokens = $phpcsFile->getTokens(); + + // If the previous token is a visibility keyword, this is constructor + // promotion. eg: `public $foobar`. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), $functionIndex, true); + if (! is_int($prev)) { + return false; + } + $prevToken = $tokens[$prev]; + if (in_array($prevToken['code'], Tokens::$scopeModifiers, true)) { + return true; + } + + // If the previous token is not a visibility keyword, but the one before it + // is, the previous token was probably a typehint and this is constructor + // promotion. eg: `public boolean $foobar`. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), $functionIndex, true); + if (! is_int($prev)) { + return false; + } + $prevToken = $tokens[$prev]; + if (in_array($prevToken['code'], Tokens::$scopeModifiers, true)) { + return true; + } + + return false; + } + + /** + * Return true if the token is inside an abstract class. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + public static function isInAbstractClass(File $phpcsFile, $stackPtr) + { + $classIndex = $phpcsFile->getCondition($stackPtr, T_CLASS); + if (! is_int($classIndex)) { + return false; + } + $classProperties = $phpcsFile->getClassProperties($classIndex); + return $classProperties['is_abstract']; + } + + /** + * Return true if the function body is empty or contains only `return;` + * + * @param File $phpcsFile + * @param int $stackPtr The index of the function keyword. + * + * @return bool + */ + public static function isFunctionBodyEmpty(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if ($tokens[$stackPtr]['code'] !== T_FUNCTION) { + return false; + } + $functionScopeStart = $tokens[$stackPtr]['scope_opener']; + $functionScopeEnd = $tokens[$stackPtr]['scope_closer']; + $tokensToIgnore = array_merge( + Tokens::$emptyTokens, + [ + T_RETURN, + T_SEMICOLON, + T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET, + ] + ); + for ($i = $functionScopeStart; $i < $functionScopeEnd; $i++) { + if (! in_array($tokens[$i]['code'], $tokensToIgnore, true)) { + return false; + } + } + return true; + } +} diff --git a/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/ScopeInfo.php b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/ScopeInfo.php new file mode 100644 index 00000000..45d12849 --- /dev/null +++ b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/ScopeInfo.php @@ -0,0 +1,40 @@ +scopeStartIndex = $scopeStartIndex; + $this->scopeEndIndex = $scopeEndIndex; + } +} diff --git a/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/ScopeManager.php b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/ScopeManager.php new file mode 100644 index 00000000..ae3b0297 --- /dev/null +++ b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/ScopeManager.php @@ -0,0 +1,108 @@ +> + */ + private $scopes = []; + + /** + * Add a scope's start and end index to our record for the file. + * + * @param File $phpcsFile + * @param int $scopeStartIndex + * + * @return ScopeInfo + */ + public function recordScopeStartAndEnd(File $phpcsFile, $scopeStartIndex) + { + $scopeEndIndex = Helpers::getScopeCloseForScopeOpen($phpcsFile, $scopeStartIndex); + $filename = $phpcsFile->getFilename(); + if (! isset($this->scopes[$filename])) { + $this->scopes[$filename] = []; + } + Helpers::debug('recording scope for file', $filename, 'start/end', $scopeStartIndex, $scopeEndIndex); + $scope = new ScopeInfo($scopeStartIndex, $scopeEndIndex); + $this->scopes[$filename][$scopeStartIndex] = $scope; + return $scope; + } + + /** + * Return the scopes for a file. + * + * @param string $filename + * + * @return ScopeInfo[] + */ + public function getScopesForFilename($filename) + { + if (empty($this->scopes[$filename])) { + return []; + } + return array_values($this->scopes[$filename]); + } + + /** + * Return the scope for a scope start index. + * + * @param string $filename + * @param int $scopeStartIndex + * + * @return ScopeInfo|null + */ + public function getScopeForScopeStart($filename, $scopeStartIndex) + { + if (empty($this->scopes[$filename][$scopeStartIndex])) { + return null; + } + return $this->scopes[$filename][$scopeStartIndex]; + } + + /** + * Find scopes closed by a scope close index. + * + * @param string $filename + * @param int $scopeEndIndex + * + * @return ScopeInfo[] + */ + public function getScopesForScopeEnd($filename, $scopeEndIndex) + { + $scopePairsForFile = $this->getScopesForFilename($filename); + $scopeIndicesThisCloses = array_reduce( + $scopePairsForFile, + /** + * @param ScopeInfo[] $found + * @param ScopeInfo $scope + * + * @return ScopeInfo[] + */ + function ($found, $scope) use ($scopeEndIndex) { + if (! is_int($scope->scopeEndIndex)) { + Helpers::debug('No scope closer found for scope start', $scope->scopeStartIndex); + return $found; + } + + if ($scopeEndIndex === $scope->scopeEndIndex) { + $found[] = $scope; + } + return $found; + }, + [] + ); + return $scopeIndicesThisCloses; + } +} diff --git a/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/ScopeType.php b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/ScopeType.php new file mode 100644 index 00000000..33171e48 --- /dev/null +++ b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Lib/ScopeType.php @@ -0,0 +1,12 @@ + + */ + public static $scopeTypeDescriptions = [ + ScopeType::LOCAL => 'variable', + ScopeType::PARAM => 'function parameter', + ScopeType::STATICSCOPE => 'static variable', + ScopeType::GLOBALSCOPE => 'global variable', + ScopeType::BOUND => 'bound variable', + ]; + + /** + * @param string $varName + */ + public function __construct($varName) + { + $this->name = $varName; + } +} diff --git a/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Sniffs/CodeAnalysis/VariableAnalysisSniff.php b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Sniffs/CodeAnalysis/VariableAnalysisSniff.php new file mode 100644 index 00000000..448c0f9e --- /dev/null +++ b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/Sniffs/CodeAnalysis/VariableAnalysisSniff.php @@ -0,0 +1,2068 @@ + + */ + private $forLoops = []; + + /** + * A list of custom functions which pass in variables to be initialized by + * reference (eg `preg_match()`) and therefore should not require those + * variables to be defined ahead of time. The list is space separated and + * each entry is of the form `functionName:1,2`. The function name comes + * first followed by a colon and a comma-separated list of argument numbers + * (starting from 1) which should be considered variable definitions. The + * special value `...` in the arguments list will cause all arguments after + * the last number to be considered variable definitions. + * + * @var string|null + */ + public $sitePassByRefFunctions = null; + + /** + * If set, allows common WordPress pass-by-reference functions in addition to + * the standard PHP ones. + * + * @var bool + */ + public $allowWordPressPassByRefFunctions = false; + + /** + * Allow exceptions in a catch block to be unused without warning. + * + * @var bool + */ + public $allowUnusedCaughtExceptions = true; + + /** + * Allow function parameters to be unused without provoking unused-var warning. + * + * @var bool + */ + public $allowUnusedFunctionParameters = false; + + /** + * If set, ignores undefined variables in the file scope (the top-level + * scope of a file). + * + * @var bool + */ + public $allowUndefinedVariablesInFileScope = false; + + /** + * If set, ignores unused variables in the file scope (the top-level + * scope of a file). + * + * @var bool + */ + public $allowUnusedVariablesInFileScope = false; + + /** + * A space-separated list of names of placeholder variables that you want to + * ignore from unused variable warnings. For example, to ignore the variables + * `$junk` and `$unused`, this could be set to `'junk unused'`. + * + * @var string|null + */ + public $validUnusedVariableNames = null; + + /** + * A PHP regexp string for variables that you want to ignore from unused + * variable warnings. For example, to ignore the variables `$_junk` and + * `$_unused`, this could be set to `'/^_/'`. + * + * @var string|null + */ + public $ignoreUnusedRegexp = null; + + /** + * A space-separated list of names of placeholder variables that you want to + * ignore from undefined variable warnings. For example, to ignore the variables + * `$post` and `$undefined`, this could be set to `'post undefined'`. + * + * @var string|null + */ + public $validUndefinedVariableNames = null; + + /** + * A PHP regexp string for variables that you want to ignore from undefined + * variable warnings. For example, to ignore the variables `$_junk` and + * `$_unused`, this could be set to `'/^_/'`. + * + * @var string|null + */ + public $validUndefinedVariableRegexp = null; + + /** + * Allows unused arguments in a function definition if they are + * followed by an argument which is used. + * + * @var bool + */ + public $allowUnusedParametersBeforeUsed = true; + + /** + * If set to true, unused values from the `key => value` syntax + * in a `foreach` loop will never be marked as unused. + * + * @var bool + */ + public $allowUnusedForeachVariables = true; + + /** + * If set to true, unused variables in a function before a require or import + * statement will not be marked as unused because they may be used in the + * required file. + * + * @var bool + */ + public $allowUnusedVariablesBeforeRequire = false; + + public function __construct() + { + $this->scopeManager = new ScopeManager(); + } + + /** + * Decide which tokens to scan. + * + * @return (int|string)[] + */ + public function register() + { + $types = [ + T_VARIABLE, + T_DOUBLE_QUOTED_STRING, + T_HEREDOC, + T_CLOSE_CURLY_BRACKET, + T_FUNCTION, + T_CLOSURE, + T_STRING, + T_COMMA, + T_SEMICOLON, + T_CLOSE_PARENTHESIS, + T_FOR, + T_ENDFOR, + ]; + if (defined('T_FN')) { + $types[] = T_FN; + } + return $types; + } + + /** + * @param string $functionName + * + * @return array + */ + private function getPassByReferenceFunction($functionName) + { + $passByRefFunctions = Constants::getPassByReferenceFunctions(); + if (!empty($this->sitePassByRefFunctions)) { + $lines = Helpers::splitStringToArray('/\s+/', trim($this->sitePassByRefFunctions)); + foreach ($lines as $line) { + list ($function, $args) = explode(':', $line); + $passByRefFunctions[$function] = explode(',', $args); + } + } + if ($this->allowWordPressPassByRefFunctions) { + $passByRefFunctions = array_merge($passByRefFunctions, Constants::getWordPressPassByReferenceFunctions()); + } + return isset($passByRefFunctions[$functionName]) ? $passByRefFunctions[$functionName] : []; + } + + /** + * Scan and process a token. + * + * This is the main processing function of the sniff. Will run on every token + * for which `register()` returns true. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $scopeStartTokenTypes = [ + T_FUNCTION, + T_CLOSURE, + ]; + + $token = $tokens[$stackPtr]; + + // Cache the current PHPCS File in an instance variable so it can be more + // easily accessed in other places which aren't passed the object. + if ($this->currentFile !== $phpcsFile) { + $this->currentFile = $phpcsFile; + $this->forLoops = []; + } + + // Add the global scope for the current file to our scope indexes. + $scopesForFilename = $this->scopeManager->getScopesForFilename($phpcsFile->getFilename()); + if (empty($scopesForFilename)) { + $this->scopeManager->recordScopeStartAndEnd($phpcsFile, 0); + } + + // Report variables defined but not used in the current scope as unused + // variables if the current token closes scopes. + $this->searchForAndProcessClosingScopesAt($phpcsFile, $stackPtr); + + // Scan variables that were postponed because they exist in the increment + // expression of a for loop if the current token closes a loop. + $this->processClosingForLoopsAt($phpcsFile, $stackPtr); + + // Find and process variables to perform two jobs: to record variable + // definition or use, and to report variables as undefined if they are used + // without having been first defined. + if ($token['code'] === T_VARIABLE) { + $this->processVariable($phpcsFile, $stackPtr); + return; + } + if (($token['code'] === T_DOUBLE_QUOTED_STRING) || ($token['code'] === T_HEREDOC)) { + $this->processVariableInString($phpcsFile, $stackPtr); + return; + } + if (($token['code'] === T_STRING) && ($token['content'] === 'compact')) { + $this->processCompact($phpcsFile, $stackPtr); + return; + } + + // Record for loop boundaries so we can delay scanning the third for loop + // expression until after the loop has been scanned. + if ($token['code'] === T_FOR) { + $this->recordForLoop($phpcsFile, $stackPtr); + return; + } + + // If the current token is a call to `get_defined_vars()`, consider that a + // usage of all variables in the current scope. + if ($this->isGetDefinedVars($phpcsFile, $stackPtr)) { + Helpers::debug('get_defined_vars is being called'); + $this->markAllVariablesRead($phpcsFile, $stackPtr); + return; + } + + // If the current token starts a scope, record that scope's start and end + // indexes so that we can determine if variables in that scope are defined + // and/or used. + if ( + in_array($token['code'], $scopeStartTokenTypes, true) || + Helpers::isArrowFunction($phpcsFile, $stackPtr) + ) { + Helpers::debug('found scope condition', $token); + $this->scopeManager->recordScopeStartAndEnd($phpcsFile, $stackPtr); + return; + } + } + + /** + * Record the boundaries of a for loop. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return void + */ + private function recordForLoop($phpcsFile, $stackPtr) + { + $this->forLoops[$stackPtr] = Helpers::makeForLoopInfo($phpcsFile, $stackPtr); + } + + /** + * Find scopes closed by a token and process their variables. + * + * Calls `processScopeClose()` for each closed scope. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return void + */ + private function searchForAndProcessClosingScopesAt($phpcsFile, $stackPtr) + { + $scopeIndicesThisCloses = $this->scopeManager->getScopesForScopeEnd($phpcsFile->getFilename(), $stackPtr); + + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + $line = $token['line']; + foreach ($scopeIndicesThisCloses as $scopeIndexThisCloses) { + Helpers::debug('found closing scope at index', $stackPtr, 'line', $line, 'for scopes starting at:', $scopeIndexThisCloses->scopeStartIndex); + $this->processScopeClose($phpcsFile, $scopeIndexThisCloses->scopeStartIndex); + } + } + + /** + * Scan variables that were postponed because they exist in the increment expression of a for loop. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return void + */ + private function processClosingForLoopsAt($phpcsFile, $stackPtr) + { + $forLoopsThisCloses = []; + foreach ($this->forLoops as $forLoop) { + if ($forLoop->blockEnd === $stackPtr) { + $forLoopsThisCloses[] = $forLoop; + } + } + + foreach ($forLoopsThisCloses as $forLoop) { + foreach ($forLoop->incrementVariables as $varIndex => $varInfo) { + Helpers::debug('processing delayed for loop increment variable at', $varIndex, $varInfo); + $this->processVariable($phpcsFile, $varIndex, ['ignore-for-loops' => true]); + } + } + } + + /** + * Return true if the token is a call to `get_defined_vars()`. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + protected function isGetDefinedVars(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + if (! $token || $token['content'] !== 'get_defined_vars') { + return false; + } + // Make sure this is a function call + $parenPointer = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if (! $parenPointer || $tokens[$parenPointer]['code'] !== T_OPEN_PARENTHESIS) { + return false; + } + return true; + } + + /** + * @return string + */ + protected function getFilename() + { + return $this->currentFile ? $this->currentFile->getFilename() : 'unknown file'; + } + + /** + * @param int $currScope + * + * @return ScopeInfo + */ + protected function getOrCreateScopeInfo($currScope) + { + $scope = $this->scopeManager->getScopeForScopeStart($this->getFilename(), $currScope); + if (! $scope) { + if (! $this->currentFile) { + throw new \Exception('Cannot create scope info; current file is not set.'); + } + $scope = $this->scopeManager->recordScopeStartAndEnd($this->currentFile, $currScope); + } + return $scope; + } + + /** + * @param string $varName + * @param int $currScope + * + * @return VariableInfo|null + */ + protected function getVariableInfo($varName, $currScope) + { + $scopeInfo = $this->scopeManager->getScopeForScopeStart($this->getFilename(), $currScope); + return ($scopeInfo && isset($scopeInfo->variables[$varName])) ? $scopeInfo->variables[$varName] : null; + } + + /** + * Returns variable data for a variable at an index. + * + * The variable will also be added to the list of variables stored in its + * scope so that its use or non-use can be reported when those scopes end by + * `processScopeClose()`. + * + * @param string $varName + * @param int $currScope + * + * @return VariableInfo + */ + protected function getOrCreateVariableInfo($varName, $currScope) + { + Helpers::debug("getOrCreateVariableInfo: starting for '{$varName}'"); + $scopeInfo = $this->getOrCreateScopeInfo($currScope); + if (isset($scopeInfo->variables[$varName])) { + Helpers::debug("getOrCreateVariableInfo: found variable for '{$varName}'", $scopeInfo->variables[$varName]); + return $scopeInfo->variables[$varName]; + } + Helpers::debug("getOrCreateVariableInfo: creating a new variable for '{$varName}' in scope", $scopeInfo); + $scopeInfo->variables[$varName] = new VariableInfo($varName); + $validUnusedVariableNames = (empty($this->validUnusedVariableNames)) + ? [] + : Helpers::splitStringToArray('/\s+/', trim($this->validUnusedVariableNames)); + $validUndefinedVariableNames = (empty($this->validUndefinedVariableNames)) + ? [] + : Helpers::splitStringToArray('/\s+/', trim($this->validUndefinedVariableNames)); + if (in_array($varName, $validUnusedVariableNames)) { + $scopeInfo->variables[$varName]->ignoreUnused = true; + } + if (isset($this->ignoreUnusedRegexp) && preg_match($this->ignoreUnusedRegexp, $varName) === 1) { + $scopeInfo->variables[$varName]->ignoreUnused = true; + } + if ($scopeInfo->scopeStartIndex === 0 && $this->allowUndefinedVariablesInFileScope) { + $scopeInfo->variables[$varName]->ignoreUndefined = true; + } + if (in_array($varName, $validUndefinedVariableNames)) { + $scopeInfo->variables[$varName]->ignoreUndefined = true; + } + if (isset($this->validUndefinedVariableRegexp) && preg_match($this->validUndefinedVariableRegexp, $varName) === 1) { + $scopeInfo->variables[$varName]->ignoreUndefined = true; + } + Helpers::debug("getOrCreateVariableInfo: scope for '{$varName}' is now", $scopeInfo); + return $scopeInfo->variables[$varName]; + } + + /** + * Record that a variable has been defined and assigned a value. + * + * If a variable has been defined within a scope, it will not be marked as + * undefined when that variable is later used. If it is not used, it will be + * marked as unused when that scope ends. + * + * Sometimes it's possible to assign something to a variable without + * definining it (eg: assignment to a reference); in that case, use + * `markVariableAssignmentWithoutInitialization()`. + * + * @param string $varName + * @param int $stackPtr + * @param int $currScope + * + * @return void + */ + protected function markVariableAssignment($varName, $stackPtr, $currScope) + { + Helpers::debug('markVariableAssignment: starting for', $varName); + $this->markVariableAssignmentWithoutInitialization($varName, $stackPtr, $currScope); + Helpers::debug('markVariableAssignment: marked as assigned without initialization', $varName); + $varInfo = $this->getOrCreateVariableInfo($varName, $currScope); + if (isset($varInfo->firstInitialized) && ($varInfo->firstInitialized <= $stackPtr)) { + Helpers::debug('markVariableAssignment: variable is already initialized', $varName); + return; + } + $varInfo->firstInitialized = $stackPtr; + Helpers::debug('markVariableAssignment: marked as initialized', $varName); + } + + /** + * Record that a variable has been assigned a value. + * + * Does not record that a variable has been defined, which is the usual state + * of affairs. For that, use `markVariableAssignment()`. + * + * This is useful for assignments to references. + * + * @param string $varName + * @param int $stackPtr + * @param int $currScope + * + * @return void + */ + protected function markVariableAssignmentWithoutInitialization($varName, $stackPtr, $currScope) + { + $varInfo = $this->getOrCreateVariableInfo($varName, $currScope); + + // Is the variable referencing another variable? If so, mark that variable used also. + if ($varInfo->referencedVariableScope !== null && $varInfo->referencedVariableScope !== $currScope) { + // Don't do this if the referenced variable does not exist; eg: if it's going to be bound at runtime like in array_walk + if ($this->getVariableInfo($varInfo->name, $varInfo->referencedVariableScope)) { + Helpers::debug('markVariableAssignmentWithoutInitialization: marking referenced variable as assigned also', $varName); + $this->markVariableAssignment($varInfo->name, $stackPtr, $varInfo->referencedVariableScope); + } + } + + if (empty($varInfo->scopeType)) { + $varInfo->scopeType = ScopeType::LOCAL; + } + $varInfo->allAssignments[] = $stackPtr; + } + + /** + * Record that a variable has been defined within a scope. + * + * @param string $varName + * @param ScopeType::PARAM|ScopeType::BOUND|ScopeType::LOCAL|ScopeType::GLOBALSCOPE|ScopeType::STATICSCOPE $scopeType + * @param ?string $typeHint + * @param int $stackPtr + * @param int $currScope + * @param ?bool $permitMatchingRedeclaration + * + * @return void + */ + protected function markVariableDeclaration( + $varName, + $scopeType, + $typeHint, + $stackPtr, + $currScope, + $permitMatchingRedeclaration = false + ) { + Helpers::debug("marking variable '{$varName}' declared in scope starting at token", $currScope); + $varInfo = $this->getOrCreateVariableInfo($varName, $currScope); + + if (! empty($varInfo->scopeType)) { + if (($permitMatchingRedeclaration === false) || ($varInfo->scopeType !== $scopeType)) { + // Issue redeclaration/reuse warning + // Note: we check off scopeType not firstDeclared, this is so that + // we catch declarations that come after implicit declarations like + // use of a variable as a local. + $this->addWarning( + 'Redeclaration of %s %s as %s.', + $stackPtr, + 'VariableRedeclaration', + [ + VariableInfo::$scopeTypeDescriptions[$varInfo->scopeType], + "\${$varName}", + VariableInfo::$scopeTypeDescriptions[$scopeType], + ] + ); + } + } + + $varInfo->scopeType = $scopeType; + if (isset($typeHint)) { + $varInfo->typeHint = $typeHint; + } + if (isset($varInfo->firstDeclared) && ($varInfo->firstDeclared <= $stackPtr)) { + Helpers::debug("variable '{$varName}' was already marked declared", $varInfo); + return; + } + $varInfo->firstDeclared = $stackPtr; + $varInfo->allAssignments[] = $stackPtr; + Helpers::debug("variable '{$varName}' marked declared", $varInfo); + } + + /** + * @param string $message + * @param int $stackPtr + * @param string $code + * @param string[] $data + * + * @return void + */ + protected function addWarning($message, $stackPtr, $code, $data) + { + if (! $this->currentFile) { + throw new \Exception('Cannot add warning; current file is not set.'); + } + $this->currentFile->addWarning( + $message, + $stackPtr, + $code, + $data + ); + } + + /** + * Record that a variable has been used within a scope. + * + * If the variable has not been defined first, this will still mark it used. + * To display a warning for undefined variables, use + * `markVariableReadAndWarnIfUndefined()`. + * + * @param string $varName + * @param int $stackPtr + * @param int $currScope + * + * @return void + */ + protected function markVariableRead($varName, $stackPtr, $currScope) + { + $varInfo = $this->getOrCreateVariableInfo($varName, $currScope); + if (isset($varInfo->firstRead) && ($varInfo->firstRead <= $stackPtr)) { + return; + } + $varInfo->firstRead = $stackPtr; + } + + /** + * Return true if a variable is defined within a scope. + * + * @param string $varName + * @param int $stackPtr + * @param int $currScope + * + * @return bool + */ + protected function isVariableUndefined($varName, $stackPtr, $currScope) + { + $varInfo = $this->getOrCreateVariableInfo($varName, $currScope); + Helpers::debug('isVariableUndefined', $varInfo, 'at', $stackPtr); + if ($varInfo->ignoreUndefined) { + return false; + } + if (isset($varInfo->firstDeclared) && $varInfo->firstDeclared <= $stackPtr) { + return false; + } + if (isset($varInfo->firstInitialized) && $varInfo->firstInitialized <= $stackPtr) { + return false; + } + // If we are inside a for loop increment expression, check to see if the + // variable was defined inside the for loop. + foreach ($this->forLoops as $forLoop) { + if ($stackPtr > $forLoop->incrementStart && $stackPtr < $forLoop->incrementEnd) { + Helpers::debug('isVariableUndefined looking at increment expression for loop', $forLoop); + if ( + isset($varInfo->firstInitialized) + && $varInfo->firstInitialized > $forLoop->blockStart + && $varInfo->firstInitialized < $forLoop->blockEnd + ) { + return false; + } + } + } + // If we are inside a for loop body, check to see if the variable was + // defined in that loop's third expression. + foreach ($this->forLoops as $forLoop) { + if ($stackPtr > $forLoop->blockStart && $stackPtr < $forLoop->blockEnd) { + foreach ($forLoop->incrementVariables as $forLoopVarInfo) { + if ($varInfo === $forLoopVarInfo) { + return false; + } + } + } + } + return true; + } + + /** + * Record a variable use and report a warning if the variable is undefined. + * + * @param File $phpcsFile + * @param string $varName + * @param int $stackPtr + * @param int $currScope + * + * @return void + */ + protected function markVariableReadAndWarnIfUndefined($phpcsFile, $varName, $stackPtr, $currScope) + { + $this->markVariableRead($varName, $stackPtr, $currScope); + if ($this->isVariableUndefined($varName, $stackPtr, $currScope) === true) { + Helpers::debug("variable $varName looks undefined"); + + if (Helpers::isVariableArrayPushShortcut($phpcsFile, $stackPtr)) { + $this->warnAboutUndefinedArrayPushShortcut($phpcsFile, $varName, $stackPtr); + // Mark the variable as defined if it's of the form `$x[] = 1;` + $this->markVariableAssignment($varName, $stackPtr, $currScope); + return; + } + + if (Helpers::isVariableInsideUnset($phpcsFile, $stackPtr)) { + $this->warnAboutUndefinedUnset($phpcsFile, $varName, $stackPtr); + return; + } + + $this->warnAboutUndefinedVariable($phpcsFile, $varName, $stackPtr); + } + } + + /** + * Mark all variables within a scope as being used. + * + * This will prevent any of the variables in that scope from being reported + * as unused. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return void + */ + protected function markAllVariablesRead(File $phpcsFile, $stackPtr) + { + $currScope = Helpers::findVariableScope($phpcsFile, $stackPtr); + if ($currScope === null) { + return; + } + $scopeInfo = $this->getOrCreateScopeInfo($currScope); + $count = count($scopeInfo->variables); + Helpers::debug("marking all $count variables in scope as read"); + foreach ($scopeInfo->variables as $varInfo) { + $this->markVariableRead($varInfo->name, $stackPtr, $scopeInfo->scopeStartIndex); + } + } + + /** + * Process a parameter definition if it is inside a function definition. + * + * This does not include variables imported by a "use" statement. + * + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName + * @param int $outerScope + * + * @return void + */ + protected function processVariableAsFunctionParameter(File $phpcsFile, $stackPtr, $varName, $outerScope) + { + Helpers::debug('processVariableAsFunctionParameter', $stackPtr, $varName); + $tokens = $phpcsFile->getTokens(); + + $functionPtr = Helpers::getFunctionIndexForFunctionParameter($phpcsFile, $stackPtr); + if (! is_int($functionPtr)) { + throw new \Exception("Function index not found for function argument index {$stackPtr}"); + } + + Helpers::debug('processVariableAsFunctionParameter found function definition', $tokens[$functionPtr]); + $this->markVariableDeclaration($varName, ScopeType::PARAM, null, $stackPtr, $functionPtr); + + // Are we pass-by-reference? + $referencePtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true, null, true); + if (($referencePtr !== false) && ($tokens[$referencePtr]['code'] === T_BITWISE_AND)) { + Helpers::debug('processVariableAsFunctionParameter found pass-by-reference to scope', $outerScope); + $varInfo = $this->getOrCreateVariableInfo($varName, $functionPtr); + $varInfo->referencedVariableScope = $outerScope; + } + + // Are we optional with a default? + if (Helpers::getNextAssignPointer($phpcsFile, $stackPtr) !== null) { + Helpers::debug('processVariableAsFunctionParameter optional with default'); + $this->markVariableAssignment($varName, $stackPtr, $functionPtr); + } + + // Are we using constructor promotion? If so, that counts as both definition and use. + if (Helpers::isConstructorPromotion($phpcsFile, $stackPtr)) { + Helpers::debug('processVariableAsFunctionParameter constructor promotion'); + $this->markVariableRead($varName, $stackPtr, $outerScope); + } + } + + /** + * Process a variable definition if it is inside a function's "use" import. + * + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName + * @param int $outerScope The start of the scope outside the function definition + * + * @return void + */ + protected function processVariableAsUseImportDefinition(File $phpcsFile, $stackPtr, $varName, $outerScope) + { + $tokens = $phpcsFile->getTokens(); + + Helpers::debug('processVariableAsUseImportDefinition', $stackPtr, $varName, $outerScope); + + $endOfArgsPtr = $phpcsFile->findPrevious([T_CLOSE_PARENTHESIS], $stackPtr - 1, null); + if (! is_int($endOfArgsPtr)) { + throw new \Exception("Arguments index not found for function use index {$stackPtr} when processing variable {$varName}"); + } + $functionPtr = Helpers::getFunctionIndexForFunctionParameter($phpcsFile, $endOfArgsPtr); + if (! is_int($functionPtr)) { + throw new \Exception("Function index not found for function use index {$stackPtr} (using {$endOfArgsPtr}) when processing variable {$varName}"); + } + + // Use is both a read (in the enclosing scope) and a define (in the function scope) + $this->markVariableRead($varName, $stackPtr, $outerScope); + + // If it's undefined in the enclosing scope, the use is wrong + if ($this->isVariableUndefined($varName, $stackPtr, $outerScope) === true) { + Helpers::debug("variable '{$varName}' in function definition looks undefined in scope", $outerScope); + $this->warnAboutUndefinedVariable($phpcsFile, $varName, $stackPtr); + return; + } + + $this->markVariableDeclaration($varName, ScopeType::BOUND, null, $stackPtr, $functionPtr); + $this->markVariableAssignment($varName, $stackPtr, $functionPtr); + + // Are we pass-by-reference? If so, then any assignment to the variable in + // the function scope also should count for the enclosing scope. + $referencePtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true, null, true); + if (is_int($referencePtr) && $tokens[$referencePtr]['code'] === T_BITWISE_AND) { + Helpers::debug("variable '{$varName}' in function definition looks passed by reference"); + $varInfo = $this->getOrCreateVariableInfo($varName, $functionPtr); + $varInfo->referencedVariableScope = $outerScope; + } + } + + /** + * Process a class property that is being defined. + * + * Property definitions are ignored currently because all property access is + * legal, even to undefined properties. + * + * Can be called for any token and will return false if the variable is not + * of this type. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + protected function processVariableAsClassProperty(File $phpcsFile, $stackPtr) + { + $propertyDeclarationKeywords = [ + T_PUBLIC, + T_PRIVATE, + T_PROTECTED, + T_VAR, + ]; + $stopAtPtr = $stackPtr - 2; + $visibilityPtr = $phpcsFile->findPrevious($propertyDeclarationKeywords, $stackPtr - 1, $stopAtPtr > 0 ? $stopAtPtr : 0); + if ($visibilityPtr) { + return true; + } + $staticPtr = $phpcsFile->findPrevious(T_STATIC, $stackPtr - 1, $stopAtPtr > 0 ? $stopAtPtr : 0); + if (! $staticPtr) { + return false; + } + $stopAtPtr = $staticPtr - 2; + $visibilityPtr = $phpcsFile->findPrevious($propertyDeclarationKeywords, $staticPtr - 1, $stopAtPtr > 0 ? $stopAtPtr : 0); + if ($visibilityPtr) { + return true; + } + // it's legal to use `static` to define properties as well as to + // define variables, so make sure we are not in a function before + // assuming it's a property. + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + if ($token && !empty($token['conditions']) && !Helpers::areConditionsWithinFunctionBeforeClass($token['conditions'])) { + return Helpers::areAnyConditionsAClass($token['conditions']); + } + return false; + } + + /** + * Process a variable that is being accessed inside a catch block. + * + * Can be called for any token and will return false if the variable is not + * of this type. + * + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName + * @param int $currScope + * + * @return bool + */ + protected function processVariableAsCatchBlock(File $phpcsFile, $stackPtr, $varName, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Are we a catch block parameter? + $openPtr = Helpers::findContainingOpeningBracket($phpcsFile, $stackPtr); + if ($openPtr === null) { + return false; + } + + $catchPtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $openPtr - 1, null, true, null, true); + if (($catchPtr !== false) && ($tokens[$catchPtr]['code'] === T_CATCH)) { + // Scope of the exception var is actually the function, not just the catch block. + $this->markVariableDeclaration($varName, ScopeType::LOCAL, null, $stackPtr, $currScope, true); + $this->markVariableAssignment($varName, $stackPtr, $currScope); + if ($this->allowUnusedCaughtExceptions) { + $varInfo = $this->getOrCreateVariableInfo($varName, $currScope); + $varInfo->ignoreUnused = true; + } + return true; + } + return false; + } + + /** + * Process a variable that is being accessed as a member of `$this`. + * + * Looks for variables of the form `$this->myVariable`. + * + * Can be called for any token and will return false if the variable is not + * of this type. + * + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName + * + * @return bool + */ + protected function processVariableAsThisWithinClass(File $phpcsFile, $stackPtr, $varName) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Are we $this within a class? + if (($varName !== 'this') || empty($token['conditions'])) { + return false; + } + + $inFunction = false; + foreach (array_reverse($token['conditions'], true) as $scopeCode) { + // $this within a closure is valid + if ($scopeCode === T_CLOSURE && $inFunction === false) { + return true; + } + if ($scopeCode === T_CLASS || $scopeCode === T_ANON_CLASS || $scopeCode === T_TRAIT) { + return true; + } + + // Handle nested function declarations. + if ($scopeCode === T_FUNCTION) { + if ($inFunction === true) { + break; + } + + $inFunction = true; + } + } + + return false; + } + + /** + * Process a superglobal variable that is being accessed. + * + * Can be called for any token and will return false if the variable is not + * of this type. + * + * @param string $varName + * + * @return bool + */ + protected function processVariableAsSuperGlobal($varName) + { + $superglobals = [ + 'GLOBALS', + '_SERVER', + '_GET', + '_POST', + '_FILES', + '_COOKIE', + '_SESSION', + '_REQUEST', + '_ENV', + 'argv', + 'argc', + 'http_response_header', + 'HTTP_RAW_POST_DATA', + ]; + // Are we a superglobal variable? + return (in_array($varName, $superglobals, true)); + } + + /** + * Process a variable that is being accessed with static syntax. + * + * That is, this will record the use of a variable of the form + * `MyClass::$myVariable` or `self::$myVariable`. + * + * Can be called for any token and will return false if the variable is not + * of this type. + * + * @param File $phpcsFile + * @param int $stackPtr + * + * @return bool + */ + protected function processVariableAsStaticMember(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $doubleColonPtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); + if ($doubleColonPtr === false || $tokens[$doubleColonPtr]['code'] !== T_DOUBLE_COLON) { + return false; + } + $classNamePtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $doubleColonPtr - 1, null, true); + $staticReferences = [ + T_STRING, + T_SELF, + T_PARENT, + T_STATIC, + T_VARIABLE, + ]; + if ($classNamePtr === false || ! in_array($tokens[$classNamePtr]['code'], $staticReferences, true)) { + return false; + } + // "When calling static methods, the function call is stronger than the + // static property operator" so look for a function call. + $parenPointer = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($parenPointer !== false && $tokens[$parenPointer]['code'] === T_OPEN_PARENTHESIS) { + return false; + } + return true; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName + * + * @return bool + */ + protected function processVariableAsStaticOutsideClass(File $phpcsFile, $stackPtr, $varName) + { + // Are we refering to self:: outside a class? + + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + $doubleColonPtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); + if ($doubleColonPtr === false || $tokens[$doubleColonPtr]['code'] !== T_DOUBLE_COLON) { + return false; + } + $classNamePtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $doubleColonPtr - 1, null, true); + if ($classNamePtr === false) { + return false; + } + $code = $tokens[$classNamePtr]['code']; + $staticReferences = [ + T_SELF, + T_STATIC, + ]; + if (! in_array($code, $staticReferences, true)) { + return false; + } + $errorClass = $code === T_SELF ? 'SelfOutsideClass' : 'StaticOutsideClass'; + $staticRefType = $code === T_SELF ? 'self::' : 'static::'; + if (!empty($token['conditions']) && Helpers::areAnyConditionsAClass($token['conditions'])) { + return false; + } + $phpcsFile->addError( + "Use of {$staticRefType}%s outside class definition.", + $stackPtr, + $errorClass, + ["\${$varName}"] + ); + return true; + } + + /** + * Process a variable that is being assigned. + * + * This will record that the variable has been defined within a scope so that + * later we can determine if it it unused and we can guarantee that any + * future uses of the variable are not using an undefined variable. + * + * References (on either side of an assignment) behave differently and this + * function handles those cases as well. + * + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName + * @param int $currScope + * + * @return void + */ + protected function processVariableAsAssignment(File $phpcsFile, $stackPtr, $varName, $currScope) + { + Helpers::debug("processVariableAsAssignment: starting for '{$varName}'"); + $assignPtr = Helpers::getNextAssignPointer($phpcsFile, $stackPtr); + if (! is_int($assignPtr)) { + return; + } + + // If the right-hand-side of the assignment to this variable is a reference + // variable, then this variable is a reference to that one, and as such any + // assignment to this variable (except another assignment by reference, + // which would change the binding) has a side effect of changing the + // referenced variable and therefore should count as both an assignment and + // a read. + $tokens = $phpcsFile->getTokens(); + $referencePtr = $phpcsFile->findNext(Tokens::$emptyTokens, $assignPtr + 1, null, true, null, true); + if (is_int($referencePtr) && $tokens[$referencePtr]['code'] === T_BITWISE_AND) { + Helpers::debug('processVariableAsAssignment: found reference variable'); + $varInfo = $this->getOrCreateVariableInfo($varName, $currScope); + // If the variable was already declared, but was not yet read, it is + // unused because we're about to change the binding; that is, unless we + // are inside a conditional block because in that case the condition may + // never activate. + $scopeInfo = $this->getOrCreateScopeInfo($currScope); + $ifPtr = Helpers::getClosestIfPositionIfBeforeOtherConditions($tokens[$referencePtr]['conditions']); + $lastAssignmentPtr = $varInfo->firstDeclared; + if (! $ifPtr && $lastAssignmentPtr) { + $this->processScopeCloseForVariable($phpcsFile, $varInfo, $scopeInfo); + } + if ($ifPtr && $lastAssignmentPtr && $ifPtr <= $lastAssignmentPtr) { + $this->processScopeCloseForVariable($phpcsFile, $varInfo, $scopeInfo); + } + // The referenced variable may have a different name, but we don't + // actually need to mark it as used in this case because the act of this + // assignment will mark it used on the next token. + $varInfo->referencedVariableScope = $currScope; + $this->markVariableDeclaration($varName, ScopeType::LOCAL, null, $stackPtr, $currScope, true); + // An assignment to a reference is a binding and should not count as + // initialization since it doesn't change any values. + $this->markVariableAssignmentWithoutInitialization($varName, $stackPtr, $currScope); + return; + } + + Helpers::debug('processVariableAsAssignment: marking as assignment in scope', $currScope); + $this->markVariableAssignment($varName, $stackPtr, $currScope); + + // If the left-hand-side of the assignment (the variable we are examining) + // is itself a reference, then that counts as a read as well as a write. + $varInfo = $this->getOrCreateVariableInfo($varName, $currScope); + if ($varInfo->isDynamicReference) { + Helpers::debug('processVariableAsAssignment: also marking as a use because variable is a reference'); + $this->markVariableRead($varName, $stackPtr, $currScope); + } + } + + /** + * Processes variables destructured from an array using shorthand list assignment. + * + * This will record the definition and assignment of variables defined using + * the format: + * + * ``` + * [ $foo, $bar, $baz ] = $ary; + * ``` + * + * Can be called for any token and will return false if the variable is not + * of this type. + * + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName + * @param int $currScope + * + * @return bool + */ + protected function processVariableAsListShorthandAssignment(File $phpcsFile, $stackPtr, $varName, $currScope) + { + // OK, are we within a [ ... ] construct? + $openPtr = Helpers::findContainingOpeningSquareBracket($phpcsFile, $stackPtr); + if (! is_int($openPtr)) { + return false; + } + + // OK, we're a [ ... ] construct... are we being assigned to? + $assignments = Helpers::getListAssignments($phpcsFile, $openPtr); + if (! $assignments) { + return false; + } + $matchingAssignment = array_reduce($assignments, function ($thisAssignment, $assignment) use ($stackPtr) { + if ($assignment === $stackPtr) { + return $assignment; + } + return $thisAssignment; + }); + if (! $matchingAssignment) { + return false; + } + + // Yes, we're being assigned. + $this->markVariableAssignment($varName, $stackPtr, $currScope); + return true; + } + + /** + * Processes variables destructured from an array using list assignment. + * + * This will record the definition and assignment of variables defined using + * the format: + * + * ``` + * list( $foo, $bar, $baz ) = $ary; + * ``` + * + * Can be called for any token and will return false if the variable is not + * of this type. + * + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName + * @param int $currScope + * + * @return bool + */ + protected function processVariableAsListAssignment(File $phpcsFile, $stackPtr, $varName, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // OK, are we within a list (...) construct? + $openPtr = Helpers::findContainingOpeningBracket($phpcsFile, $stackPtr); + if ($openPtr === null) { + return false; + } + + $prevPtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $openPtr - 1, null, true, null, true); + if ((is_bool($prevPtr)) || ($tokens[$prevPtr]['code'] !== T_LIST)) { + return false; + } + + // OK, we're a list (...) construct... are we being assigned to? + $assignments = Helpers::getListAssignments($phpcsFile, $prevPtr); + if (! $assignments) { + return false; + } + $matchingAssignment = array_reduce($assignments, function ($thisAssignment, $assignment) use ($stackPtr) { + if ($assignment === $stackPtr) { + return $assignment; + } + return $thisAssignment; + }); + if (! $matchingAssignment) { + return false; + } + + // Yes, we're being assigned. + $this->markVariableAssignment($varName, $stackPtr, $currScope); + return true; + } + + /** + * Process a variable being defined (imported, really) with the `global` keyword. + * + * Can be called for any token and will return false if the variable is not + * of this type. + * + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName + * @param int $currScope + * + * @return bool + */ + protected function processVariableAsGlobalDeclaration(File $phpcsFile, $stackPtr, $varName, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Are we a global declaration? + // Search backwards for first token that isn't whitespace/comment, comma or variable. + $ignore = Tokens::$emptyTokens; + $ignore[T_VARIABLE] = T_VARIABLE; + $ignore[T_COMMA] = T_COMMA; + + $globalPtr = $phpcsFile->findPrevious($ignore, $stackPtr - 1, null, true, null, true); + if (($globalPtr === false) || ($tokens[$globalPtr]['code'] !== T_GLOBAL)) { + return false; + } + + // It's a global declaration. + $this->markVariableDeclaration($varName, ScopeType::GLOBALSCOPE, null, $stackPtr, $currScope); + return true; + } + + /** + * Process a variable as a static declaration within a function. + * + * Specifically, this looks for variable definitions of the form `static + * $foo = 'hello';` or `static int $foo;` inside a function definition. + * + * This will not operate on variables that are written in a class definition + * outside of a function like `static $foo;` or `public static ?int $foo = + * 'bar';` because class properties (static or instance) are currently not + * tracked by this sniff. This is because a class property might be unused + * inside the class, but used outside the class (we cannot easily know if it + * is unused); this is also because it's common and legal to define class + * properties when they are assigned and that assignment can happen outside a + * class (we cannot easily know if the use of a property is undefined). These + * sorts of checks are better performed by static analysis tools that can see + * a whole project rather than a linter which can only easily see a file or + * some lines. + * + * If found, such a variable will be marked as declared (and possibly + * assigned, if it includes an initial value) within the scope of the + * function body. + * + * This will not operate on variables that use late static binding + * (`static::$foobar`) or the parameters of static methods even though they + * include the word `static` in the same statement. + * + * This only finds the defintions of static variables. Their use is handled + * by `processVariableAsStaticMember()`. + * + * Can be called for any token and will return false if the variable is not + * of this type. + * + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName + * @param int $currScope + * + * @return bool + */ + protected function processVariableAsStaticDeclaration(File $phpcsFile, $stackPtr, $varName, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Search backwards for a `static` keyword that occurs before the start of the statement. + $startOfStatement = $phpcsFile->findPrevious([T_SEMICOLON, T_OPEN_CURLY_BRACKET, T_FN_ARROW, T_OPEN_PARENTHESIS], $stackPtr - 1, null, false, null, true); + $staticPtr = $phpcsFile->findPrevious([T_STATIC], $stackPtr - 1, null, false, null, true); + if (! is_int($startOfStatement)) { + $startOfStatement = 1; + } + if (! is_int($staticPtr)) { + return false; + } + // PHPCS is bad at finding the start of statements so we have to do it ourselves. + if ($staticPtr < $startOfStatement) { + return false; + } + + // Is the 'static' keyword an anonymous static function declaration? If so, + // this is not a static variable declaration. + $tokenAfterStatic = $phpcsFile->findNext(Tokens::$emptyTokens, $staticPtr + 1, null, true, null, true); + $functionTokenTypes = [ + T_FUNCTION, + T_CLOSURE, + T_FN, + ]; + if (is_int($tokenAfterStatic) && in_array($tokens[$tokenAfterStatic]['code'], $functionTokenTypes, true)) { + return false; + } + + // Is the token inside function parameters? If so, this is not a static + // declaration because we must be inside a function body. + if (Helpers::isTokenFunctionParameter($phpcsFile, $stackPtr)) { + return false; + } + + // Is the token inside a function call? If so, this is not a static + // declaration. + if (Helpers::isTokenInsideFunctionCallArgument($phpcsFile, $stackPtr)) { + return false; + } + + // Is the keyword a late static binding? If so, this isn't the static + // keyword we're looking for, but since static:: isn't allowed in a + // compile-time constant, we also know we can't be part of a static + // declaration anyway, so there's no need to look any further. + $lateStaticBindingPtr = $phpcsFile->findNext(T_WHITESPACE, $staticPtr + 1, null, true, null, true); + if (($lateStaticBindingPtr !== false) && ($tokens[$lateStaticBindingPtr]['code'] === T_DOUBLE_COLON)) { + return false; + } + + $this->markVariableDeclaration($varName, ScopeType::STATICSCOPE, null, $stackPtr, $currScope); + if (Helpers::getNextAssignPointer($phpcsFile, $stackPtr) !== null) { + $this->markVariableAssignment($varName, $stackPtr, $currScope); + } + return true; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName + * @param int $currScope + * + * @return bool + */ + protected function processVariableAsForeachLoopVar(File $phpcsFile, $stackPtr, $varName, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Are we a foreach loopvar? + $openParenPtr = Helpers::findContainingOpeningBracket($phpcsFile, $stackPtr); + if (! is_int($openParenPtr)) { + return false; + } + $foreachPtr = Helpers::getIntOrNull($phpcsFile->findPrevious(Tokens::$emptyTokens, $openParenPtr - 1, null, true)); + if (! is_int($foreachPtr)) { + return false; + } + if ($tokens[$foreachPtr]['code'] === T_LIST) { + $openParenPtr = Helpers::findContainingOpeningBracket($phpcsFile, $foreachPtr); + if (! is_int($openParenPtr)) { + return false; + } + $foreachPtr = Helpers::getIntOrNull($phpcsFile->findPrevious(Tokens::$emptyTokens, $openParenPtr - 1, null, true)); + if (! is_int($foreachPtr)) { + return false; + } + } + if ($tokens[$foreachPtr]['code'] !== T_FOREACH) { + return false; + } + + // Is there an 'as' token between us and the foreach? + if ($phpcsFile->findPrevious(T_AS, $stackPtr - 1, $openParenPtr) === false) { + return false; + } + $this->markVariableAssignment($varName, $stackPtr, $currScope); + $varInfo = $this->getOrCreateVariableInfo($varName, $currScope); + + // Is this the value of a key => value foreach? + if ($phpcsFile->findPrevious(T_DOUBLE_ARROW, $stackPtr - 1, $openParenPtr) !== false) { + $varInfo->isForeachLoopAssociativeValue = true; + } + + // Are we pass-by-reference? + $referencePtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true, null, true); + if (($referencePtr !== false) && ($tokens[$referencePtr]['code'] === T_BITWISE_AND)) { + Helpers::debug('processVariableAsForeachLoopVar: found foreach loop variable assigned by reference'); + $varInfo->isDynamicReference = true; + } + + return true; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName + * @param int $currScope + * + * @return bool + */ + protected function processVariableAsPassByReferenceFunctionCall(File $phpcsFile, $stackPtr, $varName, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Are we pass-by-reference to known pass-by-reference function? + $functionPtr = Helpers::findFunctionCall($phpcsFile, $stackPtr); + if ($functionPtr === null || ! isset($tokens[$functionPtr])) { + return false; + } + + // Is our function a known pass-by-reference function? + $functionName = $tokens[$functionPtr]['content']; + $refArgs = $this->getPassByReferenceFunction($functionName); + if (! $refArgs) { + return false; + } + + $argPtrs = Helpers::findFunctionCallArguments($phpcsFile, $stackPtr); + + // We're within a function call arguments list, find which arg we are. + $argPos = false; + foreach ($argPtrs as $idx => $ptrs) { + if (in_array($stackPtr, $ptrs)) { + $argPos = $idx + 1; + break; + } + } + if ($argPos === false) { + return false; + } + if (!in_array($argPos, $refArgs)) { + // Our arg wasn't mentioned explicitly, are we after an elipsis catch-all? + $elipsis = array_search('...', $refArgs); + if ($elipsis === false) { + return false; + } + $elipsis = (int)$elipsis; + if ($argPos < $refArgs[$elipsis - 1]) { + return false; + } + } + + // Our argument position matches that of a pass-by-ref argument, + // check that we're the only part of the argument expression. + foreach ($argPtrs[$argPos - 1] as $ptr) { + if ($ptr === $stackPtr) { + continue; + } + if (isset(Tokens::$emptyTokens[$tokens[$ptr]['code']]) === false) { + return false; + } + } + + // Just us, we can mark it as a write. + $this->markVariableAssignment($varName, $stackPtr, $currScope); + // It's a read as well for purposes of used-variables. + $this->markVariableRead($varName, $stackPtr, $currScope); + return true; + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName + * @param int $currScope + * + * @return bool + */ + protected function processVariableAsSymbolicObjectProperty(File $phpcsFile, $stackPtr, $varName, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Are we a symbolic object property/function derefeference? + // Search backwards for first token that isn't whitespace, is it a "->" operator? + $objectOperatorPtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true, null, true); + if (($objectOperatorPtr === false) || ($tokens[$objectOperatorPtr]['code'] !== T_OBJECT_OPERATOR)) { + return false; + } + + $this->markVariableReadAndWarnIfUndefined($phpcsFile, $varName, $stackPtr, $currScope); + return true; + } + + /** + * Process a normal variable in the code. + * + * Most importantly, this function determines if the variable use is a "read" + * (using the variable for something) or a "write" (an assignment) or, + * sometimes, both at once. + * + * It also determines the scope of the variable (where it begins and ends). + * + * Using these two pieces of information, we can determine if the variable is + * being used ("read") without having been defined ("write"). + * + * We can also determine, once the scan has hit the end of a scope, if any of + * the variables within that scope have been defined ("write") without being + * used ("read"). That behavior, however, happens in the `processScopeClose()` + * function using the data gathered by this function. + * + * Some variables are used in more complex ways, so there are other similar + * functions to this one, like `processVariableInString`, and + * `processCompact`. They have the same purpose as this function, though. + * + * If the 'ignore-for-loops' option is true, we will ignore the special + * processing for the increment variables of for loops. This will prevent + * infinite loops. + * + * @param File $phpcsFile The PHP_CodeSniffer file where this token was found. + * @param int $stackPtr The position where the token was found. + * @param array $options See above. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr, $options = []) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Get the name of the variable. + $varName = Helpers::normalizeVarName($token['content']); + Helpers::debug("examining token for variable '{$varName}' on line {$token['line']}", $token); + + // Find the start of the current scope. + $currScope = Helpers::findVariableScope($phpcsFile, $stackPtr); + if ($currScope === null) { + Helpers::debug('no scope found'); + return; + } + Helpers::debug("start of scope for variable '{$varName}' is", $currScope); + + // Determine if variable is being assigned ("write") or used ("read"). + + // Read methods that preempt assignment: + // Are we a $object->$property type symbolic reference? + + // Possible assignment methods: + // Is a mandatory function/closure parameter + // Is an optional function/closure parameter with non-null value + // Is closure use declaration of a variable defined within containing scope + // catch (...) block start + // $this within a class. + // $GLOBALS, $_REQUEST, etc superglobals. + // $var part of class::$var static member + // Assignment via = + // Assignment via list (...) = + // Declares as a global + // Declares as a static + // Assignment via foreach (... as ...) { } + // Pass-by-reference to known pass-by-reference function + + // Are we inside the third expression of a for loop? Store such variables + // for processing after the loop ends by `processClosingForLoopsAt()`. + if (empty($options['ignore-for-loops'])) { + $forLoop = Helpers::getForLoopForIncrementVariable($stackPtr, $this->forLoops); + if ($forLoop) { + Helpers::debug('found variable inside for loop third expression'); + $varInfo = $this->getOrCreateVariableInfo($varName, $currScope); + $forLoop->incrementVariables[$stackPtr] = $varInfo; + return; + } + } + + // Are we a $object->$property type symbolic reference? + if ($this->processVariableAsSymbolicObjectProperty($phpcsFile, $stackPtr, $varName, $currScope)) { + Helpers::debug('found symbolic object property'); + return; + } + + // Are we a function or closure parameter? + if (Helpers::isTokenFunctionParameter($phpcsFile, $stackPtr)) { + Helpers::debug('found function definition parameter'); + $this->processVariableAsFunctionParameter($phpcsFile, $stackPtr, $varName, $currScope); + return; + } + + // Are we a variable being imported into a function's scope with "use"? + if (Helpers::isTokenInsideFunctionUseImport($phpcsFile, $stackPtr)) { + Helpers::debug('found use scope import definition'); + $this->processVariableAsUseImportDefinition($phpcsFile, $stackPtr, $varName, $currScope); + return; + } + + // Are we a catch parameter? + if ($this->processVariableAsCatchBlock($phpcsFile, $stackPtr, $varName, $currScope)) { + Helpers::debug('found catch block'); + return; + } + + // Are we $this within a class? + if ($this->processVariableAsThisWithinClass($phpcsFile, $stackPtr, $varName)) { + Helpers::debug('found this usage within a class'); + return; + } + + // Are we a $GLOBALS, $_REQUEST, etc superglobal? + if ($this->processVariableAsSuperGlobal($varName)) { + Helpers::debug('found superglobal'); + return; + } + + // Check for static members used outside a class + if ($this->processVariableAsStaticOutsideClass($phpcsFile, $stackPtr, $varName)) { + Helpers::debug('found static usage outside of class'); + return; + } + + // $var part of class::$var static member + if ($this->processVariableAsStaticMember($phpcsFile, $stackPtr)) { + Helpers::debug('found static member'); + return; + } + + if ($this->processVariableAsClassProperty($phpcsFile, $stackPtr)) { + Helpers::debug('found class property definition'); + return; + } + + // Is the next non-whitespace an assignment? + if (Helpers::isTokenInsideAssignmentLHS($phpcsFile, $stackPtr)) { + Helpers::debug('found assignment'); + $this->processVariableAsAssignment($phpcsFile, $stackPtr, $varName, $currScope); + if (Helpers::isTokenInsideAssignmentRHS($phpcsFile, $stackPtr) || Helpers::isTokenInsideFunctionCallArgument($phpcsFile, $stackPtr)) { + Helpers::debug("found assignment that's also inside an expression"); + $this->markVariableRead($varName, $stackPtr, $currScope); + return; + } + return; + } + + // OK, are we within a list (...) = construct? + if ($this->processVariableAsListAssignment($phpcsFile, $stackPtr, $varName, $currScope)) { + Helpers::debug('found list assignment'); + return; + } + + // OK, are we within a [...] = construct? + if ($this->processVariableAsListShorthandAssignment($phpcsFile, $stackPtr, $varName, $currScope)) { + Helpers::debug('found list shorthand assignment'); + return; + } + + // Are we a global declaration? + if ($this->processVariableAsGlobalDeclaration($phpcsFile, $stackPtr, $varName, $currScope)) { + Helpers::debug('found global declaration'); + return; + } + + // Are we a static declaration? + if ($this->processVariableAsStaticDeclaration($phpcsFile, $stackPtr, $varName, $currScope)) { + Helpers::debug('found static declaration'); + return; + } + + // Are we a foreach loopvar? + if ($this->processVariableAsForeachLoopVar($phpcsFile, $stackPtr, $varName, $currScope)) { + Helpers::debug('found foreach loop variable'); + return; + } + + // Are we pass-by-reference to known pass-by-reference function? + if ($this->processVariableAsPassByReferenceFunctionCall($phpcsFile, $stackPtr, $varName, $currScope)) { + Helpers::debug('found pass by reference'); + return; + } + + // Are we a numeric variable used for constructs like preg_replace? + if (Helpers::isVariableANumericVariable($varName)) { + Helpers::debug('found numeric variable'); + return; + } + + if (Helpers::isVariableInsideElseCondition($phpcsFile, $stackPtr) || Helpers::isVariableInsideElseBody($phpcsFile, $stackPtr)) { + Helpers::debug('found variable inside else condition or body'); + $this->processVaribleInsideElse($phpcsFile, $stackPtr, $varName, $currScope); + return; + } + + // Are we an isset or empty call? + if (Helpers::isVariableInsideIssetOrEmpty($phpcsFile, $stackPtr)) { + Helpers::debug('found isset or empty'); + $this->markVariableRead($varName, $stackPtr, $currScope); + return; + } + + // OK, we don't appear to be a write to the var, assume we're a read. + Helpers::debug('looks like a variable read'); + $this->markVariableReadAndWarnIfUndefined($phpcsFile, $varName, $stackPtr, $currScope); + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @param string $varName + * @param int $currScope + * + * @return void + */ + protected function processVaribleInsideElse(File $phpcsFile, $stackPtr, $varName, $currScope) + { + // Find all assignments to this variable inside the current scope. + $varInfo = $this->getOrCreateVariableInfo($varName, $currScope); + $allAssignmentIndices = array_unique($varInfo->allAssignments); + // Find the attached 'if' and 'elseif' block start and end indices. + $blockIndices = Helpers::getAttachedBlockIndicesForElse($phpcsFile, $stackPtr); + + // If all of the assignments are within the previous attached blocks, then warn about undefined. + $tokens = $phpcsFile->getTokens(); + $assignmentsInsideAttachedBlocks = []; + foreach ($allAssignmentIndices as $index) { + foreach ($blockIndices as $blockIndex) { + $blockToken = $tokens[$blockIndex]; + Helpers::debug('for variable inside else, looking at assignment', $index, 'at block index', $blockIndex, 'which is token', $blockToken); + if (isset($blockToken['scope_opener']) && isset($blockToken['scope_closer'])) { + $scopeOpener = $blockToken['scope_opener']; + $scopeCloser = $blockToken['scope_closer']; + } else { + // If the `if` statement has no scope, it is probably inline, which + // means its scope is from the end of the condition up until the next + // semicolon + $scopeOpener = isset($blockToken['parenthesis_closer']) ? $blockToken['parenthesis_closer'] : $blockIndex + 1; + $scopeCloser = $phpcsFile->findNext([T_SEMICOLON], $scopeOpener); + if (! $scopeCloser) { + throw new \Exception("Cannot find scope for if condition block at index {$stackPtr} while examining variable {$varName}"); + } + } + Helpers::debug('for variable inside else, looking at scope', $index, 'between', $scopeOpener, 'and', $scopeCloser); + if (Helpers::isIndexInsideScope($index, $scopeOpener, $scopeCloser)) { + $assignmentsInsideAttachedBlocks[] = $index; + } + } + } + + if (count($assignmentsInsideAttachedBlocks) === count($allAssignmentIndices)) { + if (! $varInfo->ignoreUndefined) { + Helpers::debug("variable $varName inside else looks undefined"); + $this->warnAboutUndefinedVariable($phpcsFile, $varName, $stackPtr); + } + return; + } + + Helpers::debug('looks like a variable read inside else'); + $this->markVariableReadAndWarnIfUndefined($phpcsFile, $varName, $stackPtr, $currScope); + } + + /** + * Called to process variables found in double quoted strings. + * + * Note that there may be more than one variable in the string, which will + * result only in one call for the string. + * + * @param File $phpcsFile The PHP_CodeSniffer file where this token was found. + * @param int $stackPtr The position where the double quoted string was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + if (!preg_match_all(Constants::getDoubleQuotedVarRegexp(), $token['content'], $matches)) { + return; + } + Helpers::debug('examining token for variable in string', $token); + + foreach ($matches[1] as $varName) { + $varName = Helpers::normalizeVarName($varName); + + // Are we $this within a class? + if ($this->processVariableAsThisWithinClass($phpcsFile, $stackPtr, $varName)) { + continue; + } + + if ($this->processVariableAsSuperGlobal($varName)) { + continue; + } + + // Are we a numeric variable used for constructs like preg_replace? + if (Helpers::isVariableANumericVariable($varName)) { + continue; + } + + $currScope = Helpers::findVariableScope($phpcsFile, $stackPtr, $varName); + if ($currScope === null) { + continue; + } + + $this->markVariableReadAndWarnIfUndefined($phpcsFile, $varName, $stackPtr, $currScope); + } + } + + /** + * @param File $phpcsFile + * @param int $stackPtr + * @param array> $arguments The stack pointers of each argument + * @param int $currScope + * + * @return void + */ + protected function processCompactArguments(File $phpcsFile, $stackPtr, $arguments, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + foreach ($arguments as $argumentPtrs) { + $argumentPtrs = array_values(array_filter($argumentPtrs, function ($argumentPtr) use ($tokens) { + return isset(Tokens::$emptyTokens[$tokens[$argumentPtr]['code']]) === false; + })); + if (empty($argumentPtrs)) { + continue; + } + if (!isset($tokens[$argumentPtrs[0]])) { + continue; + } + $argumentFirstToken = $tokens[$argumentPtrs[0]]; + if ($argumentFirstToken['code'] === T_ARRAY) { + // It's an array argument, recurse. + $arrayArguments = Helpers::findFunctionCallArguments($phpcsFile, $argumentPtrs[0]); + $this->processCompactArguments($phpcsFile, $stackPtr, $arrayArguments, $currScope); + continue; + } + if (count($argumentPtrs) > 1) { + // Complex argument, we can't handle it, ignore. + continue; + } + if ($argumentFirstToken['code'] === T_CONSTANT_ENCAPSED_STRING) { + // Single-quoted string literal, ie compact('whatever'). + // Substr is to strip the enclosing single-quotes. + $varName = substr($argumentFirstToken['content'], 1, -1); + $this->markVariableReadAndWarnIfUndefined($phpcsFile, $varName, $argumentPtrs[0], $currScope); + continue; + } + if ($argumentFirstToken['code'] === T_DOUBLE_QUOTED_STRING) { + // Double-quoted string literal. + if (preg_match(Constants::getDoubleQuotedVarRegexp(), $argumentFirstToken['content'])) { + // Bail if the string needs variable expansion, that's runtime stuff. + continue; + } + // Substr is to strip the enclosing double-quotes. + $varName = substr($argumentFirstToken['content'], 1, -1); + $this->markVariableReadAndWarnIfUndefined($phpcsFile, $varName, $argumentPtrs[0], $currScope); + continue; + } + } + } + + /** + * Called to process variables named in a call to compact(). + * + * @param File $phpcsFile The PHP_CodeSniffer file where this token was found. + * @param int $stackPtr The position where the call to compact() was found. + * + * @return void + */ + protected function processCompact(File $phpcsFile, $stackPtr) + { + $currScope = Helpers::findVariableScope($phpcsFile, $stackPtr); + if ($currScope === null) { + return; + } + + $arguments = Helpers::findFunctionCallArguments($phpcsFile, $stackPtr); + $this->processCompactArguments($phpcsFile, $stackPtr, $arguments, $currScope); + } + + /** + * Called to process the end of a scope. + * + * Note that although triggered by the closing curly brace of the scope, + * $stackPtr is the scope conditional, not the closing curly brace. + * + * @param File $phpcsFile The PHP_CodeSniffer file where this token was found. + * @param int $stackPtr The position of the scope conditional. + * + * @return void + */ + protected function processScopeClose(File $phpcsFile, $stackPtr) + { + $scopeInfo = $this->scopeManager->getScopeForScopeStart($phpcsFile->getFilename(), $stackPtr); + if (is_null($scopeInfo)) { + return; + } + foreach ($scopeInfo->variables as $varInfo) { + $this->processScopeCloseForVariable($phpcsFile, $varInfo, $scopeInfo); + } + } + + /** + * Warn about an unused variable if it has not been used within a scope. + * + * @param File $phpcsFile + * @param VariableInfo $varInfo + * @param ScopeInfo $scopeInfo + * + * @return void + */ + protected function processScopeCloseForVariable(File $phpcsFile, VariableInfo $varInfo, ScopeInfo $scopeInfo) + { + Helpers::debug('processScopeCloseForVariable', $varInfo); + if ($varInfo->ignoreUnused || isset($varInfo->firstRead)) { + return; + } + if ($this->allowUnusedFunctionParameters && $varInfo->scopeType === ScopeType::PARAM) { + return; + } + if ($this->allowUnusedParametersBeforeUsed && $varInfo->scopeType === ScopeType::PARAM && Helpers::areFollowingArgumentsUsed($varInfo, $scopeInfo)) { + Helpers::debug("variable {$varInfo->name} at end of scope has unused following args"); + return; + } + if ($this->allowUnusedForeachVariables && $varInfo->isForeachLoopAssociativeValue) { + return; + } + if ($varInfo->referencedVariableScope !== null && isset($varInfo->firstInitialized)) { + // If we're pass-by-reference then it's a common pattern to + // use the variable to return data to the caller, so any + // assignment also counts as "variable use" for the purposes + // of "unused variable" warnings. + return; + } + if ($varInfo->scopeType === ScopeType::GLOBALSCOPE && isset($varInfo->firstInitialized)) { + // If we imported this variable from the global scope, any further use of + // the variable, including assignment, should count as "variable use" for + // the purposes of "unused variable" warnings. + return; + } + if (empty($varInfo->firstDeclared) && empty($varInfo->firstInitialized)) { + return; + } + if ($this->allowUnusedVariablesBeforeRequire && Helpers::isRequireInScopeAfter($phpcsFile, $varInfo, $scopeInfo)) { + return; + } + if ($scopeInfo->scopeStartIndex === 0 && $this->allowUnusedVariablesInFileScope) { + return; + } + if ( + ! empty($varInfo->firstDeclared) + && $varInfo->scopeType === ScopeType::PARAM + && Helpers::isInAbstractClass( + $phpcsFile, + Helpers::getFunctionIndexForFunctionParameter($phpcsFile, $varInfo->firstDeclared) ?: 0 + ) + && Helpers::isFunctionBodyEmpty( + $phpcsFile, + Helpers::getFunctionIndexForFunctionParameter($phpcsFile, $varInfo->firstDeclared) ?: 0 + ) + ) { + // Allow non-abstract methods inside an abstract class to have unused + // parameters if the method body does nothing. Such methods are + // effectively optional abstract methods so their unused parameters + // should be ignored as we do with abstract method parameters. + return; + } + + $this->warnAboutUnusedVariable($phpcsFile, $varInfo); + } + + /** + * Register warnings for a variable that is defined but not used. + * + * @param File $phpcsFile + * @param VariableInfo $varInfo + * + * @return void + */ + protected function warnAboutUnusedVariable(File $phpcsFile, VariableInfo $varInfo) + { + foreach (array_unique($varInfo->allAssignments) as $indexForWarning) { + Helpers::debug("variable {$varInfo->name} at end of scope looks unused"); + $phpcsFile->addWarning( + 'Unused %s %s.', + $indexForWarning, + 'UnusedVariable', + [ + VariableInfo::$scopeTypeDescriptions[$varInfo->scopeType ?: ScopeType::LOCAL], + "\${$varInfo->name}", + ] + ); + } + } + + /** + * @param File $phpcsFile + * @param string $varName + * @param int $stackPtr + * + * @return void + */ + protected function warnAboutUndefinedVariable(File $phpcsFile, $varName, $stackPtr) + { + $phpcsFile->addWarning( + 'Variable %s is undefined.', + $stackPtr, + 'UndefinedVariable', + ["\${$varName}"] + ); + } + + /** + * @param File $phpcsFile + * @param string $varName + * @param int $stackPtr + * + * @return void + */ + protected function warnAboutUndefinedArrayPushShortcut(File $phpcsFile, $varName, $stackPtr) + { + $phpcsFile->addWarning( + 'Array variable %s is undefined.', + $stackPtr, + 'UndefinedVariable', + ["\${$varName}"] + ); + } + + /** + * @param File $phpcsFile + * @param string $varName + * @param int $stackPtr + * + * @return void + */ + protected function warnAboutUndefinedUnset(File $phpcsFile, $varName, $stackPtr) + { + $phpcsFile->addWarning( + 'Variable %s inside unset call is undefined.', + $stackPtr, + 'UndefinedUnsetVariable', + ["\${$varName}"] + ); + } +} diff --git a/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/ruleset.xml b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/ruleset.xml new file mode 100644 index 00000000..be1815a6 --- /dev/null +++ b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/ruleset.xml @@ -0,0 +1,4 @@ + + + Plugin for PHP_CodeSniffer static analysis tool that adds analysis of problematic variable use. + diff --git a/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/ruleset.xml.example b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/ruleset.xml.example new file mode 100644 index 00000000..4104f567 --- /dev/null +++ b/vendor/sirbrillig/phpcs-variable-analysis/VariableAnalysis/ruleset.xml.example @@ -0,0 +1,11 @@ + + + Plugin for PHP_CodeSniffer static analysis tool that adds analysis of problematic variable use. + + + + + diff --git a/vendor/sirbrillig/phpcs-variable-analysis/composer.json b/vendor/sirbrillig/phpcs-variable-analysis/composer.json new file mode 100644 index 00000000..54c7563f --- /dev/null +++ b/vendor/sirbrillig/phpcs-variable-analysis/composer.json @@ -0,0 +1,61 @@ +{ + "name": "sirbrillig/phpcs-variable-analysis", + "description": "A PHPCS sniff to detect problems with variables.", + "type": "phpcodesniffer-standard", + "keywords" : [ "phpcs", "static analysis" ], + "license": "BSD-2-Clause", + "authors": [ + { + "name": "Sam Graham", + "email": "php-codesniffer-variableanalysis@illusori.co.uk" + }, + { + "name": "Payton Swick", + "email": "payton@foolord.com" + } + ], + "support" : { + "issues": "https://github.com/sirbrillig/phpcs-variable-analysis/issues", + "wiki" : "https://github.com/sirbrillig/phpcs-variable-analysis/wiki", + "source": "https://github.com/sirbrillig/phpcs-variable-analysis" + }, + "config": { + "sort-order": true, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + }, + "autoload": { + "psr-4": { + "VariableAnalysis\\": "VariableAnalysis/" + } + }, + "autoload-dev": { + "psr-4": { + "VariableAnalysis\\Tests\\": "Tests/" + } + }, + "minimum-stability": "dev", + "prefer-stable": true, + "scripts": { + "test": "./vendor/bin/phpunit --no-coverage", + "coverage": "./vendor/bin/phpunit", + "lint": "./vendor/bin/phpcs", + "fix": "./vendor/bin/phpcbf", + "phpstan": "./vendor/bin/phpstan analyse", + "psalm": "./vendor/bin/psalm --no-cache", + "static-analysis": "composer phpstan && composer psalm" + }, + "require" : { + "php" : ">=5.4.0", + "squizlabs/php_codesniffer": "^3.5.6" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.5 || ^7.0 || ^8.0 || ^9.0", + "sirbrillig/phpcs-import-detection": "^1.1", + "phpcsstandards/phpcsdevcs": "^1.1", + "phpstan/phpstan": "^1.7", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.0", + "vimeo/psalm": "^0.2 || ^0.3 || ^1.1 || ^4.24 || ^5.0@beta" + } +} diff --git a/vendor/sirbrillig/phpcs-variable-analysis/psalm-autoloader.php b/vendor/sirbrillig/phpcs-variable-analysis/psalm-autoloader.php new file mode 100644 index 00000000..5f2cc85e --- /dev/null +++ b/vendor/sirbrillig/phpcs-variable-analysis/psalm-autoloader.php @@ -0,0 +1,4 @@ + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/CONTRIBUTING.md b/vendor/squizlabs/php_codesniffer/CONTRIBUTING.md new file mode 100644 index 00000000..5cc73635 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/CONTRIBUTING.md @@ -0,0 +1,13 @@ +Contributing +------------- + +Before you contribute code to PHP\_CodeSniffer, please make sure it conforms to the PHPCS coding standard and that the PHP\_CodeSniffer unit tests still pass. The easiest way to contribute is to work on a checkout of the repository, or your own fork, rather than an installed PEAR version. If you do this, you can run the following commands to check if everything is ready to submit: + + cd PHP_CodeSniffer + php bin/phpcs + +Which should display no coding standard errors. And then: + + phpunit + +Which should give you no failures or errors. You can ignore any skipped tests as these are for external tools. diff --git a/vendor/squizlabs/php_codesniffer/CodeSniffer.conf b/vendor/squizlabs/php_codesniffer/CodeSniffer.conf new file mode 100644 index 00000000..7005bb45 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/CodeSniffer.conf @@ -0,0 +1,5 @@ + '../../automattic/vipwpcs,../../phpcompatibility/php-compatibility,../../phpcompatibility/phpcompatibility-paragonie,../../phpcompatibility/phpcompatibility-wp,../../sirbrillig/phpcs-variable-analysis,../../wp-coding-standards/wpcs', +); +?> \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/CodeSniffer.conf.dist b/vendor/squizlabs/php_codesniffer/CodeSniffer.conf.dist new file mode 100644 index 00000000..f95058fa --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/CodeSniffer.conf.dist @@ -0,0 +1,9 @@ + 'PSR2', + 'report_format' => 'summary', + 'show_warnings' => '0', + 'show_progress' => '1', + 'report_width' => '120', +); +?> diff --git a/vendor/squizlabs/php_codesniffer/README.md b/vendor/squizlabs/php_codesniffer/README.md new file mode 100644 index 00000000..859de432 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/README.md @@ -0,0 +1,134 @@ +## About + +PHP_CodeSniffer is a set of two PHP scripts; the main `phpcs` script that tokenizes PHP, JavaScript and CSS files to detect violations of a defined coding standard, and a second `phpcbf` script to automatically correct coding standard violations. PHP_CodeSniffer is an essential development tool that ensures your code remains clean and consistent. + +[![Build Status](https://github.com/squizlabs/PHP_CodeSniffer/workflows/Validate/badge.svg?branch=master)](https://github.com/squizlabs/PHP_CodeSniffer/actions) +[![Build Status](https://github.com/squizlabs/PHP_CodeSniffer/workflows/Test/badge.svg?branch=master)](https://github.com/squizlabs/PHP_CodeSniffer/actions) +[![Code consistency](http://squizlabs.github.io/PHP_CodeSniffer/analysis/squizlabs/PHP_CodeSniffer/grade.svg)](http://squizlabs.github.io/PHP_CodeSniffer/analysis/squizlabs/PHP_CodeSniffer) +[![Join the chat at https://gitter.im/squizlabs/PHP_CodeSniffer](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/squizlabs/PHP_CodeSniffer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +## Requirements + +PHP_CodeSniffer requires PHP version 5.4.0 or greater, although individual sniffs may have additional requirements such as external applications and scripts. See the [Configuration Options manual page](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options) for a list of these requirements. + +If you're using PHP_CodeSniffer as part of a team, or you're running it on a [CI](https://en.wikipedia.org/wiki/Continuous_integration) server, you may want to configure your project's settings [using a configuration file](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#using-a-default-configuration-file). + + +## Installation + +The easiest way to get started with PHP_CodeSniffer is to download the Phar files for each of the commands: +``` +# Download using curl +curl -OL https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar +curl -OL https://squizlabs.github.io/PHP_CodeSniffer/phpcbf.phar + +# Or download using wget +wget https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar +wget https://squizlabs.github.io/PHP_CodeSniffer/phpcbf.phar + +# Then test the downloaded PHARs +php phpcs.phar -h +php phpcbf.phar -h +``` + +### Composer +If you use Composer, you can install PHP_CodeSniffer system-wide with the following command: +```bash +composer global require "squizlabs/php_codesniffer=*" +``` +Make sure you have the composer bin dir in your PATH. The default value is `~/.composer/vendor/bin/`, but you can check the value that you need to use by running `composer global config bin-dir --absolute`. + +Or alternatively, include a dependency for `squizlabs/php_codesniffer` in your `composer.json` file. For example: + +```json +{ + "require-dev": { + "squizlabs/php_codesniffer": "3.*" + } +} +``` + +You will then be able to run PHP_CodeSniffer from the vendor bin directory: +```bash +./vendor/bin/phpcs -h +./vendor/bin/phpcbf -h +``` +### Phive +If you use Phive, you can install PHP_CodeSniffer as a project tool using the following commands: +```bash +phive install phpcs +phive install phpcbf +``` +You will then be able to run PHP_CodeSniffer from the tools directory: +```bash +./tools/phpcs -h +./tools/phpcbf -h +``` +### PEAR +If you use PEAR, you can install PHP_CodeSniffer using the PEAR installer. This will make the `phpcs` and `phpcbf` commands immediately available for use. To install PHP_CodeSniffer using the PEAR installer, first ensure you have [installed PEAR](http://pear.php.net/manual/en/installation.getting.php) and then run the following command: +```bash +pear install PHP_CodeSniffer +``` +### Git Clone +You can also download the PHP_CodeSniffer source and run the `phpcs` and `phpcbf` commands directly from the Git clone: +```bash +git clone https://github.com/squizlabs/PHP_CodeSniffer.git +cd PHP_CodeSniffer +php bin/phpcs -h +php bin/phpcbf -h +``` +## Getting Started + +The default coding standard used by PHP_CodeSniffer is the PEAR coding standard. To check a file against the PEAR coding standard, simply specify the file's location: +```bash +phpcs /path/to/code/myfile.php +``` +Or if you wish to check an entire directory you can specify the directory location instead of a file. +```bash +phpcs /path/to/code-directory +``` +If you wish to check your code against the PSR-12 coding standard, use the `--standard` command line argument: +```bash +phpcs --standard=PSR12 /path/to/code-directory +``` + +If PHP_CodeSniffer finds any coding standard errors, a report will be shown after running the command. + +Full usage information and example reports are available on the [usage page](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage). + +## Documentation + +The documentation for PHP_CodeSniffer is available on the [Github wiki](https://github.com/squizlabs/PHP_CodeSniffer/wiki). + +## Issues + +Bug reports and feature requests can be submitted on the [Github Issue Tracker](https://github.com/squizlabs/PHP_CodeSniffer/issues). + +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for information. + +## Versioning + +PHP_CodeSniffer uses a `MAJOR.MINOR.PATCH` version number format. + +The `MAJOR` version is incremented when: +- backwards-incompatible changes are made to how the `phpcs` or `phpcbf` commands are used, or +- backwards-incompatible changes are made to the `ruleset.xml` format, or +- backwards-incompatible changes are made to the API used by sniff developers, or +- custom PHP_CodeSniffer token types are removed, or +- existing sniffs are removed from PHP_CodeSniffer entirely + +The `MINOR` version is incremented when: +- new backwards-compatible features are added to the `phpcs` and `phpcbf` commands, or +- backwards-compatible changes are made to the `ruleset.xml` format, or +- backwards-compatible changes are made to the API used by sniff developers, or +- new sniffs are added to an included standard, or +- existing sniffs are removed from an included standard + +> NOTE: Backwards-compatible changes to the API used by sniff developers will allow an existing sniff to continue running without producing fatal errors but may not result in the sniff reporting the same errors as it did previously without changes being required. + +The `PATCH` version is incremented when: +- backwards-compatible bug fixes are made + +> NOTE: As PHP_CodeSniffer exists to report and fix issues, most bugs are the result of coding standard errors being incorrectly reported or coding standard errors not being reported when they should be. This means that the messages produced by PHP_CodeSniffer, and the fixes it makes, are likely to be different between PATCH versions. diff --git a/vendor/squizlabs/php_codesniffer/autoload.php b/vendor/squizlabs/php_codesniffer/autoload.php new file mode 100644 index 00000000..0dcf1b4c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/autoload.php @@ -0,0 +1,342 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +if (class_exists('PHP_CodeSniffer\Autoload', false) === false) { + class Autoload + { + + /** + * The composer autoloader. + * + * @var \Composer\Autoload\ClassLoader + */ + private static $composerAutoloader = null; + + /** + * A mapping of file names to class names. + * + * @var array + */ + private static $loadedClasses = []; + + /** + * A mapping of class names to file names. + * + * @var array + */ + private static $loadedFiles = []; + + /** + * A list of additional directories to search during autoloading. + * + * This is typically a list of coding standard directories. + * + * @var string[] + */ + private static $searchPaths = []; + + + /** + * Loads a class. + * + * This method only loads classes that exist in the PHP_CodeSniffer namespace. + * All other classes are ignored and loaded by subsequent autoloaders. + * + * @param string $class The name of the class to load. + * + * @return bool + */ + public static function load($class) + { + // Include the composer autoloader if there is one, but re-register it + // so this autoloader runs before the composer one as we need to include + // all files so we can figure out what the class/interface/trait name is. + if (self::$composerAutoloader === null) { + // Make sure we don't try to load any of Composer's classes + // while the autoloader is being setup. + if (strpos($class, 'Composer\\') === 0) { + return; + } + + if (strpos(__DIR__, 'phar://') !== 0 + && @file_exists(__DIR__.'/../../autoload.php') === true + ) { + self::$composerAutoloader = include __DIR__.'/../../autoload.php'; + if (self::$composerAutoloader instanceof \Composer\Autoload\ClassLoader) { + self::$composerAutoloader->unregister(); + self::$composerAutoloader->register(); + } else { + // Something went wrong, so keep going without the autoloader + // although namespaced sniffs might error. + self::$composerAutoloader = false; + } + } else { + self::$composerAutoloader = false; + } + }//end if + + $ds = DIRECTORY_SEPARATOR; + $path = false; + + if (substr($class, 0, 16) === 'PHP_CodeSniffer\\') { + if (substr($class, 0, 22) === 'PHP_CodeSniffer\Tests\\') { + $isInstalled = !is_dir(__DIR__.$ds.'tests'); + if ($isInstalled === false) { + $path = __DIR__.$ds.'tests'; + } else { + $path = '@test_dir@'.$ds.'PHP_CodeSniffer'.$ds.'CodeSniffer'; + } + + $path .= $ds.substr(str_replace('\\', $ds, $class), 22).'.php'; + } else { + $path = __DIR__.$ds.'src'.$ds.substr(str_replace('\\', $ds, $class), 16).'.php'; + } + } + + // See if the composer autoloader knows where the class is. + if ($path === false && self::$composerAutoloader !== false) { + $path = self::$composerAutoloader->findFile($class); + } + + // See if the class is inside one of our alternate search paths. + if ($path === false) { + foreach (self::$searchPaths as $searchPath => $nsPrefix) { + $className = $class; + if ($nsPrefix !== '' && substr($class, 0, strlen($nsPrefix)) === $nsPrefix) { + $className = substr($class, (strlen($nsPrefix) + 1)); + } + + $path = $searchPath.$ds.str_replace('\\', $ds, $className).'.php'; + if (is_file($path) === true) { + break; + } + + $path = false; + } + } + + if ($path !== false && is_file($path) === true) { + self::loadFile($path); + return true; + } + + return false; + + }//end load() + + + /** + * Includes a file and tracks what class or interface was loaded as a result. + * + * @param string $path The path of the file to load. + * + * @return string The fully qualified name of the class in the loaded file. + */ + public static function loadFile($path) + { + if (strpos(__DIR__, 'phar://') !== 0) { + $path = realpath($path); + if ($path === false) { + return false; + } + } + + if (isset(self::$loadedClasses[$path]) === true) { + return self::$loadedClasses[$path]; + } + + $classesBeforeLoad = [ + 'classes' => get_declared_classes(), + 'interfaces' => get_declared_interfaces(), + 'traits' => get_declared_traits(), + ]; + + include $path; + + $classesAfterLoad = [ + 'classes' => get_declared_classes(), + 'interfaces' => get_declared_interfaces(), + 'traits' => get_declared_traits(), + ]; + + $className = self::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + + self::$loadedClasses[$path] = $className; + self::$loadedFiles[$className] = $path; + return self::$loadedClasses[$path]; + + }//end loadFile() + + + /** + * Determine which class was loaded based on the before and after lists of loaded classes. + * + * @param array $classesBeforeLoad The classes/interfaces/traits before the file was included. + * @param array $classesAfterLoad The classes/interfaces/traits after the file was included. + * + * @return string The fully qualified name of the class in the loaded file. + */ + public static function determineLoadedClass($classesBeforeLoad, $classesAfterLoad) + { + $className = null; + + $newClasses = array_diff($classesAfterLoad['classes'], $classesBeforeLoad['classes']); + if (PHP_VERSION_ID < 70400) { + $newClasses = array_reverse($newClasses); + } + + // Since PHP 7.4 get_declared_classes() does not guarantee any order, making + // it impossible to use order to determine which is the parent an which is the child. + // Let's reduce the list of candidates by removing all the classes known to be "parents". + // That way, at the end, only the "main" class just included will remain. + $newClasses = array_reduce( + $newClasses, + function ($remaining, $current) { + return array_diff($remaining, class_parents($current)); + }, + $newClasses + ); + + foreach ($newClasses as $name) { + if (isset(self::$loadedFiles[$name]) === false) { + $className = $name; + break; + } + } + + if ($className === null) { + $newClasses = array_reverse(array_diff($classesAfterLoad['interfaces'], $classesBeforeLoad['interfaces'])); + foreach ($newClasses as $name) { + if (isset(self::$loadedFiles[$name]) === false) { + $className = $name; + break; + } + } + } + + if ($className === null) { + $newClasses = array_reverse(array_diff($classesAfterLoad['traits'], $classesBeforeLoad['traits'])); + foreach ($newClasses as $name) { + if (isset(self::$loadedFiles[$name]) === false) { + $className = $name; + break; + } + } + } + + return $className; + + }//end determineLoadedClass() + + + /** + * Adds a directory to search during autoloading. + * + * @param string $path The path to the directory to search. + * @param string $nsPrefix The namespace prefix used by files under this path. + * + * @return void + */ + public static function addSearchPath($path, $nsPrefix='') + { + self::$searchPaths[$path] = rtrim(trim((string) $nsPrefix), '\\'); + + }//end addSearchPath() + + + /** + * Retrieve the namespaces and paths registered by external standards. + * + * @return array + */ + public static function getSearchPaths() + { + return self::$searchPaths; + + }//end getSearchPaths() + + + /** + * Gets the class name for the given file path. + * + * @param string $path The name of the file. + * + * @throws \Exception If the file path has not been loaded. + * @return string + */ + public static function getLoadedClassName($path) + { + if (isset(self::$loadedClasses[$path]) === false) { + throw new \Exception("Cannot get class name for $path; file has not been included"); + } + + return self::$loadedClasses[$path]; + + }//end getLoadedClassName() + + + /** + * Gets the file path for the given class name. + * + * @param string $class The name of the class. + * + * @throws \Exception If the class name has not been loaded + * @return string + */ + public static function getLoadedFileName($class) + { + if (isset(self::$loadedFiles[$class]) === false) { + throw new \Exception("Cannot get file name for $class; class has not been included"); + } + + return self::$loadedFiles[$class]; + + }//end getLoadedFileName() + + + /** + * Gets the mapping of file names to class names. + * + * @return array + */ + public static function getLoadedClasses() + { + return self::$loadedClasses; + + }//end getLoadedClasses() + + + /** + * Gets the mapping of class names to file names. + * + * @return array + */ + public static function getLoadedFiles() + { + return self::$loadedFiles; + + }//end getLoadedFiles() + + + }//end class + + // Register the autoloader before any existing autoloaders to ensure + // it gets a chance to hear about every autoload request, and record + // the file and class name for it. + spl_autoload_register(__NAMESPACE__.'\Autoload::load', true, true); +}//end if diff --git a/vendor/squizlabs/php_codesniffer/bin/phpcbf b/vendor/squizlabs/php_codesniffer/bin/phpcbf new file mode 100755 index 00000000..45b43f43 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/bin/phpcbf @@ -0,0 +1,19 @@ +#!/usr/bin/env php + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +if (is_file(__DIR__.'/../autoload.php') === true) { + include_once __DIR__.'/../autoload.php'; +} else { + include_once 'PHP/CodeSniffer/autoload.php'; +} + +$runner = new PHP_CodeSniffer\Runner(); +$exitCode = $runner->runPHPCBF(); +exit($exitCode); diff --git a/vendor/squizlabs/php_codesniffer/bin/phpcbf.bat b/vendor/squizlabs/php_codesniffer/bin/phpcbf.bat new file mode 100644 index 00000000..5b07a7d9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/bin/phpcbf.bat @@ -0,0 +1,12 @@ +@echo off +REM PHP Code Beautifier and Fixer fixes violations of a defined coding standard. +REM +REM @author Greg Sherwood +REM @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) +REM @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + +if "%PHP_PEAR_PHP_BIN%" neq "" ( + set PHPBIN=%PHP_PEAR_PHP_BIN% +) else set PHPBIN=php + +"%PHPBIN%" "%~dp0\phpcbf" %* diff --git a/vendor/squizlabs/php_codesniffer/bin/phpcs b/vendor/squizlabs/php_codesniffer/bin/phpcs new file mode 100755 index 00000000..52d28cdf --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/bin/phpcs @@ -0,0 +1,19 @@ +#!/usr/bin/env php + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +if (is_file(__DIR__.'/../autoload.php') === true) { + include_once __DIR__.'/../autoload.php'; +} else { + include_once 'PHP/CodeSniffer/autoload.php'; +} + +$runner = new PHP_CodeSniffer\Runner(); +$exitCode = $runner->runPHPCS(); +exit($exitCode); diff --git a/vendor/squizlabs/php_codesniffer/bin/phpcs.bat b/vendor/squizlabs/php_codesniffer/bin/phpcs.bat new file mode 100755 index 00000000..9f9be720 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/bin/phpcs.bat @@ -0,0 +1,12 @@ +@echo off +REM PHP_CodeSniffer detects violations of a defined coding standard. +REM +REM @author Greg Sherwood +REM @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) +REM @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + +if "%PHP_PEAR_PHP_BIN%" neq "" ( + set PHPBIN=%PHP_PEAR_PHP_BIN% +) else set PHPBIN=php + +"%PHPBIN%" "%~dp0\phpcs" %* diff --git a/vendor/squizlabs/php_codesniffer/composer.json b/vendor/squizlabs/php_codesniffer/composer.json new file mode 100644 index 00000000..7605a5df --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/composer.json @@ -0,0 +1,40 @@ +{ + "name": "squizlabs/php_codesniffer", + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "type": "library", + "keywords": [ + "phpcs", + "standards" + ], + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki", + "source": "https://github.com/squizlabs/PHP_CodeSniffer" + }, + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "require": { + "php": ">=5.4.0", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "ext-simplexml": "*" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ] +} diff --git a/vendor/squizlabs/php_codesniffer/licence.txt b/vendor/squizlabs/php_codesniffer/licence.txt new file mode 100644 index 00000000..9f95b677 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/licence.txt @@ -0,0 +1,24 @@ +Copyright (c) 2012, Squiz Pty Ltd (ABN 77 084 670 600) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/squizlabs/php_codesniffer/phpcs.xsd b/vendor/squizlabs/php_codesniffer/phpcs.xsd new file mode 100644 index 00000000..d93dd868 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/phpcs.xsd @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Config.php b/vendor/squizlabs/php_codesniffer/src/Config.php new file mode 100644 index 00000000..915ad003 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Config.php @@ -0,0 +1,1704 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use PHP_CodeSniffer\Exceptions\DeepExitException; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Util\Common; + +/** + * Stores the configuration used to run PHPCS and PHPCBF. + * + * @property string[] $files The files and directories to check. + * @property string[] $standards The standards being used for checking. + * @property int $verbosity How verbose the output should be. + * 0: no unnecessary output + * 1: basic output for files being checked + * 2: ruleset and file parsing output + * 3: sniff execution output + * @property bool $interactive Enable interactive checking mode. + * @property bool $parallel Check files in parallel. + * @property bool $cache Enable the use of the file cache. + * @property bool $cacheFile A file where the cache data should be written + * @property bool $colors Display colours in output. + * @property bool $explain Explain the coding standards. + * @property bool $local Process local files in directories only (no recursion). + * @property bool $showSources Show sniff source codes in report output. + * @property bool $showProgress Show basic progress information while running. + * @property bool $quiet Quiet mode; disables progress and verbose output. + * @property bool $annotations Process phpcs: annotations. + * @property int $tabWidth How many spaces each tab is worth. + * @property string $encoding The encoding of the files being checked. + * @property string[] $sniffs The sniffs that should be used for checking. + * If empty, all sniffs in the supplied standards will be used. + * @property string[] $exclude The sniffs that should be excluded from checking. + * If empty, all sniffs in the supplied standards will be used. + * @property string[] $ignored Regular expressions used to ignore files and folders during checking. + * @property string $reportFile A file where the report output should be written. + * @property string $generator The documentation generator to use. + * @property string $filter The filter to use for the run. + * @property string[] $bootstrap One of more files to include before the run begins. + * @property int $reportWidth The maximum number of columns that reports should use for output. + * Set to "auto" for have this value changed to the width of the terminal. + * @property int $errorSeverity The minimum severity an error must have to be displayed. + * @property int $warningSeverity The minimum severity a warning must have to be displayed. + * @property bool $recordErrors Record the content of error messages as well as error counts. + * @property string $suffix A suffix to add to fixed files. + * @property string $basepath A file system location to strip from the paths of files shown in reports. + * @property bool $stdin Read content from STDIN instead of supplied files. + * @property string $stdinContent Content passed directly to PHPCS on STDIN. + * @property string $stdinPath The path to use for content passed on STDIN. + * + * @property array $extensions File extensions that should be checked, and what tokenizer to use. + * E.g., array('inc' => 'PHP'); + * @property array $reports The reports to use for printing output after the run. + * The format of the array is: + * array( + * 'reportName1' => 'outputFile', + * 'reportName2' => null, + * ); + * If the array value is NULL, the report will be written to the screen. + * + * @property string[] $unknown Any arguments gathered on the command line that are unknown to us. + * E.g., using `phpcs -c` will give array('c'); + */ +class Config +{ + + /** + * The current version. + * + * @var string + */ + const VERSION = '3.7.1'; + + /** + * Package stability; either stable, beta or alpha. + * + * @var string + */ + const STABILITY = 'stable'; + + /** + * An array of settings that PHPCS and PHPCBF accept. + * + * This array is not meant to be accessed directly. Instead, use the settings + * as if they are class member vars so the __get() and __set() magic methods + * can be used to validate the values. For example, to set the verbosity level to + * level 2, use $this->verbosity = 2; instead of accessing this property directly. + * + * Each of these settings is described in the class comment property list. + * + * @var array + */ + private $settings = [ + 'files' => null, + 'standards' => null, + 'verbosity' => null, + 'interactive' => null, + 'parallel' => null, + 'cache' => null, + 'cacheFile' => null, + 'colors' => null, + 'explain' => null, + 'local' => null, + 'showSources' => null, + 'showProgress' => null, + 'quiet' => null, + 'annotations' => null, + 'tabWidth' => null, + 'encoding' => null, + 'extensions' => null, + 'sniffs' => null, + 'exclude' => null, + 'ignored' => null, + 'reportFile' => null, + 'generator' => null, + 'filter' => null, + 'bootstrap' => null, + 'reports' => null, + 'basepath' => null, + 'reportWidth' => null, + 'errorSeverity' => null, + 'warningSeverity' => null, + 'recordErrors' => null, + 'suffix' => null, + 'stdin' => null, + 'stdinContent' => null, + 'stdinPath' => null, + 'unknown' => null, + ]; + + /** + * Whether or not to kill the process when an unknown command line arg is found. + * + * If FALSE, arguments that are not command line options or file/directory paths + * will be ignored and execution will continue. These values will be stored in + * $this->unknown. + * + * @var boolean + */ + public $dieOnUnknownArg; + + /** + * The current command line arguments we are processing. + * + * @var string[] + */ + private $cliArgs = []; + + /** + * Command line values that the user has supplied directly. + * + * @var array + */ + private static $overriddenDefaults = []; + + /** + * Config file data that has been loaded for the run. + * + * @var array + */ + private static $configData = null; + + /** + * The full path to the config data file that has been loaded. + * + * @var string + */ + private static $configDataFile = null; + + /** + * Automatically discovered executable utility paths. + * + * @var array + */ + private static $executablePaths = []; + + + /** + * Get the value of an inaccessible property. + * + * @param string $name The name of the property. + * + * @return mixed + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the setting name is invalid. + */ + public function __get($name) + { + if (array_key_exists($name, $this->settings) === false) { + throw new RuntimeException("ERROR: unable to get value of property \"$name\""); + } + + return $this->settings[$name]; + + }//end __get() + + + /** + * Set the value of an inaccessible property. + * + * @param string $name The name of the property. + * @param mixed $value The value of the property. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the setting name is invalid. + */ + public function __set($name, $value) + { + if (array_key_exists($name, $this->settings) === false) { + throw new RuntimeException("Can't __set() $name; setting doesn't exist"); + } + + switch ($name) { + case 'reportWidth' : + // Support auto terminal width. + if ($value === 'auto' + && function_exists('shell_exec') === true + && preg_match('|\d+ (\d+)|', shell_exec('stty size 2>&1'), $matches) === 1 + ) { + $value = (int) $matches[1]; + } else { + $value = (int) $value; + } + break; + case 'standards' : + $cleaned = []; + + // Check if the standard name is valid, or if the case is invalid. + $installedStandards = Util\Standards::getInstalledStandards(); + foreach ($value as $standard) { + foreach ($installedStandards as $validStandard) { + if (strtolower($standard) === strtolower($validStandard)) { + $standard = $validStandard; + break; + } + } + + $cleaned[] = $standard; + } + + $value = $cleaned; + break; + default : + // No validation required. + break; + }//end switch + + $this->settings[$name] = $value; + + }//end __set() + + + /** + * Check if the value of an inaccessible property is set. + * + * @param string $name The name of the property. + * + * @return bool + */ + public function __isset($name) + { + return isset($this->settings[$name]); + + }//end __isset() + + + /** + * Unset the value of an inaccessible property. + * + * @param string $name The name of the property. + * + * @return void + */ + public function __unset($name) + { + $this->settings[$name] = null; + + }//end __unset() + + + /** + * Get the array of all config settings. + * + * @return array + */ + public function getSettings() + { + return $this->settings; + + }//end getSettings() + + + /** + * Set the array of all config settings. + * + * @param array $settings The array of config settings. + * + * @return void + */ + public function setSettings($settings) + { + return $this->settings = $settings; + + }//end setSettings() + + + /** + * Creates a Config object and populates it with command line values. + * + * @param array $cliArgs An array of values gathered from CLI args. + * @param bool $dieOnUnknownArg Whether or not to kill the process when an + * unknown command line arg is found. + * + * @return void + */ + public function __construct(array $cliArgs=[], $dieOnUnknownArg=true) + { + if (defined('PHP_CODESNIFFER_IN_TESTS') === true) { + // Let everything through during testing so that we can + // make use of PHPUnit command line arguments as well. + $this->dieOnUnknownArg = false; + } else { + $this->dieOnUnknownArg = $dieOnUnknownArg; + } + + if (empty($cliArgs) === true) { + $cliArgs = $_SERVER['argv']; + array_shift($cliArgs); + } + + $this->restoreDefaults(); + $this->setCommandLineValues($cliArgs); + + if (isset(self::$overriddenDefaults['standards']) === false) { + // They did not supply a standard to use. + // Look for a default ruleset in the current directory or higher. + $currentDir = getcwd(); + + $defaultFiles = [ + '.phpcs.xml', + 'phpcs.xml', + '.phpcs.xml.dist', + 'phpcs.xml.dist', + ]; + + do { + foreach ($defaultFiles as $defaultFilename) { + $default = $currentDir.DIRECTORY_SEPARATOR.$defaultFilename; + if (is_file($default) === true) { + $this->standards = [$default]; + break(2); + } + } + + $lastDir = $currentDir; + $currentDir = dirname($currentDir); + } while ($currentDir !== '.' && $currentDir !== $lastDir && Common::isReadable($currentDir) === true); + }//end if + + if (defined('STDIN') === false + || stripos(PHP_OS, 'WIN') === 0 + ) { + return; + } + + $handle = fopen('php://stdin', 'r'); + + // Check for content on STDIN. + if ($this->stdin === true + || (Util\Common::isStdinATTY() === false + && feof($handle) === false) + ) { + $readStreams = [$handle]; + $writeSteams = null; + + $fileContents = ''; + while (is_resource($handle) === true && feof($handle) === false) { + // Set a timeout of 200ms. + if (stream_select($readStreams, $writeSteams, $writeSteams, 0, 200000) === 0) { + break; + } + + $fileContents .= fgets($handle); + } + + if (trim($fileContents) !== '') { + $this->stdin = true; + $this->stdinContent = $fileContents; + self::$overriddenDefaults['stdin'] = true; + self::$overriddenDefaults['stdinContent'] = true; + } + }//end if + + fclose($handle); + + }//end __construct() + + + /** + * Set the command line values. + * + * @param array $args An array of command line arguments to set. + * + * @return void + */ + public function setCommandLineValues($args) + { + $this->cliArgs = $args; + $numArgs = count($args); + + for ($i = 0; $i < $numArgs; $i++) { + $arg = $this->cliArgs[$i]; + if ($arg === '') { + continue; + } + + if ($arg[0] === '-') { + if ($arg === '-') { + // Asking to read from STDIN. + $this->stdin = true; + self::$overriddenDefaults['stdin'] = true; + continue; + } + + if ($arg === '--') { + // Empty argument, ignore it. + continue; + } + + if ($arg[1] === '-') { + $this->processLongArgument(substr($arg, 2), $i); + } else { + $switches = str_split($arg); + foreach ($switches as $switch) { + if ($switch === '-') { + continue; + } + + $this->processShortArgument($switch, $i); + } + } + } else { + $this->processUnknownArgument($arg, $i); + }//end if + }//end for + + }//end setCommandLineValues() + + + /** + * Restore default values for all possible command line arguments. + * + * @return void + */ + public function restoreDefaults() + { + $this->files = []; + $this->standards = ['PEAR']; + $this->verbosity = 0; + $this->interactive = false; + $this->cache = false; + $this->cacheFile = null; + $this->colors = false; + $this->explain = false; + $this->local = false; + $this->showSources = false; + $this->showProgress = false; + $this->quiet = false; + $this->annotations = true; + $this->parallel = 1; + $this->tabWidth = 0; + $this->encoding = 'utf-8'; + $this->extensions = [ + 'php' => 'PHP', + 'inc' => 'PHP', + 'js' => 'JS', + 'css' => 'CSS', + ]; + $this->sniffs = []; + $this->exclude = []; + $this->ignored = []; + $this->reportFile = null; + $this->generator = null; + $this->filter = null; + $this->bootstrap = []; + $this->basepath = null; + $this->reports = ['full' => null]; + $this->reportWidth = 'auto'; + $this->errorSeverity = 5; + $this->warningSeverity = 5; + $this->recordErrors = true; + $this->suffix = ''; + $this->stdin = false; + $this->stdinContent = null; + $this->stdinPath = null; + $this->unknown = []; + + $standard = self::getConfigData('default_standard'); + if ($standard !== null) { + $this->standards = explode(',', $standard); + } + + $reportFormat = self::getConfigData('report_format'); + if ($reportFormat !== null) { + $this->reports = [$reportFormat => null]; + } + + $tabWidth = self::getConfigData('tab_width'); + if ($tabWidth !== null) { + $this->tabWidth = (int) $tabWidth; + } + + $encoding = self::getConfigData('encoding'); + if ($encoding !== null) { + $this->encoding = strtolower($encoding); + } + + $severity = self::getConfigData('severity'); + if ($severity !== null) { + $this->errorSeverity = (int) $severity; + $this->warningSeverity = (int) $severity; + } + + $severity = self::getConfigData('error_severity'); + if ($severity !== null) { + $this->errorSeverity = (int) $severity; + } + + $severity = self::getConfigData('warning_severity'); + if ($severity !== null) { + $this->warningSeverity = (int) $severity; + } + + $showWarnings = self::getConfigData('show_warnings'); + if ($showWarnings !== null) { + $showWarnings = (bool) $showWarnings; + if ($showWarnings === false) { + $this->warningSeverity = 0; + } + } + + $reportWidth = self::getConfigData('report_width'); + if ($reportWidth !== null) { + $this->reportWidth = $reportWidth; + } + + $showProgress = self::getConfigData('show_progress'); + if ($showProgress !== null) { + $this->showProgress = (bool) $showProgress; + } + + $quiet = self::getConfigData('quiet'); + if ($quiet !== null) { + $this->quiet = (bool) $quiet; + } + + $colors = self::getConfigData('colors'); + if ($colors !== null) { + $this->colors = (bool) $colors; + } + + if (defined('PHP_CODESNIFFER_IN_TESTS') === false) { + $cache = self::getConfigData('cache'); + if ($cache !== null) { + $this->cache = (bool) $cache; + } + + $parallel = self::getConfigData('parallel'); + if ($parallel !== null) { + $this->parallel = max((int) $parallel, 1); + } + } + + }//end restoreDefaults() + + + /** + * Processes a short (-e) command line argument. + * + * @param string $arg The command line argument. + * @param int $pos The position of the argument on the command line. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processShortArgument($arg, $pos) + { + switch ($arg) { + case 'h': + case '?': + ob_start(); + $this->printUsage(); + $output = ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($output, 0); + case 'i' : + ob_start(); + Util\Standards::printInstalledStandards(); + $output = ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($output, 0); + case 'v' : + if ($this->quiet === true) { + // Ignore when quiet mode is enabled. + break; + } + + $this->verbosity++; + self::$overriddenDefaults['verbosity'] = true; + break; + case 'l' : + $this->local = true; + self::$overriddenDefaults['local'] = true; + break; + case 's' : + $this->showSources = true; + self::$overriddenDefaults['showSources'] = true; + break; + case 'a' : + $this->interactive = true; + self::$overriddenDefaults['interactive'] = true; + break; + case 'e': + $this->explain = true; + self::$overriddenDefaults['explain'] = true; + break; + case 'p' : + if ($this->quiet === true) { + // Ignore when quiet mode is enabled. + break; + } + + $this->showProgress = true; + self::$overriddenDefaults['showProgress'] = true; + break; + case 'q' : + // Quiet mode disables a few other settings as well. + $this->quiet = true; + $this->showProgress = false; + $this->verbosity = 0; + + self::$overriddenDefaults['quiet'] = true; + break; + case 'm' : + $this->recordErrors = false; + self::$overriddenDefaults['recordErrors'] = true; + break; + case 'd' : + $ini = explode('=', $this->cliArgs[($pos + 1)]); + $this->cliArgs[($pos + 1)] = ''; + if (isset($ini[1]) === true) { + ini_set($ini[0], $ini[1]); + } else { + ini_set($ini[0], true); + } + break; + case 'n' : + if (isset(self::$overriddenDefaults['warningSeverity']) === false) { + $this->warningSeverity = 0; + self::$overriddenDefaults['warningSeverity'] = true; + } + break; + case 'w' : + if (isset(self::$overriddenDefaults['warningSeverity']) === false) { + $this->warningSeverity = $this->errorSeverity; + self::$overriddenDefaults['warningSeverity'] = true; + } + break; + default: + if ($this->dieOnUnknownArg === false) { + $unknown = $this->unknown; + $unknown[] = $arg; + $this->unknown = $unknown; + } else { + $this->processUnknownArgument('-'.$arg, $pos); + } + }//end switch + + }//end processShortArgument() + + + /** + * Processes a long (--example) command line argument. + * + * @param string $arg The command line argument. + * @param int $pos The position of the argument on the command line. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processLongArgument($arg, $pos) + { + switch ($arg) { + case 'help': + ob_start(); + $this->printUsage(); + $output = ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($output, 0); + case 'version': + $output = 'PHP_CodeSniffer version '.self::VERSION.' ('.self::STABILITY.') '; + $output .= 'by Squiz (http://www.squiz.net)'.PHP_EOL; + throw new DeepExitException($output, 0); + case 'colors': + if (isset(self::$overriddenDefaults['colors']) === true) { + break; + } + + $this->colors = true; + self::$overriddenDefaults['colors'] = true; + break; + case 'no-colors': + if (isset(self::$overriddenDefaults['colors']) === true) { + break; + } + + $this->colors = false; + self::$overriddenDefaults['colors'] = true; + break; + case 'cache': + if (isset(self::$overriddenDefaults['cache']) === true) { + break; + } + + if (defined('PHP_CODESNIFFER_IN_TESTS') === false) { + $this->cache = true; + self::$overriddenDefaults['cache'] = true; + } + break; + case 'no-cache': + if (isset(self::$overriddenDefaults['cache']) === true) { + break; + } + + $this->cache = false; + self::$overriddenDefaults['cache'] = true; + break; + case 'ignore-annotations': + if (isset(self::$overriddenDefaults['annotations']) === true) { + break; + } + + $this->annotations = false; + self::$overriddenDefaults['annotations'] = true; + break; + case 'config-set': + if (isset($this->cliArgs[($pos + 1)]) === false + || isset($this->cliArgs[($pos + 2)]) === false + ) { + $error = 'ERROR: Setting a config option requires a name and value'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $key = $this->cliArgs[($pos + 1)]; + $value = $this->cliArgs[($pos + 2)]; + $current = self::getConfigData($key); + + try { + $this->setConfigData($key, $value); + } catch (\Exception $e) { + throw new DeepExitException($e->getMessage().PHP_EOL, 3); + } + + $output = 'Using config file: '.self::$configDataFile.PHP_EOL.PHP_EOL; + + if ($current === null) { + $output .= "Config value \"$key\" added successfully".PHP_EOL; + } else { + $output .= "Config value \"$key\" updated successfully; old value was \"$current\"".PHP_EOL; + } + throw new DeepExitException($output, 0); + case 'config-delete': + if (isset($this->cliArgs[($pos + 1)]) === false) { + $error = 'ERROR: Deleting a config option requires the name of the option'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $output = 'Using config file: '.self::$configDataFile.PHP_EOL.PHP_EOL; + + $key = $this->cliArgs[($pos + 1)]; + $current = self::getConfigData($key); + if ($current === null) { + $output .= "Config value \"$key\" has not been set".PHP_EOL; + } else { + try { + $this->setConfigData($key, null); + } catch (\Exception $e) { + throw new DeepExitException($e->getMessage().PHP_EOL, 3); + } + + $output .= "Config value \"$key\" removed successfully; old value was \"$current\"".PHP_EOL; + } + throw new DeepExitException($output, 0); + case 'config-show': + ob_start(); + $data = self::getAllConfigData(); + echo 'Using config file: '.self::$configDataFile.PHP_EOL.PHP_EOL; + $this->printConfigData($data); + $output = ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($output, 0); + case 'runtime-set': + if (isset($this->cliArgs[($pos + 1)]) === false + || isset($this->cliArgs[($pos + 2)]) === false + ) { + $error = 'ERROR: Setting a runtime config option requires a name and value'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $key = $this->cliArgs[($pos + 1)]; + $value = $this->cliArgs[($pos + 2)]; + $this->cliArgs[($pos + 1)] = ''; + $this->cliArgs[($pos + 2)] = ''; + self::setConfigData($key, $value, true); + if (isset(self::$overriddenDefaults['runtime-set']) === false) { + self::$overriddenDefaults['runtime-set'] = []; + } + + self::$overriddenDefaults['runtime-set'][$key] = true; + break; + default: + if (substr($arg, 0, 7) === 'sniffs=') { + if (isset(self::$overriddenDefaults['sniffs']) === true) { + break; + } + + $sniffs = explode(',', substr($arg, 7)); + foreach ($sniffs as $sniff) { + if (substr_count($sniff, '.') !== 2) { + $error = 'ERROR: The specified sniff code "'.$sniff.'" is invalid'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } + + $this->sniffs = $sniffs; + self::$overriddenDefaults['sniffs'] = true; + } else if (substr($arg, 0, 8) === 'exclude=') { + if (isset(self::$overriddenDefaults['exclude']) === true) { + break; + } + + $sniffs = explode(',', substr($arg, 8)); + foreach ($sniffs as $sniff) { + if (substr_count($sniff, '.') !== 2) { + $error = 'ERROR: The specified sniff code "'.$sniff.'" is invalid'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } + + $this->exclude = $sniffs; + self::$overriddenDefaults['exclude'] = true; + } else if (defined('PHP_CODESNIFFER_IN_TESTS') === false + && substr($arg, 0, 6) === 'cache=' + ) { + if ((isset(self::$overriddenDefaults['cache']) === true + && $this->cache === false) + || isset(self::$overriddenDefaults['cacheFile']) === true + ) { + break; + } + + // Turn caching on. + $this->cache = true; + self::$overriddenDefaults['cache'] = true; + + $this->cacheFile = Util\Common::realpath(substr($arg, 6)); + + // It may not exist and return false instead. + if ($this->cacheFile === false) { + $this->cacheFile = substr($arg, 6); + + $dir = dirname($this->cacheFile); + if (is_dir($dir) === false) { + $error = 'ERROR: The specified cache file path "'.$this->cacheFile.'" points to a non-existent directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + if ($dir === '.') { + // Passed cache file is a file in the current directory. + $this->cacheFile = getcwd().'/'.basename($this->cacheFile); + } else { + if ($dir[0] === '/') { + // An absolute path. + $dir = Util\Common::realpath($dir); + } else { + $dir = Util\Common::realpath(getcwd().'/'.$dir); + } + + if ($dir !== false) { + // Cache file path is relative. + $this->cacheFile = $dir.'/'.basename($this->cacheFile); + } + } + }//end if + + self::$overriddenDefaults['cacheFile'] = true; + + if (is_dir($this->cacheFile) === true) { + $error = 'ERROR: The specified cache file path "'.$this->cacheFile.'" is a directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } else if (substr($arg, 0, 10) === 'bootstrap=') { + $files = explode(',', substr($arg, 10)); + $bootstrap = []; + foreach ($files as $file) { + $path = Util\Common::realpath($file); + if ($path === false) { + $error = 'ERROR: The specified bootstrap file "'.$file.'" does not exist'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $bootstrap[] = $path; + } + + $this->bootstrap = array_merge($this->bootstrap, $bootstrap); + self::$overriddenDefaults['bootstrap'] = true; + } else if (substr($arg, 0, 10) === 'file-list=') { + $fileList = substr($arg, 10); + $path = Util\Common::realpath($fileList); + if ($path === false) { + $error = 'ERROR: The specified file list "'.$fileList.'" does not exist'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $files = file($path); + foreach ($files as $inputFile) { + $inputFile = trim($inputFile); + + // Skip empty lines. + if ($inputFile === '') { + continue; + } + + $this->processFilePath($inputFile); + } + } else if (substr($arg, 0, 11) === 'stdin-path=') { + if (isset(self::$overriddenDefaults['stdinPath']) === true) { + break; + } + + $this->stdinPath = Util\Common::realpath(substr($arg, 11)); + + // It may not exist and return false instead, so use whatever they gave us. + if ($this->stdinPath === false) { + $this->stdinPath = trim(substr($arg, 11)); + } + + self::$overriddenDefaults['stdinPath'] = true; + } else if (PHP_CODESNIFFER_CBF === false && substr($arg, 0, 12) === 'report-file=') { + if (isset(self::$overriddenDefaults['reportFile']) === true) { + break; + } + + $this->reportFile = Util\Common::realpath(substr($arg, 12)); + + // It may not exist and return false instead. + if ($this->reportFile === false) { + $this->reportFile = substr($arg, 12); + + $dir = Util\Common::realpath(dirname($this->reportFile)); + if (is_dir($dir) === false) { + $error = 'ERROR: The specified report file path "'.$this->reportFile.'" points to a non-existent directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $this->reportFile = $dir.'/'.basename($this->reportFile); + }//end if + + self::$overriddenDefaults['reportFile'] = true; + + if (is_dir($this->reportFile) === true) { + $error = 'ERROR: The specified report file path "'.$this->reportFile.'" is a directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } else if (substr($arg, 0, 13) === 'report-width=') { + if (isset(self::$overriddenDefaults['reportWidth']) === true) { + break; + } + + $this->reportWidth = substr($arg, 13); + self::$overriddenDefaults['reportWidth'] = true; + } else if (substr($arg, 0, 9) === 'basepath=') { + if (isset(self::$overriddenDefaults['basepath']) === true) { + break; + } + + self::$overriddenDefaults['basepath'] = true; + + if (substr($arg, 9) === '') { + $this->basepath = null; + break; + } + + $this->basepath = Util\Common::realpath(substr($arg, 9)); + + // It may not exist and return false instead. + if ($this->basepath === false) { + $this->basepath = substr($arg, 9); + } + + if (is_dir($this->basepath) === false) { + $error = 'ERROR: The specified basepath "'.$this->basepath.'" points to a non-existent directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } else if ((substr($arg, 0, 7) === 'report=' || substr($arg, 0, 7) === 'report-')) { + $reports = []; + + if ($arg[6] === '-') { + // This is a report with file output. + $split = strpos($arg, '='); + if ($split === false) { + $report = substr($arg, 7); + $output = null; + } else { + $report = substr($arg, 7, ($split - 7)); + $output = substr($arg, ($split + 1)); + if ($output === false) { + $output = null; + } else { + $dir = Util\Common::realpath(dirname($output)); + if (is_dir($dir) === false) { + $error = 'ERROR: The specified '.$report.' report file path "'.$output.'" points to a non-existent directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $output = $dir.'/'.basename($output); + + if (is_dir($output) === true) { + $error = 'ERROR: The specified '.$report.' report file path "'.$output.'" is a directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + }//end if + }//end if + + $reports[$report] = $output; + } else { + // This is a single report. + if (isset(self::$overriddenDefaults['reports']) === true) { + break; + } + + $reportNames = explode(',', substr($arg, 7)); + foreach ($reportNames as $report) { + $reports[$report] = null; + } + }//end if + + // Remove the default value so the CLI value overrides it. + if (isset(self::$overriddenDefaults['reports']) === false) { + $this->reports = $reports; + } else { + $this->reports = array_merge($this->reports, $reports); + } + + self::$overriddenDefaults['reports'] = true; + } else if (substr($arg, 0, 7) === 'filter=') { + if (isset(self::$overriddenDefaults['filter']) === true) { + break; + } + + $this->filter = substr($arg, 7); + self::$overriddenDefaults['filter'] = true; + } else if (substr($arg, 0, 9) === 'standard=') { + $standards = trim(substr($arg, 9)); + if ($standards !== '') { + $this->standards = explode(',', $standards); + } + + self::$overriddenDefaults['standards'] = true; + } else if (substr($arg, 0, 11) === 'extensions=') { + if (isset(self::$overriddenDefaults['extensions']) === true) { + break; + } + + $extensions = explode(',', substr($arg, 11)); + $newExtensions = []; + foreach ($extensions as $ext) { + $slash = strpos($ext, '/'); + if ($slash !== false) { + // They specified the tokenizer too. + list($ext, $tokenizer) = explode('/', $ext); + $newExtensions[$ext] = strtoupper($tokenizer); + continue; + } + + if (isset($this->extensions[$ext]) === true) { + $newExtensions[$ext] = $this->extensions[$ext]; + } else { + $newExtensions[$ext] = 'PHP'; + } + } + + $this->extensions = $newExtensions; + self::$overriddenDefaults['extensions'] = true; + } else if (substr($arg, 0, 7) === 'suffix=') { + if (isset(self::$overriddenDefaults['suffix']) === true) { + break; + } + + $this->suffix = substr($arg, 7); + self::$overriddenDefaults['suffix'] = true; + } else if (substr($arg, 0, 9) === 'parallel=') { + if (isset(self::$overriddenDefaults['parallel']) === true) { + break; + } + + $this->parallel = max((int) substr($arg, 9), 1); + self::$overriddenDefaults['parallel'] = true; + } else if (substr($arg, 0, 9) === 'severity=') { + $this->errorSeverity = (int) substr($arg, 9); + $this->warningSeverity = $this->errorSeverity; + if (isset(self::$overriddenDefaults['errorSeverity']) === false) { + self::$overriddenDefaults['errorSeverity'] = true; + } + + if (isset(self::$overriddenDefaults['warningSeverity']) === false) { + self::$overriddenDefaults['warningSeverity'] = true; + } + } else if (substr($arg, 0, 15) === 'error-severity=') { + if (isset(self::$overriddenDefaults['errorSeverity']) === true) { + break; + } + + $this->errorSeverity = (int) substr($arg, 15); + self::$overriddenDefaults['errorSeverity'] = true; + } else if (substr($arg, 0, 17) === 'warning-severity=') { + if (isset(self::$overriddenDefaults['warningSeverity']) === true) { + break; + } + + $this->warningSeverity = (int) substr($arg, 17); + self::$overriddenDefaults['warningSeverity'] = true; + } else if (substr($arg, 0, 7) === 'ignore=') { + if (isset(self::$overriddenDefaults['ignored']) === true) { + break; + } + + // Split the ignore string on commas, unless the comma is escaped + // using 1 or 3 slashes (\, or \\\,). + $patterns = preg_split( + '/(?<=(?ignored = $ignored; + self::$overriddenDefaults['ignored'] = true; + } else if (substr($arg, 0, 10) === 'generator=' + && PHP_CODESNIFFER_CBF === false + ) { + if (isset(self::$overriddenDefaults['generator']) === true) { + break; + } + + $this->generator = substr($arg, 10); + self::$overriddenDefaults['generator'] = true; + } else if (substr($arg, 0, 9) === 'encoding=') { + if (isset(self::$overriddenDefaults['encoding']) === true) { + break; + } + + $this->encoding = strtolower(substr($arg, 9)); + self::$overriddenDefaults['encoding'] = true; + } else if (substr($arg, 0, 10) === 'tab-width=') { + if (isset(self::$overriddenDefaults['tabWidth']) === true) { + break; + } + + $this->tabWidth = (int) substr($arg, 10); + self::$overriddenDefaults['tabWidth'] = true; + } else { + if ($this->dieOnUnknownArg === false) { + $eqPos = strpos($arg, '='); + try { + if ($eqPos === false) { + $this->values[$arg] = $arg; + } else { + $value = substr($arg, ($eqPos + 1)); + $arg = substr($arg, 0, $eqPos); + $this->values[$arg] = $value; + } + } catch (RuntimeException $e) { + // Value is not valid, so just ignore it. + } + } else { + $this->processUnknownArgument('--'.$arg, $pos); + } + }//end if + break; + }//end switch + + }//end processLongArgument() + + + /** + * Processes an unknown command line argument. + * + * Assumes all unknown arguments are files and folders to check. + * + * @param string $arg The command line argument. + * @param int $pos The position of the argument on the command line. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processUnknownArgument($arg, $pos) + { + // We don't know about any additional switches; just files. + if ($arg[0] === '-') { + if ($this->dieOnUnknownArg === false) { + return; + } + + $error = "ERROR: option \"$arg\" not known".PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $this->processFilePath($arg); + + }//end processUnknownArgument() + + + /** + * Processes a file path and add it to the file list. + * + * @param string $path The path to the file to add. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processFilePath($path) + { + // If we are processing STDIN, don't record any files to check. + if ($this->stdin === true) { + return; + } + + $file = Util\Common::realpath($path); + if (file_exists($file) === false) { + if ($this->dieOnUnknownArg === false) { + return; + } + + $error = 'ERROR: The file "'.$path.'" does not exist.'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } else { + // Can't modify the files array directly because it's not a real + // class member, so need to use this little get/modify/set trick. + $files = $this->files; + $files[] = $file; + $this->files = $files; + self::$overriddenDefaults['files'] = true; + } + + }//end processFilePath() + + + /** + * Prints out the usage information for this script. + * + * @return void + */ + public function printUsage() + { + echo PHP_EOL; + + if (PHP_CODESNIFFER_CBF === true) { + $this->printPHPCBFUsage(); + } else { + $this->printPHPCSUsage(); + } + + echo PHP_EOL; + + }//end printUsage() + + + /** + * Prints out the short usage information for this script. + * + * @param bool $return If TRUE, the usage string is returned + * instead of output to screen. + * + * @return string|void + */ + public function printShortUsage($return=false) + { + if (PHP_CODESNIFFER_CBF === true) { + $usage = 'Run "phpcbf --help" for usage information'; + } else { + $usage = 'Run "phpcs --help" for usage information'; + } + + $usage .= PHP_EOL.PHP_EOL; + + if ($return === true) { + return $usage; + } + + echo $usage; + + }//end printShortUsage() + + + /** + * Prints out the usage information for PHPCS. + * + * @return void + */ + public function printPHPCSUsage() + { + echo 'Usage: phpcs [-nwlsaepqvi] [-d key[=value]] [--colors] [--no-colors]'.PHP_EOL; + echo ' [--cache[=]] [--no-cache] [--tab-width=]'.PHP_EOL; + echo ' [--report=] [--report-file=] [--report-=]'.PHP_EOL; + echo ' [--report-width=] [--basepath=] [--bootstrap=]'.PHP_EOL; + echo ' [--severity=] [--error-severity=] [--warning-severity=]'.PHP_EOL; + echo ' [--runtime-set key value] [--config-set key value] [--config-delete key] [--config-show]'.PHP_EOL; + echo ' [--standard=] [--sniffs=] [--exclude=]'.PHP_EOL; + echo ' [--encoding=] [--parallel=] [--generator=]'.PHP_EOL; + echo ' [--extensions=] [--ignore=] [--ignore-annotations]'.PHP_EOL; + echo ' [--stdin-path=] [--file-list=] [--filter=] - ...'.PHP_EOL; + echo PHP_EOL; + echo ' - Check STDIN instead of local files and directories'.PHP_EOL; + echo ' -n Do not print warnings (shortcut for --warning-severity=0)'.PHP_EOL; + echo ' -w Print both warnings and errors (this is the default)'.PHP_EOL; + echo ' -l Local directory only, no recursion'.PHP_EOL; + echo ' -s Show sniff codes in all reports'.PHP_EOL; + echo ' -a Run interactively'.PHP_EOL; + echo ' -e Explain a standard by showing the sniffs it includes'.PHP_EOL; + echo ' -p Show progress of the run'.PHP_EOL; + echo ' -q Quiet mode; disables progress and verbose output'.PHP_EOL; + echo ' -m Stop error messages from being recorded'.PHP_EOL; + echo ' (saves a lot of memory, but stops many reports from being used)'.PHP_EOL; + echo ' -v Print processed files'.PHP_EOL; + echo ' -vv Print ruleset and token output'.PHP_EOL; + echo ' -vvv Print sniff processing information'.PHP_EOL; + echo ' -i Show a list of installed coding standards'.PHP_EOL; + echo ' -d Set the [key] php.ini value to [value] or [true] if value is omitted'.PHP_EOL; + echo PHP_EOL; + echo ' --help Print this help message'.PHP_EOL; + echo ' --version Print version information'.PHP_EOL; + echo ' --colors Use colors in output'.PHP_EOL; + echo ' --no-colors Do not use colors in output (this is the default)'.PHP_EOL; + echo ' --cache Cache results between runs'.PHP_EOL; + echo ' --no-cache Do not cache results between runs (this is the default)'.PHP_EOL; + echo ' --ignore-annotations Ignore all phpcs: annotations in code comments'.PHP_EOL; + echo PHP_EOL; + echo ' Use a specific file for caching (uses a temporary file by default)'.PHP_EOL; + echo ' A path to strip from the front of file paths inside reports'.PHP_EOL; + echo ' A comma separated list of files to run before processing begins'.PHP_EOL; + echo ' The encoding of the files being checked (default is utf-8)'.PHP_EOL; + echo ' A comma separated list of file extensions to check'.PHP_EOL; + echo ' The type of the file can be specified using: ext/type'.PHP_EOL; + echo ' e.g., module/php,es/js'.PHP_EOL; + echo ' One or more files and/or directories to check'.PHP_EOL; + echo ' A file containing a list of files and/or directories to check (one per line)'.PHP_EOL; + echo ' Use either the "gitmodified" or "gitstaged" filter,'.PHP_EOL; + echo ' or specify the path to a custom filter class'.PHP_EOL; + echo ' Use either the "HTML", "Markdown" or "Text" generator'.PHP_EOL; + echo ' (forces documentation generation instead of checking)'.PHP_EOL; + echo ' A comma separated list of patterns to ignore files and directories'.PHP_EOL; + echo ' How many files should be checked simultaneously (default is 1)'.PHP_EOL; + echo ' Print either the "full", "xml", "checkstyle", "csv"'.PHP_EOL; + echo ' "json", "junit", "emacs", "source", "summary", "diff"'.PHP_EOL; + echo ' "svnblame", "gitblame", "hgblame" or "notifysend" report,'.PHP_EOL; + echo ' or specify the path to a custom report class'.PHP_EOL; + echo ' (the "full" report is printed by default)'.PHP_EOL; + echo ' Write the report to the specified file path'.PHP_EOL; + echo ' How many columns wide screen reports should be printed'.PHP_EOL; + echo ' or set to "auto" to use current screen width, where supported'.PHP_EOL; + echo ' The minimum severity required to display an error or warning'.PHP_EOL; + echo ' A comma separated list of sniff codes to include or exclude from checking'.PHP_EOL; + echo ' (all sniffs must be part of the specified standard)'.PHP_EOL; + echo ' The name or path of the coding standard to use'.PHP_EOL; + echo ' If processing STDIN, the file path that STDIN will be processed as'.PHP_EOL; + echo ' The number of spaces each tab represents'.PHP_EOL; + + }//end printPHPCSUsage() + + + /** + * Prints out the usage information for PHPCBF. + * + * @return void + */ + public function printPHPCBFUsage() + { + echo 'Usage: phpcbf [-nwli] [-d key[=value]] [--ignore-annotations] [--bootstrap=]'.PHP_EOL; + echo ' [--standard=] [--sniffs=] [--exclude=] [--suffix=]'.PHP_EOL; + echo ' [--severity=] [--error-severity=] [--warning-severity=]'.PHP_EOL; + echo ' [--tab-width=] [--encoding=] [--parallel=]'.PHP_EOL; + echo ' [--basepath=] [--extensions=] [--ignore=]'.PHP_EOL; + echo ' [--stdin-path=] [--file-list=] [--filter=] - ...'.PHP_EOL; + echo PHP_EOL; + echo ' - Fix STDIN instead of local files and directories'.PHP_EOL; + echo ' -n Do not fix warnings (shortcut for --warning-severity=0)'.PHP_EOL; + echo ' -w Fix both warnings and errors (on by default)'.PHP_EOL; + echo ' -l Local directory only, no recursion'.PHP_EOL; + echo ' -p Show progress of the run'.PHP_EOL; + echo ' -q Quiet mode; disables progress and verbose output'.PHP_EOL; + echo ' -v Print processed files'.PHP_EOL; + echo ' -vv Print ruleset and token output'.PHP_EOL; + echo ' -vvv Print sniff processing information'.PHP_EOL; + echo ' -i Show a list of installed coding standards'.PHP_EOL; + echo ' -d Set the [key] php.ini value to [value] or [true] if value is omitted'.PHP_EOL; + echo PHP_EOL; + echo ' --help Print this help message'.PHP_EOL; + echo ' --version Print version information'.PHP_EOL; + echo ' --ignore-annotations Ignore all phpcs: annotations in code comments'.PHP_EOL; + echo PHP_EOL; + echo ' A path to strip from the front of file paths inside reports'.PHP_EOL; + echo ' A comma separated list of files to run before processing begins'.PHP_EOL; + echo ' The encoding of the files being fixed (default is utf-8)'.PHP_EOL; + echo ' A comma separated list of file extensions to fix'.PHP_EOL; + echo ' The type of the file can be specified using: ext/type'.PHP_EOL; + echo ' e.g., module/php,es/js'.PHP_EOL; + echo ' One or more files and/or directories to fix'.PHP_EOL; + echo ' A file containing a list of files and/or directories to fix (one per line)'.PHP_EOL; + echo ' Use either the "gitmodified" or "gitstaged" filter,'.PHP_EOL; + echo ' or specify the path to a custom filter class'.PHP_EOL; + echo ' A comma separated list of patterns to ignore files and directories'.PHP_EOL; + echo ' How many files should be fixed simultaneously (default is 1)'.PHP_EOL; + echo ' The minimum severity required to fix an error or warning'.PHP_EOL; + echo ' A comma separated list of sniff codes to include or exclude from fixing'.PHP_EOL; + echo ' (all sniffs must be part of the specified standard)'.PHP_EOL; + echo ' The name or path of the coding standard to use'.PHP_EOL; + echo ' If processing STDIN, the file path that STDIN will be processed as'.PHP_EOL; + echo ' Write modified files to a filename using this suffix'.PHP_EOL; + echo ' ("diff" and "patch" are not used in this mode)'.PHP_EOL; + echo ' The number of spaces each tab represents'.PHP_EOL; + + }//end printPHPCBFUsage() + + + /** + * Get a single config value. + * + * @param string $key The name of the config value. + * + * @return string|null + * @see setConfigData() + * @see getAllConfigData() + */ + public static function getConfigData($key) + { + $phpCodeSnifferConfig = self::getAllConfigData(); + + if ($phpCodeSnifferConfig === null) { + return null; + } + + if (isset($phpCodeSnifferConfig[$key]) === false) { + return null; + } + + return $phpCodeSnifferConfig[$key]; + + }//end getConfigData() + + + /** + * Get the path to an executable utility. + * + * @param string $name The name of the executable utility. + * + * @return string|null + * @see getConfigData() + */ + public static function getExecutablePath($name) + { + $data = self::getConfigData($name.'_path'); + if ($data !== null) { + return $data; + } + + if ($name === "php") { + // For php, we know the executable path. There's no need to look it up. + return PHP_BINARY; + } + + if (array_key_exists($name, self::$executablePaths) === true) { + return self::$executablePaths[$name]; + } + + if (stripos(PHP_OS, 'WIN') === 0) { + $cmd = 'where '.escapeshellarg($name).' 2> nul'; + } else { + $cmd = 'which '.escapeshellarg($name).' 2> /dev/null'; + } + + $result = exec($cmd, $output, $retVal); + if ($retVal !== 0) { + $result = null; + } + + self::$executablePaths[$name] = $result; + return $result; + + }//end getExecutablePath() + + + /** + * Set a single config value. + * + * @param string $key The name of the config value. + * @param string|null $value The value to set. If null, the config + * entry is deleted, reverting it to the + * default value. + * @param boolean $temp Set this config data temporarily for this + * script run. This will not write the config + * data to the config file. + * + * @return bool + * @see getConfigData() + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If the config file can not be written. + */ + public static function setConfigData($key, $value, $temp=false) + { + if (isset(self::$overriddenDefaults['runtime-set']) === true + && isset(self::$overriddenDefaults['runtime-set'][$key]) === true + ) { + return false; + } + + if ($temp === false) { + $path = ''; + if (is_callable('\Phar::running') === true) { + $path = \Phar::running(false); + } + + if ($path !== '') { + $configFile = dirname($path).DIRECTORY_SEPARATOR.'CodeSniffer.conf'; + } else { + $configFile = dirname(__DIR__).DIRECTORY_SEPARATOR.'CodeSniffer.conf'; + if (is_file($configFile) === false + && strpos('@data_dir@', '@data_dir') === false + ) { + // If data_dir was replaced, this is a PEAR install and we can + // use the PEAR data dir to store the conf file. + $configFile = '@data_dir@/PHP_CodeSniffer/CodeSniffer.conf'; + } + } + + if (is_file($configFile) === true + && is_writable($configFile) === false + ) { + $error = 'ERROR: Config file '.$configFile.' is not writable'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + }//end if + + $phpCodeSnifferConfig = self::getAllConfigData(); + + if ($value === null) { + if (isset($phpCodeSnifferConfig[$key]) === true) { + unset($phpCodeSnifferConfig[$key]); + } + } else { + $phpCodeSnifferConfig[$key] = $value; + } + + if ($temp === false) { + $output = '<'.'?php'."\n".' $phpCodeSnifferConfig = '; + $output .= var_export($phpCodeSnifferConfig, true); + $output .= ";\n?".'>'; + + if (file_put_contents($configFile, $output) === false) { + $error = 'ERROR: Config file '.$configFile.' could not be written'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + self::$configDataFile = $configFile; + } + + self::$configData = $phpCodeSnifferConfig; + + // If the installed paths are being set, make sure all known + // standards paths are added to the autoloader. + if ($key === 'installed_paths') { + $installedStandards = Util\Standards::getInstalledStandardDetails(); + foreach ($installedStandards as $name => $details) { + Autoload::addSearchPath($details['path'], $details['namespace']); + } + } + + return true; + + }//end setConfigData() + + + /** + * Get all config data. + * + * @return array + * @see getConfigData() + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If the config file could not be read. + */ + public static function getAllConfigData() + { + if (self::$configData !== null) { + return self::$configData; + } + + $path = ''; + if (is_callable('\Phar::running') === true) { + $path = \Phar::running(false); + } + + if ($path !== '') { + $configFile = dirname($path).DIRECTORY_SEPARATOR.'CodeSniffer.conf'; + } else { + $configFile = dirname(__DIR__).DIRECTORY_SEPARATOR.'CodeSniffer.conf'; + if (is_file($configFile) === false + && strpos('@data_dir@', '@data_dir') === false + ) { + $configFile = '@data_dir@/PHP_CodeSniffer/CodeSniffer.conf'; + } + } + + if (is_file($configFile) === false) { + self::$configData = []; + return []; + } + + if (Common::isReadable($configFile) === false) { + $error = 'ERROR: Config file '.$configFile.' is not readable'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + include $configFile; + self::$configDataFile = $configFile; + self::$configData = $phpCodeSnifferConfig; + return self::$configData; + + }//end getAllConfigData() + + + /** + * Prints out the gathered config data. + * + * @param array $data The config data to print. + * + * @return void + */ + public function printConfigData($data) + { + $max = 0; + $keys = array_keys($data); + foreach ($keys as $key) { + $len = strlen($key); + if (strlen($key) > $max) { + $max = $len; + } + } + + if ($max === 0) { + return; + } + + $max += 2; + ksort($data); + foreach ($data as $name => $value) { + echo str_pad($name.': ', $max).$value.PHP_EOL; + } + + }//end printConfigData() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Exceptions/DeepExitException.php b/vendor/squizlabs/php_codesniffer/src/Exceptions/DeepExitException.php new file mode 100644 index 00000000..b1440944 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Exceptions/DeepExitException.php @@ -0,0 +1,18 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Exceptions; + +class DeepExitException extends \Exception +{ + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Exceptions/RuntimeException.php b/vendor/squizlabs/php_codesniffer/src/Exceptions/RuntimeException.php new file mode 100644 index 00000000..093bf13d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Exceptions/RuntimeException.php @@ -0,0 +1,15 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Exceptions; + +class RuntimeException extends \RuntimeException +{ + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Exceptions/TokenizerException.php b/vendor/squizlabs/php_codesniffer/src/Exceptions/TokenizerException.php new file mode 100644 index 00000000..ceba00cc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Exceptions/TokenizerException.php @@ -0,0 +1,15 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Exceptions; + +class TokenizerException extends \Exception +{ + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Files/DummyFile.php b/vendor/squizlabs/php_codesniffer/src/Files/DummyFile.php new file mode 100644 index 00000000..60143030 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Files/DummyFile.php @@ -0,0 +1,82 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Files; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Config; + +class DummyFile extends File +{ + + + /** + * Creates a DummyFile object and sets the content. + * + * @param string $content The content of the file. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public function __construct($content, Ruleset $ruleset, Config $config) + { + $this->setContent($content); + + // See if a filename was defined in the content. + // This is done by including: phpcs_input_file: [file path] + // as the first line of content. + $path = 'STDIN'; + if ($content !== '') { + if (substr($content, 0, 17) === 'phpcs_input_file:') { + $eolPos = strpos($content, $this->eolChar); + $filename = trim(substr($content, 17, ($eolPos - 17))); + $content = substr($content, ($eolPos + strlen($this->eolChar))); + $path = $filename; + + $this->setContent($content); + } + } + + // The CLI arg overrides anything passed in the content. + if ($config->stdinPath !== null) { + $path = $config->stdinPath; + } + + parent::__construct($path, $ruleset, $config); + + }//end __construct() + + + /** + * Set the error, warning, and fixable counts for the file. + * + * @param int $errorCount The number of errors found. + * @param int $warningCount The number of warnings found. + * @param int $fixableCount The number of fixable errors found. + * @param int $fixedCount The number of errors that were fixed. + * + * @return void + */ + public function setErrorCounts($errorCount, $warningCount, $fixableCount, $fixedCount) + { + $this->errorCount = $errorCount; + $this->warningCount = $warningCount; + $this->fixableCount = $fixableCount; + $this->fixedCount = $fixedCount; + + }//end setErrorCounts() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Files/File.php b/vendor/squizlabs/php_codesniffer/src/Files/File.php new file mode 100644 index 00000000..a15af762 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Files/File.php @@ -0,0 +1,2829 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Files; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Fixer; +use PHP_CodeSniffer\Util; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Exceptions\TokenizerException; + +class File +{ + + /** + * The absolute path to the file associated with this object. + * + * @var string + */ + public $path = ''; + + /** + * The content of the file. + * + * @var string + */ + protected $content = ''; + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + public $config = null; + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + public $ruleset = null; + + /** + * If TRUE, the entire file is being ignored. + * + * @var boolean + */ + public $ignored = false; + + /** + * The EOL character this file uses. + * + * @var string + */ + public $eolChar = ''; + + /** + * The Fixer object to control fixing errors. + * + * @var \PHP_CodeSniffer\Fixer + */ + public $fixer = null; + + /** + * The tokenizer being used for this file. + * + * @var \PHP_CodeSniffer\Tokenizers\Tokenizer + */ + public $tokenizer = null; + + /** + * The name of the tokenizer being used for this file. + * + * @var string + */ + public $tokenizerType = 'PHP'; + + /** + * Was the file loaded from cache? + * + * If TRUE, the file was loaded from a local cache. + * If FALSE, the file was tokenized and processed fully. + * + * @var boolean + */ + public $fromCache = false; + + /** + * The number of tokens in this file. + * + * Stored here to save calling count() everywhere. + * + * @var integer + */ + public $numTokens = 0; + + /** + * The tokens stack map. + * + * @var array + */ + protected $tokens = []; + + /** + * The errors raised from sniffs. + * + * @var array + * @see getErrors() + */ + protected $errors = []; + + /** + * The warnings raised from sniffs. + * + * @var array + * @see getWarnings() + */ + protected $warnings = []; + + /** + * The metrics recorded by sniffs. + * + * @var array + * @see getMetrics() + */ + protected $metrics = []; + + /** + * The metrics recorded for each token. + * + * Stops the same metric being recorded for the same token twice. + * + * @var array + * @see getMetrics() + */ + private $metricTokens = []; + + /** + * The total number of errors raised. + * + * @var integer + */ + protected $errorCount = 0; + + /** + * The total number of warnings raised. + * + * @var integer + */ + protected $warningCount = 0; + + /** + * The total number of errors and warnings that can be fixed. + * + * @var integer + */ + protected $fixableCount = 0; + + /** + * The total number of errors and warnings that were fixed. + * + * @var integer + */ + protected $fixedCount = 0; + + /** + * TRUE if errors are being replayed from the cache. + * + * @var boolean + */ + protected $replayingErrors = false; + + /** + * An array of sniffs that are being ignored. + * + * @var array + */ + protected $ignoredListeners = []; + + /** + * An array of message codes that are being ignored. + * + * @var array + */ + protected $ignoredCodes = []; + + /** + * An array of sniffs listening to this file's processing. + * + * @var \PHP_CodeSniffer\Sniffs\Sniff[] + */ + protected $listeners = []; + + /** + * The class name of the sniff currently processing the file. + * + * @var string + */ + protected $activeListener = ''; + + /** + * An array of sniffs being processed and how long they took. + * + * @var array + */ + protected $listenerTimes = []; + + /** + * A cache of often used config settings to improve performance. + * + * Storing them here saves 10k+ calls to __get() in the Config class. + * + * @var array + */ + protected $configCache = []; + + + /** + * Constructs a file. + * + * @param string $path The absolute path to the file to process. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public function __construct($path, Ruleset $ruleset, Config $config) + { + $this->path = $path; + $this->ruleset = $ruleset; + $this->config = $config; + $this->fixer = new Fixer(); + + $parts = explode('.', $path); + $extension = array_pop($parts); + if (isset($config->extensions[$extension]) === true) { + $this->tokenizerType = $config->extensions[$extension]; + } else { + // Revert to default. + $this->tokenizerType = 'PHP'; + } + + $this->configCache['cache'] = $this->config->cache; + $this->configCache['sniffs'] = array_map('strtolower', $this->config->sniffs); + $this->configCache['exclude'] = array_map('strtolower', $this->config->exclude); + $this->configCache['errorSeverity'] = $this->config->errorSeverity; + $this->configCache['warningSeverity'] = $this->config->warningSeverity; + $this->configCache['recordErrors'] = $this->config->recordErrors; + $this->configCache['ignorePatterns'] = $this->ruleset->ignorePatterns; + $this->configCache['includePatterns'] = $this->ruleset->includePatterns; + + }//end __construct() + + + /** + * Set the content of the file. + * + * Setting the content also calculates the EOL char being used. + * + * @param string $content The file content. + * + * @return void + */ + public function setContent($content) + { + $this->content = $content; + $this->tokens = []; + + try { + $this->eolChar = Util\Common::detectLineEndings($content); + } catch (RuntimeException $e) { + $this->addWarningOnLine($e->getMessage(), 1, 'Internal.DetectLineEndings'); + return; + } + + }//end setContent() + + + /** + * Reloads the content of the file. + * + * By default, we have no idea where our content comes from, + * so we can't do anything. + * + * @return void + */ + public function reloadContent() + { + + }//end reloadContent() + + + /** + * Disables caching of this file. + * + * @return void + */ + public function disableCaching() + { + $this->configCache['cache'] = false; + + }//end disableCaching() + + + /** + * Starts the stack traversal and tells listeners when tokens are found. + * + * @return void + */ + public function process() + { + if ($this->ignored === true) { + return; + } + + $this->errors = []; + $this->warnings = []; + $this->errorCount = 0; + $this->warningCount = 0; + $this->fixableCount = 0; + + $this->parse(); + + // Check if tokenizer errors cause this file to be ignored. + if ($this->ignored === true) { + return; + } + + $this->fixer->startFile($this); + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + echo "\t*** START TOKEN PROCESSING ***".PHP_EOL; + } + + $foundCode = false; + $listenerIgnoreTo = []; + $inTests = defined('PHP_CODESNIFFER_IN_TESTS'); + $checkAnnotations = $this->config->annotations; + + // Foreach of the listeners that have registered to listen for this + // token, get them to process it. + foreach ($this->tokens as $stackPtr => $token) { + // Check for ignored lines. + if ($checkAnnotations === true + && ($token['code'] === T_COMMENT + || $token['code'] === T_PHPCS_IGNORE_FILE + || $token['code'] === T_PHPCS_SET + || $token['code'] === T_DOC_COMMENT_STRING + || $token['code'] === T_DOC_COMMENT_TAG + || ($inTests === true && $token['code'] === T_INLINE_HTML)) + ) { + $commentText = ltrim($this->tokens[$stackPtr]['content'], " \t/*#"); + $commentTextLower = strtolower($commentText); + if (strpos($commentText, '@codingStandards') !== false) { + if (strpos($commentText, '@codingStandardsIgnoreFile') !== false) { + // Ignoring the whole file, just a little late. + $this->errors = []; + $this->warnings = []; + $this->errorCount = 0; + $this->warningCount = 0; + $this->fixableCount = 0; + return; + } else if (strpos($commentText, '@codingStandardsChangeSetting') !== false) { + $start = strpos($commentText, '@codingStandardsChangeSetting'); + $comment = substr($commentText, ($start + 30)); + $parts = explode(' ', $comment); + if (count($parts) >= 2) { + $sniffParts = explode('.', $parts[0]); + if (count($sniffParts) >= 3) { + // If the sniff code is not known to us, it has not been registered in this run. + // But don't throw an error as it could be there for a different standard to use. + if (isset($this->ruleset->sniffCodes[$parts[0]]) === true) { + $listenerCode = array_shift($parts); + $propertyCode = array_shift($parts); + $propertyValue = rtrim(implode(' ', $parts), " */\r\n"); + $listenerClass = $this->ruleset->sniffCodes[$listenerCode]; + $this->ruleset->setSniffProperty($listenerClass, $propertyCode, $propertyValue); + } + } + } + }//end if + } else if (substr($commentTextLower, 0, 16) === 'phpcs:ignorefile' + || substr($commentTextLower, 0, 17) === '@phpcs:ignorefile' + ) { + // Ignoring the whole file, just a little late. + $this->errors = []; + $this->warnings = []; + $this->errorCount = 0; + $this->warningCount = 0; + $this->fixableCount = 0; + return; + } else if (substr($commentTextLower, 0, 9) === 'phpcs:set' + || substr($commentTextLower, 0, 10) === '@phpcs:set' + ) { + if (isset($token['sniffCode']) === true) { + $listenerCode = $token['sniffCode']; + if (isset($this->ruleset->sniffCodes[$listenerCode]) === true) { + $propertyCode = $token['sniffProperty']; + $propertyValue = $token['sniffPropertyValue']; + $listenerClass = $this->ruleset->sniffCodes[$listenerCode]; + $this->ruleset->setSniffProperty($listenerClass, $propertyCode, $propertyValue); + } + } + }//end if + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + $type = $token['type']; + $content = Util\Common::prepareForOutput($token['content']); + echo "\t\tProcess token $stackPtr: $type => $content".PHP_EOL; + } + + if ($token['code'] !== T_INLINE_HTML) { + $foundCode = true; + } + + if (isset($this->ruleset->tokenListeners[$token['code']]) === false) { + continue; + } + + foreach ($this->ruleset->tokenListeners[$token['code']] as $listenerData) { + if (isset($this->ignoredListeners[$listenerData['class']]) === true + || (isset($listenerIgnoreTo[$listenerData['class']]) === true + && $listenerIgnoreTo[$listenerData['class']] > $stackPtr) + ) { + // This sniff is ignoring past this token, or the whole file. + continue; + } + + // Make sure this sniff supports the tokenizer + // we are currently using. + $class = $listenerData['class']; + + if (isset($listenerData['tokenizers'][$this->tokenizerType]) === false) { + continue; + } + + if (trim($this->path, '\'"') !== 'STDIN') { + // If the file path matches one of our ignore patterns, skip it. + // While there is support for a type of each pattern + // (absolute or relative) we don't actually support it here. + foreach ($listenerData['ignore'] as $pattern) { + // We assume a / directory separator, as do the exclude rules + // most developers write, so we need a special case for any system + // that is different. + if (DIRECTORY_SEPARATOR === '\\') { + $pattern = str_replace('/', '\\\\', $pattern); + } + + $pattern = '`'.$pattern.'`i'; + if (preg_match($pattern, $this->path) === 1) { + $this->ignoredListeners[$class] = true; + continue(2); + } + } + + // If the file path does not match one of our include patterns, skip it. + // While there is support for a type of each pattern + // (absolute or relative) we don't actually support it here. + if (empty($listenerData['include']) === false) { + $included = false; + foreach ($listenerData['include'] as $pattern) { + // We assume a / directory separator, as do the exclude rules + // most developers write, so we need a special case for any system + // that is different. + if (DIRECTORY_SEPARATOR === '\\') { + $pattern = str_replace('/', '\\\\', $pattern); + } + + $pattern = '`'.$pattern.'`i'; + if (preg_match($pattern, $this->path) === 1) { + $included = true; + break; + } + } + + if ($included === false) { + $this->ignoredListeners[$class] = true; + continue; + } + }//end if + }//end if + + $this->activeListener = $class; + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + $startTime = microtime(true); + echo "\t\t\tProcessing ".$this->activeListener.'... '; + } + + $ignoreTo = $this->ruleset->sniffs[$class]->process($this, $stackPtr); + if ($ignoreTo !== null) { + $listenerIgnoreTo[$this->activeListener] = $ignoreTo; + } + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + $timeTaken = (microtime(true) - $startTime); + if (isset($this->listenerTimes[$this->activeListener]) === false) { + $this->listenerTimes[$this->activeListener] = 0; + } + + $this->listenerTimes[$this->activeListener] += $timeTaken; + + $timeTaken = round(($timeTaken), 4); + echo "DONE in $timeTaken seconds".PHP_EOL; + } + + $this->activeListener = ''; + }//end foreach + }//end foreach + + // If short open tags are off but the file being checked uses + // short open tags, the whole content will be inline HTML + // and nothing will be checked. So try and handle this case. + // We don't show this error for STDIN because we can't be sure the content + // actually came directly from the user. It could be something like + // refs from a Git pre-push hook. + if ($foundCode === false && $this->tokenizerType === 'PHP' && $this->path !== 'STDIN') { + $shortTags = (bool) ini_get('short_open_tag'); + if ($shortTags === false) { + $error = 'No PHP code was found in this file and short open tags are not allowed by this install of PHP. This file may be using short open tags but PHP does not allow them.'; + $this->addWarning($error, null, 'Internal.NoCodeFound'); + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + echo "\t*** END TOKEN PROCESSING ***".PHP_EOL; + echo "\t*** START SNIFF PROCESSING REPORT ***".PHP_EOL; + + asort($this->listenerTimes, SORT_NUMERIC); + $this->listenerTimes = array_reverse($this->listenerTimes, true); + foreach ($this->listenerTimes as $listener => $timeTaken) { + echo "\t$listener: ".round(($timeTaken), 4).' secs'.PHP_EOL; + } + + echo "\t*** END SNIFF PROCESSING REPORT ***".PHP_EOL; + } + + $this->fixedCount += $this->fixer->getFixCount(); + + }//end process() + + + /** + * Tokenizes the file and prepares it for the test run. + * + * @return void + */ + public function parse() + { + if (empty($this->tokens) === false) { + // File has already been parsed. + return; + } + + try { + $tokenizerClass = 'PHP_CodeSniffer\Tokenizers\\'.$this->tokenizerType; + $this->tokenizer = new $tokenizerClass($this->content, $this->config, $this->eolChar); + $this->tokens = $this->tokenizer->getTokens(); + } catch (TokenizerException $e) { + $this->ignored = true; + $this->addWarning($e->getMessage(), null, 'Internal.Tokenizer.Exception'); + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo "[$this->tokenizerType => tokenizer error]... "; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + return; + } + + $this->numTokens = count($this->tokens); + + // Check for mixed line endings as these can cause tokenizer errors and we + // should let the user know that the results they get may be incorrect. + // This is done by removing all backslashes, removing the newline char we + // detected, then converting newlines chars into text. If any backslashes + // are left at the end, we have additional newline chars in use. + $contents = str_replace('\\', '', $this->content); + $contents = str_replace($this->eolChar, '', $contents); + $contents = str_replace("\n", '\n', $contents); + $contents = str_replace("\r", '\r', $contents); + if (strpos($contents, '\\') !== false) { + $error = 'File has mixed line endings; this may cause incorrect results'; + $this->addWarningOnLine($error, 1, 'Internal.LineEndings.Mixed'); + } + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + if ($this->numTokens === 0) { + $numLines = 0; + } else { + $numLines = $this->tokens[($this->numTokens - 1)]['line']; + } + + echo "[$this->tokenizerType => $this->numTokens tokens in $numLines lines]... "; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + }//end parse() + + + /** + * Returns the token stack for this file. + * + * @return array + */ + public function getTokens() + { + return $this->tokens; + + }//end getTokens() + + + /** + * Remove vars stored in this file that are no longer required. + * + * @return void + */ + public function cleanUp() + { + $this->listenerTimes = null; + $this->content = null; + $this->tokens = null; + $this->metricTokens = null; + $this->tokenizer = null; + $this->fixer = null; + $this->config = null; + $this->ruleset = null; + + }//end cleanUp() + + + /** + * Records an error against a specific token in the file. + * + * @param string $error The error message. + * @param int $stackPtr The stack position where the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the error message. + * @param int $severity The severity level for this error. A value of 0 + * will be converted into the default severity level. + * @param boolean $fixable Can the error be fixed by the sniff? + * + * @return boolean + */ + public function addError( + $error, + $stackPtr, + $code, + $data=[], + $severity=0, + $fixable=false + ) { + if ($stackPtr === null) { + $line = 1; + $column = 1; + } else { + $line = $this->tokens[$stackPtr]['line']; + $column = $this->tokens[$stackPtr]['column']; + } + + return $this->addMessage(true, $error, $line, $column, $code, $data, $severity, $fixable); + + }//end addError() + + + /** + * Records a warning against a specific token in the file. + * + * @param string $warning The error message. + * @param int $stackPtr The stack position where the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the warning message. + * @param int $severity The severity level for this warning. A value of 0 + * will be converted into the default severity level. + * @param boolean $fixable Can the warning be fixed by the sniff? + * + * @return boolean + */ + public function addWarning( + $warning, + $stackPtr, + $code, + $data=[], + $severity=0, + $fixable=false + ) { + if ($stackPtr === null) { + $line = 1; + $column = 1; + } else { + $line = $this->tokens[$stackPtr]['line']; + $column = $this->tokens[$stackPtr]['column']; + } + + return $this->addMessage(false, $warning, $line, $column, $code, $data, $severity, $fixable); + + }//end addWarning() + + + /** + * Records an error against a specific line in the file. + * + * @param string $error The error message. + * @param int $line The line on which the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the error message. + * @param int $severity The severity level for this error. A value of 0 + * will be converted into the default severity level. + * + * @return boolean + */ + public function addErrorOnLine( + $error, + $line, + $code, + $data=[], + $severity=0 + ) { + return $this->addMessage(true, $error, $line, 1, $code, $data, $severity, false); + + }//end addErrorOnLine() + + + /** + * Records a warning against a specific token in the file. + * + * @param string $warning The error message. + * @param int $line The line on which the warning occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the warning message. + * @param int $severity The severity level for this warning. A value of 0 will + * will be converted into the default severity level. + * + * @return boolean + */ + public function addWarningOnLine( + $warning, + $line, + $code, + $data=[], + $severity=0 + ) { + return $this->addMessage(false, $warning, $line, 1, $code, $data, $severity, false); + + }//end addWarningOnLine() + + + /** + * Records a fixable error against a specific token in the file. + * + * Returns true if the error was recorded and should be fixed. + * + * @param string $error The error message. + * @param int $stackPtr The stack position where the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the error message. + * @param int $severity The severity level for this error. A value of 0 + * will be converted into the default severity level. + * + * @return boolean + */ + public function addFixableError( + $error, + $stackPtr, + $code, + $data=[], + $severity=0 + ) { + $recorded = $this->addError($error, $stackPtr, $code, $data, $severity, true); + if ($recorded === true && $this->fixer->enabled === true) { + return true; + } + + return false; + + }//end addFixableError() + + + /** + * Records a fixable warning against a specific token in the file. + * + * Returns true if the warning was recorded and should be fixed. + * + * @param string $warning The error message. + * @param int $stackPtr The stack position where the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the warning message. + * @param int $severity The severity level for this warning. A value of 0 + * will be converted into the default severity level. + * + * @return boolean + */ + public function addFixableWarning( + $warning, + $stackPtr, + $code, + $data=[], + $severity=0 + ) { + $recorded = $this->addWarning($warning, $stackPtr, $code, $data, $severity, true); + if ($recorded === true && $this->fixer->enabled === true) { + return true; + } + + return false; + + }//end addFixableWarning() + + + /** + * Adds an error to the error stack. + * + * @param boolean $error Is this an error message? + * @param string $message The text of the message. + * @param int $line The line on which the message occurred. + * @param int $column The column at which the message occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the message. + * @param int $severity The severity level for this message. A value of 0 + * will be converted into the default severity level. + * @param boolean $fixable Can the problem be fixed by the sniff? + * + * @return boolean + */ + protected function addMessage($error, $message, $line, $column, $code, $data, $severity, $fixable) + { + // Check if this line is ignoring all message codes. + if (isset($this->tokenizer->ignoredLines[$line]['.all']) === true) { + return false; + } + + // Work out which sniff generated the message. + $parts = explode('.', $code); + if ($parts[0] === 'Internal') { + // An internal message. + $listenerCode = Util\Common::getSniffCode($this->activeListener); + $sniffCode = $code; + $checkCodes = [$sniffCode]; + } else { + if ($parts[0] !== $code) { + // The full message code has been passed in. + $sniffCode = $code; + $listenerCode = substr($sniffCode, 0, strrpos($sniffCode, '.')); + } else { + $listenerCode = Util\Common::getSniffCode($this->activeListener); + $sniffCode = $listenerCode.'.'.$code; + $parts = explode('.', $sniffCode); + } + + $checkCodes = [ + $sniffCode, + $parts[0].'.'.$parts[1].'.'.$parts[2], + $parts[0].'.'.$parts[1], + $parts[0], + ]; + }//end if + + if (isset($this->tokenizer->ignoredLines[$line]) === true) { + // Check if this line is ignoring this specific message. + $ignored = false; + foreach ($checkCodes as $checkCode) { + if (isset($this->tokenizer->ignoredLines[$line][$checkCode]) === true) { + $ignored = true; + break; + } + } + + // If it is ignored, make sure it's not whitelisted. + if ($ignored === true + && isset($this->tokenizer->ignoredLines[$line]['.except']) === true + ) { + foreach ($checkCodes as $checkCode) { + if (isset($this->tokenizer->ignoredLines[$line]['.except'][$checkCode]) === true) { + $ignored = false; + break; + } + } + } + + if ($ignored === true) { + return false; + } + }//end if + + $includeAll = true; + if ($this->configCache['cache'] === false + || $this->configCache['recordErrors'] === false + ) { + $includeAll = false; + } + + // Filter out any messages for sniffs that shouldn't have run + // due to the use of the --sniffs command line argument. + if ($includeAll === false + && ((empty($this->configCache['sniffs']) === false + && in_array(strtolower($listenerCode), $this->configCache['sniffs'], true) === false) + || (empty($this->configCache['exclude']) === false + && in_array(strtolower($listenerCode), $this->configCache['exclude'], true) === true)) + ) { + return false; + } + + // If we know this sniff code is being ignored for this file, return early. + foreach ($checkCodes as $checkCode) { + if (isset($this->ignoredCodes[$checkCode]) === true) { + return false; + } + } + + $oppositeType = 'warning'; + if ($error === false) { + $oppositeType = 'error'; + } + + foreach ($checkCodes as $checkCode) { + // Make sure this message type has not been set to the opposite message type. + if (isset($this->ruleset->ruleset[$checkCode]['type']) === true + && $this->ruleset->ruleset[$checkCode]['type'] === $oppositeType + ) { + $error = !$error; + break; + } + } + + if ($error === true) { + $configSeverity = $this->configCache['errorSeverity']; + $messageCount = &$this->errorCount; + $messages = &$this->errors; + } else { + $configSeverity = $this->configCache['warningSeverity']; + $messageCount = &$this->warningCount; + $messages = &$this->warnings; + } + + if ($includeAll === false && $configSeverity === 0) { + // Don't bother doing any processing as these messages are just going to + // be hidden in the reports anyway. + return false; + } + + if ($severity === 0) { + $severity = 5; + } + + foreach ($checkCodes as $checkCode) { + // Make sure we are interested in this severity level. + if (isset($this->ruleset->ruleset[$checkCode]['severity']) === true) { + $severity = $this->ruleset->ruleset[$checkCode]['severity']; + break; + } + } + + if ($includeAll === false && $configSeverity > $severity) { + return false; + } + + // Make sure we are not ignoring this file. + $included = null; + if (trim($this->path, '\'"') === 'STDIN') { + $included = true; + } else { + foreach ($checkCodes as $checkCode) { + $patterns = null; + + if (isset($this->configCache['includePatterns'][$checkCode]) === true) { + $patterns = $this->configCache['includePatterns'][$checkCode]; + $excluding = false; + } else if (isset($this->configCache['ignorePatterns'][$checkCode]) === true) { + $patterns = $this->configCache['ignorePatterns'][$checkCode]; + $excluding = true; + } + + if ($patterns === null) { + continue; + } + + foreach ($patterns as $pattern => $type) { + // While there is support for a type of each pattern + // (absolute or relative) we don't actually support it here. + $replacements = [ + '\\,' => ',', + '*' => '.*', + ]; + + // We assume a / directory separator, as do the exclude rules + // most developers write, so we need a special case for any system + // that is different. + if (DIRECTORY_SEPARATOR === '\\') { + $replacements['/'] = '\\\\'; + } + + $pattern = '`'.strtr($pattern, $replacements).'`i'; + $matched = preg_match($pattern, $this->path); + + if ($matched === 0) { + if ($excluding === false && $included === null) { + // This file path is not being included. + $included = false; + } + + continue; + } + + if ($excluding === true) { + // This file path is being excluded. + $this->ignoredCodes[$checkCode] = true; + return false; + } + + // This file path is being included. + $included = true; + break; + }//end foreach + }//end foreach + }//end if + + if ($included === false) { + // There were include rules set, but this file + // path didn't match any of them. + return false; + } + + $messageCount++; + if ($fixable === true) { + $this->fixableCount++; + } + + if ($this->configCache['recordErrors'] === false + && $includeAll === false + ) { + return true; + } + + // See if there is a custom error message format to use. + // But don't do this if we are replaying errors because replayed + // errors have already used the custom format and have had their + // data replaced. + if ($this->replayingErrors === false + && isset($this->ruleset->ruleset[$sniffCode]['message']) === true + ) { + $message = $this->ruleset->ruleset[$sniffCode]['message']; + } + + if (empty($data) === false) { + $message = vsprintf($message, $data); + } + + if (isset($messages[$line]) === false) { + $messages[$line] = []; + } + + if (isset($messages[$line][$column]) === false) { + $messages[$line][$column] = []; + } + + $messages[$line][$column][] = [ + 'message' => $message, + 'source' => $sniffCode, + 'listener' => $this->activeListener, + 'severity' => $severity, + 'fixable' => $fixable, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1 + && $this->fixer->enabled === true + && $fixable === true + ) { + @ob_end_clean(); + echo "\tE: [Line $line] $message ($sniffCode)".PHP_EOL; + ob_start(); + } + + return true; + + }//end addMessage() + + + /** + * Record a metric about the file being examined. + * + * @param int $stackPtr The stack position where the metric was recorded. + * @param string $metric The name of the metric being recorded. + * @param string $value The value of the metric being recorded. + * + * @return boolean + */ + public function recordMetric($stackPtr, $metric, $value) + { + if (isset($this->metrics[$metric]) === false) { + $this->metrics[$metric] = ['values' => [$value => 1]]; + $this->metricTokens[$metric][$stackPtr] = true; + } else if (isset($this->metricTokens[$metric][$stackPtr]) === false) { + $this->metricTokens[$metric][$stackPtr] = true; + if (isset($this->metrics[$metric]['values'][$value]) === false) { + $this->metrics[$metric]['values'][$value] = 1; + } else { + $this->metrics[$metric]['values'][$value]++; + } + } + + return true; + + }//end recordMetric() + + + /** + * Returns the number of errors raised. + * + * @return int + */ + public function getErrorCount() + { + return $this->errorCount; + + }//end getErrorCount() + + + /** + * Returns the number of warnings raised. + * + * @return int + */ + public function getWarningCount() + { + return $this->warningCount; + + }//end getWarningCount() + + + /** + * Returns the number of fixable errors/warnings raised. + * + * @return int + */ + public function getFixableCount() + { + return $this->fixableCount; + + }//end getFixableCount() + + + /** + * Returns the number of fixed errors/warnings. + * + * @return int + */ + public function getFixedCount() + { + return $this->fixedCount; + + }//end getFixedCount() + + + /** + * Returns the list of ignored lines. + * + * @return array + */ + public function getIgnoredLines() + { + return $this->tokenizer->ignoredLines; + + }//end getIgnoredLines() + + + /** + * Returns the errors raised from processing this file. + * + * @return array + */ + public function getErrors() + { + return $this->errors; + + }//end getErrors() + + + /** + * Returns the warnings raised from processing this file. + * + * @return array + */ + public function getWarnings() + { + return $this->warnings; + + }//end getWarnings() + + + /** + * Returns the metrics found while processing this file. + * + * @return array + */ + public function getMetrics() + { + return $this->metrics; + + }//end getMetrics() + + + /** + * Returns the absolute filename of this file. + * + * @return string + */ + public function getFilename() + { + return $this->path; + + }//end getFilename() + + + /** + * Returns the declaration name for classes, interfaces, traits, enums, and functions. + * + * @param int $stackPtr The position of the declaration token which + * declared the class, interface, trait, or function. + * + * @return string|null The name of the class, interface, trait, or function; + * or NULL if the function or class is anonymous. + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified token is not of type + * T_FUNCTION, T_CLASS, T_ANON_CLASS, + * T_CLOSURE, T_TRAIT, T_ENUM, or T_INTERFACE. + */ + public function getDeclarationName($stackPtr) + { + $tokenCode = $this->tokens[$stackPtr]['code']; + + if ($tokenCode === T_ANON_CLASS || $tokenCode === T_CLOSURE) { + return null; + } + + if ($tokenCode !== T_FUNCTION + && $tokenCode !== T_CLASS + && $tokenCode !== T_INTERFACE + && $tokenCode !== T_TRAIT + && $tokenCode !== T_ENUM + ) { + throw new RuntimeException('Token type "'.$this->tokens[$stackPtr]['type'].'" is not T_FUNCTION, T_CLASS, T_INTERFACE, T_TRAIT or T_ENUM'); + } + + if ($tokenCode === T_FUNCTION + && strtolower($this->tokens[$stackPtr]['content']) !== 'function' + ) { + // This is a function declared without the "function" keyword. + // So this token is the function name. + return $this->tokens[$stackPtr]['content']; + } + + $content = null; + for ($i = $stackPtr; $i < $this->numTokens; $i++) { + if ($this->tokens[$i]['code'] === T_STRING) { + $content = $this->tokens[$i]['content']; + break; + } + } + + return $content; + + }//end getDeclarationName() + + + /** + * Returns the method parameters for the specified function token. + * + * Also supports passing in a USE token for a closure use group. + * + * Each parameter is in the following format: + * + * + * 0 => array( + * 'name' => '$var', // The variable name. + * 'token' => integer, // The stack pointer to the variable name. + * 'content' => string, // The full content of the variable definition. + * 'has_attributes' => boolean, // Does the parameter have one or more attributes attached ? + * 'pass_by_reference' => boolean, // Is the variable passed by reference? + * 'reference_token' => integer, // The stack pointer to the reference operator + * // or FALSE if the param is not passed by reference. + * 'variable_length' => boolean, // Is the param of variable length through use of `...` ? + * 'variadic_token' => integer, // The stack pointer to the ... operator + * // or FALSE if the param is not variable length. + * 'type_hint' => string, // The type hint for the variable. + * 'type_hint_token' => integer, // The stack pointer to the start of the type hint + * // or FALSE if there is no type hint. + * 'type_hint_end_token' => integer, // The stack pointer to the end of the type hint + * // or FALSE if there is no type hint. + * 'nullable_type' => boolean, // TRUE if the type is preceded by the nullability + * // operator. + * 'comma_token' => integer, // The stack pointer to the comma after the param + * // or FALSE if this is the last param. + * ) + * + * + * Parameters with default values have additional array indexes of: + * 'default' => string, // The full content of the default value. + * 'default_token' => integer, // The stack pointer to the start of the default value. + * 'default_equal_token' => integer, // The stack pointer to the equals sign. + * + * Parameters declared using PHP 8 constructor property promotion, have these additional array indexes: + * 'property_visibility' => string, // The property visibility as declared. + * 'visibility_token' => integer, // The stack pointer to the visibility modifier token. + * 'property_readonly' => bool, // TRUE if the readonly keyword was found. + * 'readonly_token' => integer, // The stack pointer to the readonly modifier token. + * + * @param int $stackPtr The position in the stack of the function token + * to acquire the parameters for. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified $stackPtr is not of + * type T_FUNCTION, T_CLOSURE, T_USE, + * or T_FN. + */ + public function getMethodParameters($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_FUNCTION + && $this->tokens[$stackPtr]['code'] !== T_CLOSURE + && $this->tokens[$stackPtr]['code'] !== T_USE + && $this->tokens[$stackPtr]['code'] !== T_FN + ) { + throw new RuntimeException('$stackPtr must be of type T_FUNCTION or T_CLOSURE or T_USE or T_FN'); + } + + if ($this->tokens[$stackPtr]['code'] === T_USE) { + $opener = $this->findNext(T_OPEN_PARENTHESIS, ($stackPtr + 1)); + if ($opener === false || isset($this->tokens[$opener]['parenthesis_owner']) === true) { + throw new RuntimeException('$stackPtr was not a valid T_USE'); + } + } else { + if (isset($this->tokens[$stackPtr]['parenthesis_opener']) === false) { + // Live coding or syntax error, so no params to find. + return []; + } + + $opener = $this->tokens[$stackPtr]['parenthesis_opener']; + } + + if (isset($this->tokens[$opener]['parenthesis_closer']) === false) { + // Live coding or syntax error, so no params to find. + return []; + } + + $closer = $this->tokens[$opener]['parenthesis_closer']; + + $vars = []; + $currVar = null; + $paramStart = ($opener + 1); + $defaultStart = null; + $equalToken = null; + $paramCount = 0; + $hasAttributes = false; + $passByReference = false; + $referenceToken = false; + $variableLength = false; + $variadicToken = false; + $typeHint = ''; + $typeHintToken = false; + $typeHintEndToken = false; + $nullableType = false; + $visibilityToken = null; + $readonlyToken = null; + + for ($i = $paramStart; $i <= $closer; $i++) { + // Check to see if this token has a parenthesis or bracket opener. If it does + // it's likely to be an array which might have arguments in it. This + // could cause problems in our parsing below, so lets just skip to the + // end of it. + if (isset($this->tokens[$i]['parenthesis_opener']) === true) { + // Don't do this if it's the close parenthesis for the method. + if ($i !== $this->tokens[$i]['parenthesis_closer']) { + $i = $this->tokens[$i]['parenthesis_closer']; + continue; + } + } + + if (isset($this->tokens[$i]['bracket_opener']) === true) { + if ($i !== $this->tokens[$i]['bracket_closer']) { + $i = $this->tokens[$i]['bracket_closer']; + continue; + } + } + + switch ($this->tokens[$i]['code']) { + case T_ATTRIBUTE: + $hasAttributes = true; + + // Skip to the end of the attribute. + $i = $this->tokens[$i]['attribute_closer']; + break; + case T_BITWISE_AND: + if ($defaultStart === null) { + $passByReference = true; + $referenceToken = $i; + } + break; + case T_VARIABLE: + $currVar = $i; + break; + case T_ELLIPSIS: + $variableLength = true; + $variadicToken = $i; + break; + case T_CALLABLE: + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + break; + case T_SELF: + case T_PARENT: + case T_STATIC: + // Self and parent are valid, static invalid, but was probably intended as type hint. + if (isset($defaultStart) === false) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + } + break; + case T_STRING: + // This is a string, so it may be a type hint, but it could + // also be a constant used as a default value. + $prevComma = false; + for ($t = $i; $t >= $opener; $t--) { + if ($this->tokens[$t]['code'] === T_COMMA) { + $prevComma = $t; + break; + } + } + + if ($prevComma !== false) { + $nextEquals = false; + for ($t = $prevComma; $t < $i; $t++) { + if ($this->tokens[$t]['code'] === T_EQUAL) { + $nextEquals = $t; + break; + } + } + + if ($nextEquals !== false) { + break; + } + } + + if ($defaultStart === null) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + } + break; + case T_NAMESPACE: + case T_NS_SEPARATOR: + case T_TYPE_UNION: + case T_TYPE_INTERSECTION: + case T_FALSE: + case T_NULL: + // Part of a type hint or default value. + if ($defaultStart === null) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + } + break; + case T_NULLABLE: + if ($defaultStart === null) { + $nullableType = true; + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + } + break; + case T_PUBLIC: + case T_PROTECTED: + case T_PRIVATE: + if ($defaultStart === null) { + $visibilityToken = $i; + } + break; + case T_READONLY: + if ($defaultStart === null) { + $readonlyToken = $i; + } + break; + case T_CLOSE_PARENTHESIS: + case T_COMMA: + // If it's null, then there must be no parameters for this + // method. + if ($currVar === null) { + continue 2; + } + + $vars[$paramCount] = []; + $vars[$paramCount]['token'] = $currVar; + $vars[$paramCount]['name'] = $this->tokens[$currVar]['content']; + $vars[$paramCount]['content'] = trim($this->getTokensAsString($paramStart, ($i - $paramStart))); + + if ($defaultStart !== null) { + $vars[$paramCount]['default'] = trim($this->getTokensAsString($defaultStart, ($i - $defaultStart))); + $vars[$paramCount]['default_token'] = $defaultStart; + $vars[$paramCount]['default_equal_token'] = $equalToken; + } + + $vars[$paramCount]['has_attributes'] = $hasAttributes; + $vars[$paramCount]['pass_by_reference'] = $passByReference; + $vars[$paramCount]['reference_token'] = $referenceToken; + $vars[$paramCount]['variable_length'] = $variableLength; + $vars[$paramCount]['variadic_token'] = $variadicToken; + $vars[$paramCount]['type_hint'] = $typeHint; + $vars[$paramCount]['type_hint_token'] = $typeHintToken; + $vars[$paramCount]['type_hint_end_token'] = $typeHintEndToken; + $vars[$paramCount]['nullable_type'] = $nullableType; + + if ($visibilityToken !== null) { + $vars[$paramCount]['property_visibility'] = $this->tokens[$visibilityToken]['content']; + $vars[$paramCount]['visibility_token'] = $visibilityToken; + $vars[$paramCount]['property_readonly'] = false; + } + + if ($readonlyToken !== null) { + $vars[$paramCount]['property_readonly'] = true; + $vars[$paramCount]['readonly_token'] = $readonlyToken; + } + + if ($this->tokens[$i]['code'] === T_COMMA) { + $vars[$paramCount]['comma_token'] = $i; + } else { + $vars[$paramCount]['comma_token'] = false; + } + + // Reset the vars, as we are about to process the next parameter. + $currVar = null; + $paramStart = ($i + 1); + $defaultStart = null; + $equalToken = null; + $hasAttributes = false; + $passByReference = false; + $referenceToken = false; + $variableLength = false; + $variadicToken = false; + $typeHint = ''; + $typeHintToken = false; + $typeHintEndToken = false; + $nullableType = false; + $visibilityToken = null; + $readonlyToken = null; + + $paramCount++; + break; + case T_EQUAL: + $defaultStart = $this->findNext(Util\Tokens::$emptyTokens, ($i + 1), null, true); + $equalToken = $i; + break; + }//end switch + }//end for + + return $vars; + + }//end getMethodParameters() + + + /** + * Returns the visibility and implementation properties of a method. + * + * The format of the return value is: + * + * array( + * 'scope' => 'public', // Public, private, or protected + * 'scope_specified' => true, // TRUE if the scope keyword was found. + * 'return_type' => '', // The return type of the method. + * 'return_type_token' => integer, // The stack pointer to the start of the return type + * // or FALSE if there is no return type. + * 'return_type_end_token' => integer, // The stack pointer to the end of the return type + * // or FALSE if there is no return type. + * 'nullable_return_type' => false, // TRUE if the return type is preceded by the + * // nullability operator. + * 'is_abstract' => false, // TRUE if the abstract keyword was found. + * 'is_final' => false, // TRUE if the final keyword was found. + * 'is_static' => false, // TRUE if the static keyword was found. + * 'has_body' => false, // TRUE if the method has a body + * ); + * + * + * @param int $stackPtr The position in the stack of the function token to + * acquire the properties for. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified position is not a + * T_FUNCTION, T_CLOSURE, or T_FN token. + */ + public function getMethodProperties($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_FUNCTION + && $this->tokens[$stackPtr]['code'] !== T_CLOSURE + && $this->tokens[$stackPtr]['code'] !== T_FN + ) { + throw new RuntimeException('$stackPtr must be of type T_FUNCTION or T_CLOSURE or T_FN'); + } + + if ($this->tokens[$stackPtr]['code'] === T_FUNCTION) { + $valid = [ + T_PUBLIC => T_PUBLIC, + T_PRIVATE => T_PRIVATE, + T_PROTECTED => T_PROTECTED, + T_STATIC => T_STATIC, + T_FINAL => T_FINAL, + T_ABSTRACT => T_ABSTRACT, + T_WHITESPACE => T_WHITESPACE, + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + ]; + } else { + $valid = [ + T_STATIC => T_STATIC, + T_WHITESPACE => T_WHITESPACE, + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + ]; + } + + $scope = 'public'; + $scopeSpecified = false; + $isAbstract = false; + $isFinal = false; + $isStatic = false; + + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if (isset($valid[$this->tokens[$i]['code']]) === false) { + break; + } + + switch ($this->tokens[$i]['code']) { + case T_PUBLIC: + $scope = 'public'; + $scopeSpecified = true; + break; + case T_PRIVATE: + $scope = 'private'; + $scopeSpecified = true; + break; + case T_PROTECTED: + $scope = 'protected'; + $scopeSpecified = true; + break; + case T_ABSTRACT: + $isAbstract = true; + break; + case T_FINAL: + $isFinal = true; + break; + case T_STATIC: + $isStatic = true; + break; + }//end switch + }//end for + + $returnType = ''; + $returnTypeToken = false; + $returnTypeEndToken = false; + $nullableReturnType = false; + $hasBody = true; + + if (isset($this->tokens[$stackPtr]['parenthesis_closer']) === true) { + $scopeOpener = null; + if (isset($this->tokens[$stackPtr]['scope_opener']) === true) { + $scopeOpener = $this->tokens[$stackPtr]['scope_opener']; + } + + $valid = [ + T_STRING => T_STRING, + T_CALLABLE => T_CALLABLE, + T_SELF => T_SELF, + T_PARENT => T_PARENT, + T_STATIC => T_STATIC, + T_FALSE => T_FALSE, + T_NULL => T_NULL, + T_NAMESPACE => T_NAMESPACE, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_TYPE_UNION => T_TYPE_UNION, + T_TYPE_INTERSECTION => T_TYPE_INTERSECTION, + ]; + + for ($i = $this->tokens[$stackPtr]['parenthesis_closer']; $i < $this->numTokens; $i++) { + if (($scopeOpener === null && $this->tokens[$i]['code'] === T_SEMICOLON) + || ($scopeOpener !== null && $i === $scopeOpener) + ) { + // End of function definition. + break; + } + + if ($this->tokens[$i]['code'] === T_NULLABLE) { + $nullableReturnType = true; + } + + if (isset($valid[$this->tokens[$i]['code']]) === true) { + if ($returnTypeToken === false) { + $returnTypeToken = $i; + } + + $returnType .= $this->tokens[$i]['content']; + $returnTypeEndToken = $i; + } + }//end for + + if ($this->tokens[$stackPtr]['code'] === T_FN) { + $bodyToken = T_FN_ARROW; + } else { + $bodyToken = T_OPEN_CURLY_BRACKET; + } + + $end = $this->findNext([$bodyToken, T_SEMICOLON], $this->tokens[$stackPtr]['parenthesis_closer']); + $hasBody = $this->tokens[$end]['code'] === $bodyToken; + }//end if + + if ($returnType !== '' && $nullableReturnType === true) { + $returnType = '?'.$returnType; + } + + return [ + 'scope' => $scope, + 'scope_specified' => $scopeSpecified, + 'return_type' => $returnType, + 'return_type_token' => $returnTypeToken, + 'return_type_end_token' => $returnTypeEndToken, + 'nullable_return_type' => $nullableReturnType, + 'is_abstract' => $isAbstract, + 'is_final' => $isFinal, + 'is_static' => $isStatic, + 'has_body' => $hasBody, + ]; + + }//end getMethodProperties() + + + /** + * Returns the visibility and implementation properties of a class member var. + * + * The format of the return value is: + * + * + * array( + * 'scope' => string, // Public, private, or protected. + * 'scope_specified' => boolean, // TRUE if the scope was explicitly specified. + * 'is_static' => boolean, // TRUE if the static keyword was found. + * 'is_readonly' => boolean, // TRUE if the readonly keyword was found. + * 'type' => string, // The type of the var (empty if no type specified). + * 'type_token' => integer, // The stack pointer to the start of the type + * // or FALSE if there is no type. + * 'type_end_token' => integer, // The stack pointer to the end of the type + * // or FALSE if there is no type. + * 'nullable_type' => boolean, // TRUE if the type is preceded by the nullability + * // operator. + * ); + * + * + * @param int $stackPtr The position in the stack of the T_VARIABLE token to + * acquire the properties for. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified position is not a + * T_VARIABLE token, or if the position is not + * a class member variable. + */ + public function getMemberProperties($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_VARIABLE) { + throw new RuntimeException('$stackPtr must be of type T_VARIABLE'); + } + + $conditions = array_keys($this->tokens[$stackPtr]['conditions']); + $ptr = array_pop($conditions); + if (isset($this->tokens[$ptr]) === false + || ($this->tokens[$ptr]['code'] !== T_CLASS + && $this->tokens[$ptr]['code'] !== T_ANON_CLASS + && $this->tokens[$ptr]['code'] !== T_TRAIT) + ) { + if (isset($this->tokens[$ptr]) === true + && ($this->tokens[$ptr]['code'] === T_INTERFACE + || $this->tokens[$ptr]['code'] === T_ENUM) + ) { + // T_VARIABLEs in interfaces/enums can actually be method arguments + // but they wont be seen as being inside the method because there + // are no scope openers and closers for abstract methods. If it is in + // parentheses, we can be pretty sure it is a method argument. + if (isset($this->tokens[$stackPtr]['nested_parenthesis']) === false + || empty($this->tokens[$stackPtr]['nested_parenthesis']) === true + ) { + $error = 'Possible parse error: %ss may not include member vars'; + $code = sprintf('Internal.ParseError.%sHasMemberVar', ucfirst($this->tokens[$ptr]['content'])); + $data = [strtolower($this->tokens[$ptr]['content'])]; + $this->addWarning($error, $stackPtr, $code, $data); + return []; + } + } else { + throw new RuntimeException('$stackPtr is not a class member var'); + } + }//end if + + // Make sure it's not a method parameter. + if (empty($this->tokens[$stackPtr]['nested_parenthesis']) === false) { + $parenthesis = array_keys($this->tokens[$stackPtr]['nested_parenthesis']); + $deepestOpen = array_pop($parenthesis); + if ($deepestOpen > $ptr + && isset($this->tokens[$deepestOpen]['parenthesis_owner']) === true + && $this->tokens[$this->tokens[$deepestOpen]['parenthesis_owner']]['code'] === T_FUNCTION + ) { + throw new RuntimeException('$stackPtr is not a class member var'); + } + } + + $valid = [ + T_PUBLIC => T_PUBLIC, + T_PRIVATE => T_PRIVATE, + T_PROTECTED => T_PROTECTED, + T_STATIC => T_STATIC, + T_VAR => T_VAR, + T_READONLY => T_READONLY, + ]; + + $valid += Util\Tokens::$emptyTokens; + + $scope = 'public'; + $scopeSpecified = false; + $isStatic = false; + $isReadonly = false; + + $startOfStatement = $this->findPrevious( + [ + T_SEMICOLON, + T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET, + T_ATTRIBUTE_END, + ], + ($stackPtr - 1) + ); + + for ($i = ($startOfStatement + 1); $i < $stackPtr; $i++) { + if (isset($valid[$this->tokens[$i]['code']]) === false) { + break; + } + + switch ($this->tokens[$i]['code']) { + case T_PUBLIC: + $scope = 'public'; + $scopeSpecified = true; + break; + case T_PRIVATE: + $scope = 'private'; + $scopeSpecified = true; + break; + case T_PROTECTED: + $scope = 'protected'; + $scopeSpecified = true; + break; + case T_STATIC: + $isStatic = true; + break; + case T_READONLY: + $isReadonly = true; + break; + } + }//end for + + $type = ''; + $typeToken = false; + $typeEndToken = false; + $nullableType = false; + + if ($i < $stackPtr) { + // We've found a type. + $valid = [ + T_STRING => T_STRING, + T_CALLABLE => T_CALLABLE, + T_SELF => T_SELF, + T_PARENT => T_PARENT, + T_FALSE => T_FALSE, + T_NULL => T_NULL, + T_NAMESPACE => T_NAMESPACE, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_TYPE_UNION => T_TYPE_UNION, + T_TYPE_INTERSECTION => T_TYPE_INTERSECTION, + ]; + + for ($i; $i < $stackPtr; $i++) { + if ($this->tokens[$i]['code'] === T_VARIABLE) { + // Hit another variable in a group definition. + break; + } + + if ($this->tokens[$i]['code'] === T_NULLABLE) { + $nullableType = true; + } + + if (isset($valid[$this->tokens[$i]['code']]) === true) { + $typeEndToken = $i; + if ($typeToken === false) { + $typeToken = $i; + } + + $type .= $this->tokens[$i]['content']; + } + } + + if ($type !== '' && $nullableType === true) { + $type = '?'.$type; + } + }//end if + + return [ + 'scope' => $scope, + 'scope_specified' => $scopeSpecified, + 'is_static' => $isStatic, + 'is_readonly' => $isReadonly, + 'type' => $type, + 'type_token' => $typeToken, + 'type_end_token' => $typeEndToken, + 'nullable_type' => $nullableType, + ]; + + }//end getMemberProperties() + + + /** + * Returns the visibility and implementation properties of a class. + * + * The format of the return value is: + * + * array( + * 'is_abstract' => false, // true if the abstract keyword was found. + * 'is_final' => false, // true if the final keyword was found. + * ); + * + * + * @param int $stackPtr The position in the stack of the T_CLASS token to + * acquire the properties for. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified position is not a + * T_CLASS token. + */ + public function getClassProperties($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_CLASS) { + throw new RuntimeException('$stackPtr must be of type T_CLASS'); + } + + $valid = [ + T_FINAL => T_FINAL, + T_ABSTRACT => T_ABSTRACT, + T_WHITESPACE => T_WHITESPACE, + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + ]; + + $isAbstract = false; + $isFinal = false; + + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if (isset($valid[$this->tokens[$i]['code']]) === false) { + break; + } + + switch ($this->tokens[$i]['code']) { + case T_ABSTRACT: + $isAbstract = true; + break; + + case T_FINAL: + $isFinal = true; + break; + } + }//end for + + return [ + 'is_abstract' => $isAbstract, + 'is_final' => $isFinal, + ]; + + }//end getClassProperties() + + + /** + * Determine if the passed token is a reference operator. + * + * Returns true if the specified token position represents a reference. + * Returns false if the token represents a bitwise operator. + * + * @param int $stackPtr The position of the T_BITWISE_AND token. + * + * @return boolean + */ + public function isReference($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_BITWISE_AND) { + return false; + } + + $tokenBefore = $this->findPrevious( + Util\Tokens::$emptyTokens, + ($stackPtr - 1), + null, + true + ); + + if ($this->tokens[$tokenBefore]['code'] === T_FUNCTION + || $this->tokens[$tokenBefore]['code'] === T_CLOSURE + || $this->tokens[$tokenBefore]['code'] === T_FN + ) { + // Function returns a reference. + return true; + } + + if ($this->tokens[$tokenBefore]['code'] === T_DOUBLE_ARROW) { + // Inside a foreach loop or array assignment, this is a reference. + return true; + } + + if ($this->tokens[$tokenBefore]['code'] === T_AS) { + // Inside a foreach loop, this is a reference. + return true; + } + + if (isset(Util\Tokens::$assignmentTokens[$this->tokens[$tokenBefore]['code']]) === true) { + // This is directly after an assignment. It's a reference. Even if + // it is part of an operation, the other tests will handle it. + return true; + } + + $tokenAfter = $this->findNext( + Util\Tokens::$emptyTokens, + ($stackPtr + 1), + null, + true + ); + + if ($this->tokens[$tokenAfter]['code'] === T_NEW) { + return true; + } + + if (isset($this->tokens[$stackPtr]['nested_parenthesis']) === true) { + $brackets = $this->tokens[$stackPtr]['nested_parenthesis']; + $lastBracket = array_pop($brackets); + if (isset($this->tokens[$lastBracket]['parenthesis_owner']) === true) { + $owner = $this->tokens[$this->tokens[$lastBracket]['parenthesis_owner']]; + if ($owner['code'] === T_FUNCTION + || $owner['code'] === T_CLOSURE + || $owner['code'] === T_FN + ) { + $params = $this->getMethodParameters($this->tokens[$lastBracket]['parenthesis_owner']); + foreach ($params as $param) { + if ($param['reference_token'] === $stackPtr) { + // Function parameter declared to be passed by reference. + return true; + } + } + }//end if + } else { + $prev = false; + for ($t = ($this->tokens[$lastBracket]['parenthesis_opener'] - 1); $t >= 0; $t--) { + if ($this->tokens[$t]['code'] !== T_WHITESPACE) { + $prev = $t; + break; + } + } + + if ($prev !== false && $this->tokens[$prev]['code'] === T_USE) { + // Closure use by reference. + return true; + } + }//end if + }//end if + + // Pass by reference in function calls and assign by reference in arrays. + if ($this->tokens[$tokenBefore]['code'] === T_OPEN_PARENTHESIS + || $this->tokens[$tokenBefore]['code'] === T_COMMA + || $this->tokens[$tokenBefore]['code'] === T_OPEN_SHORT_ARRAY + ) { + if ($this->tokens[$tokenAfter]['code'] === T_VARIABLE) { + return true; + } else { + $skip = Util\Tokens::$emptyTokens; + $skip[] = T_NS_SEPARATOR; + $skip[] = T_SELF; + $skip[] = T_PARENT; + $skip[] = T_STATIC; + $skip[] = T_STRING; + $skip[] = T_NAMESPACE; + $skip[] = T_DOUBLE_COLON; + + $nextSignificantAfter = $this->findNext( + $skip, + ($stackPtr + 1), + null, + true + ); + if ($this->tokens[$nextSignificantAfter]['code'] === T_VARIABLE) { + return true; + } + }//end if + }//end if + + return false; + + }//end isReference() + + + /** + * Returns the content of the tokens from the specified start position in + * the token stack for the specified length. + * + * @param int $start The position to start from in the token stack. + * @param int $length The length of tokens to traverse from the start pos. + * @param bool $origContent Whether the original content or the tab replaced + * content should be used. + * + * @return string The token contents. + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified position does not exist. + */ + public function getTokensAsString($start, $length, $origContent=false) + { + if (is_int($start) === false || isset($this->tokens[$start]) === false) { + throw new RuntimeException('The $start position for getTokensAsString() must exist in the token stack'); + } + + if (is_int($length) === false || $length <= 0) { + return ''; + } + + $str = ''; + $end = ($start + $length); + if ($end > $this->numTokens) { + $end = $this->numTokens; + } + + for ($i = $start; $i < $end; $i++) { + // If tabs are being converted to spaces by the tokeniser, the + // original content should be used instead of the converted content. + if ($origContent === true && isset($this->tokens[$i]['orig_content']) === true) { + $str .= $this->tokens[$i]['orig_content']; + } else { + $str .= $this->tokens[$i]['content']; + } + } + + return $str; + + }//end getTokensAsString() + + + /** + * Returns the position of the previous specified token(s). + * + * If a value is specified, the previous token of the specified type(s) + * containing the specified value will be returned. + * + * Returns false if no token can be found. + * + * @param int|string|array $types The type(s) of tokens to search for. + * @param int $start The position to start searching from in the + * token stack. + * @param int|null $end The end position to fail if no token is found. + * if not specified or null, end will default to + * the start of the token stack. + * @param bool $exclude If true, find the previous token that is NOT of + * the types specified in $types. + * @param string|null $value The value that the token(s) must be equal to. + * If value is omitted, tokens with any value will + * be returned. + * @param bool $local If true, tokens outside the current statement + * will not be checked. IE. checking will stop + * at the previous semi-colon found. + * + * @return int|false + * @see findNext() + */ + public function findPrevious( + $types, + $start, + $end=null, + $exclude=false, + $value=null, + $local=false + ) { + $types = (array) $types; + + if ($end === null) { + $end = 0; + } + + for ($i = $start; $i >= $end; $i--) { + $found = (bool) $exclude; + foreach ($types as $type) { + if ($this->tokens[$i]['code'] === $type) { + $found = !$exclude; + break; + } + } + + if ($found === true) { + if ($value === null) { + return $i; + } else if ($this->tokens[$i]['content'] === $value) { + return $i; + } + } + + if ($local === true) { + if (isset($this->tokens[$i]['scope_opener']) === true + && $i === $this->tokens[$i]['scope_closer'] + ) { + $i = $this->tokens[$i]['scope_opener']; + } else if (isset($this->tokens[$i]['bracket_opener']) === true + && $i === $this->tokens[$i]['bracket_closer'] + ) { + $i = $this->tokens[$i]['bracket_opener']; + } else if (isset($this->tokens[$i]['parenthesis_opener']) === true + && $i === $this->tokens[$i]['parenthesis_closer'] + ) { + $i = $this->tokens[$i]['parenthesis_opener']; + } else if ($this->tokens[$i]['code'] === T_SEMICOLON) { + break; + } + } + }//end for + + return false; + + }//end findPrevious() + + + /** + * Returns the position of the next specified token(s). + * + * If a value is specified, the next token of the specified type(s) + * containing the specified value will be returned. + * + * Returns false if no token can be found. + * + * @param int|string|array $types The type(s) of tokens to search for. + * @param int $start The position to start searching from in the + * token stack. + * @param int|null $end The end position to fail if no token is found. + * if not specified or null, end will default to + * the end of the token stack. + * @param bool $exclude If true, find the next token that is NOT of + * a type specified in $types. + * @param string|null $value The value that the token(s) must be equal to. + * If value is omitted, tokens with any value will + * be returned. + * @param bool $local If true, tokens outside the current statement + * will not be checked. i.e., checking will stop + * at the next semi-colon found. + * + * @return int|false + * @see findPrevious() + */ + public function findNext( + $types, + $start, + $end=null, + $exclude=false, + $value=null, + $local=false + ) { + $types = (array) $types; + + if ($end === null || $end > $this->numTokens) { + $end = $this->numTokens; + } + + for ($i = $start; $i < $end; $i++) { + $found = (bool) $exclude; + foreach ($types as $type) { + if ($this->tokens[$i]['code'] === $type) { + $found = !$exclude; + break; + } + } + + if ($found === true) { + if ($value === null) { + return $i; + } else if ($this->tokens[$i]['content'] === $value) { + return $i; + } + } + + if ($local === true && $this->tokens[$i]['code'] === T_SEMICOLON) { + break; + } + }//end for + + return false; + + }//end findNext() + + + /** + * Returns the position of the first non-whitespace token in a statement. + * + * @param int $start The position to start searching from in the token stack. + * @param int|string|array $ignore Token types that should not be considered stop points. + * + * @return int + */ + public function findStartOfStatement($start, $ignore=null) + { + $startTokens = Util\Tokens::$blockOpeners; + $startTokens[T_OPEN_SHORT_ARRAY] = true; + $startTokens[T_OPEN_TAG] = true; + $startTokens[T_OPEN_TAG_WITH_ECHO] = true; + + $endTokens = [ + T_CLOSE_TAG => true, + T_COLON => true, + T_COMMA => true, + T_DOUBLE_ARROW => true, + T_MATCH_ARROW => true, + T_SEMICOLON => true, + ]; + + if ($ignore !== null) { + $ignore = (array) $ignore; + foreach ($ignore as $code) { + if (isset($startTokens[$code]) === true) { + unset($startTokens[$code]); + } + + if (isset($endTokens[$code]) === true) { + unset($endTokens[$code]); + } + } + } + + // If the start token is inside the case part of a match expression, + // find the start of the condition. If it's in the statement part, find + // the token that comes after the match arrow. + $matchExpression = $this->getCondition($start, T_MATCH); + if ($matchExpression !== false) { + for ($prevMatch = $start; $prevMatch > $this->tokens[$matchExpression]['scope_opener']; $prevMatch--) { + if ($prevMatch !== $start + && ($this->tokens[$prevMatch]['code'] === T_MATCH_ARROW + || $this->tokens[$prevMatch]['code'] === T_COMMA) + ) { + break; + } + + // Skip nested statements. + if (isset($this->tokens[$prevMatch]['bracket_opener']) === true + && $prevMatch === $this->tokens[$prevMatch]['bracket_closer'] + ) { + $prevMatch = $this->tokens[$prevMatch]['bracket_opener']; + } else if (isset($this->tokens[$prevMatch]['parenthesis_opener']) === true + && $prevMatch === $this->tokens[$prevMatch]['parenthesis_closer'] + ) { + $prevMatch = $this->tokens[$prevMatch]['parenthesis_opener']; + } + } + + if ($prevMatch <= $this->tokens[$matchExpression]['scope_opener']) { + // We're before the arrow in the first case. + $next = $this->findNext(Util\Tokens::$emptyTokens, ($this->tokens[$matchExpression]['scope_opener'] + 1), null, true); + if ($next === false) { + return $start; + } + + return $next; + } + + if ($this->tokens[$prevMatch]['code'] === T_COMMA) { + // We're before the arrow, but not in the first case. + $prevMatchArrow = $this->findPrevious(T_MATCH_ARROW, ($prevMatch - 1), $this->tokens[$matchExpression]['scope_opener']); + if ($prevMatchArrow === false) { + // We're before the arrow in the first case. + $next = $this->findNext(Util\Tokens::$emptyTokens, ($this->tokens[$matchExpression]['scope_opener'] + 1), null, true); + return $next; + } + + $end = $this->findEndOfStatement($prevMatchArrow); + $next = $this->findNext(Util\Tokens::$emptyTokens, ($end + 1), null, true); + return $next; + } + }//end if + + $lastNotEmpty = $start; + + // If we are starting at a token that ends a scope block, skip to + // the start and continue from there. + // If we are starting at a token that ends a statement, skip this + // token so we find the true start of the statement. + while (isset($endTokens[$this->tokens[$start]['code']]) === true + || (isset($this->tokens[$start]['scope_condition']) === true + && $start === $this->tokens[$start]['scope_closer']) + ) { + if (isset($this->tokens[$start]['scope_condition']) === true) { + $start = $this->tokens[$start]['scope_condition']; + } else { + $start--; + } + } + + for ($i = $start; $i >= 0; $i--) { + if (isset($startTokens[$this->tokens[$i]['code']]) === true + || isset($endTokens[$this->tokens[$i]['code']]) === true + ) { + // Found the end of the previous statement. + return $lastNotEmpty; + } + + if (isset($this->tokens[$i]['scope_opener']) === true + && $i === $this->tokens[$i]['scope_closer'] + && $this->tokens[$i]['code'] !== T_CLOSE_PARENTHESIS + && $this->tokens[$i]['code'] !== T_END_NOWDOC + && $this->tokens[$i]['code'] !== T_END_HEREDOC + && $this->tokens[$i]['code'] !== T_BREAK + && $this->tokens[$i]['code'] !== T_RETURN + && $this->tokens[$i]['code'] !== T_CONTINUE + && $this->tokens[$i]['code'] !== T_THROW + && $this->tokens[$i]['code'] !== T_EXIT + ) { + // Found the end of the previous scope block. + return $lastNotEmpty; + } + + // Skip nested statements. + if (isset($this->tokens[$i]['bracket_opener']) === true + && $i === $this->tokens[$i]['bracket_closer'] + ) { + $i = $this->tokens[$i]['bracket_opener']; + } else if (isset($this->tokens[$i]['parenthesis_opener']) === true + && $i === $this->tokens[$i]['parenthesis_closer'] + ) { + $i = $this->tokens[$i]['parenthesis_opener']; + } else if ($this->tokens[$i]['code'] === T_CLOSE_USE_GROUP) { + $start = $this->findPrevious(T_OPEN_USE_GROUP, ($i - 1)); + if ($start !== false) { + $i = $start; + } + }//end if + + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$i]['code']]) === false) { + $lastNotEmpty = $i; + } + }//end for + + return 0; + + }//end findStartOfStatement() + + + /** + * Returns the position of the last non-whitespace token in a statement. + * + * @param int $start The position to start searching from in the token stack. + * @param int|string|array $ignore Token types that should not be considered stop points. + * + * @return int + */ + public function findEndOfStatement($start, $ignore=null) + { + $endTokens = [ + T_COLON => true, + T_COMMA => true, + T_DOUBLE_ARROW => true, + T_SEMICOLON => true, + T_CLOSE_PARENTHESIS => true, + T_CLOSE_SQUARE_BRACKET => true, + T_CLOSE_CURLY_BRACKET => true, + T_CLOSE_SHORT_ARRAY => true, + T_OPEN_TAG => true, + T_CLOSE_TAG => true, + ]; + + if ($ignore !== null) { + $ignore = (array) $ignore; + foreach ($ignore as $code) { + unset($endTokens[$code]); + } + } + + // If the start token is inside the case part of a match expression, + // advance to the match arrow and continue looking for the + // end of the statement from there so that we skip over commas. + if ($this->tokens[$start]['code'] !== T_MATCH_ARROW) { + $matchExpression = $this->getCondition($start, T_MATCH); + if ($matchExpression !== false) { + $beforeArrow = true; + $prevMatchArrow = $this->findPrevious(T_MATCH_ARROW, ($start - 1), $this->tokens[$matchExpression]['scope_opener']); + if ($prevMatchArrow !== false) { + $prevComma = $this->findNext(T_COMMA, ($prevMatchArrow + 1), $start); + if ($prevComma === false) { + // No comma between this token and the last match arrow, + // so this token exists after the arrow and we can continue + // checking as normal. + $beforeArrow = false; + } + } + + if ($beforeArrow === true) { + $nextMatchArrow = $this->findNext(T_MATCH_ARROW, ($start + 1), $this->tokens[$matchExpression]['scope_closer']); + if ($nextMatchArrow !== false) { + $start = $nextMatchArrow; + } + } + }//end if + }//end if + + $lastNotEmpty = $start; + for ($i = $start; $i < $this->numTokens; $i++) { + if ($i !== $start && isset($endTokens[$this->tokens[$i]['code']]) === true) { + // Found the end of the statement. + if ($this->tokens[$i]['code'] === T_CLOSE_PARENTHESIS + || $this->tokens[$i]['code'] === T_CLOSE_SQUARE_BRACKET + || $this->tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET + || $this->tokens[$i]['code'] === T_CLOSE_SHORT_ARRAY + || $this->tokens[$i]['code'] === T_OPEN_TAG + || $this->tokens[$i]['code'] === T_CLOSE_TAG + ) { + return $lastNotEmpty; + } + + return $i; + } + + // Skip nested statements. + if (isset($this->tokens[$i]['scope_closer']) === true + && ($i === $this->tokens[$i]['scope_opener'] + || $i === $this->tokens[$i]['scope_condition']) + ) { + if ($this->tokens[$i]['code'] === T_FN) { + $lastNotEmpty = $this->tokens[$i]['scope_closer']; + $i = ($this->tokens[$i]['scope_closer'] - 1); + continue; + } + + if ($i === $start && isset(Util\Tokens::$scopeOpeners[$this->tokens[$i]['code']]) === true) { + return $this->tokens[$i]['scope_closer']; + } + + $i = $this->tokens[$i]['scope_closer']; + } else if (isset($this->tokens[$i]['bracket_closer']) === true + && $i === $this->tokens[$i]['bracket_opener'] + ) { + $i = $this->tokens[$i]['bracket_closer']; + } else if (isset($this->tokens[$i]['parenthesis_closer']) === true + && $i === $this->tokens[$i]['parenthesis_opener'] + ) { + $i = $this->tokens[$i]['parenthesis_closer']; + } else if ($this->tokens[$i]['code'] === T_OPEN_USE_GROUP) { + $end = $this->findNext(T_CLOSE_USE_GROUP, ($i + 1)); + if ($end !== false) { + $i = $end; + } + }//end if + + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$i]['code']]) === false) { + $lastNotEmpty = $i; + } + }//end for + + return ($this->numTokens - 1); + + }//end findEndOfStatement() + + + /** + * Returns the position of the first token on a line, matching given type. + * + * Returns false if no token can be found. + * + * @param int|string|array $types The type(s) of tokens to search for. + * @param int $start The position to start searching from in the + * token stack. The first token matching on + * this line before this token will be returned. + * @param bool $exclude If true, find the token that is NOT of + * the types specified in $types. + * @param string $value The value that the token must be equal to. + * If value is omitted, tokens with any value will + * be returned. + * + * @return int|false + */ + public function findFirstOnLine($types, $start, $exclude=false, $value=null) + { + if (is_array($types) === false) { + $types = [$types]; + } + + $foundToken = false; + + for ($i = $start; $i >= 0; $i--) { + if ($this->tokens[$i]['line'] < $this->tokens[$start]['line']) { + break; + } + + $found = $exclude; + foreach ($types as $type) { + if ($exclude === false) { + if ($this->tokens[$i]['code'] === $type) { + $found = true; + break; + } + } else { + if ($this->tokens[$i]['code'] === $type) { + $found = false; + break; + } + } + } + + if ($found === true) { + if ($value === null) { + $foundToken = $i; + } else if ($this->tokens[$i]['content'] === $value) { + $foundToken = $i; + } + } + }//end for + + return $foundToken; + + }//end findFirstOnLine() + + + /** + * Determine if the passed token has a condition of one of the passed types. + * + * @param int $stackPtr The position of the token we are checking. + * @param int|string|array $types The type(s) of tokens to search for. + * + * @return boolean + */ + public function hasCondition($stackPtr, $types) + { + // Check for the existence of the token. + if (isset($this->tokens[$stackPtr]) === false) { + return false; + } + + // Make sure the token has conditions. + if (isset($this->tokens[$stackPtr]['conditions']) === false) { + return false; + } + + $types = (array) $types; + $conditions = $this->tokens[$stackPtr]['conditions']; + + foreach ($types as $type) { + if (in_array($type, $conditions, true) === true) { + // We found a token with the required type. + return true; + } + } + + return false; + + }//end hasCondition() + + + /** + * Return the position of the condition for the passed token. + * + * Returns FALSE if the token does not have the condition. + * + * @param int $stackPtr The position of the token we are checking. + * @param int|string $type The type of token to search for. + * @param bool $first If TRUE, will return the matched condition + * furthest away from the passed token. + * If FALSE, will return the matched condition + * closest to the passed token. + * + * @return int|false + */ + public function getCondition($stackPtr, $type, $first=true) + { + // Check for the existence of the token. + if (isset($this->tokens[$stackPtr]) === false) { + return false; + } + + // Make sure the token has conditions. + if (isset($this->tokens[$stackPtr]['conditions']) === false) { + return false; + } + + $conditions = $this->tokens[$stackPtr]['conditions']; + if ($first === false) { + $conditions = array_reverse($conditions, true); + } + + foreach ($conditions as $token => $condition) { + if ($condition === $type) { + return $token; + } + } + + return false; + + }//end getCondition() + + + /** + * Returns the name of the class that the specified class extends. + * (works for classes, anonymous classes and interfaces) + * + * Returns FALSE on error or if there is no extended class name. + * + * @param int $stackPtr The stack position of the class. + * + * @return string|false + */ + public function findExtendedClassName($stackPtr) + { + // Check for the existence of the token. + if (isset($this->tokens[$stackPtr]) === false) { + return false; + } + + if ($this->tokens[$stackPtr]['code'] !== T_CLASS + && $this->tokens[$stackPtr]['code'] !== T_ANON_CLASS + && $this->tokens[$stackPtr]['code'] !== T_INTERFACE + ) { + return false; + } + + if (isset($this->tokens[$stackPtr]['scope_opener']) === false) { + return false; + } + + $classOpenerIndex = $this->tokens[$stackPtr]['scope_opener']; + $extendsIndex = $this->findNext(T_EXTENDS, $stackPtr, $classOpenerIndex); + if ($extendsIndex === false) { + return false; + } + + $find = [ + T_NS_SEPARATOR, + T_STRING, + T_WHITESPACE, + ]; + + $end = $this->findNext($find, ($extendsIndex + 1), ($classOpenerIndex + 1), true); + $name = $this->getTokensAsString(($extendsIndex + 1), ($end - $extendsIndex - 1)); + $name = trim($name); + + if ($name === '') { + return false; + } + + return $name; + + }//end findExtendedClassName() + + + /** + * Returns the names of the interfaces that the specified class or enum implements. + * + * Returns FALSE on error or if there are no implemented interface names. + * + * @param int $stackPtr The stack position of the class or enum token. + * + * @return array|false + */ + public function findImplementedInterfaceNames($stackPtr) + { + // Check for the existence of the token. + if (isset($this->tokens[$stackPtr]) === false) { + return false; + } + + if ($this->tokens[$stackPtr]['code'] !== T_CLASS + && $this->tokens[$stackPtr]['code'] !== T_ANON_CLASS + && $this->tokens[$stackPtr]['code'] !== T_ENUM + ) { + return false; + } + + if (isset($this->tokens[$stackPtr]['scope_closer']) === false) { + return false; + } + + $classOpenerIndex = $this->tokens[$stackPtr]['scope_opener']; + $implementsIndex = $this->findNext(T_IMPLEMENTS, $stackPtr, $classOpenerIndex); + if ($implementsIndex === false) { + return false; + } + + $find = [ + T_NS_SEPARATOR, + T_STRING, + T_WHITESPACE, + T_COMMA, + ]; + + $end = $this->findNext($find, ($implementsIndex + 1), ($classOpenerIndex + 1), true); + $name = $this->getTokensAsString(($implementsIndex + 1), ($end - $implementsIndex - 1)); + $name = trim($name); + + if ($name === '') { + return false; + } else { + $names = explode(',', $name); + $names = array_map('trim', $names); + return $names; + } + + }//end findImplementedInterfaceNames() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Files/FileList.php b/vendor/squizlabs/php_codesniffer/src/Files/FileList.php new file mode 100644 index 00000000..66833a3e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Files/FileList.php @@ -0,0 +1,255 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Files; + +use PHP_CodeSniffer\Autoload; +use PHP_CodeSniffer\Util; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\DeepExitException; +use ReturnTypeWillChange; + +class FileList implements \Iterator, \Countable +{ + + /** + * A list of file paths that are included in the list. + * + * @var array + */ + private $files = []; + + /** + * The number of files in the list. + * + * @var integer + */ + private $numFiles = 0; + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + public $config = null; + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + public $ruleset = null; + + /** + * An array of patterns to use for skipping files. + * + * @var array + */ + protected $ignorePatterns = []; + + + /** + * Constructs a file list and loads in an array of file paths to process. + * + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * + * @return void + */ + public function __construct(Config $config, Ruleset $ruleset) + { + $this->ruleset = $ruleset; + $this->config = $config; + + $paths = $config->files; + foreach ($paths as $path) { + $isPharFile = Util\Common::isPharFile($path); + if (is_dir($path) === true || $isPharFile === true) { + if ($isPharFile === true) { + $path = 'phar://'.$path; + } + + $filterClass = $this->getFilterClass(); + + $di = new \RecursiveDirectoryIterator($path, (\RecursiveDirectoryIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS)); + $filter = new $filterClass($di, $path, $config, $ruleset); + $iterator = new \RecursiveIteratorIterator($filter); + + foreach ($iterator as $file) { + $this->files[$file->getPathname()] = null; + $this->numFiles++; + } + } else { + $this->addFile($path); + }//end if + }//end foreach + + reset($this->files); + + }//end __construct() + + + /** + * Add a file to the list. + * + * If a file object has already been created, it can be passed here. + * If it is left NULL, it will be created when accessed. + * + * @param string $path The path to the file being added. + * @param \PHP_CodeSniffer\Files\File $file The file being added. + * + * @return void + */ + public function addFile($path, $file=null) + { + // No filtering is done for STDIN when the filename + // has not been specified. + if ($path === 'STDIN') { + $this->files[$path] = $file; + $this->numFiles++; + return; + } + + $filterClass = $this->getFilterClass(); + + $di = new \RecursiveArrayIterator([$path]); + $filter = new $filterClass($di, $path, $this->config, $this->ruleset); + $iterator = new \RecursiveIteratorIterator($filter); + + foreach ($iterator as $path) { + $this->files[$path] = $file; + $this->numFiles++; + } + + }//end addFile() + + + /** + * Get the class name of the filter being used for the run. + * + * @return string + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If the specified filter could not be found. + */ + private function getFilterClass() + { + $filterType = $this->config->filter; + + if ($filterType === null) { + $filterClass = '\PHP_CodeSniffer\Filters\Filter'; + } else { + if (strpos($filterType, '.') !== false) { + // This is a path to a custom filter class. + $filename = realpath($filterType); + if ($filename === false) { + $error = "ERROR: Custom filter \"$filterType\" not found".PHP_EOL; + throw new DeepExitException($error, 3); + } + + $filterClass = Autoload::loadFile($filename); + } else { + $filterClass = '\PHP_CodeSniffer\Filters\\'.$filterType; + } + } + + return $filterClass; + + }//end getFilterClass() + + + /** + * Rewind the iterator to the first file. + * + * @return void + */ + #[ReturnTypeWillChange] + public function rewind() + { + reset($this->files); + + }//end rewind() + + + /** + * Get the file that is currently being processed. + * + * @return \PHP_CodeSniffer\Files\File + */ + #[ReturnTypeWillChange] + public function current() + { + $path = key($this->files); + if (isset($this->files[$path]) === false) { + $this->files[$path] = new LocalFile($path, $this->ruleset, $this->config); + } + + return $this->files[$path]; + + }//end current() + + + /** + * Return the file path of the current file being processed. + * + * @return void + */ + #[ReturnTypeWillChange] + public function key() + { + return key($this->files); + + }//end key() + + + /** + * Move forward to the next file. + * + * @return void + */ + #[ReturnTypeWillChange] + public function next() + { + next($this->files); + + }//end next() + + + /** + * Checks if current position is valid. + * + * @return boolean + */ + #[ReturnTypeWillChange] + public function valid() + { + if (current($this->files) === false) { + return false; + } + + return true; + + }//end valid() + + + /** + * Return the number of files in the list. + * + * @return integer + */ + #[ReturnTypeWillChange] + public function count() + { + return $this->numFiles; + + }//end count() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Files/LocalFile.php b/vendor/squizlabs/php_codesniffer/src/Files/LocalFile.php new file mode 100644 index 00000000..ca2e74ad --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Files/LocalFile.php @@ -0,0 +1,219 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Files; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Util\Cache; +use PHP_CodeSniffer\Util\Common; + +class LocalFile extends File +{ + + + /** + * Creates a LocalFile object and sets the content. + * + * @param string $path The absolute path to the file. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public function __construct($path, Ruleset $ruleset, Config $config) + { + $this->path = trim($path); + if (Common::isReadable($this->path) === false) { + parent::__construct($this->path, $ruleset, $config); + $error = 'Error opening file; file no longer exists or you do not have access to read the file'; + $this->addMessage(true, $error, 1, 1, 'Internal.LocalFile', [], 5, false); + $this->ignored = true; + return; + } + + // Before we go and spend time tokenizing this file, just check + // to see if there is a tag up top to indicate that the whole + // file should be ignored. It must be on one of the first two lines. + if ($config->annotations === true) { + $handle = fopen($this->path, 'r'); + if ($handle !== false) { + $firstContent = fgets($handle); + $firstContent .= fgets($handle); + fclose($handle); + + if (strpos($firstContent, '@codingStandardsIgnoreFile') !== false + || stripos($firstContent, 'phpcs:ignorefile') !== false + ) { + // We are ignoring the whole file. + $this->ignored = true; + return; + } + } + } + + $this->reloadContent(); + + parent::__construct($this->path, $ruleset, $config); + + }//end __construct() + + + /** + * Loads the latest version of the file's content from the file system. + * + * @return void + */ + public function reloadContent() + { + $this->setContent(file_get_contents($this->path)); + + }//end reloadContent() + + + /** + * Processes the file. + * + * @return void + */ + public function process() + { + if ($this->ignored === true) { + return; + } + + if ($this->configCache['cache'] === false) { + parent::process(); + return; + } + + $hash = md5_file($this->path); + $hash .= fileperms($this->path); + $cache = Cache::get($this->path); + if ($cache !== false && $cache['hash'] === $hash) { + // We can't filter metrics, so just load all of them. + $this->metrics = $cache['metrics']; + + if ($this->configCache['recordErrors'] === true) { + // Replay the cached errors and warnings to filter out the ones + // we don't need for this specific run. + $this->configCache['cache'] = false; + $this->replayErrors($cache['errors'], $cache['warnings']); + $this->configCache['cache'] = true; + } else { + $this->errorCount = $cache['errorCount']; + $this->warningCount = $cache['warningCount']; + $this->fixableCount = $cache['fixableCount']; + } + + if (PHP_CODESNIFFER_VERBOSITY > 0 + || (PHP_CODESNIFFER_CBF === true && empty($this->config->files) === false) + ) { + echo "[loaded from cache]... "; + } + + $this->numTokens = $cache['numTokens']; + $this->fromCache = true; + return; + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + + parent::process(); + + $cache = [ + 'hash' => $hash, + 'errors' => $this->errors, + 'warnings' => $this->warnings, + 'metrics' => $this->metrics, + 'errorCount' => $this->errorCount, + 'warningCount' => $this->warningCount, + 'fixableCount' => $this->fixableCount, + 'numTokens' => $this->numTokens, + ]; + + Cache::set($this->path, $cache); + + // During caching, we don't filter out errors in any way, so + // we need to do that manually now by replaying them. + if ($this->configCache['recordErrors'] === true) { + $this->configCache['cache'] = false; + $this->replayErrors($this->errors, $this->warnings); + $this->configCache['cache'] = true; + } + + }//end process() + + + /** + * Clears and replays error and warnings for the file. + * + * Replaying errors and warnings allows for filtering rules to be changed + * and then errors and warnings to be reapplied with the new rules. This is + * particularly useful while caching. + * + * @param array $errors The list of errors to replay. + * @param array $warnings The list of warnings to replay. + * + * @return void + */ + private function replayErrors($errors, $warnings) + { + $this->errors = []; + $this->warnings = []; + $this->errorCount = 0; + $this->warningCount = 0; + $this->fixableCount = 0; + + $this->replayingErrors = true; + + foreach ($errors as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $this->activeListener = $error['listener']; + $this->addMessage( + true, + $error['message'], + $line, + $column, + $error['source'], + [], + $error['severity'], + $error['fixable'] + ); + } + } + } + + foreach ($warnings as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $this->activeListener = $error['listener']; + $this->addMessage( + false, + $error['message'], + $line, + $column, + $error['source'], + [], + $error['severity'], + $error['fixable'] + ); + } + } + } + + $this->replayingErrors = false; + + }//end replayErrors() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Filters/ExactMatch.php b/vendor/squizlabs/php_codesniffer/src/Filters/ExactMatch.php new file mode 100644 index 00000000..13af8ff2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Filters/ExactMatch.php @@ -0,0 +1,108 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Filters; + +use PHP_CodeSniffer\Util; + +abstract class ExactMatch extends Filter +{ + + /** + * A list of files to exclude. + * + * @var array + */ + private $blacklist = null; + + /** + * A list of files to include. + * + * If the whitelist is empty, only files in the blacklist will be excluded. + * + * @var array + */ + private $whitelist = null; + + + /** + * Check whether the current element of the iterator is acceptable. + * + * If a file is both blacklisted and whitelisted, it will be deemed unacceptable. + * + * @return bool + */ + public function accept() + { + if (parent::accept() === false) { + return false; + } + + if ($this->blacklist === null) { + $this->blacklist = $this->getblacklist(); + } + + if ($this->whitelist === null) { + $this->whitelist = $this->getwhitelist(); + } + + $filePath = Util\Common::realpath($this->current()); + + // If file is both blacklisted and whitelisted, the blacklist takes precedence. + if (isset($this->blacklist[$filePath]) === true) { + return false; + } + + if (empty($this->whitelist) === true && empty($this->blacklist) === false) { + // We are only checking a blacklist, so everything else should be whitelisted. + return true; + } + + return isset($this->whitelist[$filePath]); + + }//end accept() + + + /** + * Returns an iterator for the current entry. + * + * Ensures that the blacklist and whitelist are preserved so they don't have + * to be generated each time. + * + * @return \RecursiveIterator + */ + public function getChildren() + { + $children = parent::getChildren(); + $children->blacklist = $this->blacklist; + $children->whitelist = $this->whitelist; + return $children; + + }//end getChildren() + + + /** + * Get a list of blacklisted file paths. + * + * @return array + */ + abstract protected function getBlacklist(); + + + /** + * Get a list of whitelisted file paths. + * + * @return array + */ + abstract protected function getWhitelist(); + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Filters/Filter.php b/vendor/squizlabs/php_codesniffer/src/Filters/Filter.php new file mode 100644 index 00000000..a1246a2c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Filters/Filter.php @@ -0,0 +1,285 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Filters; + +use PHP_CodeSniffer\Util; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Config; +use ReturnTypeWillChange; + +class Filter extends \RecursiveFilterIterator +{ + + /** + * The top-level path we are filtering. + * + * @var string + */ + protected $basedir = null; + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + protected $config = null; + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected $ruleset = null; + + /** + * A list of ignore patterns that apply to directories only. + * + * @var array + */ + protected $ignoreDirPatterns = null; + + /** + * A list of ignore patterns that apply to files only. + * + * @var array + */ + protected $ignoreFilePatterns = null; + + /** + * A list of file paths we've already accepted. + * + * Used to ensure we aren't following circular symlinks. + * + * @var array + */ + protected $acceptedPaths = []; + + + /** + * Constructs a filter. + * + * @param \RecursiveIterator $iterator The iterator we are using to get file paths. + * @param string $basedir The top-level path we are filtering. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * + * @return void + */ + public function __construct($iterator, $basedir, Config $config, Ruleset $ruleset) + { + parent::__construct($iterator); + $this->basedir = $basedir; + $this->config = $config; + $this->ruleset = $ruleset; + + }//end __construct() + + + /** + * Check whether the current element of the iterator is acceptable. + * + * Files are checked for allowed extensions and ignore patterns. + * Directories are checked for ignore patterns only. + * + * @return bool + */ + #[ReturnTypeWillChange] + public function accept() + { + $filePath = $this->current(); + $realPath = Util\Common::realpath($filePath); + + if ($realPath !== false) { + // It's a real path somewhere, so record it + // to check for circular symlinks. + if (isset($this->acceptedPaths[$realPath]) === true) { + // We've been here before. + return false; + } + } + + $filePath = $this->current(); + if (is_dir($filePath) === true) { + if ($this->config->local === true) { + return false; + } + } else if ($this->shouldProcessFile($filePath) === false) { + return false; + } + + if ($this->shouldIgnorePath($filePath) === true) { + return false; + } + + $this->acceptedPaths[$realPath] = true; + return true; + + }//end accept() + + + /** + * Returns an iterator for the current entry. + * + * Ensures that the ignore patterns are preserved so they don't have + * to be generated each time. + * + * @return \RecursiveIterator + */ + #[ReturnTypeWillChange] + public function getChildren() + { + $filterClass = get_called_class(); + $children = new $filterClass( + new \RecursiveDirectoryIterator($this->current(), (\RecursiveDirectoryIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS)), + $this->basedir, + $this->config, + $this->ruleset + ); + + // Set the ignore patterns so we don't have to generate them again. + $children->ignoreDirPatterns = $this->ignoreDirPatterns; + $children->ignoreFilePatterns = $this->ignoreFilePatterns; + $children->acceptedPaths = $this->acceptedPaths; + return $children; + + }//end getChildren() + + + /** + * Checks filtering rules to see if a file should be checked. + * + * Checks both file extension filters and path ignore filters. + * + * @param string $path The path to the file being checked. + * + * @return bool + */ + protected function shouldProcessFile($path) + { + // Check that the file's extension is one we are checking. + // We are strict about checking the extension and we don't + // let files through with no extension or that start with a dot. + $fileName = basename($path); + $fileParts = explode('.', $fileName); + if ($fileParts[0] === $fileName || $fileParts[0] === '') { + return false; + } + + // Checking multi-part file extensions, so need to create a + // complete extension list and make sure one is allowed. + $extensions = []; + array_shift($fileParts); + foreach ($fileParts as $part) { + $extensions[implode('.', $fileParts)] = 1; + array_shift($fileParts); + } + + $matches = array_intersect_key($extensions, $this->config->extensions); + if (empty($matches) === true) { + return false; + } + + return true; + + }//end shouldProcessFile() + + + /** + * Checks filtering rules to see if a path should be ignored. + * + * @param string $path The path to the file or directory being checked. + * + * @return bool + */ + protected function shouldIgnorePath($path) + { + if ($this->ignoreFilePatterns === null) { + $this->ignoreDirPatterns = []; + $this->ignoreFilePatterns = []; + + $ignorePatterns = $this->config->ignored; + $rulesetIgnorePatterns = $this->ruleset->getIgnorePatterns(); + foreach ($rulesetIgnorePatterns as $pattern => $type) { + // Ignore standard/sniff specific exclude rules. + if (is_array($type) === true) { + continue; + } + + $ignorePatterns[$pattern] = $type; + } + + foreach ($ignorePatterns as $pattern => $type) { + // If the ignore pattern ends with /* then it is ignoring an entire directory. + if (substr($pattern, -2) === '/*') { + // Need to check this pattern for dirs as well as individual file paths. + $this->ignoreFilePatterns[$pattern] = $type; + + $pattern = substr($pattern, 0, -2).'(?=/|$)'; + $this->ignoreDirPatterns[$pattern] = $type; + } else { + // This is a file-specific pattern, so only need to check this + // for individual file paths. + $this->ignoreFilePatterns[$pattern] = $type; + } + } + }//end if + + $relativePath = $path; + if (strpos($path, $this->basedir) === 0) { + // The +1 cuts off the directory separator as well. + $relativePath = substr($path, (strlen($this->basedir) + 1)); + } + + if (is_dir($path) === true) { + $ignorePatterns = $this->ignoreDirPatterns; + } else { + $ignorePatterns = $this->ignoreFilePatterns; + } + + foreach ($ignorePatterns as $pattern => $type) { + // Maintains backwards compatibility in case the ignore pattern does + // not have a relative/absolute value. + if (is_int($pattern) === true) { + $pattern = $type; + $type = 'absolute'; + } + + $replacements = [ + '\\,' => ',', + '*' => '.*', + ]; + + // We assume a / directory separator, as do the exclude rules + // most developers write, so we need a special case for any system + // that is different. + if (DIRECTORY_SEPARATOR === '\\') { + $replacements['/'] = '\\\\'; + } + + $pattern = strtr($pattern, $replacements); + + if ($type === 'relative') { + $testPath = $relativePath; + } else { + $testPath = $path; + } + + $pattern = '`'.$pattern.'`i'; + if (preg_match($pattern, $testPath) === 1) { + return true; + } + }//end foreach + + return false; + + }//end shouldIgnorePath() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Filters/GitModified.php b/vendor/squizlabs/php_codesniffer/src/Filters/GitModified.php new file mode 100644 index 00000000..4b6ef3fc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Filters/GitModified.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Filters; + +use PHP_CodeSniffer\Util; + +class GitModified extends ExactMatch +{ + + + /** + * Get a list of blacklisted file paths. + * + * @return array + */ + protected function getBlacklist() + { + return []; + + }//end getBlacklist() + + + /** + * Get a list of whitelisted file paths. + * + * @return array + */ + protected function getWhitelist() + { + $modified = []; + + $cmd = 'git ls-files -o -m --exclude-standard -- '.escapeshellarg($this->basedir); + $output = []; + exec($cmd, $output); + + $basedir = $this->basedir; + if (is_dir($basedir) === false) { + $basedir = dirname($basedir); + } + + foreach ($output as $path) { + $path = Util\Common::realpath($path); + + if ($path === false) { + continue; + } + + do { + $modified[$path] = true; + $path = dirname($path); + } while ($path !== $basedir); + } + + return $modified; + + }//end getWhitelist() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Filters/GitStaged.php b/vendor/squizlabs/php_codesniffer/src/Filters/GitStaged.php new file mode 100644 index 00000000..fcb92c3d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Filters/GitStaged.php @@ -0,0 +1,68 @@ + + * @copyright 2018 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Filters; + +use PHP_CodeSniffer\Util; + +class GitStaged extends ExactMatch +{ + + + /** + * Get a list of blacklisted file paths. + * + * @return array + */ + protected function getBlacklist() + { + return []; + + }//end getBlacklist() + + + /** + * Get a list of whitelisted file paths. + * + * @return array + */ + protected function getWhitelist() + { + $modified = []; + + $cmd = 'git diff --cached --name-only -- '.escapeshellarg($this->basedir); + $output = []; + exec($cmd, $output); + + $basedir = $this->basedir; + if (is_dir($basedir) === false) { + $basedir = dirname($basedir); + } + + foreach ($output as $path) { + $path = Util\Common::realpath($path); + if ($path === false) { + // Skip deleted files. + continue; + } + + do { + $modified[$path] = true; + $path = dirname($path); + } while ($path !== $basedir); + } + + return $modified; + + }//end getWhitelist() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Fixer.php b/vendor/squizlabs/php_codesniffer/src/Fixer.php new file mode 100644 index 00000000..b8dc05b1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Fixer.php @@ -0,0 +1,806 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Common; + +class Fixer +{ + + /** + * Is the fixer enabled and fixing a file? + * + * Sniffs should check this value to ensure they are not + * doing extra processing to prepare for a fix when fixing is + * not required. + * + * @var boolean + */ + public $enabled = false; + + /** + * The number of times we have looped over a file. + * + * @var integer + */ + public $loops = 0; + + /** + * The file being fixed. + * + * @var \PHP_CodeSniffer\Files\File + */ + private $currentFile = null; + + /** + * The list of tokens that make up the file contents. + * + * This is a simplified list which just contains the token content and nothing + * else. This is the array that is updated as fixes are made, not the file's + * token array. Imploding this array will give you the file content back. + * + * @var array + */ + private $tokens = []; + + /** + * A list of tokens that have already been fixed. + * + * We don't allow the same token to be fixed more than once each time + * through a file as this can easily cause conflicts between sniffs. + * + * @var int[] + */ + private $fixedTokens = []; + + /** + * The last value of each fixed token. + * + * If a token is being "fixed" back to its last value, the fix is + * probably conflicting with another. + * + * @var array + */ + private $oldTokenValues = []; + + /** + * A list of tokens that have been fixed during a changeset. + * + * All changes in changeset must be able to be applied, or else + * the entire changeset is rejected. + * + * @var array + */ + private $changeset = []; + + /** + * Is there an open changeset. + * + * @var boolean + */ + private $inChangeset = false; + + /** + * Is the current fixing loop in conflict? + * + * @var boolean + */ + private $inConflict = false; + + /** + * The number of fixes that have been performed. + * + * @var integer + */ + private $numFixes = 0; + + + /** + * Starts fixing a new file. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being fixed. + * + * @return void + */ + public function startFile(File $phpcsFile) + { + $this->currentFile = $phpcsFile; + $this->numFixes = 0; + $this->fixedTokens = []; + + $tokens = $phpcsFile->getTokens(); + $this->tokens = []; + foreach ($tokens as $index => $token) { + if (isset($token['orig_content']) === true) { + $this->tokens[$index] = $token['orig_content']; + } else { + $this->tokens[$index] = $token['content']; + } + } + + }//end startFile() + + + /** + * Attempt to fix the file by processing it until no fixes are made. + * + * @return boolean + */ + public function fixFile() + { + $fixable = $this->currentFile->getFixableCount(); + if ($fixable === 0) { + // Nothing to fix. + return false; + } + + $this->enabled = true; + + $this->loops = 0; + while ($this->loops < 50) { + ob_start(); + + // Only needed once file content has changed. + $contents = $this->getContents(); + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + @ob_end_clean(); + echo '---START FILE CONTENT---'.PHP_EOL; + $lines = explode($this->currentFile->eolChar, $contents); + $max = strlen(count($lines)); + foreach ($lines as $lineNum => $line) { + $lineNum++; + echo str_pad($lineNum, $max, ' ', STR_PAD_LEFT).'|'.$line.PHP_EOL; + } + + echo '--- END FILE CONTENT ---'.PHP_EOL; + ob_start(); + } + + $this->inConflict = false; + $this->currentFile->ruleset->populateTokenListeners(); + $this->currentFile->setContent($contents); + $this->currentFile->process(); + ob_end_clean(); + + $this->loops++; + + if (PHP_CODESNIFFER_CBF === true && PHP_CODESNIFFER_VERBOSITY > 0) { + echo "\r".str_repeat(' ', 80)."\r"; + echo "\t=> Fixing file: $this->numFixes/$fixable violations remaining [made $this->loops pass"; + if ($this->loops > 1) { + echo 'es'; + } + + echo ']... '; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + if ($this->numFixes === 0 && $this->inConflict === false) { + // Nothing left to do. + break; + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* fixed $this->numFixes violations, starting loop ".($this->loops + 1).' *'.PHP_EOL; + } + }//end while + + $this->enabled = false; + + if ($this->numFixes > 0) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if (ob_get_level() > 0) { + ob_end_clean(); + } + + echo "\t*** Reached maximum number of loops with $this->numFixes violations left unfixed ***".PHP_EOL; + ob_start(); + } + + return false; + } + + return true; + + }//end fixFile() + + + /** + * Generates a text diff of the original file and the new content. + * + * @param string $filePath Optional file path to diff the file against. + * If not specified, the original version of the + * file will be used. + * @param boolean $colors Print coloured output or not. + * + * @return string + */ + public function generateDiff($filePath=null, $colors=true) + { + if ($filePath === null) { + $filePath = $this->currentFile->getFilename(); + } + + $cwd = getcwd().DIRECTORY_SEPARATOR; + if (strpos($filePath, $cwd) === 0) { + $filename = substr($filePath, strlen($cwd)); + } else { + $filename = $filePath; + } + + $contents = $this->getContents(); + + $tempName = tempnam(sys_get_temp_dir(), 'phpcs-fixer'); + $fixedFile = fopen($tempName, 'w'); + fwrite($fixedFile, $contents); + + // We must use something like shell_exec() because whitespace at the end + // of lines is critical to diff files. + $filename = escapeshellarg($filename); + $cmd = "diff -u -L$filename -LPHP_CodeSniffer $filename \"$tempName\""; + + $diff = shell_exec($cmd); + + fclose($fixedFile); + if (is_file($tempName) === true) { + unlink($tempName); + } + + if ($diff === null) { + return ''; + } + + if ($colors === false) { + return $diff; + } + + $diffLines = explode(PHP_EOL, $diff); + if (count($diffLines) === 1) { + // Seems to be required for cygwin. + $diffLines = explode("\n", $diff); + } + + $diff = []; + foreach ($diffLines as $line) { + if (isset($line[0]) === true) { + switch ($line[0]) { + case '-': + $diff[] = "\033[31m$line\033[0m"; + break; + case '+': + $diff[] = "\033[32m$line\033[0m"; + break; + default: + $diff[] = $line; + } + } + } + + $diff = implode(PHP_EOL, $diff); + + return $diff; + + }//end generateDiff() + + + /** + * Get a count of fixes that have been performed on the file. + * + * This value is reset every time a new file is started, or an existing + * file is restarted. + * + * @return int + */ + public function getFixCount() + { + return $this->numFixes; + + }//end getFixCount() + + + /** + * Get the current content of the file, as a string. + * + * @return string + */ + public function getContents() + { + $contents = implode($this->tokens); + return $contents; + + }//end getContents() + + + /** + * Get the current fixed content of a token. + * + * This function takes changesets into account so should be used + * instead of directly accessing the token array. + * + * @param int $stackPtr The position of the token in the token stack. + * + * @return string + */ + public function getTokenContent($stackPtr) + { + if ($this->inChangeset === true + && isset($this->changeset[$stackPtr]) === true + ) { + return $this->changeset[$stackPtr]; + } else { + return $this->tokens[$stackPtr]; + } + + }//end getTokenContent() + + + /** + * Start recording actions for a changeset. + * + * @return void + */ + public function beginChangeset() + { + if ($this->inConflict === true) { + return false; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + if ($bt[1]['class'] === __CLASS__) { + $sniff = 'Fixer'; + } else { + $sniff = Util\Common::getSniffCode($bt[1]['class']); + } + + $line = $bt[0]['line']; + + @ob_end_clean(); + echo "\t=> Changeset started by $sniff:$line".PHP_EOL; + ob_start(); + } + + $this->changeset = []; + $this->inChangeset = true; + + }//end beginChangeset() + + + /** + * Stop recording actions for a changeset, and apply logged changes. + * + * @return boolean + */ + public function endChangeset() + { + if ($this->inConflict === true) { + return false; + } + + $this->inChangeset = false; + + $success = true; + $applied = []; + foreach ($this->changeset as $stackPtr => $content) { + $success = $this->replaceToken($stackPtr, $content); + if ($success === false) { + break; + } else { + $applied[] = $stackPtr; + } + } + + if ($success === false) { + // Rolling back all changes. + foreach ($applied as $stackPtr) { + $this->revertToken($stackPtr); + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + @ob_end_clean(); + echo "\t=> Changeset failed to apply".PHP_EOL; + ob_start(); + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + $fixes = count($this->changeset); + @ob_end_clean(); + echo "\t=> Changeset ended: $fixes changes applied".PHP_EOL; + ob_start(); + } + + $this->changeset = []; + return true; + + }//end endChangeset() + + + /** + * Stop recording actions for a changeset, and discard logged changes. + * + * @return void + */ + public function rollbackChangeset() + { + $this->inChangeset = false; + $this->inConflict = false; + + if (empty($this->changeset) === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $bt = debug_backtrace(); + if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') { + $sniff = $bt[2]['class']; + $line = $bt[1]['line']; + } else { + $sniff = $bt[1]['class']; + $line = $bt[0]['line']; + } + + $sniff = Util\Common::getSniffCode($sniff); + + $numChanges = count($this->changeset); + + @ob_end_clean(); + echo "\t\tR: $sniff:$line rolled back the changeset ($numChanges changes)".PHP_EOL; + echo "\t=> Changeset rolled back".PHP_EOL; + ob_start(); + } + + $this->changeset = []; + }//end if + + }//end rollbackChangeset() + + + /** + * Replace the entire contents of a token. + * + * @param int $stackPtr The position of the token in the token stack. + * @param string $content The new content of the token. + * + * @return bool If the change was accepted. + */ + public function replaceToken($stackPtr, $content) + { + if ($this->inConflict === true) { + return false; + } + + if ($this->inChangeset === false + && isset($this->fixedTokens[$stackPtr]) === true + ) { + $indent = "\t"; + if (empty($this->changeset) === false) { + $indent .= "\t"; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + @ob_end_clean(); + echo "$indent* token $stackPtr has already been modified, skipping *".PHP_EOL; + ob_start(); + } + + return false; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') { + $sniff = $bt[2]['class']; + $line = $bt[1]['line']; + } else { + $sniff = $bt[1]['class']; + $line = $bt[0]['line']; + } + + $sniff = Util\Common::getSniffCode($sniff); + + $tokens = $this->currentFile->getTokens(); + $type = $tokens[$stackPtr]['type']; + $tokenLine = $tokens[$stackPtr]['line']; + $oldContent = Common::prepareForOutput($this->tokens[$stackPtr]); + $newContent = Common::prepareForOutput($content); + if (trim($this->tokens[$stackPtr]) === '' && isset($this->tokens[($stackPtr + 1)]) === true) { + // Add some context for whitespace only changes. + $append = Common::prepareForOutput($this->tokens[($stackPtr + 1)]); + $oldContent .= $append; + $newContent .= $append; + } + }//end if + + if ($this->inChangeset === true) { + $this->changeset[$stackPtr] = $content; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + @ob_end_clean(); + echo "\t\tQ: $sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL; + ob_start(); + } + + return true; + } + + if (isset($this->oldTokenValues[$stackPtr]) === false) { + $this->oldTokenValues[$stackPtr] = [ + 'curr' => $content, + 'prev' => $this->tokens[$stackPtr], + 'loop' => $this->loops, + ]; + } else { + if ($this->oldTokenValues[$stackPtr]['prev'] === $content + && $this->oldTokenValues[$stackPtr]['loop'] === ($this->loops - 1) + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $indent = "\t"; + if (empty($this->changeset) === false) { + $indent .= "\t"; + } + + $loop = $this->oldTokenValues[$stackPtr]['loop']; + + @ob_end_clean(); + echo "$indent**** $sniff:$line has possible conflict with another sniff on loop $loop; caused by the following change ****".PHP_EOL; + echo "$indent**** replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\" ****".PHP_EOL; + } + + if ($this->oldTokenValues[$stackPtr]['loop'] >= ($this->loops - 1)) { + $this->inConflict = true; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "$indent**** ignoring all changes until next loop ****".PHP_EOL; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + ob_start(); + } + + return false; + }//end if + + $this->oldTokenValues[$stackPtr]['prev'] = $this->oldTokenValues[$stackPtr]['curr']; + $this->oldTokenValues[$stackPtr]['curr'] = $content; + $this->oldTokenValues[$stackPtr]['loop'] = $this->loops; + }//end if + + $this->fixedTokens[$stackPtr] = $this->tokens[$stackPtr]; + $this->tokens[$stackPtr] = $content; + $this->numFixes++; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $indent = "\t"; + if (empty($this->changeset) === false) { + $indent .= "\tA: "; + } + + if (ob_get_level() > 0) { + ob_end_clean(); + } + + echo "$indent$sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL; + ob_start(); + } + + return true; + + }//end replaceToken() + + + /** + * Reverts the previous fix made to a token. + * + * @param int $stackPtr The position of the token in the token stack. + * + * @return bool If a change was reverted. + */ + public function revertToken($stackPtr) + { + if (isset($this->fixedTokens[$stackPtr]) === false) { + return false; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') { + $sniff = $bt[2]['class']; + $line = $bt[1]['line']; + } else { + $sniff = $bt[1]['class']; + $line = $bt[0]['line']; + } + + $sniff = Util\Common::getSniffCode($sniff); + + $tokens = $this->currentFile->getTokens(); + $type = $tokens[$stackPtr]['type']; + $tokenLine = $tokens[$stackPtr]['line']; + $oldContent = Common::prepareForOutput($this->tokens[$stackPtr]); + $newContent = Common::prepareForOutput($this->fixedTokens[$stackPtr]); + if (trim($this->tokens[$stackPtr]) === '' && isset($tokens[($stackPtr + 1)]) === true) { + // Add some context for whitespace only changes. + $append = Common::prepareForOutput($this->tokens[($stackPtr + 1)]); + $oldContent .= $append; + $newContent .= $append; + } + }//end if + + $this->tokens[$stackPtr] = $this->fixedTokens[$stackPtr]; + unset($this->fixedTokens[$stackPtr]); + $this->numFixes--; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $indent = "\t"; + if (empty($this->changeset) === false) { + $indent .= "\tR: "; + } + + @ob_end_clean(); + echo "$indent$sniff:$line reverted token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL; + ob_start(); + } + + return true; + + }//end revertToken() + + + /** + * Replace the content of a token with a part of its current content. + * + * @param int $stackPtr The position of the token in the token stack. + * @param int $start The first character to keep. + * @param int $length The number of characters to keep. If NULL, the content of + * the token from $start to the end of the content is kept. + * + * @return bool If the change was accepted. + */ + public function substrToken($stackPtr, $start, $length=null) + { + $current = $this->getTokenContent($stackPtr); + + if ($length === null) { + $newContent = substr($current, $start); + } else { + $newContent = substr($current, $start, $length); + } + + return $this->replaceToken($stackPtr, $newContent); + + }//end substrToken() + + + /** + * Adds a newline to end of a token's content. + * + * @param int $stackPtr The position of the token in the token stack. + * + * @return bool If the change was accepted. + */ + public function addNewline($stackPtr) + { + $current = $this->getTokenContent($stackPtr); + return $this->replaceToken($stackPtr, $current.$this->currentFile->eolChar); + + }//end addNewline() + + + /** + * Adds a newline to the start of a token's content. + * + * @param int $stackPtr The position of the token in the token stack. + * + * @return bool If the change was accepted. + */ + public function addNewlineBefore($stackPtr) + { + $current = $this->getTokenContent($stackPtr); + return $this->replaceToken($stackPtr, $this->currentFile->eolChar.$current); + + }//end addNewlineBefore() + + + /** + * Adds content to the end of a token's current content. + * + * @param int $stackPtr The position of the token in the token stack. + * @param string $content The content to add. + * + * @return bool If the change was accepted. + */ + public function addContent($stackPtr, $content) + { + $current = $this->getTokenContent($stackPtr); + return $this->replaceToken($stackPtr, $current.$content); + + }//end addContent() + + + /** + * Adds content to the start of a token's current content. + * + * @param int $stackPtr The position of the token in the token stack. + * @param string $content The content to add. + * + * @return bool If the change was accepted. + */ + public function addContentBefore($stackPtr, $content) + { + $current = $this->getTokenContent($stackPtr); + return $this->replaceToken($stackPtr, $content.$current); + + }//end addContentBefore() + + + /** + * Adjust the indent of a code block. + * + * @param int $start The position of the token in the token stack + * to start adjusting the indent from. + * @param int $end The position of the token in the token stack + * to end adjusting the indent. + * @param int $change The number of spaces to adjust the indent by + * (positive or negative). + * + * @return void + */ + public function changeCodeBlockIndent($start, $end, $change) + { + $tokens = $this->currentFile->getTokens(); + + $baseIndent = ''; + if ($change > 0) { + $baseIndent = str_repeat(' ', $change); + } + + $useChangeset = false; + if ($this->inChangeset === false) { + $this->beginChangeset(); + $useChangeset = true; + } + + for ($i = $start; $i <= $end; $i++) { + if ($tokens[$i]['column'] !== 1 + || $tokens[($i + 1)]['line'] !== $tokens[$i]['line'] + ) { + continue; + } + + $length = 0; + if ($tokens[$i]['code'] === T_WHITESPACE + || $tokens[$i]['code'] === T_DOC_COMMENT_WHITESPACE + ) { + $length = $tokens[$i]['length']; + + $padding = ($length + $change); + if ($padding > 0) { + $padding = str_repeat(' ', $padding); + } else { + $padding = ''; + } + + $newContent = $padding.ltrim($tokens[$i]['content']); + } else { + $newContent = $baseIndent.$tokens[$i]['content']; + } + + $this->replaceToken($i, $newContent); + }//end for + + if ($useChangeset === true) { + $this->endChangeset(); + } + + }//end changeCodeBlockIndent() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Generators/Generator.php b/vendor/squizlabs/php_codesniffer/src/Generators/Generator.php new file mode 100644 index 00000000..56049768 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Generators/Generator.php @@ -0,0 +1,117 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Generators; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Autoload; + +abstract class Generator +{ + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + public $ruleset = null; + + /** + * XML documentation files used to produce the final output. + * + * @var string[] + */ + public $docFiles = []; + + + /** + * Constructs a doc generator. + * + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * + * @see generate() + */ + public function __construct(Ruleset $ruleset) + { + $this->ruleset = $ruleset; + + foreach ($ruleset->sniffs as $className => $sniffClass) { + $file = Autoload::getLoadedFileName($className); + $docFile = str_replace( + DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR, + DIRECTORY_SEPARATOR.'Docs'.DIRECTORY_SEPARATOR, + $file + ); + $docFile = str_replace('Sniff.php', 'Standard.xml', $docFile); + + if (is_file($docFile) === true) { + $this->docFiles[] = $docFile; + } + } + + }//end __construct() + + + /** + * Retrieves the title of the sniff from the DOMNode supplied. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return string + */ + protected function getTitle(\DOMNode $doc) + { + return $doc->getAttribute('title'); + + }//end getTitle() + + + /** + * Generates the documentation for a standard. + * + * It's probably wise for doc generators to override this method so they + * have control over how the docs are produced. Otherwise, the processSniff + * method should be overridden to output content for each sniff. + * + * @return void + * @see processSniff() + */ + public function generate() + { + foreach ($this->docFiles as $file) { + $doc = new \DOMDocument(); + $doc->load($file); + $documentation = $doc->getElementsByTagName('documentation')->item(0); + $this->processSniff($documentation); + } + + }//end generate() + + + /** + * Process the documentation for a single sniff. + * + * Doc generators must implement this function to produce output. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + * @see generate() + */ + abstract protected function processSniff(\DOMNode $doc); + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Generators/HTML.php b/vendor/squizlabs/php_codesniffer/src/Generators/HTML.php new file mode 100644 index 00000000..db264684 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Generators/HTML.php @@ -0,0 +1,270 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Generators; + +use PHP_CodeSniffer\Config; + +class HTML extends Generator +{ + + + /** + * Generates the documentation for a standard. + * + * @return void + * @see processSniff() + */ + public function generate() + { + ob_start(); + $this->printHeader(); + $this->printToc(); + + foreach ($this->docFiles as $file) { + $doc = new \DOMDocument(); + $doc->load($file); + $documentation = $doc->getElementsByTagName('documentation')->item(0); + $this->processSniff($documentation); + } + + $this->printFooter(); + + $content = ob_get_contents(); + ob_end_clean(); + + echo $content; + + }//end generate() + + + /** + * Print the header of the HTML page. + * + * @return void + */ + protected function printHeader() + { + $standard = $this->ruleset->name; + echo ''.PHP_EOL; + echo ' '.PHP_EOL; + echo " $standard Coding Standards".PHP_EOL; + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo "

    $standard Coding Standards

    ".PHP_EOL; + + }//end printHeader() + + + /** + * Print the table of contents for the standard. + * + * The TOC is just an unordered list of bookmarks to sniffs on the page. + * + * @return void + */ + protected function printToc() + { + echo '

    Table of Contents

    '.PHP_EOL; + echo '
      '.PHP_EOL; + + foreach ($this->docFiles as $file) { + $doc = new \DOMDocument(); + $doc->load($file); + $documentation = $doc->getElementsByTagName('documentation')->item(0); + $title = $this->getTitle($documentation); + echo '
    • $title
    • ".PHP_EOL; + } + + echo '
    '.PHP_EOL; + + }//end printToc() + + + /** + * Print the footer of the HTML page. + * + * @return void + */ + protected function printFooter() + { + // Turn off errors so we don't get timezone warnings if people + // don't have their timezone set. + $errorLevel = error_reporting(0); + echo '
    '; + echo 'Documentation generated on '.date('r'); + echo ' by PHP_CodeSniffer '.Config::VERSION.''; + echo '
    '.PHP_EOL; + error_reporting($errorLevel); + + echo ' '.PHP_EOL; + echo ''.PHP_EOL; + + }//end printFooter() + + + /** + * Process the documentation for a single sniff. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + */ + public function processSniff(\DOMNode $doc) + { + $title = $this->getTitle($doc); + echo ' '.PHP_EOL; + echo "

    $title

    ".PHP_EOL; + + foreach ($doc->childNodes as $node) { + if ($node->nodeName === 'standard') { + $this->printTextBlock($node); + } else if ($node->nodeName === 'code_comparison') { + $this->printCodeComparisonBlock($node); + } + } + + }//end processSniff() + + + /** + * Print a text block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the text block. + * + * @return void + */ + protected function printTextBlock(\DOMNode $node) + { + $content = trim($node->nodeValue); + $content = htmlspecialchars($content); + + // Allow em tags only. + $content = str_replace('<em>', '', $content); + $content = str_replace('</em>', '', $content); + + echo "

    $content

    ".PHP_EOL; + + }//end printTextBlock() + + + /** + * Print a code comparison block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the code comparison block. + * + * @return void + */ + protected function printCodeComparisonBlock(\DOMNode $node) + { + $codeBlocks = $node->getElementsByTagName('code'); + + $firstTitle = $codeBlocks->item(0)->getAttribute('title'); + $first = trim($codeBlocks->item(0)->nodeValue); + $first = str_replace('', $first); + $first = str_replace(' ', ' ', $first); + $first = str_replace('', '', $first); + $first = str_replace('', '', $first); + + $secondTitle = $codeBlocks->item(1)->getAttribute('title'); + $second = trim($codeBlocks->item(1)->nodeValue); + $second = str_replace('', $second); + $second = str_replace(' ', ' ', $second); + $second = str_replace('', '', $second); + $second = str_replace('', '', $second); + + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo " ".PHP_EOL; + echo " ".PHP_EOL; + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo " ".PHP_EOL; + echo " ".PHP_EOL; + echo ' '.PHP_EOL; + echo '
    $firstTitle$secondTitle
    $first$second
    '.PHP_EOL; + + }//end printCodeComparisonBlock() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Generators/Markdown.php b/vendor/squizlabs/php_codesniffer/src/Generators/Markdown.php new file mode 100644 index 00000000..9756bcf1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Generators/Markdown.php @@ -0,0 +1,161 @@ + + * @copyright 2014 Arroba IT + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Generators; + +use PHP_CodeSniffer\Config; + +class Markdown extends Generator +{ + + + /** + * Generates the documentation for a standard. + * + * @return void + * @see processSniff() + */ + public function generate() + { + ob_start(); + $this->printHeader(); + + foreach ($this->docFiles as $file) { + $doc = new \DOMDocument(); + $doc->load($file); + $documentation = $doc->getElementsByTagName('documentation')->item(0); + $this->processSniff($documentation); + } + + $this->printFooter(); + $content = ob_get_contents(); + ob_end_clean(); + + echo $content; + + }//end generate() + + + /** + * Print the markdown header. + * + * @return void + */ + protected function printHeader() + { + $standard = $this->ruleset->name; + + echo "# $standard Coding Standard".PHP_EOL; + + }//end printHeader() + + + /** + * Print the markdown footer. + * + * @return void + */ + protected function printFooter() + { + // Turn off errors so we don't get timezone warnings if people + // don't have their timezone set. + error_reporting(0); + echo 'Documentation generated on '.date('r'); + echo ' by [PHP_CodeSniffer '.Config::VERSION.'](https://github.com/squizlabs/PHP_CodeSniffer)'.PHP_EOL; + + }//end printFooter() + + + /** + * Process the documentation for a single sniff. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + */ + protected function processSniff(\DOMNode $doc) + { + $title = $this->getTitle($doc); + echo PHP_EOL."## $title".PHP_EOL; + + foreach ($doc->childNodes as $node) { + if ($node->nodeName === 'standard') { + $this->printTextBlock($node); + } else if ($node->nodeName === 'code_comparison') { + $this->printCodeComparisonBlock($node); + } + } + + }//end processSniff() + + + /** + * Print a text block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the text block. + * + * @return void + */ + protected function printTextBlock(\DOMNode $node) + { + $content = trim($node->nodeValue); + $content = htmlspecialchars($content); + + $content = str_replace('<em>', '*', $content); + $content = str_replace('</em>', '*', $content); + + echo $content.PHP_EOL; + + }//end printTextBlock() + + + /** + * Print a code comparison block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the code comparison block. + * + * @return void + */ + protected function printCodeComparisonBlock(\DOMNode $node) + { + $codeBlocks = $node->getElementsByTagName('code'); + + $firstTitle = $codeBlocks->item(0)->getAttribute('title'); + $first = trim($codeBlocks->item(0)->nodeValue); + $first = str_replace("\n", "\n ", $first); + $first = str_replace('', '', $first); + $first = str_replace('', '', $first); + + $secondTitle = $codeBlocks->item(1)->getAttribute('title'); + $second = trim($codeBlocks->item(1)->nodeValue); + $second = str_replace("\n", "\n ", $second); + $second = str_replace('', '', $second); + $second = str_replace('', '', $second); + + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo " ".PHP_EOL; + echo " ".PHP_EOL; + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo ''.PHP_EOL; + echo ''.PHP_EOL; + echo ' '.PHP_EOL; + echo '
    $firstTitle$secondTitle
    '.PHP_EOL.PHP_EOL; + echo " $first".PHP_EOL.PHP_EOL; + echo ''.PHP_EOL.PHP_EOL; + echo " $second".PHP_EOL.PHP_EOL; + echo '
    '.PHP_EOL; + + }//end printCodeComparisonBlock() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Generators/Text.php b/vendor/squizlabs/php_codesniffer/src/Generators/Text.php new file mode 100644 index 00000000..ffff206a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Generators/Text.php @@ -0,0 +1,253 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Generators; + +class Text extends Generator +{ + + + /** + * Process the documentation for a single sniff. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + */ + public function processSniff(\DOMNode $doc) + { + $this->printTitle($doc); + + foreach ($doc->childNodes as $node) { + if ($node->nodeName === 'standard') { + $this->printTextBlock($node); + } else if ($node->nodeName === 'code_comparison') { + $this->printCodeComparisonBlock($node); + } + } + + }//end processSniff() + + + /** + * Prints the title area for a single sniff. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + */ + protected function printTitle(\DOMNode $doc) + { + $title = $this->getTitle($doc); + $standard = $this->ruleset->name; + + echo PHP_EOL; + echo str_repeat('-', (strlen("$standard CODING STANDARD: $title") + 4)); + echo strtoupper(PHP_EOL."| $standard CODING STANDARD: $title |".PHP_EOL); + echo str_repeat('-', (strlen("$standard CODING STANDARD: $title") + 4)); + echo PHP_EOL.PHP_EOL; + + }//end printTitle() + + + /** + * Print a text block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the text block. + * + * @return void + */ + protected function printTextBlock(\DOMNode $node) + { + $text = trim($node->nodeValue); + $text = str_replace('', '*', $text); + $text = str_replace('', '*', $text); + + $nodeLines = explode("\n", $text); + $lines = []; + + foreach ($nodeLines as $currentLine) { + $currentLine = trim($currentLine); + if ($currentLine === '') { + // The text contained a blank line. Respect this. + $lines[] = ''; + continue; + } + + $tempLine = ''; + $words = explode(' ', $currentLine); + + foreach ($words as $word) { + $currentLength = strlen($tempLine.$word); + if ($currentLength < 99) { + $tempLine .= $word.' '; + continue; + } + + if ($currentLength === 99 || $currentLength === 100) { + // We are already at the edge, so we are done. + $lines[] = $tempLine.$word; + $tempLine = ''; + } else { + $lines[] = rtrim($tempLine); + $tempLine = $word.' '; + } + }//end foreach + + if ($tempLine !== '') { + $lines[] = rtrim($tempLine); + } + }//end foreach + + echo implode(PHP_EOL, $lines).PHP_EOL.PHP_EOL; + + }//end printTextBlock() + + + /** + * Print a code comparison block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the code comparison block. + * + * @return void + */ + protected function printCodeComparisonBlock(\DOMNode $node) + { + $codeBlocks = $node->getElementsByTagName('code'); + $first = trim($codeBlocks->item(0)->nodeValue); + $firstTitle = $codeBlocks->item(0)->getAttribute('title'); + + $firstTitleLines = []; + $tempTitle = ''; + $words = explode(' ', $firstTitle); + + foreach ($words as $word) { + if (strlen($tempTitle.$word) >= 45) { + if (strlen($tempTitle.$word) === 45) { + // Adding the extra space will push us to the edge + // so we are done. + $firstTitleLines[] = $tempTitle.$word; + $tempTitle = ''; + } else if (strlen($tempTitle.$word) === 46) { + // We are already at the edge, so we are done. + $firstTitleLines[] = $tempTitle.$word; + $tempTitle = ''; + } else { + $firstTitleLines[] = $tempTitle; + $tempTitle = $word.' '; + } + } else { + $tempTitle .= $word.' '; + } + }//end foreach + + if ($tempTitle !== '') { + $firstTitleLines[] = $tempTitle; + } + + $first = str_replace('', '', $first); + $first = str_replace('', '', $first); + $firstLines = explode("\n", $first); + + $second = trim($codeBlocks->item(1)->nodeValue); + $secondTitle = $codeBlocks->item(1)->getAttribute('title'); + + $secondTitleLines = []; + $tempTitle = ''; + $words = explode(' ', $secondTitle); + + foreach ($words as $word) { + if (strlen($tempTitle.$word) >= 45) { + if (strlen($tempTitle.$word) === 45) { + // Adding the extra space will push us to the edge + // so we are done. + $secondTitleLines[] = $tempTitle.$word; + $tempTitle = ''; + } else if (strlen($tempTitle.$word) === 46) { + // We are already at the edge, so we are done. + $secondTitleLines[] = $tempTitle.$word; + $tempTitle = ''; + } else { + $secondTitleLines[] = $tempTitle; + $tempTitle = $word.' '; + } + } else { + $tempTitle .= $word.' '; + } + }//end foreach + + if ($tempTitle !== '') { + $secondTitleLines[] = $tempTitle; + } + + $second = str_replace('', '', $second); + $second = str_replace('', '', $second); + $secondLines = explode("\n", $second); + + $maxCodeLines = max(count($firstLines), count($secondLines)); + $maxTitleLines = max(count($firstTitleLines), count($secondTitleLines)); + + echo str_repeat('-', 41); + echo ' CODE COMPARISON '; + echo str_repeat('-', 42).PHP_EOL; + + for ($i = 0; $i < $maxTitleLines; $i++) { + if (isset($firstTitleLines[$i]) === true) { + $firstLineText = $firstTitleLines[$i]; + } else { + $firstLineText = ''; + } + + if (isset($secondTitleLines[$i]) === true) { + $secondLineText = $secondTitleLines[$i]; + } else { + $secondLineText = ''; + } + + echo '| '; + echo $firstLineText.str_repeat(' ', (46 - strlen($firstLineText))); + echo ' | '; + echo $secondLineText.str_repeat(' ', (47 - strlen($secondLineText))); + echo ' |'.PHP_EOL; + }//end for + + echo str_repeat('-', 100).PHP_EOL; + + for ($i = 0; $i < $maxCodeLines; $i++) { + if (isset($firstLines[$i]) === true) { + $firstLineText = $firstLines[$i]; + } else { + $firstLineText = ''; + } + + if (isset($secondLines[$i]) === true) { + $secondLineText = $secondLines[$i]; + } else { + $secondLineText = ''; + } + + echo '| '; + echo $firstLineText.str_repeat(' ', max(0, (47 - strlen($firstLineText)))); + echo '| '; + echo $secondLineText.str_repeat(' ', max(0, (48 - strlen($secondLineText)))); + echo '|'.PHP_EOL; + }//end for + + echo str_repeat('-', 100).PHP_EOL.PHP_EOL; + + }//end printCodeComparisonBlock() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reporter.php b/vendor/squizlabs/php_codesniffer/src/Reporter.php new file mode 100644 index 00000000..e89a20ed --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reporter.php @@ -0,0 +1,423 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use PHP_CodeSniffer\Exceptions\DeepExitException; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Reports\Report; +use PHP_CodeSniffer\Util\Common; + +class Reporter +{ + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + public $config = null; + + /** + * Total number of files that contain errors or warnings. + * + * @var integer + */ + public $totalFiles = 0; + + /** + * Total number of errors found during the run. + * + * @var integer + */ + public $totalErrors = 0; + + /** + * Total number of warnings found during the run. + * + * @var integer + */ + public $totalWarnings = 0; + + /** + * Total number of errors/warnings that can be fixed. + * + * @var integer + */ + public $totalFixable = 0; + + /** + * Total number of errors/warnings that were fixed. + * + * @var integer + */ + public $totalFixed = 0; + + /** + * When the PHPCS run started. + * + * @var float + */ + public static $startTime = 0; + + /** + * A cache of report objects. + * + * @var array + */ + private $reports = []; + + /** + * A cache of opened temporary files. + * + * @var array + */ + private $tmpFiles = []; + + + /** + * Initialise the reporter. + * + * All reports specified in the config will be created and their + * output file (or a temp file if none is specified) initialised by + * clearing the current contents. + * + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If a custom report class could not be found. + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If a report class is incorrectly set up. + */ + public function __construct(Config $config) + { + $this->config = $config; + + foreach ($config->reports as $type => $output) { + if ($output === null) { + $output = $config->reportFile; + } + + $reportClassName = ''; + if (strpos($type, '.') !== false) { + // This is a path to a custom report class. + $filename = realpath($type); + if ($filename === false) { + $error = "ERROR: Custom report \"$type\" not found".PHP_EOL; + throw new DeepExitException($error, 3); + } + + $reportClassName = Autoload::loadFile($filename); + } else if (class_exists('PHP_CodeSniffer\Reports\\'.ucfirst($type)) === true) { + // PHPCS native report. + $reportClassName = 'PHP_CodeSniffer\Reports\\'.ucfirst($type); + } else if (class_exists($type) === true) { + // FQN of a custom report. + $reportClassName = $type; + } else { + // OK, so not a FQN, try and find the report using the registered namespaces. + $registeredNamespaces = Autoload::getSearchPaths(); + $trimmedType = ltrim($type, '\\'); + + foreach ($registeredNamespaces as $nsPrefix) { + if ($nsPrefix === '') { + continue; + } + + if (class_exists($nsPrefix.'\\'.$trimmedType) === true) { + $reportClassName = $nsPrefix.'\\'.$trimmedType; + break; + } + } + }//end if + + if ($reportClassName === '') { + $error = "ERROR: Class file for report \"$type\" not found".PHP_EOL; + throw new DeepExitException($error, 3); + } + + $reportClass = new $reportClassName(); + if (($reportClass instanceof Report) === false) { + throw new RuntimeException('Class "'.$reportClassName.'" must implement the "PHP_CodeSniffer\Report" interface.'); + } + + $this->reports[$type] = [ + 'output' => $output, + 'class' => $reportClass, + ]; + + if ($output === null) { + // Using a temp file. + // This needs to be set in the constructor so that all + // child procs use the same report file when running in parallel. + $this->tmpFiles[$type] = tempnam(sys_get_temp_dir(), 'phpcs'); + file_put_contents($this->tmpFiles[$type], ''); + } else { + file_put_contents($output, ''); + } + }//end foreach + + }//end __construct() + + + /** + * Generates and prints final versions of all reports. + * + * Returns TRUE if any of the reports output content to the screen + * or FALSE if all reports were silently printed to a file. + * + * @return bool + */ + public function printReports() + { + $toScreen = false; + foreach ($this->reports as $type => $report) { + if ($report['output'] === null) { + $toScreen = true; + } + + $this->printReport($type); + } + + return $toScreen; + + }//end printReports() + + + /** + * Generates and prints a single final report. + * + * @param string $report The report type to print. + * + * @return void + */ + public function printReport($report) + { + $reportClass = $this->reports[$report]['class']; + $reportFile = $this->reports[$report]['output']; + + if ($reportFile !== null) { + $filename = $reportFile; + $toScreen = false; + } else { + if (isset($this->tmpFiles[$report]) === true) { + $filename = $this->tmpFiles[$report]; + } else { + $filename = null; + } + + $toScreen = true; + } + + $reportCache = ''; + if ($filename !== null) { + $reportCache = file_get_contents($filename); + } + + ob_start(); + $reportClass->generate( + $reportCache, + $this->totalFiles, + $this->totalErrors, + $this->totalWarnings, + $this->totalFixable, + $this->config->showSources, + $this->config->reportWidth, + $this->config->interactive, + $toScreen + ); + $generatedReport = ob_get_contents(); + ob_end_clean(); + + if ($this->config->colors !== true || $reportFile !== null) { + $generatedReport = preg_replace('`\033\[[0-9;]+m`', '', $generatedReport); + } + + if ($reportFile !== null) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo $generatedReport; + } + + file_put_contents($reportFile, $generatedReport.PHP_EOL); + } else { + echo $generatedReport; + if ($filename !== null && file_exists($filename) === true) { + unlink($filename); + unset($this->tmpFiles[$report]); + } + } + + }//end printReport() + + + /** + * Caches the result of a single processed file for all reports. + * + * The report content that is generated is appended to the output file + * assigned to each report. This content may be an intermediate report format + * and not reflect the final report output. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file that has been processed. + * + * @return void + */ + public function cacheFileReport(File $phpcsFile) + { + if (isset($this->config->reports) === false) { + // This happens during unit testing, or any time someone just wants + // the error data and not the printed report. + return; + } + + $reportData = $this->prepareFileReport($phpcsFile); + $errorsShown = false; + + foreach ($this->reports as $type => $report) { + $reportClass = $report['class']; + + ob_start(); + $result = $reportClass->generateFileReport($reportData, $phpcsFile, $this->config->showSources, $this->config->reportWidth); + if ($result === true) { + $errorsShown = true; + } + + $generatedReport = ob_get_contents(); + ob_end_clean(); + + if ($report['output'] === null) { + // Using a temp file. + if (isset($this->tmpFiles[$type]) === false) { + // When running in interactive mode, the reporter prints the full + // report many times, which will unlink the temp file. So we need + // to create a new one if it doesn't exist. + $this->tmpFiles[$type] = tempnam(sys_get_temp_dir(), 'phpcs'); + file_put_contents($this->tmpFiles[$type], ''); + } + + file_put_contents($this->tmpFiles[$type], $generatedReport, (FILE_APPEND | LOCK_EX)); + } else { + file_put_contents($report['output'], $generatedReport, (FILE_APPEND | LOCK_EX)); + }//end if + }//end foreach + + if ($errorsShown === true || PHP_CODESNIFFER_CBF === true) { + $this->totalFiles++; + $this->totalErrors += $reportData['errors']; + $this->totalWarnings += $reportData['warnings']; + + // When PHPCBF is running, we need to use the fixable error values + // after the report has run and fixed what it can. + if (PHP_CODESNIFFER_CBF === true) { + $this->totalFixable += $phpcsFile->getFixableCount(); + $this->totalFixed += $phpcsFile->getFixedCount(); + } else { + $this->totalFixable += $reportData['fixable']; + } + } + + }//end cacheFileReport() + + + /** + * Generate summary information to be used during report generation. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file that has been processed. + * + * @return array + */ + public function prepareFileReport(File $phpcsFile) + { + $report = [ + 'filename' => Common::stripBasepath($phpcsFile->getFilename(), $this->config->basepath), + 'errors' => $phpcsFile->getErrorCount(), + 'warnings' => $phpcsFile->getWarningCount(), + 'fixable' => $phpcsFile->getFixableCount(), + 'messages' => [], + ]; + + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Prefect score! + return $report; + } + + if ($this->config->recordErrors === false) { + $message = 'Errors are not being recorded but this report requires error messages. '; + $message .= 'This report will not show the correct information.'; + $report['messages'][1][1] = [ + [ + 'message' => $message, + 'source' => 'Internal.RecordErrors', + 'severity' => 5, + 'fixable' => false, + 'type' => 'ERROR', + ], + ]; + return $report; + } + + $errors = []; + + // Merge errors and warnings. + foreach ($phpcsFile->getErrors() as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + $newErrors = []; + foreach ($colErrors as $data) { + $newErrors[] = [ + 'message' => $data['message'], + 'source' => $data['source'], + 'severity' => $data['severity'], + 'fixable' => $data['fixable'], + 'type' => 'ERROR', + ]; + } + + $errors[$line][$column] = $newErrors; + } + + ksort($errors[$line]); + }//end foreach + + foreach ($phpcsFile->getWarnings() as $line => $lineWarnings) { + foreach ($lineWarnings as $column => $colWarnings) { + $newWarnings = []; + foreach ($colWarnings as $data) { + $newWarnings[] = [ + 'message' => $data['message'], + 'source' => $data['source'], + 'severity' => $data['severity'], + 'fixable' => $data['fixable'], + 'type' => 'WARNING', + ]; + } + + if (isset($errors[$line]) === false) { + $errors[$line] = []; + } + + if (isset($errors[$line][$column]) === true) { + $errors[$line][$column] = array_merge( + $newWarnings, + $errors[$line][$column] + ); + } else { + $errors[$line][$column] = $newWarnings; + } + }//end foreach + + ksort($errors[$line]); + }//end foreach + + ksort($errors); + $report['messages'] = $errors; + return $report; + + }//end prepareFileReport() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Cbf.php b/vendor/squizlabs/php_codesniffer/src/Reports/Cbf.php new file mode 100644 index 00000000..0ecde76e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Cbf.php @@ -0,0 +1,253 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Exceptions\DeepExitException; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util; + +class Cbf implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $errors = $phpcsFile->getFixableCount(); + if ($errors !== 0) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + ob_end_clean(); + $startTime = microtime(true); + echo "\t=> Fixing file: $errors/$errors violations remaining"; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + $fixed = $phpcsFile->fixer->fixFile(); + } + + if ($phpcsFile->config->stdin === true) { + // Replacing STDIN, so output current file to STDOUT + // even if nothing was fixed. Exit here because we + // can't process any more than 1 file in this setup. + $fixedContent = $phpcsFile->fixer->getContents(); + throw new DeepExitException($fixedContent, 1); + } + + if ($errors === 0) { + return false; + } + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + if ($fixed === false) { + echo 'ERROR'; + } else { + echo 'DONE'; + } + + $timeTaken = ((microtime(true) - $startTime) * 1000); + if ($timeTaken < 1000) { + $timeTaken = round($timeTaken); + echo " in {$timeTaken}ms".PHP_EOL; + } else { + $timeTaken = round(($timeTaken / 1000), 2); + echo " in $timeTaken secs".PHP_EOL; + } + } + + if ($fixed === true) { + // The filename in the report may be truncated due to a basepath setting + // but we are using it for writing here and not display, + // so find the correct path if basepath is in use. + $newFilename = $report['filename'].$phpcsFile->config->suffix; + if ($phpcsFile->config->basepath !== null) { + $newFilename = $phpcsFile->config->basepath.DIRECTORY_SEPARATOR.$newFilename; + } + + $newContent = $phpcsFile->fixer->getContents(); + file_put_contents($newFilename, $newContent); + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + if ($newFilename === $report['filename']) { + echo "\t=> File was overwritten".PHP_EOL; + } else { + echo "\t=> Fixed file written to ".basename($newFilename).PHP_EOL; + } + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + ob_start(); + } + + $errorCount = $phpcsFile->getErrorCount(); + $warningCount = $phpcsFile->getWarningCount(); + $fixableCount = $phpcsFile->getFixableCount(); + $fixedCount = ($errors - $fixableCount); + echo $report['filename'].">>$errorCount>>$warningCount>>$fixableCount>>$fixedCount".PHP_EOL; + + return $fixed; + + }//end generateFileReport() + + + /** + * Prints a summary of fixed files. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + echo PHP_EOL.'No fixable errors were found'.PHP_EOL; + return; + } + + $reportFiles = []; + $maxLength = 0; + $totalFixed = 0; + $failures = 0; + + foreach ($lines as $line) { + $parts = explode('>>', $line); + $fileLen = strlen($parts[0]); + $reportFiles[$parts[0]] = [ + 'errors' => $parts[1], + 'warnings' => $parts[2], + 'fixable' => $parts[3], + 'fixed' => $parts[4], + 'strlen' => $fileLen, + ]; + + $maxLength = max($maxLength, $fileLen); + + $totalFixed += $parts[4]; + + if ($parts[3] > 0) { + $failures++; + } + } + + $width = min($width, ($maxLength + 21)); + $width = max($width, 70); + + echo PHP_EOL."\033[1m".'PHPCBF RESULT SUMMARY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1m".'FILE'.str_repeat(' ', ($width - 20)).'FIXED REMAINING'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + foreach ($reportFiles as $file => $data) { + $padding = ($width - 18 - $data['strlen']); + if ($padding < 0) { + $file = '...'.substr($file, (($padding * -1) + 3)); + $padding = 0; + } + + echo $file.str_repeat(' ', $padding).' '; + + if ($data['fixable'] > 0) { + echo "\033[31mFAILED TO FIX\033[0m".PHP_EOL; + continue; + } + + $remaining = ($data['errors'] + $data['warnings']); + + if ($data['fixed'] !== 0) { + echo $data['fixed']; + echo str_repeat(' ', (7 - strlen((string) $data['fixed']))); + } else { + echo '0 '; + } + + if ($remaining !== 0) { + echo $remaining; + } else { + echo '0'; + } + + echo PHP_EOL; + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1mA TOTAL OF $totalFixed ERROR"; + if ($totalFixed !== 1) { + echo 'S'; + } + + $numFiles = count($reportFiles); + echo ' WERE FIXED IN '.$numFiles.' FILE'; + if ($numFiles !== 1) { + echo 'S'; + } + + echo "\033[0m"; + + if ($failures > 0) { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF FAILED TO FIX $failures FILE"; + if ($failures !== 1) { + echo 'S'; + } + + echo "\033[0m"; + } + + echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Util\Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Checkstyle.php b/vendor/squizlabs/php_codesniffer/src/Reports/Checkstyle.php new file mode 100644 index 00000000..06a78e19 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Checkstyle.php @@ -0,0 +1,109 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; + +class Checkstyle implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $out = new \XMLWriter; + $out->openMemory(); + $out->setIndent(true); + + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + $out->startElement('file'); + $out->writeAttribute('name', $report['filename']); + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $error['type'] = strtolower($error['type']); + if ($phpcsFile->config->encoding !== 'utf-8') { + $error['message'] = iconv($phpcsFile->config->encoding, 'utf-8', $error['message']); + } + + $out->startElement('error'); + $out->writeAttribute('line', $line); + $out->writeAttribute('column', $column); + $out->writeAttribute('severity', $error['type']); + $out->writeAttribute('message', $error['message']); + $out->writeAttribute('source', $error['source']); + $out->endElement(); + } + } + }//end foreach + + $out->endElement(); + echo $out->flush(); + + return true; + + }//end generateFileReport() + + + /** + * Prints all violations for processed files, in a Checkstyle format. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo ''.PHP_EOL; + echo ''.PHP_EOL; + echo $cachedData; + echo ''.PHP_EOL; + + }//end generate() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Code.php b/vendor/squizlabs/php_codesniffer/src/Reports/Code.php new file mode 100644 index 00000000..47c5581e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Code.php @@ -0,0 +1,362 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util; + +class Code implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + // How many lines to show about and below the error line. + $surroundingLines = 2; + + $file = $report['filename']; + $tokens = $phpcsFile->getTokens(); + if (empty($tokens) === true) { + if (PHP_CODESNIFFER_VERBOSITY === 1) { + $startTime = microtime(true); + echo 'CODE report is parsing '.basename($file).' '; + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "CODE report is forcing parse of $file".PHP_EOL; + } + + try { + $phpcsFile->parse(); + } catch (\Exception $e) { + // This is a second parse, so ignore exceptions. + // They would have been added to the file's error list already. + } + + if (PHP_CODESNIFFER_VERBOSITY === 1) { + $timeTaken = ((microtime(true) - $startTime) * 1000); + if ($timeTaken < 1000) { + $timeTaken = round($timeTaken); + echo "DONE in {$timeTaken}ms"; + } else { + $timeTaken = round(($timeTaken / 1000), 2); + echo "DONE in $timeTaken secs"; + } + + echo PHP_EOL; + } + + $tokens = $phpcsFile->getTokens(); + }//end if + + // Create an array that maps lines to the first token on the line. + $lineTokens = []; + $lastLine = 0; + $stackPtr = 0; + foreach ($tokens as $stackPtr => $token) { + if ($token['line'] !== $lastLine) { + if ($lastLine > 0) { + $lineTokens[$lastLine]['end'] = ($stackPtr - 1); + } + + $lastLine++; + $lineTokens[$lastLine] = [ + 'start' => $stackPtr, + 'end' => null, + ]; + } + } + + // Make sure the last token in the file sits on an imaginary + // last line so it is easier to generate code snippets at the + // end of the file. + $lineTokens[$lastLine]['end'] = $stackPtr; + + // Determine the longest code line we will be showing. + $maxSnippetLength = 0; + $eolLen = strlen($phpcsFile->eolChar); + foreach ($report['messages'] as $line => $lineErrors) { + $startLine = max(($line - $surroundingLines), 1); + $endLine = min(($line + $surroundingLines), $lastLine); + + $maxLineNumLength = strlen($endLine); + + for ($i = $startLine; $i <= $endLine; $i++) { + if ($i === 1) { + continue; + } + + $lineLength = ($tokens[($lineTokens[$i]['start'] - 1)]['column'] + $tokens[($lineTokens[$i]['start'] - 1)]['length'] - $eolLen); + $maxSnippetLength = max($lineLength, $maxSnippetLength); + } + } + + $maxSnippetLength += ($maxLineNumLength + 8); + + // Determine the longest error message we will be showing. + $maxErrorLength = 0; + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $length = strlen($error['message']); + if ($showSources === true) { + $length += (strlen($error['source']) + 3); + } + + $maxErrorLength = max($maxErrorLength, ($length + 1)); + } + } + } + + // The padding that all lines will require that are printing an error message overflow. + if ($report['warnings'] > 0) { + $typeLength = 7; + } else { + $typeLength = 5; + } + + $errorPadding = str_repeat(' ', ($maxLineNumLength + 7)); + $errorPadding .= str_repeat(' ', $typeLength); + $errorPadding .= ' '; + if ($report['fixable'] > 0) { + $errorPadding .= ' '; + } + + $errorPaddingLength = strlen($errorPadding); + + // The maximum amount of space an error message can use. + $maxErrorSpace = ($width - $errorPaddingLength); + if ($showSources === true) { + // Account for the chars used to print colors. + $maxErrorSpace += 8; + } + + // Figure out the max report width we need and can use. + $fileLength = strlen($file); + $maxWidth = max(($fileLength + 6), ($maxErrorLength + $errorPaddingLength)); + $width = max(min($width, $maxWidth), $maxSnippetLength); + if ($width < 70) { + $width = 70; + } + + // Print the file header. + echo PHP_EOL."\033[1mFILE: "; + if ($fileLength <= ($width - 6)) { + echo $file; + } else { + echo '...'.substr($file, ($fileLength - ($width - 6))); + } + + echo "\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + echo "\033[1m".'FOUND '.$report['errors'].' ERROR'; + if ($report['errors'] !== 1) { + echo 'S'; + } + + if ($report['warnings'] > 0) { + echo ' AND '.$report['warnings'].' WARNING'; + if ($report['warnings'] !== 1) { + echo 'S'; + } + } + + echo ' AFFECTING '.count($report['messages']).' LINE'; + if (count($report['messages']) !== 1) { + echo 'S'; + } + + echo "\033[0m".PHP_EOL; + + foreach ($report['messages'] as $line => $lineErrors) { + $startLine = max(($line - $surroundingLines), 1); + $endLine = min(($line + $surroundingLines), $lastLine); + + $snippet = ''; + if (isset($lineTokens[$startLine]) === true) { + for ($i = $lineTokens[$startLine]['start']; $i <= $lineTokens[$endLine]['end']; $i++) { + $snippetLine = $tokens[$i]['line']; + if ($lineTokens[$snippetLine]['start'] === $i) { + // Starting a new line. + if ($snippetLine === $line) { + $snippet .= "\033[1m".'>> '; + } else { + $snippet .= ' '; + } + + $snippet .= str_repeat(' ', ($maxLineNumLength - strlen($snippetLine))); + $snippet .= $snippetLine.': '; + if ($snippetLine === $line) { + $snippet .= "\033[0m"; + } + } + + if (isset($tokens[$i]['orig_content']) === true) { + $tokenContent = $tokens[$i]['orig_content']; + } else { + $tokenContent = $tokens[$i]['content']; + } + + if (strpos($tokenContent, "\t") !== false) { + $token = $tokens[$i]; + $token['content'] = $tokenContent; + if (stripos(PHP_OS, 'WIN') === 0) { + $tab = "\000"; + } else { + $tab = "\033[30;1m»\033[0m"; + } + + $phpcsFile->tokenizer->replaceTabsInToken($token, $tab, "\000"); + $tokenContent = $token['content']; + } + + $tokenContent = Util\Common::prepareForOutput($tokenContent, ["\r", "\n", "\t"]); + $tokenContent = str_replace("\000", ' ', $tokenContent); + + $underline = false; + if ($snippetLine === $line && isset($lineErrors[$tokens[$i]['column']]) === true) { + $underline = true; + } + + // Underline invisible characters as well. + if ($underline === true && trim($tokenContent) === '') { + $snippet .= "\033[4m".' '."\033[0m".$tokenContent; + } else { + if ($underline === true) { + $snippet .= "\033[4m"; + } + + $snippet .= $tokenContent; + + if ($underline === true) { + $snippet .= "\033[0m"; + } + } + }//end for + }//end if + + echo str_repeat('-', $width).PHP_EOL; + + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $padding = ($maxLineNumLength - strlen($line)); + echo 'LINE '.str_repeat(' ', $padding).$line.': '; + + if ($error['type'] === 'ERROR') { + echo "\033[31mERROR\033[0m"; + if ($report['warnings'] > 0) { + echo ' '; + } + } else { + echo "\033[33mWARNING\033[0m"; + } + + echo ' '; + if ($report['fixable'] > 0) { + echo '['; + if ($error['fixable'] === true) { + echo 'x'; + } else { + echo ' '; + } + + echo '] '; + } + + $message = $error['message']; + $message = str_replace("\n", "\n".$errorPadding, $message); + if ($showSources === true) { + $message = "\033[1m".$message."\033[0m".' ('.$error['source'].')'; + } + + $errorMsg = wordwrap( + $message, + $maxErrorSpace, + PHP_EOL.$errorPadding + ); + + echo $errorMsg.PHP_EOL; + }//end foreach + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo rtrim($snippet).PHP_EOL; + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + if ($report['fixable'] > 0) { + echo "\033[1m".'PHPCBF CAN FIX THE '.$report['fixable'].' MARKED SNIFF VIOLATIONS AUTOMATICALLY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + } + + return true; + + }//end generateFileReport() + + + /** + * Prints all errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + if ($cachedData === '') { + return; + } + + echo $cachedData; + + if ($toScreen === true && $interactive === false) { + Util\Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Csv.php b/vendor/squizlabs/php_codesniffer/src/Reports/Csv.php new file mode 100644 index 00000000..6db7ecfc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Csv.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +class Csv implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $filename = str_replace('"', '\"', $report['filename']); + $message = str_replace('"', '\"', $error['message']); + $type = strtolower($error['type']); + $source = $error['source']; + $severity = $error['severity']; + $fixable = (int) $error['fixable']; + echo "\"$filename\",$line,$column,$type,\"$message\",$source,$severity,$fixable".PHP_EOL; + } + } + } + + return true; + + }//end generateFileReport() + + + /** + * Generates a csv report. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo 'File,Line,Column,Type,Message,Source,Severity,Fixable'.PHP_EOL; + echo $cachedData; + + }//end generate() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Diff.php b/vendor/squizlabs/php_codesniffer/src/Reports/Diff.php new file mode 100644 index 00000000..ce4b31fc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Diff.php @@ -0,0 +1,130 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +class Diff implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $errors = $phpcsFile->getFixableCount(); + if ($errors === 0) { + return false; + } + + $phpcsFile->disableCaching(); + $tokens = $phpcsFile->getTokens(); + if (empty($tokens) === true) { + if (PHP_CODESNIFFER_VERBOSITY === 1) { + $startTime = microtime(true); + echo 'DIFF report is parsing '.basename($report['filename']).' '; + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo 'DIFF report is forcing parse of '.$report['filename'].PHP_EOL; + } + + $phpcsFile->parse(); + + if (PHP_CODESNIFFER_VERBOSITY === 1) { + $timeTaken = ((microtime(true) - $startTime) * 1000); + if ($timeTaken < 1000) { + $timeTaken = round($timeTaken); + echo "DONE in {$timeTaken}ms"; + } else { + $timeTaken = round(($timeTaken / 1000), 2); + echo "DONE in $timeTaken secs"; + } + + echo PHP_EOL; + } + + $phpcsFile->fixer->startFile($phpcsFile); + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + ob_end_clean(); + echo "\t*** START FILE FIXING ***".PHP_EOL; + } + + $fixed = $phpcsFile->fixer->fixFile(); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END FILE FIXING ***".PHP_EOL; + ob_start(); + } + + if ($fixed === false) { + return false; + } + + $diff = $phpcsFile->fixer->generateDiff(); + if ($diff === '') { + // Nothing to print. + return false; + } + + echo $diff.PHP_EOL; + return true; + + }//end generateFileReport() + + + /** + * Prints all errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo $cachedData; + if ($toScreen === true && $cachedData !== '') { + echo PHP_EOL; + } + + }//end generate() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Emacs.php b/vendor/squizlabs/php_codesniffer/src/Reports/Emacs.php new file mode 100644 index 00000000..3555f554 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Emacs.php @@ -0,0 +1,90 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +class Emacs implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $message = $error['message']; + if ($showSources === true) { + $message .= ' ('.$error['source'].')'; + } + + $type = strtolower($error['type']); + echo $report['filename'].':'.$line.':'.$column.': '.$type.' - '.$message.PHP_EOL; + } + } + } + + return true; + + }//end generateFileReport() + + + /** + * Generates an emacs report. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo $cachedData; + + }//end generate() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Full.php b/vendor/squizlabs/php_codesniffer/src/Reports/Full.php new file mode 100644 index 00000000..084bc8aa --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Full.php @@ -0,0 +1,231 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util; + +class Full implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + // The length of the word ERROR or WARNING; used for padding. + if ($report['warnings'] > 0) { + $typeLength = 7; + } else { + $typeLength = 5; + } + + // Work out the max line number length for formatting. + $maxLineNumLength = max(array_map('strlen', array_keys($report['messages']))); + + // The padding that all lines will require that are + // printing an error message overflow. + $paddingLine2 = str_repeat(' ', ($maxLineNumLength + 1)); + $paddingLine2 .= ' | '; + $paddingLine2 .= str_repeat(' ', $typeLength); + $paddingLine2 .= ' | '; + if ($report['fixable'] > 0) { + $paddingLine2 .= ' '; + } + + $paddingLength = strlen($paddingLine2); + + // Make sure the report width isn't too big. + $maxErrorLength = 0; + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $length = strlen($error['message']); + if ($showSources === true) { + $length += (strlen($error['source']) + 3); + } + + $maxErrorLength = max($maxErrorLength, ($length + 1)); + } + } + } + + $file = $report['filename']; + $fileLength = strlen($file); + $maxWidth = max(($fileLength + 6), ($maxErrorLength + $paddingLength)); + $width = min($width, $maxWidth); + if ($width < 70) { + $width = 70; + } + + echo PHP_EOL."\033[1mFILE: "; + if ($fileLength <= ($width - 6)) { + echo $file; + } else { + echo '...'.substr($file, ($fileLength - ($width - 6))); + } + + echo "\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + echo "\033[1m".'FOUND '.$report['errors'].' ERROR'; + if ($report['errors'] !== 1) { + echo 'S'; + } + + if ($report['warnings'] > 0) { + echo ' AND '.$report['warnings'].' WARNING'; + if ($report['warnings'] !== 1) { + echo 'S'; + } + } + + echo ' AFFECTING '.count($report['messages']).' LINE'; + if (count($report['messages']) !== 1) { + echo 'S'; + } + + echo "\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + // The maximum amount of space an error message can use. + $maxErrorSpace = ($width - $paddingLength - 1); + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $message = $error['message']; + $msgLines = [$message]; + if (strpos($message, "\n") !== false) { + $msgLines = explode("\n", $message); + } + + $errorMsg = ''; + $lastLine = (count($msgLines) - 1); + foreach ($msgLines as $k => $msgLine) { + if ($k === 0) { + if ($showSources === true) { + $errorMsg .= "\033[1m"; + } + } else { + $errorMsg .= PHP_EOL.$paddingLine2; + } + + if ($k === $lastLine && $showSources === true) { + $msgLine .= "\033[0m".' ('.$error['source'].')'; + } + + $errorMsg .= wordwrap( + $msgLine, + $maxErrorSpace, + PHP_EOL.$paddingLine2 + ); + } + + // The padding that goes on the front of the line. + $padding = ($maxLineNumLength - strlen($line)); + + echo ' '.str_repeat(' ', $padding).$line.' | '; + if ($error['type'] === 'ERROR') { + echo "\033[31mERROR\033[0m"; + if ($report['warnings'] > 0) { + echo ' '; + } + } else { + echo "\033[33mWARNING\033[0m"; + } + + echo ' | '; + if ($report['fixable'] > 0) { + echo '['; + if ($error['fixable'] === true) { + echo 'x'; + } else { + echo ' '; + } + + echo '] '; + } + + echo $errorMsg.PHP_EOL; + }//end foreach + }//end foreach + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + if ($report['fixable'] > 0) { + echo "\033[1m".'PHPCBF CAN FIX THE '.$report['fixable'].' MARKED SNIFF VIOLATIONS AUTOMATICALLY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + } + + echo PHP_EOL; + return true; + + }//end generateFileReport() + + + /** + * Prints all errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + if ($cachedData === '') { + return; + } + + echo $cachedData; + + if ($toScreen === true && $interactive === false) { + Util\Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Gitblame.php b/vendor/squizlabs/php_codesniffer/src/Reports/Gitblame.php new file mode 100644 index 00000000..6427567f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Gitblame.php @@ -0,0 +1,91 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Exceptions\DeepExitException; + +class Gitblame extends VersionControl +{ + + /** + * The name of the report we want in the output + * + * @var string + */ + protected $reportName = 'GIT'; + + + /** + * Extract the author from a blame line. + * + * @param string $line Line to parse. + * + * @return mixed string or false if impossible to recover. + */ + protected function getAuthor($line) + { + $blameParts = []; + $line = preg_replace('|\s+|', ' ', $line); + preg_match( + '|\(.+[0-9]{4}-[0-9]{2}-[0-9]{2}\s+[0-9]+\)|', + $line, + $blameParts + ); + + if (isset($blameParts[0]) === false) { + return false; + } + + $parts = explode(' ', $blameParts[0]); + + if (count($parts) < 2) { + return false; + } + + $parts = array_slice($parts, 0, (count($parts) - 2)); + $author = preg_replace('|\(|', '', implode(' ', $parts)); + return $author; + + }//end getAuthor() + + + /** + * Gets the blame output. + * + * @param string $filename File to blame. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + protected function getBlameContent($filename) + { + $cwd = getcwd(); + + chdir(dirname($filename)); + $command = 'git blame --date=short "'.$filename.'" 2>&1'; + $handle = popen($command, 'r'); + if ($handle === false) { + $error = 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $rawContent = stream_get_contents($handle); + pclose($handle); + + $blames = explode("\n", $rawContent); + chdir($cwd); + + return $blames; + + }//end getBlameContent() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Hgblame.php b/vendor/squizlabs/php_codesniffer/src/Reports/Hgblame.php new file mode 100644 index 00000000..f88a0683 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Hgblame.php @@ -0,0 +1,110 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Exceptions\DeepExitException; + +class Hgblame extends VersionControl +{ + + /** + * The name of the report we want in the output + * + * @var string + */ + protected $reportName = 'MERCURIAL'; + + + /** + * Extract the author from a blame line. + * + * @param string $line Line to parse. + * + * @return mixed string or false if impossible to recover. + */ + protected function getAuthor($line) + { + $blameParts = []; + $line = preg_replace('|\s+|', ' ', $line); + + preg_match( + '|(.+[0-9]{2}:[0-9]{2}:[0-9]{2}\s[0-9]{4}\s.[0-9]{4}:)|', + $line, + $blameParts + ); + + if (isset($blameParts[0]) === false) { + return false; + } + + $parts = explode(' ', $blameParts[0]); + + if (count($parts) < 6) { + return false; + } + + $parts = array_slice($parts, 0, (count($parts) - 6)); + + return trim(preg_replace('|<.+>|', '', implode(' ', $parts))); + + }//end getAuthor() + + + /** + * Gets the blame output. + * + * @param string $filename File to blame. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + protected function getBlameContent($filename) + { + $cwd = getcwd(); + + $fileParts = explode(DIRECTORY_SEPARATOR, $filename); + $found = false; + $location = ''; + while (empty($fileParts) === false) { + array_pop($fileParts); + $location = implode(DIRECTORY_SEPARATOR, $fileParts); + if (is_dir($location.DIRECTORY_SEPARATOR.'.hg') === true) { + $found = true; + break; + } + } + + if ($found === true) { + chdir($location); + } else { + $error = 'ERROR: Could not locate .hg directory '.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $command = 'hg blame -u -d -v "'.$filename.'" 2>&1'; + $handle = popen($command, 'r'); + if ($handle === false) { + $error = 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $rawContent = stream_get_contents($handle); + pclose($handle); + + $blames = explode("\n", $rawContent); + chdir($cwd); + + return $blames; + + }//end getBlameContent() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Info.php b/vendor/squizlabs/php_codesniffer/src/Reports/Info.php new file mode 100644 index 00000000..3181bcc5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Info.php @@ -0,0 +1,172 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Timing; + +class Info implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $metrics = $phpcsFile->getMetrics(); + foreach ($metrics as $metric => $data) { + foreach ($data['values'] as $value => $count) { + echo "$metric>>$value>>$count".PHP_EOL; + } + } + + return true; + + }//end generateFileReport() + + + /** + * Prints the source of all errors and warnings. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + return; + } + + $metrics = []; + foreach ($lines as $line) { + $parts = explode('>>', $line); + $metric = $parts[0]; + $value = $parts[1]; + $count = $parts[2]; + if (isset($metrics[$metric]) === false) { + $metrics[$metric] = []; + } + + if (isset($metrics[$metric][$value]) === false) { + $metrics[$metric][$value] = $count; + } else { + $metrics[$metric][$value] += $count; + } + } + + ksort($metrics); + + echo PHP_EOL."\033[1m".'PHP CODE SNIFFER INFORMATION REPORT'."\033[0m".PHP_EOL; + echo str_repeat('-', 70).PHP_EOL; + + foreach ($metrics as $metric => $values) { + if (count($values) === 1) { + $count = reset($values); + $value = key($values); + + echo "$metric: \033[4m$value\033[0m [$count/$count, 100%]".PHP_EOL; + } else { + $totalCount = 0; + $valueWidth = 0; + foreach ($values as $value => $count) { + $totalCount += $count; + $valueWidth = max($valueWidth, strlen($value)); + } + + // Length of the total string, plus however many + // thousands separators there are. + $countWidth = strlen($totalCount); + $thousandSeparatorCount = floor($countWidth / 3); + $countWidth += $thousandSeparatorCount; + + // Account for 'total' line. + $valueWidth = max(5, $valueWidth); + + echo "$metric:".PHP_EOL; + + ksort($values, SORT_NATURAL); + arsort($values); + + $percentPrefixWidth = 0; + $percentWidth = 6; + foreach ($values as $value => $count) { + $percent = round(($count / $totalCount * 100), 2); + $percentPrefix = ''; + if ($percent === 0.00) { + $percent = 0.01; + $percentPrefix = '<'; + $percentPrefixWidth = 2; + $percentWidth = 4; + } + + printf( + "\t%-{$valueWidth}s => %{$countWidth}s (%{$percentPrefixWidth}s%{$percentWidth}.2f%%)".PHP_EOL, + $value, + number_format($count), + $percentPrefix, + $percent + ); + } + + echo "\t".str_repeat('-', ($valueWidth + $countWidth + 15)).PHP_EOL; + printf( + "\t%-{$valueWidth}s => %{$countWidth}s (100.00%%)".PHP_EOL, + 'total', + number_format($totalCount) + ); + }//end if + + echo PHP_EOL; + }//end foreach + + echo str_repeat('-', 70).PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Json.php b/vendor/squizlabs/php_codesniffer/src/Reports/Json.php new file mode 100644 index 00000000..59d8f305 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Json.php @@ -0,0 +1,106 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +class Json implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $filename = str_replace('\\', '\\\\', $report['filename']); + $filename = str_replace('"', '\"', $filename); + $filename = str_replace('/', '\/', $filename); + echo '"'.$filename.'":{'; + echo '"errors":'.$report['errors'].',"warnings":'.$report['warnings'].',"messages":['; + + $messages = ''; + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $error['message'] = str_replace("\n", '\n', $error['message']); + $error['message'] = str_replace("\r", '\r', $error['message']); + $error['message'] = str_replace("\t", '\t', $error['message']); + + $fixable = false; + if ($error['fixable'] === true) { + $fixable = true; + } + + $messagesObject = (object) $error; + $messagesObject->line = $line; + $messagesObject->column = $column; + $messagesObject->fixable = $fixable; + + $messages .= json_encode($messagesObject).","; + } + } + }//end foreach + + echo rtrim($messages, ','); + echo ']},'; + + return true; + + }//end generateFileReport() + + + /** + * Generates a JSON report. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo '{"totals":{"errors":'.$totalErrors.',"warnings":'.$totalWarnings.',"fixable":'.$totalFixable.'},"files":{'; + echo rtrim($cachedData, ','); + echo "}}".PHP_EOL; + + }//end generate() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Junit.php b/vendor/squizlabs/php_codesniffer/src/Reports/Junit.php new file mode 100644 index 00000000..d3ede61d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Junit.php @@ -0,0 +1,131 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; + +class Junit implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $out = new \XMLWriter; + $out->openMemory(); + $out->setIndent(true); + + $out->startElement('testsuite'); + $out->writeAttribute('name', $report['filename']); + $out->writeAttribute('errors', 0); + + if (count($report['messages']) === 0) { + $out->writeAttribute('tests', 1); + $out->writeAttribute('failures', 0); + + $out->startElement('testcase'); + $out->writeAttribute('name', $report['filename']); + $out->endElement(); + } else { + $failures = ($report['errors'] + $report['warnings']); + $out->writeAttribute('tests', $failures); + $out->writeAttribute('failures', $failures); + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $out->startElement('testcase'); + $out->writeAttribute('name', $error['source'].' at '.$report['filename']." ($line:$column)"); + + $error['type'] = strtolower($error['type']); + if ($phpcsFile->config->encoding !== 'utf-8') { + $error['message'] = iconv($phpcsFile->config->encoding, 'utf-8', $error['message']); + } + + $out->startElement('failure'); + $out->writeAttribute('type', $error['type']); + $out->writeAttribute('message', $error['message']); + $out->endElement(); + + $out->endElement(); + } + } + } + }//end if + + $out->endElement(); + echo $out->flush(); + return true; + + }//end generateFileReport() + + + /** + * Prints all violations for processed files, in a proprietary XML format. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + // Figure out the total number of tests. + $tests = 0; + $matches = []; + preg_match_all('/tests="([0-9]+)"/', $cachedData, $matches); + if (isset($matches[1]) === true) { + foreach ($matches[1] as $match) { + $tests += $match; + } + } + + $failures = ($totalErrors + $totalWarnings); + echo ''.PHP_EOL; + echo ''.PHP_EOL; + echo $cachedData; + echo ''.PHP_EOL; + + }//end generate() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Notifysend.php b/vendor/squizlabs/php_codesniffer/src/Reports/Notifysend.php new file mode 100644 index 00000000..08416622 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Notifysend.php @@ -0,0 +1,242 @@ + + * @author Greg Sherwood + * @copyright 2012-2014 Christian Weiske + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Common; + +class Notifysend implements Report +{ + + /** + * Notification timeout in milliseconds. + * + * @var integer + */ + protected $timeout = 3000; + + /** + * Path to notify-send command. + * + * @var string + */ + protected $path = 'notify-send'; + + /** + * Show "ok, all fine" messages. + * + * @var boolean + */ + protected $showOk = true; + + /** + * Version of installed notify-send executable. + * + * @var string + */ + protected $version = null; + + + /** + * Load configuration data. + */ + public function __construct() + { + $path = Config::getExecutablePath('notifysend'); + if ($path !== null) { + $this->path = Common::escapeshellcmd($path); + } + + $timeout = Config::getConfigData('notifysend_timeout'); + if ($timeout !== null) { + $this->timeout = (int) $timeout; + } + + $showOk = Config::getConfigData('notifysend_showok'); + if ($showOk !== null) { + $this->showOk = (bool) $showOk; + } + + $this->version = str_replace( + 'notify-send ', + '', + exec($this->path.' --version') + ); + + }//end __construct() + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + echo $report['filename'].PHP_EOL; + + // We want this file counted in the total number + // of checked files even if it has no errors. + return true; + + }//end generateFileReport() + + + /** + * Generates a summary of errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $checkedFiles = explode(PHP_EOL, trim($cachedData)); + + $msg = $this->generateMessage($checkedFiles, $totalErrors, $totalWarnings); + if ($msg === null) { + if ($this->showOk === true) { + $this->notifyAllFine(); + } + } else { + $this->notifyErrors($msg); + } + + }//end generate() + + + /** + * Generate the error message to show to the user. + * + * @param string[] $checkedFiles The files checked during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * + * @return string Error message or NULL if no error/warning found. + */ + protected function generateMessage($checkedFiles, $totalErrors, $totalWarnings) + { + if ($totalErrors === 0 && $totalWarnings === 0) { + // Nothing to print. + return null; + } + + $totalFiles = count($checkedFiles); + + $msg = ''; + if ($totalFiles > 1) { + $msg .= 'Checked '.$totalFiles.' files'.PHP_EOL; + } else { + $msg .= $checkedFiles[0].PHP_EOL; + } + + if ($totalWarnings > 0) { + $msg .= $totalWarnings.' warnings'.PHP_EOL; + } + + if ($totalErrors > 0) { + $msg .= $totalErrors.' errors'.PHP_EOL; + } + + return $msg; + + }//end generateMessage() + + + /** + * Tell the user that all is fine and no error/warning has been found. + * + * @return void + */ + protected function notifyAllFine() + { + $cmd = $this->getBasicCommand(); + $cmd .= ' -i info'; + $cmd .= ' "PHP CodeSniffer: Ok"'; + $cmd .= ' "All fine"'; + exec($cmd); + + }//end notifyAllFine() + + + /** + * Tell the user that errors/warnings have been found. + * + * @param string $msg Message to display. + * + * @return void + */ + protected function notifyErrors($msg) + { + $cmd = $this->getBasicCommand(); + $cmd .= ' -i error'; + $cmd .= ' "PHP CodeSniffer: Error"'; + $cmd .= ' '.escapeshellarg(trim($msg)); + exec($cmd); + + }//end notifyErrors() + + + /** + * Generate and return the basic notify-send command string to execute. + * + * @return string Shell command with common parameters. + */ + protected function getBasicCommand() + { + $cmd = $this->path; + $cmd .= ' --category dev.validate'; + $cmd .= ' -h int:transient:1'; + $cmd .= ' -t '.(int) $this->timeout; + if (version_compare($this->version, '0.7.3', '>=') === true) { + $cmd .= ' -a phpcs'; + } + + return $cmd; + + }//end getBasicCommand() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Report.php b/vendor/squizlabs/php_codesniffer/src/Reports/Report.php new file mode 100644 index 00000000..38f8a629 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Report.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +interface Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80); + + + /** + * Generate the actual report. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ); + + +}//end interface diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Source.php b/vendor/squizlabs/php_codesniffer/src/Reports/Source.php new file mode 100644 index 00000000..ce8c3cfe --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Source.php @@ -0,0 +1,336 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Timing; + +class Source implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + $sources = []; + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $src = $error['source']; + if (isset($sources[$src]) === false) { + $sources[$src] = [ + 'fixable' => (int) $error['fixable'], + 'count' => 1, + ]; + } else { + $sources[$src]['count']++; + } + } + } + } + + foreach ($sources as $source => $data) { + echo $source.'>>'.$data['fixable'].'>>'.$data['count'].PHP_EOL; + } + + return true; + + }//end generateFileReport() + + + /** + * Prints the source of all errors and warnings. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + return; + } + + $sources = []; + $maxLength = 0; + + foreach ($lines as $line) { + $parts = explode('>>', $line); + $source = $parts[0]; + $fixable = (bool) $parts[1]; + $count = $parts[2]; + + if (isset($sources[$source]) === false) { + if ($showSources === true) { + $parts = null; + $sniff = $source; + } else { + $parts = explode('.', $source); + if ($parts[0] === 'Internal') { + $parts[2] = $parts[1]; + $parts[1] = ''; + } + + $parts[1] = $this->makeFriendlyName($parts[1]); + + $sniff = $this->makeFriendlyName($parts[2]); + if (isset($parts[3]) === true) { + $name = $this->makeFriendlyName($parts[3]); + $name[0] = strtolower($name[0]); + $sniff .= ' '.$name; + unset($parts[3]); + } + + $parts[2] = $sniff; + }//end if + + $maxLength = max($maxLength, strlen($sniff)); + + $sources[$source] = [ + 'count' => $count, + 'fixable' => $fixable, + 'parts' => $parts, + ]; + } else { + $sources[$source]['count'] += $count; + }//end if + }//end foreach + + if ($showSources === true) { + $width = min($width, ($maxLength + 11)); + } else { + $width = min($width, ($maxLength + 41)); + } + + $width = max($width, 70); + + // Sort the data based on counts and source code. + $sourceCodes = array_keys($sources); + $counts = []; + foreach ($sources as $source => $data) { + $counts[$source] = $data['count']; + } + + array_multisort($counts, SORT_DESC, $sourceCodes, SORT_ASC, SORT_NATURAL, $sources); + + echo PHP_EOL."\033[1mPHP CODE SNIFFER VIOLATION SOURCE SUMMARY\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL."\033[1m"; + if ($showSources === true) { + if ($totalFixable > 0) { + echo ' SOURCE'.str_repeat(' ', ($width - 15)).'COUNT'.PHP_EOL; + } else { + echo 'SOURCE'.str_repeat(' ', ($width - 11)).'COUNT'.PHP_EOL; + } + } else { + if ($totalFixable > 0) { + echo ' STANDARD CATEGORY SNIFF'.str_repeat(' ', ($width - 44)).'COUNT'.PHP_EOL; + } else { + echo 'STANDARD CATEGORY SNIFF'.str_repeat(' ', ($width - 40)).'COUNT'.PHP_EOL; + } + } + + echo "\033[0m".str_repeat('-', $width).PHP_EOL; + + $fixableSources = 0; + + if ($showSources === true) { + $maxSniffWidth = ($width - 7); + } else { + $maxSniffWidth = ($width - 37); + } + + if ($totalFixable > 0) { + $maxSniffWidth -= 4; + } + + foreach ($sources as $source => $sourceData) { + if ($totalFixable > 0) { + echo '['; + if ($sourceData['fixable'] === true) { + echo 'x'; + $fixableSources++; + } else { + echo ' '; + } + + echo '] '; + } + + if ($showSources === true) { + if (strlen($source) > $maxSniffWidth) { + $source = substr($source, 0, $maxSniffWidth); + } + + echo $source; + if ($totalFixable > 0) { + echo str_repeat(' ', ($width - 9 - strlen($source))); + } else { + echo str_repeat(' ', ($width - 5 - strlen($source))); + } + } else { + $parts = $sourceData['parts']; + + if (strlen($parts[0]) > 8) { + $parts[0] = substr($parts[0], 0, ((strlen($parts[0]) - 8) * -1)); + } + + echo $parts[0].str_repeat(' ', (10 - strlen($parts[0]))); + + $category = $parts[1]; + if (strlen($category) > 18) { + $category = substr($category, 0, ((strlen($category) - 18) * -1)); + } + + echo $category.str_repeat(' ', (20 - strlen($category))); + + $sniff = $parts[2]; + if (strlen($sniff) > $maxSniffWidth) { + $sniff = substr($sniff, 0, $maxSniffWidth); + } + + if ($totalFixable > 0) { + echo $sniff.str_repeat(' ', ($width - 39 - strlen($sniff))); + } else { + echo $sniff.str_repeat(' ', ($width - 35 - strlen($sniff))); + } + }//end if + + echo $sourceData['count'].PHP_EOL; + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1m".'A TOTAL OF '.($totalErrors + $totalWarnings).' SNIFF VIOLATION'; + if (($totalErrors + $totalWarnings) > 1) { + echo 'S'; + } + + echo ' WERE FOUND IN '.count($sources).' SOURCE'; + if (count($sources) !== 1) { + echo 'S'; + } + + echo "\033[0m"; + + if ($totalFixable > 0) { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF CAN FIX THE $fixableSources MARKED SOURCES AUTOMATICALLY ($totalFixable VIOLATIONS IN TOTAL)\033[0m"; + } + + echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Timing::printRunTime(); + } + + }//end generate() + + + /** + * Converts a camel caps name into a readable string. + * + * @param string $name The camel caps name to convert. + * + * @return string + */ + public function makeFriendlyName($name) + { + if (trim($name) === '') { + return ''; + } + + $friendlyName = ''; + $length = strlen($name); + + $lastWasUpper = false; + $lastWasNumeric = false; + for ($i = 0; $i < $length; $i++) { + if (is_numeric($name[$i]) === true) { + if ($lastWasNumeric === false) { + $friendlyName .= ' '; + } + + $lastWasUpper = false; + $lastWasNumeric = true; + } else { + $lastWasNumeric = false; + + $char = strtolower($name[$i]); + if ($char === $name[$i]) { + // Lowercase. + $lastWasUpper = false; + } else { + // Uppercase. + if ($lastWasUpper === false) { + $friendlyName .= ' '; + if ($i < ($length - 1)) { + $next = $name[($i + 1)]; + if (strtolower($next) === $next) { + // Next char is lowercase so it is a word boundary. + $name[$i] = strtolower($name[$i]); + } + } + } + + $lastWasUpper = true; + } + }//end if + + $friendlyName .= $name[$i]; + }//end for + + $friendlyName = trim($friendlyName); + $friendlyName[0] = strtoupper($friendlyName[0]); + + return $friendlyName; + + }//end makeFriendlyName() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Summary.php b/vendor/squizlabs/php_codesniffer/src/Reports/Summary.php new file mode 100644 index 00000000..8fe18e76 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Summary.php @@ -0,0 +1,183 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util; + +class Summary implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if (PHP_CODESNIFFER_VERBOSITY === 0 + && $report['errors'] === 0 + && $report['warnings'] === 0 + ) { + // Nothing to print. + return false; + } + + echo $report['filename'].'>>'.$report['errors'].'>>'.$report['warnings'].PHP_EOL; + return true; + + }//end generateFileReport() + + + /** + * Generates a summary of errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + return; + } + + $reportFiles = []; + $maxLength = 0; + + foreach ($lines as $line) { + $parts = explode('>>', $line); + $fileLen = strlen($parts[0]); + $reportFiles[$parts[0]] = [ + 'errors' => $parts[1], + 'warnings' => $parts[2], + 'strlen' => $fileLen, + ]; + + $maxLength = max($maxLength, $fileLen); + } + + uksort( + $reportFiles, + function ($keyA, $keyB) { + $pathPartsA = explode(DIRECTORY_SEPARATOR, $keyA); + $pathPartsB = explode(DIRECTORY_SEPARATOR, $keyB); + + do { + $partA = array_shift($pathPartsA); + $partB = array_shift($pathPartsB); + } while ($partA === $partB && empty($pathPartsA) === false && empty($pathPartsB) === false); + + if (empty($pathPartsA) === false && empty($pathPartsB) === true) { + return 1; + } else if (empty($pathPartsA) === true && empty($pathPartsB) === false) { + return -1; + } else { + return strcasecmp($partA, $partB); + } + } + ); + + $width = min($width, ($maxLength + 21)); + $width = max($width, 70); + + echo PHP_EOL."\033[1m".'PHP CODE SNIFFER REPORT SUMMARY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1m".'FILE'.str_repeat(' ', ($width - 20)).'ERRORS WARNINGS'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + foreach ($reportFiles as $file => $data) { + $padding = ($width - 18 - $data['strlen']); + if ($padding < 0) { + $file = '...'.substr($file, (($padding * -1) + 3)); + $padding = 0; + } + + echo $file.str_repeat(' ', $padding).' '; + if ($data['errors'] !== 0) { + echo "\033[31m".$data['errors']."\033[0m"; + echo str_repeat(' ', (8 - strlen((string) $data['errors']))); + } else { + echo '0 '; + } + + if ($data['warnings'] !== 0) { + echo "\033[33m".$data['warnings']."\033[0m"; + } else { + echo '0'; + } + + echo PHP_EOL; + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1mA TOTAL OF $totalErrors ERROR"; + if ($totalErrors !== 1) { + echo 'S'; + } + + echo ' AND '.$totalWarnings.' WARNING'; + if ($totalWarnings !== 1) { + echo 'S'; + } + + echo ' WERE FOUND IN '.$totalFiles.' FILE'; + if ($totalFiles !== 1) { + echo 'S'; + } + + echo "\033[0m"; + + if ($totalFixable > 0) { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF CAN FIX $totalFixable OF THESE SNIFF VIOLATIONS AUTOMATICALLY\033[0m"; + } + + echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Util\Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Svnblame.php b/vendor/squizlabs/php_codesniffer/src/Reports/Svnblame.php new file mode 100644 index 00000000..a7f65e15 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Svnblame.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Exceptions\DeepExitException; + +class Svnblame extends VersionControl +{ + + /** + * The name of the report we want in the output + * + * @var string + */ + protected $reportName = 'SVN'; + + + /** + * Extract the author from a blame line. + * + * @param string $line Line to parse. + * + * @return mixed string or false if impossible to recover. + */ + protected function getAuthor($line) + { + $blameParts = []; + preg_match('|\s*([^\s]+)\s+([^\s]+)|', $line, $blameParts); + + if (isset($blameParts[2]) === false) { + return false; + } + + return $blameParts[2]; + + }//end getAuthor() + + + /** + * Gets the blame output. + * + * @param string $filename File to blame. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + protected function getBlameContent($filename) + { + $command = 'svn blame "'.$filename.'" 2>&1'; + $handle = popen($command, 'r'); + if ($handle === false) { + $error = 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $rawContent = stream_get_contents($handle); + pclose($handle); + + $blames = explode("\n", $rawContent); + + return $blames; + + }//end getBlameContent() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/VersionControl.php b/vendor/squizlabs/php_codesniffer/src/Reports/VersionControl.php new file mode 100644 index 00000000..0f414567 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/VersionControl.php @@ -0,0 +1,376 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Timing; + +abstract class VersionControl implements Report +{ + + /** + * The name of the report we want in the output. + * + * @var string + */ + protected $reportName = 'VERSION CONTROL'; + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $blames = $this->getBlameContent($report['filename']); + + $authorCache = []; + $praiseCache = []; + $sourceCache = []; + + foreach ($report['messages'] as $line => $lineErrors) { + $author = 'Unknown'; + if (isset($blames[($line - 1)]) === true) { + $blameAuthor = $this->getAuthor($blames[($line - 1)]); + if ($blameAuthor !== false) { + $author = $blameAuthor; + } + } + + if (isset($authorCache[$author]) === false) { + $authorCache[$author] = 0; + $praiseCache[$author] = [ + 'good' => 0, + 'bad' => 0, + ]; + } + + $praiseCache[$author]['bad']++; + + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $authorCache[$author]++; + + if ($showSources === true) { + $source = $error['source']; + if (isset($sourceCache[$author][$source]) === false) { + $sourceCache[$author][$source] = [ + 'count' => 1, + 'fixable' => $error['fixable'], + ]; + } else { + $sourceCache[$author][$source]['count']++; + } + } + } + } + + unset($blames[($line - 1)]); + }//end foreach + + // Now go through and give the authors some credit for + // all the lines that do not have errors. + foreach ($blames as $line) { + $author = $this->getAuthor($line); + if ($author === false) { + $author = 'Unknown'; + } + + if (isset($authorCache[$author]) === false) { + // This author doesn't have any errors. + if (PHP_CODESNIFFER_VERBOSITY === 0) { + continue; + } + + $authorCache[$author] = 0; + $praiseCache[$author] = [ + 'good' => 0, + 'bad' => 0, + ]; + } + + $praiseCache[$author]['good']++; + }//end foreach + + foreach ($authorCache as $author => $errors) { + echo "AUTHOR>>$author>>$errors".PHP_EOL; + } + + foreach ($praiseCache as $author => $praise) { + echo "PRAISE>>$author>>".$praise['good'].'>>'.$praise['bad'].PHP_EOL; + } + + foreach ($sourceCache as $author => $sources) { + foreach ($sources as $source => $sourceData) { + $count = $sourceData['count']; + $fixable = (int) $sourceData['fixable']; + echo "SOURCE>>$author>>$source>>$count>>$fixable".PHP_EOL; + } + } + + return true; + + }//end generateFileReport() + + + /** + * Prints the author of all errors and warnings, as given by "version control blame". + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $errorsShown = ($totalErrors + $totalWarnings); + if ($errorsShown === 0) { + // Nothing to show. + return; + } + + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + return; + } + + $authorCache = []; + $praiseCache = []; + $sourceCache = []; + + foreach ($lines as $line) { + $parts = explode('>>', $line); + switch ($parts[0]) { + case 'AUTHOR': + if (isset($authorCache[$parts[1]]) === false) { + $authorCache[$parts[1]] = $parts[2]; + } else { + $authorCache[$parts[1]] += $parts[2]; + } + break; + case 'PRAISE': + if (isset($praiseCache[$parts[1]]) === false) { + $praiseCache[$parts[1]] = [ + 'good' => $parts[2], + 'bad' => $parts[3], + ]; + } else { + $praiseCache[$parts[1]]['good'] += $parts[2]; + $praiseCache[$parts[1]]['bad'] += $parts[3]; + } + break; + case 'SOURCE': + if (isset($praiseCache[$parts[1]]) === false) { + $praiseCache[$parts[1]] = []; + } + + if (isset($sourceCache[$parts[1]][$parts[2]]) === false) { + $sourceCache[$parts[1]][$parts[2]] = [ + 'count' => $parts[3], + 'fixable' => (bool) $parts[4], + ]; + } else { + $sourceCache[$parts[1]][$parts[2]]['count'] += $parts[3]; + } + break; + default: + break; + }//end switch + }//end foreach + + // Make sure the report width isn't too big. + $maxLength = 0; + foreach ($authorCache as $author => $count) { + $maxLength = max($maxLength, strlen($author)); + if ($showSources === true && isset($sourceCache[$author]) === true) { + foreach ($sourceCache[$author] as $source => $sourceData) { + if ($source === 'count') { + continue; + } + + $maxLength = max($maxLength, (strlen($source) + 9)); + } + } + } + + $width = min($width, ($maxLength + 30)); + $width = max($width, 70); + arsort($authorCache); + + echo PHP_EOL."\033[1m".'PHP CODE SNIFFER '.$this->reportName.' BLAME SUMMARY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL."\033[1m"; + if ($showSources === true) { + echo 'AUTHOR SOURCE'.str_repeat(' ', ($width - 43)).'(Author %) (Overall %) COUNT'.PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + } else { + echo 'AUTHOR'.str_repeat(' ', ($width - 34)).'(Author %) (Overall %) COUNT'.PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + } + + echo "\033[0m"; + + if ($showSources === true) { + $maxSniffWidth = ($width - 15); + + if ($totalFixable > 0) { + $maxSniffWidth -= 4; + } + } + + $fixableSources = 0; + + foreach ($authorCache as $author => $count) { + if ($praiseCache[$author]['good'] === 0) { + $percent = 0; + } else { + $total = ($praiseCache[$author]['bad'] + $praiseCache[$author]['good']); + $percent = round(($praiseCache[$author]['bad'] / $total * 100), 2); + } + + $overallPercent = '('.round((($count / $errorsShown) * 100), 2).')'; + $authorPercent = '('.$percent.')'; + $line = str_repeat(' ', (6 - strlen($count))).$count; + $line = str_repeat(' ', (12 - strlen($overallPercent))).$overallPercent.$line; + $line = str_repeat(' ', (11 - strlen($authorPercent))).$authorPercent.$line; + $line = $author.str_repeat(' ', ($width - strlen($author) - strlen($line))).$line; + + if ($showSources === true) { + $line = "\033[1m$line\033[0m"; + } + + echo $line.PHP_EOL; + + if ($showSources === true && isset($sourceCache[$author]) === true) { + $errors = $sourceCache[$author]; + asort($errors); + $errors = array_reverse($errors); + + foreach ($errors as $source => $sourceData) { + if ($source === 'count') { + continue; + } + + $count = $sourceData['count']; + + $srcLength = strlen($source); + if ($srcLength > $maxSniffWidth) { + $source = substr($source, 0, $maxSniffWidth); + } + + $line = str_repeat(' ', (5 - strlen($count))).$count; + + echo ' '; + if ($totalFixable > 0) { + echo '['; + if ($sourceData['fixable'] === true) { + echo 'x'; + $fixableSources++; + } else { + echo ' '; + } + + echo '] '; + } + + echo $source; + if ($totalFixable > 0) { + echo str_repeat(' ', ($width - 18 - strlen($source))); + } else { + echo str_repeat(' ', ($width - 14 - strlen($source))); + } + + echo $line.PHP_EOL; + }//end foreach + }//end if + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1m".'A TOTAL OF '.$errorsShown.' SNIFF VIOLATION'; + if ($errorsShown !== 1) { + echo 'S'; + } + + echo ' WERE COMMITTED BY '.count($authorCache).' AUTHOR'; + if (count($authorCache) !== 1) { + echo 'S'; + } + + echo "\033[0m"; + + if ($totalFixable > 0) { + if ($showSources === true) { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF CAN FIX THE $fixableSources MARKED SOURCES AUTOMATICALLY ($totalFixable VIOLATIONS IN TOTAL)\033[0m"; + } else { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF CAN FIX $totalFixable OF THESE SNIFF VIOLATIONS AUTOMATICALLY\033[0m"; + } + } + + echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Timing::printRunTime(); + } + + }//end generate() + + + /** + * Extract the author from a blame line. + * + * @param string $line Line to parse. + * + * @return mixed string or false if impossible to recover. + */ + abstract protected function getAuthor($line); + + + /** + * Gets the blame output. + * + * @param string $filename File to blame. + * + * @return array + */ + abstract protected function getBlameContent($filename); + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Reports/Xml.php b/vendor/squizlabs/php_codesniffer/src/Reports/Xml.php new file mode 100644 index 00000000..066383de --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Reports/Xml.php @@ -0,0 +1,126 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; + +class Xml implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $out = new \XMLWriter; + $out->openMemory(); + $out->setIndent(true); + $out->setIndentString(' '); + $out->startDocument('1.0', 'UTF-8'); + + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + $out->startElement('file'); + $out->writeAttribute('name', $report['filename']); + $out->writeAttribute('errors', $report['errors']); + $out->writeAttribute('warnings', $report['warnings']); + $out->writeAttribute('fixable', $report['fixable']); + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $error['type'] = strtolower($error['type']); + if ($phpcsFile->config->encoding !== 'utf-8') { + $error['message'] = iconv($phpcsFile->config->encoding, 'utf-8', $error['message']); + } + + $out->startElement($error['type']); + $out->writeAttribute('line', $line); + $out->writeAttribute('column', $column); + $out->writeAttribute('source', $error['source']); + $out->writeAttribute('severity', $error['severity']); + $out->writeAttribute('fixable', (int) $error['fixable']); + $out->text($error['message']); + $out->endElement(); + } + } + }//end foreach + + $out->endElement(); + + // Remove the start of the document because we will + // add that manually later. We only have it in here to + // properly set the encoding. + $content = $out->flush(); + if (strpos($content, PHP_EOL) !== false) { + $content = substr($content, (strpos($content, PHP_EOL) + strlen(PHP_EOL))); + } else if (strpos($content, "\n") !== false) { + $content = substr($content, (strpos($content, "\n") + 1)); + } + + echo $content; + + return true; + + }//end generateFileReport() + + + /** + * Prints all violations for processed files, in a proprietary XML format. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo ''.PHP_EOL; + echo ''.PHP_EOL; + echo $cachedData; + echo ''.PHP_EOL; + + }//end generate() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Ruleset.php b/vendor/squizlabs/php_codesniffer/src/Ruleset.php new file mode 100644 index 00000000..7e659706 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Ruleset.php @@ -0,0 +1,1383 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Util; + +class Ruleset +{ + + /** + * The name of the coding standard being used. + * + * If a top-level standard includes other standards, or sniffs + * from other standards, only the name of the top-level standard + * will be stored in here. + * + * If multiple top-level standards are being loaded into + * a single ruleset object, this will store a comma separated list + * of the top-level standard names. + * + * @var string + */ + public $name = ''; + + /** + * A list of file paths for the ruleset files being used. + * + * @var string[] + */ + public $paths = []; + + /** + * A list of regular expressions used to ignore specific sniffs for files and folders. + * + * Is also used to set global exclude patterns. + * The key is the regular expression and the value is the type + * of ignore pattern (absolute or relative). + * + * @var array + */ + public $ignorePatterns = []; + + /** + * A list of regular expressions used to include specific sniffs for files and folders. + * + * The key is the sniff code and the value is an array with + * the key being a regular expression and the value is the type + * of ignore pattern (absolute or relative). + * + * @var array> + */ + public $includePatterns = []; + + /** + * An array of sniff objects that are being used to check files. + * + * The key is the fully qualified name of the sniff class + * and the value is the sniff object. + * + * @var array + */ + public $sniffs = []; + + /** + * A mapping of sniff codes to fully qualified class names. + * + * The key is the sniff code and the value + * is the fully qualified name of the sniff class. + * + * @var array + */ + public $sniffCodes = []; + + /** + * An array of token types and the sniffs that are listening for them. + * + * The key is the token name being listened for and the value + * is the sniff object. + * + * @var array + */ + public $tokenListeners = []; + + /** + * An array of rules from the ruleset.xml file. + * + * It may be empty, indicating that the ruleset does not override + * any of the default sniff settings. + * + * @var array + */ + public $ruleset = []; + + /** + * The directories that the processed rulesets are in. + * + * @var string[] + */ + protected $rulesetDirs = []; + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + private $config = null; + + + /** + * Initialise the ruleset that the run will use. + * + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If no sniffs were registered. + */ + public function __construct(Config $config) + { + $this->config = $config; + $restrictions = $config->sniffs; + $exclusions = $config->exclude; + $sniffs = []; + + $standardPaths = []; + foreach ($config->standards as $standard) { + $installed = Util\Standards::getInstalledStandardPath($standard); + if ($installed === null) { + $standard = Util\Common::realpath($standard); + if (is_dir($standard) === true + && is_file(Util\Common::realpath($standard.DIRECTORY_SEPARATOR.'ruleset.xml')) === true + ) { + $standard = Util\Common::realpath($standard.DIRECTORY_SEPARATOR.'ruleset.xml'); + } + } else { + $standard = $installed; + } + + $standardPaths[] = $standard; + } + + foreach ($standardPaths as $standard) { + $ruleset = @simplexml_load_string(file_get_contents($standard)); + if ($ruleset !== false) { + $standardName = (string) $ruleset['name']; + if ($this->name !== '') { + $this->name .= ', '; + } + + $this->name .= $standardName; + + // Allow autoloading of custom files inside this standard. + if (isset($ruleset['namespace']) === true) { + $namespace = (string) $ruleset['namespace']; + } else { + $namespace = basename(dirname($standard)); + } + + Autoload::addSearchPath(dirname($standard), $namespace); + } + + if (defined('PHP_CODESNIFFER_IN_TESTS') === true && empty($restrictions) === false) { + // In unit tests, only register the sniffs that the test wants and not the entire standard. + try { + foreach ($restrictions as $restriction) { + $sniffs = array_merge($sniffs, $this->expandRulesetReference($restriction, dirname($standard))); + } + } catch (RuntimeException $e) { + // Sniff reference could not be expanded, which probably means this + // is an installed standard. Let the unit test system take care of + // setting the correct sniff for testing. + return; + } + + break; + } + + if (PHP_CODESNIFFER_VERBOSITY === 1) { + echo "Registering sniffs in the $standardName standard... "; + if (count($config->standards) > 1 || PHP_CODESNIFFER_VERBOSITY > 2) { + echo PHP_EOL; + } + } + + $sniffs = array_merge($sniffs, $this->processRuleset($standard)); + }//end foreach + + // Ignore sniff restrictions if caching is on. + if ($config->cache === true) { + $restrictions = []; + $exclusions = []; + } + + $sniffRestrictions = []; + foreach ($restrictions as $sniffCode) { + $parts = explode('.', strtolower($sniffCode)); + $sniffName = $parts[0].'\sniffs\\'.$parts[1].'\\'.$parts[2].'sniff'; + $sniffRestrictions[$sniffName] = true; + } + + $sniffExclusions = []; + foreach ($exclusions as $sniffCode) { + $parts = explode('.', strtolower($sniffCode)); + $sniffName = $parts[0].'\sniffs\\'.$parts[1].'\\'.$parts[2].'sniff'; + $sniffExclusions[$sniffName] = true; + } + + $this->registerSniffs($sniffs, $sniffRestrictions, $sniffExclusions); + $this->populateTokenListeners(); + + $numSniffs = count($this->sniffs); + if (PHP_CODESNIFFER_VERBOSITY === 1) { + echo "DONE ($numSniffs sniffs registered)".PHP_EOL; + } + + if ($numSniffs === 0) { + throw new RuntimeException('No sniffs were registered'); + } + + }//end __construct() + + + /** + * Prints a report showing the sniffs contained in a standard. + * + * @return void + */ + public function explain() + { + $sniffs = array_keys($this->sniffCodes); + sort($sniffs); + + ob_start(); + + $lastStandard = null; + $lastCount = ''; + $sniffCount = count($sniffs); + + // Add a dummy entry to the end so we loop + // one last time and clear the output buffer. + $sniffs[] = ''; + + echo PHP_EOL."The $this->name standard contains $sniffCount sniffs".PHP_EOL; + + ob_start(); + + foreach ($sniffs as $i => $sniff) { + if ($i === $sniffCount) { + $currentStandard = null; + } else { + $currentStandard = substr($sniff, 0, strpos($sniff, '.')); + if ($lastStandard === null) { + $lastStandard = $currentStandard; + } + } + + if ($currentStandard !== $lastStandard) { + $sniffList = ob_get_contents(); + ob_end_clean(); + + echo PHP_EOL.$lastStandard.' ('.$lastCount.' sniff'; + if ($lastCount > 1) { + echo 's'; + } + + echo ')'.PHP_EOL; + echo str_repeat('-', (strlen($lastStandard.$lastCount) + 10)); + echo PHP_EOL; + echo $sniffList; + + $lastStandard = $currentStandard; + $lastCount = 0; + + if ($currentStandard === null) { + break; + } + + ob_start(); + }//end if + + echo ' '.$sniff.PHP_EOL; + $lastCount++; + }//end foreach + + }//end explain() + + + /** + * Processes a single ruleset and returns a list of the sniffs it represents. + * + * Rules founds within the ruleset are processed immediately, but sniff classes + * are not registered by this method. + * + * @param string $rulesetPath The path to a ruleset XML file. + * @param int $depth How many nested processing steps we are in. This + * is only used for debug output. + * + * @return string[] + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException - If the ruleset path is invalid. + * - If a specified autoload file could not be found. + */ + public function processRuleset($rulesetPath, $depth=0) + { + $rulesetPath = Util\Common::realpath($rulesetPath); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo 'Processing ruleset '.Util\Common::stripBasepath($rulesetPath, $this->config->basepath).PHP_EOL; + } + + libxml_use_internal_errors(true); + $ruleset = simplexml_load_string(file_get_contents($rulesetPath)); + if ($ruleset === false) { + $errorMsg = "Ruleset $rulesetPath is not valid".PHP_EOL; + $errors = libxml_get_errors(); + foreach ($errors as $error) { + $errorMsg .= '- On line '.$error->line.', column '.$error->column.': '.$error->message; + } + + libxml_clear_errors(); + throw new RuntimeException($errorMsg); + } + + libxml_use_internal_errors(false); + + $ownSniffs = []; + $includedSniffs = []; + $excludedSniffs = []; + + $this->paths[] = $rulesetPath; + $rulesetDir = dirname($rulesetPath); + $this->rulesetDirs[] = $rulesetDir; + + $sniffDir = $rulesetDir.DIRECTORY_SEPARATOR.'Sniffs'; + if (is_dir($sniffDir) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\tAdding sniff files from ".Util\Common::stripBasepath($sniffDir, $this->config->basepath).' directory'.PHP_EOL; + } + + $ownSniffs = $this->expandSniffDirectory($sniffDir, $depth); + } + + // Include custom autoloaders. + foreach ($ruleset->{'autoload'} as $autoload) { + if ($this->shouldProcessElement($autoload) === false) { + continue; + } + + $autoloadPath = (string) $autoload; + + // Try relative autoload paths first. + $relativePath = Util\Common::realPath(dirname($rulesetPath).DIRECTORY_SEPARATOR.$autoloadPath); + + if ($relativePath !== false && is_file($relativePath) === true) { + $autoloadPath = $relativePath; + } else if (is_file($autoloadPath) === false) { + throw new RuntimeException('The specified autoload file "'.$autoload.'" does not exist'); + } + + include_once $autoloadPath; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> included autoloader $autoloadPath".PHP_EOL; + } + }//end foreach + + // Process custom sniff config settings. + foreach ($ruleset->{'config'} as $config) { + if ($this->shouldProcessElement($config) === false) { + continue; + } + + Config::setConfigData((string) $config['name'], (string) $config['value'], true); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> set config value ".(string) $config['name'].': '.(string) $config['value'].PHP_EOL; + } + } + + foreach ($ruleset->rule as $rule) { + if (isset($rule['ref']) === false + || $this->shouldProcessElement($rule) === false + ) { + continue; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\tProcessing rule \"".$rule['ref'].'"'.PHP_EOL; + } + + $expandedSniffs = $this->expandRulesetReference((string) $rule['ref'], $rulesetDir, $depth); + $newSniffs = array_diff($expandedSniffs, $includedSniffs); + $includedSniffs = array_merge($includedSniffs, $expandedSniffs); + + $parts = explode('.', $rule['ref']); + if (count($parts) === 4 + && $parts[0] !== '' + && $parts[1] !== '' + && $parts[2] !== '' + ) { + $sniffCode = $parts[0].'.'.$parts[1].'.'.$parts[2]; + if (isset($this->ruleset[$sniffCode]['severity']) === true + && $this->ruleset[$sniffCode]['severity'] === 0 + ) { + // This sniff code has already been turned off, but now + // it is being explicitly included again, so turn it back on. + $this->ruleset[(string) $rule['ref']]['severity'] = 5; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* disabling sniff exclusion for specific message code *".PHP_EOL; + echo str_repeat("\t", $depth); + echo "\t\t=> severity set to 5".PHP_EOL; + } + } else if (empty($newSniffs) === false) { + $newSniff = $newSniffs[0]; + if (in_array($newSniff, $ownSniffs, true) === false) { + // Including a sniff that hasn't been included higher up, but + // only including a single message from it. So turn off all messages in + // the sniff, except this one. + $this->ruleset[$sniffCode]['severity'] = 0; + $this->ruleset[(string) $rule['ref']]['severity'] = 5; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\tExcluding sniff \"".$sniffCode.'" except for "'.$parts[3].'"'.PHP_EOL; + } + } + }//end if + }//end if + + if (isset($rule->exclude) === true) { + foreach ($rule->exclude as $exclude) { + if (isset($exclude['name']) === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* ignoring empty exclude rule *".PHP_EOL; + echo "\t\t\t=> ".$exclude->asXML().PHP_EOL; + } + + continue; + } + + if ($this->shouldProcessElement($exclude) === false) { + continue; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\tExcluding rule \"".$exclude['name'].'"'.PHP_EOL; + } + + // Check if a single code is being excluded, which is a shortcut + // for setting the severity of the message to 0. + $parts = explode('.', $exclude['name']); + if (count($parts) === 4) { + $this->ruleset[(string) $exclude['name']]['severity'] = 0; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> severity set to 0".PHP_EOL; + } + } else { + $excludedSniffs = array_merge( + $excludedSniffs, + $this->expandRulesetReference((string) $exclude['name'], $rulesetDir, ($depth + 1)) + ); + } + }//end foreach + }//end if + + $this->processRule($rule, $newSniffs, $depth); + }//end foreach + + // Process custom command line arguments. + $cliArgs = []; + foreach ($ruleset->{'arg'} as $arg) { + if ($this->shouldProcessElement($arg) === false) { + continue; + } + + if (isset($arg['name']) === true) { + $argString = '--'.(string) $arg['name']; + if (isset($arg['value']) === true) { + $argString .= '='.(string) $arg['value']; + } + } else { + $argString = '-'.(string) $arg['value']; + } + + $cliArgs[] = $argString; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> set command line value $argString".PHP_EOL; + } + }//end foreach + + // Set custom php ini values as CLI args. + foreach ($ruleset->{'ini'} as $arg) { + if ($this->shouldProcessElement($arg) === false) { + continue; + } + + if (isset($arg['name']) === false) { + continue; + } + + $name = (string) $arg['name']; + $argString = $name; + if (isset($arg['value']) === true) { + $value = (string) $arg['value']; + $argString .= "=$value"; + } else { + $value = 'true'; + } + + $cliArgs[] = '-d'; + $cliArgs[] = $argString; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> set PHP ini value $name to $value".PHP_EOL; + } + }//end foreach + + if (empty($this->config->files) === true) { + // Process hard-coded file paths. + foreach ($ruleset->{'file'} as $file) { + $file = (string) $file; + $cliArgs[] = $file; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> added \"$file\" to the file list".PHP_EOL; + } + } + } + + if (empty($cliArgs) === false) { + // Change the directory so all relative paths are worked + // out based on the location of the ruleset instead of + // the location of the user. + $inPhar = Util\Common::isPharFile($rulesetDir); + if ($inPhar === false) { + $currentDir = getcwd(); + chdir($rulesetDir); + } + + $this->config->setCommandLineValues($cliArgs); + + if ($inPhar === false) { + chdir($currentDir); + } + } + + // Process custom ignore pattern rules. + foreach ($ruleset->{'exclude-pattern'} as $pattern) { + if ($this->shouldProcessElement($pattern) === false) { + continue; + } + + if (isset($pattern['type']) === false) { + $pattern['type'] = 'absolute'; + } + + $this->ignorePatterns[(string) $pattern] = (string) $pattern['type']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> added global ".(string) $pattern['type'].' ignore pattern: '.(string) $pattern.PHP_EOL; + } + } + + $includedSniffs = array_unique(array_merge($ownSniffs, $includedSniffs)); + $excludedSniffs = array_unique($excludedSniffs); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $included = count($includedSniffs); + $excluded = count($excludedSniffs); + echo str_repeat("\t", $depth); + echo "=> Ruleset processing complete; included $included sniffs and excluded $excluded".PHP_EOL; + } + + // Merge our own sniff list with our externally included + // sniff list, but filter out any excluded sniffs. + $files = []; + foreach ($includedSniffs as $sniff) { + if (in_array($sniff, $excludedSniffs, true) === true) { + continue; + } else { + $files[] = Util\Common::realpath($sniff); + } + } + + return $files; + + }//end processRuleset() + + + /** + * Expands a directory into a list of sniff files within. + * + * @param string $directory The path to a directory. + * @param int $depth How many nested processing steps we are in. This + * is only used for debug output. + * + * @return array + */ + private function expandSniffDirectory($directory, $depth=0) + { + $sniffs = []; + + $rdi = new \RecursiveDirectoryIterator($directory, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS); + $di = new \RecursiveIteratorIterator($rdi, 0, \RecursiveIteratorIterator::CATCH_GET_CHILD); + + $dirLen = strlen($directory); + + foreach ($di as $file) { + $filename = $file->getFilename(); + + // Skip hidden files. + if (substr($filename, 0, 1) === '.') { + continue; + } + + // We are only interested in PHP and sniff files. + $fileParts = explode('.', $filename); + if (array_pop($fileParts) !== 'php') { + continue; + } + + $basename = basename($filename, '.php'); + if (substr($basename, -5) !== 'Sniff') { + continue; + } + + $path = $file->getPathname(); + + // Skip files in hidden directories within the Sniffs directory of this + // standard. We use the offset with strpos() to allow hidden directories + // before, valid example: + // /home/foo/.composer/vendor/squiz/custom_tool/MyStandard/Sniffs/... + if (strpos($path, DIRECTORY_SEPARATOR.'.', $dirLen) !== false) { + continue; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Util\Common::stripBasepath($path, $this->config->basepath).PHP_EOL; + } + + $sniffs[] = $path; + }//end foreach + + return $sniffs; + + }//end expandSniffDirectory() + + + /** + * Expands a ruleset reference into a list of sniff files. + * + * @param string $ref The reference from the ruleset XML file. + * @param string $rulesetDir The directory of the ruleset XML file, used to + * evaluate relative paths. + * @param int $depth How many nested processing steps we are in. This + * is only used for debug output. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the reference is invalid. + */ + private function expandRulesetReference($ref, $rulesetDir, $depth=0) + { + // Ignore internal sniffs codes as they are used to only + // hide and change internal messages. + if (substr($ref, 0, 9) === 'Internal.') { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* ignoring internal sniff code *".PHP_EOL; + } + + return []; + } + + // As sniffs can't begin with a full stop, assume references in + // this format are relative paths and attempt to convert them + // to absolute paths. If this fails, let the reference run through + // the normal checks and have it fail as normal. + if (substr($ref, 0, 1) === '.') { + $realpath = Util\Common::realpath($rulesetDir.'/'.$ref); + if ($realpath !== false) { + $ref = $realpath; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Util\Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + } + } + } + + // As sniffs can't begin with a tilde, assume references in + // this format are relative to the user's home directory. + if (substr($ref, 0, 2) === '~/') { + $realpath = Util\Common::realpath($ref); + if ($realpath !== false) { + $ref = $realpath; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Util\Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + } + } + } + + if (is_file($ref) === true) { + if (substr($ref, -9) === 'Sniff.php') { + // A single external sniff. + $this->rulesetDirs[] = dirname(dirname(dirname($ref))); + return [$ref]; + } + } else { + // See if this is a whole standard being referenced. + $path = Util\Standards::getInstalledStandardPath($ref); + if ($path !== null && Util\Common::isPharFile($path) === true && strpos($path, 'ruleset.xml') === false) { + // If the ruleset exists inside the phar file, use it. + if (file_exists($path.DIRECTORY_SEPARATOR.'ruleset.xml') === true) { + $path .= DIRECTORY_SEPARATOR.'ruleset.xml'; + } else { + $path = null; + } + } + + if ($path !== null) { + $ref = $path; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Util\Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + } + } else if (is_dir($ref) === false) { + // Work out the sniff path. + $sepPos = strpos($ref, DIRECTORY_SEPARATOR); + if ($sepPos !== false) { + $stdName = substr($ref, 0, $sepPos); + $path = substr($ref, $sepPos); + } else { + $parts = explode('.', $ref); + $stdName = $parts[0]; + if (count($parts) === 1) { + // A whole standard? + $path = ''; + } else if (count($parts) === 2) { + // A directory of sniffs? + $path = DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR.$parts[1]; + } else { + // A single sniff? + $path = DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR.$parts[1].DIRECTORY_SEPARATOR.$parts[2].'Sniff.php'; + } + } + + $newRef = false; + $stdPath = Util\Standards::getInstalledStandardPath($stdName); + if ($stdPath !== null && $path !== '') { + if (Util\Common::isPharFile($stdPath) === true + && strpos($stdPath, 'ruleset.xml') === false + ) { + // Phar files can only return the directory, + // since ruleset can be omitted if building one standard. + $newRef = Util\Common::realpath($stdPath.$path); + } else { + $newRef = Util\Common::realpath(dirname($stdPath).$path); + } + } + + if ($newRef === false) { + // The sniff is not locally installed, so check if it is being + // referenced as a remote sniff outside the install. We do this + // by looking through all directories where we have found ruleset + // files before, looking for ones for this particular standard, + // and seeing if it is in there. + foreach ($this->rulesetDirs as $dir) { + if (strtolower(basename($dir)) !== strtolower($stdName)) { + continue; + } + + $newRef = Util\Common::realpath($dir.$path); + + if ($newRef !== false) { + $ref = $newRef; + } + } + } else { + $ref = $newRef; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Util\Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + } + }//end if + }//end if + + if (is_dir($ref) === true) { + if (is_file($ref.DIRECTORY_SEPARATOR.'ruleset.xml') === true) { + // We are referencing an external coding standard. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* rule is referencing a standard using directory name; processing *".PHP_EOL; + } + + return $this->processRuleset($ref.DIRECTORY_SEPARATOR.'ruleset.xml', ($depth + 2)); + } else { + // We are referencing a whole directory of sniffs. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* rule is referencing a directory of sniffs *".PHP_EOL; + echo str_repeat("\t", $depth); + echo "\t\tAdding sniff files from directory".PHP_EOL; + } + + return $this->expandSniffDirectory($ref, ($depth + 1)); + } + } else { + if (is_file($ref) === false) { + $error = "Referenced sniff \"$ref\" does not exist"; + throw new RuntimeException($error); + } + + if (substr($ref, -9) === 'Sniff.php') { + // A single sniff. + return [$ref]; + } else { + // Assume an external ruleset.xml file. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* rule is referencing a standard using ruleset path; processing *".PHP_EOL; + } + + return $this->processRuleset($ref, ($depth + 2)); + } + }//end if + + }//end expandRulesetReference() + + + /** + * Processes a rule from a ruleset XML file, overriding built-in defaults. + * + * @param \SimpleXMLElement $rule The rule object from a ruleset XML file. + * @param string[] $newSniffs An array of sniffs that got included by this rule. + * @param int $depth How many nested processing steps we are in. + * This is only used for debug output. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If rule settings are invalid. + */ + private function processRule($rule, $newSniffs, $depth=0) + { + $ref = (string) $rule['ref']; + $todo = [$ref]; + + $parts = explode('.', $ref); + $partsCount = count($parts); + if ($partsCount <= 2 + || $partsCount > count(array_filter($parts)) + || in_array($ref, $newSniffs) === true + ) { + // We are processing a standard, a category of sniffs or a relative path inclusion. + foreach ($newSniffs as $sniffFile) { + $parts = explode(DIRECTORY_SEPARATOR, $sniffFile); + if (count($parts) === 1 && DIRECTORY_SEPARATOR === '\\') { + // Path using forward slashes while running on Windows. + $parts = explode('/', $sniffFile); + } + + $sniffName = array_pop($parts); + $sniffCategory = array_pop($parts); + array_pop($parts); + $sniffStandard = array_pop($parts); + $todo[] = $sniffStandard.'.'.$sniffCategory.'.'.substr($sniffName, 0, -9); + } + } + + foreach ($todo as $code) { + // Custom severity. + if (isset($rule->severity) === true + && $this->shouldProcessElement($rule->severity) === true + ) { + if (isset($this->ruleset[$code]) === false) { + $this->ruleset[$code] = []; + } + + $this->ruleset[$code]['severity'] = (int) $rule->severity; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> severity set to ".(int) $rule->severity; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + } + + // Custom message type. + if (isset($rule->type) === true + && $this->shouldProcessElement($rule->type) === true + ) { + if (isset($this->ruleset[$code]) === false) { + $this->ruleset[$code] = []; + } + + $type = strtolower((string) $rule->type); + if ($type !== 'error' && $type !== 'warning') { + throw new RuntimeException("Message type \"$type\" is invalid; must be \"error\" or \"warning\""); + } + + $this->ruleset[$code]['type'] = $type; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> message type set to ".(string) $rule->type; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + }//end if + + // Custom message. + if (isset($rule->message) === true + && $this->shouldProcessElement($rule->message) === true + ) { + if (isset($this->ruleset[$code]) === false) { + $this->ruleset[$code] = []; + } + + $this->ruleset[$code]['message'] = (string) $rule->message; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> message set to ".(string) $rule->message; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + } + + // Custom properties. + if (isset($rule->properties) === true + && $this->shouldProcessElement($rule->properties) === true + ) { + foreach ($rule->properties->property as $prop) { + if ($this->shouldProcessElement($prop) === false) { + continue; + } + + if (isset($this->ruleset[$code]) === false) { + $this->ruleset[$code] = [ + 'properties' => [], + ]; + } else if (isset($this->ruleset[$code]['properties']) === false) { + $this->ruleset[$code]['properties'] = []; + } + + $name = (string) $prop['name']; + if (isset($prop['type']) === true + && (string) $prop['type'] === 'array' + ) { + $values = []; + if (isset($prop['extend']) === true + && (string) $prop['extend'] === 'true' + && isset($this->ruleset[$code]['properties'][$name]) === true + ) { + $values = $this->ruleset[$code]['properties'][$name]; + } + + if (isset($prop->element) === true) { + $printValue = ''; + foreach ($prop->element as $element) { + if ($this->shouldProcessElement($element) === false) { + continue; + } + + $value = (string) $element['value']; + if (isset($element['key']) === true) { + $key = (string) $element['key']; + $values[$key] = $value; + $printValue .= $key.'=>'.$value.','; + } else { + $values[] = $value; + $printValue .= $value.','; + } + } + + $printValue = rtrim($printValue, ','); + } else { + $value = (string) $prop['value']; + $printValue = $value; + foreach (explode(',', $value) as $val) { + list($k, $v) = explode('=>', $val.'=>'); + if ($v !== '') { + $values[trim($k)] = trim($v); + } else { + $values[] = trim($k); + } + } + }//end if + + $this->ruleset[$code]['properties'][$name] = $values; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> array property \"$name\" set to \"$printValue\""; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + } else { + $this->ruleset[$code]['properties'][$name] = (string) $prop['value']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> property \"$name\" set to \"".(string) $prop['value'].'"'; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + }//end if + }//end foreach + }//end if + + // Ignore patterns. + foreach ($rule->{'exclude-pattern'} as $pattern) { + if ($this->shouldProcessElement($pattern) === false) { + continue; + } + + if (isset($this->ignorePatterns[$code]) === false) { + $this->ignorePatterns[$code] = []; + } + + if (isset($pattern['type']) === false) { + $pattern['type'] = 'absolute'; + } + + $this->ignorePatterns[$code][(string) $pattern] = (string) $pattern['type']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> added rule-specific ".(string) $pattern['type'].' ignore pattern'; + if ($code !== $ref) { + echo " for $code"; + } + + echo ': '.(string) $pattern.PHP_EOL; + } + }//end foreach + + // Include patterns. + foreach ($rule->{'include-pattern'} as $pattern) { + if ($this->shouldProcessElement($pattern) === false) { + continue; + } + + if (isset($this->includePatterns[$code]) === false) { + $this->includePatterns[$code] = []; + } + + if (isset($pattern['type']) === false) { + $pattern['type'] = 'absolute'; + } + + $this->includePatterns[$code][(string) $pattern] = (string) $pattern['type']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> added rule-specific ".(string) $pattern['type'].' include pattern'; + if ($code !== $ref) { + echo " for $code"; + } + + echo ': '.(string) $pattern.PHP_EOL; + } + }//end foreach + }//end foreach + + }//end processRule() + + + /** + * Determine if an element should be processed or ignored. + * + * @param \SimpleXMLElement $element An object from a ruleset XML file. + * + * @return bool + */ + private function shouldProcessElement($element) + { + if (isset($element['phpcbf-only']) === false + && isset($element['phpcs-only']) === false + ) { + // No exceptions are being made. + return true; + } + + if (PHP_CODESNIFFER_CBF === true + && isset($element['phpcbf-only']) === true + && (string) $element['phpcbf-only'] === 'true' + ) { + return true; + } + + if (PHP_CODESNIFFER_CBF === false + && isset($element['phpcs-only']) === true + && (string) $element['phpcs-only'] === 'true' + ) { + return true; + } + + return false; + + }//end shouldProcessElement() + + + /** + * Loads and stores sniffs objects used for sniffing files. + * + * @param array $files Paths to the sniff files to register. + * @param array $restrictions The sniff class names to restrict the allowed + * listeners to. + * @param array $exclusions The sniff class names to exclude from the + * listeners list. + * + * @return void + */ + public function registerSniffs($files, $restrictions, $exclusions) + { + $listeners = []; + + foreach ($files as $file) { + // Work out where the position of /StandardName/Sniffs/... is + // so we can determine what the class will be called. + $sniffPos = strrpos($file, DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR); + if ($sniffPos === false) { + continue; + } + + $slashPos = strrpos(substr($file, 0, $sniffPos), DIRECTORY_SEPARATOR); + if ($slashPos === false) { + continue; + } + + $className = Autoload::loadFile($file); + $compareName = Util\Common::cleanSniffClass($className); + + // If they have specified a list of sniffs to restrict to, check + // to see if this sniff is allowed. + if (empty($restrictions) === false + && isset($restrictions[$compareName]) === false + ) { + continue; + } + + // If they have specified a list of sniffs to exclude, check + // to see if this sniff is allowed. + if (empty($exclusions) === false + && isset($exclusions[$compareName]) === true + ) { + continue; + } + + // Skip abstract classes. + $reflection = new \ReflectionClass($className); + if ($reflection->isAbstract() === true) { + continue; + } + + $listeners[$className] = $className; + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + echo "Registered $className".PHP_EOL; + } + }//end foreach + + $this->sniffs = $listeners; + + }//end registerSniffs() + + + /** + * Populates the array of PHP_CodeSniffer_Sniff objects for this file. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If sniff registration fails. + */ + public function populateTokenListeners() + { + // Construct a list of listeners indexed by token being listened for. + $this->tokenListeners = []; + + foreach ($this->sniffs as $sniffClass => $sniffObject) { + $this->sniffs[$sniffClass] = null; + $this->sniffs[$sniffClass] = new $sniffClass(); + + $sniffCode = Util\Common::getSniffCode($sniffClass); + $this->sniffCodes[$sniffCode] = $sniffClass; + + // Set custom properties. + if (isset($this->ruleset[$sniffCode]['properties']) === true) { + foreach ($this->ruleset[$sniffCode]['properties'] as $name => $value) { + $this->setSniffProperty($sniffClass, $name, $value); + } + } + + $tokenizers = []; + $vars = get_class_vars($sniffClass); + if (isset($vars['supportedTokenizers']) === true) { + foreach ($vars['supportedTokenizers'] as $tokenizer) { + $tokenizers[$tokenizer] = $tokenizer; + } + } else { + $tokenizers = ['PHP' => 'PHP']; + } + + $tokens = $this->sniffs[$sniffClass]->register(); + if (is_array($tokens) === false) { + $msg = "Sniff $sniffClass register() method must return an array"; + throw new RuntimeException($msg); + } + + $ignorePatterns = []; + $patterns = $this->getIgnorePatterns($sniffCode); + foreach ($patterns as $pattern => $type) { + $replacements = [ + '\\,' => ',', + '*' => '.*', + ]; + + $ignorePatterns[] = strtr($pattern, $replacements); + } + + $includePatterns = []; + $patterns = $this->getIncludePatterns($sniffCode); + foreach ($patterns as $pattern => $type) { + $replacements = [ + '\\,' => ',', + '*' => '.*', + ]; + + $includePatterns[] = strtr($pattern, $replacements); + } + + foreach ($tokens as $token) { + if (isset($this->tokenListeners[$token]) === false) { + $this->tokenListeners[$token] = []; + } + + if (isset($this->tokenListeners[$token][$sniffClass]) === false) { + $this->tokenListeners[$token][$sniffClass] = [ + 'class' => $sniffClass, + 'source' => $sniffCode, + 'tokenizers' => $tokenizers, + 'ignore' => $ignorePatterns, + 'include' => $includePatterns, + ]; + } + } + }//end foreach + + }//end populateTokenListeners() + + + /** + * Set a single property for a sniff. + * + * @param string $sniffClass The class name of the sniff. + * @param string $name The name of the property to change. + * @param string $value The new value of the property. + * + * @return void + */ + public function setSniffProperty($sniffClass, $name, $value) + { + // Setting a property for a sniff we are not using. + if (isset($this->sniffs[$sniffClass]) === false) { + return; + } + + $name = trim($name); + if (is_string($value) === true) { + $value = trim($value); + } + + if ($value === '') { + $value = null; + } + + // Special case for booleans. + if ($value === 'true') { + $value = true; + } else if ($value === 'false') { + $value = false; + } else if (substr($name, -2) === '[]') { + $name = substr($name, 0, -2); + $values = []; + if ($value !== null) { + foreach (explode(',', $value) as $val) { + list($k, $v) = explode('=>', $val.'=>'); + if ($v !== '') { + $values[trim($k)] = trim($v); + } else { + $values[] = trim($k); + } + } + } + + $value = $values; + } + + $this->sniffs[$sniffClass]->$name = $value; + + }//end setSniffProperty() + + + /** + * Gets the array of ignore patterns. + * + * Optionally takes a listener to get ignore patterns specified + * for that sniff only. + * + * @param string $listener The listener to get patterns for. If NULL, all + * patterns are returned. + * + * @return array + */ + public function getIgnorePatterns($listener=null) + { + if ($listener === null) { + return $this->ignorePatterns; + } + + if (isset($this->ignorePatterns[$listener]) === true) { + return $this->ignorePatterns[$listener]; + } + + return []; + + }//end getIgnorePatterns() + + + /** + * Gets the array of include patterns. + * + * Optionally takes a listener to get include patterns specified + * for that sniff only. + * + * @param string $listener The listener to get patterns for. If NULL, all + * patterns are returned. + * + * @return array + */ + public function getIncludePatterns($listener=null) + { + if ($listener === null) { + return $this->includePatterns; + } + + if (isset($this->includePatterns[$listener]) === true) { + return $this->includePatterns[$listener]; + } + + return []; + + }//end getIncludePatterns() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Runner.php b/vendor/squizlabs/php_codesniffer/src/Runner.php new file mode 100644 index 00000000..fa68ff51 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Runner.php @@ -0,0 +1,889 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use PHP_CodeSniffer\Exceptions\DeepExitException; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Files\DummyFile; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Files\FileList; +use PHP_CodeSniffer\Util\Cache; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Standards; + +class Runner +{ + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + public $config = null; + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + public $ruleset = null; + + /** + * The reporter used for generating reports after the run. + * + * @var \PHP_CodeSniffer\Reporter + */ + public $reporter = null; + + + /** + * Run the PHPCS script. + * + * @return array + */ + public function runPHPCS() + { + try { + Util\Timing::startTiming(); + Runner::checkRequirements(); + + if (defined('PHP_CODESNIFFER_CBF') === false) { + define('PHP_CODESNIFFER_CBF', false); + } + + // Creating the Config object populates it with all required settings + // based on the CLI arguments provided to the script and any config + // values the user has set. + $this->config = new Config(); + + // Init the run and load the rulesets to set additional config vars. + $this->init(); + + // Print a list of sniffs in each of the supplied standards. + // We fudge the config here so that each standard is explained in isolation. + if ($this->config->explain === true) { + $standards = $this->config->standards; + foreach ($standards as $standard) { + $this->config->standards = [$standard]; + $ruleset = new Ruleset($this->config); + $ruleset->explain(); + } + + return 0; + } + + // Generate documentation for each of the supplied standards. + if ($this->config->generator !== null) { + $standards = $this->config->standards; + foreach ($standards as $standard) { + $this->config->standards = [$standard]; + $ruleset = new Ruleset($this->config); + $class = 'PHP_CodeSniffer\Generators\\'.$this->config->generator; + $generator = new $class($ruleset); + $generator->generate(); + } + + return 0; + } + + // Other report formats don't really make sense in interactive mode + // so we hard-code the full report here and when outputting. + // We also ensure parallel processing is off because we need to do one file at a time. + if ($this->config->interactive === true) { + $this->config->reports = ['full' => null]; + $this->config->parallel = 1; + $this->config->showProgress = false; + } + + // Disable caching if we are processing STDIN as we can't be 100% + // sure where the file came from or if it will change in the future. + if ($this->config->stdin === true) { + $this->config->cache = false; + } + + $numErrors = $this->run(); + + // Print all the reports for this run. + $toScreen = $this->reporter->printReports(); + + // Only print timer output if no reports were + // printed to the screen so we don't put additional output + // in something like an XML report. If we are printing to screen, + // the report types would have already worked out who should + // print the timer info. + if ($this->config->interactive === false + && ($toScreen === false + || (($this->reporter->totalErrors + $this->reporter->totalWarnings) === 0 && $this->config->showProgress === true)) + ) { + Util\Timing::printRunTime(); + } + } catch (DeepExitException $e) { + echo $e->getMessage(); + return $e->getCode(); + }//end try + + if ($numErrors === 0) { + // No errors found. + return 0; + } else if ($this->reporter->totalFixable === 0) { + // Errors found, but none of them can be fixed by PHPCBF. + return 1; + } else { + // Errors found, and some can be fixed by PHPCBF. + return 2; + } + + }//end runPHPCS() + + + /** + * Run the PHPCBF script. + * + * @return array + */ + public function runPHPCBF() + { + if (defined('PHP_CODESNIFFER_CBF') === false) { + define('PHP_CODESNIFFER_CBF', true); + } + + try { + Util\Timing::startTiming(); + Runner::checkRequirements(); + + // Creating the Config object populates it with all required settings + // based on the CLI arguments provided to the script and any config + // values the user has set. + $this->config = new Config(); + + // When processing STDIN, we can't output anything to the screen + // or it will end up mixed in with the file output. + if ($this->config->stdin === true) { + $this->config->verbosity = 0; + } + + // Init the run and load the rulesets to set additional config vars. + $this->init(); + + // When processing STDIN, we only process one file at a time and + // we don't process all the way through, so we can't use the parallel + // running system. + if ($this->config->stdin === true) { + $this->config->parallel = 1; + } + + // Override some of the command line settings that might break the fixes. + $this->config->generator = null; + $this->config->explain = false; + $this->config->interactive = false; + $this->config->cache = false; + $this->config->showSources = false; + $this->config->recordErrors = false; + $this->config->reportFile = null; + $this->config->reports = ['cbf' => null]; + + // If a standard tries to set command line arguments itself, some + // may be blocked because PHPCBF is running, so stop the script + // dying if any are found. + $this->config->dieOnUnknownArg = false; + + $this->run(); + $this->reporter->printReports(); + + echo PHP_EOL; + Util\Timing::printRunTime(); + } catch (DeepExitException $e) { + echo $e->getMessage(); + return $e->getCode(); + }//end try + + if ($this->reporter->totalFixed === 0) { + // Nothing was fixed by PHPCBF. + if ($this->reporter->totalFixable === 0) { + // Nothing found that could be fixed. + return 0; + } else { + // Something failed to fix. + return 2; + } + } + + if ($this->reporter->totalFixable === 0) { + // PHPCBF fixed all fixable errors. + return 1; + } + + // PHPCBF fixed some fixable errors, but others failed to fix. + return 2; + + }//end runPHPCBF() + + + /** + * Exits if the minimum requirements of PHP_CodeSniffer are not met. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If the requirements are not met. + */ + public function checkRequirements() + { + // Check the PHP version. + if (PHP_VERSION_ID < 50400) { + $error = 'ERROR: PHP_CodeSniffer requires PHP version 5.4.0 or greater.'.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $requiredExtensions = [ + 'tokenizer', + 'xmlwriter', + 'SimpleXML', + ]; + $missingExtensions = []; + + foreach ($requiredExtensions as $extension) { + if (extension_loaded($extension) === false) { + $missingExtensions[] = $extension; + } + } + + if (empty($missingExtensions) === false) { + $last = array_pop($requiredExtensions); + $required = implode(', ', $requiredExtensions); + $required .= ' and '.$last; + + if (count($missingExtensions) === 1) { + $missing = $missingExtensions[0]; + } else { + $last = array_pop($missingExtensions); + $missing = implode(', ', $missingExtensions); + $missing .= ' and '.$last; + } + + $error = 'ERROR: PHP_CodeSniffer requires the %s extensions to be enabled. Please enable %s.'.PHP_EOL; + $error = sprintf($error, $required, $missing); + throw new DeepExitException($error, 3); + } + + }//end checkRequirements() + + + /** + * Init the rulesets and other high-level settings. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If a referenced standard is not installed. + */ + public function init() + { + if (defined('PHP_CODESNIFFER_CBF') === false) { + define('PHP_CODESNIFFER_CBF', false); + } + + // Ensure this option is enabled or else line endings will not always + // be detected properly for files created on a Mac with the /r line ending. + @ini_set('auto_detect_line_endings', true); + + // Disable the PCRE JIT as this caused issues with parallel running. + ini_set('pcre.jit', false); + + // Check that the standards are valid. + foreach ($this->config->standards as $standard) { + if (Util\Standards::isInstalledStandard($standard) === false) { + // They didn't select a valid coding standard, so help them + // out by letting them know which standards are installed. + $error = 'ERROR: the "'.$standard.'" coding standard is not installed. '; + ob_start(); + Util\Standards::printInstalledStandards(); + $error .= ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($error, 3); + } + } + + // Saves passing the Config object into other objects that only need + // the verbosity flag for debug output. + if (defined('PHP_CODESNIFFER_VERBOSITY') === false) { + define('PHP_CODESNIFFER_VERBOSITY', $this->config->verbosity); + } + + // Create this class so it is autoloaded and sets up a bunch + // of PHP_CodeSniffer-specific token type constants. + $tokens = new Util\Tokens(); + + // Allow autoloading of custom files inside installed standards. + $installedStandards = Standards::getInstalledStandardDetails(); + foreach ($installedStandards as $name => $details) { + Autoload::addSearchPath($details['path'], $details['namespace']); + } + + // The ruleset contains all the information about how the files + // should be checked and/or fixed. + try { + $this->ruleset = new Ruleset($this->config); + } catch (RuntimeException $e) { + $error = 'ERROR: '.$e->getMessage().PHP_EOL.PHP_EOL; + $error .= $this->config->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + }//end init() + + + /** + * Performs the run. + * + * @return int The number of errors and warnings found. + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException + */ + private function run() + { + // The class that manages all reporters for the run. + $this->reporter = new Reporter($this->config); + + // Include bootstrap files. + foreach ($this->config->bootstrap as $bootstrap) { + include $bootstrap; + } + + if ($this->config->stdin === true) { + $fileContents = $this->config->stdinContent; + if ($fileContents === null) { + $handle = fopen('php://stdin', 'r'); + stream_set_blocking($handle, true); + $fileContents = stream_get_contents($handle); + fclose($handle); + } + + $todo = new FileList($this->config, $this->ruleset); + $dummy = new DummyFile($fileContents, $this->ruleset, $this->config); + $todo->addFile($dummy->path, $dummy); + } else { + if (empty($this->config->files) === true) { + $error = 'ERROR: You must supply at least one file or directory to process.'.PHP_EOL.PHP_EOL; + $error .= $this->config->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Creating file list... '; + } + + $todo = new FileList($this->config, $this->ruleset); + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + $numFiles = count($todo); + echo "DONE ($numFiles files in queue)".PHP_EOL; + } + + if ($this->config->cache === true) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Loading cache... '; + } + + Cache::load($this->ruleset, $this->config); + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + $size = Cache::getSize(); + echo "DONE ($size files in cache)".PHP_EOL; + } + } + }//end if + + // Turn all sniff errors into exceptions. + set_error_handler([$this, 'handleErrors']); + + // If verbosity is too high, turn off parallelism so the + // debug output is clean. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $this->config->parallel = 1; + } + + // If the PCNTL extension isn't installed, we can't fork. + if (function_exists('pcntl_fork') === false) { + $this->config->parallel = 1; + } + + $lastDir = ''; + $numFiles = count($todo); + + if ($this->config->parallel === 1) { + // Running normally. + $numProcessed = 0; + foreach ($todo as $path => $file) { + if ($file->ignored === false) { + $currDir = dirname($path); + if ($lastDir !== $currDir) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Changing into directory '.Common::stripBasepath($currDir, $this->config->basepath).PHP_EOL; + } + + $lastDir = $currDir; + } + + $this->processFile($file); + } else if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Skipping '.basename($file->path).PHP_EOL; + } + + $numProcessed++; + $this->printProgress($file, $numFiles, $numProcessed); + } + } else { + // Batching and forking. + $childProcs = []; + $numPerBatch = ceil($numFiles / $this->config->parallel); + + for ($batch = 0; $batch < $this->config->parallel; $batch++) { + $startAt = ($batch * $numPerBatch); + if ($startAt >= $numFiles) { + break; + } + + $endAt = ($startAt + $numPerBatch); + if ($endAt > $numFiles) { + $endAt = $numFiles; + } + + $childOutFilename = tempnam(sys_get_temp_dir(), 'phpcs-child'); + $pid = pcntl_fork(); + if ($pid === -1) { + throw new RuntimeException('Failed to create child process'); + } else if ($pid !== 0) { + $childProcs[$pid] = $childOutFilename; + } else { + // Move forward to the start of the batch. + $todo->rewind(); + for ($i = 0; $i < $startAt; $i++) { + $todo->next(); + } + + // Reset the reporter to make sure only figures from this + // file batch are recorded. + $this->reporter->totalFiles = 0; + $this->reporter->totalErrors = 0; + $this->reporter->totalWarnings = 0; + $this->reporter->totalFixable = 0; + $this->reporter->totalFixed = 0; + + // Process the files. + $pathsProcessed = []; + ob_start(); + for ($i = $startAt; $i < $endAt; $i++) { + $path = $todo->key(); + $file = $todo->current(); + + if ($file->ignored === true) { + $todo->next(); + continue; + } + + $currDir = dirname($path); + if ($lastDir !== $currDir) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Changing into directory '.Common::stripBasepath($currDir, $this->config->basepath).PHP_EOL; + } + + $lastDir = $currDir; + } + + $this->processFile($file); + + $pathsProcessed[] = $path; + $todo->next(); + }//end for + + $debugOutput = ob_get_contents(); + ob_end_clean(); + + // Write information about the run to the filesystem + // so it can be picked up by the main process. + $childOutput = [ + 'totalFiles' => $this->reporter->totalFiles, + 'totalErrors' => $this->reporter->totalErrors, + 'totalWarnings' => $this->reporter->totalWarnings, + 'totalFixable' => $this->reporter->totalFixable, + 'totalFixed' => $this->reporter->totalFixed, + ]; + + $output = '<'.'?php'."\n".' $childOutput = '; + $output .= var_export($childOutput, true); + $output .= ";\n\$debugOutput = "; + $output .= var_export($debugOutput, true); + + if ($this->config->cache === true) { + $childCache = []; + foreach ($pathsProcessed as $path) { + $childCache[$path] = Cache::get($path); + } + + $output .= ";\n\$childCache = "; + $output .= var_export($childCache, true); + } + + $output .= ";\n?".'>'; + file_put_contents($childOutFilename, $output); + exit(); + }//end if + }//end for + + $success = $this->processChildProcs($childProcs); + if ($success === false) { + throw new RuntimeException('One or more child processes failed to run'); + } + }//end if + + restore_error_handler(); + + if (PHP_CODESNIFFER_VERBOSITY === 0 + && $this->config->interactive === false + && $this->config->showProgress === true + ) { + echo PHP_EOL.PHP_EOL; + } + + if ($this->config->cache === true) { + Cache::save(); + } + + $ignoreWarnings = Config::getConfigData('ignore_warnings_on_exit'); + $ignoreErrors = Config::getConfigData('ignore_errors_on_exit'); + + $return = ($this->reporter->totalErrors + $this->reporter->totalWarnings); + if ($ignoreErrors !== null) { + $ignoreErrors = (bool) $ignoreErrors; + if ($ignoreErrors === true) { + $return -= $this->reporter->totalErrors; + } + } + + if ($ignoreWarnings !== null) { + $ignoreWarnings = (bool) $ignoreWarnings; + if ($ignoreWarnings === true) { + $return -= $this->reporter->totalWarnings; + } + } + + return $return; + + }//end run() + + + /** + * Converts all PHP errors into exceptions. + * + * This method forces a sniff to stop processing if it is not + * able to handle a specific piece of code, instead of continuing + * and potentially getting into a loop. + * + * @param int $code The level of error raised. + * @param string $message The error message. + * @param string $file The path of the file that raised the error. + * @param int $line The line number the error was raised at. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException + */ + public function handleErrors($code, $message, $file, $line) + { + if ((error_reporting() & $code) === 0) { + // This type of error is being muted. + return true; + } + + throw new RuntimeException("$message in $file on line $line"); + + }//end handleErrors() + + + /** + * Processes a single file, including checking and fixing. + * + * @param \PHP_CodeSniffer\Files\File $file The file to be processed. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processFile($file) + { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + $startTime = microtime(true); + echo 'Processing '.basename($file->path).' '; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + try { + $file->process(); + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + $timeTaken = ((microtime(true) - $startTime) * 1000); + if ($timeTaken < 1000) { + $timeTaken = round($timeTaken); + echo "DONE in {$timeTaken}ms"; + } else { + $timeTaken = round(($timeTaken / 1000), 2); + echo "DONE in $timeTaken secs"; + } + + if (PHP_CODESNIFFER_CBF === true) { + $errors = $file->getFixableCount(); + echo " ($errors fixable violations)".PHP_EOL; + } else { + $errors = $file->getErrorCount(); + $warnings = $file->getWarningCount(); + echo " ($errors errors, $warnings warnings)".PHP_EOL; + } + } + } catch (\Exception $e) { + $error = 'An error occurred during processing; checking has been aborted. The error message was: '.$e->getMessage(); + $file->addErrorOnLine($error, 1, 'Internal.Exception'); + }//end try + + $this->reporter->cacheFileReport($file, $this->config); + + if ($this->config->interactive === true) { + /* + Running interactively. + Print the error report for the current file and then wait for user input. + */ + + // Get current violations and then clear the list to make sure + // we only print violations for a single file each time. + $numErrors = null; + while ($numErrors !== 0) { + $numErrors = ($file->getErrorCount() + $file->getWarningCount()); + if ($numErrors === 0) { + continue; + } + + $this->reporter->printReport('full'); + + echo ' to recheck, [s] to skip or [q] to quit : '; + $input = fgets(STDIN); + $input = trim($input); + + switch ($input) { + case 's': + break(2); + case 'q': + throw new DeepExitException('', 0); + default: + // Repopulate the sniffs because some of them save their state + // and only clear it when the file changes, but we are rechecking + // the same file. + $file->ruleset->populateTokenListeners(); + $file->reloadContent(); + $file->process(); + $this->reporter->cacheFileReport($file, $this->config); + break; + } + }//end while + }//end if + + // Clean up the file to save (a lot of) memory. + $file->cleanUp(); + + }//end processFile() + + + /** + * Waits for child processes to complete and cleans up after them. + * + * The reporting information returned by each child process is merged + * into the main reporter class. + * + * @param array $childProcs An array of child processes to wait for. + * + * @return bool + */ + private function processChildProcs($childProcs) + { + $numProcessed = 0; + $totalBatches = count($childProcs); + + $success = true; + + while (count($childProcs) > 0) { + $pid = pcntl_waitpid(0, $status); + if ($pid <= 0) { + continue; + } + + $out = $childProcs[$pid]; + unset($childProcs[$pid]); + if (file_exists($out) === false) { + continue; + } + + include $out; + unlink($out); + + $numProcessed++; + + if (isset($childOutput) === false) { + // The child process died, so the run has failed. + $file = new DummyFile('', $this->ruleset, $this->config); + $file->setErrorCounts(1, 0, 0, 0); + $this->printProgress($file, $totalBatches, $numProcessed); + $success = false; + continue; + } + + $this->reporter->totalFiles += $childOutput['totalFiles']; + $this->reporter->totalErrors += $childOutput['totalErrors']; + $this->reporter->totalWarnings += $childOutput['totalWarnings']; + $this->reporter->totalFixable += $childOutput['totalFixable']; + $this->reporter->totalFixed += $childOutput['totalFixed']; + + if (isset($debugOutput) === true) { + echo $debugOutput; + } + + if (isset($childCache) === true) { + foreach ($childCache as $path => $cache) { + Cache::set($path, $cache); + } + } + + // Fake a processed file so we can print progress output for the batch. + $file = new DummyFile('', $this->ruleset, $this->config); + $file->setErrorCounts( + $childOutput['totalErrors'], + $childOutput['totalWarnings'], + $childOutput['totalFixable'], + $childOutput['totalFixed'] + ); + $this->printProgress($file, $totalBatches, $numProcessed); + }//end while + + return $success; + + }//end processChildProcs() + + + /** + * Print progress information for a single processed file. + * + * @param \PHP_CodeSniffer\Files\File $file The file that was processed. + * @param int $numFiles The total number of files to process. + * @param int $numProcessed The number of files that have been processed, + * including this one. + * + * @return void + */ + public function printProgress(File $file, $numFiles, $numProcessed) + { + if (PHP_CODESNIFFER_VERBOSITY > 0 + || $this->config->showProgress === false + ) { + return; + } + + // Show progress information. + if ($file->ignored === true) { + echo 'S'; + } else { + $errors = $file->getErrorCount(); + $warnings = $file->getWarningCount(); + $fixable = $file->getFixableCount(); + $fixed = $file->getFixedCount(); + + if (PHP_CODESNIFFER_CBF === true) { + // Files with fixed errors or warnings are F (green). + // Files with unfixable errors or warnings are E (red). + // Files with no errors or warnings are . (black). + if ($fixable > 0) { + if ($this->config->colors === true) { + echo "\033[31m"; + } + + echo 'E'; + + if ($this->config->colors === true) { + echo "\033[0m"; + } + } else if ($fixed > 0) { + if ($this->config->colors === true) { + echo "\033[32m"; + } + + echo 'F'; + + if ($this->config->colors === true) { + echo "\033[0m"; + } + } else { + echo '.'; + }//end if + } else { + // Files with errors are E (red). + // Files with fixable errors are E (green). + // Files with warnings are W (yellow). + // Files with fixable warnings are W (green). + // Files with no errors or warnings are . (black). + if ($errors > 0) { + if ($this->config->colors === true) { + if ($fixable > 0) { + echo "\033[32m"; + } else { + echo "\033[31m"; + } + } + + echo 'E'; + + if ($this->config->colors === true) { + echo "\033[0m"; + } + } else if ($warnings > 0) { + if ($this->config->colors === true) { + if ($fixable > 0) { + echo "\033[32m"; + } else { + echo "\033[33m"; + } + } + + echo 'W'; + + if ($this->config->colors === true) { + echo "\033[0m"; + } + } else { + echo '.'; + }//end if + }//end if + }//end if + + $numPerLine = 60; + if ($numProcessed !== $numFiles && ($numProcessed % $numPerLine) !== 0) { + return; + } + + $percent = round(($numProcessed / $numFiles) * 100); + $padding = (strlen($numFiles) - strlen($numProcessed)); + if ($numProcessed === $numFiles + && $numFiles > $numPerLine + && ($numProcessed % $numPerLine) !== 0 + ) { + $padding += ($numPerLine - ($numFiles - (floor($numFiles / $numPerLine) * $numPerLine))); + } + + echo str_repeat(' ', $padding)." $numProcessed / $numFiles ($percent%)".PHP_EOL; + + }//end printProgress() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractArraySniff.php b/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractArraySniff.php new file mode 100644 index 00000000..141b9a13 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractArraySniff.php @@ -0,0 +1,172 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +abstract class AbstractArraySniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + final public function register() + { + return [ + T_ARRAY, + T_OPEN_SHORT_ARRAY, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_ARRAY) { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'no'); + + $arrayStart = $tokens[$stackPtr]['parenthesis_opener']; + if (isset($tokens[$arrayStart]['parenthesis_closer']) === false) { + // Incomplete array. + return; + } + + $arrayEnd = $tokens[$arrayStart]['parenthesis_closer']; + } else { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'yes'); + $arrayStart = $stackPtr; + $arrayEnd = $tokens[$stackPtr]['bracket_closer']; + } + + $lastContent = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($arrayEnd - 1), null, true); + if ($tokens[$lastContent]['code'] === T_COMMA) { + // Last array item ends with a comma. + $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'yes'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'no'); + } + + $indices = []; + + $current = $arrayStart; + while (($next = $phpcsFile->findNext(Tokens::$emptyTokens, ($current + 1), $arrayEnd, true)) !== false) { + $end = $this->getNext($phpcsFile, $next, $arrayEnd); + + if ($tokens[$end]['code'] === T_DOUBLE_ARROW) { + $indexEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($end - 1), null, true); + $valueStart = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + + $indices[] = [ + 'index_start' => $next, + 'index_end' => $indexEnd, + 'arrow' => $end, + 'value_start' => $valueStart, + ]; + } else { + $valueStart = $next; + $indices[] = ['value_start' => $valueStart]; + } + + $current = $this->getNext($phpcsFile, $valueStart, $arrayEnd); + } + + if ($tokens[$arrayStart]['line'] === $tokens[$arrayEnd]['line']) { + $this->processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices); + } else { + $this->processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices); + } + + }//end process() + + + /** + * Find next separator in array - either: comma or double arrow. + * + * @param File $phpcsFile The current file being checked. + * @param int $ptr The position of current token. + * @param int $arrayEnd The token that ends the array definition. + * + * @return int + */ + private function getNext(File $phpcsFile, $ptr, $arrayEnd) + { + $tokens = $phpcsFile->getTokens(); + + while ($ptr < $arrayEnd) { + if (isset($tokens[$ptr]['scope_closer']) === true) { + $ptr = $tokens[$ptr]['scope_closer']; + } else if (isset($tokens[$ptr]['parenthesis_closer']) === true) { + $ptr = $tokens[$ptr]['parenthesis_closer']; + } else if (isset($tokens[$ptr]['bracket_closer']) === true) { + $ptr = $tokens[$ptr]['bracket_closer']; + } + + if ($tokens[$ptr]['code'] === T_COMMA + || $tokens[$ptr]['code'] === T_DOUBLE_ARROW + ) { + return $ptr; + } + + ++$ptr; + } + + return $ptr; + + }//end getNext() + + + /** + * Processes a single-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + abstract protected function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices); + + + /** + * Processes a multi-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + abstract protected function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices); + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractPatternSniff.php b/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractPatternSniff.php new file mode 100644 index 00000000..66bc2f52 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractPatternSniff.php @@ -0,0 +1,936 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; +use PHP_CodeSniffer\Tokenizers\PHP; +use PHP_CodeSniffer\Exceptions\RuntimeException; + +abstract class AbstractPatternSniff implements Sniff +{ + + /** + * If true, comments will be ignored if they are found in the code. + * + * @var boolean + */ + public $ignoreComments = false; + + /** + * The current file being checked. + * + * @var string + */ + protected $currFile = ''; + + /** + * The parsed patterns array. + * + * @var array + */ + private $parsedPatterns = []; + + /** + * Tokens that this sniff wishes to process outside of the patterns. + * + * @var int[] + * @see registerSupplementary() + * @see processSupplementary() + */ + private $supplementaryTokens = []; + + /** + * Positions in the stack where errors have occurred. + * + * @var array + */ + private $errorPos = []; + + + /** + * Constructs a AbstractPatternSniff. + * + * @param boolean $ignoreComments If true, comments will be ignored. + */ + public function __construct($ignoreComments=null) + { + // This is here for backwards compatibility. + if ($ignoreComments !== null) { + $this->ignoreComments = $ignoreComments; + } + + $this->supplementaryTokens = $this->registerSupplementary(); + + }//end __construct() + + + /** + * Registers the tokens to listen to. + * + * Classes extending AbstractPatternTest should implement the + * getPatterns() method to register the patterns they wish to test. + * + * @return int[] + * @see process() + */ + final public function register() + { + $listenTypes = []; + $patterns = $this->getPatterns(); + + foreach ($patterns as $pattern) { + $parsedPattern = $this->parse($pattern); + + // Find a token position in the pattern that we can use + // for a listener token. + $pos = $this->getListenerTokenPos($parsedPattern); + $tokenType = $parsedPattern[$pos]['token']; + $listenTypes[] = $tokenType; + + $patternArray = [ + 'listen_pos' => $pos, + 'pattern' => $parsedPattern, + 'pattern_code' => $pattern, + ]; + + if (isset($this->parsedPatterns[$tokenType]) === false) { + $this->parsedPatterns[$tokenType] = []; + } + + $this->parsedPatterns[$tokenType][] = $patternArray; + }//end foreach + + return array_unique(array_merge($listenTypes, $this->supplementaryTokens)); + + }//end register() + + + /** + * Returns the token types that the specified pattern is checking for. + * + * Returned array is in the format: + * + * array( + * T_WHITESPACE => 0, // 0 is the position where the T_WHITESPACE token + * // should occur in the pattern. + * ); + * + * + * @param array $pattern The parsed pattern to find the acquire the token + * types from. + * + * @return array + */ + private function getPatternTokenTypes($pattern) + { + $tokenTypes = []; + foreach ($pattern as $pos => $patternInfo) { + if ($patternInfo['type'] === 'token') { + if (isset($tokenTypes[$patternInfo['token']]) === false) { + $tokenTypes[$patternInfo['token']] = $pos; + } + } + } + + return $tokenTypes; + + }//end getPatternTokenTypes() + + + /** + * Returns the position in the pattern that this test should register as + * a listener for the pattern. + * + * @param array $pattern The pattern to acquire the listener for. + * + * @return int The position in the pattern that this test should register + * as the listener. + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If we could not determine a token to listen for. + */ + private function getListenerTokenPos($pattern) + { + $tokenTypes = $this->getPatternTokenTypes($pattern); + $tokenCodes = array_keys($tokenTypes); + $token = Tokens::getHighestWeightedToken($tokenCodes); + + // If we could not get a token. + if ($token === false) { + $error = 'Could not determine a token to listen for'; + throw new RuntimeException($error); + } + + return $tokenTypes[$token]; + + }//end getListenerTokenPos() + + + /** + * Processes the test. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ + final public function process(File $phpcsFile, $stackPtr) + { + $file = $phpcsFile->getFilename(); + if ($this->currFile !== $file) { + // We have changed files, so clean up. + $this->errorPos = []; + $this->currFile = $file; + } + + $tokens = $phpcsFile->getTokens(); + + if (in_array($tokens[$stackPtr]['code'], $this->supplementaryTokens, true) === true) { + $this->processSupplementary($phpcsFile, $stackPtr); + } + + $type = $tokens[$stackPtr]['code']; + + // If the type is not set, then it must have been a token registered + // with registerSupplementary(). + if (isset($this->parsedPatterns[$type]) === false) { + return; + } + + $allErrors = []; + + // Loop over each pattern that is listening to the current token type + // that we are processing. + foreach ($this->parsedPatterns[$type] as $patternInfo) { + // If processPattern returns false, then the pattern that we are + // checking the code with must not be designed to check that code. + $errors = $this->processPattern($patternInfo, $phpcsFile, $stackPtr); + if ($errors === false) { + // The pattern didn't match. + continue; + } else if (empty($errors) === true) { + // The pattern matched, but there were no errors. + break; + } + + foreach ($errors as $stackPtr => $error) { + if (isset($this->errorPos[$stackPtr]) === false) { + $this->errorPos[$stackPtr] = true; + $allErrors[$stackPtr] = $error; + } + } + } + + foreach ($allErrors as $stackPtr => $error) { + $phpcsFile->addError($error, $stackPtr, 'Found'); + } + + }//end process() + + + /** + * Processes the pattern and verifies the code at $stackPtr. + * + * @param array $patternInfo Information about the pattern used + * for checking, which includes are + * parsed token representation of the + * pattern. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack where + * the listening token type was found. + * + * @return array + */ + protected function processPattern($patternInfo, File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $pattern = $patternInfo['pattern']; + $patternCode = $patternInfo['pattern_code']; + $errors = []; + $found = ''; + + $ignoreTokens = [T_WHITESPACE => T_WHITESPACE]; + if ($this->ignoreComments === true) { + $ignoreTokens += Tokens::$commentTokens; + } + + $origStackPtr = $stackPtr; + $hasError = false; + + if ($patternInfo['listen_pos'] > 0) { + $stackPtr--; + + for ($i = ($patternInfo['listen_pos'] - 1); $i >= 0; $i--) { + if ($pattern[$i]['type'] === 'token') { + if ($pattern[$i]['token'] === T_WHITESPACE) { + if ($tokens[$stackPtr]['code'] === T_WHITESPACE) { + $found = $tokens[$stackPtr]['content'].$found; + } + + // Only check the size of the whitespace if this is not + // the first token. We don't care about the size of + // leading whitespace, just that there is some. + if ($i !== 0) { + if ($tokens[$stackPtr]['content'] !== $pattern[$i]['value']) { + $hasError = true; + } + } + } else { + // Check to see if this important token is the same as the + // previous important token in the pattern. If it is not, + // then the pattern cannot be for this piece of code. + $prev = $phpcsFile->findPrevious( + $ignoreTokens, + $stackPtr, + null, + true + ); + + if ($prev === false + || $tokens[$prev]['code'] !== $pattern[$i]['token'] + ) { + return false; + } + + // If we skipped past some whitespace tokens, then add them + // to the found string. + $tokenContent = $phpcsFile->getTokensAsString( + ($prev + 1), + ($stackPtr - $prev - 1) + ); + + $found = $tokens[$prev]['content'].$tokenContent.$found; + + if (isset($pattern[($i - 1)]) === true + && $pattern[($i - 1)]['type'] === 'skip' + ) { + $stackPtr = $prev; + } else { + $stackPtr = ($prev - 1); + } + }//end if + } else if ($pattern[$i]['type'] === 'skip') { + // Skip to next piece of relevant code. + if ($pattern[$i]['to'] === 'parenthesis_closer') { + $to = 'parenthesis_opener'; + } else { + $to = 'scope_opener'; + } + + // Find the previous opener. + $next = $phpcsFile->findPrevious( + $ignoreTokens, + $stackPtr, + null, + true + ); + + if ($next === false || isset($tokens[$next][$to]) === false) { + // If there was not opener, then we must be + // using the wrong pattern. + return false; + } + + if ($to === 'parenthesis_opener') { + $found = '{'.$found; + } else { + $found = '('.$found; + } + + $found = '...'.$found; + + // Skip to the opening token. + $stackPtr = ($tokens[$next][$to] - 1); + } else if ($pattern[$i]['type'] === 'string') { + $found = 'abc'; + } else if ($pattern[$i]['type'] === 'newline') { + if ($this->ignoreComments === true + && isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true + ) { + $startComment = $phpcsFile->findPrevious( + Tokens::$commentTokens, + ($stackPtr - 1), + null, + true + ); + + if ($tokens[$startComment]['line'] !== $tokens[($startComment + 1)]['line']) { + $startComment++; + } + + $tokenContent = $phpcsFile->getTokensAsString( + $startComment, + ($stackPtr - $startComment + 1) + ); + + $found = $tokenContent.$found; + $stackPtr = ($startComment - 1); + } + + if ($tokens[$stackPtr]['code'] === T_WHITESPACE) { + if ($tokens[$stackPtr]['content'] !== $phpcsFile->eolChar) { + $found = $tokens[$stackPtr]['content'].$found; + + // This may just be an indent that comes after a newline + // so check the token before to make sure. If it is a newline, we + // can ignore the error here. + if (($tokens[($stackPtr - 1)]['content'] !== $phpcsFile->eolChar) + && ($this->ignoreComments === true + && isset(Tokens::$commentTokens[$tokens[($stackPtr - 1)]['code']]) === false) + ) { + $hasError = true; + } else { + $stackPtr--; + } + } else { + $found = 'EOL'.$found; + } + } else { + $found = $tokens[$stackPtr]['content'].$found; + $hasError = true; + }//end if + + if ($hasError === false && $pattern[($i - 1)]['type'] !== 'newline') { + // Make sure they only have 1 newline. + $prev = $phpcsFile->findPrevious($ignoreTokens, ($stackPtr - 1), null, true); + if ($prev !== false && $tokens[$prev]['line'] !== $tokens[$stackPtr]['line']) { + $hasError = true; + } + } + }//end if + }//end for + }//end if + + $stackPtr = $origStackPtr; + $lastAddedStackPtr = null; + $patternLen = count($pattern); + + for ($i = $patternInfo['listen_pos']; $i < $patternLen; $i++) { + if (isset($tokens[$stackPtr]) === false) { + break; + } + + if ($pattern[$i]['type'] === 'token') { + if ($pattern[$i]['token'] === T_WHITESPACE) { + if ($this->ignoreComments === true) { + // If we are ignoring comments, check to see if this current + // token is a comment. If so skip it. + if (isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true) { + continue; + } + + // If the next token is a comment, the we need to skip the + // current token as we should allow a space before a + // comment for readability. + if (isset($tokens[($stackPtr + 1)]) === true + && isset(Tokens::$commentTokens[$tokens[($stackPtr + 1)]['code']]) === true + ) { + continue; + } + } + + $tokenContent = ''; + if ($tokens[$stackPtr]['code'] === T_WHITESPACE) { + if (isset($pattern[($i + 1)]) === false) { + // This is the last token in the pattern, so just compare + // the next token of content. + $tokenContent = $tokens[$stackPtr]['content']; + } else { + // Get all the whitespace to the next token. + $next = $phpcsFile->findNext( + Tokens::$emptyTokens, + $stackPtr, + null, + true + ); + + $tokenContent = $phpcsFile->getTokensAsString( + $stackPtr, + ($next - $stackPtr) + ); + + $lastAddedStackPtr = $stackPtr; + $stackPtr = $next; + }//end if + + if ($stackPtr !== $lastAddedStackPtr) { + $found .= $tokenContent; + } + } else { + if ($stackPtr !== $lastAddedStackPtr) { + $found .= $tokens[$stackPtr]['content']; + $lastAddedStackPtr = $stackPtr; + } + }//end if + + if (isset($pattern[($i + 1)]) === true + && $pattern[($i + 1)]['type'] === 'skip' + ) { + // The next token is a skip token, so we just need to make + // sure the whitespace we found has *at least* the + // whitespace required. + if (strpos($tokenContent, $pattern[$i]['value']) !== 0) { + $hasError = true; + } + } else { + if ($tokenContent !== $pattern[$i]['value']) { + $hasError = true; + } + } + } else { + // Check to see if this important token is the same as the + // next important token in the pattern. If it is not, then + // the pattern cannot be for this piece of code. + $next = $phpcsFile->findNext( + $ignoreTokens, + $stackPtr, + null, + true + ); + + if ($next === false + || $tokens[$next]['code'] !== $pattern[$i]['token'] + ) { + // The next important token did not match the pattern. + return false; + } + + if ($lastAddedStackPtr !== null) { + if (($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET + || $tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) + && isset($tokens[$next]['scope_condition']) === true + && $tokens[$next]['scope_condition'] > $lastAddedStackPtr + ) { + // This is a brace, but the owner of it is after the current + // token, which means it does not belong to any token in + // our pattern. This means the pattern is not for us. + return false; + } + + if (($tokens[$next]['code'] === T_OPEN_PARENTHESIS + || $tokens[$next]['code'] === T_CLOSE_PARENTHESIS) + && isset($tokens[$next]['parenthesis_owner']) === true + && $tokens[$next]['parenthesis_owner'] > $lastAddedStackPtr + ) { + // This is a bracket, but the owner of it is after the current + // token, which means it does not belong to any token in + // our pattern. This means the pattern is not for us. + return false; + } + }//end if + + // If we skipped past some whitespace tokens, then add them + // to the found string. + if (($next - $stackPtr) > 0) { + $hasComment = false; + for ($j = $stackPtr; $j < $next; $j++) { + $found .= $tokens[$j]['content']; + if (isset(Tokens::$commentTokens[$tokens[$j]['code']]) === true) { + $hasComment = true; + } + } + + // If we are not ignoring comments, this additional + // whitespace or comment is not allowed. If we are + // ignoring comments, there needs to be at least one + // comment for this to be allowed. + if ($this->ignoreComments === false + || ($this->ignoreComments === true + && $hasComment === false) + ) { + $hasError = true; + } + + // Even when ignoring comments, we are not allowed to include + // newlines without the pattern specifying them, so + // everything should be on the same line. + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + $hasError = true; + } + }//end if + + if ($next !== $lastAddedStackPtr) { + $found .= $tokens[$next]['content']; + $lastAddedStackPtr = $next; + } + + if (isset($pattern[($i + 1)]) === true + && $pattern[($i + 1)]['type'] === 'skip' + ) { + $stackPtr = $next; + } else { + $stackPtr = ($next + 1); + } + }//end if + } else if ($pattern[$i]['type'] === 'skip') { + if ($pattern[$i]['to'] === 'unknown') { + $next = $phpcsFile->findNext( + $pattern[($i + 1)]['token'], + $stackPtr + ); + + if ($next === false) { + // Couldn't find the next token, so we must + // be using the wrong pattern. + return false; + } + + $found .= '...'; + $stackPtr = $next; + } else { + // Find the previous opener. + $next = $phpcsFile->findPrevious( + Tokens::$blockOpeners, + $stackPtr + ); + + if ($next === false + || isset($tokens[$next][$pattern[$i]['to']]) === false + ) { + // If there was not opener, then we must + // be using the wrong pattern. + return false; + } + + $found .= '...'; + if ($pattern[$i]['to'] === 'parenthesis_closer') { + $found .= ')'; + } else { + $found .= '}'; + } + + // Skip to the closing token. + $stackPtr = ($tokens[$next][$pattern[$i]['to']] + 1); + }//end if + } else if ($pattern[$i]['type'] === 'string') { + if ($tokens[$stackPtr]['code'] !== T_STRING) { + $hasError = true; + } + + if ($stackPtr !== $lastAddedStackPtr) { + $found .= 'abc'; + $lastAddedStackPtr = $stackPtr; + } + + $stackPtr++; + } else if ($pattern[$i]['type'] === 'newline') { + // Find the next token that contains a newline character. + $newline = 0; + for ($j = $stackPtr; $j < $phpcsFile->numTokens; $j++) { + if (strpos($tokens[$j]['content'], $phpcsFile->eolChar) !== false) { + $newline = $j; + break; + } + } + + if ($newline === 0) { + // We didn't find a newline character in the rest of the file. + $next = ($phpcsFile->numTokens - 1); + $hasError = true; + } else { + if ($this->ignoreComments === false) { + // The newline character cannot be part of a comment. + if (isset(Tokens::$commentTokens[$tokens[$newline]['code']]) === true) { + $hasError = true; + } + } + + if ($newline === $stackPtr) { + $next = ($stackPtr + 1); + } else { + // Check that there were no significant tokens that we + // skipped over to find our newline character. + $next = $phpcsFile->findNext( + $ignoreTokens, + $stackPtr, + null, + true + ); + + if ($next < $newline) { + // We skipped a non-ignored token. + $hasError = true; + } else { + $next = ($newline + 1); + } + } + }//end if + + if ($stackPtr !== $lastAddedStackPtr) { + $found .= $phpcsFile->getTokensAsString( + $stackPtr, + ($next - $stackPtr) + ); + + $lastAddedStackPtr = ($next - 1); + } + + $stackPtr = $next; + }//end if + }//end for + + if ($hasError === true) { + $error = $this->prepareError($found, $patternCode); + $errors[$origStackPtr] = $error; + } + + return $errors; + + }//end processPattern() + + + /** + * Prepares an error for the specified patternCode. + * + * @param string $found The actual found string in the code. + * @param string $patternCode The expected pattern code. + * + * @return string The error message. + */ + protected function prepareError($found, $patternCode) + { + $found = str_replace("\r\n", '\n', $found); + $found = str_replace("\n", '\n', $found); + $found = str_replace("\r", '\n', $found); + $found = str_replace("\t", '\t', $found); + $found = str_replace('EOL', '\n', $found); + $expected = str_replace('EOL', '\n', $patternCode); + + $error = "Expected \"$expected\"; found \"$found\""; + + return $error; + + }//end prepareError() + + + /** + * Returns the patterns that should be checked. + * + * @return string[] + */ + abstract protected function getPatterns(); + + + /** + * Registers any supplementary tokens that this test might wish to process. + * + * A sniff may wish to register supplementary tests when it wishes to group + * an arbitrary validation that cannot be performed using a pattern, with + * other pattern tests. + * + * @return int[] + * @see processSupplementary() + */ + protected function registerSupplementary() + { + return []; + + }//end registerSupplementary() + + + /** + * Processes any tokens registered with registerSupplementary(). + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where to + * process the skip. + * @param int $stackPtr The position in the tokens stack to + * process. + * + * @return void + * @see registerSupplementary() + */ + protected function processSupplementary(File $phpcsFile, $stackPtr) + { + + }//end processSupplementary() + + + /** + * Parses a pattern string into an array of pattern steps. + * + * @param string $pattern The pattern to parse. + * + * @return array The parsed pattern array. + * @see createSkipPattern() + * @see createTokenPattern() + */ + private function parse($pattern) + { + $patterns = []; + $length = strlen($pattern); + $lastToken = 0; + $firstToken = 0; + + for ($i = 0; $i < $length; $i++) { + $specialPattern = false; + $isLastChar = ($i === ($length - 1)); + $oldFirstToken = $firstToken; + + if (substr($pattern, $i, 3) === '...') { + // It's a skip pattern. The skip pattern requires the + // content of the token in the "from" position and the token + // to skip to. + $specialPattern = $this->createSkipPattern($pattern, ($i - 1)); + $lastToken = ($i - $firstToken); + $firstToken = ($i + 3); + $i += 2; + + if ($specialPattern['to'] !== 'unknown') { + $firstToken++; + } + } else if (substr($pattern, $i, 3) === 'abc') { + $specialPattern = ['type' => 'string']; + $lastToken = ($i - $firstToken); + $firstToken = ($i + 3); + $i += 2; + } else if (substr($pattern, $i, 3) === 'EOL') { + $specialPattern = ['type' => 'newline']; + $lastToken = ($i - $firstToken); + $firstToken = ($i + 3); + $i += 2; + }//end if + + if ($specialPattern !== false || $isLastChar === true) { + // If we are at the end of the string, don't worry about a limit. + if ($isLastChar === true) { + // Get the string from the end of the last skip pattern, if any, + // to the end of the pattern string. + $str = substr($pattern, $oldFirstToken); + } else { + // Get the string from the end of the last special pattern, + // if any, to the start of this special pattern. + if ($lastToken === 0) { + // Note that if the last special token was zero characters ago, + // there will be nothing to process so we can skip this bit. + // This happens if you have something like: EOL... in your pattern. + $str = ''; + } else { + $str = substr($pattern, $oldFirstToken, $lastToken); + } + } + + if ($str !== '') { + $tokenPatterns = $this->createTokenPattern($str); + foreach ($tokenPatterns as $tokenPattern) { + $patterns[] = $tokenPattern; + } + } + + // Make sure we don't skip the last token. + if ($isLastChar === false && $i === ($length - 1)) { + $i--; + } + }//end if + + // Add the skip pattern *after* we have processed + // all the tokens from the end of the last skip pattern + // to the start of this skip pattern. + if ($specialPattern !== false) { + $patterns[] = $specialPattern; + } + }//end for + + return $patterns; + + }//end parse() + + + /** + * Creates a skip pattern. + * + * @param string $pattern The pattern being parsed. + * @param string $from The token content that the skip pattern starts from. + * + * @return array The pattern step. + * @see createTokenPattern() + * @see parse() + */ + private function createSkipPattern($pattern, $from) + { + $skip = ['type' => 'skip']; + + $nestedParenthesis = 0; + $nestedBraces = 0; + for ($start = $from; $start >= 0; $start--) { + switch ($pattern[$start]) { + case '(': + if ($nestedParenthesis === 0) { + $skip['to'] = 'parenthesis_closer'; + } + + $nestedParenthesis--; + break; + case '{': + if ($nestedBraces === 0) { + $skip['to'] = 'scope_closer'; + } + + $nestedBraces--; + break; + case '}': + $nestedBraces++; + break; + case ')': + $nestedParenthesis++; + break; + }//end switch + + if (isset($skip['to']) === true) { + break; + } + }//end for + + if (isset($skip['to']) === false) { + $skip['to'] = 'unknown'; + } + + return $skip; + + }//end createSkipPattern() + + + /** + * Creates a token pattern. + * + * @param string $str The tokens string that the pattern should match. + * + * @return array The pattern step. + * @see createSkipPattern() + * @see parse() + */ + private function createTokenPattern($str) + { + // Don't add a space after the closing php tag as it will add a new + // whitespace token. + $tokenizer = new PHP('', null); + + // Remove the getTokens(); + $tokens = array_slice($tokens, 1, (count($tokens) - 2)); + + $patterns = []; + foreach ($tokens as $patternInfo) { + $patterns[] = [ + 'type' => 'token', + 'token' => $patternInfo['code'], + 'value' => $patternInfo['content'], + ]; + } + + return $patterns; + + }//end createTokenPattern() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractScopeSniff.php b/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractScopeSniff.php new file mode 100644 index 00000000..70d8720a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractScopeSniff.php @@ -0,0 +1,191 @@ + + * class ClassScopeTest extends PHP_CodeSniffer_Standards_AbstractScopeSniff + * { + * public function __construct() + * { + * parent::__construct(array(T_CLASS), array(T_FUNCTION)); + * } + * + * protected function processTokenWithinScope(\PHP_CodeSniffer\Files\File $phpcsFile, $stackPtr, $currScope) + * { + * $className = $phpcsFile->getDeclarationName($currScope); + * echo 'encountered a method within class '.$className; + * } + * } + * + * + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Exceptions\RuntimeException; + +abstract class AbstractScopeSniff implements Sniff +{ + + /** + * The token types that this test wishes to listen to within the scope. + * + * @var array + */ + private $tokens = []; + + /** + * The type of scope opener tokens that this test wishes to listen to. + * + * @var string + */ + private $scopeTokens = []; + + /** + * True if this test should fire on tokens outside of the scope. + * + * @var boolean + */ + private $listenOutside = false; + + + /** + * Constructs a new AbstractScopeTest. + * + * @param array $scopeTokens The type of scope the test wishes to listen to. + * @param array $tokens The tokens that the test wishes to listen to + * within the scope. + * @param boolean $listenOutside If true this test will also alert the + * extending class when a token is found outside + * the scope, by calling the + * processTokenOutsideScope method. + * + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified tokens arrays are empty + * or invalid. + */ + public function __construct( + array $scopeTokens, + array $tokens, + $listenOutside=false + ) { + if (empty($scopeTokens) === true) { + $error = 'The scope tokens list cannot be empty'; + throw new RuntimeException($error); + } + + if (empty($tokens) === true) { + $error = 'The tokens list cannot be empty'; + throw new RuntimeException($error); + } + + $invalidScopeTokens = array_intersect($scopeTokens, $tokens); + if (empty($invalidScopeTokens) === false) { + $invalid = implode(', ', $invalidScopeTokens); + $error = "Scope tokens [$invalid] can't be in the tokens array"; + throw new RuntimeException($error); + } + + $this->listenOutside = $listenOutside; + $this->scopeTokens = array_flip($scopeTokens); + $this->tokens = $tokens; + + }//end __construct() + + + /** + * The method that is called to register the tokens this test wishes to + * listen to. + * + * DO NOT OVERRIDE THIS METHOD. Use the constructor of this class to register + * for the desired tokens and scope. + * + * @return int[] + * @see __constructor() + */ + final public function register() + { + return $this->tokens; + + }//end register() + + + /** + * Processes the tokens that this test is listening for. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return ($phpcsFile->numTokens + 1) to skip + * the rest of the file. + * @see processTokenWithinScope() + */ + final public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $foundScope = false; + $skipTokens = []; + foreach ($tokens[$stackPtr]['conditions'] as $scope => $code) { + if (isset($this->scopeTokens[$code]) === true) { + $skipTokens[] = $this->processTokenWithinScope($phpcsFile, $stackPtr, $scope); + $foundScope = true; + } + } + + if ($this->listenOutside === true && $foundScope === false) { + $skipTokens[] = $this->processTokenOutsideScope($phpcsFile, $stackPtr); + } + + if (empty($skipTokens) === false) { + return min($skipTokens); + } + + return; + + }//end process() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * @param int $currScope The position in the tokens array that + * opened the scope that this test is + * listening for. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return ($phpcsFile->numTokens + 1) to skip + * the rest of the file. + */ + abstract protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope); + + + /** + * Processes a token that is found outside the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return (count($tokens) + 1) to skip + * the rest of the file. + */ + abstract protected function processTokenOutsideScope(File $phpcsFile, $stackPtr); + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractVariableSniff.php b/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractVariableSniff.php new file mode 100644 index 00000000..5dc8ba55 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractVariableSniff.php @@ -0,0 +1,230 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +abstract class AbstractVariableSniff extends AbstractScopeSniff +{ + + /** + * List of PHP Reserved variables. + * + * Used by various naming convention sniffs. + * + * @var array + */ + protected $phpReservedVars = [ + '_SERVER' => true, + '_GET' => true, + '_POST' => true, + '_REQUEST' => true, + '_SESSION' => true, + '_ENV' => true, + '_COOKIE' => true, + '_FILES' => true, + 'GLOBALS' => true, + 'http_response_header' => true, + 'HTTP_RAW_POST_DATA' => true, + 'php_errormsg' => true, + ]; + + + /** + * Constructs an AbstractVariableTest. + */ + public function __construct() + { + $scopes = Tokens::$ooScopeTokens; + + $listen = [ + T_VARIABLE, + T_DOUBLE_QUOTED_STRING, + T_HEREDOC, + ]; + + parent::__construct($scopes, $listen, true); + + }//end __construct() + + + /** + * Processes the token in the specified PHP_CodeSniffer\Files\File. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the token was found. + * @param int $currScope The current scope opener token. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return ($phpcsFile->numTokens + 1) to skip + * the rest of the file. + */ + final protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING + || $tokens[$stackPtr]['code'] === T_HEREDOC + ) { + // Check to see if this string has a variable in it. + $pattern = '|(?processVariableInString($phpcsFile, $stackPtr); + } + + return; + } + + // If this token is nested inside a function at a deeper + // level than the current OO scope that was found, it's a normal + // variable and not a member var. + $conditions = array_reverse($tokens[$stackPtr]['conditions'], true); + $inFunction = false; + foreach ($conditions as $scope => $code) { + if (isset(Tokens::$ooScopeTokens[$code]) === true) { + break; + } + + if ($code === T_FUNCTION || $code === T_CLOSURE) { + $inFunction = true; + } + } + + if ($scope !== $currScope) { + // We found a closer scope to this token, so ignore + // this particular time through the sniff. We will process + // this token when this closer scope is found to avoid + // duplicate checks. + return; + } + + // Just make sure this isn't a variable in a function declaration. + if ($inFunction === false && isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + foreach ($tokens[$stackPtr]['nested_parenthesis'] as $opener => $closer) { + if (isset($tokens[$opener]['parenthesis_owner']) === false) { + // Check if this is a USE statement for a closure. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($opener - 1), null, true); + if ($tokens[$prev]['code'] === T_USE) { + $inFunction = true; + break; + } + + continue; + } + + $owner = $tokens[$opener]['parenthesis_owner']; + if ($tokens[$owner]['code'] === T_FUNCTION + || $tokens[$owner]['code'] === T_CLOSURE + ) { + $inFunction = true; + break; + } + } + }//end if + + if ($inFunction === true) { + return $this->processVariable($phpcsFile, $stackPtr); + } else { + return $this->processMemberVar($phpcsFile, $stackPtr); + } + + }//end processTokenWithinScope() + + + /** + * Processes the token outside the scope in the file. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return ($phpcsFile->numTokens + 1) to skip + * the rest of the file. + */ + final protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + // These variables are not member vars. + if ($tokens[$stackPtr]['code'] === T_VARIABLE) { + return $this->processVariable($phpcsFile, $stackPtr); + } else if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING + || $tokens[$stackPtr]['code'] === T_HEREDOC + ) { + // Check to see if this string has a variable in it. + $pattern = '|(?processVariableInString($phpcsFile, $stackPtr); + } + } + + }//end processTokenOutsideScope() + + + /** + * Called to process class member vars. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return ($phpcsFile->numTokens + 1) to skip + * the rest of the file. + */ + abstract protected function processMemberVar(File $phpcsFile, $stackPtr); + + + /** + * Called to process normal member vars. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return ($phpcsFile->numTokens + 1) to skip + * the rest of the file. + */ + abstract protected function processVariable(File $phpcsFile, $stackPtr); + + + /** + * Called to process variables found in double quoted strings or heredocs. + * + * Note that there may be more than one variable in the string, which will + * result only in one call for the string or one call per line for heredocs. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the double quoted + * string was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return ($phpcsFile->numTokens + 1) to skip + * the rest of the file. + */ + abstract protected function processVariableInString(File $phpcsFile, $stackPtr); + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Sniffs/Sniff.php b/vendor/squizlabs/php_codesniffer/src/Sniffs/Sniff.php new file mode 100644 index 00000000..3f0fb6a1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Sniffs/Sniff.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Files\File; + +interface Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * An example return value for a sniff that wants to listen for whitespace + * and any comments would be: + * + * + * return array( + * T_WHITESPACE, + * T_DOC_COMMENT, + * T_COMMENT, + * ); + * + * + * @return mixed[] + * @see Tokens.php + */ + public function register(); + + + /** + * Called when one of the token types that this sniff is listening for + * is found. + * + * The stackPtr variable indicates where in the stack the token was found. + * A sniff can acquire information about this token, along with all the other + * tokens within the stack by first acquiring the token stack: + * + * + * $tokens = $phpcsFile->getTokens(); + * echo 'Encountered a '.$tokens[$stackPtr]['type'].' token'; + * echo 'token information: '; + * print_r($tokens[$stackPtr]); + * + * + * If the sniff discovers an anomaly in the code, they can raise an error + * by calling addError() on the \PHP_CodeSniffer\Files\File object, specifying an error + * message and the position of the offending token: + * + * + * $phpcsFile->addError('Encountered an error', $stackPtr); + * + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token was found. + * @param int $stackPtr The position in the PHP_CodeSniffer + * file's token stack where the token + * was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return (count($tokens) + 1) to skip + * the rest of the file. + */ + public function process(File $phpcsFile, $stackPtr); + + +}//end interface diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowLongArraySyntaxStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowLongArraySyntaxStandard.xml new file mode 100644 index 00000000..21b0d27d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowLongArraySyntaxStandard.xml @@ -0,0 +1,23 @@ + + + + + + + [ + 'foo' => 'bar', +]; + ]]> + + + array( + 'foo' => 'bar', +); + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowShortArraySyntaxStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowShortArraySyntaxStandard.xml new file mode 100644 index 00000000..f24767ca --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowShortArraySyntaxStandard.xml @@ -0,0 +1,23 @@ + + + + + + + array( + 'foo' => 'bar', +); + ]]> + + + [ + 'foo' => 'bar', +]; + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml new file mode 100644 index 00000000..4b0ec96d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml @@ -0,0 +1,27 @@ + + + + + + + Foo +{ +} + ]]> + + + Foo +{ +} + +class Foo +{ +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/OpeningBraceSameLineStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/OpeningBraceSameLineStandard.xml new file mode 100644 index 00000000..6226a3ff --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/OpeningBraceSameLineStandard.xml @@ -0,0 +1,28 @@ + + + + + + + { +} + ]]> + + + { +} + ]]> + + + // Start of class. +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/AssignmentInConditionStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/AssignmentInConditionStandard.xml new file mode 100644 index 00000000..9961ea05 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/AssignmentInConditionStandard.xml @@ -0,0 +1,23 @@ + + + + + + + $test === 'abc') { + // Code. +} + ]]> + + + $test = 'abc') { + // Code. +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyStatementStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyStatementStandard.xml new file mode 100644 index 00000000..c400d75e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyStatementStandard.xml @@ -0,0 +1,23 @@ + + + + + + + + + + // do nothing +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopShouldBeWhileLoopStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopShouldBeWhileLoopStandard.xml new file mode 100644 index 00000000..06f0b7a5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopShouldBeWhileLoopStandard.xml @@ -0,0 +1,23 @@ + + + + + + + $i = 0; $i < 10; $i++) { + echo "{$i}\n"; +} + ]]> + + + ;$test;) { + $test = doSomething(); +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopWithTestFunctionCallStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopWithTestFunctionCallStandard.xml new file mode 100644 index 00000000..f40d94bb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopWithTestFunctionCallStandard.xml @@ -0,0 +1,24 @@ + + + + + + + $end = count($foo); +for ($i = 0; $i < $end; $i++) { + echo $foo[$i]."\n"; +} + ]]> + + + count($foo); $i++) { + echo $foo[$i]."\n"; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/JumbledIncrementerStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/JumbledIncrementerStandard.xml new file mode 100644 index 00000000..50f07828 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/JumbledIncrementerStandard.xml @@ -0,0 +1,25 @@ + + + + + + + $i++) { + for ($j = 0; $j < 10; $j++) { + } +} + ]]> + + + $i++) { + for ($j = 0; $j < 10; $i++) { + } +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnconditionalIfStatementStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnconditionalIfStatementStandard.xml new file mode 100644 index 00000000..b2eaabe7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnconditionalIfStatementStandard.xml @@ -0,0 +1,39 @@ + + + + + + + $test) { + $var = 1; +} + ]]> + + + true) { + $var = 1; +} + ]]> + + + + + $test) { + $var = 1; +} + ]]> + + + false) { + $var = 1; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnnecessaryFinalModifierStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnnecessaryFinalModifierStandard.xml new file mode 100644 index 00000000..89367407 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnnecessaryFinalModifierStandard.xml @@ -0,0 +1,29 @@ + + + + + + + + + + final function bar() + { + } +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnusedFunctionParameterStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnusedFunctionParameterStandard.xml new file mode 100644 index 00000000..181dff4e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnusedFunctionParameterStandard.xml @@ -0,0 +1,25 @@ + + + + + + + $a + $b + $c; +} + ]]> + + + $a + $b; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UselessOverridingMethodStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UselessOverridingMethodStandard.xml new file mode 100644 index 00000000..ba8bd7e4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UselessOverridingMethodStandard.xml @@ -0,0 +1,32 @@ + + + + + + + $this->doSomethingElse(); + } +} + ]]> + + + parent::bar(); + } +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/FixmeStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/FixmeStandard.xml new file mode 100644 index 00000000..174c6b0a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/FixmeStandard.xml @@ -0,0 +1,25 @@ + + + + + + + Handle strange case +if ($test) { + $var = 1; +} + ]]> + + + FIXME: This needs to be fixed! +if ($test) { + $var = 1; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/TodoStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/TodoStandard.xml new file mode 100644 index 00000000..c9c4fc06 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/TodoStandard.xml @@ -0,0 +1,25 @@ + + + + + + + Handle strange case +if ($test) { + $var = 1; +} + ]]> + + + TODO: This needs to be fixed! +if ($test) { + $var = 1; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/DisallowYodaConditionsStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/DisallowYodaConditionsStandard.xml new file mode 100644 index 00000000..570e4192 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/DisallowYodaConditionsStandard.xml @@ -0,0 +1,23 @@ + + + + + + + { + $var = 1; +} + ]]> + + + { + $var = 1; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/InlineControlStructureStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/InlineControlStructureStandard.xml new file mode 100644 index 00000000..06ae14b7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/InlineControlStructureStandard.xml @@ -0,0 +1,22 @@ + + + + + + + { + $var = 1; +} + ]]> + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/CSSLintStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/CSSLintStandard.xml new file mode 100644 index 00000000..b57a9706 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/CSSLintStandard.xml @@ -0,0 +1,19 @@ + + + + + + + %; } + ]]> + + + %; } + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/ClosureLinterStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/ClosureLinterStandard.xml new file mode 100644 index 00000000..9df9aec4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/ClosureLinterStandard.xml @@ -0,0 +1,19 @@ + + + + + + + ]; + ]]> + + + ,]; + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/JSHintStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/JSHintStandard.xml new file mode 100644 index 00000000..7525e9e6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/JSHintStandard.xml @@ -0,0 +1,19 @@ + + + + + + + var foo = 5; + ]]> + + + foo = 5; + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ByteOrderMarkStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ByteOrderMarkStandard.xml new file mode 100644 index 00000000..88591f92 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ByteOrderMarkStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNewlineStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNewlineStandard.xml new file mode 100644 index 00000000..aa757edc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNewlineStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNoNewlineStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNoNewlineStandard.xml new file mode 100644 index 00000000..227d5621 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNoNewlineStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ExecutableFileStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ExecutableFileStandard.xml new file mode 100644 index 00000000..6114f24c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ExecutableFileStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/InlineHTMLStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/InlineHTMLStandard.xml new file mode 100644 index 00000000..3fbf5024 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/InlineHTMLStandard.xml @@ -0,0 +1,24 @@ + + + + + + + + + + some string here + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineEndingsStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineEndingsStandard.xml new file mode 100644 index 00000000..4554d0f3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineEndingsStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineLengthStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineLengthStandard.xml new file mode 100644 index 00000000..31342e3c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineLengthStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LowercasedFilenameStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LowercasedFilenameStandard.xml new file mode 100644 index 00000000..a1be34cb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LowercasedFilenameStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneClassPerFileStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneClassPerFileStandard.xml new file mode 100644 index 00000000..7b585763 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneClassPerFileStandard.xml @@ -0,0 +1,29 @@ + + + + + + + class Foo +{ +} + ]]> + + + class Foo +{ +} + +class Bar +{ +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneInterfacePerFileStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneInterfacePerFileStandard.xml new file mode 100644 index 00000000..de975319 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneInterfacePerFileStandard.xml @@ -0,0 +1,29 @@ + + + + + + + interface Foo +{ +} + ]]> + + + interface Foo +{ +} + +interface Bar +{ +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneObjectStructurePerFileStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneObjectStructurePerFileStandard.xml new file mode 100644 index 00000000..4d957e70 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneObjectStructurePerFileStandard.xml @@ -0,0 +1,29 @@ + + + + + + + trait Foo +{ +} + ]]> + + + trait Foo +{ +} + +class Bar +{ +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneTraitPerFileStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneTraitPerFileStandard.xml new file mode 100644 index 00000000..58a6482f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneTraitPerFileStandard.xml @@ -0,0 +1,29 @@ + + + + + + + trait Foo +{ +} + ]]> + + + trait Foo +{ +} + +trait Bar +{ +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/DisallowMultipleStatementsStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/DisallowMultipleStatementsStandard.xml new file mode 100644 index 00000000..f0d4490c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/DisallowMultipleStatementsStandard.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/MultipleStatementAlignmentStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/MultipleStatementAlignmentStandard.xml new file mode 100644 index 00000000..4c33d763 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/MultipleStatementAlignmentStandard.xml @@ -0,0 +1,56 @@ + + + + + + + = (1 + 2); +$veryLongVarName = 'string'; +$var = foo($bar, $baz); + ]]> + + + = (1 + 2); +$veryLongVarName = 'string'; +$var = foo($bar, $baz); + ]]> + + + + + + + + += 1; +$veryLongVarName = 1; + ]]> + + + += 1; +$veryLongVarName = 1; + ]]> + + + + + = 1; +$veryLongVarName -= 1; + ]]> + + + = 1; +$veryLongVarName -= 1; + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/NoSpaceAfterCastStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/NoSpaceAfterCastStandard.xml new file mode 100644 index 00000000..042e4f80 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/NoSpaceAfterCastStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + 1; + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterCastStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterCastStandard.xml new file mode 100644 index 00000000..75eba77c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterCastStandard.xml @@ -0,0 +1,19 @@ + + + + + + + 1; + ]]> + + + 1; + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterNotStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterNotStandard.xml new file mode 100644 index 00000000..dd3e7731 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterNotStandard.xml @@ -0,0 +1,25 @@ + + + + + + + $someVar || ! $x instanceOf stdClass) {}; + ]]> + + + $someVar || !$x instanceOf stdClass) {}; + ]]> + + + $someVar || ! + $x instanceOf stdClass) {}; + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/CallTimePassByReferenceStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/CallTimePassByReferenceStandard.xml new file mode 100644 index 00000000..738998d4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/CallTimePassByReferenceStandard.xml @@ -0,0 +1,31 @@ + + + + + + + &$bar) +{ + $bar++; +} + +$baz = 1; +foo($baz); + ]]> + + + &$baz); + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/FunctionCallArgumentSpacingStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/FunctionCallArgumentSpacingStandard.xml new file mode 100644 index 00000000..9809844d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/FunctionCallArgumentSpacingStandard.xml @@ -0,0 +1,39 @@ + + + + + + + $baz) +{ +} + ]]> + + + $baz) +{ +} + ]]> + + + + + = true) +{ +} + ]]> + + + =true) +{ +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceBsdAllmanStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceBsdAllmanStandard.xml new file mode 100644 index 00000000..414dc289 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceBsdAllmanStandard.xml @@ -0,0 +1,24 @@ + + + + + + + { + ... +} + ]]> + + + { + ... +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceKernighanRitchieStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceKernighanRitchieStandard.xml new file mode 100644 index 00000000..84c2bdd8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceKernighanRitchieStandard.xml @@ -0,0 +1,24 @@ + + + + + + + { + ... +} + ]]> + + + { + ... +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/CyclomaticComplexityStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/CyclomaticComplexityStandard.xml new file mode 100644 index 00000000..a928e7db --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/CyclomaticComplexityStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/NestingLevelStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/NestingLevelStandard.xml new file mode 100644 index 00000000..f66cd92c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/NestingLevelStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/AbstractClassNamePrefixStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/AbstractClassNamePrefixStandard.xml new file mode 100644 index 00000000..c30d26e9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/AbstractClassNamePrefixStandard.xml @@ -0,0 +1,23 @@ + + + + + + + AbstractBar +{ +} + ]]> + + + Bar +{ +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/CamelCapsFunctionNameStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/CamelCapsFunctionNameStandard.xml new file mode 100644 index 00000000..f5345b71 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/CamelCapsFunctionNameStandard.xml @@ -0,0 +1,23 @@ + + + + + + + doSomething() +{ +} + ]]> + + + do_something() +{ +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/ConstructorNameStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/ConstructorNameStandard.xml new file mode 100644 index 00000000..9dfc175f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/ConstructorNameStandard.xml @@ -0,0 +1,29 @@ + + + + + + + __construct() + { + } +} + ]]> + + + Foo() + { + } +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/InterfaceNameSuffixStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/InterfaceNameSuffixStandard.xml new file mode 100644 index 00000000..0aa0c76e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/InterfaceNameSuffixStandard.xml @@ -0,0 +1,23 @@ + + + + + + + BarInterface +{ +} + ]]> + + + Bar +{ +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/TraitNameSuffixStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/TraitNameSuffixStandard.xml new file mode 100644 index 00000000..711867e4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/TraitNameSuffixStandard.xml @@ -0,0 +1,23 @@ + + + + + + + BarTrait +{ +} + ]]> + + + Bar +{ +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/UpperCaseConstantNameStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/UpperCaseConstantNameStandard.xml new file mode 100644 index 00000000..6ef61b93 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/UpperCaseConstantNameStandard.xml @@ -0,0 +1,29 @@ + + + + + + + FOO_CONSTANT', 'foo'); + +class FooClass +{ + const FOO_CONSTANT = 'foo'; +} + ]]> + + + Foo_Constant', 'foo'); + +class FooClass +{ + const foo_constant = 'foo'; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/BacktickOperatorStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/BacktickOperatorStandard.xml new file mode 100644 index 00000000..4ebd6770 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/BacktickOperatorStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/CharacterBeforePHPOpeningTagStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/CharacterBeforePHPOpeningTagStandard.xml new file mode 100644 index 00000000..df5a0eba --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/CharacterBeforePHPOpeningTagStandard.xml @@ -0,0 +1,22 @@ + + + + + + + + + + Beginning content + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ClosingPHPTagStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ClosingPHPTagStandard.xml new file mode 100644 index 00000000..09afb2d7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ClosingPHPTagStandard.xml @@ -0,0 +1,22 @@ + + + + + + + +echo 'Foo'; +?> + ]]> + + + +echo 'Foo'; + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DeprecatedFunctionsStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DeprecatedFunctionsStandard.xml new file mode 100644 index 00000000..33b803a7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DeprecatedFunctionsStandard.xml @@ -0,0 +1,19 @@ + + + + + + + explode('a', $bar); + ]]> + + + split('a', $bar); + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowAlternativePHPTagsStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowAlternativePHPTagsStandard.xml new file mode 100644 index 00000000..bdfd5dc1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowAlternativePHPTagsStandard.xml @@ -0,0 +1,7 @@ + + + to delimit PHP code, do not use the ASP <% %> style tags nor the tags. This is the most portable way to include PHP code on differing operating systems and setups. + ]]> + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowRequestSuperglobalStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowRequestSuperglobalStandard.xml new file mode 100644 index 00000000..f9476942 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowRequestSuperglobalStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowShortOpenTagStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowShortOpenTagStandard.xml new file mode 100644 index 00000000..8086ea27 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowShortOpenTagStandard.xml @@ -0,0 +1,7 @@ + + + to delimit PHP code, not the shorthand. This is the most portable way to include PHP code on differing operating systems and setups. + ]]> + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DiscourageGotoStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DiscourageGotoStandard.xml new file mode 100644 index 00000000..83bceef4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DiscourageGotoStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ForbiddenFunctionsStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ForbiddenFunctionsStandard.xml new file mode 100644 index 00000000..c0f18b55 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ForbiddenFunctionsStandard.xml @@ -0,0 +1,19 @@ + + + + + + + count($bar); + ]]> + + + sizeof($bar); + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseConstantStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseConstantStandard.xml new file mode 100644 index 00000000..7dc30c10 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseConstantStandard.xml @@ -0,0 +1,23 @@ + + + true, false and null constants must always be lowercase. + ]]> + + + + false || $var === null) { + $var = true; +} + ]]> + + + FALSE || $var === NULL) { + $var = TRUE; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseKeywordStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseKeywordStandard.xml new file mode 100644 index 00000000..965742d9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseKeywordStandard.xml @@ -0,0 +1,19 @@ + + + + + + + array(); + ]]> + + + Array(); + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseTypeStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseTypeStandard.xml new file mode 100644 index 00000000..f38df3af --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseTypeStandard.xml @@ -0,0 +1,38 @@ + + + + + + + + + + Int $foo) : STRING { +} + ]]> + + + + + + + + + + + (BOOL) $isValid; + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/NoSilencedErrorsStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/NoSilencedErrorsStandard.xml new file mode 100644 index 00000000..df698879 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/NoSilencedErrorsStandard.xml @@ -0,0 +1,23 @@ + + + + + + + isset($foo) && $foo) { + echo "Hello\n"; +} + ]]> + + + @$foo) { + echo "Hello\n"; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SAPIUsageStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SAPIUsageStandard.xml new file mode 100644 index 00000000..e74005ad --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SAPIUsageStandard.xml @@ -0,0 +1,23 @@ + + + + + + + PHP_SAPI === 'cli') { + echo "Hello, CLI user."; +} + ]]> + + + php_sapi_name() === 'cli') { + echo "Hello, CLI user."; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/UpperCaseConstantStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/UpperCaseConstantStandard.xml new file mode 100644 index 00000000..1f337f77 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/UpperCaseConstantStandard.xml @@ -0,0 +1,23 @@ + + + true, false and null constants must always be uppercase. + ]]> + + + + FALSE || $var === NULL) { + $var = TRUE; +} + ]]> + + + false || $var === null) { + $var = true; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryStringConcatStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryStringConcatStandard.xml new file mode 100644 index 00000000..a4c9887b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryStringConcatStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/VersionControl/SubversionPropertiesStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/VersionControl/SubversionPropertiesStandard.xml new file mode 100644 index 00000000..f4f3e19c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/VersionControl/SubversionPropertiesStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ArbitraryParenthesesSpacingStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ArbitraryParenthesesSpacingStandard.xml new file mode 100644 index 00000000..30e0def9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ArbitraryParenthesesSpacingStandard.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowSpaceIndentStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowSpaceIndentStandard.xml new file mode 100644 index 00000000..2e399b34 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowSpaceIndentStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowTabIndentStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowTabIndentStandard.xml new file mode 100644 index 00000000..7013ffd9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowTabIndentStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ScopeIndentStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ScopeIndentStandard.xml new file mode 100644 index 00000000..bdd36d49 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ScopeIndentStandard.xml @@ -0,0 +1,23 @@ + + + + + + + $var = 1; +} + ]]> + + + $var = 1; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/SpreadOperatorSpacingAfterStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/SpreadOperatorSpacingAfterStandard.xml new file mode 100644 index 00000000..d33b6051 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/SpreadOperatorSpacingAfterStandard.xml @@ -0,0 +1,34 @@ + + + + + + + &...$spread) { + bar(...$spread); + + bar( + [...$foo], + ...array_values($keyedArray) + ); +} + ]]> + + + ... $spread) { + bar(... + $spread + ); + + bar( + [... $foo ],.../*comment*/array_values($keyedArray) + ); +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/ArrayIndentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/ArrayIndentSniff.php new file mode 100644 index 00000000..adb74ec8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/ArrayIndentSniff.php @@ -0,0 +1,177 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays; + +use PHP_CodeSniffer\Sniffs\AbstractArraySniff; +use PHP_CodeSniffer\Util\Tokens; + +class ArrayIndentSniff extends AbstractArraySniff +{ + + /** + * The number of spaces each array key should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Processes a single-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + public function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) + { + + }//end processSingleLineArray() + + + /** + * Processes a multi-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + public function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) + { + $tokens = $phpcsFile->getTokens(); + + // Determine how far indented the entire array declaration should be. + $ignore = Tokens::$emptyTokens; + $ignore[] = T_DOUBLE_ARROW; + $ignore[] = T_COMMA; + $prev = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); + $start = $phpcsFile->findStartOfStatement($prev); + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $start, true); + $baseIndent = ($tokens[$first]['column'] - 1); + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $startIndent = ($tokens[$first]['column'] - 1); + + // If the open brace is not indented to at least to the level of the start + // of the statement, the sniff will conflict with other sniffs trying to + // check indent levels because it's not valid. But we don't enforce exactly + // how far indented it should be. + if ($startIndent < $baseIndent) { + $error = 'Array open brace not indented correctly; expected at least %s spaces but found %s'; + $data = [ + $baseIndent, + $startIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'OpenBraceIncorrect', $data); + if ($fix === true) { + $padding = str_repeat(' ', $baseIndent); + if ($startIndent === 0) { + $phpcsFile->fixer->addContentBefore($first, $padding); + } else { + $phpcsFile->fixer->replaceToken(($first - 1), $padding); + } + } + + return; + }//end if + + $expectedIndent = ($startIndent + $this->indent); + + foreach ($indices as $index) { + if (isset($index['index_start']) === true) { + $start = $index['index_start']; + } else { + $start = $index['value_start']; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($start - 1), null, true); + if ($tokens[$prev]['line'] === $tokens[$start]['line']) { + // This index isn't the only content on the line + // so we can't check indent rules. + continue; + } + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $start, true); + + $foundIndent = ($tokens[$first]['column'] - 1); + if ($foundIndent === $expectedIndent) { + continue; + } + + $error = 'Array key not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $first, 'KeyIncorrect', $data); + if ($fix === false) { + continue; + } + + $padding = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($first, $padding); + } else { + $phpcsFile->fixer->replaceToken(($first - 1), $padding); + } + }//end foreach + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($arrayEnd - 1), null, true); + if ($tokens[$prev]['line'] === $tokens[$arrayEnd]['line']) { + $error = 'Closing brace of array declaration must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceNotNewLine'); + if ($fix === true) { + $padding = $phpcsFile->eolChar.str_repeat(' ', $expectedIndent); + $phpcsFile->fixer->addContentBefore($arrayEnd, $padding); + } + + return; + } + + // The close brace must be indented one stop less. + $expectedIndent -= $this->indent; + $foundIndent = ($tokens[$arrayEnd]['column'] - 1); + if ($foundIndent === $expectedIndent) { + return; + } + + $error = 'Array close brace not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceIncorrect', $data); + if ($fix === false) { + return; + } + + $padding = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($arrayEnd, $padding); + } else { + $phpcsFile->fixer->replaceToken(($arrayEnd - 1), $padding); + } + + }//end processMultiLineArray() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowLongArraySyntaxSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowLongArraySyntaxSniff.php new file mode 100644 index 00000000..bf7f3ed1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowLongArraySyntaxSniff.php @@ -0,0 +1,78 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowLongArraySyntaxSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_ARRAY]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'no'); + + $error = 'Short array syntax must be used to define arrays'; + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + ) { + // Live coding/parse error, just show the error, don't try and fix it. + $phpcsFile->addError($error, $stackPtr, 'Found'); + return; + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found'); + + if ($fix === true) { + $opener = $tokens[$stackPtr]['parenthesis_opener']; + $closer = $tokens[$stackPtr]['parenthesis_closer']; + + $phpcsFile->fixer->beginChangeset(); + + if ($opener === null) { + $phpcsFile->fixer->replaceToken($stackPtr, '[]'); + } else { + $phpcsFile->fixer->replaceToken($stackPtr, ''); + $phpcsFile->fixer->replaceToken($opener, '['); + $phpcsFile->fixer->replaceToken($closer, ']'); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowShortArraySyntaxSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowShortArraySyntaxSniff.php new file mode 100644 index 00000000..2ba42d67 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowShortArraySyntaxSniff.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowShortArraySyntaxSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_SHORT_ARRAY]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'yes'); + + $error = 'Short array syntax is not allowed'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found'); + + if ($fix === true) { + $tokens = $phpcsFile->getTokens(); + $opener = $tokens[$stackPtr]['bracket_opener']; + $closer = $tokens[$stackPtr]['bracket_closer']; + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($opener, 'array('); + $phpcsFile->fixer->replaceToken($closer, ')'); + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php new file mode 100644 index 00000000..3243f8b7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php @@ -0,0 +1,118 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DuplicateClassNameSniff implements Sniff +{ + + /** + * List of classes that have been found during checking. + * + * @var array + */ + protected $foundClasses = []; + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $namespace = ''; + $findTokens = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_NAMESPACE, + T_CLOSE_TAG, + ]; + + $stackPtr = $phpcsFile->findNext($findTokens, ($stackPtr + 1)); + while ($stackPtr !== false) { + if ($tokens[$stackPtr]['code'] === T_CLOSE_TAG) { + // We can stop here. The sniff will continue from the next open + // tag when PHPCS reaches that token, if there is one. + return; + } + + // Keep track of what namespace we are in. + if ($tokens[$stackPtr]['code'] === T_NAMESPACE) { + $nsEnd = $phpcsFile->findNext( + [ + T_NS_SEPARATOR, + T_STRING, + T_WHITESPACE, + ], + ($stackPtr + 1), + null, + true + ); + + $namespace = trim($phpcsFile->getTokensAsString(($stackPtr + 1), ($nsEnd - $stackPtr - 1))); + $stackPtr = $nsEnd; + } else { + $nameToken = $phpcsFile->findNext(T_STRING, $stackPtr); + $name = $tokens[$nameToken]['content']; + if ($namespace !== '') { + $name = $namespace.'\\'.$name; + } + + $compareName = strtolower($name); + if (isset($this->foundClasses[$compareName]) === true) { + $type = strtolower($tokens[$stackPtr]['content']); + $file = $this->foundClasses[$compareName]['file']; + $line = $this->foundClasses[$compareName]['line']; + $error = 'Duplicate %s name "%s" found; first defined in %s on line %s'; + $data = [ + $type, + $name, + $file, + $line, + ]; + $phpcsFile->addWarning($error, $stackPtr, 'Found', $data); + } else { + $this->foundClasses[$compareName] = [ + 'file' => $phpcsFile->getFilename(), + 'line' => $tokens[$stackPtr]['line'], + ]; + } + }//end if + + $stackPtr = $phpcsFile->findNext($findTokens, ($stackPtr + 1)); + }//end while + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/OpeningBraceSameLineSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/OpeningBraceSameLineSniff.php new file mode 100644 index 00000000..dfd925f9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/OpeningBraceSameLineSniff.php @@ -0,0 +1,124 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OpeningBraceSameLineSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $scopeIdentifier = $phpcsFile->findNext(T_STRING, ($stackPtr + 1)); + $errorData = [strtolower($tokens[$stackPtr]['content']).' '.$tokens[$scopeIdentifier]['content']]; + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + $error = 'Possible parse error: %s missing opening or closing brace'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $errorData); + return; + } + + $openingBrace = $tokens[$stackPtr]['scope_opener']; + + // Is the brace on the same line as the class/interface/trait declaration ? + $lastClassLineToken = $phpcsFile->findPrevious(T_WHITESPACE, ($openingBrace - 1), $stackPtr, true); + $lastClassLine = $tokens[$lastClassLineToken]['line']; + $braceLine = $tokens[$openingBrace]['line']; + $lineDifference = ($braceLine - $lastClassLine); + + if ($lineDifference > 0) { + $phpcsFile->recordMetric($stackPtr, 'Class opening brace placement', 'new line'); + $error = 'Opening brace should be on the same line as the declaration for %s'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceOnNewLine', $errorData); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($lastClassLineToken, ' {'); + $phpcsFile->fixer->replaceToken($openingBrace, ''); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Class opening brace placement', 'same line'); + } + + // Is the opening brace the last thing on the line ? + $next = $phpcsFile->findNext(T_WHITESPACE, ($openingBrace + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openingBrace]['line']) { + if ($next === $tokens[$stackPtr]['scope_closer']) { + // Ignore empty classes. + return; + } + + $error = 'Opening brace must be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'ContentAfterBrace'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($openingBrace); + } + } + + // Only continue checking if the opening brace looks good. + if ($lineDifference > 0) { + return; + } + + // Is there precisely one space before the opening brace ? + if ($tokens[($openingBrace - 1)]['code'] !== T_WHITESPACE) { + $length = 0; + } else if ($tokens[($openingBrace - 1)]['content'] === "\t") { + $length = '\t'; + } else { + $length = $tokens[($openingBrace - 1)]['length']; + } + + if ($length !== 1) { + $error = 'Expected 1 space before opening brace; found %s'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'SpaceBeforeBrace', $data); + if ($fix === true) { + if ($length === 0 || $length === '\t') { + $phpcsFile->fixer->addContentBefore($openingBrace, ' '); + } else { + $phpcsFile->fixer->replaceToken(($openingBrace - 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php new file mode 100644 index 00000000..8788a912 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php @@ -0,0 +1,171 @@ + + * @copyright 2017 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class AssignmentInConditionSniff implements Sniff +{ + + /** + * Assignment tokens to trigger on. + * + * Set in the register() method. + * + * @var array + */ + protected $assignmentTokens = []; + + /** + * The tokens that indicate the start of a condition. + * + * @var array + */ + protected $conditionStartTokens = []; + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + $this->assignmentTokens = Tokens::$assignmentTokens; + unset($this->assignmentTokens[T_DOUBLE_ARROW]); + + $starters = Tokens::$booleanOperators; + $starters[T_SEMICOLON] = T_SEMICOLON; + $starters[T_OPEN_PARENTHESIS] = T_OPEN_PARENTHESIS; + + $this->conditionStartTokens = $starters; + + return [ + T_IF, + T_ELSEIF, + T_FOR, + T_SWITCH, + T_CASE, + T_WHILE, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Find the condition opener/closer. + if ($token['code'] === T_FOR) { + if (isset($token['parenthesis_opener'], $token['parenthesis_closer']) === false) { + return; + } + + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($token['parenthesis_opener'] + 1), ($token['parenthesis_closer'])); + if ($semicolon === false) { + return; + } + + $opener = $semicolon; + + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($opener + 1), ($token['parenthesis_closer'])); + if ($semicolon === false) { + return; + } + + $closer = $semicolon; + unset($semicolon); + } else if ($token['code'] === T_CASE) { + if (isset($token['scope_opener']) === false) { + return; + } + + $opener = $stackPtr; + $closer = $token['scope_opener']; + } else { + if (isset($token['parenthesis_opener'], $token['parenthesis_closer']) === false) { + return; + } + + $opener = $token['parenthesis_opener']; + $closer = $token['parenthesis_closer']; + }//end if + + $startPos = $opener; + + do { + $hasAssignment = $phpcsFile->findNext($this->assignmentTokens, ($startPos + 1), $closer); + if ($hasAssignment === false) { + return; + } + + // Examine whether the left side is a variable. + $hasVariable = false; + $conditionStart = $startPos; + $altConditionStart = $phpcsFile->findPrevious($this->conditionStartTokens, ($hasAssignment - 1), $startPos); + if ($altConditionStart !== false) { + $conditionStart = $altConditionStart; + } + + for ($i = $hasAssignment; $i > $conditionStart; $i--) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + // If this is a variable or array, we've seen all we need to see. + if ($tokens[$i]['code'] === T_VARIABLE || $tokens[$i]['code'] === T_CLOSE_SQUARE_BRACKET) { + $hasVariable = true; + break; + } + + // If this is a function call or something, we are OK. + if ($tokens[$i]['code'] === T_CLOSE_PARENTHESIS) { + break; + } + } + + if ($hasVariable === true) { + $errorCode = 'Found'; + if ($token['code'] === T_WHILE) { + $errorCode = 'FoundInWhileCondition'; + } + + $phpcsFile->addWarning( + 'Variable assignment found within a condition. Did you mean to do a comparison ?', + $hasAssignment, + $errorCode + ); + } + + $startPos = $hasAssignment; + } while ($startPos < $closer); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyPHPStatementSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyPHPStatementSniff.php new file mode 100644 index 00000000..1c9e4000 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyPHPStatementSniff.php @@ -0,0 +1,162 @@ + + * @copyright 2017 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmptyPHPStatementSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return int[] + */ + public function register() + { + return [ + T_SEMICOLON, + T_CLOSE_TAG, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$stackPtr]['type']) { + // Detect `something();;`. + case 'T_SEMICOLON': + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + if ($prevNonEmpty === false) { + return; + } + + if ($tokens[$prevNonEmpty]['code'] !== T_SEMICOLON + && $tokens[$prevNonEmpty]['code'] !== T_OPEN_TAG + && $tokens[$prevNonEmpty]['code'] !== T_OPEN_TAG_WITH_ECHO + ) { + if (isset($tokens[$prevNonEmpty]['scope_condition']) === false) { + return; + } + + if ($tokens[$prevNonEmpty]['scope_opener'] !== $prevNonEmpty + && $tokens[$prevNonEmpty]['code'] !== T_CLOSE_CURLY_BRACKET + ) { + return; + } + + $scopeOwner = $tokens[$tokens[$prevNonEmpty]['scope_condition']]['code']; + if ($scopeOwner === T_CLOSURE || $scopeOwner === T_ANON_CLASS || $scopeOwner === T_MATCH) { + return; + } + + // Else, it's something like `if (foo) {};` and the semi-colon is not needed. + } + + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nested = $tokens[$stackPtr]['nested_parenthesis']; + $lastCloser = array_pop($nested); + if (isset($tokens[$lastCloser]['parenthesis_owner']) === true + && $tokens[$tokens[$lastCloser]['parenthesis_owner']]['code'] === T_FOR + ) { + // Empty for() condition. + return; + } + } + + $fix = $phpcsFile->addFixableWarning( + 'Empty PHP statement detected: superfluous semi-colon.', + $stackPtr, + 'SemicolonWithoutCodeDetected' + ); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + if ($tokens[$prevNonEmpty]['code'] === T_OPEN_TAG + || $tokens[$prevNonEmpty]['code'] === T_OPEN_TAG_WITH_ECHO + ) { + // Check for superfluous whitespace after the semi-colon which will be + // removed as the `fixer->replaceToken(($stackPtr + 1), $replacement); + } + } + + for ($i = $stackPtr; $i > $prevNonEmpty; $i--) { + if ($tokens[$i]['code'] !== T_SEMICOLON + && $tokens[$i]['code'] !== T_WHITESPACE + ) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + break; + + // Detect ``. + case 'T_CLOSE_TAG': + $prevNonEmpty = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + + if ($prevNonEmpty === false + || ($tokens[$prevNonEmpty]['code'] !== T_OPEN_TAG + && $tokens[$prevNonEmpty]['code'] !== T_OPEN_TAG_WITH_ECHO) + ) { + return; + } + + $fix = $phpcsFile->addFixableWarning( + 'Empty PHP open/close tag combination detected.', + $prevNonEmpty, + 'EmptyPHPOpenCloseTagsDetected' + ); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = $prevNonEmpty; $i <= $stackPtr; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + break; + + default: + // Deliberately left empty. + break; + }//end switch + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php new file mode 100644 index 00000000..574bb0ba --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php @@ -0,0 +1,97 @@ + + * stmt { + * // foo + * } + * stmt (conditions) { + * // foo + * } + * + * + * @author Manuel Pichler + * @author Greg Sherwood + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmptyStatementSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [ + T_TRY, + T_CATCH, + T_FINALLY, + T_DO, + T_ELSE, + T_ELSEIF, + T_FOR, + T_FOREACH, + T_IF, + T_SWITCH, + T_WHILE, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip statements without a body. + if (isset($token['scope_opener']) === false) { + return; + } + + $next = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($token['scope_opener'] + 1), + ($token['scope_closer'] - 1), + true + ); + + if ($next !== false) { + return; + } + + // Get token identifier. + $name = strtoupper($token['content']); + $error = 'Empty %s statement detected'; + $phpcsFile->addError($error, $stackPtr, 'Detected'.ucfirst(strtolower($name)), [$name]); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.php new file mode 100644 index 00000000..f583e938 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.php @@ -0,0 +1,91 @@ + + * class Foo + * { + * public function bar($x) + * { + * for (;true;) true; // No Init or Update part, may as well be: while (true) + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ForLoopShouldBeWhileLoopSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_FOR]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip invalid statement. + if (isset($token['parenthesis_opener']) === false) { + return; + } + + $next = ++$token['parenthesis_opener']; + $end = --$token['parenthesis_closer']; + + $parts = [ + 0, + 0, + 0, + ]; + $index = 0; + + for (; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + if ($code === T_SEMICOLON) { + ++$index; + } else if (isset(Tokens::$emptyTokens[$code]) === false) { + ++$parts[$index]; + } + } + + if ($parts[0] === 0 && $parts[2] === 0 && $parts[1] > 0) { + $error = 'This FOR loop can be simplified to a WHILE loop'; + $phpcsFile->addWarning($error, $stackPtr, 'CanSimplify'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php new file mode 100644 index 00000000..62a07b26 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php @@ -0,0 +1,101 @@ + + * class Foo + * { + * public function bar($x) + * { + * $a = array(1, 2, 3, 4); + * for ($i = 0; $i < count($a); $i++) { + * $a[$i] *= $i; + * } + * } + * } + * + * + * @author Greg Sherwood + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ForLoopWithTestFunctionCallSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_FOR]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip invalid statement. + if (isset($token['parenthesis_opener']) === false) { + return; + } + + $next = ++$token['parenthesis_opener']; + $end = --$token['parenthesis_closer']; + + $position = 0; + + for (; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + if ($code === T_SEMICOLON) { + ++$position; + } + + if ($position < 1) { + continue; + } else if ($position > 1) { + break; + } else if ($code !== T_VARIABLE && $code !== T_STRING) { + continue; + } + + // Find next non empty token, if it is a open curly brace we have a + // function call. + $index = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + + if ($tokens[$index]['code'] === T_OPEN_PARENTHESIS) { + $error = 'Avoid function calls in a FOR loop test part'; + $phpcsFile->addWarning($error, $stackPtr, 'NotAllowed'); + break; + } + }//end for + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php new file mode 100644 index 00000000..364658db --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php @@ -0,0 +1,134 @@ + + * class Foo + * { + * public function bar($x) + * { + * for ($i = 0; $i < 10; $i++) + * { + * for ($k = 0; $k < 20; $i++) + * { + * echo 'Hello'; + * } + * } + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class JumbledIncrementerSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_FOR]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip for-loop without body. + if (isset($token['scope_opener']) === false) { + return; + } + + // Find incrementors for outer loop. + $outer = $this->findIncrementers($tokens, $token); + + // Skip if empty. + if (count($outer) === 0) { + return; + } + + // Find nested for loops. + $start = ++$token['scope_opener']; + $end = --$token['scope_closer']; + + for (; $start <= $end; ++$start) { + if ($tokens[$start]['code'] !== T_FOR) { + continue; + } + + $inner = $this->findIncrementers($tokens, $tokens[$start]); + $diff = array_intersect($outer, $inner); + + if (count($diff) !== 0) { + $error = 'Loop incrementor (%s) jumbling with inner loop'; + $data = [join(', ', $diff)]; + $phpcsFile->addWarning($error, $stackPtr, 'Found', $data); + } + } + + }//end process() + + + /** + * Get all used variables in the incrementer part of a for statement. + * + * @param array(integer=>array) $tokens Array with all code sniffer tokens. + * @param array(string=>mixed) $token Current for loop token + * + * @return string[] List of all found incrementer variables. + */ + protected function findIncrementers(array $tokens, array $token) + { + // Skip invalid statement. + if (isset($token['parenthesis_opener']) === false) { + return []; + } + + $start = ++$token['parenthesis_opener']; + $end = --$token['parenthesis_closer']; + + $incrementers = []; + $semicolons = 0; + for ($next = $start; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + if ($code === T_SEMICOLON) { + ++$semicolons; + } else if ($semicolons === 2 && $code === T_VARIABLE) { + $incrementers[] = $tokens[$next]['content']; + } + } + + return $incrementers; + + }//end findIncrementers() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php new file mode 100644 index 00000000..cc9958c5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php @@ -0,0 +1,93 @@ +true or false + * + * + * class Foo + * { + * public function close() + * { + * if (true) + * { + * // ... + * } + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UnconditionalIfStatementSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [ + T_IF, + T_ELSEIF, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip if statement without body. + if (isset($token['parenthesis_opener']) === false) { + return; + } + + $next = ++$token['parenthesis_opener']; + $end = --$token['parenthesis_closer']; + + $goodCondition = false; + for (; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + + if (isset(Tokens::$emptyTokens[$code]) === true) { + continue; + } else if ($code !== T_TRUE && $code !== T_FALSE) { + $goodCondition = true; + } + } + + if ($goodCondition === false) { + $error = 'Avoid IF statements that are always true or false'; + $phpcsFile->addWarning($error, $stackPtr, 'Found'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php new file mode 100644 index 00000000..bed67c93 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php @@ -0,0 +1,85 @@ + + * final class Foo + * { + * public final function bar() + * { + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UnnecessaryFinalModifierSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip for-statements without body. + if (isset($token['scope_opener']) === false) { + return; + } + + // Fetch previous token. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + // Skip for non final class. + if ($prev === false || $tokens[$prev]['code'] !== T_FINAL) { + return; + } + + $next = ++$token['scope_opener']; + $end = --$token['scope_closer']; + + for (; $next <= $end; ++$next) { + if ($tokens[$next]['code'] === T_FINAL) { + $error = 'Unnecessary FINAL modifier in FINAL class'; + $phpcsFile->addWarning($error, $next, 'Found'); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php new file mode 100644 index 00000000..58aa29fe --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php @@ -0,0 +1,265 @@ + + * @author Greg Sherwood + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UnusedFunctionParameterSniff implements Sniff +{ + + /** + * The list of class type hints which will be ignored. + * + * @var array + */ + public $ignoreTypeHints = []; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + T_FN, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip broken function declarations. + if (isset($token['scope_opener']) === false || isset($token['parenthesis_opener']) === false) { + return; + } + + $errorCode = 'Found'; + $implements = false; + $extends = false; + $classPtr = $phpcsFile->getCondition($stackPtr, T_CLASS); + if ($classPtr !== false) { + $implements = $phpcsFile->findImplementedInterfaceNames($classPtr); + $extends = $phpcsFile->findExtendedClassName($classPtr); + if ($extends !== false) { + $errorCode .= 'InExtendedClass'; + } else if ($implements !== false) { + $errorCode .= 'InImplementedInterface'; + } + } + + $params = []; + $methodParams = $phpcsFile->getMethodParameters($stackPtr); + + // Skip when no parameters found. + $methodParamsCount = count($methodParams); + if ($methodParamsCount === 0) { + return; + } + + foreach ($methodParams as $param) { + if (isset($param['property_visibility']) === true) { + // Ignore constructor property promotion. + continue; + } + + $params[$param['name']] = $stackPtr; + } + + $next = ++$token['scope_opener']; + $end = --$token['scope_closer']; + + // Check the end token for arrow functions as + // they can end at a content token due to not having + // a clearly defined closing token. + if ($token['code'] === T_FN) { + ++$end; + } + + $foundContent = false; + $validTokens = [ + T_HEREDOC => T_HEREDOC, + T_NOWDOC => T_NOWDOC, + T_END_HEREDOC => T_END_HEREDOC, + T_END_NOWDOC => T_END_NOWDOC, + T_DOUBLE_QUOTED_STRING => T_DOUBLE_QUOTED_STRING, + ]; + $validTokens += Tokens::$emptyTokens; + + for (; $next <= $end; ++$next) { + $token = $tokens[$next]; + $code = $token['code']; + + // Ignorable tokens. + if (isset(Tokens::$emptyTokens[$code]) === true) { + continue; + } + + if ($foundContent === false) { + // A throw statement as the first content indicates an interface method. + if ($code === T_THROW && $implements !== false) { + return; + } + + // A return statement as the first content indicates an interface method. + if ($code === T_RETURN) { + $tmp = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + if ($tmp === false && $implements !== false) { + return; + } + + // There is a return. + if ($tokens[$tmp]['code'] === T_SEMICOLON && $implements !== false) { + return; + } + + $tmp = $phpcsFile->findNext(Tokens::$emptyTokens, ($tmp + 1), null, true); + if ($tmp !== false && $tokens[$tmp]['code'] === T_SEMICOLON && $implements !== false) { + // There is a return . + return; + } + }//end if + }//end if + + $foundContent = true; + + if ($code === T_VARIABLE && isset($params[$token['content']]) === true) { + unset($params[$token['content']]); + } else if ($code === T_DOLLAR) { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true); + if ($tokens[$nextToken]['code'] === T_OPEN_CURLY_BRACKET) { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] === T_STRING) { + $varContent = '$'.$tokens[$nextToken]['content']; + if (isset($params[$varContent]) === true) { + unset($params[$varContent]); + } + } + } + } else if ($code === T_DOUBLE_QUOTED_STRING + || $code === T_START_HEREDOC + || $code === T_START_NOWDOC + ) { + // Tokenize strings that can contain variables. + // Make sure the string is re-joined if it occurs over multiple lines. + $content = $token['content']; + for ($i = ($next + 1); $i <= $end; $i++) { + if (isset($validTokens[$tokens[$i]['code']]) === true) { + $content .= $tokens[$i]['content']; + $next++; + } else { + break; + } + } + + $stringTokens = token_get_all(sprintf('', $content)); + foreach ($stringTokens as $stringPtr => $stringToken) { + if (is_array($stringToken) === false) { + continue; + } + + $varContent = ''; + if ($stringToken[0] === T_DOLLAR_OPEN_CURLY_BRACES) { + $varContent = '$'.$stringTokens[($stringPtr + 1)][1]; + } else if ($stringToken[0] === T_VARIABLE) { + $varContent = $stringToken[1]; + } + + if ($varContent !== '' && isset($params[$varContent]) === true) { + unset($params[$varContent]); + } + } + }//end if + }//end for + + if ($foundContent === true && count($params) > 0) { + $error = 'The method parameter %s is never used'; + + // If there is only one parameter and it is unused, no need for additional errorcode toggling logic. + if ($methodParamsCount === 1) { + foreach ($params as $paramName => $position) { + if (in_array($methodParams[0]['type_hint'], $this->ignoreTypeHints, true) === true) { + continue; + } + + $data = [$paramName]; + $phpcsFile->addWarning($error, $position, $errorCode, $data); + } + + return; + } + + $foundLastUsed = false; + $lastIndex = ($methodParamsCount - 1); + $errorInfo = []; + for ($i = $lastIndex; $i >= 0; --$i) { + if ($foundLastUsed !== false) { + if (isset($params[$methodParams[$i]['name']]) === true) { + $errorInfo[$methodParams[$i]['name']] = [ + 'position' => $params[$methodParams[$i]['name']], + 'errorcode' => $errorCode.'BeforeLastUsed', + 'typehint' => $methodParams[$i]['type_hint'], + ]; + } + } else { + if (isset($params[$methodParams[$i]['name']]) === false) { + $foundLastUsed = true; + } else { + $errorInfo[$methodParams[$i]['name']] = [ + 'position' => $params[$methodParams[$i]['name']], + 'errorcode' => $errorCode.'AfterLastUsed', + 'typehint' => $methodParams[$i]['type_hint'], + ]; + } + } + }//end for + + if (count($errorInfo) > 0) { + $errorInfo = array_reverse($errorInfo); + foreach ($errorInfo as $paramName => $info) { + if (in_array($info['typehint'], $this->ignoreTypeHints, true) === true) { + continue; + } + + $data = [$paramName]; + $phpcsFile->addWarning($error, $info['position'], $info['errorcode'], $data); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php new file mode 100644 index 00000000..fded9295 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php @@ -0,0 +1,161 @@ + + * class FooBar { + * public function __construct($a, $b) { + * parent::__construct($a, $b); + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UselessOverridingMethodSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip function without body. + if (isset($token['scope_opener']) === false) { + return; + } + + // Get function name. + $methodName = $phpcsFile->getDeclarationName($stackPtr); + + // Get all parameters from method signature. + $signature = []; + foreach ($phpcsFile->getMethodParameters($stackPtr) as $param) { + $signature[] = $param['name']; + } + + $next = ++$token['scope_opener']; + $end = --$token['scope_closer']; + + for (; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + + if (isset(Tokens::$emptyTokens[$code]) === true) { + continue; + } else if ($code === T_RETURN) { + continue; + } + + break; + } + + // Any token except 'parent' indicates correct code. + if ($tokens[$next]['code'] !== T_PARENT) { + return; + } + + // Find next non empty token index, should be double colon. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + + // Skip for invalid code. + if ($next === false || $tokens[$next]['code'] !== T_DOUBLE_COLON) { + return; + } + + // Find next non empty token index, should be the function name. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + + // Skip for invalid code or other method. + if ($next === false || $tokens[$next]['content'] !== $methodName) { + return; + } + + // Find next non empty token index, should be the open parenthesis. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + + // Skip for invalid code. + if ($next === false || $tokens[$next]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + $parameters = ['']; + $parenthesisCount = 1; + $count = count($tokens); + for (++$next; $next < $count; ++$next) { + $code = $tokens[$next]['code']; + + if ($code === T_OPEN_PARENTHESIS) { + ++$parenthesisCount; + } else if ($code === T_CLOSE_PARENTHESIS) { + --$parenthesisCount; + } else if ($parenthesisCount === 1 && $code === T_COMMA) { + $parameters[] = ''; + } else if (isset(Tokens::$emptyTokens[$code]) === false) { + $parameters[(count($parameters) - 1)] .= $tokens[$next]['content']; + } + + if ($parenthesisCount === 0) { + break; + } + }//end for + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + if ($next === false || $tokens[$next]['code'] !== T_SEMICOLON) { + return; + } + + // Check rest of the scope. + for (++$next; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + // Skip for any other content. + if (isset(Tokens::$emptyTokens[$code]) === false) { + return; + } + } + + $parameters = array_map('trim', $parameters); + $parameters = array_filter($parameters); + + if (count($parameters) === count($signature) && $parameters === $signature) { + $phpcsFile->addWarning('Possible useless method overriding detected', $stackPtr, 'Found'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/DocCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/DocCommentSniff.php new file mode 100644 index 00000000..545319be --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/DocCommentSniff.php @@ -0,0 +1,353 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DocCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOC_COMMENT_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['comment_closer']) === false + || ($tokens[$tokens[$stackPtr]['comment_closer']]['content'] === '' + && $tokens[$stackPtr]['comment_closer'] === ($phpcsFile->numTokens - 1)) + ) { + // Don't process an unfinished comment during live coding. + return; + } + + $commentStart = $stackPtr; + $commentEnd = $tokens[$stackPtr]['comment_closer']; + + $empty = [ + T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_STAR, + ]; + + $short = $phpcsFile->findNext($empty, ($stackPtr + 1), $commentEnd, true); + if ($short === false) { + // No content at all. + $error = 'Doc comment is empty'; + $phpcsFile->addError($error, $stackPtr, 'Empty'); + return; + } + + // The first line of the comment should just be the /** code. + if ($tokens[$short]['line'] === $tokens[$stackPtr]['line']) { + $error = 'The open comment tag must be the only content on the line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentAfterOpen'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($stackPtr); + $phpcsFile->fixer->addContentBefore($short, '* '); + $phpcsFile->fixer->endChangeset(); + } + } + + // The last line of the comment should just be the */ code. + $prev = $phpcsFile->findPrevious($empty, ($commentEnd - 1), $stackPtr, true); + if ($tokens[$prev]['line'] === $tokens[$commentEnd]['line']) { + $error = 'The close comment tag must be the only content on the line'; + $fix = $phpcsFile->addFixableError($error, $commentEnd, 'ContentBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($commentEnd); + } + } + + // Check for additional blank lines at the end of the comment. + if ($tokens[$prev]['line'] < ($tokens[$commentEnd]['line'] - 1)) { + $error = 'Additional blank lines found at end of doc comment'; + $fix = $phpcsFile->addFixableError($error, $commentEnd, 'SpacingAfter'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $commentEnd; $i++) { + if ($tokens[($i + 1)]['line'] === $tokens[$commentEnd]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + // Check for a comment description. + if ($tokens[$short]['code'] !== T_DOC_COMMENT_STRING) { + $error = 'Missing short description in doc comment'; + $phpcsFile->addError($error, $stackPtr, 'MissingShort'); + } else { + // No extra newline before short description. + if ($tokens[$short]['line'] !== ($tokens[$stackPtr]['line'] + 1)) { + $error = 'Doc comment short description must be on the first line'; + $fix = $phpcsFile->addFixableError($error, $short, 'SpacingBeforeShort'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $stackPtr; $i < $short; $i++) { + if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) { + continue; + } else if ($tokens[$i]['line'] === $tokens[$short]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + // Account for the fact that a short description might cover + // multiple lines. + $shortContent = $tokens[$short]['content']; + $shortEnd = $short; + for ($i = ($short + 1); $i < $commentEnd; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + if ($tokens[$i]['line'] === ($tokens[$shortEnd]['line'] + 1)) { + $shortContent .= $tokens[$i]['content']; + $shortEnd = $i; + } else { + break; + } + } + } + + if (preg_match('/^\p{Ll}/u', $shortContent) === 1) { + $error = 'Doc comment short description must start with a capital letter'; + $phpcsFile->addError($error, $short, 'ShortNotCapital'); + } + + $long = $phpcsFile->findNext($empty, ($shortEnd + 1), ($commentEnd - 1), true); + if ($long !== false && $tokens[$long]['code'] === T_DOC_COMMENT_STRING) { + if ($tokens[$long]['line'] !== ($tokens[$shortEnd]['line'] + 2)) { + $error = 'There must be exactly one blank line between descriptions in a doc comment'; + $fix = $phpcsFile->addFixableError($error, $long, 'SpacingBetween'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($shortEnd + 1); $i < $long; $i++) { + if ($tokens[$i]['line'] === $tokens[$shortEnd]['line']) { + continue; + } else if ($tokens[$i]['line'] === ($tokens[$long]['line'] - 1)) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + if (preg_match('/^\p{Ll}/u', $tokens[$long]['content']) === 1) { + $error = 'Doc comment long description must start with a capital letter'; + $phpcsFile->addError($error, $long, 'LongNotCapital'); + } + }//end if + }//end if + + if (empty($tokens[$commentStart]['comment_tags']) === true) { + // No tags in the comment. + return; + } + + $firstTag = $tokens[$commentStart]['comment_tags'][0]; + $prev = $phpcsFile->findPrevious($empty, ($firstTag - 1), $stackPtr, true); + if ($tokens[$firstTag]['line'] !== ($tokens[$prev]['line'] + 2) + && $tokens[$prev]['code'] !== T_DOC_COMMENT_OPEN_TAG + ) { + $error = 'There must be exactly one blank line before the tags in a doc comment'; + $fix = $phpcsFile->addFixableError($error, $firstTag, 'SpacingBeforeTags'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $firstTag; $i++) { + if ($tokens[$i]['line'] === $tokens[$firstTag]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $indent = str_repeat(' ', $tokens[$stackPtr]['column']); + $phpcsFile->fixer->addContent($prev, $phpcsFile->eolChar.$indent.'*'.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + } + + // Break out the tags into groups and check alignment within each. + // A tag group is one where there are no blank lines between tags. + // The param tag group is special as it requires all @param tags to be inside. + $tagGroups = []; + $groupid = 0; + $paramGroupid = null; + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($pos > 0) { + $prev = $phpcsFile->findPrevious( + T_DOC_COMMENT_STRING, + ($tag - 1), + $tokens[$commentStart]['comment_tags'][($pos - 1)] + ); + + if ($prev === false) { + $prev = $tokens[$commentStart]['comment_tags'][($pos - 1)]; + } + + if ($tokens[$prev]['line'] !== ($tokens[$tag]['line'] - 1)) { + $groupid++; + } + } + + if ($tokens[$tag]['content'] === '@param') { + if ($paramGroupid !== null + && $paramGroupid !== $groupid + ) { + $error = 'Parameter tags must be grouped together in a doc comment'; + $phpcsFile->addError($error, $tag, 'ParamGroup'); + } + + if ($paramGroupid === null) { + $paramGroupid = $groupid; + } + }//end if + + $tagGroups[$groupid][] = $tag; + }//end foreach + + foreach ($tagGroups as $groupid => $group) { + $maxLength = 0; + $paddings = []; + foreach ($group as $pos => $tag) { + if ($paramGroupid === $groupid + && $tokens[$tag]['content'] !== '@param' + ) { + $error = 'Tag %s cannot be grouped with parameter tags in a doc comment'; + $data = [$tokens[$tag]['content']]; + $phpcsFile->addError($error, $tag, 'NonParamGroup', $data); + } + + $tagLength = $tokens[$tag]['length']; + if ($tagLength > $maxLength) { + $maxLength = $tagLength; + } + + // Check for a value. No value means no padding needed. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string !== false && $tokens[$string]['line'] === $tokens[$tag]['line']) { + $paddings[$tag] = $tokens[($tag + 1)]['length']; + } + } + + // Check that there was single blank line after the tag block + // but account for a multi-line tag comments. + $lastTag = $group[$pos]; + $next = $phpcsFile->findNext(T_DOC_COMMENT_TAG, ($lastTag + 3), $commentEnd); + if ($next !== false) { + $prev = $phpcsFile->findPrevious([T_DOC_COMMENT_TAG, T_DOC_COMMENT_STRING], ($next - 1), $commentStart); + if ($tokens[$next]['line'] !== ($tokens[$prev]['line'] + 2)) { + $error = 'There must be a single blank line after a tag group'; + $fix = $phpcsFile->addFixableError($error, $lastTag, 'SpacingAfterTagGroup'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $indent = str_repeat(' ', $tokens[$stackPtr]['column']); + $phpcsFile->fixer->addContent($prev, $phpcsFile->eolChar.$indent.'*'.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + // Now check paddings. + foreach ($paddings as $tag => $padding) { + $required = ($maxLength - $tokens[$tag]['length'] + 1); + + if ($padding !== $required) { + $error = 'Tag value for %s tag indented incorrectly; expected %s spaces but found %s'; + $data = [ + $tokens[$tag]['content'], + $required, + $padding, + ]; + + $fix = $phpcsFile->addFixableError($error, ($tag + 1), 'TagValueIndent', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($tag + 1), str_repeat(' ', $required)); + } + } + } + }//end foreach + + // If there is a param group, it needs to be first. + if ($paramGroupid !== null && $paramGroupid !== 0) { + $error = 'Parameter tags must be defined first in a doc comment'; + $phpcsFile->addError($error, $tagGroups[$paramGroupid][0], 'ParamNotFirst'); + } + + $foundTags = []; + foreach ($tokens[$stackPtr]['comment_tags'] as $pos => $tag) { + $tagName = $tokens[$tag]['content']; + if (isset($foundTags[$tagName]) === true) { + $lastTag = $tokens[$stackPtr]['comment_tags'][($pos - 1)]; + if ($tokens[$lastTag]['content'] !== $tagName) { + $error = 'Tags must be grouped together in a doc comment'; + $phpcsFile->addError($error, $tag, 'TagsNotGrouped'); + } + + continue; + } + + $foundTags[$tagName] = true; + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/FixmeSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/FixmeSniff.php new file mode 100644 index 00000000..84385221 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/FixmeSniff.php @@ -0,0 +1,78 @@ + + * @author Sam Graham + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FixmeSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return array_diff(Tokens::$commentTokens, Tokens::$phpcsCommentTokens); + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $matches = []; + preg_match('/(?:\A|[^\p{L}]+)fixme([^\p{L}]+(.*)|\Z)/ui', $content, $matches); + if (empty($matches) === false) { + // Clear whitespace and some common characters not required at + // the end of a fixme message to make the error more informative. + $type = 'CommentFound'; + $fixmeMessage = trim($matches[1]); + $fixmeMessage = trim($fixmeMessage, '-:[](). '); + $error = 'Comment refers to a FIXME task'; + $data = [$fixmeMessage]; + if ($fixmeMessage !== '') { + $type = 'TaskFound'; + $error .= ' "%s"'; + } + + $phpcsFile->addError($error, $stackPtr, $type, $data); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/TodoSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/TodoSniff.php new file mode 100644 index 00000000..63968046 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/TodoSniff.php @@ -0,0 +1,77 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class TodoSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return array_diff(Tokens::$commentTokens, Tokens::$phpcsCommentTokens); + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $matches = []; + preg_match('/(?:\A|[^\p{L}]+)todo([^\p{L}]+(.*)|\Z)/ui', $content, $matches); + if (empty($matches) === false) { + // Clear whitespace and some common characters not required at + // the end of a to-do message to make the warning more informative. + $type = 'CommentFound'; + $todoMessage = trim($matches[1]); + $todoMessage = trim($todoMessage, '-:[](). '); + $error = 'Comment refers to a TODO task'; + $data = [$todoMessage]; + if ($todoMessage !== '') { + $type = 'TaskFound'; + $error .= ' "%s"'; + } + + $phpcsFile->addWarning($error, $stackPtr, $type, $data); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/DisallowYodaConditionsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/DisallowYodaConditionsSniff.php new file mode 100644 index 00000000..f760fa1c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/DisallowYodaConditionsSniff.php @@ -0,0 +1,188 @@ + + * @author Mark Scherer + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowYodaConditionsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$comparisonTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $previousIndex = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + $relevantTokens = [ + T_CLOSE_SHORT_ARRAY, + T_CLOSE_PARENTHESIS, + T_TRUE, + T_FALSE, + T_NULL, + T_LNUMBER, + T_DNUMBER, + T_CONSTANT_ENCAPSED_STRING, + ]; + + if ($previousIndex === false + || in_array($tokens[$previousIndex]['code'], $relevantTokens, true) === false + ) { + return; + } + + if ($tokens[$previousIndex]['code'] === T_CLOSE_SHORT_ARRAY) { + $previousIndex = $tokens[$previousIndex]['bracket_opener']; + if ($this->isArrayStatic($phpcsFile, $previousIndex) === false) { + return; + } + } + + $prevIndex = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($previousIndex - 1), null, true); + if ($prevIndex === false) { + return; + } + + if (in_array($tokens[$prevIndex]['code'], Tokens::$arithmeticTokens, true) === true) { + return; + } + + if ($tokens[$prevIndex]['code'] === T_STRING_CONCAT) { + return; + } + + // Is it a parenthesis. + if ($tokens[$previousIndex]['code'] === T_CLOSE_PARENTHESIS) { + // Check what exists inside the parenthesis. + $closeParenthesisIndex = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($tokens[$previousIndex]['parenthesis_opener'] - 1), + null, + true + ); + + if ($closeParenthesisIndex === false || $tokens[$closeParenthesisIndex]['code'] !== T_ARRAY) { + if ($tokens[$closeParenthesisIndex]['code'] === T_STRING) { + return; + } + + // If it is not an array check what is inside. + $found = $phpcsFile->findPrevious( + T_VARIABLE, + ($previousIndex - 1), + $tokens[$previousIndex]['parenthesis_opener'] + ); + + // If a variable exists, it is not Yoda. + if ($found !== false) { + return; + } + + // If there is nothing inside the parenthesis, it it not a Yoda. + $opener = $tokens[$previousIndex]['parenthesis_opener']; + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($previousIndex - 1), ($opener + 1), true); + if ($prev === false) { + return; + } + } else if ($tokens[$closeParenthesisIndex]['code'] === T_ARRAY + && $this->isArrayStatic($phpcsFile, $closeParenthesisIndex) === false + ) { + return; + }//end if + }//end if + + $phpcsFile->addError( + 'Usage of Yoda conditions is not allowed; switch the expression order', + $stackPtr, + 'Found' + ); + + }//end process() + + + /** + * Determines if an array is a static definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $arrayToken The position of the array token. + * + * @return bool + */ + public function isArrayStatic(File $phpcsFile, $arrayToken) + { + $tokens = $phpcsFile->getTokens(); + + $arrayEnd = null; + if ($tokens[$arrayToken]['code'] === T_OPEN_SHORT_ARRAY) { + $start = $arrayToken; + $end = $tokens[$arrayToken]['bracket_closer']; + } else if ($tokens[$arrayToken]['code'] === T_ARRAY) { + $start = $tokens[$arrayToken]['parenthesis_opener']; + $end = $tokens[$arrayToken]['parenthesis_closer']; + } else { + return true; + } + + $staticTokens = Tokens::$emptyTokens; + $staticTokens += Tokens::$textStringTokens; + $staticTokens += Tokens::$assignmentTokens; + $staticTokens += Tokens::$equalityTokens; + $staticTokens += Tokens::$comparisonTokens; + $staticTokens += Tokens::$arithmeticTokens; + $staticTokens += Tokens::$operators; + $staticTokens += Tokens::$booleanOperators; + $staticTokens += Tokens::$castTokens; + $staticTokens += Tokens::$bracketTokens; + $staticTokens += [ + T_DOUBLE_ARROW => T_DOUBLE_ARROW, + T_COMMA => T_COMMA, + T_TRUE => T_TRUE, + T_FALSE => T_FALSE, + ]; + + for ($i = ($start + 1); $i < $end; $i++) { + if (isset($tokens[$i]['scope_closer']) === true) { + $i = $tokens[$i]['scope_closer']; + continue; + } + + if (isset($staticTokens[$tokens[$i]['code']]) === false) { + return false; + } + } + + return true; + + }//end isArrayStatic() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php new file mode 100644 index 00000000..a67a6a79 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php @@ -0,0 +1,381 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class InlineControlStructureSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * If true, an error will be thrown; otherwise a warning. + * + * @var boolean + */ + public $error = true; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_ELSE, + T_ELSEIF, + T_FOREACH, + T_WHILE, + T_DO, + T_SWITCH, + T_FOR, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === true) { + $phpcsFile->recordMetric($stackPtr, 'Control structure defined inline', 'no'); + return; + } + + // Ignore the ELSE in ELSE IF. We'll process the IF part later. + if ($tokens[$stackPtr]['code'] === T_ELSE) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_IF) { + return; + } + } + + if ($tokens[$stackPtr]['code'] === T_WHILE || $tokens[$stackPtr]['code'] === T_FOR) { + // This could be from a DO WHILE, which doesn't have an opening brace or a while/for without body. + if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) { + $afterParensCloser = $phpcsFile->findNext(Tokens::$emptyTokens, ($tokens[$stackPtr]['parenthesis_closer'] + 1), null, true); + if ($afterParensCloser === false) { + // Live coding. + return; + } + + if ($tokens[$afterParensCloser]['code'] === T_SEMICOLON) { + $phpcsFile->recordMetric($stackPtr, 'Control structure defined inline', 'no'); + return; + } + } + + // In Javascript DO WHILE loops without curly braces are legal. This + // is only valid if a single statement is present between the DO and + // the WHILE. We can detect this by checking only a single semicolon + // is present between them. + if ($tokens[$stackPtr]['code'] === T_WHILE && $phpcsFile->tokenizerType === 'JS') { + $lastDo = $phpcsFile->findPrevious(T_DO, ($stackPtr - 1)); + $lastSemicolon = $phpcsFile->findPrevious(T_SEMICOLON, ($stackPtr - 1)); + if ($lastDo !== false && $lastSemicolon !== false && $lastDo < $lastSemicolon) { + $precedingSemicolon = $phpcsFile->findPrevious(T_SEMICOLON, ($lastSemicolon - 1)); + if ($precedingSemicolon === false || $precedingSemicolon < $lastDo) { + return; + } + } + } + }//end if + + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false + && $tokens[$stackPtr]['code'] !== T_ELSE + ) { + if ($tokens[$stackPtr]['code'] !== T_DO) { + // Live coding or parse error. + return; + } + + $nextWhile = $phpcsFile->findNext(T_WHILE, ($stackPtr + 1)); + if ($nextWhile !== false + && isset($tokens[$nextWhile]['parenthesis_opener'], $tokens[$nextWhile]['parenthesis_closer']) === false + ) { + // Live coding or parse error. + return; + } + + unset($nextWhile); + } + + $start = $stackPtr; + if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) { + $start = $tokens[$stackPtr]['parenthesis_closer']; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($start + 1), null, true); + if ($nextNonEmpty === false) { + // Live coding or parse error. + return; + } + + if ($tokens[$nextNonEmpty]['code'] === T_OPEN_CURLY_BRACKET + || $tokens[$nextNonEmpty]['code'] === T_COLON + ) { + // T_CLOSE_CURLY_BRACKET missing, or alternative control structure with + // T_END... missing. Either live coding, parse error or end + // tag in short open tags and scan run with short_open_tag=Off. + // Bow out completely as any further detection will be unreliable + // and create incorrect fixes or cause fixer conflicts. + return ($phpcsFile->numTokens + 1); + } + + unset($nextNonEmpty, $start); + + // This is a control structure without an opening brace, + // so it is an inline statement. + if ($this->error === true) { + $fix = $phpcsFile->addFixableError('Inline control structures are not allowed', $stackPtr, 'NotAllowed'); + } else { + $fix = $phpcsFile->addFixableWarning('Inline control structures are discouraged', $stackPtr, 'Discouraged'); + } + + $phpcsFile->recordMetric($stackPtr, 'Control structure defined inline', 'yes'); + + // Stop here if we are not fixing the error. + if ($fix !== true) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) { + $closer = $tokens[$stackPtr]['parenthesis_closer']; + } else { + $closer = $stackPtr; + } + + if ($tokens[($closer + 1)]['code'] === T_WHITESPACE + || $tokens[($closer + 1)]['code'] === T_SEMICOLON + ) { + $phpcsFile->fixer->addContent($closer, ' {'); + } else { + $phpcsFile->fixer->addContent($closer, ' { '); + } + + $fixableScopeOpeners = $this->register(); + + $lastNonEmpty = $closer; + for ($end = ($closer + 1); $end < $phpcsFile->numTokens; $end++) { + if ($tokens[$end]['code'] === T_SEMICOLON) { + break; + } + + if ($tokens[$end]['code'] === T_CLOSE_TAG) { + $end = $lastNonEmpty; + break; + } + + if (in_array($tokens[$end]['code'], $fixableScopeOpeners, true) === true + && isset($tokens[$end]['scope_opener']) === false + ) { + // The best way to fix nested inline scopes is middle-out. + // So skip this one. It will be detected and fixed on a future loop. + $phpcsFile->fixer->rollbackChangeset(); + return; + } + + if (isset($tokens[$end]['scope_opener']) === true) { + $type = $tokens[$end]['code']; + $end = $tokens[$end]['scope_closer']; + if ($type === T_DO + || $type === T_IF || $type === T_ELSEIF + || $type === T_TRY || $type === T_CATCH || $type === T_FINALLY + ) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($next === false) { + break; + } + + $nextType = $tokens[$next]['code']; + + // Let additional conditions loop and find their ending. + if (($type === T_IF + || $type === T_ELSEIF) + && ($nextType === T_ELSEIF + || $nextType === T_ELSE) + ) { + continue; + } + + // Account for TRY... CATCH/FINALLY statements. + if (($type === T_TRY + || $type === T_CATCH + || $type === T_FINALLY) + && ($nextType === T_CATCH + || $nextType === T_FINALLY) + ) { + continue; + } + + // Account for DO... WHILE conditions. + if ($type === T_DO && $nextType === T_WHILE) { + $end = $phpcsFile->findNext(T_SEMICOLON, ($next + 1)); + } + } else if ($type === T_CLOSURE) { + // There should be a semicolon after the closing brace. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($next !== false && $tokens[$next]['code'] === T_SEMICOLON) { + $end = $next; + } + }//end if + + if ($tokens[$end]['code'] !== T_END_HEREDOC + && $tokens[$end]['code'] !== T_END_NOWDOC + ) { + break; + } + }//end if + + if (isset($tokens[$end]['parenthesis_closer']) === true) { + $end = $tokens[$end]['parenthesis_closer']; + $lastNonEmpty = $end; + continue; + } + + if ($tokens[$end]['code'] !== T_WHITESPACE) { + $lastNonEmpty = $end; + } + }//end for + + if ($end === $phpcsFile->numTokens) { + $end = $lastNonEmpty; + } + + $nextContent = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($nextContent === false || $tokens[$nextContent]['line'] !== $tokens[$end]['line']) { + // Looks for completely empty statements. + $next = $phpcsFile->findNext(T_WHITESPACE, ($closer + 1), ($end + 1), true); + } else { + $next = ($end + 1); + $endLine = $end; + } + + if ($next !== $end) { + if ($nextContent === false || $tokens[$nextContent]['line'] !== $tokens[$end]['line']) { + // Account for a comment on the end of the line. + for ($endLine = $end; $endLine < $phpcsFile->numTokens; $endLine++) { + if (isset($tokens[($endLine + 1)]) === false + || $tokens[$endLine]['line'] !== $tokens[($endLine + 1)]['line'] + ) { + break; + } + } + + if (isset(Tokens::$commentTokens[$tokens[$endLine]['code']]) === false + && ($tokens[$endLine]['code'] !== T_WHITESPACE + || isset(Tokens::$commentTokens[$tokens[($endLine - 1)]['code']]) === false) + ) { + $endLine = $end; + } + } + + if ($endLine !== $end) { + $endToken = $endLine; + $addedContent = ''; + } else { + $endToken = $end; + $addedContent = $phpcsFile->eolChar; + + if ($tokens[$end]['code'] !== T_SEMICOLON + && $tokens[$end]['code'] !== T_CLOSE_CURLY_BRACKET + ) { + $phpcsFile->fixer->addContent($end, '; '); + } + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($endToken + 1), null, true); + if ($next !== false + && ($tokens[$next]['code'] === T_ELSE + || $tokens[$next]['code'] === T_ELSEIF) + ) { + $phpcsFile->fixer->addContentBefore($next, '} '); + } else { + $indent = ''; + for ($first = $stackPtr; $first > 0; $first--) { + if ($tokens[$first]['column'] === 1) { + break; + } + } + + if ($tokens[$first]['code'] === T_WHITESPACE) { + $indent = $tokens[$first]['content']; + } else if ($tokens[$first]['code'] === T_INLINE_HTML + || $tokens[$first]['code'] === T_OPEN_TAG + ) { + $addedContent = ''; + } + + $addedContent .= $indent.'}'; + if ($next !== false && $tokens[$endToken]['code'] === T_COMMENT) { + $addedContent .= $phpcsFile->eolChar; + } + + $phpcsFile->fixer->addContent($endToken, $addedContent); + }//end if + } else { + if ($nextContent === false || $tokens[$nextContent]['line'] !== $tokens[$end]['line']) { + // Account for a comment on the end of the line. + for ($endLine = $end; $endLine < $phpcsFile->numTokens; $endLine++) { + if (isset($tokens[($endLine + 1)]) === false + || $tokens[$endLine]['line'] !== $tokens[($endLine + 1)]['line'] + ) { + break; + } + } + + if ($tokens[$endLine]['code'] !== T_COMMENT + && ($tokens[$endLine]['code'] !== T_WHITESPACE + || $tokens[($endLine - 1)]['code'] !== T_COMMENT) + ) { + $endLine = $end; + } + } + + if ($endLine !== $end) { + $phpcsFile->fixer->replaceToken($end, ''); + $phpcsFile->fixer->addNewlineBefore($endLine); + $phpcsFile->fixer->addContent($endLine, '}'); + } else { + $phpcsFile->fixer->replaceToken($end, '}'); + } + }//end if + + $phpcsFile->fixer->endChangeset(); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/CSSLintSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/CSSLintSniff.php new file mode 100644 index 00000000..81284787 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/CSSLintSniff.php @@ -0,0 +1,96 @@ + + * @copyright 2013-2014 Roman Levishchenko + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class CSSLintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $csslintPath = Config::getExecutablePath('csslint'); + if ($csslintPath === null) { + return; + } + + $fileName = $phpcsFile->getFilename(); + + $cmd = Common::escapeshellcmd($csslintPath).' '.escapeshellarg($fileName).' 2>&1'; + exec($cmd, $output, $retval); + + if (is_array($output) === false) { + return; + } + + $count = count($output); + + for ($i = 0; $i < $count; $i++) { + $matches = []; + $numMatches = preg_match( + '/(error|warning) at line (\d+)/', + $output[$i], + $matches + ); + + if ($numMatches === 0) { + continue; + } + + $line = (int) $matches[2]; + $message = 'csslint says: '.$output[($i + 1)]; + // First line is message with error line and error code. + // Second is error message. + // Third is wrong line in file. + // Fourth is empty line. + $i += 4; + + $phpcsFile->addWarningOnLine($message, $line, 'ExternalTool'); + }//end for + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ClosureLinterSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ClosureLinterSniff.php new file mode 100644 index 00000000..19204718 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ClosureLinterSniff.php @@ -0,0 +1,117 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class ClosureLinterSniff implements Sniff +{ + + /** + * A list of error codes that should show errors. + * + * All other error codes will show warnings. + * + * @var integer + */ + public $errorCodes = []; + + /** + * A list of error codes to ignore. + * + * @var integer + */ + public $ignoreCodes = []; + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If jslint.js could not be run + */ + public function process(File $phpcsFile, $stackPtr) + { + $lintPath = Config::getExecutablePath('gjslint'); + if ($lintPath === null) { + return; + } + + $fileName = $phpcsFile->getFilename(); + + $lintPath = Common::escapeshellcmd($lintPath); + $cmd = $lintPath.' --nosummary --notime --unix_mode '.escapeshellarg($fileName); + exec($cmd, $output, $retval); + + if (is_array($output) === false) { + return; + } + + foreach ($output as $finding) { + $matches = []; + $numMatches = preg_match('/^(.*):([0-9]+):\(.*?([0-9]+)\)(.*)$/', $finding, $matches); + if ($numMatches === 0) { + continue; + } + + // Skip error codes we are ignoring. + $code = $matches[3]; + if (in_array($code, $this->ignoreCodes) === true) { + continue; + } + + $line = (int) $matches[2]; + $error = trim($matches[4]); + + $message = 'gjslint says: (%s) %s'; + $data = [ + $code, + $error, + ]; + if (in_array($code, $this->errorCodes) === true) { + $phpcsFile->addErrorOnLine($message, $line, 'ExternalToolError', $data); + } else { + $phpcsFile->addWarningOnLine($message, $line, 'ExternalTool', $data); + } + }//end foreach + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ESLintSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ESLintSniff.php new file mode 100644 index 00000000..d11d3470 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ESLintSniff.php @@ -0,0 +1,113 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class ESLintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + /** + * ESLint configuration file path. + * + * @var string|null Path to eslintrc. Null to autodetect. + */ + public $configFile = null; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If jshint.js could not be run + */ + public function process(File $phpcsFile, $stackPtr) + { + $eslintPath = Config::getExecutablePath('eslint'); + if ($eslintPath === null) { + return; + } + + $filename = $phpcsFile->getFilename(); + + $configFile = $this->configFile; + if (empty($configFile) === true) { + // Attempt to autodetect. + $candidates = glob('.eslintrc{.js,.yaml,.yml,.json}', GLOB_BRACE); + if (empty($candidates) === false) { + $configFile = $candidates[0]; + } + } + + $eslintOptions = ['--format json']; + if (empty($configFile) === false) { + $eslintOptions[] = '--config '.escapeshellarg($configFile); + } + + $cmd = Common::escapeshellcmd(escapeshellarg($eslintPath).' '.implode(' ', $eslintOptions).' '.escapeshellarg($filename)); + + // Execute! + exec($cmd, $stdout, $code); + + if ($code <= 0) { + // No errors, continue. + return ($phpcsFile->numTokens + 1); + } + + $data = json_decode(implode("\n", $stdout)); + if (json_last_error() !== JSON_ERROR_NONE) { + // Ignore any errors. + return ($phpcsFile->numTokens + 1); + } + + // Data is a list of files, but we only pass a single one. + $messages = $data[0]->messages; + foreach ($messages as $error) { + $message = 'eslint says: '.$error->message; + if (empty($error->fatal) === false || $error->severity === 2) { + $phpcsFile->addErrorOnLine($message, $error->line, 'ExternalTool'); + } else { + $phpcsFile->addWarningOnLine($message, $error->line, 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/JSHintSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/JSHintSniff.php new file mode 100644 index 00000000..06de3594 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/JSHintSniff.php @@ -0,0 +1,95 @@ + + * @author Alexander Wei§ + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class JSHintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If jshint.js could not be run + */ + public function process(File $phpcsFile, $stackPtr) + { + $rhinoPath = Config::getExecutablePath('rhino'); + $jshintPath = Config::getExecutablePath('jshint'); + if ($rhinoPath === null && $jshintPath === null) { + return; + } + + $fileName = $phpcsFile->getFilename(); + $jshintPath = Common::escapeshellcmd($jshintPath); + + if ($rhinoPath !== null) { + $rhinoPath = Common::escapeshellcmd($rhinoPath); + $cmd = "$rhinoPath \"$jshintPath\" ".escapeshellarg($fileName); + exec($cmd, $output, $retval); + + $regex = '`^(?P.+)\(.+:(?P[0-9]+).*:[0-9]+\)$`'; + } else { + $cmd = "$jshintPath ".escapeshellarg($fileName); + exec($cmd, $output, $retval); + + $regex = '`^(.+?): line (?P[0-9]+), col [0-9]+, (?P.+)$`'; + } + + if (is_array($output) === true) { + foreach ($output as $finding) { + $matches = []; + $numMatches = preg_match($regex, $finding, $matches); + if ($numMatches === 0) { + continue; + } + + $line = (int) $matches['line']; + $message = 'jshint says: '.trim($matches['error']); + $phpcsFile->addWarningOnLine($message, $line, 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ByteOrderMarkSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ByteOrderMarkSniff.php new file mode 100644 index 00000000..cee8ecc5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ByteOrderMarkSniff.php @@ -0,0 +1,80 @@ + + * @author Greg Sherwood + * @copyright 2010-2014 mediaSELF Sp. z o.o. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ByteOrderMarkSniff implements Sniff +{ + + /** + * List of supported BOM definitions. + * + * Use encoding names as keys and hex BOM representations as values. + * + * @var array + */ + protected $bomDefinitions = [ + 'UTF-8' => 'efbbbf', + 'UTF-16 (BE)' => 'feff', + 'UTF-16 (LE)' => 'fffe', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INLINE_HTML]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // The BOM will be the very first token in the file. + if ($stackPtr !== 0) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + foreach ($this->bomDefinitions as $bomName => $expectedBomHex) { + $bomByteLength = (strlen($expectedBomHex) / 2); + $htmlBomHex = bin2hex(substr($tokens[$stackPtr]['content'], 0, $bomByteLength)); + if ($htmlBomHex === $expectedBomHex) { + $errorData = [$bomName]; + $error = 'File contains %s byte order mark, which may corrupt your application'; + $phpcsFile->addError($error, $stackPtr, 'Found', $errorData); + $phpcsFile->recordMetric($stackPtr, 'Using byte order mark', 'yes'); + return; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Using byte order mark', 'no'); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNewlineSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNewlineSniff.php new file mode 100644 index 00000000..d5375dc5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNewlineSniff.php @@ -0,0 +1,84 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EndFileNewlineSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + 'CSS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + // Skip to the end of the file. + $tokens = $phpcsFile->getTokens(); + $stackPtr = ($phpcsFile->numTokens - 1); + + if ($tokens[$stackPtr]['content'] === '') { + $stackPtr--; + } + + $eolCharLen = strlen($phpcsFile->eolChar); + $lastChars = substr($tokens[$stackPtr]['content'], ($eolCharLen * -1)); + if ($lastChars !== $phpcsFile->eolChar) { + $phpcsFile->recordMetric($stackPtr, 'Newline at EOF', 'no'); + + $error = 'File must end with a newline character'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotFound'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($stackPtr); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Newline at EOF', 'yes'); + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNoNewlineSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNoNewlineSniff.php new file mode 100644 index 00000000..41c9c749 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNoNewlineSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EndFileNoNewlineSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + 'CSS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + // Skip to the end of the file. + $tokens = $phpcsFile->getTokens(); + $stackPtr = ($phpcsFile->numTokens - 1); + + if ($tokens[$stackPtr]['content'] === '') { + --$stackPtr; + } + + $eolCharLen = strlen($phpcsFile->eolChar); + $lastChars = substr($tokens[$stackPtr]['content'], ($eolCharLen * -1)); + if ($lastChars === $phpcsFile->eolChar) { + $error = 'File must not end with a newline character'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = $stackPtr; $i > 0; $i--) { + $newContent = rtrim($tokens[$i]['content'], $phpcsFile->eolChar); + $phpcsFile->fixer->replaceToken($i, $newContent); + + if ($newContent !== '') { + break; + } + } + + $phpcsFile->fixer->endChangeset(); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ExecutableFileSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ExecutableFileSniff.php new file mode 100644 index 00000000..e1213d5f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ExecutableFileSniff.php @@ -0,0 +1,62 @@ + + * @copyright 2019 Matthew Peveler + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ExecutableFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $filename = $phpcsFile->getFilename(); + + if ($filename !== 'STDIN') { + $perms = fileperms($phpcsFile->getFilename()); + if (($perms & 0x0040) !== 0 || ($perms & 0x0008) !== 0 || ($perms & 0x0001) !== 0) { + $error = 'A PHP file should not be executable; found file permissions set to %s'; + $data = [substr(sprintf('%o', $perms), -4)]; + $phpcsFile->addError($error, 0, 'Executable', $data); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/InlineHTMLSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/InlineHTMLSniff.php new file mode 100644 index 00000000..eb01da87 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/InlineHTMLSniff.php @@ -0,0 +1,79 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class InlineHTMLSniff implements Sniff +{ + + /** + * List of supported BOM definitions. + * + * Use encoding names as keys and hex BOM representations as values. + * + * @var array + */ + protected $bomDefinitions = [ + 'UTF-8' => 'efbbbf', + 'UTF-16 (BE)' => 'feff', + 'UTF-16 (LE)' => 'fffe', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INLINE_HTML]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int|null + */ + public function process(File $phpcsFile, $stackPtr) + { + // Allow a byte-order mark. + $tokens = $phpcsFile->getTokens(); + foreach ($this->bomDefinitions as $bomName => $expectedBomHex) { + $bomByteLength = (strlen($expectedBomHex) / 2); + $htmlBomHex = bin2hex(substr($tokens[0]['content'], 0, $bomByteLength)); + if ($htmlBomHex === $expectedBomHex && strlen($tokens[0]['content']) === $bomByteLength) { + return; + } + } + + // Ignore shebang lines. + $tokens = $phpcsFile->getTokens(); + if (substr($tokens[$stackPtr]['content'], 0, 2) === '#!') { + return; + } + + $error = 'PHP files must only contain PHP code'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineEndingsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineEndingsSniff.php new file mode 100644 index 00000000..845e1bcf --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineEndingsSniff.php @@ -0,0 +1,148 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LineEndingsSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + 'CSS', + ]; + + /** + * The valid EOL character. + * + * @var string + */ + public $eolChar = '\n'; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $found = $phpcsFile->eolChar; + $found = str_replace("\n", '\n', $found); + $found = str_replace("\r", '\r', $found); + + $phpcsFile->recordMetric($stackPtr, 'EOL char', $found); + + if ($found === $this->eolChar) { + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + } + + // Check for single line files without an EOL. This is a very special + // case and the EOL char is set to \n when this happens. + if ($found === '\n') { + $tokens = $phpcsFile->getTokens(); + $lastToken = ($phpcsFile->numTokens - 1); + if ($tokens[$lastToken]['line'] === 1 + && $tokens[$lastToken]['content'] !== "\n" + ) { + return; + } + } + + $error = 'End of line character is invalid; expected "%s" but found "%s"'; + $expected = $this->eolChar; + $expected = str_replace("\n", '\n', $expected); + $expected = str_replace("\r", '\r', $expected); + $data = [ + $expected, + $found, + ]; + + // Errors are always reported on line 1, no matter where the first PHP tag is. + $fix = $phpcsFile->addFixableError($error, 0, 'InvalidEOLChar', $data); + + if ($fix === true) { + $tokens = $phpcsFile->getTokens(); + switch ($this->eolChar) { + case '\n': + $eolChar = "\n"; + break; + case '\r': + $eolChar = "\r"; + break; + case '\r\n': + $eolChar = "\r\n"; + break; + default: + $eolChar = $this->eolChar; + break; + } + + for ($i = 0; $i < $phpcsFile->numTokens; $i++) { + if (isset($tokens[($i + 1)]) === true + && $tokens[($i + 1)]['line'] <= $tokens[$i]['line'] + ) { + continue; + } + + // Token is the last on a line. + if (isset($tokens[$i]['orig_content']) === true) { + $tokenContent = $tokens[$i]['orig_content']; + } else { + $tokenContent = $tokens[$i]['content']; + } + + if ($tokenContent === '') { + // Special case for JS/CSS close tag. + continue; + } + + $newContent = rtrim($tokenContent, "\r\n"); + $newContent .= $eolChar; + if ($tokenContent !== $newContent) { + $phpcsFile->fixer->replaceToken($i, $newContent); + } + }//end for + }//end if + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineLengthSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineLengthSniff.php new file mode 100644 index 00000000..5aa45ea0 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineLengthSniff.php @@ -0,0 +1,201 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LineLengthSniff implements Sniff +{ + + /** + * The limit that the length of a line should not exceed. + * + * @var integer + */ + public $lineLimit = 80; + + /** + * The limit that the length of a line must not exceed. + * + * Set to zero (0) to disable. + * + * @var integer + */ + public $absoluteLineLimit = 100; + + /** + * Whether or not to ignore trailing comments. + * + * This has the effect of also ignoring all lines + * that only contain comments. + * + * @var boolean + */ + public $ignoreComments = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + for ($i = 1; $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['column'] === 1) { + $this->checkLineLength($phpcsFile, $tokens, $i); + } + } + + $this->checkLineLength($phpcsFile, $tokens, $i); + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + + /** + * Checks if a line is too long. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tokens The token stack. + * @param int $stackPtr The first token on the next line. + * + * @return void + */ + protected function checkLineLength($phpcsFile, $tokens, $stackPtr) + { + // The passed token is the first on the line. + $stackPtr--; + + if ($tokens[$stackPtr]['column'] === 1 + && $tokens[$stackPtr]['length'] === 0 + ) { + // Blank line. + return; + } + + if ($tokens[$stackPtr]['column'] !== 1 + && $tokens[$stackPtr]['content'] === $phpcsFile->eolChar + ) { + $stackPtr--; + } + + $onlyComment = false; + if (isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true) { + $prevNonWhiteSpace = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$stackPtr]['line'] !== $tokens[$prevNonWhiteSpace]['line']) { + $onlyComment = true; + } + } + + if ($onlyComment === true + && isset(Tokens::$phpcsCommentTokens[$tokens[$stackPtr]['code']]) === true + ) { + // Ignore PHPCS annotation comments that are on a line by themselves. + return; + } + + $lineLength = ($tokens[$stackPtr]['column'] + $tokens[$stackPtr]['length'] - 1); + + if ($this->ignoreComments === true + && isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true + ) { + // Trailing comments are being ignored in line length calculations. + if ($onlyComment === true) { + // The comment is the only thing on the line, so no need to check length. + return; + } + + $lineLength -= $tokens[$stackPtr]['length']; + } + + // Record metrics for common line length groupings. + if ($lineLength <= 80) { + $phpcsFile->recordMetric($stackPtr, 'Line length', '80 or less'); + } else if ($lineLength <= 120) { + $phpcsFile->recordMetric($stackPtr, 'Line length', '81-120'); + } else if ($lineLength <= 150) { + $phpcsFile->recordMetric($stackPtr, 'Line length', '121-150'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Line length', '151 or more'); + } + + if ($onlyComment === true) { + // If this is a long comment, check if it can be broken up onto multiple lines. + // Some comments contain unbreakable strings like URLs and so it makes sense + // to ignore the line length in these cases if the URL would be longer than the max + // line length once you indent it to the correct level. + if ($lineLength > $this->lineLimit) { + $oldLength = strlen($tokens[$stackPtr]['content']); + $newLength = strlen(ltrim($tokens[$stackPtr]['content'], "/#\t ")); + $indent = (($tokens[$stackPtr]['column'] - 1) + ($oldLength - $newLength)); + + $nonBreakingLength = $tokens[$stackPtr]['length']; + + $space = strrpos($tokens[$stackPtr]['content'], ' '); + if ($space !== false) { + $nonBreakingLength -= ($space + 1); + } + + if (($nonBreakingLength + $indent) > $this->lineLimit) { + return; + } + } + }//end if + + if ($this->absoluteLineLimit > 0 + && $lineLength > $this->absoluteLineLimit + ) { + $data = [ + $this->absoluteLineLimit, + $lineLength, + ]; + + $error = 'Line exceeds maximum limit of %s characters; contains %s characters'; + $phpcsFile->addError($error, $stackPtr, 'MaxExceeded', $data); + } else if ($lineLength > $this->lineLimit) { + $data = [ + $this->lineLimit, + $lineLength, + ]; + + $warning = 'Line exceeds %s characters; contains %s characters'; + $phpcsFile->addWarning($warning, $stackPtr, 'TooLong', $data); + } + + }//end checkLineLength() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LowercasedFilenameSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LowercasedFilenameSniff.php new file mode 100644 index 00000000..a9fd4c5d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LowercasedFilenameSniff.php @@ -0,0 +1,70 @@ + + * @copyright 2010-2014 Andy Grunwald + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LowercasedFilenameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $filename = $phpcsFile->getFilename(); + if ($filename === 'STDIN') { + return; + } + + $filename = basename($filename); + $lowercaseFilename = strtolower($filename); + if ($filename !== $lowercaseFilename) { + $data = [ + $filename, + $lowercaseFilename, + ]; + $error = 'Filename "%s" doesn\'t match the expected filename "%s"'; + $phpcsFile->addError($error, $stackPtr, 'NotFound', $data); + $phpcsFile->recordMetric($stackPtr, 'Lowercase filename', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Lowercase filename', 'yes'); + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneClassPerFileSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneClassPerFileSniff.php new file mode 100644 index 00000000..52d5d84c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneClassPerFileSniff.php @@ -0,0 +1,57 @@ + + * @copyright 2010-2014 Andy Grunwald + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OneClassPerFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $start = ($tokens[$stackPtr]['scope_closer'] + 1); + } + + $nextClass = $phpcsFile->findNext($this->register(), $start); + if ($nextClass !== false) { + $error = 'Only one class is allowed in a file'; + $phpcsFile->addError($error, $nextClass, 'MultipleFound'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneInterfacePerFileSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneInterfacePerFileSniff.php new file mode 100644 index 00000000..9a6f5bcc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneInterfacePerFileSniff.php @@ -0,0 +1,57 @@ + + * @copyright 2010-2014 Andy Grunwald + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OneInterfacePerFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INTERFACE]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $start = ($tokens[$stackPtr]['scope_closer'] + 1); + } + + $nextInterface = $phpcsFile->findNext($this->register(), $start); + if ($nextInterface !== false) { + $error = 'Only one interface is allowed in a file'; + $phpcsFile->addError($error, $nextInterface, 'MultipleFound'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneObjectStructurePerFileSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneObjectStructurePerFileSniff.php new file mode 100644 index 00000000..4d417e06 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneObjectStructurePerFileSniff.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OneObjectStructurePerFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $start = ($tokens[$stackPtr]['scope_closer'] + 1); + } + + $nextClass = $phpcsFile->findNext($this->register(), $start); + if ($nextClass !== false) { + $error = 'Only one object structure is allowed in a file'; + $phpcsFile->addError($error, $nextClass, 'MultipleFound'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneTraitPerFileSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneTraitPerFileSniff.php new file mode 100644 index 00000000..7ae523f7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneTraitPerFileSniff.php @@ -0,0 +1,57 @@ + + * @copyright 2010-2014 Alexander Obuhovich + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OneTraitPerFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_TRAIT]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $start = ($tokens[$stackPtr]['scope_closer'] + 1); + } + + $nextClass = $phpcsFile->findNext($this->register(), $start); + if ($nextClass !== false) { + $error = 'Only one trait is allowed in a file'; + $phpcsFile->addError($error, $nextClass, 'MultipleFound'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/DisallowMultipleStatementsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/DisallowMultipleStatementsSniff.php new file mode 100644 index 00000000..6f9ff9f9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/DisallowMultipleStatementsSniff.php @@ -0,0 +1,105 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowMultipleStatementsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_SEMICOLON]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $fixable = true; + $prev = $stackPtr; + + do { + $prev = $phpcsFile->findPrevious([T_SEMICOLON, T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO, T_PHPCS_IGNORE], ($prev - 1)); + if ($prev === false + || $tokens[$prev]['code'] === T_OPEN_TAG + || $tokens[$prev]['code'] === T_OPEN_TAG_WITH_ECHO + ) { + $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'no'); + return; + } + + if ($tokens[$prev]['code'] === T_PHPCS_IGNORE) { + $fixable = false; + } + } while ($tokens[$prev]['code'] === T_PHPCS_IGNORE); + + // Ignore multiple statements in a FOR condition. + foreach ([$stackPtr, $prev] as $checkToken) { + if (isset($tokens[$checkToken]['nested_parenthesis']) === true) { + foreach ($tokens[$checkToken]['nested_parenthesis'] as $bracket) { + if (isset($tokens[$bracket]['parenthesis_owner']) === false) { + // Probably a closure sitting inside a function call. + continue; + } + + $owner = $tokens[$bracket]['parenthesis_owner']; + if ($tokens[$owner]['code'] === T_FOR) { + return; + } + } + } + } + + if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) { + $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'yes'); + + $error = 'Each PHP statement must be on a line by itself'; + $code = 'SameLine'; + if ($fixable === false) { + $phpcsFile->addError($error, $stackPtr, $code); + return; + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, $code); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($prev); + if ($tokens[($prev + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($prev + 1), ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'no'); + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php new file mode 100644 index 00000000..802e5944 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php @@ -0,0 +1,426 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class MultipleStatementAlignmentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * If true, an error will be thrown; otherwise a warning. + * + * @var boolean + */ + public $error = false; + + /** + * The maximum amount of padding before the alignment is ignored. + * + * If the amount of padding required to align this assignment with the + * surrounding assignments exceeds this number, the assignment will be + * ignored and no errors or warnings will be thrown. + * + * @var integer + */ + public $maxPadding = 1000; + + /** + * Controls which side of the assignment token is used for alignment. + * + * @var boolean + */ + public $alignAtEnd = true; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $tokens = Tokens::$assignmentTokens; + unset($tokens[T_DOUBLE_ARROW]); + return $tokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $lastAssign = $this->checkAlignment($phpcsFile, $stackPtr); + return ($lastAssign + 1); + + }//end process() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $end The token where checking should end. + * If NULL, the entire file will be checked. + * + * @return int + */ + public function checkAlignment($phpcsFile, $stackPtr, $end=null) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore assignments used in a condition, like an IF or FOR or closure param defaults. + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + // If the parenthesis is on the same line as the assignment, + // then it should be ignored as it is specifically being grouped. + $parens = $tokens[$stackPtr]['nested_parenthesis']; + $lastParen = array_pop($parens); + if ($tokens[$lastParen]['line'] === $tokens[$stackPtr]['line']) { + return $stackPtr; + } + + foreach ($tokens[$stackPtr]['nested_parenthesis'] as $start => $end) { + if (isset($tokens[$start]['parenthesis_owner']) === true) { + return $stackPtr; + } + } + } + + $assignments = []; + $prevAssign = null; + $lastLine = $tokens[$stackPtr]['line']; + $maxPadding = null; + $stopped = null; + $lastCode = $stackPtr; + $lastSemi = null; + $arrayEnd = null; + + if ($end === null) { + $end = $phpcsFile->numTokens; + } + + $find = Tokens::$assignmentTokens; + unset($find[T_DOUBLE_ARROW]); + + $scopes = Tokens::$scopeOpeners; + unset($scopes[T_CLOSURE]); + unset($scopes[T_ANON_CLASS]); + unset($scopes[T_OBJECT]); + + for ($assign = $stackPtr; $assign < $end; $assign++) { + if ($tokens[$assign]['level'] < $tokens[$stackPtr]['level']) { + // Statement is in a different context, so the block is over. + break; + } + + if (isset($tokens[$assign]['scope_opener']) === true + && $tokens[$assign]['level'] === $tokens[$stackPtr]['level'] + ) { + if (isset($scopes[$tokens[$assign]['code']]) === true) { + // This type of scope indicates that the assignment block is over. + break; + } + + // Skip over the scope block because it is seen as part of the assignment block, + // but also process any assignment blocks that are inside as well. + $nextAssign = $phpcsFile->findNext($find, ($assign + 1), ($tokens[$assign]['scope_closer'] - 1)); + if ($nextAssign !== false) { + $assign = $this->checkAlignment($phpcsFile, $nextAssign); + } else { + $assign = $tokens[$assign]['scope_closer']; + } + + $lastCode = $assign; + continue; + } + + if ($assign === $arrayEnd) { + $arrayEnd = null; + } + + if (isset($find[$tokens[$assign]['code']]) === false) { + // A blank line indicates that the assignment block has ended. + if (isset(Tokens::$emptyTokens[$tokens[$assign]['code']]) === false + && ($tokens[$assign]['line'] - $tokens[$lastCode]['line']) > 1 + && $tokens[$assign]['level'] === $tokens[$stackPtr]['level'] + && $arrayEnd === null + ) { + break; + } + + if ($tokens[$assign]['code'] === T_CLOSE_TAG) { + // Breaking out of PHP ends the assignment block. + break; + } + + if ($tokens[$assign]['code'] === T_OPEN_SHORT_ARRAY + && isset($tokens[$assign]['bracket_closer']) === true + ) { + $arrayEnd = $tokens[$assign]['bracket_closer']; + } + + if ($tokens[$assign]['code'] === T_ARRAY + && isset($tokens[$assign]['parenthesis_opener']) === true + && isset($tokens[$tokens[$assign]['parenthesis_opener']]['parenthesis_closer']) === true + ) { + $arrayEnd = $tokens[$tokens[$assign]['parenthesis_opener']]['parenthesis_closer']; + } + + if (isset(Tokens::$emptyTokens[$tokens[$assign]['code']]) === false) { + $lastCode = $assign; + + if ($tokens[$assign]['code'] === T_SEMICOLON) { + if ($tokens[$assign]['conditions'] === $tokens[$stackPtr]['conditions']) { + if ($lastSemi !== null && $prevAssign !== null && $lastSemi > $prevAssign) { + // This statement did not have an assignment operator in it. + break; + } else { + $lastSemi = $assign; + } + } else if ($tokens[$assign]['level'] < $tokens[$stackPtr]['level']) { + // Statement is in a different context, so the block is over. + break; + } + } + }//end if + + continue; + } else if ($assign !== $stackPtr && $tokens[$assign]['line'] === $lastLine) { + // Skip multiple assignments on the same line. We only need to + // try and align the first assignment. + continue; + }//end if + + if ($assign !== $stackPtr) { + if ($tokens[$assign]['level'] > $tokens[$stackPtr]['level']) { + // Has to be nested inside the same conditions as the first assignment. + // We've gone one level down, so process this new block. + $assign = $this->checkAlignment($phpcsFile, $assign); + $lastCode = $assign; + continue; + } else if ($tokens[$assign]['level'] < $tokens[$stackPtr]['level']) { + // We've gone one level up, so the block we are processing is done. + break; + } else if ($arrayEnd !== null) { + // Assignments inside arrays are not part of + // the original block, so process this new block. + $assign = ($this->checkAlignment($phpcsFile, $assign, $arrayEnd) - 1); + $arrayEnd = null; + $lastCode = $assign; + continue; + } + + // Make sure it is not assigned inside a condition (eg. IF, FOR). + if (isset($tokens[$assign]['nested_parenthesis']) === true) { + // If the parenthesis is on the same line as the assignment, + // then it should be ignored as it is specifically being grouped. + $parens = $tokens[$assign]['nested_parenthesis']; + $lastParen = array_pop($parens); + if ($tokens[$lastParen]['line'] === $tokens[$assign]['line']) { + break; + } + + foreach ($tokens[$assign]['nested_parenthesis'] as $start => $end) { + if (isset($tokens[$start]['parenthesis_owner']) === true) { + break(2); + } + } + } + }//end if + + $var = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($assign - 1), + null, + true + ); + + // Make sure we wouldn't break our max padding length if we + // aligned with this statement, or they wouldn't break the max + // padding length if they aligned with us. + $varEnd = $tokens[($var + 1)]['column']; + $assignLen = $tokens[$assign]['length']; + if ($this->alignAtEnd !== true) { + $assignLen = 1; + } + + if ($assign !== $stackPtr) { + if ($prevAssign === null) { + // Processing an inner block but no assignments found. + break; + } + + if (($varEnd + 1) > $assignments[$prevAssign]['assign_col']) { + $padding = 1; + $assignColumn = ($varEnd + 1); + } else { + $padding = ($assignments[$prevAssign]['assign_col'] - $varEnd + $assignments[$prevAssign]['assign_len'] - $assignLen); + if ($padding <= 0) { + $padding = 1; + } + + if ($padding > $this->maxPadding) { + $stopped = $assign; + break; + } + + $assignColumn = ($varEnd + $padding); + }//end if + + if (($assignColumn + $assignLen) > ($assignments[$maxPadding]['assign_col'] + $assignments[$maxPadding]['assign_len'])) { + $newPadding = ($varEnd - $assignments[$maxPadding]['var_end'] + $assignLen - $assignments[$maxPadding]['assign_len'] + 1); + if ($newPadding > $this->maxPadding) { + $stopped = $assign; + break; + } else { + // New alignment settings for previous assignments. + foreach ($assignments as $i => $data) { + if ($i === $assign) { + break; + } + + $newPadding = ($varEnd - $data['var_end'] + $assignLen - $data['assign_len'] + 1); + $assignments[$i]['expected'] = $newPadding; + $assignments[$i]['assign_col'] = ($data['var_end'] + $newPadding); + } + + $padding = 1; + $assignColumn = ($varEnd + 1); + } + } else if ($padding > $assignments[$maxPadding]['expected']) { + $maxPadding = $assign; + }//end if + } else { + $padding = 1; + $assignColumn = ($varEnd + 1); + $maxPadding = $assign; + }//end if + + $found = 0; + if ($tokens[($var + 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($var + 1)]['length']; + if ($found === 0) { + // This means a newline was found. + $found = 1; + } + } + + $assignments[$assign] = [ + 'var_end' => $varEnd, + 'assign_len' => $assignLen, + 'assign_col' => $assignColumn, + 'expected' => $padding, + 'found' => $found, + ]; + + $lastLine = $tokens[$assign]['line']; + $prevAssign = $assign; + }//end for + + if (empty($assignments) === true) { + return $stackPtr; + } + + $numAssignments = count($assignments); + + $errorGenerated = false; + foreach ($assignments as $assignment => $data) { + if ($data['found'] === $data['expected']) { + continue; + } + + $expectedText = $data['expected'].' space'; + if ($data['expected'] !== 1) { + $expectedText .= 's'; + } + + if ($data['found'] === null) { + $foundText = 'a new line'; + } else { + $foundText = $data['found'].' space'; + if ($data['found'] !== 1) { + $foundText .= 's'; + } + } + + if ($numAssignments === 1) { + $type = 'Incorrect'; + $error = 'Equals sign not aligned correctly; expected %s but found %s'; + } else { + $type = 'NotSame'; + $error = 'Equals sign not aligned with surrounding assignments; expected %s but found %s'; + } + + $errorData = [ + $expectedText, + $foundText, + ]; + + if ($this->error === true) { + $fix = $phpcsFile->addFixableError($error, $assignment, $type, $errorData); + } else { + $fix = $phpcsFile->addFixableWarning($error, $assignment, $type.'Warning', $errorData); + } + + $errorGenerated = true; + + if ($fix === true && $data['found'] !== null) { + $newContent = str_repeat(' ', $data['expected']); + if ($data['found'] === 0) { + $phpcsFile->fixer->addContentBefore($assignment, $newContent); + } else { + $phpcsFile->fixer->replaceToken(($assignment - 1), $newContent); + } + } + }//end foreach + + if ($numAssignments > 1) { + if ($errorGenerated === true) { + $phpcsFile->recordMetric($stackPtr, 'Adjacent assignments aligned', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Adjacent assignments aligned', 'yes'); + } + } + + if ($stopped !== null) { + return $this->checkAlignment($phpcsFile, $stopped); + } else { + return $assign; + } + + }//end checkAlignment() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/NoSpaceAfterCastSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/NoSpaceAfterCastSniff.php new file mode 100644 index 00000000..f6a37daf --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/NoSpaceAfterCastSniff.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.4.0 Use the Generic.Formatting.SpaceAfterCast sniff with + * the $spacing property set to 0 instead. + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class NoSpaceAfterCastSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$castTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + return; + } + + $error = 'A cast statement must not be followed by a space'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceFound'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterCastSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterCastSniff.php new file mode 100644 index 00000000..f19489e8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterCastSniff.php @@ -0,0 +1,153 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SpaceAfterCastSniff implements Sniff +{ + + /** + * The number of spaces desired after a cast token. + * + * @var integer + */ + public $spacing = 1; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$castTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $this->spacing = (int) $this->spacing; + + if ($tokens[$stackPtr]['code'] === T_BINARY_CAST + && $tokens[$stackPtr]['content'] === 'b' + ) { + // You can't replace a space after this type of binary casting. + return; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + if ($this->ignoreNewlines === true + && $tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line'] + ) { + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', 'newline'); + return; + } + + if ($this->spacing === 0 && $nextNonEmpty === ($stackPtr + 1)) { + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', 0); + return; + } + + $nextNonWhitespace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($nextNonEmpty !== $nextNonWhitespace) { + $error = 'Expected %s space(s) after cast statement; comment found'; + $data = [$this->spacing]; + $phpcsFile->addError($error, $stackPtr, 'CommentFound', $data); + + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', $tokens[($stackPtr + 1)]['length']); + } else { + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', 0); + } + + return; + } + + $found = 0; + if ($tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line']) { + $found = 'newline'; + } else if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($stackPtr + 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', $found); + + if ($found === $this->spacing) { + return; + } + + $error = 'Expected %s space(s) after cast statement; %s found'; + $data = [ + $this->spacing, + $found, + ]; + + $errorCode = 'TooMuchSpace'; + if ($this->spacing !== 0) { + if ($found === 0) { + $errorCode = 'NoSpace'; + } else if ($found !== 'newline' && $found < $this->spacing) { + $errorCode = 'TooLittleSpace'; + } + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode, $data); + + if ($fix === true) { + $padding = str_repeat(' ', $this->spacing); + if ($found === 0) { + $phpcsFile->fixer->addContent($stackPtr, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + $start = ($stackPtr + 1); + + if ($this->spacing > 0) { + $phpcsFile->fixer->replaceToken($start, $padding); + ++$start; + } + + for ($i = $start; $i < $nextNonWhitespace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterNotSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterNotSniff.php new file mode 100644 index 00000000..b74ca80e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterNotSniff.php @@ -0,0 +1,135 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SpaceAfterNotSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces desired after the NOT operator. + * + * @var integer + */ + public $spacing = 1; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_BOOLEAN_NOT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $this->spacing = (int) $this->spacing; + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + if ($this->ignoreNewlines === true + && $tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line'] + ) { + return; + } + + if ($this->spacing === 0 && $nextNonEmpty === ($stackPtr + 1)) { + return; + } + + $nextNonWhitespace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($nextNonEmpty !== $nextNonWhitespace) { + $error = 'Expected %s space(s) after NOT operator; comment found'; + $data = [$this->spacing]; + $phpcsFile->addError($error, $stackPtr, 'CommentFound', $data); + return; + } + + $found = 0; + if ($tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line']) { + $found = 'newline'; + } else if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($stackPtr + 1)]['length']; + } + + if ($found === $this->spacing) { + return; + } + + $error = 'Expected %s space(s) after NOT operator; %s found'; + $data = [ + $this->spacing, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Incorrect', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->spacing); + if ($found === 0) { + $phpcsFile->fixer->addContent($stackPtr, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + $start = ($stackPtr + 1); + + if ($this->spacing > 0) { + $phpcsFile->fixer->replaceToken($start, $padding); + ++$start; + } + + for ($i = $start; $i < $nextNonWhitespace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceBeforeCastSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceBeforeCastSniff.php new file mode 100644 index 00000000..a4f85aeb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceBeforeCastSniff.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SpaceBeforeCastSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$castTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['column'] === 1) { + return; + } + + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $error = 'A cast statement must be preceded by a single space'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpace'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing before cast statement', 0); + return; + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing before cast statement', $tokens[($stackPtr - 1)]['length']); + + if ($tokens[($stackPtr - 1)]['column'] !== 1 && $tokens[($stackPtr - 1)]['length'] !== 1) { + $error = 'A cast statement must be preceded by a single space'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'TooMuchSpace'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/CallTimePassByReferenceSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/CallTimePassByReferenceSniff.php new file mode 100644 index 00000000..425748ce --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/CallTimePassByReferenceSniff.php @@ -0,0 +1,141 @@ + + * @copyright 2009-2014 Florian Grandel + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class CallTimePassByReferenceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_STRING, + T_VARIABLE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $findTokens = Tokens::$emptyTokens; + $findTokens[] = T_BITWISE_AND; + + $prev = $phpcsFile->findPrevious($findTokens, ($stackPtr - 1), null, true); + + // Skip tokens that are the names of functions or classes + // within their definitions. For example: function myFunction... + // "myFunction" is T_STRING but we should skip because it is not a + // function or method *call*. + $prevCode = $tokens[$prev]['code']; + if ($prevCode === T_FUNCTION || $prevCode === T_CLASS) { + return; + } + + // If the next non-whitespace token after the function or method call + // is not an opening parenthesis then it cant really be a *call*. + $functionName = $stackPtr; + $openBracket = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($functionName + 1), + null, + true + ); + + if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + if (isset($tokens[$openBracket]['parenthesis_closer']) === false) { + return; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + $nextSeparator = $openBracket; + $find = [ + T_VARIABLE, + T_OPEN_SHORT_ARRAY, + ]; + + while (($nextSeparator = $phpcsFile->findNext($find, ($nextSeparator + 1), $closeBracket)) !== false) { + if (isset($tokens[$nextSeparator]['nested_parenthesis']) === false) { + continue; + } + + if ($tokens[$nextSeparator]['code'] === T_OPEN_SHORT_ARRAY) { + $nextSeparator = $tokens[$nextSeparator]['bracket_closer']; + continue; + } + + // Make sure the variable belongs directly to this function call + // and is not inside a nested function call or array. + $brackets = $tokens[$nextSeparator]['nested_parenthesis']; + $lastBracket = array_pop($brackets); + if ($lastBracket !== $closeBracket) { + continue; + } + + $tokenBefore = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($nextSeparator - 1), + null, + true + ); + + if ($tokens[$tokenBefore]['code'] === T_BITWISE_AND) { + if ($phpcsFile->isReference($tokenBefore) === false) { + continue; + } + + // We also want to ignore references used in assignment + // operations passed as function arguments, but isReference() + // sees them as valid references (which they are). + $tokenBefore = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($tokenBefore - 1), + null, + true + ); + + if (isset(Tokens::$assignmentTokens[$tokens[$tokenBefore]['code']]) === true) { + continue; + } + + // T_BITWISE_AND represents a pass-by-reference. + $error = 'Call-time pass-by-reference calls are prohibited'; + $phpcsFile->addError($error, $tokenBefore, 'NotAllowed'); + }//end if + }//end while + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php new file mode 100644 index 00000000..ca922381 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php @@ -0,0 +1,185 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCallArgumentSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return[ + T_STRING, + T_ISSET, + T_UNSET, + T_SELF, + T_STATIC, + T_VARIABLE, + T_CLOSE_CURLY_BRACKET, + T_CLOSE_PARENTHESIS, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Skip tokens that are the names of functions or classes + // within their definitions. For example: + // function myFunction... + // "myFunction" is T_STRING but we should skip because it is not a + // function or method *call*. + $functionName = $stackPtr; + $ignoreTokens = Tokens::$emptyTokens; + $ignoreTokens[] = T_BITWISE_AND; + $functionKeyword = $phpcsFile->findPrevious($ignoreTokens, ($stackPtr - 1), null, true); + if ($tokens[$functionKeyword]['code'] === T_FUNCTION || $tokens[$functionKeyword]['code'] === T_CLASS) { + return; + } + + if ($tokens[$stackPtr]['code'] === T_CLOSE_CURLY_BRACKET + && isset($tokens[$stackPtr]['scope_condition']) === true + ) { + // Not a function call. + return; + } + + // If the next non-whitespace token after the function or method call + // is not an opening parenthesis then it can't really be a *call*. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($functionName + 1), null, true); + if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + if (isset($tokens[$openBracket]['parenthesis_closer']) === false) { + return; + } + + $this->checkSpacing($phpcsFile, $stackPtr, $openBracket); + + }//end process() + + + /** + * Checks the spacing around commas. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * + * @return void + */ + public function checkSpacing(File $phpcsFile, $stackPtr, $openBracket) + { + $tokens = $phpcsFile->getTokens(); + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + $nextSeparator = $openBracket; + + $find = [ + T_COMMA, + T_CLOSURE, + T_ANON_CLASS, + T_OPEN_SHORT_ARRAY, + ]; + + while (($nextSeparator = $phpcsFile->findNext($find, ($nextSeparator + 1), $closeBracket)) !== false) { + if ($tokens[$nextSeparator]['code'] === T_CLOSURE + || $tokens[$nextSeparator]['code'] === T_ANON_CLASS + ) { + // Skip closures. + $nextSeparator = $tokens[$nextSeparator]['scope_closer']; + continue; + } else if ($tokens[$nextSeparator]['code'] === T_OPEN_SHORT_ARRAY) { + // Skips arrays using short notation. + $nextSeparator = $tokens[$nextSeparator]['bracket_closer']; + continue; + } + + // Make sure the comma or variable belongs directly to this function call, + // and is not inside a nested function call or array. + $brackets = $tokens[$nextSeparator]['nested_parenthesis']; + $lastBracket = array_pop($brackets); + if ($lastBracket !== $closeBracket) { + continue; + } + + if ($tokens[$nextSeparator]['code'] === T_COMMA) { + if ($tokens[($nextSeparator - 1)]['code'] === T_WHITESPACE) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($nextSeparator - 2), null, true); + if (isset(Tokens::$heredocTokens[$tokens[$prev]['code']]) === false) { + $error = 'Space found before comma in argument list'; + $fix = $phpcsFile->addFixableError($error, $nextSeparator, 'SpaceBeforeComma'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + if ($tokens[$prev]['line'] !== $tokens[$nextSeparator]['line']) { + $phpcsFile->fixer->addContent($prev, ','); + $phpcsFile->fixer->replaceToken($nextSeparator, ''); + } else { + $phpcsFile->fixer->replaceToken(($nextSeparator - 1), ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + if ($tokens[($nextSeparator + 1)]['code'] !== T_WHITESPACE) { + $error = 'No space found after comma in argument list'; + $fix = $phpcsFile->addFixableError($error, $nextSeparator, 'NoSpaceAfterComma'); + if ($fix === true) { + $phpcsFile->fixer->addContent($nextSeparator, ' '); + } + } else { + // If there is a newline in the space, then they must be formatting + // each argument on a newline, which is valid, so ignore it. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextSeparator + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$nextSeparator]['line']) { + $space = $tokens[($nextSeparator + 1)]['length']; + if ($space > 1) { + $error = 'Expected 1 space after comma in argument list; %s found'; + $data = [$space]; + $fix = $phpcsFile->addFixableError($error, $nextSeparator, 'TooMuchSpaceAfterComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextSeparator + 1), ' '); + } + } + } + }//end if + }//end if + }//end while + + }//end checkSpacing() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceBsdAllmanSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceBsdAllmanSniff.php new file mode 100644 index 00000000..ff19526a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceBsdAllmanSniff.php @@ -0,0 +1,227 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OpeningFunctionBraceBsdAllmanSniff implements Sniff +{ + + /** + * Should this sniff check function braces? + * + * @var boolean + */ + public $checkFunctions = true; + + /** + * Should this sniff check closure braces? + * + * @var boolean + */ + public $checkClosures = false; + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + if (($tokens[$stackPtr]['code'] === T_FUNCTION + && (bool) $this->checkFunctions === false) + || ($tokens[$stackPtr]['code'] === T_CLOSURE + && (bool) $this->checkClosures === false) + ) { + return; + } + + $openingBrace = $tokens[$stackPtr]['scope_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + } + } + + // Find the end of the function declaration. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($openingBrace - 1), $closeBracket, true); + + $functionLine = $tokens[$prev]['line']; + $braceLine = $tokens[$openingBrace]['line']; + + $lineDifference = ($braceLine - $functionLine); + + $metricType = 'Function'; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $metricType = 'Closure'; + } + + if ($lineDifference === 0) { + $error = 'Opening brace should be on a new line'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceOnSameLine'); + if ($fix === true) { + $hasTrailingAnnotation = false; + for ($nextLine = ($openingBrace + 1); $nextLine < $phpcsFile->numTokens; $nextLine++) { + if ($tokens[$openingBrace]['line'] !== $tokens[$nextLine]['line']) { + break; + } + + if (isset(Tokens::$phpcsCommentTokens[$tokens[$nextLine]['code']]) === true) { + $hasTrailingAnnotation = true; + } + } + + $phpcsFile->fixer->beginChangeset(); + $indent = $phpcsFile->findFirstOnLine([], $openingBrace); + + if ($hasTrailingAnnotation === false || $nextLine === false) { + if ($tokens[$indent]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->addContentBefore($openingBrace, $tokens[$indent]['content']); + } + + if ($tokens[($openingBrace - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($openingBrace - 1), ''); + } + + $phpcsFile->fixer->addNewlineBefore($openingBrace); + } else { + $phpcsFile->fixer->replaceToken($openingBrace, ''); + $phpcsFile->fixer->addNewlineBefore($nextLine); + $phpcsFile->fixer->addContentBefore($nextLine, '{'); + + if ($tokens[$indent]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->addContentBefore($nextLine, $tokens[$indent]['content']); + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + + $phpcsFile->recordMetric($stackPtr, "$metricType opening brace placement", 'same line'); + } else if ($lineDifference > 1) { + $error = 'Opening brace should be on the line after the declaration; found %s blank line(s)'; + $data = [($lineDifference - 1)]; + + $prevNonWs = $phpcsFile->findPrevious(T_WHITESPACE, ($openingBrace - 1), $closeBracket, true); + if ($prevNonWs !== $prev) { + // There must be a comment between the end of the function declaration and the open brace. + // Report, but don't fix. + $phpcsFile->addError($error, $openingBrace, 'BraceSpacing', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceSpacing', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $openingBrace; $i > $prev; $i--) { + if ($tokens[$i]['line'] === $tokens[$openingBrace]['line']) { + if ($tokens[$i]['column'] === 1) { + $phpcsFile->fixer->addNewLineBefore($i); + } + + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + $ignore = Tokens::$phpcsCommentTokens; + $ignore[] = T_WHITESPACE; + $next = $phpcsFile->findNext($ignore, ($openingBrace + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openingBrace]['line']) { + if ($next === $tokens[$stackPtr]['scope_closer']) { + // Ignore empty functions. + return; + } + + $error = 'Opening brace must be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'ContentAfterBrace'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($openingBrace); + } + } + + // Only continue checking if the opening brace looks good. + if ($lineDifference !== 1) { + return; + } + + // We need to actually find the first piece of content on this line, + // as if this is a method with tokens before it (public, static etc) + // or an if with an else before it, then we need to start the scope + // checking from there, rather than the current token. + $lineStart = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + + // The opening brace is on the correct line, now it needs to be + // checked to be correctly indented. + $startColumn = $tokens[$lineStart]['column']; + $braceIndent = $tokens[$openingBrace]['column']; + + if ($braceIndent !== $startColumn) { + $expected = ($startColumn - 1); + $found = ($braceIndent - 1); + + $error = 'Opening brace indented incorrectly; expected %s spaces, found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceIndent', $data); + if ($fix === true) { + $indent = str_repeat(' ', $expected); + if ($found === 0) { + $phpcsFile->fixer->addContentBefore($openingBrace, $indent); + } else { + $phpcsFile->fixer->replaceToken(($openingBrace - 1), $indent); + } + } + }//end if + + $phpcsFile->recordMetric($stackPtr, "$metricType opening brace placement", 'new line'); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceKernighanRitchieSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceKernighanRitchieSniff.php new file mode 100644 index 00000000..62eafc12 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceKernighanRitchieSniff.php @@ -0,0 +1,184 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OpeningFunctionBraceKernighanRitchieSniff implements Sniff +{ + + /** + * Should this sniff check function braces? + * + * @var boolean + */ + public $checkFunctions = true; + + /** + * Should this sniff check closure braces? + * + * @var boolean + */ + public $checkClosures = false; + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return void + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + if (($tokens[$stackPtr]['code'] === T_FUNCTION + && (bool) $this->checkFunctions === false) + || ($tokens[$stackPtr]['code'] === T_CLOSURE + && (bool) $this->checkClosures === false) + ) { + return; + } + + $openingBrace = $tokens[$stackPtr]['scope_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + } + } + + // Find the end of the function declaration. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($openingBrace - 1), $closeBracket, true); + + $functionLine = $tokens[$prev]['line']; + $braceLine = $tokens[$openingBrace]['line']; + + $lineDifference = ($braceLine - $functionLine); + + $metricType = 'Function'; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $metricType = 'Closure'; + } + + if ($lineDifference > 0) { + $phpcsFile->recordMetric($stackPtr, "$metricType opening brace placement", 'new line'); + $error = 'Opening brace should be on the same line as the declaration'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceOnNewLine'); + if ($fix === true) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($openingBrace - 1), $closeBracket, true); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($prev, ' {'); + $phpcsFile->fixer->replaceToken($openingBrace, ''); + if ($tokens[($openingBrace + 1)]['code'] === T_WHITESPACE + && $tokens[($openingBrace + 2)]['line'] > $tokens[$openingBrace]['line'] + ) { + // Brace is followed by a new line, so remove it to ensure we don't + // leave behind a blank line at the top of the block. + $phpcsFile->fixer->replaceToken(($openingBrace + 1), ''); + + if ($tokens[($openingBrace - 1)]['code'] === T_WHITESPACE + && $tokens[($openingBrace - 1)]['line'] === $tokens[$openingBrace]['line'] + && $tokens[($openingBrace - 2)]['line'] < $tokens[$openingBrace]['line'] + ) { + // Brace is preceded by indent, so remove it to ensure we don't + // leave behind more indent than is required for the first line. + $phpcsFile->fixer->replaceToken(($openingBrace - 1), ''); + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + } else { + $phpcsFile->recordMetric($stackPtr, "$metricType opening brace placement", 'same line'); + }//end if + + $ignore = Tokens::$phpcsCommentTokens; + $ignore[] = T_WHITESPACE; + $next = $phpcsFile->findNext($ignore, ($openingBrace + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openingBrace]['line']) { + if ($next === $tokens[$stackPtr]['scope_closer'] + || $tokens[$next]['code'] === T_CLOSE_TAG + ) { + // Ignore empty functions. + return; + } + + $error = 'Opening brace must be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'ContentAfterBrace'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($openingBrace); + } + } + + // Only continue checking if the opening brace looks good. + if ($lineDifference > 0) { + return; + } + + // We are looking for tabs, even if they have been replaced, because + // we enforce a space here. + if (isset($tokens[($openingBrace - 1)]['orig_content']) === true) { + $spacing = $tokens[($openingBrace - 1)]['orig_content']; + } else { + $spacing = $tokens[($openingBrace - 1)]['content']; + } + + if ($tokens[($openingBrace - 1)]['code'] !== T_WHITESPACE) { + $length = 0; + } else if ($spacing === "\t") { + $length = '\t'; + } else { + $length = strlen($spacing); + } + + if ($length !== 1) { + $error = 'Expected 1 space before opening brace; found %s'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'SpaceBeforeBrace', $data); + if ($fix === true) { + if ($length === 0 || $length === '\t') { + $phpcsFile->fixer->addContentBefore($openingBrace, ' '); + } else { + $phpcsFile->fixer->replaceToken(($openingBrace - 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/CyclomaticComplexitySniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/CyclomaticComplexitySniff.php new file mode 100644 index 00000000..9bd0dff3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/CyclomaticComplexitySniff.php @@ -0,0 +1,117 @@ + + * @author Greg Sherwood + * @copyright 2007-2014 Mayflower GmbH + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class CyclomaticComplexitySniff implements Sniff +{ + + /** + * A complexity higher than this value will throw a warning. + * + * @var integer + */ + public $complexity = 10; + + /** + * A complexity higher than this value will throw an error. + * + * @var integer + */ + public $absoluteComplexity = 20; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore abstract methods. + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + // Detect start and end of this function definition. + $start = $tokens[$stackPtr]['scope_opener']; + $end = $tokens[$stackPtr]['scope_closer']; + + // Predicate nodes for PHP. + $find = [ + T_CASE => true, + T_DEFAULT => true, + T_CATCH => true, + T_IF => true, + T_FOR => true, + T_FOREACH => true, + T_WHILE => true, + T_ELSEIF => true, + T_INLINE_THEN => true, + T_COALESCE => true, + T_COALESCE_EQUAL => true, + T_MATCH_ARROW => true, + T_NULLSAFE_OBJECT_OPERATOR => true, + ]; + + $complexity = 1; + + // Iterate from start to end and count predicate nodes. + for ($i = ($start + 1); $i < $end; $i++) { + if (isset($find[$tokens[$i]['code']]) === true) { + $complexity++; + } + } + + if ($complexity > $this->absoluteComplexity) { + $error = 'Function\'s cyclomatic complexity (%s) exceeds allowed maximum of %s'; + $data = [ + $complexity, + $this->absoluteComplexity, + ]; + $phpcsFile->addError($error, $stackPtr, 'MaxExceeded', $data); + } else if ($complexity > $this->complexity) { + $warning = 'Function\'s cyclomatic complexity (%s) exceeds %s; consider refactoring the function'; + $data = [ + $complexity, + $this->complexity, + ]; + $phpcsFile->addWarning($warning, $stackPtr, 'TooHigh', $data); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/NestingLevelSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/NestingLevelSniff.php new file mode 100644 index 00000000..d001deda --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/NestingLevelSniff.php @@ -0,0 +1,100 @@ + + * @author Greg Sherwood + * @copyright 2007-2014 Mayflower GmbH + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class NestingLevelSniff implements Sniff +{ + + /** + * A nesting level higher than this value will throw a warning. + * + * @var integer + */ + public $nestingLevel = 5; + + /** + * A nesting level higher than this value will throw an error. + * + * @var integer + */ + public $absoluteNestingLevel = 10; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore abstract methods. + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + // Detect start and end of this function definition. + $start = $tokens[$stackPtr]['scope_opener']; + $end = $tokens[$stackPtr]['scope_closer']; + + $nestingLevel = 0; + + // Find the maximum nesting level of any token in the function. + for ($i = ($start + 1); $i < $end; $i++) { + $level = $tokens[$i]['level']; + if ($nestingLevel < $level) { + $nestingLevel = $level; + } + } + + // We subtract the nesting level of the function itself. + $nestingLevel = ($nestingLevel - $tokens[$stackPtr]['level'] - 1); + + if ($nestingLevel > $this->absoluteNestingLevel) { + $error = 'Function\'s nesting level (%s) exceeds allowed maximum of %s'; + $data = [ + $nestingLevel, + $this->absoluteNestingLevel, + ]; + $phpcsFile->addError($error, $stackPtr, 'MaxExceeded', $data); + } else if ($nestingLevel > $this->nestingLevel) { + $warning = 'Function\'s nesting level (%s) exceeds %s; consider refactoring the function'; + $data = [ + $nestingLevel, + $this->nestingLevel, + ]; + $phpcsFile->addWarning($warning, $stackPtr, 'TooHigh', $data); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/AbstractClassNamePrefixSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/AbstractClassNamePrefixSniff.php new file mode 100644 index 00000000..3e3af830 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/AbstractClassNamePrefixSniff.php @@ -0,0 +1,60 @@ + + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class AbstractClassNamePrefixSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($phpcsFile->getClassProperties($stackPtr)['is_abstract'] === false) { + // This class is not abstract so we don't need to check it. + return; + } + + $className = $phpcsFile->getDeclarationName($stackPtr); + if ($className === null) { + // We are not interested in anonymous classes. + return; + } + + $prefix = substr($className, 0, 8); + if (strtolower($prefix) !== 'abstract') { + $phpcsFile->addError('Abstract class names must be prefixed with "Abstract"; found "%s"', $stackPtr, 'Missing', [$className]); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.php new file mode 100644 index 00000000..b4511203 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.php @@ -0,0 +1,223 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Tokens; + +class CamelCapsFunctionNameSniff extends AbstractScopeSniff +{ + + /** + * A list of all PHP magic methods. + * + * @var array + */ + protected $magicMethods = [ + 'construct' => true, + 'destruct' => true, + 'call' => true, + 'callstatic' => true, + 'get' => true, + 'set' => true, + 'isset' => true, + 'unset' => true, + 'sleep' => true, + 'wakeup' => true, + 'serialize' => true, + 'unserialize' => true, + 'tostring' => true, + 'invoke' => true, + 'set_state' => true, + 'clone' => true, + 'debuginfo' => true, + ]; + + /** + * A list of all PHP non-magic methods starting with a double underscore. + * + * These come from PHP modules such as SOAPClient. + * + * @var array + */ + protected $methodsDoubleUnderscore = [ + 'dorequest' => true, + 'getcookies' => true, + 'getfunctions' => true, + 'getlastrequest' => true, + 'getlastrequestheaders' => true, + 'getlastresponse' => true, + 'getlastresponseheaders' => true, + 'gettypes' => true, + 'setcookie' => true, + 'setlocation' => true, + 'setsoapheaders' => true, + 'soapcall' => true, + ]; + + /** + * A list of all PHP magic functions. + * + * @var array + */ + protected $magicFunctions = ['autoload' => true]; + + /** + * If TRUE, the string must not have two capital letters next to each other. + * + * @var boolean + */ + public $strict = true; + + + /** + * Constructs a Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff. + */ + public function __construct() + { + parent::__construct(Tokens::$ooScopeTokens, [T_FUNCTION], true); + + }//end __construct() + + + /** + * Processes the tokens within the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * @param int $currScope The position of the current scope. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + $className = $phpcsFile->getDeclarationName($currScope); + if (isset($className) === false) { + $className = '[Anonymous Class]'; + } + + $errorData = [$className.'::'.$methodName]; + + $methodNameLc = strtolower($methodName); + $classNameLc = strtolower($className); + + // Is this a magic method. i.e., is prefixed with "__" ? + if (preg_match('|^__[^_]|', $methodName) !== 0) { + $magicPart = substr($methodNameLc, 2); + if (isset($this->magicMethods[$magicPart]) === true + || isset($this->methodsDoubleUnderscore[$magicPart]) === true + ) { + return; + } + + $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData); + } + + // PHP4 constructors are allowed to break our rules. + if ($methodNameLc === $classNameLc) { + return; + } + + // PHP4 destructors are allowed to break our rules. + if ($methodNameLc === '_'.$classNameLc) { + return; + } + + // Ignore first underscore in methods prefixed with "_". + $methodName = ltrim($methodName, '_'); + + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + if (Common::isCamelCaps($methodName, false, true, $this->strict) === false) { + if ($methodProps['scope_specified'] === true) { + $error = '%s method name "%s" is not in camel caps format'; + $data = [ + ucfirst($methodProps['scope']), + $errorData[0], + ]; + $phpcsFile->addError($error, $stackPtr, 'ScopeNotCamelCaps', $data); + } else { + $error = 'Method name "%s" is not in camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + } + + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'no'); + return; + } else { + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'yes'); + } + + }//end processTokenWithinScope() + + + /** + * Processes the tokens outside the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if ($functionName === null) { + // Ignore closures. + return; + } + + $errorData = [$functionName]; + + // Is this a magic function. i.e., it is prefixed with "__". + if (preg_match('|^__[^_]|', $functionName) !== 0) { + $magicPart = strtolower(substr($functionName, 2)); + if (isset($this->magicFunctions[$magicPart]) === true) { + return; + } + + $error = 'Function name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'FunctionDoubleUnderscore', $errorData); + } + + // Ignore first underscore in functions prefixed with "_". + $functionName = ltrim($functionName, '_'); + + if (Common::isCamelCaps($functionName, false, true, $this->strict) === false) { + $error = 'Function name "%s" is not in camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + $phpcsFile->recordMetric($stackPtr, 'CamelCase function name', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'yes'); + } + + }//end processTokenOutsideScope() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.php new file mode 100644 index 00000000..a4196063 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.php @@ -0,0 +1,163 @@ + + * @author Leif Wickland + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; + +class ConstructorNameSniff extends AbstractScopeSniff +{ + + /** + * The name of the class we are currently checking. + * + * @var string + */ + private $currentClass = ''; + + /** + * A list of functions in the current class. + * + * @var string[] + */ + private $functionList = []; + + + /** + * Constructs the test with the tokens it wishes to listen for. + */ + public function __construct() + { + parent::__construct([T_CLASS, T_ANON_CLASS], [T_FUNCTION], true); + + }//end __construct() + + + /** + * Processes this test when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $currScope A pointer to the start of the scope. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $className = $phpcsFile->getDeclarationName($currScope); + if (empty($className) === false) { + // Not an anonymous class. + $className = strtolower($className); + } + + if ($className !== $this->currentClass) { + $this->loadFunctionNamesInScope($phpcsFile, $currScope); + $this->currentClass = $className; + } + + $methodName = strtolower($phpcsFile->getDeclarationName($stackPtr)); + + if ($methodName === $className) { + if (in_array('__construct', $this->functionList, true) === false) { + $error = 'PHP4 style constructors are not allowed; use "__construct()" instead'; + $phpcsFile->addError($error, $stackPtr, 'OldStyle'); + } + } else if ($methodName !== '__construct') { + // Not a constructor. + return; + } + + // Stop if the constructor doesn't have a body, like when it is abstract. + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $parentClassName = strtolower($phpcsFile->findExtendedClassName($currScope)); + if ($parentClassName === false) { + return; + } + + $endFunctionIndex = $tokens[$stackPtr]['scope_closer']; + $startIndex = $stackPtr; + while (($doubleColonIndex = $phpcsFile->findNext(T_DOUBLE_COLON, $startIndex, $endFunctionIndex)) !== false) { + if ($tokens[($doubleColonIndex + 1)]['code'] === T_STRING + && strtolower($tokens[($doubleColonIndex + 1)]['content']) === $parentClassName + ) { + $error = 'PHP4 style calls to parent constructors are not allowed; use "parent::__construct()" instead'; + $phpcsFile->addError($error, ($doubleColonIndex + 1), 'OldStyleCall'); + } + + $startIndex = ($doubleColonIndex + 1); + } + + }//end processTokenWithinScope() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + + /** + * Extracts all the function names found in the given scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $currScope A pointer to the start of the scope. + * + * @return void + */ + protected function loadFunctionNamesInScope(File $phpcsFile, $currScope) + { + $this->functionList = []; + $tokens = $phpcsFile->getTokens(); + + for ($i = ($tokens[$currScope]['scope_opener'] + 1); $i < $tokens[$currScope]['scope_closer']; $i++) { + if ($tokens[$i]['code'] !== T_FUNCTION) { + continue; + } + + $this->functionList[] = trim(strtolower($phpcsFile->getDeclarationName($i))); + + if (isset($tokens[$i]['scope_closer']) !== false) { + // Skip past nested functions and such. + $i = $tokens[$i]['scope_closer']; + } + } + + }//end loadFunctionNamesInScope() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/InterfaceNameSuffixSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/InterfaceNameSuffixSniff.php new file mode 100644 index 00000000..c5dc34d4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/InterfaceNameSuffixSniff.php @@ -0,0 +1,54 @@ + + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class InterfaceNameSuffixSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_INTERFACE]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $interfaceName = $phpcsFile->getDeclarationName($stackPtr); + if ($interfaceName === null) { + return; + } + + $suffix = substr($interfaceName, -9); + if (strtolower($suffix) !== 'interface') { + $phpcsFile->addError('Interface names must be suffixed with "Interface"; found "%s"', $stackPtr, 'Missing', [$interfaceName]); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/TraitNameSuffixSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/TraitNameSuffixSniff.php new file mode 100644 index 00000000..4e3b211d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/TraitNameSuffixSniff.php @@ -0,0 +1,54 @@ + + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class TraitNameSuffixSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_TRAIT]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $traitName = $phpcsFile->getDeclarationName($stackPtr); + if ($traitName === null) { + return; + } + + $suffix = substr($traitName, -5); + if (strtolower($suffix) !== 'trait') { + $phpcsFile->addError('Trait names must be suffixed with "Trait"; found "%s"', $stackPtr, 'Missing', [$traitName]); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php new file mode 100644 index 00000000..db50eb56 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php @@ -0,0 +1,141 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UpperCaseConstantNameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_STRING, + T_CONST, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_CONST) { + // This is a class constant. + $constant = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($constant === false) { + return; + } + + $constName = $tokens[$constant]['content']; + + if (strtoupper($constName) !== $constName) { + if (strtolower($constName) === $constName) { + $phpcsFile->recordMetric($constant, 'Constant name case', 'lower'); + } else { + $phpcsFile->recordMetric($constant, 'Constant name case', 'mixed'); + } + + $error = 'Class constants must be uppercase; expected %s but found %s'; + $data = [ + strtoupper($constName), + $constName, + ]; + $phpcsFile->addError($error, $constant, 'ClassConstantNotUpperCase', $data); + } else { + $phpcsFile->recordMetric($constant, 'Constant name case', 'upper'); + } + + return; + }//end if + + // Only interested in define statements now. + if (strtolower($tokens[$stackPtr]['content']) !== 'define') { + return; + } + + // Make sure this is not a method call. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR + || $tokens[$prev]['code'] === T_DOUBLE_COLON + || $tokens[$prev]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + return; + } + + // If the next non-whitespace token after this token + // is not an opening parenthesis then it is not a function call. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($openBracket === false) { + return; + } + + // The next non-whitespace token must be the constant name. + $constPtr = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), null, true); + if ($tokens[$constPtr]['code'] !== T_CONSTANT_ENCAPSED_STRING) { + return; + } + + $constName = $tokens[$constPtr]['content']; + + // Check for constants like self::CONSTANT. + $prefix = ''; + $splitPos = strpos($constName, '::'); + if ($splitPos !== false) { + $prefix = substr($constName, 0, ($splitPos + 2)); + $constName = substr($constName, ($splitPos + 2)); + } + + // Strip namespace from constant like /foo/bar/CONSTANT. + $splitPos = strrpos($constName, '\\'); + if ($splitPos !== false) { + $prefix = substr($constName, 0, ($splitPos + 1)); + $constName = substr($constName, ($splitPos + 1)); + } + + if (strtoupper($constName) !== $constName) { + if (strtolower($constName) === $constName) { + $phpcsFile->recordMetric($stackPtr, 'Constant name case', 'lower'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Constant name case', 'mixed'); + } + + $error = 'Constants must be uppercase; expected %s but found %s'; + $data = [ + $prefix.strtoupper($constName), + $prefix.$constName, + ]; + $phpcsFile->addError($error, $stackPtr, 'ConstantNotUpperCase', $data); + } else { + $phpcsFile->recordMetric($stackPtr, 'Constant name case', 'upper'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/BacktickOperatorSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/BacktickOperatorSniff.php new file mode 100644 index 00000000..d455845b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/BacktickOperatorSniff.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class BacktickOperatorSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_BACKTICK]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $error = 'Use of the backtick operator is forbidden'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/CharacterBeforePHPOpeningTagSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/CharacterBeforePHPOpeningTagSniff.php new file mode 100644 index 00000000..f52180dd --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/CharacterBeforePHPOpeningTagSniff.php @@ -0,0 +1,86 @@ + + * @copyright 2010-2014 Andy Grunwald + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class CharacterBeforePHPOpeningTagSniff implements Sniff +{ + + /** + * List of supported BOM definitions. + * + * Use encoding names as keys and hex BOM representations as values. + * + * @var array + */ + protected $bomDefinitions = [ + 'UTF-8' => 'efbbbf', + 'UTF-16 (BE)' => 'feff', + 'UTF-16 (LE)' => 'fffe', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $expected = 0; + if ($stackPtr > 0) { + // Allow a byte-order mark. + $tokens = $phpcsFile->getTokens(); + foreach ($this->bomDefinitions as $bomName => $expectedBomHex) { + $bomByteLength = (strlen($expectedBomHex) / 2); + $htmlBomHex = bin2hex(substr($tokens[0]['content'], 0, $bomByteLength)); + if ($htmlBomHex === $expectedBomHex) { + $expected++; + break; + } + } + + // Allow a shebang line. + if (substr($tokens[0]['content'], 0, 2) === '#!') { + $expected++; + } + } + + if ($stackPtr !== $expected) { + $error = 'The opening PHP tag must be the first content in the file'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + } + + // Skip the rest of the file so we don't pick up additional + // open tags, typically embedded in HTML. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/ClosingPHPTagSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/ClosingPHPTagSniff.php new file mode 100644 index 00000000..d03bf8ab --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/ClosingPHPTagSniff.php @@ -0,0 +1,54 @@ + + * @copyright 2010-2014 Stefano Kowalke + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClosingPHPTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $closeTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr); + if ($closeTag === false) { + $error = 'The PHP open tag does not have a corresponding PHP close tag'; + $phpcsFile->addError($error, $stackPtr, 'NotFound'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DeprecatedFunctionsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DeprecatedFunctionsSniff.php new file mode 100644 index 00000000..42eaa40f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DeprecatedFunctionsSniff.php @@ -0,0 +1,73 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +class DeprecatedFunctionsSniff extends ForbiddenFunctionsSniff +{ + + /** + * A list of forbidden functions with their alternatives. + * + * The value is NULL if no alternative exists. IE, the + * function should just not be used. + * + * @var array + */ + public $forbiddenFunctions = []; + + + /** + * Constructor. + * + * Uses the Reflection API to get a list of deprecated functions. + */ + public function __construct() + { + $functions = get_defined_functions(); + + foreach ($functions['internal'] as $functionName) { + $function = new \ReflectionFunction($functionName); + + if ($function->isDeprecated() === true) { + $this->forbiddenFunctions[$functionName] = null; + } + } + + }//end __construct() + + + /** + * Generates the error or warning for this sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the forbidden function + * in the token array. + * @param string $function The name of the forbidden function. + * @param string $pattern The pattern used for the match. + * + * @return void + */ + protected function addError($phpcsFile, $stackPtr, $function, $pattern=null) + { + $data = [$function]; + $error = 'Function %s() has been deprecated'; + $type = 'Deprecated'; + + if ($this->error === true) { + $phpcsFile->addError($error, $stackPtr, $type, $data); + } else { + $phpcsFile->addWarning($error, $stackPtr, $type, $data); + } + + }//end addError() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowAlternativePHPTagsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowAlternativePHPTagsSniff.php new file mode 100644 index 00000000..433750ad --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowAlternativePHPTagsSniff.php @@ -0,0 +1,253 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowAlternativePHPTagsSniff implements Sniff +{ + + /** + * Whether ASP tags are enabled or not. + * + * @var boolean + */ + private $aspTags = false; + + /** + * The current PHP version. + * + * @var integer + */ + private $phpVersion = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + if ($this->phpVersion === null) { + $this->phpVersion = Config::getConfigData('php_version'); + if ($this->phpVersion === null) { + $this->phpVersion = PHP_VERSION_ID; + } + } + + if ($this->phpVersion < 70000) { + $this->aspTags = (bool) ini_get('asp_tags'); + } + + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + T_INLINE_HTML, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $openTag = $tokens[$stackPtr]; + $content = $openTag['content']; + + if (trim($content) === '') { + return; + } + + if ($openTag['code'] === T_OPEN_TAG) { + if ($content === '<%') { + $error = 'ASP style opening tag used; expected "findClosingTag($phpcsFile, $tokens, $stackPtr, '%>'); + $errorCode = 'ASPOpenTagFound'; + } else if (strpos($content, ''); + $errorCode = 'ScriptOpenTagFound'; + } + + if (isset($error, $closer, $errorCode) === true) { + $data = [$content]; + + if ($closer === false) { + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode, $data); + if ($fix === true) { + $this->addChangeset($phpcsFile, $tokens, $stackPtr, $closer); + } + } + } + + return; + }//end if + + if ($openTag['code'] === T_OPEN_TAG_WITH_ECHO && $content === '<%=') { + $error = 'ASP style opening tag used with echo; expected "findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $snippet = $this->getSnippet($tokens[$nextVar]['content']); + $data = [ + $snippet, + $content, + $snippet, + ]; + + $closer = $this->findClosingTag($phpcsFile, $tokens, $stackPtr, '%>'); + + if ($closer === false) { + $phpcsFile->addError($error, $stackPtr, 'ASPShortOpenTagFound', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ASPShortOpenTagFound', $data); + if ($fix === true) { + $this->addChangeset($phpcsFile, $tokens, $stackPtr, $closer, true); + } + } + + return; + }//end if + + // Account for incorrect script open tags. + if ($openTag['code'] === T_INLINE_HTML + && preg_match('`( + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.1.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.1.inc.fixed new file mode 100644 index 00000000..2a695c89 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.1.inc.fixed @@ -0,0 +1,14 @@ +
    + +Some content here. + + + + +
    diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc new file mode 100644 index 00000000..cd5a6620 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc @@ -0,0 +1,6 @@ +
    +<% echo $var; %> +

    Some text <% echo $var; %> and some more text

    +<%= $var . ' and some more text to make sure the snippet works'; %> +

    Some text <%= $var %> and some more text

    +
    diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc.fixed new file mode 100644 index 00000000..6eafb422 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc.fixed @@ -0,0 +1,6 @@ +
    + +

    Some text and some more text

    + +

    Some text and some more text

    +
    diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.3.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.3.inc new file mode 100644 index 00000000..ba86345a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.3.inc @@ -0,0 +1,7 @@ + +
    +<% echo $var; %> +

    Some text <% echo $var; %> and some more text

    +<%= $var . ' and some more text to make sure the snippet works'; %> +

    Some text <%= $var %> and some more text

    +
    diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.php new file mode 100644 index 00000000..953e8ad9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.php @@ -0,0 +1,105 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowAlternativePHPTagsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of all test files to check. + * + * @param string $testFileBase The base path that the unit tests files will have. + * + * @return string[] + */ + protected function getTestFiles($testFileBase) + { + $testFiles = [$testFileBase.'1.inc']; + + $aspTags = false; + if (PHP_VERSION_ID < 70000) { + $aspTags = (bool) ini_get('asp_tags'); + } + + if ($aspTags === true) { + $testFiles[] = $testFileBase.'2.inc'; + } else { + $testFiles[] = $testFileBase.'3.inc'; + } + + return $testFiles; + + }//end getTestFiles() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'DisallowAlternativePHPTagsUnitTest.1.inc': + return [ + 4 => 1, + 7 => 1, + 8 => 1, + 11 => 1, + ]; + case 'DisallowAlternativePHPTagsUnitTest.2.inc': + return [ + 2 => 1, + 3 => 1, + 4 => 1, + 5 => 1, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + if ($testFile === 'DisallowAlternativePHPTagsUnitTest.3.inc') { + return [ + 3 => 1, + 4 => 1, + 5 => 1, + 6 => 1, + ]; + } + + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.inc new file mode 100644 index 00000000..974e45c0 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.inc @@ -0,0 +1,16 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.php new file mode 100644 index 00000000..7ece5512 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowRequestSuperglobalUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + protected function getErrorList() + { + return [ + 2 => 1, + 12 => 1, + 13 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + protected function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc new file mode 100644 index 00000000..040e62dc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc @@ -0,0 +1,11 @@ +
    + +Some content here. + + +Some content Some more content + + +
    diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc.fixed new file mode 100644 index 00000000..1ea281a4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc.fixed @@ -0,0 +1,11 @@ +
    + +Some content here. + + +Some content Some more content + + +
    diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc new file mode 100644 index 00000000..85617ded --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc @@ -0,0 +1,8 @@ +
    + +Some content Some more content + + +
    diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc.fixed new file mode 100644 index 00000000..afe5d8f2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc.fixed @@ -0,0 +1,8 @@ +
    + +Some content Some more content + + +
    diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.3.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.3.inc new file mode 100644 index 00000000..9b7ccd6d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.3.inc @@ -0,0 +1,16 @@ +// Test warning for when short_open_tag is off. + +Some content Some more content + +// Test multi-line. +Some content Some more content + +// Make sure skipping works. +Some content Some more content + +// Only recognize closing tag after opener. +Some?> content + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowShortOpenTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of all test files to check. + * + * @param string $testFileBase The base path that the unit tests files will have. + * + * @return string[] + */ + protected function getTestFiles($testFileBase) + { + $testFiles = [$testFileBase.'1.inc']; + + $option = (bool) ini_get('short_open_tag'); + if ($option === true) { + $testFiles[] = $testFileBase.'2.inc'; + } else { + $testFiles[] = $testFileBase.'3.inc'; + } + + return $testFiles; + + }//end getTestFiles() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'DisallowShortOpenTagUnitTest.1.inc': + return [ + 5 => 1, + 6 => 1, + 7 => 1, + 10 => 1, + ]; + case 'DisallowShortOpenTagUnitTest.2.inc': + return [ + 2 => 1, + 3 => 1, + 4 => 1, + 7 => 1, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'DisallowShortOpenTagUnitTest.1.inc': + return []; + case 'DisallowShortOpenTagUnitTest.3.inc': + return [ + 3 => 1, + 6 => 1, + 11 => 1, + ]; + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DiscourageGotoUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DiscourageGotoUnitTest.inc new file mode 100644 index 00000000..f564215b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DiscourageGotoUnitTest.inc @@ -0,0 +1,18 @@ + + * @copyright 2006-2017 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DiscourageGotoUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 3 => 1, + 6 => 1, + 11 => 1, + 16 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.inc new file mode 100644 index 00000000..b30f0dde --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.inc @@ -0,0 +1,57 @@ +sizeof($array); +$size = $class->count($array); +$class->delete($filepath); +$class->unset($filepath); + +function delete() {} +function unset() {} +function sizeof() {} +function count() {} + +trait DelProvider { + public function delete() { + //irrelevant + } +} + +class LeftSideTest { + use DelProvider { + delete as protected unsetter; + } +} + +class RightSideTest { + use DelProvider { + delete as delete; + } +} + +class RightSideVisTest { + use DelProvider { + delete as protected delete; + DelProvider::delete insteadof delete; + } +} + +namespace Something\sizeof; +$var = new Sizeof(); +class SizeOf implements Something {} + +function mymodule_form_callback(SizeOf $sizeof) { +} + +$size = $class?->sizeof($array); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.php new file mode 100644 index 00000000..760e8078 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ForbiddenFunctionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 2 => 1, + 4 => 1, + 6 => 1, + ]; + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc new file mode 100644 index 00000000..0307a055 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc @@ -0,0 +1,100 @@ +NULL = 7; + +use Zend\Log\Writer\NULL as NullWriter; +new \Zend\Log\Writer\NULL(); + +namespace False; + +class True extends Null implements False {} + +use True\Something; +use Something\True; +class MyClass +{ + public function myFunction() + { + $var = array('foo' => new True()); + } +} + +$x = $f?FALSE:true; +$x = $f? FALSE:true; + +class MyClass +{ + // Spice things up a little. + const TRUE = false; +} + +var_dump(MyClass::TRUE); + +function tRUE() {} + +$input->getFilterChain()->attachByName('Null', ['type' => Null::TYPE_STRING]); + +// Issue #3332 - ignore type declarations, but not default values. +class TypedThings { + const MYCONST = FALSE; + + public int|FALSE $int = FALSE; + public Type|NULL $int = new MyObj(NULL); + + private function typed(int|FALSE $param = NULL, Type|NULL $obj = new MyObj(FALSE)) : string|FALSE|NULL + { + if (TRUE === FALSE) { + return NULL; + } + } +} + +$cl = function (int|FALSE $param = NULL, Type|NULL $obj = new MyObj(FALSE)) : string|FALSE|NULL {}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc.fixed new file mode 100644 index 00000000..3a6b094c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc.fixed @@ -0,0 +1,100 @@ +NULL = 7; + +use Zend\Log\Writer\NULL as NullWriter; +new \Zend\Log\Writer\NULL(); + +namespace False; + +class True extends Null implements False {} + +use True\Something; +use Something\True; +class MyClass +{ + public function myFunction() + { + $var = array('foo' => new True()); + } +} + +$x = $f?false:true; +$x = $f? false:true; + +class MyClass +{ + // Spice things up a little. + const TRUE = false; +} + +var_dump(MyClass::TRUE); + +function tRUE() {} + +$input->getFilterChain()->attachByName('Null', ['type' => Null::TYPE_STRING]); + +// Issue #3332 - ignore type declarations, but not default values. +class TypedThings { + const MYCONST = false; + + public int|FALSE $int = false; + public Type|NULL $int = new MyObj(null); + + private function typed(int|FALSE $param = null, Type|NULL $obj = new MyObj(false)) : string|FALSE|NULL + { + if (true === false) { + return null; + } + } +} + +$cl = function (int|FALSE $param = null, Type|NULL $obj = new MyObj(false)) : string|FALSE|NULL {}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js new file mode 100644 index 00000000..87cfb820 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js @@ -0,0 +1,14 @@ +if (variable === true) { } +if (variable === TRUE) { } +if (variable === True) { } +variable = True; + +if (variable === false) { } +if (variable === FALSE) { } +if (variable === False) { } +variable = false; + +if (variable === null) { } +if (variable === NULL) { } +if (variable === Null) { } +variable = NULL; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js.fixed new file mode 100644 index 00000000..7dbf3adf --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js.fixed @@ -0,0 +1,14 @@ +if (variable === true) { } +if (variable === true) { } +if (variable === true) { } +variable = true; + +if (variable === false) { } +if (variable === false) { } +if (variable === false) { } +variable = false; + +if (variable === null) { } +if (variable === null) { } +if (variable === null) { } +variable = null; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.php new file mode 100644 index 00000000..2fb2d6f6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowerCaseConstantUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='LowerCaseConstantUnitTest.inc') + { + switch ($testFile) { + case 'LowerCaseConstantUnitTest.inc': + return [ + 7 => 1, + 10 => 1, + 15 => 1, + 16 => 1, + 23 => 1, + 26 => 1, + 31 => 1, + 32 => 1, + 39 => 1, + 42 => 1, + 47 => 1, + 48 => 1, + 70 => 1, + 71 => 1, + 87 => 1, + 89 => 1, + 90 => 1, + 92 => 2, + 94 => 2, + 95 => 1, + 100 => 2, + ]; + break; + case 'LowerCaseConstantUnitTest.js': + return [ + 2 => 1, + 3 => 1, + 4 => 1, + 7 => 1, + 8 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc new file mode 100644 index 00000000..37579d32 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc @@ -0,0 +1,48 @@ + $x; +$r = Match ($x) { + 1 => 1, + 2 => 2, + DEFAULT, => 3, +}; + +class Reading { + Public READOnly int $var; +} + +EnuM ENUM: string +{ + Case HEARTS; +} + +__HALT_COMPILER(); // An exception due to phar support. +function diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed new file mode 100644 index 00000000..7063327a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed @@ -0,0 +1,48 @@ + $x; +$r = match ($x) { + 1 => 1, + 2 => 2, + default, => 3, +}; + +class Reading { + public readonly int $var; +} + +enum ENUM: string +{ + case HEARTS; +} + +__HALT_COMPILER(); // An exception due to phar support. +function diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.php new file mode 100644 index 00000000..6d08e127 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowerCaseKeywordUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 3, + 11 => 4, + 12 => 1, + 13 => 3, + 14 => 7, + 15 => 1, + 19 => 1, + 20 => 1, + 21 => 1, + 25 => 1, + 28 => 1, + 31 => 1, + 32 => 1, + 35 => 1, + 39 => 2, + 42 => 1, + 44 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc new file mode 100644 index 00000000..ac2a1f9e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowerCaseTypeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 14 => 1, + 15 => 1, + 16 => 1, + 17 => 1, + 18 => 1, + 21 => 4, + 22 => 3, + 23 => 3, + 25 => 1, + 26 => 2, + 27 => 2, + 32 => 4, + 36 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 43 => 2, + 44 => 1, + 46 => 1, + 49 => 1, + 51 => 2, + 53 => 1, + 55 => 2, + 60 => 1, + 61 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 66 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 71 => 3, + 72 => 2, + 73 => 3, + 74 => 3, + 78 => 3, + 82 => 2, + 85 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.inc new file mode 100644 index 00000000..72bffe2c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.inc @@ -0,0 +1,10 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class NoSilencedErrorsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 5 => 1, + 10 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.1.inc new file mode 100644 index 00000000..387cec24 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.1.inc @@ -0,0 +1,8 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class RequireStrictTypesUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'RequireStrictTypesUnitTest.1.inc': + return []; + break; + } + + return [1 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.inc new file mode 100644 index 00000000..f0f350f3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.inc @@ -0,0 +1,5 @@ +php_sapi_name() === true) {} +if ($object?->php_sapi_name() === true) {} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.php new file mode 100644 index 00000000..08c0ccdc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SAPIUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [2 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.1.inc new file mode 100644 index 00000000..4f0d9d84 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.1.inc @@ -0,0 +1,4 @@ + +
    text
    + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.php new file mode 100644 index 00000000..98d205ce --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.php @@ -0,0 +1,59 @@ + + * @author Blaine Schmeisser + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SyntaxUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'SyntaxUnitTest.1.inc': + case 'SyntaxUnitTest.2.inc': + return [3 => 1]; + break; + default: + return []; + break; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc new file mode 100644 index 00000000..30c6d298 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc @@ -0,0 +1,98 @@ +null = 7; + +use Zend\Log\Writer\Null as NullWriter; +new \Zend\Log\Writer\Null(); + +namespace False; + +class True extends Null implements False {} + +use True\Something; +use Something\True; +class MyClass +{ + public function myFunction() + { + $var = array('foo' => new True()); + } +} + +$x = $f?false:TRUE; +$x = $f? false:TRUE; + +class MyClass +{ + // Spice things up a little. + const true = FALSE; +} + +var_dump(MyClass::true); + +function true() {} + +// Issue #3332 - ignore type declarations, but not default values. +class TypedThings { + const MYCONST = false; + + public int|false $int = false; + public Type|null $int = new MyObj(null); + + private function typed(int|false $param = null, Type|null $obj = new MyObj(false)) : string|false|null + { + if (true === false) { + return null; + } + } +} + +$cl = function (int|false $param = null, Type|null $obj = new MyObj(false)) : string|false|null {}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc.fixed new file mode 100644 index 00000000..7705198c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc.fixed @@ -0,0 +1,98 @@ +null = 7; + +use Zend\Log\Writer\Null as NullWriter; +new \Zend\Log\Writer\Null(); + +namespace False; + +class True extends Null implements False {} + +use True\Something; +use Something\True; +class MyClass +{ + public function myFunction() + { + $var = array('foo' => new True()); + } +} + +$x = $f?FALSE:TRUE; +$x = $f? FALSE:TRUE; + +class MyClass +{ + // Spice things up a little. + const true = FALSE; +} + +var_dump(MyClass::true); + +function true() {} + +// Issue #3332 - ignore type declarations, but not default values. +class TypedThings { + const MYCONST = FALSE; + + public int|false $int = FALSE; + public Type|null $int = new MyObj(NULL); + + private function typed(int|false $param = NULL, Type|null $obj = new MyObj(FALSE)) : string|false|null + { + if (TRUE === FALSE) { + return NULL; + } + } +} + +$cl = function (int|false $param = NULL, Type|null $obj = new MyObj(FALSE)) : string|false|null {}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.php new file mode 100644 index 00000000..30e57763 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.php @@ -0,0 +1,70 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class UpperCaseConstantUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 10 => 1, + 15 => 1, + 16 => 1, + 23 => 1, + 26 => 1, + 31 => 1, + 32 => 1, + 39 => 1, + 42 => 1, + 47 => 1, + 48 => 1, + 70 => 1, + 71 => 1, + 85 => 1, + 87 => 1, + 88 => 1, + 90 => 2, + 92 => 2, + 93 => 1, + 98 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.inc new file mode 100644 index 00000000..43c05a11 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.inc @@ -0,0 +1,21 @@ +'; +$code = '<'.'?php '; + +$string = 'This is a really long string. ' + . 'It is being used for errors. ' + . 'The message is not translated.'; +?> diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.js new file mode 100644 index 00000000..6be79008 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.js @@ -0,0 +1,15 @@ +var x = 'My ' + 'string'; +var x = 'My ' + 1234; +var x = 'My ' + y + ' test'; + +this.errors['test'] = x; +this.errors['test' + 10] = x; +this.errors['test' + y] = x; +this.errors['test' + 'blah'] = x; +this.errors[y] = x; +this.errors[y + z] = x; +this.errors[y + z + 'My' + 'String'] = x; + +var long = 'This is a really long string. ' + + 'It is being used for errors. ' + + 'The message is not translated.'; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.php new file mode 100644 index 00000000..6a928482 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class UnnecessaryStringConcatUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='UnnecessaryStringConcatUnitTest.inc') + { + switch ($testFile) { + case 'UnnecessaryStringConcatUnitTest.inc': + return [ + 2 => 1, + 6 => 1, + 9 => 1, + 12 => 1, + 19 => 1, + 20 => 1, + ]; + break; + case 'UnnecessaryStringConcatUnitTest.js': + return [ + 1 => 1, + 8 => 1, + 11 => 1, + 14 => 1, + 15 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.css b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.css new file mode 100644 index 00000000..de84a948 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.css @@ -0,0 +1,35 @@ +/* + * This is a CSS comment. +<<<<<<< HEAD + * This is a merge conflict... +======= + * which should be detected. +>>>>>>> ref/heads/feature-branch + */ + +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; +<<<<<<< HEAD + line-height: -25px; +======= + line-height: -20px; +>>>>>>> ref/heads/feature-branch + cursor: pointer; + -moz-user-select: none; +} + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries, subsequent boundaries will still + * be detected correctly. + */ + +/* + * This is a CSS comment. +<<<<<<< HEAD + * This is a merge conflict... +======= + * which should be detected. +>>>>>>> ref/heads/feature-branch + */ diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.inc new file mode 100644 index 00000000..470c3b8f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.inc @@ -0,0 +1,61 @@ +> -1); +var_dump( +1 +<< +-1 +); + +$string = +<< 'a' +<<<<<<< HEAD + 'b' => 'b' +======= + 'c' => 'c' +>>>>>>> master + ); + } + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ + +/* + * Testing detecting subsequent merge conflicts. + * +<<<<<<< HEAD + * @var string $bar + */ +public function foo($bar){ } + +/** +============ +The above is not the boundary, the below is. +======= + * @var string $bar +>>>>>>> f19f8a5... Commit message +*/ + +// Test that stray boundaries, i.e. an opener without closer and such, are detected. +<<<<<<< HEAD +$a = 1; +======= diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.css b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.css new file mode 100644 index 00000000..6caa78d0 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.css @@ -0,0 +1,32 @@ +/* + * This is a CSS comment. +<<<<<<< HEAD + * This is a merge conflict started in a comment, ending in a CSS block. + */ +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; +======= + * which should be detected. + **/ +.SettingsTabPaneWidgetType-tab-start { + line-height: -25px; +>>>>>>> ref/heads/feature-branch + cursor: pointer; + -moz-user-select: none; +} + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries, subsequent boundaries will still + * be detected correctly. + */ + +/* + * This is a CSS comment. +<<<<<<< HEAD + * This is a merge conflict... +======= + * which should be detected. +>>>>>>> ref/heads/feature-branch + */ diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.inc new file mode 100644 index 00000000..809b17d6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.inc @@ -0,0 +1,31 @@ +>>>>>> master + */ + +/* + * Testing detecting merge conflicts using different comment styles. + * +<<<<<<< HEAD + * @var string $bar + */ +public function foo($bar){ } + +/* +======= + * @var string $bar +>>>>>>> master +*/ + +// Comment +<<<<<<< HEAD +// Second comment line. NOTE: The above opener breaks the tokenizer. +======= +// New second comment line +>>>>>>> master +// Third comment line diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.3.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.3.inc new file mode 100644 index 00000000..ce709412 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.3.inc @@ -0,0 +1,43 @@ + +
    +<<<<<<< HEAD +

    Testing a merge conflict.

    +======= +

    Another text string.

    +>>>>>>> ref/heads/feature-branch +
    + + +
    +<<<<<<< HEAD +

    +======= +

    +>>>>>>> ref/heads/feature-branch +
    + +>>>>>> master + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ +?> + +
    +<<<<<<< HEAD +

    Testing a merge conflict.

    +======= +

    Another text string.

    +>>>>>>> ref/heads/feature-branch +
    diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.4.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.4.inc new file mode 100644 index 00000000..99c0b997 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.4.inc @@ -0,0 +1,71 @@ +>>>>>> ref/heads/other-branchname +And now they are. +EOD; + +// Heredoc with a merge conflict starter, the closer is outside the heredoc. +$string = +<<>>>>>> ref/heads/other-branchname + +// Merge conflict starter outside with a closer inside of the heredoc. +// This breaks the tokenizer. +<<<<<<< HEAD +$string = +<<>>>>>> ref/heads/other-branchname +EOD; + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ + +$string = +<<>>>>>> ref/heads/other-branchname +And now they are. +EOD; + +$string = +<<>>>>>> ref/heads/other-branchname diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.5.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.5.inc new file mode 100644 index 00000000..7d55f6df --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.5.inc @@ -0,0 +1,34 @@ +>>>>>> ref/heads/other-branchname +And now they are. +EOD; + +// Break the tokenizer. +<<<<<<< HEAD + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ + +$string = +<<<'EOD' +can be problematic. +<<<<<<< HEAD +were previously not detected. +======= +should also be detected. +>>>>>>> ref/heads/other-branchname +And now they are. +EOD; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.6.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.6.inc new file mode 100644 index 00000000..aaea3245 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.6.inc @@ -0,0 +1,34 @@ +>>>>>> ref/heads/other-branchname + And now they are. + EOD; + +// Break the tokenizer. +>>>>>>> master + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ + +$string = + <<<"EOD" + Merge conflicts in PHP 7.3 indented heredocs +<<<<<<< HEAD + can be problematic. +======= + should also be detected. +>>>>>>> ref/heads/other-branchname + And now they are. + EOD; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.7.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.7.inc new file mode 100644 index 00000000..85cae1fd --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.7.inc @@ -0,0 +1,19 @@ + +
    +<<<<<<< HEAD +

    Testing a merge conflict.

    +======= +

    Another text string.

    +>>>>>>> ref/heads/feature-branch +
    + + +
    +<<<<<<< HEAD +

    +======= +

    +>>>>>>> ref/heads/feature-branch +
    + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.js new file mode 100644 index 00000000..cd7bc760 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.js @@ -0,0 +1,33 @@ + +result = x?y:z; +result = x ? y : z; + +<<<<<<< HEAD +if (something === true +======= +if (something === false +>>>>>>> develop + ^ somethingElse === true +) { +<<<<<<< HEAD + return true; +======= + return false; +>>>>>>> develop +} + +y = 1 + + 2 + - 3; + +/* +<<<<<<< HEAD + * @var string $bar + */ +if (something === true + +/** +======= + * @var string $foo +>>>>>>> master + */ diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.php new file mode 100644 index 00000000..50986f48 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.php @@ -0,0 +1,170 @@ + + * @copyright 2017 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\VersionControl; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class GitMergeConflictUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='GitMergeConflictUnitTest.1.inc') + { + switch ($testFile) { + case 'GitMergeConflictUnitTest.1.inc': + return [ + 26 => 1, + 28 => 1, + 30 => 1, + 45 => 1, + 53 => 1, + 55 => 1, + 59 => 1, + 61 => 1, + ]; + + case 'GitMergeConflictUnitTest.2.inc': + return [ + 4 => 1, + 6 => 1, + 8 => 1, + 14 => 1, + 20 => 1, + 22 => 1, + 26 => 1, + 28 => 1, + 30 => 1, + ]; + + case 'GitMergeConflictUnitTest.3.inc': + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 12 => 1, + 14 => 1, + 16 => 1, + 22 => 1, + 24 => 1, + 26 => 1, + 38 => 1, + 40 => 1, + 42 => 1, + ]; + + case 'GitMergeConflictUnitTest.4.inc': + return [ + 6 => 1, + 8 => 1, + 10 => 1, + 18 => 1, + 22 => 1, + 25 => 1, + 29 => 1, + 34 => 1, + 39 => 1, + 53 => 1, + 55 => 1, + 57 => 1, + 64 => 1, + 68 => 1, + 71 => 1, + ]; + case 'GitMergeConflictUnitTest.5.inc': + case 'GitMergeConflictUnitTest.6.inc': + return [ + 6 => 1, + 8 => 1, + 10 => 1, + 15 => 1, + 28 => 1, + 30 => 1, + 32 => 1, + ]; + + case 'GitMergeConflictUnitTest.7.inc': + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 12 => 1, + 14 => 1, + 16 => 1, + ]; + + case 'GitMergeConflictUnitTest.1.css': + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 12 => 1, + 14 => 1, + 16 => 1, + 30 => 1, + 32 => 1, + 34 => 1, + ]; + + case 'GitMergeConflictUnitTest.2.css': + return [ + 3 => 1, + 8 => 1, + 13 => 1, + 27 => 1, + 29 => 1, + 31 => 1, + ]; + + case 'GitMergeConflictUnitTest.js': + return [ + 5 => 1, + 7 => 1, + 9 => 1, + 12 => 1, + 14 => 1, + 16 => 1, + 24 => 1, + 30 => 1, + 32 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/SubversionPropertiesUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/SubversionPropertiesUnitTest.inc new file mode 100644 index 00000000..e4110dee --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/SubversionPropertiesUnitTest.inc @@ -0,0 +1,3 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\VersionControl; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SubversionPropertiesUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Should this test be skipped for some reason. + * + * @return void + */ + protected function shouldSkipTest() + { + // This sniff cannot be tested as no SVN version control directory is available. + return true; + + }//end shouldSkipTest() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.inc new file mode 100644 index 00000000..bad3998f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.inc @@ -0,0 +1,165 @@ +{$var}( $foo,$bar ); + +$bar(function( $a, $b ) { + return function( $c, $d ) use ( $a, $b ) { + echo $a, $b, $c, $d; + }; +})( 'a','b' )( 'c','d' ); + +$closure( $foo,$bar ); +$var = $closure() + $closure( $foo,$bar ) + self::$closure( $foo,$bar ); + +class Test { + public static function baz( $foo, $bar ) { + $a = new self( $foo,$bar ); + $b = new static( $foo,$bar ); + } +} + +/* + * Test warning for empty parentheses. + */ +$a = 4 + (); // Warning. +$a = 4 + ( ); // Warning. +$a = 4 + (/* Not empty */); + +/* + * Test the actual sniff. + */ +if ((null !== $extra) && ($row->extra !== $extra)) {} + +if (( null !== $extra ) && ( $row->extra !== $extra )) {} // Bad x 4. + +if (( null !== $extra // Bad x 1. + && is_int($extra)) + && ( $row->extra !== $extra // Bad x 1. + || $something ) // Bad x 1. +) {} + +if (( null !== $extra ) // Bad x 2. + && ( $row->extra !== $extra ) // Bad x 2. +) {} + +$a = (null !== $extra); +$a = ( null !== $extra ); // Bad x 2. + +$sx = $vert ? ($w - 1) : 0; + +$this->is_overloaded = ( ( ini_get("mbstring.func_overload") & 2 ) != 0 ) && function_exists('mb_substr'); // Bad x 4. + +$image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 ); + +if ( $success && ('nothumb' == $target || 'all' == $target) ) {} + +$directory = ('/' == $file[ strlen($file)-1 ]); + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 1 +if ((null !== $extra) && ($row->extra !== $extra)) {} // Bad x 4. + +if (( null !== $extra ) && ( $row->extra !== $extra )) {} + +if (( null !== $extra // Bad x 1. + && is_int($extra)) // Bad x 1. + && ( $row->extra !== $extra + || $something ) // Bad x 1. +) {} + +if ((null !== $extra) // Bad x 2. + && ($row->extra !== $extra) // Bad x 2. +) {} + +$a = (null !== $extra); // Bad x 2. +$a = ( null !== $extra ); + +$sx = $vert ? ($w - 1) : 0; // Bad x 2. + +$this->is_overloaded = ((ini_get("mbstring.func_overload") & 2) != 0) && function_exists('mb_substr'); // Bad x 4. + +$image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 ); // Bad x 4. + +if ( $success && ('nothumb' == $target || 'all' == $target) ) {} // Bad x 2. + +$directory = ('/' == $file[ strlen($file)-1 ]); // Bad x 2. + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 0 + +/* + * Test handling of ignoreNewlines. + */ +if ( + ( + null !== $extra + ) && ( + $row->extra !== $extra + ) +) {} // Bad x 4, 1 x line 123, 2 x line 125, 1 x line 127. + + +$a = ( + null !== $extra +); // Bad x 2, 1 x line 131, 1 x line 133. + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 1 +if ( + ( + null !== $extra + ) && ( + $row->extra !== $extra + ) +) {} // Bad x 4, 1 x line 137, 2 x line 139, 1 x line 141. + +$a = ( + null !== $extra +); // Bad x 2, 1 x line 144, 1 x line 146. +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 0 + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing ignoreNewlines true +if ( + ( + null !== $extra + ) && ( + $row->extra !== $extra + ) +) {} + +$a = ( + null !== $extra +); +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing ignoreNewlines false + +if (true) {} ( 1+2) === 3 ? $a = 1 : $a = 2; +class A {} ( 1+2) === 3 ? $a = 1 : $a = 2; +function foo() {} ( 1+2) === 3 ? $a = 1 : $a = 2; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.inc.fixed new file mode 100644 index 00000000..08fcd624 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.inc.fixed @@ -0,0 +1,153 @@ +{$var}( $foo,$bar ); + +$bar(function( $a, $b ) { + return function( $c, $d ) use ( $a, $b ) { + echo $a, $b, $c, $d; + }; +})( 'a','b' )( 'c','d' ); + +$closure( $foo,$bar ); +$var = $closure() + $closure( $foo,$bar ) + self::$closure( $foo,$bar ); + +class Test { + public static function baz( $foo, $bar ) { + $a = new self( $foo,$bar ); + $b = new static( $foo,$bar ); + } +} + +/* + * Test warning for empty parentheses. + */ +$a = 4 + (); // Warning. +$a = 4 + ( ); // Warning. +$a = 4 + (/* Not empty */); + +/* + * Test the actual sniff. + */ +if ((null !== $extra) && ($row->extra !== $extra)) {} + +if ((null !== $extra) && ($row->extra !== $extra)) {} // Bad x 4. + +if ((null !== $extra // Bad x 1. + && is_int($extra)) + && ($row->extra !== $extra // Bad x 1. + || $something) // Bad x 1. +) {} + +if ((null !== $extra) // Bad x 2. + && ($row->extra !== $extra) // Bad x 2. +) {} + +$a = (null !== $extra); +$a = (null !== $extra); // Bad x 2. + +$sx = $vert ? ($w - 1) : 0; + +$this->is_overloaded = ((ini_get("mbstring.func_overload") & 2) != 0) && function_exists('mb_substr'); // Bad x 4. + +$image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 ); + +if ( $success && ('nothumb' == $target || 'all' == $target) ) {} + +$directory = ('/' == $file[ strlen($file)-1 ]); + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 1 +if (( null !== $extra ) && ( $row->extra !== $extra )) {} // Bad x 4. + +if (( null !== $extra ) && ( $row->extra !== $extra )) {} + +if (( null !== $extra // Bad x 1. + && is_int($extra) ) // Bad x 1. + && ( $row->extra !== $extra + || $something ) // Bad x 1. +) {} + +if (( null !== $extra ) // Bad x 2. + && ( $row->extra !== $extra ) // Bad x 2. +) {} + +$a = ( null !== $extra ); // Bad x 2. +$a = ( null !== $extra ); + +$sx = $vert ? ( $w - 1 ) : 0; // Bad x 2. + +$this->is_overloaded = ( ( ini_get("mbstring.func_overload") & 2 ) != 0 ) && function_exists('mb_substr'); // Bad x 4. + +$image->flip( ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 ); // Bad x 4. + +if ( $success && ( 'nothumb' == $target || 'all' == $target ) ) {} // Bad x 2. + +$directory = ( '/' == $file[ strlen($file)-1 ] ); // Bad x 2. + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 0 + +/* + * Test handling of ignoreNewlines. + */ +if ( + (null !== $extra) && ($row->extra !== $extra) +) {} // Bad x 4, 1 x line 123, 2 x line 125, 1 x line 127. + + +$a = (null !== $extra); // Bad x 2, 1 x line 131, 1 x line 133. + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 1 +if ( + ( null !== $extra ) && ( $row->extra !== $extra ) +) {} // Bad x 4, 1 x line 137, 2 x line 139, 1 x line 141. + +$a = ( null !== $extra ); // Bad x 2, 1 x line 144, 1 x line 146. +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 0 + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing ignoreNewlines true +if ( + ( + null !== $extra + ) && ( + $row->extra !== $extra + ) +) {} + +$a = ( + null !== $extra +); +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing ignoreNewlines false + +if (true) {} (1+2) === 3 ? $a = 1 : $a = 2; +class A {} (1+2) === 3 ? $a = 1 : $a = 2; +function foo() {} (1+2) === 3 ? $a = 1 : $a = 2; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.php new file mode 100644 index 00000000..0f70e287 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.php @@ -0,0 +1,85 @@ + + * @copyright 2006-2017 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ArbitraryParenthesesSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 64 => 4, + 66 => 1, + 68 => 1, + 69 => 1, + 72 => 2, + 73 => 2, + 77 => 2, + 81 => 4, + 90 => 4, + 94 => 1, + 95 => 1, + 97 => 1, + 100 => 2, + 101 => 2, + 104 => 2, + 107 => 2, + 109 => 4, + 111 => 4, + 113 => 2, + 115 => 2, + 123 => 1, + 125 => 2, + 127 => 1, + 131 => 1, + 133 => 1, + 137 => 1, + 139 => 2, + 141 => 1, + 144 => 1, + 146 => 1, + 163 => 1, + 164 => 1, + 165 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 55 => 1, + 56 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.1.inc new file mode 100644 index 00000000..1826b585 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.1.inc @@ -0,0 +1,118 @@ +"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// [space][space][space][tab]return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// Doc comments are indent with tabs and one space +//[tab]/** +//[tab][space]* + /** + * CVS revision for HTTP headers. + * + * @var string + * @access private + */ + /** + * + */ + +$str = 'hello + there'; + +/** + * This PHP DocBlock should be fine, even though there is a single space at the beginning. + * + * @var int $x + */ +$x = 1; + +?> + + + Foo + + +
    +
    +
    +
    +
    +
    + + + +"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// [space][space][space][tab]return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// Doc comments are indent with tabs and one space +//[tab]/** +//[tab][space]* + /** + * CVS revision for HTTP headers. + * + * @var string + * @access private + */ + /** + * + */ + +$str = 'hello + there'; + +/** + * This PHP DocBlock should be fine, even though there is a single space at the beginning. + * + * @var int $x + */ +$x = 1; + +?> + + + Foo + + +
    +
    +
    +
    +
    +
    + + + +"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// [space][space][space][tab]return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// Doc comments are indent with tabs and one space +//[tab]/** +//[tab][space]* + /** + * CVS revision for HTTP headers. + * + * @var string + * @access private + */ + /** + * + */ + +$str = 'hello + there'; + +/** + * This PHP DocBlock should be fine, even though there is a single space at the beginning. + * + * @var int $x + */ +$x = 1; + +?> + + + Foo + + +
    +
    +
    +
    +
    +
    + + + +"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// [space][space][space][tab]return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// Doc comments are indent with tabs and one space +//[tab]/** +//[tab][space]* + /** + * CVS revision for HTTP headers. + * + * @var string + * @access private + */ + /** + * + */ + +$str = 'hello + there'; + +/** + * This PHP DocBlock should be fine, even though there is a single space at the beginning. + * + * @var int $x + */ +$x = 1; + +?> + + + Foo + + +
    +
    +
    +
    +
    +
    + + + + + + + Foo + + +
    +
    +
    +
    +
    +
    + + + + + + + Foo + + +
    +
    +
    +
    +
    +
    + + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowSpaceIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + if ($testFile === 'DisallowSpaceIndentUnitTest.2.inc') { + return; + } + + $config->tabWidth = 4; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='DisallowSpaceIndentUnitTest.1.inc') + { + switch ($testFile) { + case 'DisallowSpaceIndentUnitTest.1.inc': + case 'DisallowSpaceIndentUnitTest.2.inc': + return [ + 5 => 1, + 9 => 1, + 15 => 1, + 22 => 1, + 24 => 1, + 30 => 1, + 35 => 1, + 50 => 1, + 55 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 60 => 1, + 65 => 1, + 66 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 70 => 1, + 73 => 1, + 77 => 1, + 81 => 1, + 104 => 1, + 105 => 1, + 106 => 1, + 107 => 1, + 108 => 1, + 110 => 1, + 111 => 1, + 112 => 1, + 114 => 1, + 115 => 1, + 117 => 1, + 118 => 1, + ]; + break; + case 'DisallowSpaceIndentUnitTest.3.inc': + return [ + 2 => 1, + 5 => 1, + 10 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + ]; + break; + case 'DisallowSpaceIndentUnitTest.js': + return [3 => 1]; + break; + case 'DisallowSpaceIndentUnitTest.css': + return [2 => 1]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.1.inc new file mode 100644 index 00000000..cf61177e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.1.inc @@ -0,0 +1,93 @@ + 'Czech republic', + 'România' => 'Romania', + 'Magyarország' => 'Hungary', +); + +$var = "$hello $there"; + +?> + + + Foo + + +
    +
    +
    +
    +
    +
    + + + + 'Czech republic', + 'România' => 'Romania', + 'Magyarország' => 'Hungary', +); + +$var = "$hello $there"; + +?> + + + Foo + + +
    +
    +
    +
    +
    +
    + + + + + + + Foo + + +
    +
    +
    +
    +
    +
    + + + + + + + Foo + + +
    +
    +
    +
    +
    +
    + + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowTabIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + $config->tabWidth = 4; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'DisallowTabIndentUnitTest.1.inc': + return [ + 5 => 2, + 9 => 1, + 15 => 1, + 20 => 2, + 21 => 1, + 22 => 2, + 23 => 1, + 24 => 2, + 31 => 1, + 32 => 2, + 33 => 2, + 41 => 1, + 42 => 1, + 43 => 1, + 44 => 1, + 45 => 1, + 46 => 1, + 47 => 1, + 48 => 1, + 54 => 1, + 55 => 1, + 56 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 79 => 1, + 80 => 1, + 81 => 1, + 82 => 1, + 83 => 1, + 85 => 1, + 86 => 1, + 87 => 1, + 89 => 1, + 90 => 1, + 92 => 1, + 93 => 1, + ]; + break; + case 'DisallowTabIndentUnitTest.2.inc': + return [ + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 19 => 1, + ]; + break; + case 'DisallowTabIndentUnitTest.js': + return [ + 3 => 1, + 5 => 1, + 6 => 1, + ]; + break; + case 'DisallowTabIndentUnitTest.css': + return [ + 1 => 1, + 2 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc new file mode 100644 index 00000000..22c611be --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc @@ -0,0 +1,17 @@ + + * @copyright 2018 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class IncrementDecrementSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='IncrementDecrementSpacingUnitTest.inc') + { + switch ($testFile) { + case 'IncrementDecrementSpacingUnitTest.inc': + case 'IncrementDecrementSpacingUnitTest.js': + return [ + 5 => 1, + 6 => 1, + 8 => 1, + 10 => 1, + 13 => 1, + 14 => 1, + 16 => 1, + 17 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc new file mode 100644 index 00000000..505cb6e4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc @@ -0,0 +1,79 @@ + + * @copyright 2006-2017 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LanguageConstructSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 7 => 1, + 11 => 1, + 15 => 1, + 19 => 1, + 23 => 1, + 27 => 1, + 30 => 1, + 33 => 1, + 34 => 1, + 35 => 1, + 36 => 1, + 38 => 1, + 44 => 1, + 45 => 1, + 46 => 2, + 49 => 1, + 51 => 1, + 59 => 1, + 61 => 1, + 63 => 1, + 67 => 1, + 70 => 1, + 71 => 1, + 75 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc new file mode 100644 index 00000000..caeb503a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc @@ -0,0 +1,1611 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false + +hello(); + } + + function hello() + { + echo 'hello'; +}//end hello() + + function hello2() + { + if (TRUE) { + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; + } + + while (TRUE) { + echo 'hello'; + } + + do { + echo 'hello'; + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
    +
    +
    +validate()) {
    +    $safe = $form->getSubmitValues();
    +}
    +?>
    +
    +open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* This is a T_COMMENT + * + * + * + */ + + /** This is a T_DOC_COMMENT + */ + + /* + This T_COMMENT has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + + + + doSomething( + function () { + echo 123; + } + ); + } +} + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +$myFunction = function() { + $a = 403; + if ($a === 404) { + $a = 403; + } +}; + +class Whatever +{ + protected $_protectedArray = array( + 'normalString' => 'That email address is already in use!', + 'offendingString' => <<<'STRING' +Each line of this string is always said to be at column 0, + no matter how many spaces are placed + at the beginning of each line +and the ending STRING on the next line is reported as having to be indented. +STRING + ); +} + +class MyClass +{ + public static function myFunction() + { + if (empty($keywords) === FALSE) { + $keywords = 'foo'; + $existing = 'foo'; + } + + return $keywords; + + }//end myFunction() + +}//end class + +$var = call_user_func( + $new_var = function () use (&$a) { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + } +); + +class AnonymousFn +{ + public function getAnonFn() + { + return array( + 'functions' => Array( + 'function1' => function ($a, $b, $c) { + $a = $b + $c; + $b = $c / 2; + return Array($a, $b, $c); + }, + ), + ); + } +} +?> + +
    + +
    +
    + +
    +
    + +
    + + "") { + $test = true; + } else { + $test = true; + } + } + ?> + + + +
    +
    +
    + +
    +
    +
    + + +

    some text

    + function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +if ($foo) { + foreach ($bar as $baz) { + if ($baz) { + ?> +
    +
    +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + +<?= CHtml::encode($this->pageTitle); ?> + +expects($this->at(2)) + ->with($this->callback( + function ($subject) + { + } + ) + ); + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +echo $string->append('foo') + ->appaend('bar') + ->appaend('baz') + ->outputUsing( + function () + { + } + ); + +echo PHP_EOL; + +switch ($arg) { + case 1: + break; + case 2: + if ($arg2 == 'foo') { + } + case 3: + default: + echo 'default'; +} + +if ($tokens[$stackPtr]['content']{0} === '#') { +} else if ($tokens[$stackPtr]['content']{0} === '/' + && $tokens[$stackPtr]['content']{1} === '/' +) { +} + +$var = call_user_func( + function() { + if ($foo) { + $new_var = function() { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + }; + } + } +); + +a( + function() { + $a = function() { + $b = false; + }; + true; + } +); + +$var = [ + [ + '1' => + function () { + return true; + }, + ], + [ + '1' => + function () { + return true; + }, + '2' => true, + ] +]; + +if ($foo) { + ?> +

    + self::_replaceKeywords($failingComment, $result), + 'screenshot' => Test::getScreenshotPath( + $projectid, + $result['class_name'], + ), + ); + +} + +$this->mockedDatabase + ->with( + $this->callback( + function () { + return; + } + ) + ); + +$this->subject->recordLogin(); + +function a() +{ + if (true) { + static::$a[$b] = + static::where($c) + ->where($c) + ->where( + function ($d) { + $d->whereNull(); + $d->orWhere(); + } + ) + ->first(); + + if (static::$a[$b] === null) { + static::$a[$b] = new static( + array( + 'a' => $a->id, + 'a' => $a->id, + ) + ); + } + } + + return static::$a[$b]; +} + +$foo->load( + array( + 'bar' => function ($baz) { + $baz->call(); + } + ) +); + +hello(); + +$foo = array_unique( + array_map( + function ($entry) { + return $entry * 2; + }, + array() + ) +); +bar($foo); + +class PHP_CodeSniffer_Tokenizers_JS +{ + + public $scopeOpeners = array( + T_CASE => array( + 'end' => array( + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + ), + 'strict' => true, + ), + ); +} + +echo $string-> + append('foo')-> + appaend('bar')-> + appaend('baz')-> + outputUsing( + function () + { + } + ); + +$str = 'the items I want to show are: ' . + implode( + ', ', + array('a', 'b', 'c') + ); + +echo $str; + +$str = 'foo' + . '1' + . '2'; + +echo $str; + +bar([ + 'foo' => foo(function () { + return 'foo'; + }) +]); + +$domains = array_unique( + array_map( + function ($url) { + $urlObject = new \Purl\Url($url); + return $urlObject->registerableDomain; + }, + $sites + ) +); + +return $domains; + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +if ($foo): +if ($bar) $foo = 1; +elseif ($baz) $foo = 2; +endif; + +$this + ->method(array( + 'foo' => 'bar', + ), 'arg', array( + 'foo' => 'bar', + )); + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +foo(); + +array( + 'key1' => function ($bar) { + return $bar; + }, + 'key2' => function ($foo) { + return $foo; + }, +); + +?> + + 1, + ]; +$c = 2; + +class foo +{ + public function get() + { + $foo = ['b' => 'c', + 'd' => [ + ['e' => 'f'] + ]]; + echo '42'; + + $foo = array('b' => 'c', + 'd' => array( + array('e' => 'f') + )); + echo '42'; + } +} + +switch ($foo) { + case 1: + return array(); + case 2: + return ''; + case 3: + return $function(); + case 4: + return $functionCall($param[0]); + case 5: + return array() + array(); // Array Merge + case 6: + // String connect + return $functionReturningString('') . $functionReturningString(array()); + case 7: + return functionCall( + $withMultiLineParam[0], + array(), + $functionReturningString( + $withMultiLineParam[1] + ) + ); + case 8: + return $param[0][0]; +} + +class Test { + + public + $foo + ,$bar + ,$baz = [ ] + ; + + public function wtfindent() { + } +} + +switch ($x) { + case 1: + return [1]; + default: + return [2]; +} + +switch ($foo) { + case self::FOO: + return $this->bar($gfoo, function ($id) { + return FOO::bar($id); + }, $values); + case self::BAR: + $values = $this->bar($foo, $values); + break; +} + +$var = array( + 'long description' => + array(0, 'something'), + 'another long description' => + array(1, "something else") +); + +$services = array( + 'service 1' => + Mockery::mock('class 1') + ->shouldReceive('setFilter')->once() + ->shouldReceive('getNbResults')->atLeast()->once() + ->shouldReceive('getSlice')->once()->andReturn(array()) + ->getMock(), + 'service 2' => + Mockery::mock('class 2') + ->shouldReceive('__invoke')->once() + ->getMock() +); + +class Foo +{ + public function setUp() + { + $this->foo = new class { + public $name = 'Some value'; + }; + } +} + +try { + foo(); +} catch (\Exception $e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +if ($foo) { + foo(); +} else if ($e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} else { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +switch ($parameter) { + case null: + return [ + 'foo' => in_array( + 'foo', + [] + ), + ]; + + default: + return []; +} + +class SomeClass +{ + public function someFunc() + { + a(function () { + echo "a"; + })->b(function () { + echo "b"; + }); + + if (true) { + echo "c"; + } + echo "d"; + } +} + +$params = self::validate_parameters(self::read_competency_framework_parameters(), + array( + 'id' => $id, + )); + +$framework = api::read_framework($params['id']); +self::validate_context($framework->get_context()); +$output = $PAGE->get_renderer('tool_lp'); + +class Test123 +{ + protected static + $prop1 = [ + 'testA' => 123, + ], + $prop2 = [ + 'testB' => 456, + ]; + + protected static + $prop3 = array( + 'testA' => 123, + ), + $prop4 = array( + 'testB' => 456, + ); + + protected static $prop5; +} + +$foo = foo( + function () { + $foo->debug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +if (somethingIsTrue()) { + ?> +
    + +
    + bar(foo(function () { + }), foo(function () { + })); + +echo 'foo'; + +class Test { + + public function a() { + ?>adebug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +function test() +{ + $array = []; + foreach ($array as $data) { + [ + 'key1' => $var1, + 'key2' => $var2, + ] = $data; + foreach ($var1 as $method) { + echo $method . $var2; + } + } +} + +switch ($a) { + case 0: + $a = function () { + }; + case 1: + break; +} + +class Test +{ + public function __construct() + { +if (false) { +echo 0; + } + } +} + +return [ + 'veryLongKeySoIWantToMakeALineBreak' + => 'veryLonValueSoIWantToMakeALineBreak', + + 'someOtherKey' => [ + 'someValue' + ], + + 'arrayWithArraysInThere' => [ + ['Value1', 'Value1'] + ], +]; + +switch ($sContext) { + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +array_map( + static function ( $item ) { + echo $item; + }, + $some_array +); + +/** + * Comment. + */ +$a(function () use ($app) { + echo 'hi'; +})(); + +$app->run(); + +function foo() +{ + $foo('some + long description', function () { + }); + + $foo('some + long + description', function () { + }); + + $foo( +'some long description', function () { + }); +} + +switch ( $a ) { +case 'a': + $b = 2; + /** + * A comment. + */ + apply_filter( 'something', $b ); + break; + +case 'aa': + $b = 2; + /* + * A comment. + */ + apply_filter( 'something', $b ); + break; + +case 'b': + $b = 3; +?> + + + + + +
    + +
    + +
    + +
    + + +
    + + + +
    + [ + ], + 'b' => <<<'FOO' +foo; +FOO + ], + $a, +]; + +$query = Model::query() + ->when($a, function () { + static $b = ''; + }); + +$result = array_map( + static fn(int $number) : int => $number + 1, + $numbers +); + +$a = $a === true ? [ + 'a' => 1, + ] : [ + 'a' => 100, +]; + +return [ + Url::make('View Song', fn($song) => $song->url()) + ->onlyOnDetail(), + + new Panel('Information', [ + Text::make('Title') + ]), +]; + +echo $string?->append('foo') + ?->outputUsing(); + +// phpcs:set Generic.WhiteSpace.ScopeIndent exact true +echo $string?->append('foo') + ?->outputUsing(); +// phpcs:set Generic.WhiteSpace.ScopeIndent exact false + +if (true) { + ?> null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ($value) { + '' => null, +false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ( + $value + ) { + '' => null, + false + => false, + 1, + 2, + 3 => true, + default => +$value, +}; + +function toString(): string +{ + return sprintf( + '%s', + match ($type) { + 'foo' => 'bar', + }, + ); +} + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + }, + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + $list2 = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } + ]; + } + } +]; + +$foo = match ($type) { + 'a' => [ + 'aa' => 'DESC', + 'ab' => 'DESC', + ], + 'b' => [ + 'ba' => 'DESC', + 'bb' => 'DESC', + ], + default => [ + 'da' => 'DESC', + ], +}; + +$a = [ + 'a' => [ + 'a' => fn () => foo() + ], + 'a' => [ + 'a' => 'a', + ] +]; + +switch ($foo) { + case 'a': + $foo = match ($foo) { + 'bar' => 'custom_1', + default => 'a' + }; + return $foo; + case 'b': + return match ($foo) { + 'bar' => 'custom_1', + default => 'b' + }; + default: + return 'default'; +} + +/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */ +?> + + + + + + + <<<'INTRO' + lorem ipsum + INTRO, + 'em' => [ + [ + '', + ], + ], + 'abc' => [ + 'a' => 'wop wop', + 'b' => 'ola ola.', + ], +]; + +echo "" diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed new file mode 100644 index 00000000..6fd9e5fd --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed @@ -0,0 +1,1611 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false + +hello(); + } + + function hello() + { + echo 'hello'; + }//end hello() + + function hello2() + { + if (TRUE) { + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; + } + + while (TRUE) { + echo 'hello'; + } + + do { + echo 'hello'; + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
    +
    +
    +validate()) {
    +    $safe = $form->getSubmitValues();
    +}
    +?>
    +
    +open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* This is a T_COMMENT + * + * + * + */ + + /** This is a T_DOC_COMMENT + */ + + /* + This T_COMMENT has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + + + + doSomething( + function () { + echo 123; + } + ); + } +} + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +$myFunction = function() { + $a = 403; + if ($a === 404) { + $a = 403; + } +}; + +class Whatever +{ + protected $_protectedArray = array( + 'normalString' => 'That email address is already in use!', + 'offendingString' => <<<'STRING' +Each line of this string is always said to be at column 0, + no matter how many spaces are placed + at the beginning of each line +and the ending STRING on the next line is reported as having to be indented. +STRING + ); +} + +class MyClass +{ + public static function myFunction() + { + if (empty($keywords) === FALSE) { + $keywords = 'foo'; + $existing = 'foo'; + } + + return $keywords; + + }//end myFunction() + +}//end class + +$var = call_user_func( + $new_var = function () use (&$a) { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + } +); + +class AnonymousFn +{ + public function getAnonFn() + { + return array( + 'functions' => Array( + 'function1' => function ($a, $b, $c) { + $a = $b + $c; + $b = $c / 2; + return Array($a, $b, $c); + }, + ), + ); + } +} +?> + +
    + +
    +
    + +
    +
    + +
    + + "") { + $test = true; + } else { + $test = true; + } + } + ?> + + + +
    +
    +
    + +
    +
    +
    + + +

    some text

    + function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +if ($foo) { + foreach ($bar as $baz) { + if ($baz) { + ?> +
    +
    +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + +<?= CHtml::encode($this->pageTitle); ?> + +expects($this->at(2)) + ->with($this->callback( + function ($subject) + { + } + ) + ); + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +echo $string->append('foo') + ->appaend('bar') + ->appaend('baz') + ->outputUsing( + function () + { + } + ); + +echo PHP_EOL; + +switch ($arg) { + case 1: + break; + case 2: + if ($arg2 == 'foo') { + } + case 3: + default: + echo 'default'; +} + +if ($tokens[$stackPtr]['content']{0} === '#') { +} else if ($tokens[$stackPtr]['content']{0} === '/' + && $tokens[$stackPtr]['content']{1} === '/' +) { +} + +$var = call_user_func( + function() { + if ($foo) { + $new_var = function() { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + }; + } + } +); + +a( + function() { + $a = function() { + $b = false; + }; + true; + } +); + +$var = [ + [ + '1' => + function () { + return true; + }, + ], + [ + '1' => + function () { + return true; + }, + '2' => true, + ] +]; + +if ($foo) { + ?> +

    + self::_replaceKeywords($failingComment, $result), + 'screenshot' => Test::getScreenshotPath( + $projectid, + $result['class_name'], + ), + ); + +} + +$this->mockedDatabase + ->with( + $this->callback( + function () { + return; + } + ) + ); + +$this->subject->recordLogin(); + +function a() +{ + if (true) { + static::$a[$b] = + static::where($c) + ->where($c) + ->where( + function ($d) { + $d->whereNull(); + $d->orWhere(); + } + ) + ->first(); + + if (static::$a[$b] === null) { + static::$a[$b] = new static( + array( + 'a' => $a->id, + 'a' => $a->id, + ) + ); + } + } + + return static::$a[$b]; +} + +$foo->load( + array( + 'bar' => function ($baz) { + $baz->call(); + } + ) +); + +hello(); + +$foo = array_unique( + array_map( + function ($entry) { + return $entry * 2; + }, + array() + ) +); +bar($foo); + +class PHP_CodeSniffer_Tokenizers_JS +{ + + public $scopeOpeners = array( + T_CASE => array( + 'end' => array( + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + ), + 'strict' => true, + ), + ); +} + +echo $string-> + append('foo')-> + appaend('bar')-> + appaend('baz')-> + outputUsing( + function () + { + } + ); + +$str = 'the items I want to show are: ' . + implode( + ', ', + array('a', 'b', 'c') + ); + +echo $str; + +$str = 'foo' + . '1' + . '2'; + +echo $str; + +bar([ + 'foo' => foo(function () { + return 'foo'; + }) +]); + +$domains = array_unique( + array_map( + function ($url) { + $urlObject = new \Purl\Url($url); + return $urlObject->registerableDomain; + }, + $sites + ) +); + +return $domains; + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +if ($foo): + if ($bar) $foo = 1; + elseif ($baz) $foo = 2; +endif; + +$this + ->method(array( + 'foo' => 'bar', + ), 'arg', array( + 'foo' => 'bar', + )); + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +foo(); + +array( + 'key1' => function ($bar) { + return $bar; + }, + 'key2' => function ($foo) { + return $foo; + }, +); + +?> + + 1, + ]; +$c = 2; + +class foo +{ + public function get() + { + $foo = ['b' => 'c', + 'd' => [ + ['e' => 'f'] + ]]; + echo '42'; + + $foo = array('b' => 'c', + 'd' => array( + array('e' => 'f') + )); + echo '42'; + } +} + +switch ($foo) { + case 1: + return array(); + case 2: + return ''; + case 3: + return $function(); + case 4: + return $functionCall($param[0]); + case 5: + return array() + array(); // Array Merge + case 6: + // String connect + return $functionReturningString('') . $functionReturningString(array()); + case 7: + return functionCall( + $withMultiLineParam[0], + array(), + $functionReturningString( + $withMultiLineParam[1] + ) + ); + case 8: + return $param[0][0]; +} + +class Test { + + public + $foo + ,$bar + ,$baz = [ ] + ; + + public function wtfindent() { + } +} + +switch ($x) { + case 1: + return [1]; + default: + return [2]; +} + +switch ($foo) { + case self::FOO: + return $this->bar($gfoo, function ($id) { + return FOO::bar($id); + }, $values); + case self::BAR: + $values = $this->bar($foo, $values); + break; +} + +$var = array( + 'long description' => + array(0, 'something'), + 'another long description' => + array(1, "something else") +); + +$services = array( + 'service 1' => + Mockery::mock('class 1') + ->shouldReceive('setFilter')->once() + ->shouldReceive('getNbResults')->atLeast()->once() + ->shouldReceive('getSlice')->once()->andReturn(array()) + ->getMock(), + 'service 2' => + Mockery::mock('class 2') + ->shouldReceive('__invoke')->once() + ->getMock() +); + +class Foo +{ + public function setUp() + { + $this->foo = new class { + public $name = 'Some value'; + }; + } +} + +try { + foo(); +} catch (\Exception $e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +if ($foo) { + foo(); +} else if ($e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} else { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +switch ($parameter) { + case null: + return [ + 'foo' => in_array( + 'foo', + [] + ), + ]; + + default: + return []; +} + +class SomeClass +{ + public function someFunc() + { + a(function () { + echo "a"; + })->b(function () { + echo "b"; + }); + + if (true) { + echo "c"; + } + echo "d"; + } +} + +$params = self::validate_parameters(self::read_competency_framework_parameters(), + array( + 'id' => $id, + )); + +$framework = api::read_framework($params['id']); +self::validate_context($framework->get_context()); +$output = $PAGE->get_renderer('tool_lp'); + +class Test123 +{ + protected static + $prop1 = [ + 'testA' => 123, + ], + $prop2 = [ + 'testB' => 456, + ]; + + protected static + $prop3 = array( + 'testA' => 123, + ), + $prop4 = array( + 'testB' => 456, + ); + + protected static $prop5; +} + +$foo = foo( + function () { + $foo->debug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +if (somethingIsTrue()) { + ?> +
    + +
    + bar(foo(function () { + }), foo(function () { + })); + +echo 'foo'; + +class Test { + + public function a() { + ?>adebug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +function test() +{ + $array = []; + foreach ($array as $data) { + [ + 'key1' => $var1, + 'key2' => $var2, + ] = $data; + foreach ($var1 as $method) { + echo $method . $var2; + } + } +} + +switch ($a) { + case 0: + $a = function () { + }; + case 1: + break; +} + +class Test +{ + public function __construct() + { + if (false) { + echo 0; + } + } +} + +return [ + 'veryLongKeySoIWantToMakeALineBreak' + => 'veryLonValueSoIWantToMakeALineBreak', + + 'someOtherKey' => [ + 'someValue' + ], + + 'arrayWithArraysInThere' => [ + ['Value1', 'Value1'] + ], +]; + +switch ($sContext) { + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +array_map( + static function ( $item ) { + echo $item; + }, + $some_array +); + +/** + * Comment. + */ +$a(function () use ($app) { + echo 'hi'; +})(); + +$app->run(); + +function foo() +{ + $foo('some + long description', function () { + }); + + $foo('some + long + description', function () { + }); + + $foo( + 'some long description', function () { + }); +} + +switch ( $a ) { + case 'a': + $b = 2; + /** + * A comment. + */ + apply_filter( 'something', $b ); + break; + + case 'aa': + $b = 2; + /* + * A comment. + */ + apply_filter( 'something', $b ); + break; + + case 'b': + $b = 3; + ?> + + + + + +
    + +
    + +
    + +
    + + +
    + + + +
    + [ + ], + 'b' => <<<'FOO' +foo; +FOO + ], + $a, +]; + +$query = Model::query() + ->when($a, function () { + static $b = ''; + }); + +$result = array_map( + static fn(int $number) : int => $number + 1, + $numbers +); + +$a = $a === true ? [ + 'a' => 1, + ] : [ + 'a' => 100, +]; + +return [ + Url::make('View Song', fn($song) => $song->url()) + ->onlyOnDetail(), + + new Panel('Information', [ + Text::make('Title') + ]), +]; + +echo $string?->append('foo') + ?->outputUsing(); + +// phpcs:set Generic.WhiteSpace.ScopeIndent exact true +echo $string?->append('foo') + ?->outputUsing(); +// phpcs:set Generic.WhiteSpace.ScopeIndent exact false + +if (true) { + ?> null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ($value) { + '' => null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ( + $value + ) { + '' => null, + false + => false, + 1, + 2, + 3 => true, + default => + $value, +}; + +function toString(): string +{ + return sprintf( + '%s', + match ($type) { + 'foo' => 'bar', + }, + ); +} + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + }, + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + $list2 = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } + ]; + } + } +]; + +$foo = match ($type) { + 'a' => [ + 'aa' => 'DESC', + 'ab' => 'DESC', + ], + 'b' => [ + 'ba' => 'DESC', + 'bb' => 'DESC', + ], + default => [ + 'da' => 'DESC', + ], +}; + +$a = [ + 'a' => [ + 'a' => fn () => foo() + ], + 'a' => [ + 'a' => 'a', + ] +]; + +switch ($foo) { + case 'a': + $foo = match ($foo) { + 'bar' => 'custom_1', + default => 'a' + }; + return $foo; + case 'b': + return match ($foo) { + 'bar' => 'custom_1', + default => 'b' + }; + default: + return 'default'; +} + +/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */ +?> + + + + + + + <<<'INTRO' + lorem ipsum + INTRO, + 'em' => [ + [ + '', + ], + ], + 'abc' => [ + 'a' => 'wop wop', + 'b' => 'ola ola.', + ], +]; + +echo "" diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js new file mode 100644 index 00000000..2195bfb9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js @@ -0,0 +1,239 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false +var script = document.createElement('script'); +script.onload = function() +{ + clearTimeout(t); + script456.onload = null; + script.onreadystatechange = null; + callback.call(this); + +}; + +this.callbacks[type] = { + namespaces: {}, +others: [] +}; + +blah = function() +{ + print something; + + } + +test(blah, function() { + print something; +}); + +var test = [{x: 10}]; +var test = [{ + x: 10, + y: { + b14h: 12, + 'b14h': 12 + }, + z: 23 +}]; + +Viper.prototype = { + + _removeEvents: function(elem) + { + if (!elem) { + elem = this.element; + } + + ViperUtil.removeEvent(elem, '.' + this.getEventNamespace()); + + } + +}; + +this.init = function(data) { + if (_pageListWdgt) { + GUI.getWidget('changedPagesList').addItemClickedCallback( + function(itemid, target) { + draftChangeTypeClicked( + itemid, + target, + { + reviewData: _reviewData, + pageid: itemid + } + ); + } + ); + }//end if + +}; + +a( + function() { + var _a = function() { + b = false; + + }; + true + } +); + +(function() { + a = function() { + a(function() { + if (true) { + a = true; + } + }); + + a( + function() { + if (true) { + if (true) { + a = true; + } + } + } + ); + + a( + function() { + if (true) { + a = true; + } + } + ); + + }; + +})(); + +a.prototype = { + + a: function() + { + var currentSize = null; + ViperUtil.addEvent( + header, + 'safedblclick', + function() {}, + ); + + if (topContent) { + ViperUtil.addClass(topContent, 'Viper-popup-top'); + main.appendChild(topContent); + } + + ViperUtil.addClass(midContent, 'Viper-popup-content'); + main.appendChild(midContent); + } + +}; + +a.prototype = { + + a: function() + { + ViperUtil.addClass(midContent, 'Viper-popup-content'); + main.appendChild(midContent); + + var mouseUpAction = function() {}; + var preventMouseUp = false; + var self = this; + if (clickAction) { + } + } + +}; + +a.prototype = { + + a: function() + { + var a = function() { + var a = 'foo'; + }; + + if (true) { + } + + }, + + b: function() + { + ViperUtil.addEvent( + function() { + if (fullScreen !== true) { + currentSize = { + }; + + showfullScreen(); + } + } + ); + + }, + + c: function() + { + this.a( + { + a: function() { + form.onsubmit = function() { + return false; + }; + + var a = true; + } + } + ); + + } + +}; + +a.prototype = { + init: function() + {}, + + _b: function() + { + } + +}; + +for (var i = 0; i < 10; i++) { + var foo = {foo:{'a':'b', + 'c':'d'}}; +} + +class TestOk +{ + destroy() + { + setTimeout(a, 1000); + + if (typeof self.callbackOnClose === "function") { + self.callbackOnClose(); + } + } +} + +class TestBad +{ + destroy() + { + setTimeout(function () { + return; + }, 1000); + + if (typeof self.callbackOnClose === "function") { + self.callbackOnClose(); + } + } +} + +( function( $ ) { + foo(function( value ) { + value.bind( function( newval ) { + $( '#bar' ).html( newval ); + } ); + } )( jQuery ); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js.fixed new file mode 100644 index 00000000..d4bf409b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js.fixed @@ -0,0 +1,239 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false +var script = document.createElement('script'); +script.onload = function() +{ + clearTimeout(t); + script456.onload = null; + script.onreadystatechange = null; + callback.call(this); + +}; + +this.callbacks[type] = { + namespaces: {}, + others: [] +}; + +blah = function() +{ + print something; + +} + +test(blah, function() { + print something; +}); + +var test = [{x: 10}]; +var test = [{ + x: 10, + y: { + b14h: 12, + 'b14h': 12 + }, + z: 23 +}]; + +Viper.prototype = { + + _removeEvents: function(elem) + { + if (!elem) { + elem = this.element; + } + + ViperUtil.removeEvent(elem, '.' + this.getEventNamespace()); + + } + +}; + +this.init = function(data) { + if (_pageListWdgt) { + GUI.getWidget('changedPagesList').addItemClickedCallback( + function(itemid, target) { + draftChangeTypeClicked( + itemid, + target, + { + reviewData: _reviewData, + pageid: itemid + } + ); + } + ); + }//end if + +}; + +a( + function() { + var _a = function() { + b = false; + + }; + true + } +); + +(function() { + a = function() { + a(function() { + if (true) { + a = true; + } + }); + + a( + function() { + if (true) { + if (true) { + a = true; + } + } + } + ); + + a( + function() { + if (true) { + a = true; + } + } + ); + + }; + +})(); + +a.prototype = { + + a: function() + { + var currentSize = null; + ViperUtil.addEvent( + header, + 'safedblclick', + function() {}, + ); + + if (topContent) { + ViperUtil.addClass(topContent, 'Viper-popup-top'); + main.appendChild(topContent); + } + + ViperUtil.addClass(midContent, 'Viper-popup-content'); + main.appendChild(midContent); + } + +}; + +a.prototype = { + + a: function() + { + ViperUtil.addClass(midContent, 'Viper-popup-content'); + main.appendChild(midContent); + + var mouseUpAction = function() {}; + var preventMouseUp = false; + var self = this; + if (clickAction) { + } + } + +}; + +a.prototype = { + + a: function() + { + var a = function() { + var a = 'foo'; + }; + + if (true) { + } + + }, + + b: function() + { + ViperUtil.addEvent( + function() { + if (fullScreen !== true) { + currentSize = { + }; + + showfullScreen(); + } + } + ); + + }, + + c: function() + { + this.a( + { + a: function() { + form.onsubmit = function() { + return false; + }; + + var a = true; + } + } + ); + + } + +}; + +a.prototype = { + init: function() + {}, + + _b: function() + { + } + +}; + +for (var i = 0; i < 10; i++) { + var foo = {foo:{'a':'b', + 'c':'d'}}; +} + +class TestOk +{ + destroy() + { + setTimeout(a, 1000); + + if (typeof self.callbackOnClose === "function") { + self.callbackOnClose(); + } + } +} + +class TestBad +{ + destroy() + { + setTimeout(function () { + return; + }, 1000); + + if (typeof self.callbackOnClose === "function") { + self.callbackOnClose(); + } + } +} + +( function( $ ) { + foo(function( value ) { + value.bind( function( newval ) { + $( '#bar' ).html( newval ); + } ); + } )( jQuery ); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc new file mode 100644 index 00000000..b8bf72ad --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc @@ -0,0 +1,1611 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent true + +hello(); + } + + function hello() + { + echo 'hello'; +}//end hello() + + function hello2() + { + if (TRUE) { + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; + } + + while (TRUE) { + echo 'hello'; + } + + do { + echo 'hello'; + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
    +
    +
    +validate()) {
    +	$safe = $form->getSubmitValues();
    +}
    +?>
    +
    +open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* This is a T_COMMENT + * + * + * + */ + + /** This is a T_DOC_COMMENT + */ + + /* + This T_COMMENT has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + + + + doSomething( + function () { + echo 123; + } + ); + } +} + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +$myFunction = function() { + $a = 403; + if ($a === 404) { + $a = 403; + } +}; + +class Whatever +{ + protected $_protectedArray = array( + 'normalString' => 'That email address is already in use!', + 'offendingString' => <<<'STRING' +Each line of this string is always said to be at column 0, + no matter how many spaces are placed + at the beginning of each line +and the ending STRING on the next line is reported as having to be indented. +STRING + ); +} + +class MyClass +{ + public static function myFunction() + { + if (empty($keywords) === FALSE) { + $keywords = 'foo'; + $existing = 'foo'; + } + + return $keywords; + + }//end myFunction() + +}//end class + +$var = call_user_func( + $new_var = function () use (&$a) { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + } +); + +class AnonymousFn +{ + public function getAnonFn() + { + return array( + 'functions' => Array( + 'function1' => function ($a, $b, $c) { + $a = $b + $c; + $b = $c / 2; + return Array($a, $b, $c); + }, + ), + ); + } +} +?> + +
    + +
    +
    + +
    +
    + +
    + + "") { + $test = true; + } else { + $test = true; + } + } + ?> + + + +
    +
    +
    + +
    +
    +
    + + +

    some text

    + function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +if ($foo) { + foreach ($bar as $baz) { + if ($baz) { + ?> +
    +
    +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + +<?= CHtml::encode($this->pageTitle); ?> + +expects($this->at(2)) + ->with($this->callback( + function ($subject) + { + } + ) + ); + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +echo $string->append('foo') + ->appaend('bar') + ->appaend('baz') + ->outputUsing( + function () + { + } + ); + +echo PHP_EOL; + +switch ($arg) { + case 1: + break; + case 2: + if ($arg2 == 'foo') { + } + case 3: + default: + echo 'default'; +} + +if ($tokens[$stackPtr]['content']{0} === '#') { +} else if ($tokens[$stackPtr]['content']{0} === '/' + && $tokens[$stackPtr]['content']{1} === '/' +) { +} + +$var = call_user_func( + function() { + if ($foo) { + $new_var = function() { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + }; + } + } +); + +a( + function() { + $a = function() { + $b = false; + }; + true; + } +); + +$var = [ + [ + '1' => + function () { + return true; + }, + ], + [ + '1' => + function () { + return true; + }, + '2' => true, + ] +]; + +if ($foo) { + ?> +

    + self::_replaceKeywords($failingComment, $result), + 'screenshot' => Test::getScreenshotPath( + $projectid, + $result['class_name'], + ), + ); + +} + +$this->mockedDatabase + ->with( + $this->callback( + function () { + return; + } + ) + ); + +$this->subject->recordLogin(); + +function a() +{ + if (true) { + static::$a[$b] = + static::where($c) + ->where($c) + ->where( + function ($d) { + $d->whereNull(); + $d->orWhere(); + } + ) + ->first(); + + if (static::$a[$b] === null) { + static::$a[$b] = new static( + array( + 'a' => $a->id, + 'a' => $a->id, + ) + ); + } + } + + return static::$a[$b]; +} + +$foo->load( + array( + 'bar' => function ($baz) { + $baz->call(); + } + ) +); + +hello(); + +$foo = array_unique( + array_map( + function ($entry) { + return $entry * 2; + }, + array() + ) +); +bar($foo); + +class PHP_CodeSniffer_Tokenizers_JS +{ + + public $scopeOpeners = array( + T_CASE => array( + 'end' => array( + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + ), + 'strict' => true, + ), + ); +} + +echo $string-> + append('foo')-> + appaend('bar')-> + appaend('baz')-> + outputUsing( + function () + { + } + ); + +$str = 'the items I want to show are: ' . + implode( + ', ', + array('a', 'b', 'c') + ); + +echo $str; + +$str = 'foo' + . '1' + . '2'; + +echo $str; + +bar([ + 'foo' => foo(function () { + return 'foo'; + }) +]); + +$domains = array_unique( + array_map( + function ($url) { + $urlObject = new \Purl\Url($url); + return $urlObject->registerableDomain; + }, + $sites + ) +); + +return $domains; + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +if ($foo): +if ($bar) $foo = 1; +elseif ($baz) $foo = 2; +endif; + +$this + ->method(array( + 'foo' => 'bar', + ), 'arg', array( + 'foo' => 'bar', + )); + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +foo(); + +array( + 'key1' => function ($bar) { + return $bar; + }, + 'key2' => function ($foo) { + return $foo; + }, +); + +?> + + 1, + ]; +$c = 2; + +class foo +{ + public function get() + { + $foo = ['b' => 'c', + 'd' => [ + ['e' => 'f'] + ]]; + echo '42'; + + $foo = array('b' => 'c', + 'd' => array( + array('e' => 'f') + )); + echo '42'; + } +} + +switch ($foo) { + case 1: + return array(); + case 2: + return ''; + case 3: + return $function(); + case 4: + return $functionCall($param[0]); + case 5: + return array() + array(); // Array Merge + case 6: + // String connect + return $functionReturningString('') . $functionReturningString(array()); + case 7: + return functionCall( + $withMultiLineParam[0], + array(), + $functionReturningString( + $withMultiLineParam[1] + ) + ); + case 8: + return $param[0][0]; +} + +class Test { + + public + $foo + ,$bar + ,$baz = [ ] + ; + + public function wtfindent() { + } +} + +switch ($x) { + case 1: + return [1]; + default: + return [2]; +} + +switch ($foo) { + case self::FOO: + return $this->bar($gfoo, function ($id) { + return FOO::bar($id); + }, $values); + case self::BAR: + $values = $this->bar($foo, $values); + break; +} + +$var = array( + 'long description' => + array(0, 'something'), + 'another long description' => + array(1, "something else") +); + +$services = array( + 'service 1' => + Mockery::mock('class 1') + ->shouldReceive('setFilter')->once() + ->shouldReceive('getNbResults')->atLeast()->once() + ->shouldReceive('getSlice')->once()->andReturn(array()) + ->getMock(), + 'service 2' => + Mockery::mock('class 2') + ->shouldReceive('__invoke')->once() + ->getMock() +); + +class Foo +{ + public function setUp() + { + $this->foo = new class { + public $name = 'Some value'; + }; + } +} + +try { + foo(); +} catch (\Exception $e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +if ($foo) { + foo(); +} else if ($e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} else { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +switch ($parameter) { + case null: + return [ + 'foo' => in_array( + 'foo', + [] + ), + ]; + + default: + return []; +} + +class SomeClass +{ + public function someFunc() + { + a(function () { + echo "a"; + })->b(function () { + echo "b"; + }); + + if (true) { + echo "c"; + } + echo "d"; + } +} + +$params = self::validate_parameters(self::read_competency_framework_parameters(), + array( + 'id' => $id, + )); + +$framework = api::read_framework($params['id']); +self::validate_context($framework->get_context()); +$output = $PAGE->get_renderer('tool_lp'); + +class Test123 +{ + protected static + $prop1 = [ + 'testA' => 123, + ], + $prop2 = [ + 'testB' => 456, + ]; + + protected static + $prop3 = array( + 'testA' => 123, + ), + $prop4 = array( + 'testB' => 456, + ); + + protected static $prop5; +} + +$foo = foo( + function () { + $foo->debug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +if (somethingIsTrue()) { + ?> +
    + +
    + bar(foo(function () { + }), foo(function () { + })); + +echo 'foo'; + +class Test { + + public function a() { + ?>adebug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +function test() +{ + $array = []; + foreach ($array as $data) { + [ + 'key1' => $var1, + 'key2' => $var2, + ] = $data; + foreach ($var1 as $method) { + echo $method . $var2; + } + } +} + +switch ($a) { + case 0: + $a = function () { + }; + case 1: + break; +} + +class Test +{ + public function __construct() + { +if (false) { +echo 0; + } + } +} + +return [ + 'veryLongKeySoIWantToMakeALineBreak' + => 'veryLonValueSoIWantToMakeALineBreak', + + 'someOtherKey' => [ + 'someValue' + ], + + 'arrayWithArraysInThere' => [ + ['Value1', 'Value1'] + ], +]; + +switch ($sContext) { + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +array_map( + static function ( $item ) { + echo $item; + }, + $some_array +); + +/** + * Comment. + */ +$a(function () use ($app) { + echo 'hi'; +})(); + +$app->run(); + +function foo() +{ + $foo('some + long description', function () { + }); + + $foo('some + long + description', function () { + }); + + $foo( +'some long description', function () { + }); +} + +switch ( $a ) { +case 'a': + $b = 2; + /** + * A comment. + */ + apply_filter( 'something', $b ); + break; + +case 'aa': + $b = 2; + /* + * A comment. + */ + apply_filter( 'something', $b ); + break; + +case 'b': + $b = 3; +?> + + + + + +
    + +
    + +
    + +
    + + +
    + + + +
    + [ + ], + 'b' => <<<'FOO' +foo; +FOO + ], + $a, +]; + +$query = Model::query() + ->when($a, function () { + static $b = ''; + }); + +$result = array_map( + static fn(int $number) : int => $number + 1, + $numbers +); + +$a = $a === true ? [ + 'a' => 1, + ] : [ + 'a' => 100, +]; + +return [ + Url::make('View Song', fn($song) => $song->url()) + ->onlyOnDetail(), + + new Panel('Information', [ + Text::make('Title') + ]), +]; + +echo $string?->append('foo') + ?->outputUsing(); + +// phpcs:set Generic.WhiteSpace.ScopeIndent exact true +echo $string?->append('foo') + ?->outputUsing(); +// phpcs:set Generic.WhiteSpace.ScopeIndent exact false + +if (true) { + ?> null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ($value) { + '' => null, +false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ( + $value + ) { + '' => null, + false + => false, + 1, + 2, + 3 => true, + default => +$value, +}; + +function toString(): string +{ + return sprintf( + '%s', + match ($type) { + 'foo' => 'bar', + }, + ); +} + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + }, + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + $list2 = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } + ]; + } + } +]; + +$foo = match ($type) { + 'a' => [ + 'aa' => 'DESC', + 'ab' => 'DESC', + ], + 'b' => [ + 'ba' => 'DESC', + 'bb' => 'DESC', + ], + default => [ + 'da' => 'DESC', + ], +}; + +$a = [ + 'a' => [ + 'a' => fn () => foo() + ], + 'a' => [ + 'a' => 'a', + ] +]; + +switch ($foo) { + case 'a': + $foo = match ($foo) { + 'bar' => 'custom_1', + default => 'a' + }; + return $foo; + case 'b': + return match ($foo) { + 'bar' => 'custom_1', + default => 'b' + }; + default: + return 'default'; +} + +/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */ +?> + + + + + + + <<<'INTRO' + lorem ipsum + INTRO, + 'em' => [ + [ + '', + ], + ], + 'abc' => [ + 'a' => 'wop wop', + 'b' => 'ola ola.', + ], +]; + +echo "" diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc.fixed new file mode 100644 index 00000000..83324391 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc.fixed @@ -0,0 +1,1611 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent true + +hello(); + } + + function hello() + { + echo 'hello'; + }//end hello() + + function hello2() + { + if (TRUE) { + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; + } + + while (TRUE) { + echo 'hello'; + } + + do { + echo 'hello'; + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
    +
    +
    +validate()) {
    +	$safe = $form->getSubmitValues();
    +}
    +?>
    +
    +open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* This is a T_COMMENT + * + * + * + */ + + /** This is a T_DOC_COMMENT + */ + + /* + This T_COMMENT has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + + + + doSomething( + function () { + echo 123; + } + ); + } +} + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +$myFunction = function() { + $a = 403; + if ($a === 404) { + $a = 403; + } +}; + +class Whatever +{ + protected $_protectedArray = array( + 'normalString' => 'That email address is already in use!', + 'offendingString' => <<<'STRING' +Each line of this string is always said to be at column 0, + no matter how many spaces are placed + at the beginning of each line +and the ending STRING on the next line is reported as having to be indented. +STRING + ); +} + +class MyClass +{ + public static function myFunction() + { + if (empty($keywords) === FALSE) { + $keywords = 'foo'; + $existing = 'foo'; + } + + return $keywords; + + }//end myFunction() + +}//end class + +$var = call_user_func( + $new_var = function () use (&$a) { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + } +); + +class AnonymousFn +{ + public function getAnonFn() + { + return array( + 'functions' => Array( + 'function1' => function ($a, $b, $c) { + $a = $b + $c; + $b = $c / 2; + return Array($a, $b, $c); + }, + ), + ); + } +} +?> + +
    + +
    +
    + +
    +
    + +
    + + "") { + $test = true; + } else { + $test = true; + } + } + ?> + + + +
    +
    +
    + +
    +
    +
    + + +

    some text

    + function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +if ($foo) { + foreach ($bar as $baz) { + if ($baz) { + ?> +
    +
    +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + +<?= CHtml::encode($this->pageTitle); ?> + +expects($this->at(2)) + ->with($this->callback( + function ($subject) + { + } + ) + ); + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +echo $string->append('foo') + ->appaend('bar') + ->appaend('baz') + ->outputUsing( + function () + { + } + ); + +echo PHP_EOL; + +switch ($arg) { + case 1: + break; + case 2: + if ($arg2 == 'foo') { + } + case 3: + default: + echo 'default'; +} + +if ($tokens[$stackPtr]['content']{0} === '#') { +} else if ($tokens[$stackPtr]['content']{0} === '/' + && $tokens[$stackPtr]['content']{1} === '/' +) { +} + +$var = call_user_func( + function() { + if ($foo) { + $new_var = function() { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + }; + } + } +); + +a( + function() { + $a = function() { + $b = false; + }; + true; + } +); + +$var = [ + [ + '1' => + function () { + return true; + }, + ], + [ + '1' => + function () { + return true; + }, + '2' => true, + ] +]; + +if ($foo) { + ?> +

    + self::_replaceKeywords($failingComment, $result), + 'screenshot' => Test::getScreenshotPath( + $projectid, + $result['class_name'], + ), + ); + +} + +$this->mockedDatabase + ->with( + $this->callback( + function () { + return; + } + ) + ); + +$this->subject->recordLogin(); + +function a() +{ + if (true) { + static::$a[$b] = + static::where($c) + ->where($c) + ->where( + function ($d) { + $d->whereNull(); + $d->orWhere(); + } + ) + ->first(); + + if (static::$a[$b] === null) { + static::$a[$b] = new static( + array( + 'a' => $a->id, + 'a' => $a->id, + ) + ); + } + } + + return static::$a[$b]; +} + +$foo->load( + array( + 'bar' => function ($baz) { + $baz->call(); + } + ) +); + +hello(); + +$foo = array_unique( + array_map( + function ($entry) { + return $entry * 2; + }, + array() + ) +); +bar($foo); + +class PHP_CodeSniffer_Tokenizers_JS +{ + + public $scopeOpeners = array( + T_CASE => array( + 'end' => array( + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + ), + 'strict' => true, + ), + ); +} + +echo $string-> + append('foo')-> + appaend('bar')-> + appaend('baz')-> + outputUsing( + function () + { + } + ); + +$str = 'the items I want to show are: ' . + implode( + ', ', + array('a', 'b', 'c') + ); + +echo $str; + +$str = 'foo' + . '1' + . '2'; + +echo $str; + +bar([ + 'foo' => foo(function () { + return 'foo'; + }) +]); + +$domains = array_unique( + array_map( + function ($url) { + $urlObject = new \Purl\Url($url); + return $urlObject->registerableDomain; + }, + $sites + ) +); + +return $domains; + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +if ($foo): + if ($bar) $foo = 1; + elseif ($baz) $foo = 2; +endif; + +$this + ->method(array( + 'foo' => 'bar', + ), 'arg', array( + 'foo' => 'bar', + )); + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +foo(); + +array( + 'key1' => function ($bar) { + return $bar; + }, + 'key2' => function ($foo) { + return $foo; + }, +); + +?> + + 1, + ]; +$c = 2; + +class foo +{ + public function get() + { + $foo = ['b' => 'c', + 'd' => [ + ['e' => 'f'] + ]]; + echo '42'; + + $foo = array('b' => 'c', + 'd' => array( + array('e' => 'f') + )); + echo '42'; + } +} + +switch ($foo) { + case 1: + return array(); + case 2: + return ''; + case 3: + return $function(); + case 4: + return $functionCall($param[0]); + case 5: + return array() + array(); // Array Merge + case 6: + // String connect + return $functionReturningString('') . $functionReturningString(array()); + case 7: + return functionCall( + $withMultiLineParam[0], + array(), + $functionReturningString( + $withMultiLineParam[1] + ) + ); + case 8: + return $param[0][0]; +} + +class Test { + + public + $foo + ,$bar + ,$baz = [ ] + ; + + public function wtfindent() { + } +} + +switch ($x) { + case 1: + return [1]; + default: + return [2]; +} + +switch ($foo) { + case self::FOO: + return $this->bar($gfoo, function ($id) { + return FOO::bar($id); + }, $values); + case self::BAR: + $values = $this->bar($foo, $values); + break; +} + +$var = array( + 'long description' => + array(0, 'something'), + 'another long description' => + array(1, "something else") +); + +$services = array( + 'service 1' => + Mockery::mock('class 1') + ->shouldReceive('setFilter')->once() + ->shouldReceive('getNbResults')->atLeast()->once() + ->shouldReceive('getSlice')->once()->andReturn(array()) + ->getMock(), + 'service 2' => + Mockery::mock('class 2') + ->shouldReceive('__invoke')->once() + ->getMock() +); + +class Foo +{ + public function setUp() + { + $this->foo = new class { + public $name = 'Some value'; + }; + } +} + +try { + foo(); +} catch (\Exception $e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +if ($foo) { + foo(); +} else if ($e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} else { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +switch ($parameter) { + case null: + return [ + 'foo' => in_array( + 'foo', + [] + ), + ]; + + default: + return []; +} + +class SomeClass +{ + public function someFunc() + { + a(function () { + echo "a"; + })->b(function () { + echo "b"; + }); + + if (true) { + echo "c"; + } + echo "d"; + } +} + +$params = self::validate_parameters(self::read_competency_framework_parameters(), + array( + 'id' => $id, + )); + +$framework = api::read_framework($params['id']); +self::validate_context($framework->get_context()); +$output = $PAGE->get_renderer('tool_lp'); + +class Test123 +{ + protected static + $prop1 = [ + 'testA' => 123, + ], + $prop2 = [ + 'testB' => 456, + ]; + + protected static + $prop3 = array( + 'testA' => 123, + ), + $prop4 = array( + 'testB' => 456, + ); + + protected static $prop5; +} + +$foo = foo( + function () { + $foo->debug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +if (somethingIsTrue()) { + ?> +
    + +
    + bar(foo(function () { + }), foo(function () { + })); + +echo 'foo'; + +class Test { + + public function a() { + ?>adebug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +function test() +{ + $array = []; + foreach ($array as $data) { + [ + 'key1' => $var1, + 'key2' => $var2, + ] = $data; + foreach ($var1 as $method) { + echo $method . $var2; + } + } +} + +switch ($a) { + case 0: + $a = function () { + }; + case 1: + break; +} + +class Test +{ + public function __construct() + { + if (false) { + echo 0; + } + } +} + +return [ + 'veryLongKeySoIWantToMakeALineBreak' + => 'veryLonValueSoIWantToMakeALineBreak', + + 'someOtherKey' => [ + 'someValue' + ], + + 'arrayWithArraysInThere' => [ + ['Value1', 'Value1'] + ], +]; + +switch ($sContext) { + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +array_map( + static function ( $item ) { + echo $item; + }, + $some_array +); + +/** + * Comment. + */ +$a(function () use ($app) { + echo 'hi'; +})(); + +$app->run(); + +function foo() +{ + $foo('some + long description', function () { + }); + + $foo('some + long + description', function () { + }); + + $foo( + 'some long description', function () { + }); +} + +switch ( $a ) { + case 'a': + $b = 2; + /** + * A comment. + */ + apply_filter( 'something', $b ); + break; + + case 'aa': + $b = 2; + /* + * A comment. + */ + apply_filter( 'something', $b ); + break; + + case 'b': + $b = 3; + ?> + + + + + +
    + +
    + +
    + +
    + + +
    + + + +
    + [ + ], + 'b' => <<<'FOO' +foo; +FOO + ], + $a, +]; + +$query = Model::query() + ->when($a, function () { + static $b = ''; + }); + +$result = array_map( + static fn(int $number) : int => $number + 1, + $numbers +); + +$a = $a === true ? [ + 'a' => 1, + ] : [ + 'a' => 100, +]; + +return [ + Url::make('View Song', fn($song) => $song->url()) + ->onlyOnDetail(), + + new Panel('Information', [ + Text::make('Title') + ]), +]; + +echo $string?->append('foo') + ?->outputUsing(); + +// phpcs:set Generic.WhiteSpace.ScopeIndent exact true +echo $string?->append('foo') + ?->outputUsing(); +// phpcs:set Generic.WhiteSpace.ScopeIndent exact false + +if (true) { + ?> null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ($value) { + '' => null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ( + $value + ) { + '' => null, + false + => false, + 1, + 2, + 3 => true, + default => + $value, +}; + +function toString(): string +{ + return sprintf( + '%s', + match ($type) { + 'foo' => 'bar', + }, + ); +} + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + }, + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + $list2 = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } + ]; + } + } +]; + +$foo = match ($type) { + 'a' => [ + 'aa' => 'DESC', + 'ab' => 'DESC', + ], + 'b' => [ + 'ba' => 'DESC', + 'bb' => 'DESC', + ], + default => [ + 'da' => 'DESC', + ], +}; + +$a = [ + 'a' => [ + 'a' => fn () => foo() + ], + 'a' => [ + 'a' => 'a', + ] +]; + +switch ($foo) { + case 'a': + $foo = match ($foo) { + 'bar' => 'custom_1', + default => 'a' + }; + return $foo; + case 'b': + return match ($foo) { + 'bar' => 'custom_1', + default => 'b' + }; + default: + return 'default'; +} + +/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */ +?> + + + + + + + <<<'INTRO' + lorem ipsum + INTRO, + 'em' => [ + [ + '', + ], + ], + 'abc' => [ + 'a' => 'wop wop', + 'b' => 'ola ola.', + ], +]; + +echo "" diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc new file mode 100644 index 00000000..55d1a06a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc @@ -0,0 +1,28 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false +phpcs:set Generic.WhiteSpace.ScopeIndent exact true + $enabled, + 'compression' => $compression, + ] = $options; +} + +$this->foo() + ->bar() + ->baz(); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed new file mode 100644 index 00000000..e9ae5ff3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed @@ -0,0 +1,28 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false +phpcs:set Generic.WhiteSpace.ScopeIndent exact true + $enabled, + 'compression' => $compression, + ] = $options; +} + +$this->foo() + ->bar() + ->baz(); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.4.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.4.inc new file mode 100644 index 00000000..e58dc4de --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.4.inc @@ -0,0 +1,6 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ScopeIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + // Tab width setting is only needed for the tabbed file. + if ($testFile === 'ScopeIndentUnitTest.2.inc') { + $config->tabWidth = 4; + } else { + $config->tabWidth = 0; + } + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='ScopeIndentUnitTest.inc') + { + if ($testFile === 'ScopeIndentUnitTest.1.js') { + return [ + 6 => 1, + 14 => 1, + 21 => 1, + 30 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 39 => 1, + 42 => 1, + 59 => 1, + 60 => 1, + 75 => 1, + 120 => 1, + 121 => 1, + 122 => 1, + 123 => 1, + 141 => 1, + 142 => 1, + 155 => 1, + 156 => 1, + 168 => 1, + 184 => 1, + ]; + }//end if + + if ($testFile === 'ScopeIndentUnitTest.3.inc') { + return [ + 6 => 1, + 7 => 1, + 10 => 1, + ]; + } + + if ($testFile === 'ScopeIndentUnitTest.4.inc') { + return []; + } + + return [ + 7 => 1, + 10 => 1, + 13 => 1, + 17 => 1, + 20 => 1, + 24 => 1, + 25 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 58 => 1, + 123 => 1, + 224 => 1, + 225 => 1, + 279 => 1, + 280 => 1, + 281 => 1, + 282 => 1, + 283 => 1, + 284 => 1, + 285 => 1, + 286 => 1, + 336 => 1, + 349 => 1, + 380 => 1, + 386 => 1, + 387 => 1, + 388 => 1, + 389 => 1, + 390 => 1, + 397 => 1, + 419 => 1, + 420 => 1, + 465 => 1, + 467 => 1, + 472 => 1, + 473 => 1, + 474 => 1, + 496 => 1, + 498 => 1, + 500 => 1, + 524 => 1, + 526 => 1, + 544 => 1, + 545 => 1, + 546 => 1, + 639 => 1, + 660 => 1, + 662 => 1, + 802 => 1, + 803 => 1, + 823 => 1, + 858 => 1, + 879 => 1, + 1163 => 1, + 1197 => 1, + 1198 => 1, + 1259 => 1, + 1264 => 1, + 1265 => 1, + 1266 => 1, + 1269 => 1, + 1272 => 1, + 1273 => 1, + 1274 => 1, + 1275 => 1, + 1276 => 1, + 1277 => 1, + 1280 => 1, + 1281 => 1, + 1282 => 1, + 1284 => 1, + 1285 => 1, + 1288 => 1, + 1289 => 1, + 1290 => 1, + 1292 => 1, + 1293 => 1, + 1310 => 1, + 1312 => 1, + 1327 => 1, + 1328 => 1, + 1329 => 1, + 1330 => 1, + 1331 => 1, + 1332 => 1, + 1335 => 1, + 1340 => 1, + 1342 => 1, + 1345 => 1, + 1488 => 1, + 1489 => 1, + 1500 => 1, + 1503 => 1, + 1518 => 1, + 1520 => 1, + 1527 => 1, + 1529 => 1, + 1530 => 1, + 1583 => 1, + 1584 => 1, + 1585 => 1, + 1586 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.inc new file mode 100644 index 00000000..edce4dcc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.inc @@ -0,0 +1,73 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SpreadOperatorSpacingAfterUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 12 => 1, + 13 => 1, + 20 => 2, + 40 => 1, + 41 => 1, + 46 => 2, + 60 => 1, + 61 => 1, + 66 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Generic/ruleset.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/ruleset.xml new file mode 100644 index 00000000..728426e6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Generic/ruleset.xml @@ -0,0 +1,4 @@ + + + A collection of generic sniffs. This standard is not designed to be used to check code. + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php new file mode 100644 index 00000000..9575398a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php @@ -0,0 +1,87 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\CSS; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class BrowserSpecificStylesSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * A list of specific stylesheet suffixes we allow. + * + * These stylesheets contain browser specific styles + * so this sniff ignore them files in the form: + * *_moz.css and *_ie7.css etc. + * + * @var array + */ + protected $specificStylesheets = [ + 'moz' => true, + 'ie' => true, + 'ie7' => true, + 'ie8' => true, + 'webkit' => true, + ]; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Ignore files with browser-specific suffixes. + $filename = $phpcsFile->getFilename(); + $breakChar = strrpos($filename, '_'); + if ($breakChar !== false && substr($filename, -4) === '.css') { + $specific = substr($filename, ($breakChar + 1), -4); + if (isset($this->specificStylesheets[$specific]) === true) { + return; + } + } + + $tokens = $phpcsFile->getTokens(); + $content = $tokens[$stackPtr]['content']; + + if ($content[0] === '-') { + $error = 'Browser-specific styles are not allowed'; + $phpcsFile->addError($error, $stackPtr, 'ForbiddenStyle'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php new file mode 100644 index 00000000..81b7f1b6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php @@ -0,0 +1,125 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Channels; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowSelfActionsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // We are not interested in abstract classes. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($prev !== false && $tokens[$prev]['code'] === T_ABSTRACT) { + return; + } + + // We are only interested in Action classes. + $classNameToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $className = $tokens[$classNameToken]['content']; + if (substr($className, -7) !== 'Actions') { + return; + } + + $foundFunctions = []; + $foundCalls = []; + + // Find all static method calls in the form self::method() in the class. + $classEnd = $tokens[$stackPtr]['scope_closer']; + for ($i = ($classNameToken + 1); $i < $classEnd; $i++) { + if ($tokens[$i]['code'] !== T_DOUBLE_COLON) { + if ($tokens[$i]['code'] === T_FUNCTION) { + // Cache the function information. + $funcName = $phpcsFile->findNext(T_STRING, ($i + 1)); + $funcScope = $phpcsFile->findPrevious(Tokens::$scopeModifiers, ($i - 1)); + + $foundFunctions[$tokens[$funcName]['content']] = strtolower($tokens[$funcScope]['content']); + } + + continue; + } + + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), null, true); + if ($tokens[$prevToken]['content'] !== 'self' + && $tokens[$prevToken]['content'] !== 'static' + ) { + continue; + } + + $funcNameToken = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true); + if ($tokens[$funcNameToken]['code'] === T_VARIABLE) { + // We are only interested in function calls. + continue; + } + + $funcName = $tokens[$funcNameToken]['content']; + + // We've found the function, now we need to find it and see if it is + // public, private or protected. If it starts with an underscore we + // can assume it is private. + if ($funcName[0] === '_') { + continue; + } + + $foundCalls[$i] = [ + 'name' => $funcName, + 'type' => strtolower($tokens[$prevToken]['content']), + ]; + }//end for + + $errorClassName = substr($className, 0, -7); + + foreach ($foundCalls as $token => $funcData) { + if (isset($foundFunctions[$funcData['name']]) === false) { + // Function was not in this class, might have come from the parent. + // Either way, we can't really check this. + continue; + } else if ($foundFunctions[$funcData['name']] === 'public') { + $type = $funcData['type']; + $error = "Static calls to public methods in Action classes must not use the $type keyword; use %s::%s() instead"; + $data = [ + $errorClassName, + $funcName, + ]; + $phpcsFile->addError($error, $token, 'Found'.ucfirst($funcData['type']), $data); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php new file mode 100644 index 00000000..2d56261c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php @@ -0,0 +1,98 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Channels; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class IncludeOwnSystemSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOUBLE_COLON]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $fileName = $phpcsFile->getFilename(); + $matches = []; + if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|i', $fileName, $matches) === 0) { + // Not an actions file. + return; + } + + $ownClass = $matches[2]; + $tokens = $phpcsFile->getTokens(); + + $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 2), null, false, true); + $typeName = trim($tokens[$typeName]['content'], " '"); + switch (strtolower($tokens[($stackPtr + 1)]['content'])) { + case 'includesystem' : + $included = strtolower($typeName); + break; + case 'includeasset' : + $included = strtolower($typeName).'assettype'; + break; + case 'includewidget' : + $included = strtolower($typeName).'widgettype'; + break; + default: + return; + } + + if ($included === strtolower($ownClass)) { + $error = "You do not need to include \"%s\" from within the system's own actions file"; + $data = [$ownClass]; + $phpcsFile->addError($error, $stackPtr, 'NotRequired', $data); + } + + }//end process() + + + /** + * Determines the included class name from given token. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param array $tokens The array of file tokens. + * @param int $stackPtr The position in the tokens array of the + * potentially included class. + * + * @return string + */ + protected function getIncludedClassFromToken( + $phpcsFile, + array $tokens, + $stackPtr + ) { + + return false; + + }//end getIncludedClassFromToken() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php new file mode 100644 index 00000000..8bbd91e8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php @@ -0,0 +1,314 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Channels; + +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class IncludeSystemSniff extends AbstractScopeSniff +{ + + /** + * A list of classes that don't need to be included. + * + * @var string[] + */ + private $ignore = [ + 'self' => true, + 'static' => true, + 'parent' => true, + 'channels' => true, + 'basesystem' => true, + 'dal' => true, + 'init' => true, + 'pdo' => true, + 'util' => true, + 'ziparchive' => true, + 'phpunit_framework_assert' => true, + 'abstractmysourceunittest' => true, + 'abstractdatacleanunittest' => true, + 'exception' => true, + 'abstractwidgetwidgettype' => true, + 'domdocument' => true, + ]; + + + /** + * Constructs an AbstractScopeSniff. + */ + public function __construct() + { + parent::__construct([T_FUNCTION], [T_DOUBLE_COLON, T_EXTENDS], true); + + }//end __construct() + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param integer $stackPtr The position where the token was found. + * @param integer $currScope The current scope opener token. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine the name of the class that the static function + // is being called on. + $classNameToken = $phpcsFile->findPrevious( + T_WHITESPACE, + ($stackPtr - 1), + null, + true + ); + + // Don't process class names represented by variables as this can be + // an inexact science. + if ($tokens[$classNameToken]['code'] === T_VARIABLE) { + return; + } + + $className = $tokens[$classNameToken]['content']; + if (isset($this->ignore[strtolower($className)]) === true) { + return; + } + + $includedClasses = []; + + $fileName = strtolower($phpcsFile->getFilename()); + $matches = []; + if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|', $fileName, $matches) !== 0) { + // This is an actions file, which means we don't + // have to include the system in which it exists. + $includedClasses[$matches[2]] = true; + + // Or a system it implements. + $class = $phpcsFile->getCondition($stackPtr, T_CLASS); + $implements = $phpcsFile->findNext(T_IMPLEMENTS, $class, ($class + 10)); + if ($implements !== false) { + $implementsClass = $phpcsFile->findNext(T_STRING, $implements); + $implementsClassName = strtolower($tokens[$implementsClass]['content']); + if (substr($implementsClassName, -7) === 'actions') { + $includedClasses[substr($implementsClassName, 0, -7)] = true; + } + } + } + + // Go searching for includeSystem and includeAsset calls within this + // function, or the inclusion of .inc files, which + // would be library files. + for ($i = ($currScope + 1); $i < $stackPtr; $i++) { + $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i); + if ($name !== false) { + $includedClasses[$name] = true; + // Special case for Widgets cause they are, well, special. + } else if (strtolower($tokens[$i]['content']) === 'includewidget') { + $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($i + 1)); + $typeName = trim($tokens[$typeName]['content'], " '"); + $includedClasses[strtolower($typeName).'widgettype'] = true; + } + } + + // Now go searching for includeSystem, includeAsset or require/include + // calls outside our scope. If we are in a class, look outside the + // class. If we are not, look outside the function. + $condPtr = $currScope; + if ($phpcsFile->hasCondition($stackPtr, T_CLASS) === true) { + foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condType) { + if ($condType === T_CLASS) { + break; + } + } + } + + for ($i = 0; $i < $condPtr; $i++) { + // Skip other scopes. + if (isset($tokens[$i]['scope_closer']) === true) { + $i = $tokens[$i]['scope_closer']; + continue; + } + + $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i); + if ($name !== false) { + $includedClasses[$name] = true; + } + } + + // If we are in a testing class, we might have also included + // some systems and classes in our setUp() method. + $setupFunction = null; + if ($phpcsFile->hasCondition($stackPtr, T_CLASS) === true) { + foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condType) { + if ($condType === T_CLASS) { + // Is this is a testing class? + $name = $phpcsFile->findNext(T_STRING, $condPtr); + $name = $tokens[$name]['content']; + if (substr($name, -8) === 'UnitTest') { + // Look for a method called setUp(). + $end = $tokens[$condPtr]['scope_closer']; + $function = $phpcsFile->findNext(T_FUNCTION, ($condPtr + 1), $end); + while ($function !== false) { + $name = $phpcsFile->findNext(T_STRING, $function); + if ($tokens[$name]['content'] === 'setUp') { + $setupFunction = $function; + break; + } + + $function = $phpcsFile->findNext(T_FUNCTION, ($function + 1), $end); + } + } + } + }//end foreach + }//end if + + if ($setupFunction !== null) { + $start = ($tokens[$setupFunction]['scope_opener'] + 1); + $end = $tokens[$setupFunction]['scope_closer']; + for ($i = $start; $i < $end; $i++) { + $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i); + if ($name !== false) { + $includedClasses[$name] = true; + } + } + }//end if + + if (isset($includedClasses[strtolower($className)]) === false) { + $error = 'Static method called on non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once'; + $data = [$className]; + $phpcsFile->addError($error, $stackPtr, 'NotIncludedCall', $data); + } + + }//end processTokenWithinScope() + + + /** + * Processes a token within the scope that this test is listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * this token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_EXTENDS) { + // Find the class name. + $classNameToken = $phpcsFile->findNext(T_STRING, ($stackPtr + 1)); + $className = $tokens[$classNameToken]['content']; + } else { + // Determine the name of the class that the static function + // is being called on. But don't process class names represented by + // variables as this can be an inexact science. + $classNameToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$classNameToken]['code'] === T_VARIABLE) { + return; + } + + $className = $tokens[$classNameToken]['content']; + } + + // Some systems are always available. + if (isset($this->ignore[strtolower($className)]) === true) { + return; + } + + $includedClasses = []; + + $fileName = strtolower($phpcsFile->getFilename()); + $matches = []; + if (preg_match('|/systems/([^/]+)/([^/]+)?actions.inc$|', $fileName, $matches) !== 0) { + // This is an actions file, which means we don't + // have to include the system in which it exists + // We know the system from the path. + $includedClasses[$matches[1]] = true; + } + + // Go searching for includeSystem, includeAsset or require/include + // calls outside our scope. + for ($i = 0; $i < $stackPtr; $i++) { + // Skip classes and functions as will we never get + // into their scopes when including this file, although + // we have a chance of getting into IF, WHILE etc. + if (($tokens[$i]['code'] === T_CLASS + || $tokens[$i]['code'] === T_INTERFACE + || $tokens[$i]['code'] === T_FUNCTION) + && isset($tokens[$i]['scope_closer']) === true + ) { + $i = $tokens[$i]['scope_closer']; + continue; + } + + $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i); + if ($name !== false) { + $includedClasses[$name] = true; + // Special case for Widgets cause they are, well, special. + } else if (strtolower($tokens[$i]['content']) === 'includewidget') { + $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($i + 1)); + $typeName = trim($tokens[$typeName]['content'], " '"); + $includedClasses[strtolower($typeName).'widgettype'] = true; + } + }//end for + + if (isset($includedClasses[strtolower($className)]) === false) { + if ($tokens[$stackPtr]['code'] === T_EXTENDS) { + $error = 'Class extends non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once'; + $data = [$className]; + $phpcsFile->addError($error, $stackPtr, 'NotIncludedExtends', $data); + } else { + $error = 'Static method called on non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once'; + $data = [$className]; + $phpcsFile->addError($error, $stackPtr, 'NotIncludedCall', $data); + } + } + + }//end processTokenOutsideScope() + + + /** + * Determines the included class name from given token. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param array $tokens The array of file tokens. + * @param int $stackPtr The position in the tokens array of the + * potentially included class. + * + * @return string + */ + protected function getIncludedClassFromToken(File $phpcsFile, array $tokens, $stackPtr) + { + if (strtolower($tokens[$stackPtr]['content']) === 'includesystem') { + $systemName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1)); + $systemName = trim($tokens[$systemName]['content'], " '"); + return strtolower($systemName); + } else if (strtolower($tokens[$stackPtr]['content']) === 'includeasset') { + $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1)); + $typeName = trim($tokens[$typeName]['content'], " '"); + return strtolower($typeName).'assettype'; + } else if (isset(Tokens::$includeTokens[$tokens[$stackPtr]['code']]) === true) { + $filePath = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1)); + $filePath = $tokens[$filePath]['content']; + $filePath = trim($filePath, " '"); + $filePath = basename($filePath, '.inc'); + return strtolower($filePath); + } + + return false; + + }//end getIncludedClassFromToken() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/UnusedSystemSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/UnusedSystemSniff.php new file mode 100644 index 00000000..6b10cd3e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/UnusedSystemSniff.php @@ -0,0 +1,141 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Channels; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class UnusedSystemSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOUBLE_COLON]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check if this is a call to includeSystem, includeAsset or includeWidget. + $methodName = strtolower($tokens[($stackPtr + 1)]['content']); + if ($methodName === 'includesystem' + || $methodName === 'includeasset' + || $methodName === 'includewidget' + ) { + $systemName = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 3), null, true); + if ($systemName === false || $tokens[$systemName]['code'] !== T_CONSTANT_ENCAPSED_STRING) { + // Must be using a variable instead of a specific system name. + // We can't accurately check that. + return; + } + + $systemName = trim($tokens[$systemName]['content'], " '"); + } else { + return; + } + + if ($methodName === 'includeasset') { + $systemName .= 'assettype'; + } else if ($methodName === 'includewidget') { + $systemName .= 'widgettype'; + } + + $systemName = strtolower($systemName); + + // Now check if this system is used anywhere in this scope. + $level = $tokens[$stackPtr]['level']; + for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['level'] < $level) { + // We have gone out of scope. + // If the original include was inside an IF statement that + // is checking if the system exists, check the outer scope + // as well. + if ($tokens[$stackPtr]['level'] === $level) { + // We are still in the base level, so this is the first + // time we have got here. + $conditions = array_keys($tokens[$stackPtr]['conditions']); + if (empty($conditions) === false) { + $cond = array_pop($conditions); + if ($tokens[$cond]['code'] === T_IF) { + $i = $tokens[$cond]['scope_closer']; + $level--; + continue; + } + } + } + + break; + }//end if + + if ($tokens[$i]['code'] !== T_DOUBLE_COLON + && $tokens[$i]['code'] !== T_EXTENDS + && $tokens[$i]['code'] !== T_IMPLEMENTS + ) { + continue; + } + + switch ($tokens[$i]['code']) { + case T_DOUBLE_COLON: + $usedName = strtolower($tokens[($i - 1)]['content']); + if ($usedName === $systemName) { + // The included system was used, so it is fine. + return; + } + break; + case T_EXTENDS: + $classNameToken = $phpcsFile->findNext(T_STRING, ($i + 1)); + $className = strtolower($tokens[$classNameToken]['content']); + if ($className === $systemName) { + // The included system was used, so it is fine. + return; + } + break; + case T_IMPLEMENTS: + $endImplements = $phpcsFile->findNext([T_EXTENDS, T_OPEN_CURLY_BRACKET], ($i + 1)); + for ($x = ($i + 1); $x < $endImplements; $x++) { + if ($tokens[$x]['code'] === T_STRING) { + $className = strtolower($tokens[$x]['content']); + if ($className === $systemName) { + // The included system was used, so it is fine. + return; + } + } + } + break; + }//end switch + }//end for + + // If we get to here, the system was not use. + $error = 'Included system "%s" is never used'; + $data = [$systemName]; + $phpcsFile->addError($error, $stackPtr, 'Found', $data); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Commenting/FunctionCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Commenting/FunctionCommentSniff.php new file mode 100644 index 00000000..fd75bcb2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Commenting/FunctionCommentSniff.php @@ -0,0 +1,84 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Commenting; + +use PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\FunctionCommentSniff as SquizFunctionCommentSniff; +use PHP_CodeSniffer\Util\Tokens; +use PHP_CodeSniffer\Files\File; + +class FunctionCommentSniff extends SquizFunctionCommentSniff +{ + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + parent::process($phpcsFile, $stackPtr); + + $tokens = $phpcsFile->getTokens(); + $find = Tokens::$methodPrefixes; + $find[] = T_WHITESPACE; + + $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true); + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG) { + return; + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + $hasApiTag = false; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@api') { + if ($hasApiTag === true) { + // We've come across an API tag already, which means + // we were not the first tag in the API list. + $error = 'The @api tag must come first in the @api tag list in a function comment'; + $phpcsFile->addError($error, $tag, 'ApiNotFirst'); + } + + $hasApiTag = true; + + // There needs to be a blank line before the @api tag. + $prev = $phpcsFile->findPrevious([T_DOC_COMMENT_STRING, T_DOC_COMMENT_TAG], ($tag - 1)); + if ($tokens[$prev]['line'] !== ($tokens[$tag]['line'] - 2)) { + $error = 'There must be one blank line before the @api tag in a function comment'; + $phpcsFile->addError($error, $tag, 'ApiSpacing'); + } + } else if (substr($tokens[$tag]['content'], 0, 5) === '@api-') { + $hasApiTag = true; + + $prev = $phpcsFile->findPrevious([T_DOC_COMMENT_STRING, T_DOC_COMMENT_TAG], ($tag - 1)); + if ($tokens[$prev]['line'] !== ($tokens[$tag]['line'] - 1)) { + $error = 'There must be no blank line before the @%s tag in a function comment'; + $data = [$tokens[$tag]['content']]; + $phpcsFile->addError($error, $tag, 'ApiTagSpacing', $data); + } + }//end if + }//end foreach + + if ($hasApiTag === true && substr($tokens[$tag]['content'], 0, 4) !== '@api') { + // API tags must be the last tags in a function comment. + $error = 'The @api tags must be the last tags in a function comment'; + $phpcsFile->addError($error, $commentEnd, 'ApiNotLast'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/DebugCodeSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/DebugCodeSniff.php new file mode 100644 index 00000000..eccf6fe4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/DebugCodeSniff.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Debug; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class DebugCodeSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOUBLE_COLON]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $className = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if (strtolower($tokens[$className]['content']) === 'debug') { + $method = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $error = 'Call to debug function Debug::%s() must be removed'; + $data = [$tokens[$method]['content']]; + $phpcsFile->addError($error, $stackPtr, 'Found', $data); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/FirebugConsoleSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/FirebugConsoleSniff.php new file mode 100644 index 00000000..3115bac4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/FirebugConsoleSniff.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Debug; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class FirebugConsoleSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_STRING, + T_PROPERTY, + T_LABEL, + T_OBJECT, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (strtolower($tokens[$stackPtr]['content']) === 'console') { + $error = 'Variables, functions and labels must not be named "console"; name may conflict with Firebug internal variable'; + $phpcsFile->addError($error, $stackPtr, 'ConflictFound'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/AssignThisSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/AssignThisSniff.php new file mode 100644 index 00000000..0a3c9cf2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/AssignThisSniff.php @@ -0,0 +1,81 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Objects; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class AssignThisSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_THIS]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore this.something and other uses of "this" that are not + // direct assignments. + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] !== T_SEMICOLON) { + if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) { + return; + } + } + + // Something must be assigned to "this". + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] !== T_EQUAL) { + return; + } + + // A variable needs to be assigned to "this". + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($prev - 1), null, true); + if ($tokens[$prev]['code'] !== T_STRING) { + return; + } + + // We can only assign "this" to a var called "self". + if ($tokens[$prev]['content'] !== 'self' && $tokens[$prev]['content'] !== '_self') { + $error = 'Keyword "this" can only be assigned to a variable called "self" or "_self"'; + $phpcsFile->addError($error, $prev, 'NotSelf'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/CreateWidgetTypeCallbackSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/CreateWidgetTypeCallbackSniff.php new file mode 100644 index 00000000..8fb89376 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/CreateWidgetTypeCallbackSniff.php @@ -0,0 +1,218 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Objects; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class CreateWidgetTypeCallbackSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OBJECT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $className = $phpcsFile->findPrevious(T_STRING, ($stackPtr - 1)); + if (substr(strtolower($tokens[$className]['content']), -10) !== 'widgettype') { + return; + } + + // Search for a create method. + $create = $phpcsFile->findNext(T_PROPERTY, $stackPtr, $tokens[$stackPtr]['bracket_closer'], null, 'create'); + if ($create === false) { + return; + } + + $function = $phpcsFile->findNext([T_WHITESPACE, T_COLON], ($create + 1), null, true); + if ($tokens[$function]['code'] !== T_FUNCTION + && $tokens[$function]['code'] !== T_CLOSURE + ) { + return; + } + + $start = ($tokens[$function]['scope_opener'] + 1); + $end = ($tokens[$function]['scope_closer'] - 1); + + // Check that the first argument is called "callback". + $arg = $phpcsFile->findNext(T_WHITESPACE, ($tokens[$function]['parenthesis_opener'] + 1), null, true); + if ($tokens[$arg]['content'] !== 'callback') { + $error = 'The first argument of the create() method of a widget type must be called "callback"'; + $phpcsFile->addError($error, $arg, 'FirstArgNotCallback'); + } + + /* + Look for return statements within the function. They cannot return + anything and must be preceded by the callback.call() line. The + callback itself must contain "self" or "this" as the first argument + and there needs to be a call to the callback function somewhere + in the create method. All calls to the callback function must be + followed by a return statement or the end of the method. + */ + + $foundCallback = false; + $passedCallback = false; + $nestedFunction = null; + for ($i = $start; $i <= $end; $i++) { + // Keep track of nested functions. + if ($nestedFunction !== null) { + if ($i === $nestedFunction) { + $nestedFunction = null; + continue; + } + } else if (($tokens[$i]['code'] === T_FUNCTION + || $tokens[$i]['code'] === T_CLOSURE) + && isset($tokens[$i]['scope_closer']) === true + ) { + $nestedFunction = $tokens[$i]['scope_closer']; + continue; + } + + if ($nestedFunction === null && $tokens[$i]['code'] === T_RETURN) { + // Make sure return statements are not returning anything. + if ($tokens[($i + 1)]['code'] !== T_SEMICOLON) { + $error = 'The create() method of a widget type must not return a value'; + $phpcsFile->addError($error, $i, 'ReturnValue'); + } + + continue; + } else if ($tokens[$i]['code'] !== T_STRING + || $tokens[$i]['content'] !== 'callback' + ) { + continue; + } + + // If this is the form "callback.call(" then it is a call + // to the callback function. + if ($tokens[($i + 1)]['code'] !== T_OBJECT_OPERATOR + || $tokens[($i + 2)]['content'] !== 'call' + || $tokens[($i + 3)]['code'] !== T_OPEN_PARENTHESIS + ) { + // One last chance; this might be the callback function + // being passed to another function, like this + // "this.init(something, callback, something)". + if (isset($tokens[$i]['nested_parenthesis']) === false) { + continue; + } + + // Just make sure those brackets don't belong to anyone, + // like an IF or FOR statement. + foreach ($tokens[$i]['nested_parenthesis'] as $bracket) { + if (isset($tokens[$bracket]['parenthesis_owner']) === true) { + continue(2); + } + } + + // Note that we use this endBracket down further when checking + // for a RETURN statement. + $nestedParens = $tokens[$i]['nested_parenthesis']; + $endBracket = end($nestedParens); + $bracket = key($nestedParens); + + $prev = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($bracket - 1), + null, + true + ); + + if ($tokens[$prev]['code'] !== T_STRING) { + // This is not a function passing the callback. + continue; + } + + $passedCallback = true; + }//end if + + $foundCallback = true; + + if ($passedCallback === false) { + // The first argument must be "this" or "self". + $arg = $phpcsFile->findNext(T_WHITESPACE, ($i + 4), null, true); + if ($tokens[$arg]['content'] !== 'this' + && $tokens[$arg]['content'] !== 'self' + ) { + $error = 'The first argument passed to the callback function must be "this" or "self"'; + $phpcsFile->addError($error, $arg, 'FirstArgNotSelf'); + } + } + + // Now it must be followed by a return statement or the end of the function. + if ($passedCallback === false) { + $endBracket = $tokens[($i + 3)]['parenthesis_closer']; + } + + for ($next = $endBracket; $next <= $end; $next++) { + // Skip whitespace so we find the next content after the call. + if (isset(Tokens::$emptyTokens[$tokens[$next]['code']]) === true) { + continue; + } + + // Skip closing braces like END IF because it is not executable code. + if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) { + continue; + } + + // We don't care about anything on the current line, like a + // semicolon. It doesn't matter if there are other statements on the + // line because another sniff will check for those. + if ($tokens[$next]['line'] === $tokens[$endBracket]['line']) { + continue; + } + + break; + } + + if ($next !== $tokens[$function]['scope_closer'] + && $tokens[$next]['code'] !== T_RETURN + ) { + $error = 'The call to the callback function must be followed by a return statement if it is not the last statement in the create() method'; + $phpcsFile->addError($error, $i, 'NoReturn'); + } + }//end for + + if ($foundCallback === false) { + $error = 'The create() method of a widget type must call the callback function'; + $phpcsFile->addError($error, $create, 'CallbackNotCalled'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/DisallowNewWidgetSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/DisallowNewWidgetSniff.php new file mode 100644 index 00000000..cae7c08d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/DisallowNewWidgetSniff.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Objects; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class DisallowNewWidgetSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_NEW]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $className = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$className]['code'] !== T_STRING) { + return; + } + + if (substr(strtolower($tokens[$className]['content']), -10) === 'widgettype') { + $widgetType = substr($tokens[$className]['content'], 0, -10); + $error = 'Manual creation of widget objects is banned; use Widget::getWidget(\'%s\'); instead'; + $data = [$widgetType]; + $phpcsFile->addError($error, $stackPtr, 'Found', $data); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/AjaxNullComparisonSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/AjaxNullComparisonSniff.php new file mode 100644 index 00000000..3914b7b8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/AjaxNullComparisonSniff.php @@ -0,0 +1,103 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\PHP; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class AjaxNullComparisonSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure it is an API function. We know this by the doc comment. + $commentEnd = $phpcsFile->findPrevious(T_DOC_COMMENT_CLOSE_TAG, $stackPtr); + $commentStart = $phpcsFile->findPrevious(T_DOC_COMMENT_OPEN_TAG, ($commentEnd - 1)); + // If function doesn't contain any doc comments - skip it. + if ($commentEnd === false || $commentStart === false) { + return; + } + + $comment = $phpcsFile->getTokensAsString($commentStart, ($commentEnd - $commentStart)); + if (strpos($comment, '* @api') === false) { + return; + } + + // Find all the vars passed in as we are only interested in comparisons + // to NULL for these specific variables. + $foundVars = []; + $open = $tokens[$stackPtr]['parenthesis_opener']; + $close = $tokens[$stackPtr]['parenthesis_closer']; + for ($i = ($open + 1); $i < $close; $i++) { + if ($tokens[$i]['code'] === T_VARIABLE) { + $foundVars[$tokens[$i]['content']] = true; + } + } + + if (empty($foundVars) === true) { + return; + } + + $start = $tokens[$stackPtr]['scope_opener']; + $end = $tokens[$stackPtr]['scope_closer']; + for ($i = ($start + 1); $i < $end; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE + || isset($foundVars[$tokens[$i]['content']]) === false + ) { + continue; + } + + $operator = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true); + if ($tokens[$operator]['code'] !== T_IS_IDENTICAL + && $tokens[$operator]['code'] !== T_IS_NOT_IDENTICAL + ) { + continue; + } + + $nullValue = $phpcsFile->findNext(T_WHITESPACE, ($operator + 1), null, true); + if ($tokens[$nullValue]['code'] !== T_NULL) { + continue; + } + + $error = 'Values submitted via Ajax requests should not be compared directly to NULL; use empty() instead'; + $phpcsFile->addWarning($error, $nullValue, 'Found'); + }//end for + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/EvalObjectFactorySniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/EvalObjectFactorySniff.php new file mode 100644 index 00000000..67b35723 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/EvalObjectFactorySniff.php @@ -0,0 +1,114 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\PHP; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class EvalObjectFactorySniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EVAL]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + /* + We need to find all strings that will be in the eval + to determine if the "new" keyword is being used. + */ + + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($stackPtr + 1)); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + $strings = []; + $vars = []; + + for ($i = ($openBracket + 1); $i < $closeBracket; $i++) { + if (isset(Tokens::$stringTokens[$tokens[$i]['code']]) === true) { + $strings[$i] = $tokens[$i]['content']; + } else if ($tokens[$i]['code'] === T_VARIABLE) { + $vars[$i] = $tokens[$i]['content']; + } + } + + /* + We now have some variables that we need to expand into + the strings that were assigned to them, if any. + */ + + foreach ($vars as $varPtr => $varName) { + while (($prev = $phpcsFile->findPrevious(T_VARIABLE, ($varPtr - 1))) !== false) { + // Make sure this is an assignment of the variable. That means + // it will be the first thing on the line. + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($prev - 1), null, true); + if ($tokens[$prevContent]['line'] === $tokens[$prev]['line']) { + $varPtr = $prevContent; + continue; + } + + if ($tokens[$prev]['content'] !== $varName) { + // This variable has a different name. + $varPtr = $prevContent; + continue; + } + + // We found one. + break; + }//end while + + if ($prev !== false) { + // Find all strings on the line. + $lineEnd = $phpcsFile->findNext(T_SEMICOLON, ($prev + 1)); + for ($i = ($prev + 1); $i < $lineEnd; $i++) { + if (isset(Tokens::$stringTokens[$tokens[$i]['code']]) === true) { + $strings[$i] = $tokens[$i]['content']; + } + } + } + }//end foreach + + foreach ($strings as $string) { + // If the string has "new" in it, it is not allowed. + // We don't bother checking if the word "new" is printed to screen + // because that is unlikely to happen. We assume the use + // of "new" is for object instantiation. + if (strstr($string, ' new ') !== false) { + $error = 'Do not use eval() to create objects dynamically; use reflection instead'; + $phpcsFile->addWarning($error, $stackPtr, 'Found'); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php new file mode 100644 index 00000000..82419fcb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php @@ -0,0 +1,106 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\PHP; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class GetRequestDataSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_VARIABLE]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $varName = $tokens[$stackPtr]['content']; + if ($varName !== '$_REQUEST' + && $varName !== '$_GET' + && $varName !== '$_POST' + && $varName !== '$_FILES' + ) { + return; + } + + // The only place these super globals can be accessed directly is + // in the getRequestData() method of the Security class. + $inClass = false; + foreach ($tokens[$stackPtr]['conditions'] as $i => $type) { + if ($tokens[$i]['code'] === T_CLASS) { + $className = $phpcsFile->findNext(T_STRING, $i); + $className = $tokens[$className]['content']; + if (strtolower($className) === 'security') { + $inClass = true; + } else { + // We don't have nested classes. + break; + } + } else if ($inClass === true && $tokens[$i]['code'] === T_FUNCTION) { + $funcName = $phpcsFile->findNext(T_STRING, $i); + $funcName = $tokens[$funcName]['content']; + if (strtolower($funcName) === 'getrequestdata') { + // This is valid. + return; + } else { + // We don't have nested functions. + break; + } + }//end if + }//end foreach + + // If we get to here, the super global was used incorrectly. + // First find out how it is being used. + $globalName = strtolower(substr($varName, 2)); + $usedVar = ''; + + $openBracket = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$openBracket]['code'] === T_OPEN_SQUARE_BRACKET) { + $closeBracket = $tokens[$openBracket]['bracket_closer']; + $usedVar = $phpcsFile->getTokensAsString(($openBracket + 1), ($closeBracket - $openBracket - 1)); + } + + $type = 'SuperglobalAccessed'; + $error = 'The %s super global must not be accessed directly; use Security::getRequestData('; + $data = [$varName]; + if ($usedVar !== '') { + $type .= 'WithVar'; + $error .= '%s, \'%s\''; + $data[] = $usedVar; + $data[] = $globalName; + } + + $error .= ') instead'; + $phpcsFile->addError($error, $stackPtr, $type, $data); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php new file mode 100644 index 00000000..9b2029af --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php @@ -0,0 +1,63 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\PHP; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class ReturnFunctionValueSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_RETURN]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $functionName = $phpcsFile->findNext(T_STRING, ($stackPtr + 1), null, false, null, true); + + while ($functionName !== false) { + // Check if this is really a function. + $bracket = $phpcsFile->findNext(T_WHITESPACE, ($functionName + 1), null, true); + if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) { + // Not a function call. + $functionName = $phpcsFile->findNext(T_STRING, ($functionName + 1), null, false, null, true); + continue; + } + + $error = 'The result of a function call should be assigned to a variable before being returned'; + $phpcsFile->addWarning($error, $stackPtr, 'NotAssigned'); + break; + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php new file mode 100644 index 00000000..311cf684 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php @@ -0,0 +1,76 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Strings; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class JoinStringsSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_STRING]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param integer $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['content'] !== 'join') { + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] !== T_OBJECT_OPERATOR) { + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + if ($tokens[$prev]['code'] === T_CLOSE_SQUARE_BRACKET) { + $opener = $tokens[$prev]['bracket_opener']; + if ($tokens[($opener - 1)]['code'] !== T_STRING) { + // This means the array is declared inline, like x = [a,b,c].join() + // and not elsewhere, like x = y[a].join() + // The first is not allowed while the second is. + $error = 'Joining strings using inline arrays is not allowed; use the + operator instead'; + $phpcsFile->addError($error, $stackPtr, 'ArrayNotAllowed'); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.css new file mode 100644 index 00000000..339ee154 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.css @@ -0,0 +1,13 @@ +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; + line-height: -25px; + cursor: pointer; + -moz-user-select: none; +} + +.AssetLineageWidgetType-item { + float: left; + list-style: none; + height: 22px; + cursor: pointer; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.php new file mode 100644 index 00000000..21353499 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class BrowserSpecificStylesUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [5 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.inc new file mode 100644 index 00000000..95fd04b7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.inc @@ -0,0 +1,51 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.php new file mode 100644 index 00000000..d29bf5c6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Channels; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowSelfActionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 12 => 1, + 13 => 1, + 28 => 1, + 29 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.inc new file mode 100644 index 00000000..ccb0273e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.inc @@ -0,0 +1,112 @@ +fetch(PDO::FETCH_NUM) +BaseSystem::getDataDir(); +Util::getArrayIndex(array(), ''); + + +Channels::includeSystem('Widget'); +Widget::includeWidget('AbstractContainer'); +class MyWidget extends AbstractContainerWidgetType {} +class MyOtherWidget extends BookWidgetType {} + +$zip = new ZipArchive(); +$res = $zip->open($path, ZipArchive::CREATE); + +class AssetListingUnitTest extends AbstractMySourceUnitTest +{ + function setUp() { + parent::setUp(); + Channels::includeSystem('MySystem2'); + include_once 'Libs/FileSystem.inc'; + } + + function two() { + $siteid = MySystem2::getCurrentSiteId(); + $parserFiles = FileSystem::listDirectory(); + } + + function three() { + $siteid = MySystem3::getCurrentSiteId(); + $parserFiles = FileSystem::listDirectory(); + } +} + +if (Channels::systemExists('Log') === TRUE) { + Channels::includeSystem('Log'); +} else { + return; +} + +Log::addProjectLog('metadata.field.update', $msg); + +function two() { + Widget::includeWidget('CacheAdminScreen'); + $barChart = CacheAdminScreenWidgetType::constructBarchart($data); +} + +$adjustDialog->setOrientation(AbstractWidgetWidgetType::CENTER); + +$className = 'SquizPerspective'.ucfirst($property['type']).'PropertyType'; +Channels::includeSystem($className); +$className::setValue($assetid, $propertyid, $perspectives, $value, (array) $property['settings']); +?> diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.php new file mode 100644 index 00000000..0320038e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Channels; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class IncludeSystemUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 14 => 1, + 24 => 1, + 27 => 1, + 28 => 1, + 31 => 1, + 36 => 1, + 41 => 1, + 61 => 1, + 70 => 1, + 89 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.inc new file mode 100644 index 00000000..c7bd4738 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.inc @@ -0,0 +1,67 @@ + \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.php new file mode 100644 index 00000000..fbc0ac70 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Channels; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class UnusedSystemUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 5 => 1, + 8 => 1, + 24 => 1, + 34 => 1, + 54 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.inc new file mode 100644 index 00000000..19d5c5d4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.inc @@ -0,0 +1,101 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.php new file mode 100644 index 00000000..5cc43b64 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 28 => 1, + 36 => 1, + 37 => 2, + 49 => 1, + 58 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.inc new file mode 100644 index 00000000..34901610 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.inc @@ -0,0 +1,4 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.php new file mode 100644 index 00000000..78da9c94 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DebugCodeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 3 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.js new file mode 100644 index 00000000..d5e3df57 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.js @@ -0,0 +1,8 @@ +console.info(); +console.warn(); +console.test(); +con.sole(); +var console = { + console: 'string'; +}; +function console() {} \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.php new file mode 100644 index 00000000..3a9c2358 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FirebugConsoleUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='FirebugConsoleUnitTest.js') + { + if ($testFile !== 'FirebugConsoleUnitTest.js') { + return []; + } + + return [ + 1 => 1, + 2 => 1, + 3 => 1, + 5 => 1, + 6 => 1, + 8 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.js new file mode 100644 index 00000000..747a1008 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.js @@ -0,0 +1,20 @@ +var self = this; +buttonWidget.addClickEvent(function() { + self.addDynamicSouce(); +}); + +var x = self; +var y = this; + +var test = ''; +if (true) { + test = this +} + +var itemid = this.items[i].getAttribute('itemid'); + +for (var x = this; y < 10; y++) { + var x = this + 1; +} + +var _self = this; \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.php new file mode 100644 index 00000000..f28dff19 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class AssignThisUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='AssignThisUnitTest.js') + { + if ($testFile !== 'AssignThisUnitTest.js') { + return []; + } + + return [ + 7 => 1, + 11 => 1, + 16 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.js new file mode 100644 index 00000000..22822d32 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.js @@ -0,0 +1,186 @@ +SampleWidgetType.prototype = { + + create: function(callback) + { + if (x === 1) { + return; + } + + if (y === 1) { + callback.call(this); + // A comment here to explain the return is okay. + return; + } + + if (a === 1) { + // Cant return value even after calling callback. + callback.call(this); + return something; + } + + if (a === 1) { + // Need to pass self or this to callback function. + callback.call(a); + } + + callback.call(self); + + var self = this; + this.createChildren(null, function() { + callback.call(self, div); + }); + + // Never good to return a value. + return something; + + callback.call(self); + } + +}; + +AnotherSampleWidgetType.prototype = { + + create: function(input) + { + return; + } + + getSomething: function(input) + { + return 1; + } + +}; + + +NoCreateWidgetType.prototype = { + + getSomething: function(input) + { + return; + } + +}; + + +SomeRandom.prototype = { + + create: function(input) + { + return; + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + if (a === 1) { + // This is ok because it is the last statement, + // even though it is conditional. + callback.call(self); + } + + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + var something = callback; + + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + // Also valid because we are passing the callback to + // someone else to call. + if (y === 1) { + this.something(callback); + return; + } + + this.init(callback); + + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + // Also valid because we are passing the callback to + // someone else to call. + if (y === 1) { + this.something(callback); + } + + this.init(callback); + + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + if (a === 1) { + // This is ok because it is the last statement, + // even though it is conditional. + this.something(callback); + } + + } + +}; + + +SampleWidgetType.prototype = { + + create: function(callback) + { + if (dfx.isFn(callback) === true) { + callback.call(this, cont); + return; + } + } + +}; + + +SampleWidgetType.prototype = { + + create: function(callback) + { + dfx.foreach(items, function(item) { + return true; + }); + + if (dfx.isFn(callback) === true) { + callback.call(this); + } + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + var self = this; + this.createChildren(null, function() { + callback.call(self, div); + return; + }); + } + +}; \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.php new file mode 100644 index 00000000..a3c55bf3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class CreateWidgetTypeCallbackUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='CreateWidgetTypeCallbackUnitTest.js') + { + return [ + 18 => 1, + 23 => 2, + 26 => 1, + 30 => 1, + 34 => 1, + 43 => 2, + 91 => 1, + 123 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.inc new file mode 100644 index 00000000..acf9baf7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.inc @@ -0,0 +1,6 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.php new file mode 100644 index 00000000..333952f6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowNewWidgetUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [4 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.inc new file mode 100644 index 00000000..337914a8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.inc @@ -0,0 +1,182 @@ +getMessage()); + }//end try + + if ($something === NULL) { + if ($bar !== NULL) { + } + } + + return $issueid; + +}//end addIssue() + +/** + * Adds a new issue. + * + * Returns the new issue id. + * + * @param string $title Title of the new issue. + * @param string $description The description of the issue. + * @param string $reporter Asset id of the reporter. + * @param integer $projectid Id of the project that the issue belongs to. + * @param array $tags Array of tags. + * @param string $status The status of the issue. + * @param string $assignedTo The asset id of the user that the issue is + * assigned to. + * @param string $reportedDate If set then this date will be used instead of the + * current date and time. + * @param integer $reportedMilestone Reported milestone. + * + * @return integer + * @throws ChannelException If there is an error. + * + */ +public static function addIssue( + $title, + $description, + $reporter=NULL, + $projectid=NULL, + array $tags=array(), + $status=NULL, + $assignedTo=NULL, + $reportedDate=NULL, + $reportedMilestone=NULL +) { + // Get current projectid if not specified. + if ($projectid === NULL) { + Channels::includeSystem('Project'); + $projectid = Project::getCurrentProjectId(); + Channels::modifyBasket('project', $projectid); + } + +}//end addIssue() diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.php new file mode 100644 index 00000000..315808bd --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class AjaxNullComparisonUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 41 => 1, + 53 => 1, + 64 => 1, + 77 => 1, + 92 => 1, + 122 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.inc new file mode 100644 index 00000000..992a7dc1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.inc @@ -0,0 +1,26 @@ + \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.php new file mode 100644 index 00000000..423f242d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EvalObjectFactoryUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 4 => 1, + 12 => 1, + 21 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.inc new file mode 100644 index 00000000..7999763f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.inc @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.php new file mode 100644 index 00000000..16e4cfb2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.php @@ -0,0 +1,56 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class GetRequestDataUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 5 => 1, + 8 => 1, + 21 => 1, + 26 => 1, + 27 => 1, + 28 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.inc new file mode 100644 index 00000000..f9148a78 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.inc @@ -0,0 +1,9 @@ +myFunction(); +return $obj->variable; +return MyClass::VARIABLE; +return $variable; +return ($var + 1); +?> \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.php new file mode 100644 index 00000000..32363786 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ReturnFunctionValueUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 2 => 1, + 3 => 1, + 4 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.js new file mode 100644 index 00000000..46d90cf9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.js @@ -0,0 +1,18 @@ +one = (1 + 2); +two = (one + 2); +two = (one + one); +three = ('1' + 2); + +four = ['1', two].join(); +four = ['1', two].join(''); +four = ['1', [one, two].join(',')].join(' '); +four = ['1', [one, two].join()].join(' '); +four = ['1', [one, two].join()].join(); + +five = 'string' + ['1', [one, two].join()].join() + 'string'; + +six = myArray.join(' '); +six = [arrayOne, arrayTwo].join(); + +// This is fine because the array is not created inline. +var x = 'x' + test[x].join('p') + 't'; \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.php new file mode 100644 index 00000000..ecd490a4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class JoinStringsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='JoinStringsUnitTest.js') + { + if ($testFile !== 'JoinStringsUnitTest.js') { + return []; + } + + return [ + 6 => 1, + 7 => 1, + 8 => 2, + 9 => 2, + 10 => 2, + 12 => 2, + 15 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/MySource/ruleset.xml b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/ruleset.xml new file mode 100644 index 00000000..92407957 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/MySource/ruleset.xml @@ -0,0 +1,18 @@ + + + The MySource coding standard builds on the Squiz coding standard. Currently used for MySource Mini development. + + */Tests/* + */Oven/* + */data/* + */jquery.js + */jquery.*.js + */viper/* + DALConf.inc + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Classes/ClassDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Classes/ClassDeclarationStandard.xml new file mode 100644 index 00000000..b5d53fdf --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Classes/ClassDeclarationStandard.xml @@ -0,0 +1,22 @@ + + + + + + + { +} + ]]> + + + { +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/ClassCommentStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/ClassCommentStandard.xml new file mode 100644 index 00000000..fe816200 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/ClassCommentStandard.xml @@ -0,0 +1,177 @@ + + + + + + + /** + * The Foo class. + */ +class Foo +{ +} + ]]> + + + + + + + + /** + * The Foo class. + */ +class Foo +{ +} + ]]> + + + + + + + + /** + * The Foo class. + */ +class Foo +{ +} + ]]> + + + /** + * The Foo class. + */ + +class Foo +{ +} + ]]> + + + + + The Foo class. + */ +class Foo +{ +} + ]]> + + + The Foo class. + */ +class Foo +{ +} + ]]> + + + + + + * A helper for the Bar class. + * + * @see Bar + */ +class Foo +{ +} + ]]> + + + + * + * A helper for the Bar class. + * + * + * @see Bar + */ +class Foo +{ +} + ]]> + + + + + + * @see Bar + */ +class Foo +{ +} + ]]> + + + + * + * @see Bar + */ +class Foo +{ +} + ]]> + + + + + Release: 1.0 + */ +class Foo +{ +} + ]]> + + + 1.0 + */ +class Foo +{ +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FileCommentStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FileCommentStandard.xml new file mode 100644 index 00000000..eef0b4e3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FileCommentStandard.xml @@ -0,0 +1,286 @@ + + + + + + + /** + * Short description here. + * + * PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + ]]> + + + + + Short description here. + * + * PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + * Short description here. + * + * PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + + * PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + * + * PHP version 5 + * + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + + + + @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + @category Foo + * @category Bar + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + @package Foo_Helpers + * @category Foo + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FunctionCommentStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FunctionCommentStandard.xml new file mode 100644 index 00000000..621649f2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FunctionCommentStandard.xml @@ -0,0 +1,230 @@ + + + + + + + /** + * Short description here. + * + * @return void + */ + function foo() + { + } + ]]> + + + + + + + + Short description here. + * + * @return void + */ + function foo() + { + } + ]]> + + + + * Short description here. + * + * @return void + */ + function foo() + { + } + ]]> + + + + + + * Long description here. + * + * @return void + */ + function foo() + { + } + ]]> + + + + * + * Long description here. + * + * + * @return void + */ + function foo() + { + } + ]]> + + + + + + * @return void + */ + function foo() + { + } + ]]> + + + + * + * @return void + */ + function foo() + { + } + ]]> + + + + + FooException + */ + function foo() + { + } + ]]> + + + @throws + */ + function foo() + { + } + ]]> + + + + + @return void + */ + function foo() + { + } + ]]> + + + + + + + + $foo Foo parameter + * @param string $bar Bar parameter + * @return void + */ + function foo($foo, $bar) + { + } + ]]> + + + $qux Bar parameter + * @return void + */ + function foo($foo, $bar) + { + } + ]]> + + + + + $foo Foo parameter + * @param string $bar Bar parameter + * @return void + */ + function foo($foo, $bar) + { + } + ]]> + + + $bar Bar parameter + * @param string $foo Foo parameter + * @return void + */ + function foo($foo, $bar) + { + } + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/InlineCommentStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/InlineCommentStandard.xml new file mode 100644 index 00000000..53056e2a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/InlineCommentStandard.xml @@ -0,0 +1,19 @@ + + + + + + + // A comment. + ]]> + + + # A comment. + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/ControlSignatureStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/ControlSignatureStandard.xml new file mode 100644 index 00000000..ce430fb1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/ControlSignatureStandard.xml @@ -0,0 +1,36 @@ + + + + + + + ($foo) { +} + ]]> + + + ($foo){ +} + ]]> + + + + + { +} + ]]> + + + { +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/MultiLineConditionStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/MultiLineConditionStandard.xml new file mode 100644 index 00000000..96d451dc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/MultiLineConditionStandard.xml @@ -0,0 +1,60 @@ + + + + + + + && $bar +) { +} + ]]> + + + && $bar +) { +} + ]]> + + + + + && $bar +) { +} + ]]> + + + && + $bar +) { +} + ]]> + + + + + ) { +} + ]]> + + + ) { +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/IncludingFileStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/IncludingFileStandard.xml new file mode 100644 index 00000000..6d115be7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/IncludingFileStandard.xml @@ -0,0 +1,24 @@ + + + require_once. Anywhere you are conditionally including a class file (for example, factory methods), use include_once. Either of these will ensure that class files are included only once. They share the same file list, so you don't need to worry about mixing them - a file included with require_once will not be included again by include_once. + ]]> + + + include_once and require_once are statements, not functions. Parentheses should not surround the subject filename. + ]]> + + + + + + + ('PHP/CodeSniffer.php'); + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/LineLengthStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/LineLengthStandard.xml new file mode 100644 index 00000000..e4911ef3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/LineLengthStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Formatting/MultiLineAssignmentStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Formatting/MultiLineAssignmentStandard.xml new file mode 100644 index 00000000..e825c553 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Formatting/MultiLineAssignmentStandard.xml @@ -0,0 +1,35 @@ + + + + + + + = $bar; + ]]> + + + = + $bar; + ]]> + + + + + = $bar; + ]]> + + + = $bar; + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionCallSignatureStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionCallSignatureStandard.xml new file mode 100644 index 00000000..f8742277 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionCallSignatureStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + ( $bar, $baz, $quux ) ; + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionDeclarationStandard.xml new file mode 100644 index 00000000..ced9ae2e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionDeclarationStandard.xml @@ -0,0 +1,41 @@ + + + + + + + () use ($bar) { +}; + ]]> + + + ()use($bar){ +}; + ]]> + + + + + $bar, + $baz +) { +}; + ]]> + + + $bar, +$baz) +{ +}; + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/ValidDefaultValueStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/ValidDefaultValueStandard.xml new file mode 100644 index 00000000..56196cb6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/ValidDefaultValueStandard.xml @@ -0,0 +1,25 @@ + + + + + + + $persistent = false) +{ + ... +} + ]]> + + + $persistent = false, $dsn) +{ + ... +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidClassNameStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidClassNameStandard.xml new file mode 100644 index 00000000..d1608791 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidClassNameStandard.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidFunctionNameStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidFunctionNameStandard.xml new file mode 100644 index 00000000..60841dd4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidFunctionNameStandard.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidVariableNameStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidVariableNameStandard.xml new file mode 100644 index 00000000..4c707bdd --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidVariableNameStandard.xml @@ -0,0 +1,29 @@ + + + + + + + publicVar; + protected $protectedVar; + private $_privateVar; +} + ]]> + + + _publicVar; + protected $_protectedVar; + private $privateVar; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ObjectOperatorIndentStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ObjectOperatorIndentStandard.xml new file mode 100644 index 00000000..9dee905d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ObjectOperatorIndentStandard.xml @@ -0,0 +1,39 @@ + + + + + + + ->bar() + ->baz(); + ]]> + + + -> + bar()-> + baz(); + ]]> + + + + + ->bar() + ->baz(); + ]]> + + + ->bar() +->baz(); + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeClosingBraceStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeClosingBraceStandard.xml new file mode 100644 index 00000000..c8d6e274 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeClosingBraceStandard.xml @@ -0,0 +1,23 @@ + + + + + + + + + + } + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeIndentStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeIndentStandard.xml new file mode 100644 index 00000000..fafa07ac --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeIndentStandard.xml @@ -0,0 +1,29 @@ + + + + + + + if ($test) { + $var = 1; + } +} + ]]> + + + if ($test) { +$var = 1; +} +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php new file mode 100644 index 00000000..dbd61f3d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php @@ -0,0 +1,150 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClassDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param integer $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $errorData = [strtolower($tokens[$stackPtr]['content'])]; + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + $error = 'Possible parse error: %s missing opening or closing brace'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $errorData); + return; + } + + $curlyBrace = $tokens[$stackPtr]['scope_opener']; + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($curlyBrace - 1), $stackPtr, true); + $classLine = $tokens[$lastContent]['line']; + $braceLine = $tokens[$curlyBrace]['line']; + if ($braceLine === $classLine) { + $phpcsFile->recordMetric($stackPtr, 'Class opening brace placement', 'same line'); + $error = 'Opening brace of a %s must be on the line after the definition'; + $fix = $phpcsFile->addFixableError($error, $curlyBrace, 'OpenBraceNewLine', $errorData); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if ($tokens[($curlyBrace - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($curlyBrace - 1), ''); + } + + $phpcsFile->fixer->addNewlineBefore($curlyBrace); + $phpcsFile->fixer->endChangeset(); + } + + return; + } else { + $phpcsFile->recordMetric($stackPtr, 'Class opening brace placement', 'new line'); + + if ($braceLine > ($classLine + 1)) { + $error = 'Opening brace of a %s must be on the line following the %s declaration; found %s line(s)'; + $data = [ + $tokens[$stackPtr]['content'], + $tokens[$stackPtr]['content'], + ($braceLine - $classLine - 1), + ]; + $fix = $phpcsFile->addFixableError($error, $curlyBrace, 'OpenBraceWrongLine', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($curlyBrace - 1); $i > $lastContent; $i--) { + if ($tokens[$i]['line'] === ($tokens[$curlyBrace]['line'] + 1)) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + }//end if + }//end if + + if ($tokens[($curlyBrace + 1)]['content'] !== $phpcsFile->eolChar) { + $error = 'Opening %s brace must be on a line by itself'; + + $nextNonWhitespace = $phpcsFile->findNext(T_WHITESPACE, ($curlyBrace + 1), null, true); + if ($tokens[$nextNonWhitespace]['code'] === T_PHPCS_IGNORE) { + // Don't auto-fix if the next thing is a PHPCS ignore annotation. + $phpcsFile->addError($error, $curlyBrace, 'OpenBraceNotAlone', $errorData); + } else { + $fix = $phpcsFile->addFixableError($error, $curlyBrace, 'OpenBraceNotAlone', $errorData); + if ($fix === true) { + $phpcsFile->fixer->addNewline($curlyBrace); + } + } + } + + if ($tokens[($curlyBrace - 1)]['code'] === T_WHITESPACE) { + $prevContent = $tokens[($curlyBrace - 1)]['content']; + if ($prevContent === $phpcsFile->eolChar) { + $spaces = 0; + } else { + $spaces = $tokens[($curlyBrace - 1)]['length']; + } + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $expected = ($tokens[$first]['column'] - 1); + if ($spaces !== $expected) { + $error = 'Expected %s spaces before opening brace; %s found'; + $data = [ + $expected, + $spaces, + ]; + + $fix = $phpcsFile->addFixableError($error, $curlyBrace, 'SpaceBeforeBrace', $data); + if ($fix === true) { + $indent = str_repeat(' ', $expected); + if ($spaces === 0) { + $phpcsFile->fixer->addContentBefore($curlyBrace, $indent); + } else { + $phpcsFile->fixer->replaceToken(($curlyBrace - 1), $indent); + } + } + } + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php new file mode 100644 index 00000000..a01ea2cc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php @@ -0,0 +1,119 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class ClassCommentSniff extends FileCommentSniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $type = strtolower($tokens[$stackPtr]['content']); + $errorData = [$type]; + + $find = Tokens::$methodPrefixes; + $find[T_WHITESPACE] = T_WHITESPACE; + + for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { + if (isset($find[$tokens[$commentEnd]['code']]) === true) { + continue; + } + + if ($tokens[$commentEnd]['code'] === T_ATTRIBUTE_END + && isset($tokens[$commentEnd]['attribute_opener']) === true + ) { + $commentEnd = $tokens[$commentEnd]['attribute_opener']; + continue; + } + + break; + } + + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG + && $tokens[$commentEnd]['code'] !== T_COMMENT + ) { + $errorData[] = $phpcsFile->getDeclarationName($stackPtr); + $phpcsFile->addError('Missing doc comment for %s %s', $stackPtr, 'Missing', $errorData); + $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'no'); + return; + } + + $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'yes'); + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a %s comment', $stackPtr, 'WrongStyle', $errorData); + return; + } + + // Check each tag. + $this->processTags($phpcsFile, $stackPtr, $tokens[$commentEnd]['comment_opener']); + + }//end process() + + + /** + * Process the version tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processVersion($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if ((strstr($content, 'Release:') === false)) { + $error = 'Invalid version "%s" in doc comment; consider "Release: " instead'; + $data = [$content]; + $phpcsFile->addWarning($error, $tag, 'InvalidVersion', $data); + } + } + + }//end processVersion() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php new file mode 100644 index 00000000..6a445846 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php @@ -0,0 +1,582 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class FileCommentSniff implements Sniff +{ + + /** + * Tags in correct order and related info. + * + * @var array + */ + protected $tags = [ + '@category' => [ + 'required' => true, + 'allow_multiple' => false, + ], + '@package' => [ + 'required' => true, + 'allow_multiple' => false, + ], + '@subpackage' => [ + 'required' => false, + 'allow_multiple' => false, + ], + '@author' => [ + 'required' => true, + 'allow_multiple' => true, + ], + '@copyright' => [ + 'required' => false, + 'allow_multiple' => true, + ], + '@license' => [ + 'required' => true, + 'allow_multiple' => false, + ], + '@version' => [ + 'required' => false, + 'allow_multiple' => false, + ], + '@link' => [ + 'required' => true, + 'allow_multiple' => true, + ], + '@see' => [ + 'required' => false, + 'allow_multiple' => true, + ], + '@since' => [ + 'required' => false, + 'allow_multiple' => false, + ], + '@deprecated' => [ + 'required' => false, + 'allow_multiple' => false, + ], + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Find the next non whitespace token. + $commentStart = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + + // Allow declare() statements at the top of the file. + if ($tokens[$commentStart]['code'] === T_DECLARE) { + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($commentStart + 1)); + $commentStart = $phpcsFile->findNext(T_WHITESPACE, ($semicolon + 1), null, true); + } + + // Ignore vim header. + if ($tokens[$commentStart]['code'] === T_COMMENT) { + if (strstr($tokens[$commentStart]['content'], 'vim:') !== false) { + $commentStart = $phpcsFile->findNext( + T_WHITESPACE, + ($commentStart + 1), + null, + true + ); + } + } + + $errorToken = ($stackPtr + 1); + if (isset($tokens[$errorToken]) === false) { + $errorToken--; + } + + if ($tokens[$commentStart]['code'] === T_CLOSE_TAG) { + // We are only interested if this is the first open tag. + return ($phpcsFile->numTokens + 1); + } else if ($tokens[$commentStart]['code'] === T_COMMENT) { + $error = 'You must use "/**" style comments for a file comment'; + $phpcsFile->addError($error, $errorToken, 'WrongStyle'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'yes'); + return ($phpcsFile->numTokens + 1); + } else if ($commentStart === false + || $tokens[$commentStart]['code'] !== T_DOC_COMMENT_OPEN_TAG + ) { + $phpcsFile->addError('Missing file doc comment', $errorToken, 'Missing'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'no'); + return ($phpcsFile->numTokens + 1); + } + + $commentEnd = $tokens[$commentStart]['comment_closer']; + + for ($nextToken = ($commentEnd + 1); $nextToken < $phpcsFile->numTokens; $nextToken++) { + if ($tokens[$nextToken]['code'] === T_WHITESPACE) { + continue; + } + + if ($tokens[$nextToken]['code'] === T_ATTRIBUTE + && isset($tokens[$nextToken]['attribute_closer']) === true + ) { + $nextToken = $tokens[$nextToken]['attribute_closer']; + continue; + } + + break; + } + + if ($nextToken === $phpcsFile->numTokens) { + $nextToken--; + } + + $ignore = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_FUNCTION, + T_CLOSURE, + T_PUBLIC, + T_PRIVATE, + T_PROTECTED, + T_FINAL, + T_STATIC, + T_ABSTRACT, + T_CONST, + T_PROPERTY, + ]; + + if (in_array($tokens[$nextToken]['code'], $ignore, true) === true) { + $phpcsFile->addError('Missing file doc comment', $stackPtr, 'Missing'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'no'); + return ($phpcsFile->numTokens + 1); + } + + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'yes'); + + // Check the PHP Version, which should be in some text before the first tag. + $found = false; + for ($i = ($commentStart + 1); $i < $commentEnd; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_TAG) { + break; + } else if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING + && strstr(strtolower($tokens[$i]['content']), 'php version') !== false + ) { + $found = true; + break; + } + } + + if ($found === false) { + $error = 'PHP version not specified'; + $phpcsFile->addWarning($error, $commentEnd, 'MissingVersion'); + } + + // Check each tag. + $this->processTags($phpcsFile, $stackPtr, $commentStart); + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + + /** + * Processes each required or optional tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart Position in the stack where the comment started. + * + * @return void + */ + protected function processTags($phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + if (get_class($this) === 'PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FileCommentSniff') { + $docBlock = 'file'; + } else { + $docBlock = 'class'; + } + + $commentEnd = $tokens[$commentStart]['comment_closer']; + + $foundTags = []; + $tagTokens = []; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + $name = $tokens[$tag]['content']; + if (isset($this->tags[$name]) === false) { + continue; + } + + if ($this->tags[$name]['allow_multiple'] === false && isset($tagTokens[$name]) === true) { + $error = 'Only one %s tag is allowed in a %s comment'; + $data = [ + $name, + $docBlock, + ]; + $phpcsFile->addError($error, $tag, 'Duplicate'.ucfirst(substr($name, 1)).'Tag', $data); + } + + $foundTags[] = $name; + $tagTokens[$name][] = $tag; + + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for %s tag in %s comment'; + $data = [ + $name, + $docBlock, + ]; + $phpcsFile->addError($error, $tag, 'Empty'.ucfirst(substr($name, 1)).'Tag', $data); + continue; + } + }//end foreach + + // Check if the tags are in the correct position. + $pos = 0; + foreach ($this->tags as $tag => $tagData) { + if (isset($tagTokens[$tag]) === false) { + if ($tagData['required'] === true) { + $error = 'Missing %s tag in %s comment'; + $data = [ + $tag, + $docBlock, + ]; + $phpcsFile->addError($error, $commentEnd, 'Missing'.ucfirst(substr($tag, 1)).'Tag', $data); + } + + continue; + } else { + $method = 'process'.substr($tag, 1); + if (method_exists($this, $method) === true) { + // Process each tag if a method is defined. + call_user_func([$this, $method], $phpcsFile, $tagTokens[$tag]); + } + } + + if (isset($foundTags[$pos]) === false) { + break; + } + + if ($foundTags[$pos] !== $tag) { + $error = 'The tag in position %s should be the %s tag'; + $data = [ + ($pos + 1), + $tag, + ]; + $phpcsFile->addError($error, $tokens[$commentStart]['comment_tags'][$pos], ucfirst(substr($tag, 1)).'TagOrder', $data); + } + + // Account for multiple tags. + $pos++; + while (isset($foundTags[$pos]) === true && $foundTags[$pos] === $tag) { + $pos++; + } + }//end foreach + + }//end processTags() + + + /** + * Process the category tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processCategory($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if (Common::isUnderscoreName($content) !== true) { + $newContent = str_replace(' ', '_', $content); + $nameBits = explode('_', $newContent); + $firstBit = array_shift($nameBits); + $newName = ucfirst($firstBit).'_'; + foreach ($nameBits as $bit) { + if ($bit !== '') { + $newName .= ucfirst($bit).'_'; + } + } + + $error = 'Category name "%s" is not valid; consider "%s" instead'; + $validName = trim($newName, '_'); + $data = [ + $content, + $validName, + ]; + $phpcsFile->addError($error, $tag, 'InvalidCategory', $data); + } + }//end foreach + + }//end processCategory() + + + /** + * Process the package tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processPackage($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if (Common::isUnderscoreName($content) === true) { + continue; + } + + $newContent = str_replace(' ', '_', $content); + $newContent = trim($newContent, '_'); + $newContent = preg_replace('/[^A-Za-z_]/', '', $newContent); + + if ($newContent === '') { + $error = 'Package name "%s" is not valid'; + $data = [$content]; + $phpcsFile->addError($error, $tag, 'InvalidPackageValue', $data); + } else { + $nameBits = explode('_', $newContent); + $firstBit = array_shift($nameBits); + $newName = strtoupper($firstBit[0]).substr($firstBit, 1).'_'; + foreach ($nameBits as $bit) { + if ($bit !== '') { + $newName .= strtoupper($bit[0]).substr($bit, 1).'_'; + } + } + + $error = 'Package name "%s" is not valid; consider "%s" instead'; + $validName = trim($newName, '_'); + $data = [ + $content, + $validName, + ]; + $phpcsFile->addError($error, $tag, 'InvalidPackage', $data); + }//end if + }//end foreach + + }//end processPackage() + + + /** + * Process the subpackage tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processSubpackage($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if (Common::isUnderscoreName($content) === true) { + continue; + } + + $newContent = str_replace(' ', '_', $content); + $nameBits = explode('_', $newContent); + $firstBit = array_shift($nameBits); + $newName = strtoupper($firstBit[0]).substr($firstBit, 1).'_'; + foreach ($nameBits as $bit) { + if ($bit !== '') { + $newName .= strtoupper($bit[0]).substr($bit, 1).'_'; + } + } + + $error = 'Subpackage name "%s" is not valid; consider "%s" instead'; + $validName = trim($newName, '_'); + $data = [ + $content, + $validName, + ]; + $phpcsFile->addError($error, $tag, 'InvalidSubpackage', $data); + }//end foreach + + }//end processSubpackage() + + + /** + * Process the author tag(s) that this header comment has. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processAuthor($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + $local = '\da-zA-Z-_+'; + // Dot character cannot be the first or last character in the local-part. + $localMiddle = $local.'.\w'; + if (preg_match('/^([^<]*)\s+<(['.$local.'](['.$localMiddle.']*['.$local.'])*@[\da-zA-Z][-.\w]*[\da-zA-Z]\.[a-zA-Z]{2,})>$/', $content) === 0) { + $error = 'Content of the @author tag must be in the form "Display Name "'; + $phpcsFile->addError($error, $tag, 'InvalidAuthors'); + } + } + + }//end processAuthor() + + + /** + * Process the copyright tags. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processCopyright($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + $matches = []; + if (preg_match('/^([0-9]{4})((.{1})([0-9]{4}))? (.+)$/', $content, $matches) !== 0) { + // Check earliest-latest year order. + if ($matches[3] !== '' && $matches[3] !== null) { + if ($matches[3] !== '-') { + $error = 'A hyphen must be used between the earliest and latest year'; + $phpcsFile->addError($error, $tag, 'CopyrightHyphen'); + } + + if ($matches[4] !== '' && $matches[4] !== null && $matches[4] < $matches[1]) { + $error = "Invalid year span \"$matches[1]$matches[3]$matches[4]\" found; consider \"$matches[4]-$matches[1]\" instead"; + $phpcsFile->addWarning($error, $tag, 'InvalidCopyright'); + } + } + } else { + $error = '@copyright tag must contain a year and the name of the copyright holder'; + $phpcsFile->addError($error, $tag, 'IncompleteCopyright'); + } + }//end foreach + + }//end processCopyright() + + + /** + * Process the license tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processLicense($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + $matches = []; + preg_match('/^([^\s]+)\s+(.*)/', $content, $matches); + if (count($matches) !== 3) { + $error = '@license tag must contain a URL and a license name'; + $phpcsFile->addError($error, $tag, 'IncompleteLicense'); + } + } + + }//end processLicense() + + + /** + * Process the version tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processVersion($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if (strstr($content, 'CVS:') === false + && strstr($content, 'SVN:') === false + && strstr($content, 'GIT:') === false + && strstr($content, 'HG:') === false + ) { + $error = 'Invalid version "%s" in file comment; consider "CVS: " or "SVN: " or "GIT: " or "HG: " instead'; + $data = [$content]; + $phpcsFile->addWarning($error, $tag, 'InvalidVersion', $data); + } + } + + }//end processVersion() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php new file mode 100644 index 00000000..408856fc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php @@ -0,0 +1,525 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCommentSniff implements Sniff +{ + + /** + * Disable the check for functions with a lower visibility than the value given. + * + * Allowed values are public, protected, and private. + * + * @var string + */ + public $minimumVisibility = 'private'; + + /** + * Array of methods which do not require a return type. + * + * @var array + */ + public $specialMethods = [ + '__construct', + '__destruct', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $scopeModifier = $phpcsFile->getMethodProperties($stackPtr)['scope']; + if ($scopeModifier === 'protected' + && $this->minimumVisibility === 'public' + || $scopeModifier === 'private' + && ($this->minimumVisibility === 'public' || $this->minimumVisibility === 'protected') + ) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $ignore = Tokens::$methodPrefixes; + $ignore[T_WHITESPACE] = T_WHITESPACE; + + for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { + if (isset($ignore[$tokens[$commentEnd]['code']]) === true) { + continue; + } + + if ($tokens[$commentEnd]['code'] === T_ATTRIBUTE_END + && isset($tokens[$commentEnd]['attribute_opener']) === true + ) { + $commentEnd = $tokens[$commentEnd]['attribute_opener']; + continue; + } + + break; + } + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + // Inline comments might just be closing comments for + // control structures or functions instead of function comments + // using the wrong comment type. If there is other code on the line, + // assume they relate to that code. + $prev = $phpcsFile->findPrevious($ignore, ($commentEnd - 1), null, true); + if ($prev !== false && $tokens[$prev]['line'] === $tokens[$commentEnd]['line']) { + $commentEnd = $prev; + } + } + + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG + && $tokens[$commentEnd]['code'] !== T_COMMENT + ) { + $function = $phpcsFile->getDeclarationName($stackPtr); + $phpcsFile->addError( + 'Missing doc comment for function %s()', + $stackPtr, + 'Missing', + [$function] + ); + $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'no'); + return; + } else { + $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'yes'); + } + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a function comment', $stackPtr, 'WrongStyle'); + return; + } + + if ($tokens[$commentEnd]['line'] !== ($tokens[$stackPtr]['line'] - 1)) { + for ($i = ($commentEnd + 1); $i < $stackPtr; $i++) { + if ($tokens[$i]['column'] !== 1) { + continue; + } + + if ($tokens[$i]['code'] === T_WHITESPACE + && $tokens[$i]['line'] !== $tokens[($i + 1)]['line'] + ) { + $error = 'There must be no blank lines after the function comment'; + $phpcsFile->addError($error, $commentEnd, 'SpacingAfter'); + break; + } + } + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@see') { + // Make sure the tag isn't empty. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for @see tag in function comment'; + $phpcsFile->addError($error, $tag, 'EmptySees'); + } + } + } + + $this->processReturn($phpcsFile, $stackPtr, $commentStart); + $this->processThrows($phpcsFile, $stackPtr, $commentStart); + $this->processParams($phpcsFile, $stackPtr, $commentStart); + + }//end process() + + + /** + * Process the return comment of this function comment. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + // Skip constructor and destructor. + $methodName = $phpcsFile->getDeclarationName($stackPtr); + $isSpecialMethod = in_array($methodName, $this->specialMethods, true); + + $return = null; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@return') { + if ($return !== null) { + $error = 'Only 1 @return tag is allowed in a function comment'; + $phpcsFile->addError($error, $tag, 'DuplicateReturn'); + return; + } + + $return = $tag; + } + } + + if ($return !== null) { + $content = $tokens[($return + 2)]['content']; + if (empty($content) === true || $tokens[($return + 2)]['code'] !== T_DOC_COMMENT_STRING) { + $error = 'Return type missing for @return tag in function comment'; + $phpcsFile->addError($error, $return, 'MissingReturnType'); + } + } else { + if ($isSpecialMethod === true) { + return; + } + + $error = 'Missing @return tag in function comment'; + $phpcsFile->addError($error, $tokens[$commentStart]['comment_closer'], 'MissingReturn'); + }//end if + + }//end processReturn() + + + /** + * Process any throw tags that this function comment has. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] !== '@throws') { + continue; + } + + $exception = null; + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = []; + preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[($tag + 2)]['content'], $matches); + $exception = $matches[1]; + } + + if ($exception === null) { + $error = 'Exception type missing for @throws tag in function comment'; + $phpcsFile->addError($error, $tag, 'InvalidThrows'); + } + }//end foreach + + }//end processThrows() + + + /** + * Process the function parameter comments. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processParams(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + $params = []; + $maxType = 0; + $maxVar = 0; + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($tokens[$tag]['content'] !== '@param') { + continue; + } + + $type = ''; + $typeSpace = 0; + $var = ''; + $varSpace = 0; + $comment = ''; + $commentEnd = 0; + $commentTokens = []; + + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = []; + preg_match('/((?:(?![$.]|&(?=\$)).)*)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches); + + if (empty($matches) === false) { + $typeLen = strlen($matches[1]); + $type = trim($matches[1]); + $typeSpace = ($typeLen - strlen($type)); + $typeLen = strlen($type); + if ($typeLen > $maxType) { + $maxType = $typeLen; + } + } + + if (isset($matches[2]) === true) { + $var = $matches[2]; + $varLen = strlen($var); + if ($varLen > $maxVar) { + $maxVar = $varLen; + } + + if (isset($matches[4]) === true) { + $varSpace = strlen($matches[3]); + $comment = $matches[4]; + + // Any strings until the next tag belong to this comment. + if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) { + $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; + } else { + $end = $tokens[$commentStart]['comment_closer']; + } + + for ($i = ($tag + 3); $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + $comment .= ' '.$tokens[$i]['content']; + $commentEnd = $i; + $commentTokens[] = $i; + } + } + } else { + $error = 'Missing parameter comment'; + $phpcsFile->addError($error, $tag, 'MissingParamComment'); + }//end if + } else { + $error = 'Missing parameter name'; + $phpcsFile->addError($error, $tag, 'MissingParamName'); + }//end if + } else { + $error = 'Missing parameter type'; + $phpcsFile->addError($error, $tag, 'MissingParamType'); + }//end if + + $params[] = [ + 'tag' => $tag, + 'type' => $type, + 'var' => $var, + 'comment' => $comment, + 'comment_end' => $commentEnd, + 'comment_tokens' => $commentTokens, + 'type_space' => $typeSpace, + 'var_space' => $varSpace, + ]; + }//end foreach + + $realParams = $phpcsFile->getMethodParameters($stackPtr); + $foundParams = []; + + // We want to use ... for all variable length arguments, so add + // this prefix to the variable name so comparisons are easier. + foreach ($realParams as $pos => $param) { + if ($param['variable_length'] === true) { + $realParams[$pos]['name'] = '...'.$realParams[$pos]['name']; + } + } + + foreach ($params as $pos => $param) { + if ($param['var'] === '') { + continue; + } + + $foundParams[] = $param['var']; + + if (trim($param['type']) !== '') { + // Check number of spaces after the type. + $spaces = ($maxType - strlen($param['type']) + 1); + if ($param['type_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter type; %s found'; + $data = [ + $spaces, + $param['type_space'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamType', $data); + if ($fix === true) { + $commentToken = ($param['tag'] + 2); + + $content = $param['type']; + $content .= str_repeat(' ', $spaces); + $content .= $param['var']; + $content .= str_repeat(' ', $param['var_space']); + + $wrapLength = ($tokens[$commentToken]['length'] - $param['type_space'] - $param['var_space'] - strlen($param['type']) - strlen($param['var'])); + + $star = $phpcsFile->findPrevious(T_DOC_COMMENT_STAR, $param['tag']); + $spaceLength = (strlen($content) + $tokens[($commentToken - 1)]['length'] + $tokens[($commentToken - 2)]['length']); + + $padding = str_repeat(' ', ($tokens[$star]['column'] - 1)); + $padding .= '* '; + $padding .= str_repeat(' ', $spaceLength); + + $content .= wordwrap( + $param['comment'], + $wrapLength, + $phpcsFile->eolChar.$padding + ); + + $phpcsFile->fixer->replaceToken($commentToken, $content); + for ($i = ($commentToken + 1); $i <= $param['comment_end']; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + }//end if + }//end if + }//end if + + // Make sure the param name is correct. + if (isset($realParams[$pos]) === true) { + $realName = $realParams[$pos]['name']; + if ($realName !== $param['var']) { + $code = 'ParamNameNoMatch'; + $data = [ + $param['var'], + $realName, + ]; + + $error = 'Doc comment for parameter %s does not match '; + if (strtolower($param['var']) === strtolower($realName)) { + $error .= 'case of '; + $code = 'ParamNameNoCaseMatch'; + } + + $error .= 'actual variable name %s'; + + $phpcsFile->addError($error, $param['tag'], $code, $data); + } + } else if (substr($param['var'], -4) !== ',...') { + // We must have an extra parameter comment. + $error = 'Superfluous parameter comment'; + $phpcsFile->addError($error, $param['tag'], 'ExtraParamComment'); + }//end if + + if ($param['comment'] === '') { + continue; + } + + // Check number of spaces after the param name. + $spaces = ($maxVar - strlen($param['var']) + 1); + if ($param['var_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter name; %s found'; + $data = [ + $spaces, + $param['var_space'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamName', $data); + if ($fix === true) { + $commentToken = ($param['tag'] + 2); + + $content = $param['type']; + $content .= str_repeat(' ', $param['type_space']); + $content .= $param['var']; + $content .= str_repeat(' ', $spaces); + + $wrapLength = ($tokens[$commentToken]['length'] - $param['type_space'] - $param['var_space'] - strlen($param['type']) - strlen($param['var'])); + + $star = $phpcsFile->findPrevious(T_DOC_COMMENT_STAR, $param['tag']); + $spaceLength = (strlen($content) + $tokens[($commentToken - 1)]['length'] + $tokens[($commentToken - 2)]['length']); + + $padding = str_repeat(' ', ($tokens[$star]['column'] - 1)); + $padding .= '* '; + $padding .= str_repeat(' ', $spaceLength); + + $content .= wordwrap( + $param['comment'], + $wrapLength, + $phpcsFile->eolChar.$padding + ); + + $phpcsFile->fixer->replaceToken($commentToken, $content); + for ($i = ($commentToken + 1); $i <= $param['comment_end']; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + }//end if + }//end if + + // Check the alignment of multi-line param comments. + if ($param['tag'] !== $param['comment_end']) { + $wrapLength = ($tokens[($param['tag'] + 2)]['length'] - $param['type_space'] - $param['var_space'] - strlen($param['type']) - strlen($param['var'])); + + $startColumn = ($tokens[($param['tag'] + 2)]['column'] + $tokens[($param['tag'] + 2)]['length'] - $wrapLength); + + $star = $phpcsFile->findPrevious(T_DOC_COMMENT_STAR, $param['tag']); + $expected = ($startColumn - $tokens[$star]['column'] - 1); + + foreach ($param['comment_tokens'] as $commentToken) { + if ($tokens[$commentToken]['column'] === $startColumn) { + continue; + } + + $found = 0; + if ($tokens[($commentToken - 1)]['code'] === T_DOC_COMMENT_WHITESPACE) { + $found = $tokens[($commentToken - 1)]['length']; + } + + $error = 'Parameter comment not aligned correctly; expected %s spaces but found %s'; + $data = [ + $expected, + $found, + ]; + + if ($found < $expected) { + $code = 'ParamCommentAlignment'; + } else { + $code = 'ParamCommentAlignmentExceeded'; + } + + $fix = $phpcsFile->addFixableError($error, $commentToken, $code, $data); + if ($fix === true) { + $padding = str_repeat(' ', $expected); + if ($tokens[($commentToken - 1)]['code'] === T_DOC_COMMENT_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($commentToken - 1), $padding); + } else { + $phpcsFile->fixer->addContentBefore($commentToken, $padding); + } + } + }//end foreach + }//end if + }//end foreach + + $realNames = []; + foreach ($realParams as $realParam) { + $realNames[] = $realParam['name']; + } + + // Report missing comments. + $diff = array_diff($realNames, $foundParams); + foreach ($diff as $neededParam) { + $error = 'Doc comment for parameter "%s" missing'; + $data = [$neededParam]; + $phpcsFile->addError($error, $commentStart, 'MissingParamTag', $data); + } + + }//end processParams() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/InlineCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/InlineCommentSniff.php new file mode 100644 index 00000000..aa9f3753 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/InlineCommentSniff.php @@ -0,0 +1,68 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class InlineCommentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_COMMENT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['content'][0] === '#') { + $phpcsFile->recordMetric($stackPtr, 'Inline comment style', '# ...'); + + $error = 'Perl-style comments are not allowed. Use "// Comment."'; + $error .= ' or "/* comment */" instead.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'WrongStyle'); + if ($fix === true) { + $newComment = ltrim($tokens[$stackPtr]['content'], '# '); + $newComment = '// '.$newComment; + $phpcsFile->fixer->replaceToken($stackPtr, $newComment); + } + } else if ($tokens[$stackPtr]['content'][0] === '/' + && $tokens[$stackPtr]['content'][1] === '/' + ) { + $phpcsFile->recordMetric($stackPtr, 'Inline comment style', '// ...'); + } else if ($tokens[$stackPtr]['content'][0] === '/' + && $tokens[$stackPtr]['content'][1] === '*' + ) { + $phpcsFile->recordMetric($stackPtr, 'Inline comment style', '/* ... */'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php new file mode 100644 index 00000000..edd2d6be --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Sniffs\AbstractPatternSniff; + +class ControlSignatureSniff extends AbstractPatternSniff +{ + + /** + * If true, comments will be ignored if they are found in the code. + * + * @var boolean + */ + public $ignoreComments = true; + + + /** + * Returns the patterns that this test wishes to verify. + * + * @return string[] + */ + protected function getPatterns() + { + return [ + 'do {EOL...} while (...);EOL', + 'while (...) {EOL', + 'for (...) {EOL', + 'if (...) {EOL', + 'foreach (...) {EOL', + '} else if (...) {EOL', + '} elseif (...) {EOL', + '} else {EOL', + 'do {EOL', + 'match (...) {EOL', + ]; + + }//end getPatterns() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/MultiLineConditionSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/MultiLineConditionSniff.php new file mode 100644 index 00000000..fff62bb1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/MultiLineConditionSniff.php @@ -0,0 +1,283 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class MultiLineConditionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_ELSEIF, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false) { + return; + } + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + $spaceAfterOpen = 0; + if ($tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + if (strpos($tokens[($openBracket + 1)]['content'], $phpcsFile->eolChar) !== false) { + $spaceAfterOpen = 'newline'; + } else { + $spaceAfterOpen = $tokens[($openBracket + 1)]['length']; + } + } + + if ($spaceAfterOpen !== 0) { + $error = 'First condition of a multi-line IF statement must directly follow the opening parenthesis'; + $fix = $phpcsFile->addFixableError($error, ($openBracket + 1), 'SpacingAfterOpenBrace'); + if ($fix === true) { + if ($spaceAfterOpen === 'newline') { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } else { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } + } + } + + // We need to work out how far indented the if statement + // itself is, so we can work out how far to indent conditions. + $statementIndent = 0; + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + if ($tokens[$i]['line'] !== $tokens[$stackPtr]['line']) { + $i++; + break; + } + } + + if ($i >= 0 && $tokens[$i]['code'] === T_WHITESPACE) { + $statementIndent = $tokens[$i]['length']; + } + + // Each line between the parenthesis should be indented 4 spaces + // and start with an operator, unless the line is inside a + // function call, in which case it is ignored. + $prevLine = $tokens[$openBracket]['line']; + for ($i = ($openBracket + 1); $i <= $closeBracket; $i++) { + if ($i === $closeBracket && $tokens[$openBracket]['line'] !== $tokens[$i]['line']) { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), null, true); + if ($tokens[$prev]['line'] === $tokens[$i]['line']) { + // Closing bracket is on the same line as a condition. + $error = 'Closing parenthesis of a multi-line IF statement must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'CloseBracketNewLine'); + if ($fix === true) { + // Account for a comment at the end of the line. + $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), null, true); + if ($tokens[$next]['code'] !== T_COMMENT + && isset(Tokens::$phpcsCommentTokens[$tokens[$next]['code']]) === false + ) { + $phpcsFile->fixer->addNewlineBefore($closeBracket); + } else { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($closeBracket, ''); + $phpcsFile->fixer->addContentBefore($next, ')'); + $phpcsFile->fixer->endChangeset(); + } + } + } + }//end if + + if ($tokens[$i]['line'] !== $prevLine) { + if ($tokens[$i]['line'] === $tokens[$closeBracket]['line']) { + $next = $phpcsFile->findNext(T_WHITESPACE, $i, null, true); + if ($next !== $closeBracket) { + $expectedIndent = ($statementIndent + $this->indent); + } else { + // Closing brace needs to be indented to the same level + // as the statement. + $expectedIndent = $statementIndent; + }//end if + } else { + $expectedIndent = ($statementIndent + $this->indent); + }//end if + + if ($tokens[$i]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$i]['code']]) === true + ) { + $prevLine = $tokens[$i]['line']; + continue; + } + + // We changed lines, so this should be a whitespace indent token. + if ($tokens[$i]['code'] !== T_WHITESPACE) { + $foundIndent = 0; + } else { + $foundIndent = $tokens[$i]['length']; + } + + if ($expectedIndent !== $foundIndent) { + $error = 'Multi-line IF statement not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'Alignment', $data); + if ($fix === true) { + $spaces = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $spaces); + } else { + $phpcsFile->fixer->replaceToken($i, $spaces); + } + } + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $i, null, true); + if ($next !== $closeBracket && $tokens[$next]['line'] === $tokens[$i]['line']) { + if (isset(Tokens::$booleanOperators[$tokens[$next]['code']]) === false) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), $openBracket, true); + $fixable = true; + if (isset(Tokens::$booleanOperators[$tokens[$prev]['code']]) === false + && $phpcsFile->findNext(T_WHITESPACE, ($prev + 1), $next, true) !== false + ) { + // Condition spread over multi-lines interspersed with comments. + $fixable = false; + } + + $error = 'Each line in a multi-line IF statement must begin with a boolean operator'; + if ($fixable === false) { + $phpcsFile->addError($error, $next, 'StartWithBoolean'); + } else { + $fix = $phpcsFile->addFixableError($error, $next, 'StartWithBoolean'); + if ($fix === true) { + if (isset(Tokens::$booleanOperators[$tokens[$prev]['code']]) === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($prev, ''); + $phpcsFile->fixer->addContentBefore($next, $tokens[$prev]['content'].' '); + $phpcsFile->fixer->endChangeset(); + } else { + for ($x = ($prev + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + } + } + } + }//end if + }//end if + + $prevLine = $tokens[$i]['line']; + }//end if + + if ($tokens[$i]['code'] === T_STRING) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true); + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + // This is a function call, so skip to the end as they + // have their own indentation rules. + $i = $tokens[$next]['parenthesis_closer']; + $prevLine = $tokens[$i]['line']; + continue; + } + } + }//end for + + // From here on, we are checking the spacing of the opening and closing + // braces. If this IF statement does not use braces, we end here. + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + // The opening brace needs to be one space away from the closing parenthesis. + $openBrace = $tokens[$stackPtr]['scope_opener']; + $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), $openBrace, true); + if ($next !== false) { + // Probably comments in between tokens, so don't check. + return; + } + + if ($tokens[$openBrace]['line'] > $tokens[$closeBracket]['line']) { + $length = -1; + } else if ($openBrace === ($closeBracket + 1)) { + $length = 0; + } else if ($openBrace === ($closeBracket + 2) + && $tokens[($closeBracket + 1)]['code'] === T_WHITESPACE + ) { + $length = $tokens[($closeBracket + 1)]['length']; + } else { + // Confused, so don't check. + $length = 1; + } + + if ($length === 1) { + return; + } + + $data = [$length]; + $code = 'SpaceBeforeOpenBrace'; + + $error = 'There must be a single space between the closing parenthesis and the opening brace of a multi-line IF statement; found '; + if ($length === -1) { + $error .= 'newline'; + $code = 'NewlineBeforeOpenBrace'; + } else { + $error .= '%s spaces'; + } + + $fix = $phpcsFile->addFixableError($error, ($closeBracket + 1), $code, $data); + if ($fix === true) { + if ($length === 0) { + $phpcsFile->fixer->addContent($closeBracket, ' '); + } else { + $phpcsFile->fixer->replaceToken(($closeBracket + 1), ' '); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Files/IncludingFileSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Files/IncludingFileSniff.php new file mode 100644 index 00000000..04f208de --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Files/IncludingFileSniff.php @@ -0,0 +1,136 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class IncludingFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_INCLUDE_ONCE, + T_REQUIRE_ONCE, + T_REQUIRE, + T_INCLUDE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$nextToken]['code'] === T_OPEN_PARENTHESIS) { + $error = '"%s" is a statement not a function; no parentheses are required'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'BracketsNotRequired', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($tokens[$nextToken]['parenthesis_closer'], ''); + if ($tokens[($nextToken - 1)]['code'] !== T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($nextToken, ' '); + } else { + $phpcsFile->fixer->replaceToken($nextToken, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + if (count($tokens[$stackPtr]['conditions']) !== 0) { + $inCondition = true; + } else { + $inCondition = false; + } + + // Check to see if this including statement is within the parenthesis + // of a condition. If that's the case then we need to process it as being + // within a condition, as they are checking the return value. + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + foreach ($tokens[$stackPtr]['nested_parenthesis'] as $left => $right) { + if (isset($tokens[$left]['parenthesis_owner']) === true) { + $inCondition = true; + } + } + } + + // Check to see if they are assigning the return value of this + // including call. If they are then they are probably checking it, so + // it's conditional. + $previous = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if (isset(Tokens::$assignmentTokens[$tokens[$previous]['code']]) === true) { + // The have assigned the return value to it, so its conditional. + $inCondition = true; + } + + $tokenCode = $tokens[$stackPtr]['code']; + if ($inCondition === true) { + // We are inside a conditional statement. We need an include_once. + if ($tokenCode === T_REQUIRE_ONCE) { + $error = 'File is being conditionally included; '; + $error .= 'use "include_once" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseIncludeOnce'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'include_once'); + } + } else if ($tokenCode === T_REQUIRE) { + $error = 'File is being conditionally included; '; + $error .= 'use "include" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseInclude'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'include'); + } + } + } else { + // We are unconditionally including, we need a require_once. + if ($tokenCode === T_INCLUDE_ONCE) { + $error = 'File is being unconditionally included; '; + $error .= 'use "require_once" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseRequireOnce'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'require_once'); + } + } else if ($tokenCode === T_INCLUDE) { + $error = 'File is being unconditionally included; '; + $error .= 'use "require" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseRequire'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'require'); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Formatting/MultiLineAssignmentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Formatting/MultiLineAssignmentSniff.php new file mode 100644 index 00000000..0a7ff7db --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Formatting/MultiLineAssignmentSniff.php @@ -0,0 +1,106 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class MultiLineAssignmentSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EQUAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Equal sign can't be the last thing on the line. + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next === false) { + // Bad assignment. + return; + } + + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + $error = 'Multi-line assignments must have the equal sign on the second line'; + $phpcsFile->addError($error, $stackPtr, 'EqualSignLine'); + return; + } + + // Make sure it is the first thing on the line, otherwise we ignore it. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), false, true); + if ($prev === false) { + // Bad assignment. + return; + } + + if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) { + return; + } + + // Find the required indent based on the ident of the previous line. + $assignmentIndent = 0; + $prevLine = $tokens[$prev]['line']; + for ($i = ($prev - 1); $i >= 0; $i--) { + if ($tokens[$i]['line'] !== $prevLine) { + $i++; + break; + } + } + + if ($tokens[$i]['code'] === T_WHITESPACE) { + $assignmentIndent = $tokens[$i]['length']; + } + + // Find the actual indent. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1)); + + $expectedIndent = ($assignmentIndent + $this->indent); + $foundIndent = $tokens[$prev]['length']; + if ($foundIndent !== $expectedIndent) { + $error = 'Multi-line assignment not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + $phpcsFile->addError($error, $stackPtr, 'Indent', $data); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php new file mode 100644 index 00000000..3a339abe --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php @@ -0,0 +1,628 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCallSignatureSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + /** + * If TRUE, multiple arguments can be defined per line in a multi-line call. + * + * @var boolean + */ + public $allowMultipleArguments = true; + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $tokens = Tokens::$functionNameTokens; + + $tokens[] = T_VARIABLE; + $tokens[] = T_CLOSE_CURLY_BRACKET; + $tokens[] = T_CLOSE_SQUARE_BRACKET; + $tokens[] = T_CLOSE_PARENTHESIS; + + return $tokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_CLOSE_CURLY_BRACKET + && isset($tokens[$stackPtr]['scope_condition']) === true + ) { + // Not a function call. + return; + } + + // Find the next non-empty token. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { + // Not a function call. + return; + } + + if (isset($tokens[$openBracket]['parenthesis_closer']) === false) { + // Not a function call. + return; + } + + // Find the previous non-empty token. + $search = Tokens::$emptyTokens; + $search[] = T_BITWISE_AND; + $previous = $phpcsFile->findPrevious($search, ($stackPtr - 1), null, true); + if ($tokens[$previous]['code'] === T_FUNCTION) { + // It's a function definition, not a function call. + return; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + if (($stackPtr + 1) !== $openBracket) { + // Checking this: $value = my_function[*](...). + $error = 'Space before opening parenthesis of function call prohibited'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeOpenBracket'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $openBracket; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + // Modify the bracket as well to ensure a conflict if the bracket + // has been changed in some way by another sniff. + $phpcsFile->fixer->replaceToken($openBracket, '('); + $phpcsFile->fixer->endChangeset(); + } + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON) { + if (isset(Tokens::$emptyTokens[$tokens[($closeBracket + 1)]['code']]) === true) { + $error = 'Space after closing parenthesis of function call prohibited'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'SpaceAfterCloseBracket'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closeBracket + 1); $i < $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + // Modify the bracket as well to ensure a conflict if the bracket + // has been changed in some way by another sniff. + $phpcsFile->fixer->replaceToken($closeBracket, ')'); + $phpcsFile->fixer->endChangeset(); + } + } + } + + // Check if this is a single line or multi-line function call. + if ($this->isMultiLineCall($phpcsFile, $stackPtr, $openBracket, $tokens) === true) { + $this->processMultiLineCall($phpcsFile, $stackPtr, $openBracket, $tokens); + } else { + $this->processSingleLineCall($phpcsFile, $stackPtr, $openBracket, $tokens); + } + + }//end process() + + + /** + * Determine if this is a multi-line function call. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return bool + */ + public function isMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $tokens) + { + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + if ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']) { + return true; + } + + return false; + + }//end isMultiLineCall() + + + /** + * Processes single-line calls. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processSingleLineCall(File $phpcsFile, $stackPtr, $openBracket, $tokens) + { + $closer = $tokens[$openBracket]['parenthesis_closer']; + if ($openBracket === ($closer - 1)) { + return; + } + + // If the function call has no arguments or comments, enforce 0 spaces. + $next = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), $closer, true); + if ($next === false) { + $requiredSpacesAfterOpen = 0; + $requiredSpacesBeforeClose = 0; + } else { + $requiredSpacesAfterOpen = $this->requiredSpacesAfterOpen; + $requiredSpacesBeforeClose = $this->requiredSpacesBeforeClose; + } + + if ($requiredSpacesAfterOpen === 0 && $tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + // Checking this: $value = my_function([*]...). + $error = 'Space after opening parenthesis of function call prohibited'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterOpenBracket'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } + } else if ($requiredSpacesAfterOpen > 0) { + $spaceAfterOpen = 0; + if ($tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + $spaceAfterOpen = $tokens[($openBracket + 1)]['length']; + } + + if ($spaceAfterOpen !== $requiredSpacesAfterOpen) { + $error = 'Expected %s spaces after opening parenthesis; %s found'; + $data = [ + $requiredSpacesAfterOpen, + $spaceAfterOpen, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterOpenBracket', $data); + if ($fix === true) { + $padding = str_repeat(' ', $requiredSpacesAfterOpen); + if ($spaceAfterOpen === 0) { + $phpcsFile->fixer->addContent($openBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($openBracket + 1), $padding); + } + } + } + }//end if + + // Checking this: $value = my_function(...[*]). + $spaceBeforeClose = 0; + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($closer - 1), $openBracket, true); + if ($tokens[$prev]['code'] === T_END_HEREDOC || $tokens[$prev]['code'] === T_END_NOWDOC) { + // Need a newline after these tokens, so ignore this rule. + return; + } + + if ($tokens[$prev]['line'] !== $tokens[$closer]['line']) { + $spaceBeforeClose = 'newline'; + } else if ($tokens[($closer - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = $tokens[($closer - 1)]['length']; + } + + if ($spaceBeforeClose !== $requiredSpacesBeforeClose) { + $error = 'Expected %s spaces before closing parenthesis; %s found'; + $data = [ + $requiredSpacesBeforeClose, + $spaceBeforeClose, + ]; + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceBeforeCloseBracket', $data); + if ($fix === true) { + $padding = str_repeat(' ', $requiredSpacesBeforeClose); + + if ($spaceBeforeClose === 0) { + $phpcsFile->fixer->addContentBefore($closer, $padding); + } else if ($spaceBeforeClose === 'newline') { + $phpcsFile->fixer->beginChangeset(); + + $closingContent = ')'; + + $next = $phpcsFile->findNext(T_WHITESPACE, ($closer + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON) { + $closingContent .= ';'; + for ($i = ($closer + 1); $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + // We want to jump over any whitespace or inline comment and + // move the closing parenthesis after any other token. + $prev = ($closer - 1); + while (isset(Tokens::$emptyTokens[$tokens[$prev]['code']]) === true) { + if (($tokens[$prev]['code'] === T_COMMENT) + && (strpos($tokens[$prev]['content'], '*/') !== false) + ) { + break; + } + + $prev--; + } + + $phpcsFile->fixer->addContent($prev, $padding.$closingContent); + + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($closer - 1), null, true); + for ($i = ($prevNonWhitespace + 1); $i <= $closer; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($closer - 1), $padding); + }//end if + }//end if + }//end if + + }//end processSingleLineCall() + + + /** + * Processes multi-line calls. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $tokens) + { + // We need to work out how far indented the function + // call itself is, so we can work out how far to + // indent the arguments. + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + if ($tokens[$first]['code'] === T_CONSTANT_ENCAPSED_STRING + && $tokens[($first - 1)]['code'] === T_CONSTANT_ENCAPSED_STRING + ) { + // We are in a multi-line string, so find the start and use + // the indent from there. + $prev = $phpcsFile->findPrevious(T_CONSTANT_ENCAPSED_STRING, ($first - 2), null, true); + $first = $phpcsFile->findFirstOnLine(Tokens::$emptyTokens, $prev, true); + if ($first === false) { + $first = ($prev + 1); + } + } + + $foundFunctionIndent = 0; + if ($first !== false) { + if ($tokens[$first]['code'] === T_INLINE_HTML + || ($tokens[$first]['code'] === T_CONSTANT_ENCAPSED_STRING + && $tokens[($first - 1)]['code'] === T_CONSTANT_ENCAPSED_STRING) + ) { + $trimmed = ltrim($tokens[$first]['content']); + if ($trimmed === '') { + $foundFunctionIndent = strlen($tokens[$first]['content']); + } else { + $foundFunctionIndent = (strlen($tokens[$first]['content']) - strlen($trimmed)); + } + } else { + $foundFunctionIndent = ($tokens[$first]['column'] - 1); + } + } + + // Make sure the function indent is divisible by the indent size. + // We round down here because this accounts for times when the + // surrounding code is indented a little too far in, and not correctly + // at a tab stop. Without this, the function will be indented a further + // $indent spaces to the right. + $functionIndent = (int) (floor($foundFunctionIndent / $this->indent) * $this->indent); + $adjustment = 0; + + if ($foundFunctionIndent !== $functionIndent) { + $error = 'Opening statement of multi-line function call not indented correctly; expected %s spaces but found %s'; + $data = [ + $functionIndent, + $foundFunctionIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $first, 'OpeningIndent', $data); + if ($fix === true) { + $adjustment = ($functionIndent - $foundFunctionIndent); + $padding = str_repeat(' ', $functionIndent); + if ($foundFunctionIndent === 0) { + $phpcsFile->fixer->addContentBefore($first, $padding); + } else { + $phpcsFile->fixer->replaceToken(($first - 1), $padding); + } + } + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openBracket]['line']) { + $error = 'Opening parenthesis of a multi-line function call must be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentAfterOpenBracket'); + if ($fix === true) { + $phpcsFile->fixer->addContent( + $openBracket, + $phpcsFile->eolChar.str_repeat(' ', ($foundFunctionIndent + $this->indent)) + ); + } + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), null, true); + if ($tokens[$prev]['line'] === $tokens[$closeBracket]['line']) { + $error = 'Closing parenthesis of a multi-line function call must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'CloseBracketLine'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore( + $closeBracket, + $phpcsFile->eolChar.str_repeat(' ', ($foundFunctionIndent + $this->indent)) + ); + } + } + + // Each line between the parenthesis should be indented n spaces. + $lastLine = ($tokens[$openBracket]['line'] - 1); + $argStart = null; + $argEnd = null; + + // Start processing at the first argument. + $i = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), null, true); + + if ($tokens[$i]['line'] > ($tokens[$openBracket]['line'] + 1)) { + $error = 'The first argument in a multi-line function call must be on the line after the opening parenthesis'; + $fix = $phpcsFile->addFixableError($error, $i, 'FirstArgumentPosition'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($openBracket + 1); $x < $i; $x++) { + if ($tokens[$x]['line'] === $tokens[$openBracket]['line']) { + continue; + } + + if ($tokens[$x]['line'] === $tokens[$i]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + $i = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + + if ($tokens[($i - 1)]['code'] === T_WHITESPACE + && $tokens[($i - 1)]['line'] === $tokens[$i]['line'] + ) { + // Make sure we check the indent. + $i--; + } + + for ($i; $i < $closeBracket; $i++) { + if ($i > $argStart && $i < $argEnd) { + $inArg = true; + } else { + $inArg = false; + } + + if ($tokens[$i]['line'] !== $lastLine) { + $lastLine = $tokens[$i]['line']; + + // Ignore heredoc indentation. + if (isset(Tokens::$heredocTokens[$tokens[$i]['code']]) === true) { + continue; + } + + // Ignore multi-line string indentation. + if (isset(Tokens::$stringTokens[$tokens[$i]['code']]) === true + && $tokens[$i]['code'] === $tokens[($i - 1)]['code'] + ) { + continue; + } + + // Ignore inline HTML. + if ($tokens[$i]['code'] === T_INLINE_HTML) { + continue; + } + + if ($tokens[$i]['line'] !== $tokens[$openBracket]['line']) { + // We changed lines, so this should be a whitespace indent token, but first make + // sure it isn't a blank line because we don't need to check indent unless there + // is actually some code to indent. + if ($tokens[$i]['code'] === T_WHITESPACE) { + $nextCode = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), ($closeBracket + 1), true); + if ($tokens[$nextCode]['line'] !== $lastLine) { + if ($inArg === false) { + $error = 'Empty lines are not allowed in multi-line function calls'; + $fix = $phpcsFile->addFixableError($error, $i, 'EmptyLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + continue; + } + } else { + $nextCode = $i; + } + + if ($tokens[$nextCode]['line'] === $tokens[$closeBracket]['line']) { + // Closing brace needs to be indented to the same level + // as the function call. + $inArg = false; + $expectedIndent = ($foundFunctionIndent + $adjustment); + } else { + $expectedIndent = ($foundFunctionIndent + $this->indent + $adjustment); + } + + if ($tokens[$i]['code'] !== T_WHITESPACE + && $tokens[$i]['code'] !== T_DOC_COMMENT_WHITESPACE + ) { + // Just check if it is a multi-line block comment. If so, we can + // calculate the indent from the whitespace before the content. + if ($tokens[$i]['code'] === T_COMMENT + && $tokens[($i - 1)]['code'] === T_COMMENT + ) { + $trimmedLength = strlen(ltrim($tokens[$i]['content'])); + if ($trimmedLength === 0) { + // This is a blank comment line, so indenting it is + // pointless. + continue; + } + + $foundIndent = (strlen($tokens[$i]['content']) - $trimmedLength); + } else { + $foundIndent = 0; + } + } else { + $foundIndent = $tokens[$i]['length']; + } + + if ($foundIndent < $expectedIndent + || ($inArg === false + && $expectedIndent !== $foundIndent) + ) { + $error = 'Multi-line function call not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'Indent', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $padding = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $padding); + if (isset($tokens[$i]['scope_opener']) === true) { + $phpcsFile->fixer->changeCodeBlockIndent($i, $tokens[$i]['scope_closer'], $expectedIndent); + } + } else { + if ($tokens[$i]['code'] === T_COMMENT) { + $comment = $padding.ltrim($tokens[$i]['content']); + $phpcsFile->fixer->replaceToken($i, $comment); + } else { + $phpcsFile->fixer->replaceToken($i, $padding); + } + + if (isset($tokens[($i + 1)]['scope_opener']) === true) { + $phpcsFile->fixer->changeCodeBlockIndent(($i + 1), $tokens[($i + 1)]['scope_closer'], ($expectedIndent - $foundIndent)); + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + } else { + $nextCode = $i; + }//end if + + if ($inArg === false) { + $argStart = $nextCode; + $argEnd = $phpcsFile->findEndOfStatement($nextCode, [T_COLON]); + } + }//end if + + // If we are within an argument we should be ignoring commas + // as these are not signalling the end of an argument. + if ($inArg === false && $tokens[$i]['code'] === T_COMMA) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), $closeBracket, true); + if ($next === false) { + continue; + } + + if ($this->allowMultipleArguments === false) { + // Comma has to be the last token on the line. + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + $error = 'Only one argument is allowed per line in a multi-line function call'; + $fix = $phpcsFile->addFixableError($error, $next, 'MultipleArguments'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($next - 1); $x > $i; $x--) { + if ($tokens[$x]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContentBefore( + $next, + $phpcsFile->eolChar.str_repeat(' ', ($foundFunctionIndent + $this->indent)) + ); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + $argStart = $next; + $argEnd = $phpcsFile->findEndOfStatement($next, [T_COLON]); + }//end if + }//end for + + }//end processMultiLineCall() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php new file mode 100644 index 00000000..bd59a7cd --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php @@ -0,0 +1,522 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Standards\Generic\Sniffs\Functions\OpeningFunctionBraceBsdAllmanSniff; +use PHP_CodeSniffer\Standards\Generic\Sniffs\Functions\OpeningFunctionBraceKernighanRitchieSniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionDeclarationSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + || $tokens[$stackPtr]['parenthesis_opener'] === null + || $tokens[$stackPtr]['parenthesis_closer'] === null + ) { + return; + } + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + + if (strtolower($tokens[$stackPtr]['content']) === 'function') { + // Must be one space after the FUNCTION keyword. + if ($tokens[($stackPtr + 1)]['content'] === $phpcsFile->eolChar) { + $spaces = 'newline'; + } else if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $spaces = $tokens[($stackPtr + 1)]['length']; + } else { + $spaces = 0; + } + + if ($spaces !== 1) { + $error = 'Expected 1 space after FUNCTION keyword; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterFunction', $data); + if ($fix === true) { + if ($spaces === 0) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } + }//end if + + // Must be no space before the opening parenthesis. For closures, this is + // enforced by the previous check because there is no content between the keywords + // and the opening parenthesis. + // Unfinished closures are tokenized as T_FUNCTION however, and can be excluded + // by checking for the scope_opener. + if ($tokens[$stackPtr]['code'] === T_FUNCTION + && (isset($tokens[$stackPtr]['scope_opener']) === true || $phpcsFile->getMethodProperties($stackPtr)['has_body'] === false) + ) { + if ($tokens[($openBracket - 1)]['content'] === $phpcsFile->eolChar) { + $spaces = 'newline'; + } else if ($tokens[($openBracket - 1)]['code'] === T_WHITESPACE) { + $spaces = $tokens[($openBracket - 1)]['length']; + } else { + $spaces = 0; + } + + if ($spaces !== 0) { + $error = 'Expected 0 spaces before opening parenthesis; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $openBracket, 'SpaceBeforeOpenParen', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openBracket - 1), ''); + } + } + + // Must be no space before semicolon in abstract/interface methods. + if ($phpcsFile->getMethodProperties($stackPtr)['has_body'] === false) { + $end = $phpcsFile->findNext(T_SEMICOLON, $closeBracket); + if ($tokens[($end - 1)]['content'] === $phpcsFile->eolChar) { + $spaces = 'newline'; + } else if ($tokens[($end - 1)]['code'] === T_WHITESPACE) { + $spaces = $tokens[($end - 1)]['length']; + } else { + $spaces = 0; + } + + if ($spaces !== 0) { + $error = 'Expected 0 spaces before semicolon; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $end, 'SpaceBeforeSemicolon', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($end - 1), ''); + } + } + } + }//end if + + // Must be one space before and after USE keyword for closures. + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + if ($tokens[($use + 1)]['code'] !== T_WHITESPACE) { + $length = 0; + } else if ($tokens[($use + 1)]['content'] === "\t") { + $length = '\t'; + } else { + $length = $tokens[($use + 1)]['length']; + } + + if ($length !== 1) { + $error = 'Expected 1 space after USE keyword; found %s'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $use, 'SpaceAfterUse', $data); + if ($fix === true) { + if ($length === 0) { + $phpcsFile->fixer->addContent($use, ' '); + } else { + $phpcsFile->fixer->replaceToken(($use + 1), ' '); + } + } + } + + if ($tokens[($use - 1)]['code'] !== T_WHITESPACE) { + $length = 0; + } else if ($tokens[($use - 1)]['content'] === "\t") { + $length = '\t'; + } else { + $length = $tokens[($use - 1)]['length']; + } + + if ($length !== 1) { + $error = 'Expected 1 space before USE keyword; found %s'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $use, 'SpaceBeforeUse', $data); + if ($fix === true) { + if ($length === 0) { + $phpcsFile->fixer->addContentBefore($use, ' '); + } else { + $phpcsFile->fixer->replaceToken(($use - 1), ' '); + } + } + } + }//end if + }//end if + + if ($this->isMultiLineDeclaration($phpcsFile, $stackPtr, $openBracket, $tokens) === true) { + $this->processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens); + } else { + $this->processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens); + } + + }//end process() + + + /** + * Determine if this is a multi-line function declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return bool + */ + public function isMultiLineDeclaration($phpcsFile, $stackPtr, $openBracket, $tokens) + { + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + if ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']) { + return true; + } + + // Closures may use the USE keyword and so be multi-line in this way. + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + // If the opening and closing parenthesis of the use statement + // are also on the same line, this is a single line declaration. + $open = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $close = $tokens[$open]['parenthesis_closer']; + if ($tokens[$open]['line'] !== $tokens[$close]['line']) { + return true; + } + } + } + + return false; + + }//end isMultiLineDeclaration() + + + /** + * Processes single-line declarations. + * + * Just uses the Generic BSD-Allman brace sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens) + { + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $sniff = new OpeningFunctionBraceKernighanRitchieSniff(); + } else { + $sniff = new OpeningFunctionBraceBsdAllmanSniff(); + } + + $sniff->checkClosures = true; + $sniff->process($phpcsFile, $stackPtr); + + }//end processSingleLineDeclaration() + + + /** + * Processes multi-line declarations. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens) + { + $this->processArgumentList($phpcsFile, $stackPtr, $this->indent); + + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $open = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $closeBracket = $tokens[$open]['parenthesis_closer']; + } + } + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + // The opening brace needs to be one space away from the closing parenthesis. + $opener = $tokens[$stackPtr]['scope_opener']; + if ($tokens[$opener]['line'] !== $tokens[$closeBracket]['line']) { + $error = 'The closing parenthesis and the opening brace of a multi-line function declaration must be on the same line'; + $fix = $phpcsFile->addFixableError($error, $opener, 'NewlineBeforeOpenBrace'); + if ($fix === true) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($opener - 1), $closeBracket, true); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($prev, ' {'); + + // If the opener is on a line by itself, removing it will create + // an empty line, so just remove the entire line instead. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($opener - 1), $closeBracket, true); + $next = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), null, true); + + if ($tokens[$prev]['line'] < $tokens[$opener]['line'] + && $tokens[$next]['line'] > $tokens[$opener]['line'] + ) { + // Clear the whole line. + for ($i = ($prev + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$opener]['line']) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } else { + // Just remove the opener. + $phpcsFile->fixer->replaceToken($opener, ''); + if ($tokens[$next]['line'] === $tokens[$opener]['line']) { + $phpcsFile->fixer->replaceToken(($opener + 1), ''); + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + } else { + $prev = $tokens[($opener - 1)]; + if ($prev['code'] !== T_WHITESPACE) { + $length = 0; + } else { + $length = strlen($prev['content']); + } + + if ($length !== 1) { + $error = 'There must be a single space between the closing parenthesis and the opening brace of a multi-line function declaration; found %s spaces'; + $fix = $phpcsFile->addFixableError($error, ($opener - 1), 'SpaceBeforeOpenBrace', [$length]); + if ($fix === true) { + if ($length === 0) { + $phpcsFile->fixer->addContentBefore($opener, ' '); + } else { + $phpcsFile->fixer->replaceToken(($opener - 1), ' '); + } + } + + return; + }//end if + }//end if + + }//end processMultiLineDeclaration() + + + /** + * Processes multi-line argument list declarations. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $indent The number of spaces code should be indented. + * @param string $type The type of the token the brackets + * belong to. + * + * @return void + */ + public function processArgumentList($phpcsFile, $stackPtr, $indent, $type='function') + { + $tokens = $phpcsFile->getTokens(); + + // We need to work out how far indented the function + // declaration itself is, so we can work out how far to + // indent parameters. + $functionIndent = 0; + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + if ($tokens[$i]['line'] !== $tokens[$stackPtr]['line']) { + break; + } + } + + // Move $i back to the line the function is or to 0. + $i++; + + if ($tokens[$i]['code'] === T_WHITESPACE) { + $functionIndent = $tokens[$i]['length']; + } + + // The closing parenthesis must be on a new line, even + // when checking abstract function definitions. + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + $prev = $phpcsFile->findPrevious( + T_WHITESPACE, + ($closeBracket - 1), + null, + true + ); + + if ($tokens[$closeBracket]['line'] !== $tokens[$tokens[$closeBracket]['parenthesis_opener']]['line'] + && $tokens[$prev]['line'] === $tokens[$closeBracket]['line'] + ) { + $error = 'The closing parenthesis of a multi-line '.$type.' declaration must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'CloseBracketLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($closeBracket); + } + } + + // If this is a closure and is using a USE statement, the closing + // parenthesis we need to look at from now on is the closing parenthesis + // of the USE statement. + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $open = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $closeBracket = $tokens[$open]['parenthesis_closer']; + + $prev = $phpcsFile->findPrevious( + T_WHITESPACE, + ($closeBracket - 1), + null, + true + ); + + if ($tokens[$closeBracket]['line'] !== $tokens[$tokens[$closeBracket]['parenthesis_opener']]['line'] + && $tokens[$prev]['line'] === $tokens[$closeBracket]['line'] + ) { + $error = 'The closing parenthesis of a multi-line use declaration must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'UseCloseBracketLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($closeBracket); + } + } + }//end if + }//end if + + // Each line between the parenthesis should be indented 4 spaces. + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $lastLine = $tokens[$openBracket]['line']; + for ($i = ($openBracket + 1); $i < $closeBracket; $i++) { + if ($tokens[$i]['line'] !== $lastLine) { + if ($i === $tokens[$stackPtr]['parenthesis_closer'] + || ($tokens[$i]['code'] === T_WHITESPACE + && (($i + 1) === $closeBracket + || ($i + 1) === $tokens[$stackPtr]['parenthesis_closer'])) + ) { + // Closing braces need to be indented to the same level + // as the function. + $expectedIndent = $functionIndent; + } else { + $expectedIndent = ($functionIndent + $indent); + } + + // We changed lines, so this should be a whitespace indent token. + $foundIndent = 0; + if ($tokens[$i]['code'] === T_WHITESPACE + && $tokens[$i]['line'] !== $tokens[($i + 1)]['line'] + ) { + $error = 'Blank lines are not allowed in a multi-line '.$type.' declaration'; + $fix = $phpcsFile->addFixableError($error, $i, 'EmptyLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + // This is an empty line, so don't check the indent. + continue; + } else if ($tokens[$i]['code'] === T_WHITESPACE) { + $foundIndent = $tokens[$i]['length']; + } else if ($tokens[$i]['code'] === T_DOC_COMMENT_WHITESPACE) { + $foundIndent = $tokens[$i]['length']; + ++$expectedIndent; + } + + if ($expectedIndent !== $foundIndent) { + $error = 'Multi-line '.$type.' declaration not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'Indent', $data); + if ($fix === true) { + $spaces = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $spaces); + } else { + $phpcsFile->fixer->replaceToken($i, $spaces); + } + } + } + + $lastLine = $tokens[$i]['line']; + }//end if + + if ($tokens[$i]['code'] === T_ARRAY || $tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) { + // Skip arrays as they have their own indentation rules. + if ($tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) { + $i = $tokens[$i]['bracket_closer']; + } else { + $i = $tokens[$i]['parenthesis_closer']; + } + + $lastLine = $tokens[$i]['line']; + continue; + } + + if ($tokens[$i]['code'] === T_ATTRIBUTE) { + // Skip attributes as they have their own indentation rules. + $i = $tokens[$i]['attribute_closer']; + $lastLine = $tokens[$i]['line']; + continue; + } + }//end for + + }//end processArgumentList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/ValidDefaultValueSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/ValidDefaultValueSniff.php new file mode 100644 index 00000000..f1347078 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/ValidDefaultValueSniff.php @@ -0,0 +1,78 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ValidDefaultValueSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return int[] + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + T_FN, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Flag for when we have found a default in our arg list. + // If there is a value without a default after this, it is an error. + $defaultFound = false; + + $params = $phpcsFile->getMethodParameters($stackPtr); + foreach ($params as $param) { + if ($param['variable_length'] === true) { + continue; + } + + if (array_key_exists('default', $param) === true) { + $defaultFound = true; + // Check if the arg is type hinted and using NULL for the default. + // This does not make the argument optional - it just allows NULL + // to be passed in. + if ($param['type_hint'] !== '' && strtolower($param['default']) === 'null') { + $defaultFound = false; + } + + continue; + } + + if ($defaultFound === true) { + $error = 'Arguments with default values must be at the end of the argument list'; + $phpcsFile->addError($error, $param['token'], 'NotAtEnd'); + return; + } + }//end foreach + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidClassNameSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidClassNameSniff.php new file mode 100644 index 00000000..00e68bfe --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidClassNameSniff.php @@ -0,0 +1,98 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ValidClassNameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being processed. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $className = $phpcsFile->findNext(T_STRING, $stackPtr); + $name = trim($tokens[$className]['content']); + $errorData = [ucfirst($tokens[$stackPtr]['content'])]; + + // Make sure the first letter is a capital. + if (preg_match('|^[A-Z]|', $name) === 0) { + $error = '%s name must begin with a capital letter'; + $phpcsFile->addError($error, $stackPtr, 'StartWithCapital', $errorData); + } + + // Check that each new word starts with a capital as well, but don't + // check the first word, as it is checked above. + $validName = true; + $nameBits = explode('_', $name); + $firstBit = array_shift($nameBits); + foreach ($nameBits as $bit) { + if ($bit === '' || $bit[0] !== strtoupper($bit[0])) { + $validName = false; + break; + } + } + + if ($validName === false) { + // Strip underscores because they cause the suggested name + // to be incorrect. + $nameBits = explode('_', trim($name, '_')); + $firstBit = array_shift($nameBits); + if ($firstBit === '') { + $error = '%s name is not valid'; + $phpcsFile->addError($error, $stackPtr, 'Invalid', $errorData); + } else { + $newName = strtoupper($firstBit[0]).substr($firstBit, 1).'_'; + foreach ($nameBits as $bit) { + if ($bit !== '') { + $newName .= strtoupper($bit[0]).substr($bit, 1).'_'; + } + } + + $newName = rtrim($newName, '_'); + $error = '%s name is not valid; consider %s instead'; + $data = $errorData; + $data[] = $newName; + $phpcsFile->addError($error, $stackPtr, 'Invalid', $data); + } + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php new file mode 100644 index 00000000..e7f87d44 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php @@ -0,0 +1,284 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Tokens; + +class ValidFunctionNameSniff extends AbstractScopeSniff +{ + + /** + * A list of all PHP magic methods. + * + * @var array + */ + protected $magicMethods = [ + 'construct' => true, + 'destruct' => true, + 'call' => true, + 'callstatic' => true, + 'get' => true, + 'set' => true, + 'isset' => true, + 'unset' => true, + 'sleep' => true, + 'wakeup' => true, + 'serialize' => true, + 'unserialize' => true, + 'tostring' => true, + 'invoke' => true, + 'set_state' => true, + 'clone' => true, + 'debuginfo' => true, + ]; + + /** + * A list of all PHP magic functions. + * + * @var array + */ + protected $magicFunctions = ['autoload' => true]; + + + /** + * Constructs a PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff. + */ + public function __construct() + { + parent::__construct(Tokens::$ooScopeTokens, [T_FUNCTION], true); + + }//end __construct() + + + /** + * Processes the tokens within the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * @param int $currScope The position of the current scope. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + $className = $phpcsFile->getDeclarationName($currScope); + if (isset($className) === false) { + $className = '[Anonymous Class]'; + } + + $errorData = [$className.'::'.$methodName]; + + $methodNameLc = strtolower($methodName); + $classNameLc = strtolower($className); + + // Is this a magic method. i.e., is prefixed with "__" ? + if (preg_match('|^__[^_]|', $methodName) !== 0) { + $magicPart = substr($methodNameLc, 2); + if (isset($this->magicMethods[$magicPart]) === true) { + return; + } + + $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData); + } + + // PHP4 constructors are allowed to break our rules. + if ($methodNameLc === $classNameLc) { + return; + } + + // PHP4 destructors are allowed to break our rules. + if ($methodNameLc === '_'.$classNameLc) { + return; + } + + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + $scope = $methodProps['scope']; + $scopeSpecified = $methodProps['scope_specified']; + + if ($methodProps['scope'] === 'private') { + $isPublic = false; + } else { + $isPublic = true; + } + + // If it's a private method, it must have an underscore on the front. + if ($isPublic === false) { + if ($methodName[0] !== '_') { + $error = 'Private method name "%s" must be prefixed with an underscore'; + $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $errorData); + $phpcsFile->recordMetric($stackPtr, 'Private method prefixed with underscore', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Private method prefixed with underscore', 'yes'); + } + } + + // If it's not a private method, it must not have an underscore on the front. + if ($isPublic === true && $scopeSpecified === true && $methodName[0] === '_') { + $error = '%s method name "%s" must not be prefixed with an underscore'; + $data = [ + ucfirst($scope), + $errorData[0], + ]; + $phpcsFile->addError($error, $stackPtr, 'PublicUnderscore', $data); + } + + $testMethodName = ltrim($methodName, '_'); + + if (Common::isCamelCaps($testMethodName, false, true, false) === false) { + if ($scopeSpecified === true) { + $error = '%s method name "%s" is not in camel caps format'; + $data = [ + ucfirst($scope), + $errorData[0], + ]; + $phpcsFile->addError($error, $stackPtr, 'ScopeNotCamelCaps', $data); + } else { + $error = 'Method name "%s" is not in camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + } + } + + }//end processTokenWithinScope() + + + /** + * Processes the tokens outside the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if ($functionName === null) { + // Ignore closures. + return; + } + + if (ltrim($functionName, '_') === '') { + // Ignore special functions. + return; + } + + $errorData = [$functionName]; + + // Is this a magic function. i.e., it is prefixed with "__". + if (preg_match('|^__[^_]|', $functionName) !== 0) { + $magicPart = strtolower(substr($functionName, 2)); + if (isset($this->magicFunctions[$magicPart]) === true) { + return; + } + + $error = 'Function name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'FunctionDoubleUnderscore', $errorData); + } + + // Function names can be in two parts; the package name and + // the function name. + $packagePart = ''; + $underscorePos = strrpos($functionName, '_'); + if ($underscorePos === false) { + $camelCapsPart = $functionName; + } else { + $packagePart = substr($functionName, 0, $underscorePos); + $camelCapsPart = substr($functionName, ($underscorePos + 1)); + + // We don't care about _'s on the front. + $packagePart = ltrim($packagePart, '_'); + } + + // If it has a package part, make sure the first letter is a capital. + if ($packagePart !== '') { + if ($functionName[0] === '_') { + $error = 'Function name "%s" is invalid; only private methods should be prefixed with an underscore'; + $phpcsFile->addError($error, $stackPtr, 'FunctionUnderscore', $errorData); + } + + if ($functionName[0] !== strtoupper($functionName[0])) { + $error = 'Function name "%s" is prefixed with a package name but does not begin with a capital letter'; + $phpcsFile->addError($error, $stackPtr, 'FunctionNoCapital', $errorData); + } + } + + // If it doesn't have a camel caps part, it's not valid. + if (trim($camelCapsPart) === '') { + $error = 'Function name "%s" is not valid; name appears incomplete'; + $phpcsFile->addError($error, $stackPtr, 'FunctionInvalid', $errorData); + return; + } + + $validName = true; + $newPackagePart = $packagePart; + $newCamelCapsPart = $camelCapsPart; + + // Every function must have a camel caps part, so check that first. + if (Common::isCamelCaps($camelCapsPart, false, true, false) === false) { + $validName = false; + $newCamelCapsPart = strtolower($camelCapsPart[0]).substr($camelCapsPart, 1); + } + + if ($packagePart !== '') { + // Check that each new word starts with a capital. + $nameBits = explode('_', $packagePart); + $nameBits = array_filter($nameBits); + foreach ($nameBits as $bit) { + if ($bit[0] !== strtoupper($bit[0])) { + $newPackagePart = ''; + foreach ($nameBits as $bit) { + $newPackagePart .= strtoupper($bit[0]).substr($bit, 1).'_'; + } + + $validName = false; + break; + } + } + } + + if ($validName === false) { + if ($newPackagePart === '') { + $newName = $newCamelCapsPart; + } else { + $newName = rtrim($newPackagePart, '_').'_'.$newCamelCapsPart; + } + + $error = 'Function name "%s" is invalid; consider "%s" instead'; + $data = $errorData; + $data[] = $newName; + $phpcsFile->addError($error, $stackPtr, 'FunctionNameInvalid', $data); + } + + }//end processTokenOutsideScope() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidVariableNameSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidVariableNameSniff.php new file mode 100644 index 00000000..89af5df8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -0,0 +1,103 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; + +class ValidVariableNameSniff extends AbstractVariableSniff +{ + + + /** + * Processes class member variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $memberProps = $phpcsFile->getMemberProperties($stackPtr); + if (empty($memberProps) === true) { + return; + } + + $memberName = ltrim($tokens[$stackPtr]['content'], '$'); + $scope = $memberProps['scope']; + $scopeSpecified = $memberProps['scope_specified']; + + if ($memberProps['scope'] === 'private') { + $isPublic = false; + } else { + $isPublic = true; + } + + // If it's a private member, it must have an underscore on the front. + if ($isPublic === false && $memberName[0] !== '_') { + $error = 'Private member variable "%s" must be prefixed with an underscore'; + $data = [$memberName]; + $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $data); + return; + } + + // If it's not a private member, it must not have an underscore on the front. + if ($isPublic === true && $scopeSpecified === true && $memberName[0] === '_') { + $error = '%s member variable "%s" must not be prefixed with an underscore'; + $data = [ + ucfirst($scope), + $memberName, + ]; + $phpcsFile->addError($error, $stackPtr, 'PublicUnderscore', $data); + return; + } + + }//end processMemberVar() + + + /** + * Processes normal variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariable() + + + /** + * Processes variables in double quoted strings. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariableInString() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ObjectOperatorIndentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ObjectOperatorIndentSniff.php new file mode 100644 index 00000000..fb1b79a3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ObjectOperatorIndentSniff.php @@ -0,0 +1,204 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ObjectOperatorIndentSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + /** + * Indicates whether multilevel indenting is allowed. + * + * @var boolean + */ + public $multilevel = false; + + /** + * Tokens to listen for. + * + * @var array + */ + private $targets = [ + T_OBJECT_OPERATOR, + T_NULLSAFE_OBJECT_OPERATOR, + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return int[] + */ + public function register() + { + return $this->targets; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile All the tokens found in the document. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure this is the first object operator in a chain of them. + $start = $phpcsFile->findStartOfStatement($stackPtr); + $prev = $phpcsFile->findPrevious($this->targets, ($stackPtr - 1), $start); + if ($prev !== false) { + return; + } + + // Make sure this is a chained call. + $end = $phpcsFile->findEndOfStatement($stackPtr); + $next = $phpcsFile->findNext($this->targets, ($stackPtr + 1), $end); + if ($next === false) { + // Not a chained call. + return; + } + + // Determine correct indent. + for ($i = ($start - 1); $i >= 0; $i--) { + if ($tokens[$i]['line'] !== $tokens[$start]['line']) { + $i++; + break; + } + } + + $baseIndent = 0; + if ($i >= 0 && $tokens[$i]['code'] === T_WHITESPACE) { + $baseIndent = $tokens[$i]['length']; + } + + $baseIndent += $this->indent; + + // Determine the scope of the original object operator. + $origBrackets = null; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $origBrackets = $tokens[$stackPtr]['nested_parenthesis']; + } + + $origConditions = null; + if (isset($tokens[$stackPtr]['conditions']) === true) { + $origConditions = $tokens[$stackPtr]['conditions']; + } + + // Check indentation of each object operator in the chain. + // If the first object operator is on a different line than + // the variable, make sure we check its indentation too. + if ($tokens[$stackPtr]['line'] > $tokens[$start]['line']) { + $next = $stackPtr; + } + + $previousIndent = $baseIndent; + + while ($next !== false) { + // Make sure it is in the same scope, otherwise don't check indent. + $brackets = null; + if (isset($tokens[$next]['nested_parenthesis']) === true) { + $brackets = $tokens[$next]['nested_parenthesis']; + } + + $conditions = null; + if (isset($tokens[$next]['conditions']) === true) { + $conditions = $tokens[$next]['conditions']; + } + + if ($origBrackets === $brackets && $origConditions === $conditions) { + // Make sure it starts a line, otherwise don't check indent. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($next - 1), $stackPtr, true); + $indent = $tokens[($next - 1)]; + if ($tokens[$prev]['line'] !== $tokens[$next]['line'] + && $indent['code'] === T_WHITESPACE + ) { + if ($indent['line'] === $tokens[$next]['line']) { + $foundIndent = strlen($indent['content']); + } else { + $foundIndent = 0; + } + + $minIndent = $previousIndent; + $maxIndent = $previousIndent; + $expectedIndent = $previousIndent; + + if ($this->multilevel === true) { + $minIndent = max(($previousIndent - $this->indent), $baseIndent); + $maxIndent = ($previousIndent + $this->indent); + $expectedIndent = min(max($foundIndent, $minIndent), $maxIndent); + } + + if ($foundIndent < $minIndent || $foundIndent > $maxIndent) { + $error = 'Object operator not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $next, 'Incorrect', $data); + if ($fix === true) { + $spaces = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($next, $spaces); + } else { + $phpcsFile->fixer->replaceToken(($next - 1), $spaces); + } + } + } + + $previousIndent = $expectedIndent; + }//end if + + // It cant be the last thing on the line either. + $content = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true); + if ($tokens[$content]['line'] !== $tokens[$next]['line']) { + $error = 'Object operator must be at the start of the line, not the end'; + $fix = $phpcsFile->addFixableError($error, $next, 'StartOfLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($next + 1); $x < $content; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewlineBefore($next); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + $next = $phpcsFile->findNext( + $this->targets, + ($next + 1), + null, + false, + null, + true + ); + }//end while + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php new file mode 100644 index 00000000..097754e5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php @@ -0,0 +1,179 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ScopeClosingBraceSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return int[] + */ + public function register() + { + return Tokens::$scopeOpeners; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile All the tokens found in the document. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If this is an inline condition (ie. there is no scope opener), then + // return, as this is not a new scope. + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $scopeStart = $tokens[$stackPtr]['scope_opener']; + $scopeEnd = $tokens[$stackPtr]['scope_closer']; + + // If the scope closer doesn't think it belongs to this scope opener + // then the opener is sharing its closer with other tokens. We only + // want to process the closer once, so skip this one. + if (isset($tokens[$scopeEnd]['scope_condition']) === false + || $tokens[$scopeEnd]['scope_condition'] !== $stackPtr + ) { + return; + } + + // We need to actually find the first piece of content on this line, + // because if this is a method with tokens before it (public, static etc) + // or an if with an else before it, then we need to start the scope + // checking from there, rather than the current token. + $lineStart = ($stackPtr - 1); + for ($lineStart; $lineStart > 0; $lineStart--) { + if (strpos($tokens[$lineStart]['content'], $phpcsFile->eolChar) !== false) { + break; + } + } + + $lineStart++; + + $startColumn = 1; + if ($tokens[$lineStart]['code'] === T_WHITESPACE) { + $startColumn = $tokens[($lineStart + 1)]['column']; + } else if ($tokens[$lineStart]['code'] === T_INLINE_HTML) { + $trimmed = ltrim($tokens[$lineStart]['content']); + if ($trimmed === '') { + $startColumn = $tokens[($lineStart + 1)]['column']; + } else { + $startColumn = (strlen($tokens[$lineStart]['content']) - strlen($trimmed)); + } + } + + // Check that the closing brace is on it's own line. + $lastContent = $phpcsFile->findPrevious( + [ + T_WHITESPACE, + T_INLINE_HTML, + T_OPEN_TAG, + ], + ($scopeEnd - 1), + $scopeStart, + true + ); + + if ($tokens[$lastContent]['line'] === $tokens[$scopeEnd]['line']) { + $error = 'Closing brace must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'Line'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($scopeEnd); + } + + return; + } + + // Check now that the closing brace is lined up correctly. + $lineStart = ($scopeEnd - 1); + for ($lineStart; $lineStart > 0; $lineStart--) { + if (strpos($tokens[$lineStart]['content'], $phpcsFile->eolChar) !== false) { + break; + } + } + + $lineStart++; + + $braceIndent = 0; + if ($tokens[$lineStart]['code'] === T_WHITESPACE) { + $braceIndent = ($tokens[($lineStart + 1)]['column'] - 1); + } else if ($tokens[$lineStart]['code'] === T_INLINE_HTML) { + $trimmed = ltrim($tokens[$lineStart]['content']); + if ($trimmed === '') { + $braceIndent = ($tokens[($lineStart + 1)]['column'] - 1); + } else { + $braceIndent = (strlen($tokens[$lineStart]['content']) - strlen($trimmed) - 1); + } + } + + $fix = false; + if ($tokens[$stackPtr]['code'] === T_CASE + || $tokens[$stackPtr]['code'] === T_DEFAULT + ) { + // BREAK statements should be indented n spaces from the + // CASE or DEFAULT statement. + $expectedIndent = ($startColumn + $this->indent - 1); + if ($braceIndent !== $expectedIndent) { + $error = 'Case breaking statement indented incorrectly; expected %s spaces, found %s'; + $data = [ + $expectedIndent, + $braceIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'BreakIndent', $data); + } + } else { + $expectedIndent = max(0, ($startColumn - 1)); + if ($braceIndent !== $expectedIndent) { + $error = 'Closing brace indented incorrectly; expected %s spaces, found %s'; + $data = [ + $expectedIndent, + $braceIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'Indent', $data); + } + }//end if + + if ($fix === true) { + $spaces = str_repeat(' ', $expectedIndent); + if ($braceIndent === 0) { + $phpcsFile->fixer->addContentBefore($lineStart, $spaces); + } else { + $phpcsFile->fixer->replaceToken($lineStart, ltrim($tokens[$lineStart]['content'])); + $phpcsFile->fixer->addContentBefore($lineStart, $spaces); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeIndentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeIndentSniff.php new file mode 100644 index 00000000..2620d20f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -0,0 +1,24 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\ScopeIndentSniff as GenericScopeIndentSniff; + +class ScopeIndentSniff extends GenericScopeIndentSniff +{ + + /** + * Any scope openers that should not cause an indent. + * + * @var int[] + */ + protected $nonIndentingScopes = [T_SWITCH]; + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc new file mode 100644 index 00000000..6942944b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc @@ -0,0 +1,114 @@ +setLogger(new class {}); + +var_dump(new class(10) extends SomeClass implements SomeInterface { + private $num; + + public function __construct($num) + { + $this->num = $num; + } + + use SomeTrait; +}); + +class IncorrectClassDeclarationWithCommentAtEnd extends correctClassDeclaration /* Comment */ { +} + +class CorrectClassDeclarationWithCommentAtEnd extends correctClassDeclaration +/* Comment */ +{ +} + +// Don't move phpcs:ignore comments. +class PHPCSIgnoreAnnotationAfterOpeningBrace +{ // phpcs:ignore Standard.Cat.Sniff -- for reasons. +} + +// Moving any of the other trailing phpcs: comments is ok. +class PHPCSAnnotationAfterOpeningBrace +{ // phpcs:disable Standard.Cat.Sniff -- for reasons. +} + +if (!class_exists('ClassOpeningBraceShouldBeIndented')) { + abstract class ClassOpeningBraceShouldBeIndented +{ +} +} + +if (!class_exists('ClassOpeningBraceTooMuchIndentation')) { + final class ClassOpeningBraceTooMuchIndentation + { + } +} + +enum IncorrectBracePlacement {} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc.fixed new file mode 100644 index 00000000..26688b15 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc.fixed @@ -0,0 +1,125 @@ +setLogger(new class {}); + +var_dump(new class(10) extends SomeClass implements SomeInterface { + private $num; + + public function __construct($num) + { + $this->num = $num; + } + + use SomeTrait; +}); + +class IncorrectClassDeclarationWithCommentAtEnd extends correctClassDeclaration /* Comment */ +{ +} + +class CorrectClassDeclarationWithCommentAtEnd extends correctClassDeclaration +/* Comment */ +{ +} + +// Don't move phpcs:ignore comments. +class PHPCSIgnoreAnnotationAfterOpeningBrace +{ // phpcs:ignore Standard.Cat.Sniff -- for reasons. +} + +// Moving any of the other trailing phpcs: comments is ok. +class PHPCSAnnotationAfterOpeningBrace +{ + // phpcs:disable Standard.Cat.Sniff -- for reasons. +} + +if (!class_exists('ClassOpeningBraceShouldBeIndented')) { + abstract class ClassOpeningBraceShouldBeIndented + { +} +} + +if (!class_exists('ClassOpeningBraceTooMuchIndentation')) { + final class ClassOpeningBraceTooMuchIndentation + { + } +} + +enum IncorrectBracePlacement +{ +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.2.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.2.inc new file mode 100644 index 00000000..ac71fc9f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.2.inc @@ -0,0 +1,11 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + if ($testFile === 'ClassDeclarationUnitTest.1.inc') { + return; + } + + $config->tabWidth = 4; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ClassDeclarationUnitTest.1.inc': + return [ + 21 => 1, + 22 => 1, + 23 => 1, + 27 => 1, + 33 => 1, + 38 => 1, + 49 => 1, + 84 => 1, + 94 => 1, + 99 => 1, + 104 => 1, + 110 => 1, + 114 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + if ($testFile === 'ClassDeclarationUnitTest.2.inc') { + return [11 => 1]; + } + + return[]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.inc new file mode 100644 index 00000000..da53b99e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.inc @@ -0,0 +1,145 @@ + + * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @version Release: 1.0 + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class Extra_Description_Newlines +{ + +}//end class + + +/** + * Sample class comment + * @category PHP + * @package PHP_CodeSniffer + * @author Greg Sherwood + * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @version + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class Missing_Newlines_Before_Tags +{ + +}//end class + + +/** + * Simple class comment + * + * @category _wrong_category + * @package PHP_CodeSniffer + * @package ADDITIONAL PACKAGE TAG + * @subpackage SUBPACKAGE TAG + * @author Original Author + * @author Greg Sherwood gsherwood@squiz.net + * @author Mr T + * @author + * @copyright 1997~1994 The PHP Group + * @license http://www.php.net/license/3_0.txt + * @version INVALID VERSION CONTENT + * @see + * @see + * @link sdfsdf + * @see Net_Sample::Net_Sample() + * @see Net_Other + * @deprecated asd + * @unknown Unknown tag + * @since Class available since Release 1.2.0 + */ +class Checking_Tags +{ + class Sub_Class { + + }//end class + + +}//end class + + +/** + * + * + */ +class Empty_Class_Doc +{ + +}//end class + + +/** + * + * + */ +interface Empty_Interface_Doc +{ + +}//end interface + + +/** + * + * + */ +trait Empty_Trait_Doc +{ + +}//end trait + + +/** + * + * + */ +enum Empty_Enum_Doc +{ + +}//end enum + + +/** + * Sample class comment + * + * @category PHP + * @package PHP_CodeSniffer + * @author Greg Sherwood + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +#[Authenticate('admin_logged_in')] +class TodoController extends AbstractController implements MustBeLoggedInInterface +{ +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.php new file mode 100644 index 00000000..004a064b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.php @@ -0,0 +1,71 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 15 => 1, + 51 => 1, + 63 => 1, + 65 => 2, + 66 => 1, + 68 => 1, + 70 => 1, + 71 => 1, + 72 => 1, + 74 => 2, + 75 => 1, + 76 => 1, + 77 => 1, + 85 => 1, + 96 => 5, + 106 => 5, + 116 => 5, + 126 => 5, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 71 => 1, + 73 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.1.inc new file mode 100644 index 00000000..0b18fa38 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.1.inc @@ -0,0 +1,53 @@ + +* @author Greg Sherwood gsherwood@squiz.net +* @author Mr T +* @author +* @copyright 1997~1994 The PHP Group +* @copyright 1997~1994 The PHP Group +* @license http://www.php.net/license/3_0.txt +* @see +* @see +* @version INVALID VERSION CONTENT +* @see Net_Sample::Net_Sample() +* @see Net_Other +* @deprecated asd +* @since Class available since Release 1.2.0 +* @summary An unknown summary tag +* @package '' +* @subpackage !! +* @author Code AUthor +*/ +require_once '/some/path.php'; +?> + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.2.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.2.inc new file mode 100644 index 00000000..8845eb19 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.2.inc @@ -0,0 +1,9 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FileCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='FileCommentUnitTest.inc') + { + switch ($testFile) { + case 'FileCommentUnitTest.1.inc': + return [ + 21 => 1, + 23 => 2, + 24 => 1, + 26 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 32 => 2, + 33 => 1, + 34 => 1, + 35 => 1, + 40 => 2, + 41 => 2, + 43 => 1, + ]; + + case 'FileCommentUnitTest.2.inc': + return [1 => 1]; + + case 'FileCommentUnitTest.3.inc': + return [1 => 1]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='FileCommentUnitTest.inc') + { + switch ($testFile) { + case 'FileCommentUnitTest.1.inc': + return [ + 29 => 1, + 30 => 1, + 34 => 1, + 43 => 1, + ]; + + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc new file mode 100644 index 00000000..5c3295fd --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc @@ -0,0 +1,478 @@ + line numbers for each token. + * + * @param array $tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function foo(&$tokens, $tokenizer, $eolChar) +{ + +}//end foo() + +/** + * Gettext. + * + */ +function _() { + return $foo; +} + +class Baz { + /** + * The PHP5 constructor + * + * No return tag + */ + public function __construct() { + + } +} + +/** + * Complete a step. + * + * @param string $status Status of step to complete. + * @param array $array Array. + * @param string $note Optional note. + * + * @return void + */ +function completeStep($status, array $array = [Class1::class, 'test'], $note = '') { + echo 'foo'; +} + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string ...$name2 Comment. + * + * @return void + */ +function myFunction(string $name1, string ...$name2) { +} + + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string $name2 Comment. + * + * @return void + */ +function myFunction(string $name1, string ...$name2) { +} + +/** + * Completely invalid format, but should not cause PHP notices. + * + * @param $bar + * Comment here. + * @param ... + * Additional arguments here. + * + * @return + * Return value + * + */ +function foo($bar) { +} + +/** + * Processes the test. + * + * @param PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ +function process(File $phpcsFile, $stackPtr) +{ + +}//end process() + +/** + * Processes the test. + * + * @param int $phpcsFile The PHP_CodeSniffer + * file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ +function process(File $phpcsFile, $stackPtr) +{ + +}//end process() + +/** + * @param (Foo&Bar)|null $a Comment. + * @param string $b Comment. + * + * @return void + */ +public function setTranslator($a, &$b): void +{ + $this->translator = $translator; +} + +// phpcs:set PEAR.Commenting.FunctionComment minimumVisibility protected +private function setTranslator2($a, &$b): void +{ + $this->translator = $translator; +} + +// phpcs:set PEAR.Commenting.FunctionComment minimumVisibility public +protected function setTranslator3($a, &$b): void +{ + $this->translator = $translator; +} + +private function setTranslator4($a, &$b): void +{ + $this->translator = $translator; +} + +class Bar { + /** + * The PHP5 constructor + * + * @return + */ + public function __construct() { + + } +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] +class Bar { + /** + * The PHP5 constructor + */ + public function __construct() { + + } +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] ignored +/** + * Should be ok + */ +public function ignored() { + +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] __construct,__destruct + +class Something implements JsonSerializable { + /** + * Single attribute. + * + * @return mixed + */ + #[ReturnTypeWillChange] + public function jsonSerialize() {} + + /** + * Multiple attributes. + * + * @return Something + */ + #[AttributeA] + #[AttributeB] + public function methodName() {} + + /** + * Blank line between docblock and attribute. + * + * @return mixed + */ + + #[ReturnTypeWillChange] + public function blankLineDetectionA() {} + + /** + * Blank line between attribute and function declaration. + * + * @return mixed + */ + #[ReturnTypeWillChange] + + public function blankLineDetectionB() {} + + /** + * Blank line between both docblock and attribute and attribute and function declaration. + * + * @return mixed + */ + + #[ReturnTypeWillChange] + + public function blankLineDetectionC() {} +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc.fixed new file mode 100644 index 00000000..751b09c6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc.fixed @@ -0,0 +1,478 @@ + line numbers for each token. + * + * @param array $tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function foo(&$tokens, $tokenizer, $eolChar) +{ + +}//end foo() + +/** + * Gettext. + * + */ +function _() { + return $foo; +} + +class Baz { + /** + * The PHP5 constructor + * + * No return tag + */ + public function __construct() { + + } +} + +/** + * Complete a step. + * + * @param string $status Status of step to complete. + * @param array $array Array. + * @param string $note Optional note. + * + * @return void + */ +function completeStep($status, array $array = [Class1::class, 'test'], $note = '') { + echo 'foo'; +} + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string ...$name2 Comment. + * + * @return void + */ +function myFunction(string $name1, string ...$name2) { +} + + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string $name2 Comment. + * + * @return void + */ +function myFunction(string $name1, string ...$name2) { +} + +/** + * Completely invalid format, but should not cause PHP notices. + * + * @param $bar + * Comment here. + * @param ... + * Additional arguments here. + * + * @return + * Return value + * + */ +function foo($bar) { +} + +/** + * Processes the test. + * + * @param PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ +function process(File $phpcsFile, $stackPtr) +{ + +}//end process() + +/** + * Processes the test. + * + * @param int $phpcsFile The PHP_CodeSniffer + * file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ +function process(File $phpcsFile, $stackPtr) +{ + +}//end process() + +/** + * @param (Foo&Bar)|null $a Comment. + * @param string $b Comment. + * + * @return void + */ +public function setTranslator($a, &$b): void +{ + $this->translator = $translator; +} + +// phpcs:set PEAR.Commenting.FunctionComment minimumVisibility protected +private function setTranslator2($a, &$b): void +{ + $this->translator = $translator; +} + +// phpcs:set PEAR.Commenting.FunctionComment minimumVisibility public +protected function setTranslator3($a, &$b): void +{ + $this->translator = $translator; +} + +private function setTranslator4($a, &$b): void +{ + $this->translator = $translator; +} + +class Bar { + /** + * The PHP5 constructor + * + * @return + */ + public function __construct() { + + } +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] +class Bar { + /** + * The PHP5 constructor + */ + public function __construct() { + + } +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] ignored +/** + * Should be ok + */ +public function ignored() { + +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] __construct,__destruct + +class Something implements JsonSerializable { + /** + * Single attribute. + * + * @return mixed + */ + #[ReturnTypeWillChange] + public function jsonSerialize() {} + + /** + * Multiple attributes. + * + * @return Something + */ + #[AttributeA] + #[AttributeB] + public function methodName() {} + + /** + * Blank line between docblock and attribute. + * + * @return mixed + */ + + #[ReturnTypeWillChange] + public function blankLineDetectionA() {} + + /** + * Blank line between attribute and function declaration. + * + * @return mixed + */ + #[ReturnTypeWillChange] + + public function blankLineDetectionB() {} + + /** + * Blank line between both docblock and attribute and attribute and function declaration. + * + * @return mixed + */ + + #[ReturnTypeWillChange] + + public function blankLineDetectionC() {} +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php new file mode 100644 index 00000000..734ff73e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php @@ -0,0 +1,96 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 10 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 28 => 1, + 76 => 1, + 87 => 1, + 103 => 1, + 109 => 1, + 112 => 1, + 122 => 1, + 123 => 2, + 124 => 2, + 125 => 1, + 126 => 1, + 137 => 1, + 138 => 1, + 139 => 1, + 152 => 1, + 155 => 1, + 165 => 1, + 172 => 1, + 183 => 1, + 190 => 2, + 206 => 1, + 234 => 1, + 272 => 1, + 313 => 1, + 317 => 1, + 327 => 1, + 329 => 1, + 332 => 1, + 344 => 1, + 343 => 1, + 345 => 1, + 346 => 1, + 360 => 1, + 361 => 1, + 363 => 1, + 364 => 1, + 406 => 1, + 417 => 1, + 455 => 1, + 464 => 1, + 473 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.inc new file mode 100644 index 00000000..187228c2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.inc @@ -0,0 +1,29 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class InlineCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 15 => 1, + 24 => 1, + 25 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.inc new file mode 100644 index 00000000..cc9903aa --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.inc @@ -0,0 +1,165 @@ + 0); + +do +{ + echo $i; +} while ($i > 0); + +do +{ + echo $i; +} +while ($i > 0); + +do { echo $i; } while ($i > 0); + +do{ + echo $i; +}while($i > 0); + + +// while +while ($i < 1) { + echo $i; +} + +while($i < 1){ + echo $i; +} + +while ($i < 1) { echo $i; } + + +// for +for ($i = 1; $i < 1; $i++) { + echo $i; +} + +for($i = 1; $i < 1; $i++){ + echo $i; +} + +for ($i = 1; $i < 1; $i++) { echo $i; } + + +// foreach +foreach ($items as $item) { + echo $item; +} + +foreach($items as $item){ + echo $item; +} + +foreach ($items as $item) { echo $item; } + + +// if +if ($i == 0) { + $i = 1; +} + +if($i == 0){ + $i = 1; +} + +if ($i == 0) { $i = 1; } + + +// else +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else{ + $i = 0; +} + +if ($i == 0) { $i = 1; } else { $i = 0; } + + +// else +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else{ + $i = 0; +} + +if ($i == 0) { $i = 1; } else { $i = 0; } + + +// else if +if ($i == 0) { + $i = 1; +} else if ($i == 2) { + $i = 0; +} + +if ($i == 0) { + $i = 1; +} elseif ($i == 2) { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else if($i == 2){ + $i = 0; +} + +if ($i == 0) { + $i = 1; +}elseif($i == 2){ + $i = 0; +} + +if ($i == 0) { $i = 1; } else if ($i == 2) { $i = 0; } +if ($i == 0) { $i = 1; } elseif ($i == 2) { $i = 0; } + +if ($i == 0) { // this is ok because comments are allowed + $i = 1; +} + +if ($i == 0) {// this is ok because comments are allowed + $i = 1; +} + +if ($i == 0) { /* this is ok because comments are allowed*/ + $i = 1; +} + +if ($i == 0) +{ // this is not ok + $i = 1; +} + +if ($i == 0) /* this is ok */ { +} + +if ($i == 0) { +} +else { +} + +// match +$r = match ($x) { + 1 => 1, +}; + +$r = match( $x ){ 1 => 1 }; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.php new file mode 100644 index 00000000..98c3463b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.php @@ -0,0 +1,72 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ControlSignatureUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 14 => 1, + 20 => 1, + 22 => 1, + 32 => 1, + 36 => 1, + 44 => 1, + 48 => 1, + 56 => 1, + 60 => 1, + 68 => 1, + 72 => 1, + 84 => 1, + 88 => 2, + 100 => 1, + 104 => 2, + 122 => 2, + 128 => 1, + 132 => 3, + 133 => 2, + 147 => 1, + 157 => 1, + 165 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc new file mode 100644 index 00000000..a7a3c69d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc @@ -0,0 +1,251 @@ + +

    some text

    +errorCode() == 401 || // comment + $IPP->errorCode() == 3200) /* long comment + here + */ +{ + return false; +} + +if ($IPP->errorCode() == 401 || // comment + $IPP->errorCode() == 3200) // long comment here +{ + return false; +} + +if ($IPP->errorCode() == 401 + // Comment explaining the next condition here. + || $IPP->errorCode() == 3200 +) { + return false; +} + +function bar() { + if ($a + && $b +) { + return false; + } +} + +if ($a + && foo( + 'a', + 'b' + )) { + return false; +} + +?> + + + + + +errorCode() == 401 || // phpcs:ignore Standard.Category.Sniff -- for reasons. + $IPP->errorCode() == 3200) /* + phpcs:ignore Standard.Category.Sniff -- for reasons. + */ +{ + return false; +} + +if ($IPP->errorCode() == 401 || // phpcs:disable Standard.Category.Sniff -- for reasons. + $IPP->errorCode() == 3200) // phpcs:enable +{ + return false; +} + +if ($IPP->errorCode() == 401 + // phpcs:ignore Standard.Category.Sniff -- for reasons. + || $IPP->errorCode() == 3200 +) { + return false; +} + + if ($IPP->errorCode() == 401 || + /* + * phpcs:disable Standard.Category.Sniff -- for reasons. + */ + $IPP->errorCode() == 3200 + ) { + return false; + } + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() == 3200 + // phpcs:ignore Standard.Category.Sniff -- for reasons. +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + === 'someverylongexpectedoutput' +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + // A comment. + === 'someverylongexpectedoutput' +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + // phpcs:ignore Standard.Category.Sniff -- for reasons. + === 'someverylongexpectedoutput' +) { + return false; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc.fixed new file mode 100644 index 00000000..7d56c461 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc.fixed @@ -0,0 +1,247 @@ + +

    some text

    +errorCode() == 401 // comment + || $IPP->errorCode() == 3200 /* long comment + here + */ +) { + return false; +} + +if ($IPP->errorCode() == 401 // comment + || $IPP->errorCode() == 3200 // long comment here +) { + return false; +} + +if ($IPP->errorCode() == 401 + // Comment explaining the next condition here. + || $IPP->errorCode() == 3200 +) { + return false; +} + +function bar() { + if ($a + && $b + ) { + return false; + } +} + +if ($a + && foo( + 'a', + 'b' + ) +) { + return false; +} + +?> + + + + + +errorCode() == 401 // phpcs:ignore Standard.Category.Sniff -- for reasons. + || $IPP->errorCode() == 3200 /* + phpcs:ignore Standard.Category.Sniff -- for reasons. + */ +) { + return false; +} + +if ($IPP->errorCode() == 401 // phpcs:disable Standard.Category.Sniff -- for reasons. + || $IPP->errorCode() == 3200 // phpcs:enable +) { + return false; +} + +if ($IPP->errorCode() == 401 + // phpcs:ignore Standard.Category.Sniff -- for reasons. + || $IPP->errorCode() == 3200 +) { + return false; +} + + if ($IPP->errorCode() == 401 + /* + * phpcs:disable Standard.Category.Sniff -- for reasons. + */ + || $IPP->errorCode() == 3200 + ) { + return false; + } + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() == 3200 + // phpcs:ignore Standard.Category.Sniff -- for reasons. +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() === 'someverylongexpectedoutput' +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + // A comment. + === 'someverylongexpectedoutput' +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + // phpcs:ignore Standard.Category.Sniff -- for reasons. + === 'someverylongexpectedoutput' +) { + return false; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js new file mode 100644 index 00000000..064d7ff7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js @@ -0,0 +1,251 @@ +if (blah(param)) { + +} + +if ((condition1 + || condition2) + && condition3 + && condition4 + && condition5 +) { +} + +if ((condition1 || condition2) && condition3 && condition4 && condition5) { +} + +if ((condition1 || condition2) + && condition3 +) { +} + +if ( + (condition1 || condition2) + && condition3 +) { +} + +if ((condition1 + || condition2) +) { +} + +if ((condition1 + || condition2) + && condition3 && + condition4 +) { +} + +if ((condition1 + || condition2) + && condition3 + && condition4 + && condition5 +) { +} + +if (($condition1 + || $condition2) +) { +} + +if ((condition1 + || condition2) + ) { +} + +if ( + ( + condition1 + || condition2 + ) + && condition3 +) { +} + + +if ( condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} else if (condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} else if ( + condition1 + || condition2 && + condition3 +) { +} + +if (condition1 + || condition2 +|| condition3) { +} + +if (condition1 + || condition2 || condition3 +){ +} + +if (condition1) + console.info('bar'); + +if (condition1 + || condition2 +|| condition3) + console.info('bar'); + + +if (condition1 + || condition2 || condition3 +) + console.info('bar'); + +if (!a(post) + && (!a(context.header) + ^ a(context.header, 'Content-Type')) +) { +// ... +} + +if (foo) +{ + console.info('bar'); +} + +// Should be no errors even though lines are +// not exactly aligned together. Multi-line function +// call takes precedence. +if (array_key_exists(key, value) + && foo.bar.baz( + key, value2 + ) +) { +} + +if (true) { + foo = true; +}; + +if (foo == 401 || // comment + bar == 3200) /* long comment + here + */ +{ + return false; +} + +if (foo == 401 || // comment + bar == 3200) // long comment here +{ + return false; +} + +if (IPP.errorCode() == 401 + // Comment explaining the next condition here. + || IPP.errorCode() == 3200 +) { + return false; +} + +function bar() { + if (a + && b +) { + return false; + } +} + +if (a + && foo( + 'a', + 'b' + )) { + return false; +} + + + + + + + + + + + + + +if (foo == 401 || // phpcs:ignore Standard.Category.Sniff -- for reasons. + bar == 3200) /* + phpcs:ignore Standard.Category.Sniff -- for reasons. + */ +{ + return false; +} + +if (foo == 401 || // phpcs:disable Standard.Category.Sniff -- for reasons. + bar == 3200) // phpcs:enable +{ + return false; +} + +if (IPP.errorCode() == 401 + // phpcs:ignore Standard.Category.Sniff -- for reasons. + || IPP.errorCode() == 3200 +) { + return false; +} + + if (foo == 401 || + /* + * phpcs:disable Standard.Category.Sniff -- for reasons. + */ + bar == 3200 + ) { + return false; + } + +if (IPP.errorCode() == 401 + || IPP.errorCode() == 3200 + // phpcs:ignore Standard.Category.Sniff -- for reasons. +) { + return false; +} + +if (foo == 401 + || bar + == 'someverylongexpectedoutput' +) { + return false; +} + +if (IPP.errorCode() == 401 + || bar + // A comment. + == 'someverylongexpectedoutput' +) { + return false; +} + +if (foo == 401 + || IPP.errorCode() + // phpcs:ignore Standard.Category.Sniff -- for reasons. + == 'someverylongexpectedoutput' +) { + return false; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js.fixed new file mode 100644 index 00000000..cfde75d7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js.fixed @@ -0,0 +1,247 @@ +if (blah(param)) { + +} + +if ((condition1 + || condition2) + && condition3 + && condition4 + && condition5 +) { +} + +if ((condition1 || condition2) && condition3 && condition4 && condition5) { +} + +if ((condition1 || condition2) + && condition3 +) { +} + +if ((condition1 || condition2) + && condition3 +) { +} + +if ((condition1 + || condition2) +) { +} + +if ((condition1 + || condition2) + && condition3 + && condition4 +) { +} + +if ((condition1 + || condition2) + && condition3 + && condition4 + && condition5 +) { +} + +if (($condition1 + || $condition2) +) { +} + +if ((condition1 + || condition2) +) { +} + +if ((condition1 + || condition2) + && condition3 +) { +} + + +if (condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} else if (condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} else if (condition1 + || condition2 + && condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 || condition3 +) { +} + +if (condition1) + console.info('bar'); + +if (condition1 + || condition2 + || condition3 +) + console.info('bar'); + + +if (condition1 + || condition2 || condition3 +) + console.info('bar'); + +if (!a(post) + && (!a(context.header) + ^ a(context.header, 'Content-Type')) +) { +// ... +} + +if (foo) { + console.info('bar'); +} + +// Should be no errors even though lines are +// not exactly aligned together. Multi-line function +// call takes precedence. +if (array_key_exists(key, value) + && foo.bar.baz( + key, value2 + ) +) { +} + +if (true) { + foo = true; +}; + +if (foo == 401 // comment + || bar == 3200 /* long comment + here + */ +) { + return false; +} + +if (foo == 401 // comment + || bar == 3200 // long comment here +) { + return false; +} + +if (IPP.errorCode() == 401 + // Comment explaining the next condition here. + || IPP.errorCode() == 3200 +) { + return false; +} + +function bar() { + if (a + && b + ) { + return false; + } +} + +if (a + && foo( + 'a', + 'b' + ) +) { + return false; +} + + + + + + + + + + + + + +if (foo == 401 // phpcs:ignore Standard.Category.Sniff -- for reasons. + || bar == 3200 /* + phpcs:ignore Standard.Category.Sniff -- for reasons. + */ +) { + return false; +} + +if (foo == 401 // phpcs:disable Standard.Category.Sniff -- for reasons. + || bar == 3200 // phpcs:enable +) { + return false; +} + +if (IPP.errorCode() == 401 + // phpcs:ignore Standard.Category.Sniff -- for reasons. + || IPP.errorCode() == 3200 +) { + return false; +} + + if (foo == 401 + /* + * phpcs:disable Standard.Category.Sniff -- for reasons. + */ + || bar == 3200 + ) { + return false; + } + +if (IPP.errorCode() == 401 + || IPP.errorCode() == 3200 + // phpcs:ignore Standard.Category.Sniff -- for reasons. +) { + return false; +} + +if (foo == 401 + || bar == 'someverylongexpectedoutput' +) { + return false; +} + +if (IPP.errorCode() == 401 + || bar + // A comment. + == 'someverylongexpectedoutput' +) { + return false; +} + +if (foo == 401 + || IPP.errorCode() + // phpcs:ignore Standard.Category.Sniff -- for reasons. + == 'someverylongexpectedoutput' +) { + return false; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.php new file mode 100644 index 00000000..f78b4e3f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MultiLineConditionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='MultiLineConditionUnitTest.inc') + { + $errors = [ + 21 => 1, + 22 => 1, + 35 => 1, + 40 => 1, + 41 => 1, + 42 => 1, + 43 => 1, + 49 => 1, + 54 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 61 => 1, + 67 => 1, + 87 => 1, + 88 => 1, + 89 => 1, + 90 => 1, + 96 => 2, + 101 => 1, + 109 => 2, + 125 => 1, + 145 => 2, + 153 => 2, + 168 => 1, + 177 => 1, + 194 => 2, + 202 => 2, + 215 => 1, + 218 => 2, + 232 => 2, + 239 => 1, + 240 => 2, + 248 => 2, + ]; + + if ($testFile === 'MultiLineConditionUnitTest.inc') { + $errors[183] = 1; + } + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.inc new file mode 100644 index 00000000..dadfe923 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.inc @@ -0,0 +1,99 @@ + +
    +Some content goes here.
    +
    +
    + +
    +    Some content goes here.
    +    
    +    
    + +
    +Some content goes here.
    +
    +
    + +
    +    Some content goes here.
    +    
    +    
    + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class IncludingFileUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 5 => 1, + 11 => 1, + 12 => 1, + 16 => 1, + 17 => 1, + 33 => 1, + 34 => 1, + 47 => 1, + 48 => 1, + 64 => 1, + 65 => 1, + 73 => 1, + 74 => 1, + 85 => 1, + 86 => 1, + 98 => 1, + 99 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.inc new file mode 100644 index 00000000..fc6aea00 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.inc @@ -0,0 +1,22 @@ +additionalHeaderData[$this->strApplicationName] + = $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax')); + +$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName] + = $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax')); + +$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName] = + $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax')); + +$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName] + = $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax')); +$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName] = 'boo'; + +$var='string'; + +function getInstalledStandards( + $includeGeneric=false, + $standardsDir='' +) { +} +?> diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.php new file mode 100644 index 00000000..734d4fce --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Formatting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MultiLineAssignmentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 6 => 1, + 8 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc new file mode 100644 index 00000000..ed3d2c43 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc @@ -0,0 +1,550 @@ +getFoo() + ->doBar( + $this->getX() // no comma here + ->doY() // this is still the first method argument + ->doZ() // this is still the first method argument + ); +} + +$var = myFunction( +$foo, +$bar +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false + +fputs( + STDOUT, + "Examples: + $ {$app} , --all + $ {$app} --all", $something +); + +$array = array(); +array_map( + function($x) + { + return trim($x, $y); + }, $foo, + $array +); + +$bar = new stdClass( + 4, /* thanks */ 5, /* PSR-2 */ 6 +); + +function doSomething() +{ + return $this->getFoo() + ->doBar( + $this->getX() // no comma here + ->doY() // this is still the first method argument + ->doZ() // this is still the first method argument + ); +} + +doError( + 404, // status code + 'Not Found', // error name + 'Check your id' // fix +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true + +// Don't report errors for closing braces. Leave that to other sniffs. +foo( + [ + 'this', + 'is', + 'an', + 'array' + ], +[ + 'this', + 'is', + 'an', + 'array' + ], + array( + 'this', + 'is', +'an', +'array' + ), + array( + 'this', + 'is', + 'an', + 'array' + ), + function($x) + { + echo 'wee'; + + return trim($x); + } +); + +function foo() +{ + myFunction( + 'string'. + // comment + // comment + 'string'. + /* comment + * comment + */ + 'string' + ); +} + +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 1 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 1 +test($arg, $arg2); +test( $arg, $arg2 ); +test( $arg, $arg2 ); +test(); +test( ); +test( ); +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 0 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 0 + +?> + + + +
  • + log(// ... + 'error', + sprintf( + 'Message: %s', + isset($e->getData()['object']['evidence_details']) + ? $e->getData()['object']['evidence_details']['due_by'] + : '' + ), + array($e->getData()['object']) +); + +?> +
    + $class + ] + ); ?> +
    + + function ($x) { + return true; + }, + 'baz' => false + ) +); +$qux = array_filter( + $quux, function ($x) { + return $x; + } +); + +array_filter( + [1, 2], + function ($i) : bool { + return $i === 0; + } +); + +foo(array( + 'callback' => function () { + $foo = 'foo'; + return; + }, +)); + +foo( + $a, + /* + $c, + + $d, + */ + $e +); + +test( + 1,2,3,4 + ); + +class Test +{ + public function getInstance() + { + return new static( + 'arg', + 'foo' + ); + } + + public function getSelf() + { + return new self( + 'a','b', 'c' + ); + } +} + +$x = $var('y', +'x'); + +$obj->{$x}(1, + 2); + +return (function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})( + 'a','b' +)('c', + 'd'); + +class Foo +{ + public function bar($a, $b) + { + if (!$a || !$b) { + return; + } + + (new stdClass())->a = $a; + } +} + +return (function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})('a','b')('c','d'); + +function foo() +{ + Bar( + function () { + } + ); +} + +$deprecated_functions = [ + 'the_category_ID' + => function_call( // 7 spaces, not 8. This is the problem line. + $a, + $b + ), +]; + +$deprecated_functions = [ + 'the_category_ID' + => function_call( // 9 spaces, not 8. This is the problem line. + $a, + $b + ), +]; + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false + +printf( + '', + $obj->getName(), // Trailing comment. + $obj->getID(), // phpcs:ignore Standard.Category.SniffName -- for reasons. + $option +); + +// Handling of PHP 7.3 trailing comma's. +functionCall($args, $foo,); +functionCall( + $args, $foo, +); +functionCall( + $args, + $foo, +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true + +$this->foo( + + ['a','b'], + true + +); + +$this->foo( + + // Comment + ['a','b'], + true + +); + +function m() +{ + $t = ' + ' . (empty(true) ? ' + ' . f( + '1', + '2', + ) . ' + ' : ''); +} + +class C +{ + + public function m() + { + $a = []; + $t = + "SELECT * FROM t +WHERE f IN(" . implode( + ",", + $a + ) . ")"; + } +} + +$notices = array( + 'index' => sprintf( + translation_function('a text string with %s placeholder'), + 'replacement' + ), +); + +$componentType = $this->componentTypeRepository->findByType($this->identifier) ?: + $this->componentTypeFactory->createForType( + $this->identifier, + $this->className, + true, + $this->isPrototypal + ); + +return [ + 'export-path' => 'exports/database/' + . env( + 'APP_CUSTOMER', + 'not-configured' + ) + . '/' . env( + 'APP_IDENTIFIER', + 'not-configured' + ), +]; + +$methods .= + str_replace( + array_keys($replacements), + array_values($replacements), + $methodTemplate + ) + . PHP_EOL . PHP_EOL . str_repeat(' ', 4); + +$rangeValues['min'] = + $this->adjustLowerThreshold( + $this->normalizeRatingForFilter($rangeValues['min']) + ); + +$salesOrderThresholdTransfer->fromArray($salesOrderThresholdEntity->toArray(), true) + ->setSalesOrderThresholdValue( + $this->mapSalesOrderThresholdValueTransfer($salesOrderThresholdTransfer, $salesOrderThresholdEntity) + )->setCurrency( + (new CurrencyTransfer())->fromArray($salesOrderThresholdEntity->getCurrency()->toArray(), true) + )->setStore( + (new StoreTransfer())->fromArray($salesOrderThresholdEntity->getStore()->toArray(), true) + ); + +return trim(preg_replace_callback( + // sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) + // /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search + )); + +$a = ['a' => function ($b) { return $b; }]; +$a['a']( 1 ); + +// PHP 8.0 named parameters. +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +array_fill_keys( + keys: range( 1, + 12, + ), value: true, +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false +array_fill_keys( + keys: range( 1, + 12, + ), value: true, +); +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc.fixed new file mode 100644 index 00000000..8d02e746 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc.fixed @@ -0,0 +1,565 @@ +getFoo() + ->doBar( + $this->getX() // no comma here + ->doY() // this is still the first method argument + ->doZ() // this is still the first method argument + ); +} + +$var = myFunction( + $foo, + $bar +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false + +fputs( + STDOUT, + "Examples: + $ {$app} , --all + $ {$app} --all", + $something +); + +$array = array(); +array_map( + function($x) + { + return trim($x, $y); + }, + $foo, + $array +); + +$bar = new stdClass( + 4, /* thanks */ + 5, /* PSR-2 */ + 6 +); + +function doSomething() +{ + return $this->getFoo() + ->doBar( + $this->getX() // no comma here + ->doY() // this is still the first method argument + ->doZ() // this is still the first method argument + ); +} + +doError( + 404, // status code + 'Not Found', // error name + 'Check your id' // fix +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true + +// Don't report errors for closing braces. Leave that to other sniffs. +foo( + [ + 'this', + 'is', + 'an', + 'array' + ], + [ + 'this', + 'is', + 'an', + 'array' + ], + array( + 'this', + 'is', + 'an', + 'array' + ), + array( + 'this', + 'is', + 'an', + 'array' + ), + function($x) + { + echo 'wee'; + + return trim($x); + } +); + +function foo() +{ + myFunction( + 'string'. + // comment + // comment + 'string'. + /* comment + * comment + */ + 'string' + ); +} + +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 1 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 1 +test( $arg, $arg2 ); +test( $arg, $arg2 ); +test( $arg, $arg2 ); +test(); +test(); +test(); +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 0 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 0 + +?> + + + +
  • + log(// ... + 'error', + sprintf( + 'Message: %s', + isset($e->getData()['object']['evidence_details']) + ? $e->getData()['object']['evidence_details']['due_by'] + : '' + ), + array($e->getData()['object']) +); + +?> +
    + $class + ] + ); ?> +
    + + function ($x) { + return true; + }, + 'baz' => false + ) +); +$qux = array_filter( + $quux, function ($x) { + return $x; + } +); + +array_filter( + [1, 2], + function ($i) : bool { + return $i === 0; + } +); + +foo( + array( + 'callback' => function () { + $foo = 'foo'; + return; + }, + ) +); + +foo( + $a, + /* + $c, + + $d, + */ + $e +); + +test( + 1,2,3,4 +); + +class Test +{ + public function getInstance() + { + return new static( + 'arg', + 'foo' + ); + } + + public function getSelf() + { + return new self( + 'a','b', 'c' + ); + } +} + +$x = $var( + 'y', + 'x' +); + +$obj->{$x}( + 1, + 2 +); + +return (function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})( + 'a','b' +)( + 'c', + 'd' +); + +class Foo +{ + public function bar($a, $b) + { + if (!$a || !$b) { + return; + } + + (new stdClass())->a = $a; + } +} + +return (function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})('a','b')('c','d'); + +function foo() +{ + Bar( + function () { + } + ); +} + +$deprecated_functions = [ + 'the_category_ID' + => function_call( // 7 spaces, not 8. This is the problem line. + $a, + $b + ), +]; + +$deprecated_functions = [ + 'the_category_ID' + => function_call( // 9 spaces, not 8. This is the problem line. + $a, + $b + ), +]; + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false + +printf( + '', + $obj->getName(), // Trailing comment. + $obj->getID(), // phpcs:ignore Standard.Category.SniffName -- for reasons. + $option +); + +// Handling of PHP 7.3 trailing comma's. +functionCall($args, $foo,); +functionCall( + $args, + $foo, +); +functionCall( + $args, + $foo, +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true + +$this->foo( + ['a','b'], + true +); + +$this->foo( + // Comment + ['a','b'], + true +); + +function m() +{ + $t = ' + ' . (empty(true) ? ' + ' . f( + '1', + '2', + ) . ' + ' : ''); +} + +class C +{ + + public function m() + { + $a = []; + $t = + "SELECT * FROM t +WHERE f IN(" . implode( + ",", + $a + ) . ")"; + } +} + +$notices = array( + 'index' => sprintf( + translation_function('a text string with %s placeholder'), + 'replacement' + ), +); + +$componentType = $this->componentTypeRepository->findByType($this->identifier) ?: + $this->componentTypeFactory->createForType( + $this->identifier, + $this->className, + true, + $this->isPrototypal + ); + +return [ + 'export-path' => 'exports/database/' + . env( + 'APP_CUSTOMER', + 'not-configured' + ) + . '/' . env( + 'APP_IDENTIFIER', + 'not-configured' + ), +]; + +$methods .= + str_replace( + array_keys($replacements), + array_values($replacements), + $methodTemplate + ) + . PHP_EOL . PHP_EOL . str_repeat(' ', 4); + +$rangeValues['min'] = + $this->adjustLowerThreshold( + $this->normalizeRatingForFilter($rangeValues['min']) + ); + +$salesOrderThresholdTransfer->fromArray($salesOrderThresholdEntity->toArray(), true) + ->setSalesOrderThresholdValue( + $this->mapSalesOrderThresholdValueTransfer($salesOrderThresholdTransfer, $salesOrderThresholdEntity) + )->setCurrency( + (new CurrencyTransfer())->fromArray($salesOrderThresholdEntity->getCurrency()->toArray(), true) + )->setStore( + (new StoreTransfer())->fromArray($salesOrderThresholdEntity->getStore()->toArray(), true) + ); + +return trim( + preg_replace_callback( + // sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) + // /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search + ) +); + +$a = ['a' => function ($b) { return $b; }]; +$a['a'](1); + +// PHP 8.0 named parameters. +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +array_fill_keys( + keys: range( + 1, + 12, + ), value: true, +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js new file mode 100644 index 00000000..5e77e57a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js @@ -0,0 +1,80 @@ +test( +); +test(); +test(arg, arg2); +test (); +test( ); +test() ; +test( arg); +test( arg ); +test ( arg ); + +if (foo(arg) === true) { + +} + +var something = get(arg1, arg2); +var something = get(arg1, arg2) ; +var something = get(arg1, arg2) ; + +make_foo(string/*the string*/, true/*test*/); +make_foo(string/*the string*/, true/*test*/ ); +make_foo(string /*the string*/, true /*test*/); +make_foo(/*the string*/string, /*test*/true); +make_foo( /*the string*/string, /*test*/true); + +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 1 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 1 +test(arg, arg2); +test( arg, arg2 ); +test( arg, arg2 ); +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 0 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 0 + +this.init = function(data) { + a.b('').a(function(itemid, target) { + b( + itemid, + target, + { + reviewData: _reviewData, + pageid: itemid + }, + '', + function() { + var _showAspectItems = function(itemid) { + a.a(a.c(''), ''); + a.b(a.c('-' + itemid), ''); + }; + a.foo(function(itemid, target) { + _foo(itemid); + }); + } + ); + }); +}; + +a.prototype = { + + a: function() + { + this.addItem( + { + /** + * @return void + */ + a: function() + { + + }, + /** + * @return void + */ + a: function() + { + + }, + } + ); + } +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js.fixed new file mode 100644 index 00000000..7855ac67 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js.fixed @@ -0,0 +1,84 @@ +test( +); +test(); +test(arg, arg2); +test(); +test(); +test(); +test(arg); +test(arg); +test(arg); + +if (foo(arg) === true) { + +} + +var something = get(arg1, arg2); +var something = get(arg1, arg2); +var something = get(arg1, arg2); + +make_foo(string/*the string*/, true/*test*/); +make_foo(string/*the string*/, true/*test*/); +make_foo(string /*the string*/, true /*test*/); +make_foo(/*the string*/string, /*test*/true); +make_foo(/*the string*/string, /*test*/true); + +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 1 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 1 +test( arg, arg2 ); +test( arg, arg2 ); +test( arg, arg2 ); +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 0 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 0 + +this.init = function(data) { + a.b('').a( + function(itemid, target) { + b( + itemid, + target, + { + reviewData: _reviewData, + pageid: itemid + }, + '', + function() { + var _showAspectItems = function(itemid) { + a.a(a.c(''), ''); + a.b(a.c('-' + itemid), ''); + }; + a.foo( + function(itemid, target) { + _foo(itemid); + } + ); + } + ); + } + ); +}; + +a.prototype = { + + a: function() + { + this.addItem( + { + /** + * @return void + */ + a: function() + { + + }, + /** + * @return void + */ + a: function() + { + + }, + } + ); + } +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php new file mode 100644 index 00000000..1dd59188 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php @@ -0,0 +1,154 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionCallSignatureUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='FunctionCallSignatureUnitTest.inc') + { + if ($testFile === 'FunctionCallSignatureUnitTest.js') { + return [ + 5 => 1, + 6 => 2, + 7 => 1, + 8 => 1, + 9 => 2, + 10 => 3, + 17 => 1, + 18 => 1, + 21 => 1, + 24 => 1, + 28 => 2, + 30 => 2, + 35 => 1, + 49 => 1, + 51 => 1, + 54 => 1, + 70 => 1, + 71 => 1, + ]; + }//end if + + return [ + 5 => 1, + 6 => 2, + 7 => 1, + 8 => 1, + 9 => 2, + 10 => 3, + 17 => 1, + 18 => 1, + 31 => 1, + 34 => 1, + 43 => 2, + 57 => 1, + 59 => 1, + 63 => 1, + 64 => 1, + 82 => 1, + 93 => 1, + 100 => 1, + 106 => 2, + 119 => 1, + 120 => 1, + 129 => 1, + 137 => 1, + 142 => 2, + 171 => 1, + 180 => 1, + 181 => 1, + 194 => 1, + 213 => 2, + 215 => 2, + 217 => 2, + 218 => 2, + 277 => 1, + 278 => 1, + 303 => 1, + 308 => 1, + 321 => 1, + 322 => 1, + 329 => 1, + 330 => 1, + 337 => 1, + 342 => 1, + 343 => 1, + 345 => 1, + 346 => 2, + 353 => 1, + 354 => 1, + 355 => 2, + 377 => 1, + 378 => 1, + 379 => 1, + 380 => 1, + 385 => 1, + 386 => 1, + 387 => 1, + 388 => 1, + 393 => 1, + 394 => 1, + 395 => 1, + 396 => 1, + 411 => 1, + 422 => 1, + 424 => 1, + 429 => 1, + 432 => 1, + 440 => 1, + 441 => 1, + 442 => 1, + 464 => 1, + 510 => 1, + 513 => 1, + 514 => 1, + 523 => 1, + 524 => 3, + 527 => 2, + 539 => 1, + 540 => 1, + 546 => 1, + 547 => 1, + 548 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.inc new file mode 100644 index 00000000..02e0a20d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.inc @@ -0,0 +1,420 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='FunctionDeclarationUnitTest.inc') + { + if ($testFile === 'FunctionDeclarationUnitTest.inc') { + $errors = [ + 3 => 1, + 4 => 1, + 5 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 14 => 1, + 17 => 1, + 44 => 1, + 52 => 1, + 61 => 2, + 98 => 1, + 110 => 2, + 120 => 3, + 121 => 1, + 140 => 1, + 145 => 1, + 161 => 2, + 162 => 2, + 164 => 2, + 167 => 2, + 171 => 1, + 173 => 1, + 201 => 1, + 206 => 1, + 208 => 1, + 216 => 1, + 223 => 1, + 230 => 1, + 237 => 1, + 243 => 1, + 247 => 1, + 251 => 2, + 253 => 2, + 257 => 2, + 259 => 1, + 263 => 1, + 265 => 1, + 269 => 1, + 273 => 1, + 277 => 1, + 278 => 1, + 283 => 1, + 287 => 2, + 289 => 2, + 293 => 2, + 295 => 1, + 299 => 1, + 301 => 1, + 305 => 1, + 309 => 1, + 313 => 1, + 314 => 1, + 350 => 1, + 351 => 1, + 352 => 1, + 353 => 1, + 361 => 1, + 362 => 1, + 363 => 1, + 364 => 1, + 365 => 1, + 366 => 1, + 367 => 1, + 368 => 1, + 369 => 1, + 370 => 1, + 371 => 1, + 402 => 1, + 406 => 1, + ]; + } else { + $errors = [ + 3 => 1, + 4 => 1, + 5 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 14 => 1, + 17 => 1, + 41 => 1, + 48 => 1, + ]; + }//end if + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.inc new file mode 100644 index 00000000..8f8d64ab --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.inc @@ -0,0 +1,119 @@ + $a[] = $b; + +class OnlyConstructorPropertyPromotion { + public function __construct( + public string $name = '', + protected $bar + ) {} +} + +class ConstructorPropertyPromotionMixedWithNormalParams { + public function __construct( + public string $name = '', + ?int $optionalParam = 0, + mixed $requiredParam, + ) {} +} + +// Intentional syntax error. Must be last thing in the file. +function diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.php new file mode 100644 index 00000000..60d261cb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidDefaultValueUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 29 => 1, + 34 => 1, + 39 => 1, + 71 => 1, + 76 => 1, + 81 => 1, + 91 => 1, + 99 => 1, + 101 => 1, + 106 => 1, + 114 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.inc new file mode 100644 index 00000000..053a4fee --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.inc @@ -0,0 +1,90 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidClassNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 7 => 2, + 9 => 1, + 19 => 1, + 24 => 1, + 26 => 2, + 28 => 1, + 38 => 1, + 40 => 2, + 42 => 2, + 44 => 1, + 46 => 1, + 50 => 1, + 52 => 2, + 54 => 1, + 64 => 1, + 66 => 2, + 68 => 1, + 72 => 1, + 74 => 2, + 76 => 1, + 86 => 1, + 88 => 2, + 90 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.inc new file mode 100644 index 00000000..18b1a481 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.inc @@ -0,0 +1,243 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidFunctionNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 11 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 16 => 1, + 17 => 2, + 18 => 2, + 19 => 2, + 20 => 2, + 24 => 1, + 25 => 1, + 26 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 2, + 31 => 2, + 32 => 2, + 33 => 2, + 35 => 1, + 36 => 1, + 37 => 2, + 38 => 2, + 39 => 2, + 40 => 2, + 43 => 1, + 44 => 1, + 45 => 1, + 46 => 1, + 50 => 1, + 51 => 1, + 52 => 1, + 53 => 1, + 56 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 70 => 1, + 71 => 1, + 72 => 1, + 73 => 2, + 74 => 2, + 75 => 2, + 76 => 2, + 80 => 1, + 81 => 1, + 82 => 1, + 83 => 1, + 86 => 1, + 87 => 1, + 88 => 1, + 89 => 1, + 95 => 1, + 96 => 1, + 97 => 1, + 98 => 1, + 99 => 1, + 100 => 1, + 101 => 2, + 102 => 2, + 103 => 2, + 104 => 2, + 123 => 1, + 125 => 1, + 126 => 2, + 129 => 1, + 130 => 1, + 131 => 1, + 132 => 1, + 133 => 1, + 134 => 1, + 135 => 1, + 136 => 1, + 137 => 1, + 138 => 1, + 139 => 1, + 140 => 3, + 141 => 1, + 143 => 1, + 144 => 1, + 145 => 3, + 147 => 2, + 148 => 1, + 149 => 1, + 181 => 1, + 201 => 1, + 203 => 1, + 204 => 2, + 207 => 2, + 212 => 1, + 213 => 1, + 214 => 1, + 235 => 1, + 236 => 2, + 239 => 1, + 242 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.inc new file mode 100644 index 00000000..3c03da3f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.inc @@ -0,0 +1,101 @@ +def["POP_{$cc}_A"]}' + and POP_{$cc}_B = +'{$this->def["POP_{$cc}_B"]}')"; + } +} + +class mpgResponse{ + var $term_id; + var $currentTag; + function characterHandler($parser,$data){ + switch($this->currentTag) + { + case "term_id": { + $this->term_id=$data; + break; + } + } + }//end characterHandler +}//end class mpgResponse + +class foo +{ + const bar = <<setLogger( + new class { + private $varName = 'hello'; + private $_varName = 'hello'; +}); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.php new file mode 100644 index 00000000..834852c3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.php @@ -0,0 +1,56 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidVariableNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 12 => 1, + 17 => 1, + 22 => 1, + 92 => 1, + 93 => 1, + 94 => 1, + 99 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc new file mode 100644 index 00000000..b1b09d93 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc @@ -0,0 +1,142 @@ +someFunction("some", "parameter") +->someOtherFunc(23, 42)-> + someOtherFunc2($one, $two) + + ->someOtherFunc3(23, 42) + ->andAThirdFunction(); + + $someObject->someFunction("some", "parameter") + ->someOtherFunc(23, 42); + +$someObject->someFunction("some", "parameter")->someOtherFunc(23, 42); + +$someObject->someFunction("some", "parameter") + ->someOtherFunc(23, 42); + +func( + $bar->foo() +) + ->bar(); + +func( + $bar->foo() +) + ->bar( + $bar->foo() + ->bar() + ->func() + ); + +$object + ->setBar($foo) + ->setFoo($bar); + +if ($bar) { + $object + ->setBar($foo) + ->setFoo($bar); +} + +$response -> CompletedTrackDetails -> TrackDetails -> Events; +$response + -> CompletedTrackDetails + -> TrackDetails + -> Events; + +$response + -> CompletedTrackDetails +-> TrackDetails + -> Events; + +$var = get_object( + $foo->something() + ->query() +)->two() + ->three(); + +$foo->one( + $foo + ->two() +); + +get_object()->one() + ->two() + ->three(); + +someclass::one() + ->two() + ->three(); + +(new someclass())->one() + ->two() + ->three(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel true + +$someObject + ->startSomething() + ->someOtherFunc(23, 42) +->endSomething() +->doSomething(23, 42) +->endEverything(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() +->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel false + +$object + ?->setBar($foo) + ?->setFoo($bar); + +$someObject?->someFunction("some", "parameter") +->someOtherFunc(23, 42)?-> + someOtherFunc2($one, $two) + +->someOtherFunc3(23, 42) + ?->andAThirdFunction(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel true +$object + ?->setBar($foo) + ?->setFoo($bar); + +$someObject?->someFunction("some", "parameter") +->someOtherFunc(23, 42) + ?->someOtherFunc2($one, $two) + +->someOtherFunc3(23, 42) + ?->andAThirdFunction(); +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel false + +$someObject + ->startSomething(paramName: $value) + ->someOtherFunc(nameA: 23, nameB: 42) +->endSomething($value, name: $value) +->endEverything(); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc.fixed new file mode 100644 index 00000000..5d5b77be --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc.fixed @@ -0,0 +1,142 @@ +someFunction("some", "parameter") + ->someOtherFunc(23, 42) + ->someOtherFunc2($one, $two) + + ->someOtherFunc3(23, 42) + ->andAThirdFunction(); + + $someObject->someFunction("some", "parameter") + ->someOtherFunc(23, 42); + +$someObject->someFunction("some", "parameter")->someOtherFunc(23, 42); + +$someObject->someFunction("some", "parameter") + ->someOtherFunc(23, 42); + +func( + $bar->foo() +) + ->bar(); + +func( + $bar->foo() +) + ->bar( + $bar->foo() + ->bar() + ->func() + ); + +$object + ->setBar($foo) + ->setFoo($bar); + +if ($bar) { + $object + ->setBar($foo) + ->setFoo($bar); +} + +$response -> CompletedTrackDetails -> TrackDetails -> Events; +$response + -> CompletedTrackDetails + -> TrackDetails + -> Events; + +$response + -> CompletedTrackDetails + -> TrackDetails + -> Events; + +$var = get_object( + $foo->something() + ->query() +)->two() + ->three(); + +$foo->one( + $foo + ->two() +); + +get_object()->one() + ->two() + ->three(); + +someclass::one() + ->two() + ->three(); + +(new someclass())->one() + ->two() + ->three(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel true + +$someObject + ->startSomething() + ->someOtherFunc(23, 42) + ->endSomething() + ->doSomething(23, 42) + ->endEverything(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel false + +$object + ?->setBar($foo) + ?->setFoo($bar); + +$someObject?->someFunction("some", "parameter") + ->someOtherFunc(23, 42) + ?->someOtherFunc2($one, $two) + + ->someOtherFunc3(23, 42) + ?->andAThirdFunction(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel true +$object + ?->setBar($foo) + ?->setFoo($bar); + +$someObject?->someFunction("some", "parameter") + ->someOtherFunc(23, 42) + ?->someOtherFunc2($one, $two) + + ->someOtherFunc3(23, 42) + ?->andAThirdFunction(); +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel false + +$someObject + ->startSomething(paramName: $value) + ->someOtherFunc(nameA: 23, nameB: 42) + ->endSomething($value, name: $value) + ->endEverything(); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.php new file mode 100644 index 00000000..0cad3efc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.php @@ -0,0 +1,74 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ObjectOperatorIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 2, + 6 => 1, + 15 => 1, + 27 => 1, + 37 => 1, + 38 => 1, + 48 => 1, + 49 => 1, + 50 => 1, + 65 => 1, + 69 => 1, + 73 => 1, + 79 => 1, + 80 => 1, + 81 => 1, + 82 => 1, + 95 => 1, + 103 => 1, + 119 => 2, + 122 => 1, + 131 => 1, + 134 => 1, + 140 => 1, + 141 => 1, + 142 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc new file mode 100644 index 00000000..3f900679 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc @@ -0,0 +1,164 @@ +{$property} =& new $class_name($this->db_index); + $this->modules[$module] =& $this->{$property}; +} + +foreach ($elements as $element) { + if ($something) { + // Do IF. + } else if ($somethingElse) { + // Do ELSE. + } +} + +switch ($foo) { +case 1: + switch ($bar) { + default: + if ($something) { + echo $string{1}; + } else if ($else) { + switch ($else) { + case 1: + // Do something. + break; + default: + // Do something. + break; + } + } + } +break; +case 2: + // Do something; + break; +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + default: + return 'Unknown'; +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + return 'Processing.'; + default: + return 'Unknown'; +} + +switch($i) { +case 1: {} +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + exit; + default: + exit; +} + +if ($foo): + if ($bar): + $foo = 1; + elseif ($baz): + $foo = 2; + endif; +endif; + +if ($foo): +elseif ($baz): $foo = 2; +endif; + +?> +
      + +
    • + +
    +
      + +
    • + +
    +
      + +
    • + +
    + +getSummaryCount(); ?> +
    class="empty"> + + 'a', 2 => 'b' }; + +$match = match ($test) { + 1 => 'a', + 2 => 'b' + }; + +enum Enum +{ +} + +enum Suits {} + +enum Cards +{ + } diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc.fixed new file mode 100644 index 00000000..f369c2b2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc.fixed @@ -0,0 +1,170 @@ +{$property} =& new $class_name($this->db_index); + $this->modules[$module] =& $this->{$property}; +} + +foreach ($elements as $element) { + if ($something) { + // Do IF. + } else if ($somethingElse) { + // Do ELSE. + } +} + +switch ($foo) { +case 1: + switch ($bar) { + default: + if ($something) { + echo $string{1}; + } else if ($else) { + switch ($else) { + case 1: + // Do something. + break; + default: + // Do something. + break; + } + } + } + break; +case 2: + // Do something; + break; +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + default: + return 'Unknown'; +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + return 'Processing.'; + default: + return 'Unknown'; +} + +switch($i) { +case 1: { + } +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + exit; + default: + exit; +} + +if ($foo): + if ($bar): + $foo = 1; + elseif ($baz): + $foo = 2; + endif; +endif; + +if ($foo): +elseif ($baz): $foo = 2; +endif; + +?> +
      + +
    • + +
    +
      + +
    • + +
    +
      + +
    • + +
    + +getSummaryCount(); ?> +
    class="empty"> + + 'a', 2 => 'b' +}; + +$match = match ($test) { + 1 => 'a', + 2 => 'b' +}; + +enum Enum +{ +} + +enum Suits { +} + +enum Cards +{ +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.php new file mode 100644 index 00000000..26593254 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.php @@ -0,0 +1,67 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ScopeClosingBraceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 11 => 1, + 13 => 1, + 24 => 1, + 30 => 1, + 61 => 1, + 65 => 1, + 85 => 1, + 89 => 1, + 98 => 1, + 122 => 1, + 127 => 1, + 135 => 1, + 141 => 1, + 146 => 1, + 149 => 1, + 154 => 1, + 160 => 1, + 164 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.inc new file mode 100644 index 00000000..b122a147 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.inc @@ -0,0 +1,314 @@ +hello(); // error here + } + + function hello() // error here + { // no error here as brackets can be put anywhere in the pear standard + echo 'hello'; + } + + function hello2() + { + if (TRUE) { // error here + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; // error here + } + + while (TRUE) { + echo 'hello'; // error here + } + + do { // error here + echo 'hello'; // error here + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
    +
    +
    +validate()) {
    +    $safe = $form->getSubmitValues();
    +}
    +?>
    +
    +open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* + * + * + * + */ + + /** + */ + + /* + This comment has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ScopeIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 10 => 1, + 17 => 1, + 20 => 1, + 24 => 1, + 25 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 58 => 1, + 123 => 1, + 224 => 1, + 225 => 1, + 279 => 1, + 284 => 1, + 311 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/ruleset.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/ruleset.xml new file mode 100644 index 00000000..1bf94ca5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/ruleset.xml @@ -0,0 +1,41 @@ + + + The PEAR coding standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Classes/ClassDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Classes/ClassDeclarationStandard.xml new file mode 100644 index 00000000..eaae99b2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Classes/ClassDeclarationStandard.xml @@ -0,0 +1,48 @@ + + + + + + + class Bar { +} + ]]> + + + class Bar { +} + +class Baz { +} + ]]> + + + + + namespace Foo; + +class Bar { +} + ]]> + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Files/SideEffectsStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Files/SideEffectsStandard.xml new file mode 100644 index 00000000..0ed04a07 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Files/SideEffectsStandard.xml @@ -0,0 +1,27 @@ + + + + + + + + + + echo "Class Foo loaded." + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Methods/CamelCapsMethodNameStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Methods/CamelCapsMethodNameStandard.xml new file mode 100644 index 00000000..8db899d6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Methods/CamelCapsMethodNameStandard.xml @@ -0,0 +1,29 @@ + + + + + + + doBar() + { + } +} + ]]> + + + do_bar() + { + } +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Classes/ClassDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Classes/ClassDeclarationSniff.php new file mode 100644 index 00000000..3db26f6f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Classes/ClassDeclarationSniff.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClassDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param integer $stackPtr The position of the current token in + * the token stack. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $errorData = [strtolower($tokens[$stackPtr]['content'])]; + + $nextClass = $phpcsFile->findNext([T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM], ($tokens[$stackPtr]['scope_closer'] + 1)); + if ($nextClass !== false) { + $error = 'Each %s must be in a file by itself'; + $phpcsFile->addError($error, $nextClass, 'MultipleClasses', $errorData); + $phpcsFile->recordMetric($stackPtr, 'One class per file', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'One class per file', 'yes'); + } + + $namespace = $phpcsFile->findNext([T_NAMESPACE, T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM], 0); + if ($tokens[$namespace]['code'] !== T_NAMESPACE) { + $error = 'Each %s must be in a namespace of at least one level (a top-level vendor name)'; + $phpcsFile->addError($error, $stackPtr, 'MissingNamespace', $errorData); + $phpcsFile->recordMetric($stackPtr, 'Class defined in namespace', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Class defined in namespace', 'yes'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Files/SideEffectsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Files/SideEffectsSniff.php new file mode 100644 index 00000000..3f8c5e0d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Files/SideEffectsSniff.php @@ -0,0 +1,299 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SideEffectsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the token stack. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $result = $this->searchForConflict($phpcsFile, 0, ($phpcsFile->numTokens - 1), $tokens); + + if ($result['symbol'] !== null && $result['effect'] !== null) { + $error = 'A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should execute logic with side effects, but should not do both. The first symbol is defined on line %s and the first side effect is on line %s.'; + $data = [ + $tokens[$result['symbol']]['line'], + $tokens[$result['effect']]['line'], + ]; + $phpcsFile->addWarning($error, 0, 'FoundWithSymbols', $data); + $phpcsFile->recordMetric($stackPtr, 'Declarations and side effects mixed', 'yes'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Declarations and side effects mixed', 'no'); + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + + /** + * Searches for symbol declarations and side effects. + * + * Returns the positions of both the first symbol declared and the first + * side effect in the file. A NULL value for either indicates nothing was + * found. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $start The token to start searching from. + * @param int $end The token to search to. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return array + */ + private function searchForConflict($phpcsFile, $start, $end, $tokens) + { + $symbols = [ + T_CLASS => T_CLASS, + T_INTERFACE => T_INTERFACE, + T_TRAIT => T_TRAIT, + T_ENUM => T_ENUM, + T_FUNCTION => T_FUNCTION, + ]; + + $conditions = [ + T_IF => T_IF, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + ]; + + $checkAnnotations = $phpcsFile->config->annotations; + + $firstSymbol = null; + $firstEffect = null; + for ($i = $start; $i <= $end; $i++) { + // Respect phpcs:disable comments. + if ($checkAnnotations === true + && $tokens[$i]['code'] === T_PHPCS_DISABLE + && (empty($tokens[$i]['sniffCodes']) === true + || isset($tokens[$i]['sniffCodes']['PSR1']) === true + || isset($tokens[$i]['sniffCodes']['PSR1.Files']) === true + || isset($tokens[$i]['sniffCodes']['PSR1.Files.SideEffects']) === true) + ) { + do { + $i = $phpcsFile->findNext(T_PHPCS_ENABLE, ($i + 1)); + } while ($i !== false + && empty($tokens[$i]['sniffCodes']) === false + && isset($tokens[$i]['sniffCodes']['PSR1']) === false + && isset($tokens[$i]['sniffCodes']['PSR1.Files']) === false + && isset($tokens[$i]['sniffCodes']['PSR1.Files.SideEffects']) === false); + + if ($i === false) { + // The entire rest of the file is disabled, + // so return what we have so far. + break; + } + + continue; + } + + // Ignore whitespace and comments. + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + // Ignore PHP tags. + if ($tokens[$i]['code'] === T_OPEN_TAG + || $tokens[$i]['code'] === T_CLOSE_TAG + ) { + continue; + } + + // Ignore shebang. + if (substr($tokens[$i]['content'], 0, 2) === '#!') { + continue; + } + + // Ignore logical operators. + if (isset(Tokens::$booleanOperators[$tokens[$i]['code']]) === true) { + continue; + } + + // Ignore entire namespace, declare, const and use statements. + if ($tokens[$i]['code'] === T_NAMESPACE + || $tokens[$i]['code'] === T_USE + || $tokens[$i]['code'] === T_DECLARE + || $tokens[$i]['code'] === T_CONST + ) { + if (isset($tokens[$i]['scope_opener']) === true) { + $i = $tokens[$i]['scope_closer']; + if ($tokens[$i]['code'] === T_ENDDECLARE) { + $semicolon = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($semicolon !== false && $tokens[$semicolon]['code'] === T_SEMICOLON) { + $i = $semicolon; + } + } + } else { + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($i + 1)); + if ($semicolon !== false) { + $i = $semicolon; + } + } + + continue; + } + + // Ignore function/class prefixes. + if (isset(Tokens::$methodPrefixes[$tokens[$i]['code']]) === true) { + continue; + } + + // Ignore anon classes. + if ($tokens[$i]['code'] === T_ANON_CLASS) { + $i = $tokens[$i]['scope_closer']; + continue; + } + + // Ignore attributes. + if ($tokens[$i]['code'] === T_ATTRIBUTE + && isset($tokens[$i]['attribute_closer']) === true + ) { + $i = $tokens[$i]['attribute_closer']; + continue; + } + + // Detect and skip over symbols. + if (isset($symbols[$tokens[$i]['code']]) === true + && isset($tokens[$i]['scope_closer']) === true + ) { + if ($firstSymbol === null) { + $firstSymbol = $i; + } + + $i = $tokens[$i]['scope_closer']; + continue; + } else if ($tokens[$i]['code'] === T_STRING + && strtolower($tokens[$i]['content']) === 'define' + ) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), null, true); + if ($tokens[$prev]['code'] !== T_OBJECT_OPERATOR + && $tokens[$prev]['code'] !== T_NULLSAFE_OBJECT_OPERATOR + && $tokens[$prev]['code'] !== T_DOUBLE_COLON + && $tokens[$prev]['code'] !== T_FUNCTION + ) { + if ($firstSymbol === null) { + $firstSymbol = $i; + } + + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($i + 1)); + if ($semicolon !== false) { + $i = $semicolon; + } + + continue; + } + }//end if + + // Special case for defined() as it can be used to see + // if a constant (a symbol) should be defined or not and + // doesn't need to use a full conditional block. + if ($tokens[$i]['code'] === T_STRING + && strtolower($tokens[$i]['content']) === 'defined' + ) { + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($openBracket !== false + && $tokens[$openBracket]['code'] === T_OPEN_PARENTHESIS + && isset($tokens[$openBracket]['parenthesis_closer']) === true + ) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), null, true); + if ($tokens[$prev]['code'] !== T_OBJECT_OPERATOR + && $tokens[$prev]['code'] !== T_NULLSAFE_OBJECT_OPERATOR + && $tokens[$prev]['code'] !== T_DOUBLE_COLON + && $tokens[$prev]['code'] !== T_FUNCTION + ) { + $i = $tokens[$openBracket]['parenthesis_closer']; + continue; + } + } + }//end if + + // Conditional statements are allowed in symbol files as long as the + // contents is only a symbol definition. So don't count these as effects + // in this case. + if (isset($conditions[$tokens[$i]['code']]) === true) { + if (isset($tokens[$i]['scope_opener']) === false) { + // Probably an "else if", so just ignore. + continue; + } + + $result = $this->searchForConflict( + $phpcsFile, + ($tokens[$i]['scope_opener'] + 1), + ($tokens[$i]['scope_closer'] - 1), + $tokens + ); + + if ($result['symbol'] !== null) { + if ($firstSymbol === null) { + $firstSymbol = $result['symbol']; + } + + if ($result['effect'] !== null) { + // Found a conflict. + $firstEffect = $result['effect']; + break; + } + } + + if ($firstEffect === null) { + $firstEffect = $result['effect']; + } + + $i = $tokens[$i]['scope_closer']; + continue; + }//end if + + if ($firstEffect === null) { + $firstEffect = $i; + } + + if ($firstSymbol !== null) { + // We have a conflict we have to report, so no point continuing. + break; + } + }//end for + + return [ + 'symbol' => $firstSymbol, + 'effect' => $firstEffect, + ]; + + }//end searchForConflict() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php new file mode 100644 index 00000000..2d138146 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff as GenericCamelCapsFunctionNameSniff; +use PHP_CodeSniffer\Util\Common; + +class CamelCapsMethodNameSniff extends GenericCamelCapsFunctionNameSniff +{ + + + /** + * Processes the tokens within the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * @param int $currScope The position of the current scope. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + // Ignore magic methods. + if (preg_match('|^__[^_]|', $methodName) !== 0) { + $magicPart = strtolower(substr($methodName, 2)); + if (isset($this->magicMethods[$magicPart]) === true + || isset($this->methodsDoubleUnderscore[$magicPart]) === true + ) { + return; + } + } + + $testName = ltrim($methodName, '_'); + if ($testName !== '' && Common::isCamelCaps($testName, false, true, false) === false) { + $error = 'Method name "%s" is not in camel caps format'; + $className = $phpcsFile->getDeclarationName($currScope); + if (isset($className) === false) { + $className = '[Anonymous Class]'; + } + + $errorData = [$className.'::'.$methodName]; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'yes'); + } + + }//end processTokenWithinScope() + + + /** + * Processes the tokens outside the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.1.inc new file mode 100644 index 00000000..58cb85e3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.1.inc @@ -0,0 +1,3 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + if ($testFile === 'ClassDeclarationUnitTest.2.inc') { + return []; + } + + return [ + 2 => 1, + 3 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.1.inc new file mode 100644 index 00000000..ca538823 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.1.inc @@ -0,0 +1,79 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.10.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.10.inc new file mode 100644 index 00000000..63f256d4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.10.inc @@ -0,0 +1,8 @@ +define("MAXSIZE", 100); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.14.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.14.inc new file mode 100644 index 00000000..9499885b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.14.inc @@ -0,0 +1,2 @@ +define("MAXSIZE", 100); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.15.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.15.inc new file mode 100644 index 00000000..0500d10e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.15.inc @@ -0,0 +1,2 @@ +defined('MINSIZE') or define("MAXSIZE", 100); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.16.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.16.inc new file mode 100644 index 00000000..588ece58 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.16.inc @@ -0,0 +1,2 @@ +defined('MINSIZE') or define("MAXSIZE", 100); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.2.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.2.inc new file mode 100644 index 00000000..4c9b8e66 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.2.inc @@ -0,0 +1,24 @@ +define(); +echo $object -> define(); +Foo::define(); + +$c = new class extends Something{ + + public function someMethod() + { + // ... + } + +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.3.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.3.inc new file mode 100644 index 00000000..d4ae77ee --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.3.inc @@ -0,0 +1,6 @@ + +'; +} + +printHead(); +?> + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.5.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.5.inc new file mode 100644 index 00000000..7265c637 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.5.inc @@ -0,0 +1,2 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.6.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.6.inc new file mode 100644 index 00000000..e02fed4b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.6.inc @@ -0,0 +1,9 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SideEffectsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Set CLI values before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + if ($testFile === 'SideEffectsUnitTest.12.inc') { + $config->annotations = false; + } + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'SideEffectsUnitTest.3.inc': + case 'SideEffectsUnitTest.4.inc': + case 'SideEffectsUnitTest.5.inc': + case 'SideEffectsUnitTest.10.inc': + case 'SideEffectsUnitTest.12.inc': + case 'SideEffectsUnitTest.15.inc': + case 'SideEffectsUnitTest.16.inc': + return [1 => 1]; + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.inc new file mode 100644 index 00000000..7381517f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.inc @@ -0,0 +1,81 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Tests\Methods; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class CamelCapsMethodNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 6 => 1, + 7 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 17 => 1, + 21 => 1, + 25 => 1, + 26 => 1, + 77 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/ruleset.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/ruleset.xml new file mode 100644 index 00000000..65cbe20e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/ruleset.xml @@ -0,0 +1,47 @@ + + + The PSR1 coding standard. + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClassInstantiationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClassInstantiationStandard.xml new file mode 100644 index 00000000..ae24611d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClassInstantiationStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/NullableTypeDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/NullableTypeDeclarationStandard.xml new file mode 100644 index 00000000..2032c9a6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/NullableTypeDeclarationStandard.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Keywords/ShortFormTypeKeywordsStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Keywords/ShortFormTypeKeywordsStandard.xml new file mode 100644 index 00000000..9bb5a8a5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Keywords/ShortFormTypeKeywordsStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + (boolean) $isValid; + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Namespaces/CompoundNamespaceDepthStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Namespaces/CompoundNamespaceDepthStandard.xml new file mode 100644 index 00000000..b74e8b42 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Namespaces/CompoundNamespaceDepthStandard.xml @@ -0,0 +1,28 @@ + + + + + + + + + + SubnamespaceOne\AnotherNamespace\ClassA, + SubnamespaceOne\ClassB, + ClassZ, +}; + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Operators/OperatorSpacingStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Operators/OperatorSpacingStandard.xml new file mode 100644 index 00000000..981b1d97 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Operators/OperatorSpacingStandard.xml @@ -0,0 +1,27 @@ + + + + + + + $b) { + $variable = $foo ? 'foo' : 'bar'; +} + ]]> + + + $b) { + $variable=$foo?'foo':'bar'; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/AnonClassDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/AnonClassDeclarationSniff.php new file mode 100644 index 00000000..7a33bd94 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/AnonClassDeclarationSniff.php @@ -0,0 +1,242 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\Generic\Sniffs\Functions\FunctionCallArgumentSpacingSniff; +use PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes\ClassDeclarationSniff; +use PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions\MultiLineFunctionDeclarationSniff; +use PHP_CodeSniffer\Util\Tokens; + +class AnonClassDeclarationSniff extends ClassDeclarationSniff +{ + + /** + * The PSR2 MultiLineFunctionDeclarations sniff. + * + * @var MultiLineFunctionDeclarationSniff + */ + private $multiLineSniff = null; + + /** + * The Generic FunctionCallArgumentSpacing sniff. + * + * @var FunctionCallArgumentSpacingSniff + */ + private $functionCallSniff = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_ANON_CLASS]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + $this->multiLineSniff = new MultiLineFunctionDeclarationSniff(); + $this->functionCallSniff = new FunctionCallArgumentSpacingSniff(); + + $this->processOpen($phpcsFile, $stackPtr); + $this->processClose($phpcsFile, $stackPtr); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === true) { + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + if ($this->multiLineSniff->isMultiLineDeclaration($phpcsFile, $stackPtr, $openBracket, $tokens) === true) { + $this->processMultiLineArgumentList($phpcsFile, $stackPtr); + } else { + $this->processSingleLineArgumentList($phpcsFile, $stackPtr); + } + + $this->functionCallSniff->checkSpacing($phpcsFile, $stackPtr, $openBracket); + } + + $opener = $tokens[$stackPtr]['scope_opener']; + if ($tokens[$opener]['line'] === $tokens[$stackPtr]['line']) { + return; + } + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($opener - 1), $stackPtr, true); + + $implements = $phpcsFile->findPrevious(T_IMPLEMENTS, ($opener - 1), $stackPtr); + if ($implements !== false + && $tokens[$opener]['line'] !== $tokens[$implements]['line'] + && $tokens[$opener]['line'] === $tokens[$prev]['line'] + ) { + // Opening brace must be on a new line as implements list wraps. + $error = 'Opening brace must be on the line after the last implemented interface'; + $fix = $phpcsFile->addFixableError($error, $opener, 'OpenBraceSameLine'); + if ($fix === true) { + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $indent = str_repeat(' ', ($tokens[$first]['column'] - 1)); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($prev + 1), ''); + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->addContentBefore($opener, $indent); + $phpcsFile->fixer->endChangeset(); + } + } + + if ($tokens[$opener]['line'] > ($tokens[$prev]['line'] + 1)) { + // Opening brace is on a new line, so there must be no blank line before it. + $error = 'Opening brace must not be preceded by a blank line'; + $fix = $phpcsFile->addFixableError($error, $opener, 'OpenBraceLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($prev + 1); $x < $opener; $x++) { + if ($tokens[$x]['line'] === $tokens[$prev]['line']) { + // Maintain existing newline. + continue; + } + + if ($tokens[$x]['line'] === $tokens[$opener]['line']) { + // Maintain existing indent. + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + }//end process() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processSingleLineArgumentList(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + if ($openBracket === ($closeBracket - 1)) { + return; + } + + if ($tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + $error = 'Space after opening parenthesis of single-line argument list prohibited'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterOpenBracket'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } + } + + $spaceBeforeClose = 0; + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), $openBracket, true); + if ($tokens[$prev]['code'] === T_END_HEREDOC || $tokens[$prev]['code'] === T_END_NOWDOC) { + // Need a newline after these tokens, so ignore this rule. + return; + } + + if ($tokens[$prev]['line'] !== $tokens[$closeBracket]['line']) { + $spaceBeforeClose = 'newline'; + } else if ($tokens[($closeBracket - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = $tokens[($closeBracket - 1)]['length']; + } + + if ($spaceBeforeClose !== 0) { + $error = 'Space before closing parenthesis of single-line argument list prohibited'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeCloseBracket'); + if ($fix === true) { + if ($spaceBeforeClose === 'newline') { + $phpcsFile->fixer->beginChangeset(); + + $closingContent = ')'; + + $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON) { + $closingContent .= ';'; + for ($i = ($closeBracket + 1); $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + // We want to jump over any whitespace or inline comment and + // move the closing parenthesis after any other token. + $prev = ($closeBracket - 1); + while (isset(Tokens::$emptyTokens[$tokens[$prev]['code']]) === true) { + if (($tokens[$prev]['code'] === T_COMMENT) + && (strpos($tokens[$prev]['content'], '*/') !== false) + ) { + break; + } + + $prev--; + } + + $phpcsFile->fixer->addContent($prev, $closingContent); + + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), null, true); + for ($i = ($prevNonWhitespace + 1); $i <= $closeBracket; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($closeBracket - 1), ''); + }//end if + }//end if + }//end if + + }//end processSingleLineArgumentList() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processMultiLineArgumentList(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + + $this->multiLineSniff->processBracket($phpcsFile, $openBracket, $tokens, 'argument'); + $this->multiLineSniff->processArgumentList($phpcsFile, $stackPtr, $this->indent, 'argument'); + + }//end processMultiLineArgumentList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClassInstantiationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClassInstantiationSniff.php new file mode 100644 index 00000000..e4ebd576 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClassInstantiationSniff.php @@ -0,0 +1,114 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassInstantiationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_NEW]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Find the class name. + $allowed = [ + T_STRING => T_STRING, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_SELF => T_SELF, + T_STATIC => T_STATIC, + T_VARIABLE => T_VARIABLE, + T_DOLLAR => T_DOLLAR, + T_OBJECT_OPERATOR => T_OBJECT_OPERATOR, + T_NULLSAFE_OBJECT_OPERATOR => T_NULLSAFE_OBJECT_OPERATOR, + T_DOUBLE_COLON => T_DOUBLE_COLON, + ]; + + $allowed += Tokens::$emptyTokens; + + $classNameEnd = null; + for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) { + if (isset($allowed[$tokens[$i]['code']]) === true) { + continue; + } + + // Skip over potential attributes for anonymous classes. + if ($tokens[$i]['code'] === T_ATTRIBUTE + && isset($tokens[$i]['attribute_closer']) === true + ) { + $i = $tokens[$i]['attribute_closer']; + continue; + } + + if ($tokens[$i]['code'] === T_OPEN_SQUARE_BRACKET + || $tokens[$i]['code'] === T_OPEN_CURLY_BRACKET + ) { + $i = $tokens[$i]['bracket_closer']; + continue; + } + + $classNameEnd = $i; + break; + }//end for + + if ($classNameEnd === null) { + return; + } + + if ($tokens[$classNameEnd]['code'] === T_ANON_CLASS) { + // Ignore anon classes. + return; + } + + if ($tokens[$classNameEnd]['code'] === T_OPEN_PARENTHESIS) { + // Using parenthesis. + return; + } + + if ($classNameEnd === $stackPtr) { + // Failed to find the class name. + return; + } + + $error = 'Parentheses must be used when instantiating a new class'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MissingParentheses'); + if ($fix === true) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($classNameEnd - 1), null, true); + $phpcsFile->fixer->addContent($prev, '()'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClosingBraceSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClosingBraceSniff.php new file mode 100644 index 00000000..fa1f8d60 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClosingBraceSniff.php @@ -0,0 +1,67 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClosingBraceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_FUNCTION, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $closer = $tokens[$stackPtr]['scope_closer']; + $next = $phpcsFile->findNext(T_WHITESPACE, ($closer + 1), null, true); + if ($next === false + || $tokens[$next]['line'] !== $tokens[$closer]['line'] + ) { + return; + } + + $error = 'Closing brace must not be followed by any comment or statement on the same line'; + $phpcsFile->addError($error, $closer, 'StatementAfter'); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/OpeningBraceSpaceSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/OpeningBraceSpaceSniff.php new file mode 100644 index 00000000..83ffda4d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/OpeningBraceSpaceSniff.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OpeningBraceSpaceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$ooScopeTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + $opener = $tokens[$stackPtr]['scope_opener']; + $next = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), null, true); + if ($next === false + || $tokens[$next]['line'] <= ($tokens[$opener]['line'] + 1) + ) { + return; + } + + $error = 'Opening brace must not be followed by a blank line'; + $fix = $phpcsFile->addFixableError($error, $opener, 'Found'); + if ($fix === false) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + for ($i = ($opener + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$opener]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php new file mode 100644 index 00000000..b87c3391 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php @@ -0,0 +1,229 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class BooleanOperatorPlacementSniff implements Sniff +{ + + /** + * Used to restrict the placement of the boolean operator. + * + * Allowed value are "first" or "last". + * + * @var string|null + */ + public $allowOnly = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_WHILE, + T_SWITCH, + T_ELSEIF, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + ) { + return; + } + + $parenOpener = $tokens[$stackPtr]['parenthesis_opener']; + $parenCloser = $tokens[$stackPtr]['parenthesis_closer']; + + if ($tokens[$parenOpener]['line'] === $tokens[$parenCloser]['line']) { + // Conditions are all on the same line. + return; + } + + $find = [ + T_BOOLEAN_AND, + T_BOOLEAN_OR, + ]; + + if ($this->allowOnly === 'first' || $this->allowOnly === 'last') { + $position = $this->allowOnly; + } else { + $position = null; + } + + $operator = $parenOpener; + $error = false; + $operators = []; + + do { + $operator = $phpcsFile->findNext($find, ($operator + 1), $parenCloser); + if ($operator === false) { + break; + } + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($operator - 1), $parenOpener, true); + if ($prev === false) { + // Parse error. + return; + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($operator + 1), $parenCloser, true); + if ($next === false) { + // Parse error. + return; + } + + $firstOnLine = false; + $lastOnLine = false; + + if ($tokens[$prev]['line'] < $tokens[$operator]['line']) { + // The boolean operator is the first content on the line. + $firstOnLine = true; + } + + if ($tokens[$next]['line'] > $tokens[$operator]['line']) { + // The boolean operator is the last content on the line. + $lastOnLine = true; + } + + if ($firstOnLine === true && $lastOnLine === true) { + // The operator is the only content on the line. + // Don't record it because we can't determine + // placement information from looking at it. + continue; + } + + $operators[] = $operator; + + if ($firstOnLine === false && $lastOnLine === false) { + // It's in the middle of content, so we can't determine + // placement information from looking at it, but we may + // still need to process it. + continue; + } + + if ($firstOnLine === true) { + if ($position === null) { + $position = 'first'; + } + + if ($position !== 'first') { + $error = true; + } + } else { + if ($position === null) { + $position = 'last'; + } + + if ($position !== 'last') { + $error = true; + } + } + } while ($operator !== false); + + if ($error === false) { + return; + } + + switch ($this->allowOnly) { + case 'first': + $error = 'Boolean operators between conditions must be at the beginning of the line'; + break; + case 'last': + $error = 'Boolean operators between conditions must be at the end of the line'; + break; + default: + $error = 'Boolean operators between conditions must be at the beginning or end of the line, but not both'; + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FoundMixed'); + if ($fix === false) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + foreach ($operators as $operator) { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($operator - 1), $parenOpener, true); + $next = $phpcsFile->findNext(T_WHITESPACE, ($operator + 1), $parenCloser, true); + + if ($position === 'last') { + if ($tokens[$next]['line'] === $tokens[$operator]['line']) { + if ($tokens[$prev]['line'] === $tokens[$operator]['line']) { + // Move the content after the operator to the next line. + if ($tokens[($operator + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($operator + 1), ''); + } + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $operator, true); + $padding = str_repeat(' ', ($tokens[$first]['column'] - 1)); + $phpcsFile->fixer->addContent($operator, $phpcsFile->eolChar.$padding); + } else { + // Move the operator to the end of the previous line. + if ($tokens[($operator + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($operator + 1), ''); + } + + $phpcsFile->fixer->addContent($prev, ' '.$tokens[$operator]['content']); + $phpcsFile->fixer->replaceToken($operator, ''); + } + }//end if + } else { + if ($tokens[$prev]['line'] === $tokens[$operator]['line']) { + if ($tokens[$next]['line'] === $tokens[$operator]['line']) { + // Move the operator, and the rest of the expression, to the next line. + if ($tokens[($operator - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($operator - 1), ''); + } + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $operator, true); + $padding = str_repeat(' ', ($tokens[$first]['column'] - 1)); + $phpcsFile->fixer->addContentBefore($operator, $phpcsFile->eolChar.$padding); + } else { + // Move the operator to the start of the next line. + if ($tokens[($operator - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($operator - 1), ''); + } + + $phpcsFile->fixer->addContentBefore($next, $tokens[$operator]['content'].' '); + $phpcsFile->fixer->replaceToken($operator, ''); + } + }//end if + }//end if + }//end foreach + + $phpcsFile->fixer->endChangeset(); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/ControlStructureSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/ControlStructureSpacingSniff.php new file mode 100644 index 00000000..3d29c4ac --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/ControlStructureSpacingSniff.php @@ -0,0 +1,192 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures\ControlStructureSpacingSniff as PSR2Spacing; +use PHP_CodeSniffer\Util\Tokens; + +class ControlStructureSpacingSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_WHILE, + T_FOREACH, + T_FOR, + T_SWITCH, + T_ELSE, + T_ELSEIF, + T_CATCH, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + ) { + return; + } + + $parenOpener = $tokens[$stackPtr]['parenthesis_opener']; + $parenCloser = $tokens[$stackPtr]['parenthesis_closer']; + + if ($tokens[$parenOpener]['line'] === $tokens[$parenCloser]['line']) { + // Conditions are all on the same line, so follow PSR2. + $sniff = new PSR2Spacing(); + return $sniff->process($phpcsFile, $stackPtr); + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($parenOpener + 1), $parenCloser, true); + if ($next === false) { + // No conditions; parse error. + return; + } + + // Check the first expression. + if ($tokens[$next]['line'] !== ($tokens[$parenOpener]['line'] + 1)) { + $error = 'The first expression of a multi-line control structure must be on the line after the opening parenthesis'; + $fix = $phpcsFile->addFixableError($error, $next, 'FirstExpressionLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($parenOpener); + } + } + + // Check the indent of each line. + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $requiredIndent = ($tokens[$first]['column'] + $this->indent - 1); + for ($i = $parenOpener; $i < $parenCloser; $i++) { + if ($tokens[$i]['column'] !== 1 + || $tokens[($i + 1)]['line'] > $tokens[$i]['line'] + || isset(Tokens::$commentTokens[$tokens[$i]['code']]) === true + ) { + continue; + } + + if (($i + 1) === $parenCloser) { + break; + } + + // Leave indentation inside multi-line strings. + if (isset(Tokens::$textStringTokens[$tokens[$i]['code']]) === true + || isset(Tokens::$heredocTokens[$tokens[$i]['code']]) === true + ) { + continue; + } + + if ($tokens[$i]['code'] !== T_WHITESPACE) { + $foundIndent = 0; + } else { + $foundIndent = $tokens[$i]['length']; + } + + if ($foundIndent < $requiredIndent) { + $error = 'Each line in a multi-line control structure must be indented at least once; expected at least %s spaces, but found %s'; + $data = [ + $requiredIndent, + $foundIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $i, 'LineIndent', $data); + if ($fix === true) { + $padding = str_repeat(' ', $requiredIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $padding); + } else { + $phpcsFile->fixer->replaceToken($i, $padding); + } + } + } + }//end for + + // Check the closing parenthesis. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($parenCloser - 1), $parenOpener, true); + if ($tokens[$parenCloser]['line'] !== ($tokens[$prev]['line'] + 1)) { + $error = 'The closing parenthesis of a multi-line control structure must be on the line after the last expression'; + $fix = $phpcsFile->addFixableError($error, $parenCloser, 'CloseParenthesisLine'); + if ($fix === true) { + if ($tokens[$parenCloser]['line'] === $tokens[$prev]['line']) { + $phpcsFile->fixer->addNewlineBefore($parenCloser); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $parenCloser; $i++) { + // Maintain existing newline. + if ($tokens[$i]['line'] === $tokens[$prev]['line']) { + continue; + } + + // Maintain existing indent. + if ($tokens[$i]['line'] === $tokens[$parenCloser]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + if ($tokens[$parenCloser]['line'] !== $tokens[$prev]['line']) { + $requiredIndent = ($tokens[$first]['column'] - 1); + $foundIndent = ($tokens[$parenCloser]['column'] - 1); + if ($foundIndent !== $requiredIndent) { + $error = 'The closing parenthesis of a multi-line control structure must be indented to the same level as start of the control structure; expected %s spaces but found %s'; + $data = [ + $requiredIndent, + $foundIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $parenCloser, 'CloseParenthesisIndent', $data); + if ($fix === true) { + $padding = str_repeat(' ', $requiredIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($parenCloser, $padding); + } else { + $phpcsFile->fixer->replaceToken(($parenCloser - 1), $padding); + } + } + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/DeclareStatementSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/DeclareStatementSniff.php new file mode 100644 index 00000000..67776c33 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/DeclareStatementSniff.php @@ -0,0 +1,256 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DeclareStatementSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DECLARE]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Allow a byte-order mark. + $tokens = $phpcsFile->getTokens(); + + // There should be no space between declare keyword and opening parenthesis. + $parenthesis = ($stackPtr + 1); + if ($tokens[($stackPtr + 1)]['type'] !== 'T_OPEN_PARENTHESIS') { + $parenthesis = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $error = 'Expected no space between declare keyword and opening parenthesis in a declare statement'; + + if ($tokens[$parenthesis]['type'] === 'T_OPEN_PARENTHESIS') { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceFoundAfterDeclare'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + } else { + $phpcsFile->addError($error, $parenthesis, 'SpaceFoundAfterDeclare'); + $parenthesis = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($parenthesis + 1)); + } + } + + // There should be no space between open parenthesis and the directive. + $string = $phpcsFile->findNext(T_WHITESPACE, ($parenthesis + 1), null, true); + if ($parenthesis !== false) { + if ($tokens[($parenthesis + 1)]['type'] !== 'T_STRING') { + $error = 'Expected no space between opening parenthesis and directive in a declare statement'; + + if ($tokens[$string]['type'] === 'T_STRING') { + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'SpaceFoundBeforeDirective'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenthesis + 1), ''); + } + } else { + $phpcsFile->addError($error, $string, 'SpaceFoundBeforeDirective'); + $string = $phpcsFile->findNext(T_STRING, ($string + 1)); + } + } + } + + // There should be no space between directive and the equal sign. + $equals = $phpcsFile->findNext(T_WHITESPACE, ($string + 1), null, true); + if ($string !== false) { + // The directive must be in lowercase. + if ($tokens[$string]['content'] !== strtolower($tokens[$string]['content'])) { + $error = 'The directive of a declare statement must be in lowercase'; + $fix = $phpcsFile->addFixableError($error, $string, 'DirectiveNotLowercase'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($string, strtolower($tokens[$string]['content'])); + } + } + + if ($tokens[($string + 1)]['type'] !== 'T_EQUAL') { + $error = 'Expected no space between directive and the equals sign in a declare statement'; + + if ($tokens[$equals]['type'] === 'T_EQUAL') { + $fix = $phpcsFile->addFixableError($error, $equals, 'SpaceFoundAfterDirective'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($string + 1), ''); + } + } else { + $phpcsFile->addError($error, $equals, 'SpaceFoundAfterDirective'); + $equals = $phpcsFile->findNext(T_EQUAL, ($equals + 1)); + } + } + }//end if + + // There should be no space between equal sign and directive value. + $value = $phpcsFile->findNext(T_WHITESPACE, ($equals + 1), null, true); + if ($equals !== false) { + if ($tokens[($equals + 1)]['type'] !== 'T_LNUMBER') { + $error = 'Expected no space between equal sign and the directive value in a declare statement'; + + if ($tokens[$value]['type'] === 'T_LNUMBER') { + $fix = $phpcsFile->addFixableError($error, $value, 'SpaceFoundBeforeDirectiveValue'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($equals + 1), ''); + } + } else { + $phpcsFile->addError($error, $value, 'SpaceFoundBeforeDirectiveValue'); + $value = $phpcsFile->findNext(T_LNUMBER, ($value + 1)); + } + } + } + + $parenthesis = $phpcsFile->findNext(T_WHITESPACE, ($value + 1), null, true); + if ($value !== false) { + if ($tokens[($value + 1)]['type'] !== 'T_CLOSE_PARENTHESIS') { + $error = 'Expected no space between the directive value and closing parenthesis in a declare statement'; + + if ($tokens[$parenthesis]['type'] === 'T_CLOSE_PARENTHESIS') { + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'SpaceFoundAfterDirectiveValue'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($value + 1), ''); + } + } else { + $phpcsFile->addError($error, $parenthesis, 'SpaceFoundAfterDirectiveValue'); + $parenthesis = $phpcsFile->findNext(T_CLOSE_PARENTHESIS, ($parenthesis + 1)); + } + } + } + + // Check for semicolon. + $curlyBracket = false; + if ($tokens[($parenthesis + 1)]['type'] !== 'T_SEMICOLON') { + $token = $phpcsFile->findNext(T_WHITESPACE, ($parenthesis + 1), null, true); + + if ($tokens[$token]['type'] === 'T_OPEN_CURLY_BRACKET') { + // Block declaration. + $curlyBracket = $token; + } else if ($tokens[$token]['type'] === 'T_SEMICOLON') { + $error = 'Expected no space between the closing parenthesis and the semicolon in a declare statement'; + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'SpaceFoundBeforeSemicolon'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenthesis + 1), ''); + } + } else if ($tokens[$token]['type'] === 'T_CLOSE_TAG') { + if ($tokens[($parenthesis)]['line'] !== $tokens[$token]['line']) { + // Close tag must be on the same line.. + $error = 'The close tag must be on the same line as the declare statement'; + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'CloseTagOnNewLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenthesis + 1), ' '); + } + } + } else { + $error = 'Expected no space between the closing parenthesis and the semicolon in a declare statement'; + $phpcsFile->addError($error, $parenthesis, 'SpaceFoundBeforeSemicolon'); + + // See if there is a semicolon or curly bracket after this token. + $token = $phpcsFile->findNext([T_WHITESPACE, T_COMMENT], ($token + 1), null, true); + if ($tokens[$token]['type'] === 'T_OPEN_CURLY_BRACKET') { + $curlyBracket = $token; + } + }//end if + }//end if + + if ($curlyBracket !== false) { + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($curlyBracket - 1), null, true); + $error = 'Expected one space between closing parenthesis and opening curly bracket in a declare statement'; + + // The opening curly bracket must on the same line with a single space between closing bracket. + if ($tokens[$prevToken]['type'] !== 'T_CLOSE_PARENTHESIS') { + $phpcsFile->addError($error, $curlyBracket, 'ExtraSpaceFoundAfterBracket'); + } else if ($phpcsFile->getTokensAsString(($prevToken + 1), ($curlyBracket - $prevToken - 1)) !== ' ') { + $fix = $phpcsFile->addFixableError($error, $curlyBracket, 'ExtraSpaceFoundAfterBracket'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($prevToken + 1), ' '); + $nextToken = ($prevToken + 2); + while ($nextToken !== $curlyBracket) { + $phpcsFile->fixer->replaceToken($nextToken, ''); + $nextToken++; + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + $closeCurlyBracket = $tokens[$curlyBracket]['bracket_closer']; + + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($closeCurlyBracket - 1), null, true); + $nextToken = $phpcsFile->findNext([T_WHITESPACE, T_COMMENT], ($closeCurlyBracket + 1), null, true); + $line = $tokens[$closeCurlyBracket]['line']; + + // The closing curly bracket must be on a new line. + if ($tokens[$prevToken]['line'] === $line || $tokens[$nextToken]['line'] === $line) { + if ($tokens[$prevToken]['line'] === $line) { + $error = 'The closing curly bracket of a declare statement must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $prevToken, 'CurlyBracketNotOnNewLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($prevToken); + } + } + }//end if + + // Closing curly bracket must align with the declare keyword. + if ($tokens[$stackPtr]['column'] !== $tokens[$closeCurlyBracket]['column']) { + $error = 'The closing curly bracket of a declare statements must be aligned with the declare keyword'; + + $fix = $phpcsFile->addFixableError($error, $closeCurlyBracket, 'CloseBracketNotAligned'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closeCurlyBracket - 1), str_repeat(' ', ($tokens[$stackPtr]['column'] - 1))); + } + } + + // The open curly bracket must be the last code on the line. + $token = $phpcsFile->findNext(Tokens::$emptyTokens, ($curlyBracket + 1), null, true); + if ($tokens[$curlyBracket]['line'] === $tokens[$token]['line']) { + $error = 'The open curly bracket of a declare statement must be the last code on the line'; + $fix = $phpcsFile->addFixableError($error, $token, 'CodeFoundAfterCurlyBracket'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($token - 1), null, true); + + for ($i = ($prevToken + 1); $i < $token; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewLineBefore($token); + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/FileHeaderSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/FileHeaderSniff.php new file mode 100644 index 00000000..8a8255cf --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/FileHeaderSniff.php @@ -0,0 +1,428 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FileHeaderSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current + * token in the stack. + * + * @return int|null + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $possibleHeaders = []; + + $searchFor = Tokens::$ooScopeTokens; + $searchFor[T_OPEN_TAG] = T_OPEN_TAG; + + $openTag = $stackPtr; + do { + $headerLines = $this->getHeaderLines($phpcsFile, $openTag); + if (empty($headerLines) === true && $openTag === $stackPtr) { + // No content in the file. + return; + } + + $possibleHeaders[$openTag] = $headerLines; + if (count($headerLines) > 1) { + break; + } + + $next = $phpcsFile->findNext($searchFor, ($openTag + 1)); + if (isset(Tokens::$ooScopeTokens[$tokens[$next]['code']]) === true) { + // Once we find an OO token, the file content has + // definitely started. + break; + } + + $openTag = $next; + } while ($openTag !== false); + + if ($openTag === false) { + // We never found a proper file header. + // If the file has multiple PHP open tags, we know + // that it must be a mix of PHP and HTML (or similar) + // so the header rules do not apply. + if (count($possibleHeaders) > 1) { + return $phpcsFile->numTokens; + } + + // There is only one possible header. + // If it is the first content in the file, it technically + // serves as the file header, and the open tag needs to + // have a newline after it. Otherwise, ignore it. + if ($stackPtr > 0) { + return $phpcsFile->numTokens; + } + + $openTag = $stackPtr; + } else if (count($possibleHeaders) > 1) { + // There are other PHP blocks before the file header. + $error = 'The file header must be the first content in the file'; + $phpcsFile->addError($error, $openTag, 'HeaderPosition'); + } else { + // The first possible header was the file header block, + // so make sure it is the first content in the file. + if ($openTag !== 0) { + // Allow for hashbang lines. + $hashbang = false; + if ($tokens[($openTag - 1)]['code'] === T_INLINE_HTML) { + $content = trim($tokens[($openTag - 1)]['content']); + if (substr($content, 0, 2) === '#!') { + $hashbang = true; + } + } + + if ($hashbang === false) { + $error = 'The file header must be the first content in the file'; + $phpcsFile->addError($error, $openTag, 'HeaderPosition'); + } + } + }//end if + + $this->processHeaderLines($phpcsFile, $possibleHeaders[$openTag]); + + return $phpcsFile->numTokens; + + }//end process() + + + /** + * Gather information about the statements inside a possible file header. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current + * token in the stack. + * + * @return array + */ + public function getHeaderLines(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next === false) { + return []; + } + + $headerLines = []; + $headerLines[] = [ + 'type' => 'tag', + 'start' => $stackPtr, + 'end' => $stackPtr, + ]; + + $foundDocblock = false; + + $commentOpeners = Tokens::$scopeOpeners; + unset($commentOpeners[T_NAMESPACE]); + unset($commentOpeners[T_DECLARE]); + unset($commentOpeners[T_USE]); + unset($commentOpeners[T_IF]); + unset($commentOpeners[T_WHILE]); + unset($commentOpeners[T_FOR]); + unset($commentOpeners[T_FOREACH]); + unset($commentOpeners[T_DO]); + unset($commentOpeners[T_TRY]); + + do { + switch ($tokens[$next]['code']) { + case T_DOC_COMMENT_OPEN_TAG: + if ($foundDocblock === true) { + // Found a second docblock, so start of code. + break(2); + } + + // Make sure this is not a code-level docblock. + $end = $tokens[$next]['comment_closer']; + for ($docToken = ($end + 1); $docToken < $phpcsFile->numTokens; $docToken++) { + if (isset(Tokens::$emptyTokens[$tokens[$docToken]['code']]) === true) { + continue; + } + + if ($tokens[$docToken]['code'] === T_ATTRIBUTE + && isset($tokens[$docToken]['attribute_closer']) === true + ) { + $docToken = $tokens[$docToken]['attribute_closer']; + continue; + } + + break; + } + + if ($docToken === $phpcsFile->numTokens) { + $docToken--; + } + + if (isset($commentOpeners[$tokens[$docToken]['code']]) === false + && isset(Tokens::$methodPrefixes[$tokens[$docToken]['code']]) === false + ) { + // Check for an @var annotation. + $annotation = false; + for ($i = $next; $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_TAG + && strtolower($tokens[$i]['content']) === '@var' + ) { + $annotation = true; + break; + } + } + + if ($annotation === false) { + $foundDocblock = true; + $headerLines[] = [ + 'type' => 'docblock', + 'start' => $next, + 'end' => $end, + ]; + } + }//end if + + $next = $end; + break; + case T_DECLARE: + case T_NAMESPACE: + if (isset($tokens[$next]['scope_opener']) === true) { + // If this statement is using bracketed syntax, it doesn't + // apply to the entire files and so is not part of header. + // The header has now ended and the main code block begins. + break(2); + } + + $end = $phpcsFile->findEndOfStatement($next); + + $headerLines[] = [ + 'type' => substr(strtolower($tokens[$next]['type']), 2), + 'start' => $next, + 'end' => $end, + ]; + + $next = $end; + break; + case T_USE: + $type = 'use'; + $useType = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + if ($useType !== false && $tokens[$useType]['code'] === T_STRING) { + $content = strtolower($tokens[$useType]['content']); + if ($content === 'function' || $content === 'const') { + $type .= ' '.$content; + } + } + + $end = $phpcsFile->findEndOfStatement($next); + + $headerLines[] = [ + 'type' => $type, + 'start' => $next, + 'end' => $end, + ]; + + $next = $end; + break; + default: + // Skip comments as PSR-12 doesn't say if these are allowed or not. + if (isset(Tokens::$commentTokens[$tokens[$next]['code']]) === true) { + $next = $phpcsFile->findNext(Tokens::$commentTokens, ($next + 1), null, true); + if ($next === false) { + // We reached the end of the file. + break(2); + } + + $next--; + break; + } + + // We found the start of the main code block. + break(2); + }//end switch + + $next = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true); + } while ($next !== false); + + return $headerLines; + + }//end getHeaderLines() + + + /** + * Check the spacing and grouping of the statements inside each header block. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $headerLines Header information, as sourced + * from getHeaderLines(). + * + * @return int|null + */ + public function processHeaderLines(File $phpcsFile, $headerLines) + { + $tokens = $phpcsFile->getTokens(); + + $found = []; + + foreach ($headerLines as $i => $line) { + if (isset($headerLines[($i + 1)]) === false + || $headerLines[($i + 1)]['type'] !== $line['type'] + ) { + // We're at the end of the current header block. + // Make sure there is a single blank line after + // this block. + $next = $phpcsFile->findNext(T_WHITESPACE, ($line['end'] + 1), null, true); + if ($next !== false && $tokens[$next]['line'] !== ($tokens[$line['end']]['line'] + 2)) { + $error = 'Header blocks must be separated by a single blank line'; + $fix = $phpcsFile->addFixableError($error, $line['end'], 'SpacingAfterBlock'); + if ($fix === true) { + if ($tokens[$next]['line'] === $tokens[$line['end']]['line']) { + $phpcsFile->fixer->addContentBefore($next, $phpcsFile->eolChar.$phpcsFile->eolChar); + } else if ($tokens[$next]['line'] === ($tokens[$line['end']]['line'] + 1)) { + $phpcsFile->fixer->addNewline($line['end']); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($line['end'] + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === ($tokens[$line['end']]['line'] + 2)) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + // Make sure we haven't seen this next block before. + if (isset($headerLines[($i + 1)]) === true + && isset($found[$headerLines[($i + 1)]['type']]) === true + ) { + $error = 'Similar statements must be grouped together inside header blocks; '; + $error .= 'the first "%s" statement was found on line %s'; + $data = [ + $headerLines[($i + 1)]['type'], + $tokens[$found[$headerLines[($i + 1)]['type']]['start']]['line'], + ]; + $phpcsFile->addError($error, $headerLines[($i + 1)]['start'], 'IncorrectGrouping', $data); + } + } else if ($headerLines[($i + 1)]['type'] === $line['type']) { + // Still in the same block, so make sure there is no + // blank line after this statement. + $next = $phpcsFile->findNext(T_WHITESPACE, ($line['end'] + 1), null, true); + if ($tokens[$next]['line'] > ($tokens[$line['end']]['line'] + 1)) { + $error = 'Header blocks must not contain blank lines'; + $fix = $phpcsFile->addFixableError($error, $line['end'], 'SpacingInsideBlock'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($line['end'] + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$line['end']]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + if (isset($found[$line['type']]) === false) { + $found[$line['type']] = $line; + } + }//end foreach + + /* + Next, check that the order of the header blocks + is correct: + Opening php tag. + File-level docblock. + One or more declare statements. + The namespace declaration of the file. + One or more class-based use import statements. + One or more function-based use import statements. + One or more constant-based use import statements. + */ + + $blockOrder = [ + 'tag' => 'opening PHP tag', + 'docblock' => 'file-level docblock', + 'declare' => 'declare statements', + 'namespace' => 'namespace declaration', + 'use' => 'class-based use imports', + 'use function' => 'function-based use imports', + 'use const' => 'constant-based use imports', + ]; + + foreach (array_keys($found) as $type) { + if ($type === 'tag') { + // The opening tag is always in the correct spot. + continue; + } + + do { + $orderedType = next($blockOrder); + } while ($orderedType !== false && key($blockOrder) !== $type); + + if ($orderedType === false) { + // We didn't find the block type in the rest of the + // ordered array, so it is out of place. + // Error and reset the array to the correct position + // so we can check the next block. + reset($blockOrder); + $prevValidType = 'tag'; + do { + $orderedType = next($blockOrder); + if (isset($found[key($blockOrder)]) === true + && key($blockOrder) !== $type + ) { + $prevValidType = key($blockOrder); + } + } while ($orderedType !== false && key($blockOrder) !== $type); + + $error = 'The %s must follow the %s in the file header'; + $data = [ + $blockOrder[$type], + $blockOrder[$prevValidType], + ]; + $phpcsFile->addError($error, $found[$type]['start'], 'IncorrectOrder', $data); + }//end if + }//end foreach + + }//end processHeaderLines() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/ImportStatementSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/ImportStatementSniff.php new file mode 100644 index 00000000..176aef00 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/ImportStatementSniff.php @@ -0,0 +1,77 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ImportStatementSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_USE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure this is not a closure USE group. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + return; + } + + if ($phpcsFile->hasCondition($stackPtr, Tokens::$ooScopeTokens) === true) { + // This rule only applies to import statements. + return; + } + + if ($tokens[$next]['code'] === T_STRING + && (strtolower($tokens[$next]['content']) === 'function' + || strtolower($tokens[$next]['content']) === 'const') + ) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + } + + if ($tokens[$next]['code'] !== T_NS_SEPARATOR) { + return; + } + + $error = 'Import statements must not begin with a leading backslash'; + $fix = $phpcsFile->addFixableError($error, $next, 'LeadingSlash'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken($next, ''); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/OpenTagSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/OpenTagSniff.php new file mode 100644 index 00000000..4371bee1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/OpenTagSniff.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OpenTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current + * token in the stack. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($stackPtr !== 0) { + // This rule only applies if the open tag is on the first line of the file. + return $phpcsFile->numTokens; + } + + $next = $phpcsFile->findNext(T_INLINE_HTML, 0); + if ($next !== false) { + // This rule only applies to PHP-only files. + return $phpcsFile->numTokens; + } + + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next === false) { + // Empty file. + return; + } + + if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Opening PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAlone'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($stackPtr); + } + } + + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/NullableTypeDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/NullableTypeDeclarationSniff.php new file mode 100644 index 00000000..8d907343 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/NullableTypeDeclarationSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2018 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class NullableTypeDeclarationSniff implements Sniff +{ + + /** + * An array of valid tokens after `T_NULLABLE` occurrences. + * + * @var array + */ + private $validTokens = [ + T_STRING => true, + T_NS_SEPARATOR => true, + T_CALLABLE => true, + T_SELF => true, + T_PARENT => true, + T_STATIC => true, + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_NULLABLE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $nextNonEmptyPtr = $phpcsFile->findNext([T_WHITESPACE], ($stackPtr + 1), null, true); + if ($nextNonEmptyPtr === false) { + // Parse error or live coding. + return; + } + + $tokens = $phpcsFile->getTokens(); + $nextNonEmptyCode = $tokens[$nextNonEmptyPtr]['code']; + $validTokenFound = isset($this->validTokens[$nextNonEmptyCode]); + + if ($validTokenFound === true && $nextNonEmptyPtr === ($stackPtr + 1)) { + // Valid structure. + return; + } + + $error = 'There must not be a space between the question mark and the type in nullable type declarations'; + + if ($validTokenFound === true) { + // No other tokens then whitespace tokens found; fixable. + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'WhitespaceFound'); + if ($fix === true) { + for ($i = ($stackPtr + 1); $i < $nextNonEmptyPtr; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + return; + } + + // Non-whitespace tokens found; trigger error but don't fix. + $phpcsFile->addError($error, $stackPtr, 'UnexpectedCharactersFound'); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php new file mode 100644 index 00000000..14d91e2e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php @@ -0,0 +1,110 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ReturnTypeDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + T_FN, + ]; + + }//end register() + + + /** + * Processes this test when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + || $tokens[$stackPtr]['parenthesis_opener'] === null + || $tokens[$stackPtr]['parenthesis_closer'] === null + ) { + return; + } + + $methodProperties = $phpcsFile->getMethodProperties($stackPtr); + if ($methodProperties['return_type'] === '') { + return; + } + + $returnType = $methodProperties['return_type_token']; + if ($methodProperties['nullable_return_type'] === true) { + $returnType = $phpcsFile->findPrevious(T_NULLABLE, ($returnType - 1)); + } + + if ($tokens[($returnType - 1)]['code'] !== T_WHITESPACE + || $tokens[($returnType - 1)]['content'] !== ' ' + || $tokens[($returnType - 2)]['code'] !== T_COLON + ) { + $error = 'There must be a single space between the colon and type in a return type declaration'; + if ($tokens[($returnType - 1)]['code'] === T_WHITESPACE + && $tokens[($returnType - 2)]['code'] === T_COLON + ) { + $fix = $phpcsFile->addFixableError($error, $returnType, 'SpaceBeforeReturnType'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($returnType - 1), ' '); + } + } else if ($tokens[($returnType - 1)]['code'] === T_COLON) { + $fix = $phpcsFile->addFixableError($error, $returnType, 'SpaceBeforeReturnType'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($returnType, ' '); + } + } else { + $phpcsFile->addError($error, $returnType, 'SpaceBeforeReturnType'); + } + } + + $colon = $phpcsFile->findPrevious(T_COLON, $returnType); + if ($tokens[($colon - 1)]['code'] !== T_CLOSE_PARENTHESIS) { + $error = 'There must not be a space before the colon in a return type declaration'; + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($colon - 1), null, true); + if ($tokens[$prev]['code'] === T_CLOSE_PARENTHESIS) { + $fix = $phpcsFile->addFixableError($error, $colon, 'SpaceBeforeColon'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($prev + 1); $x < $colon; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError($error, $colon, 'SpaceBeforeColon'); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Keywords/ShortFormTypeKeywordsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Keywords/ShortFormTypeKeywordsSniff.php new file mode 100644 index 00000000..adf04d90 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Keywords/ShortFormTypeKeywordsSniff.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Keywords; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ShortFormTypeKeywordsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_BOOL_CAST, + T_INT_CAST, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $typecast = str_replace(' ', '', $tokens[$stackPtr]['content']); + $typecast = str_replace("\t", '', $typecast); + $typecast = trim($typecast, '()'); + $typecastLc = strtolower($typecast); + + if (($tokens[$stackPtr]['code'] === T_BOOL_CAST + && $typecastLc === 'bool') + || ($tokens[$stackPtr]['code'] === T_INT_CAST + && $typecastLc === 'int') + ) { + return; + } + + $error = 'Short form type keywords must be used. Found: %s'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'LongFound', $data); + if ($fix === true) { + if ($tokens[$stackPtr]['code'] === T_BOOL_CAST) { + $replacement = str_replace($typecast, 'bool', $tokens[$stackPtr]['content']); + } else { + $replacement = str_replace($typecast, 'int', $tokens[$stackPtr]['content']); + } + + $phpcsFile->fixer->replaceToken($stackPtr, $replacement); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Namespaces/CompoundNamespaceDepthSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Namespaces/CompoundNamespaceDepthSniff.php new file mode 100644 index 00000000..725fbde3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Namespaces/CompoundNamespaceDepthSniff.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Namespaces; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class CompoundNamespaceDepthSniff implements Sniff +{ + + /** + * The max depth for compound namespaces. + * + * @var integer + */ + public $maxDepth = 2; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_USE_GROUP]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->maxDepth = (int) $this->maxDepth; + + $tokens = $phpcsFile->getTokens(); + + $end = $phpcsFile->findNext(T_CLOSE_USE_GROUP, ($stackPtr + 1)); + if ($end === false) { + return; + } + + $depth = 1; + for ($i = ($stackPtr + 1); $i <= $end; $i++) { + if ($tokens[$i]['code'] === T_NS_SEPARATOR) { + $depth++; + continue; + } + + if ($i === $end || $tokens[$i]['code'] === T_COMMA) { + // End of a namespace. + if ($depth > $this->maxDepth) { + $error = 'Compound namespaces cannot have a depth more than %s'; + $data = [$this->maxDepth]; + $phpcsFile->addError($error, $i, 'TooDeep', $data); + } + + $depth = 1; + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Operators/OperatorSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Operators/OperatorSpacingSniff.php new file mode 100644 index 00000000..8757e05a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Operators/OperatorSpacingSniff.php @@ -0,0 +1,112 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Operators; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\OperatorSpacingSniff as SquizOperatorSpacingSniff; +use PHP_CodeSniffer\Util\Tokens; + +class OperatorSpacingSniff extends SquizOperatorSpacingSniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + parent::register(); + + $targets = Tokens::$comparisonTokens; + $targets += Tokens::$operators; + $targets += Tokens::$assignmentTokens; + $targets += Tokens::$booleanOperators; + $targets[] = T_INLINE_THEN; + $targets[] = T_INLINE_ELSE; + $targets[] = T_STRING_CONCAT; + $targets[] = T_INSTANCEOF; + + return $targets; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($this->isOperator($phpcsFile, $stackPtr) === false) { + return; + } + + $operator = $tokens[$stackPtr]['content']; + + $checkBefore = true; + $checkAfter = true; + + // Skip short ternary. + if ($tokens[($stackPtr)]['code'] === T_INLINE_ELSE + && $tokens[($stackPtr - 1)]['code'] === T_INLINE_THEN + ) { + $checkBefore = false; + } + + // Skip operator with comment on previous line. + if ($tokens[($stackPtr - 1)]['code'] === T_COMMENT + && $tokens[($stackPtr - 1)]['line'] < $tokens[$stackPtr]['line'] + ) { + $checkBefore = false; + } + + if (isset($tokens[($stackPtr + 1)]) === true) { + // Skip short ternary. + if ($tokens[$stackPtr]['code'] === T_INLINE_THEN + && $tokens[($stackPtr + 1)]['code'] === T_INLINE_ELSE + ) { + $checkAfter = false; + } + } else { + // Skip partial files. + $checkAfter = false; + } + + if ($checkBefore === true && $tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected at least 1 space before "%s"; 0 found'; + $data = [$operator]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBefore', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + } + + if ($checkAfter === true && $tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected at least 1 space after "%s"; 0 found'; + $data = [$operator]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfter', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Properties/ConstantVisibilitySniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Properties/ConstantVisibilitySniff.php new file mode 100644 index 00000000..7f63d1e8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Properties/ConstantVisibilitySniff.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Properties; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ConstantVisibilitySniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CONST]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure this is a class constant. + if ($phpcsFile->hasCondition($stackPtr, Tokens::$ooScopeTokens) === false) { + return; + } + + $ignore = Tokens::$emptyTokens; + $ignore[] = T_FINAL; + + $prev = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); + if (isset(Tokens::$scopeModifiers[$tokens[$prev]['code']]) === true) { + return; + } + + $error = 'Visibility must be declared on all constants if your project supports PHP 7.1 or later'; + $phpcsFile->addWarning($error, $stackPtr, 'NotFound'); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Traits/UseDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Traits/UseDeclarationSniff.php new file mode 100644 index 00000000..113e8b9f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Traits/UseDeclarationSniff.php @@ -0,0 +1,700 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Traits; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UseDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_USE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Needs to be a use statement directly inside a class. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + if (isset(Tokens::$ooScopeTokens[current($conditions)]) === false) { + return; + } + + $ooToken = key($conditions); + $opener = $tokens[$ooToken]['scope_opener']; + + // Figure out where all the use statements are. + $useTokens = [$stackPtr]; + for ($i = ($stackPtr + 1); $i < $tokens[$ooToken]['scope_closer']; $i++) { + if ($tokens[$i]['code'] === T_USE) { + $useTokens[] = $i; + } + + if (isset($tokens[$i]['scope_closer']) === true) { + $i = $tokens[$i]['scope_closer']; + } + } + + $numUseTokens = count($useTokens); + foreach ($useTokens as $usePos => $useToken) { + if ($usePos === 0) { + /* + This is the first use statement. + */ + + // The first non-comment line must be the use line. + $lastValidContent = $useToken; + for ($i = ($useToken - 1); $i > $opener; $i--) { + if ($tokens[$i]['code'] === T_WHITESPACE + && ($tokens[($i - 1)]['line'] === $tokens[$i]['line'] + || $tokens[($i + 1)]['line'] === $tokens[$i]['line']) + ) { + continue; + } + + if (isset(Tokens::$commentTokens[$tokens[$i]['code']]) === true) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + // Skip past the comment. + $i = $tokens[$i]['comment_opener']; + } + + $lastValidContent = $i; + + continue; + } + + break; + }//end for + + if ($tokens[$lastValidContent]['line'] !== ($tokens[$opener]['line'] + 1)) { + $error = 'The first trait import statement must be declared on the first non-comment line after the %s opening brace'; + $data = [strtolower($tokens[$ooToken]['content'])]; + + // Figure out if we can fix this error. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($useToken - 1), ($opener - 1), true); + if ($tokens[$prev]['line'] === $tokens[$opener]['line']) { + $fix = $phpcsFile->addFixableError($error, $useToken, 'UseAfterBrace', $data); + if ($fix === true) { + // We know that the USE statements is the first non-comment content + // in the class, so we just need to remove blank lines. + $phpcsFile->fixer->beginChangeset(); + for ($i = ($useToken - 1); $i > $opener; $i--) { + if ($tokens[$i]['line'] === $tokens[$opener]['line']) { + break; + } + + if ($tokens[$i]['line'] === $tokens[$useToken]['line']) { + continue; + } + + if ($tokens[$i]['code'] === T_WHITESPACE + && $tokens[($i - 1)]['line'] !== $tokens[$i]['line'] + && $tokens[($i + 1)]['line'] !== $tokens[$i]['line'] + ) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + if (isset(Tokens::$commentTokens[$tokens[$i]['code']]) === true) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + // Skip past the comment. + $i = $tokens[$i]['comment_opener']; + } + + $lastValidContent = $i; + } + }//end for + + $phpcsFile->fixer->endChangeset(); + }//end if + } else { + $phpcsFile->addError($error, $useToken, 'UseAfterBrace', $data); + }//end if + }//end if + } else { + // Make sure this use statement is not on the same line as the previous one. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($useToken - 1), null, true); + if ($prev !== false && $tokens[$prev]['line'] === $tokens[$useToken]['line']) { + $error = 'Each imported trait must be on its own line'; + $prevNonWs = $phpcsFile->findPrevious(T_WHITESPACE, ($useToken - 1), null, true); + if ($prevNonWs !== $prev) { + $phpcsFile->addError($error, $useToken, 'SpacingBeforeImport'); + } else { + $fix = $phpcsFile->addFixableError($error, $useToken, 'SpacingBeforeImport'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($useToken - 1); $x > $prev; $x--) { + if ($tokens[$x]['line'] === $tokens[$useToken]['line'] + ) { + // Preserve indent. + continue; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewline($prev); + if ($tokens[$prev]['line'] === $tokens[$useToken]['line']) { + if ($tokens[($useToken - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($useToken - 1), ''); + } + + $padding = str_repeat(' ', ($tokens[$useTokens[0]]['column'] - 1)); + $phpcsFile->fixer->addContent($prev, $padding); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + }//end if + }//end if + + // Check the formatting of the statement. + if (isset($tokens[$useToken]['scope_opener']) === true) { + $this->processUseGroup($phpcsFile, $useToken); + $end = $tokens[$useToken]['scope_closer']; + } else { + $this->processUseStatement($phpcsFile, $useToken); + $end = $phpcsFile->findNext(T_SEMICOLON, ($useToken + 1)); + if ($end === false) { + // Syntax error. + return; + } + } + + if ($usePos === ($numUseTokens - 1)) { + /* + This is the last use statement. + */ + + $next = $phpcsFile->findNext(T_WHITESPACE, ($end + 1), null, true); + if ($next === $tokens[$ooToken]['scope_closer']) { + // Last content in the class. + $closer = $tokens[$ooToken]['scope_closer']; + if ($tokens[$closer]['line'] > ($tokens[$end]['line'] + 1)) { + $error = 'There must be no blank line after the last trait import statement at the bottom of a %s'; + $data = [strtolower($tokens[$ooToken]['content'])]; + $fix = $phpcsFile->addFixableError($error, $end, 'BlankLineAfterLastUse', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($end + 1); $i < $closer; $i++) { + if ($tokens[$i]['line'] === $tokens[$end]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$closer]['line']) { + // Don't remove indents. + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + } else if ($tokens[$next]['code'] !== T_USE) { + // Comments are allowed on the same line as the use statement, so make sure + // we don't error for those. + for ($next = ($end + 1); $next < $tokens[$ooToken]['scope_closer']; $next++) { + if ($tokens[$next]['code'] === T_WHITESPACE) { + continue; + } + + if (isset(Tokens::$commentTokens[$tokens[$next]['code']]) === true + && $tokens[$next]['line'] === $tokens[$end]['line'] + ) { + continue; + } + + break; + } + + if ($tokens[$next]['line'] <= ($tokens[$end]['line'] + 1)) { + $error = 'There must be a blank line following the last trait import statement'; + $fix = $phpcsFile->addFixableError($error, $end, 'NoBlankLineAfterUse'); + if ($fix === true) { + if ($tokens[$next]['line'] === $tokens[$useToken]['line']) { + $phpcsFile->fixer->addContentBefore($next, $phpcsFile->eolChar.$phpcsFile->eolChar); + } else { + for ($i = ($next - 1); $i > $end; $i--) { + if ($tokens[$i]['line'] !== $tokens[$next]['line']) { + break; + } + } + + $phpcsFile->fixer->addNewlineBefore(($i + 1)); + } + } + } + }//end if + } else { + // Ensure use statements are grouped. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($next !== $useTokens[($usePos + 1)]) { + $error = 'Imported traits must be grouped together'; + $phpcsFile->addError($error, $useTokens[($usePos + 1)], 'NotGrouped'); + } + }//end if + }//end foreach + + return $tokens[$ooToken]['scope_closer']; + + }//end process() + + + /** + * Processes a group use statement. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processUseGroup(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $opener = $tokens[$stackPtr]['scope_opener']; + $closer = $tokens[$stackPtr]['scope_closer']; + + if ($tokens[$opener]['line'] !== $tokens[$stackPtr]['line']) { + $error = 'The opening brace of a trait import statement must be on the same line as the USE keyword'; + // Figure out if we can fix this error. + $canFix = true; + for ($i = ($stackPtr + 1); $i < $opener; $i++) { + if ($tokens[$i]['line'] !== $tokens[($i + 1)]['line'] + && $tokens[$i]['code'] !== T_WHITESPACE + ) { + $canFix = false; + break; + } + } + + if ($canFix === true) { + $fix = $phpcsFile->addFixableError($error, $opener, 'OpenBraceNewLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $opener; $i++) { + if ($tokens[$i]['line'] !== $tokens[($i + 1)]['line']) { + // Everything should have a single space around it. + $phpcsFile->fixer->replaceToken($i, ' '); + } + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError($error, $opener, 'OpenBraceNewLine'); + } + }//end if + + $error = 'Expected 1 space before opening brace in trait import statement; %s found'; + if ($tokens[($opener - 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $opener, 'SpaceBeforeOpeningBrace', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($opener, ' '); + } + } else if ($tokens[($opener - 1)]['content'] !== ' ') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($opener - 1), null, true); + if ($tokens[$prev]['line'] !== $tokens[$opener]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($opener - 1)]['length']; + } + + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $opener, 'SpaceBeforeOpeningBrace', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($opener - 1); $x > $prev; $x--) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContentBefore($opener, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($opener - 1), ' '); + } + } + }//end if + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($opener + 1), ($closer - 1), true); + if ($next !== false && $tokens[$next]['line'] !== ($tokens[$opener]['line'] + 1)) { + $error = 'First trait conflict resolution statement must be on the line after the opening brace'; + $nextNonWs = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), ($closer - 1), true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $opener, 'SpaceAfterOpeningBrace'); + } else { + $fix = $phpcsFile->addFixableError($error, $opener, 'SpaceAfterOpeningBrace'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($opener + 1); $x < $next; $x++) { + if ($tokens[$x]['line'] === $tokens[$next]['line']) { + // Preserve indent. + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewline($opener); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + for ($i = ($stackPtr + 1); $i < $opener; $i++) { + if ($tokens[$i]['code'] !== T_COMMA) { + continue; + } + + if ($tokens[($i - 1)]['code'] === T_WHITESPACE) { + $error = 'Expected no space before comma in trait import statement; %s found'; + $data = [$tokens[($i - 1)]['length']]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($i - 1), ''); + } + } + + $error = 'Expected 1 space after comma in trait import statement; %s found'; + if ($tokens[($i + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterComma', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($i, ' '); + } + } else if ($tokens[($i + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), $opener, true); + if ($tokens[$next]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i + 1)]['length']; + } + + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterComma', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i + 1), ' '); + } + } + }//end if + }//end for + + for ($i = ($opener + 1); $i < $closer; $i++) { + if ($tokens[$i]['code'] === T_INSTEADOF) { + $error = 'Expected 1 space before INSTEADOF in trait import statement; %s found'; + if ($tokens[($i - 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeInsteadof', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($i, ' '); + } + } else if ($tokens[($i - 1)]['content'] !== ' ') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), $opener, true); + if ($tokens[$prev]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i - 1)]['length']; + } + + $data = [$found]; + + $prevNonWs = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), $opener, true); + if ($prevNonWs !== $prev) { + $phpcsFile->addError($error, $i, 'SpaceBeforeInsteadof', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeInsteadof', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i - 1); $x > $prev; $x--) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContentBefore($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i - 1), ' '); + } + } + } + }//end if + + $error = 'Expected 1 space after INSTEADOF in trait import statement; %s found'; + if ($tokens[($i + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterInsteadof', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($i, ' '); + } + } else if ($tokens[($i + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), $closer, true); + if ($tokens[$next]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i + 1)]['length']; + } + + $data = [$found]; + + $nextNonWs = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), $closer, true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $i, 'SpaceAfterInsteadof', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterInsteadof', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i + 1), ' '); + } + } + } + }//end if + }//end if + + if ($tokens[$i]['code'] === T_AS) { + $error = 'Expected 1 space before AS in trait import statement; %s found'; + if ($tokens[($i - 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeAs', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($i, ' '); + } + } else if ($tokens[($i - 1)]['content'] !== ' ') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), $opener, true); + if ($tokens[$prev]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i - 1)]['length']; + } + + $data = [$found]; + + $prevNonWs = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), $opener, true); + if ($prevNonWs !== $prev) { + $phpcsFile->addError($error, $i, 'SpaceBeforeAs', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeAs', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i - 1); $x > $prev; $x--) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContentBefore($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i - 1), ' '); + } + } + } + }//end if + + $error = 'Expected 1 space after AS in trait import statement; %s found'; + if ($tokens[($i + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterAs', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($i, ' '); + } + } else if ($tokens[($i + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), $closer, true); + if ($tokens[$next]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i + 1)]['length']; + } + + $data = [$found]; + + $nextNonWs = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), $closer, true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $i, 'SpaceAfterAs', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterAs', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i + 1), ' '); + } + } + } + }//end if + }//end if + + if ($tokens[$i]['code'] === T_SEMICOLON) { + if ($tokens[($i - 1)]['code'] === T_WHITESPACE) { + $error = 'Expected no space before semicolon in trait import statement; %s found'; + $data = [$tokens[($i - 1)]['length']]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeSemicolon', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($i - 1), ''); + } + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), ($closer - 1), true); + if ($next !== false && $tokens[$next]['line'] === $tokens[$i]['line']) { + $error = 'Each trait conflict resolution statement must be on a line by itself'; + $nextNonWs = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), ($closer - 1), true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $i, 'ConflictSameLine'); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'ConflictSameLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if ($tokens[($i + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($i + 1), ''); + } + + $phpcsFile->fixer->addNewline($i); + $phpcsFile->fixer->endChangeset(); + } + } + } + }//end if + }//end for + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($closer - 1), ($opener + 1), true); + if ($prev !== false && $tokens[$prev]['line'] !== ($tokens[$closer]['line'] - 1)) { + $error = 'Closing brace must be on the line after the last trait conflict resolution statement'; + $prevNonWs = $phpcsFile->findPrevious(T_WHITESPACE, ($closer - 1), ($opener + 1), true); + if ($prevNonWs !== $prev) { + $phpcsFile->addError($error, $closer, 'SpaceBeforeClosingBrace'); + } else { + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceBeforeClosingBrace'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($closer - 1); $x > $prev; $x--) { + if ($tokens[$x]['line'] === $tokens[$closer]['line']) { + // Preserve indent. + continue; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end processUseGroup() + + + /** + * Processes a single use statement. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processUseStatement(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $error = 'Expected 1 space after USE in trait import statement; %s found'; + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterAs', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } else if ($tokens[($stackPtr + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr + 1)]['length']; + } + + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterAs', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($stackPtr + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($stackPtr, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + }//end if + + $next = $phpcsFile->findNext([T_COMMA, T_SEMICOLON], ($stackPtr + 1)); + if ($next !== false && $tokens[$next]['code'] === T_COMMA) { + $error = 'Each imported trait must have its own "use" import statement'; + $fix = $phpcsFile->addFixableError($error, $next, 'MultipleImport'); + if ($fix === true) { + $padding = str_repeat(' ', ($tokens[$stackPtr]['column'] - 1)); + $phpcsFile->fixer->replaceToken($next, ';'.$phpcsFile->eolChar.$padding.'use '); + } + } + + }//end processUseStatement() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc new file mode 100644 index 00000000..e132b54d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc @@ -0,0 +1,84 @@ +bar( + new class implements Bar { + // ... + }, +); + +foo(new class { +}); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc.fixed new file mode 100644 index 00000000..921dcc02 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc.fixed @@ -0,0 +1,86 @@ +bar( + new class implements Bar { + // ... + }, +); + +foo(new class { +}); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.php new file mode 100644 index 00000000..cc162b29 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.php @@ -0,0 +1,71 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class AnonClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 28 => 3, + 30 => 1, + 31 => 4, + 32 => 1, + 33 => 1, + 34 => 1, + 35 => 1, + 36 => 1, + 37 => 3, + 39 => 1, + 40 => 1, + 43 => 3, + 44 => 4, + 45 => 1, + 48 => 1, + 52 => 3, + 53 => 1, + 54 => 1, + 55 => 1, + 56 => 2, + 63 => 1, + 75 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc new file mode 100644 index 00000000..d933ee27 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc @@ -0,0 +1,44 @@ +bar(); +echo (new Foo)->bar(); +echo (new Foo((new Bar)->getBaz()))->bar(); +$foo = (new Foo)::$bar; + +echo (new Foo((new Bar//comment +)->getBaz(new Baz /* comment */)))->bar(); + +$foo = new $bar['a'](); +$foo = new $bar['a']['b'](); +$foo = new $bar['a'][$baz['a']['b']]['b'](); +$foo = new $bar['a'] [$baz['a']/* comment */ ['b']]['b']; + +$a = new self::$transport[$cap_string]; +$renderer = new $this->inline_diff_renderer; +$a = new ${$varHoldingClassName}; + +$class = new $obj?->classname(); +$class = new $obj?->classname; +$class = new ${$obj?->classname}; + +// Issue 3456. +// Anon classes should be skipped, even when there is an attribute between the new and the class keywords. +$anonWithAttribute = new #[SomeAttribute('summary')] class { + public const SOME_STUFF = 'foo'; +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc.fixed new file mode 100644 index 00000000..02e3544f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc.fixed @@ -0,0 +1,44 @@ +bar(); +echo (new Foo())->bar(); +echo (new Foo((new Bar())->getBaz()))->bar(); +$foo = (new Foo())::$bar; + +echo (new Foo((new Bar()//comment +)->getBaz(new Baz() /* comment */)))->bar(); + +$foo = new $bar['a'](); +$foo = new $bar['a']['b'](); +$foo = new $bar['a'][$baz['a']['b']]['b'](); +$foo = new $bar['a'] [$baz['a']/* comment */ ['b']]['b'](); + +$a = new self::$transport[$cap_string](); +$renderer = new $this->inline_diff_renderer(); +$a = new ${$varHoldingClassName}(); + +$class = new $obj?->classname(); +$class = new $obj?->classname(); +$class = new ${$obj?->classname}(); + +// Issue 3456. +// Anon classes should be skipped, even when there is an attribute between the new and the class keywords. +$anonWithAttribute = new #[SomeAttribute('summary')] class { + public const SOME_STUFF = 'foo'; +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.php new file mode 100644 index 00000000..3fb1ab99 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassInstantiationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 1, + 9 => 1, + 11 => 1, + 14 => 1, + 16 => 1, + 20 => 1, + 21 => 1, + 22 => 1, + 24 => 1, + 25 => 1, + 30 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 37 => 1, + 38 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.inc new file mode 100644 index 00000000..2562d26c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.inc @@ -0,0 +1,52 @@ +bar( + $arg1, + function ($arg2) use ($var1) { + // body + }, + $arg3 +); + +$instance = new class extends \Foo implements \HandleableInterface { + // Class content +}; + +$app->get('/hello/{name}', function ($name) use ($app) { + return 'Hello ' . $app->escape($name); +}); + +enum Foo4 +{ + +}//end diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.php new file mode 100644 index 00000000..d402f1bb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClosingBraceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 13 => 1, + 14 => 1, + 19 => 1, + 24 => 1, + 31 => 1, + 52 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.inc new file mode 100644 index 00000000..2c41bde9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.inc @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class OpeningBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 1, + 18 => 1, + 24 => 1, + 34 => 1, + 41 => 1, + 55 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc new file mode 100644 index 00000000..4bc2eceb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc @@ -0,0 +1,131 @@ + 0 && $n < 10) + || ($n > 10 && $n < 20) + || ($n > 20 && $n < 30) +) { + return $n; +} + +if ( + ( + $expr1 + && $expr2 + && $expr3 + && $expr4 + && $expr5 + && $expr6 + ) + || ($n > 100 && $n < 200) + || ($n > 200 && $n < 300) +) { + return $n; +} + +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly first +if ( + $expr1 + && $expr2 + && ($expr3 + || $expr4) + && $expr5 +) { + // if body +} elseif ( + $expr1 && + ($expr3 || $expr4) + && $expr5 +) { + // elseif body +} elseif ( + $expr1 + && ($expr3 || $expr4) && + $expr5 +) { + // elseif body +} + +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly last +if ( + $expr1 + && $expr2 + && ($expr3 + || $expr4) + && $expr5 +) { + // if body +} elseif ( + $expr1 && + ($expr3 || $expr4) + && $expr5 +) { + // elseif body +} elseif ( + $expr1 + && ($expr3 || $expr4) && + $expr5 +) { + // elseif body +} + +if ( + ($value == 1 || + $value == 2) + && + ($value == 3 || + $value == 4) +) { + return 5; +} + +// Reset to default. +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly + +match ( + $expr1 + && $expr2 && + $expr3 +) { + // structure body +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed new file mode 100644 index 00000000..5f4d223e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed @@ -0,0 +1,141 @@ + 0 && $n < 10) + || ($n > 10 && $n < 20) + || ($n > 20 && $n < 30) +) { + return $n; +} + +if ( + ( + $expr1 + && $expr2 + && $expr3 + && $expr4 + && $expr5 + && $expr6 + ) + || ($n > 100 && $n < 200) + || ($n > 200 && $n < 300) +) { + return $n; +} + +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly first +if ( + $expr1 + && $expr2 + && ($expr3 + || $expr4) + && $expr5 +) { + // if body +} elseif ( + $expr1 + && ($expr3 + || $expr4) + && $expr5 +) { + // elseif body +} elseif ( + $expr1 + && ($expr3 + || $expr4) + && $expr5 +) { + // elseif body +} + +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly last +if ( + $expr1 && + $expr2 && + ($expr3 || + $expr4) && + $expr5 +) { + // if body +} elseif ( + $expr1 && + ($expr3 || + $expr4) && + $expr5 +) { + // elseif body +} elseif ( + $expr1 && + ($expr3 || + $expr4) && + $expr5 +) { + // elseif body +} + +if ( + ($value == 1 || + $value == 2) + && + ($value == 3 || + $value == 4) +) { + return 5; +} + +// Reset to default. +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly + +match ( + $expr1 + && $expr2 + && $expr3 +) { + // structure body +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.php new file mode 100644 index 00000000..3eeaeebc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class BooleanOperatorPlacementUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 1, + 16 => 1, + 28 => 1, + 34 => 1, + 75 => 1, + 81 => 1, + 90 => 1, + 98 => 1, + 104 => 1, + 125 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc new file mode 100644 index 00000000..9c037d6c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc @@ -0,0 +1,100 @@ + $foo + /* + * A multi-line comment. + */ + && $foo === true + ) { + break; + } + +match ( + $expr1 && + $expr2 && + $expr3 + ) { + // structure body +}; + +match ($expr1 && +$expr2 && + $expr3) { + // structure body +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed new file mode 100644 index 00000000..7ea61b1e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed @@ -0,0 +1,103 @@ + $foo + /* + * A multi-line comment. + */ + && $foo === true + ) { + break; + } + +match ( + $expr1 && + $expr2 && + $expr3 +) { + // structure body +}; + +match ( + $expr1 && + $expr2 && + $expr3 +) { + // structure body +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.php new file mode 100644 index 00000000..6ee076f2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.php @@ -0,0 +1,68 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ControlStructureSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 2, + 16 => 1, + 17 => 1, + 18 => 1, + 22 => 1, + 23 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 48 => 2, + 58 => 1, + 59 => 1, + 92 => 1, + 96 => 1, + 97 => 1, + 98 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.inc new file mode 100644 index 00000000..f21daaff --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.inc @@ -0,0 +1,50 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DeclareStatementUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 3 => 1, + 4 => 1, + 5 => 2, + 6 => 1, + 7 => 1, + 9 => 2, + 10 => 1, + 11 => 3, + 12 => 2, + 13 => 1, + 14 => 2, + 16 => 3, + 19 => 3, + 22 => 1, + 24 => 1, + 26 => 3, + 28 => 3, + 34 => 2, + 43 => 1, + 46 => 1, + 47 => 1, + 49 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.1.inc new file mode 100644 index 00000000..1298ed71 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.1.inc @@ -0,0 +1,29 @@ + + +

    + + + +

    + + + + +

    Demo

    + + +
  • My page
  • +
  • Write
  • +
  • Sign out
  • + +
  • Sign in
  • + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.15.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.15.inc new file mode 100644 index 00000000..11102beb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.15.inc @@ -0,0 +1,5 @@ + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.16.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.16.inc new file mode 100644 index 00000000..5c3df1f3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.16.inc @@ -0,0 +1,13 @@ + + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FileHeaderUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FileHeaderUnitTest.2.inc': + return [ + 1 => 1, + 6 => 1, + 7 => 1, + 18 => 1, + 20 => 1, + 24 => 1, + ]; + case 'FileHeaderUnitTest.3.inc': + return [ + 9 => 1, + 18 => 1, + ]; + case 'FileHeaderUnitTest.4.inc': + return [ + 1 => 1, + 2 => 1, + 3 => 1, + 7 => 1, + ]; + case 'FileHeaderUnitTest.5.inc': + return [4 => 1]; + case 'FileHeaderUnitTest.7.inc': + case 'FileHeaderUnitTest.10.inc': + case 'FileHeaderUnitTest.11.inc': + return [1 => 1]; + case 'FileHeaderUnitTest.12.inc': + return [4 => 2]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.inc new file mode 100644 index 00000000..6d024eaa --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.inc @@ -0,0 +1,26 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ImportStatementUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 1, + 7 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.1.inc new file mode 100644 index 00000000..0dbdf010 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.1.inc @@ -0,0 +1,3 @@ + +hi diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.4.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.4.inc new file mode 100644 index 00000000..09be8fbe --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.4.inc @@ -0,0 +1,2 @@ + + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class OpenTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'OpenTagUnitTest.2.inc': + return [1 => 1]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc new file mode 100644 index 00000000..e3a5a775 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc @@ -0,0 +1,87 @@ + + * @copyright 2006-2018 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class NullableTypeDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + protected function getErrorList() + { + return [ + 23 => 1, + 24 => 1, + 25 => 1, + 30 => 1, + 31 => 1, + 32 => 1, + 43 => 2, + 48 => 1, + 50 => 1, + 51 => 1, + 53 => 1, + 57 => 2, + 58 => 2, + 59 => 2, + 87 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + protected function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc new file mode 100644 index 00000000..59ab1aa7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc @@ -0,0 +1,66 @@ + $arg; + +return (!$a ? [ new class { public function b(): c {} } ] : []); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc.fixed new file mode 100644 index 00000000..cd79f781 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc.fixed @@ -0,0 +1,62 @@ + $arg; + +return (!$a ? [ new class { public function b(): c {} } ] : []); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.php new file mode 100644 index 00000000..fc6b5e19 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2018 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ReturnTypeDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + protected function getErrorList() + { + return [ + 27 => 1, + 28 => 1, + 35 => 2, + 41 => 2, + 48 => 2, + 52 => 1, + 55 => 1, + 56 => 1, + 59 => 1, + 60 => 1, + 62 => 1, + 64 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + protected function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.inc new file mode 100644 index 00000000..6ce930d9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.inc @@ -0,0 +1,14 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Keywords; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ShortFormTypeKeywordsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 13 => 1, + 14 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Namespaces/CompoundNamespaceDepthUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Namespaces/CompoundNamespaceDepthUnitTest.inc new file mode 100644 index 00000000..3336fc2d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Namespaces/CompoundNamespaceDepthUnitTest.inc @@ -0,0 +1,31 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Namespaces; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class CompoundNamespaceDepthUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 1, + 18 => 1, + 21 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc new file mode 100644 index 00000000..c067e6a2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc @@ -0,0 +1,77 @@ + $b) { + $variable =$foo ? 'foo' :'bar'; + $variable.='text'.'text'; +} + +$foo+= $a&$b; +$foo = $a|$b; +$foo =$a^$b; +$foo = ~$a; +$foo *=$a<<$b; +$foo = $a>>$b; + +function foo(&$a,& $b) {} + +$foo = $a and$b; +$foo = $a or $b; +$foo = $a xor$b; +$foo = !$a; +$foo = $a&&$b; +$foo = $a||$b; + +$foo = $a instanceof Foo; +$foo = $a instanceof$b; + +$foo .= 'hi' + .= 'there'; + +$foo .= 'hi' +.= 'there'; + +$foo .= 'hi' // comment +.= 'there'; + +$foo/*comment*/=/*comment*/$a/*comment*/and/*comment*/$b; + +$foo .=//comment +'string' .=/*comment*/ +'string'; + +$foo = $foo ?: 'bar'; +$foo = $foo?:'bar'; + +try { +} catch (ExceptionType1|ExceptionType2 $e) { +} + +if (strpos($tokenContent, 'b"') === 0 && substr($tokenContent, -1) === '"') {} + +$oldConstructorPos = +1; +return -$content; + +function name($a = -1) {} + +$a =& $ref; +$a = [ 'a' => &$something ]; + +$fn = fn(array &$one) => 1; +$fn = fn(array & $one) => 1; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); + +function issue3267(string|int ...$values) {} + +function setDefault(#[ImportValue( + constraints: [ + [ + Assert\Type::class, + ['type' => 'bool'], + ], + ] + )] ?bool $value = null): void + { + // Do something + } diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc.fixed new file mode 100644 index 00000000..76764291 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc.fixed @@ -0,0 +1,77 @@ + $b) { + $variable = $foo ? 'foo' : 'bar'; + $variable .= 'text' . 'text'; +} + +$foo += $a & $b; +$foo = $a | $b; +$foo = $a ^ $b; +$foo = ~$a; +$foo *= $a << $b; +$foo = $a >> $b; + +function foo(&$a,& $b) {} + +$foo = $a and $b; +$foo = $a or $b; +$foo = $a xor $b; +$foo = !$a; +$foo = $a && $b; +$foo = $a || $b; + +$foo = $a instanceof Foo; +$foo = $a instanceof $b; + +$foo .= 'hi' + .= 'there'; + +$foo .= 'hi' +.= 'there'; + +$foo .= 'hi' // comment +.= 'there'; + +$foo/*comment*/ = /*comment*/$a/*comment*/ and /*comment*/$b; + +$foo .= //comment +'string' .= /*comment*/ +'string'; + +$foo = $foo ?: 'bar'; +$foo = $foo ?: 'bar'; + +try { +} catch (ExceptionType1 | ExceptionType2 $e) { +} + +if (strpos($tokenContent, 'b"') === 0 && substr($tokenContent, -1) === '"') {} + +$oldConstructorPos = +1; +return -$content; + +function name($a = -1) {} + +$a =& $ref; +$a = [ 'a' => &$something ]; + +$fn = fn(array &$one) => 1; +$fn = fn(array & $one) => 1; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); + +function issue3267(string|int ...$values) {} + +function setDefault(#[ImportValue( + constraints: [ + [ + Assert\Type::class, + ['type' => 'bool'], + ], + ] + )] ?bool $value = null): void + { + // Do something + } diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php new file mode 100644 index 00000000..e23fd968 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php @@ -0,0 +1,69 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Operators; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class OperatorSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 3 => 2, + 4 => 1, + 5 => 2, + 6 => 4, + 9 => 3, + 10 => 2, + 11 => 3, + 13 => 3, + 14 => 2, + 18 => 1, + 20 => 1, + 22 => 2, + 23 => 2, + 26 => 1, + 37 => 4, + 39 => 1, + 40 => 1, + 44 => 2, + 47 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Properties/ConstantVisibilityUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Properties/ConstantVisibilityUnitTest.inc new file mode 100644 index 00000000..84ea24b2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Properties/ConstantVisibilityUnitTest.inc @@ -0,0 +1,22 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Properties; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ConstantVisibilityUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 4 => 1, + 12 => 1, + 21 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.inc new file mode 100644 index 00000000..c8ad746a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.inc @@ -0,0 +1,221 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Traits; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class UseDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 15 => 1, + 29 => 2, + 30 => 1, + 42 => 1, + 57 => 3, + 59 => 3, + 61 => 1, + 63 => 5, + 65 => 1, + 71 => 1, + 73 => 2, + 76 => 1, + 86 => 2, + 103 => 1, + 112 => 1, + 122 => 1, + 132 => 1, + 157 => 1, + 165 => 1, + 170 => 1, + 208 => 1, + 219 => 3, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/ruleset.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/ruleset.xml new file mode 100644 index 00000000..ce8b71a7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/ruleset.xml @@ -0,0 +1,347 @@ + + + The PSR-12 coding standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + error + Method name "%s" must not be prefixed with an underscore to indicate visibility + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + 0 + + + 0 + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/ClassDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/ClassDeclarationStandard.xml new file mode 100644 index 00000000..4e56bc04 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/ClassDeclarationStandard.xml @@ -0,0 +1,23 @@ + + + + + + + class Foo +{ +} + ]]> + + + class Foo +{ +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/PropertyDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/PropertyDeclarationStandard.xml new file mode 100644 index 00000000..042c0c6c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/PropertyDeclarationStandard.xml @@ -0,0 +1,81 @@ + + + + + + + bar; +} + ]]> + + + _bar; +} + ]]> + + + + + private $bar; +} + ]]> + + + var $bar; +} + ]]> + + + + + + + + $bar, $baz; +} + ]]> + + + + + static $bar; + private $baz; +} + ]]> + + + static protected $bar; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ControlStructureSpacingStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ControlStructureSpacingStandard.xml new file mode 100644 index 00000000..dcbe98f5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ControlStructureSpacingStandard.xml @@ -0,0 +1,23 @@ + + + + + + + $foo) { + $var = 1; +} + ]]> + + + $foo ) { + $var = 1; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ElseIfDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ElseIfDeclarationStandard.xml new file mode 100644 index 00000000..a22dd179 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ElseIfDeclarationStandard.xml @@ -0,0 +1,27 @@ + + + + + + + elseif ($bar) { + $var = 2; +} + ]]> + + + else if ($bar) { + $var = 2; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/SwitchDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/SwitchDeclarationStandard.xml new file mode 100644 index 00000000..1d6d053d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/SwitchDeclarationStandard.xml @@ -0,0 +1,104 @@ + + + + + + + case 'bar': + break; +} + ]]> + + + case 'bar': + break; +} + ]]> + + + + + 'bar': + break; +} + ]]> + + + 'bar': + break; +} + ]]> + + + + + : + break; + default: + break; +} + ]]> + + + : + break; + default : + break; +} + ]]> + + + + + break; +} + ]]> + + + break; +} + ]]> + + + + + // no break + default: + break; +} + ]]> + + + : + break; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/EndFileNewlineStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/EndFileNewlineStandard.xml new file mode 100644 index 00000000..d6d3aad1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/EndFileNewlineStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/MethodDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/MethodDeclarationStandard.xml new file mode 100644 index 00000000..e45469e8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/MethodDeclarationStandard.xml @@ -0,0 +1,51 @@ + + + + + + + bar() + { + } +} + ]]> + + + _bar() + { + } +} + ]]> + + + + + final public static function bar() + { + } +} + ]]> + + + static public final function bar() + { + } +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/NamespaceDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/NamespaceDeclarationStandard.xml new file mode 100644 index 00000000..1f4d389a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/NamespaceDeclarationStandard.xml @@ -0,0 +1,22 @@ + + + + + + + +use \Baz; + ]]> + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/UseDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/UseDeclarationStandard.xml new file mode 100644 index 00000000..4082603c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/UseDeclarationStandard.xml @@ -0,0 +1,57 @@ + + + + + + + + + + \Foo, \Bar; + ]]> + + + + + + + + + + + + + +class Baz +{ +} + ]]> + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/ClassDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/ClassDeclarationSniff.php new file mode 100644 index 00000000..f96b0049 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/ClassDeclarationSniff.php @@ -0,0 +1,528 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PEAR\Sniffs\Classes\ClassDeclarationSniff as PEARClassDeclarationSniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDeclarationSniff extends PEARClassDeclarationSniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // We want all the errors from the PEAR standard, plus some of our own. + parent::process($phpcsFile, $stackPtr); + + // Just in case. + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + $this->processOpen($phpcsFile, $stackPtr); + $this->processClose($phpcsFile, $stackPtr); + + }//end process() + + + /** + * Processes the opening section of a class declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processOpen(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $stackPtrType = strtolower($tokens[$stackPtr]['content']); + + // Check alignment of the keyword and braces. + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $prevContent = $tokens[($stackPtr - 1)]['content']; + if ($prevContent !== $phpcsFile->eolChar) { + $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar)); + $spaces = strlen($blankSpace); + + if (in_array($tokens[($stackPtr - 2)]['code'], [T_ABSTRACT, T_FINAL], true) === true + && $spaces !== 1 + ) { + $prevContent = strtolower($tokens[($stackPtr - 2)]['content']); + $error = 'Expected 1 space between %s and %s keywords; %s found'; + $data = [ + $prevContent, + $stackPtrType, + $spaces, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeKeyword', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + } + } else if ($tokens[($stackPtr - 2)]['code'] === T_ABSTRACT + || $tokens[($stackPtr - 2)]['code'] === T_FINAL + ) { + $prevContent = strtolower($tokens[($stackPtr - 2)]['content']); + $error = 'Expected 1 space between %s and %s keywords; newline found'; + $data = [ + $prevContent, + $stackPtrType, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NewlineBeforeKeyword', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + }//end if + }//end if + + // We'll need the indent of the class/interface declaration for later. + $classIndent = 0; + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) { + continue; + } + + // We changed lines. + if ($tokens[($i + 1)]['code'] === T_WHITESPACE) { + $classIndent = $tokens[($i + 1)]['length']; + } + + break; + } + + $className = null; + $checkSpacing = true; + + if ($tokens[$stackPtr]['code'] !== T_ANON_CLASS) { + $className = $phpcsFile->findNext(T_STRING, $stackPtr); + } else { + // Ignore the spacing check if this is a simple anon class. + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next === $tokens[$stackPtr]['scope_opener'] + && $tokens[$next]['line'] > $tokens[$stackPtr]['line'] + ) { + $checkSpacing = false; + } + } + + if ($checkSpacing === true) { + // Spacing of the keyword. + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $gap = 0; + } else if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $gap = 'newline'; + } else { + $gap = $tokens[($stackPtr + 1)]['length']; + } + + if ($gap !== 1) { + $error = 'Expected 1 space after %s keyword; %s found'; + $data = [ + $stackPtrType, + $gap, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterKeyword', $data); + if ($fix === true) { + if ($gap === 0) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } + }//end if + + // Check after the class/interface name. + if ($className !== null + && $tokens[($className + 2)]['line'] === $tokens[$className]['line'] + ) { + $gap = $tokens[($className + 1)]['content']; + if (strlen($gap) !== 1) { + $found = strlen($gap); + $error = 'Expected 1 space after %s name; %s found'; + $data = [ + $stackPtrType, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $className, 'SpaceAfterName', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($className + 1), ' '); + } + } + } + + $openingBrace = $tokens[$stackPtr]['scope_opener']; + + // Check positions of the extends and implements keywords. + $compareToken = $stackPtr; + $compareType = 'name'; + if ($tokens[$stackPtr]['code'] === T_ANON_CLASS) { + if (isset($tokens[$stackPtr]['parenthesis_opener']) === true) { + $compareToken = $tokens[$stackPtr]['parenthesis_closer']; + $compareType = 'closing parenthesis'; + } else { + $compareType = 'keyword'; + } + } + + foreach (['extends', 'implements'] as $keywordType) { + $keyword = $phpcsFile->findNext(constant('T_'.strtoupper($keywordType)), ($compareToken + 1), $openingBrace); + if ($keyword !== false) { + if ($tokens[$keyword]['line'] !== $tokens[$compareToken]['line']) { + $error = 'The '.$keywordType.' keyword must be on the same line as the %s '.$compareType; + $data = [$stackPtrType]; + $fix = $phpcsFile->addFixableError($error, $keyword, ucfirst($keywordType).'Line', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $comments = []; + + for ($i = ($compareToken + 1); $i < $keyword; ++$i) { + if ($tokens[$i]['code'] === T_COMMENT) { + $comments[] = trim($tokens[$i]['content']); + } + + if ($tokens[$i]['code'] === T_WHITESPACE + || $tokens[$i]['code'] === T_COMMENT + ) { + $phpcsFile->fixer->replaceToken($i, ' '); + } + } + + $phpcsFile->fixer->addContent($compareToken, ' '); + if (empty($comments) === false) { + $i = $keyword; + while ($tokens[($i + 1)]['line'] === $tokens[$keyword]['line']) { + ++$i; + } + + $phpcsFile->fixer->addContentBefore($i, ' '.implode(' ', $comments)); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + } else { + // Check the whitespace before. Whitespace after is checked + // later by looking at the whitespace before the first class name + // in the list. + $gap = $tokens[($keyword - 1)]['length']; + if ($gap !== 1) { + $error = 'Expected 1 space before '.$keywordType.' keyword; %s found'; + $data = [$gap]; + $fix = $phpcsFile->addFixableError($error, $keyword, 'SpaceBefore'.ucfirst($keywordType), $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($keyword - 1), ' '); + } + } + }//end if + }//end if + }//end foreach + + // Check each of the extends/implements class names. If the extends/implements + // keyword is the last content on the line, it means we need to check for + // the multi-line format, so we do not include the class names + // from the extends/implements list in the following check. + // Note that classes can only extend one other class, so they can't use a + // multi-line extends format, whereas an interface can extend multiple + // other interfaces, and so uses a multi-line extends format. + if ($tokens[$stackPtr]['code'] === T_INTERFACE) { + $keywordTokenType = T_EXTENDS; + } else { + $keywordTokenType = T_IMPLEMENTS; + } + + $implements = $phpcsFile->findNext($keywordTokenType, ($stackPtr + 1), $openingBrace); + $multiLineImplements = false; + if ($implements !== false) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($openingBrace - 1), $implements, true); + if ($tokens[$prev]['line'] !== $tokens[$implements]['line']) { + $multiLineImplements = true; + } + } + + $find = [ + T_STRING, + $keywordTokenType, + ]; + + if ($className !== null) { + $start = $className; + } else if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) { + $start = $tokens[$stackPtr]['parenthesis_closer']; + } else { + $start = $stackPtr; + } + + $classNames = []; + $nextClass = $phpcsFile->findNext($find, ($start + 2), ($openingBrace - 1)); + while ($nextClass !== false) { + $classNames[] = $nextClass; + $nextClass = $phpcsFile->findNext($find, ($nextClass + 1), ($openingBrace - 1)); + } + + $classCount = count($classNames); + $checkingImplements = false; + $implementsToken = null; + foreach ($classNames as $n => $className) { + if ($tokens[$className]['code'] === $keywordTokenType) { + $checkingImplements = true; + $implementsToken = $className; + + continue; + } + + if ($checkingImplements === true + && $multiLineImplements === true + && ($tokens[($className - 1)]['code'] !== T_NS_SEPARATOR + || $tokens[($className - 2)]['code'] !== T_STRING) + ) { + $prev = $phpcsFile->findPrevious( + [ + T_NS_SEPARATOR, + T_WHITESPACE, + ], + ($className - 1), + $implements, + true + ); + + if ($prev === $implementsToken && $tokens[$className]['line'] !== ($tokens[$prev]['line'] + 1)) { + if ($keywordTokenType === T_EXTENDS) { + $error = 'The first item in a multi-line extends list must be on the line following the extends keyword'; + $fix = $phpcsFile->addFixableError($error, $className, 'FirstExtendsInterfaceSameLine'); + } else { + $error = 'The first item in a multi-line implements list must be on the line following the implements keyword'; + $fix = $phpcsFile->addFixableError($error, $className, 'FirstInterfaceSameLine'); + } + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $className; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->endChangeset(); + } + } else if ($tokens[$prev]['line'] !== ($tokens[$className]['line'] - 1)) { + if ($keywordTokenType === T_EXTENDS) { + $error = 'Only one interface may be specified per line in a multi-line extends declaration'; + $fix = $phpcsFile->addFixableError($error, $className, 'ExtendsInterfaceSameLine'); + } else { + $error = 'Only one interface may be specified per line in a multi-line implements declaration'; + $fix = $phpcsFile->addFixableError($error, $className, 'InterfaceSameLine'); + } + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $className; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->endChangeset(); + } + } else { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($className - 1), $implements); + if ($tokens[$prev]['line'] !== $tokens[$className]['line']) { + $found = 0; + } else { + $found = $tokens[$prev]['length']; + } + + $expected = ($classIndent + $this->indent); + if ($found !== $expected) { + $error = 'Expected %s spaces before interface name; %s found'; + $data = [ + $expected, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $className, 'InterfaceWrongIndent', $data); + if ($fix === true) { + $padding = str_repeat(' ', $expected); + if ($found === 0) { + $phpcsFile->fixer->addContent($prev, $padding); + } else { + $phpcsFile->fixer->replaceToken($prev, $padding); + } + } + } + }//end if + } else if ($tokens[($className - 1)]['code'] !== T_NS_SEPARATOR + || $tokens[($className - 2)]['code'] !== T_STRING + ) { + // Not part of a longer fully qualified class name. + if ($tokens[($className - 1)]['code'] === T_COMMA + || ($tokens[($className - 1)]['code'] === T_NS_SEPARATOR + && $tokens[($className - 2)]['code'] === T_COMMA) + ) { + $error = 'Expected 1 space before "%s"; 0 found'; + $data = [$tokens[$className]['content']]; + $fix = $phpcsFile->addFixableError($error, ($nextComma + 1), 'NoSpaceBeforeName', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore(($nextComma + 1), ' '); + } + } else { + if ($tokens[($className - 1)]['code'] === T_NS_SEPARATOR) { + $prev = ($className - 2); + } else { + $prev = ($className - 1); + } + + $last = $phpcsFile->findPrevious(T_WHITESPACE, $prev, null, true); + $content = $phpcsFile->getTokensAsString(($last + 1), ($prev - $last)); + if ($content !== ' ') { + $found = strlen($content); + + $error = 'Expected 1 space before "%s"; %s found'; + $data = [ + $tokens[$className]['content'], + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $className, 'SpaceBeforeName', $data); + if ($fix === true) { + if ($tokens[$prev]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($prev, ' '); + while ($tokens[--$prev]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($prev, ' '); + } + + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->addContent($prev, ' '); + } + } + }//end if + }//end if + }//end if + + if ($checkingImplements === true + && $tokens[($className + 1)]['code'] !== T_NS_SEPARATOR + && $tokens[($className + 1)]['code'] !== T_COMMA + ) { + if ($n !== ($classCount - 1)) { + // This is not the last class name, and the comma + // is not where we expect it to be. + if ($tokens[($className + 2)]['code'] !== $keywordTokenType) { + $error = 'Expected 0 spaces between "%s" and comma; %s found'; + $data = [ + $tokens[$className]['content'], + $tokens[($className + 1)]['length'], + ]; + + $fix = $phpcsFile->addFixableError($error, $className, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($className + 1), ''); + } + } + } + + $nextComma = $phpcsFile->findNext(T_COMMA, $className); + } else { + $nextComma = ($className + 1); + }//end if + }//end foreach + + }//end processOpen() + + + /** + * Processes the closing section of a class declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processClose(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check that the closing brace comes right after the code body. + $closeBrace = $tokens[$stackPtr]['scope_closer']; + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), null, true); + if ($prevContent !== $tokens[$stackPtr]['scope_opener'] + && $tokens[$prevContent]['line'] !== ($tokens[$closeBrace]['line'] - 1) + ) { + $error = 'The closing brace for the %s must go on the next line after the body'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'CloseBraceAfterBody', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prevContent + 1); $i < $closeBrace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + if (strpos($tokens[$prevContent]['content'], $phpcsFile->eolChar) === false) { + $phpcsFile->fixer->replaceToken($closeBrace, $phpcsFile->eolChar.$tokens[$closeBrace]['content']); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + if ($tokens[$stackPtr]['code'] !== T_ANON_CLASS) { + // Check the closing brace is on it's own line, but allow + // for comments like "//end class". + $ignoreTokens = Tokens::$phpcsCommentTokens; + $ignoreTokens[] = T_WHITESPACE; + $ignoreTokens[] = T_COMMENT; + $ignoreTokens[] = T_SEMICOLON; + $ignoreTokens[] = T_COMMA; + $nextContent = $phpcsFile->findNext($ignoreTokens, ($closeBrace + 1), null, true); + if ($tokens[$nextContent]['content'] !== $phpcsFile->eolChar + && $tokens[$nextContent]['line'] === $tokens[$closeBrace]['line'] + ) { + $type = strtolower($tokens[$stackPtr]['content']); + $error = 'Closing %s brace must be on a line by itself'; + $data = [$type]; + $phpcsFile->addError($error, $closeBrace, 'CloseBraceSameLine', $data); + } + } + + }//end processClose() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.php new file mode 100644 index 00000000..efdbb438 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.php @@ -0,0 +1,185 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Tokens; + +class PropertyDeclarationSniff extends AbstractVariableSniff +{ + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['content'][1] === '_') { + $error = 'Property name "%s" should not be prefixed with an underscore to indicate visibility'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addWarning($error, $stackPtr, 'Underscore', $data); + } + + // Detect multiple properties defined at the same time. Throw an error + // for this, but also only process the first property in the list so we don't + // repeat errors. + $find = Tokens::$scopeModifiers; + $find[] = T_VARIABLE; + $find[] = T_VAR; + $find[] = T_READONLY; + $find[] = T_SEMICOLON; + $find[] = T_OPEN_CURLY_BRACKET; + + $prev = $phpcsFile->findPrevious($find, ($stackPtr - 1)); + if ($tokens[$prev]['code'] === T_VARIABLE) { + return; + } + + if ($tokens[$prev]['code'] === T_VAR) { + $error = 'The var keyword must not be used to declare a property'; + $phpcsFile->addError($error, $stackPtr, 'VarUsed'); + } + + $next = $phpcsFile->findNext([T_VARIABLE, T_SEMICOLON], ($stackPtr + 1)); + if ($next !== false && $tokens[$next]['code'] === T_VARIABLE) { + $error = 'There must not be more than one property declared per statement'; + $phpcsFile->addError($error, $stackPtr, 'Multiple'); + } + + try { + $propertyInfo = $phpcsFile->getMemberProperties($stackPtr); + if (empty($propertyInfo) === true) { + return; + } + } catch (\Exception $e) { + // Turns out not to be a property after all. + return; + } + + if ($propertyInfo['type'] !== '') { + $typeToken = $propertyInfo['type_end_token']; + $error = 'There must be 1 space after the property type declaration; %s found'; + if ($tokens[($typeToken + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $typeToken, 'SpacingAfterType', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($typeToken, ' '); + } + } else if ($tokens[($typeToken + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($typeToken + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$typeToken]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($typeToken + 1)]['length']; + } + + $data = [$found]; + + $nextNonWs = $phpcsFile->findNext(Tokens::$emptyTokens, ($typeToken + 1), null, true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $typeToken, 'SpacingAfterType', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $typeToken, 'SpacingAfterType', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($typeToken + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($typeToken, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($typeToken + 1), ' '); + } + } + } + }//end if + }//end if + + if ($propertyInfo['scope_specified'] === false) { + $error = 'Visibility must be declared on property "%s"'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addError($error, $stackPtr, 'ScopeMissing', $data); + } + + if ($propertyInfo['scope_specified'] === true && $propertyInfo['is_static'] === true) { + $scopePtr = $phpcsFile->findPrevious(Tokens::$scopeModifiers, ($stackPtr - 1)); + $staticPtr = $phpcsFile->findPrevious(T_STATIC, ($stackPtr - 1)); + if ($scopePtr < $staticPtr) { + return; + } + + $error = 'The static declaration must come after the visibility declaration'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'StaticBeforeVisibility'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($scopePtr + 1); $scopePtr < $stackPtr; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken($scopePtr, ''); + $phpcsFile->fixer->addContentBefore($staticPtr, $propertyInfo['scope'].' '); + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + }//end processMemberVar() + + + /** + * Processes normal variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariable() + + + /** + * Processes variables in double quoted strings. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariableInString() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ControlStructureSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ControlStructureSpacingSniff.php new file mode 100644 index 00000000..09d2c14a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ControlStructureSpacingSniff.php @@ -0,0 +1,142 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ControlStructureSpacingSniff implements Sniff +{ + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_WHILE, + T_FOREACH, + T_FOR, + T_SWITCH, + T_ELSE, + T_ELSEIF, + T_CATCH, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + ) { + return; + } + + $parenOpener = $tokens[$stackPtr]['parenthesis_opener']; + $parenCloser = $tokens[$stackPtr]['parenthesis_closer']; + $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($parenOpener + 1), null, true); + if (in_array($tokens[$nextContent]['code'], Tokens::$commentTokens, true) === false) { + $spaceAfterOpen = 0; + if ($tokens[($parenOpener + 1)]['code'] === T_WHITESPACE) { + if (strpos($tokens[($parenOpener + 1)]['content'], $phpcsFile->eolChar) !== false) { + $spaceAfterOpen = 'newline'; + } else { + $spaceAfterOpen = $tokens[($parenOpener + 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', $spaceAfterOpen); + + if ($spaceAfterOpen !== $this->requiredSpacesAfterOpen) { + $error = 'Expected %s spaces after opening bracket; %s found'; + $data = [ + $this->requiredSpacesAfterOpen, + $spaceAfterOpen, + ]; + $fix = $phpcsFile->addFixableError($error, ($parenOpener + 1), 'SpacingAfterOpenBrace', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesAfterOpen); + if ($spaceAfterOpen === 0) { + $phpcsFile->fixer->addContent($parenOpener, $padding); + } else if ($spaceAfterOpen === 'newline') { + $phpcsFile->fixer->replaceToken(($parenOpener + 1), ''); + } else { + $phpcsFile->fixer->replaceToken(($parenOpener + 1), $padding); + } + } + } + }//end if + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($parenCloser - 1), $parenOpener, true); + if ($tokens[$prev]['line'] === $tokens[$parenCloser]['line']) { + $spaceBeforeClose = 0; + if ($tokens[($parenCloser - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = strlen(ltrim($tokens[($parenCloser - 1)]['content'], $phpcsFile->eolChar)); + } + + $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', $spaceBeforeClose); + + if ($spaceBeforeClose !== $this->requiredSpacesBeforeClose) { + $error = 'Expected %s spaces before closing bracket; %s found'; + $data = [ + $this->requiredSpacesBeforeClose, + $spaceBeforeClose, + ]; + $fix = $phpcsFile->addFixableError($error, ($parenCloser - 1), 'SpaceBeforeCloseBrace', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesBeforeClose); + if ($spaceBeforeClose === 0) { + $phpcsFile->fixer->addContentBefore($parenCloser, $padding); + } else { + $phpcsFile->fixer->replaceToken(($parenCloser - 1), $padding); + } + } + } + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ElseIfDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ElseIfDeclarationSniff.php new file mode 100644 index 00000000..9f97684a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ElseIfDeclarationSniff.php @@ -0,0 +1,72 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ElseIfDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_ELSE, + T_ELSEIF, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_ELSEIF) { + $phpcsFile->recordMetric($stackPtr, 'Use of ELSE IF or ELSEIF', 'elseif'); + return; + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_IF) { + $phpcsFile->recordMetric($stackPtr, 'Use of ELSE IF or ELSEIF', 'else if'); + $error = 'Usage of ELSE IF is discouraged; use ELSEIF instead'; + $fix = $phpcsFile->addFixableWarning($error, $stackPtr, 'NotAllowed'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($stackPtr, 'elseif'); + for ($i = ($stackPtr + 1); $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php new file mode 100644 index 00000000..de81c530 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php @@ -0,0 +1,396 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SwitchDeclarationSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_SWITCH]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // We can't process SWITCH statements unless we know where they start and end. + if (isset($tokens[$stackPtr]['scope_opener']) === false + || isset($tokens[$stackPtr]['scope_closer']) === false + ) { + return; + } + + $switch = $tokens[$stackPtr]; + $nextCase = $stackPtr; + $caseAlignment = ($switch['column'] + $this->indent); + + while (($nextCase = $this->findNextCase($phpcsFile, ($nextCase + 1), $switch['scope_closer'])) !== false) { + if ($tokens[$nextCase]['code'] === T_DEFAULT) { + $type = 'default'; + } else { + $type = 'case'; + } + + if ($tokens[$nextCase]['content'] !== strtolower($tokens[$nextCase]['content'])) { + $expected = strtolower($tokens[$nextCase]['content']); + $error = strtoupper($type).' keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + $expected, + $tokens[$nextCase]['content'], + ]; + + $fix = $phpcsFile->addFixableError($error, $nextCase, $type.'NotLower', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($nextCase, $expected); + } + } + + if ($type === 'case' + && ($tokens[($nextCase + 1)]['code'] !== T_WHITESPACE + || $tokens[($nextCase + 1)]['content'] !== ' ') + ) { + $error = 'CASE keyword must be followed by a single space'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'SpacingAfterCase'); + if ($fix === true) { + if ($tokens[($nextCase + 1)]['code'] !== T_WHITESPACE) { + $phpcsFile->fixer->addContent($nextCase, ' '); + } else { + $phpcsFile->fixer->replaceToken(($nextCase + 1), ' '); + } + } + } + + $opener = $tokens[$nextCase]['scope_opener']; + $nextCloser = $tokens[$nextCase]['scope_closer']; + if ($tokens[$opener]['code'] === T_COLON) { + if ($tokens[($opener - 1)]['code'] === T_WHITESPACE) { + $error = 'There must be no space before the colon in a '.strtoupper($type).' statement'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'SpaceBeforeColon'.strtoupper($type)); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($opener - 1), ''); + } + } + + for ($next = ($opener + 1); $next < $nextCloser; $next++) { + if (isset(Tokens::$emptyTokens[$tokens[$next]['code']]) === false + || (isset(Tokens::$commentTokens[$tokens[$next]['code']]) === true + && $tokens[$next]['line'] !== $tokens[$opener]['line']) + ) { + break; + } + } + + if ($tokens[$next]['line'] !== ($tokens[$opener]['line'] + 1)) { + $error = 'The '.strtoupper($type).' body must start on the line following the statement'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'BodyOnNextLine'.strtoupper($type)); + if ($fix === true) { + if ($tokens[$next]['line'] === $tokens[$opener]['line']) { + $padding = str_repeat(' ', ($caseAlignment + $this->indent - 1)); + $phpcsFile->fixer->addContentBefore($next, $phpcsFile->eolChar.$padding); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($opener + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$opener]['line']) { + // Ignore trailing comments. + continue; + } + + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + if ($tokens[$nextCloser]['scope_condition'] === $nextCase) { + // Only need to check some things once, even if the + // closer is shared between multiple case statements, or even + // the default case. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($nextCloser - 1), $nextCase, true); + if ($tokens[$prev]['line'] === $tokens[$nextCloser]['line']) { + $error = 'Terminating statement must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $nextCloser, 'BreakNotNewLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewLine($prev); + $phpcsFile->fixer->replaceToken($nextCloser, trim($tokens[$nextCloser]['content'])); + } + } else { + $diff = ($tokens[$nextCase]['column'] + $this->indent - $tokens[$nextCloser]['column']); + if ($diff !== 0) { + $error = 'Terminating statement must be indented to the same level as the CASE body'; + $fix = $phpcsFile->addFixableError($error, $nextCloser, 'BreakIndent'); + if ($fix === true) { + if ($diff > 0) { + $phpcsFile->fixer->addContentBefore($nextCloser, str_repeat(' ', $diff)); + } else { + $phpcsFile->fixer->substrToken(($nextCloser - 1), 0, $diff); + } + } + } + }//end if + }//end if + } else { + $error = strtoupper($type).' statements must be defined using a colon'; + $phpcsFile->addError($error, $nextCase, 'WrongOpener'.$type); + }//end if + + // We only want cases from here on in. + if ($type !== 'case') { + continue; + } + + $nextCode = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), $nextCloser, true); + + if ($tokens[$nextCode]['code'] !== T_CASE && $tokens[$nextCode]['code'] !== T_DEFAULT) { + // This case statement has content. If the next case or default comes + // before the closer, it means we don't have an obvious terminating + // statement and need to make some more effort to find one. If we + // don't, we do need a comment. + $nextCode = $this->findNextCase($phpcsFile, ($opener + 1), $nextCloser); + if ($nextCode !== false) { + $prevCode = $phpcsFile->findPrevious(T_WHITESPACE, ($nextCode - 1), $nextCase, true); + if (isset(Tokens::$commentTokens[$tokens[$prevCode]['code']]) === false + && $this->findNestedTerminator($phpcsFile, ($opener + 1), $nextCode) === false + ) { + $error = 'There must be a comment when fall-through is intentional in a non-empty case body'; + $phpcsFile->addError($error, $nextCase, 'TerminatingComment'); + } + } + } + }//end while + + }//end process() + + + /** + * Find the next CASE or DEFAULT statement from a point in the file. + * + * Note that nested switches are ignored. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position to start looking at. + * @param int $end The position to stop looking at. + * + * @return int|false + */ + private function findNextCase($phpcsFile, $stackPtr, $end) + { + $tokens = $phpcsFile->getTokens(); + while (($stackPtr = $phpcsFile->findNext([T_CASE, T_DEFAULT, T_SWITCH], $stackPtr, $end)) !== false) { + // Skip nested SWITCH statements; they are handled on their own. + if ($tokens[$stackPtr]['code'] === T_SWITCH) { + $stackPtr = $tokens[$stackPtr]['scope_closer']; + continue; + } + + break; + } + + return $stackPtr; + + }//end findNextCase() + + + /** + * Returns the position of the nested terminating statement. + * + * Returns false if no terminating statement was found. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position to start looking at. + * @param int $end The position to stop looking at. + * + * @return int|false + */ + private function findNestedTerminator($phpcsFile, $stackPtr, $end) + { + $tokens = $phpcsFile->getTokens(); + + $lastToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($end - 1), $stackPtr, true); + if ($lastToken === false) { + return false; + } + + if ($tokens[$lastToken]['code'] === T_CLOSE_CURLY_BRACKET) { + // We found a closing curly bracket and want to check if its block + // belongs to a SWITCH, IF, ELSEIF or ELSE, TRY, CATCH OR FINALLY clause. + // If yes, we continue searching for a terminating statement within that + // block. Note that we have to make sure that every block of + // the entire if/else/switch statement has a terminating statement. + // For a try/catch/finally statement, either the finally block has + // to have a terminating statement or every try/catch block has to have one. + $currentCloser = $lastToken; + $hasElseBlock = false; + $hasCatchWithoutTerminator = false; + do { + $scopeOpener = $tokens[$currentCloser]['scope_opener']; + $scopeCloser = $tokens[$currentCloser]['scope_closer']; + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($scopeOpener - 1), $stackPtr, true); + if ($prevToken === false) { + return false; + } + + // SWITCH, IF, ELSEIF, CATCH clauses possess a condition we have to account for. + if ($tokens[$prevToken]['code'] === T_CLOSE_PARENTHESIS) { + $prevToken = $tokens[$prevToken]['parenthesis_owner']; + } + + if ($tokens[$prevToken]['code'] === T_IF) { + // If we have not encountered an ELSE clause by now, we cannot + // be sure that the whole statement terminates in every case. + if ($hasElseBlock === false) { + return false; + } + + return $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + } else if ($tokens[$prevToken]['code'] === T_ELSEIF + || $tokens[$prevToken]['code'] === T_ELSE + ) { + // If we find a terminating statement within this block, + // we continue with the previous ELSEIF or IF clause. + $hasTerminator = $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + if ($hasTerminator === false) { + return false; + } + + $currentCloser = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), $stackPtr, true); + if ($tokens[$prevToken]['code'] === T_ELSE) { + $hasElseBlock = true; + } + } else if ($tokens[$prevToken]['code'] === T_FINALLY) { + // If we find a terminating statement within this block, + // the whole try/catch/finally statement is covered. + $hasTerminator = $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + if ($hasTerminator !== false) { + return $hasTerminator; + } + + // Otherwise, we continue with the previous TRY or CATCH clause. + $currentCloser = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), $stackPtr, true); + } else if ($tokens[$prevToken]['code'] === T_TRY) { + // If we've seen CATCH blocks without terminator statement and + // have not seen a FINALLY *with* a terminator statement, we + // don't even need to bother checking the TRY. + if ($hasCatchWithoutTerminator === true) { + return false; + } + + return $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + } else if ($tokens[$prevToken]['code'] === T_CATCH) { + // Keep track of seen catch statements without terminating statement, + // but don't bow out yet as there may still be a FINALLY clause + // with a terminating statement before the CATCH. + $hasTerminator = $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + if ($hasTerminator === false) { + $hasCatchWithoutTerminator = true; + } + + $currentCloser = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), $stackPtr, true); + } else if ($tokens[$prevToken]['code'] === T_SWITCH) { + $hasDefaultBlock = false; + $endOfSwitch = $tokens[$prevToken]['scope_closer']; + $nextCase = $prevToken; + + // We look for a terminating statement within every blocks. + while (($nextCase = $this->findNextCase($phpcsFile, ($nextCase + 1), $endOfSwitch)) !== false) { + if ($tokens[$nextCase]['code'] === T_DEFAULT) { + $hasDefaultBlock = true; + } + + $opener = $tokens[$nextCase]['scope_opener']; + + $nextCode = $phpcsFile->findNext(Tokens::$emptyTokens, ($opener + 1), $endOfSwitch, true); + if ($tokens[$nextCode]['code'] === T_CASE || $tokens[$nextCode]['code'] === T_DEFAULT) { + // This case statement has no content, so skip it. + continue; + } + + $endOfCase = $this->findNextCase($phpcsFile, ($opener + 1), $endOfSwitch); + if ($endOfCase === false) { + $endOfCase = $endOfSwitch; + } + + $hasTerminator = $this->findNestedTerminator($phpcsFile, ($opener + 1), $endOfCase); + if ($hasTerminator === false) { + return false; + } + }//end while + + // If we have not encountered a DEFAULT block by now, we cannot + // be sure that the whole statement terminates in every case. + if ($hasDefaultBlock === false) { + return false; + } + + return $hasTerminator; + } else { + return false; + }//end if + } while ($currentCloser !== false && $tokens[$currentCloser]['code'] === T_CLOSE_CURLY_BRACKET); + + return true; + } else if ($tokens[$lastToken]['code'] === T_SEMICOLON) { + // We found the last statement of the CASE. Now we want to + // check whether it is a terminating one. + $terminators = [ + T_RETURN => T_RETURN, + T_BREAK => T_BREAK, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + T_EXIT => T_EXIT, + ]; + + $terminator = $phpcsFile->findStartOfStatement(($lastToken - 1)); + if (isset($terminators[$tokens[$terminator]['code']]) === true) { + return $terminator; + } + }//end if + + return false; + + }//end findNestedTerminator() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/ClosingTagSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/ClosingTagSniff.php new file mode 100644 index 00000000..39834b38 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/ClosingTagSniff.php @@ -0,0 +1,89 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClosingTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure this file only contains PHP code. + for ($i = 0; $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['code'] === T_INLINE_HTML + && trim($tokens[$i]['content']) !== '' + ) { + return $phpcsFile->numTokens; + } + } + + // Find the last non-empty token. + for ($last = ($phpcsFile->numTokens - 1); $last > 0; $last--) { + if (trim($tokens[$last]['content']) !== '') { + break; + } + } + + if ($tokens[$last]['code'] === T_CLOSE_TAG) { + $error = 'A closing tag is not permitted at the end of a PHP file'; + $fix = $phpcsFile->addFixableError($error, $last, 'NotAllowed'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($last, $phpcsFile->eolChar); + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($last - 1), null, true); + if ($tokens[$prev]['code'] !== T_SEMICOLON + && $tokens[$prev]['code'] !== T_CLOSE_CURLY_BRACKET + && $tokens[$prev]['code'] !== T_OPEN_TAG + ) { + $phpcsFile->fixer->addContent($prev, ';'); + } + + $phpcsFile->fixer->endChangeset(); + } + + $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at end of PHP-only file', 'yes'); + } else { + $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at end of PHP-only file', 'no'); + }//end if + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/EndFileNewlineSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/EndFileNewlineSniff.php new file mode 100644 index 00000000..aed461f8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/EndFileNewlineSniff.php @@ -0,0 +1,107 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EndFileNewlineSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($phpcsFile->findNext(T_INLINE_HTML, ($stackPtr + 1)) !== false) { + return ($phpcsFile->numTokens + 1); + } + + // Skip to the end of the file. + $tokens = $phpcsFile->getTokens(); + $lastToken = ($phpcsFile->numTokens - 1); + + if ($tokens[$lastToken]['content'] === '') { + $lastToken--; + } + + // Hard-coding the expected \n in this sniff as it is PSR-2 specific and + // PSR-2 enforces the use of unix style newlines. + if (substr($tokens[$lastToken]['content'], -1) !== "\n") { + $error = 'Expected 1 newline at end of file; 0 found'; + $fix = $phpcsFile->addFixableError($error, $lastToken, 'NoneFound'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($lastToken); + } + + $phpcsFile->recordMetric($stackPtr, 'Number of newlines at EOF', '0'); + return ($phpcsFile->numTokens + 1); + } + + // Go looking for the last non-empty line. + $lastLine = $tokens[$lastToken]['line']; + if ($tokens[$lastToken]['code'] === T_WHITESPACE + || $tokens[$lastToken]['code'] === T_DOC_COMMENT_WHITESPACE + ) { + $lastCode = $phpcsFile->findPrevious([T_WHITESPACE, T_DOC_COMMENT_WHITESPACE], ($lastToken - 1), null, true); + } else { + $lastCode = $lastToken; + } + + $lastCodeLine = $tokens[$lastCode]['line']; + $blankLines = ($lastLine - $lastCodeLine + 1); + $phpcsFile->recordMetric($stackPtr, 'Number of newlines at EOF', $blankLines); + + if ($blankLines > 1) { + $error = 'Expected 1 blank line at end of file; %s found'; + $data = [$blankLines]; + $fix = $phpcsFile->addFixableError($error, $lastCode, 'TooMany', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($lastCode, rtrim($tokens[$lastCode]['content'])); + for ($i = ($lastCode + 1); $i < $lastToken; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken($lastToken, $phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + } + + // Skip the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php new file mode 100644 index 00000000..406f2794 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php @@ -0,0 +1,79 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions\FunctionCallSignatureSniff as PEARFunctionCallSignatureSniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCallSignatureSniff extends PEARFunctionCallSignatureSniff +{ + + /** + * If TRUE, multiple arguments can be defined per line in a multi-line call. + * + * @var boolean + */ + public $allowMultipleArguments = false; + + + /** + * Processes single-line calls. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function isMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $tokens) + { + // If the first argument is on a new line, this is a multi-line + // function call, even if there is only one argument. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + return true; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + $end = $phpcsFile->findEndOfStatement(($openBracket + 1), [T_COLON]); + while ($tokens[$end]['code'] === T_COMMA) { + // If the next bit of code is not on the same line, this is a + // multi-line function call. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $closeBracket, true); + if ($next === false) { + return false; + } + + if ($tokens[$next]['line'] !== $tokens[$end]['line']) { + return true; + } + + $end = $phpcsFile->findEndOfStatement($next, [T_COLON]); + } + + // We've reached the last argument, so see if the next content + // (should be the close bracket) is also on the same line. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $closeBracket, true); + if ($next !== false && $tokens[$next]['line'] !== $tokens[$end]['line']) { + return true; + } + + return false; + + }//end isMultiLineCall() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionClosingBraceSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionClosingBraceSniff.php new file mode 100644 index 00000000..1e11f02f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionClosingBraceSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FunctionClosingBraceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + // Probably an interface method. + return; + } + + $closeBrace = $tokens[$stackPtr]['scope_closer']; + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), null, true); + $found = ($tokens[$closeBrace]['line'] - $tokens[$prevContent]['line'] - 1); + + if ($found < 0) { + // Brace isn't on a new line, so not handled by us. + return; + } + + if ($found === 0) { + // All is good. + return; + } + + $error = 'Function closing brace must go on the next line following the body; found %s blank lines before brace'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpacingBeforeClose', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prevContent + 1); $i < $closeBrace; $i++) { + if ($tokens[$i]['line'] === $tokens[$prevContent]['line']) { + continue; + } + + // Don't remove any indentation before the brace. + if ($tokens[$i]['line'] === $tokens[$closeBrace]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php new file mode 100644 index 00000000..d23b8bee --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php @@ -0,0 +1,162 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Tokens; + +class MethodDeclarationSniff extends AbstractScopeSniff +{ + + + /** + * Constructs a Squiz_Sniffs_Scope_MethodScopeSniff. + */ + public function __construct() + { + parent::__construct(Tokens::$ooScopeTokens, [T_FUNCTION]); + + }//end __construct() + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * @param int $currScope The current scope opener token. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + if ($methodName[0] === '_' && isset($methodName[1]) === true && $methodName[1] !== '_') { + $error = 'Method name "%s" should not be prefixed with an underscore to indicate visibility'; + $data = [$methodName]; + $phpcsFile->addWarning($error, $stackPtr, 'Underscore', $data); + } + + $visibility = 0; + $static = 0; + $abstract = 0; + $final = 0; + + $find = (Tokens::$methodPrefixes + Tokens::$emptyTokens); + $prev = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true); + + $prefix = $stackPtr; + while (($prefix = $phpcsFile->findPrevious(Tokens::$methodPrefixes, ($prefix - 1), $prev)) !== false) { + switch ($tokens[$prefix]['code']) { + case T_STATIC: + $static = $prefix; + break; + case T_ABSTRACT: + $abstract = $prefix; + break; + case T_FINAL: + $final = $prefix; + break; + default: + $visibility = $prefix; + break; + } + } + + $fixes = []; + + if ($visibility !== 0 && $final > $visibility) { + $error = 'The final declaration must precede the visibility declaration'; + $fix = $phpcsFile->addFixableError($error, $final, 'FinalAfterVisibility'); + if ($fix === true) { + $fixes[$final] = ''; + $fixes[($final + 1)] = ''; + if (isset($fixes[$visibility]) === true) { + $fixes[$visibility] = 'final '.$fixes[$visibility]; + } else { + $fixes[$visibility] = 'final '.$tokens[$visibility]['content']; + } + } + } + + if ($visibility !== 0 && $abstract > $visibility) { + $error = 'The abstract declaration must precede the visibility declaration'; + $fix = $phpcsFile->addFixableError($error, $abstract, 'AbstractAfterVisibility'); + if ($fix === true) { + $fixes[$abstract] = ''; + $fixes[($abstract + 1)] = ''; + if (isset($fixes[$visibility]) === true) { + $fixes[$visibility] = 'abstract '.$fixes[$visibility]; + } else { + $fixes[$visibility] = 'abstract '.$tokens[$visibility]['content']; + } + } + } + + if ($static !== 0 && $static < $visibility) { + $error = 'The static declaration must come after the visibility declaration'; + $fix = $phpcsFile->addFixableError($error, $static, 'StaticBeforeVisibility'); + if ($fix === true) { + $fixes[$static] = ''; + $fixes[($static + 1)] = ''; + if (isset($fixes[$visibility]) === true) { + $fixes[$visibility] .= ' static'; + } else { + $fixes[$visibility] = $tokens[$visibility]['content'].' static'; + } + } + } + + // Batch all the fixes together to reduce the possibility of conflicts. + if (empty($fixes) === false) { + $phpcsFile->fixer->beginChangeset(); + foreach ($fixes as $stackPtr => $content) { + $phpcsFile->fixer->replaceToken($stackPtr, $content); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end processTokenWithinScope() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php new file mode 100644 index 00000000..bf37af09 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php @@ -0,0 +1,100 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Namespaces; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class NamespaceDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_NAMESPACE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$nextNonEmpty]['code'] === T_NS_SEPARATOR) { + // Namespace keyword as operator. Not a declaration. + return; + } + + $end = $phpcsFile->findEndOfStatement($stackPtr); + for ($i = ($end + 1); $i < ($phpcsFile->numTokens - 1); $i++) { + if ($tokens[$i]['line'] === $tokens[$end]['line']) { + continue; + } + + break; + } + + // The $i var now points to the first token on the line after the + // namespace declaration, which must be a blank line. + $next = $phpcsFile->findNext(T_WHITESPACE, $i, $phpcsFile->numTokens, true); + if ($next === false) { + return; + } + + $diff = ($tokens[$next]['line'] - $tokens[$i]['line']); + if ($diff === 1) { + return; + } + + if ($diff < 0) { + $diff = 0; + } + + $error = 'There must be one blank line after the namespace declaration'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'BlankLineAfter'); + + if ($fix === true) { + if ($diff === 0) { + $phpcsFile->fixer->addNewlineBefore($i); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($x = $i; $x < $next; $x++) { + if ($tokens[$x]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewline($i); + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php new file mode 100644 index 00000000..aba9caa7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php @@ -0,0 +1,297 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Namespaces; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UseDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_USE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->shouldIgnoreUse($phpcsFile, $stackPtr) === true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + // One space after the use keyword. + if ($tokens[($stackPtr + 1)]['content'] !== ' ') { + $error = 'There must be a single space after the USE keyword'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterUse'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + + // Only one USE declaration allowed per statement. + $next = $phpcsFile->findNext([T_COMMA, T_SEMICOLON, T_OPEN_USE_GROUP, T_CLOSE_TAG], ($stackPtr + 1)); + if ($next !== false + && $tokens[$next]['code'] !== T_SEMICOLON + && $tokens[$next]['code'] !== T_CLOSE_TAG + ) { + $error = 'There must be one USE keyword per declaration'; + + if ($tokens[$next]['code'] === T_COMMA) { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MultipleDeclarations'); + if ($fix === true) { + switch ($tokens[($stackPtr + 2)]['content']) { + case 'const': + $baseUse = 'use const'; + break; + case 'function': + $baseUse = 'use function'; + break; + default: + $baseUse = 'use'; + } + + if ($tokens[($next + 1)]['code'] !== T_WHITESPACE) { + $baseUse .= ' '; + } + + $phpcsFile->fixer->replaceToken($next, ';'.$phpcsFile->eolChar.$baseUse); + } + } else { + $closingCurly = $phpcsFile->findNext(T_CLOSE_USE_GROUP, ($next + 1)); + if ($closingCurly === false) { + // Parse error or live coding. Not auto-fixable. + $phpcsFile->addError($error, $stackPtr, 'MultipleDeclarations'); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MultipleDeclarations'); + if ($fix === true) { + $baseUse = rtrim($phpcsFile->getTokensAsString($stackPtr, ($next - $stackPtr))); + $lastNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($closingCurly - 1), null, true); + + $phpcsFile->fixer->beginChangeset(); + + // Remove base use statement. + for ($i = $stackPtr; $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + if (preg_match('`^[\r\n]+$`', $tokens[($next + 1)]['content']) === 1) { + $phpcsFile->fixer->replaceToken(($next + 1), ''); + } + + // Convert grouped use statements into full use statements. + do { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), $closingCurly, true); + if ($next === false) { + // Group use statement with trailing comma after last item. + break; + } + + $nonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($next - 1), null, true); + for ($i = ($nonWhitespace + 1); $i < $next; $i++) { + if (preg_match('`^[\r\n]+$`', $tokens[$i]['content']) === 1) { + // Preserve new lines. + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + if ($tokens[$next]['content'] === 'const' || $tokens[$next]['content'] === 'function') { + $phpcsFile->fixer->addContentBefore($next, 'use '); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), $closingCurly, true); + $phpcsFile->fixer->addContentBefore($next, str_replace('use ', '', $baseUse)); + } else { + $phpcsFile->fixer->addContentBefore($next, $baseUse); + } + + $next = $phpcsFile->findNext(T_COMMA, ($next + 1), $closingCurly); + if ($next !== false) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), $closingCurly, true); + if ($nextNonEmpty !== false && $tokens[$nextNonEmpty]['line'] === $tokens[$next]['line']) { + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($nextNonEmpty - 1), $next, true); + if ($prevNonWhitespace === $next) { + $phpcsFile->fixer->replaceToken($next, ';'.$phpcsFile->eolChar); + } else { + $phpcsFile->fixer->replaceToken($next, ';'); + $phpcsFile->fixer->addNewline($prevNonWhitespace); + } + } else { + // Last item with trailing comma or next item already on new line. + $phpcsFile->fixer->replaceToken($next, ';'); + } + } else { + // Last item without trailing comma. + $phpcsFile->fixer->addContent($lastNonWhitespace, ';'); + } + } while ($next !== false); + + // Remove closing curly,semi-colon and any whitespace between last child and closing curly. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($closingCurly + 1), null, true); + if ($next === false || $tokens[$next]['code'] !== T_SEMICOLON) { + // Parse error, forgotten semi-colon. + $next = $closingCurly; + } + + for ($i = ($lastNonWhitespace + 1); $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + }//end if + }//end if + + // Make sure this USE comes after the first namespace declaration. + $prev = $phpcsFile->findPrevious(T_NAMESPACE, ($stackPtr - 1)); + if ($prev === false) { + $next = $phpcsFile->findNext(T_NAMESPACE, ($stackPtr + 1)); + if ($next !== false) { + $error = 'USE declarations must go after the namespace declaration'; + $phpcsFile->addError($error, $stackPtr, 'UseBeforeNamespace'); + } + } + + // Only interested in the last USE statement from here onwards. + $nextUse = $phpcsFile->findNext(T_USE, ($stackPtr + 1)); + while ($this->shouldIgnoreUse($phpcsFile, $nextUse) === true) { + $nextUse = $phpcsFile->findNext(T_USE, ($nextUse + 1)); + if ($nextUse === false) { + break; + } + } + + if ($nextUse !== false) { + return; + } + + $end = $phpcsFile->findNext([T_SEMICOLON, T_CLOSE_USE_GROUP, T_CLOSE_TAG], ($stackPtr + 1)); + if ($end === false) { + return; + } + + if ($tokens[$end]['code'] === T_CLOSE_USE_GROUP) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($tokens[$nextNonEmpty]['code'] === T_SEMICOLON) { + $end = $nextNonEmpty; + } + } + + // Find either the start of the next line or the beginning of the next statement, + // whichever comes first. + for ($end = ++$end; $end < $phpcsFile->numTokens; $end++) { + if (isset(Tokens::$emptyTokens[$tokens[$end]['code']]) === false) { + break; + } + + if ($tokens[$end]['column'] === 1) { + // Reached the next line. + break; + } + } + + --$end; + + if (($tokens[$end]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$end]['code']]) === true) + && substr($tokens[$end]['content'], 0, 2) === '/*' + && substr($tokens[$end]['content'], -2) !== '*/' + ) { + // Multi-line block comments are not allowed as trailing comment after a use statement. + --$end; + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($end + 1), null, true); + + if ($next === false || $tokens[$next]['code'] === T_CLOSE_TAG) { + return; + } + + $diff = ($tokens[$next]['line'] - $tokens[$end]['line'] - 1); + if ($diff !== 1) { + if ($diff < 0) { + $diff = 0; + } + + $error = 'There must be one blank line after the last USE statement; %s found;'; + $data = [$diff]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterLastUse', $data); + if ($fix === true) { + if ($diff === 0) { + $phpcsFile->fixer->addNewline($end); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($end + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewline($end); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end process() + + + /** + * Check if this use statement is part of the namespace block. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return bool + */ + private function shouldIgnoreUse($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore USE keywords inside closures and during live coding. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next === false || $tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + return true; + } + + // Ignore USE keywords for traits. + if ($phpcsFile->hasCondition($stackPtr, [T_CLASS, T_TRAIT, T_ENUM]) === true) { + return true; + } + + return false; + + }//end shouldIgnoreUse() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc new file mode 100644 index 00000000..13e596e1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc @@ -0,0 +1,241 @@ +anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +class A extends B + implements C +{ +} + +class C2 +{ + +} // phpcs:ignore Standard.Category.Sniff + +interface I1 extends + Foo +{ +} + +interface I2 extends + Bar +{ +} + +interface I3 extends + Foo, + Bar +{ +} + +class C1 extends + Foo +{ +} + +class C2 extends + Bar +{ +} + +class C3 extends Foo implements + Bar +{ +} + +class C4 extends Foo implements + Bar +{ +} + +class C5 extends Foo implements + Bar, + Baz +{ +} + +class C6 extends \Foo\Bar implements + \Baz\Bar +{ +} + +interface I4 extends + \Baz + \Bar +{ +} + +interface I5 extends /* comment */ + \Foo\Bar +{ +} + +interface I6 extends // comment + \Foo\Bar +{ +} + +class C7 extends // comment + \Foo\Bar implements \Baz\Bar +{ +} + +class +C8 +{ +} + +foo(new class { +}); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc.fixed new file mode 100644 index 00000000..3ee394e7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc.fixed @@ -0,0 +1,234 @@ +anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +class A extends B implements C +{ +} + +class C2 +{ + +} // phpcs:ignore Standard.Category.Sniff + +interface I1 extends + Foo +{ +} + +interface I2 extends + Bar +{ +} + +interface I3 extends + Foo, + Bar +{ +} + +class C1 extends Foo +{ +} + +class C2 extends Bar +{ +} + +class C3 extends Foo implements + Bar +{ +} + +class C4 extends Foo implements + Bar +{ +} + +class C5 extends Foo implements + Bar, + Baz +{ +} + +class C6 extends \Foo\Bar implements + \Baz\Bar +{ +} + +interface I4 extends + \Baz\Bar +{ +} + +interface I5 extends /* comment */ + \Foo\Bar +{ +} + +interface I6 extends // comment + \Foo\Bar +{ +} + +class C7 extends \Foo\Bar implements \Baz\Bar // comment +{ +} + +class C8 +{ +} + +foo(new class { +}); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.php new file mode 100644 index 00000000..635ac710 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.php @@ -0,0 +1,86 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 7 => 3, + 12 => 1, + 13 => 1, + 17 => 1, + 19 => 2, + 20 => 1, + 21 => 1, + 22 => 1, + 25 => 1, + 27 => 2, + 34 => 1, + 35 => 2, + 44 => 1, + 45 => 1, + 63 => 1, + 95 => 1, + 116 => 1, + 118 => 1, + 119 => 1, + 124 => 1, + 130 => 2, + 131 => 1, + 158 => 1, + 168 => 1, + 178 => 1, + 179 => 1, + 184 => 1, + 189 => 1, + 194 => 1, + 204 => 1, + 205 => 1, + 210 => 1, + 215 => 2, + 216 => 1, + 231 => 2, + 235 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc new file mode 100644 index 00000000..33bec44e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc @@ -0,0 +1,83 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class PropertyDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 9 => 2, + 10 => 1, + 11 => 1, + 17 => 1, + 18 => 1, + 23 => 1, + 38 => 1, + 41 => 1, + 42 => 1, + 50 => 2, + 51 => 1, + 55 => 1, + 56 => 1, + 61 => 1, + 62 => 1, + 68 => 1, + 69 => 1, + 71 => 1, + 72 => 1, + 76 => 1, + 80 => 1, + 82 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 13 => 1, + 14 => 1, + 15 => 1, + 53 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc new file mode 100644 index 00000000..542ab3cf --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc @@ -0,0 +1,81 @@ + $that) {} +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 0 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 0 + +$binary = b"binary string"; + +if ($expr1 + && $expr2 ) { +} + +if ($expr1 + && $expr2 /* comment */ ) { +} + +if ($expr1 + && $expr2 + /* comment */ ) { +} + +$r = match ($x) {}; +$r = match ( $x ) {}; + +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 1 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 1 +$r = match ($x) {}; +$r = match ( $x ) {}; +$r = match ( $x ) {}; +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 0 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 0 diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed new file mode 100644 index 00000000..a29534be --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed @@ -0,0 +1,80 @@ + $that ) {} +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 0 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 0 + +$binary = b"binary string"; + +if ($expr1 + && $expr2) { +} + +if ($expr1 + && $expr2 /* comment */) { +} + +if ($expr1 + && $expr2 + /* comment */) { +} + +$r = match ($x) {}; +$r = match ($x) {}; + +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 1 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 1 +$r = match ( $x ) {}; +$r = match ( $x ) {}; +$r = match ( $x ) {}; +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 0 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 0 diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.php new file mode 100644 index 00000000..35d5e515 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ControlStructureSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 14 => 2, + 26 => 2, + 27 => 2, + 31 => 1, + 51 => 2, + 53 => 2, + 60 => 1, + 64 => 1, + 69 => 1, + 73 => 2, + 77 => 2, + 79 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc new file mode 100644 index 00000000..778659c8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc.fixed new file mode 100644 index 00000000..4a7bfdc2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc.fixed @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.php new file mode 100644 index 00000000..935205b4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ElseIfDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 4 => 1, + 12 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc new file mode 100644 index 00000000..2ca60a93 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc @@ -0,0 +1,598 @@ + 0) { + return 0; + } else { + return 1; + } + case 2: + return 2; +} + +// ERROR: No else clause +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } elseif ($bar < 0) { + return 1; + } + case 2: + return 2; +} + +// OK: No fall-through present +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } elseif ($bar < 0) { + return 1; + } +} + +// ERROR: No else clause (nested) +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } else { + if ($foo > $bar) { + continue; + } + } + case 2: + return 2; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } else { + if ($foo > $bar) { + continue; + } else { + break; + } + } + case 2: + return 2; +} + +// ERROR: Non-termination IF clause +switch ($foo) { + case 1: + if ($bar > 0) { + $offset = 0; + } else { + break; + } + case 2: + return 2; +} + +// ERROR: Non-termination IF clause (nested) +switch ($foo) { + case 1: + if ($bar > 0) { + continue; + } else { + if ($foo > $bar) { + $offset = 0; + } else { + break; + } + } + case 2: + return 2; +} + +switch ($sContext) +{ + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +$foo = $foo ? + function () { + switch ($a) { + case 'a': + break; + } + } : + null; + +switch ($foo) { +case Foo::INTERFACE: + echo '1'; + return self::INTERFACE; +case Foo::TRAIT: +case Foo::ARRAY: + echo '1'; + return self::VALUE; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return 1; + default: + return 3; + } + case 2: + return 2; +} + +// KO: Not every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return; + } + case 2: + return 2; +} + +// KO: Not every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return; + default: + $a = 1; + } + case 2: + return 2; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return 1; + default: + throw new \Exception(); + } + case 2: + return 2; +} + +switch ($foo) { + case 1: + // phpcs:ignore + case 2: + return 1; + case 3: + return 2; +} + +// Issue 3352. +switch ( $test ) { + case 2: // comment followed by empty line + + break; + + case 3: /* phpcs:ignore Stnd.Cat.SniffName -- Verify correct handling of ignore comments. */ + + + + break; + + case 4: /** inline docblock */ + + + + break; + + case 5: /* checking how it handles */ /* two trailing comments */ + + break; + + case 6: + // Comment as first content of the body. + + break; + + case 7: + /* phpcs:ignore Stnd.Cat.SniffName -- Verify correct handling of ignore comments at start of body. */ + + break; + + case 8: + /** inline docblock */ + + break; +} + +// Handle comments correctly. +switch ($foo) { + case 1: + if ($bar > 0) { + doSomething(); + } + // Comment + else { + return 1; + } + case 2: + return 2; +} + +switch ($foo) { + case 1: + if ($bar > 0) /*comment*/ { + return doSomething(); + } + else { + return 1; + } + case 2: + return 2; +} + +// Issue #3297. +// Okay - finally will always be executed, so all branches are covered by the `return` in finally. +switch ( $a ) { + case 1: + try { + doSomething(); + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + doSomething(); + } finally { + return true; + } + default: + $other = $code; + break; +} + +// Okay - all - non-finally - branches have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) /*comment*/ { + return true; + } + // Comment + catch (AnotherException $e) { + return true; + } finally { + doSomething(); + } + default: + $other = $code; + break; +} + +// Okay - finally will always be executed, so all branches are covered by the `return` in finally. +// Non-standard structure order. +switch ( $a ) { + case 1: + try { + doSomething(); + } catch (Exception $e) { + doSomething(); + } finally { + return true; + } catch (AnotherException $e) { + doSomething(); + } + default: + $other = $code; + break; +} + +// Okay - all - non-finally - branches have a terminating statement. +// Non-standard structure order. +switch ( $a ) { + case 1: + try { + return false; + } finally { + doSomething(); + } catch (MyException $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// All okay, no finally. Any exception still uncaught will terminate the case anyhow, so we're good. +switch ( $a ) { + case 1: + try { + return false; + } catch (MyException $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// All okay, no catch +switch ( $a ) { + case 1: + try { + return true; + } finally { + doSomething(); + } + case 2: + $other = $code; + break; +} + +// All okay, try-catch nested in if. +switch ( $a ) { + case 1: + if ($a) { + try { + return true; // Comment. + } catch (MyException $e) { + throw new Exception($e->getMessage()); + } + } else { + return true; + } + case 2: + $other = $code; + break; +} + +// Missing fall-through comment. +switch ( $a ) { + case 1: + try { + doSomething(); + } finally { + doSomething(); + } + case 2: + $other = $code; + break; +} + +// Missing fall-through comment. One of the catches does not have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + return true; + } finally { + doSomething(); + } + default: + $other = $code; + break; +} + +// Missing fall-through comment. Try does not have a terminating statement. +switch ( $a ) { + case 1: + try { + doSomething(); + } finally { + doSomething(); + } catch (Exception $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// Missing fall-through comment. One of the catches does not have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// Issue 3550 - comment after terminating statement. +switch (rand()) { + case 1: + if (rand() === 1) { + break; + } else { + break; // comment + } + default: + break; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc.fixed new file mode 100644 index 00000000..bbc8b7c4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc.fixed @@ -0,0 +1,593 @@ + 0) { + return 0; + } else { + return 1; + } + case 2: + return 2; +} + +// ERROR: No else clause +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } elseif ($bar < 0) { + return 1; + } + case 2: + return 2; +} + +// OK: No fall-through present +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } elseif ($bar < 0) { + return 1; + } +} + +// ERROR: No else clause (nested) +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } else { + if ($foo > $bar) { + continue; + } + } + case 2: + return 2; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } else { + if ($foo > $bar) { + continue; + } else { + break; + } + } + case 2: + return 2; +} + +// ERROR: Non-termination IF clause +switch ($foo) { + case 1: + if ($bar > 0) { + $offset = 0; + } else { + break; + } + case 2: + return 2; +} + +// ERROR: Non-termination IF clause (nested) +switch ($foo) { + case 1: + if ($bar > 0) { + continue; + } else { + if ($foo > $bar) { + $offset = 0; + } else { + break; + } + } + case 2: + return 2; +} + +switch ($sContext) +{ + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +$foo = $foo ? + function () { + switch ($a) { + case 'a': + break; + } + } : + null; + +switch ($foo) { +case Foo::INTERFACE: + echo '1'; + return self::INTERFACE; +case Foo::TRAIT: +case Foo::ARRAY: + echo '1'; + return self::VALUE; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return 1; + default: + return 3; + } + case 2: + return 2; +} + +// KO: Not every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return; + } + case 2: + return 2; +} + +// KO: Not every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return; + default: + $a = 1; + } + case 2: + return 2; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return 1; + default: + throw new \Exception(); + } + case 2: + return 2; +} + +switch ($foo) { + case 1: + // phpcs:ignore + case 2: + return 1; + case 3: + return 2; +} + +// Issue 3352. +switch ( $test ) { + case 2: // comment followed by empty line + break; + + case 3: /* phpcs:ignore Stnd.Cat.SniffName -- Verify correct handling of ignore comments. */ + break; + + case 4: /** inline docblock */ + break; + + case 5: /* checking how it handles */ /* two trailing comments */ + break; + + case 6: + // Comment as first content of the body. + + break; + + case 7: + /* phpcs:ignore Stnd.Cat.SniffName -- Verify correct handling of ignore comments at start of body. */ + + break; + + case 8: + /** inline docblock */ + + break; +} + +// Handle comments correctly. +switch ($foo) { + case 1: + if ($bar > 0) { + doSomething(); + } + // Comment + else { + return 1; + } + case 2: + return 2; +} + +switch ($foo) { + case 1: + if ($bar > 0) /*comment*/ { + return doSomething(); + } + else { + return 1; + } + case 2: + return 2; +} + +// Issue #3297. +// Okay - finally will always be executed, so all branches are covered by the `return` in finally. +switch ( $a ) { + case 1: + try { + doSomething(); + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + doSomething(); + } finally { + return true; + } + default: + $other = $code; + break; +} + +// Okay - all - non-finally - branches have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) /*comment*/ { + return true; + } + // Comment + catch (AnotherException $e) { + return true; + } finally { + doSomething(); + } + default: + $other = $code; + break; +} + +// Okay - finally will always be executed, so all branches are covered by the `return` in finally. +// Non-standard structure order. +switch ( $a ) { + case 1: + try { + doSomething(); + } catch (Exception $e) { + doSomething(); + } finally { + return true; + } catch (AnotherException $e) { + doSomething(); + } + default: + $other = $code; + break; +} + +// Okay - all - non-finally - branches have a terminating statement. +// Non-standard structure order. +switch ( $a ) { + case 1: + try { + return false; + } finally { + doSomething(); + } catch (MyException $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// All okay, no finally. Any exception still uncaught will terminate the case anyhow, so we're good. +switch ( $a ) { + case 1: + try { + return false; + } catch (MyException $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// All okay, no catch +switch ( $a ) { + case 1: + try { + return true; + } finally { + doSomething(); + } + case 2: + $other = $code; + break; +} + +// All okay, try-catch nested in if. +switch ( $a ) { + case 1: + if ($a) { + try { + return true; // Comment. + } catch (MyException $e) { + throw new Exception($e->getMessage()); + } + } else { + return true; + } + case 2: + $other = $code; + break; +} + +// Missing fall-through comment. +switch ( $a ) { + case 1: + try { + doSomething(); + } finally { + doSomething(); + } + case 2: + $other = $code; + break; +} + +// Missing fall-through comment. One of the catches does not have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + return true; + } finally { + doSomething(); + } + default: + $other = $code; + break; +} + +// Missing fall-through comment. Try does not have a terminating statement. +switch ( $a ) { + case 1: + try { + doSomething(); + } finally { + doSomething(); + } catch (Exception $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// Missing fall-through comment. One of the catches does not have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// Issue 3550 - comment after terminating statement. +switch (rand()) { + case 1: + if (rand() === 1) { + break; + } else { + break; // comment + } + default: + break; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.php new file mode 100644 index 00000000..0cd946d8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.php @@ -0,0 +1,81 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SwitchDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 1, + 11 => 1, + 14 => 1, + 16 => 1, + 20 => 1, + 23 => 1, + 29 => 1, + 33 => 1, + 37 => 2, + 108 => 2, + 109 => 1, + 111 => 1, + 113 => 2, + 114 => 1, + 128 => 1, + 141 => 1, + 172 => 1, + 194 => 1, + 224 => 1, + 236 => 1, + 260 => 1, + 300 => 1, + 311 => 1, + 346 => 1, + 350 => 1, + 356 => 1, + 362 => 1, + 384 => 1, + 528 => 1, + 541 => 1, + 558 => 1, + 575 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc new file mode 100644 index 00000000..738e70e9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc @@ -0,0 +1,12 @@ + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc.fixed new file mode 100644 index 00000000..f70b9eba --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc.fixed @@ -0,0 +1,12 @@ + + +
    + +
    \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.3.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.3.inc new file mode 100644 index 00000000..d6a86175 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.3.inc @@ -0,0 +1,7 @@ + + +A: +B: +C: \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc new file mode 100644 index 00000000..dd103cde --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc @@ -0,0 +1 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc.fixed new file mode 100644 index 00000000..1058f1f3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc.fixed @@ -0,0 +1 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.5.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.5.inc.fixed new file mode 100644 index 00000000..93d55fbd --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.5.inc.fixed @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.6.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.6.inc.fixed new file mode 100644 index 00000000..534574d4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.6.inc.fixed @@ -0,0 +1,5 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.7.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.7.inc.fixed new file mode 100644 index 00000000..68e7d8ce --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.7.inc.fixed @@ -0,0 +1,5 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClosingTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ClosingTagUnitTest.1.inc': + return [11 => 1]; + + case 'ClosingTagUnitTest.4.inc': + case 'ClosingTagUnitTest.5.inc': + return [1 => 1]; + + case 'ClosingTagUnitTest.6.inc': + case 'ClosingTagUnitTest.7.inc': + return [5 => 1]; + + default: + return []; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.1.inc new file mode 100644 index 00000000..ca2a7493 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.1.inc @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.12.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.12.inc.fixed new file mode 100644 index 00000000..d3c19fee --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.12.inc.fixed @@ -0,0 +1 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.13.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.13.inc new file mode 100644 index 00000000..fa2f476a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.13.inc @@ -0,0 +1,5 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.2.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.2.inc new file mode 100644 index 00000000..1254e4a5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.2.inc @@ -0,0 +1,2 @@ + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.5.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.5.inc new file mode 100644 index 00000000..c3a59b67 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.5.inc @@ -0,0 +1,6 @@ + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EndFileNewlineUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'EndFileNewlineUnitTest.1.inc': + case 'EndFileNewlineUnitTest.3.inc': + case 'EndFileNewlineUnitTest.6.inc': + case 'EndFileNewlineUnitTest.7.inc': + case 'EndFileNewlineUnitTest.9.inc': + case 'EndFileNewlineUnitTest.10.inc': + return [2 => 1]; + case 'EndFileNewlineUnitTest.11.inc': + case 'EndFileNewlineUnitTest.12.inc': + case 'EndFileNewlineUnitTest.13.inc': + return [1 => 1]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc new file mode 100644 index 00000000..1ca477d0 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc @@ -0,0 +1,267 @@ +get('/hello/{name}', function ($name) use ($app) { + return 'Hello '.$app->escape($name); +}, array( + '1', + '2', + '3', +)); + +// error +somefunction2($foo, $bar, [ + // ... + ], +$baz); + +// ok +somefunction3(// ... + $foo, + $bar, + [ + // ... + ], + $baz +); + +// ok +somefunction4(' + this should not + give an error + because it\'s actually + one line call + with multi-line string +'); + +// ok +somefunction5("hey, +multi-line string with some +extra args", $foo, 12); + +// error +somefunction6(' + but args in a new line + are not ok… + ', + $foo +); + +$this->setFoo(true + ? 1 + : 2, false, array( + 'value', + 'more')); + +$this->setFoo('some' + . 'long' + . 'text', 'string'); + +foo(bar(), $a); +foo();bar(); + +foo( + true +); + +myFunction(<< function ($x) { + return true; + }, + 'baz' => false + ) +); +$qux = array_filter( + $quux, function ($x) { + return $x; + } +); + +$this->listeners[] = $events->getSharedManager()->attach( + 'Zend\Mvc\Application', MvcEvent::EVENT_DISPATCH, [$this, 'selectLayout'], 100 +); + +// phpcs:set PSR2.Methods.FunctionCallSignature requiredSpacesBeforeClose 1 +foo('Testing + multiline text' + ); + +foo('Testing + multiline text: ' // . $text + ); + +foo('Testing + multiline text: ' /* . $text */ + ); + +foo('Testing + multiline text: ' /* . $text */ + // . $other_text + ); + +foo('Testing + multiline text: ' /* + . $text +// . $text2 + */ + ); +// phpcs:set PSR2.Methods.FunctionCallSignature requiredSpacesBeforeClose 0 + +foo('Testing + multiline text' +); + +foo('Testing + multiline text' + ); + +foo('Testing + multiline text' // hello +); + +foo('Testing + multiline text' /* hello */ +); + +foo('Testing + multiline text' + // hello +); + +foo('Testing + multiline text' + /* hello */ +); + +$var = foo('Testing + multiline' + // hi + ) + foo('Testing + multiline' + // hi + ) +; + +class Test +{ + public function getInstance() + { + return new static( + 'arg', + 'foo' + ); + } + + public function getSelf() + { + return new self( + 'a', 'b', 'c' + ); + } +} + +$x = $var('y', + 'x'); + +$obj->{$x}(1, +2); + +(function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})( + 'a','b' +)('c', + 'd'); + +return trim(preg_replace_callback( + // sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) + // /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search + )); + +return trim(preg_replace_callback( +// sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) +// /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ +sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), +function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; +}, +$search +)); + +// PHP 8.0 named parameters. +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +array_fill_keys( + keys: range( 1, + 12, + ), value: true, +); + +// phpcs:set PSR2.Methods.FunctionCallSignature allowMultipleArguments true +array_fill_keys( + keys: range( 1, + 12, + ), value: true, +); +// phpcs:set PSR2.Methods.FunctionCallSignature allowMultipleArguments false diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed new file mode 100644 index 00000000..dc383ed2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed @@ -0,0 +1,283 @@ +get('/hello/{name}', function ($name) use ($app) { + return 'Hello '.$app->escape($name); +}, array( + '1', + '2', + '3', +)); + +// error +somefunction2( + $foo, + $bar, + [ + // ... + ], + $baz +); + +// ok +somefunction3(// ... + $foo, + $bar, + [ + // ... + ], + $baz +); + +// ok +somefunction4(' + this should not + give an error + because it\'s actually + one line call + with multi-line string +'); + +// ok +somefunction5("hey, +multi-line string with some +extra args", $foo, 12); + +// error +somefunction6( + ' + but args in a new line + are not ok… + ', + $foo +); + +$this->setFoo(true + ? 1 + : 2, false, array( + 'value', + 'more')); + +$this->setFoo('some' + . 'long' + . 'text', 'string'); + +foo(bar(), $a); +foo();bar(); + +foo( + true +); + +myFunction(<< function ($x) { + return true; + }, + 'baz' => false + ) +); +$qux = array_filter( + $quux, + function ($x) { + return $x; + } +); + +$this->listeners[] = $events->getSharedManager()->attach( + 'Zend\Mvc\Application', + MvcEvent::EVENT_DISPATCH, + [$this, 'selectLayout'], + 100 +); + +// phpcs:set PSR2.Methods.FunctionCallSignature requiredSpacesBeforeClose 1 +foo('Testing + multiline text' ); + +foo('Testing + multiline text: ' ); // . $text + + +foo('Testing + multiline text: ' /* . $text */ ); + +foo('Testing + multiline text: ' /* . $text */ ); + // . $other_text + + +foo('Testing + multiline text: ' /* + . $text +// . $text2 + */ ); +// phpcs:set PSR2.Methods.FunctionCallSignature requiredSpacesBeforeClose 0 + +foo('Testing + multiline text'); + +foo('Testing + multiline text'); + +foo('Testing + multiline text'); // hello + + +foo('Testing + multiline text' /* hello */); + +foo('Testing + multiline text'); + // hello + + +foo('Testing + multiline text' + /* hello */); + +$var = foo('Testing + multiline') + // hi + + foo('Testing + multiline'); + // hi + + +class Test +{ + public function getInstance() + { + return new static( + 'arg', + 'foo' + ); + } + + public function getSelf() + { + return new self( + 'a', + 'b', + 'c' + ); + } +} + +$x = $var( + 'y', + 'x' +); + +$obj->{$x}( + 1, + 2 +); + +(function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})( + 'a', + 'b' +)( + 'c', + 'd' +); + +return trim(preg_replace_callback( + // sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) + // /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search +)); + +return trim(preg_replace_callback( +// sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) +// /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search +)); + +// PHP 8.0 named parameters. +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +// phpcs:set PSR2.Methods.FunctionCallSignature allowMultipleArguments true +array_fill_keys( + keys: range( + 1, + 12, + ), value: true, +); +// phpcs:set PSR2.Methods.FunctionCallSignature allowMultipleArguments false diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php new file mode 100644 index 00000000..1d878258 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php @@ -0,0 +1,94 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Methods; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionCallSignatureUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 18 => 3, + 21 => 1, + 48 => 1, + 87 => 1, + 90 => 1, + 91 => 1, + 103 => 1, + 111 => 1, + 117 => 4, + 123 => 1, + 127 => 1, + 131 => 1, + 136 => 1, + 143 => 1, + 148 => 1, + 152 => 1, + 156 => 1, + 160 => 1, + 165 => 1, + 170 => 1, + 175 => 1, + 178 => 2, + 186 => 1, + 187 => 1, + 194 => 3, + 199 => 1, + 200 => 2, + 202 => 1, + 203 => 1, + 210 => 2, + 211 => 1, + 212 => 2, + 217 => 1, + 218 => 1, + 227 => 1, + 228 => 1, + 233 => 1, + 234 => 1, + 242 => 1, + 243 => 1, + 256 => 1, + 257 => 1, + 258 => 1, + 263 => 1, + 264 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.inc new file mode 100644 index 00000000..7bf667e6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.inc @@ -0,0 +1,70 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Methods; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionClosingBraceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 16 => 1, + 23 => 1, + 40 => 1, + 47 => 1, + 63 => 1, + 70 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc new file mode 100644 index 00000000..096b44bc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Methods; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MethodDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 11 => 1, + 13 => 1, + 15 => 3, + 24 => 1, + 34 => 1, + 36 => 1, + 38 => 1, + 40 => 3, + 50 => 1, + 52 => 1, + 54 => 1, + 56 => 3, + 63 => 2, + 73 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 5 => 1, + 21 => 1, + 30 => 1, + 46 => 1, + 63 => 1, + 70 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.inc new file mode 100644 index 00000000..70339339 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.inc @@ -0,0 +1,26 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Namespaces; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class NamespaceDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 6 => 1, + 9 => 1, + 17 => 1, + 19 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.1.inc new file mode 100644 index 00000000..61befc9e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.1.inc @@ -0,0 +1,43 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.2.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.2.inc.fixed new file mode 100644 index 00000000..6579613b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.2.inc.fixed @@ -0,0 +1,27 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.3.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.3.inc new file mode 100644 index 00000000..8b290950 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.3.inc @@ -0,0 +1,16 @@ + +

    diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.5.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.5.inc new file mode 100644 index 00000000..1fdaccd3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.5.inc @@ -0,0 +1,47 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.7.inc b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.7.inc new file mode 100644 index 00000000..dee56869 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.7.inc @@ -0,0 +1 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Namespaces; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class UseDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'UseDeclarationUnitTest.2.inc': + return [ + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 16 => 1, + ]; + case 'UseDeclarationUnitTest.3.inc': + return [ + 4 => 1, + 6 => 1, + ]; + case 'UseDeclarationUnitTest.5.inc': + return [ + 5 => 1, + 6 => 1, + 8 => 1, + 14 => 1, + 17 => 1, + 18 => 1, + 19 => 1, + 21 => 1, + 28 => 1, + 30 => 1, + 35 => 1, + ]; + case 'UseDeclarationUnitTest.10.inc': + case 'UseDeclarationUnitTest.11.inc': + case 'UseDeclarationUnitTest.12.inc': + case 'UseDeclarationUnitTest.13.inc': + case 'UseDeclarationUnitTest.14.inc': + case 'UseDeclarationUnitTest.16.inc': + case 'UseDeclarationUnitTest.17.inc': + return [2 => 1]; + case 'UseDeclarationUnitTest.15.inc': + return [ + 3 => 1, + 4 => 1, + 5 => 1, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/ruleset.xml b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/ruleset.xml new file mode 100644 index 00000000..ba5bd4e0 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/ruleset.xml @@ -0,0 +1,218 @@ + + + The PSR-2 coding standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + 0 + + + 0 + + + + + + + 0 + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayBracketSpacingStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayBracketSpacingStandard.xml new file mode 100644 index 00000000..fc6ccbd6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayBracketSpacingStandard.xml @@ -0,0 +1,19 @@ + + + + + + + ['bar']; +]]> + + + [ 'bar' ]; +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayDeclarationStandard.xml new file mode 100644 index 00000000..ce4b9ae6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayDeclarationStandard.xml @@ -0,0 +1,117 @@ + + + + + + array keyword must be lowercase. + ]]> + + + + + + + + + + + array keyword. + ]]> + + + + 'value1', + 'key2' => 'value2', + ); + ]]> + + + 'value1', + 'key2' => 'value2', + ); + ]]> + + + + array keyword. The closing parenthesis must be aligned with the start of the array keyword. + ]]> + + + + 'key1' => 'value1', + 'key2' => 'value2', + ); + ]]> + + + 'key1' => 'value1', + 'key2' => 'value2', +); + ]]> + + + + + + + + => 'ValueTen', + 'keyTwenty' => 'ValueTwenty', + ); + ]]> + + + => 'ValueTen', + 'keyTwenty' => 'ValueTwenty', + ); + ]]> + + + + + + + + 'value1', + 'key2' => 'value2', + 'key3' => 'value3', + ); + ]]> + + + 'value1', + 'key2' => 'value2', + 'key3' => 'value3' + ); + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/LowercaseClassKeywordsStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/LowercaseClassKeywordsStandard.xml new file mode 100644 index 00000000..89fcb5de --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/LowercaseClassKeywordsStandard.xml @@ -0,0 +1,23 @@ + + + + + + + final class Foo extends Bar +{ +} +]]> + + + Final Class Foo Extends Bar +{ +} +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/SelfMemberReferenceStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/SelfMemberReferenceStandard.xml new file mode 100644 index 00000000..59d193ff --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/SelfMemberReferenceStandard.xml @@ -0,0 +1,63 @@ + + + + + + + self::foo(); +]]> + + + SELF::foo(); +]]> + + + + + ::foo(); +]]> + + + :: foo(); +]]> + + + + + self::bar(); + } +} +]]> + + + Foo +{ + public static function bar() + { + } + + public static function baz() + { + Foo::bar(); + } +} +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/DocCommentAlignmentStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/DocCommentAlignmentStandard.xml new file mode 100644 index 00000000..414b89a3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/DocCommentAlignmentStandard.xml @@ -0,0 +1,39 @@ + + + + + + + * @see foo() + */ +]]> + + + * @see foo() +*/ +]]> + + + + + @see foo() + */ +]]> + + + @see foo() + */ +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/FunctionCommentThrowTagStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/FunctionCommentThrowTagStandard.xml new file mode 100644 index 00000000..81df2e3f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/FunctionCommentThrowTagStandard.xml @@ -0,0 +1,32 @@ + + + + + + + @throws Exception all the time + * @return void + */ +function foo() +{ + throw new Exception('Danger!'); +} +]]> + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForEachLoopDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForEachLoopDeclarationStandard.xml new file mode 100644 index 00000000..87c61813 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForEachLoopDeclarationStandard.xml @@ -0,0 +1,39 @@ + + + + + + + $foo as $bar => $baz) { + echo $baz; +} +]]> + + + $foo as $bar=>$baz ) { + echo $baz; +} +]]> + + + + + as $bar => $baz) { + echo $baz; +} +]]> + + + AS $bar => $baz) { + echo $baz; +} +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForLoopDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForLoopDeclarationStandard.xml new file mode 100644 index 00000000..bbc43923 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForLoopDeclarationStandard.xml @@ -0,0 +1,55 @@ + + + + + + + $i = 0; $i < 10; $i++) { + echo $i; +} +]]> + + + $i = 0; $i < 10; $i++ ) { + echo $i; +} +]]> + + + + + ; $i < 10; $i++) { + echo $i; +} +]]> + + + ; $i < 10 ; $i++) { + echo $i; +} +]]> + + + + + $i < 10; $i++) { + echo $i; +} +]]> + + + $i < 10;$i++) { + echo $i; +} +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/LowercaseDeclarationStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/LowercaseDeclarationStandard.xml new file mode 100644 index 00000000..699f1f09 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/LowercaseDeclarationStandard.xml @@ -0,0 +1,23 @@ + + + + + + + if ($foo) { + $bar = true; +} +]]> + + + IF ($foo) { + $bar = true; +} +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/FunctionDuplicateArgumentStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/FunctionDuplicateArgumentStandard.xml new file mode 100644 index 00000000..a890aba6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/FunctionDuplicateArgumentStandard.xml @@ -0,0 +1,23 @@ + + + + + + + isset($foo)) { + echo $foo; +} +]]> + + + isSet($foo)) { + echo $foo; +} +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/LowercaseFunctionKeywordsStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/LowercaseFunctionKeywordsStandard.xml new file mode 100644 index 00000000..46e8a8f3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/LowercaseFunctionKeywordsStandard.xml @@ -0,0 +1,25 @@ + + + + + + + function foo() +{ + return true; +} +]]> + + + FUNCTION foo() +{ + return true; +} +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Scope/StaticThisUsageStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Scope/StaticThisUsageStandard.xml new file mode 100644 index 00000000..3c97f54e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Scope/StaticThisUsageStandard.xml @@ -0,0 +1,31 @@ + + + + + + + static function bar() + { + return self::$staticMember; + } +} +]]> + + + static function bar() + { + return $this->$staticMember; + } +} +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Strings/EchoedStringsStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Strings/EchoedStringsStandard.xml new file mode 100644 index 00000000..030f2a68 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Strings/EchoedStringsStandard.xml @@ -0,0 +1,19 @@ + + + + + + + "Hello"; +]]> + + + ("Hello"); +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/CastSpacingStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/CastSpacingStandard.xml new file mode 100644 index 00000000..0fb195cb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/CastSpacingStandard.xml @@ -0,0 +1,19 @@ + + + + + + + int)'42'; +]]> + + + int )'42'; +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionOpeningBraceStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionOpeningBraceStandard.xml new file mode 100644 index 00000000..d2bc2647 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionOpeningBraceStandard.xml @@ -0,0 +1,41 @@ + + + + + + + { +} +]]> + + + { +} +]]> + + + + + return 42; +} +]]> + + + + return 42; +} +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml new file mode 100644 index 00000000..608bed0b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml @@ -0,0 +1,19 @@ + + + + + + + "hi"; +]]> + + + "hi"; +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ObjectOperatorSpacingStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ObjectOperatorSpacingStandard.xml new file mode 100644 index 00000000..c6194d71 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ObjectOperatorSpacingStandard.xml @@ -0,0 +1,19 @@ + + + ) should not have any space around it. + ]]> + + + + ->bar(); +]]> + + + -> bar(); +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeKeywordSpacingStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeKeywordSpacingStandard.xml new file mode 100644 index 00000000..8cadf669 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeKeywordSpacingStandard.xml @@ -0,0 +1,23 @@ + + + + + + + static function foo() +{ +} +]]> + + + static function foo() +{ +} +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SemicolonSpacingStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SemicolonSpacingStandard.xml new file mode 100644 index 00000000..7b227952 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SemicolonSpacingStandard.xml @@ -0,0 +1,19 @@ + + + + + + + ; +]]> + + + ; +]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayBracketSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayBracketSpacingSniff.php new file mode 100644 index 00000000..ee63dead --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayBracketSpacingSniff.php @@ -0,0 +1,95 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Arrays; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ArrayBracketSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_SQUARE_BRACKET, + T_CLOSE_SQUARE_BRACKET, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (($tokens[$stackPtr]['code'] === T_OPEN_SQUARE_BRACKET + && isset($tokens[$stackPtr]['bracket_closer']) === false) + || ($tokens[$stackPtr]['code'] === T_CLOSE_SQUARE_BRACKET + && isset($tokens[$stackPtr]['bracket_opener']) === false) + ) { + // Bow out for parse error/during live coding. + return; + } + + // Square brackets can not have a space before them. + $prevType = $tokens[($stackPtr - 1)]['code']; + if ($prevType === T_WHITESPACE) { + $nonSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 2), null, true); + $expected = $tokens[$nonSpace]['content'].$tokens[$stackPtr]['content']; + $found = $phpcsFile->getTokensAsString($nonSpace, ($stackPtr - $nonSpace)).$tokens[$stackPtr]['content']; + $error = 'Space found before square bracket; expected "%s" but found "%s"'; + $data = [ + $expected, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeBracket', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ''); + } + } + + // Open square brackets can't ever have spaces after them. + if ($tokens[$stackPtr]['code'] === T_OPEN_SQUARE_BRACKET) { + $nextType = $tokens[($stackPtr + 1)]['code']; + if ($nextType === T_WHITESPACE) { + $nonSpace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 2), null, true); + $expected = $tokens[$stackPtr]['content'].$tokens[$nonSpace]['content']; + $found = $phpcsFile->getTokensAsString($stackPtr, ($nonSpace - $stackPtr + 1)); + $error = 'Space found after square bracket; expected "%s" but found "%s"'; + $data = [ + $expected, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterBracket', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php new file mode 100644 index 00000000..b45a4709 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php @@ -0,0 +1,895 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Arrays; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ArrayDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_ARRAY, + T_OPEN_SHORT_ARRAY, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_ARRAY) { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'no'); + + // Array keyword should be lower case. + if ($tokens[$stackPtr]['content'] !== strtolower($tokens[$stackPtr]['content'])) { + if ($tokens[$stackPtr]['content'] === strtoupper($tokens[$stackPtr]['content'])) { + $phpcsFile->recordMetric($stackPtr, 'Array keyword case', 'upper'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Array keyword case', 'mixed'); + } + + $error = 'Array keyword should be lower case; expected "array" but found "%s"'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotLowerCase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'array'); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Array keyword case', 'lower'); + } + + $arrayStart = $tokens[$stackPtr]['parenthesis_opener']; + if (isset($tokens[$arrayStart]['parenthesis_closer']) === false) { + return; + } + + $arrayEnd = $tokens[$arrayStart]['parenthesis_closer']; + + if ($arrayStart !== ($stackPtr + 1)) { + $error = 'There must be no space between the "array" keyword and the opening parenthesis'; + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), $arrayStart, true); + if (isset(Tokens::$commentTokens[$tokens[$next]['code']]) === true) { + // We don't have anywhere to put the comment, so don't attempt to fix it. + $phpcsFile->addError($error, $stackPtr, 'SpaceAfterKeyword'); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterKeyword'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $arrayStart; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'yes'); + $arrayStart = $stackPtr; + $arrayEnd = $tokens[$stackPtr]['bracket_closer']; + }//end if + + // Check for empty arrays. + $content = $phpcsFile->findNext(T_WHITESPACE, ($arrayStart + 1), ($arrayEnd + 1), true); + if ($content === $arrayEnd) { + // Empty array, but if the brackets aren't together, there's a problem. + if (($arrayEnd - $arrayStart) !== 1) { + $error = 'Empty array declaration must have no space between the parentheses'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceInEmptyArray'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($arrayStart + 1); $i < $arrayEnd; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + // We can return here because there is nothing else to check. All code + // below can assume that the array is not empty. + return; + } + + if ($tokens[$arrayStart]['line'] === $tokens[$arrayEnd]['line']) { + $this->processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd); + } else { + $this->processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd); + } + + }//end process() + + + /** + * Processes a single-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * + * @return void + */ + public function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd) + { + $tokens = $phpcsFile->getTokens(); + + // Check if there are multiple values. If so, then it has to be multiple lines + // unless it is contained inside a function call or condition. + $valueCount = 0; + $commas = []; + for ($i = ($arrayStart + 1); $i < $arrayEnd; $i++) { + // Skip bracketed statements, like function calls. + if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) { + $i = $tokens[$i]['parenthesis_closer']; + continue; + } + + if ($tokens[$i]['code'] === T_COMMA) { + // Before counting this comma, make sure we are not + // at the end of the array. + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), $arrayEnd, true); + if ($next !== false) { + $valueCount++; + $commas[] = $i; + } else { + // There is a comma at the end of a single line array. + $error = 'Comma not allowed after last value in single-line array declaration'; + $fix = $phpcsFile->addFixableError($error, $i, 'CommaAfterLast'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } + }//end for + + // Now check each of the double arrows (if any). + $nextArrow = $arrayStart; + while (($nextArrow = $phpcsFile->findNext(T_DOUBLE_ARROW, ($nextArrow + 1), $arrayEnd)) !== false) { + if ($tokens[($nextArrow - 1)]['code'] !== T_WHITESPACE) { + $content = $tokens[($nextArrow - 1)]['content']; + $error = 'Expected 1 space between "%s" and double arrow; 0 found'; + $data = [$content]; + $fix = $phpcsFile->addFixableError($error, $nextArrow, 'NoSpaceBeforeDoubleArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($nextArrow, ' '); + } + } else { + $spaceLength = $tokens[($nextArrow - 1)]['length']; + if ($spaceLength !== 1) { + $content = $tokens[($nextArrow - 2)]['content']; + $error = 'Expected 1 space between "%s" and double arrow; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $nextArrow, 'SpaceBeforeDoubleArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextArrow - 1), ' '); + } + } + }//end if + + if ($tokens[($nextArrow + 1)]['code'] !== T_WHITESPACE) { + $content = $tokens[($nextArrow + 1)]['content']; + $error = 'Expected 1 space between double arrow and "%s"; 0 found'; + $data = [$content]; + $fix = $phpcsFile->addFixableError($error, $nextArrow, 'NoSpaceAfterDoubleArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($nextArrow, ' '); + } + } else { + $spaceLength = $tokens[($nextArrow + 1)]['length']; + if ($spaceLength !== 1) { + $content = $tokens[($nextArrow + 2)]['content']; + $error = 'Expected 1 space between double arrow and "%s"; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $nextArrow, 'SpaceAfterDoubleArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextArrow + 1), ' '); + } + } + }//end if + }//end while + + if ($valueCount > 0) { + $nestedParenthesis = false; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nested = $tokens[$stackPtr]['nested_parenthesis']; + $nestedParenthesis = array_pop($nested); + } + + if ($nestedParenthesis === false + || $tokens[$nestedParenthesis]['line'] !== $tokens[$stackPtr]['line'] + ) { + $error = 'Array with multiple values cannot be declared on a single line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SingleLineNotAllowed'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($arrayStart); + + if ($tokens[($arrayEnd - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($arrayEnd - 1), $phpcsFile->eolChar); + } else { + $phpcsFile->fixer->addNewlineBefore($arrayEnd); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + } + + // We have a multiple value array that is inside a condition or + // function. Check its spacing is correct. + foreach ($commas as $comma) { + if ($tokens[($comma + 1)]['code'] !== T_WHITESPACE) { + $content = $tokens[($comma + 1)]['content']; + $error = 'Expected 1 space between comma and "%s"; 0 found'; + $data = [$content]; + $fix = $phpcsFile->addFixableError($error, $comma, 'NoSpaceAfterComma', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($comma, ' '); + } + } else { + $spaceLength = $tokens[($comma + 1)]['length']; + if ($spaceLength !== 1) { + $content = $tokens[($comma + 2)]['content']; + $error = 'Expected 1 space between comma and "%s"; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $comma, 'SpaceAfterComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($comma + 1), ' '); + } + } + }//end if + + if ($tokens[($comma - 1)]['code'] === T_WHITESPACE) { + $content = $tokens[($comma - 2)]['content']; + $spaceLength = $tokens[($comma - 1)]['length']; + $error = 'Expected 0 spaces between "%s" and comma; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $comma, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($comma - 1), ''); + } + } + }//end foreach + }//end if + + }//end processSingleLineArray() + + + /** + * Processes a multi-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * + * @return void + */ + public function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd) + { + $tokens = $phpcsFile->getTokens(); + $keywordStart = $tokens[$stackPtr]['column']; + + // Check the closing bracket is on a new line. + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($arrayEnd - 1), $arrayStart, true); + if ($tokens[$lastContent]['line'] === $tokens[$arrayEnd]['line']) { + $error = 'Closing parenthesis of array declaration must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceNewLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($arrayEnd); + } + } else if ($tokens[$arrayEnd]['column'] !== $keywordStart) { + // Check the closing bracket is lined up under the "a" in array. + $expected = ($keywordStart - 1); + $found = ($tokens[$arrayEnd]['column'] - 1); + $error = 'Closing parenthesis not aligned correctly; expected %s space(s) but found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceNotAligned', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent(($arrayEnd - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($arrayEnd - 1), str_repeat(' ', $expected)); + } + } + }//end if + + $keyUsed = false; + $singleUsed = false; + $indices = []; + $maxLength = 0; + + if ($tokens[$stackPtr]['code'] === T_ARRAY) { + $lastToken = $tokens[$stackPtr]['parenthesis_opener']; + } else { + $lastToken = $stackPtr; + } + + // Find all the double arrows that reside in this scope. + for ($nextToken = ($stackPtr + 1); $nextToken < $arrayEnd; $nextToken++) { + // Skip bracketed statements, like function calls. + if ($tokens[$nextToken]['code'] === T_OPEN_PARENTHESIS + && (isset($tokens[$nextToken]['parenthesis_owner']) === false + || $tokens[$nextToken]['parenthesis_owner'] !== $stackPtr) + ) { + $nextToken = $tokens[$nextToken]['parenthesis_closer']; + continue; + } + + if ($tokens[$nextToken]['code'] === T_ARRAY + || $tokens[$nextToken]['code'] === T_OPEN_SHORT_ARRAY + || $tokens[$nextToken]['code'] === T_CLOSURE + || $tokens[$nextToken]['code'] === T_FN + || $tokens[$nextToken]['code'] === T_MATCH + ) { + // Let subsequent calls of this test handle nested arrays. + if ($tokens[$lastToken]['code'] !== T_DOUBLE_ARROW) { + $indices[] = ['value' => $nextToken]; + $lastToken = $nextToken; + } + + if ($tokens[$nextToken]['code'] === T_ARRAY) { + $nextToken = $tokens[$tokens[$nextToken]['parenthesis_opener']]['parenthesis_closer']; + } else if ($tokens[$nextToken]['code'] === T_OPEN_SHORT_ARRAY) { + $nextToken = $tokens[$nextToken]['bracket_closer']; + } else { + // T_CLOSURE. + $nextToken = $tokens[$nextToken]['scope_closer']; + } + + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] !== T_COMMA) { + $nextToken--; + } else { + $lastToken = $nextToken; + } + + continue; + }//end if + + if ($tokens[$nextToken]['code'] !== T_DOUBLE_ARROW && $tokens[$nextToken]['code'] !== T_COMMA) { + continue; + } + + $currentEntry = []; + + if ($tokens[$nextToken]['code'] === T_COMMA) { + $stackPtrCount = 0; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $stackPtrCount = count($tokens[$stackPtr]['nested_parenthesis']); + } + + $commaCount = 0; + if (isset($tokens[$nextToken]['nested_parenthesis']) === true) { + $commaCount = count($tokens[$nextToken]['nested_parenthesis']); + if ($tokens[$stackPtr]['code'] === T_ARRAY) { + // Remove parenthesis that are used to define the array. + $commaCount--; + } + } + + if ($commaCount > $stackPtrCount) { + // This comma is inside more parenthesis than the ARRAY keyword, + // then there it is actually a comma used to separate arguments + // in a function call. + continue; + } + + if ($keyUsed === true && $tokens[$lastToken]['code'] === T_COMMA) { + $error = 'No key specified for array entry; first entry specifies key'; + $phpcsFile->addError($error, $nextToken, 'NoKeySpecified'); + return; + } + + if ($keyUsed === false) { + if ($tokens[($nextToken - 1)]['code'] === T_WHITESPACE) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($nextToken - 1), null, true); + if (($tokens[$prev]['code'] !== T_END_HEREDOC + && $tokens[$prev]['code'] !== T_END_NOWDOC) + || $tokens[($nextToken - 1)]['line'] === $tokens[$nextToken]['line'] + ) { + if ($tokens[($nextToken - 1)]['content'] === $phpcsFile->eolChar) { + $spaceLength = 'newline'; + } else { + $spaceLength = $tokens[($nextToken - 1)]['length']; + } + + $error = 'Expected 0 spaces before comma; %s found'; + $data = [$spaceLength]; + + // The error is only fixable if there is only whitespace between the tokens. + if ($prev === $phpcsFile->findPrevious(T_WHITESPACE, ($nextToken - 1), null, true)) { + $fix = $phpcsFile->addFixableError($error, $nextToken, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextToken - 1), ''); + } + } else { + $phpcsFile->addError($error, $nextToken, 'SpaceBeforeComma', $data); + } + } + }//end if + + $valueContent = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($lastToken + 1), + $nextToken, + true + ); + + $indices[] = ['value' => $valueContent]; + $singleUsed = true; + }//end if + + $lastToken = $nextToken; + continue; + }//end if + + if ($tokens[$nextToken]['code'] === T_DOUBLE_ARROW) { + if ($singleUsed === true) { + $error = 'Key specified for array entry; first entry has no key'; + $phpcsFile->addError($error, $nextToken, 'KeySpecified'); + return; + } + + $currentEntry['arrow'] = $nextToken; + $keyUsed = true; + + // Find the start of index that uses this double arrow. + $indexEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($nextToken - 1), $arrayStart, true); + $indexStart = $phpcsFile->findStartOfStatement($indexEnd); + + if ($indexStart === $indexEnd) { + $currentEntry['index'] = $indexEnd; + $currentEntry['index_content'] = $tokens[$indexEnd]['content']; + $currentEntry['index_length'] = $tokens[$indexEnd]['length']; + } else { + $currentEntry['index'] = $indexStart; + $currentEntry['index_content'] = ''; + $currentEntry['index_length'] = 0; + for ($i = $indexStart; $i <= $indexEnd; $i++) { + $currentEntry['index_content'] .= $tokens[$i]['content']; + $currentEntry['index_length'] += $tokens[$i]['length']; + } + } + + if ($maxLength < $currentEntry['index_length']) { + $maxLength = $currentEntry['index_length']; + } + + // Find the value of this index. + $nextContent = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($nextToken + 1), + $arrayEnd, + true + ); + + $currentEntry['value'] = $nextContent; + $indices[] = $currentEntry; + $lastToken = $nextToken; + }//end if + }//end for + + // Check for multi-line arrays that should be single-line. + $singleValue = false; + + if (empty($indices) === true) { + $singleValue = true; + } else if (count($indices) === 1 && $tokens[$lastToken]['code'] === T_COMMA) { + // There may be another array value without a comma. + $exclude = Tokens::$emptyTokens; + $exclude[] = T_COMMA; + $nextContent = $phpcsFile->findNext($exclude, ($indices[0]['value'] + 1), $arrayEnd, true); + if ($nextContent === false) { + $singleValue = true; + } + } + + if ($singleValue === true) { + // Before we complain, make sure the single value isn't a here/nowdoc. + $next = $phpcsFile->findNext(Tokens::$heredocTokens, ($arrayStart + 1), ($arrayEnd - 1)); + if ($next === false) { + // Array cannot be empty, so this is a multi-line array with + // a single value. It should be defined on single line. + $error = 'Multi-line array contains a single value; use single-line array instead'; + $errorCode = 'MultiLineNotAllowed'; + + $find = Tokens::$phpcsCommentTokens; + $find[] = T_COMMENT; + $comment = $phpcsFile->findNext($find, ($arrayStart + 1), $arrayEnd); + if ($comment === false) { + $fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode); + } else { + $fix = false; + $phpcsFile->addError($error, $stackPtr, $errorCode); + } + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($arrayStart + 1); $i < $arrayEnd; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + for ($i = ($arrayEnd - 1); $i > $arrayStart; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + }//end if + }//end if + + /* + This section checks for arrays that don't specify keys. + + Arrays such as: + array( + 'aaa', + 'bbb', + 'd', + ); + */ + + if ($keyUsed === false && empty($indices) === false) { + $count = count($indices); + $lastIndex = $indices[($count - 1)]['value']; + + $trailingContent = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($arrayEnd - 1), + $lastIndex, + true + ); + + if ($tokens[$trailingContent]['code'] !== T_COMMA) { + $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'no'); + $error = 'Comma required after last value in array declaration'; + $fix = $phpcsFile->addFixableError($error, $trailingContent, 'NoCommaAfterLast'); + if ($fix === true) { + $phpcsFile->fixer->addContent($trailingContent, ','); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'yes'); + } + + foreach ($indices as $valuePosition => $value) { + if (empty($value['value']) === true) { + // Array was malformed and we couldn't figure out + // the array value correctly, so we have to ignore it. + // Other parts of this sniff will correct the error. + continue; + } + + $valuePointer = $value['value']; + + $ignoreTokens = [ + T_WHITESPACE => T_WHITESPACE, + T_COMMA => T_COMMA, + ]; + $ignoreTokens += Tokens::$castTokens; + + if ($tokens[$valuePointer]['code'] === T_CLOSURE + || $tokens[$valuePointer]['code'] === T_FN + ) { + $ignoreTokens += [T_STATIC => T_STATIC]; + } + + $previous = $phpcsFile->findPrevious($ignoreTokens, ($valuePointer - 1), ($arrayStart + 1), true); + if ($previous === false) { + $previous = $stackPtr; + } + + $previousIsWhitespace = $tokens[($valuePointer - 1)]['code'] === T_WHITESPACE; + if ($tokens[$previous]['line'] === $tokens[$valuePointer]['line']) { + $error = 'Each value in a multi-line array must be on a new line'; + if ($valuePosition === 0) { + $error = 'The first value in a multi-value array must be on a new line'; + } + + $fix = $phpcsFile->addFixableError($error, $valuePointer, 'ValueNoNewline'); + if ($fix === true) { + if ($previousIsWhitespace === true) { + $phpcsFile->fixer->replaceToken(($valuePointer - 1), $phpcsFile->eolChar); + } else { + $phpcsFile->fixer->addNewlineBefore($valuePointer); + } + } + } else if ($previousIsWhitespace === true) { + $expected = $keywordStart; + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $valuePointer, true); + $found = ($tokens[$first]['column'] - 1); + if ($found !== $expected) { + $error = 'Array value not aligned correctly; expected %s spaces but found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $first, 'ValueNotAligned', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent(($first - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($first - 1), str_repeat(' ', $expected)); + } + } + } + }//end if + }//end foreach + }//end if + + /* + Below the actual indentation of the array is checked. + Errors will be thrown when a key is not aligned, when + a double arrow is not aligned, and when a value is not + aligned correctly. + If an error is found in one of the above areas, then errors + are not reported for the rest of the line to avoid reporting + spaces and columns incorrectly. Often fixing the first + problem will fix the other 2 anyway. + + For example: + + $a = array( + 'index' => '2', + ); + + or + + $a = [ + 'index' => '2', + ]; + + In this array, the double arrow is indented too far, but this + will also cause an error in the value's alignment. If the arrow were + to be moved back one space however, then both errors would be fixed. + */ + + $indicesStart = ($keywordStart + 1); + foreach ($indices as $valuePosition => $index) { + $valuePointer = $index['value']; + if ($valuePointer === false) { + // Syntax error or live coding. + continue; + } + + if (isset($index['index']) === false) { + // Array value only. + continue; + } + + $indexPointer = $index['index']; + $indexLine = $tokens[$indexPointer]['line']; + + $previous = $phpcsFile->findPrevious([T_WHITESPACE, T_COMMA], ($indexPointer - 1), ($arrayStart + 1), true); + if ($previous === false) { + $previous = $stackPtr; + } + + if ($tokens[$previous]['line'] === $indexLine) { + $error = 'Each index in a multi-line array must be on a new line'; + if ($valuePosition === 0) { + $error = 'The first index in a multi-value array must be on a new line'; + } + + $fix = $phpcsFile->addFixableError($error, $indexPointer, 'IndexNoNewline'); + if ($fix === true) { + if ($tokens[($indexPointer - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($indexPointer - 1), $phpcsFile->eolChar); + } else { + $phpcsFile->fixer->addNewlineBefore($indexPointer); + } + } + + continue; + } + + if ($tokens[$indexPointer]['column'] !== $indicesStart && ($indexPointer - 1) !== $arrayStart) { + $expected = ($indicesStart - 1); + $found = ($tokens[$indexPointer]['column'] - 1); + $error = 'Array key not aligned correctly; expected %s spaces but found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $indexPointer, 'KeyNotAligned', $data); + if ($fix === true) { + if ($found === 0 || $tokens[($indexPointer - 1)]['code'] !== T_WHITESPACE) { + $phpcsFile->fixer->addContent(($indexPointer - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($indexPointer - 1), str_repeat(' ', $expected)); + } + } + } + + $arrowStart = ($tokens[$indexPointer]['column'] + $maxLength + 1); + if ($tokens[$index['arrow']]['column'] !== $arrowStart) { + $expected = ($arrowStart - ($index['index_length'] + $tokens[$indexPointer]['column'])); + $found = ($tokens[$index['arrow']]['column'] - ($index['index_length'] + $tokens[$indexPointer]['column'])); + $error = 'Array double arrow not aligned correctly; expected %s space(s) but found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $index['arrow'], 'DoubleArrowNotAligned', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent(($index['arrow'] - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($index['arrow'] - 1), str_repeat(' ', $expected)); + } + } + + continue; + } + + $valueStart = ($arrowStart + 3); + if ($tokens[$valuePointer]['column'] !== $valueStart) { + $expected = ($valueStart - ($tokens[$index['arrow']]['length'] + $tokens[$index['arrow']]['column'])); + $found = ($tokens[$valuePointer]['column'] - ($tokens[$index['arrow']]['length'] + $tokens[$index['arrow']]['column'])); + if ($found < 0) { + $found = 'newline'; + } + + $error = 'Array value not aligned correctly; expected %s space(s) but found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $index['arrow'], 'ValueNotAligned', $data); + if ($fix === true) { + if ($found === 'newline') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($valuePointer - 1), null, true); + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $valuePointer; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken(($valuePointer - 1), str_repeat(' ', $expected)); + $phpcsFile->fixer->endChangeset(); + } else if ($found === 0) { + $phpcsFile->fixer->addContent(($valuePointer - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($valuePointer - 1), str_repeat(' ', $expected)); + } + } + }//end if + + // Check each line ends in a comma. + $valueStart = $valuePointer; + $nextComma = false; + + $end = $phpcsFile->findEndOfStatement($valueStart); + if ($end === false) { + $valueEnd = $valueStart; + } else if ($tokens[$end]['code'] === T_COMMA) { + $valueEnd = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($end - 1), $valueStart, true); + $nextComma = $end; + } else { + $valueEnd = $end; + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $arrayEnd, true); + if ($next !== false && $tokens[$next]['code'] === T_COMMA) { + $nextComma = $next; + } + } + + $valueLine = $tokens[$valueEnd]['line']; + if ($tokens[$valueEnd]['code'] === T_END_HEREDOC || $tokens[$valueEnd]['code'] === T_END_NOWDOC) { + $valueLine++; + } + + if ($nextComma === false || ($tokens[$nextComma]['line'] !== $valueLine)) { + $error = 'Each line in an array declaration must end in a comma'; + $fix = $phpcsFile->addFixableError($error, $valuePointer, 'NoComma'); + + if ($fix === true) { + // Find the end of the line and put a comma there. + for ($i = ($valuePointer + 1); $i <= $arrayEnd; $i++) { + if ($tokens[$i]['line'] > $valueLine) { + break; + } + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore(($i - 1), ','); + if ($nextComma !== false) { + $phpcsFile->fixer->replaceToken($nextComma, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + // Check that there is no space before the comma. + if ($nextComma !== false && $tokens[($nextComma - 1)]['code'] === T_WHITESPACE) { + // Here/nowdoc closing tags must have the comma on the next line. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($nextComma - 1), null, true); + if ($tokens[$prev]['code'] !== T_END_HEREDOC && $tokens[$prev]['code'] !== T_END_NOWDOC) { + $content = $tokens[($nextComma - 2)]['content']; + $spaceLength = $tokens[($nextComma - 1)]['length']; + $error = 'Expected 0 spaces between "%s" and comma; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $nextComma, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextComma - 1), ''); + } + } + } + }//end foreach + + }//end processMultiLineArray() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionClosingBraceSpaceSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionClosingBraceSpaceSniff.php new file mode 100644 index 00000000..a9a55fa8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionClosingBraceSpaceSniff.php @@ -0,0 +1,134 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDefinitionClosingBraceSpaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_CLOSE_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $next = $stackPtr; + while (true) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true); + if ($next === false) { + return; + } + + if (isset(Tokens::$emptyTokens[$tokens[$next]['code']]) === true + && $tokens[$next]['line'] === $tokens[$stackPtr]['line'] + ) { + // Trailing comment. + continue; + } + + break; + } + + if ($tokens[$next]['code'] !== T_CLOSE_TAG) { + $found = (($tokens[$next]['line'] - $tokens[$stackPtr]['line']) - 1); + if ($found !== 1) { + $error = 'Expected one blank line after closing brace of class definition; %s found'; + $data = [max(0, $found)]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterClose', $data); + + if ($fix === true) { + $firstOnLine = $next; + while ($tokens[$firstOnLine]['column'] !== 1) { + --$firstOnLine; + } + + if ($found < 0) { + // Next statement on same line as the closing brace. + $phpcsFile->fixer->addContentBefore($next, $phpcsFile->eolChar.$phpcsFile->eolChar); + } else if ($found === 0) { + // Next statement on next line, no blank line. + $phpcsFile->fixer->addContentBefore($firstOnLine, $phpcsFile->eolChar); + } else { + // Too many blank lines. + $phpcsFile->fixer->beginChangeset(); + for ($i = ($firstOnLine - 1); $i > $stackPtr; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContentBefore($firstOnLine, $phpcsFile->eolChar.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + }//end if + + // Ignore nested style definitions from here on. The spacing before the closing brace + // (a single blank line) will be enforced by the above check, which ensures there is a + // blank line after the last nested class. + $found = $phpcsFile->findPrevious( + T_CLOSE_CURLY_BRACKET, + ($stackPtr - 1), + $tokens[$stackPtr]['bracket_opener'] + ); + + if ($found !== false) { + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prev === false) { + return; + } + + if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Closing brace of class definition must be on new line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($stackPtr); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionNameSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionNameSpacingSniff.php new file mode 100644 index 00000000..4b7efd99 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionNameSpacingSniff.php @@ -0,0 +1,111 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDefinitionNameSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + // Syntax error or live coding, bow out. + return; + } + + // Do not check nested style definitions as, for example, in @media style rules. + $nested = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($stackPtr + 1), $tokens[$stackPtr]['bracket_closer']); + if ($nested !== false) { + return; + } + + // Find the first blank line before this opening brace, unless we get + // to another style definition, comment or the start of the file. + $endTokens = [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_OPEN_TAG => T_OPEN_TAG, + ]; + $endTokens += Tokens::$commentTokens; + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + $foundContent = false; + $currentLine = $tokens[$prev]['line']; + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + if (isset($endTokens[$tokens[$i]['code']]) === true) { + break; + } + + if ($tokens[$i]['line'] === $currentLine) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + $foundContent = true; + } + + continue; + } + + // We changed lines. + if ($foundContent === false) { + // Before we throw an error, make sure we are not looking + // at a gap before the style definition. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, $i, null, true); + if ($prev !== false + && isset($endTokens[$tokens[$prev]['code']]) === false + ) { + $error = 'Blank lines are not allowed between class names'; + $phpcsFile->addError($error, ($i + 1), 'BlankLinesFound'); + } + + break; + } + + $foundContent = false; + $currentLine = $tokens[$i]['line']; + }//end for + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionOpeningBraceSpaceSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionOpeningBraceSpaceSniff.php new file mode 100644 index 00000000..e56dad73 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionOpeningBraceSpaceSniff.php @@ -0,0 +1,176 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDefinitionOpeningBraceSpaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + + if ($prevNonWhitespace !== false) { + $length = 0; + if ($tokens[$stackPtr]['line'] !== $tokens[$prevNonWhitespace]['line']) { + $length = 'newline'; + } else if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + if (strpos($tokens[($stackPtr - 1)]['content'], "\t") !== false) { + $length = 'tab'; + } else { + $length = $tokens[($stackPtr - 1)]['length']; + } + } + + if ($length === 0) { + $error = 'Expected 1 space before opening brace of class definition; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoneBefore'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + } else if ($length !== 1) { + $error = 'Expected 1 space before opening brace of class definition; %s found'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Before', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($stackPtr - 1); $i > $prevNonWhitespace; $i--) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + if ($tokens[$nextNonEmpty]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Opening brace should be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentBefore'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($stackPtr); + + // Remove potentially left over trailing whitespace. + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + // Syntax error or live coding, bow out. + return; + } + + // Check for nested class definitions. + $found = $phpcsFile->findNext( + T_OPEN_CURLY_BRACKET, + ($stackPtr + 1), + $tokens[$stackPtr]['bracket_closer'] + ); + + if ($found === false) { + // Not nested. + return; + } + + $lastOnLine = $stackPtr; + for ($lastOnLine; $lastOnLine < $tokens[$stackPtr]['bracket_closer']; $lastOnLine++) { + if ($tokens[$lastOnLine]['line'] !== $tokens[($lastOnLine + 1)]['line']) { + break; + } + } + + $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, ($lastOnLine + 1), null, true); + if ($nextNonWhiteSpace === false) { + return; + } + + $foundLines = ($tokens[$nextNonWhiteSpace]['line'] - $tokens[$stackPtr]['line'] - 1); + if ($foundLines !== 1) { + $error = 'Expected 1 blank line after opening brace of nesting class definition; %s found'; + $data = [max(0, $foundLines)]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'AfterNesting', $data); + + if ($fix === true) { + $firstOnNextLine = $nextNonWhiteSpace; + while ($tokens[$firstOnNextLine]['column'] !== 1) { + --$firstOnNextLine; + } + + if ($found < 0) { + // First statement on same line as the opening brace. + $phpcsFile->fixer->addContentBefore($nextNonWhiteSpace, $phpcsFile->eolChar.$phpcsFile->eolChar); + } else if ($found === 0) { + // Next statement on next line, no blank line. + $phpcsFile->fixer->addNewlineBefore($firstOnNextLine); + } else { + // Too many blank lines. + $phpcsFile->fixer->beginChangeset(); + for ($i = ($firstOnNextLine - 1); $i > $stackPtr; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContentBefore($firstOnNextLine, $phpcsFile->eolChar.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColonSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColonSpacingSniff.php new file mode 100644 index 00000000..8548a721 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColonSpacingSniff.php @@ -0,0 +1,107 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ColonSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_COLON]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] !== T_STYLE) { + // The colon is not part of a style definition. + return; + } + + if ($tokens[$prev]['content'] === 'progid') { + // Special case for IE filters. + return; + } + + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $error = 'There must be no space before a colon in a style definition'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Before'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ''); + } + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON || $tokens[$next]['code'] === T_STYLE) { + // Empty style definition, ignore it. + return; + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after colon in style definition; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoneAfter'); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } else { + $content = $tokens[($stackPtr + 1)]['content']; + if (strpos($content, $phpcsFile->eolChar) === false) { + $length = strlen($content); + if ($length !== 1) { + $error = 'Expected 1 space after colon in style definition; %s found'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'After', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } else { + $error = 'Expected 1 space after colon in style definition; newline found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'AfterNewline'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColourDefinitionSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColourDefinitionSniff.php new file mode 100644 index 00000000..6b071ea7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColourDefinitionSniff.php @@ -0,0 +1,88 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ColourDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_COLOUR]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $colour = $tokens[$stackPtr]['content']; + + $expected = strtoupper($colour); + if ($colour !== $expected) { + $error = 'CSS colours must be defined in uppercase; expected %s but found %s'; + $data = [ + $expected, + $colour, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotUpper', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $expected); + } + } + + // Now check if shorthand can be used. + if (strlen($colour) !== 7) { + return; + } + + if ($colour[1] === $colour[2] && $colour[3] === $colour[4] && $colour[5] === $colour[6]) { + $expected = '#'.$colour[1].$colour[3].$colour[5]; + $error = 'CSS colours must use shorthand if available; expected %s but found %s'; + $data = [ + $expected, + $colour, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Shorthand', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $expected); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DisallowMultipleStyleDefinitionsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DisallowMultipleStyleDefinitionsSniff.php new file mode 100644 index 00000000..def95c1e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DisallowMultipleStyleDefinitionsSniff.php @@ -0,0 +1,71 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowMultipleStyleDefinitionsSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(T_STYLE, ($stackPtr + 1)); + if ($next === false) { + return; + } + + if ($tokens[$next]['content'] === 'progid') { + // Special case for IE filters. + return; + } + + if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Each style definition must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $next, 'Found'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($next); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateClassDefinitionSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateClassDefinitionSniff.php new file mode 100644 index 00000000..d489cb1b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateClassDefinitionSniff.php @@ -0,0 +1,116 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DuplicateClassDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Find the content of each class definition name. + $classNames = []; + $next = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($stackPtr + 1)); + if ($next === false) { + // No class definitions in the file. + return; + } + + // Save the class names in a "scope", + // to prevent false positives with @media blocks. + $scope = 'main'; + + $find = [ + T_CLOSE_CURLY_BRACKET, + T_OPEN_CURLY_BRACKET, + T_OPEN_TAG, + ]; + + while ($next !== false) { + $prev = $phpcsFile->findPrevious($find, ($next - 1)); + + // Check if an inner block was closed. + $beforePrev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + if ($beforePrev !== false + && $tokens[$beforePrev]['code'] === T_CLOSE_CURLY_BRACKET + ) { + $scope = 'main'; + } + + // Create a sorted name for the class so we can compare classes + // even when the individual names are all over the place. + $name = ''; + for ($i = ($prev + 1); $i < $next; $i++) { + $name .= $tokens[$i]['content']; + } + + $name = trim($name); + $name = str_replace("\n", ' ', $name); + $name = preg_replace('|[\s]+|', ' ', $name); + $name = preg_replace('|\s*/\*.*\*/\s*|', '', $name); + $name = str_replace(', ', ',', $name); + + $names = explode(',', $name); + sort($names); + $name = implode(',', $names); + + if ($name[0] === '@') { + // Media block has its own "scope". + $scope = $name; + } else if (isset($classNames[$scope][$name]) === true) { + $first = $classNames[$scope][$name]; + $error = 'Duplicate class definition found; first defined on line %s'; + $data = [$tokens[$first]['line']]; + $phpcsFile->addError($error, $next, 'Found', $data); + } else { + $classNames[$scope][$name] = $next; + } + + $next = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($next + 1)); + }//end while + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateStyleDefinitionSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateStyleDefinitionSniff.php new file mode 100644 index 00000000..c7479759 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateStyleDefinitionSniff.php @@ -0,0 +1,88 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DuplicateStyleDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + // Syntax error or live coding, bow out. + return; + } + + // Find the content of each style definition name. + $styleNames = []; + + $next = $stackPtr; + $end = $tokens[$stackPtr]['bracket_closer']; + + do { + $next = $phpcsFile->findNext([T_STYLE, T_OPEN_CURLY_BRACKET], ($next + 1), $end); + if ($next === false) { + // Class definition is empty. + break; + } + + if ($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET) { + $next = $tokens[$next]['bracket_closer']; + continue; + } + + $name = $tokens[$next]['content']; + if (isset($styleNames[$name]) === true) { + $first = $styleNames[$name]; + $error = 'Duplicate style definition found; first defined on line %s'; + $data = [$tokens[$first]['line']]; + $phpcsFile->addError($error, $next, 'Found', $data); + } else { + $styleNames[$name] = $next; + } + } while ($next !== false); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyClassDefinitionSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyClassDefinitionSniff.php new file mode 100644 index 00000000..d3bb9696 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyClassDefinitionSniff.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmptyClassDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + if ($next === false || $tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) { + $error = 'Class definition is empty'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyStyleDefinitionSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyStyleDefinitionSniff.php new file mode 100644 index 00000000..05f2e515 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyStyleDefinitionSniff.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmptyStyleDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = Tokens::$emptyTokens; + $ignore[] = T_COLON; + + $next = $phpcsFile->findNext($ignore, ($stackPtr + 1), null, true); + if ($next === false || $tokens[$next]['code'] === T_SEMICOLON || $tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + $error = 'Style definition is empty'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ForbiddenStylesSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ForbiddenStylesSniff.php new file mode 100644 index 00000000..d8585dc8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ForbiddenStylesSniff.php @@ -0,0 +1,177 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ForbiddenStylesSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * A list of forbidden styles with their alternatives. + * + * The value is NULL if no alternative exists. i.e., the + * style should just not be used. + * + * @var array + */ + protected $forbiddenStyles = [ + '-moz-border-radius' => 'border-radius', + '-webkit-border-radius' => 'border-radius', + '-moz-border-radius-topleft' => 'border-top-left-radius', + '-moz-border-radius-topright' => 'border-top-right-radius', + '-moz-border-radius-bottomright' => 'border-bottom-right-radius', + '-moz-border-radius-bottomleft' => 'border-bottom-left-radius', + '-moz-box-shadow' => 'box-shadow', + '-webkit-box-shadow' => 'box-shadow', + ]; + + /** + * A cache of forbidden style names, for faster lookups. + * + * @var string[] + */ + protected $forbiddenStyleNames = []; + + /** + * If true, forbidden styles will be considered regular expressions. + * + * @var boolean + */ + protected $patternMatch = false; + + /** + * If true, an error will be thrown; otherwise a warning. + * + * @var boolean + */ + public $error = true; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $this->forbiddenStyleNames = array_keys($this->forbiddenStyles); + + if ($this->patternMatch === true) { + foreach ($this->forbiddenStyleNames as $i => $name) { + $this->forbiddenStyleNames[$i] = '/'.$name.'/i'; + } + } + + return [T_STYLE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $style = strtolower($tokens[$stackPtr]['content']); + $pattern = null; + + if ($this->patternMatch === true) { + $count = 0; + $pattern = preg_replace( + $this->forbiddenStyleNames, + $this->forbiddenStyleNames, + $style, + 1, + $count + ); + + if ($count === 0) { + return; + } + + // Remove the pattern delimiters and modifier. + $pattern = substr($pattern, 1, -2); + } else { + if (in_array($style, $this->forbiddenStyleNames, true) === false) { + return; + } + }//end if + + $this->addError($phpcsFile, $stackPtr, $style, $pattern); + + }//end process() + + + /** + * Generates the error or warning for this sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the forbidden style + * in the token array. + * @param string $style The name of the forbidden style. + * @param string $pattern The pattern used for the match. + * + * @return void + */ + protected function addError($phpcsFile, $stackPtr, $style, $pattern=null) + { + $data = [$style]; + $error = 'The use of style %s is '; + if ($this->error === true) { + $type = 'Found'; + $error .= 'forbidden'; + } else { + $type = 'Discouraged'; + $error .= 'discouraged'; + } + + if ($pattern === null) { + $pattern = $style; + } + + if ($this->forbiddenStyles[$pattern] !== null) { + $data[] = $this->forbiddenStyles[$pattern]; + if ($this->error === true) { + $fix = $phpcsFile->addFixableError($error.'; use %s instead', $stackPtr, $type.'WithAlternative', $data); + } else { + $fix = $phpcsFile->addFixableWarning($error.'; use %s instead', $stackPtr, $type.'WithAlternative', $data); + } + + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $this->forbiddenStyles[$pattern]); + } + } else { + if ($this->error === true) { + $phpcsFile->addError($error, $stackPtr, $type, $data); + } else { + $phpcsFile->addWarning($error, $stackPtr, $type, $data); + } + } + + }//end addError() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/IndentationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/IndentationSniff.php new file mode 100644 index 00000000..5e35f4e9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/IndentationSniff.php @@ -0,0 +1,150 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class IndentationSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $numTokens = (count($tokens) - 2); + $indentLevel = 0; + $nestingLevel = 0; + for ($i = 1; $i < $numTokens; $i++) { + if ($tokens[$i]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$i]['code']]) === true + ) { + // Don't check the indent of comments. + continue; + } + + if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) { + $indentLevel++; + + if (isset($tokens[$i]['bracket_closer']) === false) { + // Syntax error or live coding. + // Anything after this would receive incorrect fixes, so bow out. + return; + } + + // Check for nested class definitions. + $found = $phpcsFile->findNext( + T_OPEN_CURLY_BRACKET, + ($i + 1), + $tokens[$i]['bracket_closer'] + ); + + if ($found !== false) { + $nestingLevel = $indentLevel; + } + } + + if (($tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET + && $tokens[$i]['line'] !== $tokens[($i - 1)]['line']) + || ($tokens[($i + 1)]['code'] === T_CLOSE_CURLY_BRACKET + && $tokens[$i]['line'] === $tokens[($i + 1)]['line']) + ) { + $indentLevel--; + if ($indentLevel === 0) { + $nestingLevel = 0; + } + } + + if ($tokens[$i]['column'] !== 1 + || $tokens[$i]['code'] === T_OPEN_CURLY_BRACKET + || $tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET + ) { + continue; + } + + // We started a new line, so check indent. + if ($tokens[$i]['code'] === T_WHITESPACE) { + $content = str_replace($phpcsFile->eolChar, '', $tokens[$i]['content']); + $foundIndent = strlen($content); + } else { + $foundIndent = 0; + } + + $expectedIndent = ($indentLevel * $this->indent); + if ($expectedIndent > 0 + && strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false + ) { + if ($nestingLevel !== $indentLevel) { + $error = 'Blank lines are not allowed in class definitions'; + $fix = $phpcsFile->addFixableError($error, $i, 'BlankLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } else if ($foundIndent !== $expectedIndent) { + $error = 'Line indented incorrectly; expected %s spaces, found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'Incorrect', $data); + if ($fix === true) { + $indent = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $indent); + } else { + $phpcsFile->fixer->replaceToken($i, $indent); + } + } + }//end if + }//end for + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/LowercaseStyleDefinitionSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/LowercaseStyleDefinitionSniff.php new file mode 100644 index 00000000..c80a639c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/LowercaseStyleDefinitionSniff.php @@ -0,0 +1,97 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LowercaseStyleDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + $end = ($tokens[$stackPtr]['bracket_closer'] - 1); + $inStyle = null; + + for ($i = $start; $i <= $end; $i++) { + // Skip nested definitions as they are checked individually. + if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) { + $i = $tokens[$i]['bracket_closer']; + continue; + } + + if ($tokens[$i]['code'] === T_STYLE) { + $inStyle = $tokens[$i]['content']; + } + + if ($tokens[$i]['code'] === T_SEMICOLON) { + $inStyle = null; + } + + if ($inStyle === 'progid') { + // Special case for IE filters. + continue; + } + + if ($tokens[$i]['code'] === T_STYLE + || ($inStyle !== null + && $tokens[$i]['code'] === T_STRING) + ) { + $expected = strtolower($tokens[$i]['content']); + if ($expected !== $tokens[$i]['content']) { + $error = 'Style definitions must be lowercase; expected %s but found %s'; + $data = [ + $expected, + $tokens[$i]['content'], + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'FoundUpper', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, $expected); + } + } + } + }//end for + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/MissingColonSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/MissingColonSniff.php new file mode 100644 index 00000000..dbf7d6c9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/MissingColonSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class MissingColonSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + // Syntax error or live coding, bow out. + return; + } + + $lastLine = $tokens[$stackPtr]['line']; + $end = $tokens[$stackPtr]['bracket_closer']; + + // Do not check nested style definitions as, for example, in @media style rules. + $nested = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($stackPtr + 1), $end); + if ($nested !== false) { + return; + } + + $foundColon = false; + $foundString = false; + for ($i = ($stackPtr + 1); $i <= $end; $i++) { + if ($tokens[$i]['line'] !== $lastLine) { + // We changed lines. + if ($foundColon === false && $foundString !== false) { + // We didn't find a colon on the previous line. + $error = 'No style definition found on line; check for missing colon'; + $phpcsFile->addError($error, $foundString, 'Found'); + } + + $foundColon = false; + $foundString = false; + $lastLine = $tokens[$i]['line']; + } + + if ($tokens[$i]['code'] === T_STRING) { + $foundString = $i; + } else if ($tokens[$i]['code'] === T_COLON) { + $foundColon = $i; + } + }//end for + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/NamedColoursSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/NamedColoursSniff.php new file mode 100644 index 00000000..0a51f501 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/NamedColoursSniff.php @@ -0,0 +1,93 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class NamedColoursSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * A list of named colours. + * + * This is the list of standard colours defined in the CSS specification. + * + * @var array + */ + protected $colourNames = [ + 'aqua' => 'aqua', + 'black' => 'black', + 'blue' => 'blue', + 'fuchsia' => 'fuchsia', + 'gray' => 'gray', + 'green' => 'green', + 'lime' => 'lime', + 'maroon' => 'maroon', + 'navy' => 'navy', + 'olive' => 'olive', + 'orange' => 'orange', + 'purple' => 'purple', + 'red' => 'red', + 'silver' => 'silver', + 'teal' => 'teal', + 'white' => 'white', + 'yellow' => 'yellow', + ]; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_STRING]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[($stackPtr - 1)]['code'] === T_HASH + || $tokens[($stackPtr - 1)]['code'] === T_STRING_CONCAT + ) { + // Class name. + return; + } + + if (isset($this->colourNames[strtolower($tokens[$stackPtr]['content'])]) === true) { + $error = 'Named colours are forbidden; use hex, rgb, or rgba values instead'; + $phpcsFile->addError($error, $stackPtr, 'Forbidden'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/OpacitySniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/OpacitySniff.php new file mode 100644 index 00000000..1dfbcf67 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/OpacitySniff.php @@ -0,0 +1,101 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OpacitySniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['content'] !== 'opacity') { + return; + } + + $ignore = Tokens::$emptyTokens; + $ignore[] = T_COLON; + + $next = $phpcsFile->findNext($ignore, ($stackPtr + 1), null, true); + + if ($next === false + || ($tokens[$next]['code'] !== T_DNUMBER + && $tokens[$next]['code'] !== T_LNUMBER) + ) { + return; + } + + $value = $tokens[$next]['content']; + if ($tokens[$next]['code'] === T_LNUMBER) { + if ($value !== '0' && $value !== '1') { + $error = 'Opacity values must be between 0 and 1'; + $phpcsFile->addError($error, $next, 'Invalid'); + } + } else { + if (strlen($value) > 3) { + $error = 'Opacity values must have a single value after the decimal point'; + $phpcsFile->addError($error, $next, 'DecimalPrecision'); + } else if ($value === '0.0' || $value === '1.0') { + $error = 'Opacity value does not require decimal point; use %s instead'; + $data = [$value[0]]; + $fix = $phpcsFile->addFixableError($error, $next, 'PointNotRequired', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($next, $value[0]); + } + } else if ($value[0] === '.') { + $error = 'Opacity values must not start with a decimal point; use 0%s instead'; + $data = [$value]; + $fix = $phpcsFile->addFixableError($error, $next, 'StartWithPoint', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($next, '0'.$value); + } + } else if ($value[0] !== '0') { + $error = 'Opacity values must be between 0 and 1'; + $phpcsFile->addError($error, $next, 'Invalid'); + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/SemicolonSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/SemicolonSpacingSniff.php new file mode 100644 index 00000000..fdc168e2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/SemicolonSpacingSniff.php @@ -0,0 +1,103 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SemicolonSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextStatement = $phpcsFile->findNext([T_STYLE, T_CLOSE_CURLY_BRACKET], ($stackPtr + 1)); + if ($nextStatement === false) { + return; + } + + $ignore = Tokens::$emptyTokens; + if ($tokens[$nextStatement]['code'] === T_STYLE) { + // Allow for star-prefix hack. + $ignore[] = T_MULTIPLY; + } + + $endOfThisStatement = $phpcsFile->findPrevious($ignore, ($nextStatement - 1), null, true); + if ($tokens[$endOfThisStatement]['code'] !== T_SEMICOLON) { + $error = 'Style definitions must end with a semicolon'; + $phpcsFile->addError($error, $endOfThisStatement, 'NotAtEnd'); + return; + } + + if ($tokens[($endOfThisStatement - 1)]['code'] !== T_WHITESPACE) { + return; + } + + // There is a semi-colon, so now find the last token in the statement. + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($endOfThisStatement - 1), null, true); + $found = $tokens[($endOfThisStatement - 1)]['length']; + if ($tokens[$prevNonEmpty]['line'] !== $tokens[$endOfThisStatement]['line']) { + $found = 'newline'; + } + + $error = 'Expected 0 spaces before semicolon in style definition; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $prevNonEmpty, 'SpaceFound', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($prevNonEmpty, ';'); + $phpcsFile->fixer->replaceToken($endOfThisStatement, ''); + + for ($i = ($endOfThisStatement - 1); $i > $prevNonEmpty; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ShorthandSizeSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ShorthandSizeSniff.php new file mode 100644 index 00000000..8f2d9aa8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ShorthandSizeSniff.php @@ -0,0 +1,181 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ShorthandSizeSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * A list of styles that we shouldn't check. + * + * These have values that looks like sizes, but are not. + * + * @var array + */ + protected $excludeStyles = [ + 'background-position' => 'background-position', + 'box-shadow' => 'box-shadow', + 'transform-origin' => 'transform-origin', + '-webkit-transform-origin' => '-webkit-transform-origin', + '-ms-transform-origin' => '-ms-transform-origin', + ]; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Some styles look like shorthand but are not actually a set of 4 sizes. + $style = strtolower($tokens[$stackPtr]['content']); + if (isset($this->excludeStyles[$style]) === true) { + return; + } + + $end = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1)); + if ($end === false) { + // Live coding or parse error. + return; + } + + // Get the whole style content. + $origContent = $phpcsFile->getTokensAsString(($stackPtr + 1), ($end - $stackPtr - 1)); + $origContent = trim($origContent, ':'); + $origContent = trim($origContent); + + // Account for a !important annotation. + $content = $origContent; + if (substr($content, -10) === '!important') { + $content = substr($content, 0, -10); + $content = trim($content); + } + + // Check if this style value is a set of numbers with optional prefixes. + $content = preg_replace('/\s+/', ' ', $content); + $values = []; + $num = preg_match_all( + '/(?:[0-9]+)(?:[a-zA-Z]{2}\s+|%\s+|\s+)/', + $content.' ', + $values, + PREG_SET_ORDER + ); + + // Only interested in styles that have multiple sizes defined. + if ($num < 2) { + return; + } + + // Rebuild the content we matched to ensure we got everything. + $matched = ''; + foreach ($values as $value) { + $matched .= $value[0]; + } + + if ($content !== trim($matched)) { + return; + } + + if ($num === 3) { + $expected = trim($content.' '.$values[1][0]); + $error = 'Shorthand syntax not allowed here; use %s instead'; + $data = [$expected]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if (substr($origContent, -10) === '!important') { + $expected .= ' !important'; + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 2), null, true); + $phpcsFile->fixer->replaceToken($next, $expected); + for ($next++; $next < $end; $next++) { + $phpcsFile->fixer->replaceToken($next, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + }//end if + + if ($num === 2) { + if ($values[0][0] !== $values[1][0]) { + // Both values are different, so it is already shorthand. + return; + } + } else if ($values[0][0] !== $values[2][0] || $values[1][0] !== $values[3][0]) { + // Can't shorthand this. + return; + } + + if ($values[0][0] === $values[1][0]) { + // All values are the same. + $expected = trim($values[0][0]); + } else { + $expected = trim($values[0][0]).' '.trim($values[1][0]); + } + + $error = 'Size definitions must use shorthand if available; expected "%s" but found "%s"'; + $data = [ + $expected, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotUsed', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if (substr($origContent, -10) === '!important') { + $expected .= ' !important'; + } + + $next = $phpcsFile->findNext(T_COLON, ($stackPtr + 1)); + $phpcsFile->fixer->addContent($next, ' '.$expected); + for ($next++; $next < $end; $next++) { + $phpcsFile->fixer->replaceToken($next, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.php new file mode 100644 index 00000000..3d2c4db1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.php @@ -0,0 +1,206 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes\ClassDeclarationSniff as PSR2ClassDeclarationSniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDeclarationSniff extends PSR2ClassDeclarationSniff +{ + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // We want all the errors from the PSR2 standard, plus some of our own. + parent::process($phpcsFile, $stackPtr); + + // Check that this is the only class or interface in the file. + $nextClass = $phpcsFile->findNext([T_CLASS, T_INTERFACE], ($stackPtr + 1)); + if ($nextClass !== false) { + // We have another, so an error is thrown. + $error = 'Only one interface or class is allowed in a file'; + $phpcsFile->addError($error, $nextClass, 'MultipleClasses'); + } + + }//end process() + + + /** + * Processes the opening section of a class declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processOpen(File $phpcsFile, $stackPtr) + { + parent::processOpen($phpcsFile, $stackPtr); + + $tokens = $phpcsFile->getTokens(); + + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $prevContent = $tokens[($stackPtr - 1)]['content']; + if ($prevContent !== $phpcsFile->eolChar) { + $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar)); + $spaces = strlen($blankSpace); + + if ($tokens[($stackPtr - 2)]['code'] !== T_ABSTRACT + && $tokens[($stackPtr - 2)]['code'] !== T_FINAL + ) { + if ($spaces !== 0) { + $type = strtolower($tokens[$stackPtr]['content']); + $error = 'Expected 0 spaces before %s keyword; %s found'; + $data = [ + $type, + $spaces, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeKeyword', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ''); + } + } + } + }//end if + }//end if + + }//end processOpen() + + + /** + * Processes the closing section of a class declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processClose(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $closeBrace = $tokens[$stackPtr]['scope_closer']; + + // Check that the closing brace has one blank line after it. + for ($nextContent = ($closeBrace + 1); $nextContent < $phpcsFile->numTokens; $nextContent++) { + // Ignore comments on the same line as the brace. + if ($tokens[$nextContent]['line'] === $tokens[$closeBrace]['line'] + && ($tokens[$nextContent]['code'] === T_WHITESPACE + || $tokens[$nextContent]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$nextContent]['code']]) === true) + ) { + continue; + } + + if ($tokens[$nextContent]['code'] !== T_WHITESPACE) { + break; + } + } + + if ($nextContent === $phpcsFile->numTokens) { + // Ignore the line check as this is the very end of the file. + $difference = 1; + } else { + $difference = ($tokens[$nextContent]['line'] - $tokens[$closeBrace]['line'] - 1); + } + + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), $stackPtr, true); + + if ($difference === -1 + || $tokens[$lastContent]['line'] === $tokens[$closeBrace]['line'] + ) { + $error = 'Closing %s brace must be on a line by itself'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'CloseBraceSameLine', $data); + if ($fix === true) { + if ($difference === -1) { + $phpcsFile->fixer->addNewlineBefore($nextContent); + } + + if ($tokens[$lastContent]['line'] === $tokens[$closeBrace]['line']) { + $phpcsFile->fixer->addNewlineBefore($closeBrace); + } + } + } else if ($tokens[($closeBrace - 1)]['code'] === T_WHITESPACE) { + $prevContent = $tokens[($closeBrace - 1)]['content']; + if ($prevContent !== $phpcsFile->eolChar) { + $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar)); + $spaces = strlen($blankSpace); + if ($spaces !== 0) { + if ($tokens[($closeBrace - 1)]['line'] !== $tokens[$closeBrace]['line']) { + $error = 'Expected 0 spaces before closing brace; newline found'; + $phpcsFile->addError($error, $closeBrace, 'NewLineBeforeCloseBrace'); + } else { + $error = 'Expected 0 spaces before closing brace; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpaceBeforeCloseBrace', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closeBrace - 1), ''); + } + } + } + } + }//end if + + if ($difference !== -1 && $difference !== 1) { + if ($tokens[$nextContent]['code'] === T_DOC_COMMENT_OPEN_TAG) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($tokens[$nextContent]['comment_closer'] + 1), null, true); + if ($next !== false && $tokens[$next]['code'] === T_FUNCTION) { + return; + } + } + + $error = 'Closing brace of a %s must be followed by a single blank line; found %s'; + $data = [ + $tokens[$stackPtr]['content'], + $difference, + ]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'NewlinesAfterCloseBrace', $data); + if ($fix === true) { + if ($difference === 0) { + $first = $phpcsFile->findFirstOnLine([], $nextContent, true); + $phpcsFile->fixer->addNewlineBefore($first); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closeBrace + 1); $i < $nextContent; $i++) { + if ($tokens[$i]['line'] <= ($tokens[$closeBrace]['line'] + 1)) { + continue; + } else if ($tokens[$i]['line'] === $tokens[$nextContent]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end processClose() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassFileNameSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassFileNameSniff.php new file mode 100644 index 00000000..88a7e0da --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassFileNameSniff.php @@ -0,0 +1,70 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClassFileNameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $fullPath = basename($phpcsFile->getFilename()); + $fileName = substr($fullPath, 0, strrpos($fullPath, '.')); + if ($fileName === '') { + // No filename probably means STDIN, so we can't do this check. + return; + } + + $tokens = $phpcsFile->getTokens(); + $decName = $phpcsFile->findNext(T_STRING, $stackPtr); + + if ($tokens[$decName]['content'] !== $fileName) { + $error = '%s name doesn\'t match filename; expected "%s %s"'; + $data = [ + ucfirst($tokens[$stackPtr]['content']), + $tokens[$stackPtr]['content'], + $fileName, + ]; + $phpcsFile->addError($error, $stackPtr, 'NoMatch', $data); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/DuplicatePropertySniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/DuplicatePropertySniff.php new file mode 100644 index 00000000..a632f81e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/DuplicatePropertySniff.php @@ -0,0 +1,82 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DuplicatePropertySniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OBJECT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being processed. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $properties = []; + $wantedTokens = [ + T_PROPERTY, + T_OBJECT, + ]; + + $next = $phpcsFile->findNext($wantedTokens, ($stackPtr + 1), $tokens[$stackPtr]['bracket_closer']); + while ($next !== false && $next < $tokens[$stackPtr]['bracket_closer']) { + if ($tokens[$next]['code'] === T_OBJECT) { + // Skip nested objects. + $next = $tokens[$next]['bracket_closer']; + } else { + $propName = $tokens[$next]['content']; + if (isset($properties[$propName]) === true) { + $error = 'Duplicate property definition found for "%s"; previously defined on line %s'; + $data = [ + $propName, + $tokens[$properties[$propName]]['line'], + ]; + $phpcsFile->addError($error, $next, 'Found', $data); + } + + $properties[$propName] = $next; + }//end if + + $next = $phpcsFile->findNext($wantedTokens, ($next + 1), $tokens[$stackPtr]['bracket_closer']); + }//end while + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/LowercaseClassKeywordsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/LowercaseClassKeywordsSniff.php new file mode 100644 index 00000000..5f4f78c0 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/LowercaseClassKeywordsSniff.php @@ -0,0 +1,72 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LowercaseClassKeywordsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $targets = Tokens::$ooScopeTokens; + $targets[] = T_EXTENDS; + $targets[] = T_IMPLEMENTS; + $targets[] = T_ABSTRACT; + $targets[] = T_FINAL; + $targets[] = T_VAR; + $targets[] = T_CONST; + + return $targets; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $contentLc = strtolower($content); + if ($content !== $contentLc) { + $error = '%s keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + strtoupper($content), + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FoundUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php new file mode 100644 index 00000000..d17ca44c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php @@ -0,0 +1,240 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Tokens; + +class SelfMemberReferenceSniff extends AbstractScopeSniff +{ + + + /** + * Constructs a Squiz_Sniffs_Classes_SelfMemberReferenceSniff. + */ + public function __construct() + { + parent::__construct([T_CLASS], [T_DOUBLE_COLON]); + + }//end __construct() + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * @param int $currScope The current scope opener token. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a double colon which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + $conditions = array_reverse($conditions, true); + foreach ($conditions as $conditionToken => $tokenCode) { + if ($tokenCode === T_CLASS || $tokenCode === T_ANON_CLASS || $tokenCode === T_CLOSURE) { + break; + } + } + + if ($conditionToken !== $currScope) { + return; + } + + $calledClassName = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($calledClassName === false) { + // Parse error. + return; + } + + if ($tokens[$calledClassName]['code'] === T_SELF) { + if ($tokens[$calledClassName]['content'] !== 'self') { + $error = 'Must use "self::" for local static member reference; found "%s::"'; + $data = [$tokens[$calledClassName]['content']]; + $fix = $phpcsFile->addFixableError($error, $calledClassName, 'IncorrectCase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($calledClassName, 'self'); + } + + return; + } + } else if ($tokens[$calledClassName]['code'] === T_STRING) { + // If the class is called with a namespace prefix, build fully qualified + // namespace calls for both current scope class and requested class. + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($calledClassName - 1), null, true); + if ($prevNonEmpty !== false && $tokens[$prevNonEmpty]['code'] === T_NS_SEPARATOR) { + $declarationName = $this->getDeclarationNameWithNamespace($tokens, $calledClassName); + $declarationName = ltrim($declarationName, '\\'); + $fullQualifiedClassName = $this->getNamespaceOfScope($phpcsFile, $currScope); + if ($fullQualifiedClassName === '\\') { + $fullQualifiedClassName = ''; + } else { + $fullQualifiedClassName .= '\\'; + } + + $fullQualifiedClassName .= $phpcsFile->getDeclarationName($currScope); + } else { + $declarationName = $phpcsFile->getDeclarationName($currScope); + $fullQualifiedClassName = $tokens[$calledClassName]['content']; + } + + if ($declarationName === $fullQualifiedClassName) { + // Class name is the same as the current class, which is not allowed. + $error = 'Must use "self::" for local static member reference'; + $fix = $phpcsFile->addFixableError($error, $calledClassName, 'NotUsed'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $currentPointer = ($stackPtr - 1); + while ($tokens[$currentPointer]['code'] === T_NS_SEPARATOR + || $tokens[$currentPointer]['code'] === T_STRING + || isset(Tokens::$emptyTokens[$tokens[$currentPointer]['code']]) === true + ) { + if (isset(Tokens::$emptyTokens[$tokens[$currentPointer]['code']]) === true) { + --$currentPointer; + continue; + } + + $phpcsFile->fixer->replaceToken($currentPointer, ''); + --$currentPointer; + } + + $phpcsFile->fixer->replaceToken($stackPtr, 'self::'); + $phpcsFile->fixer->endChangeset(); + + // Fix potential whitespace issues in the next loop. + return; + }//end if + }//end if + }//end if + + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($stackPtr - 1)]['length']; + $error = 'Expected 0 spaces before double colon; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, ($stackPtr - 1), 'SpaceBefore', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($stackPtr - 1); $tokens[$i]['code'] === T_WHITESPACE; $i--) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($stackPtr + 1)]['length']; + $error = 'Expected 0 spaces after double colon; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, ($stackPtr - 1), 'SpaceAfter', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($stackPtr + 1); $tokens[$i]['code'] === T_WHITESPACE; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + }//end processTokenWithinScope() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + + /** + * Returns the declaration names for classes/interfaces/functions with a namespace. + * + * @param array $tokens Token stack for this file + * @param int $stackPtr The position where the namespace building will start. + * + * @return string + */ + protected function getDeclarationNameWithNamespace(array $tokens, $stackPtr) + { + $nameParts = []; + $currentPointer = $stackPtr; + while ($tokens[$currentPointer]['code'] === T_NS_SEPARATOR + || $tokens[$currentPointer]['code'] === T_STRING + || isset(Tokens::$emptyTokens[$tokens[$currentPointer]['code']]) === true + ) { + if (isset(Tokens::$emptyTokens[$tokens[$currentPointer]['code']]) === true) { + --$currentPointer; + continue; + } + + $nameParts[] = $tokens[$currentPointer]['content']; + --$currentPointer; + } + + $nameParts = array_reverse($nameParts); + return implode('', $nameParts); + + }//end getDeclarationNameWithNamespace() + + + /** + * Returns the namespace declaration of a file. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the search for the + * namespace declaration will start. + * + * @return string + */ + protected function getNamespaceOfScope(File $phpcsFile, $stackPtr) + { + $namespace = '\\'; + $namespaceDeclaration = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr); + + if ($namespaceDeclaration !== false) { + $endOfNamespaceDeclaration = $phpcsFile->findNext([T_SEMICOLON, T_OPEN_CURLY_BRACKET], $namespaceDeclaration); + $namespace = $this->getDeclarationNameWithNamespace( + $phpcsFile->getTokens(), + ($endOfNamespaceDeclaration - 1) + ); + } + + return $namespace; + + }//end getNamespaceOfScope() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ValidClassNameSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ValidClassNameSniff.php new file mode 100644 index 00000000..ffddd2cd --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ValidClassNameSniff.php @@ -0,0 +1,87 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class ValidClassNameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being processed. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + $error = 'Possible parse error: %s missing opening or closing brace'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $data); + return; + } + + // Determine the name of the class or interface. Note that we cannot + // simply look for the first T_STRING because a class name + // starting with the number will be multiple tokens. + $opener = $tokens[$stackPtr]['scope_opener']; + $nameStart = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), $opener, true); + $nameEnd = $phpcsFile->findNext([T_WHITESPACE, T_COLON], $nameStart, $opener); + if ($nameEnd === false) { + $name = $tokens[$nameStart]['content']; + } else { + $name = trim($phpcsFile->getTokensAsString($nameStart, ($nameEnd - $nameStart))); + } + + // Check for PascalCase format. + $valid = Common::isCamelCaps($name, true, true, false); + if ($valid === false) { + $type = ucfirst($tokens[$stackPtr]['content']); + $error = '%s name "%s" is not in PascalCase format'; + $data = [ + $type, + $name, + ]; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data); + $phpcsFile->recordMetric($stackPtr, 'PascalCase class name', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'PascalCase class name', 'yes'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php new file mode 100644 index 00000000..eb647f5f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php @@ -0,0 +1,401 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class BlockCommentSniff implements Sniff +{ + + /** + * The --tab-width CLI value that is being used. + * + * @var integer + */ + private $tabWidth = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_COMMENT, + T_DOC_COMMENT_OPEN_TAG, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->tabWidth === null) { + if (isset($phpcsFile->config->tabWidth) === false || $phpcsFile->config->tabWidth === 0) { + // We have no idea how wide tabs are, so assume 4 spaces for fixing. + $this->tabWidth = 4; + } else { + $this->tabWidth = $phpcsFile->config->tabWidth; + } + } + + $tokens = $phpcsFile->getTokens(); + + // If it's an inline comment, return. + if (substr($tokens[$stackPtr]['content'], 0, 2) !== '/*') { + return; + } + + // If this is a function/class/interface doc block comment, skip it. + // We are only interested in inline doc block comments. + if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT_OPEN_TAG) { + $nextToken = $stackPtr; + do { + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] === T_ATTRIBUTE) { + $nextToken = $tokens[$nextToken]['attribute_closer']; + continue; + } + + break; + } while (true); + + $ignore = [ + T_CLASS => true, + T_INTERFACE => true, + T_TRAIT => true, + T_ENUM => true, + T_FUNCTION => true, + T_PUBLIC => true, + T_PRIVATE => true, + T_FINAL => true, + T_PROTECTED => true, + T_STATIC => true, + T_ABSTRACT => true, + T_CONST => true, + T_VAR => true, + T_READONLY => true, + ]; + if (isset($ignore[$tokens[$nextToken]['code']]) === true) { + return; + } + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prevToken]['code'] === T_OPEN_TAG) { + return; + } + + $error = 'Block comments must be started with /*'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'WrongStart'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, '/*'); + } + + $end = $tokens[$stackPtr]['comment_closer']; + if ($tokens[$end]['content'] !== '*/') { + $error = 'Block comments must be ended with */'; + $fix = $phpcsFile->addFixableError($error, $end, 'WrongEnd'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($end, '*/'); + } + } + + return; + }//end if + + $commentLines = [$stackPtr]; + $nextComment = $stackPtr; + $lastLine = $tokens[$stackPtr]['line']; + $commentString = $tokens[$stackPtr]['content']; + + // Construct the comment into an array. + while (($nextComment = $phpcsFile->findNext(T_WHITESPACE, ($nextComment + 1), null, true)) !== false) { + if ($tokens[$nextComment]['code'] !== $tokens[$stackPtr]['code'] + && isset(Tokens::$phpcsCommentTokens[$tokens[$nextComment]['code']]) === false + ) { + // Found the next bit of code. + break; + } + + if (($tokens[$nextComment]['line'] - 1) !== $lastLine) { + // Not part of the block. + break; + } + + $lastLine = $tokens[$nextComment]['line']; + $commentLines[] = $nextComment; + $commentString .= $tokens[$nextComment]['content']; + if ($tokens[$nextComment]['code'] === T_DOC_COMMENT_CLOSE_TAG + || substr($tokens[$nextComment]['content'], -2) === '*/' + ) { + break; + } + }//end while + + $commentText = str_replace($phpcsFile->eolChar, '', $commentString); + $commentText = trim($commentText, "/* \t"); + if ($commentText === '') { + $error = 'Empty block comment not allowed'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Empty'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($stackPtr, ''); + $lastToken = array_pop($commentLines); + for ($i = ($stackPtr + 1); $i <= $lastToken; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + } + + if (count($commentLines) === 1) { + $error = 'Single line block comment not allowed; use inline ("// text") comment instead'; + + // Only fix comments when they are the last token on a line. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line']) { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SingleLine'); + if ($fix === true) { + $comment = '// '.$commentText.$phpcsFile->eolChar; + $phpcsFile->fixer->replaceToken($stackPtr, $comment); + } + } else { + $phpcsFile->addError($error, $stackPtr, 'SingleLine'); + } + + return; + } + + $content = trim($tokens[$stackPtr]['content']); + if ($content !== '/*' && $content !== '/**') { + $error = 'Block comment text must start on a new line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoNewLine'); + if ($fix === true) { + $indent = ''; + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + if (isset($tokens[($stackPtr - 1)]['orig_content']) === true) { + $indent = $tokens[($stackPtr - 1)]['orig_content']; + } else { + $indent = $tokens[($stackPtr - 1)]['content']; + } + } + + $comment = preg_replace( + '/^(\s*\/\*\*?)/', + '$1'.$phpcsFile->eolChar.$indent, + $tokens[$stackPtr]['content'], + 1 + ); + $phpcsFile->fixer->replaceToken($stackPtr, $comment); + } + + return; + }//end if + + $starColumn = $tokens[$stackPtr]['column']; + $hasStars = false; + + // Make sure first line isn't blank. + if (trim($tokens[$commentLines[1]]['content']) === '') { + $error = 'Empty line not allowed at start of comment'; + $fix = $phpcsFile->addFixableError($error, $commentLines[1], 'HasEmptyLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($commentLines[1], ''); + } + } else { + // Check indentation of first line. + $content = $tokens[$commentLines[1]]['content']; + $commentText = ltrim($content); + $leadingSpace = (strlen($content) - strlen($commentText)); + + $expected = ($starColumn + 3); + if ($commentText[0] === '*') { + $expected = $starColumn; + $hasStars = true; + } + + if ($leadingSpace !== $expected) { + $expectedTxt = $expected.' space'; + if ($expected !== 1) { + $expectedTxt .= 's'; + } + + $data = [ + $expectedTxt, + $leadingSpace, + ]; + + $error = 'First line of comment not aligned correctly; expected %s but found %s'; + $fix = $phpcsFile->addFixableError($error, $commentLines[1], 'FirstLineIndent', $data); + if ($fix === true) { + if (isset($tokens[$commentLines[1]]['orig_content']) === true + && $tokens[$commentLines[1]]['orig_content'][0] === "\t" + ) { + // Line is indented using tabs. + $padding = str_repeat("\t", floor($expected / $this->tabWidth)); + $padding .= str_repeat(' ', ($expected % $this->tabWidth)); + } else { + $padding = str_repeat(' ', $expected); + } + + $phpcsFile->fixer->replaceToken($commentLines[1], $padding.$commentText); + } + }//end if + + if (preg_match('/^\p{Ll}/u', $commentText) === 1) { + $error = 'Block comments must start with a capital letter'; + $phpcsFile->addError($error, $commentLines[1], 'NoCapital'); + } + }//end if + + // Check that each line of the comment is indented past the star. + foreach ($commentLines as $line) { + // First and last lines (comment opener and closer) are handled separately. + if ($line === $commentLines[(count($commentLines) - 1)] || $line === $commentLines[0]) { + continue; + } + + // First comment line was handled above. + if ($line === $commentLines[1]) { + continue; + } + + // If it's empty, continue. + if (trim($tokens[$line]['content']) === '') { + continue; + } + + $commentText = ltrim($tokens[$line]['content']); + $leadingSpace = (strlen($tokens[$line]['content']) - strlen($commentText)); + + $expected = ($starColumn + 3); + if ($commentText[0] === '*') { + $expected = $starColumn; + $hasStars = true; + } + + if ($leadingSpace < $expected) { + $expectedTxt = $expected.' space'; + if ($expected !== 1) { + $expectedTxt .= 's'; + } + + $data = [ + $expectedTxt, + $leadingSpace, + ]; + + $error = 'Comment line indented incorrectly; expected at least %s but found %s'; + $fix = $phpcsFile->addFixableError($error, $line, 'LineIndent', $data); + if ($fix === true) { + if (isset($tokens[$line]['orig_content']) === true + && $tokens[$line]['orig_content'][0] === "\t" + ) { + // Line is indented using tabs. + $padding = str_repeat("\t", floor($expected / $this->tabWidth)); + $padding .= str_repeat(' ', ($expected % $this->tabWidth)); + } else { + $padding = str_repeat(' ', $expected); + } + + $phpcsFile->fixer->replaceToken($line, $padding.$commentText); + } + }//end if + }//end foreach + + // Finally, test the last line is correct. + $lastIndex = (count($commentLines) - 1); + $content = $tokens[$commentLines[$lastIndex]]['content']; + $commentText = ltrim($content); + if ($commentText !== '*/' && $commentText !== '**/') { + $error = 'Comment closer must be on a new line'; + $phpcsFile->addError($error, $commentLines[$lastIndex], 'CloserSameLine'); + } else { + $leadingSpace = (strlen($content) - strlen($commentText)); + + $expected = ($starColumn - 1); + if ($hasStars === true) { + $expected = $starColumn; + } + + if ($leadingSpace !== $expected) { + $expectedTxt = $expected.' space'; + if ($expected !== 1) { + $expectedTxt .= 's'; + } + + $data = [ + $expectedTxt, + $leadingSpace, + ]; + + $error = 'Last line of comment aligned incorrectly; expected %s but found %s'; + $fix = $phpcsFile->addFixableError($error, $commentLines[$lastIndex], 'LastLineIndent', $data); + if ($fix === true) { + if (isset($tokens[$line]['orig_content']) === true + && $tokens[$line]['orig_content'][0] === "\t" + ) { + // Line is indented using tabs. + $padding = str_repeat("\t", floor($expected / $this->tabWidth)); + $padding .= str_repeat(' ', ($expected % $this->tabWidth)); + } else { + $padding = str_repeat(' ', $expected); + } + + $phpcsFile->fixer->replaceToken($commentLines[$lastIndex], $padding.$commentText); + } + }//end if + }//end if + + // Check that the lines before and after this comment are blank. + $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ((isset($tokens[$contentBefore]['scope_closer']) === true + && $tokens[$contentBefore]['scope_opener'] === $contentBefore) + || $tokens[$contentBefore]['code'] === T_OPEN_TAG + || $tokens[$contentBefore]['code'] === T_OPEN_TAG_WITH_ECHO + ) { + if (($tokens[$stackPtr]['line'] - $tokens[$contentBefore]['line']) !== 1) { + $error = 'Empty line not required before block comment'; + $phpcsFile->addError($error, $stackPtr, 'HasEmptyLineBefore'); + } + } else { + if (($tokens[$stackPtr]['line'] - $tokens[$contentBefore]['line']) < 2) { + $error = 'Empty line required before block comment'; + $phpcsFile->addError($error, $stackPtr, 'NoEmptyLineBefore'); + } + } + + $commentCloser = $commentLines[$lastIndex]; + $contentAfter = $phpcsFile->findNext(T_WHITESPACE, ($commentCloser + 1), null, true); + if ($contentAfter !== false && ($tokens[$contentAfter]['line'] - $tokens[$commentCloser]['line']) < 2) { + $error = 'Empty line required after block comment'; + $phpcsFile->addError($error, $commentCloser, 'NoEmptyLineAfter'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClassCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClassCommentSniff.php new file mode 100644 index 00000000..0da4ef24 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClassCommentSniff.php @@ -0,0 +1,106 @@ + + *
  • A class doc comment exists.
  • + *
  • The comment uses the correct docblock style.
  • + *
  • There are no blank lines after the class comment.
  • + *
  • No tags are used in the docblock.
  • + * + * + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassCommentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $find = Tokens::$methodPrefixes; + $find[T_WHITESPACE] = T_WHITESPACE; + + $previousContent = null; + for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { + if (isset($find[$tokens[$commentEnd]['code']]) === true) { + continue; + } + + if ($previousContent === null) { + $previousContent = $commentEnd; + } + + if ($tokens[$commentEnd]['code'] === T_ATTRIBUTE_END + && isset($tokens[$commentEnd]['attribute_opener']) === true + ) { + $commentEnd = $tokens[$commentEnd]['attribute_opener']; + continue; + } + + break; + } + + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG + && $tokens[$commentEnd]['code'] !== T_COMMENT + ) { + $class = $phpcsFile->getDeclarationName($stackPtr); + $phpcsFile->addError('Missing doc comment for class %s', $stackPtr, 'Missing', [$class]); + $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'no'); + return; + } + + $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'yes'); + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a class comment', $stackPtr, 'WrongStyle'); + return; + } + + if ($tokens[$previousContent]['line'] !== ($tokens[$stackPtr]['line'] - 1)) { + $error = 'There must be no blank lines after the class comment'; + $phpcsFile->addError($error, $commentEnd, 'SpacingAfter'); + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + $error = '%s tag is not allowed in class comment'; + $data = [$tokens[$tag]['content']]; + $phpcsFile->addWarning($error, $tag, 'TagNotAllowed', $data); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClosingDeclarationCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClosingDeclarationCommentSniff.php new file mode 100644 index 00000000..cd509d0c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClosingDeclarationCommentSniff.php @@ -0,0 +1,132 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClosingDeclarationCommentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLASS, + T_INTERFACE, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens.. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_FUNCTION) { + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + + // Abstract methods do not require a closing comment. + if ($methodProps['is_abstract'] === true) { + return; + } + + // If this function is in an interface then we don't require + // a closing comment. + if ($phpcsFile->hasCondition($stackPtr, T_INTERFACE) === true) { + return; + } + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + $error = 'Possible parse error: non-abstract method defined as abstract'; + $phpcsFile->addWarning($error, $stackPtr, 'Abstract'); + return; + } + + $decName = $phpcsFile->getDeclarationName($stackPtr); + $comment = '//end '.$decName.'()'; + } else if ($tokens[$stackPtr]['code'] === T_CLASS) { + $comment = '//end class'; + } else if ($tokens[$stackPtr]['code'] === T_INTERFACE) { + $comment = '//end interface'; + } else { + $comment = '//end enum'; + }//end if + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + $error = 'Possible parse error: %s missing opening or closing brace'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $data); + return; + } + + $closingBracket = $tokens[$stackPtr]['scope_closer']; + + if ($closingBracket === null) { + // Possible inline structure. Other tests will handle it. + return; + } + + $data = [$comment]; + if (isset($tokens[($closingBracket + 1)]) === false || $tokens[($closingBracket + 1)]['code'] !== T_COMMENT) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($closingBracket + 1), null, true); + if (rtrim($tokens[$next]['content']) === $comment) { + // The comment isn't really missing; it is just in the wrong place. + $fix = $phpcsFile->addFixableError('Expected %s directly after closing brace', $closingBracket, 'Misplaced', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closingBracket + 1); $i < $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + // Just in case, because indentation fixes can add indents onto + // these comments and cause us to be unable to fix them. + $phpcsFile->fixer->replaceToken($next, $comment.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + } else { + $fix = $phpcsFile->addFixableError('Expected %s', $closingBracket, 'Missing', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($closingBracket, '}'.$comment.$phpcsFile->eolChar); + } + } + + return; + }//end if + + if (rtrim($tokens[($closingBracket + 1)]['content']) !== $comment) { + $fix = $phpcsFile->addFixableError('Expected %s', $closingBracket, 'Incorrect', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closingBracket + 1), $comment.$phpcsFile->eolChar); + } + + return; + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/DocCommentAlignmentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/DocCommentAlignmentSniff.php new file mode 100644 index 00000000..1f49d2c0 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/DocCommentAlignmentSniff.php @@ -0,0 +1,161 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DocCommentAlignmentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOC_COMMENT_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // We are only interested in function/class/interface doc block comments. + $ignore = Tokens::$emptyTokens; + if ($phpcsFile->tokenizerType === 'JS') { + $ignore[] = T_EQUAL; + $ignore[] = T_STRING; + $ignore[] = T_OBJECT_OPERATOR; + } + + $nextToken = $phpcsFile->findNext($ignore, ($stackPtr + 1), null, true); + $ignore = [ + T_CLASS => true, + T_INTERFACE => true, + T_ENUM => true, + T_ENUM_CASE => true, + T_FUNCTION => true, + T_PUBLIC => true, + T_PRIVATE => true, + T_PROTECTED => true, + T_STATIC => true, + T_ABSTRACT => true, + T_PROPERTY => true, + T_OBJECT => true, + T_PROTOTYPE => true, + T_VAR => true, + T_READONLY => true, + ]; + + if ($nextToken === false || isset($ignore[$tokens[$nextToken]['code']]) === false) { + // Could be a file comment. + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prevToken]['code'] !== T_OPEN_TAG) { + return; + } + } + + // There must be one space after each star (unless it is an empty comment line) + // and all the stars must be aligned correctly. + $requiredColumn = ($tokens[$stackPtr]['column'] + 1); + $endComment = $tokens[$stackPtr]['comment_closer']; + for ($i = ($stackPtr + 1); $i <= $endComment; $i++) { + if ($tokens[$i]['code'] !== T_DOC_COMMENT_STAR + && $tokens[$i]['code'] !== T_DOC_COMMENT_CLOSE_TAG + ) { + continue; + } + + if ($tokens[$i]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + if (trim($tokens[$i]['content']) === '') { + // Don't process an unfinished docblock close tag during live coding. + continue; + } + + // Can't process the close tag if it is not the first thing on the line. + $prev = $phpcsFile->findPrevious(T_DOC_COMMENT_WHITESPACE, ($i - 1), $stackPtr, true); + if ($tokens[$prev]['line'] === $tokens[$i]['line']) { + continue; + } + } + + if ($tokens[$i]['column'] !== $requiredColumn) { + $error = 'Expected %s space(s) before asterisk; %s found'; + $data = [ + ($requiredColumn - 1), + ($tokens[$i]['column'] - 1), + ]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeStar', $data); + if ($fix === true) { + $padding = str_repeat(' ', ($requiredColumn - 1)); + if ($tokens[$i]['column'] === 1) { + $phpcsFile->fixer->addContentBefore($i, $padding); + } else { + $phpcsFile->fixer->replaceToken(($i - 1), $padding); + } + } + } + + if ($tokens[$i]['code'] !== T_DOC_COMMENT_STAR) { + continue; + } + + if ($tokens[($i + 2)]['line'] !== $tokens[$i]['line']) { + // Line is empty. + continue; + } + + if ($tokens[($i + 1)]['code'] !== T_DOC_COMMENT_WHITESPACE) { + $error = 'Expected 1 space after asterisk; 0 found'; + $fix = $phpcsFile->addFixableError($error, $i, 'NoSpaceAfterStar'); + if ($fix === true) { + $phpcsFile->fixer->addContent($i, ' '); + } + } else if ($tokens[($i + 2)]['code'] === T_DOC_COMMENT_TAG + && $tokens[($i + 1)]['content'] !== ' ' + ) { + $error = 'Expected 1 space after asterisk; %s found'; + $data = [$tokens[($i + 1)]['length']]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterStar', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($i + 1), ' '); + } + } + }//end for + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/EmptyCatchCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/EmptyCatchCommentSniff.php new file mode 100644 index 00000000..4fc25219 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/EmptyCatchCommentSniff.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EmptyCatchCommentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CATCH]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile All the tokens found in the document. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $scopeStart = $tokens[$stackPtr]['scope_opener']; + $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($scopeStart + 1), $tokens[$stackPtr]['scope_closer'], true); + + if ($firstContent === false) { + $error = 'Empty CATCH statement must have a comment to explain why the exception is not handled'; + $phpcsFile->addError($error, $scopeStart, 'Missing'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FileCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FileCommentSniff.php new file mode 100644 index 00000000..08aaae29 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FileCommentSniff.php @@ -0,0 +1,227 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FileCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $commentStart = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + + if ($tokens[$commentStart]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a file comment', $commentStart, 'WrongStyle'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'yes'); + return ($phpcsFile->numTokens + 1); + } else if ($commentStart === false || $tokens[$commentStart]['code'] !== T_DOC_COMMENT_OPEN_TAG) { + $phpcsFile->addError('Missing file doc comment', $stackPtr, 'Missing'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'no'); + return ($phpcsFile->numTokens + 1); + } + + if (isset($tokens[$commentStart]['comment_closer']) === false + || ($tokens[$tokens[$commentStart]['comment_closer']]['content'] === '' + && $tokens[$commentStart]['comment_closer'] === ($phpcsFile->numTokens - 1)) + ) { + // Don't process an unfinished file comment during live coding. + return ($phpcsFile->numTokens + 1); + } + + $commentEnd = $tokens[$commentStart]['comment_closer']; + + for ($nextToken = ($commentEnd + 1); $nextToken < $phpcsFile->numTokens; $nextToken++) { + if ($tokens[$nextToken]['code'] === T_WHITESPACE) { + continue; + } + + if ($tokens[$nextToken]['code'] === T_ATTRIBUTE + && isset($tokens[$nextToken]['attribute_closer']) === true + ) { + $nextToken = $tokens[$nextToken]['attribute_closer']; + continue; + } + + break; + } + + if ($nextToken === $phpcsFile->numTokens) { + $nextToken--; + } + + $ignore = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_FUNCTION, + T_CLOSURE, + T_PUBLIC, + T_PRIVATE, + T_PROTECTED, + T_FINAL, + T_STATIC, + T_ABSTRACT, + T_CONST, + T_PROPERTY, + T_INCLUDE, + T_INCLUDE_ONCE, + T_REQUIRE, + T_REQUIRE_ONCE, + ]; + + if (in_array($tokens[$nextToken]['code'], $ignore, true) === true) { + $phpcsFile->addError('Missing file doc comment', $stackPtr, 'Missing'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'no'); + return ($phpcsFile->numTokens + 1); + } + + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'yes'); + + // No blank line between the open tag and the file comment. + if ($tokens[$commentStart]['line'] > ($tokens[$stackPtr]['line'] + 1)) { + $error = 'There must be no blank lines before the file comment'; + $phpcsFile->addError($error, $stackPtr, 'SpacingAfterOpen'); + } + + // Exactly one blank line after the file comment. + $next = $phpcsFile->findNext(T_WHITESPACE, ($commentEnd + 1), null, true); + if ($next !== false && $tokens[$next]['line'] !== ($tokens[$commentEnd]['line'] + 2)) { + $error = 'There must be exactly one blank line after the file comment'; + $phpcsFile->addError($error, $commentEnd, 'SpacingAfterComment'); + } + + // Required tags in correct order. + $required = [ + '@package' => true, + '@subpackage' => true, + '@author' => true, + '@copyright' => true, + ]; + + $foundTags = []; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + $name = $tokens[$tag]['content']; + $isRequired = isset($required[$name]); + + if ($isRequired === true && in_array($name, $foundTags, true) === true) { + $error = 'Only one %s tag is allowed in a file comment'; + $data = [$name]; + $phpcsFile->addError($error, $tag, 'Duplicate'.ucfirst(substr($name, 1)).'Tag', $data); + } + + $foundTags[] = $name; + + if ($isRequired === false) { + continue; + } + + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for %s tag in file comment'; + $data = [$name]; + $phpcsFile->addError($error, $tag, 'Empty'.ucfirst(substr($name, 1)).'Tag', $data); + continue; + } + + if ($name === '@author') { + if ($tokens[$string]['content'] !== 'Squiz Pty Ltd ') { + $error = 'Expected "Squiz Pty Ltd " for author tag'; + $fix = $phpcsFile->addFixableError($error, $tag, 'IncorrectAuthor'); + if ($fix === true) { + $expected = 'Squiz Pty Ltd '; + $phpcsFile->fixer->replaceToken($string, $expected); + } + } + } else if ($name === '@copyright') { + if (preg_match('/^([0-9]{4})(-[0-9]{4})? (Squiz Pty Ltd \(ABN 77 084 670 600\))$/', $tokens[$string]['content']) === 0) { + $error = 'Expected "xxxx-xxxx Squiz Pty Ltd (ABN 77 084 670 600)" for copyright declaration'; + $fix = $phpcsFile->addFixableError($error, $tag, 'IncorrectCopyright'); + if ($fix === true) { + $matches = []; + preg_match('/^(([0-9]{4})(-[0-9]{4})?)?.*$/', $tokens[$string]['content'], $matches); + if (isset($matches[1]) === false) { + $matches[1] = date('Y'); + } + + $expected = $matches[1].' Squiz Pty Ltd (ABN 77 084 670 600)'; + $phpcsFile->fixer->replaceToken($string, $expected); + } + } + }//end if + }//end foreach + + // Check if the tags are in the correct position. + $pos = 0; + foreach ($required as $tag => $true) { + if (in_array($tag, $foundTags, true) === false) { + $error = 'Missing %s tag in file comment'; + $data = [$tag]; + $phpcsFile->addError($error, $commentEnd, 'Missing'.ucfirst(substr($tag, 1)).'Tag', $data); + } + + if (isset($foundTags[$pos]) === false) { + break; + } + + if ($foundTags[$pos] !== $tag) { + $error = 'The tag in position %s should be the %s tag'; + $data = [ + ($pos + 1), + $tag, + ]; + $phpcsFile->addError($error, $tokens[$commentStart]['comment_tags'][$pos], ucfirst(substr($tag, 1)).'TagOrder', $data); + } + + $pos++; + }//end foreach + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php new file mode 100644 index 00000000..ba3e1710 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php @@ -0,0 +1,768 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FunctionCommentSniff as PEARFunctionCommentSniff; +use PHP_CodeSniffer\Util\Common; + +class FunctionCommentSniff extends PEARFunctionCommentSniff +{ + + /** + * Whether to skip inheritdoc comments. + * + * @var boolean + */ + public $skipIfInheritdoc = false; + + /** + * The current PHP version. + * + * @var integer + */ + private $phpVersion = null; + + + /** + * Process the return comment of this function comment. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + $return = null; + + if ($this->skipIfInheritdoc === true) { + if ($this->checkInheritdoc($phpcsFile, $stackPtr, $commentStart) === true) { + return; + } + } + + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@return') { + if ($return !== null) { + $error = 'Only 1 @return tag is allowed in a function comment'; + $phpcsFile->addError($error, $tag, 'DuplicateReturn'); + return; + } + + $return = $tag; + } + } + + // Skip constructor and destructor. + $methodName = $phpcsFile->getDeclarationName($stackPtr); + $isSpecialMethod = in_array($methodName, $this->specialMethods, true); + + if ($return !== null) { + $content = $tokens[($return + 2)]['content']; + if (empty($content) === true || $tokens[($return + 2)]['code'] !== T_DOC_COMMENT_STRING) { + $error = 'Return type missing for @return tag in function comment'; + $phpcsFile->addError($error, $return, 'MissingReturnType'); + } else { + // Support both a return type and a description. + preg_match('`^((?:\|?(?:array\([^\)]*\)|[\\\\a-z0-9\[\]]+))*)( .*)?`i', $content, $returnParts); + if (isset($returnParts[1]) === false) { + return; + } + + $returnType = $returnParts[1]; + + // Check return type (can be multiple, separated by '|'). + $typeNames = explode('|', $returnType); + $suggestedNames = []; + foreach ($typeNames as $i => $typeName) { + $suggestedName = Common::suggestType($typeName); + if (in_array($suggestedName, $suggestedNames, true) === false) { + $suggestedNames[] = $suggestedName; + } + } + + $suggestedType = implode('|', $suggestedNames); + if ($returnType !== $suggestedType) { + $error = 'Expected "%s" but found "%s" for function return type'; + $data = [ + $suggestedType, + $returnType, + ]; + $fix = $phpcsFile->addFixableError($error, $return, 'InvalidReturn', $data); + if ($fix === true) { + $replacement = $suggestedType; + if (empty($returnParts[2]) === false) { + $replacement .= $returnParts[2]; + } + + $phpcsFile->fixer->replaceToken(($return + 2), $replacement); + unset($replacement); + } + } + + // If the return type is void, make sure there is + // no return statement in the function. + if ($returnType === 'void') { + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $endToken = $tokens[$stackPtr]['scope_closer']; + for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) { + if ($tokens[$returnToken]['code'] === T_CLOSURE + || $tokens[$returnToken]['code'] === T_ANON_CLASS + ) { + $returnToken = $tokens[$returnToken]['scope_closer']; + continue; + } + + if ($tokens[$returnToken]['code'] === T_RETURN + || $tokens[$returnToken]['code'] === T_YIELD + || $tokens[$returnToken]['code'] === T_YIELD_FROM + ) { + break; + } + } + + if ($returnToken !== $endToken) { + // If the function is not returning anything, just + // exiting, then there is no problem. + $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true); + if ($tokens[$semicolon]['code'] !== T_SEMICOLON) { + $error = 'Function return type is void, but function contains return statement'; + $phpcsFile->addError($error, $return, 'InvalidReturnVoid'); + } + } + }//end if + } else if ($returnType !== 'mixed' && in_array('void', $typeNames, true) === false) { + // If return type is not void, there needs to be a return statement + // somewhere in the function that returns something. + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $endToken = $tokens[$stackPtr]['scope_closer']; + for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) { + if ($tokens[$returnToken]['code'] === T_CLOSURE + || $tokens[$returnToken]['code'] === T_ANON_CLASS + ) { + $returnToken = $tokens[$returnToken]['scope_closer']; + continue; + } + + if ($tokens[$returnToken]['code'] === T_RETURN + || $tokens[$returnToken]['code'] === T_YIELD + || $tokens[$returnToken]['code'] === T_YIELD_FROM + ) { + break; + } + } + + if ($returnToken === $endToken) { + $error = 'Function return type is not void, but function has no return statement'; + $phpcsFile->addError($error, $return, 'InvalidNoReturn'); + } else { + $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true); + if ($tokens[$semicolon]['code'] === T_SEMICOLON) { + $error = 'Function return type is not void, but function is returning void here'; + $phpcsFile->addError($error, $returnToken, 'InvalidReturnNotVoid'); + } + } + }//end if + }//end if + }//end if + } else { + if ($isSpecialMethod === true) { + return; + } + + $error = 'Missing @return tag in function comment'; + $phpcsFile->addError($error, $tokens[$commentStart]['comment_closer'], 'MissingReturn'); + }//end if + + }//end processReturn() + + + /** + * Process any throw tags that this function comment has. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + if ($this->skipIfInheritdoc === true) { + if ($this->checkInheritdoc($phpcsFile, $stackPtr, $commentStart) === true) { + return; + } + } + + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($tokens[$tag]['content'] !== '@throws') { + continue; + } + + $exception = null; + $comment = null; + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = []; + preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[($tag + 2)]['content'], $matches); + $exception = $matches[1]; + if (isset($matches[2]) === true && trim($matches[2]) !== '') { + $comment = $matches[2]; + } + } + + if ($exception === null) { + $error = 'Exception type and comment missing for @throws tag in function comment'; + $phpcsFile->addError($error, $tag, 'InvalidThrows'); + } else if ($comment === null) { + $error = 'Comment missing for @throws tag in function comment'; + $phpcsFile->addError($error, $tag, 'EmptyThrows'); + } else { + // Any strings until the next tag belong to this comment. + if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) { + $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; + } else { + $end = $tokens[$commentStart]['comment_closer']; + } + + for ($i = ($tag + 3); $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + $comment .= ' '.$tokens[$i]['content']; + } + } + + $comment = trim($comment); + + // Starts with a capital letter and ends with a fullstop. + $firstChar = $comment[0]; + if (strtoupper($firstChar) !== $firstChar) { + $error = '@throws tag comment must start with a capital letter'; + $phpcsFile->addError($error, ($tag + 2), 'ThrowsNotCapital'); + } + + $lastChar = substr($comment, -1); + if ($lastChar !== '.') { + $error = '@throws tag comment must end with a full stop'; + $phpcsFile->addError($error, ($tag + 2), 'ThrowsNoFullStop'); + } + }//end if + }//end foreach + + }//end processThrows() + + + /** + * Process the function parameter comments. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processParams(File $phpcsFile, $stackPtr, $commentStart) + { + if ($this->phpVersion === null) { + $this->phpVersion = Config::getConfigData('php_version'); + if ($this->phpVersion === null) { + $this->phpVersion = PHP_VERSION_ID; + } + } + + $tokens = $phpcsFile->getTokens(); + + if ($this->skipIfInheritdoc === true) { + if ($this->checkInheritdoc($phpcsFile, $stackPtr, $commentStart) === true) { + return; + } + } + + $params = []; + $maxType = 0; + $maxVar = 0; + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($tokens[$tag]['content'] !== '@param') { + continue; + } + + $type = ''; + $typeSpace = 0; + $var = ''; + $varSpace = 0; + $comment = ''; + $commentLines = []; + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = []; + preg_match('/([^$&.]+)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches); + + if (empty($matches) === false) { + $typeLen = strlen($matches[1]); + $type = trim($matches[1]); + $typeSpace = ($typeLen - strlen($type)); + $typeLen = strlen($type); + if ($typeLen > $maxType) { + $maxType = $typeLen; + } + } + + if (isset($matches[2]) === true) { + $var = $matches[2]; + $varLen = strlen($var); + if ($varLen > $maxVar) { + $maxVar = $varLen; + } + + if (isset($matches[4]) === true) { + $varSpace = strlen($matches[3]); + $comment = $matches[4]; + $commentLines[] = [ + 'comment' => $comment, + 'token' => ($tag + 2), + 'indent' => $varSpace, + ]; + + // Any strings until the next tag belong to this comment. + if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) { + $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; + } else { + $end = $tokens[$commentStart]['comment_closer']; + } + + for ($i = ($tag + 3); $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + $indent = 0; + if ($tokens[($i - 1)]['code'] === T_DOC_COMMENT_WHITESPACE) { + $indent = $tokens[($i - 1)]['length']; + } + + $comment .= ' '.$tokens[$i]['content']; + $commentLines[] = [ + 'comment' => $tokens[$i]['content'], + 'token' => $i, + 'indent' => $indent, + ]; + } + } + } else { + $error = 'Missing parameter comment'; + $phpcsFile->addError($error, $tag, 'MissingParamComment'); + $commentLines[] = ['comment' => '']; + }//end if + } else { + $error = 'Missing parameter name'; + $phpcsFile->addError($error, $tag, 'MissingParamName'); + }//end if + } else { + $error = 'Missing parameter type'; + $phpcsFile->addError($error, $tag, 'MissingParamType'); + }//end if + + $params[] = [ + 'tag' => $tag, + 'type' => $type, + 'var' => $var, + 'comment' => $comment, + 'commentLines' => $commentLines, + 'type_space' => $typeSpace, + 'var_space' => $varSpace, + ]; + }//end foreach + + $realParams = $phpcsFile->getMethodParameters($stackPtr); + $foundParams = []; + + // We want to use ... for all variable length arguments, so added + // this prefix to the variable name so comparisons are easier. + foreach ($realParams as $pos => $param) { + if ($param['variable_length'] === true) { + $realParams[$pos]['name'] = '...'.$realParams[$pos]['name']; + } + } + + foreach ($params as $pos => $param) { + // If the type is empty, the whole line is empty. + if ($param['type'] === '') { + continue; + } + + // Check the param type value. + $typeNames = explode('|', $param['type']); + $suggestedTypeNames = []; + + foreach ($typeNames as $typeName) { + // Strip nullable operator. + if ($typeName[0] === '?') { + $typeName = substr($typeName, 1); + } + + $suggestedName = Common::suggestType($typeName); + $suggestedTypeNames[] = $suggestedName; + + if (count($typeNames) > 1) { + continue; + } + + // Check type hint for array and custom type. + $suggestedTypeHint = ''; + if (strpos($suggestedName, 'array') !== false || substr($suggestedName, -2) === '[]') { + $suggestedTypeHint = 'array'; + } else if (strpos($suggestedName, 'callable') !== false) { + $suggestedTypeHint = 'callable'; + } else if (strpos($suggestedName, 'callback') !== false) { + $suggestedTypeHint = 'callable'; + } else if (in_array($suggestedName, Common::$allowedTypes, true) === false) { + $suggestedTypeHint = $suggestedName; + } + + if ($this->phpVersion >= 70000) { + if ($suggestedName === 'string') { + $suggestedTypeHint = 'string'; + } else if ($suggestedName === 'int' || $suggestedName === 'integer') { + $suggestedTypeHint = 'int'; + } else if ($suggestedName === 'float') { + $suggestedTypeHint = 'float'; + } else if ($suggestedName === 'bool' || $suggestedName === 'boolean') { + $suggestedTypeHint = 'bool'; + } + } + + if ($this->phpVersion >= 70200) { + if ($suggestedName === 'object') { + $suggestedTypeHint = 'object'; + } + } + + if ($this->phpVersion >= 80000) { + if ($suggestedName === 'mixed') { + $suggestedTypeHint = 'mixed'; + } + } + + if ($suggestedTypeHint !== '' && isset($realParams[$pos]) === true) { + $typeHint = $realParams[$pos]['type_hint']; + + // Remove namespace prefixes when comparing. + $compareTypeHint = substr($suggestedTypeHint, (strlen($typeHint) * -1)); + + if ($typeHint === '') { + $error = 'Type hint "%s" missing for %s'; + $data = [ + $suggestedTypeHint, + $param['var'], + ]; + + $errorCode = 'TypeHintMissing'; + if ($suggestedTypeHint === 'string' + || $suggestedTypeHint === 'int' + || $suggestedTypeHint === 'float' + || $suggestedTypeHint === 'bool' + ) { + $errorCode = 'Scalar'.$errorCode; + } + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } else if ($typeHint !== $compareTypeHint && $typeHint !== '?'.$compareTypeHint) { + $error = 'Expected type hint "%s"; found "%s" for %s'; + $data = [ + $suggestedTypeHint, + $typeHint, + $param['var'], + ]; + $phpcsFile->addError($error, $stackPtr, 'IncorrectTypeHint', $data); + }//end if + } else if ($suggestedTypeHint === '' && isset($realParams[$pos]) === true) { + $typeHint = $realParams[$pos]['type_hint']; + if ($typeHint !== '') { + $error = 'Unknown type hint "%s" found for %s'; + $data = [ + $typeHint, + $param['var'], + ]; + $phpcsFile->addError($error, $stackPtr, 'InvalidTypeHint', $data); + } + }//end if + }//end foreach + + $suggestedType = implode('|', $suggestedTypeNames); + if ($param['type'] !== $suggestedType) { + $error = 'Expected "%s" but found "%s" for parameter type'; + $data = [ + $suggestedType, + $param['type'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'IncorrectParamVarName', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $content = $suggestedType; + $content .= str_repeat(' ', $param['type_space']); + $content .= $param['var']; + $content .= str_repeat(' ', $param['var_space']); + if (isset($param['commentLines'][0]) === true) { + $content .= $param['commentLines'][0]['comment']; + } + + $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + + // Fix up the indent of additional comment lines. + foreach ($param['commentLines'] as $lineNum => $line) { + if ($lineNum === 0 + || $param['commentLines'][$lineNum]['indent'] === 0 + ) { + continue; + } + + $diff = (strlen($param['type']) - strlen($suggestedType)); + $newIndent = ($param['commentLines'][$lineNum]['indent'] - $diff); + $phpcsFile->fixer->replaceToken( + ($param['commentLines'][$lineNum]['token'] - 1), + str_repeat(' ', $newIndent) + ); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + + if ($param['var'] === '') { + continue; + } + + $foundParams[] = $param['var']; + + // Check number of spaces after the type. + $this->checkSpacingAfterParamType($phpcsFile, $param, $maxType); + + // Make sure the param name is correct. + if (isset($realParams[$pos]) === true) { + $realName = $realParams[$pos]['name']; + if ($realName !== $param['var']) { + $code = 'ParamNameNoMatch'; + $data = [ + $param['var'], + $realName, + ]; + + $error = 'Doc comment for parameter %s does not match '; + if (strtolower($param['var']) === strtolower($realName)) { + $error .= 'case of '; + $code = 'ParamNameNoCaseMatch'; + } + + $error .= 'actual variable name %s'; + + $phpcsFile->addError($error, $param['tag'], $code, $data); + } + } else if (substr($param['var'], -4) !== ',...') { + // We must have an extra parameter comment. + $error = 'Superfluous parameter comment'; + $phpcsFile->addError($error, $param['tag'], 'ExtraParamComment'); + }//end if + + if ($param['comment'] === '') { + continue; + } + + // Check number of spaces after the var name. + $this->checkSpacingAfterParamName($phpcsFile, $param, $maxVar); + + // Param comments must start with a capital letter and end with a full stop. + if (preg_match('/^(\p{Ll}|\P{L})/u', $param['comment']) === 1) { + $error = 'Parameter comment must start with a capital letter'; + $phpcsFile->addError($error, $param['tag'], 'ParamCommentNotCapital'); + } + + $lastChar = substr($param['comment'], -1); + if ($lastChar !== '.') { + $error = 'Parameter comment must end with a full stop'; + $phpcsFile->addError($error, $param['tag'], 'ParamCommentFullStop'); + } + }//end foreach + + $realNames = []; + foreach ($realParams as $realParam) { + $realNames[] = $realParam['name']; + } + + // Report missing comments. + $diff = array_diff($realNames, $foundParams); + foreach ($diff as $neededParam) { + $error = 'Doc comment for parameter "%s" missing'; + $data = [$neededParam]; + $phpcsFile->addError($error, $commentStart, 'MissingParamTag', $data); + } + + }//end processParams() + + + /** + * Check the spacing after the type of a parameter. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $param The parameter to be checked. + * @param int $maxType The maxlength of the longest parameter type. + * @param int $spacing The number of spaces to add after the type. + * + * @return void + */ + protected function checkSpacingAfterParamType(File $phpcsFile, $param, $maxType, $spacing=1) + { + // Check number of spaces after the type. + $spaces = ($maxType - strlen($param['type']) + $spacing); + if ($param['type_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter type; %s found'; + $data = [ + $spaces, + $param['type_space'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamType', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $content = $param['type']; + $content .= str_repeat(' ', $spaces); + $content .= $param['var']; + $content .= str_repeat(' ', $param['var_space']); + $content .= $param['commentLines'][0]['comment']; + $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + + // Fix up the indent of additional comment lines. + $diff = ($param['type_space'] - $spaces); + foreach ($param['commentLines'] as $lineNum => $line) { + if ($lineNum === 0 + || $param['commentLines'][$lineNum]['indent'] === 0 + ) { + continue; + } + + $newIndent = ($param['commentLines'][$lineNum]['indent'] - $diff); + if ($newIndent <= 0) { + continue; + } + + $phpcsFile->fixer->replaceToken( + ($param['commentLines'][$lineNum]['token'] - 1), + str_repeat(' ', $newIndent) + ); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + + }//end checkSpacingAfterParamType() + + + /** + * Check the spacing after the name of a parameter. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $param The parameter to be checked. + * @param int $maxVar The maxlength of the longest parameter name. + * @param int $spacing The number of spaces to add after the type. + * + * @return void + */ + protected function checkSpacingAfterParamName(File $phpcsFile, $param, $maxVar, $spacing=1) + { + // Check number of spaces after the var name. + $spaces = ($maxVar - strlen($param['var']) + $spacing); + if ($param['var_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter name; %s found'; + $data = [ + $spaces, + $param['var_space'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamName', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $content = $param['type']; + $content .= str_repeat(' ', $param['type_space']); + $content .= $param['var']; + $content .= str_repeat(' ', $spaces); + $content .= $param['commentLines'][0]['comment']; + $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + + // Fix up the indent of additional comment lines. + foreach ($param['commentLines'] as $lineNum => $line) { + if ($lineNum === 0 + || $param['commentLines'][$lineNum]['indent'] === 0 + ) { + continue; + } + + $diff = ($param['var_space'] - $spaces); + $newIndent = ($param['commentLines'][$lineNum]['indent'] - $diff); + if ($newIndent <= 0) { + continue; + } + + $phpcsFile->fixer->replaceToken( + ($param['commentLines'][$lineNum]['token'] - 1), + str_repeat(' ', $newIndent) + ); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + + }//end checkSpacingAfterParamName() + + + /** + * Determines whether the whole comment is an inheritdoc comment. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return boolean TRUE if the docblock contains only {@inheritdoc} (case-insensitive). + */ + protected function checkInheritdoc(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + $allowedTokens = [ + T_DOC_COMMENT_OPEN_TAG, + T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_STAR, + ]; + for ($i = $commentStart; $i <= $tokens[$commentStart]['comment_closer']; $i++) { + if (in_array($tokens[$i]['code'], $allowedTokens) === false) { + $trimmedContent = strtolower(trim($tokens[$i]['content'])); + + if ($trimmedContent === '{@inheritdoc}') { + return true; + } else { + return false; + } + } + } + + return false; + + }//end checkInheritdoc() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php new file mode 100644 index 00000000..a168bfe6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php @@ -0,0 +1,233 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCommentThrowTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + // Abstract or incomplete. + return; + } + + $find = Tokens::$methodPrefixes; + $find[] = T_WHITESPACE; + + $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true); + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG) { + // Function doesn't have a doc comment or is using the wrong type of comment. + return; + } + + $stackPtrEnd = $tokens[$stackPtr]['scope_closer']; + + // Find all the exception type tokens within the current scope. + $thrownExceptions = []; + $currPos = $stackPtr; + $foundThrows = false; + $unknownCount = 0; + do { + $currPos = $phpcsFile->findNext([T_THROW, T_ANON_CLASS, T_CLOSURE], ($currPos + 1), $stackPtrEnd); + if ($currPos === false) { + break; + } + + if ($tokens[$currPos]['code'] !== T_THROW) { + $currPos = $tokens[$currPos]['scope_closer']; + continue; + } + + $foundThrows = true; + + /* + If we can't find a NEW, we are probably throwing + a variable or calling a method. + + If we're throwing a variable, and it's the same variable as the + exception container from the nearest 'catch' block, we take that exception + as it is likely to be a re-throw. + + If we can't find a matching catch block, or the variable name + is different, it's probably a different variable, so we ignore it, + but they still need to provide at least one @throws tag, even through we + don't know the exception class. + */ + + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($currPos + 1), null, true); + if ($tokens[$nextToken]['code'] === T_NEW + || $tokens[$nextToken]['code'] === T_NS_SEPARATOR + || $tokens[$nextToken]['code'] === T_STRING + ) { + if ($tokens[$nextToken]['code'] === T_NEW) { + $currException = $phpcsFile->findNext( + [ + T_NS_SEPARATOR, + T_STRING, + ], + $currPos, + $stackPtrEnd, + false, + null, + true + ); + } else { + $currException = $nextToken; + } + + if ($currException !== false) { + $endException = $phpcsFile->findNext( + [ + T_NS_SEPARATOR, + T_STRING, + ], + ($currException + 1), + $stackPtrEnd, + true, + null, + true + ); + + if ($endException === false) { + $thrownExceptions[] = $tokens[$currException]['content']; + } else { + $thrownExceptions[] = $phpcsFile->getTokensAsString($currException, ($endException - $currException)); + } + }//end if + } else if ($tokens[$nextToken]['code'] === T_VARIABLE) { + // Find the nearest catch block in this scope and, if the caught var + // matches our re-thrown var, use the exception types being caught as + // exception types that are being thrown as well. + $catch = $phpcsFile->findPrevious( + T_CATCH, + $currPos, + $tokens[$stackPtr]['scope_opener'], + false, + null, + false + ); + + if ($catch !== false) { + $thrownVar = $phpcsFile->findPrevious( + T_VARIABLE, + ($tokens[$catch]['parenthesis_closer'] - 1), + $tokens[$catch]['parenthesis_opener'] + ); + + if ($tokens[$thrownVar]['content'] === $tokens[$nextToken]['content']) { + $exceptions = explode('|', $phpcsFile->getTokensAsString(($tokens[$catch]['parenthesis_opener'] + 1), ($thrownVar - $tokens[$catch]['parenthesis_opener'] - 1))); + foreach ($exceptions as $exception) { + $thrownExceptions[] = trim($exception); + } + } + } + } else { + ++$unknownCount; + }//end if + } while ($currPos < $stackPtrEnd && $currPos !== false); + + if ($foundThrows === false) { + return; + } + + // Only need one @throws tag for each type of exception thrown. + $thrownExceptions = array_unique($thrownExceptions); + + $throwTags = []; + $commentStart = $tokens[$commentEnd]['comment_opener']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] !== '@throws') { + continue; + } + + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $exception = $tokens[($tag + 2)]['content']; + $space = strpos($exception, ' '); + if ($space !== false) { + $exception = substr($exception, 0, $space); + } + + $throwTags[$exception] = true; + } + } + + if (empty($throwTags) === true) { + $error = 'Missing @throws tag in function comment'; + $phpcsFile->addError($error, $commentEnd, 'Missing'); + return; + } else if (empty($thrownExceptions) === true) { + // If token count is zero, it means that only variables are being + // thrown, so we need at least one @throws tag (checked above). + // Nothing more to do. + return; + } + + // Make sure @throws tag count matches thrown count. + $thrownCount = (count($thrownExceptions) + $unknownCount); + $tagCount = count($throwTags); + if ($thrownCount !== $tagCount) { + $error = 'Expected %s @throws tag(s) in function comment; %s found'; + $data = [ + $thrownCount, + $tagCount, + ]; + $phpcsFile->addError($error, $commentEnd, 'WrongNumber', $data); + return; + } + + foreach ($thrownExceptions as $throw) { + if (isset($throwTags[$throw]) === true) { + continue; + } + + foreach ($throwTags as $tag => $ignore) { + if (strrpos($tag, $throw) === (strlen($tag) - strlen($throw))) { + continue 2; + } + } + + $error = 'Missing @throws tag for "%s" exception'; + $data = [$throw]; + $phpcsFile->addError($error, $commentEnd, 'Missing', $data); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/InlineCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/InlineCommentSniff.php new file mode 100644 index 00000000..8ce95041 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/InlineCommentSniff.php @@ -0,0 +1,348 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class InlineCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_COMMENT, + T_DOC_COMMENT_OPEN_TAG, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If this is a function/class/interface doc block comment, skip it. + // We are only interested in inline doc block comments, which are + // not allowed. + if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT_OPEN_TAG) { + $nextToken = $stackPtr; + do { + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] === T_ATTRIBUTE) { + $nextToken = $tokens[$nextToken]['attribute_closer']; + continue; + } + + break; + } while (true); + + $ignore = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_FUNCTION, + T_CLOSURE, + T_PUBLIC, + T_PRIVATE, + T_PROTECTED, + T_FINAL, + T_STATIC, + T_ABSTRACT, + T_CONST, + T_PROPERTY, + T_INCLUDE, + T_INCLUDE_ONCE, + T_REQUIRE, + T_REQUIRE_ONCE, + ]; + + if (in_array($tokens[$nextToken]['code'], $ignore, true) === true) { + return; + } + + if ($phpcsFile->tokenizerType === 'JS') { + // We allow block comments if a function or object + // is being assigned to a variable. + $ignore = Tokens::$emptyTokens; + $ignore[] = T_EQUAL; + $ignore[] = T_STRING; + $ignore[] = T_OBJECT_OPERATOR; + $nextToken = $phpcsFile->findNext($ignore, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] === T_FUNCTION + || $tokens[$nextToken]['code'] === T_CLOSURE + || $tokens[$nextToken]['code'] === T_OBJECT + || $tokens[$nextToken]['code'] === T_PROTOTYPE + ) { + return; + } + } + + $prevToken = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($stackPtr - 1), + null, + true + ); + + if ($tokens[$prevToken]['code'] === T_OPEN_TAG) { + return; + } + + if ($tokens[$stackPtr]['content'] === '/**') { + $error = 'Inline doc block comments are not allowed; use "/* Comment */" or "// Comment" instead'; + $phpcsFile->addError($error, $stackPtr, 'DocBlock'); + } + }//end if + + if ($tokens[$stackPtr]['content'][0] === '#') { + $error = 'Perl-style comments are not allowed; use "// Comment" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'WrongStyle'); + if ($fix === true) { + $comment = ltrim($tokens[$stackPtr]['content'], "# \t"); + $phpcsFile->fixer->replaceToken($stackPtr, "// $comment"); + } + } + + // We don't want end of block comments. Check if the last token before the + // comment is a closing curly brace. + $previousContent = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$previousContent]['line'] === $tokens[$stackPtr]['line']) { + if ($tokens[$previousContent]['code'] === T_CLOSE_CURLY_BRACKET) { + return; + } + + // Special case for JS files. + if ($tokens[$previousContent]['code'] === T_COMMA + || $tokens[$previousContent]['code'] === T_SEMICOLON + ) { + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($previousContent - 1), null, true); + if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) { + return; + } + } + } + + // Only want inline comments. + if (substr($tokens[$stackPtr]['content'], 0, 2) !== '//') { + return; + } + + $commentTokens = [$stackPtr]; + + $nextComment = $stackPtr; + $lastComment = $stackPtr; + while (($nextComment = $phpcsFile->findNext(T_COMMENT, ($nextComment + 1), null, false)) !== false) { + if ($tokens[$nextComment]['line'] !== ($tokens[$lastComment]['line'] + 1)) { + break; + } + + // Only want inline comments. + if (substr($tokens[$nextComment]['content'], 0, 2) !== '//') { + break; + } + + // There is a comment on the very next line. If there is + // no code between the comments, they are part of the same + // comment block. + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($nextComment - 1), $lastComment, true); + if ($prevNonWhitespace !== $lastComment) { + break; + } + + $commentTokens[] = $nextComment; + $lastComment = $nextComment; + }//end while + + $commentText = ''; + foreach ($commentTokens as $lastCommentToken) { + $comment = rtrim($tokens[$lastCommentToken]['content']); + + if (trim(substr($comment, 2)) === '') { + continue; + } + + $spaceCount = 0; + $tabFound = false; + + $commentLength = strlen($comment); + for ($i = 2; $i < $commentLength; $i++) { + if ($comment[$i] === "\t") { + $tabFound = true; + break; + } + + if ($comment[$i] !== ' ') { + break; + } + + $spaceCount++; + } + + $fix = false; + if ($tabFound === true) { + $error = 'Tab found before comment text; expected "// %s" but found "%s"'; + $data = [ + ltrim(substr($comment, 2)), + $comment, + ]; + $fix = $phpcsFile->addFixableError($error, $lastCommentToken, 'TabBefore', $data); + } else if ($spaceCount === 0) { + $error = 'No space found before comment text; expected "// %s" but found "%s"'; + $data = [ + substr($comment, 2), + $comment, + ]; + $fix = $phpcsFile->addFixableError($error, $lastCommentToken, 'NoSpaceBefore', $data); + } else if ($spaceCount > 1) { + $error = 'Expected 1 space before comment text but found %s; use block comment if you need indentation'; + $data = [ + $spaceCount, + substr($comment, (2 + $spaceCount)), + $comment, + ]; + $fix = $phpcsFile->addFixableError($error, $lastCommentToken, 'SpacingBefore', $data); + }//end if + + if ($fix === true) { + $newComment = '// '.ltrim($tokens[$lastCommentToken]['content'], "/\t "); + $phpcsFile->fixer->replaceToken($lastCommentToken, $newComment); + } + + $commentText .= trim(substr($tokens[$lastCommentToken]['content'], 2)); + }//end foreach + + if ($commentText === '') { + $error = 'Blank comments are not allowed'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Empty'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, ''); + } + + return ($lastCommentToken + 1); + } + + if (preg_match('/^\p{Ll}/u', $commentText) === 1) { + $error = 'Inline comments must start with a capital letter'; + $phpcsFile->addError($error, $stackPtr, 'NotCapital'); + } + + // Only check the end of comment character if the start of the comment + // is a letter, indicating that the comment is just standard text. + if (preg_match('/^\p{L}/u', $commentText) === 1) { + $commentCloser = $commentText[(strlen($commentText) - 1)]; + $acceptedClosers = [ + 'full-stops' => '.', + 'exclamation marks' => '!', + 'or question marks' => '?', + ]; + + if (in_array($commentCloser, $acceptedClosers, true) === false) { + $error = 'Inline comments must end in %s'; + $ender = ''; + foreach ($acceptedClosers as $closerName => $symbol) { + $ender .= ' '.$closerName.','; + } + + $ender = trim($ender, ' ,'); + $data = [$ender]; + $phpcsFile->addError($error, $lastCommentToken, 'InvalidEndChar', $data); + } + } + + // Finally, the line below the last comment cannot be empty if this inline + // comment is on a line by itself. + if ($tokens[$previousContent]['line'] < $tokens[$stackPtr]['line']) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($lastCommentToken + 1), null, true); + if ($next === false) { + // Ignore if the comment is the last non-whitespace token in a file. + return ($lastCommentToken + 1); + } + + if ($tokens[$next]['code'] === T_DOC_COMMENT_OPEN_TAG) { + // If this inline comment is followed by a docblock, + // ignore spacing as docblock/function etc spacing rules + // are likely to conflict with our rules. + return ($lastCommentToken + 1); + } + + $errorCode = 'SpacingAfter'; + + if (isset($tokens[$stackPtr]['conditions']) === true) { + $conditions = $tokens[$stackPtr]['conditions']; + $type = end($conditions); + $conditionPtr = key($conditions); + + if (($type === T_FUNCTION || $type === T_CLOSURE) + && $tokens[$conditionPtr]['scope_closer'] === $next + ) { + $errorCode = 'SpacingAfterAtFunctionEnd'; + } + } + + for ($i = ($lastCommentToken + 1); $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['line'] === ($tokens[$lastCommentToken]['line'] + 1)) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + return ($lastCommentToken + 1); + } + } else if ($tokens[$i]['line'] > ($tokens[$lastCommentToken]['line'] + 1)) { + break; + } + } + + $error = 'There must be no blank line following an inline comment'; + $fix = $phpcsFile->addFixableError($error, $lastCommentToken, $errorCode); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($lastCommentToken + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + return ($lastCommentToken + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/LongConditionClosingCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/LongConditionClosingCommentSniff.php new file mode 100644 index 00000000..103d90ff --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/LongConditionClosingCommentSniff.php @@ -0,0 +1,218 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LongConditionClosingCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The openers that we are interested in. + * + * @var integer[] + */ + private static $openers = [ + T_SWITCH, + T_IF, + T_FOR, + T_FOREACH, + T_WHILE, + T_TRY, + T_CASE, + T_MATCH, + ]; + + /** + * The length that a code block must be before + * requiring a closing comment. + * + * @var integer + */ + public $lineLimit = 20; + + /** + * The format the end comment should be in. + * + * The placeholder %s will be replaced with the type of condition opener. + * + * @var string + */ + public $commentFormat = '//end %s'; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CLOSE_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_condition']) === false) { + // No scope condition. It is a function closer. + return; + } + + $startCondition = $tokens[$tokens[$stackPtr]['scope_condition']]; + $startBrace = $tokens[$tokens[$stackPtr]['scope_opener']]; + $endBrace = $tokens[$stackPtr]; + + // We are only interested in some code blocks. + if (in_array($startCondition['code'], self::$openers, true) === false) { + return; + } + + if ($startCondition['code'] === T_IF) { + // If this is actually an ELSE IF, skip it as the brace + // will be checked by the original IF. + $else = $phpcsFile->findPrevious(T_WHITESPACE, ($tokens[$stackPtr]['scope_condition'] - 1), null, true); + if ($tokens[$else]['code'] === T_ELSE) { + return; + } + + // IF statements that have an ELSE block need to use + // "end if" rather than "end else" or "end elseif". + do { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$nextToken]['code'] === T_ELSE || $tokens[$nextToken]['code'] === T_ELSEIF) { + // Check for ELSE IF (2 tokens) as opposed to ELSEIF (1 token). + if ($tokens[$nextToken]['code'] === T_ELSE + && isset($tokens[$nextToken]['scope_closer']) === false + ) { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] !== T_IF + || isset($tokens[$nextToken]['scope_closer']) === false + ) { + // Not an ELSE IF or is an inline ELSE IF. + break; + } + } + + if (isset($tokens[$nextToken]['scope_closer']) === false) { + // There isn't going to be anywhere to print the "end if" comment + // because there is no closer. + return; + } + + // The end brace becomes the ELSE's end brace. + $stackPtr = $tokens[$nextToken]['scope_closer']; + $endBrace = $tokens[$stackPtr]; + } else { + break; + }//end if + } while (isset($tokens[$nextToken]['scope_closer']) === true); + }//end if + + if ($startCondition['code'] === T_TRY) { + // TRY statements need to check until the end of all CATCH statements. + do { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$nextToken]['code'] === T_CATCH + || $tokens[$nextToken]['code'] === T_FINALLY + ) { + // The end brace becomes the CATCH end brace. + $stackPtr = $tokens[$nextToken]['scope_closer']; + $endBrace = $tokens[$stackPtr]; + } else { + break; + } + } while (isset($tokens[$nextToken]['scope_closer']) === true); + } + + if ($startCondition['code'] === T_MATCH) { + // Move the stackPtr to after the semi-colon/comma if there is one. + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($nextToken !== false + && ($tokens[$nextToken]['code'] === T_SEMICOLON + || $tokens[$nextToken]['code'] === T_COMMA) + ) { + $stackPtr = $nextToken; + } + } + + $lineDifference = ($endBrace['line'] - $startBrace['line']); + + $expected = sprintf($this->commentFormat, $startCondition['content']); + $comment = $phpcsFile->findNext([T_COMMENT], $stackPtr, null, false); + + if (($comment === false) || ($tokens[$comment]['line'] !== $endBrace['line'])) { + if ($lineDifference >= $this->lineLimit) { + $error = 'End comment for long condition not found; expected "%s"'; + $data = [$expected]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Missing', $data); + + if ($fix === true) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next !== false && $tokens[$next]['line'] === $tokens[$stackPtr]['line']) { + $expected .= $phpcsFile->eolChar; + } + + $phpcsFile->fixer->addContent($stackPtr, $expected); + } + } + + return; + } + + if (($comment - $stackPtr) !== 1) { + $error = 'Space found before closing comment; expected "%s"'; + $data = [$expected]; + $phpcsFile->addError($error, $stackPtr, 'SpacingBefore', $data); + } + + if (trim($tokens[$comment]['content']) !== $expected) { + $found = trim($tokens[$comment]['content']); + $error = 'Incorrect closing comment; expected "%s" but found "%s"'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Invalid', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($comment, $expected.$phpcsFile->eolChar); + } + + return; + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/PostStatementCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/PostStatementCommentSniff.php new file mode 100644 index 00000000..ce19d5c1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/PostStatementCommentSniff.php @@ -0,0 +1,121 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class PostStatementCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * Exceptions to the rule. + * + * If post statement comments are found within the condition + * parenthesis of these structures, leave them alone. + * + * @var array + */ + private $controlStructureExceptions = [ + T_IF => true, + T_ELSEIF => true, + T_SWITCH => true, + T_WHILE => true, + T_FOR => true, + T_FOREACH => true, + T_MATCH => true, + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_COMMENT]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (substr($tokens[$stackPtr]['content'], 0, 2) !== '//') { + return; + } + + $commentLine = $tokens[$stackPtr]['line']; + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + + if ($lastContent === false + || $tokens[$lastContent]['line'] !== $commentLine + || $tokens[$stackPtr]['column'] === 1 + ) { + return; + } + + if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) { + return; + } + + // Special case for JS files and PHP closures. + if ($tokens[$lastContent]['code'] === T_COMMA + || $tokens[$lastContent]['code'] === T_SEMICOLON + ) { + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($lastContent - 1), null, true); + if ($lastContent === false || $tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) { + return; + } + } + + // Special case for (trailing) comments within multi-line control structures. + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nestedParens = $tokens[$stackPtr]['nested_parenthesis']; + foreach ($nestedParens as $open => $close) { + if (isset($tokens[$open]['parenthesis_owner']) === true + && isset($this->controlStructureExceptions[$tokens[$tokens[$open]['parenthesis_owner']]['code']]) === true + ) { + return; + } + } + } + + $error = 'Comments may not appear after statements'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($stackPtr); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php new file mode 100644 index 00000000..32e89789 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php @@ -0,0 +1,193 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Common; + +class VariableCommentSniff extends AbstractVariableSniff +{ + + + /** + * Called to process class member vars. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $ignore = [ + T_PUBLIC => T_PUBLIC, + T_PRIVATE => T_PRIVATE, + T_PROTECTED => T_PROTECTED, + T_VAR => T_VAR, + T_STATIC => T_STATIC, + T_READONLY => T_READONLY, + T_WHITESPACE => T_WHITESPACE, + T_STRING => T_STRING, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_NULLABLE => T_NULLABLE, + ]; + + for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { + if (isset($ignore[$tokens[$commentEnd]['code']]) === true) { + continue; + } + + if ($tokens[$commentEnd]['code'] === T_ATTRIBUTE_END + && isset($tokens[$commentEnd]['attribute_opener']) === true + ) { + $commentEnd = $tokens[$commentEnd]['attribute_opener']; + continue; + } + + break; + } + + if ($commentEnd === false + || ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG + && $tokens[$commentEnd]['code'] !== T_COMMENT) + ) { + $phpcsFile->addError('Missing member variable doc comment', $stackPtr, 'Missing'); + return; + } + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a member variable comment', $stackPtr, 'WrongStyle'); + return; + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + + $foundVar = null; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@var') { + if ($foundVar !== null) { + $error = 'Only one @var tag is allowed in a member variable comment'; + $phpcsFile->addError($error, $tag, 'DuplicateVar'); + } else { + $foundVar = $tag; + } + } else if ($tokens[$tag]['content'] === '@see') { + // Make sure the tag isn't empty. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for @see tag in member variable comment'; + $phpcsFile->addError($error, $tag, 'EmptySees'); + } + } else { + $error = '%s tag is not allowed in member variable comment'; + $data = [$tokens[$tag]['content']]; + $phpcsFile->addWarning($error, $tag, 'TagNotAllowed', $data); + }//end if + }//end foreach + + // The @var tag is the only one we require. + if ($foundVar === null) { + $error = 'Missing @var tag in member variable comment'; + $phpcsFile->addError($error, $commentEnd, 'MissingVar'); + return; + } + + $firstTag = $tokens[$commentStart]['comment_tags'][0]; + if ($foundVar !== null && $tokens[$firstTag]['content'] !== '@var') { + $error = 'The @var tag must be the first tag in a member variable comment'; + $phpcsFile->addError($error, $foundVar, 'VarOrder'); + } + + // Make sure the tag isn't empty and has the correct padding. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $foundVar, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$foundVar]['line']) { + $error = 'Content missing for @var tag in member variable comment'; + $phpcsFile->addError($error, $foundVar, 'EmptyVar'); + return; + } + + // Support both a var type and a description. + preg_match('`^((?:\|?(?:array\([^\)]*\)|[\\\\a-z0-9\[\]]+))*)( .*)?`i', $tokens[($foundVar + 2)]['content'], $varParts); + if (isset($varParts[1]) === false) { + return; + } + + $varType = $varParts[1]; + + // Check var type (can be multiple, separated by '|'). + $typeNames = explode('|', $varType); + $suggestedNames = []; + foreach ($typeNames as $i => $typeName) { + $suggestedName = Common::suggestType($typeName); + if (in_array($suggestedName, $suggestedNames, true) === false) { + $suggestedNames[] = $suggestedName; + } + } + + $suggestedType = implode('|', $suggestedNames); + if ($varType !== $suggestedType) { + $error = 'Expected "%s" but found "%s" for @var tag in member variable comment'; + $data = [ + $suggestedType, + $varType, + ]; + $fix = $phpcsFile->addFixableError($error, $foundVar, 'IncorrectVarType', $data); + if ($fix === true) { + $replacement = $suggestedType; + if (empty($varParts[2]) === false) { + $replacement .= $varParts[2]; + } + + $phpcsFile->fixer->replaceToken(($foundVar + 2), $replacement); + unset($replacement); + } + } + + }//end processMemberVar() + + + /** + * Called to process a normal variable. + * + * Not required for this sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this token was found. + * @param int $stackPtr The position where the double quoted + * string was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + + }//end processVariable() + + + /** + * Called to process variables found in double quoted strings. + * + * Not required for this sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this token was found. + * @param int $stackPtr The position where the double quoted + * string was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + + }//end processVariableInString() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php new file mode 100644 index 00000000..8a56b23f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php @@ -0,0 +1,325 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ControlSignatureSniff implements Sniff +{ + + /** + * How many spaces should precede the colon if using alternative syntax. + * + * @var integer + */ + public $requiredSpacesBeforeColon = 1; + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return int[] + */ + public function register() + { + return [ + T_TRY, + T_CATCH, + T_FINALLY, + T_DO, + T_WHILE, + T_FOR, + T_IF, + T_FOREACH, + T_ELSE, + T_ELSEIF, + T_SWITCH, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + $isAlternative = false; + if (isset($tokens[$stackPtr]['scope_opener']) === true + && $tokens[$tokens[$stackPtr]['scope_opener']]['code'] === T_COLON + ) { + $isAlternative = true; + } + + // Single space after the keyword. + $expected = 1; + if (isset($tokens[$stackPtr]['parenthesis_closer']) === false && $isAlternative === true) { + // Catching cases like: + // if (condition) : ... else: ... endif + // where there is no condition. + $expected = (int) $this->requiredSpacesBeforeColon; + } + + $found = 1; + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $found = 0; + } else if ($tokens[($stackPtr + 1)]['content'] !== ' ') { + if (strpos($tokens[($stackPtr + 1)]['content'], $phpcsFile->eolChar) !== false) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr + 1)]['length']; + } + } + + if ($found !== $expected) { + $error = 'Expected %s space(s) after %s keyword; %s found'; + $data = [ + $expected, + strtoupper($tokens[$stackPtr]['content']), + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterKeyword', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent($stackPtr, str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), str_repeat(' ', $expected)); + } + } + } + + // Single space after closing parenthesis. + if (isset($tokens[$stackPtr]['parenthesis_closer']) === true + && isset($tokens[$stackPtr]['scope_opener']) === true + ) { + $expected = 1; + if ($isAlternative === true) { + $expected = (int) $this->requiredSpacesBeforeColon; + } + + $closer = $tokens[$stackPtr]['parenthesis_closer']; + $opener = $tokens[$stackPtr]['scope_opener']; + $content = $phpcsFile->getTokensAsString(($closer + 1), ($opener - $closer - 1)); + + if (trim($content) === '') { + if (strpos($content, $phpcsFile->eolChar) !== false) { + $found = 'newline'; + } else { + $found = strlen($content); + } + } else { + $found = '"'.str_replace($phpcsFile->eolChar, '\n', $content).'"'; + } + + if ($found !== $expected) { + $error = 'Expected %s space(s) after closing parenthesis; found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceAfterCloseParenthesis', $data); + if ($fix === true) { + $padding = str_repeat(' ', $expected); + if ($closer === ($opener - 1)) { + $phpcsFile->fixer->addContent($closer, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + if (trim($content) === '') { + $phpcsFile->fixer->addContent($closer, $padding); + if ($found !== 0) { + for ($i = ($closer + 1); $i < $opener; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } else { + $phpcsFile->fixer->addContent($closer, $padding.$tokens[$opener]['content']); + $phpcsFile->fixer->replaceToken($opener, ''); + + if ($tokens[$opener]['line'] !== $tokens[$closer]['line']) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$opener]['line']) { + for ($i = ($opener + 1); $i < $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + }//end if + }//end if + + // Single newline after opening brace. + if (isset($tokens[$stackPtr]['scope_opener']) === true) { + $opener = $tokens[$stackPtr]['scope_opener']; + for ($next = ($opener + 1); $next < $phpcsFile->numTokens; $next++) { + $code = $tokens[$next]['code']; + + if ($code === T_WHITESPACE + || ($code === T_INLINE_HTML + && trim($tokens[$next]['content']) === '') + ) { + continue; + } + + // Skip all empty tokens on the same line as the opener. + if ($tokens[$next]['line'] === $tokens[$opener]['line'] + && (isset(Tokens::$emptyTokens[$code]) === true + || $code === T_CLOSE_TAG) + ) { + continue; + } + + // We found the first bit of a code, or a comment on the + // following line. + break; + }//end for + + if ($tokens[$next]['line'] === $tokens[$opener]['line']) { + $error = 'Newline required after opening brace'; + $fix = $phpcsFile->addFixableError($error, $opener, 'NewlineAfterOpenBrace'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($opener + 1); $i < $next; $i++) { + if (trim($tokens[$i]['content']) !== '') { + break; + } + + // Remove whitespace. + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContent($opener, $phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + }//end if + } else if ($tokens[$stackPtr]['code'] === T_WHILE) { + // Zero spaces after parenthesis closer, but only if followed by a semicolon. + $closer = $tokens[$stackPtr]['parenthesis_closer']; + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($closer + 1), null, true); + if ($nextNonEmpty !== false && $tokens[$nextNonEmpty]['code'] === T_SEMICOLON) { + $found = 0; + if ($tokens[($closer + 1)]['code'] === T_WHITESPACE) { + if (strpos($tokens[($closer + 1)]['content'], $phpcsFile->eolChar) !== false) { + $found = 'newline'; + } else { + $found = $tokens[($closer + 1)]['length']; + } + } + + if ($found !== 0) { + $error = 'Expected 0 spaces before semicolon; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceBeforeSemicolon', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closer + 1), ''); + } + } + } + }//end if + + // Only want to check multi-keyword structures from here on. + if ($tokens[$stackPtr]['code'] === T_WHILE) { + if (isset($tokens[$stackPtr]['scope_closer']) !== false) { + return; + } + + $closer = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($closer === false + || $tokens[$closer]['code'] !== T_CLOSE_CURLY_BRACKET + || $tokens[$tokens[$closer]['scope_condition']]['code'] !== T_DO + ) { + return; + } + } else if ($tokens[$stackPtr]['code'] === T_ELSE + || $tokens[$stackPtr]['code'] === T_ELSEIF + || $tokens[$stackPtr]['code'] === T_CATCH + || $tokens[$stackPtr]['code'] === T_FINALLY + ) { + if (isset($tokens[$stackPtr]['scope_opener']) === true + && $tokens[$tokens[$stackPtr]['scope_opener']]['code'] === T_COLON + ) { + // Special case for alternate syntax, where this token is actually + // the closer for the previous block, so there is no spacing to check. + return; + } + + $closer = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($closer === false || $tokens[$closer]['code'] !== T_CLOSE_CURLY_BRACKET) { + return; + } + } else { + return; + }//end if + + // Single space after closing brace. + $found = 1; + if ($tokens[($closer + 1)]['code'] !== T_WHITESPACE) { + $found = 0; + } else if ($tokens[$closer]['line'] !== $tokens[$stackPtr]['line']) { + $found = 'newline'; + } else if ($tokens[($closer + 1)]['content'] !== ' ') { + $found = $tokens[($closer + 1)]['length']; + } + + if ($found !== 1) { + $error = 'Expected 1 space after closing brace; %s found'; + $data = [$found]; + + if ($phpcsFile->findNext(Tokens::$commentTokens, ($closer + 1), $stackPtr) !== false) { + // Comment found between closing brace and keyword, don't auto-fix. + $phpcsFile->addError($error, $closer, 'SpaceAfterCloseBrace', $data); + return; + } + + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceAfterCloseBrace', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent($closer, ' '); + } else { + $phpcsFile->fixer->replaceToken(($closer + 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ElseIfDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ElseIfDeclarationSniff.php new file mode 100644 index 00000000..8abb8fb3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ElseIfDeclarationSniff.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ElseIfDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_ELSEIF]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $error = 'Usage of ELSEIF not allowed; use ELSE IF instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'else if'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForEachLoopDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForEachLoopDeclarationSniff.php new file mode 100644 index 00000000..c5f22e23 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForEachLoopDeclarationSniff.php @@ -0,0 +1,236 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ForEachLoopDeclarationSniff implements Sniff +{ + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FOREACH]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + $tokens = $phpcsFile->getTokens(); + + $openingBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr); + if ($openingBracket === false) { + $error = 'Possible parse error: FOREACH has no opening parenthesis'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingOpenParenthesis'); + return; + } + + if (isset($tokens[$openingBracket]['parenthesis_closer']) === false) { + $error = 'Possible parse error: FOREACH has no closing parenthesis'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingCloseParenthesis'); + return; + } + + $closingBracket = $tokens[$openingBracket]['parenthesis_closer']; + + if ($this->requiredSpacesAfterOpen === 0 && $tokens[($openingBracket + 1)]['code'] === T_WHITESPACE) { + $error = 'Space found after opening bracket of FOREACH loop'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterOpen'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openingBracket + 1), ''); + } + } else if ($this->requiredSpacesAfterOpen > 0) { + $spaceAfterOpen = 0; + if ($tokens[($openingBracket + 1)]['code'] === T_WHITESPACE) { + $spaceAfterOpen = $tokens[($openingBracket + 1)]['length']; + } + + if ($spaceAfterOpen !== $this->requiredSpacesAfterOpen) { + $error = 'Expected %s spaces after opening bracket; %s found'; + $data = [ + $this->requiredSpacesAfterOpen, + $spaceAfterOpen, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterOpen', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesAfterOpen); + if ($spaceAfterOpen === 0) { + $phpcsFile->fixer->addContent($openingBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($openingBracket + 1), $padding); + } + } + } + }//end if + + if ($this->requiredSpacesBeforeClose === 0 && $tokens[($closingBracket - 1)]['code'] === T_WHITESPACE) { + $error = 'Space found before closing bracket of FOREACH loop'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closingBracket - 1), ''); + } + } else if ($this->requiredSpacesBeforeClose > 0) { + $spaceBeforeClose = 0; + if ($tokens[($closingBracket - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = $tokens[($closingBracket - 1)]['length']; + } + + if ($spaceBeforeClose !== $this->requiredSpacesBeforeClose) { + $error = 'Expected %s spaces before closing bracket; %s found'; + $data = [ + $this->requiredSpacesBeforeClose, + $spaceBeforeClose, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeClose', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesBeforeClose); + if ($spaceBeforeClose === 0) { + $phpcsFile->fixer->addContentBefore($closingBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($closingBracket - 1), $padding); + } + } + } + }//end if + + $asToken = $phpcsFile->findNext(T_AS, $openingBracket); + if ($asToken === false) { + $error = 'Possible parse error: FOREACH has no AS statement'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingAs'); + return; + } + + $content = $tokens[$asToken]['content']; + if ($content !== strtolower($content)) { + $expected = strtolower($content); + $error = 'AS keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + $expected, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $asToken, 'AsNotLower', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($asToken, $expected); + } + } + + $doubleArrow = $phpcsFile->findNext(T_DOUBLE_ARROW, $asToken, $closingBracket); + + if ($doubleArrow !== false) { + if ($tokens[($doubleArrow - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space before "=>"; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBeforeArrow'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($doubleArrow, ' '); + } + } else { + if ($tokens[($doubleArrow - 1)]['length'] !== 1) { + $spaces = $tokens[($doubleArrow - 1)]['length']; + $error = 'Expected 1 space before "=>"; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($doubleArrow - 1), ' '); + } + } + } + + if ($tokens[($doubleArrow + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after "=>"; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfterArrow'); + if ($fix === true) { + $phpcsFile->fixer->addContent($doubleArrow, ' '); + } + } else { + if ($tokens[($doubleArrow + 1)]['length'] !== 1) { + $spaces = $tokens[($doubleArrow + 1)]['length']; + $error = 'Expected 1 space after "=>"; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($doubleArrow + 1), ' '); + } + } + } + }//end if + + if ($tokens[($asToken - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space before "as"; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBeforeAs'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($asToken, ' '); + } + } else { + if ($tokens[($asToken - 1)]['length'] !== 1) { + $spaces = $tokens[($asToken - 1)]['length']; + $error = 'Expected 1 space before "as"; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeAs', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($asToken - 1), ' '); + } + } + } + + if ($tokens[($asToken + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after "as"; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfterAs'); + if ($fix === true) { + $phpcsFile->fixer->addContent($asToken, ' '); + } + } else { + if ($tokens[($asToken + 1)]['length'] !== 1) { + $spaces = $tokens[($asToken + 1)]['length']; + $error = 'Expected 1 space after "as"; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterAs', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($asToken + 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php new file mode 100644 index 00000000..6803f9ab --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php @@ -0,0 +1,316 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ForLoopDeclarationSniff implements Sniff +{ + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FOR]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + $tokens = $phpcsFile->getTokens(); + + $openingBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr); + if ($openingBracket === false) { + $error = 'Possible parse error: no opening parenthesis for FOR keyword'; + $phpcsFile->addWarning($error, $stackPtr, 'NoOpenBracket'); + return; + } + + $closingBracket = $tokens[$openingBracket]['parenthesis_closer']; + + if ($this->requiredSpacesAfterOpen === 0 + && $tokens[($openingBracket + 1)]['code'] === T_WHITESPACE + ) { + $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, ($openingBracket + 1), $closingBracket, true); + if ($this->ignoreNewlines === false + || $tokens[$nextNonWhiteSpace]['line'] === $tokens[$openingBracket]['line'] + ) { + $error = 'Whitespace found after opening bracket of FOR loop'; + $fix = $phpcsFile->addFixableError($error, $openingBracket, 'SpacingAfterOpen'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($openingBracket + 1); $i < $closingBracket; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } else if ($this->requiredSpacesAfterOpen > 0) { + $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, ($openingBracket + 1), $closingBracket, true); + $spaceAfterOpen = 0; + if ($tokens[$openingBracket]['line'] !== $tokens[$nextNonWhiteSpace]['line']) { + $spaceAfterOpen = 'newline'; + } else if ($tokens[($openingBracket + 1)]['code'] === T_WHITESPACE) { + $spaceAfterOpen = $tokens[($openingBracket + 1)]['length']; + } + + if ($spaceAfterOpen !== $this->requiredSpacesAfterOpen + && ($this->ignoreNewlines === false + || $spaceAfterOpen !== 'newline') + ) { + $error = 'Expected %s spaces after opening bracket; %s found'; + $data = [ + $this->requiredSpacesAfterOpen, + $spaceAfterOpen, + ]; + $fix = $phpcsFile->addFixableError($error, $openingBracket, 'SpacingAfterOpen', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesAfterOpen); + if ($spaceAfterOpen === 0) { + $phpcsFile->fixer->addContent($openingBracket, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($openingBracket + 1), $padding); + for ($i = ($openingBracket + 2); $i < $nextNonWhiteSpace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + }//end if + + $prevNonWhiteSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($closingBracket - 1), $openingBracket, true); + $beforeClosefixable = true; + if ($tokens[$prevNonWhiteSpace]['line'] !== $tokens[$closingBracket]['line'] + && isset(Tokens::$emptyTokens[$tokens[$prevNonWhiteSpace]['code']]) === true + ) { + $beforeClosefixable = false; + } + + if ($this->requiredSpacesBeforeClose === 0 + && $tokens[($closingBracket - 1)]['code'] === T_WHITESPACE + && ($this->ignoreNewlines === false + || $tokens[$prevNonWhiteSpace]['line'] === $tokens[$closingBracket]['line']) + ) { + $error = 'Whitespace found before closing bracket of FOR loop'; + + if ($beforeClosefixable === false) { + $phpcsFile->addError($error, $closingBracket, 'SpacingBeforeClose'); + } else { + $fix = $phpcsFile->addFixableError($error, $closingBracket, 'SpacingBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closingBracket - 1); $i > $openingBracket; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } else if ($this->requiredSpacesBeforeClose > 0) { + $spaceBeforeClose = 0; + if ($tokens[$closingBracket]['line'] !== $tokens[$prevNonWhiteSpace]['line']) { + $spaceBeforeClose = 'newline'; + } else if ($tokens[($closingBracket - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = $tokens[($closingBracket - 1)]['length']; + } + + if ($this->requiredSpacesBeforeClose !== $spaceBeforeClose + && ($this->ignoreNewlines === false + || $spaceBeforeClose !== 'newline') + ) { + $error = 'Expected %s spaces before closing bracket; %s found'; + $data = [ + $this->requiredSpacesBeforeClose, + $spaceBeforeClose, + ]; + + if ($beforeClosefixable === false) { + $phpcsFile->addError($error, $closingBracket, 'SpacingBeforeClose', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $closingBracket, 'SpacingBeforeClose', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesBeforeClose); + if ($spaceBeforeClose === 0) { + $phpcsFile->fixer->addContentBefore($closingBracket, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($closingBracket - 1), $padding); + for ($i = ($closingBracket - 2); $i > $prevNonWhiteSpace; $i--) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } + }//end if + }//end if + + /* + * Check whitespace around each of the semicolon tokens. + */ + + $semicolonCount = 0; + $semicolon = $openingBracket; + $targetNestinglevel = 0; + if (isset($tokens[$openingBracket]['conditions']) === true) { + $targetNestinglevel += count($tokens[$openingBracket]['conditions']); + } + + do { + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($semicolon + 1), $closingBracket); + if ($semicolon === false) { + break; + } + + if (isset($tokens[$semicolon]['conditions']) === true + && count($tokens[$semicolon]['conditions']) > $targetNestinglevel + ) { + // Semicolon doesn't belong to the for(). + continue; + } + + ++$semicolonCount; + + $humanReadableCount = 'first'; + if ($semicolonCount !== 1) { + $humanReadableCount = 'second'; + } + + $humanReadableCode = ucfirst($humanReadableCount); + $data = [$humanReadableCount]; + + // Only examine the space before the first semicolon if the first expression is not empty. + // If it *is* empty, leave it up to the `SpacingAfterOpen` logic. + $prevNonWhiteSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($semicolon - 1), $openingBracket, true); + if ($semicolonCount !== 1 || $prevNonWhiteSpace !== $openingBracket) { + if ($tokens[($semicolon - 1)]['code'] === T_WHITESPACE) { + $error = 'Whitespace found before %s semicolon of FOR loop'; + $errorCode = 'SpacingBefore'.$humanReadableCode; + $fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($semicolon - 1); $i > $prevNonWhiteSpace; $i--) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } + + // Only examine the space after the second semicolon if the last expression is not empty. + // If it *is* empty, leave it up to the `SpacingBeforeClose` logic. + $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, ($semicolon + 1), ($closingBracket + 1), true); + if ($semicolonCount !== 2 || $nextNonWhiteSpace !== $closingBracket) { + if ($tokens[($semicolon + 1)]['code'] !== T_WHITESPACE + && $tokens[($semicolon + 1)]['code'] !== T_SEMICOLON + ) { + $error = 'Expected 1 space after %s semicolon of FOR loop; 0 found'; + $errorCode = 'NoSpaceAfter'.$humanReadableCode; + $fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($semicolon, ' '); + } + } else if ($tokens[($semicolon + 1)]['code'] === T_WHITESPACE + && $tokens[$nextNonWhiteSpace]['code'] !== T_SEMICOLON + ) { + $spaces = $tokens[($semicolon + 1)]['length']; + if ($tokens[$semicolon]['line'] !== $tokens[$nextNonWhiteSpace]['line']) { + $spaces = 'newline'; + } + + if ($spaces !== 1 + && ($this->ignoreNewlines === false + || $spaces !== 'newline') + ) { + $error = 'Expected 1 space after %s semicolon of FOR loop; %s found'; + $errorCode = 'SpacingAfter'.$humanReadableCode; + $data[] = $spaces; + $fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($semicolon + 1), ' '); + for ($i = ($semicolon + 2); $i < $nextNonWhiteSpace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + }//end if + } while ($semicolonCount < 2); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/InlineIfDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/InlineIfDeclarationSniff.php new file mode 100644 index 00000000..28443794 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/InlineIfDeclarationSniff.php @@ -0,0 +1,155 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class InlineIfDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INLINE_THEN]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $openBracket = null; + $closeBracket = null; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $parens = $tokens[$stackPtr]['nested_parenthesis']; + $openBracket = array_pop($parens); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + } + + // Find the beginning of the statement. If we don't find a + // semicolon (end of statement) or comma (end of array value) + // then assume the content before the closing parenthesis is the end. + $else = $phpcsFile->findNext(T_INLINE_ELSE, ($stackPtr + 1)); + $statementEnd = $phpcsFile->findNext([T_SEMICOLON, T_COMMA], ($else + 1), $closeBracket); + if ($statementEnd === false) { + $statementEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), null, true); + } + + // Make sure it's all on the same line. + if ($tokens[$statementEnd]['line'] !== $tokens[$stackPtr]['line']) { + $error = 'Inline shorthand IF statement must be declared on a single line'; + $phpcsFile->addError($error, $stackPtr, 'NotSingleLine'); + return; + } + + // Make sure there are spaces around the question mark. + $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + $contentAfter = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$contentBefore]['code'] !== T_CLOSE_PARENTHESIS) { + $error = 'Inline shorthand IF statement requires brackets around comparison'; + $phpcsFile->addError($error, $stackPtr, 'NoBrackets'); + } + + $spaceBefore = ($tokens[$stackPtr]['column'] - ($tokens[$contentBefore]['column'] + $tokens[$contentBefore]['length'])); + if ($spaceBefore !== 1) { + $error = 'Inline shorthand IF statement requires 1 space before THEN; %s found'; + $data = [$spaceBefore]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeThen', $data); + if ($fix === true) { + if ($spaceBefore === 0) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + } + } + + // If there is no content between the ? and the : operators, then they are + // trying to replicate an elvis operator, even though PHP doesn't have one. + // In this case, we want no spaces between the two operators so ?: looks like + // an operator itself. + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_INLINE_ELSE) { + $inlineElse = $next; + if ($inlineElse !== ($stackPtr + 1)) { + $error = 'Inline shorthand IF statement without THEN statement requires 0 spaces between THEN and ELSE'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ElvisSpacing'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + } + } else { + $spaceAfter = (($tokens[$contentAfter]['column']) - ($tokens[$stackPtr]['column'] + 1)); + if ($spaceAfter !== 1) { + $error = 'Inline shorthand IF statement requires 1 space after THEN; %s found'; + $data = [$spaceAfter]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterThen', $data); + if ($fix === true) { + if ($spaceAfter === 0) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } + + // Make sure the ELSE has the correct spacing. + $inlineElse = $phpcsFile->findNext(T_INLINE_ELSE, ($stackPtr + 1), $statementEnd, false); + $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($inlineElse - 1), null, true); + $spaceBefore = ($tokens[$inlineElse]['column'] - ($tokens[$contentBefore]['column'] + $tokens[$contentBefore]['length'])); + if ($spaceBefore !== 1) { + $error = 'Inline shorthand IF statement requires 1 space before ELSE; %s found'; + $data = [$spaceBefore]; + $fix = $phpcsFile->addFixableError($error, $inlineElse, 'SpacingBeforeElse', $data); + if ($fix === true) { + if ($spaceBefore === 0) { + $phpcsFile->fixer->addContentBefore($inlineElse, ' '); + } else { + $phpcsFile->fixer->replaceToken(($inlineElse - 1), ' '); + } + } + } + }//end if + + $contentAfter = $phpcsFile->findNext(T_WHITESPACE, ($inlineElse + 1), null, true); + $spaceAfter = (($tokens[$contentAfter]['column']) - ($tokens[$inlineElse]['column'] + 1)); + if ($spaceAfter !== 1) { + $error = 'Inline shorthand IF statement requires 1 space after ELSE; %s found'; + $data = [$spaceAfter]; + $fix = $phpcsFile->addFixableError($error, $inlineElse, 'SpacingAfterElse', $data); + if ($fix === true) { + if ($spaceAfter === 0) { + $phpcsFile->fixer->addContent($inlineElse, ' '); + } else { + $phpcsFile->fixer->replaceToken(($inlineElse + 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/LowercaseDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/LowercaseDeclarationSniff.php new file mode 100644 index 00000000..cba07684 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/LowercaseDeclarationSniff.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LowercaseDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_ELSE, + T_ELSEIF, + T_FOREACH, + T_FOR, + T_DO, + T_SWITCH, + T_WHILE, + T_TRY, + T_CATCH, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $contentLc = strtolower($content); + if ($content !== $contentLc) { + $error = '%s keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + strtoupper($content), + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FoundUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/SwitchDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/SwitchDeclarationSniff.php new file mode 100644 index 00000000..a5f3769d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/SwitchDeclarationSniff.php @@ -0,0 +1,304 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SwitchDeclarationSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_SWITCH]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // We can't process SWITCH statements unless we know where they start and end. + if (isset($tokens[$stackPtr]['scope_opener']) === false + || isset($tokens[$stackPtr]['scope_closer']) === false + ) { + return; + } + + $switch = $tokens[$stackPtr]; + $nextCase = $stackPtr; + $caseAlignment = ($switch['column'] + $this->indent); + $caseCount = 0; + $foundDefault = false; + + while (($nextCase = $phpcsFile->findNext([T_CASE, T_DEFAULT, T_SWITCH], ($nextCase + 1), $switch['scope_closer'])) !== false) { + // Skip nested SWITCH statements; they are handled on their own. + if ($tokens[$nextCase]['code'] === T_SWITCH) { + $nextCase = $tokens[$nextCase]['scope_closer']; + continue; + } + + if ($tokens[$nextCase]['code'] === T_DEFAULT) { + $type = 'Default'; + $foundDefault = true; + } else { + $type = 'Case'; + $caseCount++; + } + + if ($tokens[$nextCase]['content'] !== strtolower($tokens[$nextCase]['content'])) { + $expected = strtolower($tokens[$nextCase]['content']); + $error = strtoupper($type).' keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + $expected, + $tokens[$nextCase]['content'], + ]; + + $fix = $phpcsFile->addFixableError($error, $nextCase, $type.'NotLower', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($nextCase, $expected); + } + } + + if ($tokens[$nextCase]['column'] !== $caseAlignment) { + $error = strtoupper($type).' keyword must be indented '.$this->indent.' spaces from SWITCH keyword'; + $fix = $phpcsFile->addFixableError($error, $nextCase, $type.'Indent'); + + if ($fix === true) { + $padding = str_repeat(' ', ($caseAlignment - 1)); + if ($tokens[$nextCase]['column'] === 1 + || $tokens[($nextCase - 1)]['code'] !== T_WHITESPACE + ) { + $phpcsFile->fixer->addContentBefore($nextCase, $padding); + } else { + $phpcsFile->fixer->replaceToken(($nextCase - 1), $padding); + } + } + } + + if ($type === 'Case' + && ($tokens[($nextCase + 1)]['type'] !== 'T_WHITESPACE' + || $tokens[($nextCase + 1)]['content'] !== ' ') + ) { + $error = 'CASE keyword must be followed by a single space'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'SpacingAfterCase'); + if ($fix === true) { + if ($tokens[($nextCase + 1)]['type'] !== 'T_WHITESPACE') { + $phpcsFile->fixer->addContent($nextCase, ' '); + } else { + $phpcsFile->fixer->replaceToken(($nextCase + 1), ' '); + } + } + } + + if (isset($tokens[$nextCase]['scope_opener']) === false) { + $error = 'Possible parse error: CASE missing opening colon'; + $phpcsFile->addWarning($error, $nextCase, 'MissingColon'); + continue; + } + + $opener = $tokens[$nextCase]['scope_opener']; + if ($tokens[($opener - 1)]['type'] === 'T_WHITESPACE') { + $error = 'There must be no space before the colon in a '.strtoupper($type).' statement'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'SpaceBeforeColon'.$type); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($opener - 1), ''); + } + } + + $nextBreak = $tokens[$nextCase]['scope_closer']; + if ($tokens[$nextBreak]['code'] === T_BREAK + || $tokens[$nextBreak]['code'] === T_RETURN + || $tokens[$nextBreak]['code'] === T_CONTINUE + || $tokens[$nextBreak]['code'] === T_THROW + || $tokens[$nextBreak]['code'] === T_EXIT + ) { + if ($tokens[$nextBreak]['scope_condition'] === $nextCase) { + // Only need to check a couple of things once, even if the + // break is shared between multiple case statements, or even + // the default case. + if ($tokens[$nextBreak]['column'] !== $caseAlignment) { + $error = 'Case breaking statement must be indented '.$this->indent.' spaces from SWITCH keyword'; + $fix = $phpcsFile->addFixableError($error, $nextBreak, 'BreakIndent'); + + if ($fix === true) { + $padding = str_repeat(' ', ($caseAlignment - 1)); + if ($tokens[$nextBreak]['column'] === 1 + || $tokens[($nextBreak - 1)]['code'] !== T_WHITESPACE + ) { + $phpcsFile->fixer->addContentBefore($nextBreak, $padding); + } else { + $phpcsFile->fixer->replaceToken(($nextBreak - 1), $padding); + } + } + } + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($nextBreak - 1), $stackPtr, true); + if ($tokens[$prev]['line'] !== ($tokens[$nextBreak]['line'] - 1)) { + $error = 'Blank lines are not allowed before case breaking statements'; + $phpcsFile->addError($error, $nextBreak, 'SpacingBeforeBreak'); + } + + $nextLine = $tokens[$tokens[$stackPtr]['scope_closer']]['line']; + $semicolon = $phpcsFile->findEndOfStatement($nextBreak); + for ($i = ($semicolon + 1); $i < $tokens[$stackPtr]['scope_closer']; $i++) { + if ($tokens[$i]['type'] !== 'T_WHITESPACE') { + $nextLine = $tokens[$i]['line']; + break; + } + } + + if ($type === 'Case') { + // Ensure the BREAK statement is followed by + // a single blank line, or the end switch brace. + if ($nextLine !== ($tokens[$semicolon]['line'] + 2) && $i !== $tokens[$stackPtr]['scope_closer']) { + $error = 'Case breaking statements must be followed by a single blank line'; + $fix = $phpcsFile->addFixableError($error, $nextBreak, 'SpacingAfterBreak'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($semicolon + 1); $i <= $tokens[$stackPtr]['scope_closer']; $i++) { + if ($tokens[$i]['line'] === $nextLine) { + $phpcsFile->fixer->addNewlineBefore($i); + break; + } + + if ($tokens[$i]['line'] === $tokens[$semicolon]['line']) { + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + } else { + // Ensure the BREAK statement is not followed by a blank line. + if ($nextLine !== ($tokens[$semicolon]['line'] + 1)) { + $error = 'Blank lines are not allowed after the DEFAULT case\'s breaking statement'; + $phpcsFile->addError($error, $nextBreak, 'SpacingAfterDefaultBreak'); + } + }//end if + + $caseLine = $tokens[$nextCase]['line']; + $nextLine = $tokens[$nextBreak]['line']; + for ($i = ($opener + 1); $i < $nextBreak; $i++) { + if ($tokens[$i]['type'] !== 'T_WHITESPACE') { + $nextLine = $tokens[$i]['line']; + break; + } + } + + if ($nextLine !== ($caseLine + 1)) { + $error = 'Blank lines are not allowed after '.strtoupper($type).' statements'; + $phpcsFile->addError($error, $nextCase, 'SpacingAfter'.$type); + } + }//end if + + if ($tokens[$nextBreak]['code'] === T_BREAK) { + if ($type === 'Case') { + // Ensure empty CASE statements are not allowed. + // They must have some code content in them. A comment is not enough. + // But count RETURN statements as valid content if they also + // happen to close the CASE statement. + $foundContent = false; + for ($i = ($tokens[$nextCase]['scope_opener'] + 1); $i < $nextBreak; $i++) { + if ($tokens[$i]['code'] === T_CASE) { + $i = $tokens[$i]['scope_opener']; + continue; + } + + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) { + $foundContent = true; + break; + } + } + + if ($foundContent === false) { + $error = 'Empty CASE statements are not allowed'; + $phpcsFile->addError($error, $nextCase, 'EmptyCase'); + } + } else { + // Ensure empty DEFAULT statements are not allowed. + // They must (at least) have a comment describing why + // the default case is being ignored. + $foundContent = false; + for ($i = ($tokens[$nextCase]['scope_opener'] + 1); $i < $nextBreak; $i++) { + if ($tokens[$i]['type'] !== 'T_WHITESPACE') { + $foundContent = true; + break; + } + } + + if ($foundContent === false) { + $error = 'Comment required for empty DEFAULT case'; + $phpcsFile->addError($error, $nextCase, 'EmptyDefault'); + } + }//end if + }//end if + } else if ($type === 'Default') { + $error = 'DEFAULT case must have a breaking statement'; + $phpcsFile->addError($error, $nextCase, 'DefaultNoBreak'); + }//end if + }//end while + + if ($foundDefault === false) { + $error = 'All SWITCH statements must contain a DEFAULT case'; + $phpcsFile->addError($error, $stackPtr, 'MissingDefault'); + } + + if ($tokens[$switch['scope_closer']]['column'] !== $switch['column']) { + $error = 'Closing brace of SWITCH statement must be aligned with SWITCH keyword'; + $phpcsFile->addError($error, $switch['scope_closer'], 'CloseBraceAlign'); + } + + if ($caseCount === 0) { + $error = 'SWITCH statements must contain at least one CASE statement'; + $phpcsFile->addError($error, $stackPtr, 'MissingCase'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JSLintSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JSLintSniff.php new file mode 100644 index 00000000..49dfc2c4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JSLintSniff.php @@ -0,0 +1,86 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class JSLintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If jslint.js could not be run + */ + public function process(File $phpcsFile, $stackPtr) + { + $rhinoPath = Config::getExecutablePath('rhino'); + $jslintPath = Config::getExecutablePath('jslint'); + if ($rhinoPath === null || $jslintPath === null) { + return; + } + + $fileName = $phpcsFile->getFilename(); + + $rhinoPath = Common::escapeshellcmd($rhinoPath); + $jslintPath = Common::escapeshellcmd($jslintPath); + + $cmd = "$rhinoPath \"$jslintPath\" ".escapeshellarg($fileName); + exec($cmd, $output, $retval); + + if (is_array($output) === true) { + foreach ($output as $finding) { + $matches = []; + $numMatches = preg_match('/Lint at line ([0-9]+).*:(.*)$/', $finding, $matches); + if ($numMatches === 0) { + continue; + } + + $line = (int) $matches[1]; + $message = 'jslint says: '.trim($matches[2]); + $phpcsFile->addWarningOnLine($message, $line, 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JavaScriptLintSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JavaScriptLintSniff.php new file mode 100644 index 00000000..30dca672 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JavaScriptLintSniff.php @@ -0,0 +1,89 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class JavaScriptLintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If Javascript Lint ran into trouble. + */ + public function process(File $phpcsFile, $stackPtr) + { + $jslPath = Config::getExecutablePath('jsl'); + if ($jslPath === null) { + return; + } + + $fileName = $phpcsFile->getFilename(); + + $cmd = '"'.Common::escapeshellcmd($jslPath).'" -nologo -nofilelisting -nocontext -nosummary -output-format __LINE__:__ERROR__ -process '.escapeshellarg($fileName); + $msg = exec($cmd, $output, $retval); + + // Variable $exitCode is the last line of $output if no error occurs, on + // error it is numeric. Try to handle various error conditions and + // provide useful error reporting. + if ($retval === 2 || $retval === 4) { + if (is_array($output) === true) { + $msg = join('\n', $output); + } + + throw new RuntimeException("Failed invoking JavaScript Lint, retval was [$retval], output was [$msg]"); + } + + if (is_array($output) === true) { + foreach ($output as $finding) { + $split = strpos($finding, ':'); + $line = substr($finding, 0, $split); + $message = substr($finding, ($split + 1)); + $phpcsFile->addWarningOnLine(trim($message), $line, 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Files/FileExtensionSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Files/FileExtensionSniff.php new file mode 100644 index 00000000..6277b809 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Files/FileExtensionSniff.php @@ -0,0 +1,68 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FileExtensionSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $fileName = $phpcsFile->getFilename(); + $extension = substr($fileName, strrpos($fileName, '.')); + $nextClass = $phpcsFile->findNext([T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM], $stackPtr); + + if ($nextClass !== false) { + $phpcsFile->recordMetric($stackPtr, 'File extension for class files', $extension); + if ($extension === '.php') { + $error = '%s found in ".php" file; use ".inc" extension instead'; + $data = [ucfirst($tokens[$nextClass]['content'])]; + $phpcsFile->addError($error, $stackPtr, 'ClassFound', $data); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'File extension for non-class files', $extension); + if ($extension === '.inc') { + $error = 'No interface or class found in ".inc" file; use ".php" extension instead'; + $phpcsFile->addError($error, $stackPtr, 'NoClass'); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php new file mode 100644 index 00000000..60b113d3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php @@ -0,0 +1,393 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OperatorBracketSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$operators; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($phpcsFile->tokenizerType === 'JS' && $tokens[$stackPtr]['code'] === T_PLUS) { + // JavaScript uses the plus operator for string concatenation as well + // so we cannot accurately determine if it is a string concat or addition. + // So just ignore it. + return; + } + + // If the & is a reference, then we don't want to check for brackets. + if ($tokens[$stackPtr]['code'] === T_BITWISE_AND && $phpcsFile->isReference($stackPtr) === true) { + return; + } + + // There is one instance where brackets aren't needed, which involves + // the minus sign being used to assign a negative number to a variable. + if ($tokens[$stackPtr]['code'] === T_MINUS) { + // Check to see if we are trying to return -n. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_RETURN) { + return; + } + + $number = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$number]['code'] === T_LNUMBER || $tokens[$number]['code'] === T_DNUMBER) { + $previous = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($previous !== false) { + $isAssignment = isset(Tokens::$assignmentTokens[$tokens[$previous]['code']]); + $isEquality = isset(Tokens::$equalityTokens[$tokens[$previous]['code']]); + $isComparison = isset(Tokens::$comparisonTokens[$tokens[$previous]['code']]); + $isUnary = isset(Tokens::$operators[$tokens[$previous]['code']]); + if ($isAssignment === true || $isEquality === true || $isComparison === true || $isUnary === true) { + // This is a negative assignment or comparison. + // We need to check that the minus and the number are + // adjacent. + if (($number - $stackPtr) !== 1) { + $error = 'No space allowed between minus sign and number'; + $phpcsFile->addError($error, $stackPtr, 'SpacingAfterMinus'); + } + + return; + } + } + } + }//end if + + $previousToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true, null, true); + if ($previousToken !== false) { + // A list of tokens that indicate that the token is not + // part of an arithmetic operation. + $invalidTokens = [ + T_COMMA => true, + T_COLON => true, + T_OPEN_PARENTHESIS => true, + T_OPEN_SQUARE_BRACKET => true, + T_OPEN_CURLY_BRACKET => true, + T_OPEN_SHORT_ARRAY => true, + T_CASE => true, + T_EXIT => true, + ]; + + if (isset($invalidTokens[$tokens[$previousToken]['code']]) === true) { + return; + } + } + + if ($tokens[$stackPtr]['code'] === T_BITWISE_OR + && isset($tokens[$stackPtr]['nested_parenthesis']) === true + ) { + $brackets = $tokens[$stackPtr]['nested_parenthesis']; + $lastBracket = array_pop($brackets); + if (isset($tokens[$lastBracket]['parenthesis_owner']) === true + && $tokens[$tokens[$lastBracket]['parenthesis_owner']]['code'] === T_CATCH + ) { + // This is a pipe character inside a catch statement, so it is acting + // as an exception type separator and not an arithmetic operation. + return; + } + } + + // Tokens that are allowed inside a bracketed operation. + $allowed = [ + T_VARIABLE, + T_LNUMBER, + T_DNUMBER, + T_STRING, + T_WHITESPACE, + T_NS_SEPARATOR, + T_THIS, + T_SELF, + T_STATIC, + T_OBJECT_OPERATOR, + T_NULLSAFE_OBJECT_OPERATOR, + T_DOUBLE_COLON, + T_OPEN_SQUARE_BRACKET, + T_CLOSE_SQUARE_BRACKET, + T_MODULUS, + T_NONE, + T_BITWISE_NOT, + ]; + + $allowed += Tokens::$operators; + + $lastBracket = false; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $parenthesis = array_reverse($tokens[$stackPtr]['nested_parenthesis'], true); + foreach ($parenthesis as $bracket => $endBracket) { + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($bracket - 1), null, true); + $prevCode = $tokens[$prevToken]['code']; + + if ($prevCode === T_ISSET) { + // This operation is inside an isset() call, but has + // no bracket of it's own. + break; + } + + if ($prevCode === T_STRING || $prevCode === T_SWITCH || $prevCode === T_MATCH) { + // We allow simple operations to not be bracketed. + // For example, ceil($one / $two). + for ($prev = ($stackPtr - 1); $prev > $bracket; $prev--) { + if (in_array($tokens[$prev]['code'], $allowed, true) === true) { + continue; + } + + if ($tokens[$prev]['code'] === T_CLOSE_PARENTHESIS) { + $prev = $tokens[$prev]['parenthesis_opener']; + } else { + break; + } + } + + if ($prev !== $bracket) { + break; + } + + for ($next = ($stackPtr + 1); $next < $endBracket; $next++) { + if (in_array($tokens[$next]['code'], $allowed, true) === true) { + continue; + } + + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + $next = $tokens[$next]['parenthesis_closer']; + } else { + break; + } + } + + if ($next !== $endBracket) { + break; + } + }//end if + + if (in_array($prevCode, Tokens::$scopeOpeners, true) === true) { + // This operation is inside a control structure like FOREACH + // or IF, but has no bracket of it's own. + // The only control structures allowed to do this are SWITCH and MATCH. + if ($prevCode !== T_SWITCH && $prevCode !== T_MATCH) { + break; + } + } + + if ($prevCode === T_OPEN_PARENTHESIS) { + // These are two open parenthesis in a row. If the current + // one doesn't enclose the operator, go to the previous one. + if ($endBracket < $stackPtr) { + continue; + } + } + + $lastBracket = $bracket; + break; + }//end foreach + }//end if + + if ($lastBracket === false) { + // It is not in a bracketed statement at all. + $this->addMissingBracketsError($phpcsFile, $stackPtr); + return; + } else if ($tokens[$lastBracket]['parenthesis_closer'] < $stackPtr) { + // There are a set of brackets in front of it that don't include it. + $this->addMissingBracketsError($phpcsFile, $stackPtr); + return; + } else { + // We are enclosed in a set of bracket, so the last thing to + // check is that we are not also enclosed in square brackets + // like this: ($array[$index + 1]), which is invalid. + $brackets = [ + T_OPEN_SQUARE_BRACKET, + T_CLOSE_SQUARE_BRACKET, + ]; + + $squareBracket = $phpcsFile->findPrevious($brackets, ($stackPtr - 1), $lastBracket); + if ($squareBracket !== false && $tokens[$squareBracket]['code'] === T_OPEN_SQUARE_BRACKET) { + $closeSquareBracket = $phpcsFile->findNext($brackets, ($stackPtr + 1)); + if ($closeSquareBracket !== false && $tokens[$closeSquareBracket]['code'] === T_CLOSE_SQUARE_BRACKET) { + $this->addMissingBracketsError($phpcsFile, $stackPtr); + } + } + + return; + }//end if + + $lastAssignment = $phpcsFile->findPrevious(Tokens::$assignmentTokens, $stackPtr, null, false, null, true); + if ($lastAssignment !== false && $lastAssignment > $lastBracket) { + $this->addMissingBracketsError($phpcsFile, $stackPtr); + } + + }//end process() + + + /** + * Add and fix the missing brackets error. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function addMissingBracketsError($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $allowed = [ + T_VARIABLE => true, + T_LNUMBER => true, + T_DNUMBER => true, + T_STRING => true, + T_CONSTANT_ENCAPSED_STRING => true, + T_DOUBLE_QUOTED_STRING => true, + T_WHITESPACE => true, + T_NS_SEPARATOR => true, + T_THIS => true, + T_SELF => true, + T_STATIC => true, + T_OBJECT_OPERATOR => true, + T_NULLSAFE_OBJECT_OPERATOR => true, + T_DOUBLE_COLON => true, + T_MODULUS => true, + T_ISSET => true, + T_ARRAY => true, + T_NONE => true, + T_BITWISE_NOT => true, + ]; + + // Find the first token in the expression. + for ($before = ($stackPtr - 1); $before > 0; $before--) { + // Special case for plus operators because we can't tell if they are used + // for addition or string contact. So assume string concat to be safe. + if ($phpcsFile->tokenizerType === 'JS' && $tokens[$before]['code'] === T_PLUS) { + break; + } + + if (isset(Tokens::$emptyTokens[$tokens[$before]['code']]) === true + || isset(Tokens::$operators[$tokens[$before]['code']]) === true + || isset(Tokens::$castTokens[$tokens[$before]['code']]) === true + || isset($allowed[$tokens[$before]['code']]) === true + ) { + continue; + } + + if ($tokens[$before]['code'] === T_CLOSE_PARENTHESIS) { + $before = $tokens[$before]['parenthesis_opener']; + continue; + } + + if ($tokens[$before]['code'] === T_CLOSE_SQUARE_BRACKET) { + $before = $tokens[$before]['bracket_opener']; + continue; + } + + if ($tokens[$before]['code'] === T_CLOSE_SHORT_ARRAY) { + $before = $tokens[$before]['bracket_opener']; + continue; + } + + break; + }//end for + + $before = $phpcsFile->findNext(Tokens::$emptyTokens, ($before + 1), null, true); + + // A few extra tokens are allowed to be on the right side of the expression. + $allowed[T_EQUAL] = true; + $allowed[T_NEW] = true; + + // Find the last token in the expression. + for ($after = ($stackPtr + 1); $after < $phpcsFile->numTokens; $after++) { + // Special case for plus operators because we can't tell if they are used + // for addition or string concat. So assume string concat to be safe. + if ($phpcsFile->tokenizerType === 'JS' && $tokens[$after]['code'] === T_PLUS) { + break; + } + + if (isset(Tokens::$emptyTokens[$tokens[$after]['code']]) === true + || isset(Tokens::$operators[$tokens[$after]['code']]) === true + || isset(Tokens::$castTokens[$tokens[$after]['code']]) === true + || isset($allowed[$tokens[$after]['code']]) === true + ) { + continue; + } + + if ($tokens[$after]['code'] === T_OPEN_PARENTHESIS) { + $after = $tokens[$after]['parenthesis_closer']; + continue; + } + + if ($tokens[$after]['code'] === T_OPEN_SQUARE_BRACKET) { + $after = $tokens[$after]['bracket_closer']; + continue; + } + + if ($tokens[$after]['code'] === T_OPEN_SHORT_ARRAY) { + $after = $tokens[$after]['bracket_closer']; + continue; + } + + break; + }//end for + + $after = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($after - 1), null, true); + + $error = 'Operation must be bracketed'; + if ($before === $after || $before === $stackPtr || $after === $stackPtr) { + $phpcsFile->addError($error, $stackPtr, 'MissingBrackets'); + return; + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MissingBrackets'); + if ($fix === true) { + // Can only fix this error if both tokens are available for fixing. + // Adding one bracket without the other will create parse errors. + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($before, '('.$tokens[$before]['content']); + $phpcsFile->fixer->replaceToken($after, $tokens[$after]['content'].')'); + $phpcsFile->fixer->endChangeset(); + } + + }//end addMissingBracketsError() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php new file mode 100644 index 00000000..e696d800 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php @@ -0,0 +1,398 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionDeclarationArgumentSpacingSniff implements Sniff +{ + + /** + * How many spaces should surround the equals signs. + * + * @var integer + */ + public $equalsSpacing = 0; + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + T_FN, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + || $tokens[$stackPtr]['parenthesis_opener'] === null + || $tokens[$stackPtr]['parenthesis_closer'] === null + ) { + return; + } + + $this->equalsSpacing = (int) $this->equalsSpacing; + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + + $this->processBracket($phpcsFile, $tokens[$stackPtr]['parenthesis_opener']); + + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($tokens[$stackPtr]['parenthesis_closer'] + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1), null); + $this->processBracket($phpcsFile, $openBracket); + } + } + + }//end process() + + + /** + * Processes the contents of a single set of brackets. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $openBracket The position of the open bracket + * in the stack. + * + * @return void + */ + public function processBracket($phpcsFile, $openBracket) + { + $tokens = $phpcsFile->getTokens(); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + $multiLine = ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']); + + if (isset($tokens[$openBracket]['parenthesis_owner']) === true) { + $stackPtr = $tokens[$openBracket]['parenthesis_owner']; + } else { + $stackPtr = $phpcsFile->findPrevious(T_USE, ($openBracket - 1)); + } + + $params = $phpcsFile->getMethodParameters($stackPtr); + + if (empty($params) === true) { + // Check spacing around parenthesis. + $next = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), $closeBracket, true); + if ($next === false) { + if (($closeBracket - $openBracket) !== 1) { + if ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($openBracket + 1)]['length']; + } + + $error = 'Expected 0 spaces between parenthesis of function declaration; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $openBracket, 'SpacingBetween', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } + } + + // No params, so we don't check normal spacing rules. + return; + } + }//end if + + foreach ($params as $paramNumber => $param) { + if ($param['pass_by_reference'] === true) { + $refToken = $param['reference_token']; + + $gap = 0; + if ($tokens[($refToken + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($refToken + 1)]['length']; + } + + if ($gap !== 0) { + $error = 'Expected 0 spaces after reference operator for argument "%s"; %s found'; + $data = [ + $param['name'], + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $refToken, 'SpacingAfterReference', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($refToken + 1), ''); + } + } + }//end if + + if ($param['variable_length'] === true) { + $variadicToken = $param['variadic_token']; + + $gap = 0; + if ($tokens[($variadicToken + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($variadicToken + 1)]['length']; + } + + if ($gap !== 0) { + $error = 'Expected 0 spaces after variadic operator for argument "%s"; %s found'; + $data = [ + $param['name'], + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $variadicToken, 'SpacingAfterVariadic', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($variadicToken + 1), ''); + } + } + }//end if + + if (isset($param['default_equal_token']) === true) { + $equalToken = $param['default_equal_token']; + + $spacesBefore = 0; + if (($equalToken - $param['token']) > 1) { + $spacesBefore = $tokens[($param['token'] + 1)]['length']; + } + + if ($spacesBefore !== $this->equalsSpacing) { + $error = 'Incorrect spacing between argument "%s" and equals sign; expected '.$this->equalsSpacing.' but found %s'; + $data = [ + $param['name'], + $spacesBefore, + ]; + + $fix = $phpcsFile->addFixableError($error, $equalToken, 'SpaceBeforeEquals', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->equalsSpacing); + if ($spacesBefore === 0) { + $phpcsFile->fixer->addContentBefore($equalToken, $padding); + } else { + $phpcsFile->fixer->replaceToken(($equalToken - 1), $padding); + } + } + }//end if + + $spacesAfter = 0; + if ($tokens[($equalToken + 1)]['code'] === T_WHITESPACE) { + $spacesAfter = $tokens[($equalToken + 1)]['length']; + } + + if ($spacesAfter !== $this->equalsSpacing) { + $error = 'Incorrect spacing between default value and equals sign for argument "%s"; expected '.$this->equalsSpacing.' but found %s'; + $data = [ + $param['name'], + $spacesAfter, + ]; + + $fix = $phpcsFile->addFixableError($error, $equalToken, 'SpaceAfterEquals', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->equalsSpacing); + if ($spacesAfter === 0) { + $phpcsFile->fixer->addContent($equalToken, $padding); + } else { + $phpcsFile->fixer->replaceToken(($equalToken + 1), $padding); + } + } + }//end if + }//end if + + if ($param['type_hint_token'] !== false) { + $typeHintToken = $param['type_hint_end_token']; + + $gap = 0; + if ($tokens[($typeHintToken + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($typeHintToken + 1)]['length']; + } + + if ($gap !== 1) { + $error = 'Expected 1 space between type hint and argument "%s"; %s found'; + $data = [ + $param['name'], + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $typeHintToken, 'SpacingAfterHint', $data); + if ($fix === true) { + if ($gap === 0) { + $phpcsFile->fixer->addContent($typeHintToken, ' '); + } else { + $phpcsFile->fixer->replaceToken(($typeHintToken + 1), ' '); + } + } + } + }//end if + + $commaToken = false; + if ($paramNumber > 0 && $params[($paramNumber - 1)]['comma_token'] !== false) { + $commaToken = $params[($paramNumber - 1)]['comma_token']; + } + + if ($commaToken !== false) { + if ($tokens[($commaToken - 1)]['code'] === T_WHITESPACE) { + $error = 'Expected 0 spaces between argument "%s" and comma; %s found'; + $data = [ + $params[($paramNumber - 1)]['name'], + $tokens[($commaToken - 1)]['length'], + ]; + + $fix = $phpcsFile->addFixableError($error, $commaToken, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($commaToken - 1), ''); + } + } + + // Don't check spacing after the comma if it is the last content on the line. + $checkComma = true; + if ($multiLine === true) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($commaToken + 1), $closeBracket, true); + if ($tokens[$next]['line'] !== $tokens[$commaToken]['line']) { + $checkComma = false; + } + } + + if ($checkComma === true) { + if ($param['type_hint_token'] === false) { + $spacesAfter = 0; + if ($tokens[($commaToken + 1)]['code'] === T_WHITESPACE) { + $spacesAfter = $tokens[($commaToken + 1)]['length']; + } + + if ($spacesAfter === 0) { + $error = 'Expected 1 space between comma and argument "%s"; 0 found'; + $data = [$param['name']]; + $fix = $phpcsFile->addFixableError($error, $commaToken, 'NoSpaceBeforeArg', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($commaToken, ' '); + } + } else if ($spacesAfter !== 1) { + $error = 'Expected 1 space between comma and argument "%s"; %s found'; + $data = [ + $param['name'], + $spacesAfter, + ]; + + $fix = $phpcsFile->addFixableError($error, $commaToken, 'SpacingBeforeArg', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($commaToken + 1), ' '); + } + }//end if + } else { + $hint = $phpcsFile->getTokensAsString($param['type_hint_token'], (($param['type_hint_end_token'] - $param['type_hint_token']) + 1)); + if ($param['nullable_type'] === true) { + $hint = '?'.$hint; + } + + if ($tokens[($commaToken + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space between comma and type hint "%s"; 0 found'; + $data = [$hint]; + $fix = $phpcsFile->addFixableError($error, $commaToken, 'NoSpaceBeforeHint', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($commaToken, ' '); + } + } else { + $gap = $tokens[($commaToken + 1)]['length']; + if ($gap !== 1) { + $error = 'Expected 1 space between comma and type hint "%s"; %s found'; + $data = [ + $hint, + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $commaToken, 'SpacingBeforeHint', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($commaToken + 1), ' '); + } + } + }//end if + }//end if + }//end if + }//end if + }//end foreach + + // Only check spacing around parenthesis for single line definitions. + if ($multiLine === true) { + return; + } + + $gap = 0; + if ($tokens[($closeBracket - 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($closeBracket - 1)]['length']; + } + + if ($gap !== $this->requiredSpacesBeforeClose) { + $error = 'Expected %s spaces before closing parenthesis; %s found'; + $data = [ + $this->requiredSpacesBeforeClose, + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'SpacingBeforeClose', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesBeforeClose); + if ($gap === 0) { + $phpcsFile->fixer->addContentBefore($closeBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($closeBracket - 1), $padding); + } + } + } + + $gap = 0; + if ($tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($openBracket + 1)]['length']; + } + + if ($gap !== $this->requiredSpacesAfterOpen) { + $error = 'Expected %s spaces after opening parenthesis; %s found'; + $data = [ + $this->requiredSpacesAfterOpen, + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $openBracket, 'SpacingAfterOpen', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesAfterOpen); + if ($gap === 0) { + $phpcsFile->fixer->addContent($openBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($openBracket + 1), $padding); + } + } + } + + }//end processBracket() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationSniff.php new file mode 100644 index 00000000..4b6a6acf --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationSniff.php @@ -0,0 +1,34 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Sniffs\AbstractPatternSniff; + +class FunctionDeclarationSniff extends AbstractPatternSniff +{ + + + /** + * Returns an array of patterns to check are correct. + * + * @return array + */ + protected function getPatterns() + { + return [ + 'function abc(...);', + 'function abc(...)', + 'abstract function abc(...);', + ]; + + }//end getPatterns() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDuplicateArgumentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDuplicateArgumentSniff.php new file mode 100644 index 00000000..f6fc383a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDuplicateArgumentSniff.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FunctionDuplicateArgumentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + + $foundVariables = []; + for ($i = ($openBracket + 1); $i < $closeBracket; $i++) { + if ($tokens[$i]['code'] === T_VARIABLE) { + $variable = $tokens[$i]['content']; + if (in_array($variable, $foundVariables, true) === true) { + $error = 'Variable "%s" appears more than once in function declaration'; + $data = [$variable]; + $phpcsFile->addError($error, $i, 'Found', $data); + } else { + $foundVariables[] = $variable; + } + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/GlobalFunctionSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/GlobalFunctionSniff.php new file mode 100644 index 00000000..24588a91 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/GlobalFunctionSniff.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class GlobalFunctionSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (empty($tokens[$stackPtr]['conditions']) === true) { + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if ($functionName === null) { + return; + } + + // Special exception for __autoload as it needs to be global. + if ($functionName !== '__autoload') { + $error = 'Consider putting global function "%s" in a static class'; + $data = [$functionName]; + $phpcsFile->addWarning($error, $stackPtr, 'Found', $data); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php new file mode 100644 index 00000000..2357960c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php @@ -0,0 +1,69 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LowercaseFunctionKeywordsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $tokens = Tokens::$methodPrefixes; + $tokens[] = T_FUNCTION; + $tokens[] = T_CLOSURE; + $tokens[] = T_FN; + + return $tokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $contentLc = strtolower($content); + if ($content !== $contentLc) { + $error = '%s keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + strtoupper($content), + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FoundUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/MultiLineFunctionDeclarationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/MultiLineFunctionDeclarationSniff.php new file mode 100644 index 00000000..c12bd0c4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/MultiLineFunctionDeclarationSniff.php @@ -0,0 +1,258 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions\FunctionDeclarationSniff as PEARFunctionDeclarationSniff; +use PHP_CodeSniffer\Util\Tokens; + +class MultiLineFunctionDeclarationSniff extends PEARFunctionDeclarationSniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Determine if this is a multi-line function declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function isMultiLineDeclaration($phpcsFile, $stackPtr, $openBracket, $tokens) + { + $bracketsToCheck = [$stackPtr => $openBracket]; + + // Closures may use the USE keyword and so be multi-line in this way. + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($tokens[$openBracket]['parenthesis_closer'] + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $open = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + if ($open !== false) { + $bracketsToCheck[$use] = $open; + } + } + } + + foreach ($bracketsToCheck as $stackPtr => $openBracket) { + // If the first argument is on a new line, this is a multi-line + // function declaration, even if there is only one argument. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + return true; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + $end = $phpcsFile->findEndOfStatement($openBracket + 1); + while ($tokens[$end]['code'] === T_COMMA) { + // If the next bit of code is not on the same line, this is a + // multi-line function declaration. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $closeBracket, true); + if ($next === false) { + continue(2); + } + + if ($tokens[$next]['line'] !== $tokens[$end]['line']) { + return true; + } + + $end = $phpcsFile->findEndOfStatement($next); + } + + // We've reached the last argument, so see if the next content + // (should be the close bracket) is also on the same line. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $closeBracket, true); + if ($next !== false && $tokens[$next]['line'] !== $tokens[$end]['line']) { + return true; + } + }//end foreach + + return false; + + }//end isMultiLineDeclaration() + + + /** + * Processes single-line declarations. + * + * Just uses the Generic BSD-Allman brace sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens) + { + // We do everything the parent sniff does, and a bit more because we + // define multi-line declarations a bit differently. + parent::processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens); + + $openingBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closingBracket = $tokens[$stackPtr]['parenthesis_closer']; + + $prevNonWhiteSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($closingBracket - 1), $openingBracket, true); + if ($tokens[$prevNonWhiteSpace]['line'] !== $tokens[$closingBracket]['line']) { + $error = 'There must not be a newline before the closing parenthesis of a single-line function declaration'; + + if (isset(Tokens::$emptyTokens[$tokens[$prevNonWhiteSpace]['code']]) === true) { + $phpcsFile->addError($error, $closingBracket, 'CloseBracketNewLine'); + } else { + $fix = $phpcsFile->addFixableError($error, $closingBracket, 'CloseBracketNewLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closingBracket - 1); $i > $openingBracket; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end processSingleLineDeclaration() + + + /** + * Processes multi-line declarations. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens) + { + // We do everything the parent sniff does, and a bit more. + parent::processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens); + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $this->processBracket($phpcsFile, $openBracket, $tokens, 'function'); + + if ($tokens[$stackPtr]['code'] !== T_CLOSURE) { + return; + } + + $use = $phpcsFile->findNext(T_USE, ($tokens[$stackPtr]['parenthesis_closer'] + 1), $tokens[$stackPtr]['scope_opener']); + if ($use === false) { + return; + } + + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1), null); + $this->processBracket($phpcsFile, $openBracket, $tokens, 'use'); + + }//end processMultiLineDeclaration() + + + /** + * Processes the contents of a single set of brackets. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $openBracket The position of the open bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * @param string $type The type of the token the brackets + * belong to (function or use). + * + * @return void + */ + public function processBracket($phpcsFile, $openBracket, $tokens, $type='function') + { + $errorPrefix = ''; + if ($type === 'use') { + $errorPrefix = 'Use'; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + // The open bracket should be the last thing on the line. + if ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openBracket]['line']) { + $error = 'The first parameter of a multi-line '.$type.' declaration must be on the line after the opening bracket'; + $fix = $phpcsFile->addFixableError($error, $next, $errorPrefix.'FirstParamSpacing'); + if ($fix === true) { + if ($tokens[$next]['line'] === $tokens[$openBracket]['line']) { + $phpcsFile->fixer->addNewline($openBracket); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($x = $openBracket; $x < $next; $x++) { + if ($tokens[$x]['line'] === $tokens[$openBracket]['line']) { + continue; + } + + if ($tokens[$x]['line'] === $tokens[$next]['line']) { + break; + } + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + }//end if + + // Each line between the brackets should contain a single parameter. + $lastComma = null; + for ($i = ($openBracket + 1); $i < $closeBracket; $i++) { + // Skip brackets, like arrays, as they can contain commas. + if (isset($tokens[$i]['bracket_opener']) === true) { + $i = $tokens[$i]['bracket_closer']; + continue; + } + + if (isset($tokens[$i]['parenthesis_opener']) === true) { + $i = $tokens[$i]['parenthesis_closer']; + continue; + } + + if ($tokens[$i]['code'] !== T_COMMA) { + continue; + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$i]['line']) { + $error = 'Multi-line '.$type.' declarations must define one parameter per line'; + $fix = $phpcsFile->addFixableError($error, $next, $errorPrefix.'OneParamPerLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($i); + } + } + }//end for + + }//end processBracket() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidFunctionNameSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidFunctionNameSniff.php new file mode 100644 index 00000000..878035e6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidFunctionNameSniff.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidFunctionNameSniff as PEARValidFunctionNameSniff; +use PHP_CodeSniffer\Util\Common; + +class ValidFunctionNameSniff extends PEARValidFunctionNameSniff +{ + + + /** + * Processes the tokens outside the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if ($functionName === null) { + return; + } + + $errorData = [$functionName]; + + // Does this function claim to be magical? + if (preg_match('|^__[^_]|', $functionName) !== 0) { + $error = 'Function name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'DoubleUnderscore', $errorData); + + $functionName = ltrim($functionName, '_'); + } + + if (Common::isCamelCaps($functionName, false, true, false) === false) { + $error = 'Function name "%s" is not in camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + } + + }//end processTokenOutsideScope() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidVariableNameSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidVariableNameSniff.php new file mode 100644 index 00000000..5c3a7493 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -0,0 +1,190 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Tokens; + +class ValidVariableNameSniff extends AbstractVariableSniff +{ + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $varName = ltrim($tokens[$stackPtr]['content'], '$'); + + // If it's a php reserved var, then its ok. + if (isset($this->phpReservedVars[$varName]) === true) { + return; + } + + $objOperator = $phpcsFile->findNext([T_WHITESPACE], ($stackPtr + 1), null, true); + if ($tokens[$objOperator]['code'] === T_OBJECT_OPERATOR + || $tokens[$objOperator]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + // Check to see if we are using a variable from an object. + $var = $phpcsFile->findNext([T_WHITESPACE], ($objOperator + 1), null, true); + if ($tokens[$var]['code'] === T_STRING) { + $bracket = $phpcsFile->findNext([T_WHITESPACE], ($var + 1), null, true); + if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) { + $objVarName = $tokens[$var]['content']; + + // There is no way for us to know if the var is public or + // private, so we have to ignore a leading underscore if there is + // one and just check the main part of the variable name. + $originalVarName = $objVarName; + if (substr($objVarName, 0, 1) === '_') { + $objVarName = substr($objVarName, 1); + } + + if (Common::isCamelCaps($objVarName, false, true, false) === false) { + $error = 'Member variable "%s" is not in valid camel caps format'; + $data = [$originalVarName]; + $phpcsFile->addError($error, $var, 'MemberNotCamelCaps', $data); + } + }//end if + }//end if + }//end if + + $objOperator = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$objOperator]['code'] === T_DOUBLE_COLON) { + // The variable lives within a class, and is referenced like + // this: MyClass::$_variable, so we don't know its scope. + $objVarName = $varName; + if (substr($objVarName, 0, 1) === '_') { + $objVarName = substr($objVarName, 1); + } + + if (Common::isCamelCaps($objVarName, false, true, false) === false) { + $error = 'Member variable "%s" is not in valid camel caps format'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addError($error, $stackPtr, 'MemberNotCamelCaps', $data); + } + + return; + } + + // There is no way for us to know if the var is public or private, + // so we have to ignore a leading underscore if there is one and just + // check the main part of the variable name. + $originalVarName = $varName; + if (substr($varName, 0, 1) === '_') { + $inClass = $phpcsFile->hasCondition($stackPtr, Tokens::$ooScopeTokens); + if ($inClass === true) { + $varName = substr($varName, 1); + } + } + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$originalVarName]; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data); + } + + }//end processVariable() + + + /** + * Processes class member variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $varName = ltrim($tokens[$stackPtr]['content'], '$'); + $memberProps = $phpcsFile->getMemberProperties($stackPtr); + if (empty($memberProps) === true) { + // Couldn't get any info about this variable, which + // generally means it is invalid or possibly has a parse + // error. Any errors will be reported by the core, so + // we can ignore it. + return; + } + + $public = ($memberProps['scope'] !== 'private'); + $errorData = [$varName]; + + if ($public === true) { + if (substr($varName, 0, 1) === '_') { + $error = '%s member variable "%s" must not contain a leading underscore'; + $data = [ + ucfirst($memberProps['scope']), + $errorData[0], + ]; + $phpcsFile->addError($error, $stackPtr, 'PublicHasUnderscore', $data); + } + } else { + if (substr($varName, 0, 1) !== '_') { + $error = 'Private member variable "%s" must contain a leading underscore'; + $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $errorData); + } + } + + // Remove a potential underscore prefix for testing CamelCaps. + $varName = ltrim($varName, '_'); + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Member variable "%s" is not in valid camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'MemberNotCamelCaps', $errorData); + } + + }//end processMemberVar() + + + /** + * Processes the variable found within a double quoted string. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the double quoted + * string. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (preg_match_all('|[^\\\]\${?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)|', $tokens[$stackPtr]['content'], $matches) !== 0) { + foreach ($matches[1] as $varName) { + // If it's a php reserved var, then its ok. + if (isset($this->phpReservedVars[$varName]) === true) { + continue; + } + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'StringNotCamelCaps', $data); + } + } + } + + }//end processVariableInString() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/DisallowObjectStringIndexSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/DisallowObjectStringIndexSniff.php new file mode 100644 index 00000000..c324e205 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/DisallowObjectStringIndexSniff.php @@ -0,0 +1,85 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Objects; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowObjectStringIndexSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_SQUARE_BRACKET]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check if the next non whitespace token is a string. + $index = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$index]['code'] !== T_CONSTANT_ENCAPSED_STRING) { + return; + } + + // Make sure it is the only thing in the square brackets. + $next = $phpcsFile->findNext(T_WHITESPACE, ($index + 1), null, true); + if ($tokens[$next]['code'] !== T_CLOSE_SQUARE_BRACKET) { + return; + } + + // Allow indexes that have dots in them because we can't write + // them in dot notation. + $content = trim($tokens[$index]['content'], '"\' '); + if (strpos($content, '.') !== false) { + return; + } + + // Also ignore reserved words. + if ($content === 'super') { + return; + } + + // Token before the opening square bracket cannot be a var name. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_STRING) { + $error = 'Object indexes must be written in dot notation'; + $phpcsFile->addError($error, $prev, 'Found'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php new file mode 100644 index 00000000..84facf05 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php @@ -0,0 +1,85 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Objects; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ObjectInstantiationSniff implements Sniff +{ + + + /** + * Registers the token types that this sniff wishes to listen to. + * + * @return array + */ + public function register() + { + return [T_NEW]; + + }//end register() + + + /** + * Process the tokens that this sniff is listening for. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $allowedTokens = Tokens::$emptyTokens; + $allowedTokens[] = T_BITWISE_AND; + + $prev = $phpcsFile->findPrevious($allowedTokens, ($stackPtr - 1), null, true); + + $allowedTokens = [ + T_EQUAL => T_EQUAL, + T_COALESCE_EQUAL => T_COALESCE_EQUAL, + T_DOUBLE_ARROW => T_DOUBLE_ARROW, + T_FN_ARROW => T_FN_ARROW, + T_MATCH_ARROW => T_MATCH_ARROW, + T_THROW => T_THROW, + T_RETURN => T_RETURN, + ]; + + if (isset($allowedTokens[$tokens[$prev]['code']]) === true) { + return; + } + + $ternaryLikeTokens = [ + T_COALESCE => true, + T_INLINE_THEN => true, + T_INLINE_ELSE => true, + ]; + + // For ternary like tokens, walk a little further back to see if it is preceded by + // one of the allowed tokens (within the same statement). + if (isset($ternaryLikeTokens[$tokens[$prev]['code']]) === true) { + $hasAllowedBefore = $phpcsFile->findPrevious($allowedTokens, ($prev - 1), null, false, null, true); + if ($hasAllowedBefore !== false) { + return; + } + } + + $error = 'New objects must be assigned to a variable'; + $phpcsFile->addError($error, $stackPtr, 'NotAssigned'); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectMemberCommaSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectMemberCommaSniff.php new file mode 100644 index 00000000..787d3fc8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectMemberCommaSniff.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Objects; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ObjectMemberCommaSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Registers the token types that this sniff wishes to listen to. + * + * @return array + */ + public function register() + { + return [T_CLOSE_OBJECT]; + + }//end register() + + + /** + * Process the tokens that this sniff is listening for. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_COMMA) { + $error = 'Last member of object must not be followed by a comma'; + $fix = $phpcsFile->addFixableError($error, $prev, 'Found'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($prev, ''); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ComparisonOperatorUsageSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ComparisonOperatorUsageSniff.php new file mode 100644 index 00000000..85e9825f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ComparisonOperatorUsageSniff.php @@ -0,0 +1,235 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Operators; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ComparisonOperatorUsageSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * A list of valid comparison operators. + * + * @var array + */ + private static $validOps = [ + T_IS_IDENTICAL => true, + T_IS_NOT_IDENTICAL => true, + T_LESS_THAN => true, + T_GREATER_THAN => true, + T_IS_GREATER_OR_EQUAL => true, + T_IS_SMALLER_OR_EQUAL => true, + T_INSTANCEOF => true, + ]; + + /** + * A list of invalid operators with their alternatives. + * + * @var array + */ + private static $invalidOps = [ + 'PHP' => [ + T_IS_EQUAL => '===', + T_IS_NOT_EQUAL => '!==', + T_BOOLEAN_NOT => '=== FALSE', + ], + 'JS' => [ + T_IS_EQUAL => '===', + T_IS_NOT_EQUAL => '!==', + ], + ]; + + + /** + * Registers the token types that this sniff wishes to listen to. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_ELSEIF, + T_INLINE_THEN, + T_WHILE, + T_FOR, + ]; + + }//end register() + + + /** + * Process the tokens that this sniff is listening for. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where the token + * was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenizer = $phpcsFile->tokenizerType; + + if ($tokens[$stackPtr]['code'] === T_INLINE_THEN) { + $end = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$end]['code'] !== T_CLOSE_PARENTHESIS) { + // This inline IF statement does not have its condition + // bracketed, so we need to guess where it starts. + for ($i = ($end - 1); $i >= 0; $i--) { + if ($tokens[$i]['code'] === T_SEMICOLON) { + // Stop here as we assume it is the end + // of the previous statement. + break; + } else if ($tokens[$i]['code'] === T_OPEN_TAG) { + // Stop here as this is the start of the file. + break; + } else if ($tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET) { + // Stop if this is the closing brace of + // a code block. + if (isset($tokens[$i]['scope_opener']) === true) { + break; + } + } else if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) { + // Stop if this is the opening brace of + // a code block. + if (isset($tokens[$i]['scope_closer']) === true) { + break; + } + } else if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) { + // Stop if this is the start of a pair of + // parentheses that surrounds the inline + // IF statement. + if (isset($tokens[$i]['parenthesis_closer']) === true + && $tokens[$i]['parenthesis_closer'] >= $stackPtr + ) { + break; + } + }//end if + }//end for + + $start = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + } else { + if (isset($tokens[$end]['parenthesis_opener']) === false) { + return; + } + + $start = $tokens[$end]['parenthesis_opener']; + }//end if + } else if ($tokens[$stackPtr]['code'] === T_FOR) { + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false) { + return; + } + + $openingBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closingBracket = $tokens[$stackPtr]['parenthesis_closer']; + + $start = $phpcsFile->findNext(T_SEMICOLON, $openingBracket, $closingBracket); + $end = $phpcsFile->findNext(T_SEMICOLON, ($start + 1), $closingBracket); + if ($start === false || $end === false) { + return; + } + } else { + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false) { + return; + } + + $start = $tokens[$stackPtr]['parenthesis_opener']; + $end = $tokens[$stackPtr]['parenthesis_closer']; + }//end if + + $requiredOps = 0; + $foundOps = 0; + $foundBooleans = 0; + + $lastNonEmpty = $start; + + for ($i = $start; $i <= $end; $i++) { + $type = $tokens[$i]['code']; + if (isset(self::$invalidOps[$tokenizer][$type]) === true) { + $error = 'Operator %s prohibited; use %s instead'; + $data = [ + $tokens[$i]['content'], + self::$invalidOps[$tokenizer][$type], + ]; + $phpcsFile->addError($error, $i, 'NotAllowed', $data); + $foundOps++; + } else if (isset(self::$validOps[$type]) === true) { + $foundOps++; + } + + if ($type === T_OPEN_PARENTHESIS + && isset($tokens[$i]['parenthesis_closer']) === true + && isset(Tokens::$functionNameTokens[$tokens[$lastNonEmpty]['code']]) === true + ) { + $i = $tokens[$i]['parenthesis_closer']; + $lastNonEmpty = $i; + continue; + } + + if ($tokens[$i]['code'] === T_TRUE || $tokens[$i]['code'] === T_FALSE) { + $foundBooleans++; + } + + if ($phpcsFile->tokenizerType !== 'JS' + && ($tokens[$i]['code'] === T_BOOLEAN_AND + || $tokens[$i]['code'] === T_BOOLEAN_OR) + ) { + $requiredOps++; + + // When the instanceof operator is used with another operator + // like ===, you can get more ops than are required. + if ($foundOps > $requiredOps) { + $foundOps = $requiredOps; + } + + // If we get to here and we have not found the right number of + // comparison operators, then we must have had an implicit + // true operation i.e., if ($a) instead of the required + // if ($a === true), so let's add an error. + if ($requiredOps !== $foundOps) { + $error = 'Implicit true comparisons prohibited; use === TRUE instead'; + $phpcsFile->addError($error, $stackPtr, 'ImplicitTrue'); + $foundOps++; + } + } + + if (isset(Tokens::$emptyTokens[$type]) === false) { + $lastNonEmpty = $i; + } + }//end for + + $requiredOps++; + + if ($phpcsFile->tokenizerType !== 'JS' + && $foundOps < $requiredOps + && ($requiredOps !== $foundBooleans) + ) { + $error = 'Implicit true comparisons prohibited; use === TRUE instead'; + $phpcsFile->addError($error, $stackPtr, 'ImplicitTrue'); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/IncrementDecrementUsageSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/IncrementDecrementUsageSniff.php new file mode 100644 index 00000000..cb377845 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/IncrementDecrementUsageSniff.php @@ -0,0 +1,225 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Operators; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class IncrementDecrementUsageSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_EQUAL, + T_PLUS_EQUAL, + T_MINUS_EQUAL, + T_INC, + T_DEC, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_INC || $tokens[$stackPtr]['code'] === T_DEC) { + $this->processIncDec($phpcsFile, $stackPtr); + } else { + $this->processAssignment($phpcsFile, $stackPtr); + } + + }//end process() + + + /** + * Checks to ensure increment and decrement operators are not confusing. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + protected function processIncDec($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Work out where the variable is so we know where to + // start looking for other operators. + if ($tokens[($stackPtr - 1)]['code'] === T_VARIABLE + || ($tokens[($stackPtr - 1)]['code'] === T_STRING + && ($tokens[($stackPtr - 2)]['code'] === T_OBJECT_OPERATOR + || $tokens[($stackPtr - 2)]['code'] === T_NULLSAFE_OBJECT_OPERATOR)) + ) { + $start = ($stackPtr + 1); + } else { + $start = ($stackPtr + 2); + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $start, null, true); + if ($next === false) { + return; + } + + if (isset(Tokens::$arithmeticTokens[$tokens[$next]['code']]) === true) { + $error = 'Increment and decrement operators cannot be used in an arithmetic operation'; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed'); + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($start - 3), null, true); + if ($prev === false) { + return; + } + + // Check if this is in a string concat. + if ($tokens[$next]['code'] === T_STRING_CONCAT || $tokens[$prev]['code'] === T_STRING_CONCAT) { + $error = 'Increment and decrement operators must be bracketed when used in string concatenation'; + $phpcsFile->addError($error, $stackPtr, 'NoBrackets'); + } + + }//end processIncDec() + + + /** + * Checks to ensure increment and decrement operators are used. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + protected function processAssignment($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $assignedVar = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + // Not an assignment, return. + if ($tokens[$assignedVar]['code'] !== T_VARIABLE) { + return; + } + + $statementEnd = $phpcsFile->findNext([T_SEMICOLON, T_CLOSE_PARENTHESIS, T_CLOSE_SQUARE_BRACKET, T_CLOSE_CURLY_BRACKET], $stackPtr); + + // If there is anything other than variables, numbers, spaces or operators we need to return. + $noiseTokens = $phpcsFile->findNext([T_LNUMBER, T_VARIABLE, T_WHITESPACE, T_PLUS, T_MINUS, T_OPEN_PARENTHESIS], ($stackPtr + 1), $statementEnd, true); + + if ($noiseTokens !== false) { + return; + } + + // If we are already using += or -=, we need to ignore + // the statement if a variable is being used. + if ($tokens[$stackPtr]['code'] !== T_EQUAL) { + $nextVar = $phpcsFile->findNext(T_VARIABLE, ($stackPtr + 1), $statementEnd); + if ($nextVar !== false) { + return; + } + } + + if ($tokens[$stackPtr]['code'] === T_EQUAL) { + $nextVar = ($stackPtr + 1); + $previousVariable = ($stackPtr + 1); + $variableCount = 0; + while (($nextVar = $phpcsFile->findNext(T_VARIABLE, ($nextVar + 1), $statementEnd)) !== false) { + $previousVariable = $nextVar; + $variableCount++; + } + + if ($variableCount !== 1) { + return; + } + + $nextVar = $previousVariable; + if ($tokens[$nextVar]['content'] !== $tokens[$assignedVar]['content']) { + return; + } + } + + // We have only one variable, and it's the same as what is being assigned, + // so we need to check what is being added or subtracted. + $nextNumber = ($stackPtr + 1); + $previousNumber = ($stackPtr + 1); + $numberCount = 0; + while (($nextNumber = $phpcsFile->findNext([T_LNUMBER], ($nextNumber + 1), $statementEnd, false)) !== false) { + $previousNumber = $nextNumber; + $numberCount++; + } + + if ($numberCount !== 1) { + return; + } + + $nextNumber = $previousNumber; + if ($tokens[$nextNumber]['content'] === '1') { + if ($tokens[$stackPtr]['code'] === T_EQUAL) { + $opToken = $phpcsFile->findNext([T_PLUS, T_MINUS], ($nextVar + 1), $statementEnd); + if ($opToken === false) { + // Operator was before the variable, like: + // $var = 1 + $var; + // So we ignore it. + return; + } + + $operator = $tokens[$opToken]['content']; + } else { + $operator = substr($tokens[$stackPtr]['content'], 0, 1); + } + + // If we are adding or subtracting negative value, the operator + // needs to be reversed. + if ($tokens[$stackPtr]['code'] !== T_EQUAL) { + $negative = $phpcsFile->findPrevious(T_MINUS, ($nextNumber - 1), $stackPtr); + if ($negative !== false) { + if ($operator === '+') { + $operator = '-'; + } else { + $operator = '+'; + } + } + } + + $expected = $operator.$operator.$tokens[$assignedVar]['content']; + $found = $phpcsFile->getTokensAsString($assignedVar, ($statementEnd - $assignedVar + 1)); + + if ($operator === '+') { + $error = 'Increment'; + } else { + $error = 'Decrement'; + } + + $error .= " operators should be used where possible; found \"$found\" but expected \"$expected\""; + $phpcsFile->addError($error, $stackPtr, 'Found'); + }//end if + + }//end processAssignment() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php new file mode 100644 index 00000000..f9ea6202 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php @@ -0,0 +1,67 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Operators; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ValidLogicalOperatorsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_LOGICAL_AND, + T_LOGICAL_OR, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $replacements = [ + 'and' => '&&', + 'or' => '||', + ]; + + $operator = strtolower($tokens[$stackPtr]['content']); + if (isset($replacements[$operator]) === false) { + return; + } + + $error = 'Logical operator "%s" is prohibited; use "%s" instead'; + $data = [ + $operator, + $replacements[$operator], + ]; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed', $data); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php new file mode 100644 index 00000000..04d06338 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php @@ -0,0 +1,288 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Exceptions\TokenizerException; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class CommentedOutCodeSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'CSS', + ]; + + /** + * If a comment is more than $maxPercentage% code, a warning will be shown. + * + * @var integer + */ + public $maxPercentage = 35; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_COMMENT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore comments at the end of code blocks. + if (substr($tokens[$stackPtr]['content'], 0, 6) === '//end ') { + return; + } + + $content = ''; + $lastLineSeen = $tokens[$stackPtr]['line']; + $commentStyle = 'line'; + if (strpos($tokens[$stackPtr]['content'], '/*') === 0) { + $commentStyle = 'block'; + } + + $lastCommentBlockToken = $stackPtr; + for ($i = $stackPtr; $i < $phpcsFile->numTokens; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) { + break; + } + + if ($tokens[$i]['code'] === T_WHITESPACE) { + continue; + } + + if (isset(Tokens::$phpcsCommentTokens[$tokens[$i]['code']]) === true) { + $lastLineSeen = $tokens[$i]['line']; + continue; + } + + if ($commentStyle === 'line' + && ($lastLineSeen + 1) <= $tokens[$i]['line'] + && strpos($tokens[$i]['content'], '/*') === 0 + ) { + // First non-whitespace token on a new line is start of a different style comment. + break; + } + + if ($commentStyle === 'line' + && ($lastLineSeen + 1) < $tokens[$i]['line'] + ) { + // Blank line breaks a '//' style comment block. + break; + } + + /* + Trim as much off the comment as possible so we don't + have additional whitespace tokens or comment tokens + */ + + $tokenContent = trim($tokens[$i]['content']); + $break = false; + + if ($commentStyle === 'line') { + if (substr($tokenContent, 0, 2) === '//') { + $tokenContent = substr($tokenContent, 2); + } + + if (substr($tokenContent, 0, 1) === '#') { + $tokenContent = substr($tokenContent, 1); + } + } else { + if (substr($tokenContent, 0, 3) === '/**') { + $tokenContent = substr($tokenContent, 3); + } + + if (substr($tokenContent, 0, 2) === '/*') { + $tokenContent = substr($tokenContent, 2); + } + + if (substr($tokenContent, -2) === '*/') { + $tokenContent = substr($tokenContent, 0, -2); + $break = true; + } + + if (substr($tokenContent, 0, 1) === '*') { + $tokenContent = substr($tokenContent, 1); + } + }//end if + + $content .= $tokenContent.$phpcsFile->eolChar; + $lastLineSeen = $tokens[$i]['line']; + + $lastCommentBlockToken = $i; + + if ($break === true) { + // Closer of a block comment found. + break; + } + }//end for + + // Ignore typical warning suppression annotations from other tools. + if (preg_match('`^\s*@[A-Za-z()\._-]+\s*$`', $content) === 1) { + return ($lastCommentBlockToken + 1); + } + + // Quite a few comments use multiple dashes, equals signs etc + // to frame comments and licence headers. + $content = preg_replace('/[-=#*]{2,}/', '-', $content); + + // Random numbers sitting inside the content can throw parse errors + // for invalid literals in PHP7+, so strip those. + $content = preg_replace('/\d+/', '', $content); + + $content = trim($content); + + if ($content === '') { + return ($lastCommentBlockToken + 1); + } + + if ($phpcsFile->tokenizerType === 'PHP') { + $content = ''; + } + + // Because we are not really parsing code, the tokenizer can throw all sorts + // of errors that don't mean anything, so ignore them. + $oldErrors = ini_get('error_reporting'); + ini_set('error_reporting', 0); + try { + $tokenizerClass = get_class($phpcsFile->tokenizer); + $tokenizer = new $tokenizerClass($content, $phpcsFile->config, $phpcsFile->eolChar); + $stringTokens = $tokenizer->getTokens(); + } catch (TokenizerException $e) { + // We couldn't check the comment, so ignore it. + ini_set('error_reporting', $oldErrors); + return ($lastCommentBlockToken + 1); + } + + ini_set('error_reporting', $oldErrors); + + $numTokens = count($stringTokens); + + /* + We know what the first two and last two tokens should be + (because we put them there) so ignore this comment if those + tokens were not parsed correctly. It obviously means this is not + valid code. + */ + + // First token is always the opening tag. + if ($stringTokens[0]['code'] !== T_OPEN_TAG) { + return ($lastCommentBlockToken + 1); + } else { + array_shift($stringTokens); + --$numTokens; + } + + // Last token is always the closing tag, unless something went wrong. + if (isset($stringTokens[($numTokens - 1)]) === false + || $stringTokens[($numTokens - 1)]['code'] !== T_CLOSE_TAG + ) { + return ($lastCommentBlockToken + 1); + } else { + array_pop($stringTokens); + --$numTokens; + } + + // Second last token is always whitespace or a comment, depending + // on the code inside the comment. + if ($phpcsFile->tokenizerType === 'PHP') { + if (isset(Tokens::$emptyTokens[$stringTokens[($numTokens - 1)]['code']]) === false) { + return ($lastCommentBlockToken + 1); + } + + if ($stringTokens[($numTokens - 1)]['code'] === T_WHITESPACE) { + array_pop($stringTokens); + --$numTokens; + } + } + + $emptyTokens = [ + T_WHITESPACE => true, + T_STRING => true, + T_STRING_CONCAT => true, + T_ENCAPSED_AND_WHITESPACE => true, + T_NONE => true, + T_COMMENT => true, + ]; + $emptyTokens += Tokens::$phpcsCommentTokens; + + $numComment = 0; + $numPossible = 0; + $numCode = 0; + $numNonWhitespace = 0; + + for ($i = 0; $i < $numTokens; $i++) { + if (isset($emptyTokens[$stringTokens[$i]['code']]) === true) { + // Looks like comment. + $numComment++; + } else if (isset(Tokens::$comparisonTokens[$stringTokens[$i]['code']]) === true + || isset(Tokens::$arithmeticTokens[$stringTokens[$i]['code']]) === true + || $stringTokens[$i]['code'] === T_GOTO_LABEL + ) { + // Commented out HTML/XML and other docs contain a lot of these + // characters, so it is best to not use them directly. + $numPossible++; + } else { + // Looks like code. + $numCode++; + } + + if ($stringTokens[$i]['code'] !== T_WHITESPACE) { + ++$numNonWhitespace; + } + } + + // Ignore comments with only two or less non-whitespace tokens. + // Sample size too small for a reliably determination. + if ($numNonWhitespace <= 2) { + return ($lastCommentBlockToken + 1); + } + + $percentCode = ceil((($numCode / $numTokens) * 100)); + if ($percentCode > $this->maxPercentage) { + // Just in case. + $percentCode = min(100, $percentCode); + + $error = 'This comment is %s%% valid code; is this commented out code?'; + $data = [$percentCode]; + $phpcsFile->addWarning($error, $stackPtr, 'Found', $data); + } + + return ($lastCommentBlockToken + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowBooleanStatementSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowBooleanStatementSniff.php new file mode 100644 index 00000000..9d8077f5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowBooleanStatementSniff.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowBooleanStatementSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$booleanOperators; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + foreach ($tokens[$stackPtr]['nested_parenthesis'] as $open => $close) { + if (isset($tokens[$open]['parenthesis_owner']) === true) { + // Any owner means we are not just a simple statement. + return; + } + } + } + + $error = 'Boolean operators are not allowed outside of control structure conditions'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowComparisonAssignmentSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowComparisonAssignmentSniff.php new file mode 100644 index 00000000..7c7e2246 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowComparisonAssignmentSniff.php @@ -0,0 +1,111 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowComparisonAssignmentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EQUAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore default value assignments in function definitions. + $function = $phpcsFile->findPrevious(T_FUNCTION, ($stackPtr - 1), null, false, null, true); + if ($function !== false) { + $opener = $tokens[$function]['parenthesis_opener']; + $closer = $tokens[$function]['parenthesis_closer']; + if ($opener < $stackPtr && $closer > $stackPtr) { + return; + } + } + + // Ignore values in array definitions. + $array = $phpcsFile->findNext( + T_ARRAY, + ($stackPtr + 1), + null, + false, + null, + true + ); + + if ($array !== false) { + return; + } + + // Ignore function calls. + $ignore = [ + T_NULLSAFE_OBJECT_OPERATOR, + T_OBJECT_OPERATOR, + T_STRING, + T_VARIABLE, + T_WHITESPACE, + ]; + + $next = $phpcsFile->findNext($ignore, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_CLOSURE + || ($tokens[$next]['code'] === T_OPEN_PARENTHESIS + && $tokens[($next - 1)]['code'] === T_STRING) + ) { + // Code will look like: $var = myFunction( + // and will be ignored. + return; + } + + $endStatement = $phpcsFile->findEndOfStatement($stackPtr); + for ($i = ($stackPtr + 1); $i < $endStatement; $i++) { + if ((isset(Tokens::$comparisonTokens[$tokens[$i]['code']]) === true + && $tokens[$i]['code'] !== T_COALESCE) + || $tokens[$i]['code'] === T_INLINE_THEN + ) { + $error = 'The value of a comparison must not be assigned to a variable'; + $phpcsFile->addError($error, $stackPtr, 'AssignedComparison'); + break; + } + + if (isset(Tokens::$booleanOperators[$tokens[$i]['code']]) === true + || $tokens[$i]['code'] === T_BOOLEAN_NOT + ) { + $error = 'The value of a boolean operation must not be assigned to a variable'; + $phpcsFile->addError($error, $stackPtr, 'AssignedBool'); + break; + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowInlineIfSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowInlineIfSniff.php new file mode 100644 index 00000000..60b0c370 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowInlineIfSniff.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowInlineIfSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INLINE_THEN]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $phpcsFile->addError('Inline IF statements are not allowed', $stackPtr, 'Found'); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php new file mode 100644 index 00000000..4448d244 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php @@ -0,0 +1,186 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowMultipleAssignmentsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EQUAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore default value assignments in function definitions. + $function = $phpcsFile->findPrevious([T_FUNCTION, T_CLOSURE, T_FN], ($stackPtr - 1), null, false, null, true); + if ($function !== false) { + $opener = $tokens[$function]['parenthesis_opener']; + $closer = $tokens[$function]['parenthesis_closer']; + if ($opener < $stackPtr && $closer > $stackPtr) { + return; + } + } + + // Ignore assignments in WHILE loop conditions. + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nested = $tokens[$stackPtr]['nested_parenthesis']; + foreach ($nested as $opener => $closer) { + if (isset($tokens[$opener]['parenthesis_owner']) === true + && $tokens[$tokens[$opener]['parenthesis_owner']]['code'] === T_WHILE + ) { + return; + } + } + } + + // Ignore member var definitions. + if (empty($tokens[$stackPtr]['conditions']) === false) { + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if (isset(Tokens::$ooScopeTokens[$tokens[$deepestScope]['code']]) === true) { + return; + } + } + + /* + The general rule is: + Find an equal sign and go backwards along the line. If you hit an + end bracket, skip to the opening bracket. When you find a variable, + stop. That variable must be the first non-empty token on the line + or in the statement. If not, throw an error. + */ + + for ($varToken = ($stackPtr - 1); $varToken >= 0; $varToken--) { + if (in_array($tokens[$varToken]['code'], [T_SEMICOLON, T_OPEN_CURLY_BRACKET], true) === true) { + // We've reached the next statement, so we + // didn't find a variable. + return; + } + + // Skip brackets. + if (isset($tokens[$varToken]['parenthesis_opener']) === true && $tokens[$varToken]['parenthesis_opener'] < $varToken) { + $varToken = $tokens[$varToken]['parenthesis_opener']; + continue; + } + + if (isset($tokens[$varToken]['bracket_opener']) === true) { + $varToken = $tokens[$varToken]['bracket_opener']; + continue; + } + + if ($tokens[$varToken]['code'] === T_VARIABLE) { + // We found our variable. + break; + } + }//end for + + if ($varToken <= 0) { + // Didn't find a variable. + return; + } + + $start = $phpcsFile->findStartOfStatement($varToken); + + $allowed = Tokens::$emptyTokens; + + $allowed[T_STRING] = T_STRING; + $allowed[T_NS_SEPARATOR] = T_NS_SEPARATOR; + $allowed[T_DOUBLE_COLON] = T_DOUBLE_COLON; + $allowed[T_OBJECT_OPERATOR] = T_OBJECT_OPERATOR; + $allowed[T_ASPERAND] = T_ASPERAND; + $allowed[T_DOLLAR] = T_DOLLAR; + $allowed[T_SELF] = T_SELF; + $allowed[T_PARENT] = T_PARENT; + $allowed[T_STATIC] = T_STATIC; + + $varToken = $phpcsFile->findPrevious($allowed, ($varToken - 1), null, true); + + if ($varToken < $start + && $tokens[$varToken]['code'] !== T_OPEN_PARENTHESIS + && $tokens[$varToken]['code'] !== T_OPEN_SQUARE_BRACKET + ) { + $varToken = $start; + } + + // Ignore the first part of FOR loops as we are allowed to + // assign variables there even though the variable is not the + // first thing on the line. + if ($tokens[$varToken]['code'] === T_OPEN_PARENTHESIS && isset($tokens[$varToken]['parenthesis_owner']) === true) { + $owner = $tokens[$varToken]['parenthesis_owner']; + if ($tokens[$owner]['code'] === T_FOR) { + return; + } + } + + if ($tokens[$varToken]['code'] === T_VARIABLE + || $tokens[$varToken]['code'] === T_OPEN_TAG + || $tokens[$varToken]['code'] === T_GOTO_LABEL + || $tokens[$varToken]['code'] === T_INLINE_THEN + || $tokens[$varToken]['code'] === T_INLINE_ELSE + || $tokens[$varToken]['code'] === T_SEMICOLON + || $tokens[$varToken]['code'] === T_CLOSE_PARENTHESIS + || isset($allowed[$tokens[$varToken]['code']]) === true + ) { + return; + } + + $error = 'Assignments must be the first block of code on a line'; + $errorCode = 'Found'; + + if (isset($nested) === true) { + $controlStructures = [ + T_IF => T_IF, + T_ELSEIF => T_ELSEIF, + T_SWITCH => T_SWITCH, + T_CASE => T_CASE, + T_FOR => T_FOR, + T_MATCH => T_MATCH, + ]; + foreach ($nested as $opener => $closer) { + if (isset($tokens[$opener]['parenthesis_owner']) === true + && isset($controlStructures[$tokens[$tokens[$opener]['parenthesis_owner']]['code']]) === true + ) { + $errorCode .= 'InControlStructure'; + break; + } + } + } + + $phpcsFile->addError($error, $stackPtr, $errorCode); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowSizeFunctionsInLoopsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowSizeFunctionsInLoopsSniff.php new file mode 100644 index 00000000..a0f1161c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowSizeFunctionsInLoopsSniff.php @@ -0,0 +1,116 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowSizeFunctionsInLoopsSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * An array of functions we don't want in the condition of loops. + * + * @var array + */ + protected $forbiddenFunctions = [ + 'PHP' => [ + 'sizeof' => true, + 'strlen' => true, + 'count' => true, + ], + 'JS' => ['length' => true], + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_WHILE, + T_FOR, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenizer = $phpcsFile->tokenizerType; + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + + if ($tokens[$stackPtr]['code'] === T_FOR) { + // We only want to check the condition in FOR loops. + $start = $phpcsFile->findNext(T_SEMICOLON, ($openBracket + 1)); + $end = $phpcsFile->findPrevious(T_SEMICOLON, ($closeBracket - 1)); + } else { + $start = $openBracket; + $end = $closeBracket; + } + + for ($i = ($start + 1); $i < $end; $i++) { + if ($tokens[$i]['code'] === T_STRING + && isset($this->forbiddenFunctions[$tokenizer][$tokens[$i]['content']]) === true + ) { + $functionName = $tokens[$i]['content']; + if ($tokenizer === 'JS') { + // Needs to be in the form object.function to be valid. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), null, true); + if ($prev === false || $tokens[$prev]['code'] !== T_OBJECT_OPERATOR) { + continue; + } + + $functionName = 'object.'.$functionName; + } else { + // Make sure it isn't a member var. + if ($tokens[($i - 1)]['code'] === T_OBJECT_OPERATOR + || $tokens[($i - 1)]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + continue; + } + + $functionName .= '()'; + } + + $error = 'The use of %s inside a loop condition is not allowed; assign the return value to a variable and use the variable in the loop condition instead'; + $data = [$functionName]; + $phpcsFile->addError($error, $i, 'Found', $data); + }//end if + }//end for + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DiscouragedFunctionsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DiscouragedFunctionsSniff.php new file mode 100644 index 00000000..9f86a179 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DiscouragedFunctionsSniff.php @@ -0,0 +1,38 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\ForbiddenFunctionsSniff as GenericForbiddenFunctionsSniff; + +class DiscouragedFunctionsSniff extends GenericForbiddenFunctionsSniff +{ + + /** + * A list of forbidden functions with their alternatives. + * + * The value is NULL if no alternative exists. IE, the + * function should just not be used. + * + * @var array + */ + public $forbiddenFunctions = [ + 'error_log' => null, + 'print_r' => null, + 'var_dump' => null, + ]; + + /** + * If true, an error will be thrown; otherwise a warning. + * + * @var boolean + */ + public $error = false; + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php new file mode 100644 index 00000000..ef11aa6c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php @@ -0,0 +1,402 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmbeddedPhpSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If the close php tag is on the same line as the opening + // then we have an inline embedded PHP block. + $closeTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr); + if ($closeTag === false || $tokens[$stackPtr]['line'] !== $tokens[$closeTag]['line']) { + $this->validateMultilineEmbeddedPhp($phpcsFile, $stackPtr); + } else { + $this->validateInlineEmbeddedPhp($phpcsFile, $stackPtr); + } + + }//end process() + + + /** + * Validates embedded PHP that exists on multiple lines. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + private function validateMultilineEmbeddedPhp($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $prevTag = $phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)); + if ($prevTag === false) { + // This is the first open tag. + return; + } + + $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $closingTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr); + if ($closingTag !== false) { + $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($closingTag + 1), $phpcsFile->numTokens, true); + if ($nextContent === false) { + // Final closing tag. It will be handled elsewhere. + return; + } + + // We have an opening and a closing tag, that lie within other content. + if ($firstContent === $closingTag) { + $error = 'Empty embedded PHP tag found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Empty'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $stackPtr; $i <= $closingTag; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + } + }//end if + + if ($tokens[$firstContent]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Opening PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentAfterOpen'); + if ($fix === true) { + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $padding = (strlen($tokens[$first]['content']) - strlen(ltrim($tokens[$first]['content']))); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($stackPtr); + $phpcsFile->fixer->addContent($stackPtr, str_repeat(' ', $padding)); + $phpcsFile->fixer->endChangeset(); + } + } else { + // Check the indent of the first line, except if it is a scope closer. + if (isset($tokens[$firstContent]['scope_closer']) === false + || $tokens[$firstContent]['scope_closer'] !== $firstContent + ) { + // Check for a blank line at the top. + if ($tokens[$firstContent]['line'] > ($tokens[$stackPtr]['line'] + 1)) { + // Find a token on the blank line to throw the error on. + $i = $stackPtr; + do { + $i++; + } while ($tokens[$i]['line'] !== ($tokens[$stackPtr]['line'] + 1)); + + $error = 'Blank line found at start of embedded PHP content'; + $fix = $phpcsFile->addFixableError($error, $i, 'SpacingBefore'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $firstContent; $i++) { + if ($tokens[$i]['line'] === $tokens[$firstContent]['line'] + || $tokens[$i]['line'] === $tokens[$stackPtr]['line'] + ) { + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr); + if ($first === false) { + $first = $phpcsFile->findFirstOnLine(T_INLINE_HTML, $stackPtr); + $indent = (strlen($tokens[$first]['content']) - strlen(ltrim($tokens[$first]['content']))); + } else { + $indent = ($tokens[($first + 1)]['column'] - 1); + } + + $contentColumn = ($tokens[$firstContent]['column'] - 1); + if ($contentColumn !== $indent) { + $error = 'First line of embedded PHP code must be indented %s spaces; %s found'; + $data = [ + $indent, + $contentColumn, + ]; + $fix = $phpcsFile->addFixableError($error, $firstContent, 'Indent', $data); + if ($fix === true) { + $padding = str_repeat(' ', $indent); + if ($contentColumn === 0) { + $phpcsFile->fixer->addContentBefore($firstContent, $padding); + } else { + $phpcsFile->fixer->replaceToken(($firstContent - 1), $padding); + } + } + } + }//end if + }//end if + + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$lastContent]['line'] === $tokens[$stackPtr]['line'] + && trim($tokens[$lastContent]['content']) !== '' + ) { + $error = 'Opening PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentBeforeOpen'); + if ($fix === true) { + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr); + if ($first === false) { + $first = $phpcsFile->findFirstOnLine(T_INLINE_HTML, $stackPtr); + $padding = (strlen($tokens[$first]['content']) - strlen(ltrim($tokens[$first]['content']))); + } else { + $padding = ($tokens[($first + 1)]['column'] - 1); + } + + $phpcsFile->fixer->addContentBefore($stackPtr, $phpcsFile->eolChar.str_repeat(' ', $padding)); + } + } else { + // Find the first token on the first non-empty line we find. + for ($first = ($stackPtr - 1); $first > 0; $first--) { + if ($tokens[$first]['line'] === $tokens[$stackPtr]['line']) { + continue; + } else if (trim($tokens[$first]['content']) !== '') { + $first = $phpcsFile->findFirstOnLine([], $first, true); + break; + } + } + + $expected = 0; + if ($tokens[$first]['code'] === T_INLINE_HTML + && trim($tokens[$first]['content']) !== '' + ) { + $expected = (strlen($tokens[$first]['content']) - strlen(ltrim($tokens[$first]['content']))); + } else if ($tokens[$first]['code'] === T_WHITESPACE) { + $expected = ($tokens[($first + 1)]['column'] - 1); + } + + $expected += 4; + $found = ($tokens[$stackPtr]['column'] - 1); + if ($found > $expected) { + $error = 'Opening PHP tag indent incorrect; expected no more than %s spaces but found %s'; + $data = [ + $expected, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'OpenTagIndent', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), str_repeat(' ', $expected)); + } + } + }//end if + + if ($closingTag === false) { + return; + } + + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closingTag - 1), ($stackPtr + 1), true); + $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($closingTag + 1), null, true); + + if ($tokens[$lastContent]['line'] === $tokens[$closingTag]['line']) { + $error = 'Closing PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $closingTag, 'ContentBeforeEnd'); + if ($fix === true) { + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $closingTag, true); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore($closingTag, str_repeat(' ', ($tokens[$first]['column'] - 1))); + $phpcsFile->fixer->addNewlineBefore($closingTag); + $phpcsFile->fixer->endChangeset(); + } + } else if ($tokens[$nextContent]['line'] === $tokens[$closingTag]['line']) { + $error = 'Closing PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $closingTag, 'ContentAfterEnd'); + if ($fix === true) { + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $closingTag, true); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($closingTag); + $phpcsFile->fixer->addContent($closingTag, str_repeat(' ', ($tokens[$first]['column'] - 1))); + $phpcsFile->fixer->endChangeset(); + } + }//end if + + $next = $phpcsFile->findNext(T_OPEN_TAG, ($closingTag + 1)); + if ($next === false) { + return; + } + + // Check for a blank line at the bottom. + if ((isset($tokens[$lastContent]['scope_closer']) === false + || $tokens[$lastContent]['scope_closer'] !== $lastContent) + && $tokens[$lastContent]['line'] < ($tokens[$closingTag]['line'] - 1) + ) { + // Find a token on the blank line to throw the error on. + $i = $closingTag; + do { + $i--; + } while ($tokens[$i]['line'] !== ($tokens[$closingTag]['line'] - 1)); + + $error = 'Blank line found at end of embedded PHP content'; + $fix = $phpcsFile->addFixableError($error, $i, 'SpacingAfter'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($lastContent + 1); $i < $closingTag; $i++) { + if ($tokens[$i]['line'] === $tokens[$lastContent]['line'] + || $tokens[$i]['line'] === $tokens[$closingTag]['line'] + ) { + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + }//end validateMultilineEmbeddedPhp() + + + /** + * Validates embedded PHP that exists on one line. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + private function validateInlineEmbeddedPhp($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // We only want one line PHP sections, so return if the closing tag is + // on the next line. + $closeTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr, null, false); + if ($tokens[$stackPtr]['line'] !== $tokens[$closeTag]['line']) { + return; + } + + // Check that there is one, and only one space at the start of the statement. + $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), $closeTag, true); + + if ($firstContent === false) { + $error = 'Empty embedded PHP tag found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Empty'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $stackPtr; $i <= $closeTag; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + } + + // The open tag token always contains a single space after it. + $leadingSpace = 1; + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $leadingSpace = ($tokens[($stackPtr + 1)]['length'] + 1); + } + + if ($leadingSpace !== 1) { + $error = 'Expected 1 space after opening PHP tag; %s found'; + $data = [$leadingSpace]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterOpen', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($closeTag - 1), $stackPtr, true); + if ($prev !== $stackPtr) { + if ((isset($tokens[$prev]['scope_opener']) === false + || $tokens[$prev]['scope_opener'] !== $prev) + && (isset($tokens[$prev]['scope_closer']) === false + || $tokens[$prev]['scope_closer'] !== $prev) + && $tokens[$prev]['code'] !== T_SEMICOLON + ) { + $error = 'Inline PHP statement must end with a semicolon'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSemicolon'); + if ($fix === true) { + $phpcsFile->fixer->addContent($prev, ';'); + } + } else if ($tokens[$prev]['code'] === T_SEMICOLON) { + $statementCount = 1; + for ($i = ($stackPtr + 1); $i < $prev; $i++) { + if ($tokens[$i]['code'] === T_SEMICOLON) { + $statementCount++; + } + } + + if ($statementCount > 1) { + $error = 'Inline PHP statement must contain a single statement; %s found'; + $data = [$statementCount]; + $phpcsFile->addError($error, $stackPtr, 'MultipleStatements', $data); + } + } + }//end if + + $trailingSpace = 0; + if ($tokens[($closeTag - 1)]['code'] === T_WHITESPACE) { + $trailingSpace = $tokens[($closeTag - 1)]['length']; + } else if (($tokens[($closeTag - 1)]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[($closeTag - 1)]['code']]) === true) + && substr($tokens[($closeTag - 1)]['content'], -1) === ' ' + ) { + $trailingSpace = (strlen($tokens[($closeTag - 1)]['content']) - strlen(rtrim($tokens[($closeTag - 1)]['content']))); + } + + if ($trailingSpace !== 1) { + $error = 'Expected 1 space before closing PHP tag; %s found'; + $data = [$trailingSpace]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeClose', $data); + if ($fix === true) { + if ($trailingSpace === 0) { + $phpcsFile->fixer->addContentBefore($closeTag, ' '); + } else if ($tokens[($closeTag - 1)]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[($closeTag - 1)]['code']]) === true + ) { + $phpcsFile->fixer->replaceToken(($closeTag - 1), rtrim($tokens[($closeTag - 1)]['content']).' '); + } else { + $phpcsFile->fixer->replaceToken(($closeTag - 1), ' '); + } + } + } + + }//end validateInlineEmbeddedPhp() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EvalSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EvalSniff.php new file mode 100644 index 00000000..3162c14b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EvalSniff.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EvalSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EVAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $error = 'Use of eval() is discouraged'; + $phpcsFile->addWarning($error, $stackPtr, 'Discouraged'); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/GlobalKeywordSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/GlobalKeywordSniff.php new file mode 100644 index 00000000..024eff8a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/GlobalKeywordSniff.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class GlobalKeywordSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_GLOBAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextVar = $tokens[$phpcsFile->findNext([T_VARIABLE], $stackPtr)]; + $varName = str_replace('$', '', $nextVar['content']); + $error = 'Use of the "global" keyword is forbidden; use "$GLOBALS[\'%s\']" instead'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed', $data); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/HeredocSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/HeredocSniff.php new file mode 100644 index 00000000..67369cb2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/HeredocSniff.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class HeredocSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_START_HEREDOC, + T_START_NOWDOC, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $error = 'Use of heredoc and nowdoc syntax ("<<<") is not allowed; use standard strings or inline HTML instead'; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed'); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php new file mode 100644 index 00000000..4e3ee215 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php @@ -0,0 +1,68 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class InnerFunctionsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $function = $phpcsFile->getCondition($stackPtr, T_FUNCTION); + if ($function === false) { + // Not a nested function. + return; + } + + $class = $phpcsFile->getCondition($stackPtr, T_ANON_CLASS, false); + if ($class !== false && $class > $function) { + // Ignore methods in anon classes. + return; + } + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_EQUAL) { + // Ignore closures. + return; + } + + $error = 'The use of inner functions is forbidden'; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed'); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php new file mode 100644 index 00000000..519b7f6c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php @@ -0,0 +1,162 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LowercasePHPFunctionsSniff implements Sniff +{ + + /** + * String -> int hash map of all php built in function names + * + * @var array + */ + private $builtInFunctions; + + + /** + * Construct the LowercasePHPFunctionSniff + */ + public function __construct() + { + + $allFunctions = get_defined_functions(); + $this->builtInFunctions = array_flip($allFunctions['internal']); + + }//end __construct() + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_STRING]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $contentLc = strtolower($content); + if ($content === $contentLc) { + return; + } + + // Make sure it is an inbuilt PHP function. + // PHP_CodeSniffer can possibly include user defined functions + // through the use of vendor/autoload.php. + if (isset($this->builtInFunctions[$contentLc]) === false) { + return; + } + + // Make sure this is a function call or a use statement. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next === false) { + // Not a function call. + return; + } + + $ignore = Tokens::$emptyTokens; + $ignore[] = T_BITWISE_AND; + $prev = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); + $prevPrev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + + if ($tokens[$next]['code'] !== T_OPEN_PARENTHESIS) { + // Is this a use statement importing a PHP native function ? + if ($tokens[$next]['code'] !== T_NS_SEPARATOR + && $tokens[$prev]['code'] === T_STRING + && $tokens[$prev]['content'] === 'function' + && $prevPrev !== false + && $tokens[$prevPrev]['code'] === T_USE + ) { + $error = 'Use statements for PHP native functions must be lowercase; expected "%s" but found "%s"'; + $data = [ + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseStatementUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + } + + // No open parenthesis; not a "use function" statement nor a function call. + return; + }//end if + + if ($tokens[$prev]['code'] === T_FUNCTION) { + // Function declaration, not a function call. + return; + } + + if ($tokens[$prev]['code'] === T_NS_SEPARATOR) { + if ($prevPrev !== false + && ($tokens[$prevPrev]['code'] === T_STRING + || $tokens[$prevPrev]['code'] === T_NAMESPACE + || $tokens[$prevPrev]['code'] === T_NEW) + ) { + // Namespaced class/function, not an inbuilt function. + // Could potentially give false negatives for non-namespaced files + // when namespace\functionName() is encountered. + return; + } + } + + if ($tokens[$prev]['code'] === T_NEW) { + // Object creation, not an inbuilt function. + return; + } + + if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR + || $tokens[$prev]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + // Not an inbuilt function. + return; + } + + if ($tokens[$prev]['code'] === T_DOUBLE_COLON) { + // Not an inbuilt function. + return; + } + + $error = 'Calls to PHP native functions must be lowercase; expected "%s" but found "%s"'; + $data = [ + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'CallUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php new file mode 100644 index 00000000..343d9b29 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php @@ -0,0 +1,277 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class NonExecutableCodeSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_BREAK, + T_CONTINUE, + T_RETURN, + T_THROW, + T_EXIT, + T_GOTO, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If this token is preceded with an "or", it only relates to one line + // and should be ignored. For example: fopen() or die(). + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_LOGICAL_OR || $tokens[$prev]['code'] === T_BOOLEAN_OR) { + return; + } + + // Check if this token is actually part of a one-line IF or ELSE statement. + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if ($tokens[$i]['code'] === T_CLOSE_PARENTHESIS) { + $i = $tokens[$i]['parenthesis_opener']; + continue; + } else if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + break; + } + + if ($tokens[$i]['code'] === T_IF + || $tokens[$i]['code'] === T_ELSE + || $tokens[$i]['code'] === T_ELSEIF + ) { + return; + } + + if ($tokens[$stackPtr]['code'] === T_RETURN) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true); + if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) { + // If this is the closing brace of a function + // then this return statement doesn't return anything + // and is not required anyway. + $owner = $tokens[$next]['scope_condition']; + if ($tokens[$owner]['code'] === T_FUNCTION) { + $warning = 'Empty return statement not required here'; + $phpcsFile->addWarning($warning, $stackPtr, 'ReturnNotRequired'); + return; + } + } + } + } + + if (isset($tokens[$stackPtr]['scope_opener']) === true) { + $owner = $tokens[$stackPtr]['scope_condition']; + if ($tokens[$owner]['code'] === T_CASE || $tokens[$owner]['code'] === T_DEFAULT) { + // This token closes the scope of a CASE or DEFAULT statement + // so any code between this statement and the next CASE, DEFAULT or + // end of SWITCH token will not be executable. + $end = $phpcsFile->findEndOfStatement($stackPtr); + $next = $phpcsFile->findNext( + [ + T_CASE, + T_DEFAULT, + T_CLOSE_CURLY_BRACKET, + T_ENDSWITCH, + ], + ($end + 1) + ); + + if ($next !== false) { + $lastLine = $tokens[$end]['line']; + for ($i = ($stackPtr + 1); $i < $next; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + $line = $tokens[$i]['line']; + if ($line > $lastLine) { + $type = substr($tokens[$stackPtr]['type'], 2); + $warning = 'Code after the %s statement on line %s cannot be executed'; + $data = [ + $type, + $tokens[$stackPtr]['line'], + ]; + $phpcsFile->addWarning($warning, $i, 'Unreachable', $data); + $lastLine = $line; + } + } + }//end if + + // That's all we have to check for these types of statements. + return; + }//end if + }//end if + + // This token may be part of an inline condition. + // If we find a closing parenthesis that belongs to a condition + // we should ignore this token. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if (isset($tokens[$prev]['parenthesis_owner']) === true) { + $owner = $tokens[$prev]['parenthesis_owner']; + $ignore = [ + T_IF => true, + T_ELSE => true, + T_ELSEIF => true, + ]; + if (isset($ignore[$tokens[$owner]['code']]) === true) { + return; + } + } + + $ourConditions = array_keys($tokens[$stackPtr]['conditions']); + + if (empty($ourConditions) === false) { + $condition = array_pop($ourConditions); + + if (isset($tokens[$condition]['scope_closer']) === false) { + return; + } + + // Special case for BREAK statements sitting directly inside SWITCH + // statements. If we get to this point, we know the BREAK is not being + // used to close a CASE statement, so it is most likely non-executable + // code itself (as is the case when you put return; break; at the end of + // a case). So we need to ignore this token. + if ($tokens[$condition]['code'] === T_SWITCH + && $tokens[$stackPtr]['code'] === T_BREAK + ) { + return; + } + + $closer = $tokens[$condition]['scope_closer']; + + // If the closer for our condition is shared with other openers, + // we will need to throw errors from this token to the next + // shared opener (if there is one), not to the scope closer. + $nextOpener = null; + for ($i = ($stackPtr + 1); $i < $closer; $i++) { + if (isset($tokens[$i]['scope_closer']) === true) { + if ($tokens[$i]['scope_closer'] === $closer) { + // We found an opener that shares the same + // closing token as us. + $nextOpener = $i; + break; + } + } + }//end for + + if ($nextOpener === null) { + $end = $closer; + } else { + $end = ($nextOpener - 1); + } + } else { + // This token is in the global scope. + if ($tokens[$stackPtr]['code'] === T_BREAK) { + return; + } + + // Throw an error for all lines until the end of the file. + $end = ($phpcsFile->numTokens - 1); + }//end if + + // Find the semicolon that ends this statement, skipping + // nested statements like FOR loops and closures. + for ($start = ($stackPtr + 1); $start < $phpcsFile->numTokens; $start++) { + if ($start === $end) { + break; + } + + if (isset($tokens[$start]['parenthesis_closer']) === true + && $tokens[$start]['code'] === T_OPEN_PARENTHESIS + ) { + $start = $tokens[$start]['parenthesis_closer']; + continue; + } + + if (isset($tokens[$start]['bracket_closer']) === true + && $tokens[$start]['code'] === T_OPEN_CURLY_BRACKET + ) { + $start = $tokens[$start]['bracket_closer']; + continue; + } + + if ($tokens[$start]['code'] === T_SEMICOLON) { + break; + } + }//end for + + if (isset($tokens[$start]) === false) { + return; + } + + $lastLine = $tokens[$start]['line']; + for ($i = ($start + 1); $i < $end; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true + || isset(Tokens::$bracketTokens[$tokens[$i]['code']]) === true + || $tokens[$i]['code'] === T_SEMICOLON + ) { + continue; + } + + // Skip whole functions and classes/interfaces because they are not + // technically executed code, but rather declarations that may be used. + if (isset(Tokens::$ooScopeTokens[$tokens[$i]['code']]) === true + || $tokens[$i]['code'] === T_FUNCTION + || $tokens[$i]['code'] === T_CLOSURE + ) { + if (isset($tokens[$i]['scope_closer']) === false) { + // Parse error/Live coding. + return; + } + + $i = $tokens[$i]['scope_closer']; + continue; + } + + $line = $tokens[$i]['line']; + if ($line > $lastLine) { + $type = substr($tokens[$stackPtr]['type'], 2); + $warning = 'Code after the %s statement on line %s cannot be executed'; + $data = [ + $type, + $tokens[$stackPtr]['line'], + ]; + $phpcsFile->addWarning($warning, $i, 'Unreachable', $data); + $lastLine = $line; + } + }//end for + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MemberVarScopeSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MemberVarScopeSniff.php new file mode 100644 index 00000000..5239b644 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MemberVarScopeSniff.php @@ -0,0 +1,77 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Scope; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; + +class MemberVarScopeSniff extends AbstractVariableSniff +{ + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $properties = $phpcsFile->getMemberProperties($stackPtr); + + if ($properties === [] || $properties['scope_specified'] !== false) { + return; + } + + $error = 'Scope modifier not specified for member variable "%s"'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addError($error, $stackPtr, 'Missing', $data); + + }//end processMemberVar() + + + /** + * Processes normal variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariable() + + + /** + * Processes variables in double quoted strings. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariableInString() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MethodScopeSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MethodScopeSniff.php new file mode 100644 index 00000000..8a34a4f2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MethodScopeSniff.php @@ -0,0 +1,83 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Scope; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Tokens; + +class MethodScopeSniff extends AbstractScopeSniff +{ + + + /** + * Constructs a Squiz_Sniffs_Scope_MethodScopeSniff. + */ + public function __construct() + { + parent::__construct(Tokens::$ooScopeTokens, [T_FUNCTION]); + + }//end __construct() + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * @param int $currScope The current scope opener token. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + $properties = $phpcsFile->getMethodProperties($stackPtr); + if ($properties['scope_specified'] === false) { + $error = 'Visibility must be declared on method "%s"'; + $data = [$methodName]; + $phpcsFile->addError($error, $stackPtr, 'Missing', $data); + } + + }//end processTokenWithinScope() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/StaticThisUsageSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/StaticThisUsageSniff.php new file mode 100644 index 00000000..79cb9f3f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/StaticThisUsageSniff.php @@ -0,0 +1,128 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Scope; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Tokens; + +class StaticThisUsageSniff extends AbstractScopeSniff +{ + + + /** + * Constructs the test with the tokens it wishes to listen for. + */ + public function __construct() + { + parent::__construct([T_CLASS, T_TRAIT, T_ENUM, T_ANON_CLASS], [T_FUNCTION]); + + }//end __construct() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param int $currScope A pointer to the start of the scope. + * + * @return void + */ + public function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + // Ignore abstract functions. + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next === false || $tokens[$next]['code'] !== T_STRING) { + // Not a function declaration, or incomplete. + return; + } + + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + if ($methodProps['is_static'] === false) { + return; + } + + $next = $stackPtr; + $end = $tokens[$stackPtr]['scope_closer']; + + $this->checkThisUsage($phpcsFile, $next, $end); + + }//end processTokenWithinScope() + + + /** + * Check for $this variable usage between $next and $end tokens. + * + * @param File $phpcsFile The current file being scanned. + * @param int $next The position of the next token to check. + * @param int $end The position of the last token to check. + * + * @return void + */ + private function checkThisUsage(File $phpcsFile, $next, $end) + { + $tokens = $phpcsFile->getTokens(); + + do { + $next = $phpcsFile->findNext([T_VARIABLE, T_ANON_CLASS], ($next + 1), $end); + if ($next === false) { + continue; + } + + if ($tokens[$next]['code'] === T_ANON_CLASS) { + $this->checkThisUsage($phpcsFile, $next, $tokens[$next]['scope_opener']); + $next = $tokens[$next]['scope_closer']; + continue; + } + + if ($tokens[$next]['content'] !== '$this') { + continue; + } + + $error = 'Usage of "$this" in static methods will cause runtime errors'; + $phpcsFile->addError($error, $next, 'Found'); + } while ($next !== false); + + }//end checkThisUsage() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/ConcatenationSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/ConcatenationSpacingSniff.php new file mode 100644 index 00000000..9d32e54a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/ConcatenationSpacingSniff.php @@ -0,0 +1,164 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ConcatenationSpacingSniff implements Sniff +{ + + /** + * The number of spaces before and after a string concat. + * + * @var integer + */ + public $spacing = 0; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_STRING_CONCAT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[($stackPtr + 2)]) === false) { + // Syntax error or live coding, bow out. + return; + } + + $ignoreBefore = false; + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_END_HEREDOC || $tokens[$prev]['code'] === T_END_NOWDOC) { + // Spacing before must be preserved due to the here/nowdoc closing tag. + $ignoreBefore = true; + } + + $this->spacing = (int) $this->spacing; + + if ($ignoreBefore === false) { + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $before = 0; + } else { + if ($tokens[($stackPtr - 2)]['line'] !== $tokens[$stackPtr]['line']) { + $before = 'newline'; + } else { + $before = $tokens[($stackPtr - 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing before string concat', $before); + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $after = 0; + } else { + if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $after = 'newline'; + } else { + $after = $tokens[($stackPtr + 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing after string concat', $after); + + if (($ignoreBefore === true + || $before === $this->spacing + || ($before === 'newline' + && $this->ignoreNewlines === true)) + && ($after === $this->spacing + || ($after === 'newline' + && $this->ignoreNewlines === true)) + ) { + return; + } + + if ($this->spacing === 0) { + $message = 'Concat operator must not be surrounded by spaces'; + $data = []; + } else { + if ($this->spacing > 1) { + $message = 'Concat operator must be surrounded by %s spaces'; + } else { + $message = 'Concat operator must be surrounded by a single space'; + } + + $data = [$this->spacing]; + } + + $fix = $phpcsFile->addFixableError($message, $stackPtr, 'PaddingFound', $data); + + if ($fix === true) { + $padding = str_repeat(' ', $this->spacing); + if ($ignoreBefore === false && ($before !== 'newline' || $this->ignoreNewlines === false)) { + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($stackPtr - 1), $padding); + if ($this->spacing === 0 + && ($tokens[($stackPtr - 2)]['code'] === T_LNUMBER + || $tokens[($stackPtr - 2)]['code'] === T_DNUMBER) + ) { + $phpcsFile->fixer->replaceToken(($stackPtr - 2), '('.$tokens[($stackPtr - 2)]['content'].')'); + } + + $phpcsFile->fixer->endChangeset(); + } else if ($this->spacing > 0) { + $phpcsFile->fixer->addContent(($stackPtr - 1), $padding); + } + } + + if ($after !== 'newline' || $this->ignoreNewlines === false) { + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($stackPtr + 1), $padding); + if ($this->spacing === 0 + && ($tokens[($stackPtr + 2)]['code'] === T_LNUMBER + || $tokens[($stackPtr + 2)]['code'] === T_DNUMBER) + ) { + $phpcsFile->fixer->replaceToken(($stackPtr + 2), '('.$tokens[($stackPtr + 2)]['content'].')'); + } + + $phpcsFile->fixer->endChangeset(); + } else if ($this->spacing > 0) { + $phpcsFile->fixer->addContent($stackPtr, $padding); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php new file mode 100644 index 00000000..1ff99b9c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php @@ -0,0 +1,144 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DoubleQuoteUsageSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CONSTANT_ENCAPSED_STRING, + T_DOUBLE_QUOTED_STRING, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If tabs are being converted to spaces by the tokeniser, the + // original content should be used instead of the converted content. + if (isset($tokens[$stackPtr]['orig_content']) === true) { + $workingString = $tokens[$stackPtr]['orig_content']; + } else { + $workingString = $tokens[$stackPtr]['content']; + } + + $lastStringToken = $stackPtr; + + $i = ($stackPtr + 1); + if (isset($tokens[$i]) === true) { + while ($i < $phpcsFile->numTokens + && $tokens[$i]['code'] === $tokens[$stackPtr]['code'] + ) { + if (isset($tokens[$i]['orig_content']) === true) { + $workingString .= $tokens[$i]['orig_content']; + } else { + $workingString .= $tokens[$i]['content']; + } + + $lastStringToken = $i; + $i++; + } + } + + $skipTo = ($lastStringToken + 1); + + // Check if it's a double quoted string. + if ($workingString[0] !== '"' || substr($workingString, -1) !== '"') { + return $skipTo; + } + + // The use of variables in double quoted strings is not allowed. + if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING) { + $stringTokens = token_get_all('addError($error, $stackPtr, 'ContainsVar', $data); + } + } + + return $skipTo; + }//end if + + $allowedChars = [ + '\0', + '\1', + '\2', + '\3', + '\4', + '\5', + '\6', + '\7', + '\n', + '\r', + '\f', + '\t', + '\v', + '\x', + '\b', + '\e', + '\u', + '\'', + ]; + + foreach ($allowedChars as $testChar) { + if (strpos($workingString, $testChar) !== false) { + return $skipTo; + } + } + + $error = 'String %s does not require double quotes; use single quotes instead'; + $data = [str_replace(["\r", "\n"], ['\r', '\n'], $workingString)]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotRequired', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $innerContent = substr($workingString, 1, -1); + $innerContent = str_replace('\"', '"', $innerContent); + $innerContent = str_replace('\\$', '$', $innerContent); + $phpcsFile->fixer->replaceToken($stackPtr, "'$innerContent'"); + while ($lastStringToken !== $stackPtr) { + $phpcsFile->fixer->replaceToken($lastStringToken, ''); + $lastStringToken--; + } + + $phpcsFile->fixer->endChangeset(); + } + + return $skipTo; + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/EchoedStringsSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/EchoedStringsSniff.php new file mode 100644 index 00000000..512d878a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/EchoedStringsSniff.php @@ -0,0 +1,88 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EchoedStringsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_ECHO]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + // If the first non-whitespace token is not an opening parenthesis, then we are not concerned. + if ($tokens[$firstContent]['code'] !== T_OPEN_PARENTHESIS) { + $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); + return; + } + + $end = $phpcsFile->findNext([T_SEMICOLON, T_CLOSE_TAG], $stackPtr, null, false); + + // If the token before the semi-colon is not a closing parenthesis, then we are not concerned. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($end - 1), null, true); + if ($tokens[$prev]['code'] !== T_CLOSE_PARENTHESIS) { + $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); + return; + } + + // If the parenthesis don't match, then we are not concerned. + if ($tokens[$firstContent]['parenthesis_closer'] !== $prev) { + $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); + return; + } + + $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'yes'); + + if (($phpcsFile->findNext(Tokens::$operators, $stackPtr, $end, false)) === false) { + // There are no arithmetic operators in this. + $error = 'Echoed strings should not be bracketed'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'HasBracket'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($firstContent, ''); + if ($tokens[($firstContent - 1)]['code'] !== T_WHITESPACE) { + $phpcsFile->fixer->addContent(($firstContent - 1), ' '); + } + + $phpcsFile->fixer->replaceToken($prev, ''); + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php new file mode 100644 index 00000000..95f95ed6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php @@ -0,0 +1,65 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class CastSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$castTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $expected = str_replace(' ', '', $content); + $expected = str_replace("\t", '', $expected); + + if ($content !== $expected) { + $error = 'Cast statements must not contain whitespace; expected "%s" but found "%s"'; + $data = [ + $expected, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContainsWhiteSpace', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $expected); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php new file mode 100644 index 00000000..808888f4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php @@ -0,0 +1,359 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ControlStructureSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_WHILE, + T_FOREACH, + T_FOR, + T_SWITCH, + T_DO, + T_ELSE, + T_ELSEIF, + T_TRY, + T_CATCH, + T_FINALLY, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === true + && isset($tokens[$stackPtr]['parenthesis_closer']) === true + ) { + $parenOpener = $tokens[$stackPtr]['parenthesis_opener']; + $parenCloser = $tokens[$stackPtr]['parenthesis_closer']; + if ($tokens[($parenOpener + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($parenOpener + 1)]['length']; + + if ($gap === 0) { + $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', 'newline'); + $gap = 'newline'; + } else { + $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', $gap); + } + + $error = 'Expected 0 spaces after opening bracket; %s found'; + $data = [$gap]; + $fix = $phpcsFile->addFixableError($error, ($parenOpener + 1), 'SpacingAfterOpenBrace', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenOpener + 1), ''); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', 0); + } + + if ($tokens[$parenOpener]['line'] === $tokens[$parenCloser]['line'] + && $tokens[($parenCloser - 1)]['code'] === T_WHITESPACE + ) { + $gap = $tokens[($parenCloser - 1)]['length']; + $error = 'Expected 0 spaces before closing bracket; %s found'; + $data = [$gap]; + $fix = $phpcsFile->addFixableError($error, ($parenCloser - 1), 'SpaceBeforeCloseBrace', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenCloser - 1), ''); + } + + if ($gap === 0) { + $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', 'newline'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', $gap); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', 0); + } + }//end if + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $scopeOpener = $tokens[$stackPtr]['scope_opener']; + $scopeCloser = $tokens[$stackPtr]['scope_closer']; + + for ($firstContent = ($scopeOpener + 1); $firstContent < $phpcsFile->numTokens; $firstContent++) { + $code = $tokens[$firstContent]['code']; + + if ($code === T_WHITESPACE + || ($code === T_INLINE_HTML + && trim($tokens[$firstContent]['content']) === '') + ) { + continue; + } + + // Skip all empty tokens on the same line as the opener. + if ($tokens[$firstContent]['line'] === $tokens[$scopeOpener]['line'] + && (isset(Tokens::$emptyTokens[$code]) === true + || $code === T_CLOSE_TAG) + ) { + continue; + } + + break; + } + + // We ignore spacing for some structures that tend to have their own rules. + $ignore = [ + T_FUNCTION => true, + T_CLASS => true, + T_INTERFACE => true, + T_TRAIT => true, + T_ENUM => true, + T_DOC_COMMENT_OPEN_TAG => true, + ]; + + if (isset($ignore[$tokens[$firstContent]['code']]) === false + && $tokens[$firstContent]['line'] >= ($tokens[$scopeOpener]['line'] + 2) + ) { + $gap = ($tokens[$firstContent]['line'] - $tokens[$scopeOpener]['line'] - 1); + $phpcsFile->recordMetric($stackPtr, 'Blank lines at start of control structure', $gap); + + $error = 'Blank line found at start of control structure'; + $fix = $phpcsFile->addFixableError($error, $scopeOpener, 'SpacingAfterOpen'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $i = ($scopeOpener + 1); + while ($tokens[$i]['line'] !== $tokens[$firstContent]['line']) { + // Start removing content from the line after the opener. + if ($tokens[$i]['line'] !== $tokens[$scopeOpener]['line']) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $i++; + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Blank lines at start of control structure', 0); + }//end if + + if ($firstContent !== $scopeCloser) { + $lastContent = $phpcsFile->findPrevious( + T_WHITESPACE, + ($scopeCloser - 1), + null, + true + ); + + $lastNonEmptyContent = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($scopeCloser - 1), + null, + true + ); + + $checkToken = $lastContent; + if (isset($tokens[$lastNonEmptyContent]['scope_condition']) === true) { + $checkToken = $tokens[$lastNonEmptyContent]['scope_condition']; + } + + if (isset($ignore[$tokens[$checkToken]['code']]) === false + && $tokens[$lastContent]['line'] <= ($tokens[$scopeCloser]['line'] - 2) + ) { + $errorToken = $scopeCloser; + for ($i = ($scopeCloser - 1); $i > $lastContent; $i--) { + if ($tokens[$i]['line'] < $tokens[$scopeCloser]['line']) { + $errorToken = $i; + break; + } + } + + $gap = ($tokens[$scopeCloser]['line'] - $tokens[$lastContent]['line'] - 1); + $phpcsFile->recordMetric($stackPtr, 'Blank lines at end of control structure', $gap); + + $error = 'Blank line found at end of control structure'; + $fix = $phpcsFile->addFixableError($error, $errorToken, 'SpacingBeforeClose'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($scopeCloser - 1); $i > $lastContent; $i--) { + if ($tokens[$i]['line'] === $tokens[$scopeCloser]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$lastContent]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Blank lines at end of control structure', 0); + }//end if + }//end if + + if ($tokens[$stackPtr]['code'] === T_MATCH) { + // Move the scope closer to the semicolon/comma. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($scopeCloser + 1), null, true); + if ($next !== false + && ($tokens[$next]['code'] === T_SEMICOLON || $tokens[$next]['code'] === T_COMMA) + ) { + $scopeCloser = $next; + } + } + + $trailingContent = $phpcsFile->findNext( + T_WHITESPACE, + ($scopeCloser + 1), + null, + true + ); + + if ($tokens[$trailingContent]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$trailingContent]['code']]) === true + ) { + // Special exception for code where the comment about + // an ELSE or ELSEIF is written between the control structures. + $nextCode = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($scopeCloser + 1), + null, + true + ); + + if ($tokens[$nextCode]['code'] === T_ELSE + || $tokens[$nextCode]['code'] === T_ELSEIF + || $tokens[$trailingContent]['line'] === $tokens[$scopeCloser]['line'] + ) { + $trailingContent = $nextCode; + } + }//end if + + if ($tokens[$trailingContent]['code'] === T_ELSE) { + if ($tokens[$stackPtr]['code'] === T_IF) { + // IF with ELSE. + return; + } + } + + if ($tokens[$trailingContent]['code'] === T_WHILE + && $tokens[$stackPtr]['code'] === T_DO + ) { + // DO with WHILE. + return; + } + + if ($tokens[$trailingContent]['code'] === T_CLOSE_TAG) { + // At the end of the script or embedded code. + return; + } + + if (isset($tokens[$trailingContent]['scope_condition']) === true + && $tokens[$trailingContent]['scope_condition'] !== $trailingContent + && isset($tokens[$trailingContent]['scope_opener']) === true + && $tokens[$trailingContent]['scope_opener'] !== $trailingContent + ) { + // Another control structure's closing brace. + $owner = $tokens[$trailingContent]['scope_condition']; + if ($tokens[$owner]['code'] === T_FUNCTION) { + // The next content is the closing brace of a function + // so normal function rules apply and we can ignore it. + return; + } + + if ($tokens[$owner]['code'] === T_CLOSURE + && ($phpcsFile->hasCondition($stackPtr, [T_FUNCTION, T_CLOSURE]) === true + || isset($tokens[$stackPtr]['nested_parenthesis']) === true) + ) { + return; + } + + if ($tokens[$trailingContent]['line'] !== ($tokens[$scopeCloser]['line'] + 1)) { + $error = 'Blank line found after control structure'; + $fix = $phpcsFile->addFixableError($error, $scopeCloser, 'LineAfterClose'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $i = ($scopeCloser + 1); + while ($tokens[$i]['line'] !== $tokens[$trailingContent]['line']) { + $phpcsFile->fixer->replaceToken($i, ''); + $i++; + } + + $phpcsFile->fixer->addNewline($scopeCloser); + $phpcsFile->fixer->endChangeset(); + } + } + } else if ($tokens[$trailingContent]['code'] !== T_ELSE + && $tokens[$trailingContent]['code'] !== T_ELSEIF + && $tokens[$trailingContent]['code'] !== T_CATCH + && $tokens[$trailingContent]['code'] !== T_FINALLY + && $tokens[$trailingContent]['line'] === ($tokens[$scopeCloser]['line'] + 1) + ) { + $error = 'No blank line found after control structure'; + $fix = $phpcsFile->addFixableError($error, $scopeCloser, 'NoLineAfterClose'); + if ($fix === true) { + $trailingContent = $phpcsFile->findNext( + T_WHITESPACE, + ($scopeCloser + 1), + null, + true + ); + + if (($tokens[$trailingContent]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$trailingContent]['code']]) === true) + && $tokens[$trailingContent]['line'] === $tokens[$scopeCloser]['line'] + ) { + $phpcsFile->fixer->addNewline($trailingContent); + } else { + $phpcsFile->fixer->addNewline($scopeCloser); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php new file mode 100644 index 00000000..68871990 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php @@ -0,0 +1,164 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FunctionClosingBraceSpaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + // Probably an interface method. + return; + } + + $closeBrace = $tokens[$stackPtr]['scope_closer']; + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), null, true); + + // Special case for empty JS functions. + if ($phpcsFile->tokenizerType === 'JS' && $prevContent === $tokens[$stackPtr]['scope_opener']) { + // In this case, the opening and closing brace must be + // right next to each other. + if ($tokens[$stackPtr]['scope_closer'] !== ($tokens[$stackPtr]['scope_opener'] + 1)) { + $error = 'The opening and closing braces of empty functions must be directly next to each other; e.g., function () {}'; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpacingBetween'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($tokens[$stackPtr]['scope_opener'] + 1); $i < $closeBrace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + return; + } + + $nestedFunction = false; + if ($phpcsFile->hasCondition($stackPtr, [T_FUNCTION, T_CLOSURE]) === true + || isset($tokens[$stackPtr]['nested_parenthesis']) === true + ) { + $nestedFunction = true; + } + + $braceLine = $tokens[$closeBrace]['line']; + $prevLine = $tokens[$prevContent]['line']; + $found = ($braceLine - $prevLine - 1); + + if ($nestedFunction === true) { + if ($found < 0) { + $error = 'Closing brace of nested function must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'ContentBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($closeBrace); + } + } else if ($found > 0) { + $error = 'Expected 0 blank lines before closing brace of nested function; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpacingBeforeNestedClose', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $changeMade = false; + for ($i = ($prevContent + 1); $i < $closeBrace; $i++) { + // Try and maintain indentation. + if ($tokens[$i]['line'] === ($braceLine - 1)) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + $changeMade = true; + } + + // Special case for when the last content contains the newline + // token as well, like with a comment. + if ($changeMade === false) { + $phpcsFile->fixer->replaceToken(($prevContent + 1), ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + } else { + if ($found !== 1) { + if ($found < 0) { + $found = 0; + } + + $error = 'Expected 1 blank line before closing function brace; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpacingBeforeClose', $data); + + if ($fix === true) { + if ($found > 1) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prevContent + 1); $i < ($closeBrace - 1); $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken($i, $phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } else { + // Try and maintain indentation. + if ($tokens[($closeBrace - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->addNewlineBefore($closeBrace - 1); + } else { + $phpcsFile->fixer->addNewlineBefore($closeBrace); + } + } + } + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php new file mode 100644 index 00000000..09c5a48a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php @@ -0,0 +1,98 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FunctionOpeningBraceSpaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + // Probably an interface or abstract method. + return; + } + + $openBrace = $tokens[$stackPtr]['scope_opener']; + $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($openBrace + 1), null, true); + + if ($nextContent === $tokens[$stackPtr]['scope_closer']) { + // The next bit of content is the closing brace, so this + // is an empty function and should have a blank line + // between the opening and closing braces. + return; + } + + $braceLine = $tokens[$openBrace]['line']; + $nextLine = $tokens[$nextContent]['line']; + + $found = ($nextLine - $braceLine - 1); + if ($found > 0) { + $error = 'Expected 0 blank lines after opening function brace; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $openBrace, 'SpacingAfter', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($openBrace + 1); $i < $nextContent; $i++) { + if ($tokens[$i]['line'] === $nextLine) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewline($openBrace); + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php new file mode 100644 index 00000000..1f4704b9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php @@ -0,0 +1,367 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionSpacingSniff implements Sniff +{ + + /** + * The number of blank lines between functions. + * + * @var integer + */ + public $spacing = 2; + + /** + * The number of blank lines before the first function in a class. + * + * @var integer + */ + public $spacingBeforeFirst = 2; + + /** + * The number of blank lines after the last function in a class. + * + * @var integer + */ + public $spacingAfterLast = 2; + + /** + * Original properties as set in a custom ruleset (if any). + * + * @var array|null + */ + private $rulesetProperties = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this sniff when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $previousNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($previousNonEmpty !== false + && $tokens[$previousNonEmpty]['code'] === T_OPEN_TAG + && $tokens[$previousNonEmpty]['line'] !== 1 + ) { + // Ignore functions at the start of an embedded PHP block. + return; + } + + // If the ruleset has only overridden the spacing property, use + // that value for all spacing rules. + if ($this->rulesetProperties === null) { + $this->rulesetProperties = []; + if (isset($phpcsFile->ruleset->ruleset['Squiz.WhiteSpace.FunctionSpacing']) === true + && isset($phpcsFile->ruleset->ruleset['Squiz.WhiteSpace.FunctionSpacing']['properties']) === true + ) { + $this->rulesetProperties = $phpcsFile->ruleset->ruleset['Squiz.WhiteSpace.FunctionSpacing']['properties']; + if (isset($this->rulesetProperties['spacing']) === true) { + if (isset($this->rulesetProperties['spacingBeforeFirst']) === false) { + $this->spacingBeforeFirst = $this->spacing; + } + + if (isset($this->rulesetProperties['spacingAfterLast']) === false) { + $this->spacingAfterLast = $this->spacing; + } + } + } + } + + $this->spacing = (int) $this->spacing; + $this->spacingBeforeFirst = (int) $this->spacingBeforeFirst; + $this->spacingAfterLast = (int) $this->spacingAfterLast; + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + // Must be an interface method, so the closer is the semicolon. + $closer = $phpcsFile->findNext(T_SEMICOLON, $stackPtr); + } else { + $closer = $tokens[$stackPtr]['scope_closer']; + } + + $isFirst = false; + $isLast = false; + + $ignore = ([T_WHITESPACE => T_WHITESPACE] + Tokens::$methodPrefixes); + + $prev = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); + + while ($tokens[$prev]['code'] === T_ATTRIBUTE_END) { + // Skip past function attributes. + $prev = $phpcsFile->findPrevious($ignore, ($tokens[$prev]['attribute_opener'] - 1), null, true); + } + + if ($tokens[$prev]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + // Skip past function docblocks. + $prev = $phpcsFile->findPrevious($ignore, ($tokens[$prev]['comment_opener'] - 1), null, true); + } + + if ($tokens[$prev]['code'] === T_OPEN_CURLY_BRACKET) { + $isFirst = true; + } + + $next = $phpcsFile->findNext($ignore, ($closer + 1), null, true); + if (isset(Tokens::$emptyTokens[$tokens[$next]['code']]) === true + && $tokens[$next]['line'] === $tokens[$closer]['line'] + ) { + // Skip past "end" comments. + $next = $phpcsFile->findNext($ignore, ($next + 1), null, true); + } + + if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) { + $isLast = true; + } + + /* + Check the number of blank lines + after the function. + */ + + // Allow for comments on the same line as the closer. + for ($nextLineToken = ($closer + 1); $nextLineToken < $phpcsFile->numTokens; $nextLineToken++) { + if ($tokens[$nextLineToken]['line'] !== $tokens[$closer]['line']) { + break; + } + } + + $requiredSpacing = $this->spacing; + $errorCode = 'After'; + if ($isLast === true) { + $requiredSpacing = $this->spacingAfterLast; + $errorCode = 'AfterLast'; + } + + $foundLines = 0; + if ($nextLineToken === ($phpcsFile->numTokens - 1)) { + // We are at the end of the file. + // Don't check spacing after the function because this + // should be done by an EOF sniff. + $foundLines = $requiredSpacing; + } else { + $nextContent = $phpcsFile->findNext(T_WHITESPACE, $nextLineToken, null, true); + if ($nextContent === false) { + // We are at the end of the file. + // Don't check spacing after the function because this + // should be done by an EOF sniff. + $foundLines = $requiredSpacing; + } else { + $foundLines = ($tokens[$nextContent]['line'] - $tokens[$nextLineToken]['line']); + } + } + + if ($isLast === true) { + $phpcsFile->recordMetric($stackPtr, 'Function spacing after last', $foundLines); + } else { + $phpcsFile->recordMetric($stackPtr, 'Function spacing after', $foundLines); + } + + if ($foundLines !== $requiredSpacing) { + $error = 'Expected %s blank line'; + if ($requiredSpacing !== 1) { + $error .= 's'; + } + + $error .= ' after function; %s found'; + $data = [ + $requiredSpacing, + $foundLines, + ]; + + $fix = $phpcsFile->addFixableError($error, $closer, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $nextLineToken; $i <= $nextContent; $i++) { + if ($tokens[$i]['line'] === $tokens[$nextContent]['line']) { + $phpcsFile->fixer->addContentBefore($i, str_repeat($phpcsFile->eolChar, $requiredSpacing)); + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + + /* + Check the number of blank lines + before the function. + */ + + $prevLineToken = null; + for ($i = $stackPtr; $i >= 0; $i--) { + if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) { + continue; + } + + $prevLineToken = $i; + break; + } + + if ($prevLineToken === null) { + // Never found the previous line, which means + // there are 0 blank lines before the function. + $foundLines = 0; + $prevContent = 0; + $prevLineToken = 0; + } else { + $currentLine = $tokens[$stackPtr]['line']; + + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, $prevLineToken, null, true); + + if ($tokens[$prevContent]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$prevContent]['code']]) === true + ) { + // Ignore comments as they can have different spacing rules, and this + // isn't a proper function comment anyway. + return; + } + + while ($tokens[$prevContent]['code'] === T_ATTRIBUTE_END + && $tokens[$prevContent]['line'] === ($currentLine - 1) + ) { + // Account for function attributes. + $currentLine = $tokens[$tokens[$prevContent]['attribute_opener']]['line']; + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($tokens[$prevContent]['attribute_opener'] - 1), null, true); + } + + if ($tokens[$prevContent]['code'] === T_DOC_COMMENT_CLOSE_TAG + && $tokens[$prevContent]['line'] === ($currentLine - 1) + ) { + // Account for function comments. + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($tokens[$prevContent]['comment_opener'] - 1), null, true); + } + + $prevLineToken = $prevContent; + + // Before we throw an error, check that we are not throwing an error + // for another function. We don't want to error for no blank lines after + // the previous function and no blank lines before this one as well. + $prevLine = ($tokens[$prevContent]['line'] - 1); + $i = ($stackPtr - 1); + $foundLines = 0; + + $stopAt = 0; + if (isset($tokens[$stackPtr]['conditions']) === true) { + $conditions = $tokens[$stackPtr]['conditions']; + $conditions = array_keys($conditions); + $stopAt = array_pop($conditions); + } + + while ($currentLine !== $prevLine && $currentLine > 1 && $i > $stopAt) { + if ($tokens[$i]['code'] === T_FUNCTION) { + // Found another interface or abstract function. + return; + } + + if ($tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET + && $tokens[$tokens[$i]['scope_condition']]['code'] === T_FUNCTION + ) { + // Found a previous function. + return; + } + + $currentLine = $tokens[$i]['line']; + if ($currentLine === $prevLine) { + break; + } + + if ($tokens[($i - 1)]['line'] < $currentLine && $tokens[($i + 1)]['line'] > $currentLine) { + // This token is on a line by itself. If it is whitespace, the line is empty. + if ($tokens[$i]['code'] === T_WHITESPACE) { + $foundLines++; + } + } + + $i--; + }//end while + }//end if + + $requiredSpacing = $this->spacing; + $errorCode = 'Before'; + if ($isFirst === true) { + $requiredSpacing = $this->spacingBeforeFirst; + $errorCode = 'BeforeFirst'; + + $phpcsFile->recordMetric($stackPtr, 'Function spacing before first', $foundLines); + } else { + $phpcsFile->recordMetric($stackPtr, 'Function spacing before', $foundLines); + } + + if ($foundLines !== $requiredSpacing) { + $error = 'Expected %s blank line'; + if ($requiredSpacing !== 1) { + $error .= 's'; + } + + $error .= ' before function; %s found'; + $data = [ + $requiredSpacing, + $foundLines, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode, $data); + if ($fix === true) { + $nextSpace = $phpcsFile->findNext(T_WHITESPACE, ($prevContent + 1), $stackPtr); + if ($nextSpace === false) { + $nextSpace = ($stackPtr - 1); + } + + if ($foundLines < $requiredSpacing) { + $padding = str_repeat($phpcsFile->eolChar, ($requiredSpacing - $foundLines)); + $phpcsFile->fixer->addContent($prevLineToken, $padding); + } else { + $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($nextSpace + 1), null, true); + $phpcsFile->fixer->beginChangeset(); + for ($i = $nextSpace; $i < $nextContent; $i++) { + if ($tokens[$i]['line'] === $tokens[$prevContent]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$nextContent]['line']) { + $phpcsFile->fixer->addContentBefore($i, str_repeat($phpcsFile->eolChar, $requiredSpacing)); + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php new file mode 100644 index 00000000..c1492bf7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php @@ -0,0 +1,89 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util; + +class LanguageConstructSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_ECHO, + T_PRINT, + T_RETURN, + T_INCLUDE, + T_INCLUDE_ONCE, + T_REQUIRE, + T_REQUIRE_ONCE, + T_NEW, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[($stackPtr + 1)]) === false) { + // Skip if there is no next token. + return; + } + + if ($tokens[($stackPtr + 1)]['code'] === T_SEMICOLON) { + // No content for this language construct. + return; + } + + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $content = $tokens[($stackPtr + 1)]['content']; + if ($content !== ' ') { + $error = 'Language constructs must be followed by a single space; expected 1 space but found "%s"'; + $data = [Util\Common::prepareForOutput($content)]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'IncorrectSingle', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } else if ($tokens[($stackPtr + 1)]['code'] !== T_OPEN_PARENTHESIS) { + $error = 'Language constructs must be followed by a single space; expected "%s" but found "%s"'; + $data = [ + $tokens[$stackPtr]['content'].' '.$tokens[($stackPtr + 1)]['content'], + $tokens[$stackPtr]['content'].$tokens[($stackPtr + 1)]['content'], + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Incorrect', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LogicalOperatorSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LogicalOperatorSpacingSniff.php new file mode 100644 index 00000000..a89a02a9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LogicalOperatorSpacingSniff.php @@ -0,0 +1,102 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LogicalOperatorSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$booleanOperators; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check there is one space before the operator. + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space before logical operator; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBefore'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + } else { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$stackPtr]['line'] === $tokens[$prev]['line'] + && $tokens[($stackPtr - 1)]['length'] !== 1 + ) { + $found = $tokens[($stackPtr - 1)]['length']; + $error = 'Expected 1 space before logical operator; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'TooMuchSpaceBefore', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + } + } + + // Check there is one space after the operator. + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after logical operator; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfter'); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } else { + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$stackPtr]['line'] === $tokens[$next]['line'] + && $tokens[($stackPtr + 1)]['length'] !== 1 + ) { + $found = $tokens[($stackPtr + 1)]['length']; + $error = 'Expected 1 space after logical operator; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'TooMuchSpaceAfter', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/MemberVarSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/MemberVarSpacingSniff.php new file mode 100644 index 00000000..0ece1aca --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/MemberVarSpacingSniff.php @@ -0,0 +1,254 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Tokens; + +class MemberVarSpacingSniff extends AbstractVariableSniff +{ + + /** + * The number of blank lines between member vars. + * + * @var integer + */ + public $spacing = 1; + + /** + * The number of blank lines before the first member var. + * + * @var integer + */ + public $spacingBeforeFirst = 1; + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $validPrefixes = Tokens::$methodPrefixes; + $validPrefixes[] = T_VAR; + + $startOfStatement = $phpcsFile->findPrevious($validPrefixes, ($stackPtr - 1), null, false, null, true); + if ($startOfStatement === false) { + return; + } + + $endOfStatement = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1), null, false, null, true); + + $ignore = $validPrefixes; + $ignore[T_WHITESPACE] = T_WHITESPACE; + + $start = $startOfStatement; + for ($prev = ($startOfStatement - 1); $prev >= 0; $prev--) { + if (isset($ignore[$tokens[$prev]['code']]) === true) { + continue; + } + + if ($tokens[$prev]['code'] === T_ATTRIBUTE_END + && isset($tokens[$prev]['attribute_opener']) === true + ) { + $prev = $tokens[$prev]['attribute_opener']; + $start = $prev; + continue; + } + + break; + } + + if (isset(Tokens::$commentTokens[$tokens[$prev]['code']]) === true) { + // Assume the comment belongs to the member var if it is on a line by itself. + $prevContent = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + if ($tokens[$prevContent]['line'] !== $tokens[$prev]['line']) { + // Check the spacing, but then skip it. + $foundLines = ($tokens[$startOfStatement]['line'] - $tokens[$prev]['line'] - 1); + if ($foundLines > 0) { + for ($i = ($prev + 1); $i < $startOfStatement; $i++) { + if ($tokens[$i]['column'] !== 1) { + continue; + } + + if ($tokens[$i]['code'] === T_WHITESPACE + && $tokens[$i]['line'] !== $tokens[($i + 1)]['line'] + ) { + $error = 'Expected 0 blank lines after member var comment; %s found'; + $data = [$foundLines]; + $fix = $phpcsFile->addFixableError($error, $prev, 'AfterComment', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + // Inline comments have the newline included in the content but + // docblocks do not. + if ($tokens[$prev]['code'] === T_COMMENT) { + $phpcsFile->fixer->replaceToken($prev, rtrim($tokens[$prev]['content'])); + } + + for ($i = ($prev + 1); $i <= $startOfStatement; $i++) { + if ($tokens[$i]['line'] === $tokens[$startOfStatement]['line']) { + break; + } + + // Remove the newline after the docblock, and any entirely + // empty lines before the member var. + if ($tokens[$i]['code'] === T_WHITESPACE + && $tokens[$i]['line'] === $tokens[$prev]['line'] + || ($tokens[$i]['column'] === 1 + && $tokens[$i]['line'] !== $tokens[($i + 1)]['line']) + ) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->endChangeset(); + }//end if + + break; + }//end if + }//end for + }//end if + + $start = $prev; + }//end if + }//end if + + // There needs to be n blank lines before the var, not counting comments. + if ($start === $startOfStatement) { + // No comment found. + $first = $phpcsFile->findFirstOnLine(Tokens::$emptyTokens, $start, true); + if ($first === false) { + $first = $start; + } + } else if ($tokens[$start]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + $first = $tokens[$start]['comment_opener']; + } else { + $first = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($start - 1), null, true); + $first = $phpcsFile->findNext(array_merge(Tokens::$commentTokens, [T_ATTRIBUTE]), ($first + 1)); + } + + // Determine if this is the first member var. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($first - 1), null, true); + if ($tokens[$prev]['code'] === T_CLOSE_CURLY_BRACKET + && isset($tokens[$prev]['scope_condition']) === true + && $tokens[$tokens[$prev]['scope_condition']]['code'] === T_FUNCTION + ) { + return; + } + + if ($tokens[$prev]['code'] === T_OPEN_CURLY_BRACKET + && isset(Tokens::$ooScopeTokens[$tokens[$tokens[$prev]['scope_condition']]['code']]) === true + ) { + $errorMsg = 'Expected %s blank line(s) before first member var; %s found'; + $errorCode = 'FirstIncorrect'; + $spacing = (int) $this->spacingBeforeFirst; + } else { + $errorMsg = 'Expected %s blank line(s) before member var; %s found'; + $errorCode = 'Incorrect'; + $spacing = (int) $this->spacing; + } + + $foundLines = ($tokens[$first]['line'] - $tokens[$prev]['line'] - 1); + + if ($errorCode === 'FirstIncorrect') { + $phpcsFile->recordMetric($stackPtr, 'Member var spacing before first', $foundLines); + } else { + $phpcsFile->recordMetric($stackPtr, 'Member var spacing before', $foundLines); + } + + if ($foundLines === $spacing) { + if ($endOfStatement !== false) { + return $endOfStatement; + } + + return; + } + + $data = [ + $spacing, + $foundLines, + ]; + + $fix = $phpcsFile->addFixableError($errorMsg, $startOfStatement, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $first; $i++) { + if ($tokens[$i]['line'] === $tokens[$prev]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$first]['line']) { + for ($x = 1; $x <= $spacing; $x++) { + $phpcsFile->fixer->addNewlineBefore($i); + } + + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + + if ($endOfStatement !== false) { + return $endOfStatement; + } + + return; + + }//end processMemberVar() + + + /** + * Processes normal variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariable() + + + /** + * Processes variables in double quoted strings. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariableInString() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php new file mode 100644 index 00000000..cc5db164 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php @@ -0,0 +1,167 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ObjectOperatorSpacingSniff implements Sniff +{ + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OBJECT_OPERATOR, + T_DOUBLE_COLON, + T_NULLSAFE_OBJECT_OPERATOR, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $before = 0; + } else { + if ($tokens[($stackPtr - 2)]['line'] !== $tokens[$stackPtr]['line']) { + $before = 'newline'; + } else { + $before = $tokens[($stackPtr - 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing before object operator', $before); + $this->checkSpacingBeforeOperator($phpcsFile, $stackPtr, $before); + + if (isset($tokens[($stackPtr + 1)]) === false + || isset($tokens[($stackPtr + 2)]) === false + ) { + return; + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $after = 0; + } else { + if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $after = 'newline'; + } else { + $after = $tokens[($stackPtr + 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing after object operator', $after); + $this->checkSpacingAfterOperator($phpcsFile, $stackPtr, $after); + + }//end process() + + + /** + * Check the spacing before the operator. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param mixed $before The number of spaces found before the + * operator or the string 'newline'. + * + * @return boolean true if there was no error, false otherwise. + */ + protected function checkSpacingBeforeOperator(File $phpcsFile, $stackPtr, $before) + { + if ($before !== 0 + && ($before !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Space found before object operator'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Before'); + if ($fix === true) { + $tokens = $phpcsFile->getTokens(); + $curPos = ($stackPtr - 1); + + $phpcsFile->fixer->beginChangeset(); + while ($tokens[$curPos]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($curPos, ''); + --$curPos; + } + + $phpcsFile->fixer->endChangeset(); + } + + return false; + } + + return true; + + }//end checkSpacingBeforeOperator() + + + /** + * Check the spacing after the operator. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param mixed $after The number of spaces found after the + * operator or the string 'newline'. + * + * @return boolean true if there was no error, false otherwise. + */ + protected function checkSpacingAfterOperator(File $phpcsFile, $stackPtr, $after) + { + if ($after !== 0 + && ($after !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Space found after object operator'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'After'); + if ($fix === true) { + $tokens = $phpcsFile->getTokens(); + $curPos = ($stackPtr + 1); + + $phpcsFile->fixer->beginChangeset(); + while ($tokens[$curPos]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($curPos, ''); + ++$curPos; + } + + $phpcsFile->fixer->endChangeset(); + } + + return false; + } + + return true; + + }//end checkSpacingAfterOperator() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php new file mode 100644 index 00000000..2627d10d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php @@ -0,0 +1,381 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OperatorSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + /** + * Don't check spacing for assignment operators. + * + * This allows multiple assignment statements to be aligned. + * + * @var boolean + */ + public $ignoreSpacingBeforeAssignments = true; + + /** + * A list of tokens that aren't considered as operands. + * + * @var string[] + */ + private $nonOperandTokens = []; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + /* + First we setup an array of all the tokens that can come before + a T_MINUS or T_PLUS token to indicate that the token is not being + used as an operator. + */ + + // Trying to operate on a negative value; eg. ($var * -1). + $this->nonOperandTokens = Tokens::$operators; + + // Trying to compare a negative value; eg. ($var === -1). + $this->nonOperandTokens += Tokens::$comparisonTokens; + + // Trying to compare a negative value; eg. ($var || -1 === $b). + $this->nonOperandTokens += Tokens::$booleanOperators; + + // Trying to assign a negative value; eg. ($var = -1). + $this->nonOperandTokens += Tokens::$assignmentTokens; + + // Returning/printing a negative value; eg. (return -1). + $this->nonOperandTokens += [ + T_RETURN => T_RETURN, + T_ECHO => T_ECHO, + T_EXIT => T_EXIT, + T_PRINT => T_PRINT, + T_YIELD => T_YIELD, + T_FN_ARROW => T_FN_ARROW, + ]; + + // Trying to use a negative value; eg. myFunction($var, -2). + $this->nonOperandTokens += [ + T_CASE => T_CASE, + T_COLON => T_COLON, + T_COMMA => T_COMMA, + T_INLINE_ELSE => T_INLINE_ELSE, + T_INLINE_THEN => T_INLINE_THEN, + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_OPEN_SHORT_ARRAY => T_OPEN_SHORT_ARRAY, + T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET, + T_STRING_CONCAT => T_STRING_CONCAT, + ]; + + // Casting a negative value; eg. (array) -$a. + $this->nonOperandTokens += Tokens::$castTokens; + + /* + These are the tokens the sniff is looking for. + */ + + $targets = Tokens::$comparisonTokens; + $targets += Tokens::$operators; + $targets += Tokens::$assignmentTokens; + $targets[] = T_INLINE_THEN; + $targets[] = T_INLINE_ELSE; + $targets[] = T_INSTANCEOF; + + return $targets; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($this->isOperator($phpcsFile, $stackPtr) === false) { + return; + } + + if ($tokens[$stackPtr]['code'] === T_BITWISE_AND) { + // Check there is one space before the & operator. + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space before "&" operator; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBeforeAmp'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Space before operator', 0); + } else { + if ($tokens[($stackPtr - 2)]['line'] !== $tokens[$stackPtr]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr - 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Space before operator', $found); + if ($found !== 1 + && ($found !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Expected 1 space before "&" operator; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeAmp', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + } + }//end if + + $hasNext = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($hasNext === false) { + // Live coding/parse error at end of file. + return; + } + + // Check there is one space after the & operator. + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after "&" operator; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfterAmp'); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Space after operator', 0); + } else { + if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr + 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Space after operator', $found); + if ($found !== 1 + && ($found !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Expected 1 space after "&" operator; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterAmp', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + }//end if + + return; + }//end if + + $operator = $tokens[$stackPtr]['content']; + + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE + && (($tokens[($stackPtr - 1)]['code'] === T_INLINE_THEN + && $tokens[($stackPtr)]['code'] === T_INLINE_ELSE) === false) + ) { + $error = "Expected 1 space before \"$operator\"; 0 found"; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBefore'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Space before operator', 0); + } else if (isset(Tokens::$assignmentTokens[$tokens[$stackPtr]['code']]) === false + || $this->ignoreSpacingBeforeAssignments === false + ) { + // Throw an error for assignments only if enabled using the sniff property + // because other standards allow multiple spaces to align assignments. + if ($tokens[($stackPtr - 2)]['line'] !== $tokens[$stackPtr]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr - 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Space before operator', $found); + if ($found !== 1 + && ($found !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Expected 1 space before "%s"; %s found'; + $data = [ + $operator, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBefore', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if ($found === 'newline') { + $i = ($stackPtr - 2); + while ($tokens[$i]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($i, ''); + $i--; + } + } + + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + $hasNext = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($hasNext === false) { + // Live coding/parse error at end of file. + return; + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + // Skip short ternary such as: "$foo = $bar ?: true;". + if (($tokens[$stackPtr]['code'] === T_INLINE_THEN + && $tokens[($stackPtr + 1)]['code'] === T_INLINE_ELSE) + ) { + return; + } + + $error = "Expected 1 space after \"$operator\"; 0 found"; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfter'); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Space after operator', 0); + } else { + if (isset($tokens[($stackPtr + 2)]) === true + && $tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line'] + ) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr + 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Space after operator', $found); + if ($found !== 1 + && ($found !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Expected 1 space after "%s"; %s found'; + $data = [ + $operator, + $found, + ]; + + $nextNonWhitespace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($nextNonWhitespace !== false + && isset(Tokens::$commentTokens[$tokens[$nextNonWhitespace]['code']]) === true + && $found === 'newline' + ) { + // Don't auto-fix when it's a comment or PHPCS annotation on a new line as + // it causes fixer conflicts and can cause the meaning of annotations to change. + $phpcsFile->addError($error, $stackPtr, 'SpacingAfter', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfter', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + }//end if + }//end if + + }//end process() + + + /** + * Checks if an operator is actually a different type of token in the current context. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the operator in + * the stack. + * + * @return boolean + */ + protected function isOperator(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Skip default values in function declarations. + // Skip declare statements. + if ($tokens[$stackPtr]['code'] === T_EQUAL + || $tokens[$stackPtr]['code'] === T_MINUS + ) { + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $parenthesis = array_keys($tokens[$stackPtr]['nested_parenthesis']); + $bracket = array_pop($parenthesis); + if (isset($tokens[$bracket]['parenthesis_owner']) === true) { + $function = $tokens[$bracket]['parenthesis_owner']; + if ($tokens[$function]['code'] === T_FUNCTION + || $tokens[$function]['code'] === T_CLOSURE + || $tokens[$function]['code'] === T_FN + || $tokens[$function]['code'] === T_DECLARE + ) { + return false; + } + } + } + } + + if ($tokens[$stackPtr]['code'] === T_EQUAL) { + // Skip for '=&' case. + if (isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)]['code'] === T_BITWISE_AND + ) { + return false; + } + } + + if ($tokens[$stackPtr]['code'] === T_BITWISE_AND) { + // If it's not a reference, then we expect one space either side of the + // bitwise operator. + if ($phpcsFile->isReference($stackPtr) === true) { + return false; + } + } + + if ($tokens[$stackPtr]['code'] === T_MINUS || $tokens[$stackPtr]['code'] === T_PLUS) { + // Check minus spacing, but make sure we aren't just assigning + // a minus value or returning one. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if (isset($this->nonOperandTokens[$tokens[$prev]['code']]) === true) { + return false; + } + }//end if + + return true; + + }//end isOperator() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/PropertyLabelSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/PropertyLabelSpacingSniff.php new file mode 100644 index 00000000..198460df --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/PropertyLabelSpacingSniff.php @@ -0,0 +1,79 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class PropertyLabelSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_PROPERTY, + T_LABEL, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $colon = $phpcsFile->findNext(T_COLON, ($stackPtr + 1)); + + if ($colon !== ($stackPtr + 1)) { + $error = 'There must be no space before the colon in a property/label declaration'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Before'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + } + + if ($tokens[($colon + 1)]['code'] !== T_WHITESPACE || $tokens[($colon + 1)]['content'] !== ' ') { + $error = 'There must be a single space after the colon in a property/label declaration'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'After'); + if ($fix === true) { + if ($tokens[($colon + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($colon + 1), ' '); + } else { + $phpcsFile->fixer->addContent($colon, ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php new file mode 100644 index 00000000..fd038753 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php @@ -0,0 +1,114 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ScopeClosingBraceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$scopeOpeners; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile All the tokens found in the document. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If this is an inline condition (ie. there is no scope opener), then + // return, as this is not a new scope. + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + // We need to actually find the first piece of content on this line, + // as if this is a method with tokens before it (public, static etc) + // or an if with an else before it, then we need to start the scope + // checking from there, rather than the current token. + $lineStart = $phpcsFile->findFirstOnLine([T_WHITESPACE, T_INLINE_HTML], $stackPtr, true); + while ($tokens[$lineStart]['code'] === T_CONSTANT_ENCAPSED_STRING + && $tokens[($lineStart - 1)]['code'] === T_CONSTANT_ENCAPSED_STRING + ) { + $lineStart = $phpcsFile->findFirstOnLine([T_WHITESPACE, T_INLINE_HTML], ($lineStart - 1), true); + } + + $startColumn = $tokens[$lineStart]['column']; + $scopeStart = $tokens[$stackPtr]['scope_opener']; + $scopeEnd = $tokens[$stackPtr]['scope_closer']; + + // Check that the closing brace is on it's own line. + $lastContent = $phpcsFile->findPrevious([T_INLINE_HTML, T_WHITESPACE, T_OPEN_TAG], ($scopeEnd - 1), $scopeStart, true); + for ($lineStart = $scopeEnd; $tokens[$lineStart]['column'] > 1; $lineStart--); + + if ($tokens[$lastContent]['line'] === $tokens[$scopeEnd]['line'] + || ($tokens[$lineStart]['code'] === T_INLINE_HTML + && trim($tokens[$lineStart]['content']) !== '') + ) { + $error = 'Closing brace must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'ContentBefore'); + if ($fix === true) { + if ($tokens[$lastContent]['line'] === $tokens[$scopeEnd]['line']) { + $phpcsFile->fixer->addNewlineBefore($scopeEnd); + } else { + $phpcsFile->fixer->addNewlineBefore(($lineStart + 1)); + } + } + + return; + } + + // Check now that the closing brace is lined up correctly. + $lineStart = $phpcsFile->findFirstOnLine([T_WHITESPACE, T_INLINE_HTML], $scopeEnd, true); + $braceIndent = $tokens[$lineStart]['column']; + if ($tokens[$stackPtr]['code'] !== T_DEFAULT + && $tokens[$stackPtr]['code'] !== T_CASE + && $braceIndent !== $startColumn + ) { + $error = 'Closing brace indented incorrectly; expected %s spaces, found %s'; + $data = [ + ($startColumn - 1), + ($braceIndent - 1), + ]; + + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'Indent', $data); + if ($fix === true) { + $diff = ($startColumn - $braceIndent); + if ($diff > 0) { + $phpcsFile->fixer->addContentBefore($lineStart, str_repeat(' ', $diff)); + } else { + $phpcsFile->fixer->substrToken(($lineStart - 1), 0, $diff); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php new file mode 100644 index 00000000..2d800f05 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php @@ -0,0 +1,169 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ScopeKeywordSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $register = Tokens::$scopeModifiers; + $register[] = T_STATIC; + $register[] = T_READONLY; + return $register; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[($stackPtr + 1)]) === false) { + return; + } + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + if ($tokens[$stackPtr]['code'] === T_STATIC) { + if (($nextToken === false || $tokens[$nextToken]['code'] === T_DOUBLE_COLON) + || $tokens[$prevToken]['code'] === T_NEW + ) { + // Late static binding, e.g., static:: OR new static() usage or live coding. + return; + } + + if ($prevToken !== false + && $tokens[$prevToken]['code'] === T_TYPE_UNION + ) { + // Not a scope keyword, but a union return type. + return; + } + + if ($prevToken !== false + && $tokens[$prevToken]['code'] === T_NULLABLE + ) { + // Not a scope keyword, but a return type. + return; + } + + if ($prevToken !== false + && $tokens[$prevToken]['code'] === T_COLON + ) { + $prevPrevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), null, true); + if ($prevPrevToken !== false + && $tokens[$prevPrevToken]['code'] === T_CLOSE_PARENTHESIS + ) { + // Not a scope keyword, but a return type. + return; + } + } + }//end if + + if ($tokens[$prevToken]['code'] === T_AS) { + // Trait visibility change, e.g., "use HelloWorld { sayHello as private; }". + return; + } + + $isInFunctionDeclaration = false; + if (empty($tokens[$stackPtr]['nested_parenthesis']) === false) { + // Check if this is PHP 8.0 constructor property promotion. + // In that case, we can't have multi-property definitions. + $nestedParens = $tokens[$stackPtr]['nested_parenthesis']; + $lastCloseParens = end($nestedParens); + if (isset($tokens[$lastCloseParens]['parenthesis_owner']) === true + && $tokens[$tokens[$lastCloseParens]['parenthesis_owner']]['code'] === T_FUNCTION + ) { + $isInFunctionDeclaration = true; + } + } + + if ($nextToken !== false + && $tokens[$nextToken]['code'] === T_VARIABLE + && $isInFunctionDeclaration === false + ) { + $endOfStatement = $phpcsFile->findNext(T_SEMICOLON, ($nextToken + 1)); + if ($endOfStatement === false) { + // Live coding. + return; + } + + $multiProperty = $phpcsFile->findNext(T_VARIABLE, ($nextToken + 1), $endOfStatement); + if ($multiProperty !== false + && $tokens[$stackPtr]['line'] !== $tokens[$nextToken]['line'] + && $tokens[$nextToken]['line'] !== $tokens[$endOfStatement]['line'] + ) { + // Allow for multiple properties definitions to each be on their own line. + return; + } + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $spacing = 0; + } else { + if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $spacing = 'newline'; + } else { + $spacing = $tokens[($stackPtr + 1)]['length']; + } + } + + if ($spacing !== 1) { + $error = 'Scope keyword "%s" must be followed by a single space; found %s'; + $data = [ + $tokens[$stackPtr]['content'], + $spacing, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Incorrect', $data); + if ($fix === true) { + if ($spacing === 0) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } else { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($stackPtr + 2); $i < $phpcsFile->numTokens; $i++) { + if (isset($tokens[$i]) === false || $tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php new file mode 100644 index 00000000..bdcf9a5d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php @@ -0,0 +1,116 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SemicolonSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_SEMICOLON]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $prevType = $tokens[($stackPtr - 1)]['code']; + if (isset(Tokens::$emptyTokens[$prevType]) === false) { + return; + } + + $nonSpace = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 2), null, true); + + // Detect whether this is a semi-colon for a condition in a `for()` control structure. + $forCondition = false; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nestedParens = $tokens[$stackPtr]['nested_parenthesis']; + $closeParenthesis = end($nestedParens); + + if (isset($tokens[$closeParenthesis]['parenthesis_owner']) === true) { + $owner = $tokens[$closeParenthesis]['parenthesis_owner']; + + if ($tokens[$owner]['code'] === T_FOR) { + $forCondition = true; + $nonSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 2), null, true); + } + } + } + + if ($tokens[$nonSpace]['code'] === T_SEMICOLON + || ($forCondition === true && $nonSpace === $tokens[$owner]['parenthesis_opener']) + || (isset($tokens[$nonSpace]['scope_opener']) === true + && $tokens[$nonSpace]['scope_opener'] === $nonSpace) + ) { + // Empty statement. + return; + } + + $expected = $tokens[$nonSpace]['content'].';'; + $found = $phpcsFile->getTokensAsString($nonSpace, ($stackPtr - $nonSpace)).';'; + $found = str_replace("\n", '\n', $found); + $found = str_replace("\r", '\r', $found); + $found = str_replace("\t", '\t', $found); + $error = 'Space found before semicolon; expected "%s" but found "%s"'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Incorrect', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $i = ($stackPtr - 1); + while (($tokens[$i]['code'] === T_WHITESPACE) && ($i > $nonSpace)) { + $phpcsFile->fixer->replaceToken($i, ''); + $i--; + } + + $phpcsFile->fixer->addContent($nonSpace, ';'); + $phpcsFile->fixer->replaceToken($stackPtr, ''); + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php new file mode 100644 index 00000000..e99d829b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php @@ -0,0 +1,265 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class SuperfluousWhitespaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + 'CSS', + ]; + + /** + * If TRUE, whitespace rules are not checked for blank lines. + * + * Blank lines are those that contain only whitespace. + * + * @var boolean + */ + public $ignoreBlankLines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + T_CLOSE_TAG, + T_WHITESPACE, + T_COMMENT, + T_DOC_COMMENT_WHITESPACE, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_OPEN_TAG) { + /* + Check for start of file whitespace. + */ + + if ($phpcsFile->tokenizerType !== 'PHP') { + // The first token is always the open tag inserted when tokenized + // and the second token is always the first piece of content in + // the file. If the second token is whitespace, there was + // whitespace at the start of the file. + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + return; + } + + if ($phpcsFile->fixer->enabled === true) { + $stackPtr = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + } + } else { + // If it's the first token, then there is no space. + if ($stackPtr === 0) { + return; + } + + $beforeOpen = ''; + + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + // If we find something that isn't inline html then there is something previous in the file. + if ($tokens[$i]['type'] !== 'T_INLINE_HTML') { + return; + } + + $beforeOpen .= $tokens[$i]['content']; + } + + // If we have ended up with inline html make sure it isn't just whitespace. + if (preg_match('`^[\pZ\s]+$`u', $beforeOpen) !== 1) { + return; + } + }//end if + + $fix = $phpcsFile->addFixableError('Additional whitespace found at start of file', $stackPtr, 'StartFile'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = 0; $i < $stackPtr; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else if ($tokens[$stackPtr]['code'] === T_CLOSE_TAG) { + /* + Check for end of file whitespace. + */ + + if ($phpcsFile->tokenizerType === 'PHP') { + if (isset($tokens[($stackPtr + 1)]) === false) { + // The close PHP token is the last in the file. + return; + } + + $afterClose = ''; + + for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) { + // If we find something that isn't inline HTML then there + // is more to the file. + if ($tokens[$i]['type'] !== 'T_INLINE_HTML') { + return; + } + + $afterClose .= $tokens[$i]['content']; + } + + // If we have ended up with inline html make sure it isn't just whitespace. + if (preg_match('`^[\pZ\s]+$`u', $afterClose) !== 1) { + return; + } + } else { + // The last token is always the close tag inserted when tokenized + // and the second last token is always the last piece of content in + // the file. If the second last token is whitespace, there was + // whitespace at the end of the file. + $stackPtr--; + + // The pointer is now looking at the last content in the file and + // not the fake PHP end tag the tokenizer inserted. + if ($tokens[$stackPtr]['code'] !== T_WHITESPACE) { + return; + } + + // Allow a single newline at the end of the last line in the file. + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE + && $tokens[$stackPtr]['content'] === $phpcsFile->eolChar + ) { + return; + } + }//end if + + $fix = $phpcsFile->addFixableError('Additional whitespace found at end of file', $stackPtr, 'EndFile'); + if ($fix === true) { + if ($phpcsFile->tokenizerType !== 'PHP') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + $stackPtr = ($prev + 1); + } + + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + /* + Check for end of line whitespace. + */ + + // Ignore whitespace that is not at the end of a line. + if (isset($tokens[($stackPtr + 1)]['line']) === true + && $tokens[($stackPtr + 1)]['line'] === $tokens[$stackPtr]['line'] + ) { + return; + } + + // Ignore blank lines if required. + if ($this->ignoreBlankLines === true + && $tokens[$stackPtr]['code'] === T_WHITESPACE + && $tokens[($stackPtr - 1)]['line'] !== $tokens[$stackPtr]['line'] + ) { + return; + } + + $tokenContent = rtrim($tokens[$stackPtr]['content'], $phpcsFile->eolChar); + if (empty($tokenContent) === false) { + if ($tokenContent !== rtrim($tokenContent)) { + $fix = $phpcsFile->addFixableError('Whitespace found at end of line', $stackPtr, 'EndLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, rtrim($tokenContent).$phpcsFile->eolChar); + } + } + } else if ($tokens[($stackPtr - 1)]['content'] !== rtrim($tokens[($stackPtr - 1)]['content']) + && $tokens[($stackPtr - 1)]['line'] === $tokens[$stackPtr]['line'] + ) { + $fix = $phpcsFile->addFixableError('Whitespace found at end of line', ($stackPtr - 1), 'EndLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), rtrim($tokens[($stackPtr - 1)]['content'])); + } + } + + /* + Check for multiple blank lines in a function. + */ + + if (($phpcsFile->hasCondition($stackPtr, [T_FUNCTION, T_CLOSURE]) === true) + && $tokens[($stackPtr - 1)]['line'] < $tokens[$stackPtr]['line'] + && $tokens[($stackPtr - 2)]['line'] === $tokens[($stackPtr - 1)]['line'] + ) { + // Properties and functions in nested classes have their own rules for spacing. + $conditions = $tokens[$stackPtr]['conditions']; + $deepestScope = end($conditions); + if ($deepestScope === T_ANON_CLASS) { + return; + } + + // This is an empty line and the line before this one is not + // empty, so this could be the start of a multiple empty + // line block. + $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr, null, true); + $lines = ($tokens[$next]['line'] - $tokens[$stackPtr]['line']); + if ($lines > 1) { + $error = 'Functions must not contain multiple empty lines in a row; found %s empty lines'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'EmptyLines', [$lines]); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $i = $stackPtr; + while ($tokens[$i]['line'] !== $tokens[$next]['line']) { + $phpcsFile->fixer->replaceToken($i, ''); + $i++; + } + + $phpcsFile->fixer->addNewlineBefore($i); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc new file mode 100644 index 00000000..8ffc868a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc @@ -0,0 +1,31 @@ + 'bar', + 'bar' => 'foo', +]; + +if ($foo) {} +[$a, $b] = $c; + +echo foo()[ 1 ]; + +echo $this->addedCustomFunctions['nonce']; +echo $this->deprecated_functions[ $function_name ]['version']; + +echo [ 1,2,3 ][0]; +echo [ 1,2,3 ][ 0 ]; +echo 'PHP'[ 0 ]; + +$array = []; +$var = $var[$var[$var]]]; // Syntax error +$var = $var[$var[$var]; // Syntax error + +$myArray[ /* key start */'key'] = $value; +$myArray[ /* key start */'key'/* key end */ ] = $value; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc.fixed new file mode 100644 index 00000000..41d66409 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc.fixed @@ -0,0 +1,31 @@ + 'bar', + 'bar' => 'foo', +]; + +if ($foo) {} +[$a, $b] = $c; + +echo foo()[1]; + +echo $this->addedCustomFunctions['nonce']; +echo $this->deprecated_functions[$function_name]['version']; + +echo [ 1,2,3 ][0]; +echo [ 1,2,3 ][0]; +echo 'PHP'[0]; + +$array = []; +$var = $var[$var[$var]]]; // Syntax error +$var = $var[$var[$var]; // Syntax error + +$myArray[/* key start */'key'] = $value; +$myArray[/* key start */'key'/* key end */] = $value; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.php new file mode 100644 index 00000000..304a0d42 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Arrays; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ArrayBracketSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 3, + 7 => 3, + 17 => 2, + 20 => 2, + 23 => 2, + 24 => 2, + 30 => 1, + 31 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc new file mode 100644 index 00000000..2774660c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc @@ -0,0 +1,488 @@ + 1, + ); +} + +class TestClass +{ + public $good = array( + 'width' => '', + 'height' => '', + ); + + private $_bad = Array( + 'width' => '', + 'height' => '' + ); + + + public function test() + { + $truck = array( + 'width' => '', + 'height' => '', + ); + + $plane = Array( + 'width' => '', + 'height' => '', + ); + + $car = array( + 'width' => '', + 'height' => '', + ); + + $bus = array( + 'width' => '', + 'height' => '' + ); + + $train = array ( + TRUE, + FALSE, + 'aaa' + ); + + $inline = array('aaa', 'bbb', 'ccc'); + $inline = array('aaa'); + $inline = Array('aaa'); + + $bigone = array( + 'name' => 'bigone', + 'children' => Array( + '1a' => 'child', + '11b' => 'child', + '111c' => 'child', + 'children' => Array( + 'child' => 'aaa', + ), + ), + 'short_name' => 'big' + ); + } + +}//end class + +$value = array ( ); +$value = array( ); +$value = array('1'=>$one, '2' => $two, '3'=> $three, '4' =>$four); +$value = array('1'=>$one); + +if (in_array('1', array('1','2','3')) === TRUE) { + $value = in_array('1', array('1' , '2', '3','4')); +} + +$value = array( + '1'=> TRUE, + FALSE, + '3' => 'aaa',); + +$value = array( + '1'=> TRUE, + FALSE, + ); + +$value = array( + TRUE, + '1' => FALSE, + ); + +$value = array(1, + 2 , + 3 , + ); + +$value = array(1 => $one, + 2 => $two , + 3 => $three , + ); + +$value = array( + 'tag' => $tag, + 'space' => $this->_getIndentation($tag, $tagElement), + ); + +$expected = array( + array( + '1' => 1, + '1' => 2, + ), + ); + +$expected = array( + array( + '1' => 1, + '1' => 2 + ) + ); + +// Space in second arg. +$args = array( + '"'.$this->id.'"', + (int) $hasSessions, + ); + +// No errors. +$paths = array( + Init::ROOT_DIR.'/Systems' => 'Systems', + Init::ROOT_DIR.'/Installer' => 'Systems', + ); + +$x = array( + ); + +$x = array('test' + ); +$x = array('test', + ); +$x = array('name' => 'test', + ); + +$x = array( + $x, + ); + +$func = array( + $x, + 'get'.$x.'Replacement' + ); + +$array = array( + 'input_one' => 'one', + 'inputTwo' => 'two', + 'input_3' => 3, + ); + +$array = array( + 'input_one', + 'inputTwo', + 'input_3', + ); + +// Malformed +$foo = array(1 +, 2); + +$listItems[$aliasPath] = array('itemContent' => implode('
    ', $aliases)); + +$listItems[$aliasPath] = array( + 'itemContent' => implode('
    ', $aliases) + ); + +$x = array + ( + $x, + $y, + ); + +$x = array +( + $x, + $y, + ); + +$x = array( + + $x, + $y, + ); + +$test = array( + 'test' => TestFunction::blah( + $value1, + $value2 + ), + ); + +$c = array('a' => 1,); + +function b() +{ + $a = array( + 'a' => a('a'), + + ); + +} + +$foo = Array('[',']',':',"\n","\r"); +$bar = Array('[',']',':',' ',' '); + +function foo() +{ + return array($a, $b->screen); +} + +$array = array( + 'name' => 'contactSubject', + 'required' => TRUE, + 'validators' => array( + new \Zend\Validator\InArray(array('haystack' => array_keys($aSubjects))), + ), + ); + +$var = array( + 'ViewHelper', + array('Foo'), + 'Errors', + ); + +$data = array( + 'first', + 'second', + 'third', + // Add more here + ); + +$data = array( + 'first', + 'second', + //'third', + ); + +$data = array( + 'first', + 'second' + //'third', + ); + +$foo = array( + $this->getViewName() . '.id' => 'value', + $this->getViewName() . '.title' => 'value', + ); + +$foo = array( + $this->getViewName() . '.id', + $this->getViewName() . '.title', + ); + +$weightings = array( + T_CLOSURE => 100, + + /* + Conditions. + */ + + T_WHILE => 50, + + /* + Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + + T_BOOLEAN_AND => 5, + + /* + Equality. + */ + + T_IS_GREATER_OR_EQUAL => 5, + ); + +foreach (array( + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ) as $key => $value) { +} + +$ids = array( + '1', // Foo. + '13', // Bar. + ); + +array( + 'key1' => function($bar) { + return $bar; + }, + 'key2' => function($foo) { + return $foo; + }, + 'key3' => function($bar) { + return $bar; + } +); + +array( + 'key1' => array( + '1', + '2', + ) +); + +$var = array( + 'tab_template' => ' +
  • %s
  • ', + 'panel_template' => ' +
    + %s +
    ', + ); + +function test() : array +{ + return []; +} + +$fields = array( + 'id' => array('type' => 'INT'), + 'value' => array('type' => 'VARCHAR')); + +get_current_screen()->add_help_tab( array( + 'id' => << false); + +$x = array( + 'xxxx' => array('aaaaaaaaaa' => 'ccccccccccc', + 'bbbbbbbb' => false), +); + +$foo = array + ('foo' => array + ('bar1' => 1 + ,'bar2' => 1 + ,'bar3' => 1 + ,'bar4' => 1 + ,'bar5' => 1 + ) + ); + +$foo = array( + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], array('notverified', 'unverified'), true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), + ); + +$foo = foo( + array( + // comment + ) +); + +$foo = array( + << lorem( + 1 + ), 2 => 2, +); + +$foo = array( + 'тип' => 'авто', + 'цвет' => 'синий', + ); + +$paths = array( + Init::ROOT_DIR.'/тип' => 'авто', + Init::ROOT_DIR.'/цвет' => 'синий', + ); + +$foo = array(<< fn() => return 1, + 'bb' => fn() => return 2, + 'ccc' => ( true ) ? + fn() => return 1 : + fn() => return 2, + ); + +$array = array( + 1 => '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', + ); + +$foo = array( + $this->fn => 'value', + $foo->fn => 'value', + ); + +array($a, $b, +$c); + +array('a' => $a, 'b' => $b, +'c' => $c); + +array( + static function() { + return null; + }, + (array) array(), + (bool) array(), + (double) array(), + (int) array(), + (object) array(), + (string) array(), + (unset) array(), +); + +array( + 'foo', + 'bar' + // This is a non-fixable error. + , +); + +yield array( + static fn () : string => '', +); + +yield array( + static fn () : string => '', + ); + +$foo = [ + 'foo' => match ($anything) { + 'foo' => 'bar', + default => null, + }, + ]; + +// Intentional syntax error. +$a = array( + 'a' => + ); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc.fixed new file mode 100644 index 00000000..b4520064 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc.fixed @@ -0,0 +1,524 @@ + 1); +} + +class TestClass +{ + public $good = array( + 'width' => '', + 'height' => '', + ); + + private $_bad = array( + 'width' => '', + 'height' => '', + ); + + + public function test() + { + $truck = array( + 'width' => '', + 'height' => '', + ); + + $plane = array( + 'width' => '', + 'height' => '', + ); + + $car = array( + 'width' => '', + 'height' => '', + ); + + $bus = array( + 'width' => '', + 'height' => '', + ); + + $train = array( + TRUE, + FALSE, + 'aaa', + ); + + $inline = array( + 'aaa', + 'bbb', + 'ccc', + ); + $inline = array('aaa'); + $inline = array('aaa'); + + $bigone = array( + 'name' => 'bigone', + 'children' => array( + '1a' => 'child', + '11b' => 'child', + '111c' => 'child', + 'children' => array('child' => 'aaa'), + ), + 'short_name' => 'big', + ); + } + +}//end class + +$value = array(); +$value = array(); +$value = array( + '1' => $one, + '2' => $two, + '3' => $three, + '4' => $four, + ); +$value = array('1' => $one); + +if (in_array('1', array('1', '2', '3')) === TRUE) { + $value = in_array('1', array('1', '2', '3', '4')); +} + +$value = array( + '1'=> TRUE, + FALSE, + '3' => 'aaa', + ); + +$value = array( + '1'=> TRUE, + FALSE, + ); + +$value = array( + TRUE, + '1' => FALSE, + ); + +$value = array( + 1, + 2, + 3, + ); + +$value = array( + 1 => $one, + 2 => $two, + 3 => $three, + ); + +$value = array( + 'tag' => $tag, + 'space' => $this->_getIndentation($tag, $tagElement), + ); + +$expected = array( + array( + '1' => 1, + '1' => 2, + ), + ); + +$expected = array( + array( + '1' => 1, + '1' => 2, + ), + ); + +// Space in second arg. +$args = array( + '"'.$this->id.'"', + (int) $hasSessions, + ); + +// No errors. +$paths = array( + Init::ROOT_DIR.'/Systems' => 'Systems', + Init::ROOT_DIR.'/Installer' => 'Systems', + ); + +$x = array(); + +$x = array('test'); +$x = array('test'); +$x = array('name' => 'test'); + +$x = array($x); + +$func = array( + $x, + 'get'.$x.'Replacement', + ); + +$array = array( + 'input_one' => 'one', + 'inputTwo' => 'two', + 'input_3' => 3, + ); + +$array = array( + 'input_one', + 'inputTwo', + 'input_3', + ); + +// Malformed +$foo = array( + 1, + 2, + ); + +$listItems[$aliasPath] = array('itemContent' => implode('
    ', $aliases)); + +$listItems[$aliasPath] = array( + 'itemContent' => implode('
    ', $aliases), + ); + +$x = array( + $x, + $y, + ); + +$x = array( + $x, + $y, + ); + +$x = array( + + $x, + $y, + ); + +$test = array( + 'test' => TestFunction::blah( + $value1, + $value2 + ), + ); + +$c = array('a' => 1); + +function b() +{ + $a = array( + 'a' => a('a'), + + ); + +} + +$foo = array( + '[', + ']', + ':', + "\n", + "\r", + ); +$bar = array( + '[', + ']', + ':', + ' ', + ' ', + ); + +function foo() +{ + return array( + $a, + $b->screen, + ); +} + +$array = array( + 'name' => 'contactSubject', + 'required' => TRUE, + 'validators' => array( + new \Zend\Validator\InArray(array('haystack' => array_keys($aSubjects))), + ), + ); + +$var = array( + 'ViewHelper', + array('Foo'), + 'Errors', + ); + +$data = array( + 'first', + 'second', + 'third', + // Add more here + ); + +$data = array( + 'first', + 'second', + //'third', + ); + +$data = array( + 'first', + 'second', + //'third', + ); + +$foo = array( + $this->getViewName() . '.id' => 'value', + $this->getViewName() . '.title' => 'value', + ); + +$foo = array( + $this->getViewName() . '.id', + $this->getViewName() . '.title', + ); + +$weightings = array( + T_CLOSURE => 100, + + /* + Conditions. + */ + + T_WHILE => 50, + + /* + Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + + T_BOOLEAN_AND => 5, + + /* + Equality. + */ + + T_IS_GREATER_OR_EQUAL => 5, + ); + +foreach (array( + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ) as $key => $value) { +} + +$ids = array( + '1', // Foo. + '13', // Bar. + ); + +array( + 'key1' => function($bar) { + return $bar; + }, + 'key2' => function($foo) { + return $foo; + }, + 'key3' => function($bar) { + return $bar; + }, +); + +array( + 'key1' => array( + '1', + '2', + ), +); + +$var = array( + 'tab_template' => ' +
  • %s
  • ', + 'panel_template' => ' +
    + %s +
    ', + ); + +function test() : array +{ + return []; +} + +$fields = array( + 'id' => array('type' => 'INT'), + 'value' => array('type' => 'VARCHAR'), + ); + +get_current_screen()->add_help_tab( array( + 'id' => << false); + +$x = array( + 'xxxx' => array( + 'aaaaaaaaaa' => 'ccccccccccc', + 'bbbbbbbb' => false, + ), + ); + +$foo = array( + 'foo' => array( + 'bar1' => 1, + 'bar2' => 1, + 'bar3' => 1, + 'bar4' => 1, + 'bar5' => 1, + ), + ); + +$foo = array( + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], array('notverified', 'unverified'), true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), + ); + +$foo = foo( + array( + // comment + ) +); + +$foo = array( + << lorem( + 1 + ), + 2 => 2, +); + +$foo = array( + 'тип' => 'авто', + 'цвет' => 'синий', + ); + +$paths = array( + Init::ROOT_DIR.'/тип' => 'авто', + Init::ROOT_DIR.'/цвет' => 'синий', + ); + +$foo = array(<< fn() => return 1, + 'bb' => fn() => return 2, + 'ccc' => ( true ) ? + fn() => return 1 : + fn() => return 2, + ); + +$array = array( + 1 => '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', + ); + +$foo = array( + $this->fn => 'value', + $foo->fn => 'value', + ); + +array( + $a, + $b, + $c, +); + +array( + 'a' => $a, + 'b' => $b, + 'c' => $c, +); + +array( + static function() { + return null; + }, + (array) array(), + (bool) array(), + (double) array(), + (int) array(), + (object) array(), + (string) array(), + (unset) array(), +); + +array( + 'foo', + 'bar' + // This is a non-fixable error. + , +); + +yield array( + static fn () : string => '', + ); + +yield array( + static fn () : string => '', + ); + +$foo = [ + 'foo' => match ($anything) { + 'foo' => 'bar', + default => null, + }, + ]; + +// Intentional syntax error. +$a = array( + 'a' => + ); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc new file mode 100644 index 00000000..621970fa --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc @@ -0,0 +1,470 @@ + 1, + ]; +} + +class TestClass +{ + public $good = [ + 'width' => '', + 'height' => '', + ]; + + private $_bad = [ + 'width' => '', + 'height' => '' + ]; + + + public function test() + { + $truck = [ + 'width' => '', + 'height' => '', + ]; + + $plane = [ + 'width' => '', + 'height' => '', + ]; + + $car = [ + 'width' => '', + 'height' => '', + ]; + + $bus = [ + 'width' => '', + 'height' => '' + ]; + + $train = [ + TRUE, + FALSE, + 'aaa' + ]; + + $inline = ['aaa', 'bbb', 'ccc']; + $inline = ['aaa']; + $inline = ['aaa']; + + $bigone = [ + 'name' => 'bigone', + 'children' => [ + '1a' => 'child', + '11b' => 'child', + '111c' => 'child', + 'children' => [ + 'child' => 'aaa', + ], + ], + 'short_name' => 'big' + ]; + } + +}//end class + +$value = [ ]; +$value = [ ]; +$value = ['1'=>$one, '2' => $two, '3'=> $three, '4' =>$four]; +$value = ['1'=>$one]; + +if (in_array('1', ['1','2','3']) === TRUE) { + $value = in_array('1', ['1' , '2', '3','4']); +} + +$value = [ + '1'=> TRUE, + FALSE, + '3' => 'aaa',]; + +$value = [ + '1'=> TRUE, + FALSE, + ]; + +$value = [ + TRUE, + '1' => FALSE, + ]; + +$value = [1, + 2 , + 3 , + ]; + +$value = [1 => $one, + 2 => $two , + 3 => $three , + ]; + +$value = [ + 'tag' => $tag, + 'space' => $this->_getIndentation($tag, $tagElement), + ]; + +$expected = [ + [ + '1' => 1, + '1' => 2, + ], + ]; + +$expected = [ + [ + '1' => 1, + '1' => 2 + ] + ]; + +// Space in second arg. +$args = [ + '"'.$this->id.'"', + (int) $hasSessions, + ]; + +// No errors. +$paths = [ + Init::ROOT_DIR.'/Systems' => 'Systems', + Init::ROOT_DIR.'/Installer' => 'Systems', + ]; + +$x = [ + ]; + +$x = ['test' + ]; +$x = ['test', + ]; +$x = ['name' => 'test', + ]; + +$x = [ + $x, + ]; + +$func = [ + $x, + 'get'.$x.'Replacement' + ]; + +$array = [ + 'input_one' => 'one', + 'inputTwo' => 'two', + 'input_3' => 3, + ]; + +$array = [ + 'input_one', + 'inputTwo', + 'input_3', + ]; + +// Malformed +$foo = [1 +, 2]; + +$listItems[$aliasPath] = ['itemContent' => implode('
    ', $aliases)]; + +$listItems[$aliasPath] = [ + 'itemContent' => implode('
    ', $aliases) + ]; + +$x = + [ + $x, + $y, + ]; + +$x = +[ + $x, + $y, + ]; + +$x = [ + + $x, + $y, + ]; + +$test = [ + 'test' => TestFunction::blah( + $value1, + $value2 + ), + ]; + +$c = ['a' => 1,]; +$c->{$var}[ ] = 2; + +$foo = ['[',']',':',"\n","\r"]; +$bar = ['[',']',':',' ',' ']; + +function foo() +{ + return [$a, $b->screen]; +} + +$array = [ + 'name' => 'contactSubject', + 'required' => TRUE, + 'validators' => [ + new \Zend\Validator\InArray(['haystack' => array_keys($aSubjects)]), + ], + ]; + +$var = [ + 'ViewHelper', + ['Foo'], + 'Errors', + ]; + +$data = [ + 'first', + 'second', + 'third', + // Add more here + ]; + +$data = [ + 'first', + 'second', + //'third', + ]; + +$data = [ + 'first', + 'second' + //'third', + ]; + +$foo = [ + $this->getViewName() . '.id' => 'value', + $this->getViewName() . '.title' => 'value', + ]; + +$foo = [ + $this->getViewName() . '.id', + $this->getViewName() . '.title', + ]; + +$weightings = [ + T_CLOSURE => 100, + + /* + Conditions. + */ + + T_WHILE => 50, + + /* + Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + + T_BOOLEAN_AND => 5, + + /* + Equality. + */ + + T_IS_GREATER_OR_EQUAL => 5, + ]; + +foreach ([ + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ] as $key => $value) { +} + +$ids = [ + '1', // Foo. + '13', // Bar. + ]; + +[ + 'key1' => function($bar) { + return $bar; + }, + 'key2' => function($foo) { + return $foo; + }, + 'key3' => function($bar) { + return $bar; + } +]; + +[ + 'key1' => [ + '1', + '2', + ] +]; + +$var = [ + 'tab_template' => ' +
  • %s
  • ', + 'panel_template' => ' +
    + %s +
    ', + ]; + +function test() : array +{ + return []; +} + +$fields = [ + 'id' => ['type' => 'INT'], + 'value' => ['type' => 'VARCHAR']]; + +get_current_screen()->add_help_tab( [ + 'id' => << false]; + +$x = [ + 'xxxx' => ['aaaaaaaaaa' => 'ccccccccccc', + 'bbbbbbbb' => false], +]; + +$foo = ['foo' => ['bar1' => 1 + ,'bar2' => 1 + ,'bar3' => 1 + ,'bar4' => 1 + ,'bar5' => 1 + ] + ]; + +$foo = [ + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], ['notverified', 'unverified'], true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), + ]; + + +$foo = foo( + [ + // comment + ] +); + +$foo = [ + << lorem( + 1 + ), 2 => 2, +]; + +$foo = [ + 'тип' => 'авто', + 'цвет' => 'синий', + ]; + +$paths = [ + Init::ROOT_DIR.'/тип' => 'авто', + Init::ROOT_DIR.'/цвет' => 'синий', + ]; + +$foo = [<< fn() => return 1, + 'bb' => fn() => return 2, + 'ccc' => ( true ) ? + fn() => return 1 : + fn() => return 2, + ]; + +$array = [ + 1 => '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', + ]; + +$foo = [ + $this->fn => 'value', + $foo->fn => 'value', + ]; + +[$a, $b, +$c]; + +['a' => $a, 'b' => $b, +'c' => $c]; + +[ + static function() { + return null; + }, + (array) [], + (bool) [], + (double) [], + (int) [], + (object) [], + (string) [], + (unset) [], +]; + +[ + 'foo', + 'bar' + // This is a non-fixable error. + , +]; + +yield [ + static fn () : string => '', +]; + +yield [ + static fn () : string => '', + ]; + +// Intentional syntax error. +$a = [ + 'a' => + ]; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc.fixed new file mode 100644 index 00000000..efe4c450 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc.fixed @@ -0,0 +1,504 @@ + 1]; +} + +class TestClass +{ + public $good = [ + 'width' => '', + 'height' => '', + ]; + + private $_bad = [ + 'width' => '', + 'height' => '', + ]; + + + public function test() + { + $truck = [ + 'width' => '', + 'height' => '', + ]; + + $plane = [ + 'width' => '', + 'height' => '', + ]; + + $car = [ + 'width' => '', + 'height' => '', + ]; + + $bus = [ + 'width' => '', + 'height' => '', + ]; + + $train = [ + TRUE, + FALSE, + 'aaa', + ]; + + $inline = [ + 'aaa', + 'bbb', + 'ccc', + ]; + $inline = ['aaa']; + $inline = ['aaa']; + + $bigone = [ + 'name' => 'bigone', + 'children' => [ + '1a' => 'child', + '11b' => 'child', + '111c' => 'child', + 'children' => ['child' => 'aaa'], + ], + 'short_name' => 'big', + ]; + } + +}//end class + +$value = []; +$value = []; +$value = [ + '1' => $one, + '2' => $two, + '3' => $three, + '4' => $four, + ]; +$value = ['1' => $one]; + +if (in_array('1', ['1', '2', '3']) === TRUE) { + $value = in_array('1', ['1', '2', '3', '4']); +} + +$value = [ + '1'=> TRUE, + FALSE, + '3' => 'aaa', + ]; + +$value = [ + '1'=> TRUE, + FALSE, + ]; + +$value = [ + TRUE, + '1' => FALSE, + ]; + +$value = [ + 1, + 2, + 3, + ]; + +$value = [ + 1 => $one, + 2 => $two, + 3 => $three, + ]; + +$value = [ + 'tag' => $tag, + 'space' => $this->_getIndentation($tag, $tagElement), + ]; + +$expected = [ + [ + '1' => 1, + '1' => 2, + ], + ]; + +$expected = [ + [ + '1' => 1, + '1' => 2, + ], + ]; + +// Space in second arg. +$args = [ + '"'.$this->id.'"', + (int) $hasSessions, + ]; + +// No errors. +$paths = [ + Init::ROOT_DIR.'/Systems' => 'Systems', + Init::ROOT_DIR.'/Installer' => 'Systems', + ]; + +$x = []; + +$x = ['test']; +$x = ['test']; +$x = ['name' => 'test']; + +$x = [$x]; + +$func = [ + $x, + 'get'.$x.'Replacement', + ]; + +$array = [ + 'input_one' => 'one', + 'inputTwo' => 'two', + 'input_3' => 3, + ]; + +$array = [ + 'input_one', + 'inputTwo', + 'input_3', + ]; + +// Malformed +$foo = [ + 1, + 2, + ]; + +$listItems[$aliasPath] = ['itemContent' => implode('
    ', $aliases)]; + +$listItems[$aliasPath] = [ + 'itemContent' => implode('
    ', $aliases), + ]; + +$x = + [ + $x, + $y, + ]; + +$x = +[ + $x, + $y, +]; + +$x = [ + + $x, + $y, + ]; + +$test = [ + 'test' => TestFunction::blah( + $value1, + $value2 + ), + ]; + +$c = ['a' => 1]; +$c->{$var}[ ] = 2; + +$foo = [ + '[', + ']', + ':', + "\n", + "\r", + ]; +$bar = [ + '[', + ']', + ':', + ' ', + ' ', + ]; + +function foo() +{ + return [ + $a, + $b->screen, + ]; +} + +$array = [ + 'name' => 'contactSubject', + 'required' => TRUE, + 'validators' => [ + new \Zend\Validator\InArray(['haystack' => array_keys($aSubjects)]), + ], + ]; + +$var = [ + 'ViewHelper', + ['Foo'], + 'Errors', + ]; + +$data = [ + 'first', + 'second', + 'third', + // Add more here + ]; + +$data = [ + 'first', + 'second', + //'third', + ]; + +$data = [ + 'first', + 'second', + //'third', + ]; + +$foo = [ + $this->getViewName() . '.id' => 'value', + $this->getViewName() . '.title' => 'value', + ]; + +$foo = [ + $this->getViewName() . '.id', + $this->getViewName() . '.title', + ]; + +$weightings = [ + T_CLOSURE => 100, + + /* + Conditions. + */ + + T_WHILE => 50, + + /* + Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + + T_BOOLEAN_AND => 5, + + /* + Equality. + */ + + T_IS_GREATER_OR_EQUAL => 5, + ]; + +foreach ([ + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ] as $key => $value) { +} + +$ids = [ + '1', // Foo. + '13', // Bar. + ]; + +[ + 'key1' => function($bar) { + return $bar; + }, + 'key2' => function($foo) { + return $foo; + }, + 'key3' => function($bar) { + return $bar; + }, +]; + +[ + 'key1' => [ + '1', + '2', + ], +]; + +$var = [ + 'tab_template' => ' +
  • %s
  • ', + 'panel_template' => ' +
    + %s +
    ', + ]; + +function test() : array +{ + return []; +} + +$fields = [ + 'id' => ['type' => 'INT'], + 'value' => ['type' => 'VARCHAR'], + ]; + +get_current_screen()->add_help_tab( [ + 'id' => << false]; + +$x = [ + 'xxxx' => [ + 'aaaaaaaaaa' => 'ccccccccccc', + 'bbbbbbbb' => false, + ], + ]; + +$foo = [ + 'foo' => [ + 'bar1' => 1, + 'bar2' => 1, + 'bar3' => 1, + 'bar4' => 1, + 'bar5' => 1, + ], + ]; + +$foo = [ + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], ['notverified', 'unverified'], true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), + ]; + + +$foo = foo( + [ + // comment + ] +); + +$foo = [ + << lorem( + 1 + ), + 2 => 2, +]; + +$foo = [ + 'тип' => 'авто', + 'цвет' => 'синий', + ]; + +$paths = [ + Init::ROOT_DIR.'/тип' => 'авто', + Init::ROOT_DIR.'/цвет' => 'синий', + ]; + +$foo = [<< fn() => return 1, + 'bb' => fn() => return 2, + 'ccc' => ( true ) ? + fn() => return 1 : + fn() => return 2, + ]; + +$array = [ + 1 => '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', + ]; + +$foo = [ + $this->fn => 'value', + $foo->fn => 'value', + ]; + +[ + $a, + $b, + $c, +]; + +[ + 'a' => $a, + 'b' => $b, + 'c' => $c, +]; + +[ + static function() { + return null; + }, + (array) [], + (bool) [], + (double) [], + (int) [], + (object) [], + (string) [], + (unset) [], +]; + +[ + 'foo', + 'bar' + // This is a non-fixable error. + , +]; + +yield [ + static fn () : string => '', + ]; + +yield [ + static fn () : string => '', + ]; + +// Intentional syntax error. +$a = [ + 'a' => + ]; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.php new file mode 100644 index 00000000..15ce0746 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.php @@ -0,0 +1,236 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Arrays; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ArrayDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ArrayDeclarationUnitTest.1.inc': + return [ + 2 => 1, + 8 => 2, + 10 => 2, + 22 => 1, + 23 => 2, + 24 => 2, + 25 => 1, + 31 => 2, + 35 => 1, + 36 => 2, + 41 => 1, + 46 => 1, + 47 => 1, + 50 => 1, + 51 => 1, + 53 => 1, + 56 => 1, + 58 => 1, + 61 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 66 => 3, + 70 => 1, + 76 => 2, + 77 => 1, + 78 => 7, + 79 => 2, + 81 => 2, + 82 => 4, + 87 => 1, + 88 => 1, + 92 => 1, + 97 => 1, + 100 => 1, + 101 => 1, + 102 => 1, + 105 => 1, + 106 => 1, + 107 => 1, + 125 => 1, + 126 => 1, + 141 => 1, + 144 => 1, + 146 => 1, + 148 => 1, + 151 => 1, + 157 => 1, + 173 => 1, + 174 => 3, + 179 => 1, + 182 => 1, + 188 => 1, + 207 => 1, + 212 => 2, + 214 => 1, + 218 => 2, + 219 => 2, + 223 => 1, + 255 => 1, + 294 => 1, + 295 => 1, + 296 => 1, + 311 => 1, + 317 => 1, + 339 => 2, + 348 => 2, + 352 => 2, + 355 => 3, + 358 => 3, + 359 => 2, + 360 => 1, + 362 => 1, + 363 => 2, + 364 => 1, + 365 => 2, + 366 => 2, + 367 => 2, + 368 => 2, + 369 => 1, + 370 => 1, + 383 => 1, + 394 => 1, + 400 => 1, + 406 => 1, + 441 => 1, + 444 => 2, + 445 => 2, + 447 => 2, + 448 => 3, + 467 => 1, + 471 => 1, + 472 => 1, + ]; + case 'ArrayDeclarationUnitTest.2.inc': + return [ + 2 => 1, + 10 => 1, + 23 => 2, + 24 => 2, + 25 => 1, + 31 => 2, + 36 => 2, + 41 => 1, + 46 => 1, + 47 => 1, + 51 => 1, + 53 => 1, + 56 => 1, + 61 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 66 => 2, + 70 => 1, + 76 => 1, + 77 => 1, + 78 => 7, + 79 => 2, + 81 => 2, + 82 => 4, + 87 => 1, + 88 => 1, + 92 => 1, + 97 => 1, + 100 => 1, + 101 => 1, + 102 => 1, + 105 => 1, + 106 => 1, + 107 => 1, + 125 => 1, + 126 => 1, + 141 => 1, + 144 => 1, + 146 => 1, + 148 => 1, + 151 => 1, + 157 => 1, + 173 => 1, + 174 => 3, + 179 => 1, + 190 => 1, + 191 => 1, + 192 => 1, + 207 => 1, + 210 => 1, + 211 => 1, + 215 => 1, + 247 => 1, + 286 => 1, + 287 => 1, + 288 => 1, + 303 => 1, + 309 => 1, + 331 => 2, + 345 => 3, + 348 => 3, + 349 => 2, + 350 => 1, + 352 => 2, + 353 => 2, + 354 => 2, + 355 => 2, + 356 => 2, + 357 => 1, + 358 => 1, + 372 => 1, + 383 => 1, + 389 => 1, + 395 => 1, + 430 => 1, + 433 => 2, + 434 => 2, + 436 => 2, + 437 => 3, + 456 => 1, + 460 => 1, + 461 => 1, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css new file mode 100644 index 00000000..39abce23 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css @@ -0,0 +1,81 @@ +.my-style { +} + + +.my-style { +} + +/* Comment */ + +.my-style { +} + + +/* Comment */ + +.my-style { + float: left; + +} + +.AssetLineageWidgetType-item { + color: #CCC; +} + +/*.AssetLineageWidgetType-item2 .selected, +.AssetLineageWidgetType-item .selected { +}*/ + +.AssetLineageWidgetType-item.selected { +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } +} + +.GUITextBox.container:after {} + +@media screen and (max-device-width: 769px) { + .no-blank-line-after { + } + .no-blank-line-after-second-def { + } .my-style { + } + + .no-blank-line-and-trailing-comment { + } /* end long class */ + .too-many-blank-lines-and-trailing-comment-extra-whitespace-after-brace { + } /* end long class */ + + + + .has-blank-line-and-trailing-comment { + } /* end long class */ + + .no-blank-line-and-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + .too-many-blank-lines-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + + + + .has-blank-line-and-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%;}} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css.fixed new file mode 100644 index 00000000..ca77e83b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css.fixed @@ -0,0 +1,85 @@ +.my-style { +} + +.my-style { +} + +/* Comment */ + +.my-style { +} + +/* Comment */ + +.my-style { + float: left; + +} + +.AssetLineageWidgetType-item { + color: #CCC; +} + +/*.AssetLineageWidgetType-item2 .selected, +.AssetLineageWidgetType-item .selected { +}*/ + +.AssetLineageWidgetType-item.selected { +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +.GUITextBox.container:after { +} + +@media screen and (max-device-width: 769px) { + .no-blank-line-after { + } + + .no-blank-line-after-second-def { + } + +.my-style { + } + + .no-blank-line-and-trailing-comment { + } /* end long class */ + + .too-many-blank-lines-and-trailing-comment-extra-whitespace-after-brace { + } /* end long class */ + + .has-blank-line-and-trailing-comment { + } /* end long class */ + + .no-blank-line-and-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + + .too-many-blank-lines-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + + .has-blank-line-and-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; +} + +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.php new file mode 100644 index 00000000..528fcfd6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassDefinitionClosingBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 11 => 1, + 44 => 1, + 47 => 1, + 51 => 1, + 53 => 1, + 57 => 1, + 59 => 1, + 67 => 1, + 69 => 1, + 81 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.css new file mode 100644 index 00000000..6496cb83 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.css @@ -0,0 +1,66 @@ +.AssetListingEditWidgetType-BottomPanel select, +#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew { + float: left; +} + +.AssetListingEditWidgetType-BottomPanel select, + +#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew { + float: left; +} + +.AssetListingEditWidgetType-BottomPanel select, +/*.AssetListingEditWidgetType-BottomPanel ul,*/ +#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew { + float: left; +} + +.AssetListingEditWidgetType-BottomPanel select, + +.AssetListingEditWidgetType-BottomPanel ul, +#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew { + float: left; +} + +#SuperUsersSystemConfigScreen-table { + display: block; + left: 50%; + margin-left: -500px; + margin-top: 180px; + position: relative; + width: 1000px; +} + +/** + * More styles below here. + */ + +td.TableWidgetType-header.TableWidgetType-header-lastLogin, +td.TableWidgetType-header.TableWidgetType-header-remove, +td.TableWidgetType-header.TableWidgetType-header-email, +td.TableWidgetType-header.TableWidgetType-header-userName { + background: url(images/ScreenImages/table_header_bg.png) repeat-x; + border-top: 1px solid #D4D4D4; + color: #787878; + height: 33px; + padding-left: 12px; + width: 150px; +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + padding: 20px; + margin: 40px; + } +} + +.foo +{ + border: none; +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.php new file mode 100644 index 00000000..41202bc8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassDefinitionNameSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 19 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css new file mode 100644 index 00000000..98c8fa56 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css @@ -0,0 +1,108 @@ +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title{ + float: left; +} +.HelpWidgetType-new-bug-title { + + float: left; +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + + + header #logo img { + max-width: 100%; + } + +} + +.GUITextBox.container:after {} + +.single-line {float: left;} + +#opening-brace-on-different-line + + +{ + color: #FFFFFF; +} + +#opening-brace-on-different-line-and-inline-style + + +{color: #FFFFFF;} + +@media screen and (max-device-width: 769px) { .everything-on-one-line { float: left; } } + +/* Document handling of comments in various places */ +.no-space-before-opening-with-comment /* comment*/{ + float: left; +} + +.space-before-opening-with-comment-on-next-line +/* comment*/ { + float: left; +} + +#opening-brace-on-different-line-with-comment-between +/*comment*/ +{ + padding: 0; +} + +.single-line-with-comment { /* comment*/ float: left; } + +.multi-line-with-trailing-comment { /* comment*/ + float: left; +} + + +@media screen and (max-device-width: 769px) { + /*comment*/ + .comment-line-after-nesting-class-opening { + } +} + +@media screen and (max-device-width: 769px) { + + /*comment*/ + .blank-line-and-comment-line-after-nesting-class-opening { + } +} + +@media screen and (max-device-width: 769px) { + + + + /* phpcs:ignore Standard.Category.Sniffname -- for reasons */ + .blank-line-and-annotation-after-nesting-class-opening { + } +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css.fixed new file mode 100644 index 00000000..b3f48a5c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css.fixed @@ -0,0 +1,106 @@ +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + + float: left; +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +.GUITextBox.container:after { +} + +.single-line { +float: left;} + +#opening-brace-on-different-line { + color: #FFFFFF; +} + +#opening-brace-on-different-line-and-inline-style { +color: #FFFFFF;} + +@media screen and (max-device-width: 769px) { + +.everything-on-one-line { +float: left; } } + +/* Document handling of comments in various places */ +.no-space-before-opening-with-comment /* comment*/ { + float: left; +} + +.space-before-opening-with-comment-on-next-line +/* comment*/ { + float: left; +} + +#opening-brace-on-different-line-with-comment-between +/*comment*/ { + padding: 0; +} + +.single-line-with-comment { +/* comment*/ float: left; } + +.multi-line-with-trailing-comment { /* comment*/ + float: left; +} + + +@media screen and (max-device-width: 769px) { + + /*comment*/ + .comment-line-after-nesting-class-opening { + } +} + +@media screen and (max-device-width: 769px) { + + /*comment*/ + .blank-line-and-comment-line-after-nesting-class-opening { + } +} + +@media screen and (max-device-width: 769px) { + + /* phpcs:ignore Standard.Category.Sniffname -- for reasons */ + .blank-line-and-annotation-after-nesting-class-opening { + } +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.php new file mode 100644 index 00000000..d1e44219 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassDefinitionOpeningBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 7 => 1, + 10 => 1, + 26 => 1, + 33 => 1, + 43 => 1, + 45 => 1, + 50 => 1, + 57 => 2, + 59 => 2, + 62 => 1, + 73 => 1, + 77 => 1, + 84 => 1, + 97 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css new file mode 100644 index 00000000..391bc85a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css @@ -0,0 +1,42 @@ +body { +font-family: Arial, Helvetica, sans-serif; +margin : 40px 0 0 0; +padding : 0; +background: #8FB7DB url(diag_lines_bg.gif) top left; +margin-top: +10px; +margin-bottom: +0px; +} + +.TableWidgetType .recover:hover { + background-color: #FFF; +} + +#clearCache-settings:rootNodes-list_0 { + border-top: none; +} + +.LookupEditScreenWidgetType-urls a, .LookupEditScreenWidgetType-urls a:visited { + text-decoration: none; + color: #444; +} + +/* checking embedded PHP */ +li { + background:url(/images//bullet.gif) left px no-repeat; + margin:0px; + padding-left:10px; + margin-bottom:px; + margin-top: px; + line-height:13px; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); +} + +/* Empty style defs. */ +.p { + margin:; + margin-right: + margin-left: 10px; + float:/* Some comment. */ ; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css.fixed new file mode 100644 index 00000000..e68bddce --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css.fixed @@ -0,0 +1,40 @@ +body { +font-family: Arial, Helvetica, sans-serif; +margin: 40px 0 0 0; +padding: 0; +background: #8FB7DB url(diag_lines_bg.gif) top left; +margin-top: 10px; +margin-bottom: 0px; +} + +.TableWidgetType .recover:hover { + background-color: #FFF; +} + +#clearCache-settings:rootNodes-list_0 { + border-top: none; +} + +.LookupEditScreenWidgetType-urls a, .LookupEditScreenWidgetType-urls a:visited { + text-decoration: none; + color: #444; +} + +/* checking embedded PHP */ +li { + background: url(/images//bullet.gif) left px no-repeat; + margin: 0px; + padding-left: 10px; + margin-bottom: px; + margin-top: px; + line-height: 13px; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); +} + +/* Empty style defs. */ +.p { + margin:; + margin-right: + margin-left: 10px; + float: /* Some comment. */ ; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.php new file mode 100644 index 00000000..9b8aa103 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ColonSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 2, + 5 => 1, + 6 => 1, + 8 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 32 => 1, + 41 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css new file mode 100644 index 00000000..2dfd22ad --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css @@ -0,0 +1,16 @@ +#title-bar-bottom-right { + background-color: #333333; + padding: 10px; + border-bottom: 1px dotted #F0F0F0; + border-top: 1px dotted #FF00FF; + background: #08f7db url(diag_lines_bg.gif) top left; + + /* The sniff only deals with HEX colours. */ + color: DarkSlateGray; + background-color: rgb(255, 0, 0); + background-color: rgba(0, 0, 255, 0.3); + background-color: hsl(120, 100%, 50%); +} + +#add-new-comment { +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css.fixed new file mode 100644 index 00000000..039209dd --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css.fixed @@ -0,0 +1,16 @@ +#title-bar-bottom-right { + background-color: #333; + padding: 10px; + border-bottom: 1px dotted #F0F0F0; + border-top: 1px dotted #F0F; + background: #08F7DB url(diag_lines_bg.gif) top left; + + /* The sniff only deals with HEX colours. */ + color: DarkSlateGray; + background-color: rgb(255, 0, 0); + background-color: rgba(0, 0, 255, 0.3); + background-color: hsl(120, 100%, 50%); +} + +#add-new-comment { +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.php new file mode 100644 index 00000000..d535fdc2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ColourDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 5 => 1, + 6 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css new file mode 100644 index 00000000..4c11beaa --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css @@ -0,0 +1,17 @@ +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; + height: 100%;float: left; + line-height: -25px; + cursor: pointer; margin: 10px; float: right; +} + +/* testing embedded PHP */ +li { + background:url(/images//bullet.gif) left px no-repeat; margin:0px; padding-left:10px; margin-bottom:px; line-height:13px; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); +} + +/* Document handling of comments and annotations. */ +div#annotations {-webkit-tap-highlight-color:transparent;/* phpcs:disable Standard.Cat.SniffName */-webkit-touch-callout:none;/*phpcs:enable*/-webkit-user-select:none;} + +div#comments {height:100%;/*comment*/width:100%;} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css.fixed new file mode 100644 index 00000000..93a7815e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css.fixed @@ -0,0 +1,27 @@ +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; + height: 100%; +float: left; + line-height: -25px; + cursor: pointer; +margin: 10px; +float: right; +} + +/* testing embedded PHP */ +li { + background:url(/images//bullet.gif) left px no-repeat; +margin:0px; +padding-left:10px; +margin-bottom:px; +line-height:13px; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); +} + +/* Document handling of comments and annotations. */ +div#annotations {-webkit-tap-highlight-color:transparent;/* phpcs:disable Standard.Cat.SniffName */ +-webkit-touch-callout:none;/*phpcs:enable*/ +-webkit-user-select:none;} + +div#comments {height:100%;/*comment*/ +width:100%;} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.php new file mode 100644 index 00000000..8e3b4873 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowMultipleStyleDefinitionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 2, + 10 => 4, + 15 => 2, + 17 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.css new file mode 100644 index 00000000..8ac95012 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.css @@ -0,0 +1,103 @@ +.AssetLineageWidgetType-item { + color: #FFF; +} + +.AssetLineageWidgetType-title { + color: #CCC; +} + +.AssetLineageWidgetType-item { + color: #CCC; +} + +.AssetLineageWidgetType-item .selected { +} + +.AssetLineageWidgetType-item.selected { +} + +#Blah .AssetLineageWidgetType-item { +} + +#X.selected, +.AssetLineageWidgetType-item { +} + +.MyClass, .YourClass { +} + +.YourClass, .MyClass { +} + +.YourClass, .MyClass, .OurClass { +} + + +.ClassAtTopOfMediaBlock { +} + +@media print { + .ClassAtTopOfMediaBlock { + } + + .ClassInMultipleMediaBlocks { + } +} + +.ClassNotAtTopOfMediaBlock { +} + +@media handheld { + .SameClassInMediaBlock { + } + + .ClassNotAtTopOfMediaBlock { + } + + .SameClassInMediaBlock { + } +} + +@media braille { + .PlaceholderClass { + } + + .ClassNotAtTopOfMediaBlock { + } + + .ClassInMultipleMediaBlocks { + } +} + +.foo /* any comment */ +{ color: red; } + +/* print comment */ +@media print { + /* comment1 */ + td { + } + + /* comment2 */ + img { + } + + /* comment3 */ + td { + } +} + +@media handheld /* handheld comment */ +{ + td /* comment1 */ + { + } + + img /* comment2 */ + { + } + + td /* comment3 */ + { + } +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.php new file mode 100644 index 00000000..2a95971b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DuplicateClassDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 29 => 1, + 57 => 1, + 86 => 1, + 101 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.css new file mode 100644 index 00000000..c9c849f6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.css @@ -0,0 +1,27 @@ +.ViperSubToolbar-wrapper { + height: 34px; + left: 0; + position: fixed; + top: 60px; + z-index: 997; + left: 50%; +} + +.expandable { + -moz-transition-property: margin-left, margin-right; + -moz-transition-duration: 0.2s; + -moz-transition-timing-function: ease; + -webkit-transition-property: margin-left, margin-right; + -webkit-transition-duration: 0.2s; + -webkit-transition-timing-function: ease; + z-index: 2; +} + +@media only screen and (max-width: 480px) { + header nav.meta a { display: none; } + header nav.meta a.search { display: block; } +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.php new file mode 100644 index 00000000..c555461b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DuplicateStyleDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [7 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.css new file mode 100644 index 00000000..801dcda1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.css @@ -0,0 +1,15 @@ +.HelpWidgetType-new-bug-title {} +.HelpWidgetType-new-bug-title { +} +.HelpWidgetType-new-bug-title { + +} +.HelpWidgetType-new-bug-title { + +} +.HelpWidgetType-new-bug-title { + /* Nothing to see here */ +} +.HelpWidgetType-new-bug-title { + float: left; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.php new file mode 100644 index 00000000..b3fd318c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EmptyClassDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 1 => 1, + 2 => 1, + 4 => 1, + 7 => 1, + 10 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.css new file mode 100644 index 00000000..24910b71 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.css @@ -0,0 +1,11 @@ +#MetadataAdminScreen-addField-fieldType { + margin-left: 10px; + margin-right: + float: ; +} + +#MetadataAdminScreen-addField-fieldType li { + margin-right: /* @todo */ + margin-left: 10px; + float: /* Some comment. */ ; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.php new file mode 100644 index 00000000..f5bc858d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EmptyStyleDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 1, + 8 => 1, + 10 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css new file mode 100644 index 00000000..dbd54870 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css @@ -0,0 +1,18 @@ +#add-new-comment { + -moz-border-radius: 1px; + -webkit-border-radius: 1px; + border-radius: 1px; + + -moz-border-radius-topleft: 1px; + -moz-border-radius-topright: 1px; + -moz-border-radius-bottomright: 1px; + -moz-border-radius-bottomleft: 1px; + border-top-left-radius: 1px; + border-top-right-radius: 1px; + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; + + -moz-box-shadow: 1px; + -webkit-box-shadow: 1px; + box-shadow: 1px; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css.fixed new file mode 100644 index 00000000..a8ea2704 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css.fixed @@ -0,0 +1,18 @@ +#add-new-comment { + border-radius: 1px; + border-radius: 1px; + border-radius: 1px; + + border-top-left-radius: 1px; + border-top-right-radius: 1px; + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; + border-top-left-radius: 1px; + border-top-right-radius: 1px; + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; + + box-shadow: 1px; + box-shadow: 1px; + box-shadow: 1px; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.php new file mode 100644 index 00000000..28aa8ec3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ForbiddenStylesUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 3 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 15 => 1, + 16 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css new file mode 100644 index 00000000..216f00ee --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css @@ -0,0 +1,79 @@ +body { + + font-family: Arial, Helvetica, sans-serif; + margin: 40px 0 0 0; +padding: 0; + background: #8FB7DB url(diag_lines_bg.gif) top left; + +} + +td { + margin: 40px; + + padding: 20px; +} + +/* +#AdminScreenModeWidgetType-tab_pane-containers .TabPaneWidgetType-tab-selected-left { + background: transparent url(images/ScreenImages/tab_on_left.png) no-repeat; +} +#AdminScreenModeWidgetType-tab_pane-containers .TabPaneWidgetType-tab-selected-right { + background: transparent url(images/ScreenImages/tab_on_right.png) no-repeat; +} +*/ + +.GUITextBox.container:after {} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + padding: 20px; + margin: 40px; + } +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + + header #logo img { + min-width: 100%; + } + +} + +td { + margin: 40px; + + padding: 20px; + + +} + +.GUIFileUpload { +/* opacity: 0.25; */ +} + +.foo +{ + border: none; +} + +.mortgage-calculator h2 { + background: #072237; + color: #fff; + font-weight: normal; + height: 50px; + line-height: 50px; + padding: 0 0 0 30px; + } + +.WhitelistCommentIndentationShouldBeIgnored { +/* phpcs:disable Standard.Category.Sniff -- for reasons. */ +} + +/* syntax error */ +--------------------------------------------- */ diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css.fixed new file mode 100644 index 00000000..1fd128a5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css.fixed @@ -0,0 +1,73 @@ +body { + font-family: Arial, Helvetica, sans-serif; + margin: 40px 0 0 0; + padding: 0; + background: #8FB7DB url(diag_lines_bg.gif) top left; +} + +td { + margin: 40px; + padding: 20px; +} + +/* +#AdminScreenModeWidgetType-tab_pane-containers .TabPaneWidgetType-tab-selected-left { + background: transparent url(images/ScreenImages/tab_on_left.png) no-repeat; +} +#AdminScreenModeWidgetType-tab_pane-containers .TabPaneWidgetType-tab-selected-right { + background: transparent url(images/ScreenImages/tab_on_right.png) no-repeat; +} +*/ + +.GUITextBox.container:after {} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + padding: 20px; + margin: 40px; + } +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + + header #logo img { + min-width: 100%; + } + +} + +td { + margin: 40px; + padding: 20px; +} + +.GUIFileUpload { +/* opacity: 0.25; */ +} + +.foo +{ + border: none; +} + +.mortgage-calculator h2 { + background: #072237; + color: #fff; + font-weight: normal; + height: 50px; + line-height: 50px; + padding: 0 0 0 30px; +} + +.WhitelistCommentIndentationShouldBeIgnored { +/* phpcs:disable Standard.Category.Sniff -- for reasons. */ +} + +/* syntax error */ +--------------------------------------------- */ diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.2.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.2.css new file mode 100644 index 00000000..48b22f6d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.2.css @@ -0,0 +1,3 @@ +/* Live coding. Has to be the last (only) test in the file. */ +.intentional-parse-error { + float: left diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.php new file mode 100644 index 00000000..9413b4ff --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class IndentationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'IndentationUnitTest.1.css': + return [ + 2 => 1, + 3 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 12 => 1, + 30 => 1, + 32 => 1, + 50 => 1, + 52 => 1, + 53 => 1, + 66 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 70 => 1, + 71 => 1, + 72 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.css new file mode 100644 index 00000000..d0f2982f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.css @@ -0,0 +1,14 @@ +.SettingsTabPaneWidgetType-tab-mid { + font-family: Arial; + Font-Family: arial; + background-color: #DA9393; + BACKGROUND-IMAGE: URL(Warning_Close.png); +} + +@media screen and (max-device-width: 769px) { + + .SettingsTabPaneWidgetType-tab-mid { + Font-Family: arial; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); + } +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.php new file mode 100644 index 00000000..1a25aaac --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowercaseStyleDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 3 => 1, + 5 => 2, + 11 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.css new file mode 100644 index 00000000..6c947e5b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.css @@ -0,0 +1,21 @@ +.my-style { + margin-right 15px; + float: left; + margin-left 15px; + margin-top: 15px; + margin-bottom 15px; +} + +@media screen and (max-device-width: 769px) { + header #logo img { + max-width: 100%; + margin-bottom 15px; + } +} + +#foo { background-color: #FF0000; +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.php new file mode 100644 index 00000000..dc0809e2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MissingColonUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 1, + 6 => 1, + 12 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.css new file mode 100644 index 00000000..05637a60 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.css @@ -0,0 +1,25 @@ +#red { + background-color: red; +} + +.red { + border-bottom: 1px dotted black; + border-top: 1px dotted gray; +} + +#red.yellow { + background: yellow url(diag_lines_bg.gif) top left; + text-shadow: 0 1px 0 white; +} + +.something--white { + border: 0; +} + +.something--------------white { + border: 0; +} + +.-white { + border: 0; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.php new file mode 100644 index 00000000..a8032fad --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class NamedColoursUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 6 => 1, + 7 => 1, + 11 => 1, + 12 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css new file mode 100644 index 00000000..c656c78e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css @@ -0,0 +1,35 @@ +.my-style { + opacity: 0; + opacity: 0.0; + opacity: 1; + opacity: 1.0; + opacity: 1.5; + opacity: .5; + opacity: 0.5; + opacity: 2; + opacity: -1; + opacity: 0.55; +} + +div { + font-size: 1.2em; + background: linear-gradient(to bottom, #00F, #0F0) repeat scroll 50% 50% #EEE; + min-width: 250px; + max-width: 100%; + padding-bottom: 50px; + box-shadow: 2px -3px 3px rgba(100, 100, 100, 0.33); + border-left: 1px solid #000; + border-right: 1px solid #000; + border-top: 1px solid #000; + border-bottom: 1px dotted #000; + background: url(../1/2/3/4-5-6_7_100x100.png) repeat scroll 50% 50% #EEE; + opacity: -1; +} + +.my-commented-style { + opacity: /*comment*/ 0; + opacity: /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + 0.0; + opacity: /*comment*/ 1.0; + opacity: /*comment*/ .5; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css.fixed new file mode 100644 index 00000000..257e41a7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css.fixed @@ -0,0 +1,35 @@ +.my-style { + opacity: 0; + opacity: 0; + opacity: 1; + opacity: 1; + opacity: 1.5; + opacity: 0.5; + opacity: 0.5; + opacity: 2; + opacity: -1; + opacity: 0.55; +} + +div { + font-size: 1.2em; + background: linear-gradient(to bottom, #00F, #0F0) repeat scroll 50% 50% #EEE; + min-width: 250px; + max-width: 100%; + padding-bottom: 50px; + box-shadow: 2px -3px 3px rgba(100, 100, 100, 0.33); + border-left: 1px solid #000; + border-right: 1px solid #000; + border-top: 1px solid #000; + border-bottom: 1px dotted #000; + background: url(../1/2/3/4-5-6_7_100x100.png) repeat scroll 50% 50% #EEE; + opacity: -1; +} + +.my-commented-style { + opacity: /*comment*/ 0; + opacity: /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + 0; + opacity: /*comment*/ 1; + opacity: /*comment*/ 0.5; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.php new file mode 100644 index 00000000..9fe839da --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class OpacityUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 26 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css new file mode 100644 index 00000000..3ccb162e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css @@ -0,0 +1,61 @@ +.HelpWidgetType-new-bug-title { + width: 308px + float: left; +} + +#MetadataAdminScreen-addField-add { + float: left ; +} + +.TableWidgetType .recover:hover { + background-color: #FFF; +} + +#clearCache-settings:rootNodes-list_0 { + border-top: none; +} + +.HelpWidgetType-list { + list-style-image: url(); +} + +@media (min-width: 320px) and (max-width: 961px) { + .tooltipsrt:hover span.tltp, + .tooltipstp:hover span.tltp { + visibility: hidden; + } +} + +#single-line-multi-statement-no-semicolon { + padding: 0 border: 20; +} + +#multi-line-style-no-semicolon { + padding: 0 /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + border: + 20 + margin: + 0px /* top */ + 10px /* right + left */ +} + +#multi-line-style-whitespace { + padding: 0 /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ ; + border: + 20 ; + margin: + 10px /* top */ + 0px /* right + left */ + + + ; +} + +.allow-for-star-hack { + cursor: pointer; + *cursor: hand; +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css.fixed new file mode 100644 index 00000000..7efef588 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css.fixed @@ -0,0 +1,58 @@ +.HelpWidgetType-new-bug-title { + width: 308px + float: left; +} + +#MetadataAdminScreen-addField-add { + float: left; +} + +.TableWidgetType .recover:hover { + background-color: #FFF; +} + +#clearCache-settings:rootNodes-list_0 { + border-top: none; +} + +.HelpWidgetType-list { + list-style-image: url(); +} + +@media (min-width: 320px) and (max-width: 961px) { + .tooltipsrt:hover span.tltp, + .tooltipstp:hover span.tltp { + visibility: hidden; + } +} + +#single-line-multi-statement-no-semicolon { + padding: 0 border: 20; +} + +#multi-line-style-no-semicolon { + padding: 0 /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + border: + 20 + margin: + 0px /* top */ + 10px /* right + left */ +} + +#multi-line-style-whitespace { + padding: 0; /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + border: + 20; + margin: + 10px /* top */ + 0px; /* right + left */ +} + +.allow-for-star-hack { + cursor: pointer; + *cursor: hand; +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.php new file mode 100644 index 00000000..897df65e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SemicolonSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 7 => 1, + 30 => 1, + 34 => 1, + 36 => 1, + 39 => 1, + 43 => 1, + 45 => 1, + 48 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css new file mode 100644 index 00000000..cfc4503c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css @@ -0,0 +1,45 @@ +#add-new-comment { + background-color: #333333; + padding: 10px; + border-bottom: 1px dotted #F0F0F0; + border-top: 1px dotted #FF00FF; + background: #8fb7db url(diag_lines_bg.gif) top left; + tab-size: 1; + margin: 8px 8px 8px 8px; + margin: 8px 8px; + margin: 0 0 0 0; + margin: 0 8px 0 8px; + margin: 8px 4px 8px 4px; + margin: 8px 4% 8px 4%; + margin: 6px 2px 9px 2px; + margin: 6px 2px 9px; + border-radius: 2px 2px 2px 2px !important; + border-width: 2px 2px 2px 2px; + border-width: 1px 2px 2px 4px; + margin: 97px auto 0 auto; + text-shadow: 0 1px 0 #fff; + border-width: + 2px + 4px + 2px + 4px; + + /* These are style names excluded from this rule. */ + background-position: 0 0; + box-shadow: 2px 2px 2px 2px; + transform-origin: 0 110% 0; + + /* Sizes with comments between them will be ignored for the purposes of this sniff. */ + margin: 8px /*top*/ 8px /*right*/ 8px /*bottom*/ 8px /*left*/; + + /* Same with PHPCS annotations. */ + border-width: + 2px /* phpcs:ignore Standard.Category.SniffName -- for reasons */ + 4px + 2px /* phpcs:disable Standard.Category.SniffName -- for reasons */ + 4px; +} + +/* Intentional parse error. Live coding resilience. This has to be the last test in the file. */ +#live-coding { + margin: 8px 8px 8px 8px diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css.fixed new file mode 100644 index 00000000..3472cb17 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css.fixed @@ -0,0 +1,41 @@ +#add-new-comment { + background-color: #333333; + padding: 10px; + border-bottom: 1px dotted #F0F0F0; + border-top: 1px dotted #FF00FF; + background: #8fb7db url(diag_lines_bg.gif) top left; + tab-size: 1; + margin: 8px; + margin: 8px; + margin: 0; + margin: 0 8px; + margin: 8px 4px; + margin: 8px 4%; + margin: 6px 2px 9px 2px; + margin: 6px 2px 9px 2px; + border-radius: 2px !important; + border-width: 2px; + border-width: 1px 2px 2px 4px; + margin: 97px auto 0 auto; + text-shadow: 0 1px 0 #fff; + border-width: 2px 4px; + + /* These are style names excluded from this rule. */ + background-position: 0 0; + box-shadow: 2px 2px 2px 2px; + transform-origin: 0 110% 0; + + /* Sizes with comments between them will be ignored for the purposes of this sniff. */ + margin: 8px /*top*/ 8px /*right*/ 8px /*bottom*/ 8px /*left*/; + + /* Same with PHPCS annotations. */ + border-width: + 2px /* phpcs:ignore Standard.Category.SniffName -- for reasons */ + 4px + 2px /* phpcs:disable Standard.Category.SniffName -- for reasons */ + 4px; +} + +/* Intentional parse error. Live coding resilience. This has to be the last test in the file. */ +#live-coding { + margin: 8px 8px 8px 8px diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.php new file mode 100644 index 00000000..3d0baaad --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ShorthandSizeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 8 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 15 => 1, + 16 => 1, + 17 => 1, + 21 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.inc new file mode 100644 index 00000000..43ef6c9c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.inc @@ -0,0 +1,121 @@ + + + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 6 => 1, + 10 => 1, + 15 => 2, + 18 => 1, + 22 => 4, + 23 => 4, + 24 => 4, + 27 => 2, + 30 => 2, + 34 => 1, + 35 => 1, + 39 => 1, + 42 => 1, + 45 => 1, + 48 => 1, + 50 => 2, + 51 => 1, + 55 => 1, + 59 => 4, + 63 => 1, + 65 => 1, + 69 => 3, + 74 => 2, + 77 => 1, + 80 => 1, + 85 => 3, + 89 => 1, + 92 => 1, + 97 => 1, + 108 => 1, + 114 => 1, + 116 => 1, + 118 => 1, + 121 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.inc new file mode 100644 index 00000000..8b5a5aa7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.inc @@ -0,0 +1,45 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.php new file mode 100644 index 00000000..5964d2b1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.php @@ -0,0 +1,77 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassFileNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 16 => 1, + 17 => 1, + 18 => 1, + 19 => 1, + 20 => 1, + 21 => 1, + 22 => 1, + 23 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 35 => 1, + 36 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 40 => 1, + 41 => 1, + 42 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.js new file mode 100644 index 00000000..04126f86 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.js @@ -0,0 +1,45 @@ +var x = { + abc: 1, + zyz: 2, + abc: 5, + mno: { + abc: 4 + }, + abc: 5 + + this.request({ + action: 'getSubmissions' + }); + + this.request({ + action: 'deleteSubmission' + }); +} + + +LinkingEditScreenWidgetType.prototype = { + + _addDeleteButtonEvent: function(parentid) + { + var params = { + screen: 'LinkingEditScreenWidget', + assetid: self.assetid, + parentid: parentid, + assetid: parentid, + op: 'deleteLink' + }; + + }, + + saveDesignEdit: function() + { + var params = { + screen: [this.id, 'Widget'].join(''), + assetid: this.assetid, + changes: dfx.jsonEncode(this.currnetLinksWdgt.getChanges()), + op: 'saveLinkEdit' + }; + + } + +}; \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.php new file mode 100644 index 00000000..1b71eb2c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DuplicatePropertyUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 8 => 1, + 28 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.inc new file mode 100644 index 00000000..ea8cd89e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.inc @@ -0,0 +1,14 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowercaseClassKeywordsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 2 => 3, + 3 => 3, + 4 => 1, + 5 => 1, + 6 => 2, + 10 => 1, + 11 => 1, + 14 => 1, + ]; + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc new file mode 100644 index 00000000..0a0729a0 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc @@ -0,0 +1,174 @@ +testResults; + + + // Correct call to self. + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = parent::selfMemberReferenceUnitTestFunction(); + + // Incorrect case. + $testResults[] = Self::selfMemberReferenceUnitTestFunction(); + $testResults[] = SELF::selfMemberReferenceUnitTestFunction(); + $testResults[] = SelfMemberReferenceUnitTestExample::selfMemberReferenceUnitTestFunction(); + + + // Incorrect spacing. + $testResults[] = self ::selfMemberReferenceUnitTestFunction(); + $testResults[] = self:: selfMemberReferenceUnitTestFunction(); + $testResults[] = self :: selfMemberReferenceUnitTestFunction(); + + // Remove ALL the newlines + $testResults[] = self + + + + + :: + + + + + selfMemberReferenceUnitTestFunction(); + + } + + + function selfMemberReferenceUnitTestFunction() + { + $this->testCount = $this->testCount + 1; + return $this->testCount; + + } + + +} + + +class MyClass { + + public static function test($value) { + echo "$value\n"; + } + + public static function walk() { + $callback = function($value, $key) { + // This is valid because you can't use self:: in a closure. + MyClass::test($value); + }; + + $array = array(1,2,3); + array_walk($array, $callback); + } +} + +MyClass::walk(); + +class Controller +{ + public function Action() + { + Doctrine\Common\Util\Debug::dump(); + } +} + +class Foo +{ + public static function bar() + { + \Foo::baz(); + } +} + +namespace TYPO3\CMS\Reports; + +class Status { + const NOTICE = -2; + const INFO = -1; + const OK = 0; + const WARNING = 1; + const ERROR = 2; +} + +namespace TYPO3\CMS\Reports\Report\Status; + +class Status implements \TYPO3\CMS\Reports\ReportInterface { + public function getHighestSeverity(array $statusCollection) { + $highestSeverity = \TYPO3\CMS\Reports\Status::NOTICE; + } +} + +namespace Foo; + +class Bar { + + function myFunction() + { + \Foo\Whatever::something(); + \Foo\Bar::something(); + } +} + +namespace Foo\Bar; + +class Baz { + + function myFunction() + { + \Foo\Bar\Whatever::something(); + \Foo\Bar\Baz::something(); + } +} + +class Nested_Anon_Class { + public function getAnonymousClass() { + // Spacing/comments should not cause false negatives for the NotUsed error. + Nested_Anon_Class :: $prop; + Nested_Anon_Class + /* some comment */ + + :: + + // phpcs:ignore Standard.Category.SniffName -- for reasons. + Bar(); + + // Anonymous class is a different scope. + return new class() { + public function nested_function() { + Nested_Anon_Class::$prop; + Nested_Anon_Class::BAR; + } + }; + } +} + +// Test dealing with scoped namespaces. +namespace Foo\Baz { + class BarFoo { + public function foo() { + echo Foo\Baz\BarFoo::$prop; + } + } +} + +// Prevent false negative when namespace has whitespace/comments. +namespace Foo /*comment*/ \ Bah { + class BarFoo { + public function foo() { + echo Foo \ /*comment*/ Bah\BarFoo::$prop; + } + } +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc.fixed new file mode 100644 index 00000000..f2c1731d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc.fixed @@ -0,0 +1,162 @@ +testResults; + + + // Correct call to self. + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = parent::selfMemberReferenceUnitTestFunction(); + + // Incorrect case. + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + + + // Incorrect spacing. + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + + // Remove ALL the newlines + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + + } + + + function selfMemberReferenceUnitTestFunction() + { + $this->testCount = $this->testCount + 1; + return $this->testCount; + + } + + +} + + +class MyClass { + + public static function test($value) { + echo "$value\n"; + } + + public static function walk() { + $callback = function($value, $key) { + // This is valid because you can't use self:: in a closure. + MyClass::test($value); + }; + + $array = array(1,2,3); + array_walk($array, $callback); + } +} + +MyClass::walk(); + +class Controller +{ + public function Action() + { + Doctrine\Common\Util\Debug::dump(); + } +} + +class Foo +{ + public static function bar() + { + self::baz(); + } +} + +namespace TYPO3\CMS\Reports; + +class Status { + const NOTICE = -2; + const INFO = -1; + const OK = 0; + const WARNING = 1; + const ERROR = 2; +} + +namespace TYPO3\CMS\Reports\Report\Status; + +class Status implements \TYPO3\CMS\Reports\ReportInterface { + public function getHighestSeverity(array $statusCollection) { + $highestSeverity = \TYPO3\CMS\Reports\Status::NOTICE; + } +} + +namespace Foo; + +class Bar { + + function myFunction() + { + \Foo\Whatever::something(); + self::something(); + } +} + +namespace Foo\Bar; + +class Baz { + + function myFunction() + { + \Foo\Bar\Whatever::something(); + self::something(); + } +} + +class Nested_Anon_Class { + public function getAnonymousClass() { + // Spacing/comments should not cause false negatives for the NotUsed error. + self::$prop; + + /* some comment */ + + self::// phpcs:ignore Standard.Category.SniffName -- for reasons. + Bar(); + + // Anonymous class is a different scope. + return new class() { + public function nested_function() { + Nested_Anon_Class::$prop; + Nested_Anon_Class::BAR; + } + }; + } +} + +// Test dealing with scoped namespaces. +namespace Foo\Baz { + class BarFoo { + public function foo() { + echo self::$prop; + } + } +} + +// Prevent false negative when namespace has whitespace/comments. +namespace Foo /*comment*/ \ Bah { + class BarFoo { + public function foo() { + echo /*comment*/ self::$prop; + } + } +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.php new file mode 100644 index 00000000..ea493d3c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SelfMemberReferenceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 24 => 1, + 25 => 1, + 26 => 1, + 30 => 1, + 31 => 1, + 32 => 2, + 40 => 2, + 92 => 1, + 121 => 1, + 132 => 1, + 139 => 3, + 140 => 1, + 143 => 2, + 162 => 1, + 171 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.inc new file mode 100644 index 00000000..3fe39435 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.inc @@ -0,0 +1,191 @@ +anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +// Valid interface name. +interface ValidCamelCaseClass extends MyClass {} + + +// Incorrect usage of camel case. +interface invalidCamelCaseClass extends MyClass {} +interface Invalid_Camel_Case_Class_With_Underscores implements MyClass {} + + +// All lowercase. +interface invalidlowercaseclass extends MyClass {} +interface invalid_lowercase_class_with_underscores extends MyClass {} + + +// All uppercase. +interface VALIDUPPERCASECLASS extends MyClass {} +interface INVALID_UPPERCASE_CLASS_WITH_UNDERSCORES extends MyClass {} + + +// Mix camel case with uppercase. +interface ValidCamelCaseClassWithUPPERCASE extends MyClass {} + + +// Usage of numeric characters. +interface ValidCamelCaseClassWith1Number extends MyClass {} +interface ValidCamelCaseClassWith12345Numbers extends MyClass {} +interface 5InvalidCamelCaseClassStartingWithNumber extends MyClass {} +interface ValidCamelCaseClassEndingWithNumber5 extends MyClass {} +interface 12345 extends MyClass {} + +interface Testing{} + +interface Base +{ + protected $anonymous; + + public function __construct(); +} + + +// Valid trait name. +trait ValidCamelCaseClass extends MyClass {} + + +// Incorrect usage of camel case. +trait invalidCamelCaseClass extends MyClass {} +trait Invalid_Camel_Case_Class_With_Underscores implements MyClass {} + + +// All lowercase. +trait invalidlowercaseclass extends MyClass {} +trait invalid_lowercase_class_with_underscores extends MyClass {} + + +// All uppercase. +trait VALIDUPPERCASECLASS extends MyClass {} +trait INVALID_UPPERCASE_CLASS_WITH_UNDERSCORES extends MyClass {} + + +// Mix camel case with uppercase. +trait ValidCamelCaseClassWithUPPERCASE extends MyClass {} + + +// Usage of numeric characters. +trait ValidCamelCaseClassWith1Number extends MyClass {} +trait ValidCamelCaseClassWith12345Numbers extends MyClass {} +trait 5InvalidCamelCaseClassStartingWithNumber extends MyClass {} +trait ValidCamelCaseClassEndingWithNumber5 extends MyClass {} +trait 12345 extends MyClass {} + +trait Testing{} + +trait Base +{ + protected $anonymous; + + public function __construct() + { + $this->anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +// Valid enum name. +enum ValidCamelCaseClass: string {} + + +// Incorrect usage of camel case. +enum invalidCamelCaseClass {} +enum Invalid_Camel_Case_Class_With_Underscores {} + + +// All lowercase. +enum invalidlowercaseclass: INT {} +enum invalid_lowercase_class_with_underscores {} + + +// All uppercase. +enum VALIDUPPERCASECLASS: int {} +enum INVALID_UPPERCASE_CLASS_WITH_UNDERSCORES {} + + +// Mix camel case with uppercase. +enum ValidCamelCaseClassWithUPPERCASE : string {} + + +// Usage of numeric characters. +enum ValidCamelCaseClassWith1Number {} +enum ValidCamelCaseClassWith12345Numbers : string {} +enum ValidCamelCaseClassEndingWithNumber5 {} + +enum Testing{} + +enum Base +{ + public function __construct() + { + $this->anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +if ( class_exists( Test :: class ) ) {} +if ( class_exists( Test2 ::class ) ) {} + +$foo = new class( + new class implements Countable { + } +) extends DateTime { +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.php new file mode 100644 index 00000000..b7de260b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidClassNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 10 => 1, + 14 => 1, + 15 => 1, + 20 => 1, + 30 => 1, + 32 => 1, + 57 => 1, + 58 => 1, + 62 => 1, + 63 => 1, + 68 => 1, + 78 => 1, + 80 => 1, + 97 => 1, + 98 => 1, + 102 => 1, + 103 => 1, + 108 => 1, + 118 => 1, + 120 => 1, + 145 => 1, + 146 => 1, + 150 => 1, + 151 => 1, + 156 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc new file mode 100644 index 00000000..7cd04a21 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc @@ -0,0 +1,309 @@ + + + + + + + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class BlockCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + $config->tabWidth = 4; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 3 => 1, + 8 => 1, + 20 => 1, + 24 => 1, + 30 => 1, + 31 => 1, + 34 => 1, + 40 => 1, + 45 => 1, + 49 => 1, + 51 => 1, + 53 => 1, + 57 => 1, + 60 => 1, + 61 => 1, + 63 => 1, + 65 => 1, + 68 => 1, + 70 => 1, + 72 => 1, + 75 => 1, + 84 => 1, + 87 => 1, + 89 => 1, + 92 => 1, + 111 => 1, + 159 => 1, + 181 => 1, + 188 => 1, + 208 => 1, + 214 => 1, + 226 => 1, + 227 => 1, + 232 => 1, + 233 => 1, + 256 => 1, + 271 => 1, + 273 => 1, + ]; + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.inc new file mode 100644 index 00000000..28aff226 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.inc @@ -0,0 +1,133 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 15 => 1, + 31 => 1, + 54 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 29 => 1, + 30 => 1, + 50 => 1, + 66 => 1, + 67 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.inc new file mode 100644 index 00000000..1a57149b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.inc @@ -0,0 +1,86 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClosingDeclarationCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 13 => 1, + 17 => 1, + 31 => 1, + 41 => 1, + 59 => 1, + 63 => 1, + 67 => 1, + 79 => 1, + 83 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [71 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc new file mode 100644 index 00000000..e42cf8ab --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc @@ -0,0 +1,103 @@ + line numbers for each token. + * + * Long description with some points: + * - one + * - two + * - three + * + * @param array &$tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to + * process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function myFunction() {} + +class MyClass2 +{ + /** + * Some info about the variable here. + */ + var $x; +} + +abstract class MyClass +{ + /** +* Property comment + */ + readonly public string $prop; +} + +/** + * Some info about the enum here + * +*/ +enum Suits: string +{ + /** + * Some info about the case here. + */ + case HEARTS; +} + +/** ************************************************************************ + * Example with no errors. + **************************************************************************/ +function example() {} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc.fixed new file mode 100644 index 00000000..6182b539 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc.fixed @@ -0,0 +1,103 @@ + line numbers for each token. + * + * Long description with some points: + * - one + * - two + * - three + * + * @param array &$tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to + * process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function myFunction() {} + +class MyClass2 +{ + /** + * Some info about the variable here. + */ + var $x; +} + +abstract class MyClass +{ + /** + * Property comment + */ + readonly public string $prop; +} + +/** + * Some info about the enum here + * + */ +enum Suits: string +{ + /** + * Some info about the case here. + */ + case HEARTS; +} + +/** ************************************************************************ + * Example with no errors. + **************************************************************************/ +function example() {} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js new file mode 100644 index 00000000..6e1a8781 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js @@ -0,0 +1,76 @@ + +/** +* Some info about the class here + * + */ +foo.prototype = { + + /** + * Some info about the function here. + * + *@return void + */ + bar: function() {} +} + +/** + * Some info about the class here + * + */ +foo.prototype = { + + /** + *Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** + * Some info about the class here + * +*/ +foo.prototype = { + + /** + * Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +function myFunction() +{ + console.info('hi'); + /** + Comment here. + */ +} + +/** + * Creates a map of tokens => line numbers for each token. + * + * Long description with some points: + * - one + * - two + * - three + * + * @param array &$tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to + * process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function myFunction() {} + +$.extend(Datepicker.prototype, { + _widgetDatepicker: function() { + }, + /* Action for selecting a new month/year. */ +}); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js.fixed new file mode 100644 index 00000000..9edb4ccc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js.fixed @@ -0,0 +1,76 @@ + +/** + * Some info about the class here + * + */ +foo.prototype = { + + /** + * Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** + * Some info about the class here + * + */ +foo.prototype = { + + /** + * Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** + * Some info about the class here + * + */ +foo.prototype = { + + /** + * Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +function myFunction() +{ + console.info('hi'); + /** + Comment here. + */ +} + +/** + * Creates a map of tokens => line numbers for each token. + * + * Long description with some points: + * - one + * - two + * - three + * + * @param array &$tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to + * process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function myFunction() {} + +$.extend(Datepicker.prototype, { + _widgetDatepicker: function() { + }, + /* Action for selecting a new month/year. */ +}); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.php new file mode 100644 index 00000000..acbf13e8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.php @@ -0,0 +1,76 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DocCommentAlignmentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='DocCommentAlignmentUnitTest.inc') + { + $errors = [ + 3 => 1, + 11 => 1, + 17 => 1, + 18 => 1, + 19 => 1, + 23 => 2, + 24 => 1, + 25 => 2, + 26 => 1, + 32 => 1, + 33 => 1, + 38 => 1, + 39 => 1, + ]; + + if ($testFile === 'DocCommentAlignmentUnitTest.inc') { + $errors[75] = 1; + $errors[83] = 1; + $errors[84] = 1; + $errors[90] = 1; + $errors[91] = 1; + $errors[95] = 1; + $errors[96] = 1; + } + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.inc new file mode 100644 index 00000000..cde6e462 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.inc @@ -0,0 +1,55 @@ + \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.php new file mode 100644 index 00000000..3c1668e4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EmptyCatchCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 13 => 1, + 33 => 1, + 49 => 1, + 50 => 1, + 51 => 1, + 52 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc new file mode 100644 index 00000000..1db2861b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc @@ -0,0 +1,43 @@ + +* @author +* @copyright 1997~1994 The PHP Group +* @copyright 1994-1997 The PHP Group +* @copyright The PHP Group +* @license http://www.php.net/license/3_0.txt +* @summary An unknown summary tag +* +*/ + + +?> + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc.fixed new file mode 100644 index 00000000..e42e037c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc.fixed @@ -0,0 +1,43 @@ + +* @author +* @copyright 1997 Squiz Pty Ltd (ABN 77 084 670 600) +* @copyright 1994-1997 Squiz Pty Ltd (ABN 77 084 670 600) +* @copyright 2022 Squiz Pty Ltd (ABN 77 084 670 600) +* @license http://www.php.net/license/3_0.txt +* @summary An unknown summary tag +* +*/ + + +?> + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js new file mode 100644 index 00000000..57d8d37a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js @@ -0,0 +1,40 @@ + + + + +/** +* +* 0Multi-line short description without full stop +* +* +* asdasd +* long description for file (if any) +* asdasdadada +* +* PHP versio +* +* LICENSE: This source file is subject to version 3.0 of the PHP license +* that is available through the world-wide-web at the following URI: +* http://www.php.net/license/3_0.txt. If you did not receive a copy of +* the PHP License and are unable to obtain it through the web, please +* send a note to license@php.net so we can mail you a copy immediately. +* @package SquizCMS +* @package ADDITIONAL PACKAGE TAG +* @subpkg not_camelcased +* @author Antônio Carlos Venâncio Júnior +* @author +* @copyright 1997~1994 The PHP Group +* @copyright 1994-1997 The PHP Group +* @copyright The PHP Group +* @license http://www.php.net/license/3_0.txt +* @summary An unknown summary tag +* +*/ + + +/** +* This bit here is not qualified as file comment +* +* as it is not the first comment in the file +* +*/ diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js.fixed new file mode 100644 index 00000000..90046c71 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js.fixed @@ -0,0 +1,40 @@ + + + + +/** +* +* 0Multi-line short description without full stop +* +* +* asdasd +* long description for file (if any) +* asdasdadada +* +* PHP versio +* +* LICENSE: This source file is subject to version 3.0 of the PHP license +* that is available through the world-wide-web at the following URI: +* http://www.php.net/license/3_0.txt. If you did not receive a copy of +* the PHP License and are unable to obtain it through the web, please +* send a note to license@php.net so we can mail you a copy immediately. +* @package SquizCMS +* @package ADDITIONAL PACKAGE TAG +* @subpkg not_camelcased +* @author Squiz Pty Ltd +* @author +* @copyright 1997 Squiz Pty Ltd (ABN 77 084 670 600) +* @copyright 1994-1997 Squiz Pty Ltd (ABN 77 084 670 600) +* @copyright 2022 Squiz Pty Ltd (ABN 77 084 670 600) +* @license http://www.php.net/license/3_0.txt +* @summary An unknown summary tag +* +*/ + + +/** +* This bit here is not qualified as file comment +* +* as it is not the first comment in the file +* +*/ diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.inc new file mode 100644 index 00000000..520d3497 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.inc @@ -0,0 +1,11 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ + +echo 'hi'; \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.js new file mode 100644 index 00000000..4bb4d50d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.js @@ -0,0 +1,10 @@ +/** + * File comment. + * + * @package Package + * @subpackage Subpackage + * @author Squiz Pty Ltd + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ + +print 'hi'; \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.3.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.3.inc new file mode 100644 index 00000000..b47603f2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.3.inc @@ -0,0 +1,9 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.4.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.4.inc new file mode 100644 index 00000000..2fdeeba1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.4.inc @@ -0,0 +1,3 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ + +class Foo { +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.7.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.7.inc new file mode 100644 index 00000000..7074dac2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.7.inc @@ -0,0 +1,12 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ +#[Attribute] +class Foo { +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.8.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.8.inc new file mode 100644 index 00000000..5ef90f2a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.8.inc @@ -0,0 +1,9 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.9.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.9.inc new file mode 100644 index 00000000..f6c9d996 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.9.inc @@ -0,0 +1,12 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ + +enum Foo { +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.php new file mode 100644 index 00000000..ee81369a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.php @@ -0,0 +1,76 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FileCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='FileCommentUnitTest.inc') + { + switch ($testFile) { + case 'FileCommentUnitTest.1.inc': + case 'FileCommentUnitTest.1.js': + return [ + 1 => 1, + 22 => 2, + 23 => 1, + 24 => 2, + 25 => 2, + 26 => 1, + 27 => 2, + 28 => 2, + 32 => 2, + ]; + + case 'FileCommentUnitTest.4.inc': + case 'FileCommentUnitTest.6.inc': + case 'FileCommentUnitTest.7.inc': + case 'FileCommentUnitTest.9.inc': + return [1 => 1]; + + case 'FileCommentUnitTest.5.inc': + return [2 => 1]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.inc new file mode 100644 index 00000000..7e94bb26 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.inc @@ -0,0 +1,511 @@ +callSomeFunction(); + + }//end okFunction() + + + /** + * Comment inside function. + * + * @throws Exception + */ + function okFunction() + { + /** + * @var FooClass + */ + $foo = FooFactory::factory(); + throw new Exception; + + }//end okFunction + + /** + * Needs at throws tag for rethrown exception, + * even though we have one throws tag. + * + * @throws PHP_Exception1 + */ + public function notOkVariableRethrown() + { + throw new PHP_Exception1('Error'); + + try { + // Do something. + } catch (PHP_Exception2 $e) { + logError(); + throw $e; + } + + }//end notOkVariableRethrown() + + /** + * Needs at throws tag for rethrown exception, + * even though we have one throws tag. + * + * @throws PHP_Exception1 + */ + public function notOkVariableRethrown() + { + throw new PHP_Exception1('Error'); + + try { + // Do something. + } catch (PHP_Exception1 | PHP_Exception2 $e) { + logError(); + throw $e; + } + + }//end notOkVariableRethrown() + + /** + * Has correct throws tags for all exceptions + * + * @throws PHP_Exception1 + * @throws PHP_Exception2 + */ + public function okVariableRethrown() + { + throw new PHP_Exception1('Error'); + + try { + // Do something. + } catch (PHP_Exception2 $e) { + logError(); + throw $e; + } + + }//end okVariableRethrown() + + /** + * Has correct throws tags for all exceptions + * + * @throws PHP_Exception1 + * @throws PHP_Exception2 + */ + public function okVariableMultiRethrown() + { + try { + // Do something. + } catch (PHP_Exception1 | PHP_Exception2 $e) { + logError(); + throw $e; + } + + }//end okVariableMultiRethrown() +}//end class + +class NamespacedException { + /** + * @throws \Exception + */ + public function foo() { + throw new \Exception(); + } + + /** + * @throws \Foo\Bar\FooBarException + */ + public function fooBar2() { + throw new \Foo\Bar\FooBarException(); + } + + /** + * @throws FooBarException + */ + public function fooBar2() { + throw new \Foo\Bar\FooBarException(); + } +} + +class Foo { + /** + * Comment + */ + public function foo() { + }//end foo() + + public function bar() { + throw new Exception(); + } + + /** + * Returns information for a test. + * + * This info includes parameters, their valid values. + * + * @param integer $projectid Id of the project. + * + * @return array + * @throws ChannelException If the project is invalid. + */ + public static function getTestInfo($projectid=NULL) + { + try { + DAL::beginTransaction(); + DAL::commit(); + } catch (DALException $e) { + DAL::rollBack(); + throw new ChannelException($e); + } + } +} + +class Test +{ + /** + * Folder name. + * + * @var string + */ + protected $folderName; + + protected function setUp() + { + parent::setUp(); + + if ( !strlen($this->folderName) ) { + throw new \RuntimeException('The $this->folderName must be specified before proceeding.'); + } + } + + /* + * + */ + protected function foo() + { + } + + /** + * @return Closure + */ + public function getStuff() + { + return function () { + throw new RuntimeException("bam!"); + }; + } +} + +/** + * Class comment. + */ +class A +{ + /** + * Function B. + */ + public function b() + { + return new class { + public function c() + { + throw new \Exception(); + } + } + } +} + +/** + * Class comment. + */ +class A +{ + /** + * Function B. + */ + public function b() + { + return new class { + /** + * Tag and token number mismatch. + * + * @throws PHP_Exception1 + * @throws PHP_Exception2 + */ + public function oneLessThrowsTagNeeded() + { + throw new PHP_Exception1('Error'); + + }//end oneLessThrowsTagNeeded() + } + } +} + +abstract class SomeClass { + /** + * Comment here. + */ + abstract public function getGroups(); +} + +class SomeClass { + /** + * Validates something. + * + * @param string $method The set method parameter. + * + * @return string The validated method. + * + * @throws Prefix_Invalid_Argument_Exception The invalid argument exception. + * @throws InvalidArgumentException The invalid argument exception. + */ + protected function validate_something( $something ) { + if ( ! Prefix_Validator::is_string( $something ) ) { + throw Prefix_Invalid_Argument_Exception::invalid_string_parameter( $something, 'something' ); + } + + if ( ! in_array( $something, $this->valid_http_something, true ) ) { + throw new InvalidArgumentException( sprintf( '%s is not a valid HTTP something', $something ) ); + } + + return $something; + } + + /** + * Comment + * + * @throws Exception1 Comment. + * @throws Exception2 Comment. + * @throws Exception3 Comment. + */ + public function foo() { + switch ($foo) { + case 1: + throw Exception1::a(); + case 2: + throw Exception1::b(); + case 3: + throw Exception1::c(); + case 4: + throw Exception2::a(); + case 5: + throw Exception2::b(); + default: + throw new Exception3; + + } + } +} + +namespace Test\Admin { + class NameSpacedClass { + /** + * @throws \ExceptionFromGlobalNamespace + */ + public function ExceptionInGlobalNamespace() { + throw new \ExceptionFromGlobalNamespace(); + } + + /** + * @throws ExceptionFromSameNamespace + */ + public function ExceptionInSameNamespace() { + throw new ExceptionFromSameNamespace(); + } + + /** + * @throws \Test\Admin\ExceptionFromSameNamespace + */ + public function ExceptionInSameNamespaceToo() { + throw new ExceptionFromSameNamespace(); + } + + /** + * @throws \Different\NameSpaceName\ExceptionFromDifferentNamespace + */ + public function ExceptionInSameNamespaceToo() { + throw new \Different\NameSpaceName\ExceptionFromDifferentNamespace(); + } + } +} + +namespace { + class GlobalNameSpaceClass { + /** + * @throws SomeGlobalException + */ + public function ThrowGlobalException() { + throw new SomeGlobalException(); + } + + /** + * @throws \SomeGlobalException + */ + public function ThrowGlobalExceptionToo() { + throw new SomeGlobalException(); + } + } +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.php new file mode 100644 index 00000000..1e2d07fa --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionCommentThrowTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 21 => 1, + 35 => 1, + 47 => 1, + 61 => 2, + 106 => 1, + 123 => 1, + 200 => 1, + 219 => 1, + 287 => 1, + 397 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc new file mode 100644 index 00000000..4f59f60b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc @@ -0,0 +1,1048 @@ +MyClass) + */ +public function caseSensitive($a1, $a2, $a3, arRay $a4, $a5, $a6, myclas $a7) +{ + +}//end caseSensitive() + + +/** + * More type hint check for custom type and array. + * + * @param array $a1 Comment here. + * @param array $a2 Comment here. + * @param MyClass $a3 Comment here. + * @param MyClass $a4 Comment here. + * + * @return array(int => MyClass) + */ +public function typeHint(MyClass $a1, $a2, myclass $a3, $a4) +{ + return (3 => 'myclass obj'); + +}//end typeHint() + + +/** + * Mixed variable type separated by a '|'. + * + * @param array|string $a1 Comment here. + * @param mixed $a2 Comment here. + * @param string|array $a3 Comment here. + * @param MyClass|int $a4 Comment here. + * + * @return bool + */ +public function mixedType($a1, $a2, $a3, $a4) +{ + return true; + +}//end mixedType() + + +/** + * Array type. + * + * @param array(MyClass) $a1 OK. + * @param array() $a2 Invalid type. + * @param array( $a3 Typo. + * @param array(int) $a4 Use 'array(integer)' instead. + * @param array(int => integer) $a5 Use 'array(integer => integer)' instead. + * @param array(integer => bool) $a6 Use 'array(integer => boolean)' instead. + * @param aRRay $a7 Use 'array' instead. + * @param string $a8 String with unknown type hint. + * + * @return int + */ +public function mixedArrayType($a1, $a2, array $a3, $a4, $a5, $a6, $a7, unknownTypeHint $a8) +{ + return 1; + +}//end mixedArrayType() + + +/** + */ +function empty1() +{ +}//end empty1() + + +/** + * + */ +function empty2() +{ +}//end empty2() + + +/** + * + * + * + */ +function empty3() +{ +}//end empty3 + + +/** + * @return boolean + */ +public function missingShortDescriptionInFunctionComment() +{ + return true; + +}//end missingShortDescriptionInFunctionComment() + + +class Another_Class +{ + + /** + * Destructor should not include a return tag. + * + * @return void + */ + function __destruct() + { + return; + } + + /** + * Constructor should not include a return tag. + * + * @return void + */ + function __construct() + { + return; + } + +}//end class + + +/** + * Comment param alignment test. + * + * @param string $varrr1 Comment1.. + * @param string $vr2 Comment2. + * @param string $var3 Comment3.. + * + * @return void + */ +public static function paramAlign($varrr1, $vr2, $var3) +{ + +}//end paramAlign() + + +/** + * Comment. + * + * @param string $id Comment. + * @param array $design Comment. + * + * @return void + */ +public static function paint($id, array $design) +{ + +}//end paint() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @since 4.0.0 + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + } + +}//end myFunction() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + return; + } + + return 'blah'; + +}//end myFunction() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + } + + return 'blah'; + +}//end myFunction() + +/** + * Test function. + * + * @param string $arg1 An argument + * + * @access public + * @return bool + */ + +echo $blah; + +function myFunction($arg1) {} + +class MyClass() { + /** + * An abstract function. + * + * @return string[] + */ + abstract final protected function myFunction(); +} + +/** + * Comment. + * + * @param mixed $test An argument. + * + * @return mixed + */ +function test($test) +{ + if ($test === TRUE) { + return; + } + + return $test; + +}//end test() + + +/** Comment. + * + * @return mixed + * + */ +function test() +{ + +}//end test() + +/** + * Comment. + * + * @param \other\ns\item $test An argument. + * + * @return mixed + */ +function test(\other\ns\item $test) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param item $test An argument. + * + * @return mixed + */ +function test(\other\ns\item $test) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param \first\ns\item $test An argument. + * + * @return mixed + */ +function test(\first\ns\item $test = \second\ns::CONSTANT) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param \first\item $test An argument. + * + * @return mixed + */ +function test(\first\ns\item $test = \second\ns::CONSTANT) +{ + return $test; + +}//end test() + +// Closures should be ignored. +preg_replace_callback( + '~-([a-z])~', + function ($match) { + return strtoupper($match[1]); + }, + 'hello-world' +); + +$callback = function ($bar) use ($foo) + { + $bar += $foo; + }; + +/** + * Comment should end with '*', not '**' before the slash. + **/ +function test123() { + +} + +/** + * Cant use resource for type hint. + * + * @param resource $test An argument. + * + * @return mixed + */ +function test($test) +{ + return $test; + +}//end test() + +/** + * Variable number of args. + * + * @param string $a1 Comment here. + * @param string $a2 Comment here. + * @param string $a2,... Comment here. + * + * @return boolean + */ +public function variableArgs($a1, $a2) +{ + return true; + +}//end variableArgs() + +/** + * Contains closure. + * + * @return void + */ +public function containsClosure() +{ + function ($e) { + return new Event($e); + }, + +}//end containsClosure() + +/** + * 这是一条测试评论. + * + * @return void + */ +public function test() +{ + +}//end variableArgs() + +/** + * Uses callable. + * + * @param callable $cb Test parameter. + * + * @return void + */ +public function usesCallable(callable $cb) { + $cb(); +}//end usesCallable() + +/** + * Creates a map of tokens => line numbers for each token. + * + * @param array $tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to process this file. + * @param string $eolChar The EOL character + * to use for splitting strings. + * + * @return void + * @throws Exception If something really bad + * happens while doing foo. + */ +public function foo(array &$tokens, $tokenizer, $eolChar) +{ + +}//end foo() + +/** + * Some description. + * + * @param \Vendor\Package\SomeClass $someclass Some class. + * @param \OtherVendor\Package\SomeClass2 $someclass2 Some class. + * @param \OtherVendor\Package\SomeClass2 $someclass3 Some class. + * + * @return void + */ +public function foo(SomeClass $someclass, \OtherVendor\Package\SomeClass2 $someclass2, SomeClass3 $someclass3) +{ +} + +/** + * Gettext. + * + * @return string + */ +public function _() { + return $foo; +} + +class Baz { + /** + * The PHP5 constructor + * + * No return tag + */ + public function __construct() { + + } +} + +/** + * Test + * + * @return void + * @throws E + */ +function myFunction() {} + +/** + * Yield test + * + * @return integer + */ +function yieldTest() +{ + for ($i = 0; $i < 5; $i++) { + yield $i; + } +} + +/** + * Yield test + * + * @return void + */ +function yieldTest() +{ + for ($i = 0; $i < 5; $i++) { + yield $i; + } +} + +/** + * Using "array" as a type hint should satisfy a specified array parameter type. + * + * @param MyClass[] $values An array of MyClass objects. + * + * @return void + */ +public function specifiedArray(array $values) { + +}// end specifiedArray() + +/** + * Using "callable" as a type hint should satisfy a "callback" parameter type. + * + * @param callback $cb A callback. + * + * @return void + */ +public function callableCallback(callable $cb) { + +}// end callableCallback() + +/** + * PHP7 type hints. + * + * @param string $name1 Comment. + * @param integer $name2 Comment. + * @param float $name3 Comment. + * @param boolean $name4 Comment. + * + * @return void + */ +public function myFunction (string $name1, int $name2, float $name3, bool $name4) { +} + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string ...$name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} + + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string $name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} + +/** + * Return description function + correct type. + * + * @return integer This is a description. + */ +public function myFunction() { + return 5; +} + +/** + * Return description function + incorrect type. + * + * @return int This is a description. + */ +public function myFunction() { + return 5; +} + +/** + * Return description function + no return. + * + * @return void This is a description. + */ +public function myFunction() { +} + +/** + * Return description function + mixed return. + * + * @return mixed This is a description. + */ +public function myFunction() { +} + +/** + * Function comment. + * + * @param $bar + * Comment here. + * @param ... + * Additional arguments here. + * + * @return + * Return value + * + */ +function foo($bar) { +} + +/** + * Do something. + * + * @return void + */ +public function someFunc(): void +{ + $class = new class + { + /** + * Do something. + * + * @return string + */ + public function getString(): string + { + return 'some string'; + } + }; +} + +/** + * Return description function + mixed return types. + * + * @return bool|int This is a description. + */ +function returnTypeWithDescriptionA() +{ + return 5; + +}//end returnTypeWithDescriptionA() + + +/** + * Return description function + mixed return types. + * + * @return real|bool This is a description. + */ +function returnTypeWithDescriptionB() +{ + return 5; + +}//end returnTypeWithDescriptionB() + + +/** + * Return description function + lots of different mixed return types. + * + * @return int|object|string[]|real|double|float|bool|array(int=>MyClass)|callable And here we have a description + */ +function returnTypeWithDescriptionC() +{ + return 5; + +}//end returnTypeWithDescriptionC() + + +/** + * Return description function + lots of different mixed return types. + * + * @return array(int=>bool)|\OtherVendor\Package\SomeClass2|MyClass[]|void And here we have a description + */ +function returnTypeWithDescriptionD() +{ + +}//end returnTypeWithDescriptionD() + +/** + * Yield from test + * + * @return int[] + */ +function yieldFromTest() +{ + yield from foo(); +} + +/** + * Audio + * + * Generates an audio element to embed sounds + * + * @param mixed $src Either a source string or + * an array of sources. + * @param mixed $unsupportedMessage The message to display + * if the media tag is not supported by the browser. + * @param mixed $attributes HTML attributes. + * @return string + */ +function audio( + $src, + $unsupportedMessage = '', + $attributes = '', +) +{ + return 'test'; +} + +/** + * Test function + * + * @return array + */ +function returnArrayWithClosure() +{ + function () { + return; + }; + + return []; +} + +/** + * Test function + * + * @return array + */ +function returnArrayWithAnonymousClass() +{ + new class { + /** + * @return void + */ + public function test() { + return; + } + }; + + return []; +} + +/** + * @return void + */ +function returnVoidWithClosure() +{ + function () { + return 1; + }; +} + +/** + * @return void + */ +function returnVoidWithAnonymousClass() +{ + new class { + /** + * @return integer + */ + public function test() + { + return 1; + } + }; +} + +class TestReturnVoid +{ + /** + * @return void + */ + public function test() + { + function () { + return 4; + }; + } +} + +/** + * Comment here. + * + * @param integer $a This is A. + * @param ?array $b This is B. + * + * @return void + */ +public static function foo(?int $a, ?array $b) {} + +/** + * Comment here. + * + * @param object $a This is A. + * @param object $b This is B. + * + * @return void + */ +public function foo(object $a, ?object $b) {} + +/** + * Prepares given PHP class method for later code building. + * + * @param integer $foo Comment. + * - Additional comment. + * + * @return void + */ +function foo($foo) {} + +/** + * {@inheritDoc} + */ +public function foo($a, $b) {} + +// phpcs:set Squiz.Commenting.FunctionComment skipIfInheritdoc true + +/** + * {@inheritDoc} + */ +public function foo($a, $b) {} + +/** + * Foo. + * + * @param mixed $a Comment. + * + * @return mixed + */ +public function foo(mixed $a): mixed {} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] +class Bar { + /** + * The PHP5 constructor + */ + public function __construct() { + + } +} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] ignored +/** + * Should be ok + */ +public function ignored() { + +} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] __construct,__destruct + +/** + * @return void + * @throws Exception If any other error occurs. */ +function throwCommentOneLine() {} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc.fixed new file mode 100644 index 00000000..21a4103e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc.fixed @@ -0,0 +1,1048 @@ + MyClass) + */ +public function caseSensitive($a1, $a2, $a3, arRay $a4, $a5, $a6, myclas $a7) +{ + +}//end caseSensitive() + + +/** + * More type hint check for custom type and array. + * + * @param array $a1 Comment here. + * @param array $a2 Comment here. + * @param MyClass $a3 Comment here. + * @param MyClass $a4 Comment here. + * + * @return array(integer => MyClass) + */ +public function typeHint(MyClass $a1, $a2, myclass $a3, $a4) +{ + return (3 => 'myclass obj'); + +}//end typeHint() + + +/** + * Mixed variable type separated by a '|'. + * + * @param array|string $a1 Comment here. + * @param mixed $a2 Comment here. + * @param string|array $a3 Comment here. + * @param MyClass|integer $a4 Comment here. + * + * @return boolean + */ +public function mixedType($a1, $a2, $a3, $a4) +{ + return true; + +}//end mixedType() + + +/** + * Array type. + * + * @param array(MyClass) $a1 OK. + * @param array $a2 Invalid type. + * @param array $a3 Typo. + * @param array(integer) $a4 Use 'array(integer)' instead. + * @param array(integer => integer) $a5 Use 'array(integer => integer)' instead. + * @param array(integer => boolean) $a6 Use 'array(integer => boolean)' instead. + * @param array $a7 Use 'array' instead. + * @param string $a8 String with unknown type hint. + * + * @return integer + */ +public function mixedArrayType($a1, $a2, array $a3, $a4, $a5, $a6, $a7, unknownTypeHint $a8) +{ + return 1; + +}//end mixedArrayType() + + +/** + */ +function empty1() +{ +}//end empty1() + + +/** + * + */ +function empty2() +{ +}//end empty2() + + +/** + * + * + * + */ +function empty3() +{ +}//end empty3 + + +/** + * @return boolean + */ +public function missingShortDescriptionInFunctionComment() +{ + return true; + +}//end missingShortDescriptionInFunctionComment() + + +class Another_Class +{ + + /** + * Destructor should not include a return tag. + * + * @return void + */ + function __destruct() + { + return; + } + + /** + * Constructor should not include a return tag. + * + * @return void + */ + function __construct() + { + return; + } + +}//end class + + +/** + * Comment param alignment test. + * + * @param string $varrr1 Comment1.. + * @param string $vr2 Comment2. + * @param string $var3 Comment3.. + * + * @return void + */ +public static function paramAlign($varrr1, $vr2, $var3) +{ + +}//end paramAlign() + + +/** + * Comment. + * + * @param string $id Comment. + * @param array $design Comment. + * + * @return void + */ +public static function paint($id, array $design) +{ + +}//end paint() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @since 4.0.0 + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + } + +}//end myFunction() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + return; + } + + return 'blah'; + +}//end myFunction() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + } + + return 'blah'; + +}//end myFunction() + +/** + * Test function. + * + * @param string $arg1 An argument + * + * @access public + * @return bool + */ + +echo $blah; + +function myFunction($arg1) {} + +class MyClass() { + /** + * An abstract function. + * + * @return string[] + */ + abstract final protected function myFunction(); +} + +/** + * Comment. + * + * @param mixed $test An argument. + * + * @return mixed + */ +function test($test) +{ + if ($test === TRUE) { + return; + } + + return $test; + +}//end test() + + +/** Comment. + * + * @return mixed + * + */ +function test() +{ + +}//end test() + +/** + * Comment. + * + * @param \other\ns\item $test An argument. + * + * @return mixed + */ +function test(\other\ns\item $test) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param item $test An argument. + * + * @return mixed + */ +function test(\other\ns\item $test) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param \first\ns\item $test An argument. + * + * @return mixed + */ +function test(\first\ns\item $test = \second\ns::CONSTANT) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param \first\item $test An argument. + * + * @return mixed + */ +function test(\first\ns\item $test = \second\ns::CONSTANT) +{ + return $test; + +}//end test() + +// Closures should be ignored. +preg_replace_callback( + '~-([a-z])~', + function ($match) { + return strtoupper($match[1]); + }, + 'hello-world' +); + +$callback = function ($bar) use ($foo) + { + $bar += $foo; + }; + +/** + * Comment should end with '*', not '**' before the slash. + **/ +function test123() { + +} + +/** + * Cant use resource for type hint. + * + * @param resource $test An argument. + * + * @return mixed + */ +function test($test) +{ + return $test; + +}//end test() + +/** + * Variable number of args. + * + * @param string $a1 Comment here. + * @param string $a2 Comment here. + * @param string $a2,... Comment here. + * + * @return boolean + */ +public function variableArgs($a1, $a2) +{ + return true; + +}//end variableArgs() + +/** + * Contains closure. + * + * @return void + */ +public function containsClosure() +{ + function ($e) { + return new Event($e); + }, + +}//end containsClosure() + +/** + * 这是一条测试评论. + * + * @return void + */ +public function test() +{ + +}//end variableArgs() + +/** + * Uses callable. + * + * @param callable $cb Test parameter. + * + * @return void + */ +public function usesCallable(callable $cb) { + $cb(); +}//end usesCallable() + +/** + * Creates a map of tokens => line numbers for each token. + * + * @param array $tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to process this file. + * @param string $eolChar The EOL character + * to use for splitting strings. + * + * @return void + * @throws Exception If something really bad + * happens while doing foo. + */ +public function foo(array &$tokens, $tokenizer, $eolChar) +{ + +}//end foo() + +/** + * Some description. + * + * @param \Vendor\Package\SomeClass $someclass Some class. + * @param \OtherVendor\Package\SomeClass2 $someclass2 Some class. + * @param \OtherVendor\Package\SomeClass2 $someclass3 Some class. + * + * @return void + */ +public function foo(SomeClass $someclass, \OtherVendor\Package\SomeClass2 $someclass2, SomeClass3 $someclass3) +{ +} + +/** + * Gettext. + * + * @return string + */ +public function _() { + return $foo; +} + +class Baz { + /** + * The PHP5 constructor + * + * No return tag + */ + public function __construct() { + + } +} + +/** + * Test + * + * @return void + * @throws E + */ +function myFunction() {} + +/** + * Yield test + * + * @return integer + */ +function yieldTest() +{ + for ($i = 0; $i < 5; $i++) { + yield $i; + } +} + +/** + * Yield test + * + * @return void + */ +function yieldTest() +{ + for ($i = 0; $i < 5; $i++) { + yield $i; + } +} + +/** + * Using "array" as a type hint should satisfy a specified array parameter type. + * + * @param MyClass[] $values An array of MyClass objects. + * + * @return void + */ +public function specifiedArray(array $values) { + +}// end specifiedArray() + +/** + * Using "callable" as a type hint should satisfy a "callback" parameter type. + * + * @param callback $cb A callback. + * + * @return void + */ +public function callableCallback(callable $cb) { + +}// end callableCallback() + +/** + * PHP7 type hints. + * + * @param string $name1 Comment. + * @param integer $name2 Comment. + * @param float $name3 Comment. + * @param boolean $name4 Comment. + * + * @return void + */ +public function myFunction (string $name1, int $name2, float $name3, bool $name4) { +} + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string ...$name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} + + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string $name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} + +/** + * Return description function + correct type. + * + * @return integer This is a description. + */ +public function myFunction() { + return 5; +} + +/** + * Return description function + incorrect type. + * + * @return integer This is a description. + */ +public function myFunction() { + return 5; +} + +/** + * Return description function + no return. + * + * @return void This is a description. + */ +public function myFunction() { +} + +/** + * Return description function + mixed return. + * + * @return mixed This is a description. + */ +public function myFunction() { +} + +/** + * Function comment. + * + * @param $bar + * Comment here. + * @param ... + * Additional arguments here. + * + * @return + * Return value + * + */ +function foo($bar) { +} + +/** + * Do something. + * + * @return void + */ +public function someFunc(): void +{ + $class = new class + { + /** + * Do something. + * + * @return string + */ + public function getString(): string + { + return 'some string'; + } + }; +} + +/** + * Return description function + mixed return types. + * + * @return boolean|integer This is a description. + */ +function returnTypeWithDescriptionA() +{ + return 5; + +}//end returnTypeWithDescriptionA() + + +/** + * Return description function + mixed return types. + * + * @return float|boolean This is a description. + */ +function returnTypeWithDescriptionB() +{ + return 5; + +}//end returnTypeWithDescriptionB() + + +/** + * Return description function + lots of different mixed return types. + * + * @return integer|object|string[]|float|boolean|array(integer => MyClass)|callable And here we have a description + */ +function returnTypeWithDescriptionC() +{ + return 5; + +}//end returnTypeWithDescriptionC() + + +/** + * Return description function + lots of different mixed return types. + * + * @return array(integer => boolean)|\OtherVendor\Package\SomeClass2|MyClass[]|void And here we have a description + */ +function returnTypeWithDescriptionD() +{ + +}//end returnTypeWithDescriptionD() + +/** + * Yield from test + * + * @return int[] + */ +function yieldFromTest() +{ + yield from foo(); +} + +/** + * Audio + * + * Generates an audio element to embed sounds + * + * @param mixed $src Either a source string or + * an array of sources. + * @param mixed $unsupportedMessage The message to display + * if the media tag is not supported by the browser. + * @param mixed $attributes HTML attributes. + * @return string + */ +function audio( + $src, + $unsupportedMessage = '', + $attributes = '', +) +{ + return 'test'; +} + +/** + * Test function + * + * @return array + */ +function returnArrayWithClosure() +{ + function () { + return; + }; + + return []; +} + +/** + * Test function + * + * @return array + */ +function returnArrayWithAnonymousClass() +{ + new class { + /** + * @return void + */ + public function test() { + return; + } + }; + + return []; +} + +/** + * @return void + */ +function returnVoidWithClosure() +{ + function () { + return 1; + }; +} + +/** + * @return void + */ +function returnVoidWithAnonymousClass() +{ + new class { + /** + * @return integer + */ + public function test() + { + return 1; + } + }; +} + +class TestReturnVoid +{ + /** + * @return void + */ + public function test() + { + function () { + return 4; + }; + } +} + +/** + * Comment here. + * + * @param integer $a This is A. + * @param array $b This is B. + * + * @return void + */ +public static function foo(?int $a, ?array $b) {} + +/** + * Comment here. + * + * @param object $a This is A. + * @param object $b This is B. + * + * @return void + */ +public function foo(object $a, ?object $b) {} + +/** + * Prepares given PHP class method for later code building. + * + * @param integer $foo Comment. + * - Additional comment. + * + * @return void + */ +function foo($foo) {} + +/** + * {@inheritDoc} + */ +public function foo($a, $b) {} + +// phpcs:set Squiz.Commenting.FunctionComment skipIfInheritdoc true + +/** + * {@inheritDoc} + */ +public function foo($a, $b) {} + +/** + * Foo. + * + * @param mixed $a Comment. + * + * @return mixed + */ +public function foo(mixed $a): mixed {} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] +class Bar { + /** + * The PHP5 constructor + */ + public function __construct() { + + } +} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] ignored +/** + * Should be ok + */ +public function ignored() { + +} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] __construct,__destruct + +/** + * @return void + * @throws Exception If any other error occurs. */ +function throwCommentOneLine() {} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php new file mode 100644 index 00000000..632b7c51 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php @@ -0,0 +1,177 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 5 => 1, + 10 => 3, + 12 => 2, + 13 => 2, + 14 => 1, + 15 => 1, + 28 => 1, + 43 => 1, + 76 => 1, + 87 => 1, + 103 => 1, + 109 => 1, + 112 => 1, + 122 => 1, + 123 => 3, + 124 => 2, + 125 => 1, + 126 => 1, + 137 => 4, + 138 => 4, + 139 => 4, + 143 => 2, + 152 => 1, + 155 => 2, + 159 => 1, + 166 => 1, + 173 => 1, + 183 => 1, + 190 => 2, + 193 => 2, + 196 => 1, + 199 => 2, + 210 => 1, + 211 => 1, + 222 => 1, + 223 => 1, + 224 => 1, + 225 => 1, + 226 => 1, + 227 => 1, + 230 => 2, + 232 => 2, + 246 => 1, + 248 => 4, + 261 => 1, + 263 => 1, + 276 => 1, + 277 => 1, + 278 => 1, + 279 => 1, + 280 => 1, + 281 => 1, + 284 => 1, + 286 => 7, + 294 => 1, + 302 => 1, + 312 => 1, + 358 => 1, + 359 => 2, + 372 => 1, + 373 => 1, + 387 => 1, + 407 => 1, + 441 => 1, + 500 => 1, + 526 => 1, + 548 => 1, + 641 => 1, + 669 => 1, + 688 => 1, + 744 => 1, + 748 => 1, + 767 => 1, + 789 => 1, + 792 => 1, + 794 => 1, + 797 => 1, + 801 => 1, + 828 => 1, + 840 => 1, + 852 => 1, + 864 => 1, + 886 => 1, + 888 => 1, + 890 => 1, + 978 => 1, + 997 => 1, + 1004 => 2, + 1006 => 1, + 1029 => 1, + ]; + + // Scalar type hints only work from PHP 7 onwards. + if (PHP_VERSION_ID >= 70000) { + $errors[17] = 3; + $errors[128] = 1; + $errors[143] = 3; + $errors[161] = 2; + $errors[201] = 1; + $errors[232] = 7; + $errors[363] = 3; + $errors[377] = 1; + $errors[575] = 2; + $errors[627] = 1; + $errors[1002] = 1; + } else { + $errors[729] = 4; + $errors[740] = 2; + $errors[752] = 2; + $errors[982] = 1; + } + + // Object type hints only work from PHP 7.2 onwards. + if (PHP_VERSION_ID >= 70200) { + $errors[627] = 2; + } else { + $errors[992] = 2; + } + + // Mixed type hints only work from PHP 8.0 onwards. + if (PHP_VERSION_ID >= 80000) { + $errors[265] = 1; + $errors[459] = 1; + $errors[893] = 3; + } else { + $errors[1023] = 1; + } + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc new file mode 100644 index 00000000..10a0b4b4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc @@ -0,0 +1,183 @@ + One +// -> One.One +// -> Two + +/* + Here is some inline example code: + -> One + -> One.One + -> Two +*/ + +/** + * Comment should be ignored in PHP 5.4. + * + */ +trait MyTrait { + +} + +$foo = 'foo'; // Var set to foo. + +echo $foo; + +// Comment here. +echo $foo; + +/** + * Comments about the include + */ +include_once($blah); + +// some comment without capital or full stop +echo $foo; // An unrelated comment. + +// An unrelated comment. +echo $foo; // some comment without capital or full stop + +class Foo +{ + // This is fine. + + /** + * Spacing is ignored above. + */ + function bar(){} +} + +if ($foo) { +}//end if +// Another comment here. +$foo++; + +if ($foo) { +}//end if +// another comment here. +$foo++; + +/** + * Comment should be ignored, even though there is an attribute between the docblock and the class declaration. + */ + +#[AttributeA] + +final class MyClass +{ + /** + * Comment should be ignored, even though there is an attribute between the docblock and the function declaration + */ + #[AttributeA] + #[AttributeB] + final public function test() {} +} + +/** + * Comment should be ignored. + * + */ +enum MyEnum { + +} + +/* + * N.B.: The below test line must be the last test in the file. + * Testing that a new line after an inline comment when it's the last non-whitespace + * token in a file, does *not* throw an error as this would conflict with the common + * "new line required at end of file" rule. + */ + +// For this test line having an empty line below it, is fine. diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc.fixed new file mode 100644 index 00000000..97ae0149 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc.fixed @@ -0,0 +1,176 @@ + One +// -> One.One +// -> Two +/* + Here is some inline example code: + -> One + -> One.One + -> Two +*/ + +/** + * Comment should be ignored in PHP 5.4. + * + */ +trait MyTrait { + +} + +$foo = 'foo'; // Var set to foo. + +echo $foo; + +// Comment here. +echo $foo; + +/** + * Comments about the include + */ +include_once($blah); + +// some comment without capital or full stop +echo $foo; // An unrelated comment. + +// An unrelated comment. +echo $foo; // some comment without capital or full stop + +class Foo +{ + // This is fine. + + /** + * Spacing is ignored above. + */ + function bar(){} +} + +if ($foo) { +}//end if +// Another comment here. +$foo++; + +if ($foo) { +}//end if +// another comment here. +$foo++; + +/** + * Comment should be ignored, even though there is an attribute between the docblock and the class declaration. + */ + +#[AttributeA] + +final class MyClass +{ + /** + * Comment should be ignored, even though there is an attribute between the docblock and the function declaration + */ + #[AttributeA] + #[AttributeB] + final public function test() {} +} + +/** + * Comment should be ignored. + * + */ +enum MyEnum { + +} + +/* + * N.B.: The below test line must be the last test in the file. + * Testing that a new line after an inline comment when it's the last non-whitespace + * token in a file, does *not* throw an error as this would conflict with the common + * "new line required at end of file" rule. + */ + +// For this test line having an empty line below it, is fine. diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js new file mode 100644 index 00000000..6b1093e6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js @@ -0,0 +1,129 @@ +// Some content here. +var code = 'hello'; + +// This comment contains # multiple +// hash signs (#). +code = 'hello'; + +/** + * This is the first line of a function comment. + * This is the second line. + */ +function testFunction() +{ + // Callback methods which are added by external objects. + this.callbacks = {}; + +}//end testFunction() + +/** + * This is the first line of a class comment. + * This is the second line. + */ +myClass.prototype = { + + /** + * This is the first line of a method comment. + * This is the second line. + */ + load: function(url, callback) + { + // Some code here. + + } +}; + +// some code goes here! + +/* + A longer comment goes here. + It spans multiple lines!! + Or does it? +*/ + +// 0This is a simple multi-line +// comment! +code = 'hello'; + +//This is not valid. +code = 'hello'; + +// Neither is this! +code = 'hello'; + +// +code = 'hello'; + +/** Neither is this! **/ +code = 'hello'; + +/** + * This is the first line of a function comment. + * This is the second line. + */ +var myFunction = function() { +} + +/** + * This is the first line of a function comment. + * This is the second line. + */ +myFunction = function() { +} + +/** + * This is the first line of a function comment. + * This is the second line. + */ +myClass.myFunction = function() { +} + +dfx.getIframeDocument = function(iframe) +{ + return doc; + +};//end dfx.getIframeDocument() + +mig.Gallery.prototype = { + + init: function(cb) + { + + },//end init() + + imageClicked: function(id) + { + + }//end imageClicked() + +}; + +// Here is some inline example code: +// -> One +// -> One.One +// -> Two + +/* + Here is some inline example code: + -> One + -> One.One + -> Two +*/ + + +var foo = 'foo'; // Var set to foo. + +console.info(foo); + +// Comment here. +console.info(foo); + +//** +* invalid comment +*/ + +// some comment without capital or full stop +console.log(foo); // An unrelated comment. + +// An unrelated comment. +console.log(foo); // some comment without capital or full stop diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js.fixed new file mode 100644 index 00000000..20e5041e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js.fixed @@ -0,0 +1,125 @@ +// Some content here. +var code = 'hello'; + +// This comment contains # multiple +// hash signs (#). +code = 'hello'; + +/** + * This is the first line of a function comment. + * This is the second line. + */ +function testFunction() +{ + // Callback methods which are added by external objects. + this.callbacks = {}; + +}//end testFunction() + +/** + * This is the first line of a class comment. + * This is the second line. + */ +myClass.prototype = { + + /** + * This is the first line of a method comment. + * This is the second line. + */ + load: function(url, callback) + { + // Some code here. + } +}; + +// some code goes here! +/* + A longer comment goes here. + It spans multiple lines!! + Or does it? +*/ + +// 0This is a simple multi-line +// comment! +code = 'hello'; + +// This is not valid. +code = 'hello'; + +// Neither is this! +code = 'hello'; + +code = 'hello'; + +/** Neither is this! **/ +code = 'hello'; + +/** + * This is the first line of a function comment. + * This is the second line. + */ +var myFunction = function() { +} + +/** + * This is the first line of a function comment. + * This is the second line. + */ +myFunction = function() { +} + +/** + * This is the first line of a function comment. + * This is the second line. + */ +myClass.myFunction = function() { +} + +dfx.getIframeDocument = function(iframe) +{ + return doc; + +};//end dfx.getIframeDocument() + +mig.Gallery.prototype = { + + init: function(cb) + { + + },//end init() + + imageClicked: function(id) + { + + }//end imageClicked() + +}; + +// Here is some inline example code: +// -> One +// -> One.One +// -> Two +/* + Here is some inline example code: + -> One + -> One.One + -> Two +*/ + + +var foo = 'foo'; // Var set to foo. + +console.info(foo); + +// Comment here. +console.info(foo); + +// ** +* invalid comment +*/ + +// some comment without capital or full stop +console.log(foo); // An unrelated comment. + +// An unrelated comment. +console.log(foo); // some comment without capital or full stop diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.php new file mode 100644 index 00000000..e4a5298b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class InlineCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='InlineCommentUnitTest.inc') + { + switch ($testFile) { + case 'InlineCommentUnitTest.inc': + $errors = [ + 17 => 1, + 27 => 1, + 28 => 1, + 32 => 2, + 36 => 1, + 44 => 2, + 58 => 1, + 61 => 1, + 64 => 1, + 67 => 1, + 95 => 1, + 96 => 1, + 97 => 3, + 118 => 1, + 126 => 2, + 130 => 2, + 149 => 1, + ]; + + return $errors; + case 'InlineCommentUnitTest.js': + return [ + 31 => 1, + 36 => 2, + 48 => 1, + 51 => 1, + 54 => 1, + 57 => 1, + 102 => 1, + 103 => 1, + 104 => 3, + 118 => 1, + 121 => 1, + 125 => 2, + 129 => 2, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc new file mode 100644 index 00000000..d6c4cf6c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc @@ -0,0 +1,1033 @@ + match ($foo) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 + }, +]; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc.fixed new file mode 100644 index 00000000..176cfe24 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc.fixed @@ -0,0 +1,1033 @@ + match ($foo) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 + },//end match +]; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js new file mode 100644 index 00000000..c0cf2821 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js @@ -0,0 +1,444 @@ +function long_function() +{ + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } else { + // Short ELSE + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } else { + // Short ELSE + } +} + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end for + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + for (val =1; val < 20; val++) { + // Short for. + } + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end while + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + while (something) { + // Short while. + } + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} + +if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } +} //end if + +if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } +} else { + // Short ELSE +} //end if + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} //end for + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} //end while + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end for + +if (true) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} else if (condition) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} else { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end if + +if (something) { + // Line 1 + // Line 2 +} else if (somethingElse) { + // Line 1 + // Line 2 +} else { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} + +switch (something) { + case '1': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '2': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '3': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '4': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '5': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; +} + +// Wrong comment +if (condition) { + condition = true; +}//end foreach diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js.fixed new file mode 100644 index 00000000..231b51c5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js.fixed @@ -0,0 +1,444 @@ +function long_function() +{ + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } else { + // Short ELSE + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } else { + // Short ELSE + }//end if +} + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end for + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + for (val =1; val < 20; val++) { + // Short for. + } + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end for + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end while + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + while (something) { + // Short while. + } + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end while + +if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } +} //end if + +if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } +} else { + // Short ELSE +} //end if + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} //end for + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} //end while + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end while + +if (true) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} else if (condition) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} else { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end if + +if (something) { + // Line 1 + // Line 2 +} else if (somethingElse) { + // Line 1 + // Line 2 +} else { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end if + +switch (something) { + case '1': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '2': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '3': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '4': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '5': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; +}//end switch + +// Wrong comment +if (condition) { + condition = true; +}//end if diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.php new file mode 100644 index 00000000..5b61612c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.php @@ -0,0 +1,103 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LongConditionClosingCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='LongConditionClosingCommentUnitTest.inc') + { + switch ($testFile) { + case 'LongConditionClosingCommentUnitTest.inc': + return [ + 49 => 1, + 99 => 1, + 146 => 1, + 192 => 1, + 215 => 1, + 238 => 1, + 261 => 1, + 286 => 1, + 309 => 1, + 332 => 1, + 355 => 1, + 378 => 1, + 493 => 1, + 531 => 1, + 536 => 1, + 540 => 1, + 562 => 1, + 601 => 1, + 629 => 1, + 663 => 1, + 765 => 1, + 798 => 1, + 811 => 1, + 897 => 1, + 931 => 1, + 962 => 1, + 985 => 2, + 1008 => 1, + 1032 => 1, + ]; + break; + case 'LongConditionClosingCommentUnitTest.js': + return [ + 47 => 1, + 97 => 1, + 144 => 1, + 190 => 1, + 213 => 1, + 238 => 1, + 261 => 1, + 284 => 1, + 307 => 1, + 401 => 1, + 439 => 1, + 444 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js new file mode 100644 index 00000000..6de64210 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js @@ -0,0 +1,36 @@ +function test(id, buttons) // cool function +{ + alert('hello'); + alert('hello again'); // And again. + // Valid comment. + +}//end test() + +var good = true; // Indeed. + +mig.Gallery.prototype = { + + init: function(cb) + { + + },//end init() + + imageClicked: function(id) + { + + }//end imageClicked() + +}; + +dfx.getIframeDocument = function(iframe) +{ + + return doc; + +};//end dfx.getIframeDocument() + +// Verify that multi-line control structure with comments and annotations are left alone. +if (condition // comment + && anotherCondition) { + condition = true; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js.fixed new file mode 100644 index 00000000..1953760d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js.fixed @@ -0,0 +1,39 @@ +function test(id, buttons) +// cool function +{ + alert('hello'); + alert('hello again'); +// And again. + // Valid comment. + +}//end test() + +var good = true; +// Indeed. + +mig.Gallery.prototype = { + + init: function(cb) + { + + },//end init() + + imageClicked: function(id) + { + + }//end imageClicked() + +}; + +dfx.getIframeDocument = function(iframe) +{ + + return doc; + +};//end dfx.getIframeDocument() + +// Verify that multi-line control structure with comments and annotations are left alone. +if (condition // comment + && anotherCondition) { + condition = true; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.2.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.2.js new file mode 100644 index 00000000..88d0e7d4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.2.js @@ -0,0 +1,2 @@ +// Comment as first thing in a JS file. +var i = 100; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc new file mode 100644 index 00000000..b8346961 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc @@ -0,0 +1,54 @@ + function($b) { + }, // comment. + 'key' => 'value', // phpcs:ignore Standard.Category.SniffName -- for reasons. + 'key' => 'value', // comment. +]; + +// Verify that multi-line control structure with comments and annotations are left alone. +for ( + $i = 0; /* Start */ + $i < 10; /* phpcs:ignore Standard.Category.SniffName -- for reasons. */ + $i++ // comment + +) {} + +if ( $condition === true // comment + && $anotherCondition === false +) {} + +$match = match($foo // comment + && $bar +) { + 1 => 1, // comment +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc.fixed new file mode 100644 index 00000000..21a4bbe0 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc.fixed @@ -0,0 +1,59 @@ + function($b) { + }, // comment. + 'key' => 'value', // phpcs:ignore Standard.Category.SniffName -- for reasons. + 'key' => 'value', +// comment. +]; + +// Verify that multi-line control structure with comments and annotations are left alone. +for ( + $i = 0; /* Start */ + $i < 10; /* phpcs:ignore Standard.Category.SniffName -- for reasons. */ + $i++ // comment + +) {} + +if ( $condition === true // comment + && $anotherCondition === false +) {} + +$match = match($foo // comment + && $bar +) { + 1 => 1, +// comment +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.php new file mode 100644 index 00000000..a04426f1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.php @@ -0,0 +1,69 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class PostStatementCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='PostStatementCommentUnitTest.inc') + { + switch ($testFile) { + case 'PostStatementCommentUnitTest.inc': + return [ + 6 => 1, + 10 => 1, + 18 => 1, + 35 => 1, + 53 => 1, + ]; + + case 'PostStatementCommentUnitTest.1.js': + return [ + 1 => 1, + 4 => 1, + 9 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc new file mode 100644 index 00000000..36efc443 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc @@ -0,0 +1,404 @@ + $content) { + echo $content; + } + + return $var1; + + }//end checkVariable() + + + /** + * + * + */ + $emptyVarDoc = ''; + + /** + * Var type checking (int v.s. integer). + * + * @var int + */ + private $_varSimpleTypeCheck; + + + /** + * Var type checking (array(int => string) v.s. array(int => string)). + * + * @var array(int => string) + */ + private $_varArrayTypeCheck; + + + /** + * Boolean @var tag Capitalized + * + * @var Boolean + */ + public $CapBoolTag = true; + + + /** + * Boolean @var tag Capitalized + * + * @var BOOLEAN + */ + public $CapBoolTag2 = true; + + + /** + * Double @var tag Capitalized + * + * @var Double + */ + public $CapDoubleTag = 1; + + + /** + * Double @var tag Capitalized + * + * @var DOUBLE + */ + public $CapDoubleTag2 = 1; + + + /** + * Real @var tag Capitalized + * + * @var Real + */ + public $CapRealTag = 1; + + + /** + * Real @var tag Capitalized + * + * @var REAL + */ + public $CapRealTag2 = 1; + + + /** + * Float @var tag Capitalized + * + * @var Float + */ + public $CapFloatTag = 1; + + + /** + * Float @var tag Capitalized + * + * @var FLOAT + */ + public $CapFloatTag2 = 1; + + + /** + * Int @var tag Capitalized + * + * @var Int + */ + public $CapIntTag = 1; + + + /** + * Int @var tag Capitalized + * + * @var INT + */ + public $CapIntTag2 = 1; + + + /** + * Integer @var tag Capitalized + * + * @var Integer + */ + public $CapIntTag3 = 1; + + + /** + * Integer @var tag Capitalized + * + * @var INTEGER + */ + public $CapIntTag4 = 1; + + + /** + * Array @var tag Capitalized + * + * @var Array + */ + public $CapVarTag = []; + + + /** + * Array @var tag All Caps + * + * @var ARRAY + */ + public $CapVarTag2 = []; + + + /** + * Array @var tag Capitalized + * + * @var Array() + */ + public $CapVarTag3 = []; + + + /** + * Array @var tag All Caps + * + * @var ARRAY() + */ + public $CapVarTag4 = []; + + + /** + * Var type checking (STRING v.s. string). + * + * @var STRING + */ + private $_varCaseTypeCheck; + + + /** + * @var integer + */ + private $_varWithNoShortComment; + + protected $noComment2 = ''; + + + /** + * @var int Var type checking (int v.s. integer) with single-line comment. + */ + private $_varSimpleTypeCheckSingleLine; + + +}//end class + + +/** + * VariableCommentUnitTest2. + * + * Long description goes here. + * + */ +class VariableCommentUnitTest2 +{ + + public $hello; + + /** Comment starts here. + * + * @var string + * + */ + private $_varCaseTypeCheck; + + /** + * 这是一条测试评论. + * + * @var string + */ + public $foo; + +}//end class + + +/* + * Class comment + */ +class Foo +{ + + protected $bar; + + /** + * Short description of the member variable. + * + * @var array + */ + public static array $variableName = array(); + +} + +class Foo +{ + + /** + * Short description of the member variable. + * + * @var array + */ + public array $variableName = array(); + + + // Not "/**" style comment. + // + // @var string + private ?Folder\ClassName $_incorrectCommentStyle = null; + + + var int $noComment = 1; + } + +class HasAttributes +{ + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\Id]#[ORM\Column("integer")] + private $id; + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\GeneratedValue] + #[ORM\Column(ORM\Column::T_INTEGER)] + protected $height; +} + +class ReadOnlyProps +{ + /** + * Short description of the member variable. + * + * @var array + */ + public readonly array $variableName = array(); + + /** + * Short description of the member variable. + * + * @var + */ + readonly protected ?int $variableName = 10; + + private readonly string $variable; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc.fixed new file mode 100644 index 00000000..5c652f54 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc.fixed @@ -0,0 +1,404 @@ + $content) { + echo $content; + } + + return $var1; + + }//end checkVariable() + + + /** + * + * + */ + $emptyVarDoc = ''; + + /** + * Var type checking (int v.s. integer). + * + * @var integer + */ + private $_varSimpleTypeCheck; + + + /** + * Var type checking (array(int => string) v.s. array(int => string)). + * + * @var array(integer => string) + */ + private $_varArrayTypeCheck; + + + /** + * Boolean @var tag Capitalized + * + * @var boolean + */ + public $CapBoolTag = true; + + + /** + * Boolean @var tag Capitalized + * + * @var boolean + */ + public $CapBoolTag2 = true; + + + /** + * Double @var tag Capitalized + * + * @var float + */ + public $CapDoubleTag = 1; + + + /** + * Double @var tag Capitalized + * + * @var float + */ + public $CapDoubleTag2 = 1; + + + /** + * Real @var tag Capitalized + * + * @var float + */ + public $CapRealTag = 1; + + + /** + * Real @var tag Capitalized + * + * @var float + */ + public $CapRealTag2 = 1; + + + /** + * Float @var tag Capitalized + * + * @var float + */ + public $CapFloatTag = 1; + + + /** + * Float @var tag Capitalized + * + * @var float + */ + public $CapFloatTag2 = 1; + + + /** + * Int @var tag Capitalized + * + * @var integer + */ + public $CapIntTag = 1; + + + /** + * Int @var tag Capitalized + * + * @var integer + */ + public $CapIntTag2 = 1; + + + /** + * Integer @var tag Capitalized + * + * @var integer + */ + public $CapIntTag3 = 1; + + + /** + * Integer @var tag Capitalized + * + * @var integer + */ + public $CapIntTag4 = 1; + + + /** + * Array @var tag Capitalized + * + * @var array + */ + public $CapVarTag = []; + + + /** + * Array @var tag All Caps + * + * @var array + */ + public $CapVarTag2 = []; + + + /** + * Array @var tag Capitalized + * + * @var array + */ + public $CapVarTag3 = []; + + + /** + * Array @var tag All Caps + * + * @var array + */ + public $CapVarTag4 = []; + + + /** + * Var type checking (STRING v.s. string). + * + * @var string + */ + private $_varCaseTypeCheck; + + + /** + * @var integer + */ + private $_varWithNoShortComment; + + protected $noComment2 = ''; + + + /** + * @var integer Var type checking (int v.s. integer) with single-line comment. + */ + private $_varSimpleTypeCheckSingleLine; + + +}//end class + + +/** + * VariableCommentUnitTest2. + * + * Long description goes here. + * + */ +class VariableCommentUnitTest2 +{ + + public $hello; + + /** Comment starts here. + * + * @var string + * + */ + private $_varCaseTypeCheck; + + /** + * 这是一条测试评论. + * + * @var string + */ + public $foo; + +}//end class + + +/* + * Class comment + */ +class Foo +{ + + protected $bar; + + /** + * Short description of the member variable. + * + * @var array + */ + public static array $variableName = array(); + +} + +class Foo +{ + + /** + * Short description of the member variable. + * + * @var array + */ + public array $variableName = array(); + + + // Not "/**" style comment. + // + // @var string + private ?Folder\ClassName $_incorrectCommentStyle = null; + + + var int $noComment = 1; + } + +class HasAttributes +{ + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\Id]#[ORM\Column("integer")] + private $id; + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\GeneratedValue] + #[ORM\Column(ORM\Column::T_INTEGER)] + protected $height; +} + +class ReadOnlyProps +{ + /** + * Short description of the member variable. + * + * @var array + */ + public readonly array $variableName = array(); + + /** + * Short description of the member variable. + * + * @var + */ + readonly protected ?int $variableName = 10; + + private readonly string $variable; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.php new file mode 100644 index 00000000..1af5e148 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.php @@ -0,0 +1,83 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class VariableCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 21 => 1, + 24 => 1, + 56 => 1, + 64 => 1, + 73 => 1, + 84 => 1, + 130 => 1, + 136 => 1, + 144 => 1, + 152 => 1, + 160 => 1, + 168 => 1, + 176 => 1, + 184 => 1, + 192 => 1, + 200 => 1, + 208 => 1, + 216 => 1, + 224 => 1, + 232 => 1, + 240 => 1, + 248 => 1, + 256 => 1, + 264 => 1, + 272 => 1, + 280 => 1, + 290 => 1, + 294 => 1, + 311 => 1, + 336 => 1, + 361 => 1, + 364 => 1, + 399 => 1, + 403 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [93 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.inc new file mode 100644 index 00000000..8eaf1b03 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.inc @@ -0,0 +1,310 @@ + 0); + +do +{ + echo $i; +} while ($i > 0); + +do +{ + echo $i; +} +while ($i > 0); + +do { echo $i; } while ($i > 0); + +do{ + echo $i; +}while($i > 0); + +while ($i < 1) { + echo $i; +} + +while($i < 1){ + echo $i; +} + +while ($i < 1) { echo $i; } + +for ($i = 1; $i < 1; $i++) { + echo $i; +} + +for($i = 1; $i < 1; $i++){ + echo $i; +} + +for ($i = 1; $i < 1; $i++) { echo $i; } + +if ($i == 0) { + $i = 1; +} + +if($i == 0){ + $i = 1; +} + +if ($i == 0) { $i = 1; } + +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else{ + $i = 0; +} + +if ($i == 0) { $i = 1; } else { $i = 0; } + +if ($i == 0) { + $i = 1; +} else if ($i == 2) { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else if($i == 2){ + $i = 0; +} + +if ($i == 0) { $i = 1; } else if ($i == 2) { $i = 0; } + +if ($i == 0) { // comments are allowed + $i = 1; +} + +if ($i == 0) {// comments are allowed + $i = 1; +} + +if ($i == 0) { /* comments are allowed*/ + $i = 1; +} + +if ($i == 0) +{ // this is ok + $i = 1; +} + +if ($i == 0) /* this is ok */ { +} + +try { + $code = 'this'; +} catch (Exception $e) { + // Caught! +} + +try { $code = 'this'; } catch (Exception $e) { + // Caught! +} + +do { echo $i; +} while ($i > 0); + +if ($i === 0) { + + $i = 1 +} + +if ($a) { + +} +elseif ($b) { +} + +foreach ($items as $item) { + echo $item; +} + +foreach($items as $item){ + echo $item; +} + +if ($a && $b) // && $c) +{ +} + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +try { + // try body +} +catch (FirstExceptionType $e) { + // catch body +} +catch (OtherExceptionType $e) { + // catch body +} + +switch($foo) { + + case 'bar': + break; + +} + +if ($foo) : +endif; + +?> + +getRow()): ?> +

    + + + +
    + +
    + + + + + + + hello + + + + hello + + + + +getRow()) : ?> +

    + + + + + + + + hello + + + + hello + + 1, +}; + +$r = match($x){1 => 1}; + +// Intentional parse error. This should be the last test in the file. +foreach + // Some unrelated comment. diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.inc.fixed new file mode 100644 index 00000000..dc5233d9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.inc.fixed @@ -0,0 +1,314 @@ + 0); + +do { + echo $i; +} while ($i > 0); + +do { + echo $i; +} while ($i > 0); + +do { +echo $i; } while ($i > 0); + +do { + echo $i; +} while ($i > 0); + +while ($i < 1) { + echo $i; +} + +while ($i < 1) { + echo $i; +} + +while ($i < 1) { +echo $i; } + +for ($i = 1; $i < 1; $i++) { + echo $i; +} + +for ($i = 1; $i < 1; $i++) { + echo $i; +} + +for ($i = 1; $i < 1; $i++) { +echo $i; } + +if ($i == 0) { + $i = 1; +} + +if ($i == 0) { + $i = 1; +} + +if ($i == 0) { +$i = 1; } + +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { +$i = 1; } else { +$i = 0; } + +if ($i == 0) { + $i = 1; +} else if ($i == 2) { + $i = 0; +} + +if ($i == 0) { + $i = 1; +} else if ($i == 2) { + $i = 0; +} + +if ($i == 0) { +$i = 1; } else if ($i == 2) { +$i = 0; } + +if ($i == 0) { // comments are allowed + $i = 1; +} + +if ($i == 0) {// comments are allowed + $i = 1; +} + +if ($i == 0) { /* comments are allowed*/ + $i = 1; +} + +if ($i == 0) { // this is ok + $i = 1; +} + +if ($i == 0) { /* this is ok */ +} + +try { + $code = 'this'; +} catch (Exception $e) { + // Caught! +} + +try { +$code = 'this'; } catch (Exception $e) { + // Caught! +} + +do { +echo $i; +} while ($i > 0); + +if ($i === 0) { + + $i = 1 +} + +if ($a) { + +} elseif ($b) { +} + +foreach ($items as $item) { + echo $item; +} + +foreach ($items as $item) { + echo $item; +} + +if ($a && $b) { // && $c) +} + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +try { + // try body +} catch (FirstExceptionType $e) { + // catch body +} catch (OtherExceptionType $e) { + // catch body +} + +switch ($foo) { + + case 'bar': + break; + +} + +if ($foo) : +endif; + +?> + +getRow()) : ?> +

    + + + +
    + +
    + + + + + + + hello + + + + hello + + + + +getRow()): ?> +

    + + + + + + + + hello + + + + hello + + 1, +}; + +$r = match ($x) { +1 => 1}; + +// Intentional parse error. This should be the last test in the file. +foreach + // Some unrelated comment. diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js new file mode 100644 index 00000000..6c2e9ffe --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js @@ -0,0 +1,135 @@ + +i = 0; +do { + i = 0; +} while (i > 0); + +do +{ + i = 0; +} while (i > 0); + +do +{ + i = 0; +} +while (i > 0); + +do { i = 0; } while (i > 0); + +do{ + i = 0; +}while(i > 0); + +while (i < 1) { + i = 0; +} + +while(i < 1){ + i = 0; +} + +while (i < 1) { i = 0; } + +for (i = 1; i < 1; i++) { + i = 0; +} + +for(i = 1; i < 1; i++){ + i = 0; +} + +for (i = 1; i < 1; i++) { i = 0; } + +if (i == 0) { + i = 1; +} + +if(i == 0){ + i = 1; +} + +if (i == 0) { i = 1; } + +if (i == 0) { + i = 1; +} else { + i = 0; +} + +if (i == 0) { + i = 1; +}else{ + i = 0; +} + +if (i == 0) { i = 1; } else { i = 0; } + +if (i == 0) { + i = 1; +} else if (i == 2) { + i = 0; +} + +if (i == 0) { + i = 1; +}else if(i == 2){ + i = 0; +} + +if (i == 0) { i = 1; } else if (i == 2) { i = 0; } + +if (i == 0) { // comments are allowed + i = 1; +} + +if (i == 0) {// comments are allowed + i = 1; +} + +if (i == 0) { /* comments are allowed*/ + i = 1; +} + +if (i == 0) +{ // this is ok + i = 1; +} + +if (i == 0) /* this is ok */ { +} + +try { + code = 'this'; +} catch (e) { + // Caught! +} + +try { code = 'this'; } catch (e) { + // Caught! +} + +do { i = 0; +} while (i > 0); + +if (i === 0) { + + i = 1 +} + +if (window.jQuery)(function($) { + $.fn.reset = function() { + return this.each(function() { + try { + this.reset(); + } catch (e) { + } + }); + }; +})(jQuery); + +if ($("#myid").rotationDegrees()=='90') + $('.modal').css({'transform': 'rotate(90deg)'}); + +if ($("#myid").rotationDegrees()=='90') + $foo = {'transform': 'rotate(90deg)'}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js.fixed new file mode 100644 index 00000000..e3ed6de7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js.fixed @@ -0,0 +1,141 @@ + +i = 0; +do { + i = 0; +} while (i > 0); + +do { + i = 0; +} while (i > 0); + +do { + i = 0; +} while (i > 0); + +do { +i = 0; } while (i > 0); + +do { + i = 0; +} while (i > 0); + +while (i < 1) { + i = 0; +} + +while (i < 1) { + i = 0; +} + +while (i < 1) { +i = 0; } + +for (i = 1; i < 1; i++) { + i = 0; +} + +for (i = 1; i < 1; i++) { + i = 0; +} + +for (i = 1; i < 1; i++) { +i = 0; } + +if (i == 0) { + i = 1; +} + +if (i == 0) { + i = 1; +} + +if (i == 0) { +i = 1; } + +if (i == 0) { + i = 1; +} else { + i = 0; +} + +if (i == 0) { + i = 1; +} else { + i = 0; +} + +if (i == 0) { +i = 1; } else { +i = 0; } + +if (i == 0) { + i = 1; +} else if (i == 2) { + i = 0; +} + +if (i == 0) { + i = 1; +} else if (i == 2) { + i = 0; +} + +if (i == 0) { +i = 1; } else if (i == 2) { +i = 0; } + +if (i == 0) { // comments are allowed + i = 1; +} + +if (i == 0) {// comments are allowed + i = 1; +} + +if (i == 0) { /* comments are allowed*/ + i = 1; +} + +if (i == 0) { // this is ok + i = 1; +} + +if (i == 0) { /* this is ok */ +} + +try { + code = 'this'; +} catch (e) { + // Caught! +} + +try { +code = 'this'; } catch (e) { + // Caught! +} + +do { +i = 0; +} while (i > 0); + +if (i === 0) { + + i = 1 +} + +if (window.jQuery)(function($) { + $.fn.reset = function() { + return this.each(function() { + try { + this.reset(); + } catch (e) { + } + }); + }; +})(jQuery); + +if ($("#myid").rotationDegrees()=='90') + $('.modal').css({'transform': 'rotate(90deg)'}); + +if ($("#myid").rotationDegrees()=='90') + $foo = {'transform': 'rotate(90deg)'}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.php new file mode 100644 index 00000000..92427f0d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.php @@ -0,0 +1,102 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ControlSignatureUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='ControlSignatureUnitTest.inc') + { + $errors = [ + 7 => 1, + 12 => 1, + 15 => 1, + 18 => 1, + 20 => 1, + 22 => 2, + 28 => 2, + 32 => 1, + 38 => 2, + 42 => 1, + 48 => 2, + 52 => 1, + 62 => 2, + 66 => 2, + 76 => 4, + 80 => 2, + 94 => 1, + 99 => 1, + 108 => 1, + 112 => 1, + ]; + + if ($testFile === 'ControlSignatureUnitTest.inc') { + $errors[122] = 1; + $errors[130] = 2; + $errors[134] = 1; + $errors[150] = 1; + $errors[153] = 1; + $errors[158] = 1; + $errors[165] = 1; + $errors[170] = 2; + $errors[185] = 1; + $errors[190] = 2; + $errors[191] = 2; + $errors[195] = 1; + $errors[227] = 1; + $errors[234] = 1; + $errors[239] = 2; + $errors[243] = 2; + $errors[244] = 2; + $errors[248] = 1; + $errors[259] = 1; + $errors[262] = 1; + $errors[267] = 1; + $errors[269] = 1; + $errors[276] = 1; + $errors[279] = 1; + $errors[283] = 1; + $errors[306] = 3; + }//end if + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc new file mode 100644 index 00000000..91d0a23c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc @@ -0,0 +1,14 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ElseIfDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 8 => 1, + 13 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc new file mode 100644 index 00000000..4709923e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc @@ -0,0 +1,36 @@ + $that) { +} + +// Invalid. +foreach ( $something as $blah => $that ) { +} + +foreach ($something as $blah => $that) { +} + +foreach ($something as $blah => $that) { +} + +foreach (${something}AS$blah=>$that) { +} + +// The works. +foreach ( $something aS $blah => $that ) { +} + +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesBeforeClose 1 +foreach ($something as $blah => $that) {} +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesBeforeClose 0 + +foreach ([ + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ] as $key => $value) { +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc.fixed new file mode 100644 index 00000000..b0de6ebc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc.fixed @@ -0,0 +1,36 @@ + $that) { +} + +// Invalid. +foreach ($something as $blah => $that) { +} + +foreach ($something as $blah => $that) { +} + +foreach ($something as $blah => $that) { +} + +foreach (${something} as $blah => $that) { +} + +// The works. +foreach ($something as $blah => $that) { +} + +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesBeforeClose 1 +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesBeforeClose 0 + +foreach ([ + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ] as $key => $value) { +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.php new file mode 100644 index 00000000..6957ff67 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.php @@ -0,0 +1,56 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ForEachLoopDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 8 => 2, + 11 => 2, + 14 => 2, + 17 => 5, + 21 => 7, + 26 => 2, + 28 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inc new file mode 100644 index 00000000..5022e74c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inc @@ -0,0 +1,129 @@ +i ; }; $i < function() { return $this->max; }; $i++) {} +for ($i = function() { return $this->i; }; $i < function() { return $this->max; } ; $i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration ignoreNewlines true +for ( + $i = 0; + $i < 5; + $i++ +) { + // body here +} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration ignoreNewlines false + +// This test has to be the last one in the file! Intentional parse error check. +for diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inc.fixed new file mode 100644 index 00000000..6a1e7634 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inc.fixed @@ -0,0 +1,95 @@ +i ; }; $i < function() { return $this->max; }; $i++) {} +for ($i = function() { return $this->i; }; $i < function() { return $this->max; }; $i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration ignoreNewlines true +for ( + $i = 0; + $i < 5; + $i++ +) { + // body here +} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration ignoreNewlines false + +// This test has to be the last one in the file! Intentional parse error check. +for diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js new file mode 100644 index 00000000..cfda6c12 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js @@ -0,0 +1,125 @@ +// Valid. +for (var i = 0; i < 10; i++) { +} + +// Invalid. +for ( i = 0; i < 10; i++ ) { +} + +for (i = 0; i < 10; i++) { +} + +for (var i = 0 ; i < 10 ; i++) { +} + +for (i = 0;i < 10;i++) { +} + +// The works. +for ( var i = 0 ; i < 10 ; i++ ) { +} + +this.formats = {}; +dfx.inherits('ContentFormat', 'Widget'); + +for (var widgetid in this.loadedContents) { + if (dfx.isset(widget) === true) { + widget.loadAutoSaveCWidgetStore.setData('activeScreen', null);widget.getContents(this.loadedContents[widgetid], function() {self.widgetLoaded(widget.id);}); + } +} + +for (var i = 0; i < 10;) { +} +for (var i = 0; i < 10; ) { +} + +for (var i = 0; ; i++) { +} +for (var i = 0;; i++) { +} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for (var i = 0; i < 10; i++) {} +for ( var i = 0; i < 10; i++ ) {} +for ( var i = 0; i < 10; i++ ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +for ( ; i < 10; i++) {} +for (; i < 10; i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( ; i < 10; i++ ) {} +for ( ; i < 10; i++ ) {} +for (; i < 10; i++ ) {} + +for ( i = 0; i < 10; ) {} +for ( i = 0; i < 10;) {} +for ( i = 0; i < 10; ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +// Test handling of comments and inline annotations. +for ( /*phpcs:enable*/ i = 0 /*start*/ ; /*end*/i < 10/*comment*/; i++ /*comment*/ ) {} + +// Test multi-line FOR control structure. +for ( + i = 0; + i < 10; + i++ +) {} + +// Test multi-line FOR control structure with comments and annotations. +for ( + i = 0; /* Start */ + i < 10; /* phpcs:ignore Standard.Category.SniffName -- for reasons. */ + i++ // comment + +) {} + +// Test fixing each error in one go. Note: lines 84 + 88 contain trailing whitespace on purpose. +for ( + + + i = 0 + + ; + + i < 10 + + ; + + i++ + + +) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( + + + + i = 0 + + ; + + i < 10 + + ; + + i++ + + +) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +// Test with semi-colon not belonging to for. +for (i = function() {self.widgetLoaded(widget.id) ; }; i < function() {self.widgetLoaded(widget.id);}; i++) {} +for (i = function() {self.widgetLoaded(widget.id);}; i < function() {self.widgetLoaded(widget.id);} ; i++) {} + +// This test has to be the last one in the file! Intentional parse error check. +for diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js.fixed new file mode 100644 index 00000000..00ced643 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js.fixed @@ -0,0 +1,91 @@ +// Valid. +for (var i = 0; i < 10; i++) { +} + +// Invalid. +for (i = 0; i < 10; i++) { +} + +for (i = 0; i < 10; i++) { +} + +for (var i = 0; i < 10; i++) { +} + +for (i = 0; i < 10; i++) { +} + +// The works. +for (var i = 0; i < 10; i++) { +} + +this.formats = {}; +dfx.inherits('ContentFormat', 'Widget'); + +for (var widgetid in this.loadedContents) { + if (dfx.isset(widget) === true) { + widget.loadAutoSaveCWidgetStore.setData('activeScreen', null);widget.getContents(this.loadedContents[widgetid], function() {self.widgetLoaded(widget.id);}); + } +} + +for (var i = 0; i < 10;) { +} +for (var i = 0; i < 10;) { +} + +for (var i = 0;; i++) { +} +for (var i = 0;; i++) { +} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( var i = 0; i < 10; i++ ) {} +for ( var i = 0; i < 10; i++ ) {} +for ( var i = 0; i < 10; i++ ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +for (; i < 10; i++) {} +for (; i < 10; i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( ; i < 10; i++ ) {} +for ( ; i < 10; i++ ) {} +for ( ; i < 10; i++ ) {} + +for ( i = 0; i < 10; ) {} +for ( i = 0; i < 10; ) {} +for ( i = 0; i < 10; ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +// Test handling of comments and inline annotations. +for (/*phpcs:enable*/ i = 0 /*start*/; /*end*/i < 10/*comment*/; i++ /*comment*/) {} + +// Test multi-line FOR control structure. +for (i = 0; i < 10; i++) {} + +// Test multi-line FOR control structure with comments and annotations. +for (i = 0; /* Start */ + i < 10; /* phpcs:ignore Standard.Category.SniffName -- for reasons. */ + i++ // comment + +) {} + +// Test fixing each error in one go. Note: lines 84 + 88 contain trailing whitespace on purpose. +for (i = 0; i < 10; i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( i = 0; i < 10; i++ ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +// Test with semi-colon not belonging to for. +for (i = function() {self.widgetLoaded(widget.id) ; }; i < function() {self.widgetLoaded(widget.id);}; i++) {} +for (i = function() {self.widgetLoaded(widget.id);}; i < function() {self.widgetLoaded(widget.id);}; i++) {} + +// This test has to be the last one in the file! Intentional parse error check. +for diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.php new file mode 100644 index 00000000..51638866 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.php @@ -0,0 +1,132 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ForLoopDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='ForLoopDeclarationUnitTest.inc') + { + switch ($testFile) { + case 'ForLoopDeclarationUnitTest.inc': + return [ + 8 => 2, + 11 => 2, + 14 => 2, + 17 => 2, + 21 => 6, + 27 => 1, + 30 => 1, + 37 => 2, + 39 => 2, + 43 => 1, + 49 => 1, + 50 => 1, + 53 => 1, + 54 => 1, + 59 => 4, + 62 => 1, + 63 => 1, + 64 => 1, + 66 => 1, + 69 => 1, + 74 => 1, + 77 => 1, + 82 => 2, + 86 => 2, + 91 => 1, + 95 => 1, + 101 => 2, + 105 => 2, + 110 => 1, + 116 => 2, + ]; + + case 'ForLoopDeclarationUnitTest.js': + return [ + 6 => 2, + 9 => 2, + 12 => 2, + 15 => 2, + 19 => 6, + 33 => 1, + 36 => 1, + 43 => 2, + 45 => 2, + 49 => 1, + 55 => 1, + 56 => 1, + 59 => 1, + 60 => 1, + 65 => 4, + 68 => 1, + 69 => 1, + 70 => 1, + 72 => 1, + 75 => 1, + 80 => 1, + 83 => 1, + 88 => 2, + 92 => 2, + 97 => 1, + 101 => 1, + 107 => 2, + 111 => 2, + 116 => 1, + 122 => 2, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='ForLoopDeclarationUnitTest.inc') + { + switch ($testFile) { + case 'ForLoopDeclarationUnitTest.inc': + return [129 => 1]; + + case 'ForLoopDeclarationUnitTest.js': + return [125 => 1]; + + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc new file mode 100644 index 00000000..f54ed8af --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc @@ -0,0 +1,48 @@ +id.'"', + '"'.$this->stepInfo['title'].'"', + '"'.((isset($this->stepInfo['description']) === TRUE) ? $this->stepInfo['description'] : '').'"', + '"'.(isset($this->stepInfo['description']) === TRUE ? $this->stepInfo['description'] : '').'"', + '"'.$this->stepInfo['title'].'"', + ); + +echo (TRUE)?'Hello':'Bye'; + +$array = array( + 'one' => ($test == 1) ? true : false, + 'two' => (($test == 1) ? true : false), + 'three' => (($test == 1) ? true : false) +); +$var = ($test == 1) ? true : false; +$var = (myFunc(1,2,3) == 1) ? true : false; + +set('config', function() { + $foo = ($bar === "on") ? "1" : "2"; +}); + +$config = function() { + $foo = ($bar === "on") ? "1" : "2"; +}; + +rand(0, 1) ? 'ěščřžýáí' : NULL; + +$c = ($argv[1]) ? : ""; +$filepath = realpath($argv[1]) ?: $argv[1]; +$c = ($argv[1]) ? /* comment */ : ""; +$c = ($argv[1]) ? +: ""; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc.fixed new file mode 100644 index 00000000..f7aa1d67 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc.fixed @@ -0,0 +1,48 @@ +id.'"', + '"'.$this->stepInfo['title'].'"', + '"'.((isset($this->stepInfo['description']) === TRUE) ? $this->stepInfo['description'] : '').'"', + '"'.(isset($this->stepInfo['description']) === TRUE ? $this->stepInfo['description'] : '').'"', + '"'.$this->stepInfo['title'].'"', + ); + +echo (TRUE) ? 'Hello' : 'Bye'; + +$array = array( + 'one' => ($test == 1) ? true : false, + 'two' => (($test == 1) ? true : false), + 'three' => (($test == 1) ? true : false) +); +$var = ($test == 1) ? true : false; +$var = (myFunc(1,2,3) == 1) ? true : false; + +set('config', function() { + $foo = ($bar === "on") ? "1" : "2"; +}); + +$config = function() { + $foo = ($bar === "on") ? "1" : "2"; +}; + +rand(0, 1) ? 'ěščřžýáí' : NULL; + +$c = ($argv[1]) ?: ""; +$filepath = realpath($argv[1]) ?: $argv[1]; +$c = ($argv[1]) ? /* comment */ : ""; +$c = ($argv[1]) ? +: ""; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.php new file mode 100644 index 00000000..97212dba --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class InlineIfDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getCliValues($testFile) + { + return ['--encoding=utf-8']; + + }//end getCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 10 => 1, + 13 => 1, + 20 => 1, + 24 => 4, + 44 => 1, + 47 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.inc new file mode 100644 index 00000000..1acf3eac --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.inc @@ -0,0 +1,24 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowercaseDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 9 => 1, + 10 => 1, + 12 => 1, + 14 => 1, + 15 => 1, + 16 => 1, + 20 => 1, + 21 => 1, + 24 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.inc new file mode 100644 index 00000000..cf397607 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.inc @@ -0,0 +1,333 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SwitchDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='SwitchDeclarationUnitTest.inc') + { + switch ($testFile) { + case 'SwitchDeclarationUnitTest.inc': + return [ + 27 => 1, + 29 => 1, + 34 => 1, + 36 => 1, + 44 => 1, + 48 => 1, + 52 => 1, + 54 => 1, + 55 => 1, + 56 => 1, + 58 => 1, + 59 => 1, + 61 => 1, + 62 => 1, + 79 => 1, + 85 => 2, + 88 => 2, + 89 => 2, + 92 => 1, + 95 => 3, + 99 => 1, + 116 => 1, + 122 => 1, + 127 => 2, + 134 => 2, + 135 => 1, + 138 => 1, + 143 => 1, + 144 => 1, + 147 => 1, + 165 => 1, + 172 => 1, + 176 => 2, + 180 => 1, + 192 => 2, + 196 => 1, + 223 => 1, + 266 => 1, + 282 => 1, + 284 => 2, + 322 => 1, + 323 => 1, + 327 => 1, + 329 => 1, + 330 => 1, + ]; + + case 'SwitchDeclarationUnitTest.js': + return [ + 27 => 1, + 29 => 1, + 34 => 1, + 36 => 1, + 44 => 1, + 48 => 1, + 52 => 1, + 54 => 1, + 55 => 1, + 56 => 1, + 58 => 1, + 59 => 1, + 61 => 1, + 62 => 1, + 79 => 1, + 85 => 2, + 88 => 2, + 89 => 2, + 92 => 1, + 95 => 3, + 99 => 1, + 116 => 1, + 122 => 1, + 127 => 2, + 134 => 2, + 135 => 1, + 138 => 1, + 143 => 1, + 144 => 1, + 147 => 1, + 165 => 1, + 172 => 1, + 176 => 2, + 180 => 1, + 192 => 2, + 196 => 1, + 223 => 1, + 266 => 1, + 282 => 1, + 284 => 2, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='SwitchDeclarationUnitTest.inc') + { + if ($testFile === 'SwitchDeclarationUnitTest.js') { + return [273 => 1]; + } + + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.js new file mode 100644 index 00000000..797e0eea --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.js @@ -0,0 +1,2 @@ +alert('hi') +alert('hi'); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.php new file mode 100644 index 00000000..7ccfe1a3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.php @@ -0,0 +1,69 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; +use PHP_CodeSniffer\Config; + +class JSLintUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Should this test be skipped for some reason. + * + * @return void + */ + protected function shouldSkipTest() + { + $jslPath = Config::getExecutablePath('jslint'); + if ($jslPath === null) { + return true; + } + + return false; + + }//end shouldSkipTest() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 1 => 2, + 2 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.js new file mode 100644 index 00000000..797e0eea --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.js @@ -0,0 +1,2 @@ +alert('hi') +alert('hi'); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.php new file mode 100644 index 00000000..1e83f1f4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; +use PHP_CodeSniffer\Config; + +class JavaScriptLintUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Should this test be skipped for some reason. + * + * @return void + */ + protected function shouldSkipTest() + { + $jslPath = Config::getExecutablePath('jsl'); + if ($jslPath === null) { + return true; + } + + return false; + + }//end shouldSkipTest() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [2 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.1.inc new file mode 100644 index 00000000..3279edb5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.1.inc @@ -0,0 +1,3 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.2.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.2.inc new file mode 100644 index 00000000..05be6330 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.2.inc @@ -0,0 +1,3 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.3.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.3.inc new file mode 100644 index 00000000..ec1b0239 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.3.inc @@ -0,0 +1,3 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.4.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.4.inc new file mode 100644 index 00000000..ed045646 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.4.inc @@ -0,0 +1,3 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.5.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.5.inc new file mode 100644 index 00000000..d777aff6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.5.inc @@ -0,0 +1,3 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.php new file mode 100644 index 00000000..7e613b33 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FileExtensionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FileExtensionUnitTest.1.inc': + return [1 => 1]; + default: + return []; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc new file mode 100644 index 00000000..2a480bb9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc @@ -0,0 +1,195 @@ +words[$wordPos-1]) || $this->words[$wordPos-1] !== ' ') { +} else if ($this->tokens[$pos + 1] === "\n") { +} + +if ($pos === count($this->tokens) - 1) { + $file = '...'.substr($file, (($padding * -1) + 3)); +} + +if (substr($basename, -5) !== 'Sniff') { + $i = ($this->_tokens[$i]['parenthesis_closer'] + 1); +} + +$pos = $this->_getShortCommentEndPos(); +if ($pos === -1) { + $stackPtr = ($tokens[$next][$to] - 1); + $stackPtr = ($tokens[$next][$pattern[$i]['to']] + 1); + $var = (($var1 + $var2) + $var3 + $var4) +} + +$commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1); +$commentEnd = ($this->_phpcsFile->findNext(T_DOC_COMMENT, ($commentStart + 1), null, true) - 1); +$expected .= '...'.substr($tokens[($stackPtr - 2)]['content'], -5).$tokens[$stackPtr]['content']; + +if (($tokens[$nextToken - 1]['code']) !== T_WHITESPACE) { + $errorPos = ($params[(count($params) - 1)]->getLine() + $commentStart); +} + +while (($nextSpace = $phpcsFile->findNext(T_WHITESPACE, $nextSpace + 1, $nextBreak)) !== false) { +} + +foreach ($attributes as $id => &$attribute) { +} + +class MyClass +{ + + + public function &myFunction(array &$one, array &$two) + { + + }//end myFunction() + + +}//end class + +if ($index < -1) $index = 0; +if ($index < - 1) $index = 0; + +$three = ceil($one / $two); +$three = ceil(($one / $two) / $four); +$three = ceil($one / ($two / $four)); + +$four = -0.25; + +$three = ceil($one[1] / $two); + +switch ($number % 10) { + case -1: + $suffix = 'st'; + break; +} + +$expectedPermission = array( + 'granted' => 4, + 'denied' => 1, + 'cascade' => TRUE, + 'blockergranted' => 2, + 'blockerdenied' => - 3, + 'effective' => TRUE, + ); + +$value = (int) isset($blah) + 2; +$value = (int) isset($blah) + (int) isset($foo) + (int) isset($bar); + +doSomething(getValue($var, 2)) - $y; + +$codeFiles = array($global => $codeFiles[$global]) + $codeFiles; + +$var = array(-1); +$var = [-1]; +$var = [0, -1, -2]; + +$cntPages = ceil(count($items) / self::ON_PAGE); + +error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING); +error_reporting(E_ALL & ~E_NOTICE | ~E_WARNING); +$results = $stmt->fetchAll(\PDO::FETCH_ASSOC | \PDO::FETCH_GROUP | \PDO::FETCH_UNIQUE); +$di = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS); +foo(1 + 2 + 3); + +if (empty($foo[-1]) === true) { + $foo[-1] = 'foo'; +} + +try { +} catch (AException | BException $e) { +} + +$var = $foo['blah'] + []; + +$a = 2 * ${x} - ${minus}; + +$foo = $bar ?? $baz ?? ''; + +$foo = $myString{-1}; + +$value = (binary) $blah + b"binary $foo"; + +$test = (1 * static::TEST); +$test = myfunc(1 * static::TEST); + +$errorPos = $params[$x]?->getLine() + $commentStart; + +$foo = $this->gmail ?? $this->gmail = new Google_Service_Gmail($this->google); + +exit -1; + +$expr = match ($number - 10) { + -1 => 0, +}; + +$expr = match ($number % 10) { + 1 => 2 * $num, +}; + +$expr = match (true) { + $num * 100 > 500 => 'expression in key', +}; + +// PHP 8.0 named parameters. +if ($pos === count(value: $this->tokens) - 1) { + $file = '...'.substr(string: $file, offset: $padding * -1 + 3); +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc.fixed new file mode 100644 index 00000000..669b16b2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc.fixed @@ -0,0 +1,195 @@ +words[($wordPos-1)]) || $this->words[($wordPos-1)] !== ' ') { +} else if ($this->tokens[($pos + 1)] === "\n") { +} + +if ($pos === (count($this->tokens) - 1)) { + $file = '...'.substr($file, (($padding * -1) + 3)); +} + +if (substr($basename, -5) !== 'Sniff') { + $i = ($this->_tokens[$i]['parenthesis_closer'] + 1); +} + +$pos = $this->_getShortCommentEndPos(); +if ($pos === -1) { + $stackPtr = ($tokens[$next][$to] - 1); + $stackPtr = ($tokens[$next][$pattern[$i]['to']] + 1); + $var = (($var1 + $var2) + $var3 + $var4) +} + +$commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1); +$commentEnd = ($this->_phpcsFile->findNext(T_DOC_COMMENT, ($commentStart + 1), null, true) - 1); +$expected .= '...'.substr($tokens[($stackPtr - 2)]['content'], -5).$tokens[$stackPtr]['content']; + +if (($tokens[($nextToken - 1)]['code']) !== T_WHITESPACE) { + $errorPos = ($params[(count($params) - 1)]->getLine() + $commentStart); +} + +while (($nextSpace = $phpcsFile->findNext(T_WHITESPACE, ($nextSpace + 1), $nextBreak)) !== false) { +} + +foreach ($attributes as $id => &$attribute) { +} + +class MyClass +{ + + + public function &myFunction(array &$one, array &$two) + { + + }//end myFunction() + + +}//end class + +if ($index < -1) $index = 0; +if ($index < - 1) $index = 0; + +$three = ceil($one / $two); +$three = ceil(($one / $two) / $four); +$three = ceil($one / ($two / $four)); + +$four = -0.25; + +$three = ceil($one[1] / $two); + +switch ($number % 10) { + case -1: + $suffix = 'st'; + break; +} + +$expectedPermission = array( + 'granted' => 4, + 'denied' => 1, + 'cascade' => TRUE, + 'blockergranted' => 2, + 'blockerdenied' => - 3, + 'effective' => TRUE, + ); + +$value = ((int) isset($blah) + 2); +$value = ((int) isset($blah) + (int) isset($foo) + (int) isset($bar)); + +(doSomething(getValue($var, 2)) - $y); + +$codeFiles = (array($global => $codeFiles[$global]) + $codeFiles); + +$var = array(-1); +$var = [-1]; +$var = [0, -1, -2]; + +$cntPages = ceil(count($items) / self::ON_PAGE); + +error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING); +error_reporting(E_ALL & ~E_NOTICE | ~E_WARNING); +$results = $stmt->fetchAll(\PDO::FETCH_ASSOC | \PDO::FETCH_GROUP | \PDO::FETCH_UNIQUE); +$di = new \RecursiveDirectoryIterator($path, (\RecursiveDirectoryIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS)); +foo(1 + 2 + 3); + +if (empty($foo[-1]) === true) { + $foo[-1] = 'foo'; +} + +try { +} catch (AException | BException $e) { +} + +$var = ($foo['blah'] + []); + +$a = 2 * ${x} - ${minus}; + +$foo = ($bar ?? $baz ?? ''); + +$foo = $myString{-1}; + +$value = ((binary) $blah + b"binary $foo"); + +$test = (1 * static::TEST); +$test = myfunc(1 * static::TEST); + +$errorPos = ($params[$x]?->getLine() + $commentStart); + +$foo = ($this->gmail ?? $this->gmail = new Google_Service_Gmail($this->google)); + +exit -1; + +$expr = match ($number - 10) { + -1 => 0, +}; + +$expr = match ($number % 10) { + 1 => (2 * $num), +}; + +$expr = match (true) { + ($num * 100) > 500 => 'expression in key', +}; + +// PHP 8.0 named parameters. +if ($pos === (count(value: $this->tokens) - 1)) { + $file = '...'.substr(string: $file, offset: ($padding * -1 + 3)); +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js new file mode 100644 index 00000000..92ed8038 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js @@ -0,0 +1,118 @@ +value = (one + two); +value = one + two; + +value = (one - two); +value = one - two; + +value = (one * two); +value = one * two; + +value = (one / two); +value = one / two; + +value = (one % two); +value = one % two; + +value = (one + two + three); +value = one + two + three; +value = (one + (two + three)); +value = one + (two + three); + +value++; +value--; +value = -1; +value = - 1; + +value = (1 + 2); +value = 1 + 2; + +value = (1 - 2); +value = 1 - 2; + +value = (1 * 2); +value = 1 * 2; + +value = (1 / 2); +value = 1 / 2; + +value = (1 % 2); +value = 1 % 2; + +value = (1 + 2 + 3); +value = 1 + 2 + 3; +value = (1 + (2 + 3)); +value = 1 + (2 + 3); + +value = one + 2 + 3 - (four * five * (6 + 7)) + nine + 2; +value = myFunction(tokens[stackPtr - 1]); + +for (i = 1 + 2; i < 4 + 5; i++) { +} + +function myFunction() +{ + value = (one + 1) + (two + 2) + (myFunction() + 2); + value = myFunction() + 2; + value = (myFunction(mvar) + myFunction2(mvar)); + return -1; +} + +params['mode'] = id.replace(/WidgetType/, ''); + +if (index < -1) index = 0; +if (index < - 1) index = 0; + +var classN = prvId.replace(/\./g, '-'); + +three = myFunction(one / two); +three = myFunction((one / two) / four); +three = myFunction(one / (two / four)); + +four = -0.25; + +id = id.replace(/row\/:/gi, ''); +return /MSIE/.test(navigator.userAgent); + +var re = new RegExp(/<\/?(\w+)((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>/gim); + +var options = { + minVal: -1, + maxVal: -1 +}; + +stepWidth = Math.round(this.width / 5); + +date.setMonth(d[2] - 1); + +switch (number % 10) { + case -1: + suffix = 'st'; + break; +} + +var pathSplit = ipt.value.split(/\/|\\/); + +if (pairs[i].search(/=/) !== -1) { +} + +if (urlValue.search(/[a-zA-z]+:\/\//) !== 0) { +} + +if (urlValue.search(/[a-zA-z]+:\/\/*/) !== 0) { +} + +if (!value || /^\s*$/.test(value)) { + return true; +} + +parseInt(dfx.attr(selectors[idx], 'elemOffsetTop'), 10) - scrollCoords.y + 'px' + +if (something === true + ^ somethingElse === true +) { + return false; +} + +if (true === /^\d*\.?\d*$/.test(input)) return true; + +if ( ! /^(?:a|select)$/i.test( element.tagName ) ) return true; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js.fixed new file mode 100644 index 00000000..04e35d97 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js.fixed @@ -0,0 +1,118 @@ +value = (one + two); +value = one + two; + +value = (one - two); +value = (one - two); + +value = (one * two); +value = (one * two); + +value = (one / two); +value = (one / two); + +value = (one % two); +value = (one % two); + +value = (one + two + three); +value = one + two + three; +value = (one + (two + three)); +value = one + (two + three); + +value++; +value--; +value = -1; +value = - 1; + +value = (1 + 2); +value = 1 + 2; + +value = (1 - 2); +value = (1 - 2); + +value = (1 * 2); +value = (1 * 2); + +value = (1 / 2); +value = (1 / 2); + +value = (1 % 2); +value = (1 % 2); + +value = (1 + 2 + 3); +value = 1 + 2 + 3; +value = (1 + (2 + 3)); +value = 1 + (2 + 3); + +value = one + 2 + (3 - (four * five * (6 + 7))) + nine + 2; +value = myFunction(tokens[(stackPtr - 1)]); + +for (i = 1 + 2; i < 4 + 5; i++) { +} + +function myFunction() +{ + value = (one + 1) + (two + 2) + (myFunction() + 2); + value = myFunction() + 2; + value = (myFunction(mvar) + myFunction2(mvar)); + return -1; +} + +params['mode'] = id.replace(/WidgetType/, ''); + +if (index < -1) index = 0; +if (index < - 1) index = 0; + +var classN = prvId.replace(/\./g, '-'); + +three = myFunction(one / two); +three = myFunction((one / two) / four); +three = myFunction(one / (two / four)); + +four = -0.25; + +id = id.replace(/row\/:/gi, ''); +return /MSIE/.test(navigator.userAgent); + +var re = new RegExp(/<\/?(\w+)((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>/gim); + +var options = { + minVal: -1, + maxVal: -1 +}; + +stepWidth = Math.round(this.width / 5); + +date.setMonth(d[2] - 1); + +switch (number % 10) { + case -1: + suffix = 'st'; + break; +} + +var pathSplit = ipt.value.split(/\/|\\/); + +if (pairs[i].search(/=/) !== -1) { +} + +if (urlValue.search(/[a-zA-z]+:\/\//) !== 0) { +} + +if (urlValue.search(/[a-zA-z]+:\/\/*/) !== 0) { +} + +if (!value || /^\s*$/.test(value)) { + return true; +} + +(parseInt(dfx.attr(selectors[idx], 'elemOffsetTop'), 10) - scrollCoords.y) + 'px' + +if (something === true + ^ somethingElse === true +) { + return false; +} + +if (true === /^\d*\.?\d*$/.test(input)) return true; + +if ( ! /^(?:a|select)$/i.test( element.tagName ) ) return true; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.php new file mode 100644 index 00000000..4f04a6eb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.php @@ -0,0 +1,117 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Formatting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class OperatorBracketUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='OperatorBracketUnitTest.inc') + { + switch ($testFile) { + case 'OperatorBracketUnitTest.inc': + return [ + 3 => 1, + 6 => 1, + 9 => 1, + 12 => 1, + 15 => 1, + 18 => 2, + 20 => 1, + 25 => 1, + 28 => 1, + 31 => 1, + 34 => 1, + 37 => 1, + 40 => 1, + 43 => 2, + 45 => 1, + 47 => 5, + 48 => 1, + 50 => 2, + 55 => 2, + 56 => 1, + 63 => 2, + 64 => 1, + 67 => 1, + 86 => 1, + 90 => 1, + 109 => 1, + 130 => 1, + 134 => 1, + 135 => 2, + 137 => 1, + 139 => 1, + 150 => 1, + 161 => 1, + 163 => 2, + 165 => 2, + 169 => 1, + 174 => 1, + 176 => 1, + 185 => 1, + 189 => 1, + 193 => 1, + 194 => 2, + ]; + break; + case 'OperatorBracketUnitTest.js': + return [ + 5 => 1, + 8 => 1, + 11 => 1, + 14 => 1, + 24 => 1, + 30 => 1, + 33 => 1, + 36 => 1, + 39 => 1, + 46 => 1, + 47 => 1, + 63 => 1, + 108 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc new file mode 100644 index 00000000..33564e2e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc @@ -0,0 +1,111 @@ + $a($b); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc.fixed new file mode 100644 index 00000000..68fb1c1c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc.fixed @@ -0,0 +1,111 @@ + $a($b); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.php new file mode 100644 index 00000000..65e987dd --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.php @@ -0,0 +1,86 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionDeclarationArgumentSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 2, + 7 => 2, + 8 => 2, + 9 => 2, + 11 => 2, + 13 => 7, + 14 => 2, + 15 => 2, + 16 => 4, + 18 => 2, + 35 => 2, + 36 => 2, + 44 => 2, + 45 => 1, + 46 => 1, + 51 => 2, + 53 => 2, + 55 => 1, + 56 => 1, + 58 => 1, + 73 => 7, + 76 => 1, + 77 => 1, + 81 => 1, + 89 => 2, + 92 => 1, + 93 => 1, + 94 => 1, + 95 => 1, + 99 => 11, + 100 => 2, + 101 => 2, + 102 => 2, + 106 => 1, + 107 => 2, + 111 => 3, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.inc new file mode 100644 index 00000000..0cde1138 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.inc @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 55 => 1, + 68 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.inc new file mode 100644 index 00000000..27102d05 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.inc @@ -0,0 +1,6 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.php new file mode 100644 index 00000000..da09cef3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionDuplicateArgumentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 2, + 5 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.inc new file mode 100644 index 00000000..b7b7f205 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.inc @@ -0,0 +1,17 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.php new file mode 100644 index 00000000..7be76488 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class GlobalFunctionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [2 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc new file mode 100644 index 00000000..4e868336 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc @@ -0,0 +1,28 @@ + $x; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc.fixed new file mode 100644 index 00000000..48c99777 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc.fixed @@ -0,0 +1,28 @@ + $x; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.php new file mode 100644 index 00000000..1e1537b7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowercaseFunctionKeywordsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 16 => 1, + 17 => 1, + 20 => 1, + 21 => 1, + 22 => 1, + 23 => 1, + 24 => 3, + 25 => 4, + 28 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.inc new file mode 100644 index 00000000..fce0b237 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.inc @@ -0,0 +1,257 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MultiLineFunctionDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='MultiLineFunctionDeclarationUnitTest.inc') + { + if ($testFile === 'MultiLineFunctionDeclarationUnitTest.inc') { + $errors = [ + 2 => 1, + 3 => 1, + 4 => 2, + 5 => 1, + 7 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 16 => 1, + 36 => 1, + 43 => 2, + 48 => 1, + 81 => 1, + 82 => 2, + 88 => 1, + 102 => 2, + 137 => 1, + 141 => 2, + 142 => 1, + 158 => 1, + 160 => 1, + 182 => 2, + 186 => 2, + 190 => 2, + 194 => 1, + 195 => 1, + 233 => 1, + 234 => 1, + 235 => 1, + 236 => 1, + 244 => 1, + 245 => 1, + 246 => 1, + 247 => 1, + 248 => 1, + 249 => 1, + 250 => 1, + 251 => 1, + 252 => 1, + 253 => 1, + 254 => 1, + ]; + } else { + $errors = [ + 2 => 1, + 3 => 1, + 4 => 2, + 5 => 1, + 7 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 16 => 1, + 26 => 1, + 36 => 1, + 43 => 2, + 48 => 1, + 65 => 1, + ]; + }//end if + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.inc new file mode 100644 index 00000000..aacef347 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.inc @@ -0,0 +1,27 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.php new file mode 100644 index 00000000..77f13bb2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidFunctionNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 14 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.inc new file mode 100644 index 00000000..87c3bdf2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.inc @@ -0,0 +1,157 @@ +varName2; +echo $this->var_name2; +echo $this->varname2; +echo $this->_varName2; +echo $object->varName2; +echo $object->var_name2; +echo $object_name->varname2; +echo $object_name->_varName2; + +echo $this->myFunction($one, $two); +echo $object->myFunction($one_two); + +$error = "format is \$GLOBALS['$varName']"; + +echo $_SESSION['var_name']; +echo $_FILES['var_name']; +echo $_ENV['var_name']; +echo $_COOKIE['var_name']; + +$XML = 'hello'; +$myXML = 'hello'; +$XMLParser = 'hello'; +$xmlParser = 'hello'; + +echo "{$_SERVER['HOSTNAME']} $var_name"; + +// Need to be the last thing in this test file. +$obj->$classVar = $prefix.'-'.$type; + +class foo +{ + const bar = <<varName; +echo $obj?->var_name; +echo $obj?->varname; +echo $obj?->_varName; + +enum SomeEnum +{ + public function foo($foo, $_foo, $foo_bar) { + $bar = 1; + $_bar = 2; + $bar_foo = 3; + } +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.php new file mode 100644 index 00000000..9acbe241 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.php @@ -0,0 +1,88 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidVariableNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 3 => 1, + 5 => 1, + 10 => 1, + 12 => 1, + 15 => 1, + 17 => 1, + 20 => 1, + 22 => 1, + 25 => 1, + 27 => 1, + 31 => 1, + 33 => 1, + 36 => 1, + 37 => 1, + 39 => 1, + 42 => 1, + 44 => 1, + 53 => 1, + 58 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 67 => 1, + 81 => 1, + 106 => 1, + 107 => 2, + 108 => 1, + 111 => 1, + 112 => 1, + 113 => 1, + 114 => 1, + 123 => 1, + 138 => 1, + 141 => 1, + 146 => 1, + 152 => 1, + 155 => 1, + ]; + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.js new file mode 100644 index 00000000..1c61fbfb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.js @@ -0,0 +1,37 @@ +function test(id) +{ + + this.id = id; + +} +/**/ +test.prototype = { + init: function() + { + var x = {}; + x.name = 'test'; + x['phone'] = 123124324; + var t = ['test', 'this'].join(''); + var y = ['test'].join(''); + var a = x[0]; + var z = x[x['name']]; + var p = x[x.name]; + } + +}; + +function test() { + this.errors['step_' + step] = errors; + this.errors['test'] = x; + this.errors['test' + 10] = x; + this.errors['test' + y] = x; + this.errors['test' + 'blah'] = x; + this.errors[y] = x; + this.errors[y + z] = x; + this.permissions['workflow.cancel'] = x; +} + +if (child.prototype) { + above.prototype['constructor'] = parent; + child.prototype['super'] = new above(); +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.php new file mode 100644 index 00000000..cb2d58e5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowObjectStringIndexUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='DisallowObjectStringIndexUnitTest.js') + { + if ($testFile !== 'DisallowObjectStringIndexUnitTest.js') { + return []; + } + + return [ + 13 => 1, + 17 => 1, + 25 => 1, + 35 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc new file mode 100644 index 00000000..41c88128 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc @@ -0,0 +1,46 @@ + new MyClass()); +$object->myFunction(new MyClass()); + +throw new MyException($msg); + +function foo() { return new MyClass(); } + +$doodad = $x ? new Foo : new Bar; + +function returnFn() { + $fn = fn($x) => new MyClass(); +} + +function returnMatch() { + $match = match($x) { + 0 => new MyClass() + } +} + +// Issue 3333. +$time2 ??= new \DateTime(); +$time3 = $time1 ?? new \DateTime(); +$time3 = $time1 ?? $time2 ?? new \DateTime(); + +function_call($time1 ?? new \DateTime()); +$return = function_call($time1 ?? new \DateTime()); // False negative depending on interpretation of the sniff. + +function returnViaTernary() { + return ($y == false ) ? ($x === true ? new Foo : new Bar) : new FooBar; +} + +function nonAssignmentTernary() { + if (($x ? new Foo() : new Bar) instanceof FooBar) { + // Do something. + } +} + +// Intentional parse error. This must be the last test in the file. +function new +?> diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php new file mode 100644 index 00000000..f9979fa2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ObjectInstantiationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 8 => 1, + 31 => 1, + 39 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js new file mode 100644 index 00000000..28bf85ad --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js @@ -0,0 +1,47 @@ +this.request({ action: 'getTypeFormatContents', }); + +addTypeFormatButton.addClickEvent(function() { + self.addNewTypeFormat(); +}); + +var x = {}; + +var y = { + VarOne : 'If you ask me, thats if you ask', + VarTwo : ['Alonzo played you', 'for a fool', 'esse'], + VarThree: function(arg) { + console.info(1); + } +}; + +var z = { + VarOne : 'If you ask me, thats if you ask', + VarTwo : ['Alonzo played you', 'for a fool', 'esse'], + VarThree: function(arg) { + console.info(1); + }, +}; + +var x = function() { + console.info(2); +}; + +AssetListingEditWidgetType.prototype = { + init: function(data, assetid, editables) + { + } +}; + +AssetListingEditWidgetType.prototype = { + init: function(data, assetid, editables) + { + }, +}; + +AssetListingEditWidgetType.prototype = { + // phpcs: disable Standard.Cat.SniffName -- testing annotation between closing brace and comma + init: function(data, assetid, editables) + { + }, + // phpcs:enable +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js.fixed new file mode 100644 index 00000000..df548c74 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js.fixed @@ -0,0 +1,47 @@ +this.request({ action: 'getTypeFormatContents' }); + +addTypeFormatButton.addClickEvent(function() { + self.addNewTypeFormat(); +}); + +var x = {}; + +var y = { + VarOne : 'If you ask me, thats if you ask', + VarTwo : ['Alonzo played you', 'for a fool', 'esse'], + VarThree: function(arg) { + console.info(1); + } +}; + +var z = { + VarOne : 'If you ask me, thats if you ask', + VarTwo : ['Alonzo played you', 'for a fool', 'esse'], + VarThree: function(arg) { + console.info(1); + } +}; + +var x = function() { + console.info(2); +}; + +AssetListingEditWidgetType.prototype = { + init: function(data, assetid, editables) + { + } +}; + +AssetListingEditWidgetType.prototype = { + init: function(data, assetid, editables) + { + } +}; + +AssetListingEditWidgetType.prototype = { + // phpcs: disable Standard.Cat.SniffName -- testing annotation between closing brace and comma + init: function(data, assetid, editables) + { + } + // phpcs:enable +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.php new file mode 100644 index 00000000..ab1cf810 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ObjectMemberCommaUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 1 => 1, + 22 => 1, + 38 => 1, + 45 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.inc new file mode 100644 index 00000000..8522438d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.inc @@ -0,0 +1,138 @@ + + 0)) { +} + +myFunction($var1 === true ? "" : "foobar"); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.js new file mode 100644 index 00000000..048223ba --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.js @@ -0,0 +1,71 @@ +if (value === TRUE) { +} else if (value === FALSE) { +} + +if (value == TRUE) { +} else if (value == FALSE) { +} + +if (value) { +} else if (!value) { +} + +if (value.isSomething === TRUE) { +} else if (myFunction(value) === FALSE) { +} + +if (value.isSomething == TRUE) { +} else if (myFunction(value) == FALSE) { +} + +if (value.isSomething) { +} else if (!myFunction(value)) { +} + +if (value === TRUE || other === FALSE) { +} + +if (value == TRUE || other == FALSE) { +} + +if (value || !other) { +} + +if (one === TRUE || two === TRUE || three === FALSE || four === TRUE) { +} + +if (one || two || !three || four) { +} + +while (one == true) { +} + +while (one === true) { +} + +do { +} while (one == true); + +do { +} while (one === true); + +for (one = 10; one != 0; one--) { +} + +for (one = 10; one !== 0; one--) { +} + +for (type in types) { +} + +variable = (variable2 === true) ? variable1 : "foobar"; + +variable = (variable2 == true) ? variable1 : "foobar"; + +variable = (variable2 === false) ? variable1 : "foobar"; + +variable = (variable2 == false) ? variable1 : "foobar"; + +variable = (variable2 === 0) ? variable1 : "foobar"; + +variable = (variable2 == 0) ? variable1 : "foobar"; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.php new file mode 100644 index 00000000..5618a7fc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.php @@ -0,0 +1,101 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Operators; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ComparisonOperatorUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='ComparisonOperatorUsageUnitTest.inc') + { + switch ($testFile) { + case 'ComparisonOperatorUsageUnitTest.inc': + return [ + 6 => 1, + 7 => 1, + 10 => 1, + 11 => 1, + 18 => 1, + 19 => 1, + 22 => 1, + 23 => 1, + 29 => 2, + 32 => 2, + 38 => 4, + 47 => 2, + 69 => 1, + 72 => 1, + 75 => 1, + 78 => 1, + 80 => 1, + 82 => 1, + 83 => 1, + 89 => 1, + 92 => 1, + 100 => 1, + 106 => 1, + 112 => 1, + 123 => 1, + 127 => 1, + 131 => 1, + 135 => 1, + ]; + break; + case 'ComparisonOperatorUsageUnitTest.js': + return [ + 5 => 1, + 6 => 1, + 17 => 1, + 18 => 1, + 28 => 2, + 40 => 1, + 47 => 1, + 52 => 1, + 63 => 1, + 67 => 1, + 71 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.inc new file mode 100644 index 00000000..a4f82d1a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.inc @@ -0,0 +1,42 @@ +i++).$id; +$id = $obj?->i++.$id; +$id = $obj?->i++*10; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.php new file mode 100644 index 00000000..3846905d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Operators; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class IncrementDecrementUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 6 => 1, + 12 => 1, + 16 => 1, + 25 => 1, + 26 => 1, + 27 => 1, + 29 => 1, + 31 => 1, + 41 => 1, + 42 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc new file mode 100644 index 00000000..328ccc5d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc @@ -0,0 +1,28 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php new file mode 100644 index 00000000..fc351319 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Operators; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidLogicalOperatorsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 11 => 1, + 17 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.css new file mode 100644 index 00000000..94cc8f27 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.css @@ -0,0 +1,23 @@ +/* CSS Document */ + +body { +font-family: Arial, Helvetica, sans-serif; +margin : 40px 0 0 0; +padding : 0; +/*background: #8FB7DB url(login_glow_bg.jpg) no-repeat 30% 0;*/ +background: #8FB7DB url(diag_lines_bg.gif) top left; +} + +#login-container { + margin-left: -225px; + margin-top: -161px; + position:absolute; + top :50%; + /*left :50%;*/ + width:450px; +} + +#cacheConfig-dayLabel, #cacheConfig-hourLabel, #cacheConfig-minuteLabel { + float: left; + padding-right: 8px; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.inc new file mode 100644 index 00000000..121240a9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.inc @@ -0,0 +1,158 @@ + + * + * Title + * Contents + * + * ... + * + * + * + * + * @return void + */ + +/* + [^\'"] +*/ + +// http://www.google.com + +// Base config function. + +// function () + +// T_STRING is not a function call or not listed in _getFunctionListWithCallableArgument(). + + // function myFunction( $param ) + // { + // do_something(); + // }//end myFunction() + // + +/* +function myFunction( $param ) +{ + // phpcs:disable Standard.Category.Sniff -- for reasons. + if ( preg_match( '`[abc]`', $param ) > 0 ) { + do_something(); + } + // phpcs:enable Standard.Category.Sniff -- for reasons. + +}//end myFunction() +*/ + + /* + * function myFunction( $param ) // @phpcs:ignore Standard.Category.Sniff -- for reasons. + * { + * + * }//end myFunction() + */ + + /* + * function myFunction( $param ) + * { + * // phpcs:disable Standard.Category.Sniff -- for reasons. + * if ( preg_match( '`[abc]`', $param ) > 0 ) { + * do_something(); + * } + * // phpcs:enable Standard.Category.Sniff -- for reasons. + * + * }//end myFunction() + */ + + // function myFunction( $param ) + // { + // phpcs:disable Standard.Category.Sniff -- for reasons. + // do_something(); + // phpcs:enable Standard.Category.Sniff -- for reasons. + // }//end myFunction() + // + +echo 'something'; // @codeCoverageIgnore +echo 'something'; // @codeCoverageIgnoreStart +echo 'something'; // @SuppressWarnings(PHPMD.UnusedLocalVariable) + +// Ok! + +/* Go! */ + +// ISO-639-3 + + // But override with a different text if any. + /* + $id = intval( str_replace( 'hook_name', '', $order_method['method_id'] ) ); + if ( ! empty( $id ) ) { + $info_text = get_post_meta( $location_id, 'meta_name' ); + + if ( ! empty( $info_text ) ) { + $text = $info_text; + } + + } + */ + // function() { $a = $b; }; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.php new file mode 100644 index 00000000..36c556d8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.php @@ -0,0 +1,76 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class CommentedOutCodeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='CommentedOutCodeUnitTest.inc') + { + switch ($testFile) { + case 'CommentedOutCodeUnitTest.inc': + return [ + 6 => 1, + 8 => 1, + 15 => 1, + 19 => 1, + 87 => 1, + 91 => 1, + 97 => 1, + 109 => 1, + 116 => 1, + 128 => 1, + 147 => 1, + 158 => 1, + ]; + break; + case 'CommentedOutCodeUnitTest.css': + return [ + 7 => 1, + 16 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.inc new file mode 100644 index 00000000..4701c23e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.inc @@ -0,0 +1,27 @@ + \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.php new file mode 100644 index 00000000..6439b632 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowBooleanStatementUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 8 => 1, + 13 => 1, + 15 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.inc new file mode 100644 index 00000000..022aca73 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.inc @@ -0,0 +1,73 @@ +nextSibling; $node; $node = $node->nextSibling) { + if ($node->nodeType !== XML_ELEMENT_NODE) { + continue; + } + + for ($node = $fields->nextSibling; $node; $node = $node->nextSibling) { + if ($node->nodeType !== XML_ELEMENT_NODE) { + continue; + } + } +} + +$a = $b ? $c : $d; +$a = $b === true ? $c : $d; + +$this->_args = $this->_getArgs(($_SERVER['argv'] ?? [])); +$args = ($_SERVER['argv'] ?? []); + +$a = [ + 'a' => ($foo) ? $foo : $bar, +]; + +$a = [ + 'a' => ($foo) ? fn() => return 1 : fn() => return 2, +]; + +$var = $foo->something(!$var); +$var = $foo?->something(!$var); + +$callback = function ($value) { + if ($value > 10) { + return false; + } +}; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.php new file mode 100644 index 00000000..c8d8b0b8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowComparisonAssignmentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 10 => 1, + 52 => 1, + 53 => 1, + 58 => 1, + 62 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.inc new file mode 100644 index 00000000..f57e0710 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.inc @@ -0,0 +1,18 @@ + $x; + +$b = fn ($b) => $b ? true : false; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.js new file mode 100644 index 00000000..56387c06 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.js @@ -0,0 +1,2 @@ +x = (x?a:x); +id = id.replace(/row\/:/gi, ''); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.php new file mode 100644 index 00000000..27083ce2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.php @@ -0,0 +1,63 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowInlineIfUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='DisallowInlineIfUnitTest.inc') + { + switch ($testFile) { + case 'DisallowInlineIfUnitTest.inc': + return [ + 8 => 1, + 18 => 1, + ]; + break; + case 'DisallowInlineIfUnitTest.js': + return [1 => 1]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.inc new file mode 100644 index 00000000..f657fb4a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.inc @@ -0,0 +1,110 @@ +fetch(PDO::FETCH_NUM)) { + $result[$row[0]] = array(); + $result[$row[0]][] = $current; + + self::$_inTransaction = TRUE; + parent::$_inTransaction = TRUE; + static::$_inTransaction = TRUE; + $$varName = $varValue; + } + +}//end getVar() + +class myClass +{ + private static $_dbh = NULL; + public $dbh = NULL; + protected $dbh = NULL; + var $dbh = NULL; // Old PHP4 compatible code. +} + +A::$a = 'b'; +\A::$a = 'c'; +\A\B\C::$d = 'd'; +B\C::$d = 'e'; + +@$a = 1; + +$a = []; +foreach ($a as $b) + $c = 'd'; + +$var = $var2; +list ($a, $b) = explode(',', $c); +$var1 ? $var2 = 0 : $var2 = 1; + +$obj->$classVar = $prefix.'-'.$type; + +$closureWithDefaultParamter = function(array $testArray=array()) {}; +?> + + + 10, + false => 0 + }, +]; + +$arrow_function = fn ($a = null) => $a; + +function ($html) { + $regEx = '/regexp/'; + + return preg_replace_callback($regEx, function ($matches) { + [$all] = $matches; + return $all; + }, $html); +}; + + +function () { + $a = false; + + some_label: + + $b = getB(); +}; + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.php new file mode 100644 index 00000000..618d76ef --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowMultipleAssignmentsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 5 => 2, + 7 => 1, + 9 => 1, + 12 => 1, + 14 => 1, + 15 => 1, + 79 => 1, + 85 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.inc new file mode 100644 index 00000000..56802e37 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.inc @@ -0,0 +1,58 @@ +children); $i++) { +} + + + +for ($i = 0; $i < sizeof($array); $i++) { +} + +$num = sizeof($array); + +while ($i < sizeof($array)) { +} + +do { +} while ($i < sizeof($array)); + +for ($i = 0; $i < sizeof($this->children); $i++) { +} + + + + +for ($i = 0; $i < strlen($string); $i++) { +} + +$num = strlen($string); + +while ($i < strlen($string)) { +} + +do { +} while ($i < strlen($string)); + +for ($i = 0; $i < strlen($this->string); $i++) { +} + +for ($i = sizeof($array); $i > 0; $i--) { +} + +do { + echo $a->count; + $a->count--; +} while($a->count); + +for ($i = 0; $i < $a->count; $i++) {} +for ($i = 0; $i < $a?->count; $i++) {} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.js new file mode 100644 index 00000000..8f7f7b94 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.js @@ -0,0 +1,13 @@ +for (var i = 0; i < permissions.length; i++) { + // Code here. +} + +var permLen = permissions.length; +for (var length = 0; i < permLen; i++) { + // Code here. +} + +var myArray = [1, 2, 3, 4]; +for (var i = myArray.length; i >= 0; i--) { + var x = i; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.php new file mode 100644 index 00000000..21260ad7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowSizeFunctionsInLoopsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='DisallowSizeFunctionsInLoopsUnitTest.inc') + { + switch ($testFile) { + case 'DisallowSizeFunctionsInLoopsUnitTest.inc': + return [ + 2 => 1, + 7 => 1, + 11 => 1, + 13 => 1, + 18 => 1, + 23 => 1, + 27 => 1, + 29 => 1, + 35 => 1, + 40 => 1, + 44 => 1, + 46 => 1, + ]; + break; + case 'DisallowSizeFunctionsInLoopsUnitTest.js': + return [1 => 1]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.inc new file mode 100644 index 00000000..ca457a2e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.inc @@ -0,0 +1,5 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.php new file mode 100644 index 00000000..2b2ff5b4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DiscouragedFunctionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 2 => 1, + 3 => 1, + 4 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc new file mode 100644 index 00000000..c61d5a39 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc @@ -0,0 +1,119 @@ + + + +<?php echo $title ?> + + + + + hello + + + + + + + + + + + + + + + + + + + + + +section as $section) { + ?> + + + + + + section as $section) { + ?> +
    + + + + + + + + +?> + + + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc.fixed new file mode 100644 index 00000000..5b43d849 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc.fixed @@ -0,0 +1,119 @@ + + + +<?php echo $title; ?> + + + + + hello + + + + + + + + + + + + + + + + + + + +section as $section) { + ?> +
    + + + + + section as $section) { + ?> +
    + + + + + + + + + + + + +?> + + + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.php new file mode 100644 index 00000000..f8cf4cc7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.php @@ -0,0 +1,78 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EmbeddedPhpUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 12 => 1, + 18 => 1, + 19 => 2, + 20 => 1, + 21 => 1, + 22 => 3, + 24 => 1, + 26 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 34 => 1, + 36 => 1, + 40 => 1, + 41 => 1, + 44 => 1, + 45 => 1, + 49 => 1, + 59 => 1, + 63 => 1, + 93 => 1, + 94 => 2, + 100 => 1, + 102 => 1, + 112 => 1, + 113 => 1, + 116 => 1, + 117 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.inc new file mode 100644 index 00000000..ee4c73e5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.inc @@ -0,0 +1,5 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.php new file mode 100644 index 00000000..adee7882 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EvalUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 2 => 1, + 4 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.inc new file mode 100644 index 00000000..4b2a2109 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.inc @@ -0,0 +1,13 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.php new file mode 100644 index 00000000..52f6a00a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class GlobalKeywordUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 8 => 1, + 9 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.inc new file mode 100644 index 00000000..56f4393a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.inc @@ -0,0 +1,27 @@ +foo. +Now, I am printing some {$foo->bar[1]}. +This should not print a capital 'A': \x41 +EOT; + +// The following function has a simulated git conflict for testing. +// This is not a merge conflict - it is a valid test case. +// Please do not remove. +function test() + { + $arr = array( + 'a' => 'a' +<<<<<<< HEAD + 'b' => 'b' +======= + 'c' => 'c' +>>>>>>> master + ); + } diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.php new file mode 100644 index 00000000..2f06f0b0 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class HeredocUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 8 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.inc new file mode 100644 index 00000000..dd851461 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.inc @@ -0,0 +1,50 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class InnerFunctionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 46 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc new file mode 100644 index 00000000..c67381ad --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc @@ -0,0 +1,43 @@ +Count(); +$count = $object::Count(); +$count = $object->count(); +$count = $object::count(); +class MyClass { + public function Count() {} +} + +function &Sort() { + +} + +$connection = new Db\Adapter\Pdo\Mysql($config); + +namespace Strtolower\Silly; + +use function strToUpper as somethingElse; +use function MyClass\WordsToUpper as UCWords; // Intentional redeclared function error. +use function strToUpper\NotTheFunction; + +class ArrayUnique {} + +$sillyComments = strToLower /*comment*/ ($string); + +$callToGlobalFunction = \STR_REPEAT($a, 2); +$callToGlobalFunction = \ /*comment*/ str_Repeat($a, 2); + +$callToNamespacedFunction = MyNamespace /* phpcs:ignore Standard */ \STR_REPEAT($a, 2); +$callToNamespacedFunction = namespace\STR_REPEAT($a, 2); // Could potentially be false negative. + +$filePath = new \File($path); + +$count = $object?->Count(); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc.fixed new file mode 100644 index 00000000..40507c04 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc.fixed @@ -0,0 +1,43 @@ +Count(); +$count = $object::Count(); +$count = $object->count(); +$count = $object::count(); +class MyClass { + public function Count() {} +} + +function &Sort() { + +} + +$connection = new Db\Adapter\Pdo\Mysql($config); + +namespace Strtolower\Silly; + +use function strtoupper as somethingElse; +use function MyClass\WordsToUpper as UCWords; // Intentional redeclared function error. +use function strToUpper\NotTheFunction; + +class ArrayUnique {} + +$sillyComments = strtolower /*comment*/ ($string); + +$callToGlobalFunction = \str_repeat($a, 2); +$callToGlobalFunction = \ /*comment*/ str_repeat($a, 2); + +$callToNamespacedFunction = MyNamespace /* phpcs:ignore Standard */ \STR_REPEAT($a, 2); +$callToNamespacedFunction = namespace\STR_REPEAT($a, 2); // Could potentially be false negative. + +$filePath = new \File($path); + +$count = $object?->Count(); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.php new file mode 100644 index 00000000..708d01ef --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowercasePHPFunctionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 1, + 27 => 1, + 33 => 1, + 35 => 1, + 36 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.1.inc new file mode 100644 index 00000000..ed7f0115 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.1.inc @@ -0,0 +1,301 @@ +{$action . 'JsonAction'}(); +} + +switch (true) { + case 1: + return foo( + function () { + $foo = $bar; // when this is removed it works ok + return false; // from here on it reports unreachable + } + ); +} + +for($i=0,$j=50; $i<100; $i++) { + while($j--) { + if($j==17) { + goto end; + echo 'unreachable'; + } + } +} + +switch ($var) { + case '1': + goto end; + echo 'hi'; + + case '2': + case '3': + if ($something === true) { + goto end; + echo 'hi'; + } + break; + default: + goto end; + + if ($something === true) { + goto end; + echo 'hi'; + } +} + +end: +echo 'j hit 17'; + +// Issue 2512. +class TestAlternativeControlStructures { + + public function alternative_switch_in_function( $var ) { + + switch ( $var ) : + case 'value1': + do_something(); + break; + + default: + case 'value2': + do_something_else(); + break; + endswitch; + } + + public function various_alternative_control_structures() { + $_while = 1; + + for ( $a = 0; $a++ < 1; ) : + foreach ( [ 1 ] as $b ) : + while ( $_while-- ) : + if ( 1 ) : + switch ( 1 ) : + default: + echo 'yay, we made it!'; + break; + endswitch; + endif; + endwhile; + endforeach; + endfor; + } +} + +$var_after_class_in_global_space = 1; +do_something_else(); + +// Intentional syntax error. +return array_map( diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.2.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.2.inc new file mode 100644 index 00000000..c9bf052f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.2.inc @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class NonExecutableCodeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'NonExecutableCodeUnitTest.1.inc': + return [ + 5 => 1, + 11 => 1, + 17 => 1, + 18 => 1, + 19 => 2, + 28 => 1, + 32 => 1, + 33 => 2, + 34 => 2, + 42 => 1, + 45 => 1, + 54 => 1, + 58 => 1, + 73 => 1, + 83 => 1, + 95 => 1, + 105 => 1, + 123 => 1, + 147 => 1, + 150 => 1, + 153 => 1, + 166 => 1, + 180 => 1, + 232 => 1, + 240 => 1, + 246 => 1, + 252 => 1, + 253 => 1, + 254 => 2, + ]; + break; + case 'NonExecutableCodeUnitTest.2.inc': + return [ + 7 => 1, + 8 => 1, + 9 => 1, + 10 => 2, + 14 => 1, + 54 => 2, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.inc new file mode 100644 index 00000000..6df12cca --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.inc @@ -0,0 +1,72 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Scope; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MemberVarScopeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 25 => 1, + 29 => 1, + 33 => 1, + 39 => 1, + 41 => 1, + 66 => 2, + 67 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [71 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.inc new file mode 100644 index 00000000..3cc617d7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.inc @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Scope; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MethodScopeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 6 => 1, + 30 => 1, + 39 => 1, + 46 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.inc new file mode 100644 index 00000000..dd6530e8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.inc @@ -0,0 +1,127 @@ +func2()); + $result = $this->getValue($value); + return $this->setValue($result); + } + + public static function /* */ func1() + { + return $this->setValue($result); + } + + public static function + func1() + { + return $this->setValue($result); + } + + public function func1() + { + $value = 'hello'; + $newValue = array($this->func2()); + $result = $this->getValue($value); + return $this->setValue($result); + } + + function func1() + { + $value = 'hello'; + $newValue = array($this->func2()); + $result = $this->getValue($value); + return $this->setValue($result); + } + + public static function func1() { + return function() { + echo $this->name; + }; + } + + private static function func1(array $data) + { + return new class() + { + private $data; + + public function __construct(array $data) + { + $this->data = $data; + } + }; + } + + public function getAnonymousClass() { + return new class() { + public static function something() { + $this->doSomething(); + } + }; + } +} + +trait MyTrait { + public static function myFunc() { + $this->doSomething(); + } +} + +$b = new class() +{ + public static function myFunc() { + $this->doSomething(); + } + + public static function other() { + return fn () => $this->name; + } + + public static function anonClassUseThis() { + return new class($this) { + public function __construct($class) { + } + }; + } + + public static function anonClassAnotherThis() { + return new class() { + public function __construct() { + $this->id = 1; + } + }; + } + + public static function anonClassNestedUseThis() { + return new class(new class($this) {}) { + }; + } + + public static function anonClassNestedAnotherThis() { + return new class(new class() { + public function __construct() { + $this->id = 1; + } + }) { + }; + } + + public static function thisMustBeLowercase() { + $This = 'hey'; + + return $This; + } +} + +enum MyEnum { + private function notStatic () { + $this->doSomething(); + } + + public static function myFunc() { + $this->doSomething(); + } +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.php new file mode 100644 index 00000000..b1a5dd6a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Scope; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class StaticThisUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 8 => 1, + 9 => 1, + 14 => 1, + 20 => 1, + 41 => 1, + 61 => 1, + 69 => 1, + 76 => 1, + 80 => 1, + 84 => 1, + 99 => 1, + 125 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc new file mode 100644 index 00000000..3bf4186e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc @@ -0,0 +1,49 @@ +add_help_tab( array( +'id' => <<', +) ); + +// phpcs:set Squiz.Strings.ConcatenationSpacing spacing 1 + +$string = 'Hello'.$there.'. How are'.$you.$going. "today $okay"; +$string = 'Hello' . $there . '. How are' . $you . $going . "today $okay"; +$string = 'Hello'.$there; +$string = 'Hello'. $there; +$string = 'Hello' .$there; + +// phpcs:set Squiz.Strings.ConcatenationSpacing ignoreNewlines true +$y = '1' + . '2' + . '3'; + +$y = '1' . + '2' . + '3'; + +$y = '1' +. '2' +. '3'; + +$y = '1' + .'2'. + '3' + . '4'; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc.fixed new file mode 100644 index 00000000..b45f1a43 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc.fixed @@ -0,0 +1,47 @@ +add_help_tab( array( +'id' => <<', +) ); + +// phpcs:set Squiz.Strings.ConcatenationSpacing spacing 1 + +$string = 'Hello' . $there . '. How are' . $you . $going . "today $okay"; +$string = 'Hello' . $there . '. How are' . $you . $going . "today $okay"; +$string = 'Hello' . $there; +$string = 'Hello' . $there; +$string = 'Hello' . $there; + +// phpcs:set Squiz.Strings.ConcatenationSpacing ignoreNewlines true +$y = '1' + . '2' + . '3'; + +$y = '1' . + '2' . + '3'; + +$y = '1' +. '2' +. '3'; + +$y = '1' + . '2' . + '3' + . '4'; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.php new file mode 100644 index 00000000..862af7d2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ConcatenationSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 5, + 5 => 1, + 6 => 1, + 9 => 1, + 10 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 16 => 5, + 22 => 1, + 27 => 5, + 29 => 1, + 30 => 1, + 31 => 1, + 47 => 2, + 49 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc new file mode 100644 index 00000000..c8cc6383 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc @@ -0,0 +1,37 @@ +"; +$string = "Value: $var[test]"; +$string = "\0"; +$string = "\$var"; + +$x = "bar = '$z', +baz = '" . $a . "'...$x"; + +$string = "Hello +there"; +$string = 'Hello +there'; + +$string = "\123 \234"."\u123"."\e"; + +echo "window.location = \"".$url."\";\n"; +echo "" + +$string = "Hello + there"; + +function test() { + echo "It Worked'; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc.fixed new file mode 100644 index 00000000..97309194 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc.fixed @@ -0,0 +1,37 @@ +"; +$string = "Value: $var[test]"; +$string = "\0"; +$string = '$var'; + +$x = "bar = '$z', +baz = '" . $a . "'...$x"; + +$string = 'Hello +there'; +$string = 'Hello +there'; + +$string = "\123 \234"."\u123"."\e"; + +echo 'window.location = "'.$url."\";\n"; +echo '' + +$string = 'Hello + there'; + +function test() { + echo "It Worked'; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.php new file mode 100644 index 00000000..a95d1888 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DoubleQuoteUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 5 => 1, + 6 => 1, + 8 => 2, + 14 => 1, + 15 => 1, + 17 => 1, + 19 => 1, + 20 => 1, + 22 => 1, + 29 => 1, + 30 => 1, + 32 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc new file mode 100644 index 00000000..9e0391da --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc @@ -0,0 +1,13 @@ +returndate == 0) ? 'Not returned' : date('d/m/Y', $loan_device->returndate); +?> +

    +

    diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc.fixed new file mode 100644 index 00000000..37c7d24c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc.fixed @@ -0,0 +1,13 @@ +returndate == 0) ? 'Not returned' : date('d/m/Y', $loan_device->returndate); +?> +

    +

    diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.php new file mode 100644 index 00000000..0d9af1e9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EchoedStringsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 13 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.inc new file mode 100644 index 00000000..fa65112f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.inc @@ -0,0 +1,9 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class CastSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 1, + 5 => 1, + 6 => 1, + 9 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc new file mode 100644 index 00000000..70abae43 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc @@ -0,0 +1,269 @@ + +
    + + + +
    + children as $child) { + // There should be no error after this + // foreach, because it is followed by a + // close PHP tag. + } + ?> +
    +children as $child) { + echo $child; + +} + +if ($defaultPageDesign === 0 + && $defaultCascade === TRUE + && $defaultChildDesign === 0 +) { + $settingsUpdated = FALSE; +} + +foreach ( $blah as $var ) { + if ( $blah ) { + } +} + +if ( + $defaultPageDesign === 0 + && $defaultCascade === TRUE + && $defaultChildDesign === 0 +) { + $settingsUpdated = FALSE; +} + +$moo = 'blar'; +switch ($moo) +{ + case 'blar': + if ($moo === 'blar2') { + $moo = 'blar' + } + return $moo; + + default: + $moo = 'moo'; + break; +} + +do { +} +while (true); + +try { + // Something +} catch (Exception $e) { + // Something +} + +try { + + // Something + +} catch (Exception $e) { + + // Something + +} + +if ($one) { +} +elseif ($two) { +} +// else if something +else if ($three) { +} // else do something +else { +} + +if ($one) { + +} + +do { + echo 'hi'; +} while ( $blah ); + +if ($one) { +} +// No blank line here. +if ($two) { +} + +switch ($moo) +{ + case 'blar': + if ($moo === 'blar2') { + $moo = 'blar' + } + + return $moo; +} + +try { + // Something +} +catch (Exception $e) { + // Something +} +finally { + // Something +} + +if ($foo) { + + + /** + * Comment + */ + function foo() { + // Code here + } + + + /** + * Comment + */ + class bar() { + + }//end class + + +} + +if (true) { // some comment goes here + + echo 'foo'; +} + +if (true) { echo 'foo'; + + echo 'foo'; +} + +if ($true) { + echo 'hi 2'; +}//end if +echo 'hi'; + +if ($true) { + echo 'hi 2'; +} // phpcs:enable Standard.Category.Sniff -- for reasons. +echo 'hi'; + +?> + + + + + + + 1, + 2 => 2, + +}; +echo $expr; + +if($true) { + + enum SomeEnum {} + +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc.fixed new file mode 100644 index 00000000..c64de25e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc.fixed @@ -0,0 +1,261 @@ + + + + + +
    + children as $child) { + // There should be no error after this + // foreach, because it is followed by a + // close PHP tag. + } + ?> +
    +children as $child) { + echo $child; +} + +if ($defaultPageDesign === 0 + && $defaultCascade === TRUE + && $defaultChildDesign === 0 +) { + $settingsUpdated = FALSE; +} + +foreach ($blah as $var) { + if ($blah) { + } +} + +if ($defaultPageDesign === 0 + && $defaultCascade === TRUE + && $defaultChildDesign === 0 +) { + $settingsUpdated = FALSE; +} + +$moo = 'blar'; +switch ($moo) +{ + case 'blar': + if ($moo === 'blar2') { + $moo = 'blar' + } + return $moo; + + default: + $moo = 'moo'; + break; +} + +do { +} +while (true); + +try { + // Something +} catch (Exception $e) { + // Something +} + +try { + // Something +} catch (Exception $e) { + // Something +} + +if ($one) { +} +elseif ($two) { +} +// else if something +else if ($three) { +} // else do something +else { +} + +if ($one) { +} + +do { + echo 'hi'; +} while ($blah); + +if ($one) { +} + +// No blank line here. +if ($two) { +} + +switch ($moo) +{ + case 'blar': + if ($moo === 'blar2') { + $moo = 'blar' + } + return $moo; +} + +try { + // Something +} +catch (Exception $e) { + // Something +} +finally { + // Something +} + +if ($foo) { + + + /** + * Comment + */ + function foo() { + // Code here + } + + + /** + * Comment + */ + class bar() { + + }//end class + + +} + +if (true) { // some comment goes here + echo 'foo'; +} + +if (true) { echo 'foo'; + + echo 'foo'; +} + +if ($true) { + echo 'hi 2'; +}//end if + +echo 'hi'; + +if ($true) { + echo 'hi 2'; +} // phpcs:enable Standard.Category.Sniff -- for reasons. + +echo 'hi'; + +?> + + + + + + 1, + 2 => 2, +}; + +echo $expr; + +if($true) { + + enum SomeEnum {} + +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js new file mode 100644 index 00000000..1c889a1c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js @@ -0,0 +1,93 @@ + +if (something) { +} +for (i = 0; i < 10; i++) { +} + +while (true) { + for (i = 0; i < 10; i++) { + } + if (something) { + } + + do { + } while (true); + +} + +if (one) { +} else (two) { +} else if (three) { +} +if (one) { +} else (two) { +} else if (three) { +} + +switch (blah) { + case 'one': + if (blah) { + // There are no spaces before break. + } + break; + + default: + if (blah) { + // There are no spaces before break. + } + break; +} + +switch (blah) { + case 'one': + if (blah) { + // There are no spaces before break. + } + break; + + default: + if (blah) { + // Code here. + } +} + +for (i = 0; i < 10; i++) { + if (blah) { + } + break; +} + +while (true) { + for (i = 0; i < 10; i++) { + + if (something) { + } + + } + + do { + + alert(i); + } while (true); +} + +for ( i = 0; i < 10; i++ ) { + if ( blah ) { + } +} + +var x = { + a: function () { + if (blah) { + } + + }, +}; + +if (one) { +} +// else if something +else if (two) { +} // else do something +else { +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js.fixed new file mode 100644 index 00000000..bb979bc8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js.fixed @@ -0,0 +1,93 @@ + +if (something) { +} + +for (i = 0; i < 10; i++) { +} + +while (true) { + for (i = 0; i < 10; i++) { + } + + if (something) { + } + + do { + } while (true); +} + +if (one) { +} else (two) { +} else if (three) { +} + +if (one) { +} else (two) { +} else if (three) { +} + +switch (blah) { + case 'one': + if (blah) { + // There are no spaces before break. + } + break; + + default: + if (blah) { + // There are no spaces before break. + } + break; +} + +switch (blah) { + case 'one': + if (blah) { + // There are no spaces before break. + } + break; + + default: + if (blah) { + // Code here. + } +} + +for (i = 0; i < 10; i++) { + if (blah) { + } + + break; +} + +while (true) { + for (i = 0; i < 10; i++) { + if (something) { + } + } + + do { + alert(i); + } while (true); +} + +for (i = 0; i < 10; i++) { + if (blah) { + } +} + +var x = { + a: function () { + if (blah) { + } + + }, +}; + +if (one) { +} +// else if something +else if (two) { +} // else do something +else { +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.php new file mode 100644 index 00000000..ac3f5d6f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.php @@ -0,0 +1,103 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ControlStructureSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='ControlStructureSpacingUnitTest.inc') + { + switch ($testFile) { + case 'ControlStructureSpacingUnitTest.inc': + return [ + 3 => 1, + 5 => 1, + 8 => 1, + 15 => 1, + 23 => 1, + 74 => 1, + 79 => 1, + 82 => 1, + 83 => 1, + 87 => 1, + 103 => 1, + 113 => 2, + 114 => 2, + 118 => 1, + 150 => 1, + 153 => 1, + 154 => 1, + 157 => 1, + 170 => 1, + 176 => 2, + 179 => 1, + 189 => 1, + 225 => 1, + 237 => 1, + 242 => 1, + 246 => 1, + 248 => 1, + 257 => 3, + 261 => 1, + 262 => 1, + ]; + break; + case 'ControlStructureSpacingUnitTest.js': + return [ + 3 => 1, + 9 => 1, + 15 => 1, + 21 => 1, + 56 => 1, + 61 => 1, + 64 => 1, + 65 => 1, + 68 => 1, + 74 => 2, + 75 => 2, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.inc new file mode 100644 index 00000000..e831e257 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.inc @@ -0,0 +1,39 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionClosingBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='FunctionClosingBraceSpaceUnitTest.inc') + { + switch ($testFile) { + case 'FunctionClosingBraceSpaceUnitTest.inc': + return [ + 10 => 1, + 21 => 1, + 28 => 1, + 29 => 1, + 31 => 1, + 39 => 1, + ]; + break; + case 'FunctionClosingBraceSpaceUnitTest.js': + return [ + 13 => 1, + 25 => 1, + 32 => 1, + 53 => 1, + 59 => 1, + 67 => 1, + 84 => 1, + 128 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.inc new file mode 100644 index 00000000..fe2c903b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.inc @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionOpeningBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='FunctionOpeningBraceSpaceUnitTest.inc') + { + switch ($testFile) { + case 'FunctionOpeningBraceSpaceUnitTest.inc': + return [ + 10 => 1, + 25 => 1, + 49 => 1, + ]; + + case 'FunctionOpeningBraceSpaceUnitTest.js': + return [ + 11 => 1, + 31 => 1, + 38 => 1, + 88 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc new file mode 100644 index 00000000..36a287f0 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc @@ -0,0 +1,576 @@ +setLogger(new class { + public function a(){} + private function b(){} + protected function c(){} +}); + +?> + +setLogger(new class { + + public function a(){} + + private function b(){} + + protected function c(){} + +}); + +?> + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FunctionSpacingUnitTest.1.inc': + return [ + 26 => 1, + 35 => 1, + 44 => 1, + 51 => 1, + 55 => 1, + 61 => 1, + 64 => 1, + 66 => 1, + 81 => 1, + 100 => 1, + 111 => 1, + 113 => 1, + 119 => 2, + 141 => 1, + 160 => 1, + 173 => 2, + 190 => 1, + 224 => 2, + 281 => 1, + 282 => 1, + 295 => 1, + 297 => 1, + 303 => 1, + 327 => 1, + 329 => 1, + 338 => 1, + 344 => 1, + 345 => 1, + 354 => 2, + 355 => 1, + 356 => 1, + 360 => 2, + 361 => 1, + 362 => 1, + 385 => 1, + 399 => 1, + 411 => 2, + 418 => 2, + 426 => 2, + 432 => 1, + 437 => 1, + 438 => 1, + 442 => 2, + 444 => 1, + 449 => 1, + 458 => 2, + 459 => 1, + 460 => 1, + 465 => 2, + 466 => 1, + 467 => 1, + 471 => 1, + 473 => 2, + 475 => 1, + 478 => 2, + 479 => 1, + 483 => 2, + 495 => 1, + 529 => 1, + 539 => 1, + 547 => 2, + 551 => 1, + 553 => 1, + 560 => 1, + 566 => 1, + ]; + + case 'FunctionSpacingUnitTest.2.inc': + return [2 => 1]; + + case 'FunctionSpacingUnitTest.3.inc': + return [7 => 1]; + + case 'FunctionSpacingUnitTest.5.inc': + return [5 => 1]; + + case 'FunctionSpacingUnitTest.6.inc': + return [10 => 1]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc new file mode 100644 index 00000000..e8f2edad --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc @@ -0,0 +1,43 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LanguageConstructSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 7 => 1, + 11 => 1, + 15 => 1, + 19 => 1, + 23 => 1, + 27 => 1, + 31 => 1, + 34 => 1, + 35 => 1, + 39 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.inc new file mode 100644 index 00000000..c2f4ec7d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.inc @@ -0,0 +1,19 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LogicalOperatorSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='LogicalOperatorSpacingUnitTest.inc') + { + return [ + 4 => 2, + 5 => 3, + 6 => 3, + 15 => 1, + 17 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc new file mode 100644 index 00000000..12b55176 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc @@ -0,0 +1,374 @@ + 'a', 'b' => 'b' ), + $varQ = 'string', + $varR = 123; +} + +// Make sure the determination of whether a property is the first property or not is done correctly. +class ClassUsingSimpleTraits +{ + use HelloWorld; + + + /* comment */ + public $firstVar = array( 'a', 'b' ); + protected $secondVar = true; +} + +class ClassUsingComplexTraits +{ + use A, B { + B::smallTalk insteadof A; + A::bigTalk insteadof B; + } + + + + public $firstVar = array( 'a', 'b' ); + + + /* comment */ + protected $secondVar = true; +} + +class Foo +{ + + + private function foo() + { + } + + + /* no error here because after function */ + private $bar = false; +} + +class CommentedOutCodeAtStartOfClass { + + /** + * Description. + * + * @var bool + */ + //public $commented_out_property = true; + + /** + * Description. + * + * @var bool + */ + public $property = true; +} + +class CommentedOutCodeAtStartOfClassNoBlankLine { + + // phpcs:disable Stnd.Cat.Sniff -- For reasons. + /** + * Description. + * + * @var bool + */ + public $property = true; +} + +class HasAttributes +{ + /** + * Short description of the member variable. + * + * @var array + */ + + #[ORM\Id]#[ORM\Column("integer")] + + private $id; + + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\GeneratedValue] + + #[ORM\Column(ORM\Column::T_INTEGER)] + protected $height; + + #[SingleAttribute] + protected $propertySingle; + + #[FirstAttribute] + #[SecondAttribute] + protected $propertyDouble; + #[ThirdAttribute] + protected $propertyWithoutSpacing; +} + +enum SomeEnum +{ + // Enum cannot have properties + + case ONE = 'one'; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc.fixed new file mode 100644 index 00000000..d683eaad --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc.fixed @@ -0,0 +1,359 @@ + 'a', 'b' => 'b' ), + $varQ = 'string', + $varR = 123; +} + +// Make sure the determination of whether a property is the first property or not is done correctly. +class ClassUsingSimpleTraits +{ + use HelloWorld; + + /* comment */ + public $firstVar = array( 'a', 'b' ); + + protected $secondVar = true; +} + +class ClassUsingComplexTraits +{ + use A, B { + B::smallTalk insteadof A; + A::bigTalk insteadof B; + } + + public $firstVar = array( 'a', 'b' ); + + /* comment */ + protected $secondVar = true; +} + +class Foo +{ + + + private function foo() + { + } + + + /* no error here because after function */ + private $bar = false; +} + +class CommentedOutCodeAtStartOfClass { + + /** + * Description. + * + * @var bool + */ + //public $commented_out_property = true; + + /** + * Description. + * + * @var bool + */ + public $property = true; +} + +class CommentedOutCodeAtStartOfClassNoBlankLine { + + // phpcs:disable Stnd.Cat.Sniff -- For reasons. + + /** + * Description. + * + * @var bool + */ + public $property = true; +} + +class HasAttributes +{ + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\Id]#[ORM\Column("integer")] + private $id; + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\GeneratedValue] + #[ORM\Column(ORM\Column::T_INTEGER)] + protected $height; + + #[SingleAttribute] + protected $propertySingle; + + #[FirstAttribute] + #[SecondAttribute] + protected $propertyDouble; + + #[ThirdAttribute] + protected $propertyWithoutSpacing; +} + +enum SomeEnum +{ + // Enum cannot have properties + + case ONE = 'one'; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.php new file mode 100644 index 00000000..9b406681 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.php @@ -0,0 +1,85 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MemberVarSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 7 => 1, + 20 => 1, + 30 => 1, + 35 => 1, + 44 => 1, + 50 => 1, + 73 => 1, + 86 => 1, + 106 => 1, + 115 => 1, + 150 => 1, + 160 => 1, + 165 => 1, + 177 => 1, + 186 => 1, + 200 => 1, + 209 => 1, + 211 => 1, + 224 => 1, + 229 => 1, + 241 => 1, + 246 => 1, + 252 => 1, + 254 => 1, + 261 => 1, + 275 => 1, + 276 => 1, + 288 => 1, + 292 => 1, + 333 => 1, + 342 => 1, + 346 => 1, + 353 => 1, + 357 => 1, + 366 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc new file mode 100644 index 00000000..67f8ee14 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc @@ -0,0 +1,52 @@ +testThis(); +$this-> testThis(); +$this -> testThis(); +$this-> /* comment here */testThis(); +$this/* comment here */ -> testThis(); +$this + ->testThis(); +$this-> + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines true + +$this->testThis(); +$this-> testThis(); +$this -> testThis(); +$this->/* comment here */testThis(); +$this/* comment here */ -> testThis(); +$this + ->testThis(); +$this-> + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines false + +thisObject::testThis(); +thisObject:: testThis(); +thisObject :: testThis(); +thisObject::/* comment here */testThis(); +thisObject/* comment here */ :: testThis(); +thisObject + ::testThis(); +thisObject:: + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines true + +thisObject::testThis(); +thisObject:: testThis(); +thisObject :: testThis(); +thisObject::/* comment here */testThis(); +thisObject/* comment here */ :: testThis(); +thisObject + ::testThis(); +thisObject:: + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines false + +$this?->testThis(); +$this?-> testThis(); +$this ?-> testThis(); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc.fixed new file mode 100644 index 00000000..730b8e4a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc.fixed @@ -0,0 +1,48 @@ +testThis(); +$this->testThis(); +$this->testThis(); +$this->/* comment here */testThis(); +$this/* comment here */->testThis(); +$this->testThis(); +$this->testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines true + +$this->testThis(); +$this->testThis(); +$this->testThis(); +$this->/* comment here */testThis(); +$this/* comment here */->testThis(); +$this + ->testThis(); +$this-> + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines false + +thisObject::testThis(); +thisObject::testThis(); +thisObject::testThis(); +thisObject::/* comment here */testThis(); +thisObject/* comment here */::testThis(); +thisObject::testThis(); +thisObject::testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines true + +thisObject::testThis(); +thisObject::testThis(); +thisObject::testThis(); +thisObject::/* comment here */testThis(); +thisObject/* comment here */::testThis(); +thisObject + ::testThis(); +thisObject:: + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines false + +$this?->testThis(); +$this?->testThis(); +$this?->testThis(); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.php new file mode 100644 index 00000000..82a4056f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.php @@ -0,0 +1,68 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ObjectOperatorSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 2, + 5 => 1, + 6 => 2, + 8 => 1, + 9 => 1, + 15 => 1, + 16 => 2, + 18 => 2, + 27 => 1, + 28 => 2, + 30 => 2, + 32 => 1, + 33 => 1, + 39 => 1, + 40 => 2, + 42 => 2, + 51 => 1, + 52 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc new file mode 100644 index 00000000..f89cf08d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc @@ -0,0 +1,481 @@ + $j && $k< $l && $m>= $n && $o<= $p && $q<> $r; + +$a ==$b && $c !=$d && $e ===$f && $g !==$h; +$i >$j && $k <$l && $m >=$n && $o <=$p && $q <>$r; + +function myFunction($variable=0, $var2='string') {} + +if (index > -1) { +} + +array_walk_recursive($array, function(&$item) use (&$something) { +}); + +$var = saveFile(&$model, &$foo); + +// This is all valid. +$boo = -$foo; +function foo($boo = -1) {} +$foo = array('boo' => -1); +$x = $test ? -1 : 1; +$y = $test ? 1 : -1; +$z = $test ?: false; + +$closureWithDefaultParameter = function (array $testArray=array()) {}; + +switch ($foo) { + case -1: + break; +} + +$y = 1 * -1; +$y = -1 * 1; +$y = -1 * $var; +$y = 10 / -2; +$y = -10 / 2; +$y = (-10 / 2); +$y = (-10 / $var); +$y = 10 + -2; +$y = -10 + 2; + +$a = $x?$y:$z; +$a = $x ? $y : $z; + +$y = 1 + + 2 + - 3; + +$y = 1 + + 2 - + 3; + +$y = 1 ++ 2 +- 3; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true +$y = 1 + + 2 + - 3; + +$y = 1 + + 2 - + 3; + +$y = 1 ++ 2 +- 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false + +if (true || -1 == $b) { +} + +$var = array(-1); +$var = [-1]; +$var = [0, -1, -2]; + +$y = array(&$x); +$y = [&$x]; +$y = array(&$a, &$b, &$c); +$y = [&$a, &$b, &$c]; +$y = array(&$a => 1, 2 => &$b, &$c); +$y = [&$a => 1, 2 => &$b, &$c]; + +if ($a <=> $b) { +} + +if ($a <=>$b) { +} + +$a |= $b; +$a **= $b; +$a ??= $b; + +$a = +1; + +function bar($boo = +1) {} + +$username = $_GET['user']??'nobody'; + +function foo(string $bar, array $baz, ?MyClass $object) : MyClass {} + +declare(strict_types=1); + +function foo($c = ((BAR)?10:100)) {} + +$res = $a ?: $b; +$res = $a ?: $b; +$res = $a ?: $b; +$res = $a ?: $b; + +$res = $a ? : $b; +$res = $a ? : $b; +$res = $a ? : $b; +$res = $a ? : $b; + +function foo(string $a = '', ?string $b = ''): ?string {} + +// Issue #1605. +$text = preg_replace_callback( + self::CHAR_REFS_REGEX, + [ 'Sanitizer', 'decodeCharReferencesCallback' ], + $text, /* limit */ -1, $count ); + +if (true || /* test */ -1 == $b) {} +$y = 10 + /* test */ -2; + +// Issue #1604. +Hooks::run( 'ParserOptionsRegister', [ + &self::$defaults, + &self::$inCacheKey, + &self::$lazyOptions, +] ); + +$x = $foo ? function (): int { + return 1; +} : $bar; + +$x = $foo ? function ($foo) + // comment + : int { + return 1; +} : $bar; + +$x = $foo ? function ($foo) use /* comment */ ($bar): int { + return 1; +} : $bar; + +$x = !$foo ? $bar : function (): int { + return 1; +}; + +$a = + // Comment. + [ + 'a', + 'b', + ]; + +$a = +// phpcs:ignore Standard.Category.Sniff -- for reasons. +[ + 'a', + 'b', +]; + +$foo = is_array($bar) ? array_map( + function () {}, + $bar + ) : $bar; + +function bar(): array {} + +if ($line{-1} === ':') { + $line = substr($line, 0, -1); +} + +$a = $a instanceof $b; +$a = $a instanceof $b; +$a = ($a)instanceof$b; + +fn&($x) => $x; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments false +$a = 3; + +yield -1; +echo -1; +$a = -1; +func(-1); +$a = [-1]; +return -1; +print -1; +$a &= -1; +switch ($a) { + case -1: +} +$a = $a ?? -1; +$a .= -1; +$a /= -1; +$a = [1 => -1]; +$a = $a == -1; +$a = $a >= -1; +$a = $a === -1; +$a = $a != -1; +$a = $a !== -1; +$a = $a <= -1; +$a = $a <=> -1; +$a = $a and -1; +$a = $a or -1; +$a = $a xor -1; +$a -= -1; +$a %= -1; +$a *= -1; +$a |= -1; +$a += -1; +$a = $a ** -1; +$a **= -1; +$a = $a << -1; +$a <<= -1; +$a = $a >> -1; +$a >>= -1; +$a = (string) -1; +$a = (array) -1; +$a = (bool) -1; +$a = (object) -1; +$a = (unset) -1; +$a = (float) -1; +$a = (int) -1; +$a ^= -1; +$a = [$a, -1]; +$a = $a[-1]; +$a = $a ? -1 : -1; + +yield - 1; +echo - 1; +$a = - 1; +func(- 1); +$a = [- 1]; +return - 1; +print - 1; +$a &= - 1; +switch ($a) { + case - 1: +} +$a = $a ?? - 1; +$a .= - 1; +$a /= - 1; +$a = [1 => - 1]; +$a = $a == - 1; +$a = $a >= - 1; +$a = $a === - 1; +$a = $a != - 1; +$a = $a !== - 1; +$a = $a <= - 1; +$a = $a <=> - 1; +$a = $a and - 1; +$a = $a or - 1; +$a = $a xor - 1; +$a -= - 1; +$a %= - 1; +$a *= - 1; +$a |= - 1; +$a += - 1; +$a = $a ** - 1; +$a **= - 1; +$a = $a << - 1; +$a <<= - 1; +$a = $a >> - 1; +$a >>= - 1; +$a = (string) - 1; +$a = (array) - 1; +$a = (bool) - 1; +$a = (object) - 1; +$a = (unset) - 1; +$a = (float) - 1; +$a = (int) - 1; +$a ^= - 1; +$a = [$a, - 1]; +$a = $a[- 1]; +$a = $a ? - 1 : - 1; + + +yield -$b; +echo -$b; +$a = -$b; +func(-$b); +$a = [-$b]; +return -$b; +print -$b; +$a &= -$b; +switch ($a) { + case -$b: +} +$a = $a ?? -$b; +$a .= -$b; +$a /= -$b; +$a = [1 => -$b]; +$a = $a == -$b; +$a = $a >= -$b; +$a = $a === -$b; +$a = $a != -$b; +$a = $a !== -$b; +$a = $a <= -$b; +$a = $a <=> -$b; +$a = $a and -$b; +$a = $a or -$b; +$a = $a xor -$b; +$a -= -$b; +$a %= -$b; +$a *= -$b; +$a |= -$b; +$a += -$b; +$a = $a ** -$b; +$a **= -$b; +$a = $a << -$b; +$a <<= -$b; +$a = $a >> -$b; +$a >>= -$b; +$a = (string) -$b; +$a = (array) -$b; +$a = (bool) -$b; +$a = (object) -$b; +$a = (unset) -$b; +$a = (float) -$b; +$a = (int) -$b; +$a ^= -$b; +$a = [$a, -$b]; +$a = $a[-$b]; +$a = $a ? -$b : -$b; + +yield - $b; +echo - $b; +$a = - $b; +func(- $b); +$a = [- $b]; +return - $b; +print - $b; +$a &= - $b; +switch ($a) { + case - $b: +} +$a = $a ?? - $b; +$a .= - $b; +$a /= - $b; +$a = [1 => - $b]; +$a = $a == - $b; +$a = $a >= - $b; +$a = $a === - $b; +$a = $a != - $b; +$a = $a !== - $b; +$a = $a <= - $b; +$a = $a <=> - $b; +$a = $a and - $b; +$a = $a or - $b; +$a = $a xor - $b; +$a -= - $b; +$a %= - $b; +$a *= - $b; +$a |= - $b; +$a += - $b; +$a = $a ** - $b; +$a **= - $b; +$a = $a << - $b; +$a <<= - $b; +$a = $a >> - $b; +$a >>= - $b; +$a = (string) - $b; +$a = (array) - $b; +$a = (bool) - $b; +$a = (object) - $b; +$a = (unset) - $b; +$a = (float) - $b; +$a = (int) - $b; +$a ^= - $b; +$a = [$a, - $b]; +$a = $a[- $b]; +$a = $a ? - $b : - $b; + +exit -1; + +$cl = function ($boo =-1) {}; +$cl = function ($boo =+1) {}; +$fn = fn ($boo =-1) => $boo; +$fn = fn ($boo =+1) => $boo; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); + +$a = 'a '.-MY_CONSTANT; +$a = 'a '.-$b; +$a = 'a '.- MY_CONSTANT; +$a = 'a '.- $b; + +/* Intentional parse error. This has to be the last test in the file. */ +$a = 10 + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc.fixed new file mode 100644 index 00000000..138616e7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc.fixed @@ -0,0 +1,475 @@ + $j && $k < $l && $m >= $n && $o <= $p && $q <> $r; + +$a == $b && $c != $d && $e === $f && $g !== $h; +$i > $j && $k < $l && $m >= $n && $o <= $p && $q <> $r; + +function myFunction($variable=0, $var2='string') {} + +if (index > -1) { +} + +array_walk_recursive($array, function(&$item) use (&$something) { +}); + +$var = saveFile(&$model, &$foo); + +// This is all valid. +$boo = -$foo; +function foo($boo = -1) {} +$foo = array('boo' => -1); +$x = $test ? -1 : 1; +$y = $test ? 1 : -1; +$z = $test ?: false; + +$closureWithDefaultParameter = function (array $testArray=array()) {}; + +switch ($foo) { + case -1: + break; +} + +$y = 1 * -1; +$y = -1 * 1; +$y = -1 * $var; +$y = 10 / -2; +$y = -10 / 2; +$y = (-10 / 2); +$y = (-10 / $var); +$y = 10 + -2; +$y = -10 + 2; + +$a = $x ? $y : $z; +$a = $x ? $y : $z; + +$y = 1 + 2 - 3; + +$y = 1 + 2 - 3; + +$y = 1 + 2 - 3; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true +$y = 1 + + 2 + - 3; + +$y = 1 + + 2 - + 3; + +$y = 1 ++ 2 +- 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false + +if (true || -1 == $b) { +} + +$var = array(-1); +$var = [-1]; +$var = [0, -1, -2]; + +$y = array(&$x); +$y = [&$x]; +$y = array(&$a, &$b, &$c); +$y = [&$a, &$b, &$c]; +$y = array(&$a => 1, 2 => &$b, &$c); +$y = [&$a => 1, 2 => &$b, &$c]; + +if ($a <=> $b) { +} + +if ($a <=> $b) { +} + +$a |= $b; +$a **= $b; +$a ??= $b; + +$a = +1; + +function bar($boo = +1) {} + +$username = $_GET['user'] ?? 'nobody'; + +function foo(string $bar, array $baz, ?MyClass $object) : MyClass {} + +declare(strict_types=1); + +function foo($c = ((BAR) ? 10 : 100)) {} + +$res = $a ?: $b; +$res = $a ?: $b; +$res = $a ?: $b; +$res = $a ?: $b; + +$res = $a ? : $b; +$res = $a ? : $b; +$res = $a ? : $b; +$res = $a ? : $b; + +function foo(string $a = '', ?string $b = ''): ?string {} + +// Issue #1605. +$text = preg_replace_callback( + self::CHAR_REFS_REGEX, + [ 'Sanitizer', 'decodeCharReferencesCallback' ], + $text, /* limit */ -1, $count ); + +if (true || /* test */ -1 == $b) {} +$y = 10 + /* test */ -2; + +// Issue #1604. +Hooks::run( 'ParserOptionsRegister', [ + &self::$defaults, + &self::$inCacheKey, + &self::$lazyOptions, +] ); + +$x = $foo ? function (): int { + return 1; +} : $bar; + +$x = $foo ? function ($foo) + // comment + : int { + return 1; +} : $bar; + +$x = $foo ? function ($foo) use /* comment */ ($bar): int { + return 1; +} : $bar; + +$x = !$foo ? $bar : function (): int { + return 1; +}; + +$a = + // Comment. + [ + 'a', + 'b', + ]; + +$a = +// phpcs:ignore Standard.Category.Sniff -- for reasons. +[ + 'a', + 'b', +]; + +$foo = is_array($bar) ? array_map( + function () {}, + $bar + ) : $bar; + +function bar(): array {} + +if ($line{-1} === ':') { + $line = substr($line, 0, -1); +} + +$a = $a instanceof $b; +$a = $a instanceof $b; +$a = ($a) instanceof $b; + +fn&($x) => $x; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments false +$a = 3; + +yield -1; +echo -1; +$a = -1; +func(-1); +$a = [-1]; +return -1; +print -1; +$a &= -1; +switch ($a) { + case -1: +} +$a = $a ?? -1; +$a .= -1; +$a /= -1; +$a = [1 => -1]; +$a = $a == -1; +$a = $a >= -1; +$a = $a === -1; +$a = $a != -1; +$a = $a !== -1; +$a = $a <= -1; +$a = $a <=> -1; +$a = $a and -1; +$a = $a or -1; +$a = $a xor -1; +$a -= -1; +$a %= -1; +$a *= -1; +$a |= -1; +$a += -1; +$a = $a ** -1; +$a **= -1; +$a = $a << -1; +$a <<= -1; +$a = $a >> -1; +$a >>= -1; +$a = (string) -1; +$a = (array) -1; +$a = (bool) -1; +$a = (object) -1; +$a = (unset) -1; +$a = (float) -1; +$a = (int) -1; +$a ^= -1; +$a = [$a, -1]; +$a = $a[-1]; +$a = $a ? -1 : -1; + +yield - 1; +echo - 1; +$a = - 1; +func(- 1); +$a = [- 1]; +return - 1; +print - 1; +$a &= - 1; +switch ($a) { + case - 1: +} +$a = $a ?? - 1; +$a .= - 1; +$a /= - 1; +$a = [1 => - 1]; +$a = $a == - 1; +$a = $a >= - 1; +$a = $a === - 1; +$a = $a != - 1; +$a = $a !== - 1; +$a = $a <= - 1; +$a = $a <=> - 1; +$a = $a and - 1; +$a = $a or - 1; +$a = $a xor - 1; +$a -= - 1; +$a %= - 1; +$a *= - 1; +$a |= - 1; +$a += - 1; +$a = $a ** - 1; +$a **= - 1; +$a = $a << - 1; +$a <<= - 1; +$a = $a >> - 1; +$a >>= - 1; +$a = (string) - 1; +$a = (array) - 1; +$a = (bool) - 1; +$a = (object) - 1; +$a = (unset) - 1; +$a = (float) - 1; +$a = (int) - 1; +$a ^= - 1; +$a = [$a, - 1]; +$a = $a[- 1]; +$a = $a ? - 1 : - 1; + + +yield -$b; +echo -$b; +$a = -$b; +func(-$b); +$a = [-$b]; +return -$b; +print -$b; +$a &= -$b; +switch ($a) { + case -$b: +} +$a = $a ?? -$b; +$a .= -$b; +$a /= -$b; +$a = [1 => -$b]; +$a = $a == -$b; +$a = $a >= -$b; +$a = $a === -$b; +$a = $a != -$b; +$a = $a !== -$b; +$a = $a <= -$b; +$a = $a <=> -$b; +$a = $a and -$b; +$a = $a or -$b; +$a = $a xor -$b; +$a -= -$b; +$a %= -$b; +$a *= -$b; +$a |= -$b; +$a += -$b; +$a = $a ** -$b; +$a **= -$b; +$a = $a << -$b; +$a <<= -$b; +$a = $a >> -$b; +$a >>= -$b; +$a = (string) -$b; +$a = (array) -$b; +$a = (bool) -$b; +$a = (object) -$b; +$a = (unset) -$b; +$a = (float) -$b; +$a = (int) -$b; +$a ^= -$b; +$a = [$a, -$b]; +$a = $a[-$b]; +$a = $a ? -$b : -$b; + +yield - $b; +echo - $b; +$a = - $b; +func(- $b); +$a = [- $b]; +return - $b; +print - $b; +$a &= - $b; +switch ($a) { + case - $b: +} +$a = $a ?? - $b; +$a .= - $b; +$a /= - $b; +$a = [1 => - $b]; +$a = $a == - $b; +$a = $a >= - $b; +$a = $a === - $b; +$a = $a != - $b; +$a = $a !== - $b; +$a = $a <= - $b; +$a = $a <=> - $b; +$a = $a and - $b; +$a = $a or - $b; +$a = $a xor - $b; +$a -= - $b; +$a %= - $b; +$a *= - $b; +$a |= - $b; +$a += - $b; +$a = $a ** - $b; +$a **= - $b; +$a = $a << - $b; +$a <<= - $b; +$a = $a >> - $b; +$a >>= - $b; +$a = (string) - $b; +$a = (array) - $b; +$a = (bool) - $b; +$a = (object) - $b; +$a = (unset) - $b; +$a = (float) - $b; +$a = (int) - $b; +$a ^= - $b; +$a = [$a, - $b]; +$a = $a[- $b]; +$a = $a ? - $b : - $b; + +exit -1; + +$cl = function ($boo =-1) {}; +$cl = function ($boo =+1) {}; +$fn = fn ($boo =-1) => $boo; +$fn = fn ($boo =+1) => $boo; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); + +$a = 'a '.-MY_CONSTANT; +$a = 'a '.-$b; +$a = 'a '.- MY_CONSTANT; +$a = 'a '.- $b; + +/* Intentional parse error. This has to be the last test in the file. */ +$a = 10 + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js new file mode 100644 index 00000000..16eb130f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js @@ -0,0 +1,103 @@ + + +result = 1 + 2; +result = 1 + 2; +result = 1 + 2; +result = 1 +2; +result = 1+ 2; +result = 1+2; + +result = 1 - 2; +result = 1 - 2; +result = 1 - 2; +result = 1 -2; +result = 1- 2; +result = 1-2; + +result = 1 * 2; +result = 1 * 2; +result = 1 * 2; +result = 1 *2; +result = 1* 2; +result = 1*2; + +result = 1 / 2; +result = 1 / 2; +result = 1 / 2; +result = 1 /2; +result = 1/ 2; +result = 1/2; + +result = 1 % 2; +result = 1 % 2; +result = 1 % 2; +result = 1 %2; +result = 1% 2; +result = 1%2; +result = '100%'; + +result += 4; +result+=4; +result -= 4; +result-=4; +result /= 4; +result/=4; +result *=4; +result*=4; + +$.localScroll({offset: {top: -32}}); + +switch (result) { + case -1: + break; +} + +result = x?y:z; +result = x ? y : z; + +if (something === true + ^ somethingElse === true +) { + return false; +} + +y = 1 + + 2 + - 3; + +y = 1 + + 2 - + 3; + +y = 1 ++ 2 +- 3; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true +y = 1 + + 2 + - 3; + +y = 1 + + 2 - + 3; + +y = 1 ++ 2 +- 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false + +if (true || -1 == b) { +} + +x = x << y; +x <<= y; +x = x >> y; +x >>= y; +x = x >>> y; +x >>>= y; + +var foo = bar.map(baz=> baz.length); + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments false +a = 3; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed new file mode 100644 index 00000000..877db467 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed @@ -0,0 +1,97 @@ + + +result = 1 + 2; +result = 1 + 2; +result = 1 + 2; +result = 1 + 2; +result = 1 + 2; +result = 1 + 2; + +result = 1 - 2; +result = 1 - 2; +result = 1 - 2; +result = 1 - 2; +result = 1 - 2; +result = 1 - 2; + +result = 1 * 2; +result = 1 * 2; +result = 1 * 2; +result = 1 * 2; +result = 1 * 2; +result = 1 * 2; + +result = 1 / 2; +result = 1 / 2; +result = 1 / 2; +result = 1 / 2; +result = 1 / 2; +result = 1 / 2; + +result = 1 % 2; +result = 1 % 2; +result = 1 % 2; +result = 1 % 2; +result = 1 % 2; +result = 1 % 2; +result = '100%'; + +result += 4; +result += 4; +result -= 4; +result -= 4; +result /= 4; +result /= 4; +result *= 4; +result *= 4; + +$.localScroll({offset: {top: -32}}); + +switch (result) { + case -1: + break; +} + +result = x ? y : z; +result = x ? y : z; + +if (something === true + ^ somethingElse === true +) { + return false; +} + +y = 1 + 2 - 3; + +y = 1 + 2 - 3; + +y = 1 + 2 - 3; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true +y = 1 + + 2 + - 3; + +y = 1 + + 2 - + 3; + +y = 1 ++ 2 +- 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false + +if (true || -1 == b) { +} + +x = x << y; +x <<= y; +x = x >> y; +x >>= y; +x = x >>> y; +x >>>= y; + +var foo = bar.map(baz => baz.length); + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments false +a = 3; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php new file mode 100644 index 00000000..8e8ad98d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php @@ -0,0 +1,170 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class OperatorSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='OperatorSpacingUnitTest.inc') + { + switch ($testFile) { + case 'OperatorSpacingUnitTest.inc': + return [ + 4 => 1, + 5 => 2, + 6 => 1, + 7 => 1, + 8 => 2, + 11 => 1, + 12 => 2, + 13 => 1, + 14 => 1, + 15 => 2, + 18 => 1, + 19 => 2, + 20 => 1, + 21 => 1, + 22 => 2, + 25 => 1, + 26 => 2, + 27 => 1, + 28 => 1, + 29 => 2, + 32 => 1, + 33 => 2, + 34 => 1, + 35 => 1, + 36 => 2, + 40 => 2, + 42 => 2, + 44 => 2, + 45 => 1, + 46 => 2, + 53 => 4, + 54 => 3, + 59 => 10, + 64 => 1, + 77 => 4, + 78 => 1, + 79 => 1, + 80 => 2, + 81 => 1, + 84 => 6, + 85 => 6, + 87 => 4, + 88 => 5, + 90 => 4, + 91 => 5, + 128 => 4, + 132 => 1, + 133 => 1, + 135 => 1, + 136 => 1, + 140 => 1, + 141 => 1, + 174 => 1, + 177 => 1, + 178 => 1, + 179 => 1, + 185 => 2, + 191 => 4, + 194 => 1, + 195 => 1, + 196 => 2, + 199 => 1, + 200 => 1, + 201 => 2, + 239 => 1, + 246 => 1, + 265 => 2, + 266 => 2, + 271 => 2, + ]; + break; + case 'OperatorSpacingUnitTest.js': + return [ + 4 => 1, + 5 => 2, + 6 => 1, + 7 => 1, + 8 => 2, + 11 => 1, + 12 => 2, + 13 => 1, + 14 => 1, + 15 => 2, + 18 => 1, + 19 => 2, + 20 => 1, + 21 => 1, + 22 => 2, + 25 => 1, + 26 => 2, + 27 => 1, + 28 => 1, + 29 => 2, + 32 => 1, + 33 => 2, + 34 => 1, + 35 => 1, + 36 => 2, + 40 => 2, + 42 => 2, + 44 => 2, + 45 => 1, + 46 => 2, + 55 => 4, + 65 => 1, + 66 => 1, + 68 => 1, + 69 => 1, + 73 => 1, + 74 => 1, + 100 => 1, + 103 => 2, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js new file mode 100644 index 00000000..15890b96 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js @@ -0,0 +1,40 @@ +var x = { + b: 'x', + xasd: x, + abc:x, + a: function () { + alert('thats right'); + x = (x?a:x); + }, + casdasd : 123123, + omgwtfbbq: { + a: 1, + b: 2 + } +}; + +id = id.replace(/row\/:/gi, ''); + +outer_loop: +for (i=0; i<3; i++) { + for (j=0; j<5; j++) { + if (j==x) + break outer_loop; + } +} +alert('hi'); + +even_number: if ((i % 2) == 0) { + if (i == 12) + break even_number; +} + +switch (blah) { + case dfx.DOM_VK_LEFT: + this.caretLeft(shiftKey); + break; + default: + if (blah) { + } + break; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js.fixed new file mode 100644 index 00000000..f332878e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js.fixed @@ -0,0 +1,39 @@ +var x = { + b: 'x', + xasd: x, + abc: x, + a: function () { + alert('thats right'); + x = (x?a:x); + }, + casdasd: 123123, + omgwtfbbq: { + a: 1, + b: 2 + } +}; + +id = id.replace(/row\/:/gi, ''); + +outer_loop: for (i=0; i<3; i++) { + for (j=0; j<5; j++) { + if (j==x) + break outer_loop; + } +} +alert('hi'); + +even_number: if ((i % 2) == 0) { + if (i == 12) + break even_number; +} + +switch (blah) { + case dfx.DOM_VK_LEFT: + this.caretLeft(shiftKey); + break; + default: + if (blah) { + } + break; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.php new file mode 100644 index 00000000..e80f9367 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class PropertyLabelSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 1, + 9 => 2, + 10 => 1, + 12 => 1, + 18 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc new file mode 100644 index 00000000..ecae5c6d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc @@ -0,0 +1,134 @@ +{$property} =& new $class_name($this->db_index); + $this->modules[$module] =& $this->{$property}; +} + +foreach ($elements as $element) { + if ($something) { + // Do IF. + } else if ($somethingElse) { + // Do ELSE. + } +} + +if ($token['code'] === T_COMMENT + && $multiLineComment === false + && (substr($token['content'], 0, 2) === '//' + || $token['content']{0} === '#') +) { +} + +switch ($blah) { + case 'one': + echo 'one'; + break; + default: + echo 'another'; +} + +?> + +getRow()): ?> +

    + + + +
    + +

    o hai!

    + +
    + + + + + + + + + + + + $x + $y; + +$match = match ($test) { 1 => 'a', 2 => 'b' }; + +$match = match ($test) { + 1 => 'a', + 2 => 'b' + }; + +?> + +
    + +
    + +{$property} =& new $class_name($this->db_index); + $this->modules[$module] =& $this->{$property}; +} + +foreach ($elements as $element) { + if ($something) { + // Do IF. + } else if ($somethingElse) { + // Do ELSE. + } +} + +if ($token['code'] === T_COMMENT + && $multiLineComment === false + && (substr($token['content'], 0, 2) === '//' + || $token['content']{0} === '#') +) { +} + +switch ($blah) { + case 'one': + echo 'one'; + break; + default: + echo 'another'; +} + +?> + +getRow()): ?> +

    + + + +
    + +

    o hai!

    + +
    + + + + + + + + + + + + $x + $y; + +$match = match ($test) { 1 => 'a', 2 => 'b' +}; + +$match = match ($test) { + 1 => 'a', + 2 => 'b' +}; + +?> + +
    + +
    + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ScopeClosingBraceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 11 => 1, + 13 => 1, + 24 => 1, + 80 => 1, + 102 => 1, + 111 => 1, + 116 => 1, + 122 => 1, + 130 => 1, + 134 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc new file mode 100644 index 00000000..12685dc9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc @@ -0,0 +1,141 @@ + 'a', 'b' => 'b' ), + $varQ = 'string', + $varR = 123; + + // Intentionally missing a semi-colon for testing. + public + $varS, + $varT +} + +// Issue #3188 - static as return type. +public static function fCreate($attributes = []): static +{ + return static::factory()->create($attributes); +} + +public static function fCreate($attributes = []): ?static +{ + return static::factory()->create($attributes); +} + +// Also account for static used within union types. +public function fCreate($attributes = []): object|static +{ +} + +// Ensure that static as a scope keyword when preceeded by a colon which is not for a type declaration is still handled. +$callback = $cond ? get_fn_name() : static function ($a) { return $a * 10; }; + +class TypedProperties { + public + int $var; + + protected string $stringA, $stringB; + + private bool + $boolA, + $boolB; +} + +// PHP 8.0 constructor property promotion. +class ConstructorPropertyPromotionTest { + public function __construct( + public $x = 0.0, + protected $y = '', + private $z = null, + $normalParam, + ) {} +} + +class ConstructorPropertyPromotionWithTypesTest { + public function __construct(protected float|int $x, public?string &$y = 'test', private mixed $z) {} +} + +// PHP 8.1 readonly keywords. +class ReadonlyTest { + public readonly int $publicReadonlyProperty; + + protected readonly int $protectedReadonlyProperty; + + readonly protected int $protectedReadonlyProperty; + + readonly private int $privateReadonlyProperty; + + public function __construct(readonly protected float|int $x, public readonly?string &$y = 'test') {} +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc.fixed new file mode 100644 index 00000000..d3b682ed --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc.fixed @@ -0,0 +1,135 @@ + 'a', 'b' => 'b' ), + $varQ = 'string', + $varR = 123; + + // Intentionally missing a semi-colon for testing. + public + $varS, + $varT +} + +// Issue #3188 - static as return type. +public static function fCreate($attributes = []): static +{ + return static::factory()->create($attributes); +} + +public static function fCreate($attributes = []): ?static +{ + return static::factory()->create($attributes); +} + +// Also account for static used within union types. +public function fCreate($attributes = []): object|static +{ +} + +// Ensure that static as a scope keyword when preceeded by a colon which is not for a type declaration is still handled. +$callback = $cond ? get_fn_name() : static function ($a) { return $a * 10; }; + +class TypedProperties { + public int $var; + + protected string $stringA, $stringB; + + private bool + $boolA, + $boolB; +} + +// PHP 8.0 constructor property promotion. +class ConstructorPropertyPromotionTest { + public function __construct( + public $x = 0.0, + protected $y = '', + private $z = null, + $normalParam, + ) {} +} + +class ConstructorPropertyPromotionWithTypesTest { + public function __construct(protected float|int $x, public ?string &$y = 'test', private mixed $z) {} +} + +// PHP 8.1 readonly keywords. +class ReadonlyTest { + public readonly int $publicReadonlyProperty; + + protected readonly int $protectedReadonlyProperty; + + readonly protected int $protectedReadonlyProperty; + + readonly private int $privateReadonlyProperty; + + public function __construct(readonly protected float|int $x, public readonly ?string &$y = 'test') {} +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.php new file mode 100644 index 00000000..30b66215 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.php @@ -0,0 +1,70 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ScopeKeywordSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 2, + 8 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 17 => 2, + 26 => 1, + 28 => 1, + 29 => 1, + 64 => 1, + 67 => 1, + 71 => 1, + 103 => 1, + 106 => 1, + 111 => 1, + 119 => 1, + 121 => 1, + 127 => 2, + 134 => 2, + 138 => 2, + 140 => 3, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc new file mode 100644 index 00000000..393f4845 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc @@ -0,0 +1,42 @@ +testThis(); +$test = $this->testThis() ; +$test = $this->testThis() ; +for ($var = 1 ; $var < 10 ; $var++) { + echo $var ; +} +$test = $this->testThis() /* comment here */; +$test = $this->testThis() /* comment here */ ; + +$hello ='foo'; +; + +$sum = $a /* + $b */; +$sum = $a // + $b +; +$sum = $a /* + $b + + $c */ ; + +/* + * Test that the sniff does *not* throw incorrect errors for semi-colons in + * "empty" parts of a `for` control structure. + */ +for ($i = 1; ; $i++) {} +for ( ; $ptr >= 0; $ptr-- ) {} +for ( ; ; ) {} + +// But it should when the semi-colon in a `for` follows a comment (but shouldn't move the semi-colon). +for ( /* Deliberately left empty. */ ; $ptr >= 0; $ptr-- ) {} +for ( $i = 1 ; /* Deliberately left empty. */ ; $i++ ) {} + +switch ($foo) { + case 'foo': + ; + break + ; +} + +// This is an empty statement and should be ignored. +if ($foo) { +; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc.fixed new file mode 100644 index 00000000..0d06324d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc.fixed @@ -0,0 +1,41 @@ +testThis(); +$test = $this->testThis(); +$test = $this->testThis(); +for ($var = 1; $var < 10; $var++) { + echo $var; +} +$test = $this->testThis(); /* comment here */ +$test = $this->testThis(); /* comment here */ + +$hello ='foo'; +; + +$sum = $a; /* + $b */ +$sum = $a; // + $b + +$sum = $a; /* + $b + + $c */ + +/* + * Test that the sniff does *not* throw incorrect errors for semi-colons in + * "empty" parts of a `for` control structure. + */ +for ($i = 1; ; $i++) {} +for ( ; $ptr >= 0; $ptr-- ) {} +for ( ; ; ) {} + +// But it should when the semi-colon in a `for` follows a comment (but shouldn't move the semi-colon). +for ( /* Deliberately left empty. */; $ptr >= 0; $ptr-- ) {} +for ( $i = 1; /* Deliberately left empty. */; $i++ ) {} + +switch ($foo) { + case 'foo': + ; + break; +} + +// This is an empty statement and should be ignored. +if ($foo) { +; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js new file mode 100644 index 00000000..3aafd6da --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js @@ -0,0 +1,25 @@ +var x = { + a: function () { + alert('thats right') ; + x = (x?a:x) ; + }, +} ; + +id = id.replace(/row\/:;/gi, ''); + +for (i=0 ; i<3 ; i++) { + for (j=0; j<5 ; j++) { + if (j==x) + break ; + } +} +alert('hi'); +; + +var sum = a /* + b */; + +var sum = a // +b +; + +var sum = a /* +b + + c */ ; diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js.fixed new file mode 100644 index 00000000..a547144d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js.fixed @@ -0,0 +1,25 @@ +var x = { + a: function () { + alert('thats right'); + x = (x?a:x); + }, +}; + +id = id.replace(/row\/:;/gi, ''); + +for (i=0; i<3; i++) { + for (j=0; j<5; j++) { + if (j==x) + break; + } +} +alert('hi'); +; + +var sum = a; /* + b */ + +var sum = a; // +b + + +var sum = a; /* +b + + c */ diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.php new file mode 100644 index 00000000..72196f8e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.php @@ -0,0 +1,83 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SemicolonSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='SemicolonSpacingUnitTest.inc') + { + switch ($testFile) { + case 'SemicolonSpacingUnitTest.inc': + return [ + 3 => 1, + 4 => 1, + 5 => 2, + 6 => 1, + 8 => 1, + 9 => 1, + 14 => 1, + 16 => 1, + 18 => 1, + 29 => 1, + 30 => 2, + 36 => 1, + ]; + break; + case 'SemicolonSpacingUnitTest.js': + return [ + 3 => 1, + 4 => 1, + 6 => 1, + 10 => 2, + 11 => 1, + 13 => 1, + 19 => 1, + 22 => 1, + 25 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css new file mode 100644 index 00000000..1dd1b6e6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css @@ -0,0 +1,25 @@ + +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} + +.HelpWidgetType-new-bug-title{ + float: left; +} + +/* phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true */ +.HelpWidgetType-new-bug-title{ + float: left; +} + +.HelpWidgetType-new-bug-title{ + float: left; +} +/* phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false */ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css.fixed new file mode 100644 index 00000000..59ddddb0 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css.fixed @@ -0,0 +1,23 @@ +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} + +.HelpWidgetType-new-bug-title{ + float: left; +} + +/* phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true */ +.HelpWidgetType-new-bug-title{ + float: left; +} + +.HelpWidgetType-new-bug-title{ + float: left; +} +/* phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false */ diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc new file mode 100644 index 00000000..f9dca29a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc @@ -0,0 +1,74 @@ + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc.fixed new file mode 100644 index 00000000..1d764ebf --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc.fixed @@ -0,0 +1,68 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js new file mode 100644 index 00000000..be542e77 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js @@ -0,0 +1,56 @@ + +alert('hi'); +alert('hello'); + +if (something) { + +} + + +function myFunction() +{ + alert('code here'); + + alert('code here'); + + + // Hello. + + /* + HI + */ + + +} + +function myFunction2() +{ + alert('code here'); + + + alert('code here'); + +} + +MyFunction = function() +{ + alert('code here'); + + + alert('code here'); + +}; + +// phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true + +function myFunction2() +{ + alert('code here'); + + alert('code here'); + +} + +// phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js.fixed new file mode 100644 index 00000000..960111a5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js.fixed @@ -0,0 +1,50 @@ +alert('hi'); +alert('hello'); + +if (something) { + +} + + +function myFunction() +{ + alert('code here'); + + alert('code here'); + + // Hello. + + /* + HI + */ + +} + +function myFunction2() +{ + alert('code here'); + + alert('code here'); + +} + +MyFunction = function() +{ + alert('code here'); + + alert('code here'); + +}; + +// phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true + +function myFunction2() +{ + alert('code here'); + + alert('code here'); + +} + +// phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css new file mode 100644 index 00000000..2025eeb1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css @@ -0,0 +1,3 @@ +.HelpWidgetType-new-bug-title { + float: left; +} \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css.fixed new file mode 100644 index 00000000..2025eeb1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css.fixed @@ -0,0 +1,3 @@ +.HelpWidgetType-new-bug-title { + float: left; +} \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc new file mode 100644 index 00000000..a6e2b8ad --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc @@ -0,0 +1,9 @@ + + +

    + +

    + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc.fixed new file mode 100644 index 00000000..78c45251 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc.fixed @@ -0,0 +1,7 @@ + +

    + +

    diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js new file mode 100644 index 00000000..7b0c8eac --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js @@ -0,0 +1 @@ +alert('hi'); \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js.fixed new file mode 100644 index 00000000..7b0c8eac --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js.fixed @@ -0,0 +1 @@ +alert('hi'); \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css new file mode 100644 index 00000000..9f794a08 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css @@ -0,0 +1,3 @@ +.HelpWidgetType-new-bug-title { + float: left; +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css.fixed new file mode 100644 index 00000000..2025eeb1 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css.fixed @@ -0,0 +1,3 @@ +.HelpWidgetType-new-bug-title { + float: left; +} \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc new file mode 100644 index 00000000..661ebdaf --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc.fixed new file mode 100644 index 00000000..0cb97480 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc.fixed @@ -0,0 +1,5 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js new file mode 100644 index 00000000..70f67193 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js @@ -0,0 +1 @@ +alert('hi'); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js.fixed new file mode 100644 index 00000000..70f67193 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js.fixed @@ -0,0 +1 @@ +alert('hi'); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc new file mode 100644 index 00000000..96860ffb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc.fixed new file mode 100644 index 00000000..b26b5b2c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc.fixed @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc new file mode 100644 index 00000000..4d6f06bc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc @@ -0,0 +1,5 @@ +   +  \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc.fixed new file mode 100644 index 00000000..8ec5f30d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc.fixed @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.php new file mode 100644 index 00000000..b9ff96fb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.php @@ -0,0 +1,113 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SuperfluousWhitespaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='SuperfluousWhitespaceUnitTest.inc') + { + switch ($testFile) { + case 'SuperfluousWhitespaceUnitTest.1.inc': + return [ + 2 => 1, + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 16 => 1, + 23 => 1, + 28 => 1, + 33 => 1, + 49 => 1, + 62 => 1, + 65 => 1, + 73 => 1, + ]; + break; + case 'SuperfluousWhitespaceUnitTest.2.inc': + return [ + 2 => 1, + 8 => 1, + ]; + break; + case 'SuperfluousWhitespaceUnitTest.3.inc': + return [ + 6 => 1, + 10 => 1, + ]; + break; + case 'SuperfluousWhitespaceUnitTest.4.inc': + case 'SuperfluousWhitespaceUnitTest.5.inc': + return [ + 1 => 1, + 4 => 1, + ]; + break; + case 'SuperfluousWhitespaceUnitTest.1.js': + return [ + 1 => 1, + 3 => 1, + 4 => 1, + 5 => 1, + 6 => 1, + 15 => 1, + 22 => 1, + 29 => 1, + 38 => 1, + 56 => 1, + ]; + break; + case 'SuperfluousWhitespaceUnitTest.1.css': + return [ + 1 => 1, + 8 => 1, + 9 => 1, + 11 => 1, + 25 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/ruleset.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/ruleset.xml new file mode 100644 index 00000000..87ab4c3e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/ruleset.xml @@ -0,0 +1,132 @@ + + + The Squiz coding standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + %2$s + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + + + + + + 0 + + + error + + + + + 0 + + + error + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Debug/CodeAnalyzerStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Debug/CodeAnalyzerStandard.xml new file mode 100644 index 00000000..c462b4f8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Debug/CodeAnalyzerStandard.xml @@ -0,0 +1,25 @@ + + + + + + + $bar + $baz; +} + ]]> + + + $bar + 2; +} + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Files/ClosingTagStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Files/ClosingTagStandard.xml new file mode 100644 index 00000000..aa60b8ab --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Files/ClosingTagStandard.xml @@ -0,0 +1,22 @@ + + + + + + + + + + ?> + ]]> + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/NamingConventions/ValidVariableNameStandard.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/NamingConventions/ValidVariableNameStandard.xml new file mode 100644 index 00000000..5bcde4b8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/NamingConventions/ValidVariableNameStandard.xml @@ -0,0 +1,37 @@ + + + + + + + $testNumber = 1; + ]]> + + + $Test_Number = 1; + ]]> + + + + + _bar; +} + ]]> + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php new file mode 100644 index 00000000..5df4b0fc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php @@ -0,0 +1,98 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Sniffs\Debug; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Util\Common; + +class CodeAnalyzerSniff implements Sniff +{ + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return int + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If ZendCodeAnalyzer could not be run. + */ + public function process(File $phpcsFile, $stackPtr) + { + $analyzerPath = Config::getExecutablePath('zend_ca'); + if ($analyzerPath === null) { + return; + } + + $fileName = $phpcsFile->getFilename(); + + // In the command, 2>&1 is important because the code analyzer sends its + // findings to stderr. $output normally contains only stdout, so using 2>&1 + // will pipe even stderr to stdout. + $cmd = Common::escapeshellcmd($analyzerPath).' '.escapeshellarg($fileName).' 2>&1'; + + // There is the possibility to pass "--ide" as an option to the analyzer. + // This would result in an output format which would be easier to parse. + // The problem here is that no cleartext error messages are returned; only + // error-code-labels. So for a start we go for cleartext output. + $exitCode = exec($cmd, $output, $retval); + + // Variable $exitCode is the last line of $output if no error occurs, on + // error it is numeric. Try to handle various error conditions and + // provide useful error reporting. + if (is_numeric($exitCode) === true && $exitCode > 0) { + if (is_array($output) === true) { + $msg = join('\n', $output); + } + + throw new RuntimeException("Failed invoking ZendCodeAnalyzer, exitcode was [$exitCode], retval was [$retval], output was [$msg]"); + } + + if (is_array($output) === true) { + foreach ($output as $finding) { + // The first two lines of analyzer output contain + // something like this: + // > Zend Code Analyzer 1.2.2 + // > Analyzing ... + // So skip these... + $res = preg_match("/^.+\(line ([0-9]+)\):(.+)$/", $finding, $regs); + if (empty($regs) === true || $res === false) { + continue; + } + + $phpcsFile->addWarningOnLine(trim($regs[2]), $regs[1], 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Files/ClosingTagSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Files/ClosingTagSniff.php new file mode 100644 index 00000000..0ed34d13 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Files/ClosingTagSniff.php @@ -0,0 +1,79 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Sniffs\Files; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class ClosingTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Find the last non-empty token. + $tokens = $phpcsFile->getTokens(); + for ($last = ($phpcsFile->numTokens - 1); $last > 0; $last--) { + if (trim($tokens[$last]['content']) !== '') { + break; + } + } + + if ($tokens[$last]['code'] === T_CLOSE_TAG) { + $error = 'A closing tag is not permitted at the end of a PHP file'; + $fix = $phpcsFile->addFixableError($error, $last, 'NotAllowed'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($last, $phpcsFile->eolChar); + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($last - 1), null, true); + if ($tokens[$prev]['code'] !== T_SEMICOLON + && $tokens[$prev]['code'] !== T_CLOSE_CURLY_BRACKET + && $tokens[$prev]['code'] !== T_OPEN_TAG + ) { + $phpcsFile->fixer->addContent($prev, ';'); + } + + $phpcsFile->fixer->endChangeset(); + } + + $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at EOF', 'yes'); + } else { + $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at EOF', 'no'); + }//end if + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php new file mode 100644 index 00000000..267cd0ad --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -0,0 +1,196 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class ValidVariableNameSniff extends AbstractVariableSniff +{ + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $varName = ltrim($tokens[$stackPtr]['content'], '$'); + + // If it's a php reserved var, then its ok. + if (isset($this->phpReservedVars[$varName]) === true) { + return; + } + + $objOperator = $phpcsFile->findNext([T_WHITESPACE], ($stackPtr + 1), null, true); + if ($tokens[$objOperator]['code'] === T_OBJECT_OPERATOR + || $tokens[$objOperator]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + // Check to see if we are using a variable from an object. + $var = $phpcsFile->findNext([T_WHITESPACE], ($objOperator + 1), null, true); + if ($tokens[$var]['code'] === T_STRING) { + // Either a var name or a function call, so check for bracket. + $bracket = $phpcsFile->findNext([T_WHITESPACE], ($var + 1), null, true); + + if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) { + $objVarName = $tokens[$var]['content']; + + // There is no way for us to know if the var is public or private, + // so we have to ignore a leading underscore if there is one and just + // check the main part of the variable name. + $originalVarName = $objVarName; + if (substr($objVarName, 0, 1) === '_') { + $objVarName = substr($objVarName, 1); + } + + if (Common::isCamelCaps($objVarName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$originalVarName]; + $phpcsFile->addError($error, $var, 'NotCamelCaps', $data); + } else if (preg_match('|\d|', $objVarName) === 1) { + $warning = 'Variable "%s" contains numbers but this is discouraged'; + $data = [$originalVarName]; + $phpcsFile->addWarning($warning, $stackPtr, 'ContainsNumbers', $data); + } + }//end if + }//end if + }//end if + + // There is no way for us to know if the var is public or private, + // so we have to ignore a leading underscore if there is one and just + // check the main part of the variable name. + $originalVarName = $varName; + if (substr($varName, 0, 1) === '_') { + $objOperator = $phpcsFile->findPrevious([T_WHITESPACE], ($stackPtr - 1), null, true); + if ($tokens[$objOperator]['code'] === T_DOUBLE_COLON) { + // The variable lives within a class, and is referenced like + // this: MyClass::$_variable, so we don't know its scope. + $inClass = true; + } else { + $inClass = $phpcsFile->hasCondition($stackPtr, Tokens::$ooScopeTokens); + } + + if ($inClass === true) { + $varName = substr($varName, 1); + } + } + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$originalVarName]; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data); + } else if (preg_match('|\d|', $varName) === 1) { + $warning = 'Variable "%s" contains numbers but this is discouraged'; + $data = [$originalVarName]; + $phpcsFile->addWarning($warning, $stackPtr, 'ContainsNumbers', $data); + } + + }//end processVariable() + + + /** + * Processes class member variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $varName = ltrim($tokens[$stackPtr]['content'], '$'); + $memberProps = $phpcsFile->getMemberProperties($stackPtr); + if (empty($memberProps) === true) { + // Exception encountered. + return; + } + + $public = ($memberProps['scope'] === 'public'); + + if ($public === true) { + if (substr($varName, 0, 1) === '_') { + $error = 'Public member variable "%s" must not contain a leading underscore'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'PublicHasUnderscore', $data); + } + } else { + if (substr($varName, 0, 1) !== '_') { + $scope = ucfirst($memberProps['scope']); + $error = '%s member variable "%s" must contain a leading underscore'; + $data = [ + $scope, + $varName, + ]; + $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $data); + } + } + + // Remove a potential underscore prefix for testing CamelCaps. + $varName = ltrim($varName, '_'); + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Member variable "%s" is not in valid camel caps format'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'MemberVarNotCamelCaps', $data); + } else if (preg_match('|\d|', $varName) === 1) { + $warning = 'Member variable "%s" contains numbers but this is discouraged'; + $data = [$varName]; + $phpcsFile->addWarning($warning, $stackPtr, 'MemberVarContainsNumbers', $data); + } + + }//end processMemberVar() + + + /** + * Processes the variable found within a double quoted string. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the double quoted + * string. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (preg_match_all('|[^\\\]\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)|', $tokens[$stackPtr]['content'], $matches) !== 0) { + foreach ($matches[1] as $varName) { + // If it's a php reserved var, then its ok. + if (isset($this->phpReservedVars[$varName]) === true) { + continue; + } + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'StringVarNotCamelCaps', $data); + } else if (preg_match('|\d|', $varName) === 1) { + $warning = 'Variable "%s" contains numbers but this is discouraged'; + $data = [$varName]; + $phpcsFile->addWarning($warning, $stackPtr, 'StringVarContainsNumbers', $data); + } + }//end foreach + }//end if + + }//end processVariableInString() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.inc new file mode 100644 index 00000000..c8d0499d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.inc @@ -0,0 +1,6 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.php new file mode 100644 index 00000000..efd3b900 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; +use PHP_CodeSniffer\Config; + +class CodeAnalyzerUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Should this test be skipped for some reason. + * + * @return void + */ + protected function shouldSkipTest() + { + $analyzerPath = Config::getExecutablePath('zend_ca'); + if ($analyzerPath === null) { + return true; + } + + return false; + + }//end shouldSkipTest() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [2 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc new file mode 100644 index 00000000..7e7089dc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc @@ -0,0 +1,12 @@ + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc.fixed new file mode 100644 index 00000000..caf3b38e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc.fixed @@ -0,0 +1,12 @@ + + +

    + +
    diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc new file mode 100644 index 00000000..63df04d5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc @@ -0,0 +1 @@ +add('arg'))?> diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc.fixed new file mode 100644 index 00000000..b4c46219 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc.fixed @@ -0,0 +1 @@ +add('arg')); diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc new file mode 100644 index 00000000..539365da --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc @@ -0,0 +1 @@ +add('arg')) /* comment */ ?> diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc.fixed new file mode 100644 index 00000000..4cc31a51 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc.fixed @@ -0,0 +1 @@ +add('arg')); /* comment */ diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc new file mode 100644 index 00000000..09e48440 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc @@ -0,0 +1 @@ +add('arg')); } ?> diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc.fixed new file mode 100644 index 00000000..9ff112a4 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc.fixed @@ -0,0 +1 @@ +add('arg')); } diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc new file mode 100644 index 00000000..48de7e03 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc @@ -0,0 +1,3 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc.fixed new file mode 100644 index 00000000..796727a8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc.fixed @@ -0,0 +1,3 @@ + diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.7.inc.fixed b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.7.inc.fixed new file mode 100644 index 00000000..dc84e23e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.7.inc.fixed @@ -0,0 +1 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClosingTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ClosingTagUnitTest.1.inc': + return [11 => 1]; + + case 'ClosingTagUnitTest.3.inc': + case 'ClosingTagUnitTest.4.inc': + case 'ClosingTagUnitTest.5.inc': + case 'ClosingTagUnitTest.7.inc': + return [1 => 1]; + + case 'ClosingTagUnitTest.6.inc': + return [3 => 1]; + + default: + return []; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.inc b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.inc new file mode 100644 index 00000000..3325e115 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.inc @@ -0,0 +1,131 @@ +varName; +echo $this->var_name; +echo $this->varname; +echo $this->_varName; +echo $this->varName2; +echo $object->varName; +echo $object->var_name; +echo $object->varName2; +echo $object_name->varname; +echo $object_name->_varName; +echo $object_name->varName2; + +echo $this->myFunction($one, $two); +echo $object->myFunction($one_two, $var2); + +$error = "format is \$GLOBALS['$varName']"; +$error = "format is \$GLOBALS['$varName2']"; + +echo $_SESSION['var_name']; +echo $_FILES['var_name']; +echo $_ENV['var_name']; +echo $_COOKIE['var_name']; +echo $_COOKIE['var_name2']; + +$XML = 'hello'; +$myXML = 'hello'; +$XMLParser = 'hello'; +$xmlParser = 'hello'; +$xmlParser2 = 'hello'; + +echo "{$_SERVER['HOSTNAME']} $var_name"; + +$someObject->{$name}; +$someObject->my_function($var_name); + +var_dump($http_response_header); +var_dump($HTTP_RAW_POST_DATA); +var_dump($php_errormsg); + +interface Base +{ + protected $anonymous; + + public function __construct(); +} + +$anonClass = new class() { + public function foo($foo, $_foo, $foo_bar) { + $bar = 1; + $_bar = 2; + $bar_foo = 3; + } +}; + +echo $obj?->varName; +echo $obj?->var_name; +echo $obj?->varName; + +enum SomeEnum +{ + public function foo($foo, $_foo, $foo_bar) { + $bar = 1; + $_bar = 2; + $bar_foo = 3; + } +} diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.php b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.php new file mode 100644 index 00000000..e57c7356 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.php @@ -0,0 +1,96 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidVariableNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 11 => 1, + 13 => 1, + 17 => 1, + 19 => 1, + 23 => 1, + 25 => 1, + 29 => 1, + 31 => 1, + 36 => 1, + 38 => 1, + 42 => 1, + 44 => 1, + 48 => 1, + 50 => 1, + 61 => 1, + 67 => 1, + 72 => 1, + 74 => 1, + 75 => 1, + 76 => 1, + 79 => 1, + 96 => 1, + 99 => 1, + 113 => 1, + 116 => 1, + 121 => 1, + 126 => 1, + 129 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 6 => 1, + 14 => 1, + 20 => 1, + 26 => 1, + 32 => 1, + 39 => 1, + 45 => 1, + 51 => 1, + 64 => 1, + 70 => 1, + 73 => 1, + 76 => 1, + 79 => 1, + 82 => 1, + 94 => 1, + 107 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Standards/Zend/ruleset.xml b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/ruleset.xml new file mode 100644 index 00000000..d10b1039 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Standards/Zend/ruleset.xml @@ -0,0 +1,32 @@ + + + A coding standard based on an early Zend Framework coding standard. Note that this standard is out of date. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/src/Tokenizers/CSS.php b/vendor/squizlabs/php_codesniffer/src/Tokenizers/CSS.php new file mode 100644 index 00000000..b7c2018b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Tokenizers/CSS.php @@ -0,0 +1,537 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\TokenizerException; +use PHP_CodeSniffer\Util; + +class CSS extends PHP +{ + + + /** + * Initialise the tokenizer. + * + * Pre-checks the content to see if it looks minified. + * + * @param string $content The content to tokenize, + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * @param string $eolChar The EOL char used in the content. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\TokenizerException If the file appears to be minified. + */ + public function __construct($content, Config $config, $eolChar='\n') + { + if ($this->isMinifiedContent($content, $eolChar) === true) { + throw new TokenizerException('File appears to be minified and cannot be processed'); + } + + parent::__construct($content, $config, $eolChar); + + }//end __construct() + + + /** + * Creates an array of tokens when given some CSS code. + * + * Uses the PHP tokenizer to do all the tricky work + * + * @param string $string The string to tokenize. + * + * @return array + */ + public function tokenize($string) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START CSS TOKENIZING 1ST PASS ***".PHP_EOL; + } + + // If the content doesn't have an EOL char on the end, add one so + // the open and close tags we add are parsed correctly. + $eolAdded = false; + if (substr($string, (strlen($this->eolChar) * -1)) !== $this->eolChar) { + $string .= $this->eolChar; + $eolAdded = true; + } + + $string = str_replace('', '^PHPCS_CSS_T_CLOSE_TAG^', $string); + $tokens = parent::tokenize(''); + + $finalTokens = []; + $finalTokens[0] = [ + 'code' => T_OPEN_TAG, + 'type' => 'T_OPEN_TAG', + 'content' => '', + ]; + + $newStackPtr = 1; + $numTokens = count($tokens); + $multiLineComment = false; + for ($stackPtr = 1; $stackPtr < $numTokens; $stackPtr++) { + $token = $tokens[$stackPtr]; + + // CSS files don't have lists, breaks etc, so convert these to + // standard strings early so they can be converted into T_STYLE + // tokens and joined with other strings if needed. + if ($token['code'] === T_BREAK + || $token['code'] === T_LIST + || $token['code'] === T_DEFAULT + || $token['code'] === T_SWITCH + || $token['code'] === T_FOR + || $token['code'] === T_FOREACH + || $token['code'] === T_WHILE + || $token['code'] === T_DEC + || $token['code'] === T_NEW + ) { + $token['type'] = 'T_STRING'; + $token['code'] = T_STRING; + } + + $token['content'] = str_replace('^PHPCS_CSS_T_OPEN_TAG^', '', $token['content']); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $token['type']; + $content = Util\Common::prepareForOutput($token['content']); + echo "\tProcess token $stackPtr: $type => $content".PHP_EOL; + } + + if ($token['code'] === T_BITWISE_XOR + && $tokens[($stackPtr + 1)]['content'] === 'PHPCS_CSS_T_OPEN_TAG' + ) { + $content = ''; + $stackPtr += 2; + break; + } else { + $content .= $tokens[$stackPtr]['content']; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> Found embedded PHP code: "; + $cleanContent = Util\Common::prepareForOutput($content); + echo $cleanContent.PHP_EOL; + } + + $finalTokens[$newStackPtr] = [ + 'type' => 'T_EMBEDDED_PHP', + 'code' => T_EMBEDDED_PHP, + 'content' => $content, + ]; + + $newStackPtr++; + continue; + }//end if + + if ($token['code'] === T_GOTO_LABEL) { + // Convert these back to T_STRING followed by T_COLON so we can + // more easily process style definitions. + $finalTokens[$newStackPtr] = [ + 'type' => 'T_STRING', + 'code' => T_STRING, + 'content' => substr($token['content'], 0, -1), + ]; + $newStackPtr++; + $finalTokens[$newStackPtr] = [ + 'type' => 'T_COLON', + 'code' => T_COLON, + 'content' => ':', + ]; + $newStackPtr++; + continue; + } + + if ($token['code'] === T_FUNCTION) { + // There are no functions in CSS, so convert this to a string. + $finalTokens[$newStackPtr] = [ + 'type' => 'T_STRING', + 'code' => T_STRING, + 'content' => $token['content'], + ]; + + $newStackPtr++; + continue; + } + + if ($token['code'] === T_COMMENT + && substr($token['content'], 0, 2) === '/*' + ) { + // Multi-line comment. Record it so we can ignore other + // comment tags until we get out of this one. + $multiLineComment = true; + } + + if ($token['code'] === T_COMMENT + && $multiLineComment === false + && (substr($token['content'], 0, 2) === '//' + || $token['content'][0] === '#') + ) { + $content = ltrim($token['content'], '#/'); + + // Guard against PHP7+ syntax errors by stripping + // leading zeros so the content doesn't look like an invalid int. + $leadingZero = false; + if ($content[0] === '0') { + $content = '1'.$content; + $leadingZero = true; + } + + $commentTokens = parent::tokenize(''); + + // The first and last tokens are the open/close tags. + array_shift($commentTokens); + array_pop($commentTokens); + + if ($leadingZero === true) { + $commentTokens[0]['content'] = substr($commentTokens[0]['content'], 1); + $content = substr($content, 1); + } + + if ($token['content'][0] === '#') { + // The # character is not a comment in CSS files, so + // determine what it means in this context. + $firstContent = $commentTokens[0]['content']; + + // If the first content is just a number, it is probably a + // colour like 8FB7DB, which PHP splits into 8 and FB7DB. + if (($commentTokens[0]['code'] === T_LNUMBER + || $commentTokens[0]['code'] === T_DNUMBER) + && $commentTokens[1]['code'] === T_STRING + ) { + $firstContent .= $commentTokens[1]['content']; + array_shift($commentTokens); + } + + // If the first content looks like a colour and not a class + // definition, join the tokens together. + if (preg_match('/^[ABCDEF0-9]+$/i', $firstContent) === 1 + && $commentTokens[1]['content'] !== '-' + ) { + array_shift($commentTokens); + // Work out what we trimmed off above and remember to re-add it. + $trimmed = substr($token['content'], 0, (strlen($token['content']) - strlen($content))); + $finalTokens[$newStackPtr] = [ + 'type' => 'T_COLOUR', + 'code' => T_COLOUR, + 'content' => $trimmed.$firstContent, + ]; + } else { + $finalTokens[$newStackPtr] = [ + 'type' => 'T_HASH', + 'code' => T_HASH, + 'content' => '#', + ]; + } + } else { + $finalTokens[$newStackPtr] = [ + 'type' => 'T_STRING', + 'code' => T_STRING, + 'content' => '//', + ]; + }//end if + + $newStackPtr++; + + array_splice($tokens, $stackPtr, 1, $commentTokens); + $numTokens = count($tokens); + $stackPtr--; + continue; + }//end if + + if ($token['code'] === T_COMMENT + && substr($token['content'], -2) === '*/' + ) { + // Multi-line comment is done. + $multiLineComment = false; + } + + $finalTokens[$newStackPtr] = $token; + $newStackPtr++; + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END CSS TOKENIZING 1ST PASS ***".PHP_EOL; + echo "\t*** START CSS TOKENIZING 2ND PASS ***".PHP_EOL; + } + + // A flag to indicate if we are inside a style definition, + // which is defined using curly braces. + $inStyleDef = false; + + // A flag to indicate if an At-rule like "@media" is used, which will result + // in nested curly brackets. + $asperandStart = false; + + $numTokens = count($finalTokens); + for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) { + $token = $finalTokens[$stackPtr]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $token['type']; + $content = Util\Common::prepareForOutput($token['content']); + echo "\tProcess token $stackPtr: $type => $content".PHP_EOL; + } + + switch ($token['code']) { + case T_OPEN_CURLY_BRACKET: + // Opening curly brackets for an At-rule do not start a style + // definition. We also reset the asperand flag here because the next + // opening curly bracket could be indeed the start of a style + // definition. + if ($asperandStart === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($inStyleDef === true) { + echo "\t\t* style definition closed *".PHP_EOL; + } + + if ($asperandStart === true) { + echo "\t\t* at-rule definition closed *".PHP_EOL; + } + } + + $inStyleDef = false; + $asperandStart = false; + } else { + $inStyleDef = true; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* style definition opened *".PHP_EOL; + } + } + break; + case T_CLOSE_CURLY_BRACKET: + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($inStyleDef === true) { + echo "\t\t* style definition closed *".PHP_EOL; + } + + if ($asperandStart === true) { + echo "\t\t* at-rule definition closed *".PHP_EOL; + } + } + + $inStyleDef = false; + $asperandStart = false; + break; + case T_MINUS: + // Minus signs are often used instead of spaces inside + // class names, IDs and styles. + if ($finalTokens[($stackPtr + 1)]['code'] === T_STRING) { + if ($finalTokens[($stackPtr - 1)]['code'] === T_STRING) { + $newContent = $finalTokens[($stackPtr - 1)]['content'].'-'.$finalTokens[($stackPtr + 1)]['content']; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is a string joiner; ignoring this and previous token".PHP_EOL; + $old = Util\Common::prepareForOutput($finalTokens[($stackPtr + 1)]['content']); + $new = Util\Common::prepareForOutput($newContent); + echo "\t\t=> token ".($stackPtr + 1)." content changed from \"$old\" to \"$new\"".PHP_EOL; + } + + $finalTokens[($stackPtr + 1)]['content'] = $newContent; + unset($finalTokens[$stackPtr]); + unset($finalTokens[($stackPtr - 1)]); + } else { + $newContent = '-'.$finalTokens[($stackPtr + 1)]['content']; + + $finalTokens[($stackPtr + 1)]['content'] = $newContent; + unset($finalTokens[$stackPtr]); + } + } else if ($finalTokens[($stackPtr + 1)]['code'] === T_LNUMBER) { + // They can also be used to provide negative numbers. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is part of a negative number; adding content to next token and ignoring *".PHP_EOL; + $content = Util\Common::prepareForOutput($finalTokens[($stackPtr + 1)]['content']); + echo "\t\t=> token ".($stackPtr + 1)." content changed from \"$content\" to \"-$content\"".PHP_EOL; + } + + $finalTokens[($stackPtr + 1)]['content'] = '-'.$finalTokens[($stackPtr + 1)]['content']; + unset($finalTokens[$stackPtr]); + }//end if + break; + case T_COLON: + // Only interested in colons that are defining styles. + if ($inStyleDef === false) { + break; + } + + for ($x = ($stackPtr - 1); $x >= 0; $x--) { + if (isset(Util\Tokens::$emptyTokens[$finalTokens[$x]['code']]) === false) { + break; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $finalTokens[$x]['type']; + echo "\t\t=> token $x changed from $type to T_STYLE".PHP_EOL; + } + + $finalTokens[$x]['type'] = 'T_STYLE'; + $finalTokens[$x]['code'] = T_STYLE; + break; + case T_STRING: + if (strtolower($token['content']) === 'url') { + // Find the next content. + for ($x = ($stackPtr + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$finalTokens[$x]['code']]) === false) { + break; + } + } + + // Needs to be in the format "url(" for it to be a URL. + if ($finalTokens[$x]['code'] !== T_OPEN_PARENTHESIS) { + continue 2; + } + + // Make sure the content isn't empty. + for ($y = ($x + 1); $y < $numTokens; $y++) { + if (isset(Util\Tokens::$emptyTokens[$finalTokens[$y]['code']]) === false) { + break; + } + } + + if ($finalTokens[$y]['code'] === T_CLOSE_PARENTHESIS) { + continue 2; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + for ($i = ($stackPtr + 1); $i <= $y; $i++) { + $type = $finalTokens[$i]['type']; + $content = Util\Common::prepareForOutput($finalTokens[$i]['content']); + echo "\tProcess token $i: $type => $content".PHP_EOL; + } + + echo "\t\t* token starts a URL *".PHP_EOL; + } + + // Join all the content together inside the url() statement. + $newContent = ''; + for ($i = ($x + 2); $i < $numTokens; $i++) { + if ($finalTokens[$i]['code'] === T_CLOSE_PARENTHESIS) { + break; + } + + $newContent .= $finalTokens[$i]['content']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($finalTokens[$i]['content']); + echo "\t\t=> token $i added to URL string and ignored: $content".PHP_EOL; + } + + unset($finalTokens[$i]); + } + + $stackPtr = $i; + + // If the content inside the "url()" is in double quotes + // there will only be one token and so we don't have to do + // anything except change its type. If it is not empty, + // we need to do some token merging. + $finalTokens[($x + 1)]['type'] = 'T_URL'; + $finalTokens[($x + 1)]['code'] = T_URL; + + if ($newContent !== '') { + $finalTokens[($x + 1)]['content'] .= $newContent; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($finalTokens[($x + 1)]['content']); + echo "\t\t=> token content changed to: $content".PHP_EOL; + } + } + } else if ($finalTokens[$stackPtr]['content'][0] === '-' + && $finalTokens[($stackPtr + 1)]['code'] === T_STRING + ) { + if (isset($finalTokens[($stackPtr - 1)]) === true + && $finalTokens[($stackPtr - 1)]['code'] === T_STRING + ) { + $newContent = $finalTokens[($stackPtr - 1)]['content'].$finalTokens[$stackPtr]['content'].$finalTokens[($stackPtr + 1)]['content']; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is a string joiner; ignoring this and previous token".PHP_EOL; + $old = Util\Common::prepareForOutput($finalTokens[($stackPtr + 1)]['content']); + $new = Util\Common::prepareForOutput($newContent); + echo "\t\t=> token ".($stackPtr + 1)." content changed from \"$old\" to \"$new\"".PHP_EOL; + } + + $finalTokens[($stackPtr + 1)]['content'] = $newContent; + unset($finalTokens[$stackPtr]); + unset($finalTokens[($stackPtr - 1)]); + } else { + $newContent = $finalTokens[$stackPtr]['content'].$finalTokens[($stackPtr + 1)]['content']; + + $finalTokens[($stackPtr + 1)]['content'] = $newContent; + unset($finalTokens[$stackPtr]); + } + }//end if + break; + case T_ASPERAND: + $asperandStart = true; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* at-rule definition opened *".PHP_EOL; + } + break; + default: + // Nothing special to be done with this token. + break; + }//end switch + }//end for + + // Reset the array keys to avoid gaps. + $finalTokens = array_values($finalTokens); + $numTokens = count($finalTokens); + + // Blank out the content of the end tag. + $finalTokens[($numTokens - 1)]['content'] = ''; + + if ($eolAdded === true) { + // Strip off the extra EOL char we added for tokenizing. + $finalTokens[($numTokens - 2)]['content'] = substr( + $finalTokens[($numTokens - 2)]['content'], + 0, + (strlen($this->eolChar) * -1) + ); + + if ($finalTokens[($numTokens - 2)]['content'] === '') { + unset($finalTokens[($numTokens - 2)]); + $finalTokens = array_values($finalTokens); + $numTokens = count($finalTokens); + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END CSS TOKENIZING 2ND PASS ***".PHP_EOL; + } + + return $finalTokens; + + }//end tokenize() + + + /** + * Performs additional processing after main tokenizing. + * + * @return void + */ + public function processAdditional() + { + /* + We override this method because we don't want the PHP version to + run during CSS processing because it is wasted processing time. + */ + + }//end processAdditional() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Tokenizers/Comment.php b/vendor/squizlabs/php_codesniffer/src/Tokenizers/Comment.php new file mode 100644 index 00000000..beba53c2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Tokenizers/Comment.php @@ -0,0 +1,277 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Util; + +class Comment +{ + + + /** + * Creates an array of tokens when given some PHP code. + * + * Starts by using token_get_all() but does a lot of extra processing + * to insert information about the context of the token. + * + * @param string $string The string to tokenize. + * @param string $eolChar The EOL character to use for splitting strings. + * @param int $stackPtr The position of the first token in the file. + * + * @return array + */ + public function tokenizeString($string, $eolChar, $stackPtr) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t*** START COMMENT TOKENIZING ***".PHP_EOL; + } + + $tokens = []; + $numChars = strlen($string); + + /* + Doc block comments start with /*, but typically contain an + extra star when they are used for function and class comments. + */ + + $char = ($numChars - strlen(ltrim($string, '/*'))); + $openTag = substr($string, 0, $char); + $string = ltrim($string, '/*'); + + $tokens[$stackPtr] = [ + 'content' => $openTag, + 'code' => T_DOC_COMMENT_OPEN_TAG, + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'comment_tags' => [], + ]; + + $openPtr = $stackPtr; + $stackPtr++; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($openTag); + echo "\t\tCreate comment token: T_DOC_COMMENT_OPEN_TAG => $content".PHP_EOL; + } + + /* + Strip off the close tag so it doesn't interfere with any + of our comment line processing. The token will be added to the + stack just before we return it. + */ + + $closeTag = [ + 'content' => substr($string, strlen(rtrim($string, '/*'))), + 'code' => T_DOC_COMMENT_CLOSE_TAG, + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'comment_opener' => $openPtr, + ]; + + if ($closeTag['content'] === false) { + $closeTag['content'] = ''; + } + + $string = rtrim($string, '/*'); + + /* + Process each line of the comment. + */ + + $lines = explode($eolChar, $string); + $numLines = count($lines); + foreach ($lines as $lineNum => $string) { + if ($lineNum !== ($numLines - 1)) { + $string .= $eolChar; + } + + $char = 0; + $numChars = strlen($string); + + // We've started a new line, so process the indent. + $space = $this->collectWhitespace($string, $char, $numChars); + if ($space !== null) { + $tokens[$stackPtr] = $space; + $stackPtr++; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($space['content']); + echo "\t\tCreate comment token: T_DOC_COMMENT_WHITESPACE => $content".PHP_EOL; + } + + $char += strlen($space['content']); + if ($char === $numChars) { + break; + } + } + + if ($string === '') { + continue; + } + + if ($lineNum > 0 && $string[$char] === '*') { + // This is a function or class doc block line. + $char++; + $tokens[$stackPtr] = [ + 'content' => '*', + 'code' => T_DOC_COMMENT_STAR, + 'type' => 'T_DOC_COMMENT_STAR', + ]; + + $stackPtr++; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\tCreate comment token: T_DOC_COMMENT_STAR => *".PHP_EOL; + } + } + + // Now we are ready to process the actual content of the line. + $lineTokens = $this->processLine($string, $eolChar, $char, $numChars); + foreach ($lineTokens as $lineToken) { + $tokens[$stackPtr] = $lineToken; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($lineToken['content']); + $type = $lineToken['type']; + echo "\t\tCreate comment token: $type => $content".PHP_EOL; + } + + if ($lineToken['code'] === T_DOC_COMMENT_TAG) { + $tokens[$openPtr]['comment_tags'][] = $stackPtr; + } + + $stackPtr++; + } + }//end foreach + + $tokens[$stackPtr] = $closeTag; + $tokens[$openPtr]['comment_closer'] = $stackPtr; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($closeTag['content']); + echo "\t\tCreate comment token: T_DOC_COMMENT_CLOSE_TAG => $content".PHP_EOL; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t*** END COMMENT TOKENIZING ***".PHP_EOL; + } + + return $tokens; + + }//end tokenizeString() + + + /** + * Process a single line of a comment. + * + * @param string $string The comment string being tokenized. + * @param string $eolChar The EOL character to use for splitting strings. + * @param int $start The position in the string to start processing. + * @param int $end The position in the string to end processing. + * + * @return array + */ + private function processLine($string, $eolChar, $start, $end) + { + $tokens = []; + + // Collect content padding. + $space = $this->collectWhitespace($string, $start, $end); + if ($space !== null) { + $tokens[] = $space; + $start += strlen($space['content']); + } + + if (isset($string[$start]) === false) { + return $tokens; + } + + if ($string[$start] === '@') { + // The content up until the first whitespace is the tag name. + $matches = []; + preg_match('/@[^\s]+/', $string, $matches, 0, $start); + if (isset($matches[0]) === true + && substr(strtolower($matches[0]), 0, 7) !== '@phpcs:' + ) { + $tagName = $matches[0]; + $start += strlen($tagName); + $tokens[] = [ + 'content' => $tagName, + 'code' => T_DOC_COMMENT_TAG, + 'type' => 'T_DOC_COMMENT_TAG', + ]; + + // Then there will be some whitespace. + $space = $this->collectWhitespace($string, $start, $end); + if ($space !== null) { + $tokens[] = $space; + $start += strlen($space['content']); + } + } + }//end if + + // Process the rest of the line. + $eol = strpos($string, $eolChar, $start); + if ($eol === false) { + $eol = $end; + } + + if ($eol > $start) { + $tokens[] = [ + 'content' => substr($string, $start, ($eol - $start)), + 'code' => T_DOC_COMMENT_STRING, + 'type' => 'T_DOC_COMMENT_STRING', + ]; + } + + if ($eol !== $end) { + $tokens[] = [ + 'content' => substr($string, $eol, strlen($eolChar)), + 'code' => T_DOC_COMMENT_WHITESPACE, + 'type' => 'T_DOC_COMMENT_WHITESPACE', + ]; + } + + return $tokens; + + }//end processLine() + + + /** + * Collect consecutive whitespace into a single token. + * + * @param string $string The comment string being tokenized. + * @param int $start The position in the string to start processing. + * @param int $end The position in the string to end processing. + * + * @return array|null + */ + private function collectWhitespace($string, $start, $end) + { + $space = ''; + for ($start; $start < $end; $start++) { + if ($string[$start] !== ' ' && $string[$start] !== "\t") { + break; + } + + $space .= $string[$start]; + } + + if ($space === '') { + return null; + } + + $token = [ + 'content' => $space, + 'code' => T_DOC_COMMENT_WHITESPACE, + 'type' => 'T_DOC_COMMENT_WHITESPACE', + ]; + + return $token; + + }//end collectWhitespace() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Tokenizers/JS.php b/vendor/squizlabs/php_codesniffer/src/Tokenizers/JS.php new file mode 100644 index 00000000..ee2f8429 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Tokenizers/JS.php @@ -0,0 +1,1256 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\TokenizerException; +use PHP_CodeSniffer\Util; + +class JS extends Tokenizer +{ + + /** + * A list of tokens that are allowed to open a scope. + * + * This array also contains information about what kind of token the scope + * opener uses to open and close the scope, if the token strictly requires + * an opener, if the token can share a scope closer, and who it can be shared + * with. An example of a token that shares a scope closer is a CASE scope. + * + * @var array + */ + public $scopeOpeners = [ + T_IF => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_TRY => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CATCH => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_ELSE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_FOR => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_CLASS => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_FUNCTION => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_WHILE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_DO => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_SWITCH => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CASE => [ + 'start' => [T_COLON => T_COLON], + 'end' => [ + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + ], + 'strict' => true, + 'shared' => true, + 'with' => [ + T_DEFAULT => T_DEFAULT, + T_CASE => T_CASE, + T_SWITCH => T_SWITCH, + ], + ], + T_DEFAULT => [ + 'start' => [T_COLON => T_COLON], + 'end' => [ + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + ], + 'strict' => true, + 'shared' => true, + 'with' => [ + T_CASE => T_CASE, + T_SWITCH => T_SWITCH, + ], + ], + ]; + + /** + * A list of tokens that end the scope. + * + * This array is just a unique collection of the end tokens + * from the _scopeOpeners array. The data is duplicated here to + * save time during parsing of the file. + * + * @var array + */ + public $endScopeTokens = [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_BREAK => T_BREAK, + ]; + + /** + * A list of special JS tokens and their types. + * + * @var array + */ + protected $tokenValues = [ + 'class' => 'T_CLASS', + 'function' => 'T_FUNCTION', + 'prototype' => 'T_PROTOTYPE', + 'try' => 'T_TRY', + 'catch' => 'T_CATCH', + 'return' => 'T_RETURN', + 'throw' => 'T_THROW', + 'break' => 'T_BREAK', + 'switch' => 'T_SWITCH', + 'continue' => 'T_CONTINUE', + 'if' => 'T_IF', + 'else' => 'T_ELSE', + 'do' => 'T_DO', + 'while' => 'T_WHILE', + 'for' => 'T_FOR', + 'var' => 'T_VAR', + 'case' => 'T_CASE', + 'default' => 'T_DEFAULT', + 'true' => 'T_TRUE', + 'false' => 'T_FALSE', + 'null' => 'T_NULL', + 'this' => 'T_THIS', + 'typeof' => 'T_TYPEOF', + '(' => 'T_OPEN_PARENTHESIS', + ')' => 'T_CLOSE_PARENTHESIS', + '{' => 'T_OPEN_CURLY_BRACKET', + '}' => 'T_CLOSE_CURLY_BRACKET', + '[' => 'T_OPEN_SQUARE_BRACKET', + ']' => 'T_CLOSE_SQUARE_BRACKET', + '?' => 'T_INLINE_THEN', + '.' => 'T_OBJECT_OPERATOR', + '+' => 'T_PLUS', + '-' => 'T_MINUS', + '*' => 'T_MULTIPLY', + '%' => 'T_MODULUS', + '/' => 'T_DIVIDE', + '^' => 'T_LOGICAL_XOR', + ',' => 'T_COMMA', + ';' => 'T_SEMICOLON', + ':' => 'T_COLON', + '<' => 'T_LESS_THAN', + '>' => 'T_GREATER_THAN', + '<<' => 'T_SL', + '>>' => 'T_SR', + '>>>' => 'T_ZSR', + '<<=' => 'T_SL_EQUAL', + '>>=' => 'T_SR_EQUAL', + '>>>=' => 'T_ZSR_EQUAL', + '<=' => 'T_IS_SMALLER_OR_EQUAL', + '>=' => 'T_IS_GREATER_OR_EQUAL', + '=>' => 'T_DOUBLE_ARROW', + '!' => 'T_BOOLEAN_NOT', + '||' => 'T_BOOLEAN_OR', + '&&' => 'T_BOOLEAN_AND', + '|' => 'T_BITWISE_OR', + '&' => 'T_BITWISE_AND', + '!=' => 'T_IS_NOT_EQUAL', + '!==' => 'T_IS_NOT_IDENTICAL', + '=' => 'T_EQUAL', + '==' => 'T_IS_EQUAL', + '===' => 'T_IS_IDENTICAL', + '-=' => 'T_MINUS_EQUAL', + '+=' => 'T_PLUS_EQUAL', + '*=' => 'T_MUL_EQUAL', + '/=' => 'T_DIV_EQUAL', + '%=' => 'T_MOD_EQUAL', + '++' => 'T_INC', + '--' => 'T_DEC', + '//' => 'T_COMMENT', + '/*' => 'T_COMMENT', + '/**' => 'T_DOC_COMMENT', + '*/' => 'T_COMMENT', + ]; + + /** + * A list string delimiters. + * + * @var array + */ + protected $stringTokens = [ + '\'' => '\'', + '"' => '"', + ]; + + /** + * A list tokens that start and end comments. + * + * @var array + */ + protected $commentTokens = [ + '//' => null, + '/*' => '*/', + '/**' => '*/', + ]; + + + /** + * Initialise the tokenizer. + * + * Pre-checks the content to see if it looks minified. + * + * @param string $content The content to tokenize, + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * @param string $eolChar The EOL char used in the content. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\TokenizerException If the file appears to be minified. + */ + public function __construct($content, Config $config, $eolChar='\n') + { + if ($this->isMinifiedContent($content, $eolChar) === true) { + throw new TokenizerException('File appears to be minified and cannot be processed'); + } + + parent::__construct($content, $config, $eolChar); + + }//end __construct() + + + /** + * Creates an array of tokens when given some JS code. + * + * @param string $string The string to tokenize. + * + * @return array + */ + public function tokenize($string) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START JS TOKENIZING ***".PHP_EOL; + } + + $maxTokenLength = 0; + foreach ($this->tokenValues as $token => $values) { + if (strlen($token) > $maxTokenLength) { + $maxTokenLength = strlen($token); + } + } + + $tokens = []; + $inString = ''; + $stringChar = null; + $inComment = ''; + $buffer = ''; + $preStringBuffer = ''; + $cleanBuffer = false; + + $commentTokenizer = new Comment(); + + $tokens[] = [ + 'code' => T_OPEN_TAG, + 'type' => 'T_OPEN_TAG', + 'content' => '', + ]; + + // Convert newlines to single characters for ease of + // processing. We will change them back later. + $string = str_replace($this->eolChar, "\n", $string); + + $chars = str_split($string); + $numChars = count($chars); + for ($i = 0; $i < $numChars; $i++) { + $char = $chars[$i]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($char); + $bufferContent = Util\Common::prepareForOutput($buffer); + + if ($inString !== '') { + echo "\t"; + } + + if ($inComment !== '') { + echo "\t"; + } + + echo "\tProcess char $i => $content (buffer: $bufferContent)".PHP_EOL; + }//end if + + if ($inString === '' && $inComment === '' && $buffer !== '') { + // If the buffer only has whitespace and we are about to + // add a character, store the whitespace first. + if (trim($char) !== '' && trim($buffer) === '') { + $tokens[] = [ + 'code' => T_WHITESPACE, + 'type' => 'T_WHITESPACE', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_WHITESPACE ($content)".PHP_EOL; + } + + $buffer = ''; + } + + // If the buffer is not whitespace and we are about to + // add a whitespace character, store the content first. + if ($inString === '' + && $inComment === '' + && trim($char) === '' + && trim($buffer) !== '' + ) { + $tokens[] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_STRING ($content)".PHP_EOL; + } + + $buffer = ''; + } + }//end if + + // Process strings. + if ($inComment === '' && isset($this->stringTokens[$char]) === true) { + if ($inString === $char) { + // This could be the end of the string, but make sure it + // is not escaped first. + $escapes = 0; + for ($x = ($i - 1); $x >= 0; $x--) { + if ($chars[$x] !== '\\') { + break; + } + + $escapes++; + } + + if ($escapes === 0 || ($escapes % 2) === 0) { + // There is an even number escape chars, + // so this is not escaped, it is the end of the string. + $tokens[] = [ + 'code' => T_CONSTANT_ENCAPSED_STRING, + 'type' => 'T_CONSTANT_ENCAPSED_STRING', + 'content' => str_replace("\n", $this->eolChar, $buffer).$char, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* found end of string *".PHP_EOL; + $content = Util\Common::prepareForOutput($buffer.$char); + echo "\t=> Added token T_CONSTANT_ENCAPSED_STRING ($content)".PHP_EOL; + } + + $buffer = ''; + $preStringBuffer = ''; + $inString = ''; + $stringChar = null; + continue; + }//end if + } else if ($inString === '') { + $inString = $char; + $stringChar = $i; + $preStringBuffer = $buffer; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* looking for string closer *".PHP_EOL; + } + }//end if + }//end if + + if ($inString !== '' && $char === "\n") { + // Unless this newline character is escaped, the string did not + // end before the end of the line, which means it probably + // wasn't a string at all (maybe a regex). + if ($chars[($i - 1)] !== '\\') { + $i = $stringChar; + $buffer = $preStringBuffer; + $preStringBuffer = ''; + $inString = ''; + $stringChar = null; + $char = $chars[$i]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* found newline before end of string, bailing *".PHP_EOL; + } + } + } + + $buffer .= $char; + + // We don't look for special tokens inside strings, + // so if we are in a string, we can continue here now + // that the current char is in the buffer. + if ($inString !== '') { + continue; + } + + // Special case for T_DIVIDE which can actually be + // the start of a regular expression. + if ($buffer === $char && $char === '/' && $chars[($i + 1)] !== '*') { + $regex = $this->getRegexToken($i, $string, $chars, $tokens); + if ($regex !== null) { + $tokens[] = [ + 'code' => T_REGULAR_EXPRESSION, + 'type' => 'T_REGULAR_EXPRESSION', + 'content' => $regex['content'], + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($regex['content']); + echo "\t=> Added token T_REGULAR_EXPRESSION ($content)".PHP_EOL; + } + + $i = $regex['end']; + $buffer = ''; + $cleanBuffer = false; + continue; + }//end if + }//end if + + // Check for known tokens, but ignore tokens found that are not at + // the end of a string, like FOR and this.FORmat. + if (isset($this->tokenValues[strtolower($buffer)]) === true + && (preg_match('|[a-zA-z0-9_]|', $char) === 0 + || isset($chars[($i + 1)]) === false + || preg_match('|[a-zA-z0-9_]|', $chars[($i + 1)]) === 0) + ) { + $matchedToken = false; + $lookAheadLength = ($maxTokenLength - strlen($buffer)); + + if ($lookAheadLength > 0) { + // The buffer contains a token type, but we need + // to look ahead at the next chars to see if this is + // actually part of a larger token. For example, + // FOR and FOREACH. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* buffer possibly contains token, looking ahead $lookAheadLength chars *".PHP_EOL; + } + + $charBuffer = $buffer; + for ($x = 1; $x <= $lookAheadLength; $x++) { + if (isset($chars[($i + $x)]) === false) { + break; + } + + $charBuffer .= $chars[($i + $x)]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($charBuffer); + echo "\t\t=> Looking ahead $x chars => $content".PHP_EOL; + } + + if (isset($this->tokenValues[strtolower($charBuffer)]) === true) { + // We've found something larger that matches + // so we can ignore this char. Except for 1 very specific + // case where a comment like /**/ needs to tokenize as + // T_COMMENT and not T_DOC_COMMENT. + $oldType = $this->tokenValues[strtolower($buffer)]; + $newType = $this->tokenValues[strtolower($charBuffer)]; + if ($oldType === 'T_COMMENT' + && $newType === 'T_DOC_COMMENT' + && $chars[($i + $x + 1)] === '/' + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* look ahead ignored T_DOC_COMMENT, continuing *".PHP_EOL; + } + } else { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* look ahead found more specific token ($newType), ignoring $i *".PHP_EOL; + } + + $matchedToken = true; + break; + } + }//end if + }//end for + }//end if + + if ($matchedToken === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1 && $lookAheadLength > 0) { + echo "\t\t* look ahead found nothing *".PHP_EOL; + } + + $value = $this->tokenValues[strtolower($buffer)]; + + if ($value === 'T_FUNCTION' && $buffer !== 'function') { + // The function keyword needs to be all lowercase or else + // it is just a function called "Function". + $value = 'T_STRING'; + } + + $tokens[] = [ + 'code' => constant($value), + 'type' => $value, + 'content' => $buffer, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token $value ($content)".PHP_EOL; + } + + $cleanBuffer = true; + }//end if + } else if (isset($this->tokenValues[strtolower($char)]) === true) { + // No matter what token we end up using, we don't + // need the content in the buffer any more because we have + // found a valid token. + $newContent = substr(str_replace("\n", $this->eolChar, $buffer), 0, -1); + if ($newContent !== '') { + $tokens[] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => $newContent, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput(substr($buffer, 0, -1)); + echo "\t=> Added token T_STRING ($content)".PHP_EOL; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* char is token, looking ahead ".($maxTokenLength - 1).' chars *'.PHP_EOL; + } + + // The char is a token type, but we need to look ahead at the + // next chars to see if this is actually part of a larger token. + // For example, = and ===. + $charBuffer = $char; + $matchedToken = false; + for ($x = 1; $x <= $maxTokenLength; $x++) { + if (isset($chars[($i + $x)]) === false) { + break; + } + + $charBuffer .= $chars[($i + $x)]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($charBuffer); + echo "\t\t=> Looking ahead $x chars => $content".PHP_EOL; + } + + if (isset($this->tokenValues[strtolower($charBuffer)]) === true) { + // We've found something larger that matches + // so we can ignore this char. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokenValues[strtolower($charBuffer)]; + echo "\t\t* look ahead found more specific token ($type), ignoring $i *".PHP_EOL; + } + + $matchedToken = true; + break; + } + }//end for + + if ($matchedToken === false) { + $value = $this->tokenValues[strtolower($char)]; + $tokens[] = [ + 'code' => constant($value), + 'type' => $value, + 'content' => $char, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* look ahead found nothing *".PHP_EOL; + $content = Util\Common::prepareForOutput($char); + echo "\t=> Added token $value ($content)".PHP_EOL; + } + + $cleanBuffer = true; + } else { + $buffer = $char; + }//end if + }//end if + + // Keep track of content inside comments. + if ($inComment === '' + && array_key_exists($buffer, $this->commentTokens) === true + ) { + // This is not really a comment if the content + // looks like \// (i.e., it is escaped). + if (isset($chars[($i - 2)]) === true && $chars[($i - 2)] === '\\') { + $lastToken = array_pop($tokens); + $lastContent = $lastToken['content']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $value = $this->tokenValues[strtolower($lastContent)]; + $content = Util\Common::prepareForOutput($lastContent); + echo "\t=> Removed token $value ($content)".PHP_EOL; + } + + $lastChars = str_split($lastContent); + $lastNumChars = count($lastChars); + for ($x = 0; $x < $lastNumChars; $x++) { + $lastChar = $lastChars[$x]; + $value = $this->tokenValues[strtolower($lastChar)]; + $tokens[] = [ + 'code' => constant($value), + 'type' => $value, + 'content' => $lastChar, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($lastChar); + echo "\t=> Added token $value ($content)".PHP_EOL; + } + } + } else { + // We have started a comment. + $inComment = $buffer; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* looking for end of comment *".PHP_EOL; + } + }//end if + } else if ($inComment !== '') { + if ($this->commentTokens[$inComment] === null) { + // Comment ends at the next newline. + if (strpos($buffer, "\n") !== false) { + $inComment = ''; + } + } else { + if ($this->commentTokens[$inComment] === $buffer) { + $inComment = ''; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($inComment === '') { + echo "\t\t* found end of comment *".PHP_EOL; + } + } + + if ($inComment === '' && $cleanBuffer === false) { + $tokens[] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_STRING ($content)".PHP_EOL; + } + + $buffer = ''; + } + }//end if + + if ($cleanBuffer === true) { + $buffer = ''; + $cleanBuffer = false; + } + }//end for + + if (empty($buffer) === false) { + if ($inString !== '') { + // The string did not end before the end of the file, + // which means there was probably a syntax error somewhere. + $tokens[] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_STRING ($content)".PHP_EOL; + } + } else { + // Buffer contains whitespace from the end of the file. + $tokens[] = [ + 'code' => T_WHITESPACE, + 'type' => 'T_WHITESPACE', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_WHITESPACE ($content)".PHP_EOL; + } + }//end if + }//end if + + $tokens[] = [ + 'code' => T_CLOSE_TAG, + 'type' => 'T_CLOSE_TAG', + 'content' => '', + ]; + + /* + Now that we have done some basic tokenizing, we need to + modify the tokens to join some together and split some apart + so they match what the PHP tokenizer does. + */ + + $finalTokens = []; + $newStackPtr = 0; + $numTokens = count($tokens); + for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) { + $token = $tokens[$stackPtr]; + + /* + Look for comments and join the tokens together. + */ + + if ($token['code'] === T_COMMENT || $token['code'] === T_DOC_COMMENT) { + $newContent = ''; + $tokenContent = $token['content']; + + $endContent = null; + if (isset($this->commentTokens[$tokenContent]) === true) { + $endContent = $this->commentTokens[$tokenContent]; + } + + while ($tokenContent !== $endContent) { + if ($endContent === null + && strpos($tokenContent, $this->eolChar) !== false + ) { + // A null end token means the comment ends at the end of + // the line so we look for newlines and split the token. + $tokens[$stackPtr]['content'] = substr( + $tokenContent, + (strpos($tokenContent, $this->eolChar) + strlen($this->eolChar)) + ); + + $tokenContent = substr( + $tokenContent, + 0, + (strpos($tokenContent, $this->eolChar) + strlen($this->eolChar)) + ); + + // If the substr failed, skip the token as the content + // will now be blank. + if ($tokens[$stackPtr]['content'] !== false + && $tokens[$stackPtr]['content'] !== '' + ) { + $stackPtr--; + } + + break; + }//end if + + $stackPtr++; + $newContent .= $tokenContent; + if (isset($tokens[$stackPtr]) === false) { + break; + } + + $tokenContent = $tokens[$stackPtr]['content']; + }//end while + + if ($token['code'] === T_DOC_COMMENT) { + $commentTokens = $commentTokenizer->tokenizeString($newContent.$tokenContent, $this->eolChar, $newStackPtr); + foreach ($commentTokens as $commentToken) { + $finalTokens[$newStackPtr] = $commentToken; + $newStackPtr++; + } + + continue; + } else { + // Save the new content in the current token so + // the code below can chop it up on newlines. + $token['content'] = $newContent.$tokenContent; + } + }//end if + + /* + If this token has newlines in its content, split each line up + and create a new token for each line. We do this so it's easier + to ascertain where errors occur on a line. + Note that $token[1] is the token's content. + */ + + if (strpos($token['content'], $this->eolChar) !== false) { + $tokenLines = explode($this->eolChar, $token['content']); + $numLines = count($tokenLines); + + for ($i = 0; $i < $numLines; $i++) { + $newToken = ['content' => $tokenLines[$i]]; + if ($i === ($numLines - 1)) { + if ($tokenLines[$i] === '') { + break; + } + } else { + $newToken['content'] .= $this->eolChar; + } + + $newToken['type'] = $token['type']; + $newToken['code'] = $token['code']; + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + } + } else { + $finalTokens[$newStackPtr] = $token; + $newStackPtr++; + }//end if + + // Convert numbers, including decimals. + if ($token['code'] === T_STRING + || $token['code'] === T_OBJECT_OPERATOR + ) { + $newContent = ''; + $oldStackPtr = $stackPtr; + while (preg_match('|^[0-9\.]+$|', $tokens[$stackPtr]['content']) !== 0) { + $newContent .= $tokens[$stackPtr]['content']; + $stackPtr++; + } + + if ($newContent !== '' && $newContent !== '.') { + $finalTokens[($newStackPtr - 1)]['content'] = $newContent; + if (ctype_digit($newContent) === true) { + $finalTokens[($newStackPtr - 1)]['code'] = constant('T_LNUMBER'); + $finalTokens[($newStackPtr - 1)]['type'] = 'T_LNUMBER'; + } else { + $finalTokens[($newStackPtr - 1)]['code'] = constant('T_DNUMBER'); + $finalTokens[($newStackPtr - 1)]['type'] = 'T_DNUMBER'; + } + + $stackPtr--; + continue; + } else { + $stackPtr = $oldStackPtr; + } + }//end if + + // Convert the token after an object operator into a string, in most cases. + if ($token['code'] === T_OBJECT_OPERATOR) { + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (isset(Util\Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + if ($tokens[$i]['code'] !== T_PROTOTYPE + && $tokens[$i]['code'] !== T_LNUMBER + && $tokens[$i]['code'] !== T_DNUMBER + ) { + $tokens[$i]['code'] = T_STRING; + $tokens[$i]['type'] = 'T_STRING'; + } + + break; + } + } + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END TOKENIZING ***".PHP_EOL; + } + + return $finalTokens; + + }//end tokenize() + + + /** + * Tokenizes a regular expression if one is found. + * + * If a regular expression is not found, NULL is returned. + * + * @param string $char The index of the possible regex start character. + * @param string $string The complete content of the string being tokenized. + * @param string $chars An array of characters being tokenized. + * @param string $tokens The current array of tokens found in the string. + * + * @return array|null + */ + public function getRegexToken($char, $string, $chars, $tokens) + { + $beforeTokens = [ + T_EQUAL => true, + T_IS_NOT_EQUAL => true, + T_IS_IDENTICAL => true, + T_IS_NOT_IDENTICAL => true, + T_OPEN_PARENTHESIS => true, + T_OPEN_SQUARE_BRACKET => true, + T_RETURN => true, + T_BOOLEAN_OR => true, + T_BOOLEAN_AND => true, + T_BOOLEAN_NOT => true, + T_BITWISE_OR => true, + T_BITWISE_AND => true, + T_COMMA => true, + T_COLON => true, + T_TYPEOF => true, + T_INLINE_THEN => true, + T_INLINE_ELSE => true, + ]; + + $afterTokens = [ + ',' => true, + ')' => true, + ']' => true, + ';' => true, + ' ' => true, + '.' => true, + ':' => true, + $this->eolChar => true, + ]; + + // Find the last non-whitespace token that was added + // to the tokens array. + $numTokens = count($tokens); + for ($prev = ($numTokens - 1); $prev >= 0; $prev--) { + if (isset(Util\Tokens::$emptyTokens[$tokens[$prev]['code']]) === false) { + break; + } + } + + if (isset($beforeTokens[$tokens[$prev]['code']]) === false) { + return null; + } + + // This is probably a regular expression, so look for the end of it. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* token possibly starts a regular expression *".PHP_EOL; + } + + $numChars = count($chars); + for ($next = ($char + 1); $next < $numChars; $next++) { + if ($chars[$next] === '/') { + // Just make sure this is not escaped first. + if ($chars[($next - 1)] !== '\\') { + // In the simple form: /.../ so we found the end. + break; + } else if ($chars[($next - 2)] === '\\') { + // In the form: /...\\/ so we found the end. + break; + } + } else { + $possibleEolChar = substr($string, $next, strlen($this->eolChar)); + if ($possibleEolChar === $this->eolChar) { + // This is the last token on the line and regular + // expressions need to be defined on a single line, + // so this is not a regular expression. + break; + } + } + } + + if ($chars[$next] !== '/') { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* could not find end of regular expression *".PHP_EOL; + } + + return null; + } + + while (preg_match('|[a-zA-Z]|', $chars[($next + 1)]) !== 0) { + // The token directly after the end of the regex can + // be modifiers like global and case insensitive + // (.e.g, /pattern/gi). + $next++; + } + + $regexEnd = $next; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* found end of regular expression at token $regexEnd *".PHP_EOL; + } + + for ($next += 1; $next < $numChars; $next++) { + if ($chars[$next] !== ' ') { + break; + } else { + $possibleEolChar = substr($string, $next, strlen($this->eolChar)); + if ($possibleEolChar === $this->eolChar) { + // This is the last token on the line. + break; + } + } + } + + if (isset($afterTokens[$chars[$next]]) === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* tokens after regular expression do not look correct *".PHP_EOL; + } + + return null; + } + + // This is a regular expression, so join all the tokens together. + $content = ''; + for ($x = $char; $x <= $regexEnd; $x++) { + $content .= $chars[$x]; + } + + $token = [ + 'start' => $char, + 'end' => $regexEnd, + 'content' => $content, + ]; + + return $token; + + }//end getRegexToken() + + + /** + * Performs additional processing after main tokenizing. + * + * This additional processing looks for properties, closures, labels and objects. + * + * @return void + */ + public function processAdditional() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START ADDITIONAL JS PROCESSING ***".PHP_EOL; + } + + $numTokens = count($this->tokens); + $classStack = []; + + for ($i = 0; $i < $numTokens; $i++) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + $content = Util\Common::prepareForOutput($this->tokens[$i]['content']); + + echo str_repeat("\t", count($classStack)); + echo "\tProcess token $i: $type => $content".PHP_EOL; + } + + // Looking for functions that are actually closures. + if ($this->tokens[$i]['code'] === T_FUNCTION && isset($this->tokens[$i]['scope_opener']) === true) { + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + break; + } + } + + if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) { + $this->tokens[$i]['code'] = T_CLOSURE; + $this->tokens[$i]['type'] = 'T_CLOSURE'; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo str_repeat("\t", count($classStack)); + echo "\t* token $i on line $line changed from T_FUNCTION to T_CLOSURE *".PHP_EOL; + } + + for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) { + if (isset($this->tokens[$x]['conditions'][$i]) === false) { + continue; + } + + $this->tokens[$x]['conditions'][$i] = T_CLOSURE; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo str_repeat("\t", count($classStack)); + echo "\t\t* cleaned $x ($type) *".PHP_EOL; + } + } + }//end if + + continue; + } else if ($this->tokens[$i]['code'] === T_OPEN_CURLY_BRACKET + && isset($this->tokens[$i]['scope_condition']) === false + && isset($this->tokens[$i]['bracket_closer']) === true + ) { + $condition = $this->tokens[$i]['conditions']; + $condition = end($condition); + if ($condition === T_CLASS) { + // Possibly an ES6 method. To be classified as one, the previous + // non-empty tokens need to be a set of parenthesis, and then a string + // (the method name). + for ($parenCloser = ($i - 1); $parenCloser > 0; $parenCloser--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$parenCloser]['code']]) === false) { + break; + } + } + + if ($this->tokens[$parenCloser]['code'] === T_CLOSE_PARENTHESIS) { + $parenOpener = $this->tokens[$parenCloser]['parenthesis_opener']; + for ($name = ($parenOpener - 1); $name > 0; $name--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$name]['code']]) === false) { + break; + } + } + + if ($this->tokens[$name]['code'] === T_STRING) { + // We found a method name. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$name]['line']; + echo str_repeat("\t", count($classStack)); + echo "\t* token $name on line $line changed from T_STRING to T_FUNCTION *".PHP_EOL; + } + + $closer = $this->tokens[$i]['bracket_closer']; + + $this->tokens[$name]['code'] = T_FUNCTION; + $this->tokens[$name]['type'] = 'T_FUNCTION'; + + foreach ([$name, $i, $closer] as $token) { + $this->tokens[$token]['scope_condition'] = $name; + $this->tokens[$token]['scope_opener'] = $i; + $this->tokens[$token]['scope_closer'] = $closer; + $this->tokens[$token]['parenthesis_opener'] = $parenOpener; + $this->tokens[$token]['parenthesis_closer'] = $parenCloser; + $this->tokens[$token]['parenthesis_owner'] = $name; + } + + $this->tokens[$parenOpener]['parenthesis_owner'] = $name; + $this->tokens[$parenCloser]['parenthesis_owner'] = $name; + + for ($x = ($i + 1); $x < $closer; $x++) { + $this->tokens[$x]['conditions'][$name] = T_FUNCTION; + ksort($this->tokens[$x]['conditions'], SORT_NUMERIC); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo str_repeat("\t", count($classStack)); + echo "\t\t* added T_FUNCTION condition to $x ($type) *".PHP_EOL; + } + } + + continue; + }//end if + }//end if + }//end if + + $classStack[] = $i; + + $closer = $this->tokens[$i]['bracket_closer']; + $this->tokens[$i]['code'] = T_OBJECT; + $this->tokens[$i]['type'] = 'T_OBJECT'; + $this->tokens[$closer]['code'] = T_CLOSE_OBJECT; + $this->tokens[$closer]['type'] = 'T_CLOSE_OBJECT'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($classStack)); + echo "\t* token $i converted from T_OPEN_CURLY_BRACKET to T_OBJECT *".PHP_EOL; + echo str_repeat("\t", count($classStack)); + echo "\t* token $closer converted from T_CLOSE_CURLY_BRACKET to T_CLOSE_OBJECT *".PHP_EOL; + } + + for ($x = ($i + 1); $x < $closer; $x++) { + $this->tokens[$x]['conditions'][$i] = T_OBJECT; + ksort($this->tokens[$x]['conditions'], SORT_NUMERIC); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo str_repeat("\t", count($classStack)); + echo "\t\t* added T_OBJECT condition to $x ($type) *".PHP_EOL; + } + } + } else if ($this->tokens[$i]['code'] === T_CLOSE_OBJECT) { + $opener = array_pop($classStack); + } else if ($this->tokens[$i]['code'] === T_COLON) { + // If it is a scope opener, it belongs to a + // DEFAULT or CASE statement. + if (isset($this->tokens[$i]['scope_condition']) === true) { + continue; + } + + // Make sure this is not part of an inline IF statement. + for ($x = ($i - 1); $x >= 0; $x--) { + if ($this->tokens[$x]['code'] === T_INLINE_THEN) { + $this->tokens[$i]['code'] = T_INLINE_ELSE; + $this->tokens[$i]['type'] = 'T_INLINE_ELSE'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($classStack)); + echo "\t* token $i converted from T_COLON to T_INLINE_THEN *".PHP_EOL; + } + + continue(2); + } else if ($this->tokens[$x]['line'] < $this->tokens[$i]['line']) { + break; + } + } + + // The string to the left of the colon is either a property or label. + for ($label = ($i - 1); $label >= 0; $label--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$label]['code']]) === false) { + break; + } + } + + if ($this->tokens[$label]['code'] !== T_STRING + && $this->tokens[$label]['code'] !== T_CONSTANT_ENCAPSED_STRING + ) { + continue; + } + + if (empty($classStack) === false) { + $this->tokens[$label]['code'] = T_PROPERTY; + $this->tokens[$label]['type'] = 'T_PROPERTY'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($classStack)); + echo "\t* token $label converted from T_STRING to T_PROPERTY *".PHP_EOL; + } + } else { + $this->tokens[$label]['code'] = T_LABEL; + $this->tokens[$label]['type'] = 'T_LABEL'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($classStack)); + echo "\t* token $label converted from T_STRING to T_LABEL *".PHP_EOL; + } + }//end if + }//end if + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END ADDITIONAL JS PROCESSING ***".PHP_EOL; + } + + }//end processAdditional() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Tokenizers/PHP.php b/vendor/squizlabs/php_codesniffer/src/Tokenizers/PHP.php new file mode 100644 index 00000000..63fbcc48 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Tokenizers/PHP.php @@ -0,0 +1,3484 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Util; + +class PHP extends Tokenizer +{ + + /** + * A list of tokens that are allowed to open a scope. + * + * This array also contains information about what kind of token the scope + * opener uses to open and close the scope, if the token strictly requires + * an opener, if the token can share a scope closer, and who it can be shared + * with. An example of a token that shares a scope closer is a CASE scope. + * + * @var array + */ + public $scopeOpeners = [ + T_IF => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDIF => T_ENDIF, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + ], + 'strict' => false, + 'shared' => false, + 'with' => [ + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + ], + ], + T_TRY => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CATCH => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_FINALLY => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_ELSE => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDIF => T_ENDIF, + ], + 'strict' => false, + 'shared' => false, + 'with' => [ + T_IF => T_IF, + T_ELSEIF => T_ELSEIF, + ], + ], + T_ELSEIF => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDIF => T_ENDIF, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + ], + 'strict' => false, + 'shared' => false, + 'with' => [ + T_IF => T_IF, + T_ELSE => T_ELSE, + ], + ], + T_FOR => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDFOR => T_ENDFOR, + ], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_FOREACH => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDFOREACH => T_ENDFOREACH, + ], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_INTERFACE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_FUNCTION => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CLASS => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_TRAIT => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_ENUM => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_USE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_DECLARE => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDDECLARE => T_ENDDECLARE, + ], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_NAMESPACE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_WHILE => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDWHILE => T_ENDWHILE, + ], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_DO => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_SWITCH => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDSWITCH => T_ENDSWITCH, + ], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CASE => [ + 'start' => [ + T_COLON => T_COLON, + T_SEMICOLON => T_SEMICOLON, + ], + 'end' => [ + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + T_EXIT => T_EXIT, + ], + 'strict' => true, + 'shared' => true, + 'with' => [ + T_DEFAULT => T_DEFAULT, + T_CASE => T_CASE, + T_SWITCH => T_SWITCH, + ], + ], + T_DEFAULT => [ + 'start' => [ + T_COLON => T_COLON, + T_SEMICOLON => T_SEMICOLON, + ], + 'end' => [ + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + T_EXIT => T_EXIT, + ], + 'strict' => true, + 'shared' => true, + 'with' => [ + T_CASE => T_CASE, + T_SWITCH => T_SWITCH, + ], + ], + T_MATCH => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_START_HEREDOC => [ + 'start' => [T_START_HEREDOC => T_START_HEREDOC], + 'end' => [T_END_HEREDOC => T_END_HEREDOC], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_START_NOWDOC => [ + 'start' => [T_START_NOWDOC => T_START_NOWDOC], + 'end' => [T_END_NOWDOC => T_END_NOWDOC], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + ]; + + /** + * A list of tokens that end the scope. + * + * This array is just a unique collection of the end tokens + * from the scopeOpeners array. The data is duplicated here to + * save time during parsing of the file. + * + * @var array + */ + public $endScopeTokens = [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDIF => T_ENDIF, + T_ENDFOR => T_ENDFOR, + T_ENDFOREACH => T_ENDFOREACH, + T_ENDWHILE => T_ENDWHILE, + T_ENDSWITCH => T_ENDSWITCH, + T_ENDDECLARE => T_ENDDECLARE, + T_BREAK => T_BREAK, + T_END_HEREDOC => T_END_HEREDOC, + T_END_NOWDOC => T_END_NOWDOC, + ]; + + /** + * Known lengths of tokens. + * + * @var array + */ + public $knownLengths = [ + T_ABSTRACT => 8, + T_AND_EQUAL => 2, + T_ARRAY => 5, + T_AS => 2, + T_BOOLEAN_AND => 2, + T_BOOLEAN_OR => 2, + T_BREAK => 5, + T_CALLABLE => 8, + T_CASE => 4, + T_CATCH => 5, + T_CLASS => 5, + T_CLASS_C => 9, + T_CLONE => 5, + T_CONCAT_EQUAL => 2, + T_CONST => 5, + T_CONTINUE => 8, + T_CURLY_OPEN => 2, + T_DEC => 2, + T_DECLARE => 7, + T_DEFAULT => 7, + T_DIR => 7, + T_DIV_EQUAL => 2, + T_DO => 2, + T_DOLLAR_OPEN_CURLY_BRACES => 2, + T_DOUBLE_ARROW => 2, + T_DOUBLE_COLON => 2, + T_ECHO => 4, + T_ELLIPSIS => 3, + T_ELSE => 4, + T_ELSEIF => 6, + T_EMPTY => 5, + T_ENDDECLARE => 10, + T_ENDFOR => 6, + T_ENDFOREACH => 10, + T_ENDIF => 5, + T_ENDSWITCH => 9, + T_ENDWHILE => 8, + T_ENUM => 4, + T_ENUM_CASE => 4, + T_EVAL => 4, + T_EXTENDS => 7, + T_FILE => 8, + T_FINAL => 5, + T_FINALLY => 7, + T_FN => 2, + T_FOR => 3, + T_FOREACH => 7, + T_FUNCTION => 8, + T_FUNC_C => 12, + T_GLOBAL => 6, + T_GOTO => 4, + T_HALT_COMPILER => 15, + T_IF => 2, + T_IMPLEMENTS => 10, + T_INC => 2, + T_INCLUDE => 7, + T_INCLUDE_ONCE => 12, + T_INSTANCEOF => 10, + T_INSTEADOF => 9, + T_INTERFACE => 9, + T_ISSET => 5, + T_IS_EQUAL => 2, + T_IS_GREATER_OR_EQUAL => 2, + T_IS_IDENTICAL => 3, + T_IS_NOT_EQUAL => 2, + T_IS_NOT_IDENTICAL => 3, + T_IS_SMALLER_OR_EQUAL => 2, + T_LINE => 8, + T_LIST => 4, + T_LOGICAL_AND => 3, + T_LOGICAL_OR => 2, + T_LOGICAL_XOR => 3, + T_MATCH => 5, + T_MATCH_ARROW => 2, + T_MATCH_DEFAULT => 7, + T_METHOD_C => 10, + T_MINUS_EQUAL => 2, + T_POW_EQUAL => 3, + T_MOD_EQUAL => 2, + T_MUL_EQUAL => 2, + T_NAMESPACE => 9, + T_NS_C => 13, + T_NS_SEPARATOR => 1, + T_NEW => 3, + T_NULLSAFE_OBJECT_OPERATOR => 3, + T_OBJECT_OPERATOR => 2, + T_OPEN_TAG_WITH_ECHO => 3, + T_OR_EQUAL => 2, + T_PLUS_EQUAL => 2, + T_PRINT => 5, + T_PRIVATE => 7, + T_PUBLIC => 6, + T_PROTECTED => 9, + T_READONLY => 8, + T_REQUIRE => 7, + T_REQUIRE_ONCE => 12, + T_RETURN => 6, + T_STATIC => 6, + T_SWITCH => 6, + T_THROW => 5, + T_TRAIT => 5, + T_TRAIT_C => 9, + T_TRY => 3, + T_UNSET => 5, + T_USE => 3, + T_VAR => 3, + T_WHILE => 5, + T_XOR_EQUAL => 2, + T_YIELD => 5, + T_OPEN_CURLY_BRACKET => 1, + T_CLOSE_CURLY_BRACKET => 1, + T_OPEN_SQUARE_BRACKET => 1, + T_CLOSE_SQUARE_BRACKET => 1, + T_OPEN_PARENTHESIS => 1, + T_CLOSE_PARENTHESIS => 1, + T_COLON => 1, + T_STRING_CONCAT => 1, + T_INLINE_THEN => 1, + T_INLINE_ELSE => 1, + T_NULLABLE => 1, + T_NULL => 4, + T_FALSE => 5, + T_TRUE => 4, + T_SEMICOLON => 1, + T_EQUAL => 1, + T_MULTIPLY => 1, + T_DIVIDE => 1, + T_PLUS => 1, + T_MINUS => 1, + T_MODULUS => 1, + T_POW => 2, + T_SPACESHIP => 3, + T_COALESCE => 2, + T_COALESCE_EQUAL => 3, + T_BITWISE_AND => 1, + T_BITWISE_OR => 1, + T_BITWISE_XOR => 1, + T_SL => 2, + T_SR => 2, + T_SL_EQUAL => 3, + T_SR_EQUAL => 3, + T_GREATER_THAN => 1, + T_LESS_THAN => 1, + T_BOOLEAN_NOT => 1, + T_SELF => 4, + T_PARENT => 6, + T_COMMA => 1, + T_THIS => 4, + T_CLOSURE => 8, + T_BACKTICK => 1, + T_OPEN_SHORT_ARRAY => 1, + T_CLOSE_SHORT_ARRAY => 1, + T_TYPE_UNION => 1, + T_TYPE_INTERSECTION => 1, + ]; + + /** + * Contexts in which keywords should always be tokenized as T_STRING. + * + * @var array + */ + protected $tstringContexts = [ + T_OBJECT_OPERATOR => true, + T_NULLSAFE_OBJECT_OPERATOR => true, + T_FUNCTION => true, + T_CLASS => true, + T_INTERFACE => true, + T_TRAIT => true, + T_ENUM => true, + T_ENUM_CASE => true, + T_EXTENDS => true, + T_IMPLEMENTS => true, + T_ATTRIBUTE => true, + T_NEW => true, + T_CONST => true, + T_NS_SEPARATOR => true, + T_USE => true, + T_NAMESPACE => true, + T_PAAMAYIM_NEKUDOTAYIM => true, + ]; + + /** + * A cache of different token types, resolved into arrays. + * + * @var array + * @see standardiseToken() + */ + private static $resolveTokenCache = []; + + + /** + * Creates an array of tokens when given some PHP code. + * + * Starts by using token_get_all() but does a lot of extra processing + * to insert information about the context of the token. + * + * @param string $string The string to tokenize. + * + * @return array + */ + protected function tokenize($string) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START PHP TOKENIZING ***".PHP_EOL; + $isWin = false; + if (stripos(PHP_OS, 'WIN') === 0) { + $isWin = true; + } + } + + $tokens = @token_get_all($string); + $finalTokens = []; + + $newStackPtr = 0; + $numTokens = count($tokens); + $lastNotEmptyToken = 0; + + $insideInlineIf = []; + $insideUseGroup = false; + + $commentTokenizer = new Comment(); + + for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) { + // Special case for tokens we have needed to blank out. + if ($tokens[$stackPtr] === null) { + continue; + } + + $token = (array) $tokens[$stackPtr]; + $tokenIsArray = isset($token[1]); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($tokenIsArray === true) { + $type = Util\Tokens::tokenName($token[0]); + $content = Util\Common::prepareForOutput($token[1]); + } else { + $newToken = self::resolveSimpleToken($token[0]); + $type = $newToken['type']; + $content = Util\Common::prepareForOutput($token[0]); + } + + echo "\tProcess token "; + if ($tokenIsArray === true) { + echo "[$stackPtr]"; + } else { + echo " $stackPtr "; + } + + echo ": $type => $content"; + }//end if + + if ($newStackPtr > 0 + && isset(Util\Tokens::$emptyTokens[$finalTokens[($newStackPtr - 1)]['code']]) === false + ) { + $lastNotEmptyToken = ($newStackPtr - 1); + } + + /* + If we are using \r\n newline characters, the \r and \n are sometimes + split over two tokens. This normally occurs after comments. We need + to merge these two characters together so that our line endings are + consistent for all lines. + */ + + if ($tokenIsArray === true && substr($token[1], -1) === "\r") { + if (isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][1][0] === "\n" + ) { + $token[1] .= "\n"; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($isWin === true) { + echo '\n'; + } else { + echo "\033[30;1m\\n\033[0m"; + } + } + + if ($tokens[($stackPtr + 1)][1] === "\n") { + // This token's content has been merged into the previous, + // so we can skip it. + $tokens[($stackPtr + 1)] = ''; + } else { + $tokens[($stackPtr + 1)][1] = substr($tokens[($stackPtr + 1)][1], 1); + } + } + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + + /* + Tokenize context sensitive keyword as string when it should be string. + */ + + if ($tokenIsArray === true + && isset(Util\Tokens::$contextSensitiveKeywords[$token[0]]) === true + && (isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === true + || $finalTokens[$lastNotEmptyToken]['content'] === '&') + ) { + if (isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === true) { + $preserveKeyword = false; + + // `new class`, and `new static` should be preserved. + if ($finalTokens[$lastNotEmptyToken]['code'] === T_NEW + && ($token[0] === T_CLASS + || $token[0] === T_STATIC) + ) { + $preserveKeyword = true; + } + + // `new class extends` `new class implements` should be preserved + if (($token[0] === T_EXTENDS || $token[0] === T_IMPLEMENTS) + && $finalTokens[$lastNotEmptyToken]['code'] === T_CLASS + ) { + $preserveKeyword = true; + } + + // `namespace\` should be preserved + if ($token[0] === T_NAMESPACE) { + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false) { + break; + } + + if (isset(Util\Tokens::$emptyTokens[$tokens[$i][0]]) === true) { + continue; + } + + if ($tokens[$i][0] === T_NS_SEPARATOR) { + $preserveKeyword = true; + } + + break; + } + } + }//end if + + if ($finalTokens[$lastNotEmptyToken]['content'] === '&') { + $preserveKeyword = true; + + for ($i = ($lastNotEmptyToken - 1); $i >= 0; $i--) { + if (isset(Util\Tokens::$emptyTokens[$finalTokens[$i]['code']]) === true) { + continue; + } + + if ($finalTokens[$i]['code'] === T_FUNCTION) { + $preserveKeyword = false; + } + + break; + } + } + + if ($preserveKeyword === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = Util\Tokens::tokenName($token[0]); + echo "\t\t* token $stackPtr changed from $type to T_STRING".PHP_EOL; + } + + $finalTokens[$newStackPtr] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => $token[1], + ]; + + $newStackPtr++; + continue; + } + }//end if + + /* + Parse doc blocks into something that can be easily iterated over. + */ + + if ($tokenIsArray === true + && ($token[0] === T_DOC_COMMENT + || ($token[0] === T_COMMENT && strpos($token[1], '/**') === 0)) + ) { + $commentTokens = $commentTokenizer->tokenizeString($token[1], $this->eolChar, $newStackPtr); + foreach ($commentTokens as $commentToken) { + $finalTokens[$newStackPtr] = $commentToken; + $newStackPtr++; + } + + continue; + } + + /* + PHP 8 tokenizes a new line after a slash and hash comment to the next whitespace token. + */ + + if (PHP_VERSION_ID >= 80000 + && $tokenIsArray === true + && ($token[0] === T_COMMENT && (strpos($token[1], '//') === 0 || strpos($token[1], '#') === 0)) + && isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === T_WHITESPACE + ) { + $nextToken = $tokens[($stackPtr + 1)]; + + // If the next token is a single new line, merge it into the comment token + // and set to it up to be skipped. + if ($nextToken[1] === "\n" || $nextToken[1] === "\r\n" || $nextToken[1] === "\n\r") { + $token[1] .= $nextToken[1]; + $tokens[($stackPtr + 1)] = null; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* merged newline after comment into comment token $stackPtr".PHP_EOL; + } + } else { + // This may be a whitespace token consisting of multiple new lines. + if (strpos($nextToken[1], "\r\n") === 0) { + $token[1] .= "\r\n"; + $tokens[($stackPtr + 1)][1] = substr($nextToken[1], 2); + } else if (strpos($nextToken[1], "\n\r") === 0) { + $token[1] .= "\n\r"; + $tokens[($stackPtr + 1)][1] = substr($nextToken[1], 2); + } else if (strpos($nextToken[1], "\n") === 0) { + $token[1] .= "\n"; + $tokens[($stackPtr + 1)][1] = substr($nextToken[1], 1); + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* stripped first newline after comment and added it to comment token $stackPtr".PHP_EOL; + } + }//end if + }//end if + + /* + For Explicit Octal Notation prior to PHP 8.1 we need to combine the + T_LNUMBER and T_STRING token values into a single token value, and + then ignore the T_STRING token. + */ + + if (PHP_VERSION_ID < 80100 + && $tokenIsArray === true && $token[1] === '0' + && (isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === T_STRING + && strtolower($tokens[($stackPtr + 1)][1][0]) === 'o' + && $tokens[($stackPtr + 1)][1][1] !== '_') + && preg_match('`^(o[0-7]+(?:_[0-7]+)?)([0-9_]*)$`i', $tokens[($stackPtr + 1)][1], $matches) === 1 + ) { + $finalTokens[$newStackPtr] = [ + 'code' => T_LNUMBER, + 'type' => 'T_LNUMBER', + 'content' => $token[1] .= $matches[1], + ]; + $newStackPtr++; + + if (isset($matches[2]) === true && $matches[2] !== '') { + $type = 'T_LNUMBER'; + if ($matches[2][0] === '_') { + $type = 'T_STRING'; + } + + $finalTokens[$newStackPtr] = [ + 'code' => constant($type), + 'type' => $type, + 'content' => $matches[2], + ]; + $newStackPtr++; + } + + $stackPtr++; + continue; + }//end if + + /* + PHP 8.1 introduced two dedicated tokens for the & character. + Retokenizing both of these to T_BITWISE_AND, which is the + token PHPCS already tokenized them as. + */ + + if ($tokenIsArray === true + && ($token[0] === T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG + || $token[0] === T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG) + ) { + $finalTokens[$newStackPtr] = [ + 'code' => T_BITWISE_AND, + 'type' => 'T_BITWISE_AND', + 'content' => $token[1], + ]; + $newStackPtr++; + continue; + } + + /* + If this is a double quoted string, PHP will tokenize the whole + thing which causes problems with the scope map when braces are + within the string. So we need to merge the tokens together to + provide a single string. + */ + + if ($tokenIsArray === false && ($token[0] === '"' || $token[0] === 'b"')) { + // Binary casts need a special token. + if ($token[0] === 'b"') { + $finalTokens[$newStackPtr] = [ + 'code' => T_BINARY_CAST, + 'type' => 'T_BINARY_CAST', + 'content' => 'b', + ]; + $newStackPtr++; + } + + $tokenContent = '"'; + $nestedVars = []; + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + $subToken = (array) $tokens[$i]; + $subTokenIsArray = isset($subToken[1]); + + if ($subTokenIsArray === true) { + $tokenContent .= $subToken[1]; + if (($subToken[1] === '{' + || $subToken[1] === '${') + && $subToken[0] !== T_ENCAPSED_AND_WHITESPACE + ) { + $nestedVars[] = $i; + } + } else { + $tokenContent .= $subToken[0]; + if ($subToken[0] === '}') { + array_pop($nestedVars); + } + } + + if ($subTokenIsArray === false + && $subToken[0] === '"' + && empty($nestedVars) === true + ) { + // We found the other end of the double quoted string. + break; + } + }//end for + + $stackPtr = $i; + + // Convert each line within the double quoted string to a + // new token, so it conforms with other multiple line tokens. + $tokenLines = explode($this->eolChar, $tokenContent); + $numLines = count($tokenLines); + $newToken = []; + + for ($j = 0; $j < $numLines; $j++) { + $newToken['content'] = $tokenLines[$j]; + if ($j === ($numLines - 1)) { + if ($tokenLines[$j] === '') { + break; + } + } else { + $newToken['content'] .= $this->eolChar; + } + + $newToken['code'] = T_DOUBLE_QUOTED_STRING; + $newToken['type'] = 'T_DOUBLE_QUOTED_STRING'; + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + } + + // Continue, as we're done with this token. + continue; + }//end if + + /* + Detect binary casting and assign the casts their own token. + */ + + if ($tokenIsArray === true + && $token[0] === T_CONSTANT_ENCAPSED_STRING + && (substr($token[1], 0, 2) === 'b"' + || substr($token[1], 0, 2) === "b'") + ) { + $finalTokens[$newStackPtr] = [ + 'code' => T_BINARY_CAST, + 'type' => 'T_BINARY_CAST', + 'content' => 'b', + ]; + $newStackPtr++; + $token[1] = substr($token[1], 1); + } + + if ($tokenIsArray === true + && $token[0] === T_STRING_CAST + && preg_match('`^\(\s*binary\s*\)$`i', $token[1]) === 1 + ) { + $finalTokens[$newStackPtr] = [ + 'code' => T_BINARY_CAST, + 'type' => 'T_BINARY_CAST', + 'content' => $token[1], + ]; + $newStackPtr++; + continue; + } + + /* + If this is a heredoc, PHP will tokenize the whole + thing which causes problems when heredocs don't + contain real PHP code, which is almost never. + We want to leave the start and end heredoc tokens + alone though. + */ + + if ($tokenIsArray === true && $token[0] === T_START_HEREDOC) { + // Add the start heredoc token to the final array. + $finalTokens[$newStackPtr] = self::standardiseToken($token); + + // Check if this is actually a nowdoc and use a different token + // to help the sniffs. + $nowdoc = false; + if (strpos($token[1], "'") !== false) { + $finalTokens[$newStackPtr]['code'] = T_START_NOWDOC; + $finalTokens[$newStackPtr]['type'] = 'T_START_NOWDOC'; + $nowdoc = true; + } + + $tokenContent = ''; + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + $subTokenIsArray = is_array($tokens[$i]); + if ($subTokenIsArray === true + && $tokens[$i][0] === T_END_HEREDOC + ) { + // We found the other end of the heredoc. + break; + } + + if ($subTokenIsArray === true) { + $tokenContent .= $tokens[$i][1]; + } else { + $tokenContent .= $tokens[$i]; + } + } + + if ($i === $numTokens) { + // We got to the end of the file and never + // found the closing token, so this probably wasn't + // a heredoc. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $finalTokens[$newStackPtr]['type']; + echo "\t\t* failed to find the end of the here/nowdoc".PHP_EOL; + echo "\t\t* token $stackPtr changed from $type to T_STRING".PHP_EOL; + } + + $finalTokens[$newStackPtr]['code'] = T_STRING; + $finalTokens[$newStackPtr]['type'] = 'T_STRING'; + $newStackPtr++; + continue; + } + + $stackPtr = $i; + $newStackPtr++; + + // Convert each line within the heredoc to a + // new token, so it conforms with other multiple line tokens. + $tokenLines = explode($this->eolChar, $tokenContent); + $numLines = count($tokenLines); + $newToken = []; + + for ($j = 0; $j < $numLines; $j++) { + $newToken['content'] = $tokenLines[$j]; + if ($j === ($numLines - 1)) { + if ($tokenLines[$j] === '') { + break; + } + } else { + $newToken['content'] .= $this->eolChar; + } + + if ($nowdoc === true) { + $newToken['code'] = T_NOWDOC; + $newToken['type'] = 'T_NOWDOC'; + } else { + $newToken['code'] = T_HEREDOC; + $newToken['type'] = 'T_HEREDOC'; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + }//end for + + // Add the end heredoc token to the final array. + $finalTokens[$newStackPtr] = self::standardiseToken($tokens[$stackPtr]); + + if ($nowdoc === true) { + $finalTokens[$newStackPtr]['code'] = T_END_NOWDOC; + $finalTokens[$newStackPtr]['type'] = 'T_END_NOWDOC'; + } + + $newStackPtr++; + + // Continue, as we're done with this token. + continue; + }//end if + + /* + Enum keyword for PHP < 8.1 + */ + + if ($tokenIsArray === true + && $token[0] === T_STRING + && strtolower($token[1]) === 'enum' + ) { + // Get the next non-empty token. + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false + || isset(Util\Tokens::$emptyTokens[$tokens[$i][0]]) === false + ) { + break; + } + } + + if (isset($tokens[$i]) === true + && is_array($tokens[$i]) === true + && $tokens[$i][0] === T_STRING + ) { + // Modify $tokens directly so we can use it later when converting enum "case". + $tokens[$stackPtr][0] = T_ENUM; + + $newToken = []; + $newToken['code'] = T_ENUM; + $newToken['type'] = 'T_ENUM'; + $newToken['content'] = $token[1]; + $finalTokens[$newStackPtr] = $newToken; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_STRING to T_ENUM".PHP_EOL; + } + + $newStackPtr++; + continue; + } + }//end if + + /* + Convert enum "case" to T_ENUM_CASE + */ + + if ($tokenIsArray === true + && $token[0] === T_CASE + && isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === false + ) { + $isEnumCase = false; + $scope = 1; + + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if ($tokens[$i] === '}') { + $scope++; + continue; + } + + if ($tokens[$i] === '{') { + $scope--; + continue; + } + + if (is_array($tokens[$i]) === false) { + continue; + } + + if ($scope !== 0) { + continue; + } + + if ($tokens[$i][0] === T_SWITCH) { + break; + } + + if ($tokens[$i][0] === T_ENUM || $tokens[$i][0] === T_ENUM_CASE) { + $isEnumCase = true; + break; + } + }//end for + + if ($isEnumCase === true) { + // Modify $tokens directly so we can use it as optimisation for other enum "case". + $tokens[$stackPtr][0] = T_ENUM_CASE; + + $newToken = []; + $newToken['code'] = T_ENUM_CASE; + $newToken['type'] = 'T_ENUM_CASE'; + $newToken['content'] = $token[1]; + $finalTokens[$newStackPtr] = $newToken; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_CASE to T_ENUM_CASE".PHP_EOL; + } + + $newStackPtr++; + continue; + } + }//end if + + /* + As of PHP 8.0 fully qualified, partially qualified and namespace relative + identifier names are tokenized differently. + This "undoes" the new tokenization so the tokenization will be the same in + in PHP 5, 7 and 8. + */ + + if (PHP_VERSION_ID >= 80000 + && $tokenIsArray === true + && ($token[0] === T_NAME_QUALIFIED + || $token[0] === T_NAME_FULLY_QUALIFIED + || $token[0] === T_NAME_RELATIVE) + ) { + $name = $token[1]; + + if ($token[0] === T_NAME_FULLY_QUALIFIED) { + $newToken = []; + $newToken['code'] = T_NS_SEPARATOR; + $newToken['type'] = 'T_NS_SEPARATOR'; + $newToken['content'] = '\\'; + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + + $name = ltrim($name, '\\'); + } + + if ($token[0] === T_NAME_RELATIVE) { + $newToken = []; + $newToken['code'] = T_NAMESPACE; + $newToken['type'] = 'T_NAMESPACE'; + $newToken['content'] = substr($name, 0, 9); + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + + $newToken = []; + $newToken['code'] = T_NS_SEPARATOR; + $newToken['type'] = 'T_NS_SEPARATOR'; + $newToken['content'] = '\\'; + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + + $name = substr($name, 10); + } + + $parts = explode('\\', $name); + $partCount = count($parts); + $lastPart = ($partCount - 1); + + foreach ($parts as $i => $part) { + $newToken = []; + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + $newToken['content'] = $part; + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + + if ($i !== $lastPart) { + $newToken = []; + $newToken['code'] = T_NS_SEPARATOR; + $newToken['type'] = 'T_NS_SEPARATOR'; + $newToken['content'] = '\\'; + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = Util\Tokens::tokenName($token[0]); + $content = Util\Common::prepareForOutput($token[1]); + echo "\t\t* token $stackPtr split into individual tokens; was: $type => $content".PHP_EOL; + } + + continue; + }//end if + + /* + PHP 8.0 Attributes + */ + + if (PHP_VERSION_ID < 80000 + && $token[0] === T_COMMENT + && strpos($token[1], '#[') === 0 + ) { + $subTokens = $this->parsePhpAttribute($tokens, $stackPtr); + if ($subTokens !== null) { + array_splice($tokens, $stackPtr, 1, $subTokens); + $numTokens = count($tokens); + + $tokenIsArray = true; + $token = $tokens[$stackPtr]; + } else { + $token[0] = T_ATTRIBUTE; + } + } + + if ($tokenIsArray === true + && $token[0] === T_ATTRIBUTE + ) { + // Go looking for the close bracket. + $bracketCloser = $this->findCloser($tokens, ($stackPtr + 1), ['[', '#['], ']'); + + $newToken = []; + $newToken['code'] = T_ATTRIBUTE; + $newToken['type'] = 'T_ATTRIBUTE'; + $newToken['content'] = '#['; + $finalTokens[$newStackPtr] = $newToken; + + $tokens[$bracketCloser] = []; + $tokens[$bracketCloser][0] = T_ATTRIBUTE_END; + $tokens[$bracketCloser][1] = ']'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $bracketCloser changed from T_CLOSE_SQUARE_BRACKET to T_ATTRIBUTE_END".PHP_EOL; + } + + $newStackPtr++; + continue; + }//end if + + /* + Tokenize the parameter labels for PHP 8.0 named parameters as a special T_PARAM_NAME + token and ensure that the colon after it is always T_COLON. + */ + + if ($tokenIsArray === true + && ($token[0] === T_STRING + || preg_match('`^[a-zA-Z_\x80-\xff]`', $token[1]) === 1) + ) { + // Get the next non-empty token. + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false + || isset(Util\Tokens::$emptyTokens[$tokens[$i][0]]) === false + ) { + break; + } + } + + if (isset($tokens[$i]) === true + && is_array($tokens[$i]) === false + && $tokens[$i] === ':' + ) { + // Get the previous non-empty token. + for ($j = ($stackPtr - 1); $j > 0; $j--) { + if (is_array($tokens[$j]) === false + || isset(Util\Tokens::$emptyTokens[$tokens[$j][0]]) === false + ) { + break; + } + } + + if (is_array($tokens[$j]) === false + && ($tokens[$j] === '(' + || $tokens[$j] === ',') + ) { + $newToken = []; + $newToken['code'] = T_PARAM_NAME; + $newToken['type'] = 'T_PARAM_NAME'; + $newToken['content'] = $token[1]; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + + // Modify the original token stack so that future checks, like + // determining T_COLON vs T_INLINE_ELSE can handle this correctly. + $tokens[$stackPtr][0] = T_PARAM_NAME; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = Util\Tokens::tokenName($token[0]); + echo "\t\t* token $stackPtr changed from $type to T_PARAM_NAME".PHP_EOL; + } + + continue; + } + }//end if + }//end if + + /* + "readonly" keyword for PHP < 8.1 + */ + + if (PHP_VERSION_ID < 80100 + && $tokenIsArray === true + && strtolower($token[1]) === 'readonly' + && isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === false + ) { + // Get the next non-whitespace token. + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false + || $tokens[$i][0] !== T_WHITESPACE + ) { + break; + } + } + + if (isset($tokens[$i]) === false + || $tokens[$i] !== '(' + ) { + $finalTokens[$newStackPtr] = [ + 'code' => T_READONLY, + 'type' => 'T_READONLY', + 'content' => $token[1], + ]; + $newStackPtr++; + + continue; + } + }//end if + + /* + Before PHP 7.0, the "yield from" was tokenized as + T_YIELD, T_WHITESPACE and T_STRING. So look for + and change this token in earlier versions. + */ + + if (PHP_VERSION_ID < 70000 + && PHP_VERSION_ID >= 50500 + && $tokenIsArray === true + && $token[0] === T_YIELD + && isset($tokens[($stackPtr + 1)]) === true + && isset($tokens[($stackPtr + 2)]) === true + && $tokens[($stackPtr + 1)][0] === T_WHITESPACE + && $tokens[($stackPtr + 2)][0] === T_STRING + && strtolower($tokens[($stackPtr + 2)][1]) === 'from' + ) { + // Could be multi-line, so adjust the token stack. + $token[0] = T_YIELD_FROM; + $token[1] .= $tokens[($stackPtr + 1)][1].$tokens[($stackPtr + 2)][1]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + for ($i = ($stackPtr + 1); $i <= ($stackPtr + 2); $i++) { + $type = Util\Tokens::tokenName($tokens[$i][0]); + $content = Util\Common::prepareForOutput($tokens[$i][1]); + echo "\t\t* token $i merged into T_YIELD_FROM; was: $type => $content".PHP_EOL; + } + } + + $tokens[($stackPtr + 1)] = null; + $tokens[($stackPtr + 2)] = null; + } + + /* + Before PHP 5.5, the yield keyword was tokenized as + T_STRING. So look for and change this token in + earlier versions. + Checks also if it is just "yield" or "yield from". + */ + + if (PHP_VERSION_ID < 50500 + && $tokenIsArray === true + && $token[0] === T_STRING + && strtolower($token[1]) === 'yield' + && isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === false + ) { + if (isset($tokens[($stackPtr + 1)]) === true + && isset($tokens[($stackPtr + 2)]) === true + && $tokens[($stackPtr + 1)][0] === T_WHITESPACE + && $tokens[($stackPtr + 2)][0] === T_STRING + && strtolower($tokens[($stackPtr + 2)][1]) === 'from' + ) { + // Could be multi-line, so just just the token stack. + $token[0] = T_YIELD_FROM; + $token[1] .= $tokens[($stackPtr + 1)][1].$tokens[($stackPtr + 2)][1]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + for ($i = ($stackPtr + 1); $i <= ($stackPtr + 2); $i++) { + $type = Util\Tokens::tokenName($tokens[$i][0]); + $content = Util\Common::prepareForOutput($tokens[$i][1]); + echo "\t\t* token $i merged into T_YIELD_FROM; was: $type => $content".PHP_EOL; + } + } + + $tokens[($stackPtr + 1)] = null; + $tokens[($stackPtr + 2)] = null; + } else { + $newToken = []; + $newToken['code'] = T_YIELD; + $newToken['type'] = 'T_YIELD'; + $newToken['content'] = $token[1]; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + continue; + }//end if + }//end if + + /* + Before PHP 5.6, the ... operator was tokenized as three + T_STRING_CONCAT tokens in a row. So look for and combine + these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '.' + && isset($tokens[($stackPtr + 1)]) === true + && isset($tokens[($stackPtr + 2)]) === true + && $tokens[($stackPtr + 1)] === '.' + && $tokens[($stackPtr + 2)] === '.' + ) { + $newToken = []; + $newToken['code'] = T_ELLIPSIS; + $newToken['type'] = 'T_ELLIPSIS'; + $newToken['content'] = '...'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr += 2; + continue; + } + + /* + Before PHP 5.6, the ** operator was tokenized as two + T_MULTIPLY tokens in a row. So look for and combine + these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '*' + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)] === '*' + ) { + $newToken = []; + $newToken['code'] = T_POW; + $newToken['type'] = 'T_POW'; + $newToken['content'] = '**'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + Before PHP 5.6, the **= operator was tokenized as + T_MULTIPLY followed by T_MUL_EQUAL. So look for and combine + these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '*' + && isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][1] === '*=' + ) { + $newToken = []; + $newToken['code'] = T_POW_EQUAL; + $newToken['type'] = 'T_POW_EQUAL'; + $newToken['content'] = '**='; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + Before PHP 7, the ??= operator was tokenized as + T_INLINE_THEN, T_INLINE_THEN, T_EQUAL. + Between PHP 7.0 and 7.3, the ??= operator was tokenized as + T_COALESCE, T_EQUAL. + So look for and combine these tokens in earlier versions. + */ + + if (($tokenIsArray === false + && $token[0] === '?' + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === '?' + && isset($tokens[($stackPtr + 2)]) === true + && $tokens[($stackPtr + 2)][0] === '=') + || ($tokenIsArray === true + && $token[0] === T_COALESCE + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === '=') + ) { + $newToken = []; + $newToken['code'] = T_COALESCE_EQUAL; + $newToken['type'] = 'T_COALESCE_EQUAL'; + $newToken['content'] = '??='; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + + if ($tokenIsArray === false) { + // Pre PHP 7. + $stackPtr++; + } + + continue; + } + + /* + Before PHP 7, the ?? operator was tokenized as + T_INLINE_THEN followed by T_INLINE_THEN. + So look for and combine these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '?' + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === '?' + ) { + $newToken = []; + $newToken['code'] = T_COALESCE; + $newToken['type'] = 'T_COALESCE'; + $newToken['content'] = '??'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + Before PHP 8, the ?-> operator was tokenized as + T_INLINE_THEN followed by T_OBJECT_OPERATOR. + So look for and combine these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '?' + && isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === T_OBJECT_OPERATOR + ) { + $newToken = []; + $newToken['code'] = T_NULLSAFE_OBJECT_OPERATOR; + $newToken['type'] = 'T_NULLSAFE_OBJECT_OPERATOR'; + $newToken['content'] = '?->'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + Before PHP 7.4, underscores inside T_LNUMBER and T_DNUMBER + tokens split the token with a T_STRING. So look for + and change these tokens in earlier versions. + */ + + if (PHP_VERSION_ID < 70400 + && ($tokenIsArray === true + && ($token[0] === T_LNUMBER + || $token[0] === T_DNUMBER) + && isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === T_STRING + && $tokens[($stackPtr + 1)][1][0] === '_') + ) { + $newContent = $token[1]; + $newType = $token[0]; + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false) { + break; + } + + if ($tokens[$i][0] === T_LNUMBER + || $tokens[$i][0] === T_DNUMBER + ) { + $newContent .= $tokens[$i][1]; + continue; + } + + if ($tokens[$i][0] === T_STRING + && $tokens[$i][1][0] === '_' + && ((strpos($newContent, '0x') === 0 + && preg_match('`^((? PHP_INT_MAX) + || (stripos($newContent, '0b') === 0 && bindec(str_replace('_', '', $newContent)) > PHP_INT_MAX) + || (stripos($newContent, '0o') === 0 && octdec(str_replace('_', '', $newContent)) > PHP_INT_MAX) + || (stripos($newContent, '0x') !== 0 + && stripos($newContent, 'e') !== false || strpos($newContent, '.') !== false) + || (strpos($newContent, '0') === 0 && stripos($newContent, '0x') !== 0 + && stripos($newContent, '0b') !== 0 && octdec(str_replace('_', '', $newContent)) > PHP_INT_MAX) + || (strpos($newContent, '0') !== 0 && str_replace('_', '', $newContent) > PHP_INT_MAX)) + ) { + $newType = T_DNUMBER; + } + + $newToken = []; + $newToken['code'] = $newType; + $newToken['type'] = Util\Tokens::tokenName($newType); + $newToken['content'] = $newContent; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr = ($i - 1); + continue; + }//end if + + /* + Backfill the T_MATCH token for PHP versions < 8.0 and + do initial correction for non-match expression T_MATCH tokens + to T_STRING for PHP >= 8.0. + A final check for non-match expression T_MATCH tokens is done + in PHP::processAdditional(). + */ + + if ($tokenIsArray === true + && (($token[0] === T_STRING + && strtolower($token[1]) === 'match') + || $token[0] === T_MATCH) + ) { + $isMatch = false; + for ($x = ($stackPtr + 1); $x < $numTokens; $x++) { + if (isset($tokens[$x][0], Util\Tokens::$emptyTokens[$tokens[$x][0]]) === true) { + continue; + } + + if ($tokens[$x] !== '(') { + // This is not a match expression. + break; + } + + if (isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === true) { + // Also not a match expression. + break; + } + + $isMatch = true; + break; + }//end for + + if ($isMatch === true && $token[0] === T_STRING) { + $newToken = []; + $newToken['code'] = T_MATCH; + $newToken['type'] = 'T_MATCH'; + $newToken['content'] = $token[1]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_STRING to T_MATCH".PHP_EOL; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue; + } else if ($isMatch === false && $token[0] === T_MATCH) { + // PHP 8.0, match keyword, but not a match expression. + $newToken = []; + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + $newToken['content'] = $token[1]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_MATCH to T_STRING".PHP_EOL; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue; + }//end if + }//end if + + /* + Retokenize the T_DEFAULT in match control structures as T_MATCH_DEFAULT + to prevent scope being set and the scope for switch default statements + breaking. + */ + + if ($tokenIsArray === true + && $token[0] === T_DEFAULT + && isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === false + ) { + for ($x = ($stackPtr + 1); $x < $numTokens; $x++) { + if ($tokens[$x] === ',') { + // Skip over potential trailing comma (supported in PHP). + continue; + } + + if (is_array($tokens[$x]) === false + || isset(Util\Tokens::$emptyTokens[$tokens[$x][0]]) === false + ) { + // Non-empty, non-comma content. + break; + } + } + + if (isset($tokens[$x]) === true + && is_array($tokens[$x]) === true + && $tokens[$x][0] === T_DOUBLE_ARROW + ) { + // Modify the original token stack for the double arrow so that + // future checks can disregard the double arrow token more easily. + // For match expression "case" statements, this is handled + // in PHP::processAdditional(). + $tokens[$x][0] = T_MATCH_ARROW; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $x changed from T_DOUBLE_ARROW to T_MATCH_ARROW".PHP_EOL; + } + + $newToken = []; + $newToken['code'] = T_MATCH_DEFAULT; + $newToken['type'] = 'T_MATCH_DEFAULT'; + $newToken['content'] = $token[1]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_DEFAULT to T_MATCH_DEFAULT".PHP_EOL; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue; + }//end if + }//end if + + /* + Convert ? to T_NULLABLE OR T_INLINE_THEN + */ + + if ($tokenIsArray === false && $token[0] === '?') { + $newToken = []; + $newToken['content'] = '?'; + + /* + * Check if the next non-empty token is one of the tokens which can be used + * in type declarations. If not, it's definitely a ternary. + * At this point, the only token types which need to be taken into consideration + * as potential type declarations are identifier names, T_ARRAY, T_CALLABLE and T_NS_SEPARATOR. + */ + + $lastRelevantNonEmpty = null; + + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === true) { + $tokenType = $tokens[$i][0]; + } else { + $tokenType = $tokens[$i]; + } + + if (isset(Util\Tokens::$emptyTokens[$tokenType]) === true) { + continue; + } + + if ($tokenType === T_STRING + || $tokenType === T_NAME_FULLY_QUALIFIED + || $tokenType === T_NAME_RELATIVE + || $tokenType === T_NAME_QUALIFIED + || $tokenType === T_ARRAY + || $tokenType === T_NAMESPACE + || $tokenType === T_NS_SEPARATOR + ) { + $lastRelevantNonEmpty = $tokenType; + continue; + } + + if (($tokenType !== T_CALLABLE + && isset($lastRelevantNonEmpty) === false) + || ($lastRelevantNonEmpty === T_ARRAY + && $tokenType === '(') + || (($lastRelevantNonEmpty === T_STRING + || $lastRelevantNonEmpty === T_NAME_FULLY_QUALIFIED + || $lastRelevantNonEmpty === T_NAME_RELATIVE + || $lastRelevantNonEmpty === T_NAME_QUALIFIED) + && ($tokenType === T_DOUBLE_COLON + || $tokenType === '(' + || $tokenType === ':')) + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from ? to T_INLINE_THEN".PHP_EOL; + } + + $newToken['code'] = T_INLINE_THEN; + $newToken['type'] = 'T_INLINE_THEN'; + + $insideInlineIf[] = $stackPtr; + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue 2; + } + + break; + }//end for + + /* + * This can still be a nullable type or a ternary. + * Do additional checking. + */ + + $prevNonEmpty = null; + $lastSeenNonEmpty = null; + + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + if (is_array($tokens[$i]) === true) { + $tokenType = $tokens[$i][0]; + } else { + $tokenType = $tokens[$i]; + } + + if ($tokenType === T_STATIC + && ($lastSeenNonEmpty === T_DOUBLE_COLON + || $lastSeenNonEmpty === '(') + ) { + $lastSeenNonEmpty = $tokenType; + continue; + } + + if ($prevNonEmpty === null + && isset(Util\Tokens::$emptyTokens[$tokenType]) === false + ) { + // Found the previous non-empty token. + if ($tokenType === ':' || $tokenType === ',' || $tokenType === T_ATTRIBUTE_END) { + $newToken['code'] = T_NULLABLE; + $newToken['type'] = 'T_NULLABLE'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from ? to T_NULLABLE".PHP_EOL; + } + + break; + } + + $prevNonEmpty = $tokenType; + } + + if ($tokenType === T_FUNCTION + || $tokenType === T_FN + || isset(Util\Tokens::$methodPrefixes[$tokenType]) === true + || $tokenType === T_VAR + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from ? to T_NULLABLE".PHP_EOL; + } + + $newToken['code'] = T_NULLABLE; + $newToken['type'] = 'T_NULLABLE'; + break; + } else if (in_array($tokenType, [T_DOUBLE_ARROW, T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO, '=', '{', ';'], true) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from ? to T_INLINE_THEN".PHP_EOL; + } + + $newToken['code'] = T_INLINE_THEN; + $newToken['type'] = 'T_INLINE_THEN'; + + $insideInlineIf[] = $stackPtr; + break; + } + + if (isset(Util\Tokens::$emptyTokens[$tokenType]) === false) { + $lastSeenNonEmpty = $tokenType; + } + }//end for + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue; + }//end if + + /* + Tokens after a double colon may look like scope openers, + such as when writing code like Foo::NAMESPACE, but they are + only ever variables or strings. + */ + + if ($stackPtr > 1 + && (is_array($tokens[($stackPtr - 1)]) === true + && $tokens[($stackPtr - 1)][0] === T_PAAMAYIM_NEKUDOTAYIM) + && $tokenIsArray === true + && $token[0] !== T_STRING + && $token[0] !== T_VARIABLE + && $token[0] !== T_DOLLAR + && isset(Util\Tokens::$emptyTokens[$token[0]]) === false + ) { + $newToken = []; + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + $newToken['content'] = $token[1]; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + continue; + } + + /* + Backfill the T_FN token for PHP versions < 7.4. + */ + + if ($tokenIsArray === true + && $token[0] === T_STRING + && strtolower($token[1]) === 'fn' + ) { + // Modify the original token stack so that + // future checks (like looking for T_NULLABLE) can + // detect the T_FN token more easily. + $tokens[$stackPtr][0] = T_FN; + $token[0] = T_FN; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_STRING to T_FN".PHP_EOL; + } + } + + /* + This is a special condition for T_ARRAY tokens used for + function return types. We want to keep the parenthesis map clean, + so let's tag these tokens as T_STRING. + */ + + if ($tokenIsArray === true + && ($token[0] === T_FUNCTION + || $token[0] === T_FN) + && $finalTokens[$lastNotEmptyToken]['code'] !== T_USE + ) { + // Go looking for the colon to start the return type hint. + // Start by finding the closing parenthesis of the function. + $parenthesisStack = []; + $parenthesisCloser = false; + for ($x = ($stackPtr + 1); $x < $numTokens; $x++) { + if (is_array($tokens[$x]) === false && $tokens[$x] === '(') { + $parenthesisStack[] = $x; + } else if (is_array($tokens[$x]) === false && $tokens[$x] === ')') { + array_pop($parenthesisStack); + if (empty($parenthesisStack) === true) { + $parenthesisCloser = $x; + break; + } + } + } + + if ($parenthesisCloser !== false) { + for ($x = ($parenthesisCloser + 1); $x < $numTokens; $x++) { + if (is_array($tokens[$x]) === false + || isset(Util\Tokens::$emptyTokens[$tokens[$x][0]]) === false + ) { + // Non-empty content. + if (is_array($tokens[$x]) === true && $tokens[$x][0] === T_USE) { + // Found a use statements, so search ahead for the closing parenthesis. + for ($x += 1; $x < $numTokens; $x++) { + if (is_array($tokens[$x]) === false && $tokens[$x] === ')') { + continue(2); + } + } + } + + break; + } + } + + if (isset($tokens[$x]) === true + && is_array($tokens[$x]) === false + && $tokens[$x] === ':' + ) { + // Find the start of the return type. + for ($x += 1; $x < $numTokens; $x++) { + if (is_array($tokens[$x]) === true + && isset(Util\Tokens::$emptyTokens[$tokens[$x][0]]) === true + ) { + // Whitespace or comments before the return type. + continue; + } + + if (is_array($tokens[$x]) === false && $tokens[$x] === '?') { + // Found a nullable operator, so skip it. + // But also convert the token to save the tokenizer + // a bit of time later on. + $tokens[$x] = [ + T_NULLABLE, + '?', + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $x changed from ? to T_NULLABLE".PHP_EOL; + } + + continue; + } + + break; + }//end for + }//end if + }//end if + }//end if + + /* + Before PHP 7, the <=> operator was tokenized as + T_IS_SMALLER_OR_EQUAL followed by T_GREATER_THAN. + So look for and combine these tokens in earlier versions. + */ + + if ($tokenIsArray === true + && $token[0] === T_IS_SMALLER_OR_EQUAL + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === '>' + ) { + $newToken = []; + $newToken['code'] = T_SPACESHIP; + $newToken['type'] = 'T_SPACESHIP'; + $newToken['content'] = '<=>'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + PHP doesn't assign a token to goto labels, so we have to. + These are just string tokens with a single colon after them. Double + colons are already tokenized and so don't interfere with this check. + But we do have to account for CASE statements, that look just like + goto labels. + */ + + if ($tokenIsArray === true + && $token[0] === T_STRING + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)] === ':' + && (is_array($tokens[($stackPtr - 1)]) === false + || $tokens[($stackPtr - 1)][0] !== T_PAAMAYIM_NEKUDOTAYIM) + ) { + $stopTokens = [ + T_CASE => true, + T_SEMICOLON => true, + T_OPEN_TAG => true, + T_OPEN_CURLY_BRACKET => true, + T_INLINE_THEN => true, + T_ENUM => true, + ]; + + for ($x = ($newStackPtr - 1); $x > 0; $x--) { + if (isset($stopTokens[$finalTokens[$x]['code']]) === true) { + break; + } + } + + if ($finalTokens[$x]['code'] !== T_CASE + && $finalTokens[$x]['code'] !== T_INLINE_THEN + && $finalTokens[$x]['code'] !== T_ENUM + ) { + $finalTokens[$newStackPtr] = [ + 'content' => $token[1].':', + 'code' => T_GOTO_LABEL, + 'type' => 'T_GOTO_LABEL', + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_STRING to T_GOTO_LABEL".PHP_EOL; + echo "\t\t* skipping T_COLON token ".($stackPtr + 1).PHP_EOL; + } + + $newStackPtr++; + $stackPtr++; + continue; + } + }//end if + + /* + If this token has newlines in its content, split each line up + and create a new token for each line. We do this so it's easier + to ascertain where errors occur on a line. + Note that $token[1] is the token's content. + */ + + if ($tokenIsArray === true && strpos($token[1], $this->eolChar) !== false) { + $tokenLines = explode($this->eolChar, $token[1]); + $numLines = count($tokenLines); + $newToken = [ + 'type' => Util\Tokens::tokenName($token[0]), + 'code' => $token[0], + 'content' => '', + ]; + + for ($i = 0; $i < $numLines; $i++) { + $newToken['content'] = $tokenLines[$i]; + if ($i === ($numLines - 1)) { + if ($tokenLines[$i] === '') { + break; + } + } else { + $newToken['content'] .= $this->eolChar; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + } + } else { + // Some T_STRING tokens should remain that way due to their context. + if ($tokenIsArray === true + && $token[0] === T_STRING + && isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === true + ) { + // Special case for syntax like: return new self/new parent + // where self/parent should not be a string. + $tokenContentLower = strtolower($token[1]); + if ($finalTokens[$lastNotEmptyToken]['code'] === T_NEW + && ($tokenContentLower === 'self' || $tokenContentLower === 'parent') + ) { + $finalTokens[$newStackPtr] = [ + 'content' => $token[1], + ]; + if ($tokenContentLower === 'self') { + $finalTokens[$newStackPtr]['code'] = T_SELF; + $finalTokens[$newStackPtr]['type'] = 'T_SELF'; + } + + if ($tokenContentLower === 'parent') { + $finalTokens[$newStackPtr]['code'] = T_PARENT; + $finalTokens[$newStackPtr]['type'] = 'T_PARENT'; + } + } else { + $finalTokens[$newStackPtr] = [ + 'content' => $token[1], + 'code' => T_STRING, + 'type' => 'T_STRING', + ]; + } + + $newStackPtr++; + continue; + }//end if + + $newToken = null; + if ($tokenIsArray === false) { + if (isset(self::$resolveTokenCache[$token[0]]) === true) { + $newToken = self::$resolveTokenCache[$token[0]]; + } + } else { + $cacheKey = null; + if ($token[0] === T_STRING) { + $cacheKey = strtolower($token[1]); + } else if ($token[0] !== T_CURLY_OPEN) { + $cacheKey = $token[0]; + } + + if ($cacheKey !== null && isset(self::$resolveTokenCache[$cacheKey]) === true) { + $newToken = self::$resolveTokenCache[$cacheKey]; + $newToken['content'] = $token[1]; + } + } + + if ($newToken === null) { + $newToken = self::standardiseToken($token); + } + + // Convert colons that are actually the ELSE component of an + // inline IF statement. + if (empty($insideInlineIf) === false && $newToken['code'] === T_COLON) { + $isInlineIf = true; + + // Make sure this isn't a named parameter label. + // Get the previous non-empty token. + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if (is_array($tokens[$i]) === false + || isset(Util\Tokens::$emptyTokens[$tokens[$i][0]]) === false + ) { + break; + } + } + + if ($tokens[$i][0] === T_PARAM_NAME) { + $isInlineIf = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is parameter label, not T_INLINE_ELSE".PHP_EOL; + } + } + + if ($isInlineIf === true) { + // Make sure this isn't a return type separator. + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if (is_array($tokens[$i]) === false + || ($tokens[$i][0] !== T_DOC_COMMENT + && $tokens[$i][0] !== T_COMMENT + && $tokens[$i][0] !== T_WHITESPACE) + ) { + break; + } + } + + if ($tokens[$i] === ')') { + $parenCount = 1; + for ($i--; $i > 0; $i--) { + if ($tokens[$i] === '(') { + $parenCount--; + if ($parenCount === 0) { + break; + } + } else if ($tokens[$i] === ')') { + $parenCount++; + } + } + + // We've found the open parenthesis, so if the previous + // non-empty token is FUNCTION or USE, this is a return type. + // Note that we need to skip T_STRING tokens here as these + // can be function names. + for ($i--; $i > 0; $i--) { + if (is_array($tokens[$i]) === false + || ($tokens[$i][0] !== T_DOC_COMMENT + && $tokens[$i][0] !== T_COMMENT + && $tokens[$i][0] !== T_WHITESPACE + && $tokens[$i][0] !== T_STRING) + ) { + break; + } + } + + if ($tokens[$i][0] === T_FUNCTION || $tokens[$i][0] === T_FN || $tokens[$i][0] === T_USE) { + $isInlineIf = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is return type, not T_INLINE_ELSE".PHP_EOL; + } + } + }//end if + }//end if + + // Check to see if this is a CASE or DEFAULT opener. + if ($isInlineIf === true) { + $inlineIfToken = $insideInlineIf[(count($insideInlineIf) - 1)]; + for ($i = $stackPtr; $i > $inlineIfToken; $i--) { + if (is_array($tokens[$i]) === true + && ($tokens[$i][0] === T_CASE + || $tokens[$i][0] === T_DEFAULT) + ) { + $isInlineIf = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is T_CASE or T_DEFAULT opener, not T_INLINE_ELSE".PHP_EOL; + } + + break; + } + + if (is_array($tokens[$i]) === false + && ($tokens[$i] === ';' + || $tokens[$i] === '{') + ) { + break; + } + } + }//end if + + if ($isInlineIf === true) { + array_pop($insideInlineIf); + $newToken['code'] = T_INLINE_ELSE; + $newToken['type'] = 'T_INLINE_ELSE'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token changed from T_COLON to T_INLINE_ELSE".PHP_EOL; + } + } + }//end if + + // This is a special condition for T_ARRAY tokens used for anything else + // but array declarations, like type hinting function arguments as + // being arrays. + // We want to keep the parenthesis map clean, so let's tag these tokens as + // T_STRING. + if ($newToken['code'] === T_ARRAY) { + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false + || isset(Util\Tokens::$emptyTokens[$tokens[$i][0]]) === false + ) { + // Non-empty content. + break; + } + } + + if ($i !== $numTokens && $tokens[$i] !== '(') { + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + } + } + + // This is a special case when checking PHP 5.5+ code in PHP < 5.5 + // where "finally" should be T_FINALLY instead of T_STRING. + if ($newToken['code'] === T_STRING + && strtolower($newToken['content']) === 'finally' + && $finalTokens[$lastNotEmptyToken]['code'] === T_CLOSE_CURLY_BRACKET + ) { + $newToken['code'] = T_FINALLY; + $newToken['type'] = 'T_FINALLY'; + } + + // This is a special case for PHP 5.6 use function and use const + // where "function" and "const" should be T_STRING instead of T_FUNCTION + // and T_CONST. + if (($newToken['code'] === T_FUNCTION + || $newToken['code'] === T_CONST) + && ($finalTokens[$lastNotEmptyToken]['code'] === T_USE || $insideUseGroup === true) + ) { + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + } + + // This is a special case for use groups in PHP 7+ where leaving + // the curly braces as their normal tokens would confuse + // the scope map and sniffs. + if ($newToken['code'] === T_OPEN_CURLY_BRACKET + && $finalTokens[$lastNotEmptyToken]['code'] === T_NS_SEPARATOR + ) { + $newToken['code'] = T_OPEN_USE_GROUP; + $newToken['type'] = 'T_OPEN_USE_GROUP'; + $insideUseGroup = true; + } + + if ($insideUseGroup === true && $newToken['code'] === T_CLOSE_CURLY_BRACKET) { + $newToken['code'] = T_CLOSE_USE_GROUP; + $newToken['type'] = 'T_CLOSE_USE_GROUP'; + $insideUseGroup = false; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + }//end if + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END PHP TOKENIZING ***".PHP_EOL; + } + + return $finalTokens; + + }//end tokenize() + + + /** + * Performs additional processing after main tokenizing. + * + * This additional processing checks for CASE statements that are using curly + * braces for scope openers and closers. It also turns some T_FUNCTION tokens + * into T_CLOSURE when they are not standard function definitions. It also + * detects short array syntax and converts those square brackets into new tokens. + * It also corrects some usage of the static and class keywords. It also + * assigns tokens to function return types. + * + * @return void + */ + protected function processAdditional() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START ADDITIONAL PHP PROCESSING ***".PHP_EOL; + } + + $this->createAttributesNestingMap(); + + $numTokens = count($this->tokens); + for ($i = ($numTokens - 1); $i >= 0; $i--) { + // Check for any unset scope conditions due to alternate IF/ENDIF syntax. + if (isset($this->tokens[$i]['scope_opener']) === true + && isset($this->tokens[$i]['scope_condition']) === false + ) { + $this->tokens[$i]['scope_condition'] = $this->tokens[$this->tokens[$i]['scope_opener']]['scope_condition']; + } + + if ($this->tokens[$i]['code'] === T_FUNCTION) { + /* + Detect functions that are actually closures and + assign them a different token. + */ + + if (isset($this->tokens[$i]['scope_opener']) === true) { + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false + && $this->tokens[$x]['code'] !== T_BITWISE_AND + ) { + break; + } + } + + if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) { + $this->tokens[$i]['code'] = T_CLOSURE; + $this->tokens[$i]['type'] = 'T_CLOSURE'; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t* token $i on line $line changed from T_FUNCTION to T_CLOSURE".PHP_EOL; + } + + for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) { + if (isset($this->tokens[$x]['conditions'][$i]) === false) { + continue; + } + + $this->tokens[$x]['conditions'][$i] = T_CLOSURE; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo "\t\t* cleaned $x ($type) *".PHP_EOL; + } + } + } + }//end if + + continue; + } else if ($this->tokens[$i]['code'] === T_CLASS && isset($this->tokens[$i]['scope_opener']) === true) { + /* + Detect anonymous classes and assign them a different token. + */ + + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + break; + } + } + + if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS + || $this->tokens[$x]['code'] === T_OPEN_CURLY_BRACKET + || $this->tokens[$x]['code'] === T_EXTENDS + || $this->tokens[$x]['code'] === T_IMPLEMENTS + ) { + $this->tokens[$i]['code'] = T_ANON_CLASS; + $this->tokens[$i]['type'] = 'T_ANON_CLASS'; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t* token $i on line $line changed from T_CLASS to T_ANON_CLASS".PHP_EOL; + } + + if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS + && isset($this->tokens[$x]['parenthesis_closer']) === true + ) { + $closer = $this->tokens[$x]['parenthesis_closer']; + + $this->tokens[$i]['parenthesis_opener'] = $x; + $this->tokens[$i]['parenthesis_closer'] = $closer; + $this->tokens[$i]['parenthesis_owner'] = $i; + $this->tokens[$x]['parenthesis_owner'] = $i; + $this->tokens[$closer]['parenthesis_owner'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t\t* added parenthesis keys to T_ANON_CLASS token $i on line $line".PHP_EOL; + } + } + + for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) { + if (isset($this->tokens[$x]['conditions'][$i]) === false) { + continue; + } + + $this->tokens[$x]['conditions'][$i] = T_ANON_CLASS; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo "\t\t* cleaned $x ($type) *".PHP_EOL; + } + } + }//end if + + continue; + } else if ($this->tokens[$i]['code'] === T_FN && isset($this->tokens[($i + 1)]) === true) { + // Possible arrow function. + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false + && $this->tokens[$x]['code'] !== T_BITWISE_AND + ) { + // Non-whitespace content. + break; + } + } + + if (isset($this->tokens[$x]) === true && $this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) { + $ignore = Util\Tokens::$emptyTokens; + $ignore += [ + T_ARRAY => T_ARRAY, + T_CALLABLE => T_CALLABLE, + T_COLON => T_COLON, + T_NAMESPACE => T_NAMESPACE, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_NULL => T_NULL, + T_NULLABLE => T_NULLABLE, + T_PARENT => T_PARENT, + T_SELF => T_SELF, + T_STATIC => T_STATIC, + T_STRING => T_STRING, + T_TYPE_UNION => T_TYPE_UNION, + T_TYPE_INTERSECTION => T_TYPE_INTERSECTION, + ]; + + $closer = $this->tokens[$x]['parenthesis_closer']; + for ($arrow = ($closer + 1); $arrow < $numTokens; $arrow++) { + if (isset($ignore[$this->tokens[$arrow]['code']]) === false) { + break; + } + } + + if ($this->tokens[$arrow]['code'] === T_DOUBLE_ARROW) { + $endTokens = [ + T_COLON => true, + T_COMMA => true, + T_SEMICOLON => true, + T_CLOSE_PARENTHESIS => true, + T_CLOSE_SQUARE_BRACKET => true, + T_CLOSE_CURLY_BRACKET => true, + T_CLOSE_SHORT_ARRAY => true, + T_OPEN_TAG => true, + T_CLOSE_TAG => true, + ]; + + $inTernary = false; + $lastEndToken = null; + + for ($scopeCloser = ($arrow + 1); $scopeCloser < $numTokens; $scopeCloser++) { + // Arrow function closer should never be shared with the closer of a match + // control structure. + if (isset($this->tokens[$scopeCloser]['scope_closer'], $this->tokens[$scopeCloser]['scope_condition']) === true + && $scopeCloser === $this->tokens[$scopeCloser]['scope_closer'] + && $this->tokens[$this->tokens[$scopeCloser]['scope_condition']]['code'] === T_MATCH + ) { + if ($arrow < $this->tokens[$scopeCloser]['scope_condition']) { + // Match in return value of arrow function. Move on to the next token. + continue; + } + + // Arrow function as return value for the last match case without trailing comma. + if ($lastEndToken !== null) { + $scopeCloser = $lastEndToken; + break; + } + + for ($lastNonEmpty = ($scopeCloser - 1); $lastNonEmpty > $arrow; $lastNonEmpty--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$lastNonEmpty]['code']]) === false) { + $scopeCloser = $lastNonEmpty; + break 2; + } + } + } + + if (isset($endTokens[$this->tokens[$scopeCloser]['code']]) === true) { + if ($lastEndToken !== null + && ((isset($this->tokens[$scopeCloser]['parenthesis_opener']) === true + && $this->tokens[$scopeCloser]['parenthesis_opener'] < $arrow) + || (isset($this->tokens[$scopeCloser]['bracket_opener']) === true + && $this->tokens[$scopeCloser]['bracket_opener'] < $arrow)) + ) { + for ($lastNonEmpty = ($scopeCloser - 1); $lastNonEmpty > $arrow; $lastNonEmpty--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$lastNonEmpty]['code']]) === false) { + $scopeCloser = $lastNonEmpty; + break; + } + } + } + + break; + } + + if ($inTernary === false + && isset($this->tokens[$scopeCloser]['scope_closer'], $this->tokens[$scopeCloser]['scope_condition']) === true + && $scopeCloser === $this->tokens[$scopeCloser]['scope_closer'] + && $this->tokens[$this->tokens[$scopeCloser]['scope_condition']]['code'] === T_FN + ) { + // Found a nested arrow function that already has the closer set and is in + // the same scope as us, so we can use its closer. + break; + } + + if (isset($this->tokens[$scopeCloser]['scope_closer']) === true + && $this->tokens[$scopeCloser]['code'] !== T_INLINE_ELSE + && $this->tokens[$scopeCloser]['code'] !== T_END_HEREDOC + && $this->tokens[$scopeCloser]['code'] !== T_END_NOWDOC + ) { + // We minus 1 here in case the closer can be shared with us. + $scopeCloser = ($this->tokens[$scopeCloser]['scope_closer'] - 1); + continue; + } + + if (isset($this->tokens[$scopeCloser]['parenthesis_closer']) === true) { + $scopeCloser = $this->tokens[$scopeCloser]['parenthesis_closer']; + $lastEndToken = $scopeCloser; + continue; + } + + if (isset($this->tokens[$scopeCloser]['bracket_closer']) === true) { + $scopeCloser = $this->tokens[$scopeCloser]['bracket_closer']; + $lastEndToken = $scopeCloser; + continue; + } + + if ($this->tokens[$scopeCloser]['code'] === T_INLINE_THEN) { + $inTernary = true; + continue; + } + + if ($this->tokens[$scopeCloser]['code'] === T_INLINE_ELSE) { + if ($inTernary === false) { + break; + } + + $inTernary = false; + continue; + } + }//end for + + if ($scopeCloser !== $numTokens) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t=> token $i on line $line processed as arrow function".PHP_EOL; + echo "\t\t* scope opener set to $arrow *".PHP_EOL; + echo "\t\t* scope closer set to $scopeCloser *".PHP_EOL; + echo "\t\t* parenthesis opener set to $x *".PHP_EOL; + echo "\t\t* parenthesis closer set to $closer *".PHP_EOL; + } + + $this->tokens[$i]['code'] = T_FN; + $this->tokens[$i]['type'] = 'T_FN'; + $this->tokens[$i]['scope_condition'] = $i; + $this->tokens[$i]['scope_opener'] = $arrow; + $this->tokens[$i]['scope_closer'] = $scopeCloser; + $this->tokens[$i]['parenthesis_owner'] = $i; + $this->tokens[$i]['parenthesis_opener'] = $x; + $this->tokens[$i]['parenthesis_closer'] = $closer; + + $this->tokens[$arrow]['code'] = T_FN_ARROW; + $this->tokens[$arrow]['type'] = 'T_FN_ARROW'; + + $this->tokens[$arrow]['scope_condition'] = $i; + $this->tokens[$arrow]['scope_opener'] = $arrow; + $this->tokens[$arrow]['scope_closer'] = $scopeCloser; + $this->tokens[$scopeCloser]['scope_condition'] = $i; + $this->tokens[$scopeCloser]['scope_opener'] = $arrow; + $this->tokens[$scopeCloser]['scope_closer'] = $scopeCloser; + + $opener = $this->tokens[$i]['parenthesis_opener']; + $closer = $this->tokens[$i]['parenthesis_closer']; + $this->tokens[$opener]['parenthesis_owner'] = $i; + $this->tokens[$closer]['parenthesis_owner'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$arrow]['line']; + echo "\t\t* token $arrow on line $line changed from T_DOUBLE_ARROW to T_FN_ARROW".PHP_EOL; + } + }//end if + }//end if + }//end if + + // If after all that, the extra tokens are not set, this is not an arrow function. + if (isset($this->tokens[$i]['scope_closer']) === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t=> token $i on line $line is not an arrow function".PHP_EOL; + echo "\t\t* token changed from T_FN to T_STRING".PHP_EOL; + } + + $this->tokens[$i]['code'] = T_STRING; + $this->tokens[$i]['type'] = 'T_STRING'; + } + } else if ($this->tokens[$i]['code'] === T_OPEN_SQUARE_BRACKET) { + if (isset($this->tokens[$i]['bracket_closer']) === false) { + continue; + } + + // Unless there is a variable or a bracket before this token, + // it is the start of an array being defined using the short syntax. + $isShortArray = false; + $allowed = [ + T_CLOSE_SQUARE_BRACKET => T_CLOSE_SQUARE_BRACKET, + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS, + T_VARIABLE => T_VARIABLE, + T_OBJECT_OPERATOR => T_OBJECT_OPERATOR, + T_NULLSAFE_OBJECT_OPERATOR => T_NULLSAFE_OBJECT_OPERATOR, + T_STRING => T_STRING, + T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING, + T_DOUBLE_QUOTED_STRING => T_DOUBLE_QUOTED_STRING, + ]; + $allowed += Util\Tokens::$magicConstants; + + for ($x = ($i - 1); $x >= 0; $x--) { + // If we hit a scope opener, the statement has ended + // without finding anything, so it's probably an array + // using PHP 7.1 short list syntax. + if (isset($this->tokens[$x]['scope_opener']) === true) { + $isShortArray = true; + break; + } + + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + if (isset($allowed[$this->tokens[$x]['code']]) === false) { + $isShortArray = true; + } + + break; + } + } + + if ($isShortArray === true) { + $this->tokens[$i]['code'] = T_OPEN_SHORT_ARRAY; + $this->tokens[$i]['type'] = 'T_OPEN_SHORT_ARRAY'; + + $closer = $this->tokens[$i]['bracket_closer']; + $this->tokens[$closer]['code'] = T_CLOSE_SHORT_ARRAY; + $this->tokens[$closer]['type'] = 'T_CLOSE_SHORT_ARRAY'; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t* token $i on line $line changed from T_OPEN_SQUARE_BRACKET to T_OPEN_SHORT_ARRAY".PHP_EOL; + $line = $this->tokens[$closer]['line']; + echo "\t* token $closer on line $line changed from T_CLOSE_SQUARE_BRACKET to T_CLOSE_SHORT_ARRAY".PHP_EOL; + } + } + + continue; + } else if ($this->tokens[$i]['code'] === T_MATCH) { + if (isset($this->tokens[$i]['scope_opener'], $this->tokens[$i]['scope_closer']) === false) { + // Not a match expression after all. + $this->tokens[$i]['code'] = T_STRING; + $this->tokens[$i]['type'] = 'T_STRING'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $i changed from T_MATCH to T_STRING".PHP_EOL; + } + + if (isset($this->tokens[$i]['parenthesis_opener'], $this->tokens[$i]['parenthesis_closer']) === true) { + $opener = $this->tokens[$i]['parenthesis_opener']; + $closer = $this->tokens[$i]['parenthesis_closer']; + unset( + $this->tokens[$opener]['parenthesis_owner'], + $this->tokens[$closer]['parenthesis_owner'] + ); + unset( + $this->tokens[$i]['parenthesis_opener'], + $this->tokens[$i]['parenthesis_closer'], + $this->tokens[$i]['parenthesis_owner'] + ); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* cleaned parenthesis of token $i *".PHP_EOL; + } + } + } else { + // Retokenize the double arrows for match expression cases to `T_MATCH_ARROW`. + $searchFor = [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET, + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_OPEN_SHORT_ARRAY => T_OPEN_SHORT_ARRAY, + T_DOUBLE_ARROW => T_DOUBLE_ARROW, + ]; + $searchFor += Util\Tokens::$scopeOpeners; + + for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) { + if (isset($searchFor[$this->tokens[$x]['code']]) === false) { + continue; + } + + if (isset($this->tokens[$x]['scope_closer']) === true) { + $x = $this->tokens[$x]['scope_closer']; + continue; + } + + if (isset($this->tokens[$x]['parenthesis_closer']) === true) { + $x = $this->tokens[$x]['parenthesis_closer']; + continue; + } + + if (isset($this->tokens[$x]['bracket_closer']) === true) { + $x = $this->tokens[$x]['bracket_closer']; + continue; + } + + // This must be a double arrow, but make sure anyhow. + if ($this->tokens[$x]['code'] === T_DOUBLE_ARROW) { + $this->tokens[$x]['code'] = T_MATCH_ARROW; + $this->tokens[$x]['type'] = 'T_MATCH_ARROW'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $x changed from T_DOUBLE_ARROW to T_MATCH_ARROW".PHP_EOL; + } + } + }//end for + }//end if + + continue; + } else if ($this->tokens[$i]['code'] === T_BITWISE_OR + || $this->tokens[$i]['code'] === T_BITWISE_AND + ) { + /* + Convert "|" to T_TYPE_UNION or leave as T_BITWISE_OR. + Convert "&" to T_TYPE_INTERSECTION or leave as T_BITWISE_AND. + */ + + $allowed = [ + T_STRING => T_STRING, + T_CALLABLE => T_CALLABLE, + T_SELF => T_SELF, + T_PARENT => T_PARENT, + T_STATIC => T_STATIC, + T_FALSE => T_FALSE, + T_NULL => T_NULL, + T_NAMESPACE => T_NAMESPACE, + T_NS_SEPARATOR => T_NS_SEPARATOR, + ]; + + $suspectedType = null; + $typeTokenCount = 0; + + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true) { + continue; + } + + if (isset($allowed[$this->tokens[$x]['code']]) === true) { + ++$typeTokenCount; + continue; + } + + if ($typeTokenCount > 0 + && ($this->tokens[$x]['code'] === T_BITWISE_AND + || $this->tokens[$x]['code'] === T_ELLIPSIS) + ) { + // Skip past reference and variadic indicators for parameter types. + continue; + } + + if ($this->tokens[$x]['code'] === T_VARIABLE) { + // Parameter/Property defaults can not contain variables, so this could be a type. + $suspectedType = 'property or parameter'; + break; + } + + if ($this->tokens[$x]['code'] === T_DOUBLE_ARROW) { + // Possible arrow function. + $suspectedType = 'return'; + break; + } + + if ($this->tokens[$x]['code'] === T_SEMICOLON) { + // Possible abstract method or interface method. + $suspectedType = 'return'; + break; + } + + if ($this->tokens[$x]['code'] === T_OPEN_CURLY_BRACKET + && isset($this->tokens[$x]['scope_condition']) === true + && $this->tokens[$this->tokens[$x]['scope_condition']]['code'] === T_FUNCTION + ) { + $suspectedType = 'return'; + } + + break; + }//end for + + if ($typeTokenCount === 0 || isset($suspectedType) === false) { + // Definitely not a union or intersection type, move on. + continue; + } + + $typeTokenCount = 0; + $typeOperators = [$i]; + $confirmed = false; + + for ($x = ($i - 1); $x >= 0; $x--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true) { + continue; + } + + if (isset($allowed[$this->tokens[$x]['code']]) === true) { + ++$typeTokenCount; + continue; + } + + // Union and intersection types can't use the nullable operator, but be tolerant to parse errors. + if ($typeTokenCount > 0 && $this->tokens[$x]['code'] === T_NULLABLE) { + continue; + } + + if ($this->tokens[$x]['code'] === T_BITWISE_OR || $this->tokens[$x]['code'] === T_BITWISE_AND) { + $typeOperators[] = $x; + continue; + } + + if ($suspectedType === 'return' && $this->tokens[$x]['code'] === T_COLON) { + $confirmed = true; + break; + } + + if ($suspectedType === 'property or parameter' + && (isset(Util\Tokens::$scopeModifiers[$this->tokens[$x]['code']]) === true + || $this->tokens[$x]['code'] === T_VAR + || $this->tokens[$x]['code'] === T_READONLY) + ) { + // This will also confirm constructor property promotion parameters, but that's fine. + $confirmed = true; + } + + break; + }//end for + + if ($confirmed === false + && $suspectedType === 'property or parameter' + && isset($this->tokens[$i]['nested_parenthesis']) === true + ) { + $parens = $this->tokens[$i]['nested_parenthesis']; + $last = end($parens); + + if (isset($this->tokens[$last]['parenthesis_owner']) === true + && $this->tokens[$this->tokens[$last]['parenthesis_owner']]['code'] === T_FUNCTION + ) { + $confirmed = true; + } else { + // No parenthesis owner set, this may be an arrow function which has not yet + // had additional processing done. + if (isset($this->tokens[$last]['parenthesis_opener']) === true) { + for ($x = ($this->tokens[$last]['parenthesis_opener'] - 1); $x >= 0; $x--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true) { + continue; + } + + break; + } + + if ($this->tokens[$x]['code'] === T_FN) { + for (--$x; $x >= 0; $x--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true + || $this->tokens[$x]['code'] === T_BITWISE_AND + ) { + continue; + } + + break; + } + + if ($this->tokens[$x]['code'] !== T_FUNCTION) { + $confirmed = true; + } + } + }//end if + }//end if + + unset($parens, $last); + }//end if + + if ($confirmed === false) { + // Not a union or intersection type after all, move on. + continue; + } + + foreach ($typeOperators as $x) { + if ($this->tokens[$x]['code'] === T_BITWISE_OR) { + $this->tokens[$x]['code'] = T_TYPE_UNION; + $this->tokens[$x]['type'] = 'T_TYPE_UNION'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$x]['line']; + echo "\t* token $x on line $line changed from T_BITWISE_OR to T_TYPE_UNION".PHP_EOL; + } + } else { + $this->tokens[$x]['code'] = T_TYPE_INTERSECTION; + $this->tokens[$x]['type'] = 'T_TYPE_INTERSECTION'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$x]['line']; + echo "\t* token $x on line $line changed from T_BITWISE_AND to T_TYPE_INTERSECTION".PHP_EOL; + } + } + } + + continue; + } else if ($this->tokens[$i]['code'] === T_STATIC) { + for ($x = ($i - 1); $x > 0; $x--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + break; + } + } + + if ($this->tokens[$x]['code'] === T_INSTANCEOF) { + $this->tokens[$i]['code'] = T_STRING; + $this->tokens[$i]['type'] = 'T_STRING'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t* token $i on line $line changed from T_STATIC to T_STRING".PHP_EOL; + } + } + + continue; + } else if ($this->tokens[$i]['code'] === T_TRUE + || $this->tokens[$i]['code'] === T_FALSE + || $this->tokens[$i]['code'] === T_NULL + ) { + for ($x = ($i + 1); $i < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + // Non-whitespace content. + break; + } + } + + if (isset($this->tstringContexts[$this->tokens[$x]['code']]) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + $type = $this->tokens[$i]['type']; + echo "\t* token $i on line $line changed from $type to T_STRING".PHP_EOL; + } + + $this->tokens[$i]['code'] = T_STRING; + $this->tokens[$i]['type'] = 'T_STRING'; + } + }//end if + + if (($this->tokens[$i]['code'] !== T_CASE + && $this->tokens[$i]['code'] !== T_DEFAULT) + || isset($this->tokens[$i]['scope_opener']) === false + ) { + // Only interested in CASE and DEFAULT statements from here on in. + continue; + } + + $scopeOpener = $this->tokens[$i]['scope_opener']; + $scopeCloser = $this->tokens[$i]['scope_closer']; + + // If the first char after the opener is a curly brace + // and that brace has been ignored, it is actually + // opening this case statement and the opener and closer are + // probably set incorrectly. + for ($x = ($scopeOpener + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + // Non-whitespace content. + break; + } + } + + if ($this->tokens[$x]['code'] === T_CASE || $this->tokens[$x]['code'] === T_DEFAULT) { + // Special case for multiple CASE statements that share the same + // closer. Because we are going backwards through the file, this next + // CASE statement is already fixed, so just use its closer and don't + // worry about fixing anything. + $newCloser = $this->tokens[$x]['scope_closer']; + $this->tokens[$i]['scope_closer'] = $newCloser; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $oldType = $this->tokens[$scopeCloser]['type']; + $newType = $this->tokens[$newCloser]['type']; + $line = $this->tokens[$i]['line']; + echo "\t* token $i (T_CASE) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL; + } + + continue; + } + + if ($this->tokens[$x]['code'] !== T_OPEN_CURLY_BRACKET + || isset($this->tokens[$x]['scope_condition']) === true + ) { + // Not a CASE/DEFAULT with a curly brace opener. + continue; + } + + // The closer for this CASE/DEFAULT should be the closing curly brace and + // not whatever it already is. The opener needs to be the opening curly + // brace so everything matches up. + $newCloser = $this->tokens[$x]['bracket_closer']; + foreach ([$i, $x, $newCloser] as $index) { + $this->tokens[$index]['scope_condition'] = $i; + $this->tokens[$index]['scope_opener'] = $x; + $this->tokens[$index]['scope_closer'] = $newCloser; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + $tokenType = $this->tokens[$i]['type']; + + $oldType = $this->tokens[$scopeOpener]['type']; + $newType = $this->tokens[$x]['type']; + echo "\t* token $i ($tokenType) on line $line opener changed from $scopeOpener ($oldType) to $x ($newType)".PHP_EOL; + + $oldType = $this->tokens[$scopeCloser]['type']; + $newType = $this->tokens[$newCloser]['type']; + echo "\t* token $i ($tokenType) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL; + } + + if ($this->tokens[$scopeOpener]['scope_condition'] === $i) { + unset($this->tokens[$scopeOpener]['scope_condition']); + unset($this->tokens[$scopeOpener]['scope_opener']); + unset($this->tokens[$scopeOpener]['scope_closer']); + } + + if ($this->tokens[$scopeCloser]['scope_condition'] === $i) { + unset($this->tokens[$scopeCloser]['scope_condition']); + unset($this->tokens[$scopeCloser]['scope_opener']); + unset($this->tokens[$scopeCloser]['scope_closer']); + } else { + // We were using a shared closer. All tokens that were + // sharing this closer with us, except for the scope condition + // and it's opener, need to now point to the new closer. + $condition = $this->tokens[$scopeCloser]['scope_condition']; + $start = ($this->tokens[$condition]['scope_opener'] + 1); + for ($y = $start; $y < $scopeCloser; $y++) { + if (isset($this->tokens[$y]['scope_closer']) === true + && $this->tokens[$y]['scope_closer'] === $scopeCloser + ) { + $this->tokens[$y]['scope_closer'] = $newCloser; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$y]['line']; + $tokenType = $this->tokens[$y]['type']; + $oldType = $this->tokens[$scopeCloser]['type']; + $newType = $this->tokens[$newCloser]['type']; + echo "\t\t* token $y ($tokenType) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL; + } + } + } + }//end if + + unset($this->tokens[$x]['bracket_opener']); + unset($this->tokens[$x]['bracket_closer']); + unset($this->tokens[$newCloser]['bracket_opener']); + unset($this->tokens[$newCloser]['bracket_closer']); + $this->tokens[$scopeCloser]['conditions'][] = $i; + + // Now fix up all the tokens that think they are + // inside the CASE/DEFAULT statement when they are really outside. + for ($x = $newCloser; $x < $scopeCloser; $x++) { + foreach ($this->tokens[$x]['conditions'] as $num => $oldCond) { + if ($oldCond === $this->tokens[$i]['code']) { + $oldConditions = $this->tokens[$x]['conditions']; + unset($this->tokens[$x]['conditions'][$num]); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + $oldConds = ''; + foreach ($oldConditions as $condition) { + $oldConds .= Util\Tokens::tokenName($condition).','; + } + + $oldConds = rtrim($oldConds, ','); + + $newConds = ''; + foreach ($this->tokens[$x]['conditions'] as $condition) { + $newConds .= Util\Tokens::tokenName($condition).','; + } + + $newConds = rtrim($newConds, ','); + + echo "\t\t* cleaned $x ($type) *".PHP_EOL; + echo "\t\t\t=> conditions changed from $oldConds to $newConds".PHP_EOL; + } + + break; + }//end if + }//end foreach + }//end for + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END ADDITIONAL PHP PROCESSING ***".PHP_EOL; + } + + }//end processAdditional() + + + /** + * Takes a token produced from token_get_all() and produces a + * more uniform token. + * + * @param string|array $token The token to convert. + * + * @return array The new token. + */ + public static function standardiseToken($token) + { + if (isset($token[1]) === false) { + if (isset(self::$resolveTokenCache[$token[0]]) === true) { + return self::$resolveTokenCache[$token[0]]; + } + } else { + $cacheKey = null; + if ($token[0] === T_STRING) { + $cacheKey = strtolower($token[1]); + } else if ($token[0] !== T_CURLY_OPEN) { + $cacheKey = $token[0]; + } + + if ($cacheKey !== null && isset(self::$resolveTokenCache[$cacheKey]) === true) { + $newToken = self::$resolveTokenCache[$cacheKey]; + $newToken['content'] = $token[1]; + return $newToken; + } + } + + if (isset($token[1]) === false) { + return self::resolveSimpleToken($token[0]); + } + + if ($token[0] === T_STRING) { + switch ($cacheKey) { + case 'false': + $newToken['type'] = 'T_FALSE'; + break; + case 'true': + $newToken['type'] = 'T_TRUE'; + break; + case 'null': + $newToken['type'] = 'T_NULL'; + break; + case 'self': + $newToken['type'] = 'T_SELF'; + break; + case 'parent': + $newToken['type'] = 'T_PARENT'; + break; + default: + $newToken['type'] = 'T_STRING'; + break; + } + + $newToken['code'] = constant($newToken['type']); + + self::$resolveTokenCache[$cacheKey] = $newToken; + } else if ($token[0] === T_CURLY_OPEN) { + $newToken = [ + 'code' => T_OPEN_CURLY_BRACKET, + 'type' => 'T_OPEN_CURLY_BRACKET', + ]; + } else { + $newToken = [ + 'code' => $token[0], + 'type' => Util\Tokens::tokenName($token[0]), + ]; + + self::$resolveTokenCache[$token[0]] = $newToken; + }//end if + + $newToken['content'] = $token[1]; + return $newToken; + + }//end standardiseToken() + + + /** + * Converts simple tokens into a format that conforms to complex tokens + * produced by token_get_all(). + * + * Simple tokens are tokens that are not in array form when produced from + * token_get_all(). + * + * @param string $token The simple token to convert. + * + * @return array The new token in array format. + */ + public static function resolveSimpleToken($token) + { + $newToken = []; + + switch ($token) { + case '{': + $newToken['type'] = 'T_OPEN_CURLY_BRACKET'; + break; + case '}': + $newToken['type'] = 'T_CLOSE_CURLY_BRACKET'; + break; + case '[': + $newToken['type'] = 'T_OPEN_SQUARE_BRACKET'; + break; + case ']': + $newToken['type'] = 'T_CLOSE_SQUARE_BRACKET'; + break; + case '(': + $newToken['type'] = 'T_OPEN_PARENTHESIS'; + break; + case ')': + $newToken['type'] = 'T_CLOSE_PARENTHESIS'; + break; + case ':': + $newToken['type'] = 'T_COLON'; + break; + case '.': + $newToken['type'] = 'T_STRING_CONCAT'; + break; + case ';': + $newToken['type'] = 'T_SEMICOLON'; + break; + case '=': + $newToken['type'] = 'T_EQUAL'; + break; + case '*': + $newToken['type'] = 'T_MULTIPLY'; + break; + case '/': + $newToken['type'] = 'T_DIVIDE'; + break; + case '+': + $newToken['type'] = 'T_PLUS'; + break; + case '-': + $newToken['type'] = 'T_MINUS'; + break; + case '%': + $newToken['type'] = 'T_MODULUS'; + break; + case '^': + $newToken['type'] = 'T_BITWISE_XOR'; + break; + case '&': + $newToken['type'] = 'T_BITWISE_AND'; + break; + case '|': + $newToken['type'] = 'T_BITWISE_OR'; + break; + case '~': + $newToken['type'] = 'T_BITWISE_NOT'; + break; + case '<': + $newToken['type'] = 'T_LESS_THAN'; + break; + case '>': + $newToken['type'] = 'T_GREATER_THAN'; + break; + case '!': + $newToken['type'] = 'T_BOOLEAN_NOT'; + break; + case ',': + $newToken['type'] = 'T_COMMA'; + break; + case '@': + $newToken['type'] = 'T_ASPERAND'; + break; + case '$': + $newToken['type'] = 'T_DOLLAR'; + break; + case '`': + $newToken['type'] = 'T_BACKTICK'; + break; + default: + $newToken['type'] = 'T_NONE'; + break; + }//end switch + + $newToken['code'] = constant($newToken['type']); + $newToken['content'] = $token; + + self::$resolveTokenCache[$token] = $newToken; + return $newToken; + + }//end resolveSimpleToken() + + + /** + * Finds a "closer" token (closing parenthesis or square bracket for example) + * Handle parenthesis balancing while searching for closing token + * + * @param array $tokens The list of tokens to iterate searching the closing token (as returned by token_get_all) + * @param int $start The starting position + * @param string|string[] $openerTokens The opening character + * @param string $closerChar The closing character + * + * @return int|null The position of the closing token, if found. NULL otherwise. + */ + private function findCloser(array &$tokens, $start, $openerTokens, $closerChar) + { + $numTokens = count($tokens); + $stack = [0]; + $closer = null; + $openerTokens = (array) $openerTokens; + + for ($x = $start; $x < $numTokens; $x++) { + if (in_array($tokens[$x], $openerTokens, true) === true + || (is_array($tokens[$x]) === true && in_array($tokens[$x][1], $openerTokens, true) === true) + ) { + $stack[] = $x; + } else if ($tokens[$x] === $closerChar) { + array_pop($stack); + if (empty($stack) === true) { + $closer = $x; + break; + } + } + } + + return $closer; + + }//end findCloser() + + + /** + * PHP 8 attributes parser for PHP < 8 + * Handles single-line and multiline attributes. + * + * @param array $tokens The original array of tokens (as returned by token_get_all) + * @param int $stackPtr The current position in token array + * + * @return array|null The array of parsed attribute tokens + */ + private function parsePhpAttribute(array &$tokens, $stackPtr) + { + + $token = $tokens[$stackPtr]; + + $commentBody = substr($token[1], 2); + $subTokens = @token_get_all(' $subToken) { + if (is_array($subToken) === true + && $subToken[0] === T_COMMENT + && strpos($subToken[1], '#[') === 0 + ) { + $reparsed = $this->parsePhpAttribute($subTokens, $i); + if ($reparsed !== null) { + array_splice($subTokens, $i, 1, $reparsed); + } else { + $subToken[0] = T_ATTRIBUTE; + } + } + } + + array_splice($subTokens, 0, 1, [[T_ATTRIBUTE, '#[']]); + + // Go looking for the close bracket. + $bracketCloser = $this->findCloser($subTokens, 1, '[', ']'); + if (PHP_VERSION_ID < 80000 && $bracketCloser === null) { + foreach (array_slice($tokens, ($stackPtr + 1)) as $token) { + if (is_array($token) === true) { + $commentBody .= $token[1]; + } else { + $commentBody .= $token; + } + } + + $subTokens = @token_get_all('findCloser($subTokens, 1, '[', ']'); + if ($bracketCloser !== null) { + array_splice($tokens, ($stackPtr + 1), count($tokens), array_slice($subTokens, ($bracketCloser + 1))); + $subTokens = array_slice($subTokens, 0, ($bracketCloser + 1)); + } + } + + if ($bracketCloser === null) { + return null; + } + + return $subTokens; + + }//end parsePhpAttribute() + + + /** + * Creates a map for the attributes tokens that surround other tokens. + * + * @return void + */ + private function createAttributesNestingMap() + { + $map = []; + for ($i = 0; $i < $this->numTokens; $i++) { + if (isset($this->tokens[$i]['attribute_opener']) === true + && $i === $this->tokens[$i]['attribute_opener'] + ) { + if (empty($map) === false) { + $this->tokens[$i]['nested_attributes'] = $map; + } + + if (isset($this->tokens[$i]['attribute_closer']) === true) { + $map[$this->tokens[$i]['attribute_opener']] + = $this->tokens[$i]['attribute_closer']; + } + } else if (isset($this->tokens[$i]['attribute_closer']) === true + && $i === $this->tokens[$i]['attribute_closer'] + ) { + array_pop($map); + if (empty($map) === false) { + $this->tokens[$i]['nested_attributes'] = $map; + } + } else { + if (empty($map) === false) { + $this->tokens[$i]['nested_attributes'] = $map; + } + }//end if + }//end for + + }//end createAttributesNestingMap() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Tokenizers/Tokenizer.php b/vendor/squizlabs/php_codesniffer/src/Tokenizers/Tokenizer.php new file mode 100644 index 00000000..c79323cc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Tokenizers/Tokenizer.php @@ -0,0 +1,1732 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Exceptions\TokenizerException; +use PHP_CodeSniffer\Util; + +abstract class Tokenizer +{ + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + protected $config = null; + + /** + * The EOL char used in the content. + * + * @var string + */ + protected $eolChar = []; + + /** + * A token-based representation of the content. + * + * @var array + */ + protected $tokens = []; + + /** + * The number of tokens in the tokens array. + * + * @var integer + */ + protected $numTokens = 0; + + /** + * A list of tokens that are allowed to open a scope. + * + * @var array + */ + public $scopeOpeners = []; + + /** + * A list of tokens that end the scope. + * + * @var array + */ + public $endScopeTokens = []; + + /** + * Known lengths of tokens. + * + * @var array + */ + public $knownLengths = []; + + /** + * A list of lines being ignored due to error suppression comments. + * + * @var array + */ + public $ignoredLines = []; + + + /** + * Initialise and run the tokenizer. + * + * @param string $content The content to tokenize, + * @param \PHP_CodeSniffer\Config | null $config The config data for the run. + * @param string $eolChar The EOL char used in the content. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\TokenizerException If the file appears to be minified. + */ + public function __construct($content, $config, $eolChar='\n') + { + $this->eolChar = $eolChar; + + $this->config = $config; + $this->tokens = $this->tokenize($content); + + if ($config === null) { + return; + } + + $this->createPositionMap(); + $this->createTokenMap(); + $this->createParenthesisNestingMap(); + $this->createScopeMap(); + $this->createLevelMap(); + + // Allow the tokenizer to do additional processing if required. + $this->processAdditional(); + + }//end __construct() + + + /** + * Checks the content to see if it looks minified. + * + * @param string $content The content to tokenize. + * @param string $eolChar The EOL char used in the content. + * + * @return boolean + */ + protected function isMinifiedContent($content, $eolChar='\n') + { + // Minified files often have a very large number of characters per line + // and cause issues when tokenizing. + $numChars = strlen($content); + $numLines = (substr_count($content, $eolChar) + 1); + $average = ($numChars / $numLines); + if ($average > 100) { + return true; + } + + return false; + + }//end isMinifiedContent() + + + /** + * Gets the array of tokens. + * + * @return array + */ + public function getTokens() + { + return $this->tokens; + + }//end getTokens() + + + /** + * Creates an array of tokens when given some content. + * + * @param string $string The string to tokenize. + * + * @return array + */ + abstract protected function tokenize($string); + + + /** + * Performs additional processing after main tokenizing. + * + * @return void + */ + abstract protected function processAdditional(); + + + /** + * Sets token position information. + * + * Can also convert tabs into spaces. Each tab can represent between + * 1 and $width spaces, so this cannot be a straight string replace. + * + * @return void + */ + private function createPositionMap() + { + $currColumn = 1; + $lineNumber = 1; + $eolLen = strlen($this->eolChar); + $ignoring = null; + $inTests = defined('PHP_CODESNIFFER_IN_TESTS'); + + $checkEncoding = false; + if (function_exists('iconv_strlen') === true) { + $checkEncoding = true; + } + + $checkAnnotations = $this->config->annotations; + $encoding = $this->config->encoding; + $tabWidth = $this->config->tabWidth; + + $tokensWithTabs = [ + T_WHITESPACE => true, + T_COMMENT => true, + T_DOC_COMMENT => true, + T_DOC_COMMENT_WHITESPACE => true, + T_DOC_COMMENT_STRING => true, + T_CONSTANT_ENCAPSED_STRING => true, + T_DOUBLE_QUOTED_STRING => true, + T_HEREDOC => true, + T_NOWDOC => true, + T_INLINE_HTML => true, + ]; + + $this->numTokens = count($this->tokens); + for ($i = 0; $i < $this->numTokens; $i++) { + $this->tokens[$i]['line'] = $lineNumber; + $this->tokens[$i]['column'] = $currColumn; + + if (isset($this->knownLengths[$this->tokens[$i]['code']]) === true) { + // There are no tabs in the tokens we know the length of. + $length = $this->knownLengths[$this->tokens[$i]['code']]; + $currColumn += $length; + } else if ($tabWidth === 0 + || isset($tokensWithTabs[$this->tokens[$i]['code']]) === false + || strpos($this->tokens[$i]['content'], "\t") === false + ) { + // There are no tabs in this content, or we aren't replacing them. + if ($checkEncoding === true) { + // Not using the default encoding, so take a bit more care. + $oldLevel = error_reporting(); + error_reporting(0); + $length = iconv_strlen($this->tokens[$i]['content'], $encoding); + error_reporting($oldLevel); + + if ($length === false) { + // String contained invalid characters, so revert to default. + $length = strlen($this->tokens[$i]['content']); + } + } else { + $length = strlen($this->tokens[$i]['content']); + } + + $currColumn += $length; + } else { + $this->replaceTabsInToken($this->tokens[$i]); + $length = $this->tokens[$i]['length']; + $currColumn += $length; + }//end if + + $this->tokens[$i]['length'] = $length; + + if (isset($this->knownLengths[$this->tokens[$i]['code']]) === false + && strpos($this->tokens[$i]['content'], $this->eolChar) !== false + ) { + $lineNumber++; + $currColumn = 1; + + // Newline chars are not counted in the token length. + $this->tokens[$i]['length'] -= $eolLen; + } + + if ($this->tokens[$i]['code'] === T_COMMENT + || $this->tokens[$i]['code'] === T_DOC_COMMENT_STRING + || $this->tokens[$i]['code'] === T_DOC_COMMENT_TAG + || ($inTests === true && $this->tokens[$i]['code'] === T_INLINE_HTML) + ) { + $commentText = ltrim($this->tokens[$i]['content'], " \t/*#"); + $commentText = rtrim($commentText, " */\t\r\n"); + $commentTextLower = strtolower($commentText); + if (strpos($commentText, '@codingStandards') !== false) { + // If this comment is the only thing on the line, it tells us + // to ignore the following line. If the line contains other content + // then we are just ignoring this one single line. + $ownLine = false; + if ($i > 0) { + for ($prev = ($i - 1); $prev >= 0; $prev--) { + if ($this->tokens[$prev]['code'] === T_WHITESPACE) { + continue; + } + + break; + } + + if ($this->tokens[$prev]['line'] !== $this->tokens[$i]['line']) { + $ownLine = true; + } + } + + if ($ignoring === null + && strpos($commentText, '@codingStandardsIgnoreStart') !== false + ) { + $ignoring = ['.all' => true]; + if ($ownLine === true) { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + } else if ($ignoring !== null + && strpos($commentText, '@codingStandardsIgnoreEnd') !== false + ) { + if ($ownLine === true) { + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + } else { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + + $ignoring = null; + } else if ($ignoring === null + && strpos($commentText, '@codingStandardsIgnoreLine') !== false + ) { + $ignoring = ['.all' => true]; + if ($ownLine === true) { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + $this->ignoredLines[($this->tokens[$i]['line'] + 1)] = $ignoring; + } else { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + + $ignoring = null; + }//end if + } else if (substr($commentTextLower, 0, 6) === 'phpcs:' + || substr($commentTextLower, 0, 7) === '@phpcs:' + ) { + // If the @phpcs: syntax is being used, strip the @ to make + // comparisons easier. + if ($commentText[0] === '@') { + $commentText = substr($commentText, 1); + $commentTextLower = strtolower($commentText); + } + + // If there is a comment on the end, strip it off. + $commentStart = strpos($commentTextLower, ' --'); + if ($commentStart !== false) { + $commentText = substr($commentText, 0, $commentStart); + $commentTextLower = strtolower($commentText); + } + + // If this comment is the only thing on the line, it tells us + // to ignore the following line. If the line contains other content + // then we are just ignoring this one single line. + $lineHasOtherContent = false; + $lineHasOtherTokens = false; + if ($i > 0) { + for ($prev = ($i - 1); $prev > 0; $prev--) { + if ($this->tokens[$prev]['line'] !== $this->tokens[$i]['line']) { + // Changed lines. + break; + } + + if ($this->tokens[$prev]['code'] === T_WHITESPACE + || $this->tokens[$prev]['code'] === T_DOC_COMMENT_WHITESPACE + || ($this->tokens[$prev]['code'] === T_INLINE_HTML + && trim($this->tokens[$prev]['content']) === '') + ) { + continue; + } + + $lineHasOtherTokens = true; + + if ($this->tokens[$prev]['code'] === T_OPEN_TAG + || $this->tokens[$prev]['code'] === T_DOC_COMMENT_STAR + ) { + continue; + } + + $lineHasOtherContent = true; + break; + }//end for + + $changedLines = false; + for ($next = $i; $next < $this->numTokens; $next++) { + if ($changedLines === true) { + // Changed lines. + break; + } + + if (isset($this->knownLengths[$this->tokens[$next]['code']]) === false + && strpos($this->tokens[$next]['content'], $this->eolChar) !== false + ) { + // Last token on the current line. + $changedLines = true; + } + + if ($next === $i) { + continue; + } + + if ($this->tokens[$next]['code'] === T_WHITESPACE + || $this->tokens[$next]['code'] === T_DOC_COMMENT_WHITESPACE + || ($this->tokens[$next]['code'] === T_INLINE_HTML + && trim($this->tokens[$next]['content']) === '') + ) { + continue; + } + + $lineHasOtherTokens = true; + + if ($this->tokens[$next]['code'] === T_CLOSE_TAG) { + continue; + } + + $lineHasOtherContent = true; + break; + }//end for + }//end if + + if (substr($commentTextLower, 0, 9) === 'phpcs:set') { + // Ignore standards for complete lines that change sniff settings. + if ($lineHasOtherTokens === false) { + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + } + + // Need to maintain case here, to get the correct sniff code. + $parts = explode(' ', substr($commentText, 10)); + if (count($parts) >= 2) { + $sniffParts = explode('.', $parts[0]); + if (count($sniffParts) >= 3) { + $this->tokens[$i]['sniffCode'] = array_shift($parts); + $this->tokens[$i]['sniffProperty'] = array_shift($parts); + $this->tokens[$i]['sniffPropertyValue'] = rtrim(implode(' ', $parts), " */\r\n"); + } + } + + $this->tokens[$i]['code'] = T_PHPCS_SET; + $this->tokens[$i]['type'] = 'T_PHPCS_SET'; + } else if (substr($commentTextLower, 0, 16) === 'phpcs:ignorefile') { + // The whole file will be ignored, but at least set the correct token. + $this->tokens[$i]['code'] = T_PHPCS_IGNORE_FILE; + $this->tokens[$i]['type'] = 'T_PHPCS_IGNORE_FILE'; + } else if (substr($commentTextLower, 0, 13) === 'phpcs:disable') { + if ($lineHasOtherContent === false) { + // Completely ignore the comment line. + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + } + + if ($ignoring === null) { + $ignoring = []; + } + + $disabledSniffs = []; + + $additionalText = substr($commentText, 14); + if (empty($additionalText) === true) { + $ignoring = ['.all' => true]; + } else { + $parts = explode(',', $additionalText); + foreach ($parts as $sniffCode) { + $sniffCode = trim($sniffCode); + $disabledSniffs[$sniffCode] = true; + $ignoring[$sniffCode] = true; + + // This newly disabled sniff might be disabling an existing + // enabled exception that we are tracking. + if (isset($ignoring['.except']) === true) { + foreach (array_keys($ignoring['.except']) as $ignoredSniffCode) { + if ($ignoredSniffCode === $sniffCode + || strpos($ignoredSniffCode, $sniffCode.'.') === 0 + ) { + unset($ignoring['.except'][$ignoredSniffCode]); + } + } + + if (empty($ignoring['.except']) === true) { + unset($ignoring['.except']); + } + } + }//end foreach + }//end if + + $this->tokens[$i]['code'] = T_PHPCS_DISABLE; + $this->tokens[$i]['type'] = 'T_PHPCS_DISABLE'; + $this->tokens[$i]['sniffCodes'] = $disabledSniffs; + } else if (substr($commentTextLower, 0, 12) === 'phpcs:enable') { + if ($ignoring !== null) { + $enabledSniffs = []; + + $additionalText = substr($commentText, 13); + if (empty($additionalText) === true) { + $ignoring = null; + } else { + $parts = explode(',', $additionalText); + foreach ($parts as $sniffCode) { + $sniffCode = trim($sniffCode); + $enabledSniffs[$sniffCode] = true; + + // This new enabled sniff might remove previously disabled + // sniffs if it is actually a standard or category of sniffs. + foreach (array_keys($ignoring) as $ignoredSniffCode) { + if ($ignoredSniffCode === $sniffCode + || strpos($ignoredSniffCode, $sniffCode.'.') === 0 + ) { + unset($ignoring[$ignoredSniffCode]); + } + } + + // This new enabled sniff might be able to clear up + // previously enabled sniffs if it is actually a standard or + // category of sniffs. + if (isset($ignoring['.except']) === true) { + foreach (array_keys($ignoring['.except']) as $ignoredSniffCode) { + if ($ignoredSniffCode === $sniffCode + || strpos($ignoredSniffCode, $sniffCode.'.') === 0 + ) { + unset($ignoring['.except'][$ignoredSniffCode]); + } + } + } + }//end foreach + + if (empty($ignoring) === true) { + $ignoring = null; + } else { + if (isset($ignoring['.except']) === true) { + $ignoring['.except'] += $enabledSniffs; + } else { + $ignoring['.except'] = $enabledSniffs; + } + } + }//end if + + if ($lineHasOtherContent === false) { + // Completely ignore the comment line. + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + } else { + // The comment is on the same line as the code it is ignoring, + // so respect the new ignore rules. + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + + $this->tokens[$i]['sniffCodes'] = $enabledSniffs; + }//end if + + $this->tokens[$i]['code'] = T_PHPCS_ENABLE; + $this->tokens[$i]['type'] = 'T_PHPCS_ENABLE'; + } else if (substr($commentTextLower, 0, 12) === 'phpcs:ignore') { + $ignoreRules = []; + + $additionalText = substr($commentText, 13); + if (empty($additionalText) === true) { + $ignoreRules = ['.all' => true]; + } else { + $parts = explode(',', $additionalText); + foreach ($parts as $sniffCode) { + $ignoreRules[trim($sniffCode)] = true; + } + } + + $this->tokens[$i]['code'] = T_PHPCS_IGNORE; + $this->tokens[$i]['type'] = 'T_PHPCS_IGNORE'; + $this->tokens[$i]['sniffCodes'] = $ignoreRules; + + if ($ignoring !== null) { + $ignoreRules += $ignoring; + } + + if ($lineHasOtherContent === false) { + // Completely ignore the comment line, and set the following + // line to include the ignore rules we've set. + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + $this->ignoredLines[($this->tokens[$i]['line'] + 1)] = $ignoreRules; + } else { + // The comment is on the same line as the code it is ignoring, + // so respect the ignore rules it set. + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoreRules; + } + }//end if + }//end if + }//end if + + if ($ignoring !== null && isset($this->ignoredLines[$this->tokens[$i]['line']]) === false) { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + }//end for + + // If annotations are being ignored, we clear out all the ignore rules + // but leave the annotations tokenized as normal. + if ($checkAnnotations === false) { + $this->ignoredLines = []; + } + + }//end createPositionMap() + + + /** + * Replaces tabs in original token content with spaces. + * + * Each tab can represent between 1 and $config->tabWidth spaces, + * so this cannot be a straight string replace. The original content + * is placed into an orig_content index and the new token length is also + * set in the length index. + * + * @param array $token The token to replace tabs inside. + * @param string $prefix The character to use to represent the start of a tab. + * @param string $padding The character to use to represent the end of a tab. + * @param int $tabWidth The number of spaces each tab represents. + * + * @return void + */ + public function replaceTabsInToken(&$token, $prefix=' ', $padding=' ', $tabWidth=null) + { + $checkEncoding = false; + if (function_exists('iconv_strlen') === true) { + $checkEncoding = true; + } + + $currColumn = $token['column']; + if ($tabWidth === null) { + $tabWidth = $this->config->tabWidth; + if ($tabWidth === 0) { + $tabWidth = 1; + } + } + + if (rtrim($token['content'], "\t") === '') { + // String only contains tabs, so we can shortcut the process. + $numTabs = strlen($token['content']); + + $firstTabSize = ($tabWidth - (($currColumn - 1) % $tabWidth)); + $length = ($firstTabSize + ($tabWidth * ($numTabs - 1))); + $newContent = $prefix.str_repeat($padding, ($length - 1)); + } else { + // We need to determine the length of each tab. + $tabs = explode("\t", $token['content']); + + $numTabs = (count($tabs) - 1); + $tabNum = 0; + $newContent = ''; + $length = 0; + + foreach ($tabs as $content) { + if ($content !== '') { + $newContent .= $content; + if ($checkEncoding === true) { + // Not using the default encoding, so take a bit more care. + $oldLevel = error_reporting(); + error_reporting(0); + $contentLength = iconv_strlen($content, $this->config->encoding); + error_reporting($oldLevel); + if ($contentLength === false) { + // String contained invalid characters, so revert to default. + $contentLength = strlen($content); + } + } else { + $contentLength = strlen($content); + } + + $currColumn += $contentLength; + $length += $contentLength; + } + + // The last piece of content does not have a tab after it. + if ($tabNum === $numTabs) { + break; + } + + // Process the tab that comes after the content. + $tabNum++; + + // Move the pointer to the next tab stop. + $pad = ($tabWidth - ($currColumn + $tabWidth - 1) % $tabWidth); + $currColumn += $pad; + $length += $pad; + $newContent .= $prefix.str_repeat($padding, ($pad - 1)); + }//end foreach + }//end if + + $token['orig_content'] = $token['content']; + $token['content'] = $newContent; + $token['length'] = $length; + + }//end replaceTabsInToken() + + + /** + * Creates a map of brackets positions. + * + * @return void + */ + private function createTokenMap() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START TOKEN MAP ***".PHP_EOL; + } + + $squareOpeners = []; + $curlyOpeners = []; + $this->numTokens = count($this->tokens); + + $openers = []; + $openOwner = null; + + for ($i = 0; $i < $this->numTokens; $i++) { + /* + Parenthesis mapping. + */ + + if (isset(Util\Tokens::$parenthesisOpeners[$this->tokens[$i]['code']]) === true) { + $this->tokens[$i]['parenthesis_opener'] = null; + $this->tokens[$i]['parenthesis_closer'] = null; + $this->tokens[$i]['parenthesis_owner'] = $i; + $openOwner = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found parenthesis owner at $i".PHP_EOL; + } + } else if ($this->tokens[$i]['code'] === T_OPEN_PARENTHESIS) { + $openers[] = $i; + $this->tokens[$i]['parenthesis_opener'] = $i; + if ($openOwner !== null) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($openers)); + echo "=> Found parenthesis opener at $i for $openOwner".PHP_EOL; + } + + $this->tokens[$openOwner]['parenthesis_opener'] = $i; + $this->tokens[$i]['parenthesis_owner'] = $openOwner; + $openOwner = null; + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($openers)); + echo "=> Found unowned parenthesis opener at $i".PHP_EOL; + } + } else if ($this->tokens[$i]['code'] === T_CLOSE_PARENTHESIS) { + // Did we set an owner for this set of parenthesis? + $numOpeners = count($openers); + if ($numOpeners !== 0) { + $opener = array_pop($openers); + if (isset($this->tokens[$opener]['parenthesis_owner']) === true) { + $owner = $this->tokens[$opener]['parenthesis_owner']; + + $this->tokens[$owner]['parenthesis_closer'] = $i; + $this->tokens[$i]['parenthesis_owner'] = $owner; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found parenthesis closer at $i for $owner".PHP_EOL; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found unowned parenthesis closer at $i for $opener".PHP_EOL; + } + + $this->tokens[$i]['parenthesis_opener'] = $opener; + $this->tokens[$i]['parenthesis_closer'] = $i; + $this->tokens[$opener]['parenthesis_closer'] = $i; + }//end if + } else if ($this->tokens[$i]['code'] === T_ATTRIBUTE) { + $openers[] = $i; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($openers)); + echo "=> Found attribute opener at $i".PHP_EOL; + } + + $this->tokens[$i]['attribute_opener'] = $i; + $this->tokens[$i]['attribute_closer'] = null; + } else if ($this->tokens[$i]['code'] === T_ATTRIBUTE_END) { + $numOpeners = count($openers); + if ($numOpeners !== 0) { + $opener = array_pop($openers); + if (isset($this->tokens[$opener]['attribute_opener']) === true) { + $this->tokens[$opener]['attribute_closer'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found attribute closer at $i for $opener".PHP_EOL; + } + + for ($x = ($opener + 1); $x <= $i; ++$x) { + if (isset($this->tokens[$x]['attribute_closer']) === true) { + continue; + } + + $this->tokens[$x]['attribute_opener'] = $opener; + $this->tokens[$x]['attribute_closer'] = $i; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found unowned attribute closer at $i for $opener".PHP_EOL; + } + }//end if + }//end if + + /* + Bracket mapping. + */ + + switch ($this->tokens[$i]['code']) { + case T_OPEN_SQUARE_BRACKET: + $squareOpeners[] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($squareOpeners)); + echo str_repeat("\t", count($curlyOpeners)); + echo "=> Found square bracket opener at $i".PHP_EOL; + } + break; + case T_OPEN_CURLY_BRACKET: + if (isset($this->tokens[$i]['scope_closer']) === false) { + $curlyOpeners[] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($squareOpeners)); + echo str_repeat("\t", count($curlyOpeners)); + echo "=> Found curly bracket opener at $i".PHP_EOL; + } + } + break; + case T_CLOSE_SQUARE_BRACKET: + if (empty($squareOpeners) === false) { + $opener = array_pop($squareOpeners); + $this->tokens[$i]['bracket_opener'] = $opener; + $this->tokens[$i]['bracket_closer'] = $i; + $this->tokens[$opener]['bracket_opener'] = $opener; + $this->tokens[$opener]['bracket_closer'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($squareOpeners)); + echo str_repeat("\t", count($curlyOpeners)); + echo "\t=> Found square bracket closer at $i for $opener".PHP_EOL; + } + } + break; + case T_CLOSE_CURLY_BRACKET: + if (empty($curlyOpeners) === false + && isset($this->tokens[$i]['scope_opener']) === false + ) { + $opener = array_pop($curlyOpeners); + $this->tokens[$i]['bracket_opener'] = $opener; + $this->tokens[$i]['bracket_closer'] = $i; + $this->tokens[$opener]['bracket_opener'] = $opener; + $this->tokens[$opener]['bracket_closer'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($squareOpeners)); + echo str_repeat("\t", count($curlyOpeners)); + echo "\t=> Found curly bracket closer at $i for $opener".PHP_EOL; + } + } + break; + default: + continue 2; + }//end switch + }//end for + + // Cleanup for any openers that we didn't find closers for. + // This typically means there was a syntax error breaking things. + foreach ($openers as $opener) { + unset($this->tokens[$opener]['parenthesis_opener']); + unset($this->tokens[$opener]['parenthesis_owner']); + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END TOKEN MAP ***".PHP_EOL; + } + + }//end createTokenMap() + + + /** + * Creates a map for the parenthesis tokens that surround other tokens. + * + * @return void + */ + private function createParenthesisNestingMap() + { + $map = []; + for ($i = 0; $i < $this->numTokens; $i++) { + if (isset($this->tokens[$i]['parenthesis_opener']) === true + && $i === $this->tokens[$i]['parenthesis_opener'] + ) { + if (empty($map) === false) { + $this->tokens[$i]['nested_parenthesis'] = $map; + } + + if (isset($this->tokens[$i]['parenthesis_closer']) === true) { + $map[$this->tokens[$i]['parenthesis_opener']] + = $this->tokens[$i]['parenthesis_closer']; + } + } else if (isset($this->tokens[$i]['parenthesis_closer']) === true + && $i === $this->tokens[$i]['parenthesis_closer'] + ) { + array_pop($map); + if (empty($map) === false) { + $this->tokens[$i]['nested_parenthesis'] = $map; + } + } else { + if (empty($map) === false) { + $this->tokens[$i]['nested_parenthesis'] = $map; + } + }//end if + }//end for + + }//end createParenthesisNestingMap() + + + /** + * Creates a scope map of tokens that open scopes. + * + * @return void + * @see recurseScopeMap() + */ + private function createScopeMap() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START SCOPE MAP ***".PHP_EOL; + } + + for ($i = 0; $i < $this->numTokens; $i++) { + // Check to see if the current token starts a new scope. + if (isset($this->scopeOpeners[$this->tokens[$i]['code']]) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + $content = Util\Common::prepareForOutput($this->tokens[$i]['content']); + echo "\tStart scope map at $i:$type => $content".PHP_EOL; + } + + if (isset($this->tokens[$i]['scope_condition']) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* already processed, skipping *".PHP_EOL; + } + + continue; + } + + $i = $this->recurseScopeMap($i); + }//end if + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END SCOPE MAP ***".PHP_EOL; + } + + }//end createScopeMap() + + + /** + * Recurses though the scope openers to build a scope map. + * + * @param int $stackPtr The position in the stack of the token that + * opened the scope (eg. an IF token or FOR token). + * @param int $depth How many scope levels down we are. + * @param int $ignore How many curly braces we are ignoring. + * + * @return int The position in the stack that closed the scope. + * @throws \PHP_CodeSniffer\Exceptions\TokenizerException If the nesting level gets too deep. + */ + private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "=> Begin scope map recursion at token $stackPtr with depth $depth".PHP_EOL; + } + + $opener = null; + $currType = $this->tokens[$stackPtr]['code']; + $startLine = $this->tokens[$stackPtr]['line']; + + // We will need this to restore the value if we end up + // returning a token ID that causes our calling function to go back + // over already ignored braces. + $originalIgnore = $ignore; + + // If the start token for this scope opener is the same as + // the scope token, we have already found our opener. + if (isset($this->scopeOpeners[$currType]['start'][$currType]) === true) { + $opener = $stackPtr; + } + + for ($i = ($stackPtr + 1); $i < $this->numTokens; $i++) { + $tokenType = $this->tokens[$i]['code']; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + $line = $this->tokens[$i]['line']; + $content = Util\Common::prepareForOutput($this->tokens[$i]['content']); + + echo str_repeat("\t", $depth); + echo "Process token $i on line $line ["; + if ($opener !== null) { + echo "opener:$opener;"; + } + + if ($ignore > 0) { + echo "ignore=$ignore;"; + } + + echo "]: $type => $content".PHP_EOL; + }//end if + + // Very special case for IF statements in PHP that can be defined without + // scope tokens. E.g., if (1) 1; 1 ? (1 ? 1 : 1) : 1; + // If an IF statement below this one has an opener but no + // keyword, the opener will be incorrectly assigned to this IF statement. + // The same case also applies to USE statements, which don't have to have + // openers, so a following USE statement can cause an incorrect brace match. + if (($currType === T_IF || $currType === T_ELSE || $currType === T_USE) + && $opener === null + && ($this->tokens[$i]['code'] === T_SEMICOLON + || $this->tokens[$i]['code'] === T_CLOSE_TAG) + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + if ($this->tokens[$i]['code'] === T_SEMICOLON) { + $closerType = 'semicolon'; + } else { + $closerType = 'close tag'; + } + + echo "=> Found $closerType before scope opener for $stackPtr:$type, bailing".PHP_EOL; + } + + return $i; + } + + // Special case for PHP control structures that have no braces. + // If we find a curly brace closer before we find the opener, + // we're not going to find an opener. That closer probably belongs to + // a control structure higher up. + if ($opener === null + && $ignore === 0 + && $tokenType === T_CLOSE_CURLY_BRACKET + && isset($this->scopeOpeners[$currType]['end'][$tokenType]) === true + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found curly brace closer before scope opener for $stackPtr:$type, bailing".PHP_EOL; + } + + return ($i - 1); + } + + if ($opener !== null + && (isset($this->tokens[$i]['scope_opener']) === false + || $this->scopeOpeners[$this->tokens[$stackPtr]['code']]['shared'] === true) + && isset($this->scopeOpeners[$currType]['end'][$tokenType]) === true + ) { + if ($ignore > 0 && $tokenType === T_CLOSE_CURLY_BRACKET) { + // The last opening bracket must have been for a string + // offset or alike, so let's ignore it. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* finished ignoring curly brace *'.PHP_EOL; + } + + $ignore--; + continue; + } else if ($this->tokens[$opener]['code'] === T_OPEN_CURLY_BRACKET + && $tokenType !== T_CLOSE_CURLY_BRACKET + ) { + // The opener is a curly bracket so the closer must be a curly bracket as well. + // We ignore this closer to handle cases such as T_ELSE or T_ELSEIF being considered + // a closer of T_IF when it should not. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Ignoring non-curly scope closer for $stackPtr:$type".PHP_EOL; + } + } else { + $scopeCloser = $i; + $todo = [ + $stackPtr, + $opener, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + $closerType = $this->tokens[$scopeCloser]['type']; + echo str_repeat("\t", $depth); + echo "=> Found scope closer ($scopeCloser:$closerType) for $stackPtr:$type".PHP_EOL; + } + + $validCloser = true; + if (($this->tokens[$stackPtr]['code'] === T_IF || $this->tokens[$stackPtr]['code'] === T_ELSEIF) + && ($tokenType === T_ELSE || $tokenType === T_ELSEIF) + ) { + // To be a closer, this token must have an opener. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "* closer needs to be tested *".PHP_EOL; + } + + $i = self::recurseScopeMap($i, ($depth + 1), $ignore); + + if (isset($this->tokens[$scopeCloser]['scope_opener']) === false) { + $validCloser = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "* closer is not valid (no opener found) *".PHP_EOL; + } + } else if ($this->tokens[$this->tokens[$scopeCloser]['scope_opener']]['code'] !== $this->tokens[$opener]['code']) { + $validCloser = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + $type = $this->tokens[$this->tokens[$scopeCloser]['scope_opener']]['type']; + $openerType = $this->tokens[$opener]['type']; + echo "* closer is not valid (mismatched opener type; $type != $openerType) *".PHP_EOL; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "* closer was valid *".PHP_EOL; + } + } else { + // The closer was not processed, so we need to + // complete that token as well. + $todo[] = $scopeCloser; + }//end if + + if ($validCloser === true) { + foreach ($todo as $token) { + $this->tokens[$token]['scope_condition'] = $stackPtr; + $this->tokens[$token]['scope_opener'] = $opener; + $this->tokens[$token]['scope_closer'] = $scopeCloser; + } + + if ($this->scopeOpeners[$this->tokens[$stackPtr]['code']]['shared'] === true) { + // As we are going back to where we started originally, restore + // the ignore value back to its original value. + $ignore = $originalIgnore; + return $opener; + } else if ($scopeCloser === $i + && isset($this->scopeOpeners[$tokenType]) === true + ) { + // Unset scope_condition here or else the token will appear to have + // already been processed, and it will be skipped. Normally we want that, + // but in this case, the token is both a closer and an opener, so + // it needs to act like an opener. This is also why we return the + // token before this one; so the closer has a chance to be processed + // a second time, but as an opener. + unset($this->tokens[$scopeCloser]['scope_condition']); + return ($i - 1); + } else { + return $i; + } + } else { + continue; + }//end if + }//end if + }//end if + + // Is this an opening condition ? + if (isset($this->scopeOpeners[$tokenType]) === true) { + if ($opener === null) { + if ($tokenType === T_USE) { + // PHP use keywords are special because they can be + // used as blocks but also inline in function definitions. + // So if we find them nested inside another opener, just skip them. + continue; + } + + if ($tokenType === T_NAMESPACE) { + // PHP namespace keywords are special because they can be + // used as blocks but also inline as operators. + // So if we find them nested inside another opener, just skip them. + continue; + } + + if ($tokenType === T_FUNCTION + && $this->tokens[$stackPtr]['code'] !== T_FUNCTION + ) { + // Probably a closure, so process it manually. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found function before scope opener for $stackPtr:$type, processing manually".PHP_EOL; + } + + if (isset($this->tokens[$i]['scope_closer']) === true) { + // We've already processed this closure. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* already processed, skipping *'.PHP_EOL; + } + + $i = $this->tokens[$i]['scope_closer']; + continue; + } + + $i = self::recurseScopeMap($i, ($depth + 1), $ignore); + continue; + }//end if + + if ($tokenType === T_CLASS) { + // Probably an anonymous class inside another anonymous class, + // so process it manually. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found class before scope opener for $stackPtr:$type, processing manually".PHP_EOL; + } + + if (isset($this->tokens[$i]['scope_closer']) === true) { + // We've already processed this anon class. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* already processed, skipping *'.PHP_EOL; + } + + $i = $this->tokens[$i]['scope_closer']; + continue; + } + + $i = self::recurseScopeMap($i, ($depth + 1), $ignore); + continue; + }//end if + + // Found another opening condition but still haven't + // found our opener, so we are never going to find one. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found new opening condition before scope opener for $stackPtr:$type, "; + } + + if (($this->tokens[$stackPtr]['code'] === T_IF + || $this->tokens[$stackPtr]['code'] === T_ELSEIF + || $this->tokens[$stackPtr]['code'] === T_ELSE) + && ($this->tokens[$i]['code'] === T_ELSE + || $this->tokens[$i]['code'] === T_ELSEIF) + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "continuing".PHP_EOL; + } + + return ($i - 1); + } else { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "backtracking".PHP_EOL; + } + + return $stackPtr; + } + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* token is an opening condition *'.PHP_EOL; + } + + $isShared = ($this->scopeOpeners[$tokenType]['shared'] === true); + + if (isset($this->tokens[$i]['scope_condition']) === true) { + // We've been here before. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* already processed, skipping *'.PHP_EOL; + } + + if ($isShared === false + && isset($this->tokens[$i]['scope_closer']) === true + ) { + $i = $this->tokens[$i]['scope_closer']; + } + + continue; + } else if ($currType === $tokenType + && $isShared === false + && $opener === null + ) { + // We haven't yet found our opener, but we have found another + // scope opener which is the same type as us, and we don't + // share openers, so we will never find one. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* it was another token\'s opener, bailing *'.PHP_EOL; + } + + return $stackPtr; + } else { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* searching for opener *'.PHP_EOL; + } + + if (isset($this->scopeOpeners[$tokenType]['end'][T_CLOSE_CURLY_BRACKET]) === true) { + $oldIgnore = $ignore; + $ignore = 0; + } + + // PHP has a max nesting level for functions. Stop before we hit that limit + // because too many loops means we've run into trouble anyway. + if ($depth > 50) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* reached maximum nesting level; aborting *'.PHP_EOL; + } + + throw new TokenizerException('Maximum nesting level reached; file could not be processed'); + } + + $oldDepth = $depth; + if ($isShared === true + && isset($this->scopeOpeners[$tokenType]['with'][$currType]) === true + ) { + // Don't allow the depth to increment because this is + // possibly not a true nesting if we are sharing our closer. + // This can happen, for example, when a SWITCH has a large + // number of CASE statements with the same shared BREAK. + $depth--; + } + + $i = self::recurseScopeMap($i, ($depth + 1), $ignore); + $depth = $oldDepth; + + if (isset($this->scopeOpeners[$tokenType]['end'][T_CLOSE_CURLY_BRACKET]) === true) { + $ignore = $oldIgnore; + } + }//end if + }//end if + + if (isset($this->scopeOpeners[$currType]['start'][$tokenType]) === true + && $opener === null + ) { + if ($tokenType === T_OPEN_CURLY_BRACKET) { + if (isset($this->tokens[$stackPtr]['parenthesis_closer']) === true + && $i < $this->tokens[$stackPtr]['parenthesis_closer'] + ) { + // We found a curly brace inside the condition of the + // current scope opener, so it must be a string offset. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* ignoring curly brace inside condition *'.PHP_EOL; + } + + $ignore++; + } else { + // Make sure this is actually an opener and not a + // string offset (e.g., $var{0}). + for ($x = ($i - 1); $x > 0; $x--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true) { + continue; + } else { + // If the first non-whitespace/comment token looks like this + // brace is a string offset, or this brace is mid-way through + // a new statement, it isn't a scope opener. + $disallowed = Util\Tokens::$assignmentTokens; + $disallowed += [ + T_DOLLAR => true, + T_VARIABLE => true, + T_OBJECT_OPERATOR => true, + T_NULLSAFE_OBJECT_OPERATOR => true, + T_COMMA => true, + T_OPEN_PARENTHESIS => true, + ]; + + if (isset($disallowed[$this->tokens[$x]['code']]) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* ignoring curly brace *'.PHP_EOL; + } + + $ignore++; + } + + break; + }//end if + }//end for + }//end if + }//end if + + if ($ignore === 0 || $tokenType !== T_OPEN_CURLY_BRACKET) { + $openerNested = isset($this->tokens[$i]['nested_parenthesis']); + $ownerNested = isset($this->tokens[$stackPtr]['nested_parenthesis']); + + if (($openerNested === true && $ownerNested === false) + || ($openerNested === false && $ownerNested === true) + || ($openerNested === true + && $this->tokens[$i]['nested_parenthesis'] !== $this->tokens[$stackPtr]['nested_parenthesis']) + ) { + // We found the a token that looks like the opener, but it's nested differently. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + echo str_repeat("\t", $depth); + echo "* ignoring possible opener $i:$type as nested parenthesis don't match *".PHP_EOL; + } + } else { + // We found the opening scope token for $currType. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found scope opener for $stackPtr:$type".PHP_EOL; + } + + $opener = $i; + } + }//end if + } else if ($tokenType === T_SEMICOLON + && $opener === null + && (isset($this->tokens[$stackPtr]['parenthesis_closer']) === false + || $i > $this->tokens[$stackPtr]['parenthesis_closer']) + ) { + // Found the end of a statement but still haven't + // found our opener, so we are never going to find one. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found end of statement before scope opener for $stackPtr:$type, continuing".PHP_EOL; + } + + return ($i - 1); + } else if ($tokenType === T_OPEN_PARENTHESIS) { + if (isset($this->tokens[$i]['parenthesis_owner']) === true) { + $owner = $this->tokens[$i]['parenthesis_owner']; + if (isset(Util\Tokens::$scopeOpeners[$this->tokens[$owner]['code']]) === true + && isset($this->tokens[$i]['parenthesis_closer']) === true + ) { + // If we get into here, then we opened a parenthesis for + // a scope (eg. an if or else if) so we need to update the + // start of the line so that when we check to see + // if the closing parenthesis is more than n lines away from + // the statement, we check from the closing parenthesis. + $startLine = $this->tokens[$this->tokens[$i]['parenthesis_closer']]['line']; + } + } + } else if ($tokenType === T_OPEN_CURLY_BRACKET && $opener !== null) { + // We opened something that we don't have a scope opener for. + // Examples of this are curly brackets for string offsets etc. + // We want to ignore this so that we don't have an invalid scope + // map. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* ignoring curly brace *'.PHP_EOL; + } + + $ignore++; + } else if ($tokenType === T_CLOSE_CURLY_BRACKET && $ignore > 0) { + // We found the end token for the opener we were ignoring. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* finished ignoring curly brace *'.PHP_EOL; + } + + $ignore--; + } else if ($opener === null + && isset($this->scopeOpeners[$currType]) === true + ) { + // If we still haven't found the opener after 30 lines, + // we're not going to find it, unless we know it requires + // an opener (in which case we better keep looking) or the last + // token was empty (in which case we'll just confirm there is + // more code in this file and not just a big comment). + if ($this->tokens[$i]['line'] >= ($startLine + 30) + && isset(Util\Tokens::$emptyTokens[$this->tokens[($i - 1)]['code']]) === false + ) { + if ($this->scopeOpeners[$currType]['strict'] === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + $lines = ($this->tokens[$i]['line'] - $startLine); + echo str_repeat("\t", $depth); + echo "=> Still looking for $stackPtr:$type scope opener after $lines lines".PHP_EOL; + } + } else { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Couldn't find scope opener for $stackPtr:$type, bailing".PHP_EOL; + } + + return $stackPtr; + } + } + } else if ($opener !== null + && $tokenType !== T_BREAK + && isset($this->endScopeTokens[$tokenType]) === true + ) { + if (isset($this->tokens[$i]['scope_condition']) === false) { + if ($ignore > 0) { + // We found the end token for the opener we were ignoring. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* finished ignoring curly brace *'.PHP_EOL; + } + + $ignore--; + } else { + // We found a token that closes the scope but it doesn't + // have a condition, so it belongs to another token and + // our token doesn't have a closer, so pretend this is + // the closer. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found (unexpected) scope closer for $stackPtr:$type".PHP_EOL; + } + + foreach ([$stackPtr, $opener] as $token) { + $this->tokens[$token]['scope_condition'] = $stackPtr; + $this->tokens[$token]['scope_opener'] = $opener; + $this->tokens[$token]['scope_closer'] = $i; + } + + return ($i - 1); + }//end if + }//end if + }//end if + }//end for + + return $stackPtr; + + }//end recurseScopeMap() + + + /** + * Constructs the level map. + * + * The level map adds a 'level' index to each token which indicates the + * depth that a token within a set of scope blocks. It also adds a + * 'conditions' index which is an array of the scope conditions that opened + * each of the scopes - position 0 being the first scope opener. + * + * @return void + */ + private function createLevelMap() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START LEVEL MAP ***".PHP_EOL; + } + + $this->numTokens = count($this->tokens); + $level = 0; + $conditions = []; + $lastOpener = null; + $openers = []; + + for ($i = 0; $i < $this->numTokens; $i++) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + $line = $this->tokens[$i]['line']; + $len = $this->tokens[$i]['length']; + $col = $this->tokens[$i]['column']; + + $content = Util\Common::prepareForOutput($this->tokens[$i]['content']); + + echo str_repeat("\t", ($level + 1)); + echo "Process token $i on line $line [col:$col;len:$len;lvl:$level;"; + if (empty($conditions) !== true) { + $conditionString = 'conds;'; + foreach ($conditions as $condition) { + $conditionString .= Util\Tokens::tokenName($condition).','; + } + + echo rtrim($conditionString, ',').';'; + } + + echo "]: $type => $content".PHP_EOL; + }//end if + + $this->tokens[$i]['level'] = $level; + $this->tokens[$i]['conditions'] = $conditions; + + if (isset($this->tokens[$i]['scope_condition']) === true) { + // Check to see if this token opened the scope. + if ($this->tokens[$i]['scope_opener'] === $i) { + $stackPtr = $this->tokens[$i]['scope_condition']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", ($level + 1)); + echo "=> Found scope opener for $stackPtr:$type".PHP_EOL; + } + + $stackPtr = $this->tokens[$i]['scope_condition']; + + // If we find a scope opener that has a shared closer, + // then we need to go back over the condition map that we + // just created and fix ourselves as we just added some + // conditions where there was none. This happens for T_CASE + // statements that are using the same break statement. + if ($lastOpener !== null && $this->tokens[$lastOpener]['scope_closer'] === $this->tokens[$i]['scope_closer']) { + // This opener shares its closer with the previous opener, + // but we still need to check if the two openers share their + // closer with each other directly (like CASE and DEFAULT) + // or if they are just sharing because one doesn't have a + // closer (like CASE with no BREAK using a SWITCHes closer). + $thisType = $this->tokens[$this->tokens[$i]['scope_condition']]['code']; + $opener = $this->tokens[$lastOpener]['scope_condition']; + + $isShared = isset($this->scopeOpeners[$thisType]['with'][$this->tokens[$opener]['code']]); + + reset($this->scopeOpeners[$thisType]['end']); + reset($this->scopeOpeners[$this->tokens[$opener]['code']]['end']); + $sameEnd = (current($this->scopeOpeners[$thisType]['end']) === current($this->scopeOpeners[$this->tokens[$opener]['code']]['end'])); + + if ($isShared === true && $sameEnd === true) { + $badToken = $opener; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$badToken]['type']; + echo str_repeat("\t", ($level + 1)); + echo "* shared closer, cleaning up $badToken:$type *".PHP_EOL; + } + + for ($x = $this->tokens[$i]['scope_condition']; $x <= $i; $x++) { + $oldConditions = $this->tokens[$x]['conditions']; + $oldLevel = $this->tokens[$x]['level']; + $this->tokens[$x]['level']--; + unset($this->tokens[$x]['conditions'][$badToken]); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + $oldConds = ''; + foreach ($oldConditions as $condition) { + $oldConds .= Util\Tokens::tokenName($condition).','; + } + + $oldConds = rtrim($oldConds, ','); + + $newConds = ''; + foreach ($this->tokens[$x]['conditions'] as $condition) { + $newConds .= Util\Tokens::tokenName($condition).','; + } + + $newConds = rtrim($newConds, ','); + + $newLevel = $this->tokens[$x]['level']; + echo str_repeat("\t", ($level + 1)); + echo "* cleaned $x:$type *".PHP_EOL; + echo str_repeat("\t", ($level + 2)); + echo "=> level changed from $oldLevel to $newLevel".PHP_EOL; + echo str_repeat("\t", ($level + 2)); + echo "=> conditions changed from $oldConds to $newConds".PHP_EOL; + }//end if + }//end for + + unset($conditions[$badToken]); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$badToken]['type']; + echo str_repeat("\t", ($level + 1)); + echo "* token $badToken:$type removed from conditions array *".PHP_EOL; + } + + unset($openers[$lastOpener]); + + $level--; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", ($level + 2)); + echo '* level decreased *'.PHP_EOL; + } + }//end if + }//end if + + $level++; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", ($level + 1)); + echo '* level increased *'.PHP_EOL; + } + + $conditions[$stackPtr] = $this->tokens[$stackPtr]['code']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", ($level + 1)); + echo "* token $stackPtr:$type added to conditions array *".PHP_EOL; + } + + $lastOpener = $this->tokens[$i]['scope_opener']; + if ($lastOpener !== null) { + $openers[$lastOpener] = $lastOpener; + } + } else if ($lastOpener !== null && $this->tokens[$lastOpener]['scope_closer'] === $i) { + foreach (array_reverse($openers) as $opener) { + if ($this->tokens[$opener]['scope_closer'] === $i) { + $oldOpener = array_pop($openers); + if (empty($openers) === false) { + $lastOpener = array_pop($openers); + $openers[$lastOpener] = $lastOpener; + } else { + $lastOpener = null; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$oldOpener]['type']; + echo str_repeat("\t", ($level + 1)); + echo "=> Found scope closer for $oldOpener:$type".PHP_EOL; + } + + $oldCondition = array_pop($conditions); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", ($level + 1)); + echo '* token '.Util\Tokens::tokenName($oldCondition).' removed from conditions array *'.PHP_EOL; + } + + // Make sure this closer actually belongs to us. + // Either the condition also has to think this is the + // closer, or it has to allow sharing with us. + $condition = $this->tokens[$this->tokens[$i]['scope_condition']]['code']; + if ($condition !== $oldCondition) { + if (isset($this->scopeOpeners[$oldCondition]['with'][$condition]) === false) { + $badToken = $this->tokens[$oldOpener]['scope_condition']; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = Util\Tokens::tokenName($oldCondition); + echo str_repeat("\t", ($level + 1)); + echo "* scope closer was bad, cleaning up $badToken:$type *".PHP_EOL; + } + + for ($x = ($oldOpener + 1); $x <= $i; $x++) { + $oldConditions = $this->tokens[$x]['conditions']; + $oldLevel = $this->tokens[$x]['level']; + $this->tokens[$x]['level']--; + unset($this->tokens[$x]['conditions'][$badToken]); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + $oldConds = ''; + foreach ($oldConditions as $condition) { + $oldConds .= Util\Tokens::tokenName($condition).','; + } + + $oldConds = rtrim($oldConds, ','); + + $newConds = ''; + foreach ($this->tokens[$x]['conditions'] as $condition) { + $newConds .= Util\Tokens::tokenName($condition).','; + } + + $newConds = rtrim($newConds, ','); + + $newLevel = $this->tokens[$x]['level']; + echo str_repeat("\t", ($level + 1)); + echo "* cleaned $x:$type *".PHP_EOL; + echo str_repeat("\t", ($level + 2)); + echo "=> level changed from $oldLevel to $newLevel".PHP_EOL; + echo str_repeat("\t", ($level + 2)); + echo "=> conditions changed from $oldConds to $newConds".PHP_EOL; + }//end if + }//end for + }//end if + }//end if + + $level--; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", ($level + 2)); + echo '* level decreased *'.PHP_EOL; + } + + $this->tokens[$i]['level'] = $level; + $this->tokens[$i]['conditions'] = $conditions; + }//end if + }//end foreach + }//end if + }//end if + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END LEVEL MAP ***".PHP_EOL; + } + + }//end createLevelMap() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Util/Cache.php b/vendor/squizlabs/php_codesniffer/src/Util/Cache.php new file mode 100644 index 00000000..68abef59 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Util/Cache.php @@ -0,0 +1,351 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +use PHP_CodeSniffer\Autoload; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; + +class Cache +{ + + /** + * The filesystem location of the cache file. + * + * @var void + */ + private static $path = ''; + + /** + * The cached data. + * + * @var array + */ + private static $cache = []; + + + /** + * Loads existing cache data for the run, if any. + * + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public static function load(Ruleset $ruleset, Config $config) + { + // Look at every loaded sniff class so far and use their file contents + // to generate a hash for the code used during the run. + // At this point, the loaded class list contains the core PHPCS code + // and all sniffs that have been loaded as part of the run. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL."\tGenerating loaded file list for code hash".PHP_EOL; + } + + $codeHashFiles = []; + + $classes = array_keys(Autoload::getLoadedClasses()); + sort($classes); + + $installDir = dirname(__DIR__); + $installDirLen = strlen($installDir); + $standardDir = $installDir.DIRECTORY_SEPARATOR.'Standards'; + $standardDirLen = strlen($standardDir); + foreach ($classes as $file) { + if (substr($file, 0, $standardDirLen) !== $standardDir) { + if (substr($file, 0, $installDirLen) === $installDir) { + // We are only interested in sniffs here. + continue; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> external file: $file".PHP_EOL; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> internal sniff: $file".PHP_EOL; + } + + $codeHashFiles[] = $file; + } + + // Add the content of the used rulesets to the hash so that sniff setting + // changes in the ruleset invalidate the cache. + $rulesets = $ruleset->paths; + sort($rulesets); + foreach ($rulesets as $file) { + if (substr($file, 0, $standardDirLen) !== $standardDir) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> external ruleset: $file".PHP_EOL; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> internal ruleset: $file".PHP_EOL; + } + + $codeHashFiles[] = $file; + } + + // Go through the core PHPCS code and add those files to the file + // hash. This ensures that core PHPCS changes will also invalidate the cache. + // Note that we ignore sniffs here, and any files that don't affect + // the outcome of the run. + $di = new \RecursiveDirectoryIterator( + $installDir, + (\FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS) + ); + $filter = new \RecursiveCallbackFilterIterator( + $di, + function ($file, $key, $iterator) { + // Skip non-php files. + $filename = $file->getFilename(); + if ($file->isFile() === true && substr($filename, -4) !== '.php') { + return false; + } + + $filePath = Common::realpath($key); + if ($filePath === false) { + return false; + } + + if ($iterator->hasChildren() === true + && ($filename === 'Standards' + || $filename === 'Exceptions' + || $filename === 'Reports' + || $filename === 'Generators') + ) { + return false; + } + + return true; + } + ); + + $iterator = new \RecursiveIteratorIterator($filter); + foreach ($iterator as $file) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> core file: $file".PHP_EOL; + } + + $codeHashFiles[] = $file->getPathname(); + } + + $codeHash = ''; + sort($codeHashFiles); + foreach ($codeHashFiles as $file) { + $codeHash .= md5_file($file); + } + + $codeHash = md5($codeHash); + + // Along with the code hash, use various settings that can affect + // the results of a run to create a new hash. This hash will be used + // in the cache file name. + $rulesetHash = md5(var_export($ruleset->ignorePatterns, true).var_export($ruleset->includePatterns, true)); + $phpExtensionsHash = md5(var_export(get_loaded_extensions(), true)); + $configData = [ + 'phpVersion' => PHP_VERSION_ID, + 'phpExtensions' => $phpExtensionsHash, + 'tabWidth' => $config->tabWidth, + 'encoding' => $config->encoding, + 'recordErrors' => $config->recordErrors, + 'annotations' => $config->annotations, + 'configData' => Config::getAllConfigData(), + 'codeHash' => $codeHash, + 'rulesetHash' => $rulesetHash, + ]; + + $configString = var_export($configData, true); + $cacheHash = substr(sha1($configString), 0, 12); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\tGenerating cache key data".PHP_EOL; + foreach ($configData as $key => $value) { + if (is_array($value) === true) { + echo "\t\t=> $key:".PHP_EOL; + foreach ($value as $subKey => $subValue) { + echo "\t\t\t=> $subKey: $subValue".PHP_EOL; + } + + continue; + } + + if ($value === true || $value === false) { + $value = (int) $value; + } + + echo "\t\t=> $key: $value".PHP_EOL; + } + + echo "\t\t=> cacheHash: $cacheHash".PHP_EOL; + }//end if + + if ($config->cacheFile !== null) { + $cacheFile = $config->cacheFile; + } else { + // Determine the common paths for all files being checked. + // We can use this to locate an existing cache file, or to + // determine where to create a new one. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\tChecking possible cache file paths".PHP_EOL; + } + + $paths = []; + foreach ($config->files as $file) { + $file = Common::realpath($file); + while ($file !== DIRECTORY_SEPARATOR) { + if (isset($paths[$file]) === false) { + $paths[$file] = 1; + } else { + $paths[$file]++; + } + + $lastFile = $file; + $file = dirname($file); + if ($file === $lastFile) { + // Just in case something went wrong, + // we don't want to end up in an infinite loop. + break; + } + } + } + + ksort($paths); + $paths = array_reverse($paths); + + $numFiles = count($config->files); + + $cacheFile = null; + $cacheDir = getenv('XDG_CACHE_HOME'); + if ($cacheDir === false || is_dir($cacheDir) === false) { + $cacheDir = sys_get_temp_dir(); + } + + foreach ($paths as $file => $count) { + if ($count !== $numFiles) { + unset($paths[$file]); + continue; + } + + $fileHash = substr(sha1($file), 0, 12); + $testFile = $cacheDir.DIRECTORY_SEPARATOR."phpcs.$fileHash.$cacheHash.cache"; + if ($cacheFile === null) { + // This will be our default location if we can't find + // an existing file. + $cacheFile = $testFile; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> $testFile".PHP_EOL; + echo "\t\t\t * based on shared location: $file *".PHP_EOL; + } + + if (file_exists($testFile) === true) { + $cacheFile = $testFile; + break; + } + }//end foreach + + if ($cacheFile === null) { + // Unlikely, but just in case $paths is empty for some reason. + $cacheFile = $cacheDir.DIRECTORY_SEPARATOR."phpcs.$cacheHash.cache"; + } + }//end if + + self::$path = $cacheFile; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t=> Using cache file: ".self::$path.PHP_EOL; + } + + if (file_exists(self::$path) === true) { + self::$cache = json_decode(file_get_contents(self::$path), true); + + // Verify the contents of the cache file. + if (self::$cache['config'] !== $configData) { + self::$cache = []; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* cache was invalid and has been cleared *".PHP_EOL; + } + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* cache file does not exist *".PHP_EOL; + } + + self::$cache['config'] = $configData; + + }//end load() + + + /** + * Saves the current cache to the filesystem. + * + * @return void + */ + public static function save() + { + file_put_contents(self::$path, json_encode(self::$cache)); + + }//end save() + + + /** + * Retrieves a single entry from the cache. + * + * @param string $key The key of the data to get. If NULL, + * everything in the cache is returned. + * + * @return mixed + */ + public static function get($key=null) + { + if ($key === null) { + return self::$cache; + } + + if (isset(self::$cache[$key]) === true) { + return self::$cache[$key]; + } + + return false; + + }//end get() + + + /** + * Retrieves a single entry from the cache. + * + * @param string $key The key of the data to set. If NULL, + * sets the entire cache. + * @param mixed $value The value to set. + * + * @return void + */ + public static function set($key, $value) + { + if ($key === null) { + self::$cache = $value; + } else { + self::$cache[$key] = $value; + } + + }//end set() + + + /** + * Retrieves the number of cache entries. + * + * @return int + */ + public static function getSize() + { + return (count(self::$cache) - 1); + + }//end getSize() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Util/Common.php b/vendor/squizlabs/php_codesniffer/src/Util/Common.php new file mode 100644 index 00000000..caf4db77 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Util/Common.php @@ -0,0 +1,570 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +class Common +{ + + /** + * An array of variable types for param/var we will check. + * + * @var string[] + */ + public static $allowedTypes = [ + 'array', + 'boolean', + 'float', + 'integer', + 'mixed', + 'object', + 'string', + 'resource', + 'callable', + ]; + + + /** + * Return TRUE if the path is a PHAR file. + * + * @param string $path The path to use. + * + * @return mixed + */ + public static function isPharFile($path) + { + if (strpos($path, 'phar://') === 0) { + return true; + } + + return false; + + }//end isPharFile() + + + /** + * Checks if a file is readable. + * + * Addresses PHP bug related to reading files from network drives on Windows. + * e.g. when using WSL2. + * + * @param string $path The path to the file. + * + * @return boolean + */ + public static function isReadable($path) + { + if (@is_readable($path) === true) { + return true; + } + + if (@file_exists($path) === true && @is_file($path) === true) { + $f = @fopen($path, 'rb'); + if (fclose($f) === true) { + return true; + } + } + + return false; + + }//end isReadable() + + + /** + * CodeSniffer alternative for realpath. + * + * Allows for PHAR support. + * + * @param string $path The path to use. + * + * @return mixed + */ + public static function realpath($path) + { + // Support the path replacement of ~ with the user's home directory. + if (substr($path, 0, 2) === '~/') { + $homeDir = getenv('HOME'); + if ($homeDir !== false) { + $path = $homeDir.substr($path, 1); + } + } + + // Check for process substitution. + if (strpos($path, '/dev/fd') === 0) { + return str_replace('/dev/fd', 'php://fd', $path); + } + + // No extra work needed if this is not a phar file. + if (self::isPharFile($path) === false) { + return realpath($path); + } + + // Before trying to break down the file path, + // check if it exists first because it will mostly not + // change after running the below code. + if (file_exists($path) === true) { + return $path; + } + + $phar = \Phar::running(false); + $extra = str_replace('phar://'.$phar, '', $path); + $path = realpath($phar); + if ($path === false) { + return false; + } + + $path = 'phar://'.$path.$extra; + if (file_exists($path) === true) { + return $path; + } + + return false; + + }//end realpath() + + + /** + * Removes a base path from the front of a file path. + * + * @param string $path The path of the file. + * @param string $basepath The base path to remove. This should not end + * with a directory separator. + * + * @return string + */ + public static function stripBasepath($path, $basepath) + { + if (empty($basepath) === true) { + return $path; + } + + $basepathLen = strlen($basepath); + if (substr($path, 0, $basepathLen) === $basepath) { + $path = substr($path, $basepathLen); + } + + $path = ltrim($path, DIRECTORY_SEPARATOR); + if ($path === '') { + $path = '.'; + } + + return $path; + + }//end stripBasepath() + + + /** + * Detects the EOL character being used in a string. + * + * @param string $contents The contents to check. + * + * @return string + */ + public static function detectLineEndings($contents) + { + if (preg_match("/\r\n?|\n/", $contents, $matches) !== 1) { + // Assume there are no newlines. + $eolChar = "\n"; + } else { + $eolChar = $matches[0]; + } + + return $eolChar; + + }//end detectLineEndings() + + + /** + * Check if STDIN is a TTY. + * + * @return boolean + */ + public static function isStdinATTY() + { + // The check is slow (especially calling `tty`) so we static + // cache the result. + static $isTTY = null; + + if ($isTTY !== null) { + return $isTTY; + } + + if (defined('STDIN') === false) { + return false; + } + + // If PHP has the POSIX extensions we will use them. + if (function_exists('posix_isatty') === true) { + $isTTY = (posix_isatty(STDIN) === true); + return $isTTY; + } + + // Next try is detecting whether we have `tty` installed and use that. + if (defined('PHP_WINDOWS_VERSION_PLATFORM') === true) { + $devnull = 'NUL'; + $which = 'where'; + } else { + $devnull = '/dev/null'; + $which = 'which'; + } + + $tty = trim(shell_exec("$which tty 2> $devnull")); + if (empty($tty) === false) { + exec("tty -s 2> $devnull", $output, $returnValue); + $isTTY = ($returnValue === 0); + return $isTTY; + } + + // Finally we will use fstat. The solution borrowed from + // https://stackoverflow.com/questions/11327367/detect-if-a-php-script-is-being-run-interactively-or-not + // This doesn't work on Mingw/Cygwin/... using Mintty but they + // have `tty` installed. + $type = [ + 'S_IFMT' => 0170000, + 'S_IFIFO' => 0010000, + ]; + + $stat = fstat(STDIN); + $mode = ($stat['mode'] & $type['S_IFMT']); + $isTTY = ($mode !== $type['S_IFIFO']); + + return $isTTY; + + }//end isStdinATTY() + + + /** + * Escape a path to a system command. + * + * @param string $cmd The path to the system command. + * + * @return string + */ + public static function escapeshellcmd($cmd) + { + $cmd = escapeshellcmd($cmd); + + if (stripos(PHP_OS, 'WIN') === 0) { + // Spaces are not escaped by escapeshellcmd on Windows, but need to be + // for the command to be able to execute. + $cmd = preg_replace('`(? 0) { + return false; + } + + if ($strict === true) { + // Check that there are not two capital letters next to each other. + $length = strlen($string); + $lastCharWasCaps = $classFormat; + + for ($i = 1; $i < $length; $i++) { + $ascii = ord($string[$i]); + if ($ascii >= 48 && $ascii <= 57) { + // The character is a number, so it cant be a capital. + $isCaps = false; + } else { + if (strtoupper($string[$i]) === $string[$i]) { + $isCaps = true; + } else { + $isCaps = false; + } + } + + if ($isCaps === true && $lastCharWasCaps === true) { + return false; + } + + $lastCharWasCaps = $isCaps; + } + }//end if + + return true; + + }//end isCamelCaps() + + + /** + * Returns true if the specified string is in the underscore caps format. + * + * @param string $string The string to verify. + * + * @return boolean + */ + public static function isUnderscoreName($string) + { + // If there are space in the name, it can't be valid. + if (strpos($string, ' ') !== false) { + return false; + } + + $validName = true; + $nameBits = explode('_', $string); + + if (preg_match('|^[A-Z]|', $string) === 0) { + // Name does not begin with a capital letter. + $validName = false; + } else { + foreach ($nameBits as $bit) { + if ($bit === '') { + continue; + } + + if ($bit[0] !== strtoupper($bit[0])) { + $validName = false; + break; + } + } + } + + return $validName; + + }//end isUnderscoreName() + + + /** + * Returns a valid variable type for param/var tags. + * + * If type is not one of the standard types, it must be a custom type. + * Returns the correct type name suggestion if type name is invalid. + * + * @param string $varType The variable type to process. + * + * @return string + */ + public static function suggestType($varType) + { + if ($varType === '') { + return ''; + } + + if (in_array($varType, self::$allowedTypes, true) === true) { + return $varType; + } else { + $lowerVarType = strtolower($varType); + switch ($lowerVarType) { + case 'bool': + case 'boolean': + return 'boolean'; + case 'double': + case 'real': + case 'float': + return 'float'; + case 'int': + case 'integer': + return 'integer'; + case 'array()': + case 'array': + return 'array'; + }//end switch + + if (strpos($lowerVarType, 'array(') !== false) { + // Valid array declaration: + // array, array(type), array(type1 => type2). + $matches = []; + $pattern = '/^array\(\s*([^\s^=^>]*)(\s*=>\s*(.*))?\s*\)/i'; + if (preg_match($pattern, $varType, $matches) !== 0) { + $type1 = ''; + if (isset($matches[1]) === true) { + $type1 = $matches[1]; + } + + $type2 = ''; + if (isset($matches[3]) === true) { + $type2 = $matches[3]; + } + + $type1 = self::suggestType($type1); + $type2 = self::suggestType($type2); + if ($type2 !== '') { + $type2 = ' => '.$type2; + } + + return "array($type1$type2)"; + } else { + return 'array'; + }//end if + } else if (in_array($lowerVarType, self::$allowedTypes, true) === true) { + // A valid type, but not lower cased. + return $lowerVarType; + } else { + // Must be a custom type name. + return $varType; + }//end if + }//end if + + }//end suggestType() + + + /** + * Given a sniff class name, returns the code for the sniff. + * + * @param string $sniffClass The fully qualified sniff class name. + * + * @return string + */ + public static function getSniffCode($sniffClass) + { + $parts = explode('\\', $sniffClass); + $sniff = array_pop($parts); + + if (substr($sniff, -5) === 'Sniff') { + // Sniff class name. + $sniff = substr($sniff, 0, -5); + } else { + // Unit test class name. + $sniff = substr($sniff, 0, -8); + } + + $category = array_pop($parts); + $sniffDir = array_pop($parts); + $standard = array_pop($parts); + $code = $standard.'.'.$category.'.'.$sniff; + return $code; + + }//end getSniffCode() + + + /** + * Removes project-specific information from a sniff class name. + * + * @param string $sniffClass The fully qualified sniff class name. + * + * @return string + */ + public static function cleanSniffClass($sniffClass) + { + $newName = strtolower($sniffClass); + + $sniffPos = strrpos($newName, '\sniffs\\'); + if ($sniffPos === false) { + // Nothing we can do as it isn't in a known format. + return $newName; + } + + $end = (strlen($newName) - $sniffPos + 1); + $start = strrpos($newName, '\\', ($end * -1)); + + if ($start === false) { + // Nothing needs to be cleaned. + return $newName; + } + + $newName = substr($newName, ($start + 1)); + return $newName; + + }//end cleanSniffClass() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Util/Standards.php b/vendor/squizlabs/php_codesniffer/src/Util/Standards.php new file mode 100644 index 00000000..65e5d6cb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Util/Standards.php @@ -0,0 +1,339 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +use PHP_CodeSniffer\Config; + +class Standards +{ + + + /** + * Get a list of paths where standards are installed. + * + * Unresolvable relative paths will be excluded from the results. + * + * @return array + */ + public static function getInstalledStandardPaths() + { + $ds = DIRECTORY_SEPARATOR; + + $installedPaths = [dirname(dirname(__DIR__)).$ds.'src'.$ds.'Standards']; + $configPaths = Config::getConfigData('installed_paths'); + if ($configPaths !== null) { + $installedPaths = array_merge($installedPaths, explode(',', $configPaths)); + } + + $resolvedInstalledPaths = []; + foreach ($installedPaths as $installedPath) { + if (substr($installedPath, 0, 1) === '.') { + $installedPath = Common::realPath(__DIR__.$ds.'..'.$ds.'..'.$ds.$installedPath); + if ($installedPath === false) { + continue; + } + } + + $resolvedInstalledPaths[] = $installedPath; + } + + return $resolvedInstalledPaths; + + }//end getInstalledStandardPaths() + + + /** + * Get the details of all coding standards installed. + * + * Coding standards are directories located in the + * CodeSniffer/Standards directory. Valid coding standards + * include a Sniffs subdirectory. + * + * The details returned for each standard are: + * - path: the path to the coding standard's main directory + * - name: the name of the coding standard, as sourced from the ruleset.xml file + * - namespace: the namespace used by the coding standard, as sourced from the ruleset.xml file + * + * If you only need the paths to the installed standards, + * use getInstalledStandardPaths() instead as it performs less work to + * retrieve coding standard names. + * + * @param boolean $includeGeneric If true, the special "Generic" + * coding standard will be included + * if installed. + * @param string $standardsDir A specific directory to look for standards + * in. If not specified, PHP_CodeSniffer will + * look in its default locations. + * + * @return array + * @see getInstalledStandardPaths() + */ + public static function getInstalledStandardDetails( + $includeGeneric=false, + $standardsDir='' + ) { + $rulesets = []; + + if ($standardsDir === '') { + $installedPaths = self::getInstalledStandardPaths(); + } else { + $installedPaths = [$standardsDir]; + } + + foreach ($installedPaths as $standardsDir) { + // Check if the installed dir is actually a standard itself. + $csFile = $standardsDir.'/ruleset.xml'; + if (is_file($csFile) === true) { + $rulesets[] = $csFile; + continue; + } + + if (is_dir($standardsDir) === false) { + continue; + } + + $di = new \DirectoryIterator($standardsDir); + foreach ($di as $file) { + if ($file->isDir() === true && $file->isDot() === false) { + $filename = $file->getFilename(); + + // Ignore the special "Generic" standard. + if ($includeGeneric === false && $filename === 'Generic') { + continue; + } + + // Valid coding standard dirs include a ruleset. + $csFile = $file->getPathname().'/ruleset.xml'; + if (is_file($csFile) === true) { + $rulesets[] = $csFile; + } + } + } + }//end foreach + + $installedStandards = []; + + foreach ($rulesets as $rulesetPath) { + $ruleset = @simplexml_load_string(file_get_contents($rulesetPath)); + if ($ruleset === false) { + continue; + } + + $standardName = (string) $ruleset['name']; + $dirname = basename(dirname($rulesetPath)); + + if (isset($ruleset['namespace']) === true) { + $namespace = (string) $ruleset['namespace']; + } else { + $namespace = $dirname; + } + + $installedStandards[$dirname] = [ + 'path' => dirname($rulesetPath), + 'name' => $standardName, + 'namespace' => $namespace, + ]; + }//end foreach + + return $installedStandards; + + }//end getInstalledStandardDetails() + + + /** + * Get a list of all coding standards installed. + * + * Coding standards are directories located in the + * CodeSniffer/Standards directory. Valid coding standards + * include a Sniffs subdirectory. + * + * @param boolean $includeGeneric If true, the special "Generic" + * coding standard will be included + * if installed. + * @param string $standardsDir A specific directory to look for standards + * in. If not specified, PHP_CodeSniffer will + * look in its default locations. + * + * @return array + * @see isInstalledStandard() + */ + public static function getInstalledStandards( + $includeGeneric=false, + $standardsDir='' + ) { + $installedStandards = []; + + if ($standardsDir === '') { + $installedPaths = self::getInstalledStandardPaths(); + } else { + $installedPaths = [$standardsDir]; + } + + foreach ($installedPaths as $standardsDir) { + // Check if the installed dir is actually a standard itself. + $csFile = $standardsDir.'/ruleset.xml'; + if (is_file($csFile) === true) { + $basename = basename($standardsDir); + $installedStandards[$basename] = $basename; + continue; + } + + if (is_dir($standardsDir) === false) { + // Doesn't exist. + continue; + } + + $di = new \DirectoryIterator($standardsDir); + $standardsInDir = []; + foreach ($di as $file) { + if ($file->isDir() === true && $file->isDot() === false) { + $filename = $file->getFilename(); + + // Ignore the special "Generic" standard. + if ($includeGeneric === false && $filename === 'Generic') { + continue; + } + + // Valid coding standard dirs include a ruleset. + $csFile = $file->getPathname().'/ruleset.xml'; + if (is_file($csFile) === true) { + $standardsInDir[$filename] = $filename; + } + } + } + + natsort($standardsInDir); + $installedStandards += $standardsInDir; + }//end foreach + + return $installedStandards; + + }//end getInstalledStandards() + + + /** + * Determine if a standard is installed. + * + * Coding standards are directories located in the + * CodeSniffer/Standards directory. Valid coding standards + * include a ruleset.xml file. + * + * @param string $standard The name of the coding standard. + * + * @return boolean + * @see getInstalledStandards() + */ + public static function isInstalledStandard($standard) + { + $path = self::getInstalledStandardPath($standard); + if ($path !== null && strpos($path, 'ruleset.xml') !== false) { + return true; + } else { + // This could be a custom standard, installed outside our + // standards directory. + $standard = Common::realPath($standard); + if ($standard === false) { + return false; + } + + // Might be an actual ruleset file itUtil. + // If it has an XML extension, let's at least try it. + if (is_file($standard) === true + && (substr(strtolower($standard), -4) === '.xml' + || substr(strtolower($standard), -9) === '.xml.dist') + ) { + return true; + } + + // If it is a directory with a ruleset.xml file in it, + // it is a standard. + $ruleset = rtrim($standard, ' /\\').DIRECTORY_SEPARATOR.'ruleset.xml'; + if (is_file($ruleset) === true) { + return true; + } + }//end if + + return false; + + }//end isInstalledStandard() + + + /** + * Return the path of an installed coding standard. + * + * Coding standards are directories located in the + * CodeSniffer/Standards directory. Valid coding standards + * include a ruleset.xml file. + * + * @param string $standard The name of the coding standard. + * + * @return string|null + */ + public static function getInstalledStandardPath($standard) + { + if (strpos($standard, '.') !== false) { + return null; + } + + $installedPaths = self::getInstalledStandardPaths(); + foreach ($installedPaths as $installedPath) { + $standardPath = $installedPath.DIRECTORY_SEPARATOR.$standard; + if (file_exists($standardPath) === false) { + if (basename($installedPath) !== $standard) { + continue; + } + + $standardPath = $installedPath; + } + + $path = Common::realpath($standardPath.DIRECTORY_SEPARATOR.'ruleset.xml'); + + if ($path !== false && is_file($path) === true) { + return $path; + } else if (Common::isPharFile($standardPath) === true) { + $path = Common::realpath($standardPath); + if ($path !== false) { + return $path; + } + } + }//end foreach + + return null; + + }//end getInstalledStandardPath() + + + /** + * Prints out a list of installed coding standards. + * + * @return void + */ + public static function printInstalledStandards() + { + $installedStandards = self::getInstalledStandards(); + $numStandards = count($installedStandards); + + if ($numStandards === 0) { + echo 'No coding standards are installed.'.PHP_EOL; + } else { + $lastStandard = array_pop($installedStandards); + if ($numStandards === 1) { + echo "The only coding standard installed is $lastStandard".PHP_EOL; + } else { + $standardList = implode(', ', $installedStandards); + $standardList .= ' and '.$lastStandard; + echo 'The installed coding standards are '.$standardList.PHP_EOL; + } + } + + }//end printInstalledStandards() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Util/Timing.php b/vendor/squizlabs/php_codesniffer/src/Util/Timing.php new file mode 100644 index 00000000..95ee8521 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Util/Timing.php @@ -0,0 +1,86 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +class Timing +{ + + /** + * The start time of the run. + * + * @var float + */ + private static $startTime; + + /** + * Used to make sure we only print the run time once per run. + * + * @var boolean + */ + private static $printed = false; + + + /** + * Start recording time for the run. + * + * @return void + */ + public static function startTiming() + { + + self::$startTime = microtime(true); + + }//end startTiming() + + + /** + * Print information about the run. + * + * @param boolean $force If TRUE, prints the output even if it has + * already been printed during the run. + * + * @return void + */ + public static function printRunTime($force=false) + { + if ($force === false && self::$printed === true) { + // A double call. + return; + } + + if (self::$startTime === null) { + // Timing was never started. + return; + } + + $time = ((microtime(true) - self::$startTime) * 1000); + + if ($time > 60000) { + $mins = floor($time / 60000); + $secs = round((fmod($time, 60000) / 1000), 2); + $time = $mins.' mins'; + if ($secs !== 0) { + $time .= ", $secs secs"; + } + } else if ($time > 1000) { + $time = round(($time / 1000), 2).' secs'; + } else { + $time = round($time).'ms'; + } + + $mem = round((memory_get_peak_usage(true) / (1024 * 1024)), 2).'MB'; + echo "Time: $time; Memory: $mem".PHP_EOL.PHP_EOL; + + self::$printed = true; + + }//end printRunTime() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/src/Util/Tokens.php b/vendor/squizlabs/php_codesniffer/src/Util/Tokens.php new file mode 100644 index 00000000..1208e4f0 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/src/Util/Tokens.php @@ -0,0 +1,809 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +define('T_NONE', 'PHPCS_T_NONE'); +define('T_OPEN_CURLY_BRACKET', 'PHPCS_T_OPEN_CURLY_BRACKET'); +define('T_CLOSE_CURLY_BRACKET', 'PHPCS_T_CLOSE_CURLY_BRACKET'); +define('T_OPEN_SQUARE_BRACKET', 'PHPCS_T_OPEN_SQUARE_BRACKET'); +define('T_CLOSE_SQUARE_BRACKET', 'PHPCS_T_CLOSE_SQUARE_BRACKET'); +define('T_OPEN_PARENTHESIS', 'PHPCS_T_OPEN_PARENTHESIS'); +define('T_CLOSE_PARENTHESIS', 'PHPCS_T_CLOSE_PARENTHESIS'); +define('T_COLON', 'PHPCS_T_COLON'); +define('T_NULLABLE', 'PHPCS_T_NULLABLE'); +define('T_STRING_CONCAT', 'PHPCS_T_STRING_CONCAT'); +define('T_INLINE_THEN', 'PHPCS_T_INLINE_THEN'); +define('T_INLINE_ELSE', 'PHPCS_T_INLINE_ELSE'); +define('T_NULL', 'PHPCS_T_NULL'); +define('T_FALSE', 'PHPCS_T_FALSE'); +define('T_TRUE', 'PHPCS_T_TRUE'); +define('T_SEMICOLON', 'PHPCS_T_SEMICOLON'); +define('T_EQUAL', 'PHPCS_T_EQUAL'); +define('T_MULTIPLY', 'PHPCS_T_MULTIPLY'); +define('T_DIVIDE', 'PHPCS_T_DIVIDE'); +define('T_PLUS', 'PHPCS_T_PLUS'); +define('T_MINUS', 'PHPCS_T_MINUS'); +define('T_MODULUS', 'PHPCS_T_MODULUS'); +define('T_BITWISE_AND', 'PHPCS_T_BITWISE_AND'); +define('T_BITWISE_OR', 'PHPCS_T_BITWISE_OR'); +define('T_BITWISE_XOR', 'PHPCS_T_BITWISE_XOR'); +define('T_BITWISE_NOT', 'PHPCS_T_BITWISE_NOT'); +define('T_ARRAY_HINT', 'PHPCS_T_ARRAY_HINT'); +define('T_GREATER_THAN', 'PHPCS_T_GREATER_THAN'); +define('T_LESS_THAN', 'PHPCS_T_LESS_THAN'); +define('T_BOOLEAN_NOT', 'PHPCS_T_BOOLEAN_NOT'); +define('T_SELF', 'PHPCS_T_SELF'); +define('T_PARENT', 'PHPCS_T_PARENT'); +define('T_DOUBLE_QUOTED_STRING', 'PHPCS_T_DOUBLE_QUOTED_STRING'); +define('T_COMMA', 'PHPCS_T_COMMA'); +define('T_HEREDOC', 'PHPCS_T_HEREDOC'); +define('T_PROTOTYPE', 'PHPCS_T_PROTOTYPE'); +define('T_THIS', 'PHPCS_T_THIS'); +define('T_REGULAR_EXPRESSION', 'PHPCS_T_REGULAR_EXPRESSION'); +define('T_PROPERTY', 'PHPCS_T_PROPERTY'); +define('T_LABEL', 'PHPCS_T_LABEL'); +define('T_OBJECT', 'PHPCS_T_OBJECT'); +define('T_CLOSE_OBJECT', 'PHPCS_T_CLOSE_OBJECT'); +define('T_COLOUR', 'PHPCS_T_COLOUR'); +define('T_HASH', 'PHPCS_T_HASH'); +define('T_URL', 'PHPCS_T_URL'); +define('T_STYLE', 'PHPCS_T_STYLE'); +define('T_ASPERAND', 'PHPCS_T_ASPERAND'); +define('T_DOLLAR', 'PHPCS_T_DOLLAR'); +define('T_TYPEOF', 'PHPCS_T_TYPEOF'); +define('T_CLOSURE', 'PHPCS_T_CLOSURE'); +define('T_ANON_CLASS', 'PHPCS_T_ANON_CLASS'); +define('T_BACKTICK', 'PHPCS_T_BACKTICK'); +define('T_START_NOWDOC', 'PHPCS_T_START_NOWDOC'); +define('T_NOWDOC', 'PHPCS_T_NOWDOC'); +define('T_END_NOWDOC', 'PHPCS_T_END_NOWDOC'); +define('T_OPEN_SHORT_ARRAY', 'PHPCS_T_OPEN_SHORT_ARRAY'); +define('T_CLOSE_SHORT_ARRAY', 'PHPCS_T_CLOSE_SHORT_ARRAY'); +define('T_GOTO_LABEL', 'PHPCS_T_GOTO_LABEL'); +define('T_BINARY_CAST', 'PHPCS_T_BINARY_CAST'); +define('T_EMBEDDED_PHP', 'PHPCS_T_EMBEDDED_PHP'); +define('T_RETURN_TYPE', 'PHPCS_T_RETURN_TYPE'); +define('T_OPEN_USE_GROUP', 'PHPCS_T_OPEN_USE_GROUP'); +define('T_CLOSE_USE_GROUP', 'PHPCS_T_CLOSE_USE_GROUP'); +define('T_ZSR', 'PHPCS_T_ZSR'); +define('T_ZSR_EQUAL', 'PHPCS_T_ZSR_EQUAL'); +define('T_FN_ARROW', 'PHPCS_T_FN_ARROW'); +define('T_TYPE_UNION', 'PHPCS_T_TYPE_UNION'); +define('T_PARAM_NAME', 'PHPCS_T_PARAM_NAME'); +define('T_MATCH_ARROW', 'PHPCS_T_MATCH_ARROW'); +define('T_MATCH_DEFAULT', 'PHPCS_T_MATCH_DEFAULT'); +define('T_ATTRIBUTE_END', 'PHPCS_T_ATTRIBUTE_END'); +define('T_ENUM_CASE', 'PHPCS_T_ENUM_CASE'); +define('T_TYPE_INTERSECTION', 'PHPCS_T_TYPE_INTERSECTION'); + +// Some PHP 5.5 tokens, replicated for lower versions. +if (defined('T_FINALLY') === false) { + define('T_FINALLY', 'PHPCS_T_FINALLY'); +} + +if (defined('T_YIELD') === false) { + define('T_YIELD', 'PHPCS_T_YIELD'); +} + +// Some PHP 5.6 tokens, replicated for lower versions. +if (defined('T_ELLIPSIS') === false) { + define('T_ELLIPSIS', 'PHPCS_T_ELLIPSIS'); +} + +if (defined('T_POW') === false) { + define('T_POW', 'PHPCS_T_POW'); +} + +if (defined('T_POW_EQUAL') === false) { + define('T_POW_EQUAL', 'PHPCS_T_POW_EQUAL'); +} + +// Some PHP 7 tokens, replicated for lower versions. +if (defined('T_SPACESHIP') === false) { + define('T_SPACESHIP', 'PHPCS_T_SPACESHIP'); +} + +if (defined('T_COALESCE') === false) { + define('T_COALESCE', 'PHPCS_T_COALESCE'); +} + +if (defined('T_COALESCE_EQUAL') === false) { + define('T_COALESCE_EQUAL', 'PHPCS_T_COALESCE_EQUAL'); +} + +if (defined('T_YIELD_FROM') === false) { + define('T_YIELD_FROM', 'PHPCS_T_YIELD_FROM'); +} + +// Some PHP 7.4 tokens, replicated for lower versions. +if (defined('T_BAD_CHARACTER') === false) { + define('T_BAD_CHARACTER', 'PHPCS_T_BAD_CHARACTER'); +} + +if (defined('T_FN') === false) { + define('T_FN', 'PHPCS_T_FN'); +} + +// Some PHP 8.0 tokens, replicated for lower versions. +if (defined('T_NULLSAFE_OBJECT_OPERATOR') === false) { + define('T_NULLSAFE_OBJECT_OPERATOR', 'PHPCS_T_NULLSAFE_OBJECT_OPERATOR'); +} + +if (defined('T_NAME_QUALIFIED') === false) { + define('T_NAME_QUALIFIED', 'PHPCS_T_NAME_QUALIFIED'); +} + +if (defined('T_NAME_FULLY_QUALIFIED') === false) { + define('T_NAME_FULLY_QUALIFIED', 'PHPCS_T_NAME_FULLY_QUALIFIED'); +} + +if (defined('T_NAME_RELATIVE') === false) { + define('T_NAME_RELATIVE', 'PHPCS_T_NAME_RELATIVE'); +} + +if (defined('T_MATCH') === false) { + define('T_MATCH', 'PHPCS_T_MATCH'); +} + +if (defined('T_ATTRIBUTE') === false) { + define('T_ATTRIBUTE', 'PHPCS_T_ATTRIBUTE'); +} + +// Some PHP 8.1 tokens, replicated for lower versions. +if (defined('T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG') === false) { + define('T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG', 'PHPCS_T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG'); +} + +if (defined('T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG') === false) { + define('T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG', 'PHPCS_T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG'); +} + +if (defined('T_READONLY') === false) { + define('T_READONLY', 'PHPCS_T_READONLY'); +} + +if (defined('T_ENUM') === false) { + define('T_ENUM', 'PHPCS_T_ENUM'); +} + +// Tokens used for parsing doc blocks. +define('T_DOC_COMMENT_STAR', 'PHPCS_T_DOC_COMMENT_STAR'); +define('T_DOC_COMMENT_WHITESPACE', 'PHPCS_T_DOC_COMMENT_WHITESPACE'); +define('T_DOC_COMMENT_TAG', 'PHPCS_T_DOC_COMMENT_TAG'); +define('T_DOC_COMMENT_OPEN_TAG', 'PHPCS_T_DOC_COMMENT_OPEN_TAG'); +define('T_DOC_COMMENT_CLOSE_TAG', 'PHPCS_T_DOC_COMMENT_CLOSE_TAG'); +define('T_DOC_COMMENT_STRING', 'PHPCS_T_DOC_COMMENT_STRING'); + +// Tokens used for PHPCS instruction comments. +define('T_PHPCS_ENABLE', 'PHPCS_T_PHPCS_ENABLE'); +define('T_PHPCS_DISABLE', 'PHPCS_T_PHPCS_DISABLE'); +define('T_PHPCS_SET', 'PHPCS_T_PHPCS_SET'); +define('T_PHPCS_IGNORE', 'PHPCS_T_PHPCS_IGNORE'); +define('T_PHPCS_IGNORE_FILE', 'PHPCS_T_PHPCS_IGNORE_FILE'); + +final class Tokens +{ + + /** + * The token weightings. + * + * @var array + */ + public static $weightings = [ + T_CLASS => 1000, + T_INTERFACE => 1000, + T_TRAIT => 1000, + T_ENUM => 1000, + T_NAMESPACE => 1000, + T_FUNCTION => 100, + T_CLOSURE => 100, + + /* + * Conditions. + */ + + T_WHILE => 50, + T_FOR => 50, + T_FOREACH => 50, + T_IF => 50, + T_ELSE => 50, + T_ELSEIF => 50, + T_DO => 50, + T_TRY => 50, + T_CATCH => 50, + T_FINALLY => 50, + T_SWITCH => 50, + T_MATCH => 50, + + T_SELF => 25, + T_PARENT => 25, + + /* + * Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + T_BITWISE_OR => 8, + T_BITWISE_XOR => 8, + + T_MULTIPLY => 5, + T_DIVIDE => 5, + T_PLUS => 5, + T_MINUS => 5, + T_MODULUS => 5, + T_POW => 5, + T_SPACESHIP => 5, + T_COALESCE => 5, + T_COALESCE_EQUAL => 5, + + T_SL => 5, + T_SR => 5, + T_SL_EQUAL => 5, + T_SR_EQUAL => 5, + + T_EQUAL => 5, + T_AND_EQUAL => 5, + T_CONCAT_EQUAL => 5, + T_DIV_EQUAL => 5, + T_MINUS_EQUAL => 5, + T_MOD_EQUAL => 5, + T_MUL_EQUAL => 5, + T_OR_EQUAL => 5, + T_PLUS_EQUAL => 5, + T_XOR_EQUAL => 5, + + T_BOOLEAN_AND => 5, + T_BOOLEAN_OR => 5, + + /* + * Equality. + */ + + T_IS_EQUAL => 5, + T_IS_NOT_EQUAL => 5, + T_IS_IDENTICAL => 5, + T_IS_NOT_IDENTICAL => 5, + T_IS_SMALLER_OR_EQUAL => 5, + T_IS_GREATER_OR_EQUAL => 5, + ]; + + /** + * Tokens that represent assignments. + * + * @var array + */ + public static $assignmentTokens = [ + T_EQUAL => T_EQUAL, + T_AND_EQUAL => T_AND_EQUAL, + T_OR_EQUAL => T_OR_EQUAL, + T_CONCAT_EQUAL => T_CONCAT_EQUAL, + T_DIV_EQUAL => T_DIV_EQUAL, + T_MINUS_EQUAL => T_MINUS_EQUAL, + T_POW_EQUAL => T_POW_EQUAL, + T_MOD_EQUAL => T_MOD_EQUAL, + T_MUL_EQUAL => T_MUL_EQUAL, + T_PLUS_EQUAL => T_PLUS_EQUAL, + T_XOR_EQUAL => T_XOR_EQUAL, + T_DOUBLE_ARROW => T_DOUBLE_ARROW, + T_SL_EQUAL => T_SL_EQUAL, + T_SR_EQUAL => T_SR_EQUAL, + T_COALESCE_EQUAL => T_COALESCE_EQUAL, + T_ZSR_EQUAL => T_ZSR_EQUAL, + ]; + + /** + * Tokens that represent equality comparisons. + * + * @var array + */ + public static $equalityTokens = [ + T_IS_EQUAL => T_IS_EQUAL, + T_IS_NOT_EQUAL => T_IS_NOT_EQUAL, + T_IS_IDENTICAL => T_IS_IDENTICAL, + T_IS_NOT_IDENTICAL => T_IS_NOT_IDENTICAL, + T_IS_SMALLER_OR_EQUAL => T_IS_SMALLER_OR_EQUAL, + T_IS_GREATER_OR_EQUAL => T_IS_GREATER_OR_EQUAL, + ]; + + /** + * Tokens that represent comparison operator. + * + * @var array + */ + public static $comparisonTokens = [ + T_IS_EQUAL => T_IS_EQUAL, + T_IS_IDENTICAL => T_IS_IDENTICAL, + T_IS_NOT_EQUAL => T_IS_NOT_EQUAL, + T_IS_NOT_IDENTICAL => T_IS_NOT_IDENTICAL, + T_LESS_THAN => T_LESS_THAN, + T_GREATER_THAN => T_GREATER_THAN, + T_IS_SMALLER_OR_EQUAL => T_IS_SMALLER_OR_EQUAL, + T_IS_GREATER_OR_EQUAL => T_IS_GREATER_OR_EQUAL, + T_SPACESHIP => T_SPACESHIP, + T_COALESCE => T_COALESCE, + ]; + + /** + * Tokens that represent arithmetic operators. + * + * @var array + */ + public static $arithmeticTokens = [ + T_PLUS => T_PLUS, + T_MINUS => T_MINUS, + T_MULTIPLY => T_MULTIPLY, + T_DIVIDE => T_DIVIDE, + T_MODULUS => T_MODULUS, + T_POW => T_POW, + ]; + + /** + * Tokens that perform operations. + * + * @var array + */ + public static $operators = [ + T_MINUS => T_MINUS, + T_PLUS => T_PLUS, + T_MULTIPLY => T_MULTIPLY, + T_DIVIDE => T_DIVIDE, + T_MODULUS => T_MODULUS, + T_POW => T_POW, + T_SPACESHIP => T_SPACESHIP, + T_COALESCE => T_COALESCE, + T_BITWISE_AND => T_BITWISE_AND, + T_BITWISE_OR => T_BITWISE_OR, + T_BITWISE_XOR => T_BITWISE_XOR, + T_SL => T_SL, + T_SR => T_SR, + ]; + + /** + * Tokens that perform boolean operations. + * + * @var array + */ + public static $booleanOperators = [ + T_BOOLEAN_AND => T_BOOLEAN_AND, + T_BOOLEAN_OR => T_BOOLEAN_OR, + T_LOGICAL_AND => T_LOGICAL_AND, + T_LOGICAL_OR => T_LOGICAL_OR, + T_LOGICAL_XOR => T_LOGICAL_XOR, + ]; + + /** + * Tokens that represent casting. + * + * @var array + */ + public static $castTokens = [ + T_INT_CAST => T_INT_CAST, + T_STRING_CAST => T_STRING_CAST, + T_DOUBLE_CAST => T_DOUBLE_CAST, + T_ARRAY_CAST => T_ARRAY_CAST, + T_BOOL_CAST => T_BOOL_CAST, + T_OBJECT_CAST => T_OBJECT_CAST, + T_UNSET_CAST => T_UNSET_CAST, + T_BINARY_CAST => T_BINARY_CAST, + ]; + + /** + * Token types that open parenthesis. + * + * @var array + */ + public static $parenthesisOpeners = [ + T_ARRAY => T_ARRAY, + T_LIST => T_LIST, + T_FUNCTION => T_FUNCTION, + T_CLOSURE => T_CLOSURE, + T_ANON_CLASS => T_ANON_CLASS, + T_WHILE => T_WHILE, + T_FOR => T_FOR, + T_FOREACH => T_FOREACH, + T_SWITCH => T_SWITCH, + T_IF => T_IF, + T_ELSEIF => T_ELSEIF, + T_CATCH => T_CATCH, + T_DECLARE => T_DECLARE, + T_MATCH => T_MATCH, + ]; + + /** + * Tokens that are allowed to open scopes. + * + * @var array + */ + public static $scopeOpeners = [ + T_CLASS => T_CLASS, + T_ANON_CLASS => T_ANON_CLASS, + T_INTERFACE => T_INTERFACE, + T_TRAIT => T_TRAIT, + T_ENUM => T_ENUM, + T_NAMESPACE => T_NAMESPACE, + T_FUNCTION => T_FUNCTION, + T_CLOSURE => T_CLOSURE, + T_IF => T_IF, + T_SWITCH => T_SWITCH, + T_CASE => T_CASE, + T_DECLARE => T_DECLARE, + T_DEFAULT => T_DEFAULT, + T_WHILE => T_WHILE, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + T_FOR => T_FOR, + T_FOREACH => T_FOREACH, + T_DO => T_DO, + T_TRY => T_TRY, + T_CATCH => T_CATCH, + T_FINALLY => T_FINALLY, + T_PROPERTY => T_PROPERTY, + T_OBJECT => T_OBJECT, + T_USE => T_USE, + T_MATCH => T_MATCH, + ]; + + /** + * Tokens that represent scope modifiers. + * + * @var array + */ + public static $scopeModifiers = [ + T_PRIVATE => T_PRIVATE, + T_PUBLIC => T_PUBLIC, + T_PROTECTED => T_PROTECTED, + ]; + + /** + * Tokens that can prefix a method name + * + * @var array + */ + public static $methodPrefixes = [ + T_PRIVATE => T_PRIVATE, + T_PUBLIC => T_PUBLIC, + T_PROTECTED => T_PROTECTED, + T_ABSTRACT => T_ABSTRACT, + T_STATIC => T_STATIC, + T_FINAL => T_FINAL, + ]; + + /** + * Tokens that open code blocks. + * + * @var array + */ + public static $blockOpeners = [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET, + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_OBJECT => T_OBJECT, + ]; + + /** + * Tokens that don't represent code. + * + * @var array + */ + public static $emptyTokens = [ + T_WHITESPACE => T_WHITESPACE, + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + T_DOC_COMMENT_STAR => T_DOC_COMMENT_STAR, + T_DOC_COMMENT_WHITESPACE => T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_TAG => T_DOC_COMMENT_TAG, + T_DOC_COMMENT_OPEN_TAG => T_DOC_COMMENT_OPEN_TAG, + T_DOC_COMMENT_CLOSE_TAG => T_DOC_COMMENT_CLOSE_TAG, + T_DOC_COMMENT_STRING => T_DOC_COMMENT_STRING, + T_PHPCS_ENABLE => T_PHPCS_ENABLE, + T_PHPCS_DISABLE => T_PHPCS_DISABLE, + T_PHPCS_SET => T_PHPCS_SET, + T_PHPCS_IGNORE => T_PHPCS_IGNORE, + T_PHPCS_IGNORE_FILE => T_PHPCS_IGNORE_FILE, + ]; + + /** + * Tokens that are comments. + * + * @var array + */ + public static $commentTokens = [ + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + T_DOC_COMMENT_STAR => T_DOC_COMMENT_STAR, + T_DOC_COMMENT_WHITESPACE => T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_TAG => T_DOC_COMMENT_TAG, + T_DOC_COMMENT_OPEN_TAG => T_DOC_COMMENT_OPEN_TAG, + T_DOC_COMMENT_CLOSE_TAG => T_DOC_COMMENT_CLOSE_TAG, + T_DOC_COMMENT_STRING => T_DOC_COMMENT_STRING, + T_PHPCS_ENABLE => T_PHPCS_ENABLE, + T_PHPCS_DISABLE => T_PHPCS_DISABLE, + T_PHPCS_SET => T_PHPCS_SET, + T_PHPCS_IGNORE => T_PHPCS_IGNORE, + T_PHPCS_IGNORE_FILE => T_PHPCS_IGNORE_FILE, + ]; + + /** + * Tokens that are comments containing PHPCS instructions. + * + * @var array + */ + public static $phpcsCommentTokens = [ + T_PHPCS_ENABLE => T_PHPCS_ENABLE, + T_PHPCS_DISABLE => T_PHPCS_DISABLE, + T_PHPCS_SET => T_PHPCS_SET, + T_PHPCS_IGNORE => T_PHPCS_IGNORE, + T_PHPCS_IGNORE_FILE => T_PHPCS_IGNORE_FILE, + ]; + + /** + * Tokens that represent strings. + * + * Note that T_STRINGS are NOT represented in this list. + * + * @var array + */ + public static $stringTokens = [ + T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING, + T_DOUBLE_QUOTED_STRING => T_DOUBLE_QUOTED_STRING, + ]; + + /** + * Tokens that represent text strings. + * + * @var array + */ + public static $textStringTokens = [ + T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING, + T_DOUBLE_QUOTED_STRING => T_DOUBLE_QUOTED_STRING, + T_INLINE_HTML => T_INLINE_HTML, + T_HEREDOC => T_HEREDOC, + T_NOWDOC => T_NOWDOC, + ]; + + /** + * Tokens that represent brackets and parenthesis. + * + * @var array + */ + public static $bracketTokens = [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET, + T_CLOSE_SQUARE_BRACKET => T_CLOSE_SQUARE_BRACKET, + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS, + ]; + + /** + * Tokens that include files. + * + * @var array + */ + public static $includeTokens = [ + T_REQUIRE_ONCE => T_REQUIRE_ONCE, + T_REQUIRE => T_REQUIRE, + T_INCLUDE_ONCE => T_INCLUDE_ONCE, + T_INCLUDE => T_INCLUDE, + ]; + + /** + * Tokens that make up a heredoc string. + * + * @var array + */ + public static $heredocTokens = [ + T_START_HEREDOC => T_START_HEREDOC, + T_END_HEREDOC => T_END_HEREDOC, + T_HEREDOC => T_HEREDOC, + T_START_NOWDOC => T_START_NOWDOC, + T_END_NOWDOC => T_END_NOWDOC, + T_NOWDOC => T_NOWDOC, + ]; + + /** + * Tokens that represent the names of called functions. + * + * Mostly, these are just strings. But PHP tokenizes some language + * constructs and functions using their own tokens. + * + * @var array + */ + public static $functionNameTokens = [ + T_STRING => T_STRING, + T_EVAL => T_EVAL, + T_EXIT => T_EXIT, + T_INCLUDE => T_INCLUDE, + T_INCLUDE_ONCE => T_INCLUDE_ONCE, + T_REQUIRE => T_REQUIRE, + T_REQUIRE_ONCE => T_REQUIRE_ONCE, + T_ISSET => T_ISSET, + T_UNSET => T_UNSET, + T_EMPTY => T_EMPTY, + T_SELF => T_SELF, + T_STATIC => T_STATIC, + ]; + + /** + * Tokens that open class and object scopes. + * + * @var array + */ + public static $ooScopeTokens = [ + T_CLASS => T_CLASS, + T_ANON_CLASS => T_ANON_CLASS, + T_INTERFACE => T_INTERFACE, + T_TRAIT => T_TRAIT, + T_ENUM => T_ENUM, + ]; + + /** + * Tokens representing PHP magic constants. + * + * @var array => + * + * @link https://www.php.net/language.constants.predefined PHP Manual on magic constants + */ + public static $magicConstants = [ + T_CLASS_C => T_CLASS_C, + T_DIR => T_DIR, + T_FILE => T_FILE, + T_FUNC_C => T_FUNC_C, + T_LINE => T_LINE, + T_METHOD_C => T_METHOD_C, + T_NS_C => T_NS_C, + T_TRAIT_C => T_TRAIT_C, + ]; + + /** + * Tokens representing context sensitive keywords in PHP. + * + * @var array + * + * https://wiki.php.net/rfc/context_sensitive_lexer + */ + public static $contextSensitiveKeywords = [ + T_ABSTRACT => T_ABSTRACT, + T_ARRAY => T_ARRAY, + T_AS => T_AS, + T_BREAK => T_BREAK, + T_CALLABLE => T_CALLABLE, + T_CASE => T_CASE, + T_CATCH => T_CATCH, + T_CLASS => T_CLASS, + T_CLONE => T_CLONE, + T_CONST => T_CONST, + T_CONTINUE => T_CONTINUE, + T_DECLARE => T_DECLARE, + T_DEFAULT => T_DEFAULT, + T_DO => T_DO, + T_ECHO => T_ECHO, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + T_EMPTY => T_EMPTY, + T_ENDDECLARE => T_ENDDECLARE, + T_ENDFOR => T_ENDFOR, + T_ENDFOREACH => T_ENDFOREACH, + T_ENDIF => T_ENDIF, + T_ENDSWITCH => T_ENDSWITCH, + T_ENDWHILE => T_ENDWHILE, + T_ENUM => T_ENUM, + T_EVAL => T_EVAL, + T_EXIT => T_EXIT, + T_EXTENDS => T_EXTENDS, + T_FINAL => T_FINAL, + T_FINALLY => T_FINALLY, + T_FN => T_FN, + T_FOR => T_FOR, + T_FOREACH => T_FOREACH, + T_FUNCTION => T_FUNCTION, + T_GLOBAL => T_GLOBAL, + T_GOTO => T_GOTO, + T_IF => T_IF, + T_IMPLEMENTS => T_IMPLEMENTS, + T_INCLUDE => T_INCLUDE, + T_INCLUDE_ONCE => T_INCLUDE_ONCE, + T_INSTANCEOF => T_INSTANCEOF, + T_INSTEADOF => T_INSTEADOF, + T_INTERFACE => T_INTERFACE, + T_ISSET => T_ISSET, + T_LIST => T_LIST, + T_LOGICAL_AND => T_LOGICAL_AND, + T_LOGICAL_OR => T_LOGICAL_OR, + T_LOGICAL_XOR => T_LOGICAL_XOR, + T_MATCH => T_MATCH, + T_NAMESPACE => T_NAMESPACE, + T_NEW => T_NEW, + T_PRINT => T_PRINT, + T_PRIVATE => T_PRIVATE, + T_PROTECTED => T_PROTECTED, + T_PUBLIC => T_PUBLIC, + T_READONLY => T_READONLY, + T_REQUIRE => T_REQUIRE, + T_REQUIRE_ONCE => T_REQUIRE_ONCE, + T_RETURN => T_RETURN, + T_STATIC => T_STATIC, + T_SWITCH => T_SWITCH, + T_THROW => T_THROW, + T_TRAIT => T_TRAIT, + T_TRY => T_TRY, + T_UNSET => T_UNSET, + T_USE => T_USE, + T_VAR => T_VAR, + T_WHILE => T_WHILE, + T_YIELD => T_YIELD, + T_YIELD_FROM => T_YIELD_FROM, + ]; + + + /** + * Given a token, returns the name of the token. + * + * If passed an integer, the token name is sourced from PHP's token_name() + * function. If passed a string, it is assumed to be a PHPCS-supplied token + * that begins with PHPCS_T_, so the name is sourced from the token value itself. + * + * @param int|string $token The token to get the name for. + * + * @return string + */ + public static function tokenName($token) + { + if (is_string($token) === false) { + // PHP-supplied token name. + return token_name($token); + } + + return substr($token, 6); + + }//end tokenName() + + + /** + * Returns the highest weighted token type. + * + * Tokens are weighted by their approximate frequency of appearance in code + * - the less frequently they appear in the code, the higher the weighting. + * For example T_CLASS tokens appear very infrequently in a file, and + * therefore have a high weighting. + * + * Returns false if there are no weightings for any of the specified tokens. + * + * @param array $tokens The token types to get the highest weighted + * type for. + * + * @return int|false The highest weighted token. + */ + public static function getHighestWeightedToken(array $tokens) + { + $highest = -1; + $highestType = false; + + $weights = self::$weightings; + + foreach ($tokens as $token) { + if (isset($weights[$token]) === true) { + $weight = $weights[$token]; + } else { + $weight = 0; + } + + if ($weight > $highest) { + $highest = $weight; + $highestType = $token; + } + } + + return $highestType; + + }//end getHighestWeightedToken() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/AllTests.php b/vendor/squizlabs/php_codesniffer/tests/AllTests.php new file mode 100644 index 00000000..9d099c1e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/AllTests.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests; + +if ($GLOBALS['PHP_CODESNIFFER_PEAR'] === false) { + include_once 'Core/AllTests.php'; + include_once 'Standards/AllSniffs.php'; +} else { + include_once 'CodeSniffer/Core/AllTests.php'; + include_once 'CodeSniffer/Standards/AllSniffs.php'; + include_once 'FileList.php'; +} + +// PHPUnit 7 made the TestSuite run() method incompatible with +// older PHPUnit versions due to return type hints, so maintain +// two different suite objects. +$phpunit7 = false; +if (class_exists('\PHPUnit\Runner\Version') === true) { + $version = \PHPUnit\Runner\Version::id(); + if ($version[0] === '7') { + $phpunit7 = true; + } +} + +if ($phpunit7 === true) { + include_once 'TestSuite7.php'; +} else { + include_once 'TestSuite.php'; +} + +class PHP_CodeSniffer_AllTests +{ + + + /** + * Add all PHP_CodeSniffer test suites into a single test suite. + * + * @return \PHPUnit\Framework\TestSuite + */ + public static function suite() + { + $GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'] = []; + $GLOBALS['PHP_CODESNIFFER_TEST_DIRS'] = []; + + // Use a special PHP_CodeSniffer test suite so that we can + // unset our autoload function after the run. + $suite = new TestSuite('PHP CodeSniffer'); + + $suite->addTest(Core\AllTests::suite()); + $suite->addTest(Standards\AllSniffs::suite()); + + return $suite; + + }//end suite() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/AbstractMethodUnitTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/AbstractMethodUnitTest.php new file mode 100644 index 00000000..4d4f5469 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/AbstractMethodUnitTest.php @@ -0,0 +1,140 @@ + + * @copyright 2018-2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Files\DummyFile; +use PHPUnit\Framework\TestCase; + +abstract class AbstractMethodUnitTest extends TestCase +{ + + /** + * The file extension of the test case file (without leading dot). + * + * This allows child classes to overrule the default `inc` with, for instance, + * `js` or `css` when applicable. + * + * @var string + */ + protected static $fileExtension = 'inc'; + + /** + * The \PHP_CodeSniffer\Files\File object containing the parsed contents of the test case file. + * + * @var \PHP_CodeSniffer\Files\File + */ + protected static $phpcsFile; + + + /** + * Initialize & tokenize \PHP_CodeSniffer\Files\File with code from the test case file. + * + * The test case file for a unit test class has to be in the same directory + * directory and use the same file name as the test class, using the .inc extension. + * + * @return void + */ + public static function setUpBeforeClass() + { + $config = new Config(); + $config->standards = ['PSR1']; + + $ruleset = new Ruleset($config); + + // Default to a file with the same name as the test class. Extension is property based. + $relativeCN = str_replace(__NAMESPACE__, '', get_called_class()); + $relativePath = str_replace('\\', DIRECTORY_SEPARATOR, $relativeCN); + $pathToTestFile = realpath(__DIR__).$relativePath.'.'.static::$fileExtension; + + // Make sure the file gets parsed correctly based on the file type. + $contents = 'phpcs_input_file: '.$pathToTestFile.PHP_EOL; + $contents .= file_get_contents($pathToTestFile); + + self::$phpcsFile = new DummyFile($contents, $ruleset, $config); + self::$phpcsFile->process(); + + }//end setUpBeforeClass() + + + /** + * Clean up after finished test. + * + * @return void + */ + public static function tearDownAfterClass() + { + self::$phpcsFile = null; + + }//end tearDownAfterClass() + + + /** + * Get the token pointer for a target token based on a specific comment found on the line before. + * + * Note: the test delimiter comment MUST start with "/* test" to allow this function to + * distinguish between comments used *in* a test and test delimiters. + * + * @param string $commentString The delimiter comment to look for. + * @param int|string|array $tokenType The type of token(s) to look for. + * @param string $tokenContent Optional. The token content for the target token. + * + * @return int + */ + public function getTargetToken($commentString, $tokenType, $tokenContent=null) + { + $start = (self::$phpcsFile->numTokens - 1); + $comment = self::$phpcsFile->findPrevious( + T_COMMENT, + $start, + null, + false, + $commentString + ); + + $tokens = self::$phpcsFile->getTokens(); + $end = ($start + 1); + + // Limit the token finding to between this and the next delimiter comment. + for ($i = ($comment + 1); $i < $end; $i++) { + if ($tokens[$i]['code'] !== T_COMMENT) { + continue; + } + + if (stripos($tokens[$i]['content'], '/* test') === 0) { + $end = $i; + break; + } + } + + $target = self::$phpcsFile->findNext( + $tokenType, + ($comment + 1), + $end, + false, + $tokenContent + ); + + if ($target === false) { + $msg = 'Failed to find test target token for comment string: '.$commentString; + if ($tokenContent !== null) { + $msg .= ' With token content: '.$tokenContent; + } + + $this->assertFalse(true, $msg); + } + + return $target; + + }//end getTargetToken() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/AllTests.php b/vendor/squizlabs/php_codesniffer/tests/Core/AllTests.php new file mode 100644 index 00000000..304690ef --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/AllTests.php @@ -0,0 +1,63 @@ + + * @author Juliette Reinders Folmer + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core; + +use PHP_CodeSniffer\Tests\FileList; +use PHPUnit\TextUI\TestRunner; +use PHPUnit\Framework\TestSuite; + +class AllTests +{ + + + /** + * Prepare the test runner. + * + * @return void + */ + public static function main() + { + TestRunner::run(self::suite()); + + }//end main() + + + /** + * Add all core unit tests into a test suite. + * + * @return \PHPUnit\Framework\TestSuite + */ + public static function suite() + { + $suite = new TestSuite('PHP CodeSniffer Core'); + + $testFileIterator = new FileList(__DIR__, '', '`Test\.php$`Di'); + foreach ($testFileIterator->fileIterator as $file) { + if (strpos($file, 'AbstractMethodUnitTest.php') !== false) { + continue; + } + + include_once $file; + + $class = str_replace(__DIR__, '', $file); + $class = str_replace('.php', '', $class); + $class = str_replace('/', '\\', $class); + $class = 'PHP_CodeSniffer\Tests\Core'.$class; + + $suite->addTestSuite($class); + } + + return $suite; + + }//end suite() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/DetermineLoadedClassTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/DetermineLoadedClassTest.php new file mode 100644 index 00000000..65542b67 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/DetermineLoadedClassTest.php @@ -0,0 +1,118 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Autoloader; + +use PHPUnit\Framework\TestCase; + +class DetermineLoadedClassTest extends TestCase +{ + + + /** + * Load the test files. + * + * @return void + */ + public static function setUpBeforeClass() + { + include __DIR__.'/TestFiles/Sub/C.inc'; + + }//end setUpBeforeClass() + + + /** + * Test for when class list is ordered. + * + * @return void + */ + public function testOrdered() + { + $classesBeforeLoad = [ + 'classes' => [], + 'interfaces' => [], + 'traits' => [], + ]; + + $classesAfterLoad = [ + 'classes' => [ + 'PHP_CodeSniffer\Tests\Core\Autoloader\A', + 'PHP_CodeSniffer\Tests\Core\Autoloader\B', + 'PHP_CodeSniffer\Tests\Core\Autoloader\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', + ], + 'interfaces' => [], + 'traits' => [], + ]; + + $className = \PHP_CodeSniffer\Autoload::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + $this->assertEquals('PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', $className); + + }//end testOrdered() + + + /** + * Test for when class list is out of order. + * + * @return void + */ + public function testUnordered() + { + $classesBeforeLoad = [ + 'classes' => [], + 'interfaces' => [], + 'traits' => [], + ]; + + $classesAfterLoad = [ + 'classes' => [ + 'PHP_CodeSniffer\Tests\Core\Autoloader\A', + 'PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\B', + ], + 'interfaces' => [], + 'traits' => [], + ]; + + $className = \PHP_CodeSniffer\Autoload::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + $this->assertEquals('PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', $className); + + $classesAfterLoad = [ + 'classes' => [ + 'PHP_CodeSniffer\Tests\Core\Autoloader\A', + 'PHP_CodeSniffer\Tests\Core\Autoloader\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\B', + ], + 'interfaces' => [], + 'traits' => [], + ]; + + $className = \PHP_CodeSniffer\Autoload::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + $this->assertEquals('PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', $className); + + $classesAfterLoad = [ + 'classes' => [ + 'PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\A', + 'PHP_CodeSniffer\Tests\Core\Autoloader\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\B', + ], + 'interfaces' => [], + 'traits' => [], + ]; + + $className = \PHP_CodeSniffer\Autoload::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + $this->assertEquals('PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', $className); + + }//end testUnordered() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/A.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/A.inc new file mode 100644 index 00000000..c1433718 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/A.inc @@ -0,0 +1,3 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Files\DummyFile; +use PHPUnit\Framework\TestCase; + +class ErrorSuppressionTest extends TestCase +{ + + + /** + * Test suppressing a single error. + * + * @param string $before Annotation to place before the code. + * @param string $after Annotation to place after the code. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 0. + * + * @dataProvider dataSuppressError + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressError($before, $after, $expectedErrors=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + } + + $content = 'process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + }//end testSuppressError() + + + /** + * Data provider. + * + * @see testSuppressError() + * + * @return array + */ + public function dataSuppressError() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedErrors' => 1, + ], + + // Inline slash comments. + 'disable/enable: slash comment' => [ + 'before' => '// phpcs:disable'.PHP_EOL, + 'after' => '// phpcs:enable', + ], + 'disable/enable: multi-line slash comment, tab indented' => [ + 'before' => "\t".'// For reasons'.PHP_EOL."\t".'// phpcs:disable'.PHP_EOL."\t", + 'after' => "\t".'// phpcs:enable', + ], + 'disable/enable: slash comment, with @' => [ + 'before' => '// @phpcs:disable'.PHP_EOL, + 'after' => '// @phpcs:enable', + ], + 'disable/enable: slash comment, mixed case' => [ + 'before' => '// PHPCS:Disable'.PHP_EOL, + 'after' => '// pHPcs:enabLE', + ], + + // Inline hash comments. + 'disable/enable: hash comment' => [ + 'before' => '# phpcs:disable'.PHP_EOL, + 'after' => '# phpcs:enable', + ], + 'disable/enable: multi-line hash comment, tab indented' => [ + 'before' => "\t".'# For reasons'.PHP_EOL."\t".'# phpcs:disable'.PHP_EOL."\t", + 'after' => "\t".'# phpcs:enable', + ], + 'disable/enable: hash comment, with @' => [ + 'before' => '# @phpcs:disable'.PHP_EOL, + 'after' => '# @phpcs:enable', + ], + 'disable/enable: hash comment, mixed case' => [ + 'before' => '# PHPCS:Disable'.PHP_EOL, + 'after' => '# pHPcs:enabLE', + ], + + // Inline star (block) comments. + 'disable/enable: star comment' => [ + 'before' => '/* phpcs:disable */'.PHP_EOL, + 'after' => '/* phpcs:enable */', + ], + 'disable/enable: multi-line star comment' => [ + 'before' => '/*'.PHP_EOL.' phpcs:disable'.PHP_EOL.' */'.PHP_EOL, + 'after' => '/*'.PHP_EOL.' phpcs:enable'.PHP_EOL.' */', + ], + 'disable/enable: multi-line star comment, each line starred' => [ + 'before' => '/*'.PHP_EOL.' * phpcs:disable'.PHP_EOL.' */'.PHP_EOL, + 'after' => '/*'.PHP_EOL.' * phpcs:enable'.PHP_EOL.' */', + ], + 'disable/enable: multi-line star comment, each line starred, tab indented' => [ + 'before' => "\t".'/*'.PHP_EOL."\t".' * phpcs:disable'.PHP_EOL."\t".' */'.PHP_EOL."\t", + 'after' => "\t".'/*'.PHP_EOL.' * phpcs:enable'.PHP_EOL.' */', + ], + + // Docblock comments. + 'disable/enable: single line docblock comment' => [ + 'before' => '/** phpcs:disable */'.PHP_EOL, + 'after' => '/** phpcs:enable */', + ], + + // Deprecated syntax. + 'old style: slash comment' => [ + 'before' => '// @codingStandardsIgnoreStart'.PHP_EOL, + 'after' => '// @codingStandardsIgnoreEnd', + ], + 'old style: star comment' => [ + 'before' => '/* @codingStandardsIgnoreStart */'.PHP_EOL, + 'after' => '/* @codingStandardsIgnoreEnd */', + ], + 'old style: multi-line star comment' => [ + 'before' => '/*'.PHP_EOL.' @codingStandardsIgnoreStart'.PHP_EOL.' */'.PHP_EOL, + 'after' => '/*'.PHP_EOL.' @codingStandardsIgnoreEnd'.PHP_EOL.' */', + ], + 'old style: single line docblock comment' => [ + 'before' => '/** @codingStandardsIgnoreStart */'.PHP_EOL, + 'after' => '/** @codingStandardsIgnoreEnd */', + ], + ]; + + }//end dataSuppressError() + + + /** + * Test suppressing 1 out of 2 errors. + * + * @param string $before Annotation to place before the code. + * @param string $between Annotation to place between the code. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 1. + * + * @dataProvider dataSuppressSomeErrors + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressSomeErrors($before, $between, $expectedErrors=1) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + }//end testSuppressSomeErrors() + + + /** + * Data provider. + * + * @see testSuppressSomeErrors() + * + * @return array + */ + public function dataSuppressSomeErrors() + { + return [ + 'no suppression' => [ + 'before' => '', + 'between' => '', + 'expectedErrors' => 2, + ], + + // With suppression. + 'disable/enable: slash comment' => [ + 'before' => '// phpcs:disable', + 'between' => '// phpcs:enable', + ], + 'disable/enable: slash comment, with @' => [ + 'before' => '// @phpcs:disable', + 'between' => '// @phpcs:enable', + ], + 'disable/enable: hash comment' => [ + 'before' => '# phpcs:disable', + 'between' => '# phpcs:enable', + ], + 'disable/enable: hash comment, with @' => [ + 'before' => '# @phpcs:disable', + 'between' => '# @phpcs:enable', + ], + 'disable/enable: single line docblock comment' => [ + 'before' => '/** phpcs:disable */', + 'between' => '/** phpcs:enable */', + ], + + // Deprecated syntax. + 'old style: slash comment' => [ + 'before' => '// @codingStandardsIgnoreStart', + 'between' => '// @codingStandardsIgnoreEnd', + ], + 'old style: single line docblock comment' => [ + 'before' => '/** @codingStandardsIgnoreStart */', + 'between' => '/** @codingStandardsIgnoreEnd */', + ], + ]; + + }//end dataSuppressSomeErrors() + + + /** + * Test suppressing a single warning. + * + * @param string $before Annotation to place before the code. + * @param string $after Annotation to place after the code. + * @param int $expectedWarnings Optional. Number of warnings expected. + * Defaults to 0. + * + * @dataProvider dataSuppressWarning + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressWarning($before, $after, $expectedWarnings=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.Commenting.Todo']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testSuppressWarning() + + + /** + * Data provider. + * + * @see testSuppressWarning() + * + * @return array + */ + public function dataSuppressWarning() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedWarnings' => 1, + ], + + // With suppression. + 'disable/enable: slash comment' => [ + 'before' => '// phpcs:disable', + 'after' => '// phpcs:enable', + ], + 'disable/enable: slash comment, with @' => [ + 'before' => '// @phpcs:disable', + 'after' => '// @phpcs:enable', + ], + 'disable/enable: single line docblock comment' => [ + 'before' => '/** phpcs:disable */', + 'after' => '/** phpcs:enable */', + ], + + // Deprecated syntax. + 'old style: slash comment' => [ + 'before' => '// @codingStandardsIgnoreStart', + 'after' => '// @codingStandardsIgnoreEnd', + ], + 'old style: single line docblock comment' => [ + 'before' => '/** @codingStandardsIgnoreStart */', + 'after' => '/** @codingStandardsIgnoreEnd */', + ], + ]; + + }//end dataSuppressWarning() + + + /** + * Test suppressing a single error using a single line ignore. + * + * @param string $before Annotation to place before the code. + * @param string $after Optional. Annotation to place after the code. + * Defaults to an empty string. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 1. + * + * @dataProvider dataSuppressLine + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressLine($before, $after='', $expectedErrors=1) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + }//end testSuppressLine() + + + /** + * Data provider. + * + * @see testSuppressLine() + * + * @return array + */ + public function dataSuppressLine() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedErrors' => 2, + ], + + // With suppression on line before. + 'ignore: line before, slash comment' => ['before' => '// phpcs:ignore'], + 'ignore: line before, slash comment, with @' => ['before' => '// @phpcs:ignore'], + 'ignore: line before, hash comment' => ['before' => '# phpcs:ignore'], + 'ignore: line before, hash comment, with @' => ['before' => '# @phpcs:ignore'], + 'ignore: line before, star comment' => ['before' => '/* phpcs:ignore */'], + 'ignore: line before, star comment, with @' => ['before' => '/* @phpcs:ignore */'], + + // With suppression as trailing comment on code line. + 'ignore: end of line, slash comment' => [ + 'before' => '', + 'after' => ' // phpcs:ignore', + ], + 'ignore: end of line, slash comment, with @' => [ + 'before' => '', + 'after' => ' // @phpcs:ignore', + ], + 'ignore: end of line, hash comment' => [ + 'before' => '', + 'after' => ' # phpcs:ignore', + ], + 'ignore: end of line, hash comment, with @' => [ + 'before' => '', + 'after' => ' # @phpcs:ignore', + ], + + // Deprecated syntax. + 'old style: line before, slash comment' => ['before' => '// @codingStandardsIgnoreLine'], + 'old style: end of line, slash comment' => [ + 'before' => '', + 'after' => ' // @codingStandardsIgnoreLine', + ], + ]; + + }//end dataSuppressLine() + + + /** + * Test suppressing a single error using a single line ignore in the middle of a line. + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressLineMidLine() + { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + + $content = 'process(); + + $this->assertSame(0, $file->getErrorCount()); + $this->assertCount(0, $file->getErrors()); + + }//end testSuppressLineMidLine() + + + /** + * Test suppressing a single error using a single line ignore within a docblock. + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressLineWithinDocblock() + { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.Files.LineLength']; + + $ruleset = new Ruleset($config); + + // Process with @ suppression on line before inside docblock. + $comment = str_repeat('a ', 50); + $content = <<process(); + + $this->assertSame(0, $file->getErrorCount()); + $this->assertCount(0, $file->getErrors()); + + }//end testSuppressLineWithinDocblock() + + + /** + * Test that using a single line ignore does not interfere with other suppressions. + * + * @param string $before Annotation to place before the code. + * @param string $after Annotation to place after the code. + * + * @dataProvider dataNestedSuppressLine + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testNestedSuppressLine($before, $after) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame(0, $file->getErrorCount()); + $this->assertCount(0, $file->getErrors()); + + }//end testNestedSuppressLine() + + + /** + * Data provider. + * + * @see testNestedSuppressLine() + * + * @return array + */ + public function dataNestedSuppressLine() + { + return [ + // Process with disable/enable suppression and no single line suppression. + 'disable/enable: slash comment, no single line suppression' => [ + 'before' => '// phpcs:disable', + 'after' => '// phpcs:enable', + ], + 'disable/enable: slash comment, with @, no single line suppression' => [ + 'before' => '// @phpcs:disable', + 'after' => '// @phpcs:enable', + ], + 'disable/enable: hash comment, no single line suppression' => [ + 'before' => '# phpcs:disable', + 'after' => '# phpcs:enable', + ], + 'old style: slash comment, no single line suppression' => [ + 'before' => '// @codingStandardsIgnoreStart', + 'after' => '// @codingStandardsIgnoreEnd', + ], + + // Process with line suppression nested within disable/enable suppression. + 'disable/enable: slash comment, next line nested single line suppression' => [ + 'before' => '// phpcs:disable'.PHP_EOL.'// phpcs:ignore', + 'after' => '// phpcs:enable', + ], + 'disable/enable: slash comment, with @, next line nested single line suppression' => [ + 'before' => '// @phpcs:disable'.PHP_EOL.'// @phpcs:ignore', + 'after' => '// @phpcs:enable', + ], + 'disable/enable: hash comment, next line nested single line suppression' => [ + 'before' => '# @phpcs:disable'.PHP_EOL.'# @phpcs:ignore', + 'after' => '# @phpcs:enable', + ], + 'old style: slash comment, next line nested single line suppression' => [ + 'before' => '// @codingStandardsIgnoreStart'.PHP_EOL.'// @codingStandardsIgnoreLine', + 'after' => '// @codingStandardsIgnoreEnd', + ], + ]; + + }//end dataNestedSuppressLine() + + + /** + * Test suppressing a scope opener. + * + * @param string $before Annotation to place before the scope opener. + * @param string $after Annotation to place after the scope opener. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 0. + * + * @dataProvider dataSuppressScope + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressScope($before, $after, $expectedErrors=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['PEAR']; + $config->sniffs = ['PEAR.Functions.FunctionDeclaration']; + + $ruleset = new Ruleset($config); + } + + $content = 'foo(); + } +} +EOD; + $file = new DummyFile($content, $ruleset, $config); + $file->process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + }//end testSuppressScope() + + + /** + * Data provider. + * + * @see testSuppressScope() + * + * @return array + */ + public function dataSuppressScope() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedErrors' => 1, + ], + + // Process with suppression. + 'disable/enable: slash comment' => [ + 'before' => '//phpcs:disable', + 'after' => '//phpcs:enable', + ], + 'disable/enable: slash comment, with @' => [ + 'before' => '//@phpcs:disable', + 'after' => '//@phpcs:enable', + ], + 'disable/enable: hash comment' => [ + 'before' => '#phpcs:disable', + 'after' => '#phpcs:enable', + ], + 'disable/enable: single line docblock comment' => [ + 'before' => '/** phpcs:disable */', + 'after' => '/** phpcs:enable */', + ], + 'disable/enable: single line docblock comment, with @' => [ + 'before' => '/** @phpcs:disable */', + 'after' => '/** @phpcs:enable */', + ], + + // Deprecated syntax. + 'old style: start/end, slash comment' => [ + 'before' => '//@codingStandardsIgnoreStart', + 'after' => '//@codingStandardsIgnoreEnd', + ], + 'old style: start/end, single line docblock comment' => [ + 'before' => '/** @codingStandardsIgnoreStart */', + 'after' => '/** @codingStandardsIgnoreEnd */', + ], + ]; + + }//end dataSuppressScope() + + + /** + * Test suppressing a whole file. + * + * @param string $before Annotation to place before the code. + * @param string $after Optional. Annotation to place after the code. + * Defaults to an empty string. + * @param int $expectedWarnings Optional. Number of warnings expected. + * Defaults to 0. + * + * @dataProvider dataSuppressFile + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressFile($before, $after='', $expectedWarnings=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.Commenting.Todo']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testSuppressFile() + + + /** + * Data provider. + * + * @see testSuppressFile() + * + * @return array + */ + public function dataSuppressFile() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedErrors' => 1, + ], + + // Process with suppression. + 'ignoreFile: start of file, slash comment' => ['before' => '// phpcs:ignoreFile'], + 'ignoreFile: start of file, slash comment, with @' => ['before' => '// @phpcs:ignoreFile'], + 'ignoreFile: start of file, slash comment, mixed case' => ['before' => '// PHPCS:Ignorefile'], + 'ignoreFile: start of file, hash comment' => ['before' => '# phpcs:ignoreFile'], + 'ignoreFile: start of file, hash comment, with @' => ['before' => '# @phpcs:ignoreFile'], + 'ignoreFile: start of file, single-line star comment' => ['before' => '/* phpcs:ignoreFile */'], + 'ignoreFile: start of file, multi-line star comment' => [ + 'before' => '/*'.PHP_EOL.' phpcs:ignoreFile'.PHP_EOL.' */', + ], + 'ignoreFile: start of file, single-line docblock comment' => ['before' => '/** phpcs:ignoreFile */'], + + // Process late comment. + 'ignoreFile: late comment, slash comment' => [ + 'before' => '', + 'after' => '// phpcs:ignoreFile', + ], + + // Deprecated syntax. + 'old style: start of file, slash comment' => ['before' => '// @codingStandardsIgnoreFile'], + 'old style: start of file, single-line star comment' => ['before' => '/* @codingStandardsIgnoreFile */'], + 'old style: start of file, multi-line star comment' => [ + 'before' => '/*'.PHP_EOL.' @codingStandardsIgnoreFile'.PHP_EOL.' */', + ], + 'old style: start of file, single-line docblock comment' => ['before' => '/** @codingStandardsIgnoreFile */'], + + // Deprecated syntax, late comment. + 'old style: late comment, slash comment' => [ + 'before' => '', + 'after' => '// @codingStandardsIgnoreFile', + ], + ]; + + }//end dataSuppressFile() + + + /** + * Test disabling specific sniffs. + * + * @param string $before Annotation to place before the code. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 0. + * @param int $expectedWarnings Optional. Number of warnings expected. + * Defaults to 0. + * + * @dataProvider dataDisableSelected + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testDisableSelected($before, $expectedErrors=0, $expectedWarnings=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = [ + 'Generic.PHP.LowerCaseConstant', + 'Generic.Commenting.Todo', + ]; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testDisableSelected() + + + /** + * Data provider. + * + * @see testDisableSelected() + * + * @return array + */ + public function dataDisableSelected() + { + return [ + // Single sniff. + 'disable: single sniff' => [ + 'before' => '// phpcs:disable Generic.Commenting.Todo', + 'expectedErrors' => 1, + ], + 'disable: single sniff with reason' => [ + 'before' => '# phpcs:disable Generic.Commenting.Todo -- for reasons', + 'expectedErrors' => 1, + ], + 'disable: single sniff, docblock' => [ + 'before' => '/**'.PHP_EOL.' * phpcs:disable Generic.Commenting.Todo'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + ], + 'disable: single sniff, docblock, with @' => [ + 'before' => '/**'.PHP_EOL.' * @phpcs:disable Generic.Commenting.Todo'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + ], + + // Multiple sniffs. + 'disable: multiple sniffs in one comment' => ['before' => '// phpcs:disable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant'], + 'disable: multiple sniff in multiple comments' => [ + 'before' => '// phpcs:disable Generic.Commenting.Todo'.PHP_EOL.'// phpcs:disable Generic.PHP.LowerCaseConstant', + ], + + // Selectiveness variations. + 'disable: complete category' => [ + 'before' => '// phpcs:disable Generic.Commenting', + 'expectedErrors' => 1, + ], + 'disable: whole standard' => ['before' => '// phpcs:disable Generic'], + 'disable: single errorcode' => [ + 'before' => '# @phpcs:disable Generic.Commenting.Todo.TaskFound', + 'expectedErrors' => 1, + ], + 'disable: single errorcode and a category' => ['before' => '// phpcs:disable Generic.PHP.LowerCaseConstant.Found,Generic.Commenting'], + + // Wrong category/sniff/code. + 'disable: wrong error code and category' => [ + 'before' => '/**'.PHP_EOL.' * phpcs:disable Generic.PHP.LowerCaseConstant.Upper,Generic.Comments'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: wrong category, docblock' => [ + 'before' => '/**'.PHP_EOL.' * phpcs:disable Generic.Files'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: wrong category, docblock, with @' => [ + 'before' => '/**'.PHP_EOL.' * @phpcs:disable Generic.Files'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + ]; + + }//end dataDisableSelected() + + + /** + * Test re-enabling specific sniffs that have been disabled. + * + * @param string $code Code pattern to check. + * @param int $expectedErrors Number of errors expected. + * @param int $expectedWarnings Number of warnings expected. + * + * @dataProvider dataEnableSelected + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testEnableSelected($code, $expectedErrors, $expectedWarnings) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = [ + 'Generic.PHP.LowerCaseConstant', + 'Generic.Commenting.Todo', + ]; + + $ruleset = new Ruleset($config); + } + + $content = 'process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testEnableSelected() + + + /** + * Data provider. + * + * @see testEnableSelected() + * + * @return array + */ + public function dataEnableSelected() + { + return [ + 'disable/enable: a single sniff' => [ + 'code' => ' + // phpcs:disable Generic.Commenting.Todo + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable/enable: multiple sniffs' => [ + 'code' => ' + // phpcs:disable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant + //TODO: write some code + $var = FALSE;', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: multiple sniffs; enable: one' => [ + 'code' => ' + # phpcs:disable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant + $var = FALSE; + //TODO: write some code + # phpcs:enable Generic.Commenting.Todo + //TODO: write some code + $var = FALSE;', + 'expectedErrors' => 0, + 'expectedWarnings' => 1, + ], + 'disable/enable: complete category' => [ + 'code' => ' + // phpcs:disable Generic.Commenting + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable/enable: whole standard' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic + //TODO: write some code', + 'expectedErrors' => 0, + 'expectedWarnings' => 1, + ], + 'disable: whole standard; enable: category from the standard' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting + //TODO: write some code', + 'expectedErrors' => 0, + 'expectedWarnings' => 1, + ], + 'disable: a category; enable: the whole standard containing the category' => [ + 'code' => ' + # phpcs:disable Generic.Commenting + $var = FALSE; + //TODO: write some code + # phpcs:enable Generic + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: single sniff; enable: the category containing the sniff' => [ + 'code' => ' + // phpcs:disable Generic.Commenting.Todo + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: whole standard; enable: single sniff from the standard' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo + //TODO: write some code', + 'expectedErrors' => 0, + 'expectedWarnings' => 1, + ], + 'disable: whole standard; enable: single sniff from the standard; disable: that same sniff; enable: everything' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo + //TODO: write some code + // phpcs:disable Generic.Commenting.Todo + //TODO: write some code + // phpcs:enable + //TODO: write some code', + 'expectedErrors' => 0, + 'expectedWarnings' => 2, + ], + 'disable: whole standard; enable: single sniff from the standard; enable: other sniff from the standard' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo + //TODO: write some code + $var = FALSE; + // phpcs:enable Generic.PHP.LowerCaseConstant + //TODO: write some code + $var = FALSE;', + 'expectedErrors' => 1, + 'expectedWarnings' => 2, + ], + ]; + + }//end dataEnableSelected() + + + /** + * Test ignoring specific sniffs. + * + * @param string $before Annotation to place before the code. + * @param int $expectedErrors Number of errors expected. + * @param int $expectedWarnings Number of warnings expected. + * + * @dataProvider dataIgnoreSelected + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testIgnoreSelected($before, $expectedErrors, $expectedWarnings) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = [ + 'Generic.PHP.LowerCaseConstant', + 'Generic.Commenting.Todo', + ]; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testIgnoreSelected() + + + /** + * Data provider. + * + * @see testIgnoreSelected() + * + * @return array + */ + public function dataIgnoreSelected() + { + return [ + 'no suppression' => [ + 'before' => '', + 'expectedErrors' => 2, + 'expectedWarnings' => 2, + ], + + // With suppression. + 'ignore: single sniff' => [ + 'before' => '// phpcs:ignore Generic.Commenting.Todo', + 'expectedErrors' => 2, + 'expectedWarnings' => 1, + ], + 'ignore: multiple sniffs' => [ + 'before' => '// phpcs:ignore Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: single sniff; ignore: single sniff' => [ + 'before' => '// phpcs:disable Generic.Commenting.Todo'.PHP_EOL.'// phpcs:ignore Generic.PHP.LowerCaseConstant', + 'expectedErrors' => 1, + 'expectedWarnings' => 0, + ], + 'ignore: category of sniffs' => [ + 'before' => '# phpcs:ignore Generic.Commenting', + 'expectedErrors' => 2, + 'expectedWarnings' => 1, + ], + 'ignore: whole standard' => [ + 'before' => '// phpcs:ignore Generic', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + ]; + + }//end dataIgnoreSelected() + + + /** + * Test ignoring specific sniffs. + * + * @param string $code Code pattern to check. + * @param int $expectedErrors Number of errors expected. + * @param int $expectedWarnings Number of warnings expected. + * + * @dataProvider dataCommenting + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testCommenting($code, $expectedErrors, $expectedWarnings) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = [ + 'Generic.PHP.LowerCaseConstant', + 'Generic.Commenting.Todo', + ]; + + $ruleset = new Ruleset($config); + } + + $content = 'process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testCommenting() + + + /** + * Data provider. + * + * @see testCommenting() + * + * @return array + */ + public function dataCommenting() + { + return [ + 'ignore: single sniff' => [ + 'code' => ' + // phpcs:ignore Generic.Commenting.Todo -- Because reasons + $var = FALSE; //TODO: write some code + $var = FALSE; //TODO: write some code', + 'expectedErrors' => 2, + 'expectedWarnings' => 1, + ], + 'disable: single sniff; enable: same sniff - test whitespace handling around reason delimiter' => [ + 'code' => ' + // phpcs:disable Generic.Commenting.Todo --Because reasons + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo -- Because reasons + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: single sniff, multi-line comment' => [ + 'code' => ' + /* + Disable some checks + phpcs:disable Generic.Commenting.Todo + */ + $var = FALSE; + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 0, + ], + 'ignore: single sniff, multi-line slash comment' => [ + 'code' => ' + // Turn off a check for the next line of code. + // phpcs:ignore Generic.Commenting.Todo + $var = FALSE; //TODO: write some code + $var = FALSE; //TODO: write some code', + 'expectedErrors' => 2, + 'expectedWarnings' => 1, + ], + 'enable before disable, sniff not in standard' => [ + 'code' => ' + // phpcs:enable Generic.PHP.NoSilencedErrors -- Because reasons + $var = @delete( $filename ); + ', + 'expectedErrors' => 0, + 'expectedWarnings' => 0, + ], + ]; + + }//end dataCommenting() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.inc new file mode 100644 index 00000000..6dfd0a28 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.inc @@ -0,0 +1,105 @@ + fn() => return 1, + 'b' => fn() => return 1, +]; + +/* testStaticArrowFunction */ +static fn ($a) => $a; + +/* testArrowFunctionReturnValue */ +fn(): array => [a($a, $b)]; + +/* testArrowFunctionAsArgument */ +$foo = foo( + fn() => bar() +); + +/* testArrowFunctionWithArrayAsArgument */ +$foo = foo( + fn() => [$row[0], $row[3]] +); + +$match = match ($a) { + /* testMatchCase */ + 1 => 'foo', + /* testMatchDefault */ + default => 'bar' +}; + +$match = match ($a) { + /* testMatchMultipleCase */ + 1, 2, => $a * $b, + /* testMatchDefaultComma */ + default, => 'something' +}; + +match ($pressedKey) { + /* testMatchFunctionCall */ + Key::RETURN_ => save($value, $user) +}; + +$result = match (true) { + /* testMatchFunctionCallArm */ + str_contains($text, 'Welcome') || str_contains($text, 'Hello') => 'en', + str_contains($text, 'Bienvenue') || str_contains($text, 'Bonjour') => 'fr', + default => 'pl' +}; + +/* testMatchClosure */ +$result = match ($key) { + 1 => function($a, $b) {}, + 2 => function($b, $c) {}, +}; + +/* testMatchArray */ +$result = match ($key) { + 1 => [1,2,3], + 2 => [1 => one(), 2 => two()], +}; + +/* testNestedMatch */ +$result = match ($key) { + 1 => match ($key) { + 1 => 'one', + 2 => 'two', + }, + 2 => match ($key) { + 1 => 'two', + 2 => 'one', + }, +}; + +return 0; diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.php new file mode 100644 index 00000000..7bff26b5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.php @@ -0,0 +1,415 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class FindEndOfStatementTest extends AbstractMethodUnitTest +{ + + + /** + * Test a simple assignment. + * + * @return void + */ + public function testSimpleAssignment() + { + $start = $this->getTargetToken('/* testSimpleAssignment */', T_VARIABLE); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 5), $found); + + }//end testSimpleAssignment() + + + /** + * Test a direct call to a control structure. + * + * @return void + */ + public function testControlStructure() + { + $start = $this->getTargetToken('/* testControlStructure */', T_WHILE); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 6), $found); + + }//end testControlStructure() + + + /** + * Test the assignment of a closure. + * + * @return void + */ + public function testClosureAssignment() + { + $start = $this->getTargetToken('/* testClosureAssignment */', T_VARIABLE, '$a'); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 13), $found); + + }//end testClosureAssignment() + + + /** + * Test using a heredoc in a function argument. + * + * @return void + */ + public function testHeredocFunctionArg() + { + // Find the end of the function. + $start = $this->getTargetToken('/* testHeredocFunctionArg */', T_STRING, 'myFunction'); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 10), $found); + + // Find the end of the heredoc. + $start += 2; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 4), $found); + + // Find the end of the last arg. + $start = ($found + 2); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame($start, $found); + + }//end testHeredocFunctionArg() + + + /** + * Test parts of a switch statement. + * + * @return void + */ + public function testSwitch() + { + // Find the end of the switch. + $start = $this->getTargetToken('/* testSwitch */', T_SWITCH); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 28), $found); + + // Find the end of the case. + $start += 9; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 8), $found); + + // Find the end of default case. + $start += 11; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 6), $found); + + }//end testSwitch() + + + /** + * Test statements that are array values. + * + * @return void + */ + public function testStatementAsArrayValue() + { + // Test short array syntax. + $start = $this->getTargetToken('/* testStatementAsArrayValue */', T_NEW); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 2), $found); + + // Test long array syntax. + $start += 12; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 2), $found); + + // Test same statement outside of array. + $start += 10; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 3), $found); + + }//end testStatementAsArrayValue() + + + /** + * Test a use group. + * + * @return void + */ + public function testUseGroup() + { + $start = $this->getTargetToken('/* testUseGroup */', T_USE); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 23), $found); + + }//end testUseGroup() + + + /** + * Test arrow function as array value. + * + * @return void + */ + public function testArrowFunctionArrayValue() + { + $start = $this->getTargetToken('/* testArrowFunctionArrayValue */', T_FN); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 9), $found); + + }//end testArrowFunctionArrayValue() + + + /** + * Test static arrow function. + * + * @return void + */ + public function testStaticArrowFunction() + { + $static = $this->getTargetToken('/* testStaticArrowFunction */', T_STATIC); + $fn = $this->getTargetToken('/* testStaticArrowFunction */', T_FN); + + $endOfStatementStatic = self::$phpcsFile->findEndOfStatement($static); + $endOfStatementFn = self::$phpcsFile->findEndOfStatement($fn); + + $this->assertSame($endOfStatementFn, $endOfStatementStatic); + + }//end testStaticArrowFunction() + + + /** + * Test arrow function with return value. + * + * @return void + */ + public function testArrowFunctionReturnValue() + { + $start = $this->getTargetToken('/* testArrowFunctionReturnValue */', T_FN); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 18), $found); + + }//end testArrowFunctionReturnValue() + + + /** + * Test arrow function used as a function argument. + * + * @return void + */ + public function testArrowFunctionAsArgument() + { + $start = $this->getTargetToken('/* testArrowFunctionAsArgument */', T_FN); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 8), $found); + + }//end testArrowFunctionAsArgument() + + + /** + * Test arrow function with arrays used as a function argument. + * + * @return void + */ + public function testArrowFunctionWithArrayAsArgument() + { + $start = $this->getTargetToken('/* testArrowFunctionWithArrayAsArgument */', T_FN); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 17), $found); + + }//end testArrowFunctionWithArrayAsArgument() + + + /** + * Test simple match expression case. + * + * @return void + */ + public function testMatchCase() + { + $start = $this->getTargetToken('/* testMatchCase */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 5), $found); + + $start = $this->getTargetToken('/* testMatchCase */', T_CONSTANT_ENCAPSED_STRING); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 1), $found); + + }//end testMatchCase() + + + /** + * Test simple match expression default case. + * + * @return void + */ + public function testMatchDefault() + { + $start = $this->getTargetToken('/* testMatchDefault */', T_MATCH_DEFAULT); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 4), $found); + + $start = $this->getTargetToken('/* testMatchDefault */', T_CONSTANT_ENCAPSED_STRING); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame($start, $found); + + }//end testMatchDefault() + + + /** + * Test multiple comma-separated match expression case values. + * + * @return void + */ + public function testMatchMultipleCase() + { + $start = $this->getTargetToken('/* testMatchMultipleCase */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + $this->assertSame(($start + 13), $found); + + $start += 6; + $found = self::$phpcsFile->findEndOfStatement($start); + $this->assertSame(($start + 7), $found); + + }//end testMatchMultipleCase() + + + /** + * Test match expression default case with trailing comma. + * + * @return void + */ + public function testMatchDefaultComma() + { + $start = $this->getTargetToken('/* testMatchDefaultComma */', T_MATCH_DEFAULT); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 5), $found); + + }//end testMatchDefaultComma() + + + /** + * Test match expression with function call. + * + * @return void + */ + public function testMatchFunctionCall() + { + $start = $this->getTargetToken('/* testMatchFunctionCall */', T_STRING); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 12), $found); + + $start += 8; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 1), $found); + + }//end testMatchFunctionCall() + + + /** + * Test match expression with function call in the arm. + * + * @return void + */ + public function testMatchFunctionCallArm() + { + // Check the first case. + $start = $this->getTargetToken('/* testMatchFunctionCallArm */', T_STRING); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 21), $found); + + // Check the second case. + $start += 24; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 21), $found); + + }//end testMatchFunctionCallArm() + + + /** + * Test match expression with closure. + * + * @return void + */ + public function testMatchClosure() + { + $start = $this->getTargetToken('/* testMatchClosure */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 14), $found); + + $start += 17; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 14), $found); + + }//end testMatchClosure() + + + /** + * Test match expression with array declaration. + * + * @return void + */ + public function testMatchArray() + { + $start = $this->getTargetToken('/* testMatchArray */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 11), $found); + + $start += 14; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 22), $found); + + }//end testMatchArray() + + + /** + * Test nested match expressions. + * + * @return void + */ + public function testNestedMatch() + { + $start = $this->getTargetToken('/* testNestedMatch */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 30), $found); + + $start += 21; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 5), $found); + + }//end testNestedMatch() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/File/FindExtendedClassNameTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/File/FindExtendedClassNameTest.inc new file mode 100644 index 00000000..aead06cd --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/File/FindExtendedClassNameTest.inc @@ -0,0 +1,37 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class FindExtendedClassNameTest extends AbstractMethodUnitTest +{ + + + /** + * Test retrieving the name of the class being extended by another class + * (or interface). + * + * @param string $identifier Comment which precedes the test case. + * @param bool $expected Expected function output. + * + * @dataProvider dataExtendedClass + * + * @return void + */ + public function testFindExtendedClassName($identifier, $expected) + { + $OOToken = $this->getTargetToken($identifier, [T_CLASS, T_ANON_CLASS, T_INTERFACE]); + $result = self::$phpcsFile->findExtendedClassName($OOToken); + $this->assertSame($expected, $result); + + }//end testFindExtendedClassName() + + + /** + * Data provider for the FindExtendedClassName test. + * + * @see testFindExtendedClassName() + * + * @return array + */ + public function dataExtendedClass() + { + return [ + [ + '/* testExtendedClass */', + 'testFECNClass', + ], + [ + '/* testNamespacedClass */', + '\PHP_CodeSniffer\Tests\Core\File\testFECNClass', + ], + [ + '/* testNonExtendedClass */', + false, + ], + [ + '/* testInterface */', + false, + ], + [ + '/* testInterfaceThatExtendsInterface */', + 'testFECNInterface', + ], + [ + '/* testInterfaceThatExtendsFQCNInterface */', + '\PHP_CodeSniffer\Tests\Core\File\testFECNInterface', + ], + [ + '/* testNestedExtendedClass */', + false, + ], + [ + '/* testNestedExtendedAnonClass */', + 'testFECNAnonClass', + ], + [ + '/* testClassThatExtendsAndImplements */', + 'testFECNClass', + ], + [ + '/* testClassThatImplementsAndExtends */', + 'testFECNClass', + ], + ]; + + }//end dataExtendedClass() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/File/FindImplementedInterfaceNamesTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/File/FindImplementedInterfaceNamesTest.inc new file mode 100644 index 00000000..44c0f643 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/File/FindImplementedInterfaceNamesTest.inc @@ -0,0 +1,35 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class FindImplementedInterfaceNamesTest extends AbstractMethodUnitTest +{ + + + /** + * Test retrieving the name(s) of the interfaces being implemented by a class. + * + * @param string $identifier Comment which precedes the test case. + * @param bool $expected Expected function output. + * + * @dataProvider dataImplementedInterface + * + * @return void + */ + public function testFindImplementedInterfaceNames($identifier, $expected) + { + $OOToken = $this->getTargetToken($identifier, [T_CLASS, T_ANON_CLASS, T_INTERFACE, T_ENUM]); + $result = self::$phpcsFile->findImplementedInterfaceNames($OOToken); + $this->assertSame($expected, $result); + + }//end testFindImplementedInterfaceNames() + + + /** + * Data provider for the FindImplementedInterfaceNames test. + * + * @see testFindImplementedInterfaceNames() + * + * @return array + */ + public function dataImplementedInterface() + { + return [ + [ + '/* testImplementedClass */', + ['testFIINInterface'], + ], + [ + '/* testMultiImplementedClass */', + [ + 'testFIINInterface', + 'testFIINInterface2', + ], + ], + [ + '/* testNamespacedClass */', + ['\PHP_CodeSniffer\Tests\Core\File\testFIINInterface'], + ], + [ + '/* testNonImplementedClass */', + false, + ], + [ + '/* testInterface */', + false, + ], + [ + '/* testClassThatExtendsAndImplements */', + [ + 'InterfaceA', + '\NameSpaced\Cat\InterfaceB', + ], + ], + [ + '/* testClassThatImplementsAndExtends */', + [ + '\InterfaceA', + 'InterfaceB', + ], + ], + [ + '/* testBackedEnumWithoutImplements */', + false, + ], + [ + '/* testEnumImplements */', + ['Colorful'], + ], + [ + '/* testBackedEnumImplements */', + [ + 'Colorful', + '\Deck', + ], + ], + ]; + + }//end dataImplementedInterface() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.inc new file mode 100644 index 00000000..ce9dfad3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.inc @@ -0,0 +1,123 @@ + $foo + $bar, 'b' => true]; + +/* testUseGroup */ +use Vendor\Package\{ClassA as A, ClassB, ClassC as C}; + +$a = [ + /* testArrowFunctionArrayValue */ + 'a' => fn() => return 1, + 'b' => fn() => return 1, +]; + +/* testStaticArrowFunction */ +static fn ($a) => $a; + +/* testArrowFunctionReturnValue */ +fn(): array => [a($a, $b)]; + +/* testArrowFunctionAsArgument */ +$foo = foo( + fn() => bar() +); + +/* testArrowFunctionWithArrayAsArgument */ +$foo = foo( + fn() => [$row[0], $row[3]] +); + +$match = match ($a) { + /* testMatchCase */ + 1 => 'foo', + /* testMatchDefault */ + default => 'bar' +}; + +$match = match ($a) { + /* testMatchMultipleCase */ + 1, 2, => $a * $b, + /* testMatchDefaultComma */ + default, => 'something' +}; + +match ($pressedKey) { + /* testMatchFunctionCall */ + Key::RETURN_ => save($value, $user) +}; + +$result = match (true) { + /* testMatchFunctionCallArm */ + str_contains($text, 'Welcome') || str_contains($text, 'Hello') => 'en', + str_contains($text, 'Bienvenue') || str_contains($text, 'Bonjour') => 'fr', + default => 'pl' +}; + +/* testMatchClosure */ +$result = match ($key) { + 1 => function($a, $b) {}, + 2 => function($b, $c) {}, +}; + +/* testMatchArray */ +$result = match ($key) { + 1 => [1,2,3], + 2 => [1 => one($a, $b), 2 => two($b, $c)], + 3 => [], +}; + +/* testNestedMatch */ +$result = match ($key) { + 1 => match ($key) { + 1 => 'one', + 2 => 'two', + }, + 2 => match ($key) { + 1 => 'two', + 2 => 'one', + }, +}; + +return 0; + +/* testOpenTag */ +?> +

    Test

    +', foo(), ''; + +/* testOpenTagWithEcho */ +?> +

    Test

    +', foo(), ''; diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.php new file mode 100644 index 00000000..464021f6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.php @@ -0,0 +1,503 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class FindStartOfStatementTest extends AbstractMethodUnitTest +{ + + + /** + * Test a simple assignment. + * + * @return void + */ + public function testSimpleAssignment() + { + $start = $this->getTargetToken('/* testSimpleAssignment */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 5), $found); + + }//end testSimpleAssignment() + + + /** + * Test a function call. + * + * @return void + */ + public function testFunctionCall() + { + $start = $this->getTargetToken('/* testFunctionCall */', T_CLOSE_PARENTHESIS); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + }//end testFunctionCall() + + + /** + * Test a function call. + * + * @return void + */ + public function testFunctionCallArgument() + { + $start = $this->getTargetToken('/* testFunctionCallArgument */', T_VARIABLE, '$b'); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame($start, $found); + + }//end testFunctionCallArgument() + + + /** + * Test a direct call to a control structure. + * + * @return void + */ + public function testControlStructure() + { + $start = $this->getTargetToken('/* testControlStructure */', T_CLOSE_CURLY_BRACKET); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + }//end testControlStructure() + + + /** + * Test the assignment of a closure. + * + * @return void + */ + public function testClosureAssignment() + { + $start = $this->getTargetToken('/* testClosureAssignment */', T_CLOSE_CURLY_BRACKET); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 12), $found); + + }//end testClosureAssignment() + + + /** + * Test using a heredoc in a function argument. + * + * @return void + */ + public function testHeredocFunctionArg() + { + // Find the start of the function. + $start = $this->getTargetToken('/* testHeredocFunctionArg */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 10), $found); + + // Find the start of the heredoc. + $start -= 4; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 4), $found); + + // Find the start of the last arg. + $start += 2; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame($start, $found); + + }//end testHeredocFunctionArg() + + + /** + * Test parts of a switch statement. + * + * @return void + */ + public function testSwitch() + { + // Find the start of the switch. + $start = $this->getTargetToken('/* testSwitch */', T_CLOSE_CURLY_BRACKET); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 47), $found); + + // Find the start of default case. + $start -= 5; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + // Find the start of the second case. + $start -= 12; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 5), $found); + + // Find the start of the first case. + $start -= 13; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 8), $found); + + // Test inside the first case. + $start--; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + }//end testSwitch() + + + /** + * Test statements that are array values. + * + * @return void + */ + public function testStatementAsArrayValue() + { + // Test short array syntax. + $start = $this->getTargetToken('/* testStatementAsArrayValue */', T_STRING, 'Datetime'); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 2), $found); + + // Test long array syntax. + $start += 12; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 2), $found); + + // Test same statement outside of array. + $start++; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 9), $found); + + // Test with an array index. + $start += 17; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 5), $found); + + }//end testStatementAsArrayValue() + + + /** + * Test a use group. + * + * @return void + */ + public function testUseGroup() + { + $start = $this->getTargetToken('/* testUseGroup */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 23), $found); + + }//end testUseGroup() + + + /** + * Test arrow function as array value. + * + * @return void + */ + public function testArrowFunctionArrayValue() + { + $start = $this->getTargetToken('/* testArrowFunctionArrayValue */', T_COMMA); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 9), $found); + + }//end testArrowFunctionArrayValue() + + + /** + * Test static arrow function. + * + * @return void + */ + public function testStaticArrowFunction() + { + $start = $this->getTargetToken('/* testStaticArrowFunction */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 11), $found); + + }//end testStaticArrowFunction() + + + /** + * Test arrow function with return value. + * + * @return void + */ + public function testArrowFunctionReturnValue() + { + $start = $this->getTargetToken('/* testArrowFunctionReturnValue */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 18), $found); + + }//end testArrowFunctionReturnValue() + + + /** + * Test arrow function used as a function argument. + * + * @return void + */ + public function testArrowFunctionAsArgument() + { + $start = $this->getTargetToken('/* testArrowFunctionAsArgument */', T_FN); + $start += 8; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 8), $found); + + }//end testArrowFunctionAsArgument() + + + /** + * Test arrow function with arrays used as a function argument. + * + * @return void + */ + public function testArrowFunctionWithArrayAsArgument() + { + $start = $this->getTargetToken('/* testArrowFunctionWithArrayAsArgument */', T_FN); + $start += 17; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 17), $found); + + }//end testArrowFunctionWithArrayAsArgument() + + + /** + * Test simple match expression case. + * + * @return void + */ + public function testMatchCase() + { + $start = $this->getTargetToken('/* testMatchCase */', T_COMMA); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + }//end testMatchCase() + + + /** + * Test simple match expression default case. + * + * @return void + */ + public function testMatchDefault() + { + $start = $this->getTargetToken('/* testMatchDefault */', T_CONSTANT_ENCAPSED_STRING, "'bar'"); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame($start, $found); + + }//end testMatchDefault() + + + /** + * Test multiple comma-separated match expression case values. + * + * @return void + */ + public function testMatchMultipleCase() + { + $start = $this->getTargetToken('/* testMatchMultipleCase */', T_MATCH_ARROW); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + $start += 6; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 4), $found); + + }//end testMatchMultipleCase() + + + /** + * Test match expression default case with trailing comma. + * + * @return void + */ + public function testMatchDefaultComma() + { + $start = $this->getTargetToken('/* testMatchDefaultComma */', T_MATCH_ARROW); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 3), $found); + + $start += 2; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame($start, $found); + + }//end testMatchDefaultComma() + + + /** + * Test match expression with function call. + * + * @return void + */ + public function testMatchFunctionCall() + { + $start = $this->getTargetToken('/* testMatchFunctionCall */', T_CLOSE_PARENTHESIS); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + }//end testMatchFunctionCall() + + + /** + * Test match expression with function call in the arm. + * + * @return void + */ + public function testMatchFunctionCallArm() + { + // Check the first case. + $start = $this->getTargetToken('/* testMatchFunctionCallArm */', T_MATCH_ARROW); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 18), $found); + + // Check the second case. + $start += 24; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 18), $found); + + }//end testMatchFunctionCallArm() + + + /** + * Test match expression with closure. + * + * @return void + */ + public function testMatchClosure() + { + $start = $this->getTargetToken('/* testMatchClosure */', T_LNUMBER); + $start += 14; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 10), $found); + + $start += 17; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 10), $found); + + }//end testMatchClosure() + + + /** + * Test match expression with array declaration. + * + * @return void + */ + public function testMatchArray() + { + // Start of first case statement. + $start = $this->getTargetToken('/* testMatchArray */', T_LNUMBER); + $found = self::$phpcsFile->findStartOfStatement($start); + $this->assertSame($start, $found); + + // Comma after first statement. + $start += 11; + $found = self::$phpcsFile->findStartOfStatement($start); + $this->assertSame(($start - 7), $found); + + // Start of second case statement. + $start += 3; + $found = self::$phpcsFile->findStartOfStatement($start); + $this->assertSame($start, $found); + + // Comma after first statement. + $start += 30; + $found = self::$phpcsFile->findStartOfStatement($start); + $this->assertSame(($start - 26), $found); + + }//end testMatchArray() + + + /** + * Test nested match expressions. + * + * @return void + */ + public function testNestedMatch() + { + $start = $this->getTargetToken('/* testNestedMatch */', T_LNUMBER); + $start += 30; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 26), $found); + + $start -= 4; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + $start -= 3; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 2), $found); + + }//end testNestedMatch() + + + /** + * Test nested match expressions. + * + * @return void + */ + public function testOpenTag() + { + $start = $this->getTargetToken('/* testOpenTag */', T_OPEN_TAG); + $start += 2; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + }//end testOpenTag() + + + /** + * Test nested match expressions. + * + * @return void + */ + public function testOpenTagWithEcho() + { + $start = $this->getTargetToken('/* testOpenTagWithEcho */', T_OPEN_TAG_WITH_ECHO); + $start += 3; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + }//end testOpenTagWithEcho() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.inc new file mode 100644 index 00000000..f40b6021 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.inc @@ -0,0 +1,304 @@ + 'a', 'b' => 'b' ), + /* testGroupPrivate 3 */ + $varQ = 'string', + /* testGroupPrivate 4 */ + $varR = 123, + /* testGroupPrivate 5 */ + $varS = ONE / self::THREE, + /* testGroupPrivate 6 */ + $varT = [ + 'a' => 'a', + 'b' => 'b' + ], + /* testGroupPrivate 7 */ + $varU = __DIR__ . "/base"; + + + /* testMethodParam */ + public function methodName($param) { + /* testImportedGlobal */ + global $importedGlobal = true; + + /* testLocalVariable */ + $localVariable = true; + } + + /* testPropertyAfterMethod */ + private static $varV = true; + + /* testMessyNullableType */ + public /* comment + */ ? //comment + array $foo = []; + + /* testNamespaceType */ + public \MyNamespace\MyClass $foo; + + /* testNullableNamespaceType 1 */ + private ?ClassName $nullableClassType; + + /* testNullableNamespaceType 2 */ + protected ?Folder\ClassName $nullableClassType2; + + /* testMultilineNamespaceType */ + public \MyNamespace /** comment *\/ comment */ + \MyClass /* comment */ + \Foo $foo; + +} + +interface Base +{ + /* testInterfaceProperty */ + protected $anonymous; +} + +/* testGlobalVariable */ +$globalVariable = true; + +/* testNotAVariable */ +return; + +$a = ( $foo == $bar ? new stdClass() : + new class() { + /* testNestedProperty 1 */ + public $var = true; + + /* testNestedMethodParam 1 */ + public function something($var = false) {} + } +); + +function_call( 'param', new class { + /* testNestedProperty 2 */ + public $year = 2017; + + /* testNestedMethodParam 2 */ + public function __construct( $open, $post_id ) {} +}, 10, 2 ); + +class PHP8Mixed { + /* testPHP8MixedTypeHint */ + public static miXed $mixed; + + /* testPHP8MixedTypeHintNullable */ + // Intentional fatal error - nullability is not allowed with mixed, but that's not the concern of the method. + private ?mixed $nullableMixed; +} + +class NSOperatorInType { + /* testNamespaceOperatorTypeHint */ + public ?namespace\Name $prop; +} + +$anon = class() { + /* testPHP8UnionTypesSimple */ + public int|float $unionTypeSimple; + + /* testPHP8UnionTypesTwoClasses */ + private MyClassA|\Package\MyClassB $unionTypesTwoClasses; + + /* testPHP8UnionTypesAllBaseTypes */ + protected array|bool|int|float|NULL|object|string $unionTypesAllBaseTypes; + + /* testPHP8UnionTypesAllPseudoTypes */ + // Intentional fatal error - mixing types which cannot be combined, but that's not the concern of the method. + var false|mixed|self|parent|iterable|Resource $unionTypesAllPseudoTypes; + + /* testPHP8UnionTypesIllegalTypes */ + // Intentional fatal error - types which are not allowed for properties, but that's not the concern of the method. + public callable|static|void $unionTypesIllegalTypes; + + /* testPHP8UnionTypesNullable */ + // Intentional fatal error - nullability is not allowed with union types, but that's not the concern of the method. + public ?int|float $unionTypesNullable; + + /* testPHP8PseudoTypeNull */ + // Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method. + public null $pseudoTypeNull; + + /* testPHP8PseudoTypeFalse */ + // Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method. + public false $pseudoTypeFalse; + + /* testPHP8PseudoTypeFalseAndBool */ + // Intentional fatal error - false pseudotype is not allowed in combination with bool, but that's not the concern of the method. + public bool|FALSE $pseudoTypeFalseAndBool; + + /* testPHP8ObjectAndClass */ + // Intentional fatal error - object is not allowed in combination with class name, but that's not the concern of the method. + public object|ClassName $objectAndClass; + + /* testPHP8PseudoTypeIterableAndArray */ + // Intentional fatal error - iterable pseudotype is not allowed in combination with array or Traversable, but that's not the concern of the method. + public iterable|array|Traversable $pseudoTypeIterableAndArray; + + /* testPHP8DuplicateTypeInUnionWhitespaceAndComment */ + // Intentional fatal error - duplicate types are not allowed in union types, but that's not the concern of the method. + public int |string| /*comment*/ INT $duplicateTypeInUnion; + + /* testPHP81Readonly */ + public readonly int $readonly; + + /* testPHP81ReadonlyWithNullableType */ + public readonly ?array $array; + + /* testPHP81ReadonlyWithUnionType */ + public readonly string|int $readonlyWithUnionType; + + /* testPHP81ReadonlyWithUnionTypeWithNull */ + protected ReadOnly string|null $readonlyWithUnionTypeWithNull; + + /* testPHP81OnlyReadonlyWithUnionType */ + readonly string|int $onlyReadonly; +}; + +$anon = class { + /* testPHP8PropertySingleAttribute */ + #[PropertyWithAttribute] + public string $foo; + + /* testPHP8PropertyMultipleAttributes */ + #[PropertyWithAttribute(foo: 'bar'), MyAttribute] + protected ?int|float $bar; + + /* testPHP8PropertyMultilineAttribute */ + #[ + PropertyWithAttribute(/* comment */ 'baz') + ] + private mixed $baz; +}; + +enum Suit +{ + /* testEnumProperty */ + protected $anonymous; +} + +enum Direction implements ArrayAccess +{ + case Up; + case Down; + + /* testEnumMethodParamNotProperty */ + public function offsetGet($val) { ... } +} + +$anon = class() { + /* testPHP81IntersectionTypes */ + public Foo&Bar $intersectionType; + + /* testPHP81MoreIntersectionTypes */ + public Foo&Bar&Baz $moreIntersectionTypes; + + /* testPHP81IllegalIntersectionTypes */ + // Intentional fatal error - types which are not allowed for intersection type, but that's not the concern of the method. + public int&string $illegalIntersectionType; + + /* testPHP81NulltableIntersectionType */ + // Intentional fatal error - nullability is not allowed with intersection type, but that's not the concern of the method. + public ?Foo&Bar $nullableIntersectionType; +}; diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.php new file mode 100644 index 00000000..69dfde1e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.php @@ -0,0 +1,864 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class GetMemberPropertiesTest extends AbstractMethodUnitTest +{ + + + /** + * Test the getMemberProperties() method. + * + * @param string $identifier Comment which precedes the test case. + * @param bool $expected Expected function output. + * + * @dataProvider dataGetMemberProperties + * + * @return void + */ + public function testGetMemberProperties($identifier, $expected) + { + $variable = $this->getTargetToken($identifier, T_VARIABLE); + $result = self::$phpcsFile->getMemberProperties($variable); + + $this->assertArraySubset($expected, $result, true); + + }//end testGetMemberProperties() + + + /** + * Data provider for the GetMemberProperties test. + * + * @see testGetMemberProperties() + * + * @return array + */ + public function dataGetMemberProperties() + { + return [ + [ + '/* testVar */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testVarType */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?int', + 'nullable_type' => true, + ], + ], + [ + '/* testPublic */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testPublicType */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'string', + 'nullable_type' => false, + ], + ], + [ + '/* testProtected */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testProtectedType */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'bool', + 'nullable_type' => false, + ], + ], + [ + '/* testPrivate */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testPrivateType */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'array', + 'nullable_type' => false, + ], + ], + [ + '/* testStatic */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testStaticType */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '?string', + 'nullable_type' => true, + ], + ], + [ + '/* testStaticVar */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testVarStatic */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testPublicStatic */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testProtectedStatic */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testPrivateStatic */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testPublicStaticWithDocblock */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testProtectedStaticWithDocblock */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testPrivateStaticWithDocblock */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupType 1 */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'float', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupType 2 */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'float', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupNullableType 1 */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '?string', + 'nullable_type' => true, + ], + ], + [ + '/* testGroupNullableType 2 */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '?string', + 'nullable_type' => true, + ], + ], + [ + '/* testNoPrefix */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupProtectedStatic 1 */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupProtectedStatic 2 */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupProtectedStatic 3 */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupPrivate 1 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupPrivate 2 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupPrivate 3 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupPrivate 4 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupPrivate 5 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupPrivate 6 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupPrivate 7 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testMessyNullableType */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?array', + 'nullable_type' => true, + ], + ], + [ + '/* testNamespaceType */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '\MyNamespace\MyClass', + 'nullable_type' => false, + ], + ], + [ + '/* testNullableNamespaceType 1 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?ClassName', + 'nullable_type' => true, + ], + ], + [ + '/* testNullableNamespaceType 2 */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?Folder\ClassName', + 'nullable_type' => true, + ], + ], + [ + '/* testMultilineNamespaceType */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '\MyNamespace\MyClass\Foo', + 'nullable_type' => false, + ], + ], + [ + '/* testPropertyAfterMethod */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testInterfaceProperty */', + [], + ], + [ + '/* testNestedProperty 1 */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testNestedProperty 2 */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8MixedTypeHint */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => 'miXed', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8MixedTypeHintNullable */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?mixed', + 'nullable_type' => true, + ], + ], + [ + '/* testNamespaceOperatorTypeHint */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?namespace\Name', + 'nullable_type' => true, + ], + ], + [ + '/* testPHP8UnionTypesSimple */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'int|float', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8UnionTypesTwoClasses */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'MyClassA|\Package\MyClassB', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8UnionTypesAllBaseTypes */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'array|bool|int|float|NULL|object|string', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8UnionTypesAllPseudoTypes */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'false|mixed|self|parent|iterable|Resource', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8UnionTypesIllegalTypes */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + // Missing static, but that's OK as not an allowed syntax. + 'type' => 'callable||void', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8UnionTypesNullable */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?int|float', + 'nullable_type' => true, + ], + ], + [ + '/* testPHP8PseudoTypeNull */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'null', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8PseudoTypeFalse */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'false', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8PseudoTypeFalseAndBool */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'bool|FALSE', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8ObjectAndClass */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'object|ClassName', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8PseudoTypeIterableAndArray */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'iterable|array|Traversable', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8DuplicateTypeInUnionWhitespaceAndComment */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'int|string|INT', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP81Readonly */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => true, + 'type' => 'int', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP81ReadonlyWithNullableType */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => true, + 'type' => '?array', + 'nullable_type' => true, + ], + ], + [ + '/* testPHP81ReadonlyWithUnionType */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => true, + 'type' => 'string|int', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP81ReadonlyWithUnionTypeWithNull */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => true, + 'type' => 'string|null', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP81OnlyReadonlyWithUnionType */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => true, + 'type' => 'string|int', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8PropertySingleAttribute */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'string', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8PropertyMultipleAttributes */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?int|float', + 'nullable_type' => true, + ], + ], + [ + '/* testPHP8PropertyMultilineAttribute */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'mixed', + 'nullable_type' => false, + ], + ], + [ + '/* testEnumProperty */', + [], + ], + [ + '/* testPHP81IntersectionTypes */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'type' => 'Foo&Bar', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP81MoreIntersectionTypes */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'type' => 'Foo&Bar&Baz', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP81IllegalIntersectionTypes */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'type' => 'int&string', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP81NulltableIntersectionType */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'type' => '?Foo&Bar', + 'nullable_type' => true, + ], + ], + ]; + + }//end dataGetMemberProperties() + + + /** + * Test receiving an expected exception when a non property is passed. + * + * @param string $identifier Comment which precedes the test case. + * + * @expectedException PHP_CodeSniffer\Exceptions\RuntimeException + * @expectedExceptionMessage $stackPtr is not a class member var + * + * @dataProvider dataNotClassProperty + * + * @return void + */ + public function testNotClassPropertyException($identifier) + { + $variable = $this->getTargetToken($identifier, T_VARIABLE); + $result = self::$phpcsFile->getMemberProperties($variable); + + }//end testNotClassPropertyException() + + + /** + * Data provider for the NotClassPropertyException test. + * + * @see testNotClassPropertyException() + * + * @return array + */ + public function dataNotClassProperty() + { + return [ + ['/* testMethodParam */'], + ['/* testImportedGlobal */'], + ['/* testLocalVariable */'], + ['/* testGlobalVariable */'], + ['/* testNestedMethodParam 1 */'], + ['/* testNestedMethodParam 2 */'], + ['/* testEnumMethodParamNotProperty */'], + ]; + + }//end dataNotClassProperty() + + + /** + * Test receiving an expected exception when a non variable is passed. + * + * @expectedException PHP_CodeSniffer\Exceptions\RuntimeException + * @expectedExceptionMessage $stackPtr must be of type T_VARIABLE + * + * @return void + */ + public function testNotAVariableException() + { + $next = $this->getTargetToken('/* testNotAVariable */', T_RETURN); + $result = self::$phpcsFile->getMemberProperties($next); + + }//end testNotAVariableException() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.inc new file mode 100644 index 00000000..dc465491 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.inc @@ -0,0 +1,164 @@ + $b; + +/* testPHP8MixedTypeHint */ +function mixedTypeHint(mixed &...$var1) {} + +/* testPHP8MixedTypeHintNullable */ +// Intentional fatal error - nullability is not allowed with mixed, but that's not the concern of the method. +function mixedTypeHintNullable(?Mixed $var1) {} + +/* testNamespaceOperatorTypeHint */ +function namespaceOperatorTypeHint(?namespace\Name $var1) {} + +/* testPHP8UnionTypesSimple */ +function unionTypeSimple(int|float $number, self|parent &...$obj) {} + +/* testPHP8UnionTypesWithSpreadOperatorAndReference */ +function globalFunctionWithSpreadAndReference(float|null &$paramA, string|int ...$paramB) {} + +/* testPHP8UnionTypesSimpleWithBitwiseOrInDefault */ +$fn = fn(int|float $var = CONSTANT_A | CONSTANT_B) => $var; + +/* testPHP8UnionTypesTwoClasses */ +function unionTypesTwoClasses(MyClassA|\Package\MyClassB $var) {} + +/* testPHP8UnionTypesAllBaseTypes */ +function unionTypesAllBaseTypes(array|bool|callable|int|float|null|object|string $var) {} + +/* testPHP8UnionTypesAllPseudoTypes */ +// Intentional fatal error - mixing types which cannot be combined, but that's not the concern of the method. +function unionTypesAllPseudoTypes(false|mixed|self|parent|iterable|Resource $var) {} + +/* testPHP8UnionTypesNullable */ +// Intentional fatal error - nullability is not allowed with union types, but that's not the concern of the method. +$closure = function (?int|float $number) {}; + +/* testPHP8PseudoTypeNull */ +// Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method. +function pseudoTypeNull(null $var = null) {} + +/* testPHP8PseudoTypeFalse */ +// Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method. +function pseudoTypeFalse(false $var = false) {} + +/* testPHP8PseudoTypeFalseAndBool */ +// Intentional fatal error - false pseudotype is not allowed in combination with bool, but that's not the concern of the method. +function pseudoTypeFalseAndBool(bool|false $var = false) {} + +/* testPHP8ObjectAndClass */ +// Intentional fatal error - object is not allowed in combination with class name, but that's not the concern of the method. +function objectAndClass(object|ClassName $var) {} + +/* testPHP8PseudoTypeIterableAndArray */ +// Intentional fatal error - iterable pseudotype is not allowed in combination with array or Traversable, but that's not the concern of the method. +function pseudoTypeIterableAndArray(iterable|array|Traversable $var) {} + +/* testPHP8DuplicateTypeInUnionWhitespaceAndComment */ +// Intentional fatal error - duplicate types are not allowed in union types, but that's not the concern of the method. +function duplicateTypeInUnion( int | string /*comment*/ | INT $var) {} + +class ConstructorPropertyPromotionNoTypes { + /* testPHP8ConstructorPropertyPromotionNoTypes */ + public function __construct( + public $x = 0.0, + protected $y = '', + private $z = null, + ) {} +} + +class ConstructorPropertyPromotionWithTypes { + /* testPHP8ConstructorPropertyPromotionWithTypes */ + public function __construct(protected float|int $x, public ?string &$y = 'test', private mixed $z) {} +} + +class ConstructorPropertyPromotionAndNormalParams { + /* testPHP8ConstructorPropertyPromotionAndNormalParam */ + public function __construct(public int $promotedProp, ?int $normalArg) {} +} + +class ConstructorPropertyPromotionWithReadOnly { + /* testPHP81ConstructorPropertyPromotionWithReadOnly */ + public function __construct(public readonly ?int $promotedProp, readonly private string|bool &$promotedToo) {} +} + +/* testPHP8ConstructorPropertyPromotionGlobalFunction */ +// Intentional fatal error. Property promotion not allowed in non-constructor, but that's not the concern of this method. +function globalFunction(private $x) {} + +abstract class ConstructorPropertyPromotionAbstractMethod { + /* testPHP8ConstructorPropertyPromotionAbstractMethod */ + // Intentional fatal error. + // 1. Property promotion not allowed in abstract method, but that's not the concern of this method. + // 2. Variadic arguments not allowed in property promotion, but that's not the concern of this method. + // 3. The callable type is not supported for properties, but that's not the concern of this method. + abstract public function __construct(public callable $y, private ...$x); +} + +/* testCommentsInParameter */ +function commentsInParams( + // Leading comment. + ?MyClass /*-*/ & /*-*/.../*-*/ $param /*-*/ = /*-*/ 'default value' . /*-*/ 'second part' // Trailing comment. +) {} + +/* testParameterAttributesInFunctionDeclaration */ +class ParametersWithAttributes( + public function __construct( + #[\MyExample\MyAttribute] private string $constructorPropPromTypedParamSingleAttribute, + #[MyAttr([1, 2])] + Type|false + $typedParamSingleAttribute, + #[MyAttribute(1234), MyAttribute(5678)] ?int $nullableTypedParamMultiAttribute, + #[WithoutArgument] #[SingleArgument(0)] $nonTypedParamTwoAttributes, + #[MyAttribute(array("key" => "value"))] + &...$otherParam, + ) {} +} + +/* testPHP8IntersectionTypes */ +function intersectionTypes(Foo&Bar $obj1, Boo&Bar $obj2) {} + +/* testPHP81IntersectionTypesWithSpreadOperatorAndReference */ +function globalFunctionWithSpreadAndReference(Boo&Bar &$paramA, Foo&Bar ...$paramB) {} + +/* testPHP81MoreIntersectionTypes */ +function moreIntersectionTypes(MyClassA&\Package\MyClassB&\Package\MyClassC $var) {} + +/* testPHP81IllegalIntersectionTypes */ +// Intentional fatal error - simple types are not allowed with intersection types, but that's not the concern of the method. +$closure = function (string&int $numeric_string) {}; + +/* testPHP81NullableIntersectionTypes */ +// Intentional fatal error - nullability is not allowed with intersection types, but that's not the concern of the method. +$closure = function (?Foo&Bar $object) {}; diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.php new file mode 100644 index 00000000..f70d64f2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.php @@ -0,0 +1,1145 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class GetMethodParametersTest extends AbstractMethodUnitTest +{ + + + /** + * Verify pass-by-reference parsing. + * + * @return void + */ + public function testPassByReference() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => '&$var', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPassByReference() + + + /** + * Verify array hint parsing. + * + * @return void + */ + public function testArrayHint() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'array $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'array', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrayHint() + + + /** + * Verify type hint parsing. + * + * @return void + */ + public function testTypeHint() + { + $expected = []; + $expected[0] = [ + 'name' => '$var1', + 'content' => 'foo $var1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'foo', + 'nullable_type' => false, + ]; + + $expected[1] = [ + 'name' => '$var2', + 'content' => 'bar $var2', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'bar', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testTypeHint() + + + /** + * Verify self type hint parsing. + * + * @return void + */ + public function testSelfTypeHint() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'self $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'self', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testSelfTypeHint() + + + /** + * Verify nullable type hint parsing. + * + * @return void + */ + public function testNullableTypeHint() + { + $expected = []; + $expected[0] = [ + 'name' => '$var1', + 'content' => '?int $var1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?int', + 'nullable_type' => true, + ]; + + $expected[1] = [ + 'name' => '$var2', + 'content' => '?\bar $var2', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?\bar', + 'nullable_type' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNullableTypeHint() + + + /** + * Verify variable. + * + * @return void + */ + public function testVariable() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => '$var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testVariable() + + + /** + * Verify default value parsing with a single function param. + * + * @return void + */ + public function testSingleDefaultValue() + { + $expected = []; + $expected[0] = [ + 'name' => '$var1', + 'content' => '$var1=self::CONSTANT', + 'has_attributes' => false, + 'default' => 'self::CONSTANT', + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testSingleDefaultValue() + + + /** + * Verify default value parsing. + * + * @return void + */ + public function testDefaultValues() + { + $expected = []; + $expected[0] = [ + 'name' => '$var1', + 'content' => '$var1=1', + 'has_attributes' => false, + 'default' => '1', + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + ]; + $expected[1] = [ + 'name' => '$var2', + 'content' => "\$var2='value'", + 'has_attributes' => false, + 'default' => "'value'", + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testDefaultValues() + + + /** + * Verify "bitwise and" in default value !== pass-by-reference. + * + * @return void + */ + public function testBitwiseAndConstantExpressionDefaultValue() + { + $expected = []; + $expected[0] = [ + 'name' => '$a', + 'content' => '$a = 10 & 20', + 'default' => '10 & 20', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testBitwiseAndConstantExpressionDefaultValue() + + + /** + * Verify that arrow functions are supported. + * + * @return void + */ + public function testArrowFunction() + { + $expected = []; + $expected[0] = [ + 'name' => '$a', + 'content' => 'int $a', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'int', + 'nullable_type' => false, + ]; + + $expected[1] = [ + 'name' => '$b', + 'content' => '...$b', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => true, + 'type_hint' => '', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrowFunction() + + + /** + * Verify recognition of PHP8 mixed type declaration. + * + * @return void + */ + public function testPHP8MixedTypeHint() + { + $expected = []; + $expected[0] = [ + 'name' => '$var1', + 'content' => 'mixed &...$var1', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => true, + 'type_hint' => 'mixed', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8MixedTypeHint() + + + /** + * Verify recognition of PHP8 mixed type declaration with nullability. + * + * @return void + */ + public function testPHP8MixedTypeHintNullable() + { + $expected = []; + $expected[0] = [ + 'name' => '$var1', + 'content' => '?Mixed $var1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?Mixed', + 'nullable_type' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8MixedTypeHintNullable() + + + /** + * Verify recognition of type declarations using the namespace operator. + * + * @return void + */ + public function testNamespaceOperatorTypeHint() + { + $expected = []; + $expected[0] = [ + 'name' => '$var1', + 'content' => '?namespace\Name $var1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?namespace\Name', + 'nullable_type' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNamespaceOperatorTypeHint() + + + /** + * Verify recognition of PHP8 union type declaration. + * + * @return void + */ + public function testPHP8UnionTypesSimple() + { + $expected = []; + $expected[0] = [ + 'name' => '$number', + 'content' => 'int|float $number', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'int|float', + 'nullable_type' => false, + ]; + $expected[1] = [ + 'name' => '$obj', + 'content' => 'self|parent &...$obj', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => true, + 'type_hint' => 'self|parent', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesSimple() + + + /** + * Verify recognition of PHP8 union type declaration when the variable has either a spread operator or a reference. + * + * @return void + */ + public function testPHP8UnionTypesWithSpreadOperatorAndReference() + { + $expected = []; + $expected[0] = [ + 'name' => '$paramA', + 'content' => 'float|null &$paramA', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => false, + 'type_hint' => 'float|null', + 'nullable_type' => false, + ]; + $expected[1] = [ + 'name' => '$paramB', + 'content' => 'string|int ...$paramB', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => true, + 'type_hint' => 'string|int', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesWithSpreadOperatorAndReference() + + + /** + * Verify recognition of PHP8 union type declaration with a bitwise or in the default value. + * + * @return void + */ + public function testPHP8UnionTypesSimpleWithBitwiseOrInDefault() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'int|float $var = CONSTANT_A | CONSTANT_B', + 'default' => 'CONSTANT_A | CONSTANT_B', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'int|float', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesSimpleWithBitwiseOrInDefault() + + + /** + * Verify recognition of PHP8 union type declaration with two classes. + * + * @return void + */ + public function testPHP8UnionTypesTwoClasses() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'MyClassA|\Package\MyClassB $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'MyClassA|\Package\MyClassB', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesTwoClasses() + + + /** + * Verify recognition of PHP8 union type declaration with all base types. + * + * @return void + */ + public function testPHP8UnionTypesAllBaseTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'array|bool|callable|int|float|null|object|string $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'array|bool|callable|int|float|null|object|string', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesAllBaseTypes() + + + /** + * Verify recognition of PHP8 union type declaration with all pseudo types. + * + * @return void + */ + public function testPHP8UnionTypesAllPseudoTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'false|mixed|self|parent|iterable|Resource $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'false|mixed|self|parent|iterable|Resource', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesAllPseudoTypes() + + + /** + * Verify recognition of PHP8 union type declaration with (illegal) nullability. + * + * @return void + */ + public function testPHP8UnionTypesNullable() + { + $expected = []; + $expected[0] = [ + 'name' => '$number', + 'content' => '?int|float $number', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?int|float', + 'nullable_type' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesNullable() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) single type null. + * + * @return void + */ + public function testPHP8PseudoTypeNull() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'null $var = null', + 'default' => 'null', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'null', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeNull() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) single type false. + * + * @return void + */ + public function testPHP8PseudoTypeFalse() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'false $var = false', + 'default' => 'false', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'false', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeFalse() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type false combined with type bool. + * + * @return void + */ + public function testPHP8PseudoTypeFalseAndBool() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'bool|false $var = false', + 'default' => 'false', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'bool|false', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeFalseAndBool() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type object combined with a class name. + * + * @return void + */ + public function testPHP8ObjectAndClass() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'object|ClassName $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'object|ClassName', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ObjectAndClass() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type iterable combined with array/Traversable. + * + * @return void + */ + public function testPHP8PseudoTypeIterableAndArray() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'iterable|array|Traversable $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'iterable|array|Traversable', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeIterableAndArray() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) duplicate types. + * + * @return void + */ + public function testPHP8DuplicateTypeInUnionWhitespaceAndComment() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'int | string /*comment*/ | INT $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'int|string|INT', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8DuplicateTypeInUnionWhitespaceAndComment() + + + /** + * Verify recognition of PHP8 constructor property promotion without type declaration, with defaults. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionNoTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$x', + 'content' => 'public $x = 0.0', + 'default' => '0.0', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + 'property_visibility' => 'public', + 'property_readonly' => false, + ]; + $expected[1] = [ + 'name' => '$y', + 'content' => 'protected $y = \'\'', + 'default' => "''", + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + 'property_visibility' => 'protected', + 'property_readonly' => false, + ]; + $expected[2] = [ + 'name' => '$z', + 'content' => 'private $z = null', + 'default' => 'null', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + 'property_visibility' => 'private', + 'property_readonly' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionNoTypes() + + + /** + * Verify recognition of PHP8 constructor property promotion with type declarations. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionWithTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$x', + 'content' => 'protected float|int $x', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'float|int', + 'nullable_type' => false, + 'property_visibility' => 'protected', + 'property_readonly' => false, + ]; + $expected[1] = [ + 'name' => '$y', + 'content' => 'public ?string &$y = \'test\'', + 'default' => "'test'", + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => false, + 'type_hint' => '?string', + 'nullable_type' => true, + 'property_visibility' => 'public', + 'property_readonly' => false, + ]; + $expected[2] = [ + 'name' => '$z', + 'content' => 'private mixed $z', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'mixed', + 'nullable_type' => false, + 'property_visibility' => 'private', + 'property_readonly' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionWithTypes() + + + /** + * Verify recognition of PHP8 constructor with both property promotion as well as normal parameters. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionAndNormalParam() + { + $expected = []; + $expected[0] = [ + 'name' => '$promotedProp', + 'content' => 'public int $promotedProp', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'int', + 'nullable_type' => false, + 'property_visibility' => 'public', + 'property_readonly' => false, + ]; + $expected[1] = [ + 'name' => '$normalArg', + 'content' => '?int $normalArg', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?int', + 'nullable_type' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionAndNormalParam() + + + /** + * Verify recognition of PHP8 constructor with property promotion using PHP 8.1 readonly keyword. + * + * @return void + */ + public function testPHP81ConstructorPropertyPromotionWithReadOnly() + { + $expected = []; + $expected[0] = [ + 'name' => '$promotedProp', + 'content' => 'public readonly ?int $promotedProp', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?int', + 'nullable_type' => true, + 'property_visibility' => 'public', + 'property_readonly' => true, + ]; + $expected[1] = [ + 'name' => '$promotedToo', + 'content' => 'readonly private string|bool &$promotedToo', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => false, + 'type_hint' => 'string|bool', + 'nullable_type' => false, + 'property_visibility' => 'private', + 'property_readonly' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81ConstructorPropertyPromotionWithReadOnly() + + + /** + * Verify behaviour when a non-constructor function uses PHP 8 property promotion syntax. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionGlobalFunction() + { + $expected = []; + $expected[0] = [ + 'name' => '$x', + 'content' => 'private $x', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + 'property_visibility' => 'private', + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionGlobalFunction() + + + /** + * Verify behaviour when an abstract constructor uses PHP 8 property promotion syntax. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionAbstractMethod() + { + $expected = []; + $expected[0] = [ + 'name' => '$y', + 'content' => 'public callable $y', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'callable', + 'nullable_type' => false, + 'property_visibility' => 'public', + ]; + $expected[1] = [ + 'name' => '$x', + 'content' => 'private ...$x', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => true, + 'type_hint' => '', + 'nullable_type' => false, + 'property_visibility' => 'private', + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionAbstractMethod() + + + /** + * Verify and document behaviour when there are comments within a parameter declaration. + * + * @return void + */ + public function testCommentsInParameter() + { + $expected = []; + $expected[0] = [ + 'name' => '$param', + 'content' => '// Leading comment. + ?MyClass /*-*/ & /*-*/.../*-*/ $param /*-*/ = /*-*/ \'default value\' . /*-*/ \'second part\' // Trailing comment.', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => true, + 'type_hint' => '?MyClass', + 'nullable_type' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testCommentsInParameter() + + + /** + * Verify behaviour when parameters have attributes attached. + * + * @return void + */ + public function testParameterAttributesInFunctionDeclaration() + { + $expected = []; + $expected[0] = [ + 'name' => '$constructorPropPromTypedParamSingleAttribute', + 'content' => '#[\MyExample\MyAttribute] private string $constructorPropPromTypedParamSingleAttribute', + 'has_attributes' => true, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'string', + 'nullable_type' => false, + 'property_visibility' => 'private', + ]; + $expected[1] = [ + 'name' => '$typedParamSingleAttribute', + 'content' => '#[MyAttr([1, 2])] + Type|false + $typedParamSingleAttribute', + 'has_attributes' => true, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'Type|false', + 'nullable_type' => false, + ]; + $expected[2] = [ + 'name' => '$nullableTypedParamMultiAttribute', + 'content' => '#[MyAttribute(1234), MyAttribute(5678)] ?int $nullableTypedParamMultiAttribute', + 'has_attributes' => true, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?int', + 'nullable_type' => true, + ]; + $expected[3] = [ + 'name' => '$nonTypedParamTwoAttributes', + 'content' => '#[WithoutArgument] #[SingleArgument(0)] $nonTypedParamTwoAttributes', + 'has_attributes' => true, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + ]; + $expected[4] = [ + 'name' => '$otherParam', + 'content' => '#[MyAttribute(array("key" => "value"))] + &...$otherParam', + 'has_attributes' => true, + 'pass_by_reference' => true, + 'variable_length' => true, + 'type_hint' => '', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testParameterAttributesInFunctionDeclaration() + + + /** + * Verify recognition of PHP8.1 intersection type declaration. + * + * @return void + */ + public function testPHP8IntersectionTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$obj1', + 'content' => 'Foo&Bar $obj1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'Foo&Bar', + 'nullable_type' => false, + ]; + $expected[1] = [ + 'name' => '$obj2', + 'content' => 'Boo&Bar $obj2', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'Boo&Bar', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8IntersectionTypes() + + + /** + * Verify recognition of PHP8 intersection type declaration when the variable has either a spread operator or a reference. + * + * @return void + */ + public function testPHP81IntersectionTypesWithSpreadOperatorAndReference() + { + $expected = []; + $expected[0] = [ + 'name' => '$paramA', + 'content' => 'Boo&Bar &$paramA', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => false, + 'type_hint' => 'Boo&Bar', + 'nullable_type' => false, + ]; + $expected[1] = [ + 'name' => '$paramB', + 'content' => 'Foo&Bar ...$paramB', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => true, + 'type_hint' => 'Foo&Bar', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81IntersectionTypesWithSpreadOperatorAndReference() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with more types. + * + * @return void + */ + public function testPHP81MoreIntersectionTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'MyClassA&\Package\MyClassB&\Package\MyClassC $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'MyClassA&\Package\MyClassB&\Package\MyClassC', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81MoreIntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with illegal simple types. + * + * @return void + */ + public function testPHP81IllegalIntersectionTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$numeric_string', + 'content' => 'string&int $numeric_string', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'string&int', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81IllegalIntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with (illegal) nullability. + * + * @return void + */ + public function testPHP81NullableIntersectionTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$object', + 'content' => '?Foo&Bar $object', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?Foo&Bar', + 'nullable_type' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81NullableIntersectionTypes() + + + /** + * Test helper. + * + * @param string $commentString The comment which preceeds the test. + * @param array $expected The expected function output. + * + * @return void + */ + private function getMethodParametersTestHelper($commentString, $expected) + { + $function = $this->getTargetToken($commentString, [T_FUNCTION, T_CLOSURE, T_FN]); + $found = self::$phpcsFile->getMethodParameters($function); + + $this->assertArraySubset($expected, $found, true); + + }//end getMethodParametersTestHelper() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.inc new file mode 100644 index 00000000..0c592369 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.inc @@ -0,0 +1,152 @@ + $number + 1, + $numbers +); + +class ReturnMe { + /* testReturnTypeStatic */ + private function myFunction(): static { + return $this; + } +} + +/* testPHP8MixedTypeHint */ +function mixedTypeHint() :mixed {} + +/* testPHP8MixedTypeHintNullable */ +// Intentional fatal error - nullability is not allowed with mixed, but that's not the concern of the method. +function mixedTypeHintNullable(): ?mixed {} + +/* testNamespaceOperatorTypeHint */ +function namespaceOperatorTypeHint() : ?namespace\Name {} + +/* testPHP8UnionTypesSimple */ +function unionTypeSimple($number) : int|float {} + +/* testPHP8UnionTypesTwoClasses */ +$fn = fn($var): MyClassA|\Package\MyClassB => $var; + +/* testPHP8UnionTypesAllBaseTypes */ +function unionTypesAllBaseTypes() : array|bool|callable|int|float|null|Object|string {} + +/* testPHP8UnionTypesAllPseudoTypes */ +// Intentional fatal error - mixing types which cannot be combined, but that's not the concern of the method. +function unionTypesAllPseudoTypes($var) : false|MIXED|self|parent|static|iterable|Resource|void {} + +/* testPHP8UnionTypesNullable */ +// Intentional fatal error - nullability is not allowed with union types, but that's not the concern of the method. +$closure = function () use($a) :?int|float {}; + +/* testPHP8PseudoTypeNull */ +// Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method. +function pseudoTypeNull(): null {} + +/* testPHP8PseudoTypeFalse */ +// Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method. +function pseudoTypeFalse(): false {} + +/* testPHP8PseudoTypeFalseAndBool */ +// Intentional fatal error - false pseudotype is not allowed in combination with bool, but that's not the concern of the method. +function pseudoTypeFalseAndBool(): bool|false {} + +/* testPHP8ObjectAndClass */ +// Intentional fatal error - object is not allowed in combination with class name, but that's not the concern of the method. +function objectAndClass(): object|ClassName {} + +/* testPHP8PseudoTypeIterableAndArray */ +// Intentional fatal error - iterable pseudotype is not allowed in combination with array or Traversable, but that's not the concern of the method. +interface FooBar { + public function pseudoTypeIterableAndArray(): iterable|array|Traversable; +} + +/* testPHP8DuplicateTypeInUnionWhitespaceAndComment */ +// Intentional fatal error - duplicate types are not allowed in union types, but that's not the concern of the method. +function duplicateTypeInUnion(): int | /*comment*/ string | INT {} + +/* testPHP81NeverType */ +function never(): never {} + +/* testPHP81NullableNeverType */ +// Intentional fatal error - nullability is not allowed with never, but that's not the concern of the method. +function nullableNever(): ?never {} + +/* testPHP8IntersectionTypes */ +function intersectionTypes(): Foo&Bar {} + +/* testPHP81MoreIntersectionTypes */ +function moreIntersectionTypes(): MyClassA&\Package\MyClassB&\Package\MyClassC {} + +/* testPHP81IntersectionArrowFunction */ +$fn = fn($var): MyClassA&\Package\MyClassB => $var; + +/* testPHP81IllegalIntersectionTypes */ +// Intentional fatal error - simple types are not allowed with intersection types, but that's not the concern of the method. +$closure = function (): string&int {}; + +/* testPHP81NullableIntersectionTypes */ +// Intentional fatal error - nullability is not allowed with intersection types, but that's not the concern of the method. +$closure = function (): ?Foo&Bar {}; diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.php new file mode 100644 index 00000000..2f552bfe --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.php @@ -0,0 +1,911 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class GetMethodPropertiesTest extends AbstractMethodUnitTest +{ + + + /** + * Test a basic function. + * + * @return void + */ + public function testBasicFunction() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testBasicFunction() + + + /** + * Test a function with a return type. + * + * @return void + */ + public function testReturnFunction() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'array', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnFunction() + + + /** + * Test a closure used as a function argument. + * + * @return void + */ + public function testNestedClosure() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'int', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNestedClosure() + + + /** + * Test a basic method. + * + * @return void + */ + public function testBasicMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testBasicMethod() + + + /** + * Test a private static method. + * + * @return void + */ + public function testPrivateStaticMethod() + { + $expected = [ + 'scope' => 'private', + 'scope_specified' => true, + 'return_type' => '', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => true, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPrivateStaticMethod() + + + /** + * Test a basic final method. + * + * @return void + */ + public function testFinalMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => '', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => true, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testFinalMethod() + + + /** + * Test a protected method with a return type. + * + * @return void + */ + public function testProtectedReturnMethod() + { + $expected = [ + 'scope' => 'protected', + 'scope_specified' => true, + 'return_type' => 'int', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testProtectedReturnMethod() + + + /** + * Test a public method with a return type. + * + * @return void + */ + public function testPublicReturnMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => 'array', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPublicReturnMethod() + + + /** + * Test a public method with a nullable return type. + * + * @return void + */ + public function testNullableReturnMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => '?array', + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNullableReturnMethod() + + + /** + * Test a public method with a nullable return type. + * + * @return void + */ + public function testMessyNullableReturnMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => '?array', + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testMessyNullableReturnMethod() + + + /** + * Test a method with a namespaced return type. + * + * @return void + */ + public function testReturnNamespace() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '\MyNamespace\MyClass', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnNamespace() + + + /** + * Test a method with a messy namespaces return type. + * + * @return void + */ + public function testReturnMultilineNamespace() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '\MyNamespace\MyClass\Foo', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnMultilineNamespace() + + + /** + * Test a basic abstract method. + * + * @return void + */ + public function testAbstractMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'nullable_return_type' => false, + 'is_abstract' => true, + 'is_final' => false, + 'is_static' => false, + 'has_body' => false, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testAbstractMethod() + + + /** + * Test an abstract method with a return type. + * + * @return void + */ + public function testAbstractReturnMethod() + { + $expected = [ + 'scope' => 'protected', + 'scope_specified' => true, + 'return_type' => 'bool', + 'nullable_return_type' => false, + 'is_abstract' => true, + 'is_final' => false, + 'is_static' => false, + 'has_body' => false, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testAbstractReturnMethod() + + + /** + * Test a basic interface method. + * + * @return void + */ + public function testInterfaceMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => false, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testInterfaceMethod() + + + /** + * Test a static arrow function. + * + * @return void + */ + public function testArrowFunction() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'int', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => true, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrowFunction() + + + /** + * Test a function with return type "static". + * + * @return void + */ + public function testReturnTypeStatic() + { + $expected = [ + 'scope' => 'private', + 'scope_specified' => true, + 'return_type' => 'static', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnTypeStatic() + + + /** + * Test a function with return type "mixed". + * + * @return void + */ + public function testPHP8MixedTypeHint() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'mixed', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8MixedTypeHint() + + + /** + * Test a function with return type "mixed" and nullability. + * + * @return void + */ + public function testPHP8MixedTypeHintNullable() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?mixed', + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8MixedTypeHintNullable() + + + /** + * Test a function with return type using the namespace operator. + * + * @return void + */ + public function testNamespaceOperatorTypeHint() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?namespace\Name', + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNamespaceOperatorTypeHint() + + + /** + * Verify recognition of PHP8 union type declaration. + * + * @return void + */ + public function testPHP8UnionTypesSimple() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'int|float', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesSimple() + + + /** + * Verify recognition of PHP8 union type declaration with two classes. + * + * @return void + */ + public function testPHP8UnionTypesTwoClasses() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'MyClassA|\Package\MyClassB', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesTwoClasses() + + + /** + * Verify recognition of PHP8 union type declaration with all base types. + * + * @return void + */ + public function testPHP8UnionTypesAllBaseTypes() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'array|bool|callable|int|float|null|Object|string', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesAllBaseTypes() + + + /** + * Verify recognition of PHP8 union type declaration with all pseudo types. + * + * @return void + */ + public function testPHP8UnionTypesAllPseudoTypes() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'false|MIXED|self|parent|static|iterable|Resource|void', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesAllPseudoTypes() + + + /** + * Verify recognition of PHP8 union type declaration with (illegal) nullability. + * + * @return void + */ + public function testPHP8UnionTypesNullable() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?int|float', + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesNullable() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) single type null. + * + * @return void + */ + public function testPHP8PseudoTypeNull() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'null', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeNull() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) single type false. + * + * @return void + */ + public function testPHP8PseudoTypeFalse() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'false', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeFalse() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type false combined with type bool. + * + * @return void + */ + public function testPHP8PseudoTypeFalseAndBool() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'bool|false', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeFalseAndBool() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type object combined with a class name. + * + * @return void + */ + public function testPHP8ObjectAndClass() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'object|ClassName', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ObjectAndClass() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type iterable combined with array/Traversable. + * + * @return void + */ + public function testPHP8PseudoTypeIterableAndArray() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => 'iterable|array|Traversable', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => false, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeIterableAndArray() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) duplicate types. + * + * @return void + */ + public function testPHP8DuplicateTypeInUnionWhitespaceAndComment() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'int|string|INT', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8DuplicateTypeInUnionWhitespaceAndComment() + + + /** + * Verify recognition of PHP8.1 type "never". + * + * @return void + */ + public function testPHP81NeverType() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'never', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81NeverType() + + + /** + * Verify recognition of PHP8.1 type "never" with (illegal) nullability. + * + * @return void + */ + public function testPHP81NullableNeverType() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?never', + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81NullableNeverType() + + + /** + /** + * Verify recognition of PHP8.1 intersection type declaration. + * + * @return void + */ + public function testPHP8IntersectionTypes() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'Foo&Bar', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8IntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with more types. + * + * @return void + */ + public function testPHP81MoreIntersectionTypes() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'MyClassA&\Package\MyClassB&\Package\MyClassC', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81MoreIntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration in arrow function. + * + * @return void + */ + public function testPHP81IntersectionArrowFunction() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'MyClassA&\Package\MyClassB', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81IntersectionArrowFunction() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with illegal simple types. + * + * @return void + */ + public function testPHP81IllegalIntersectionTypes() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'string&int', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81IllegalIntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with (illegal) nullability. + * + * @return void + */ + public function testPHP81NullableIntersectionTypes() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?Foo&Bar', + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81NullableIntersectionTypes() + + + /** + * Test helper. + * + * @param string $commentString The comment which preceeds the test. + * @param array $expected The expected function output. + * + * @return void + */ + private function getMethodPropertiesTestHelper($commentString, $expected) + { + $function = $this->getTargetToken($commentString, [T_FUNCTION, T_CLOSURE, T_FN]); + $found = self::$phpcsFile->getMethodProperties($function); + + $this->assertArraySubset($expected, $found, true); + + }//end getMethodPropertiesTestHelper() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.inc new file mode 100644 index 00000000..cd40ed3b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.inc @@ -0,0 +1,150 @@ + $first, 'b' => $something & $somethingElse ]; + +/* testBitwiseAndF */ +$a = array( 'a' => $first, 'b' => $something & \MyClass::$somethingElse ); + +/* testBitwiseAndG */ +$a = $something & $somethingElse; + +/* testBitwiseAndH */ +function myFunction($a = 10 & 20) {} + +/* testBitwiseAndI */ +$closure = function ($a = MY_CONSTANT & parent::OTHER_CONSTANT) {}; + +/* testFunctionReturnByReference */ +function &myFunction() {} + +/* testFunctionPassByReferenceA */ +function myFunction( &$a ) {} + +/* testFunctionPassByReferenceB */ +function myFunction( $a, &$b ) {} + +/* testFunctionPassByReferenceC */ +$closure = function ( &$a ) {}; + +/* testFunctionPassByReferenceD */ +$closure = function ( $a, &$b ) {}; + +/* testFunctionPassByReferenceE */ +function myFunction(array &$one) {} + +/* testFunctionPassByReferenceF */ +$closure = function (\MyClass &$one) {}; + +/* testFunctionPassByReferenceG */ +$closure = function myFunc($param, &...$moreParams) {}; + +/* testForeachValueByReference */ +foreach( $array as $key => &$value ) {} + +/* testForeachKeyByReference */ +foreach( $array as &$key => $value ) {} + +/* testArrayValueByReferenceA */ +$a = [ 'a' => &$something ]; + +/* testArrayValueByReferenceB */ +$a = [ 'a' => $something, 'b' => &$somethingElse ]; + +/* testArrayValueByReferenceC */ +$a = [ &$something ]; + +/* testArrayValueByReferenceD */ +$a = [ $something, &$somethingElse ]; + +/* testArrayValueByReferenceE */ +$a = array( 'a' => &$something ); + +/* testArrayValueByReferenceF */ +$a = array( 'a' => $something, 'b' => &$somethingElse ); + +/* testArrayValueByReferenceG */ +$a = array( &$something ); + +/* testArrayValueByReferenceH */ +$a = array( $something, &$somethingElse ); + +/* testAssignByReferenceA */ +$b = &$something; + +/* testAssignByReferenceB */ +$b =& $something; + +/* testAssignByReferenceC */ +$b .= &$something; + +/* testAssignByReferenceD */ +$myValue = &$obj->getValue(); + +/* testAssignByReferenceE */ +$collection = &collector(); + +/* testPassByReferenceA */ +functionCall(&$something, $somethingElse); + +/* testPassByReferenceB */ +functionCall($something, &$somethingElse); + +/* testPassByReferenceC */ +functionCall($something, &$this->somethingElse); + +/* testPassByReferenceD */ +functionCall($something, &self::$somethingElse); + +/* testPassByReferenceE */ +functionCall($something, &parent::$somethingElse); + +/* testPassByReferenceF */ +functionCall($something, &static::$somethingElse); + +/* testPassByReferenceG */ +functionCall($something, &SomeClass::$somethingElse); + +/* testPassByReferenceH */ +functionCall(&\SomeClass::$somethingElse); + +/* testPassByReferenceI */ +functionCall($something, &\SomeNS\SomeClass::$somethingElse); + +/* testPassByReferenceJ */ +functionCall($something, &namespace\SomeClass::$somethingElse); + +/* testNewByReferenceA */ +$foobar2 = &new Foobar(); + +/* testNewByReferenceB */ +functionCall( $something , &new Foobar() ); + +/* testUseByReference */ +$closure = function() use (&$var){}; + +/* testArrowFunctionReturnByReference */ +fn&($x) => $x; + +/* testArrowFunctionPassByReferenceA */ +$fn = fn(array &$one) => 1; + +/* testArrowFunctionPassByReferenceB */ +$fn = fn($param, &...$moreParams) => 1; + +/* testClosureReturnByReference */ +$closure = function &($param) use ($value) {}; diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.php new file mode 100644 index 00000000..ea2dddba --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.php @@ -0,0 +1,248 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class IsReferenceTest extends AbstractMethodUnitTest +{ + + + /** + * Test correctly identifying whether a "bitwise and" token is a reference or not. + * + * @param string $identifier Comment which precedes the test case. + * @param bool $expected Expected function output. + * + * @dataProvider dataIsReference + * + * @return void + */ + public function testIsReference($identifier, $expected) + { + $bitwiseAnd = $this->getTargetToken($identifier, T_BITWISE_AND); + $result = self::$phpcsFile->isReference($bitwiseAnd); + $this->assertSame($expected, $result); + + }//end testIsReference() + + + /** + * Data provider for the IsReference test. + * + * @see testIsReference() + * + * @return array + */ + public function dataIsReference() + { + return [ + [ + '/* testBitwiseAndA */', + false, + ], + [ + '/* testBitwiseAndB */', + false, + ], + [ + '/* testBitwiseAndC */', + false, + ], + [ + '/* testBitwiseAndD */', + false, + ], + [ + '/* testBitwiseAndE */', + false, + ], + [ + '/* testBitwiseAndF */', + false, + ], + [ + '/* testBitwiseAndG */', + false, + ], + [ + '/* testBitwiseAndH */', + false, + ], + [ + '/* testBitwiseAndI */', + false, + ], + [ + '/* testFunctionReturnByReference */', + true, + ], + [ + '/* testFunctionPassByReferenceA */', + true, + ], + [ + '/* testFunctionPassByReferenceB */', + true, + ], + [ + '/* testFunctionPassByReferenceC */', + true, + ], + [ + '/* testFunctionPassByReferenceD */', + true, + ], + [ + '/* testFunctionPassByReferenceE */', + true, + ], + [ + '/* testFunctionPassByReferenceF */', + true, + ], + [ + '/* testFunctionPassByReferenceG */', + true, + ], + [ + '/* testForeachValueByReference */', + true, + ], + [ + '/* testForeachKeyByReference */', + true, + ], + [ + '/* testArrayValueByReferenceA */', + true, + ], + [ + '/* testArrayValueByReferenceB */', + true, + ], + [ + '/* testArrayValueByReferenceC */', + true, + ], + [ + '/* testArrayValueByReferenceD */', + true, + ], + [ + '/* testArrayValueByReferenceE */', + true, + ], + [ + '/* testArrayValueByReferenceF */', + true, + ], + [ + '/* testArrayValueByReferenceG */', + true, + ], + [ + '/* testArrayValueByReferenceH */', + true, + ], + [ + '/* testAssignByReferenceA */', + true, + ], + [ + '/* testAssignByReferenceB */', + true, + ], + [ + '/* testAssignByReferenceC */', + true, + ], + [ + '/* testAssignByReferenceD */', + true, + ], + [ + '/* testAssignByReferenceE */', + true, + ], + [ + '/* testPassByReferenceA */', + true, + ], + [ + '/* testPassByReferenceB */', + true, + ], + [ + '/* testPassByReferenceC */', + true, + ], + [ + '/* testPassByReferenceD */', + true, + ], + [ + '/* testPassByReferenceE */', + true, + ], + [ + '/* testPassByReferenceF */', + true, + ], + [ + '/* testPassByReferenceG */', + true, + ], + [ + '/* testPassByReferenceH */', + true, + ], + [ + '/* testPassByReferenceI */', + true, + ], + [ + '/* testPassByReferenceJ */', + true, + ], + [ + '/* testNewByReferenceA */', + true, + ], + [ + '/* testNewByReferenceB */', + true, + ], + [ + '/* testUseByReference */', + true, + ], + [ + '/* testArrowFunctionReturnByReference */', + true, + ], + [ + '/* testArrowFunctionPassByReferenceA */', + true, + ], + [ + '/* testArrowFunctionPassByReferenceB */', + true, + ], + [ + '/* testClosureReturnByReference */', + true, + ], + ]; + + }//end dataIsReference() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.php new file mode 100644 index 00000000..2c9f57cd --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.php @@ -0,0 +1,154 @@ + + * @author Juliette Reinders Folmer + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Filters\Filter; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Filters\Filter; +use PHP_CodeSniffer\Ruleset; +use PHPUnit\Framework\TestCase; + +class AcceptTest extends TestCase +{ + + /** + * The Config object. + * + * @var \PHP_CodeSniffer\Config + */ + protected static $config; + + /** + * The Ruleset object. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected static $ruleset; + + + /** + * Initialize the test. + * + * @return void + */ + public function setUp() + { + if ($GLOBALS['PHP_CODESNIFFER_PEAR'] === true) { + // PEAR installs test and sniff files into different locations + // so these tests will not pass as they directly reference files + // by relative location. + $this->markTestSkipped('Test cannot run from a PEAR install'); + } + + }//end setUp() + + + /** + * Initialize the config and ruleset objects based on the `AcceptTest.xml` ruleset file. + * + * @return void + */ + public static function setUpBeforeClass() + { + if ($GLOBALS['PHP_CODESNIFFER_PEAR'] === true) { + // This test will be skipped. + return; + } + + $standard = __DIR__.'/'.basename(__FILE__, '.php').'.xml'; + self::$config = new Config(["--standard=$standard", "--ignore=*/somethingelse/*"]); + self::$ruleset = new Ruleset(self::$config); + + }//end setUpBeforeClass() + + + /** + * Test filtering a file list for excluded paths. + * + * @param array $inputPaths List of file paths to be filtered. + * @param array $expectedOutput Expected filtering result. + * + * @dataProvider dataExcludePatterns + * + * @return void + */ + public function testExcludePatterns($inputPaths, $expectedOutput) + { + $fakeDI = new \RecursiveArrayIterator($inputPaths); + $filter = new Filter($fakeDI, '/', self::$config, self::$ruleset); + $iterator = new \RecursiveIteratorIterator($filter); + $files = []; + + foreach ($iterator as $file) { + $files[] = $file; + } + + $this->assertEquals($expectedOutput, $files); + + }//end testExcludePatterns() + + + /** + * Data provider. + * + * @see testExcludePatterns + * + * @return array + */ + public function dataExcludePatterns() + { + $testCases = [ + // Test top-level exclude patterns. + [ + [ + '/path/to/src/Main.php', + '/path/to/src/Something/Main.php', + '/path/to/src/Somethingelse/Main.php', + '/path/to/src/SomethingelseEvenLonger/Main.php', + '/path/to/src/Other/Main.php', + ], + [ + '/path/to/src/Main.php', + '/path/to/src/SomethingelseEvenLonger/Main.php', + ], + ], + + // Test ignoring standard/sniff specific exclude patterns. + [ + [ + '/path/to/src/generic-project/Main.php', + '/path/to/src/generic/Main.php', + '/path/to/src/anything-generic/Main.php', + ], + [ + '/path/to/src/generic-project/Main.php', + '/path/to/src/generic/Main.php', + '/path/to/src/anything-generic/Main.php', + ], + ], + ]; + + // Allow these tests to work on Windows as well. + if (DIRECTORY_SEPARATOR === '\\') { + foreach ($testCases as $key => $case) { + foreach ($case as $nr => $param) { + foreach ($param as $file => $value) { + $testCases[$key][$nr][$file] = strtr($value, '/', '\\'); + } + } + } + } + + return $testCases; + + }//end dataExcludePatterns() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.xml b/vendor/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.xml new file mode 100644 index 00000000..3d3e1de0 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.xml @@ -0,0 +1,16 @@ + + + Ruleset to test the filtering based on exclude patterns. + + + */something/* + + */Other/Main\.php$ + + + + /anything/* + + /YetAnother/Main\.php + + diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/IsCamelCapsTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/IsCamelCapsTest.php new file mode 100644 index 00000000..b60d524b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/IsCamelCapsTest.php @@ -0,0 +1,135 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core; + +use PHP_CodeSniffer\Util\Common; +use PHPUnit\Framework\TestCase; + +class IsCamelCapsTest extends TestCase +{ + + + /** + * Test valid public function/method names. + * + * @return void + */ + public function testValidNotClassFormatPublic() + { + $this->assertTrue(Common::isCamelCaps('thisIsCamelCaps', false, true, true)); + $this->assertTrue(Common::isCamelCaps('thisISCamelCaps', false, true, false)); + + }//end testValidNotClassFormatPublic() + + + /** + * Test invalid public function/method names. + * + * @return void + */ + public function testInvalidNotClassFormatPublic() + { + $this->assertFalse(Common::isCamelCaps('_thisIsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('thisISCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('ThisIsCamelCaps', false, true, true)); + + $this->assertFalse(Common::isCamelCaps('3thisIsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('*thisIsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('-thisIsCamelCaps', false, true, true)); + + $this->assertFalse(Common::isCamelCaps('this*IsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('this-IsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('this_IsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('this_is_camel_caps', false, true, true)); + + }//end testInvalidNotClassFormatPublic() + + + /** + * Test valid private method names. + * + * @return void + */ + public function testValidNotClassFormatPrivate() + { + $this->assertTrue(Common::isCamelCaps('_thisIsCamelCaps', false, false, true)); + $this->assertTrue(Common::isCamelCaps('_thisISCamelCaps', false, false, false)); + $this->assertTrue(Common::isCamelCaps('_i18N', false, false, true)); + $this->assertTrue(Common::isCamelCaps('_i18n', false, false, true)); + + }//end testValidNotClassFormatPrivate() + + + /** + * Test invalid private method names. + * + * @return void + */ + public function testInvalidNotClassFormatPrivate() + { + $this->assertFalse(Common::isCamelCaps('thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('_thisISCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('__thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('__thisISCamelCaps', false, false, false)); + + $this->assertFalse(Common::isCamelCaps('3thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('*thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('-thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('_this_is_camel_caps', false, false, true)); + + }//end testInvalidNotClassFormatPrivate() + + + /** + * Test valid class names. + * + * @return void + */ + public function testValidClassFormatPublic() + { + $this->assertTrue(Common::isCamelCaps('ThisIsCamelCaps', true, true, true)); + $this->assertTrue(Common::isCamelCaps('ThisISCamelCaps', true, true, false)); + $this->assertTrue(Common::isCamelCaps('This3IsCamelCaps', true, true, false)); + + }//end testValidClassFormatPublic() + + + /** + * Test invalid class names. + * + * @return void + */ + public function testInvalidClassFormat() + { + $this->assertFalse(Common::isCamelCaps('thisIsCamelCaps', true)); + $this->assertFalse(Common::isCamelCaps('This-IsCamelCaps', true)); + $this->assertFalse(Common::isCamelCaps('This_Is_Camel_Caps', true)); + + }//end testInvalidClassFormat() + + + /** + * Test invalid class names with the private flag set. + * + * Note that the private flag is ignored if the class format + * flag is set, so these names are all invalid. + * + * @return void + */ + public function testInvalidClassFormatPrivate() + { + $this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', true, true)); + $this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', true, false)); + + }//end testInvalidClassFormatPrivate() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.php new file mode 100644 index 00000000..8b138e0b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.php @@ -0,0 +1,118 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Ruleset; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; +use PHPUnit\Framework\TestCase; + +class RuleInclusionAbsoluteLinuxTest extends TestCase +{ + + /** + * The Ruleset object. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected $ruleset; + + /** + * Path to the ruleset file. + * + * @var string + */ + private $standard = ''; + + /** + * The original content of the ruleset. + * + * @var string + */ + private $contents = ''; + + + /** + * Initialize the config and ruleset objects. + * + * @return void + */ + public function setUp() + { + if ($GLOBALS['PHP_CODESNIFFER_PEAR'] === true) { + // PEAR installs test and sniff files into different locations + // so these tests will not pass as they directly reference files + // by relative location. + $this->markTestSkipped('Test cannot run from a PEAR install'); + } + + $this->standard = __DIR__.'/'.basename(__FILE__, '.php').'.xml'; + $repoRootDir = dirname(dirname(dirname(__DIR__))); + + // On-the-fly adjust the ruleset test file to be able to test sniffs included with absolute paths. + $contents = file_get_contents($this->standard); + $this->contents = $contents; + + $newPath = $repoRootDir; + if (DIRECTORY_SEPARATOR === '\\') { + $newPath = str_replace('\\', '/', $repoRootDir); + } + + $adjusted = str_replace('%path_slash_forward%', $newPath, $contents); + + if (file_put_contents($this->standard, $adjusted) === false) { + $this->markTestSkipped('On the fly ruleset adjustment failed'); + } + + // Initialize the config and ruleset objects for the test. + $config = new Config(["--standard={$this->standard}"]); + $this->ruleset = new Ruleset($config); + + }//end setUp() + + + /** + * Reset ruleset file. + * + * @return void + */ + public function tearDown() + { + file_put_contents($this->standard, $this->contents); + + }//end tearDown() + + + /** + * Test that sniffs registed with a Linux absolute path are correctly recognized and that + * properties are correctly set for them. + * + * @return void + */ + public function testLinuxStylePathRuleInclusion() + { + // Test that the sniff is correctly registered. + $this->assertObjectHasAttribute('sniffCodes', $this->ruleset); + $this->assertCount(1, $this->ruleset->sniffCodes); + $this->assertArrayHasKey('Generic.Formatting.SpaceAfterNot', $this->ruleset->sniffCodes); + $this->assertSame( + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterNotSniff', + $this->ruleset->sniffCodes['Generic.Formatting.SpaceAfterNot'] + ); + + // Test that the sniff properties are correctly set. + $this->assertSame( + '10', + $this->ruleset->sniffs['PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterNotSniff']->spacing + ); + + }//end testLinuxStylePathRuleInclusion() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.xml b/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.xml new file mode 100644 index 00000000..64d1aae6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.php new file mode 100644 index 00000000..f8e3255b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.php @@ -0,0 +1,119 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Ruleset; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; +use PHPUnit\Framework\TestCase; + +class RuleInclusionAbsoluteWindowsTest extends TestCase +{ + + /** + * The Ruleset object. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected $ruleset; + + /** + * Path to the ruleset file. + * + * @var string + */ + private $standard = ''; + + /** + * The original content of the ruleset. + * + * @var string + */ + private $contents = ''; + + + /** + * Initialize the config and ruleset objects. + * + * @return void + */ + public function setUp() + { + if (DIRECTORY_SEPARATOR === '/') { + $this->markTestSkipped('Windows specific test'); + } + + if ($GLOBALS['PHP_CODESNIFFER_PEAR'] === true) { + // PEAR installs test and sniff files into different locations + // so these tests will not pass as they directly reference files + // by relative location. + $this->markTestSkipped('Test cannot run from a PEAR install'); + } + + $this->standard = __DIR__.'/'.basename(__FILE__, '.php').'.xml'; + $repoRootDir = dirname(dirname(dirname(__DIR__))); + + // On-the-fly adjust the ruleset test file to be able to test sniffs included with absolute paths. + $contents = file_get_contents($this->standard); + $this->contents = $contents; + + $adjusted = str_replace('%path_slash_back%', $repoRootDir, $contents); + + if (file_put_contents($this->standard, $adjusted) === false) { + $this->markTestSkipped('On the fly ruleset adjustment failed'); + } + + // Initialize the config and ruleset objects for the test. + $config = new Config(["--standard={$this->standard}"]); + $this->ruleset = new Ruleset($config); + + }//end setUp() + + + /** + * Reset ruleset file. + * + * @return void + */ + public function tearDown() + { + if (DIRECTORY_SEPARATOR !== '/') { + file_put_contents($this->standard, $this->contents); + } + + }//end tearDown() + + + /** + * Test that sniffs registed with a Windows absolute path are correctly recognized and that + * properties are correctly set for them. + * + * @return void + */ + public function testWindowsStylePathRuleInclusion() + { + // Test that the sniff is correctly registered. + $this->assertObjectHasAttribute('sniffCodes', $this->ruleset); + $this->assertCount(1, $this->ruleset->sniffCodes); + $this->assertArrayHasKey('Generic.Formatting.SpaceAfterCast', $this->ruleset->sniffCodes); + $this->assertSame( + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterCastSniff', + $this->ruleset->sniffCodes['Generic.Formatting.SpaceAfterCast'] + ); + + // Test that the sniff property is correctly set. + $this->assertSame( + '10', + $this->ruleset->sniffs['PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterCastSniff']->spacing + ); + + }//end testWindowsStylePathRuleInclusion() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.xml b/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.xml new file mode 100644 index 00000000..15710d20 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest-include.xml b/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest-include.xml new file mode 100644 index 00000000..ca116d45 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest-include.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.php new file mode 100644 index 00000000..24abe8da --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.php @@ -0,0 +1,297 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Ruleset; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; +use PHPUnit\Framework\TestCase; + +class RuleInclusionTest extends TestCase +{ + + /** + * The Ruleset object. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected static $ruleset; + + /** + * Path to the ruleset file. + * + * @var string + */ + private static $standard = ''; + + /** + * The original content of the ruleset. + * + * @var string + */ + private static $contents = ''; + + + /** + * Initialize the test. + * + * @return void + */ + public function setUp() + { + if ($GLOBALS['PHP_CODESNIFFER_PEAR'] === true) { + // PEAR installs test and sniff files into different locations + // so these tests will not pass as they directly reference files + // by relative location. + $this->markTestSkipped('Test cannot run from a PEAR install'); + } + + }//end setUp() + + + /** + * Initialize the config and ruleset objects based on the `RuleInclusionTest.xml` ruleset file. + * + * @return void + */ + public static function setUpBeforeClass() + { + if ($GLOBALS['PHP_CODESNIFFER_PEAR'] === true) { + // This test will be skipped. + return; + } + + $standard = __DIR__.'/'.basename(__FILE__, '.php').'.xml'; + self::$standard = $standard; + + // On-the-fly adjust the ruleset test file to be able to test + // sniffs included with relative paths. + $contents = file_get_contents($standard); + self::$contents = $contents; + + $repoRootDir = basename(dirname(dirname(dirname(__DIR__)))); + + $newPath = $repoRootDir; + if (DIRECTORY_SEPARATOR === '\\') { + $newPath = str_replace('\\', '/', $repoRootDir); + } + + $adjusted = str_replace('%path_root_dir%', $newPath, $contents); + + if (file_put_contents($standard, $adjusted) === false) { + self::markTestSkipped('On the fly ruleset adjustment failed'); + } + + $config = new Config(["--standard=$standard"]); + self::$ruleset = new Ruleset($config); + + }//end setUpBeforeClass() + + + /** + * Reset ruleset file. + * + * @return void + */ + public function tearDown() + { + file_put_contents(self::$standard, self::$contents); + + }//end tearDown() + + + /** + * Test that sniffs are registered. + * + * @return void + */ + public function testHasSniffCodes() + { + $this->assertObjectHasAttribute('sniffCodes', self::$ruleset); + $this->assertCount(14, self::$ruleset->sniffCodes); + + }//end testHasSniffCodes() + + + /** + * Test that sniffs are correctly registered, independently on the syntax used to include the sniff. + * + * @param string $key Expected array key. + * @param string $value Expected array value. + * + * @dataProvider dataRegisteredSniffCodes + * + * @return void + */ + public function testRegisteredSniffCodes($key, $value) + { + $this->assertArrayHasKey($key, self::$ruleset->sniffCodes); + $this->assertSame($value, self::$ruleset->sniffCodes[$key]); + + }//end testRegisteredSniffCodes() + + + /** + * Data provider. + * + * @see self::testRegisteredSniffCodes() + * + * @return array + */ + public function dataRegisteredSniffCodes() + { + return [ + [ + 'PSR1.Classes.ClassDeclaration', + 'PHP_CodeSniffer\Standards\PSR1\Sniffs\Classes\ClassDeclarationSniff', + ], + [ + 'PSR1.Files.SideEffects', + 'PHP_CodeSniffer\Standards\PSR1\Sniffs\Files\SideEffectsSniff', + ], + [ + 'PSR1.Methods.CamelCapsMethodName', + 'PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniff', + ], + [ + 'Generic.PHP.DisallowAlternativePHPTags', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\DisallowAlternativePHPTagsSniff', + ], + [ + 'Generic.PHP.DisallowShortOpenTag', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\DisallowShortOpenTagSniff', + ], + [ + 'Generic.Files.ByteOrderMark', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Files\ByteOrderMarkSniff', + ], + [ + 'Squiz.Classes.ValidClassName', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes\ValidClassNameSniff', + ], + [ + 'Generic.NamingConventions.UpperCaseConstantName', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\UpperCaseConstantNameSniff', + ], + [ + 'Zend.NamingConventions.ValidVariableName', + 'PHP_CodeSniffer\Standards\Zend\Sniffs\NamingConventions\ValidVariableNameSniff', + ], + [ + 'Generic.Arrays.ArrayIndent', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays\ArrayIndentSniff', + ], + [ + 'Generic.Metrics.CyclomaticComplexity', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\CyclomaticComplexitySniff', + ], + [ + 'Generic.Files.LineLength', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff', + ], + [ + 'Generic.NamingConventions.CamelCapsFunctionName', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff', + ], + [ + 'Generic.Metrics.NestingLevel', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\NestingLevelSniff', + ], + ]; + + }//end dataRegisteredSniffCodes() + + + /** + * Test that setting properties for standards, categories, sniffs works for all supported rule + * inclusion methods. + * + * @param string $sniffClass The name of the sniff class. + * @param string $propertyName The name of the changed property. + * @param mixed $expectedValue The value expected for the property. + * + * @dataProvider dataSettingProperties + * + * @return void + */ + public function testSettingProperties($sniffClass, $propertyName, $expectedValue) + { + $this->assertObjectHasAttribute('sniffs', self::$ruleset); + $this->assertArrayHasKey($sniffClass, self::$ruleset->sniffs); + $this->assertObjectHasAttribute($propertyName, self::$ruleset->sniffs[$sniffClass]); + + $actualValue = self::$ruleset->sniffs[$sniffClass]->$propertyName; + $this->assertSame($expectedValue, $actualValue); + + }//end testSettingProperties() + + + /** + * Data provider. + * + * @see self::testSettingProperties() + * + * @return array + */ + public function dataSettingProperties() + { + return [ + 'ClassDeclarationSniff' => [ + 'PHP_CodeSniffer\Standards\PSR1\Sniffs\Classes\ClassDeclarationSniff', + 'setforallsniffs', + true, + ], + 'SideEffectsSniff' => [ + 'PHP_CodeSniffer\Standards\PSR1\Sniffs\Files\SideEffectsSniff', + 'setforallsniffs', + true, + ], + 'ValidVariableNameSniff' => [ + 'PHP_CodeSniffer\Standards\Zend\Sniffs\NamingConventions\ValidVariableNameSniff', + 'setforallincategory', + true, + ], + 'ArrayIndentSniff' => [ + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays\ArrayIndentSniff', + 'indent', + '2', + ], + 'LineLengthSniff' => [ + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff', + 'lineLimit', + '10', + ], + 'CamelCapsFunctionNameSniff' => [ + 'PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff', + 'strict', + false, + ], + 'NestingLevelSniff-nestingLevel' => [ + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\NestingLevelSniff', + 'nestingLevel', + '2', + ], + 'NestingLevelSniff-setforsniffsinincludedruleset' => [ + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\NestingLevelSniff', + 'setforsniffsinincludedruleset', + true, + ], + + // Testing that setting a property at error code level does *not* work. + 'CyclomaticComplexitySniff' => [ + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\CyclomaticComplexitySniff', + 'complexity', + 10, + ], + ]; + + }//end dataSettingProperties() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.xml b/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.xml new file mode 100644 index 00000000..06ce040e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.inc new file mode 100644 index 00000000..48822958 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.inc @@ -0,0 +1,51 @@ +1,'2'=>2,'3'=>3]; + +/* testMissingKeys */ +$foo = ['1'=>1,2,'3'=>3]; + +/* testMultiTokenKeys */ +$paths = array( + Init::ROOT_DIR.'/a' => 'a', + Init::ROOT_DIR.'/b' => 'b', +); + +/* testMissingKeysCoalesceTernary */ +return [ + $a => static function () { return [1,2,3]; }, + $b ?? $c, + $d ? [$e] : [$f], +]; + +/* testTernaryValues */ +$foo = [ + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], array('notverified', 'unverified'), true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), +]; + +/* testHeredocValues */ +$foo = array( + << '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', +); diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.php new file mode 100644 index 00000000..20c28d60 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.php @@ -0,0 +1,290 @@ + + * @copyright 2006-2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Sniffs; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class AbstractArraySniffTest extends AbstractMethodUnitTest +{ + + /** + * The sniff objects we are testing. + * + * This extends the \PHP_CodeSniffer\Sniffs\AbstractArraySniff class to make the + * internal workings of the sniff observable. + * + * @var \PHP_CodeSniffer\Sniffs\AbstractArraySniffTestable + */ + protected static $sniff; + + + /** + * Initialize & tokenize \PHP_CodeSniffer\Files\File with code from the test case file. + * + * The test case file for a unit test class has to be in the same directory + * directory and use the same file name as the test class, using the .inc extension. + * + * @return void + */ + public static function setUpBeforeClass() + { + self::$sniff = new AbstractArraySniffTestable(); + parent::setUpBeforeClass(); + + }//end setUpBeforeClass() + + + /** + * Test an array of simple values only. + * + * @return void + */ + public function testSimpleValues() + { + $token = $this->getTargetToken('/* testSimpleValues */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => ['value_start' => ($token + 1)], + 1 => ['value_start' => ($token + 3)], + 2 => ['value_start' => ($token + 5)], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testSimpleValues() + + + /** + * Test an array of simple keys and values. + * + * @return void + */ + public function testSimpleKeyValues() + { + $token = $this->getTargetToken('/* testSimpleKeyValues */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 1), + 'index_end' => ($token + 1), + 'arrow' => ($token + 2), + 'value_start' => ($token + 3), + ], + 1 => [ + 'index_start' => ($token + 5), + 'index_end' => ($token + 5), + 'arrow' => ($token + 6), + 'value_start' => ($token + 7), + ], + 2 => [ + 'index_start' => ($token + 9), + 'index_end' => ($token + 9), + 'arrow' => ($token + 10), + 'value_start' => ($token + 11), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testSimpleKeyValues() + + + /** + * Test an array of simple keys and values. + * + * @return void + */ + public function testMissingKeys() + { + $token = $this->getTargetToken('/* testMissingKeys */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 1), + 'index_end' => ($token + 1), + 'arrow' => ($token + 2), + 'value_start' => ($token + 3), + ], + 1 => [ + 'value_start' => ($token + 5), + ], + 2 => [ + 'index_start' => ($token + 7), + 'index_end' => ($token + 7), + 'arrow' => ($token + 8), + 'value_start' => ($token + 9), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testMissingKeys() + + + /** + * Test an array with keys that span multiple tokens. + * + * @return void + */ + public function testMultiTokenKeys() + { + $token = $this->getTargetToken('/* testMultiTokenKeys */', T_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 4), + 'index_end' => ($token + 8), + 'arrow' => ($token + 10), + 'value_start' => ($token + 12), + ], + 1 => [ + 'index_start' => ($token + 16), + 'index_end' => ($token + 20), + 'arrow' => ($token + 22), + 'value_start' => ($token + 24), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testMultiTokenKeys() + + + /** + * Test an array of simple keys and values. + * + * @return void + */ + public function testMissingKeysCoalesceTernary() + { + $token = $this->getTargetToken('/* testMissingKeysCoalesceTernary */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 3), + 'index_end' => ($token + 3), + 'arrow' => ($token + 5), + 'value_start' => ($token + 7), + ], + 1 => [ + 'value_start' => ($token + 31), + ], + 2 => [ + 'value_start' => ($token + 39), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testMissingKeysCoalesceTernary() + + + /** + * Test an array of ternary values. + * + * @return void + */ + public function testTernaryValues() + { + $token = $this->getTargetToken('/* testTernaryValues */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 3), + 'index_end' => ($token + 3), + 'arrow' => ($token + 5), + 'value_start' => ($token + 7), + ], + 1 => [ + 'index_start' => ($token + 32), + 'index_end' => ($token + 32), + 'arrow' => ($token + 34), + 'value_start' => ($token + 36), + ], + 2 => [ + 'index_start' => ($token + 72), + 'index_end' => ($token + 72), + 'arrow' => ($token + 74), + 'value_start' => ($token + 76), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testTernaryValues() + + + /** + * Test an array of heredocs. + * + * @return void + */ + public function testHeredocValues() + { + $token = $this->getTargetToken('/* testHeredocValues */', T_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'value_start' => ($token + 4), + ], + 1 => [ + 'value_start' => ($token + 10), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testHeredocValues() + + + /** + * Test an array of with an arrow function as a value. + * + * @return void + */ + public function testArrowFunctionValue() + { + $token = $this->getTargetToken('/* testArrowFunctionValue */', T_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 4), + 'index_end' => ($token + 4), + 'arrow' => ($token + 6), + 'value_start' => ($token + 8), + ], + 1 => [ + 'index_start' => ($token + 12), + 'index_end' => ($token + 12), + 'arrow' => ($token + 14), + 'value_start' => ($token + 16), + ], + 2 => [ + 'index_start' => ($token + 34), + 'index_end' => ($token + 34), + 'arrow' => ($token + 36), + 'value_start' => ($token + 38), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testArrowFunctionValue() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTestable.php b/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTestable.php new file mode 100644 index 00000000..a224012f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTestable.php @@ -0,0 +1,65 @@ + + * @copyright 2006-2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Sniffs; + +use PHP_CodeSniffer\Sniffs\AbstractArraySniff; + +class AbstractArraySniffTestable extends AbstractArraySniff +{ + + /** + * The array indicies that were found during processing. + * + * @var array + */ + public $indicies = []; + + + /** + * Processes a single-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + public function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) + { + $this->indicies = $indices; + + }//end processSingleLineArray() + + + /** + * Processes a multi-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + public function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) + { + $this->indicies = $indices; + + }//end processMultiLineArray() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/AnonClassParenthesisOwnerTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/AnonClassParenthesisOwnerTest.inc new file mode 100644 index 00000000..5867691c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/AnonClassParenthesisOwnerTest.inc @@ -0,0 +1,19 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class AnonClassParenthesisOwnerTest extends AbstractMethodUnitTest +{ + + + /** + * Test that anonymous class tokens without parenthesis do not get assigned a parenthesis owner. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataAnonClassNoParentheses + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testAnonClassNoParentheses($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $anonClass = $this->getTargetToken($testMarker, T_ANON_CLASS); + $this->assertFalse(array_key_exists('parenthesis_owner', $tokens[$anonClass])); + $this->assertFalse(array_key_exists('parenthesis_opener', $tokens[$anonClass])); + $this->assertFalse(array_key_exists('parenthesis_closer', $tokens[$anonClass])); + + }//end testAnonClassNoParentheses() + + + /** + * Test that the next open/close parenthesis after an anonymous class without parenthesis + * do not get assigned the anonymous class as a parenthesis owner. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataAnonClassNoParentheses + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testAnonClassNoParenthesesNextOpenClose($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + $function = $this->getTargetToken($testMarker, T_FUNCTION); + + $opener = $this->getTargetToken($testMarker, T_OPEN_PARENTHESIS); + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$opener])); + $this->assertSame($function, $tokens[$opener]['parenthesis_owner']); + + $closer = $this->getTargetToken($testMarker, T_CLOSE_PARENTHESIS); + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$closer])); + $this->assertSame($function, $tokens[$closer]['parenthesis_owner']); + + }//end testAnonClassNoParenthesesNextOpenClose() + + + /** + * Data provider. + * + * @see testAnonClassNoParentheses() + * @see testAnonClassNoParenthesesNextOpenClose() + * + * @return array + */ + public function dataAnonClassNoParentheses() + { + return [ + ['/* testNoParentheses */'], + ['/* testNoParenthesesAndEmptyTokens */'], + ]; + + }//end dataAnonClassNoParentheses() + + + /** + * Test that anonymous class tokens with parenthesis get assigned a parenthesis owner, + * opener and closer; and that the opener/closer get the anonymous class assigned as owner. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataAnonClassWithParentheses + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testAnonClassWithParentheses($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + $anonClass = $this->getTargetToken($testMarker, T_ANON_CLASS); + $opener = $this->getTargetToken($testMarker, T_OPEN_PARENTHESIS); + $closer = $this->getTargetToken($testMarker, T_CLOSE_PARENTHESIS); + + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$anonClass])); + $this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$anonClass])); + $this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$anonClass])); + $this->assertSame($anonClass, $tokens[$anonClass]['parenthesis_owner']); + $this->assertSame($opener, $tokens[$anonClass]['parenthesis_opener']); + $this->assertSame($closer, $tokens[$anonClass]['parenthesis_closer']); + + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$opener])); + $this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$opener])); + $this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$opener])); + $this->assertSame($anonClass, $tokens[$opener]['parenthesis_owner']); + $this->assertSame($opener, $tokens[$opener]['parenthesis_opener']); + $this->assertSame($closer, $tokens[$opener]['parenthesis_closer']); + + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$closer])); + $this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$closer])); + $this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$closer])); + $this->assertSame($anonClass, $tokens[$closer]['parenthesis_owner']); + $this->assertSame($opener, $tokens[$closer]['parenthesis_opener']); + $this->assertSame($closer, $tokens[$closer]['parenthesis_closer']); + + }//end testAnonClassWithParentheses() + + + /** + * Data provider. + * + * @see testAnonClassWithParentheses() + * + * @return array + */ + public function dataAnonClassWithParentheses() + { + return [ + ['/* testWithParentheses */'], + ['/* testWithParenthesesAndEmptyTokens */'], + ]; + + }//end dataAnonClassWithParentheses() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ArrayKeywordTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ArrayKeywordTest.inc new file mode 100644 index 00000000..ce5c553c --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ArrayKeywordTest.inc @@ -0,0 +1,35 @@ + 10); + +/* testArrayWithComment */ +$var = Array /*comment*/ (1 => 10); + +/* testNestingArray */ +$var = array( + /* testNestedArray */ + array( + 'key' => 'value', + + /* testClosureReturnType */ + 'closure' => function($a) use($global) : Array {}, + ), +); + +/* testFunctionDeclarationParamType */ +function foo(array $a) {} + +/* testFunctionDeclarationReturnType */ +function foo($a) : int|array|null {} + +class Bar { + /* testClassConst */ + const ARRAY = []; + + /* testClassMethod */ + public function array() {} +} diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ArrayKeywordTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ArrayKeywordTest.php new file mode 100644 index 00000000..237258a6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ArrayKeywordTest.php @@ -0,0 +1,170 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class ArrayKeywordTest extends AbstractMethodUnitTest +{ + + + /** + * Test that the array keyword is correctly tokenized as `T_ARRAY`. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent Optional. The token content to look for. + * + * @dataProvider dataArrayKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap + * + * @return void + */ + public function testArrayKeyword($testMarker, $testContent='array') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_ARRAY, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_ARRAY (code)'); + $this->assertSame('T_ARRAY', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_ARRAY (type)'); + + $this->assertArrayHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is not set'); + $this->assertArrayHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is not set'); + + }//end testArrayKeyword() + + + /** + * Data provider. + * + * @see testArrayKeyword() + * + * @return array + */ + public function dataArrayKeyword() + { + return [ + 'empty array' => ['/* testEmptyArray */'], + 'array with space before parenthesis' => ['/* testArrayWithSpace */'], + 'array with comment before parenthesis' => [ + '/* testArrayWithComment */', + 'Array', + ], + 'nested: outer array' => ['/* testNestingArray */'], + 'nested: inner array' => ['/* testNestedArray */'], + ]; + + }//end dataArrayKeyword() + + + /** + * Test that the array keyword when used in a type declaration is correctly tokenized as `T_STRING`. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent Optional. The token content to look for. + * + * @dataProvider dataArrayType + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap + * + * @return void + */ + public function testArrayType($testMarker, $testContent='array') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + }//end testArrayType() + + + /** + * Data provider. + * + * @see testArrayType() + * + * @return array + */ + public function dataArrayType() + { + return [ + 'closure return type' => [ + '/* testClosureReturnType */', + 'Array', + ], + 'function param type' => ['/* testFunctionDeclarationParamType */'], + 'function union return type' => ['/* testFunctionDeclarationReturnType */'], + ]; + + }//end dataArrayType() + + + /** + * Verify that the retokenization of `T_ARRAY` tokens to `T_STRING` is handled correctly + * for tokens with the contents 'array' which aren't in actual fact the array keyword. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotArrayKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap + * + * @return void + */ + public function testNotArrayKeyword($testMarker, $testContent='array') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + }//end testNotArrayKeyword() + + + /** + * Data provider. + * + * @see testNotArrayKeyword() + * + * @return array + */ + public function dataNotArrayKeyword() + { + return [ + 'class-constant-name' => [ + '/* testClassConst */', + 'ARRAY', + ], + 'class-method-name' => ['/* testClassMethod */'], + ]; + + }//end dataNotArrayKeyword() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/AttributesTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/AttributesTest.inc new file mode 100644 index 00000000..e539adf8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/AttributesTest.inc @@ -0,0 +1,90 @@ + 'foobar'])] +function attribute_with_params_on_function_test() {} + +/* testAttributeWithShortClosureParameter */ +#[AttributeWithParams(static fn ($value) => ! $value)] +function attribute_with_short_closure_param_test() {} + +/* testTwoAttributeOnTheSameLine */ +#[CustomAttribute] #[AttributeWithParams('foo')] +function two_attribute_on_same_line_test() {} + +/* testAttributeAndCommentOnTheSameLine */ +#[CustomAttribute] // This is a comment +function attribute_and_line_comment_on_same_line_test() {} + +/* testAttributeGrouping */ +#[CustomAttribute, AttributeWithParams('foo'), AttributeWithParams('foo', bar: ['bar' => 'foobar'])] +function attribute_grouping_test() {} + +/* testAttributeMultiline */ +#[ + CustomAttribute, + AttributeWithParams('foo'), + AttributeWithParams('foo', bar: ['bar' => 'foobar']) +] +function attribute_multiline_test() {} + +/* testAttributeMultilineWithComment */ +#[ + CustomAttribute, // comment + AttributeWithParams(/* another comment */ 'foo'), + AttributeWithParams('foo', bar: ['bar' => 'foobar']) +] +function attribute_multiline_with_comment_test() {} + +/* testSingleAttributeOnParameter */ +function single_attribute_on_parameter_test(#[ParamAttribute] int $param) {} + +/* testMultipleAttributesOnParameter */ +function multiple_attributes_on_parameter_test(#[ParamAttribute, AttributeWithParams(/* another comment */ 'foo')] int $param) {} + +/* testFqcnAttribute */ +#[Boo\QualifiedName, \Foo\FullyQualifiedName('foo')] +function fqcn_attrebute_test() {} + +/* testNestedAttributes */ +#[Boo\QualifiedName(fn (#[AttributeOne('boo')] $value) => (string) $value)] +function nested_attributes_test() {} + +/* testMultilineAttributesOnParameter */ +function multiline_attributes_on_parameter_test(#[ + AttributeWithParams( + 'foo' + ) + ] int $param) {} + +/* testAttributeContainingTextLookingLikeCloseTag */ +#[DeprecationReason('reason: ')] +function attribute_containing_text_looking_like_close_tag() {} + +/* testAttributeContainingMultilineTextLookingLikeCloseTag */ +#[DeprecationReason( + 'reason: ' +)] +function attribute_containing_mulitline_text_looking_like_close_tag() {} + +/* testInvalidAttribute */ +#[ThisIsNotAnAttribute +function invalid_attribute_test() {} diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/AttributesTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/AttributesTest.php new file mode 100644 index 00000000..b10a1efb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/AttributesTest.php @@ -0,0 +1,659 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +class AttributesTest extends AbstractMethodUnitTest +{ + + + /** + * Test that attributes are parsed correctly. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int $length The number of tokens between opener and closer. + * @param array $tokenCodes The codes of tokens inside the attributes. + * + * @dataProvider dataAttribute + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testAttribute($testMarker, $length, $tokenCodes) + { + $tokens = self::$phpcsFile->getTokens(); + + $attribute = $this->getTargetToken($testMarker, T_ATTRIBUTE); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(($attribute + $length), $closer); + + $this->assertSame(T_ATTRIBUTE_END, $tokens[$closer]['code']); + + $this->assertSame($tokens[$attribute]['attribute_opener'], $tokens[$closer]['attribute_opener']); + $this->assertSame($tokens[$attribute]['attribute_closer'], $tokens[$closer]['attribute_closer']); + + $map = array_map( + function ($token) use ($attribute, $length) { + $this->assertArrayHasKey('attribute_closer', $token); + $this->assertSame(($attribute + $length), $token['attribute_closer']); + + return $token['code']; + }, + array_slice($tokens, ($attribute + 1), ($length - 1)) + ); + + $this->assertSame($tokenCodes, $map); + + }//end testAttribute() + + + /** + * Data provider. + * + * @see testAttribute() + * + * @return array + */ + public function dataAttribute() + { + return [ + [ + '/* testAttribute */', + 2, + [ T_STRING ], + ], + [ + '/* testAttributeWithParams */', + 7, + [ + T_STRING, + T_OPEN_PARENTHESIS, + T_STRING, + T_DOUBLE_COLON, + T_STRING, + T_CLOSE_PARENTHESIS, + ], + ], + [ + '/* testAttributeWithNamedParam */', + 10, + [ + T_STRING, + T_OPEN_PARENTHESIS, + T_PARAM_NAME, + T_COLON, + T_WHITESPACE, + T_STRING, + T_DOUBLE_COLON, + T_STRING, + T_CLOSE_PARENTHESIS, + ], + ], + [ + '/* testAttributeOnFunction */', + 2, + [ T_STRING ], + ], + [ + '/* testAttributeOnFunctionWithParams */', + 17, + [ + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_COMMA, + T_WHITESPACE, + T_PARAM_NAME, + T_COLON, + T_WHITESPACE, + T_OPEN_SHORT_ARRAY, + T_CONSTANT_ENCAPSED_STRING, + T_WHITESPACE, + T_DOUBLE_ARROW, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_SHORT_ARRAY, + T_CLOSE_PARENTHESIS, + ], + ], + [ + '/* testAttributeWithShortClosureParameter */', + 17, + [ + T_STRING, + T_OPEN_PARENTHESIS, + T_STATIC, + T_WHITESPACE, + T_FN, + T_WHITESPACE, + T_OPEN_PARENTHESIS, + T_VARIABLE, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_FN_ARROW, + T_WHITESPACE, + T_BOOLEAN_NOT, + T_WHITESPACE, + T_VARIABLE, + T_CLOSE_PARENTHESIS, + ], + ], + [ + '/* testAttributeGrouping */', + 26, + [ + T_STRING, + T_COMMA, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + T_COMMA, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_COMMA, + T_WHITESPACE, + T_PARAM_NAME, + T_COLON, + T_WHITESPACE, + T_OPEN_SHORT_ARRAY, + T_CONSTANT_ENCAPSED_STRING, + T_WHITESPACE, + T_DOUBLE_ARROW, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_SHORT_ARRAY, + T_CLOSE_PARENTHESIS, + ], + ], + [ + '/* testAttributeMultiline */', + 31, + [ + T_WHITESPACE, + T_WHITESPACE, + T_STRING, + T_COMMA, + T_WHITESPACE, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + T_COMMA, + T_WHITESPACE, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_COMMA, + T_WHITESPACE, + T_PARAM_NAME, + T_COLON, + T_WHITESPACE, + T_OPEN_SHORT_ARRAY, + T_CONSTANT_ENCAPSED_STRING, + T_WHITESPACE, + T_DOUBLE_ARROW, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_SHORT_ARRAY, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + ], + ], + [ + '/* testFqcnAttribute */', + 13, + [ + T_STRING, + T_NS_SEPARATOR, + T_STRING, + T_COMMA, + T_WHITESPACE, + T_NS_SEPARATOR, + T_STRING, + T_NS_SEPARATOR, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + ], + ], + ]; + + }//end dataAttribute() + + + /** + * Test that multiple attributes on the same line are parsed correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testTwoAttributesOnTheSameLine() + { + $tokens = self::$phpcsFile->getTokens(); + + $attribute = $this->getTargetToken('/* testTwoAttributeOnTheSameLine */', T_ATTRIBUTE); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(T_WHITESPACE, $tokens[($closer + 1)]['code']); + $this->assertSame(T_ATTRIBUTE, $tokens[($closer + 2)]['code']); + $this->assertArrayHasKey('attribute_closer', $tokens[($closer + 2)]); + + }//end testTwoAttributesOnTheSameLine() + + + /** + * Test that attribute followed by a line comment is parsed correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testAttributeAndLineComment() + { + $tokens = self::$phpcsFile->getTokens(); + + $attribute = $this->getTargetToken('/* testAttributeAndCommentOnTheSameLine */', T_ATTRIBUTE); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(T_WHITESPACE, $tokens[($closer + 1)]['code']); + $this->assertSame(T_COMMENT, $tokens[($closer + 2)]['code']); + + }//end testAttributeAndLineComment() + + + /** + * Test that attribute followed by a line comment is parsed correctly. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int $position The token position (starting from T_FUNCTION) of T_ATTRIBUTE token. + * @param int $length The number of tokens between opener and closer. + * @param array $tokenCodes The codes of tokens inside the attributes. + * + * @dataProvider dataAttributeOnParameters + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testAttributeOnParameters($testMarker, $position, $length, array $tokenCodes) + { + $tokens = self::$phpcsFile->getTokens(); + + $function = $this->getTargetToken($testMarker, T_FUNCTION); + $attribute = ($function + $position); + + $this->assertSame(T_ATTRIBUTE, $tokens[$attribute]['code']); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $this->assertSame(($attribute + $length), $tokens[$attribute]['attribute_closer']); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(T_WHITESPACE, $tokens[($closer + 1)]['code']); + $this->assertSame(T_STRING, $tokens[($closer + 2)]['code']); + $this->assertSame('int', $tokens[($closer + 2)]['content']); + + $this->assertSame(T_VARIABLE, $tokens[($closer + 4)]['code']); + $this->assertSame('$param', $tokens[($closer + 4)]['content']); + + $map = array_map( + function ($token) use ($attribute, $length) { + $this->assertArrayHasKey('attribute_closer', $token); + $this->assertSame(($attribute + $length), $token['attribute_closer']); + + return $token['code']; + }, + array_slice($tokens, ($attribute + 1), ($length - 1)) + ); + + $this->assertSame($tokenCodes, $map); + + }//end testAttributeOnParameters() + + + /** + * Data provider. + * + * @see testAttributeOnParameters() + * + * @return array + */ + public function dataAttributeOnParameters() + { + return [ + [ + '/* testSingleAttributeOnParameter */', + 4, + 2, + [T_STRING], + ], + [ + '/* testMultipleAttributesOnParameter */', + 4, + 10, + [ + T_STRING, + T_COMMA, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_COMMENT, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + ], + ], + [ + '/* testMultilineAttributesOnParameter */', + 4, + 13, + [ + T_WHITESPACE, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_WHITESPACE, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_WHITESPACE, + T_WHITESPACE, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_WHITESPACE, + ], + ], + ]; + + }//end dataAttributeOnParameters() + + + /** + * Test that an attribute containing text which looks like a PHP close tag is tokenized correctly. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int $length The number of tokens between opener and closer. + * @param array $expectedTokensAttribute The codes of tokens inside the attributes. + * @param array $expectedTokensAfter The codes of tokens after the attributes. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @dataProvider dataAttributeOnTextLookingLikeCloseTag + * + * @return void + */ + public function testAttributeContainingTextLookingLikeCloseTag($testMarker, $length, array $expectedTokensAttribute, array $expectedTokensAfter) + { + $tokens = self::$phpcsFile->getTokens(); + + $attribute = $this->getTargetToken($testMarker, T_ATTRIBUTE); + + $this->assertSame('T_ATTRIBUTE', $tokens[$attribute]['type']); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(($attribute + $length), $closer); + $this->assertSame(T_ATTRIBUTE_END, $tokens[$closer]['code']); + $this->assertSame('T_ATTRIBUTE_END', $tokens[$closer]['type']); + + $this->assertSame($tokens[$attribute]['attribute_opener'], $tokens[$closer]['attribute_opener']); + $this->assertSame($tokens[$attribute]['attribute_closer'], $tokens[$closer]['attribute_closer']); + + $i = ($attribute + 1); + foreach ($expectedTokensAttribute as $item) { + list($expectedType, $expectedContents) = $item; + $this->assertSame($expectedType, $tokens[$i]['type']); + $this->assertSame($expectedContents, $tokens[$i]['content']); + $this->assertArrayHasKey('attribute_opener', $tokens[$i]); + $this->assertArrayHasKey('attribute_closer', $tokens[$i]); + ++$i; + } + + $i = ($closer + 1); + foreach ($expectedTokensAfter as $expectedCode) { + $this->assertSame($expectedCode, $tokens[$i]['code']); + ++$i; + } + + }//end testAttributeContainingTextLookingLikeCloseTag() + + + /** + * Data provider. + * + * @see dataAttributeOnTextLookingLikeCloseTag() + * + * @return array + */ + public function dataAttributeOnTextLookingLikeCloseTag() + { + return [ + [ + '/* testAttributeContainingTextLookingLikeCloseTag */', + 5, + [ + [ + 'T_STRING', + 'DeprecationReason', + ], + [ + 'T_OPEN_PARENTHESIS', + '(', + ], + [ + 'T_CONSTANT_ENCAPSED_STRING', + "'reason: '", + ], + [ + 'T_CLOSE_PARENTHESIS', + ')', + ], + [ + 'T_ATTRIBUTE_END', + ']', + ], + ], + [ + T_WHITESPACE, + T_FUNCTION, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET, + ], + ], + [ + '/* testAttributeContainingMultilineTextLookingLikeCloseTag */', + 8, + [ + [ + 'T_STRING', + 'DeprecationReason', + ], + [ + 'T_OPEN_PARENTHESIS', + '(', + ], + [ + 'T_WHITESPACE', + "\n", + ], + [ + 'T_WHITESPACE', + " ", + ], + [ + 'T_CONSTANT_ENCAPSED_STRING', + "'reason: '", + ], + [ + 'T_WHITESPACE', + "\n", + ], + [ + 'T_CLOSE_PARENTHESIS', + ')', + ], + [ + 'T_ATTRIBUTE_END', + ']', + ], + ], + [ + T_WHITESPACE, + T_FUNCTION, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET, + ], + ], + ]; + + }//end dataAttributeOnTextLookingLikeCloseTag() + + + /** + * Test that invalid attribute (or comment starting with #[ and without ]) are parsed correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testInvalidAttribute() + { + $tokens = self::$phpcsFile->getTokens(); + + $attribute = $this->getTargetToken('/* testInvalidAttribute */', T_ATTRIBUTE); + + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + $this->assertNull($tokens[$attribute]['attribute_closer']); + + }//end testInvalidAttribute() + + + /** + * Test that nested attributes are parsed correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testNestedAttributes() + { + $tokens = self::$phpcsFile->getTokens(); + $tokenCodes = [ + T_STRING, + T_NS_SEPARATOR, + T_STRING, + T_OPEN_PARENTHESIS, + T_FN, + T_WHITESPACE, + T_OPEN_PARENTHESIS, + T_ATTRIBUTE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + T_ATTRIBUTE_END, + T_WHITESPACE, + T_VARIABLE, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_FN_ARROW, + T_WHITESPACE, + T_STRING_CAST, + T_WHITESPACE, + T_VARIABLE, + T_CLOSE_PARENTHESIS, + ]; + + $attribute = $this->getTargetToken('/* testNestedAttributes */', T_ATTRIBUTE); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(($attribute + 24), $closer); + + $this->assertSame(T_ATTRIBUTE_END, $tokens[$closer]['code']); + + $this->assertSame($tokens[$attribute]['attribute_opener'], $tokens[$closer]['attribute_opener']); + $this->assertSame($tokens[$attribute]['attribute_closer'], $tokens[$closer]['attribute_closer']); + + $this->assertArrayNotHasKey('nested_attributes', $tokens[$attribute]); + $this->assertArrayHasKey('nested_attributes', $tokens[($attribute + 8)]); + $this->assertSame([$attribute => ($attribute + 24)], $tokens[($attribute + 8)]['nested_attributes']); + + $test = function (array $tokens, $length, $nestedMap) use ($attribute) { + foreach ($tokens as $token) { + $this->assertArrayHasKey('attribute_closer', $token); + $this->assertSame(($attribute + $length), $token['attribute_closer']); + $this->assertSame($nestedMap, $token['nested_attributes']); + } + }; + + $test(array_slice($tokens, ($attribute + 1), 7), 24, [$attribute => $attribute + 24]); + $test(array_slice($tokens, ($attribute + 8), 1), 8 + 5, [$attribute => $attribute + 24]); + + // Length here is 8 (nested attribute offset) + 5 (real length). + $test( + array_slice($tokens, ($attribute + 9), 4), + 8 + 5, + [ + $attribute => $attribute + 24, + $attribute + 8 => $attribute + 13, + ] + ); + + $test(array_slice($tokens, ($attribute + 13), 1), 8 + 5, [$attribute => $attribute + 24]); + $test(array_slice($tokens, ($attribute + 14), 10), 24, [$attribute => $attribute + 24]); + + $map = array_map( + static function ($token) { + return $token['code']; + }, + array_slice($tokens, ($attribute + 1), 23) + ); + + $this->assertSame($tokenCodes, $map); + + }//end testNestedAttributes() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillEnumTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillEnumTest.inc new file mode 100644 index 00000000..82bfe24f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillEnumTest.inc @@ -0,0 +1,95 @@ +enum = 'foo'; + } +} + +/* testEnumUsedAsFunctionName */ +function enum() +{ +} + +/* testDeclarationContainingComment */ +enum /* comment */ Name +{ + case SOME_CASE; +} + +enum /* testEnumUsedAsEnumName */ Enum +{ +} + +/* testEnumUsedAsNamespaceName */ +namespace Enum; +/* testEnumUsedAsPartOfNamespaceName */ +namespace My\Enum\Collection; +/* testEnumUsedInObjectInitialization */ +$obj = new Enum; +/* testEnumAsFunctionCall */ +$var = enum($a, $b); +/* testEnumAsFunctionCallWithNamespace */ +var = namespace\enum(); +/* testClassConstantFetchWithEnumAsClassName */ +echo Enum::CONSTANT; +/* testClassConstantFetchWithEnumAsConstantName */ +echo ClassName::ENUM; + +/* testParseErrorMissingName */ +enum { + case SOME_CASE; +} + +/* testParseErrorLiveCoding */ +// This must be the last test in the file. +enum diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillEnumTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillEnumTest.php new file mode 100644 index 00000000..33cff3a2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillEnumTest.php @@ -0,0 +1,229 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class BackfillEnumTest extends AbstractMethodUnitTest +{ + + + /** + * Test that the "enum" keyword is tokenized as such. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $testContent The token content to look for. + * @param int $openerOffset Offset to find expected scope opener. + * @param int $closerOffset Offset to find expected scope closer. + * + * @dataProvider dataEnums + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testEnums($testMarker, $testContent, $openerOffset, $closerOffset) + { + $tokens = self::$phpcsFile->getTokens(); + + $enum = $this->getTargetToken($testMarker, [T_ENUM, T_STRING], $testContent); + + $this->assertSame(T_ENUM, $tokens[$enum]['code']); + $this->assertSame('T_ENUM', $tokens[$enum]['type']); + + $this->assertArrayHasKey('scope_condition', $tokens[$enum]); + $this->assertArrayHasKey('scope_opener', $tokens[$enum]); + $this->assertArrayHasKey('scope_closer', $tokens[$enum]); + + $this->assertSame($enum, $tokens[$enum]['scope_condition']); + + $scopeOpener = $tokens[$enum]['scope_opener']; + $scopeCloser = $tokens[$enum]['scope_closer']; + + $expectedScopeOpener = ($enum + $openerOffset); + $expectedScopeCloser = ($enum + $closerOffset); + + $this->assertSame($expectedScopeOpener, $scopeOpener); + $this->assertArrayHasKey('scope_condition', $tokens[$scopeOpener]); + $this->assertArrayHasKey('scope_opener', $tokens[$scopeOpener]); + $this->assertArrayHasKey('scope_closer', $tokens[$scopeOpener]); + $this->assertSame($enum, $tokens[$scopeOpener]['scope_condition']); + $this->assertSame($scopeOpener, $tokens[$scopeOpener]['scope_opener']); + $this->assertSame($scopeCloser, $tokens[$scopeOpener]['scope_closer']); + + $this->assertSame($expectedScopeCloser, $scopeCloser); + $this->assertArrayHasKey('scope_condition', $tokens[$scopeCloser]); + $this->assertArrayHasKey('scope_opener', $tokens[$scopeCloser]); + $this->assertArrayHasKey('scope_closer', $tokens[$scopeCloser]); + $this->assertSame($enum, $tokens[$scopeCloser]['scope_condition']); + $this->assertSame($scopeOpener, $tokens[$scopeCloser]['scope_opener']); + $this->assertSame($scopeCloser, $tokens[$scopeCloser]['scope_closer']); + + }//end testEnums() + + + /** + * Data provider. + * + * @see testEnums() + * + * @return array + */ + public function dataEnums() + { + return [ + [ + '/* testPureEnum */', + 'enum', + 4, + 12, + ], + [ + '/* testBackedIntEnum */', + 'enum', + 7, + 29, + ], + [ + '/* testBackedStringEnum */', + 'enum', + 8, + 30, + ], + [ + '/* testComplexEnum */', + 'enum', + 11, + 72, + ], + [ + '/* testEnumWithEnumAsClassName */', + 'enum', + 6, + 7, + ], + [ + '/* testEnumIsCaseInsensitive */', + 'EnUm', + 4, + 5, + ], + [ + '/* testDeclarationContainingComment */', + 'enum', + 6, + 14, + ], + ]; + + }//end dataEnums() + + + /** + * Test that "enum" when not used as the keyword is still tokenized as `T_STRING`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotEnums + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNotEnums($testMarker, $testContent) + { + $tokens = self::$phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, [T_ENUM, T_STRING], $testContent); + $this->assertSame(T_STRING, $tokens[$target]['code']); + $this->assertSame('T_STRING', $tokens[$target]['type']); + + }//end testNotEnums() + + + /** + * Data provider. + * + * @see testNotEnums() + * + * @return array + */ + public function dataNotEnums() + { + return [ + [ + '/* testEnumAsClassNameAfterEnumKeyword */', + 'Enum', + ], + [ + '/* testEnumUsedAsClassName */', + 'Enum', + ], + [ + '/* testEnumUsedAsClassConstantName */', + 'ENUM', + ], + [ + '/* testEnumUsedAsMethodName */', + 'enum', + ], + [ + '/* testEnumUsedAsPropertyName */', + 'enum', + ], + [ + '/* testEnumUsedAsFunctionName */', + 'enum', + ], + [ + '/* testEnumUsedAsEnumName */', + 'Enum', + ], + [ + '/* testEnumUsedAsNamespaceName */', + 'Enum', + ], + [ + '/* testEnumUsedAsPartOfNamespaceName */', + 'Enum', + ], + [ + '/* testEnumUsedInObjectInitialization */', + 'Enum', + ], + [ + '/* testEnumAsFunctionCall */', + 'enum', + ], + [ + '/* testEnumAsFunctionCallWithNamespace */', + 'enum', + ], + [ + '/* testClassConstantFetchWithEnumAsClassName */', + 'Enum', + ], + [ + '/* testClassConstantFetchWithEnumAsConstantName */', + 'ENUM', + ], + [ + '/* testParseErrorMissingName */', + 'enum', + ], + [ + '/* testParseErrorLiveCoding */', + 'enum', + ], + ]; + + }//end dataNotEnums() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.inc new file mode 100644 index 00000000..154d4895 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.inc @@ -0,0 +1,28 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class BackfillExplicitOctalNotationTest extends AbstractMethodUnitTest +{ + + + /** + * Test that explicitly-defined octal values are tokenized as a single number and not as a number and a string. + * + * @param string $marker The comment which prefaces the target token in the test file. + * @param string $value The expected content of the token + * @param int|string $nextToken The expected next token. + * @param string $nextContent The expected content of the next token. + * + * @dataProvider dataExplicitOctalNotation + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testExplicitOctalNotation($marker, $value, $nextToken, $nextContent) + { + $tokens = self::$phpcsFile->getTokens(); + + $number = $this->getTargetToken($marker, [T_LNUMBER]); + + $this->assertSame($value, $tokens[$number]['content'], 'Content of integer token does not match expectation'); + + $this->assertSame($nextToken, $tokens[($number + 1)]['code'], 'Next token is not the expected type, but '.$tokens[($number + 1)]['type']); + $this->assertSame($nextContent, $tokens[($number + 1)]['content'], 'Next token did not have the expected contents'); + + }//end testExplicitOctalNotation() + + + /** + * Data provider. + * + * @see testExplicitOctalNotation() + * + * @return array + */ + public function dataExplicitOctalNotation() + { + return [ + [ + 'marker' => '/* testExplicitOctal */', + 'value' => '0o137041', + 'nextToken' => T_SEMICOLON, + 'nextContent' => ';', + ], + [ + 'marker' => '/* testExplicitOctalCapitalised */', + 'value' => '0O137041', + 'nextToken' => T_SEMICOLON, + 'nextContent' => ';', + ], + [ + 'marker' => '/* testExplicitOctalWithNumericSeparator */', + 'value' => '0o137_041', + 'nextToken' => T_SEMICOLON, + 'nextContent' => ';', + ], + [ + 'marker' => '/* testInvalid1 */', + 'value' => '0', + 'nextToken' => T_STRING, + 'nextContent' => 'o_137', + ], + [ + 'marker' => '/* testInvalid2 */', + 'value' => '0', + 'nextToken' => T_STRING, + 'nextContent' => 'O_41', + ], + [ + 'marker' => '/* testInvalid3 */', + 'value' => '0', + 'nextToken' => T_STRING, + 'nextContent' => 'o91', + ], + [ + 'marker' => '/* testInvalid4 */', + 'value' => '0O2', + 'nextToken' => T_LNUMBER, + 'nextContent' => '82', + ], + [ + 'marker' => '/* testInvalid5 */', + 'value' => '0o2', + 'nextToken' => T_LNUMBER, + 'nextContent' => '8_2', + ], + [ + 'marker' => '/* testInvalid6 */', + 'value' => '0o2', + 'nextToken' => T_STRING, + 'nextContent' => '_82', + ], + ]; + + }//end dataExplicitOctalNotation() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillFnTokenTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillFnTokenTest.inc new file mode 100644 index 00000000..13f165b7 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillFnTokenTest.inc @@ -0,0 +1,198 @@ + $x + $y; + +/* testMixedCase */ +$fn1 = Fn($x) => $x + $y; + +/* testWhitespace */ +$fn1 = fn ($x) => $x + $y; + +/* testComment */ +$fn1 = fn /* comment here */ ($x) => $x + $y; + +/* testHeredoc */ +$fn1 = fn() => << /* testNestedInner */ fn($y) => $x * $y + $z; + +/* testNestedSharedCloserOuter */ +$foo = foo(fn() => /* testNestedSharedCloserInner */ fn() => bar() === true); + +/* testFunctionCall */ +$extended = fn($c) => $callable($factory($c), $c); + +/* testChainedFunctionCall */ +$result = Collection::from([1, 2]) + ->map(fn($v) => $v * 2) + ->reduce(/* testFunctionArgument */ fn($tmp, $v) => $tmp + $v, 0); + +/* testClosure */ +$extended = fn($c) => $callable(function() { + for ($x = 1; $x < 10; $x++) { + echo $x; + } + + echo 'done'; +}, $c); + +/* testArrayIndex */ +$found = in_array_cb($needle, $haystack, fn($array, $needle) => $array[2] === $needle); + +$result = array_map( + /* testReturnType */ + static fn(int $number) : int => $number + 1, + $numbers +); + +/* testReference */ +fn&($x) => $x; + +/* testGrouped */ +(fn($x) => $x) + $y; + +/* testArrayValue */ +$a = [ + 'a' => fn() => return 1, +]; + +/* testArrayValueNoTrailingComma */ +$a = [ + 'a' => fn() => foo() +]; + +/* testYield */ +$a = fn($x) => yield 'k' => $x; + +/* testNullableNamespace */ +$a = fn(?\DateTime $x) : ?\DateTime => $x; + +/* testNamespaceOperatorInTypes */ +$fn = fn(namespace\Foo $a) : ?namespace\Foo => $a; + +/* testSelfReturnType */ +fn(self $a) : self => $a; + +/* testParentReturnType */ +fn(parent $a) : parent => $a; + +/* testCallableReturnType */ +fn(callable $a) : callable => $a; + +/* testArrayReturnType */ +fn(array $a) : array => $a; + +/* testStaticReturnType */ +fn(array $a) : static => $a; + +/* testUnionParamType */ +$arrowWithUnionParam = fn(int|float $param) : SomeClass => new SomeClass($param); + +/* testUnionReturnType */ +$arrowWithUnionReturn = fn($param) : int|float => $param | 10; + +/* testTernary */ +$fn = fn($a) => $a ? /* testTernaryThen */ fn() : string => 'a' : /* testTernaryElse */ fn() : string => 'b'; + +/* testTernaryWithTypes */ +$fn = fn(int|null $a) : array|null => $a ? null : []; + +function matchInArrow($x) { + /* testWithMatchValue */ + $fn = fn($x) => match(true) { + 1, 2, 3, 4, 5 => 'foo', + default => 'bar', + }; +} + +function matchInArrowAndMore($x) { + /* testWithMatchValueAndMore */ + $fn = fn($x) => match(true) { + 1, 2, 3, 4, 5 => 'foo', + default => 'bar', + } . 'suffix'; +} + +function arrowFunctionInMatchWithTrailingComma($x) { + return match ($x) { + /* testInMatchNotLastValue */ + 1 => fn($y) => callMe($y), + /* testInMatchLastValueWithTrailingComma */ + default => fn($y) => callThem($y), + }; +} + +function arrowFunctionInMatchNoTrailingComma1($x) { + return match ($x) { + 1 => fn($y) => callMe($y), + /* testInMatchLastValueNoTrailingComma1 */ + default => fn($y) => callThem($y) + }; +} + +function arrowFunctionInMatchNoTrailingComma2($x) { + return match ($x) { + /* testInMatchLastValueNoTrailingComma2 */ + default => fn($y) => 5 * $y + }; +} + +/* testConstantDeclaration */ +const FN = 'a'; + +/* testConstantDeclarationLower */ +const fn = 'a'; + +class Foo { + /* testStaticMethodName */ + public static function fn($param) { + /* testNestedInMethod */ + $fn = fn($c) => $callable($factory($c), $c); + } + + public function foo() { + /* testPropertyAssignment */ + $this->fn = 'a'; + } +} + +$anon = new class() { + /* testAnonClassMethodName */ + protected function fN($param) { + } +} + +/* testNonArrowStaticMethodCall */ +$a = Foo::fn($param); + +/* testNonArrowConstantAccess */ +$a = MyClass::FN; + +/* testNonArrowConstantAccessMixed */ +$a = MyClass::Fn; + +/* testNonArrowObjectMethodCall */ +$a = $obj->fn($param); + +/* testNonArrowObjectMethodCallUpper */ +$a = $obj->FN($param); + +/* testNonArrowNamespacedFunctionCall */ +$a = MyNS\Sub\Fn($param); + +/* testNonArrowNamespaceOperatorFunctionCall */ +$a = namespace\fn($param); + +/* testNonArrowFunctionNameWithUnionTypes */ +function fn(int|float $param) : string|null {} + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +$fn = fn diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillFnTokenTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillFnTokenTest.php new file mode 100644 index 00000000..4d0f4c06 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillFnTokenTest.php @@ -0,0 +1,802 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class BackfillFnTokenTest extends AbstractMethodUnitTest +{ + + + /** + * Test simple arrow functions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testSimple() + { + foreach (['/* testStandard */', '/* testMixedCase */'] as $comment) { + $token = $this->getTargetToken($comment, T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 12); + } + + }//end testSimple() + + + /** + * Test whitespace inside arrow function definitions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testWhitespace() + { + $token = $this->getTargetToken('/* testWhitespace */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 6, 13); + + }//end testWhitespace() + + + /** + * Test comments inside arrow function definitions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testComment() + { + $token = $this->getTargetToken('/* testComment */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 8, 15); + + }//end testComment() + + + /** + * Test heredocs inside arrow function definitions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testHeredoc() + { + $token = $this->getTargetToken('/* testHeredoc */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 4, 9); + + }//end testHeredoc() + + + /** + * Test nested arrow functions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNestedOuter() + { + $token = $this->getTargetToken('/* testNestedOuter */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 25); + + }//end testNestedOuter() + + + /** + * Test nested arrow functions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNestedInner() + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testNestedInner */', T_FN); + $this->backfillHelper($token, true); + + $expectedScopeOpener = ($token + 5); + $expectedScopeCloser = ($token + 16); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer is not the semicolon token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer is not the semicolon token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame(($token - 4), $tokens[$closer]['scope_opener'], 'Closer scope opener is not the arrow token of the "outer" arrow function (shared scope closer)'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer is not the semicolon token'); + + }//end testNestedInner() + + + /** + * Test nested arrow functions with a shared closer. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNestedSharedCloser() + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testNestedSharedCloserOuter */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 4, 20); + + $token = $this->getTargetToken('/* testNestedSharedCloserInner */', T_FN); + $this->backfillHelper($token, true); + + $expectedScopeOpener = ($token + 4); + $expectedScopeCloser = ($token + 12); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener for "inner" arrow function is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer for "inner" arrow function is not the TRUE token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener for "inner" arrow function is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer for "inner" arrow function is not the semicolon token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame(($token - 4), $tokens[$closer]['scope_opener'], 'Closer scope opener for "inner" arrow function is not the arrow token of the "outer" arrow function (shared scope closer)'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer for "inner" arrow function is not the TRUE token'); + + }//end testNestedSharedCloser() + + + /** + * Test arrow functions that call functions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testFunctionCall() + { + $token = $this->getTargetToken('/* testFunctionCall */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 17); + + }//end testFunctionCall() + + + /** + * Test arrow functions that are included in chained calls. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testChainedFunctionCall() + { + $token = $this->getTargetToken('/* testChainedFunctionCall */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 12, 'bracket'); + + }//end testChainedFunctionCall() + + + /** + * Test arrow functions that are used as function arguments. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testFunctionArgument() + { + $token = $this->getTargetToken('/* testFunctionArgument */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 8, 15, 'comma'); + + }//end testFunctionArgument() + + + /** + * Test arrow functions that use closures. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testClosure() + { + $token = $this->getTargetToken('/* testClosure */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 60, 'comma'); + + }//end testClosure() + + + /** + * Test arrow functions using an array index. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testArrayIndex() + { + $token = $this->getTargetToken('/* testArrayIndex */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 8, 17, 'comma'); + + }//end testArrayIndex() + + + /** + * Test arrow functions with a return type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testReturnType() + { + $token = $this->getTargetToken('/* testReturnType */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 11, 18, 'comma'); + + }//end testReturnType() + + + /** + * Test arrow functions that return a reference. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testReference() + { + $token = $this->getTargetToken('/* testReference */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 6, 9); + + }//end testReference() + + + /** + * Test arrow functions that are grouped by parenthesis. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testGrouped() + { + $token = $this->getTargetToken('/* testGrouped */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 8); + + }//end testGrouped() + + + /** + * Test arrow functions that are used as array values. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testArrayValue() + { + $token = $this->getTargetToken('/* testArrayValue */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 4, 9, 'comma'); + + }//end testArrayValue() + + + /** + * Test arrow functions that are used as array values with no trailing comma. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testArrayValueNoTrailingComma() + { + $token = $this->getTargetToken('/* testArrayValueNoTrailingComma */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 4, 8, 'closing parenthesis'); + + }//end testArrayValueNoTrailingComma() + + + /** + * Test arrow functions that use the yield keyword. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testYield() + { + $token = $this->getTargetToken('/* testYield */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 14); + + }//end testYield() + + + /** + * Test arrow functions that use nullable namespace types. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNullableNamespace() + { + $token = $this->getTargetToken('/* testNullableNamespace */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 15, 18); + + }//end testNullableNamespace() + + + /** + * Test arrow functions that use the namespace operator in the return type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNamespaceOperatorInTypes() + { + $token = $this->getTargetToken('/* testNamespaceOperatorInTypes */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 16, 19); + + }//end testNamespaceOperatorInTypes() + + + /** + * Test arrow functions that use self/parent/callable/array/static return types. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testKeywordReturnTypes() + { + $tokens = self::$phpcsFile->getTokens(); + + $testMarkers = [ + 'Self', + 'Parent', + 'Callable', + 'Array', + 'Static', + ]; + + foreach ($testMarkers as $marker) { + $token = $this->getTargetToken('/* test'.$marker.'ReturnType */', T_FN); + $this->backfillHelper($token); + + $expectedScopeOpener = ($token + 11); + $expectedScopeCloser = ($token + 14); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], "Scope opener is not the arrow token (for $marker)"); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], "Scope closer is not the semicolon token(for $marker)"); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], "Opener scope opener is not the arrow token(for $marker)"); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], "Opener scope closer is not the semicolon token(for $marker)"); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame($expectedScopeOpener, $tokens[$closer]['scope_opener'], "Closer scope opener is not the arrow token(for $marker)"); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], "Closer scope closer is not the semicolon token(for $marker)"); + } + + }//end testKeywordReturnTypes() + + + /** + * Test arrow function with a union parameter type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testUnionParamType() + { + $token = $this->getTargetToken('/* testUnionParamType */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 13, 21); + + }//end testUnionParamType() + + + /** + * Test arrow function with a union return type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testUnionReturnType() + { + $token = $this->getTargetToken('/* testUnionReturnType */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 11, 18); + + }//end testUnionReturnType() + + + /** + * Test arrow functions used in ternary operators. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testTernary() + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testTernary */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 40); + + $token = $this->getTargetToken('/* testTernaryThen */', T_FN); + $this->backfillHelper($token); + + $expectedScopeOpener = ($token + 8); + $expectedScopeCloser = ($token + 12); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener for THEN is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer for THEN is not the semicolon token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener for THEN is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer for THEN is not the semicolon token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame($expectedScopeOpener, $tokens[$closer]['scope_opener'], 'Closer scope opener for THEN is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer for THEN is not the semicolon token'); + + $token = $this->getTargetToken('/* testTernaryElse */', T_FN); + $this->backfillHelper($token, true); + + $expectedScopeOpener = ($token + 8); + $expectedScopeCloser = ($token + 11); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener for ELSE is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer for ELSE is not the semicolon token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener for ELSE is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer for ELSE is not the semicolon token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame(($token - 24), $tokens[$closer]['scope_opener'], 'Closer scope opener for ELSE is not the arrow token of the "outer" arrow function (shared scope closer)'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer for ELSE is not the semicolon token'); + + }//end testTernary() + + + /** + * Test typed arrow functions used in ternary operators. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testTernaryWithTypes() + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testTernaryWithTypes */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 15, 27); + + }//end testTernaryWithTypes() + + + /** + * Test arrow function returning a match control structure. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testWithMatchValue() + { + $token = $this->getTargetToken('/* testWithMatchValue */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 44); + + }//end testWithMatchValue() + + + /** + * Test arrow function returning a match control structure with something behind it. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testWithMatchValueAndMore() + { + $token = $this->getTargetToken('/* testWithMatchValueAndMore */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 48); + + }//end testWithMatchValueAndMore() + + + /** + * Test match control structure returning arrow functions. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * @param string $expectedCloserType The type of token expected for the scope closer. + * @param string $expectedCloserFriendlyName A friendly name for the type of token expected for the scope closer + * to be used in the error message for failing tests. + * + * @dataProvider dataInMatchValue + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testInMatchValue($testMarker, $openerOffset, $closerOffset, $expectedCloserType, $expectedCloserFriendlyName) + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, $openerOffset, $closerOffset, $expectedCloserFriendlyName); + + $this->assertSame($expectedCloserType, $tokens[($token + $closerOffset)]['type'], 'Mismatched scope closer type'); + + }//end testInMatchValue() + + + /** + * Data provider. + * + * @see testInMatchValue() + * + * @return array + */ + public function dataInMatchValue() + { + return [ + 'not_last_value' => [ + '/* testInMatchNotLastValue */', + 5, + 11, + 'T_COMMA', + 'comma', + ], + 'last_value_with_trailing_comma' => [ + '/* testInMatchLastValueWithTrailingComma */', + 5, + 11, + 'T_COMMA', + 'comma', + ], + 'last_value_without_trailing_comma_1' => [ + '/* testInMatchLastValueNoTrailingComma1 */', + 5, + 10, + 'T_CLOSE_PARENTHESIS', + 'close parenthesis', + ], + 'last_value_without_trailing_comma_2' => [ + '/* testInMatchLastValueNoTrailingComma2 */', + 5, + 11, + 'T_VARIABLE', + '$y variable', + ], + ]; + + }//end dataInMatchValue() + + + /** + * Test arrow function nested within a method declaration. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNestedInMethod() + { + $token = $this->getTargetToken('/* testNestedInMethod */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 17); + + }//end testNestedInMethod() + + + /** + * Verify that "fn" keywords which are not arrow functions get tokenized as T_STRING and don't + * have the extra token array indexes. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotAnArrowFunction + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNotAnArrowFunction($testMarker, $testContent='fn') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_STRING, T_FN], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + }//end testNotAnArrowFunction() + + + /** + * Data provider. + * + * @see testNotAnArrowFunction() + * + * @return array + */ + public function dataNotAnArrowFunction() + { + return [ + ['/* testFunctionName */'], + [ + '/* testConstantDeclaration */', + 'FN', + ], + [ + '/* testConstantDeclarationLower */', + 'fn', + ], + ['/* testStaticMethodName */'], + ['/* testPropertyAssignment */'], + [ + '/* testAnonClassMethodName */', + 'fN', + ], + ['/* testNonArrowStaticMethodCall */'], + [ + '/* testNonArrowConstantAccess */', + 'FN', + ], + [ + '/* testNonArrowConstantAccessMixed */', + 'Fn', + ], + ['/* testNonArrowObjectMethodCall */'], + [ + '/* testNonArrowObjectMethodCallUpper */', + 'FN', + ], + [ + '/* testNonArrowNamespacedFunctionCall */', + 'Fn', + ], + ['/* testNonArrowNamespaceOperatorFunctionCall */'], + ['/* testNonArrowFunctionNameWithUnionTypes */'], + ['/* testLiveCoding */'], + ]; + + }//end dataNotAnArrowFunction() + + + /** + * Helper function to check that all token keys are correctly set for T_FN tokens. + * + * @param int $token The T_FN token to check. + * @param bool $skipScopeCloserCheck Whether to skip the scope closer check. + * This should be set to "true" when testing nested arrow functions, + * where the "inner" arrow function shares a scope closer with the + * "outer" arrow function, as the 'scope_condition' for the scope closer + * of the "inner" arrow function will point to the "outer" arrow function. + * + * @return void + */ + private function backfillHelper($token, $skipScopeCloserCheck=false) + { + $tokens = self::$phpcsFile->getTokens(); + + $this->assertTrue(array_key_exists('scope_condition', $tokens[$token]), 'Scope condition is not set'); + $this->assertTrue(array_key_exists('scope_opener', $tokens[$token]), 'Scope opener is not set'); + $this->assertTrue(array_key_exists('scope_closer', $tokens[$token]), 'Scope closer is not set'); + $this->assertSame($tokens[$token]['scope_condition'], $token, 'Scope condition is not the T_FN token'); + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$token]), 'Parenthesis owner is not set'); + $this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$token]), 'Parenthesis opener is not set'); + $this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$token]), 'Parenthesis closer is not set'); + $this->assertSame($tokens[$token]['parenthesis_owner'], $token, 'Parenthesis owner is not the T_FN token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertTrue(array_key_exists('scope_condition', $tokens[$opener]), 'Opener scope condition is not set'); + $this->assertTrue(array_key_exists('scope_opener', $tokens[$opener]), 'Opener scope opener is not set'); + $this->assertTrue(array_key_exists('scope_closer', $tokens[$opener]), 'Opener scope closer is not set'); + $this->assertSame($tokens[$opener]['scope_condition'], $token, 'Opener scope condition is not the T_FN token'); + $this->assertSame(T_FN_ARROW, $tokens[$opener]['code'], 'Arrow scope opener not tokenized as T_FN_ARROW (code)'); + $this->assertSame('T_FN_ARROW', $tokens[$opener]['type'], 'Arrow scope opener not tokenized as T_FN_ARROW (type)'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertTrue(array_key_exists('scope_condition', $tokens[$closer]), 'Closer scope condition is not set'); + $this->assertTrue(array_key_exists('scope_opener', $tokens[$closer]), 'Closer scope opener is not set'); + $this->assertTrue(array_key_exists('scope_closer', $tokens[$closer]), 'Closer scope closer is not set'); + if ($skipScopeCloserCheck === false) { + $this->assertSame($tokens[$closer]['scope_condition'], $token, 'Closer scope condition is not the T_FN token'); + } + + $opener = $tokens[$token]['parenthesis_opener']; + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$opener]), 'Opening parenthesis owner is not set'); + $this->assertSame($tokens[$opener]['parenthesis_owner'], $token, 'Opening parenthesis owner is not the T_FN token'); + + $closer = $tokens[$token]['parenthesis_closer']; + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$closer]), 'Closing parenthesis owner is not set'); + $this->assertSame($tokens[$closer]['parenthesis_owner'], $token, 'Closing parenthesis owner is not the T_FN token'); + + }//end backfillHelper() + + + /** + * Helper function to check that the scope opener/closer positions are correctly set for T_FN tokens. + * + * @param int $token The T_FN token to check. + * @param int $openerOffset The expected offset of the scope opener in relation to + * the fn keyword. + * @param int $closerOffset The expected offset of the scope closer in relation to + * the fn keyword. + * @param string $expectedCloserType Optional. The type of token expected for the scope closer. + * + * @return void + */ + private function scopePositionTestHelper($token, $openerOffset, $closerOffset, $expectedCloserType='semicolon') + { + $tokens = self::$phpcsFile->getTokens(); + $expectedScopeOpener = ($token + $openerOffset); + $expectedScopeCloser = ($token + $closerOffset); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer is not the '.$expectedCloserType.' token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer is not the '.$expectedCloserType.' token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame($expectedScopeOpener, $tokens[$closer]['scope_opener'], 'Closer scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer is not the '.$expectedCloserType.' token'); + + }//end scopePositionTestHelper() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillMatchTokenTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillMatchTokenTest.inc new file mode 100644 index 00000000..095a4d7d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillMatchTokenTest.inc @@ -0,0 +1,319 @@ + 'Zero', + 1 => 'One', + 2 => 'Two', + }; +} + +function matchNoTrailingComma($bool) { + /* testMatchNoTrailingComma */ + echo match ($bool) { + true => "true\n", + false => "false\n" + }; +} + +function matchWithDefault($i) { + /* testMatchWithDefault */ + return match ($i) { + 1 => 1, + 2 => 2, + default => 'default', + }; +} + +function matchExpressionInCondition($i) { + /* testMatchExpressionInCondition */ + return match (true) { + $i >= 50 => '50+', + $i >= 40 => '40-50', + $i >= 30 => '30-40', + $i >= 20 => '20-30', + $i >= 10 => '10-20', + default => '0-10', + }; +} + +function matchMultiCase($day) { + /* testMatchMultiCase */ + return match ($day) { + 1, 7 => false, + 2, 3, 4, 5, 6 => true, + }; +} + +function matchMultiCaseTrailingCommaInCase($bool) { + /* testMatchMultiCaseTrailingCommaInCase */ + echo match ($bool) { + false, + 0, + => "false\n", + true, + 1, + => "true\n", + default, + => "not bool\n", + }; +} + +assert((function () { + /* testMatchInClosureNotLowercase */ + Match ('foo') { + 'foo', 'bar' => false, + 'baz' => 'a', + default => 'b', + }; +})()); + +function matchInArrowFunction($x) { + /* testMatchInArrowFunction */ + $fn = fn($x) => match(true) { + 1, 2, 3, 4, 5 => 'foo', + default => 'bar', + }; +} + +function arrowFunctionInMatchNoTrailingComma($x) { + /* testArrowFunctionInMatchNoTrailingComma */ + return match ($x) { + 1 => fn($y) => callMe($y), + default => fn($y) => callThem($y) + }; +} + +/* testMatchInFunctionCallParamNotLowercase */ +var_dump(MATCH ( 'foo' ) { + 'foo' => dump_and_return('foo'), + 'bar' => dump_and_return('bar'), +}); + +/* testMatchInMethodCallParam */ +Test::usesValue(match(true) { true => $i }); + +/* testMatchDiscardResult */ +match (1) { + 1 => print "Executed\n", +}; + +/* testMatchWithDuplicateConditionsWithComments */ +echo match /*comment*/ ( $value /*comment*/ ) { + // Comment. + 2, 1 => '2, 1', + 1 => 1, + 3 => 3, + 4 => 4, + 5 => 5, +}; + +/* testNestedMatchOuter */ +$x = match ($y) { + /* testNestedMatchInner */ + default => match ($z) { 1 => 1 }, +}; + +/* testMatchInTernaryCondition */ +$x = match ($test) { 1 => 'a', 2 => 'b' } ? + /* testMatchInTernaryThen */ match ($test) { 1 => 'a', 2 => 'b' } : + /* testMatchInTernaryElse */ match ($notTest) { 3 => 'a', 4 => 'b' }; + +/* testMatchInArrayValue */ +$array = array( + match ($test) { 1 => 'a', 2 => 'b' }, +); + +/* testMatchInArrayKey */ +$array = [ + match ($test) { 1 => 'a', 2 => 'b' } => 'dynamic keys, woho!', +]; + +/* testMatchreturningArray */ +$matcher = match ($x) { + 0 => array( 0 => 1, 'a' => 2, 'b' => 3 ), + 1 => [1, 2, 3], + 2 => array( 1, [1, 2, 3], 2, 3), + 3 => [ 0 => 1, 'a' => array(1, 2, 3), 'b' => 2, 3], +}; + +/* testSwitchContainingMatch */ +switch ($something) { + /* testMatchWithDefaultNestedInSwitchCase1 */ + case 'foo': + $var = [1, 2, 3]; + $var = match ($i) { + 1 => 1, + default => 'default', + }; + continue 2; + + /* testMatchWithDefaultNestedInSwitchCase2 */ + case 'bar' ; + $i = callMe($a, $b); + return match ($i) { + 1 => 1, + default => 'default', + }; + + /* testMatchWithDefaultNestedInSwitchDefault */ + default: + echo 'something', match ($i) { + 1 => 1, + default => 'default', + }; + break; +} + +/* testMatchContainingSwitch */ +$x = match ($y) { + 5, 8 => function($z) { + /* testSwitchNestedInMatch1 */ + switch($z) { + case 'a': + $var = [1, 2, 3]; + return 'a'; + /* testSwitchDefaultNestedInMatchCase */ + default: + $i = callMe($a, $b); + return 'default1'; + } + }, + default => function($z) { + /* testSwitchNestedInMatch2 */ + switch($z) { + case 'a'; + $i = callMe($a, $b); + return 'b'; + /* testSwitchDefaultNestedInMatchDefault */ + default; + $var = [1, 2, 3]; + return 'default2'; + } + } +}; + +/* testMatchNoCases */ +// Intentional fatal error. +$x = match (true) {}; + +/* testMatchMultiDefault */ +// Intentional fatal error. +echo match (1) { + default => 'foo', + 1 => 'bar', + 2 => 'baz', + default => 'qux', +}; + +/* testNoMatchStaticMethodCall */ +$a = Foo::match($param); + +/* testNoMatchClassConstantAccess */ +$a = MyClass::MATCH; + +/* testNoMatchClassConstantArrayAccessMixedCase */ +$a = MyClass::Match[$a]; + +/* testNoMatchMethodCall */ +$a = $obj->match($param); + +/* testNoMatchMethodCallUpper */ +$a = $obj??->MATCH()->chain($param); + +/* testNoMatchPropertyAccess */ +$a = $obj->match; + +/* testNoMatchNamespacedFunctionCall */ +// Intentional fatal error. +$a = MyNS\Sub\match($param); + +/* testNoMatchNamespaceOperatorFunctionCall */ +// Intentional fatal error. +$a = namespace\match($param); + +interface MatchInterface { + /* testNoMatchInterfaceMethodDeclaration */ + public static function match($param); +} + +class MatchClass { + /* testNoMatchClassConstantDeclarationLower */ + const match = 'a'; + + /* testNoMatchClassMethodDeclaration */ + public static function match($param) { + /* testNoMatchPropertyAssignment */ + $this->match = 'a'; + } +} + +/* testNoMatchClassInstantiation */ +$obj = new Match(); + +$anon = new class() { + /* testNoMatchAnonClassMethodDeclaration */ + protected function maTCH($param) { + } +}; + +/* testNoMatchClassDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +class Match {} + +/* testNoMatchInterfaceDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +interface Match {} + +/* testNoMatchTraitDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +trait Match {} + +/* testNoMatchConstantDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +const MATCH = '1'; + +/* testNoMatchFunctionDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +function match() {} + +/* testNoMatchNamespaceDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +namespace Match {} + +/* testNoMatchExtendedClassDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +class Foo extends Match {} + +/* testNoMatchImplementedClassDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +class Bar implements Match {} + +/* testNoMatchInUseStatement */ +// Intentional fatal error in PHP < 8. Match is now a reserved keyword. +use Match\me; + +function brokenMatchNoCurlies($x) { + /* testNoMatchMissingCurlies */ + // Intentional fatal error. New control structure is not supported without curly braces. + return match ($x) + 0 => 'Zero', + 1 => 'One', + 2 => 'Two', + ; +} + +function brokenMatchAlternativeSyntax($x) { + /* testNoMatchAlternativeSyntax */ + // Intentional fatal error. Alternative syntax is not supported. + return match ($x) : + 0 => 'Zero', + 1 => 'One', + 2 => 'Two', + endmatch; +} + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +echo match diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillMatchTokenTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillMatchTokenTest.php new file mode 100644 index 00000000..80f909ac --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillMatchTokenTest.php @@ -0,0 +1,529 @@ + + * @copyright 2020-2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +class BackfillMatchTokenTest extends AbstractMethodUnitTest +{ + + + /** + * Test tokenization of match expressions. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * @param string $testContent The token content to look for. + * + * @dataProvider dataMatchExpression + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testMatchExpression($testMarker, $openerOffset, $closerOffset, $testContent='match') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_STRING, T_MATCH], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_MATCH, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH (code)'); + $this->assertSame('T_MATCH', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH (type)'); + + $this->scopeTestHelper($token, $openerOffset, $closerOffset); + $this->parenthesisTestHelper($token); + + }//end testMatchExpression() + + + /** + * Data provider. + * + * @see testMatchExpression() + * + * @return array + */ + public function dataMatchExpression() + { + return [ + 'simple_match' => [ + '/* testMatchSimple */', + 6, + 33, + ], + 'no_trailing_comma' => [ + '/* testMatchNoTrailingComma */', + 6, + 24, + ], + 'with_default_case' => [ + '/* testMatchWithDefault */', + 6, + 33, + ], + 'expression_in_condition' => [ + '/* testMatchExpressionInCondition */', + 6, + 77, + ], + 'multicase' => [ + '/* testMatchMultiCase */', + 6, + 40, + ], + 'multicase_trailing_comma_in_case' => [ + '/* testMatchMultiCaseTrailingCommaInCase */', + 6, + 47, + ], + 'in_closure_not_lowercase' => [ + '/* testMatchInClosureNotLowercase */', + 6, + 36, + 'Match', + ], + 'in_arrow_function' => [ + '/* testMatchInArrowFunction */', + 5, + 36, + ], + 'arrow_function_in_match_no_trailing_comma' => [ + '/* testArrowFunctionInMatchNoTrailingComma */', + 6, + 44, + ], + 'in_function_call_param_not_lowercase' => [ + '/* testMatchInFunctionCallParamNotLowercase */', + 8, + 32, + 'MATCH', + ], + 'in_method_call_param' => [ + '/* testMatchInMethodCallParam */', + 5, + 13, + ], + 'discard_result' => [ + '/* testMatchDiscardResult */', + 6, + 18, + ], + 'duplicate_conditions_and_comments' => [ + '/* testMatchWithDuplicateConditionsWithComments */', + 12, + 59, + ], + 'nested_match_outer' => [ + '/* testNestedMatchOuter */', + 6, + 33, + ], + 'nested_match_inner' => [ + '/* testNestedMatchInner */', + 6, + 14, + ], + 'ternary_condition' => [ + '/* testMatchInTernaryCondition */', + 6, + 21, + ], + 'ternary_then' => [ + '/* testMatchInTernaryThen */', + 6, + 21, + ], + 'ternary_else' => [ + '/* testMatchInTernaryElse */', + 6, + 21, + ], + 'array_value' => [ + '/* testMatchInArrayValue */', + 6, + 21, + ], + 'array_key' => [ + '/* testMatchInArrayKey */', + 6, + 21, + ], + 'returning_array' => [ + '/* testMatchreturningArray */', + 6, + 125, + ], + 'nested_in_switch_case_1' => [ + '/* testMatchWithDefaultNestedInSwitchCase1 */', + 6, + 25, + ], + 'nested_in_switch_case_2' => [ + '/* testMatchWithDefaultNestedInSwitchCase2 */', + 6, + 25, + ], + 'nested_in_switch_default' => [ + '/* testMatchWithDefaultNestedInSwitchDefault */', + 6, + 25, + ], + 'match_with_nested_switch' => [ + '/* testMatchContainingSwitch */', + 6, + 180, + ], + 'no_cases' => [ + '/* testMatchNoCases */', + 6, + 7, + ], + 'multi_default' => [ + '/* testMatchMultiDefault */', + 6, + 40, + ], + ]; + + }//end dataMatchExpression() + + + /** + * Verify that "match" keywords which are not match control structures get tokenized as T_STRING + * and don't have the extra token array indexes. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotAMatchStructure + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNotAMatchStructure($testMarker, $testContent='match') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_STRING, T_MATCH], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + $next = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($token + 1), null, true); + if ($next !== false && $tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set for opener after'); + } + + }//end testNotAMatchStructure() + + + /** + * Data provider. + * + * @see testNotAMatchStructure() + * + * @return array + */ + public function dataNotAMatchStructure() + { + return [ + 'static_method_call' => ['/* testNoMatchStaticMethodCall */'], + 'class_constant_access' => [ + '/* testNoMatchClassConstantAccess */', + 'MATCH', + ], + 'class_constant_array_access' => [ + '/* testNoMatchClassConstantArrayAccessMixedCase */', + 'Match', + ], + 'method_call' => ['/* testNoMatchMethodCall */'], + 'method_call_uppercase' => [ + '/* testNoMatchMethodCallUpper */', + 'MATCH', + ], + 'property_access' => ['/* testNoMatchPropertyAccess */'], + 'namespaced_function_call' => ['/* testNoMatchNamespacedFunctionCall */'], + 'namespace_operator_function_call' => ['/* testNoMatchNamespaceOperatorFunctionCall */'], + 'interface_method_declaration' => ['/* testNoMatchInterfaceMethodDeclaration */'], + 'class_constant_declaration' => ['/* testNoMatchClassConstantDeclarationLower */'], + 'class_method_declaration' => ['/* testNoMatchClassMethodDeclaration */'], + 'property_assigment' => ['/* testNoMatchPropertyAssignment */'], + 'class_instantiation' => [ + '/* testNoMatchClassInstantiation */', + 'Match', + ], + 'anon_class_method_declaration' => [ + '/* testNoMatchAnonClassMethodDeclaration */', + 'maTCH', + ], + 'class_declaration' => [ + '/* testNoMatchClassDeclaration */', + 'Match', + ], + 'interface_declaration' => [ + '/* testNoMatchInterfaceDeclaration */', + 'Match', + ], + 'trait_declaration' => [ + '/* testNoMatchTraitDeclaration */', + 'Match', + ], + 'constant_declaration' => [ + '/* testNoMatchConstantDeclaration */', + 'MATCH', + ], + 'function_declaration' => ['/* testNoMatchFunctionDeclaration */'], + 'namespace_declaration' => [ + '/* testNoMatchNamespaceDeclaration */', + 'Match', + ], + 'class_extends_declaration' => [ + '/* testNoMatchExtendedClassDeclaration */', + 'Match', + ], + 'class_implements_declaration' => [ + '/* testNoMatchImplementedClassDeclaration */', + 'Match', + ], + 'use_statement' => [ + '/* testNoMatchInUseStatement */', + 'Match', + ], + 'unsupported_inline_control_structure' => ['/* testNoMatchMissingCurlies */'], + 'unsupported_alternative_syntax' => ['/* testNoMatchAlternativeSyntax */'], + 'live_coding' => ['/* testLiveCoding */'], + ]; + + }//end dataNotAMatchStructure() + + + /** + * Verify that the tokenization of switch structures is not affected by the backfill. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * + * @dataProvider dataSwitchExpression + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testSwitchExpression($testMarker, $openerOffset, $closerOffset) + { + $token = $this->getTargetToken($testMarker, T_SWITCH); + + $this->scopeTestHelper($token, $openerOffset, $closerOffset); + $this->parenthesisTestHelper($token); + + }//end testSwitchExpression() + + + /** + * Data provider. + * + * @see testSwitchExpression() + * + * @return array + */ + public function dataSwitchExpression() + { + return [ + 'switch_containing_match' => [ + '/* testSwitchContainingMatch */', + 6, + 174, + ], + 'match_containing_switch_1' => [ + '/* testSwitchNestedInMatch1 */', + 5, + 63, + ], + 'match_containing_switch_2' => [ + '/* testSwitchNestedInMatch2 */', + 5, + 63, + ], + ]; + + }//end dataSwitchExpression() + + + /** + * Verify that the tokenization of a switch case/default structure containing a match structure + * or contained *in* a match structure is not affected by the backfill. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * + * @dataProvider dataSwitchCaseVersusMatch + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testSwitchCaseVersusMatch($testMarker, $openerOffset, $closerOffset) + { + $token = $this->getTargetToken($testMarker, [T_CASE, T_DEFAULT]); + + $this->scopeTestHelper($token, $openerOffset, $closerOffset); + + }//end testSwitchCaseVersusMatch() + + + /** + * Data provider. + * + * @see testSwitchCaseVersusMatch() + * + * @return array + */ + public function dataSwitchCaseVersusMatch() + { + return [ + 'switch_with_nested_match_case_1' => [ + '/* testMatchWithDefaultNestedInSwitchCase1 */', + 3, + 55, + ], + 'switch_with_nested_match_case_2' => [ + '/* testMatchWithDefaultNestedInSwitchCase2 */', + 4, + 21, + ], + 'switch_with_nested_match_default_case' => [ + '/* testMatchWithDefaultNestedInSwitchDefault */', + 1, + 38, + ], + 'match_with_nested_switch_case' => [ + '/* testSwitchDefaultNestedInMatchCase */', + 1, + 18, + ], + 'match_with_nested_switch_default_case' => [ + '/* testSwitchDefaultNestedInMatchDefault */', + 1, + 20, + ], + ]; + + }//end dataSwitchCaseVersusMatch() + + + /** + * Helper function to verify that all scope related array indexes for a control structure + * are set correctly. + * + * @param string $token The control structure token to check. + * @param int $openerOffset The expected offset of the scope opener in relation to + * the control structure token. + * @param int $closerOffset The expected offset of the scope closer in relation to + * the control structure token. + * @param bool $skipScopeCloserCheck Whether to skip the scope closer check. + * This should be set to "true" when testing nested arrow functions, + * where the "inner" arrow function shares a scope closer with the + * "outer" arrow function, as the 'scope_condition' for the scope closer + * of the "inner" arrow function will point to the "outer" arrow function. + * + * @return void + */ + private function scopeTestHelper($token, $openerOffset, $closerOffset, $skipScopeCloserCheck=false) + { + $tokens = self::$phpcsFile->getTokens(); + $tokenArray = $tokens[$token]; + $tokenType = $tokenArray['type']; + $expectedScopeOpener = ($token + $openerOffset); + $expectedScopeCloser = ($token + $closerOffset); + + $this->assertArrayHasKey('scope_condition', $tokenArray, 'Scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokenArray, 'Scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokenArray, 'Scope closer is not set'); + $this->assertSame($token, $tokenArray['scope_condition'], 'Scope condition is not the '.$tokenType.' token'); + $this->assertSame($expectedScopeOpener, $tokenArray['scope_opener'], 'Scope opener of the '.$tokenType.' token incorrect'); + $this->assertSame($expectedScopeCloser, $tokenArray['scope_closer'], 'Scope closer of the '.$tokenType.' token incorrect'); + + $opener = $tokenArray['scope_opener']; + $this->assertArrayHasKey('scope_condition', $tokens[$opener], 'Opener scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokens[$opener], 'Opener scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokens[$opener], 'Opener scope closer is not set'); + $this->assertSame($token, $tokens[$opener]['scope_condition'], 'Opener scope condition is not the '.$tokenType.' token'); + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], $tokenType.' opener scope opener token incorrect'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], $tokenType.' opener scope closer token incorrect'); + + $closer = $tokenArray['scope_closer']; + $this->assertArrayHasKey('scope_condition', $tokens[$closer], 'Closer scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokens[$closer], 'Closer scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokens[$closer], 'Closer scope closer is not set'); + if ($skipScopeCloserCheck === false) { + $this->assertSame($token, $tokens[$closer]['scope_condition'], 'Closer scope condition is not the '.$tokenType.' token'); + } + + $this->assertSame($expectedScopeOpener, $tokens[$closer]['scope_opener'], $tokenType.' closer scope opener token incorrect'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], $tokenType.' closer scope closer token incorrect'); + + if (($opener + 1) !== $closer) { + for ($i = ($opener + 1); $i < $closer; $i++) { + $this->assertArrayHasKey( + $token, + $tokens[$i]['conditions'], + $tokenType.' condition not added for token belonging to the '.$tokenType.' structure' + ); + } + } + + }//end scopeTestHelper() + + + /** + * Helper function to verify that all parenthesis related array indexes for a control structure + * token are set correctly. + * + * @param int $token The position of the control structure token. + * + * @return void + */ + private function parenthesisTestHelper($token) + { + $tokens = self::$phpcsFile->getTokens(); + $tokenArray = $tokens[$token]; + $tokenType = $tokenArray['type']; + + $this->assertArrayHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is not set'); + $this->assertArrayHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is not set'); + $this->assertSame($token, $tokenArray['parenthesis_owner'], 'Parenthesis owner is not the '.$tokenType.' token'); + + $opener = $tokenArray['parenthesis_opener']; + $this->assertArrayHasKey('parenthesis_owner', $tokens[$opener], 'Opening parenthesis owner is not set'); + $this->assertSame($token, $tokens[$opener]['parenthesis_owner'], 'Opening parenthesis owner is not the '.$tokenType.' token'); + + $closer = $tokenArray['parenthesis_closer']; + $this->assertArrayHasKey('parenthesis_owner', $tokens[$closer], 'Closing parenthesis owner is not set'); + $this->assertSame($token, $tokens[$closer]['parenthesis_owner'], 'Closing parenthesis owner is not the '.$tokenType.' token'); + + }//end parenthesisTestHelper() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc new file mode 100644 index 00000000..d8559705 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc @@ -0,0 +1,94 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class BackfillNumericSeparatorTest extends AbstractMethodUnitTest +{ + + + /** + * Test that numbers using numeric separators are tokenized correctly. + * + * @param array $testData The data required for the specific test case. + * + * @dataProvider dataTestBackfill + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testBackfill($testData) + { + $tokens = self::$phpcsFile->getTokens(); + $number = $this->getTargetToken($testData['marker'], [T_LNUMBER, T_DNUMBER]); + + $this->assertSame(constant($testData['type']), $tokens[$number]['code']); + $this->assertSame($testData['type'], $tokens[$number]['type']); + $this->assertSame($testData['value'], $tokens[$number]['content']); + + }//end testBackfill() + + + /** + * Data provider. + * + * @see testBackfill() + * + * @return array + */ + public function dataTestBackfill() + { + $testHexType = 'T_LNUMBER'; + if (PHP_INT_MAX < 0xCAFEF00D) { + $testHexType = 'T_DNUMBER'; + } + + $testHexMultipleType = 'T_LNUMBER'; + if (PHP_INT_MAX < 0x42726F776E) { + $testHexMultipleType = 'T_DNUMBER'; + } + + $testIntMoreThanMaxType = 'T_LNUMBER'; + if (PHP_INT_MAX < 10223372036854775807) { + $testIntMoreThanMaxType = 'T_DNUMBER'; + } + + return [ + [ + [ + 'marker' => '/* testSimpleLNumber */', + 'type' => 'T_LNUMBER', + 'value' => '1_000_000_000', + ], + ], + [ + [ + 'marker' => '/* testSimpleDNumber */', + 'type' => 'T_DNUMBER', + 'value' => '107_925_284.88', + ], + ], + [ + [ + 'marker' => '/* testFloat */', + 'type' => 'T_DNUMBER', + 'value' => '6.674_083e-11', + ], + ], + [ + [ + 'marker' => '/* testFloat2 */', + 'type' => 'T_DNUMBER', + 'value' => '6.674_083e+11', + ], + ], + [ + [ + 'marker' => '/* testFloat3 */', + 'type' => 'T_DNUMBER', + 'value' => '1_2.3_4e1_23', + ], + ], + [ + [ + 'marker' => '/* testHex */', + 'type' => $testHexType, + 'value' => '0xCAFE_F00D', + ], + ], + [ + [ + 'marker' => '/* testHexMultiple */', + 'type' => $testHexMultipleType, + 'value' => '0x42_72_6F_77_6E', + ], + ], + [ + [ + 'marker' => '/* testHexInt */', + 'type' => 'T_LNUMBER', + 'value' => '0x42_72_6F', + ], + ], + [ + [ + 'marker' => '/* testBinary */', + 'type' => 'T_LNUMBER', + 'value' => '0b0101_1111', + ], + ], + [ + [ + 'marker' => '/* testOctal */', + 'type' => 'T_LNUMBER', + 'value' => '0137_041', + ], + ], + [ + [ + 'marker' => '/* testExplicitOctal */', + 'type' => 'T_LNUMBER', + 'value' => '0o137_041', + ], + ], + [ + [ + 'marker' => '/* testExplicitOctalCapitalised */', + 'type' => 'T_LNUMBER', + 'value' => '0O137_041', + ], + ], + [ + [ + 'marker' => '/* testIntMoreThanMax */', + 'type' => $testIntMoreThanMaxType, + 'value' => '10_223_372_036_854_775_807', + ], + ], + ]; + + }//end dataTestBackfill() + + + /** + * Test that numbers using numeric separators which are considered parse errors and/or + * which aren't relevant to the backfill, do not incorrectly trigger the backfill anyway. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param array $expectedTokens The token type and content of the expected token sequence. + * + * @dataProvider dataNoBackfill + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNoBackfill($testMarker, $expectedTokens) + { + $tokens = self::$phpcsFile->getTokens(); + $number = $this->getTargetToken($testMarker, [T_LNUMBER, T_DNUMBER]); + + foreach ($expectedTokens as $key => $expectedToken) { + $i = ($number + $key); + $this->assertSame($expectedToken['code'], $tokens[$i]['code']); + $this->assertSame($expectedToken['content'], $tokens[$i]['content']); + } + + }//end testNoBackfill() + + + /** + * Data provider. + * + * @see testBackfill() + * + * @return array + */ + public function dataNoBackfill() + { + return [ + [ + '/* testInvalid1 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '100', + ], + [ + 'code' => T_STRING, + 'content' => '_', + ], + ], + ], + [ + '/* testInvalid2 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '1', + ], + [ + 'code' => T_STRING, + 'content' => '__1', + ], + ], + ], + [ + '/* testInvalid3 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '1', + ], + [ + 'code' => T_STRING, + 'content' => '_', + ], + [ + 'code' => T_DNUMBER, + 'content' => '.0', + ], + ], + ], + [ + '/* testInvalid4 */', + [ + [ + 'code' => T_DNUMBER, + 'content' => '1.', + ], + [ + 'code' => T_STRING, + 'content' => '_0', + ], + ], + ], + [ + '/* testInvalid5 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '0', + ], + [ + 'code' => T_STRING, + 'content' => 'x_123', + ], + ], + ], + [ + '/* testInvalid6 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '0', + ], + [ + 'code' => T_STRING, + 'content' => 'b_101', + ], + ], + ], + [ + '/* testInvalid7 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '1', + ], + [ + 'code' => T_STRING, + 'content' => '_e2', + ], + ], + ], + [ + '/* testInvalid8 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '1', + ], + [ + 'code' => T_STRING, + 'content' => 'e_2', + ], + ], + ], + [ + '/* testInvalid9 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '107_925_284', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_DNUMBER, + 'content' => '.88', + ], + ], + ], + [ + '/* testInvalid10 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '107_925_284', + ], + [ + 'code' => T_COMMENT, + 'content' => '/*comment*/', + ], + [ + 'code' => T_DNUMBER, + 'content' => '.88', + ], + ], + ], + [ + '/* testInvalid11 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '0', + ], + [ + 'code' => T_STRING, + 'content' => 'o_137', + ], + ], + ], + [ + '/* testInvalid12 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '0', + ], + [ + 'code' => T_STRING, + 'content' => 'O_41', + ], + ], + ], + [ + '/* testCalc1 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '667_083', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_MINUS, + 'content' => '-', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_LNUMBER, + 'content' => '11', + ], + ], + ], + [ + '/* test Calc2 */', + [ + [ + 'code' => T_DNUMBER, + 'content' => '6.674_08e3', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_PLUS, + 'content' => '+', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_LNUMBER, + 'content' => '11', + ], + ], + ], + ]; + + }//end dataNoBackfill() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillReadonlyTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillReadonlyTest.inc new file mode 100644 index 00000000..eaf0b4b3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillReadonlyTest.inc @@ -0,0 +1,100 @@ +readonly = 'foo'; + + /* testReadonlyPropertyInTernaryOperator */ + $isReadonly = $this->readonly ? true : false; + } +} + +/* testReadonlyUsedAsFunctionName */ +function readonly() +{ +} + +/* testReadonlyUsedAsNamespaceName */ +namespace Readonly; +/* testReadonlyUsedAsPartOfNamespaceName */ +namespace My\Readonly\Collection; +/* testReadonlyAsFunctionCall */ +$var = readonly($a, $b); +/* testClassConstantFetchWithReadonlyAsConstantName */ +echo ClassName::READONLY; + +/* testReadonlyUsedAsFunctionCallWithSpaceBetweenKeywordAndParens */ +$var = readonly /* comment */ (); + +/* testParseErrorLiveCoding */ +// This must be the last test in the file. +readonly diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillReadonlyTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillReadonlyTest.php new file mode 100644 index 00000000..dddc18eb --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillReadonlyTest.php @@ -0,0 +1,236 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class BackfillReadonlyTest extends AbstractMethodUnitTest +{ + + + /** + * Test that the "readonly" keyword is tokenized as such. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $testContent The token content to look for. + * + * @dataProvider dataReadonly + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testReadonly($testMarker, $testContent) + { + $tokens = self::$phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, [T_READONLY, T_STRING], $testContent); + $this->assertSame(T_READONLY, $tokens[$target]['code']); + $this->assertSame('T_READONLY', $tokens[$target]['type']); + + }//end testReadonly() + + + /** + * Data provider. + * + * @see testReadonly() + * + * @return array + */ + public function dataReadonly() + { + return [ + [ + '/* testReadonlyProperty */', + 'readonly', + ], + [ + '/* testVarReadonlyProperty */', + 'readonly', + ], + [ + '/* testReadonlyVarProperty */', + 'readonly', + ], + [ + '/* testStaticReadonlyProperty */', + 'readonly', + ], + [ + '/* testReadonlyStaticProperty */', + 'readonly', + ], + [ + '/* testConstReadonlyProperty */', + 'readonly', + ], + [ + '/* testReadonlyPropertyWithoutType */', + 'readonly', + ], + [ + '/* testPublicReadonlyProperty */', + 'readonly', + ], + [ + '/* testProtectedReadonlyProperty */', + 'readonly', + ], + [ + '/* testPrivateReadonlyProperty */', + 'readonly', + ], + [ + '/* testPublicReadonlyPropertyWithReadonlyFirst */', + 'readonly', + ], + [ + '/* testProtectedReadonlyPropertyWithReadonlyFirst */', + 'readonly', + ], + [ + '/* testPrivateReadonlyPropertyWithReadonlyFirst */', + 'readonly', + ], + [ + '/* testReadonlyWithCommentsInDeclaration */', + 'readonly', + ], + [ + '/* testReadonlyWithNullableProperty */', + 'readonly', + ], + [ + '/* testReadonlyNullablePropertyWithUnionTypeHintAndNullFirst */', + 'readonly', + ], + [ + '/* testReadonlyNullablePropertyWithUnionTypeHintAndNullLast */', + 'readonly', + ], + [ + '/* testReadonlyPropertyWithArrayTypeHint */', + 'readonly', + ], + [ + '/* testReadonlyPropertyWithSelfTypeHint */', + 'readonly', + ], + [ + '/* testReadonlyPropertyWithParentTypeHint */', + 'readonly', + ], + [ + '/* testReadonlyPropertyWithFullyQualifiedTypeHint */', + 'readonly', + ], + [ + '/* testReadonlyIsCaseInsensitive */', + 'ReAdOnLy', + ], + [ + '/* testReadonlyConstructorPropertyPromotion */', + 'readonly', + ], + [ + '/* testReadonlyConstructorPropertyPromotionWithReference */', + 'ReadOnly', + ], + [ + '/* testReadonlyPropertyInAnonymousClass */', + 'readonly', + ], + [ + '/* testReadonlyUsedAsFunctionCallWithSpaceBetweenKeywordAndParens */', + 'readonly', + ], + [ + '/* testParseErrorLiveCoding */', + 'readonly', + ], + ]; + + }//end dataReadonly() + + + /** + * Test that "readonly" when not used as the keyword is still tokenized as `T_STRING`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotReadonly + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNotReadonly($testMarker, $testContent) + { + $tokens = self::$phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, [T_READONLY, T_STRING], $testContent); + $this->assertSame(T_STRING, $tokens[$target]['code']); + $this->assertSame('T_STRING', $tokens[$target]['type']); + + }//end testNotReadonly() + + + /** + * Data provider. + * + * @see testNotReadonly() + * + * @return array + */ + public function dataNotReadonly() + { + return [ + [ + '/* testReadonlyUsedAsClassConstantName */', + 'READONLY', + ], + [ + '/* testReadonlyUsedAsMethodName */', + 'readonly', + ], + [ + '/* testReadonlyUsedAsPropertyName */', + 'readonly', + ], + [ + '/* testReadonlyPropertyInTernaryOperator */', + 'readonly', + ], + [ + '/* testReadonlyUsedAsFunctionName */', + 'readonly', + ], + [ + '/* testReadonlyUsedAsNamespaceName */', + 'Readonly', + ], + [ + '/* testReadonlyUsedAsPartOfNamespaceName */', + 'Readonly', + ], + [ + '/* testReadonlyAsFunctionCall */', + 'readonly', + ], + [ + '/* testClassConstantFetchWithReadonlyAsConstantName */', + 'READONLY', + ], + ]; + + }//end dataNotReadonly() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BitwiseOrTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BitwiseOrTest.inc new file mode 100644 index 00000000..bfdbdc18 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BitwiseOrTest.inc @@ -0,0 +1,134 @@ + $param | $int; + +/* testTypeUnionArrowReturnType */ +$arrowWithReturnType = fn ($param) : int|null => $param * 10; + +/* testBitwiseOrInArrayKey */ +$array = array( + A | B => /* testBitwiseOrInArrayValue */ B | C +); + +/* testBitwiseOrInShortArrayKey */ +$array = [ + A | B => /* testBitwiseOrInShortArrayValue */ B | C +]; + +/* testBitwiseOrTryCatch */ +try { +} catch ( ExceptionA | ExceptionB $e ) { +} + +/* testBitwiseOrNonArrowFnFunctionCall */ +$obj->fn($something | $else); + +/* testTypeUnionNonArrowFunctionDeclaration */ +function &fn(int|false $something) {} + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +return function( type| diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BitwiseOrTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BitwiseOrTest.php new file mode 100644 index 00000000..d56e7340 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/BitwiseOrTest.php @@ -0,0 +1,138 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class BitwiseOrTest extends AbstractMethodUnitTest +{ + + + /** + * Test that non-union type bitwise or tokens are still tokenized as bitwise or. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataBitwiseOr + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testBitwiseOr($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $opener = $this->getTargetToken($testMarker, [T_BITWISE_OR, T_TYPE_UNION]); + $this->assertSame(T_BITWISE_OR, $tokens[$opener]['code']); + $this->assertSame('T_BITWISE_OR', $tokens[$opener]['type']); + + }//end testBitwiseOr() + + + /** + * Data provider. + * + * @see testBitwiseOr() + * + * @return array + */ + public function dataBitwiseOr() + { + return [ + ['/* testBitwiseOr1 */'], + ['/* testBitwiseOr2 */'], + ['/* testBitwiseOrPropertyDefaultValue */'], + ['/* testBitwiseOrParamDefaultValue */'], + ['/* testBitwiseOr3 */'], + ['/* testBitwiseOrClosureParamDefault */'], + ['/* testBitwiseOrArrowParamDefault */'], + ['/* testBitwiseOrArrowExpression */'], + ['/* testBitwiseOrInArrayKey */'], + ['/* testBitwiseOrInArrayValue */'], + ['/* testBitwiseOrInShortArrayKey */'], + ['/* testBitwiseOrInShortArrayValue */'], + ['/* testBitwiseOrTryCatch */'], + ['/* testBitwiseOrNonArrowFnFunctionCall */'], + ['/* testLiveCoding */'], + ]; + + }//end dataBitwiseOr() + + + /** + * Test that bitwise or tokens when used as part of a union type are tokenized as `T_TYPE_UNION`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataTypeUnion + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testTypeUnion($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $opener = $this->getTargetToken($testMarker, [T_BITWISE_OR, T_TYPE_UNION]); + $this->assertSame(T_TYPE_UNION, $tokens[$opener]['code']); + $this->assertSame('T_TYPE_UNION', $tokens[$opener]['type']); + + }//end testTypeUnion() + + + /** + * Data provider. + * + * @see testTypeUnion() + * + * @return array + */ + public function dataTypeUnion() + { + return [ + ['/* testTypeUnionPropertySimple */'], + ['/* testTypeUnionPropertyReverseModifierOrder */'], + ['/* testTypeUnionPropertyMulti1 */'], + ['/* testTypeUnionPropertyMulti2 */'], + ['/* testTypeUnionPropertyMulti3 */'], + ['/* testTypeUnionPropertyNamespaceRelative */'], + ['/* testTypeUnionPropertyPartiallyQualified */'], + ['/* testTypeUnionPropertyFullyQualified */'], + ['/* testTypeUnionPropertyWithReadOnlyKeyword */'], + ['/* testTypeUnionPropertyWithReadOnlyKeywordFirst */'], + ['/* testTypeUnionPropertyWithStaticAndReadOnlyKeywords */'], + ['/* testTypeUnionPropertyWithVarAndReadOnlyKeywords */'], + ['/* testTypeUnionPropertyWithOnlyReadOnlyKeyword */'], + ['/* testTypeUnionParam1 */'], + ['/* testTypeUnionParam2 */'], + ['/* testTypeUnionParam3 */'], + ['/* testTypeUnionParamNamespaceRelative */'], + ['/* testTypeUnionParamPartiallyQualified */'], + ['/* testTypeUnionParamFullyQualified */'], + ['/* testTypeUnionReturnType */'], + ['/* testTypeUnionConstructorPropertyPromotion */'], + ['/* testTypeUnionAbstractMethodReturnType1 */'], + ['/* testTypeUnionAbstractMethodReturnType2 */'], + ['/* testTypeUnionReturnTypeNamespaceRelative */'], + ['/* testTypeUnionReturnPartiallyQualified */'], + ['/* testTypeUnionReturnFullyQualified */'], + ['/* testTypeUnionClosureParamIllegalNullable */'], + ['/* testTypeUnionWithReference */'], + ['/* testTypeUnionWithSpreadOperator */'], + ['/* testTypeUnionClosureReturn */'], + ['/* testTypeUnionArrowParam */'], + ['/* testTypeUnionArrowReturnType */'], + ['/* testTypeUnionNonArrowFunctionDeclaration */'], + ]; + + }//end dataTypeUnion() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.inc new file mode 100644 index 00000000..82fe5643 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.inc @@ -0,0 +1,227 @@ + 'a', + 2 => 'b', + /* testMatchDefaultIsKeyword */ default => 'default', +}; + +$closure = /* testFnIsKeyword */ fn () => 'string'; + +function () { + /* testYieldIsKeyword */ yield $f; + /* testYieldFromIsKeyword */ yield from someFunction(); +}; + +/* testDeclareIsKeyword */ declare(ticks=1): +/* testEndDeclareIsKeyword */ enddeclare; + +if (true /* testAndIsKeyword */ and false /* testOrIsKeyword */ or null /* testXorIsKeyword */ xor 0) { + +} + +$anonymousClass = new /* testAnonymousClassIsKeyword */ class {}; +$anonymousClass2 = new class /* testExtendsInAnonymousClassIsKeyword */ extends SomeParent {}; +$anonymousClass3 = new class /* testImplementsInAnonymousClassIsKeyword */ implements SomeInterface {}; + +$instantiated1 = new /* testClassInstantiationParentIsKeyword */ parent(); +$instantiated2 = new /* testClassInstantiationSelfIsKeyword */ SELF; +$instantiated3 = new /* testClassInstantiationStaticIsKeyword */ static($param); + +class Foo extends /* testNamespaceInNameIsKeyword */ namespace\Exception +{} + +function /* testKeywordAfterFunctionShouldBeString */ eval() {} +function /* testKeywordAfterFunctionByRefShouldBeString */ &switch() {} diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.php new file mode 100644 index 00000000..a747e573 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.php @@ -0,0 +1,509 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +class ContextSensitiveKeywordsTest extends AbstractMethodUnitTest +{ + + + /** + * Test that context sensitive keyword is tokenized as string when it should be string. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataStrings + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testStrings($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, (Tokens::$contextSensitiveKeywords + [T_STRING])); + + $this->assertSame(T_STRING, $tokens[$token]['code']); + $this->assertSame('T_STRING', $tokens[$token]['type']); + + }//end testStrings() + + + /** + * Data provider. + * + * @see testStrings() + * + * @return array + */ + public function dataStrings() + { + return [ + ['/* testAbstract */'], + ['/* testArray */'], + ['/* testAs */'], + ['/* testBreak */'], + ['/* testCallable */'], + ['/* testCase */'], + ['/* testCatch */'], + ['/* testClass */'], + ['/* testClone */'], + ['/* testConst */'], + ['/* testContinue */'], + ['/* testDeclare */'], + ['/* testDefault */'], + ['/* testDo */'], + ['/* testEcho */'], + ['/* testElse */'], + ['/* testElseIf */'], + ['/* testEmpty */'], + ['/* testEndDeclare */'], + ['/* testEndFor */'], + ['/* testEndForeach */'], + ['/* testEndIf */'], + ['/* testEndSwitch */'], + ['/* testEndWhile */'], + ['/* testEnum */'], + ['/* testEval */'], + ['/* testExit */'], + ['/* testExtends */'], + ['/* testFinal */'], + ['/* testFinally */'], + ['/* testFn */'], + ['/* testFor */'], + ['/* testForeach */'], + ['/* testFunction */'], + ['/* testGlobal */'], + ['/* testGoto */'], + ['/* testIf */'], + ['/* testImplements */'], + ['/* testInclude */'], + ['/* testIncludeOnce */'], + ['/* testInstanceOf */'], + ['/* testInsteadOf */'], + ['/* testInterface */'], + ['/* testIsset */'], + ['/* testList */'], + ['/* testMatch */'], + ['/* testNamespace */'], + ['/* testNew */'], + ['/* testParent */'], + ['/* testPrint */'], + ['/* testPrivate */'], + ['/* testProtected */'], + ['/* testPublic */'], + ['/* testReadonly */'], + ['/* testRequire */'], + ['/* testRequireOnce */'], + ['/* testReturn */'], + ['/* testSelf */'], + ['/* testStatic */'], + ['/* testSwitch */'], + ['/* testThrows */'], + ['/* testTrait */'], + ['/* testTry */'], + ['/* testUnset */'], + ['/* testUse */'], + ['/* testVar */'], + ['/* testWhile */'], + ['/* testYield */'], + ['/* testYieldFrom */'], + ['/* testAnd */'], + ['/* testOr */'], + ['/* testXor */'], + + ['/* testKeywordAfterNamespaceShouldBeString */'], + ['/* testNamespaceNameIsString1 */'], + ['/* testNamespaceNameIsString2 */'], + ['/* testNamespaceNameIsString3 */'], + + ['/* testKeywordAfterFunctionShouldBeString */'], + ['/* testKeywordAfterFunctionByRefShouldBeString */'], + ]; + + }//end dataStrings() + + + /** + * Test that context sensitive keyword is tokenized as keyword when it should be keyword. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $expectedTokenType The expected token type. + * + * @dataProvider dataKeywords + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testKeywords($testMarker, $expectedTokenType) + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, (Tokens::$contextSensitiveKeywords + [T_ANON_CLASS, T_MATCH_DEFAULT, T_PARENT, T_SELF, T_STRING])); + + $this->assertSame(constant($expectedTokenType), $tokens[$token]['code']); + $this->assertSame($expectedTokenType, $tokens[$token]['type']); + + }//end testKeywords() + + + /** + * Data provider. + * + * @see testKeywords() + * + * @return array + */ + public function dataKeywords() + { + return [ + [ + '/* testNamespaceIsKeyword */', + 'T_NAMESPACE', + ], + [ + '/* testAbstractIsKeyword */', + 'T_ABSTRACT', + ], + [ + '/* testClassIsKeyword */', + 'T_CLASS', + ], + [ + '/* testExtendsIsKeyword */', + 'T_EXTENDS', + ], + [ + '/* testImplementsIsKeyword */', + 'T_IMPLEMENTS', + ], + [ + '/* testUseIsKeyword */', + 'T_USE', + ], + [ + '/* testInsteadOfIsKeyword */', + 'T_INSTEADOF', + ], + [ + '/* testAsIsKeyword */', + 'T_AS', + ], + [ + '/* testConstIsKeyword */', + 'T_CONST', + ], + [ + '/* testPrivateIsKeyword */', + 'T_PRIVATE', + ], + [ + '/* testProtectedIsKeyword */', + 'T_PROTECTED', + ], + [ + '/* testPublicIsKeyword */', + 'T_PUBLIC', + ], + [ + '/* testVarIsKeyword */', + 'T_VAR', + ], + [ + '/* testStaticIsKeyword */', + 'T_STATIC', + ], + [ + '/* testReadonlyIsKeyword */', + 'T_READONLY', + ], + [ + '/* testFinalIsKeyword */', + 'T_FINAL', + ], + [ + '/* testFunctionIsKeyword */', + 'T_FUNCTION', + ], + [ + '/* testCallableIsKeyword */', + 'T_CALLABLE', + ], + [ + '/* testSelfIsKeyword */', + 'T_SELF', + ], + [ + '/* testParentIsKeyword */', + 'T_PARENT', + ], + [ + '/* testReturnIsKeyword */', + 'T_RETURN', + ], + + [ + '/* testInterfaceIsKeyword */', + 'T_INTERFACE', + ], + [ + '/* testTraitIsKeyword */', + 'T_TRAIT', + ], + [ + '/* testEnumIsKeyword */', + 'T_ENUM', + ], + + [ + '/* testNewIsKeyword */', + 'T_NEW', + ], + [ + '/* testInstanceOfIsKeyword */', + 'T_INSTANCEOF', + ], + [ + '/* testCloneIsKeyword */', + 'T_CLONE', + ], + + [ + '/* testIfIsKeyword */', + 'T_IF', + ], + [ + '/* testEmptyIsKeyword */', + 'T_EMPTY', + ], + [ + '/* testElseIfIsKeyword */', + 'T_ELSEIF', + ], + [ + '/* testElseIsKeyword */', + 'T_ELSE', + ], + [ + '/* testEndIfIsKeyword */', + 'T_ENDIF', + ], + + [ + '/* testForIsKeyword */', + 'T_FOR', + ], + [ + '/* testEndForIsKeyword */', + 'T_ENDFOR', + ], + + [ + '/* testForeachIsKeyword */', + 'T_FOREACH', + ], + [ + '/* testEndForeachIsKeyword */', + 'T_ENDFOREACH', + ], + + [ + '/* testSwitchIsKeyword */', + 'T_SWITCH', + ], + [ + '/* testCaseIsKeyword */', + 'T_CASE', + ], + [ + '/* testDefaultIsKeyword */', + 'T_DEFAULT', + ], + [ + '/* testEndSwitchIsKeyword */', + 'T_ENDSWITCH', + ], + [ + '/* testBreakIsKeyword */', + 'T_BREAK', + ], + [ + '/* testContinueIsKeyword */', + 'T_CONTINUE', + ], + + [ + '/* testDoIsKeyword */', + 'T_DO', + ], + [ + '/* testWhileIsKeyword */', + 'T_WHILE', + ], + [ + '/* testEndWhileIsKeyword */', + 'T_ENDWHILE', + ], + + [ + '/* testTryIsKeyword */', + 'T_TRY', + ], + [ + '/* testThrowIsKeyword */', + 'T_THROW', + ], + [ + '/* testCatchIsKeyword */', + 'T_CATCH', + ], + [ + '/* testFinallyIsKeyword */', + 'T_FINALLY', + ], + + [ + '/* testGlobalIsKeyword */', + 'T_GLOBAL', + ], + [ + '/* testEchoIsKeyword */', + 'T_ECHO', + ], + [ + '/* testPrintIsKeyword */', + 'T_PRINT', + ], + [ + '/* testDieIsKeyword */', + 'T_EXIT', + ], + [ + '/* testEvalIsKeyword */', + 'T_EVAL', + ], + [ + '/* testExitIsKeyword */', + 'T_EXIT', + ], + [ + '/* testIssetIsKeyword */', + 'T_ISSET', + ], + [ + '/* testUnsetIsKeyword */', + 'T_UNSET', + ], + + [ + '/* testIncludeIsKeyword */', + 'T_INCLUDE', + ], + [ + '/* testIncludeOnceIsKeyword */', + 'T_INCLUDE_ONCE', + ], + [ + '/* testRequireIsKeyword */', + 'T_REQUIRE', + ], + [ + '/* testRequireOnceIsKeyword */', + 'T_REQUIRE_ONCE', + ], + + [ + '/* testListIsKeyword */', + 'T_LIST', + ], + [ + '/* testGotoIsKeyword */', + 'T_GOTO', + ], + [ + '/* testMatchIsKeyword */', + 'T_MATCH', + ], + [ + '/* testMatchDefaultIsKeyword */', + 'T_MATCH_DEFAULT', + ], + [ + '/* testFnIsKeyword */', + 'T_FN', + ], + + [ + '/* testYieldIsKeyword */', + 'T_YIELD', + ], + [ + '/* testYieldFromIsKeyword */', + 'T_YIELD_FROM', + ], + + [ + '/* testDeclareIsKeyword */', + 'T_DECLARE', + ], + [ + '/* testEndDeclareIsKeyword */', + 'T_ENDDECLARE', + ], + + [ + '/* testAndIsKeyword */', + 'T_LOGICAL_AND', + ], + [ + '/* testOrIsKeyword */', + 'T_LOGICAL_OR', + ], + [ + '/* testXorIsKeyword */', + 'T_LOGICAL_XOR', + ], + + [ + '/* testAnonymousClassIsKeyword */', + 'T_ANON_CLASS', + ], + [ + '/* testExtendsInAnonymousClassIsKeyword */', + 'T_EXTENDS', + ], + [ + '/* testImplementsInAnonymousClassIsKeyword */', + 'T_IMPLEMENTS', + ], + [ + '/* testClassInstantiationParentIsKeyword */', + 'T_PARENT', + ], + [ + '/* testClassInstantiationSelfIsKeyword */', + 'T_SELF', + ], + [ + '/* testClassInstantiationStaticIsKeyword */', + 'T_STATIC', + ], + [ + '/* testNamespaceInNameIsKeyword */', + 'T_NAMESPACE', + ], + ]; + + }//end dataKeywords() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DefaultKeywordTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DefaultKeywordTest.inc new file mode 100644 index 00000000..648149d2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DefaultKeywordTest.inc @@ -0,0 +1,203 @@ + 1, + 2 => 2, + /* testSimpleMatchDefault */ + default => 'default', + }; +} + +function switchWithDefault($i) { + switch ($i) { + case 1: + return 1; + case 2: + return 2; + /* testSimpleSwitchDefault */ + default: + return 'default'; + } +} + +function switchWithDefaultAndCurlies($i) { + switch ($i) { + case 1: + return 1; + case 2: + return 2; + /* testSimpleSwitchDefaultWithCurlies */ + default: { + return 'default'; + } + } +} + +function matchWithDefaultInSwitch() { + switch ($something) { + case 'foo': + $var = [1, 2, 3]; + $var = match ($i) { + 1 => 1, + /* testMatchDefaultNestedInSwitchCase1 */ + default => 'default', + }; + continue; + + case 'bar' : + $i = callMe($a, $b); + return match ($i) { + 1 => 1, + /* testMatchDefaultNestedInSwitchCase2 */ + default => 'default', + }; + + /* testSwitchDefault */ + default; + echo 'something', match ($i) { + 1, => 1, + /* testMatchDefaultNestedInSwitchDefault */ + default, => 'default', + }; + break; + } +} + +function switchWithDefaultInMatch() { + $x = match ($y) { + 5, 8 => function($z) { + switch($z) { + case 'a'; + $var = [1, 2, 3]; + return 'a'; + /* testSwitchDefaultNestedInMatchCase */ + default: + $var = [1, 2, 3]; + return 'default1'; + } + }, + /* testMatchDefault */ + default => function($z) { + switch($z) { + case 'a': + $i = callMe($a, $b); + return 'b'; + /* testSwitchDefaultNestedInMatchDefault */ + default: + $i = callMe($a, $b); + return 'default2'; + } + } + }; +} + +function shortArrayWithConstantKey() { + $arr = [ + /* testClassConstantAsShortArrayKey */ + SomeClass::DEFAULT => 1, + /* testClassPropertyAsShortArrayKey */ + SomeClass->DEFAULT => 1, + /* testNamespacedConstantAsShortArrayKey */ + // Intentional parse error PHP < 8.0. Reserved keyword used as namespaced constant. + SomeNamespace\DEFAULT => 1, + /* testFQNGlobalConstantAsShortArrayKey */ + // Intentional parse error in PHP < 8.0. Reserved keyword used as global constant. + \DEFAULT => 1, + ]; +} + +function longArrayWithConstantKey() { + $arr = array( + /* testClassConstantAsLongArrayKey */ + SomeClass::DEFAULT => 1, + ); +} + +function yieldWithConstantKey() { + /* testClassConstantAsYieldKey */ + yield SomeClass::DEFAULT => 1; +} + +function longArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchDefaultWithNestedLongArrayWithClassConstantKey */ + DEFAULT => array( + /* testClassConstantAsLongArrayKeyNestedInMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultWithNestedLongArrayWithClassConstantKeyLevelDown */ + DEFAULT => array( + /* testClassConstantAsLongArrayKeyNestedInMatchLevelDown */ + SomeClass::DEFAULT => 1, + ), + }, + ), + }; +} + +function shortArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchDefaultWithNestedShortArrayWithClassConstantKey */ + DEFAULT => [ + /* testClassConstantAsShortArrayKeyNestedInMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultWithNestedShortArrayWithClassConstantKeyLevelDown */ + DEFAULT => [ + /* testClassConstantAsShortArrayKeyNestedInMatchLevelDown */ + SomeClass::DEFAULT => 1, + ], + }, + ], + }; +} + + +function longArrayWithConstantKeyWithNestedMatch() { + return array( + /* testClassConstantAsLongArrayKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultNestedInLongArray */ + DEFAULT => 'foo' + }, + ); +} + +function shortArrayWithConstantKeyWithNestedMatch() { + return [ + /* testClassConstantAsShortArrayKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultNestedInShortArray */ + DEFAULT => 'foo' + }, + ]; +} + +function switchWithConstantNonDefault($i) { + switch ($i) { + /* testClassConstantInSwitchCase */ + case SomeClass::DEFAULT: + return 1; + + /* testClassPropertyInSwitchCase */ + case SomeClass->DEFAULT: + return 2; + + /* testNamespacedConstantInSwitchCase */ + // Intentional parse error PHP < 8.0. Reserved keyword used as constant. + case SomeNamespace\DEFAULT: + return 2; + + /* testNamespaceRelativeConstantInSwitchCase */ + // Intentional parse error PHP < 8.0. Reserved keyword used as global constant. + case namespace\DEFAULT: + return 2; + } +} + +class Foo { + /* testClassConstant */ + const DEFAULT = 'foo'; + + /* testMethodDeclaration */ + public function default() {} +} diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DefaultKeywordTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DefaultKeywordTest.php new file mode 100644 index 00000000..9a5b061a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DefaultKeywordTest.php @@ -0,0 +1,302 @@ + + * @copyright 2020-2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class DefaultKeywordTest extends AbstractMethodUnitTest +{ + + + /** + * Test the retokenization of the `default` keyword for match structure to `T_MATCH_DEFAULT`. + * + * Note: Cases and default structures within a match structure do *NOT* get case/default scope + * conditions, in contrast to case and default structures in switch control structures. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataMatchDefault + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testMatchDefault($testMarker, $testContent='default') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_MATCH_DEFAULT, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_DEFAULT (code)'); + $this->assertSame('T_MATCH_DEFAULT', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_DEFAULT (type)'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + + }//end testMatchDefault() + + + /** + * Data provider. + * + * @see testMatchDefault() + * + * @return array + */ + public function dataMatchDefault() + { + return [ + 'simple_match_default' => ['/* testSimpleMatchDefault */'], + 'match_default_in_switch_case_1' => ['/* testMatchDefaultNestedInSwitchCase1 */'], + 'match_default_in_switch_case_2' => ['/* testMatchDefaultNestedInSwitchCase2 */'], + 'match_default_in_switch_default' => ['/* testMatchDefaultNestedInSwitchDefault */'], + 'match_default_containing_switch' => ['/* testMatchDefault */'], + + 'match_default_with_nested_long_array_and_default_key' => [ + '/* testMatchDefaultWithNestedLongArrayWithClassConstantKey */', + 'DEFAULT', + ], + 'match_default_with_nested_long_array_and_default_key_2' => [ + '/* testMatchDefaultWithNestedLongArrayWithClassConstantKeyLevelDown */', + 'DEFAULT', + ], + 'match_default_with_nested_short_array_and_default_key' => [ + '/* testMatchDefaultWithNestedShortArrayWithClassConstantKey */', + 'DEFAULT', + ], + 'match_default_with_nested_short_array_and_default_key_2' => [ + '/* testMatchDefaultWithNestedShortArrayWithClassConstantKeyLevelDown */', + 'DEFAULT', + ], + 'match_default_in_long_array' => [ + '/* testMatchDefaultNestedInLongArray */', + 'DEFAULT', + ], + 'match_default_in_short_array' => [ + '/* testMatchDefaultNestedInShortArray */', + 'DEFAULT', + ], + ]; + + }//end dataMatchDefault() + + + /** + * Verify that the retokenization of `T_DEFAULT` tokens in match constructs, doesn't negatively + * impact the tokenization of `T_DEFAULT` tokens in switch control structures. + * + * Note: Cases and default structures within a switch control structure *do* get case/default scope + * conditions. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * @param int|null $conditionStop The expected offset at which tokens stop having T_DEFAULT as a scope condition. + * @param string $testContent The token content to look for. + * + * @dataProvider dataSwitchDefault + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testSwitchDefault($testMarker, $openerOffset, $closerOffset, $conditionStop=null, $testContent='default') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + $expectedScopeOpener = ($token + $openerOffset); + $expectedScopeCloser = ($token + $closerOffset); + + $this->assertSame(T_DEFAULT, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_DEFAULT (code)'); + $this->assertSame('T_DEFAULT', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_DEFAULT (type)'); + + $this->assertArrayHasKey('scope_condition', $tokenArray, 'Scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokenArray, 'Scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokenArray, 'Scope closer is not set'); + $this->assertSame($token, $tokenArray['scope_condition'], 'Scope condition is not the T_DEFAULT token'); + $this->assertSame($expectedScopeOpener, $tokenArray['scope_opener'], 'Scope opener of the T_DEFAULT token incorrect'); + $this->assertSame($expectedScopeCloser, $tokenArray['scope_closer'], 'Scope closer of the T_DEFAULT token incorrect'); + + $opener = $tokenArray['scope_opener']; + $this->assertArrayHasKey('scope_condition', $tokens[$opener], 'Opener scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokens[$opener], 'Opener scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokens[$opener], 'Opener scope closer is not set'); + $this->assertSame($token, $tokens[$opener]['scope_condition'], 'Opener scope condition is not the T_DEFAULT token'); + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'T_DEFAULT opener scope opener token incorrect'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'T_DEFAULT opener scope closer token incorrect'); + + $closer = $tokenArray['scope_closer']; + $this->assertArrayHasKey('scope_condition', $tokens[$closer], 'Closer scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokens[$closer], 'Closer scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokens[$closer], 'Closer scope closer is not set'); + $this->assertSame($token, $tokens[$closer]['scope_condition'], 'Closer scope condition is not the T_DEFAULT token'); + $this->assertSame($expectedScopeOpener, $tokens[$closer]['scope_opener'], 'T_DEFAULT closer scope opener token incorrect'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'T_DEFAULT closer scope closer token incorrect'); + + if (($opener + 1) !== $closer) { + $end = $closer; + if (isset($conditionStop) === true) { + $end = $conditionStop; + } + + for ($i = ($opener + 1); $i < $end; $i++) { + $this->assertArrayHasKey( + $token, + $tokens[$i]['conditions'], + 'T_DEFAULT condition not added for token belonging to the T_DEFAULT structure' + ); + } + } + + }//end testSwitchDefault() + + + /** + * Data provider. + * + * @see testSwitchDefault() + * + * @return array + */ + public function dataSwitchDefault() + { + return [ + 'simple_switch_default' => [ + '/* testSimpleSwitchDefault */', + 1, + 4, + ], + 'simple_switch_default_with_curlies' => [ + // For a default structure with curly braces, the scope opener + // will be the open curly and the closer the close curly. + // However, scope conditions will not be set for open to close, + // but only for the open token up to the "break/return/continue" etc. + '/* testSimpleSwitchDefaultWithCurlies */', + 3, + 12, + 6, + ], + 'switch_default_toplevel' => [ + '/* testSwitchDefault */', + 1, + 43, + ], + 'switch_default_nested_in_match_case' => [ + '/* testSwitchDefaultNestedInMatchCase */', + 1, + 20, + ], + 'switch_default_nested_in_match_default' => [ + '/* testSwitchDefaultNestedInMatchDefault */', + 1, + 18, + ], + ]; + + }//end dataSwitchDefault() + + + /** + * Verify that the retokenization of `T_DEFAULT` tokens in match constructs, doesn't negatively + * impact the tokenization of `T_STRING` tokens with the contents 'default' which aren't in + * actual fact the default keyword. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotDefaultKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNotDefaultKeyword($testMarker, $testContent='DEFAULT') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + + }//end testNotDefaultKeyword() + + + /** + * Data provider. + * + * @see testNotDefaultKeyword() + * + * @return array + */ + public function dataNotDefaultKeyword() + { + return [ + 'class-constant-as-short-array-key' => ['/* testClassConstantAsShortArrayKey */'], + 'class-property-as-short-array-key' => ['/* testClassPropertyAsShortArrayKey */'], + 'namespaced-constant-as-short-array-key' => ['/* testNamespacedConstantAsShortArrayKey */'], + 'fqn-global-constant-as-short-array-key' => ['/* testFQNGlobalConstantAsShortArrayKey */'], + 'class-constant-as-long-array-key' => ['/* testClassConstantAsLongArrayKey */'], + 'class-constant-as-yield-key' => ['/* testClassConstantAsYieldKey */'], + + 'class-constant-as-long-array-key-nested-in-match' => ['/* testClassConstantAsLongArrayKeyNestedInMatch */'], + 'class-constant-as-long-array-key-nested-in-match-2' => ['/* testClassConstantAsLongArrayKeyNestedInMatchLevelDown */'], + 'class-constant-as-short-array-key-nested-in-match' => ['/* testClassConstantAsShortArrayKeyNestedInMatch */'], + 'class-constant-as-short-array-key-nested-in-match-2' => ['/* testClassConstantAsShortArrayKeyNestedInMatchLevelDown */'], + 'class-constant-as-long-array-key-with-nested-match' => ['/* testClassConstantAsLongArrayKeyWithNestedMatch */'], + 'class-constant-as-short-array-key-with-nested-match' => ['/* testClassConstantAsShortArrayKeyWithNestedMatch */'], + + 'class-constant-in-switch-case' => ['/* testClassConstantInSwitchCase */'], + 'class-property-in-switch-case' => ['/* testClassPropertyInSwitchCase */'], + 'namespaced-constant-in-switch-case' => ['/* testNamespacedConstantInSwitchCase */'], + 'namespace-relative-constant-in-switch-case' => ['/* testNamespaceRelativeConstantInSwitchCase */'], + + 'class-constant-declaration' => ['/* testClassConstant */'], + 'class-method-declaration' => [ + '/* testMethodDeclaration */', + 'default', + ], + ]; + + }//end dataNotDefaultKeyword() + + + /** + * Test a specific edge case where a scope opener would be incorrectly set. + * + * @link https://github.com/squizlabs/PHP_CodeSniffer/issues/3326 + * + * @return void + */ + public function testIssue3326() + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testClassConstant */', [T_SEMICOLON]); + $tokenArray = $tokens[$token]; + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + + }//end testIssue3326() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleArrowTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleArrowTest.inc new file mode 100644 index 00000000..b67b0660 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleArrowTest.inc @@ -0,0 +1,281 @@ + 'Zero', + ); +} + +function simpleShortArray($x) { + return [ + /* testShortArrayArrowSimple */ + 0 => 'Zero', + ]; +} + +function simpleLongList($x) { + list( + /* testLongListArrowSimple */ + 0 => $a, + ) = $x; +} + +function simpleShortList($x) { + [ + /* testShortListArrowSimple */ + 0 => $a, + ] = $x; +} + +function simpleYield($x) { + $i = 0; + foreach (explode("\n", $x) as $line) { + /* testYieldArrowSimple */ + yield ++$i => $line; + } +} + +function simpleForeach($x) { + /* testForeachArrowSimple */ + foreach ($x as $k => $value) {} +} + +function simpleMatch($x) { + return match ($x) { + /* testMatchArrowSimpleSingleCase */ + 0 => 'Zero', + /* testMatchArrowSimpleMultiCase */ + 2, 4, 6 => 'Zero', + /* testMatchArrowSimpleSingleCaseWithTrailingComma */ + 1, => 'Zero', + /* testMatchArrowSimpleMultiCaseWithTrailingComma */ + 3, 5, => 'Zero', + }; +} + +function simpleArrowFunction($y) { + /* testFnArrowSimple */ + return fn ($y) => callMe($y); +} + +function matchNestedInMatch() { + $x = match ($y) { + /* testMatchArrowNestedMatchOuter */ + default, => match ($z) { + /* testMatchArrowNestedMatchInner */ + 1 => 1 + }, + }; +} + +function matchNestedInLongArrayValue() { + $array = array( + /* testLongArrayArrowWithNestedMatchValue1 */ + 'a' => match ($test) { + /* testMatchArrowInLongArrayValue1 */ + 1 => 'a', + /* testMatchArrowInLongArrayValue2 */ + 2 => 'b' + }, + /* testLongArrayArrowWithNestedMatchValue2 */ + $i => match ($test) { + /* testMatchArrowInLongArrayValue3 */ + 1 => 'a', + }, + ); +} + +function matchNestedInShortArrayValue() { + $array = [ + /* testShortArrayArrowWithNestedMatchValue1 */ + 'a' => match ($test) { + /* testMatchArrowInShortArrayValue1 */ + 1 => 'a', + /* testMatchArrowInShortArrayValue2 */ + 2 => 'b' + }, + /* testShortArrayArrowWithNestedMatchValue2 */ + $i => match ($test) { + /* testMatchArrowInShortArrayValue3 */ + 1 => 'a', + }, + ]; +} + +function matchNestedInLongArrayKey() { + $array = array( + match ($test) { /* testMatchArrowInLongArrayKey1 */ 1 => 'a', /* testMatchArrowInLongArrayKey2 */ 2 => 'b' } + /* testLongArrayArrowWithMatchKey */ + => 'dynamic keys, woho!', + ); +} + +function matchNestedInShortArrayKey() { + $array = [ + match ($test) { /* testMatchArrowInShortArrayKey1 */ 1 => 'a', /* testMatchArrowInShortArrayKey2 */ 2 => 'b' } + /* testShortArrayArrowWithMatchKey */ + => 'dynamic keys, woho!', + ]; +} + +function arraysNestedInMatch() { + $matcher = match ($x) { + /* testMatchArrowWithLongArrayBodyWithKeys */ + 0 => array( + /* testLongArrayArrowInMatchBody1 */ + 0 => 1, + /* testLongArrayArrowInMatchBody2 */ + 'a' => 2, + /* testLongArrayArrowInMatchBody3 */ + 'b' => 3 + ), + /* testMatchArrowWithShortArrayBodyWithoutKeys */ + 1 => [1, 2, 3], + /* testMatchArrowWithLongArrayBodyWithoutKeys */ + 2 => array( 1, [1, 2, 3], 2, 3), + /* testMatchArrowWithShortArrayBodyWithKeys */ + 3 => [ + /* testShortArrayArrowInMatchBody1 */ + 0 => 1, + /* testShortArrayArrowInMatchBody2 */ + 'a' => array(1, 2, 3), + /* testShortArrayArrowInMatchBody3 */ + 'b' => 2, + 3 + ], + /* testShortArrayArrowinMatchCase1 */ + [4 => 'a', /* testShortArrayArrowinMatchCase2 */ 5 => 6] + /* testMatchArrowWithShortArrayWithKeysAsCase */ + => 'match with array as case value', + /* testShortArrayArrowinMatchCase3 */ + [4 => 'a'], /* testLongArrayArrowinMatchCase4 */ array(5 => 6), + /* testMatchArrowWithMultipleArraysWithKeysAsCase */ + => 'match with multiple arrays as case value', + }; +} + +function matchNestedInArrowFunction($x) { + /* testFnArrowWithMatchInValue */ + $fn = fn($x) => match(true) { + /* testMatchArrowInFnBody1 */ + 1, 2, 3, 4, 5 => 'foo', + /* testMatchArrowInFnBody2 */ + default => 'bar', + }; +} + +function arrowFunctionsNestedInMatch($x) { + return match ($x) { + /* testMatchArrowWithFnBody1 */ + 1 => /* testFnArrowInMatchBody1 */ fn($y) => callMe($y), + /* testMatchArrowWithFnBody2 */ + default => /* testFnArrowInMatchBody2 */ fn($y) => callThem($y) + }; +} + +function matchShortArrayMismash() { + $array = [ + match ($test) { + /* testMatchArrowInComplexShortArrayKey1 */ + 1 => [ /* testShortArrayArrowInComplexMatchValueinShortArrayKey */ 1 => 'a'], + /* testMatchArrowInComplexShortArrayKey2 */ + 2 => 'b' + /* testShortArrayArrowInComplexMatchArrayMismash */ + } => match ($test) { + /* testMatchArrowInComplexShortArrayValue1 */ + 1 => [ /* testShortArrayArrowInComplexMatchValueinShortArrayValue */ 1 => 'a'], + /* testMatchArrowInComplexShortArrayValue2 */ + 2 => /* testFnArrowInComplexMatchValueInShortArrayValue */ fn($y) => callMe($y) + }, + ]; +} + + +function longListInMatch($x, $y) { + return match($x) { + /* testMatchArrowWithLongListBody */ + 1 => list('a' => $a, /* testLongListArrowInMatchBody */ 'b' => $b, 'c' => list('d' => $c)) = $y, + /* testLongListArrowInMatchCase */ + list('a' => $a, 'b' => $b) = $y /* testMatchArrowWithLongListInCase */ => 'something' + }; +} + +function shortListInMatch($x, $y) { + return match($x) { + /* testMatchArrowWithShortListBody */ + 1 => ['a' => $a, 'b' => $b, 'c' => /* testShortListArrowInMatchBody */ ['d' => $c]] = $y, + /* testShortListArrowInMatchCase */ + ['a' => $a, 'b' => $b] = $y /* testMatchArrowWithShortListInCase */ => 'something' + }; +} + +function matchInLongList() { + /* testMatchArrowInLongListKey */ + list(match($x) {1 => 1, 2 => 2} /* testLongListArrowWithMatchInKey */ => $a) = $array; +} + +function matchInShortList() { + /* testMatchArrowInShortListKey */ + [match($x) {1 => 1, 2 => 2} /* testShortListArrowWithMatchInKey */ => $a] = $array; +} + +function longArrayWithConstantKey() { + $arr = array( + /* testLongArrayArrowWithClassConstantKey */ + SomeClass::DEFAULT => 1, + ); +} + +function shortArrayWithConstantKey() { + $arr = [ + /* testShortArrayArrowWithClassConstantKey */ + SomeClass::DEFAULT => 1, + ]; +} + +function yieldWithConstantKey() { + /* testYieldArrowWithClassConstantKey */ + yield SomeClass::DEFAULT => 1; +} + +function longArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchArrowWithNestedLongArrayWithClassConstantKey */ + default => array( + /* testLongArrayArrowWithClassConstantKeyNestedInMatch */ + SomeClass::DEFAULT => 1, + ), + }; +} + +function shortArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchArrowWithNestedShortArrayWithClassConstantKey */ + default => [ + /* testShortArrayArrowWithClassConstantKeyNestedInMatch */ + SomeClass::DEFAULT => 1, + ], + }; +} + + +function longArrayWithConstantKeyWithNestedMatch() { + return array( + /* testLongArrayArrowWithClassConstantKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchArrowNestedInLongArrayWithClassConstantKey */ + default => 'foo' + }, + ); +} + +function shortArrayWithConstantKeyWithNestedMatch() { + return [ + /* testShortArrayArrowWithClassConstantKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchArrowNestedInShortArrayWithClassConstantKey */ + default => 'foo' + }, + ]; +} diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleArrowTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleArrowTest.php new file mode 100644 index 00000000..ad1a411f --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleArrowTest.php @@ -0,0 +1,237 @@ + + * @copyright 2020-2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class DoubleArrowTest extends AbstractMethodUnitTest +{ + + + /** + * Test that "normal" double arrows are correctly tokenized as `T_DOUBLE_ARROW`. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataDoubleArrow + * @coversNothing + * + * @return void + */ + public function testDoubleArrow($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_DOUBLE_ARROW, T_MATCH_ARROW, T_FN_ARROW]); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_DOUBLE_ARROW, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_DOUBLE_ARROW (code)'); + $this->assertSame('T_DOUBLE_ARROW', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_DOUBLE_ARROW (type)'); + + }//end testDoubleArrow() + + + /** + * Data provider. + * + * @see testDoubleArrow() + * + * @return array + */ + public function dataDoubleArrow() + { + return [ + 'simple_long_array' => ['/* testLongArrayArrowSimple */'], + 'simple_short_array' => ['/* testShortArrayArrowSimple */'], + 'simple_long_list' => ['/* testLongListArrowSimple */'], + 'simple_short_list' => ['/* testShortListArrowSimple */'], + 'simple_yield' => ['/* testYieldArrowSimple */'], + 'simple_foreach' => ['/* testForeachArrowSimple */'], + + 'long_array_with_match_value_1' => ['/* testLongArrayArrowWithNestedMatchValue1 */'], + 'long_array_with_match_value_2' => ['/* testLongArrayArrowWithNestedMatchValue2 */'], + 'short_array_with_match_value_1' => ['/* testShortArrayArrowWithNestedMatchValue1 */'], + 'short_array_with_match_value_2' => ['/* testShortArrayArrowWithNestedMatchValue2 */'], + + 'long_array_with_match_key' => ['/* testLongArrayArrowWithMatchKey */'], + 'short_array_with_match_key' => ['/* testShortArrayArrowWithMatchKey */'], + + 'long_array_in_match_body_1' => ['/* testLongArrayArrowInMatchBody1 */'], + 'long_array_in_match_body_2' => ['/* testLongArrayArrowInMatchBody2 */'], + 'long_array_in_match_body_3' => ['/* testLongArrayArrowInMatchBody3 */'], + 'short_array_in_match_body_1' => ['/* testShortArrayArrowInMatchBody1 */'], + 'short_array_in_match_body_2' => ['/* testShortArrayArrowInMatchBody2 */'], + 'short_array_in_match_body_3' => ['/* testShortArrayArrowInMatchBody3 */'], + + 'short_array_in_match_case_1' => ['/* testShortArrayArrowinMatchCase1 */'], + 'short_array_in_match_case_2' => ['/* testShortArrayArrowinMatchCase2 */'], + 'short_array_in_match_case_3' => ['/* testShortArrayArrowinMatchCase3 */'], + 'long_array_in_match_case_4' => ['/* testLongArrayArrowinMatchCase4 */'], + + 'in_complex_short_array_key_match_value' => ['/* testShortArrayArrowInComplexMatchValueinShortArrayKey */'], + 'in_complex_short_array_toplevel' => ['/* testShortArrayArrowInComplexMatchArrayMismash */'], + 'in_complex_short_array_value_match_value' => ['/* testShortArrayArrowInComplexMatchValueinShortArrayValue */'], + + 'long_list_in_match_body' => ['/* testLongListArrowInMatchBody */'], + 'long_list_in_match_case' => ['/* testLongListArrowInMatchCase */'], + 'short_list_in_match_body' => ['/* testShortListArrowInMatchBody */'], + 'short_list_in_match_case' => ['/* testShortListArrowInMatchCase */'], + 'long_list_with_match_in_key' => ['/* testLongListArrowWithMatchInKey */'], + 'short_list_with_match_in_key' => ['/* testShortListArrowWithMatchInKey */'], + + 'long_array_with_constant_default_in_key' => ['/* testLongArrayArrowWithClassConstantKey */'], + 'short_array_with_constant_default_in_key' => ['/* testShortArrayArrowWithClassConstantKey */'], + 'yield_with_constant_default_in_key' => ['/* testYieldArrowWithClassConstantKey */'], + + 'long_array_with_default_in_key_in_match' => ['/* testLongArrayArrowWithClassConstantKeyNestedInMatch */'], + 'short_array_with_default_in_key_in_match' => ['/* testShortArrayArrowWithClassConstantKeyNestedInMatch */'], + 'long_array_with_default_in_key_with_match' => ['/* testLongArrayArrowWithClassConstantKeyWithNestedMatch */'], + 'short_array_with_default_in_key_with_match' => ['/* testShortArrayArrowWithClassConstantKeyWithNestedMatch */'], + ]; + + }//end dataDoubleArrow() + + + /** + * Test that double arrows in match expressions which are the demarkation between a case and the return value + * are correctly tokenized as `T_MATCH_ARROW`. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataMatchArrow + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testMatchArrow($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_DOUBLE_ARROW, T_MATCH_ARROW, T_FN_ARROW]); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_MATCH_ARROW, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_ARROW (code)'); + $this->assertSame('T_MATCH_ARROW', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_ARROW (type)'); + + }//end testMatchArrow() + + + /** + * Data provider. + * + * @see testMatchArrow() + * + * @return array + */ + public function dataMatchArrow() + { + return [ + 'single_case' => ['/* testMatchArrowSimpleSingleCase */'], + 'multi_case' => ['/* testMatchArrowSimpleMultiCase */'], + 'single_case_with_trailing_comma' => ['/* testMatchArrowSimpleSingleCaseWithTrailingComma */'], + 'multi_case_with_trailing_comma' => ['/* testMatchArrowSimpleMultiCaseWithTrailingComma */'], + 'match_nested_outer' => ['/* testMatchArrowNestedMatchOuter */'], + 'match_nested_inner' => ['/* testMatchArrowNestedMatchInner */'], + + 'in_long_array_value_1' => ['/* testMatchArrowInLongArrayValue1 */'], + 'in_long_array_value_2' => ['/* testMatchArrowInLongArrayValue2 */'], + 'in_long_array_value_3' => ['/* testMatchArrowInLongArrayValue3 */'], + 'in_short_array_value_1' => ['/* testMatchArrowInShortArrayValue1 */'], + 'in_short_array_value_2' => ['/* testMatchArrowInShortArrayValue2 */'], + 'in_short_array_value_3' => ['/* testMatchArrowInShortArrayValue3 */'], + + 'in_long_array_key_1' => ['/* testMatchArrowInLongArrayKey1 */'], + 'in_long_array_key_2' => ['/* testMatchArrowInLongArrayKey2 */'], + 'in_short_array_key_1' => ['/* testMatchArrowInShortArrayKey1 */'], + 'in_short_array_key_2' => ['/* testMatchArrowInShortArrayKey2 */'], + + 'with_long_array_value_with_keys' => ['/* testMatchArrowWithLongArrayBodyWithKeys */'], + 'with_short_array_value_without_keys' => ['/* testMatchArrowWithShortArrayBodyWithoutKeys */'], + 'with_long_array_value_without_keys' => ['/* testMatchArrowWithLongArrayBodyWithoutKeys */'], + 'with_short_array_value_with_keys' => ['/* testMatchArrowWithShortArrayBodyWithKeys */'], + + 'with_short_array_with_keys_as_case' => ['/* testMatchArrowWithShortArrayWithKeysAsCase */'], + 'with_multiple_arrays_with_keys_as_case' => ['/* testMatchArrowWithMultipleArraysWithKeysAsCase */'], + + 'in_fn_body_case' => ['/* testMatchArrowInFnBody1 */'], + 'in_fn_body_default' => ['/* testMatchArrowInFnBody2 */'], + 'with_fn_body_case' => ['/* testMatchArrowWithFnBody1 */'], + 'with_fn_body_default' => ['/* testMatchArrowWithFnBody2 */'], + + 'in_complex_short_array_key_1' => ['/* testMatchArrowInComplexShortArrayKey1 */'], + 'in_complex_short_array_key_2' => ['/* testMatchArrowInComplexShortArrayKey2 */'], + 'in_complex_short_array_value_1' => ['/* testMatchArrowInComplexShortArrayValue1 */'], + 'in_complex_short_array_value_2' => ['/* testMatchArrowInComplexShortArrayValue2 */'], + + 'with_long_list_in_body' => ['/* testMatchArrowWithLongListBody */'], + 'with_long_list_in_case' => ['/* testMatchArrowWithLongListInCase */'], + 'with_short_list_in_body' => ['/* testMatchArrowWithShortListBody */'], + 'with_short_list_in_case' => ['/* testMatchArrowWithShortListInCase */'], + 'in_long_list_key' => ['/* testMatchArrowInLongListKey */'], + 'in_short_list_key' => ['/* testMatchArrowInShortListKey */'], + + 'with_long_array_value_with_default_key' => ['/* testMatchArrowWithNestedLongArrayWithClassConstantKey */'], + 'with_short_array_value_with_default_key' => ['/* testMatchArrowWithNestedShortArrayWithClassConstantKey */'], + 'in_long_array_value_with_default_key' => ['/* testMatchArrowNestedInLongArrayWithClassConstantKey */'], + 'in_short_array_value_with_default_key' => ['/* testMatchArrowNestedInShortArrayWithClassConstantKey */'], + ]; + + }//end dataMatchArrow() + + + /** + * Test that double arrows used as the scope opener for an arrow function + * are correctly tokenized as `T_FN_ARROW`. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataFnArrow + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testFnArrow($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_DOUBLE_ARROW, T_MATCH_ARROW, T_FN_ARROW]); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_FN_ARROW, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_FN_ARROW (code)'); + $this->assertSame('T_FN_ARROW', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_FN_ARROW (type)'); + + }//end testFnArrow() + + + /** + * Data provider. + * + * @see testFnArrow() + * + * @return array + */ + public function dataFnArrow() + { + return [ + 'simple_fn' => ['/* testFnArrowSimple */'], + + 'with_match_as_value' => ['/* testFnArrowWithMatchInValue */'], + 'in_match_value_case' => ['/* testFnArrowInMatchBody1 */'], + 'in_match_value_default' => ['/* testFnArrowInMatchBody2 */'], + + 'in_complex_match_value_in_short_array' => ['/* testFnArrowInComplexMatchValueInShortArrayValue */'], + ]; + + }//end dataFnArrow() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleQuotedStringTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleQuotedStringTest.inc new file mode 100644 index 00000000..62535b1e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleQuotedStringTest.inc @@ -0,0 +1,52 @@ +bar"; +/* testProperty2 */ +"{$foo->bar}"; + +/* testMethod1 */ +"{$foo->bar()}"; + +/* testClosure1 */ +"{$foo()}"; + +/* testChain1 */ +"{$foo['bar']->baz()()}"; + +/* testVariableVar1 */ +"${$bar}"; +/* testVariableVar2 */ +"${(foo)}"; +/* testVariableVar3 */ +"${foo->bar}"; + +/* testNested1 */ +"${foo["${bar}"]}"; +/* testNested2 */ +"${foo["${bar['baz']}"]}"; +/* testNested3 */ +"${foo->{$baz}}"; +/* testNested4 */ +"${foo->{${'a'}}}"; +/* testNested5 */ +"${foo->{"${'a'}"}}"; + +/* testParseError */ +"${foo["${bar diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleQuotedStringTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleQuotedStringTest.php new file mode 100644 index 00000000..cc9fe49e --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleQuotedStringTest.php @@ -0,0 +1,136 @@ + + * @copyright 2022 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class DoubleQuotedStringTest extends AbstractMethodUnitTest +{ + + + /** + * Test that double quoted strings contain the complete string. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $expectedContent The expected content of the double quoted string. + * + * @dataProvider dataDoubleQuotedString + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testDoubleQuotedString($testMarker, $expectedContent) + { + $tokens = self::$phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, T_DOUBLE_QUOTED_STRING); + $this->assertSame($expectedContent, $tokens[$target]['content']); + + }//end testDoubleQuotedString() + + + /** + * Data provider. + * + * @see testDoubleQuotedString() + * + * @return array + */ + public function dataDoubleQuotedString() + { + return [ + [ + 'testMarker' => '/* testSimple1 */', + 'expectedContent' => '"$foo"', + ], + [ + 'testMarker' => '/* testSimple2 */', + 'expectedContent' => '"{$foo}"', + ], + [ + 'testMarker' => '/* testSimple3 */', + 'expectedContent' => '"${foo}"', + ], + [ + 'testMarker' => '/* testDIM1 */', + 'expectedContent' => '"$foo[bar]"', + ], + [ + 'testMarker' => '/* testDIM2 */', + 'expectedContent' => '"{$foo[\'bar\']}"', + ], + [ + 'testMarker' => '/* testDIM3 */', + 'expectedContent' => '"${foo[\'bar\']}"', + ], + [ + 'testMarker' => '/* testProperty1 */', + 'expectedContent' => '"$foo->bar"', + ], + [ + 'testMarker' => '/* testProperty2 */', + 'expectedContent' => '"{$foo->bar}"', + ], + [ + 'testMarker' => '/* testMethod1 */', + 'expectedContent' => '"{$foo->bar()}"', + ], + [ + 'testMarker' => '/* testClosure1 */', + 'expectedContent' => '"{$foo()}"', + ], + [ + 'testMarker' => '/* testChain1 */', + 'expectedContent' => '"{$foo[\'bar\']->baz()()}"', + ], + [ + 'testMarker' => '/* testVariableVar1 */', + 'expectedContent' => '"${$bar}"', + ], + [ + 'testMarker' => '/* testVariableVar2 */', + 'expectedContent' => '"${(foo)}"', + ], + [ + 'testMarker' => '/* testVariableVar3 */', + 'expectedContent' => '"${foo->bar}"', + ], + [ + 'testMarker' => '/* testNested1 */', + 'expectedContent' => '"${foo["${bar}"]}"', + ], + [ + 'testMarker' => '/* testNested2 */', + 'expectedContent' => '"${foo["${bar[\'baz\']}"]}"', + ], + [ + 'testMarker' => '/* testNested3 */', + 'expectedContent' => '"${foo->{$baz}}"', + ], + [ + 'testMarker' => '/* testNested4 */', + 'expectedContent' => '"${foo->{${\'a\'}}}"', + ], + [ + 'testMarker' => '/* testNested5 */', + 'expectedContent' => '"${foo->{"${\'a\'}"}}"', + ], + [ + 'testMarker' => '/* testParseError */', + 'expectedContent' => '"${foo["${bar +', + ], + ]; + + }//end dataDoubleQuotedString() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/EnumCaseTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/EnumCaseTest.inc new file mode 100644 index 00000000..13b87242 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/EnumCaseTest.inc @@ -0,0 +1,95 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class EnumCaseTest extends AbstractMethodUnitTest +{ + + + /** + * Test that the enum "case" is converted to T_ENUM_CASE. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataEnumCases + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testEnumCases($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $enumCase = $this->getTargetToken($testMarker, [T_ENUM_CASE, T_CASE]); + + $this->assertSame(T_ENUM_CASE, $tokens[$enumCase]['code']); + $this->assertSame('T_ENUM_CASE', $tokens[$enumCase]['type']); + + $this->assertArrayNotHasKey('scope_condition', $tokens[$enumCase], 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokens[$enumCase], 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokens[$enumCase], 'Scope closer is set'); + + }//end testEnumCases() + + + /** + * Data provider. + * + * @see testEnumCases() + * + * @return array + */ + public function dataEnumCases() + { + return [ + ['/* testPureEnumCase */'], + ['/* testBackingIntegerEnumCase */'], + ['/* testBackingStringEnumCase */'], + ['/* testEnumCaseInComplexEnum */'], + ['/* testEnumCaseIsCaseInsensitive */'], + ['/* testEnumCaseAfterSwitch */'], + ['/* testEnumCaseAfterSwitchWithEndSwitch */'], + ]; + + }//end dataEnumCases() + + + /** + * Test that "case" that is not enum case is still tokenized as `T_CASE`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataNotEnumCases + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testNotEnumCases($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $case = $this->getTargetToken($testMarker, [T_ENUM_CASE, T_CASE]); + + $this->assertSame(T_CASE, $tokens[$case]['code']); + $this->assertSame('T_CASE', $tokens[$case]['type']); + + $this->assertArrayHasKey('scope_condition', $tokens[$case], 'Scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokens[$case], 'Scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokens[$case], 'Scope closer is not set'); + + }//end testNotEnumCases() + + + /** + * Data provider. + * + * @see testNotEnumCases() + * + * @return array + */ + public function dataNotEnumCases() + { + return [ + ['/* testCaseWithSemicolonIsNotEnumCase */'], + ['/* testCaseWithConstantIsNotEnumCase */'], + ['/* testCaseWithConstantAndIdenticalIsNotEnumCase */'], + ['/* testCaseWithAssigmentToConstantIsNotEnumCase */'], + ['/* testIsNotEnumCaseIsCaseInsensitive */'], + ['/* testCaseInSwitchWhenCreatingEnumInSwitch1 */'], + ['/* testCaseInSwitchWhenCreatingEnumInSwitch2 */'], + ]; + + }//end dataNotEnumCases() + + + /** + * Test that "case" that is not enum case is still tokenized as `T_CASE`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataKeywordAsEnumCaseNameShouldBeString + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testKeywordAsEnumCaseNameShouldBeString($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $enumCaseName = $this->getTargetToken($testMarker, [T_STRING, T_INTERFACE, T_TRAIT, T_ENUM, T_FUNCTION, T_FALSE, T_DEFAULT, T_ARRAY]); + + $this->assertSame(T_STRING, $tokens[$enumCaseName]['code']); + $this->assertSame('T_STRING', $tokens[$enumCaseName]['type']); + + }//end testKeywordAsEnumCaseNameShouldBeString() + + + /** + * Data provider. + * + * @see testKeywordAsEnumCaseNameShouldBeString() + * + * @return array + */ + public function dataKeywordAsEnumCaseNameShouldBeString() + { + return [ + ['/* testKeywordAsEnumCaseNameShouldBeString1 */'], + ['/* testKeywordAsEnumCaseNameShouldBeString2 */'], + ['/* testKeywordAsEnumCaseNameShouldBeString3 */'], + ['/* testKeywordAsEnumCaseNameShouldBeString4 */'], + ]; + + }//end dataKeywordAsEnumCaseNameShouldBeString() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/FinallyTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/FinallyTest.inc new file mode 100644 index 00000000..e65600b6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/FinallyTest.inc @@ -0,0 +1,40 @@ +finally = 'foo'; + } +} diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/FinallyTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/FinallyTest.php new file mode 100644 index 00000000..2b28bc5d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/FinallyTest.php @@ -0,0 +1,96 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class FinallyTest extends AbstractMethodUnitTest +{ + + + /** + * Test that the finally keyword is tokenized as such. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataFinallyKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testFinallyKeyword($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, [T_FINALLY, T_STRING]); + $this->assertSame(T_FINALLY, $tokens[$target]['code']); + $this->assertSame('T_FINALLY', $tokens[$target]['type']); + + }//end testFinallyKeyword() + + + /** + * Data provider. + * + * @see testFinallyKeyword() + * + * @return array + */ + public function dataFinallyKeyword() + { + return [ + ['/* testTryCatchFinally */'], + ['/* testTryFinallyCatch */'], + ['/* testTryFinally */'], + ]; + + }//end dataFinallyKeyword() + + + /** + * Test that 'finally' when not used as the reserved keyword is tokenized as `T_STRING`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataFinallyNonKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testFinallyNonKeyword($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, [T_FINALLY, T_STRING]); + $this->assertSame(T_STRING, $tokens[$target]['code']); + $this->assertSame('T_STRING', $tokens[$target]['type']); + + }//end testFinallyNonKeyword() + + + /** + * Data provider. + * + * @see testFinallyNonKeyword() + * + * @return array + */ + public function dataFinallyNonKeyword() + { + return [ + ['/* testFinallyUsedAsClassConstantName */'], + ['/* testFinallyUsedAsMethodName */'], + ['/* testFinallyUsedAsPropertyName */'], + ]; + + }//end dataFinallyNonKeyword() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/GotoLabelTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/GotoLabelTest.inc new file mode 100644 index 00000000..12df5d29 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/GotoLabelTest.inc @@ -0,0 +1,56 @@ + +
    + +property: + // Do something. + break; +} + +switch (true) { + /* testNotGotoDeclarationGlobalConstantInTernary */ + case $x === ($cond) ? CONST_A : CONST_B: + // Do something. + break; +} + +/* testNotGotoDeclarationEnumWithType */ +enum Suit: string implements Colorful, CardGame {} diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/GotoLabelTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/GotoLabelTest.php new file mode 100644 index 00000000..0f937cc8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/GotoLabelTest.php @@ -0,0 +1,175 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class GotoLabelTest extends AbstractMethodUnitTest +{ + + + /** + * Verify that the label in a goto statement is tokenized as T_STRING. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to expect. + * + * @dataProvider dataGotoStatement + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testGotoStatement($testMarker, $testContent) + { + $tokens = self::$phpcsFile->getTokens(); + + $label = $this->getTargetToken($testMarker, T_STRING); + + $this->assertInternalType('int', $label); + $this->assertSame($testContent, $tokens[$label]['content']); + + }//end testGotoStatement() + + + /** + * Data provider. + * + * @see testGotoStatement() + * + * @return array + */ + public function dataGotoStatement() + { + return [ + [ + '/* testGotoStatement */', + 'marker', + ], + [ + '/* testGotoStatementInLoop */', + 'end', + ], + ]; + + }//end dataGotoStatement() + + + /** + * Verify that the label in a goto declaration is tokenized as T_GOTO_LABEL. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to expect. + * + * @dataProvider dataGotoDeclaration + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testGotoDeclaration($testMarker, $testContent) + { + $tokens = self::$phpcsFile->getTokens(); + + $label = $this->getTargetToken($testMarker, T_GOTO_LABEL); + + $this->assertInternalType('int', $label); + $this->assertSame($testContent, $tokens[$label]['content']); + + }//end testGotoDeclaration() + + + /** + * Data provider. + * + * @see testGotoDeclaration() + * + * @return array + */ + public function dataGotoDeclaration() + { + return [ + [ + '/* testGotoDeclaration */', + 'marker:', + ], + [ + '/* testGotoDeclarationOutsideLoop */', + 'end:', + ], + ]; + + }//end dataGotoDeclaration() + + + /** + * Verify that the constant used in a switch - case statement is not confused with a goto label. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to expect. + * + * @dataProvider dataNotAGotoDeclaration + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNotAGotoDeclaration($testMarker, $testContent) + { + $tokens = self::$phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_GOTO_LABEL, T_STRING], $testContent); + + $this->assertSame(T_STRING, $tokens[$target]['code']); + $this->assertSame('T_STRING', $tokens[$target]['type']); + + }//end testNotAGotoDeclaration() + + + /** + * Data provider. + * + * @see testNotAGotoDeclaration() + * + * @return array + */ + public function dataNotAGotoDeclaration() + { + return [ + [ + '/* testNotGotoDeclarationGlobalConstant */', + 'CONSTANT', + ], + [ + '/* testNotGotoDeclarationNamespacedConstant */', + 'CONSTANT', + ], + [ + '/* testNotGotoDeclarationClassConstant */', + 'CONSTANT', + ], + [ + '/* testNotGotoDeclarationClassProperty */', + 'property', + ], + [ + '/* testNotGotoDeclarationGlobalConstantInTernary */', + 'CONST_A', + ], + [ + '/* testNotGotoDeclarationGlobalConstantInTernary */', + 'CONST_B', + ], + [ + '/* testNotGotoDeclarationEnumWithType */', + 'Suit', + ], + ]; + + }//end dataNotAGotoDeclaration() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.inc new file mode 100644 index 00000000..4497f5c3 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.inc @@ -0,0 +1,404 @@ +getPos(skip: false), + count: count(array_or_countable: $array), + value: 50 +); + +array_fill( + start_index: /* testNestedFunctionCallInner1 */ $obj->getPos(skip: false), + count: /* testNestedFunctionCallInner2 */ count(array_or_countable: $array), + value: 50 +); + +/* testNamespaceOperatorFunction */ +namespace\function_name(label:$string, more: false); + +/* testNamespaceRelativeFunction */ +Partially\Qualified\function_name(label:$string, more: false); + +/* testNamespacedFQNFunction */ +\Fully\Qualified\function_name(label: $string, more:false); + +/* testVariableFunction */ +$fn(label: $string, more:false); + +/* testVariableVariableFunction */ +${$fn}(label: $string, more:false); + +/* testMethodCall */ +$obj->methodName(label: $foo, more: $bar); + +/* testVariableMethodCall */ +$obj->{$var}(label: $foo, more: $bar); + +/* testClassInstantiation */ +$obj = new MyClass(label: $string, more:false); + +/* testClassInstantiationSelf */ +$obj = new self(label: $string, more:true); + +/* testClassInstantiationStatic */ +$obj = new static(label: $string, more:false); + +/* testAnonClass */ +$anon = new class(label: $string, more: false) { + public function __construct($label, $more) {} +}; + +function myfoo( $💩💩💩, $Пасха, $_valid) {} +/* testNonAsciiNames */ +foo(💩💩💩: [], Пасха: 'text', _valid: 123); + +/* testMixedPositionalAndNamedArgsWithTernary */ +foo( $cond ? true : false, name: $value2 ); + +/* testNamedArgWithTernary */ +foo( label: $cond ? true : false, more: $cond ? CONSTANT_A : CONSTANT_B ); + +/* testTernaryWithFunctionCallsInThenElse */ +echo $cond ? foo( label: $something ) : foo( more: $something_else ); + +/* testTernaryWithConstantsInThenElse */ +echo $cond ? CONSTANT_NAME : OTHER_CONSTANT; + +switch ($s) { + /* testSwitchCaseWithConstant */ + case MY_CONSTANT: + // Do something. + break; + + /* testSwitchCaseWithClassProperty */ + case $obj->property: + // Do something. + break; + + /* testSwitchDefault */ + default: + // Do something. + break; +} + +/* testTernaryWithClosuresAndReturnTypes */ +$closure = $cond ? function() : bool {return true;} : function() : int {return 123;}; + +/* testTernaryWithArrowFunctionsAndReturnTypes */ +$fn = $cond ? fn() : bool => true : fn() : int => 123; + + +/* testCompileErrorNamedBeforePositional */ +// Not the concern of PHPCS. Should still be handled. +test(param: $bar, $foo); + +/* testDuplicateName1 */ +// Error Exception, but not the concern of PHPCS. Should still be handled. +test(param: 1, /* testDuplicateName2 */ param: 2); + +/* testIncorrectOrderWithVariadic */ +// Error Exception, but not the concern of PHPCS. Should still be handled. +array_fill(start_index: 0, ...[100, 50]); + +/* testCompileErrorIncorrectOrderWithVariadic */ +// Not the concern of PHPCS. Should still be handled. +test(...$values, param: $value); // Compile-time error + +/* testParseErrorNoValue */ +// Not the concern of PHPCS. Should still be handled. +test(param1:, param2:); + +/* testParseErrorDynamicName */ +// Parse error. Ignore. +function_name($variableStoringParamName: $value); + +/* testParseErrorExit */ +// Exit is a language construct, not a function. Named params not supported, handle it anyway. +exit(status: $value); + +/* testParseErrorEmpty */ +// Empty is a language construct, not a function. Named params not supported, handle it anyway. +empty(variable: $value); + +/* testParseErrorEval */ +// Eval is a language construct, not a function. Named params not supported, handle it anyway. +eval(code: $value); + +/* testParseErrorArbitraryParentheses */ +// Parse error. Not named param, handle it anyway. +$calc = (something: $value / $other); + + +/* testReservedKeywordAbstract1 */ +foobar(abstract: $value, /* testReservedKeywordAbstract2 */ abstract: $value); + +/* testReservedKeywordAnd1 */ +foobar(and: $value, /* testReservedKeywordAnd2 */ and: $value); + +/* testReservedKeywordArray1 */ +foobar(array: $value, /* testReservedKeywordArray2 */ array: $value); + +/* testReservedKeywordAs1 */ +foobar(as: $value, /* testReservedKeywordAs2 */ as: $value); + +/* testReservedKeywordBreak1 */ +foobar(break: $value, /* testReservedKeywordBreak2 */ break: $value); + +/* testReservedKeywordCallable1 */ +foobar(callable: $value, /* testReservedKeywordCallable2 */ callable: $value); + +/* testReservedKeywordCase1 */ +foobar(case: $value, /* testReservedKeywordCase2 */ case: $value); + +/* testReservedKeywordCatch1 */ +foobar(catch: $value, /* testReservedKeywordCatch2 */ catch: $value); + +/* testReservedKeywordClass1 */ +foobar(class: $value, /* testReservedKeywordClass2 */ class: $value); + +/* testReservedKeywordClone1 */ +foobar(clone: $value, /* testReservedKeywordClone2 */ clone: $value); + +/* testReservedKeywordConst1 */ +foobar(const: $value, /* testReservedKeywordConst2 */ const: $value); + +/* testReservedKeywordContinue1 */ +foobar(continue: $value, /* testReservedKeywordContinue2 */ continue: $value); + +/* testReservedKeywordDeclare1 */ +foobar(declare: $value, /* testReservedKeywordDeclare2 */ declare: $value); + +/* testReservedKeywordDefault1 */ +foobar(default: $value, /* testReservedKeywordDefault2 */ default: $value); + +/* testReservedKeywordDie1 */ +foobar(die: $value, /* testReservedKeywordDie2 */ die: $value); + +/* testReservedKeywordDo1 */ +foobar(do: $value, /* testReservedKeywordDo2 */ do: $value); + +/* testReservedKeywordEcho1 */ +foobar(echo: $value, /* testReservedKeywordEcho2 */ echo: $value); + +/* testReservedKeywordElse1 */ +foobar(else: $value, /* testReservedKeywordElse2 */ else: $value); + +/* testReservedKeywordElseif1 */ +foobar(elseif: $value, /* testReservedKeywordElseif2 */ elseif: $value); + +/* testReservedKeywordEmpty1 */ +foobar(empty: $value, /* testReservedKeywordEmpty2 */ empty: $value); + +/* testReservedKeywordEnddeclare1 */ +foobar(enddeclare: $value, /* testReservedKeywordEnddeclare2 */ enddeclare: $value); + +/* testReservedKeywordEndfor1 */ +foobar(endfor: $value, /* testReservedKeywordEndfor2 */ endfor: $value); + +/* testReservedKeywordEndforeach1 */ +foobar(endforeach: $value, /* testReservedKeywordEndforeach2 */ endforeach: $value); + +/* testReservedKeywordEndif1 */ +foobar(endif: $value, /* testReservedKeywordEndif2 */ endif: $value); + +/* testReservedKeywordEndswitch1 */ +foobar(endswitch: $value, /* testReservedKeywordEndswitch2 */ endswitch: $value); + +/* testReservedKeywordEndwhile1 */ +foobar(endwhile: $value, /* testReservedKeywordEndwhile2 */ endwhile: $value); + +/* testReservedKeywordEval1 */ +foobar(eval: $value, /* testReservedKeywordEval2 */ eval: $value); + +/* testReservedKeywordExit1 */ +foobar(exit: $value, /* testReservedKeywordExit2 */ exit: $value); + +/* testReservedKeywordExtends1 */ +foobar(extends: $value, /* testReservedKeywordExtends2 */ extends: $value); + +/* testReservedKeywordFinal1 */ +foobar(final: $value, /* testReservedKeywordFinal2 */ final: $value); + +/* testReservedKeywordFinally1 */ +foobar(finally: $value, /* testReservedKeywordFinally2 */ finally: $value); + +/* testReservedKeywordFn1 */ +foobar(fn: $value, /* testReservedKeywordFn2 */ fn: $value); + +/* testReservedKeywordFor1 */ +foobar(for: $value, /* testReservedKeywordFor2 */ for: $value); + +/* testReservedKeywordForeach1 */ +foobar(foreach: $value, /* testReservedKeywordForeach2 */ foreach: $value); + +/* testReservedKeywordFunction1 */ +foobar(function: $value, /* testReservedKeywordFunction2 */ function: $value); + +/* testReservedKeywordGlobal1 */ +foobar(global: $value, /* testReservedKeywordGlobal2 */ global: $value); + +/* testReservedKeywordGoto1 */ +foobar(goto: $value, /* testReservedKeywordGoto2 */ goto: $value); + +/* testReservedKeywordIf1 */ +foobar(if: $value, /* testReservedKeywordIf2 */ if: $value); + +/* testReservedKeywordImplements1 */ +foobar(implements: $value, /* testReservedKeywordImplements2 */ implements: $value); + +/* testReservedKeywordInclude1 */ +foobar(include: $value, /* testReservedKeywordInclude2 */ include: $value); + +/* testReservedKeywordInclude_once1 */ +foobar(include_once: $value, /* testReservedKeywordInclude_once2 */ include_once: $value); + +/* testReservedKeywordInstanceof1 */ +foobar(instanceof: $value, /* testReservedKeywordInstanceof2 */ instanceof: $value); + +/* testReservedKeywordInsteadof1 */ +foobar(insteadof: $value, /* testReservedKeywordInsteadof2 */ insteadof: $value); + +/* testReservedKeywordInterface1 */ +foobar(interface: $value, /* testReservedKeywordInterface2 */ interface: $value); + +/* testReservedKeywordIsset1 */ +foobar(isset: $value, /* testReservedKeywordIsset2 */ isset: $value); + +/* testReservedKeywordList1 */ +foobar(list: $value, /* testReservedKeywordList2 */ list: $value); + +/* testReservedKeywordMatch1 */ +foobar(match: $value, /* testReservedKeywordMatch2 */ match: $value); + +/* testReservedKeywordNamespace1 */ +foobar(namespace: $value, /* testReservedKeywordNamespace2 */ namespace: $value); + +/* testReservedKeywordNew1 */ +foobar(new: $value, /* testReservedKeywordNew2 */ new: $value); + +/* testReservedKeywordOr1 */ +foobar(or: $value, /* testReservedKeywordOr2 */ or: $value); + +/* testReservedKeywordPrint1 */ +foobar(print: $value, /* testReservedKeywordPrint2 */ print: $value); + +/* testReservedKeywordPrivate1 */ +foobar(private: $value, /* testReservedKeywordPrivate2 */ private: $value); + +/* testReservedKeywordProtected1 */ +foobar(protected: $value, /* testReservedKeywordProtected2 */ protected: $value); + +/* testReservedKeywordPublic1 */ +foobar(public: $value, /* testReservedKeywordPublic2 */ public: $value); + +/* testReservedKeywordReadonly1 */ +foobar(readonly: $value, /* testReservedKeywordReadonly2 */ readonly: $value); + +/* testReservedKeywordRequire1 */ +foobar(require: $value, /* testReservedKeywordRequire2 */ require: $value); + +/* testReservedKeywordRequire_once1 */ +foobar(require_once: $value, /* testReservedKeywordRequire_once2 */ require_once: $value); + +/* testReservedKeywordReturn1 */ +foobar(return: $value, /* testReservedKeywordReturn2 */ return: $value); + +/* testReservedKeywordStatic1 */ +foobar(static: $value, /* testReservedKeywordStatic2 */ static: $value); + +/* testReservedKeywordSwitch1 */ +foobar(switch: $value, /* testReservedKeywordSwitch2 */ switch: $value); + +/* testReservedKeywordThrow1 */ +foobar(throw: $value, /* testReservedKeywordThrow2 */ throw: $value); + +/* testReservedKeywordTrait1 */ +foobar(trait: $value, /* testReservedKeywordTrait2 */ trait: $value); + +/* testReservedKeywordTry1 */ +foobar(try: $value, /* testReservedKeywordTry2 */ try: $value); + +/* testReservedKeywordUnset1 */ +foobar(unset: $value, /* testReservedKeywordUnset2 */ unset: $value); + +/* testReservedKeywordUse1 */ +foobar(use: $value, /* testReservedKeywordUse2 */ use: $value); + +/* testReservedKeywordVar1 */ +foobar(var: $value, /* testReservedKeywordVar2 */ var: $value); + +/* testReservedKeywordWhile1 */ +foobar(while: $value, /* testReservedKeywordWhile2 */ while: $value); + +/* testReservedKeywordXor1 */ +foobar(xor: $value, /* testReservedKeywordXor2 */ xor: $value); + +/* testReservedKeywordYield1 */ +foobar(yield: $value, /* testReservedKeywordYield2 */ yield: $value); + +/* testReservedKeywordInt1 */ +foobar(int: $value, /* testReservedKeywordInt2 */ int: $value); + +/* testReservedKeywordFloat1 */ +foobar(float: $value, /* testReservedKeywordFloat2 */ float: $value); + +/* testReservedKeywordBool1 */ +foobar(bool: $value, /* testReservedKeywordBool2 */ bool: $value); + +/* testReservedKeywordString1 */ +foobar(string: $value, /* testReservedKeywordString2 */ string: $value); + +/* testReservedKeywordTrue1 */ +foobar(true: $value, /* testReservedKeywordTrue2 */ true: $value); + +/* testReservedKeywordFalse1 */ +foobar(false: $value, /* testReservedKeywordFalse2 */ false: $value); + +/* testReservedKeywordNull1 */ +foobar(null: $value, /* testReservedKeywordNull2 */ null: $value); + +/* testReservedKeywordVoid1 */ +foobar(void: $value, /* testReservedKeywordVoid2 */ void: $value); + +/* testReservedKeywordIterable1 */ +foobar(iterable: $value, /* testReservedKeywordIterable2 */ iterable: $value); + +/* testReservedKeywordObject1 */ +foobar(object: $value, /* testReservedKeywordObject2 */ object: $value); + +/* testReservedKeywordResource1 */ +foobar(resource: $value, /* testReservedKeywordResource2 */ resource: $value); + +/* testReservedKeywordMixed1 */ +foobar(mixed: $value, /* testReservedKeywordMixed2 */ mixed: $value); + +/* testReservedKeywordNumeric1 */ +foobar(numeric: $value, /* testReservedKeywordNumeric2 */ numeric: $value); + +/* testReservedKeywordParent1 */ +foobar(parent: $value, /* testReservedKeywordParent2 */ parent: $value); + +/* testReservedKeywordSelf1 */ +foobar(self: $value, /* testReservedKeywordSelf2 */ self: $value); + +/* testReservedKeywordNever1 */ +foobar(never: $value, /* testReservedKeywordNever2 */ never: $value); diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.php new file mode 100644 index 00000000..0a878c1d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.php @@ -0,0 +1,884 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +class NamedFunctionCallArgumentsTest extends AbstractMethodUnitTest +{ + + + /** + * Verify that parameter labels are tokenized as T_PARAM_NAME and that + * the colon after it is tokenized as a T_COLON. + * + * @param string $testMarker The comment prefacing the target token. + * @param array $parameters The token content for each parameter label to look for. + * + * @dataProvider dataNamedFunctionCallArguments + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNamedFunctionCallArguments($testMarker, $parameters) + { + $tokens = self::$phpcsFile->getTokens(); + + foreach ($parameters as $content) { + $label = $this->getTargetToken($testMarker, [T_STRING, T_PARAM_NAME], $content); + + $this->assertSame( + T_PARAM_NAME, + $tokens[$label]['code'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_PARAM_NAME (code)' + ); + $this->assertSame( + 'T_PARAM_NAME', + $tokens[$label]['type'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_PARAM_NAME (type)' + ); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + }//end foreach + + }//end testNamedFunctionCallArguments() + + + /** + * Data provider. + * + * @see testNamedFunctionCallArguments() + * + * @return array + */ + public function dataNamedFunctionCallArguments() + { + return [ + [ + '/* testNamedArgs */', + [ + 'start_index', + 'count', + 'value', + ], + ], + [ + '/* testNamedArgsMultiline */', + [ + 'start_index', + 'count', + 'value', + ], + ], + [ + '/* testNamedArgsWithWhitespaceAndComments */', + [ + 'start_index', + 'count', + 'value', + ], + ], + [ + '/* testMixedPositionalAndNamedArgs */', + ['double_encode'], + ], + [ + '/* testNestedFunctionCallOuter */', + [ + 'start_index', + 'count', + 'value', + ], + ], + [ + '/* testNestedFunctionCallInner1 */', + ['skip'], + ], + [ + '/* testNestedFunctionCallInner2 */', + ['array_or_countable'], + ], + [ + '/* testNamespaceOperatorFunction */', + [ + 'label', + 'more', + ], + ], + [ + '/* testNamespaceRelativeFunction */', + [ + 'label', + 'more', + ], + ], + [ + '/* testNamespacedFQNFunction */', + [ + 'label', + 'more', + ], + ], + [ + '/* testVariableFunction */', + [ + 'label', + 'more', + ], + ], + [ + '/* testVariableVariableFunction */', + [ + 'label', + 'more', + ], + ], + [ + '/* testMethodCall */', + [ + 'label', + 'more', + ], + ], + [ + '/* testVariableMethodCall */', + [ + 'label', + 'more', + ], + ], + [ + '/* testClassInstantiation */', + [ + 'label', + 'more', + ], + ], + [ + '/* testClassInstantiationSelf */', + [ + 'label', + 'more', + ], + ], + [ + '/* testClassInstantiationStatic */', + [ + 'label', + 'more', + ], + ], + [ + '/* testAnonClass */', + [ + 'label', + 'more', + ], + ], + [ + '/* testNonAsciiNames */', + [ + '💩💩💩', + 'Пасха', + '_valid', + ], + ], + + // Coding errors which should still be handled. + [ + '/* testCompileErrorNamedBeforePositional */', + ['param'], + ], + [ + '/* testDuplicateName1 */', + ['param'], + ], + [ + '/* testDuplicateName2 */', + ['param'], + ], + [ + '/* testIncorrectOrderWithVariadic */', + ['start_index'], + ], + [ + '/* testCompileErrorIncorrectOrderWithVariadic */', + ['param'], + ], + [ + '/* testParseErrorNoValue */', + [ + 'param1', + 'param2', + ], + ], + [ + '/* testParseErrorExit */', + ['status'], + ], + [ + '/* testParseErrorEmpty */', + ['variable'], + ], + [ + '/* testParseErrorEval */', + ['code'], + ], + [ + '/* testParseErrorArbitraryParentheses */', + ['something'], + ], + ]; + + }//end dataNamedFunctionCallArguments() + + + /** + * Verify that other T_STRING tokens within a function call are still tokenized as T_STRING. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $content The token content to look for. + * + * @dataProvider dataOtherTstringInFunctionCall + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testOtherTstringInFunctionCall($testMarker, $content) + { + $tokens = self::$phpcsFile->getTokens(); + + $label = $this->getTargetToken($testMarker, [T_STRING, T_PARAM_NAME], $content); + + $this->assertSame( + T_STRING, + $tokens[$label]['code'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_STRING (code)' + ); + $this->assertSame( + 'T_STRING', + $tokens[$label]['type'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_STRING (type)' + ); + + }//end testOtherTstringInFunctionCall() + + + /** + * Data provider. + * + * @see testOtherTstringInFunctionCall() + * + * @return array + */ + public function dataOtherTstringInFunctionCall() + { + return [ + [ + '/* testPositionalArgs */', + 'START_INDEX', + ], + [ + '/* testPositionalArgs */', + 'COUNT', + ], + [ + '/* testPositionalArgs */', + 'VALUE', + ], + [ + '/* testNestedFunctionCallInner2 */', + 'count', + ], + ]; + + }//end dataOtherTstringInFunctionCall() + + + /** + * Verify whether the colons are tokenized correctly when a ternary is used in a mixed + * positional and named arguments function call. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testMixedPositionalAndNamedArgsWithTernary() + { + $tokens = self::$phpcsFile->getTokens(); + + $true = $this->getTargetToken('/* testMixedPositionalAndNamedArgsWithTernary */', T_TRUE); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($true + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + $label = $this->getTargetToken('/* testMixedPositionalAndNamedArgsWithTernary */', T_PARAM_NAME, 'name'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testMixedPositionalAndNamedArgsWithTernary() + + + /** + * Verify whether the colons are tokenized correctly when a ternary is used + * in a named arguments function call. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNamedArgWithTernary() + { + $tokens = self::$phpcsFile->getTokens(); + + /* + * First argument. + */ + + $label = $this->getTargetToken('/* testNamedArgWithTernary */', T_PARAM_NAME, 'label'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'First arg: Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'First arg: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'First arg: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $true = $this->getTargetToken('/* testNamedArgWithTernary */', T_TRUE); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($true + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'First arg ternary: Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'First arg ternary: Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + /* + * Second argument. + */ + + $label = $this->getTargetToken('/* testNamedArgWithTernary */', T_PARAM_NAME, 'more'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Second arg: Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Second arg: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Second arg: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $true = $this->getTargetToken('/* testNamedArgWithTernary */', T_STRING, 'CONSTANT_A'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($true + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'Second arg ternary: Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'Second arg ternary: Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + }//end testNamedArgWithTernary() + + + /** + * Verify whether the colons are tokenized correctly when named arguments + * function calls are used in a ternary. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testTernaryWithFunctionCallsInThenElse() + { + $tokens = self::$phpcsFile->getTokens(); + + /* + * Then. + */ + + $label = $this->getTargetToken('/* testTernaryWithFunctionCallsInThenElse */', T_PARAM_NAME, 'label'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Function in then: Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Function in then: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Function in then: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $closeParens = $this->getTargetToken('/* testTernaryWithFunctionCallsInThenElse */', T_CLOSE_PARENTHESIS); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($closeParens + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + /* + * Else. + */ + + $label = $this->getTargetToken('/* testTernaryWithFunctionCallsInThenElse */', T_PARAM_NAME, 'more'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Function in else: Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Function in else: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Function in else: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testTernaryWithFunctionCallsInThenElse() + + + /** + * Verify whether the colons are tokenized correctly when constants are used in a ternary. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testTernaryWithConstantsInThenElse() + { + $tokens = self::$phpcsFile->getTokens(); + + $constant = $this->getTargetToken('/* testTernaryWithConstantsInThenElse */', T_STRING, 'CONSTANT_NAME'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($constant + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + }//end testTernaryWithConstantsInThenElse() + + + /** + * Verify whether the colons are tokenized correctly in a switch statement. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testSwitchStatement() + { + $tokens = self::$phpcsFile->getTokens(); + + $label = $this->getTargetToken('/* testSwitchCaseWithConstant */', T_STRING, 'MY_CONSTANT'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'First case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'First case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $label = $this->getTargetToken('/* testSwitchCaseWithClassProperty */', T_STRING, 'property'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Second case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Second case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $default = $this->getTargetToken('/* testSwitchDefault */', T_DEFAULT); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($default + 1), null, true); + + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Default case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Default case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testSwitchStatement() + + + /** + * Verify that a variable parameter label (parse error) is still tokenized as T_VARIABLE. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testParseErrorVariableLabel() + { + $tokens = self::$phpcsFile->getTokens(); + + $label = $this->getTargetToken('/* testParseErrorDynamicName */', [T_VARIABLE, T_PARAM_NAME], '$variableStoringParamName'); + + $this->assertSame( + T_VARIABLE, + $tokens[$label]['code'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_VARIABLE (code)' + ); + $this->assertSame( + 'T_VARIABLE', + $tokens[$label]['type'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_VARIABLE (type)' + ); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testParseErrorVariableLabel() + + + /** + * Verify that reserved keywords used as a parameter label are tokenized as T_PARAM_NAME + * and that the colon after it is tokenized as a T_COLON. + * + * @param string $testMarker The comment prefacing the target token. + * @param array $tokenTypes The token codes to look for. + * @param string $tokenContent The token content to look for. + * + * @dataProvider dataReservedKeywordsAsName + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testReservedKeywordsAsName($testMarker, $tokenTypes, $tokenContent) + { + $tokens = self::$phpcsFile->getTokens(); + $label = $this->getTargetToken($testMarker, $tokenTypes, $tokenContent); + + $this->assertSame( + T_PARAM_NAME, + $tokens[$label]['code'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_PARAM_NAME (code)' + ); + $this->assertSame( + 'T_PARAM_NAME', + $tokens[$label]['type'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_PARAM_NAME (type)' + ); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testReservedKeywordsAsName() + + + /** + * Data provider. + * + * @see testReservedKeywordsAsName() + * + * @return array + */ + public function dataReservedKeywordsAsName() + { + $reservedKeywords = [ + // '__halt_compiler', NOT TESTABLE + 'abstract', + 'and', + 'array', + 'as', + 'break', + 'callable', + 'case', + 'catch', + 'class', + 'clone', + 'const', + 'continue', + 'declare', + 'default', + 'die', + 'do', + 'echo', + 'else', + 'elseif', + 'empty', + 'enddeclare', + 'endfor', + 'endforeach', + 'endif', + 'endswitch', + 'endwhile', + 'eval', + 'exit', + 'extends', + 'final', + 'finally', + 'fn', + 'for', + 'foreach', + 'function', + 'global', + 'goto', + 'if', + 'implements', + 'include', + 'include_once', + 'instanceof', + 'insteadof', + 'interface', + 'isset', + 'list', + 'match', + 'namespace', + 'new', + 'or', + 'print', + 'private', + 'protected', + 'public', + 'readonly', + 'require', + 'require_once', + 'return', + 'static', + 'switch', + 'throw', + 'trait', + 'try', + 'unset', + 'use', + 'var', + 'while', + 'xor', + 'yield', + 'int', + 'float', + 'bool', + 'string', + 'true', + 'false', + 'null', + 'void', + 'iterable', + 'object', + 'resource', + 'mixed', + 'numeric', + 'never', + + // Not reserved keyword, but do have their own token in PHPCS. + 'parent', + 'self', + ]; + + $data = []; + + foreach ($reservedKeywords as $keyword) { + $tokensTypes = [ + T_PARAM_NAME, + T_STRING, + T_GOTO_LABEL, + ]; + $tokenName = 'T_'.strtoupper($keyword); + + if ($keyword === 'and') { + $tokensTypes[] = T_LOGICAL_AND; + } else if ($keyword === 'die') { + $tokensTypes[] = T_EXIT; + } else if ($keyword === 'or') { + $tokensTypes[] = T_LOGICAL_OR; + } else if ($keyword === 'xor') { + $tokensTypes[] = T_LOGICAL_XOR; + } else if ($keyword === '__halt_compiler') { + $tokensTypes[] = T_HALT_COMPILER; + } else if (defined($tokenName) === true) { + $tokensTypes[] = constant($tokenName); + } + + $data[$keyword.'FirstParam'] = [ + '/* testReservedKeyword'.ucfirst($keyword).'1 */', + $tokensTypes, + $keyword, + ]; + + $data[$keyword.'SecondParam'] = [ + '/* testReservedKeyword'.ucfirst($keyword).'2 */', + $tokensTypes, + $keyword, + ]; + }//end foreach + + return $data; + + }//end dataReservedKeywordsAsName() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/NullsafeObjectOperatorTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/NullsafeObjectOperatorTest.inc new file mode 100644 index 00000000..982841ea --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/NullsafeObjectOperatorTest.inc @@ -0,0 +1,29 @@ +foo; + +/* testNullsafeObjectOperator */ +echo $obj?->foo; + +/* testNullsafeObjectOperatorWriteContext */ +// Intentional parse error, but not the concern of the tokenizer. +$foo?->bar->baz = 'baz'; + +/* testTernaryThen */ +echo $obj ? $obj->prop : $other->prop; + +/* testParseErrorWhitespaceNotAllowed */ +echo $obj ? + -> foo; + +/* testParseErrorCommentNotAllowed */ +echo $obj ?/*comment*/-> foo; + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +echo $obj? diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/NullsafeObjectOperatorTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/NullsafeObjectOperatorTest.php new file mode 100644 index 00000000..8e465a3b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/NullsafeObjectOperatorTest.php @@ -0,0 +1,140 @@ += 8.0 nullsafe object operator. + * + * @author Juliette Reinders Folmer + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +class NullsafeObjectOperatorTest extends AbstractMethodUnitTest +{ + + /** + * Tokens to search for. + * + * @var array + */ + protected $find = [ + T_NULLSAFE_OBJECT_OPERATOR, + T_OBJECT_OPERATOR, + T_INLINE_THEN, + ]; + + + /** + * Test that a normal object operator is still tokenized as such. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testObjectOperator() + { + $tokens = self::$phpcsFile->getTokens(); + + $operator = $this->getTargetToken('/* testObjectOperator */', $this->find); + $this->assertSame(T_OBJECT_OPERATOR, $tokens[$operator]['code'], 'Failed asserting code is object operator'); + $this->assertSame('T_OBJECT_OPERATOR', $tokens[$operator]['type'], 'Failed asserting type is object operator'); + + }//end testObjectOperator() + + + /** + * Test that a nullsafe object operator is tokenized as such. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataNullsafeObjectOperator + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNullsafeObjectOperator($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $operator = $this->getTargetToken($testMarker, $this->find); + $this->assertSame(T_NULLSAFE_OBJECT_OPERATOR, $tokens[$operator]['code'], 'Failed asserting code is nullsafe object operator'); + $this->assertSame('T_NULLSAFE_OBJECT_OPERATOR', $tokens[$operator]['type'], 'Failed asserting type is nullsafe object operator'); + + }//end testNullsafeObjectOperator() + + + /** + * Data provider. + * + * @see testNullsafeObjectOperator() + * + * @return array + */ + public function dataNullsafeObjectOperator() + { + return [ + ['/* testNullsafeObjectOperator */'], + ['/* testNullsafeObjectOperatorWriteContext */'], + ]; + + }//end dataNullsafeObjectOperator() + + + /** + * Test that a question mark not followed by an object operator is tokenized as T_TERNARY_THEN. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param bool $testObjectOperator Whether to test for the next non-empty token being tokenized + * as an object operator. + * + * @dataProvider dataTernaryThen + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testTernaryThen($testMarker, $testObjectOperator=false) + { + $tokens = self::$phpcsFile->getTokens(); + + $operator = $this->getTargetToken($testMarker, $this->find); + $this->assertSame(T_INLINE_THEN, $tokens[$operator]['code'], 'Failed asserting code is inline then'); + $this->assertSame('T_INLINE_THEN', $tokens[$operator]['type'], 'Failed asserting type is inline then'); + + if ($testObjectOperator === true) { + $next = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($operator + 1), null, true); + $this->assertSame(T_OBJECT_OPERATOR, $tokens[$next]['code'], 'Failed asserting code is object operator'); + $this->assertSame('T_OBJECT_OPERATOR', $tokens[$next]['type'], 'Failed asserting type is object operator'); + } + + }//end testTernaryThen() + + + /** + * Data provider. + * + * @see testTernaryThen() + * + * @return array + */ + public function dataTernaryThen() + { + return [ + ['/* testTernaryThen */'], + [ + '/* testParseErrorWhitespaceNotAllowed */', + true, + ], + [ + '/* testParseErrorCommentNotAllowed */', + true, + ], + ['/* testLiveCoding */'], + ]; + + }//end dataTernaryThen() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc new file mode 100644 index 00000000..e2d61bb6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc @@ -0,0 +1,19 @@ + new namespace\Baz; diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php new file mode 100644 index 00000000..23cbd987 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php @@ -0,0 +1,98 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class ScopeSettingWithNamespaceOperatorTest extends AbstractMethodUnitTest +{ + + + /** + * Test that the scope opener/closers are set correctly when the namespace keyword is encountered as an operator. + * + * @param string $testMarker The comment which prefaces the target tokens in the test file. + * @param int|string[] $tokenTypes The token type to search for. + * @param int|string[] $open Optional. The token type for the scope opener. + * @param int|string[] $close Optional. The token type for the scope closer. + * + * @dataProvider dataScopeSetting + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testScopeSetting($testMarker, $tokenTypes, $open=T_OPEN_CURLY_BRACKET, $close=T_CLOSE_CURLY_BRACKET) + { + $tokens = self::$phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, $tokenTypes); + $opener = $this->getTargetToken($testMarker, $open); + $closer = $this->getTargetToken($testMarker, $close); + + $this->assertArrayHasKey('scope_opener', $tokens[$target], 'Scope opener missing'); + $this->assertArrayHasKey('scope_closer', $tokens[$target], 'Scope closer missing'); + $this->assertSame($opener, $tokens[$target]['scope_opener'], 'Scope opener not same'); + $this->assertSame($closer, $tokens[$target]['scope_closer'], 'Scope closer not same'); + + $this->assertArrayHasKey('scope_opener', $tokens[$opener], 'Scope opener missing for open curly'); + $this->assertArrayHasKey('scope_closer', $tokens[$opener], 'Scope closer missing for open curly'); + $this->assertSame($opener, $tokens[$opener]['scope_opener'], 'Scope opener not same for open curly'); + $this->assertSame($closer, $tokens[$opener]['scope_closer'], 'Scope closer not same for open curly'); + + $this->assertArrayHasKey('scope_opener', $tokens[$closer], 'Scope opener missing for close curly'); + $this->assertArrayHasKey('scope_closer', $tokens[$closer], 'Scope closer missing for close curly'); + $this->assertSame($opener, $tokens[$closer]['scope_opener'], 'Scope opener not same for close curly'); + $this->assertSame($closer, $tokens[$closer]['scope_closer'], 'Scope closer not same for close curly'); + + }//end testScopeSetting() + + + /** + * Data provider. + * + * @see testScopeSetting() + * + * @return array + */ + public function dataScopeSetting() + { + return [ + [ + '/* testClassExtends */', + [T_CLASS], + ], + [ + '/* testClassImplements */', + [T_ANON_CLASS], + ], + [ + '/* testInterfaceExtends */', + [T_INTERFACE], + ], + [ + '/* testFunctionReturnType */', + [T_FUNCTION], + ], + [ + '/* testClosureReturnType */', + [T_CLOSURE], + ], + [ + '/* testArrowFunctionReturnType */', + [T_FN], + [T_FN_ARROW], + [T_SEMICOLON], + ], + ]; + + }//end dataScopeSetting() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ShortArrayTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ShortArrayTest.inc new file mode 100644 index 00000000..54065f21 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ShortArrayTest.inc @@ -0,0 +1,97 @@ +function_call()[$x]; + +/* testStaticMethodCallDereferencing */ +$var = ClassName::function_call()[$x]; + +/* testPropertyDereferencing */ +$var = $obj->property[2]; + +/* testPropertyDereferencingWithInaccessibleName */ +$var = $ref->{'ref-type'}[1]; + +/* testStaticPropertyDereferencing */ +$var ClassName::$property[2]; + +/* testStringDereferencing */ +$var = 'PHP'[1]; + +/* testStringDereferencingDoubleQuoted */ +$var = "PHP"[$y]; + +/* testConstantDereferencing */ +$var = MY_CONSTANT[1]; + +/* testClassConstantDereferencing */ +$var ClassName::CONSTANT_NAME[2]; + +/* testMagicConstantDereferencing */ +$var = __FILE__[0]; + +/* testArrayAccessCurlyBraces */ +$var = $array{'key'}['key']; + +/* testArrayLiteralDereferencing */ +echo array(1, 2, 3)[0]; + +echo [1, 2, 3]/* testShortArrayLiteralDereferencing */[0]; + +/* testClassMemberDereferencingOnInstantiation1 */ +(new foo)[0]; + +/* testClassMemberDereferencingOnInstantiation2 */ +$a = (new Foo( array(1, array(4, 5), 3) ))[1][0]; + +/* testClassMemberDereferencingOnClone */ +echo (clone $iterable)[20]; + +/* testNullsafeMethodCallDereferencing */ +$var = $obj?->function_call()[$x]; + +/* testInterpolatedStringDereferencing */ +$var = "PHP{$rocks}"[1]; + +/* + * Short array brackets. + */ + +/* testShortArrayDeclarationEmpty */ +$array = []; + +/* testShortArrayDeclarationWithOneValue */ +$array = [1]; + +/* testShortArrayDeclarationWithMultipleValues */ +$array = [1, 2, 3]; + +/* testShortArrayDeclarationWithDereferencing */ +echo [1, 2, 3][0]; + +/* testShortListDeclaration */ +[ $a, $b ] = $array; + +[ $a, $b, /* testNestedListDeclaration */, [$c, $d]] = $array; + +/* testArrayWithinFunctionCall */ +$var = functionCall([$x, $y]); + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +$array = [ diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ShortArrayTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ShortArrayTest.php new file mode 100644 index 00000000..0484d4fc --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/ShortArrayTest.php @@ -0,0 +1,132 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class ShortArrayTest extends AbstractMethodUnitTest +{ + + + /** + * Test that real square brackets are still tokenized as square brackets. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataSquareBrackets + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testSquareBrackets($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $opener = $this->getTargetToken($testMarker, [T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY]); + $this->assertSame(T_OPEN_SQUARE_BRACKET, $tokens[$opener]['code']); + $this->assertSame('T_OPEN_SQUARE_BRACKET', $tokens[$opener]['type']); + + if (isset($tokens[$opener]['bracket_closer']) === true) { + $closer = $tokens[$opener]['bracket_closer']; + $this->assertSame(T_CLOSE_SQUARE_BRACKET, $tokens[$closer]['code']); + $this->assertSame('T_CLOSE_SQUARE_BRACKET', $tokens[$closer]['type']); + } + + }//end testSquareBrackets() + + + /** + * Data provider. + * + * @see testSquareBrackets() + * + * @return array + */ + public function dataSquareBrackets() + { + return [ + ['/* testArrayAccess1 */'], + ['/* testArrayAccess2 */'], + ['/* testArrayAssignment */'], + ['/* testFunctionCallDereferencing */'], + ['/* testMethodCallDereferencing */'], + ['/* testStaticMethodCallDereferencing */'], + ['/* testPropertyDereferencing */'], + ['/* testPropertyDereferencingWithInaccessibleName */'], + ['/* testStaticPropertyDereferencing */'], + ['/* testStringDereferencing */'], + ['/* testStringDereferencingDoubleQuoted */'], + ['/* testConstantDereferencing */'], + ['/* testClassConstantDereferencing */'], + ['/* testMagicConstantDereferencing */'], + ['/* testArrayAccessCurlyBraces */'], + ['/* testArrayLiteralDereferencing */'], + ['/* testShortArrayLiteralDereferencing */'], + ['/* testClassMemberDereferencingOnInstantiation1 */'], + ['/* testClassMemberDereferencingOnInstantiation2 */'], + ['/* testClassMemberDereferencingOnClone */'], + ['/* testNullsafeMethodCallDereferencing */'], + ['/* testInterpolatedStringDereferencing */'], + ['/* testLiveCoding */'], + ]; + + }//end dataSquareBrackets() + + + /** + * Test that short arrays and short lists are still tokenized as short arrays. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataShortArrays + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testShortArrays($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $opener = $this->getTargetToken($testMarker, [T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY]); + $this->assertSame(T_OPEN_SHORT_ARRAY, $tokens[$opener]['code']); + $this->assertSame('T_OPEN_SHORT_ARRAY', $tokens[$opener]['type']); + + if (isset($tokens[$opener]['bracket_closer']) === true) { + $closer = $tokens[$opener]['bracket_closer']; + $this->assertSame(T_CLOSE_SHORT_ARRAY, $tokens[$closer]['code']); + $this->assertSame('T_CLOSE_SHORT_ARRAY', $tokens[$closer]['type']); + } + + }//end testShortArrays() + + + /** + * Data provider. + * + * @see testShortArrays() + * + * @return array + */ + public function dataShortArrays() + { + return [ + ['/* testShortArrayDeclarationEmpty */'], + ['/* testShortArrayDeclarationWithOneValue */'], + ['/* testShortArrayDeclarationWithMultipleValues */'], + ['/* testShortArrayDeclarationWithDereferencing */'], + ['/* testShortListDeclaration */'], + ['/* testNestedListDeclaration */'], + ['/* testArrayWithinFunctionCall */'], + ]; + + }//end dataShortArrays() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceTest.inc new file mode 100644 index 00000000..3bf013c6 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceTest.inc @@ -0,0 +1,139 @@ + + + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +class StableCommentWhitespaceTest extends AbstractMethodUnitTest +{ + + + /** + * Test that comment tokenization with new lines at the end of the comment is stable. + * + * @param string $testMarker The comment prefacing the test. + * @param array $expectedTokens The tokenization expected. + * + * @dataProvider dataCommentTokenization + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testCommentTokenization($testMarker, $expectedTokens) + { + $tokens = self::$phpcsFile->getTokens(); + $comment = $this->getTargetToken($testMarker, Tokens::$commentTokens); + + foreach ($expectedTokens as $key => $tokenInfo) { + $this->assertSame(constant($tokenInfo['type']), $tokens[$comment]['code']); + $this->assertSame($tokenInfo['type'], $tokens[$comment]['type']); + $this->assertSame($tokenInfo['content'], $tokens[$comment]['content']); + + ++$comment; + } + + }//end testCommentTokenization() + + + /** + * Data provider. + * + * @see testCommentTokenization() + * + * @return array + */ + public function dataCommentTokenization() + { + return [ + [ + '/* testSingleLineSlashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineSlashCommentTrailing */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineSlashAnnotation */', + [ + [ + 'type' => 'T_PHPCS_DISABLE', + 'content' => '// phpcs:disable Stnd.Cat +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithIndent */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithAnnotationStart */', + [ + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithAnnotationMiddle */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// @phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithAnnotationEnd */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineStarComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Single line star comment */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineStarCommentTrailing */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineStarAnnotation */', + [ + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '/* phpcs:ignore Stnd.Cat */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineStarComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment3 */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineStarCommentWithIndent */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment3 */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineStarCommentWithAnnotationStart */', + [ + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '/* @phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment3 */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineStarCommentWithAnnotationMiddle */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment1 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => ' * phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment3 */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineStarCommentWithAnnotationEnd */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment2 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => ' * phpcs:ignore Stnd.Cat */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + + [ + '/* testSingleLineDocblockComment */', + [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineDocblockCommentTrailing */', + [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineDocblockAnnotation */', + [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => 'phpcs:ignore Stnd.Cat.Sniff ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + + [ + '/* testMultiLineDocblockComment */', + [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment1', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment2', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_TAG', + 'content' => '@tag', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineDocblockCommentWithIndent */', + [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment1', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment2', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_TAG', + 'content' => '@tag', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineDocblockCommentWithAnnotation */', + [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => 'phpcs:ignore Stnd.Cat', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_TAG', + 'content' => '@tag', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineDocblockCommentWithTagAnnotation */', + [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '@phpcs:ignore Stnd.Cat', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_TAG', + 'content' => '@tag', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineHashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineHashCommentTrailing */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineHashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineHashCommentWithIndent */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment1 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment2 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineSlashCommentNoNewLineAtEnd */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Slash ', + ], + [ + 'type' => 'T_CLOSE_TAG', + 'content' => '?> +', + ], + ], + ], + [ + '/* testSingleLineHashCommentNoNewLineAtEnd */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Hash ', + ], + [ + 'type' => 'T_CLOSE_TAG', + 'content' => '?> +', + ], + ], + ], + [ + '/* testCommentAtEndOfFile */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment', + ], + ], + ], + ]; + + }//end dataCommentTokenization() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceWinTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceWinTest.inc new file mode 100644 index 00000000..dc98eb01 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceWinTest.inc @@ -0,0 +1,63 @@ + + + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +class StableCommentWhitespaceWinTest extends AbstractMethodUnitTest +{ + + + /** + * Test that comment tokenization with new lines at the end of the comment is stable. + * + * @param string $testMarker The comment prefacing the test. + * @param array $expectedTokens The tokenization expected. + * + * @dataProvider dataCommentTokenization + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testCommentTokenization($testMarker, $expectedTokens) + { + $tokens = self::$phpcsFile->getTokens(); + $comment = $this->getTargetToken($testMarker, Tokens::$commentTokens); + + foreach ($expectedTokens as $key => $tokenInfo) { + $this->assertSame(constant($tokenInfo['type']), $tokens[$comment]['code']); + $this->assertSame($tokenInfo['type'], $tokens[$comment]['type']); + $this->assertSame($tokenInfo['content'], $tokens[$comment]['content']); + + ++$comment; + } + + }//end testCommentTokenization() + + + /** + * Data provider. + * + * @see testCommentTokenization() + * + * @return array + */ + public function dataCommentTokenization() + { + return [ + [ + '/* testSingleLineSlashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineSlashCommentTrailing */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineSlashAnnotation */', + [ + [ + 'type' => 'T_PHPCS_DISABLE', + 'content' => '// phpcs:disable Stnd.Cat +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithIndent */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithAnnotationStart */', + [ + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithAnnotationMiddle */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// @phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithAnnotationEnd */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineSlashCommentNoNewLineAtEnd */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Slash ', + ], + [ + 'type' => 'T_CLOSE_TAG', + 'content' => '?> +', + ], + ], + ], + [ + '/* testSingleLineHashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineHashCommentTrailing */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineHashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineHashCommentWithIndent */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment1 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment2 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineHashCommentNoNewLineAtEnd */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Hash ', + ], + [ + 'type' => 'T_CLOSE_TAG', + 'content' => '?> +', + ], + ], + ], + [ + '/* testCommentAtEndOfFile */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment', + ], + ], + ], + ]; + + }//end dataCommentTokenization() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/TypeIntersectionTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/TypeIntersectionTest.inc new file mode 100644 index 00000000..abf9b85b --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/TypeIntersectionTest.inc @@ -0,0 +1,120 @@ + $param & $int; + +/* testTypeIntersectionArrowReturnType */ +$arrowWithReturnType = fn ($param) : Foo&Bar => $param * 10; + +/* testBitwiseAndInArrayKey */ +$array = array( + A & B => /* testBitwiseAndInArrayValue */ B & C +); + +/* testBitwiseAndInShortArrayKey */ +$array = [ + A & B => /* testBitwiseAndInShortArrayValue */ B & C +]; + +/* testBitwiseAndNonArrowFnFunctionCall */ +$obj->fn($something & $else); + +/* testBitwiseAnd6 */ +function &fn(/* testTypeIntersectionNonArrowFunctionDeclaration */ Foo&Bar $something) {} + +/* testTypeIntersectionWithInvalidTypes */ +function (int&string $var) {}; + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +return function( Foo& diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/TypeIntersectionTest.php b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/TypeIntersectionTest.php new file mode 100644 index 00000000..21700219 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/TypeIntersectionTest.php @@ -0,0 +1,138 @@ + + * @author Jaroslav Hanslík + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class TypeIntersectionTest extends AbstractMethodUnitTest +{ + + + /** + * Test that non-intersection type bitwise and tokens are still tokenized as bitwise and. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataBitwiseAnd + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testBitwiseAnd($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $opener = $this->getTargetToken($testMarker, [T_BITWISE_AND, T_TYPE_INTERSECTION]); + $this->assertSame(T_BITWISE_AND, $tokens[$opener]['code']); + $this->assertSame('T_BITWISE_AND', $tokens[$opener]['type']); + + }//end testBitwiseAnd() + + + /** + * Data provider. + * + * @see testBitwiseAnd() + * + * @return array + */ + public function dataBitwiseAnd() + { + return [ + ['/* testBitwiseAnd1 */'], + ['/* testBitwiseAnd2 */'], + ['/* testBitwiseAndPropertyDefaultValue */'], + ['/* testBitwiseAndParamDefaultValue */'], + ['/* testBitwiseAnd3 */'], + ['/* testBitwiseAnd4 */'], + ['/* testBitwiseAnd5 */'], + ['/* testBitwiseAndClosureParamDefault */'], + ['/* testBitwiseAndArrowParamDefault */'], + ['/* testBitwiseAndArrowExpression */'], + ['/* testBitwiseAndInArrayKey */'], + ['/* testBitwiseAndInArrayValue */'], + ['/* testBitwiseAndInShortArrayKey */'], + ['/* testBitwiseAndInShortArrayValue */'], + ['/* testBitwiseAndNonArrowFnFunctionCall */'], + ['/* testBitwiseAnd6 */'], + ['/* testLiveCoding */'], + ]; + + }//end dataBitwiseAnd() + + + /** + * Test that bitwise and tokens when used as part of a intersection type are tokenized as `T_TYPE_INTERSECTION`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataTypeIntersection + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testTypeIntersection($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $opener = $this->getTargetToken($testMarker, [T_BITWISE_AND, T_TYPE_INTERSECTION]); + $this->assertSame(T_TYPE_INTERSECTION, $tokens[$opener]['code']); + $this->assertSame('T_TYPE_INTERSECTION', $tokens[$opener]['type']); + + }//end testTypeIntersection() + + + /** + * Data provider. + * + * @see testTypeIntersection() + * + * @return array + */ + public function dataTypeIntersection() + { + return [ + ['/* testTypeIntersectionPropertySimple */'], + ['/* testTypeIntersectionPropertyReverseModifierOrder */'], + ['/* testTypeIntersectionPropertyMulti1 */'], + ['/* testTypeIntersectionPropertyMulti2 */'], + ['/* testTypeIntersectionPropertyMulti3 */'], + ['/* testTypeIntersectionPropertyNamespaceRelative */'], + ['/* testTypeIntersectionPropertyPartiallyQualified */'], + ['/* testTypeIntersectionPropertyFullyQualified */'], + ['/* testTypeIntersectionPropertyWithReadOnlyKeyword */'], + ['/* testTypeIntersectionParam1 */'], + ['/* testTypeIntersectionParam2 */'], + ['/* testTypeIntersectionParam3 */'], + ['/* testTypeIntersectionParamNamespaceRelative */'], + ['/* testTypeIntersectionParamPartiallyQualified */'], + ['/* testTypeIntersectionParamFullyQualified */'], + ['/* testTypeIntersectionReturnType */'], + ['/* testTypeIntersectionConstructorPropertyPromotion */'], + ['/* testTypeIntersectionAbstractMethodReturnType1 */'], + ['/* testTypeIntersectionAbstractMethodReturnType2 */'], + ['/* testTypeIntersectionReturnTypeNamespaceRelative */'], + ['/* testTypeIntersectionReturnPartiallyQualified */'], + ['/* testTypeIntersectionReturnFullyQualified */'], + ['/* testTypeIntersectionClosureParamIllegalNullable */'], + ['/* testTypeIntersectionWithReference */'], + ['/* testTypeIntersectionWithSpreadOperator */'], + ['/* testTypeIntersectionClosureReturn */'], + ['/* testTypeIntersectionArrowParam */'], + ['/* testTypeIntersectionArrowReturnType */'], + ['/* testTypeIntersectionNonArrowFunctionDeclaration */'], + ['/* testTypeIntersectionWithInvalidTypes */'], + ]; + + }//end dataTypeIntersection() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/UndoNamespacedNameSingleTokenTest.inc b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/UndoNamespacedNameSingleTokenTest.inc new file mode 100644 index 00000000..540f72c9 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizer/UndoNamespacedNameSingleTokenTest.inc @@ -0,0 +1,147 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class UndoNamespacedNameSingleTokenTest extends AbstractMethodUnitTest +{ + + + /** + * Test that identifier names are tokenized the same across PHP versions, based on the PHP 5/7 tokenization. + * + * @param string $testMarker The comment prefacing the test. + * @param array $expectedTokens The tokenization expected. + * + * @dataProvider dataIdentifierTokenization + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testIdentifierTokenization($testMarker, $expectedTokens) + { + $tokens = self::$phpcsFile->getTokens(); + $identifier = $this->getTargetToken($testMarker, constant($expectedTokens[0]['type'])); + + foreach ($expectedTokens as $key => $tokenInfo) { + $this->assertSame(constant($tokenInfo['type']), $tokens[$identifier]['code']); + $this->assertSame($tokenInfo['type'], $tokens[$identifier]['type']); + $this->assertSame($tokenInfo['content'], $tokens[$identifier]['content']); + + ++$identifier; + } + + }//end testIdentifierTokenization() + + + /** + * Data provider. + * + * @see testIdentifierTokenization() + * + * @return array + */ + public function dataIdentifierTokenization() + { + return [ + [ + '/* testNamespaceDeclaration */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Package', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testNamespaceDeclarationWithLevels */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'SubLevel', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Domain', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testUseStatement */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testUseStatementWithLevels */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Domain', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testFunctionUseStatement */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'function', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testFunctionUseStatementWithLevels */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'function', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_in_ns', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testConstantUseStatement */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'const', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'CONSTANT_NAME', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testConstantUseStatementWithLevels */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'const', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'OTHER_CONSTANT', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testMultiUseUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'UnqualifiedClassName', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + ], + ], + [ + '/* testMultiUsePartiallyQualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Sublevel', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'PartiallyClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testGroupUseStatement */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_OPEN_USE_GROUP', + 'content' => '{', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'AnotherDomain', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_grouped', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'const', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'CONSTANT_GROUPED', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Sub', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'YetAnotherDomain', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'SubLevelA', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_grouped_too', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'const', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'SubLevelB', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'CONSTANT_GROUPED_TOO', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_CLOSE_USE_GROUP', + 'content' => '}', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testClassName */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'MyClass', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testExtendedFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'FQN', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testImplementsRelative */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + ], + ], + [ + '/* testImplementsFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Fully', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Qualified', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + ], + ], + [ + '/* testImplementsUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Unqualified', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + ], + ], + [ + '/* testImplementsPartiallyQualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Sub', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testFunctionName */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testTypeDeclarationRelative */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_TYPE_UNION', + 'content' => '|', + ], + [ + 'type' => 'T_STRING', + 'content' => 'object', + ], + ], + ], + [ + '/* testTypeDeclarationFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Fully', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Qualified', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testTypeDeclarationUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Unqualified', + ], + [ + 'type' => 'T_TYPE_UNION', + 'content' => '|', + ], + [ + 'type' => 'T_FALSE', + 'content' => 'false', + ], + ], + ], + [ + '/* testTypeDeclarationPartiallyQualified */', + [ + [ + 'type' => 'T_NULLABLE', + 'content' => '?', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Sublevel', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testReturnTypeFQN */', + [ + [ + 'type' => 'T_NULLABLE', + 'content' => '?', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testFunctionCallRelative */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'NameSpace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testFunctionCallFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Package', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testFunctionCallUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testFunctionPartiallyQualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testCatchRelative */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'SubLevel', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Exception', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testCatchFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Exception', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testCatchUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Exception', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testCatchPartiallyQualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Exception', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testNewRelative */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testNewFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testNewUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testNewPartiallyQualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testDoubleColonRelative */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_DOUBLE_COLON', + 'content' => '::', + ], + ], + ], + [ + '/* testDoubleColonFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_DOUBLE_COLON', + 'content' => '::', + ], + ], + ], + [ + '/* testDoubleColonUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_DOUBLE_COLON', + 'content' => '::', + ], + ], + ], + [ + '/* testDoubleColonPartiallyQualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_DOUBLE_COLON', + 'content' => '::', + ], + ], + ], + [ + '/* testInstanceOfRelative */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testInstanceOfFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Full', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_CLOSE_PARENTHESIS', + 'content' => ')', + ], + ], + ], + [ + '/* testInstanceOfUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testInstanceOfPartiallyQualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Partially', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testInvalidInPHP8Whitespace */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Sublevel', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testInvalidInPHP8Comments */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Fully', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat.Sniff -- for reasons +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Qualified', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '/* comment */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + ]; + + }//end dataIdentifierTokenization() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/FileList.php b/vendor/squizlabs/php_codesniffer/tests/FileList.php new file mode 100644 index 00000000..8ef57b7a --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/FileList.php @@ -0,0 +1,94 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests; + +class FileList +{ + + /** + * The path to the project root directory. + * + * @var string + */ + protected $rootPath; + + /** + * Recursive directory iterator. + * + * @var \DirectoryIterator + */ + public $fileIterator; + + /** + * Base regex to use if no filter regex is provided. + * + * Matches based on: + * - File path starts with the project root (replacement done in constructor). + * - Don't match .git/ files. + * - Don't match dot files, i.e. "." or "..". + * - Don't match backup files. + * - Match everything else in a case-insensitive manner. + * + * @var string + */ + private $baseRegex = '`^%s(?!\.git/)(?!(.*/)?\.+$)(?!.*\.(bak|orig)).*$`Dix'; + + + /** + * Constructor. + * + * @param string $directory The directory to examine. + * @param string $rootPath Path to the project root. + * @param string $filter PCRE regular expression to filter the file list with. + */ + public function __construct($directory, $rootPath='', $filter='') + { + $this->rootPath = $rootPath; + + $directory = new \RecursiveDirectoryIterator( + $directory, + \RecursiveDirectoryIterator::UNIX_PATHS + ); + $flattened = new \RecursiveIteratorIterator( + $directory, + \RecursiveIteratorIterator::LEAVES_ONLY, + \RecursiveIteratorIterator::CATCH_GET_CHILD + ); + + if ($filter === '') { + $filter = sprintf($this->baseRegex, preg_quote($this->rootPath)); + } + + $this->fileIterator = new \RegexIterator($flattened, $filter); + + return $this; + + }//end __construct() + + + /** + * Retrieve the filtered file list as an array. + * + * @return array + */ + public function getList() + { + $fileList = []; + + foreach ($this->fileIterator as $file) { + $fileList[] = str_replace($this->rootPath, '', $file); + } + + return $fileList; + + }//end getList() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Standards/AbstractSniffUnitTest.php b/vendor/squizlabs/php_codesniffer/tests/Standards/AbstractSniffUnitTest.php new file mode 100644 index 00000000..c050a0c2 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Standards/AbstractSniffUnitTest.php @@ -0,0 +1,461 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Standards; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Files\LocalFile; +use PHP_CodeSniffer\Util\Common; +use PHPUnit\Framework\TestCase; + +abstract class AbstractSniffUnitTest extends TestCase +{ + + /** + * Enable or disable the backup and restoration of the $GLOBALS array. + * Overwrite this attribute in a child class of TestCase. + * Setting this attribute in setUp() has no effect! + * + * @var boolean + */ + protected $backupGlobals = false; + + /** + * The path to the standard's main directory. + * + * @var string + */ + public $standardsDir = null; + + /** + * The path to the standard's test directory. + * + * @var string + */ + public $testsDir = null; + + + /** + * Sets up this unit test. + * + * @return void + */ + protected function setUp() + { + $class = get_class($this); + $this->standardsDir = $GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'][$class]; + $this->testsDir = $GLOBALS['PHP_CODESNIFFER_TEST_DIRS'][$class]; + + }//end setUp() + + + /** + * Get a list of all test files to check. + * + * These will have the same base as the sniff name but different extensions. + * We ignore the .php file as it is the class. + * + * @param string $testFileBase The base path that the unit tests files will have. + * + * @return string[] + */ + protected function getTestFiles($testFileBase) + { + $testFiles = []; + + $dir = substr($testFileBase, 0, strrpos($testFileBase, DIRECTORY_SEPARATOR)); + $di = new \DirectoryIterator($dir); + + foreach ($di as $file) { + $path = $file->getPathname(); + if (substr($path, 0, strlen($testFileBase)) === $testFileBase) { + if ($path !== $testFileBase.'php' && substr($path, -5) !== 'fixed' && substr($path, -4) !== '.bak') { + $testFiles[] = $path; + } + } + } + + // Put them in order. + sort($testFiles); + + return $testFiles; + + }//end getTestFiles() + + + /** + * Should this test be skipped for some reason. + * + * @return boolean + */ + protected function shouldSkipTest() + { + return false; + + }//end shouldSkipTest() + + + /** + * Tests the extending classes Sniff class. + * + * @return void + * @throws \PHPUnit\Framework\Exception + */ + final public function testSniff() + { + // Skip this test if we can't run in this environment. + if ($this->shouldSkipTest() === true) { + $this->markTestSkipped(); + } + + $sniffCode = Common::getSniffCode(get_class($this)); + list($standardName, $categoryName, $sniffName) = explode('.', $sniffCode); + + $testFileBase = $this->testsDir.$categoryName.DIRECTORY_SEPARATOR.$sniffName.'UnitTest.'; + + // Get a list of all test files to check. + $testFiles = $this->getTestFiles($testFileBase); + $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES'][] = $testFiles; + + if (isset($GLOBALS['PHP_CODESNIFFER_CONFIG']) === true) { + $config = $GLOBALS['PHP_CODESNIFFER_CONFIG']; + } else { + $config = new Config(); + $config->cache = false; + $GLOBALS['PHP_CODESNIFFER_CONFIG'] = $config; + } + + $config->standards = [$standardName]; + $config->sniffs = [$sniffCode]; + $config->ignored = []; + + if (isset($GLOBALS['PHP_CODESNIFFER_RULESETS']) === false) { + $GLOBALS['PHP_CODESNIFFER_RULESETS'] = []; + } + + if (isset($GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName]) === false) { + $ruleset = new Ruleset($config); + $GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName] = $ruleset; + } + + $ruleset = $GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName]; + + $sniffFile = $this->standardsDir.DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR.$categoryName.DIRECTORY_SEPARATOR.$sniffName.'Sniff.php'; + + $sniffClassName = substr(get_class($this), 0, -8).'Sniff'; + $sniffClassName = str_replace('\Tests\\', '\Sniffs\\', $sniffClassName); + $sniffClassName = Common::cleanSniffClass($sniffClassName); + + $restrictions = [strtolower($sniffClassName) => true]; + $ruleset->registerSniffs([$sniffFile], $restrictions, []); + $ruleset->populateTokenListeners(); + + $failureMessages = []; + foreach ($testFiles as $testFile) { + $filename = basename($testFile); + $oldConfig = $config->getSettings(); + + try { + $this->setCliValues($filename, $config); + $phpcsFile = new LocalFile($testFile, $ruleset, $config); + $phpcsFile->process(); + } catch (RuntimeException $e) { + $this->fail('An unexpected exception has been caught: '.$e->getMessage()); + } + + $failures = $this->generateFailureMessages($phpcsFile); + $failureMessages = array_merge($failureMessages, $failures); + + if ($phpcsFile->getFixableCount() > 0) { + // Attempt to fix the errors. + $phpcsFile->fixer->fixFile(); + $fixable = $phpcsFile->getFixableCount(); + if ($fixable > 0) { + $failureMessages[] = "Failed to fix $fixable fixable violations in $filename"; + } + + // Check for a .fixed file to check for accuracy of fixes. + $fixedFile = $testFile.'.fixed'; + if (file_exists($fixedFile) === true) { + $diff = $phpcsFile->fixer->generateDiff($fixedFile); + if (trim($diff) !== '') { + $filename = basename($testFile); + $fixedFilename = basename($fixedFile); + $failureMessages[] = "Fixed version of $filename does not match expected version in $fixedFilename; the diff is\n$diff"; + } + } + } + + // Restore the config. + $config->setSettings($oldConfig); + }//end foreach + + if (empty($failureMessages) === false) { + $this->fail(implode(PHP_EOL, $failureMessages)); + } + + }//end testSniff() + + + /** + * Generate a list of test failures for a given sniffed file. + * + * @param \PHP_CodeSniffer\Files\LocalFile $file The file being tested. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException + */ + public function generateFailureMessages(LocalFile $file) + { + $testFile = $file->getFilename(); + + $foundErrors = $file->getErrors(); + $foundWarnings = $file->getWarnings(); + $expectedErrors = $this->getErrorList(basename($testFile)); + $expectedWarnings = $this->getWarningList(basename($testFile)); + + if (is_array($expectedErrors) === false) { + throw new RuntimeException('getErrorList() must return an array'); + } + + if (is_array($expectedWarnings) === false) { + throw new RuntimeException('getWarningList() must return an array'); + } + + /* + We merge errors and warnings together to make it easier + to iterate over them and produce the errors string. In this way, + we can report on errors and warnings in the same line even though + it's not really structured to allow that. + */ + + $allProblems = []; + $failureMessages = []; + + foreach ($foundErrors as $line => $lineErrors) { + foreach ($lineErrors as $column => $errors) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $foundErrorsTemp = []; + foreach ($allProblems[$line]['found_errors'] as $foundError) { + $foundErrorsTemp[] = $foundError; + } + + $errorsTemp = []; + foreach ($errors as $foundError) { + $errorsTemp[] = $foundError['message'].' ('.$foundError['source'].')'; + + $source = $foundError['source']; + if (in_array($source, $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'], true) === false) { + $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'][] = $source; + } + + if ($foundError['fixable'] === true + && in_array($source, $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'], true) === false + ) { + $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'][] = $source; + } + } + + $allProblems[$line]['found_errors'] = array_merge($foundErrorsTemp, $errorsTemp); + }//end foreach + + if (isset($expectedErrors[$line]) === true) { + $allProblems[$line]['expected_errors'] = $expectedErrors[$line]; + } else { + $allProblems[$line]['expected_errors'] = 0; + } + + unset($expectedErrors[$line]); + }//end foreach + + foreach ($expectedErrors as $line => $numErrors) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $allProblems[$line]['expected_errors'] = $numErrors; + } + + foreach ($foundWarnings as $line => $lineWarnings) { + foreach ($lineWarnings as $column => $warnings) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $foundWarningsTemp = []; + foreach ($allProblems[$line]['found_warnings'] as $foundWarning) { + $foundWarningsTemp[] = $foundWarning; + } + + $warningsTemp = []; + foreach ($warnings as $warning) { + $warningsTemp[] = $warning['message'].' ('.$warning['source'].')'; + + $source = $warning['source']; + if (in_array($source, $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'], true) === false) { + $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'][] = $source; + } + + if ($warning['fixable'] === true + && in_array($source, $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'], true) === false + ) { + $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'][] = $source; + } + } + + $allProblems[$line]['found_warnings'] = array_merge($foundWarningsTemp, $warningsTemp); + }//end foreach + + if (isset($expectedWarnings[$line]) === true) { + $allProblems[$line]['expected_warnings'] = $expectedWarnings[$line]; + } else { + $allProblems[$line]['expected_warnings'] = 0; + } + + unset($expectedWarnings[$line]); + }//end foreach + + foreach ($expectedWarnings as $line => $numWarnings) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $allProblems[$line]['expected_warnings'] = $numWarnings; + } + + // Order the messages by line number. + ksort($allProblems); + + foreach ($allProblems as $line => $problems) { + $numErrors = count($problems['found_errors']); + $numWarnings = count($problems['found_warnings']); + $expectedErrors = $problems['expected_errors']; + $expectedWarnings = $problems['expected_warnings']; + + $errors = ''; + $foundString = ''; + + if ($expectedErrors !== $numErrors || $expectedWarnings !== $numWarnings) { + $lineMessage = "[LINE $line]"; + $expectedMessage = 'Expected '; + $foundMessage = 'in '.basename($testFile).' but found '; + + if ($expectedErrors !== $numErrors) { + $expectedMessage .= "$expectedErrors error(s)"; + $foundMessage .= "$numErrors error(s)"; + if ($numErrors !== 0) { + $foundString .= 'error(s)'; + $errors .= implode(PHP_EOL.' -> ', $problems['found_errors']); + } + + if ($expectedWarnings !== $numWarnings) { + $expectedMessage .= ' and '; + $foundMessage .= ' and '; + if ($numWarnings !== 0) { + if ($foundString !== '') { + $foundString .= ' and '; + } + } + } + } + + if ($expectedWarnings !== $numWarnings) { + $expectedMessage .= "$expectedWarnings warning(s)"; + $foundMessage .= "$numWarnings warning(s)"; + if ($numWarnings !== 0) { + $foundString .= 'warning(s)'; + if (empty($errors) === false) { + $errors .= PHP_EOL.' -> '; + } + + $errors .= implode(PHP_EOL.' -> ', $problems['found_warnings']); + } + } + + $fullMessage = "$lineMessage $expectedMessage $foundMessage."; + if ($errors !== '') { + $fullMessage .= " The $foundString found were:".PHP_EOL." -> $errors"; + } + + $failureMessages[] = $fullMessage; + }//end if + }//end foreach + + return $failureMessages; + + }//end generateFailureMessages() + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $filename The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public function setCliValues($filename, $config) + { + return; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + abstract protected function getErrorList(); + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + abstract protected function getWarningList(); + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php b/vendor/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php new file mode 100644 index 00000000..24527dd5 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php @@ -0,0 +1,123 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Standards; + +use PHP_CodeSniffer\Util\Standards; +use PHP_CodeSniffer\Autoload; +use PHPUnit\TextUI\TestRunner; +use PHPUnit\Framework\TestSuite; + +class AllSniffs +{ + + + /** + * Prepare the test runner. + * + * @return void + */ + public static function main() + { + TestRunner::run(self::suite()); + + }//end main() + + + /** + * Add all sniff unit tests into a test suite. + * + * Sniff unit tests are found by recursing through the 'Tests' directory + * of each installed coding standard. + * + * @return \PHPUnit\Framework\TestSuite + */ + public static function suite() + { + $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'] = []; + $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'] = []; + $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES'] = []; + + $suite = new TestSuite('PHP CodeSniffer Standards'); + + $isInstalled = !is_file(__DIR__.'/../../autoload.php'); + + // Optionally allow for ignoring the tests for one or more standards. + $ignoreTestsForStandards = getenv('PHPCS_IGNORE_TESTS'); + if ($ignoreTestsForStandards === false) { + $ignoreTestsForStandards = []; + } else { + $ignoreTestsForStandards = explode(',', $ignoreTestsForStandards); + } + + $installedStandards = self::getInstalledStandardDetails(); + + foreach ($installedStandards as $standard => $details) { + Autoload::addSearchPath($details['path'], $details['namespace']); + + // If the test is running PEAR installed, the built-in standards + // are split into different directories; one for the sniffs and + // a different file system location for tests. + if ($isInstalled === true && is_dir(dirname($details['path']).DIRECTORY_SEPARATOR.'Generic') === true) { + $testPath = realpath(__DIR__.'/../../src/Standards/'.$standard); + } else { + $testPath = $details['path']; + } + + if (in_array($standard, $ignoreTestsForStandards, true) === true) { + continue; + } + + $testsDir = $testPath.DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR; + if (is_dir($testsDir) === false) { + // No tests for this standard. + continue; + } + + $di = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($testsDir)); + + foreach ($di as $file) { + // Skip hidden files. + if (substr($file->getFilename(), 0, 1) === '.') { + continue; + } + + // Tests must have the extension 'php'. + $parts = explode('.', $file); + $ext = array_pop($parts); + if ($ext !== 'php') { + continue; + } + + $className = Autoload::loadFile($file->getPathname()); + $GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'][$className] = $details['path']; + $GLOBALS['PHP_CODESNIFFER_TEST_DIRS'][$className] = $testsDir; + $suite->addTestSuite($className); + } + }//end foreach + + return $suite; + + }//end suite() + + + /** + * Get the details of all coding standards installed. + * + * @return array + * @see Standards::getInstalledStandardDetails() + */ + protected static function getInstalledStandardDetails() + { + return Standards::getInstalledStandardDetails(true); + + }//end getInstalledStandardDetails() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/TestSuite.php b/vendor/squizlabs/php_codesniffer/tests/TestSuite.php new file mode 100644 index 00000000..9eb269f8 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/TestSuite.php @@ -0,0 +1,35 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests; + +use PHPUnit\Framework\TestSuite as PHPUnit_TestSuite; +use PHPUnit\Framework\TestResult; + +class TestSuite extends PHPUnit_TestSuite +{ + + + /** + * Runs the tests and collects their result in a TestResult. + * + * @param \PHPUnit\Framework\TestResult $result A test result. + * + * @return \PHPUnit\Framework\TestResult + */ + public function run(TestResult $result=null) + { + $result = parent::run($result); + printPHPCodeSnifferTestOutput(); + return $result; + + }//end run() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/TestSuite7.php b/vendor/squizlabs/php_codesniffer/tests/TestSuite7.php new file mode 100644 index 00000000..43db293d --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/TestSuite7.php @@ -0,0 +1,35 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests; + +use PHPUnit\Framework\TestSuite as PHPUnit_TestSuite; +use PHPUnit\Framework\TestResult; + +class TestSuite extends PHPUnit_TestSuite +{ + + + /** + * Runs the tests and collects their result in a TestResult. + * + * @param \PHPUnit\Framework\TestResult $result A test result. + * + * @return \PHPUnit\Framework\TestResult + */ + public function run(TestResult $result=null): TestResult + { + $result = parent::run($result); + printPHPCodeSnifferTestOutput(); + return $result; + + }//end run() + + +}//end class diff --git a/vendor/squizlabs/php_codesniffer/tests/bootstrap.php b/vendor/squizlabs/php_codesniffer/tests/bootstrap.php new file mode 100644 index 00000000..47084d11 --- /dev/null +++ b/vendor/squizlabs/php_codesniffer/tests/bootstrap.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2017 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +if (defined('PHP_CODESNIFFER_IN_TESTS') === false) { + define('PHP_CODESNIFFER_IN_TESTS', true); +} + +if (defined('PHP_CODESNIFFER_CBF') === false) { + define('PHP_CODESNIFFER_CBF', false); +} + +if (defined('PHP_CODESNIFFER_VERBOSITY') === false) { + define('PHP_CODESNIFFER_VERBOSITY', 0); +} + +if (is_file(__DIR__.'/../autoload.php') === true) { + include_once __DIR__.'/../autoload.php'; +} else { + include_once 'PHP/CodeSniffer/autoload.php'; +} + +$tokens = new \PHP_CodeSniffer\Util\Tokens(); + +// Compatibility for PHPUnit < 6 and PHPUnit 6+. +if (class_exists('PHPUnit_Framework_TestSuite') === true && class_exists('PHPUnit\Framework\TestSuite') === false) { + class_alias('PHPUnit_Framework_TestSuite', 'PHPUnit'.'\Framework\TestSuite'); +} + +if (class_exists('PHPUnit_Framework_TestCase') === true && class_exists('PHPUnit\Framework\TestCase') === false) { + class_alias('PHPUnit_Framework_TestCase', 'PHPUnit'.'\Framework\TestCase'); +} + +if (class_exists('PHPUnit_TextUI_TestRunner') === true && class_exists('PHPUnit\TextUI\TestRunner') === false) { + class_alias('PHPUnit_TextUI_TestRunner', 'PHPUnit'.'\TextUI\TestRunner'); +} + +if (class_exists('PHPUnit_Framework_TestResult') === true && class_exists('PHPUnit\Framework\TestResult') === false) { + class_alias('PHPUnit_Framework_TestResult', 'PHPUnit'.'\Framework\TestResult'); +} + +// Determine whether this is a PEAR install or not. +$GLOBALS['PHP_CODESNIFFER_PEAR'] = false; + +if (is_file(__DIR__.'/../autoload.php') === false) { + $GLOBALS['PHP_CODESNIFFER_PEAR'] = true; +} + + +/** + * A global util function to help print unit test fixing data. + * + * @return void + */ +function printPHPCodeSnifferTestOutput() +{ + echo PHP_EOL.PHP_EOL; + + $output = 'The test files'; + $data = []; + + $codeCount = count($GLOBALS['PHP_CODESNIFFER_SNIFF_CODES']); + if (empty($GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES']) === false) { + $files = call_user_func_array('array_merge', $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES']); + $files = array_unique($files); + $fileCount = count($files); + + $output = '%d sniff test files'; + $data[] = $fileCount; + } + + $output .= ' generated %d unique error codes'; + $data[] = $codeCount; + + if ($codeCount > 0) { + $fixes = count($GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES']); + $percent = round(($fixes / $codeCount * 100), 2); + + $output .= '; %d were fixable (%d%%)'; + $data[] = $fixes; + $data[] = $percent; + } + + vprintf($output, $data); + +}//end printPHPCodeSnifferTestOutput() diff --git a/vendor/theseer/tokenizer/.php_cs.dist b/vendor/theseer/tokenizer/.php_cs.dist new file mode 100644 index 00000000..8ac26d09 --- /dev/null +++ b/vendor/theseer/tokenizer/.php_cs.dist @@ -0,0 +1,213 @@ +registerCustomFixers([ + new \PharIo\CSFixer\PhpdocSingleLineVarFixer() + ]) + ->setRiskyAllowed(true) + ->setRules( + [ + 'PharIo/phpdoc_single_line_var_fixer' => true, + + 'align_multiline_comment' => true, + 'array_indentation' => true, + 'array_syntax' => ['syntax' => 'short'], + 'binary_operator_spaces' => [ + 'operators' => [ + '=' => 'align_single_space_minimal', + '=>' => 'align', + ], + ], + 'blank_line_after_namespace' => true, + 'blank_line_after_opening_tag' => false, + 'blank_line_before_statement' => [ + 'statements' => [ + 'break', + 'continue', + 'declare', + 'do', + 'for', + 'foreach', + 'if', + 'include', + 'include_once', + 'require', + 'require_once', + 'return', + 'switch', + 'throw', + 'try', + 'while', + 'yield', + ], + ], + 'braces' => [ + 'allow_single_line_closure' => false, + 'position_after_anonymous_constructs' => 'same', + 'position_after_control_structures' => 'same', + 'position_after_functions_and_oop_constructs' => 'same' + ], + 'cast_spaces' => ['space' => 'none'], + + // This fixer removes the blank line at class start, no way to disable that, so we disable the fixer :( + //'class_attributes_separation' => ['elements' => ['const', 'method', 'property']], + + 'combine_consecutive_issets' => true, + 'combine_consecutive_unsets' => true, + 'compact_nullable_typehint' => true, + 'concat_space' => ['spacing' => 'one'], + 'date_time_immutable' => true, + 'declare_equal_normalize' => ['space' => 'single'], + 'declare_strict_types' => true, + 'dir_constant' => true, + 'elseif' => true, + 'encoding' => true, + 'full_opening_tag' => true, + 'fully_qualified_strict_types' => true, + 'function_declaration' => [ + 'closure_function_spacing' => 'one' + ], + 'header_comment' => false, + 'indentation_type' => true, + 'is_null' => true, + 'line_ending' => true, + 'list_syntax' => ['syntax' => 'short'], + 'logical_operators' => true, + 'lowercase_cast' => true, + 'lowercase_constants' => true, + 'lowercase_keywords' => true, + 'lowercase_static_reference' => true, + 'magic_constant_casing' => true, + 'method_argument_space' => ['ensure_fully_multiline' => true], + 'modernize_types_casting' => true, + 'multiline_comment_opening_closing' => true, + 'multiline_whitespace_before_semicolons' => true, + 'native_constant_invocation' => true, + 'native_function_casing' => true, + 'native_function_invocation' => true, + 'new_with_braces' => false, + 'no_alias_functions' => true, + 'no_alternative_syntax' => true, + 'no_blank_lines_after_class_opening' => false, + 'no_blank_lines_after_phpdoc' => true, + 'no_blank_lines_before_namespace' => true, + 'no_closing_tag' => true, + 'no_empty_comment' => true, + 'no_empty_phpdoc' => true, + 'no_empty_statement' => true, + 'no_extra_blank_lines' => true, + 'no_homoglyph_names' => true, + 'no_leading_import_slash' => true, + 'no_leading_namespace_whitespace' => true, + 'no_mixed_echo_print' => ['use' => 'print'], + 'no_multiline_whitespace_around_double_arrow' => true, + 'no_null_property_initialization' => true, + 'no_php4_constructor' => true, + 'no_short_bool_cast' => true, + 'no_short_echo_tag' => true, + 'no_singleline_whitespace_before_semicolons' => true, + 'no_spaces_after_function_name' => true, + 'no_spaces_inside_parenthesis' => true, + 'no_superfluous_elseif' => true, + 'no_superfluous_phpdoc_tags' => true, + 'no_trailing_comma_in_list_call' => true, + 'no_trailing_comma_in_singleline_array' => true, + 'no_trailing_whitespace' => true, + 'no_trailing_whitespace_in_comment' => true, + 'no_unneeded_control_parentheses' => false, + 'no_unneeded_curly_braces' => false, + 'no_unneeded_final_method' => true, + 'no_unreachable_default_argument_value' => true, + 'no_unset_on_property' => true, + 'no_unused_imports' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'no_whitespace_before_comma_in_array' => true, + 'no_whitespace_in_blank_line' => true, + 'non_printable_character' => true, + 'normalize_index_brace' => true, + 'object_operator_without_whitespace' => true, + 'ordered_class_elements' => [ + 'order' => [ + 'use_trait', + 'constant_public', + 'constant_protected', + 'constant_private', + 'property_public_static', + 'property_protected_static', + 'property_private_static', + 'property_public', + 'property_protected', + 'property_private', + 'method_public_static', + 'construct', + 'destruct', + 'magic', + 'phpunit', + 'method_public', + 'method_protected', + 'method_private', + 'method_protected_static', + 'method_private_static', + ], + ], + 'ordered_imports' => true, + 'phpdoc_add_missing_param_annotation' => true, + 'phpdoc_align' => true, + 'phpdoc_annotation_without_dot' => true, + 'phpdoc_indent' => true, + 'phpdoc_no_access' => true, + 'phpdoc_no_empty_return' => true, + 'phpdoc_no_package' => true, + 'phpdoc_order' => true, + 'phpdoc_return_self_reference' => true, + 'phpdoc_scalar' => true, + 'phpdoc_separation' => true, + 'phpdoc_single_line_var_spacing' => true, + 'phpdoc_to_comment' => false, + 'phpdoc_trim' => true, + 'phpdoc_trim_consecutive_blank_line_separation' => true, + 'phpdoc_types' => ['groups' => ['simple', 'meta']], + 'phpdoc_types_order' => true, + 'phpdoc_to_return_type' => true, + 'phpdoc_var_without_name' => true, + 'pow_to_exponentiation' => true, + 'protected_to_private' => true, + 'return_assignment' => true, + 'return_type_declaration' => ['space_before' => 'none'], + 'self_accessor' => false, + 'semicolon_after_instruction' => true, + 'set_type_to_cast' => true, + 'short_scalar_cast' => true, + 'simplified_null_return' => true, + 'single_blank_line_at_eof' => true, + 'single_import_per_statement' => true, + 'single_line_after_imports' => true, + 'single_quote' => true, + 'standardize_not_equals' => true, + 'ternary_to_null_coalescing' => true, + 'trailing_comma_in_multiline_array' => false, + 'trim_array_spaces' => true, + 'unary_operator_spaces' => true, + 'visibility_required' => [ + 'elements' => [ + 'const', + 'method', + 'property', + ], + ], + 'void_return' => true, + 'whitespace_after_comma_in_array' => true, + 'yoda_style' => false + ] + ) + ->setFinder( + PhpCsFixer\Finder::create() + ->files() + ->in(__DIR__ . '/src') + ->in(__DIR__ . '/tests') + ->notName('*.phpt') + ->notName('autoload.php') + ); diff --git a/vendor/theseer/tokenizer/CHANGELOG.md b/vendor/theseer/tokenizer/CHANGELOG.md new file mode 100644 index 00000000..1eff3830 --- /dev/null +++ b/vendor/theseer/tokenizer/CHANGELOG.md @@ -0,0 +1,71 @@ +# Changelog + +All notable changes to Tokenizer are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + + +## [1.2.1] - 2021-07-28 + +### Fixed + +* [#13](https://github.com/theseer/tokenizer/issues/13): Fatal error when tokenizing files that contain only a single empty line + + +## [1.2.0] - 2020-07-13 + +This release is now PHP 8.0 compliant. + +### Fixed + +* Whitespace handling in general (only noticable in the intermediate `TokenCollection`) is now consitent + +### Changed + +* Updated `Tokenizer` to deal with changed whitespace handling in PHP 8.0 + The XMLSerializer was unaffected. + + +## [1.1.3] - 2019-06-14 + +### Changed + +* Ensure XMLSerializer can deal with empty token collections + +### Fixed + +* [#2](https://github.com/theseer/tokenizer/issues/2): Fatal error in infection / phpunit + + +## [1.1.2] - 2019-04-04 + +### Changed + +* Reverted PHPUnit 8 test update to stay PHP 7.0 compliant + + +## [1.1.1] - 2019-04-03 + +### Fixed + +* [#1](https://github.com/theseer/tokenizer/issues/1): Empty file causes invalid array read + +### Changed + +* Tests should now be PHPUnit 8 compliant + + +## [1.1.0] - 2017-04-07 + +### Added + +* Allow use of custom namespace for XML serialization + + +## [1.0.0] - 2017-04-05 + +Initial Release + +[1.1.3]: https://github.com/theseer/tokenizer/compare/1.1.2...1.1.3 +[1.1.2]: https://github.com/theseer/tokenizer/compare/1.1.1...1.1.2 +[1.1.1]: https://github.com/theseer/tokenizer/compare/1.1.0...1.1.1 +[1.1.0]: https://github.com/theseer/tokenizer/compare/1.0.0...1.1.0 +[1.0.0]: https://github.com/theseer/tokenizer/compare/b2493e57de80c1b7414219b28503fa5c6b4d0a98...1.0.0 diff --git a/vendor/theseer/tokenizer/LICENSE b/vendor/theseer/tokenizer/LICENSE new file mode 100644 index 00000000..e9694ad6 --- /dev/null +++ b/vendor/theseer/tokenizer/LICENSE @@ -0,0 +1,30 @@ +Tokenizer + +Copyright (c) 2017 Arne Blankerts and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of Arne Blankerts nor the names of contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/theseer/tokenizer/README.md b/vendor/theseer/tokenizer/README.md new file mode 100644 index 00000000..e91ed891 --- /dev/null +++ b/vendor/theseer/tokenizer/README.md @@ -0,0 +1,50 @@ +# Tokenizer + +A small library for converting tokenized PHP source code into XML. + +[![Test](https://github.com/theseer/tokenizer/actions/workflows/ci.yml/badge.svg)](https://github.com/theseer/tokenizer/actions/workflows/ci.yml) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/theseer/tokenizer/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/theseer/tokenizer/?branch=master) +[![Code Coverage](https://scrutinizer-ci.com/g/theseer/tokenizer/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/theseer/tokenizer/?branch=master) +[![Build Status](https://scrutinizer-ci.com/g/theseer/tokenizer/badges/build.png?b=master)](https://scrutinizer-ci.com/g/theseer/tokenizer/build-status/master) + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + + composer require theseer/tokenizer + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + + composer require --dev theseer/tokenizer + +## Usage examples + +```php +$tokenizer = new TheSeer\Tokenizer\Tokenizer(); +$tokens = $tokenizer->parse(file_get_contents(__DIR__ . '/src/XMLSerializer.php')); + +$serializer = new TheSeer\Tokenizer\XMLSerializer(); +$xml = $serializer->toXML($tokens); + +echo $xml; +``` + +The generated XML structure looks something like this: + +```xml + + + + <?php + declare + ( + strict_types + + = + + 1 + ) + ; + + +``` diff --git a/vendor/theseer/tokenizer/composer.json b/vendor/theseer/tokenizer/composer.json new file mode 100644 index 00000000..3f452a9f --- /dev/null +++ b/vendor/theseer/tokenizer/composer.json @@ -0,0 +1,27 @@ +{ + "name": "theseer/tokenizer", + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "support": { + "issues": "https://github.com/theseer/tokenizer/issues" + }, + "require": { + "php": "^7.2 || ^8.0", + "ext-xmlwriter": "*", + "ext-dom": "*", + "ext-tokenizer": "*" + }, + "autoload": { + "classmap": [ + "src/" + ] + } +} + diff --git a/vendor/theseer/tokenizer/composer.lock b/vendor/theseer/tokenizer/composer.lock new file mode 100644 index 00000000..07fba9b5 --- /dev/null +++ b/vendor/theseer/tokenizer/composer.lock @@ -0,0 +1,22 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "b010f1b3d9d47d431ee1cb54ac1de755", + "packages": [], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.2 || ^8.0", + "ext-xmlwriter": "*", + "ext-dom": "*", + "ext-tokenizer": "*" + }, + "platform-dev": [] +} diff --git a/vendor/theseer/tokenizer/src/Exception.php b/vendor/theseer/tokenizer/src/Exception.php new file mode 100644 index 00000000..71fc117a --- /dev/null +++ b/vendor/theseer/tokenizer/src/Exception.php @@ -0,0 +1,5 @@ +ensureValidUri($value); + $this->value = $value; + } + + public function asString(): string { + return $this->value; + } + + private function ensureValidUri($value): void { + if (\strpos($value, ':') === false) { + throw new NamespaceUriException( + \sprintf("Namespace URI '%s' must contain at least one colon", $value) + ); + } + } +} diff --git a/vendor/theseer/tokenizer/src/NamespaceUriException.php b/vendor/theseer/tokenizer/src/NamespaceUriException.php new file mode 100644 index 00000000..ab1c48d2 --- /dev/null +++ b/vendor/theseer/tokenizer/src/NamespaceUriException.php @@ -0,0 +1,5 @@ +line = $line; + $this->name = $name; + $this->value = $value; + } + + public function getLine(): int { + return $this->line; + } + + public function getName(): string { + return $this->name; + } + + public function getValue(): string { + return $this->value; + } +} diff --git a/vendor/theseer/tokenizer/src/TokenCollection.php b/vendor/theseer/tokenizer/src/TokenCollection.php new file mode 100644 index 00000000..e5e6e401 --- /dev/null +++ b/vendor/theseer/tokenizer/src/TokenCollection.php @@ -0,0 +1,93 @@ +tokens[] = $token; + } + + public function current(): Token { + return \current($this->tokens); + } + + public function key(): int { + return \key($this->tokens); + } + + public function next(): void { + \next($this->tokens); + $this->pos++; + } + + public function valid(): bool { + return $this->count() > $this->pos; + } + + public function rewind(): void { + \reset($this->tokens); + $this->pos = 0; + } + + public function count(): int { + return \count($this->tokens); + } + + public function offsetExists($offset): bool { + return isset($this->tokens[$offset]); + } + + /** + * @throws TokenCollectionException + */ + public function offsetGet($offset): Token { + if (!$this->offsetExists($offset)) { + throw new TokenCollectionException( + \sprintf('No Token at offest %s', $offset) + ); + } + + return $this->tokens[$offset]; + } + + /** + * @param Token $value + * + * @throws TokenCollectionException + */ + public function offsetSet($offset, $value): void { + if (!\is_int($offset)) { + $type = \gettype($offset); + + throw new TokenCollectionException( + \sprintf( + 'Offset must be of type integer, %s given', + $type === 'object' ? \get_class($value) : $type + ) + ); + } + + if (!$value instanceof Token) { + $type = \gettype($value); + + throw new TokenCollectionException( + \sprintf( + 'Value must be of type %s, %s given', + Token::class, + $type === 'object' ? \get_class($value) : $type + ) + ); + } + $this->tokens[$offset] = $value; + } + + public function offsetUnset($offset): void { + unset($this->tokens[$offset]); + } +} diff --git a/vendor/theseer/tokenizer/src/TokenCollectionException.php b/vendor/theseer/tokenizer/src/TokenCollectionException.php new file mode 100644 index 00000000..4291ce0c --- /dev/null +++ b/vendor/theseer/tokenizer/src/TokenCollectionException.php @@ -0,0 +1,5 @@ + 'T_OPEN_BRACKET', + ')' => 'T_CLOSE_BRACKET', + '[' => 'T_OPEN_SQUARE', + ']' => 'T_CLOSE_SQUARE', + '{' => 'T_OPEN_CURLY', + '}' => 'T_CLOSE_CURLY', + ';' => 'T_SEMICOLON', + '.' => 'T_DOT', + ',' => 'T_COMMA', + '=' => 'T_EQUAL', + '<' => 'T_LT', + '>' => 'T_GT', + '+' => 'T_PLUS', + '-' => 'T_MINUS', + '*' => 'T_MULT', + '/' => 'T_DIV', + '?' => 'T_QUESTION_MARK', + '!' => 'T_EXCLAMATION_MARK', + ':' => 'T_COLON', + '"' => 'T_DOUBLE_QUOTES', + '@' => 'T_AT', + '&' => 'T_AMPERSAND', + '%' => 'T_PERCENT', + '|' => 'T_PIPE', + '$' => 'T_DOLLAR', + '^' => 'T_CARET', + '~' => 'T_TILDE', + '`' => 'T_BACKTICK' + ]; + + public function parse(string $source): TokenCollection { + $result = new TokenCollection(); + + if ($source === '') { + return $result; + } + + $tokens = \token_get_all($source); + + $lastToken = new Token( + $tokens[0][2], + 'Placeholder', + '' + ); + + foreach ($tokens as $pos => $tok) { + if (\is_string($tok)) { + $token = new Token( + $lastToken->getLine(), + $this->map[$tok], + $tok + ); + $result->addToken($token); + $lastToken = $token; + + continue; + } + + $line = $tok[2]; + $values = \preg_split('/\R+/Uu', $tok[1]); + + foreach ($values as $v) { + $token = new Token( + $line, + \token_name($tok[0]), + $v + ); + $lastToken = $token; + $line++; + + if ($v === '') { + continue; + } + + $result->addToken($token); + } + } + + return $this->fillBlanks($result, $lastToken->getLine()); + } + + private function fillBlanks(TokenCollection $tokens, int $maxLine): TokenCollection { + $prev = new Token( + 0, + 'Placeholder', + '' + ); + + $final = new TokenCollection(); + + foreach ($tokens as $token) { + if ($prev === null) { + $final->addToken($token); + $prev = $token; + + continue; + } + + $gap = $token->getLine() - $prev->getLine(); + + while ($gap > 1) { + $linebreak = new Token( + $prev->getLine() + 1, + 'T_WHITESPACE', + '' + ); + $final->addToken($linebreak); + $prev = $linebreak; + $gap--; + } + + $final->addToken($token); + $prev = $token; + } + + $gap = $maxLine - $prev->getLine(); + + while ($gap > 0) { + $linebreak = new Token( + $prev->getLine() + 1, + 'T_WHITESPACE', + '' + ); + $final->addToken($linebreak); + $prev = $linebreak; + $gap--; + } + + return $final; + } +} diff --git a/vendor/theseer/tokenizer/src/XMLSerializer.php b/vendor/theseer/tokenizer/src/XMLSerializer.php new file mode 100644 index 00000000..e67a7fe8 --- /dev/null +++ b/vendor/theseer/tokenizer/src/XMLSerializer.php @@ -0,0 +1,79 @@ +xmlns = $xmlns; + } + + public function toDom(TokenCollection $tokens): DOMDocument { + $dom = new DOMDocument(); + $dom->preserveWhiteSpace = false; + $dom->loadXML($this->toXML($tokens)); + + return $dom; + } + + public function toXML(TokenCollection $tokens): string { + $this->writer = new \XMLWriter(); + $this->writer->openMemory(); + $this->writer->setIndent(true); + $this->writer->startDocument(); + $this->writer->startElement('source'); + $this->writer->writeAttribute('xmlns', $this->xmlns->asString()); + + if (\count($tokens) > 0) { + $this->writer->startElement('line'); + $this->writer->writeAttribute('no', '1'); + + $this->previousToken = $tokens[0]; + + foreach ($tokens as $token) { + $this->addToken($token); + } + } + + $this->writer->endElement(); + $this->writer->endElement(); + $this->writer->endDocument(); + + return $this->writer->outputMemory(); + } + + private function addToken(Token $token): void { + if ($this->previousToken->getLine() < $token->getLine()) { + $this->writer->endElement(); + + $this->writer->startElement('line'); + $this->writer->writeAttribute('no', (string)$token->getLine()); + $this->previousToken = $token; + } + + if ($token->getValue() !== '') { + $this->writer->startElement('token'); + $this->writer->writeAttribute('name', $token->getName()); + $this->writer->writeRaw(\htmlspecialchars($token->getValue(), \ENT_NOQUOTES | \ENT_DISALLOWED | \ENT_XML1)); + $this->writer->endElement(); + } + } +} diff --git a/vendor/togos/gitignore/.gitignore b/vendor/togos/gitignore/.gitignore new file mode 100644 index 00000000..ff72e2d0 --- /dev/null +++ b/vendor/togos/gitignore/.gitignore @@ -0,0 +1,2 @@ +/composer.lock +/vendor diff --git a/vendor/togos/gitignore/Makefile b/vendor/togos/gitignore/Makefile new file mode 100644 index 00000000..3f547218 --- /dev/null +++ b/vendor/togos/gitignore/Makefile @@ -0,0 +1,13 @@ +default: run-unit-tests + +.PHONY: run-unit-tests + +composer.lock: | composer.json + composer install + +vendor: composer.lock + composer install + touch "$@" + +run-unit-tests: vendor + vendor/bin/phpsimplertest --bootstrap vendor/autoload.php src/test/ --colorful-output diff --git a/vendor/togos/gitignore/composer.json b/vendor/togos/gitignore/composer.json new file mode 100644 index 00000000..b5df8a8c --- /dev/null +++ b/vendor/togos/gitignore/composer.json @@ -0,0 +1,27 @@ +{ + "name": "togos/gitignore", + "description": "Parser for .gitignore (and sparse-checkout, and anything else using the same format) files", + "license": "MIT", + + "require": { + "php": ">=5.2" + }, + "autoload": { + "psr-0": { + "TOGoS_GitIgnore_": "src/main/php/" + } + }, + + + "require-dev": { + "togos/simpler-test": "1.1.1" + }, + "autoload-dev": { + "psr-0": { + "TOGoS_GitIgnore_": "src/test/php/" + } + }, + "scripts": { + "test": "vendor/bin/phpsimplertest --colorful-output --bootstrap vendor/autoload.php src/test/" + } +} diff --git a/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/FileFinder.php b/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/FileFinder.php new file mode 100644 index 00000000..a4769376 --- /dev/null +++ b/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/FileFinder.php @@ -0,0 +1,42 @@ +ruleset = $options['ruleset']; + $this->invertRulesetResult = $options['invertRulesetResult']; + $this->defaultResult = $options['defaultResult']; + $this->includeDirectories = $options['includeDirectories']; + $this->callback = $options['callback']; + } + + protected function match($rootDir, $f) { + $result = $this->ruleset->match($f); + if( $this->invertRulesetResult and $result !== null ) $result = !$result; + return $result === null ? $this->defaultResult : $result; + } + + protected function _findFiles($rootDir, $f) { + if( preg_match('#/$#', $rootDir) ) throw new Exception("Root directory argument to _findFiles should not end with a slash; given «{$rootDir}»"); + if( preg_match('#^/|/$#', $f) ) throw new Exception("Relative path argument to _findFiles should not start or end with a slash; given «{$f}»"); + //echo "_findFiles($rootDir, $f)\n"; + $fullPath = $f == '' ? $rootDir : $rootDir.'/'.$f; + if( $this->includeDirectories or !is_dir($fullPath) ) { + $result = $this->match($rootDir, $f); + call_user_func($this->callback, $f, $result); + } + if( is_dir($fullPath) ) { + $dh = opendir($fullPath); + while( ($fn = readdir($dh)) !== false ) { + if( $fn == '.' or $fn == '..' ) continue; + $this->_findFiles($rootDir, $f == '' ? $fn : $f.'/'.$fn); + } + closedir($dh); + } + } + + public function findFiles($dir) { + self::_findFiles($dir, ''); + } +} \ No newline at end of file diff --git a/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/Pattern.php b/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/Pattern.php new file mode 100644 index 00000000..10b9ab0c --- /dev/null +++ b/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/Pattern.php @@ -0,0 +1,56 @@ +patternString = $pattern; + $this->regex = $regex; + } + + public function getPatternString() { + return $this->patternString; + } + + protected static function patternToRegex($pp) { + preg_match_all('/\*|\*\*|\?|[^\*\?]|\[![^\]+]|\[[^\]+]/', $pp, $bifs); + $regex = ''; + foreach( $bifs[0] as $part ) { + if( $part == '**' ) $regex .= ".*"; + else if( $part == '*' ) $regex .= "[^/]*"; + else if( $part == '?' ) $regex .= '?'; + else if( $part[0] == '[' ) { + // Not exactly, but maybe close enough. + // Maybe fnmatch is the thing to use + if( $part[1] == '!' ) $part[1] = '^'; + $regex .= $part; + } + else $regex .= preg_quote($part, '#'); + } + return $regex; + } + + public static function parse($pattern) { + $r = self::patternToRegex($pattern); + if( strlen($pattern) == 0 ) { + throw new Exception("Zero-length pattern string passed to ".__METHOD__); + } + if( $pattern[0] == '/' ) { + $r = '#^'.substr($r,1).'(?:$|/)#'; + } else { + $r = '#(?:^|/)'.$r.'(?:$|/)#'; + } + return new self($pattern, $r); + } + + public function match($path) { + if( strlen($path) > 0 and $path[0] == '/' ) { + throw new Exception("Paths passed to #match should not start with a slash; given: «".$path."»"); + } + if( !is_string($path) ) { + throw new Exception(__METHOD__." expects a string; given ".TOGoS_GitIgnore_Util::describe($path)); + } + return preg_match($this->regex, $path); + } +} diff --git a/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/Rule.php b/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/Rule.php new file mode 100644 index 00000000..3b09bcd5 --- /dev/null +++ b/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/Rule.php @@ -0,0 +1,33 @@ +pattern = $pattern; + $this->isExclusion = $isExclusion; + } + + /** @return true: include this file, false: exclude this file, null: rule does not apply to this file */ + public function match($path) { + if( !is_string($path) ) { + throw new Exception(__METHOD__." expects a string; given ".TOGoS_GitIgnore_Util::describe($path)); + } + if( $this->pattern->match($path) ) { + return $this->isExclusion ? false : true; + } + return null; + } + + public static function parse($str) { + $isExclusion = false; + if( $str[0] == '!' ) { + $isExclusion = true; + $str = substr($str, 1); + } + $pattern = TOGoS_GitIgnore_Pattern::parse($str); + return new self($pattern, $isExclusion); + } +} diff --git a/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/Ruleset.php b/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/Ruleset.php new file mode 100644 index 00000000..19b99cae --- /dev/null +++ b/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/Ruleset.php @@ -0,0 +1,51 @@ +rules[] = $rule; + } + + public function match($path) { + if( !is_string($path) ) { + throw new Exception(__METHOD__." expects a string; given ".TOGoS_GitIgnore_Util::describe($path)); + } + $lastResult = null; + foreach( $this->rules as $rule ) { + $result = $rule->match($path); + if( $result !== null ) $lastResult = $result; + } + return $lastResult; + } + + public static function loadFromStrings($lines) { + $rs = new self; + foreach( $lines as $line ) $rs->addRule($line); + return $rs; + } + + public static function loadFromString($str) { + $lines = explode("\n", $str); + return self::loadFromStrings($lines); + } + + public static function loadFromFile($filename) { + $rs = new self; + $fh = fopen($filename); + while( ($line = fgets($fh)) ) $rs->addRule($line); + fclose($fh); + return $rs; + } +} diff --git a/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/Util.php b/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/Util.php new file mode 100644 index 00000000..f4282ac7 --- /dev/null +++ b/vendor/togos/gitignore/src/main/php/TOGoS/GitIgnore/Util.php @@ -0,0 +1,17 @@ +results[$f] = $result; + } + + protected function assertKeyedequals($expectedValue, $array, $key) { + $this->assertTrue( array_key_exists($key, $array), "Expected key '$key' to be present in array" ); + $this->assertEquals($expectedValue, $array[$key]); + } + + public function testSparsenessConfig() { + $finder = new TOGoS_GitIgnore_FileFinder(array( + 'ruleset' => TOGoS_GitIgnore_Ruleset::loadFromStrings(array( + '*', + '!test1.ruleset', + '/test-dir', + '!b.txt', + )), + 'invertRulesetResult' => false, + 'defaultResult' => false, + 'includeDirectories' => false, + 'callback' => array($this,'addResult') + )); + + $this->results = array(); + $finder->findFiles(__DIR__); + + $this->assertFalse(array_key_exists("test-dir", $this->results)); + $this->assertKeyedEquals(true , $this->results, "FileFinderTest.php"); + //$this->assertKeyedEquals(false, $this->results, "FileFinderTest.php~"); + $this->assertKeyedEquals(true , $this->results, "test-dir/a.txt"); + $this->assertKeyedEquals(false, $this->results, "test-dir/b.txt"); + $this->assertKeyedEquals(false, $this->results, "test1.ruleset"); + } +} diff --git a/vendor/togos/gitignore/src/test/php/TOGoS/GitIgnore/RulesetTest.php b/vendor/togos/gitignore/src/test/php/TOGoS/GitIgnore/RulesetTest.php new file mode 100644 index 00000000..b825e409 --- /dev/null +++ b/vendor/togos/gitignore/src/test/php/TOGoS/GitIgnore/RulesetTest.php @@ -0,0 +1,29 @@ + true, 'input' => $bif[1]); + } else if( preg_match('/^# should not match: (.*)$/', $line, $bif) ) { + $cases[] = array('expectedOutput' => false, 'input' => $bif[1]); + } + } + return $cases; + } + + public function testIt() { + $rules1Content = file_get_contents(__DIR__.'/test1.ruleset'); + $ruleset = TOGoS_GitIgnore_Ruleset::loadFromString($rules1Content); + $testCases = $this->parseTestCases($rules1Content); + foreach( $testCases as $case ) { + $shouldMatch = $case['expectedOutput']; + $doesMatch = $ruleset->match($case['input']); + if( $doesMatch === null ) $doesMatch = false; + $this->assertEquals($shouldMatch, $doesMatch, "Expected '{$case['input']}' to ".($shouldMatch ? "match" : "not match")); + } + } +} diff --git a/vendor/togos/gitignore/src/test/php/TOGoS/GitIgnore/test-dir/a.txt b/vendor/togos/gitignore/src/test/php/TOGoS/GitIgnore/test-dir/a.txt new file mode 100644 index 00000000..b6fd0f69 --- /dev/null +++ b/vendor/togos/gitignore/src/test/php/TOGoS/GitIgnore/test-dir/a.txt @@ -0,0 +1 @@ +Hi I'm test file A. diff --git a/vendor/togos/gitignore/src/test/php/TOGoS/GitIgnore/test-dir/b.txt b/vendor/togos/gitignore/src/test/php/TOGoS/GitIgnore/test-dir/b.txt new file mode 100644 index 00000000..23181f60 --- /dev/null +++ b/vendor/togos/gitignore/src/test/php/TOGoS/GitIgnore/test-dir/b.txt @@ -0,0 +1 @@ +Hi I'm test file B. diff --git a/vendor/togos/gitignore/src/test/php/TOGoS/GitIgnore/test1.ruleset b/vendor/togos/gitignore/src/test/php/TOGoS/GitIgnore/test1.ruleset new file mode 100644 index 00000000..6f567b0c --- /dev/null +++ b/vendor/togos/gitignore/src/test/php/TOGoS/GitIgnore/test1.ruleset @@ -0,0 +1,26 @@ +# A comment line! +# The following should be ignored, not match '#foo.txt' +#foo.txt +# And here's some blank lines: + + +# any file.txt, in any subdirectory: +file.txt +# Any file called 'bar' anywhere under any [sub]directory called 'foo' +foo/**/bar +# Unless it's specifically this one: +!/foo/sux/bar +# or one of these: +!batch/bar + +## Test cases +# should not match: #foo.txt +# should match: file.txt +# should match: soup/file.txt +# should not match: bile.txt +# should not match: file +# should match: foo/anxiety/bar +# should match: kangaroo/foo/stuff/bar +# should not match: foo/sux/bar +# should not match: batch/bar +# should not match: foo/batch/bar diff --git a/vendor/wp-coding-standards/wpcs/.gitattributes b/vendor/wp-coding-standards/wpcs/.gitattributes new file mode 100644 index 00000000..c12f94cf --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/.gitattributes @@ -0,0 +1,25 @@ +# +# Exclude these files from release archives. +# This will also make them unavailable when using Composer with `--prefer-dist`. +# If you develop for WPCS using Composer, use `--prefer-source`. +# https://blog.madewithlove.be/post/gitattributes/ +# +/.travis.yml export-ignore +/.phpcs.xml.dist export-ignore +/phpunit.xml.dist export-ignore +/.github export-ignore +/bin export-ignore +/WordPress/Tests export-ignore + +# +# Auto detect text files and perform LF normalization +# http://davidlaing.com/2012/09/19/customise-your-gitattributes-to-become-a-git-ninja/ +# +* text=auto + +# +# The above will handle all files NOT found below +# +*.md text +*.php text +*.inc text diff --git a/vendor/wp-coding-standards/wpcs/.gitignore b/vendor/wp-coding-standards/wpcs/.gitignore new file mode 100644 index 00000000..bfec4c3c --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/.gitignore @@ -0,0 +1,5 @@ +vendor +composer.lock +phpunit.xml +phpcs.xml +.phpcs.xml diff --git a/vendor/wp-coding-standards/wpcs/CHANGELOG.md b/vendor/wp-coding-standards/wpcs/CHANGELOG.md new file mode 100644 index 00000000..f8c8c987 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/CHANGELOG.md @@ -0,0 +1,1208 @@ +# Change Log for WordPress Coding Standards + +All notable changes to this project will be documented in this file. + +This projects adheres to [Semantic Versioning](https://semver.org/) and [Keep a CHANGELOG](https://keepachangelog.com/). + +## [Unreleased] + +_No documentation available about unreleased changes as of yet._ + +## [2.3.0] - 2020-05-14 + +### Added +- The `WordPress.WP.I18n` sniff contains a new check for translatable text strings which are wrapped in HTML tags, like `

    Translate me

    `. Those tags should be moved out of the translatable string. + Note: Translatable strings wrapped in `
    ` tags where the URL is intended to be localized will not trigger this check. + +### Changed +- The default value for `minimum_supported_wp_version`, as used by a [number of sniffs detecting usage of deprecated WP features](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#minimum-wp-version-to-check-for-usage-of-deprecated-functions-classes-and-function-parameters), has been updated to `5.1`. +- The `WordPress.WP.DeprecatedFunctions` sniff will now detect functions deprecated in WP 5.4. +- Improved grammar of an error message in the `WordPress.WP.DiscouragedFunctions` sniff. +- CI: The codebase is now - preliminary - being tested against the PHPCS 4.x development branch. + +### Fixed +- All function call detection sniffs: fixed a bug where constants with the same name as one of the targeted functions could inadvertently be recognized as if they were a called function. +- `WordPress.DB.PreparedSQL`: fixed a bug where the sniff would trigger on the namespace separator character `\\`. +- `WordPress.Security.EscapeOutput`: fixed a bug with the variable replacement in one of the error messages. + + +## [2.2.1] - 2020-02-04 + +### Added +- Metrics to the `WordPress.Arrays.CommaAfterArrayItem` sniff. These can be displayed using `--report=info`. +- The `sanitize_hex_color()` and the `sanitize_hex_color_no_hash()` functions to the `escapingFunctions` list used by the `WordPress.Security.EscapeOutput` sniff. + +### Changed +- The recommended version of the suggested DealerDirect PHPCS Composer plugin is now `^0.6`. + +### Fixed +- `WordPress.PHP.NoSilencedErrors`: depending on the custom properties set, the metrics would be different. +- `WordPress.WhiteSpace.ControlStructureSpacing`: fixed undefined index notice for closures with `use`. +- `WordPress.WP.GlobalVariablesOverride`: fixed undefined offset notice when the `treat_files_as_scoped` property would be set to `true`. +- `WordPress.WP.I18n`: fixed a _Trying to access array offset on value of type null_ error when the sniff was run on PHP 7.4 and would encounter a translation function expecting singular and plural texts for which one of these arguments was missing. + +## [2.2.0] - 2019-11-11 + +Note: The repository has moved. The new URL is https://github.com/WordPress/WordPress-Coding-Standards. +The move does not affect the package name for Packagist. This remains the same: `wp-coding-standards/wpcs`. + +### Added +- New `WordPress.DateTime.CurrentTimeTimestamp` sniff to the `WordPress-Core` ruleset, which checks against the use of the WP native `current_time()` function to retrieve a timestamp as this won't be a _real_ timestamp. Includes an auto-fixer. +- New `WordPress.DateTime.RestrictedFunctions` sniff to the `WordPress-Core` ruleset, which checks for the use of certain date/time related functions. Initially this sniff forbids the use of the PHP native `date_default_timezone_set()` and `date()` functions. +- New `WordPress.PHP.DisallowShortTernary` sniff to the `WordPress-Core` ruleset, which, as the name implies, disallows the use of short ternaries. +- New `WordPress.CodeAnalysis.EscapedNotTranslated` sniff to the `WordPress-Extra` ruleset which will warn when a text string is escaped for output, but not being translated, while the arguments passed to the function call give the impression that translation is intended. +- New `WordPress.NamingConventions.ValidPostTypeSlug` sniff to the `WordPress-Extra` ruleset which will examine calls to `register_post_type()` and throw errors when an invalid post type slug is used. +- `Generic.Arrays.DisallowShortArraySyntax` to the `WordPress-Core` ruleset. +- `WordPress.NamingConventions.PrefixAllGlobals`: the `PHP` prefix has been added to the prefix blacklist as it is reserved by PHP itself. +- The `wp_sanitize_redirect()` function to the `sanitizingFunctions` list used by the `WordPress.Security.NonceVerification`, `WordPress.Security.ValidatedSanitizedInput` and `WordPress.Security.EscapeOutput` sniffs. +- The `sanitize_key()` and the `highlight_string()` functions to the `escapingFunctions` list used by the `WordPress.Security.EscapeOutput` sniff. +- The `RECOVERY_MODE_COOKIE` constant to the list of WP Core constants which may be defined by plugins and themes and therefore don't need to be prefixed (`WordPress.NamingConventions.PrefixAllGlobals`). +- `$content_width`, `$plugin`, `$mu_plugin` and `$network_plugin` to the list of WP globals which is used by both the `WordPress.Variables.GlobalVariables` and the `WordPress.NamingConventions.PrefixAllGlobals` sniffs. +- `Sniff::is_short_list()` utility method to determine whether a _short array_ open/close token actually represents a PHP 7.1+ short list. +- `Sniff::find_list_open_close()` utility method to find the opener and closer for `list()` constructs, including short lists. +- `Sniff::get_list_variables()` utility method which will retrieve an array with the token pointers to the variables which are being assigned to in a `list()` construct. Includes support for short lists. +- `Sniff::is_function_deprecated()` static utility method to determine whether a declared function has been marked as deprecated in the function DocBlock. +- End-user documentation to the following existing sniffs: `WordPress.Arrays.ArrayIndentation`, `WordPress.Arrays.ArrayKeySpacingRestrictions`, `WordPress.Arrays.MultipleStatementAlignment`, `WordPress.Classes.ClassInstantiation`, `WordPress.NamingConventions.ValidHookName`, `WordPress.PHP.IniSet`, `WordPress.Security.SafeRedirect`, `WordPress.WhiteSpace.CastStructureSpacing`, `WordPress.WhiteSpace.DisallowInlineTabs`, `WordPress.WhiteSpace.PrecisionAlignment`, `WordPress.WP.CronInterval`, `WordPress.WP.DeprecatedClasses`, `WordPress.WP.DeprecatedFunctions`, `WordPress.WP.DeprecatedParameters`, `WordPress.WP.DeprecatedParameterValues`, `WordPress.WP.EnqueuedResources`, `WordPress.WP.PostsPerPage`. + This documentation can be exposed via the [`PHP_CodeSniffer` `--generator=...` command-line argument](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage). + +### Changed +- The default value for `minimum_supported_wp_version`, as used by a [number of sniffs detecting usage of deprecated WP features](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#minimum-wp-version-to-check-for-usage-of-deprecated-functions-classes-and-function-parameters), has been updated to `5.0`. +- The `WordPress.Arrays.ArrayKeySpacingRestrictions` sniff has two new error codes: `TooMuchSpaceBeforeKey` and `TooMuchSpaceAfterKey`. Both auto-fixable. + The sniff will now check that there is _exactly_ one space on the inside of the square brackets around the array key for non-string, non-numeric array keys. Previously, it only checked that there was whitespace, not how much whitespace. +- `WordPress.Arrays.ArrayKeySpacingRestrictions`: the fixers have been made more efficient and less fixer-conflict prone. +- `WordPress.NamingConventions.PrefixAllGlobals`: plugin/theme prefixes should be at least three characters long. A new `ShortPrefixPassed` error has been added for when the prefix passed does not comply with this rule. +- `WordPress.WhiteSpace.CastStructureSpacing` now allows for no whitespace before a cast when the cast is preceded by the spread `...` operator. This pre-empts a fixer conflict for when the spacing around the spread operator will start to get checked. +- The `WordPress.WP.DeprecatedClasses` sniff will now detect classes deprecated in WP 4.9 and WP 5.3. +- The `WordPress.WP.DeprecatedFunctions` sniff will now detect functions deprecated in WP 5.3. +- `WordPress.NamingConventions.ValidHookName` now has "cleaner" error messages and higher precision for the line on which an error is thrown. +- `WordPress.Security.EscapeOutput`: if an error refers to array access via a variable, the array index key will now be included in the error message. +- The processing of the `WordPress` ruleset by `PHP_CodeSniffer` will now be faster. +- Various minor code tweaks and clean up. +- Various minor documentation fixes. +- Documentation: updated the repo URL in all relevant places. + +### Deprecated +- The `WordPress.WP.TimezoneChange` sniff. Use the `WordPress.DateTime.RestrictedFunctions` instead. + The deprecated sniff will be removed in WPCS 3.0.0. + +### Fixed +- All sniffs in the `WordPress.Arrays` category will no longer treat _short lists_ as if they were a short array. +- The `WordPress.NamingConventions.ValidFunctionName` and the `WordPress.NamingConventions.PrefixAllGlobals` sniff will now ignore functions marked as `@deprecated`. +- Both the `WordPress.NamingConventions.PrefixAllGlobals` sniff as well as the `WordPress.WP.GlobalVariablesOverride` sniff have been updated to recognize variables being declared via (long/short) `list()` constructs and handle them correctly. +- Both the `WordPress.NamingConventions.PrefixAllGlobals` sniff as well as the `WordPress.WP.GlobalVariablesOverride` sniff will now take a limited list of WP global variables _which are intended to be overwritten by plugins/themes_ into account. + Initially this list contains the `$content_width` and the `$wp_cockneyreplace` variables. +- `WordPress.NamingConventions.ValidHookName`: will no longer examine a string array access index key as if it were a part of the hook name. +- `WordPress.Security.EscapeOutput`: will no longer trigger on the typical `basename( __FILE__ )` pattern if found as the first parameter passed to a call to `_deprecated_file()`. +- `WordPress.WP.CapitalPDangit`: now allows for the `.test` TLD in URLs. +- WPCS is now fully compatible with PHP 7.4. + Note: `PHP_CodeSniffer` itself is only compatible with PHP 7.4 from PHPCS 3.5.0 onwards. + + +## [2.1.1] - 2019-05-21 + +### Changed +- The `WordPress.WP.CapitalPDangit` will now ignore misspelled instances of `WordPress` within constant declarations. + This covers both constants declared using `defined()` as well as constants declared using the `const` keyword. +- The default value for `minimum_supported_wp_version`, as used by a [number of sniffs detecting usage of deprecated WP features](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#minimum-wp-version-to-check-for-usage-of-deprecated-functions-classes-and-function-parameters), has been updated to `4.9`. + +### Removed +- `paginate_comments_links()` from the list of auto-escaped functions `Sniff::$autoEscapedFunctions`. + This affects the `WordPress.Security.EscapeOutput` sniff. + +### Fixed +- The `$current_blog` and `$tag_ID` variables have been added to the list of WordPress global variables. + This fixes some false positives from the `WordPress.NamingConventions.PrefixAllGlobals` and the `WordPress.WP.GlobalVariablesOverride` sniffs. +- The generic `TestCase` class name has been added to the `$test_class_whitelist`. + This fixes some false positives from the `WordPress.NamingConventions.FileName`, `WordPress.NamingConventions.PrefixAllGlobals` and the `WordPress.WP.GlobalVariablesOverride` sniffs. +- The `WordPress.NamingConventions.ValidVariableName` sniff will now correctly recognize `$tag_ID` as a WordPress native, mixed-case variable. +- The `WordPress.Security.NonceVerification` sniff will now correctly recognize nonce verification within a nested closure or anonymous class. + + +## [2.1.0] - 2019-04-08 + +### Added +- New `WordPress.PHP.IniSet` sniff to the `WordPress-Extra` ruleset. + This sniff will detect calls to `ini_set()` and `ini_alter()` and warn against their use as changing configuration values at runtime leads to an unpredictable runtime environment, which can result in conflicts between core/plugins/themes. + - The sniff will not throw notices about a very limited set of "safe" ini directives. + - For a number of ini directives for which there are alternative, non-conflicting ways to achieve the same available, the sniff will throw an `error` and advise using the alternative. +- `doubleval()`, `count()` and `sizeof()` to `Sniff::$unslashingSanitizingFunctions` property. + While `count()` and its alias `sizeof()`, don't actually unslash or sanitize, the output of these functions is safe to use without unslashing or sanitizing. + This affects the `WordPress.Security.ValidatedSanitizedInput` and the `WordPress.Security.NonceVerification` sniffs. +- The new WP 5.1 `WP_UnitTestCase_Base` class to the `Sniff::$test_class_whitelist` property. +- New `Sniff::get_array_access_keys()` utility method to retrieve all array keys for a variable using multi-level array access. +- New `Sniff::is_class_object_call()`, `Sniff::is_token_namespaced()` utility methods. + These should help make the checking of whether or not a function call is a global function, method call or a namespaced function call more consistent. + This also implements allowing for the [namespace keyword being used as an operator](https://www.php.net/manual/en/language.namespaces.nsconstants.php#example-258). +- New `Sniff::is_in_function_call()` utility method to facilitate checking whether a token is (part of) a parameter passed to a specific (set of) function(s). +- New `Sniff::is_in_type_test()` utility method to determine if a variable is being type tested, along with a `Sniff::$typeTestFunctions` property containing the names of the functions this applies to. +- New `Sniff::is_in_array_comparison()` utility method to determine if a variable is (part of) a parameter in an array-value comparison, along with a `Sniff::$arrayCompareFunctions` property containing the names of the relevant functions. +- New `Sniff::$arrayWalkingFunctions` property containing the names of array functions which apply a callback to the array, but don't change the array by reference. +- New `Sniff::$unslashingFunctions` property containing the names of functions which unslash data passed to them and return the unslashed result. + +### Changed +- Moved the `WordPress.PHP.StrictComparisons`, `WordPress.PHP.StrictInArray` and the `WordPress.CodeAnalysis.AssignmentInCondition` sniff from the `WordPress-Extra` to the `WordPress-Core` ruleset. +- The `Squiz.Commenting.InlineComment.SpacingAfter` error is no longer included in the `WordPress-Docs` ruleset. +- The default value for `minimum_supported_wp_version`, as used by a [number of sniffs detecting usage of deprecated WP features](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#minimum-wp-version-to-check-for-usage-of-deprecated-functions-classes-and-function-parameters), has been updated to `4.8`. +- The `WordPress.WP.DeprecatedFunctions` sniff will now detect functions deprecated in WP 5.1. +- The `WordPress.Security.NonceVerification` sniff now allows for variable type testing, comparisons, unslashing and sanitization before the nonce check. A nonce check within the same scope, however, is still required. +- The `WordPress.Security.ValidatedSanitizedInput` sniff now allows for using a superglobal in an array-value comparison without sanitization, same as when the superglobal is used in a scalar value comparison. +- `WordPress.NamingConventions.PrefixAllGlobals`: some of the error messages have been made more explicit. +- The error messages for the `WordPress.Security.ValidatedSanitizedInput` sniff will now contain information on the index keys accessed. +- The error message for the `WordPress.Security.ValidatedSanitizedInput.InputNotValidated` has been reworded to make it more obvious what the actual issue being reported is. +- The error message for the `WordPress.Security.ValidatedSanitizedInput.MissingUnslash` has been reworded. +- The `Sniff::is_comparison()` method now has a new `$include_coalesce` parameter to allow for toggling whether the null coalesce operator should be seen as a comparison operator. Defaults to `true`. +- All sniffs are now also being tested against PHP 7.4 (unstable) for consistent sniff results. +- The recommended version of the suggested DealerDirect PHPCS Composer plugin is now `^0.5.0`. +- Various minor code tweaks and clean up. + +### Removed +- `ini_set` and `ini_alter` from the list of functions detected by the `WordPress.PHP.DiscouragedFunctions` sniff. + These are now covered via the new `WordPress.PHP.IniSet` sniff. +- `in_array()` and `array_key_exists()` from the list of `Sniff::$sanitizingFunctions`. These are now handled differently. + +### Fixed +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff would underreport when global functions would be autoloaded via a Composer autoload `files` configuration. +- The `WordPress.Security.EscapeOutput` sniff will now recognize `map_deep()` for escaping the values in an array via a callback to an output escaping function. This should prevent false positives. +- The `WordPress.Security.NonceVerification` sniff will no longer inadvertently allow for a variable to be sanitized without a nonce check within the same scope. +- The `WordPress.Security.ValidatedSanitizedInput` sniff will no longer throw errors when a variable is only being type tested. +- The `WordPress.Security.ValidatedSanitizedInput` sniff will now correctly recognize the null coalesce (PHP 7.0) and null coalesce equal (PHP 7.4) operators and will now throw errors for missing unslashing and sanitization where relevant. +- The `WordPress.WP.AlternativeFunctions` sniff will no longer recommend using the WP_FileSystem when PHP native input streams, like `php://input`, or the PHP input stream constants are being read or written to. +- The `WordPress.WP.AlternativeFunctions` sniff will no longer report on usage of the `curl_version()` function. +- The `WordPress.WP.CronInterval` sniff now has improved function recognition which should lower the chance of false positives. +- The `WordPress.WP.EnqueuedResources` sniff will no longer throw false positives for inline jQuery code trying to access a stylesheet link tag. +- Various bugfixes for the `Sniff::has_nonce_check()` method: + - The method will no longer incorrectly identify methods/namespaced functions mirroring the name of WP native nonce verification functions as if they were the global functions. + This will prevent some false negatives. + - The method will now skip over nested closed scopes, such as closures and anonymous classes. This should prevent some false negatives for nonce verification being done while not in the correct scope. + + These fixes affect the `WordPress.Security.NonceVerification` sniff. +- The `Sniff::is_in_isset_or_empty()` method now also checks for usage of `array_key_exist()` and `key_exists()` and will regard these as correct ways to validate a variable. + This should prevent false positives for the `WordPress.Security.ValidatedSanitizedInput` and the `WordPress.Security.NonceVerification` sniffs. +- Various bugfixes for the `Sniff::is_sanitized()` method: + - The method presumed the WordPress coding style regarding code layout, which could lead to false positives. + - The method will no longer incorrectly identify methods/namespaced functions mirroring the name of WP/PHP native unslashing/sanitization functions as if they were the global functions. + This will prevent some false negatives. + - The method will now recognize `map_deep()` for sanitizing an array via a callback to a sanitization function. This should prevent false positives. + - The method will now recognize `stripslashes_deep()` and `stripslashes_from_strings_only()` as valid unslashing functions. This should prevent false positives. + All these fixes affect both the `WordPress.Security.ValidatedSanitizedInput` and the `WordPress.Security.NonceVerification` sniff. +- Various bugfixes for the `Sniff::is_validated()` method: + - The method did not verify correctly whether a variable being validated was the same variable as later used which could lead to false negatives. + - The method did not verify correctly whether a variable being validated had the same array index keys as the variable as later used which could lead to both false negatives as well as false positives. + - The method now also checks for usage of `array_key_exist()` and `key_exists()` and will regard these as correct ways to validate a variable. This should prevent some false positives. + - The methods will now recognize the null coalesce and the null coalesce equal operators as ways to validate a variable. This prevents some false positives. + The results from the `WordPress.Security.ValidatedSanitizedInput` sniff should be more accurate because of these fixes. +- A potential "Undefined index" notice from the `Sniff::is_assignment()` method. + + +## [2.0.0] - 2019-01-16 + +### Important information about this release: + +WordPressCS 2.0.0 contains breaking changes, both for people using custom rulesets as well as for sniff developers who maintain a custom PHPCS standard based on WordPressCS. + +Support for `PHP_CodeSniffer` 2.x has been dropped, the new minimum `PHP_CodeSniffer` version is 3.3.1. +Also, all previously deprecated sniffs, properties and methods have been removed. + +Please read the complete changelog carefully before you upgrade. + +If you are a maintainer of an external standard based on WordPressCS and any of your custom sniffs are based on or extend WPCS sniffs, please read the [Developers Upgrade Guide to WordPressCS 2.0.0](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Upgrade-Guide-to-WordPressCS-2.0.0-for-Developers-of-external-standards). + +### Changes since 2.0.0-RC1 + +#### Fixed + +- `WordPress-Extra`: Reverted back to including the `Squiz.WhiteSpace.LanguageConstructSpacing` sniff instead of the new `Generic.WhiteSpace.LanguageConstructSpacing` sniff as the new sniff is not (yet) available when the PEAR install of PHPCS is used. + +### Changes since 1.2.1 +For a full list of changes from the 1.2.1 version, please review the following changelog: +* https://github.com/WordPress/WordPress-Coding-Standards/releases/tag/2.0.0-RC1 + + +## [2.0.0-RC1] - 2018-12-31 + +### Important information about this release: + +This is the first release candidate for WordPressCS 2.0.0. +WordPressCS 2.0.0 contains breaking changes, both for people using custom rulesets as well as for sniff developers who maintain a custom PHPCS standard based on WordPressCS. + +Support for `PHP_CodeSniffer` 2.x has been dropped, the new minimum `PHP_CodeSniffer` version is 3.3.1. +Also, all previously deprecated sniffs, properties and methods have been removed. + +Please read the complete changelog carefully before you upgrade. + +If you are a maintainer of an external standard based on WordPressCS and any of your custom sniffs are based on or extend WPCS sniffs, please read the [Developers Upgrade Guide to WordPressCS 2.0.0](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Upgrade-Guide-to-WordPressCS-2.0.0-for-Developers-of-external-standards). + +### Added +- `Generic.PHP.DiscourageGoto`, `Generic.PHP.LowerCaseType`, `Generic.WhiteSpace.ArbitraryParenthesesSpacing` and `PSR12.Keywords.ShortFormTypeKeywords` to the `WordPress-Core` ruleset. +- Checking the spacing around the `instanceof` operator to the `WordPress.WhiteSpace.OperatorSpacing` sniff. + +### Changed +- The minimum required `PHP_CodeSniffer` version to 3.3.1 (was 2.9.0). +- The namespace used by WordPressCS has been changed from `WordPress` to `WordPressCS\WordPress`. + This was not possible while `PHP_CodeSniffer` 2.x was still supported, but WordPressCS, as a good Open Source citizen, does not want to occupy the `WordPress` namespace and is releasing its use of it now this is viable. +- The `WordPress.DB.PreparedSQL` sniff used the same error code for two different errors. + The `NotPrepared` error code remains, however an additional `InterpolatedNotPrepared` error code has been added for the second error. + If you are referencing the old error code in a ruleset XML file or in inline annotations, you may need to update it. +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff used the same error code for some errors as well as warnings. + The `NonPrefixedConstantFound` error code remains for the related error, but the warning will now use the new `VariableConstantNameFound` error code. + The `NonPrefixedHooknameFound` error code remains for the related error, but the warning will now use the new `DynamicHooknameFound` error code. + If you are referencing the old error codes in a ruleset XML file or in inline annotations, you may need to update these to use the new codes instead. +- `WordPress.NamingConventions.ValidVariableName`: the error messages and error codes used by this sniff have been changed for improved usability and consistency. + - The error messages will now show a suggestion for a valid alternative name for the variable. + - The `NotSnakeCaseMemberVar` error code has been renamed to `UsedPropertyNotSnakeCase`. + - The `NotSnakeCase` error code has been renamed to `VariableNotSnakeCase`. + - The `MemberNotSnakeCase` error code has been renamed to `PropertyNotSnakeCase`. + - The `StringNotSnakeCase` error code has been renamed to `InterpolatedVariableNotSnakeCase`. + If you are referencing the old error codes in a ruleset XML file or in inline annotations, you may need to update these to use the new codes instead. +- The `WordPress.Security.NonceVerification` sniff used the same error code for both an error as well as a warning. + The old error code `NoNonceVerification` is no longer used. + The `error` now uses the `Missing` error code, while the `warning` now uses the `Recommended` error code. + If you are referencing the old error code in a ruleset XML file or in inline annotations, please update these to use the new codes instead. +- The `WordPress.WP.DiscouragedConstants` sniff used to have two error codes `UsageFound` and `DeclarationFound`. + These error codes will now be prefixed by the name of the constant found to allow for more fine-grained excluding/ignoring of warnings generated by this sniff. + If you are referencing the old error codes in a ruleset XML file or in inline annotations, you may need to update these to use the new codes instead. +- The `WordPress.WP.GlobalVariablesOverride.OverrideProhibited` error code has been replaced by the `WordPress.WP.GlobalVariablesOverride.Prohibited` error code. + If you are referencing the old error code in a ruleset XML file or in inline annotations, you may need to update it. +- `WordPress-Extra`: Replaced the inclusion of the `Generic.Files.OneClassPerFile`, `Generic.Files.OneInterfacePerFile` and the `Generic.Files.OneTraitPerFile` sniffs with the new `Generic.Files.OneObjectStructurePerFile` sniff. +- `WordPress-Extra`: Replaced the inclusion of the `Squiz.WhiteSpace.LanguageConstructSpacing` sniff with the new `Generic.WhiteSpace.LanguageConstructSpacing` sniff. +- `WordPress-Extra`: Replaced the inclusion of the `Squiz.Scope.MemberVarScope` sniff with the more comprehensive `PSR2.Classes.PropertyDeclaration` sniff. +- `WordPress.NamingConventions.ValidFunctionName`: Added a unit test confirming support for interfaces extending multiple interfaces. +- `WordPress.NamingConventions.ValidVariableName`: Added unit tests confirming support for multi-variable/property declarations. +- The `get_name_suggestion()` method has been moved from the `WordPress.NamingConventions.ValidFunctionName` sniff to the base `Sniff` class, renamed to `get_snake_case_name_suggestion()` and made static. +- The rulesets are now validated against the `PHP_CodeSniffer` XSD schema. +- Updated the [custom ruleset example](https://github.com/WordPress/WordPress-Coding-Standards/blob/develop/phpcs.xml.dist.sample) to use the recommended ruleset syntax for `PHP_CodeSniffer` 3.3.1+, including using the new [array property format](https://github.com/squizlabs/PHP_CodeSniffer/releases/tag/3.3.0) which is now supported. +- Dev: The command to run the unit tests has changed. Please see the updated instructions in the [CONTRIBUTING.md](https://github.com/WordPress/WordPress-Coding-Standards/blob/develop/.github/CONTRIBUTING.md) file. + The `bin/pre-commit` example git hook has been updated to match. Additionally a `run-tests` script has been added to the `composer.json` file for your convenience. + To facilitate this, PHPUnit has been added to `require-dev`, even though it is strictly speaking a dependency of PHPCS, not of WPCS. +- Dev: The DealerDirect PHPCS Composer plugin has been added to `require-dev`. +- Various code tweaks and clean up. +- User facing documentation, including the wiki, as well as inline documentation has been updated for all the changes contained in WordPressCS 2.0 and other recommended best practices for `PHP_CodeSniffer` 3.3.1+. + +### Deprecated +- The use of the [WordPressCS native whitelist comments](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Whitelisting-code-which-flags-errors), which were introduced in WPCS 0.4.0, have been deprecated and support will be removed in WPCS 3.0.0. + The WordPressCS native whitelist comments will continue to work for now, but a deprecation warning will be thrown when they are encountered. + You are encouraged to upgrade our whitelist comment to use the [PHPCS native selective ignore annotations](https://github.com/squizlabs/PHP_CodeSniffer/releases/tag/3.2.0) as introduced in `PHP_CodeSniffer` 3.2.0, as soon as possible. + +### Removed +- Support for PHP 5.3. PHP 5.4 is the minimum requirement for `PHP_CodeSniffer` 3.x. + Includes removing any and all workarounds which were in place to still support PHP 5.3. +- Support for `PHP_CodeSniffer` < 3.3.1. + Includes removing any and all workarounds which were in place for supporting older `PHP_CodeSniffer` versions. +- The `WordPress-VIP` standard which was deprecated since WordPressCS 1.0.0. + For checking a theme/plugin for hosting on the WordPress.com VIP platform, please use the [Automattic VIP coding standards](https://github.com/Automattic/VIP-Coding-Standards) instead. +- Support for array properties set in a custom ruleset without the `type="array"` attribute. + Support for this was deprecated in WPCS 1.0.0. + If in doubt about how properties should be set in your custom ruleset, please refer to the [Customizable sniff properties](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties) wiki page which contains XML code examples for setting each and every WPCS native sniff property. + As the minimum `PHP_CodeSniffer` version is now 3.3.1, you can now also use the [new format for setting array properties](https://github.com/squizlabs/PHP_CodeSniffer/releases/tag/3.3.0), so this would be a great moment to review and update your custom ruleset. + Note: the ability to set select properties from the command-line as comma-delimited strings is _not_ affected by this change. +- The following sniffs have been removed outright without deprecation. + If you are referencing these sniffs in a ruleset XML file or in inline annotations, please update these to reference the replacement sniffs instead. + - `WordPress.Functions.FunctionCallSignatureNoParams` - superseded by a bug fix in the upstream `PEAR.Functions.FunctionCallSignature` sniff. + - `WordPress.PHP.DiscourageGoto` - replaced by the same sniff which is now available upstream: `Generic.PHP.DiscourageGoto`. + - `WordPress.WhiteSpace.SemicolonSpacing` - superseded by a bug fix in the upstream `Squiz.WhiteSpace.SemicolonSpacing` sniff. + - `WordPress.WhiteSpace.ArbitraryParenthesesSpacing` - replaced by the same sniff which is now available upstream: `Generic.WhiteSpace.ArbitraryParenthesesSpacing`. +- The following "base" sniffs which were previously already deprecated and turned into abstract base classes, have been removed: + - `WordPress.Arrays.ArrayAssignmentRestrictions` - use the `AbstractArrayAssignmentRestrictionsSniff` class instead. + - `WordPress.Functions.FunctionRestrictions` - use the `AbstractFunctionRestrictionsSniff` class instead. + - `WordPress.Variables.VariableRestrictions` without replacement. +- The following sniffs which were previously deprecated, have been removed: + - `WordPress.Arrays.ArrayDeclaration` - use the other sniffs in the `WordPress.Arrays` category instead. + - `WordPress.CSRF.NonceVerification` - use `WordPress.Security.NonceVerification` instead. + - `WordPress.Functions.DontExtract` - use `WordPress.PHP.DontExtract` instead. + - `WordPress.Variables.GlobalVariables` - use `WordPress.WP.GlobalVariablesOverride` instead. + - `WordPress.VIP.CronInterval` - use `WordPress.WP.CronInterval` instead. + - `WordPress.VIP.DirectDatabaseQuery` - use `WordPress.DB.DirectDatabaseQuery` instead. + - `WordPress.VIP.PluginMenuSlug` - use `WordPress.Security.PluginMenuSlug` instead. + - `WordPress.VIP.SlowDBQuery` - use `WordPress.DB.SlowDBQuery` instead. + - `WordPress.VIP.TimezoneChange` - use `WordPress.WP.TimezoneChange` instead. + - `WordPress.VIP.ValidatedSanitizedInput` - use `WordPress.Security.ValidatedSanitizedInput` instead. + - `WordPress.WP.PreparedSQL` - use `WordPress.DB.PreparedSQL` instead. + - `WordPress.XSS.EscapeOutput` - use `WordPress.Security.EscapeOutput` instead. + - `WordPress.PHP.DiscouragedFunctions` without direct replacement. + The checks previously contained in this sniff were moved to separate sniffs in WPCS 0.11.0. + - `WordPress.Variables.VariableRestrictions` without replacement. + - `WordPress.VIP.AdminBarRemoval` without replacement. + - `WordPress.VIP.FileSystemWritesDisallow` without replacement. + - `WordPress.VIP.OrderByRand` without replacement. + - `WordPress.VIP.PostsPerPage` without replacement. + Part of the previous functionality was split off in WPCS 1.0.0 to the `WordPress.WP.PostsPerPage` sniff. + - `WordPress.VIP.RestrictedFunctions` without replacement. + - `WordPress.VIP.RestrictedVariables` without replacement. + - `WordPress.VIP.SessionFunctionsUsage` without replacement. + - `WordPress.VIP.SessionVariableUsage` without replacement. + - `WordPress.VIP.SuperGlobalInputUsage` without replacement. +- The `WordPress.DB.SlowDBQuery.DeprecatedWhitelistFlagFound` error code which is superseded by the blanket deprecation warning for using the now deprecated WPCS native whitelist comments. +- The `WordPress.PHP.TypeCasts.NonLowercaseFound` error code which has been replaced by the upstream `Generic.PHP.LowerCaseType` sniff. +- The `WordPress.PHP.TypeCasts.LongBoolFound` and `WordPress.PHP.TypeCasts.LongIntFound` error codes which has been replaced by the new upstream `PSR12.Keywords.ShortFormTypeKeywords` sniff. +- The `WordPress.Security.EscapeOutput.OutputNotEscapedShortEcho` error code which was only ever used if WPCS was run on PHP 5.3 with the `short_open_tag` ini directive set to `off`. +- The following sniff categories which were previously deprecated, have been removed, though select categories may be reinstated in the future: + - `CSRF` + - `Functions` + - `Variables` + - `VIP` + - `XSS` +- `WordPress.NamingConventions.ValidVariableName`: The `customVariableWhitelist` property, which had been deprecated since WordPressCS 0.11.0. Use the `customPropertiesWhitelist` property instead. +- `WordPress.Security.EscapeOutput`: The `customSanitizingFunctions` property, which had been deprecated since WordPressCS 0.5.0. Use the `customEscapingFunctions` property instead. +- `WordPress.Security.NonceVerification`: The `errorForSuperGlobals` and `warnForSuperGlobals` properties, which had been deprecated since WordPressCS 0.12.0. +- The `vip_powered_wpcom` function from the `Sniff::$autoEscapedFunctions` list which is used by the `WordPress.Security.EscapeOutput` sniff. +- The `AbstractVariableRestrictionsSniff` class, which was deprecated since WordPressCS 1.0.0. +- The `Sniff::has_html_open_tag()` utility method, which was deprecated since WordPressCS 1.0.0. +- The internal `$php_reserved_vars` property from the `WordPress.NamingConventions.ValidVariableName` sniff in favour of using a PHPCS native property which is now available. +- The class aliases and WPCS native autoloader used for PHPCS cross-version support. +- The unit test framework workarounds for PHPCS cross-version unit testing. +- Support for the `@codingStandardsChangeSetting` annotation, which is generally only used in unit tests. +- The old generic GitHub issue template which was replaced by more specific issue templates in WPCS 1.2.0. + +### Fixed +- Support for PHP 7.3. + `PHP_CodeSniffer` < 3.3.1 was not fully compatible with PHP 7.3. Now the minimum required PHPCS has been upped to `PHP_CodeSniffer` 3.3.1, WordPressCS will run on PHP 7.3 without issue. +- `WordPress.Arrays.ArrayDeclarationSpacing`: improved fixing of the placement of array items following an array item with a trailing multi-line comment. +- `WordPress.NamingConventions.ValidFunctionName`: the sniff will no longer throw false positives nor duplicate errors for methods declared in nested anonymous classes. + The error message has also been improved for methods in anonymous classes. +- `WordPress.NamingConventions.ValidFunctionName`: the sniff will no longer throw false positives for PHP 4-style class constructors/destructors where the name of the constructor/destructor method did not use the same case as the class name. + + +## [1.2.1] - 2018-12-18 + +Note: This will be the last release supporting PHP_CodeSniffer 2.x. + +### Changed +- The default value for `minimum_supported_wp_version`, as used by a [number of sniffs detecting usage of deprecated WP features](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#minimum-wp-version-to-check-for-usage-of-deprecated-functions-classes-and-function-parameters), has been updated to `4.7`. +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff will now report the error for hook names and constant names declared with `define()` on the line containing the parameter for the hook/constant name. Previously, it would report the error on the line containing the function call. +- Various minor housekeeping fixes to inline documentation, rulesets, code. + +### Removed +- `comment_author_email_link()`, `comment_author_email()`, `comment_author_IP()`, `comment_author_link()`, `comment_author_rss()`, `comment_author_url_link()`, `comment_author_url()`, `comment_author()`, `comment_date()`, `comment_excerpt()`, `comment_form_title()`, `comment_form()`, `comment_id_fields()`, `comment_ID()`, `comment_reply_link()`, `comment_text_rss()`, `comment_text()`, `comment_time()`, `comment_type()`, `comments_link()`, `comments_number()`, `comments_popup_link()`, `comments_popup_script()`, `comments_rss_link()`, `delete_get_calendar_cache()`, `edit_bookmark_link()`, `edit_comment_link()`, `edit_post_link()`, `edit_tag_link()`, `get_footer()`, `get_header()`, `get_sidebar()`, `get_the_title()`, `next_comments_link()`, `next_image_link()`, `next_post_link()`, `next_posts_link()`, `permalink_anchor()`, `posts_nav_link()`, `previous_comments_link()`, `previous_image_link()`, `previous_post_link()`, `previous_posts_link()`, `sticky_class()`, `the_attachment_link()`, `the_author_link()`, `the_author_meta()`, `the_author_posts_link()`, `the_author_posts()`, `the_category_rss()`, `the_category()`, `the_content_rss()`, `the_content()`, `the_date_xml()`, `the_excerpt_rss()`, `the_excerpt()`, `the_feed_link()`, `the_ID()`, `the_meta()`, `the_modified_author()`, `the_modified_date()`, `the_modified_time()`, `the_permalink()`, `the_post_thumbnail()`, `the_search_query()`, `the_shortlink()`, `the_tags()`, `the_taxonomies()`, `the_terms()`, `the_time()`, `the_title_rss()`, `the_title()`, `wp_enqueue_script()`, `wp_meta()`, `wp_shortlink_header()` and `wp_shortlink_wp_head()` from the list of auto-escaped functions `Sniff::$autoEscapedFunctions`. This affects the `WordPress.Security.EscapeOutput` sniff. + +### Fixed +- The `WordPress.WhiteSpace.PrecisionAlignment` sniff would loose the value of a custom set `ignoreAlignmentTokens` property when scanning more than one file. + + +## [1.2.0] - 2018-11-12 + +### Added +- New `WordPress.PHP.TypeCasts` sniff to the `WordPress-Core` ruleset. + This new sniff checks that PHP type casts are: + * lowercase; + * short form, i.e. `(bool)` not `(boolean)`; + * normalized, i.e. `(float)` not `(real)`. + Additionally, the new sniff discourages the use of the `(unset)` and `(binary)` type casts. +- New `WordPress.Utils.I18nTextDomainFixer` sniff which can compehensively replace/add `text-domain`s in a plugin or theme. + Important notes: + - This sniff is disabled by default and intended as a utility tool. + - The sniff will fix the text domains in all I18n function calls as well as in a plugin/theme `Text Domain:` header. + - Passing the following properties will activate the sniff: + - `old_text_domain`: an array with one or more (old) text domains which need to be replaced; + - `new_text_domain`: the correct (new) text domain as a string. +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff will now also verify that namespace names use a valid prefix. + * The sniff allows for underscores and (other) non-word characters in a passed prefix to be converted to namespace separators when used in a namespace name. + In other words, if a prefix of `my_plugin` is passed as a value to the `prefixes` property, a namespace name of both `My\Plugin` as well as `My_Plugin\\`, will be accepted automatically. + * Passing a prefix property value containing namespace separators will now also be allowed and will no longer trigger a warning. +- `WordPress` to the prefix blacklist for the `WordPress.NamingConventions.PrefixAllGlobals` sniff. + While the prefix cannot be `WordPress`, a prefix can still _start with_ or _contain_ `WordPress`. +- Additional unit tests covering a change in the tokenizer which will be included in the upcoming `PHP_CodeSniffer` 3.4.0 release. +- A variety of issue templates for use on GitHub. + +### Changed +- The `Sniff::valid_direct_scope()` method will now return the `$stackPtr` to the valid scope if a valid direct scope has been detected. Previously, it would return `true`. +- Minor hardening and efficiency improvements to the `WordPress.NamingConventions.PrefixAllGlobals` sniff. +- The inline documentation of the `WordPress-Core` ruleset has been updated to be in line again with [the handbook](https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/). +- The inline links to documentation about the VIP requirements have been updated. +- Updated the [custom ruleset example](https://github.com/WordPress/WordPress-Coding-Standards/blob/develop/phpcs.xml.dist.sample) to recommend using `PHPCompatibilityWP` rather than `PHPCompatibility`. +- All sniffs are now also being tested against PHP 7.3 for consistent sniff results. + Note: PHP 7.3 is only supported in combination with PHPCS 3.3.1 or higher as `PHP_CodeSniffer` itself has an incompatibility in earlier versions. +- Minor grammar fixes in text strings and documentation. +- Minor consistency improvement for the unit test case files. +- Minor tweaks to the `composer.json` file. +- Updated the PHPCompatibility `dev` dependency. + +### Removed +- The `WordPress.WhiteSpace.CastStructureSpacing.NoSpaceAfterCloseParenthesis` error code as an error for the same issue was already being thrown by an included upstream sniff. + +### Fixed +- The `WordPress.CodeAnalysis.EmptyStatement` would throw a false positive for an empty condition in a `for()` statement. +- The `Sniff::is_class_property()` method could, in certain circumstances, incorrectly recognize parameters in a method declaration as class properties. It would also, incorrectly, fail to recognize class properties when the object they are declared in, was nested in parentheses. + This affected, amongst others, the `GlobalVariablesOverride` sniff. +- The `Sniff::get_declared_namespace_name()` method could get confused over whitespace and comments within a namespace name, which could lead to incorrect results (mostly underreporting). + This affected, amongst others, the `GlobalVariablesOverride` sniff. + The return value of the method will now no longer contain any whitespace or comments encountered. +- The `Sniff::has_whitelist_comment()` method would sometimes incorrectly regard `// phpcs:set` comments as whitelist comments. + +## [1.1.0] - 2018-09-10 + +### Added +- New `WordPress.PHP.NoSilencedErrors` sniff. This sniff replaces the `Generic.PHP.NoSilencedErrors` sniff which was previously used and included in the `WordPress-Core` ruleset. + The WordPress specific version of the sniff differs from the PHPCS version in that it: + * Allows the error control operator `@` if it preceeds a function call to a limited list of PHP functions for which no amount of error checking can prevent a PHP warning from being thrown. + * Allows for a used-defined list of (additional) function names to be passed to the sniff via the `custom_whitelist` property in a custom ruleset, for which - if the error control operator is detected in front of a function call to one of the functions in this whitelist - no warnings will be thrown. + * Displays a brief snippet of code in the `warning` message text to show the context in which the error control operator is being used. The length of the snippet (in tokens) can be customized via the `context_length` property. + * Contains a public `use_default_whitelist` property which can be set from a custom ruleset which regulates whether or not the standard whitelist of PHP functions should be used by the sniff. + The user-defined whitelist will always be respected. + By default, this property is set to `true` for the `WordPress-Core` ruleset and to `false` for the `WordPress-Extra` ruleset (which is stricter regarding these kind of best practices). +- Metrics to the `WordPress.NamingConventions.PrefixAllGlobals` sniff to aid people in determining the most commonly used prefix in a legacy project. + For an example of how to use this feature, please see the detailed explanation in the [pull request](https://github.com/WordPress/WordPress-Coding-Standards/pull/1437). + +### Changed +- The `PEAR.Functions.FunctionCallSignature` sniff, which is part of the `WordPress-Core` ruleset, used to allow multiple function call parameters per line in multi-line function calls. This will no longer be allowed. + As of this release, if a function call is multi-line, each parameter should start on a new line and an `error` will be thrown if the code being analysed does not comply with that rule. + The sniff behaviour for single-line function calls is not affected by this change. +- Moved the `WordPress.CodeAnalysis.EmptyStatement` sniff from the `WordPress-Extra` to the `WordPress-Core` ruleset. +- Moved the `Squiz.PHP.CommentedOutCode` sniff from the `WordPress-Docs` to the `WordPress-Extra` ruleset and lowered the threshold for determining whether or not a comment is commented out code from 45% to 40%. +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff now has improved support for recognizing whether or not (non-prefixed) globals are declared in the context of unit tests. +- The `is_foreach_as()` method has been moved from the `GlobalVariablesOverrideSniff` class to the WordPress `Sniff` base class. +- The `Sniff::is_token_in_test_method()` utility method now has improved support for recognizing test methods in anonymous classes. +- Minor efficiency improvement to the `Sniff::is_safe_casted()` method. +- CI: Minor tweaks to the Travis script. +- CI: Improved Composer scripts for use by WPCS developers. +- Dev: Removed IDE specific files from `.gitignore`. +- Readme: Improved the documentation about the project history and the badge display. + +### Fixed +- The `WordPress.Security.ValidatedSanitizedInput` sniff will now recognize array keys in superglobals independently of the string quote-style used for the array key. +- The `WordPress.WhiteSpace.PrecisionAlignment` sniff will no longer throw false positives for DocBlocks for JavaScript functions within inline HTML. +- `WordPress.WP.DeprecatedClasses`: The error codes for this sniff were unstable as they were based on the code being analysed instead of on fixed values. +- Various bugfixes for the `WordPress.WP.GlobalVariablesOverride` sniff: + - Previously, the sniff only checked variables in the global namespace when a `global` statement would be encountered. As of now, all variable assignments in the global namespace will be checked. + - Nested functions/closures/classes which don't import the global variable will now be skipped over when encountered within another function, preventing false positives. + - Parameters in function declarations will no longer throw false positives. + - The error message for assignments to a subkey of the `$GLOBALS` superglobal has been improved. + - Various efficiency improvements. +- The `Sniff::is_in_isset_or_empty()` method presumed the WordPress coding style regarding code layout, which could lead to incorrect results (mostly underreporting). + This affected, amongst others, the `WordPress.Security.ValidatedSanitizedInput` sniff. +- Broken links in the inline developer documentation. + + +## [1.0.0] - 2018-07-25 + +### Important information about this release: + +If you use the WordPress Coding Standards with a custom ruleset, please be aware that a number of sniffs have been moved between categories and that the old sniff names have been deprecated. +If you selectively include any of these sniffs in your custom ruleset or set custom property values for these sniffs, your custom ruleset will need to be updated. + +The `WordPress-VIP` ruleset has also been deprecated. If you used that ruleset to check your theme/plugin for hosting on the WordPress.com VIP platform, please use the [Automattic VIP coding standards](https://github.com/Automattic/VIP-Coding-Standards) instead. +If you used that ruleset for any other reason, you should probably use the `WordPress-Extra` or `WordPress` ruleset instead. + +These and some related changes have been annotated in detail in the `Deprecated` section of this changelog. + +Please read the complete changelog carefully before you upgrade. + +If you are a maintainer of an external standard based on WPCS and any of your custom sniffs are based on or extend WPCS sniffs, the same applies. + +### Added +- `WordPress.PHP.PregQuoteDelimiter` sniff to the `WordPress-Extra` ruleset to warn about calls to `preg_quote()` which don't pass the `$delimiter` parameter. +- `WordPress.Security.SafeRedirect` sniff to the `WordPress-Extra` ruleset to warn about potential open redirect vulnerabilities. +- `WordPress.WP.DeprecatedParameterValues` sniff to the `WordPress-Extra` ruleset to detect deprecated parameter values being passed to select functions. +- `WordPress.WP.EnqueuedResourceParameters` sniff to the `WordPress-Extra` ruleset to detect: + - Calls to the script/style register/enqueue functions which don't pass a `$version` for the script/style, which can cause issues with browser caching; and/or + - Calls to the register/enqueue script functions which don't pass the `$in_footer` parameter, which causes scripts - by default - to be loaded in the HTML header in a layout rendering blocking manner. +- Detection of calls to `strip_tags()` and various PHP native `..rand()` functions to the `WordPress.WP.AlternativeFunctions` sniff. +- `readonly()` to the list of auto-escaped functions `Sniff::$autoEscapedFunctions`. This affects the `WordPress.Security.EscapeOutput` sniff. +- The `WordPress.Security.PluginMenuSlug`, `WordPress.WP.CronInterval`, `WordPress.WP.PostsPerPage` and `WordPress.WP.TimezoneChange` sniffs are now included in the `WordPress-Extra` ruleset. Previously, they were already included in the `WordPress` and `WordPress-VIP` rulesets. +- New utility method `Sniff::is_use_of_global_constant()`. +- A rationale to the package suggestion made via `composer.json`. +- CI: Validation of the `composer.json` file on each build. +- A wiki page with instructions on how to [set up WPCS to run with Eclipse on XAMPP](https://github.com/WordPress/WordPress-Coding-Standards/wiki/How-to-use-WPCS-with-Eclipse-and-XAMPP). +- Readme: A link to an external resource with more examples for setting up PHPCS for CI. +- Readme: A badge-based quick overview of the project. + +### Changed +- The `WordPress` ruleset no longer includes the `WordPress-VIP` ruleset, nor does it include any of the (deprecated) `VIP` sniffs anymore. +- The following sniffs have been moved to a new category: + - `CronInterval` from the `VIP` category to the `WP` category. + - `DirectDatabaseQuery` from the `VIP` category to the `DB` category. + - `DontExtract` from the `Functions` category to the `PHP` category. + - `EscapeOutput` from the `XSS` category to the `Security` category. + - `GlobalVariables` from the `Variables` category to the `WP` category. + - `NonceVerification` from the `CSRF` category to the `Security` category. + - `PluginMenuSlug` from the `VIP` category to the `Security` category. + - `PreparedSQL` from the `WP` category to the `DB` category. + - `SlowDBQuery` from the `VIP` category to the `DB` category. + - `TimezoneChange` from the `VIP` category to the `WP` category. + - `ValidatedSanitizedInput` from the `VIP` category to the `Security` category. +- The `WordPress.VIP.PostsPerPage` sniff has been split into two distinct sniffs: + - `WordPress.WP.PostsPerPage` which will check for the use of a high pagination limit and will throw a `warning` when this is encountered. For the `VIP` ruleset, the error level remains `error`. + - `WordPress.VIP.PostsPerPage` wich will check for disabling of pagination. +- The default value for `minimum_supported_wp_version`, as used by a [number of sniffs detecting usage of deprecated WP features](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#minimum-wp-version-to-check-for-usage-of-deprecated-functions-classes-and-function-parameters), has been updated to `4.6`. +- The `WordPress.WP.AlternativeFunctions` sniff will now only throw a warning if/when the recommended alternative function is available in the minimum supported WP version of a project. + In addition to this, certain alternatives are only valid alternatives in certain circumstances, like when the WP version only supports the first parameter of the PHP function it is trying to replace. + This will now be taken into account for: + - `wp_strip_all_tags()` is only a valid alternative for the PHP native `strip_tags()` when the second parameter `$allowed_tags` has not been passed. + - `wp_parse_url()` only added support for the second parameter `$component` of the PHP native `parse_url()` function in WP 4.7.0. +- The `WordPress.WP.DeprecatedFunctions` sniff will now detect functions deprecated in WP 4.9. +- The `WordPress.WP.GlobalVariablesOverride` sniff will now display the name of the variable being overridden in the error message. +- The `WordPress.WP.I18n` sniff now extends the `AbstractFunctionRestrictionSniff`. +- Assignments in conditions in ternaries as detected by the `WordPress.CodeAnalysis.AssignmentInCondition` sniff will now be reported under a separate error code `FoundInTernaryCondition`. +- The default error level for the notices from the `WordPress.DB.DirectDatabaseQuery` sniff has been lowered from `error` to `warning`. For the `VIP` ruleset, the error level remains `error`. +- The default error level for the notices from the `WordPress.Security.PluginMenuSlug` sniff has been lowered from `error` to `warning`. For the `VIP` ruleset, the error level remains `error`. +- The default error level for the notices from the `WordPress.WP.CronInterval` sniff has been lowered from `error` to `warning`. For the `VIP` ruleset, the error level remains `error`. +- The `Sniff::get_function_call_parameters()` utility method now has improved handling of closures when passed as function call parameters. +- Rulesets: a number of error codes were previously silenced by explicitly `exclude`-ing them. Now, they will be silenced by setting the `severity` to `0` which makes it more easily discoverable for maintainers of custom rulesets how to enable these error codes again. +- Various performance optimizations which should most notably make a difference when running WPCS on PHP 7. +- References to the WordPress.com VIP platform have been clarified. +- Unit Tests: custom properties set in unit test files are reset after use. +- Various improvements to the ruleset used by the WPCS project itself and minor code clean up related to this. +- CI: Each change will now also be tested against the lowest supported PHPCS 3 version. +- CI: Each change will now also be checked for PHP cross-version compatibility. +- CI: The rulesets will now also be tested on each change to ensure no unexpected messages are thrown. +- CI: Minor changes to the script to make the build testing faster. +- Updated the [custom ruleset example](https://github.com/WordPress/WordPress-Coding-Standards/blob/develop/phpcs.xml.dist.sample) for the changes contained in this release and to reflect current best practices regarding the PHPCompatibility standard. +- The instructions on how to set up WPCS for various IDEs have been moved from the `README` to the [wiki](https://github.com/WordPress/WordPress-Coding-Standards/wiki). +- Updated output examples in `README.md` and `CONTRIBUTING.md` and other minor changes to these files. +- Updated references to the PHPCompatibility standard to reflect its new location and recommend using PHPCompatibilityWP. + +### Deprecated +- The `WordPress-VIP` ruleset has been deprecated. + For checking a theme/plugin for hosting on the WordPress.com VIP platform, please use the [Automattic VIP coding standards](https://github.com/Automattic/VIP-Coding-Standards) instead. + If you used the `WordPress-VIP` ruleset for any other reason, you should probably use the `WordPress-Extra` or `WordPress` ruleset instead. +- The following sniffs have been deprecated and will be removed in WPCS 2.0.0: + - `WordPress.CSRF.NonceVerification` - use `WordPress.Security.NonceVerification` instead. + - `WordPress.Functions.DontExtract` - use `WordPress.PHP.DontExtract` instead. + - `WordPress.Variables.GlobalVariables` - use `WordPress.WP.GlobalVariablesOverride` instead. + - `WordPress.VIP.CronInterval` - use `WordPress.WP.CronInterval` instead. + - `WordPress.VIP.DirectDatabaseQuery` - use `WordPress.DB.DirectDatabaseQuery` instead. + - `WordPress.VIP.PluginMenuSlug` - use `WordPress.Security.PluginMenuSlug` instead. + - `WordPress.VIP.SlowDBQuery` - use `WordPress.DB.SlowDBQuery` instead. + - `WordPress.VIP.TimezoneChange` - use `WordPress.WP.TimezoneChange` instead. + - `WordPress.VIP.ValidatedSanitizedInput` - use `WordPress.Security.ValidatedSanitizedInput` instead. + - `WordPress.WP.PreparedSQL` - use `WordPress.DB.PreparedSQL` instead. + - `WordPress.XSS.EscapeOutput` - use `WordPress.Security.EscapeOutput` instead. + - `WordPress.VIP.AdminBarRemoval` without replacement. + - `WordPress.VIP.FileSystemWritesDisallow` without replacement. + - `WordPress.VIP.OrderByRand` without replacement. + - `WordPress.VIP.RestrictedFunctions` without replacement. + - `WordPress.VIP.RestrictedVariables` without replacement. + - `WordPress.VIP.SessionFunctionsUsage` without replacement. + - `WordPress.VIP.SessionVariableUsage` without replacement. + - `WordPress.VIP.SuperGlobalInputUsage` without replacement. +- The following sniff categories have been deprecated and will be removed in WPCS 2.0.0: + - `CSRF` + - `Variables` + - `XSS` +- The `posts_per_page` property in the `WordPress.VIP.PostsPerPage` sniff has been deprecated as the related functionality has been moved to the `WordPress.WP.PostsPerPage` sniff. + See [WP PostsPerPage: post limit](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#wp-postsperpage-post-limit) for more information about this property. +- The `exclude` property which is available to most sniffs which extend the `AbstractArrayAssignmentRestrictions`, `AbstractFunctionRestrictions` and `AbstractVariableRestrictions` classes or any of their children, used to be a `string` property and expected a comma-delimited list of groups to exclude. + The type of the property has now been changed to `array`. Custom rulesets which pass this property need to be adjusted to reflect this change. + Support for passing the property as a comma-delimited string has been deprecated and will be removed in WPCS 2.0.0. + See [Excluding a group of checks](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#excluding-a-group-of-checks) for more information about the sniffs affected by this change. +- The `AbstractVariableRestrictionsSniff` class has been deprecated as all sniffs depending on this class have been deprecated. Unless a new sniff is created in the near future which uses this class, the abstract class will be removed in WPCS 2.0.0. +- The `Sniff::has_html_open_tag()` utility method has been deprecated as it is now only used by deprecated sniffs. The method will be removed in WPCS 2.0.0. + +### Removed +- `cancel_comment_reply_link()`, `get_bookmark()`, `get_comment_date()`, `get_comment_time()`, `get_template_part()`, `has_post_thumbnail()`, `is_attachement()`, `post_password_required()` and `wp_attachment_is_image()` from the list of auto-escaped functions `Sniff::$autoEscapedFunctions`. This affects the `WordPress.Security.EscapeOutput` sniff. +- WPCS no longer explicitly supports HHVM and builds are no longer tested against HHVM. + For now, running WPCS on HHVM to test PHP code may still work for a little while, but HHVM has announced they are [dropping PHP support](https://hhvm.com/blog/2017/09/18/the-future-of-hhvm.html). + +### Fixed +- Compatibility with PHP 7.3. A change in PHP 7.3 was causing the `WordPress.DB.RestrictedClasses`, `WordPress.DB.RestrictedFunctions` and the `WordPress.WP.AlternativeFunctions` sniffs to fail to correctly detect issues. +- Compatibility with the latest releases from [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer). + PHPCS 3.2.0 introduced new annotations which can be used inline to selectively disable/ignore certain sniffs. + **Note**: The initial implementation of the new annotations was buggy. If you intend to start using these new style annotations, you are strongly advised to use PHPCS 3.3.0 or higher. + For more information about these annotations, please refer to the [PHPCS Wiki](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#ignoring-parts-of-a-file). + - The [WPCS native whitelist comments](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Whitelisting-code-which-flags-errors) can now be combined with the new style PHPCS whitelist annotations in the `-- for reasons` part of the annotation. + - `WordPress.Arrays.ArrayDeclarationSpacing`: the fixer will now handle the new style annotations correctly. + - `WordPress.Arrays.CommaAfterArrayItem`: prevent a fixer loop when new style annotations are encountered. + - `WordPress.Files.FileName`: respect the new style annotations if these would selectively disable this sniff. + - `WordPress.WhiteSpace.ControlStructureSpacing`: handle the new style annotations correctly for the "blank line at the start/end of control structure" checks and prevent a fixer conflict when the new style annotations are encountered. + - `WordPress.WhiteSpace.PrecisionAlignment`: allow for checking of for precision alignment on lines containing new style annotations when `phpcs` is run with `--ignore-annotations`. +- The `Sniff::is_test_class()` method now has improved recognition of namespaced test classes. + This positively affects the `WordPress.Files.FileName`, `WordPress.NamingConventions.PrefixAllGlobals` and `WordPress.WP.GlobalVariablesOverride` sniffs, which each allow for test classes to (partially) not comply with the rules these sniffs check for. + This fixes the following bugs: + - Namespaced classes where the classname was one of the whitelisted global classes would incorrectly be recognized as a test class, even though they were not the same class. + This also happened if a namespaced class `extend`ed one of the whitelisted global classes. + - A namespaced custom test class where the name was split between the namespace declaration and the extended class declaration was not correctly recognized as the whitelisted test class. + - A namespaced test class which extended another class using a FQCN prefixed with a `\\` would not be correctly recognized. + - The `custom_test_class_whitelist` property which is available for each of these sniffs expects to be passed a Fully Qualified Class Name. FQCNs prefixed with a global namespace indicator will now be correctly handled. +- The determination of whether a `T_STRING` is a function call or not has been improved in the `AbstractFunctionRestrictions` class. This improvement benefits all sniffs which extend this abstract and any of its children (> 10 sniffs) and fixes the following false positives: + - Class declarations will no longer be confused with function calls. + - Use statement alias declarations will no longer be confused with function calls. +- Various bugs in the `WordPress.Arrays.ArrayIndentation` sniff: + - The sniff will no longer throw false positives or try to fix multi-line text strings where the closing quote is on a line by itself. + - The sniff would go into a fixer loop when it encountered a multi-line trailing comment after an array item. +- The `WordPress.CodeAnalysis.AssignmentInCondition` was throwing false positives for ternaries in nested, but unrelated, parentheses. +- The `WordPress.CodeAnalysis.EmptyStatement` and `WordPress.Files.FileName` sniffs underreported as they did not take PHP short open echo tags into account. +- Various bugs in the `WordPress.NamingConventions.PrefixAllGlobals` sniff: + - Parameters in a closure declaration were incorrectly being regarded as global variables. + - Non-prefixed variables created by a `foreach()` construct in the global namespace were previously not detected. + - Non-prefixed globals found in namespaced test classes should be ignored by the sniff, but were not. + - Definition of non-prefixed global WP constants which are intended to be overruled, should not trigger an error from this sniff. + - The sniff presumed the WP naming conventions for PHP constructs, while it should check for the construct being prefixed regardless of whether camelCase, PascalCase, snake_case or other naming conventions are used. + - The sniff presumed the WP naming conventions for prefixes used in hook names. The sniff will now be more tolerant when non-conventional word separators are used in prefixes for hooks. +- The `WordPress.NamingConventions.ValidFunctionName` sniff no longer "hides" one message behind another. The sniff will now correctly throw a message about function names not being in `snake_case`, even when the `FunctionDoubleUnderscore` or `MethodDoubleUnderscore` error codes have been excluded. +- The `WordPress.PHP.StrictInArray` sniff will no longer throw an error when `in_array`, `array_search` or `array_keys` are used in a file `use` statement. +- Various bugs in the `WordPress.Security.EscapeOutput` sniff: + - A limited list of native PHP constants which are safe to use, such as `PHP_EOL`, has been added. When any of these constants are encountered, the sniff will no longer demand output escaping for them. + - The sniff was underreporting issues with variables passed to `trigger_error()`. + - While reporting an issue, sometimes the wrong error message was used. The sniff logic has been adjusted to prevent this. + - The sniff will now correctly ignore the open and close brackets of short arrays. + - The sniff would throw false positives when `echo`, `print`, `exit` or `die` were encountered as constants, function or class names. While it may not be a good idea to use PHP keywords in such a way, it is allowed, so the sniff should handle this correctly. +- The `WordPress.WhiteSpace.ControlStructureSpacing` sniff would inadvertently throw an error for the spacing around the colon for a return type in a function declaration. +- The `WordPress.WP.AlternativeFunctions` sniff used to flag all function calls to `file_get_contents()` twice, suggesting to use `wp_remote_get()` - which is only applicable for remote URLs - and the `WP_FileSystem` API - which is not needed when just _reading_ local files. These messages contradicted each other. + The sniff will now try to determine whether the file requested is local or remote and will only throw a `warning` suggesting to use `wp_remote_get()`, if a remote URL is being requested or when it could not be determined if the requested file is local or remote. +- The expected default value for `wp_upload_bits()` in the `WordPress.WP.DeprecatedParameters` sniff. +- The `WordPress.WP.GlobalVariablesOverride` sniff previously did not detect variables created by a `foreach()` construct which would override WP global variables. +- Various bugs in the `WordPress.WP.I18n` sniff: + - The sniff will no longer throw false positives for calls to methods carrying the same name as any of the global WP functions being targeted and has improved handling of parse errors and live coding. + - A numeric `0` would throw a false positive for "no translatable content found". +- The fixer in the `WordPress.WhiteSpace.ControlStructureSpacing` sniff will no longer inadvertently remove return type declarations. +- Various bugs in the `WordPress.WhiteSpace.PrecisionAlignment` sniff: + - Inline HTML before the first PHP open tag was not being examined. + - Files which only contained short open echo tags for PHP were not being examined. + - The last line of inline HTML in a file was not being examined. +- Some best practice sniffs presumed the WordPress coding style regarding code layout, which could lead to incorrect results (mostly underreporting). + The following sniffs have received fixes related to this: + - `WordPress.DB.PreparedSQL` + - `WordPress.NamingConventions.ValidVariableName` + - `WordPress.WP.CronInterval` + - `WordPress.WP.I18n` +- Various minor fixes based on visual inspection and Scrutinizer analysis feedback. +- Typo in the instructions contained in `CONTRIBUTING.md`. +- Broken link in the `README.md` file. + + +## [0.14.1] - 2018-02-15 + +### Fixed +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff contained a bug which could inadvertently trigger class autoloading of the project being sniffed and by extension could cause fatal errors during the PHPCS run. + +## [0.14.0] - 2017-11-01 + +### Added +- `WordPress.Arrays.MultipleStatementAlignment` sniff to the `WordPress-Core` ruleset which will align the array assignment operator for multi-item, multi-line associative arrays. + This new sniff offers four custom properties to customize its behaviour: [`ignoreNewlines`](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#array-alignment-allow-for-new-lines), [`exact`](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#array-alignment-allow-non-exact-alignment), [`maxColumn`](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#array-alignment-maximum-column) and [`alignMultilineItems`](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#array-alignment-dealing-with-multi-line-items). +- `WordPress.DB.PreparedSQLPlaceholders` sniff to the `WordPress-Core` ruleset which will analyse the placeholders passed to `$wpdb->prepare()` for their validity, check whether queries using `IN ()` and `LIKE` statements are created correctly and will check whether a correct number of replacements are passed. + This sniff should help detect queries which are impacted by the security fixes to `$wpdb->prepare()` which shipped with WP 4.8.2 and 4.8.3. + The sniff also adds a new ["PreparedSQLPlaceholders replacement count" whitelist comment](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Whitelisting-code-which-flags-errors#preparedsql-placeholders-vs-replacements) for pertinent replacement count vs placeholder mismatches. Please consider carefully whether something could be a bug when you are tempted to use the whitelist comment and if so, [report it](https://github.com/WordPress/WordPress-Coding-Standards/issues/new). +- `WordPress.PHP.DiscourageGoto` sniff to the `WordPress-Core` ruleset. +- `WordPress.PHP.RestrictedFunctions` sniff to the `WordPress-Core` ruleset which initially forbids the use of `create_function()`. + This was previous only discouraged under certain circumstances. +- `WordPress.WhiteSpace.ArbitraryParenthesesSpacing` sniff to the `WordPress-Core` ruleset which checks the spacing on the inside of arbitrary parentheses. +- `WordPress.WhiteSpace.PrecisionAlignment` sniff to the `WordPress-Core` ruleset which will throw a warning when precision alignment is detected in PHP, JS and CSS files. +- `WordPress.WhiteSpace.SemicolonSpacing` sniff to the `WordPress-Core` ruleset which will throw a (fixable) error when whitespace is found before a semi-colon, except for when the semi-colon denotes an empty `for()` condition. +- `WordPress.CodeAnalysis.AssignmentInCondition` sniff to the `WordPress-Extra` ruleset. +- `WordPress.WP.DiscouragedConstants` sniff to the `WordPress-Extra` and `WordPress-VIP` rulesets to detect usage of deprecated WordPress constants, such as `STYLESHEETPATH` and `HEADER_IMAGE`. +- Ability to pass the `minimum_supported_version` to use for the `DeprecatedFunctions`, `DeprecatedClasses` and `DeprecatedParameters` sniff in one go. You can pass a `minimum_supported_wp_version` runtime variable for this [from the command line or pass it using a `config` directive in a custom ruleset](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#setting-minimum-supported-wp-version-for-all-sniffs-in-one-go-wpcs-0140). +- `Generic.Formatting.MultipleStatementAlignment` - customized to have a `maxPadding` of `40` -, `Generic.Functions.FunctionCallArgumentSpacing` and `Squiz.WhiteSpace.ObjectOperatorSpacing` to the `WordPress-Core` ruleset. +- `Squiz.Scope.MethodScope`, `Squiz.Scope.MemberVarScope`, `Squiz.WhiteSpace.ScopeKeywordSpacing`, `PSR2.Methods.MethodDeclaration`, `Generic.Files.OneClassPerFile`, `Generic.Files.OneInterfacePerFile`, `Generic.Files.OneTraitPerFile`, `PEAR.Files.IncludingFile`, `Squiz.WhiteSpace.LanguageConstructSpacing`, `PSR2.Namespaces.NamespaceDeclaration` to the `WordPress-Extra` ruleset. +- The `is_class_constant()`, `is_class_property` and `valid_direct_scope()` utility methods to the `WordPress\Sniff` class. + +### Changed +- When passing an array property via a custom ruleset to PHP_CodeSniffer, spaces around the key/value are taken as intentional and parsed as part of the array key/value. In practice, this leads to confusion and WPCS does not expect any values which could be preceded/followed by a space, so for the WordPress Coding Standard native array properties, like `customAutoEscapedFunction`, `text_domain`, `prefixes`, WPCS will now trim whitespace from the keys/values received before use. +- The WPCS native whitelist comments used to only work when they were put on the _end of the line_ of the code they applied to. As of now, they will also be recognized when they are be put at the _end of the statement_ they apply to. +- The `WordPress.Arrays.ArrayDeclarationSpacing` sniff used to enforce all associative arrays to be multi-line. The handbook has been updated to only require this for multi-item associative arrays and the sniff has been updated accordingly. + [The original behaviour can still be enforced](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#arrays-forcing-single-item-associative-arrays-to-be-multi-line) by setting the new `allow_single_item_single_line_associative_arrays` property to `false` in a custom ruleset. +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff will now allow for a limited list of WP core hooks which are intended to be called by plugins and themes. +- The `WordPress.PHP.DiscouragedFunctions` sniff used to include `create_function`. This check has been moved to the new `WordPress.PHP.RestrictedFunctions` sniff. +- The `WordPress.PHP.StrictInArray` sniff now has a separate error code `FoundNonStrictFalse` for when the `$strict` parameter has been set to `false`. This allows for excluding the warnings for that particular situation, which will normally be intentional, via a custom ruleset. +- The `WordPress.VIP.CronInterval` sniff now allows for customizing the minimum allowed cron interval by [setting a property in a custom ruleset](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#vip-croninterval-minimum-interval). +- The `WordPress.VIP.RestrictedFunctions` sniff used to prohibit the use of certain WP native functions, recommending the use of `wpcom_vip_get_term_link()`, `wpcom_vip_get_term_by()` and `wpcom_vip_get_category_by_slug()` instead, as the WP native functions were not being cached. As the results of the relevant WP native functions are cached as of WP 4.8, the advice has now been reversed i.e. use the WP native functions instead of `wpcom...` functions. +- The `WordPress.VIP.PostsPerPage` sniff now allows for customizing the `post_per_page` limit for which the sniff will trigger by [setting a property in a custom ruleset](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#vip-postsperpage-post-limit). +- The `WordPress.WP.I18n` sniff will now allow and actively encourage omitting the text domain in I18n function calls if the text domain passed via the `text_domain` property is `default`, i.e. the domain used by Core. + When `default` is one of several text domains passed via the `text_domain` property, the error thrown when the domain is missing has been downgraded to a `warning`. +- The `WordPress.XSS.EscapeOutput` sniff now has a separate error code `OutputNotEscapedShortEcho` and the error message texts have been updated. +- Moved `Squiz.PHP.Eval` from the `WordPress-Extra` and `WordPress-VIP` to the `WordPress-Core` ruleset. +- Removed two sniffs from the `WordPress-VIP` ruleset which were already included via the `WordPress-Core` ruleset. +- The unit test suite is now compatible with PHPCS 3.1.0+ and PHPUnit 6.x. +- Some tidying up of the unit test case files. +- All sniffs are now also being tested against PHP 7.2 for consistent sniff results. +- An attempt is made to detect potential fixer conflicts early via a special build test. +- Various minor documentation fixes. +- Improved the Atom setup instructions in the Readme. +- Updated the unit testing information in Contributing. +- Updated the [custom ruleset example](https://github.com/WordPress/WordPress-Coding-Standards/blob/develop/phpcs.xml.dist.sample) for the changes contained in this release and to make it more explicit what is recommended versus example code. +- The minimum recommended version for the suggested `DealerDirect/phpcodesniffer-composer-installer` Composer plugin has gone up to `0.4.3`. This patch version fixes support for PHP 5.3. + +### Fixed +- The `WordPress.Arrays.ArrayIndentation` sniff did not correctly handle array items with multi-line strings as a value. +- The `WordPress.Arrays.ArrayIndentation` sniff did not correctly handle array items directly after an array item with a trailing comment. +- The `WordPress.Classes.ClassInstantiation` sniff will now correctly handle detection when using `new $array['key']` or `new $array[0]`. +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff did not allow for arbitrary word separators in hook names. +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff did not correctly recognize namespaced constants as prefixed. +- The `WordPress.PHP.StrictInArray` sniff would erronously trigger if the `true` for `$strict` was passed in uppercase. +- The `WordPress.PHP.YodaConditions` sniff could get confused over complex ternaries containing assignments. This has been remedied. +- The `WordPress.WP.PreparedSQL` sniff would erronously throw errors about comments found within a DB function call. +- The `WordPress.WP.PreparedSQL` sniff would erronously throw errors about `(int)`, `(float)` and `(bool)` casts and would also flag the subsequent variable which had been safe casted. +- The `WordPress.XSS.EscapeOutput` sniff would erronously trigger when using a fully qualified function call - including the global namespace `\` indicator - to one of the escaping functions. +- The lists of WP global variables and WP mixed case variables have been synchronized, which fixes some false positives. + + +## [0.13.1] - 2017-08-07 + +### Fixed +- Fatal error when using PHPCS 3.x with the `installed_paths` config variable set via the ruleset. + +## [0.13.0] - 2017-08-03 + +### Added +- Support for PHP_CodeSniffer 3.0.2+. The minimum required PHPCS version (2.9.0) stays the same. +- Support for the PHPCS 3 `--ignore-annotations` command line option. If you pass this option, both PHPCS native `@ignore ...` annotations as well as the WPCS specific [whitelist flags](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Whitelisting-code-which-flags-errors) will be ignored. + +### Changed +- The minimum required PHP version is now 5.3 when used in combination with PHPCS 2.x and PHP 5.4 when used in combination with PHPCS 3.x. +- The way the unit tests can be run is now slightly different for PHPCS 2.x versus 3.x. For more details, please refer to the updated information in the [Contributing Guidelines](CONTRIBUTING.md). +- Release archives will no longer contain the unit tests and other typical development files. You can still get these by using Composer with `--prefer-source` or by checking out a git clone of the repository. +- Various textual improvements to the Readme. +- Various textual improvements to the Contributing Guidelines. +- Minor internal changes. + +### Removed +- The `WordPress.Arrays.ArrayDeclaration` sniff has been deprecated. The last remaining checks this sniff contained have been moved to the `WordPress.Arrays.ArrayDeclarationSpacing` sniff. +- Work-arounds which were in place to support PHP 5.2. + +### Fixed +- A minor bug where the auto-fixer could accidentally remove a comment near an array opener. + + +## [0.12.0] - 2017-07-21 + +### Added +- A default file encoding setting to the `WordPress-Core` ruleset. All files sniffed will now be regarded as `utf-8` by default. +- `WordPress.Arrays.ArrayIndentation` sniff to the `WordPress-Core` ruleset to verify - and auto-fix - the indentation of array items and the array closer for multi-line arrays. This replaces the (partial) indentation fixing contained within the `WordPress.Array.ArrayDeclarationSpacing` sniff. +- `WordPress.Arrays.CommaAfterArrayItem` sniff to the `WordPress-Core` ruleset to enforce that each array item is followed by a comma - except for the last item in a single-line array - and checks the spacing around the comma. This replaces (and improves) the checks which were previously included in the `WordPress.Arrays.ArrayDeclaration` sniff which were causing incorrect fixes and fixer conflicts. +- `WordPress.Functions.FunctionCallSignatureNoParams` sniff to the `WordPress-Core` ruleset to verify that function calls without parameters do not have any whitespace between the parentheses. +- `WordPress.WhiteSpace.DisallowInlineTabs` to the `WordPress-Core` ruleset to verify - and auto-fix - that spaces are used for mid-line alignment. +- `WordPress.WP.CapitalPDangit` sniff to the `WordPress-Core` ruleset to - where relevant - verify that `WordPress` is spelled correctly. For misspellings in text strings and comment text, the sniff can auto-fix violations. +- `Squiz.Classes.SelfMemberReference` whitespace related checks to the `WordPress-Core` ruleset and the additional check for using `self` rather than a FQN to the `WordPress-Extra` ruleset. +- `Squiz.PHP.EmbeddedPhp` sniff to the `WordPress-Core` ruleset to check PHP code embedded within HTML blocks. +- `PSR2.ControlStructures.SwitchDeclaration` to the `WordPress-Core` ruleset to check for the correct layout of `switch` control structures. +- `WordPress.Classes.ClassInstantion` sniff to the `WordPress-Extra` ruleset to detect - and auto-fix - missing parentheses on object instantiation and superfluous whitespace in PHP and JS files. The sniff will also detect `new` being assigned by reference. +- `WordPress.CodeAnalysis.EmptyStatement` sniff to the `WordPress-Extra` ruleset to detect - and auto-fix - superfluous semi-colons and empty PHP open-close tag combinations. +- `WordPress.NamingConventions.PrefixAllGlobals` sniff to the `WordPress-Extra` ruleset to verify that all functions, classes, interfaces, traits, variables, constants and hook names which are declared/defined in the global namespace are prefixed with one of the prefixes provided via a custom property or via the command line. + To activate this sniff, [one or more allowed prefixes should be provided to the sniff](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#naming-conventions-prefix-everything-in-the-global-namespace). This can be done using a custom ruleset or via the command line. + PHP superglobals and WP global variables are exempt from variable name prefixing. Deprecated hook names will also be disregarded when non-prefixed. Back-fills for known native PHP functionality is also accounted for. + For verified exceptions, [unprefixed code can be whitelisted](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Whitelisting-code-which-flags-errors#non-prefixed-functionclassvariableconstant-in-the-global-namespace). + Code in unit test files is automatically exempt from this sniff. +- `WordPress.WP.DeprecatedClasses` sniff to the `WordPress-Extra` ruleset to detect usage of deprecated WordPress classes. +- `WordPress.WP.DeprecatedParameters` sniff to the `WordPress-Extra` ruleset to detect deprecated parameters being passed to WordPress functions with a value other than the expected default. +- The `sanitize_textarea_field()` function to the `sanitizingFunctions` list used by the `WordPress.CSRF.NonceVerification`, `WordPress.VIP.ValidatedSanitizedInput` and `WordPress.XSS.EscapeOutput` sniffs. +- The `find_array_open_closer()` utility method to the `WordPress_Sniff` class. +- Information about setting `installed_paths` using a custom ruleset to the Readme. +- Additional support links to the `composer.json` file. +- Support for Composer PHPCS plugins which sort out the `installed_paths` setting. +- Linting and code-style check of the XML ruleset files provided by WPCS. + +### Changed +- The minimum required PHP_CodeSniffer version to 2.9.0 (was 2.8.1). **Take note**: PHPCS 3.x is not (yet) supported. The next release is expected to fix that. +- Improved support for detecting issues in code using heredoc and/or nowdoc syntax. +- Improved sniff efficiency, precision and performance for a number of sniffs. +- Updated a few sniffs to take advantage of new features and fixes which are included in PHP_CodeSniffer 2.9.0. +- `WordPress.Files.Filename`: The "file name mirrors the class name prefixed with 'class'" check for PHP files containing a class will no longer be applied to typical unit test classes, i.e. for classes which extend `WP_UnitTestCase`, `PHPUnit_Framework_TestCase` and `PHPUnit\Framework\TestCase`. Additional test case base classes can be passed to the sniff using the new [`custom_test_class_whitelist` property](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#custom-unit-test-classes). +- The `WordPress.Files.FileName` sniff allows now for more theme-specific template hierarchy based file name exceptions. +- The whitelist flag for the `WordPress.VIP.SlowQuery` sniff was `tax_query` which was unintuitive. This has now been changed to `slow query` to be in line with other whitelist flags. +- The `WordPress.WhiteSpace.OperatorSpacing` sniff will now ignore operator spacing within `declare()` statements. +- The `WordPress.WhiteSpace.OperatorSpacing` sniff now extends the upstream `Squiz.WhiteSpace.OperatorSpacing` sniff for improved results and will now also examine the spacing around ternary operators and logical (`&&`, `||`) operators. +- The `WordPress.WP.DeprecatedFunctions` sniff will now detect functions deprecated in WP 4.7 and 4.8. Additionally, a number of other deprecated functions which were previously not being detected have been added to the sniff and for a number of functions the "alternative" for the deprecated function has been added/improved. +- The `WordPress.XSS.EscapeOutput` sniff will now also detect unescaped output when the short open echo tags `` PHP open tags. +- `WordPress.Classes.ClassOpeningStatement` sniff to the `WordPress-Core` ruleset to flag - and fix - class opening brace placement. +- `WordPress.NamingConventions.ValidHookName` sniff to the `WordPress-Core` ruleset to flag filter and action hooks which don't comply with the guideline of lowercase letters and underscores. For maintaining backward-compatibility of hook names an `additionalWordDelimiters` property can be added via a custom ruleset. +- `WordPress.Functions.DontExtract` sniff to the `WordPress-Core` ruleset to flag usage of the `extract()` function. +- `WordPress.PHP.POSIXFunctions` sniff to the `WordPress-Core` ruleset to flag usage of regex functions from the POSIX PHP extension which was deprecated since PHP 5.3 and removed in PHP 7. +- `WordPress.DB.RestrictedFunctions` and `WordPress.DB.RestrictedClasses` sniffs to the `WordPress-Core` ruleset to flag usage of direct database calls using PHP functions and classes rather than the WP functions for the same. +- Abstract `AbstractClassRestrictions` parent class to allow for easier sniffing for usage of specific classes. +- `Squiz.Strings.ConcatenationSpacing`, `PSR2.ControlStructures.ElseIfDeclaration`, `PSR2.Files.ClosingTag`, `Generic.NamingConventions.UpperCaseConstantName` to the `WordPress-Core` ruleset. +- Ability to add arbitrary variables to the whitelist via a custom ruleset property for the `WordPress.NamingConventions.ValidVariableName` sniff. +- Ability to use a whitelist comment for tax queries for the `WordPress.VIP.SlowDBQuery` sniff. +- Instructions on how to use WPCS with Atom and SublimeLinter to the Readme. +- Reference to the [wiki](https://github.com/WordPress/WordPress-Coding-Standards/wiki) to the Readme. +- Recommendation to also use the [PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility) ruleset to the Readme. + +### Changed +- The minimum required PHP_CodeSniffer version to 2.6.0. +- Moved the `WordPress.WP.PreparedSQL` sniff from `WordPress-Extra` to `WordPress-Core`. +- `WordPress.PHP.StrictInArray` will now also flag non-strict usage of `array_keys()` and `array_search()`. +- Added `_deprecated_constructor()` and `_deprecated_hook()` to the list of printing functions. +- Added numerous additional functions to sniff for to the `WordPress.VIP.RestrictedFunctions` sniff as per the VIP guidelines. +- Upped the `posts_per_page` limit from 50 to 100 in `WordPress.VIP.PostsPerPage` sniff as per the VIP guidelines. +- Added `cat_ID` to the whitelisted exceptions for the `WordPress.NamingConventions.ValidVariableName` sniff. +- Added `__debugInfo` to the magic method whitelist for class methods starting with double underscore in the `WordPress.NamingConventions.ValidFunctionName` sniff. +- An error will now also be thrown for non-magic _functions_ using a double underscore prefix - `WordPress.NamingConventions.ValidFunctionName` sniff. +- The `WordPress.Arrays.ArrayAssignmentRestrictions`, `WordPress.Functions.FunctionRestrictions`, `WordPress.Variables.VariableRestrictions` sniffs weren't in actual fact sniffs, but parent classes for child sniffs. These have now all been turned into proper abstract parent classes and moved to the main `WordPress` directory. +- The array provided to `AbstractFunctionRestrictions` can now take a `whitelist` key to whitelist select functions when blocking a group of functions by function prefix. +- Updated installation instructions in the readme. +- The `WordPress-Core` ruleset is now ordered according to the handbook +- The WPCS code base itself now complies with the WordPress-Core, -Extra and -Docs coding standards. +- Various other code quality and code consistency improvements under the hood. + +### Removed +- `Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingBeforeClose` from the `WordPress-Core` standard (was causing duplicate messages for the same issue). +- `Squiz.Commenting.FunctionComment.ScalarTypeHintMissing`, `Squiz.Commenting.InlineComment.NotCapital` from the `WordPress-Docs` standard. +- Removed the sniffing for `get_pages()` from the `WordPress.VIP.RestrictedFunctions` sniff as per the VIP guidelines. +- Removed the sniffing for `extract()` from the `WordPress.VIP.RestrictedFunctions` sniff as it's now covered in a separate sniff. +- Removed the sniffing for the POSIX functions from the `WordPress.PHP.DiscouragedFunctions` sniff as it's now covered in a separate sniff. + +### Fixed +- Error message precision for the `WordPress.NamingConventions.ValidVariableName` sniff. +- Bug in the `WordPress.WhiteSpace.ControlStructureSpacing.BlankLineAfterEnd` sniff which was incorrectly being triggered on last method of class. +- Function name sniffs based on the `AbstractFunctionRestrictions` parent class will now do a case-insensitive function name comparison. +- Function name sniffs in the `WordPress.PHP.DiscouragedFunctions` sniff will now do a case-insensitive function name comparison. +- Whitelist comments directly followed by a PHP closing tag were not being recognized. +- Some PHP Magic constants were not recognized by the `WordPress.XSS.EscapeOutput` sniff. +- An error message suggesting camel caps rather than the intended snake case format in the `WordPress.NamingConventions.ValidFunctionName` sniff. +- `WordPress.WhiteSpace.ControlStructureSpacing` should no longer throw error notices during live code review. +- Errors will be no longer be thrown for methods not complying with the naming conventions when the class extends a parent class or implements an interface - `WordPress.NamingConventions.ValidFunctionName` sniff. + + +## [0.9.0] - 2016-02-01 + +### Added +- `count()` to the list of auto-escaped functions. +- `Squiz.PHP.CommentedOutCode` sniff to `WordPress-VIP` ruleset. +- Support for PHP 5.2. +- `attachment_url_to_postid()` and `parse_url()` to the restricted functions for `WordPress-VIP`. +- `WordPress.VIP.OrderByRand` sniff. +- `WordPress.PHP.StrictInArray` sniff for `WordPress-VIP` and `WordPress-Extra`. +- `get_tag_link()`, `get_category_link()`, `get_cat_ID()`, `url_to_post_id()`, `attachment_url_to_postid()` +`get_posts()`, `wp_get_recent_posts()`, `get_pages()`, `get_children()`, `wp_get_post_terms()` +`wp_get_post_categories()`, `wp_get_post_tags()`, `wp_get_object_terms()`, `term_exists()`, +`count_user_posts()`, `wp_old_slug_redirect()`, `get_adjacent_post()`, `get_previous_post()`, +`get_next_post()` to uncached functions in `WordPress.VIP.RestrictedFunctions` sniff. +- `wp_handle_upload()` and `array_key_exists()` to the list of sanitizing functions. +- Checking for object properties in `WordPress.PHP.YodaConditions` sniff. +- `WordPress.NamingConventions.ValidVariableName` sniff. +- Flagging of function calls incorporated into database queries in `WordPress.WP.PreparedSQL`. +- Recognition of escaping and auto-escaped functions in `WordPress.WP.PreparedSQL`. +- `true`, `false`, and `null` to the tokens ignored in `WordPress.XSS.EscapeOutput`. + +### Fixed +- Incorrect ternary detection in `WordPress.XSS.EscapeOutput` sniff. +- False positives when detecting variables interpolated into strings in the +`WordPress.WP.PreparedSQL` and `WordPress.VIP.ValidatedSanitizedInput` sniffs. +- False positives in `WordPress.PHP.YodaConditions` when the variable is being casted. +- `$wpdb` properties being flagged in `WordPress.WP.PreparedSQL` sniff. +- False positive in `WordPress.PHP.YodaConditions` when the a string is on the left side of the +comparison. + +## [0.8.0] - 2015-10-02 + +### Added +- `implode()` and `join()` to the list of formatting functions in the `WordPress.XSS.EscapeOutput` +sniff. This is useful when you need to have HTML in the `$glue` parameter. +- Support in the `WordPress.XSS.EscapeOutput` sniff for escaping an array of values +using `array_map()`. (Otherwise the support for `implode()` isn't of much use :) +- Docs for running WPCS in Sublime Text. +- `nl2br()` to the list of formatting functions. +- `wp_dropdown_pages()` to the list of printing functions. +- Error codes to all error/warning messages. +- `WordPress.WP.PreparedSQL` sniff for flagging unprepared SQL queries. + +### Removed +- Sniffing for the number of spaces before a closure's opening parenthesis from the +default configuration of the `WordPress.WhiteSpace.ControlStructureSpacing` sniff. It +can be re-enabled per-project as desired. + +### Fixed +- The `WordPress.XSS.EscapeOutput` sniff giving error messages with the closing +parenthesis in them instead of the offending function's name. + +## [0.7.1] - 2015-08-31 + +### Changed +- The default number of spaces before a closure's opening parenthesis from 1 to 0. + +## [0.7.0] - 2015-08-30 + +### Added +- Automatic error fixing to the `WordPress.Arrays.ArrayKeySpacingRestrictions` sniff. +- Functions and closures to the control structures checked by the `WordPress.WhiteSpace.ControlStructureSpacing` +sniff. +- Sniffing and fixing for extra spacing in the `WordPress.WhiteSpace.ControlStructureSpacing` +sniff. (Previously it only checked for insufficient spacing.) +- `.twig` files to the default ignored files. +- `esc_url_raw()` and `hash_equals()` to the list of sanitizing functions. +- `intval()` and `boolval()` to list of unslashing functions. +- `do_shortcode()` to the list of auto-escaped functions. + +### Removed +- `WordPress.Functions.FunctionDeclarationArgumentSpacing` in favor of the upstream +sniff `Squiz.Functions.FunctionDeclarationArgumentSpacing`. + +### Fixed +- Reference to incorrect issue in the inline docs of the `WordPress.VIP.SessionVariableUsage` +sniff. +- `WordPress.XSS.EscapeOutput` sniff incorrectly handling ternary conditions in +`echo` statements without parentheses in some cases. + +## [0.6.0] - 2015-06-30 + +### Added +- Support for `wp_cache_add()` and `wp_cache_delete()`, as well as custom cache +functions,in the `WordPress.VIP.DirectDatabaseQuery` sniff. + +### Removed +- `WordPress.Functions.FunctionRestrictions` and `WordPress.Variables.VariableRestrictions` +from the `WordPress-VIP` standard, since they are just parents for other sniffs. + +## [0.5.0] - 2015-06-01 + +### Added +- `WordPress.CSRF.NonceVerification` sniff to flag form processing without nonce verification. +- `in_array()` and `is_array()` to the list of sanitizing functions. +- Support for automatic error fixing to the `WordPress.Arrays.ArrayDeclaration` sniff. +- `WordPress.PHP.StrictComparisions` to the `WordPress-VIP` and `WordPress-Extra` rulesets. +- `WordPress-Docs` ruleset to sniff for proper commenting. +- `Generic.PHP.LowerCaseKeyword`, `Generic.Files.EndFileNewline`, `Generic.Files.LowercasedFilename`, +`Generic.Formatting.SpaceAfterCast`, and `Generic.Functions.OpeningFunctionBraceKernighanRitchie` to the `WordPress-Core` ruleset. +- `Generic.PHP.DeprecatedFunctions`, `Generic.PHP.ForbiddenFunctions`, `Generic.Functions.CallTimePassByReference`, +`Generic.Formatting.DisallowMultipleStatements`, `Generic.CodeAnalysis.EmptyStatement`, +`Generic.CodeAnalysis.ForLoopShouldBeWhileLoop`, `Generic.CodeAnalysis.ForLoopWithTestFunctionCall`, +`Generic.CodeAnalysis.JumbledIncrementer`, `Generic.CodeAnalysis.UnconditionalIfStatement`, +`Generic.CodeAnalysis.UnnecessaryFinalModifier`, `Generic.CodeAnalysis.UselessOverridingMethod`, +`Generic.Classes.DuplicateClassName`, and `Generic.Strings.UnnecessaryStringConcat` to the `WordPress-Extra` ruleset. +- Error for missing use of `wp_unslash()` on superglobal data to the `WordPress.VIP.ValidatedSanitizedInput` sniff. + +### Changed +- The `WordPress.VIP.ValidatedSanitizedInput` sniff to require sanitization of input even when it is being directly escaped and output. +- The minimum required PHP_CodeSniffer version to 2.2.0. +- The `WordPress.VIP.ValidatedSanitizedInput` and `WordPress.XSS.EscapeOutput` sniffs: +the list of escaping functions was split from the list of sanitizing functions. The `customSanitizingFunctions` +property has been moved to the `ValidatedSanitizedInput` sniff, and the `customEscapingFunctions` +property should now be used instead for the `EscapeOutput` sniff. +- The `WordPress.Arrays.ArrayDeclaration` sniff to give errors for `NoSpaceAfterOpenParenthesis`, `SpaceAfterArrayOpener`, and `SpaceAfterArrayCloser`, instead of warnings. +- The `WordPress.NamingConventions.ValidFunctionName` sniff to allow camelCase method names in classes that implement interfaces. + +### Fixed +- The `WordPress.VIP.ValidatedSanitizedInput` sniff not reporting missing validation when reporting missing sanitization. +- The `WordPress.VIP.ValidatedSanitizedInput` sniff flagging superglobals as needing sanitization when they were only being used in a comparison using `if` or `switch`, etc. + +## [0.4.0] - 2015-05-01 + +### Added +- Change log file. +- Handling for string-interpolated input variables in the `WordPress.VIP.ValidatedSanitizedInput` sniff. +- Errors for using uncached functions when cached equivalents exist. +- `space_before_colon` setting for the `WordPress.WhiteSpace.ControlStructureSpacing` sniff, for control structures using alternative syntax. Possible values: `'required'`, `'optional'`, `'forbidden'`. +- Support for `sanitization` whitelisting comments for the `WordPress.VIP.ValidatedSanitizedInput` sniff. +- Granular error/warning names for all errors and warnings. +- Handling for ternary conditions in the `WordPress.XSS.EscapeOutput` sniff. +- `die`, `exit`, `printf`, `vprintf`, `wp_die`, `_deprecated_argument`, `_deprecated_function`, `_deprecated_file`, `_doing_it_wrong`, `trigger_error`, and `user_error` to the list of printing functions in the `WordPress.XSS.EscapeOutput` sniff. +- `customPrintingFunctions` setting for the `WordPress.XSS.EscapeOutput` sniff. +- `rawurlencode()` and `wp_parse_id_list()` to the list of "sanitizing" functions in the `WordPress.XSS.EscapeOutput` sniff. +- `json_encode()` to the list of discouraged functions in the `WordPress.PHP.DiscouragedFunctions` sniff, in favor of `wp_json_encode()`. +- `vip_powered_wpcom()` to the list of auto-escaped functions in the `WordPress.XSS.EscapeOutput` sniff. +- `debug_print_backtrace()` and `var_export()` to the list of discouraged functions in the `WordPress.PHP.DiscouragedFunctions` sniff. +- Smart handling for formatting functions (`sprintf()` and `wp_sprintf()`) in the `WordPress.XSS.EscapeOutput` sniff. +- `WordPress.PHP.StrictComparisons` sniff. +- Correct handling of `array_map()` in the `WordPress.VIP.ValidatedSanitizedInput` sniff. +- `$_COOKIE` and `$_FILE` to the list of superglobals flagged by the `WordPress.VIP.ValidatedSanitizedInput` and `WordPress.VIP.SuperGlobalInputUsage` sniffs. +- `$_SERVER` to the list of superglobals flagged by the `WordPress.VIP.SuperGlobalInputUsage` sniff. +- `Squiz.ControlStructures.ControlSignature` sniff to the rulesets. + +### Changed +- `WordPress.Arrays.ArrayKeySpacingRestrictions` sniff to give errors for `NoSpacesAroundArrayKeys` and `SpacesAroundArrayKeys` instead of just warnings. +- `WordPress.NamingConventions.ValidFunctionName` sniff to allow for camel caps method names in child classes. +- `WordPress.XSS.EscapeOutput` sniff to allow for integers (e.g. `echo 5` and `print( -1 )`). + +### Removed +- Errors for mixed key/keyless array elements in the `WordPress.Arrays.ArrayDeclaration` sniff. +- BOM from `WordPress.WhiteSpace.OperatorSpacing` sniff file. +- `$content_width` from the list of non-overwritable globals in the `WordPress.Variables.GlobalVariables` sniff. +- `WordPress.Arrays.ArrayAssignmentRestrictions` sniff from the `WordPress-VIP` ruleset. + +### Fixed +- Incorrect errors for `else` statements using alternative syntax. +- `WordPress.VIP.ValidatedSanitizedInput` sniff not always treating casting as sanitization. +- `WordPress.XSS.EscapeOutput` sniff flagging comments as needing to be escaped. +- `WordPress.XSS.EscapeOutput` sniff not sniffing comma-delimited `echo` arguments after encountering the first escaping function in the statement. +- `WordPress.PHP.YodaConditions` sniff not flagging comparisons to constants or function calls. +- `WordPress.Arrays.ArrayDeclaration` sniff not ignoring doc comments. +- Link to phpStorm instructions in `README.md`. +- Poor performance of the `WordPress.Arrays.ArrayAssignmentRestrictions` sniff. +- Poor performance of the `WordPress.Files.FileName` sniff. + +## [0.3.0] - 2014-12-11 + +See the comparison for full list. + +### Changed +- Use semantic version tags for releases. + +## [2013-10-06] + +See the comparison for full list. + +## 2013-06-11 + +Initial tagged release. + +[Unreleased]: https://github.com/WordPress/WordPress-Coding-Standards/compare/master...HEAD +[2.2.1]: https://github.com/WordPress/WordPress-Coding-Standards/compare/2.2.0...2.2.1 +[2.2.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/2.1.1...2.2.0 +[2.1.1]: https://github.com/WordPress/WordPress-Coding-Standards/compare/2.1.0...2.1.1 +[2.1.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/2.0.0...2.1.0 +[2.0.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/2.0.0-RC1...2.0.0 +[2.0.0-RC1]: https://github.com/WordPress/WordPress-Coding-Standards/compare/1.2.1...2.0.0-RC1 +[1.2.1]: https://github.com/WordPress/WordPress-Coding-Standards/compare/1.2.0...1.2.1 +[1.2.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/1.1.0...1.2.0 +[1.1.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/1.0.0...1.1.0 +[1.0.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.14.1...1.0.0 +[0.14.1]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.14.0...0.14.1 +[0.14.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.13.1...0.14.0 +[0.13.1]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.13.0...0.13.1 +[0.13.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.12.0...0.13.0 +[0.12.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.11.0...0.12.0 +[0.11.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.10.0...0.11.0 +[0.10.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.9.0...0.10.0 +[0.9.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.8.0...0.9.0 +[0.8.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.7.1...0.8.0 +[0.7.1]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.7.0...0.7.1 +[0.7.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.6.0...0.7.0 +[0.6.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.5.0...0.6.0 +[0.5.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.4.0...0.5.0 +[0.4.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.3.0...0.4.0 +[0.3.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/2013-10-06...0.3.0 +[2013-10-06]: https://github.com/WordPress/WordPress-Coding-Standards/compare/2013-06-11...2013-10-06 diff --git a/vendor/wp-coding-standards/wpcs/LICENSE b/vendor/wp-coding-standards/wpcs/LICENSE new file mode 100644 index 00000000..359e1a72 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2009 John Godley and contributors. + +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/wp-coding-standards/wpcs/README.md b/vendor/wp-coding-standards/wpcs/README.md new file mode 100644 index 00000000..42eda804 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/README.md @@ -0,0 +1,296 @@ + + + +# WordPress Coding Standards for PHP_CodeSniffer + +* [Introduction](#introduction) +* [Project history](#project-history) +* [Installation](#installation) + + [Requirements](#requirements) + + [Composer](#composer) + + [Standalone](#standalone) +* [Rulesets](#rulesets) + + [Standards subsets](#standards-subsets) + + [Using a custom ruleset](#using-a-custom-ruleset) + + [Customizing sniff behaviour](#customizing-sniff-behaviour) + + [Recommended additional rulesets](#recommended-additional-rulesets) +* [How to use](#how-to-use) + + [Command line](#command-line) + + [Using PHPCS and WPCS from within your IDE](#using-phpcs-and-wpcs-from-within-your-ide) +* [Running your code through WPCS automatically using CI tools](#running-your-code-through-wpcs-automatically-using-ci-tools) + + [Travis CI](#travis-ci) +* [Fixing errors or whitelisting them](#fixing-errors-or-whitelisting-them) + + [Tools shipped with WPCS](#tools-shipped-with-wpcs) +* [Contributing](#contributing) +* [License](#license) + +## Introduction + +This project is a collection of [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) rules (sniffs) to validate code developed for WordPress. It ensures code quality and adherence to coding conventions, especially the official [WordPress Coding Standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/). + +## Project history + + - On 22nd April 2009, the original project from [Urban Giraffe](https://urbangiraffe.com/articles/wordpress-codesniffer-standard/) was packaged and published. + - In May 2011 the project was forked and [added](https://github.com/WordPress/WordPress-Coding-Standards/commit/04fd547c691ca2baae3fa8e195a46b0c9dd671c5) to GitHub by [Chris Adams](https://chrisadams.me.uk/). + - In April 2012 [XWP](https://xwp.co/) started to dedicate resources to develop and lead the creation of the sniffs and rulesets for `WordPress-Core`, `WordPress-VIP` (WordPress.com VIP), and `WordPress-Extra`. + - In May 2015, an initial documentation ruleset was [added](https://github.com/WordPress/WordPress-Coding-Standards/commit/b1a4bf8232a22563ef66f8a529357275a49f47dc#diff-a17c358c3262a26e9228268eb0a7b8c8) as `WordPress-Docs`. + - In 2015, [J.D. Grimes](https://github.com/JDGrimes) began significant contributions, along with maintenance from [Gary Jones](https://github.com/GaryJones). + - In 2016, [Juliette Reinders Folmer](https://github.com/jrfnl) began contributing heavily, adding more commits in a year than anyone else in the five years since the project was added to GitHub. + - In July 2018, version [`1.0.0`](https://github.com/WordPress/WordPress-Coding-Standards/releases/tag/1.0.0) of the project was released. + +## Installation + +### Requirements + +The WordPress Coding Standards require PHP 5.4 or higher and [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) version **3.3.1** or higher. + +### Composer + +Standards can be installed with the [Composer](https://getcomposer.org/) dependency manager: + + composer create-project wp-coding-standards/wpcs --no-dev + +Running this command will: + +1. Install WordPress standards into `wpcs` directory. +2. Install PHP_CodeSniffer. +3. Register WordPress standards in PHP_CodeSniffer configuration. +4. Make `phpcs` command available from `wpcs/vendor/bin`. + +For the convenience of using `phpcs` as a global command, you may want to add the path to the `wpcs/vendor/bin` directory to a `PATH` environment variable for your operating system. + +#### Installing WPCS as a dependency + +When installing the WordPress Coding Standards as a dependency in a larger project, the above mentioned step 3 will not be executed automatically. + +There are two actively maintained Composer plugins which can handle the registration of standards with PHP_CodeSniffer for you: +* [composer-phpcodesniffer-standards-plugin](https://github.com/higidi/composer-phpcodesniffer-standards-plugin) +* [phpcodesniffer-composer-installer](https://github.com/DealerDirect/phpcodesniffer-composer-installer):"^0.6" + +It is strongly suggested to `require` one of these plugins in your project to handle the registration of external standards with PHPCS for you. + +### Standalone + +1. Install PHP_CodeSniffer by following its [installation instructions](https://github.com/squizlabs/PHP_CodeSniffer#installation) (via Composer, Phar file, PEAR, or Git checkout). + + Do ensure that PHP_CodeSniffer's version matches our [requirements](#requirements), if, for example, you're using [VVV](https://github.com/Varying-Vagrant-Vagrants/VVV). + +2. Clone the WordPress standards repository: + + git clone -b master https://github.com/WordPress/WordPress-Coding-Standards.git wpcs + +3. Add its path to the PHP_CodeSniffer configuration: + + phpcs --config-set installed_paths /path/to/wpcs + + **Pro-tip:** Alternatively, you can tell PHP_CodeSniffer the path to the WordPress standards by adding the following snippet to your custom ruleset: + ```xml + + ``` + +To summarize: + +```bash +cd ~/projects +git clone https://github.com/squizlabs/PHP_CodeSniffer.git phpcs +git clone -b master https://github.com/WordPress/WordPress-Coding-Standards.git wpcs +cd phpcs +./bin/phpcs --config-set installed_paths ../wpcs +``` + +And then add the `~/projects/phpcs/bin` directory to your `PATH` environment variable via your `.bashrc`. + +You should then see `WordPress-Core` et al listed when you run `phpcs -i`. + +## Rulesets + +### Standards subsets + +The project encompasses a super-set of the sniffs that the WordPress community may need. If you use the `WordPress` standard you will get all the checks. + +You can use the following as standard names when invoking `phpcs` to select sniffs, fitting your needs: + +* `WordPress` - complete set with all of the sniffs in the project + - `WordPress-Core` - main ruleset for [WordPress core coding standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/) + - `WordPress-Docs` - additional ruleset for [WordPress inline documentation standards](https://make.wordpress.org/core/handbook/best-practices/inline-documentation-standards/) + - `WordPress-Extra` - extended ruleset for recommended best practices, not sufficiently covered in the WordPress core coding standards + - includes `WordPress-Core` + +**Note:** The WPCS package used to include a `WordPress-VIP` ruleset and associated sniffs, prior to WPCS 2.0.0. +The `WordPress-VIP` ruleset was originally intended to aid with the [WordPress.com VIP coding requirements](https://vip.wordpress.com/documentation/vip-go/code-review-blockers-warnings-notices/), but has been superseded. It is recommended to use the [official VIP coding standards](https://github.com/Automattic/VIP-Coding-Standards) ruleset instead for checking code against the VIP platform requirements. + +### Using a custom ruleset + +If you need to further customize the selection of sniffs for your project - you can create a custom ruleset file. When you name this file either `.phpcs.xml`, `phpcs.xml`, `.phpcs.xml.dist` or `phpcs.xml.dist`, PHP_CodeSniffer will automatically locate it as long as it is placed in the directory from which you run the CodeSniffer or in a directory above it. If you follow these naming conventions you don't have to supply a `--standard` arg. For more info, read about [using a default configuration file](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#using-a-default-configuration-file). See also provided [`phpcs.xml.dist.sample`](phpcs.xml.dist.sample) file and [fully annotated example](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml) in the PHP_CodeSniffer documentation. + +### Customizing sniff behaviour + +The WordPress Coding Standard contains a number of sniffs which are configurable. This means that you can turn parts of the sniff on or off, or change the behaviour by setting a property for the sniff in your custom `.phpcs.xml.dist` file. + +You can find a complete list of all the properties you can change in the [wiki](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties). + +### Recommended additional rulesets + +The [PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility) ruleset and its subset [PHPCompatibilityWP](https://github.com/PHPCompatibility/PHPCompatibilityWP) come highly recommended. +The [PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility) sniffs are designed to analyse your code for cross-PHP version compatibility. + +The [PHPCompatibilityWP](https://github.com/PHPCompatibility/PHPCompatibilityWP) ruleset is based on PHPCompatibility, but specifically crafted to prevent false positives for projects which expect to run within the context of WordPress, i.e. core, plugins and themes. + +Install either as a separate ruleset and run it separately against your code or add it to your custom ruleset, like so: +```xml + + + *\.php$ + +``` + +Whichever way you run it, do make sure you set the `testVersion` to run the sniffs against. The `testVersion` determines for which PHP versions you will receive compatibility information. The recommended setting for this at this moment is `5.2-` to support the same PHP versions as WordPress Core supports. + +For more information about setting the `testVersion`, see: +* [PHPCompatibility: Sniffing your code for compatibility with specific PHP version(s)](https://github.com/PHPCompatibility/PHPCompatibility#sniffing-your-code-for-compatibility-with-specific-php-versions) +* [PHPCompatibility: Using a custom ruleset](https://github.com/PHPCompatibility/PHPCompatibility#using-a-custom-ruleset) + +## How to use + +### Command line + +Run the `phpcs` command line tool on a given file or directory, for example: + + phpcs --standard=WordPress wp-load.php + +Will result in following output: + + ------------------------------------------------------------------------------------------ + FOUND 8 ERRORS AND 10 WARNINGS AFFECTING 11 LINES + ------------------------------------------------------------------------------------------ + 24 | WARNING | [ ] error_reporting() can lead to full path disclosure. + 24 | WARNING | [ ] error_reporting() found. Changing configuration at runtime is rarely + | | necessary. + 37 | WARNING | [x] "require_once" is a statement not a function; no parentheses are + | | required + 39 | WARNING | [ ] Silencing errors is discouraged + 39 | WARNING | [ ] Silencing errors is discouraged + 42 | WARNING | [x] "require_once" is a statement not a function; no parentheses are + | | required + 46 | ERROR | [ ] Inline comments must end in full-stops, exclamation marks, or + | | question marks + 46 | ERROR | [x] There must be no blank line following an inline comment + 49 | WARNING | [x] "require_once" is a statement not a function; no parentheses are + | | required + 54 | WARNING | [x] "require_once" is a statement not a function; no parentheses are + | | required + 63 | WARNING | [ ] Detected access of super global var $_SERVER, probably needs manual + | | inspection. + 63 | ERROR | [ ] Detected usage of a non-validated input variable: $_SERVER + 63 | ERROR | [ ] Missing wp_unslash() before sanitization. + 63 | ERROR | [ ] Detected usage of a non-sanitized input variable: $_SERVER + 69 | WARNING | [x] "require_once" is a statement not a function; no parentheses are + | | required + 74 | ERROR | [ ] Inline comments must end in full-stops, exclamation marks, or + | | question marks + 92 | ERROR | [ ] All output should be run through an escaping function (see the + | | Security sections in the WordPress Developer Handbooks), found + | | '$die'. + 92 | ERROR | [ ] All output should be run through an escaping function (see the + | | Security sections in the WordPress Developer Handbooks), found '__'. + ------------------------------------------------------------------------------------------ + PHPCBF CAN FIX THE 6 MARKED SNIFF VIOLATIONS AUTOMATICALLY + ------------------------------------------------------------------------------------------ + +### Using PHPCS and WPCS from within your IDE + +* **PhpStorm** : Please see "[PHP Code Sniffer with WordPress Coding Standards Integration](https://confluence.jetbrains.com/display/PhpStorm/WordPress+Development+using+PhpStorm#WordPressDevelopmentusingPhpStorm-PHPCodeSnifferwithWordPressCodingStandardsIntegrationinPhpStorm)" in the PhpStorm documentation. +* **Sublime Text** : Please see "[Setting up WPCS to work in Sublime Text](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Setting-up-WPCS-to-work-in-Sublime-Text)" in the wiki. +* **Atom**: Please see "[Setting up WPCS to work in Atom](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Setting-up-WPCS-to-work-in-Atom)" in the wiki. +* **Visual Studio**: Please see "[Setting up PHP CodeSniffer in Visual Studio Code](https://tommcfarlin.com/php-codesniffer-in-visual-studio-code/)", a tutorial by Tom McFarlin. +* **Eclipse with XAMPP**: Please see "[Setting up WPCS when using Eclipse with XAMPP](https://github.com/WordPress/WordPress-Coding-Standards/wiki/How-to-use-WPCS-with-Eclipse-and-XAMPP)" in the wiki. + + +## Running your code through WPCS automatically using CI tools + +### [Travis CI](https://travis-ci.com/) + +To integrate PHPCS with WPCS with Travis CI, you'll need to install both `before_install` and add the run command to the `script`. +If your project uses Composer, the typical instructions might be different. + +If you use a matrix setup in Travis to test your code against different PHP and/or WordPress versions, you don't need to run PHPCS on each variant of the matrix as the results will be same. +You can set an environment variable in the Travis matrix to only run the sniffs against one setup in the matrix. + +#### Travis CI example +```yaml +language: php + +matrix: + include: + # Arbitrary PHP version to run the sniffs against. + - php: '7.0' + env: SNIFF=1 + +before_install: + - if [[ "$SNIFF" == "1" ]]; then export PHPCS_DIR=/tmp/phpcs; fi + - if [[ "$SNIFF" == "1" ]]; then export SNIFFS_DIR=/tmp/sniffs; fi + # Install PHP_CodeSniffer. + - if [[ "$SNIFF" == "1" ]]; then git clone -b master --depth 1 https://github.com/squizlabs/PHP_CodeSniffer.git $PHPCS_DIR; fi + # Install WordPress Coding Standards. + - if [[ "$SNIFF" == "1" ]]; then git clone -b master --depth 1 https://github.com/WordPress/WordPress-Coding-Standards.git $SNIFFS_DIR; fi + # Set install path for WordPress Coding Standards. + - if [[ "$SNIFF" == "1" ]]; then $PHPCS_DIR/bin/phpcs --config-set installed_paths $SNIFFS_DIR; fi + # After CodeSniffer install you should refresh your path. + - if [[ "$SNIFF" == "1" ]]; then phpenv rehash; fi + +script: + # Run against WordPress Coding Standards. + # If you use a custom ruleset, change `--standard=WordPress` to point to your ruleset file, + # for example: `--standard=wpcs.xml`. + # You can use any of the normal PHPCS command line arguments in the command: + # https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage + - if [[ "$SNIFF" == "1" ]]; then $PHPCS_DIR/bin/phpcs -p . --standard=WordPress; fi +``` + +More examples and advice about integrating PHPCS in your Travis build tests can be found here: https://github.com/jrfnl/make-phpcs-work-for-you/tree/master/travis-examples + + +## Fixing errors or whitelisting them + +You can find information on how to deal with some of the more frequent issues in the [wiki](https://github.com/WordPress/WordPress-Coding-Standards/wiki). + +### Tools shipped with WPCS + +Since version 1.2.0, WPCS has a special sniff category `Utils`. + +This sniff category contains some tools which, generally speaking, will only be needed to be run once over a codebase and for which the fixers can be considered _risky_, i.e. very careful review by a developer is needed before accepting the fixes made by these sniffs. + +The sniffs in this category are disabled by default and can only be activated by adding some properties for each sniff via a custom ruleset. + +At this moment, WPCS offer the following tools: +* `WordPress.Utils.I18nTextDomainFixer` - This sniff can replace the text domain used in a code-base. + The sniff will fix the text domains in both I18n function calls as well as in a plugin/theme header. + Passing the following properties will activate the sniff: + - `old_text_domain`: an array with one or more (old) text domain names which need to be replaced; + - `new_text_domain`: the correct (new) text domain as a string. + + +## Contributing + +See [CONTRIBUTING](.github/CONTRIBUTING.md), including information about [unit testing](.github/CONTRIBUTING.md#unit-testing) the standard. + +## License + +See [LICENSE](LICENSE) (MIT). diff --git a/vendor/wp-coding-standards/wpcs/WordPress-Core/ruleset.xml b/vendor/wp-coding-standards/wpcs/WordPress-Core/ruleset.xml new file mode 100644 index 00000000..0bff5a0d --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress-Core/ruleset.xml @@ -0,0 +1,529 @@ + + + + Non-controversial generally-agreed upon WordPress Coding Standards + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + error + The "goto" language construct should not be used. + + + + + error + eval() is a security risk so not allowed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress-Docs/ruleset.xml b/vendor/wp-coding-standards/wpcs/WordPress-Docs/ruleset.xml new file mode 100644 index 00000000..e16001ed --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress-Docs/ruleset.xml @@ -0,0 +1,109 @@ + + + + WordPress Coding Standards for Inline Documentation and Comments + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress-Extra/ruleset.xml b/vendor/wp-coding-standards/wpcs/WordPress-Extra/ruleset.xml new file mode 100644 index 00000000..4a2f9599 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress-Extra/ruleset.xml @@ -0,0 +1,187 @@ + + + + Best practices beyond core WordPress Coding Standards + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + warning + + + warning + + + warning + + + + + + + + + + + + warning + Best practice suggestion: Declare only one class/interface/trait in a file. + + + + + + + + + + + + 5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + error + + + error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/AbstractArrayAssignmentRestrictionsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/AbstractArrayAssignmentRestrictionsSniff.php new file mode 100644 index 00000000..7c662cd0 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/AbstractArrayAssignmentRestrictionsSniff.php @@ -0,0 +1,240 @@ +setup_groups() ) { + return array(); + } + + return array( + \T_DOUBLE_ARROW, + \T_CLOSE_SQUARE_BRACKET, + \T_CONSTANT_ENCAPSED_STRING, + \T_DOUBLE_QUOTED_STRING, + ); + } + + /** + * Groups of variables to restrict. + * + * This method should be overridden in extending classes. + * + * Example: groups => array( + * 'groupname' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Dont use this one please!', + * 'keys' => array( 'key1', 'another_key' ), + * 'callback' => array( 'class', 'method' ), // Optional. + * ) + * ) + * + * @return array + */ + abstract public function getGroups(); + + /** + * Cache the groups. + * + * @since 0.13.0 + * + * @return bool True if the groups were setup. False if not. + */ + protected function setup_groups() { + $this->groups_cache = $this->getGroups(); + + if ( empty( $this->groups_cache ) && empty( self::$groups ) ) { + return false; + } + + // Allow for adding extra unit tests. + if ( ! empty( self::$groups ) ) { + $this->groups_cache = array_merge( $this->groups_cache, self::$groups ); + } + + return true; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + + $this->excluded_groups = $this->merge_custom_array( $this->exclude ); + if ( array_diff_key( $this->groups_cache, $this->excluded_groups ) === array() ) { + // All groups have been excluded. + // Don't remove the listener as the exclude property can be changed inline. + return; + } + + $token = $this->tokens[ $stackPtr ]; + + if ( \T_CLOSE_SQUARE_BRACKET === $token['code'] ) { + $equal = $this->phpcsFile->findNext( \T_WHITESPACE, ( $stackPtr + 1 ), null, true ); + if ( \T_EQUAL !== $this->tokens[ $equal ]['code'] ) { + return; // This is not an assignment! + } + } + + // Instances: Multi-dimensional array, keyed by line. + $inst = array(); + + /* + * Covers: + * $foo = array( 'bar' => 'taz' ); + * $foo['bar'] = $taz; + */ + if ( \in_array( $token['code'], array( \T_CLOSE_SQUARE_BRACKET, \T_DOUBLE_ARROW ), true ) ) { + $operator = $stackPtr; // T_DOUBLE_ARROW. + if ( \T_CLOSE_SQUARE_BRACKET === $token['code'] ) { + $operator = $this->phpcsFile->findNext( \T_EQUAL, ( $stackPtr + 1 ) ); + } + + $keyIdx = $this->phpcsFile->findPrevious( array( \T_WHITESPACE, \T_CLOSE_SQUARE_BRACKET ), ( $operator - 1 ), null, true ); + if ( ! is_numeric( $this->tokens[ $keyIdx ]['content'] ) ) { + $key = $this->strip_quotes( $this->tokens[ $keyIdx ]['content'] ); + $valStart = $this->phpcsFile->findNext( array( \T_WHITESPACE ), ( $operator + 1 ), null, true ); + $valEnd = $this->phpcsFile->findNext( array( \T_COMMA, \T_SEMICOLON ), ( $valStart + 1 ), null, false, null, true ); + $val = $this->phpcsFile->getTokensAsString( $valStart, ( $valEnd - $valStart ) ); + $val = $this->strip_quotes( $val ); + $inst[ $key ][] = array( $val, $token['line'] ); + } + } elseif ( \in_array( $token['code'], array( \T_CONSTANT_ENCAPSED_STRING, \T_DOUBLE_QUOTED_STRING ), true ) ) { + // $foo = 'bar=taz&other=thing'; + if ( preg_match_all( '#(?:^|&)([a-z_]+)=([^&]*)#i', $this->strip_quotes( $token['content'] ), $matches ) <= 0 ) { + return; // No assignments here, nothing to check. + } + foreach ( $matches[1] as $i => $_k ) { + $inst[ $_k ][] = array( $matches[2][ $i ], $token['line'] ); + } + } + + if ( empty( $inst ) ) { + return; + } + + foreach ( $this->groups_cache as $groupName => $group ) { + + if ( isset( $this->excluded_groups[ $groupName ] ) ) { + continue; + } + + $callback = ( isset( $group['callback'] ) && is_callable( $group['callback'] ) ) ? $group['callback'] : array( $this, 'callback' ); + + foreach ( $inst as $key => $assignments ) { + foreach ( $assignments as $occurance ) { + list( $val, $line ) = $occurance; + + if ( ! \in_array( $key, $group['keys'], true ) ) { + continue; + } + + $output = \call_user_func( $callback, $key, $val, $line, $group ); + + if ( ! isset( $output ) || false === $output ) { + continue; + } elseif ( true === $output ) { + $message = $group['message']; + } else { + $message = $output; + } + + $this->addMessage( + $message, + $stackPtr, + ( 'error' === $group['type'] ), + $this->string_to_errorcode( $groupName . '_' . $key ), + array( $key, $val ) + ); + } + } + } + } + + /** + * Callback to process each confirmed key, to check value. + * + * This method must be extended to add the logic to check assignment value. + * + * @param string $key Array index / key. + * @param mixed $val Assigned value. + * @param int $line Token line. + * @param array $group Group definition. + * @return mixed FALSE if no match, TRUE if matches, STRING if matches + * with custom error message passed to ->process(). + */ + abstract public function callback( $key, $val, $line, $group ); + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/AbstractClassRestrictionsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/AbstractClassRestrictionsSniff.php new file mode 100644 index 00000000..9374622e --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/AbstractClassRestrictionsSniff.php @@ -0,0 +1,245 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Avoid direct calls to the database.', + * 'classes' => array( 'PDO', '\Namespace\Classname' ), + * ) + * ) + * + * You can use * wildcards to target a group of (namespaced) classes. + * Aliased namespaces (use ..) are currently not supported. + * + * Documented here for clarity. Not (re)defined as it is already defined in the parent class. + * + * @return array + * + abstract public function getGroups(); + */ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + // Prepare the function group regular expressions only once. + if ( false === $this->setup_groups( 'classes' ) ) { + return array(); + } + + return array( + \T_DOUBLE_COLON, + \T_NEW, + \T_EXTENDS, + \T_IMPLEMENTS, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * {@internal Unlike in the `AbstractFunctionRestrictionsSniff`, + * we can't do a preliminary check on classes as at this point + * we don't know the class name yet.}} + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + // Reset the temporary storage before processing the token. + unset( $this->classname ); + + $this->excluded_groups = $this->merge_custom_array( $this->exclude ); + if ( array_diff_key( $this->groups, $this->excluded_groups ) === array() ) { + // All groups have been excluded. + // Don't remove the listener as the exclude property can be changed inline. + return; + } + + if ( true === $this->is_targetted_token( $stackPtr ) ) { + return $this->check_for_matches( $stackPtr ); + } + } + + /** + * Determine if we have a valid classname for the target token. + * + * @since 0.11.0 This logic was originally contained in the `process()` method. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return bool + */ + public function is_targetted_token( $stackPtr ) { + + $token = $this->tokens[ $stackPtr ]; + $classname = ''; + + if ( \in_array( $token['code'], array( \T_NEW, \T_EXTENDS, \T_IMPLEMENTS ), true ) ) { + if ( \T_NEW === $token['code'] ) { + $nameEnd = ( $this->phpcsFile->findNext( array( \T_OPEN_PARENTHESIS, \T_WHITESPACE, \T_SEMICOLON, \T_OBJECT_OPERATOR ), ( $stackPtr + 2 ) ) - 1 ); + } else { + $nameEnd = ( $this->phpcsFile->findNext( array( \T_CLOSE_CURLY_BRACKET, \T_WHITESPACE ), ( $stackPtr + 2 ) ) - 1 ); + } + + $length = ( $nameEnd - ( $stackPtr + 1 ) ); + $classname = $this->phpcsFile->getTokensAsString( ( $stackPtr + 2 ), $length ); + + if ( \T_NS_SEPARATOR !== $this->tokens[ ( $stackPtr + 2 ) ]['code'] ) { + $classname = $this->get_namespaced_classname( $classname, ( $stackPtr - 1 ) ); + } + } + + if ( \T_DOUBLE_COLON === $token['code'] ) { + $nameEnd = $this->phpcsFile->findPrevious( \T_STRING, ( $stackPtr - 1 ) ); + $nameStart = ( $this->phpcsFile->findPrevious( array( \T_STRING, \T_NS_SEPARATOR, \T_NAMESPACE ), ( $nameEnd - 1 ), null, true, null, true ) + 1 ); + $length = ( $nameEnd - ( $nameStart - 1 ) ); + $classname = $this->phpcsFile->getTokensAsString( $nameStart, $length ); + + if ( \T_NS_SEPARATOR !== $this->tokens[ $nameStart ]['code'] ) { + $classname = $this->get_namespaced_classname( $classname, ( $nameStart - 1 ) ); + } + } + + // Stop if we couldn't determine a classname. + if ( empty( $classname ) ) { + return false; + } + + // Nothing to do if 'parent', 'self' or 'static'. + if ( \in_array( $classname, array( 'parent', 'self', 'static' ), true ) ) { + return false; + } + + $this->classname = $classname; + return true; + } + + /** + * Verify if the current token is one of the targetted classes. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function check_for_matches( $stackPtr ) { + $skip_to = array(); + + foreach ( $this->groups as $groupName => $group ) { + + if ( isset( $this->excluded_groups[ $groupName ] ) ) { + continue; + } + + if ( preg_match( $group['regex'], $this->classname ) === 1 ) { + $skip_to[] = $this->process_matched_token( $stackPtr, $groupName, $this->classname ); + } + } + + if ( empty( $skip_to ) || min( $skip_to ) === 0 ) { + return; + } + + return min( $skip_to ); + } + + /** + * Prepare the class name for use in a regular expression. + * + * The getGroups() method allows for providing class names with a wildcard * to target + * a group of classes within a namespace. It also allows for providing class names as + * 'ordinary' names or prefixed with one or more namespaces. + * This prepare routine takes that into account while still safely escaping the + * class name for use in a regular expression. + * + * @param string $classname Class name, potentially prefixed with namespaces. + * @return string Regex escaped class name. + */ + protected function prepare_name_for_regex( $classname ) { + $classname = trim( $classname, '\\' ); // Make sure all classnames have a \ prefix, but only one. + return parent::prepare_name_for_regex( $classname ); + } + + /** + * See if the classname was found in a namespaced file and if so, add the namespace to the classname. + * + * @param string $classname The full classname as found. + * @param int $search_from The token position to search up from. + * @return string Classname, potentially prefixed with the namespace. + */ + protected function get_namespaced_classname( $classname, $search_from ) { + // Don't do anything if this is already a fully qualified classname. + if ( empty( $classname ) || '\\' === $classname[0] ) { + return $classname; + } + + // Remove the namespace keyword if used. + if ( 0 === strpos( $classname, 'namespace\\' ) ) { + $classname = substr( $classname, 10 ); + } + + $namespace_keyword = $this->phpcsFile->findPrevious( \T_NAMESPACE, $search_from ); + if ( false === $namespace_keyword ) { + // No namespace keyword found at all, so global namespace. + $classname = '\\' . $classname; + } else { + $namespace = $this->determine_namespace( $search_from ); + + if ( ! empty( $namespace ) ) { + $classname = '\\' . $namespace . '\\' . $classname; + } else { + // No actual namespace found, so global namespace. + $classname = '\\' . $classname; + } + } + + return $classname; + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/AbstractFunctionParameterSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/AbstractFunctionParameterSniff.php new file mode 100644 index 00000000..ab68a1dc --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/AbstractFunctionParameterSniff.php @@ -0,0 +1,112 @@ +target_functions ) ) { + return array(); + } + + return array( + $this->group_name => array( + 'functions' => array_keys( $this->target_functions ), + ), + ); + } + + /** + * Process a matched token. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_matched_token( $stackPtr, $group_name, $matched_content ) { + + $parameters = $this->get_function_call_parameters( $stackPtr ); + + if ( empty( $parameters ) ) { + return $this->process_no_parameters( $stackPtr, $group_name, $matched_content ); + } else { + return $this->process_parameters( $stackPtr, $group_name, $matched_content, $parameters ); + } + } + + /** + * Process the parameters of a matched function. + * + * This method has to be made concrete in child classes. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + abstract public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ); + + /** + * Process the function if no parameters were found. + * + * Defaults to doing nothing. Can be overloaded in child classes to handle functions + * were parameters are expected, but none found. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_no_parameters( $stackPtr, $group_name, $matched_content ) { + return; + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/AbstractFunctionRestrictionsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/AbstractFunctionRestrictionsSniff.php new file mode 100644 index 00000000..53ea9a25 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/AbstractFunctionRestrictionsSniff.php @@ -0,0 +1,342 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function', 'mysql_*' ), + * // Only useful when using wildcards: + * 'whitelist' => array( 'mysql_to_rfc3339' => true, ), + * ) + * ) + * + * You can use * wildcards to target a group of functions. + * When you use * wildcards, you may inadvertently restrict too many + * functions. In that case you can add the `whitelist` key to + * whitelist individual functions to prevent false positives. + * + * @return array + */ + abstract public function getGroups(); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + // Prepare the function group regular expressions only once. + if ( false === $this->setup_groups( 'functions' ) ) { + return array(); + } + + return array( + \T_STRING, + ); + } + + /** + * Set up the regular expressions for each group. + * + * @since 0.10.0 + * + * @param string $key The group array index key where the input for the regular expression can be found. + * @return bool True if the groups were setup. False if not. + */ + protected function setup_groups( $key ) { + // Prepare the function group regular expressions only once. + $this->groups = $this->getGroups(); + + if ( empty( $this->groups ) && empty( self::$unittest_groups ) ) { + return false; + } + + // Allow for adding extra unit tests. + if ( ! empty( self::$unittest_groups ) ) { + $this->groups = array_merge( $this->groups, self::$unittest_groups ); + } + + $all_items = array(); + foreach ( $this->groups as $groupName => $group ) { + if ( empty( $group[ $key ] ) ) { + unset( $this->groups[ $groupName ] ); + } else { + $items = array_map( array( $this, 'prepare_name_for_regex' ), $group[ $key ] ); + $all_items[] = $items; + $items = implode( '|', $items ); + + $this->groups[ $groupName ]['regex'] = sprintf( $this->regex_pattern, $items ); + } + } + + if ( empty( $this->groups ) ) { + return false; + } + + // Create one "super-regex" to allow for initial filtering. + $all_items = \call_user_func_array( 'array_merge', $all_items ); + $all_items = implode( '|', array_unique( $all_items ) ); + $this->prelim_check_regex = sprintf( $this->regex_pattern, $all_items ); + + return true; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + $this->excluded_groups = $this->merge_custom_array( $this->exclude ); + if ( array_diff_key( $this->groups, $this->excluded_groups ) === array() ) { + // All groups have been excluded. + // Don't remove the listener as the exclude property can be changed inline. + return; + } + + // Preliminary check. If the content of the T_STRING is not one of the functions we're + // looking for, we can bow out before doing the heavy lifting of checking whether + // this is a function call. + if ( preg_match( $this->prelim_check_regex, $this->tokens[ $stackPtr ]['content'] ) !== 1 ) { + return; + } + + if ( true === $this->is_targetted_token( $stackPtr ) ) { + return $this->check_for_matches( $stackPtr ); + } + } + + /** + * Verify is the current token is a function call. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return bool + */ + public function is_targetted_token( $stackPtr ) { + + if ( \T_STRING !== $this->tokens[ $stackPtr ]['code'] ) { + return false; + } + + // Exclude function definitions, class methods, and namespaced calls. + if ( $this->is_class_object_call( $stackPtr ) === true ) { + return false; + } + + if ( $this->is_token_namespaced( $stackPtr ) === true ) { + return false; + } + + $prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true ); + if ( false !== $prev ) { + // Skip sniffing on function, class definitions or for function aliases in use statements. + $skipped = array( + \T_FUNCTION => \T_FUNCTION, + \T_CLASS => \T_CLASS, + \T_AS => \T_AS, // Use declaration alias. + ); + + if ( isset( $skipped[ $this->tokens[ $prev ]['code'] ] ) ) { + return false; + } + } + + // Check if this could even be a function call. + $next = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + if ( false === $next ) { + return false; + } + + // Check for `use function ... (as|;)`. + if ( ( \T_STRING === $this->tokens[ $prev ]['code'] && 'function' === $this->tokens[ $prev ]['content'] ) + && ( \T_AS === $this->tokens[ $next ]['code'] || \T_SEMICOLON === $this->tokens[ $next ]['code'] ) + ) { + return true; + } + + // If it's not a `use` statement, there should be parenthesis. + if ( \T_OPEN_PARENTHESIS !== $this->tokens[ $next ]['code'] ) { + return false; + } + + return true; + } + + /** + * Verify if the current token is one of the targetted functions. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function check_for_matches( $stackPtr ) { + $token_content = strtolower( $this->tokens[ $stackPtr ]['content'] ); + $skip_to = array(); + + foreach ( $this->groups as $groupName => $group ) { + + if ( isset( $this->excluded_groups[ $groupName ] ) ) { + continue; + } + + if ( isset( $group['whitelist'][ $token_content ] ) ) { + continue; + } + + if ( preg_match( $group['regex'], $token_content ) === 1 ) { + $skip_to[] = $this->process_matched_token( $stackPtr, $groupName, $token_content ); + } + } + + if ( empty( $skip_to ) || min( $skip_to ) === 0 ) { + return; + } + + return min( $skip_to ); + } + + /** + * Process a matched token. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_matched_token( $stackPtr, $group_name, $matched_content ) { + + $this->addMessage( + $this->groups[ $group_name ]['message'], + $stackPtr, + ( 'error' === $this->groups[ $group_name ]['type'] ), + $this->string_to_errorcode( $group_name . '_' . $matched_content ), + array( $matched_content ) + ); + } + + /** + * Prepare the function name for use in a regular expression. + * + * The getGroups() method allows for providing function names with a wildcard * to target + * a group of functions. This prepare routine takes that into account while still safely + * escaping the function name for use in a regular expression. + * + * @since 0.10.0 + * + * @param string $function Function name. + * @return string Regex escaped function name. + */ + protected function prepare_name_for_regex( $function ) { + $function = str_replace( array( '.*', '*' ), '@@', $function ); // Replace wildcards with placeholder. + $function = preg_quote( $function, '`' ); + $function = str_replace( '@@', '.*', $function ); // Replace placeholder with regex wildcard. + + return $function; + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/Arrays/ArrayIndentationStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/Arrays/ArrayIndentationStandard.xml new file mode 100644 index 00000000..5b9a1dee --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/Arrays/ArrayIndentationStandard.xml @@ -0,0 +1,112 @@ + + + + + + + 22, +); + ]]> + + + 22, + ); + ]]> + + + + + + + + 22, + 'comment_count' => array( + 'value' => 25, + 'compare' => '>=', + ), + 'post_type' => array( + 'post', + 'page', + ), +); + ]]> + + + 22, + 'comment_count' => array( + 'value' => 25, + 'compare' => '>=', + ), + 'post_type' => array( + 'post', + 'page', + ), +); + ]]> + + + + + + + + 'start of phrase' + . 'concatented additional phrase' + . 'more text', +); + ]]> + + + 'start of phrase' +. 'concatented additional phrase' +. 'more text', +); + ]]> + + + + + + + + << + start of phrase + concatented additional phrase + more text +EOD +, +); + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/Arrays/ArrayKeySpacingRestrictionsStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/Arrays/ArrayKeySpacingRestrictionsStandard.xml new file mode 100644 index 00000000..c1e27a13 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/Arrays/ArrayKeySpacingRestrictionsStandard.xml @@ -0,0 +1,27 @@ + + + + + + + [ $post_id ]; +$post_title = $post[ 'concatenated' . $title ]; +$post = $posts[ HOME_PAGE ]; +$post = $posts[123]; +$post_title = $post['post_title']; + ]]> + + + [$post_id]; +$post_title = $post['concatenated' . $title ]; +$post = $posts[HOME_PAGE]; +$post = $posts[ 123 ]; +$post_title = $post[ 'post_title' ]; + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/Arrays/MultipleStatementAlignmentStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/Arrays/MultipleStatementAlignmentStandard.xml new file mode 100644 index 00000000..b3f87cbb --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/Arrays/MultipleStatementAlignmentStandard.xml @@ -0,0 +1,46 @@ + + + + + + + => 22 ); +$bar = array( 'year' => $current_year ); + ]]> + + + =>22 ); +$bar = array( 'year'=> $current_year ); + ]]> + + + + + + + + => 22, + 'year' => $current_year, + 'monthnum' => $current_month, +); + ]]> + + + => 22, + 'year' => $current_year, + 'monthnum' => $current_month, +); + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/Classes/ClassInstantiationStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/Classes/ClassInstantiationStandard.xml new file mode 100644 index 00000000..cdd749ec --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/Classes/ClassInstantiationStandard.xml @@ -0,0 +1,53 @@ + + + + + + + (); + ]]> + + + + + + + + + + + + + + (); + ]]> + + + + + + + + new Foobar(); + ]]> + + + & new Foobar(); + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/CodeAnalysis/EscapedNotTranslatedStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/CodeAnalysis/EscapedNotTranslatedStandard.xml new file mode 100644 index 00000000..3755a3c9 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/CodeAnalysis/EscapedNotTranslatedStandard.xml @@ -0,0 +1,20 @@ + + + + + + + esc_html__( 'text', 'domain' ); + ]]> + + + esc_html( 'text', 'domain' ); + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/DateTime/CurrentTimeTimestampStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/DateTime/CurrentTimeTimestampStandard.xml new file mode 100644 index 00000000..add8ed23 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/DateTime/CurrentTimeTimestampStandard.xml @@ -0,0 +1,31 @@ + + + + + + + time(); + ]]> + + + current_time( 'timestamp', true ); + ]]> + + + + + 'Y-m-d' ); + ]]> + + + current_time( 'U', false ); + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/NamingConventions/ValidHookNameStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/NamingConventions/ValidHookNameStandard.xml new file mode 100644 index 00000000..479dbd9b --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/NamingConventions/ValidHookNameStandard.xml @@ -0,0 +1,32 @@ + + + + + + + + 'prefix_hook_name', $var ); + ]]> + + + 'Prefix_Hook_NAME', $var ); + ]]> + + + + + 'prefix_hook_name', $var ); + ]]> + + + 'prefix\hook-name', $var ); + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/NamingConventions/ValidPostTypeSlugStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/NamingConventions/ValidPostTypeSlugStandard.xml new file mode 100644 index 00000000..86be1bbe --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/NamingConventions/ValidPostTypeSlugStandard.xml @@ -0,0 +1,117 @@ + + + + + + + 'my_short_slug', + array() +); + ]]> + + + 'my_own_post_type_too_long', + array() +); + ]]> + + + + + + + + 'my_post_type_slug', + array() +); + ]]> + + + 'my/post/type/slug', + array() +); + ]]> + + + + + + + + 'my_post_active', + array() +); + ]]> + + + "my_post_{$status}", + array() +); + ]]> + + + + + + + + 'prefixed_author', + array() +); + ]]> + + + 'author', + array() +); + ]]> + + + + + + + + 'prefixed_author', + array() +); + ]]> + + + 'wp_author', + array() +); + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/PHP/DisallowShortTernaryStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/PHP/DisallowShortTernaryStandard.xml new file mode 100644 index 00000000..c81b2fd8 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/PHP/DisallowShortTernaryStandard.xml @@ -0,0 +1,20 @@ + + + + + + + ? + $data['height'] : 0; + ]]> + + + ? : 0; + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/PHP/IniSetStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/PHP/IniSetStandard.xml new file mode 100644 index 00000000..dfc74e91 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/PHP/IniSetStandard.xml @@ -0,0 +1,36 @@ + + + + + + + + + + 'short_open_tag', 'off' ); + ]]> + + + + + + + + wp_raise_memory_limit(); + ]]> + + + 'memory_limit', '256M' ); + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/Security/SafeRedirectStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/Security/SafeRedirectStandard.xml new file mode 100644 index 00000000..c2bcf5b8 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/Security/SafeRedirectStandard.xml @@ -0,0 +1,19 @@ + + + + + + + wp_safe_redirect( $location ); + ]]> + + + wp_redirect( $location ); + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/CronIntervalStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/CronIntervalStandard.xml new file mode 100644 index 00000000..55a9037d --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/CronIntervalStandard.xml @@ -0,0 +1,41 @@ + + + + + + + HOUR_IN_SECONDS, + 'display' => __( 'Every hour' ) + ); + return $schedules; +} + +add_filter( + 'cron_schedules', + 'adjust_schedules' +); + ]]> + + + 9 * 60, + 'display' => __( 'Every 9 minutes' ) + ); + return $schedules; +} + +add_filter( + 'cron_schedules', + 'adjust_schedules' +); + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedClassesStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedClassesStandard.xml new file mode 100644 index 00000000..4d06f6e3 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedClassesStandard.xml @@ -0,0 +1,19 @@ + + + + + + + WP_User_Query(); + ]]> + + + WP_User_Search(); // Deprecated WP 3.1. + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedFunctionsStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedFunctionsStandard.xml new file mode 100644 index 00000000..7fcc9c4e --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedFunctionsStandard.xml @@ -0,0 +1,19 @@ + + + + + + + get_sites(); + ]]> + + + wp_get_sites(); // Deprecated WP 4.6. + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedParameterValuesStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedParameterValuesStandard.xml new file mode 100644 index 00000000..0348fdff --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedParameterValuesStandard.xml @@ -0,0 +1,19 @@ + + + + + + + 'url' ); + ]]> + + + 'home' ); // Deprecated WP 2.2.0. + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedParametersStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedParametersStandard.xml new file mode 100644 index 00000000..6399ca62 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedParametersStandard.xml @@ -0,0 +1,36 @@ + + + after the deprecated parameter, only ever pass the default value. + ]]> + + + + + + + $string ); + ]]> + + + + + '', 'yes' ); + ]]> + + + 'oops', 'yes' ); + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/EnqueuedResourcesStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/EnqueuedResourcesStandard.xml new file mode 100644 index 00000000..3857df3d --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/EnqueuedResourcesStandard.xml @@ -0,0 +1,53 @@ + + + + + + + wp_enqueue_script( + 'someScript-js', + $path_to_file, + array( 'jquery' ), + '1.0.0', + true +); + ]]> + + + ', + esc_url( $path_to_file ) +); + ]]> + + + + + + + + wp_enqueue_style( + 'style-name', + $path_to_file, + array(), + '1.0.0' +); + ]]> + + + ', + esc_url( $path_to_file ) +); + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/PostsPerPageStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/PostsPerPageStandard.xml new file mode 100644 index 00000000..aa24f740 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WP/PostsPerPageStandard.xml @@ -0,0 +1,69 @@ + + + + + + + -1, +); +$args = array( + 'posts_per_page' => 100, +); +$args = array( + 'posts_per_page' => '10', +); + +$query_args['posts_per_page'] = 100; + +_query_posts( 'nopaging=1&posts_per_page=50' ); + ]]> + + + 101, +); + +$query_args['posts_per_page'] = 200; + +_query_posts( 'nopaging=1&posts_per_page=999' ); + ]]> + + + + + -1, +); +$args = array( + 'numberposts' => 100, +); +$args = array( + 'numberposts' => '10', +); + +$query_args['numberposts'] = '-1'; + +_query_posts( 'numberposts=50' ); + ]]> + + + 101, +); + +$query_args['numberposts'] = '200'; + +_query_posts( 'numberposts=999' ); + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/CastStructureSpacingStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/CastStructureSpacingStandard.xml new file mode 100644 index 00000000..8539325b --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/CastStructureSpacingStandard.xml @@ -0,0 +1,23 @@ + + + + + + + (int) '420'; + +// No space between spread operator and cast. +$a = function_call( ...(array) $mixed ); + ]]> + + + =(int) '420'; + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/DisallowInlineTabsStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/DisallowInlineTabsStandard.xml new file mode 100644 index 00000000..16f1da2f --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/DisallowInlineTabsStandard.xml @@ -0,0 +1,25 @@ + + + + + + + [space]=> 'lor', + 'b'[space][space][space]=> 'em', +); + ]]> + + + [tab]=> 'lor', + 'b'[tab]=> 'em', +); + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/PrecisionAlignmentStandard.xml b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/PrecisionAlignmentStandard.xml new file mode 100644 index 00000000..ca819ffd --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/PrecisionAlignmentStandard.xml @@ -0,0 +1,31 @@ + + + + + + + [tab]$var = true; + ]]> + + + [space][space]$var = true; + ]]> + + + + + [tab][space][space][space][space]$var = true; + ]]> + + + [tab][space][space][space]$var = true; + ]]> + + + diff --git a/vendor/wp-coding-standards/wpcs/WordPress/PHPCSHelper.php b/vendor/wp-coding-standards/wpcs/WordPress/PHPCSHelper.php new file mode 100644 index 00000000..1599a97a --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/PHPCSHelper.php @@ -0,0 +1,109 @@ +config->tabWidth ) && $phpcsFile->config->tabWidth > 0 ) { + $tab_width = $phpcsFile->config->tabWidth; + } + + return $tab_width; + } + + /** + * Check whether the `--ignore-annotations` option has been used. + * + * @since 0.13.0 + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile Optional. The current file being processed. + * + * @return bool True if annotations should be ignored, false otherwise. + */ + public static function ignore_annotations( File $phpcsFile = null ) { + if ( isset( $phpcsFile, $phpcsFile->config->annotations ) ) { + return ! $phpcsFile->config->annotations; + } else { + $annotations = Config::getConfigData( 'annotations' ); + if ( isset( $annotations ) ) { + return ! $annotations; + } + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniff.php new file mode 100644 index 00000000..55ca6e74 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniff.php @@ -0,0 +1,3424 @@ + true`, i.e. the array item is set as the array key. + * This allows for sniffs to verify whether something is in one of these + * lists using `isset()` rather than `in_array()` which is a much more + * efficient (faster) check to execute and therefore improves the + * performance of the sniffs. + * The `true` value in those cases is used as a placeholder and has no + * meaning in and of itself. + * In the rare few cases where the array values *do* have meaning, this + * is documented in the property documentation.}} + */ +abstract class Sniff implements PHPCS_Sniff { + + /** + * Regex to get complex variables from T_DOUBLE_QUOTED_STRING or T_HEREDOC. + * + * @since 0.14.0 + * + * @var string + */ + const REGEX_COMPLEX_VARS = '`(?:(\{)?(?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)(?:->\$?(?P>varname)|\[[^\]]+\]|::\$?(?P>varname)|\([^\)]*\))*(?(3)\}|)(?(2)\}|)(?(1)\}|)`'; + + /** + * Minimum supported WordPress version. + * + * Currently used by the `WordPress.WP.AlternativeFunctions`, + * `WordPress.WP.DeprecatedClasses`, `WordPress.WP.DeprecatedFunctions` + * and the `WordPress.WP.DeprecatedParameter` sniff. + * + * These sniffs will throw an error when usage of a deprecated class/function/parameter + * is detected if the class/function/parameter was deprecated before the minimum + * supported WP version; a warning otherwise. + * By default, it is set to presume that a project will support the current + * WP version and up to three releases before. + * + * This property allows changing the minimum supported WP version used by + * these sniffs by setting a property in a custom phpcs.xml ruleset. + * This property will need to be set for each sniff which uses it. + * + * Example usage: + * + * + * + * + * + * + * Alternatively, the value can be passed in one go for all sniff using it via + * the command line or by setting a `` value in a custom phpcs.xml ruleset. + * Note: the `_wp_` in the command line property name! + * + * CL: `phpcs --runtime-set minimum_supported_wp_version 4.5` + * Ruleset: `` + * + * @since 0.14.0 Previously the individual sniffs each contained this property. + * + * @internal When the value of this property is changed, it will also need + * to be changed in the `WP/AlternativeFunctionsUnitTest.inc` file. + * + * @var string WordPress version. + */ + public $minimum_supported_version = '5.1'; + + /** + * Custom list of classes which test classes can extend. + * + * This property allows end-users to add to the $test_class_whitelist via their ruleset. + * This property will need to be set for each sniff which uses the + * `is_test_class()` method. + * Currently the method is used by the `WordPress.WP.GlobalVariablesOverride`, + * `WordPress.NamingConventions.PrefixAllGlobals` and the `WordPress.Files.Filename` sniffs. + * + * Example usage: + * + * + * + * + * + * + * + * + * + * @since 0.11.0 + * + * @var string|string[] + */ + public $custom_test_class_whitelist = array(); + + /** + * List of the functions which verify nonces. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $nonceVerificationFunctions = array( + 'wp_verify_nonce' => true, + 'check_admin_referer' => true, + 'check_ajax_referer' => true, + ); + + /** + * Functions that escape values for display. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $escapingFunctions = array( + 'absint' => true, + 'esc_attr__' => true, + 'esc_attr_e' => true, + 'esc_attr_x' => true, + 'esc_attr' => true, + 'esc_html__' => true, + 'esc_html_e' => true, + 'esc_html_x' => true, + 'esc_html' => true, + 'esc_js' => true, + 'esc_sql' => true, + 'esc_textarea' => true, + 'esc_url_raw' => true, + 'esc_url' => true, + 'filter_input' => true, + 'filter_var' => true, + 'floatval' => true, + 'highlight_string' => true, + 'intval' => true, + 'json_encode' => true, + 'like_escape' => true, + 'number_format' => true, + 'rawurlencode' => true, + 'sanitize_hex_color' => true, + 'sanitize_hex_color_no_hash' => true, + 'sanitize_html_class' => true, + 'sanitize_key' => true, + 'sanitize_user_field' => true, + 'tag_escape' => true, + 'urlencode_deep' => true, + 'urlencode' => true, + 'wp_json_encode' => true, + 'wp_kses_allowed_html' => true, + 'wp_kses_data' => true, + 'wp_kses_post' => true, + 'wp_kses' => true, + ); + + /** + * Functions whose output is automatically escaped for display. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $autoEscapedFunctions = array( + 'allowed_tags' => true, + 'bloginfo' => true, + 'body_class' => true, + 'calendar_week_mod' => true, + 'category_description' => true, + 'checked' => true, + 'comment_class' => true, + 'count' => true, + 'disabled' => true, + 'do_shortcode' => true, + 'do_shortcode_tag' => true, + 'get_archives_link' => true, + 'get_attachment_link' => true, + 'get_avatar' => true, + 'get_bookmark_field' => true, + 'get_calendar' => true, + 'get_comment_author_link' => true, + 'get_current_blog_id' => true, + 'get_delete_post_link' => true, + 'get_search_form' => true, + 'get_search_query' => true, + 'get_the_author_link' => true, + 'get_the_author' => true, + 'get_the_date' => true, + 'get_the_ID' => true, + 'get_the_post_thumbnail' => true, + 'get_the_term_list' => true, + 'post_type_archive_title' => true, + 'readonly' => true, + 'selected' => true, + 'single_cat_title' => true, + 'single_month_title' => true, + 'single_post_title' => true, + 'single_tag_title' => true, + 'single_term_title' => true, + 'tag_description' => true, + 'term_description' => true, + 'the_author' => true, + 'the_date' => true, + 'the_title_attribute' => true, + 'walk_nav_menu_tree' => true, + 'wp_dropdown_categories' => true, + 'wp_dropdown_users' => true, + 'wp_generate_tag_cloud' => true, + 'wp_get_archives' => true, + 'wp_get_attachment_image' => true, + 'wp_get_attachment_link' => true, + 'wp_link_pages' => true, + 'wp_list_authors' => true, + 'wp_list_bookmarks' => true, + 'wp_list_categories' => true, + 'wp_list_comments' => true, + 'wp_login_form' => true, + 'wp_loginout' => true, + 'wp_nav_menu' => true, + 'wp_register' => true, + 'wp_tag_cloud' => true, + 'wp_title' => true, + ); + + /** + * Functions that sanitize values. + * + * This list is complementary to the `$unslashingSanitizingFunctions` + * list. + * Sanitizing functions should be added to this list if they do *not* + * implicitely unslash data and to the `$unslashingsanitizingFunctions` + * list if they do. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $sanitizingFunctions = array( + '_wp_handle_upload' => true, + 'esc_url_raw' => true, + 'filter_input' => true, + 'filter_var' => true, + 'hash_equals' => true, + 'is_email' => true, + 'number_format' => true, + 'sanitize_bookmark_field' => true, + 'sanitize_bookmark' => true, + 'sanitize_email' => true, + 'sanitize_file_name' => true, + 'sanitize_hex_color_no_hash' => true, + 'sanitize_hex_color' => true, + 'sanitize_html_class' => true, + 'sanitize_meta' => true, + 'sanitize_mime_type' => true, + 'sanitize_option' => true, + 'sanitize_sql_orderby' => true, + 'sanitize_term_field' => true, + 'sanitize_term' => true, + 'sanitize_text_field' => true, + 'sanitize_textarea_field' => true, + 'sanitize_title_for_query' => true, + 'sanitize_title_with_dashes' => true, + 'sanitize_title' => true, + 'sanitize_user_field' => true, + 'sanitize_user' => true, + 'validate_file' => true, + 'wp_handle_sideload' => true, + 'wp_handle_upload' => true, + 'wp_kses_allowed_html' => true, + 'wp_kses_data' => true, + 'wp_kses_post' => true, + 'wp_kses' => true, + 'wp_parse_id_list' => true, + 'wp_redirect' => true, + 'wp_safe_redirect' => true, + 'wp_sanitize_redirect' => true, + 'wp_strip_all_tags' => true, + ); + + /** + * Sanitizing functions that implicitly unslash the data passed to them. + * + * This list is complementary to the `$sanitizingFunctions` list. + * Sanitizing functions should be added to this list if they also + * implicitely unslash data and to the `$sanitizingFunctions` list + * if they don't. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $unslashingSanitizingFunctions = array( + 'absint' => true, + 'boolval' => true, + 'count' => true, + 'doubleval' => true, + 'floatval' => true, + 'intval' => true, + 'sanitize_key' => true, + 'sizeof' => true, + ); + + /** + * Functions which unslash the data passed to them. + * + * @since 2.1.0 + * + * @var array + */ + protected $unslashingFunctions = array( + 'stripslashes_deep' => true, + 'stripslashes_from_strings_only' => true, + 'wp_unslash' => true, + ); + + /** + * List of PHP native functions to test the type of a variable. + * + * Using these functions is safe in combination with superglobals without + * unslashing or sanitization. + * + * They should, however, not be regarded as unslashing or sanitization functions. + * + * @since 2.1.0 + * + * @var array + */ + protected $typeTestFunctions = array( + 'is_array' => true, + 'is_bool' => true, + 'is_callable' => true, + 'is_countable' => true, + 'is_double' => true, + 'is_float' => true, + 'is_int' => true, + 'is_integer' => true, + 'is_iterable' => true, + 'is_long' => true, + 'is_null' => true, + 'is_numeric' => true, + 'is_object' => true, + 'is_real' => true, + 'is_resource' => true, + 'is_scalar' => true, + 'is_string' => true, + ); + + /** + * Token which when they preceed code indicate the value is safely casted. + * + * @since 1.1.0 + * + * @var array + */ + protected $safe_casts = array( + \T_INT_CAST => true, + \T_DOUBLE_CAST => true, + \T_BOOL_CAST => true, + \T_UNSET_CAST => true, + ); + + /** + * List of array functions which apply a callback to the array. + * + * These are often used for sanitization/escaping an array variable. + * + * Note: functions which alter the array by reference are not listed here on purpose. + * These cannot easily be used for sanitization as they can't be combined with unslashing. + * Similarly, they cannot be used for late escaping as the return value is a boolean, not + * the altered array. + * + * @since 2.1.0 + * + * @var array => + */ + protected $arrayWalkingFunctions = array( + 'array_map' => 1, + 'map_deep' => 2, + ); + + /** + * Array functions to compare a $needle to a predefined set of values. + * + * If the value is set to an integer, the function needs to have at least that + * many parameters for it to be considered as a comparison. + * + * @since 2.1.0 + * + * @var array => + */ + protected $arrayCompareFunctions = array( + 'in_array' => true, + 'array_search' => true, + 'array_keys' => 2, + ); + + /** + * Functions that format strings. + * + * These functions are often used for formatting values just before output, and + * it is common practice to escape the individual parameters passed to them as + * needed instead of escaping the entire result. This is especially true when the + * string being formatted contains HTML, which makes escaping the full result + * more difficult. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $formattingFunctions = array( + 'array_fill' => true, + 'ent2ncr' => true, + 'implode' => true, + 'join' => true, + 'nl2br' => true, + 'sprintf' => true, + 'vsprintf' => true, + 'wp_sprintf' => true, + ); + + /** + * Functions which print output incorporating the values passed to them. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $printingFunctions = array( + '_deprecated_argument' => true, + '_deprecated_constructor' => true, + '_deprecated_file' => true, + '_deprecated_function' => true, + '_deprecated_hook' => true, + '_doing_it_wrong' => true, + '_e' => true, + '_ex' => true, + 'printf' => true, + 'trigger_error' => true, + 'user_error' => true, + 'vprintf' => true, + 'wp_die' => true, + 'wp_dropdown_pages' => true, + ); + + /** + * Functions that escape values for use in SQL queries. + * + * @since 0.9.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $SQLEscapingFunctions = array( + 'absint' => true, + 'esc_sql' => true, + 'floatval' => true, + 'intval' => true, + 'like_escape' => true, + ); + + /** + * Functions whose output is automatically escaped for use in SQL queries. + * + * @since 0.9.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $SQLAutoEscapedFunctions = array( + 'count' => true, + ); + + /** + * A list of functions that get data from the cache. + * + * @since 0.6.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $cacheGetFunctions = array( + 'wp_cache_get' => true, + ); + + /** + * A list of functions that set data in the cache. + * + * @since 0.6.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $cacheSetFunctions = array( + 'wp_cache_set' => true, + 'wp_cache_add' => true, + ); + + /** + * A list of functions that delete data from the cache. + * + * @since 0.6.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $cacheDeleteFunctions = array( + 'wp_cache_delete' => true, + 'clean_attachment_cache' => true, + 'clean_blog_cache' => true, + 'clean_bookmark_cache' => true, + 'clean_category_cache' => true, + 'clean_comment_cache' => true, + 'clean_network_cache' => true, + 'clean_object_term_cache' => true, + 'clean_page_cache' => true, + 'clean_post_cache' => true, + 'clean_term_cache' => true, + 'clean_user_cache' => true, + ); + + /** + * A list of functions that invoke WP hooks (filters/actions). + * + * @since 0.10.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $hookInvokeFunctions = array( + 'do_action' => true, + 'do_action_ref_array' => true, + 'do_action_deprecated' => true, + 'apply_filters' => true, + 'apply_filters_ref_array' => true, + 'apply_filters_deprecated' => true, + ); + + /** + * A list of functions that are used to interact with the WP plugins API. + * + * @since 0.10.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array => + */ + protected $hookFunctions = array( + 'has_filter' => 1, + 'add_filter' => 1, + 'remove_filter' => 1, + 'remove_all_filters' => 1, + 'doing_filter' => 1, // Hook name optional. + 'has_action' => 1, + 'add_action' => 1, + 'doing_action' => 1, // Hook name optional. + 'did_action' => 1, + 'remove_action' => 1, + 'remove_all_actions' => 1, + 'current_filter' => 0, // No hook name argument. + ); + + /** + * List of global WP variables. + * + * @since 0.3.0 + * @since 0.11.0 Changed visibility from public to protected. + * @since 0.12.0 Renamed from `$globals` to `$wp_globals` to be more descriptive. + * @since 0.12.0 Moved here from the WordPress.Variables.GlobalVariables sniff. + * + * @var array + */ + protected $wp_globals = array( + '_links_add_base' => true, + '_links_add_target' => true, + '_menu_item_sort_prop' => true, + '_nav_menu_placeholder' => true, + '_new_bundled_files' => true, + '_old_files' => true, + '_parent_pages' => true, + '_registered_pages' => true, + '_updated_user_settings' => true, + '_wp_additional_image_sizes' => true, + '_wp_admin_css_colors' => true, + '_wp_default_headers' => true, + '_wp_deprecated_widgets_callbacks' => true, + '_wp_last_object_menu' => true, + '_wp_last_utility_menu' => true, + '_wp_menu_nopriv' => true, + '_wp_nav_menu_max_depth' => true, + '_wp_post_type_features' => true, + '_wp_real_parent_file' => true, + '_wp_registered_nav_menus' => true, + '_wp_sidebars_widgets' => true, + '_wp_submenu_nopriv' => true, + '_wp_suspend_cache_invalidation' => true, + '_wp_theme_features' => true, + '_wp_using_ext_object_cache' => true, + 'action' => true, + 'active_signup' => true, + 'admin_body_class' => true, + 'admin_page_hooks' => true, + 'all_links' => true, + 'allowedentitynames' => true, + 'allowedposttags' => true, + 'allowedtags' => true, + 'auth_secure_cookie' => true, + 'authordata' => true, + 'avail_post_mime_types' => true, + 'avail_post_stati' => true, + 'blog_id' => true, + 'blog_title' => true, + 'blogname' => true, + 'cat' => true, + 'cat_id' => true, + 'charset_collate' => true, + 'comment' => true, + 'comment_alt' => true, + 'comment_depth' => true, + 'comment_status' => true, + 'comment_thread_alt' => true, + 'comment_type' => true, + 'comments' => true, + 'compress_css' => true, + 'compress_scripts' => true, + 'concatenate_scripts' => true, + 'content_width' => true, + 'current_blog' => true, + 'current_screen' => true, + 'current_site' => true, + 'current_user' => true, + 'currentcat' => true, + 'currentday' => true, + 'currentmonth' => true, + 'custom_background' => true, + 'custom_image_header' => true, + 'default_menu_order' => true, + 'descriptions' => true, + 'domain' => true, + 'editor_styles' => true, + 'error' => true, + 'errors' => true, + 'EZSQL_ERROR' => true, + 'feeds' => true, + 'GETID3_ERRORARRAY' => true, + 'hook_suffix' => true, + 'HTTP_RAW_POST_DATA' => true, + 'id' => true, + 'in_comment_loop' => true, + 'interim_login' => true, + 'is_apache' => true, + 'is_chrome' => true, + 'is_gecko' => true, + 'is_IE' => true, + 'is_IIS' => true, + 'is_iis7' => true, + 'is_macIE' => true, + 'is_NS4' => true, + 'is_opera' => true, + 'is_safari' => true, + 'is_winIE' => true, + 'l10n' => true, + 'link' => true, + 'link_id' => true, + 'locale' => true, + 'locked_post_status' => true, + 'lost' => true, + 'm' => true, + 'map' => true, + 'menu' => true, + 'menu_order' => true, + 'merged_filters' => true, + 'mode' => true, + 'monthnum' => true, + 'more' => true, + 'mu_plugin' => true, + 'multipage' => true, + 'names' => true, + 'nav_menu_selected_id' => true, + 'network_plugin' => true, + 'new_whitelist_options' => true, + 'numpages' => true, + 'one_theme_location_no_menus' => true, + 'opml' => true, + 'order' => true, + 'orderby' => true, + 'overridden_cpage' => true, + 'page' => true, + 'paged' => true, + 'pagenow' => true, + 'pages' => true, + 'parent_file' => true, + 'pass_allowed_html' => true, + 'pass_allowed_protocols' => true, + 'path' => true, + 'per_page' => true, + 'PHP_SELF' => true, + 'phpmailer' => true, + 'plugin_page' => true, + 'plugin' => true, + 'plugins' => true, + 'post' => true, + 'post_default_category' => true, + 'post_default_title' => true, + 'post_ID' => true, + 'post_id' => true, + 'post_mime_types' => true, + 'post_type' => true, + 'post_type_object' => true, + 'posts' => true, + 'preview' => true, + 'previouscat' => true, + 'previousday' => true, + 'previousweekday' => true, + 'redir_tab' => true, + 'required_mysql_version' => true, + 'required_php_version' => true, + 'rnd_value' => true, + 'role' => true, + 's' => true, + 'search' => true, + 'self' => true, + 'shortcode_tags' => true, + 'show_admin_bar' => true, + 'sidebars_widgets' => true, + 'status' => true, + 'submenu' => true, + 'submenu_file' => true, + 'super_admins' => true, + 'tab' => true, + 'table_prefix' => true, + 'tabs' => true, + 'tag' => true, + 'tag_ID' => true, + 'targets' => true, + 'tax' => true, + 'taxnow' => true, + 'taxonomy' => true, + 'term' => true, + 'text_direction' => true, + 'theme_field_defaults' => true, + 'themes_allowedtags' => true, + 'timeend' => true, + 'timestart' => true, + 'tinymce_version' => true, + 'title' => true, + 'totals' => true, + 'type' => true, + 'typenow' => true, + 'updated_timestamp' => true, + 'upgrading' => true, + 'urls' => true, + 'user_email' => true, + 'user_ID' => true, + 'user_identity' => true, + 'user_level' => true, + 'user_login' => true, + 'user_url' => true, + 'userdata' => true, + 'usersearch' => true, + 'whitelist_options' => true, + 'withcomments' => true, + 'wp' => true, + 'wp_actions' => true, + 'wp_admin_bar' => true, + 'wp_cockneyreplace' => true, + 'wp_current_db_version' => true, + 'wp_current_filter' => true, + 'wp_customize' => true, + 'wp_dashboard_control_callbacks' => true, + 'wp_db_version' => true, + 'wp_did_header' => true, + 'wp_embed' => true, + 'wp_file_descriptions' => true, + 'wp_filesystem' => true, + 'wp_filter' => true, + 'wp_hasher' => true, + 'wp_header_to_desc' => true, + 'wp_importers' => true, + 'wp_json' => true, + 'wp_list_table' => true, + 'wp_local_package' => true, + 'wp_locale' => true, + 'wp_meta_boxes' => true, + 'wp_object_cache' => true, + 'wp_plugin_paths' => true, + 'wp_post_statuses' => true, + 'wp_post_types' => true, + 'wp_queries' => true, + 'wp_query' => true, + 'wp_registered_sidebars' => true, + 'wp_registered_widget_controls' => true, + 'wp_registered_widget_updates' => true, + 'wp_registered_widgets' => true, + 'wp_rewrite' => true, + 'wp_rich_edit' => true, + 'wp_rich_edit_exists' => true, + 'wp_roles' => true, + 'wp_scripts' => true, + 'wp_settings_errors' => true, + 'wp_settings_fields' => true, + 'wp_settings_sections' => true, + 'wp_smiliessearch' => true, + 'wp_styles' => true, + 'wp_taxonomies' => true, + 'wp_the_query' => true, + 'wp_theme_directories' => true, + 'wp_themes' => true, + 'wp_user_roles' => true, + 'wp_version' => true, + 'wp_widget_factory' => true, + 'wp_xmlrpc_server' => true, + 'wpcommentsjavascript' => true, + 'wpcommentspopupfile' => true, + 'wpdb' => true, + 'wpsmiliestrans' => true, + 'year' => true, + ); + + /** + * A list of superglobals that incorporate user input. + * + * @since 0.5.0 + * @since 0.11.0 Changed from static to non-static. + * + * @var string[] + */ + protected $input_superglobals = array( + '$_COOKIE', + '$_GET', + '$_FILES', + '$_POST', + '$_REQUEST', + '$_SERVER', + ); + + /** + * Whitelist of classes which test classes can extend. + * + * @since 0.11.0 + * + * @var string[] + */ + protected $test_class_whitelist = array( + 'WP_UnitTestCase_Base' => true, + 'WP_UnitTestCase' => true, + 'WP_Ajax_UnitTestCase' => true, + 'WP_Canonical_UnitTestCase' => true, + 'WP_Test_REST_TestCase' => true, + 'WP_Test_REST_Controller_Testcase' => true, + 'WP_Test_REST_Post_Type_Controller_Testcase' => true, + 'WP_XMLRPC_UnitTestCase' => true, + 'PHPUnit_Framework_TestCase' => true, + 'PHPUnit\Framework\TestCase' => true, + // PHPUnit native TestCase class when imported via use statement. + 'TestCase' => true, + ); + + /** + * The current file being sniffed. + * + * @since 0.4.0 + * + * @var \PHP_CodeSniffer\Files\File + */ + protected $phpcsFile; + + /** + * The list of tokens in the current file being sniffed. + * + * @since 0.4.0 + * + * @var array + */ + protected $tokens; + + /** + * Set sniff properties and hand off to child class for processing of the token. + * + * @since 0.11.0 + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process( File $phpcsFile, $stackPtr ) { + $this->init( $phpcsFile ); + return $this->process_token( $stackPtr ); + } + + /** + * Processes a sniff when one of its tokens is encountered. + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + abstract public function process_token( $stackPtr ); + + /** + * Initialize the class for the current process. + * + * This method must be called by child classes before using many of the methods + * below. + * + * @since 0.4.0 + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file currently being processed. + */ + protected function init( File $phpcsFile ) { + $this->phpcsFile = $phpcsFile; + $this->tokens = $phpcsFile->getTokens(); + } + + /** + * Strip quotes surrounding an arbitrary string. + * + * Intended for use with the contents of a T_CONSTANT_ENCAPSED_STRING / T_DOUBLE_QUOTED_STRING. + * + * @since 0.11.0 + * + * @param string $string The raw string. + * @return string String without quotes around it. + */ + public function strip_quotes( $string ) { + return preg_replace( '`^([\'"])(.*)\1$`Ds', '$2', $string ); + } + + /** + * Add a PHPCS message to the output stack as either a warning or an error. + * + * @since 0.11.0 + * + * @param string $message The message. + * @param int $stackPtr The position of the token the message relates to. + * @param bool $is_error Optional. Whether to report the message as an 'error' or 'warning'. + * Defaults to true (error). + * @param string $code Optional error code for the message. Defaults to 'Found'. + * @param array $data Optional input for the data replacements. + * @param int $severity Optional. Severity level. Defaults to 0 which will translate to + * the PHPCS default severity level. + * @return bool + */ + protected function addMessage( $message, $stackPtr, $is_error = true, $code = 'Found', $data = array(), $severity = 0 ) { + return $this->throwMessage( $message, $stackPtr, $is_error, $code, $data, $severity, false ); + } + + /** + * Add a fixable PHPCS message to the output stack as either a warning or an error. + * + * @since 0.11.0 + * + * @param string $message The message. + * @param int $stackPtr The position of the token the message relates to. + * @param bool $is_error Optional. Whether to report the message as an 'error' or 'warning'. + * Defaults to true (error). + * @param string $code Optional error code for the message. Defaults to 'Found'. + * @param array $data Optional input for the data replacements. + * @param int $severity Optional. Severity level. Defaults to 0 which will translate to + * the PHPCS default severity level. + * @return bool + */ + protected function addFixableMessage( $message, $stackPtr, $is_error = true, $code = 'Found', $data = array(), $severity = 0 ) { + return $this->throwMessage( $message, $stackPtr, $is_error, $code, $data, $severity, true ); + } + + /** + * Add a PHPCS message to the output stack as either a warning or an error. + * + * @since 0.11.0 + * + * @param string $message The message. + * @param int $stackPtr The position of the token the message relates to. + * @param bool $is_error Optional. Whether to report the message as an 'error' or 'warning'. + * Defaults to true (error). + * @param string $code Optional error code for the message. Defaults to 'Found'. + * @param array $data Optional input for the data replacements. + * @param int $severity Optional. Severity level. Defaults to 0 which will translate to + * the PHPCS default severity level. + * @param bool $fixable Optional. Whether this is a fixable error. Defaults to false. + * @return bool + */ + private function throwMessage( $message, $stackPtr, $is_error = true, $code = 'Found', $data = array(), $severity = 0, $fixable = false ) { + + $method = 'add'; + if ( true === $fixable ) { + $method .= 'Fixable'; + } + + if ( true === $is_error ) { + $method .= 'Error'; + } else { + $method .= 'Warning'; + } + + return \call_user_func( array( $this->phpcsFile, $method ), $message, $stackPtr, $code, $data, $severity ); + } + + /** + * Convert an arbitrary string to an alphanumeric string with underscores. + * + * Pre-empt issues with arbitrary strings being used as error codes in XML and PHP. + * + * @since 0.11.0 + * + * @param string $base_string Arbitrary string. + * + * @return string + */ + protected function string_to_errorcode( $base_string ) { + return preg_replace( '`[^a-z0-9_]`i', '_', $base_string ); + } + + /** + * Transform the name of a PHP construct (function, variable etc) to one in snake_case. + * + * @since 2.0.0 Moved from the `WordPress.NamingConventions.ValidFunctionName` sniff + * to this class, renamed from `get_name_suggestion` and made static + * so it can also be used by classes which don't extend this class. + * + * @param string $name The construct name. + * + * @return string + */ + public static function get_snake_case_name_suggestion( $name ) { + $suggested = preg_replace( '`([A-Z])`', '_$1', $name ); + $suggested = strtolower( $suggested ); + $suggested = str_replace( '__', '_', $suggested ); + $suggested = trim( $suggested, '_' ); + return $suggested; + } + + /** + * Merge a pre-set array with a ruleset provided array. + * + * - By default flips custom lists to allow for using `isset()` instead + * of `in_array()`. + * - When `$flip` is true: + * * Presumes the base array is in a `'value' => true` format. + * * Any custom items will be given the value `false` to be able to + * distinguish them from pre-set (base array) values. + * * Will filter previously added custom items out from the base array + * before merging/returning to allow for resetting to the base array. + * + * {@internal Function is static as it doesn't use any of the properties or others + * methods anyway and this way the `WordPress.NamingConventions.ValidVariableName` sniff + * which extends an upstream sniff can also use it.}} + * + * @since 0.11.0 + * @since 2.0.0 No longer supports custom array properties which were incorrectly + * passed as a string. + * + * @param array $custom Custom list as provided via a ruleset. + * @param array $base Optional. Base list. Defaults to an empty array. + * Expects `value => true` format when `$flip` is true. + * @param bool $flip Optional. Whether or not to flip the custom list. + * Defaults to true. + * @return array + */ + public static function merge_custom_array( $custom, $base = array(), $flip = true ) { + if ( true === $flip ) { + $base = array_filter( $base ); + } + + if ( empty( $custom ) || ! \is_array( $custom ) ) { + return $base; + } + + if ( true === $flip ) { + $custom = array_fill_keys( $custom, false ); + } + + if ( empty( $base ) ) { + return $custom; + } + + return array_merge( $base, $custom ); + } + + /** + * Get the last pointer in a line. + * + * @since 0.4.0 + * + * @param integer $stackPtr The position of the current token in the stack passed + * in $tokens. + * + * @return integer Position of the last pointer on that line. + */ + protected function get_last_ptr_on_line( $stackPtr ) { + + $tokens = $this->tokens; + $currentLine = $tokens[ $stackPtr ]['line']; + $nextPtr = ( $stackPtr + 1 ); + + while ( isset( $tokens[ $nextPtr ] ) && $tokens[ $nextPtr ]['line'] === $currentLine ) { + $nextPtr++; + // Do nothing, we just want the last token of the line. + } + + // We've made it to the next line, back up one to the last in the previous line. + // We do this for micro-optimization of the above loop. + $lastPtr = ( $nextPtr - 1 ); + + return $lastPtr; + } + + /** + * Overrule the minimum supported WordPress version with a command-line/config value. + * + * Handle setting the minimum supported WP version in one go for all sniffs which + * expect it via the command line or via a `` variable in a ruleset. + * The config variable overrules the default `$minimum_supported_version` and/or a + * `$minimum_supported_version` set for individual sniffs through the ruleset. + * + * @since 0.14.0 + */ + protected function get_wp_version_from_cl() { + $cl_supported_version = trim( PHPCSHelper::get_config_data( 'minimum_supported_wp_version' ) ); + if ( ! empty( $cl_supported_version ) + && filter_var( $cl_supported_version, \FILTER_VALIDATE_FLOAT ) !== false + ) { + $this->minimum_supported_version = $cl_supported_version; + } + } + + /** + * Find whitelisting comment. + * + * Comment must be at the end of the line or at the end of the statement + * and must use // format. + * It can be prefixed or suffixed with anything e.g. "foobar" will match: + * ... // foobar okay + * ... // WPCS: foobar whitelist. + * + * There is an exception, and that is when PHP is being interspersed with HTML. + * In that case, the comment should always come at the end of the statement (right + * before the closing tag, ?>). For example: + * + * + * + * @since 0.4.0 + * @since 0.14.0 Whitelist comments at the end of the statement are now also accepted. + * + * @deprecated 2.0.0 Use the PHPCS native `phpcs:ignore` annotations instead. + * + * @param string $comment Comment to find. + * @param integer $stackPtr The position of the current token in the stack passed + * in $tokens. + * + * @return boolean True if whitelisting comment was found, false otherwise. + */ + protected function has_whitelist_comment( $comment, $stackPtr ) { + + // Respect the PHPCS 3.x --ignore-annotations setting. + if ( true === PHPCSHelper::ignore_annotations( $this->phpcsFile ) ) { + return false; + } + + static $thrown_notices = array(); + + $deprecation_notice = 'Using the WPCS native whitelist comments is deprecated. Please use the PHPCS native "phpcs:ignore Standard.Category.SniffName.ErrorCode" annotations instead. Found: %s'; + $deprecation_code = 'DeprecatedWhitelistCommentFound'; + $filename = $this->phpcsFile->getFileName(); + + $regex = '#\b' . preg_quote( $comment, '#' ) . '\b#i'; + + // There is a findEndOfStatement() method, but it considers more tokens than + // we need to consider here. + $end_of_statement = $this->phpcsFile->findNext( array( \T_CLOSE_TAG, \T_SEMICOLON ), $stackPtr ); + + if ( false !== $end_of_statement ) { + // If the statement was ended by a semicolon, check if there is a whitelist comment directly after it. + if ( \T_SEMICOLON === $this->tokens[ $end_of_statement ]['code'] ) { + $lastPtr = $this->phpcsFile->findNext( \T_WHITESPACE, ( $end_of_statement + 1 ), null, true ); + } elseif ( \T_CLOSE_TAG === $this->tokens[ $end_of_statement ]['code'] ) { + // If the semicolon was left out and it was terminated by an ending tag, we need to look backwards. + $lastPtr = $this->phpcsFile->findPrevious( \T_WHITESPACE, ( $end_of_statement - 1 ), null, true ); + } + + if ( ( \T_COMMENT === $this->tokens[ $lastPtr ]['code'] + || ( isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $lastPtr ]['code'] ] ) + && \T_PHPCS_SET !== $this->tokens[ $lastPtr ]['code'] ) ) + && $this->tokens[ $lastPtr ]['line'] === $this->tokens[ $end_of_statement ]['line'] + && preg_match( $regex, $this->tokens[ $lastPtr ]['content'] ) === 1 + ) { + if ( isset( $thrown_notices[ $filename ][ $lastPtr ] ) === false + && isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $lastPtr ]['code'] ] ) === false + ) { + $this->phpcsFile->addWarning( + $deprecation_notice, + $lastPtr, + $deprecation_code, + array( $this->tokens[ $lastPtr ]['content'] ) + ); + + $thrown_notices[ $filename ][ $lastPtr ] = true; + } + + return true; + } + } + + // No whitelist comment found so far. Check at the end of the stackPtr line. + // Note: a T_COMMENT includes the new line character, so may be the last token on the line! + $end_of_line = $this->get_last_ptr_on_line( $stackPtr ); + $lastPtr = $this->phpcsFile->findPrevious( \T_WHITESPACE, $end_of_line, null, true ); + + if ( ( \T_COMMENT === $this->tokens[ $lastPtr ]['code'] + || ( isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $lastPtr ]['code'] ] ) + && \T_PHPCS_SET !== $this->tokens[ $lastPtr ]['code'] ) ) + && $this->tokens[ $lastPtr ]['line'] === $this->tokens[ $stackPtr ]['line'] + && preg_match( $regex, $this->tokens[ $lastPtr ]['content'] ) === 1 + ) { + if ( isset( $thrown_notices[ $filename ][ $lastPtr ] ) === false + && isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $lastPtr ]['code'] ] ) === false + ) { + $this->phpcsFile->addWarning( + $deprecation_notice, + $lastPtr, + $deprecation_code, + array( $this->tokens[ $lastPtr ]['content'] ) + ); + + $thrown_notices[ $filename ][ $lastPtr ] = true; + } + + return true; + } + + return false; + } + + /** + * Check if a token is used within a unit test. + * + * Unit test methods are identified as such: + * - Method is within a known unit test class; + * - or Method is within a class/trait which extends a known unit test class. + * + * @since 0.11.0 + * @since 1.1.0 Supports anonymous test classes and improved handling of nested scopes. + * + * @param int $stackPtr The position of the token to be examined. + * + * @return bool True if the token is within a unit test, false otherwise. + */ + protected function is_token_in_test_method( $stackPtr ) { + // Is the token inside of a function definition ? + $functionToken = $this->phpcsFile->getCondition( $stackPtr, \T_FUNCTION ); + if ( false === $functionToken ) { + // No conditions or no function condition. + return false; + } + + $conditions = $this->tokens[ $stackPtr ]['conditions']; + foreach ( $conditions as $token => $condition ) { + if ( $token === $functionToken ) { + // Only examine the conditions the function is nested in, not those nested within the function. + break; + } + + if ( isset( Tokens::$ooScopeTokens[ $condition ] ) ) { + $is_test_class = $this->is_test_class( $token ); + if ( true === $is_test_class ) { + return true; + } + } + } + + return false; + } + + /** + * Check if a class token is part of a unit test suite. + * + * Unit test classes are identified as such: + * - Class which either extends WP_UnitTestCase or PHPUnit_Framework_TestCase + * or a custom whitelisted unit test class. + * + * @since 0.12.0 Split off from the `is_token_in_test_method()` method. + * @since 1.0.0 Improved recognition of namespaced class names. + * + * @param int $stackPtr The position of the token to be examined. + * This should be a class, anonymous class or trait token. + * + * @return bool True if the class is a unit test class, false otherwise. + */ + protected function is_test_class( $stackPtr ) { + + if ( isset( $this->tokens[ $stackPtr ], Tokens::$ooScopeTokens[ $this->tokens[ $stackPtr ]['code'] ] ) === false ) { + return false; + } + + // Add any potentially whitelisted custom test classes to the whitelist. + $whitelist = $this->merge_custom_array( + $this->custom_test_class_whitelist, + $this->test_class_whitelist + ); + + /* + * Show some tolerance for user input. + * The custom test class names should be passed as FQN without a prefixing `\`. + */ + foreach ( $whitelist as $k => $v ) { + $whitelist[ $k ] = ltrim( $v, '\\' ); + } + + // Is the class/trait one of the whitelisted test classes ? + $namespace = $this->determine_namespace( $stackPtr ); + $className = $this->phpcsFile->getDeclarationName( $stackPtr ); + if ( '' !== $namespace ) { + if ( isset( $whitelist[ $namespace . '\\' . $className ] ) ) { + return true; + } + } elseif ( isset( $whitelist[ $className ] ) ) { + return true; + } + + // Does the class/trait extend one of the whitelisted test classes ? + $extendedClassName = $this->phpcsFile->findExtendedClassName( $stackPtr ); + if ( false === $extendedClassName ) { + return false; + } + + if ( '\\' === $extendedClassName[0] ) { + if ( isset( $whitelist[ substr( $extendedClassName, 1 ) ] ) ) { + return true; + } + } elseif ( '' !== $namespace ) { + if ( isset( $whitelist[ $namespace . '\\' . $extendedClassName ] ) ) { + return true; + } + } elseif ( isset( $whitelist[ $extendedClassName ] ) ) { + return true; + } + + /* + * Not examining imported classes via `use` statements as with the variety of syntaxes, + * this would get very complicated. + * After all, users can add an `` for a particular sniff to their + * custom ruleset to selectively exclude the test directory. + */ + + return false; + } + + /** + * Check if this variable is being assigned a value. + * + * E.g., $var = 'foo'; + * + * Also handles array assignments to arbitrary depth: + * + * $array['key'][ $foo ][ something() ] = $bar; + * + * @since 0.5.0 + * + * @param int $stackPtr The index of the token in the stack. This must point to + * either a T_VARIABLE or T_CLOSE_SQUARE_BRACKET token. + * + * @return bool Whether the token is a variable being assigned a value. + */ + protected function is_assignment( $stackPtr ) { + + static $valid = array( + \T_VARIABLE => true, + \T_CLOSE_SQUARE_BRACKET => true, + ); + + // Must be a variable, constant or closing square bracket (see below). + if ( ! isset( $valid[ $this->tokens[ $stackPtr ]['code'] ] ) ) { + return false; + } + + $next_non_empty = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $stackPtr + 1 ), + null, + true, + null, + true + ); + + // No token found. + if ( false === $next_non_empty ) { + return false; + } + + // If the next token is an assignment, that's all we need to know. + if ( isset( Tokens::$assignmentTokens[ $this->tokens[ $next_non_empty ]['code'] ] ) ) { + return true; + } + + // Check if this is an array assignment, e.g., `$var['key'] = 'val';` . + if ( \T_OPEN_SQUARE_BRACKET === $this->tokens[ $next_non_empty ]['code'] + && isset( $this->tokens[ $next_non_empty ]['bracket_closer'] ) + ) { + return $this->is_assignment( $this->tokens[ $next_non_empty ]['bracket_closer'] ); + } + + return false; + } + + /** + * Check if this token has an associated nonce check. + * + * @since 0.5.0 + * + * @param int $stackPtr The position of the current token in the stack of tokens. + * + * @return bool + */ + protected function has_nonce_check( $stackPtr ) { + + /** + * A cache of the scope that we last checked for nonce verification in. + * + * @var array { + * @var string $file The name of the file. + * @var int $start The index of the token where the scope started. + * @var int $end The index of the token where the scope ended. + * @var bool|int $nonce_check The index of the token where an nonce check + * was found, or false if none was found. + * } + */ + static $last; + + $start = 0; + $end = $stackPtr; + + $tokens = $this->phpcsFile->getTokens(); + + // If we're in a function, only look inside of it. + // Once PHPCS 3.5.0 comes out this should be changed to the new Conditions::GetLastCondition() method. + if ( isset( $tokens[ $stackPtr ]['conditions'] ) === true ) { + $conditions = $tokens[ $stackPtr ]['conditions']; + $conditions = array_reverse( $conditions, true ); + foreach ( $conditions as $tokenPtr => $condition ) { + if ( \T_FUNCTION === $condition || \T_CLOSURE === $condition ) { + $start = $tokens[ $tokenPtr ]['scope_opener']; + break; + } + } + } + + $allow_nonce_after = false; + if ( $this->is_in_isset_or_empty( $stackPtr ) + || $this->is_in_type_test( $stackPtr ) + || $this->is_comparison( $stackPtr ) + || $this->is_in_array_comparison( $stackPtr ) + || $this->is_in_function_call( $stackPtr, $this->unslashingFunctions ) !== false + || $this->is_only_sanitized( $stackPtr ) + ) { + $allow_nonce_after = true; + } + + // We allow for certain actions, such as an isset() check to come before the nonce check. + // If this superglobal is inside such a check, look for the nonce after it as well, + // all the way to the end of the scope. + if ( true === $allow_nonce_after ) { + $end = ( 0 === $start ) ? $this->phpcsFile->numTokens : $tokens[ $start ]['scope_closer']; + } + + // Check if we've looked here before. + $filename = $this->phpcsFile->getFilename(); + + if ( is_array( $last ) + && $filename === $last['file'] + && $start === $last['start'] + ) { + + if ( false !== $last['nonce_check'] ) { + // If we have already found an nonce check in this scope, we just + // need to check whether it comes before this token. It is OK if the + // check is after the token though, if this was only a isset() check. + return ( true === $allow_nonce_after || $last['nonce_check'] < $stackPtr ); + } elseif ( $end <= $last['end'] ) { + // If not, we can still go ahead and return false if we've already + // checked to the end of the search area. + return false; + } + + // We haven't checked this far yet, but we can still save work by + // skipping over the part we've already checked. + $start = $last['end']; + } else { + $last = array( + 'file' => $filename, + 'start' => $start, + 'end' => $end, + ); + } + + // Loop through the tokens looking for nonce verification functions. + for ( $i = $start; $i < $end; $i++ ) { + // Skip over nested closed scope constructs. + if ( \T_FUNCTION === $tokens[ $i ]['code'] + || \T_CLOSURE === $tokens[ $i ]['code'] + || isset( Tokens::$ooScopeTokens[ $tokens[ $i ]['code'] ] ) + ) { + if ( isset( $tokens[ $i ]['scope_closer'] ) ) { + $i = $tokens[ $i ]['scope_closer']; + } + continue; + } + + // If this isn't a function name, skip it. + if ( \T_STRING !== $tokens[ $i ]['code'] ) { + continue; + } + + // If this is one of the nonce verification functions, we can bail out. + if ( isset( $this->nonceVerificationFunctions[ $tokens[ $i ]['content'] ] ) ) { + /* + * Now, make sure it is a call to a global function. + */ + if ( $this->is_class_object_call( $i ) === true ) { + continue; + } + + if ( $this->is_token_namespaced( $i ) === true ) { + continue; + } + + $last['nonce_check'] = $i; + return true; + } + } + + // We're still here, so no luck. + $last['nonce_check'] = false; + + return false; + } + + /** + * Check if a token is inside of an isset(), empty() or array_key_exists() statement. + * + * @since 0.5.0 + * @since 2.1.0 Now checks for the token being used as the array parameter + * in function calls to array_key_exists() and key_exists() as well. + * + * @param int $stackPtr The index of the token in the stack. + * + * @return bool Whether the token is inside an isset() or empty() statement. + */ + protected function is_in_isset_or_empty( $stackPtr ) { + + if ( ! isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + return false; + } + + $nested_parenthesis = $this->tokens[ $stackPtr ]['nested_parenthesis']; + + end( $nested_parenthesis ); + $open_parenthesis = key( $nested_parenthesis ); + + $previous_non_empty = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $open_parenthesis - 1 ), null, true, null, true ); + if ( false === $previous_non_empty ) { + return false; + } + + $previous_code = $this->tokens[ $previous_non_empty ]['code']; + if ( \T_ISSET === $previous_code || \T_EMPTY === $previous_code ) { + return true; + } + + $valid_functions = array( + 'array_key_exists' => true, + 'key_exists' => true, // Alias. + ); + + $functionPtr = $this->is_in_function_call( $stackPtr, $valid_functions ); + if ( false !== $functionPtr ) { + $second_param = $this->get_function_call_parameter( $functionPtr, 2 ); + if ( $stackPtr >= $second_param['start'] && $stackPtr <= $second_param['end'] ) { + return true; + } + } + + return false; + } + + /** + * Check if a particular token is a (static or non-static) call to a class method or property. + * + * @internal Note: this may still mistake a namespaced function imported via a `use` statement for + * a global function! + * + * @since 2.1.0 + * + * @param int $stackPtr The index of the token in the stack. + * + * @return bool + */ + protected function is_class_object_call( $stackPtr ) { + $before = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true, null, true ); + + if ( false === $before ) { + return false; + } + + if ( \T_OBJECT_OPERATOR !== $this->tokens[ $before ]['code'] + && \T_DOUBLE_COLON !== $this->tokens[ $before ]['code'] + ) { + return false; + } + + return true; + } + + /** + * Check if a particular token is prefixed with a namespace. + * + * @internal This will give a false positive if the file is not namespaced and the token is prefixed + * with `namespace\`. + * + * @since 2.1.0 + * + * @param int $stackPtr The index of the token in the stack. + * + * @return bool + */ + protected function is_token_namespaced( $stackPtr ) { + $prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true, null, true ); + + if ( false === $prev ) { + return false; + } + + if ( \T_NS_SEPARATOR !== $this->tokens[ $prev ]['code'] ) { + return false; + } + + $before_prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $prev - 1 ), null, true, null, true ); + if ( false === $before_prev ) { + return false; + } + + if ( \T_STRING !== $this->tokens[ $before_prev ]['code'] + && \T_NAMESPACE !== $this->tokens[ $before_prev ]['code'] + ) { + return false; + } + + return true; + } + + /** + * Check if a token is (part of) a parameter for a function call to a select list of functions. + * + * This is useful, for instance, when trying to determine the context a variable is used in. + * + * For example: this function could be used to determine if the variable `$foo` is used + * in a global function call to the function `is_foo()`. + * In that case, a call to this function would return the stackPtr to the T_STRING `is_foo` + * for code like: `is_foo( $foo, 'some_other_param' )`, while it would return `false` for + * the following code `is_bar( $foo, 'some_other_param' )`. + * + * @since 2.1.0 + * + * @param int $stackPtr The index of the token in the stack. + * @param array $valid_functions List of valid function names. + * Note: The keys to this array should be the function names + * in lowercase. Values are irrelevant. + * @param bool $global Optional. Whether to make sure that the function call is + * to a global function. If `false`, calls to methods, be it static + * `Class::method()` or via an object `$obj->method()`, and + * namespaced function calls, like `MyNS\function_name()` will + * also be accepted. + * Defaults to `true`. + * @param bool $allow_nested Optional. Whether to allow for nested function calls within the + * call to this function. + * I.e. when checking whether a token is within a function call + * to `strtolower()`, whether to accept `strtolower( trim( $var ) )` + * or only `strtolower( $var )`. + * Defaults to `false`. + * + * @return int|bool Stack pointer to the function call T_STRING token or false otherwise. + */ + protected function is_in_function_call( $stackPtr, $valid_functions, $global = true, $allow_nested = false ) { + if ( ! isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + return false; + } + + $nested_parenthesis = $this->tokens[ $stackPtr ]['nested_parenthesis']; + if ( false === $allow_nested ) { + $nested_parenthesis = array_reverse( $nested_parenthesis, true ); + } + + foreach ( $nested_parenthesis as $open => $close ) { + + $prev_non_empty = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $open - 1 ), null, true, null, true ); + if ( false === $prev_non_empty || \T_STRING !== $this->tokens[ $prev_non_empty ]['code'] ) { + continue; + } + + if ( isset( $valid_functions[ strtolower( $this->tokens[ $prev_non_empty ]['content'] ) ] ) === false ) { + if ( false === $allow_nested ) { + // Function call encountered, but not to one of the allowed functions. + return false; + } + + continue; + } + + if ( false === $global ) { + return $prev_non_empty; + } + + /* + * Now, make sure it is a global function. + */ + if ( $this->is_class_object_call( $prev_non_empty ) === true ) { + continue; + } + + if ( $this->is_token_namespaced( $prev_non_empty ) === true ) { + continue; + } + + return $prev_non_empty; + } + + return false; + } + + /** + * Check if a token is inside of an is_...() statement. + * + * @since 2.1.0 + * + * @param int $stackPtr The index of the token in the stack. + * + * @return bool Whether the token is being type tested. + */ + protected function is_in_type_test( $stackPtr ) { + /* + * Casting the potential integer stack pointer return value to boolean here is fine. + * The return can never be `0` as there will always be a PHP open tag before the + * function call. + */ + return (bool) $this->is_in_function_call( $stackPtr, $this->typeTestFunctions ); + } + + /** + * Check if something is only being sanitized. + * + * @since 0.5.0 + * + * @param int $stackPtr The index of the token in the stack. + * + * @return bool Whether the token is only within a sanitization. + */ + protected function is_only_sanitized( $stackPtr ) { + + // If it isn't being sanitized at all. + if ( ! $this->is_sanitized( $stackPtr ) ) { + return false; + } + + // If this isn't set, we know the value must have only been casted, because + // is_sanitized() would have returned false otherwise. + if ( ! isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + return true; + } + + // At this point we're expecting the value to have not been casted. If it + // was, it wasn't *only* casted, because it's also in a function. + if ( $this->is_safe_casted( $stackPtr ) ) { + return false; + } + + // The only parentheses should belong to the sanitizing function. If there's + // more than one set, this isn't *only* sanitization. + return ( \count( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) === 1 ); + } + + /** + * Check if something is being casted to a safe value. + * + * @since 0.5.0 + * + * @param int $stackPtr The index of the token in the stack. + * + * @return bool Whether the token being casted. + */ + protected function is_safe_casted( $stackPtr ) { + + // Get the last non-empty token. + $prev = $this->phpcsFile->findPrevious( + Tokens::$emptyTokens, + ( $stackPtr - 1 ), + null, + true + ); + + if ( false === $prev ) { + return false; + } + + // Check if it is a safe cast. + return isset( $this->safe_casts[ $this->tokens[ $prev ]['code'] ] ); + } + + /** + * Check if something is being sanitized. + * + * @since 0.5.0 + * + * @param int $stackPtr The index of the token in the stack. + * @param bool $require_unslash Whether to give an error if no unslashing function + * is used on the variable before sanitization. + * + * @return bool Whether the token being sanitized. + */ + protected function is_sanitized( $stackPtr, $require_unslash = false ) { + + // First we check if it is being casted to a safe value. + if ( $this->is_safe_casted( $stackPtr ) ) { + return true; + } + + // If this isn't within a function call, we know already that it's not safe. + if ( ! isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + if ( $require_unslash ) { + $this->add_unslash_error( $stackPtr ); + } + + return false; + } + + // Get the function that it's in. + $nested_parenthesis = $this->tokens[ $stackPtr ]['nested_parenthesis']; + $nested_openers = array_keys( $nested_parenthesis ); + $function_opener = array_pop( $nested_openers ); + $functionPtr = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $function_opener - 1 ), null, true, null, true ); + + // If it is just being unset, the value isn't used at all, so it's safe. + if ( \T_UNSET === $this->tokens[ $functionPtr ]['code'] ) { + return true; + } + + $valid_functions = $this->sanitizingFunctions; + $valid_functions += $this->unslashingSanitizingFunctions; + $valid_functions += $this->unslashingFunctions; + $valid_functions += $this->arrayWalkingFunctions; + + $functionPtr = $this->is_in_function_call( $stackPtr, $valid_functions ); + + // If this isn't a call to one of the valid functions, it sure isn't a sanitizing function. + if ( false === $functionPtr ) { + if ( true === $require_unslash ) { + $this->add_unslash_error( $stackPtr ); + } + + return false; + } + + $functionName = $this->tokens[ $functionPtr ]['content']; + + // Check if an unslashing function is being used. + if ( isset( $this->unslashingFunctions[ $functionName ] ) ) { + + $is_unslashed = true; + + // Remove the unslashing functions. + $valid_functions = array_diff_key( $valid_functions, $this->unslashingFunctions ); + + // Check is any of the remaining (sanitizing) functions is used. + $higherFunctionPtr = $this->is_in_function_call( $functionPtr, $valid_functions ); + + // If there is no other valid function being used, this value is unsanitized. + if ( false === $higherFunctionPtr ) { + return false; + } + + $functionPtr = $higherFunctionPtr; + $functionName = $this->tokens[ $functionPtr ]['content']; + + } else { + $is_unslashed = false; + } + + // Arrays might be sanitized via an array walking function using a callback. + if ( isset( $this->arrayWalkingFunctions[ $functionName ] ) ) { + + // Get the callback parameter. + $callback = $this->get_function_call_parameter( $functionPtr, $this->arrayWalkingFunctions[ $functionName ] ); + + if ( ! empty( $callback ) ) { + /* + * If this is a function callback (not a method callback array) and we're able + * to resolve the function name, do so. + */ + $first_non_empty = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $callback['start'], + ( $callback['end'] + 1 ), + true + ); + + if ( false !== $first_non_empty && \T_CONSTANT_ENCAPSED_STRING === $this->tokens[ $first_non_empty ]['code'] ) { + $functionName = $this->strip_quotes( $this->tokens[ $first_non_empty ]['content'] ); + } + } + } + + // If slashing is required, give an error. + if ( ! $is_unslashed && $require_unslash && ! isset( $this->unslashingSanitizingFunctions[ $functionName ] ) ) { + $this->add_unslash_error( $stackPtr ); + } + + // Check if this is a sanitizing function. + if ( isset( $this->sanitizingFunctions[ $functionName ] ) || isset( $this->unslashingSanitizingFunctions[ $functionName ] ) ) { + return true; + } + + return false; + } + + /** + * Add an error for missing use of unslashing. + * + * @since 0.5.0 + * + * @param int $stackPtr The index of the token in the stack. + */ + public function add_unslash_error( $stackPtr ) { + + $this->phpcsFile->addError( + '%s data not unslashed before sanitization. Use wp_unslash() or similar', + $stackPtr, + 'MissingUnslash', + array( $this->tokens[ $stackPtr ]['content'] ) + ); + } + + /** + * Get the index keys of an array variable. + * + * E.g., "bar" and "baz" in $foo['bar']['baz']. + * + * @since 2.1.0 + * + * @param int $stackPtr The index of the variable token in the stack. + * @param bool $all Whether to get all keys or only the first. + * Defaults to `true`(= all). + * + * @return array An array of index keys whose value is being accessed. + * or an empty array if this is not array access. + */ + protected function get_array_access_keys( $stackPtr, $all = true ) { + + $keys = array(); + + if ( \T_VARIABLE !== $this->tokens[ $stackPtr ]['code'] ) { + return $keys; + } + + $current = $stackPtr; + + do { + // Find the next non-empty token. + $open_bracket = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $current + 1 ), + null, + true + ); + + // If it isn't a bracket, this isn't an array-access. + if ( false === $open_bracket + || \T_OPEN_SQUARE_BRACKET !== $this->tokens[ $open_bracket ]['code'] + || ! isset( $this->tokens[ $open_bracket ]['bracket_closer'] ) + ) { + break; + } + + $key = $this->phpcsFile->getTokensAsString( + ( $open_bracket + 1 ), + ( $this->tokens[ $open_bracket ]['bracket_closer'] - $open_bracket - 1 ) + ); + + $keys[] = trim( $key ); + $current = $this->tokens[ $open_bracket ]['bracket_closer']; + } while ( isset( $this->tokens[ $current ] ) && true === $all ); + + return $keys; + } + + /** + * Get the index key of an array variable. + * + * E.g., "bar" in $foo['bar']. + * + * @since 0.5.0 + * @since 2.1.0 Now uses get_array_access_keys() under the hood. + * + * @param int $stackPtr The index of the token in the stack. + * + * @return string|false The array index key whose value is being accessed. + */ + protected function get_array_access_key( $stackPtr ) { + + $keys = $this->get_array_access_keys( $stackPtr, false ); + + if ( isset( $keys[0] ) ) { + return $keys[0]; + } + + return false; + } + + /** + * Check if the existence of a variable is validated with isset(), empty(), array_key_exists() + * or key_exists(). + * + * When $in_condition_only is false, (which is the default), this is considered + * valid: + * + * ```php + * if ( isset( $var ) ) { + * // Do stuff, like maybe return or exit (but could be anything) + * } + * + * foo( $var ); + * ``` + * + * When it is true, that would be invalid, the use of the variable must be within + * the scope of the validating condition, like this: + * + * ```php + * if ( isset( $var ) ) { + * foo( $var ); + * } + * ``` + * + * @since 0.5.0 + * @since 2.1.0 Now recognizes array_key_exists() and key_exists() as validation functions. + * @since 2.1.0 Stricter check on whether the correct variable and the correct + * array keys are being validated. + * + * @param int $stackPtr The index of this token in the stack. + * @param array|string $array_keys An array key to check for ("bar" in $foo['bar']) + * or an array of keys for multi-level array access. + * @param bool $in_condition_only Whether to require that this use of the + * variable occur within the scope of the + * validating condition, or just in the same + * scope as it (default). + * + * @return bool Whether the var is validated. + */ + protected function is_validated( $stackPtr, $array_keys = array(), $in_condition_only = false ) { + + if ( $in_condition_only ) { + /* + * This is a stricter check, requiring the variable to be used only + * within the validation condition. + */ + + // If there are no conditions, there's no validation. + if ( empty( $this->tokens[ $stackPtr ]['conditions'] ) ) { + return false; + } + + $conditions = $this->tokens[ $stackPtr ]['conditions']; + end( $conditions ); // Get closest condition. + $conditionPtr = key( $conditions ); + $condition = $this->tokens[ $conditionPtr ]; + + if ( ! isset( $condition['parenthesis_opener'] ) ) { + // Live coding or parse error. + return false; + } + + $scope_start = $condition['parenthesis_opener']; + $scope_end = $condition['parenthesis_closer']; + + } else { + /* + * We are are more loose, requiring only that the variable be validated + * in the same function/file scope as it is used. + */ + + $scope_start = 0; + + // Check if we are in a function. + $function = $this->phpcsFile->getCondition( $stackPtr, \T_FUNCTION ); + + // If so, we check only within the function, otherwise the whole file. + if ( false !== $function ) { + $scope_start = $this->tokens[ $function ]['scope_opener']; + } else { + // Check if we are in a closure. + $closure = $this->phpcsFile->getCondition( $stackPtr, \T_CLOSURE ); + + // If so, we check only within the closure. + if ( false !== $closure ) { + $scope_start = $this->tokens[ $closure ]['scope_opener']; + } + } + + $scope_end = $stackPtr; + } + + if ( ! empty( $array_keys ) && ! is_array( $array_keys ) ) { + $array_keys = (array) $array_keys; + } + + $bare_array_keys = array_map( array( $this, 'strip_quotes' ), $array_keys ); + $targets = array( + \T_ISSET => 'construct', + \T_EMPTY => 'construct', + \T_UNSET => 'construct', + \T_STRING => 'function_call', + \T_COALESCE => 'coalesce', + \T_COALESCE_EQUAL => 'coalesce', + ); + + // phpcs:ignore Generic.CodeAnalysis.JumbledIncrementer.Found -- On purpose, see below. + for ( $i = ( $scope_start + 1 ); $i < $scope_end; $i++ ) { + + if ( isset( $targets[ $this->tokens[ $i ]['code'] ] ) === false ) { + continue; + } + + switch ( $targets[ $this->tokens[ $i ]['code'] ] ) { + case 'construct': + $issetOpener = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $i + 1 ), null, true, null, true ); + if ( false === $issetOpener || \T_OPEN_PARENTHESIS !== $this->tokens[ $issetOpener ]['code'] ) { + // Parse error or live coding. + continue 2; + } + + $issetCloser = $this->tokens[ $issetOpener ]['parenthesis_closer']; + + // Look for this variable. We purposely stomp $i from the parent loop. + for ( $i = ( $issetOpener + 1 ); $i < $issetCloser; $i++ ) { + + if ( \T_VARIABLE !== $this->tokens[ $i ]['code'] ) { + continue; + } + + if ( $this->tokens[ $stackPtr ]['content'] !== $this->tokens[ $i ]['content'] ) { + continue; + } + + // If we're checking for specific array keys (ex: 'hello' in + // $_POST['hello']), that must match too. Quote-style, however, doesn't matter. + if ( ! empty( $bare_array_keys ) ) { + $found_keys = $this->get_array_access_keys( $i ); + $found_keys = array_map( array( $this, 'strip_quotes' ), $found_keys ); + $diff = array_diff_assoc( $bare_array_keys, $found_keys ); + if ( ! empty( $diff ) ) { + continue; + } + } + + return true; + } + + break; + + case 'function_call': + // Only check calls to array_key_exists() and key_exists(). + if ( 'array_key_exists' !== $this->tokens[ $i ]['content'] + && 'key_exists' !== $this->tokens[ $i ]['content'] + ) { + continue 2; + } + + $next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $i + 1 ), null, true, null, true ); + if ( false === $next_non_empty || \T_OPEN_PARENTHESIS !== $this->tokens[ $next_non_empty ]['code'] ) { + // Not a function call. + continue 2; + } + + if ( $this->is_class_object_call( $i ) === true ) { + // Method call. + continue 2; + } + + if ( $this->is_token_namespaced( $i ) === true ) { + // Namespaced function call. + continue 2; + } + + $params = $this->get_function_call_parameters( $i ); + if ( count( $params ) < 2 ) { + continue 2; + } + + $param2_first_token = $this->phpcsFile->findNext( Tokens::$emptyTokens, $params[2]['start'], ( $params[2]['end'] + 1 ), true ); + if ( false === $param2_first_token + || \T_VARIABLE !== $this->tokens[ $param2_first_token ]['code'] + || $this->tokens[ $param2_first_token ]['content'] !== $this->tokens[ $stackPtr ]['content'] + ) { + continue 2; + } + + if ( ! empty( $bare_array_keys ) ) { + // Prevent the original array from being altered. + $bare_keys = $bare_array_keys; + $last_key = array_pop( $bare_keys ); + + /* + * For multi-level array access, the complete set of keys could be split between + * the first and the second parameter, but could also be completely in the second + * parameter, so we need to check both options. + */ + + $found_keys = $this->get_array_access_keys( $param2_first_token ); + $found_keys = array_map( array( $this, 'strip_quotes' ), $found_keys ); + + // First try matching the complete set against the second parameter. + $diff = array_diff_assoc( $bare_array_keys, $found_keys ); + if ( empty( $diff ) ) { + return true; + } + + // If that failed, try getting an exact match for the subset against the + // second parameter and the last key against the first. + if ( $bare_keys === $found_keys && $this->strip_quotes( $params[1]['raw'] ) === $last_key ) { + return true; + } + + // Didn't find the correct array keys. + continue 2; + } + + return true; + + case 'coalesce': + $prev = $i; + do { + $prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $prev - 1 ), null, true, null, true ); + // Skip over array keys, like $_GET['key']['subkey']. + if ( \T_CLOSE_SQUARE_BRACKET === $this->tokens[ $prev ]['code'] ) { + $prev = $this->tokens[ $prev ]['bracket_opener']; + continue; + } + + break; + } while ( $prev >= ( $scope_start + 1 ) ); + + // We should now have reached the variable. + if ( \T_VARIABLE !== $this->tokens[ $prev ]['code'] ) { + continue 2; + } + + if ( $this->tokens[ $prev ]['content'] !== $this->tokens[ $stackPtr ]['content'] ) { + continue 2; + } + + if ( ! empty( $bare_array_keys ) ) { + $found_keys = $this->get_array_access_keys( $prev ); + $found_keys = array_map( array( $this, 'strip_quotes' ), $found_keys ); + $diff = array_diff_assoc( $bare_array_keys, $found_keys ); + if ( ! empty( $diff ) ) { + continue 2; + } + } + + // Right variable, correct key. + return true; + } + } + + return false; + } + + /** + * Check whether a variable is being compared to another value. + * + * E.g., $var === 'foo', 1 <= $var, etc. + * + * Also recognizes `switch ( $var )`. + * + * @since 0.5.0 + * @since 2.1.0 Added the $include_coalesce parameter. + * + * @param int $stackPtr The index of this token in the stack. + * @param bool $include_coalesce Optional. Whether or not to regard the null + * coalesce operator - ?? - as a comparison operator. + * Defaults to true. + * Null coalesce is a special comparison operator in this + * sense as it doesn't compare a variable to whatever is + * on the other side of the comparison operator. + * + * @return bool Whether this is a comparison. + */ + protected function is_comparison( $stackPtr, $include_coalesce = true ) { + + $comparisonTokens = Tokens::$comparisonTokens; + if ( false === $include_coalesce ) { + unset( $comparisonTokens[ \T_COALESCE ] ); + } + + // We first check if this is a switch statement (switch ( $var )). + if ( isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + $nested_parenthesis = $this->tokens[ $stackPtr ]['nested_parenthesis']; + $close_parenthesis = end( $nested_parenthesis ); + + if ( + isset( $this->tokens[ $close_parenthesis ]['parenthesis_owner'] ) + && \T_SWITCH === $this->tokens[ $this->tokens[ $close_parenthesis ]['parenthesis_owner'] ]['code'] + ) { + return true; + } + } + + // Find the previous non-empty token. We check before the var first because + // yoda conditions are usually expected. + $previous_token = $this->phpcsFile->findPrevious( + Tokens::$emptyTokens, + ( $stackPtr - 1 ), + null, + true + ); + + if ( isset( $comparisonTokens[ $this->tokens[ $previous_token ]['code'] ] ) ) { + return true; + } + + // Maybe the comparison operator is after this. + $next_token = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $stackPtr + 1 ), + null, + true + ); + + // This might be an opening square bracket in the case of arrays ($var['a']). + while ( false !== $next_token && \T_OPEN_SQUARE_BRACKET === $this->tokens[ $next_token ]['code'] ) { + + $next_token = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $this->tokens[ $next_token ]['bracket_closer'] + 1 ), + null, + true + ); + } + + if ( false !== $next_token && isset( $comparisonTokens[ $this->tokens[ $next_token ]['code'] ] ) ) { + return true; + } + + return false; + } + + /** + * Check if a token is inside of an array-value comparison function. + * + * @since 2.1.0 + * + * @param int $stackPtr The index of the token in the stack. + * + * @return bool Whether the token is (part of) a parameter to an + * array-value comparison function. + */ + protected function is_in_array_comparison( $stackPtr ) { + $function_ptr = $this->is_in_function_call( $stackPtr, $this->arrayCompareFunctions, true, true ); + if ( false === $function_ptr ) { + return false; + } + + $function_name = $this->tokens[ $function_ptr ]['content']; + if ( true === $this->arrayCompareFunctions[ $function_name ] ) { + return true; + } + + if ( $this->get_function_call_parameter_count( $function_ptr ) >= $this->arrayCompareFunctions[ $function_name ] ) { + return true; + } + + return false; + } + + /** + * Check what type of 'use' statement a token is part of. + * + * The T_USE token has multiple different uses: + * + * 1. In a closure: function () use ( $var ) {} + * 2. In a class, to import a trait: use Trait_Name + * 3. In a namespace, to import a class: use Some\Class; + * + * This function will check the token and return 'closure', 'trait', or 'class', + * based on which of these uses the use is being used for. + * + * @since 0.7.0 + * + * @param int $stackPtr The position of the token to check. + * + * @return string The type of use. + */ + protected function get_use_type( $stackPtr ) { + + // USE keywords inside closures. + $next = $this->phpcsFile->findNext( \T_WHITESPACE, ( $stackPtr + 1 ), null, true ); + + if ( \T_OPEN_PARENTHESIS === $this->tokens[ $next ]['code'] ) { + return 'closure'; + } + + // USE keywords for traits. + $valid_scopes = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_TRAIT' => true, + ); + if ( false !== $this->valid_direct_scope( $stackPtr, $valid_scopes ) ) { + return 'trait'; + } + + // USE keywords for classes to import to a namespace. + return 'class'; + } + + /** + * Get the interpolated variable names from a string. + * + * Check if '$' is followed by a valid variable name, and that it is not preceded by an escape sequence. + * + * @since 0.9.0 + * + * @param string $string The contents of a T_DOUBLE_QUOTED_STRING or T_HEREDOC token. + * + * @return array Variable names (without '$' sigil). + */ + protected function get_interpolated_variables( $string ) { + $variables = array(); + if ( preg_match_all( '/(?P\\\\*)\$(?P\w+)/', $string, $match_sets, \PREG_SET_ORDER ) ) { + foreach ( $match_sets as $matches ) { + if ( ! isset( $matches['backslashes'] ) || ( \strlen( $matches['backslashes'] ) % 2 ) === 0 ) { + $variables[] = $matches['symbol']; + } + } + } + return $variables; + } + + /** + * Strip variables from an arbitrary double quoted/heredoc string. + * + * Intended for use with the contents of a T_DOUBLE_QUOTED_STRING or T_HEREDOC token. + * + * @since 0.14.0 + * + * @param string $string The raw string. + * + * @return string String without variables in it. + */ + public function strip_interpolated_variables( $string ) { + if ( strpos( $string, '$' ) === false ) { + return $string; + } + + return preg_replace( self::REGEX_COMPLEX_VARS, '', $string ); + } + + /** + * Checks if a function call has parameters. + * + * Expects to be passed the T_STRING stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Extra feature: If passed an T_ARRAY or T_OPEN_SHORT_ARRAY stack pointer, it + * will detect whether the array has values or is empty. + * + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/120 + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/152 + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the function call token. + * + * @return bool + */ + public function does_function_call_have_parameters( $stackPtr ) { + + // Check for the existence of the token. + if ( false === isset( $this->tokens[ $stackPtr ] ) ) { + return false; + } + + // Is this one of the tokens this function handles ? + if ( false === \in_array( $this->tokens[ $stackPtr ]['code'], array( \T_STRING, \T_ARRAY, \T_OPEN_SHORT_ARRAY ), true ) ) { + return false; + } + + $next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true, null, true ); + + // Deal with short array syntax. + if ( 'T_OPEN_SHORT_ARRAY' === $this->tokens[ $stackPtr ]['type'] ) { + if ( false === isset( $this->tokens[ $stackPtr ]['bracket_closer'] ) ) { + return false; + } + + if ( $next_non_empty === $this->tokens[ $stackPtr ]['bracket_closer'] ) { + // No parameters. + return false; + } else { + return true; + } + } + + // Deal with function calls & long arrays. + // Next non-empty token should be the open parenthesis. + if ( false === $next_non_empty && \T_OPEN_PARENTHESIS !== $this->tokens[ $next_non_empty ]['code'] ) { + return false; + } + + if ( false === isset( $this->tokens[ $next_non_empty ]['parenthesis_closer'] ) ) { + return false; + } + + $close_parenthesis = $this->tokens[ $next_non_empty ]['parenthesis_closer']; + $next_next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $next_non_empty + 1 ), ( $close_parenthesis + 1 ), true ); + + if ( $next_next_non_empty === $close_parenthesis ) { + // No parameters. + return false; + } + + return true; + } + + /** + * Count the number of parameters a function call has been passed. + * + * Expects to be passed the T_STRING stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Extra feature: If passed an T_ARRAY or T_OPEN_SHORT_ARRAY stack pointer, + * it will return the number of values in the array. + * + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/111 + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/114 + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/151 + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the function call token. + * + * @return int + */ + public function get_function_call_parameter_count( $stackPtr ) { + if ( false === $this->does_function_call_have_parameters( $stackPtr ) ) { + return 0; + } + + return \count( $this->get_function_call_parameters( $stackPtr ) ); + } + + /** + * Get information on all parameters passed to a function call. + * + * Expects to be passed the T_STRING stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Extra feature: If passed an T_ARRAY or T_OPEN_SHORT_ARRAY stack pointer, + * it will tokenize the values / key/value pairs contained in the array call. + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the function call token. + * + * @return array Multi-dimentional array with parameter details or + * empty array if no parameters are found. + * + * @type int $position 1-based index position of the parameter. { + * @type int $start Stack pointer for the start of the parameter. + * @type int $end Stack pointer for the end of parameter. + * @type int $raw Trimmed raw parameter content. + * } + */ + public function get_function_call_parameters( $stackPtr ) { + if ( false === $this->does_function_call_have_parameters( $stackPtr ) ) { + return array(); + } + + /* + * Ok, we know we have a T_STRING, T_ARRAY or T_OPEN_SHORT_ARRAY with parameters + * and valid open & close brackets/parenthesis. + */ + + // Mark the beginning and end tokens. + if ( 'T_OPEN_SHORT_ARRAY' === $this->tokens[ $stackPtr ]['type'] ) { + $opener = $stackPtr; + $closer = $this->tokens[ $stackPtr ]['bracket_closer']; + + $nestedParenthesisCount = 0; + } else { + $opener = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true, null, true ); + $closer = $this->tokens[ $opener ]['parenthesis_closer']; + + $nestedParenthesisCount = 1; + } + + // Which nesting level is the one we are interested in ? + if ( isset( $this->tokens[ $opener ]['nested_parenthesis'] ) ) { + $nestedParenthesisCount += \count( $this->tokens[ $opener ]['nested_parenthesis'] ); + } + + $parameters = array(); + $next_comma = $opener; + $param_start = ( $opener + 1 ); + $cnt = 1; + while ( $next_comma = $this->phpcsFile->findNext( array( \T_COMMA, $this->tokens[ $closer ]['code'], \T_OPEN_SHORT_ARRAY, \T_CLOSURE ), ( $next_comma + 1 ), ( $closer + 1 ) ) ) { + // Ignore anything within short array definition brackets. + if ( 'T_OPEN_SHORT_ARRAY' === $this->tokens[ $next_comma ]['type'] + && ( isset( $this->tokens[ $next_comma ]['bracket_opener'] ) + && $this->tokens[ $next_comma ]['bracket_opener'] === $next_comma ) + && isset( $this->tokens[ $next_comma ]['bracket_closer'] ) + ) { + // Skip forward to the end of the short array definition. + $next_comma = $this->tokens[ $next_comma ]['bracket_closer']; + continue; + } + + // Skip past closures passed as function parameters. + if ( 'T_CLOSURE' === $this->tokens[ $next_comma ]['type'] + && ( isset( $this->tokens[ $next_comma ]['scope_condition'] ) + && $this->tokens[ $next_comma ]['scope_condition'] === $next_comma ) + && isset( $this->tokens[ $next_comma ]['scope_closer'] ) + ) { + // Skip forward to the end of the closure declaration. + $next_comma = $this->tokens[ $next_comma ]['scope_closer']; + continue; + } + + // Ignore comma's at a lower nesting level. + if ( \T_COMMA === $this->tokens[ $next_comma ]['code'] + && isset( $this->tokens[ $next_comma ]['nested_parenthesis'] ) + && \count( $this->tokens[ $next_comma ]['nested_parenthesis'] ) !== $nestedParenthesisCount + ) { + continue; + } + + // Ignore closing parenthesis/bracket if not 'ours'. + if ( $this->tokens[ $next_comma ]['type'] === $this->tokens[ $closer ]['type'] && $next_comma !== $closer ) { + continue; + } + + // Ok, we've reached the end of the parameter. + $parameters[ $cnt ]['start'] = $param_start; + $parameters[ $cnt ]['end'] = ( $next_comma - 1 ); + $parameters[ $cnt ]['raw'] = trim( $this->phpcsFile->getTokensAsString( $param_start, ( $next_comma - $param_start ) ) ); + + /* + * Check if there are more tokens before the closing parenthesis. + * Prevents code like the following from setting a third parameter: + * functionCall( $param1, $param2, ); + */ + $has_next_param = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $next_comma + 1 ), $closer, true, null, true ); + if ( false === $has_next_param ) { + break; + } + + // Prepare for the next parameter. + $param_start = ( $next_comma + 1 ); + $cnt++; + } + + return $parameters; + } + + /** + * Get information on a specific parameter passed to a function call. + * + * Expects to be passed the T_STRING stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Will return a array with the start token pointer, end token pointer and the raw value + * of the parameter at a specific offset. + * If the specified parameter is not found, will return false. + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the function call token. + * @param int $param_offset The 1-based index position of the parameter to retrieve. + * + * @return array|false + */ + public function get_function_call_parameter( $stackPtr, $param_offset ) { + $parameters = $this->get_function_call_parameters( $stackPtr ); + + if ( false === isset( $parameters[ $param_offset ] ) ) { + return false; + } + + return $parameters[ $param_offset ]; + } + + /** + * Find the array opener & closer based on a T_ARRAY or T_OPEN_SHORT_ARRAY token. + * + * @since 0.12.0 + * + * @param int $stackPtr The stack pointer to the array token. + * + * @return array|bool Array with two keys `opener`, `closer` or false if + * either or these could not be determined. + */ + protected function find_array_open_close( $stackPtr ) { + /* + * Determine the array opener & closer. + */ + if ( \T_ARRAY === $this->tokens[ $stackPtr ]['code'] ) { + if ( isset( $this->tokens[ $stackPtr ]['parenthesis_opener'] ) ) { + $opener = $this->tokens[ $stackPtr ]['parenthesis_opener']; + + if ( isset( $this->tokens[ $opener ]['parenthesis_closer'] ) ) { + $closer = $this->tokens[ $opener ]['parenthesis_closer']; + } + } + } else { + // Short array syntax. + $opener = $stackPtr; + $closer = $this->tokens[ $stackPtr ]['bracket_closer']; + } + + if ( isset( $opener, $closer ) ) { + return array( + 'opener' => $opener, + 'closer' => $closer, + ); + } + + return false; + } + + /** + * Find the list opener & closer based on a T_LIST or T_OPEN_SHORT_ARRAY token. + * + * @since 2.2.0 + * + * @param int $stackPtr The stack pointer to the array token. + * + * @return array|bool Array with two keys `opener`, `closer` or false if + * not a (short) list token or if either or these + * could not be determined. + */ + protected function find_list_open_close( $stackPtr ) { + /* + * Determine the list opener & closer. + */ + if ( \T_LIST === $this->tokens[ $stackPtr ]['code'] ) { + // PHPCS 3.5.0. + if ( isset( $this->tokens[ $stackPtr ]['parenthesis_opener'] ) ) { + $opener = $this->tokens[ $stackPtr ]['parenthesis_opener']; + + } else { + // PHPCS < 3.5.0. + $next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + if ( false !== $next_non_empty + && \T_OPEN_PARENTHESIS === $this->tokens[ $next_non_empty ]['code'] + ) { + $opener = $next_non_empty; + } + } + + if ( isset( $opener, $this->tokens[ $opener ]['parenthesis_closer'] ) ) { + $closer = $this->tokens[ $opener ]['parenthesis_closer']; + } + } + + if ( \T_OPEN_SHORT_ARRAY === $this->tokens[ $stackPtr ]['code'] + && $this->is_short_list( $stackPtr ) === true + ) { + $opener = $stackPtr; + $closer = $this->tokens[ $stackPtr ]['bracket_closer']; + } + + if ( isset( $opener, $closer ) ) { + return array( + 'opener' => $opener, + 'closer' => $closer, + ); + } + + return false; + } + + /** + * Determine the namespace name an arbitrary token lives in. + * + * @since 0.10.0 + * @since 0.12.0 Moved from the `AbstractClassRestrictionsSniff` to this class. + * + * @param int $stackPtr The token position for which to determine the namespace. + * + * @return string Namespace name or empty string if it couldn't be determined or no namespace applies. + */ + public function determine_namespace( $stackPtr ) { + + // Check for the existence of the token. + if ( ! isset( $this->tokens[ $stackPtr ] ) ) { + return ''; + } + + // Check for scoped namespace {}. + if ( ! empty( $this->tokens[ $stackPtr ]['conditions'] ) ) { + $namespacePtr = $this->phpcsFile->getCondition( $stackPtr, \T_NAMESPACE ); + if ( false !== $namespacePtr ) { + $namespace = $this->get_declared_namespace_name( $namespacePtr ); + if ( false !== $namespace ) { + return $namespace; + } + + // We are in a scoped namespace, but couldn't determine the name. + // Searching for a global namespace is futile. + return ''; + } + } + + /* + * Not in a scoped namespace, so let's see if we can find a non-scoped namespace instead. + * Keeping in mind that: + * - there can be multiple non-scoped namespaces in a file (bad practice, but it happens). + * - the namespace keyword can also be used as part of a function/method call and such. + * - that a non-named namespace resolves to the global namespace. + */ + $previousNSToken = $stackPtr; + $namespace = false; + do { + $previousNSToken = $this->phpcsFile->findPrevious( \T_NAMESPACE, ( $previousNSToken - 1 ) ); + + // Stop if we encounter a scoped namespace declaration as we already know we're not in one. + if ( ! empty( $this->tokens[ $previousNSToken ]['scope_condition'] ) + && $this->tokens[ $previousNSToken ]['scope_condition'] === $previousNSToken + ) { + break; + } + + $namespace = $this->get_declared_namespace_name( $previousNSToken ); + + } while ( false === $namespace && false !== $previousNSToken ); + + // If we still haven't got a namespace, return an empty string. + if ( false === $namespace ) { + return ''; + } + + return $namespace; + } + + /** + * Get the complete namespace name for a namespace declaration. + * + * For hierarchical namespaces, the name will be composed of several tokens, + * i.e. MyProject\Sub\Level which will be returned together as one string. + * + * @since 0.12.0 A lesser variant of this method previously existed in the + * `AbstractClassRestrictionsSniff` class. + * + * @param int|bool $stackPtr The position of a T_NAMESPACE token. + * + * @return string|false Namespace name or false if not a namespace declaration. + * Namespace name can be an empty string for global namespace declaration. + */ + public function get_declared_namespace_name( $stackPtr ) { + + // Check for the existence of the token. + if ( false === $stackPtr || ! isset( $this->tokens[ $stackPtr ] ) ) { + return false; + } + + if ( \T_NAMESPACE !== $this->tokens[ $stackPtr ]['code'] ) { + return false; + } + + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true, null, true ); + if ( \T_NS_SEPARATOR === $this->tokens[ $nextToken ]['code'] ) { + // Not a namespace declaration, but use of, i.e. `namespace\someFunction();`. + return false; + } + + if ( \T_OPEN_CURLY_BRACKET === $this->tokens[ $nextToken ]['code'] ) { + // Declaration for global namespace when using multiple namespaces in a file. + // I.e.: `namespace {}`. + return ''; + } + + // Ok, this should be a namespace declaration, so get all the parts together. + $acceptedTokens = array( + \T_STRING => true, + \T_NS_SEPARATOR => true, + ); + $validTokens = $acceptedTokens + Tokens::$emptyTokens; + + $namespaceName = ''; + while ( isset( $validTokens[ $this->tokens[ $nextToken ]['code'] ] ) ) { + if ( isset( $acceptedTokens[ $this->tokens[ $nextToken ]['code'] ] ) ) { + $namespaceName .= trim( $this->tokens[ $nextToken ]['content'] ); + } + ++$nextToken; + } + + return $namespaceName; + } + + /** + * Check whether a T_CONST token is a class constant declaration. + * + * @since 0.14.0 + * + * @param int $stackPtr The position in the stack of the T_CONST token to verify. + * + * @return bool + */ + public function is_class_constant( $stackPtr ) { + if ( ! isset( $this->tokens[ $stackPtr ] ) || \T_CONST !== $this->tokens[ $stackPtr ]['code'] ) { + return false; + } + + // Note: traits can not declare constants. + $valid_scopes = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_INTERFACE' => true, + ); + + return is_int( $this->valid_direct_scope( $stackPtr, $valid_scopes ) ); + } + + /** + * Check whether a T_VARIABLE token is a class property declaration. + * + * @since 0.14.0 + * + * @param int $stackPtr The position in the stack of the T_VARIABLE token to verify. + * + * @return bool + */ + public function is_class_property( $stackPtr ) { + if ( ! isset( $this->tokens[ $stackPtr ] ) || \T_VARIABLE !== $this->tokens[ $stackPtr ]['code'] ) { + return false; + } + + // Note: interfaces can not declare properties. + $valid_scopes = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_TRAIT' => true, + ); + + $scopePtr = $this->valid_direct_scope( $stackPtr, $valid_scopes ); + if ( false !== $scopePtr ) { + // Make sure it's not a method parameter. + if ( empty( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + return true; + } else { + $parenthesis = array_keys( $this->tokens[ $stackPtr ]['nested_parenthesis'] ); + $deepest_open = array_pop( $parenthesis ); + if ( $deepest_open < $scopePtr + || isset( $this->tokens[ $deepest_open ]['parenthesis_owner'] ) === false + || \T_FUNCTION !== $this->tokens[ $this->tokens[ $deepest_open ]['parenthesis_owner'] ]['code'] + ) { + return true; + } + } + } + + return false; + } + + /** + * Check whether the direct wrapping scope of a token is within a limited set of + * acceptable tokens. + * + * Used to check, for instance, if a T_CONST is a class constant. + * + * @since 0.14.0 + * + * @param int $stackPtr The position in the stack of the token to verify. + * @param array $valid_scopes Array of token types. + * Keys should be the token types in string format + * to allow for newer token types. + * Value is irrelevant. + * + * @return int|bool StackPtr to the scope if valid, false otherwise. + */ + protected function valid_direct_scope( $stackPtr, array $valid_scopes ) { + if ( empty( $this->tokens[ $stackPtr ]['conditions'] ) ) { + return false; + } + + /* + * Check only the direct wrapping scope of the token. + */ + $conditions = array_keys( $this->tokens[ $stackPtr ]['conditions'] ); + $ptr = array_pop( $conditions ); + + if ( ! isset( $this->tokens[ $ptr ] ) ) { + return false; + } + + if ( isset( $valid_scopes[ $this->tokens[ $ptr ]['type'] ] ) ) { + return $ptr; + } + + return false; + } + + /** + * Checks whether this is a call to a $wpdb method that we want to sniff. + * + * If available in the child class, the $methodPtr, $i and $end properties are + * automatically set to correspond to the start and end of the method call. + * The $i property is also set if this is not a method call but rather the + * use of a $wpdb property. + * + * @since 0.8.0 + * @since 0.9.0 The return value is now always boolean. The $end and $i member + * vars are automatically updated. + * @since 0.14.0 Moved this method from the `PreparedSQL` sniff to the base WP sniff. + * + * {@internal This method should probably be refactored.}} + * + * @param int $stackPtr The index of the $wpdb variable. + * @param array $target_methods Array of methods. Key(s) should be method name. + * + * @return bool Whether this is a $wpdb method call. + */ + protected function is_wpdb_method_call( $stackPtr, $target_methods ) { + + // Check for wpdb. + if ( ( \T_VARIABLE === $this->tokens[ $stackPtr ]['code'] && '$wpdb' !== $this->tokens[ $stackPtr ]['content'] ) + || ( \T_STRING === $this->tokens[ $stackPtr ]['code'] && 'wpdb' !== $this->tokens[ $stackPtr ]['content'] ) + ) { + return false; + } + + // Check that this is a method call. + $is_object_call = $this->phpcsFile->findNext( + array( \T_OBJECT_OPERATOR, \T_DOUBLE_COLON ), + ( $stackPtr + 1 ), + null, + false, + null, + true + ); + if ( false === $is_object_call ) { + return false; + } + + $methodPtr = $this->phpcsFile->findNext( \T_WHITESPACE, ( $is_object_call + 1 ), null, true, null, true ); + if ( false === $methodPtr ) { + return false; + } + + if ( \T_STRING === $this->tokens[ $methodPtr ]['code'] && property_exists( $this, 'methodPtr' ) ) { + $this->methodPtr = $methodPtr; + } + + // Find the opening parenthesis. + $opening_paren = $this->phpcsFile->findNext( \T_WHITESPACE, ( $methodPtr + 1 ), null, true, null, true ); + + if ( false === $opening_paren ) { + return false; + } + + if ( property_exists( $this, 'i' ) ) { + $this->i = $opening_paren; + } + + if ( \T_OPEN_PARENTHESIS !== $this->tokens[ $opening_paren ]['code'] + || ! isset( $this->tokens[ $opening_paren ]['parenthesis_closer'] ) + ) { + return false; + } + + // Check that this is one of the methods that we are interested in. + if ( ! isset( $target_methods[ $this->tokens[ $methodPtr ]['content'] ] ) ) { + return false; + } + + // Find the end of the first parameter. + $end = $this->phpcsFile->findEndOfStatement( $opening_paren + 1 ); + + if ( \T_COMMA !== $this->tokens[ $end ]['code'] ) { + ++$end; + } + + if ( property_exists( $this, 'end' ) ) { + $this->end = $end; + } + + return true; + } + + /** + * Determine whether an arbitrary T_STRING token is the use of a global constant. + * + * @since 1.0.0 + * + * @param int $stackPtr The position of the function call token. + * + * @return bool + */ + public function is_use_of_global_constant( $stackPtr ) { + // Check for the existence of the token. + if ( ! isset( $this->tokens[ $stackPtr ] ) ) { + return false; + } + + // Is this one of the tokens this function handles ? + if ( \T_STRING !== $this->tokens[ $stackPtr ]['code'] ) { + return false; + } + + $next = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + if ( false !== $next + && ( \T_OPEN_PARENTHESIS === $this->tokens[ $next ]['code'] + || \T_DOUBLE_COLON === $this->tokens[ $next ]['code'] ) + ) { + // Function call or declaration. + return false; + } + + // Array of tokens which if found preceding the $stackPtr indicate that a T_STRING is not a global constant. + $tokens_to_ignore = array( + 'T_NAMESPACE' => true, + 'T_USE' => true, + 'T_CLASS' => true, + 'T_TRAIT' => true, + 'T_INTERFACE' => true, + 'T_EXTENDS' => true, + 'T_IMPLEMENTS' => true, + 'T_NEW' => true, + 'T_FUNCTION' => true, + 'T_DOUBLE_COLON' => true, + 'T_OBJECT_OPERATOR' => true, + 'T_INSTANCEOF' => true, + 'T_INSTEADOF' => true, + 'T_GOTO' => true, + 'T_AS' => true, + 'T_PUBLIC' => true, + 'T_PROTECTED' => true, + 'T_PRIVATE' => true, + ); + + $prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true ); + if ( false !== $prev + && isset( $tokens_to_ignore[ $this->tokens[ $prev ]['type'] ] ) + ) { + // Not the use of a constant. + return false; + } + + if ( $this->is_token_namespaced( $stackPtr ) === true ) { + // Namespaced constant of the same name. + return false; + } + + if ( false !== $prev + && \T_CONST === $this->tokens[ $prev ]['code'] + && $this->is_class_constant( $prev ) + ) { + // Class constant declaration of the same name. + return false; + } + + /* + * Deal with a number of variations of use statements. + */ + for ( $i = $stackPtr; $i > 0; $i-- ) { + if ( $this->tokens[ $i ]['line'] !== $this->tokens[ $stackPtr ]['line'] ) { + break; + } + } + + $firstOnLine = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $i + 1 ), null, true ); + if ( false !== $firstOnLine && \T_USE === $this->tokens[ $firstOnLine ]['code'] ) { + $nextOnLine = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $firstOnLine + 1 ), null, true ); + if ( false !== $nextOnLine ) { + if ( \T_STRING === $this->tokens[ $nextOnLine ]['code'] + && 'const' === $this->tokens[ $nextOnLine ]['content'] + ) { + $hasNsSep = $this->phpcsFile->findNext( \T_NS_SEPARATOR, ( $nextOnLine + 1 ), $stackPtr ); + if ( false !== $hasNsSep ) { + // Namespaced const (group) use statement. + return false; + } + } else { + // Not a const use statement. + return false; + } + } + } + + return true; + } + + /** + * Determine if a variable is in the `as $key => $value` part of a foreach condition. + * + * @since 1.0.0 + * @since 1.1.0 Moved from the PrefixAllGlobals sniff to the Sniff base class. + * + * @param int $stackPtr Pointer to the variable. + * + * @return bool True if it is. False otherwise. + */ + protected function is_foreach_as( $stackPtr ) { + if ( ! isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + return false; + } + + $nested_parenthesis = $this->tokens[ $stackPtr ]['nested_parenthesis']; + $close_parenthesis = end( $nested_parenthesis ); + $open_parenthesis = key( $nested_parenthesis ); + if ( ! isset( $this->tokens[ $close_parenthesis ]['parenthesis_owner'] ) ) { + return false; + } + + if ( \T_FOREACH !== $this->tokens[ $this->tokens[ $close_parenthesis ]['parenthesis_owner'] ]['code'] ) { + return false; + } + + $as_ptr = $this->phpcsFile->findNext( \T_AS, ( $open_parenthesis + 1 ), $close_parenthesis ); + if ( false === $as_ptr ) { + // Should never happen. + return false; + } + + return ( $stackPtr > $as_ptr ); + } + + /** + * Determine whether a T_OPEN/CLOSE_SHORT_ARRAY token is a short list() construct. + * + * @internal This function will be introduced in PHPCS upstream in version 3.5.0 + * and can be removed from WPCS once WPCS raises the minimum version. + * + * @since 2.2.0 + * + * @param int $stackPtr The position of the array bracket token. + * + * @return bool True if the token passed is the open/close bracket of a short list. + * False if the token is a short array bracket or not + * a T_OPEN/CLOSE_SHORT_ARRAY token. + */ + protected function is_short_list( $stackPtr ) { + // Is this one of the tokens this function handles ? + if ( \T_OPEN_SHORT_ARRAY !== $this->tokens[ $stackPtr ]['code'] + && \T_CLOSE_SHORT_ARRAY !== $this->tokens[ $stackPtr ]['code'] + ) { + return false; + } + + switch ( $this->tokens[ $stackPtr ]['code'] ) { + case \T_OPEN_SHORT_ARRAY: + $opener = $stackPtr; + $closer = $this->tokens[ $stackPtr ]['bracket_closer']; + break; + + case \T_CLOSE_SHORT_ARRAY: + $opener = $this->tokens[ $stackPtr ]['bracket_opener']; + $closer = $stackPtr; + break; + } + + $nextNonEmpty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $closer + 1 ), null, true, null, true ); + if ( false !== $nextNonEmpty && \T_EQUAL === $this->tokens[ $nextNonEmpty ]['code'] ) { + return true; + } + + // Check for short list in foreach, i.e. `foreach($array as [$a, $b])`. + if ( $this->is_foreach_as( $stackPtr ) === true ) { + return true; + } + + // Maybe this is a short list syntax nested inside another short list syntax ? + $parentOpen = $opener; + do { + $parentOpen = $this->phpcsFile->findPrevious( + \T_OPEN_SHORT_ARRAY, + ( $parentOpen - 1 ), + null, + false, + null, + true + ); + + if ( false === $parentOpen ) { + return false; + } + } while ( $this->tokens[ $parentOpen ]['bracket_closer'] < $opener ); + + return $this->is_short_list( $parentOpen ); + } + + /** + * Get a list of the token pointers to the variables being assigned to in a list statement. + * + * @internal No need to take special measures for nested lists. Nested or not, + * each list part can only contain one variable being written to. + * + * @since 2.2.0 + * + * @param int $stackPtr The position of the T_LIST or T_OPEN_SHORT_ARRAY + * token in the stack. + * @param array $list_open_close Optional. Array containing the token pointers to + * the list opener and closer. + * + * @return array Array with the stack pointers to the variables or an empty + * array when not a (short) list. + */ + protected function get_list_variables( $stackPtr, $list_open_close = array() ) { + if ( \T_LIST !== $this->tokens[ $stackPtr ]['code'] + && \T_OPEN_SHORT_ARRAY !== $this->tokens[ $stackPtr ]['code'] + ) { + return array(); + } + + if ( empty( $list_open_close ) ) { + $list_open_close = $this->find_list_open_close( $stackPtr ); + if ( false === $list_open_close ) { + // Not a (short) list. + return array(); + } + } + + $var_pointers = array(); + $current = $list_open_close['opener']; + $closer = $list_open_close['closer']; + $last = false; + do { + ++$current; + $next_comma = $this->phpcsFile->findNext( \T_COMMA, $current, $closer ); + if ( false === $next_comma ) { + $next_comma = $closer; + $last = true; + } + + // Skip over the "key" part in keyed lists. + $arrow = $this->phpcsFile->findNext( \T_DOUBLE_ARROW, $current, $next_comma ); + if ( false !== $arrow ) { + $current = ( $arrow + 1 ); + } + + /* + * Each list item can only have one variable to which an assignment is being made. + * This can be an array with a (variable) index, but that doesn't matter, we're only + * concerned with the actual variable. + */ + $var = $this->phpcsFile->findNext( \T_VARIABLE, $current, $next_comma ); + if ( false !== $var ) { + // Not an empty list item. + $var_pointers[] = $var; + } + + $current = $next_comma; + + } while ( false === $last ); + + return $var_pointers; + } + + /** + * Check whether a function has been marked as deprecated via a @deprecated tag + * in the function docblock. + * + * {@internal This method is static to allow the ValidFunctionName class to use it.}} + * + * @since 2.2.0 + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of a T_FUNCTION + * token in the stack. + * + * @return bool + */ + public static function is_function_deprecated( File $phpcsFile, $stackPtr ) { + $tokens = $phpcsFile->getTokens(); + $find = Tokens::$methodPrefixes; + $find[] = \T_WHITESPACE; + + $comment_end = $phpcsFile->findPrevious( $find, ( $stackPtr - 1 ), null, true ); + if ( \T_DOC_COMMENT_CLOSE_TAG !== $tokens[ $comment_end ]['code'] ) { + // Function doesn't have a doc comment or is using the wrong type of comment. + return false; + } + + $comment_start = $tokens[ $comment_end ]['comment_opener']; + foreach ( $tokens[ $comment_start ]['comment_tags'] as $tag ) { + if ( '@deprecated' === $tokens[ $tag ]['content'] ) { + return true; + } + } + + return false; + } +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayDeclarationSpacingSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayDeclarationSpacingSniff.php new file mode 100644 index 00000000..5488bfd3 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayDeclarationSpacingSniff.php @@ -0,0 +1,468 @@ + \T_ARRAY, + \T_OPEN_SHORT_ARRAY => \T_OPEN_SHORT_ARRAY, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 0.12.0 + * + * @return array + */ + public function register() { + return $this->targets; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.12.0 The actual checks contained in this method used to + * be in the `processSingleLineArray()` method. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + + if ( \T_OPEN_SHORT_ARRAY === $this->tokens[ $stackPtr ]['code'] + && $this->is_short_list( $stackPtr ) + ) { + // Short list, not short array. + return; + } + + /* + * Determine the array opener & closer. + */ + $array_open_close = $this->find_array_open_close( $stackPtr ); + if ( false === $array_open_close ) { + // Array open/close could not be determined. + return; + } + + $opener = $array_open_close['opener']; + $closer = $array_open_close['closer']; + unset( $array_open_close ); + + /* + * Long arrays only: Check for space between the array keyword and the open parenthesis. + */ + if ( \T_ARRAY === $this->tokens[ $stackPtr ]['code'] ) { + + if ( ( $stackPtr + 1 ) !== $opener ) { + $error = 'There must be no space between the "array" keyword and the opening parenthesis'; + $error_code = 'SpaceAfterKeyword'; + + $nextNonWhitespace = $this->phpcsFile->findNext( \T_WHITESPACE, ( $stackPtr + 1 ), ( $opener + 1 ), true ); + if ( $nextNonWhitespace !== $opener ) { + // Don't auto-fix: Something other than whitespace found between keyword and open parenthesis. + $this->phpcsFile->addError( $error, $stackPtr, $error_code ); + } else { + + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, $error_code ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + for ( $i = ( $stackPtr + 1 ); $i < $opener; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + $this->phpcsFile->fixer->endChangeset(); + unset( $i ); + } + } + unset( $error, $error_code, $nextNonWhitespace, $fix ); + } + } + + /* + * Check for empty arrays. + */ + $nextNonWhitespace = $this->phpcsFile->findNext( \T_WHITESPACE, ( $opener + 1 ), ( $closer + 1 ), true ); + if ( $nextNonWhitespace === $closer ) { + + if ( ( $opener + 1 ) !== $closer ) { + $fix = $this->phpcsFile->addFixableError( + 'Empty array declaration must have no space between the parentheses', + $stackPtr, + 'SpaceInEmptyArray' + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + for ( $i = ( $opener + 1 ); $i < $closer; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + $this->phpcsFile->fixer->endChangeset(); + unset( $i ); + } + } + + // This array is empty, so the below checks aren't necessary. + return; + } + unset( $nextNonWhitespace ); + + // Pass off to either the single line or multi-line array analysis. + if ( $this->tokens[ $opener ]['line'] === $this->tokens[ $closer ]['line'] ) { + $this->process_single_line_array( $stackPtr, $opener, $closer ); + } else { + $this->process_multi_line_array( $stackPtr, $opener, $closer ); + } + } + + /** + * Process a single-line array. + * + * @since 0.13.0 The actual checks contained in this method used to + * be in the `process()` method. + * + * @param int $stackPtr The position of the current token in the stack. + * @param int $opener The position of the array opener. + * @param int $closer The position of the array closer. + * + * @return void + */ + protected function process_single_line_array( $stackPtr, $opener, $closer ) { + /* + * Check that associative arrays are always multi-line. + */ + $array_has_keys = $this->phpcsFile->findNext( \T_DOUBLE_ARROW, $opener, $closer ); + if ( false !== $array_has_keys ) { + + $array_items = $this->get_function_call_parameters( $stackPtr ); + + if ( ( false === $this->allow_single_item_single_line_associative_arrays + && ! empty( $array_items ) ) + || ( true === $this->allow_single_item_single_line_associative_arrays + && \count( $array_items ) > 1 ) + ) { + /* + * Make sure the double arrow is for *this* array, not for a nested one. + */ + $array_has_keys = false; // Reset before doing more detailed check. + foreach ( $array_items as $item ) { + for ( $ptr = $item['start']; $ptr <= $item['end']; $ptr++ ) { + if ( \T_DOUBLE_ARROW === $this->tokens[ $ptr ]['code'] ) { + $array_has_keys = true; + break 2; + } + + // Skip passed any nested arrays. + if ( isset( $this->targets[ $this->tokens[ $ptr ]['code'] ] ) ) { + $nested_array_open_close = $this->find_array_open_close( $ptr ); + if ( false === $nested_array_open_close ) { + // Nested array open/close could not be determined. + continue; + } + + $ptr = $nested_array_open_close['closer']; + } + } + } + + if ( true === $array_has_keys ) { + + $phrase = 'an'; + if ( true === $this->allow_single_item_single_line_associative_arrays ) { + $phrase = 'a multi-item'; + } + $fix = $this->phpcsFile->addFixableError( + 'When %s array uses associative keys, each value should start on a new line.', + $closer, + 'AssociativeArrayFound', + array( $phrase ) + ); + + if ( true === $fix ) { + + $this->phpcsFile->fixer->beginChangeset(); + + foreach ( $array_items as $item ) { + /* + * Add a line break before the first non-empty token in the array item. + * Prevents extraneous whitespace at the start of the line which could be + * interpreted as alignment whitespace. + */ + $first_non_empty = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $item['start'], + ( $item['end'] + 1 ), + true + ); + if ( false === $first_non_empty ) { + continue; + } + + if ( $item['start'] <= ( $first_non_empty - 1 ) + && \T_WHITESPACE === $this->tokens[ ( $first_non_empty - 1 ) ]['code'] + ) { + // Remove whitespace which would otherwise becoming trailing + // (as it gives problems with the fixed file). + $this->phpcsFile->fixer->replaceToken( ( $first_non_empty - 1 ), '' ); + } + + $this->phpcsFile->fixer->addNewlineBefore( $first_non_empty ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + + // No need to check for spacing around opener/closer as this array should be multi-line. + return; + } + } + } + + /* + * Check that there is a single space after the array opener and before the array closer. + */ + if ( \T_WHITESPACE !== $this->tokens[ ( $opener + 1 ) ]['code'] ) { + + $fix = $this->phpcsFile->addFixableError( + 'Missing space after array opener.', + $opener, + 'NoSpaceAfterArrayOpener' + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $opener, ' ' ); + } + } elseif ( ' ' !== $this->tokens[ ( $opener + 1 ) ]['content'] ) { + + $fix = $this->phpcsFile->addFixableError( + 'Expected 1 space after array opener, found %s.', + $opener, + 'SpaceAfterArrayOpener', + array( \strlen( $this->tokens[ ( $opener + 1 ) ]['content'] ) ) + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $opener + 1 ), ' ' ); + } + } + + if ( \T_WHITESPACE !== $this->tokens[ ( $closer - 1 ) ]['code'] ) { + + $fix = $this->phpcsFile->addFixableError( + 'Missing space before array closer.', + $closer, + 'NoSpaceBeforeArrayCloser' + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContentBefore( $closer, ' ' ); + } + } elseif ( ' ' !== $this->tokens[ ( $closer - 1 ) ]['content'] ) { + + $fix = $this->phpcsFile->addFixableError( + 'Expected 1 space before array closer, found %s.', + $closer, + 'SpaceBeforeArrayCloser', + array( \strlen( $this->tokens[ ( $closer - 1 ) ]['content'] ) ) + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $closer - 1 ), ' ' ); + } + } + } + + /** + * Process a multi-line array. + * + * @since 0.13.0 The actual checks contained in this method used to + * be in the `ArrayDeclaration` sniff. + * + * @param int $stackPtr The position of the current token in the stack. + * @param int $opener The position of the array opener. + * @param int $closer The position of the array closer. + * + * @return void + */ + protected function process_multi_line_array( $stackPtr, $opener, $closer ) { + /* + * Check that the closing bracket is on a new line. + */ + $last_content = $this->phpcsFile->findPrevious( \T_WHITESPACE, ( $closer - 1 ), $opener, true ); + if ( false !== $last_content + && $this->tokens[ $last_content ]['line'] === $this->tokens[ $closer ]['line'] + ) { + $fix = $this->phpcsFile->addFixableError( + 'Closing parenthesis of array declaration must be on a new line', + $closer, + 'CloseBraceNewLine' + ); + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + if ( $last_content < ( $closer - 1 ) + && \T_WHITESPACE === $this->tokens[ ( $closer - 1 ) ]['code'] + ) { + // Remove whitespace which would otherwise becoming trailing + // (as it gives problems with the fixed file). + $this->phpcsFile->fixer->replaceToken( ( $closer - 1 ), '' ); + } + + $this->phpcsFile->fixer->addNewlineBefore( $closer ); + $this->phpcsFile->fixer->endChangeset(); + } + } + + /* + * Check that each array item starts on a new line. + */ + $array_items = $this->get_function_call_parameters( $stackPtr ); + $end_of_last_item = $opener; + + foreach ( $array_items as $item ) { + $end_of_this_item = ( $item['end'] + 1 ); + + // Find the line on which the item starts. + $first_content = $this->phpcsFile->findNext( + array( \T_WHITESPACE, \T_DOC_COMMENT_WHITESPACE ), + $item['start'], + $end_of_this_item, + true + ); + + // Ignore comments after array items if the next real content starts on a new line. + if ( $this->tokens[ $first_content ]['line'] === $this->tokens[ $end_of_last_item ]['line'] + && ( \T_COMMENT === $this->tokens[ $first_content ]['code'] + || isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $first_content ]['code'] ] ) ) + ) { + $end_of_comment = $first_content; + + // Find the end of (multi-line) /* */- style trailing comments. + if ( substr( ltrim( $this->tokens[ $end_of_comment ]['content'] ), 0, 2 ) === '/*' ) { + while ( ( \T_COMMENT === $this->tokens[ $end_of_comment ]['code'] + || isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $end_of_comment ]['code'] ] ) ) + && substr( rtrim( $this->tokens[ $end_of_comment ]['content'] ), -2 ) !== '*/' + && ( $end_of_comment + 1 ) < $end_of_this_item + ) { + $end_of_comment++; + } + + if ( $this->tokens[ $end_of_comment ]['line'] !== $this->tokens[ $end_of_last_item ]['line'] ) { + // Multi-line trailing comment. + $end_of_last_item = $end_of_comment; + } + } + + $next = $this->phpcsFile->findNext( + array( \T_WHITESPACE, \T_DOC_COMMENT_WHITESPACE ), + ( $end_of_comment + 1 ), + $end_of_this_item, + true + ); + + if ( false === $next ) { + // Shouldn't happen, but just in case. + $end_of_last_item = $end_of_this_item; + continue; + } + + if ( $this->tokens[ $next ]['line'] !== $this->tokens[ $first_content ]['line'] ) { + $first_content = $next; + } + } + + if ( false === $first_content ) { + // Shouldn't happen, but just in case. + $end_of_last_item = $end_of_this_item; + continue; + } + + if ( $this->tokens[ $end_of_last_item ]['line'] === $this->tokens[ $first_content ]['line'] ) { + + $fix = $this->phpcsFile->addFixableError( + 'Each item in a multi-line array must be on a new line', + $first_content, + 'ArrayItemNoNewLine' + ); + + if ( true === $fix ) { + + $this->phpcsFile->fixer->beginChangeset(); + + if ( ( $end_of_last_item + 1 ) <= ( $first_content - 1 ) + && \T_WHITESPACE === $this->tokens[ ( $first_content - 1 ) ]['code'] + ) { + // Remove whitespace which would otherwise becoming trailing + // (as it gives problems with the fixed file). + $this->phpcsFile->fixer->replaceToken( ( $first_content - 1 ), '' ); + } + + $this->phpcsFile->fixer->addNewlineBefore( $first_content ); + $this->phpcsFile->fixer->endChangeset(); + } + } + + $end_of_last_item = $end_of_this_item; + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayIndentationSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayIndentationSniff.php new file mode 100644 index 00000000..c0b5dcf5 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayIndentationSniff.php @@ -0,0 +1,542 @@ +ignore_tokens = Tokens::$heredocTokens; + unset( $this->ignore_tokens[ \T_START_HEREDOC ], $this->ignore_tokens[ \T_START_NOWDOC ] ); + $this->ignore_tokens[ \T_INLINE_HTML ] = \T_INLINE_HTML; + + return array( + \T_ARRAY, + \T_OPEN_SHORT_ARRAY, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + if ( ! isset( $this->tab_width ) ) { + $this->tab_width = PHPCSHelper::get_tab_width( $this->phpcsFile ); + } + + if ( \T_OPEN_SHORT_ARRAY === $this->tokens[ $stackPtr ]['code'] + && $this->is_short_list( $stackPtr ) + ) { + // Short list, not short array. + return; + } + + /* + * Determine the array opener & closer. + */ + $array_open_close = $this->find_array_open_close( $stackPtr ); + if ( false === $array_open_close ) { + // Array open/close could not be determined. + return; + } + + $opener = $array_open_close['opener']; + $closer = $array_open_close['closer']; + + if ( $this->tokens[ $opener ]['line'] === $this->tokens[ $closer ]['line'] ) { + // Not interested in single line arrays. + return; + } + + /* + * Check the closing bracket is lined up with the start of the content on the line + * containing the array opener. + */ + $opener_line_spaces = $this->get_indentation_size( $opener ); + $closer_line_spaces = ( $this->tokens[ $closer ]['column'] - 1 ); + + if ( $closer_line_spaces !== $opener_line_spaces ) { + $error = 'Array closer not aligned correctly; expected %s space(s) but found %s'; + $error_code = 'CloseBraceNotAligned'; + + /* + * Report & fix the issue if the close brace is on its own line with + * nothing or only indentation whitespace before it. + */ + if ( 0 === $closer_line_spaces + || ( \T_WHITESPACE === $this->tokens[ ( $closer - 1 ) ]['code'] + && 1 === $this->tokens[ ( $closer - 1 ) ]['column'] ) + ) { + $this->add_array_alignment_error( + $closer, + $error, + $error_code, + $opener_line_spaces, + $closer_line_spaces, + $this->get_indentation_string( $opener_line_spaces ) + ); + } else { + /* + * Otherwise, only report the error, don't try and fix it (yet). + * + * It will get corrected in a future loop of the fixer once the closer + * has been moved to its own line by the `ArrayDeclarationSpacing` sniff. + */ + $this->phpcsFile->addError( + $error, + $closer, + $error_code, + array( $opener_line_spaces, $closer_line_spaces ) + ); + } + + unset( $error, $error_code ); + } + + /* + * Verify & correct the array item indentation. + */ + $array_items = $this->get_function_call_parameters( $stackPtr ); + if ( empty( $array_items ) ) { + // Strange, no array items found. + return; + } + + $expected_spaces = ( $opener_line_spaces + $this->tab_width ); + $expected_indent = $this->get_indentation_string( $expected_spaces ); + $end_of_previous_item = $opener; + + foreach ( $array_items as $item ) { + $end_of_this_item = ( $item['end'] + 1 ); + + // Find the line on which the item starts. + $first_content = $this->phpcsFile->findNext( + array( \T_WHITESPACE, \T_DOC_COMMENT_WHITESPACE ), + $item['start'], + $end_of_this_item, + true + ); + + // Deal with trailing comments. + if ( false !== $first_content + && \T_COMMENT === $this->tokens[ $first_content ]['code'] + && $this->tokens[ $first_content ]['line'] === $this->tokens[ $end_of_previous_item ]['line'] + ) { + $first_content = $this->phpcsFile->findNext( + array( \T_WHITESPACE, \T_DOC_COMMENT_WHITESPACE, \T_COMMENT ), + ( $first_content + 1 ), + $end_of_this_item, + true + ); + } + + if ( false === $first_content ) { + $end_of_previous_item = $end_of_this_item; + continue; + } + + // Bow out from reporting and fixing mixed multi-line/single-line arrays. + // That is handled by the ArrayDeclarationSpacingSniff. + if ( $this->tokens[ $first_content ]['line'] === $this->tokens[ $end_of_previous_item ]['line'] + || ( 1 !== $this->tokens[ $first_content ]['column'] + && \T_WHITESPACE !== $this->tokens[ ( $first_content - 1 ) ]['code'] ) + ) { + return $closer; + } + + $found_spaces = ( $this->tokens[ $first_content ]['column'] - 1 ); + + if ( $found_spaces !== $expected_spaces ) { + $this->add_array_alignment_error( + $first_content, + 'Array item not aligned correctly; expected %s spaces but found %s', + 'ItemNotAligned', + $expected_spaces, + $found_spaces, + $expected_indent + ); + } + + // No need for further checking if this is a one-line array item. + if ( $this->tokens[ $first_content ]['line'] === $this->tokens[ $item['end'] ]['line'] ) { + $end_of_previous_item = $end_of_this_item; + continue; + } + + /* + * Multi-line array items. + * + * Verify & if needed, correct the indentation of subsequent lines. + * Subsequent lines may be indented more or less than the mimimum expected indent, + * but the "first line after" should be indented - at least - as much as the very first line + * of the array item. + * Indentation correction for subsequent lines will be based on that diff. + */ + + // Find first token on second line of the array item. + // If the second line is a heredoc/nowdoc, continue on until we find a line with a different token. + // Same for the second line of a multi-line text string. + for ( $ptr = ( $first_content + 1 ); $ptr <= $item['end']; $ptr++ ) { + if ( $this->tokens[ $first_content ]['line'] !== $this->tokens[ $ptr ]['line'] + && 1 === $this->tokens[ $ptr ]['column'] + && false === $this->ignore_token( $ptr ) + ) { + break; + } + } + + $first_content_on_line2 = $this->phpcsFile->findNext( + array( \T_WHITESPACE, \T_DOC_COMMENT_WHITESPACE ), + $ptr, + $end_of_this_item, + true + ); + + if ( false === $first_content_on_line2 ) { + /* + * Apparently there were only tokens in the ignore list on subsequent lines. + * + * In that case, the comma after the array item might be on a line by itself, + * so check its placement. + */ + if ( $this->tokens[ $item['end'] ]['line'] !== $this->tokens[ $end_of_this_item ]['line'] + && \T_COMMA === $this->tokens[ $end_of_this_item ]['code'] + && ( $this->tokens[ $end_of_this_item ]['column'] - 1 ) !== $expected_spaces + ) { + $this->add_array_alignment_error( + $end_of_this_item, + 'Comma after multi-line array item not aligned correctly; expected %s spaces, but found %s', + 'MultiLineArrayItemCommaNotAligned', + $expected_spaces, + ( $this->tokens[ $end_of_this_item ]['column'] - 1 ), + $expected_indent + ); + } + + $end_of_previous_item = $end_of_this_item; + continue; + } + + $found_spaces_on_line2 = $this->get_indentation_size( $first_content_on_line2 ); + $expected_spaces_on_line2 = $expected_spaces; + + if ( $found_spaces < $found_spaces_on_line2 ) { + $expected_spaces_on_line2 += ( $found_spaces_on_line2 - $found_spaces ); + } + + if ( $found_spaces_on_line2 !== $expected_spaces_on_line2 ) { + + $fix = $this->phpcsFile->addFixableError( + 'Multi-line array item not aligned correctly; expected %s spaces, but found %s', + $first_content_on_line2, + 'MultiLineArrayItemNotAligned', + array( + $expected_spaces_on_line2, + $found_spaces_on_line2, + ) + ); + + if ( true === $fix ) { + $expected_indent_on_line2 = $this->get_indentation_string( $expected_spaces_on_line2 ); + + $this->phpcsFile->fixer->beginChangeset(); + + // Fix second line for the array item. + if ( 1 === $this->tokens[ $first_content_on_line2 ]['column'] + && \T_COMMENT === $this->tokens[ $first_content_on_line2 ]['code'] + ) { + $actual_comment = ltrim( $this->tokens[ $first_content_on_line2 ]['content'] ); + $replacement = $expected_indent_on_line2 . $actual_comment; + + $this->phpcsFile->fixer->replaceToken( $first_content_on_line2, $replacement ); + + } else { + $this->fix_alignment_error( $first_content_on_line2, $expected_indent_on_line2 ); + } + + // Fix subsequent lines. + for ( $i = ( $first_content_on_line2 + 1 ); $i <= $item['end']; $i++ ) { + // We're only interested in the first token on each line. + if ( 1 !== $this->tokens[ $i ]['column'] ) { + if ( $this->tokens[ $i ]['line'] === $this->tokens[ $item['end'] ]['line'] ) { + // We might as well quit if we're past the first token on the last line. + break; + } + continue; + } + + $first_content_on_line = $this->phpcsFile->findNext( + array( \T_WHITESPACE, \T_DOC_COMMENT_WHITESPACE ), + $i, + $end_of_this_item, + true + ); + + if ( false === $first_content_on_line ) { + break; + } + + // Ignore lines with heredoc and nowdoc tokens and subsequent lines in multi-line strings. + if ( true === $this->ignore_token( $first_content_on_line ) ) { + $i = $first_content_on_line; + continue; + } + + $found_spaces_on_line = $this->get_indentation_size( $first_content_on_line ); + $expected_spaces_on_line = ( $expected_spaces_on_line2 + ( $found_spaces_on_line - $found_spaces_on_line2 ) ); + $expected_spaces_on_line = max( $expected_spaces_on_line, 0 ); // Can't be below 0. + $expected_indent_on_line = $this->get_indentation_string( $expected_spaces_on_line ); + + if ( $found_spaces_on_line !== $expected_spaces_on_line ) { + if ( 1 === $this->tokens[ $first_content_on_line ]['column'] + && \T_COMMENT === $this->tokens[ $first_content_on_line ]['code'] + ) { + $actual_comment = ltrim( $this->tokens[ $first_content_on_line ]['content'] ); + $replacement = $expected_indent_on_line . $actual_comment; + + $this->phpcsFile->fixer->replaceToken( $first_content_on_line, $replacement ); + } else { + $this->fix_alignment_error( $first_content_on_line, $expected_indent_on_line ); + } + } + + // Move past any potential empty lines between the previous non-empty line and this one. + // No need to do the fixes twice. + $i = $first_content_on_line; + } + + /* + * Check the placement of the comma after the array item as it might be on a line by itself. + */ + if ( $this->tokens[ $item['end'] ]['line'] !== $this->tokens[ $end_of_this_item ]['line'] + && \T_COMMA === $this->tokens[ $end_of_this_item ]['code'] + && ( $this->tokens[ $end_of_this_item ]['column'] - 1 ) !== $expected_spaces + ) { + $this->add_array_alignment_error( + $end_of_this_item, + 'Comma after array item not aligned correctly; expected %s spaces, but found %s', + 'MultiLineArrayItemCommaNotAligned', + $expected_spaces, + ( $this->tokens[ $end_of_this_item ]['column'] - 1 ), + $expected_indent + ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + } + + $end_of_previous_item = $end_of_this_item; + } + } + + /** + * Should the token be ignored ? + * + * This method is only intended to be used with the first token on a line + * for subsequent lines in an multi-line array item. + * + * @param int $ptr Stack pointer to the first token on a line. + * + * @return bool + */ + protected function ignore_token( $ptr ) { + $token_code = $this->tokens[ $ptr ]['code']; + + if ( isset( $this->ignore_tokens[ $token_code ] ) ) { + return true; + } + + /* + * If it's a subsequent line of a multi-line sting, it will not start with a quote + * character, nor just *be* a quote character. + */ + if ( \T_CONSTANT_ENCAPSED_STRING === $token_code + || \T_DOUBLE_QUOTED_STRING === $token_code + ) { + // Deal with closing quote of a multi-line string being on its own line. + if ( "'" === $this->tokens[ $ptr ]['content'] + || '"' === $this->tokens[ $ptr ]['content'] + ) { + return true; + } + + // Deal with subsequent lines of a multi-line string where the token is broken up per line. + if ( "'" !== $this->tokens[ $ptr ]['content'][0] + && '"' !== $this->tokens[ $ptr ]['content'][0] + ) { + return true; + } + } + + return false; + } + + /** + * Determine the line indentation whitespace. + * + * @param int $ptr Stack pointer to an arbitrary token on a line. + * + * @return int Nr of spaces found. Where necessary, tabs are translated to spaces. + */ + protected function get_indentation_size( $ptr ) { + + // Find the first token on the line. + for ( ; $ptr >= 0; $ptr-- ) { + if ( 1 === $this->tokens[ $ptr ]['column'] ) { + break; + } + } + + $whitespace = ''; + + if ( \T_WHITESPACE === $this->tokens[ $ptr ]['code'] + || \T_DOC_COMMENT_WHITESPACE === $this->tokens[ $ptr ]['code'] + ) { + return $this->tokens[ $ptr ]['length']; + } + + /* + * Special case for multi-line, non-docblock comments. + * Only applicable for subsequent lines in an array item. + * + * First/Single line is tokenized as T_WHITESPACE + T_COMMENT + * Subsequent lines are tokenized as T_COMMENT including the indentation whitespace. + */ + if ( \T_COMMENT === $this->tokens[ $ptr ]['code'] ) { + $content = $this->tokens[ $ptr ]['content']; + $actual_comment = ltrim( $content ); + $whitespace = str_replace( $actual_comment, '', $content ); + } + + return \strlen( $whitespace ); + } + + /** + * Create an indentation string. + * + * @param int $nr Number of spaces the indentation should be. + * + * @return string + */ + protected function get_indentation_string( $nr ) { + if ( 0 >= $nr ) { + return ''; + } + + // Space-based indentation. + if ( false === $this->tabIndent ) { + return str_repeat( ' ', $nr ); + } + + // Tab-based indentation. + $num_tabs = (int) floor( $nr / $this->tab_width ); + $remaining = ( $nr % $this->tab_width ); + $tab_indent = str_repeat( "\t", $num_tabs ); + $tab_indent .= str_repeat( ' ', $remaining ); + + return $tab_indent; + } + + /** + * Throw an error and fix incorrect array alignment. + * + * @param int $ptr Stack pointer to the first content on the line. + * @param string $error Error message. + * @param string $error_code Error code. + * @param int $expected Expected nr of spaces (tabs translated to space value). + * @param int $found Found nr of spaces (tabs translated to space value). + * @param string $new_indent Whitespace indent replacement content. + */ + protected function add_array_alignment_error( $ptr, $error, $error_code, $expected, $found, $new_indent ) { + + $fix = $this->phpcsFile->addFixableError( $error, $ptr, $error_code, array( $expected, $found ) ); + if ( true === $fix ) { + $this->fix_alignment_error( $ptr, $new_indent ); + } + } + + /** + * Fix incorrect array alignment. + * + * @param int $ptr Stack pointer to the first content on the line. + * @param string $new_indent Whitespace indent replacement content. + */ + protected function fix_alignment_error( $ptr, $new_indent ) { + if ( 1 === $this->tokens[ $ptr ]['column'] ) { + $this->phpcsFile->fixer->addContentBefore( $ptr, $new_indent ); + } else { + $this->phpcsFile->fixer->replaceToken( ( $ptr - 1 ), $new_indent ); + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayKeySpacingRestrictionsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayKeySpacingRestrictionsSniff.php new file mode 100644 index 00000000..6b3203cd --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayKeySpacingRestrictionsSniff.php @@ -0,0 +1,192 @@ +tokens[ $stackPtr ]; + if ( ! isset( $token['bracket_closer'] ) ) { + $this->phpcsFile->addWarning( 'Missing bracket closer.', $stackPtr, 'MissingBracketCloser' ); + return; + } + + $need_spaces = $this->phpcsFile->findNext( + array( \T_CONSTANT_ENCAPSED_STRING, \T_LNUMBER, \T_WHITESPACE, \T_MINUS ), + ( $stackPtr + 1 ), + $token['bracket_closer'], + true + ); + + $spaced1 = ( \T_WHITESPACE === $this->tokens[ ( $stackPtr + 1 ) ]['code'] ); + $spaced2 = ( \T_WHITESPACE === $this->tokens[ ( $token['bracket_closer'] - 1 ) ]['code'] ); + + // It should have spaces unless if it only has strings or numbers as the key. + if ( false !== $need_spaces + && ( false === $spaced1 || false === $spaced2 ) + ) { + $error = 'Array keys must be surrounded by spaces unless they contain a string or an integer.'; + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, 'NoSpacesAroundArrayKeys' ); + if ( true === $fix ) { + if ( ! $spaced1 ) { + $this->phpcsFile->fixer->addContentBefore( ( $stackPtr + 1 ), ' ' ); + } + if ( ! $spaced2 ) { + $this->phpcsFile->fixer->addContentBefore( $token['bracket_closer'], ' ' ); + } + } + } elseif ( false === $need_spaces && ( $spaced1 || $spaced2 ) ) { + $error = 'Array keys must NOT be surrounded by spaces if they only contain a string or an integer.'; + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, 'SpacesAroundArrayKeys' ); + if ( true === $fix ) { + if ( $spaced1 ) { + $this->phpcsFile->fixer->beginChangeset(); + $this->phpcsFile->fixer->replaceToken( ( $stackPtr + 1 ), '' ); + + for ( $i = ( $stackPtr + 2 ); $i < $token['bracket_closer']; $i++ ) { + if ( \T_WHITESPACE !== $this->tokens[ $i ]['code'] ) { + break; + } + + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + if ( $spaced2 ) { + $this->phpcsFile->fixer->beginChangeset(); + $this->phpcsFile->fixer->replaceToken( ( $token['bracket_closer'] - 1 ), '' ); + + for ( $i = ( $token['bracket_closer'] - 2 ); $i > $stackPtr; $i-- ) { + if ( \T_WHITESPACE !== $this->tokens[ $i ]['code'] ) { + break; + } + + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + } + } + + // If spaces are needed, check that there is only one space. + if ( false !== $need_spaces && ( $spaced1 || $spaced2 ) ) { + if ( $spaced1 ) { + $ptr = ( $stackPtr + 1 ); + $length = 0; + if ( $this->tokens[ $ptr ]['line'] !== $this->tokens[ ( $ptr + 1 ) ]['line'] ) { + $length = 'newline'; + } else { + $length = $this->tokens[ $ptr ]['length']; + } + + if ( 1 !== $length ) { + $error = 'There should be exactly one space before the array key. Found: %s'; + $data = array( $length ); + $fix = $this->phpcsFile->addFixableError( + $error, + $ptr, + 'TooMuchSpaceBeforeKey', + $data + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + $this->phpcsFile->fixer->replaceToken( $ptr, ' ' ); + + for ( $i = ( $ptr + 1 ); $i < $token['bracket_closer']; $i++ ) { + if ( \T_WHITESPACE !== $this->tokens[ $i ]['code'] ) { + break; + } + + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + } + } + + if ( $spaced2 ) { + $prev_non_empty = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $token['bracket_closer'] - 1 ), null, true ); + $ptr = ( $prev_non_empty + 1 ); + $length = 0; + if ( $this->tokens[ $ptr ]['line'] !== $this->tokens[ $token['bracket_closer'] ]['line'] ) { + $length = 'newline'; + } else { + $length = $this->tokens[ $ptr ]['length']; + } + + if ( 1 !== $length ) { + $error = 'There should be exactly one space after the array key. Found: %s'; + $data = array( $length ); + $fix = $this->phpcsFile->addFixableError( + $error, + $ptr, + 'TooMuchSpaceAfterKey', + $data + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + $this->phpcsFile->fixer->replaceToken( $ptr, ' ' ); + + for ( $i = ( $ptr + 1 ); $i < $token['bracket_closer']; $i++ ) { + if ( \T_WHITESPACE !== $this->tokens[ $i ]['code'] ) { + break; + } + + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + } + } + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/CommaAfterArrayItemSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/CommaAfterArrayItemSniff.php new file mode 100644 index 00000000..902bc670 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/CommaAfterArrayItemSniff.php @@ -0,0 +1,313 @@ +tokens[ $stackPtr ]['code'] + && $this->is_short_list( $stackPtr ) + ) { + // Short list, not short array. + return; + } + + /* + * Determine the array opener & closer. + */ + $array_open_close = $this->find_array_open_close( $stackPtr ); + if ( false === $array_open_close ) { + // Array open/close could not be determined. + return; + } + + $opener = $array_open_close['opener']; + $closer = $array_open_close['closer']; + unset( $array_open_close ); + + // This array is empty, so the below checks aren't necessary. + if ( ( $opener + 1 ) === $closer ) { + return; + } + + $single_line = true; + if ( $this->tokens[ $opener ]['line'] !== $this->tokens[ $closer ]['line'] ) { + $single_line = false; + } + + $array_items = $this->get_function_call_parameters( $stackPtr ); + if ( empty( $array_items ) ) { + // Strange, no array items found. + return; + } + + $array_item_count = \count( $array_items ); + + // Note: $item_index is 1-based and the array items are split on the commas! + foreach ( $array_items as $item_index => $item ) { + $maybe_comma = ( $item['end'] + 1 ); + $is_comma = false; + if ( isset( $this->tokens[ $maybe_comma ] ) && \T_COMMA === $this->tokens[ $maybe_comma ]['code'] ) { + $is_comma = true; + } + + /* + * Check if this is a comma at the end of the last item in a single line array. + */ + if ( true === $single_line && $item_index === $array_item_count ) { + + $this->phpcsFile->recordMetric( + $stackPtr, + 'Single line array - comma after last item', + ( true === $is_comma ? 'yes' : 'no' ) + ); + + if ( true === $is_comma ) { + $fix = $this->phpcsFile->addFixableError( + 'Comma not allowed after last value in single-line array declaration', + $maybe_comma, + 'CommaAfterLast' + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( $maybe_comma, '' ); + } + } + + /* + * No need to do the spacing checks for the last item in a single line array. + * This is handled by another sniff checking the spacing before the array closer. + */ + continue; + } + + $last_content = $this->phpcsFile->findPrevious( + Tokens::$emptyTokens, + $item['end'], + $item['start'], + true + ); + + if ( false === $last_content ) { + // Shouldn't be able to happen, but just in case, ignore this array item. + continue; + } + + /** + * Make sure every item in a multi-line array has a comma at the end. + * + * Should in reality only be triggered by the last item in a multi-line array + * as otherwise we'd have a parse error already. + */ + if ( false === $is_comma && false === $single_line ) { + + $fix = $this->phpcsFile->addFixableError( + 'Each array item in a multi-line array declaration must end in a comma', + $last_content, + 'NoComma' + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $last_content, ',' ); + } + } + + if ( false === $single_line && $item_index === $array_item_count ) { + $this->phpcsFile->recordMetric( + $stackPtr, + 'Multi-line array - comma after last item', + ( true === $is_comma ? 'yes' : 'no' ) + ); + } + + if ( false === $is_comma ) { + // Can't check spacing around the comma if there is no comma. + continue; + } + + /* + * Check for whitespace at the end of the array item. + */ + if ( $last_content !== $item['end'] + // Ignore whitespace at the end of a multi-line item if it is the end of a heredoc/nowdoc. + && ( true === $single_line + || ! isset( Tokens::$heredocTokens[ $this->tokens[ $last_content ]['code'] ] ) ) + ) { + $newlines = 0; + $spaces = 0; + for ( $i = $item['end']; $i > $last_content; $i-- ) { + + if ( \T_WHITESPACE === $this->tokens[ $i ]['code'] ) { + if ( $this->tokens[ $i ]['content'] === $this->phpcsFile->eolChar ) { + $newlines++; + } else { + $spaces += $this->tokens[ $i ]['length']; + } + } elseif ( \T_COMMENT === $this->tokens[ $i ]['code'] + || isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $i ]['code'] ] ) + ) { + break; + } + } + + $space_phrases = array(); + if ( $spaces > 0 ) { + $space_phrases[] = $spaces . ' spaces'; + } + if ( $newlines > 0 ) { + $space_phrases[] = $newlines . ' newlines'; + } + unset( $newlines, $spaces ); + + $fix = $this->phpcsFile->addFixableError( + 'Expected 0 spaces between "%s" and comma; %s found', + $maybe_comma, + 'SpaceBeforeComma', + array( + $this->tokens[ $last_content ]['content'], + implode( ' and ', $space_phrases ), + ) + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + for ( $i = $item['end']; $i > $last_content; $i-- ) { + + if ( \T_WHITESPACE === $this->tokens[ $i ]['code'] ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + + } elseif ( \T_COMMENT === $this->tokens[ $i ]['code'] + || isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $i ]['code'] ] ) + ) { + // We need to move the comma to before the comment. + $this->phpcsFile->fixer->addContent( $last_content, ',' ); + $this->phpcsFile->fixer->replaceToken( $maybe_comma, '' ); + + /* + * No need to worry about removing too much whitespace in + * combination with a `//` comment as in that case, the newline + * is part of the comment, so we're good. + */ + + break; + } + } + $this->phpcsFile->fixer->endChangeset(); + } + } + + if ( ! isset( $this->tokens[ ( $maybe_comma + 1 ) ] ) ) { + // Shouldn't be able to happen, but just in case. + continue; + } + + /* + * Check whitespace after the comma. + */ + $next_token = $this->tokens[ ( $maybe_comma + 1 ) ]; + + if ( \T_WHITESPACE === $next_token['code'] ) { + + if ( false === $single_line && $this->phpcsFile->eolChar === $next_token['content'] ) { + continue; + } + + $next_non_whitespace = $this->phpcsFile->findNext( + \T_WHITESPACE, + ( $maybe_comma + 1 ), + $closer, + true + ); + + if ( false === $next_non_whitespace + || ( false === $single_line + && $this->tokens[ $next_non_whitespace ]['line'] === $this->tokens[ $maybe_comma ]['line'] + && ( \T_COMMENT === $this->tokens[ $next_non_whitespace ]['code'] + || isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $next_non_whitespace ]['code'] ] ) ) ) + ) { + continue; + } + + $space_length = $next_token['length']; + if ( 1 === $space_length ) { + continue; + } + + $fix = $this->phpcsFile->addFixableError( + 'Expected 1 space between comma and "%s"; %s found', + $maybe_comma, + 'SpaceAfterComma', + array( + $this->tokens[ $next_non_whitespace ]['content'], + $space_length, + ) + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $maybe_comma + 1 ), ' ' ); + } + } else { + // This is either a comment or a mixed single/multi-line array. + // Just add a space and let other sniffs sort out the array layout. + $fix = $this->phpcsFile->addFixableError( + 'Expected 1 space between comma and "%s"; 0 found', + $maybe_comma, + 'NoSpaceAfterComma', + array( $next_token['content'] ) + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $maybe_comma, ' ' ); + } + } + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/MultipleStatementAlignmentSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/MultipleStatementAlignmentSniff.php new file mode 100644 index 00000000..dc68e4f9 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/MultipleStatementAlignmentSniff.php @@ -0,0 +1,617 @@ += 60, align at column 60. + * - for the outliers, i.e. the array indexes where the end position + * goes past column 60, it will not align the arrow, the sniff will + * just make sure there is only one space between the end of the + * array index and the double arrow. + * + * The column value is regarded as a hard value, i.e. includes indentation, + * so setting it very low is not a good idea. + * + * @since 0.14.0 + * + * @var int + */ + public $maxColumn = 1000; + + /** + * Whether or not to align the arrow operator for multi-line array items. + * + * Whether or not an item is regarded as multi-line is based on the **value** + * of the item, not the key. + * + * Valid values are: + * - 'always': Default. Align all arrays items regardless of single/multi-line. + * - 'never': Never align array items which span multiple lines. + * This will enforce one space between the array index and the + * double arrow operator for multi-line array items, independently + * of the alignment of the rest of the array items. + * Multi-line items where the arrow is already aligned with the + * "expected" alignment, however, will be left alone. + * - operator : Only align the operator for multi-line arrays items if the + * + number percentage of multi-line items passes the comparison. + * - As it is a percentage, the number has to be between 0 and 100. + * - Supported operators: <, <=, >, >=, ==, =, !=, <> + * - The percentage is calculated against all array items + * (with and without assignment operator). + * - The (new) expected alignment will be calculated based only + * on the items being aligned. + * - Multi-line items where the arrow is already aligned with the + * (new) "expected" alignment, however, will be left alone. + * Examples: + * * Setting this to `!=100` or `<100` means that alignment will + * be enforced, unless *all* array items are multi-line. + * This is probably the most commonly desired situation. + * * Setting this to `=100` means that alignment will only + * be enforced, if *all* array items are multi-line. + * * Setting this to `<50` means that the majority of array items + * need to be single line before alignment is enforced for + * multi-line items in the array. + * * Setting this to `=0` is useless as in that case there are + * no multi-line items in the array anyway. + * + * This setting will respect the `ignoreNewlines` and `maxColumnn` settings. + * + * @since 0.14.0 + * + * @var string|int + */ + public $alignMultilineItems = 'always'; + + /** + * Storage for parsed $alignMultilineItems operator part. + * + * @since 0.14.0 + * + * @var string + */ + private $operator; + + /** + * Storage for parsed $alignMultilineItems numeric part. + * + * Stored as a string as the comparison will be done string based. + * + * @since 0.14.0 + * + * @var string + */ + private $number; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 0.14.0 + * + * @return array + */ + public function register() { + return array( + \T_ARRAY, + \T_OPEN_SHORT_ARRAY, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + if ( \T_OPEN_SHORT_ARRAY === $this->tokens[ $stackPtr ]['code'] + && $this->is_short_list( $stackPtr ) + ) { + // Short list, not short array. + return; + } + + /* + * Determine the array opener & closer. + */ + $array_open_close = $this->find_array_open_close( $stackPtr ); + if ( false === $array_open_close ) { + // Array open/close could not be determined. + return; + } + + $opener = $array_open_close['opener']; + $closer = $array_open_close['closer']; + + $array_items = $this->get_function_call_parameters( $stackPtr ); + if ( empty( $array_items ) ) { + return; + } + + // Pass off to either the single line or multi-line array analysis. + if ( $this->tokens[ $opener ]['line'] === $this->tokens[ $closer ]['line'] ) { + return $this->process_single_line_array( $stackPtr, $array_items, $opener, $closer ); + } else { + return $this->process_multi_line_array( $stackPtr, $array_items, $opener, $closer ); + } + } + + /** + * Process a single-line array. + * + * While the WP standard does not allow single line multi-item associative arrays, + * this sniff should function independently of that. + * + * The `WordPress.WhiteSpace.OperatorSpacing` sniff already covers checking that + * there is a space between the array key and the double arrow, but doesn't + * enforce it to be exactly one space for single line arrays. + * That is what this method covers. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param array $items Info array containing information on each array item. + * @param int $opener The position of the array opener. + * @param int $closer The position of the array closer. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + protected function process_single_line_array( $stackPtr, $items, $opener, $closer ) { + /* + * For single line arrays, we don't care about what level the arrow is from. + * Just find and fix them all. + */ + $next_arrow = $this->phpcsFile->findNext( + \T_DOUBLE_ARROW, + ( $opener + 1 ), + $closer + ); + + while ( false !== $next_arrow ) { + if ( \T_WHITESPACE === $this->tokens[ ( $next_arrow - 1 ) ]['code'] ) { + $space_length = $this->tokens[ ( $next_arrow - 1 ) ]['length']; + if ( 1 !== $space_length ) { + $error = 'Expected 1 space between "%s" and double arrow; %s found'; + $data = array( + $this->tokens[ ( $next_arrow - 2 ) ]['content'], + $space_length, + ); + + $fix = $this->phpcsFile->addFixableWarning( $error, $next_arrow, 'SpaceBeforeDoubleArrow', $data ); + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $next_arrow - 1 ), ' ' ); + } + } + } + + // Find the position of the next double arrow. + $next_arrow = $this->phpcsFile->findNext( + \T_DOUBLE_ARROW, + ( $next_arrow + 1 ), + $closer + ); + } + + // Ignore any child-arrays as the double arrows in these will already have been handled. + return ( $closer + 1 ); + } + + /** + * Process a multi-line array. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param array $items Info array containing information on each array item. + * @param int $opener The position of the array opener. + * @param int $closer The position of the array closer. + * + * @return void + */ + protected function process_multi_line_array( $stackPtr, $items, $opener, $closer ) { + + $this->maxColumn = (int) $this->maxColumn; + $this->validate_align_multiline_items(); + + /* + * Determine what the spacing before the arrow should be. + * + * Will unset any array items without double arrow and with new line whitespace + * if newlines are to be ignored, so the second foreach loop only has to deal + * with items which need attention. + * + * This sniff does not take incorrect indentation of array keys into account. + * That's for the `WordPress.Arrays.ArrayIndentation` sniff to fix. + * If that would affect the alignment, a second (or third) loop of the fixer + * will correct it (again) after the indentation has been fixed. + */ + $index_end_cols = array(); // Keep track of the end column position of index keys. + $double_arrow_cols = array(); // Keep track of arrow column position and count. + $multi_line_count = 0; + $total_items = \count( $items ); + + foreach ( $items as $key => $item ) { + if ( strpos( $item['raw'], '=>' ) === false ) { + // Ignore items without assignment operators. + unset( $items[ $key ] ); + continue; + } + + // Find the position of the first double arrow. + $double_arrow = $this->phpcsFile->findNext( + \T_DOUBLE_ARROW, + $item['start'], + ( $item['end'] + 1 ) + ); + + if ( false === $double_arrow ) { + // Shouldn't happen, just in case. + unset( $items[ $key ] ); + continue; + } + + // Make sure the arrow is for this item and not for a nested array value assignment. + $has_array_opener = $this->phpcsFile->findNext( + $this->register(), + $item['start'], + $double_arrow + ); + + if ( false !== $has_array_opener ) { + // Double arrow is for a nested array. + unset( $items[ $key ] ); + continue; + } + + // Find the end of the array key. + $last_index_token = $this->phpcsFile->findPrevious( + \T_WHITESPACE, + ( $double_arrow - 1 ), + $item['start'], + true + ); + + if ( false === $last_index_token ) { + // Shouldn't happen, but just in case. + unset( $items[ $key ] ); + continue; + } + + if ( true === $this->ignoreNewlines + && $this->tokens[ $last_index_token ]['line'] !== $this->tokens[ $double_arrow ]['line'] + ) { + // Ignore this item as it has a new line between the item key and the double arrow. + unset( $items[ $key ] ); + continue; + } + + $index_end_position = ( $this->tokens[ $last_index_token ]['column'] + ( $this->tokens[ $last_index_token ]['length'] - 1 ) ); + $items[ $key ]['operatorPtr'] = $double_arrow; + $items[ $key ]['last_index_token'] = $last_index_token; + $items[ $key ]['last_index_col'] = $index_end_position; + + if ( $this->tokens[ $last_index_token ]['line'] === $this->tokens[ $item['end'] ]['line'] ) { + $items[ $key ]['single_line'] = true; + } else { + $items[ $key ]['single_line'] = false; + $multi_line_count++; + } + + if ( ( $index_end_position + 2 ) <= $this->maxColumn ) { + $index_end_cols[] = $index_end_position; + } + + if ( ! isset( $double_arrow_cols[ $this->tokens[ $double_arrow ]['column'] ] ) ) { + $double_arrow_cols[ $this->tokens[ $double_arrow ]['column'] ] = 1; + } else { + $double_arrow_cols[ $this->tokens[ $double_arrow ]['column'] ]++; + } + } + unset( $key, $item, $double_arrow, $has_array_opener, $last_index_token ); + + if ( empty( $items ) || empty( $index_end_cols ) ) { + // No actionable array items found. + return; + } + + /* + * Determine whether the operators for multi-line items should be aligned. + */ + if ( 'always' === $this->alignMultilineItems ) { + $alignMultilineItems = true; + } elseif ( 'never' === $this->alignMultilineItems ) { + $alignMultilineItems = false; + } else { + $percentage = (string) round( ( $multi_line_count / $total_items ) * 100, 0 ); + + // Bit hacky, but this is the only comparison function in PHP which allows to + // pass the comparison operator. And hey, it works ;-). + $alignMultilineItems = version_compare( $percentage, $this->number, $this->operator ); + } + + /* + * If necessary, rebuild the $index_end_cols and $double_arrow_cols arrays + * excluding multi-line items. + */ + if ( false === $alignMultilineItems ) { + $select_index_end_cols = array(); + $double_arrow_cols = array(); + + foreach ( $items as $item ) { + if ( false === $item['single_line'] ) { + continue; + } + + if ( ( $item['last_index_col'] + 2 ) <= $this->maxColumn ) { + $select_index_end_cols[] = $item['last_index_col']; + } + + if ( ! isset( $double_arrow_cols[ $this->tokens[ $item['operatorPtr'] ]['column'] ] ) ) { + $double_arrow_cols[ $this->tokens[ $item['operatorPtr'] ]['column'] ] = 1; + } else { + $double_arrow_cols[ $this->tokens[ $item['operatorPtr'] ]['column'] ]++; + } + } + } + + /* + * Determine the expected position of the double arrows. + */ + if ( ! empty( $select_index_end_cols ) ) { + $max_index_width = max( $select_index_end_cols ); + } else { + $max_index_width = max( $index_end_cols ); + } + + $expected_col = ( $max_index_width + 2 ); + + if ( false === $this->exact && ! empty( $double_arrow_cols ) ) { + /* + * If the alignment does not have to be exact, see if a majority + * group of the arrows is already at an acceptable position. + */ + arsort( $double_arrow_cols, \SORT_NUMERIC ); + reset( $double_arrow_cols ); + $count = current( $double_arrow_cols ); + + if ( $count > 1 || ( 1 === $count && \count( $items ) === 1 ) ) { + // Allow for several groups of arrows having the same $count. + $filtered_double_arrow_cols = array_keys( $double_arrow_cols, $count, true ); + + foreach ( $filtered_double_arrow_cols as $col ) { + if ( $col > $expected_col && $col <= $this->maxColumn ) { + $expected_col = $col; + break; + } + } + } + } + unset( $max_index_width, $count, $filtered_double_arrow_cols, $col ); + + /* + * Verify and correct the spacing around the double arrows. + */ + foreach ( $items as $item ) { + if ( $this->tokens[ $item['operatorPtr'] ]['column'] === $expected_col + && $this->tokens[ $item['operatorPtr'] ]['line'] === $this->tokens[ $item['last_index_token'] ]['line'] + ) { + // Already correctly aligned. + continue; + } + + if ( \T_WHITESPACE !== $this->tokens[ ( $item['operatorPtr'] - 1 ) ]['code'] ) { + $before = 0; + } else { + if ( $this->tokens[ $item['last_index_token'] ]['line'] !== $this->tokens[ $item['operatorPtr'] ]['line'] ) { + $before = 'newline'; + } else { + $before = $this->tokens[ ( $item['operatorPtr'] - 1 ) ]['length']; + } + } + + /* + * Deal with index sizes larger than maxColumn and with multi-line + * array items which should not be aligned. + */ + if ( ( $item['last_index_col'] + 2 ) > $this->maxColumn + || ( false === $alignMultilineItems && false === $item['single_line'] ) + ) { + + if ( ( $item['last_index_col'] + 2 ) === $this->tokens[ $item['operatorPtr'] ]['column'] + && $this->tokens[ $item['operatorPtr'] ]['line'] === $this->tokens[ $item['last_index_token'] ]['line'] + ) { + // MaxColumn/Multi-line item exception, already correctly aligned. + continue; + } + + $prefix = 'LongIndex'; + if ( false === $alignMultilineItems && false === $item['single_line'] ) { + $prefix = 'MultilineItem'; + } + + $error_code = $prefix . 'SpaceBeforeDoubleArrow'; + if ( 0 === $before ) { + $error_code = $prefix . 'NoSpaceBeforeDoubleArrow'; + } + + $fix = $this->phpcsFile->addFixableWarning( + 'Expected 1 space between "%s" and double arrow; %s found.', + $item['operatorPtr'], + $error_code, + array( + $this->tokens[ $item['last_index_token'] ]['content'], + $before, + ) + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + // Remove whitespace tokens between the end of the index and the arrow, if any. + for ( $i = ( $item['last_index_token'] + 1 ); $i < $item['operatorPtr']; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + // Add the correct whitespace. + $this->phpcsFile->fixer->addContent( $item['last_index_token'], ' ' ); + + $this->phpcsFile->fixer->endChangeset(); + } + continue; + } + + /* + * Deal with the space before double arrows in all other cases. + */ + $expected_whitespace = $expected_col - ( $this->tokens[ $item['last_index_token'] ]['column'] + $this->tokens[ $item['last_index_token'] ]['length'] ); + + $fix = $this->phpcsFile->addFixableWarning( + 'Array double arrow not aligned correctly; expected %s space(s) between "%s" and double arrow, but found %s.', + $item['operatorPtr'], + 'DoubleArrowNotAligned', + array( + $expected_whitespace, + $this->tokens[ $item['last_index_token'] ]['content'], + $before, + ) + ); + + if ( true === $fix ) { + if ( 0 === $before || 'newline' === $before ) { + $this->phpcsFile->fixer->beginChangeset(); + + // Remove whitespace tokens between the end of the index and the arrow, if any. + for ( $i = ( $item['last_index_token'] + 1 ); $i < $item['operatorPtr']; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + // Add the correct whitespace. + $this->phpcsFile->fixer->addContent( + $item['last_index_token'], + str_repeat( ' ', $expected_whitespace ) + ); + + $this->phpcsFile->fixer->endChangeset(); + } elseif ( $expected_whitespace > $before ) { + // Add to the existing whitespace to prevent replacing tabs with spaces. + // That's the concern of another sniff. + $this->phpcsFile->fixer->addContent( + ( $item['operatorPtr'] - 1 ), + str_repeat( ' ', ( $expected_whitespace - $before ) ) + ); + } else { + // Too much whitespace found. + $this->phpcsFile->fixer->replaceToken( + ( $item['operatorPtr'] - 1 ), + str_repeat( ' ', $expected_whitespace ) + ); + } + } + } + } + + /** + * Validate that a valid value has been received for the alignMultilineItems property. + * + * This message may be thrown more than once if the property is being changed inline in a file. + * + * @since 0.14.0 + */ + protected function validate_align_multiline_items() { + $alignMultilineItems = $this->alignMultilineItems; + + if ( 'always' === $alignMultilineItems || 'never' === $alignMultilineItems ) { + return; + } else { + // Correct for a potentially added % sign. + $alignMultilineItems = rtrim( $alignMultilineItems, '%' ); + + if ( preg_match( '`^([=<>!]{1,2})(100|[0-9]{1,2})$`', $alignMultilineItems, $matches ) > 0 ) { + $operator = $matches[1]; + $number = (int) $matches[2]; + + if ( \in_array( $operator, array( '<', '<=', '>', '>=', '==', '=', '!=', '<>' ), true ) === true + && ( $number >= 0 && $number <= 100 ) + ) { + $this->alignMultilineItems = $alignMultilineItems; + $this->number = (string) $number; + $this->operator = $operator; + return; + } + } + } + + $this->phpcsFile->addError( + 'Invalid property value passed: "%s". The value for the "alignMultilineItems" property for the "WordPress.Arrays.MultipleStatementAlignment" sniff should be either "always", "never" or an comparison operator + a number between 0 and 100.', + 0, + 'InvalidPropertyPassed', + array( $this->alignMultilineItems ) + ); + + // Reset to the default if an invalid value was received. + $this->alignMultilineItems = 'always'; + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Classes/ClassInstantiationSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Classes/ClassInstantiationSniff.php new file mode 100644 index 00000000..3572fbee --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Classes/ClassInstantiationSniff.php @@ -0,0 +1,204 @@ +classname_tokens = Tokens::$emptyTokens; + $this->classname_tokens[ \T_NS_SEPARATOR ] = \T_NS_SEPARATOR; + $this->classname_tokens[ \T_STRING ] = \T_STRING; + $this->classname_tokens[ \T_SELF ] = \T_SELF; + $this->classname_tokens[ \T_STATIC ] = \T_STATIC; + $this->classname_tokens[ \T_PARENT ] = \T_PARENT; + $this->classname_tokens[ \T_ANON_CLASS ] = \T_ANON_CLASS; + + // Classname in a variable. + $this->classname_tokens[ \T_VARIABLE ] = \T_VARIABLE; + $this->classname_tokens[ \T_DOUBLE_COLON ] = \T_DOUBLE_COLON; + $this->classname_tokens[ \T_OBJECT_OPERATOR ] = \T_OBJECT_OPERATOR; + $this->classname_tokens[ \T_OPEN_SQUARE_BRACKET ] = \T_OPEN_SQUARE_BRACKET; + $this->classname_tokens[ \T_CLOSE_SQUARE_BRACKET ] = \T_CLOSE_SQUARE_BRACKET; + $this->classname_tokens[ \T_CONSTANT_ENCAPSED_STRING ] = \T_CONSTANT_ENCAPSED_STRING; + $this->classname_tokens[ \T_LNUMBER ] = \T_LNUMBER; + + return array( + \T_NEW, + \T_STRING, // JS. + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + // Make sure we have the right token, JS vs PHP. + if ( ( 'PHP' === $this->phpcsFile->tokenizerType && \T_NEW !== $this->tokens[ $stackPtr ]['code'] ) + || ( 'JS' === $this->phpcsFile->tokenizerType + && ( \T_STRING !== $this->tokens[ $stackPtr ]['code'] + || 'new' !== strtolower( $this->tokens[ $stackPtr ]['content'] ) ) ) + ) { + return; + } + + /* + * Check for new by reference used in PHP files. + */ + if ( 'PHP' === $this->phpcsFile->tokenizerType ) { + $prev_non_empty = $this->phpcsFile->findPrevious( + Tokens::$emptyTokens, + ( $stackPtr - 1 ), + null, + true + ); + + if ( false !== $prev_non_empty && 'T_BITWISE_AND' === $this->tokens[ $prev_non_empty ]['type'] ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Assigning new by reference', 'yes' ); + + $this->phpcsFile->addError( + 'Assigning the return value of new by reference is no longer supported by PHP.', + $stackPtr, + 'NewByReferenceFound' + ); + } else { + $this->phpcsFile->recordMetric( $stackPtr, 'Assigning new by reference', 'no' ); + } + } + + /* + * Check for parenthesis & correct placement thereof. + */ + $next_non_empty_after_class_name = $this->phpcsFile->findNext( + $this->classname_tokens, + ( $stackPtr + 1 ), + null, + true, + null, + true + ); + + if ( false === $next_non_empty_after_class_name ) { + // Live coding. + return; + } + + // Walk back to the last part of the class name. + $has_comment = false; + for ( $classname_ptr = ( $next_non_empty_after_class_name - 1 ); $classname_ptr >= $stackPtr; $classname_ptr-- ) { + if ( ! isset( Tokens::$emptyTokens[ $this->tokens[ $classname_ptr ]['code'] ] ) ) { + // Prevent a false positive on variable variables, disregard them for now. + if ( $stackPtr === $classname_ptr ) { + return; + } + + break; + } + + if ( \T_WHITESPACE !== $this->tokens[ $classname_ptr ]['code'] ) { + $has_comment = true; + } + } + + if ( \T_OPEN_PARENTHESIS !== $this->tokens[ $next_non_empty_after_class_name ]['code'] ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Object instantiation with parenthesis', 'no' ); + + $fix = $this->phpcsFile->addFixableError( + 'Parenthesis should always be used when instantiating a new object.', + $classname_ptr, + 'MissingParenthesis' + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $classname_ptr, '()' ); + } + } else { + $this->phpcsFile->recordMetric( $stackPtr, 'Object instantiation with parenthesis', 'yes' ); + + if ( ( $next_non_empty_after_class_name - 1 ) !== $classname_ptr ) { + $this->phpcsFile->recordMetric( + $stackPtr, + 'Space between classname and parenthesis', + ( $next_non_empty_after_class_name - $classname_ptr ) + ); + + $error = 'There must be no spaces between the class name and the open parenthesis when instantiating a new object.'; + $error_code = 'SpaceBeforeParenthesis'; + + if ( false === $has_comment ) { + $fix = $this->phpcsFile->addFixableError( $error, $next_non_empty_after_class_name, $error_code ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + for ( $i = ( $next_non_empty_after_class_name - 1 ); $i > $classname_ptr; $i-- ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + $this->phpcsFile->fixer->endChangeset(); + } + } else { + $this->phpcsFile->addError( $error, $next_non_empty_after_class_name, $error_code ); + } + } else { + $this->phpcsFile->recordMetric( $stackPtr, 'Space between classname and parenthesis', 0 ); + } + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php new file mode 100644 index 00000000..bf5879b8 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php @@ -0,0 +1,235 @@ +assignment_tokens = Tokens::$assignmentTokens; + unset( $this->assignment_tokens[ \T_DOUBLE_ARROW ] ); + + $starters = Tokens::$booleanOperators; + $starters[ \T_SEMICOLON ] = \T_SEMICOLON; + $starters[ \T_OPEN_PARENTHESIS ] = \T_OPEN_PARENTHESIS; + $starters[ \T_INLINE_ELSE ] = \T_INLINE_ELSE; + + $this->condition_start_tokens = $starters; + + return array( + \T_IF, + \T_ELSEIF, + \T_FOR, + \T_SWITCH, + \T_CASE, + \T_WHILE, + \T_INLINE_THEN, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + + $token = $this->tokens[ $stackPtr ]; + + // Find the condition opener/closer. + if ( \T_FOR === $token['code'] ) { + if ( isset( $token['parenthesis_opener'], $token['parenthesis_closer'] ) === false ) { + return; + } + + $semicolon = $this->phpcsFile->findNext( \T_SEMICOLON, ( $token['parenthesis_opener'] + 1 ), $token['parenthesis_closer'] ); + if ( false === $semicolon ) { + return; + } + + $opener = $semicolon; + $semicolon = $this->phpcsFile->findNext( \T_SEMICOLON, ( $opener + 1 ), $token['parenthesis_closer'] ); + if ( false === $semicolon ) { + return; + } + + $closer = $semicolon; + unset( $semicolon ); + + } elseif ( \T_CASE === $token['code'] ) { + if ( isset( $token['scope_opener'] ) === false ) { + return; + } + + $opener = $stackPtr; + $closer = $token['scope_opener']; + + } elseif ( \T_INLINE_THEN === $token['code'] ) { + // Check if the condition for the ternary is bracketed. + $prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true ); + if ( false === $prev ) { + // Shouldn't happen, but in that case we don't have anything to examine anyway. + return; + } + + if ( \T_CLOSE_PARENTHESIS === $this->tokens[ $prev ]['code'] ) { + if ( ! isset( $this->tokens[ $prev ]['parenthesis_opener'] ) ) { + return; + } + + $opener = $this->tokens[ $prev ]['parenthesis_opener']; + $closer = $prev; + } elseif ( isset( $token['nested_parenthesis'] ) ) { + $closer = end( $token['nested_parenthesis'] ); + $opener = key( $token['nested_parenthesis'] ); + + $next_statement_closer = $this->phpcsFile->findEndOfStatement( $stackPtr, array( \T_COLON, \T_CLOSE_PARENTHESIS, \T_CLOSE_SQUARE_BRACKET ) ); + if ( false !== $next_statement_closer && $next_statement_closer < $closer ) { + // Parentheses are unrelated to the ternary. + return; + } + + $prev_statement_closer = $this->phpcsFile->findStartOfStatement( $stackPtr, array( \T_COLON, \T_OPEN_PARENTHESIS, \T_OPEN_SQUARE_BRACKET ) ); + if ( false !== $prev_statement_closer && $opener < $prev_statement_closer ) { + // Parentheses are unrelated to the ternary. + return; + } + + if ( $closer > $stackPtr ) { + $closer = $stackPtr; + } + } else { + // No parenthesis found, can't determine where the conditional part of the ternary starts. + return; + } + } else { + if ( isset( $token['parenthesis_opener'], $token['parenthesis_closer'] ) === false ) { + return; + } + + $opener = $token['parenthesis_opener']; + $closer = $token['parenthesis_closer']; + } + + $startPos = $opener; + + do { + $hasAssignment = $this->phpcsFile->findNext( $this->assignment_tokens, ( $startPos + 1 ), $closer ); + if ( false === $hasAssignment ) { + return; + } + + // Examine whether the left side is a variable. + $hasVariable = false; + $conditionStart = $startPos; + $altConditionStart = $this->phpcsFile->findPrevious( + $this->condition_start_tokens, + ( $hasAssignment - 1 ), + $startPos + ); + if ( false !== $altConditionStart ) { + $conditionStart = $altConditionStart; + } + + for ( $i = $hasAssignment; $i > $conditionStart; $i-- ) { + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + // If this is a variable or array, we've seen all we need to see. + if ( \T_VARIABLE === $this->tokens[ $i ]['code'] + || \T_CLOSE_SQUARE_BRACKET === $this->tokens[ $i ]['code'] + ) { + $hasVariable = true; + break; + } + + // If this is a function call or something, we are OK. + if ( \T_CLOSE_PARENTHESIS === $this->tokens[ $i ]['code'] ) { + break; + } + } + + if ( true === $hasVariable ) { + $errorCode = 'Found'; + if ( \T_WHILE === $token['code'] ) { + $errorCode = 'FoundInWhileCondition'; + } elseif ( \T_INLINE_THEN === $token['code'] ) { + $errorCode = 'FoundInTernaryCondition'; + } + + $this->phpcsFile->addWarning( + 'Variable assignment found within a condition. Did you mean to do a comparison?', + $hasAssignment, + $errorCode + ); + } else { + $this->phpcsFile->addWarning( + 'Assignment found within a condition. Did you mean to do a comparison?', + $hasAssignment, + 'NonVariableAssignmentFound' + ); + } + + $startPos = $hasAssignment; + + } while ( $startPos < $closer ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/EmptyStatementSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/EmptyStatementSniff.php new file mode 100644 index 00000000..21e22014 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/EmptyStatementSniff.php @@ -0,0 +1,161 @@ +tokens[ $stackPtr ]['type'] ) { + /* + * Detect `something();;`. + */ + case 'T_SEMICOLON': + $prevNonEmpty = $this->phpcsFile->findPrevious( + Tokens::$emptyTokens, + ( $stackPtr - 1 ), + null, + true + ); + + if ( false === $prevNonEmpty + || ( \T_SEMICOLON !== $this->tokens[ $prevNonEmpty ]['code'] + && \T_OPEN_TAG !== $this->tokens[ $prevNonEmpty ]['code'] + && \T_OPEN_TAG_WITH_ECHO !== $this->tokens[ $prevNonEmpty ]['code'] ) + ) { + return; + } + + if ( isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + $nested = $this->tokens[ $stackPtr ]['nested_parenthesis']; + $last_closer = array_pop( $nested ); + if ( isset( $this->tokens[ $last_closer ]['parenthesis_owner'] ) + && \T_FOR === $this->tokens[ $this->tokens[ $last_closer ]['parenthesis_owner'] ]['code'] + ) { + // Empty for() condition. + return; + } + } + + $fix = $this->phpcsFile->addFixableWarning( + 'Empty PHP statement detected: superfluous semi-colon.', + $stackPtr, + 'SemicolonWithoutCodeDetected' + ); + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + if ( \T_OPEN_TAG === $this->tokens[ $prevNonEmpty ]['code'] + || \T_OPEN_TAG_WITH_ECHO === $this->tokens[ $prevNonEmpty ]['code'] + ) { + /* + * Check for superfluous whitespace after the semi-colon which will be + * removed as the `tokens[ ( $stackPtr + 1 ) ]['code'] ) { + $replacement = str_replace( ' ', '', $this->tokens[ ( $stackPtr + 1 ) ]['content'] ); + $this->phpcsFile->fixer->replaceToken( ( $stackPtr + 1 ), $replacement ); + } + } + + for ( $i = $stackPtr; $i > $prevNonEmpty; $i-- ) { + if ( \T_SEMICOLON !== $this->tokens[ $i ]['code'] + && \T_WHITESPACE !== $this->tokens[ $i ]['code'] + ) { + break; + } + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + break; + + /* + * Detect ``. + */ + case 'T_CLOSE_TAG': + $prevNonEmpty = $this->phpcsFile->findPrevious( + \T_WHITESPACE, + ( $stackPtr - 1 ), + null, + true + ); + + if ( false === $prevNonEmpty + || ( \T_OPEN_TAG !== $this->tokens[ $prevNonEmpty ]['code'] + && \T_OPEN_TAG_WITH_ECHO !== $this->tokens[ $prevNonEmpty ]['code'] ) + ) { + return; + } + + $fix = $this->phpcsFile->addFixableWarning( + 'Empty PHP open/close tag combination detected.', + $prevNonEmpty, + 'EmptyPHPOpenCloseTagsDetected' + ); + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + for ( $i = $prevNonEmpty; $i <= $stackPtr; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + $this->phpcsFile->fixer->endChangeset(); + } + break; + + default: + /* Deliberately left empty. */ + break; + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/EscapedNotTranslatedSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/EscapedNotTranslatedSniff.php new file mode 100644 index 00000000..5a7af877 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/EscapedNotTranslatedSniff.php @@ -0,0 +1,90 @@ + => + */ + protected $target_functions = array( + 'esc_html' => 'esc_html__', + 'esc_attr' => 'esc_attr__', + ); + + /** + * Process the parameters of a matched function. + * + * @since 2.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + if ( \count( $parameters ) === 1 ) { + return; + } + + /* + * We already know that there will be a valid open+close parenthesis, otherwise the sniff + * would have bowed out long before. + */ + $opener = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + $closer = $this->tokens[ $opener ]['parenthesis_closer']; + + $data = array( + $matched_content, + $this->target_functions[ $matched_content ], + $this->phpcsFile->getTokensAsString( $stackPtr, ( $closer - $stackPtr + 1 ) ), + ); + + $this->phpcsFile->addWarning( + '%s() expects only one parameter. Did you mean to use %s() ? Found: %s', + $stackPtr, + 'Found', + $data + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/DirectDatabaseQuerySniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/DirectDatabaseQuerySniff.php new file mode 100644 index 00000000..583e9d9c --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/DirectDatabaseQuerySniff.php @@ -0,0 +1,265 @@ + array(), + 'cacheset' => array(), + 'cachedelete' => array(), + ); + + /** + * The lists of $wpdb methods. + * + * @since 0.6.0 + * @since 0.11.0 Changed from static to non-static. + * + * @var array[] + */ + protected $methods = array( + 'cachable' => array( + 'delete' => true, + 'get_var' => true, + 'get_col' => true, + 'get_row' => true, + 'get_results' => true, + 'query' => true, + 'replace' => true, + 'update' => true, + ), + 'noncachable' => array( + 'insert' => true, + ), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array( + \T_VARIABLE, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + // Check for $wpdb variable. + if ( '$wpdb' !== $this->tokens[ $stackPtr ]['content'] ) { + return; + } + + $is_object_call = $this->phpcsFile->findNext( \T_OBJECT_OPERATOR, ( $stackPtr + 1 ), null, false, null, true ); + if ( false === $is_object_call ) { + return; // This is not a call to the wpdb object. + } + + $methodPtr = $this->phpcsFile->findNext( array( \T_WHITESPACE ), ( $is_object_call + 1 ), null, true, null, true ); + $method = $this->tokens[ $methodPtr ]['content']; + + $this->mergeFunctionLists(); + + if ( ! isset( $this->methods['all'][ $method ] ) ) { + return; + } + + $endOfStatement = $this->phpcsFile->findNext( \T_SEMICOLON, ( $stackPtr + 1 ), null, false, null, true ); + $endOfLineComment = ''; + for ( $i = ( $endOfStatement + 1 ); $i < $this->phpcsFile->numTokens; $i++ ) { + + if ( $this->tokens[ $i ]['line'] !== $this->tokens[ $endOfStatement ]['line'] ) { + break; + } + + if ( \T_COMMENT === $this->tokens[ $i ]['code'] ) { + $endOfLineComment .= $this->tokens[ $i ]['content']; + } + } + + $whitelisted_db_call = false; + if ( preg_match( '/db call\W*(?:ok|pass|clear|whitelist)/i', $endOfLineComment ) ) { + $whitelisted_db_call = true; + } + + // Check for Database Schema Changes. + for ( $_pos = ( $stackPtr + 1 ); $_pos < $endOfStatement; $_pos++ ) { + $_pos = $this->phpcsFile->findNext( Tokens::$textStringTokens, $_pos, $endOfStatement, false, null, true ); + if ( false === $_pos ) { + break; + } + + if ( preg_match( '#\b(?:ALTER|CREATE|DROP)\b#i', $this->tokens[ $_pos ]['content'] ) > 0 ) { + $this->phpcsFile->addWarning( 'Attempting a database schema change is discouraged.', $_pos, 'SchemaChange' ); + } + } + + // Flag instance if not whitelisted. + if ( ! $whitelisted_db_call ) { + $this->phpcsFile->addWarning( 'Usage of a direct database call is discouraged.', $stackPtr, 'DirectQuery' ); + } + + if ( ! isset( $this->methods['cachable'][ $method ] ) ) { + return $endOfStatement; + } + + $whitelisted_cache = false; + $cached = false; + $wp_cache_get = false; + if ( preg_match( '/cache\s+(?:ok|pass|clear|whitelist)/i', $endOfLineComment ) ) { + $whitelisted_cache = true; + } + if ( ! $whitelisted_cache && ! empty( $this->tokens[ $stackPtr ]['conditions'] ) ) { + $scope_function = $this->phpcsFile->getCondition( $stackPtr, \T_FUNCTION ); + + if ( false === $scope_function ) { + $scope_function = $this->phpcsFile->getCondition( $stackPtr, \T_CLOSURE ); + } + + if ( false !== $scope_function ) { + $scopeStart = $this->tokens[ $scope_function ]['scope_opener']; + $scopeEnd = $this->tokens[ $scope_function ]['scope_closer']; + + for ( $i = ( $scopeStart + 1 ); $i < $scopeEnd; $i++ ) { + if ( \T_STRING === $this->tokens[ $i ]['code'] ) { + + if ( isset( $this->cacheDeleteFunctions[ $this->tokens[ $i ]['content'] ] ) ) { + + if ( \in_array( $method, array( 'query', 'update', 'replace', 'delete' ), true ) ) { + $cached = true; + break; + } + } elseif ( isset( $this->cacheGetFunctions[ $this->tokens[ $i ]['content'] ] ) ) { + + $wp_cache_get = true; + + } elseif ( isset( $this->cacheSetFunctions[ $this->tokens[ $i ]['content'] ] ) ) { + + if ( $wp_cache_get ) { + $cached = true; + break; + } + } + } + } + } + } + + if ( ! $cached && ! $whitelisted_cache ) { + $message = 'Direct database call without caching detected. Consider using wp_cache_get() / wp_cache_set() or wp_cache_delete().'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'NoCaching' ); + } + + return $endOfStatement; + } + + /** + * Merge custom functions provided via a custom ruleset with the defaults, if we haven't already. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @return void + */ + protected function mergeFunctionLists() { + if ( ! isset( $this->methods['all'] ) ) { + $this->methods['all'] = array_merge( $this->methods['cachable'], $this->methods['noncachable'] ); + } + + if ( $this->customCacheGetFunctions !== $this->addedCustomFunctions['cacheget'] ) { + $this->cacheGetFunctions = $this->merge_custom_array( + $this->customCacheGetFunctions, + $this->cacheGetFunctions + ); + + $this->addedCustomFunctions['cacheget'] = $this->customCacheGetFunctions; + } + + if ( $this->customCacheSetFunctions !== $this->addedCustomFunctions['cacheset'] ) { + $this->cacheSetFunctions = $this->merge_custom_array( + $this->customCacheSetFunctions, + $this->cacheSetFunctions + ); + + $this->addedCustomFunctions['cacheset'] = $this->customCacheSetFunctions; + } + + if ( $this->customCacheDeleteFunctions !== $this->addedCustomFunctions['cachedelete'] ) { + $this->cacheDeleteFunctions = $this->merge_custom_array( + $this->customCacheDeleteFunctions, + $this->cacheDeleteFunctions + ); + + $this->addedCustomFunctions['cachedelete'] = $this->customCacheDeleteFunctions; + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/PreparedSQLPlaceholdersSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/PreparedSQLPlaceholdersSniff.php new file mode 100644 index 00000000..8f184c6b --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/PreparedSQLPlaceholdersSniff.php @@ -0,0 +1,661 @@ +prepare method. + * + * Check the following issues: + * - The only placeholders supported are: %d, %f (%F) and %s and their variations. + * - Literal % signs need to be properly escaped as `%%`. + * - Simple placeholders (%d, %f, %F, %s) should be left unquoted in the query string. + * - Complex placeholders - numbered and formatted variants - will not be quoted + * automagically by $wpdb->prepare(), so if used for values, should be quoted in + * the query string. + * - Either an array of replacements should be passed matching the number of + * placeholders found or individual parameters for each placeholder should + * be passed. + * - Wildcards for LIKE compare values should be passed in via a replacement parameter. + * + * The sniff allows for a specific pattern with a variable number of placeholders + * created using code along the lines of: + * `sprintf( 'query .... IN (%s) ...', implode( ',', array_fill( 0, count( $something ), '%s' ) ) )`. + * + * A "PreparedSQLPlaceholders replacement count" whitelist comment is supported + * specifically to silence the `ReplacementsWrongNumber` and `UnfinishedPrepare` + * error codes. The other error codes are not affected by it. + * + * @link https://developer.wordpress.org/reference/classes/wpdb/prepare/ + * @link https://core.trac.wordpress.org/changeset/41496 + * @link https://core.trac.wordpress.org/changeset/41471 + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.14.0 + */ +class PreparedSQLPlaceholdersSniff extends Sniff { + + /** + * These regexes copied from http://php.net/manual/en/function.sprintf.php#93552 + * and adjusted for limitations in `$wpdb->prepare()`. + * + * Near duplicate of the one used in the WP.I18n sniff, but with fewer types allowed. + * + * Note: The regex delimiters and modifiers are not included to allow this regex to be + * concatenated together with other regex partials. + * + * @since 0.14.0 + * + * @var string + */ + const PREPARE_PLACEHOLDER_REGEX = '(?: + (? true, + ); + + /** + * Storage for the stack pointer to the method call token. + * + * @since 0.14.0 + * + * @var int + */ + protected $methodPtr; + + /** + * Simple regex snippet to recognize and remember quotes. + * + * @since 0.14.0 + * + * @var string + */ + private $regex_quote = '["\']'; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 0.14.0 + * + * @return array + */ + public function register() { + return array( + \T_VARIABLE, + \T_STRING, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + + if ( ! $this->is_wpdb_method_call( $stackPtr, $this->target_methods ) ) { + return; + } + + $parameters = $this->get_function_call_parameters( $this->methodPtr ); + if ( empty( $parameters ) ) { + return; + } + + $query = $parameters[1]; + $text_string_tokens_found = false; + $variable_found = false; + $sql_wildcard_found = false; + $total_placeholders = 0; + $total_parameters = \count( $parameters ); + $valid_in_clauses = array( + 'uses_in' => 0, + 'implode_fill' => 0, + 'adjustment_count' => 0, + ); + + for ( $i = $query['start']; $i <= $query['end']; $i++ ) { + // Skip over groups of tokens if they are part of an inline function call. + if ( isset( $skip_from, $skip_to ) && $i >= $skip_from && $i < $skip_to ) { + $i = $skip_to; + continue; + } + + if ( ! isset( Tokens::$textStringTokens[ $this->tokens[ $i ]['code'] ] ) ) { + if ( \T_VARIABLE === $this->tokens[ $i ]['code'] ) { + if ( '$wpdb' !== $this->tokens[ $i ]['content'] ) { + $variable_found = true; + } + continue; + } + + // Detect a specific pattern for variable replacements in combination with `IN`. + if ( \T_STRING === $this->tokens[ $i ]['code'] ) { + + if ( 'sprintf' === strtolower( $this->tokens[ $i ]['content'] ) ) { + $sprintf_parameters = $this->get_function_call_parameters( $i ); + + if ( ! empty( $sprintf_parameters ) ) { + $skip_from = ( $sprintf_parameters[1]['end'] + 1 ); + $last_param = end( $sprintf_parameters ); + $skip_to = ( $last_param['end'] + 1 ); + + $valid_in_clauses['implode_fill'] += $this->analyse_sprintf( $sprintf_parameters ); + $valid_in_clauses['adjustment_count'] += ( \count( $sprintf_parameters ) - 1 ); + } + unset( $sprintf_parameters, $last_param ); + + } elseif ( 'implode' === strtolower( $this->tokens[ $i ]['content'] ) ) { + $prev = $this->phpcsFile->findPrevious( + Tokens::$textStringTokens, + ( $i - 1 ), + $query['start'] + ); + + $prev_content = $this->strip_quotes( $this->tokens[ $prev ]['content'] ); + $regex_quote = $this->get_regex_quote_snippet( $prev_content, $this->tokens[ $prev ]['content'] ); + + // Only examine the implode if preceded by an ` IN (`. + if ( preg_match( '`\s+IN\s*\(\s*(' . $regex_quote . ')?$`i', $prev_content, $match ) > 0 ) { + + if ( isset( $match[1] ) && $regex_quote !== $this->regex_quote ) { + $this->phpcsFile->addError( + 'Dynamic placeholder generation should not have surrounding quotes.', + $i, + 'QuotedDynamicPlaceholderGeneration' + ); + } + + if ( $this->analyse_implode( $i ) === true ) { + ++$valid_in_clauses['uses_in']; + ++$valid_in_clauses['implode_fill']; + + $next = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $i + 1 ), null, true ); + if ( \T_OPEN_PARENTHESIS === $this->tokens[ $next ]['code'] + && isset( $this->tokens[ $next ]['parenthesis_closer'] ) + ) { + $skip_from = ( $i + 1 ); + $skip_to = ( $this->tokens[ $next ]['parenthesis_closer'] + 1 ); + } + } + } + unset( $prev, $next, $prev_content, $regex_quote, $match ); + } + } + + continue; + } + + $text_string_tokens_found = true; + $content = $this->tokens[ $i ]['content']; + + $regex_quote = $this->regex_quote; + if ( isset( Tokens::$stringTokens[ $this->tokens[ $i ]['code'] ] ) ) { + $content = $this->strip_quotes( $content ); + $regex_quote = $this->get_regex_quote_snippet( $content, $this->tokens[ $i ]['content'] ); + } + + if ( \T_DOUBLE_QUOTED_STRING === $this->tokens[ $i ]['code'] + || \T_HEREDOC === $this->tokens[ $i ]['code'] + ) { + // Only interested in actual query text, so strip out variables. + $stripped_content = $this->strip_interpolated_variables( $content ); + if ( $stripped_content !== $content ) { + $interpolated_vars = $this->get_interpolated_variables( $content ); + $vars_without_wpdb = array_diff( $interpolated_vars, array( 'wpdb' ) ); + $content = $stripped_content; + + if ( ! empty( $vars_without_wpdb ) ) { + $variable_found = true; + } + } + unset( $stripped_content, $interpolated_vars, $vars_without_wpdb ); + } + + $placeholders = preg_match_all( '`' . self::PREPARE_PLACEHOLDER_REGEX . '`x', $content, $matches ); + if ( $placeholders > 0 ) { + $total_placeholders += $placeholders; + } + + /* + * Analyse the query for incorrect LIKE queries. + * + * - `LIKE %s` is the only correct one. + * - `LIKE '%s'` or `LIKE "%s"` will not be reported here, but in the quote check. + * - Any other `LIKE` statement should be reported, either for using `LIKE` without + * SQL wildcards or for not passing the SQL wildcards via the replacement. + */ + $regex = '`\s+LIKE\s*(?:(' . $regex_quote . ')(?!%s(?:\1|$))(?P.*?)(?:\1|$)|(?:concat\((?![^\)]*%s[^\)]*\))(?P[^\)]*))\))`i'; + if ( preg_match_all( $regex, $content, $matches ) > 0 ) { + $walk = array(); + if ( ! empty( $matches['content'] ) ) { + $matches['content'] = array_filter( $matches['content'] ); + if ( ! empty( $matches['content'] ) ) { + $walk[] = 'content'; + } + } + if ( ! empty( $matches['concat'] ) ) { + $matches['concat'] = array_filter( $matches['concat'] ); + if ( ! empty( $matches['concat'] ) ) { + $walk[] = 'concat'; + } + } + + if ( ! empty( $walk ) ) { + foreach ( $walk as $match_key ) { + foreach ( $matches[ $match_key ] as $index => $match ) { + $data = array( $matches[0][ $index ] ); + + // Both a `%` as well as a `_` are wildcards in SQL. + if ( strpos( $match, '%' ) === false && strpos( $match, '_' ) === false ) { + $this->phpcsFile->addWarning( + 'Unless you are using SQL wildcards, using LIKE is inefficient. Use a straight compare instead. Found: %s.', + $i, + 'LikeWithoutWildcards', + $data + ); + } else { + $sql_wildcard_found = true; + + if ( strpos( $match, '%s' ) === false ) { + $this->phpcsFile->addError( + 'SQL wildcards for a LIKE query should be passed in through a replacement parameter. Found: %s.', + $i, + 'LikeWildcardsInQuery', + $data + ); + } else { + $this->phpcsFile->addError( + 'SQL wildcards for a LIKE query should be passed in through a replacement parameter and the variable part of the replacement should be escaped using "esc_like()". Found: %s.', + $i, + 'LikeWildcardsInQueryWithPlaceholder', + $data + ); + } + } + + /* + * Don't throw `UnescapedLiteral`, `UnsupportedPlaceholder` or `QuotedPlaceholder` + * for this part of the SQL query. + */ + $content = preg_replace( '`' . preg_quote( $match, '`' ) . '`', '', $content, 1 ); + } + } + } + unset( $matches, $index, $match, $data ); + } + + if ( strpos( $content, '%' ) === false ) { + continue; + } + + /* + * Analyse the query for unsupported placeholders. + */ + if ( preg_match_all( self::UNSUPPORTED_PLACEHOLDER_REGEX, $content, $matches ) > 0 ) { + if ( ! empty( $matches[0] ) ) { + foreach ( $matches[0] as $match ) { + if ( '%' === $match ) { + $this->phpcsFile->addError( + 'Found unescaped literal "%%" character.', + $i, + 'UnescapedLiteral', + array( $match ) + ); + } else { + $this->phpcsFile->addError( + 'Unsupported placeholder used in $wpdb->prepare(). Found: "%s".', + $i, + 'UnsupportedPlaceholder', + array( $match ) + ); + } + } + } + unset( $match, $matches ); + } + + /* + * Analyse the query for quoted placeholders. + */ + $regex = '`(' . $regex_quote . ')%[dfFs]\1`'; + if ( preg_match_all( $regex, $content, $matches ) > 0 ) { + if ( ! empty( $matches[0] ) ) { + foreach ( $matches[0] as $match ) { + $this->phpcsFile->addError( + 'Simple placeholders should not be quoted in the query string in $wpdb->prepare(). Found: %s.', + $i, + 'QuotedSimplePlaceholder', + array( $match ) + ); + } + } + unset( $match, $matches ); + } + + /* + * Analyse the query for unquoted complex placeholders. + */ + $regex = '`(? 0 ) { + if ( ! empty( $matches[0] ) ) { + foreach ( $matches[0] as $match ) { + if ( preg_match( '`%[dfFs]`', $match ) !== 1 ) { + $this->phpcsFile->addWarning( + 'Complex placeholders used for values in the query string in $wpdb->prepare() will NOT be quoted automagically. Found: %s.', + $i, + 'UnquotedComplexPlaceholder', + array( $match ) + ); + } + } + } + unset( $match, $matches ); + } + + /* + * Check for an ` IN (%s)` clause. + */ + $found_in = preg_match_all( '`\s+IN\s*\(\s*%s\s*\)`i', $content, $matches ); + if ( $found_in > 0 ) { + $valid_in_clauses['uses_in'] += $found_in; + } + unset( $found_in ); + } + + if ( false === $text_string_tokens_found ) { + // Query string passed in as a variable or function call, nothing to examine. + return; + } + + $count_diff_whitelisted = $this->has_whitelist_comment( + 'PreparedSQLPlaceholders replacement count', + $stackPtr + ); + + if ( 0 === $total_placeholders ) { + if ( 1 === $total_parameters ) { + if ( false === $variable_found && false === $sql_wildcard_found ) { + /* + * Only throw this warning if the PreparedSQL sniff won't throw one about + * variables being found. + * Also don't throw it if we just advised to use a replacement variable to pass a + * string containing an SQL wildcard. + */ + $this->phpcsFile->addWarning( + 'It is not necessary to prepare a query which doesn\'t use variable replacement.', + $i, + 'UnnecessaryPrepare' + ); + } + } elseif ( false === $count_diff_whitelisted && 0 === $valid_in_clauses['uses_in'] ) { + $this->phpcsFile->addWarning( + 'Replacement variables found, but no valid placeholders found in the query.', + $i, + 'UnfinishedPrepare' + ); + } + + return; + } + + if ( 1 === $total_parameters ) { + $this->phpcsFile->addError( + 'Placeholders found in the query passed to $wpdb->prepare(), but no replacements found. Expected %d replacement(s) parameters.', + $stackPtr, + 'MissingReplacements', + array( $total_placeholders ) + ); + return; + } + + if ( true === $count_diff_whitelisted ) { + return; + } + + $replacements = $parameters; + array_shift( $replacements ); // Remove the query. + + // The parameters may have been passed as an array in parameter 2. + if ( isset( $parameters[2] ) && 2 === $total_parameters ) { + $next = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $parameters[2]['start'], + ( $parameters[2]['end'] + 1 ), + true + ); + + if ( false !== $next + && ( \T_ARRAY === $this->tokens[ $next ]['code'] + || \T_OPEN_SHORT_ARRAY === $this->tokens[ $next ]['code'] ) + ) { + $replacements = $this->get_function_call_parameters( $next ); + } + } + + $total_replacements = \count( $replacements ); + $total_placeholders -= $valid_in_clauses['adjustment_count']; + + // Bow out when `IN` clauses have been used which appear to be correct. + if ( $valid_in_clauses['uses_in'] > 0 + && $valid_in_clauses['uses_in'] === $valid_in_clauses['implode_fill'] + && 1 === $total_replacements + ) { + return; + } + + /* + * Verify that the correct amount of replacements have been passed. + */ + if ( $total_replacements !== $total_placeholders ) { + $this->phpcsFile->addWarning( + 'Incorrect number of replacements passed to $wpdb->prepare(). Found %d replacement parameters, expected %d.', + $stackPtr, + 'ReplacementsWrongNumber', + array( $total_replacements, $total_placeholders ) + ); + } + } + + /** + * Retrieve a regex snippet to recognize and remember quotes based on the quote style + * used in the original string (if any). + * + * This allows for recognizing `"` and `\'` in single quoted strings, + * recognizing `'` and `\"` in double quotes strings and `'` and `"`when the quote + * style is unknown or it is a non-quoted string (heredoc/nowdoc and such). + * + * @since 0.14.0 + * + * @param string $stripped_content Text string content without surrounding quotes. + * @param string $original_content Original content for the same text string. + * + * @return string + */ + protected function get_regex_quote_snippet( $stripped_content, $original_content ) { + $regex_quote = $this->regex_quote; + + if ( $original_content !== $stripped_content ) { + $quote_style = $original_content[0]; + + if ( '"' === $quote_style ) { + $regex_quote = '\\\\"|\''; + } elseif ( "'" === $quote_style ) { + $regex_quote = '"|\\\\\''; + } + } + + return $regex_quote; + } + + /** + * Analyse a sprintf() query wrapper to see if it contains a specific code pattern + * to deal correctly with `IN` queries. + * + * The pattern we are searching for is: + * `sprintf( 'query ....', implode( ',', array_fill( 0, count( $something ), '%s' ) ) )` + * + * @since 0.14.0 + * + * @param array $sprintf_params Parameters details for the sprintf call. + * + * @return int The number of times the pattern was found in the replacements. + */ + protected function analyse_sprintf( $sprintf_params ) { + $found = 0; + + unset( $sprintf_params[1] ); + + foreach ( $sprintf_params as $sprintf_param ) { + if ( strpos( strtolower( $sprintf_param['raw'] ), 'implode' ) === false ) { + continue; + } + + $implode = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $sprintf_param['start'], + $sprintf_param['end'], + true + ); + if ( \T_STRING === $this->tokens[ $implode ]['code'] + && 'implode' === strtolower( $this->tokens[ $implode ]['content'] ) + ) { + if ( $this->analyse_implode( $implode ) === true ) { + ++$found; + } + } + } + + return $found; + } + + /** + * Analyse an implode() function call to see if it contains a specific code pattern + * to dynamically create placeholders. + * + * The pattern we are searching for is: + * `implode( ',', array_fill( 0, count( $something ), '%s' ) )` + * + * This pattern presumes unquoted placeholders! + * + * @since 0.14.0 + * + * @param int $implode_token The stackPtr to the implode function call. + * + * @return bool True if the pattern is found, false otherwise. + */ + protected function analyse_implode( $implode_token ) { + $implode_params = $this->get_function_call_parameters( $implode_token ); + + if ( empty( $implode_params ) || \count( $implode_params ) !== 2 ) { + return false; + } + + if ( preg_match( '`^(["\']), ?\1$`', $implode_params[1]['raw'] ) !== 1 ) { + return false; + } + + if ( strpos( strtolower( $implode_params[2]['raw'] ), 'array_fill' ) === false ) { + return false; + } + + $array_fill = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $implode_params[2]['start'], + $implode_params[2]['end'], + true + ); + + if ( \T_STRING !== $this->tokens[ $array_fill ]['code'] + || 'array_fill' !== strtolower( $this->tokens[ $array_fill ]['content'] ) + ) { + return false; + } + + $array_fill_params = $this->get_function_call_parameters( $array_fill ); + + if ( empty( $array_fill_params ) || \count( $array_fill_params ) !== 3 ) { + return false; + } + + return (bool) preg_match( '`^(["\'])%[dfFs]\1$`', $array_fill_params[3]['raw'] ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/PreparedSQLSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/PreparedSQLSniff.php new file mode 100644 index 00000000..1fe2ad96 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/PreparedSQLSniff.php @@ -0,0 +1,210 @@ + true, + 'get_col' => true, + 'get_row' => true, + 'get_results' => true, + 'prepare' => true, + 'query' => true, + ); + + /** + * Tokens that we don't flag when they are found in a $wpdb method call. + * + * @since 0.9.0 + * + * @var array + */ + protected $ignored_tokens = array( + \T_OBJECT_OPERATOR => true, + \T_OPEN_PARENTHESIS => true, + \T_CLOSE_PARENTHESIS => true, + \T_STRING_CONCAT => true, + \T_CONSTANT_ENCAPSED_STRING => true, + \T_OPEN_SQUARE_BRACKET => true, + \T_CLOSE_SQUARE_BRACKET => true, + \T_COMMA => true, + \T_LNUMBER => true, + \T_START_HEREDOC => true, + \T_END_HEREDOC => true, + \T_START_NOWDOC => true, + \T_NOWDOC => true, + \T_END_NOWDOC => true, + \T_INT_CAST => true, + \T_DOUBLE_CAST => true, + \T_BOOL_CAST => true, + \T_NS_SEPARATOR => true, + ); + + /** + * A loop pointer. + * + * It is a property so that we can access it in all of our methods. + * + * @since 0.9.0 + * + * @var int + */ + protected $i; + + /** + * The loop end marker. + * + * It is a property so that we can access it in all of our methods. + * + * @since 0.9.0 + * + * @var int + */ + protected $end; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 0.8.0 + * + * @return array + */ + public function register() { + + $this->ignored_tokens += Tokens::$emptyTokens; + + return array( + \T_VARIABLE, + \T_STRING, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.8.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + if ( ! $this->is_wpdb_method_call( $stackPtr, $this->methods ) ) { + return; + } + + if ( $this->has_whitelist_comment( 'unprepared SQL', $stackPtr ) ) { + return; + } + + for ( $this->i; $this->i < $this->end; $this->i++ ) { + + if ( isset( $this->ignored_tokens[ $this->tokens[ $this->i ]['code'] ] ) ) { + continue; + } + + if ( \T_DOUBLE_QUOTED_STRING === $this->tokens[ $this->i ]['code'] + || \T_HEREDOC === $this->tokens[ $this->i ]['code'] + ) { + + $bad_variables = array_filter( + $this->get_interpolated_variables( $this->tokens[ $this->i ]['content'] ), + function ( $symbol ) { + return ( 'wpdb' !== $symbol ); + } + ); + + foreach ( $bad_variables as $bad_variable ) { + $this->phpcsFile->addError( + 'Use placeholders and $wpdb->prepare(); found interpolated variable $%s at %s', + $this->i, + 'InterpolatedNotPrepared', + array( + $bad_variable, + $this->tokens[ $this->i ]['content'], + ) + ); + } + continue; + } + + if ( \T_VARIABLE === $this->tokens[ $this->i ]['code'] ) { + if ( '$wpdb' === $this->tokens[ $this->i ]['content'] ) { + $this->is_wpdb_method_call( $this->i, $this->methods ); + continue; + } + + if ( $this->is_safe_casted( $this->i ) ) { + continue; + } + } + + if ( \T_STRING === $this->tokens[ $this->i ]['code'] ) { + + if ( + isset( $this->SQLEscapingFunctions[ $this->tokens[ $this->i ]['content'] ] ) + || isset( $this->SQLAutoEscapedFunctions[ $this->tokens[ $this->i ]['content'] ] ) + ) { + + // Find the opening parenthesis. + $opening_paren = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $this->i + 1 ), null, true, null, true ); + + if ( false !== $opening_paren + && \T_OPEN_PARENTHESIS === $this->tokens[ $opening_paren ]['code'] + && isset( $this->tokens[ $opening_paren ]['parenthesis_closer'] ) + ) { + // Skip past the end of the function. + $this->i = $this->tokens[ $opening_paren ]['parenthesis_closer']; + continue; + } + } elseif ( isset( $this->formattingFunctions[ $this->tokens[ $this->i ]['content'] ] ) ) { + continue; + } + } + + $this->phpcsFile->addError( + 'Use placeholders and $wpdb->prepare(); found %s', + $this->i, + 'NotPrepared', + array( $this->tokens[ $this->i ]['content'] ) + ); + } + + return $this->end; + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/RestrictedClassesSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/RestrictedClassesSniff.php new file mode 100644 index 00000000..5ae13ee5 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/RestrictedClassesSniff.php @@ -0,0 +1,60 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Avoid direct calls to the database.', + * 'classes' => array( 'PDO', '\Namespace\Classname' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + + 'mysql' => array( + 'type' => 'error', + 'message' => 'Accessing the database directly should be avoided. Please use the $wpdb object and associated functions instead. Found: %s.', + 'classes' => array( + 'mysqli', + 'PDO', + 'PDOStatement', + ), + ), + + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/RestrictedFunctionsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/RestrictedFunctionsSniff.php new file mode 100644 index 00000000..dbab49fe --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/RestrictedFunctionsSniff.php @@ -0,0 +1,66 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + + 'mysql' => array( + 'type' => 'error', + 'message' => 'Accessing the database directly should be avoided. Please use the $wpdb object and associated functions instead. Found: %s.', + 'functions' => array( + 'mysql_*', + 'mysqli_*', + 'mysqlnd_ms_*', + 'mysqlnd_qc_*', + 'mysqlnd_uh_*', + 'mysqlnd_memcache_*', + 'maxdb_*', + ), + 'whitelist' => array( + 'mysql_to_rfc3339' => true, + ), + ), + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/SlowDBQuerySniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/SlowDBQuerySniff.php new file mode 100644 index 00000000..4feebdcb --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DB/SlowDBQuerySniff.php @@ -0,0 +1,86 @@ + array( + 'type' => 'warning', + 'message' => 'Detected usage of %s, possible slow query.', + 'keys' => array( + 'tax_query', + 'meta_query', + 'meta_key', + 'meta_value', + ), + ), + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.10.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + if ( $this->has_whitelist_comment( 'slow query', $stackPtr ) ) { + return; + } elseif ( $this->has_whitelist_comment( 'tax_query', $stackPtr ) ) { + return; + } + + return parent::process_token( $stackPtr ); + } + + /** + * Callback to process each confirmed key, to check value. + * This must be extended to add the logic to check assignment value. + * + * @param string $key Array index / key. + * @param mixed $val Assigned value. + * @param int $line Token line. + * @param array $group Group definition. + * @return mixed FALSE if no match, TRUE if matches, STRING if matches + * with custom error message passed to ->process(). + */ + public function callback( $key, $val, $line, $group ) { + return true; + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DateTime/CurrentTimeTimestampSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DateTime/CurrentTimeTimestampSniff.php new file mode 100644 index 00000000..180ae240 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DateTime/CurrentTimeTimestampSniff.php @@ -0,0 +1,174 @@ + => + */ + protected $target_functions = array( + 'current_time' => true, + ); + + /** + * Process the parameters of a matched function. + * + * @since 2.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + /* + * We already know there will be valid open & close parentheses as otherwise the parameter + * retrieval function call would have returned an empty array, so no additional checks needed. + */ + $open_parens = $this->phpcsFile->findNext( \T_OPEN_PARENTHESIS, $stackPtr ); + $close_parens = $this->tokens[ $open_parens ]['parenthesis_closer']; + + /* + * Check whether the first parameter is a timestamp format. + */ + for ( $i = $parameters[1]['start']; $i <= $parameters[1]['end']; $i++ ) { + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + if ( isset( Tokens::$textStringTokens[ $this->tokens[ $i ]['code'] ] ) ) { + $content_first = trim( $this->strip_quotes( $this->tokens[ $i ]['content'] ) ); + if ( 'U' !== $content_first && 'timestamp' !== $content_first ) { + // Most likely valid use of current_time(). + return; + } + + continue; + } + + if ( isset( Tokens::$heredocTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + /* + * If we're still here, we've encountered an unexpected token, like a variable or + * function call. Bow out as we can't determine the runtime value. + */ + return; + } + + $gmt_true = false; + + /* + * Check whether the second parameter, $gmt, is a set to `true` or `1`. + */ + if ( isset( $parameters[2] ) ) { + $content_second = ''; + if ( 'true' === $parameters[2]['raw'] || '1' === $parameters[2]['raw'] ) { + $content_second = $parameters[2]['raw']; + $gmt_true = true; + } else { + // Do a more extensive parameter check. + for ( $i = $parameters[2]['start']; $i <= $parameters[2]['end']; $i++ ) { + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + $content_second .= $this->tokens[ $i ]['content']; + } + + if ( 'true' === $content_second || '1' === $content_second ) { + $gmt_true = true; + } + } + } + + /* + * Non-UTC timestamp requested. + */ + if ( false === $gmt_true ) { + $this->phpcsFile->addWarning( + 'Calling current_time() with a $type of "timestamp" or "U" is strongly discouraged as it will not return a Unix (UTC) timestamp. Please consider using a non-timestamp format or otherwise refactoring this code.', + $stackPtr, + 'Requested' + ); + + return; + } + + /* + * UTC timestamp requested. Should use time() instead. + */ + $has_comment = $this->phpcsFile->findNext( Tokens::$commentTokens, ( $stackPtr + 1 ), ( $close_parens + 1 ) ); + $error = 'Don\'t use current_time() for retrieving a Unix (UTC) timestamp. Use time() instead. Found: %s'; + $error_code = 'RequestedUTC'; + + $code_snippet = "current_time( '" . $content_first . "'"; + if ( isset( $content_second ) ) { + $code_snippet .= ', ' . $content_second; + } + $code_snippet .= ' )'; + + if ( false !== $has_comment ) { + // If there are comments, we don't auto-fix as it would remove those comments. + $this->phpcsFile->addError( $error, $stackPtr, $error_code, array( $code_snippet ) ); + + return; + } + + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, $error_code, array( $code_snippet ) ); + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + for ( $i = ( $stackPtr + 1 ); $i < $close_parens; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->replaceToken( $stackPtr, 'time(' ); + $this->phpcsFile->fixer->endChangeset(); + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DateTime/RestrictedFunctionsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DateTime/RestrictedFunctionsSniff.php new file mode 100644 index 00000000..0da07019 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/DateTime/RestrictedFunctionsSniff.php @@ -0,0 +1,62 @@ + array( + 'type' => 'error', + 'message' => 'Using %s() and similar isn\'t allowed, instead use WP internal timezone support.', + 'functions' => array( + 'date_default_timezone_set', + ), + ), + + /* + * Use gmdate(), not date(). + * Don't rely on the current PHP time zone as it might have been changed by third party code. + * + * @link https://make.wordpress.org/core/2019/09/23/date-time-improvements-wp-5-3/ + * @link https://core.trac.wordpress.org/ticket/46438 + * @link https://github.com/WordPress/WordPress-Coding-Standards/issues/1713 + */ + 'date' => array( + 'type' => 'error', + 'message' => '%s() is affected by runtime timezone changes which can cause date/time to be incorrectly displayed. Use gmdate() instead.', + 'functions' => array( + 'date', + ), + ), + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Files/FileNameSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Files/FileNameSniff.php new file mode 100644 index 00000000..598bc39b --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Files/FileNameSniff.php @@ -0,0 +1,248 @@ + true, + 'class.wp-scripts.php' => true, + 'class.wp-styles.php' => true, + ); + + /** + * Unit test version of the historical exceptions in WP core. + * + * @since 0.11.0 + * + * @var array + */ + private $unittest_class_exceptions = array( + 'class.wp-dependencies.inc' => true, + 'class.wp-scripts.inc' => true, + 'class.wp-styles.inc' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + if ( \defined( '\PHP_CODESNIFFER_IN_TESTS' ) ) { + $this->class_exceptions = array_merge( $this->class_exceptions, $this->unittest_class_exceptions ); + } + + return array( + \T_OPEN_TAG, + \T_OPEN_TAG_WITH_ECHO, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + // Usage of `strip_quotes` is to ensure `stdin_path` passed by IDEs does not include quotes. + $file = $this->strip_quotes( $this->phpcsFile->getFileName() ); + if ( 'STDIN' === $file ) { + return; + } + + // Respect phpcs:disable comments as long as they are not accompanied by an enable (PHPCS 3.2+). + if ( \defined( '\T_PHPCS_DISABLE' ) && \defined( '\T_PHPCS_ENABLE' ) ) { + $i = -1; + while ( $i = $this->phpcsFile->findNext( \T_PHPCS_DISABLE, ( $i + 1 ) ) ) { + if ( empty( $this->tokens[ $i ]['sniffCodes'] ) + || isset( $this->tokens[ $i ]['sniffCodes']['WordPress'] ) + || isset( $this->tokens[ $i ]['sniffCodes']['WordPress.Files'] ) + || isset( $this->tokens[ $i ]['sniffCodes']['WordPress.Files.FileName'] ) + ) { + do { + $i = $this->phpcsFile->findNext( \T_PHPCS_ENABLE, ( $i + 1 ) ); + } while ( false !== $i + && ! empty( $this->tokens[ $i ]['sniffCodes'] ) + && ! isset( $this->tokens[ $i ]['sniffCodes']['WordPress'] ) + && ! isset( $this->tokens[ $i ]['sniffCodes']['WordPress.Files'] ) + && ! isset( $this->tokens[ $i ]['sniffCodes']['WordPress.Files.FileName'] ) ); + + if ( false === $i ) { + // The entire (rest of the) file is disabled. + return; + } + } + } + } + + $fileName = basename( $file ); + $expected = strtolower( str_replace( '_', '-', $fileName ) ); + + /* + * Generic check for lowercase hyphenated file names. + */ + if ( $fileName !== $expected && ( false === $this->is_theme || 1 !== preg_match( self::THEME_EXCEPTIONS_REGEX, $fileName ) ) ) { + $this->phpcsFile->addError( + 'Filenames should be all lowercase with hyphens as word separators. Expected %s, but found %s.', + 0, + 'NotHyphenatedLowercase', + array( $expected, $fileName ) + ); + } + unset( $expected ); + + /* + * Check files containing a class for the "class-" prefix and that the rest of + * the file name reflects the class name. + */ + if ( true === $this->strict_class_file_names ) { + $has_class = $this->phpcsFile->findNext( \T_CLASS, $stackPtr ); + if ( false !== $has_class && false === $this->is_test_class( $has_class ) ) { + $class_name = $this->phpcsFile->getDeclarationName( $has_class ); + $expected = 'class-' . strtolower( str_replace( '_', '-', $class_name ) ); + + if ( substr( $fileName, 0, -4 ) !== $expected && ! isset( $this->class_exceptions[ $fileName ] ) ) { + $this->phpcsFile->addError( + 'Class file names should be based on the class name with "class-" prepended. Expected %s, but found %s.', + 0, + 'InvalidClassFileName', + array( + $expected . '.php', + $fileName, + ) + ); + } + unset( $expected ); + } + } + + /* + * Check non-class files in "wp-includes" with a "@subpackage Template" tag for a "-template" suffix. + */ + if ( false !== strpos( $file, \DIRECTORY_SEPARATOR . 'wp-includes' . \DIRECTORY_SEPARATOR ) ) { + $subpackage_tag = $this->phpcsFile->findNext( \T_DOC_COMMENT_TAG, $stackPtr, null, false, '@subpackage' ); + if ( false !== $subpackage_tag ) { + $subpackage = $this->phpcsFile->findNext( \T_DOC_COMMENT_STRING, $subpackage_tag ); + if ( false !== $subpackage ) { + $fileName_end = substr( $fileName, -13 ); + $has_class = $this->phpcsFile->findNext( \T_CLASS, $stackPtr ); + + if ( ( 'Template' === trim( $this->tokens[ $subpackage ]['content'] ) + && $this->tokens[ $subpackage_tag ]['line'] === $this->tokens[ $subpackage ]['line'] ) + && ( ( ! \defined( '\PHP_CODESNIFFER_IN_TESTS' ) && '-template.php' !== $fileName_end ) + || ( \defined( '\PHP_CODESNIFFER_IN_TESTS' ) && '-template.inc' !== $fileName_end ) ) + && false === $has_class + ) { + $this->phpcsFile->addError( + 'Files containing template tags should have "-template" appended to the end of the file name. Expected %s, but found %s.', + 0, + 'InvalidTemplateTagFileName', + array( + substr( $fileName, 0, -4 ) . '-template.php', + $fileName, + ) + ); + } + } + } + } + + // Only run this sniff once per file, no need to run it again. + return ( $this->phpcsFile->numTokens + 1 ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/PrefixAllGlobalsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/PrefixAllGlobalsSniff.php new file mode 100644 index 00000000..8374faf6 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/PrefixAllGlobalsSniff.php @@ -0,0 +1,1046 @@ + true, + 'wp' => true, + '_' => true, + 'php' => true, // See #1728, the 'php' prefix is reserved by PHP itself. + ); + + /** + * Target prefixes after validation. + * + * All prefixes are lowercased for case-insensitive compare. + * + * @since 0.12.0 + * + * @var string[] + */ + private $validated_prefixes = array(); + + /** + * Target namespace prefixes after validation with regex indicator. + * + * All prefixes are lowercased for case-insensitive compare. + * If the prefix doesn't already contain a namespace separator, but does contain + * non-word characters, these will have been replaced with regex syntax to allow + * for namespace separators and the `is_regex` indicator will have been set to `true`. + * + * @since 1.2.0 + * + * @var array + */ + private $validated_namespace_prefixes = array(); + + /** + * Cache of previously set prefixes. + * + * Prevents having to do the same prefix validation over and over again. + * + * @since 0.12.0 + * + * @var string[] + */ + private $previous_prefixes = array(); + + /** + * A list of all PHP superglobals with the exception of $GLOBALS which is handled separately. + * + * @since 0.12.0 + * + * @var array + */ + protected $superglobals = array( + '_COOKIE' => true, + '_ENV' => true, + '_GET' => true, + '_FILES' => true, + '_POST' => true, + '_REQUEST' => true, + '_SERVER' => true, + '_SESSION' => true, + ); + + /** + * A list of core hooks that are allowed to be called by plugins and themes. + * + * @since 0.14.0 + * + * @var array + */ + protected $whitelisted_core_hooks = array( + 'widget_title' => true, + 'add_meta_boxes' => true, + ); + + /** + * A list of core constants that are allowed to be defined by plugins and themes. + * + * @since 1.0.0 + * + * Source: {@link https://core.trac.wordpress.org/browser/trunk/src/wp-includes/default-constants.php#L0} + * The constants are listed in the order they are found in the source file + * to make life easier for future updates. + * Only overrulable constants are listed, i.e. those defined within core within + * a `if ( ! defined() ) {}` wrapper. + * + * @var array + */ + protected $whitelisted_core_constants = array( + 'WP_MEMORY_LIMIT' => true, + 'WP_MAX_MEMORY_LIMIT' => true, + 'WP_CONTENT_DIR' => true, + 'WP_DEBUG' => true, + 'WP_DEBUG_DISPLAY' => true, + 'WP_DEBUG_LOG' => true, + 'WP_CACHE' => true, + 'SCRIPT_DEBUG' => true, + 'MEDIA_TRASH' => true, + 'SHORTINIT' => true, + 'WP_CONTENT_URL' => true, + 'WP_PLUGIN_DIR' => true, + 'WP_PLUGIN_URL' => true, + 'PLUGINDIR' => true, + 'WPMU_PLUGIN_DIR' => true, + 'WPMU_PLUGIN_URL' => true, + 'MUPLUGINDIR' => true, + 'COOKIEHASH' => true, + 'USER_COOKIE' => true, + 'PASS_COOKIE' => true, + 'AUTH_COOKIE' => true, + 'SECURE_AUTH_COOKIE' => true, + 'LOGGED_IN_COOKIE' => true, + 'TEST_COOKIE' => true, + 'COOKIEPATH' => true, + 'SITECOOKIEPATH' => true, + 'ADMIN_COOKIE_PATH' => true, + 'PLUGINS_COOKIE_PATH' => true, + 'COOKIE_DOMAIN' => true, + 'RECOVERY_MODE_COOKIE' => true, + 'FORCE_SSL_ADMIN' => true, + 'FORCE_SSL_LOGIN' => true, + 'AUTOSAVE_INTERVAL' => true, + 'EMPTY_TRASH_DAYS' => true, + 'WP_POST_REVISIONS' => true, + 'WP_CRON_LOCK_TIMEOUT' => true, + 'WP_DEFAULT_THEME' => true, + ); + + /** + * List of all PHP native functions. + * + * Using this list rather than a call to `function_exists()` prevents + * false negatives from user-defined functions when those would be + * autoloaded via a Composer autoload files directives. + * + * @var array + */ + private $built_in_functions; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 0.12.0 + * + * @return array + */ + public function register() { + // Get a list of all PHP native functions. + $all_functions = get_defined_functions(); + $this->built_in_functions = array_flip( $all_functions['internal'] ); + + // Set the sniff targets. + $targets = array( + \T_NAMESPACE => \T_NAMESPACE, + \T_FUNCTION => \T_FUNCTION, + \T_CONST => \T_CONST, + \T_VARIABLE => \T_VARIABLE, + \T_DOLLAR => \T_DOLLAR, // Variable variables. + \T_LIST => \T_LIST, + \T_OPEN_SHORT_ARRAY => \T_OPEN_SHORT_ARRAY, + ); + $targets += Tokens::$ooScopeTokens; // T_ANON_CLASS is only used for skipping over test classes. + + // Add function call target for hook names and constants defined using define(). + $parent = parent::register(); + if ( ! empty( $parent ) ) { + $targets[] = \T_STRING; + } + + return $targets; + } + + /** + * Groups of functions to restrict. + * + * @since 0.12.0 + * + * @return array + */ + public function getGroups() { + $this->target_functions = $this->hookInvokeFunctions; + unset( + $this->target_functions['do_action_deprecated'], + $this->target_functions['apply_filters_deprecated'] + ); + + $this->target_functions['define'] = true; + + return parent::getGroups(); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.12.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + /* + * Allow for whitelisting. + * + * Generally speaking a theme/plugin should *only* execute their own hooks, but there may be a + * good reason to execute a core hook. + * + * Similarly, newer PHP or WP functions or constants may need to be emulated for continued support + * of older PHP and WP versions. + */ + if ( $this->has_whitelist_comment( 'prefix', $stackPtr ) ) { + return; + } + + // Allow overruling the prefixes set in a ruleset via the command line. + $cl_prefixes = trim( PHPCSHelper::get_config_data( 'prefixes' ) ); + if ( ! empty( $cl_prefixes ) ) { + $this->prefixes = array_filter( array_map( 'trim', explode( ',', $cl_prefixes ) ) ); + } + + $this->prefixes = $this->merge_custom_array( $this->prefixes, array(), false ); + if ( empty( $this->prefixes ) ) { + // No prefixes passed, nothing to do. + return; + } + + $this->validate_prefixes(); + if ( empty( $this->validated_prefixes ) ) { + // No _valid_ prefixes passed, nothing to do. + return; + } + + // Ignore test classes. + if ( isset( Tokens::$ooScopeTokens[ $this->tokens[ $stackPtr ]['code'] ] ) + && true === $this->is_test_class( $stackPtr ) + ) { + if ( $this->tokens[ $stackPtr ]['scope_condition'] === $stackPtr && isset( $this->tokens[ $stackPtr ]['scope_closer'] ) ) { + // Skip forward to end of test class. + return $this->tokens[ $stackPtr ]['scope_closer']; + } + return; + } + + if ( \T_ANON_CLASS === $this->tokens[ $stackPtr ]['code'] ) { + // Token was only registered to allow skipping over test classes. + return; + } + + if ( \T_STRING === $this->tokens[ $stackPtr ]['code'] ) { + // Disallow excluding function groups for this sniff. + $this->exclude = array(); + + return parent::process_token( $stackPtr ); + + } elseif ( \T_DOLLAR === $this->tokens[ $stackPtr ]['code'] ) { + + return $this->process_variable_variable( $stackPtr ); + + } elseif ( \T_VARIABLE === $this->tokens[ $stackPtr ]['code'] ) { + + return $this->process_variable_assignment( $stackPtr ); + + } elseif ( \T_LIST === $this->tokens[ $stackPtr ]['code'] + || \T_OPEN_SHORT_ARRAY === $this->tokens[ $stackPtr ]['code'] + ) { + return $this->process_list_assignment( $stackPtr ); + + } elseif ( \T_NAMESPACE === $this->tokens[ $stackPtr ]['code'] ) { + $namespace_name = $this->get_declared_namespace_name( $stackPtr ); + + if ( false === $namespace_name || '' === $namespace_name || '\\' === $namespace_name ) { + return; + } + + foreach ( $this->validated_namespace_prefixes as $key => $prefix_info ) { + if ( false === $prefix_info['is_regex'] ) { + if ( stripos( $namespace_name, $prefix_info['prefix'] ) === 0 ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Prefix all globals: allowed prefixes', $key ); + return; + } + } else { + // Ok, so this prefix should be used as a regex. + $regex = '`^' . $prefix_info['prefix'] . '`i'; + if ( preg_match( $regex, $namespace_name ) > 0 ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Prefix all globals: allowed prefixes', $key ); + return; + } + } + } + + // Still here ? In that case, we have a non-prefixed namespace name. + $recorded = $this->phpcsFile->addError( + self::ERROR_MSG, + $stackPtr, + 'NonPrefixedNamespaceFound', + array( + 'Namespaces declared', + $namespace_name, + ) + ); + + if ( true === $recorded ) { + $this->record_potential_prefix_metric( $stackPtr, $namespace_name ); + } + + return; + + } else { + + // Namespaced methods, classes and constants do not need to be prefixed. + $namespace = $this->determine_namespace( $stackPtr ); + if ( '' !== $namespace && '\\' !== $namespace ) { + return; + } + + $item_name = ''; + $error_text = 'Unknown syntax used'; + $error_code = 'NonPrefixedSyntaxFound'; + + switch ( $this->tokens[ $stackPtr ]['type'] ) { + case 'T_FUNCTION': + // Methods in a class do not need to be prefixed. + if ( $this->phpcsFile->hasCondition( $stackPtr, Tokens::$ooScopeTokens ) === true ) { + return; + } + + if ( $this->is_function_deprecated( $this->phpcsFile, $stackPtr ) === true ) { + /* + * Deprecated functions don't have to comply with the naming conventions, + * otherwise functions deprecated in favour of a function with a compliant + * name would still trigger an error. + */ + return; + } + + $item_name = $this->phpcsFile->getDeclarationName( $stackPtr ); + if ( isset( $this->built_in_functions[ $item_name ] ) ) { + // Backfill for PHP native function. + return; + } + + $error_text = 'Functions declared in the global namespace'; + $error_code = 'NonPrefixedFunctionFound'; + break; + + case 'T_CLASS': + case 'T_INTERFACE': + case 'T_TRAIT': + $item_name = $this->phpcsFile->getDeclarationName( $stackPtr ); + $error_text = 'Classes declared'; + $error_code = 'NonPrefixedClassFound'; + + switch ( $this->tokens[ $stackPtr ]['type'] ) { + case 'T_CLASS': + if ( class_exists( '\\' . $item_name, false ) ) { + // Backfill for PHP native class. + return; + } + break; + + case 'T_INTERFACE': + if ( interface_exists( '\\' . $item_name, false ) ) { + // Backfill for PHP native interface. + return; + } + + $error_text = 'Interfaces declared'; + $error_code = 'NonPrefixedInterfaceFound'; + break; + + case 'T_TRAIT': + // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.trait_existsFound + if ( function_exists( '\trait_exists' ) && trait_exists( '\\' . $item_name, false ) ) { + // Backfill for PHP native trait. + return; + } + + $error_text = 'Traits declared'; + $error_code = 'NonPrefixedTraitFound'; + break; + + default: + // Left empty on purpose. + break; + } + + break; + + case 'T_CONST': + // Constants in a class do not need to be prefixed. + if ( true === $this->is_class_constant( $stackPtr ) ) { + return; + } + + $constant_name_ptr = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true, null, true ); + if ( false === $constant_name_ptr ) { + // Live coding. + return; + } + + $item_name = $this->tokens[ $constant_name_ptr ]['content']; + if ( \defined( '\\' . $item_name ) ) { + // Backfill for PHP native constant. + return; + } + + if ( isset( $this->whitelisted_core_constants[ $item_name ] ) ) { + // Defining a WP Core constant intended for overruling. + return; + } + + $error_text = 'Global constants defined'; + $error_code = 'NonPrefixedConstantFound'; + break; + + default: + // Left empty on purpose. + break; + + } + + if ( empty( $item_name ) || $this->is_prefixed( $stackPtr, $item_name ) === true ) { + return; + } + + $recorded = $this->phpcsFile->addError( + self::ERROR_MSG, + $stackPtr, + $error_code, + array( + $error_text, + $item_name, + ) + ); + + if ( true === $recorded ) { + $this->record_potential_prefix_metric( $stackPtr, $item_name ); + } + } + } + + /** + * Handle variable variables defined in the global namespace. + * + * @since 0.12.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + protected function process_variable_variable( $stackPtr ) { + static $indicators = array( + \T_OPEN_CURLY_BRACKET => true, + \T_VARIABLE => true, + ); + + // Is this a variable variable ? + // Not concerned with nested ones as those will be recognized on their own token. + $next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true, null, true ); + if ( false === $next_non_empty || ! isset( $indicators[ $this->tokens[ $next_non_empty ]['code'] ] ) ) { + return; + } + + if ( \T_OPEN_CURLY_BRACKET === $this->tokens[ $next_non_empty ]['code'] + && isset( $this->tokens[ $next_non_empty ]['bracket_closer'] ) + ) { + // Skip over the variable part. + $next_non_empty = $this->tokens[ $next_non_empty ]['bracket_closer']; + } + + $maybe_assignment = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $next_non_empty + 1 ), null, true, null, true ); + + while ( false !== $maybe_assignment + && \T_OPEN_SQUARE_BRACKET === $this->tokens[ $maybe_assignment ]['code'] + && isset( $this->tokens[ $maybe_assignment ]['bracket_closer'] ) + ) { + $maybe_assignment = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $this->tokens[ $maybe_assignment ]['bracket_closer'] + 1 ), + null, + true, + null, + true + ); + } + + if ( false === $maybe_assignment ) { + return; + } + + if ( ! isset( Tokens::$assignmentTokens[ $this->tokens[ $maybe_assignment ]['code'] ] ) ) { + // Not an assignment. + return; + } + + $error = self::ERROR_MSG; + + /* + * Local variable variables in a function do not need to be prefixed. + * But a variable variable could evaluate to the name of an imported global + * variable. + * Not concerned with imported variable variables (global.. ) as that has been + * forbidden since PHP 7.0. Presuming cross-version code and if not, that + * is for the PHPCompatibility standard to detect. + */ + if ( $this->phpcsFile->hasCondition( $stackPtr, array( \T_FUNCTION, \T_CLOSURE ) ) === true ) { + $condition = $this->phpcsFile->getCondition( $stackPtr, \T_FUNCTION ); + if ( false === $condition ) { + $condition = $this->phpcsFile->getCondition( $stackPtr, \T_CLOSURE ); + } + + $has_global = $this->phpcsFile->findPrevious( \T_GLOBAL, ( $stackPtr - 1 ), $this->tokens[ $condition ]['scope_opener'] ); + if ( false === $has_global ) { + // No variable import happening. + return; + } + + $error = 'Variable variable which could potentially override an imported global variable detected. ' . $error; + } + + $variable_name = $this->phpcsFile->getTokensAsString( $stackPtr, ( ( $next_non_empty - $stackPtr ) + 1 ) ); + + // Still here ? In that case, the variable name should be prefixed. + $recorded = $this->phpcsFile->addWarning( + $error, + $stackPtr, + 'NonPrefixedVariableFound', + array( + 'Global variables defined', + $variable_name, + ) + ); + + if ( true === $recorded ) { + $this->record_potential_prefix_metric( $stackPtr, $variable_name ); + } + + // Skip over the variable part of the variable. + return ( $next_non_empty + 1 ); + } + + /** + * Check that defined global variables are prefixed. + * + * @since 0.12.0 + * @since 2.2.0 Added $in_list parameter. + * + * @param int $stackPtr The position of the current token in the stack. + * @param bool $in_list Whether or not this is a variable in a list assignment. + * Defaults to false. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + protected function process_variable_assignment( $stackPtr, $in_list = false ) { + /* + * We're only concerned with variables which are being defined. + * `is_assigment()` will not recognize property assignments, which is good in this case. + * However it will also not recognize $b in `foreach( $a as $b )` as an assignment, so + * we need a separate check for that. + */ + if ( false === $in_list + && false === $this->is_assignment( $stackPtr ) + && false === $this->is_foreach_as( $stackPtr ) + ) { + return; + } + + $is_error = true; + $variable_name = substr( $this->tokens[ $stackPtr ]['content'], 1 ); // Strip the dollar sign. + + // Bow out early if we know for certain no prefix is needed. + if ( $this->variable_prefixed_or_whitelisted( $stackPtr, $variable_name ) === true ) { + return; + } + + if ( 'GLOBALS' === $variable_name ) { + $array_open = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true, null, true ); + if ( false === $array_open || \T_OPEN_SQUARE_BRACKET !== $this->tokens[ $array_open ]['code'] ) { + // Live coding or something very silly. + return; + } + + $array_key = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $array_open + 1 ), null, true, null, true ); + if ( false === $array_key ) { + // No key found, nothing to do. + return; + } + + $stackPtr = $array_key; + $variable_name = $this->strip_quotes( $this->tokens[ $array_key ]['content'] ); + + // Check whether a prefix is needed. + if ( isset( Tokens::$stringTokens[ $this->tokens[ $array_key ]['code'] ] ) + && $this->variable_prefixed_or_whitelisted( $stackPtr, $variable_name ) === true + ) { + return; + } + + if ( \T_DOUBLE_QUOTED_STRING === $this->tokens[ $array_key ]['code'] ) { + // If the array key is a double quoted string, try again with only + // the part before the first variable (if any). + $exploded = explode( '$', $variable_name ); + $first = rtrim( $exploded[0], '{' ); + if ( '' !== $first ) { + if ( $this->variable_prefixed_or_whitelisted( $array_key, $first ) === true ) { + return; + } + } else { + // If the first part was dynamic, throw a warning. + $is_error = false; + } + } elseif ( ! isset( Tokens::$stringTokens[ $this->tokens[ $array_key ]['code'] ] ) ) { + // Dynamic array key, throw a warning. + $is_error = false; + } + } else { + // Function parameters do not need to be prefixed. + if ( false === $in_list && isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + foreach ( $this->tokens[ $stackPtr ]['nested_parenthesis'] as $opener => $closer ) { + if ( isset( $this->tokens[ $opener ]['parenthesis_owner'] ) + && ( \T_FUNCTION === $this->tokens[ $this->tokens[ $opener ]['parenthesis_owner'] ]['code'] + || \T_CLOSURE === $this->tokens[ $this->tokens[ $opener ]['parenthesis_owner'] ]['code'] ) + ) { + return; + } + } + unset( $opener, $closer ); + } + + // Properties in a class do not need to be prefixed. + if ( false === $in_list && true === $this->is_class_property( $stackPtr ) ) { + return; + } + + // Local variables in a function do not need to be prefixed unless they are being imported. + if ( $this->phpcsFile->hasCondition( $stackPtr, array( \T_FUNCTION, \T_CLOSURE ) ) === true ) { + $condition = $this->phpcsFile->getCondition( $stackPtr, \T_FUNCTION ); + if ( false === $condition ) { + $condition = $this->phpcsFile->getCondition( $stackPtr, \T_CLOSURE ); + } + + $has_global = $this->phpcsFile->findPrevious( \T_GLOBAL, ( $stackPtr - 1 ), $this->tokens[ $condition ]['scope_opener'] ); + if ( false === $has_global ) { + // No variable import happening. + return; + } + + // Ok, this may be an imported global variable. + $end_of_statement = $this->phpcsFile->findNext( \T_SEMICOLON, ( $has_global + 1 ) ); + if ( false === $end_of_statement ) { + // No semi-colon - live coding. + return; + } + + for ( $ptr = ( $has_global + 1 ); $ptr <= $end_of_statement; $ptr++ ) { + // Move the stack pointer to the next variable. + $ptr = $this->phpcsFile->findNext( \T_VARIABLE, $ptr, $end_of_statement, false, null, true ); + + if ( false === $ptr ) { + // Reached the end of the global statement without finding the variable, + // so this must be a local variable. + return; + } + + if ( substr( $this->tokens[ $ptr ]['content'], 1 ) === $variable_name ) { + break; + } + } + + unset( $condition, $has_global, $end_of_statement, $ptr, $imported ); + + } + } + + // Still here ? In that case, the variable name should be prefixed. + $recorded = $this->addMessage( + self::ERROR_MSG, + $stackPtr, + $is_error, + 'NonPrefixedVariableFound', + array( + 'Global variables defined', + '$' . $variable_name, + ) + ); + + if ( true === $recorded ) { + $this->record_potential_prefix_metric( $stackPtr, $variable_name ); + } + } + + /** + * Check that global variables declared via a list construct are prefixed. + * + * @internal No need to take special measures for nested lists. Nested or not, + * each list part can only contain one variable being written to. + * + * @since 2.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + protected function process_list_assignment( $stackPtr ) { + $list_open_close = $this->find_list_open_close( $stackPtr ); + if ( false === $list_open_close ) { + // Short array, not short list. + return; + } + + $var_pointers = $this->get_list_variables( $stackPtr, $list_open_close ); + foreach ( $var_pointers as $ptr ) { + $this->process_variable_assignment( $ptr, true ); + } + + // No need to re-examine these variables. + return $list_open_close['closer']; + } + + /** + * Process the parameters of a matched function. + * + * @since 0.12.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + + // No matter whether it is a constant definition or a hook call, both use the first parameter. + if ( ! isset( $parameters[1] ) ) { + return; + } + + $is_error = true; + $raw_content = $this->strip_quotes( $parameters[1]['raw'] ); + + if ( ( 'define' !== $matched_content + && isset( $this->whitelisted_core_hooks[ $raw_content ] ) ) + || ( 'define' === $matched_content + && isset( $this->whitelisted_core_constants[ $raw_content ] ) ) + ) { + return; + } + + if ( $this->is_prefixed( $parameters[1]['start'], $raw_content ) === true ) { + return; + } else { + // This may be a dynamic hook/constant name. + $first_non_empty = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $parameters[1]['start'], + ( $parameters[1]['end'] + 1 ), + true + ); + + if ( false === $first_non_empty ) { + return; + } + + $first_non_empty_content = $this->strip_quotes( $this->tokens[ $first_non_empty ]['content'] ); + + // Try again with just the first token if it's a text string. + if ( isset( Tokens::$stringTokens[ $this->tokens[ $first_non_empty ]['code'] ] ) + && $this->is_prefixed( $parameters[1]['start'], $first_non_empty_content ) === true + ) { + return; + } + + if ( \T_DOUBLE_QUOTED_STRING === $this->tokens[ $first_non_empty ]['code'] ) { + // If the first part of the parameter is a double quoted string, try again with only + // the part before the first variable (if any). + $exploded = explode( '$', $first_non_empty_content ); + $first = rtrim( $exploded[0], '{' ); + if ( '' !== $first ) { + if ( $this->is_prefixed( $parameters[1]['start'], $first ) === true ) { + return; + } + } else { + // Start of hook/constant name is dynamic, throw a warning. + $is_error = false; + } + } elseif ( ! isset( Tokens::$stringTokens[ $this->tokens[ $first_non_empty ]['code'] ] ) ) { + // Dynamic hook/constant name, throw a warning. + $is_error = false; + } + } + + if ( 'define' === $matched_content ) { + if ( \defined( '\\' . $raw_content ) ) { + // Backfill for PHP native constant. + return; + } + + if ( strpos( $raw_content, '\\' ) !== false ) { + // Namespaced or unreachable constant. + return; + } + + $data = array( 'Global constants defined' ); + $error_code = 'NonPrefixedConstantFound'; + if ( false === $is_error ) { + $error_code = 'VariableConstantNameFound'; + } + } else { + $data = array( 'Hook names invoked' ); + $error_code = 'NonPrefixedHooknameFound'; + if ( false === $is_error ) { + $error_code = 'DynamicHooknameFound'; + } + } + + $data[] = $raw_content; + + $recorded = $this->addMessage( self::ERROR_MSG, $first_non_empty, $is_error, $error_code, $data ); + + if ( true === $recorded ) { + $this->record_potential_prefix_metric( $stackPtr, $raw_content ); + } + } + + /** + * Check if a function/class/constant/variable name is prefixed with one of the expected prefixes. + * + * @since 0.12.0 + * @since 0.14.0 Allows for other non-word characters as well as underscores to better support hook names. + * @since 1.0.0 Does not require a word seperator anymore after a prefix. + * This allows for improved code style independent checking, + * i.e. allows for camelCase naming and the likes. + * @since 1.0.1 - Added $stackPtr parameter. + * - The function now also records metrics about the prefixes encountered. + * + * @param int $stackPtr The position of the token to record the metric against. + * @param string $name Name to check for a prefix. + * + * @return bool True when the name is one of the prefixes or starts with an allowed prefix. + * False otherwise. + */ + private function is_prefixed( $stackPtr, $name ) { + foreach ( $this->validated_prefixes as $prefix ) { + if ( stripos( $name, $prefix ) === 0 ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Prefix all globals: allowed prefixes', $prefix ); + return true; + } + } + + return false; + } + + /** + * Check if a variable name might need a prefix. + * + * Prefix is not needed for: + * - superglobals, + * - WP native globals, + * - variables which are already prefixed. + * + * @since 0.12.0 + * @since 1.0.1 Added $stackPtr parameter. + * + * @param int $stackPtr The position of the token to record the metric against. + * @param string $name Variable name without the dollar sign. + * + * @return bool True if the variable name is whitelisted or already prefixed. + * False otherwise. + */ + private function variable_prefixed_or_whitelisted( $stackPtr, $name ) { + // Ignore superglobals and WP global variables. + if ( isset( $this->superglobals[ $name ] ) || isset( $this->wp_globals[ $name ] ) ) { + return true; + } + + return $this->is_prefixed( $stackPtr, $name ); + } + + /** + * Validate an array of prefixes as passed through a custom property or via the command line. + * + * Checks that the prefix: + * - is not one of the blacklisted ones. + * - complies with the PHP rules for valid function, class, variable, constant names. + * + * @since 0.12.0 + */ + private function validate_prefixes() { + if ( $this->previous_prefixes === $this->prefixes ) { + return; + } + + // Set the cache *before* validation so as to not break the above compare. + $this->previous_prefixes = $this->prefixes; + + // Validate the passed prefix(es). + $prefixes = array(); + $ns_prefixes = array(); + foreach ( $this->prefixes as $key => $prefix ) { + $prefixLC = strtolower( $prefix ); + + if ( isset( $this->prefix_blacklist[ $prefixLC ] ) ) { + $this->phpcsFile->addError( + 'The "%s" prefix is not allowed.', + 0, + 'ForbiddenPrefixPassed', + array( $prefix ) + ); + continue; + } + + $prefix_length = strlen( $prefix ); + if ( function_exists( 'iconv_strlen' ) ) { + $prefix_length = iconv_strlen( $prefix, $this->phpcsFile->config->encoding ); + } + + if ( $prefix_length < self::MIN_PREFIX_LENGTH ) { + $this->phpcsFile->addError( + 'The "%s" prefix is too short. Short prefixes are not unique enough and may cause name collisions with other code.', + 0, + 'ShortPrefixPassed', + array( $prefix ) + ); + continue; + } + + // Validate the prefix against characters allowed for function, class, constant names etc. + if ( preg_match( '`^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff\\\\]*$`', $prefix ) !== 1 ) { + $this->phpcsFile->addWarning( + 'The "%s" prefix is not a valid namespace/function/class/variable/constant prefix in PHP.', + 0, + 'InvalidPrefixPassed', + array( $prefix ) + ); + } + + // Lowercase the prefix to allow for direct compare. + $prefixes[ $key ] = $prefixLC; + + /* + * Replace non-word characters in the prefix with a regex snippet, but only if the + * string doesn't already contain namespace separators. + */ + $is_regex = false; + if ( strpos( $prefix, '\\' ) === false && preg_match( '`[_\W]`', $prefix ) > 0 ) { + $prefix = preg_replace( '`([_\W])`', '[\\\\\\\\$1]', $prefixLC ); + $is_regex = true; + } + + $ns_prefixes[ $prefixLC ] = array( + 'prefix' => $prefix, + 'is_regex' => $is_regex, + ); + } + + // Set the validated prefixes caches. + $this->validated_prefixes = $prefixes; + $this->validated_namespace_prefixes = $ns_prefixes; + } + + /** + * Record the "potential prefix" metric. + * + * @since 1.0.1 + * + * @param int $stackPtr The position of the token to record the metric against. + * @param string $construct_name Name of the global construct to try and distill a potential prefix from. + * + * @return void + */ + private function record_potential_prefix_metric( $stackPtr, $construct_name ) { + if ( preg_match( '`^([A-Z]*[a-z0-9]*+)`', ltrim( $construct_name, '\$_' ), $matches ) > 0 + && isset( $matches[1] ) && '' !== $matches[1] + ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Prefix all globals: potential prefixes - start of non-prefixed construct', strtolower( $matches[1] ) ); + } + } +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidFunctionNameSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidFunctionNameSniff.php new file mode 100644 index 00000000..d8826ce1 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidFunctionNameSniff.php @@ -0,0 +1,187 @@ +getDeclarationName( $stackPtr ); + + if ( ! isset( $functionName ) ) { + // Ignore closures. + return; + } + + if ( '' === ltrim( $functionName, '_' ) ) { + // Ignore special functions, like __(). + return; + } + + $functionNameLc = strtolower( $functionName ); + + // Is this a magic function ? I.e., it is prefixed with "__" ? + // Outside class scope this basically just means __autoload(). + if ( 0 === strpos( $functionName, '__' ) ) { + $magicPart = substr( $functionNameLc, 2 ); + if ( isset( $this->magicFunctions[ $magicPart ] ) ) { + return; + } + + $error = 'Function name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $errorData = array( $functionName ); + $phpcsFile->addError( $error, $stackPtr, 'FunctionDoubleUnderscore', $errorData ); + } + + if ( $functionNameLc !== $functionName ) { + $error = 'Function name "%s" is not in snake case format, try "%s"'; + $errorData = array( + $functionName, + Sniff::get_snake_case_name_suggestion( $functionName ), + ); + $phpcsFile->addError( $error, $stackPtr, 'FunctionNameInvalid', $errorData ); + } + } + + /** + * Processes the tokens within the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * @param int $currScope The position of the current scope. + * + * @return void + */ + protected function processTokenWithinScope( File $phpcsFile, $stackPtr, $currScope ) { + + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[ $stackPtr ]['conditions']; + end( $conditions ); + $deepestScope = key( $conditions ); + if ( $deepestScope !== $currScope ) { + return; + } + + if ( Sniff::is_function_deprecated( $phpcsFile, $stackPtr ) === true ) { + /* + * Deprecated functions don't have to comply with the naming conventions, + * otherwise functions deprecated in favour of a function with a compliant + * name would still trigger an error. + */ + return; + } + + $methodName = $phpcsFile->getDeclarationName( $stackPtr ); + + if ( ! isset( $methodName ) ) { + // Ignore closures. + return; + } + + $className = $phpcsFile->getDeclarationName( $currScope ); + if ( isset( $className ) === false ) { + $className = '[Anonymous Class]'; + } + + $methodNameLc = strtolower( $methodName ); + $classNameLc = strtolower( $className ); + + // Ignore special functions. + if ( '' === ltrim( $methodName, '_' ) ) { + return; + } + + // PHP4 constructors are allowed to break our rules. + if ( $methodNameLc === $classNameLc ) { + return; + } + + // PHP4 destructors are allowed to break our rules. + if ( '_' . $classNameLc === $methodNameLc ) { + return; + } + + $extended = $phpcsFile->findExtendedClassName( $currScope ); + $interfaces = $phpcsFile->findImplementedInterfaceNames( $currScope ); + + // If this is a child class or interface implementation, it may have to use camelCase or double underscores. + if ( ! empty( $extended ) || ! empty( $interfaces ) ) { + return; + } + + // Is this a magic method ? I.e. is it prefixed with "__" ? + if ( 0 === strpos( $methodName, '__' ) ) { + $magicPart = substr( $methodNameLc, 2 ); + if ( isset( $this->magicMethods[ $magicPart ] ) ) { + return; + } + + $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $errorData = array( $className . '::' . $methodName ); + $phpcsFile->addError( $error, $stackPtr, 'MethodDoubleUnderscore', $errorData ); + } + + // Check for all lowercase. + if ( $methodNameLc !== $methodName ) { + $error = 'Method name "%s" in class %s is not in snake case format, try "%s"'; + $errorData = array( + $methodName, + $className, + Sniff::get_snake_case_name_suggestion( $methodName ), + ); + $phpcsFile->addError( $error, $stackPtr, 'MethodNameInvalid', $errorData ); + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidHookNameSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidHookNameSniff.php new file mode 100644 index 00000000..da62331d --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidHookNameSniff.php @@ -0,0 +1,289 @@ + + * + * + * + * + * + * Provide several extra delimiters as one string: + * + * + * + * + * + * + * @var string + */ + public $additionalWordDelimiters = ''; + + /** + * Regular expression to test for correct punctuation of a hook name. + * + * The placeholder will be replaced by potentially provided additional + * word delimiters in the `prepare_regex()` method. + * + * @var string + */ + protected $punctuation_regex = '`[^\w%s]`'; + + /** + * Groups of functions to restrict. + * + * @since 0.11.0 + * + * @return array + */ + public function getGroups() { + $this->target_functions = $this->hookInvokeFunctions; + + // No need to examine the names of deprecated hooks. + unset( + $this->target_functions['do_action_deprecated'], + $this->target_functions['apply_filters_deprecated'] + ); + + return parent::getGroups(); + } + + /** + * Process the parameters of a matched function. + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + + $regex = $this->prepare_regex(); + + $case_errors = 0; + $underscores = 0; + $content = array(); + $expected = array(); + + for ( $i = $parameters[1]['start']; $i <= $parameters[1]['end']; $i++ ) { + // Skip past comment tokens. + if ( isset( Tokens::$commentTokens[ $this->tokens[ $i ]['code'] ] ) !== false ) { + continue; + } + + $content[ $i ] = $this->tokens[ $i ]['content']; + $expected[ $i ] = $this->tokens[ $i ]['content']; + + // Skip past potential variable array access: $var['Key']. + if ( \T_VARIABLE === $this->tokens[ $i ]['code'] ) { + do { + $open_bracket = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $i + 1 ), null, true ); + if ( false === $open_bracket + || \T_OPEN_SQUARE_BRACKET !== $this->tokens[ $open_bracket ]['code'] + || ! isset( $this->tokens[ $open_bracket ]['bracket_closer'] ) + ) { + continue 2; + } + + $i = $this->tokens[ $open_bracket ]['bracket_closer']; + + } while ( isset( $this->tokens[ $i ] ) && $i <= $parameters[1]['end'] ); + + continue; + } + + // Skip past non-string tokens. + if ( isset( Tokens::$stringTokens[ $this->tokens[ $i ]['code'] ] ) === false ) { + continue; + } + + $string = $this->strip_quotes( $this->tokens[ $i ]['content'] ); + + /* + * Here be dragons - a double quoted string can contain extrapolated variables + * which don't have to comply with these rules. + */ + if ( \T_DOUBLE_QUOTED_STRING === $this->tokens[ $i ]['code'] ) { + $transform = $this->transform_complex_string( $string, $regex ); + $case_transform = $this->transform_complex_string( $string, $regex, 'case' ); + $punct_transform = $this->transform_complex_string( $string, $regex, 'punctuation' ); + } else { + $transform = $this->transform( $string, $regex ); + $case_transform = $this->transform( $string, $regex, 'case' ); + $punct_transform = $this->transform( $string, $regex, 'punctuation' ); + } + + if ( $string === $transform ) { + continue; + } + + if ( \T_DOUBLE_QUOTED_STRING === $this->tokens[ $i ]['code'] ) { + $expected[ $i ] = '"' . $transform . '"'; + } else { + $expected[ $i ] = '\'' . $transform . '\''; + } + + if ( $string !== $case_transform ) { + $case_errors++; + } + if ( $string !== $punct_transform ) { + $underscores++; + } + } + + $first_non_empty = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $parameters[1]['start'], + ( $parameters[1]['end'] + 1 ), + true + ); + + $data = array( + trim( implode( '', $expected ) ), + trim( implode( '', $content ) ), + ); + + if ( $case_errors > 0 ) { + $error = 'Hook names should be lowercase. Expected: %s, but found: %s.'; + $this->phpcsFile->addError( $error, $first_non_empty, 'NotLowercase', $data ); + } + if ( $underscores > 0 ) { + $error = 'Words in hook names should be separated using underscores. Expected: %s, but found: %s.'; + $this->phpcsFile->addWarning( $error, $first_non_empty, 'UseUnderscores', $data ); + } + } + + /** + * Prepare the punctuation regular expression. + * + * Merges the existing regular expression with potentially provided extra word delimiters to allow. + * This is done 'late' and for each found token as otherwise inline `phpcs:set` directives + * would be ignored. + * + * @return string + */ + protected function prepare_regex() { + $extra = ''; + if ( '' !== $this->additionalWordDelimiters && \is_string( $this->additionalWordDelimiters ) ) { + $extra = preg_quote( $this->additionalWordDelimiters, '`' ); + } + + return sprintf( $this->punctuation_regex, $extra ); + } + + /** + * Transform an arbitrary string to lowercase and replace punctuation and spaces with underscores. + * + * @param string $string The target string. + * @param string $regex The punctuation regular expression to use. + * @param string $transform_type Whether to a partial or complete transform. + * Valid values are: 'full', 'case', 'punctuation'. + * @return string + */ + protected function transform( $string, $regex, $transform_type = 'full' ) { + + switch ( $transform_type ) { + case 'case': + return strtolower( $string ); + + case 'punctuation': + return preg_replace( $regex, '_', $string ); + + case 'full': + default: + return preg_replace( $regex, '_', strtolower( $string ) ); + } + } + + /** + * Transform a complex string which may contain variable extrapolation. + * + * @param string $string The target string. + * @param string $regex The punctuation regular expression to use. + * @param string $transform_type Whether to a partial or complete transform. + * Valid values are: 'full', 'case', 'punctuation'. + * @return string + */ + protected function transform_complex_string( $string, $regex, $transform_type = 'full' ) { + $output = preg_split( '`([\{\}\$\[\] ])`', $string, -1, \PREG_SPLIT_DELIM_CAPTURE ); + + $is_variable = false; + $has_braces = false; + $braces = 0; + + foreach ( $output as $i => $part ) { + if ( \in_array( $part, array( '$', '{' ), true ) ) { + $is_variable = true; + if ( '{' === $part ) { + $has_braces = true; + $braces++; + } + continue; + } + + if ( true === $is_variable ) { + if ( '[' === $part ) { + $has_braces = true; + $braces++; + } + if ( \in_array( $part, array( '}', ']' ), true ) ) { + $braces--; + } + if ( false === $has_braces && ' ' === $part ) { + $is_variable = false; + $output[ $i ] = $this->transform( $part, $regex, $transform_type ); + } + + if ( ( true === $has_braces && 0 === $braces ) && false === \in_array( $output[ ( $i + 1 ) ], array( '{', '[' ), true ) ) { + $has_braces = false; + $is_variable = false; + } + continue; + } + + $output[ $i ] = $this->transform( $part, $regex, $transform_type ); + } + + return implode( '', $output ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php new file mode 100644 index 00000000..caedae8b --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php @@ -0,0 +1,208 @@ + true, + ); + + /** + * Array of reserved post type names which can not be used by themes and plugins. + * + * @since 2.2.0 + * + * @var array + */ + protected $reserved_names = array( + 'post' => true, + 'page' => true, + 'attachment' => true, + 'revision' => true, + 'nav_menu_item' => true, + 'custom_css' => true, + 'customize_changeset' => true, + 'oembed_cache' => true, + 'user_request' => true, + 'wp_block' => true, + 'action' => true, + 'author' => true, + 'order' => true, + 'theme' => true, + ); + + /** + * All valid tokens for in the first parameter of register_post_type(). + * + * Set in `register()`. + * + * @since 2.2.0 + * + * @var string + */ + private $valid_tokens = array(); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 2.2.0 + * + * @return array + */ + public function register() { + $this->valid_tokens = Tokens::$textStringTokens + Tokens::$heredocTokens + Tokens::$emptyTokens; + return parent::register(); + } + + /** + * Process the parameter of a matched function. + * + * Errors on invalid post type names when reserved keywords are used, + * the post type is too long, or contains invalid characters. + * + * @since 2.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param array $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + + $string_pos = $this->phpcsFile->findNext( Tokens::$textStringTokens, $parameters[1]['start'], ( $parameters[1]['end'] + 1 ) ); + $has_invalid_tokens = $this->phpcsFile->findNext( $this->valid_tokens, $parameters[1]['start'], ( $parameters[1]['end'] + 1 ), true ); + if ( false !== $has_invalid_tokens || false === $string_pos ) { + // Check for non string based slug parameter (we cannot determine if this is valid). + $this->phpcsFile->addWarning( + 'The post type slug is not a string literal. It is not possible to automatically determine the validity of this slug. Found: %s.', + $stackPtr, + 'NotStringLiteral', + array( + $parameters[1]['raw'], + ), + 3 + ); + return; + } + + $post_type = $this->strip_quotes( $this->tokens[ $string_pos ]['content'] ); + + if ( strlen( $post_type ) === 0 ) { + // Error for using empty slug. + $this->phpcsFile->addError( + 'register_post_type() called without a post type slug. The slug must be a non-empty string.', + $parameters[1]['start'], + 'Empty' + ); + return; + } + + $data = array( + $this->tokens[ $string_pos ]['content'], + ); + + // Warn for dynamic parts in the slug parameter. + if ( 'T_DOUBLE_QUOTED_STRING' === $this->tokens[ $string_pos ]['type'] || ( 'T_HEREDOC' === $this->tokens[ $string_pos ]['type'] && strpos( $this->tokens[ $string_pos ]['content'], '$' ) !== false ) ) { + $this->phpcsFile->addWarning( + 'The post type slug may, or may not, get too long with dynamic contents and could contain invalid characters. Found: %s.', + $string_pos, + 'PartiallyDynamic', + $data + ); + $post_type = $this->strip_interpolated_variables( $post_type ); + } + + if ( preg_match( self::POST_TYPE_CHARACTER_WHITELIST, $post_type ) === 0 ) { + // Error for invalid characters. + $this->phpcsFile->addError( + 'register_post_type() called with invalid post type %s. Post type contains invalid characters. Only lowercase alphanumeric characters, dashes, and underscores are allowed.', + $string_pos, + 'InvalidCharacters', + $data + ); + } + + if ( isset( $this->reserved_names[ $post_type ] ) ) { + // Error for using reserved slug names. + $this->phpcsFile->addError( + 'register_post_type() called with reserved post type %s. Reserved post types should not be used as they interfere with the functioning of WordPress itself.', + $string_pos, + 'Reserved', + $data + ); + } elseif ( stripos( $post_type, 'wp_' ) === 0 ) { + // Error for using reserved slug prefix. + $this->phpcsFile->addError( + 'The post type passed to register_post_type() uses a prefix reserved for WordPress itself. Found: %s.', + $string_pos, + 'ReservedPrefix', + $data + ); + } + + // Error for slugs that are too long. + if ( strlen( $post_type ) > self::POST_TYPE_MAX_LENGTH ) { + $this->phpcsFile->addError( + 'A post type slug must not exceed %d characters. Found: %s (%d characters).', + $string_pos, + 'TooLong', + array( + self::POST_TYPE_MAX_LENGTH, + $this->tokens[ $string_pos ]['content'], + strlen( $post_type ), + ) + ); + } + } +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidVariableNameSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidVariableNameSniff.php new file mode 100644 index 00000000..34314ff1 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -0,0 +1,299 @@ + true, + 'GETID3_ERRORARRAY' => true, + 'is_IE' => true, + 'is_IIS' => true, + 'is_macIE' => true, + 'is_NS4' => true, + 'is_winIE' => true, + 'PHP_SELF' => true, + 'post_ID' => true, + 'tag_ID' => true, + 'user_ID' => true, + ); + + /** + * List of member variables that can have mixed case. + * + * @since 0.9.0 + * @since 0.11.0 Changed from public to protected. + * + * @var array + */ + protected $whitelisted_mixed_case_member_var_names = array( + 'ID' => true, + 'comment_ID' => true, + 'comment_post_ID' => true, + 'post_ID' => true, + 'comment_author_IP' => true, + 'cat_ID' => true, + ); + + /** + * Custom list of properties which can have mixed case. + * + * @since 0.11.0 + * + * @var string|string[] + */ + public $customPropertiesWhitelist = array(); + + /** + * Cache of previously added custom functions. + * + * Prevents having to do the same merges over and over again. + * + * @since 0.10.0 + * @since 0.11.0 - Name changed from $addedCustomVariables. + * - Changed the format from simple bool to array. + * + * @var array + */ + protected $addedCustomProperties = array( + 'properties' => null, + ); + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcs_file The file being scanned. + * @param int $stack_ptr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processVariable( File $phpcs_file, $stack_ptr ) { + + $tokens = $phpcs_file->getTokens(); + $var_name = ltrim( $tokens[ $stack_ptr ]['content'], '$' ); + + // If it's a php reserved var, then its ok. + if ( isset( $this->phpReservedVars[ $var_name ] ) ) { + return; + } + + // Merge any custom variables with the defaults. + $this->mergeWhiteList(); + + // Likewise if it is a mixed-case var used by WordPress core. + if ( isset( $this->wordpress_mixed_case_vars[ $var_name ] ) ) { + return; + } + + $obj_operator = $phpcs_file->findNext( Tokens::$emptyTokens, ( $stack_ptr + 1 ), null, true ); + if ( \T_OBJECT_OPERATOR === $tokens[ $obj_operator ]['code'] ) { + // Check to see if we are using a variable from an object. + $var = $phpcs_file->findNext( Tokens::$emptyTokens, ( $obj_operator + 1 ), null, true ); + if ( \T_STRING === $tokens[ $var ]['code'] ) { + $bracket = $phpcs_file->findNext( Tokens::$emptyTokens, ( $var + 1 ), null, true ); + if ( \T_OPEN_PARENTHESIS !== $tokens[ $bracket ]['code'] ) { + $obj_var_name = $tokens[ $var ]['content']; + + // There is no way for us to know if the var is public or + // private, so we have to ignore a leading underscore if there is + // one and just check the main part of the variable name. + $original_var_name = $obj_var_name; + if ( '_' === substr( $obj_var_name, 0, 1 ) ) { + $obj_var_name = substr( $obj_var_name, 1 ); + } + + if ( ! isset( $this->whitelisted_mixed_case_member_var_names[ $obj_var_name ] ) && self::isSnakeCase( $obj_var_name ) === false ) { + $error = 'Object property "$%s" is not in valid snake_case format, try "$%s"'; + $data = array( + $original_var_name, + Sniff::get_snake_case_name_suggestion( $original_var_name ), + ); + $phpcs_file->addError( $error, $var, 'UsedPropertyNotSnakeCase', $data ); + } + } + } + } + + $in_class = false; + $obj_operator = $phpcs_file->findPrevious( Tokens::$emptyTokens, ( $stack_ptr - 1 ), null, true ); + if ( \T_DOUBLE_COLON === $tokens[ $obj_operator ]['code'] || \T_OBJECT_OPERATOR === $tokens[ $obj_operator ]['code'] ) { + // The variable lives within a class, and is referenced like + // this: MyClass::$_variable or $class->variable. + $in_class = true; + } + + // There is no way for us to know if the var is public or private, + // so we have to ignore a leading underscore if there is one and just + // check the main part of the variable name. + $original_var_name = $var_name; + if ( '_' === substr( $var_name, 0, 1 ) && true === $in_class ) { + $var_name = substr( $var_name, 1 ); + } + + if ( self::isSnakeCase( $var_name ) === false ) { + if ( $in_class && ! isset( $this->whitelisted_mixed_case_member_var_names[ $var_name ] ) ) { + $error = 'Object property "$%s" is not in valid snake_case format, try "$%s"'; + $error_name = 'UsedPropertyNotSnakeCase'; + } elseif ( ! $in_class ) { + $error = 'Variable "$%s" is not in valid snake_case format, try "$%s"'; + $error_name = 'VariableNotSnakeCase'; + } + + if ( isset( $error, $error_name ) ) { + $data = array( + $original_var_name, + Sniff::get_snake_case_name_suggestion( $original_var_name ), + ); + $phpcs_file->addError( $error, $stack_ptr, $error_name, $data ); + } + } + } + + /** + * Processes class member variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcs_file The file being scanned. + * @param int $stack_ptr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processMemberVar( File $phpcs_file, $stack_ptr ) { + + $tokens = $phpcs_file->getTokens(); + + $var_name = ltrim( $tokens[ $stack_ptr ]['content'], '$' ); + $member_props = $phpcs_file->getMemberProperties( $stack_ptr ); + if ( empty( $member_props ) ) { + // Couldn't get any info about this variable, which + // generally means it is invalid or possibly has a parse + // error. Any errors will be reported by the core, so + // we can ignore it. + return; + } + + // Merge any custom variables with the defaults. + $this->mergeWhiteList(); + + if ( ! isset( $this->whitelisted_mixed_case_member_var_names[ $var_name ] ) && false === self::isSnakeCase( $var_name ) ) { + $error = 'Member variable "$%s" is not in valid snake_case format, try "$%s"'; + $data = array( + $var_name, + Sniff::get_snake_case_name_suggestion( $var_name ), + ); + $phpcs_file->addError( $error, $stack_ptr, 'PropertyNotSnakeCase', $data ); + } + } + + /** + * Processes the variable found within a double quoted string. + * + * @param \PHP_CodeSniffer\Files\File $phpcs_file The file being scanned. + * @param int $stack_ptr The position of the double quoted + * string. + * + * @return void + */ + protected function processVariableInString( File $phpcs_file, $stack_ptr ) { + + $tokens = $phpcs_file->getTokens(); + + if ( preg_match_all( '|[^\\\]\${?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)|', $tokens[ $stack_ptr ]['content'], $matches ) > 0 ) { + + // Merge any custom variables with the defaults. + $this->mergeWhiteList(); + + foreach ( $matches[1] as $var_name ) { + // If it's a php reserved var, then its ok. + if ( isset( $this->phpReservedVars[ $var_name ] ) ) { + continue; + } + + // Likewise if it is a mixed-case var used by WordPress core. + if ( isset( $this->wordpress_mixed_case_vars[ $var_name ] ) ) { + return; + } + + if ( false === self::isSnakeCase( $var_name ) ) { + $error = 'Variable "$%s" is not in valid snake_case format, try "$%s"'; + $data = array( + $var_name, + Sniff::get_snake_case_name_suggestion( $var_name ), + ); + $phpcs_file->addError( $error, $stack_ptr, 'InterpolatedVariableNotSnakeCase', $data ); + } + } + } + } + + /** + * Return whether the variable is in snake_case. + * + * @param string $var_name Variable name. + * @return bool + */ + public static function isSnakeCase( $var_name ) { + return (bool) preg_match( '/^[a-z0-9_]+$/', $var_name ); + } + + /** + * Merge a custom whitelist provided via a custom ruleset with the predefined whitelist, + * if we haven't already. + * + * @since 0.10.0 + * @since 2.0.0 Removed unused $phpcs_file parameter. + * + * @return void + */ + protected function mergeWhiteList() { + if ( $this->customPropertiesWhitelist !== $this->addedCustomProperties['properties'] ) { + // Fix property potentially passed as comma-delimited string. + $customProperties = Sniff::merge_custom_array( $this->customPropertiesWhitelist, array(), false ); + + $this->whitelisted_mixed_case_member_var_names = Sniff::merge_custom_array( + $customProperties, + $this->whitelisted_mixed_case_member_var_names + ); + + $this->addedCustomProperties['properties'] = $this->customPropertiesWhitelist; + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DevelopmentFunctionsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DevelopmentFunctionsSniff.php new file mode 100644 index 00000000..59e914dc --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DevelopmentFunctionsSniff.php @@ -0,0 +1,66 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'error_log' => array( + 'type' => 'warning', + 'message' => '%s() found. Debug code should not normally be used in production.', + 'functions' => array( + 'error_log', + 'var_dump', + 'var_export', + 'print_r', + 'trigger_error', + 'set_error_handler', + 'debug_backtrace', + 'debug_print_backtrace', + 'wp_debug_backtrace_summary', + ), + ), + + 'prevent_path_disclosure' => array( + 'type' => 'warning', + 'message' => '%s() can lead to full path disclosure.', + 'functions' => array( + 'error_reporting', + 'phpinfo', + ), + ), + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DisallowShortTernarySniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DisallowShortTernarySniff.php new file mode 100644 index 00000000..6c734b8c --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DisallowShortTernarySniff.php @@ -0,0 +1,65 @@ +phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + if ( false === $nextNonEmpty ) { + // Live coding or parse error. + return; + } + + if ( \T_INLINE_ELSE !== $this->tokens[ $nextNonEmpty ]['code'] ) { + return; + } + + $this->phpcsFile->addError( + 'Using short ternaries is not allowed', + $stackPtr, + 'Found' + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DiscouragedPHPFunctionsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DiscouragedPHPFunctionsSniff.php new file mode 100644 index 00000000..39f87c09 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DiscouragedPHPFunctionsSniff.php @@ -0,0 +1,103 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'serialize' => array( + 'type' => 'warning', + 'message' => '%s() found. Serialized data has known vulnerability problems with Object Injection. JSON is generally a better approach for serializing data. See https://www.owasp.org/index.php/PHP_Object_Injection', + 'functions' => array( + 'serialize', + 'unserialize', + ), + ), + + 'urlencode' => array( + 'type' => 'warning', + 'message' => '%s() should only be used when dealing with legacy applications rawurlencode() should now be used instead. See http://php.net/manual/en/function.rawurlencode.php and http://www.faqs.org/rfcs/rfc3986.html', + 'functions' => array( + 'urlencode', + ), + ), + + 'runtime_configuration' => array( + 'type' => 'warning', + 'message' => '%s() found. Changing configuration values at runtime is strongly discouraged.', + 'functions' => array( + 'error_reporting', + 'ini_restore', + 'apache_setenv', + 'putenv', + 'set_include_path', + 'restore_include_path', + // This alias was DEPRECATED in PHP 5.3.0, and REMOVED as of PHP 7.0.0. + 'magic_quotes_runtime', + // Warning This function was DEPRECATED in PHP 5.3.0, and REMOVED as of PHP 7.0.0. + 'set_magic_quotes_runtime', + // Warning This function was removed from most SAPIs in PHP 5.3.0, and was removed from PHP-FPM in PHP 7.0.0. + 'dl', + ), + ), + + 'system_calls' => array( + 'type' => 'warning', + 'message' => '%s() found. PHP system calls are often disabled by server admins.', + 'functions' => array( + 'exec', + 'passthru', + 'proc_open', + 'shell_exec', + 'system', + 'popen', + ), + ), + + 'obfuscation' => array( + 'type' => 'warning', + 'message' => '%s() can be used to obfuscate code which is strongly discouraged. Please verify that the function is used for benign reasons.', + 'functions' => array( + 'base64_decode', + 'base64_encode', + 'convert_uudecode', + 'convert_uuencode', + 'str_rot13', + ), + ), + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DontExtractSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DontExtractSniff.php new file mode 100644 index 00000000..af2233bb --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DontExtractSniff.php @@ -0,0 +1,55 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + + 'extract' => array( + 'type' => 'error', + 'message' => '%s() usage is highly discouraged, due to the complexity and unintended issues it might cause.', + 'functions' => array( + 'extract', + ), + ), + + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/IniSetSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/IniSetSniff.php new file mode 100644 index 00000000..178386d1 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/IniSetSniff.php @@ -0,0 +1,177 @@ + true, + 'ini_alter' => true, + ); + + /** + * Array of PHP configuration options that are allowed to be manipulated. + * + * @since 2.1.0 + * + * @var array Multidimensional array with parameter details. + * $whitelisted_options = array( + * (string) option name. = array( + * (string[]) 'valid_values' = array() + * ) + * ); + */ + protected $whitelisted_options = array( + 'auto_detect_line_endings' => array(), + 'highlight.bg' => array(), + 'highlight.comment' => array(), + 'highlight.default' => array(), + 'highlight.html' => array(), + 'highlight.keyword' => array(), + 'highlight.string' => array(), + 'short_open_tag' => array( + 'valid_values' => array( 'true', '1', 'on' ), + ), + ); + + /** + * Array of PHP configuration options that are not allowed to be manipulated. + * + * @since 2.1.0 + * + * @var array Multidimensional array with parameter details. + * $blacklisted_options = array( + * (string) option name. = array( + * (string[]) 'invalid_values' = array() + * (string) 'message' + * ) + * ); + */ + protected $blacklisted_options = array( + 'bcmath.scale' => array( + 'message' => 'Use `bcscale()` instead.', + ), + 'display_errors' => array( + 'message' => 'Use `WP_DEBUG_DISPLAY` instead.', + ), + 'error_reporting' => array( + 'message' => 'Use `WP_DEBUG` instead.', + ), + 'filter.default' => array( + 'message' => 'Changing the option value can break other plugins. Use the filter flag constants when calling the Filter functions instead.', + ), + 'filter.default_flags' => array( + 'message' => 'Changing the option value can break other plugins. Use the filter flag constants when calling the Filter functions instead.', + ), + 'iconv.input_encoding' => array( + 'message' => 'PHP < 5.6 only - use `iconv_set_encoding()` instead.', + ), + 'iconv.internal_encoding' => array( + 'message' => 'PHP < 5.6 only - use `iconv_set_encoding()` instead.', + ), + 'iconv.output_encoding' => array( + 'message' => 'PHP < 5.6 only - use `iconv_set_encoding()` instead.', + ), + 'ignore_user_abort' => array( + 'message' => 'Use `ignore_user_abort()` instead.', + ), + 'log_errors' => array( + 'message' => 'Use `WP_DEBUG_LOG` instead.', + ), + 'max_execution_time' => array( + 'message' => 'Use `set_time_limit()` instead.', + ), + 'memory_limit' => array( + 'message' => 'Use `wp_raise_memory_limit()` or hook into the filters in that function.', + ), + 'short_open_tag' => array( + 'invalid_values' => array( 'false', '0', 'off' ), + 'message' => 'Turning off short_open_tag is prohibited as it can break other plugins.', + ), + ); + + /** + * Process the parameter of a matched function. + * + * Errors if an option is found in the blacklist. Warns as + * 'risky' when the option is not found in the whitelist. + * + * @since 2.1.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + $option_name = $this->strip_quotes( $parameters[1]['raw'] ); + $option_value = $this->strip_quotes( $parameters[2]['raw'] ); + if ( isset( $this->whitelisted_options[ $option_name ] ) ) { + $whitelisted_option = $this->whitelisted_options[ $option_name ]; + if ( ! isset( $whitelisted_option['valid_values'] ) || in_array( strtolower( $option_value ), $whitelisted_option['valid_values'], true ) ) { + return; + } + } + + if ( isset( $this->blacklisted_options[ $option_name ] ) ) { + $blacklisted_option = $this->blacklisted_options[ $option_name ]; + if ( ! isset( $blacklisted_option['invalid_values'] ) || in_array( strtolower( $option_value ), $blacklisted_option['invalid_values'], true ) ) { + $this->phpcsFile->addError( + '%s(%s, %s) found. %s', + $stackPtr, + $this->string_to_errorcode( $option_name . '_Blacklisted' ), + array( + $matched_content, + $parameters[1]['raw'], + $parameters[2]['raw'], + $blacklisted_option['message'], + ) + ); + return; + } + } + + $this->phpcsFile->addWarning( + '%s(%s, %s) found. Changing configuration values at runtime is strongly discouraged.', + $stackPtr, + 'Risky', + array( + $matched_content, + $parameters[1]['raw'], + $parameters[2]['raw'], + ) + ); + } +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/NoSilencedErrorsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/NoSilencedErrorsSniff.php new file mode 100644 index 00000000..ee3b3b3a --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/NoSilencedErrorsSniff.php @@ -0,0 +1,239 @@ + => + */ + protected $function_whitelist = array( + // Directory extension. + 'chdir' => true, + 'opendir' => true, + 'scandir' => true, + + // File extension. + 'file_exists' => true, + 'file_get_contents' => true, + 'file' => true, + 'fileatime' => true, + 'filectime' => true, + 'filegroup' => true, + 'fileinode' => true, + 'filemtime' => true, + 'fileowner' => true, + 'fileperms' => true, + 'filesize' => true, + 'filetype' => true, + 'fopen' => true, + 'is_dir' => true, + 'is_executable' => true, + 'is_file' => true, + 'is_link' => true, + 'is_readable' => true, + 'is_writable' => true, + 'is_writeable' => true, + 'lstat' => true, + 'mkdir' => true, + 'move_uploaded_file' => true, + 'readfile' => true, + 'readlink' => true, + 'rename' => true, + 'rmdir' => true, + 'stat' => true, + 'unlink' => true, + + // FTP extension. + 'ftp_chdir' => true, + 'ftp_login' => true, + 'ftp_rename' => true, + + // Stream extension. + 'stream_select' => true, + 'stream_set_chunk_size' => true, + + // Zlib extension. + 'deflate_add' => true, + 'deflate_init' => true, + 'inflate_add' => true, + 'inflate_init' => true, + 'readgzfile' => true, + + // Miscellaneous other functions. + 'imagecreatefromstring' => true, + 'parse_url' => true, // Pre-PHP 5.3.3 an E_WARNING was thrown when URL parsing failed. + 'unserialize' => true, + ); + + /** + * Tokens which are regarded as empty for the purpose of determining + * the name of the called function. + * + * This property is set from within the register() method. + * + * @since 1.1.0 + * + * @var array + */ + private $empty_tokens = array(); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 1.1.0 + * + * @return array + */ + public function register() { + $this->empty_tokens = Tokens::$emptyTokens; + $this->empty_tokens[ \T_NS_SEPARATOR ] = \T_NS_SEPARATOR; + $this->empty_tokens[ \T_BITWISE_AND ] = \T_BITWISE_AND; + + return array( + \T_ASPERAND, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 1.1.0 + * + * @param int $stackPtr The position of the current token in the stack. + */ + public function process_token( $stackPtr ) { + // Handle the user-defined custom function whitelist. + $this->custom_whitelist = $this->merge_custom_array( $this->custom_whitelist, array(), false ); + $this->custom_whitelist = array_map( 'strtolower', $this->custom_whitelist ); + + /* + * Check if the error silencing is done for one of the whitelisted functions. + * + * @internal The function call name determination is done even when there is no whitelist active + * to allow the metrics to be more informative. + */ + $next_non_empty = $this->phpcsFile->findNext( $this->empty_tokens, ( $stackPtr + 1 ), null, true, null, true ); + if ( false !== $next_non_empty && \T_STRING === $this->tokens[ $next_non_empty ]['code'] ) { + $has_parenthesis = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $next_non_empty + 1 ), null, true, null, true ); + if ( false !== $has_parenthesis && \T_OPEN_PARENTHESIS === $this->tokens[ $has_parenthesis ]['code'] ) { + $function_name = strtolower( $this->tokens[ $next_non_empty ]['content'] ); + if ( ( true === $this->use_default_whitelist + && isset( $this->function_whitelist[ $function_name ] ) === true ) + || ( ! empty( $this->custom_whitelist ) + && in_array( $function_name, $this->custom_whitelist, true ) === true ) + ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Error silencing', 'whitelisted function call: ' . $function_name ); + return; + } + } + } + + $this->context_length = (int) $this->context_length; + $context_length = $this->context_length; + if ( $this->context_length <= 0 ) { + $context_length = 2; + } + + // Prepare the "Found" string to display. + $end_of_statement = $this->phpcsFile->findEndOfStatement( $stackPtr, \T_COMMA ); + if ( ( $end_of_statement - $stackPtr ) < $context_length ) { + $context_length = ( $end_of_statement - $stackPtr ); + } + $found = $this->phpcsFile->getTokensAsString( $stackPtr, $context_length ); + $found = str_replace( array( "\t", "\n", "\r" ), ' ', $found ) . '...'; + + $error_msg = 'Silencing errors is strongly discouraged. Use proper error checking instead.'; + $data = array(); + if ( $this->context_length > 0 ) { + $error_msg .= ' Found: %s'; + $data[] = $found; + } + + $this->phpcsFile->addWarning( + $error_msg, + $stackPtr, + 'Discouraged', + $data + ); + + if ( isset( $function_name ) ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Error silencing', '@' . $function_name ); + } else { + $this->phpcsFile->recordMetric( $stackPtr, 'Error silencing', $found ); + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/POSIXFunctionsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/POSIXFunctionsSniff.php new file mode 100644 index 00000000..9fb1cdcb --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/POSIXFunctionsSniff.php @@ -0,0 +1,76 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'ereg' => array( + 'type' => 'error', + 'message' => '%s() has been deprecated since PHP 5.3 and removed in PHP 7.0, please use preg_match() instead.', + 'functions' => array( + 'ereg', + 'eregi', + 'sql_regcase', + ), + ), + + 'ereg_replace' => array( + 'type' => 'error', + 'message' => '%s() has been deprecated since PHP 5.3 and removed in PHP 7.0, please use preg_replace() instead.', + 'functions' => array( + 'ereg_replace', + 'eregi_replace', + ), + ), + + 'split' => array( + 'type' => 'error', + 'message' => '%s() has been deprecated since PHP 5.3 and removed in PHP 7.0, please use explode(), str_split() or preg_split() instead.', + 'functions' => array( + 'split', + 'spliti', + ), + ), + + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/PregQuoteDelimiterSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/PregQuoteDelimiterSniff.php new file mode 100644 index 00000000..a67e1173 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/PregQuoteDelimiterSniff.php @@ -0,0 +1,69 @@ + => + */ + protected $target_functions = array( + 'preg_quote' => true, + ); + + /** + * Process the parameters of a matched function. + * + * @since 1.0.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + if ( \count( $parameters ) > 1 ) { + return; + } + + $this->phpcsFile->addWarning( + 'Passing the $delimiter as the second parameter to preg_quote() is strongly recommended.', + $stackPtr, + 'Missing' + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/RestrictedPHPFunctionsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/RestrictedPHPFunctionsSniff.php new file mode 100644 index 00000000..280c94d9 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/RestrictedPHPFunctionsSniff.php @@ -0,0 +1,48 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'create_function' => array( + 'type' => 'error', + 'message' => '%s() is deprecated as of PHP 7.2, please use full fledged functions or anonymous functions instead.', + 'functions' => array( + 'create_function', + ), + ), + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/StrictComparisonsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/StrictComparisonsSniff.php new file mode 100644 index 00000000..85fe0554 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/StrictComparisonsSniff.php @@ -0,0 +1,56 @@ +has_whitelist_comment( 'loose comparison', $stackPtr ) ) { + $error = 'Found: ' . $this->tokens[ $stackPtr ]['content'] . '. Use strict comparisons (=== or !==).'; + $this->phpcsFile->addWarning( $error, $stackPtr, 'LooseComparison' ); + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/StrictInArraySniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/StrictInArraySniff.php new file mode 100644 index 00000000..4973e9bb --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/StrictInArraySniff.php @@ -0,0 +1,105 @@ + => + */ + protected $target_functions = array( + 'in_array' => true, + 'array_search' => true, + 'array_keys' => false, + ); + + /** + * Process the parameters of a matched function. + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + // Check if the strict check is actually needed. + if ( false === $this->target_functions[ $matched_content ] ) { + if ( \count( $parameters ) === 1 ) { + return; + } + } + + // We're only interested in the third parameter. + if ( false === isset( $parameters[3] ) || 'true' !== strtolower( $parameters[3]['raw'] ) ) { + $errorcode = 'MissingTrueStrict'; + + /* + * Use a different error code when `false` is found to allow for excluding + * the warning as this will be a conscious choice made by the dev. + */ + if ( isset( $parameters[3] ) && 'false' === strtolower( $parameters[3]['raw'] ) ) { + $errorcode = 'FoundNonStrictFalse'; + } + + $this->phpcsFile->addWarning( + 'Not using strict comparison for %s; supply true for third argument.', + ( isset( $parameters[3]['start'] ) ? $parameters[3]['start'] : $parameters[1]['start'] ), + $errorcode, + array( $matched_content ) + ); + return; + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/TypeCastsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/TypeCastsSniff.php new file mode 100644 index 00000000..7aded55f --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/TypeCastsSniff.php @@ -0,0 +1,99 @@ +tokens[ $stackPtr ]['code']; + $typecast = str_replace( ' ', '', $this->tokens[ $stackPtr ]['content'] ); + $typecast_lc = strtolower( $typecast ); + + switch ( $token_code ) { + case \T_DOUBLE_CAST: + if ( '(float)' !== $typecast_lc ) { + $fix = $this->phpcsFile->addFixableError( + 'Normalized type keywords must be used; expected "(float)" but found "%s"', + $stackPtr, + 'DoubleRealFound', + array( $typecast ) + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( $stackPtr, '(float)' ); + } + } + break; + + case \T_UNSET_CAST: + $this->phpcsFile->addWarning( + 'Using the "(unset)" cast is strongly discouraged. Use the "unset()" language construct or assign "null" as the value to the variable instead.', + $stackPtr, + 'UnsetFound' + ); + break; + + case \T_STRING_CAST: + case \T_BINARY_CAST: + if ( \T_STRING_CAST === $token_code && '(binary)' !== $typecast_lc ) { + break; + } + + $this->phpcsFile->addWarning( + 'Using binary casting is strongly discouraged. Found: "%s"', + $stackPtr, + 'BinaryFound', + array( $typecast ) + ); + break; + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/YodaConditionsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/YodaConditionsSniff.php new file mode 100644 index 00000000..9f3f3d10 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/YodaConditionsSniff.php @@ -0,0 +1,125 @@ +condition_start_tokens = $starters; + + return array( + \T_IS_EQUAL, + \T_IS_NOT_EQUAL, + \T_IS_IDENTICAL, + \T_IS_NOT_IDENTICAL, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + + $start = $this->phpcsFile->findPrevious( $this->condition_start_tokens, $stackPtr, null, false, null, true ); + + $needs_yoda = false; + + // Note: going backwards! + for ( $i = $stackPtr; $i > $start; $i-- ) { + + // Ignore whitespace. + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + // If this is a variable or array, we've seen all we need to see. + if ( \T_VARIABLE === $this->tokens[ $i ]['code'] + || \T_CLOSE_SQUARE_BRACKET === $this->tokens[ $i ]['code'] + ) { + $needs_yoda = true; + break; + } + + // If this is a function call or something, we are OK. + if ( \T_CLOSE_PARENTHESIS === $this->tokens[ $i ]['code'] ) { + return; + } + } + + if ( ! $needs_yoda ) { + return; + } + + // Check if this is a var to var comparison, e.g.: if ( $var1 == $var2 ). + $next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + + if ( isset( Tokens::$castTokens[ $this->tokens[ $next_non_empty ]['code'] ] ) ) { + $next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $next_non_empty + 1 ), null, true ); + } + + if ( \in_array( $this->tokens[ $next_non_empty ]['code'], array( \T_SELF, \T_PARENT, \T_STATIC ), true ) ) { + $next_non_empty = $this->phpcsFile->findNext( + ( Tokens::$emptyTokens + array( \T_DOUBLE_COLON => \T_DOUBLE_COLON ) ), + ( $next_non_empty + 1 ), + null, + true + ); + } + + if ( \T_VARIABLE === $this->tokens[ $next_non_empty ]['code'] ) { + return; + } + + $this->phpcsFile->addError( 'Use Yoda Condition checks, you must.', $stackPtr, 'NotYoda' ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/EscapeOutputSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/EscapeOutputSniff.php new file mode 100644 index 00000000..48a4766b --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/EscapeOutputSniff.php @@ -0,0 +1,505 @@ + 'esc_html_e() or esc_attr_e()', + '_ex' => 'echo esc_html_x() or echo esc_attr_x()', + ); + + /** + * Cache of previously added custom functions. + * + * Prevents having to do the same merges over and over again. + * + * @since 0.4.0 + * @since 0.11.0 - Changed from public static to protected non-static. + * - Changed the format from simple bool to array. + * + * @var array + */ + protected $addedCustomFunctions = array( + 'escape' => array(), + 'autoescape' => array(), + 'sanitize' => array(), + 'print' => array(), + ); + + /** + * List of names of the tokens representing PHP magic constants. + * + * @since 0.10.0 + * + * @var array + */ + private $magic_constant_tokens = array( + 'T_CLASS_C' => true, // __CLASS__ + 'T_DIR' => true, // __DIR__ + 'T_FILE' => true, // __FILE__ + 'T_FUNC_C' => true, // __FUNCTION__ + 'T_LINE' => true, // __LINE__ + 'T_METHOD_C' => true, // __METHOD__ + 'T_NS_C' => true, // __NAMESPACE__ + 'T_TRAIT_C' => true, // __TRAIT__ + ); + + /** + * List of names of the native PHP constants which can be considered safe. + * + * @since 1.0.0 + * + * @var array + */ + private $safe_php_constants = array( + 'PHP_EOL' => true, // String. + 'PHP_VERSION' => true, // Integer. + 'PHP_MAJOR_VERSION' => true, // Integer. + 'PHP_MINOR_VERSION' => true, // Integer. + 'PHP_RELEASE_VERSION' => true, // Integer. + 'PHP_VERSION_ID' => true, // Integer. + 'PHP_EXTRA_VERSION' => true, // String. + 'PHP_DEBUG' => true, // Integer. + ); + + /** + * List of tokens which can be considered as safe when directly part of the output. + * + * @since 0.12.0 + * + * @var array + */ + private $safe_components = array( + 'T_CONSTANT_ENCAPSED_STRING' => true, + 'T_LNUMBER' => true, + 'T_MINUS' => true, + 'T_PLUS' => true, + 'T_MULTIPLY' => true, + 'T_DIVIDE' => true, + 'T_MODULUS' => true, + 'T_TRUE' => true, + 'T_FALSE' => true, + 'T_NULL' => true, + 'T_DNUMBER' => true, + 'T_START_NOWDOC' => true, + 'T_NOWDOC' => true, + 'T_END_NOWDOC' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + + return array( + \T_ECHO, + \T_PRINT, + \T_EXIT, + \T_STRING, + \T_OPEN_TAG_WITH_ECHO, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + $this->mergeFunctionLists(); + + $function = $this->tokens[ $stackPtr ]['content']; + + // Find the opening parenthesis (if present; T_ECHO might not have it). + $open_paren = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + + // If function, not T_ECHO nor T_PRINT. + if ( \T_STRING === $this->tokens[ $stackPtr ]['code'] ) { + // Skip if it is a function but is not one of the printing functions. + if ( ! isset( $this->printingFunctions[ $this->tokens[ $stackPtr ]['content'] ] ) ) { + return; + } + + if ( isset( $this->tokens[ $open_paren ]['parenthesis_closer'] ) ) { + $end_of_statement = $this->tokens[ $open_paren ]['parenthesis_closer']; + } + + // These functions only need to have the first argument escaped. + if ( \in_array( $function, array( 'trigger_error', 'user_error' ), true ) ) { + $first_param = $this->get_function_call_parameter( $stackPtr, 1 ); + $end_of_statement = ( $first_param['end'] + 1 ); + unset( $first_param ); + } + + /* + * If the first param to `_deprecated_file()` follows the typical `basename( __FILE__ )` + * pattern, it doesn't need to be escaped. + */ + if ( '_deprecated_file' === $function ) { + $first_param = $this->get_function_call_parameter( $stackPtr, 1 ); + + // Quick check. This disregards comments. + if ( preg_match( '`^basename\s*\(\s*__FILE__\s*\)$`', $first_param['raw'] ) === 1 ) { + $stackPtr = ( $first_param['end'] + 2 ); + } + unset( $first_param ); + } + } + + // Checking for the ignore comment, ex: //xss ok. + if ( $this->has_whitelist_comment( 'xss', $stackPtr ) ) { + return; + } + + if ( isset( $this->unsafePrintingFunctions[ $function ] ) ) { + $error = $this->phpcsFile->addError( + "All output should be run through an escaping function (like %s), found '%s'.", + $stackPtr, + 'UnsafePrintingFunction', + array( $this->unsafePrintingFunctions[ $function ], $function ) + ); + + // If the error was reported, don't bother checking the function's arguments. + if ( $error ) { + return isset( $end_of_statement ) ? $end_of_statement : null; + } + } + + $ternary = false; + + // This is already determined if this is a function and not T_ECHO. + if ( ! isset( $end_of_statement ) ) { + + $end_of_statement = $this->phpcsFile->findNext( array( \T_SEMICOLON, \T_CLOSE_TAG ), $stackPtr ); + $last_token = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $end_of_statement - 1 ), null, true ); + + // Check for the ternary operator. We only need to do this here if this + // echo is lacking parenthesis. Otherwise it will be handled below. + if ( \T_OPEN_PARENTHESIS !== $this->tokens[ $open_paren ]['code'] || \T_CLOSE_PARENTHESIS !== $this->tokens[ $last_token ]['code'] ) { + + $ternary = $this->phpcsFile->findNext( \T_INLINE_THEN, $stackPtr, $end_of_statement ); + + // If there is a ternary skip over the part before the ?. However, if + // the ternary is within parentheses, it will be handled in the loop. + if ( false !== $ternary && empty( $this->tokens[ $ternary ]['nested_parenthesis'] ) ) { + $stackPtr = $ternary; + } + } + } + + // Ignore the function itself. + $stackPtr++; + + $in_cast = false; + + // Looping through echo'd components. + $watch = true; + for ( $i = $stackPtr; $i < $end_of_statement; $i++ ) { + + // Ignore whitespaces and comments. + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + // Ignore namespace separators. + if ( \T_NS_SEPARATOR === $this->tokens[ $i ]['code'] ) { + continue; + } + + if ( \T_OPEN_PARENTHESIS === $this->tokens[ $i ]['code'] ) { + + if ( ! isset( $this->tokens[ $i ]['parenthesis_closer'] ) ) { + // Live coding or parse error. + break; + } + + if ( $in_cast ) { + + // Skip to the end of a function call if it has been casted to a safe value. + $i = $this->tokens[ $i ]['parenthesis_closer']; + $in_cast = false; + + } else { + + // Skip over the condition part of a ternary (i.e., to after the ?). + $ternary = $this->phpcsFile->findNext( \T_INLINE_THEN, $i, $this->tokens[ $i ]['parenthesis_closer'] ); + + if ( false !== $ternary ) { + + $next_paren = $this->phpcsFile->findNext( \T_OPEN_PARENTHESIS, ( $i + 1 ), $this->tokens[ $i ]['parenthesis_closer'] ); + + // We only do it if the ternary isn't within a subset of parentheses. + if ( false === $next_paren || ( isset( $this->tokens[ $next_paren ]['parenthesis_closer'] ) && $ternary > $this->tokens[ $next_paren ]['parenthesis_closer'] ) ) { + $i = $ternary; + } + } + } + + continue; + } + + // Handle arrays for those functions that accept them. + if ( \T_ARRAY === $this->tokens[ $i ]['code'] ) { + $i++; // Skip the opening parenthesis. + continue; + } + + if ( \T_OPEN_SHORT_ARRAY === $this->tokens[ $i ]['code'] + || \T_CLOSE_SHORT_ARRAY === $this->tokens[ $i ]['code'] + ) { + continue; + } + + if ( \in_array( $this->tokens[ $i ]['code'], array( \T_DOUBLE_ARROW, \T_CLOSE_PARENTHESIS ), true ) ) { + continue; + } + + // Handle magic constants for debug functions. + if ( isset( $this->magic_constant_tokens[ $this->tokens[ $i ]['type'] ] ) ) { + continue; + } + + // Handle safe PHP native constants. + if ( \T_STRING === $this->tokens[ $i ]['code'] + && isset( $this->safe_php_constants[ $this->tokens[ $i ]['content'] ] ) + && $this->is_use_of_global_constant( $i ) + ) { + continue; + } + + // Wake up on concatenation characters, another part to check. + if ( \T_STRING_CONCAT === $this->tokens[ $i ]['code'] ) { + $watch = true; + continue; + } + + // Wake up after a ternary else (:). + if ( false !== $ternary && \T_INLINE_ELSE === $this->tokens[ $i ]['code'] ) { + $watch = true; + continue; + } + + // Wake up for commas. + if ( \T_COMMA === $this->tokens[ $i ]['code'] ) { + $in_cast = false; + $watch = true; + continue; + } + + if ( false === $watch ) { + continue; + } + + // Allow T_CONSTANT_ENCAPSED_STRING eg: echo 'Some String'; + // Also T_LNUMBER, e.g.: echo 45; exit -1; and booleans. + if ( isset( $this->safe_components[ $this->tokens[ $i ]['type'] ] ) ) { + continue; + } + + $watch = false; + + // Allow int/double/bool casted variables. + if ( isset( $this->safe_casts[ $this->tokens[ $i ]['code'] ] ) ) { + $in_cast = true; + continue; + } + + // Now check that next token is a function call. + if ( \T_STRING === $this->tokens[ $i ]['code'] ) { + + $ptr = $i; + $functionName = $this->tokens[ $i ]['content']; + $function_opener = $this->phpcsFile->findNext( \T_OPEN_PARENTHESIS, ( $i + 1 ), null, false, null, true ); + $is_formatting_function = isset( $this->formattingFunctions[ $functionName ] ); + + if ( false !== $function_opener ) { + + if ( isset( $this->arrayWalkingFunctions[ $functionName ] ) ) { + + // Get the callback parameter. + $callback = $this->get_function_call_parameter( + $ptr, + $this->arrayWalkingFunctions[ $functionName ] + ); + + if ( ! empty( $callback ) ) { + /* + * If this is a function callback (not a method callback array) and we're able + * to resolve the function name, do so. + */ + $mapped_function = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $callback['start'], + ( $callback['end'] + 1 ), + true + ); + + if ( false !== $mapped_function + && \T_CONSTANT_ENCAPSED_STRING === $this->tokens[ $mapped_function ]['code'] + ) { + $functionName = $this->strip_quotes( $this->tokens[ $mapped_function ]['content'] ); + $ptr = $mapped_function; + } + } + } + + // Skip pointer to after the function. + // If this is a formatting function we just skip over the opening + // parenthesis. Otherwise we skip all the way to the closing. + if ( $is_formatting_function ) { + $i = ( $function_opener + 1 ); + $watch = true; + } else { + if ( isset( $this->tokens[ $function_opener ]['parenthesis_closer'] ) ) { + $i = $this->tokens[ $function_opener ]['parenthesis_closer']; + } else { + // Live coding or parse error. + break; + } + } + } + + // If this is a safe function, we don't flag it. + if ( + $is_formatting_function + || isset( $this->autoEscapedFunctions[ $functionName ] ) + || isset( $this->escapingFunctions[ $functionName ] ) + ) { + continue; + } + + $content = $functionName; + + } else { + $content = $this->tokens[ $i ]['content']; + $ptr = $i; + } + + // Make the error message a little more informative for array access variables. + if ( \T_VARIABLE === $this->tokens[ $ptr ]['code'] ) { + $array_keys = $this->get_array_access_keys( $ptr ); + + if ( ! empty( $array_keys ) ) { + $content .= '[' . implode( '][', $array_keys ) . ']'; + } + } + + $this->phpcsFile->addError( + "All output should be run through an escaping function (see the Security sections in the WordPress Developer Handbooks), found '%s'.", + $ptr, + 'OutputNotEscaped', + array( $content ) + ); + } + + return $end_of_statement; + } + + /** + * Merge custom functions provided via a custom ruleset with the defaults, if we haven't already. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @return void + */ + protected function mergeFunctionLists() { + if ( $this->customEscapingFunctions !== $this->addedCustomFunctions['escape'] ) { + $customEscapeFunctions = $this->merge_custom_array( $this->customEscapingFunctions, array(), false ); + + $this->escapingFunctions = $this->merge_custom_array( + $customEscapeFunctions, + $this->escapingFunctions + ); + + $this->addedCustomFunctions['escape'] = $this->customEscapingFunctions; + } + + if ( $this->customAutoEscapedFunctions !== $this->addedCustomFunctions['autoescape'] ) { + $this->autoEscapedFunctions = $this->merge_custom_array( + $this->customAutoEscapedFunctions, + $this->autoEscapedFunctions + ); + + $this->addedCustomFunctions['autoescape'] = $this->customAutoEscapedFunctions; + } + + if ( $this->customPrintingFunctions !== $this->addedCustomFunctions['print'] ) { + + $this->printingFunctions = $this->merge_custom_array( + $this->customPrintingFunctions, + $this->printingFunctions + ); + + $this->addedCustomFunctions['print'] = $this->customPrintingFunctions; + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/NonceVerificationSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/NonceVerificationSniff.php new file mode 100644 index 00000000..15f4a604 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/NonceVerificationSniff.php @@ -0,0 +1,178 @@ + true, + '$_FILE' => true, + '$_GET' => false, + '$_REQUEST' => false, + ); + + /** + * Custom list of functions which verify nonces. + * + * @since 0.5.0 + * + * @var string|string[] + */ + public $customNonceVerificationFunctions = array(); + + /** + * Custom list of functions that sanitize the values passed to them. + * + * @since 0.11.0 + * + * @var string|string[] + */ + public $customSanitizingFunctions = array(); + + /** + * Custom sanitizing functions that implicitly unslash the values passed to them. + * + * @since 0.11.0 + * + * @var string|string[] + */ + public $customUnslashingSanitizingFunctions = array(); + + /** + * Cache of previously added custom functions. + * + * Prevents having to do the same merges over and over again. + * + * @since 0.5.0 + * @since 0.11.0 - Changed from public static to protected non-static. + * - Changed the format from simple bool to array. + * + * @var array + */ + protected $addedCustomFunctions = array( + 'nonce' => array(), + 'sanitize' => array(), + 'unslashsanitize' => array(), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + + return array( + \T_VARIABLE, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + + $instance = $this->tokens[ $stackPtr ]; + + if ( ! isset( $this->superglobals[ $instance['content'] ] ) ) { + return; + } + + if ( $this->has_whitelist_comment( 'CSRF', $stackPtr ) ) { + return; + } + + if ( $this->is_assignment( $stackPtr ) ) { + return; + } + + $this->mergeFunctionLists(); + + if ( $this->has_nonce_check( $stackPtr ) ) { + return; + } + + $error_code = 'Missing'; + if ( false === $this->superglobals[ $instance['content'] ] ) { + $error_code = 'Recommended'; + } + + // If we're still here, no nonce-verification function was found. + $this->addMessage( + 'Processing form data without nonce verification.', + $stackPtr, + $this->superglobals[ $instance['content'] ], + $error_code + ); + } + + /** + * Merge custom functions provided via a custom ruleset with the defaults, if we haven't already. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @return void + */ + protected function mergeFunctionLists() { + if ( $this->customNonceVerificationFunctions !== $this->addedCustomFunctions['nonce'] ) { + $this->nonceVerificationFunctions = $this->merge_custom_array( + $this->customNonceVerificationFunctions, + $this->nonceVerificationFunctions + ); + + $this->addedCustomFunctions['nonce'] = $this->customNonceVerificationFunctions; + } + + if ( $this->customSanitizingFunctions !== $this->addedCustomFunctions['sanitize'] ) { + $this->sanitizingFunctions = $this->merge_custom_array( + $this->customSanitizingFunctions, + $this->sanitizingFunctions + ); + + $this->addedCustomFunctions['sanitize'] = $this->customSanitizingFunctions; + } + + if ( $this->customUnslashingSanitizingFunctions !== $this->addedCustomFunctions['unslashsanitize'] ) { + $this->unslashingSanitizingFunctions = $this->merge_custom_array( + $this->customUnslashingSanitizingFunctions, + $this->unslashingSanitizingFunctions + ); + + $this->addedCustomFunctions['unslashsanitize'] = $this->customUnslashingSanitizingFunctions; + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/PluginMenuSlugSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/PluginMenuSlugSniff.php new file mode 100644 index 00000000..08d8d58e --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/PluginMenuSlugSniff.php @@ -0,0 +1,89 @@ + => + */ + protected $target_functions = array( + 'add_menu_page' => array( 4 ), + 'add_object_page' => array( 4 ), + 'add_utility_page' => array( 4 ), + 'add_submenu_page' => array( 1, 5 ), + 'add_dashboard_page' => array( 4 ), + 'add_posts_page' => array( 4 ), + 'add_media_page' => array( 4 ), + 'add_links_page' => array( 4 ), + 'add_pages_page' => array( 4 ), + 'add_comments_page' => array( 4 ), + 'add_theme_page' => array( 4 ), + 'add_plugins_page' => array( 4 ), + 'add_users_page' => array( 4 ), + 'add_management_page' => array( 4 ), + 'add_options_page' => array( 4 ), + ); + + /** + * Process the parameters of a matched function. + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + foreach ( $this->target_functions[ $matched_content ] as $position ) { + if ( isset( $parameters[ $position ] ) ) { + $file_constant = $this->phpcsFile->findNext( \T_FILE, $parameters[ $position ]['start'], ( $parameters[ $position ]['end'] + 1 ) ); + + if ( false !== $file_constant ) { + $this->phpcsFile->addWarning( 'Using __FILE__ for menu slugs risks exposing filesystem structure.', $stackPtr, 'Using__FILE__' ); + } + } + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/SafeRedirectSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/SafeRedirectSniff.php new file mode 100644 index 00000000..2f6aa6a6 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/SafeRedirectSniff.php @@ -0,0 +1,48 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'wp_redirect' => array( + 'type' => 'warning', + 'message' => '%s() found. Using wp_safe_redirect(), along with the allowed_redirect_hosts filter if needed, can help avoid any chances of malicious redirects within code. It is also important to remember to call exit() after a redirect so that no other unwanted code is executed.', + 'functions' => array( + 'wp_redirect', + ), + ), + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/ValidatedSanitizedInputSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/ValidatedSanitizedInputSniff.php new file mode 100644 index 00000000..a545c580 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Security/ValidatedSanitizedInputSniff.php @@ -0,0 +1,233 @@ + array(), + 'unslashsanitize' => array(), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array( + \T_VARIABLE, + \T_DOUBLE_QUOTED_STRING, + \T_HEREDOC, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + + $superglobals = $this->input_superglobals; + + // Handling string interpolation. + if ( \T_DOUBLE_QUOTED_STRING === $this->tokens[ $stackPtr ]['code'] + || \T_HEREDOC === $this->tokens[ $stackPtr ]['code'] + ) { + $interpolated_variables = array_map( + function ( $symbol ) { + return '$' . $symbol; + }, + $this->get_interpolated_variables( $this->tokens[ $stackPtr ]['content'] ) + ); + foreach ( array_intersect( $interpolated_variables, $superglobals ) as $bad_variable ) { + $this->phpcsFile->addError( 'Detected usage of a non-sanitized, non-validated input variable %s: %s', $stackPtr, 'InputNotValidatedNotSanitized', array( $bad_variable, $this->tokens[ $stackPtr ]['content'] ) ); + } + + return; + } + + // Check if this is a superglobal. + if ( ! \in_array( $this->tokens[ $stackPtr ]['content'], $superglobals, true ) ) { + return; + } + + // If we're overriding a superglobal with an assignment, no need to test. + if ( $this->is_assignment( $stackPtr ) ) { + return; + } + + // This superglobal is being validated. + if ( $this->is_in_isset_or_empty( $stackPtr ) ) { + return; + } + + $array_keys = $this->get_array_access_keys( $stackPtr ); + + if ( empty( $array_keys ) ) { + return; + } + + $error_data = array( $this->tokens[ $stackPtr ]['content'] . '[' . implode( '][', $array_keys ) . ']' ); + + /* + * Check for validation first. + */ + $validated = false; + + for ( $i = ( $stackPtr + 1 ); $i < $this->phpcsFile->numTokens; $i++ ) { + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + if ( \T_OPEN_SQUARE_BRACKET === $this->tokens[ $i ]['code'] + && isset( $this->tokens[ $i ]['bracket_closer'] ) + ) { + // Skip over array keys. + $i = $this->tokens[ $i ]['bracket_closer']; + continue; + } + + if ( \T_COALESCE === $this->tokens[ $i ]['code'] ) { + $validated = true; + } + + // Anything else means this is not a validation coalesce. + break; + } + + if ( false === $validated ) { + $validated = $this->is_validated( $stackPtr, $array_keys, $this->check_validation_in_scope_only ); + } + + if ( false === $validated ) { + $this->phpcsFile->addError( + 'Detected usage of a possibly undefined superglobal array index: %s. Use isset() or empty() to check the index exists before using it', + $stackPtr, + 'InputNotValidated', + $error_data + ); + } + + if ( $this->has_whitelist_comment( 'sanitization', $stackPtr ) ) { + return; + } + + // If this variable is being tested with one of the `is_..()` functions, sanitization isn't needed. + if ( $this->is_in_type_test( $stackPtr ) ) { + return; + } + + // If this is a comparison ('a' == $_POST['foo']), sanitization isn't needed. + if ( $this->is_comparison( $stackPtr, false ) ) { + return; + } + + // If this is a comparison using the array comparison functions, sanitization isn't needed. + if ( $this->is_in_array_comparison( $stackPtr ) ) { + return; + } + + $this->mergeFunctionLists(); + + // Now look for sanitizing functions. + if ( ! $this->is_sanitized( $stackPtr, true ) ) { + $this->phpcsFile->addError( + 'Detected usage of a non-sanitized input variable: %s', + $stackPtr, + 'InputNotSanitized', + $error_data + ); + } + } + + /** + * Merge custom functions provided via a custom ruleset with the defaults, if we haven't already. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @return void + */ + protected function mergeFunctionLists() { + if ( $this->customSanitizingFunctions !== $this->addedCustomFunctions['sanitize'] ) { + $this->sanitizingFunctions = $this->merge_custom_array( + $this->customSanitizingFunctions, + $this->sanitizingFunctions + ); + + $this->addedCustomFunctions['sanitize'] = $this->customSanitizingFunctions; + } + + if ( $this->customUnslashingSanitizingFunctions !== $this->addedCustomFunctions['unslashsanitize'] ) { + $this->unslashingSanitizingFunctions = $this->merge_custom_array( + $this->customUnslashingSanitizingFunctions, + $this->unslashingSanitizingFunctions + ); + + $this->addedCustomFunctions['unslashsanitize'] = $this->customUnslashingSanitizingFunctions; + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Utils/I18nTextDomainFixerSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Utils/I18nTextDomainFixerSniff.php new file mode 100644 index 00000000..e7090b48 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Utils/I18nTextDomainFixerSniff.php @@ -0,0 +1,731 @@ + => + */ + protected $target_functions = array( + 'load_textdomain' => 1, + 'load_plugin_textdomain' => 1, + 'load_muplugin_textdomain' => 1, + 'load_theme_textdomain' => 1, + 'load_child_theme_textdomain' => 1, + 'unload_textdomain' => 1, + + '__' => 2, + '_e' => 2, + '_x' => 3, + '_ex' => 3, + '_n' => 4, + '_nx' => 5, + '_n_noop' => 3, + '_nx_noop' => 4, + 'translate_nooped_plural' => 3, + '_c' => 2, // Deprecated. + '_nc' => 4, // Deprecated. + '__ngettext' => 4, // Deprecated. + '__ngettext_noop' => 3, // Deprecated. + 'translate_with_context' => 2, // Deprecated. + + 'esc_html__' => 2, + 'esc_html_e' => 2, + 'esc_html_x' => 3, + 'esc_attr__' => 2, + 'esc_attr_e' => 2, + 'esc_attr_x' => 3, + + 'is_textdomain_loaded' => 1, + 'get_translations_for_domain' => 1, + + // Shouldn't be used by plugins/themes. + 'translate' => 2, + 'translate_with_gettext_context' => 3, + + // WP private functions. Shouldn't be used by plugins/themes. + '_load_textdomain_just_in_time' => 1, + '_get_path_to_translation_from_lang_dir' => 1, + '_get_path_to_translation' => 1, + ); + + /** + * Whether a valid new text domain was found. + * + * @since 1.2.0 + * + * @var bool + */ + private $is_valid = false; + + /** + * The new text domain as validated. + * + * @since 1.2.0 + * + * @var string + */ + private $validated_textdomain = ''; + + /** + * Whether the plugin/theme header has been seen and fixed yet. + * + * @since 1.2.0 + * + * @var bool + */ + private $header_found = false; + + /** + * Possible headers for a theme. + * + * @link https://developer.wordpress.org/themes/basics/main-stylesheet-style-css/ + * + * @since 1.2.0 + * + * @var array Array key is the header name, the value indicated whether it is a + * required (true) or optional (false) header. + */ + private $theme_headers = array( + 'Theme Name' => true, + 'Theme URI' => false, + 'Author' => true, + 'Author URI' => false, + 'Description' => true, + 'Version' => true, + 'License' => true, + 'License URI' => true, + 'Tags' => false, + 'Text Domain' => true, + 'Domain Path' => false, + ); + + /** + * Possible headers for a plugin. + * + * @link https://developer.wordpress.org/plugins/the-basics/header-requirements/ + * + * @since 1.2.0 + * + * @var array Array key is the header name, the value indicated whether it is a + * required (true) or optional (false) header. + */ + private $plugin_headers = array( + 'Plugin Name' => true, + 'Plugin URI' => false, + 'Description' => false, + 'Version' => false, + 'Author' => false, + 'Author URI' => false, + 'License' => false, + 'License URI' => false, + 'Text Domain' => false, + 'Domain Path' => false, + 'Network' => false, + ); + + /** + * Regex template to match theme/plugin headers. + * + * @since 1.2.0 + * + * @var string + */ + private $header_regex_template = '`^(?:\s*(?:(?:\*|//)\s*)?)?(%s)\s*:\s*([^\r\n]+)`'; + + /** + * Regex to match theme headers. + * + * Set from within the register() method. + * + * @since 1.2.0 + * + * @var string + */ + private $theme_header_regex; + + /** + * Regex to match plugin headers. + * + * Set from within the register() method. + * + * @since 1.2.0 + * + * @var string + */ + private $plugin_header_regex; + + /** + * The --tab-width CLI value that is being used. + * + * @since 1.2.0 + * + * @var integer + */ + private $tab_width = null; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 1.2.0 + * + * @return array + */ + public function register() { + $headers = array_map( + 'preg_quote', + array_keys( $this->theme_headers ), + array_fill( 0, \count( $this->theme_headers ), '`' ) + ); + $this->theme_header_regex = sprintf( $this->header_regex_template, implode( '|', $headers ) ); + + $headers = array_map( + 'preg_quote', + array_keys( $this->plugin_headers ), + array_fill( 0, \count( $this->plugin_headers ), '`' ) + ); + $this->plugin_header_regex = sprintf( $this->header_regex_template, implode( '|', $headers ) ); + + $targets = parent::register(); + + $targets[] = \T_DOC_COMMENT_OPEN_TAG; + $targets[] = \T_COMMENT; + + return $targets; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 1.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + // Check if the old/new properties are correctly set. If not, bow out. + if ( ! is_string( $this->new_text_domain ) + || '' === $this->new_text_domain + ) { + return ( $this->phpcsFile->numTokens + 1 ); + } + + if ( isset( $this->old_text_domain ) ) { + $this->old_text_domain = $this->merge_custom_array( $this->old_text_domain, array(), false ); + + if ( ! is_array( $this->old_text_domain ) + || array() === $this->old_text_domain + ) { + return ( $this->phpcsFile->numTokens + 1 ); + } + } + + // Only validate and throw warning about the text domain once. + if ( $this->new_text_domain !== $this->validated_textdomain ) { + $this->is_valid = false; + $this->validated_textdomain = $this->new_text_domain; + $this->header_found = false; + + if ( 'default' === $this->new_text_domain ) { + $this->phpcsFile->addWarning( + 'The "default" text domain is reserved for WordPress core use and should not be used by plugins or themes', + 0, + 'ReservedNewDomain', + array( $this->new_text_domain ) + ); + + return ( $this->phpcsFile->numTokens + 1 ); + } + + if ( preg_match( '`^[a-z0-9-]+$`', $this->new_text_domain ) !== 1 ) { + $this->phpcsFile->addWarning( + 'The text domain should be a simple lowercase text string with words separated by dashes. "%s" appears invalid', + 0, + 'InvalidNewDomain', + array( $this->new_text_domain ) + ); + + return ( $this->phpcsFile->numTokens + 1 ); + } + + // If the text domain passed both validations, it should be considered valid. + $this->is_valid = true; + + } elseif ( false === $this->is_valid ) { + return ( $this->phpcsFile->numTokens + 1 ); + } + + if ( isset( $this->tab_width ) === false ) { + if ( isset( $this->phpcsFile->config->tabWidth ) === false + || 0 === $this->phpcsFile->config->tabWidth + ) { + // We have no idea how wide tabs are, so assume 4 spaces for fixing. + $this->tab_width = 4; + } else { + $this->tab_width = $this->phpcsFile->config->tabWidth; + } + } + + if ( \T_DOC_COMMENT_OPEN_TAG === $this->tokens[ $stackPtr ]['code'] + || \T_COMMENT === $this->tokens[ $stackPtr ]['code'] + ) { + // Examine for plugin/theme file header. + return $this->process_comments( $stackPtr ); + + } elseif ( 'CSS' !== $this->phpcsFile->tokenizerType ) { + // Examine a T_STRING token in a PHP file as a function call. + return parent::process_token( $stackPtr ); + } + } + + + /** + * Process the parameters of a matched function. + * + * @since 1.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + $target_param = $this->target_functions[ $matched_content ]; + + if ( isset( $parameters[ $target_param ] ) === false && 1 !== $target_param ) { + $error_msg = 'Missing $domain arg'; + $error_code = 'MissingArgDomain'; + + if ( isset( $parameters[ ( $target_param - 1 ) ] ) ) { + $fix = $this->phpcsFile->addFixableError( $error_msg, $stackPtr, $error_code ); + + if ( true === $fix ) { + $start_previous = $parameters[ ( $target_param - 1 ) ]['start']; + $end_previous = $parameters[ ( $target_param - 1 ) ]['end']; + if ( \T_WHITESPACE === $this->tokens[ $start_previous ]['code'] + && $this->tokens[ $start_previous ]['content'] === $this->phpcsFile->eolChar + ) { + // Replicate the new line + indentation of the previous item. + $replacement = ','; + for ( $i = $start_previous; $i <= $end_previous; $i++ ) { + if ( \T_WHITESPACE !== $this->tokens[ $i ]['code'] ) { + break; + } + + if ( isset( $this->tokens[ $i ]['orig_content'] ) ) { + $replacement .= $this->tokens[ $i ]['orig_content']; + } else { + $replacement .= $this->tokens[ $i ]['content']; + } + } + + $replacement .= "'{$this->new_text_domain}'"; + } else { + $replacement = ", '{$this->new_text_domain}'"; + } + + if ( \T_WHITESPACE === $this->tokens[ $end_previous ]['code'] ) { + $this->phpcsFile->fixer->addContentBefore( $end_previous, $replacement ); + } else { + $this->phpcsFile->fixer->addContent( $end_previous, $replacement ); + } + } + } else { + $error_msg .= ' and preceding argument(s)'; + $error_code = 'MissingArgs'; + + // Expected preceeding param also missing, just throw the warning. + $this->phpcsFile->addWarning( $error_msg, $stackPtr, $error_code ); + } + + return; + } + + // Target parameter found. Let's examine it. + $domain_param_start = $parameters[ $target_param ]['start']; + $domain_param_end = $parameters[ $target_param ]['end']; + $domain_token = null; + + for ( $i = $domain_param_start; $i <= $domain_param_end; $i++ ) { + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + if ( \T_CONSTANT_ENCAPSED_STRING !== $this->tokens[ $i ]['code'] ) { + // Unexpected token found, not our concern. This is handled by the I18n sniff. + return; + } + + if ( isset( $domain_token ) ) { + // More than one T_CONSTANT_ENCAPSED_STRING found, not our concern. This is handled by the I18n sniff. + return; + } + + $domain_token = $i; + } + + // If we're still here, this means only one T_CONSTANT_ENCAPSED_STRING was found. + $old_domain = $this->strip_quotes( $this->tokens[ $domain_token ]['content'] ); + + if ( ! \in_array( $old_domain, $this->old_text_domain, true ) ) { + // Not a text domain targetted for replacement, ignore. + return; + } + + $fix = $this->phpcsFile->addFixableError( + 'Mismatched text domain. Expected \'%s\' but found \'%s\'', + $domain_token, + 'TextDomainMismatch', + array( $this->new_text_domain, $old_domain ) + ); + + if ( true === $fix ) { + $replacement = str_replace( $old_domain, $this->new_text_domain, $this->tokens[ $domain_token ]['content'] ); + $this->phpcsFile->fixer->replaceToken( $domain_token, $replacement ); + } + } + + /** + * Process the function if no parameters were found. + * + * @since 1.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * + * @return void + */ + public function process_no_parameters( $stackPtr, $group_name, $matched_content ) { + + $target_param = $this->target_functions[ $matched_content ]; + + if ( 1 !== $target_param ) { + // Only process the no param case as fixable if the text domain is expected to be the first parameter. + $this->phpcsFile->addWarning( 'Missing $domain arg and preceding argument(s)', $stackPtr, 'MissingArgs' ); + return; + } + + $opener = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + if ( \T_OPEN_PARENTHESIS !== $this->tokens[ $opener ]['code'] + || isset( $this->tokens[ $opener ]['parenthesis_closer'] ) === false + ) { + // Parse error or live coding. + return; + } + + $fix = $this->phpcsFile->addFixableError( 'Missing $domain arg', $stackPtr, 'MissingArgDomain' ); + if ( true === $fix ) { + $closer = $this->tokens[ $opener ]['parenthesis_closer']; + $replacement = " '{$this->new_text_domain}' "; + + if ( $this->tokens[ $opener ]['line'] !== $this->tokens[ $closer ]['line'] ) { + $replacement = trim( $replacement ); + $addBefore = ( $closer - 1 ); + if ( \T_WHITESPACE === $this->tokens[ ( $closer - 1 ) ]['code'] + && $this->tokens[ $closer - 1 ]['line'] === $this->tokens[ $closer ]['line'] + ) { + if ( isset( $this->tokens[ ( $closer - 1 ) ]['orig_content'] ) ) { + $replacement = $this->tokens[ ( $closer - 1 ) ]['orig_content'] + . "\t" + . $replacement; + } else { + $replacement = $this->tokens[ ( $closer - 1 ) ]['content'] + . str_repeat( ' ', $this->tab_width ) + . $replacement; + } + + --$addBefore; + } else { + // We don't know whether the code uses tabs or spaces, so presume WPCS, i.e. tabs. + $replacement = "\t" . $replacement; + } + + $replacement = $this->phpcsFile->eolChar . $replacement; + + $this->phpcsFile->fixer->addContentBefore( $addBefore, $replacement ); + + } elseif ( \T_WHITESPACE === $this->tokens[ ( $closer - 1 ) ]['code'] ) { + $this->phpcsFile->fixer->replaceToken( ( $closer - 1 ), $replacement ); + } else { + $this->phpcsFile->fixer->addContentBefore( $closer, $replacement ); + } + } + } + + + /** + * Process comments to find the plugin/theme headers. + * + * @since 1.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_comments( $stackPtr ) { + if ( true === $this->header_found && ! defined( 'PHP_CODESNIFFER_IN_TESTS' ) ) { + return; + } + + $regex = $this->plugin_header_regex; + $headers = $this->plugin_headers; + $type = 'plugin'; + $skip_to = $stackPtr; + + $file = $this->strip_quotes( $this->phpcsFile->getFileName() ); + if ( 'STDIN' === $file ) { + return; + } + + $file_name = basename( $file ); + if ( 'CSS' === $this->phpcsFile->tokenizerType ) { + if ( 'style.css' !== $file_name && ! defined( 'PHP_CODESNIFFER_IN_TESTS' ) ) { + // CSS files only need to be examined for the file header. + return ( $this->phpcsFile->numTokens + 1 ); + } + + $regex = $this->theme_header_regex; + $headers = $this->theme_headers; + $type = 'theme'; + } + + $comment_details = array( + 'required_header_found' => false, + 'headers_found' => 0, + 'text_domain_ptr' => false, + 'text_domain_found' => '', + 'last_header_ptr' => false, + 'last_header_matches' => array(), + ); + + if ( \T_COMMENT === $this->tokens[ $stackPtr ]['code'] ) { + $block_comment = false; + if ( substr( $this->tokens[ $stackPtr ]['content'], 0, 2 ) === '/*' ) { + $block_comment = true; + } + + $current = $stackPtr; + do { + if ( false === $comment_details['text_domain_ptr'] + || false === $comment_details['required_header_found'] + || $comment_details['headers_found'] < 3 + ) { + $comment_details = $this->examine_comment_line( $current, $regex, $headers, $comment_details ); + } + + if ( true === $block_comment && substr( $this->tokens[ $current ]['content'], -2 ) === '*/' ) { + ++$current; + break; + } + + ++$current; + } while ( isset( $this->tokens[ $current ] ) && \T_COMMENT === $this->tokens[ $current ]['code'] ); + + $skip_to = $current; + + } else { + if ( ! isset( $this->tokens[ $stackPtr ]['comment_closer'] ) ) { + return; + } + + $closer = $this->tokens[ $stackPtr ]['comment_closer']; + $current = $stackPtr; + + while ( ( $current = $this->phpcsFile->findNext( \T_DOC_COMMENT_STRING, ( $current + 1 ), $closer ) ) !== false ) { + $comment_details = $this->examine_comment_line( $current, $regex, $headers, $comment_details ); + + if ( false !== $comment_details['text_domain_ptr'] + && true === $comment_details['required_header_found'] + && $comment_details['headers_found'] >= 3 + ) { + // No need to look at the rest of the docblock. + break; + } + } + + $skip_to = $closer; + } + + // So, was this the plugin/theme header ? + if ( true === $comment_details['required_header_found'] + && $comment_details['headers_found'] >= 3 + ) { + $this->header_found = true; + + $text_domain_ptr = $comment_details['text_domain_ptr']; + $text_domain_found = $comment_details['text_domain_found']; + + if ( false !== $text_domain_ptr ) { + if ( $this->new_text_domain !== $text_domain_found + && ( \in_array( $text_domain_found, $this->old_text_domain, true ) ) + ) { + $fix = $this->phpcsFile->addFixableError( + 'Mismatched text domain in %s header. Expected \'%s\' but found \'%s\'', + $text_domain_ptr, + 'TextDomainHeaderMismatch', + array( + $type, + $this->new_text_domain, + $text_domain_found, + ) + ); + + if ( true === $fix ) { + if ( isset( $this->tokens[ $text_domain_ptr ]['orig_content'] ) ) { + $replacement = $this->tokens[ $text_domain_ptr ]['orig_content']; + } else { + $replacement = $this->tokens[ $text_domain_ptr ]['content']; + } + + $replacement = str_replace( $text_domain_found, $this->new_text_domain, $replacement ); + + $this->phpcsFile->fixer->replaceToken( $text_domain_ptr, $replacement ); + } + } + } else { + $last_header_ptr = $comment_details['last_header_ptr']; + $last_header_matches = $comment_details['last_header_matches']; + + $fix = $this->phpcsFile->addFixableError( + 'Missing "Text Domain" in %s header', + $last_header_ptr, + 'MissingTextDomainHeader', + array( $type ) + ); + + if ( true === $fix ) { + if ( isset( $this->tokens[ $last_header_ptr ]['orig_content'] ) ) { + $replacement = $this->tokens[ $last_header_ptr ]['orig_content']; + } else { + $replacement = $this->tokens[ $last_header_ptr ]['content']; + } + + $replacement = str_replace( $last_header_matches[1], 'Text Domain', $replacement ); + $replacement = str_replace( $last_header_matches[2], $this->new_text_domain, $replacement ); + + if ( \T_DOC_COMMENT_OPEN_TAG === $this->tokens[ $stackPtr ]['code'] ) { + for ( $i = ( $last_header_ptr - 1 ); ; $i-- ) { + if ( $this->tokens[ $i ]['line'] !== $this->tokens[ $last_header_ptr ]['line'] ) { + ++$i; + break; + } + } + + $replacement = $this->phpcsFile->eolChar + . $this->phpcsFile->getTokensAsString( $i, ( $last_header_ptr - $i ), true ) + . $replacement; + } + + $this->phpcsFile->fixer->addContent( $comment_details['last_header_ptr'], $replacement ); + } + } + } + + return $skip_to; + } + + /** + * Examine an individual token in a larger comment for plugin/theme headers. + * + * @since 1.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $regex The regex to use to examine the comment line. + * @param array $headers Valid headers for a plugin or theme. + * @param array $comment_details The information collected so far. + * + * @return array Adjusted $comment_details array + */ + protected function examine_comment_line( $stackPtr, $regex, $headers, $comment_details ) { + if ( preg_match( $regex, $this->tokens[ $stackPtr ]['content'], $matches ) === 1 ) { + ++$comment_details['headers_found']; + + if ( true === $headers[ $matches[1] ] ) { + $comment_details['required_header_found'] = true; + } + + if ( 'Text Domain' === $matches[1] ) { + $comment_details['text_domain_ptr'] = $stackPtr; + $comment_details['text_domain_found'] = trim( $matches[2] ); + } + + $comment_details['last_header_ptr'] = $stackPtr; + $comment_details['last_header_matches'] = $matches; + } + + return $comment_details; + } +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/AlternativeFunctionsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/AlternativeFunctionsSniff.php new file mode 100644 index 00000000..fc6e8fbb --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/AlternativeFunctionsSniff.php @@ -0,0 +1,316 @@ + true, + 'php://output' => true, + 'php://stdin' => true, + 'php://stdout' => true, + 'php://stderr' => true, + ); + + /** + * Local input streams which should not be flagged for the file system function checks if + * the $filename starts with them. + * + * @link http://php.net/manual/en/wrappers.php.php + * + * @var array + */ + protected $allowed_local_stream_partials = array( + 'php://temp/', + 'php://fd/', + ); + + /** + * Local input stream constants which should not be flagged for the file system function checks. + * + * @link http://php.net/manual/en/wrappers.php.php + * + * @var array + */ + protected $allowed_local_stream_constants = array( + 'STDIN' => true, + 'STDOUT' => true, + 'STDERR' => true, + ); + + /** + * Groups of functions to restrict. + * + * Example: groups => array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'since' => '4.9.0', //=> the WP version in which the alternative became available. + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'curl' => array( + 'type' => 'warning', + 'message' => 'Using cURL functions is highly discouraged. Use wp_remote_get() instead.', + 'since' => '2.7.0', + 'functions' => array( + 'curl_*', + ), + 'whitelist' => array( + 'curl_version' => true, + ), + ), + + 'parse_url' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged because of inconsistency in the output across PHP versions; use wp_parse_url() instead.', + 'since' => '4.4.0', + 'functions' => array( + 'parse_url', + ), + ), + + 'json_encode' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged. Use wp_json_encode() instead.', + 'since' => '4.1.0', + 'functions' => array( + 'json_encode', + ), + ), + + 'file_get_contents' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged. Use wp_remote_get() for remote URLs instead.', + 'since' => '2.7.0', + 'functions' => array( + 'file_get_contents', + ), + ), + + 'file_system_read' => array( + 'type' => 'warning', + 'message' => 'File operations should use WP_Filesystem methods instead of direct PHP filesystem calls. Found: %s()', + 'since' => '2.5.0', + 'functions' => array( + 'readfile', + 'fclose', + 'fopen', + 'fread', + 'fwrite', + 'file_put_contents', + 'fsockopen', + 'pfsockopen', + ), + ), + + 'strip_tags' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged. Use the more comprehensive wp_strip_all_tags() instead.', + 'since' => '2.9.0', + 'functions' => array( + 'strip_tags', + ), + ), + + 'rand_seeding' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged. Rand seeding is not necessary when using the wp_rand() function (as you should).', + 'since' => '2.6.2', + 'functions' => array( + 'srand', + 'mt_srand', + ), + ), + + 'rand' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged. Use the far less predictable wp_rand() instead.', + 'since' => '2.6.2', + 'functions' => array( + 'rand', + 'mt_rand', + ), + ), + ); + } + + /** + * Process a matched token. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_matched_token( $stackPtr, $group_name, $matched_content ) { + + $this->get_wp_version_from_cl(); + + /* + * Deal with exceptions. + */ + switch ( $matched_content ) { + case 'strip_tags': + /* + * The function `wp_strip_all_tags()` is only a valid alternative when + * only the first parameter is passed to `strip_tags()`. + */ + if ( $this->get_function_call_parameter_count( $stackPtr ) !== 1 ) { + return; + } + + break; + + case 'wp_parse_url': + /* + * Before WP 4.7.0, the function `wp_parse_url()` was only a valid alternative + * if no second param was passed to `parse_url()`. + * + * @see https://developer.wordpress.org/reference/functions/wp_parse_url/#changelog + */ + if ( $this->get_function_call_parameter_count( $stackPtr ) !== 1 + && version_compare( $this->minimum_supported_version, '4.7.0', '<' ) + ) { + return; + } + + break; + + case 'file_get_contents': + /* + * Using `wp_remote_get()` will only work for remote URLs. + * See if we can determine is this function call is for a local file and if so, bow out. + */ + $params = $this->get_function_call_parameters( $stackPtr ); + + if ( isset( $params[2] ) && 'true' === $params[2]['raw'] ) { + // Setting `$use_include_path` to `true` is only relevant for local files. + return; + } + + if ( isset( $params[1] ) === false ) { + // If the file to get is not set, this is a non-issue anyway. + return; + } + + if ( strpos( $params[1]['raw'], 'http:' ) !== false + || strpos( $params[1]['raw'], 'https:' ) !== false + ) { + // Definitely a URL, throw notice. + break; + } + + if ( preg_match( '`\b(?:ABSPATH|WP_(?:CONTENT|PLUGIN)_DIR|WPMU_PLUGIN_DIR|TEMPLATEPATH|STYLESHEETPATH|(?:MU)?PLUGINDIR)\b`', $params[1]['raw'] ) === 1 ) { + // Using any of the constants matched in this regex is an indicator of a local file. + return; + } + + if ( preg_match( '`(?:get_home_path|plugin_dir_path|get_(?:stylesheet|template)_directory|wp_upload_dir)\s*\(`i', $params[1]['raw'] ) === 1 ) { + // Using any of the functions matched in the regex is an indicator of a local file. + return; + } + + if ( $this->is_local_data_stream( $params[1]['raw'] ) === true ) { + // Local data stream. + return; + } + + unset( $params ); + + break; + + case 'readfile': + case 'fopen': + case 'file_put_contents': + /* + * Allow for handling raw data streams from the request body. + */ + $first_param = $this->get_function_call_parameter( $stackPtr, 1 ); + + if ( false === $first_param ) { + // If the file to work with is not set, local data streams don't come into play. + break; + } + + if ( $this->is_local_data_stream( $first_param['raw'] ) === true ) { + // Local data stream. + return; + } + + unset( $first_param ); + + break; + } + + if ( ! isset( $this->groups[ $group_name ]['since'] ) ) { + return parent::process_matched_token( $stackPtr, $group_name, $matched_content ); + } + + // Verify if the alternative is available in the minimum supported WP version. + if ( version_compare( $this->groups[ $group_name ]['since'], $this->minimum_supported_version, '<=' ) ) { + return parent::process_matched_token( $stackPtr, $group_name, $matched_content ); + } + } + + /** + * Determine based on the "raw" parameter value, whether a file parameter points to + * a local data stream. + * + * @param string $raw_param_value Raw parameter value. + * + * @return bool True if this is a local data stream. False otherwise. + */ + protected function is_local_data_stream( $raw_param_value ) { + + $raw_stripped = $this->strip_quotes( $raw_param_value ); + if ( isset( $this->allowed_local_streams[ $raw_stripped ] ) + || isset( $this->allowed_local_stream_constants[ $raw_param_value ] ) + ) { + return true; + } + + foreach ( $this->allowed_local_stream_partials as $partial ) { + if ( strpos( $raw_stripped, $partial ) === 0 ) { + return true; + } + } + + return false; + } +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/CapitalPDangitSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/CapitalPDangitSniff.php new file mode 100644 index 00000000..bf98233f --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/CapitalPDangitSniff.php @@ -0,0 +1,292 @@ +\'"()]*?\.(?:php|js|css|png|j[e]?pg|gif|pot))#i'; + + /** + * Regex to match a large number or spelling variations of WordPress in class names. + * + * @var string + */ + const WP_CLASSNAME_REGEX = '`(?:^|_)(Word[_]*Pres+)(?:_|$)`i'; + + /** + * String tokens we want to listen for. + * + * @var array + */ + private $text_string_tokens = array( + \T_CONSTANT_ENCAPSED_STRING => \T_CONSTANT_ENCAPSED_STRING, + \T_DOUBLE_QUOTED_STRING => \T_DOUBLE_QUOTED_STRING, + \T_HEREDOC => \T_HEREDOC, + \T_NOWDOC => \T_NOWDOC, + \T_INLINE_HTML => \T_INLINE_HTML, + ); + + /** + * Comment tokens we want to listen for as they contain text strings. + * + * @var array + */ + private $comment_text_tokens = array( + \T_DOC_COMMENT => \T_DOC_COMMENT, + \T_DOC_COMMENT_STRING => \T_DOC_COMMENT_STRING, + \T_COMMENT => \T_COMMENT, + ); + + /** + * Combined text string and comment tokens array. + * + * This property is set in the register() method and used for lookups. + * + * @var array + */ + private $text_and_comment_tokens = array(); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 0.12.0 + * + * @return array + */ + public function register() { + // Union the arrays - keeps the array keys. + $this->text_and_comment_tokens = ( $this->text_string_tokens + $this->comment_text_tokens ); + + $targets = ( $this->text_and_comment_tokens + Tokens::$ooScopeTokens ); + + // Also sniff for array tokens to make skipping anything within those more efficient. + $targets[ \T_ARRAY ] = \T_ARRAY; + $targets[ \T_OPEN_SHORT_ARRAY ] = \T_OPEN_SHORT_ARRAY; + + return $targets; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.12.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + if ( $this->has_whitelist_comment( 'spelling', $stackPtr ) ) { + return; + } + + /* + * Ignore tokens within an array definition as this is a false positive in 80% of all cases. + * + * The return values skip to the end of the array. + * This prevents the sniff "hanging" on very long configuration arrays. + */ + if ( \T_OPEN_SHORT_ARRAY === $this->tokens[ $stackPtr ]['code'] && isset( $this->tokens[ $stackPtr ]['bracket_closer'] ) ) { + return $this->tokens[ $stackPtr ]['bracket_closer']; + } elseif ( \T_ARRAY === $this->tokens[ $stackPtr ]['code'] && isset( $this->tokens[ $stackPtr ]['parenthesis_closer'] ) ) { + return $this->tokens[ $stackPtr ]['parenthesis_closer']; + } + + /* + * Deal with misspellings in class/interface/trait names. + * These are not auto-fixable, but need the attention of a developer. + */ + if ( isset( Tokens::$ooScopeTokens[ $this->tokens[ $stackPtr ]['code'] ] ) ) { + $classname = $this->phpcsFile->getDeclarationName( $stackPtr ); + if ( empty( $classname ) ) { + return; + } + + if ( preg_match_all( self::WP_CLASSNAME_REGEX, $classname, $matches, \PREG_PATTERN_ORDER ) > 0 ) { + $mispelled = $this->retrieve_misspellings( $matches[1] ); + + if ( ! empty( $mispelled ) ) { + $this->phpcsFile->addWarning( + 'Please spell "WordPress" correctly. Found: "%s" as part of the class/interface/trait name.', + $stackPtr, + 'MisspelledClassName', + array( implode( ', ', $mispelled ) ) + ); + } + } + + return; + } + + /* + * Deal with misspellings in text strings and documentation. + */ + + // Ignore content of docblock @link tags. + if ( \T_DOC_COMMENT_STRING === $this->tokens[ $stackPtr ]['code'] + || \T_DOC_COMMENT === $this->tokens[ $stackPtr ]['code'] + ) { + + $comment_start = $this->phpcsFile->findPrevious( \T_DOC_COMMENT_OPEN_TAG, ( $stackPtr - 1 ) ); + if ( false !== $comment_start ) { + $comment_tag = $this->phpcsFile->findPrevious( \T_DOC_COMMENT_TAG, ( $stackPtr - 1 ), $comment_start ); + if ( false !== $comment_tag && '@link' === $this->tokens[ $comment_tag ]['content'] ) { + // @link tag, so ignore. + return; + } + } + } + + // Ignore any text strings which are array keys `$var['key']` as this is a false positive in 80% of all cases. + if ( \T_CONSTANT_ENCAPSED_STRING === $this->tokens[ $stackPtr ]['code'] ) { + $prevToken = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true, null, true ); + if ( false !== $prevToken && \T_OPEN_SQUARE_BRACKET === $this->tokens[ $prevToken ]['code'] ) { + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true, null, true ); + if ( false !== $nextToken && \T_CLOSE_SQUARE_BRACKET === $this->tokens[ $nextToken ]['code'] ) { + return; + } + } + } + + // Ignore constant declarations via define(). + if ( $this->is_in_function_call( $stackPtr, array( 'define' => true ), true, true ) ) { + return; + } + + // Ignore constant declarations using the const keyword. + $stop_points = array( + \T_CONST, + \T_SEMICOLON, + \T_OPEN_TAG, + \T_CLOSE_TAG, + \T_OPEN_CURLY_BRACKET, + ); + $maybe_const = $this->phpcsFile->findPrevious( $stop_points, ( $stackPtr - 1 ) ); + if ( false !== $maybe_const && \T_CONST === $this->tokens[ $maybe_const ]['code'] ) { + return; + } + + $content = $this->tokens[ $stackPtr ]['content']; + + if ( preg_match_all( self::WP_REGEX, $content, $matches, ( \PREG_PATTERN_ORDER | \PREG_OFFSET_CAPTURE ) ) > 0 ) { + /* + * Prevent some typical false positives. + */ + if ( isset( $this->text_and_comment_tokens[ $this->tokens[ $stackPtr ]['code'] ] ) ) { + $offset = 0; + foreach ( $matches[1] as $key => $match_data ) { + $next_offset = ( $match_data[1] + \strlen( $match_data[0] ) ); + + // Prevent matches on part of a URL. + if ( preg_match( '`http[s]?://[^\s<>\'"()]*' . preg_quote( $match_data[0], '`' ) . '`', $content, $discard, 0, $offset ) === 1 ) { + unset( $matches[1][ $key ] ); + } elseif ( preg_match( '`[a-z]+=(["\'])' . preg_quote( $match_data[0], '`' ) . '\1`', $content, $discard, 0, $offset ) === 1 ) { + // Prevent matches on html attributes like: `value="wordpress"`. + unset( $matches[1][ $key ] ); + } elseif ( preg_match( '`\\\\\'' . preg_quote( $match_data[0], '`' ) . '\\\\\'`', $content, $discard, 0, $offset ) === 1 ) { + // Prevent matches on xpath queries and such: `\'wordpress\'`. + unset( $matches[1][ $key ] ); + } elseif ( preg_match( '`(?:\?|&|&)[a-z0-9_]+=' . preg_quote( $match_data[0], '`' ) . '(?:&|$)`', $content, $discard, 0, $offset ) === 1 ) { + // Prevent matches on url query strings: `?something=wordpress`. + unset( $matches[1][ $key ] ); + } + + $offset = $next_offset; + } + + if ( empty( $matches[1] ) ) { + return; + } + } + + $mispelled = $this->retrieve_misspellings( $matches[1] ); + + if ( empty( $mispelled ) ) { + return; + } + + $fix = $this->phpcsFile->addFixableWarning( + 'Please spell "WordPress" correctly. Found %s misspelling(s): %s', + $stackPtr, + 'Misspelled', + array( + \count( $mispelled ), + implode( ', ', $mispelled ), + ) + ); + + if ( true === $fix ) { + // Apply fixes based on offset to ensure we don't replace false positives. + $replacement = $content; + foreach ( $matches[1] as $match ) { + $replacement = substr_replace( $replacement, 'WordPress', $match[1], \strlen( $match[0] ) ); + } + + $this->phpcsFile->fixer->replaceToken( $stackPtr, $replacement ); + } + } + } + + /** + * Retrieve a list of misspellings based on an array of matched variations on the target word. + * + * @param array $match_stack Array of matched variations of the target word. + * @return array Array containing only the misspelled variants. + */ + protected function retrieve_misspellings( $match_stack ) { + $mispelled = array(); + foreach ( $match_stack as $match ) { + // Deal with multi-dimensional arrays when capturing offset. + if ( \is_array( $match ) ) { + $match = $match[0]; + } + + if ( 'WordPress' !== $match ) { + $mispelled[] = $match; + } + } + + return $mispelled; + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/CronIntervalSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/CronIntervalSniff.php new file mode 100644 index 00000000..7cfdddd9 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/CronIntervalSniff.php @@ -0,0 +1,235 @@ + 60, + 'HOUR_IN_SECONDS' => 3600, + 'DAY_IN_SECONDS' => 86400, + 'WEEK_IN_SECONDS' => 604800, + 'MONTH_IN_SECONDS' => 2592000, + 'YEAR_IN_SECONDS' => 31536000, + ); + + /** + * Function within which the hook should be found. + * + * @var array + */ + protected $valid_functions = array( + 'add_filter' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array( + \T_CONSTANT_ENCAPSED_STRING, + \T_DOUBLE_QUOTED_STRING, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + $token = $this->tokens[ $stackPtr ]; + + if ( 'cron_schedules' !== $this->strip_quotes( $token['content'] ) ) { + return; + } + + // If within add_filter. + $functionPtr = $this->is_in_function_call( $stackPtr, $this->valid_functions ); + if ( false === $functionPtr ) { + return; + } + + $callback = $this->get_function_call_parameter( $functionPtr, 2 ); + if ( false === $callback ) { + return; + } + + if ( $stackPtr >= $callback['start'] ) { + // "cron_schedules" found in the second parameter, not the first. + return; + } + + // Detect callback function name. + $callbackArrayPtr = $this->phpcsFile->findNext( Tokens::$emptyTokens, $callback['start'], ( $callback['end'] + 1 ), true ); + + // If callback is array, get second element. + if ( false !== $callbackArrayPtr + && ( \T_ARRAY === $this->tokens[ $callbackArrayPtr ]['code'] + || \T_OPEN_SHORT_ARRAY === $this->tokens[ $callbackArrayPtr ]['code'] ) + ) { + $callback = $this->get_function_call_parameter( $callbackArrayPtr, 2 ); + + if ( false === $callback ) { + $this->confused( $stackPtr ); + return; + } + } + + unset( $functionPtr ); + + // Search for the function in tokens. + $callbackFunctionPtr = $this->phpcsFile->findNext( array( \T_CONSTANT_ENCAPSED_STRING, \T_DOUBLE_QUOTED_STRING, \T_CLOSURE ), $callback['start'], ( $callback['end'] + 1 ) ); + + if ( false === $callbackFunctionPtr ) { + $this->confused( $stackPtr ); + return; + } + + if ( \T_CLOSURE === $this->tokens[ $callbackFunctionPtr ]['code'] ) { + $functionPtr = $callbackFunctionPtr; + } else { + $functionName = $this->strip_quotes( $this->tokens[ $callbackFunctionPtr ]['content'] ); + + for ( $ptr = 0; $ptr < $this->phpcsFile->numTokens; $ptr++ ) { + if ( \T_FUNCTION === $this->tokens[ $ptr ]['code'] ) { + $foundName = $this->phpcsFile->getDeclarationName( $ptr ); + if ( $foundName === $functionName ) { + $functionPtr = $ptr; + break; + } elseif ( isset( $this->tokens[ $ptr ]['scope_closer'] ) ) { + // Skip to the end of the function definition. + $ptr = $this->tokens[ $ptr ]['scope_closer']; + } + } + } + } + + if ( ! isset( $functionPtr ) ) { + $this->confused( $stackPtr ); + return; + } + + if ( ! isset( $this->tokens[ $functionPtr ]['scope_opener'], $this->tokens[ $functionPtr ]['scope_closer'] ) ) { + return; + } + + $opening = $this->tokens[ $functionPtr ]['scope_opener']; + $closing = $this->tokens[ $functionPtr ]['scope_closer']; + for ( $i = $opening; $i <= $closing; $i++ ) { + + if ( \in_array( $this->tokens[ $i ]['code'], array( \T_CONSTANT_ENCAPSED_STRING, \T_DOUBLE_QUOTED_STRING ), true ) ) { + if ( 'interval' === $this->strip_quotes( $this->tokens[ $i ]['content'] ) ) { + $operator = $this->phpcsFile->findNext( \T_DOUBLE_ARROW, $i, null, false, null, true ); + if ( false === $operator ) { + $this->confused( $stackPtr ); + return; + } + + $valueStart = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $operator + 1 ), null, true, null, true ); + $valueEnd = $this->phpcsFile->findNext( array( \T_COMMA, \T_CLOSE_PARENTHESIS ), ( $valueStart + 1 ) ); + $value = ''; + for ( $j = $valueStart; $j < $valueEnd; $j++ ) { + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $j ]['code'] ] ) ) { + continue; + } + $value .= $this->tokens[ $j ]['content']; + } + + if ( is_numeric( $value ) ) { + $interval = $value; + break; + } + + // Deal correctly with WP time constants. + $value = str_replace( array_keys( $this->wp_time_constants ), array_values( $this->wp_time_constants ), $value ); + + // If all digits and operators, eval! + if ( preg_match( '#^[\s\d+*/-]+$#', $value ) > 0 ) { + $interval = eval( "return ( $value );" ); // phpcs:ignore Squiz.PHP.Eval -- No harm here. + break; + } + + $this->confused( $stackPtr ); + return; + } + } + } + + $this->min_interval = (int) $this->min_interval; + + if ( isset( $interval ) && $interval < $this->min_interval ) { + $minutes = round( ( $this->min_interval / 60 ), 1 ); + $this->phpcsFile->addWarning( + 'Scheduling crons at %s sec ( less than %s minutes ) is discouraged.', + $stackPtr, + 'CronSchedulesInterval', + array( + $interval, + $minutes, + ) + ); + return; + } + } + + /** + * Add warning about unclear cron schedule change. + * + * @param int $stackPtr The position of the current token in the stack. + */ + public function confused( $stackPtr ) { + $this->phpcsFile->addWarning( + 'Detected changing of cron_schedules, but could not detect the interval value.', + $stackPtr, + 'ChangeDetected' + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedClassesSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedClassesSniff.php new file mode 100644 index 00000000..9d1f95bf --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedClassesSniff.php @@ -0,0 +1,120 @@ + value + * in a custom ruleset. + * + * @uses \WordPressCS\WordPress\Sniff::$minimum_supported_version + */ +class DeprecatedClassesSniff extends AbstractClassRestrictionsSniff { + + /** + * List of deprecated classes with alternative when available. + * + * To be updated after every major release. + * + * Version numbers should be fully qualified. + * + * @var array + */ + private $deprecated_classes = array( + + // WP 3.1.0. + 'WP_User_Search' => array( + 'alt' => 'WP_User_Query', + 'version' => '3.1.0', + ), + + // WP 4.9.0. + 'Customize_New_Menu_Section' => array( + 'version' => '4.9.0', + ), + 'WP_Customize_New_Menu_Control' => array( + 'version' => '4.9.0', + ), + + // WP 5.3.0. + 'Services_JSON' => array( + 'alt' => 'The PHP native JSON extension', + 'version' => '5.3.0', + ), + ); + + + /** + * Groups of classes to restrict. + * + * @return array + */ + public function getGroups() { + // Make sure all array keys are lowercase. + $this->deprecated_classes = array_change_key_case( $this->deprecated_classes, CASE_LOWER ); + + return array( + 'deprecated_classes' => array( + 'classes' => array_keys( $this->deprecated_classes ), + ), + ); + } + + /** + * Process a matched token. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. Will + * always be 'deprecated_classes'. + * @param string $matched_content The token content (class name) which was matched. + * + * @return void + */ + public function process_matched_token( $stackPtr, $group_name, $matched_content ) { + + $this->get_wp_version_from_cl(); + + $class_name = ltrim( strtolower( $matched_content ), '\\' ); + + $message = 'The %s class has been deprecated since WordPress version %s.'; + $data = array( + ltrim( $matched_content, '\\' ), + $this->deprecated_classes[ $class_name ]['version'], + ); + + if ( ! empty( $this->deprecated_classes[ $class_name ]['alt'] ) ) { + $message .= ' Use %s instead.'; + $data[] = $this->deprecated_classes[ $class_name ]['alt']; + } + + $this->addMessage( + $message, + $stackPtr, + ( version_compare( $this->deprecated_classes[ $class_name ]['version'], $this->minimum_supported_version, '<' ) ), + $this->string_to_errorcode( $class_name . 'Found' ), + $data + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedFunctionsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedFunctionsSniff.php new file mode 100644 index 00000000..df7a4b55 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedFunctionsSniff.php @@ -0,0 +1,1422 @@ + value + * in a custom ruleset. + * + * @uses \WordPressCS\WordPress\Sniff::$minimum_supported_version + */ +class DeprecatedFunctionsSniff extends AbstractFunctionRestrictionsSniff { + + /** + * List of deprecated functions with alternative when available. + * + * To be updated after every major release. + * Last updated for WordPress 4.8. + * + * Version numbers should be fully qualified. + * Replacement functions should have parentheses. + * + * To retrieve a function list for comparison, the following tool is available: + * https://github.com/JDGrimes/wp-deprecated-code-scanner + * + * @var array + */ + private $deprecated_functions = array( + + // WP 0.71. + 'the_category_head' => array( + 'alt' => 'get_the_category_by_ID()', + 'version' => '0.71', + ), + 'the_category_ID' => array( + 'alt' => 'get_the_category()', + 'version' => '0.71', + ), + + // WP 1.2.0. + 'permalink_link' => array( + 'alt' => 'the_permalink()', + 'version' => '1.2.0', + ), + + // WP 1.5.0. + 'start_wp' => array( + // Verified correct alternative. + 'alt' => 'the Loop', + 'version' => '1.5.0', + ), + + // WP 1.5.1. + 'get_postdata' => array( + 'alt' => 'get_post()', + 'version' => '1.5.1', + ), + + // WP 2.0.0. + 'create_user' => array( + 'alt' => 'wp_create_user()', + 'version' => '2.0.0', + ), + 'next_post' => array( + 'alt' => 'next_post_link()', + 'version' => '2.0.0', + ), + 'previous_post' => array( + 'alt' => 'previous_post_link()', + 'version' => '2.0.0', + ), + 'user_can_create_draft' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_create_post' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_delete_post' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_delete_post_comments' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_edit_post' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_edit_post_comments' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_edit_post_date' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_edit_user' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_set_post_date' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + + // WP 2.1.0. + 'dropdown_cats' => array( + 'alt' => 'wp_dropdown_categories()', + 'version' => '2.1.0', + ), + 'get_archives' => array( + 'alt' => 'wp_get_archives()', + 'version' => '2.1.0', + ), + 'get_author_link' => array( + 'alt' => 'get_author_posts_url()', + 'version' => '2.1.0', + ), + 'get_autotoggle' => array( + 'alt' => '', + 'version' => '2.1.0', + ), + 'get_link' => array( + 'alt' => 'get_bookmark()', + 'version' => '2.1.0', + ), + 'get_linkcatname' => array( + 'alt' => 'get_category()', + 'version' => '2.1.0', + ), + 'get_linkobjects' => array( + 'alt' => 'get_bookmarks()', + 'version' => '2.1.0', + ), + 'get_linkobjectsbyname' => array( + 'alt' => 'get_bookmarks()', + 'version' => '2.1.0', + ), + 'get_linkrating' => array( + 'alt' => 'sanitize_bookmark_field()', + 'version' => '2.1.0', + ), + 'get_links' => array( + 'alt' => 'get_bookmarks()', + 'version' => '2.1.0', + ), + 'get_links_list' => array( + 'alt' => 'wp_list_bookmarks()', + 'version' => '2.1.0', + ), + 'get_links_withrating' => array( + 'alt' => 'get_bookmarks()', + 'version' => '2.1.0', + ), + 'get_linksbyname' => array( + 'alt' => 'get_bookmarks()', + 'version' => '2.1.0', + ), + 'get_linksbyname_withrating' => array( + 'alt' => 'get_bookmarks()', + 'version' => '2.1.0', + ), + 'get_settings' => array( + 'alt' => 'get_option()', + 'version' => '2.1.0', + ), + 'link_pages' => array( + 'alt' => 'wp_link_pages()', + 'version' => '2.1.0', + ), + 'links_popup_script' => array( + 'alt' => '', + 'version' => '2.1.0', + ), + 'list_authors' => array( + 'alt' => 'wp_list_authors()', + 'version' => '2.1.0', + ), + 'list_cats' => array( + 'alt' => 'wp_list_categories()', + 'version' => '2.1.0', + ), + 'tinymce_include' => array( + 'alt' => 'wp_editor()', + 'version' => '2.1.0', + ), + 'wp_get_links' => array( + 'alt' => 'wp_list_bookmarks()', + 'version' => '2.1.0', + ), + 'wp_get_linksbyname' => array( + 'alt' => 'wp_list_bookmarks()', + 'version' => '2.1.0', + ), + 'wp_get_post_cats' => array( + 'alt' => 'wp_get_post_categories()', + 'version' => '2.1.0', + ), + 'wp_list_cats' => array( + 'alt' => 'wp_list_categories()', + 'version' => '2.1.0', + ), + 'wp_set_post_cats' => array( + 'alt' => 'wp_set_post_categories()', + 'version' => '2.1.0', + ), + + // WP 2.2.0. + 'comments_rss' => array( + 'alt' => 'get_post_comments_feed_link()', + 'version' => '2.2.0', + ), + + // WP 2.3.0. + 'permalink_single_rss' => array( + 'alt' => 'the_permalink_rss()', + 'version' => '2.3.0', + ), + + // WP 2.5.0. + 'comments_rss_link' => array( + 'alt' => 'post_comments_feed_link()', + 'version' => '2.5.0', + ), + 'documentation_link' => array( + 'alt' => '', + 'version' => '2.5.0', + ), + 'get_attachment_icon' => array( + 'alt' => 'wp_get_attachment_image()', + 'version' => '2.5.0', + ), + 'get_attachment_icon_src' => array( + 'alt' => 'wp_get_attachment_image_src()', + 'version' => '2.5.0', + ), + 'get_attachment_innerHTML' => array( + 'alt' => 'wp_get_attachment_image()', + 'version' => '2.5.0', + ), + 'get_author_rss_link' => array( + 'alt' => 'get_author_feed_link()', + 'version' => '2.5.0', + ), + 'get_category_rss_link' => array( + 'alt' => 'get_category_feed_link()', + 'version' => '2.5.0', + ), + 'get_the_attachment_link' => array( + 'alt' => 'wp_get_attachment_link()', + 'version' => '2.5.0', + ), + 'gzip_compression' => array( + 'alt' => '', + 'version' => '2.5.0', + ), + 'wp_clearcookie' => array( + 'alt' => 'wp_clear_auth_cookie()', + 'version' => '2.5.0', + ), + 'wp_get_cookie_login' => array( + 'alt' => '', + 'version' => '2.5.0', + ), + 'wp_login' => array( + 'alt' => 'wp_signon()', + 'version' => '2.5.0', + ), + 'wp_setcookie' => array( + 'alt' => 'wp_set_auth_cookie()', + 'version' => '2.5.0', + ), + + // WP 2.6.0. + 'dropdown_categories' => array( + 'alt' => 'wp_category_checklist()', + 'version' => '2.6.0', + ), + 'dropdown_link_categories' => array( + 'alt' => 'wp_link_category_checklist()', + 'version' => '2.6.0', + ), + + // WP 2.7.0. + 'get_commentdata' => array( + 'alt' => 'get_comment()', + 'version' => '2.7.0', + ), + // This is a method i.e. WP_Filesystem_Base::find_base_dir() See #731. + 'find_base_dir' => array( + 'alt' => 'WP_Filesystem::abspath()', + 'version' => '2.7.0', + ), + // This is a method i.e. WP_Filesystem_Base::get_base_dir() See #731. + 'get_base_dir' => array( + 'alt' => 'WP_Filesystem::abspath()', + 'version' => '2.7.0', + ), + + // WP 2.8.0. + '__ngettext' => array( + 'alt' => '_n()', + 'version' => '2.8.0', + ), + '__ngettext_noop' => array( + 'alt' => '_n_noop()', + 'version' => '2.8.0', + ), + 'attribute_escape' => array( + 'alt' => 'esc_attr()', + 'version' => '2.8.0', + ), + 'get_author_name' => array( + 'alt' => 'get_the_author_meta(\'display_name\')', + 'version' => '2.8.0', + ), + 'get_category_children' => array( + 'alt' => 'get_term_children()', + 'version' => '2.8.0', + ), + 'get_catname' => array( + 'alt' => 'get_cat_name()', + 'version' => '2.8.0', + ), + 'get_the_author_aim' => array( + 'alt' => 'get_the_author_meta(\'aim\')', + 'version' => '2.8.0', + ), + 'get_the_author_description' => array( + 'alt' => 'get_the_author_meta(\'description\')', + 'version' => '2.8.0', + ), + 'get_the_author_email' => array( + 'alt' => 'get_the_author_meta(\'email\')', + 'version' => '2.8.0', + ), + 'get_the_author_firstname' => array( + 'alt' => 'get_the_author_meta(\'first_name\')', + 'version' => '2.8.0', + ), + 'get_the_author_icq' => array( + 'alt' => 'get_the_author_meta(\'icq\')', + 'version' => '2.8.0', + ), + 'get_the_author_ID' => array( + 'alt' => 'get_the_author_meta(\'ID\')', + 'version' => '2.8.0', + ), + 'get_the_author_lastname' => array( + 'alt' => 'get_the_author_meta(\'last_name\')', + 'version' => '2.8.0', + ), + 'get_the_author_login' => array( + 'alt' => 'get_the_author_meta(\'login\')', + 'version' => '2.8.0', + ), + 'get_the_author_msn' => array( + 'alt' => 'get_the_author_meta(\'msn\')', + 'version' => '2.8.0', + ), + 'get_the_author_nickname' => array( + 'alt' => 'get_the_author_meta(\'nickname\')', + 'version' => '2.8.0', + ), + 'get_the_author_url' => array( + 'alt' => 'get_the_author_meta(\'url\')', + 'version' => '2.8.0', + ), + 'get_the_author_yim' => array( + 'alt' => 'get_the_author_meta(\'yim\')', + 'version' => '2.8.0', + ), + 'js_escape' => array( + 'alt' => 'esc_js()', + 'version' => '2.8.0', + ), + 'register_sidebar_widget' => array( + 'alt' => 'wp_register_sidebar_widget()', + 'version' => '2.8.0', + ), + 'register_widget_control' => array( + 'alt' => 'wp_register_widget_control()', + 'version' => '2.8.0', + ), + 'sanitize_url' => array( + 'alt' => 'esc_url_raw()', + 'version' => '2.8.0', + ), + 'the_author_aim' => array( + 'alt' => 'the_author_meta(\'aim\')', + 'version' => '2.8.0', + ), + 'the_author_description' => array( + 'alt' => 'the_author_meta(\'description\')', + 'version' => '2.8.0', + ), + 'the_author_email' => array( + 'alt' => 'the_author_meta(\'email\')', + 'version' => '2.8.0', + ), + 'the_author_firstname' => array( + 'alt' => 'the_author_meta(\'first_name\')', + 'version' => '2.8.0', + ), + 'the_author_icq' => array( + 'alt' => 'the_author_meta(\'icq\')', + 'version' => '2.8.0', + ), + 'the_author_ID' => array( + 'alt' => 'the_author_meta(\'ID\')', + 'version' => '2.8.0', + ), + 'the_author_lastname' => array( + 'alt' => 'the_author_meta(\'last_name\')', + 'version' => '2.8.0', + ), + 'the_author_login' => array( + 'alt' => 'the_author_meta(\'login\')', + 'version' => '2.8.0', + ), + 'the_author_msn' => array( + 'alt' => 'the_author_meta(\'msn\')', + 'version' => '2.8.0', + ), + 'the_author_nickname' => array( + 'alt' => 'the_author_meta(\'nickname\')', + 'version' => '2.8.0', + ), + 'the_author_url' => array( + 'alt' => 'the_author_meta(\'url\')', + 'version' => '2.8.0', + ), + 'the_author_yim' => array( + 'alt' => 'the_author_meta(\'yim\')', + 'version' => '2.8.0', + ), + 'unregister_sidebar_widget' => array( + 'alt' => 'wp_unregister_sidebar_widget()', + 'version' => '2.8.0', + ), + 'unregister_widget_control' => array( + 'alt' => 'wp_unregister_widget_control()', + 'version' => '2.8.0', + ), + 'wp_specialchars' => array( + 'alt' => 'esc_html()', + 'version' => '2.8.0', + ), + + // WP 2.9.0. + '_c' => array( + 'alt' => '_x()', + 'version' => '2.9.0', + ), + '_nc' => array( + 'alt' => '_nx()', + 'version' => '2.9.0', + ), + 'get_real_file_to_edit' => array( + 'alt' => '', + 'version' => '2.9.0', + ), + 'make_url_footnote' => array( + 'alt' => '', + 'version' => '2.9.0', + ), + 'the_content_rss' => array( + 'alt' => 'the_content_feed()', + 'version' => '2.9.0', + ), + 'translate_with_context' => array( + 'alt' => '_x()', + 'version' => '2.9.0', + ), + + // WP 3.0.0. + 'activate_sitewide_plugin' => array( + 'alt' => 'activate_plugin()', + 'version' => '3.0.0', + ), + 'add_option_update_handler' => array( + 'alt' => 'register_setting()', + 'version' => '3.0.0', + ), + 'automatic_feed_links' => array( + 'alt' => 'add_theme_support( \'automatic-feed-links\' )', + 'version' => '3.0.0', + ), + 'clean_url' => array( + 'alt' => 'esc_url()', + 'version' => '3.0.0', + ), + 'clear_global_post_cache' => array( + 'alt' => 'clean_post_cache()', + 'version' => '3.0.0', + ), + 'codepress_footer_js' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + 'codepress_get_lang' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + 'deactivate_sitewide_plugin' => array( + 'alt' => 'deactivate_plugin()', + 'version' => '3.0.0', + ), + 'delete_usermeta' => array( + 'alt' => 'delete_user_meta()', + 'version' => '3.0.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'funky_javascript_callback' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + 'funky_javascript_fix' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + 'generate_random_password' => array( + 'alt' => 'wp_generate_password()', + 'version' => '3.0.0', + ), + 'get_alloptions' => array( + 'alt' => 'wp_load_alloptions()', + 'version' => '3.0.0', + ), + 'get_blog_list' => array( + 'alt' => 'wp_get_sites()', + 'version' => '3.0.0', + ), + 'get_most_active_blogs' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + 'get_profile' => array( + 'alt' => 'get_the_author_meta()', + 'version' => '3.0.0', + ), + 'get_user_details' => array( + 'alt' => 'get_user_by()', + 'version' => '3.0.0', + ), + 'get_usermeta' => array( + 'alt' => 'get_user_meta()', + 'version' => '3.0.0', + ), + 'get_usernumposts' => array( + 'alt' => 'count_user_posts()', + 'version' => '3.0.0', + ), + 'graceful_fail' => array( + 'alt' => 'wp_die()', + 'version' => '3.0.0', + ), + // Verified version & alternative. + 'install_blog_defaults' => array( + 'alt' => 'wp_install_defaults', + 'version' => '3.0.0', + ), + 'is_main_blog' => array( + 'alt' => 'is_main_site()', + 'version' => '3.0.0', + ), + 'is_site_admin' => array( + 'alt' => 'is_super_admin()', + 'version' => '3.0.0', + ), + 'is_taxonomy' => array( + 'alt' => 'taxonomy_exists()', + 'version' => '3.0.0', + ), + 'is_term' => array( + 'alt' => 'term_exists()', + 'version' => '3.0.0', + ), + 'is_wpmu_sitewide_plugin' => array( + 'alt' => 'is_network_only_plugin()', + 'version' => '3.0.0', + ), + 'mu_options' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + 'remove_option_update_handler' => array( + 'alt' => 'unregister_setting()', + 'version' => '3.0.0', + ), + 'set_current_user' => array( + 'alt' => 'wp_set_current_user()', + 'version' => '3.0.0', + ), + 'update_usermeta' => array( + 'alt' => 'update_user_meta()', + 'version' => '3.0.0', + ), + 'use_codepress' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + 'validate_email' => array( + 'alt' => 'is_email()', + 'version' => '3.0.0', + ), + 'wp_dropdown_cats' => array( + 'alt' => 'wp_dropdown_categories()', + 'version' => '3.0.0', + ), + 'wp_shrink_dimensions' => array( + 'alt' => 'wp_constrain_dimensions()', + 'version' => '3.0.0', + ), + 'wpmu_checkAvailableSpace' => array( + 'alt' => 'is_upload_space_available()', + 'version' => '3.0.0', + ), + 'wpmu_menu' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + + // WP 3.1.0. + 'get_author_user_ids' => array( + 'alt' => 'get_users()', + 'version' => '3.1.0', + ), + 'get_dashboard_blog' => array( + 'alt' => 'get_site()', + 'version' => '3.1.0', + ), + 'get_editable_authors' => array( + 'alt' => 'get_users()', + 'version' => '3.1.0', + ), + 'get_editable_user_ids' => array( + 'alt' => 'get_users()', + 'version' => '3.1.0', + ), + 'get_nonauthor_user_ids' => array( + 'alt' => 'get_users()', + 'version' => '3.1.0', + ), + 'get_others_drafts' => array( + 'alt' => '', + 'version' => '3.1.0', + ), + 'get_others_pending' => array( + 'alt' => '', + 'version' => '3.1.0', + ), + 'get_others_unpublished_posts' => array( + 'alt' => '', + 'version' => '3.1.0', + ), + 'get_users_of_blog' => array( + 'alt' => 'get_users()', + 'version' => '3.1.0', + ), + 'install_themes_feature_list' => array( + 'alt' => 'get_theme_feature_list()', + 'version' => '3.1.0', + ), + 'is_plugin_page' => array( + // Verified correct alternative. + 'alt' => 'global $plugin_page and/or get_plugin_page_hookname() hooks', + 'version' => '3.1.0', + ), + 'update_category_cache' => array( + 'alt' => '', + 'version' => '3.1.0', + ), + + // WP 3.2.0. + 'favorite_actions' => array( + 'alt' => 'WP_Admin_Bar', + 'version' => '3.2.0', + ), + 'wp_dashboard_quick_press_output' => array( + 'alt' => 'wp_dashboard_quick_press()', + 'version' => '3.2.0', + ), + 'wp_timezone_supported' => array( + 'alt' => '', + 'version' => '3.2.0', + ), + + // WP 3.3.0. + 'add_contextual_help' => array( + 'alt' => 'get_current_screen()->add_help_tab()', + 'version' => '3.3.0', + ), + 'get_boundary_post_rel_link' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'get_index_rel_link' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'get_parent_post_rel_link' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'get_user_by_email' => array( + 'alt' => 'get_user_by(\'email\')', + 'version' => '3.3.0', + ), + 'get_user_metavalues' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'get_userdatabylogin' => array( + 'alt' => 'get_user_by(\'login\')', + 'version' => '3.3.0', + ), + 'index_rel_link' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'is_blog_user' => array( + 'alt' => 'is_user_member_of_blog()', + 'version' => '3.3.0', + ), + 'media_upload_audio' => array( + 'alt' => 'wp_media_upload_handler()', + 'version' => '3.3.0', + ), + 'media_upload_file' => array( + 'alt' => 'wp_media_upload_handler()', + 'version' => '3.3.0', + ), + 'media_upload_image' => array( + 'alt' => 'wp_media_upload_handler()', + 'version' => '3.3.0', + ), + 'media_upload_video' => array( + 'alt' => 'wp_media_upload_handler()', + 'version' => '3.3.0', + ), + 'parent_post_rel_link' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'sanitize_user_object' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'screen_layout' => array( + 'alt' => '$current_screen->render_screen_layout()', + 'version' => '3.3.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'screen_meta' => array( + 'alt' => '$current_screen->render_screen_meta()', + 'version' => '3.3.0', + ), + 'screen_options' => array( + 'alt' => '$current_screen->render_per_page_options()', + 'version' => '3.3.0', + ), + 'start_post_rel_link' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'the_editor' => array( + 'alt' => 'wp_editor()', + 'version' => '3.3.0', + ), + 'type_url_form_audio' => array( + 'alt' => 'wp_media_insert_url_form(\'audio\')', + 'version' => '3.3.0', + ), + 'type_url_form_file' => array( + 'alt' => 'wp_media_insert_url_form(\'file\')', + 'version' => '3.3.0', + ), + 'type_url_form_image' => array( + 'alt' => 'wp_media_insert_url_form(\'image\')', + 'version' => '3.3.0', + ), + 'type_url_form_video' => array( + 'alt' => 'wp_media_insert_url_form(\'video\')', + 'version' => '3.3.0', + ), + 'wp_admin_bar_dashboard_view_site_menu' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'wp_preload_dialogs' => array( + 'alt' => 'wp_editor()', + 'version' => '3.3.0', + ), + 'wp_print_editor_js' => array( + 'alt' => 'wp_editor()', + 'version' => '3.3.0', + ), + 'wp_quicktags' => array( + 'alt' => 'wp_editor()', + 'version' => '3.3.0', + ), + 'wp_tiny_mce' => array( + 'alt' => 'wp_editor()', + 'version' => '3.3.0', + ), + 'wpmu_admin_do_redirect' => array( + 'alt' => 'wp_redirect()', + 'version' => '3.3.0', + ), + 'wpmu_admin_redirect_add_updated_param' => array( + 'alt' => 'add_query_arg()', + 'version' => '3.3.0', + ), + + // WP 3.4.0. + 'add_custom_background' => array( + 'alt' => 'add_theme_support( \'custom-background\', $args )', + 'version' => '3.4.0', + ), + 'add_custom_image_header' => array( + 'alt' => 'add_theme_support( \'custom-header\', $args )', + 'version' => '3.4.0', + ), + 'clean_page_cache' => array( + 'alt' => 'clean_post_cache()', + 'version' => '3.4.0', + ), + 'clean_pre' => array( + 'alt' => '', + 'version' => '3.4.0', + ), + 'current_theme_info' => array( + 'alt' => 'wp_get_theme()', + 'version' => '3.4.0', + ), + 'debug_fclose' => array( + 'alt' => 'error_log()', + 'version' => '3.4.0', + ), + 'debug_fopen' => array( + 'alt' => 'error_log()', + 'version' => '3.4.0', + ), + 'debug_fwrite' => array( + 'alt' => 'error_log()', + 'version' => '3.4.0', + ), + 'display_theme' => array( + 'alt' => '', + 'version' => '3.4.0', + ), + 'get_allowed_themes' => array( + 'alt' => 'wp_get_themes( array( \'allowed\' => true ) )', + 'version' => '3.4.0', + ), + 'get_broken_themes' => array( + 'alt' => 'wp_get_themes( array( \'errors\' => true )', + 'version' => '3.4.0', + ), + 'get_current_theme' => array( + 'alt' => 'wp_get_theme()', + 'version' => '3.4.0', + ), + 'get_site_allowed_themes' => array( + 'alt' => 'WP_Theme::get_allowed_on_network()', + 'version' => '3.4.0', + ), + 'get_theme' => array( + 'alt' => 'wp_get_theme( $stylesheet )', + 'version' => '3.4.0', + ), + 'get_theme_data' => array( + 'alt' => 'wp_get_theme()', + 'version' => '3.4.0', + ), + 'get_themes' => array( + 'alt' => 'wp_get_themes()', + 'version' => '3.4.0', + ), + 'logIO' => array( + 'alt' => 'error_log()', + 'version' => '3.4.0', + ), + 'remove_custom_background' => array( + 'alt' => 'remove_theme_support( \'custom-background\' )', + 'version' => '3.4.0', + ), + 'remove_custom_image_header' => array( + 'alt' => 'remove_theme_support( \'custom-header\' )', + 'version' => '3.4.0', + ), + 'update_page_cache' => array( + 'alt' => 'update_post_cache()', + 'version' => '3.4.0', + ), + 'wpmu_get_blog_allowedthemes' => array( + 'alt' => 'WP_Theme::get_allowed_on_site()', + 'version' => '3.4.0', + ), + + // WP 3.4.1. + 'wp_explain_nonce' => array( + 'alt' => 'wp_nonce_ays()', + 'version' => '3.4.1', + ), + + // WP 3.5.0. + '_flip_image_resource' => array( + 'alt' => 'WP_Image_Editor::flip()', + 'version' => '3.5.0', + ), + '_get_post_ancestors' => array( + 'alt' => '', + 'version' => '3.5.0', + ), + '_insert_into_post_button' => array( + 'alt' => '', + 'version' => '3.5.0', + ), + '_media_button' => array( + 'alt' => '', + 'version' => '3.5.0', + ), + '_rotate_image_resource' => array( + 'alt' => 'WP_Image_Editor::rotate()', + 'version' => '3.5.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + '_save_post_hook' => array( + 'alt' => '', + 'version' => '3.5.0', + ), + 'gd_edit_image_support' => array( + 'alt' => 'wp_image_editor_supports()', + 'version' => '3.5.0', + ), + 'get_default_page_to_edit' => array( + 'alt' => 'get_default_post_to_edit( \'page\' )', + 'version' => '3.5.0', + ), + 'get_post_to_edit' => array( + 'alt' => 'get_post()', + 'version' => '3.5.0', + ), + 'get_udims' => array( + 'alt' => 'wp_constrain_dimensions()', + 'version' => '3.5.0', + ), + 'image_resize' => array( + 'alt' => 'wp_get_image_editor()', + 'version' => '3.5.0', + ), + 'sticky_class' => array( + 'alt' => 'post_class()', + 'version' => '3.5.0', + ), + 'user_pass_ok' => array( + 'alt' => 'wp_authenticate()', + 'version' => '3.5.0', + ), + 'wp_cache_reset' => array( + 'alt' => 'WP_Object_Cache::reset()', + 'version' => '3.5.0', + ), + 'wp_create_thumbnail' => array( + 'alt' => 'image_resize()', + 'version' => '3.5.0', + ), + 'wp_get_single_post' => array( + 'alt' => 'get_post()', + 'version' => '3.5.0', + ), + 'wp_load_image' => array( + 'alt' => 'wp_get_image_editor()', + 'version' => '3.5.0', + ), + + // WP 3.6.0. + 'get_user_id_from_string' => array( + 'alt' => 'get_user_by()', + 'version' => '3.6.0', + ), + 'wp_convert_bytes_to_hr' => array( + 'alt' => 'size_format()', + 'version' => '3.6.0', + ), + 'wp_nav_menu_locations_meta_box' => array( + 'alt' => '', + 'version' => '3.6.0', + ), + + // WP 3.7.0. + '_search_terms_tidy' => array( + 'alt' => '', + 'version' => '3.7.0', + ), + 'get_blogaddress_by_domain' => array( + 'alt' => '', + 'version' => '3.7.0', + ), + 'the_attachment_links' => array( + 'alt' => '', + 'version' => '3.7.0', + ), + 'wp_update_core' => array( + 'alt' => 'new Core_Upgrader();', + 'version' => '3.7.0', + ), + 'wp_update_plugin' => array( + 'alt' => 'new Plugin_Upgrader();', + 'version' => '3.7.0', + ), + 'wp_update_theme' => array( + 'alt' => 'new Theme_Upgrader();', + 'version' => '3.7.0', + ), + + // WP 3.8.0. + 'get_screen_icon' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + 'screen_icon' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_incoming_links' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_incoming_links_control' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_incoming_links_output' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_plugins' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_primary_control' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_recent_comments_control' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_secondary' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_secondary_control' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_secondary_output' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + + // WP 3.9.0. + '_relocate_children' => array( + 'alt' => '', + 'version' => '3.9.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'default_topic_count_text' => array( + 'alt' => '', + 'version' => '3.9.0', + ), + 'format_to_post' => array( + 'alt' => '', + 'version' => '3.9.0', + ), + 'get_current_site_name' => array( + 'alt' => 'get_current_site()', + 'version' => '3.9.0', + ), + 'rich_edit_exists' => array( + 'alt' => '', + 'version' => '3.9.0', + ), + 'wpmu_current_site' => array( + 'alt' => '', + 'version' => '3.9.0', + ), + + // WP 4.0.0. + 'get_all_category_ids' => array( + 'alt' => 'get_terms()', + 'version' => '4.0.0', + ), + 'like_escape' => array( + 'alt' => 'wpdb::esc_like()', + 'version' => '4.0.0', + ), + 'url_is_accessable_via_ssl' => array( + 'alt' => '', + 'version' => '4.0.0', + ), + + // WP 4.1.0. + // This is a method from the WP_Customize_Image_Control class. See #731. + 'add_tab' => array( + 'alt' => '', + 'version' => '4.1.0', + ), + // This is a method from the WP_Customize_Image_Control class. See #731. + 'prepare_control' => array( + 'alt' => '', + 'version' => '4.1.0', + ), + // This is a method from the WP_Customize_Image_Control class. See #731. + 'print_tab_image' => array( + 'alt' => '', + 'version' => '4.1.0', + ), + // This is a method from the WP_Customize_Image_Control class. See #731. + 'remove_tab' => array( + 'alt' => '', + 'version' => '4.1.0', + ), + + // WP 4.2.0. + // This is a method from the WP_Customize_Widgets class. See #731. + 'prepreview_added_sidebars_widgets' => array( + 'alt' => 'the \'customize_dynamic_setting_args\' filter', + 'version' => '4.2.0', + ), + // This is a method from the WP_Customize_Widgets class. See #731. + 'prepreview_added_widget_instance' => array( + 'alt' => 'the \'customize_dynamic_setting_args\' filter', + 'version' => '4.2.0', + ), + // This is a method from the WP_Customize_Widgets class. See #731. + 'remove_prepreview_filters' => array( + 'alt' => 'the \'customize_dynamic_setting_args\' filter', + 'version' => '4.2.0', + ), + // This is a method from the WP_Customize_Widgets class. See #731. + 'setup_widget_addition_previews' => array( + 'alt' => 'the \'customize_dynamic_setting_args\' filter', + 'version' => '4.2.0', + ), + + // WP 4.3.0. + '_preview_theme_stylesheet_filter' => array( + 'alt' => '', + 'version' => '4.3.0', + ), + '_preview_theme_template_filter' => array( + 'alt' => '', + 'version' => '4.3.0', + ), + 'preview_theme' => array( + 'alt' => '', + 'version' => '4.3.0', + ), + 'preview_theme_ob_filter' => array( + 'alt' => '', + 'version' => '4.3.0', + ), + 'preview_theme_ob_filter_callback' => array( + 'alt' => '', + 'version' => '4.3.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_ajax_wp_fullscreen_save_post' => array( + 'alt' => '', + 'version' => '4.3.0', + ), + 'wp_htmledit_pre' => array( + 'alt' => 'format_for_editor()', + 'version' => '4.3.0', + ), + 'wp_richedit_pre' => array( + 'alt' => 'format_for_editor()', + 'version' => '4.3.0', + ), + + // WP 4.4.0. + 'create_empty_blog' => array( + 'alt' => '', + 'version' => '4.4.0', + ), + 'force_ssl_login' => array( + 'alt' => 'force_ssl_admin()', + 'version' => '4.4.0', + ), + 'get_admin_users_for_domain' => array( + 'alt' => '', + 'version' => '4.4.0', + ), + 'post_permalink' => array( + 'alt' => 'get_permalink()', + 'version' => '4.4.0', + ), + 'wp_get_http' => array( + 'alt' => 'the WP_Http class', + 'version' => '4.4.0', + ), + // This is a method i.e. WP_Widget_Recent_Comments::flush_widget_cache() See #731. + 'flush_widget_cache' => array( + 'alt' => '', + 'version' => '4.4.0', + ), + + // WP 4.5.0. + 'add_object_page' => array( + 'alt' => 'add_menu_page()', + 'version' => '4.5.0', + ), + 'add_utility_page' => array( + 'alt' => 'add_menu_page()', + 'version' => '4.5.0', + ), + 'comments_popup_script' => array( + 'alt' => '', + 'version' => '4.5.0', + ), + 'get_comments_popup_template' => array( + 'alt' => '', + 'version' => '4.5.0', + ), + 'get_currentuserinfo' => array( + 'alt' => 'wp_get_current_user()', + 'version' => '4.5.0', + ), + 'is_comments_popup' => array( + 'alt' => '', + 'version' => '4.5.0', + ), + 'popuplinks' => array( + 'alt' => '', + 'version' => '4.5.0', + ), + + // WP 4.6.0. + 'post_form_autocomplete_off' => array( + 'alt' => '', + 'version' => '4.6.0', + ), + 'wp_embed_handler_googlevideo' => array( + 'alt' => '', + 'version' => '4.6.0', + ), + 'wp_get_sites' => array( + 'alt' => 'get_sites()', + 'version' => '4.6.0', + ), + + // WP 4.7.0. + '_sort_nav_menu_items' => array( + 'alt' => 'wp_list_sort()', + 'version' => '4.7.0', + ), + '_usort_terms_by_ID' => array( + 'alt' => 'wp_list_sort()', + 'version' => '4.7.0', + ), + '_usort_terms_by_name' => array( + 'alt' => 'wp_list_sort()', + 'version' => '4.7.0', + ), + 'get_paged_template' => array( + 'alt' => '', + 'version' => '4.7.0', + ), + 'wp_get_network' => array( + 'alt' => 'get_network()', + 'version' => '4.7.0', + ), + 'wp_kses_js_entities' => array( + 'alt' => '', + 'version' => '4.7.0', + ), + + // WP 4.8.0. + 'wp_dashboard_plugins_output' => array( + 'alt' => '', + 'version' => '4.8.0', + ), + + // WP 4.9.0. + 'get_shortcut_link' => array( + 'alt' => '', + 'version' => '4.9.0', + ), + 'is_user_option_local' => array( + 'alt' => '', + 'version' => '4.9.0', + ), + 'wp_ajax_press_this_add_category' => array( + 'alt' => '', + 'version' => '4.9.0', + ), + 'wp_ajax_press_this_save_post' => array( + 'alt' => '', + 'version' => '4.9.0', + ), + + // WP 5.1.0. + 'insert_blog' => array( + 'alt' => 'wp_insert_site()', + 'version' => '5.1.0', + ), + 'install_blog' => array( + 'alt' => '', + 'version' => '5.1.0', + ), + + // WP 5.3.0. + '_wp_json_prepare_data' => array( + 'alt' => '', + 'version' => '5.3.0', + ), + '_wp_privacy_requests_screen_options' => array( + 'alt' => '', + 'version' => '5.3.0', + ), + 'update_user_status' => array( + 'alt' => 'wp_update_user()', + 'version' => '5.3.0', + ), + + // WP 5.4.0. + 'wp_get_user_request_data' => array( + 'alt' => 'wp_get_user_request()', + 'version' => '5.4.0', + ), + ); + + /** + * Groups of functions to restrict. + * + * @return array + */ + public function getGroups() { + // Make sure all array keys are lowercase. + $this->deprecated_functions = array_change_key_case( $this->deprecated_functions, CASE_LOWER ); + + return array( + 'deprecated_functions' => array( + 'functions' => array_keys( $this->deprecated_functions ), + ), + ); + } + + /** + * Process a matched token. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. Will + * always be 'deprecated_functions'. + * @param string $matched_content The token content (function name) which was matched. + * + * @return void + */ + public function process_matched_token( $stackPtr, $group_name, $matched_content ) { + + $this->get_wp_version_from_cl(); + + $function_name = strtolower( $matched_content ); + + $message = '%s() has been deprecated since WordPress version %s.'; + $data = array( + $matched_content, + $this->deprecated_functions[ $function_name ]['version'], + ); + + if ( ! empty( $this->deprecated_functions[ $function_name ]['alt'] ) ) { + $message .= ' Use %s instead.'; + $data[] = $this->deprecated_functions[ $function_name ]['alt']; + } + + $this->addMessage( + $message, + $stackPtr, + ( version_compare( $this->deprecated_functions[ $function_name ]['version'], $this->minimum_supported_version, '<' ) ), + $this->string_to_errorcode( $matched_content . 'Found' ), + $data + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedParameterValuesSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedParameterValuesSniff.php new file mode 100644 index 00000000..0758def2 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedParameterValuesSniff.php @@ -0,0 +1,216 @@ + array( + * (int) Target parameter position, 1-based. => array( + * (string) Parameter value. => array( + * 'alt' => (string) Suggested alternative. + * 'version' => (int) The WordPress version when deprecated. + * ) + * ) + * ) + * ); + */ + protected $target_functions = array( + 'add_settings_field' => array( + 4 => array( + 'misc' => array( + 'alt' => 'another settings group', + 'version' => '3.0.0', + ), + 'privacy' => array( + 'alt' => 'another settings group', + 'version' => '3.5.0', + ), + ), + ), + 'add_settings_section' => array( + 4 => array( + 'misc' => array( + 'alt' => 'another settings group', + 'version' => '3.0.0', + ), + 'privacy' => array( + 'alt' => 'another settings group', + 'version' => '3.5.0', + ), + ), + ), + 'bloginfo' => array( + 1 => array( + 'home' => array( + 'alt' => 'the "url" argument', + 'version' => '2.2.0', + ), + 'siteurl' => array( + 'alt' => 'the "url" argument', + 'version' => '2.2.0', + ), + 'text_direction' => array( + 'alt' => 'is_rtl()', + 'version' => '2.2.0', + ), + ), + ), + 'get_bloginfo' => array( + 1 => array( + 'home' => array( + 'alt' => 'the "url" argument', + 'version' => '2.2.0', + ), + 'siteurl' => array( + 'alt' => 'the "url" argument', + 'version' => '2.2.0', + ), + 'text_direction' => array( + 'alt' => 'is_rtl()', + 'version' => '2.2.0', + ), + ), + ), + 'register_setting' => array( + 1 => array( + 'misc' => array( + 'alt' => 'another settings group', + 'version' => '3.0.0', + ), + 'privacy' => array( + 'alt' => 'another settings group', + 'version' => '3.5.0', + ), + ), + ), + 'unregister_setting' => array( + 1 => array( + 'misc' => array( + 'alt' => 'another settings group', + 'version' => '3.0.0', + ), + 'privacy' => array( + 'alt' => 'another settings group', + 'version' => '3.5.0', + ), + ), + ), + ); + + /** + * Process the parameters of a matched function. + * + * @since 1.0.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + $this->get_wp_version_from_cl(); + $param_count = \count( $parameters ); + foreach ( $this->target_functions[ $matched_content ] as $position => $parameter_args ) { + + // Stop if the position is higher then the total number of parameters. + if ( $position > $param_count ) { + break; + } + + $this->process_parameter( $matched_content, $parameters[ $position ], $parameter_args ); + } + } + + /** + * Process the parameter of a matched function. + * + * @since 1.0.0 + * + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameter Array with start and end token positon of the parameter. + * @param array $parameter_args Array with alternative and WordPress deprecation version of the parameter. + * + * @return void + */ + protected function process_parameter( $matched_content, $parameter, $parameter_args ) { + + $parameter_position = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $parameter['start'], + $parameter['end'] + 1, + true + ); + + if ( false === $parameter_position ) { + return; + } + + $matched_parameter = $this->strip_quotes( $this->tokens[ $parameter_position ]['content'] ); + if ( ! isset( $parameter_args[ $matched_parameter ] ) ) { + return; + } + + $message = 'The parameter value "%s" has been deprecated since WordPress version %s.'; + $data = array( + $matched_parameter, + $parameter_args[ $matched_parameter ]['version'], + ); + + if ( ! empty( $parameter_args[ $matched_parameter ]['alt'] ) ) { + $message .= ' Use %s instead.'; + $data[] = $parameter_args[ $matched_parameter ]['alt']; + } + + $is_error = version_compare( $parameter_args[ $matched_parameter ]['version'], $this->minimum_supported_version, '<' ); + $this->addMessage( + $message, + $parameter_position, + $is_error, + $this->string_to_errorcode( 'Found' ), + $data + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedParametersSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedParametersSniff.php new file mode 100644 index 00000000..3d45bafc --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedParametersSniff.php @@ -0,0 +1,338 @@ + value + * in a custom ruleset. + * + * @uses \WordPressCS\WordPress\Sniff::$minimum_supported_version + */ +class DeprecatedParametersSniff extends AbstractFunctionParameterSniff { + + /** + * The group name for this group of functions. + * + * @since 0.12.0 + * + * @var string + */ + protected $group_name = 'wp_deprecated_parameters'; + + /** + * Array of function, argument, and default value for deprecated argument. + * + * The functions are ordered alphabetically. + * Last updated for WordPress 4.8.0. + * + * @since 0.12.0 + * + * @var array Multidimensional array with parameter details. + * $target_functions = array( + * (string) Function name. => array( + * (int) Target parameter position, 1-based. => array( + * 'value' => (mixed) Expected default value for the + * deprecated parameter. Currently the default + * values: true, false, null, empty arrays and + * both empty and non-empty strings can be + * handled correctly by the process_parameters() + * method. When an additional default value is + * added, the relevant code in the + * process_parameters() method will need to be + * adjusted. + * 'version' => (int) The WordPress version when deprecated. + * ) + * ) + * ); + */ + protected $target_functions = array( + + 'add_option' => array( + 3 => array( + 'value' => '', + 'version' => '2.3.0', + ), + ), + 'comments_link' => array( + 1 => array( + 'value' => '', + 'version' => '0.72', + ), + 2 => array( + 'value' => '', + 'version' => '1.3.0', + ), + ), + 'comments_number' => array( + 4 => array( + 'value' => '', + 'version' => '1.3.0', + ), + ), + 'convert_chars' => array( + 2 => array( + 'value' => '', + 'version' => '0.71', + ), + ), + 'discover_pingback_server_uri' => array( + 2 => array( + 'value' => '', + 'version' => '2.7.0', + ), + ), + 'get_category_parents' => array( + 5 => array( + 'value' => array(), + 'version' => '4.8.0', + ), + ), + 'get_delete_post_link' => array( + 2 => array( + 'value' => '', + 'version' => '3.0.0', + ), + ), + 'get_last_updated' => array( + 1 => array( + 'value' => '', + 'version' => '3.0.0', // Was previously part of MU. + ), + ), + 'get_the_author' => array( + 1 => array( + 'value' => '', + 'version' => '2.1.0', + ), + ), + 'get_user_option' => array( + 3 => array( + 'value' => '', + 'version' => '2.3.0', + ), + ), + 'get_wp_title_rss' => array( + 1 => array( + 'value' => '–', + 'version' => '4.4.0', + ), + ), + 'is_email' => array( + 2 => array( + 'value' => false, + 'version' => '3.0.0', + ), + ), + 'load_plugin_textdomain' => array( + 2 => array( + 'value' => false, + 'version' => '2.7.0', + ), + ), + 'safecss_filter_attr' => array( + 2 => array( + 'value' => '', + 'version' => '2.8.1', + ), + ), + 'the_attachment_link' => array( + 3 => array( + 'value' => false, + 'version' => '2.5.0', + ), + ), + 'the_author' => array( + 1 => array( + 'value' => '', + 'version' => '2.1.0', + ), + 2 => array( + 'value' => true, + 'version' => '1.5.0', + ), + ), + 'the_author_posts_link' => array( + 1 => array( + 'value' => '', + 'version' => '2.1.0', + ), + ), + 'trackback_rdf' => array( + 1 => array( + 'value' => '', + 'version' => '2.5.0', + ), + ), + 'trackback_url' => array( + 1 => array( + 'value' => true, + 'version' => '2.5.0', + ), + ), + 'update_blog_option' => array( + 4 => array( + 'value' => null, + 'version' => '3.1.0', + ), + ), + 'update_blog_status' => array( + 4 => array( + 'value' => null, + 'version' => '3.1.0', + ), + ), + 'update_user_status' => array( + 4 => array( + 'value' => null, + 'version' => '3.0.2', + ), + ), + 'unregister_setting' => array( + 4 => array( + 'value' => '', + 'version' => '4.7.0', + ), + ), + 'wp_get_http_headers' => array( + 2 => array( + 'value' => false, + 'version' => '2.7.0', + ), + ), + 'wp_get_sidebars_widgets' => array( + 1 => array( + 'value' => true, + 'version' => '2.8.1', + ), + ), + 'wp_install' => array( + 5 => array( + 'value' => '', + 'version' => '2.6.0', + ), + ), + 'wp_new_user_notification' => array( + 2 => array( + 'value' => null, + 'version' => '4.3.1', + ), + ), + 'wp_notify_postauthor' => array( + 2 => array( + 'value' => null, + 'version' => '3.8.0', + ), + ), + 'wp_title_rss' => array( + 1 => array( + 'value' => '–', + 'version' => '4.4.0', + ), + ), + 'wp_upload_bits' => array( + 2 => array( + 'value' => null, + 'version' => '2.0.0', + ), + ), + 'xfn_check' => array( + 3 => array( + 'value' => '', + 'version' => '2.5.0', + ), + ), + ); + + /** + * Process the parameters of a matched function. + * + * @since 0.12.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + + $this->get_wp_version_from_cl(); + + $paramCount = \count( $parameters ); + foreach ( $this->target_functions[ $matched_content ] as $position => $parameter_args ) { + + // Check that number of parameters defined is not less than the position to check. + if ( $position > $paramCount ) { + break; + } + + // The list will need to updated if the default value is not supported. + switch ( $parameters[ $position ]['raw'] ) { + case 'true': + $matched_parameter = true; + break; + case 'false': + $matched_parameter = false; + break; + case 'null': + $matched_parameter = null; + break; + case 'array()': + case '[]': + $matched_parameter = array(); + break; + default: + $matched_parameter = $this->strip_quotes( $parameters[ $position ]['raw'] ); + break; + } + + if ( $parameter_args['value'] === $matched_parameter ) { + continue; + } + + $message = 'The parameter "%s" at position #%s of %s() has been deprecated since WordPress version %s.'; + $is_error = version_compare( $parameter_args['version'], $this->minimum_supported_version, '<' ); + $code = $this->string_to_errorcode( ucfirst( $matched_content ) . 'Param' . $position . 'Found' ); + + $data = array( + $parameters[ $position ]['raw'], + $position, + $matched_content, + $parameter_args['version'], + ); + + if ( isset( $parameter_args['value'] ) && $position < $paramCount ) { + $message .= ' Use "%s" instead.'; + $data[] = (string) $parameter_args['value']; + } else { + $message .= ' Instead do not pass the parameter.'; + } + + $this->addMessage( $message, $stackPtr, $is_error, $code, $data, 0 ); + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DiscouragedConstantsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DiscouragedConstantsSniff.php new file mode 100644 index 00000000..bcd960c4 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DiscouragedConstantsSniff.php @@ -0,0 +1,217 @@ + 'get_stylesheet_directory()', + 'TEMPLATEPATH' => 'get_template_directory()', + 'PLUGINDIR' => 'WP_PLUGIN_DIR', + 'MUPLUGINDIR' => 'WPMU_PLUGIN_DIR', + 'HEADER_IMAGE' => 'add_theme_support( \'custom-header\' )', + 'NO_HEADER_TEXT' => 'add_theme_support( \'custom-header\' )', + 'HEADER_TEXTCOLOR' => 'add_theme_support( \'custom-header\' )', + 'HEADER_IMAGE_WIDTH' => 'add_theme_support( \'custom-header\' )', + 'HEADER_IMAGE_HEIGHT' => 'add_theme_support( \'custom-header\' )', + 'BACKGROUND_COLOR' => 'add_theme_support( \'custom-background\' )', + 'BACKGROUND_IMAGE' => 'add_theme_support( \'custom-background\' )', + ); + + /** + * Array of functions to check. + * + * @since 0.14.0 + * + * @var array => + */ + protected $target_functions = array( + 'define' => 1, + ); + + /** + * Array of tokens which if found preceding the $stackPtr indicate that a T_STRING is not a constant. + * + * @var array + */ + private $preceding_tokens_to_ignore = array( + \T_NAMESPACE => true, + \T_USE => true, + \T_CLASS => true, + \T_TRAIT => true, + \T_INTERFACE => true, + \T_EXTENDS => true, + \T_IMPLEMENTS => true, + \T_NEW => true, + \T_FUNCTION => true, + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_INSTANCEOF => true, + \T_GOTO => true, + ); + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + if ( isset( $this->target_functions[ strtolower( $this->tokens[ $stackPtr ]['content'] ) ] ) ) { + // Disallow excluding function groups for this sniff. + $this->exclude = array(); + + return parent::process_token( $stackPtr ); + + } else { + return $this->process_arbitrary_tstring( $stackPtr ); + } + } + + /** + * Process an arbitrary T_STRING token to determine whether it is one of the target constants. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_arbitrary_tstring( $stackPtr ) { + $content = $this->tokens[ $stackPtr ]['content']; + + if ( ! isset( $this->discouraged_constants[ $content ] ) ) { + return; + } + + $next = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + if ( false !== $next && \T_OPEN_PARENTHESIS === $this->tokens[ $next ]['code'] ) { + // Function call or declaration. + return; + } + + $prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true ); + if ( false !== $prev && isset( $this->preceding_tokens_to_ignore[ $this->tokens[ $prev ]['code'] ] ) ) { + // Not the use of a constant. + return; + } + + if ( $this->is_token_namespaced( $stackPtr ) === true ) { + // Namespaced constant of the same name. + return; + } + + if ( false !== $prev + && \T_CONST === $this->tokens[ $prev ]['code'] + && true === $this->is_class_constant( $prev ) + ) { + // Class constant of the same name. + return; + } + + /* + * Deal with a number of variations of use statements. + */ + for ( $i = $stackPtr; $i > 0; $i-- ) { + if ( $this->tokens[ $i ]['line'] !== $this->tokens[ $stackPtr ]['line'] ) { + break; + } + } + + $first_on_line = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $i + 1 ), null, true ); + if ( false !== $first_on_line && \T_USE === $this->tokens[ $first_on_line ]['code'] ) { + $next_on_line = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $first_on_line + 1 ), null, true ); + if ( false !== $next_on_line ) { + if ( ( \T_STRING === $this->tokens[ $next_on_line ]['code'] + && 'const' === $this->tokens[ $next_on_line ]['content'] ) + || \T_CONST === $this->tokens[ $next_on_line ]['code'] // Happens in some PHPCS versions. + ) { + $has_ns_sep = $this->phpcsFile->findNext( \T_NS_SEPARATOR, ( $next_on_line + 1 ), $stackPtr ); + if ( false !== $has_ns_sep ) { + // Namespaced const (group) use statement. + return; + } + } else { + // Not a const use statement. + return; + } + } + } + + // Ok, this is really one of the discouraged constants. + $this->phpcsFile->addWarning( + 'Found usage of constant "%s". Use %s instead.', + $stackPtr, + $this->string_to_errorcode( $content . 'UsageFound' ), + array( + $content, + $this->discouraged_constants[ $content ], + ) + ); + } + + /** + * Process the parameters of a matched `define` function call. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + $function_name = strtolower( $matched_content ); + $target_param = $this->target_functions[ $function_name ]; + + // Was the target parameter passed ? + if ( ! isset( $parameters[ $target_param ] ) ) { + return; + } + + $raw_content = $this->strip_quotes( $parameters[ $target_param ]['raw'] ); + + if ( isset( $this->discouraged_constants[ $raw_content ] ) ) { + $this->phpcsFile->addWarning( + 'Found declaration of constant "%s". Use %s instead.', + $stackPtr, + $this->string_to_errorcode( $raw_content . 'DeclarationFound' ), + array( + $raw_content, + $this->discouraged_constants[ $raw_content ], + ) + ); + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DiscouragedFunctionsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DiscouragedFunctionsSniff.php new file mode 100644 index 00000000..d51504a3 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DiscouragedFunctionsSniff.php @@ -0,0 +1,57 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'query_posts' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged. Use WP_Query instead.', + 'functions' => array( + 'query_posts', + ), + ), + + 'wp_reset_query' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged. Use wp_reset_postdata() instead.', + 'functions' => array( + 'wp_reset_query', + ), + ), + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/EnqueuedResourceParametersSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/EnqueuedResourceParametersSniff.php new file mode 100644 index 00000000..9c1f5f1e --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/EnqueuedResourceParametersSniff.php @@ -0,0 +1,223 @@ + => + */ + protected $target_functions = array( + 'wp_register_script' => true, + 'wp_enqueue_script' => true, + 'wp_register_style' => true, + 'wp_enqueue_style' => true, + ); + + /** + * False + the empty tokens array. + * + * This array is enriched with the $emptyTokens array in the register() method. + * + * @var array + */ + private $false_tokens = array( + \T_FALSE => \T_FALSE, + ); + + /** + * Token codes which are "safe" to accept to determine whether a version would evaluate to `false`. + * + * This array is enriched with the several of the PHPCS token arrays in the register() method. + * + * @var array + */ + private $safe_tokens = array( + \T_NULL => \T_NULL, + \T_FALSE => \T_FALSE, + \T_TRUE => \T_TRUE, + \T_LNUMBER => \T_LNUMBER, + \T_DNUMBER => \T_DNUMBER, + \T_CONSTANT_ENCAPSED_STRING => \T_CONSTANT_ENCAPSED_STRING, + \T_START_NOWDOC => \T_START_NOWDOC, + \T_NOWDOC => \T_NOWDOC, + \T_END_NOWDOC => \T_END_NOWDOC, + \T_OPEN_PARENTHESIS => \T_OPEN_PARENTHESIS, + \T_CLOSE_PARENTHESIS => \T_CLOSE_PARENTHESIS, + \T_STRING_CONCAT => \T_STRING_CONCAT, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * Overloads and calls the parent method to allow for adding additional tokens to the $safe_tokens property. + * + * @return array + */ + public function register() { + $this->false_tokens += Tokens::$emptyTokens; + + $this->safe_tokens += Tokens::$emptyTokens; + $this->safe_tokens += Tokens::$assignmentTokens; + $this->safe_tokens += Tokens::$comparisonTokens; + $this->safe_tokens += Tokens::$operators; + $this->safe_tokens += Tokens::$booleanOperators; + $this->safe_tokens += Tokens::$castTokens; + + return parent::register(); + } + + /** + * Process the parameters of a matched function. + * + * @since 1.0.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + + // Check to see if a source ($src) is specified. + if ( ! isset( $parameters[2] ) ) { + return; + } + + /* + * Version Check: Check to make sure the version is set explicitly. + */ + + if ( ! isset( $parameters[4] ) || 'null' === $parameters[4]['raw'] ) { + $type = 'script'; + if ( strpos( $matched_content, '_style' ) !== false ) { + $type = 'style'; + } + + $this->phpcsFile->addError( + 'Resource version not set in call to %s(). This means new versions of the %s will not always be loaded due to browser caching.', + $stackPtr, + 'MissingVersion', + array( $matched_content, $type ) + ); + } else { + // The version argument should have a non-false value. + if ( $this->is_falsy( $parameters[4]['start'], $parameters[4]['end'] ) ) { + $this->phpcsFile->addError( + 'Version parameter is not explicitly set or has been set to an equivalent of "false" for %s; ' . + 'This means that the WordPress core version will be used which is not recommended for plugin or theme development.', + $stackPtr, + 'NoExplicitVersion', + array( $matched_content ) + ); + } + } + + /* + * In footer Check + * + * Check to make sure that $in_footer is set to true. + * It will warn the user to make sure it is intended. + * + * Only wp_register_script and wp_enqueue_script need this check, + * as this parameter is not available to wp_register_style and wp_enqueue_style. + */ + if ( 'wp_register_script' !== $matched_content && 'wp_enqueue_script' !== $matched_content ) { + return; + } + + if ( ! isset( $parameters[5] ) ) { + // If in footer is not set, throw a warning about the default. + $this->phpcsFile->addWarning( + 'In footer ($in_footer) is not set explicitly %s; ' . + 'It is recommended to load scripts in the footer. Please set this value to `true` to load it in the footer, or explicitly `false` if it should be loaded in the header.', + $stackPtr, + 'NotInFooter', + array( $matched_content ) + ); + } + } + + /** + * Determine if a range has a falsy value. + * + * @param int $start The position to start looking from. + * @param int $end The position to stop looking (inclusive). + * + * @return bool True if the parameter is falsy. + * False if the parameter is not falsy or when it + * couldn't be reliably determined. + */ + protected function is_falsy( $start, $end ) { + + // Find anything excluding the false tokens. + $has_non_false = $this->phpcsFile->findNext( $this->false_tokens, $start, ( $end + 1 ), true ); + // If no non-false tokens are found, we are good. + if ( false === $has_non_false ) { + return true; + } + + $code_string = ''; + for ( $i = $start; $i <= $end; $i++ ) { + if ( isset( $this->safe_tokens[ $this->tokens[ $i ]['code'] ] ) === false ) { + // Function call/variable or other token which makes it neigh impossible + // to determine whether the actual value would evaluate to false. + return false; + } + + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) === true ) { + continue; + } + + $code_string .= $this->tokens[ $i ]['content']; + } + + if ( '' === $code_string ) { + return false; + } + + // Evaluate the argument to figure out the outcome is false or not. + // phpcs:ignore Squiz.PHP.Eval -- No harm here. + return ( false === eval( "return (bool) $code_string;" ) ); + } +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/EnqueuedResourcesSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/EnqueuedResourcesSniff.php new file mode 100644 index 00000000..27572e95 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/EnqueuedResourcesSniff.php @@ -0,0 +1,64 @@ +tokens[ $stackPtr ]; + + if ( preg_match( '# rel=\\\\?[\'"]?stylesheet\\\\?[\'"]?#', $token['content'] ) > 0 ) { + $this->phpcsFile->addError( + 'Stylesheets must be registered/enqueued via wp_enqueue_style', + $stackPtr, + 'NonEnqueuedStylesheet' + ); + } + + if ( preg_match( '#]*(?<=src=)#', $token['content'] ) > 0 ) { + $this->phpcsFile->addError( + 'Scripts must be registered/enqueued via wp_enqueue_script', + $stackPtr, + 'NonEnqueuedScript' + ); + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/GlobalVariablesOverrideSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/GlobalVariablesOverrideSniff.php new file mode 100644 index 00000000..37bf68b2 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/GlobalVariablesOverrideSniff.php @@ -0,0 +1,466 @@ + true, + 'wp_cockneyreplace' => true, + ); + + /** + * Scoped object and function structures to skip over as + * variables will have a different scope within those. + * + * @since 1.1.0 + * + * @var array + */ + private $skip_over = array( + \T_FUNCTION => true, + \T_CLOSURE => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 0.3.0 + * @since 1.1.0 Added class tokens for improved test classes skipping. + * + * @return array + */ + public function register() { + // Add the OO scope tokens to the $skip_over property. + $this->skip_over += Tokens::$ooScopeTokens; + + $targets = array( + \T_GLOBAL, + \T_VARIABLE, + \T_LIST, + \T_OPEN_SHORT_ARRAY, + ); + + // Only used to skip over test classes. + $targets += Tokens::$ooScopeTokens; + + return $targets; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.3.0 + * @since 1.1.0 Split the token specific logic off into separate methods. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + $token = $this->tokens[ $stackPtr ]; + + // Ignore variable overrides in test classes. + if ( isset( Tokens::$ooScopeTokens[ $token['code'] ] ) ) { + + if ( true === $this->is_test_class( $stackPtr ) + && $token['scope_condition'] === $stackPtr + && isset( $token['scope_closer'] ) + ) { + // Skip forward to end of test class. + return $token['scope_closer']; + } + + // Otherwise ignore the tokens as they were only registered to enable skipping over test classes. + return; + } + + /* + * Examine variables within a function scope based on a `global` statement in the + * function. + * Examine variables not within a function scope, but within a list construct, based + * on that. + * Examine variables not within a function scope and access to the `$GLOBALS` + * variable based on the variable token. + */ + $in_function_scope = $this->phpcsFile->hasCondition( $stackPtr, array( \T_FUNCTION, \T_CLOSURE ) ); + + if ( ( \T_LIST === $token['code'] || \T_OPEN_SHORT_ARRAY === $token['code'] ) + && false === $in_function_scope + && false === $this->treat_files_as_scoped + ) { + return $this->process_list_assignment( $stackPtr ); + } elseif ( \T_VARIABLE === $token['code'] + && ( '$GLOBALS' === $token['content'] + || ( false === $in_function_scope && false === $this->treat_files_as_scoped ) ) + ) { + return $this->process_variable_assignment( $stackPtr ); + } elseif ( \T_GLOBAL === $token['code'] + && ( true === $in_function_scope || true === $this->treat_files_as_scoped ) + ) { + return $this->process_global_statement( $stackPtr, $in_function_scope ); + } + } + + /** + * Check that global variables declared via a list construct are prefixed. + * + * @internal No need to take special measures for nested lists. Nested or not, + * each list part can only contain one variable being written to. + * + * @since 2.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + protected function process_list_assignment( $stackPtr ) { + $list_open_close = $this->find_list_open_close( $stackPtr ); + if ( false === $list_open_close ) { + // Short array, not short list. + return; + } + + $var_pointers = $this->get_list_variables( $stackPtr, $list_open_close ); + foreach ( $var_pointers as $ptr ) { + $this->process_variable_assignment( $ptr, true ); + } + + // No need to re-examine these variables. + return $list_open_close['closer']; + } + + /** + * Check that defined global variables are prefixed. + * + * @since 1.1.0 Logic was previously contained in the process_token() method. + * + * @param int $stackPtr The position of the current token in the stack. + * @param bool $in_list Whether or not this is a variable in a list assignment. + * Defaults to false. + * + * @return void + */ + protected function process_variable_assignment( $stackPtr, $in_list = false ) { + + if ( $this->has_whitelist_comment( 'override', $stackPtr ) === true ) { + return; + } + + $token = $this->tokens[ $stackPtr ]; + $var_name = substr( $token['content'], 1 ); // Strip the dollar sign. + $data = array(); + + // Determine the variable name for `$GLOBALS['array_key']`. + if ( 'GLOBALS' === $var_name ) { + $bracketPtr = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + + if ( false === $bracketPtr || \T_OPEN_SQUARE_BRACKET !== $this->tokens[ $bracketPtr ]['code'] || ! isset( $this->tokens[ $bracketPtr ]['bracket_closer'] ) ) { + return; + } + + // Retrieve the array key and avoid getting tripped up by some simple obfuscation. + $var_name = ''; + $start = ( $bracketPtr + 1 ); + for ( $ptr = $start; $ptr < $this->tokens[ $bracketPtr ]['bracket_closer']; $ptr++ ) { + /* + * If the globals array key contains a variable, constant, function call + * or interpolated variable, bow out. + */ + if ( \T_VARIABLE === $this->tokens[ $ptr ]['code'] + || \T_STRING === $this->tokens[ $ptr ]['code'] + || \T_DOUBLE_QUOTED_STRING === $this->tokens[ $ptr ]['code'] + ) { + return; + } + + if ( \T_CONSTANT_ENCAPSED_STRING === $this->tokens[ $ptr ]['code'] ) { + $var_name .= $this->strip_quotes( $this->tokens[ $ptr ]['content'] ); + } + } + + if ( '' === $var_name ) { + // Shouldn't happen, but just in case. + return; + } + + // Set up the data for the error message. + $data[] = '$GLOBALS[\'' . $var_name . '\']'; + } + + /* + * Is this one of the WP global variables ? + */ + if ( isset( $this->wp_globals[ $var_name ] ) === false ) { + return; + } + + /* + * Is this one of the WP global variables which are allowed to be overwritten ? + */ + if ( isset( $this->override_allowed[ $var_name ] ) === true ) { + return; + } + + /* + * Check if the variable value is being changed. + */ + if ( false === $in_list + && false === $this->is_assignment( $stackPtr ) + && false === $this->is_foreach_as( $stackPtr ) + ) { + return; + } + + /* + * Function parameters with the same name as a WP global variable are fine, + * including when they are being assigned a default value. + */ + if ( false === $in_list && isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + foreach ( $this->tokens[ $stackPtr ]['nested_parenthesis'] as $opener => $closer ) { + if ( isset( $this->tokens[ $opener ]['parenthesis_owner'] ) + && ( \T_FUNCTION === $this->tokens[ $this->tokens[ $opener ]['parenthesis_owner'] ]['code'] + || \T_CLOSURE === $this->tokens[ $this->tokens[ $opener ]['parenthesis_owner'] ]['code'] ) + ) { + return; + } + } + unset( $opener, $closer ); + } + + /* + * Class property declarations with the same name as WP global variables are fine. + */ + if ( false === $in_list && true === $this->is_class_property( $stackPtr ) ) { + return; + } + + // Still here ? In that case, the WP global variable is being tampered with. + $this->add_error( $stackPtr, $data ); + } + + /** + * Check that global variables imported into a function scope using a global statement + * are not being overruled. + * + * @since 1.1.0 Logic was previously contained in the process_token() method. + * + * @param int $stackPtr The position of the current token in the stack. + * @param bool $in_function_scope Whether the global statement is within a scoped function/closure. + * + * @return void + */ + protected function process_global_statement( $stackPtr, $in_function_scope ) { + /* + * Collect the variables to watch for. + */ + $search = array(); + $ptr = ( $stackPtr + 1 ); + while ( isset( $this->tokens[ $ptr ] ) ) { + $var = $this->tokens[ $ptr ]; + + // Halt the loop at end of statement. + if ( \T_SEMICOLON === $var['code'] ) { + break; + } + + if ( \T_VARIABLE === $var['code'] ) { + $var_name = substr( $var['content'], 1 ); + if ( isset( $this->wp_globals[ $var_name ] ) + && isset( $this->override_allowed[ $var_name ] ) === false + ) { + $search[] = $var['content']; + } + } + + $ptr++; + } + unset( $var ); + + if ( empty( $search ) ) { + return; + } + + /* + * Search for assignments to the imported global variables within the relevant scope. + */ + $start = $ptr; + if ( true === $in_function_scope ) { + $function_cond = $this->phpcsFile->getCondition( $stackPtr, \T_FUNCTION ); + $closure_cond = $this->phpcsFile->getCondition( $stackPtr, \T_CLOSURE ); + $scope_cond = max( $function_cond, $closure_cond ); // If false, it will evaluate as zero, so this is fine. + if ( isset( $this->tokens[ $scope_cond ]['scope_closer'] ) === false ) { + // Live coding or parse error. + return; + } + $end = $this->tokens[ $scope_cond ]['scope_closer']; + } else { + // Global statement in the global namespace with file is being treated as scoped. + $end = $this->phpcsFile->numTokens; + } + + for ( $ptr = $start; $ptr < $end; $ptr++ ) { + + // Skip over nested functions, classes and the likes. + if ( isset( $this->skip_over[ $this->tokens[ $ptr ]['code'] ] ) ) { + if ( ! isset( $this->tokens[ $ptr ]['scope_closer'] ) ) { + // Live coding or parse error. + break; + } + + $ptr = $this->tokens[ $ptr ]['scope_closer']; + continue; + } + + // Make sure to recognize assignments to variables in a list construct. + if ( \T_LIST === $this->tokens[ $ptr ]['code'] + || \T_OPEN_SHORT_ARRAY === $this->tokens[ $ptr ]['code'] + ) { + $list_open_close = $this->find_list_open_close( $ptr ); + + if ( false === $list_open_close ) { + // Short array, not short list. + continue; + } + + $var_pointers = $this->get_list_variables( $ptr, $list_open_close ); + foreach ( $var_pointers as $ptr ) { + $var_name = $this->tokens[ $ptr ]['content']; + if ( '$GLOBALS' === $var_name ) { + $var_name = '$' . $this->strip_quotes( $this->get_array_access_key( $ptr ) ); + } + + if ( \in_array( $var_name, $search, true ) ) { + $this->process_variable_assignment( $ptr, true ); + } + } + + // No need to re-examine these variables. + $ptr = $list_open_close['closer']; + continue; + } + + if ( \T_VARIABLE !== $this->tokens[ $ptr ]['code'] ) { + continue; + } + + if ( \in_array( $this->tokens[ $ptr ]['content'], $search, true ) === false ) { + // Not one of the variables we're interested in. + continue; + } + + // Don't throw false positives for static class properties. + if ( $this->is_class_object_call( $ptr ) === true ) { + continue; + } + + if ( true === $this->is_assignment( $ptr ) ) { + $this->maybe_add_error( $ptr ); + continue; + } + + // Check if this is a variable assignment within a `foreach()` declaration. + if ( $this->is_foreach_as( $ptr ) === true ) { + $this->maybe_add_error( $ptr ); + } + } + } + + /** + * Add the error if there is no whitelist comment present. + * + * @since 0.11.0 + * @since 1.1.0 - Visibility changed from public to protected. + * - Check for being in a test class moved to the process_token() method. + * + * @param int $stackPtr The position of the token to throw the error for. + * + * @return void + */ + protected function maybe_add_error( $stackPtr ) { + if ( $this->has_whitelist_comment( 'override', $stackPtr ) === false ) { + $this->add_error( $stackPtr ); + } + } + + /** + * Add the error. + * + * @since 1.1.0 + * + * @param int $stackPtr The position of the token to throw the error for. + * @param array $data Optional. Array containing one entry holding the + * name of the variable being overruled. + * Defaults to the 'content' of the $stackPtr token. + * + * @return void + */ + protected function add_error( $stackPtr, $data = array() ) { + if ( empty( $data ) ) { + $data[] = $this->tokens[ $stackPtr ]['content']; + } + + $this->phpcsFile->addError( + 'Overriding WordPress globals is prohibited. Found assignment to %s', + $stackPtr, + 'Prohibited', + $data + ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/I18nSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/I18nSniff.php new file mode 100644 index 00000000..d229cb5e --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/I18nSniff.php @@ -0,0 +1,789 @@ +phpcsFile->getFilename() + * @link https://youtrack.jetbrains.com/issue/WI-17740 + * + * @var string[]|string + */ + public $text_domain; + + /** + * The I18N functions in use in WP. + * + * @since 0.10.0 + * @since 0.11.0 Changed visibility from public to protected. + * + * @var array => + */ + protected $i18n_functions = array( + 'translate' => 'simple', + '__' => 'simple', + 'esc_attr__' => 'simple', + 'esc_html__' => 'simple', + '_e' => 'simple', + 'esc_attr_e' => 'simple', + 'esc_html_e' => 'simple', + 'translate_with_gettext_context' => 'context', + '_x' => 'context', + '_ex' => 'context', + 'esc_attr_x' => 'context', + 'esc_html_x' => 'context', + '_n' => 'number', + '_nx' => 'number_context', + '_n_noop' => 'noopnumber', + '_nx_noop' => 'noopnumber_context', + ); + + /** + * Toggle whether or not to check for translators comments for text string containing placeholders. + * + * Intended to make this part of the sniff unit testable, but can be used by end-users too, + * though they can just as easily disable this via the sniff code. + * + * @since 0.11.0 + * + * @var bool + */ + public $check_translator_comments = true; + + /** + * Whether or not the `default` text domain is one of the allowed text domains. + * + * @since 0.14.0 + * + * @var bool + */ + private $text_domain_contains_default = false; + + /** + * Whether or not the `default` text domain is the only allowed text domain. + * + * @since 0.14.0 + * + * @var bool + */ + private $text_domain_is_default = false; + + /** + * Groups of functions to restrict. + * + * Example: groups => array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'i18n' => array( + 'functions' => array_keys( $this->i18n_functions ), + ), + 'typos' => array( + 'functions' => array( + '_', + ), + ), + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 1.0.0 Defers to the abstractFunctionRestriction sniff for determining + * whether something is a function call. The logic after that has + * been split off to the `process_matched_token()` method. + * + * @param int $stack_ptr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stack_ptr ) { + + // Reset defaults. + $this->text_domain_contains_default = false; + $this->text_domain_is_default = false; + + // Allow overruling the text_domain set in a ruleset via the command line. + $cl_text_domain = trim( PHPCSHelper::get_config_data( 'text_domain' ) ); + if ( ! empty( $cl_text_domain ) ) { + $this->text_domain = array_filter( array_map( 'trim', explode( ',', $cl_text_domain ) ) ); + } + + $this->text_domain = $this->merge_custom_array( $this->text_domain, array(), false ); + + if ( ! empty( $this->text_domain ) ) { + if ( \in_array( 'default', $this->text_domain, true ) ) { + $this->text_domain_contains_default = true; + if ( \count( $this->text_domain ) === 1 ) { + $this->text_domain_is_default = true; + } + } + } + + // Prevent exclusion of the i18n group. + $this->exclude = array(); + + parent::process_token( $stack_ptr ); + } + + /** + * Process a matched token. + * + * @since 1.0.0 Logic split off from the `process_token()` method. + * + * @param int $stack_ptr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_matched_token( $stack_ptr, $group_name, $matched_content ) { + + $func_open_paren_token = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stack_ptr + 1 ), null, true ); + if ( false === $func_open_paren_token + || \T_OPEN_PARENTHESIS !== $this->tokens[ $func_open_paren_token ]['code'] + || ! isset( $this->tokens[ $func_open_paren_token ]['parenthesis_closer'] ) + ) { + // Live coding, parse error or not a function call. + return; + } + + if ( 'typos' === $group_name && '_' === $matched_content ) { + $this->phpcsFile->addError( 'Found single-underscore "_()" function when double-underscore expected.', $stack_ptr, 'SingleUnderscoreGetTextFunction' ); + return; + } + + if ( \in_array( $matched_content, array( 'translate', 'translate_with_gettext_context' ), true ) ) { + $this->phpcsFile->addWarning( 'Use of the "%s()" function is reserved for low-level API usage.', $stack_ptr, 'LowLevelTranslationFunction', array( $matched_content ) ); + } + + $arguments_tokens = array(); + $argument_tokens = array(); + $tokens = $this->tokens; + + // Look at arguments. + for ( $i = ( $func_open_paren_token + 1 ); $i < $this->tokens[ $func_open_paren_token ]['parenthesis_closer']; $i++ ) { + $this_token = $this->tokens[ $i ]; + $this_token['token_index'] = $i; + if ( isset( Tokens::$emptyTokens[ $this_token['code'] ] ) ) { + continue; + } + if ( \T_COMMA === $this_token['code'] ) { + $arguments_tokens[] = $argument_tokens; + $argument_tokens = array(); + continue; + } + + // Merge consecutive single or double quoted strings (when they span multiple lines). + if ( isset( Tokens::$textStringTokens[ $this_token['code'] ] ) ) { + for ( $j = ( $i + 1 ); $j < $this->tokens[ $func_open_paren_token ]['parenthesis_closer']; $j++ ) { + if ( $this_token['code'] === $this->tokens[ $j ]['code'] ) { + $this_token['content'] .= $this->tokens[ $j ]['content']; + $i = $j; + } else { + break; + } + } + } + $argument_tokens[] = $this_token; + + // Include everything up to and including the parenthesis_closer if this token has one. + if ( ! empty( $this_token['parenthesis_closer'] ) ) { + for ( $j = ( $i + 1 ); $j <= $this_token['parenthesis_closer']; $j++ ) { + $tokens[ $j ]['token_index'] = $j; + $argument_tokens[] = $tokens[ $j ]; + } + $i = $this_token['parenthesis_closer']; + } + } + + if ( ! empty( $argument_tokens ) ) { + $arguments_tokens[] = $argument_tokens; + } + unset( $argument_tokens ); + + $argument_assertions = array(); + if ( 'simple' === $this->i18n_functions[ $matched_content ] ) { + $argument_assertions[] = array( + 'arg_name' => 'text', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'domain', + 'tokens' => array_shift( $arguments_tokens ), + ); + } elseif ( 'context' === $this->i18n_functions[ $matched_content ] ) { + $argument_assertions[] = array( + 'arg_name' => 'text', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'context', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'domain', + 'tokens' => array_shift( $arguments_tokens ), + ); + } elseif ( 'number' === $this->i18n_functions[ $matched_content ] ) { + $argument_assertions[] = array( + 'arg_name' => 'single', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'plural', + 'tokens' => array_shift( $arguments_tokens ), + ); + array_shift( $arguments_tokens ); + $argument_assertions[] = array( + 'arg_name' => 'domain', + 'tokens' => array_shift( $arguments_tokens ), + ); + } elseif ( 'number_context' === $this->i18n_functions[ $matched_content ] ) { + $argument_assertions[] = array( + 'arg_name' => 'single', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'plural', + 'tokens' => array_shift( $arguments_tokens ), + ); + array_shift( $arguments_tokens ); + $argument_assertions[] = array( + 'arg_name' => 'context', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'domain', + 'tokens' => array_shift( $arguments_tokens ), + ); + } elseif ( 'noopnumber' === $this->i18n_functions[ $matched_content ] ) { + $argument_assertions[] = array( + 'arg_name' => 'single', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'plural', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'domain', + 'tokens' => array_shift( $arguments_tokens ), + ); + } elseif ( 'noopnumber_context' === $this->i18n_functions[ $matched_content ] ) { + $argument_assertions[] = array( + 'arg_name' => 'single', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'plural', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'context', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'domain', + 'tokens' => array_shift( $arguments_tokens ), + ); + } + + if ( ! empty( $arguments_tokens ) ) { + $this->phpcsFile->addError( 'Too many arguments for function "%s".', $func_open_paren_token, 'TooManyFunctionArgs', array( $matched_content ) ); + } + + foreach ( $argument_assertions as $argument_assertion_context ) { + if ( empty( $argument_assertion_context['tokens'][0] ) ) { + $argument_assertion_context['stack_ptr'] = $func_open_paren_token; + } else { + $argument_assertion_context['stack_ptr'] = $argument_assertion_context['tokens'][0]['token_index']; + } + $this->check_argument_tokens( $argument_assertion_context ); + } + + /* + * For _n*() calls, compare the singular and plural strings. + * If either of the arguments is missing, empty or has more than 1 token, skip out. + * An error for that will already have been reported via the `check_argument_tokens()` method. + */ + if ( false !== strpos( $this->i18n_functions[ $matched_content ], 'number' ) + && isset( $argument_assertions[0]['tokens'], $argument_assertions[1]['tokens'] ) + && count( $argument_assertions[0]['tokens'] ) === 1 + && count( $argument_assertions[1]['tokens'] ) === 1 + ) { + $single_context = $argument_assertions[0]; + $plural_context = $argument_assertions[1]; + + $this->compare_single_and_plural_arguments( $stack_ptr, $single_context, $plural_context ); + } + + if ( true === $this->check_translator_comments ) { + $this->check_for_translator_comment( $stack_ptr, $argument_assertions ); + } + } + + /** + * Check if supplied tokens represent a translation text string literal. + * + * @param array $context Context (@todo needs better description). + * @return bool + */ + protected function check_argument_tokens( $context ) { + $stack_ptr = $context['stack_ptr']; + $tokens = $context['tokens']; + $arg_name = $context['arg_name']; + $is_error = empty( $context['warning'] ); + $content = isset( $tokens[0] ) ? $tokens[0]['content'] : ''; + + if ( empty( $tokens ) || 0 === \count( $tokens ) ) { + $code = $this->string_to_errorcode( 'MissingArg' . ucfirst( $arg_name ) ); + if ( 'domain' !== $arg_name ) { + $this->addMessage( 'Missing $%s arg.', $stack_ptr, $is_error, $code, array( $arg_name ) ); + return false; + } + + // Ok, we're examining a text domain, now deal correctly with the 'default' text domain. + if ( true === $this->text_domain_is_default ) { + return true; + } + + if ( true === $this->text_domain_contains_default ) { + $this->phpcsFile->addWarning( + 'Missing $%s arg. If this text string is supposed to use a WP Core translation, use the "default" text domain.', + $stack_ptr, + $code . 'Default', + array( $arg_name ) + ); + } elseif ( ! empty( $this->text_domain ) ) { + $this->addMessage( 'Missing $%s arg.', $stack_ptr, $is_error, $code, array( $arg_name ) ); + } + + return false; + } + + if ( \count( $tokens ) > 1 ) { + $contents = ''; + foreach ( $tokens as $token ) { + $contents .= $token['content']; + } + $code = $this->string_to_errorcode( 'NonSingularStringLiteral' . ucfirst( $arg_name ) ); + $this->addMessage( 'The $%s arg must be a single string literal, not "%s".', $stack_ptr, $is_error, $code, array( $arg_name, $contents ) ); + return false; + } + + if ( \in_array( $arg_name, array( 'text', 'single', 'plural' ), true ) ) { + $this->check_text( $context ); + } + + if ( \T_DOUBLE_QUOTED_STRING === $tokens[0]['code'] || \T_HEREDOC === $tokens[0]['code'] ) { + $interpolated_variables = $this->get_interpolated_variables( $content ); + foreach ( $interpolated_variables as $interpolated_variable ) { + $code = $this->string_to_errorcode( 'InterpolatedVariable' . ucfirst( $arg_name ) ); + $this->addMessage( 'The $%s arg must not contain interpolated variables. Found "$%s".', $stack_ptr, $is_error, $code, array( $arg_name, $interpolated_variable ) ); + } + if ( ! empty( $interpolated_variables ) ) { + return false; + } + } + + if ( isset( Tokens::$textStringTokens[ $tokens[0]['code'] ] ) ) { + if ( 'domain' === $arg_name && ! empty( $this->text_domain ) ) { + $stripped_content = $this->strip_quotes( $content ); + + if ( ! \in_array( $stripped_content, $this->text_domain, true ) ) { + $this->addMessage( + 'Mismatched text domain. Expected \'%s\' but got %s.', + $stack_ptr, + $is_error, + 'TextDomainMismatch', + array( implode( "' or '", $this->text_domain ), $content ) + ); + return false; + } + + if ( true === $this->text_domain_is_default && 'default' === $stripped_content ) { + $fixable = false; + $error = 'No need to supply the text domain when the only accepted text domain is "default".'; + $error_code = 'SuperfluousDefaultTextDomain'; + + if ( $tokens[0]['token_index'] === $stack_ptr ) { + $prev = $this->phpcsFile->findPrevious( \T_WHITESPACE, ( $stack_ptr - 1 ), null, true ); + if ( false !== $prev && \T_COMMA === $this->tokens[ $prev ]['code'] ) { + $fixable = true; + } + } + + if ( false === $fixable ) { + $this->phpcsFile->addWarning( $error, $stack_ptr, $error_code ); + return false; + } + + $fix = $this->phpcsFile->addFixableWarning( $error, $stack_ptr, $error_code ); + if ( true === $fix ) { + // Remove preceeding comma, whitespace and the text domain token. + $this->phpcsFile->fixer->beginChangeset(); + for ( $i = $prev; $i <= $stack_ptr; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + $this->phpcsFile->fixer->endChangeset(); + } + + return false; + } + } + + return true; + } + + $code = $this->string_to_errorcode( 'NonSingularStringLiteral' . ucfirst( $arg_name ) ); + $this->addMessage( 'The $%s arg must be a single string literal, not "%s".', $stack_ptr, $is_error, $code, array( $arg_name, $content ) ); + return false; + } + + /** + * Check for inconsistencies between single and plural arguments. + * + * @param int $stack_ptr The position of the current token in the stack. + * @param array $single_context Single context (@todo needs better description). + * @param array $plural_context Plural context (@todo needs better description). + * @return void + */ + protected function compare_single_and_plural_arguments( $stack_ptr, $single_context, $plural_context ) { + $single_content = $single_context['tokens'][0]['content']; + $plural_content = $plural_context['tokens'][0]['content']; + + preg_match_all( self::SPRINTF_PLACEHOLDER_REGEX, $single_content, $single_placeholders ); + $single_placeholders = $single_placeholders[0]; + + preg_match_all( self::SPRINTF_PLACEHOLDER_REGEX, $plural_content, $plural_placeholders ); + $plural_placeholders = $plural_placeholders[0]; + + // English conflates "singular" with "only one", described in the codex: + // https://codex.wordpress.org/I18n_for_WordPress_Developers#Plurals . + if ( \count( $single_placeholders ) < \count( $plural_placeholders ) ) { + $error_string = 'Missing singular placeholder, needed for some languages. See https://codex.wordpress.org/I18n_for_WordPress_Developers#Plurals'; + $single_index = $single_context['tokens'][0]['token_index']; + + $this->phpcsFile->addError( $error_string, $single_index, 'MissingSingularPlaceholder' ); + } + + // Reordering is fine, but mismatched placeholders is probably wrong. + sort( $single_placeholders ); + sort( $plural_placeholders ); + + if ( $single_placeholders !== $plural_placeholders ) { + $this->phpcsFile->addWarning( 'Mismatched placeholders is probably an error', $stack_ptr, 'MismatchedPlaceholders' ); + } + } + + /** + * Check the string itself for problems. + * + * @param array $context Context (@todo needs better description). + * @return void + */ + protected function check_text( $context ) { + $stack_ptr = $context['stack_ptr']; + $arg_name = $context['arg_name']; + $content = $context['tokens'][0]['content']; + $is_error = empty( $context['warning'] ); + + // UnorderedPlaceholders: Check for multiple unordered placeholders. + $unordered_matches_count = preg_match_all( self::UNORDERED_SPRINTF_PLACEHOLDER_REGEX, $content, $unordered_matches ); + $unordered_matches = $unordered_matches[0]; + $all_matches_count = preg_match_all( self::SPRINTF_PLACEHOLDER_REGEX, $content, $all_matches ); + + if ( $unordered_matches_count > 0 && $unordered_matches_count !== $all_matches_count && $all_matches_count > 1 ) { + $code = $this->string_to_errorcode( 'MixedOrderedPlaceholders' . ucfirst( $arg_name ) ); + $this->phpcsFile->addError( + 'Multiple placeholders should be ordered. Mix of ordered and non-ordered placeholders found. Found: %s.', + $stack_ptr, + $code, + array( implode( ', ', $all_matches[0] ) ) + ); + + } elseif ( $unordered_matches_count >= 2 ) { + $code = $this->string_to_errorcode( 'UnorderedPlaceholders' . ucfirst( $arg_name ) ); + + $suggestions = array(); + $replace_regexes = array(); + $replacements = array(); + for ( $i = 0; $i < $unordered_matches_count; $i++ ) { + $to_insert = ( $i + 1 ); + $to_insert .= ( '"' !== $content[0] ) ? '$' : '\$'; + $suggestions[ $i ] = substr_replace( $unordered_matches[ $i ], $to_insert, 1, 0 ); + + // Prepare the strings for use a regex. + $replace_regexes[ $i ] = '`\Q' . $unordered_matches[ $i ] . '\E`'; + // Note: the initial \\ is a literal \, the four \ in the replacement translate to also to a literal \. + $replacements[ $i ] = str_replace( '\\', '\\\\', $suggestions[ $i ] ); + // Note: the $ needs escaping to prevent numeric sequences after the $ being interpreted as match replacements. + $replacements[ $i ] = str_replace( '$', '\\$', $replacements[ $i ] ); + } + + $fix = $this->addFixableMessage( + 'Multiple placeholders should be ordered. Expected \'%s\', but got %s.', + $stack_ptr, + $is_error, + $code, + array( implode( ', ', $suggestions ), implode( ', ', $unordered_matches ) ) + ); + + if ( true === $fix ) { + $fixed_str = preg_replace( $replace_regexes, $replacements, $content, 1 ); + + $this->phpcsFile->fixer->replaceToken( $stack_ptr, $fixed_str ); + } + } + + /* + * NoEmptyStrings. + * + * Strip placeholders and surrounding quotes. + */ + $content_without_quotes = trim( $this->strip_quotes( $content ) ); + $non_placeholder_content = preg_replace( self::SPRINTF_PLACEHOLDER_REGEX, '', $content_without_quotes ); + + if ( '' === $non_placeholder_content ) { + $this->phpcsFile->addError( 'Strings should have translatable content', $stack_ptr, 'NoEmptyStrings' ); + return; + } + + /* + * NoHtmlWrappedStrings + * + * Strip surrounding quotes. + */ + $reader = new \XMLReader(); + $reader->XML( $content_without_quotes, 'UTF-8', LIBXML_NOERROR | LIBXML_ERR_NONE | LIBXML_NOWARNING ); + + // Is the first node an HTML element? + if ( ! $reader->read() || \XMLReader::ELEMENT !== $reader->nodeType ) { + return; + } + + // If the opening HTML element includes placeholders in its attributes, we don't warn. + // E.g. ''. + $i = 0; + while ( $attr = $reader->getAttributeNo( $i ) ) { + if ( preg_match( self::SPRINTF_PLACEHOLDER_REGEX, $attr ) === 1 ) { + return; + } + + ++$i; + } + + // We don't flag strings wrapped in `...`, as the link target might actually need localization. + if ( 'a' === $reader->name && $reader->getAttribute( 'href' ) ) { + return; + } + + // Does the entire string only consist of this HTML node? + if ( $reader->readOuterXml() === $content_without_quotes ) { + $this->phpcsFile->addWarning( 'Strings should not be wrapped in HTML', $stack_ptr, 'NoHtmlWrappedStrings' ); + } + } + + /** + * Check for the presence of a translators comment if one of the text strings contains a placeholder. + * + * @param int $stack_ptr The position of the gettext call token in the stack. + * @param array $args The function arguments. + * @return void + */ + protected function check_for_translator_comment( $stack_ptr, $args ) { + foreach ( $args as $arg ) { + if ( false === \in_array( $arg['arg_name'], array( 'text', 'single', 'plural' ), true ) ) { + continue; + } + + if ( empty( $arg['tokens'] ) ) { + continue; + } + + foreach ( $arg['tokens'] as $token ) { + if ( empty( $token['content'] ) ) { + continue; + } + + if ( preg_match( self::SPRINTF_PLACEHOLDER_REGEX, $token['content'], $placeholders ) < 1 ) { + // No placeholders found. + continue; + } + + $previous_comment = $this->phpcsFile->findPrevious( Tokens::$commentTokens, ( $stack_ptr - 1 ) ); + + if ( false !== $previous_comment ) { + /* + * Check that the comment is either on the line before the gettext call or + * if it's not, that there is only whitespace between. + */ + $correctly_placed = false; + + if ( ( $this->tokens[ $previous_comment ]['line'] + 1 ) === $this->tokens[ $stack_ptr ]['line'] ) { + $correctly_placed = true; + } else { + $next_non_whitespace = $this->phpcsFile->findNext( \T_WHITESPACE, ( $previous_comment + 1 ), $stack_ptr, true ); + if ( false === $next_non_whitespace || $this->tokens[ $next_non_whitespace ]['line'] === $this->tokens[ $stack_ptr ]['line'] ) { + // No non-whitespace found or next non-whitespace is on same line as gettext call. + $correctly_placed = true; + } + unset( $next_non_whitespace ); + } + + /* + * Check that the comment starts with 'translators:'. + */ + if ( true === $correctly_placed ) { + + if ( \T_COMMENT === $this->tokens[ $previous_comment ]['code'] ) { + $comment_text = trim( $this->tokens[ $previous_comment ]['content'] ); + + // If it's multi-line /* */ comment, collect all the parts. + if ( '*/' === substr( $comment_text, -2 ) && '/*' !== substr( $comment_text, 0, 2 ) ) { + for ( $i = ( $previous_comment - 1 ); 0 <= $i; $i-- ) { + if ( \T_COMMENT !== $this->tokens[ $i ]['code'] ) { + break; + } + + $comment_text = trim( $this->tokens[ $i ]['content'] ) . $comment_text; + } + } + + if ( true === $this->is_translators_comment( $comment_text ) ) { + // Comment is ok. + return; + } + } elseif ( \T_DOC_COMMENT_CLOSE_TAG === $this->tokens[ $previous_comment ]['code'] ) { + // If it's docblock comment (wrong style) make sure that it's a translators comment. + $db_start = $this->phpcsFile->findPrevious( \T_DOC_COMMENT_OPEN_TAG, ( $previous_comment - 1 ) ); + $db_first_text = $this->phpcsFile->findNext( \T_DOC_COMMENT_STRING, ( $db_start + 1 ), $previous_comment ); + + if ( true === $this->is_translators_comment( $this->tokens[ $db_first_text ]['content'] ) ) { + $this->phpcsFile->addWarning( + 'A "translators:" comment must be a "/* */" style comment. Docblock comments will not be picked up by the tools to generate a ".pot" file.', + $stack_ptr, + 'TranslatorsCommentWrongStyle' + ); + return; + } + } + } + } + + // Found placeholders but no translators comment. + $this->phpcsFile->addWarning( + 'A gettext call containing placeholders was found, but was not accompanied by a "translators:" comment on the line above to clarify the meaning of the placeholders.', + $stack_ptr, + 'MissingTranslatorsComment' + ); + return; + } + } + } + + /** + * Check if a (collated) comment string starts with 'translators:'. + * + * @since 0.11.0 + * + * @param string $content Comment string content. + * @return bool + */ + private function is_translators_comment( $content ) { + if ( preg_match( '`^(?:(?://|/\*{1,2}) )?translators:`i', $content, $matches ) === 1 ) { + return true; + } + return false; + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/PostsPerPageSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/PostsPerPageSniff.php new file mode 100644 index 00000000..968a0342 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/PostsPerPageSniff.php @@ -0,0 +1,78 @@ + array( + 'type' => 'warning', + 'keys' => array( + 'posts_per_page', + 'numberposts', + ), + ), + ); + } + + /** + * Callback to process each confirmed key, to check value. + * + * @param string $key Array index / key. + * @param mixed $val Assigned value. + * @param int $line Token line. + * @param array $group Group definition. + * @return mixed FALSE if no match, TRUE if matches, STRING if matches + * with custom error message passed to ->process(). + */ + public function callback( $key, $val, $line, $group ) { + $this->posts_per_page = (int) $this->posts_per_page; + + if ( $val > $this->posts_per_page ) { + return 'Detected high pagination limit, `%s` is set to `%s`'; + } + + return false; + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/TimezoneChangeSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/TimezoneChangeSniff.php new file mode 100644 index 00000000..f376c5e3 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/TimezoneChangeSniff.php @@ -0,0 +1,88 @@ + false, + 'FoundPropertyForDeprecatedSniff' => false, + ); + + /** + * Don't use. + * + * @deprecated 2.2.0 + * + * @return array + */ + public function getGroups() { + $groups = parent::getGroups(); + return array( 'timezone_change' => $groups['timezone_change'] ); + } + + /** + * Don't use. + * + * @since 2.2.0 Added to allow for throwing the deprecation notices. + * @deprecated 2.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void|int + */ + public function process_token( $stackPtr ) { + if ( false === $this->thrown['DeprecatedSniff'] ) { + $this->thrown['DeprecatedSniff'] = $this->phpcsFile->addWarning( + 'The "WordPress.WP.TimezoneChange" sniff has been deprecated. Use the "WordPress.DateTime.RestrictedFunctions" sniff instead. Please update your custom ruleset.', + 0, + 'DeprecatedSniff' + ); + } + + if ( ! empty( $this->exclude ) + && false === $this->thrown['FoundPropertyForDeprecatedSniff'] + ) { + $this->thrown['FoundPropertyForDeprecatedSniff'] = $this->phpcsFile->addWarning( + 'The "WordPress.WP.TimezoneChange" sniff has been deprecated. Use the "WordPress.DateTime.RestrictedFunctions" sniff instead. "exclude" property setting found. Please update your custom ruleset.', + 0, + 'FoundPropertyForDeprecatedSniff' + ); + } + + return parent::process_token( $stackPtr ); + } +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/CastStructureSpacingSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/CastStructureSpacingSniff.php new file mode 100755 index 00000000..41494b91 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/CastStructureSpacingSniff.php @@ -0,0 +1,62 @@ +tokens[ ( $stackPtr - 1 ) ]['code'] + && \T_ELLIPSIS !== $this->tokens[ ( $stackPtr - 1 ) ]['code'] + ) { + $error = 'No space before opening casting parenthesis is prohibited'; + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, 'NoSpaceBeforeOpenParenthesis' ); + if ( true === $fix ) { + $this->phpcsFile->fixer->addContentBefore( $stackPtr, ' ' ); + } + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php new file mode 100644 index 00000000..5f7b9a3c --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php @@ -0,0 +1,572 @@ + true, + \T_CLOSURE => true, + \T_DO => true, + \T_ELSE => true, + \T_TRY => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array( + \T_IF, + \T_WHILE, + \T_FOREACH, + \T_FOR, + \T_SWITCH, + \T_DO, + \T_ELSE, + \T_ELSEIF, + \T_FUNCTION, + \T_CLOSURE, + \T_USE, + \T_TRY, + \T_CATCH, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + $this->spaces_before_closure_open_paren = (int) $this->spaces_before_closure_open_paren; + + if ( isset( $this->tokens[ ( $stackPtr + 1 ) ] ) && \T_WHITESPACE !== $this->tokens[ ( $stackPtr + 1 ) ]['code'] + && ! ( \T_ELSE === $this->tokens[ $stackPtr ]['code'] && \T_COLON === $this->tokens[ ( $stackPtr + 1 ) ]['code'] ) + && ! ( \T_CLOSURE === $this->tokens[ $stackPtr ]['code'] + && 0 >= $this->spaces_before_closure_open_paren ) + ) { + $error = 'Space after opening control structure is required'; + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, 'NoSpaceAfterStructureOpen' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $stackPtr, ' ' ); + } + } + + if ( ! isset( $this->tokens[ $stackPtr ]['scope_closer'] ) ) { + + if ( \T_USE === $this->tokens[ $stackPtr ]['code'] && 'closure' === $this->get_use_type( $stackPtr ) ) { + $scopeOpener = $this->phpcsFile->findNext( \T_OPEN_CURLY_BRACKET, ( $stackPtr + 1 ) ); + $scopeCloser = $this->tokens[ $scopeOpener ]['scope_closer']; + } elseif ( \T_WHILE !== $this->tokens[ $stackPtr ]['code'] ) { + return; + } + } else { + $scopeOpener = $this->tokens[ $stackPtr ]['scope_opener']; + $scopeCloser = $this->tokens[ $stackPtr ]['scope_closer']; + } + + // Alternative syntax. + if ( isset( $scopeOpener ) && \T_COLON === $this->tokens[ $scopeOpener ]['code'] ) { + + if ( 'required' === $this->space_before_colon ) { + + if ( \T_WHITESPACE !== $this->tokens[ ( $scopeOpener - 1 ) ]['code'] ) { + $error = 'Space between opening control structure and T_COLON is required'; + $fix = $this->phpcsFile->addFixableError( $error, $scopeOpener, 'NoSpaceBetweenStructureColon' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContentBefore( $scopeOpener, ' ' ); + } + } + } elseif ( 'forbidden' === $this->space_before_colon ) { + + if ( \T_WHITESPACE === $this->tokens[ ( $scopeOpener - 1 ) ]['code'] ) { + $error = 'Extra space between opening control structure and T_COLON found'; + $fix = $this->phpcsFile->addFixableError( $error, ( $scopeOpener - 1 ), 'SpaceBetweenStructureColon' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $scopeOpener - 1 ), '' ); + } + } + } + } + + $parenthesisOpener = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + + // If this is a function declaration. + if ( \T_FUNCTION === $this->tokens[ $stackPtr ]['code'] ) { + + if ( \T_STRING === $this->tokens[ $parenthesisOpener ]['code'] ) { + + $function_name_ptr = $parenthesisOpener; + + } elseif ( \T_BITWISE_AND === $this->tokens[ $parenthesisOpener ]['code'] ) { + + // This function returns by reference (function &function_name() {}). + $parenthesisOpener = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $parenthesisOpener + 1 ), + null, + true + ); + $function_name_ptr = $parenthesisOpener; + } + + if ( isset( $function_name_ptr ) ) { + $parenthesisOpener = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $parenthesisOpener + 1 ), + null, + true + ); + + // Checking this: function my_function[*](...) {}. + if ( ( $function_name_ptr + 1 ) !== $parenthesisOpener ) { + + $error = 'Space between function name and opening parenthesis is prohibited.'; + $fix = $this->phpcsFile->addFixableError( + $error, + $stackPtr, + 'SpaceBeforeFunctionOpenParenthesis', + $this->tokens[ ( $function_name_ptr + 1 ) ]['content'] + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $function_name_ptr + 1 ), '' ); + } + } + } + } elseif ( \T_CLOSURE === $this->tokens[ $stackPtr ]['code'] ) { + + // Check if there is a use () statement. + if ( isset( $this->tokens[ $parenthesisOpener ]['parenthesis_closer'] ) ) { + + $usePtr = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $this->tokens[ $parenthesisOpener ]['parenthesis_closer'] + 1 ), + null, + true, + null, + true + ); + + // If it is, we set that as the "scope opener". + if ( \T_USE === $this->tokens[ $usePtr ]['code'] ) { + $scopeOpener = $usePtr; + } + } + } + + if ( \T_COLON !== $this->tokens[ $parenthesisOpener ]['code'] + && \T_FUNCTION !== $this->tokens[ $stackPtr ]['code'] + ) { + + if ( \T_CLOSURE === $this->tokens[ $stackPtr ]['code'] + && 0 === $this->spaces_before_closure_open_paren + ) { + + if ( ( $stackPtr + 1 ) !== $parenthesisOpener ) { + // Checking this: function[*](...) {}. + $error = 'Space before closure opening parenthesis is prohibited'; + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, 'SpaceBeforeClosureOpenParenthesis' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $stackPtr + 1 ), '' ); + } + } + } elseif ( + ( + \T_CLOSURE !== $this->tokens[ $stackPtr ]['code'] + || 1 === $this->spaces_before_closure_open_paren + ) + && ( $stackPtr + 1 ) === $parenthesisOpener + ) { + + // Checking this: if[*](...) {}. + $error = 'No space before opening parenthesis is prohibited'; + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, 'NoSpaceBeforeOpenParenthesis' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $stackPtr, ' ' ); + } + } + } + + if ( \T_WHITESPACE === $this->tokens[ ( $stackPtr + 1 ) ]['code'] + && ' ' !== $this->tokens[ ( $stackPtr + 1 ) ]['content'] + ) { + // Checking this: if [*](...) {}. + $error = 'Expected exactly one space before opening parenthesis; "%s" found.'; + $fix = $this->phpcsFile->addFixableError( + $error, + $stackPtr, + 'ExtraSpaceBeforeOpenParenthesis', + $this->tokens[ ( $stackPtr + 1 ) ]['content'] + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $stackPtr + 1 ), ' ' ); + } + } + + if ( \T_CLOSE_PARENTHESIS !== $this->tokens[ ( $parenthesisOpener + 1 ) ]['code'] ) { + if ( \T_WHITESPACE !== $this->tokens[ ( $parenthesisOpener + 1 ) ]['code'] ) { + // Checking this: $value = my_function([*]...). + $error = 'No space after opening parenthesis is prohibited'; + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, 'NoSpaceAfterOpenParenthesis' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $parenthesisOpener, ' ' ); + } + } elseif ( ( ' ' !== $this->tokens[ ( $parenthesisOpener + 1 ) ]['content'] + && "\n" !== $this->tokens[ ( $parenthesisOpener + 1 ) ]['content'] + && "\r\n" !== $this->tokens[ ( $parenthesisOpener + 1 ) ]['content'] ) + && ! isset( $this->ignore_extra_space_after_open_paren[ $this->tokens[ $stackPtr ]['code'] ] ) + ) { + // Checking this: if ([*]...) {}. + $error = 'Expected exactly one space after opening parenthesis; "%s" found.'; + $fix = $this->phpcsFile->addFixableError( + $error, + $stackPtr, + 'ExtraSpaceAfterOpenParenthesis', + $this->tokens[ ( $parenthesisOpener + 1 ) ]['content'] + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $parenthesisOpener + 1 ), ' ' ); + } + } + } + + if ( isset( $this->tokens[ $parenthesisOpener ]['parenthesis_closer'] ) ) { + + $parenthesisCloser = $this->tokens[ $parenthesisOpener ]['parenthesis_closer']; + + if ( \T_CLOSE_PARENTHESIS !== $this->tokens[ ( $parenthesisOpener + 1 ) ]['code'] ) { + + // Checking this: if (...[*]) {}. + if ( \T_WHITESPACE !== $this->tokens[ ( $parenthesisCloser - 1 ) ]['code'] ) { + $error = 'No space before closing parenthesis is prohibited'; + $fix = $this->phpcsFile->addFixableError( $error, $parenthesisCloser, 'NoSpaceBeforeCloseParenthesis' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContentBefore( $parenthesisCloser, ' ' ); + } + } elseif ( ' ' !== $this->tokens[ ( $parenthesisCloser - 1 ) ]['content'] ) { + $prevNonEmpty = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $parenthesisCloser - 1 ), null, true ); + if ( $this->tokens[ ( $parenthesisCloser ) ]['line'] === $this->tokens[ ( $prevNonEmpty + 1 ) ]['line'] ) { + $error = 'Expected exactly one space before closing parenthesis; "%s" found.'; + $fix = $this->phpcsFile->addFixableError( + $error, + $stackPtr, + 'ExtraSpaceBeforeCloseParenthesis', + $this->tokens[ ( $parenthesisCloser - 1 ) ]['content'] + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $parenthesisCloser - 1 ), ' ' ); + } + } + } + + if ( \T_WHITESPACE !== $this->tokens[ ( $parenthesisCloser + 1 ) ]['code'] + && ! ( // Do NOT flag : immediately following ) for return types declarations. + \T_COLON === $this->tokens[ ( $parenthesisCloser + 1 ) ]['code'] + && ( isset( $this->tokens[ $parenthesisCloser ]['parenthesis_owner'] ) === false + || in_array( $this->tokens[ $this->tokens[ $parenthesisCloser ]['parenthesis_owner'] ]['code'], array( \T_FUNCTION, \T_CLOSURE ), true ) ) + ) + && ( isset( $scopeOpener ) && \T_COLON !== $this->tokens[ $scopeOpener ]['code'] ) + ) { + $error = 'Space between opening control structure and closing parenthesis is required'; + $fix = $this->phpcsFile->addFixableError( $error, $scopeOpener, 'NoSpaceAfterCloseParenthesis' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContentBefore( $scopeOpener, ' ' ); + } + } + } + + // Ignore this for function declarations. Handled by the OpeningFunctionBraceKernighanRitchie sniff. + if ( \T_FUNCTION !== $this->tokens[ $stackPtr ]['code'] + && \T_CLOSURE !== $this->tokens[ $stackPtr ]['code'] + && isset( $this->tokens[ $parenthesisOpener ]['parenthesis_owner'] ) + && ( isset( $scopeOpener ) + && $this->tokens[ $parenthesisCloser ]['line'] !== $this->tokens[ $scopeOpener ]['line'] ) + ) { + $error = 'Opening brace should be on the same line as the declaration'; + $fix = $this->phpcsFile->addFixableError( $error, $parenthesisOpener, 'OpenBraceNotSameLine' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + for ( $i = ( $parenthesisCloser + 1 ); $i < $scopeOpener; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->addContent( $parenthesisCloser, ' ' ); + $this->phpcsFile->fixer->endChangeset(); + } + return; + + } elseif ( \T_WHITESPACE === $this->tokens[ ( $parenthesisCloser + 1 ) ]['code'] + && ' ' !== $this->tokens[ ( $parenthesisCloser + 1 ) ]['content'] + ) { + + // Checking this: if (...) [*]{}. + $error = 'Expected exactly one space between closing parenthesis and opening control structure; "%s" found.'; + $fix = $this->phpcsFile->addFixableError( + $error, + $stackPtr, + 'ExtraSpaceAfterCloseParenthesis', + $this->tokens[ ( $parenthesisCloser + 1 ) ]['content'] + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $parenthesisCloser + 1 ), ' ' ); + } + } + } + + if ( false !== $this->blank_line_check && isset( $scopeOpener ) ) { + $firstContent = $this->phpcsFile->findNext( \T_WHITESPACE, ( $scopeOpener + 1 ), null, true ); + + // We ignore spacing for some structures that tend to have their own rules. + $ignore = array( + \T_FUNCTION => true, + \T_CLOSURE => true, + \T_DOC_COMMENT_OPEN_TAG => true, + \T_CLOSE_TAG => true, + \T_COMMENT => true, + ); + $ignore += Tokens::$ooScopeTokens; + + if ( ! isset( $ignore[ $this->tokens[ $firstContent ]['code'] ] ) + && $this->tokens[ $firstContent ]['line'] > ( $this->tokens[ $scopeOpener ]['line'] + 1 ) + ) { + $error = 'Blank line found at start of control structure'; + $fix = $this->phpcsFile->addFixableError( $error, $scopeOpener, 'BlankLineAfterStart' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + for ( $i = ( $scopeOpener + 1 ); $i < $firstContent; $i++ ) { + if ( $this->tokens[ $i ]['line'] === $this->tokens[ $firstContent ]['line'] ) { + break; + } + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->addNewline( $scopeOpener ); + $this->phpcsFile->fixer->endChangeset(); + } + } + + if ( $firstContent !== $scopeCloser ) { + $lastContent = $this->phpcsFile->findPrevious( \T_WHITESPACE, ( $scopeCloser - 1 ), null, true ); + + $lastNonEmptyContent = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $scopeCloser - 1 ), null, true ); + + $checkToken = $lastContent; + if ( isset( $this->tokens[ $lastNonEmptyContent ]['scope_condition'] ) ) { + $checkToken = $this->tokens[ $lastNonEmptyContent ]['scope_condition']; + } + + if ( ! isset( $ignore[ $this->tokens[ $checkToken ]['code'] ] ) + && $this->tokens[ $lastContent ]['line'] <= ( $this->tokens[ $scopeCloser ]['line'] - 2 ) + ) { + for ( $i = ( $scopeCloser - 1 ); $i > $lastContent; $i-- ) { + if ( $this->tokens[ $i ]['line'] < $this->tokens[ $scopeCloser ]['line'] + && \T_OPEN_TAG !== $this->tokens[ $firstContent ]['code'] + ) { + // TODO: Reporting error at empty line won't highlight it in IDE. + $error = 'Blank line found at end of control structure'; + $fix = $this->phpcsFile->addFixableError( $error, $i, 'BlankLineBeforeEnd' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + for ( $j = ( $lastContent + 1 ); $j < $scopeCloser; $j++ ) { + if ( $this->tokens[ $j ]['line'] === $this->tokens[ $scopeCloser ]['line'] ) { + break; + } + $this->phpcsFile->fixer->replaceToken( $j, '' ); + } + + /* + * PHPCS annotations, like normal inline comments, are tokenized including + * the new line at the end, so don't add any extra as it would cause a fixer + * conflict. + */ + if ( \T_COMMENT !== $this->tokens[ $lastContent ]['code'] + && ! isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $lastContent ]['code'] ] ) ) { + $this->phpcsFile->fixer->addNewlineBefore( $j ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + break; + } + } + } + } + unset( $ignore ); + } + + if ( ! isset( $scopeCloser ) || true !== $this->blank_line_after_check ) { + return; + } + + // {@internal This is just for the blank line check. Only whitespace should be considered, + // not "other" empty tokens.}} + $trailingContent = $this->phpcsFile->findNext( \T_WHITESPACE, ( $scopeCloser + 1 ), null, true ); + if ( false === $trailingContent ) { + return; + } + + if ( \T_COMMENT === $this->tokens[ $trailingContent ]['code'] + || isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $trailingContent ]['code'] ] ) + ) { + // Special exception for code where the comment about + // an ELSE or ELSEIF is written between the control structures. + $nextCode = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $scopeCloser + 1 ), null, true ); + + if ( \T_ELSE === $this->tokens[ $nextCode ]['code'] || \T_ELSEIF === $this->tokens[ $nextCode ]['code'] ) { + $trailingContent = $nextCode; + } + + // Move past end comments. + if ( $this->tokens[ $trailingContent ]['line'] === $this->tokens[ $scopeCloser ]['line'] ) { + if ( preg_match( '`^//[ ]?end`i', $this->tokens[ $trailingContent ]['content'], $matches ) > 0 ) { + $scopeCloser = $trailingContent; + $trailingContent = $this->phpcsFile->findNext( \T_WHITESPACE, ( $trailingContent + 1 ), null, true ); + } + } + } + + if ( \T_ELSE === $this->tokens[ $trailingContent ]['code'] && \T_IF === $this->tokens[ $stackPtr ]['code'] ) { + // IF with ELSE. + return; + } + + if ( \T_WHILE === $this->tokens[ $trailingContent ]['code'] && \T_DO === $this->tokens[ $stackPtr ]['code'] ) { + // DO with WHILE. + return; + } + + if ( \T_CLOSE_TAG === $this->tokens[ $trailingContent ]['code'] ) { + // At the end of the script or embedded code. + return; + } + + if ( isset( $this->tokens[ $trailingContent ]['scope_condition'] ) + && \T_CLOSE_CURLY_BRACKET === $this->tokens[ $trailingContent ]['code'] + ) { + // Another control structure's closing brace. + $owner = $this->tokens[ $trailingContent ]['scope_condition']; + if ( \in_array( $this->tokens[ $owner ]['code'], array( \T_FUNCTION, \T_CLOSURE, \T_CLASS, \T_ANON_CLASS, \T_INTERFACE, \T_TRAIT ), true ) ) { + // The next content is the closing brace of a function, class, interface or trait + // so normal function/class rules apply and we can ignore it. + return; + } + + if ( ( $this->tokens[ $scopeCloser ]['line'] + 1 ) !== $this->tokens[ $trailingContent ]['line'] ) { + // TODO: Won't cover following case: "} echo 'OK';". + $error = 'Blank line found after control structure'; + $fix = $this->phpcsFile->addFixableError( $error, $scopeCloser, 'BlankLineAfterEnd' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + $i = ( $scopeCloser + 1 ); + while ( $this->tokens[ $i ]['line'] !== $this->tokens[ $trailingContent ]['line'] ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + $i++; + } + + // TODO: Instead a separate error should be triggered when content comes right after closing brace. + if ( \T_COMMENT !== $this->tokens[ $scopeCloser ]['code'] + && isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $scopeCloser ]['code'] ] ) === false + ) { + $this->phpcsFile->fixer->addNewlineBefore( $trailingContent ); + } + $this->phpcsFile->fixer->endChangeset(); + } + } + } + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/DisallowInlineTabsSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/DisallowInlineTabsSniff.php new file mode 100644 index 00000000..c20a4d33 --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/DisallowInlineTabsSniff.php @@ -0,0 +1,104 @@ +tab_width ) ) { + $this->tab_width = PHPCSHelper::get_tab_width( $this->phpcsFile ); + } + + $check_tokens = array( + \T_WHITESPACE => true, + \T_DOC_COMMENT_WHITESPACE => true, + \T_DOC_COMMENT_STRING => true, + ); + + for ( $i = ( $stackPtr + 1 ); $i < $this->phpcsFile->numTokens; $i++ ) { + // Skip all non-whitespace tokens and skip whitespace at the start of a new line. + if ( ! isset( $check_tokens[ $this->tokens[ $i ]['code'] ] ) || 1 === $this->tokens[ $i ]['column'] ) { + continue; + } + + // If tabs are being converted to spaces by the tokenizer, the + // original content should be checked instead of the converted content. + if ( isset( $this->tokens[ $i ]['orig_content'] ) ) { + $content = $this->tokens[ $i ]['orig_content']; + } else { + $content = $this->tokens[ $i ]['content']; + } + + if ( '' === $content || strpos( $content, "\t" ) === false ) { + continue; + } + + $fix = $this->phpcsFile->addFixableError( + 'Spaces must be used for mid-line alignment; tabs are not allowed', + $i, + 'NonIndentTabsUsed' + ); + if ( true === $fix ) { + if ( isset( $this->tokens[ $i ]['orig_content'] ) ) { + // Use the replacement that PHPCS has already done. + $this->phpcsFile->fixer->replaceToken( $i, $this->tokens[ $i ]['content'] ); + } else { + // Replace tabs with spaces, using an indent of $tab_width. + // Other sniffs can then correct the indent if they need to. + $spaces = str_repeat( ' ', $this->tab_width ); + $newContent = str_replace( "\t", $spaces, $this->tokens[ $i ]['content'] ); + $this->phpcsFile->fixer->replaceToken( $i, $newContent ); + } + } + } + + // Ignore the rest of the file. + return ( $this->phpcsFile->numTokens + 1 ); + } + +} diff --git a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/OperatorSpacingSniff.php b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/OperatorSpacingSniff.php new file mode 100644 index 00000000..17e5090c --- /dev/null +++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/OperatorSpacingSniff.php @@ -0,0 +1,64 @@ + + * + * + * + * + * + * + * + * + * @var array + */ + public $ignoreAlignmentTokens = array(); + + /** + * The --tab-width CLI value that is being used. + * + * @var int + */ + private $tab_width; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array( + \T_OPEN_TAG, + \T_OPEN_TAG_WITH_ECHO, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int Integer stack pointer to skip the rest of the file. + */ + public function process_token( $stackPtr ) { + if ( ! isset( $this->tab_width ) ) { + $this->tab_width = PHPCSHelper::get_tab_width( $this->phpcsFile ); + } + + // Handle any custom ignore tokens received from a ruleset. + $ignoreAlignmentTokens = $this->merge_custom_array( $this->ignoreAlignmentTokens ); + + $check_tokens = array( + \T_WHITESPACE => true, + \T_INLINE_HTML => true, + \T_DOC_COMMENT_WHITESPACE => true, + \T_COMMENT => true, + ); + $check_tokens += Tokens::$phpcsCommentTokens; + + for ( $i = 0; $i < $this->phpcsFile->numTokens; $i++ ) { + + if ( 1 !== $this->tokens[ $i ]['column'] ) { + continue; + } elseif ( isset( $check_tokens[ $this->tokens[ $i ]['code'] ] ) === false + || ( isset( $this->tokens[ ( $i + 1 ) ] ) + && \T_WHITESPACE === $this->tokens[ ( $i + 1 ) ]['code'] ) + || $this->tokens[ $i ]['content'] === $this->phpcsFile->eolChar + || isset( $ignoreAlignmentTokens[ $this->tokens[ $i ]['type'] ] ) + || ( isset( $this->tokens[ ( $i + 1 ) ] ) + && isset( $ignoreAlignmentTokens[ $this->tokens[ ( $i + 1 ) ]['type'] ] ) ) + ) { + continue; + } + + $spaces = 0; + switch ( $this->tokens[ $i ]['type'] ) { + case 'T_WHITESPACE': + $spaces = ( $this->tokens[ $i ]['length'] % $this->tab_width ); + break; + + case 'T_DOC_COMMENT_WHITESPACE': + $length = $this->tokens[ $i ]['length']; + $spaces = ( $length % $this->tab_width ); + + if ( isset( $this->tokens[ ( $i + 1 ) ] ) + && ( \T_DOC_COMMENT_STAR === $this->tokens[ ( $i + 1 ) ]['code'] + || \T_DOC_COMMENT_CLOSE_TAG === $this->tokens[ ( $i + 1 ) ]['code'] ) + && 0 !== $spaces + ) { + // One alignment space expected before the *. + --$spaces; + } + break; + + case 'T_COMMENT': + case 'T_PHPCS_ENABLE': + case 'T_PHPCS_DISABLE': + case 'T_PHPCS_SET': + case 'T_PHPCS_IGNORE': + case 'T_PHPCS_IGNORE_FILE': + /* + * Indentation whitespace for subsequent lines of multi-line comments + * are tokenized as part of the comment. + */ + $comment = ltrim( $this->tokens[ $i ]['content'] ); + $whitespace = str_replace( $comment, '', $this->tokens[ $i ]['content'] ); + $length = \strlen( $whitespace ); + $spaces = ( $length % $this->tab_width ); + + if ( isset( $comment[0] ) && '*' === $comment[0] && 0 !== $spaces ) { + --$spaces; + } + break; + + case 'T_INLINE_HTML': + if ( $this->tokens[ $i ]['content'] === $this->phpcsFile->eolChar ) { + $spaces = 0; + } else { + /* + * Indentation whitespace for inline HTML is part of the T_INLINE_HTML token. + */ + $content = ltrim( $this->tokens[ $i ]['content'] ); + $whitespace = str_replace( $content, '', $this->tokens[ $i ]['content'] ); + $spaces = ( \strlen( $whitespace ) % $this->tab_width ); + } + + /* + * Prevent triggering on multi-line /*-style inline javascript comments. + * This may cause false negatives as there is no check for being in a + *